diff --git a/.codespell/exclude-file.txt b/.codespell/exclude-file.txt index 08e1a2b9059e3..7e6bad4bf0bcf 100644 --- a/.codespell/exclude-file.txt +++ b/.codespell/exclude-file.txt @@ -8,3 +8,4 @@ i1Qb$TE"rl ZEN = "the zen of python beautiful is better than ugly explicit is better than implicit simple is better than complex complex is better than complicated flat is better than nested sparse is better than dense readability counts special cases arent special enough to break the rules although practicality beats purity errors should never pass silently unless explicitly silenced in the face of ambiguity refuse the temptation to guess there should be one and preferably only one obvious way to do it although that way may not be obvious at first unless youre dutch now is better than never although never is often better than right now if the implementation is hard to explain its a bad idea if the implementation is easy to explain it may be a good idea namespaces are one honking great idea lets do more of those" "arent", "youre", +USB_MANUFACTURER = "Wee Noise Makers" diff --git a/.codespell/ignore-words.txt b/.codespell/ignore-words.txt index fc8feaca9780b..48bee0f30ba7a 100644 --- a/.codespell/ignore-words.txt +++ b/.codespell/ignore-words.txt @@ -26,3 +26,4 @@ ftbfs straightaway ftbs ftb +curren diff --git a/.devcontainer/add_kitware_archive.sh b/.devcontainer/add_kitware_archive.sh new file mode 100755 index 0000000000000..aff0b6c8d0f09 --- /dev/null +++ b/.devcontainer/add_kitware_archive.sh @@ -0,0 +1,107 @@ +#!/bin/sh +# ----------------------------------------------------------------------------- +# This script is from: https://apt.kitware.com/kitware-archive.sh +# +# It installs key and repo for the kitware CMAKE-archive. +# +# Author: Bernhard Bablok +# +# ----------------------------------------------------------------------------- + +set -eu + +help() { + echo "Usage: $0 [--release ] [--rc]" > /dev/stderr +} + +doing= +rc= +release= +help= +for opt in "$@" +do + case "${doing}" in + release) + release="${opt}" + doing= + ;; + "") + case "${opt}" in + --rc) + rc=1 + ;; + --release) + doing=release + ;; + --help) + help=1 + ;; + esac + ;; + esac +done + +if [ -n "${doing}" ] +then + echo "--${doing} option given no argument." > /dev/stderr + echo > /dev/stderr + help + exit 1 +fi + +if [ -n "${help}" ] +then + help + exit +fi + +if [ -z "${release}" ] +then + unset UBUNTU_CODENAME + . /etc/os-release + + if [ -z "${UBUNTU_CODENAME+x}" ] + then + echo "This is not an Ubuntu system. Aborting." > /dev/stderr + exit 1 + fi + + release="${UBUNTU_CODENAME}" +fi + +case "${release}" in +noble|jammy|focal) + packages= + keyring_packages="ca-certificates gpg wget" + ;; +*) + echo "Only Ubuntu Noble (24.04), Jammy (22.04), and Focal (20.04) are supported. Aborting." > /dev/stderr + exit 1 + ;; +esac + +get_keyring= +if [ ! -f /usr/share/doc/kitware-archive-keyring/copyright ] +then + packages="${packages} ${keyring_packages}" + get_keyring=1 +fi + +# Start the real work +set -x + +apt-get update +# shellcheck disable=SC2086 +apt-get install -y ${packages} + +test -n "${get_keyring}" && (wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - > /usr/share/keyrings/kitware-archive-keyring.gpg) + +echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${release} main" > /etc/apt/sources.list.d/kitware.list +if [ -n "${rc}" ] +then + echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ${release}-rc main" >> /etc/apt/sources.list.d/kitware.list +fi + +apt-get update +test -n "${get_keyring}" && rm /usr/share/keyrings/kitware-archive-keyring.gpg +apt-get install -y kitware-archive-keyring diff --git a/.devcontainer/common_tools.sh b/.devcontainer/common_tools.sh index 14cf76c3fe22d..d94977b01cc47 100755 --- a/.devcontainer/common_tools.sh +++ b/.devcontainer/common_tools.sh @@ -15,6 +15,11 @@ cd "$REPO_ROOT" # --- repositories and tools ------------------------------------------------ +echo -e "[common_tools.sh] adding kitware-archive (for current CMAKE)" +sudo .devcontainer/add_kitware_archive.sh +echo -e "[common_tools.sh] installing current version of CMAKE" +sudo apt-get -y install cmake + echo -e "[common_tools.sh] adding pybricks/ppa" sudo add-apt-repository -y ppa:pybricks/ppa echo -e "[common_tools.sh] installing uncrustify and mtools" diff --git a/.devcontainer/cortex-m-toolchain.sh b/.devcontainer/cortex-m-toolchain.sh index de1ccde62742a..56be006544f1c 100755 --- a/.devcontainer/cortex-m-toolchain.sh +++ b/.devcontainer/cortex-m-toolchain.sh @@ -14,10 +14,10 @@ echo -e "[cortex-m-toolchain.sh] downloading and installing gcc-arm-non-eabi too cd /workspaces wget -qO gcc-arm-none-eabi.tar.xz \ - https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x86_64-arm-none-eabi.tar.xz + https://developer.arm.com/-/media/Files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-eabi.tar.xz tar -xJf gcc-arm-none-eabi.tar.xz -ln -s arm-gnu-toolchain-13.2.Rel1-x86_64-arm-none-eabi gcc-arm-none-eabi +ln -s arm-gnu-toolchain-15.2.rel1-x86_64-arm-none-eabi gcc-arm-none-eabi rm -f gcc-arm-none-eabi.tar.xz echo -e "[cortex-m-toolchain.sh] update PATH in environment" diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 690e5f46a4fc0..195e1e06eea46 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,12 @@ +# all: Prune trailing whitespace. +dda9b9c6da5d3c31fa8769e581a753e95a270803 + +# all: Remove the "STATIC" macro and just use "static" instead. +decf8e6a8bb940d5829ca3296790631fcece7b21 + +# renesas-ra: Fix spelling mistakes found by codespell. +b3f2f18f927fa2fad10daf63d8c391331f5edf58 + # all: Update Python formatting to ruff-format. bbd8760bd9a2302e5abee29db279102bb11d7732 diff --git a/.gitattributes b/.gitattributes index 38bba729fc191..d226cebf5d81d 100644 --- a/.gitattributes +++ b/.gitattributes @@ -27,4 +27,5 @@ # These should also not be modified by git. tests/basics/string_cr_conversion.py -text tests/basics/string_crlf_conversion.py -text +tests/micropython/test_normalize_newlines.py.exp -text # CIRCUITPY-CHANGE: remove non-CircuitPython tests diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c81bf63123dd4..8617ce3f03fda 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,5 +1,5 @@ name: 🐞 Bug Report -description: Create a bug report to help us improve +description: Create a bug report to help us improve CircuitPython labels: - bug body: @@ -7,14 +7,14 @@ body: attributes: value: >- Thanks for testing out CircuitPython! Now that you have encountered a - bug... you can file a report for it. + bug, you can file a report for it. - type: textarea id: firmware attributes: - label: CircuitPython version + label: CircuitPython version and board name description: >- - Include the version of CircuitPython you're running. You can see it in - the `boot_out.txt` file, as well as in the `REPL`. + Include the version of CircuitPython you're running and the name of the board you're using. + You can find this information in the `boot_out.txt` file, as well as in the REPL. placeholder: Adafruit CircuitPython 6.2.0 on 2021-03-01; Raspberry Pi Pico with rp2040 render: python validations: @@ -23,7 +23,7 @@ body: id: code attributes: label: Code/REPL - description: This is automatically rendered as Python, so no need for backticks. + description: Code here is automatically rendered as Python, so you don't need to include backticks. placeholder: | import busio, bitbangio i2c = bitbangio.I2C(board.GP1, board.GP0) diff --git a/.github/actions/deps/external/action.yml b/.github/actions/deps/external/action.yml index 68626dde50fef..81e73f871efc6 100644 --- a/.github/actions/deps/external/action.yml +++ b/.github/actions/deps/external/action.yml @@ -22,11 +22,12 @@ runs: if: >- inputs.port != 'none' && inputs.port != 'litex' && - inputs.port != 'espressif' + inputs.port != 'espressif' && + inputs.port != 'zephyr-cp' uses: carlosperate/arm-none-eabi-gcc-action@v1 with: # When changing this update what Windows grabs too! - release: '13.2.Rel1' + release: '15.2.Rel1' # espressif - name: Get espressif toolchain @@ -51,10 +52,20 @@ runs: # common - name: Cache python dependencies - if: inputs.port != 'espressif' + if: inputs.port != 'espressif' && inputs.port != 'zephyr-cp' uses: ./.github/actions/deps/python with: action: ${{ inputs.action }} + - name: Set ESP-IDF constraints path + if: inputs.port == 'espressif' + run: python3 -u tools/ci_set_idf_constraint.py + shell: bash + - name: Install python dependencies - run: pip install -r requirements-dev.txt + run: | + if [ -n "${IDF_CONSTRAINT_FILE:-}" ] && [ -f "$IDF_CONSTRAINT_FILE" ]; then + pip install -c "$IDF_CONSTRAINT_FILE" -r requirements-dev.txt + else + pip install -r requirements-dev.txt + fi shell: bash diff --git a/.github/actions/deps/ports/action.yml b/.github/actions/deps/ports/action.yml index 2412c475c01a5..6f91ea62cec14 100644 --- a/.github/actions/deps/ports/action.yml +++ b/.github/actions/deps/ports/action.yml @@ -4,33 +4,29 @@ inputs: board: required: true type: string - -outputs: port: - value: ${{ steps.board-to-port.outputs.port }} + required: true + type: string runs: using: composite steps: - - name: Board to port - id: board-to-port - run: | - PORT=$(find ports/*/boards/ -type d -name ${{ inputs.board }} | sed 's/^ports\///g;s/\/boards.*//g') - if [ -z $PORT ]; then (exit 1); else echo >> $GITHUB_OUTPUT "port=$PORT"; fi - shell: bash - - name: Set up broadcom - if: steps.board-to-port.outputs.port == 'broadcom' + if: inputs.port == 'broadcom' uses: ./.github/actions/deps/ports/broadcom - name: Set up espressif - if: steps.board-to-port.outputs.port == 'espressif' + if: inputs.port == 'espressif' uses: ./.github/actions/deps/ports/espressif - name: Set up litex - if: steps.board-to-port.outputs.port == 'litex' + if: inputs.port == 'litex' uses: ./.github/actions/deps/ports/litex - name: Set up nordic - if: steps.board-to-port.outputs.port == 'nordic' + if: inputs.port == 'nordic' uses: ./.github/actions/deps/ports/nordic + + - name: Set up Zephyr + if: inputs.port == 'zephyr-cp' + uses: ./.github/actions/deps/ports/zephyr-cp diff --git a/.github/actions/deps/ports/broadcom/action.yml b/.github/actions/deps/ports/broadcom/action.yml index 99f53064b3f68..fc375aa10f74f 100644 --- a/.github/actions/deps/ports/broadcom/action.yml +++ b/.github/actions/deps/ports/broadcom/action.yml @@ -5,8 +5,8 @@ runs: steps: - name: Get broadcom toolchain run: | - wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz - sudo tar -C /usr --strip-components=1 -xaf gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz + wget --no-verbose https://adafruit-circuit-python.s3.amazonaws.com/arm-gnu-toolchain-15.2.rel1-x86_64-aarch64-none-elf.tar.xz + sudo tar -C /usr --strip-components=1 -xaf arm-gnu-toolchain-15.2.rel1-x86_64-aarch64-none-elf.tar.xz sudo apt-get update sudo apt-get install -y mtools shell: bash diff --git a/.github/actions/deps/ports/espressif/action.yml b/.github/actions/deps/ports/espressif/action.yml index 122940bb95a1e..321a0fb2b3023 100644 --- a/.github/actions/deps/ports/espressif/action.yml +++ b/.github/actions/deps/ports/espressif/action.yml @@ -7,6 +7,7 @@ runs: run: | echo >> $GITHUB_ENV "IDF_PATH=$GITHUB_WORKSPACE/ports/espressif/esp-idf" echo >> $GITHUB_ENV "IDF_TOOLS_PATH=$GITHUB_WORKSPACE/.idf_tools" + echo >> $GITHUB_ENV "ESP_ROM_ELF_DIR=$GITHUB_WORKSPACE/.idf_tools" shell: bash - name: Get IDF commit @@ -18,7 +19,7 @@ runs: shell: bash - name: Cache IDF submodules - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | .git/modules/ports/espressif/esp-idf @@ -26,7 +27,7 @@ runs: key: submodules-idf-${{ steps.idf-commit.outputs.commit }} - name: Cache IDF tools - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ${{ env.IDF_TOOLS_PATH }} key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-idf-${{ steps.idf-commit.outputs.commit }} diff --git a/.github/actions/deps/ports/nordic/action.yml b/.github/actions/deps/ports/nordic/action.yml index 5f08b17ca7a68..96754be9507c5 100644 --- a/.github/actions/deps/ports/nordic/action.yml +++ b/.github/actions/deps/ports/nordic/action.yml @@ -5,7 +5,7 @@ runs: steps: - name: Get nrfutil 7+ run: | - wget https://developer.nordicsemi.com/.pc-tools/nrfutil/x64-linux/nrfutil + wget https://files.nordicsemi.com/artifactory/swtools/external/nrfutil/executables/x86_64-unknown-linux-gnu/nrfutil chmod +x nrfutil ./nrfutil install nrf5sdk-tools mkdir -p $HOME/.local/bin diff --git a/.github/actions/deps/ports/zephyr-cp/action.yml b/.github/actions/deps/ports/zephyr-cp/action.yml new file mode 100644 index 0000000000000..6c538e3fa573e --- /dev/null +++ b/.github/actions/deps/ports/zephyr-cp/action.yml @@ -0,0 +1,28 @@ +name: Fetch Zephyr port deps + +runs: + using: composite + steps: + - name: Get Linux build dependencies + if: runner.os == 'Linux' + run: | + echo "--- cpu model ---" + grep "model name" /proc/cpuinfo | head -1 + sudo dpkg --add-architecture i386 + sudo apt-get update + sudo apt-get install -y libusb-1.0-0-dev libudev-dev pkg-config mtools + # We have to hold python3 so the following install works. See https://github.com/actions/runner-images/issues/13803 + sudo apt-mark hold python3 + sudo apt-get install -y libsdl2-dev:i386 libsdl2-image-dev:i386 + echo "PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" >> $GITHUB_ENV + shell: bash + - name: Setup Zephyr project + uses: zephyrproject-rtos/action-zephyr-setup@v1 + with: + app-path: zephyr-config + base-path: ports/zephyr-cp + toolchains: arm-zephyr-eabi + - name: Export cmake info + run: west zephyr-export + shell: bash + working-directory: ports/zephyr-cp diff --git a/.github/actions/deps/python/action.yml b/.github/actions/deps/python/action.yml index da59b87b17a29..bc8b578c1473d 100644 --- a/.github/actions/deps/python/action.yml +++ b/.github/actions/deps/python/action.yml @@ -16,7 +16,7 @@ runs: - name: Cache python dependencies id: cache-python-deps if: inputs.action == 'cache' - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: .cp_tools key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} @@ -24,7 +24,7 @@ runs: - name: Restore python dependencies id: restore-python-deps if: inputs.action == 'restore' - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: .cp_tools key: ${{ runner.os }}-${{ env.pythonLocation }}-tools-cp-${{ hashFiles('requirements-dev.txt') }} diff --git a/.github/actions/deps/submodules/action.yml b/.github/actions/deps/submodules/action.yml index 6878c5e7e5da9..5ec57b594c0da 100644 --- a/.github/actions/deps/submodules/action.yml +++ b/.github/actions/deps/submodules/action.yml @@ -22,7 +22,7 @@ inputs: - restore version: - description: 'Whether to generate CP version' + description: 'Whether to fetch tags to identify CP version' required: false default: false type: boolean @@ -48,7 +48,7 @@ runs: - name: Cache submodules if: ${{ inputs.action == 'cache' }} - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" key: submodules-common-${{ hashFiles('submodule_status') }} @@ -56,7 +56,7 @@ runs: - name: Restore submodules if: ${{ inputs.action == 'restore' }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@v5 with: path: ".git/modules/\n${{ join(fromJSON(steps.create-submodule-status.outputs.submodules), '\n') }}" key: submodules-common-${{ hashFiles('submodule_status') }} @@ -80,7 +80,7 @@ runs: git fetch --no-recurse-submodules --shallow-since="2021-07-01" origin $GITHUB_SHA git repack -d echo "::endgroup::" - CP_VERSION=$(tools/describe) + CP_VERSION=$(python py/version.py) echo "$CP_VERSION" echo "CP_VERSION=$CP_VERSION" >> $GITHUB_ENV echo "cp-version=$CP_VERSION" >> $GITHUB_OUTPUT diff --git a/.github/actions/mpy_cross/action.yml b/.github/actions/mpy_cross/action.yml index 8839f790915cf..469b8b0763e95 100644 --- a/.github/actions/mpy_cross/action.yml +++ b/.github/actions/mpy_cross/action.yml @@ -16,7 +16,7 @@ runs: id: download-mpy-cross if: inputs.download == 'true' continue-on-error: true - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: mpy-cross path: mpy-cross/build @@ -36,7 +36,7 @@ runs: - name: Upload mpy-cross if: inputs.download == 'false' || steps.download-mpy-cross.outcome == 'failure' continue-on-error: true - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: mpy-cross path: mpy-cross/build/mpy-cross diff --git a/.github/actions/upload_aws/action.yml b/.github/actions/upload_aws/action.yml index 643dd003427dc..bc34aebdea7b7 100644 --- a/.github/actions/upload_aws/action.yml +++ b/.github/actions/upload_aws/action.yml @@ -20,8 +20,11 @@ runs: steps: - name: Upload to S3 if: >- - (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') || - (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')) + (github.event_name == 'push' && github.repository_owner == 'adafruit') && + (github.ref == 'refs/heads/main' || + (startswith(github.ref, 'refs/heads/') && endswith(github.ref, '.x'))) || + (github.event_name == 'release' && + (github.event.action == 'published' || github.event.action == 'rerequested')) run: >- [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp ${{ inputs.source }} s3://adafruit-circuit-python/bin/${{ inputs.destination }} diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000000..21f1e4e630ae2 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,10 @@ +Thanks for submitting a pull request to CircuitPython! Remove these instructions before submitting. + + See https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github for detailed instructions. + +- Consider whether to submit this PR against `main` or against (if it exists) the branch for the current stable release or an upcoming minor release. The branch will be named `i.j.x`, for example, `9.2.x`. Bug fixes and minor enhancements can be submitted against the stable release branch, and will be merged to `main` regularly. +- Create your own fork of `circuitpython` and create a branch for your changes. +- Use `pre-commit` to check your commits before submitting. See https://learn.adafruit.com/contribute-to-circuitpython-with-git-and-github/check-your-code. +- Test your changes and tell us how you tested. + +--- diff --git a/.github/workflows/build-board-custom.yml b/.github/workflows/build-board-custom.yml index e479540be63ab..c17e1b13f9791 100644 --- a/.github/workflows/build-board-custom.yml +++ b/.github/workflows/build-board-custom.yml @@ -36,40 +36,55 @@ run-name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ in jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Set up repository run: | git clone --filter=tree:0 https://github.com/adafruit/circuitpython.git $GITHUB_WORKSPACE - name: Checkout head / tag + env: + TAG: ${{ inputs.version == 'latest' && 'HEAD' || inputs.version }} run: | - git checkout ${{ inputs.version == 'latest' && 'HEAD' || inputs.version }} + git checkout "$TAG" - name: fork compatibility if: github.repository_owner != 'adafruit' + env: + REPO: ${{ github.repository }} run: | - git remote add fork https://github.com/${{github.repository}}.git + git remote add fork "https://github.com/$REPO.git" git fetch fork --filter=tree:0 - name: branch compatibility if: inputs.branch != 'main' && inputs.version == 'latest' && github.repository_owner == 'adafruit' + env: + BRANCH: ${{ inputs.branch }} run: | - git checkout ${{inputs.branch}} + git checkout "$BRANCH" - name: branch compatibility (fork) if: inputs.branch != '' && inputs.version == 'latest' && github.repository_owner != 'adafruit' + env: + BRANCH: ${{ inputs.branch }} run: | - git checkout -b fork-branch fork/${{inputs.branch}} + git checkout -b fork-branch "fork/$BRANCH" - name: Set up identifier if: inputs.debug || inputs.flags != '' run: | > custom-build && git add custom-build - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x + - name: Board to port + id: board-to-port + run: | + PORT=$(python tools/board_to_port.py "${{ inputs.board }}") + echo "port=$PORT" >> $GITHUB_OUTPUT + shell: bash - name: Set up port id: set-up-port uses: ./.github/actions/deps/ports with: board: ${{ inputs.board }} + port: ${{ steps.board-to-port.outputs.port }} - name: Set up submodules id: set-up-submodules uses: ./.github/actions/deps/submodules @@ -80,7 +95,7 @@ jobs: uses: ./.github/actions/deps/external with: action: cache - port: ${{ steps.set-up-port.outputs.port }} + port: ${{ steps.board-to-port.outputs.port }} - name: Set up mpy-cross if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross @@ -89,7 +104,7 @@ jobs: download: false - name: Versions run: | - tools/describe + python py/version.py gcc --version python3 --version cmake --version || true @@ -101,10 +116,15 @@ jobs: riscv64-unknown-elf-gcc --version || true mkfs.fat --version || true - name: Build board - run: make -j4 ${{ inputs.flags }} BOARD=${{ inputs.board }} DEBUG=${{ inputs.debug && '1' || '0' }} TRANSLATION=${{ inputs.language }} - working-directory: ports/${{ steps.set-up-port.outputs.port }} + env: + TRANSLATION: ${{ inputs.language }} + BOARD: ${{ inputs.board }} + FLAGS: ${{ inputs.flags }} + DEBUG: ${{ inputs.debug && '1' || '0' }} + run: make -j4 $FLAGS BOARD="$BOARD" DEBUG=$DEBUG TRANSLATION="$TRANSLATION" + working-directory: ports/${{ steps.board-to-port.outputs.port }} - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ inputs.board }}-${{ inputs.language }}-${{ inputs.version }}${{ inputs.flags != '' && '-custom' || '' }}${{ inputs.debug && '-debug' || '' }} - path: ports/${{ steps.set-up-port.outputs.port }}/build-${{ inputs.board }}/firmware.* + path: ports/${{ steps.board-to-port.outputs.port }}/build-${{ inputs.board }}/firmware.* diff --git a/.github/workflows/build-boards.yml b/.github/workflows/build-boards.yml index 07f3628207995..6fbc5b6a08f15 100644 --- a/.github/workflows/build-boards.yml +++ b/.github/workflows/build-boards.yml @@ -9,6 +9,9 @@ on: cp-version: required: true type: string + port: + required: true + type: string secrets: AWS_ACCESS_KEY_ID: required: false @@ -17,7 +20,7 @@ on: jobs: board: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 env: CP_VERSION: ${{ inputs.cp-version }} strategy: @@ -26,14 +29,15 @@ jobs: board: ${{ fromJSON(inputs.boards) }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x @@ -42,6 +46,7 @@ jobs: uses: ./.github/actions/deps/ports with: board: ${{ matrix.board }} + port: ${{ inputs.port }} - name: Set up submodules id: set-up-submodules @@ -50,7 +55,7 @@ jobs: - name: Set up external uses: ./.github/actions/deps/external with: - port: ${{ steps.set-up-port.outputs.port }} + port: ${{ inputs.port }} - name: Set up mpy-cross if: steps.set-up-submodules.outputs.frozen == 'True' uses: ./.github/actions/mpy_cross @@ -82,7 +87,7 @@ jobs: HEAD_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.board }} path: bin/${{ matrix.board }} diff --git a/.github/workflows/build-mpy-cross.yml b/.github/workflows/build-mpy-cross.yml index 26226d84e6af0..9e5c1cdfc4a8d 100644 --- a/.github/workflows/build-mpy-cross.yml +++ b/.github/workflows/build-mpy-cross.yml @@ -14,7 +14,7 @@ on: jobs: build: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 strategy: fail-fast: false matrix: @@ -28,13 +28,14 @@ jobs: OS_static-raspbian: linux-raspbian steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -57,12 +58,15 @@ jobs: run: make -C mpy-cross -j4 -f Makefile.${{ matrix.mpy-cross }} - name: Set output + env: + EX: ${{ env[format('EX_{0}', matrix.mpy-cross)] || matrix.mpy-cross }} + OS: ${{ env[format('OS_{0}', matrix.mpy-cross)] }}" run: | - echo >> $GITHUB_ENV "EX=${{ env[format('EX_{0}', matrix.mpy-cross)] || matrix.mpy-cross }}" - echo >> $GITHUB_ENV "OS=${{ env[format('OS_{0}', matrix.mpy-cross)] }}" + echo >> $GITHUB_ENV "EX=$EX" + echo >> $GITHUB_ENV "OS=$OS" - name: Upload artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: mpy-cross.${{ env.EX }} path: mpy-cross/build-${{ matrix.mpy-cross }}/mpy-cross.${{ env.EX }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f9026830bb050..6a2329a411340 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ concurrency: jobs: scheduler: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 outputs: docs: ${{ steps.set-matrix.outputs.docs }} ports: ${{ steps.set-matrix.outputs.ports }} @@ -28,13 +28,14 @@ jobs: env: GITHUB_CONTEXT: ${{ toJson(github) }} - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Duplicate USB VID/PID check @@ -66,7 +67,9 @@ jobs: EXCLUDE_COMMIT: ${{ github.event.pull_request.head.sha }} - name: Set head sha (pull) if: github.event_name == 'pull_request' - run: echo "HEAD_SHA=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV + env: + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: echo "HEAD_SHA=$HEAD_SHA" >> $GITHUB_ENV - name: Set base sha (pull) if: github.event_name == 'pull_request' run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true @@ -74,7 +77,9 @@ jobs: SHA: ${{ steps.get-last-commit-with-checks.outputs.commit_sha || github.event.pull_request.base.sha }} - name: Set head sha (push) if: github.event_name == 'push' - run: echo "HEAD_SHA=${{ github.event.after }}" >> $GITHUB_ENV + env: + SHA: ${{ github.event.after }} + run: echo "HEAD_SHA=$SHA" >> $GITHUB_ENV - name: Set base sha (push) if: github.event_name == 'push' run: git cat-file -e $SHA && echo "BASE_SHA=$SHA" >> $GITHUB_ENV || true @@ -102,20 +107,21 @@ jobs: cp-version: ${{ needs.scheduler.outputs.cp-version }} mpy-cross-mac: - runs-on: macos-12 + runs-on: macos-latest needs: scheduler if: needs.scheduler.outputs.ports != '{}' env: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -125,57 +131,45 @@ jobs: gcc --version python3 --version msgfmt --version - - name: Build mpy-cross - run: make -C mpy-cross -j4 - - uses: actions/upload-artifact@v4 - with: - name: mpy-cross-macos-x64 - path: mpy-cross/build/mpy-cross - name: Build mpy-cross (arm64) run: make -C mpy-cross -j4 -f Makefile.m1 V=2 - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: mpy-cross-macos-arm64 path: mpy-cross/build-arm64/mpy-cross-arm64 - - name: Make universal binary - run: lipo -create -output mpy-cross-macos-universal mpy-cross/build/mpy-cross mpy-cross/build-arm64/mpy-cross-arm64 - - name: Upload artifact - uses: actions/upload-artifact@v4 - with: - name: mpy-cross-macos-universal - path: mpy-cross-macos-universal - name: Upload to S3 if: >- (github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'adafruit') || (github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'rerequested')) run: | - [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross-macos-universal s3://adafruit-circuit-python/bin/mpy-cross/macos/mpy-cross-macos-${{ env.CP_VERSION }}-universal --no-progress --region us-east-1 - [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build-arm64/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/macos/mpy-cross-macos-${{ env.CP_VERSION }}-arm64 --no-progress --region us-east-1 - [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build/mpy-cross s3://adafruit-circuit-python/bin/mpy-cross/macos/mpy-cross-macos-${{ env.CP_VERSION }}-x64 --no-progress --region us-east-1 + [ -z "$AWS_ACCESS_KEY_ID" ] || aws s3 cp mpy-cross/build-arm64/mpy-cross-arm64 s3://adafruit-circuit-python/bin/mpy-cross/macos/mpy-cross-macos-"${CP_VERSION}"-arm64 --no-progress --region us-east-1 env: AWS_PAGER: '' AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} docs: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 needs: scheduler if: needs.scheduler.outputs.docs == 'True' env: CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules uses: ./.github/actions/deps/submodules + with: + version: true - name: Install dependencies run: | sudo apt-get update @@ -183,20 +177,20 @@ jobs: pip install -r requirements-doc.txt - name: Build and Validate Stubs run: make check-stubs -j4 - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: stubs path: circuitpython-stubs/dist/* - name: Test Documentation Build (HTML) - run: sphinx-build -E -W -b html -D version=${{ env.CP_VERSION }} -D release=${{ env.CP_VERSION }} . _build/html - - uses: actions/upload-artifact@v4 + run: sphinx-build -E -W -b html -D version="$CP_VERSION" -D release="$CP_VERSION" . _build/html + - uses: actions/upload-artifact@v7 with: name: docs-html path: _build/html - name: Test Documentation Build (LaTeX/PDF) run: | make latexpdf - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@v7 with: name: docs-latexpdf path: _build/latex @@ -252,9 +246,9 @@ jobs: python3 -c "import sys, locale; print(sys.getdefaultencoding(), locale.getpreferredencoding(False))" - name: Install dependencies run: | - wget --no-verbose -O gcc-arm.zip https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-mingw-w64-i686-arm-none-eabi.zip - unzip -q -d /tmp gcc-arm.zip - tar -C /tmp/arm-gnu-toolchain* -cf - . | tar -C /usr/local -xf - + wget --no-verbose -O gcc-arm.zip https://developer.arm.com/-/media/Files/downloads/gnu/15.2.rel1/binrel/arm-gnu-toolchain-15.2.rel1-mingw-w64-i686-arm-none-eabi.zip + unzip -q -d /tmp/arm-gnu-toolchain gcc-arm.zip + tar -C /tmp/arm-gnu-toolchain -cf - . | tar -C /usr/local -xf - # We could use a venv instead, but that requires entering the venv on each run step # that runs in its own shell. There are some actions that help with that, but not for msys2 # that I can find. (dhalbert) @@ -266,11 +260,12 @@ jobs: which python; python --version; python -c "import cascadetoml" which python3; python3 --version; python3 -c "import cascadetoml" - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up submodules uses: ./.github/actions/deps/submodules - name: build mpy-cross @@ -289,6 +284,35 @@ jobs: # ERROR: Platform MINGW64_NT-10.0-17763-x86_64 appears to be unsupported # https://github.com/espressif/esp-idf/issues/7062 + windows-zephyr: + strategy: + matrix: + os: [windows-2022, windows-2025] + runs-on: ${{ matrix.os }} + needs: scheduler + if: needs.scheduler.outputs.windows == 'True' + env: + CP_VERSION: ${{ needs.scheduler.outputs.cp-version }} + steps: + - name: Set up repository + uses: actions/checkout@v6 + with: + submodules: false + show-progress: false + fetch-depth: 1 + persist-credentials: false + - uses: actions/setup-python@v6 + with: + python-version: '3.13' + - name: Set up Zephyr + uses: ./.github/actions/deps/ports/zephyr-cp + - name: Set up submodules + uses: ./.github/actions/deps/submodules + - name: build mpy-cross + run: make -j4 -C mpy-cross + - name: build ek_ra8d1 + run: make -j4 -C ports/zephyr-cp BOARD=renesas_ek_ra8d1 + ports: needs: [scheduler, mpy-cross, tests] if: needs.scheduler.outputs.ports != '{}' @@ -301,3 +325,4 @@ jobs: with: boards: ${{ toJSON(fromJSON(needs.scheduler.outputs.ports)[matrix.port]) }} cp-version: ${{ needs.scheduler.outputs.cp-version }} + port: ${{ matrix.port }} diff --git a/.github/workflows/bundle_cron.yml b/.github/workflows/bundle_cron.yml new file mode 100644 index 0000000000000..eefffaaa5b9ab --- /dev/null +++ b/.github/workflows/bundle_cron.yml @@ -0,0 +1,58 @@ +# SPDX-FileCopyrightText: 2019 Michael Schroeder +# +# SPDX-License-Identifier: MIT + +name: Update Bundles + +on: + schedule: + - cron: 0 5 * * * + workflow_dispatch: + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + steps: + - name: repository + env: + OWNER_IS_ADAFRUIT: ${{ startswith(github.repository, 'adafruit/') }} + run: | + echo "This workflow will only run if Adafruit is the repository owner." + echo "Repository owner is Adafruit: $OWNER_IS_ADAFRUIT" + update-bundles: + runs-on: ubuntu-latest + # Only run the build on Adafruit's repository. Forks won't have the secrets. + # It's necessary to do this here, since 'schedule' events cannot (currently) + # be limited (they run on all forks' default branches). + if: startswith(github.repository, 'adafruit/') + steps: + - name: Set up Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: 3.12 + - name: Load contributor cache + uses: actions/cache@v5 + with: + key: "contributor-cache" + path: "contributors.json" + - name: Versions + run: | + python3 --version + - uses: actions/checkout@v6 + with: + repository: 'adafruit/adabot' + submodules: true + - name: Install deps + run: | + pip install -r requirements.txt + - name: Run adabot.circuitpython_bundle + env: + ADABOT_EMAIL: ${{ secrets.ADABOT_EMAIL }} + ADABOT_GITHUB_USER: ${{ secrets.ADABOT_GITHUB_USER }} + ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + BIGQUERY_PRIVATE_KEY: ${{ secrets.BIGQUERY_PRIVATE_KEY }} + BIGQUERY_CLIENT_EMAIL: ${{ secrets.BIGQUERY_CLIENT_EMAIL }} + run: | + python3 -u -m adabot.circuitpython_bundle diff --git a/.github/workflows/create-website-pr.yml b/.github/workflows/create-website-pr.yml index 050d1d3941417..559a41e67e793 100644 --- a/.github/workflows/create-website-pr.yml +++ b/.github/workflows/create-website-pr.yml @@ -10,20 +10,21 @@ on: jobs: website: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Dump GitHub context run: echo "$GITHUB_CONTEXT" env: GITHUB_CONTEXT: ${{ toJson(github) }} - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules diff --git a/.github/workflows/learn_cron.yml b/.github/workflows/learn_cron.yml new file mode 100644 index 0000000000000..135089bfd5ef2 --- /dev/null +++ b/.github/workflows/learn_cron.yml @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +name: Tag Learning System Guides + +on: + schedule: + - cron: 0 5 * * * + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + if: ${{ (github.repository_owner != 'adafruit') }} + steps: + - run: | + echo "This workflow is only intended to run in the adafruit fork" + + update-learn: + runs-on: ubuntu-latest + # Only run the build if the access token has been configured. This will be + # the case on Adafruit's repository. It's necessary to do this here, since + # 'schedule' events cannot (currently) be limited (they run on all forks' + # default branches). + if: ${{ (github.repository_owner == 'adafruit') }} + steps: + - uses: actions/checkout@v6 + with: + repository: ${{ github.repository_owner }}/Adafruit_Learning_System_Guides + token: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + - name: Tag a release + env: + ADABOT_EMAIL: ${{ secrets.ADABOT_EMAIL }} + run: | + git config --global user.name adabot + git config --global user.email "$ADABOT_EMAIL" + TAG_NAME=`date +%Y%m%d` + git tag $TAG_NAME + git push origin $TAG_NAME diff --git a/.github/workflows/notify-on-issue-label.yml b/.github/workflows/notify-on-issue-label.yml index da1ac0a18e28a..2b229156811f8 100644 --- a/.github/workflows/notify-on-issue-label.yml +++ b/.github/workflows/notify-on-issue-label.yml @@ -10,7 +10,7 @@ jobs: permissions: issues: write steps: - - uses: tekktrik/issue-labeled-ping@v1 + - uses: tekktrik/issue-labeled-ping@v2 with: github-token: ${{ secrets.GITHUB_TOKEN }} user: v923z diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index ceeba5900d6ae..21ae984e46870 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -14,16 +14,17 @@ concurrency: jobs: pre-commit: - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - name: Set up repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: submodules: false show-progress: false fetch-depth: 1 + persist-credentials: false - name: Set up python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: 3.x - name: Set up submodules @@ -41,7 +42,7 @@ jobs: run: git diff > ~/pre-commit.patch - name: Upload patch if: failure() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: patch path: ~/pre-commit.patch diff --git a/.github/workflows/reports_cron.yml b/.github/workflows/reports_cron.yml new file mode 100644 index 0000000000000..476ead95d256a --- /dev/null +++ b/.github/workflows/reports_cron.yml @@ -0,0 +1,91 @@ +# SPDX-FileCopyrightText: 2019 Michael Schroeder +# +# SPDX-License-Identifier: MIT + +name: Run Daily Reports + +on: + schedule: + # The actor (github.actor) that runs the cron job may be the user who created the cron job + # initially. It does not appear to be settable via a secret or environment variable. + - cron: 15 5 * * * + workflow_dispatch: + + +jobs: + check-repo-owner: + # This job is so the entire workflow will end successfully and give some + # output to explain why it hasn't run on a non-Adafruit fork. + runs-on: ubuntu-latest + steps: + - name: repository + env: + OWNER_IS_ADAFRUIT: ${{ startswith(github.repository, 'adafruit/') }} + run: | + echo "This workflow will only run if Adafruit is the repository owner." + echo "Repository owner is Adafruit: $OWNER_IS_ADAFRUIT" + run-reports: + runs-on: ubuntu-latest + # Only run the build on Adafruit's repository. Forks won't have the secrets. + # It's necessary to do this here, since 'schedule' events cannot (currently) + # be limited (they run on all forks' default branches). + if: startswith(github.repository, 'adafruit/') + env: + ADABOT_GITHUB_USER: ${{ secrets.ADABOT_GITHUB_USER }} + ADABOT_GITHUB_ACCESS_TOKEN: ${{ secrets.ADABOT_GITHUB_ACCESS_TOKEN }} + RTD_TOKEN: ${{ secrets.RTD_TOKEN }} + BIGQUERY_PRIVATE_KEY: ${{ secrets.BIGQUERY_PRIVATE_KEY }} + BIGQUERY_CLIENT_EMAIL: ${{ secrets.BIGQUERY_CLIENT_EMAIL }} + steps: + - name: Set up Python 3.11 + uses: actions/setup-python@v6 + with: + python-version: 3.11 + - name: Versions + run: | + python3 --version + - uses: actions/checkout@v6 + with: + repository: 'adafruit/adabot' + submodules: true + - name: Install deps + run: | + pip install -r requirements.txt + - name: Make Directory For Report Files + run: mkdir -p bin/adabot + - name: Set Date Variable + id: today + run: | + echo date=$( + date +%Y%m%d + ) >> $GITHUB_OUTPUT + - name: Run adabot.circuitpython_libraries + env: + # LIB_CHECK_CP_FILE is for circuitpython_libraries.py output + LIB_CHECK_CP_FILE: bin/adabot/circuitpython_library_report_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.circuitpython_libraries -o $LIB_CHECK_CP_FILE + continue-on-error: true + - name: Run adabot.circuitpython_library_download_stats + env: + # LIB_DL_STATS_FILE is for future Bundle and PyPi download stats script + LIB_DL_STATS_FILE: bin/adabot/library_download_stats_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.circuitpython_library_download_stats -o $LIB_DL_STATS_FILE + continue-on-error: true + - name: Run adabot.arduino_libraries + env: + # LIB_CHECK_ARD_FILE is for arduino_libraries.py output + LIB_CHECK_ARD_FILE: bin/adabot/arduino_library_report_${{ steps.today.outputs.date }}.txt + run: | + python3 -u -m adabot.arduino_libraries -o $LIB_CHECK_ARD_FILE + continue-on-error: true + - name: Check For Files + run: | + ls bin/adabot + - name: Upload Reports To AWS S3 + if: ${{ github.event_name != 'workflow_dispatch' }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: "[ -z \"$AWS_ACCESS_KEY_ID\" ] || aws s3 cp bin/adabot/ s3://adafruit-circuit-python/adabot/bin/reports/ --recursive --no-progress --region us-east-1" diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 729be77979dee..83154bbbd2b66 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -23,45 +23,82 @@ jobs: TEST_native: --emit native TEST_native_mpy: --via-mpy --emit native -d basics float micropython steps: - - name: Set up repository - uses: actions/checkout@v4 - with: - submodules: false - show-progress: false - fetch-depth: 1 - - name: Set up python - uses: actions/setup-python@v5 - with: - python-version: 3.12 - - name: Set up submodules - uses: ./.github/actions/deps/submodules - with: - target: tests - - name: Set up external - if: matrix.test == 'all' - uses: ./.github/actions/deps/external - - name: Set up mpy-cross - uses: ./.github/actions/mpy_cross - with: - cp-version: ${{ inputs.cp-version }} - - name: Build unix port - run: make -C ports/unix VARIANT=coverage -j4 - - name: Run tests - run: ./run-tests.py -j4 ${{ env[format('TEST_{0}', matrix.test)] }} - working-directory: tests - - name: Print failure info - run: ./run-tests.py -j4 --print-failures - if: failure() - working-directory: tests - - name: Build native modules - if: matrix.test == 'all' - run: | - make -C examples/natmod/features1 - make -C examples/natmod/features2 - make -C examples/natmod/heapq - make -C examples/natmod/random - make -C examples/natmod/re - - name: Test native modules - if: matrix.test == 'all' - run: ./run-natmodtests.py extmod/{heapq*,re*,zlib*}.py - working-directory: tests + - name: Set up repository + uses: actions/checkout@v6 + with: + submodules: false + show-progress: false + fetch-depth: 1 + - name: Set up python + uses: actions/setup-python@v6 + with: + python-version: 3.12 + - name: Set up submodules + uses: ./.github/actions/deps/submodules + with: + target: tests + - name: Set up external + if: matrix.test == 'all' + uses: ./.github/actions/deps/external + - name: Set up mpy-cross + uses: ./.github/actions/mpy_cross + with: + cp-version: ${{ inputs.cp-version }} + - name: Build unix port + run: make -C ports/unix VARIANT=coverage -j4 + - name: Run tests + run: ./run-tests.py -j4 ${{ env[format('TEST_{0}', matrix.test)] }} + working-directory: tests + - name: Print failure info + run: ./run-tests.py -j4 --print-failures + if: failure() + working-directory: tests + # Not working after MicroPython v1.23 merge. + # - name: Build native modules + # if: matrix.test == 'all' + # run: | + # make -C examples/natmod/features1 + # make -C examples/natmod/features2 + # make -C examples/natmod/heapq + # make -C examples/natmod/random + # make -C examples/natmod/re + # - name: Test native modules + # if: matrix.test == 'all' + # run: ./run-natmodtests.py extmod/{heapq*,random*,re*}.py + # working-directory: tests + + zephyr: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + env: + CP_VERSION: ${{ inputs.cp-version }} + steps: + - name: Set up repository + uses: actions/checkout@v6 + with: + submodules: false + show-progress: false + fetch-depth: 1 + - name: Set up python + uses: actions/setup-python@v6 + with: + python-version: 3.13 + - name: Set up Zephyr + uses: ./.github/actions/deps/ports/zephyr-cp + - name: Set up submodules + id: set-up-submodules + uses: ./.github/actions/deps/submodules + with: + target: zephyr-cp + - name: Set up external + uses: ./.github/actions/deps/external + - name: Build native sim target + run: make -C ports/zephyr-cp -j2 BOARD=native_native_sim + - name: Build bsim + run: make -j 2 everything + working-directory: ports/zephyr-cp/tools/bsim + - name: Build native_nrf5340bsim + run: make -C ports/zephyr-cp -j2 BOARD=native_nrf5340bsim + - name: Run Zephyr tests + run: make -C ports/zephyr-cp test diff --git a/.gitignore b/.gitignore index 9679ed5e0e2bc..ca6872387dd27 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ *.o *.a !atmel-samd/asf/**/*.a +!ports/espressif/microros-lib/**/*.a *.elf *.bin !*.toml.bin @@ -38,10 +39,12 @@ bin/ circuitpython-stubs/ test-stubs/ build-*/ +docs/genrst/ -# Test failure outputs +# Test failure outputs and intermediate artifacts ###################### tests/results/* +tests/ports/unix/ffi_lib.so # Python cache files ###################### @@ -52,6 +55,9 @@ __pycache__/ ###################### GNUmakefile user.props +user_pre_mpconfigport.mk +user_post_mpconfigport.mk +user_post_circuitpy_defns.mk # Sphinx output ############### @@ -75,6 +81,7 @@ TAGS #################### *~ +# MacOS desktop metadata files *.DS_Store **/*.DS_Store *.icloud @@ -97,3 +104,16 @@ TAGS # clangd cache ############## .cache + +**/CLAUDE.local.md +.claude + +# windsurf rules +.windsurfrules + +# git-review-web outputs +.review + +# Zephyr trace files +**/channel0_0 +**/*.perfetto-trace diff --git a/.gitmodules b/.gitmodules index 1762544b77666..a7b67b8d86051 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,10 +7,10 @@ url = https://github.com/micropython/axtls.git [submodule "lib/libffi"] path = lib/libffi - url = https://github.com/atgreen/libffi + url = https://github.com/libffi/libffi [submodule "lib/berkeley-db-1.xx"] path = lib/berkeley-db-1.xx - url = https://github.com/pfalcon/berkeley-db-1.xx + url = https://github.com/micropython/berkeley-db-1.xx [submodule "tools/uf2"] path = tools/uf2 url = https://github.com/Microsoft/uf2.git @@ -143,10 +143,11 @@ [submodule "ports/espressif/esp-idf"] path = ports/espressif/esp-idf url = https://github.com/adafruit/esp-idf.git - branch = circuitpython-v5.3 + branch = circuitpython-v5.5.1 [submodule "ports/espressif/esp-protocols"] path = ports/espressif/esp-protocols - url = https://github.com/espressif/esp-protocols.git + url = https://github.com/adafruit/esp-protocols.git + branch = circuitpython [submodule "ports/espressif/esp-camera"] path = ports/espressif/esp-camera url = https://github.com/adafruit/esp32-camera.git @@ -172,6 +173,7 @@ [submodule "ports/raspberrypi/sdk"] path = ports/raspberrypi/sdk url = https://github.com/raspberrypi/pico-sdk.git + branch = force_inline_critical_section_2.1.1 [submodule "data/nvm.toml"] path = data/nvm.toml url = https://github.com/adafruit/nvm.toml.git @@ -311,7 +313,7 @@ [submodule "ports/raspberrypi/lib/lwip"] path = ports/raspberrypi/lib/lwip url = https://github.com/adafruit/lwip.git - branch = circuitpython8 + branch = circuitpython9 [submodule "lib/mbedtls"] path = lib/mbedtls url = https://github.com/ARMmbed/mbedtls.git @@ -344,8 +346,8 @@ url = https://github.com/adafruit/Adafruit_CircuitPython_Wave.git [submodule "ports/raspberrypi/lib/Pico-PIO-USB"] path = ports/raspberrypi/lib/Pico-PIO-USB - url = https://github.com/adafruit/Pico-PIO-USB.git - branch = sdk2_fix + url = https://github.com/sekigon-gonnoc/Pico-PIO-USB.git + branch = main [submodule "lib/micropython-lib"] path = lib/micropython-lib url = https://github.com/micropython/micropython-lib.git @@ -407,3 +409,15 @@ [submodule "frozen/Adafruit_CircuitPython_Wiznet5k"] path = frozen/Adafruit_CircuitPython_Wiznet5k url = https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k +[submodule "ports/analog/msdk"] + path = ports/analog/msdk + url = https://github.com/analogdevicesinc/msdk.git +[submodule "ports/espressif/microros-lib"] + path = ports/espressif/microros-lib + url = https://github.com/hierophect/microros-lib.git +[submodule "frozen/Adafruit_CircuitPython_OPT4048"] + path = frozen/Adafruit_CircuitPython_OPT4048 + url = https://github.com/adafruit/Adafruit_CircuitPython_OPT4048.git +[submodule "frozen/CircuitPython_edupico2_paj7620"] + path = frozen/CircuitPython_edupico2_paj7620 + url = https://github.com/CytronTechnologies/CircuitPython_edupico2_paj7620.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 226bbdea62874..c39faf99f00d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,19 +4,33 @@ # CIRCUITPY-CHANGE: CircuitPython-specific. +# Note that by default, pre-commit hooks do not look inside submodules. +# So you don't need to exclude submodules explicitly here. + repos: -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.0.1 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 hooks: - - id: check-yaml - - id: end-of-file-fixer - exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|ports/raspberrypi/sdk|lib/tinyusb)' - - id: trailing-whitespace - exclude: '^(tests/.*\.exp|tests/cmdline/.*|tests/.*/data/.*|lib/mbedtls_errors/generate_errors.diff|ports/raspberrypi/sdk|lib/tinyusb)' -- repo: https://github.com/codespell-project/codespell - rev: v2.2.4 + - id: check-yaml + - id: end-of-file-fixer + exclude: | + (?x)^( + tests/.*\.exp| + tests/cmdline/.*| + tests/.*/data/.* + ) + - id: trailing-whitespace + exclude: | + (?x)^( + tests/.*\.exp| + tests/cmdline/.*| + tests/.*/data/.*| + lib/mbedtls_errors/generate_errors.diff + ) + - repo: https://github.com/codespell-project/codespell + rev: v2.4.1 hooks: - - id: codespell + - id: codespell args: [-w] exclude: | (?x)^( @@ -25,23 +39,30 @@ repos: tests/unicode/data/utf-8_invalid.txt| tests/extmod/data/qr.pgm| tests/basics/bytearray_byte_operations.py| - ports/raspberrypi/sdk + ports/zephyr-cp/cptools/compat2driver.py ) -- repo: local + - repo: local hooks: - - id: translations + - id: translations name: Translations entry: sh -c "if ! make check-translate; then make translate; fi" types: [c] pass_filenames: false language: system - - id: formatting + - id: formatting name: Formatting - entry: python3 tools/codeformat.py - types_or: [c, python] - language: system - exclude: | - (?x)^( - lib/tinyusb| - ports/raspberrypi/sdk - ) + entry: python3 tools/codeformat.py -v -c + language: python + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.15.7 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] + # Run the formatter. + - id: ruff-format + - repo: https://github.com/tox-dev/pyproject-fmt + rev: "v2.21.0" + hooks: + - id: pyproject-fmt diff --git a/.readthedocs.yml b/.readthedocs.yml index 5bfae07bc268e..504363e9772ed 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -9,7 +9,7 @@ version: 2 build: - os: ubuntu-20.04 + os: ubuntu-24.04 tools: python: "3" jobs: diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000..e7d2fdbbe8caf --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,4 @@ +- Capture CircuitPython output by finding the matching device in `/dev/serial/by-id` +- You can mount the CIRCUITPY drive by doing `udisksctl mount -b /dev/disk/by-label/CIRCUITPY` and access it via `/run/media//CIRCUITPY`. +- `circup` is a command line tool to install libraries and examples to CIRCUITPY. +- When connecting to serial devices on Linux use /dev/serial/by-id. These will be more stable than /dev/ttyACM*. diff --git a/BUILDING.md b/BUILDING.md index 34cd544d73658..6778965bed099 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -64,6 +64,52 @@ If you aren't sure what boards exist, have a peek in the boards subdirectory of If you have a fast computer with many cores, consider adding `-j` to your build flags, such as `-j17` on a 6-core 12-thread machine. +## Configuration + +Ports and boards are preconfigured, thus make knows how to build a specific +board. Power users can change the configuration of a specific board or port, +either by passing compile-time options to make, or by creating appropriate +make include files. + +The configuration system is hierarchical. A higher level will typically only +set an option that a lower level hasn't configured: + +* board configuration: `mpconfigport.mk` +* pre-port user configuration: `user_pre_mpconfigport.mk` +* port configuration: `mpconfigport.mk` +* post-port user configuration: `user_post_mpconfigport.mk` +* global configuration: `py/circuitpython_mpconfig.mk` + +The board configuration is within the board-directory, e.g. +`ports/raspberrypi/boards/raspberry_pi_pico/`, the port configuration is +in the port-directory, e.g. `ports/raspberrypi/`. + +Editing these configuration files is the way to go if you want to change +the default behavior and ultimately create a pull-request. Otherwise, +changes should go into one of the user configuration files. + +User specific configurations are optional and should be maintained out of +tree. Passing `-I directory` tells make where to search for the additional +configuration files. E.g. to speed up boots by removing the wait-time for +the save-mode button press, you would: + +* create a directory: `mkdir -p ~/my_cp_config` +* create the config file: `echo 'CIRCUITPY_SKIP_SAFE_MODE_WAIT=0' > ~/my_cp_config/user_pre_mpconfigport.mk` +* run make with: `make -I ~/my_cp_config BOARD=raspberry_pi_pico` + +Besides the `user*mpconfigport.mk` files, there is another optional file +named `user_post_circuitpy_defns.mk`. This file is included at the end +and can be used to tweak compiler-definitions that are not covered by +one of the compile time options `CIRCUITPY_*`. + +Example: to create a build for the Pico2-W with an integrated saves-partition, +you would create a `user_post_circuitpy_defns.mk` with the following content: + + $(info ===> processing user_post_circuitpy_defns.mk) + ifeq (${BOARD},raspberry_pi_pico2_w) + CFLAGS += -DCIRCUITPY_SAVES_PARTITION_SIZE=1048576 + endif + ## Testing If you are working on changes to the core language, you might find it useful to run the test suite. diff --git a/LICENSE b/LICENSE index 4338915beb14a..90d19f757b2db 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2023 Damien P. George +Copyright (c) 2013-2025 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -22,8 +22,6 @@ THE SOFTWARE. -------------------------------------------------------------------------------- -#CIRCUITPY-CHANGE: - Unless specified otherwise (see below), the above license and copyright applies to all files derived from MicroPython in this repository. diff --git a/LICENSE_MicroPython b/LICENSE_MicroPython index 2b9a64b89a723..1fad9b4134e01 100644 --- a/LICENSE_MicroPython +++ b/LICENSE_MicroPython @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2013-2022 Damien P. George +Copyright (c) 2013-2025 Damien P. George Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -35,9 +35,7 @@ used during the build process and is not part of the compiled source code. / (MIT) /drivers - /cc3000 (BSD-3-clause) /cc3100 (BSD-3-clause) - /wiznet5k (BSD-3-clause) /lib /asf4 (Apache-2.0) /axtls (BSD-3-clause) @@ -50,24 +48,31 @@ used during the build process and is not part of the compiled source code. /cmsis (BSD-3-clause) /crypto-algorithms (NONE) /libhydrogen (ISC) + /libmetal (BSD-3-clause) /littlefs (BSD-3-clause) /lwip (BSD-3-clause) /mynewt-nimble (Apache-2.0) /nrfx (BSD-3-clause) /nxp_driver (BSD-3-Clause) /oofatfs (BSD-1-clause) + /open-amp (BSD-3-clause) /pico-sdk (BSD-3-clause) /re15 (BSD-3-clause) /stm32lib (BSD-3-clause) /tinytest (BSD-3-clause) /tinyusb (MIT) /uzlib (Zlib) + /wiznet5k (MIT) /logo (uses OFL-1.1) /ports /cc3200 /hal (BSD-3-clause) /simplelink (BSD-3-clause) /FreeRTOS (GPL-2.0 with FreeRTOS exception) + /esp32 + /ppp_set_auth.* (Apache-2.0) + /rp2 + /mutex_extra.c (BSD-3-clause) /stm32 /usbd*.c (MCD-ST Liberty SW License Agreement V2) /stm32_it.* (MIT + BSD-3-clause) @@ -77,8 +82,6 @@ used during the build process and is not part of the compiled source code. /*/stm32*.h (BSD-3-clause) /usbdev (MCD-ST Liberty SW License Agreement V2) /usbhost (MCD-ST Liberty SW License Agreement V2) - /teensy - /core (PJRC.COM) /zephyr /src (Apache-2.0) /tools diff --git a/Makefile b/Makefile index 30966918c3651..175a1b6a3025f 100644 --- a/Makefile +++ b/Makefile @@ -40,20 +40,30 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(BASEOPTS) # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(BASEOPTS) -TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/cxd56 ports/espressif ports/mimxrt10xx ports/nordic ports/raspberrypi ports/stm py shared-bindings shared-module supervisor +TRANSLATE_SOURCES = extmod lib main.c ports/atmel-samd ports/analog ports/cxd56 ports/espressif ports/mimxrt10xx ports/nordic ports/raspberrypi ports/renode ports/stm ports/zephyr-cp py shared-bindings shared-module supervisor # Paths to exclude from TRANSLATE_SOURCES # Each must be preceded by "-path"; if any wildcards, enclose in quotes. # Separate by "-o" (Find's "or" operand) TRANSLATE_SOURCES_EXC = -path "ports/*/build-*" \ -o -path "ports/*/build" \ + -o -path ports/analog/msdk \ -o -path ports/atmel-samd/asf4 \ -o -path ports/cxd56/spresense-exported-sdk \ + -o -path ports/espressif/esp-camera \ -o -path ports/espressif/esp-idf \ + -o -path ports/espressif/esp-protocols \ -o -path ports/mimxrt10xx/sdk \ + -o -path ports/nordic/bluetooth \ + -o -path ports/nordic/nrfx \ + -o -path ports/raspberrypi/lib \ -o -path ports/raspberrypi/sdk \ + -o -path ports/stm/peripherals \ -o -path ports/stm/st_driver \ - -o -path lib/tinyusb \ - -o -path lib/lwip \ + -o -path ports/zephyr-cp/bootloader \ + -o -path ports/zephyr-cp/modules \ + -o -path ports/zephyr-cp/tools \ + -o -path ports/zephyr-cp/zephyr \ + -o -path lib \ -o -path extmod/ulab/circuitpython \ -o -path extmod/ulab/micropython \ @@ -226,7 +236,7 @@ pseudoxml: .PHONY: all-source all-source: -TRANSLATE_CHECK_SUBMODULES=if ! [ -f extmod/ulab/README.md ]; then python tools/ci_fetch_deps.py translate; fi +TRANSLATE_CHECK_SUBMODULES=if ! [ -f extmod/ulab/README.md ]; then $(PYTHON) tools/ci_fetch_deps.py translate; fi TRANSLATE_COMMAND=find $(TRANSLATE_SOURCES) -type d \( $(TRANSLATE_SOURCES_EXC) \) -prune -o -type f \( -iname "*.c" -o -iname "*.h" \) -print | (LC_ALL=C sort) | xgettext -x locale/synthetic.pot -f- -L C -s --add-location=file --keyword=MP_ERROR_TEXT -o - | sed -e '/"POT-Creation-Date: /d' locale/circuitpython.pot: all-source $(TRANSLATE_CHECK_SUBMODULES) @@ -261,21 +271,21 @@ check-translate: .PHONY: stubs stubs: - @rm -rf circuitpython-stubs - @mkdir circuitpython-stubs - @$(PYTHON) tools/extract_pyi.py shared-bindings/ $(STUBDIR) - @$(PYTHON) tools/extract_pyi.py extmod/ulab/code/ $(STUBDIR)/ulab - @$(PYTHON) tools/extract_pyi.py ports/atmel-samd/bindings $(STUBDIR) - @$(PYTHON) tools/extract_pyi.py ports/espressif/bindings $(STUBDIR) - @$(PYTHON) tools/extract_pyi.py ports/raspberrypi/bindings $(STUBDIR) - @cp setup.py-stubs circuitpython-stubs/setup.py - @cp README.rst-stubs circuitpython-stubs/README.rst - @cp MANIFEST.in-stubs circuitpython-stubs/MANIFEST.in - @$(PYTHON) tools/board_stubs/build_board_specific_stubs/board_stub_builder.py - @cp -r tools/board_stubs/circuitpython_setboard circuitpython-stubs/circuitpython_setboard - @$(PYTHON) -m build circuitpython-stubs - @touch circuitpython-stubs/board/__init__.py - @touch circuitpython-stubs/board_definitions/__init__.py + rm -rf circuitpython-stubs + mkdir circuitpython-stubs + $(PYTHON) tools/extract_pyi.py shared-bindings/ $(STUBDIR) + $(PYTHON) tools/extract_pyi.py extmod/ulab/code/ $(STUBDIR)/ulab + for d in ports/*/bindings; do \ + $(PYTHON) tools/extract_pyi.py "$$d" $(STUBDIR); done + sed -e "s,__version__,`python -msetuptools_scm`," < setup.py-stubs > circuitpython-stubs/setup.py + cp README.rst-stubs circuitpython-stubs/README.rst + cp MANIFEST.in-stubs circuitpython-stubs/MANIFEST.in + cp -r stubs/* circuitpython-stubs + $(PYTHON) tools/board_stubs/build_board_specific_stubs/board_stub_builder.py + cp -r tools/board_stubs/circuitpython_setboard circuitpython-stubs/circuitpython_setboard + $(PYTHON) -m build circuitpython-stubs + touch circuitpython-stubs/board/__init__.py + touch circuitpython-stubs/board_definitions/__init__.py .PHONY: check-stubs check-stubs: stubs @@ -289,6 +299,9 @@ update-frozen-libraries: one-of-each: samd21 litex mimxrt10xx nordic stm +analog: + $(MAKE) -C ports/analog/ BOARD=apard32690 + samd21: $(MAKE) -C ports/atmel-samd BOARD=trinket_m0 @@ -362,5 +375,6 @@ coverage-fresh: make -j -C ports/unix VARIANT=coverage .PHONY: run-tests +# If TESTS="abc.py def.py" is specified as an arg, run only those tests. Otherwise, run all tests. run-tests: - cd tests; MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py + cd tests; MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py $(TESTS) diff --git a/README.rst b/README.rst index 642a55dfb9f46..89c7d9229d8ed 100644 --- a/README.rst +++ b/README.rst @@ -136,6 +136,9 @@ Behavior - Adds a safe mode that does not run user code after a hard crash or brown out. This makes it possible to fix code that causes nasty crashes by making it available through mass storage after the crash. A reset (the button) is needed after it's fixed to get back into normal mode. +- A 1 second delay is added to the boot process during which time the status LED will flash, and + resetting the device or pressing the boot button will force the device into safe mode. This delay + can be removed by a compile time option (``CIRCUITPY_SKIP_SAFE_MODE_WAIT``). - Safe mode may be handled programmatically by providing a ``safemode.py``. ``safemode.py`` is run if the board has reset due to entering safe mode, unless the safe mode initiated by the user by pressing button(s). @@ -223,9 +226,9 @@ Ports Ports include the code unique to a microcontroller line. -The following ports are available: ``atmel-samd``, ``cxd56``, ``espressif``, ``litex``, ``mimxrt10xx``, ``nordic``, ``raspberrypi``, ``renode``, ``silabs`` (``efr32``), ``stm``, ``unix``. +The following ports are available: ``atmel-samd``, ``cxd56``, ``espressif``, ``litex``, ``mimxrt10xx``, ``nordic``, ``raspberrypi``, ``renode``, ``silabs`` (``efr32``), ``stm``, ``unix``, and ``zephyr-cp``. -However, not all ports are fully functional. Some have limited limited functionality and known serious bugs. +However, not all ports are fully functional. Some have limited functionality and known serious bugs. For details, refer to the **Port status** section in the `latest release `__ notes. Boards diff --git a/conf.py b/conf.py index 7120fa3f00a35..e2a8cbbd82faa 100644 --- a/conf.py +++ b/conf.py @@ -32,17 +32,15 @@ from sphinx import addnodes from sphinx.ext import intersphinx -tools_describe = str(pathlib.Path(__file__).parent / "tools/describe") - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('docs')) -sys.path.insert(0, os.path.abspath('.')) +sys.path.insert(0, os.path.abspath("docs")) +sys.path.insert(0, os.path.abspath(".")) import shared_bindings_matrix -master_doc = 'docs/index' +master_doc = "docs/index" # Grab the JSON values to use while building the module support matrix # in 'shared-bindings/index.rst' @@ -50,7 +48,7 @@ # The stubs must be built before we calculate the shared bindings matrix subprocess.check_output(["make", "stubs"]) -#modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards() +# modules_support_matrix = shared_bindings_matrix.support_matrix_excluded_boards() modules_support_matrix = shared_bindings_matrix.support_matrix_by_board() modules_support_matrix_reverse = defaultdict(list) for board, matrix_info in modules_support_matrix.items(): @@ -58,55 +56,65 @@ modules_support_matrix_reverse[module].append(board) modules_support_matrix_reverse = dict( - (module, sorted(boards)) - for module, boards in modules_support_matrix_reverse.items() + (module, sorted(boards)) for module, boards in modules_support_matrix_reverse.items() ) html_context = { - 'support_matrix': modules_support_matrix, - 'support_matrix_reverse': modules_support_matrix_reverse + "support_matrix": modules_support_matrix, + "support_matrix_reverse": modules_support_matrix_reverse, } # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.3' +needs_sphinx = "1.3" # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', + "sphinx.ext.autodoc", + "sphinx.ext.doctest", "sphinxcontrib.jquery", - 'sphinxcontrib.rsvgconverter', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx_search.extension', - 'rstjinja', - 'myst_parser', + "sphinxcontrib.rsvgconverter", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx_search.extension", + "rstjinja", + "myst_parser", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['templates', "docs/templates"] +templates_path = ["templates", "docs/templates"] # The suffix of source filenames. source_suffix = { - '.rst': 'restructuredtext', - '.md': 'markdown', + ".rst": "restructuredtext", + ".md": "markdown", } -extensions.append('autoapi.extension') +extensions.append("autoapi.extension") -autoapi_type = 'python' +autoapi_type = "python" # Uncomment this if debugging autoapi autoapi_keep_files = True -autoapi_dirs = [os.path.join('circuitpython-stubs', x) for x in os.listdir('circuitpython-stubs') if os.path.exists(os.path.join("circuitpython-stubs", x, "__init__.pyi"))] +autoapi_dirs = [ + os.path.join("circuitpython-stubs", x) + for x in os.listdir("circuitpython-stubs") + if os.path.exists(os.path.join("circuitpython-stubs", x, "__init__.pyi")) +] print("autoapi_dirs", autoapi_dirs) autoapi_add_toctree_entry = False -autoapi_options = ['members', 'undoc-members', 'private-members', 'show-inheritance', 'special-members', 'show-module-summary'] -autoapi_template_dir = 'docs/autoapi/templates' +autoapi_options = [ + "members", + "undoc-members", + "private-members", + "show-inheritance", + "special-members", + "show-module-summary", +] +autoapi_template_dir = "docs/autoapi/templates" autoapi_python_class_content = "both" autoapi_python_use_implicit_namespaces = True autoapi_root = "shared-bindings" @@ -117,23 +125,25 @@ # See https://github.com/sphinx-doc/sphinx/issues/12300 suppress_warnings = ["config.cache"] + def autoapi_prepare_jinja_env(jinja_env): - jinja_env.globals['support_matrix_reverse'] = modules_support_matrix_reverse + jinja_env.globals["support_matrix_reverse"] = modules_support_matrix_reverse + -redirects_file = 'docs/redirects.txt' +redirects_file = "docs/redirects.txt" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -#master_doc = 'index' +# master_doc = 'index' # Get current date (execution) for copyright year current_date = time.localtime() # General information about the project. -project = 'Adafruit CircuitPython' -copyright = f'2014-{current_date.tm_year}, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)' +project = "Adafruit CircuitPython" +copyright = f"2014-{current_date.tm_year}, MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)" # These are overwritten on ReadTheDocs. # The version info for the project you're documenting, acts as replacement for @@ -145,15 +155,11 @@ def autoapi_prepare_jinja_env(jinja_env): final_version = "" git_describe = subprocess.run( - [tools_describe], - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - encoding="utf-8" + ["python", "py/version.py"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding="utf-8" ) if git_describe.returncode == 0: git_version = re.search( - r"^\d(?:\.\d){0,2}(?:\-(?:alpha|beta|rc)\.\d+){0,1}", - str(git_describe.stdout) + r"^\d(?:\.\d){0,2}(?:\-(?:alpha|beta|rc)\.\d+){0,1}", str(git_describe.stdout) ) if git_version: final_version = git_version[0] @@ -164,107 +170,58 @@ def autoapi_prepare_jinja_env(jinja_env): # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ["**/build*", - ".git", - ".github", - ".env", - ".venv", - ".direnv", - ".devcontainer/Readme.md", - "circuitpython-stubs", - "data", - "docs/autoapi", - "docs/README.md", - "drivers", - "examples", - "extmod", - "frozen", - "lib", - "main.c", - "mpy-cross", - "ports/*/*.c", - "ports/*/*.h", - "ports/*/boards", - "ports/*/common-hal", - "ports/*/supervisor", - "ports/atmel-samd/asf4", - "ports/atmel-samd/asf4_conf", - "ports/atmel-samd/external_flash", - "ports/atmel-samd/freetouch", - "ports/atmel-samd/peripherals", - "ports/atmel-samd/QTouch", - "ports/atmel-samd/tools", - "ports/broadcom/firmware", - "ports/broadcom/peripherals", - "ports/cxd56/mkspk", - "ports/cxd56/spresense-exported-sdk", - "ports/espressif/certificates", - "ports/espressif/esp-idf", - "ports/espressif/esp-camera", - "ports/espressif/esp-protocols", - "ports/espressif/.idf_tools", - "ports/espressif/peripherals", - "ports/litex/hw", - "ports/minimal", - "ports/mimxrt10xx/peripherals", - "ports/mimxrt10xx/sdk", - "ports/nordic/device", - "ports/nordic/bluetooth", - "ports/nordic/modules", - "ports/nordic/nrfx", - "ports/nordic/peripherals", - "ports/nordic/usb", - "ports/raspberrypi/sdk", - "ports/raspberrypi/lib", - "ports/silabs/gecko_sdk", - "ports/silabs/tools", - "ports/stm/st_driver", - "ports/stm/packages", - "ports/stm/peripherals", - "ports/stm/ref", - "py", - "shared/*", - "shared-bindings/util.*", - "shared-module", - "supervisor", - "tests", - "test-stubs", - "tools", - "circuitpython-stubs/README.rst"] +include_patterns = [ + # Top directory documentation + "*.rst", + "*.md", + # Docs inherited from microypython (but not templates or README.md, see below) + "docs/**", + # Module documentation + "shared-bindings/**", + "ports/*/bindings/**", + # Port READMEs in various formats + "ports/*/README*", +] +exclude_patterns = [ + "docs/autoapi/templates/**", + "docs/README.md", + "AGENTS.md", + "**/AGENTS.md", +] # The reST default role (used for this markup: `text`) to use for all # documents. -default_role = 'any' +default_role = "any" # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # Global include files. Sphinx docs suggest using rst_epilog in preference # of rst_prolog, so we follow. Absolute paths below mean "from the base @@ -276,138 +233,141 @@ def autoapi_prepare_jinja_env(jinja_env): # -- Options for HTML output ---------------------------------------------- import sphinx_rtd_theme -html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.'] + +html_theme = "sphinx_rtd_theme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = ['.'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = '../../logo/trans-logo.png' +# html_logo = '../../logo/trans-logo.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = 'docs/static/favicon.ico' +html_favicon = "docs/static/favicon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['docs/static'] +html_static_path = ["docs/static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -html_last_updated_fmt = '%d %b %Y' +html_last_updated_fmt = "%d %b %Y" # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {"index": "topindex.html"} +# html_additional_pages = {"index": "topindex.html"} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'CircuitPythondoc' +htmlhelp_basename = "CircuitPythondoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -# Include 3 levels of headers in PDF ToC -'preamble': r''' + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Include 3 levels of headers in PDF ToC + "preamble": r""" \setcounter{tocdepth}{2} \hbadness=99999 \hfuzz=20pt \usepackage{pdflscape} -''', +""", } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ("docs/pdf", 'CircuitPython.tex', 'CircuitPython Documentation', - 'CircuitPython Contributors', 'manual'), - # Uncomment this if you want to build a PDF of the board -> module support matrix. - # ("shared-bindings/support_matrix", 'SupportMatrix.tex', 'Board Support Matrix', - # 'CircuitPython Contributors', 'manual'), + ( + "docs/pdf", + "CircuitPython.tex", + "CircuitPython Documentation", + "CircuitPython Contributors", + "manual", + ), + # Uncomment this if you want to build a PDF of the board -> module support matrix. + # ("shared-bindings/support_matrix", 'SupportMatrix.tex', 'Board Support Matrix', + # 'CircuitPython Contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- @@ -415,12 +375,11 @@ def autoapi_prepare_jinja_env(jinja_env): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'CircuitPython', 'CircuitPython Documentation', - ['CircuitPython contributors'], 1), + ("index", "CircuitPython", "CircuitPython Documentation", ["CircuitPython contributors"], 1), ] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -429,29 +388,40 @@ def autoapi_prepare_jinja_env(jinja_env): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'CircuitPython', 'CircuitPython Documentation', - 'CircuitPython contributors', 'CircuitPython', 'Python for Microcontrollers.', - 'Miscellaneous'), + ( + master_doc, + "CircuitPython", + "CircuitPython Documentation", + "CircuitPython contributors", + "CircuitPython", + "Python for Microcontrollers.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {"python": ('https://docs.python.org/3/', None), - "register": ('https://circuitpython.readthedocs.io/projects/register/en/latest/', None), - "mcp2515": ('https://circuitpython.readthedocs.io/projects/mcp2515/en/latest/', None), - "typing": ('https://circuitpython.readthedocs.io/projects/adafruit-circuitpython-typing/en/latest/', None)} +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "register": ("https://circuitpython.readthedocs.io/projects/register/en/latest/", None), + "mcp2515": ("https://circuitpython.readthedocs.io/projects/mcp2515/en/latest/", None), + "typing": ( + "https://circuitpython.readthedocs.io/projects/adafruit-circuitpython-typing/en/latest/", + None, + ), +} # Adapted from sphinxcontrib-redirects from sphinx.builders import html as builders @@ -469,20 +439,21 @@ def generate_redirects(app): return if not isinstance(app.builder, builders.StandaloneHTMLBuilder): - logging.warn("The 'sphinxcontib-redirects' plugin is only supported " - "by the 'html' builder and subclasses. Skipping...") - logging.warn(f"Builder is {app.builder.name} ({type(app.builder)})") + logging.warning( + "The 'sphinxcontib-redirects' plugin is only supported " + "by the 'html' builder and subclasses. Skipping..." + ) + logging.warning(f"Builder is {app.builder.name} ({type(app.builder)})") return with open(path) as redirects: for line in redirects.readlines(): - from_path, to_path = line.rstrip().split(' ') + from_path, to_path = line.rstrip().split(" ") logging.debug("Redirecting '%s' to '%s'" % (from_path, to_path)) from_path = os.path.splitext(from_path)[0] + ".html" - to_path_prefix = '..%s' % os.path.sep * ( - len(from_path.split(os.path.sep)) - 1) + to_path_prefix = "..%s" % os.path.sep * (len(from_path.split(os.path.sep)) - 1) to_path = to_path_prefix + to_path redirected_filename = os.path.join(app.builder.outdir, from_path) @@ -490,8 +461,9 @@ def generate_redirects(app): if not os.path.exists(redirected_directory): os.makedirs(redirected_directory) - with open(redirected_filename, 'w') as f: - f.write(TEMPLATE % urllib.parse.quote(to_path, '#/')) + with open(redirected_filename, "w") as f: + f.write(TEMPLATE % urllib.parse.quote(to_path, "#/")) + def adafruit_typing_workaround(app, env, node, contnode): # Sphinx marks a requesting node that uses circuitpython-typing @@ -547,7 +519,7 @@ def setup(app): app.add_css_file("customstyle.css") app.add_css_file("filter.css") app.add_js_file("filter.js") - app.add_config_value('redirects_file', 'redirects', 'env') - app.connect('builder-inited', generate_redirects) - app.connect('missing-reference', adafruit_typing_workaround) + app.add_config_value("redirects_file", "redirects", "env") + app.connect("builder-inited", generate_redirects) + app.connect("missing-reference", adafruit_typing_workaround) app.add_transform(CoreModuleTransform) diff --git a/data/nvm.toml b/data/nvm.toml index 6b678f15e378e..8bca037b052a4 160000 --- a/data/nvm.toml +++ b/data/nvm.toml @@ -1 +1 @@ -Subproject commit 6b678f15e378edce820f2ffdef3286b3e55449e7 +Subproject commit 8bca037b052a4a4dc46a56a25a1b802652ee3f47 diff --git a/devices/ble_hci/common-hal/_bleio/Adapter.c b/devices/ble_hci/common-hal/_bleio/Adapter.c index fac7eb9f5fddf..03ec7a5588f11 100644 --- a/devices/ble_hci/common-hal/_bleio/Adapter.c +++ b/devices/ble_hci/common-hal/_bleio/Adapter.c @@ -29,7 +29,7 @@ #include "shared-bindings/_bleio/ScanEntry.h" #include "shared-bindings/time/__init__.h" -#if CIRCUITPY_OS_GETENV +#if CIRCUITPY_SETTINGS_TOML #include "shared-bindings/os/__init__.h" #endif @@ -261,7 +261,7 @@ static void _adapter_set_name(bleio_adapter_obj_t *self, mp_obj_str_t *name_obj) static void bleio_adapter_hci_init(bleio_adapter_obj_t *self) { mp_int_t name_len = 0; - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML mp_obj_t name = common_hal_os_getenv("CIRCUITPY_BLE_NAME", mp_const_none); if (name != mp_const_none) { mp_arg_validate_type_string(name, MP_QSTR_CIRCUITPY_BLE_NAME); diff --git a/devices/ble_hci/common-hal/_bleio/Characteristic.c b/devices/ble_hci/common-hal/_bleio/Characteristic.c index f142239ded22f..49b66d38e7256 100644 --- a/devices/ble_hci/common-hal/_bleio/Characteristic.c +++ b/devices/ble_hci/common-hal/_bleio/Characteristic.c @@ -50,6 +50,17 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->handle == BLE_GATT_HANDLE_INVALID; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + self->handle = BLE_GATT_HANDLE_INVALID; +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); } @@ -169,7 +180,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? CCCD_NOTIFY : 0) | diff --git a/devices/ble_hci/common-hal/_bleio/Connection.h b/devices/ble_hci/common-hal/_bleio/Connection.h index 04edb104ddcb2..02a000501bfde 100644 --- a/devices/ble_hci/common-hal/_bleio/Connection.h +++ b/devices/ble_hci/common-hal/_bleio/Connection.h @@ -61,6 +61,7 @@ typedef struct { uint8_t disconnect_reason; } bleio_connection_obj_t; +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/devices/ble_hci/common-hal/_bleio/PacketBuffer.c b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c index 97626205a62ff..771a1509f3924 100644 --- a/devices/ble_hci/common-hal/_bleio/PacketBuffer.c +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.c @@ -247,3 +247,7 @@ void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { ringbuf_deinit(&self->ringbuf); } } + +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self) { + return !common_hal_bleio_packet_buffer_deinited(self) && self->conn_handle != BLE_CONN_HANDLE_INVALID; +} diff --git a/devices/ble_hci/common-hal/_bleio/PacketBuffer.h b/devices/ble_hci/common-hal/_bleio/PacketBuffer.h index 563f365d21b01..4e001339fe323 100644 --- a/devices/ble_hci/common-hal/_bleio/PacketBuffer.h +++ b/devices/ble_hci/common-hal/_bleio/PacketBuffer.h @@ -28,4 +28,7 @@ typedef struct { bool packet_queued; } bleio_packet_buffer_obj_t; +// Unused, but needed for _common_hal_bleio_packet_buffer_construct() +typedef void *ble_event_handler_t; + void bleio_packet_buffer_update(bleio_packet_buffer_obj_t *self, mp_buffer_info_t *bufinfo); diff --git a/devices/ble_hci/common-hal/_bleio/__init__.c b/devices/ble_hci/common-hal/_bleio/__init__.c index 9663e70699807..f9fdbc50f6489 100644 --- a/devices/ble_hci/common-hal/_bleio/__init__.c +++ b/devices/ble_hci/common-hal/_bleio/__init__.c @@ -40,13 +40,13 @@ bool vm_used_ble; void common_hal_bleio_init(void) { } -void bleio_user_reset() { +void bleio_user_reset(void) { // HCI doesn't support the BLE workflow so just do a full reset. bleio_reset(); } // Turn off BLE on a reset or reload. -void bleio_reset() { +void bleio_reset(void) { // Create a UUID object for all CCCD's. cccd_uuid.base.type = &bleio_uuid_type; common_hal_bleio_uuid_construct(&cccd_uuid, BLE_UUID_CCCD, NULL); @@ -84,7 +84,7 @@ bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) { return &common_hal_bleio_adapter_obj; } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } diff --git a/docs/README.md b/docs/README.md index 1ad4ca802e926..cddc45b03b311 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -Adafruit's CircuitPython Documentation +Adafruit CircuitPython Documentation ========================= The latest documentation can be found at: diff --git a/docs/environment.rst b/docs/environment.rst index d29cb2a618710..36404eb81f928 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -53,8 +53,13 @@ Details of the toml language subset CircuitPython behavior ---------------------- -CircuitPython will also read the environment to configure its behavior. Other -keys are ignored by CircuitPython. Here are the keys it uses: +CircuitPython will also read the environment to configure its behavior. Some keys are read at +startup once and others are read on reload (ctrl-D in the REPL). If a reload doesn't change things, +then try a reset (a power cycle or pressing the reset button). Other keys are ignored by CircuitPython. +Here are the keys it uses: + +Core CircuitPython keys +^^^^^^^^^^^^^^^^^^^^^^^ CIRCUITPY_BLE_NAME ~~~~~~~~~~~~~~~~~~ @@ -94,3 +99,110 @@ Wi-Fi password used to auto connect to CIRCUITPY_WIFI_SSID. CIRCUITPY_WIFI_SSID ~~~~~~~~~~~~~~~~~~~ Wi-Fi SSID to auto-connect to even if user code is not running. + +Additional board specific keys +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +CIRCUITPY_DISPLAY_WIDTH (Sunton, MaTouch) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Selects the correct screen resolution (1024x600 or 800x640) for the particular board variant. +If the CIRCUITPY_DISPLAY_WIDTH parameter is set to a value of 1024 the display is initialized +during power up at 1024x600 otherwise the display will be initialized at a resolution +of 800x480. + +`MaTouch ESP32-S3 Parallel TFT with Touch 7“ `_ +`Sunton ESP32-2432S028 `_ +`Sunton ESP32-2432S024C `_ + +CIRCUITPY_DISPLAY_ROTATION +~~~~~~~~~~~~~~~~~~~~~~~~~~ +Selects the correct screen rotation (0, 90, 180 or 270) for the particular board variant. +If the CIRCUITPY_DISPLAY_ROTATION parameter is set the display will be initialized +during power up with the selected rotation, otherwise the display will be initialized with +a rotation of 0. Attempting to initialize the screen with a rotation other than 0, +90, 180 or 270 is not supported and will result in an unexpected screen rotation. + +`Sunton ESP32-8048S050 `_ +`Adafruit Feather RP2350 `_ +`Adafruit Metro RP2350 `_ + +CIRCUITPY_DISPLAY_FREQUENCY +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allows the entry of a display frequency used during the "dotclock" framebuffer construction. +If a valid frequency is not defined the board will initialize the framebuffer with a +frequency of 12500000hz (12.5Mhz). The value should be entered as an integer in hertz +i.e. CIRCUITPY_DISPLAY_FREQUENCY=16000000 will override the default value with a 16Mhz +display frequency. + +`Sunton ESP32-8048S050 `_ + + +CIRCUITPY_PICODVI_ENABLE +~~~~~~~~~~~~~~~~~~~~~~~~ +Whether to configure the display at board initialization time, one of the following: + +.. code-block:: + + CIRCUITPY_PICODVI_ENABLE="detect" # when EDID EEPROM is detected (default) + CIRCUITPY_PICODVI_ENABLE="always" + CIRCUITPY_PICODVI_ENABLE="never" + +A display configured in this manner is available at ``supervisor.runtime.display`` +until it is released by ``displayio.release_displays()``. It does not appear at +``board.DISPLAY``. + +`Adafruit Feather RP2350 `_ +`Adafruit Metro RP2350 `_ + +CIRCUITPY_DISPLAY_WIDTH, CIRCUITPY_DISPLAY_HEIGHT, and CIRCUITPY_DISPLAY_COLOR_DEPTH (RP2350 boards with DVI or HSTX connector) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Selects the desired resolution and color depth. + +Supported resolutions are: + * 640x480 with color depth 1, 2, 4 or 8 bits per pixel + * 320x240 with pixel doubling and color depth 8, 16, or 32 bits per pixel + * 360x200 with pixel doubling and color depth 8, 16, or 32 bits per pixel + +See :py:class:`picodvi.Framebuffer` for more details. + +The default value, if unspecified, is 360x200 16 bits per pixel if the connected +display is 1920x1080 or a multiple of it, otherwise 320x240 with 16 bits per pixel. + +If height is unspecified, it is set from the width. For example, a width of 640 +implies a height of 480. + +Example: Configure the display to 640x480 black and white (1 bit per pixel): + +.. code-block:: + + CIRCUITPY_DISPLAY_WIDTH=640 + CIRCUITPY_DISPLAY_COLOR_DEPTH=1 + +`Adafruit Feather RP2350 `_ +`Adafruit Metro RP2350 `_ + +CIRCUITPY_TERMINAL_SCALE +~~~~~~~~~~~~~~~~~~~~~~~~ +Allows the entry of a display scaling factor used during the terminalio console construction. +The entered scaling factor only affects the terminalio console and has no impact on +the UART, Web Workflow, BLE Workflow, etc consoles. + +This feature is not enabled on boards that the CIRCUITPY_SETTINGS_TOML (or CIRCUITPY_FULL_BUILD) +flag has been set to 0. Currently this is primarily boards with limited flash including some +of the Atmel_samd boards based on the SAMD21/M0 microprocessor. + +CIRCUITPY_TERMINAL_FONT +~~~~~~~~~~~~~~~~~~~~~~~ +Specifies a custom font file path to use for the terminalio console instead of the default +``/fonts/terminal.lvfontbin``. This allows users to create and use custom fonts for the +CircuitPython console. + +This feature requires both CIRCUITPY_SETTINGS_TOML and CIRCUITPY_LVFONTIO to be enabled. + +Example: + +.. code-block:: + + CIRCUITPY_TERMINAL_FONT="/fonts/myfont.lvfontbin" + +`boards that the terminalio core module is available on `_ diff --git a/docs/library/array.rst b/docs/library/array.rst index a7a3b5952e150..63b86a806c3d3 100644 --- a/docs/library/array.rst +++ b/docs/library/array.rst @@ -19,6 +19,10 @@ Classes array are given by an `iterable`. If it is not provided, an empty array is created. + In addition to the methods below, array objects also implement the buffer + protocol. This means the contents of the entire array can be accessed as raw + bytes via a `memoryview` or other interfaces which use this protocol. + .. method:: append(val) Append new element ``val`` to the end of array, growing it. diff --git a/docs/library/binascii.rst b/docs/library/binascii.rst index 1eba46652d7fc..0797692b02030 100644 --- a/docs/library/binascii.rst +++ b/docs/library/binascii.rst @@ -39,6 +39,6 @@ Functions .. function:: crc32(data, value=0, /) - Compute CRC-32, the 32-bit checksum of the bytes in *data* starting with an + Compute CRC-32, the 32-bit checksum of the bytes in ``data`` starting with an initial CRC of *value*. The default initial CRC is 0. The algorithm is consistent with the ZIP file checksum. diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst index 6003c23fb131b..148c1513f3d4e 100644 --- a/docs/library/builtins.rst +++ b/docs/library/builtins.rst @@ -31,6 +31,8 @@ Functions and types .. class:: bytearray() + |see_cpython| `python:bytearray`. + .. class:: bytes() |see_cpython| `python:bytes`. @@ -86,15 +88,9 @@ Functions and types .. class:: int() - .. classmethod:: from_bytes(bytes, byteorder) - - In CircuitPython, the ``byteorder`` parameter must be positional (this is - compatible with CPython). - - .. method:: to_bytes(size, byteorder) + .. classmethod:: from_bytes(bytes, byteorder="big", *, signed=False) - In CircuitPython, the ``byteorder`` parameter must be positional (this is - compatible with CPython). + .. method:: to_bytes(length=1, byteorder="big", *, signed=False) .. function:: isinstance() diff --git a/docs/library/collections.rst b/docs/library/collections.rst index e400158c99cfd..c3ec763d20e1b 100644 --- a/docs/library/collections.rst +++ b/docs/library/collections.rst @@ -31,35 +31,37 @@ Classes - *flag* is optional and can be set to 1 to check for overflow when adding items. If the deque is full and overflow checking is enabled, - an IndexError will be raised when adding items. + an ``IndexError`` will be raised when adding items. Deque objects have the following methods: .. method:: deque.append(x) Add *x* to the right side of the deque. - Raises IndexError if overflow checking is enabled and there is no more room left. + Raises ``IndexError`` if overflow checking is enabled and there is + no more room in the queue. .. method:: deque.appendleft(x) Add *x* to the left side of the deque. - Raises IndexError if overflow checking is enabled and there is no more room left. + Raises ``IndexError`` if overflow checking is enabled and there is + no more room in the queue. .. method:: deque.pop() Remove and return an item from the right side of the deque. - Raises IndexError if no items are present. + Raises ``IndexError`` if no items are present. .. method:: deque.popleft() Remove and return an item from the left side of the deque. - Raises IndexError if no items are present. + Raises ``IndexError`` if no items are present. .. method:: deque.extend(iterable) - Extend the right side of the deque by appending items from the *iterable* argument. + Extend the right side of the deque by appending items from the ``iterable`` argument. Raises IndexError if overflow checking is enabled and there is no more room left - for all of the items in *iterable*. + for all of the items in ``iterable``. In addition to the above, deques support iteration, ``bool``, ``len(d)``, ``reversed(d)``, membership testing with the ``in`` operator, and subscript references like ``d[0]``. @@ -107,3 +109,19 @@ Classes a 2 w 5 b 3 + + .. method:: OrderedDict.popitem() + + Remove and return a (key, value) pair from the dictionary. + Pairs are returned in LIFO order. + + .. admonition:: Difference to CPython + :class: attention + + ``OrderedDict.popitem()`` does not support the ``last=False`` argument and + will always remove and return the last item if present. + + A workaround for this is to use ``pop()`` to remove the first item:: + + first_key = next(iter(d)) + d.pop(first_key) diff --git a/docs/library/ctypes.rst b/docs/library/ctypes.rst deleted file mode 100644 index 803ddacdcef5e..0000000000000 --- a/docs/library/ctypes.rst +++ /dev/null @@ -1,325 +0,0 @@ -:mod:`uctypes` -- access binary data in a structured way -======================================================== - -.. module:: uctypes - :synopsis: access binary data in a structured way - -This module implements "foreign data interface" for MicroPython. The idea -behind it is similar to CPython's ``ctypes`` modules, but the actual API is -different, streamlined and optimized for small size. The basic idea of the -module is to define data structure layout with about the same power as the -C language allows, and then access it using familiar dot-syntax to reference -sub-fields. - -.. warning:: - - ``uctypes`` module allows access to arbitrary memory addresses of the - machine (including I/O and control registers). Uncareful usage of it - may lead to crashes, data loss, and even hardware malfunction. - -.. seealso:: - - Module :mod:`struct` - Standard Python way to access binary data structures (doesn't scale - well to large and complex structures). - -Usage examples:: - - import uctypes - - # Example 1: Subset of ELF file header - # https://wikipedia.org/wiki/Executable_and_Linkable_Format#File_header - ELF_HEADER = { - "EI_MAG": (0x0 | uctypes.ARRAY, 4 | uctypes.UINT8), - "EI_DATA": 0x5 | uctypes.UINT8, - "e_machine": 0x12 | uctypes.UINT16, - } - - # "f" is an ELF file opened in binary mode - buf = f.read(uctypes.sizeof(ELF_HEADER, uctypes.LITTLE_ENDIAN)) - header = uctypes.struct(uctypes.addressof(buf), ELF_HEADER, uctypes.LITTLE_ENDIAN) - assert header.EI_MAG == b"\x7fELF" - assert header.EI_DATA == 1, "Oops, wrong endianness. Could retry with uctypes.BIG_ENDIAN." - print("machine:", hex(header.e_machine)) - - - # Example 2: In-memory data structure, with pointers - COORD = { - "x": 0 | uctypes.FLOAT32, - "y": 4 | uctypes.FLOAT32, - } - - STRUCT1 = { - "data1": 0 | uctypes.UINT8, - "data2": 4 | uctypes.UINT32, - "ptr": (8 | uctypes.PTR, COORD), - } - - # Suppose you have address of a structure of type STRUCT1 in "addr" - # uctypes.NATIVE is optional (used by default) - struct1 = uctypes.struct(addr, STRUCT1, uctypes.NATIVE) - print("x:", struct1.ptr[0].x) - - - # Example 3: Access to CPU registers. Subset of STM32F4xx WWDG block - WWDG_LAYOUT = { - "WWDG_CR": (0, { - # BFUINT32 here means size of the WWDG_CR register - "WDGA": 7 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, - "T": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, - }), - "WWDG_CFR": (4, { - "EWI": 9 << uctypes.BF_POS | 1 << uctypes.BF_LEN | uctypes.BFUINT32, - "WDGTB": 7 << uctypes.BF_POS | 2 << uctypes.BF_LEN | uctypes.BFUINT32, - "W": 0 << uctypes.BF_POS | 7 << uctypes.BF_LEN | uctypes.BFUINT32, - }), - } - - WWDG = uctypes.struct(0x40002c00, WWDG_LAYOUT) - - WWDG.WWDG_CFR.WDGTB = 0b10 - WWDG.WWDG_CR.WDGA = 1 - print("Current counter:", WWDG.WWDG_CR.T) - -Defining structure layout -------------------------- - -Structure layout is defined by a "descriptor" - a Python dictionary which -encodes field names as keys and other properties required to access them as -associated values:: - - { - "field1": , - "field2": , - ... - } - -Currently, ``uctypes`` requires explicit specification of offsets for each -field. Offset are given in bytes from the structure start. - -Following are encoding examples for various field types: - -* Scalar types:: - - "field_name": offset | uctypes.UINT32 - - in other words, the value is a scalar type identifier ORed with a field offset - (in bytes) from the start of the structure. - -* Recursive structures:: - - "sub": (offset, { - "b0": 0 | uctypes.UINT8, - "b1": 1 | uctypes.UINT8, - }) - - i.e. value is a 2-tuple, first element of which is an offset, and second is - a structure descriptor dictionary (note: offsets in recursive descriptors - are relative to the structure it defines). Of course, recursive structures - can be specified not just by a literal dictionary, but by referring to a - structure descriptor dictionary (defined earlier) by name. - -* Arrays of primitive types:: - - "arr": (offset | uctypes.ARRAY, size | uctypes.UINT8), - - i.e. value is a 2-tuple, first element of which is ARRAY flag ORed - with offset, and second is scalar element type ORed number of elements - in the array. - -* Arrays of aggregate types:: - - "arr2": (offset | uctypes.ARRAY, size, {"b": 0 | uctypes.UINT8}), - - i.e. value is a 3-tuple, first element of which is ARRAY flag ORed - with offset, second is a number of elements in the array, and third is - a descriptor of element type. - -* Pointer to a primitive type:: - - "ptr": (offset | uctypes.PTR, uctypes.UINT8), - - i.e. value is a 2-tuple, first element of which is PTR flag ORed - with offset, and second is a scalar element type. - -* Pointer to an aggregate type:: - - "ptr2": (offset | uctypes.PTR, {"b": 0 | uctypes.UINT8}), - - i.e. value is a 2-tuple, first element of which is PTR flag ORed - with offset, second is a descriptor of type pointed to. - -* Bitfields:: - - "bitf0": offset | uctypes.BFUINT16 | lsbit << uctypes.BF_POS | bitsize << uctypes.BF_LEN, - - i.e. value is a type of scalar value containing given bitfield (typenames are - similar to scalar types, but prefixes with ``BF``), ORed with offset for - scalar value containing the bitfield, and further ORed with values for - bit position and bit length of the bitfield within the scalar value, shifted by - BF_POS and BF_LEN bits, respectively. A bitfield position is counted - from the least significant bit of the scalar (having position of 0), and - is the number of right-most bit of a field (in other words, it's a number - of bits a scalar needs to be shifted right to extract the bitfield). - - In the example above, first a UINT16 value will be extracted at offset 0 - (this detail may be important when accessing hardware registers, where - particular access size and alignment are required), and then bitfield - whose rightmost bit is *lsbit* bit of this UINT16, and length - is *bitsize* bits, will be extracted. For example, if *lsbit* is 0 and - *bitsize* is 8, then effectively it will access least-significant byte - of UINT16. - - Note that bitfield operations are independent of target byte endianness, - in particular, example above will access least-significant byte of UINT16 - in both little- and big-endian structures. But it depends on the least - significant bit being numbered 0. Some targets may use different - numbering in their native ABI, but ``uctypes`` always uses the normalized - numbering described above. - -Module contents ---------------- - -.. class:: struct(addr, descriptor, layout_type=NATIVE, /) - - Instantiate a "foreign data structure" object based on structure address in - memory, descriptor (encoded as a dictionary), and layout type (see below). - -.. data:: LITTLE_ENDIAN - - Layout type for a little-endian packed structure. (Packed means that every - field occupies exactly as many bytes as defined in the descriptor, i.e. - the alignment is 1). - -.. data:: BIG_ENDIAN - - Layout type for a big-endian packed structure. - -.. data:: NATIVE - - Layout type for a native structure - with data endianness and alignment - conforming to the ABI of the system on which MicroPython runs. - -.. function:: sizeof(struct, layout_type=NATIVE, /) - - Return size of data structure in bytes. The *struct* argument can be - either a structure class or a specific instantiated structure object - (or its aggregate field). - -.. function:: addressof(obj) - - Return address of an object. Argument should be bytes, bytearray or - other object supporting buffer protocol (and address of this buffer - is what actually returned). - -.. function:: bytes_at(addr, size) - - Capture memory at the given address and size as bytes object. As bytes - object is immutable, memory is actually duplicated and copied into - bytes object, so if memory contents change later, created object - retains original value. - -.. function:: bytearray_at(addr, size) - - Capture memory at the given address and size as bytearray object. - Unlike bytes_at() function above, memory is captured by reference, - so it can be both written too, and you will access current value - at the given memory address. - -.. data:: UINT8 - INT8 - UINT16 - INT16 - UINT32 - INT32 - UINT64 - INT64 - - Integer types for structure descriptors. Constants for 8, 16, 32, - and 64 bit types are provided, both signed and unsigned. - -.. data:: FLOAT32 - FLOAT64 - - Floating-point types for structure descriptors. - -.. data:: VOID - - ``VOID`` is an alias for ``UINT8``, and is provided to conveniently define - C's void pointers: ``(uctypes.PTR, uctypes.VOID)``. - -.. data:: PTR - ARRAY - - Type constants for pointers and arrays. Note that there is no explicit - constant for structures, it's implicit: an aggregate type without ``PTR`` - or ``ARRAY`` flags is a structure. - -Structure descriptors and instantiating structure objects ---------------------------------------------------------- - -Given a structure descriptor dictionary and its layout type, you can -instantiate a specific structure instance at a given memory address -using :class:`uctypes.struct()` constructor. Memory address usually comes from -following sources: - -* Predefined address, when accessing hardware registers on a baremetal - system. Lookup these addresses in datasheet for a particular MCU/SoC. -* As a return value from a call to some FFI (Foreign Function Interface) - function. -* From `uctypes.addressof()`, when you want to pass arguments to an FFI - function, or alternatively, to access some data for I/O (for example, - data read from a file or network socket). - -Structure objects ------------------ - -Structure objects allow accessing individual fields using standard dot -notation: ``my_struct.substruct1.field1``. If a field is of scalar type, -getting it will produce a primitive value (Python integer or float) -corresponding to the value contained in a field. A scalar field can also -be assigned to. - -If a field is an array, its individual elements can be accessed with -the standard subscript operator ``[]`` - both read and assigned to. - -If a field is a pointer, it can be dereferenced using ``[0]`` syntax -(corresponding to C ``*`` operator, though ``[0]`` works in C too). -Subscripting a pointer with other integer values but 0 are also supported, -with the same semantics as in C. - -Summing up, accessing structure fields generally follows the C syntax, -except for pointer dereference, when you need to use ``[0]`` operator -instead of ``*``. - -Limitations ------------ - -1. Accessing non-scalar fields leads to allocation of intermediate objects -to represent them. This means that special care should be taken to -layout a structure which needs to be accessed when memory allocation -is disabled (e.g. from an interrupt). The recommendations are: - -* Avoid accessing nested structures. For example, instead of - ``mcu_registers.peripheral_a.register1``, define separate layout - descriptors for each peripheral, to be accessed as - ``peripheral_a.register1``. Or just cache a particular peripheral: - ``peripheral_a = mcu_registers.peripheral_a``. If a register - consists of multiple bitfields, you would need to cache references - to a particular register: ``reg_a = mcu_registers.peripheral_a.reg_a``. -* Avoid other non-scalar data, like arrays. For example, instead of - ``peripheral_a.register[0]`` use ``peripheral_a.register0``. Again, - an alternative is to cache intermediate values, e.g. - ``register0 = peripheral_a.register[0]``. - -2. Range of offsets supported by the ``uctypes`` module is limited. -The exact range supported is considered an implementation detail, -and the general suggestion is to split structure definitions to -cover from a few kilobytes to a few dozen of kilobytes maximum. -In most cases, this is a natural situation anyway, e.g. it doesn't make -sense to define all registers of an MCU (spread over 32-bit address -space) in one structure, but rather a peripheral block by peripheral -block. In some extreme cases, you may need to split a structure in -several parts artificially (e.g. if accessing native data structure -with multi-megabyte array in the middle, though that would be a very -synthetic case). diff --git a/docs/library/errno.rst b/docs/library/errno.rst index 61970291df57a..10ecd4d2c791d 100644 --- a/docs/library/errno.rst +++ b/docs/library/errno.rst @@ -7,7 +7,7 @@ |see_cpython_module| :mod:`python:errno`. This module provides access to symbolic error codes for `OSError` exception. -The codes available may vary per CircuitPython build. +Some codes are not available on the smallest CircuitPython builds, such as SAMD21, for space reasons. Constants --------- diff --git a/docs/library/index.rst b/docs/library/index.rst index 3a06bc2cee323..4e763e8a27e00 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -17,7 +17,7 @@ limited flash memory: ``binascii``, ``errno``, ``json``, ``re``. These libraries are not currently enabled in any CircuitPython build, but may be in the future: -``ctypes``, ``platform`` +``platform`` .. toctree:: :maxdepth: 1 @@ -33,9 +33,8 @@ These libraries are not currently enabled in any CircuitPython build, but may be json.rst platform.rst re.rst - sys.rst - ctypes.rst select.rst + sys.rst Omitted ``string`` functions ---------------------------- @@ -55,4 +54,4 @@ the following libraries. .. toctree:: :maxdepth: 1 - micropython.rst + ../../shared-bindings/micropython/index.rst diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst deleted file mode 100644 index 166192de3a38e..0000000000000 --- a/docs/library/micropython.rst +++ /dev/null @@ -1,28 +0,0 @@ -:mod:`micropython` -- MicroPython extensions and internals -========================================================== - -.. module:: micropython - :synopsis: access and control MicroPython internals - -Functions ---------- - -.. function:: const(expr) - - Used to declare that the expression is a constant so that the compiler can - optimise it. The use of this function should be as follows:: - - from micropython import const - - CONST_X = const(123) - CONST_Y = const(2 * CONST_X + 1) - - Constants declared this way are still accessible as global variables from - outside the module they are declared in. On the other hand, if a constant - begins with an underscore then it is hidden, it is not available as a global - variable, and does not take up any memory during execution. - - This `const` function is recognised directly by the MicroPython parser and is - provided as part of the :mod:`micropython` module mainly so that scripts can be - written which run under both CPython and MicroPython, by following the above - pattern. diff --git a/docs/library/platform.rst b/docs/library/platform.rst index c091477d84cb1..c19ef0f5df524 100644 --- a/docs/library/platform.rst +++ b/docs/library/platform.rst @@ -36,3 +36,11 @@ Functions Returns a tuple of strings *(lib, version)*, where *lib* is the name of the libc that MicroPython is linked to, and *version* the corresponding version of this libc. + +.. function:: processor() + + Returns a string with a detailed name of the processor, if one is available. + If no name for the processor is known, it will return an empty string + instead. + + This is currently available only on RISC-V targets (both 32 and 64 bits). diff --git a/docs/library/re.rst b/docs/library/re.rst index 19b15d2d2c299..b8aeefd90cfa4 100644 --- a/docs/library/re.rst +++ b/docs/library/re.rst @@ -154,8 +154,8 @@ Regex objects Compiled regular expression. Instances of this class are created using `re.compile()`. -.. method:: regex.match(string) - regex.search(string) +.. method:: regex.match(string, [pos, [endpos]]) + regex.search(string, [pos, [endpos]]) regex.sub(replace, string, count=0, flags=0, /) Similar to the module-level functions :meth:`match`, :meth:`search` @@ -163,6 +163,16 @@ Compiled regular expression. Instances of this class are created using Using methods is (much) more efficient if the same regex is applied to multiple strings. + The optional second parameter *pos* gives an index in the string where the + search is to start; it defaults to ``0``. This is not completely equivalent + to slicing the string; the ``'^'`` pattern character matches at the real + beginning of the string and at positions just after a newline, but not + necessarily at the index where the search is to start. + + The optional parameter *endpos* limits how far the string will be searched; + it will be as if the string is *endpos* characters long, so only the + characters from *pos* to ``endpos - 1`` will be searched for a match. + .. method:: regex.split(string, max_split=-1, /) Split a *string* using regex. If *max_split* is given, it specifies diff --git a/docs/library/sys.rst b/docs/library/sys.rst index 4e8c889eb0172..c9c687df35936 100644 --- a/docs/library/sys.rst +++ b/docs/library/sys.rst @@ -12,17 +12,9 @@ Functions .. function:: exit(retval=0, /) Terminate current program with a given exit code. Underlyingly, this - function raise as `SystemExit` exception. If an argument is given, its + function raises a `SystemExit` exception. If an argument is given, its value given as an argument to `SystemExit`. -.. function:: print_exception(exc, file=sys.stdout, /) - - This function is being deprecated and will be removed starting in - CircuitPython 10.x, `traceback.print_exception()` should be used instead. - - Print exception with a traceback to a file-like object *file* (or - `sys.stdout` by default). - .. admonition:: Difference to CPython :class: attention @@ -52,6 +44,8 @@ Constants * *version* - tuple (major, minor, micro), e.g. (1, 7, 0) * *_machine* - string describing the underlying machine * *_mpy* - supported mpy file-format version (optional attribute) + * *_build* - string that can help identify the configuration that + MicroPython was built with This object is the recommended way to distinguish CircuitPython from other Python implementations (note that it still may not exist in the very @@ -116,15 +110,15 @@ Constants .. data:: stderr - Standard error ``stream``. + Standard error `stream`. .. data:: stdin - Standard input ``stream``. + Standard input `stream`. .. data:: stdout - Standard output ``stream``. + Standard output `stream`. .. data:: version diff --git a/docs/porting.rst b/docs/porting.rst index f4ed2ab4cc86e..9cb28b7e5d4ac 100644 --- a/docs/porting.rst +++ b/docs/porting.rst @@ -72,6 +72,7 @@ as a natural "TODO" list. An example minimal build list is shown below: CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_I2CTARGET = 0 + CIRCUITPY_SPITARGET = 0 # Requires SPI, PulseIO (stub ok): CIRCUITPY_DISPLAYIO = 0 diff --git a/docs/redirects.txt b/docs/redirects.txt index 1016d0bd70b71..b2d4b5621fb98 100644 --- a/docs/redirects.txt +++ b/docs/redirects.txt @@ -1,4 +1,5 @@ index.rst README.html +docs/library/micropython.rst shared-bindings/micropython shared-bindings//__init__.rst shared-bindings// shared-bindings/_bleio/Adapter.rst shared-bindings/_bleio/#_bleio.Adapter shared-bindings/_bleio/Address.rst shared-bindings/_bleio/#_bleio.Address diff --git a/docs/reference/glossary.rst b/docs/reference/glossary.rst index 9e9330de4ccfe..391dc307d2343 100644 --- a/docs/reference/glossary.rst +++ b/docs/reference/glossary.rst @@ -186,6 +186,13 @@ Glossary Most MicroPython boards make a REPL available over a UART, and this is typically accessible on a host PC via USB. + small integer + MicroPython optimises the internal representation of integers such that + "small" values do not take up space on the heap, and calculations with + them do not require heap allocation. On most 32-bit ports, this + corresponds to values in the interval ``-2**30 <= x < 2**30``, but this + should be considered an implementation detail and not relied upon. + stream Also known as a "file-like object". A Python object which provides sequential read-write access to the underlying data. A stream object diff --git a/docs/rstjinja.py b/docs/rstjinja.py index 7d5fff5c6c357..04c855a1a4049 100644 --- a/docs/rstjinja.py +++ b/docs/rstjinja.py @@ -3,11 +3,13 @@ import re + def render_with_jinja(docname, source): - if re.search('^\s*.. jinja$', source[0], re.M): + if re.search("^\s*.. jinja$", source[0], re.M): return True return False + def rstjinja(app, docname, source): """ Render our pages as a jinja template for fancy templating goodness. @@ -24,18 +26,19 @@ def rstjinja(app, docname, source): print(f"rendering {docname} as jinja templates") if app.builder.format == "html": - rendered = app.builder.templates.render_string( - src, app.config.html_context - ) + rendered = app.builder.templates.render_string(src, app.config.html_context) else: from sphinx.util.template import BaseRenderer + renderer = BaseRenderer() - rendered = renderer.render_string( - src, - app.config.html_context - ) + rendered = renderer.render_string(src, app.config.html_context) source[0] = rendered + def setup(app): app.connect("source-read", rstjinja) + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/docs/shared_bindings_matrix.py b/docs/shared_bindings_matrix.py index 33dfad01e986b..8fbee4beea5b5 100644 --- a/docs/shared_bindings_matrix.py +++ b/docs/shared_bindings_matrix.py @@ -26,11 +26,12 @@ import pathlib import re import subprocess - +import tomllib from concurrent.futures import ThreadPoolExecutor SUPPORTED_PORTS = [ + "analog", "atmel-samd", "broadcom", "cxd56", @@ -42,6 +43,7 @@ "renode", "silabs", "stm", + "zephyr-cp", ] ALIASES_BY_BOARD = { @@ -56,8 +58,7 @@ ALIASES_BRAND_NAMES = { "circuitplayground_express_4h": "Adafruit Circuit Playground Express 4-H", - "circuitplayground_express_digikey_pycon2019": - "Circuit Playground Express Digi-Key PyCon 2019", + "circuitplayground_express_digikey_pycon2019": "Circuit Playground Express Digi-Key PyCon 2019", "edgebadge": "Adafruit EdgeBadge", "pyportal_pynt": "Adafruit PyPortal Pynt", "gemma_m0_pycon2018": "Adafruit Gemma M0 PyCon 2018", @@ -65,6 +66,9 @@ ADDITIONAL_MODULES = { "_asyncio": "MICROPY_PY_ASYNCIO", + "_bleio (native)": "CIRCUITPY_BLEIO_NATIVE", + "_bleio (HCI co-processor)": "CIRCUITPY_BLEIO_HCI", + "_eve": "CIRCUITPY__EVE", "adafruit_bus_device": "CIRCUITPY_BUSDEVICE", "adafruit_pixelbuf": "CIRCUITPY_PIXELBUF", "array": "CIRCUITPY_ARRAY", @@ -80,8 +84,9 @@ "keypad.Keys": "CIRCUITPY_KEYPAD_KEYS", "keypad.ShiftRegisterKeys": "CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS", "keypad_demux.DemuxKeyMatrix": "CIRCUITPY_KEYPAD_DEMUX", - "os.getenv": "CIRCUITPY_OS_GETENV", + "os.getenv": "CIRCUITPY_SETTINGS_TOML", "select": "MICROPY_PY_SELECT_SELECT", + "supervisor.get_setting": "CIRCUITPY_SETTINGS_TOML", "sys": "CIRCUITPY_SYS", "terminalio": "CIRCUITPY_DISPLAYIO", "usb": "CIRCUITPY_PYUSB", @@ -116,8 +121,12 @@ def get_bindings(): bindings_modules = [] for d in get_circuitpython_root_dir().glob("ports/*/bindings"): bindings_modules.extend(module.name for module in d.iterdir() if d.is_dir()) - return shared_bindings_modules + bindings_modules + MODULES_NOT_IN_BINDINGS + \ - list(ADDITIONAL_MODULES.keys()) + return ( + shared_bindings_modules + + bindings_modules + + MODULES_NOT_IN_BINDINGS + + list(ADDITIONAL_MODULES.keys()) + ) def get_board_mapping(): @@ -128,14 +137,21 @@ def get_board_mapping(): boards = {} for port in SUPPORTED_PORTS: board_path = root_dir / "ports" / port / "boards" - for board_path in os.scandir(board_path): + # Zephyr port has vendor specific subdirectories to match zephyr (and + # clean up the boards folder.) + g = "*/*" if port == "zephyr-cp" else "*" + for board_path in board_path.glob(g): if board_path.is_dir(): board_id = board_path.name + if port == "zephyr-cp": + vendor = board_path.parent.name + board_id = f"{vendor}_{board_id}" aliases = ALIASES_BY_BOARD.get(board_path.name, []) boards[board_id] = { "port": port, "download_count": 0, "aliases": aliases, + "directory": board_path, } for alias in aliases: boards[alias] = { @@ -143,6 +159,7 @@ def get_board_mapping(): "download_count": 0, "alias": True, "aliases": [], + "directory": board_path, } return boards @@ -177,16 +194,23 @@ def get_settings_from_makefile(port_dir, board_name): This list must explicitly include any setting queried by tools/ci_set_matrix.py. """ - if os.getenv('NO_BINDINGS_MATRIX'): - return { - 'CIRCUITPY_BUILD_EXTENSIONS': '.bin' - } + if os.getenv("NO_BINDINGS_MATRIX"): + return {"CIRCUITPY_BUILD_EXTENSIONS": ".bin"} contents = subprocess.run( - ["make", "-C", port_dir, "-f", "Makefile", f"BOARD={board_name}", - "print-CFLAGS", "print-CIRCUITPY_BUILD_EXTENSIONS", - "print-FROZEN_MPY_DIRS", "print-SRC_PATTERNS", - "print-SRC_SUPERVISOR"], + [ + "make", + "-C", + port_dir, + "-f", + "Makefile", + f"BOARD={board_name}", + "print-CFLAGS", + "print-CIRCUITPY_BUILD_EXTENSIONS", + "print-FROZEN_MPY_DIRS", + "print-SRC_PATTERNS", + "print-SRC_SUPERVISOR", + ], encoding="utf-8", errors="replace", stdout=subprocess.PIPE, @@ -202,8 +226,8 @@ def get_settings_from_makefile(port_dir, board_name): settings = {} for line in contents.stdout.split("\n"): - if line.startswith('CFLAGS ='): - for m in re.findall(r'-D([A-Z][A-Z0-9_]*)=(\d+)', line): + if line.startswith("CFLAGS ="): + for m in re.findall(r"-D([A-Z][A-Z0-9_]*)=(\d+)", line): settings[m[0]] = m[1] elif m := re.match(r"^([A-Z][A-Z0-9_]*) = (.*)$", line): settings[m.group(1)] = m.group(2) @@ -248,11 +272,13 @@ def get_repository_url(directory): repository_urls[directory] = path return path + def remove_prefix(s, prefix): if not s.startswith(prefix): raise ValueError(f"{s=} does not start with {prefix=}") return s.removeprefix(prefix) + def frozen_modules_from_dirs(frozen_mpy_dirs, withurl): """ Go through the list of frozen directories and extract the python modules. @@ -264,7 +290,7 @@ def frozen_modules_from_dirs(frozen_mpy_dirs, withurl): """ frozen_modules = [] for frozen_path in filter(lambda x: x, frozen_mpy_dirs.split(" ")): - frozen_path = remove_prefix(frozen_path, '../../') + frozen_path = remove_prefix(frozen_path, "../../") source_dir = get_circuitpython_root_dir() / frozen_path url_repository = get_repository_url(source_dir) for sub in source_dir.glob("*"): @@ -293,67 +319,72 @@ def lookup_setting(settings, key, default=""): return value -def all_ports_all_boards(ports=SUPPORTED_PORTS): - for port in ports: - port_dir = get_circuitpython_root_dir() / "ports" / port - for entry in (port_dir / "boards").iterdir(): - if not entry.is_dir(): - continue - yield (port, entry) - - -def support_matrix_by_board(use_branded_name=True, withurl=True, - add_port=False, add_chips=False, - add_pins=False, add_branded_name=False): +def support_matrix_by_board( + use_branded_name=True, + withurl=True, + add_port=False, + add_chips=False, + add_pins=False, + add_branded_name=False, +): """Compiles a list of the available core modules available for each board. """ base = build_module_map() def support_matrix(arg): - port, entry = arg - port_dir = get_circuitpython_root_dir() / "ports" / port - settings = get_settings_from_makefile(str(port_dir), entry.name) + board_id, board_info = arg + port = board_info["port"] + board_directory = board_info["directory"] + port_dir = board_directory.parent.parent + if port != "zephyr-cp": + settings = get_settings_from_makefile(str(port_dir), board_directory.name) + autogen_board_info = None + else: + circuitpython_toml_fn = board_directory / "circuitpython.toml" + with circuitpython_toml_fn.open("rb") as f: + settings = tomllib.load(f) + + autogen_board_info_fn = board_directory / "autogen_board_info.toml" + with autogen_board_info_fn.open("rb") as f: + autogen_board_info = tomllib.load(f) if use_branded_name or add_branded_name: - with open(entry / "mpconfigboard.h") as get_name: - board_contents = get_name.read() - board_name_re = re.search( - r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", board_contents - ) - if board_name_re: - branded_name = board_name_re.group(1).strip('"') - if '"' in branded_name: # sometimes the closing " is not at line end - branded_name = branded_name[:branded_name.index('"')] - board_name = branded_name + if autogen_board_info: + branded_name = autogen_board_info["name"] + else: + with open(board_directory / "mpconfigboard.h") as get_name: + board_contents = get_name.read() + board_name_re = re.search(r"(?<=MICROPY_HW_BOARD_NAME)\s+(.+)", board_contents) + if board_name_re: + branded_name = board_name_re.group(1).strip('"') + if '"' in branded_name: # sometimes the closing " is not at line end + branded_name = branded_name[: branded_name.index('"')] + board_name = branded_name if use_branded_name: board_name = branded_name else: - board_name = entry.name + board_name = board_id if add_chips: - with open(entry / "mpconfigboard.h") as get_name: + with open(board_directory / "mpconfigboard.h") as get_name: board_contents = get_name.read() - mcu_re = re.search( - r'(?<=MICROPY_HW_MCU_NAME)\s+(.+)', board_contents - ) + mcu_re = re.search(r"(?<=MICROPY_HW_MCU_NAME)\s+(.+)", board_contents) if mcu_re: mcu = mcu_re.group(1).strip('"') if '"' in mcu: # in case the closing " is not at line end - mcu = mcu[:mcu.index('"')] + mcu = mcu[: mcu.index('"')] else: mcu = "" - with open(entry / "mpconfigboard.mk") as get_name: + with open(board_directory / "mpconfigboard.mk") as get_name: board_contents = get_name.read() - flash_re = re.search( - r'(?<=EXTERNAL_FLASH_DEVICES)\s+=\s+(.+)', board_contents - ) + flash_re = re.search(r"(?<=EXTERNAL_FLASH_DEVICES)\s+=\s+(.+)", board_contents) if flash_re: # deal with the variability in the way multiple flash chips # are denoted. We want them to end up as a quoted, # comma separated string - flash = flash_re.group(1).replace('"','') + flash = flash_re.group(1).replace('"', "") flash = f'"{flash}"' else: flash = "" @@ -361,7 +392,7 @@ def support_matrix(arg): if add_pins: pins = [] try: - with open(entry / "pins.c") as get_name: + with open(board_directory / "pins.c") as get_name: pin_lines = get_name.readlines() except FileNotFoundError: # silabs boards have no pins.c pass @@ -374,35 +405,38 @@ def support_matrix(arg): pins.append((board_pin, chip_pin)) board_modules = [] - for module in base: - key = base[module]["key"] - if int(lookup_setting(settings, key, "0")): - board_modules.append(base[module]["name"]) + if autogen_board_info: + autogen_modules = autogen_board_info["modules"] + for k in autogen_modules: + if autogen_modules[k]: + board_modules.append(k) + else: + for module in base: + key = base[module]["key"] + if int(lookup_setting(settings, key, "0")): + board_modules.append(base[module]["name"]) board_modules.sort() if "CIRCUITPY_BUILD_EXTENSIONS" in settings: - board_extensions = [ - extension.strip() - for extension in settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",") - ] + board_extensions = settings["CIRCUITPY_BUILD_EXTENSIONS"] + if isinstance(board_extensions, str): + board_extensions = [extension.strip() for extension in board_extensions.split(",")] else: raise OSError(f"Board extensions undefined: {board_name}.") frozen_modules = [] if "FROZEN_MPY_DIRS" in settings: - frozen_modules = frozen_modules_from_dirs( - settings["FROZEN_MPY_DIRS"], withurl - ) + frozen_modules = frozen_modules_from_dirs(settings["FROZEN_MPY_DIRS"], withurl) if frozen_modules: frozen_modules.sort() # generate alias boards too board_info = { - "modules": board_modules, - "frozen_libraries": frozen_modules, - "extensions": board_extensions, - } + "modules": board_modules, + "frozen_libraries": frozen_modules, + "extensions": board_extensions, + } if add_branded_name: board_info["branded_name"] = branded_name if add_port: @@ -412,14 +446,9 @@ def support_matrix(arg): board_info["flash"] = flash if add_pins: board_info["pins"] = pins - board_matrix = [ - ( - board_name, - board_info - ) - ] - if entry.name in ALIASES_BY_BOARD: - for alias in ALIASES_BY_BOARD[entry.name]: + board_matrix = [(board_name, board_info)] + if board_id in ALIASES_BY_BOARD: + for alias in ALIASES_BY_BOARD[board_id]: if use_branded_name: if alias in ALIASES_BRAND_NAMES: alias = ALIASES_BRAND_NAMES[alias] @@ -429,7 +458,7 @@ def support_matrix(arg): "modules": board_modules, "frozen_libraries": frozen_modules, "extensions": board_extensions, - } + } if add_branded_name: board_info["branded_name"] = branded_name if add_port: @@ -439,22 +468,20 @@ def support_matrix(arg): board_info["flash"] = flash if add_pins: board_info["pins"] = pins - board_matrix.append( - ( - alias, - board_info - ) - ) + board_matrix.append((alias, board_info)) return board_matrix # this is now a list of (board,modules) + board_mapping = get_board_mapping() + real_boards = [] + for board in board_mapping: + if not board_mapping[board].get("alias", False): + real_boards.append((board, board_mapping[board])) executor = ThreadPoolExecutor(max_workers=os.cpu_count()) - mapped_exec = executor.map(support_matrix, all_ports_all_boards()) + mapped_exec = executor.map(support_matrix, real_boards) # flatmap with comprehensions boards = dict( - sorted( - [board for matrix in mapped_exec for board in matrix], key=lambda x: x[0] - ) + sorted([board for matrix in mapped_exec for board in matrix], key=lambda x: x[0]) ) return boards diff --git a/docs/supported_ports.rst b/docs/supported_ports.rst index 69eaa5ef14891..ca36999f42398 100644 --- a/docs/supported_ports.rst +++ b/docs/supported_ports.rst @@ -12,6 +12,7 @@ Additional testing is limited. .. toctree:: :maxdepth: 2 + ../ports/analog/README ../ports/atmel-samd/README ../ports/broadcom/README ../ports/cxd56/README @@ -24,3 +25,4 @@ Additional testing is limited. ../ports/silabs/README ../ports/stm/README ../ports/unix/README + ../ports/zephyr-cp/README diff --git a/docs/workflows.md b/docs/workflows.md index 727cc5401caf8..84d7530e2fe99 100644 --- a/docs/workflows.md +++ b/docs/workflows.md @@ -19,10 +19,36 @@ The workflow APIs are documented here. These USB interfaces are enabled by default on boards with USB support. They are usable once the device has been plugged into a host. -### CIRCUITPY drive +### Mass Storage CircuitPython exposes a standard mass storage (MSC) interface to enable file manipulation over a -standard interface. This interface works underneath the file system at the block level so using it -excludes other types of workflows from manipulating the file system at the same time. +standard interface. (This is how USB drives work.) This interface works underneath the file system at +the block level so using it excludes other types of workflows from manipulating the file system at +the same time. + +CircuitPython 10.x adds multiple Logical Units (LUNs) to the mass storage interface. This allows for +multiple drives to be accessed and ejected independently. + +#### CIRCUITPY drive +The CIRCUITPY drive is the main drive that CircuitPython uses. It is writable by the host by default +and read-only to CircuitPython. `storage.remount()` can be used to remount the drive to +CircuitPython as read-write. + +#### CPSAVES drive +The board may also expose a CPSAVES drive. (This is based on the ``CIRCUITPY_SAVES_PARTITION_SIZE`` +setting in ``mpconfigboard.h``.) It is a portion of the main flash that is writable by CircuitPython +by default. It is read-only to the host. `storage.remount()` can be used to remount the drive to the +host as read-write. + +#### SD card drive +A few boards have SD card automounting. (This is based on the ``DEFAULT_SD`` settings in +``mpconfigboard.h``.) The card is writable from CircuitPython by default and read-only to the host. +`storage.remount()` can be used to remount the drive to the host as read-write. + +On most other boards, except for ``atmel-samd`` boards, an SD card mounted in user code +at ``/sd`` will become visible after a few seconds on the attached host computer, as an +additional drive besides CIRCUITPY and (if present) CPSAVES. It will present with the volume +label on the SD card. Depending on the host operating system settings, the drive may or may not be +auto-mounted on the host. Host writes to drives mounted by user code will not trigger a reload. ### CDC serial CircuitPython exposes one CDC USB interface for CircuitPython serial. This is a standard serial diff --git a/examples/natmod/.gitignore b/examples/natmod/.gitignore deleted file mode 100644 index 4815d20f06be7..0000000000000 --- a/examples/natmod/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.mpy diff --git a/examples/natmod/README.md b/examples/natmod/README.md deleted file mode 100644 index 0cc4010ef42f3..0000000000000 --- a/examples/natmod/README.md +++ /dev/null @@ -1,74 +0,0 @@ -# Dynamic Native Modules - -Dynamic Native Modules are .mpy files that contain native machine code from a -language other than Python. For more info see [the documentation] -(https://docs.micropython.org/en/latest/develop/natmod.html). - -This should not be confused with [User C Modules] -(https://docs.micropython.org/en/latest/develop/cmodules.html) which are a -mechanism to add additional out-of-tree modules into the firmware build. - -## Examples - -This directory contains several examples of writing dynamic native modules, in -two main categories: - -1. Feature examples. - - * `features0` - A module containing a single "factorial" function which - demonstrates working with integers. - - * `features1` - A module that demonstrates some common tasks: - - defining simple functions exposed to Python - - defining local, helper C functions - - defining constant integers and strings exposed to Python - - getting and creating integer objects - - creating Python lists - - raising exceptions - - allocating memory - - BSS and constant data (rodata) - - relocated pointers in rodata - - * `features2` - This is a hybrid module containing both Python and C code, - and additionally the C code is spread over multiple files. It also - demonstrates using floating point (only when the target supports - hardware floating point). - - * `features3` - A module that shows how to use types, constant objects, - and creating dictionary instances. - - * `features4` - A module that demonstrates how to define a class. - -2. Dynamic version of existing built-ins. - - This provides a way to add missing functionality to firmware that doesn't - include certain built-in modules. See the `heapq`, `random`, `re`, - `deflate`, `btree`, and `framebuf` directories. - - So for example, if your firmware was compiled with `MICROPY_PY_FRAMEBUF` - disabled (e.g. to save flash space), then it would not include the - `framebuf` module. The `framebuf` native module provides a way to add the - `framebuf` module dynamically. - - The way these work is they define a dynamic native module which - `#include`'s the original module and then does the necessary - initialisation of the module's globals dict. - -## Build instructions - -To compile an example, you need to have the same toolchain available as -required for your target port. e.g. `arm-none-eabi-gcc` for any ARM Cortex M -target. See the port instructions for details. - -You also need to have the `pyelftools` Python package available, either via -your system package manager or installed from PyPI in a virtual environment -with `pip`. - -Each example provides a Makefile. You should specify the `ARCH` argument to -make (one of x86, x64, armv6m, armv7m, xtensa, xtensawin): - -``` -$ cd features0 -$ make ARCH=armv7m -$ mpremote cp features0.mpy : -``` diff --git a/examples/natmod/deflate/Makefile b/examples/natmod/deflate/Makefile deleted file mode 100644 index 86ef29b6324b3..0000000000000 --- a/examples/natmod/deflate/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module (different to built-in uzlib so it can coexist) -MOD = deflate_$(ARCH) - -# Source files (.c or .py) -SRC = deflate.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/deflate/deflate.c b/examples/natmod/deflate/deflate.c deleted file mode 100644 index fa475bd067240..0000000000000 --- a/examples/natmod/deflate/deflate.c +++ /dev/null @@ -1,70 +0,0 @@ -#define MICROPY_PY_DEFLATE (1) -#define MICROPY_PY_DEFLATE_COMPRESS (1) - -#include "py/dynruntime.h" - -#if !defined(__linux__) -void *memcpy(void *dst, const void *src, size_t n) { - return mp_fun_table.memmove_(dst, src, n); -} -void *memset(void *s, int c, size_t n) { - return mp_fun_table.memset_(s, c, n); -} -#endif - -mp_obj_full_type_t deflateio_type; - -#include "extmod/moddeflate.c" - -// Re-implemented from py/stream.c, not yet available in dynruntime.h. -mp_obj_t mp_stream_close(mp_obj_t stream) { - const mp_stream_p_t *stream_p = mp_get_stream(stream); - int error; - mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_CLOSE, 0, &error); - if (res == MP_STREAM_ERROR) { - mp_raise_OSError(error); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close); - -// Re-implemented from py/stream.c, not yet available in dynruntime.h. -STATIC mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return mp_stream_close(args[0]); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream___exit___obj, 4, 4, mp_stream___exit__); - -// Re-implemented from obj.c, not yet available in dynruntime.h. -mp_obj_t mp_identity(mp_obj_t self) { - return self; -} -MP_DEFINE_CONST_FUN_OBJ_1(mp_identity_obj, mp_identity); - -mp_map_elem_t deflateio_locals_dict_table[7]; -STATIC MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table); - -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - MP_DYNRUNTIME_INIT_ENTRY - - deflateio_type.base.type = mp_fun_table.type_type; - deflateio_type.name = MP_QSTR_DeflateIO; - MP_OBJ_TYPE_SET_SLOT(&deflateio_type, make_new, &deflateio_make_new, 0); - MP_OBJ_TYPE_SET_SLOT(&deflateio_type, protocol, &deflateio_stream_p, 1); - deflateio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) }; - deflateio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) }; - deflateio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) }; - deflateio_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_OBJ_FROM_PTR(&mp_stream_write_obj) }; - deflateio_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&mp_stream_close_obj) }; - deflateio_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR___enter__), MP_OBJ_FROM_PTR(&mp_identity_obj) }; - deflateio_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR___exit__), MP_OBJ_FROM_PTR(&mp_stream___exit___obj) }; - MP_OBJ_TYPE_SET_SLOT(&deflateio_type, locals_dict, (void*)&deflateio_locals_dict, 2); - - mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_deflate)); - mp_store_global(MP_QSTR_DeflateIO, MP_OBJ_FROM_PTR(&deflateio_type)); - mp_store_global(MP_QSTR_RAW, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_RAW)); - mp_store_global(MP_QSTR_ZLIB, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_ZLIB)); - mp_store_global(MP_QSTR_GZIP, MP_OBJ_NEW_SMALL_INT(DEFLATEIO_FORMAT_GZIP)); - - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/features0/Makefile b/examples/natmod/features0/Makefile deleted file mode 100644 index 57490df90abe7..0000000000000 --- a/examples/natmod/features0/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module -MOD = features0 - -# Source files (.c or .py) -SRC = features0.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -# Include to get the rules for compiling and linking the module -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features0/features0.c b/examples/natmod/features0/features0.c deleted file mode 100644 index 1b1867a3bc935..0000000000000 --- a/examples/natmod/features0/features0.c +++ /dev/null @@ -1,40 +0,0 @@ -/* This example demonstrates the following features in a native module: - - defining a simple function exposed to Python - - defining a local, helper C function - - getting and creating integer objects -*/ - -// Include the header file to get access to the MicroPython API -#include "py/dynruntime.h" - -// Helper function to compute factorial -STATIC mp_int_t factorial_helper(mp_int_t x) { - if (x == 0) { - return 1; - } - return x * factorial_helper(x - 1); -} - -// This is the function which will be called from Python, as factorial(x) -STATIC mp_obj_t factorial(mp_obj_t x_obj) { - // Extract the integer from the MicroPython input object - mp_int_t x = mp_obj_get_int(x_obj); - // Calculate the factorial - mp_int_t result = factorial_helper(x); - // Convert the result to a MicroPython integer object and return it - return mp_obj_new_int(result); -} -// Define a Python reference to the function above -STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial); - -// This is the entry point and is called when the module is imported -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // This must be first, it sets up the globals dict and other things - MP_DYNRUNTIME_INIT_ENTRY - - // Make the function available in the module's namespace - mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj)); - - // This must be last, it restores the globals dict - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/features1/Makefile b/examples/natmod/features1/Makefile deleted file mode 100644 index 010640daf9746..0000000000000 --- a/examples/natmod/features1/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module -MOD = features1 - -# Source files (.c or .py) -SRC = features1.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -# Include to get the rules for compiling and linking the module -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features1/features1.c b/examples/natmod/features1/features1.c deleted file mode 100644 index d2494b2138865..0000000000000 --- a/examples/natmod/features1/features1.c +++ /dev/null @@ -1,106 +0,0 @@ -/* This example demonstrates the following features in a native module: - - defining simple functions exposed to Python - - defining local, helper C functions - - defining constant integers and strings exposed to Python - - getting and creating integer objects - - creating Python lists - - raising exceptions - - allocating memory - - BSS and constant data (rodata) - - relocated pointers in rodata -*/ - -// Include the header file to get access to the MicroPython API -#include "py/dynruntime.h" - -// BSS (zero) data -uint16_t data16[4]; - -// Constant data (rodata) -const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 }; -const uint16_t table16[] = { 0x1000, 0x2000 }; - -// Constant data pointing to BSS/constant data -uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] }; -const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] }; - -// A simple function that adds its 2 arguments (must be integers) -STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) { - mp_int_t x = mp_obj_get_int(x_in); - mp_int_t y = mp_obj_get_int(y_in); - return mp_obj_new_int(x + y); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); - -// A local helper function (not exposed to Python) -STATIC mp_int_t fibonacci_helper(mp_int_t x) { - if (x < MP_ARRAY_SIZE(table8)) { - return table8[x]; - } else { - return fibonacci_helper(x - 1) + fibonacci_helper(x - 2); - } -} - -// A function which computes Fibonacci numbers -STATIC mp_obj_t fibonacci(mp_obj_t x_in) { - mp_int_t x = mp_obj_get_int(x_in); - if (x < 0) { - mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number")); - } - return mp_obj_new_int(fibonacci_helper(x)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci); - -// A function that accesses the BSS data -STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - // Create a list holding all items from data16 - mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL)); - for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) { - lst->items[i] = mp_obj_new_int(data16[i]); - } - return MP_OBJ_FROM_PTR(lst); - } else if (n_args == 1) { - // Get one item from data16 - mp_int_t idx = mp_obj_get_int(args[0]) & 3; - return mp_obj_new_int(data16[idx]); - } else { - // Set one item in data16 (via table_ptr16a) - mp_int_t idx = mp_obj_get_int(args[0]) & 3; - *table_ptr16a[idx] = mp_obj_get_int(args[1]); - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access); - -// A function that allocates memory and creates a bytearray -STATIC mp_obj_t make_array(void) { - uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b)); - for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) { - ptr[i] = *table_ptr16b[i]; - } - return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array); - -// This is the entry point and is called when the module is imported -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // This must be first, it sets up the globals dict and other things - MP_DYNRUNTIME_INIT_ENTRY - - // Messages can be printed as usual - mp_printf(&mp_plat_print, "initialising module self=%p\n", self); - - // Make the functions available in the module's namespace - mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); - mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj)); - mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj)); - mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj)); - - // Add some constants to the module's namespace - mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42)); - mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON)); - - // This must be last, it restores the globals dict - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/features2/Makefile b/examples/natmod/features2/Makefile deleted file mode 100644 index 4fd23c6879d47..0000000000000 --- a/examples/natmod/features2/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module -MOD = features2 - -# Source files (.c or .py) -SRC = main.c prod.c test.py - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -# Include to get the rules for compiling and linking the module -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features2/main.c b/examples/natmod/features2/main.c deleted file mode 100644 index 1a39700dc4b71..0000000000000 --- a/examples/natmod/features2/main.c +++ /dev/null @@ -1,83 +0,0 @@ -/* This example demonstrates the following features in a native module: - - using floats - - defining additional code in Python (see test.py) - - have extra C code in a separate file (see prod.c) -*/ - -// Include the header file to get access to the MicroPython API -#include "py/dynruntime.h" - -// Include the header for auxiliary C code for this module -#include "prod.h" - -// Automatically detect if this module should include double-precision code. -// If double precision is supported by the target architecture then it can -// be used in native module regardless of what float setting the target -// MicroPython runtime uses (being none, float or double). -#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8)) -#define USE_DOUBLE 1 -#else -#define USE_DOUBLE 0 -#endif - -// A function that uses the default float type configured for the current target -// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level -STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) { - return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add); - -// A function that explicitly uses single precision floats -STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) { - return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f); - -#if USE_DOUBLE -// A function that explicitly uses double precision floats -STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) { - return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d); -#endif - -// A function that computes the product of floats in an array. -// This function uses the most general C argument interface, which is more difficult -// to use but has access to the globals dict of the module via self->globals. -STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // Check number of arguments is valid - mp_arg_check_num(n_args, n_kw, 1, 1, false); - - // Extract buffer pointer and verify typecode - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW); - if (bufinfo.typecode != 'f') { - mp_raise_ValueError(MP_ERROR_TEXT("expecting float array")); - } - - // Compute product, store result back in first element of array - float *ptr = bufinfo.buf; - float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr); - ptr[0] = prod; - - return mp_const_none; -} - -// This is the entry point and is called when the module is imported -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // This must be first, it sets up the globals dict and other things - MP_DYNRUNTIME_INIT_ENTRY - - // Make the functions available in the module's namespace - mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj)); - mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj)); - #if USE_DOUBLE - mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj)); - #endif - - // The productf function uses the most general C argument interface - mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf)); - - // This must be last, it restores the globals dict - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/features2/prod.c b/examples/natmod/features2/prod.c deleted file mode 100644 index 7791dcad1d214..0000000000000 --- a/examples/natmod/features2/prod.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "prod.h" - -float prod_array(int n, float *ar) { - float ans = 1; - for (int i = 0; i < n; ++i) { - ans *= ar[i]; - } - return ans; -} diff --git a/examples/natmod/features2/prod.h b/examples/natmod/features2/prod.h deleted file mode 100644 index f27dd8d0330fe..0000000000000 --- a/examples/natmod/features2/prod.h +++ /dev/null @@ -1 +0,0 @@ -float prod_array(int n, float *ar); diff --git a/examples/natmod/features2/test.py b/examples/natmod/features2/test.py deleted file mode 100644 index af79b9692c216..0000000000000 --- a/examples/natmod/features2/test.py +++ /dev/null @@ -1,31 +0,0 @@ -# This Python code will be merged with the C code in main.c - -# ruff: noqa: F821 - this file is evaluated with C-defined names in scope - -import array - - -def isclose(a, b): - return abs(a - b) < 1e-3 - - -def test(): - tests = [ - isclose(add(0.1, 0.2), 0.3), - isclose(add_f(0.1, 0.2), 0.3), - ] - - ar = array.array("f", [1, 2, 3.5]) - productf(ar) - tests.append(isclose(ar[0], 7)) - - if "add_d" in globals(): - tests.append(isclose(add_d(0.1, 0.2), 0.3)) - - print(tests) - - if not all(tests): - raise SystemExit(1) - - -test() diff --git a/examples/natmod/features3/Makefile b/examples/natmod/features3/Makefile deleted file mode 100644 index 4a5f71b8f255b..0000000000000 --- a/examples/natmod/features3/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module -MOD = features3 - -# Source files (.c or .py) -SRC = features3.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -# Include to get the rules for compiling and linking the module -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features3/features3.c b/examples/natmod/features3/features3.c deleted file mode 100644 index 20efd67cdcefd..0000000000000 --- a/examples/natmod/features3/features3.c +++ /dev/null @@ -1,60 +0,0 @@ -/* This example demonstrates the following features in a native module: - - using types - - using constant objects - - creating dictionaries -*/ - -// Include the header file to get access to the MicroPython API. -#include "py/dynruntime.h" - -// A function that returns a tuple of object types. -STATIC mp_obj_t get_types(void) { - return mp_obj_new_tuple(9, ((mp_obj_t []) { - MP_OBJ_FROM_PTR(&mp_type_type), - MP_OBJ_FROM_PTR(&mp_type_NoneType), - MP_OBJ_FROM_PTR(&mp_type_bool), - MP_OBJ_FROM_PTR(&mp_type_int), - MP_OBJ_FROM_PTR(&mp_type_str), - MP_OBJ_FROM_PTR(&mp_type_bytes), - MP_OBJ_FROM_PTR(&mp_type_tuple), - MP_OBJ_FROM_PTR(&mp_type_list), - MP_OBJ_FROM_PTR(&mp_type_dict), - })); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_types_obj, get_types); - -// A function that returns a tuple of constant objects. -STATIC mp_obj_t get_const_objects(void) { - return mp_obj_new_tuple(5, ((mp_obj_t []) { - mp_const_none, - mp_const_false, - mp_const_true, - mp_const_empty_bytes, - mp_const_empty_tuple, - })); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_const_objects_obj, get_const_objects); - -// A function that creates a dictionary from the given arguments. -STATIC mp_obj_t make_dict(size_t n_args, const mp_obj_t *args) { - mp_obj_t dict = mp_obj_new_dict(n_args / 2); - for (; n_args >= 2; n_args -= 2, args += 2) { - mp_obj_dict_store(dict, args[0], args[1]); - } - return dict; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(make_dict_obj, 0, MP_OBJ_FUN_ARGS_MAX, make_dict); - -// This is the entry point and is called when the module is imported. -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // This must be first, it sets up the globals dict and other things. - MP_DYNRUNTIME_INIT_ENTRY - - // Make the functions available in the module's namespace. - mp_store_global(MP_QSTR_make_dict, MP_OBJ_FROM_PTR(&make_dict_obj)); - mp_store_global(MP_QSTR_get_types, MP_OBJ_FROM_PTR(&get_types_obj)); - mp_store_global(MP_QSTR_get_const_objects, MP_OBJ_FROM_PTR(&get_const_objects_obj)); - - // This must be last, it restores the globals dict. - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/features4/Makefile b/examples/natmod/features4/Makefile deleted file mode 100644 index f76a31a7cc141..0000000000000 --- a/examples/natmod/features4/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module -MOD = features4 - -# Source files (.c or .py) -SRC = features4.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -# Include to get the rules for compiling and linking the module -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/features4/features4.c b/examples/natmod/features4/features4.c deleted file mode 100644 index 336f4ecf64080..0000000000000 --- a/examples/natmod/features4/features4.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - This example extends on features0 but demonstrates how to define a class. - - The Factorial class constructor takes an integer, and then the calculate - method can be called to get the factorial. - - >>> import features4 - >>> f = features4.Factorial(4) - >>> f.calculate() - 24 -*/ - -// Include the header file to get access to the MicroPython API -#include "py/dynruntime.h" - -// This is type(Factorial) -mp_obj_full_type_t mp_type_factorial; - -// This is the internal state of a Factorial instance. -typedef struct { - mp_obj_base_t base; - mp_int_t n; -} mp_obj_factorial_t; - -// Essentially Factorial.__new__ (but also kind of __init__). -// Takes a single argument (the number to find the factorial of) -STATIC mp_obj_t factorial_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { - mp_arg_check_num(n_args, n_kw, 1, 1, false); - - mp_obj_factorial_t *o = mp_obj_malloc(mp_obj_factorial_t, type); - o->n = mp_obj_get_int(args_in[0]); - - return MP_OBJ_FROM_PTR(o); -} - -STATIC mp_int_t factorial_helper(mp_int_t x) { - if (x == 0) { - return 1; - } - return x * factorial_helper(x - 1); -} - -// Implements Factorial.calculate() -STATIC mp_obj_t factorial_calculate(mp_obj_t self_in) { - mp_obj_factorial_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(factorial_helper(self->n)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_calculate_obj, factorial_calculate); - -// Locals dict for the Factorial type (will have a single method, calculate, -// added in mpy_init). -mp_map_elem_t factorial_locals_dict_table[1]; -STATIC MP_DEFINE_CONST_DICT(factorial_locals_dict, factorial_locals_dict_table); - -// This is the entry point and is called when the module is imported -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - // This must be first, it sets up the globals dict and other things - MP_DYNRUNTIME_INIT_ENTRY - - // Initialise the type. - mp_type_factorial.base.type = (void*)&mp_type_type; - mp_type_factorial.flags = MP_TYPE_FLAG_NONE; - mp_type_factorial.name = MP_QSTR_Factorial; - MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, make_new, factorial_make_new, 0); - factorial_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_calculate), MP_OBJ_FROM_PTR(&factorial_calculate_obj) }; - MP_OBJ_TYPE_SET_SLOT(&mp_type_factorial, locals_dict, (void*)&factorial_locals_dict, 1); - - // Make the Factorial type available on the module. - mp_store_global(MP_QSTR_Factorial, MP_OBJ_FROM_PTR(&mp_type_factorial)); - - // This must be last, it restores the globals dict - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/heapq/Makefile b/examples/natmod/heapq/Makefile deleted file mode 100644 index af45b472da1ae..0000000000000 --- a/examples/natmod/heapq/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module (different to built-in heapq so it can coexist) -MOD = heapq_$(ARCH) - -# Source files (.c or .py) -SRC = heapq.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/heapq/heapq.c b/examples/natmod/heapq/heapq.c deleted file mode 100644 index ed19652a66b1d..0000000000000 --- a/examples/natmod/heapq/heapq.c +++ /dev/null @@ -1,16 +0,0 @@ -#define MICROPY_PY_HEAPQ (1) - -#include "py/dynruntime.h" - -#include "extmod/modheapq.c" - -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - MP_DYNRUNTIME_INIT_ENTRY - - mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_heapq)); - mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_heapq_heappush_obj)); - mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_heapq_heappop_obj)); - mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_heapq_heapify_obj)); - - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/random/Makefile b/examples/natmod/random/Makefile deleted file mode 100644 index 5c50227b15f9d..0000000000000 --- a/examples/natmod/random/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module (different to built-in random so it can coexist) -MOD = random_$(ARCH) - -# Source files (.c or .py) -SRC = random.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/random/random.c b/examples/natmod/random/random.c deleted file mode 100644 index 92257b8bc6811..0000000000000 --- a/examples/natmod/random/random.c +++ /dev/null @@ -1,33 +0,0 @@ -#define MICROPY_PY_RANDOM (1) -#define MICROPY_PY_RANDOM_EXTRA_FUNCS (1) - -#include "py/dynruntime.h" - -// Dynamic native modules don't support a data section so these must go in the BSS -uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; -uint8_t yasmarang_dat; - -#include "extmod/modrandom.c" - -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - MP_DYNRUNTIME_INIT_ENTRY - - yasmarang_pad = 0xeda4baba; - yasmarang_n = 69; - yasmarang_d = 233; - - mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_random)); - mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_random_getrandbits_obj)); - mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_random_seed_obj)); - #if MICROPY_PY_RANDOM_EXTRA_FUNCS - mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_random_randrange_obj)); - mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_random_randint_obj)); - mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_random_choice_obj)); - #if MICROPY_PY_BUILTINS_FLOAT - mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_random_random_obj)); - mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_random_uniform_obj)); - #endif - #endif - - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/natmod/re/Makefile b/examples/natmod/re/Makefile deleted file mode 100644 index 1ba540110650d..0000000000000 --- a/examples/natmod/re/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Location of top-level MicroPython directory -MPY_DIR = ../../.. - -# Name of module (different to built-in re so it can coexist) -MOD = re_$(ARCH) - -# Source files (.c or .py) -SRC = re.c - -# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin) -ARCH = x64 - -include $(MPY_DIR)/py/dynruntime.mk diff --git a/examples/natmod/re/re.c b/examples/natmod/re/re.c deleted file mode 100644 index df89ea83530ec..0000000000000 --- a/examples/natmod/re/re.c +++ /dev/null @@ -1,78 +0,0 @@ -#define MICROPY_STACK_CHECK (1) -#define MICROPY_PY_RE (1) -#define MICROPY_PY_RE_MATCH_GROUPS (1) -#define MICROPY_PY_RE_MATCH_SPAN_START_END (1) -#define MICROPY_PY_RE_SUB (0) // requires vstr interface - -#include -#include "py/dynruntime.h" - -#define STACK_LIMIT (2048) - -const char *stack_top; - -void mp_stack_check(void) { - // Assumes descending stack on target - volatile char dummy; - if (stack_top - &dummy >= STACK_LIMIT) { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded")); - } -} - -#if !defined(__linux__) -void *memcpy(void *dst, const void *src, size_t n) { - return mp_fun_table.memmove_(dst, src, n); -} -void *memset(void *s, int c, size_t n) { - return mp_fun_table.memset_(s, c, n); -} -#endif - -void *memmove(void *dest, const void *src, size_t n) { - return mp_fun_table.memmove_(dest, src, n); -} - -mp_obj_full_type_t match_type; -mp_obj_full_type_t re_type; - -#include "extmod/modre.c" - -mp_map_elem_t match_locals_dict_table[5]; -STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); - -mp_map_elem_t re_locals_dict_table[3]; -STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); - -mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) { - MP_DYNRUNTIME_INIT_ENTRY - - char dummy; - stack_top = &dummy; - - // Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section - // to copy in this key/value pair if they are specified as a struct, so assign them separately. - - match_type.base.type = (void*)&mp_fun_table.type_type; - match_type.name = MP_QSTR_match; - MP_OBJ_TYPE_SET_SLOT(&match_type, print, match_print, 0); - match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) }; - match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) }; - match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) }; - match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) }; - match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) }; - MP_OBJ_TYPE_SET_SLOT(&match_type, locals_dict, (void*)&match_locals_dict, 1); - - re_type.base.type = (void*)&mp_fun_table.type_type; - re_type.name = MP_QSTR_re; - MP_OBJ_TYPE_SET_SLOT(&re_type, print, re_print, 0); - re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) }; - re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) }; - re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) }; - MP_OBJ_TYPE_SET_SLOT(&re_type, locals_dict, (void*)&re_locals_dict, 1); - - mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj)); - mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj)); - mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj)); - - MP_DYNRUNTIME_INIT_EXIT -} diff --git a/examples/usercmodule/cexample/examplemodule.c b/examples/usercmodule/cexample/examplemodule.c deleted file mode 100644 index 9416613ba9520..0000000000000 --- a/examples/usercmodule/cexample/examplemodule.c +++ /dev/null @@ -1,90 +0,0 @@ -// Include MicroPython API. -#include "py/runtime.h" - -// Used to get the time in the Timer class example. -#include "py/mphal.h" - -// This is the function which will be called from Python as cexample.add_ints(a, b). -STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) { - // Extract the ints from the micropython input objects. - int a = mp_obj_get_int(a_obj); - int b = mp_obj_get_int(b_obj); - - // Calculate the addition and convert to MicroPython object. - return mp_obj_new_int(a + b); -} -// Define a Python reference to the function above. -STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints); - -// This structure represents Timer instance objects. -typedef struct _example_Timer_obj_t { - // All objects start with the base. - mp_obj_base_t base; - // Everything below can be thought of as instance attributes, but they - // cannot be accessed by MicroPython code directly. In this example we - // store the time at which the object was created. - mp_uint_t start_time; -} example_Timer_obj_t; - -// This is the Timer.time() method. After creating a Timer object, this -// can be called to get the time elapsed since creating the Timer. -STATIC mp_obj_t example_Timer_time(mp_obj_t self_in) { - // The first argument is self. It is cast to the *example_Timer_obj_t - // type so we can read its attributes. - example_Timer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - // Get the elapsed time and return it as a MicroPython integer. - mp_uint_t elapsed = mp_hal_ticks_ms() - self->start_time; - return mp_obj_new_int_from_uint(elapsed); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(example_Timer_time_obj, example_Timer_time); - -// This represents Timer.__new__ and Timer.__init__, which is called when -// the user instantiates a Timer object. -STATIC mp_obj_t example_Timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // Allocates the new object and sets the type. - example_Timer_obj_t *self = mp_obj_malloc(example_Timer_obj_t, type); - - // Initializes the time for this Timer instance. - self->start_time = mp_hal_ticks_ms(); - - // The make_new function always returns self. - return MP_OBJ_FROM_PTR(self); -} - -// This collects all methods and other static class attributes of the Timer. -// The table structure is similar to the module table, as detailed below. -STATIC const mp_rom_map_elem_t example_Timer_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&example_Timer_time_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(example_Timer_locals_dict, example_Timer_locals_dict_table); - -// This defines the type(Timer) object. -MP_DEFINE_CONST_OBJ_TYPE( - example_type_Timer, - MP_QSTR_Timer, - MP_TYPE_FLAG_NONE, - make_new, example_Timer_make_new, - locals_dict, &example_Timer_locals_dict - ); - -// Define all attributes of the module. -// Table entries are key/value pairs of the attribute name (a string) -// and the MicroPython object reference. -// All identifiers and strings are written as MP_QSTR_xxx and will be -// optimized to word-sized integers by the build system (interned strings). -STATIC const mp_rom_map_elem_t example_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) }, - { MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) }, - { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&example_type_Timer) }, -}; -STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table); - -// Define module object. -const mp_obj_module_t example_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&example_module_globals, -}; - -// Register the module to make it available in Python. -MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule); diff --git a/examples/usercmodule/cexample/micropython.cmake b/examples/usercmodule/cexample/micropython.cmake deleted file mode 100644 index ba076a16b246b..0000000000000 --- a/examples/usercmodule/cexample/micropython.cmake +++ /dev/null @@ -1,15 +0,0 @@ -# Create an INTERFACE library for our C module. -add_library(usermod_cexample INTERFACE) - -# Add our source files to the lib -target_sources(usermod_cexample INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/examplemodule.c -) - -# Add the current directory as an include directory. -target_include_directories(usermod_cexample INTERFACE - ${CMAKE_CURRENT_LIST_DIR} -) - -# Link our INTERFACE library to the usermod target. -target_link_libraries(usermod INTERFACE usermod_cexample) diff --git a/examples/usercmodule/cexample/micropython.mk b/examples/usercmodule/cexample/micropython.mk deleted file mode 100644 index d6801dac0ba5b..0000000000000 --- a/examples/usercmodule/cexample/micropython.mk +++ /dev/null @@ -1,8 +0,0 @@ -CEXAMPLE_MOD_DIR := $(USERMOD_DIR) - -# Add all C files to SRC_USERMOD. -SRC_USERMOD += $(CEXAMPLE_MOD_DIR)/examplemodule.c - -# We can add our module folder to include paths if needed -# This is not actually needed in this example. -CFLAGS_USERMOD += -I$(CEXAMPLE_MOD_DIR) diff --git a/examples/usercmodule/cppexample/example.cpp b/examples/usercmodule/cppexample/example.cpp deleted file mode 100644 index 2df832baa76f5..0000000000000 --- a/examples/usercmodule/cppexample/example.cpp +++ /dev/null @@ -1,24 +0,0 @@ -extern "C" { -#include -#include - -// Here we implement the function using C++ code, but since it's -// declaration has to be compatible with C everything goes in extern "C" scope. -mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj) { - // The following no-ops are just here to verify the static assertions used in - // the public API all compile with C++. - MP_STATIC_ASSERT_STR_ARRAY_COMPATIBLE; - if (mp_obj_is_type(a_obj, &mp_type_BaseException)) { - } - - // Prove we have (at least) C++11 features. - const auto a = mp_obj_get_int(a_obj); - const auto b = mp_obj_get_int(b_obj); - const auto sum = [&]() { - return mp_obj_new_int(a + b); - } (); - // Prove we're being scanned for QSTRs. - mp_obj_t tup[] = {sum, MP_ROM_QSTR(MP_QSTR_hellocpp)}; - return mp_obj_new_tuple(2, tup); -} -} diff --git a/examples/usercmodule/cppexample/examplemodule.c b/examples/usercmodule/cppexample/examplemodule.c deleted file mode 100644 index 96a1a74438845..0000000000000 --- a/examples/usercmodule/cppexample/examplemodule.c +++ /dev/null @@ -1,25 +0,0 @@ -#include - -// Define a Python reference to the function we'll make available. -// See example.cpp for the definition. -STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc); - -// Define all attributes of the module. -// Table entries are key/value pairs of the attribute name (a string) -// and the MicroPython object reference. -// All identifiers and strings are written as MP_QSTR_xxx and will be -// optimized to word-sized integers by the build system (interned strings). -STATIC const mp_rom_map_elem_t cppexample_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cppexample) }, - { MP_ROM_QSTR(MP_QSTR_cppfunc), MP_ROM_PTR(&cppfunc_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(cppexample_module_globals, cppexample_module_globals_table); - -// Define module object. -const mp_obj_module_t cppexample_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&cppexample_module_globals, -}; - -// Register the module to make it available in Python. -MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule); diff --git a/examples/usercmodule/cppexample/examplemodule.h b/examples/usercmodule/cppexample/examplemodule.h deleted file mode 100644 index d89384a630060..0000000000000 --- a/examples/usercmodule/cppexample/examplemodule.h +++ /dev/null @@ -1,5 +0,0 @@ -// Include MicroPython API. -#include "py/runtime.h" - -// Declare the function we'll make available in Python as cppexample.cppfunc(). -extern mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj); diff --git a/examples/usercmodule/cppexample/micropython.cmake b/examples/usercmodule/cppexample/micropython.cmake deleted file mode 100644 index 6da972c94e3b5..0000000000000 --- a/examples/usercmodule/cppexample/micropython.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# Create an INTERFACE library for our CPP module. -add_library(usermod_cppexample INTERFACE) - -# Add our source files to the library. -target_sources(usermod_cppexample INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/example.cpp - ${CMAKE_CURRENT_LIST_DIR}/examplemodule.c -) - -# Add the current directory as an include directory. -target_include_directories(usermod_cppexample INTERFACE - ${CMAKE_CURRENT_LIST_DIR} -) - -# Link our INTERFACE library to the usermod target. -target_link_libraries(usermod INTERFACE usermod_cppexample) diff --git a/examples/usercmodule/cppexample/micropython.mk b/examples/usercmodule/cppexample/micropython.mk deleted file mode 100644 index 0071d4fcc72b6..0000000000000 --- a/examples/usercmodule/cppexample/micropython.mk +++ /dev/null @@ -1,12 +0,0 @@ -CPPEXAMPLE_MOD_DIR := $(USERMOD_DIR) - -# Add our source files to the respective variables. -SRC_USERMOD += $(CPPEXAMPLE_MOD_DIR)/examplemodule.c -SRC_USERMOD_CXX += $(CPPEXAMPLE_MOD_DIR)/example.cpp - -# Add our module directory to the include path. -CFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR) -CXXFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR) -std=c++11 - -# We use C++ features so have to link against the standard library. -LDFLAGS_USERMOD += -lstdc++ diff --git a/examples/usercmodule/micropython.cmake b/examples/usercmodule/micropython.cmake deleted file mode 100644 index b9802401fa9f7..0000000000000 --- a/examples/usercmodule/micropython.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# This top-level micropython.cmake is responsible for listing -# the individual modules we want to include. -# Paths are absolute, and ${CMAKE_CURRENT_LIST_DIR} can be -# used to prefix subdirectories. - -# Add the C example. -include(${CMAKE_CURRENT_LIST_DIR}/cexample/micropython.cmake) - -# Add the CPP example. -include(${CMAKE_CURRENT_LIST_DIR}/cppexample/micropython.cmake) diff --git a/examples/usercmodule/subpackage/README.md b/examples/usercmodule/subpackage/README.md deleted file mode 100644 index c7f2ee53a2408..0000000000000 --- a/examples/usercmodule/subpackage/README.md +++ /dev/null @@ -1 +0,0 @@ -This is an example of a user C module that includes subpackages. diff --git a/examples/usercmodule/subpackage/micropython.cmake b/examples/usercmodule/subpackage/micropython.cmake deleted file mode 100644 index a51e7a80613d3..0000000000000 --- a/examples/usercmodule/subpackage/micropython.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Create an INTERFACE library for our C module. -add_library(usermod_subpackage_example INTERFACE) - -# Add our source files to the lib -target_sources(usermod_subpackage_example INTERFACE - ${CMAKE_CURRENT_LIST_DIR}/examplemodule.c -) - -# Add the current directory as an include directory. -target_include_directories(usermod_subpackage_example INTERFACE - ${CMAKE_CURRENT_LIST_DIR} -) - -target_compile_definitions(usermod_subpackage_example INTERFACE - MICROPY_MODULE_BUILTIN_SUBPACKAGES=1 -) - -# Link our INTERFACE library to the usermod target. -target_link_libraries(usermod INTERFACE usermod_subpackage_example) diff --git a/examples/usercmodule/subpackage/micropython.mk b/examples/usercmodule/subpackage/micropython.mk deleted file mode 100644 index 99ebf13ec19ab..0000000000000 --- a/examples/usercmodule/subpackage/micropython.mk +++ /dev/null @@ -1,10 +0,0 @@ -SUBPACKAGE_EXAMPLE_MOD_DIR := $(USERMOD_DIR) - -# Add all C files to SRC_USERMOD. -SRC_USERMOD += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/modexamplepackage.c - -# We can add our module folder to include paths if needed -# This is not actually needed in this example. -CFLAGS_USERMOD += -I$(SUBPACKAGE_EXAMPLE_MOD_DIR) -DMICROPY_MODULE_BUILTIN_SUBPACKAGES=1 - -QSTR_DEFS += $(SUBPACKAGE_EXAMPLE_MOD_DIR)/qstrdefsexamplepackage.h diff --git a/examples/usercmodule/subpackage/modexamplepackage.c b/examples/usercmodule/subpackage/modexamplepackage.c deleted file mode 100644 index 70e1e4005b30d..0000000000000 --- a/examples/usercmodule/subpackage/modexamplepackage.c +++ /dev/null @@ -1,84 +0,0 @@ -// Include MicroPython API. -#include "py/runtime.h" - -// Define example_package.foo.bar.f() -STATIC mp_obj_t example_package_foo_bar_f(void) { - mp_printf(&mp_plat_print, "example_package.foo.bar.f\n"); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_bar_f_obj, example_package_foo_bar_f); - -// Define all attributes of the second-level sub-package (example_package.foo.bar). -STATIC const mp_rom_map_elem_t example_package_foo_bar_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo_dot_bar) }, - { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_bar_f_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(example_package_foo_bar_globals, example_package_foo_bar_globals_table); - -// Define example_package.foo.bar module object. -const mp_obj_module_t example_package_foo_bar_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&example_package_foo_bar_globals, -}; - -// Define example_package.foo.f() -STATIC mp_obj_t example_package_foo_f(void) { - mp_printf(&mp_plat_print, "example_package.foo.f\n"); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_foo_f_obj, example_package_foo_f); - -// Define all attributes of the first-level sub-package (example_package.foo). -STATIC const mp_rom_map_elem_t example_package_foo_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package_dot_foo) }, - { MP_ROM_QSTR(MP_QSTR_bar), MP_ROM_PTR(&example_package_foo_bar_user_cmodule) }, - { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_foo_f_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(example_package_foo_globals, example_package_foo_globals_table); - -// Define example_package.foo module object. -const mp_obj_module_t example_package_foo_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&example_package_foo_globals, -}; - -// Define example_package.f() -STATIC mp_obj_t example_package_f(void) { - mp_printf(&mp_plat_print, "example_package.f\n"); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package_f_obj, example_package_f); - -STATIC mp_obj_t example_package___init__(void) { - if (!MP_STATE_VM(example_package_initialised)) { - // __init__ for builtins is called each time the module is imported, - // so ensure that initialisation only happens once. - MP_STATE_VM(example_package_initialised) = true; - mp_printf(&mp_plat_print, "example_package.__init__\n"); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(example_package___init___obj, example_package___init__); - -// The "initialised" state is stored on mp_state so that it is cleared on soft -// reset. -MP_REGISTER_ROOT_POINTER(int example_package_initialised); - -// Define all attributes of the top-level package (example_package). -STATIC const mp_rom_map_elem_t example_package_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_example_package) }, - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&example_package___init___obj) }, - { MP_ROM_QSTR(MP_QSTR_foo), MP_ROM_PTR(&example_package_foo_user_cmodule) }, - { MP_ROM_QSTR(MP_QSTR_f), MP_ROM_PTR(&example_package_f_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(example_package_globals, example_package_globals_table); - -// Define module object. -const mp_obj_module_t example_package_user_cmodule = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&example_package_globals, -}; - -// Register the module to make it available in Python. -// Note: subpackages should not be registered with MP_REGISTER_MODULE. -MP_REGISTER_MODULE(MP_QSTR_example_package, example_package_user_cmodule); diff --git a/examples/usercmodule/subpackage/qstrdefsexamplepackage.h b/examples/usercmodule/subpackage/qstrdefsexamplepackage.h deleted file mode 100644 index 057ec5279d003..0000000000000 --- a/examples/usercmodule/subpackage/qstrdefsexamplepackage.h +++ /dev/null @@ -1,2 +0,0 @@ -Q(example_package.foo) -Q(example_package.foo.bar) diff --git a/extmod/extmod.mk b/extmod/extmod.mk index a72d473bb4859..5b2772e4e2a99 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -14,7 +14,6 @@ SRC_EXTMOD_C += \ extmod/modrandom.c \ extmod/modre.c \ extmod/modselect.c \ - extmod/moductypes.c \ extmod/modzlib.c \ extmod/vfs.c \ extmod/vfs_blockdev.c \ @@ -25,7 +24,6 @@ SRC_EXTMOD_C += \ extmod/vfs_posix.c \ extmod/vfs_posix_file.c \ extmod/vfs_reader.c \ - extmod/virtpin.c \ shared/libc/abort_.c \ shared/libc/printf.c \ @@ -75,6 +73,9 @@ SRC_LIB_LIBM_C += $(addprefix lib/libm/,\ SRC_LIB_LIBM_SQRT_SW_C += lib/libm/ef_sqrt.c SRC_LIB_LIBM_SQRT_HW_C += lib/libm/thumb_vfp_sqrtf.c +# Disable warnings in libm. +$(BUILD)/lib/libm/kf_rem_pio2.o: CFLAGS += -Wno-maybe-uninitialized + # Double-precision math library. SRC_LIB_LIBM_DBL_C += $(addprefix lib/libm_dbl/,\ __cos.c \ @@ -127,6 +128,7 @@ SRC_LIB_LIBM_DBL_SQRT_HW_C += lib/libm_dbl/thumb_vfp_sqrt.c # Too many warnings in libm_dbl, disable for now. $(BUILD)/lib/libm_dbl/%.o: CFLAGS += -Wno-double-promotion -Wno-float-conversion +$(BUILD)/lib/libm_dbl/__rem_pio2_large.o: CFLAGS += -Wno-maybe-uninitialized ################################################################################ # VFS FAT FS @@ -160,7 +162,7 @@ endif ifeq ($(MICROPY_VFS_LFS2),1) CFLAGS_EXTMOD += -DMICROPY_VFS_LFS2=1 -CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT +CFLAGS_THIRDPARTY += -DLFS2_NO_MALLOC -DLFS2_NO_DEBUG -DLFS2_NO_WARN -DLFS2_NO_ERROR -DLFS2_NO_ASSERT -DLFS2_DEFINES=extmod/littlefs-include/lfs2_defines.h SRC_THIRDPARTY_C += $(addprefix $(LITTLEFS_DIR)/,\ lfs2.c \ lfs2_util.c \ @@ -197,28 +199,37 @@ SRC_THIRDPARTY_C += $(addprefix $(AXTLS_DIR)/,\ ) else ifeq ($(MICROPY_SSL_MBEDTLS),1) MBEDTLS_DIR = lib/mbedtls -MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config.h\" +MBEDTLS_CONFIG_FILE ?= \"mbedtls/mbedtls_config_port.h\" GIT_SUBMODULES += $(MBEDTLS_DIR) CFLAGS_EXTMOD += -DMBEDTLS_CONFIG_FILE=$(MBEDTLS_CONFIG_FILE) CFLAGS_EXTMOD += -DMICROPY_SSL_MBEDTLS=1 -I$(TOP)/$(MBEDTLS_DIR)/include +ifeq ($(MICROPY_PY_SSL_ECDSA_SIGN_ALT),1) +CFLAGS_EXTMOD += -DMICROPY_PY_SSL_ECDSA_SIGN_ALT=1 +LDFLAGS_EXTMOD += -Wl,--wrap=mbedtls_ecdsa_write_signature +endif SRC_THIRDPARTY_C += lib/mbedtls_errors/mp_mbedtls_errors.c SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ aes.c \ aesni.c \ - arc4.c \ asn1parse.c \ asn1write.c \ base64.c \ + bignum_core.c \ + bignum_mod.c \ + bignum_mod_raw.c \ bignum.c \ - blowfish.c \ camellia.c \ ccm.c \ - certs.c \ chacha20.c \ chachapoly.c \ cipher.c \ cipher_wrap.c \ + nist_kw.c \ + aria.c \ cmac.c \ + constant_time.c \ + mps_reader.c \ + mps_trace.c \ ctr_drbg.c \ debug.c \ des.c \ @@ -231,20 +242,17 @@ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ entropy.c \ entropy_poll.c \ gcm.c \ - havege.c \ hmac_drbg.c \ - md2.c \ - md4.c \ md5.c \ md.c \ oid.c \ padlock.c \ pem.c \ pk.c \ - pkcs11.c \ pkcs12.c \ pkcs5.c \ pkparse.c \ + pk_ecc.c \ pk_wrap.c \ pkwrite.c \ platform.c \ @@ -252,20 +260,21 @@ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ poly1305.c \ ripemd160.c \ rsa.c \ - rsa_internal.c \ + rsa_alt_helpers.c \ sha1.c \ sha256.c \ sha512.c \ ssl_cache.c \ ssl_ciphersuites.c \ - ssl_cli.c \ + ssl_client.c \ ssl_cookie.c \ - ssl_srv.c \ + ssl_debug_helpers_generated.c \ ssl_msg.c \ ssl_ticket.c \ ssl_tls.c \ + ssl_tls12_client.c \ + ssl_tls12_server.c \ timing.c \ - constant_time.c \ x509.c \ x509_create.c \ x509_crl.c \ @@ -273,7 +282,6 @@ SRC_THIRDPARTY_C += $(addprefix $(MBEDTLS_DIR)/library/,\ x509_csr.c \ x509write_crt.c \ x509write_csr.c \ - xtea.c \ ) endif endif @@ -291,6 +299,8 @@ $(BUILD)/$(LWIP_DIR)/core/ipv4/dhcp.o: CFLAGS += -Wno-address SRC_THIRDPARTY_C += shared/netutils/netutils.c SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ apps/mdns/mdns.c \ + apps/mdns/mdns_domain.c \ + apps/mdns/mdns_out.c \ core/def.c \ core/dns.c \ core/inet_chksum.c \ @@ -308,6 +318,7 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ core/tcp_out.c \ core/timeouts.c \ core/udp.c \ + core/ipv4/acd.c \ core/ipv4/autoip.c \ core/ipv4/dhcp.c \ core/ipv4/etharp.c \ @@ -326,6 +337,32 @@ SRC_THIRDPARTY_C += $(addprefix $(LWIP_DIR)/,\ core/ipv6/mld6.c \ core/ipv6/nd6.c \ netif/ethernet.c \ + netif/ppp/auth.c \ + netif/ppp/ccp.c \ + netif/ppp/chap-md5.c \ + netif/ppp/chap_ms.c \ + netif/ppp/chap-new.c \ + netif/ppp/demand.c \ + netif/ppp/eap.c \ + netif/ppp/ecp.c \ + netif/ppp/eui64.c \ + netif/ppp/fsm.c \ + netif/ppp/ipcp.c \ + netif/ppp/ipv6cp.c \ + netif/ppp/lcp.c \ + netif/ppp/magic.c \ + netif/ppp/mppe.c \ + netif/ppp/multilink.c \ + netif/ppp/polarssl/md5.c \ + netif/ppp/pppapi.c \ + netif/ppp/ppp.c \ + netif/ppp/pppcrypt.c \ + netif/ppp/pppoe.c \ + netif/ppp/pppol2tp.c \ + netif/ppp/pppos.c \ + netif/ppp/upap.c \ + netif/ppp/utils.c \ + netif/ppp/vj.c \ ) ifeq ($(MICROPY_PY_LWIP_LOOPBACK),1) CFLAGS_EXTMOD += -DLWIP_NETIF_LOOPBACK=1 @@ -341,8 +378,10 @@ endif ifeq ($(MICROPY_PY_BTREE),1) BTREE_DIR = lib/berkeley-db-1.xx -BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error=printf -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA) -INC += -I$(TOP)/$(BTREE_DIR)/PORT/include +BERKELEY_DB_CONFIG_FILE ?= \"extmod/berkeley-db/berkeley_db_config_port.h\" +CFLAGS_EXTMOD += -DBERKELEY_DB_CONFIG_FILE=$(BERKELEY_DB_CONFIG_FILE) +CFLAGS_EXTMOD += $(BTREE_DEFS_EXTRA) +INC += -I$(TOP)/$(BTREE_DIR)/include SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\ btree/bt_close.c \ btree/bt_conv.c \ @@ -361,9 +400,7 @@ SRC_THIRDPARTY_C += $(addprefix $(BTREE_DIR)/,\ ) CFLAGS_EXTMOD += -DMICROPY_PY_BTREE=1 # we need to suppress certain warnings to get berkeley-db to compile cleanly -# and we have separate BTREE_DEFS so the definitions don't interfere with other source code -$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter -Wno-deprecated-non-prototype -Wno-unknown-warning-option $(BTREE_DEFS) -$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) +$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter -Wno-deprecated-non-prototype -Wno-unknown-warning-option endif ################################################################################ @@ -374,15 +411,14 @@ CYW43_DIR = lib/cyw43-driver GIT_SUBMODULES += $(CYW43_DIR) CFLAGS_EXTMOD += -DMICROPY_PY_NETWORK_CYW43=1 SRC_THIRDPARTY_C += $(addprefix $(CYW43_DIR)/src/,\ + cyw43_bthci_uart.c \ cyw43_ctrl.c \ cyw43_lwip.c \ cyw43_ll.c \ cyw43_sdio.c \ + cyw43_spi.c \ cyw43_stats.c \ ) -ifeq ($(MICROPY_PY_BLUETOOTH),1) -DRIVERS_SRC_C += drivers/cyw43/cywbt.c -endif $(BUILD)/$(CYW43_DIR)/src/cyw43_%.o: CFLAGS += -std=c11 endif # MICROPY_PY_NETWORK_CYW43 @@ -425,7 +461,7 @@ ESP_HOSTED_SRC_C = $(addprefix $(ESP_HOSTED_DIR)/,\ ) ifeq ($(MICROPY_PY_BLUETOOTH),1) -ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci.c +ESP_HOSTED_SRC_C += $(ESP_HOSTED_DIR)/esp_hosted_bthci_uart.c endif # Include the protobuf-c support functions @@ -478,3 +514,68 @@ include $(TOP)/extmod/btstack/btstack.mk endif endif + +################################################################################ +# openamp + +ifeq ($(MICROPY_PY_OPENAMP),1) +OPENAMP_DIR = lib/open-amp +LIBMETAL_DIR = lib/libmetal +GIT_SUBMODULES += $(LIBMETAL_DIR) $(OPENAMP_DIR) +MICROPY_PY_OPENAMP_MODE ?= 0 +include $(TOP)/extmod/libmetal/libmetal.mk + +INC += -I$(TOP)/$(OPENAMP_DIR) +CFLAGS += -DMICROPY_PY_OPENAMP=1 + +ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1) +CFLAGS += -DMICROPY_PY_OPENAMP_REMOTEPROC=1 +endif + +ifeq ($(MICROPY_PY_OPENAMP_MODE),0) +CFLAGS += -DMICROPY_PY_OPENAMP_HOST=1 +CFLAGS_THIRDPARTY += -DVIRTIO_DRIVER_ONLY +else ifeq ($(MICROPY_PY_OPENAMP_MODE),1) +CFLAGS += -DMICROPY_PY_OPENAMP_DEVICE=1 +CFLAGS_THIRDPARTY += -DVIRTIO_DEVICE_ONLY +else +$(error Invalid Open-AMP mode specified: $(MICROPY_PY_OPENAMP_MODE)) +endif + +CFLAGS_THIRDPARTY += \ + -I$(BUILD)/openamp \ + -I$(TOP)/$(OPENAMP_DIR) \ + -I$(TOP)/$(OPENAMP_DIR)/lib/include/ \ + -DMETAL_INTERNAL \ + -DNO_ATOMIC_64_SUPPORT \ + -DRPMSG_BUFFER_SIZE=512 \ + +# OpenAMP's source files. +SRC_OPENAMP_C += $(addprefix $(OPENAMP_DIR)/lib/,\ + rpmsg/rpmsg.c \ + rpmsg/rpmsg_virtio.c \ + virtio/virtio.c \ + virtio/virtqueue.c \ + virtio_mmio/virtio_mmio_drv.c \ + ) + +# OpenAMP's remoteproc source files. +ifeq ($(MICROPY_PY_OPENAMP_REMOTEPROC),1) +SRC_OPENAMP_C += $(addprefix $(OPENAMP_DIR)/lib/remoteproc/,\ + elf_loader.c \ + remoteproc.c \ + remoteproc_virtio.c \ + rsc_table_parser.c \ + ) +endif # MICROPY_PY_OPENAMP_REMOTEPROC + +# Disable compiler warnings in OpenAMP (variables used only for assert). +$(BUILD)/$(OPENAMP_DIR)/lib/rpmsg/rpmsg_virtio.o: CFLAGS += -Wno-unused-but-set-variable +$(BUILD)/$(OPENAMP_DIR)/lib/virtio_mmio/virtio_mmio_drv.o: CFLAGS += -Wno-unused-but-set-variable + +# We need to have generated libmetal before compiling OpenAMP. +$(addprefix $(BUILD)/, $(SRC_OPENAMP_C:.c=.o)): $(BUILD)/openamp/metal/config.h + +SRC_THIRDPARTY_C += $(SRC_OPENAMP_C) $(SRC_LIBMETAL_C:$(BUILD)/%=%) + +endif # MICROPY_PY_OPENAMP diff --git a/extmod/lwip-include/arch/cc.h b/extmod/lwip-include/arch/cc.h deleted file mode 100644 index 400dc6ec75de1..0000000000000 --- a/extmod/lwip-include/arch/cc.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H - -#include - -// Generate lwip's internal types from stdint - -typedef uint8_t u8_t; -typedef int8_t s8_t; -typedef uint16_t u16_t; -typedef int16_t s16_t; -typedef uint32_t u32_t; -typedef int32_t s32_t; - -typedef u32_t mem_ptr_t; - -#define U16_F "hu" -#define S16_F "hd" -#define X16_F "hx" -#define U32_F "u" -#define S32_F "d" -#define X32_F "x" - -#define X8_F "02x" -#define SZT_F "u" - -#define BYTE_ORDER LITTLE_ENDIAN - -#define LWIP_CHKSUM_ALGORITHM 2 - -#include -#define LWIP_PLATFORM_DIAG(x) -#define LWIP_PLATFORM_ASSERT(x) { assert(1); } - -//#define PACK_STRUCT_FIELD(x) x __attribute__((packed)) -#define PACK_STRUCT_FIELD(x) x -#define PACK_STRUCT_STRUCT __attribute__((packed)) -#define PACK_STRUCT_BEGIN -#define PACK_STRUCT_END - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_CC_H diff --git a/extmod/lwip-include/arch/perf.h b/extmod/lwip-include/arch/perf.h deleted file mode 100644 index d310fc339f162..0000000000000 --- a/extmod/lwip-include/arch/perf.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H - -#define PERF_START /* null definition */ -#define PERF_STOP(x) /* null definition */ - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_ARCH_PERF_H diff --git a/extmod/lwip-include/lwipopts.h b/extmod/lwip-include/lwipopts.h deleted file mode 100644 index 584decfe85f83..0000000000000 --- a/extmod/lwip-include/lwipopts.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H -#define MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H - -#include -#include -#include - -// We're running without an OS for this port. We don't provide any services except light protection. -#define NO_SYS 1 - -#define SYS_LIGHTWEIGHT_PROT 1 -#include -typedef uint32_t sys_prot_t; - -#define TCP_LISTEN_BACKLOG 1 - -// We'll put these into a proper ifdef once somebody implements an ethernet driver -#define LWIP_ARP 0 -#define LWIP_ETHERNET 0 - -#define LWIP_DNS 1 - -#define LWIP_NETCONN 0 -#define LWIP_SOCKET 0 - -// CIRCUITPY-CHANGE: #if instead of #ifdef -#if MICROPY_PY_LWIP_SLIP -#define LWIP_HAVE_SLIPIF 1 -#endif - -// For now, we can simply define this as a macro for the timer code. But this function isn't -// universal and other ports will need to do something else. It may be necessary to move -// things like this into a port-provided header file. -#define sys_now mp_hal_ticks_ms - -#endif // MICROPY_INCLUDED_EXTMOD_LWIP_INCLUDE_LWIPOPTS_H diff --git a/extmod/modasyncio.c b/extmod/modasyncio.c index 8d7b52bc227ea..f73d32baf6dbc 100644 --- a/extmod/modasyncio.c +++ b/extmod/modasyncio.c @@ -58,12 +58,15 @@ typedef struct _mp_obj_task_t { typedef struct _mp_obj_task_queue_t { mp_obj_base_t base; mp_obj_task_t *heap; + #if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK + mp_obj_t push_callback; + #endif } mp_obj_task_queue_t; -STATIC const mp_obj_type_t task_queue_type; -STATIC const mp_obj_type_t task_type; +static const mp_obj_type_t task_queue_type; +static const mp_obj_type_t task_type; -STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); /******************************************************************************/ // Ticks for task ordering in pairing heap @@ -74,7 +77,7 @@ STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, si #define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1) #if !CIRCUITPY || (defined(__unix__) || defined(__APPLE__)) -STATIC mp_obj_t ticks(void) { +static mp_obj_t ticks(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & _TICKS_MAX); } #else @@ -87,14 +90,14 @@ STATIC mp_obj_t ticks(void) { #endif // CIRCUITPY-CHANGE: ticks_diff must match adafruit_ticks -STATIC mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) { +static mp_int_t ticks_diff(mp_obj_t t1_in, mp_obj_t t0_in) { mp_uint_t t0 = MP_OBJ_SMALL_INT_VALUE(t0_in); mp_uint_t t1 = MP_OBJ_SMALL_INT_VALUE(t1_in); mp_int_t diff = ((t1 - t0 + _TICKS_HALFPERIOD) & _TICKS_MAX) - _TICKS_HALFPERIOD; return diff; } -STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { +static int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { mp_obj_task_t *t1 = (mp_obj_task_t *)n1; mp_obj_task_t *t2 = (mp_obj_task_t *)n2; return MP_OBJ_SMALL_INT_VALUE(ticks_diff(t1->ph_key, t2->ph_key)) < 0; @@ -103,15 +106,22 @@ STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) { /******************************************************************************/ // TaskQueue class -STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)args; - mp_arg_check_num(n_args, n_kw, 0, 0, false); + mp_arg_check_num(n_args, n_kw, 0, MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK ? 1 : 0, false); mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type); self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt); + #if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK + if (n_args == 1) { + self->push_callback = args[0]; + } else { + self->push_callback = MP_OBJ_NULL; + } + #endif return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) { +static mp_obj_t task_queue_peek(mp_obj_t self_in) { mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in); if (self->heap == NULL) { return mp_const_none; @@ -119,9 +129,9 @@ STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(self->heap); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek); +static MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek); -STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) { +static mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) { mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]); task->data = mp_const_none; @@ -132,11 +142,16 @@ STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) { task->ph_key = args[2]; } self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task)); + #if MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK + if (self->push_callback != MP_OBJ_NULL) { + mp_call_function_1(self->push_callback, MP_OBJ_NEW_SMALL_INT(0)); + } + #endif return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push); -STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) { +static mp_obj_t task_queue_pop(mp_obj_t self_in) { mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap); if (head == NULL) { @@ -145,30 +160,25 @@ STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) { self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap); return MP_OBJ_FROM_PTR(head); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop); +static MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop); -STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) { +static mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) { mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_task_t *task = MP_OBJ_TO_PTR(task_in); self->heap = (mp_obj_task_t *)mp_pairheap_delete(task_lt, &self->heap->pairheap, &task->pairheap); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove); +static MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove); -STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = { +static const mp_rom_map_elem_t task_queue_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) }, { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) }, - - // CIRCUITPY-CHANGE: Remove these in CircuitPython 10.0.0 - { MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_obj) }, - { MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_obj) }, - { MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table); +static MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( task_queue_type, MP_QSTR_TaskQueue, MP_TYPE_FLAG_NONE, @@ -180,9 +190,9 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // Task class // This is the core asyncio context with cur_task, _task_queue and CancelledError. -STATIC mp_obj_t asyncio_context = MP_OBJ_NULL; +mp_obj_t mp_asyncio_context = MP_OBJ_NULL; -STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_obj_task_t *self = m_new_obj(mp_obj_task_t); self->pairheap.base.type = type; @@ -192,25 +202,25 @@ STATIC mp_obj_t task_make_new(const mp_obj_type_t *type, size_t n_args, size_t n self->state = TASK_STATE_RUNNING_NOT_WAITED_ON; self->ph_key = MP_OBJ_NEW_SMALL_INT(0); if (n_args == 2) { - asyncio_context = args[1]; + mp_asyncio_context = args[1]; } return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t task_done(mp_obj_t self_in) { +static mp_obj_t task_done(mp_obj_t self_in) { mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(TASK_IS_DONE(self)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_done_obj, task_done); +static MP_DEFINE_CONST_FUN_OBJ_1(task_done_obj, task_done); -STATIC mp_obj_t task_cancel(mp_obj_t self_in) { +static mp_obj_t task_cancel(mp_obj_t self_in) { mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); // Check if task is already finished. if (TASK_IS_DONE(self)) { return mp_const_false; } // Can't cancel self (not supported yet). - mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task)); + mp_obj_t cur_task = mp_obj_dict_get(mp_asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task)); if (self_in == cur_task) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't cancel self")); } @@ -219,7 +229,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) { self = MP_OBJ_TO_PTR(self->data); } - mp_obj_t _task_queue = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue)); + mp_obj_t _task_queue = mp_obj_dict_get(mp_asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR__task_queue)); // Reschedule Task as a cancelled task. mp_obj_t dest[3]; @@ -242,21 +252,21 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) { task_queue_push(2, dest); } - self->data = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError)); + self->data = mp_obj_dict_get(mp_asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError)); return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel); +static MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel); // CIRCUITPY-CHANGE: CircuitPython provides __await__(). -STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); +static mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf); -STATIC mp_obj_t task_await(mp_obj_t self_in) { +static mp_obj_t task_await(mp_obj_t self_in) { return task_getiter(self_in, NULL); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_await_obj, task_await); +static MP_DEFINE_CONST_FUN_OBJ_1(task_await_obj, task_await); -STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] == MP_OBJ_NULL) { // Load @@ -274,6 +284,7 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[1] = self_in; } else if (attr == MP_QSTR_ph_key) { dest[0] = self->ph_key; + // CIRCUITPY-CHANGE: await } else if (attr == MP_QSTR___await__) { dest[0] = MP_OBJ_FROM_PTR(&task_await_obj); dest[1] = self_in; @@ -290,7 +301,7 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { (void)iter_buf; mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); if (TASK_IS_DONE(self)) { @@ -306,7 +317,7 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { return self_in; } -STATIC mp_obj_t task_iternext(mp_obj_t self_in) { +static mp_obj_t task_iternext(mp_obj_t self_in) { mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); if (TASK_IS_DONE(self)) { // CIRCUITPY-CHANGE @@ -319,7 +330,7 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) { } } else { // Put calling task on waiting queue. - mp_obj_t cur_task = mp_obj_dict_get(asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task)); + mp_obj_t cur_task = mp_obj_dict_get(mp_asyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task)); mp_obj_t args[2] = { self->state, cur_task }; task_queue_push(2, args); // Set calling task's data to this task that it waits on, to double-link it. @@ -328,12 +339,12 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) { return mp_const_none; } -STATIC const mp_getiter_iternext_custom_t task_getiter_iternext = { +static const mp_getiter_iternext_custom_t task_getiter_iternext = { .getiter = task_getiter, .iternext = task_iternext, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( task_type, MP_QSTR_Task, MP_TYPE_FLAG_ITER_IS_CUSTOM, @@ -345,12 +356,12 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( /******************************************************************************/ // C-level asyncio module -STATIC const mp_rom_map_elem_t mp_module_asyncio_globals_table[] = { +static const mp_rom_map_elem_t mp_module_asyncio_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__asyncio) }, { MP_ROM_QSTR(MP_QSTR_TaskQueue), MP_ROM_PTR(&task_queue_type) }, { MP_ROM_QSTR(MP_QSTR_Task), MP_ROM_PTR(&task_type) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_asyncio_globals, mp_module_asyncio_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_asyncio_globals, mp_module_asyncio_globals_table); const mp_obj_module_t mp_module_asyncio = { .base = { &mp_type_module }, diff --git a/extmod/modbinascii.c b/extmod/modbinascii.c index 90fa7bbf906f0..2469744fc38de 100644 --- a/extmod/modbinascii.c +++ b/extmod/modbinascii.c @@ -44,15 +44,15 @@ static void check_not_unicode(const mp_obj_t arg) { } #if MICROPY_PY_BUILTINS_BYTES_HEX -STATIC mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) { +static mp_obj_t bytes_hex_as_bytes(size_t n_args, const mp_obj_t *args) { return mp_obj_bytes_hex(n_args, args, &mp_type_bytes); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_hex_as_bytes_obj, 1, 2, bytes_hex_as_bytes); -STATIC mp_obj_t bytes_fromhex_bytes(mp_obj_t data) { +static mp_obj_t bytes_fromhex_bytes(mp_obj_t data) { return mp_obj_bytes_fromhex(MP_OBJ_FROM_PTR(&mp_type_bytes), data); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes); +static MP_DEFINE_CONST_FUN_OBJ_1(bytes_fromhex_obj, bytes_fromhex_bytes); #endif // If ch is a character in the base64 alphabet, and is not a pad character, then @@ -74,7 +74,7 @@ static int mod_binascii_sextet(byte ch) { } } -STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { +static mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); byte *in = bufinfo.buf; @@ -115,9 +115,9 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) { return mp_obj_new_bytes_from_vstr(&vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); -STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_newline }; static const mp_arg_t allowed_args[] = { { MP_QSTR_newline, MP_ARG_BOOL, {.u_bool = true} }, @@ -179,13 +179,13 @@ STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, } return mp_obj_new_bytes_from_vstr(&vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64); +static MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64); // CIRCUITPY-CHANGE: no deflate #if MICROPY_PY_BINASCII_CRC32 #include "lib/uzlib/uzlib.h" -STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; // CIRCUITPY-CHANGE check_not_unicode(args[0]); @@ -194,10 +194,10 @@ STATIC mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) { crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff); return mp_obj_new_int_from_uint(crc ^ 0xffffffff); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32); #endif -STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { +static const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_binascii) }, #if MICROPY_PY_BUILTINS_BYTES_HEX { MP_ROM_QSTR(MP_QSTR_hexlify), MP_ROM_PTR(&bytes_hex_as_bytes_obj) }, @@ -211,7 +211,7 @@ STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table); const mp_obj_module_t mp_module_binascii = { .base = { &mp_type_module }, diff --git a/extmod/moddeflate.c b/extmod/moddeflate.c index 560ee3f0abce9..920b898b2ccc2 100644 --- a/extmod/moddeflate.c +++ b/extmod/moddeflate.c @@ -85,7 +85,7 @@ typedef struct { #endif } mp_obj_deflateio_t; -STATIC int deflateio_read_stream(void *data) { +static int deflateio_read_stream(void *data) { mp_obj_deflateio_t *self = data; const mp_stream_p_t *stream = mp_get_stream(self->stream); int err; @@ -100,7 +100,7 @@ STATIC int deflateio_read_stream(void *data) { return c; } -STATIC bool deflateio_init_read(mp_obj_deflateio_t *self) { +static bool deflateio_init_read(mp_obj_deflateio_t *self) { if (self->read) { return true; } @@ -142,7 +142,7 @@ STATIC bool deflateio_init_read(mp_obj_deflateio_t *self) { } } - size_t window_len = 1 << wbits; + size_t window_len = (size_t)1 << wbits; self->read->window = m_new(uint8_t, window_len); uzlib_uncompress_init(&self->read->decomp, self->read->window, window_len); @@ -151,7 +151,7 @@ STATIC bool deflateio_init_read(mp_obj_deflateio_t *self) { } #if MICROPY_PY_DEFLATE_COMPRESS -STATIC void deflateio_out_byte(void *data, uint8_t b) { +static void deflateio_out_byte(void *data, uint8_t b) { mp_obj_deflateio_t *self = data; const mp_stream_p_t *stream = mp_get_stream(self->stream); int err; @@ -161,23 +161,27 @@ STATIC void deflateio_out_byte(void *data, uint8_t b) { } } -STATIC bool deflateio_init_write(mp_obj_deflateio_t *self) { +static bool deflateio_init_write(mp_obj_deflateio_t *self) { if (self->write) { return true; } const mp_stream_p_t *stream = mp_get_stream_raise(self->stream, MP_STREAM_OP_WRITE); - self->write = m_new_obj(mp_obj_deflateio_write_t); - self->write->input_len = 0; - int wbits = self->window_bits; if (wbits == 0) { // Same default wbits for all formats. wbits = DEFLATEIO_DEFAULT_WBITS; } + + // Allocate the large window before allocating the mp_obj_deflateio_write_t, in case the + // window allocation fails the mp_obj_deflateio_t object will remain in a consistent state. size_t window_len = 1 << wbits; - self->write->window = m_new(uint8_t, window_len); + uint8_t *window = m_new(uint8_t, window_len); + + self->write = m_new_obj(mp_obj_deflateio_write_t); + self->write->window = window; + self->write->input_len = 0; uzlib_lz77_init(&self->write->lz77, self->write->window, window_len); self->write->lz77.dest_write_data = self; @@ -214,7 +218,7 @@ STATIC bool deflateio_init_write(mp_obj_deflateio_t *self) { } #endif -STATIC mp_obj_t deflateio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { +static mp_obj_t deflateio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { // args: stream, format=NONE, wbits=0, close=False mp_arg_check_num(n_args, n_kw, 1, 4, false); @@ -241,7 +245,7 @@ STATIC mp_obj_t deflateio_make_new(const mp_obj_type_t *type, size_t n_args, siz return MP_OBJ_FROM_PTR(self); } -STATIC mp_uint_t deflateio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t deflateio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(o_in); if (self->stream == MP_OBJ_NULL || !deflateio_init_read(self)) { @@ -268,7 +272,7 @@ STATIC mp_uint_t deflateio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *e } #if MICROPY_PY_DEFLATE_COMPRESS -STATIC mp_uint_t deflateio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t deflateio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(self_in); if (self->stream == MP_OBJ_NULL || !deflateio_init_write(self)) { @@ -302,7 +306,7 @@ static inline void put_be32(char *buf, uint32_t value) { } #endif -STATIC mp_uint_t deflateio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t deflateio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { if (request == MP_STREAM_CLOSE) { mp_obj_deflateio_t *self = MP_OBJ_TO_PTR(self_in); @@ -351,7 +355,7 @@ STATIC mp_uint_t deflateio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t } } -STATIC const mp_stream_p_t deflateio_stream_p = { +static const mp_stream_p_t deflateio_stream_p = { .read = deflateio_read, #if MICROPY_PY_DEFLATE_COMPRESS .write = deflateio_write, @@ -360,7 +364,7 @@ STATIC const mp_stream_p_t deflateio_stream_p = { }; #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t deflateio_locals_dict_table[] = { +static const mp_rom_map_elem_t deflateio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, @@ -371,9 +375,9 @@ STATIC const mp_rom_map_elem_t deflateio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table); +static MP_DEFINE_CONST_DICT(deflateio_locals_dict, deflateio_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( deflateio_type, MP_QSTR_DeflateIO, MP_TYPE_FLAG_NONE, @@ -382,7 +386,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &deflateio_locals_dict ); -STATIC const mp_rom_map_elem_t mp_module_deflate_globals_table[] = { +static const mp_rom_map_elem_t mp_module_deflate_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_deflate) }, { MP_ROM_QSTR(MP_QSTR_DeflateIO), MP_ROM_PTR(&deflateio_type) }, { MP_ROM_QSTR(MP_QSTR_AUTO), MP_ROM_INT(DEFLATEIO_FORMAT_AUTO) }, @@ -390,7 +394,7 @@ STATIC const mp_rom_map_elem_t mp_module_deflate_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ZLIB), MP_ROM_INT(DEFLATEIO_FORMAT_ZLIB) }, { MP_ROM_QSTR(MP_QSTR_GZIP), MP_ROM_INT(DEFLATEIO_FORMAT_GZIP) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_deflate_globals, mp_module_deflate_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_deflate_globals, mp_module_deflate_globals_table); const mp_obj_module_t mp_module_deflate = { .base = { &mp_type_module }, diff --git a/extmod/modhashlib.c b/extmod/modhashlib.c index fc9c87320004b..a31347356831e 100644 --- a/extmod/modhashlib.c +++ b/extmod/modhashlib.c @@ -71,7 +71,7 @@ static void hashlib_ensure_not_final(mp_obj_hash_t *self) { } #if MICROPY_PY_HASHLIB_SHA256 -STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg); +static mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_MBEDTLS @@ -81,9 +81,9 @@ STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg); #define mbedtls_sha256_finish_ret mbedtls_sha256_finish #endif -STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(mbedtls_sha256_context), type); o->final = false; mbedtls_sha256_init((mbedtls_sha256_context *)&o->state); mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0); @@ -93,7 +93,7 @@ STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); mp_buffer_info_t bufinfo; @@ -102,7 +102,7 @@ STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -125,9 +125,9 @@ static void check_not_unicode(const mp_obj_t arg) { #include "lib/crypto-algorithms/sha256.c" -STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(CRYAL_SHA256_CTX), type); o->final = false; sha256_init((CRYAL_SHA256_CTX *)o->state); if (n_args == 1) { @@ -136,7 +136,7 @@ STATIC mp_obj_t hashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { // CIRCUITPY-CHANGE check_not_unicode(arg); mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); @@ -147,7 +147,7 @@ STATIC mp_obj_t hashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -158,17 +158,17 @@ STATIC mp_obj_t hashlib_sha256_digest(mp_obj_t self_in) { } #endif -STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha256_update_obj, hashlib_sha256_update); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha256_digest_obj, hashlib_sha256_digest); +static MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha256_update_obj, hashlib_sha256_update); +static MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha256_digest_obj, hashlib_sha256_digest); -STATIC const mp_rom_map_elem_t hashlib_sha256_locals_dict_table[] = { +static const mp_rom_map_elem_t hashlib_sha256_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha256_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha256_digest_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(hashlib_sha256_locals_dict, hashlib_sha256_locals_dict_table); +static MP_DEFINE_CONST_DICT(hashlib_sha256_locals_dict, hashlib_sha256_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( hashlib_sha256_type, MP_QSTR_sha256, MP_TYPE_FLAG_NONE, @@ -178,12 +178,12 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( #endif #if MICROPY_PY_HASHLIB_SHA1 -STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg); +static mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_AXTLS -STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(SHA1_CTX), type); o->final = false; SHA1_Init((SHA1_CTX *)o->state); if (n_args == 1) { @@ -192,7 +192,7 @@ STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); mp_buffer_info_t bufinfo; @@ -201,7 +201,7 @@ STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -220,9 +220,9 @@ STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { #define mbedtls_sha1_finish_ret mbedtls_sha1_finish #endif -STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(mbedtls_sha1_context), type); o->final = false; mbedtls_sha1_init((mbedtls_sha1_context *)o->state); mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state); @@ -232,7 +232,7 @@ STATIC mp_obj_t hashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); mp_buffer_info_t bufinfo; @@ -241,7 +241,7 @@ STATIC mp_obj_t hashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -253,16 +253,16 @@ STATIC mp_obj_t hashlib_sha1_digest(mp_obj_t self_in) { } #endif -STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha1_update_obj, hashlib_sha1_update); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha1_digest_obj, hashlib_sha1_digest); +static MP_DEFINE_CONST_FUN_OBJ_2(hashlib_sha1_update_obj, hashlib_sha1_update); +static MP_DEFINE_CONST_FUN_OBJ_1(hashlib_sha1_digest_obj, hashlib_sha1_digest); -STATIC const mp_rom_map_elem_t hashlib_sha1_locals_dict_table[] = { +static const mp_rom_map_elem_t hashlib_sha1_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_sha1_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_sha1_digest_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(hashlib_sha1_locals_dict, hashlib_sha1_locals_dict_table); +static MP_DEFINE_CONST_DICT(hashlib_sha1_locals_dict, hashlib_sha1_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( hashlib_sha1_type, MP_QSTR_sha1, MP_TYPE_FLAG_NONE, @@ -272,12 +272,12 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( #endif #if MICROPY_PY_HASHLIB_MD5 -STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg); +static mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg); #if MICROPY_SSL_AXTLS -STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(MD5_CTX), type); o->final = false; MD5_Init((MD5_CTX *)o->state); if (n_args == 1) { @@ -286,7 +286,7 @@ STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, s return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); mp_buffer_info_t bufinfo; @@ -295,7 +295,7 @@ STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -314,9 +314,9 @@ STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { #define mbedtls_md5_finish_ret mbedtls_md5_finish #endif -STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); - mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type); + mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, state, char, sizeof(mbedtls_md5_context), type); o->final = false; mbedtls_md5_init((mbedtls_md5_context *)o->state); mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state); @@ -326,7 +326,7 @@ STATIC mp_obj_t hashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, s return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); mp_buffer_info_t bufinfo; @@ -335,7 +335,7 @@ STATIC mp_obj_t hashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { +static mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); hashlib_ensure_not_final(self); self->final = true; @@ -347,16 +347,16 @@ STATIC mp_obj_t hashlib_md5_digest(mp_obj_t self_in) { } #endif // MICROPY_SSL_MBEDTLS -STATIC MP_DEFINE_CONST_FUN_OBJ_2(hashlib_md5_update_obj, hashlib_md5_update); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(hashlib_md5_digest_obj, hashlib_md5_digest); +static MP_DEFINE_CONST_FUN_OBJ_2(hashlib_md5_update_obj, hashlib_md5_update); +static MP_DEFINE_CONST_FUN_OBJ_1(hashlib_md5_digest_obj, hashlib_md5_digest); -STATIC const mp_rom_map_elem_t hashlib_md5_locals_dict_table[] = { +static const mp_rom_map_elem_t hashlib_md5_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&hashlib_md5_update_obj) }, { MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&hashlib_md5_digest_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(hashlib_md5_locals_dict, hashlib_md5_locals_dict_table); +static MP_DEFINE_CONST_DICT(hashlib_md5_locals_dict, hashlib_md5_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( hashlib_md5_type, MP_QSTR_md5, MP_TYPE_FLAG_NONE, @@ -365,7 +365,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); #endif // MICROPY_PY_HASHLIB_MD5 -STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { +static const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hashlib) }, #if MICROPY_PY_HASHLIB_SHA256 { MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&hashlib_sha256_type) }, @@ -378,7 +378,7 @@ STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table); const mp_obj_module_t mp_module_hashlib = { .base = { &mp_type_module }, diff --git a/extmod/modheapq.c b/extmod/modheapq.c index db1e35bac2830..bb8c7d2bf175e 100644 --- a/extmod/modheapq.c +++ b/extmod/modheapq.c @@ -31,14 +31,14 @@ // the algorithm here is modelled on CPython's heapq.py -STATIC mp_obj_list_t *heapq_get_heap(mp_obj_t heap_in) { +static mp_obj_list_t *heapq_get_heap(mp_obj_t heap_in) { if (!mp_obj_is_type(heap_in, &mp_type_list)) { mp_raise_TypeError(MP_ERROR_TEXT("heap must be a list")); } return MP_OBJ_TO_PTR(heap_in); } -STATIC void heapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) { +static void heapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) { mp_obj_t item = heap->items[pos]; while (pos > start_pos) { mp_uint_t parent_pos = (pos - 1) >> 1; @@ -53,7 +53,7 @@ STATIC void heapq_heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uin heap->items[pos] = item; } -STATIC void heapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { +static void heapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { mp_uint_t start_pos = pos; mp_uint_t end_pos = heap->len; mp_obj_t item = heap->items[pos]; @@ -70,15 +70,15 @@ STATIC void heapq_heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) { heapq_heap_siftdown(heap, start_pos, pos); } -STATIC mp_obj_t mod_heapq_heappush(mp_obj_t heap_in, mp_obj_t item) { +static mp_obj_t mod_heapq_heappush(mp_obj_t heap_in, mp_obj_t item) { mp_obj_list_t *heap = heapq_get_heap(heap_in); mp_obj_list_append(heap_in, item); heapq_heap_siftdown(heap, 0, heap->len - 1); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_heapq_heappush_obj, mod_heapq_heappush); +static MP_DEFINE_CONST_FUN_OBJ_2(mod_heapq_heappush_obj, mod_heapq_heappush); -STATIC mp_obj_t mod_heapq_heappop(mp_obj_t heap_in) { +static mp_obj_t mod_heapq_heappop(mp_obj_t heap_in) { mp_obj_list_t *heap = heapq_get_heap(heap_in); if (heap->len == 0) { mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty heap")); @@ -92,26 +92,26 @@ STATIC mp_obj_t mod_heapq_heappop(mp_obj_t heap_in) { } return item; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heappop_obj, mod_heapq_heappop); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heappop_obj, mod_heapq_heappop); -STATIC mp_obj_t mod_heapq_heapify(mp_obj_t heap_in) { +static mp_obj_t mod_heapq_heapify(mp_obj_t heap_in) { mp_obj_list_t *heap = heapq_get_heap(heap_in); for (mp_uint_t i = heap->len / 2; i > 0;) { heapq_heap_siftup(heap, --i); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heapify_obj, mod_heapq_heapify); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_heapq_heapify_obj, mod_heapq_heapify); #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t mp_module_heapq_globals_table[] = { +static const mp_rom_map_elem_t mp_module_heapq_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_heapq) }, { MP_ROM_QSTR(MP_QSTR_heappush), MP_ROM_PTR(&mod_heapq_heappush_obj) }, { MP_ROM_QSTR(MP_QSTR_heappop), MP_ROM_PTR(&mod_heapq_heappop_obj) }, { MP_ROM_QSTR(MP_QSTR_heapify), MP_ROM_PTR(&mod_heapq_heapify_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_heapq_globals, mp_module_heapq_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_heapq_globals, mp_module_heapq_globals_table); const mp_obj_module_t mp_module_heapq = { .base = { &mp_type_module }, diff --git a/extmod/modjson.c b/extmod/modjson.c index 12dc70632594b..77f4a336aa821 100644 --- a/extmod/modjson.c +++ b/extmod/modjson.c @@ -44,7 +44,7 @@ enum { DUMP_MODE_TO_STREAM = 2, }; -STATIC mp_obj_t mod_json_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) { +static mp_obj_t mod_json_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, unsigned int mode) { enum { ARG_separators }; static const mp_arg_t allowed_args[] = { { MP_QSTR_separators, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, @@ -81,34 +81,34 @@ STATIC mp_obj_t mod_json_dump_helper(size_t n_args, const mp_obj_t *pos_args, mp } } -STATIC mp_obj_t mod_json_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mod_json_dump(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STREAM); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dump_obj, 2, mod_json_dump); +static MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dump_obj, 2, mod_json_dump); -STATIC mp_obj_t mod_json_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mod_json_dumps(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return mod_json_dump_helper(n_args, pos_args, kw_args, DUMP_MODE_TO_STRING); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dumps_obj, 1, mod_json_dumps); +static MP_DEFINE_CONST_FUN_OBJ_KW(mod_json_dumps_obj, 1, mod_json_dumps); #else -STATIC mp_obj_t mod_json_dump(mp_obj_t obj, mp_obj_t stream) { +static mp_obj_t mod_json_dump(mp_obj_t obj, mp_obj_t stream) { mp_get_stream_raise(stream, MP_STREAM_OP_WRITE); mp_print_t print = {MP_OBJ_TO_PTR(stream), mp_stream_write_adaptor}; mp_obj_print_helper(&print, obj, PRINT_JSON); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_json_dump_obj, mod_json_dump); +static MP_DEFINE_CONST_FUN_OBJ_2(mod_json_dump_obj, mod_json_dump); -STATIC mp_obj_t mod_json_dumps(mp_obj_t obj) { +static mp_obj_t mod_json_dumps(mp_obj_t obj) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 8, &print); mp_obj_print_helper(&print, obj, PRINT_JSON); return mp_obj_new_str_from_utf8_vstr(&vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_dumps_obj, mod_json_dumps); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_json_dumps_obj, mod_json_dumps); #endif @@ -147,7 +147,7 @@ typedef struct _json_stream_t { #define S_CUR(s) ((s).cur) #define S_NEXT(s) (json_stream_next(&(s))) -STATIC byte json_stream_next(json_stream_t *s) { +static byte json_stream_next(json_stream_t *s) { mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode); // CIRCUITPY-CHANGE JSON_DEBUG(" usjon_stream_next err:%2d cur: %c \n", s->errcode, s->cur); @@ -167,7 +167,7 @@ STATIC byte json_stream_next(json_stream_t *s) { #define CIRCUITPY_JSON_READ_CHUNK_SIZE 64 -STATIC mp_uint_t json_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t json_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { (void)size; // Ignore size because we know it's always 1. json_stream_t *s = obj; @@ -190,7 +190,7 @@ STATIC mp_uint_t json_python_readinto(mp_obj_t obj, void *buf, mp_uint_t size, i return 1; } -STATIC mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) { +static mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) { const mp_stream_p_t *stream_p = mp_proto_get(0, stream_obj); json_stream_t s; uint8_t character_buffer[CIRCUITPY_JSON_READ_CHUNK_SIZE]; @@ -227,7 +227,8 @@ STATIC mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) { for (;;) { cont: if (S_END(s)) { - break; + // Input finished abruptly in the middle of a composite entity. + goto fail; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; @@ -431,12 +432,12 @@ STATIC mp_obj_t _mod_json_load(mp_obj_t stream_obj, bool return_first_json) { } // CIRCUITPY-CHANGE -STATIC mp_obj_t mod_json_load(mp_obj_t stream_obj) { +static mp_obj_t mod_json_load(mp_obj_t stream_obj) { return _mod_json_load(stream_obj, true); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_load_obj, mod_json_load); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_json_load_obj, mod_json_load); -STATIC mp_obj_t mod_json_loads(mp_obj_t obj) { +static mp_obj_t mod_json_loads(mp_obj_t obj) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(obj, &bufinfo, MP_BUFFER_READ); vstr_t vstr = {bufinfo.len, bufinfo.len, (char *)bufinfo.buf, true}; @@ -444,9 +445,9 @@ STATIC mp_obj_t mod_json_loads(mp_obj_t obj) { // CIRCUITPY-CHANGE return _mod_json_load(MP_OBJ_FROM_PTR(&sio), false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_json_loads_obj, mod_json_loads); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_json_loads_obj, mod_json_loads); -STATIC const mp_rom_map_elem_t mp_module_json_globals_table[] = { +static const mp_rom_map_elem_t mp_module_json_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_json) }, { MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_json_dump_obj) }, { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_json_dumps_obj) }, @@ -454,7 +455,7 @@ STATIC const mp_rom_map_elem_t mp_module_json_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_json_loads_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_json_globals, mp_module_json_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_json_globals, mp_module_json_globals_table); const mp_obj_module_t mp_module_json = { .base = { &mp_type_module }, diff --git a/extmod/modmachine.c b/extmod/modmachine.c deleted file mode 100644 index a64b8ba79d43a..0000000000000 --- a/extmod/modmachine.c +++ /dev/null @@ -1,242 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2023 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "py/runtime.h" - -#if MICROPY_PY_MACHINE - -#include "extmod/modmachine.h" -#include "shared/runtime/pyexec.h" - -#if MICROPY_PY_MACHINE_DHT_READINTO -#include "drivers/dht/dht.h" -#endif - -// The port must provide implementations of these low-level machine functions. - -STATIC void mp_machine_idle(void); - -#if MICROPY_PY_MACHINE_BOOTLOADER -NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args); -#endif - -#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS -STATIC mp_obj_t mp_machine_unique_id(void); -NORETURN STATIC void mp_machine_reset(void); -STATIC mp_int_t mp_machine_reset_cause(void); -STATIC mp_obj_t mp_machine_get_freq(void); -STATIC void mp_machine_set_freq(size_t n_args, const mp_obj_t *args); -STATIC void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args); -NORETURN STATIC void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args); -#endif - -// The port can provide additional machine-module implementation in this file. -#ifdef MICROPY_PY_MACHINE_INCLUDEFILE -#include MICROPY_PY_MACHINE_INCLUDEFILE -#endif - -STATIC mp_obj_t machine_soft_reset(void) { - pyexec_system_exit = PYEXEC_FORCED_EXIT; - mp_raise_type(&mp_type_SystemExit); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); - -#if MICROPY_PY_MACHINE_BOOTLOADER -NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args) { - mp_machine_bootloader(n_args, args); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj, 0, 1, machine_bootloader); -#endif - -STATIC mp_obj_t machine_idle(void) { - mp_machine_idle(); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); - -#if MICROPY_PY_MACHINE_BARE_METAL_FUNCS - -STATIC mp_obj_t machine_unique_id(void) { - return mp_machine_unique_id(); -} -MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id); - -NORETURN STATIC mp_obj_t machine_reset(void) { - mp_machine_reset(); -} -MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); - -STATIC mp_obj_t machine_reset_cause(void) { - return MP_OBJ_NEW_SMALL_INT(mp_machine_reset_cause()); -} -MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); - -STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { - if (n_args == 0) { - return mp_machine_get_freq(); - } else { - mp_machine_set_freq(n_args, args); - return mp_const_none; - } -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); - -STATIC mp_obj_t machine_lightsleep(size_t n_args, const mp_obj_t *args) { - mp_machine_lightsleep(n_args, args); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj, 0, 1, machine_lightsleep); - -NORETURN STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { - mp_machine_deepsleep(n_args, args); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj, 0, 1, machine_deepsleep); - -#endif - -#if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ - -STATIC mp_obj_t machine_disable_irq(void) { - uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION(); - return mp_obj_new_int(state); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq); - -STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) { - uint32_t state = mp_obj_get_int(state_in); - MICROPY_END_ATOMIC_SECTION(state); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq); - -#endif - -STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_machine) }, - - // Memory access objects. - { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) }, - { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) }, - - // Miscellaneous functions. - #if MICROPY_PY_MACHINE_BARE_METAL_FUNCS - { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) }, - #endif - - // Reset related functions. - { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) }, - #if MICROPY_PY_MACHINE_BOOTLOADER - { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) }, - #endif - #if MICROPY_PY_MACHINE_BARE_METAL_FUNCS - { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) }, - { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, - #endif - - // Power related functions. - { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) }, - #if MICROPY_PY_MACHINE_BARE_METAL_FUNCS - { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) }, - { MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) }, - { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) }, - #endif - - // Interrupt related functions. - #if MICROPY_PY_MACHINE_DISABLE_IRQ_ENABLE_IRQ - { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) }, - { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) }, - #endif - - // Functions for bit protocols. - #if MICROPY_PY_MACHINE_BITSTREAM - { MP_ROM_QSTR(MP_QSTR_bitstream), MP_ROM_PTR(&machine_bitstream_obj) }, - #endif - #if MICROPY_PY_MACHINE_DHT_READINTO - { MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) }, - #endif - #if MICROPY_PY_MACHINE_PULSE - { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) }, - #endif - - // Classes for PinBase and Signal. - #if MICROPY_PY_MACHINE_PIN_BASE - { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) }, - #endif - { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) }, - - // Classes for software bus protocols. - #if MICROPY_PY_MACHINE_SOFTI2C - { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, - #endif - #if MICROPY_PY_MACHINE_SOFTSPI - { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, - #endif - - // Classes for hardware peripherals. - #if MICROPY_PY_MACHINE_ADC - { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, - #endif - #if MICROPY_PY_MACHINE_ADC_BLOCK - { MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adc_block_type) }, - #endif - #if MICROPY_PY_MACHINE_DAC - { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, - #endif - #if MICROPY_PY_MACHINE_I2C - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, - #endif - #if MICROPY_PY_MACHINE_I2S - { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, - #endif - #if MICROPY_PY_MACHINE_PWM - { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, - #endif - #if MICROPY_PY_MACHINE_SPI - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, - #endif - #if MICROPY_PY_MACHINE_UART - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, - #endif - #if MICROPY_PY_MACHINE_WDT - { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) }, - #endif - - // A port can add extra entries to the module by defining the following macro. - #ifdef MICROPY_PY_MACHINE_EXTRA_GLOBALS - MICROPY_PY_MACHINE_EXTRA_GLOBALS - #endif -}; -STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); - -const mp_obj_module_t mp_module_machine = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&machine_module_globals, -}; - -MP_REGISTER_EXTENSIBLE_MODULE(MP_QSTR_machine, mp_module_machine); - -#endif // MICROPY_PY_MACHINE diff --git a/extmod/modmachine.h b/extmod/modmachine.h deleted file mode 100644 index d186ce661510c..0000000000000 --- a/extmod/modmachine.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2023 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_EXTMOD_MODMACHINE_H -#define MICROPY_INCLUDED_EXTMOD_MODMACHINE_H - -#include "py/mphal.h" -#include "py/obj.h" - -#if MICROPY_PY_MACHINE - -#include "drivers/bus/spi.h" - -// Whether to enable the ADC.init() method. -// Requires a port to implement mp_machine_adc_init_helper(). -#ifndef MICROPY_PY_MACHINE_ADC_INIT -#define MICROPY_PY_MACHINE_ADC_INIT (0) -#endif - -// Whether to enable the ADC.deinit() method. -// Requires a port to implement mp_machine_adc_deinit(). -#ifndef MICROPY_PY_MACHINE_ADC_DEINIT -#define MICROPY_PY_MACHINE_ADC_DEINIT (0) -#endif - -// Whether to enable the ADC.block() method. -// Requires a port to implement mp_machine_adc_block(). -#ifndef MICROPY_PY_MACHINE_ADC_BLOCK -#define MICROPY_PY_MACHINE_ADC_BLOCK (0) -#endif - -// Whether to enable the ADC.read_uv() method. -// Requires a port to implement mp_machine_adc_read_uv(). -#ifndef MICROPY_PY_MACHINE_ADC_READ_UV -#define MICROPY_PY_MACHINE_ADC_READ_UV (0) -#endif - -// Whether to enable the ADC.atten() and ADC.width() methods. -// Note: these are legacy and should not be used on new ports. -#ifndef MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH -#define MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH (0) -#endif - -// Whether to enable the ADC.read() method. -// Note: this is legacy and should not be used on new ports. -#ifndef MICROPY_PY_MACHINE_ADC_READ -#define MICROPY_PY_MACHINE_ADC_READ (0) -#endif - -// Whether to enable the UART.sendbreak() method. -// Requires a port to implement mp_machine_uart_sendbreak(). -#ifndef MICROPY_PY_MACHINE_UART_SENDBREAK -#define MICROPY_PY_MACHINE_UART_SENDBREAK (0) -#endif - -// Whether to enable the UART.readchar() and UART.writechar() methods. -// Requires a port to implement mp_machine_uart_readchar() and mp_machine_uart_writechar(). -#ifndef MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR -#define MICROPY_PY_MACHINE_UART_READCHAR_WRITECHAR (0) -#endif - -// Whether to enable the UART.irq() method. -// Requires a port to implement mp_machine_uart_irq(). -#ifndef MICROPY_PY_MACHINE_UART_IRQ -#define MICROPY_PY_MACHINE_UART_IRQ (0) -#endif - -// Temporary support for legacy construction of SoftI2C via I2C type. -#define MP_MACHINE_I2C_CHECK_FOR_LEGACY_SOFTI2C_CONSTRUCTION(n_args, n_kw, all_args) \ - do { \ - if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \ - mp_print_str(MICROPY_ERROR_PRINTER, "Warning: I2C(-1, ...) is deprecated, use SoftI2C(...) instead\n"); \ - if (n_args != 0) { \ - --n_args; \ - ++all_args; \ - } \ - return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_i2c_type, make_new)(&mp_machine_soft_i2c_type, n_args, n_kw, all_args); \ - } \ - } while (0) - -// Temporary support for legacy construction of SoftSPI via SPI type. -#define MP_MACHINE_SPI_CHECK_FOR_LEGACY_SOFTSPI_CONSTRUCTION(n_args, n_kw, all_args) \ - do { \ - if (n_args == 0 || all_args[0] == MP_OBJ_NEW_SMALL_INT(-1)) { \ - mp_print_str(MICROPY_ERROR_PRINTER, "Warning: SPI(-1, ...) is deprecated, use SoftSPI(...) instead\n"); \ - if (n_args != 0) { \ - --n_args; \ - ++all_args; \ - } \ - return MP_OBJ_TYPE_GET_SLOT(&mp_machine_soft_spi_type, make_new)(&mp_machine_soft_spi_type, n_args, n_kw, all_args); \ - } \ - } while (0) - -#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C - -#define MP_MACHINE_I2C_FLAG_READ (0x01) // if not set then it's a write -#define MP_MACHINE_I2C_FLAG_STOP (0x02) - -#if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 -// If set, the first mp_machine_i2c_buf_t in a transfer is a write. -#define MP_MACHINE_I2C_FLAG_WRITE1 (0x04) -#endif - -#endif - -// A port must provide these types, but they are otherwise opaque. -typedef struct _machine_adc_obj_t machine_adc_obj_t; -typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t; -typedef struct _machine_i2s_obj_t machine_i2s_obj_t; -typedef struct _machine_pwm_obj_t machine_pwm_obj_t; -typedef struct _machine_uart_obj_t machine_uart_obj_t; -typedef struct _machine_wdt_obj_t machine_wdt_obj_t; - -typedef struct _machine_mem_obj_t { - mp_obj_base_t base; - unsigned elem_size; // in bytes -} machine_mem_obj_t; - -#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C - -typedef struct _mp_machine_i2c_buf_t { - size_t len; - uint8_t *buf; -} mp_machine_i2c_buf_t; - -// I2C protocol: -// - init must be non-NULL -// - start/stop/read/write can be NULL, meaning operation is not supported -// - transfer must be non-NULL -// - transfer_single only needs to be set if transfer=mp_machine_i2c_transfer_adaptor -typedef struct _mp_machine_i2c_p_t { - #if MICROPY_PY_MACHINE_I2C_TRANSFER_WRITE1 - bool transfer_supports_write1; - #endif - void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - int (*start)(mp_obj_base_t *obj); - int (*stop)(mp_obj_base_t *obj); - int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); - int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len); - int (*transfer)(mp_obj_base_t *obj, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); - int (*transfer_single)(mp_obj_base_t *obj, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags); -} mp_machine_i2c_p_t; - -// SoftI2C object. -typedef struct _mp_machine_soft_i2c_obj_t { - mp_obj_base_t base; - uint32_t us_delay; - uint32_t us_timeout; - mp_hal_pin_obj_t scl; - mp_hal_pin_obj_t sda; -} mp_machine_soft_i2c_obj_t; - -#endif - -#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI - -// SPI protocol. -typedef struct _mp_machine_spi_p_t { - void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - void (*deinit)(mp_obj_base_t *obj); // can be NULL - void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest); -} mp_machine_spi_p_t; - -// SoftSPI object. -typedef struct _mp_machine_soft_spi_obj_t { - mp_obj_base_t base; - mp_soft_spi_obj_t spi; -} mp_machine_soft_spi_obj_t; - -#endif - -// Objects for machine.mem8, machine.mem16 and machine.mem32. -extern const machine_mem_obj_t machine_mem8_obj; -extern const machine_mem_obj_t machine_mem16_obj; -extern const machine_mem_obj_t machine_mem32_obj; - -// These classes correspond to machine.Type entries in the machine module. -// Their Python bindings are implemented in extmod, and their implementation -// is provided by a port. -extern const mp_obj_type_t machine_adc_type; -extern const mp_obj_type_t machine_adc_block_type; -extern const mp_obj_type_t machine_i2c_type; -extern const mp_obj_type_t machine_i2s_type; -extern const mp_obj_type_t machine_mem_type; -extern const mp_obj_type_t machine_pin_type; -extern const mp_obj_type_t machine_pinbase_type; -extern const mp_obj_type_t machine_pwm_type; -extern const mp_obj_type_t machine_rtc_type; -extern const mp_obj_type_t machine_signal_type; -extern const mp_obj_type_t machine_spi_type; -extern const mp_obj_type_t machine_timer_type; -extern const mp_obj_type_t machine_uart_type; -extern const mp_obj_type_t machine_wdt_type; - -#if MICROPY_PY_MACHINE_SOFTI2C -extern const mp_obj_type_t mp_machine_soft_i2c_type; -#endif -#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SOFTI2C -extern const mp_obj_dict_t mp_machine_i2c_locals_dict; -#endif - -#if MICROPY_PY_MACHINE_SOFTSPI -extern const mp_obj_type_t mp_machine_soft_spi_type; -extern const mp_machine_spi_p_t mp_machine_soft_spi_p; -#endif -#if MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_SOFTSPI -extern const mp_obj_dict_t mp_machine_spi_locals_dict; -#endif - -#if defined(MICROPY_MACHINE_MEM_GET_READ_ADDR) -uintptr_t MICROPY_MACHINE_MEM_GET_READ_ADDR(mp_obj_t addr_o, uint align); -#endif -#if defined(MICROPY_MACHINE_MEM_GET_WRITE_ADDR) -uintptr_t MICROPY_MACHINE_MEM_GET_WRITE_ADDR(mp_obj_t addr_o, uint align); -#endif - -NORETURN mp_obj_t machine_bootloader(size_t n_args, const mp_obj_t *args); -void machine_bitstream_high_low(mp_hal_pin_obj_t pin, uint32_t *timing_ns, const uint8_t *buf, size_t len); -mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us); - -MP_DECLARE_CONST_FUN_OBJ_0(machine_unique_id_obj); -MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_obj); -MP_DECLARE_CONST_FUN_OBJ_0(machine_reset_cause_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_lightsleep_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_deepsleep_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bootloader_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_bitstream_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj); - -#if MICROPY_PY_MACHINE_I2C -int mp_machine_i2c_transfer_adaptor(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); -int mp_machine_soft_i2c_transfer(mp_obj_base_t *self, uint16_t addr, size_t n, mp_machine_i2c_buf_t *bufs, unsigned int flags); -#endif - -#if MICROPY_PY_MACHINE_SPI -mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj); -MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj); -MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj); -MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj); -#endif - -#endif // MICROPY_PY_MACHINE - -#endif // MICROPY_INCLUDED_EXTMOD_MODMACHINE_H diff --git a/extmod/modos.c b/extmod/modos.c index 5a088b5202989..69fdc3fac0a06 100644 --- a/extmod/modos.c +++ b/extmod/modos.c @@ -73,11 +73,12 @@ #if MICROPY_PY_OS_SYNC // sync() // Sync all filesystems. -STATIC mp_obj_t mp_os_sync(void) { +static mp_obj_t mp_os_sync(void) { #if MICROPY_VFS_FAT for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { - // this assumes that vfs->obj is fs_user_mount_t with block device functions - disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL); + if (mp_obj_is_type(vfs->obj, &mp_fat_vfs_type)) { + disk_ioctl(MP_OBJ_TO_PTR(vfs->obj), CTRL_SYNC, NULL); + } } #endif return mp_const_none; @@ -93,20 +94,20 @@ MP_DEFINE_CONST_FUN_OBJ_0(mp_os_sync_obj, mp_os_sync); #define CONST_RELEASE const #endif -STATIC const qstr mp_os_uname_info_fields[] = { +static const qstr mp_os_uname_info_fields[] = { MP_QSTR_sysname, MP_QSTR_nodename, MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine }; -STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); -STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); -STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_os_uname_info_release_obj, MICROPY_VERSION_STRING); -STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN); -STATIC const MP_DEFINE_STR_OBJ(mp_os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); +static const MP_DEFINE_STR_OBJ(mp_os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM); +static const MP_DEFINE_STR_OBJ(mp_os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM); +static CONST_RELEASE MP_DEFINE_STR_OBJ(mp_os_uname_info_release_obj, MICROPY_VERSION_STRING); +static const MP_DEFINE_STR_OBJ(mp_os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN); +static const MP_DEFINE_STR_OBJ(mp_os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); -STATIC MP_DEFINE_ATTRTUPLE( +static MP_DEFINE_ATTRTUPLE( mp_os_uname_info_obj, mp_os_uname_info_fields, 5, @@ -117,7 +118,7 @@ STATIC MP_DEFINE_ATTRTUPLE( MP_ROM_PTR(&mp_os_uname_info_machine_obj) ); -STATIC mp_obj_t mp_os_uname(void) { +static mp_obj_t mp_os_uname(void) { #if MICROPY_PY_OS_UNAME_RELEASE_DYNAMIC const char *release = mp_os_uname_release(); mp_os_uname_info_release_obj.len = strlen(release); @@ -125,12 +126,12 @@ STATIC mp_obj_t mp_os_uname(void) { #endif return MP_OBJ_FROM_PTR(&mp_os_uname_info_obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_os_uname_obj, mp_os_uname); #endif #if MICROPY_PY_OS_DUPTERM_NOTIFY -STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) { +static mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) { (void)obj_in; for (;;) { int c = mp_os_dupterm_rx_chr(); @@ -141,10 +142,10 @@ STATIC mp_obj_t mp_os_dupterm_notify(mp_obj_t obj_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_os_dupterm_notify_obj, mp_os_dupterm_notify); #endif -STATIC const mp_rom_map_elem_t os_module_globals_table[] = { +static const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_os) }, #if MICROPY_PY_OS_GETENV_PUTENV_UNSETENV @@ -152,9 +153,6 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_os_putenv_obj) }, { MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_os_unsetenv_obj) }, #endif - #if MICROPY_PY_OS_SEP - { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, - #endif #if MICROPY_PY_OS_SYNC { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_os_sync_obj) }, #endif @@ -169,16 +167,19 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { #endif #if MICROPY_VFS + { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) }, { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) }, { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) }, { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) }, + #if MICROPY_VFS_WRITABLE { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove + #endif { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) }, - { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove #endif // The following are MicroPython extensions. @@ -195,6 +196,10 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { #if MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) }, + #endif + + // The following MicroPython extensions are deprecated. Use the `vfs` module instead. + #if !MICROPY_PREVIEW_VERSION_2 && MICROPY_VFS { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) }, #if MICROPY_VFS_FAT @@ -219,7 +224,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_mbfs_remove_obj) }, #endif }; -STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); +static MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table); const mp_obj_module_t mp_module_os = { .base = { &mp_type_module }, diff --git a/extmod/modplatform.c b/extmod/modplatform.c index 73846f946d0ed..e1f5476c3b3aa 100644 --- a/extmod/modplatform.c +++ b/extmod/modplatform.c @@ -36,39 +36,77 @@ // platform - Access to underlying platform's identifying data -STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \ +static const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \ MICROPY_VERSION_STRING "-" MICROPY_PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" \ MICROPY_PLATFORM_LIBC_LIB "" MICROPY_PLATFORM_LIBC_VER); -STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER); -STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB); -STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER); -STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = { +static const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER); +static const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB); +static const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER); +static const mp_rom_obj_tuple_t info_libc_tuple_obj = { {&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)} }; -STATIC mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t platform_platform(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return MP_OBJ_FROM_PTR(&info_platform_obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform); +static MP_DEFINE_CONST_FUN_OBJ_KW(platform_platform_obj, 0, platform_platform); -STATIC mp_obj_t platform_python_compiler(void) { +static mp_obj_t platform_python_compiler(void) { return MP_OBJ_FROM_PTR(&info_python_compiler_obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler); +static MP_DEFINE_CONST_FUN_OBJ_0(platform_python_compiler_obj, platform_python_compiler); -STATIC mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t platform_libc_ver(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { return MP_OBJ_FROM_PTR(&info_libc_tuple_obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver); +static MP_DEFINE_CONST_FUN_OBJ_KW(platform_libc_ver_obj, 0, platform_libc_ver); -STATIC const mp_rom_map_elem_t modplatform_globals_table[] = { +#ifdef __riscv +static mp_obj_t platform_processor(void) { + #if (__riscv_xlen <= 64) && !defined(__linux__) + uintptr_t misa_csr = 0; + + // Load the MISA CSR directly. + __asm volatile ( + "csrr %0, misa \n" + : "+r" (misa_csr) + : + : + ); + + char processor_buffer[31] = { // "RV32"/"RV64" + up to 26 chars. + #if (__riscv_xlen < 64) + "RV32" + #else + "RV64" + #endif + }; + mp_uint_t offset = 4; + for (mp_uint_t bit = 0; bit < 26; bit++) { + if (misa_csr & (1U << bit)) { + processor_buffer[offset++] = 'A' + bit; + } + } + + return mp_obj_new_str(processor_buffer, offset); + #else + return MP_OBJ_NEW_QSTR(MP_QSTR_); + #endif +} +static MP_DEFINE_CONST_FUN_OBJ_0(platform_processor_obj, platform_processor); +#endif + +static const mp_rom_map_elem_t modplatform_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_platform) }, { MP_ROM_QSTR(MP_QSTR_platform), MP_ROM_PTR(&platform_platform_obj) }, { MP_ROM_QSTR(MP_QSTR_python_compiler), MP_ROM_PTR(&platform_python_compiler_obj) }, { MP_ROM_QSTR(MP_QSTR_libc_ver), MP_ROM_PTR(&platform_libc_ver_obj) }, + #ifdef __riscv + { MP_ROM_QSTR(MP_QSTR_processor), MP_ROM_PTR(&platform_processor_obj) }, + #endif }; -STATIC MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table); +static MP_DEFINE_CONST_DICT(modplatform_globals, modplatform_globals_table); const mp_obj_module_t mp_module_platform = { .base = { &mp_type_module }, diff --git a/extmod/modplatform.h b/extmod/modplatform.h index 56a50e53c5445..a155f071cba1b 100644 --- a/extmod/modplatform.h +++ b/extmod/modplatform.h @@ -36,7 +36,11 @@ // See: https://sourceforge.net/p/predef/wiki/Home/ #if defined(__ARM_ARCH) +#if defined(__ARM_ARCH_ISA_A64) +#define MICROPY_PLATFORM_ARCH "aarch64" +#else #define MICROPY_PLATFORM_ARCH "arm" +#endif #elif defined(__x86_64__) || defined(_M_X64) #define MICROPY_PLATFORM_ARCH "x86_64" #elif defined(__i386__) || defined(_M_IX86) @@ -44,12 +48,22 @@ #elif defined(__xtensa__) #define MICROPY_PLATFORM_ARCH "xtensa" #elif defined(__riscv) +#if __riscv_xlen == 64 +#define MICROPY_PLATFORM_ARCH "riscv64" +#else #define MICROPY_PLATFORM_ARCH "riscv" +#endif #else #define MICROPY_PLATFORM_ARCH "" #endif -#if defined(__GNUC__) +#if defined(__clang__) +#define MICROPY_PLATFORM_COMPILER \ + "Clang " \ + MP_STRINGIFY(__clang_major__) "." \ + MP_STRINGIFY(__clang_minor__) "." \ + MP_STRINGIFY(__clang_patchlevel__) +#elif defined(__GNUC__) #define MICROPY_PLATFORM_COMPILER \ "GCC " \ MP_STRINGIFY(__GNUC__) "." \ @@ -83,12 +97,20 @@ #elif defined(__NEWLIB__) #define MICROPY_PLATFORM_LIBC_LIB "newlib" #define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION +#elif defined(_PICOLIBC__) +#define MICROPY_PLATFORM_LIBC_LIB "picolibc" +#define MICROPY_PLATFORM_LIBC_VER _PICOLIBC_VERSION +#elif defined(__ANDROID__) +#define MICROPY_PLATFORM_LIBC_LIB "bionic" +#define MICROPY_PLATFORM_LIBC_VER MP_STRINGIFY(__ANDROID_API__) #else #define MICROPY_PLATFORM_LIBC_LIB "" #define MICROPY_PLATFORM_LIBC_VER "" #endif -#if defined(__linux) +#if defined(__ANDROID__) +#define MICROPY_PLATFORM_SYSTEM "Android" +#elif defined(__linux) #define MICROPY_PLATFORM_SYSTEM "Linux" #elif defined(__unix__) #define MICROPY_PLATFORM_SYSTEM "Unix" diff --git a/extmod/modrandom.c b/extmod/modrandom.c index e65f31488bfeb..79a1b18baac2d 100644 --- a/extmod/modrandom.c +++ b/extmod/modrandom.c @@ -46,16 +46,16 @@ #if !MICROPY_ENABLE_DYNRUNTIME #if SEED_ON_IMPORT // If the state is seeded on import then keep these variables in the BSS. -STATIC uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; -STATIC uint8_t yasmarang_dat; +static uint32_t yasmarang_pad, yasmarang_n, yasmarang_d; +static uint8_t yasmarang_dat; #else // Without seed-on-import these variables must be initialised via the data section. -STATIC uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233; -STATIC uint8_t yasmarang_dat = 0; +static uint32_t yasmarang_pad = 0xeda4baba, yasmarang_n = 69, yasmarang_d = 233; +static uint8_t yasmarang_dat = 0; #endif #endif -STATIC uint32_t yasmarang(void) { +static uint32_t yasmarang(void) { yasmarang_pad += yasmarang_dat + yasmarang_d * yasmarang_n; yasmarang_pad = (yasmarang_pad << 3) + (yasmarang_pad >> 29); yasmarang_n = yasmarang_pad | 2; @@ -71,7 +71,7 @@ STATIC uint32_t yasmarang(void) { // returns an unsigned integer below the given argument // n must not be zero -STATIC uint32_t yasmarang_randbelow(uint32_t n) { +static uint32_t yasmarang_randbelow(uint32_t n) { uint32_t mask = 1; while ((n & mask) < n) { mask = (mask << 1) | 1; @@ -85,8 +85,8 @@ STATIC uint32_t yasmarang_randbelow(uint32_t n) { #endif -STATIC mp_obj_t mod_random_getrandbits(mp_obj_t num_in) { - int n = mp_obj_get_int(num_in); +static mp_obj_t mod_random_getrandbits(mp_obj_t num_in) { + mp_int_t n = mp_obj_get_int(num_in); if (n > 32 || n < 0) { mp_raise_ValueError(MP_ERROR_TEXT("bits must be 32 or less")); } @@ -98,9 +98,9 @@ STATIC mp_obj_t mod_random_getrandbits(mp_obj_t num_in) { mask >>= (32 - n); return mp_obj_new_int_from_uint(yasmarang() & mask); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_getrandbits_obj, mod_random_getrandbits); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_random_getrandbits_obj, mod_random_getrandbits); -STATIC mp_obj_t mod_random_seed(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_random_seed(size_t n_args, const mp_obj_t *args) { mp_uint_t seed; if (n_args == 0 || args[0] == mp_const_none) { #ifdef MICROPY_PY_RANDOM_SEED_INIT_FUNC @@ -111,22 +111,22 @@ STATIC mp_obj_t mod_random_seed(size_t n_args, const mp_obj_t *args) { } else { seed = mp_obj_get_int_truncated(args[0]); } - yasmarang_pad = seed; + yasmarang_pad = (uint32_t)seed; yasmarang_n = 69; yasmarang_d = 233; yasmarang_dat = 0; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_seed_obj, 0, 1, mod_random_seed); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_seed_obj, 0, 1, mod_random_seed); #if MICROPY_PY_RANDOM_EXTRA_FUNCS -STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { mp_int_t start = mp_obj_get_int(args[0]); if (n_args == 1) { // range(stop) if (start > 0) { - return mp_obj_new_int(yasmarang_randbelow(start)); + return mp_obj_new_int(yasmarang_randbelow((uint32_t)start)); } else { goto error; } @@ -135,7 +135,7 @@ STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { if (n_args == 2) { // range(start, stop) if (start < stop) { - return mp_obj_new_int(start + yasmarang_randbelow(stop - start)); + return mp_obj_new_int(start + yasmarang_randbelow((uint32_t)(stop - start))); } else { goto error; } @@ -151,7 +151,7 @@ STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { goto error; } if (n > 0) { - return mp_obj_new_int(start + step * yasmarang_randbelow(n)); + return mp_obj_new_int(start + step * yasmarang_randbelow((uint32_t)n)); } else { goto error; } @@ -161,33 +161,33 @@ STATIC mp_obj_t mod_random_randrange(size_t n_args, const mp_obj_t *args) { error: mp_raise_ValueError(NULL); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_randrange_obj, 1, 3, mod_random_randrange); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_random_randrange_obj, 1, 3, mod_random_randrange); -STATIC mp_obj_t mod_random_randint(mp_obj_t a_in, mp_obj_t b_in) { +static mp_obj_t mod_random_randint(mp_obj_t a_in, mp_obj_t b_in) { mp_int_t a = mp_obj_get_int(a_in); mp_int_t b = mp_obj_get_int(b_in); if (a <= b) { - return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1)); + return mp_obj_new_int(a + yasmarang_randbelow((uint32_t)(b - a + 1))); } else { mp_raise_ValueError(NULL); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_randint_obj, mod_random_randint); +static MP_DEFINE_CONST_FUN_OBJ_2(mod_random_randint_obj, mod_random_randint); -STATIC mp_obj_t mod_random_choice(mp_obj_t seq) { +static mp_obj_t mod_random_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len > 0) { - return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow(len)), MP_OBJ_SENTINEL); + return mp_obj_subscr(seq, mp_obj_new_int(yasmarang_randbelow((uint32_t)len)), MP_OBJ_SENTINEL); } else { mp_raise_type(&mp_type_IndexError); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_random_choice_obj, mod_random_choice); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_random_choice_obj, mod_random_choice); #if MICROPY_PY_BUILTINS_FLOAT // returns a number in the range [0..1) using Yasmarang to fill in the fraction bits -STATIC mp_float_t yasmarang_float(void) { +static mp_float_t yasmarang_float(void) { mp_float_union_t u; u.p.sgn = 0; u.p.exp = (1 << (MP_FLOAT_EXP_BITS - 1)) - 1; @@ -199,24 +199,24 @@ STATIC mp_float_t yasmarang_float(void) { return u.f - 1; } -STATIC mp_obj_t mod_random_random(void) { +static mp_obj_t mod_random_random(void) { return mp_obj_new_float(yasmarang_float()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random_random_obj, mod_random_random); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_random_random_obj, mod_random_random); -STATIC mp_obj_t mod_random_uniform(mp_obj_t a_in, mp_obj_t b_in) { +static mp_obj_t mod_random_uniform(mp_obj_t a_in, mp_obj_t b_in) { mp_float_t a = mp_obj_get_float(a_in); mp_float_t b = mp_obj_get_float(b_in); return mp_obj_new_float(a + (b - a) * yasmarang_float()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_random_uniform_obj, mod_random_uniform); +static MP_DEFINE_CONST_FUN_OBJ_2(mod_random_uniform_obj, mod_random_uniform); #endif #endif // MICROPY_PY_RANDOM_EXTRA_FUNCS #if SEED_ON_IMPORT -STATIC mp_obj_t mod_random___init__(void) { +static mp_obj_t mod_random___init__(void) { // This module may be imported by more than one name so need to ensure // that it's only ever seeded once. static bool seeded = false; @@ -226,11 +226,11 @@ STATIC mp_obj_t mod_random___init__(void) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_random___init___obj, mod_random___init__); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_random___init___obj, mod_random___init__); #endif #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t mp_module_random_globals_table[] = { +static const mp_rom_map_elem_t mp_module_random_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_random) }, #if SEED_ON_IMPORT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&mod_random___init___obj) }, @@ -248,7 +248,7 @@ STATIC const mp_rom_map_elem_t mp_module_random_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_random_globals, mp_module_random_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_random_globals, mp_module_random_globals_table); const mp_obj_module_t mp_module_random = { .base = { &mp_type_module }, diff --git a/extmod/modre.c b/extmod/modre.c index d6ea1b65b7c71..36fff1d1dc668 100644 --- a/extmod/modre.c +++ b/extmod/modre.c @@ -31,7 +31,7 @@ #include "py/runtime.h" #include "py/binary.h" #include "py/objstr.h" -#include "py/stackctrl.h" +#include "py/cstack.h" #if MICROPY_PY_BUILTINS_STR_UNICODE #include "py/unicode.h" @@ -39,7 +39,7 @@ #if MICROPY_PY_RE -#define re1_5_stack_chk() MP_STACK_CHECK() +#define re1_5_stack_chk() mp_cstack_check() #include "lib/re1.5/re1.5.h" @@ -57,18 +57,18 @@ typedef struct _mp_obj_match_t { const char *caps[0]; } mp_obj_match_t; -STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args); +static mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args); #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_obj_type_t re_type; +static const mp_obj_type_t re_type; #endif -STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->num_matches); } -STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) { +static mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) { mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t no = mp_obj_get_int(no_in); if (no < 0 || no >= self->num_matches) { @@ -87,7 +87,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(match_group_obj, match_group); #if MICROPY_PY_RE_MATCH_GROUPS -STATIC mp_obj_t match_groups(mp_obj_t self_in) { +static mp_obj_t match_groups(mp_obj_t self_in) { mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in); if (self->num_matches <= 1) { return mp_const_empty_tuple; @@ -104,7 +104,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(match_groups_obj, match_groups); #if MICROPY_PY_RE_MATCH_SPAN_START_END -STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span[2]) { +static void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span[2]) { mp_obj_match_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t no = 0; @@ -141,21 +141,21 @@ STATIC void match_span_helper(size_t n_args, const mp_obj_t *args, mp_obj_t span span[1] = mp_obj_new_int(e); } -STATIC mp_obj_t match_span(size_t n_args, const mp_obj_t *args) { +static mp_obj_t match_span(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return mp_obj_new_tuple(2, span); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_span_obj, 1, 2, match_span); -STATIC mp_obj_t match_start(size_t n_args, const mp_obj_t *args) { +static mp_obj_t match_start(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return span[0]; } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_start_obj, 1, 2, match_start); -STATIC mp_obj_t match_end(size_t n_args, const mp_obj_t *args) { +static mp_obj_t match_end(size_t n_args, const mp_obj_t *args) { mp_obj_t span[2]; match_span_helper(n_args, args, span); return span[1]; @@ -165,7 +165,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(match_end_obj, 1, 2, match_end); #endif #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { +static const mp_rom_map_elem_t match_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_group), MP_ROM_PTR(&match_group_obj) }, #if MICROPY_PY_RE_MATCH_GROUPS { MP_ROM_QSTR(MP_QSTR_groups), MP_ROM_PTR(&match_groups_obj) }, @@ -177,9 +177,9 @@ STATIC const mp_rom_map_elem_t match_locals_dict_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); +static MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( match_type, MP_QSTR_match, MP_TYPE_FLAG_NONE, @@ -188,17 +188,19 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); #endif -STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self); } -STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { - (void)n_args; +// Note: this function can't be named re_exec because it may clash with system headers, eg on FreeBSD +static mp_obj_t re_exec_helper(bool is_anchored, uint n_args, const mp_obj_t *args) { mp_obj_re_t *self; + bool was_compiled = false; if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); + was_compiled = true; } else { self = MP_OBJ_TO_PTR(mod_re_compile(1, args)); } @@ -206,37 +208,28 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { size_t len; subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; - // CIRCUITPY-CHANGE - #if MICROPY_PY_RE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) - - if (n_args > 2) { - const mp_obj_type_t *self_type = mp_obj_get_type(args[1]); - mp_int_t str_len = MP_OBJ_SMALL_INT_VALUE(mp_obj_len(args[1])); - const byte *begin = (const byte *)subj.begin; - int pos = mp_obj_get_int(args[2]); - if (pos >= str_len) { - return mp_const_none; - } - if (pos < 0) { - pos = 0; + if (was_compiled && n_args > 2) { + // Arg #2 is starting-pos + mp_int_t startpos = mp_obj_get_int(args[2]); + if (startpos > (mp_int_t)len) { + startpos = len; + } else if (startpos < 0) { + startpos = 0; } - const byte *pos_ptr = str_index_to_ptr(self_type, begin, len, MP_OBJ_NEW_SMALL_INT(pos), true); - - const byte *endpos_ptr = (const byte *)subj.end; + subj.begin += startpos; if (n_args > 3) { - int endpos = mp_obj_get_int(args[3]); - if (endpos <= pos) { - return mp_const_none; + // Arg #3 is ending-pos + mp_int_t endpos = mp_obj_get_int(args[3]); + if (endpos > (mp_int_t)len) { + endpos = len; + } else if (endpos < startpos) { + endpos = startpos; } - // Will cap to length - endpos_ptr = str_index_to_ptr(self_type, begin, len, args[3], true); + subj.end = subj.begin_line + endpos; } - - subj.begin = (const char *)pos_ptr; - subj.end = (const char *)endpos_ptr; } - #endif + int caps_num = (self->re.sub + 1) * 2; mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num); // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char @@ -253,17 +246,17 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { return MP_OBJ_FROM_PTR(match); } -STATIC mp_obj_t re_match(size_t n_args, const mp_obj_t *args) { - return re_exec(true, n_args, args); +static mp_obj_t re_match(size_t n_args, const mp_obj_t *args) { + return re_exec_helper(true, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_match_obj, 2, 4, re_match); -STATIC mp_obj_t re_search(size_t n_args, const mp_obj_t *args) { - return re_exec(false, n_args, args); +static mp_obj_t re_search(size_t n_args, const mp_obj_t *args) { + return re_exec_helper(false, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search); -STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { +static mp_obj_t re_split(size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]); Subject subj; size_t len; @@ -310,7 +303,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_split_obj, 2, 3, re_split); #if MICROPY_PY_RE_SUB -STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { +static mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) { mp_obj_re_t *self; if (mp_obj_is_type(args[0], (mp_obj_type_t *)&re_type)) { self = MP_OBJ_TO_PTR(args[0]); @@ -432,7 +425,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_sub_obj, 3, 5, re_sub_helper); #endif #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { +static const mp_rom_map_elem_t re_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) }, { MP_ROM_QSTR(MP_QSTR_search), MP_ROM_PTR(&re_search_obj) }, { MP_ROM_QSTR(MP_QSTR_split), MP_ROM_PTR(&re_split_obj) }, @@ -441,9 +434,9 @@ STATIC const mp_rom_map_elem_t re_locals_dict_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); +static MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( re_type, MP_QSTR_re, MP_TYPE_FLAG_NONE, @@ -452,14 +445,17 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); #endif -STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; const char *re_str = mp_obj_str_get_str(args[0]); int size = re1_5_sizecode(re_str); if (size == -1) { + #if MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_NORMAL + mp_raise_ValueError(MP_ERROR_TEXT("regex too complex")); + #endif goto error; } - mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, (mp_obj_type_t *)&re_type); + mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, re.insts, char, size, (mp_obj_type_t *)&re_type); #if MICROPY_PY_RE_DEBUG int flags = 0; if (n_args > 1) { @@ -469,6 +465,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { int error = re1_5_compilecode(&o->re, re_str); if (error != 0) { error: + // CIRCUITPY-CHANGE: capitalized mp_raise_ValueError(MP_ERROR_TEXT("Error in regex")); } #if MICROPY_PY_RE_DEBUG @@ -481,7 +478,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile); #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = { +static const mp_rom_map_elem_t mp_module_re_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_re) }, { MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mod_re_compile_obj) }, { MP_ROM_QSTR(MP_QSTR_match), MP_ROM_PTR(&re_match_obj) }, @@ -494,7 +491,7 @@ STATIC const mp_rom_map_elem_t mp_module_re_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table); const mp_obj_module_t mp_module_re = { .base = { &mp_type_module }, diff --git a/extmod/modselect.c b/extmod/modselect.c index 7d86de3cfac3a..c4edee6a56b90 100644 --- a/extmod/modselect.c +++ b/extmod/modselect.c @@ -98,7 +98,7 @@ typedef struct _poll_set_t { #endif } poll_set_t; -STATIC void poll_set_init(poll_set_t *poll_set, size_t n) { +static void poll_set_init(poll_set_t *poll_set, size_t n) { mp_map_init(&poll_set->map, n); #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS poll_set->alloc = 0; @@ -109,19 +109,19 @@ STATIC void poll_set_init(poll_set_t *poll_set, size_t n) { } #if MICROPY_PY_SELECT_SELECT -STATIC void poll_set_deinit(poll_set_t *poll_set) { +static void poll_set_deinit(poll_set_t *poll_set) { mp_map_deinit(&poll_set->map); } #endif #if MICROPY_PY_SELECT_POSIX_OPTIMISATIONS -STATIC mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) { +static mp_uint_t poll_obj_get_events(poll_obj_t *poll_obj) { assert(poll_obj->pollfd == NULL); return poll_obj->nonfd_events; } -STATIC void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) { +static void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) { if (poll_obj->pollfd != NULL) { poll_obj->pollfd->events = events; } else { @@ -129,7 +129,7 @@ STATIC void poll_obj_set_events(poll_obj_t *poll_obj, mp_uint_t events) { } } -STATIC mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) { +static mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) { if (poll_obj->pollfd != NULL) { return poll_obj->pollfd->revents; } else { @@ -137,7 +137,7 @@ STATIC mp_uint_t poll_obj_get_revents(poll_obj_t *poll_obj) { } } -STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) { +static void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) { if (poll_obj->pollfd != NULL) { poll_obj->pollfd->revents = revents; } else { @@ -148,7 +148,7 @@ STATIC void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) { // How much (in pollfds) to grow the allocation for poll_set->pollfds by. #define POLL_SET_ALLOC_INCREMENT (4) -STATIC struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) { +static struct pollfd *poll_set_add_fd(poll_set_t *poll_set, int fd) { struct pollfd *free_slot = NULL; if (poll_set->used == poll_set->max_used) { @@ -230,7 +230,7 @@ static inline void poll_obj_set_revents(poll_obj_t *poll_obj, mp_uint_t revents) #endif -STATIC void poll_set_add_obj(poll_set_t *poll_set, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t events, bool or_events) { +static void poll_set_add_obj(poll_set_t *poll_set, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t events, bool or_events) { for (mp_uint_t i = 0; i < obj_len; i++) { mp_map_elem_t *elem = mp_map_lookup(&poll_set->map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); if (elem->value == MP_OBJ_NULL) { @@ -292,7 +292,7 @@ STATIC void poll_set_add_obj(poll_set_t *poll_set, const mp_obj_t *obj, mp_uint_ } // For each object in the poll set, poll it once. -STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) { +static mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) { mp_uint_t n_ready = 0; for (mp_uint_t i = 0; i < poll_set->map.alloc; ++i) { if (!mp_map_slot_is_filled(&poll_set->map, i)) { @@ -340,7 +340,7 @@ STATIC mp_uint_t poll_set_poll_once(poll_set_t *poll_set, size_t *rwx_num) { return n_ready; } -STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) { +static mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size_t *rwx_num, mp_uint_t timeout) { mp_uint_t start_ticks = mp_hal_ticks_ms(); bool has_timeout = timeout != (mp_uint_t)-1; @@ -421,7 +421,7 @@ STATIC mp_uint_t poll_set_poll_until_ready_or_timeout(poll_set_t *poll_set, size #if MICROPY_PY_SELECT_SELECT // select(rlist, wlist, xlist[, timeout]) -STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { +static mp_obj_t select_select(size_t n_args, const mp_obj_t *args) { // get array data from tuple/list arguments size_t rwx_len[3]; mp_obj_t *r_array, *w_array, *x_array; @@ -496,7 +496,7 @@ typedef struct _mp_obj_poll_t { } mp_obj_poll_t; // register(obj[, eventmask]) -STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { +static mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); mp_uint_t events; if (n_args == 3) { @@ -510,7 +510,7 @@ STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register); // unregister(obj) -STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { +static mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND); @@ -533,7 +533,7 @@ STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) { MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister); // modify(obj, eventmask) -STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { +static mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->poll_set.map, mp_obj_id(obj_in), MP_MAP_LOOKUP); if (elem == NULL) { @@ -544,7 +544,7 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas } MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify); -STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { +static mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); // work out timeout (its given already in ms) @@ -567,7 +567,7 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) { return poll_set_poll_until_ready_or_timeout(&self->poll_set, NULL, timeout); } -STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { +static mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); mp_uint_t n_ready = poll_poll_internal(n_args, args); @@ -588,7 +588,7 @@ STATIC mp_obj_t poll_poll(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 2, poll_poll); -STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { +static mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]); if (self->ret_tuple == MP_OBJ_NULL) { @@ -603,7 +603,7 @@ STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll); -STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { +static mp_obj_t poll_iternext(mp_obj_t self_in) { mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in); if (self->iter_cnt == 0) { @@ -635,16 +635,16 @@ STATIC mp_obj_t poll_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = { +static const mp_rom_map_elem_t poll_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) }, { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) }, { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) }, { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) }, { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); +static MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_poll, MP_QSTR_poll, MP_TYPE_FLAG_ITER_IS_ITERNEXT, @@ -653,7 +653,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); // poll() -STATIC mp_obj_t select_poll(void) { +static mp_obj_t select_poll(void) { mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll); poll_set_init(&poll->poll_set, 0); poll->iter_cnt = 0; @@ -662,7 +662,7 @@ STATIC mp_obj_t select_poll(void) { } MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll); -STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { +static const mp_rom_map_elem_t mp_module_select_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_select) }, #if MICROPY_PY_SELECT_SELECT { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) }, @@ -674,7 +674,7 @@ STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_ROM_INT(MP_STREAM_POLL_HUP) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table); const mp_obj_module_t mp_module_select = { .base = { &mp_type_module }, diff --git a/extmod/modtime.c b/extmod/modtime.c index 805c2621c0b67..ee898828a4ab1 100644 --- a/extmod/modtime.c +++ b/extmod/modtime.c @@ -52,27 +52,27 @@ // - second is 0-59 // - weekday is 0-6 for Mon-Sun // - yearday is 1-366 -STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { +static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { + timeutils_struct_time_t tm; if (n_args == 0 || args[0] == mp_const_none) { // Get current date and time. - return mp_time_localtime_get(); + mp_time_localtime_get(&tm); } else { // Convert given seconds to tuple. - mp_int_t seconds = mp_obj_get_int(args[0]); - timeutils_struct_time_t tm; + mp_timestamp_t seconds = timeutils_obj_get_timestamp(args[0]); timeutils_seconds_since_epoch_to_struct_time(seconds, &tm); - mp_obj_t tuple[8] = { - tuple[0] = mp_obj_new_int(tm.tm_year), - tuple[1] = mp_obj_new_int(tm.tm_mon), - tuple[2] = mp_obj_new_int(tm.tm_mday), - tuple[3] = mp_obj_new_int(tm.tm_hour), - tuple[4] = mp_obj_new_int(tm.tm_min), - tuple[5] = mp_obj_new_int(tm.tm_sec), - tuple[6] = mp_obj_new_int(tm.tm_wday), - tuple[7] = mp_obj_new_int(tm.tm_yday), - }; - return mp_obj_new_tuple(8, tuple); } + mp_obj_t tuple[8] = { + mp_obj_new_int(tm.tm_year), + mp_obj_new_int(tm.tm_mon), + mp_obj_new_int(tm.tm_mday), + mp_obj_new_int(tm.tm_hour), + mp_obj_new_int(tm.tm_min), + mp_obj_new_int(tm.tm_sec), + mp_obj_new_int(tm.tm_wday), + mp_obj_new_int(tm.tm_yday), + }; + return mp_obj_new_tuple(8, tuple); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_time_localtime_obj, 0, 1, time_localtime); @@ -80,7 +80,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_time_localtime_obj, 0, 1, time_localtime) // This is the inverse function of localtime. Its argument is a full 8-tuple // which expresses a time as per localtime. It returns an integer which is // the number of seconds since the Epoch (eg 1st Jan 1970, or 1st Jan 2000). -STATIC mp_obj_t time_mktime(mp_obj_t tuple) { +static mp_obj_t time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); @@ -90,7 +90,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) { mp_raise_TypeError(MP_ERROR_TEXT("mktime needs a tuple of length 8 or 9")); } - return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), + return timeutils_obj_from_timestamp(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5]))); } @@ -102,21 +102,21 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_time_mktime_obj, time_mktime); // time() // Return the number of seconds since the Epoch. -STATIC mp_obj_t time_time(void) { +static mp_obj_t time_time(void) { return mp_time_time_get(); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_obj, time_time); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_obj, time_time); // time_ns() // Returns the number of nanoseconds since the Epoch, as an integer. -STATIC mp_obj_t time_time_ns(void) { +static mp_obj_t time_time_ns(void) { return mp_obj_new_int_from_ull(mp_hal_time_ns()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_time_time_ns_obj, time_time_ns); #endif // MICROPY_PY_TIME_TIME_TIME_NS -STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { +static mp_obj_t time_sleep(mp_obj_t seconds_o) { #ifdef MICROPY_PY_TIME_CUSTOM_SLEEP mp_time_sleep(seconds_o); #else @@ -130,7 +130,7 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_obj, time_sleep); -STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { +static mp_obj_t time_sleep_ms(mp_obj_t arg) { mp_int_t ms = mp_obj_get_int(arg); if (ms >= 0) { mp_hal_delay_ms(ms); @@ -139,7 +139,7 @@ STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_ms_obj, time_sleep_ms); -STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { +static mp_obj_t time_sleep_us(mp_obj_t arg) { mp_int_t us = mp_obj_get_int(arg); if (us > 0) { mp_hal_delay_us(us); @@ -148,22 +148,22 @@ STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_time_sleep_us_obj, time_sleep_us); -STATIC mp_obj_t time_ticks_ms(void) { +static mp_obj_t time_ticks_ms(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_TIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_ms_obj, time_ticks_ms); -STATIC mp_obj_t time_ticks_us(void) { +static mp_obj_t time_ticks_us(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_TIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_us_obj, time_ticks_us); -STATIC mp_obj_t time_ticks_cpu(void) { +static mp_obj_t time_ticks_cpu(void) { return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_TIME_TICKS_PERIOD - 1)); } MP_DEFINE_CONST_FUN_OBJ_0(mp_time_ticks_cpu_obj, time_ticks_cpu); -STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) { +static mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) { // we assume that the arguments come from ticks_xx so are small ints mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in); mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in); @@ -175,7 +175,7 @@ STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) { } MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_diff_obj, time_ticks_diff); -STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { +static mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { // we assume that first argument come from ticks_xx so is small int mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in); mp_uint_t delta = mp_obj_get_int(delta_in); @@ -196,7 +196,7 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { } MP_DEFINE_CONST_FUN_OBJ_2(mp_time_ticks_add_obj, time_ticks_add); -STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { +static const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_time) }, #if MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME @@ -224,7 +224,7 @@ STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { MICROPY_PY_TIME_EXTRA_GLOBALS #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table); const mp_obj_module_t mp_module_time = { .base = { &mp_type_module }, diff --git a/extmod/moductypes.c b/extmod/moductypes.c deleted file mode 100644 index f56567107df7e..0000000000000 --- a/extmod/moductypes.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2014-2018 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -#include "py/runtime.h" -#include "py/objtuple.h" -#include "py/binary.h" - -#if MICROPY_PY_UCTYPES - -// The uctypes module allows defining the layout of a raw data structure (using -// terms of the C language), and then access memory buffers using this definition. -// The module also provides convenience functions to access memory buffers -// contained in Python objects or wrap memory buffers in Python objects. - -#define LAYOUT_LITTLE_ENDIAN (0) -#define LAYOUT_BIG_ENDIAN (1) -#define LAYOUT_NATIVE (2) - -#define VAL_TYPE_BITS 4 -#define BITF_LEN_BITS 5 -#define BITF_OFF_BITS 5 -#define OFFSET_BITS 17 -#define LEN_BITS (OFFSET_BITS + BITF_OFF_BITS) -#if VAL_TYPE_BITS + BITF_LEN_BITS + BITF_OFF_BITS + OFFSET_BITS != 31 -#error Invalid encoding field length -#endif - -enum { - UINT8, INT8, UINT16, INT16, - UINT32, INT32, UINT64, INT64, - - BFUINT8, BFINT8, BFUINT16, BFINT16, - BFUINT32, BFINT32, - - FLOAT32, FLOAT64, -}; - -#define AGG_TYPE_BITS 2 - -enum { - STRUCT, PTR, ARRAY, -}; - -// Here we need to set sign bit right -#define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1) -#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1)) -// Bit 0 is "is_signed" -#define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1)) -#define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits) - -#define IS_SCALAR_ARRAY(tuple_desc) ((tuple_desc)->len == 2) -// We cannot apply the below to INT8, as their range [-128, 127] -#define IS_SCALAR_ARRAY_OF_BYTES(tuple_desc) (GET_TYPE(MP_OBJ_SMALL_INT_VALUE((tuple_desc)->items[1]), VAL_TYPE_BITS) == UINT8) - -// "struct" in uctypes context means "structural", i.e. aggregate, type. -STATIC const mp_obj_type_t uctypes_struct_type; - -typedef struct _mp_obj_uctypes_struct_t { - mp_obj_base_t base; - mp_obj_t desc; - byte *addr; - uint32_t flags; -} mp_obj_uctypes_struct_t; - -STATIC NORETURN void syntax_error(void) { - mp_raise_TypeError(MP_ERROR_TEXT("syntax error in uctypes descriptor")); -} - -STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 2, 3, false); - mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type); - o->addr = (void *)(uintptr_t)mp_obj_get_int_truncated(args[0]); - o->desc = args[1]; - o->flags = LAYOUT_NATIVE; - if (n_args == 3) { - o->flags = mp_obj_get_int(args[2]); - } - return MP_OBJ_FROM_PTR(o); -} - -STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); - const char *typen = "unk"; - if (mp_obj_is_dict_or_ordereddict(self->desc)) { - typen = "STRUCT"; - } else if (mp_obj_is_type(self->desc, &mp_type_tuple)) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); - uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); - switch (agg_type) { - case PTR: - typen = "PTR"; - break; - case ARRAY: - typen = "ARRAY"; - break; - } - } else { - typen = "ERROR"; - } - mp_printf(print, "", typen, self->addr); -} - -// Get size of any type descriptor -STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size); - -// Get size of scalar type descriptor -static inline mp_uint_t uctypes_struct_scalar_size(int val_type) { - if (val_type == FLOAT32) { - return 4; - } else { - return GET_SCALAR_SIZE(val_type & 7); - } -} - -// Get size of aggregate type descriptor -STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_uint_t *max_field_size) { - mp_uint_t total_size = 0; - - mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]); - mp_uint_t agg_type = GET_TYPE(offset_, AGG_TYPE_BITS); - - switch (agg_type) { - case STRUCT: - return uctypes_struct_size(t->items[1], layout_type, max_field_size); - case PTR: - if (sizeof(void *) > *max_field_size) { - *max_field_size = sizeof(void *); - } - return sizeof(void *); - case ARRAY: { - mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]); - uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); - arr_sz &= VALUE_MASK(VAL_TYPE_BITS); - mp_uint_t item_s; - if (t->len == 2) { - // Elements of array are scalar - item_s = uctypes_struct_scalar_size(val_type); - if (item_s > *max_field_size) { - *max_field_size = item_s; - } - } else { - // Elements of array are aggregates - item_s = uctypes_struct_size(t->items[2], layout_type, max_field_size); - } - - return item_s * arr_sz; - } - default: - assert(0); - } - - return total_size; -} - -STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, int layout_type, mp_uint_t *max_field_size) { - if (!mp_obj_is_dict_or_ordereddict(desc_in)) { - if (mp_obj_is_type(desc_in, &mp_type_tuple)) { - return uctypes_struct_agg_size((mp_obj_tuple_t *)MP_OBJ_TO_PTR(desc_in), layout_type, max_field_size); - } else if (mp_obj_is_small_int(desc_in)) { - // We allow sizeof on both type definitions and structures/structure fields, - // but scalar structure field is lowered into native Python int, so all - // type info is lost. So, we cannot say if it's scalar type description, - // or such lowered scalar. - mp_raise_TypeError(MP_ERROR_TEXT("can't unambiguously get sizeof scalar")); - } - syntax_error(); - } - - mp_obj_dict_t *d = MP_OBJ_TO_PTR(desc_in); - mp_uint_t total_size = 0; - - for (mp_uint_t i = 0; i < d->map.alloc; i++) { - if (mp_map_slot_is_filled(&d->map, i)) { - mp_obj_t v = d->map.table[i].value; - if (mp_obj_is_small_int(v)) { - mp_uint_t offset = MP_OBJ_SMALL_INT_VALUE(v); - mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS); - offset &= VALUE_MASK(VAL_TYPE_BITS); - if (val_type >= BFUINT8 && val_type <= BFINT32) { - offset &= (1 << OFFSET_BITS) - 1; - } - mp_uint_t s = uctypes_struct_scalar_size(val_type); - if (s > *max_field_size) { - *max_field_size = s; - } - if (offset + s > total_size) { - total_size = offset + s; - } - } else { - if (!mp_obj_is_type(v, &mp_type_tuple)) { - syntax_error(); - } - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(v); - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); - offset &= VALUE_MASK(AGG_TYPE_BITS); - mp_uint_t s = uctypes_struct_agg_size(t, layout_type, max_field_size); - if (offset + s > total_size) { - total_size = offset + s; - } - } - } - } - - // Round size up to alignment of biggest field - if (layout_type == LAYOUT_NATIVE) { - total_size = (total_size + *max_field_size - 1) & ~(*max_field_size - 1); - } - return total_size; -} - -STATIC mp_obj_t uctypes_struct_sizeof(size_t n_args, const mp_obj_t *args) { - mp_obj_t obj_in = args[0]; - mp_uint_t max_field_size = 0; - if (mp_obj_is_type(obj_in, &mp_type_bytearray)) { - return mp_obj_len(obj_in); - } - int layout_type = LAYOUT_NATIVE; - // We can apply sizeof either to structure definition (a dict) - // or to instantiated structure - if (mp_obj_is_type(obj_in, &uctypes_struct_type)) { - if (n_args != 1) { - mp_raise_TypeError(NULL); - } - // Extract structure definition - mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in); - obj_in = obj->desc; - layout_type = obj->flags; - } else { - if (n_args == 2) { - layout_type = mp_obj_get_int(args[1]); - } - } - mp_uint_t size = uctypes_struct_size(obj_in, layout_type, &max_field_size); - return MP_OBJ_NEW_SMALL_INT(size); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(uctypes_struct_sizeof_obj, 1, 2, uctypes_struct_sizeof); - -static inline mp_obj_t get_unaligned(uint val_type, byte *p, int big_endian) { - char struct_type = big_endian ? '>' : '<'; - static const char type2char[16] = "BbHhIiQq------fd"; - return mp_binary_get_val(struct_type, type2char[val_type], p, &p); -} - -static inline void set_unaligned(uint val_type, byte *p, int big_endian, mp_obj_t val) { - char struct_type = big_endian ? '>' : '<'; - static const char type2char[16] = "BbHhIiQq------fd"; - mp_binary_set_val(struct_type, type2char[val_type], val, p, &p); -} - -static inline mp_uint_t get_aligned_basic(uint val_type, void *p) { - switch (val_type) { - case UINT8: - return *(uint8_t *)p; - case UINT16: - return *(uint16_t *)p; - case UINT32: - return *(uint32_t *)p; - } - assert(0); - return 0; -} - -static inline void set_aligned_basic(uint val_type, void *p, mp_uint_t v) { - switch (val_type) { - case UINT8: - *(uint8_t *)p = (uint8_t)v; - return; - case UINT16: - *(uint16_t *)p = (uint16_t)v; - return; - case UINT32: - *(uint32_t *)p = (uint32_t)v; - return; - } - assert(0); -} - -STATIC mp_obj_t get_aligned(uint val_type, void *p, mp_int_t index) { - switch (val_type) { - case UINT8: - return MP_OBJ_NEW_SMALL_INT(((uint8_t *)p)[index]); - case INT8: - return MP_OBJ_NEW_SMALL_INT(((int8_t *)p)[index]); - case UINT16: - return MP_OBJ_NEW_SMALL_INT(((uint16_t *)p)[index]); - case INT16: - return MP_OBJ_NEW_SMALL_INT(((int16_t *)p)[index]); - case UINT32: - return mp_obj_new_int_from_uint(((uint32_t *)p)[index]); - case INT32: - return mp_obj_new_int(((int32_t *)p)[index]); - case UINT64: - return mp_obj_new_int_from_ull(((uint64_t *)p)[index]); - case INT64: - return mp_obj_new_int_from_ll(((int64_t *)p)[index]); - #if MICROPY_PY_BUILTINS_FLOAT - case FLOAT32: - return mp_obj_new_float_from_f(((float *)p)[index]); - case FLOAT64: - return mp_obj_new_float_from_d(((double *)p)[index]); - #endif - default: - assert(0); - return MP_OBJ_NULL; - } -} - -STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) { - #if MICROPY_PY_BUILTINS_FLOAT - if (val_type == FLOAT32 || val_type == FLOAT64) { - if (val_type == FLOAT32) { - ((float *)p)[index] = mp_obj_get_float_to_f(val); - } else { - ((double *)p)[index] = mp_obj_get_float_to_d(val); - } - return; - } - #endif - mp_int_t v = mp_obj_get_int_truncated(val); - switch (val_type) { - case UINT8: - ((uint8_t *)p)[index] = (uint8_t)v; - return; - case INT8: - ((int8_t *)p)[index] = (int8_t)v; - return; - case UINT16: - ((uint16_t *)p)[index] = (uint16_t)v; - return; - case INT16: - ((int16_t *)p)[index] = (int16_t)v; - return; - case UINT32: - ((uint32_t *)p)[index] = (uint32_t)v; - return; - case INT32: - ((int32_t *)p)[index] = (int32_t)v; - return; - case INT64: - case UINT64: - if (sizeof(mp_int_t) == 8) { - ((uint64_t *)p)[index] = (uint64_t)v; - } else { - // TODO: Doesn't offer atomic store semantics, but should at least try - set_unaligned(val_type, (void *)&((uint64_t *)p)[index], MP_ENDIANNESS_BIG, val); - } - return; - default: - assert(0); - } -} - -STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) { - mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); - - if (!mp_obj_is_dict_or_ordereddict(self->desc)) { - mp_raise_TypeError(MP_ERROR_TEXT("struct: no fields")); - } - - mp_obj_t deref = mp_obj_dict_get(self->desc, MP_OBJ_NEW_QSTR(attr)); - if (mp_obj_is_small_int(deref)) { - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref); - mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS); - offset &= VALUE_MASK(VAL_TYPE_BITS); - - if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) { - if (self->flags == LAYOUT_NATIVE) { - if (set_val == MP_OBJ_NULL) { - return get_aligned(val_type, self->addr + offset, 0); - } else { - set_aligned(val_type, self->addr + offset, 0, set_val); - return set_val; // just !MP_OBJ_NULL - } - } else { - if (set_val == MP_OBJ_NULL) { - return get_unaligned(val_type, self->addr + offset, self->flags); - } else { - set_unaligned(val_type, self->addr + offset, self->flags, set_val); - return set_val; // just !MP_OBJ_NULL - } - } - } else if (val_type >= BFUINT8 && val_type <= BFINT32) { - uint bit_offset = (offset >> OFFSET_BITS) & 31; - uint bit_len = (offset >> LEN_BITS) & 31; - offset &= (1 << OFFSET_BITS) - 1; - mp_uint_t val; - if (self->flags == LAYOUT_NATIVE) { - val = get_aligned_basic(val_type & 6, self->addr + offset); - } else { - val = mp_binary_get_int(GET_SCALAR_SIZE(val_type & 7), val_type & 1, self->flags, self->addr + offset); - } - if (set_val == MP_OBJ_NULL) { - val >>= bit_offset; - val &= (1 << bit_len) - 1; - // TODO: signed - assert((val_type & 1) == 0); - return mp_obj_new_int(val); - } else { - mp_uint_t set_val_int = (mp_uint_t)mp_obj_get_int(set_val); - mp_uint_t mask = (1 << bit_len) - 1; - set_val_int &= mask; - set_val_int <<= bit_offset; - mask <<= bit_offset; - val = (val & ~mask) | set_val_int; - - if (self->flags == LAYOUT_NATIVE) { - set_aligned_basic(val_type & 6, self->addr + offset, val); - } else { - mp_binary_set_int(GET_SCALAR_SIZE(val_type & 7), self->flags == LAYOUT_BIG_ENDIAN, - self->addr + offset, val); - } - return set_val; // just !MP_OBJ_NULL - } - } - - assert(0); - return MP_OBJ_NULL; - } - - if (!mp_obj_is_type(deref, &mp_type_tuple)) { - syntax_error(); - } - - if (set_val != MP_OBJ_NULL) { - // Cannot assign to aggregate - syntax_error(); - } - - mp_obj_tuple_t *sub = MP_OBJ_TO_PTR(deref); - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]); - mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS); - offset &= VALUE_MASK(AGG_TYPE_BITS); - - switch (agg_type) { - case STRUCT: { - mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type); - o->desc = sub->items[1]; - o->addr = self->addr + offset; - o->flags = self->flags; - return MP_OBJ_FROM_PTR(o); - } - case ARRAY: { - mp_uint_t dummy; - if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) { - return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, self->flags, &dummy), self->addr + offset); - } - // Fall thru to return uctypes struct object - MP_FALLTHROUGH - } - case PTR: { - mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type); - o->desc = MP_OBJ_FROM_PTR(sub); - o->addr = self->addr + offset; - o->flags = self->flags; - return MP_OBJ_FROM_PTR(o); - } - } - - // Should be unreachable once all cases are handled - return MP_OBJ_NULL; -} - -STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - if (dest[0] == MP_OBJ_NULL) { - // load attribute - mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL); - dest[0] = val; - } else { - // delete/store attribute - if (uctypes_struct_attr_op(self_in, attr, dest[1]) != MP_OBJ_NULL) { - dest[0] = MP_OBJ_NULL; // indicate success - } - } -} - -STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { - mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); - - if (value == MP_OBJ_NULL) { - // delete - return MP_OBJ_NULL; // op not supported - } else { - // load / store - if (!mp_obj_is_type(self->desc, &mp_type_tuple)) { - mp_raise_TypeError(MP_ERROR_TEXT("struct: can't index")); - } - - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); - uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); - - mp_int_t index = MP_OBJ_SMALL_INT_VALUE(index_in); - - if (agg_type == ARRAY) { - mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]); - uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS); - arr_sz &= VALUE_MASK(VAL_TYPE_BITS); - if (index >= arr_sz) { - mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("struct: index out of range")); - } - - if (t->len == 2) { - // array of scalars - if (self->flags == LAYOUT_NATIVE) { - if (value == MP_OBJ_SENTINEL) { - return get_aligned(val_type, self->addr, index); - } else { - set_aligned(val_type, self->addr, index, value); - return value; // just !MP_OBJ_NULL - } - } else { - byte *p = self->addr + uctypes_struct_scalar_size(val_type) * index; - if (value == MP_OBJ_SENTINEL) { - return get_unaligned(val_type, p, self->flags); - } else { - set_unaligned(val_type, p, self->flags, value); - return value; // just !MP_OBJ_NULL - } - } - } else if (value == MP_OBJ_SENTINEL) { - mp_uint_t dummy = 0; - mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy); - mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type); - o->desc = t->items[2]; - o->addr = self->addr + size * index; - o->flags = self->flags; - return MP_OBJ_FROM_PTR(o); - } else { - return MP_OBJ_NULL; // op not supported - } - - } else if (agg_type == PTR) { - byte *p = *(void **)self->addr; - if (mp_obj_is_small_int(t->items[1])) { - uint val_type = GET_TYPE(MP_OBJ_SMALL_INT_VALUE(t->items[1]), VAL_TYPE_BITS); - return get_aligned(val_type, p, index); - } else { - mp_uint_t dummy = 0; - mp_uint_t size = uctypes_struct_size(t->items[1], self->flags, &dummy); - mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type); - o->desc = t->items[1]; - o->addr = p + size * index; - o->flags = self->flags; - return MP_OBJ_FROM_PTR(o); - } - } - - assert(0); - return MP_OBJ_NULL; - } -} - -STATIC mp_obj_t uctypes_struct_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); - switch (op) { - case MP_UNARY_OP_INT_MAYBE: - if (mp_obj_is_type(self->desc, &mp_type_tuple)) { - mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc); - mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]); - uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS); - if (agg_type == PTR) { - byte *p = *(void **)self->addr; - return mp_obj_new_int((mp_int_t)(uintptr_t)p); - } - } - MP_FALLTHROUGH - - default: - return MP_OBJ_NULL; // op not supported - } -} - -STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { - (void)flags; - mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in); - mp_uint_t max_field_size = 0; - mp_uint_t size = uctypes_struct_size(self->desc, self->flags, &max_field_size); - - bufinfo->buf = self->addr; - bufinfo->len = size; - bufinfo->typecode = BYTEARRAY_TYPECODE; - return 0; -} - -// addressof() -// Return address of object's data (applies to objects providing the buffer interface). -STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - return mp_obj_new_int((mp_int_t)(uintptr_t)bufinfo.buf); -} -MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof); - -// bytearray_at() -// Capture memory at given address of given size as bytearray. -STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) { - return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void *)(uintptr_t)mp_obj_int_get_truncated(ptr)); -} -MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at); - -// bytes_at() -// Capture memory at given address of given size as bytes. -STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) { - return mp_obj_new_bytes((void *)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size)); -} -MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at); - -STATIC MP_DEFINE_CONST_OBJ_TYPE( - uctypes_struct_type, - MP_QSTR_struct, - MP_TYPE_FLAG_NONE, - make_new, uctypes_struct_make_new, - print, uctypes_struct_print, - attr, uctypes_struct_attr, - subscr, uctypes_struct_subscr, - unary_op, uctypes_struct_unary_op, - buffer, uctypes_get_buffer - ); - -STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uctypes) }, - { MP_ROM_QSTR(MP_QSTR_struct), MP_ROM_PTR(&uctypes_struct_type) }, - { MP_ROM_QSTR(MP_QSTR_sizeof), MP_ROM_PTR(&uctypes_struct_sizeof_obj) }, - { MP_ROM_QSTR(MP_QSTR_addressof), MP_ROM_PTR(&uctypes_struct_addressof_obj) }, - { MP_ROM_QSTR(MP_QSTR_bytes_at), MP_ROM_PTR(&uctypes_struct_bytes_at_obj) }, - { MP_ROM_QSTR(MP_QSTR_bytearray_at), MP_ROM_PTR(&uctypes_struct_bytearray_at_obj) }, - - { MP_ROM_QSTR(MP_QSTR_NATIVE), MP_ROM_INT(LAYOUT_NATIVE) }, - { MP_ROM_QSTR(MP_QSTR_LITTLE_ENDIAN), MP_ROM_INT(LAYOUT_LITTLE_ENDIAN) }, - { MP_ROM_QSTR(MP_QSTR_BIG_ENDIAN), MP_ROM_INT(LAYOUT_BIG_ENDIAN) }, - - { MP_ROM_QSTR(MP_QSTR_VOID), MP_ROM_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) }, - - { MP_ROM_QSTR(MP_QSTR_UINT8), MP_ROM_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_INT8), MP_ROM_INT(TYPE2SMALLINT(INT8, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_UINT16), MP_ROM_INT(TYPE2SMALLINT(UINT16, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_INT16), MP_ROM_INT(TYPE2SMALLINT(INT16, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_UINT32), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_INT32), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_UINT64), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_INT64), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) }, - - { MP_ROM_QSTR(MP_QSTR_BFUINT8), MP_ROM_INT(TYPE2SMALLINT(BFUINT8, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_BFINT8), MP_ROM_INT(TYPE2SMALLINT(BFINT8, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_BFUINT16), MP_ROM_INT(TYPE2SMALLINT(BFUINT16, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_BFINT16), MP_ROM_INT(TYPE2SMALLINT(BFINT16, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_BFUINT32), MP_ROM_INT(TYPE2SMALLINT(BFUINT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_BFINT32), MP_ROM_INT(TYPE2SMALLINT(BFINT32, VAL_TYPE_BITS)) }, - - { MP_ROM_QSTR(MP_QSTR_BF_POS), MP_ROM_INT(OFFSET_BITS) }, - { MP_ROM_QSTR(MP_QSTR_BF_LEN), MP_ROM_INT(LEN_BITS) }, - - #if MICROPY_PY_BUILTINS_FLOAT - { MP_ROM_QSTR(MP_QSTR_FLOAT32), MP_ROM_INT(TYPE2SMALLINT(FLOAT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, VAL_TYPE_BITS)) }, - #endif - - #if MICROPY_PY_UCTYPES_NATIVE_C_TYPES - // C native type aliases. These depend on GCC-compatible predefined - // preprocessor macros. - #if __SIZEOF_SHORT__ == 2 - { MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, VAL_TYPE_BITS)) }, - #endif - #if __SIZEOF_INT__ == 4 - { MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) }, - #endif - #if __SIZEOF_LONG__ == 4 - { MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) }, - #elif __SIZEOF_LONG__ == 8 - { MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) }, - #endif - #if __SIZEOF_LONG_LONG__ == 8 - { MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) }, - #endif - #endif // MICROPY_PY_UCTYPES_NATIVE_C_TYPES - - { MP_ROM_QSTR(MP_QSTR_PTR), MP_ROM_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) }, - { MP_ROM_QSTR(MP_QSTR_ARRAY), MP_ROM_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) }, -}; -STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals_table); - -const mp_obj_module_t mp_module_uctypes = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t *)&mp_module_uctypes_globals, -}; - -// uctypes is not a Python standard library module (hence "uctypes" -// not "ctypes") and therefore shouldn't be extensible. -MP_REGISTER_MODULE(MP_QSTR_uctypes, mp_module_uctypes); - -#endif diff --git a/extmod/modzlib.c b/extmod/modzlib.c index 3984647a5d7ac..10b656a469d2d 100644 --- a/extmod/modzlib.c +++ b/extmod/modzlib.c @@ -1,3 +1,5 @@ +// CIRCUITPY-CHANGE: This module was removed from MicroPython but CircuitPython still uses it. + /* * This file is part of the MicroPython project, http://micropython.org/ * @@ -49,7 +51,7 @@ typedef struct _mp_obj_decompio_t { bool eof; } mp_obj_decompio_t; -STATIC int read_src_stream(TINF_DATA *data) { +static int read_src_stream(TINF_DATA *data) { byte *p = (void *)data; p -= offsetof(mp_obj_decompio_t, decomp); mp_obj_decompio_t *self = (mp_obj_decompio_t *)p; @@ -67,7 +69,7 @@ STATIC int read_src_stream(TINF_DATA *data) { return c; } -STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_get_stream_raise(args[0], MP_STREAM_OP_READ); mp_obj_decompio_t *o = mp_obj_malloc(mp_obj_decompio_t, type); @@ -106,7 +108,7 @@ STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size return MP_OBJ_FROM_PTR(o); } -STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in); if (o->eof) { return 0; @@ -127,21 +129,21 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er } #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { +static const mp_rom_map_elem_t decompio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); +static MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); #endif -STATIC const mp_stream_p_t decompio_stream_p = { +static const mp_stream_p_t decompio_stream_p = { .read = decompio_read, }; #if !MICROPY_ENABLE_DYNRUNTIME -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( decompio_type, MP_QSTR_DecompIO, MP_TYPE_FLAG_NONE, @@ -151,7 +153,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); #endif -STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { mp_obj_t data = args[0]; mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); @@ -213,16 +215,16 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) { error: mp_raise_type_arg(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress); #if !MICROPY_ENABLE_DYNRUNTIME -STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = { +static const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) }, { MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) }, { MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table); const mp_obj_module_t mp_module_uzlib = { .base = { &mp_type_module }, diff --git a/extmod/ulab b/extmod/ulab index eacb0c9af47f8..1d3ddd8f5228e 160000 --- a/extmod/ulab +++ b/extmod/ulab @@ -1 +1 @@ -Subproject commit eacb0c9af47f85f5d4864b721c3b28661364e8e3 +Subproject commit 1d3ddd8f5228e2c7335dac71f4846e6abb0ec9f9 diff --git a/extmod/vfs.c b/extmod/vfs.c index 21dbac5c2bfcc..c4156990bcc38 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -42,11 +42,15 @@ #include "extmod/vfs_lfs.h" #endif -// CIRCUITPY-CHANGE: handle undefined without a warning -#if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX +#if MICROPY_VFS_POSIX #include "extmod/vfs_posix.h" #endif + +#if CIRCUITPY_SDCARDIO +#include "shared-module/sdcardio/__init__.h" +#endif + // For mp_vfs_proxy_call, the maximum number of additional args that can be passed. // A fixed maximum size is used to avoid the need for a costly variable array. #define PROXY_MAX_ARGS (2) @@ -67,6 +71,10 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) { // path is "" or "/" so return virtual root return MP_VFS_ROOT; } + // CIRCUITPY-CHANGE: Try and automount the SD card. + #if CIRCUITPY_SDCARDIO + automount_sd_card(); + #endif for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { size_t len = vfs->len - 1; if (len == 0) { @@ -93,8 +101,8 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) { return MP_STATE_VM(vfs_cur); } -// Version of mp_vfs_lookup_path that takes and returns uPy string objects. -STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { +// Version of mp_vfs_lookup_path that takes and returns MicroPython string objects. +static mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { const char *path = mp_obj_str_get_str(path_in); const char *p_out; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out); @@ -107,7 +115,7 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { return vfs; } -STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { assert(n_args <= PROXY_MAX_ARGS); if (vfs == MP_VFS_NONE) { // mount point not found @@ -140,7 +148,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } // delegate to vfs.stat() method - mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out)); + mp_obj_t path_o = mp_obj_new_str_from_cstr(path_out); mp_obj_t stat; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { @@ -160,7 +168,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } } -STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { +static mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { #if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2 nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { @@ -203,22 +211,36 @@ STATIC mp_obj_t mp_vfs_autodetect(mp_obj_t bdev_obj) { } mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_readonly, ARG_mkfs }; + if (n_args == 0) { + // zero-args, output a table of all current mountpoints + mp_obj_t mount_list = mp_obj_new_list(0, NULL); + mp_vfs_mount_t *vfsp = MP_STATE_VM(vfs_mount_table); + while (vfsp != NULL) { + mp_obj_t items[] = { vfsp->obj, mp_obj_new_str(vfsp->str, vfsp->len) }; + mp_obj_list_append(mount_list, mp_obj_new_tuple(MP_ARRAY_SIZE(items), items)); + vfsp = vfsp->next; + } + return mount_list; + } + + enum { ARG_fsobj, ARG_mount_point, ARG_readonly, ARG_mkfs }; static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} }, { MP_QSTR_mkfs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_FALSE} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // get the mount point size_t mnt_len; - const char *mnt_str = mp_obj_str_get_data(pos_args[1], &mnt_len); + const char *mnt_str = mp_obj_str_get_data(args[ARG_mount_point].u_obj, &mnt_len); // see if we need to auto-detect and create the filesystem - mp_obj_t vfs_obj = pos_args[0]; + mp_obj_t vfs_obj = args[ARG_fsobj].u_obj; mp_obj_t dest[2]; mp_load_method_maybe(vfs_obj, MP_QSTR_mount, dest); if (dest[0] == MP_OBJ_NULL) { @@ -235,11 +257,13 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args vfs->next = NULL; // call the underlying object to do any mounting operation - mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t *)&args); + mp_arg_val_t *proxy_args = &args[ARG_readonly]; + size_t proxy_args_len = MP_ARRAY_SIZE(args) - ARG_readonly; + mp_vfs_proxy_call(vfs, MP_QSTR_mount, proxy_args_len, (mp_obj_t *)proxy_args); // check that the destination mount point is unused const char *path_out; - mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(mp_obj_str_get_str(pos_args[1]), &path_out); + mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(mp_obj_str_get_str(args[ARG_mount_point].u_obj), &path_out); if (existing_mount != MP_VFS_NONE && existing_mount != MP_VFS_ROOT) { if (vfs->len != 1 && existing_mount->len == 1) { // if root dir is mounted, still allow to mount something within a subdir of root @@ -263,7 +287,7 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj, 2, mp_vfs_mount); +MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj, 0, mp_vfs_mount); mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) { // remove vfs from the mount table @@ -274,7 +298,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) { mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len); } for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { - if ((mnt_str != NULL && !memcmp(mnt_str, (*vfsp)->str, mnt_len + 1)) || (*vfsp)->obj == mnt_in) { + if ((mnt_str != NULL && mnt_len == (*vfsp)->len && !memcmp(mnt_str, (*vfsp)->str, mnt_len)) || (*vfsp)->obj == mnt_in) { vfs = *vfsp; *vfsp = (*vfsp)->next; break; @@ -311,8 +335,7 @@ mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // CIRCUITPY-CHANGE: handle undefined without a warning - #if defined(MICROPY_VFS_POSIX) && MICROPY_VFS_POSIX + #if MICROPY_VFS_POSIX // If the file is an integer then delegate straight to the POSIX handler if (mp_obj_is_small_int(args[ARG_file].u_obj)) { return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, args[ARG_file].u_obj, args[ARG_mode].u_obj); @@ -367,8 +390,18 @@ mp_obj_t mp_vfs_getcwd(void) { } MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd); -// CIRCUITPY-CHANGE: accessible from shared-module/os/__init__.c -mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) { +typedef struct _mp_vfs_ilistdir_it_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + union { + mp_vfs_mount_t *vfs; + mp_obj_t iter; + } cur; + bool is_str; + bool is_iter; +} mp_vfs_ilistdir_it_t; + +static mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) { mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->is_iter) { // continue delegating to root dir @@ -435,6 +468,8 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir); +#if MICROPY_VFS_WRITABLE + mp_obj_t mp_vfs_mkdir(mp_obj_t path_in) { // CIRCUITPY-CHANGE: initialize mp_obj_t path_out = mp_const_none; @@ -472,6 +507,8 @@ mp_obj_t mp_vfs_rmdir(mp_obj_t path_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj, mp_vfs_rmdir); +#endif // MICROPY_VFS_WRITABLE + mp_obj_t mp_vfs_stat(mp_obj_t path_in) { mp_obj_t path_out; mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out); @@ -541,6 +578,32 @@ int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point) { return ret; } +#if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL + +int mp_vfs_mount_romfs_protected(void) { + int ret; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(MP_VFS_ROM_IOCTL_GET_SEGMENT), MP_OBJ_NEW_SMALL_INT(0) }; + mp_obj_t rom = mp_vfs_rom_ioctl(2, args); + mp_obj_t romfs = mp_call_function_1(MP_OBJ_FROM_PTR(&mp_type_vfs_rom), rom); + mp_obj_t mount_point = MP_OBJ_NEW_QSTR(MP_QSTR__slash_rom); + mp_call_function_2(MP_OBJ_FROM_PTR(&mp_vfs_mount_obj), romfs, mount_point); + #if MICROPY_PY_SYS_PATH_ARGV_DEFAULTS + // Add "/rom" and "/rom/lib" to `sys.path`. + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_rom)); + mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_rom_slash_lib)); + #endif + ret = 0; // success + nlr_pop(); + } else { + ret = -MP_EIO; + } + return ret; +} + +#endif + MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_cur); MP_REGISTER_ROOT_POINTER(struct _mp_vfs_mount_t *vfs_mount_table); diff --git a/extmod/vfs.h b/extmod/vfs.h index c6c471d476c0f..699232e56cd87 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -52,6 +52,8 @@ #define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020) // Bit set when something has claimed the right to mutate the blockdev. #define MP_BLOCKDEV_FLAG_LOCKED (0x0040) +// Ignore write protections. Used to override other flags temporarily. +#define MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION (0x0080) // constants for block protocol ioctl #define MP_BLOCKDEV_IOCTL_INIT (1) @@ -61,6 +63,13 @@ #define MP_BLOCKDEV_IOCTL_BLOCK_SIZE (5) #define MP_BLOCKDEV_IOCTL_BLOCK_ERASE (6) +// Constants for vfs.rom_ioctl() function. +#define MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS (1) // rom_ioctl(1) +#define MP_VFS_ROM_IOCTL_GET_SEGMENT (2) // rom_ioctl(2, ) +#define MP_VFS_ROM_IOCTL_WRITE_PREPARE (3) // rom_ioctl(3, , ) +#define MP_VFS_ROM_IOCTL_WRITE (4) // rom_ioctl(4, , , ) +#define MP_VFS_ROM_IOCTL_WRITE_COMPLETE (5) // rom_ioctl(5, ) + // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { // CIRCUITPY-CHANGE @@ -71,6 +80,10 @@ typedef struct _mp_vfs_proto_t { typedef struct _mp_vfs_blockdev_t { uint16_t flags; size_t block_size; + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + size_t offset; + int size; + #endif mp_obj_t readblocks[5]; mp_obj_t writeblocks[5]; // new protocol uses just ioctl, old uses sync (optional) and count @@ -90,19 +103,6 @@ typedef struct _mp_vfs_mount_t { struct _mp_vfs_mount_t *next; } mp_vfs_mount_t; -// CIRCUITPY-CHANGE: allow outside use of ilistdir_it_iternext -typedef struct _mp_vfs_ilistdir_it_t { - mp_obj_base_t base; - mp_fun_1_t iternext; - union { - mp_vfs_mount_t *vfs; - mp_obj_t iter; - } cur; - bool is_str; - bool is_iter; -} mp_vfs_ilistdir_it_t; - -mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in); void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev); int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf); int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf); @@ -119,14 +119,19 @@ mp_obj_t mp_vfs_chdir(mp_obj_t path_in); mp_obj_t mp_vfs_getcwd(void); mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args); mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args); +#if MICROPY_VFS_WRITABLE mp_obj_t mp_vfs_mkdir(mp_obj_t path_in); mp_obj_t mp_vfs_remove(mp_obj_t path_in); mp_obj_t mp_vfs_rename(mp_obj_t old_path_in, mp_obj_t new_path_in); mp_obj_t mp_vfs_rmdir(mp_obj_t path_in); +#endif mp_obj_t mp_vfs_stat(mp_obj_t path_in); mp_obj_t mp_vfs_statvfs(mp_obj_t path_in); int mp_vfs_mount_and_chdir_protected(mp_obj_t bdev, mp_obj_t mount_point); +#if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL +int mp_vfs_mount_romfs_protected(void); +#endif MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_umount_obj); @@ -135,11 +140,21 @@ MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj); +#if MICROPY_VFS_WRITABLE MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_remove_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_vfs_rename_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_rmdir_obj); +#endif MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_stat_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_statvfs_obj); +#if MICROPY_VFS_ROM_IOCTL +// When MICROPY_VFS_ROM_IOCTL is enabled a port must define the following function. +// This is a generic interface to allow querying and modifying the user-accessible, +// read-only memory area of a device, if it is configured with such an area. +// Supported ioctl commands are given by MP_VFS_ROM_IOCTL_xxx. +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args); +#endif + #endif // MICROPY_INCLUDED_EXTMOD_VFS_H diff --git a/extmod/vfs_blockdev.c b/extmod/vfs_blockdev.c index eda5cecc147a9..74d1262364ef4 100644 --- a/extmod/vfs_blockdev.c +++ b/extmod/vfs_blockdev.c @@ -63,7 +63,16 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) { #endif #if CIRCUITPY_SDIOIO if (mp_obj_get_type(bdev) == &sdioio_SDCard_type) { - // TODO: Enable native blockdev for SDIO too. + self->flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; + self->readblocks[0] = mp_const_none; + self->readblocks[1] = bdev; + self->readblocks[2] = (mp_obj_t)sdioio_sdcard_readblocks; // native version + self->writeblocks[0] = mp_const_none; + self->writeblocks[1] = bdev; + self->writeblocks[2] = (mp_obj_t)sdioio_sdcard_writeblocks; // native version + self->u.ioctl[0] = mp_const_none; + self->u.ioctl[1] = bdev; + self->u.ioctl[2] = (mp_obj_t)sdioio_sdcard_ioctl; // native version } #endif if (self->u.ioctl[0] != MP_OBJ_NULL) { @@ -76,6 +85,34 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) { } } +// Helper function to minimise code size of read/write functions +// note the n_args argument is moved to the end for further code size reduction (args keep same position in caller and callee). +static int mp_vfs_blockdev_call_rw(mp_obj_t *args, size_t block_num, size_t block_off, size_t len, void *buf, size_t n_args) { + mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf}; + args[2] = MP_OBJ_NEW_SMALL_INT(block_num); + args[3] = MP_OBJ_FROM_PTR(&ar); + args[4] = MP_OBJ_NEW_SMALL_INT(block_off); // ignored for n_args == 2 + mp_obj_t ret = mp_call_method_n_kw(n_args, 0, args); + + if (ret == mp_const_none) { + return 0; + } else { + // Some block devices return a bool indicating success, so + // convert those to an errno integer code. + if (ret == mp_const_true) { + return 0; + } else if (ret == mp_const_false) { + return -MP_EIO; + } + // Block device functions are expected to return 0 on success + // and negative integer on errors. Check for positive integer + // results as some callers (i.e. littlefs) will produce corrupt + // results from these. + int i = mp_obj_get_int(ret); + return i > 0 ? (-MP_EINVAL) : i; + } +} + int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) { if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) { // CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so @@ -83,26 +120,12 @@ int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_b mp_uint_t (*f)(mp_obj_t self, uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2]; return f(self->readblocks[1], buf, block_num, num_blocks); } else { - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf}; - self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); - self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, self->readblocks); - // TODO handle error return - return 0; + return mp_vfs_blockdev_call_rw(self->readblocks, block_num, 0, num_blocks * self->block_size, buf, 2); } } int mp_vfs_blockdev_read_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t block_off, size_t len, uint8_t *buf) { - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, buf}; - self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); - self->readblocks[3] = MP_OBJ_FROM_PTR(&ar); - self->readblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); - mp_obj_t ret = mp_call_method_n_kw(3, 0, self->readblocks); - if (ret == mp_const_none) { - return 0; - } else { - return MP_OBJ_SMALL_INT_VALUE(ret); - } + return mp_vfs_blockdev_call_rw(self->readblocks, block_num, block_off, len, buf, 3); } int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, const uint8_t *buf) { @@ -117,12 +140,7 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_ mp_uint_t (*f)(mp_obj_t self, const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2]; return f(self->writeblocks[1], buf, block_num, num_blocks); } else { - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf}; - self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); - self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); - mp_call_method_n_kw(2, 0, self->writeblocks); - // TODO handle error return - return 0; + return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, 0, num_blocks * self->block_size, (void *)buf, 2); } } @@ -131,17 +149,7 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t // read-only block device return -MP_EROFS; } - - mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, len, (void *)buf}; - self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num); - self->writeblocks[3] = MP_OBJ_FROM_PTR(&ar); - self->writeblocks[4] = MP_OBJ_NEW_SMALL_INT(block_off); - mp_obj_t ret = mp_call_method_n_kw(3, 0, self->writeblocks); - if (ret == mp_const_none) { - return 0; - } else { - return MP_OBJ_SMALL_INT_VALUE(ret); - } + return mp_vfs_blockdev_call_rw(self->writeblocks, block_num, block_off, len, (void *)buf, 3); } mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) { diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index ee0b8eb735bd4..95ed79eb18bd5 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -38,6 +38,7 @@ // CIRCUITPY-CHANGE: extra includes #include +#include "py/gc.h" #include "py/obj.h" #include "py/objproperty.h" #include "py/runtime.h" @@ -57,11 +58,11 @@ // CIRCUITPY-CHANGE // Factoring this common call saves about 90 bytes. -STATIC NORETURN void mp_raise_OSError_fresult(FRESULT res) { +static MP_NORETURN void mp_raise_OSError_fresult(FRESULT res) { mp_raise_OSError(fresult_to_errno_table[res]); } -STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) { +static mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) { fs_user_mount_t *vfs = vfs_in; FILINFO fno; assert(vfs != NULL); @@ -76,7 +77,7 @@ STATIC mp_import_stat_t fat_vfs_import_stat(void *vfs_in, const char *path) { return MP_IMPORT_STAT_NO_EXIST; } -STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); // create new object @@ -102,23 +103,23 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_ } // CIRCUITPY-CHANGE -STATIC void verify_fs_writable(fs_user_mount_t *vfs) { +static void verify_fs_writable(fs_user_mount_t *vfs) { if (!filesystem_is_writable_by_python(vfs)) { mp_raise_OSError(MP_EROFS); } } #if FF_FS_REENTRANT -STATIC mp_obj_t fat_vfs_del(mp_obj_t self_in) { +static mp_obj_t fat_vfs_del(mp_obj_t self_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(self_in); // f_umount only needs to be called to release the sync object f_umount(&self->fatfs); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del); +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_del_obj, fat_vfs_del); #endif -STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { +static mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { // create new object fs_user_mount_t *vfs = MP_OBJ_TO_PTR(fat_vfs_make_new(&mp_fat_vfs_type, 1, 0, &bdev_in)); @@ -133,10 +134,15 @@ STATIC mp_obj_t fat_vfs_mkfs(mp_obj_t bdev_in) { mp_raise_OSError_fresult(res); } + // set the filesystem label if it's configured + #ifdef MICROPY_HW_FLASH_FS_LABEL + f_setlabel(&vfs->fatfs, MICROPY_HW_FLASH_FS_LABEL); + #endif + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj)); +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_mkfs_fun_obj, fat_vfs_mkfs); +static MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mkfs_fun_obj)); typedef struct _mp_vfs_fat_ilistdir_it_t { mp_obj_base_t base; @@ -146,7 +152,7 @@ typedef struct _mp_vfs_fat_ilistdir_it_t { FF_DIR dir; } mp_vfs_fat_ilistdir_it_t; -STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { +static mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); for (;;) { @@ -163,7 +169,7 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { // make 4-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); if (self->is_str) { - t->items[0] = mp_obj_new_str(fn, strlen(fn)); + t->items[0] = mp_obj_new_str_from_cstr(fn); } else { t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); } @@ -186,14 +192,14 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -STATIC mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) { +static mp_obj_t mp_vfs_fat_ilistdir_it_del(mp_obj_t self_in) { mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); // ignore result / error because we may be closing a second time. f_closedir(&self->dir); return mp_const_none; } -STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { +static mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; const char *path; @@ -207,8 +213,7 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { } // Create a new iterator object to list the dir - mp_vfs_fat_ilistdir_it_t *iter = m_new_obj_with_finaliser(mp_vfs_fat_ilistdir_it_t); - iter->base.type = &mp_type_polymorph_iter_with_finaliser; + mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc_with_finaliser(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter_with_finaliser); iter->iternext = mp_vfs_fat_ilistdir_it_iternext; iter->finaliser = mp_vfs_fat_ilistdir_it_del; iter->is_str = is_str_type; @@ -220,9 +225,9 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) { return MP_OBJ_FROM_PTR(iter); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func); -STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) { +static mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); // CIRCUITPY-CHANGE verify_fs_writable(self); @@ -250,17 +255,17 @@ STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_in } } -STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { +static mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { return fat_vfs_remove_internal(vfs_in, path_in, 0); // 0 == file attribute } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); -STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { +static mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { return fat_vfs_remove_internal(vfs_in, path_in, AM_DIR); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); -STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) { +static mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); // CIRCUITPY-CHANGE verify_fs_writable(self); @@ -281,9 +286,9 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_ } } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename); +static MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_rename_obj, fat_vfs_rename); -STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) { +static mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); verify_fs_writable(self); const char *path = mp_obj_str_get_str(path_o); @@ -295,10 +300,10 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) { mp_raise_OSError_fresult(res); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir); // Change current directory. -STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) { +static mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path; path = mp_obj_str_get_str(path_in); @@ -312,10 +317,10 @@ STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir); // Get the current directory. -STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { +static mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); char buf[MICROPY_ALLOC_PATH_MAX + 1]; FRESULT res = f_getcwd(&self->fatfs, buf, sizeof(buf)); @@ -323,12 +328,12 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) { // CIRCUITPY-CHANGE mp_raise_OSError_fresult(res); } - return mp_obj_new_str(buf, strlen(buf)); + return mp_obj_new_str_from_cstr(buf); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd); // Get the status of a file or directory. -STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { +static mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path = mp_obj_str_get_str(path_in); @@ -343,7 +348,10 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { FRESULT res = f_stat(&self->fatfs, path, &fno); if (res != FR_OK) { // CIRCUITPY-CHANGE - mp_raise_OSError_fresult(res); + if (gc_alloc_possible()) { + mp_raise_OSError_fresult(res); + } + return mp_const_none; } } @@ -384,10 +392,10 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) { return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat); // Get the status of a VFS. -STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { +static mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); (void)path_in; @@ -414,18 +422,15 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) { return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs); +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs); -STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { +static mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); - // Read-only device indicated by writeblocks[0] == MP_OBJ_NULL. - // User can specify read-only device by: - // 1. readonly=True keyword argument - // 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already) - if (mp_obj_is_true(readonly)) { - self->blockdev.writeblocks[0] = MP_OBJ_NULL; - } + // CIRCUITPY-CHANGE: Use MP_BLOCKDEV_FLAG_USB_WRITABLE instead of writeblocks[0] =/!= MP_OBJ_NULL + // to specify read-write. + // If readonly to Python, it's writable by USB and vice versa. + filesystem_set_writable_by_usb(self, mp_obj_is_true(readonly)); // check if we need to make the filesystem FRESULT res = (self->blockdev.flags & MP_BLOCKDEV_FLAG_NO_FILESYSTEM) ? FR_NO_FILESYSTEM : FR_OK; @@ -441,17 +446,17 @@ STATIC mp_obj_t vfs_fat_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount); +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_fat_mount_obj, vfs_fat_mount); -STATIC mp_obj_t vfs_fat_umount(mp_obj_t self_in) { +static mp_obj_t vfs_fat_umount(mp_obj_t self_in) { (void)self_in; // keep the FAT filesystem mounted internally so the VFS methods can still be used return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount); // CIRCUITPY-CHANGE -STATIC mp_obj_t vfs_fat_utime(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t times_in) { +static mp_obj_t vfs_fat_utime(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t times_in) { mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in); const char *path = mp_obj_str_get_str(path_in); if (!mp_obj_is_tuple_compatible(times_in)) { @@ -478,22 +483,19 @@ STATIC mp_obj_t vfs_fat_utime(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t times_ return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_utime_obj, vfs_fat_utime); +static MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_utime_obj, vfs_fat_utime); -STATIC mp_obj_t vfs_fat_getreadonly(mp_obj_t self_in) { +static mp_obj_t vfs_fat_getreadonly(mp_obj_t self_in) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(!filesystem_is_writable_by_python(self)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getreadonly_obj, vfs_fat_getreadonly); -STATIC const mp_obj_property_t fat_vfs_readonly_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&fat_vfs_getreadonly_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getreadonly_obj, vfs_fat_getreadonly); + +static MP_PROPERTY_GETTER(fat_vfs_readonly_obj, + (mp_obj_t)&fat_vfs_getreadonly_obj); #if MICROPY_FATFS_USE_LABEL -STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { +static mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); char working_buf[12]; FRESULT res = f_getlabel(&self->fatfs, working_buf, NULL); @@ -502,9 +504,9 @@ STATIC mp_obj_t vfs_fat_getlabel(mp_obj_t self_in) { } return mp_obj_new_str(working_buf, strlen(working_buf)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel); +static MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getlabel_obj, vfs_fat_getlabel); -STATIC mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { +static mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); verify_fs_writable(self); const char *label_str = mp_obj_str_get_str(label_in); @@ -517,16 +519,15 @@ STATIC mp_obj_t vfs_fat_setlabel(mp_obj_t self_in, mp_obj_t label_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_setlabel_obj, vfs_fat_setlabel); -STATIC const mp_obj_property_t fat_vfs_label_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&fat_vfs_getlabel_obj, - (mp_obj_t)&fat_vfs_setlabel_obj, - MP_ROM_NONE}, -}; +static MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_setlabel_obj, vfs_fat_setlabel); + +static MP_PROPERTY_GETSET(fat_vfs_label_obj, + (mp_obj_t)&fat_vfs_getlabel_obj, + (mp_obj_t)&fat_vfs_setlabel_obj); #endif -STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { +static const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { + // CIRCUITPY-CHANGE: correct name #if FF_FS_REENTRANT { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&fat_vfs_del_obj) }, #endif @@ -550,9 +551,9 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_label), MP_ROM_PTR(&fat_vfs_label_obj) }, #endif }; -STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); +static MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); -STATIC const mp_vfs_proto_t fat_vfs_proto = { +static const mp_vfs_proto_t fat_vfs_proto = { // CIRCUITPY-CHANGE MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs) .import_stat = fat_vfs_import_stat, diff --git a/extmod/vfs_fat_diskio.c b/extmod/vfs_fat_diskio.c index 1bcd471f2162e..591da07eb5630 100644 --- a/extmod/vfs_fat_diskio.c +++ b/extmod/vfs_fat_diskio.c @@ -43,8 +43,11 @@ #include "lib/oofatfs/diskio.h" #include "extmod/vfs_fat.h" +// CIRCUITPY-CHANGE +#include "supervisor/filesystem.h" + typedef void *bdev_t; -STATIC fs_user_mount_t *disk_get_device(void *bdev) { +static fs_user_mount_t *disk_get_device(void *bdev) { return (fs_user_mount_t *)bdev; } @@ -153,7 +156,8 @@ DRESULT disk_ioctl( if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) { // error initialising stat = STA_NOINIT; - } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) { + // CIRCUITPY-CHANGE: writability from Python check + } else if (!filesystem_is_writable_by_python(vfs)) { stat = STA_PROTECT; } else { stat = 0; diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 74dabce99eb2c..2a3021ee9a8fe 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -62,13 +62,13 @@ const byte fresult_to_errno_table[20] = { [FR_INVALID_PARAMETER] = MP_EINVAL, }; -STATIC void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void file_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; // CIRCUITPY-CHANGE mp_printf(print, "", mp_obj_get_type_qstr(self_in), MP_OBJ_TO_PTR(self_in)); } -STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); UINT sz_out; FRESULT res = f_read(&self->fp, buf, size, &sz_out); @@ -79,7 +79,7 @@ STATIC mp_uint_t file_obj_read(mp_obj_t self_in, void *buf, mp_uint_t size, int return sz_out; } -STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); UINT sz_out; FRESULT res = f_write(&self->fp, buf, size, &sz_out); @@ -95,7 +95,7 @@ STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t siz return sz_out; } -STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(o_in); if (request == MP_STREAM_SEEK) { @@ -145,7 +145,7 @@ STATIC mp_uint_t file_obj_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, // TODO gc hook to close the file if not already closed -STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { +static const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, @@ -160,9 +160,9 @@ STATIC const mp_rom_map_elem_t vfs_fat_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); +static MP_DEFINE_CONST_DICT(vfs_fat_rawfile_locals_dict, vfs_fat_rawfile_locals_dict_table); -STATIC const mp_stream_p_t vfs_fat_fileio_stream_p = { +static const mp_stream_p_t vfs_fat_fileio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, @@ -177,7 +177,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &vfs_fat_rawfile_locals_dict ); -STATIC const mp_stream_p_t vfs_fat_textio_stream_p = { +static const mp_stream_p_t vfs_fat_textio_stream_p = { .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, @@ -194,7 +194,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); // Factory function for I/O stream classes -STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { +static mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { fs_user_mount_t *self = MP_OBJ_TO_PTR(self_in); const mp_obj_type_t *type = &mp_type_vfs_fat_textio; @@ -251,8 +251,7 @@ STATIC mp_obj_t fat_vfs_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_i } - pyb_file_obj_t *o = m_new_obj_with_finaliser(pyb_file_obj_t); - o->base.type = type; + pyb_file_obj_t *o = mp_obj_malloc_with_finaliser(pyb_file_obj_t, type); const char *fname = mp_obj_str_get_str(path_in); FRESULT res = f_open(&self->fatfs, &o->fp, fname, mode); diff --git a/extmod/vfs_lfs.c b/extmod/vfs_lfs.c index 4fb86b89b76c3..19063d6306604 100644 --- a/extmod/vfs_lfs.c +++ b/extmod/vfs_lfs.c @@ -127,7 +127,7 @@ typedef struct _mp_obj_vfs_lfs2_file_t { const char *mp_vfs_lfs2_make_path(mp_obj_vfs_lfs2_t *self, mp_obj_t path_in); mp_obj_t mp_vfs_lfs2_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); -STATIC void lfs_get_mtime(uint8_t buf[8]) { +static void lfs_get_mtime(uint8_t buf[8]) { // On-disk storage of timestamps uses 1970 as the Epoch, so convert from host's Epoch. uint64_t ns = timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(mp_hal_time_ns()); // Store "ns" to "buf" in little-endian format (essentially htole64). diff --git a/extmod/vfs_lfsx.c b/extmod/vfs_lfsx.c index e78c154d1fe8d..bbdd21cfb9176 100644 --- a/extmod/vfs_lfsx.c +++ b/extmod/vfs_lfsx.c @@ -43,7 +43,7 @@ #error "MICROPY_VFS_LFS requires MICROPY_ENABLE_FINALISER" #endif -STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) { +static int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, int arg, bool must_return_int) { mp_obj_t ret = mp_vfs_blockdev_ioctl(c->context, cmd, arg); int ret_i = 0; if (must_return_int || ret != mp_const_none) { @@ -52,23 +52,23 @@ STATIC int MP_VFS_LFSx(dev_ioctl)(const struct LFSx_API (config) * c, int cmd, i return ret_i; } -STATIC int MP_VFS_LFSx(dev_read)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) { +static int MP_VFS_LFSx(dev_read)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, void *buffer, LFSx_API(size_t) size) { return mp_vfs_blockdev_read_ext(c->context, block, off, size, buffer); } -STATIC int MP_VFS_LFSx(dev_prog)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, const void *buffer, LFSx_API(size_t) size) { +static int MP_VFS_LFSx(dev_prog)(const struct LFSx_API (config) * c, LFSx_API(block_t) block, LFSx_API(off_t) off, const void *buffer, LFSx_API(size_t) size) { return mp_vfs_blockdev_write_ext(c->context, block, off, size, buffer); } -STATIC int MP_VFS_LFSx(dev_erase)(const struct LFSx_API (config) * c, LFSx_API(block_t) block) { +static int MP_VFS_LFSx(dev_erase)(const struct LFSx_API (config) * c, LFSx_API(block_t) block) { return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_BLOCK_ERASE, block, true); } -STATIC int MP_VFS_LFSx(dev_sync)(const struct LFSx_API (config) * c) { +static int MP_VFS_LFSx(dev_sync)(const struct LFSx_API (config) * c) { return MP_VFS_LFSx(dev_ioctl)(c, MP_BLOCKDEV_IOCTL_SYNC, 0, false); } -STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { +static void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size_t read_size, size_t prog_size, size_t lookahead) { self->blockdev.flags = MP_BLOCKDEV_FLAG_FREE_OBJ; mp_vfs_blockdev_init(&self->blockdev, bdev); @@ -104,6 +104,12 @@ STATIC void MP_VFS_LFSx(init_config)(MP_OBJ_VFS_LFSx * self, mp_obj_t bdev, size config->read_buffer = m_new(uint8_t, config->cache_size); config->prog_buffer = m_new(uint8_t, config->cache_size); config->lookahead_buffer = m_new(uint8_t, config->lookahead_size); + #ifdef LFS2_MULTIVERSION + // This can be set to override the on-disk lfs version. + // eg. for compat with lfs2 < v2.6 add the following to make: + // CFLAGS += '-DLFS2_MULTIVERSION=0x00020000' + config->disk_version = LFS2_MULTIVERSION; + #endif #endif } @@ -120,7 +126,7 @@ const char *MP_VFS_LFSx(make_path)(MP_OBJ_VFS_LFSx * self, mp_obj_t path_in) { return path; } -STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t * type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { +static mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t * type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); @@ -140,7 +146,7 @@ STATIC mp_obj_t MP_VFS_LFSx(make_new)(const mp_obj_type_t * type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_arg_val_t args[MP_ARRAY_SIZE(lfs_make_allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(lfs_make_allowed_args), lfs_make_allowed_args, args); @@ -153,11 +159,11 @@ STATIC mp_obj_t MP_VFS_LFSx(mkfs)(size_t n_args, const mp_obj_t *pos_args, mp_ma } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(MP_VFS_LFSx(mkfs_fun_obj), 0, MP_VFS_LFSx(mkfs)); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(MP_VFS_LFSx(mkfs_obj), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_fun_obj))); +static MP_DEFINE_CONST_FUN_OBJ_KW(MP_VFS_LFSx(mkfs_fun_obj), 0, MP_VFS_LFSx(mkfs)); +static MP_DEFINE_CONST_STATICMETHOD_OBJ(MP_VFS_LFSx(mkfs_obj), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_fun_obj))); // Implementation of mp_vfs_lfs_file_open is provided in vfs_lfsx_file.c -STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); +static MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(open_obj), MP_VFS_LFSx(file_open)); typedef struct MP_VFS_LFSx (_ilistdir_it_t) { mp_obj_base_t base; @@ -168,7 +174,7 @@ typedef struct MP_VFS_LFSx (_ilistdir_it_t) { LFSx_API(dir_t) dir; } MP_VFS_LFSx(ilistdir_it_t); -STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { +static mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); if (self->vfs == NULL) { @@ -192,7 +198,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { // make 4-tuple with info about this entry mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); if (self->is_str) { - t->items[0] = mp_obj_new_str(info.name, strlen(info.name)); + t->items[0] = mp_obj_new_str_from_cstr(info.name); } else { t->items[0] = mp_obj_new_bytes((const byte *)info.name, strlen(info.name)); } @@ -203,7 +209,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_iternext)(mp_obj_t self_in) { return MP_OBJ_FROM_PTR(t); } -STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) { +static mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) { MP_VFS_LFSx(ilistdir_it_t) * self = MP_OBJ_TO_PTR(self_in); if (self->vfs != NULL) { LFSx_API(dir_close)(&self->vfs->lfs, &self->dir); @@ -211,7 +217,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_it_del)(mp_obj_t self_in) { return mp_const_none; } -STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { +static mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(args[0]); bool is_str_type = true; const char *path; @@ -224,8 +230,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) path = vstr_null_terminated_str(&self->cur_dir); } - MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj_with_finaliser(MP_VFS_LFSx(ilistdir_it_t)); - iter->base.type = &mp_type_polymorph_iter_with_finaliser; + MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc_with_finaliser(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter_with_finaliser); iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); iter->finaliser = MP_VFS_LFSx(ilistdir_it_del); @@ -237,9 +242,9 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args) iter->vfs = self; return MP_OBJ_FROM_PTR(iter); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(MP_VFS_LFSx(ilistdir_obj), 1, 2, MP_VFS_LFSx(ilistdir_func)); -STATIC mp_obj_t MP_VFS_LFSx(remove)(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t MP_VFS_LFSx(remove)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_in); int ret = LFSx_API(remove)(&self->lfs, path); @@ -248,9 +253,9 @@ STATIC mp_obj_t MP_VFS_LFSx(remove)(mp_obj_t self_in, mp_obj_t path_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(remove_obj), MP_VFS_LFSx(remove)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(remove_obj), MP_VFS_LFSx(remove)); -STATIC mp_obj_t MP_VFS_LFSx(rmdir)(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t MP_VFS_LFSx(rmdir)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_in); int ret = LFSx_API(remove)(&self->lfs, path); @@ -259,9 +264,9 @@ STATIC mp_obj_t MP_VFS_LFSx(rmdir)(mp_obj_t self_in, mp_obj_t path_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(rmdir_obj), MP_VFS_LFSx(rmdir)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(rmdir_obj), MP_VFS_LFSx(rmdir)); -STATIC mp_obj_t MP_VFS_LFSx(rename)(mp_obj_t self_in, mp_obj_t path_old_in, mp_obj_t path_new_in) { +static mp_obj_t MP_VFS_LFSx(rename)(mp_obj_t self_in, mp_obj_t path_old_in, mp_obj_t path_new_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path_old = MP_VFS_LFSx(make_path)(self, path_old_in); const char *path = mp_obj_str_get_str(path_new_in); @@ -278,9 +283,9 @@ STATIC mp_obj_t MP_VFS_LFSx(rename)(mp_obj_t self_in, mp_obj_t path_old_in, mp_o } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(rename_obj), MP_VFS_LFSx(rename)); +static MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(rename_obj), MP_VFS_LFSx(rename)); -STATIC mp_obj_t MP_VFS_LFSx(mkdir)(mp_obj_t self_in, mp_obj_t path_o) { +static mp_obj_t MP_VFS_LFSx(mkdir)(mp_obj_t self_in, mp_obj_t path_o) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_o); int ret = LFSx_API(mkdir)(&self->lfs, path); @@ -289,9 +294,9 @@ STATIC mp_obj_t MP_VFS_LFSx(mkdir)(mp_obj_t self_in, mp_obj_t path_o) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(mkdir_obj), MP_VFS_LFSx(mkdir)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(mkdir_obj), MP_VFS_LFSx(mkdir)); -STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); // Check path exists @@ -301,7 +306,7 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { struct LFSx_API (info) info; int ret = LFSx_API(stat)(&self->lfs, path, &info); if (ret < 0 || info.type != LFSx_MACRO(_TYPE_DIR)) { - mp_raise_OSError(-MP_ENOENT); + mp_raise_OSError(MP_ENOENT); } } @@ -357,9 +362,9 @@ STATIC mp_obj_t MP_VFS_LFSx(chdir)(mp_obj_t self_in, mp_obj_t path_in) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(chdir_obj), MP_VFS_LFSx(chdir)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(chdir_obj), MP_VFS_LFSx(chdir)); -STATIC mp_obj_t MP_VFS_LFSx(getcwd)(mp_obj_t self_in) { +static mp_obj_t MP_VFS_LFSx(getcwd)(mp_obj_t self_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); if (vstr_len(&self->cur_dir) == 1) { return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); @@ -368,9 +373,9 @@ STATIC mp_obj_t MP_VFS_LFSx(getcwd)(mp_obj_t self_in) { return mp_obj_new_str(self->cur_dir.buf, self->cur_dir.len - 1); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(getcwd_obj), MP_VFS_LFSx(getcwd)); +static MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(getcwd_obj), MP_VFS_LFSx(getcwd)); -STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); const char *path = MP_VFS_LFSx(make_path)(self, path_in); struct LFSx_API (info) info; @@ -379,7 +384,7 @@ STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { mp_raise_OSError(-ret); } - mp_uint_t mtime = 0; + mp_timestamp_t mtime = 0; #if LFS_BUILD_VERSION == 2 uint8_t mtime_buf[8]; lfs2_ssize_t sz = lfs2_getattr(&self->lfs, path, LFS_ATTR_MTIME, &mtime_buf, sizeof(mtime_buf)); @@ -401,22 +406,22 @@ STATIC mp_obj_t MP_VFS_LFSx(stat)(mp_obj_t self_in, mp_obj_t path_in) { t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid t->items[6] = mp_obj_new_int_from_uint(info.size); // st_size - t->items[7] = mp_obj_new_int_from_uint(mtime); // st_atime - t->items[8] = mp_obj_new_int_from_uint(mtime); // st_mtime - t->items[9] = mp_obj_new_int_from_uint(mtime); // st_ctime + t->items[7] = timeutils_obj_from_timestamp(mtime); // st_atime + t->items[8] = timeutils_obj_from_timestamp(mtime); // st_mtime + t->items[9] = timeutils_obj_from_timestamp(mtime); // st_ctime return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(stat_obj), MP_VFS_LFSx(stat)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(stat_obj), MP_VFS_LFSx(stat)); -STATIC int LFSx_API(traverse_cb)(void *data, LFSx_API(block_t) bl) { +static int LFSx_API(traverse_cb)(void *data, LFSx_API(block_t) bl) { (void)bl; uint32_t *n = (uint32_t *)data; *n += 1; return LFSx_MACRO(_ERR_OK); } -STATIC mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { (void)path_in; MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); uint32_t n_used_blocks = 0; @@ -443,9 +448,9 @@ STATIC mp_obj_t MP_VFS_LFSx(statvfs)(mp_obj_t self_in, mp_obj_t path_in) { return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(statvfs_obj), MP_VFS_LFSx(statvfs)); +static MP_DEFINE_CONST_FUN_OBJ_2(MP_VFS_LFSx(statvfs_obj), MP_VFS_LFSx(statvfs)); -STATIC mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { +static mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); (void)mkfs; @@ -458,17 +463,17 @@ STATIC mp_obj_t MP_VFS_LFSx(mount)(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(mount_obj), MP_VFS_LFSx(mount)); +static MP_DEFINE_CONST_FUN_OBJ_3(MP_VFS_LFSx(mount_obj), MP_VFS_LFSx(mount)); -STATIC mp_obj_t MP_VFS_LFSx(umount)(mp_obj_t self_in) { +static mp_obj_t MP_VFS_LFSx(umount)(mp_obj_t self_in) { MP_OBJ_VFS_LFSx *self = MP_OBJ_TO_PTR(self_in); // LFS unmount never fails LFSx_API(unmount)(&self->lfs); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(umount_obj), MP_VFS_LFSx(umount)); +static MP_DEFINE_CONST_FUN_OBJ_1(MP_VFS_LFSx(umount_obj), MP_VFS_LFSx(umount)); -STATIC const mp_rom_map_elem_t MP_VFS_LFSx(locals_dict_table)[] = { +static const mp_rom_map_elem_t MP_VFS_LFSx(locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&MP_VFS_LFSx(mkfs_obj)) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&MP_VFS_LFSx(open_obj)) }, { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&MP_VFS_LFSx(ilistdir_obj)) }, @@ -483,9 +488,9 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&MP_VFS_LFSx(mount_obj)) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&MP_VFS_LFSx(umount_obj)) }, }; -STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(locals_dict), MP_VFS_LFSx(locals_dict_table)); +static MP_DEFINE_CONST_DICT(MP_VFS_LFSx(locals_dict), MP_VFS_LFSx(locals_dict_table)); -STATIC mp_import_stat_t MP_VFS_LFSx(import_stat)(void *self_in, const char *path) { +static mp_import_stat_t MP_VFS_LFSx(import_stat)(void *self_in, const char *path) { MP_OBJ_VFS_LFSx *self = self_in; struct LFSx_API (info) info; mp_obj_str_t path_obj = { { &mp_type_str }, 0, 0, (const byte *)path }; @@ -501,7 +506,7 @@ STATIC mp_import_stat_t MP_VFS_LFSx(import_stat)(void *self_in, const char *path return MP_IMPORT_STAT_NO_EXIST; } -STATIC const mp_vfs_proto_t MP_VFS_LFSx(proto) = { +static const mp_vfs_proto_t MP_VFS_LFSx(proto) = { .import_stat = MP_VFS_LFSx(import_stat), }; diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index b9f332339733e..56daa53e06869 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -35,13 +35,13 @@ #include "py/mperrno.h" #include "extmod/vfs.h" -STATIC void MP_VFS_LFSx(check_open)(MP_OBJ_VFS_LFSx_FILE * self) { +static void MP_VFS_LFSx(check_open)(MP_OBJ_VFS_LFSx_FILE * self) { if (self->vfs == NULL) { mp_raise_ValueError(NULL); } } -STATIC void MP_VFS_LFSx(file_print)(const mp_print_t * print, mp_obj_t self_in, mp_print_kind_t kind) { +static void MP_VFS_LFSx(file_print)(const mp_print_t * print, mp_obj_t self_in, mp_print_kind_t kind) { (void)self_in; (void)kind; mp_printf(print, "", mp_obj_get_type_str(self_in)); @@ -90,11 +90,10 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod } #if LFS_BUILD_VERSION == 1 - MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->prog_size); + MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->prog_size, type); #else - MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->cache_size); + MP_OBJ_VFS_LFSx_FILE *o = mp_obj_malloc_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->cache_size, type); #endif - o->base.type = type; o->vfs = self; #if !MICROPY_GC_CONSERVATIVE_CLEAR memset(&o->file, 0, sizeof(o->file)); @@ -123,7 +122,7 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod return MP_OBJ_FROM_PTR(o); } -STATIC mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); MP_VFS_LFSx(check_open)(self); LFSx_API(ssize_t) sz = LFSx_API(file_read)(&self->vfs->lfs, &self->file, buf, size); @@ -134,7 +133,7 @@ STATIC mp_uint_t MP_VFS_LFSx(file_read)(mp_obj_t self_in, void *buf, mp_uint_t s return sz; } -STATIC mp_uint_t MP_VFS_LFSx(file_write)(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t MP_VFS_LFSx(file_write)(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); MP_VFS_LFSx(check_open)(self); #if LFS_BUILD_VERSION == 2 @@ -150,7 +149,7 @@ STATIC mp_uint_t MP_VFS_LFSx(file_write)(mp_obj_t self_in, const void *buf, mp_u return sz; } -STATIC mp_uint_t MP_VFS_LFSx(file_ioctl)(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t MP_VFS_LFSx(file_ioctl)(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { MP_OBJ_VFS_LFSx_FILE *self = MP_OBJ_TO_PTR(self_in); if (request != MP_STREAM_CLOSE) { @@ -195,7 +194,7 @@ STATIC mp_uint_t MP_VFS_LFSx(file_ioctl)(mp_obj_t self_in, mp_uint_t request, ui } } -STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { +static const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, @@ -209,9 +208,9 @@ STATIC const mp_rom_map_elem_t MP_VFS_LFSx(file_locals_dict_table)[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); +static MP_DEFINE_CONST_DICT(MP_VFS_LFSx(file_locals_dict), MP_VFS_LFSx(file_locals_dict_table)); -STATIC const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { +static const mp_stream_p_t MP_VFS_LFSx(fileio_stream_p) = { .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), @@ -226,7 +225,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &MP_VFS_LFSx(file_locals_dict) ); -STATIC const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { +static const mp_stream_p_t MP_VFS_LFSx(textio_stream_p) = { .read = MP_VFS_LFSx(file_read), .write = MP_VFS_LFSx(file_write), .ioctl = MP_VFS_LFSx(file_ioctl), diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index e29b47cccda83..27f833e802f69 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -57,7 +57,7 @@ typedef struct _mp_obj_vfs_posix_t { bool readonly; } mp_obj_vfs_posix_t; -STATIC const char *vfs_posix_get_path_str(mp_obj_vfs_posix_t *self, mp_obj_t path) { +static const char *vfs_posix_get_path_str(mp_obj_vfs_posix_t *self, mp_obj_t path) { const char *path_str = mp_obj_str_get_str(path); if (self->root_len == 0 || path_str[0] != '/') { return path_str; @@ -68,7 +68,7 @@ STATIC const char *vfs_posix_get_path_str(mp_obj_vfs_posix_t *self, mp_obj_t pat } } -STATIC mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path) { +static mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path) { const char *path_str = mp_obj_str_get_str(path); if (self->root_len == 0 || path_str[0] != '/') { return path; @@ -79,7 +79,7 @@ STATIC mp_obj_t vfs_posix_get_path_obj(mp_obj_vfs_posix_t *self, mp_obj_t path) } } -STATIC mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (*f)(const char *)) { +static mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (*f)(const char *)) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); int ret = f(vfs_posix_get_path_str(self, path_in)); if (ret != 0) { @@ -88,7 +88,7 @@ STATIC mp_obj_t vfs_posix_fun1_helper(mp_obj_t self_in, mp_obj_t path_in, int (* return mp_const_none; } -STATIC mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path) { +static mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path) { mp_obj_vfs_posix_t *self = self_in; if (self->root_len != 0) { self->root.len = self->root_len; @@ -106,7 +106,7 @@ STATIC mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path return MP_IMPORT_STAT_NO_EXIST; } -STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_obj_vfs_posix_t *vfs = mp_obj_malloc(mp_obj_vfs_posix_t, type); @@ -137,12 +137,12 @@ STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, siz vstr_add_char(&vfs->root, '/'); } vfs->root_len = vfs->root.len; - vfs->readonly = false; + vfs->readonly = !MICROPY_VFS_POSIX_WRITABLE; return MP_OBJ_FROM_PTR(vfs); } -STATIC mp_obj_t vfs_posix_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { +static mp_obj_t vfs_posix_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); if (mp_obj_is_true(readonly)) { self->readonly = true; @@ -152,18 +152,29 @@ STATIC mp_obj_t vfs_posix_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mk } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_mount_obj, vfs_posix_mount); +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_mount_obj, vfs_posix_mount); -STATIC mp_obj_t vfs_posix_umount(mp_obj_t self_in) { +static mp_obj_t vfs_posix_umount(mp_obj_t self_in) { (void)self_in; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_umount_obj, vfs_posix_umount); +static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_umount_obj, vfs_posix_umount); -STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { +static inline bool vfs_posix_is_readonly(mp_obj_vfs_posix_t *self) { + return !MICROPY_VFS_POSIX_WRITABLE || self->readonly; +} + +static void vfs_posix_require_writable(mp_obj_t self_in) { + mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); + if (vfs_posix_is_readonly(self)) { + mp_raise_OSError(MP_EROFS); + } +} + +static mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *mode = mp_obj_str_get_str(mode_in); - if (self->readonly + if (vfs_posix_is_readonly(self) && (strchr(mode, 'w') != NULL || strchr(mode, 'a') != NULL || strchr(mode, '+') != NULL)) { mp_raise_OSError(MP_EROFS); } @@ -172,14 +183,14 @@ STATIC mp_obj_t vfs_posix_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode } return mp_vfs_posix_file_open(&mp_type_vfs_posix_textio, path_in, mode_in); } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open); +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_open_obj, vfs_posix_open); -STATIC mp_obj_t vfs_posix_chdir(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_chdir(mp_obj_t self_in, mp_obj_t path_in) { return vfs_posix_fun1_helper(self_in, path_in, chdir); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_chdir_obj, vfs_posix_chdir); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_chdir_obj, vfs_posix_chdir); -STATIC mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) { +static mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); char buf[MICROPY_ALLOC_PATH_MAX + 1]; const char *ret = getcwd(buf, sizeof(buf)); @@ -194,9 +205,9 @@ STATIC mp_obj_t vfs_posix_getcwd(mp_obj_t self_in) { } #endif } - return mp_obj_new_str(ret, strlen(ret)); + return mp_obj_new_str_from_cstr(ret); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); +static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_getcwd_obj, vfs_posix_getcwd); typedef struct _vfs_posix_ilistdir_it_t { mp_obj_base_t base; @@ -206,7 +217,7 @@ typedef struct _vfs_posix_ilistdir_it_t { DIR *dir; } vfs_posix_ilistdir_it_t; -STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { +static mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->dir == NULL) { @@ -234,7 +245,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); if (self->is_str) { - t->items[0] = mp_obj_new_str(fn, strlen(fn)); + t->items[0] = mp_obj_new_str_from_cstr(fn); } else { t->items[0] = mp_obj_new_bytes((const byte *)fn, strlen(fn)); } @@ -266,7 +277,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) { } } -STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) { +static mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) { vfs_posix_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->dir != NULL) { MP_THREAD_GIL_EXIT(); @@ -276,10 +287,9 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_del(mp_obj_t self_in) { return mp_const_none; } -STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); - vfs_posix_ilistdir_it_t *iter = m_new_obj_with_finaliser(vfs_posix_ilistdir_it_t); - iter->base.type = &mp_type_polymorph_iter_with_finaliser; + vfs_posix_ilistdir_it_t *iter = mp_obj_malloc_with_finaliser(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter_with_finaliser); iter->iternext = vfs_posix_ilistdir_it_iternext; iter->finaliser = vfs_posix_ilistdir_it_del; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; @@ -295,7 +305,7 @@ STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { } return MP_OBJ_FROM_PTR(iter); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_ilistdir_obj, vfs_posix_ilistdir); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_ilistdir_obj, vfs_posix_ilistdir); typedef struct _mp_obj_listdir_t { mp_obj_base_t base; @@ -303,7 +313,8 @@ typedef struct _mp_obj_listdir_t { DIR *dir; } mp_obj_listdir_t; -STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *path = vfs_posix_get_path_str(self, path_in); MP_THREAD_GIL_EXIT(); @@ -318,14 +329,16 @@ STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_mkdir_obj, vfs_posix_mkdir); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_mkdir_obj, vfs_posix_mkdir); -STATIC mp_obj_t vfs_posix_remove(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_remove(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); return vfs_posix_fun1_helper(self_in, path_in, unlink); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_remove_obj, vfs_posix_remove); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_remove_obj, vfs_posix_remove); -STATIC mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) { +static mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_t new_path_in) { + vfs_posix_require_writable(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); const char *old_path = vfs_posix_get_path_str(self, old_path_in); const char *new_path = vfs_posix_get_path_str(self, new_path_in); @@ -337,14 +350,15 @@ STATIC mp_obj_t vfs_posix_rename(mp_obj_t self_in, mp_obj_t old_path_in, mp_obj_ } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_rename_obj, vfs_posix_rename); +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_posix_rename_obj, vfs_posix_rename); -STATIC mp_obj_t vfs_posix_rmdir(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_rmdir(mp_obj_t self_in, mp_obj_t path_in) { + vfs_posix_require_writable(self_in); return vfs_posix_fun1_helper(self_in, path_in, rmdir); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_rmdir_obj, vfs_posix_rmdir); -STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); struct stat sb; const char *path = vfs_posix_get_path_str(self, path_in); @@ -363,7 +377,7 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) { t->items[9] = mp_obj_new_int_from_uint(sb.st_ctime); return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat); #if MICROPY_PY_OS_STATVFS @@ -387,7 +401,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat); #define F_FLAG sb.f_flag #endif -STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) { +static mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) { mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); STRUCT_STATVFS sb; const char *path = vfs_posix_get_path_str(self, path_in); @@ -406,11 +420,11 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) { t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX); return MP_OBJ_FROM_PTR(t); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs); +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs); #endif -STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { +static const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_posix_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_posix_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&vfs_posix_open_obj) }, @@ -427,9 +441,9 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) }, #endif }; -STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); +static MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); -STATIC const mp_vfs_proto_t vfs_posix_proto = { +static const mp_vfs_proto_t vfs_posix_proto = { .import_stat = mp_vfs_posix_import_stat, }; diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 2f70789543911..501550cb502c5 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -47,7 +47,7 @@ typedef struct _mp_obj_vfs_posix_file_t { } mp_obj_vfs_posix_file_t; #if MICROPY_CPYTHON_COMPAT -STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { +static void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { if (o->fd < 0) { mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file")); } @@ -56,14 +56,13 @@ STATIC void check_fd_is_open(const mp_obj_vfs_posix_file_t *o) { #define check_fd_is_open(o) #endif -STATIC void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void vfs_posix_file_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); } mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_obj_t mode_in) { - mp_obj_vfs_posix_file_t *o = m_new_obj_with_finaliser(mp_obj_vfs_posix_file_t); const char *mode_s = mp_obj_str_get_str(mode_in); int mode_rw = 0, mode_x = 0; @@ -92,7 +91,8 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ } } - o->base.type = type; + mp_obj_vfs_posix_file_t *o = mp_obj_malloc_with_finaliser(mp_obj_vfs_posix_file_t, type); + o->fd = -1; // In case open() fails below, initialise this as a "closed" file object. mp_obj_t fid = file_in; @@ -108,14 +108,14 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_ return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) { +static mp_obj_t vfs_posix_file_fileno(mp_obj_t self_in) { mp_obj_vfs_posix_file_t *self = MP_OBJ_TO_PTR(self_in); check_fd_is_open(self); return MP_OBJ_NEW_SMALL_INT(self->fd); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_file_fileno_obj, vfs_posix_file_fileno); +static MP_DEFINE_CONST_FUN_OBJ_1(vfs_posix_file_fileno_obj, vfs_posix_file_fileno); -STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); ssize_t r; @@ -126,7 +126,7 @@ STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, i return (mp_uint_t)r; } -STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); check_fd_is_open(o); #if MICROPY_PY_OS_DUPTERM @@ -143,7 +143,7 @@ STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t return (mp_uint_t)r; } -STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in); if (request != MP_STREAM_CLOSE) { @@ -160,12 +160,27 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ #if defined(__APPLE__) #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == ENOTSUP) #elif defined(_MSC_VER) + // In debug builds fsync (i.e. _commit on windows) will generate a debug report via _ASSERTE when + // called with non-redirected stdin/stdout/stderr (i.e. _isatty) handles because FlushFileBuffers, + // which it calls internally, will fail since console output is not buffered. + // In release builds it also fails, but merely returns an error which is handled appropriately below. + // The check for the handle being stdin/stdout/stderr is added explicitly because according to + // the documentation _isatty is also true for serial ports for instance. + #ifdef _DEBUG + if ((o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO) && _isatty(o->fd)) { + return 0; + } + #endif #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL || err == EBADF) #else #define VFS_POSIX_STREAM_STDIO_ERR_CATCH (err == EINVAL) #endif MP_HAL_RETRY_SYSCALL(ret, fsync(o->fd), { if (VFS_POSIX_STREAM_STDIO_ERR_CATCH + // Note: comparing fd against the standard FILENOs is technically not correct, for example: + // sys.stderr.close() in Python code results in close(STDERR_FILENO) here, but because + // open() uses the next available file descriptor, opening an arbitrary file with + // fd = open('/some/file') means that fd becomes STDERR_FILENO. && (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) { return 0; } @@ -237,7 +252,7 @@ STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_ } } -STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { +static const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&vfs_posix_file_fileno_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, @@ -253,9 +268,9 @@ STATIC const mp_rom_map_elem_t vfs_posix_rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); +static MP_DEFINE_CONST_DICT(vfs_posix_rawfile_locals_dict, vfs_posix_rawfile_locals_dict_table); -STATIC const mp_stream_p_t vfs_posix_fileio_stream_p = { +static const mp_stream_p_t vfs_posix_fileio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, @@ -270,7 +285,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &vfs_posix_rawfile_locals_dict ); -STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { +static const mp_stream_p_t vfs_posix_textio_stream_p = { .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, @@ -288,7 +303,7 @@ mp_obj_vfs_posix_file_t mp_sys_stdin_obj; mp_obj_vfs_posix_file_t mp_sys_stdout_obj; mp_obj_vfs_posix_file_t mp_sys_stderr_obj; -STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // These objects are read-only. return; diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c index 13fc31bee5080..6c36770295be6 100644 --- a/extmod/vfs_reader.c +++ b/extmod/vfs_reader.c @@ -49,7 +49,7 @@ typedef struct _mp_reader_vfs_t { byte buf[]; } mp_reader_vfs_t; -STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) { +static mp_uint_t mp_reader_vfs_readbyte(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; if (reader->bufpos >= reader->buflen) { if (reader->buflen < reader->bufsize) { @@ -70,7 +70,7 @@ STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) { return reader->buf[reader->bufpos++]; } -STATIC void mp_reader_vfs_close(void *data) { +static void mp_reader_vfs_close(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; mp_stream_close(reader->file); m_del_obj(mp_reader_vfs_t, reader); @@ -83,8 +83,19 @@ void mp_reader_new_file(mp_reader_t *reader, qstr filename) { }; mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); - const mp_stream_p_t *stream_p = mp_get_stream(file); + const mp_stream_p_t *stream_p = mp_get_stream_raise(file, MP_STREAM_OP_READ); int errcode = 0; + + #if MICROPY_VFS_ROM + // Check if the stream can be memory mapped. + mp_buffer_info_t bufinfo; + if (mp_get_buffer(file, &bufinfo, MP_BUFFER_READ)) { + mp_reader_new_mem(reader, bufinfo.buf, bufinfo.len, MP_READER_IS_ROM); + return; + } + #endif + + // Determine how big the input buffer should be, if the stream requests a certain size or not. mp_uint_t bufsize = stream_p->ioctl(file, MP_STREAM_GET_BUFFER_SIZE, 0, &errcode); if (bufsize == MP_STREAM_ERROR || bufsize == 0) { // bufsize == 0 is included here to support mpremote v1.21 and older where mount file ioctl @@ -94,6 +105,7 @@ void mp_reader_new_file(mp_reader_t *reader, qstr filename) { bufsize = MIN(MICROPY_READER_VFS_MAX_BUFFER_SIZE, MAX(MICROPY_READER_VFS_MIN_BUFFER_SIZE, bufsize)); } + // Create the reader. mp_reader_vfs_t *rf = m_new_obj_var(mp_reader_vfs_t, buf, byte, bufsize); rf->file = file; rf->bufsize = bufsize; diff --git a/extmod/vfs_rom.c b/extmod/vfs_rom.c new file mode 100644 index 0000000000000..7d814cb980524 --- /dev/null +++ b/extmod/vfs_rom.c @@ -0,0 +1,471 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// ROMFS filesystem format +// ======================= +// +// ROMFS is a flexible and extensible filesystem format designed to represent a +// directory hierarchy with files, where those files are read-only and their data +// can be memory mapped. +// +// Concepts: +// - varuint: An unsigned integer that is encoded in a variable number of bytes. It is +// stored big-endian with the high bit of the byte set if there are following bytes. +// - record: A variable sized element with a type. It is stored as two varuint's and then +// a payload. The first varuint is the record kind and the second varuint is the +// payload length (which may be zero bytes long). +// +// A ROMFS filesystem is a record with record kind 0x14a6b1, chosen so the encoded value +// is 0xd2-0xcd-0x31 which is "RM1" with the first two bytes having their high bit set. +// If the ROMFS record's payload is non-empty then it contains records. +// +// Record types: +// - 0 = unused, can be used to detect corruption of the filesystem. +// - 1 = padding/comments, can contain any data in their payload. +// - 2 = verbatim data, used to store file data. +// - 3 = indirect data, pointer to offset within the ROMFS payload. +// - 4 = a directory: payload contains a varuint which is the length of the directory +// name in bytes, then the name, then optional nested records for the contents +// of the directory (including optional metadata). +// - 5 = a file: payload contains a varuint which is the length of the filename in bytes +// then the name, then optional nested records. +// +// Remarks: +// - A varuint can be padded if needed by prepending with one or more 0x80 bytes. This +// padding does not change any semantics. +// - The size of the ROMFS record (including kind and length and payload) must be a +// multiple of 2 (because it's not possible to add a padding record of one byte). +// - File data can be optionally aligned using padding records and/or indirect data +// records. +// - There is no limit to the size of directory/file names or file data. +// +// Unknown record types must be skipped over. They may in the future add optional +// features, while still retaining backwards compatibility. Such features may be: +// - Alignment requirements of the ROMFS record. +// - Timestamps on directories/files. +// - A precomputed hash of a file, or other metadata. +// - An optimised lookup table indexing the directory hierarchy. + +#include + +#include "py/bc.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "extmod/vfs.h" +#include "extmod/vfs_rom.h" + +#if MICROPY_VFS_ROM + +#define ROMFS_SIZE_MIN (4) +#define ROMFS_HEADER_BYTE0 (0x80 | 'R') +#define ROMFS_HEADER_BYTE1 (0x80 | 'M') +#define ROMFS_HEADER_BYTE2 (0x00 | '1') + +// Values for `record_kind_t`. +#define ROMFS_RECORD_KIND_UNUSED (0) +#define ROMFS_RECORD_KIND_PADDING (1) +#define ROMFS_RECORD_KIND_DATA_VERBATIM (2) +#define ROMFS_RECORD_KIND_DATA_POINTER (3) +#define ROMFS_RECORD_KIND_DIRECTORY (4) +#define ROMFS_RECORD_KIND_FILE (5) +#define ROMFS_RECORD_KIND_FILESYSTEM (0x14a6b1) + +typedef mp_uint_t record_kind_t; + +struct _mp_obj_vfs_rom_t { + mp_obj_base_t base; + mp_obj_t memory; + const uint8_t *filesystem; + const uint8_t *filesystem_end; +}; + +// Returns 0 for success, -1 for failure. +static int mp_decode_uint_checked(const uint8_t **ptr, const uint8_t *ptr_max, mp_uint_t *value_out) { + mp_uint_t unum = 0; + byte val; + const uint8_t *p = *ptr; + do { + if (p >= ptr_max) { + return -1; + } + val = *p++; + unum = (unum << 7) | (val & 0x7f); + } while ((val & 0x80) != 0); + *ptr = p; + *value_out = unum; + return 0; +} + +static record_kind_t extract_record(const uint8_t **fs, const uint8_t **fs_next, const uint8_t *fs_max) { + mp_uint_t record_kind; + if (mp_decode_uint_checked(fs, fs_max, &record_kind) != 0) { + return ROMFS_RECORD_KIND_UNUSED; + } + mp_uint_t record_len; + if (mp_decode_uint_checked(fs, fs_max, &record_len) != 0) { + return ROMFS_RECORD_KIND_UNUSED; + } + *fs_next = *fs + record_len; + return record_kind; +} + +// Returns 0 for success, a negative integer for failure. +static int extract_data(mp_obj_vfs_rom_t *self, const uint8_t *fs, const uint8_t *fs_top, size_t *size_out, const uint8_t **data_out) { + while (fs < fs_top) { + const uint8_t *fs_next; + record_kind_t record_kind = extract_record(&fs, &fs_next, fs_top); + if (record_kind == ROMFS_RECORD_KIND_UNUSED) { + // Corrupt filesystem. + break; + } else if (record_kind == ROMFS_RECORD_KIND_DATA_VERBATIM) { + // Verbatim data. + if (size_out != NULL) { + *size_out = fs_next - fs; + *data_out = fs; + } + return 0; + } else if (record_kind == ROMFS_RECORD_KIND_DATA_POINTER) { + // Pointer to data. + mp_uint_t size; + if (mp_decode_uint_checked(&fs, fs_next, &size) != 0) { + break; + } + mp_uint_t offset; + if (mp_decode_uint_checked(&fs, fs_next, &offset) != 0) { + break; + } + if (size_out != NULL) { + *size_out = size; + *data_out = self->filesystem + offset; + } + return 0; + } else { + // Skip this record. + fs = fs_next; + } + } + return -MP_EIO; +} + +// Searches for `path` in the filesystem. +// `path` must be null-terminated. +mp_import_stat_t mp_vfs_rom_search_filesystem(mp_obj_vfs_rom_t *self, const char *path, size_t *size_out, const uint8_t **data_out) { + const uint8_t *fs = self->filesystem; + const uint8_t *fs_top = self->filesystem_end; + size_t path_len = strlen(path); + if (*path == '/') { + // An optional slash at the start of the path enters the top-level filesystem. + ++path; + --path_len; + } + while (path_len > 0 && fs < fs_top) { + const uint8_t *fs_next; + record_kind_t record_kind = extract_record(&fs, &fs_next, fs_top); + if (record_kind == ROMFS_RECORD_KIND_UNUSED) { + // Corrupt filesystem. + return MP_IMPORT_STAT_NO_EXIST; + } else if (record_kind == ROMFS_RECORD_KIND_DIRECTORY || record_kind == ROMFS_RECORD_KIND_FILE) { + // A directory or file record. + mp_uint_t name_len; + if (mp_decode_uint_checked(&fs, fs_next, &name_len) != 0) { + // Corrupt filesystem. + return MP_IMPORT_STAT_NO_EXIST; + } + if ((name_len == path_len + || (name_len < path_len && path[name_len] == '/')) + && memcmp(path, fs, name_len) == 0) { + // Name matches, so enter this record. + fs += name_len; + fs_top = fs_next; + path += name_len; + path_len -= name_len; + if (record_kind == ROMFS_RECORD_KIND_DIRECTORY) { + // Continue searching in this directory. + if (*path == '/') { + ++path; + --path_len; + } + } else { + // Return this file. + if (path_len != 0) { + return MP_IMPORT_STAT_NO_EXIST; + } + if (extract_data(self, fs, fs_top, size_out, data_out) != 0) { + // Corrupt filesystem. + return MP_IMPORT_STAT_NO_EXIST; + } + return MP_IMPORT_STAT_FILE; + } + } else { + // Skip this directory/file record. + fs = fs_next; + } + } else { + // Skip this record. + fs = fs_next; + } + } + if (path_len == 0) { + if (size_out != NULL) { + *size_out = fs_top - fs; + *data_out = fs; + } + return MP_IMPORT_STAT_DIR; + } + return MP_IMPORT_STAT_NO_EXIST; +} + +static mp_obj_t vfs_rom_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + mp_obj_vfs_rom_t *self = m_new_obj(mp_obj_vfs_rom_t); + self->base.type = type; + self->memory = args[0]; + + // Get the ROMFS memory region. + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(self->memory, &bufinfo, MP_BUFFER_READ); + if (bufinfo.len < ROMFS_SIZE_MIN) { + mp_raise_OSError(MP_ENODEV); + } + self->filesystem = bufinfo.buf; + + // Verify it is a ROMFS. + if (!(self->filesystem[0] == ROMFS_HEADER_BYTE0 + && self->filesystem[1] == ROMFS_HEADER_BYTE1 + && self->filesystem[2] == ROMFS_HEADER_BYTE2)) { + mp_raise_OSError(MP_ENODEV); + } + + // The ROMFS is a record itself, so enter into it and compute its limit. + record_kind_t record_kind = extract_record(&self->filesystem, &self->filesystem_end, self->filesystem + bufinfo.len); + if (record_kind != ROMFS_RECORD_KIND_FILESYSTEM) { + mp_raise_OSError(MP_ENODEV); + } + + // Check the filesystem is within the limits of the input buffer. + if (self->filesystem_end > (const uint8_t *)bufinfo.buf + bufinfo.len) { + mp_raise_OSError(MP_ENODEV); + } + + return MP_OBJ_FROM_PTR(self); +} + +static mp_obj_t vfs_rom_mount(mp_obj_t self_in, mp_obj_t readonly, mp_obj_t mkfs) { + (void)self_in; + (void)readonly; + if (mp_obj_is_true(mkfs)) { + mp_raise_OSError(MP_EPERM); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_rom_mount_obj, vfs_rom_mount); + +// mp_vfs_rom_file_open is implemented in vfs_rom_file.c. +static MP_DEFINE_CONST_FUN_OBJ_3(vfs_rom_open_obj, mp_vfs_rom_file_open); + +static mp_obj_t vfs_rom_chdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_rom_get_path_str(self, path_in); + if (path[0] == '/' && path[1] == '\0') { + // Allow chdir to the root of the filesystem. + } else { + // Don't allow chdir to any subdirectory (not currently implemented). + mp_raise_OSError(MP_EOPNOTSUPP); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_rom_chdir_obj, vfs_rom_chdir); + +static mp_obj_t vfs_rom_getcwd(mp_obj_t self_in) { + (void)self_in; + // The current directory is always the root of the ROMFS. + return MP_OBJ_NEW_QSTR(MP_QSTR_); +} +static MP_DEFINE_CONST_FUN_OBJ_1(vfs_rom_getcwd_obj, vfs_rom_getcwd); + +typedef struct _vfs_rom_ilistdir_it_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + mp_obj_vfs_rom_t *vfs_rom; + bool is_str; + const uint8_t *index; + const uint8_t *index_top; +} vfs_rom_ilistdir_it_t; + +static mp_obj_t vfs_rom_ilistdir_it_iternext(mp_obj_t self_in) { + vfs_rom_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in); + + while (self->index < self->index_top) { + const uint8_t *index_next; + record_kind_t record_kind = extract_record(&self->index, &index_next, self->index_top); + uint32_t type; + mp_uint_t name_len; + size_t data_len; + if (record_kind == ROMFS_RECORD_KIND_UNUSED) { + // Corrupt filesystem. + self->index = self->index_top; + break; + } else if (record_kind == ROMFS_RECORD_KIND_DIRECTORY || record_kind == ROMFS_RECORD_KIND_FILE) { + // A directory or file record. + if (mp_decode_uint_checked(&self->index, index_next, &name_len) != 0) { + // Corrupt filesystem. + self->index = self->index_top; + break; + } + if (record_kind == ROMFS_RECORD_KIND_DIRECTORY) { + // A directory. + type = MP_S_IFDIR; + data_len = index_next - self->index - name_len; + } else { + // A file. + type = MP_S_IFREG; + const uint8_t *data_value; + if (extract_data(self->vfs_rom, self->index + name_len, index_next, &data_len, &data_value) != 0) { + // Corrupt filesystem. + break; + } + } + } else { + // Skip this record. + self->index = index_next; + continue; + } + + const uint8_t *name_str = self->index; + self->index = index_next; + + // Make 4-tuple with info about this entry: (name, attr, inode, size) + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL)); + + if (self->is_str) { + t->items[0] = mp_obj_new_str((const char *)name_str, name_len); + } else { + t->items[0] = mp_obj_new_bytes(name_str, name_len); + } + + t->items[1] = MP_OBJ_NEW_SMALL_INT(type); + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); + t->items[3] = mp_obj_new_int(data_len); + + return MP_OBJ_FROM_PTR(t); + } + + return MP_OBJ_STOP_ITERATION; +} + +static mp_obj_t vfs_rom_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + vfs_rom_ilistdir_it_t *iter = m_new_obj(vfs_rom_ilistdir_it_t); + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = vfs_rom_ilistdir_it_iternext; + iter->vfs_rom = self; + iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; + const char *path = mp_vfs_rom_get_path_str(self, path_in); + size_t size; + if (mp_vfs_rom_search_filesystem(self, path, &size, &iter->index) != MP_IMPORT_STAT_DIR) { + mp_raise_OSError(MP_ENOENT); + } + iter->index_top = iter->index + size; + return MP_OBJ_FROM_PTR(iter); +} +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_rom_ilistdir_obj, vfs_rom_ilistdir); + +static mp_obj_t vfs_rom_stat(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + const char *path = mp_vfs_rom_get_path_str(self, path_in); + size_t file_size; + const uint8_t *file_data; + mp_import_stat_t stat = mp_vfs_rom_search_filesystem(self, path, &file_size, &file_data); + if (stat == MP_IMPORT_STAT_NO_EXIST) { + mp_raise_OSError(MP_ENOENT); + } + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(stat == MP_IMPORT_STAT_FILE ? MP_S_IFREG : MP_S_IFDIR); // st_mode + t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino + t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev + t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink + t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid + t->items[6] = MP_OBJ_NEW_SMALL_INT(file_size); // st_size + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // st_atime + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // st_mtime + t->items[9] = MP_OBJ_NEW_SMALL_INT(0); // st_ctime + return MP_OBJ_FROM_PTR(t); +} +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_rom_stat_obj, vfs_rom_stat); + +static mp_obj_t vfs_rom_statvfs(mp_obj_t self_in, mp_obj_t path_in) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + (void)path_in; + size_t filesystem_len = self->filesystem_end - self->filesystem; + mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); + t->items[0] = MP_OBJ_NEW_SMALL_INT(1); // f_bsize + t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // f_frsize + t->items[2] = mp_obj_new_int_from_uint(filesystem_len); // f_blocks + t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // f_bfree + t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // f_bavail + t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files + t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree + t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail + t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags + t->items[9] = MP_OBJ_NEW_SMALL_INT(32767); // f_namemax + return MP_OBJ_FROM_PTR(t); +} +static MP_DEFINE_CONST_FUN_OBJ_2(vfs_rom_statvfs_obj, vfs_rom_statvfs); + +static const mp_rom_map_elem_t vfs_rom_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_rom_mount_obj) }, + { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&vfs_rom_open_obj) }, + + { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&vfs_rom_chdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&vfs_rom_getcwd_obj) }, + { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&vfs_rom_ilistdir_obj) }, + { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_rom_stat_obj) }, + { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_rom_statvfs_obj) }, +}; +static MP_DEFINE_CONST_DICT(vfs_rom_locals_dict, vfs_rom_locals_dict_table); + +static mp_import_stat_t mp_vfs_rom_import_stat(void *self_in, const char *path) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + return mp_vfs_rom_search_filesystem(self, path, NULL, NULL); +} + +static const mp_vfs_proto_t vfs_rom_proto = { + .import_stat = mp_vfs_rom_import_stat, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_rom, + MP_QSTR_VfsRom, + MP_TYPE_FLAG_NONE, + make_new, vfs_rom_make_new, + protocol, &vfs_rom_proto, + locals_dict, &vfs_rom_locals_dict + ); + +#endif // MICROPY_VFS_ROM diff --git a/extmod/vfs_rom.h b/extmod/vfs_rom.h new file mode 100644 index 0000000000000..d8e2b911ba0ca --- /dev/null +++ b/extmod/vfs_rom.h @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_EXTMOD_VFS_ROM_H +#define MICROPY_INCLUDED_EXTMOD_VFS_ROM_H + +#include "py/builtin.h" +#include "py/obj.h" + +#if MICROPY_VFS_ROM + +typedef struct _mp_obj_vfs_rom_t mp_obj_vfs_rom_t; + +extern const mp_obj_type_t mp_type_vfs_rom; + +static inline const char *mp_vfs_rom_get_path_str(mp_obj_vfs_rom_t *self, mp_obj_t path) { + return mp_obj_str_get_str(path); +} + +mp_import_stat_t mp_vfs_rom_search_filesystem(mp_obj_vfs_rom_t *self, const char *path, size_t *size_out, const uint8_t **data_out); +mp_obj_t mp_vfs_rom_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in); + +#endif // MICROPY_VFS_ROM + +#endif // MICROPY_INCLUDED_EXTMOD_VFS_ROM_H diff --git a/extmod/vfs_rom_file.c b/extmod/vfs_rom_file.c new file mode 100644 index 0000000000000..57aca8c5dc7d3 --- /dev/null +++ b/extmod/vfs_rom_file.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2022 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "py/reader.h" +#include "py/runtime.h" +#include "py/stream.h" +#include "extmod/vfs_rom.h" + +#if MICROPY_VFS_ROM + +typedef struct _mp_obj_vfs_rom_file_t { + mp_obj_base_t base; + size_t file_size; + size_t file_offset; + const uint8_t *file_data; +} mp_obj_vfs_rom_file_t; + +static const mp_obj_type_t mp_type_vfs_rom_fileio; +static const mp_obj_type_t mp_type_vfs_rom_textio; + +mp_obj_t mp_vfs_rom_file_open(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mode_in) { + mp_obj_vfs_rom_t *self = MP_OBJ_TO_PTR(self_in); + + const char *mode_s = mp_obj_str_get_str(mode_in); + const mp_obj_type_t *type = &mp_type_vfs_rom_textio; + while (*mode_s) { + switch (*mode_s++) { + case 'r': + break; + case 'w': + case 'a': + case '+': + mp_raise_OSError(MP_EROFS); + case 'b': + type = &mp_type_vfs_rom_fileio; + break; + case 't': + type = &mp_type_vfs_rom_textio; + break; + } + } + + mp_obj_vfs_rom_file_t *o = m_new_obj(mp_obj_vfs_rom_file_t); + o->base.type = type; + o->file_offset = 0; + + const char *path = mp_vfs_rom_get_path_str(self, path_in); + mp_import_stat_t stat = mp_vfs_rom_search_filesystem(self, path, &o->file_size, &o->file_data); + if (stat == MP_IMPORT_STAT_NO_EXIST) { + mp_raise_OSError(MP_ENOENT); + } else if (stat == MP_IMPORT_STAT_DIR) { + mp_raise_OSError(MP_EISDIR); + } + + return MP_OBJ_FROM_PTR(o); +} + +static mp_int_t vfs_rom_file_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + mp_obj_vfs_rom_file_t *self = MP_OBJ_TO_PTR(self_in); + if (flags == MP_BUFFER_READ) { + bufinfo->buf = (void *)self->file_data; + bufinfo->len = self->file_size; + bufinfo->typecode = 'B'; + return 0; + } else { + // Can't write to a ROM file. + return 1; + } +} + +static mp_uint_t vfs_rom_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { + mp_obj_vfs_rom_file_t *self = MP_OBJ_TO_PTR(o_in); + size_t remain = self->file_size - self->file_offset; + if (size > remain) { + size = remain; + } + memcpy(buf, self->file_data + self->file_offset, size); + self->file_offset += size; + return size; +} + +static mp_uint_t vfs_rom_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { + mp_obj_vfs_rom_file_t *self = MP_OBJ_TO_PTR(o_in); + + switch (request) { + case MP_STREAM_SEEK: { + struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg; + if (s->whence == 0) { // SEEK_SET + self->file_offset = (size_t)s->offset; + } else if (s->whence == 1) { // SEEK_CUR + self->file_offset += s->offset; + } else { // SEEK_END + self->file_offset = self->file_size + s->offset; + } + if (self->file_offset > self->file_size) { + if (s->offset < 0) { + // Seek to before the start of the file. + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } + self->file_offset = self->file_size; + } + s->offset = self->file_offset; + return 0; + } + case MP_STREAM_CLOSE: + return 0; + default: + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; + } +} + +static const mp_rom_map_elem_t vfs_rom_rawfile_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj) }, + { MP_ROM_QSTR(MP_QSTR_seek), MP_ROM_PTR(&mp_stream_seek_obj) }, + { MP_ROM_QSTR(MP_QSTR_tell), MP_ROM_PTR(&mp_stream_tell_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, +}; +static MP_DEFINE_CONST_DICT(vfs_rom_rawfile_locals_dict, vfs_rom_rawfile_locals_dict_table); + +static const mp_stream_p_t vfs_rom_fileio_stream_p = { + .read = vfs_rom_file_read, + .ioctl = vfs_rom_file_ioctl, +}; + +static MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_rom_fileio, + MP_QSTR_FileIO, + MP_TYPE_FLAG_ITER_IS_STREAM, + buffer, vfs_rom_file_get_buffer, + protocol, &vfs_rom_fileio_stream_p, + locals_dict, &vfs_rom_rawfile_locals_dict + ); + +static const mp_stream_p_t vfs_rom_textio_stream_p = { + .read = vfs_rom_file_read, + .ioctl = vfs_rom_file_ioctl, + .is_text = true, +}; + +static MP_DEFINE_CONST_OBJ_TYPE( + mp_type_vfs_rom_textio, + MP_QSTR_TextIOWrapper, + MP_TYPE_FLAG_ITER_IS_STREAM, + protocol, &vfs_rom_textio_stream_p, + locals_dict, &vfs_rom_rawfile_locals_dict + ); + +#endif // MICROPY_VFS_ROM diff --git a/extmod/virtpin.c b/extmod/virtpin.c deleted file mode 100644 index cd0b9f92f830e..0000000000000 --- a/extmod/virtpin.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "extmod/virtpin.h" - -int mp_virtual_pin_read(mp_obj_t pin) { - mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); - return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL); -} - -void mp_virtual_pin_write(mp_obj_t pin, int value) { - mp_obj_base_t *s = (mp_obj_base_t *)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t *)MP_OBJ_TYPE_GET_SLOT(s->type, protocol); - pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL); -} diff --git a/extmod/virtpin.h b/extmod/virtpin.h deleted file mode 100644 index 81094f21cf16e..0000000000000 --- a/extmod/virtpin.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_EXTMOD_VIRTPIN_H -#define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H - -#include "py/obj.h" -// CIRCUITPY-CHANGE -#include "py/proto.h" - -#define MP_PIN_READ (1) -#define MP_PIN_WRITE (2) -#define MP_PIN_INPUT (3) -#define MP_PIN_OUTPUT (4) - -// Pin protocol -typedef struct _mp_pin_p_t { - // CIRCUITPY-CHANGE - MP_PROTOCOL_HEAD - mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); -} mp_pin_p_t; - -int mp_virtual_pin_read(mp_obj_t pin); -void mp_virtual_pin_write(mp_obj_t pin, int value); - -// If a port exposes a Pin object, it's constructor should be like this -mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); - -#endif // MICROPY_INCLUDED_EXTMOD_VIRTPIN_H diff --git a/frozen/Adafruit_CircuitPython_AHTx0 b/frozen/Adafruit_CircuitPython_AHTx0 index d6e60adfae22a..043c7163c1d66 160000 --- a/frozen/Adafruit_CircuitPython_AHTx0 +++ b/frozen/Adafruit_CircuitPython_AHTx0 @@ -1 +1 @@ -Subproject commit d6e60adfae22a8d2bf94c2e207c4a4e9f0bfc7f8 +Subproject commit 043c7163c1d66a9d3ef2150e6140f92af973c9b1 diff --git a/frozen/Adafruit_CircuitPython_APDS9960 b/frozen/Adafruit_CircuitPython_APDS9960 index ebccbd6e8c927..0134a126af843 160000 --- a/frozen/Adafruit_CircuitPython_APDS9960 +++ b/frozen/Adafruit_CircuitPython_APDS9960 @@ -1 +1 @@ -Subproject commit ebccbd6e8c927905d62bd0cc5832109920d413b2 +Subproject commit 0134a126af8430126c9a569a29958802716262fc diff --git a/frozen/Adafruit_CircuitPython_BLE b/frozen/Adafruit_CircuitPython_BLE index 9f2da7ce2ad61..63c9af9a343c6 160000 --- a/frozen/Adafruit_CircuitPython_BLE +++ b/frozen/Adafruit_CircuitPython_BLE @@ -1 +1 @@ -Subproject commit 9f2da7ce2ad6116ea97e1980bb55f0fed4774856 +Subproject commit 63c9af9a343c68ebbd013054b799d2e35a513343 diff --git a/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center b/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center index 7f5498803921b..a636fc984dced 160000 --- a/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center +++ b/frozen/Adafruit_CircuitPython_BLE_Apple_Notification_Center @@ -1 +1 @@ -Subproject commit 7f5498803921b61168fe108b386653fa0a930ad1 +Subproject commit a636fc984dced58f5f0815c5c531a03ee092f7ad diff --git a/frozen/Adafruit_CircuitPython_Bitmap_Font b/frozen/Adafruit_CircuitPython_Bitmap_Font index 735d8167df6bf..2b320bb26492b 160000 --- a/frozen/Adafruit_CircuitPython_Bitmap_Font +++ b/frozen/Adafruit_CircuitPython_Bitmap_Font @@ -1 +1 @@ -Subproject commit 735d8167df6bffcda71b5338e7c6df0268a39b7e +Subproject commit 2b320bb26492b84d3ddabb2cd712d8db41a8b983 diff --git a/frozen/Adafruit_CircuitPython_BusDevice b/frozen/Adafruit_CircuitPython_BusDevice index 88250a1e29a80..d4b283c85b7b2 160000 --- a/frozen/Adafruit_CircuitPython_BusDevice +++ b/frozen/Adafruit_CircuitPython_BusDevice @@ -1 +1 @@ -Subproject commit 88250a1e29a806dfc2a9dd9045bb0591a1178cca +Subproject commit d4b283c85b7b2043eb0d095638a47305a1f4ef61 diff --git a/frozen/Adafruit_CircuitPython_CircuitPlayground b/frozen/Adafruit_CircuitPython_CircuitPlayground index 9c25878e0b7bf..2ee9b7ddd9d85 160000 --- a/frozen/Adafruit_CircuitPython_CircuitPlayground +++ b/frozen/Adafruit_CircuitPython_CircuitPlayground @@ -1 +1 @@ -Subproject commit 9c25878e0b7bf2ad2085190a3d8be78579006667 +Subproject commit 2ee9b7ddd9d8574f1a154c67b5c849d2e44e3435 diff --git a/frozen/Adafruit_CircuitPython_ConnectionManager b/frozen/Adafruit_CircuitPython_ConnectionManager index 67d649b363cc3..89e59ec81bdfa 160000 --- a/frozen/Adafruit_CircuitPython_ConnectionManager +++ b/frozen/Adafruit_CircuitPython_ConnectionManager @@ -1 +1 @@ -Subproject commit 67d649b363cc3464b7959652a32cb62662ee60c3 +Subproject commit 89e59ec81bdfa7349b08ba3adf0d3cefc57af4d2 diff --git a/frozen/Adafruit_CircuitPython_Crickit b/frozen/Adafruit_CircuitPython_Crickit index 9aadbbd6e3cad..e3c372fecf720 160000 --- a/frozen/Adafruit_CircuitPython_Crickit +++ b/frozen/Adafruit_CircuitPython_Crickit @@ -1 +1 @@ -Subproject commit 9aadbbd6e3cad460cbe49bf3c73792df66bf9fe5 +Subproject commit e3c372fecf7209320826009de88818d91809cff6 diff --git a/frozen/Adafruit_CircuitPython_DRV2605 b/frozen/Adafruit_CircuitPython_DRV2605 index 90e9f4302225e..18b7397ec2123 160000 --- a/frozen/Adafruit_CircuitPython_DRV2605 +++ b/frozen/Adafruit_CircuitPython_DRV2605 @@ -1 +1 @@ -Subproject commit 90e9f4302225e9111afd394e5dcb174e96847b28 +Subproject commit 18b7397ec21235fc398625a52f995a3be31eb59a diff --git a/frozen/Adafruit_CircuitPython_DS3231 b/frozen/Adafruit_CircuitPython_DS3231 index 7b99df2081e7b..552104c8aed47 160000 --- a/frozen/Adafruit_CircuitPython_DS3231 +++ b/frozen/Adafruit_CircuitPython_DS3231 @@ -1 +1 @@ -Subproject commit 7b99df2081e7b700d052ad9b455d41cbba43c302 +Subproject commit 552104c8aed472c7437413e94b8954e63b4a4d4d diff --git a/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 b/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 index 40d7b8eb7a7d8..8c7acd451ad53 160000 --- a/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 +++ b/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 @@ -1 +1 @@ -Subproject commit 40d7b8eb7a7d8fc91a62414d4f764dd48283d86d +Subproject commit 8c7acd451ad53f7dc3b33a704c885032a03c1064 diff --git a/frozen/Adafruit_CircuitPython_Display_Shapes b/frozen/Adafruit_CircuitPython_Display_Shapes index 2742ae5025b0a..bf6c2addf2465 160000 --- a/frozen/Adafruit_CircuitPython_Display_Shapes +++ b/frozen/Adafruit_CircuitPython_Display_Shapes @@ -1 +1 @@ -Subproject commit 2742ae5025b0a9bcc853a8b89b293f8e46331498 +Subproject commit bf6c2addf2465625de747d2f4ea1613fcded7840 diff --git a/frozen/Adafruit_CircuitPython_Display_Text b/frozen/Adafruit_CircuitPython_Display_Text index 535317831ffa6..6450c7a3dc4c1 160000 --- a/frozen/Adafruit_CircuitPython_Display_Text +++ b/frozen/Adafruit_CircuitPython_Display_Text @@ -1 +1 @@ -Subproject commit 535317831ffa667180902595daa666be153989eb +Subproject commit 6450c7a3dc4c16c4af4b75eda549537dffb5a73c diff --git a/frozen/Adafruit_CircuitPython_DotStar b/frozen/Adafruit_CircuitPython_DotStar index 1945d1aa9c523..a12e2ce2046af 160000 --- a/frozen/Adafruit_CircuitPython_DotStar +++ b/frozen/Adafruit_CircuitPython_DotStar @@ -1 +1 @@ -Subproject commit 1945d1aa9c5232287c490fbb6d637c92d866ed01 +Subproject commit a12e2ce2046afc1791ca6aa2bdeb33cb97f7def0 diff --git a/frozen/Adafruit_CircuitPython_ESP32SPI b/frozen/Adafruit_CircuitPython_ESP32SPI index e7e129aa6d9fe..ec1d2e66ace17 160000 --- a/frozen/Adafruit_CircuitPython_ESP32SPI +++ b/frozen/Adafruit_CircuitPython_ESP32SPI @@ -1 +1 @@ -Subproject commit e7e129aa6d9fec4e0844ec195c184073c8a1f5d3 +Subproject commit ec1d2e66ace176c13d7128a839287601a97a6bda diff --git a/frozen/Adafruit_CircuitPython_FakeRequests b/frozen/Adafruit_CircuitPython_FakeRequests index 248d7b1413491..f9f9d061a6645 160000 --- a/frozen/Adafruit_CircuitPython_FakeRequests +++ b/frozen/Adafruit_CircuitPython_FakeRequests @@ -1 +1 @@ -Subproject commit 248d7b14134915883b4693fddf74bb77cca2ffd1 +Subproject commit f9f9d061a66453e0d3164ffd4e046ed3b6007669 diff --git a/frozen/Adafruit_CircuitPython_FocalTouch b/frozen/Adafruit_CircuitPython_FocalTouch index 6d3d68872179b..e18ecd678ec3a 160000 --- a/frozen/Adafruit_CircuitPython_FocalTouch +++ b/frozen/Adafruit_CircuitPython_FocalTouch @@ -1 +1 @@ -Subproject commit 6d3d68872179b3a2b681779dd1e73db92b9b8f5e +Subproject commit e18ecd678ec3ac4fef884db18ddb2aab56bf44f9 diff --git a/frozen/Adafruit_CircuitPython_HID b/frozen/Adafruit_CircuitPython_HID index be6db4658d269..a147d3b5b9763 160000 --- a/frozen/Adafruit_CircuitPython_HID +++ b/frozen/Adafruit_CircuitPython_HID @@ -1 +1 @@ -Subproject commit be6db4658d26902b6d5191d16de658adb92d018a +Subproject commit a147d3b5b976371601b460622209d327f51eb681 diff --git a/frozen/Adafruit_CircuitPython_HTTPServer b/frozen/Adafruit_CircuitPython_HTTPServer index 9b16e16f5b1c1..d55c6f54aba54 160000 --- a/frozen/Adafruit_CircuitPython_HTTPServer +++ b/frozen/Adafruit_CircuitPython_HTTPServer @@ -1 +1 @@ -Subproject commit 9b16e16f5b1c1a346fb57ffcd0c6db9538a20803 +Subproject commit d55c6f54aba54df9b0e0b9d83ddf7fca46eea5e4 diff --git a/frozen/Adafruit_CircuitPython_IRRemote b/frozen/Adafruit_CircuitPython_IRRemote index c4daaa7521a49..646cc051881a0 160000 --- a/frozen/Adafruit_CircuitPython_IRRemote +++ b/frozen/Adafruit_CircuitPython_IRRemote @@ -1 +1 @@ -Subproject commit c4daaa7521a491f7045cf10007764e95e4e2c265 +Subproject commit 646cc051881a07d8bd5c442320479c6e5e553567 diff --git a/frozen/Adafruit_CircuitPython_IS31FL3731 b/frozen/Adafruit_CircuitPython_IS31FL3731 index 9f1202c3c6879..c011e8e0d021a 160000 --- a/frozen/Adafruit_CircuitPython_IS31FL3731 +++ b/frozen/Adafruit_CircuitPython_IS31FL3731 @@ -1 +1 @@ -Subproject commit 9f1202c3c6879c62d70058b0f43f21ef51c2ebe6 +Subproject commit c011e8e0d021a6c5870242eb721f012922002fc8 diff --git a/frozen/Adafruit_CircuitPython_ImageLoad b/frozen/Adafruit_CircuitPython_ImageLoad index 72a7a4a0f6bb9..458bc46b63ea2 160000 --- a/frozen/Adafruit_CircuitPython_ImageLoad +++ b/frozen/Adafruit_CircuitPython_ImageLoad @@ -1 +1 @@ -Subproject commit 72a7a4a0f6bb99cd0ab50d21988dea6d2321bf72 +Subproject commit 458bc46b63ea2bfc51529b05b62b4df3c5902e17 diff --git a/frozen/Adafruit_CircuitPython_LC709203F b/frozen/Adafruit_CircuitPython_LC709203F index 2809e03a16b53..e32e39a18d23a 160000 --- a/frozen/Adafruit_CircuitPython_LC709203F +++ b/frozen/Adafruit_CircuitPython_LC709203F @@ -1 +1 @@ -Subproject commit 2809e03a16b53e0a131c37d4dbe2140d7412c402 +Subproject commit e32e39a18d23ae58fe97b3472253b6cbcbc8ebd0 diff --git a/frozen/Adafruit_CircuitPython_LED_Animation b/frozen/Adafruit_CircuitPython_LED_Animation index 576a094602b09..7cc736df1628f 160000 --- a/frozen/Adafruit_CircuitPython_LED_Animation +++ b/frozen/Adafruit_CircuitPython_LED_Animation @@ -1 +1 @@ -Subproject commit 576a094602b099a1f211f126f68ff3cb07d32a05 +Subproject commit 7cc736df1628f767c4fc6f23287cedbf6e80f4ce diff --git a/frozen/Adafruit_CircuitPython_LIS3DH b/frozen/Adafruit_CircuitPython_LIS3DH index 8591697e54f04..ca871b8bc59b2 160000 --- a/frozen/Adafruit_CircuitPython_LIS3DH +++ b/frozen/Adafruit_CircuitPython_LIS3DH @@ -1 +1 @@ -Subproject commit 8591697e54f04711f2ed309753ddf4b334b05114 +Subproject commit ca871b8bc59b23acbfd779bf59d420599e8bcbb5 diff --git a/frozen/Adafruit_CircuitPython_LSM6DS b/frozen/Adafruit_CircuitPython_LSM6DS index c4d6b88c5d537..9d94dc6a3350c 160000 --- a/frozen/Adafruit_CircuitPython_LSM6DS +++ b/frozen/Adafruit_CircuitPython_LSM6DS @@ -1 +1 @@ -Subproject commit c4d6b88c5d537e0ba6b430987ccb2020475dc2e5 +Subproject commit 9d94dc6a3350cb8766baa4a1247e36576b00f68a diff --git a/frozen/Adafruit_CircuitPython_MIDI b/frozen/Adafruit_CircuitPython_MIDI index 36f8d5ab01dc8..5feb31fbd31f2 160000 --- a/frozen/Adafruit_CircuitPython_MIDI +++ b/frozen/Adafruit_CircuitPython_MIDI @@ -1 +1 @@ -Subproject commit 36f8d5ab01dc82f41b6779683bd32130ad798848 +Subproject commit 5feb31fbd31f2475862e0cb55c89359cb688ad34 diff --git a/frozen/Adafruit_CircuitPython_MPU6050 b/frozen/Adafruit_CircuitPython_MPU6050 index 58a9a05c0c4ad..d3761591ccf76 160000 --- a/frozen/Adafruit_CircuitPython_MPU6050 +++ b/frozen/Adafruit_CircuitPython_MPU6050 @@ -1 +1 @@ -Subproject commit 58a9a05c0c4ada11ea9f18c953f62eab97b94c17 +Subproject commit d3761591ccf7629b39675dd1db45184b96a3b779 diff --git a/frozen/Adafruit_CircuitPython_Motor b/frozen/Adafruit_CircuitPython_Motor index 0c598f67c4688..f55b2910b0109 160000 --- a/frozen/Adafruit_CircuitPython_Motor +++ b/frozen/Adafruit_CircuitPython_Motor @@ -1 +1 @@ -Subproject commit 0c598f67c4688f0108b9671c2834ef343032906b +Subproject commit f55b2910b01094904461d769581221c20418a267 diff --git a/frozen/Adafruit_CircuitPython_NeoPixel b/frozen/Adafruit_CircuitPython_NeoPixel index 310621f32839b..d3eaf5c45dde4 160000 --- a/frozen/Adafruit_CircuitPython_NeoPixel +++ b/frozen/Adafruit_CircuitPython_NeoPixel @@ -1 +1 @@ -Subproject commit 310621f32839b73f892b227650c5d002a310e7c5 +Subproject commit d3eaf5c45dde45588f9a2eb2ffbe0b9025251bee diff --git a/frozen/Adafruit_CircuitPython_OPT4048 b/frozen/Adafruit_CircuitPython_OPT4048 new file mode 160000 index 0000000000000..ddfe6b13acef7 --- /dev/null +++ b/frozen/Adafruit_CircuitPython_OPT4048 @@ -0,0 +1 @@ +Subproject commit ddfe6b13acef7076333ee8e0ecd27bc4186512b9 diff --git a/frozen/Adafruit_CircuitPython_PCF8563 b/frozen/Adafruit_CircuitPython_PCF8563 index cadd17904543d..16e3112885b0b 160000 --- a/frozen/Adafruit_CircuitPython_PCF8563 +++ b/frozen/Adafruit_CircuitPython_PCF8563 @@ -1 +1 @@ -Subproject commit cadd17904543d43c5ef19206ed8471b3476f119c +Subproject commit 16e3112885b0b6149b4dfa1749181424dd5da122 diff --git a/frozen/Adafruit_CircuitPython_Pixel_Framebuf b/frozen/Adafruit_CircuitPython_Pixel_Framebuf index b09586b52dcfd..555b30acf78ba 160000 --- a/frozen/Adafruit_CircuitPython_Pixel_Framebuf +++ b/frozen/Adafruit_CircuitPython_Pixel_Framebuf @@ -1 +1 @@ -Subproject commit b09586b52dcfd51e8730a126899b4128df258a8c +Subproject commit 555b30acf78ba65cec48f64b3350e19fddada4ce diff --git a/frozen/Adafruit_CircuitPython_PortalBase b/frozen/Adafruit_CircuitPython_PortalBase index e23cc47d97a97..b67904c7bca12 160000 --- a/frozen/Adafruit_CircuitPython_PortalBase +++ b/frozen/Adafruit_CircuitPython_PortalBase @@ -1 +1 @@ -Subproject commit e23cc47d97a97a3dc65b951c0bfc085668c8d1b1 +Subproject commit b67904c7bca12d7ee443e16bc40d64fd67c7cb48 diff --git a/frozen/Adafruit_CircuitPython_ProgressBar b/frozen/Adafruit_CircuitPython_ProgressBar index ac96488c8caae..fab168ab38f61 160000 --- a/frozen/Adafruit_CircuitPython_ProgressBar +++ b/frozen/Adafruit_CircuitPython_ProgressBar @@ -1 +1 @@ -Subproject commit ac96488c8caaeb18eaed7a83289f81380eba2978 +Subproject commit fab168ab38f61f654735140c67c7defdad512de8 diff --git a/frozen/Adafruit_CircuitPython_RFM69 b/frozen/Adafruit_CircuitPython_RFM69 index 5e050c4596fd6..1837cb10b353a 160000 --- a/frozen/Adafruit_CircuitPython_RFM69 +++ b/frozen/Adafruit_CircuitPython_RFM69 @@ -1 +1 @@ -Subproject commit 5e050c4596fd639d91fbd63ae99617b75485c7af +Subproject commit 1837cb10b353a6349c33d87c0f045c80c08003e3 diff --git a/frozen/Adafruit_CircuitPython_RFM9x b/frozen/Adafruit_CircuitPython_RFM9x index c5c3d629d42dc..ad3a28df5e0ca 160000 --- a/frozen/Adafruit_CircuitPython_RFM9x +++ b/frozen/Adafruit_CircuitPython_RFM9x @@ -1 +1 @@ -Subproject commit c5c3d629d42dc56bc34d892306582947385cf133 +Subproject commit ad3a28df5e0cab2a24b9a6acf0667fe7c5a26563 diff --git a/frozen/Adafruit_CircuitPython_Register b/frozen/Adafruit_CircuitPython_Register index d37349183b82c..2a7039c548456 160000 --- a/frozen/Adafruit_CircuitPython_Register +++ b/frozen/Adafruit_CircuitPython_Register @@ -1 +1 @@ -Subproject commit d37349183b82cd7d05af57a77eb3765e17e7be3f +Subproject commit 2a7039c548456ddf7573814967ce494f61adbc46 diff --git a/frozen/Adafruit_CircuitPython_Requests b/frozen/Adafruit_CircuitPython_Requests index 6c56de79fb49e..44186adfc6a98 160000 --- a/frozen/Adafruit_CircuitPython_Requests +++ b/frozen/Adafruit_CircuitPython_Requests @@ -1 +1 @@ -Subproject commit 6c56de79fb49ef16164148b68a63336d82b69f7a +Subproject commit 44186adfc6a982f26007cba2b103dd65cbb68c65 diff --git a/frozen/Adafruit_CircuitPython_SD b/frozen/Adafruit_CircuitPython_SD index 8688597c753b7..c700b45d484a7 160000 --- a/frozen/Adafruit_CircuitPython_SD +++ b/frozen/Adafruit_CircuitPython_SD @@ -1 +1 @@ -Subproject commit 8688597c753b76beb8a834daef592294ffba216c +Subproject commit c700b45d484a7e5054cf1856b871f3f25edb5ebb diff --git a/frozen/Adafruit_CircuitPython_SHT4x b/frozen/Adafruit_CircuitPython_SHT4x index a727b08bc7046..2b5317830e662 160000 --- a/frozen/Adafruit_CircuitPython_SHT4x +++ b/frozen/Adafruit_CircuitPython_SHT4x @@ -1 +1 @@ -Subproject commit a727b08bc7046a997d5f10e8b59a81bbe0f54da2 +Subproject commit 2b5317830e66233017e68f8b459261bc4240307d diff --git a/frozen/Adafruit_CircuitPython_SSD1306 b/frozen/Adafruit_CircuitPython_SSD1306 index a990c874389b6..04d8d531e8ed2 160000 --- a/frozen/Adafruit_CircuitPython_SSD1306 +++ b/frozen/Adafruit_CircuitPython_SSD1306 @@ -1 +1 @@ -Subproject commit a990c874389b6fd27636b21f9b831fc91781e925 +Subproject commit 04d8d531e8ed2df45c061c8b3c6d91abda001f13 diff --git a/frozen/Adafruit_CircuitPython_SSD1680 b/frozen/Adafruit_CircuitPython_SSD1680 index 5417f6225fb05..c98b43e11eca5 160000 --- a/frozen/Adafruit_CircuitPython_SSD1680 +++ b/frozen/Adafruit_CircuitPython_SSD1680 @@ -1 +1 @@ -Subproject commit 5417f6225fb0573853972852ebdfa3aa080fed93 +Subproject commit c98b43e11eca52c9885c48e866325595f5614eb8 diff --git a/frozen/Adafruit_CircuitPython_ST7789 b/frozen/Adafruit_CircuitPython_ST7789 index fd4c53e6b0ed4..8fb8cbf7c4cf4 160000 --- a/frozen/Adafruit_CircuitPython_ST7789 +++ b/frozen/Adafruit_CircuitPython_ST7789 @@ -1 +1 @@ -Subproject commit fd4c53e6b0ed4805362362837aa7dd71ae7fe1da +Subproject commit 8fb8cbf7c4cf404c1334df67a7512ccf99a00c52 diff --git a/frozen/Adafruit_CircuitPython_SimpleIO b/frozen/Adafruit_CircuitPython_SimpleIO index 967a12a68c4b8..b024e7276cf37 160000 --- a/frozen/Adafruit_CircuitPython_SimpleIO +++ b/frozen/Adafruit_CircuitPython_SimpleIO @@ -1 +1 @@ -Subproject commit 967a12a68c4b82048cb5efe99847408215188561 +Subproject commit b024e7276cf3796dddcced3cbe438195d310661b diff --git a/frozen/Adafruit_CircuitPython_SimpleMath b/frozen/Adafruit_CircuitPython_SimpleMath index 4bb3eb415019c..9ebbdae834ca3 160000 --- a/frozen/Adafruit_CircuitPython_SimpleMath +++ b/frozen/Adafruit_CircuitPython_SimpleMath @@ -1 +1 @@ -Subproject commit 4bb3eb415019cb7c143dd6c467289e20409af788 +Subproject commit 9ebbdae834ca3225bf411ba54c9e3148d8c26b6c diff --git a/frozen/Adafruit_CircuitPython_Thermistor b/frozen/Adafruit_CircuitPython_Thermistor index 09034b0fe5221..bdfeb28d741a0 160000 --- a/frozen/Adafruit_CircuitPython_Thermistor +++ b/frozen/Adafruit_CircuitPython_Thermistor @@ -1 +1 @@ -Subproject commit 09034b0fe5221faf8c2c01042e97a9d6334a1680 +Subproject commit bdfeb28d741a0233c4d8789b610d116831c9c0dd diff --git a/frozen/Adafruit_CircuitPython_Ticks b/frozen/Adafruit_CircuitPython_Ticks index 527d90e91fa70..415f35dceaf43 160000 --- a/frozen/Adafruit_CircuitPython_Ticks +++ b/frozen/Adafruit_CircuitPython_Ticks @@ -1 +1 @@ -Subproject commit 527d90e91fa70d08399291229bdcb2e9a6605a6a +Subproject commit 415f35dceaf43f6e2bbc879f7049fed5e52f3c4a diff --git a/frozen/Adafruit_CircuitPython_UC8151D b/frozen/Adafruit_CircuitPython_UC8151D index a74fbafaecc5e..ec3fd72eb4219 160000 --- a/frozen/Adafruit_CircuitPython_UC8151D +++ b/frozen/Adafruit_CircuitPython_UC8151D @@ -1 +1 @@ -Subproject commit a74fbafaecc5e44b462ef5ee2538e6a3ebf676e8 +Subproject commit ec3fd72eb4219520c2ad5dd33e2e865a7e4b9d6a diff --git a/frozen/Adafruit_CircuitPython_Wave b/frozen/Adafruit_CircuitPython_Wave index 71f20ac457ba7..10f7ed33cbf75 160000 --- a/frozen/Adafruit_CircuitPython_Wave +++ b/frozen/Adafruit_CircuitPython_Wave @@ -1 +1 @@ -Subproject commit 71f20ac457ba73d462c9851ce0d7c3c466efa3c3 +Subproject commit 10f7ed33cbf75b0f42ffe9aae721f57583a33ce6 diff --git a/frozen/Adafruit_CircuitPython_Wiznet5k b/frozen/Adafruit_CircuitPython_Wiznet5k index 6abacdf332602..1e786b93a5a1d 160000 --- a/frozen/Adafruit_CircuitPython_Wiznet5k +++ b/frozen/Adafruit_CircuitPython_Wiznet5k @@ -1 +1 @@ -Subproject commit 6abacdf332602afb35fce0e68763c1b47e0c0297 +Subproject commit 1e786b93a5a1dede2fa6f44634336f666d153f6a diff --git a/frozen/Adafruit_CircuitPython_asyncio b/frozen/Adafruit_CircuitPython_asyncio index 2ea2b06c7dcc4..d0d63f113c7da 160000 --- a/frozen/Adafruit_CircuitPython_asyncio +++ b/frozen/Adafruit_CircuitPython_asyncio @@ -1 +1 @@ -Subproject commit 2ea2b06c7dcc41538790cc4cef5bc3e709b80762 +Subproject commit d0d63f113c7da0852bdc5aa303cd738e45d40fbc diff --git a/frozen/Adafruit_CircuitPython_framebuf b/frozen/Adafruit_CircuitPython_framebuf index dd4c4e927819f..3d2036d2926f7 160000 --- a/frozen/Adafruit_CircuitPython_framebuf +++ b/frozen/Adafruit_CircuitPython_framebuf @@ -1 +1 @@ -Subproject commit dd4c4e927819f51ff1b1aa45ff11750581628d79 +Subproject commit 3d2036d2926f7d04a00908845dd14cb18e3d8b90 diff --git a/frozen/Adafruit_CircuitPython_seesaw b/frozen/Adafruit_CircuitPython_seesaw index 3109848de6c7d..daab794981f17 160000 --- a/frozen/Adafruit_CircuitPython_seesaw +++ b/frozen/Adafruit_CircuitPython_seesaw @@ -1 +1 @@ -Subproject commit 3109848de6c7de1755ac2ccdcfc58460b7cc09bf +Subproject commit daab794981f177041fe1a4a9266a9688c45480e9 diff --git a/frozen/CircuitPython_edupico2_paj7620 b/frozen/CircuitPython_edupico2_paj7620 new file mode 160000 index 0000000000000..16a4d78472499 --- /dev/null +++ b/frozen/CircuitPython_edupico2_paj7620 @@ -0,0 +1 @@ +Subproject commit 16a4d784724992862cffd594aeed8c627ecc18b3 diff --git a/frozen/circuitpython-stage b/frozen/circuitpython-stage index 25e35a8620bfa..7b71363acb67c 160000 --- a/frozen/circuitpython-stage +++ b/frozen/circuitpython-stage @@ -1 +1 @@ -Subproject commit 25e35a8620bfab08ff4ec30bf89667dca0b05fcf +Subproject commit 7b71363acb67cb1b254b12607f35280cfb4ad6c1 diff --git a/frozen/pew-pewpew-lcd b/frozen/pew-pewpew-lcd index 5ef39129207d5..56ed57038f2b6 160000 --- a/frozen/pew-pewpew-lcd +++ b/frozen/pew-pewpew-lcd @@ -1 +1 @@ -Subproject commit 5ef39129207d5b9ad52b839f934ccdd0a8a7ed8a +Subproject commit 56ed57038f2b64d108786d53996e41f63986eebf diff --git a/lib/berkeley-db-1.xx b/lib/berkeley-db-1.xx index 35aaec4418ad7..0f3bb6947c2f5 160000 --- a/lib/berkeley-db-1.xx +++ b/lib/berkeley-db-1.xx @@ -1 +1 @@ -Subproject commit 35aaec4418ad78628a3b935885dd189d41ce779b +Subproject commit 0f3bb6947c2f57233916dccd7bb425d7bf86e5a6 diff --git a/lib/certificates b/lib/certificates index ad28d2ee548bd..d7c6385f67166 160000 --- a/lib/certificates +++ b/lib/certificates @@ -1 +1 @@ -Subproject commit ad28d2ee548bd55033f0a88df6f8902589c365a6 +Subproject commit d7c6385f671665820ea2d307b0a94f9e61ef6f91 diff --git a/lib/libffi b/lib/libffi index e9de7e35f2339..3d0ce1e6fcf19 160000 --- a/lib/libffi +++ b/lib/libffi @@ -1 +1 @@ -Subproject commit e9de7e35f2339598b16cbb375f9992643ed81209 +Subproject commit 3d0ce1e6fcf19f853894862abcbac0ae78a7be60 diff --git a/lib/libm/libm.h b/lib/libm/libm.h index f782249e53465..75a2a775f8945 100644 --- a/lib/libm/libm.h +++ b/lib/libm/libm.h @@ -19,7 +19,15 @@ #include #include +// CIRCUITPY-CHANGE: prevent undefined warnings +#ifndef FLT_EVAL_METHOD #define FLT_EVAL_METHOD 0 +#endif + +// These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this. +// If compilation fails here then check the host compiler's FLT_EVAL_METHOD. +typedef float float_t; +typedef double double_t; #define FORCE_EVAL(x) do { \ if (sizeof(x) == sizeof(float)) { \ diff --git a/lib/libm/wf_lgamma.c b/lib/libm/wf_lgamma.c index bcf3705420ec8..7580d2f74e5a8 100644 --- a/lib/libm/wf_lgamma.c +++ b/lib/libm/wf_lgamma.c @@ -24,7 +24,9 @@ */ #include "fdlibm.h" +#ifndef _IEEE_LIBM #define _IEEE_LIBM 1 +#endif #ifdef __STDC__ float lgammaf(float x) diff --git a/lib/libm/wf_tgamma.c b/lib/libm/wf_tgamma.c index 3ff05f331d099..1a6c74ca11d86 100644 --- a/lib/libm/wf_tgamma.c +++ b/lib/libm/wf_tgamma.c @@ -24,7 +24,9 @@ #include "math.h" #include "fdlibm.h" +#ifndef _IEEE_LIBM #define _IEEE_LIBM 1 +#endif #ifdef __STDC__ float tgammaf(float x) diff --git a/lib/libm_dbl/libm.h b/lib/libm_dbl/libm.h index dc0b431a44857..fa49ad1cddda5 100644 --- a/lib/libm_dbl/libm.h +++ b/lib/libm_dbl/libm.h @@ -15,7 +15,10 @@ #include #include -#define FLT_EVAL_METHOD 0 +// These lines verify that FLT_EVAL_METHOD==0, MicroPython's libm requires this. +// If compilation fails here then check the host compiler's FLT_EVAL_METHOD. +typedef float float_t; +typedef double double_t; #define FORCE_EVAL(x) do { \ if (sizeof(x) == sizeof(float)) { \ @@ -86,7 +89,9 @@ do { \ (d) = __u.f; \ } while (0) +#if !defined(DBL_EPSILON) #define DBL_EPSILON 2.22044604925031308085e-16 +#endif int __rem_pio2(double, double*); int __rem_pio2_large(double*, double*, int, int, int); diff --git a/lib/libm_dbl/rint.c b/lib/libm_dbl/rint.c index fbba390e7d723..b85dec8f2465e 100644 --- a/lib/libm_dbl/rint.c +++ b/lib/libm_dbl/rint.c @@ -2,7 +2,7 @@ #include #include -#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 +#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 || FLT_EVAL_METHOD==16 #define EPS DBL_EPSILON #elif FLT_EVAL_METHOD==2 #define EPS LDBL_EPSILON diff --git a/lib/littlefs/lfs1.c b/lib/littlefs/lfs1.c index 6a3fd670012cc..ec18dc470258c 100644 --- a/lib/littlefs/lfs1.c +++ b/lib/littlefs/lfs1.c @@ -2141,7 +2141,7 @@ int lfs1_format(lfs1_t *lfs1, const struct lfs1_config *cfg) { .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, .d.nlen = sizeof(superblock.d.magic), .d.version = LFS1_DISK_VERSION, - .d.magic = {"littlefs"}, + .d.magic = {'l', 'i', 't', 't', 'l', 'e', 'f', 's'}, .d.block_size = lfs1->cfg->block_size, .d.block_count = lfs1->cfg->block_count, .d.root = {lfs1->root[0], lfs1->root[1]}, diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c index 613213669c8f7..8d18b7d110521 100644 --- a/lib/littlefs/lfs2.c +++ b/lib/littlefs/lfs2.c @@ -93,6 +93,7 @@ static int lfs2_bd_read(lfs2_t *lfs2, // bypass cache? diff = lfs2_aligndown(diff, lfs2->cfg->read_size); int err = lfs2->cfg->read(lfs2->cfg, block, off, data, diff); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -282,6 +283,21 @@ static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) { /// Small type-level utilities /// + +// some operations on paths +static inline lfs2_size_t lfs2_path_namelen(const char *path) { + return strcspn(path, "/"); +} + +static inline bool lfs2_path_islast(const char *path) { + lfs2_size_t namelen = lfs2_path_namelen(path); + return path[namelen + strspn(path + namelen, "/")] == '\0'; +} + +static inline bool lfs2_path_isdir(const char *path) { + return path[lfs2_path_namelen(path)] != '\0'; +} + // operations on block pairs static inline void lfs2_pair_swap(lfs2_block_t pair[2]) { lfs2_block_t t = pair[0]; @@ -389,18 +405,15 @@ struct lfs2_diskoff { // operations on global state static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) { - for (int i = 0; i < 3; i++) { - ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i]; - } + a->tag ^= b->tag; + a->pair[0] ^= b->pair[0]; + a->pair[1] ^= b->pair[1]; } static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) { - for (int i = 0; i < 3; i++) { - if (((uint32_t*)a)[i] != 0) { - return false; - } - } - return true; + return a->tag == 0 + && a->pair[0] == 0 + && a->pair[1] == 0; } #ifndef LFS2_READONLY @@ -550,9 +563,9 @@ static int lfs2_dir_compact(lfs2_t *lfs2, lfs2_mdir_t *source, uint16_t begin, uint16_t end); static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size); -static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size); -static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file); +static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file); static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file); static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file); @@ -574,65 +587,72 @@ static int lfs21_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); #endif -static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir); +static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir); static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size); -static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size); -static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file); -static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file); +static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file); +static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file); -static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2); -static int lfs2_fs_rawtraverse(lfs2_t *lfs2, +static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2); +static int lfs2_fs_traverse_(lfs2_t *lfs2, int (*cb)(void *data, lfs2_block_t block), void *data, bool includeorphans); static int lfs2_deinit(lfs2_t *lfs2); -static int lfs2_rawunmount(lfs2_t *lfs2); +static int lfs2_unmount_(lfs2_t *lfs2); /// Block allocator /// + +// allocations should call this when all allocated blocks are committed to +// the filesystem +// +// after a checkpoint, the block allocator may realloc any untracked blocks +static void lfs2_alloc_ckpoint(lfs2_t *lfs2) { + lfs2->lookahead.ckpoint = lfs2->block_count; +} + +// drop the lookahead buffer, this is done during mounting and failed +// traversals in order to avoid invalid lookahead state +static void lfs2_alloc_drop(lfs2_t *lfs2) { + lfs2->lookahead.size = 0; + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); +} + #ifndef LFS2_READONLY static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) { lfs2_t *lfs2 = (lfs2_t*)p; - lfs2_block_t off = ((block - lfs2->free.off) + lfs2_block_t off = ((block - lfs2->lookahead.start) + lfs2->block_count) % lfs2->block_count; - if (off < lfs2->free.size) { - lfs2->free.buffer[off / 32] |= 1U << (off % 32); + if (off < lfs2->lookahead.size) { + lfs2->lookahead.buffer[off / 8] |= 1U << (off % 8); } return 0; } #endif -// indicate allocated blocks have been committed into the filesystem, this -// is to prevent blocks from being garbage collected in the middle of a -// commit operation -static void lfs2_alloc_ack(lfs2_t *lfs2) { - lfs2->free.ack = lfs2->block_count; -} - -// drop the lookahead buffer, this is done during mounting and failed -// traversals in order to avoid invalid lookahead state -static void lfs2_alloc_drop(lfs2_t *lfs2) { - lfs2->free.size = 0; - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); -} - #ifndef LFS2_READONLY -static int lfs2_fs_rawgc(lfs2_t *lfs2) { - // Move free offset at the first unused block (lfs2->free.i) - // lfs2->free.i is equal lfs2->free.size when all blocks are used - lfs2->free.off = (lfs2->free.off + lfs2->free.i) % lfs2->block_count; - lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack); - lfs2->free.i = 0; +static int lfs2_alloc_scan(lfs2_t *lfs2) { + // move lookahead buffer to the first unused block + // + // note we limit the lookahead buffer to at most the amount of blocks + // checkpointed, this prevents the math in lfs2_alloc from underflowing + lfs2->lookahead.start = (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count; + lfs2->lookahead.next = 0; + lfs2->lookahead.size = lfs2_min( + 8*lfs2->cfg->lookahead_size, + lfs2->lookahead.ckpoint); // find mask of free blocks from tree - memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); - int err = lfs2_fs_rawtraverse(lfs2, lfs2_alloc_lookahead, lfs2, true); + memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size); + int err = lfs2_fs_traverse_(lfs2, lfs2_alloc_lookahead, lfs2, true); if (err) { lfs2_alloc_drop(lfs2); return err; @@ -645,36 +665,49 @@ static int lfs2_fs_rawgc(lfs2_t *lfs2) { #ifndef LFS2_READONLY static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) { while (true) { - while (lfs2->free.i != lfs2->free.size) { - lfs2_block_t off = lfs2->free.i; - lfs2->free.i += 1; - lfs2->free.ack -= 1; - - if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) { + // scan our lookahead buffer for free blocks + while (lfs2->lookahead.next < lfs2->lookahead.size) { + if (!(lfs2->lookahead.buffer[lfs2->lookahead.next / 8] + & (1U << (lfs2->lookahead.next % 8)))) { // found a free block - *block = (lfs2->free.off + off) % lfs2->block_count; - - // eagerly find next off so an alloc ack can - // discredit old lookahead blocks - while (lfs2->free.i != lfs2->free.size && - (lfs2->free.buffer[lfs2->free.i / 32] - & (1U << (lfs2->free.i % 32)))) { - lfs2->free.i += 1; - lfs2->free.ack -= 1; + *block = (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count; + + // eagerly find next free block to maximize how many blocks + // lfs2_alloc_ckpoint makes available for scanning + while (true) { + lfs2->lookahead.next += 1; + lfs2->lookahead.ckpoint -= 1; + + if (lfs2->lookahead.next >= lfs2->lookahead.size + || !(lfs2->lookahead.buffer[lfs2->lookahead.next / 8] + & (1U << (lfs2->lookahead.next % 8)))) { + return 0; + } } - - return 0; } + + lfs2->lookahead.next += 1; + lfs2->lookahead.ckpoint -= 1; } - // check if we have looked at all blocks since last ack - if (lfs2->free.ack == 0) { - LFS2_ERROR("No more free space %"PRIu32, - lfs2->free.i + lfs2->free.off); + // In order to keep our block allocator from spinning forever when our + // filesystem is full, we mark points where there are no in-flight + // allocations with a checkpoint before starting a set of allocations. + // + // If we've looked at all blocks since the last checkpoint, we report + // the filesystem as out of storage. + // + if (lfs2->lookahead.ckpoint <= 0) { + LFS2_ERROR("No more free space 0x%"PRIx32, + (lfs2->lookahead.start + lfs2->lookahead.next) + % lfs2->block_count); return LFS2_ERR_NOSPC; } - int err = lfs2_fs_rawgc(lfs2); + // No blocks in our lookahead buffer, we need to scan the filesystem for + // unused blocks in the next lookahead window. + int err = lfs2_alloc_scan(lfs2); if(err) { return err; } @@ -690,11 +723,14 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, lfs2_tag_t ntag = dir->etag; lfs2_stag_t gdiff = 0; + // synthetic moves if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) && - lfs2_tag_id(gmask) != 0 && - lfs2_tag_id(lfs2->gdisk.tag) <= lfs2_tag_id(gtag)) { - // synthetic moves - gdiff -= LFS2_MKTAG(0, 1, 0); + lfs2_tag_id(gmask) != 0) { + if (lfs2_tag_id(lfs2->gdisk.tag) == lfs2_tag_id(gtag)) { + return LFS2_ERR_NOENT; + } else if (lfs2_tag_id(lfs2->gdisk.tag) < lfs2_tag_id(gtag)) { + gdiff -= LFS2_MKTAG(0, 1, 0); + } } // iterate over dir block backwards (for faster lookups) @@ -704,6 +740,7 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, int err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, sizeof(ntag), dir->pair[0], off, &ntag, sizeof(ntag)); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -732,6 +769,7 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir, err = lfs2_bd_read(lfs2, NULL, &lfs2->rcache, diff, dir->pair[0], off+sizeof(tag)+goff, gbuffer, diff); + LFS2_ASSERT(err <= 0); if (err) { return err; } @@ -793,9 +831,6 @@ static int lfs2_dir_getread(lfs2_t *lfs2, const lfs2_mdir_t *dir, size -= diff; continue; } - - // rcache takes priority - diff = lfs2_min(diff, rcache->off-off); } // load to cache, first condition can no longer fail @@ -1247,6 +1282,7 @@ static lfs2_stag_t lfs2_dir_fetchmatch(lfs2_t *lfs2, if (err == LFS2_ERR_CORRUPT) { break; } + return err; } lfs2_fcrc_fromle32(&fcrc); @@ -1438,32 +1474,46 @@ static int lfs2_dir_find_match(void *data, return LFS2_CMP_EQ; } +// lfs2_dir_find tries to set path and id even if file is not found +// +// returns: +// - 0 if file is found +// - LFS2_ERR_NOENT if file or parent is not found +// - LFS2_ERR_NOTDIR if parent is not a dir static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, const char **path, uint16_t *id) { // we reduce path to a single name if we can find it const char *name = *path; - if (id) { - *id = 0x3ff; - } // default to root dir lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0); dir->tail[0] = lfs2->root[0]; dir->tail[1] = lfs2->root[1]; + // empty paths are not allowed + if (*name == '\0') { + return LFS2_ERR_INVAL; + } + while (true) { nextname: - // skip slashes - name += strspn(name, "/"); + // skip slashes if we're a directory + if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + name += strspn(name, "/"); + } lfs2_size_t namelen = strcspn(name, "/"); - // skip '.' and root '..' - if ((namelen == 1 && memcmp(name, ".", 1) == 0) || - (namelen == 2 && memcmp(name, "..", 2) == 0)) { + // skip '.' + if (namelen == 1 && memcmp(name, ".", 1) == 0) { name += namelen; goto nextname; } + // error on unmatched '..', trying to go above root? + if (namelen == 2 && memcmp(name, "..", 2) == 0) { + return LFS2_ERR_INVAL; + } + // skip if matched by '..' in name const char *suffix = name + namelen; lfs2_size_t sufflen; @@ -1475,7 +1525,9 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, break; } - if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { + if (sufflen == 1 && memcmp(suffix, ".", 1) == 0) { + // noop + } else if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) { depth -= 1; if (depth == 0) { name = suffix + sufflen; @@ -1489,14 +1541,14 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, } // found path - if (name[0] == '\0') { + if (*name == '\0') { return tag; } // update what we've found so far *path = name; - // only continue if we hit a directory + // only continue if we're a directory if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { return LFS2_ERR_NOTDIR; } @@ -1516,8 +1568,7 @@ static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir, tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail, LFS2_MKTAG(0x780, 0, 0), LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen), - // are we last name? - (strchr(name, '/') == NULL) ? id : NULL, + id, lfs2_dir_find_match, &(struct lfs2_dir_find_match){ lfs2, name, namelen}); if (tag < 0) { @@ -2105,13 +2156,14 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, // And we cap at half a block to avoid degenerate cases with // nearly-full metadata blocks. // + lfs2_size_t metadata_max = (lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size; if (end - split < 0xff && size <= lfs2_min( - lfs2->cfg->block_size - 40, + metadata_max - 40, lfs2_alignup( - (lfs2->cfg->metadata_max - ? lfs2->cfg->metadata_max - : lfs2->cfg->block_size)/2, + metadata_max/2, lfs2->cfg->prog_size))) { break; } @@ -2146,14 +2198,16 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, && lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) { // oh no! we're writing too much to the superblock, // should we expand? - lfs2_ssize_t size = lfs2_fs_rawsize(lfs2); + lfs2_ssize_t size = lfs2_fs_size_(lfs2); if (size < 0) { return size; } - // do we have extra space? littlefs can't reclaim this space - // by itself, so expand cautiously - if ((lfs2_size_t)size < lfs2->block_count/2) { + // littlefs cannot reclaim expanded superblocks, so expand cautiously + // + // if our filesystem is more than ~88% full, don't expand, this is + // somewhat arbitrary + if (lfs2->block_count - size > lfs2->block_count/8) { LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev); int err = lfs2_dir_split(lfs2, dir, attrs, attrcount, source, begin, end); @@ -2166,7 +2220,8 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir, // we can do, we'll error later if we've become frozen LFS2_WARN("Unable to expand superblock"); } else { - end = begin; + // duplicate the superblock entry into the new superblock + end = 1; } } } @@ -2213,7 +2268,7 @@ static int lfs2_dir_relocatingcommit(lfs2_t *lfs2, lfs2_mdir_t *dir, } } - if (dir->erased) { + if (dir->erased && dir->count < 0xff) { // try to commit struct lfs2_commit commit = { .block = dir->pair[0], @@ -2312,7 +2367,8 @@ fixmlist:; if (d->m.pair != pair) { for (int i = 0; i < attrcount; i++) { if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE && - d->id == lfs2_tag_id(attrs[i].tag)) { + d->id == lfs2_tag_id(attrs[i].tag) && + d->type != LFS2_TYPE_DIR) { d->m.pair[0] = LFS2_BLOCK_NULL; d->m.pair[1] = LFS2_BLOCK_NULL; } else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE && @@ -2333,7 +2389,9 @@ fixmlist:; while (d->id >= d->m.count && d->m.split) { // we split and id is on tail now - d->id -= d->m.count; + if (lfs2_pair_cmp(d->m.tail, lfs2->root) != 0) { + d->id -= d->m.count; + } int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail); if (err) { return err; @@ -2499,7 +2557,7 @@ static int lfs2_dir_orphaningcommit(lfs2_t *lfs2, lfs2_mdir_t *dir, if (err != LFS2_ERR_NOENT) { if (lfs2_gstate_hasorphans(&lfs2->gstate)) { // next step, clean up orphans - err = lfs2_fs_preporphans(lfs2, -hasparent); + err = lfs2_fs_preporphans(lfs2, -(int8_t)hasparent); if (err) { return err; } @@ -2564,7 +2622,7 @@ static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir, /// Top level directory operations /// #ifndef LFS2_READONLY -static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { +static int lfs2_mkdir_(lfs2_t *lfs2, const char *path) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -2575,18 +2633,18 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { cwd.next = lfs2->mlist; uint16_t id; err = lfs2_dir_find(lfs2, &cwd.m, &path, &id); - if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) { + if (!(err == LFS2_ERR_NOENT && lfs2_path_islast(path))) { return (err < 0) ? err : LFS2_ERR_EXIST; } // check that name fits - lfs2_size_t nlen = strlen(path); + lfs2_size_t nlen = lfs2_path_namelen(path); if (nlen > lfs2->name_max) { return LFS2_ERR_NAMETOOLONG; } // build up new directory - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); lfs2_mdir_t dir; err = lfs2_dir_alloc(lfs2, &dir); if (err) { @@ -2660,7 +2718,7 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) { } #endif -static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { +static int lfs2_dir_open_(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL); if (tag < 0) { return tag; @@ -2704,14 +2762,14 @@ static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { return 0; } -static int lfs2_dir_rawclose(lfs2_t *lfs2, lfs2_dir_t *dir) { +static int lfs2_dir_close_(lfs2_t *lfs2, lfs2_dir_t *dir) { // remove from list of mdirs lfs2_mlist_remove(lfs2, (struct lfs2_mlist *)dir); return 0; } -static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { +static int lfs2_dir_read_(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { memset(info, 0, sizeof(*info)); // special offset for '.' and '..' @@ -2756,9 +2814,9 @@ static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *inf return true; } -static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { +static int lfs2_dir_seek_(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { // simply walk from head dir - int err = lfs2_dir_rawrewind(lfs2, dir); + int err = lfs2_dir_rewind_(lfs2, dir); if (err) { return err; } @@ -2793,12 +2851,12 @@ static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { return 0; } -static lfs2_soff_t lfs2_dir_rawtell(lfs2_t *lfs2, lfs2_dir_t *dir) { +static lfs2_soff_t lfs2_dir_tell_(lfs2_t *lfs2, lfs2_dir_t *dir) { (void)lfs2; return dir->pos; } -static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir) { +static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir) { // reload the head dir int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head); if (err) { @@ -3004,7 +3062,7 @@ static int lfs2_ctz_traverse(lfs2_t *lfs2, /// Top level file operations /// -static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, +static int lfs2_file_opencfg_(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags, const struct lfs2_file_config *cfg) { #ifndef LFS2_READONLY @@ -3029,7 +3087,7 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, // allocate entry for file if it doesn't exist lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id); - if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) { + if (tag < 0 && !(tag == LFS2_ERR_NOENT && lfs2_path_islast(path))) { err = tag; goto cleanup; } @@ -3049,8 +3107,14 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, goto cleanup; } + // don't allow trailing slashes + if (lfs2_path_isdir(path)) { + err = LFS2_ERR_NOTDIR; + goto cleanup; + } + // check that name fits - lfs2_size_t nlen = strlen(path); + lfs2_size_t nlen = lfs2_path_namelen(path); if (nlen > lfs2->name_max) { err = LFS2_ERR_NAMETOOLONG; goto cleanup; @@ -3166,22 +3230,22 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file, #ifndef LFS2_READONLY file->flags |= LFS2_F_ERRED; #endif - lfs2_file_rawclose(lfs2, file); + lfs2_file_close_(lfs2, file); return err; } #ifndef LFS2_NO_MALLOC -static int lfs2_file_rawopen(lfs2_t *lfs2, lfs2_file_t *file, +static int lfs2_file_open_(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) { static const struct lfs2_file_config defaults = {0}; - int err = lfs2_file_rawopencfg(lfs2, file, path, flags, &defaults); + int err = lfs2_file_opencfg_(lfs2, file, path, flags, &defaults); return err; } #endif -static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file) { +static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file) { #ifndef LFS2_READONLY - int err = lfs2_file_rawsync(lfs2, file); + int err = lfs2_file_sync_(lfs2, file); #else int err = 0; #endif @@ -3272,7 +3336,7 @@ static int lfs2_file_relocate(lfs2_t *lfs2, lfs2_file_t *file) { #ifndef LFS2_READONLY static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) { file->off = file->pos; - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); int err = lfs2_file_relocate(lfs2, file); if (err) { return err; @@ -3364,7 +3428,7 @@ static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file) { } #ifndef LFS2_READONLY -static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) { +static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file) { if (file->flags & LFS2_F_ERRED) { // it's not safe to do anything if our file errored return 0; @@ -3379,6 +3443,15 @@ static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) { if ((file->flags & LFS2_F_DIRTY) && !lfs2_pair_isnull(file->m.pair)) { + // before we commit metadata, we need sync the disk to make sure + // data writes don't complete after metadata writes + if (!(file->flags & LFS2_F_INLINE)) { + err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false); + if (err) { + return err; + } + } + // update dir entry uint16_t type; const void *buffer; @@ -3477,7 +3550,7 @@ static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file, return size; } -static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file, void *buffer, lfs2_size_t size) { LFS2_ASSERT((file->flags & LFS2_O_RDONLY) == LFS2_O_RDONLY); @@ -3502,11 +3575,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, lfs2_size_t nsize = size; if ((file->flags & LFS2_F_INLINE) && - lfs2_max(file->pos+nsize, file->ctz.size) > - lfs2_min(0x3fe, lfs2_min( - lfs2->cfg->cache_size, - (lfs2->cfg->metadata_max ? - lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) { + lfs2_max(file->pos+nsize, file->ctz.size) > lfs2->inline_max) { // inline file doesn't fit anymore int err = lfs2_file_outline(lfs2, file); if (err) { @@ -3535,7 +3604,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, } // extend file with new blocks - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache, file->block, file->pos, &file->block, &file->off); @@ -3578,13 +3647,13 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file, data += diff; nsize -= diff; - lfs2_alloc_ack(lfs2); + lfs2_alloc_ckpoint(lfs2); } return size; } -static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file, const void *buffer, lfs2_size_t size) { LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY); @@ -3628,25 +3697,19 @@ static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file, } #endif -static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, +static lfs2_soff_t lfs2_file_seek_(lfs2_t *lfs2, lfs2_file_t *file, lfs2_soff_t off, int whence) { // find new pos + // + // fortunately for us, littlefs is limited to 31-bit file sizes, so we + // don't have to worry too much about integer overflow lfs2_off_t npos = file->pos; if (whence == LFS2_SEEK_SET) { npos = off; } else if (whence == LFS2_SEEK_CUR) { - if ((lfs2_soff_t)file->pos + off < 0) { - return LFS2_ERR_INVAL; - } else { - npos = file->pos + off; - } + npos = file->pos + (lfs2_off_t)off; } else if (whence == LFS2_SEEK_END) { - lfs2_soff_t res = lfs2_file_rawsize(lfs2, file) + off; - if (res < 0) { - return LFS2_ERR_INVAL; - } else { - npos = res; - } + npos = (lfs2_off_t)lfs2_file_size_(lfs2, file) + (lfs2_off_t)off; } if (npos > lfs2->file_max) { @@ -3661,13 +3724,8 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, // if we're only reading and our new offset is still in the file's cache // we can avoid flushing and needing to reread the data - if ( -#ifndef LFS2_READONLY - !(file->flags & LFS2_F_WRITING) -#else - true -#endif - ) { + if ((file->flags & LFS2_F_READING) + && file->off != lfs2->cfg->block_size) { int oindex = lfs2_ctz_index(lfs2, &(lfs2_off_t){file->pos}); lfs2_off_t noff = npos; int nindex = lfs2_ctz_index(lfs2, &noff); @@ -3692,7 +3750,7 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file, } #ifndef LFS2_READONLY -static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { +static int lfs2_file_truncate_(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY); if (size > LFS2_FILE_MAX) { @@ -3700,15 +3758,12 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } lfs2_off_t pos = file->pos; - lfs2_off_t oldsize = lfs2_file_rawsize(lfs2, file); + lfs2_off_t oldsize = lfs2_file_size_(lfs2, file); if (size < oldsize) { // revert to inline file? - if (size <= lfs2_min(0x3fe, lfs2_min( - lfs2->cfg->cache_size, - (lfs2->cfg->metadata_max ? - lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) { + if (size <= lfs2->inline_max) { // flush+seek to head - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3753,14 +3808,14 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } } else if (size > oldsize) { // flush+seek if not already at end - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_END); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_END); if (res < 0) { return (int)res; } // fill with zeros while (file->pos < size) { - res = lfs2_file_rawwrite(lfs2, file, &(uint8_t){0}, 1); + res = lfs2_file_write_(lfs2, file, &(uint8_t){0}, 1); if (res < 0) { return (int)res; } @@ -3768,7 +3823,7 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } // restore pos - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, pos, LFS2_SEEK_SET); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, pos, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3777,13 +3832,13 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz } #endif -static lfs2_soff_t lfs2_file_rawtell(lfs2_t *lfs2, lfs2_file_t *file) { +static lfs2_soff_t lfs2_file_tell_(lfs2_t *lfs2, lfs2_file_t *file) { (void)lfs2; return file->pos; } -static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) { - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET); +static int lfs2_file_rewind_(lfs2_t *lfs2, lfs2_file_t *file) { + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET); if (res < 0) { return (int)res; } @@ -3791,7 +3846,7 @@ static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) { return 0; } -static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) { +static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file) { (void)lfs2; #ifndef LFS2_READONLY @@ -3805,18 +3860,24 @@ static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) { /// General fs operations /// -static int lfs2_rawstat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { +static int lfs2_stat_(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); if (tag < 0) { return (int)tag; } + // only allow trailing slashes on dirs + if (strchr(path, '/') != NULL + && lfs2_tag_type3(tag) != LFS2_TYPE_DIR) { + return LFS2_ERR_NOTDIR; + } + return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info); } #ifndef LFS2_READONLY -static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { +static int lfs2_remove_(lfs2_t *lfs2, const char *path) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -3872,7 +3933,9 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { } lfs2->mlist = dir.next; - if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) { + if (lfs2_gstate_hasorphans(&lfs2->gstate)) { + LFS2_ASSERT(lfs2_tag_type3(tag) == LFS2_TYPE_DIR); + // fix orphan err = lfs2_fs_preporphans(lfs2, -1); if (err) { @@ -3895,7 +3958,7 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) { #endif #ifndef LFS2_READONLY -static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { +static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath) { // deorphan if we haven't yet, needed at most once after poweron int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -3914,7 +3977,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath uint16_t newid; lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid); if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) && - !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) { + !(prevtag == LFS2_ERR_NOENT && lfs2_path_islast(newpath))) { return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL; } @@ -3925,8 +3988,14 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath struct lfs2_mlist prevdir; prevdir.next = lfs2->mlist; if (prevtag == LFS2_ERR_NOENT) { + // if we're a file, don't allow trailing slashes + if (lfs2_path_isdir(newpath) + && lfs2_tag_type3(oldtag) != LFS2_TYPE_DIR) { + return LFS2_ERR_NOTDIR; + } + // check that name fits - lfs2_size_t nlen = strlen(newpath); + lfs2_size_t nlen = lfs2_path_namelen(newpath); if (nlen > lfs2->name_max) { return LFS2_ERR_NAMETOOLONG; } @@ -3938,7 +4007,9 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath newoldid += 1; } } else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) { - return LFS2_ERR_ISDIR; + return (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) + ? LFS2_ERR_ISDIR + : LFS2_ERR_NOTDIR; } else if (samepair && newid == newoldid) { // we're renaming to ourselves?? return 0; @@ -3984,7 +4055,8 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath {LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT, LFS2_TYPE_DELETE, newid, 0), NULL}, {LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL}, - {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath}, + {LFS2_MKTAG(lfs2_tag_type3(oldtag), + newid, lfs2_path_namelen(newpath)), newpath}, {LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd}, {LFS2_MKTAG_IF(samepair, LFS2_TYPE_DELETE, newoldid, 0), NULL})); @@ -4007,8 +4079,10 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath } lfs2->mlist = prevdir.next; - if (prevtag != LFS2_ERR_NOENT - && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) { + if (lfs2_gstate_hasorphans(&lfs2->gstate)) { + LFS2_ASSERT(prevtag != LFS2_ERR_NOENT + && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR); + // fix orphan err = lfs2_fs_preporphans(lfs2, -1); if (err) { @@ -4030,7 +4104,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath } #endif -static lfs2_ssize_t lfs2_rawgetattr(lfs2_t *lfs2, const char *path, +static lfs2_ssize_t lfs2_getattr_(lfs2_t *lfs2, const char *path, uint8_t type, void *buffer, lfs2_size_t size) { lfs2_mdir_t cwd; lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL); @@ -4088,7 +4162,7 @@ static int lfs2_commitattr(lfs2_t *lfs2, const char *path, #endif #ifndef LFS2_READONLY -static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path, +static int lfs2_setattr_(lfs2_t *lfs2, const char *path, uint8_t type, const void *buffer, lfs2_size_t size) { if (size > lfs2->attr_max) { return LFS2_ERR_NOSPC; @@ -4099,13 +4173,28 @@ static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path, #endif #ifndef LFS2_READONLY -static int lfs2_rawremoveattr(lfs2_t *lfs2, const char *path, uint8_t type) { +static int lfs2_removeattr_(lfs2_t *lfs2, const char *path, uint8_t type) { return lfs2_commitattr(lfs2, path, type, NULL, 0x3ff); } #endif /// Filesystem operations /// + +// compile time checks, see lfs2.h for why these limits exist +#if LFS2_NAME_MAX > 1022 +#error "Invalid LFS2_NAME_MAX, must be <= 1022" +#endif + +#if LFS2_FILE_MAX > 2147483647 +#error "Invalid LFS2_FILE_MAX, must be <= 2147483647" +#endif + +#if LFS2_ATTR_MAX > 1022 +#error "Invalid LFS2_ATTR_MAX, must be <= 1022" +#endif + +// common filesystem initialization static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { lfs2->cfg = cfg; lfs2->block_count = cfg->block_count; // May be 0 @@ -4126,6 +4215,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { // which littlefs currently does not support LFS2_ASSERT((bool)0x80000000); + // check that the required io functions are provided + LFS2_ASSERT(lfs2->cfg->read != NULL); +#ifndef LFS2_READONLY + LFS2_ASSERT(lfs2->cfg->prog != NULL); + LFS2_ASSERT(lfs2->cfg->erase != NULL); + LFS2_ASSERT(lfs2->cfg->sync != NULL); +#endif + // validate that the lfs2-cfg sizes were initiated properly before // performing any arithmetic logics with them LFS2_ASSERT(lfs2->cfg->read_size != 0); @@ -4153,6 +4250,23 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { // wear-leveling. LFS2_ASSERT(lfs2->cfg->block_cycles != 0); + // check that compact_thresh makes sense + // + // metadata can't be compacted below block_size/2, and metadata can't + // exceed a block_size + LFS2_ASSERT(lfs2->cfg->compact_thresh == 0 + || lfs2->cfg->compact_thresh >= lfs2->cfg->block_size/2); + LFS2_ASSERT(lfs2->cfg->compact_thresh == (lfs2_size_t)-1 + || lfs2->cfg->compact_thresh <= lfs2->cfg->block_size); + + // check that metadata_max is a multiple of read_size and prog_size, + // and a factor of the block_size + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->metadata_max % lfs2->cfg->read_size == 0); + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->metadata_max % lfs2->cfg->prog_size == 0); + LFS2_ASSERT(!lfs2->cfg->metadata_max + || lfs2->cfg->block_size % lfs2->cfg->metadata_max == 0); // setup read cache if (lfs2->cfg->read_buffer) { @@ -4180,15 +4294,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { lfs2_cache_zero(lfs2, &lfs2->rcache); lfs2_cache_zero(lfs2, &lfs2->pcache); - // setup lookahead, must be multiple of 64-bits, 32-bit aligned + // setup lookahead buffer, note mount finishes initializing this after + // we establish a decent pseudo-random seed LFS2_ASSERT(lfs2->cfg->lookahead_size > 0); - LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 && - (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0); if (lfs2->cfg->lookahead_buffer) { - lfs2->free.buffer = lfs2->cfg->lookahead_buffer; + lfs2->lookahead.buffer = lfs2->cfg->lookahead_buffer; } else { - lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); - if (!lfs2->free.buffer) { + lfs2->lookahead.buffer = lfs2_malloc(lfs2->cfg->lookahead_size); + if (!lfs2->lookahead.buffer) { err = LFS2_ERR_NOMEM; goto cleanup; } @@ -4215,6 +4328,27 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_ASSERT(lfs2->cfg->metadata_max <= lfs2->cfg->block_size); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= lfs2->cfg->cache_size); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= lfs2->attr_max); + LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1 + || lfs2->cfg->inline_max <= ((lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size)/8); + lfs2->inline_max = lfs2->cfg->inline_max; + if (lfs2->inline_max == (lfs2_size_t)-1) { + lfs2->inline_max = 0; + } else if (lfs2->inline_max == 0) { + lfs2->inline_max = lfs2_min( + lfs2->cfg->cache_size, + lfs2_min( + lfs2->attr_max, + ((lfs2->cfg->metadata_max) + ? lfs2->cfg->metadata_max + : lfs2->cfg->block_size)/8)); + } + // setup default state lfs2->root[0] = LFS2_BLOCK_NULL; lfs2->root[1] = LFS2_BLOCK_NULL; @@ -4245,7 +4379,7 @@ static int lfs2_deinit(lfs2_t *lfs2) { } if (!lfs2->cfg->lookahead_buffer) { - lfs2_free(lfs2->free.buffer); + lfs2_free(lfs2->lookahead.buffer); } return 0; @@ -4254,7 +4388,7 @@ static int lfs2_deinit(lfs2_t *lfs2) { #ifndef LFS2_READONLY -static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { +static int lfs2_format_(lfs2_t *lfs2, const struct lfs2_config *cfg) { int err = 0; { err = lfs2_init(lfs2, cfg); @@ -4265,12 +4399,12 @@ static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { LFS2_ASSERT(cfg->block_count != 0); // create free lookahead - memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size); - lfs2->free.off = 0; - lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, + memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size); + lfs2->lookahead.start = 0; + lfs2->lookahead.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->block_count); - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); // create root dir lfs2_mdir_t root; @@ -4321,7 +4455,31 @@ static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) { } #endif -static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { +struct lfs2_tortoise_t { + lfs2_block_t pair[2]; + lfs2_size_t i; + lfs2_size_t period; +}; + +static int lfs2_tortoise_detectcycles( + const lfs2_mdir_t *dir, struct lfs2_tortoise_t *tortoise) { + // detect cycles with Brent's algorithm + if (lfs2_pair_issync(dir->tail, tortoise->pair)) { + LFS2_WARN("Cycle detected in tail list"); + return LFS2_ERR_CORRUPT; + } + if (tortoise->i == tortoise->period) { + tortoise->pair[0] = dir->tail[0]; + tortoise->pair[1] = dir->tail[1]; + tortoise->i = 0; + tortoise->period *= 2; + } + tortoise->i += 1; + + return LFS2_ERR_OK; +} + +static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) { int err = lfs2_init(lfs2, cfg); if (err) { return err; @@ -4329,23 +4487,16 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // scan directory blocks for superblock and any global updates lfs2_mdir_t dir = {.tail = {0, 1}}; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; while (!lfs2_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(dir.tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); - err = LFS2_ERR_CORRUPT; + err = lfs2_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { goto cleanup; } - if (tortoise_i == tortoise_period) { - tortoise[0] = dir.tail[0]; - tortoise[1] = dir.tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; // fetch next block in tail list lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail, @@ -4394,6 +4545,7 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // found older minor version? set an in-device only bit in the // gstate so we know we need to rewrite the superblock before // the first write + bool needssuperblock = false; if (minor_version < lfs2_fs_disk_version_minor(lfs2)) { LFS2_DEBUG("Found older minor version " "v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16, @@ -4401,10 +4553,11 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { minor_version, lfs2_fs_disk_version_major(lfs2), lfs2_fs_disk_version_minor(lfs2)); - // note this bit is reserved on disk, so fetching more gstate - // will not interfere here - lfs2_fs_prepsuperblock(lfs2, true); + needssuperblock = true; } + // note this bit is reserved on disk, so fetching more gstate + // will not interfere here + lfs2_fs_prepsuperblock(lfs2, needssuperblock); // check superblock configuration if (superblock.name_max) { @@ -4438,6 +4591,9 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { } lfs2->attr_max = superblock.attr_max; + + // we also need to update inline_max in case attr_max changed + lfs2->inline_max = lfs2_min(lfs2->inline_max, lfs2->attr_max); } // this is where we get the block_count from disk if block_count=0 @@ -4478,23 +4634,23 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) { // setup free lookahead, to distribute allocations uniformly across // boots, we start the allocator at a random location - lfs2->free.off = lfs2->seed % lfs2->block_count; + lfs2->lookahead.start = lfs2->seed % lfs2->block_count; lfs2_alloc_drop(lfs2); return 0; cleanup: - lfs2_rawunmount(lfs2); + lfs2_unmount_(lfs2); return err; } -static int lfs2_rawunmount(lfs2_t *lfs2) { +static int lfs2_unmount_(lfs2_t *lfs2) { return lfs2_deinit(lfs2); } /// Filesystem filesystem operations /// -static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { +static int lfs2_fs_stat_(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { // if the superblock is up-to-date, we must be on the most recent // minor version of littlefs if (!lfs2_gstate_needssuperblock(&lfs2->gstate)) { @@ -4534,7 +4690,7 @@ static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { return 0; } -int lfs2_fs_rawtraverse(lfs2_t *lfs2, +int lfs2_fs_traverse_(lfs2_t *lfs2, int (*cb)(void *data, lfs2_block_t block), void *data, bool includeorphans) { // iterate over metadata pairs @@ -4553,22 +4709,17 @@ int lfs2_fs_rawtraverse(lfs2_t *lfs2, } #endif - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(dir.tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(dir.tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); + err = lfs2_tortoise_detectcycles(&dir, &tortoise); + if (err < 0) { return LFS2_ERR_CORRUPT; } - if (tortoise_i == tortoise_period) { - tortoise[0] = dir.tail[0]; - tortoise[1] = dir.tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; for (int i = 0; i < 2; i++) { int err = cb(data, dir.tail[i]); @@ -4647,22 +4798,17 @@ static int lfs2_fs_pred(lfs2_t *lfs2, // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(pdir->tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(pdir->tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); + err = lfs2_tortoise_detectcycles(pdir, &tortoise); + if (err < 0) { return LFS2_ERR_CORRUPT; } - if (tortoise_i == tortoise_period) { - tortoise[0] = pdir->tail[0]; - tortoise[1] = pdir->tail[1]; - tortoise_i = 0; - tortoise_period *= 2; - } - tortoise_i += 1; if (lfs2_pair_cmp(pdir->tail, pair) == 0) { return 0; @@ -4712,22 +4858,17 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2], // use fetchmatch with callback to find pairs parent->tail[0] = 0; parent->tail[1] = 1; - lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}; - lfs2_size_t tortoise_i = 1; - lfs2_size_t tortoise_period = 1; + struct lfs2_tortoise_t tortoise = { + .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL}, + .i = 1, + .period = 1, + }; + int err = LFS2_ERR_OK; while (!lfs2_pair_isnull(parent->tail)) { - // detect cycles with Brent's algorithm - if (lfs2_pair_issync(parent->tail, tortoise)) { - LFS2_WARN("Cycle detected in tail list"); - return LFS2_ERR_CORRUPT; - } - if (tortoise_i == tortoise_period) { - tortoise[0] = parent->tail[0]; - tortoise[1] = parent->tail[1]; - tortoise_i = 0; - tortoise_period *= 2; + err = lfs2_tortoise_detectcycles(parent, &tortoise); + if (err < 0) { + return err; } - tortoise_i += 1; lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail, LFS2_MKTAG(0x7ff, 0, 0x3ff), @@ -4999,7 +5140,7 @@ static int lfs2_fs_forceconsistency(lfs2_t *lfs2) { #endif #ifndef LFS2_READONLY -static int lfs2_fs_rawmkconsistent(lfs2_t *lfs2) { +static int lfs2_fs_mkconsistent_(lfs2_t *lfs2) { // lfs2_fs_forceconsistency does most of the work here int err = lfs2_fs_forceconsistency(lfs2); if (err) { @@ -5035,9 +5176,9 @@ static int lfs2_fs_size_count(void *p, lfs2_block_t block) { return 0; } -static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) { +static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2) { lfs2_size_t size = 0; - int err = lfs2_fs_rawtraverse(lfs2, lfs2_fs_size_count, &size, false); + int err = lfs2_fs_traverse_(lfs2, lfs2_fs_size_count, &size, false); if (err) { return err; } @@ -5045,41 +5186,118 @@ static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) { return size; } +// explicit garbage collection #ifndef LFS2_READONLY -static int lfs2_fs_rawgrow(lfs2_t *lfs2, lfs2_size_t block_count) { - // shrinking is not supported - LFS2_ASSERT(block_count >= lfs2->block_count); +static int lfs2_fs_gc_(lfs2_t *lfs2) { + // force consistency, even if we're not necessarily going to write, + // because this function is supposed to take care of janitorial work + // isn't it? + int err = lfs2_fs_forceconsistency(lfs2); + if (err) { + return err; + } - if (block_count > lfs2->block_count) { - lfs2->block_count = block_count; + // try to compact metadata pairs, note we can't really accomplish + // anything if compact_thresh doesn't at least leave a prog_size + // available + if (lfs2->cfg->compact_thresh + < lfs2->cfg->block_size - lfs2->cfg->prog_size) { + // iterate over all mdirs + lfs2_mdir_t mdir = {.tail = {0, 1}}; + while (!lfs2_pair_isnull(mdir.tail)) { + err = lfs2_dir_fetch(lfs2, &mdir, mdir.tail); + if (err) { + return err; + } - // fetch the root - lfs2_mdir_t root; - int err = lfs2_dir_fetch(lfs2, &root, lfs2->root); + // not erased? exceeds our compaction threshold? + if (!mdir.erased || ((lfs2->cfg->compact_thresh == 0) + ? mdir.off > lfs2->cfg->block_size - lfs2->cfg->block_size/8 + : mdir.off > lfs2->cfg->compact_thresh)) { + // the easiest way to trigger a compaction is to mark + // the mdir as unerased and add an empty commit + mdir.erased = false; + err = lfs2_dir_commit(lfs2, &mdir, NULL, 0); + if (err) { + return err; + } + } + } + } + + // try to populate the lookahead buffer, unless it's already full + if (lfs2->lookahead.size < lfs2_min( + 8 * lfs2->cfg->lookahead_size, + lfs2->block_count)) { + err = lfs2_alloc_scan(lfs2); if (err) { return err; } + } - // update the superblock - lfs2_superblock_t superblock; - lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0), - LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), - &superblock); - if (tag < 0) { - return tag; - } - lfs2_superblock_fromle32(&superblock); + return 0; +} +#endif - superblock.block_count = lfs2->block_count; +#ifndef LFS2_READONLY +#ifdef LFS2_SHRINKNONRELOCATING +static int lfs2_shrink_checkblock(void *data, lfs2_block_t block) { + lfs2_size_t threshold = *((lfs2_size_t*)data); + if (block >= threshold) { + return LFS2_ERR_NOTEMPTY; + } + return 0; +} +#endif - lfs2_superblock_tole32(&superblock); - err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( - {tag, &superblock})); +static int lfs2_fs_grow_(lfs2_t *lfs2, lfs2_size_t block_count) { + int err; + + if (block_count == lfs2->block_count) { + return 0; + } + + +#ifndef LFS2_SHRINKNONRELOCATING + // shrinking is not supported + LFS2_ASSERT(block_count >= lfs2->block_count); +#endif +#ifdef LFS2_SHRINKNONRELOCATING + if (block_count < lfs2->block_count) { + err = lfs2_fs_traverse_(lfs2, lfs2_shrink_checkblock, &block_count, true); if (err) { return err; } } +#endif + + lfs2->block_count = block_count; + // fetch the root + lfs2_mdir_t root; + err = lfs2_dir_fetch(lfs2, &root, lfs2->root); + if (err) { + return err; + } + + // update the superblock + lfs2_superblock_t superblock; + lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0), + LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)), + &superblock); + if (tag < 0) { + return tag; + } + lfs2_superblock_fromle32(&superblock); + + superblock.block_count = lfs2->block_count; + + lfs2_superblock_tole32(&superblock); + err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS( + {tag, &superblock})); + if (err) { + return err; + } return 0; } #endif @@ -5451,10 +5669,10 @@ static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21, lfs2->lfs21->root[1] = LFS2_BLOCK_NULL; // setup free lookahead - lfs2->free.off = 0; - lfs2->free.size = 0; - lfs2->free.i = 0; - lfs2_alloc_ack(lfs2); + lfs2->lookahead.start = 0; + lfs2->lookahead.size = 0; + lfs2->lookahead.next = 0; + lfs2_alloc_ckpoint(lfs2); // load superblock lfs21_dir_t dir; @@ -5505,7 +5723,7 @@ static int lfs21_unmount(lfs2_t *lfs2) { } /// v1 migration /// -static int lfs2_rawmigrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { +static int lfs2_migrate_(lfs2_t *lfs2, const struct lfs2_config *cfg) { struct lfs21 lfs21; // Indeterminate filesystem size not allowed for migration. @@ -5759,7 +5977,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -5772,7 +5990,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawformat(lfs2, cfg); + err = lfs2_format_(lfs2, cfg); LFS2_TRACE("lfs2_format -> %d", err); LFS2_UNLOCK(cfg); @@ -5789,7 +6007,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -5802,7 +6020,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawmount(lfs2, cfg); + err = lfs2_mount_(lfs2, cfg); LFS2_TRACE("lfs2_mount -> %d", err); LFS2_UNLOCK(cfg); @@ -5816,7 +6034,7 @@ int lfs2_unmount(lfs2_t *lfs2) { } LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2); - err = lfs2_rawunmount(lfs2); + err = lfs2_unmount_(lfs2); LFS2_TRACE("lfs2_unmount -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5831,7 +6049,7 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) { } LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path); - err = lfs2_rawremove(lfs2, path); + err = lfs2_remove_(lfs2, path); LFS2_TRACE("lfs2_remove -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5847,7 +6065,7 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) { } LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath); - err = lfs2_rawrename(lfs2, oldpath, newpath); + err = lfs2_rename_(lfs2, oldpath, newpath); LFS2_TRACE("lfs2_rename -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5862,7 +6080,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) { } LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info); - err = lfs2_rawstat(lfs2, path, info); + err = lfs2_stat_(lfs2, path, info); LFS2_TRACE("lfs2_stat -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5878,7 +6096,7 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); - lfs2_ssize_t res = lfs2_rawgetattr(lfs2, path, type, buffer, size); + lfs2_ssize_t res = lfs2_getattr_(lfs2, path, type, buffer, size); LFS2_TRACE("lfs2_getattr -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -5895,7 +6113,7 @@ int lfs2_setattr(lfs2_t *lfs2, const char *path, LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")", (void*)lfs2, path, type, buffer, size); - err = lfs2_rawsetattr(lfs2, path, type, buffer, size); + err = lfs2_setattr_(lfs2, path, type, buffer, size); LFS2_TRACE("lfs2_setattr -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5911,7 +6129,7 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) { } LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type); - err = lfs2_rawremoveattr(lfs2, path, type); + err = lfs2_removeattr_(lfs2, path, type); LFS2_TRACE("lfs2_removeattr -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5926,10 +6144,10 @@ int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags) return err; } LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)", - (void*)lfs2, (void*)file, path, flags); + (void*)lfs2, (void*)file, path, (unsigned)flags); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawopen(lfs2, file, path, flags); + err = lfs2_file_open_(lfs2, file, path, flags); LFS2_TRACE("lfs2_file_open -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5946,11 +6164,11 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file, } LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {" ".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})", - (void*)lfs2, (void*)file, path, flags, + (void*)lfs2, (void*)file, path, (unsigned)flags, (void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawopencfg(lfs2, file, path, flags, cfg); + err = lfs2_file_opencfg_(lfs2, file, path, flags, cfg); LFS2_TRACE("lfs2_file_opencfg -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5965,7 +6183,7 @@ int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawclose(lfs2, file); + err = lfs2_file_close_(lfs2, file); LFS2_TRACE("lfs2_file_close -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5981,7 +6199,7 @@ int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawsync(lfs2, file); + err = lfs2_file_sync_(lfs2, file); LFS2_TRACE("lfs2_file_sync -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -5999,7 +6217,7 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_ssize_t res = lfs2_file_rawread(lfs2, file, buffer, size); + lfs2_ssize_t res = lfs2_file_read_(lfs2, file, buffer, size); LFS2_TRACE("lfs2_file_read -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6017,7 +6235,7 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, buffer, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, buffer, size); + lfs2_ssize_t res = lfs2_file_write_(lfs2, file, buffer, size); LFS2_TRACE("lfs2_file_write -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6035,7 +6253,7 @@ lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file, (void*)lfs2, (void*)file, off, whence); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, off, whence); + lfs2_soff_t res = lfs2_file_seek_(lfs2, file, off, whence); LFS2_TRACE("lfs2_file_seek -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6052,7 +6270,7 @@ int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) { (void*)lfs2, (void*)file, size); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - err = lfs2_file_rawtruncate(lfs2, file, size); + err = lfs2_file_truncate_(lfs2, file, size); LFS2_TRACE("lfs2_file_truncate -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6068,7 +6286,7 @@ lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawtell(lfs2, file); + lfs2_soff_t res = lfs2_file_tell_(lfs2, file); LFS2_TRACE("lfs2_file_tell -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6082,7 +6300,7 @@ int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) { } LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file); - err = lfs2_file_rawrewind(lfs2, file); + err = lfs2_file_rewind_(lfs2, file); LFS2_TRACE("lfs2_file_rewind -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6097,9 +6315,9 @@ lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) { LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file); LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file)); - lfs2_soff_t res = lfs2_file_rawsize(lfs2, file); + lfs2_soff_t res = lfs2_file_size_(lfs2, file); - LFS2_TRACE("lfs2_file_size -> %"PRId32, res); + LFS2_TRACE("lfs2_file_size -> %"PRIu32, res); LFS2_UNLOCK(lfs2->cfg); return res; } @@ -6112,7 +6330,7 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) { } LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path); - err = lfs2_rawmkdir(lfs2, path); + err = lfs2_mkdir_(lfs2, path); LFS2_TRACE("lfs2_mkdir -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6128,7 +6346,7 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) { LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path); LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)dir)); - err = lfs2_dir_rawopen(lfs2, dir, path); + err = lfs2_dir_open_(lfs2, dir, path); LFS2_TRACE("lfs2_dir_open -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6142,7 +6360,7 @@ int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir); - err = lfs2_dir_rawclose(lfs2, dir); + err = lfs2_dir_close_(lfs2, dir); LFS2_TRACE("lfs2_dir_close -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6157,7 +6375,7 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) { LFS2_TRACE("lfs2_dir_read(%p, %p, %p)", (void*)lfs2, (void*)dir, (void*)info); - err = lfs2_dir_rawread(lfs2, dir, info); + err = lfs2_dir_read_(lfs2, dir, info); LFS2_TRACE("lfs2_dir_read -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6172,7 +6390,7 @@ int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) { LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")", (void*)lfs2, (void*)dir, off); - err = lfs2_dir_rawseek(lfs2, dir, off); + err = lfs2_dir_seek_(lfs2, dir, off); LFS2_TRACE("lfs2_dir_seek -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6186,7 +6404,7 @@ lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir); - lfs2_soff_t res = lfs2_dir_rawtell(lfs2, dir); + lfs2_soff_t res = lfs2_dir_tell_(lfs2, dir); LFS2_TRACE("lfs2_dir_tell -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6200,7 +6418,7 @@ int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) { } LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir); - err = lfs2_dir_rawrewind(lfs2, dir); + err = lfs2_dir_rewind_(lfs2, dir); LFS2_TRACE("lfs2_dir_rewind -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6214,7 +6432,7 @@ int lfs2_fs_stat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) { } LFS2_TRACE("lfs2_fs_stat(%p, %p)", (void*)lfs2, (void*)fsinfo); - err = lfs2_fs_rawstat(lfs2, fsinfo); + err = lfs2_fs_stat_(lfs2, fsinfo); LFS2_TRACE("lfs2_fs_stat -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6228,7 +6446,7 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) { } LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2); - lfs2_ssize_t res = lfs2_fs_rawsize(lfs2); + lfs2_ssize_t res = lfs2_fs_size_(lfs2); LFS2_TRACE("lfs2_fs_size -> %"PRId32, res); LFS2_UNLOCK(lfs2->cfg); @@ -6243,7 +6461,7 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data) LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)", (void*)lfs2, (void*)(uintptr_t)cb, data); - err = lfs2_fs_rawtraverse(lfs2, cb, data, true); + err = lfs2_fs_traverse_(lfs2, cb, data, true); LFS2_TRACE("lfs2_fs_traverse -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6251,32 +6469,32 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data) } #ifndef LFS2_READONLY -int lfs2_fs_gc(lfs2_t *lfs2) { +int lfs2_fs_mkconsistent(lfs2_t *lfs2) { int err = LFS2_LOCK(lfs2->cfg); if (err) { return err; } - LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2); + LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2); - err = lfs2_fs_rawgc(lfs2); + err = lfs2_fs_mkconsistent_(lfs2); - LFS2_TRACE("lfs2_fs_gc -> %d", err); + LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err); LFS2_UNLOCK(lfs2->cfg); return err; } #endif #ifndef LFS2_READONLY -int lfs2_fs_mkconsistent(lfs2_t *lfs2) { +int lfs2_fs_gc(lfs2_t *lfs2) { int err = LFS2_LOCK(lfs2->cfg); if (err) { return err; } - LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2); + LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2); - err = lfs2_fs_rawmkconsistent(lfs2); + err = lfs2_fs_gc_(lfs2); - LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err); + LFS2_TRACE("lfs2_fs_gc -> %d", err); LFS2_UNLOCK(lfs2->cfg); return err; } @@ -6290,7 +6508,7 @@ int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count) { } LFS2_TRACE("lfs2_fs_grow(%p, %"PRIu32")", (void*)lfs2, block_count); - err = lfs2_fs_rawgrow(lfs2, block_count); + err = lfs2_fs_grow_(lfs2, block_count); LFS2_TRACE("lfs2_fs_grow -> %d", err); LFS2_UNLOCK(lfs2->cfg); @@ -6308,7 +6526,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { ".read=%p, .prog=%p, .erase=%p, .sync=%p, " ".read_size=%"PRIu32", .prog_size=%"PRIu32", " ".block_size=%"PRIu32", .block_count=%"PRIu32", " - ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", " + ".block_cycles=%"PRId32", .cache_size=%"PRIu32", " ".lookahead_size=%"PRIu32", .read_buffer=%p, " ".prog_buffer=%p, .lookahead_buffer=%p, " ".name_max=%"PRIu32", .file_max=%"PRIu32", " @@ -6321,7 +6539,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) { cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer, cfg->name_max, cfg->file_max, cfg->attr_max); - err = lfs2_rawmigrate(lfs2, cfg); + err = lfs2_migrate_(lfs2, cfg); LFS2_TRACE("lfs2_migrate -> %d", err); LFS2_UNLOCK(cfg); diff --git a/lib/littlefs/lfs2.h b/lib/littlefs/lfs2.h index 559ccebac9269..aee0619e9326a 100644 --- a/lib/littlefs/lfs2.h +++ b/lib/littlefs/lfs2.h @@ -21,7 +21,7 @@ extern "C" // Software library version // Major (top-nibble), incremented on backwards incompatible changes // Minor (bottom-nibble), incremented on feature additions -#define LFS2_VERSION 0x00020008 +#define LFS2_VERSION 0x0002000b #define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) #define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) @@ -52,16 +52,15 @@ typedef uint32_t lfs2_block_t; #endif // Maximum size of a file in bytes, may be redefined to limit to support other -// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the -// functions lfs2_file_seek, lfs2_file_size, and lfs2_file_tell will return -// incorrect values due to using signed integers. Stored in superblock and -// must be respected by other littlefs drivers. +// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be +// respected by other littlefs drivers. #ifndef LFS2_FILE_MAX #define LFS2_FILE_MAX 2147483647 #endif // Maximum size of custom attributes in bytes, may be redefined, but there is -// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. +// no real benefit to using a smaller LFS2_ATTR_MAX. Limited to <= 1022. Stored +// in superblock and must be respected by other littlefs drivers. #ifndef LFS2_ATTR_MAX #define LFS2_ATTR_MAX 1022 #endif @@ -205,7 +204,8 @@ struct lfs2_config { // program sizes. lfs2_size_t block_size; - // Number of erasable blocks on the device. + // Number of erasable blocks on the device. Defaults to block_count stored + // on disk when zero. lfs2_size_t block_count; // Number of erase cycles before littlefs evicts metadata logs and moves @@ -226,9 +226,20 @@ struct lfs2_config { // Size of the lookahead buffer in bytes. A larger lookahead buffer // increases the number of blocks found during an allocation pass. The // lookahead buffer is stored as a compact bitmap, so each byte of RAM - // can track 8 blocks. Must be a multiple of 8. + // can track 8 blocks. lfs2_size_t lookahead_size; + // Threshold for metadata compaction during lfs2_fs_gc in bytes. Metadata + // pairs that exceed this threshold will be compacted during lfs2_fs_gc. + // Defaults to ~88% block_size when zero, though the default may change + // in the future. + // + // Note this only affects lfs2_fs_gc. Normal compactions still only occur + // when full. + // + // Set to -1 to disable metadata compaction during lfs2_fs_gc. + lfs2_size_t compact_thresh; + // Optional statically allocated read buffer. Must be cache_size. // By default lfs2_malloc is used to allocate this buffer. void *read_buffer; @@ -237,25 +248,24 @@ struct lfs2_config { // By default lfs2_malloc is used to allocate this buffer. void *prog_buffer; - // Optional statically allocated lookahead buffer. Must be lookahead_size - // and aligned to a 32-bit boundary. By default lfs2_malloc is used to - // allocate this buffer. + // Optional statically allocated lookahead buffer. Must be lookahead_size. + // By default lfs2_malloc is used to allocate this buffer. void *lookahead_buffer; // Optional upper limit on length of file names in bytes. No downside for // larger names except the size of the info struct which is controlled by - // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX when zero. Stored in - // superblock and must be respected by other littlefs drivers. + // the LFS2_NAME_MAX define. Defaults to LFS2_NAME_MAX or name_max stored on + // disk when zero. lfs2_size_t name_max; // Optional upper limit on files in bytes. No downside for larger files - // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX when zero. Stored - // in superblock and must be respected by other littlefs drivers. + // but must be <= LFS2_FILE_MAX. Defaults to LFS2_FILE_MAX or file_max stored + // on disk when zero. lfs2_size_t file_max; // Optional upper limit on custom attributes in bytes. No downside for // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to - // LFS2_ATTR_MAX when zero. + // LFS2_ATTR_MAX or attr_max stored on disk when zero. lfs2_size_t attr_max; // Optional upper limit on total space given to metadata pairs in bytes. On @@ -264,6 +274,15 @@ struct lfs2_config { // Defaults to block_size when zero. lfs2_size_t metadata_max; + // Optional upper limit on inlined files in bytes. Inlined files live in + // metadata and decrease storage requirements, but may be limited to + // improve metadata-related performance. Must be <= cache_size, <= + // attr_max, and <= block_size/8. Defaults to the largest possible + // inline_max when zero. + // + // Set to -1 to disable inlined files. + lfs2_size_t inline_max; + #ifdef LFS2_MULTIVERSION // On-disk version to use when writing in the form of 16-bit major version // + 16-bit minor version. This limiting metadata to what is supported by @@ -430,19 +449,20 @@ typedef struct lfs2 { lfs2_gstate_t gdisk; lfs2_gstate_t gdelta; - struct lfs2_free { - lfs2_block_t off; + struct lfs2_lookahead { + lfs2_block_t start; lfs2_block_t size; - lfs2_block_t i; - lfs2_block_t ack; - uint32_t *buffer; - } free; + lfs2_block_t next; + lfs2_block_t ckpoint; + uint8_t *buffer; + } lookahead; const struct lfs2_config *cfg; lfs2_size_t block_count; lfs2_size_t name_max; lfs2_size_t file_max; lfs2_size_t attr_max; + lfs2_size_t inline_max; #ifdef LFS2_MIGRATE struct lfs21 *lfs21; @@ -712,18 +732,6 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2); // Returns a negative error code on failure. int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void*, lfs2_block_t), void *data); -// Attempt to proactively find free blocks -// -// Calling this function is not required, but may allowing the offloading of -// the expensive block allocation scan to a less time-critical code path. -// -// Note: littlefs currently does not persist any found free blocks to disk. -// This may change in the future. -// -// Returns a negative error code on failure. Finding no free blocks is -// not an error. -int lfs2_fs_gc(lfs2_t *lfs2); - #ifndef LFS2_READONLY // Attempt to make the filesystem consistent and ready for writing // @@ -736,11 +744,33 @@ int lfs2_fs_gc(lfs2_t *lfs2); int lfs2_fs_mkconsistent(lfs2_t *lfs2); #endif +#ifndef LFS2_READONLY +// Attempt any janitorial work +// +// This currently: +// 1. Calls mkconsistent if not already consistent +// 2. Compacts metadata > compact_thresh +// 3. Populates the block allocator +// +// Though additional janitorial work may be added in the future. +// +// Calling this function is not required, but may allow the offloading of +// expensive janitorial work to a less time-critical code path. +// +// Returns a negative error code on failure. Accomplishing nothing is not +// an error. +int lfs2_fs_gc(lfs2_t *lfs2); +#endif + #ifndef LFS2_READONLY // Grows the filesystem to a new size, updating the superblock with the new // block count. // -// Note: This is irreversible. +// If LFS2_SHRINKNONRELOCATING is defined, this function will also accept +// block_counts smaller than the current configuration, after checking +// that none of the blocks that are being removed are in use. +// Note that littlefs's pseudorandom block allocation means that +// this is very unlikely to work in the general case. // // Returns a negative error code on failure. int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count); diff --git a/lib/littlefs/lfs2_util.c b/lib/littlefs/lfs2_util.c index c9850e78869c3..4fe7e5340ce77 100644 --- a/lib/littlefs/lfs2_util.c +++ b/lib/littlefs/lfs2_util.c @@ -11,6 +11,8 @@ #ifndef LFS2_CONFIG +// If user provides their own CRC impl we don't need this +#ifndef LFS2_CRC // Software CRC implementation with small lookup table uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { static const uint32_t rtable[16] = { @@ -29,6 +31,7 @@ uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { return crc; } +#endif #endif diff --git a/lib/littlefs/lfs2_util.h b/lib/littlefs/lfs2_util.h index dd2cbcc106d84..12c82a630b079 100644 --- a/lib/littlefs/lfs2_util.h +++ b/lib/littlefs/lfs2_util.h @@ -8,6 +8,9 @@ #ifndef LFS2_UTIL_H #define LFS2_UTIL_H +#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) +#define LFS2_STRINGIZE2(x) #x + // Users can override lfs2_util.h with their own configuration by defining // LFS2_CONFIG as a header file to include (-DLFS2_CONFIG=lfs2_config.h). // @@ -15,11 +18,26 @@ // provided by the config file. To start, I would suggest copying lfs2_util.h // and modifying as needed. #ifdef LFS2_CONFIG -#define LFS2_STRINGIZE(x) LFS2_STRINGIZE2(x) -#define LFS2_STRINGIZE2(x) #x #include LFS2_STRINGIZE(LFS2_CONFIG) #else +// Alternatively, users can provide a header file which defines +// macros and other things consumed by littlefs. +// +// For example, provide my_defines.h, which contains +// something like: +// +// #include +// extern void *my_malloc(size_t sz); +// #define LFS2_MALLOC(sz) my_malloc(sz) +// +// And build littlefs with the header by defining LFS2_DEFINES. +// (-DLFS2_DEFINES=my_defines.h) + +#ifdef LFS2_DEFINES +#include LFS2_STRINGIZE(LFS2_DEFINES) +#endif + // System includes #include #include @@ -177,10 +195,10 @@ static inline uint32_t lfs2_fromle32(uint32_t a) { (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) return __builtin_bswap32(a); #else - return (((uint8_t*)&a)[0] << 0) | - (((uint8_t*)&a)[1] << 8) | - (((uint8_t*)&a)[2] << 16) | - (((uint8_t*)&a)[3] << 24); + return ((uint32_t)((uint8_t*)&a)[0] << 0) | + ((uint32_t)((uint8_t*)&a)[1] << 8) | + ((uint32_t)((uint8_t*)&a)[2] << 16) | + ((uint32_t)((uint8_t*)&a)[3] << 24); #endif } @@ -200,10 +218,10 @@ static inline uint32_t lfs2_frombe32(uint32_t a) { (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) return a; #else - return (((uint8_t*)&a)[0] << 24) | - (((uint8_t*)&a)[1] << 16) | - (((uint8_t*)&a)[2] << 8) | - (((uint8_t*)&a)[3] << 0); + return ((uint32_t)((uint8_t*)&a)[0] << 24) | + ((uint32_t)((uint8_t*)&a)[1] << 16) | + ((uint32_t)((uint8_t*)&a)[2] << 8) | + ((uint32_t)((uint8_t*)&a)[3] << 0); #endif } @@ -212,12 +230,22 @@ static inline uint32_t lfs2_tobe32(uint32_t a) { } // Calculate CRC-32 with polynomial = 0x04c11db7 +#ifdef LFS2_CRC +static inline uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size) { + return LFS2_CRC(crc, buffer, size); +} +#else uint32_t lfs2_crc(uint32_t crc, const void *buffer, size_t size); +#endif // Allocate memory, only used if buffers are not provided to littlefs -// Note, memory must be 64-bit aligned +// +// littlefs current has no alignment requirements, as it only allocates +// byte-level buffers. static inline void *lfs2_malloc(size_t size) { -#ifndef LFS2_NO_MALLOC +#if defined(LFS2_MALLOC) + return LFS2_MALLOC(size); +#elif !defined(LFS2_NO_MALLOC) return malloc(size); #else (void)size; @@ -227,7 +255,9 @@ static inline void *lfs2_malloc(size_t size) { // Deallocate memory, only used if buffers are not provided to littlefs static inline void lfs2_free(void *p) { -#ifndef LFS2_NO_MALLOC +#if defined(LFS2_FREE) + LFS2_FREE(p); +#elif !defined(LFS2_NO_MALLOC) free(p); #else (void)p; diff --git a/lib/mbedtls_config/crt_bundle.c b/lib/mbedtls_config/crt_bundle.c index b0994e22ab9ba..9c546a2688313 100644 --- a/lib/mbedtls_config/crt_bundle.c +++ b/lib/mbedtls_config/crt_bundle.c @@ -41,8 +41,8 @@ static mbedtls_x509_crt s_dummy_crt; #define LOGD(tag, fmt, ...) do {} while (0) #endif -extern const uint8_t x509_crt_imported_bundle_bin_start[] asm ("_binary_x509_crt_bundle_start"); -extern const uint8_t x509_crt_imported_bundle_bin_end[] asm ("_binary_x509_crt_bundle_end"); +extern const uint8_t x509_crt_imported_bundle_bin_start[] __asm__ ("_binary_x509_crt_bundle_start"); +extern const uint8_t x509_crt_imported_bundle_bin_end[] __asm__ ("_binary_x509_crt_bundle_end"); typedef struct crt_bundle_t { diff --git a/lib/mbedtls_config/mbedtls_config.h b/lib/mbedtls_config/mbedtls_config.h index 3791924a13c65..7943994e1575e 100644 --- a/lib/mbedtls_config/mbedtls_config.h +++ b/lib/mbedtls_config/mbedtls_config.h @@ -93,6 +93,7 @@ #define MBEDTLS_PKCS5_C #define MBEDTLS_PEM_PARSE_C #define MBEDTLS_PK_C +#define MBEDTLS_PK_HAVE_ECC_KEYS #define MBEDTLS_PK_PARSE_C #define MBEDTLS_PLATFORM_C #define MBEDTLS_RSA_C @@ -100,6 +101,7 @@ #define MBEDTLS_SHA256_C #define MBEDTLS_SHA512_C #define MBEDTLS_SSL_CLI_C +#define MBEDTLS_SSL_PROTO_DTLS #define MBEDTLS_SSL_SRV_C #define MBEDTLS_SSL_TLS_C #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE diff --git a/lib/mbedtls_config/mbedtls_port.c b/lib/mbedtls_config/mbedtls_port.c index 73929c85e81ed..b7e8ceae5de0f 100644 --- a/lib/mbedtls_config/mbedtls_port.c +++ b/lib/mbedtls_config/mbedtls_port.c @@ -27,15 +27,13 @@ #if CIRCUITPY_SSL_MBEDTLS +#include "py/runtime.h" #include "mbedtls_config.h" #include "mbedtls/entropy_poll.h" -#include "hardware/rtc.h" #include "shared/timeutils/timeutils.h" #include "shared-bindings/os/__init__.h" - -#include "hardware/rtc.h" -#include "shared/timeutils/timeutils.h" +#include "shared-bindings/time/__init__.h" extern uint8_t rosc_random_u8(size_t cycles); @@ -46,9 +44,10 @@ int mbedtls_hardware_poll(void *data, unsigned char *output, size_t len, size_t } time_t rp2_rtctime_seconds(time_t *timer) { - datetime_t t; - rtc_get_datetime(&t); - return timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec); + mp_obj_t datetime = mp_load_attr(MP_STATE_VM(rtc_time_source), MP_QSTR_datetime); + timeutils_struct_time_t tm; + struct_time_to_tm(datetime, &tm); + return timeutils_seconds_since_epoch(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } #endif diff --git a/lib/micropython-lib b/lib/micropython-lib index 7cdf70881519c..6ae440a8a1442 160000 --- a/lib/micropython-lib +++ b/lib/micropython-lib @@ -1 +1 @@ -Subproject commit 7cdf70881519c73667efbc4a61a04d9c1a49babb +Subproject commit 6ae440a8a144233e6e703f6759b7e7a0afaa37a4 diff --git a/lib/protomatter b/lib/protomatter index 282920f9ce594..f83bac7e42107 160000 --- a/lib/protomatter +++ b/lib/protomatter @@ -1 +1 @@ -Subproject commit 282920f9ce5948c02e1c803b9c2b6ecee7dc7b66 +Subproject commit f83bac7e421077812523fddb83d3e25f29753315 diff --git a/lib/tinytest/README b/lib/tinytest/README deleted file mode 100644 index 28165d8bc794a..0000000000000 --- a/lib/tinytest/README +++ /dev/null @@ -1,17 +0,0 @@ -Tinytest is a tiny little test framework written in C by Nick Mathewson. - -It is distributed under the 3-clause BSD license. You can use it in -your own programs so long as you follow the license's conditions. - -It's been tested on Windows, Mac, and many of the free Unixes. - -It knows how to fork before running certain tests, and it makes -text-mode output in a format I like. - -For info on how to use it, check out tinytest_demo.c. - -You can get the latest version using Git, by pulling from - git://github.com/nmathewson/tinytest.git - -Patches are welcome. Patches that turn this from tinytest to hugetest -will not be applied. If you want a huge test framework, use CUnit. diff --git a/lib/tinytest/tinytest.c b/lib/tinytest/tinytest.c deleted file mode 100644 index 1a5030ae3c5ac..0000000000000 --- a/lib/tinytest/tinytest.c +++ /dev/null @@ -1,473 +0,0 @@ -/* tinytest.c -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifdef TINYTEST_LOCAL -#include "tinytest_local.h" -#endif - -#include -#include -#include -#include - -#ifndef NO_FORKING - -#ifdef _WIN32 -#include -#else -#include -#include -#include -#endif - -#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \ - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070) -/* Workaround for a stupid bug in OSX 10.6 */ -#define FORK_BREAKS_GCOV -#include -#endif -#endif - -#endif /* !NO_FORKING */ - -#ifndef __GNUC__ -#define __attribute__(x) -#endif - -#include "tinytest.h" -#include "tinytest_macros.h" - -#define LONGEST_TEST_NAME 16384 - -static int in_tinytest_main = 0; /**< true if we're in tinytest_main().*/ -static int n_ok = 0; /**< Number of tests that have passed */ -static int n_bad = 0; /**< Number of tests that have failed. */ -static int n_skipped = 0; /**< Number of tests that have been skipped. */ - -static int opt_forked = 0; /**< True iff we're called from inside a win32 fork*/ -static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */ -static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */ -const char *verbosity_flag = ""; - -const struct testlist_alias_t *cfg_aliases=NULL; - -enum outcome { SKIP=2, OK=1, FAIL=0 }; -static enum outcome cur_test_outcome = 0; -const char *cur_test_prefix = NULL; /**< prefix of the current test group */ -/** Name of the current test, if we haven't logged is yet. Used for --quiet */ -const char *cur_test_name = NULL; - -#ifdef _WIN32 -/* Copy of argv[0] for win32. */ -static char commandname[MAX_PATH+1]; -#endif - -static void usage(struct testgroup_t *groups, int list_groups) - __attribute__((noreturn)); -static int process_test_option(struct testgroup_t *groups, const char *test); - -static enum outcome -testcase_run_bare_(const struct testcase_t *testcase) -{ - void *env = NULL; - int outcome; - if (testcase->setup) { - env = testcase->setup->setup_fn(testcase); - if (!env) - return FAIL; - else if (env == (void*)TT_SKIP) - return SKIP; - } - - cur_test_outcome = OK; - testcase->fn(env); - outcome = cur_test_outcome; - - if (testcase->setup) { - if (testcase->setup->cleanup_fn(testcase, env) == 0) - outcome = FAIL; - } - - return outcome; -} - -#define MAGIC_EXITCODE 42 - -#ifndef NO_FORKING - -static enum outcome -testcase_run_forked_(const struct testgroup_t *group, - const struct testcase_t *testcase) -{ -#ifdef _WIN32 - /* Fork? On Win32? How primitive! We'll do what the smart kids do: - we'll invoke our own exe (whose name we recall from the command - line) with a command line that tells it to run just the test we - want, and this time without forking. - - (No, threads aren't an option. The whole point of forking is to - share no state between tests.) - */ - int ok; - char buffer[LONGEST_TEST_NAME+256]; - STARTUPINFOA si; - PROCESS_INFORMATION info; - DWORD exitcode; - - if (!in_tinytest_main) { - printf("\nERROR. On Windows, testcase_run_forked_ must be" - " called from within tinytest_main.\n"); - abort(); - } - if (opt_verbosity>0) - printf("[forking] "); - - snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", - commandname, verbosity_flag, group->prefix, testcase->name); - - memset(&si, 0, sizeof(si)); - memset(&info, 0, sizeof(info)); - si.cb = sizeof(si); - - ok = CreateProcessA(commandname, buffer, NULL, NULL, 0, - 0, NULL, NULL, &si, &info); - if (!ok) { - printf("CreateProcess failed!\n"); - return 0; - } - WaitForSingleObject(info.hProcess, INFINITE); - GetExitCodeProcess(info.hProcess, &exitcode); - CloseHandle(info.hProcess); - CloseHandle(info.hThread); - if (exitcode == 0) - return OK; - else if (exitcode == MAGIC_EXITCODE) - return SKIP; - else - return FAIL; -#else - int outcome_pipe[2]; - pid_t pid; - (void)group; - - if (pipe(outcome_pipe)) - perror("opening pipe"); - - if (opt_verbosity>0) - printf("[forking] "); - pid = fork(); -#ifdef FORK_BREAKS_GCOV - vproc_transaction_begin(0); -#endif - if (!pid) { - /* child. */ - int test_r, write_r; - char b[1]; - close(outcome_pipe[0]); - test_r = testcase_run_bare_(testcase); - assert(0<=(int)test_r && (int)test_r<=2); - b[0] = "NYS"[test_r]; - write_r = (int)write(outcome_pipe[1], b, 1); - if (write_r != 1) { - perror("write outcome to pipe"); - exit(1); - } - exit(0); - return FAIL; /* unreachable */ - } else { - /* parent */ - int status, r; - char b[1]; - /* Close this now, so that if the other side closes it, - * our read fails. */ - close(outcome_pipe[1]); - r = (int)read(outcome_pipe[0], b, 1); - if (r == 0) { - printf("[Lost connection!] "); - return 0; - } else if (r != 1) { - perror("read outcome from pipe"); - } - waitpid(pid, &status, 0); - close(outcome_pipe[0]); - return b[0]=='Y' ? OK : (b[0]=='S' ? SKIP : FAIL); - } -#endif -} - -#endif /* !NO_FORKING */ - -int -testcase_run_one(const struct testgroup_t *group, - const struct testcase_t *testcase) -{ - enum outcome outcome; - - if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) { - if (opt_verbosity>0) - printf("%s%s: %s\n", - group->prefix, testcase->name, - (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED"); - ++n_skipped; - return SKIP; - } - - if (opt_verbosity>0 && !opt_forked) { - printf("%s%s: ", group->prefix, testcase->name); - } else { - if (opt_verbosity==0) printf("."); - cur_test_prefix = group->prefix; - cur_test_name = testcase->name; - } - -#ifndef NO_FORKING - if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { - outcome = testcase_run_forked_(group, testcase); - } else { -#else - { -#endif - outcome = testcase_run_bare_(testcase); - } - - if (outcome == OK) { - ++n_ok; - if (opt_verbosity>0 && !opt_forked) - puts(opt_verbosity==1?"OK":""); - } else if (outcome == SKIP) { - ++n_skipped; - if (opt_verbosity>0 && !opt_forked) - puts("SKIPPED"); - } else { - ++n_bad; - if (!opt_forked) - printf("\n [%s FAILED]\n", testcase->name); - } - - if (opt_forked) { - exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1)); - return 1; /* unreachable */ - } else { - return (int)outcome; - } -} - -int -tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag) -{ - int i, j; - size_t length = LONGEST_TEST_NAME; - char fullname[LONGEST_TEST_NAME]; - int found=0; - if (strstr(arg, "..")) - length = strstr(arg,"..")-arg; - for (i=0; groups[i].prefix; ++i) { - for (j=0; groups[i].cases[j].name; ++j) { - struct testcase_t *testcase = &groups[i].cases[j]; - snprintf(fullname, sizeof(fullname), "%s%s", - groups[i].prefix, testcase->name); - if (!flag) { /* Hack! */ - printf(" %s", fullname); - if (testcase->flags & TT_OFF_BY_DEFAULT) - puts(" (Off by default)"); - else if (testcase->flags & TT_SKIP) - puts(" (DISABLED)"); - else - puts(""); - } - if (!strncmp(fullname, arg, length)) { - if (set) - testcase->flags |= flag; - else - testcase->flags &= ~flag; - ++found; - } - } - } - return found; -} - -static void -usage(struct testgroup_t *groups, int list_groups) -{ - puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); - puts(" Specify tests by name, or using a prefix ending with '..'"); - puts(" To skip a test, prefix its name with a colon."); - puts(" To enable a disabled test, prefix its name with a plus."); - puts(" Use --list-tests for a list of tests."); - if (list_groups) { - puts("Known tests are:"); - tinytest_set_flag_(groups, "..", 1, 0); - } - exit(0); -} - -static int -process_test_alias(struct testgroup_t *groups, const char *test) -{ - int i, j, n, r; - for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) { - if (!strcmp(cfg_aliases[i].name, test)) { - n = 0; - for (j = 0; cfg_aliases[i].tests[j]; ++j) { - r = process_test_option(groups, cfg_aliases[i].tests[j]); - if (r<0) - return -1; - n += r; - } - return n; - } - } - printf("No such test alias as @%s!",test); - return -1; -} - -static int -process_test_option(struct testgroup_t *groups, const char *test) -{ - int flag = TT_ENABLED_; - int n = 0; - if (test[0] == '@') { - return process_test_alias(groups, test + 1); - } else if (test[0] == ':') { - ++test; - flag = TT_SKIP; - } else if (test[0] == '+') { - ++test; - ++n; - if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) { - printf("No such test as %s!\n", test); - return -1; - } - } else { - ++n; - } - if (!tinytest_set_flag_(groups, test, 1, flag)) { - printf("No such test as %s!\n", test); - return -1; - } - return n; -} - -void -tinytest_set_aliases(const struct testlist_alias_t *aliases) -{ - cfg_aliases = aliases; -} - -int -tinytest_main(int c, const char **v, struct testgroup_t *groups) -{ - int i, j, n=0; - -#ifdef _WIN32 - const char *sp = strrchr(v[0], '.'); - const char *extension = ""; - if (!sp || stricmp(sp, ".exe")) - extension = ".exe"; /* Add an exe so CreateProcess will work */ - snprintf(commandname, sizeof(commandname), "%s%s", v[0], extension); - commandname[MAX_PATH]='\0'; -#endif - for (i=1; i= 1) - printf("%d tests ok. (%d skipped)\n", n_ok, n_skipped); - - return (n_bad == 0) ? 0 : 1; -} - -int -tinytest_get_verbosity_(void) -{ - return opt_verbosity; -} - -void -tinytest_set_test_failed_(void) -{ - if (opt_verbosity <= 0 && cur_test_name) { - if (opt_verbosity==0) puts(""); - printf("%s%s: ", cur_test_prefix, cur_test_name); - cur_test_name = NULL; - } - cur_test_outcome = 0; -} - -void -tinytest_set_test_skipped_(void) -{ - if (cur_test_outcome==OK) - cur_test_outcome = SKIP; -} diff --git a/lib/tinytest/tinytest.h b/lib/tinytest/tinytest.h deleted file mode 100644 index dff440e3190ed..0000000000000 --- a/lib/tinytest/tinytest.h +++ /dev/null @@ -1,98 +0,0 @@ -/* tinytest.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_H_INCLUDED_ -#define TINYTEST_H_INCLUDED_ - -/** Flag for a test that needs to run in a subprocess. */ -#define TT_FORK (1<<0) -/** Runtime flag for a test we've decided to skip. */ -#define TT_SKIP (1<<1) -/** Internal runtime flag for a test we've decided to run. */ -#define TT_ENABLED_ (1<<2) -/** Flag for a test that's off by default. */ -#define TT_OFF_BY_DEFAULT (1<<3) -/** If you add your own flags, make them start at this point. */ -#define TT_FIRST_USER_FLAG (1<<4) - -typedef void (*testcase_fn)(void *); - -struct testcase_t; - -/** Functions to initialize/teardown a structure for a testcase. */ -struct testcase_setup_t { - /** Return a new structure for use by a given testcase. */ - void *(*setup_fn)(const struct testcase_t *); - /** Clean/free a structure from setup_fn. Return 1 if ok, 0 on err. */ - int (*cleanup_fn)(const struct testcase_t *, void *); -}; - -/** A single test-case that you can run. */ -struct testcase_t { - const char *name; /**< An identifier for this case. */ - testcase_fn fn; /**< The function to run to implement this case. */ - unsigned long flags; /**< Bitfield of TT_* flags. */ - const struct testcase_setup_t *setup; /**< Optional setup/cleanup fns*/ - void *setup_data; /**< Extra data usable by setup function */ -}; -#define END_OF_TESTCASES { NULL, NULL, 0, NULL, NULL } - -/** A group of tests that are selectable together. */ -struct testgroup_t { - const char *prefix; /**< Prefix to prepend to testnames. */ - struct testcase_t *cases; /** Array, ending with END_OF_TESTCASES */ -}; -#define END_OF_GROUPS { NULL, NULL} - -struct testlist_alias_t { - const char *name; - const char **tests; -}; -#define END_OF_ALIASES { NULL, NULL } - -/** Implementation: called from a test to indicate failure, before logging. */ -void tinytest_set_test_failed_(void); -/** Implementation: called from a test to indicate that we're skipping. */ -void tinytest_set_test_skipped_(void); -/** Implementation: return 0 for quiet, 1 for normal, 2 for loud. */ -int tinytest_get_verbosity_(void); -/** Implementation: Set a flag on tests matching a name; returns number - * of tests that matched. */ -int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long); - -/** Set all tests in 'groups' matching the name 'named' to be skipped. */ -#define tinytest_skip(groups, named) \ - tinytest_set_flag_(groups, named, 1, TT_SKIP) - -/** Run a single testcase in a single group. */ -int testcase_run_one(const struct testgroup_t *,const struct testcase_t *); - -void tinytest_set_aliases(const struct testlist_alias_t *aliases); - -/** Run a set of testcases from an END_OF_GROUPS-terminated array of groups, - as selected from the command line. */ -int tinytest_main(int argc, const char **argv, struct testgroup_t *groups); - -#endif diff --git a/lib/tinytest/tinytest_macros.h b/lib/tinytest/tinytest_macros.h deleted file mode 100644 index 9ff69b1d506da..0000000000000 --- a/lib/tinytest/tinytest_macros.h +++ /dev/null @@ -1,184 +0,0 @@ -/* tinytest_macros.h -- Copyright 2009-2012 Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef TINYTEST_MACROS_H_INCLUDED_ -#define TINYTEST_MACROS_H_INCLUDED_ - -/* Helpers for defining statement-like macros */ -#define TT_STMT_BEGIN do { -#define TT_STMT_END } while (0) - -/* Redefine this if your test functions want to abort with something besides - * "goto end;" */ -#ifndef TT_EXIT_TEST_FUNCTION -#define TT_EXIT_TEST_FUNCTION TT_STMT_BEGIN goto end; TT_STMT_END -#endif - -/* Redefine this if you want to note success/failure in some different way. */ -#ifndef TT_DECLARE -#define TT_DECLARE(prefix, args) \ - TT_STMT_BEGIN \ - printf("\n %s %s:%d: ",prefix,__FILE__,__LINE__); \ - printf args ; \ - TT_STMT_END -#endif - -/* Announce a failure. Args are parenthesized printf args. */ -#define TT_GRIPE(args) TT_DECLARE("FAIL", args) - -/* Announce a non-failure if we're verbose. */ -#define TT_BLATHER(args) \ - TT_STMT_BEGIN \ - if (tinytest_get_verbosity_()>1) TT_DECLARE(" OK", args); \ - TT_STMT_END - -#define TT_DIE(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define TT_FAIL(args) \ - TT_STMT_BEGIN \ - tinytest_set_test_failed_(); \ - TT_GRIPE(args); \ - TT_STMT_END - -/* Fail and abort the current test for the reason in msg */ -#define tt_abort_printf(msg) TT_DIE(msg) -#define tt_abort_perror(op) TT_DIE(("%s: %s [%d]",(op),strerror(errno), errno)) -#define tt_abort_msg(msg) TT_DIE(("%s", msg)) -#define tt_abort() TT_DIE(("%s", "(Failed.)")) - -/* Fail but do not abort the current test for the reason in msg. */ -#define tt_failprint_f(msg) TT_FAIL(msg) -#define tt_fail_perror(op) TT_FAIL(("%s: %s [%d]",(op),strerror(errno), errno)) -#define tt_fail_msg(msg) TT_FAIL(("%s", msg)) -#define tt_fail() TT_FAIL(("%s", "(Failed.)")) - -/* End the current test, and indicate we are skipping it. */ -#define tt_skip() \ - TT_STMT_BEGIN \ - tinytest_set_test_skipped_(); \ - TT_EXIT_TEST_FUNCTION; \ - TT_STMT_END - -#define tt_want_(b, msg, fail) \ - TT_STMT_BEGIN \ - if (!(b)) { \ - tinytest_set_test_failed_(); \ - TT_GRIPE(("%s",msg)); \ - fail; \ - } else { \ - TT_BLATHER(("%s",msg)); \ - } \ - TT_STMT_END - -/* Assert b, but do not stop the test if b fails. Log msg on failure. */ -#define tt_want_msg(b, msg) \ - tt_want_(b, msg, ); - -/* Assert b and stop the test if b fails. Log msg on failure. */ -#define tt_assert_msg(b, msg) \ - tt_want_(b, msg, TT_EXIT_TEST_FUNCTION); - -/* Assert b, but do not stop the test if b fails. */ -#define tt_want(b) tt_want_msg( (b), "want("#b")") -/* Assert b, and stop the test if b fails. */ -#define tt_assert(b) tt_assert_msg((b), "assert("#b")") - -#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \ - setup_block,cleanup_block,die_on_fail) \ - TT_STMT_BEGIN \ - type val1_ = (type)(a); \ - type val2_ = (type)(b); \ - int tt_status_ = (test); \ - if (!tt_status_ || tinytest_get_verbosity_()>1) { \ - printf_type print_; \ - printf_type print1_; \ - printf_type print2_; \ - type value_ = val1_; \ - setup_block; \ - print1_ = print_; \ - value_ = val2_; \ - setup_block; \ - print2_ = print_; \ - TT_DECLARE(tt_status_?" OK":"FAIL", \ - ("assert(%s): "printf_fmt" vs "printf_fmt, \ - str_test, print1_, print2_)); \ - print_ = print1_; \ - cleanup_block; \ - print_ = print2_; \ - cleanup_block; \ - if (!tt_status_) { \ - tinytest_set_test_failed_(); \ - die_on_fail ; \ - } \ - } \ - TT_STMT_END - -#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \ - tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \ - {print_=value_;},{},die_on_fail) - -/* Helper: assert that a op b, when cast to type. Format the values with - * printf format fmt on failure. */ -#define tt_assert_op_type(a,op,b,type,fmt) \ - tt_assert_test_type(a,b,#a" "#op" "#b,type,(val1_ op val2_),fmt, \ - TT_EXIT_TEST_FUNCTION) - -#define tt_int_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_), \ - "%ld",TT_EXIT_TEST_FUNCTION) - -#define tt_uint_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ - (val1_ op val2_),"%lu",TT_EXIT_TEST_FUNCTION) - -#define tt_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ - (val1_ op val2_),"%p",TT_EXIT_TEST_FUNCTION) - -#define tt_str_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ - (strcmp(val1_,val2_) op 0),"<%s>",TT_EXIT_TEST_FUNCTION) - -#define tt_want_int_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0) - -#define tt_want_uint_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ - (val1_ op val2_),"%lu",(void)0) - -#define tt_want_ptr_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ - (val1_ op val2_),"%p",(void)0) - -#define tt_want_str_op(a,op,b) \ - tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \ - (strcmp(val1_,val2_) op 0),"<%s>",(void)0) - -#endif diff --git a/lib/tinyusb b/lib/tinyusb index ac1fd3266644a..c1bf19ed6cf1e 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit ac1fd3266644a2d87e38ef3e353ed9f60a618d50 +Subproject commit c1bf19ed6cf1eaa791f221c1bc5ce4b3d069f76d diff --git a/locale/ID.po b/locale/ID.po index a4a60d84d4b45..ca862a9714768 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -6,15 +6,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Scott Shawcroft \n" +"PO-Revision-Date: 2026-02-13 15:09+0000\n" +"Last-Translator: Arif Budiman \n" "Language-Team: LANGUAGE \n" "Language: ID\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.16-dev\n" #: main.c msgid "" @@ -29,6 +29,8 @@ msgid "" "\n" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +"\n" +"Kode dihentikan karena pemuatan ulang otomatis. Akan segera dimuat ulang.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -36,18 +38,25 @@ msgid "" "Please file an issue with your program at github.com/adafruit/circuitpython/" "issues." msgstr "" +"\n" +"Silakan laporkan masalah dengan program Anda di github.com/adafruit/" +"sirkuitpython/issues." #: supervisor/shared/safe_mode.c msgid "" "\n" "Press reset to exit safe mode.\n" msgstr "" +"\n" +"Tekan reset untuk keluar dari mode aman.\n" #: supervisor/shared/safe_mode.c msgid "" "\n" "You are in safe mode because:\n" msgstr "" +"\n" +"Anda berada dalam mode aman karena:\n" #: py/obj.c msgid " File \"%q\"" @@ -67,7 +76,7 @@ msgstr " tidak ketemu.\n" #: main.c msgid " output:\n" -msgstr "output:\n" +msgstr " output:\n" #: py/objstr.c #, c-format @@ -85,17 +94,17 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q dan %q berisi pin duplikat" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" -msgstr "" +msgstr "%q dan %q harus berbeda" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "%q and %q must share a clock unit" -msgstr "" +msgstr "%q dan %q harus berbagi unit jam" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "%q cannot be changed once mode is set to %q" -msgstr "" +msgstr "%q tidak dapat diubah setelah mode diatur ke %q" #: shared-bindings/microcontroller/Pin.c msgid "%q contains duplicate pins" @@ -105,9 +114,13 @@ msgstr "%q berisi pin duplikat" msgid "%q failure: %d" msgstr "%q gagal: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q dalam %q harus bertipe %q atau %q, bukan %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" -msgstr "" +msgstr "%q dalam %q harus bertipe %q, bukan %q" #: ports/espressif/common-hal/espulp/ULP.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c @@ -131,19 +144,19 @@ msgstr "indeks %q harus bilangan bulat, bukan %s" #: shared-module/bitbangio/SPI.c msgid "%q init failed" -msgstr "" +msgstr "%q inisiasi gagal" #: ports/espressif/bindings/espnow/Peer.c shared-bindings/dualbank/__init__.c msgid "%q is %q" -msgstr "" +msgstr "%q adalah %q" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "%q is read-only for this board" -msgstr "" +msgstr "%q hanya dapat dibaca untuk papan ini" #: py/argcheck.c shared-bindings/usb_hid/Device.c msgid "%q length must be %d" -msgstr "" +msgstr "%q panjangnya harus %d" #: py/argcheck.c msgid "%q length must be %d-%d" @@ -151,19 +164,19 @@ msgstr "%q panjang harus %d-%d" #: py/argcheck.c msgid "%q length must be <= %d" -msgstr "" +msgstr "%q panjangnya harus <= %d" #: py/argcheck.c msgid "%q length must be >= %d" -msgstr "" +msgstr "%q panjangnya harus >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" -msgstr "" +msgstr "%q dipindahkan dari %q ke %q" #: py/argcheck.c msgid "%q must be %d" -msgstr "" +msgstr "%q harusnya %d" #: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/displayio/Bitmap.c @@ -175,7 +188,7 @@ msgstr "%q harus %d-%d" #: shared-bindings/busdisplay/BusDisplay.c msgid "%q must be 1 when %q is True" -msgstr "" +msgstr "%q harus 1 ketika %q bernilai Benar" #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c @@ -184,7 +197,7 @@ msgstr "%q harus <= %d" #: ports/espressif/common-hal/watchdog/WatchDogTimer.c msgid "%q must be <= %u" -msgstr "" +msgstr "%q harus <= %u" #: py/argcheck.c msgid "%q must be >= %d" @@ -192,43 +205,45 @@ msgstr "%q harus >= %d" #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" -msgstr "" +msgstr "%q harus berupa bytearray atau array bertipe 'H' atau 'B'" #: shared-bindings/audiocore/RawSample.c msgid "%q must be a bytearray or array of type 'h', 'H', 'b', or 'B'" -msgstr "" +msgstr "%q harus berupa bytearray atau array bertipe 'h', 'H', 'b', atau 'B'" #: shared-bindings/warnings/__init__.c msgid "%q must be a subclass of %q" -msgstr "" +msgstr "%q harus menjadi subkelas dari %q" #: ports/espressif/common-hal/analogbufio/BufferedIn.c msgid "%q must be array of type 'H'" -msgstr "" +msgstr "%q harus berupa array bertipe 'H'" #: shared-module/synthio/__init__.c msgid "%q must be array of type 'h'" -msgstr "" +msgstr "%q harus berupa array bertipe 'h'" #: shared-bindings/audiobusio/PDMIn.c msgid "%q must be multiple of 8." -msgstr "" +msgstr "%q harus kelipatan 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" -msgstr "" +msgstr "%q harus bertipe %q atau %q, bukan %q" #: shared-bindings/jpegio/JpegDecoder.c msgid "%q must be of type %q, %q, or %q, not %q" -msgstr "" +msgstr "%q harus bertipe %q, %q, atau %q, bukan %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" -msgstr "" +msgstr "%q harus dari tipe %q, bukan %q" #: ports/atmel-samd/common-hal/busio/UART.c msgid "%q must be power of 2" @@ -236,7 +251,7 @@ msgstr "%q harus pangkat 2" #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" -msgstr "" +msgstr "%q di luar batas" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c @@ -249,15 +264,15 @@ msgstr "%q di luar jangkauan" #: py/objmodule.c py/runtime.c msgid "%q renamed %q" -msgstr "" +msgstr "%q berganti nama menjadi %q" #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" -msgstr "" +msgstr "%q step tidak boleh nol" #: shared-module/bitbangio/I2C.c msgid "%q too long" -msgstr "" +msgstr "%q terlalu panjang" #: py/bc.c py/objnamedtuple.c msgid "%q() takes %d positional arguments but %d were given" @@ -265,31 +280,32 @@ msgstr "%q() mengambil posisi argumen %d tapi %d yang diberikan" #: shared-module/jpegio/JpegDecoder.c msgid "%q() without %q()" -msgstr "" +msgstr "%q() tanpa %q()" #: shared-bindings/usb_hid/Device.c msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, dan %q semuanya harus memiliki panjang yang sama" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" -msgstr "" +msgstr "%q=%q" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] shifts in more bits than pin count" -msgstr "" +msgstr "%q[%u] berpindah lebih banyak bit daripada jumlah pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] shifts out more bits than pin count" -msgstr "" +msgstr "%q[%u] menggeser lebih banyak bit daripada jumlah pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] uses extra pin" -msgstr "" +msgstr "%q[%u] menggunakan pin tambahan" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] waits on input outside of count" -msgstr "" +msgstr "%q[%u] menunggu input di luar hitungan" #: ports/espressif/common-hal/espidf/__init__.c #, c-format @@ -305,7 +321,7 @@ msgid "'%q' object does not support '%q'" msgstr "Objek '%q' tidak mendukung '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "Objek '%q' bukan merupakan iterator" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -313,7 +329,7 @@ msgid "'%q' object is not callable" msgstr "Objek '%q' tidak dapat dipanggil" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "Objek '%q' tidak dapat diulang" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -364,17 +380,17 @@ msgstr "'%s' integer %d tidak berada dalam jangkauan %d..%d" #: py/emitinlinethumb.c #, c-format msgid "'%s' integer 0x%x doesn't fit in mask 0x%x" -msgstr "" +msgstr "'%s' Integer 0x%x tidak cocok dengan mask 0x%x" #: py/obj.c #, c-format msgid "'%s' object doesn't support item assignment" -msgstr "" +msgstr "Objek '%s' tidak mendukung penetapan item" #: py/obj.c #, c-format msgid "'%s' object doesn't support item deletion" -msgstr "" +msgstr "Objek '%s' tidak mendukung penghapusan item" #: py/runtime.c msgid "'%s' object has no attribute '%q'" @@ -383,7 +399,7 @@ msgstr "Objek '%s' tidak memiliki atribut '%q'" #: py/obj.c #, c-format msgid "'%s' object isn't subscriptable" -msgstr "" +msgstr "Objek '%s' tidak dapat dijadikan subskrip" #: py/objstr.c msgid "'=' alignment not allowed in string format specifier" @@ -403,7 +419,7 @@ msgstr "'await' diluar fungsi" #: py/compile.c msgid "'break'/'continue' outside loop" -msgstr "" +msgstr "'break'/'continue' di luar loop" #: py/compile.c msgid "'data' requires at least 2 arguments" @@ -417,6 +433,10 @@ msgstr "'data' membutuhkan argumen integer" msgid "'label' requires 1 argument" msgstr "'label' membutuhkan 1 argumen" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' tidak diimplementasikan" + #: py/compile.c msgid "'return' outside function" msgstr "'return' diluar fungsi" @@ -431,7 +451,7 @@ msgstr "'yield' diluar fungsi" #: py/compile.c msgid "* arg after **" -msgstr "" +msgstr "* arg setelah **" #: py/compile.c msgid "*x must be assignment target" @@ -445,7 +465,7 @@ msgstr ", dalam %q\n" #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid ".show(x) removed. Use .root_group = x" -msgstr "" +msgstr ".show(x) dihapus. Gunakan .root_group = x" #: py/objcomplex.c msgid "0.0 to a complex power" @@ -457,7 +477,7 @@ msgstr "pow() 3-arg tidak didukung" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "AP could not be started" -msgstr "" +msgstr "AP tidak dapat dimulai" #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c #, c-format @@ -468,15 +488,15 @@ msgstr "Alamat harus sepanjang %d byte" #: ports/nordic/common-hal/memorymap/AddressRange.c #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Address range not allowed" -msgstr "" +msgstr "Rentang alamat tidak diizinkan" #: shared-bindings/memorymap/AddressRange.c msgid "Address range wraps around" -msgstr "" +msgstr "Rentang alamat melingkar" #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" -msgstr "" +msgstr "Semua peripheral CAN sedang digunakan" #: ports/espressif/common-hal/busio/I2C.c #: ports/espressif/common-hal/i2ctarget/I2CTarget.c @@ -502,11 +522,11 @@ msgstr "Semua perangkat UART sedang digunakan" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/rotaryio/IncrementalEncoder.c msgid "All channels in use" -msgstr "" +msgstr "Semua saluran sedang digunakan" #: ports/raspberrypi/common-hal/usb_host/Port.c msgid "All dma channels in use" -msgstr "" +msgstr "Semua saluran dma sedang digunakan" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "All event channels in use" @@ -517,7 +537,7 @@ msgstr "Semua channel event sedang digunakan" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c msgid "All state machines in use" -msgstr "" +msgstr "Semua mesin status yang digunakan" #: ports/atmel-samd/audio_dma.c msgid "All sync event channels in use" @@ -536,7 +556,6 @@ msgstr "Semua timer untuk pin ini sedang digunakan" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Semua timer sedang digunakan" @@ -547,28 +566,33 @@ msgstr "Sudah disebarkan." #: ports/atmel-samd/common-hal/canio/Listener.c msgid "Already have all-matches listener" -msgstr "" +msgstr "Sudah memiliki listener semua-kecocokan" + +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Sudah dalam proses" #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c #: shared-module/memorymonitor/AllocationSize.c msgid "Already running" -msgstr "" +msgstr "Sudah berjalan" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" -msgstr "" +msgstr "Sudah memindai jaringan wifi" #: shared-module/os/getenv.c #, c-format msgid "An error occurred while retrieving '%s':\n" -msgstr "" +msgstr "Terjadi kesalahan saat mengambil '%s':\n" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Another PWMAudioOut is already active" -msgstr "" +msgstr "PWMAudioOut lainnya sudah aktif" #: ports/atmel-samd/common-hal/pulseio/PulseOut.c #: ports/cxd56/common-hal/pulseio/PulseOut.c @@ -584,22 +608,31 @@ msgstr "Array harus mengandung halfwords (ketik 'H')" msgid "Array values should be single bytes." msgstr "Nilai array harus berupa byte tunggal." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "Transfer SPI async sedang berlangsung pada bus ini, terus menunggu." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" -msgstr "" +msgstr "Mencoba mengalokasikan %d blok" #: ports/raspberrypi/audio_dma.c msgid "Audio conversion not implemented" -msgstr "" +msgstr "Konversi audio belum diimplementasikan" + +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Kesalahan sumber audio" #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" -msgstr "" +msgstr "AuthMode.OPEN tidak digunakan dengan kata sandi" #: shared-bindings/wifi/Radio.c supervisor/shared/web_workflow/web_workflow.c msgid "Authentication failure" -msgstr "" +msgstr "Kegagalan otentikasi" #: main.c msgid "Auto-reload is off.\n" @@ -615,7 +648,7 @@ msgstr "" #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" -msgstr "" +msgstr "Baudrate tidak didukung oleh periferal" #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -624,19 +657,19 @@ msgstr "Di bawah frame rate minimum" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential GPIO pins" -msgstr "" +msgstr "Jam bit dan pemilihan kata harus berupa pin GPIO berurutan" #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" -msgstr "" +msgstr "Ukuran bitmap dan bit per nilai harus cocok" #: supervisor/shared/safe_mode.c msgid "Boot device must be first (interface #0)." -msgstr "" +msgstr "Perangkat boot harus menjadi yang pertama (interface #0)." #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" -msgstr "" +msgstr "RX dan TX diperlukan untuk kontrol aliran" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -650,7 +683,7 @@ msgstr "Buffer + offset terlalu kecil %d %d %d" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" -msgstr "" +msgstr "Elemen buffer harus berukuran panjang 4 byte atau kurang" #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Buffer is not a bytearray." @@ -662,13 +695,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Panjang buffer %d terlalu besar. Itu harus kurang dari %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Panjang buffer harus kelipatan 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Buffer harus kelipatan %d byte" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -680,7 +713,7 @@ msgstr "Buffer terlalu pendek untuk %d byte" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/struct/__init__.c shared-module/struct/__init__.c msgid "Buffer too small" -msgstr "" +msgstr "Buffer terlalu kecil" #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c @@ -700,11 +733,11 @@ msgstr "Blok CBC harus merupakan kelipatan 16 byte" #: supervisor/shared/safe_mode.c msgid "CIRCUITPY drive could not be found or created." -msgstr "" +msgstr "Drive CIRCUITPY tidak bisa ditemukan atau dibuat." #: ports/espressif/common-hal/espidf/__init__.c msgid "CRC or checksum was invalid" -msgstr "" +msgstr "CRC atau checksum tidak valid" #: py/objtype.c msgid "Call super().__init__() before accessing native object." @@ -712,19 +745,29 @@ msgstr "Panggil super().__init__() sebelum mengakses objek asli." #: ports/cxd56/common-hal/camera/Camera.c msgid "Camera init" -msgstr "" +msgstr "Inisialisasi kamera" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on RTC IO from deep sleep." msgstr "" +"Hanya dapat mengaktifkan alarm pada RTC IO dari mode tidur dalam (deep " +"sleep)." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on one low pin while others alarm high from deep sleep." msgstr "" +"Hanya dapat mengaktifkan alarm pada satu pin rendah sementara pin lainnya " +"dalam keadaan tinggi dari mode tidur dalam (deep sleep)." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on two low pins from deep sleep." msgstr "" +"Hanya dapat mengaktifkan alarm pada dua pin rendah dari mode tidur dalam " +"(deep sleep)." + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "Tidak dapat membuat AudioOut karena kanal berkelanjutan sudah terbuka" #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c @@ -735,11 +778,11 @@ msgstr "Tidak dapat mengatur CCCD pada Karakteristik lokal" #: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c #: shared-bindings/usb_video/__init__.c msgid "Cannot change USB devices now" -msgstr "" +msgstr "Tidak dapat mengganti perangkat USB saat ini" #: shared-bindings/_bleio/Adapter.c msgid "Cannot create a new Adapter; use _bleio.adapter;" -msgstr "" +msgstr "Tidak dapat membuat Adapter baru; gunakan _bleio.adapter;" #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c @@ -766,15 +809,15 @@ msgstr "" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot pull on input-only pin." -msgstr "" +msgstr "Tidak dapat menarik pin input saja." #: shared-bindings/audiobusio/PDMIn.c msgid "Cannot record to a file" msgstr "Tidak dapat merekam ke file" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "" +msgid "Cannot remount path when visible via USB." +msgstr "Tidak dapat me-remount jalur ketika terlihat melalui USB." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -789,13 +832,17 @@ msgstr "Tidak dapat menentukan RTS atau CTS dalam mode RS485" msgid "Cannot subclass slice" msgstr "Tidak dapat membuat subkelas dari irisan" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "Tidak dapat menggunakan GPIO0..15 bersamaan dengan GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" -msgstr "" +msgstr "Tidak dapat bangun di tepi pin, hanya level" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge. Only level." -msgstr "" +msgstr "Tidak dapat bergerak di tepi pin. Hanya level." #: shared-bindings/_bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" @@ -818,15 +865,19 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "Coordinate arrays have different lengths" -msgstr "" +msgstr "Deretan koordinat memiliki panjang yang berbeda" #: shared-bindings/bitmaptools/__init__.c msgid "Coordinate arrays types have different sizes" -msgstr "" +msgstr "Tipe array koordinat memiliki ukuran yang berbeda" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "Tidak dapat mempublikasikan ke topik ROS" #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" -msgstr "" +msgstr "Tidak dapat mengatur alamat" #: ports/stm/common-hal/busio/UART.c msgid "Could not start interrupt, RX busy" @@ -836,6 +887,11 @@ msgstr "Tidak dapat memulai interupsi, RX sibuk" msgid "Couldn't allocate decoder" msgstr "Tidak dapat mengalokasikan dekoder" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Kegagalan ROS kritis selama soft reboot, reset diperlukan: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Terjadi kesalahan saat menginisialisasi kanal DAC" @@ -853,18 +909,14 @@ msgstr "DAC sudah digunakan" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 pin harus byte disejajarkan" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Potongan data harus mengikuti fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" -msgstr "" +msgstr "Kesalahan format data (mungkin data rusak)" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "" +msgstr "Data tidak didukung dengan iklan terarah" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c @@ -874,6 +926,8 @@ msgstr "Data terlalu besar untuk paket advertisment" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" +"Pin tidur dalam (deep sleep) harus menggunakan tepi naik dengan penarik ke " +"bawah (pulldown)." #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." @@ -881,7 +935,7 @@ msgstr "Kapasitas tujuan lebih kecil dari destination_length." #: shared-module/jpegio/JpegDecoder.c msgid "Device error or wrong termination of input stream" -msgstr "" +msgstr "Kesalahan perangkat atau penghentian aliran input yang salah" #: ports/nordic/common-hal/audiobusio/I2SOut.c msgid "Device in use" @@ -900,7 +954,7 @@ msgstr "Rotasi tampilan harus dalam kelipatan 90 derajat" #: main.c msgid "Done" -msgstr "" +msgstr "Selesai" #: shared-bindings/digitalio/DigitalInOut.c msgid "Drive mode not used when direction is input." @@ -908,7 +962,7 @@ msgstr "Mode kendara tidak digunakan saat arah input." #: py/obj.c msgid "During handling of the above exception, another exception occurred:" -msgstr "" +msgstr "Selama penanganan pengecualian di atas, pengecualian lain terjadi:" #: shared-bindings/aesio/aes.c msgid "ECB only operates on 16 bytes at a time" @@ -917,7 +971,7 @@ msgstr "ECB hanya beroperasi pada 16 byte di satu waktu" #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c msgid "ESP-IDF memory allocation failed" -msgstr "" +msgstr "Alokasi memori ESP-IDF gagal" #: extmod/modre.c msgid "Error in regex" @@ -925,11 +979,11 @@ msgstr "Error pada regex" #: supervisor/shared/safe_mode.c msgid "Error in safemode.py." -msgstr "" +msgstr "Kesalahan dalam safemode.py." #: shared-bindings/alarm/__init__.c msgid "Expected a kind of %q" -msgstr "" +msgstr "Diharapkan semacam %q" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c @@ -942,7 +996,7 @@ msgstr "FFT didefinisikan hanya untuk ndarrays" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "FFT is implemented for linear arrays only" -msgstr "" +msgstr "FFT diimplementasikan hanya untuk array linier" #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." @@ -955,28 +1009,30 @@ msgstr "Gagal memperoleh mutex, err 0x%04x" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Failed to add service TXT record" -msgstr "" +msgstr "Gagal menambahkan record TXT layanan" #: shared-bindings/mdns/Server.c msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" +"Gagal menambahkan record TXT layanan; ditemukan non-string atau bytes dalam " +"txt_records" #: shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" -msgstr "" +msgstr "Gagal mengalokasikan buffer %q" #: ports/espressif/common-hal/wifi/__init__.c msgid "Failed to allocate Wifi memory" -msgstr "" +msgstr "Gagal mengalokasikan memori Wifi" #: ports/espressif/common-hal/wifi/ScannedNetworks.c msgid "Failed to allocate wifi scan memory" -msgstr "" +msgstr "Gagal mengalokasikan memori pemindaian wifi" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Failed to buffer the sample" -msgstr "" +msgstr "Gagal membuffer sampel" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c @@ -987,15 +1043,47 @@ msgstr "Gagal terhubung: kesalahan internal" msgid "Failed to connect: timeout" msgstr "Gagal terhubung: habis waktu" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Gagal membuat kanal berkelanjutan: argumen tidak valid" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Gagal membuat kanal berkelanjutan: status tidak valid" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Gagal membuat kanal berkelanjutan: tidak ada memori" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Gagal membuat kanal berkelanjutan: tidak ditemukan" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Gagal mengaktifkan berkelanjutan" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Gagal mengurai file MP3" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Gagal mendaftarkan callback event berkelanjutan" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Gagal melepaskan mutex, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Gagal menetapkan hostname" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Gagal memulai audio async" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Gagal menulis flash internal." @@ -1004,44 +1092,47 @@ msgstr "Gagal menulis flash internal." msgid "File exists" msgstr "File sudah ada" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" -msgstr "" +msgstr "File tidak ditemukan" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" -msgstr "" +msgstr "Filter terlalu kompleks" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is duplicate" -msgstr "" +msgstr "Firmware adalah duplikat" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is invalid" -msgstr "" +msgstr "Firmware tidak valid" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is too big" -msgstr "" +msgstr "Firmware terlalu besar" #: shared-bindings/bitmaptools/__init__.c msgid "For L8 colorspace, input bitmap must have 8 bits per pixel" -msgstr "" +msgstr "Untuk colorspace L8, bitmap input harus memiliki 8 bit per piksel" #: shared-bindings/bitmaptools/__init__.c msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" -msgstr "" +msgstr "Untuk colorspace RGB, bitmap input harus memiliki 16 bit per piksel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" -msgstr "" +msgstr "Format tidak didukung" #: ports/mimxrt10xx/common-hal/microcontroller/Processor.c msgid "" "Frequency must be 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 or 1008 Mhz" msgstr "" +"Frekuensi harus 24, 150, 396, 450, 528, 600, 720, 816, 912, 960 atau 1008 Mhz" #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c @@ -1050,11 +1141,11 @@ msgstr "Fungsinya membutuhkan kunci" #: ports/cxd56/common-hal/gnss/GNSS.c msgid "GNSS init" -msgstr "" +msgstr "Inisialisasi GNSS" #: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" -msgstr "" +msgstr "Kegagalan Umum" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c @@ -1064,7 +1155,7 @@ msgstr "Grup sudah digunakan" #: supervisor/shared/safe_mode.c msgid "Hard fault: memory access or instruction error." -msgstr "" +msgstr "Hard fault: kesalahan akses memori atau instruksi." #: ports/mimxrt10xx/common-hal/busio/SPI.c #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/I2C.c @@ -1075,7 +1166,7 @@ msgstr "Perangkat keras sedang digunakan, coba pin alternatif" #: supervisor/shared/safe_mode.c msgid "Heap allocation when VM not running." -msgstr "" +msgstr "Alokasi heap ketika VM tidak berjalan." #: extmod/vfs_posix_file.c py/objstringio.c msgid "I/O operation on closed file" @@ -1083,16 +1174,16 @@ msgstr "operasi I/O pada file tertutup" #: ports/stm/common-hal/busio/I2C.c msgid "I2C init error" -msgstr "" +msgstr "Kesalahan inisialisasi I2C" #: ports/raspberrypi/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c msgid "I2C peripheral in use" -msgstr "" +msgstr "Periferal I2C sedang digunakan" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "In-buffer elements must be <= 4 bytes long" -msgstr "" +msgstr "Elemen in-buffer harus <= 4 byte panjangnya" #: shared-bindings/_pew/PewPew.c msgid "Incorrect buffer size" @@ -1100,24 +1191,25 @@ msgstr "Ukuran penyangga salah" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Init program size invalid" -msgstr "" +msgstr "Ukuran program inisialisasi tidak valid" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direction conflicts with initial out pin direction" -msgstr "" +msgstr "Arah pin set awal berkonflik dengan arah pin out awal" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin state conflicts with initial out pin state" -msgstr "" +msgstr "Status pin set awal berkonflik dengan status pin out awal" #: shared-bindings/bitops/__init__.c #, c-format msgid "Input buffer length (%d) must be a multiple of the strand count (%d)" msgstr "" +"Panjang buffer input (%d) harus merupakan kelipatan dari jumlah strand (%d)" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c msgid "Input taking too long" -msgstr "" +msgstr "Input memakan waktu terlalu lama" #: py/moderrno.c msgid "Input/output error" @@ -1135,19 +1227,20 @@ msgstr "Enkripsi tidak cukup" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient memory pool for the image" -msgstr "" +msgstr "Pool memori tidak mencukupi untuk gambar" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient stream input buffer" -msgstr "" +msgstr "Buffer input stream tidak mencukupi" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" -msgstr "" +msgstr "Interface harus dimulai" #: ports/atmel-samd/audio_dma.c ports/raspberrypi/audio_dma.c msgid "Internal audio buffer too small" -msgstr "" +msgstr "Buffer audio internal terlalu kecil" #: ports/stm/common-hal/busio/UART.c msgid "Internal define error" @@ -1155,7 +1248,7 @@ msgstr "Kesalahan definisi internal" #: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c msgid "Internal error" -msgstr "" +msgstr "Kesalahan internal" #: shared-module/rgbmatrix/RGBMatrix.c #, c-format @@ -1173,36 +1266,40 @@ msgstr "Kesalahan internal #%d" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-bindings/pwmio/PWMOut.c msgid "Internal resource(s) in use" -msgstr "" +msgstr "Sumber daya internal sedang digunakan" #: supervisor/shared/safe_mode.c msgid "Internal watchdog timer expired." -msgstr "" +msgstr "Timer watchdog internal kedaluwarsa." #: supervisor/shared/safe_mode.c msgid "Interrupt error." -msgstr "" +msgstr "Kesalahan interrupt." #: shared-module/jpegio/JpegDecoder.c msgid "Interrupted by output function" -msgstr "" +msgstr "Diinterupsi oleh fungsi output" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" -msgstr "" +msgstr "%q tidak valid" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "%q dan %q tidak valid" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1218,15 +1315,19 @@ msgstr "Nilai Unit ADC tidak valid" #: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid BLE parameter" -msgstr "" +msgstr "Parameter BLE tidak valid" #: shared-bindings/wifi/Radio.c msgid "Invalid BSSID" -msgstr "" +msgstr "BSSID tidak valid" #: shared-bindings/wifi/Radio.c msgid "Invalid MAC address" -msgstr "" +msgstr "Alamat MAC tidak valid" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "ID domain ROS tidak valid" #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" @@ -1239,16 +1340,16 @@ msgstr "Bit per nilai tidak valid" #: shared-module/os/getenv.c #, c-format msgid "Invalid byte %.*s" -msgstr "" +msgstr "Byte tidak valid %.*s" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" -msgstr "" +msgstr "data_pins[%d] tidak valid" #: shared-module/msgpack/__init__.c msgid "Invalid format" -msgstr "" +msgstr "Format tidak valid" #: shared-module/audiocore/WaveFile.c msgid "Invalid format chunk size" @@ -1256,27 +1357,29 @@ msgstr "Ukuran potongan format tidak valid" #: shared-bindings/wifi/Radio.c msgid "Invalid hex password" -msgstr "" +msgstr "Password hex tidak valid" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" -msgstr "" +msgstr "Alamat MAC multicast tidak valid" #: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" -msgstr "" +msgstr "Ukuran tidak valid" #: shared-module/ssl/SSLSocket.c msgid "Invalid socket for TLS" -msgstr "" +msgstr "Socket tidak valid untuk TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" -msgstr "" +msgstr "Status tidak valid" #: shared-module/os/getenv.c msgid "Invalid unicode escape" -msgstr "" +msgstr "Escape unicode tidak valid" #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" @@ -1284,11 +1387,11 @@ msgstr "Panjang kunci harus 16, 24, atau 32 byte" #: shared-module/os/getenv.c msgid "Key not found" -msgstr "" +msgstr "Kunci tidak ditemukan" #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" -msgstr "" +msgstr "Pemetaan LED harus sesuai dengan ukuran display" #: py/compile.c msgid "LHS of keyword arg must be an id" @@ -1296,76 +1399,84 @@ msgstr "LHS dari keyword arg harus menjadi sebuah id" #: shared-module/displayio/Group.c msgid "Layer already in a group" -msgstr "" +msgstr "Layer sudah ada dalam grup" #: shared-module/displayio/Group.c msgid "Layer must be a Group or TileGrid subclass" -msgstr "" +msgstr "Layer harus merupakan subclass Group atau TileGrid" #: shared-bindings/audiocore/RawSample.c msgid "Length of %q must be an even multiple of channel_count * type_size" msgstr "" +"Panjang %q harus merupakan kelipatan genap dari channel_count * type_size" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" -msgstr "" +msgstr "Alamat MAC tidak valid" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" -msgstr "" +msgstr "Keamanan MITM tidak didukung" + +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "Kesalahan Clock MMC/SDIO %x" #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" -msgstr "" +msgstr "Mapping harus berupa tuple" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" -msgstr "" +msgstr "Ukuran data tidak cocok" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched swap flag" -msgstr "" +msgstr "Flag swap tidak cocok" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] reads pin(s)" -msgstr "" +msgstr "first_in_pin tidak ada. %q[%u] membaca pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] shifts in from pin(s)" -msgstr "" +msgstr "first_in_pin tidak ada. %q[%u] melakukan shift in dari pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_in_pin. %q[%u] waits based on pin" -msgstr "" +msgstr "first_in_pin tidak ada. %q[%u] menunggu berdasarkan pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_out_pin. %q[%u] shifts out to pin(s)" -msgstr "" +msgstr "first_out_pin tidak ada. %q[%u] melakukan shift out ke pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_out_pin. %q[%u] writes pin(s)" -msgstr "" +msgstr "first_out_pin tidak ada. %q[%u] menulis pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing first_set_pin. %q[%u] sets pin(s)" -msgstr "" +msgstr "first_set_pin tidak ada. %q[%u] menetapkan pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing jmp_pin. %q[%u] jumps on pin" -msgstr "" +msgstr "jmp_pin tidak ada. %q[%u] melompat pada pin" #: shared-module/storage/__init__.c msgid "Mount point directory missing" -msgstr "" +msgstr "Direktori titik mount tidak ada" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Harus berupa subclass %q." #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c msgid "Must provide 5/6/5 RGB pins" -msgstr "" +msgstr "Harus menyediakan pin RGB 5/6/5" #: ports/mimxrt10xx/common-hal/busio/SPI.c shared-bindings/busio/SPI.c msgid "Must provide MISO or MOSI pin" @@ -1378,23 +1489,23 @@ msgstr "Harus menggunakan kelipatan 6 pin rgb, bukan %d" #: supervisor/shared/safe_mode.c msgid "NLR jump failed. Likely memory corruption." -msgstr "" +msgstr "Lompatan NLR gagal. Kemungkinan korupsi memori." #: ports/espressif/common-hal/nvm/ByteArray.c msgid "NVS Error" -msgstr "" +msgstr "Kesalahan NVS" #: shared-bindings/socketpool/SocketPool.c msgid "Name or service not known" -msgstr "" +msgstr "Nama atau layanan tidak diketahui" #: shared-bindings/displayio/TileGrid.c msgid "New bitmap must be same size as old bitmap" -msgstr "" +msgstr "Bitmap baru harus berukuran sama dengan bitmap lama" #: ports/espressif/common-hal/_bleio/__init__.c msgid "Nimble out of memory" -msgstr "" +msgstr "Nimble kehabisan memori" #: ports/atmel-samd/common-hal/busio/UART.c #: ports/espressif/common-hal/busio/SPI.c @@ -1429,26 +1540,26 @@ msgstr "tidak ada channel DMA ditemukan" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "No DMA pacing timer found" -msgstr "" +msgstr "Tidak ditemukan timer pacing DMA" #: shared-module/adafruit_bus_device/i2c_device/I2CDevice.c #, c-format msgid "No I2C device at address: 0x%x" -msgstr "" +msgstr "Tidak ada perangkat I2C pada alamat: 0x%x" #: supervisor/shared/web_workflow/web_workflow.c msgid "No IP" -msgstr "" +msgstr "Tidak ada IP" #: ports/atmel-samd/common-hal/microcontroller/__init__.c #: ports/cxd56/common-hal/microcontroller/__init__.c #: ports/mimxrt10xx/common-hal/microcontroller/__init__.c msgid "No bootloader present" -msgstr "" +msgstr "Tidak ada bootloader" #: shared-module/usb/core/Device.c msgid "No configuration set" -msgstr "" +msgstr "Tidak ada konfigurasi yang ditetapkan" #: shared-bindings/_bleio/PacketBuffer.c msgid "No connection: length cannot be determined" @@ -1470,11 +1581,11 @@ msgstr "Tidak ada perangkat keras acak yang tersedia" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "" +msgstr "Tidak ada in dalam program" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "" +msgstr "Tidak ada in atau out dalam program" #: py/objint.c shared-bindings/time/__init__.c msgid "No long integer support" @@ -1482,30 +1593,34 @@ msgstr "Tidak ada dukungan bilangan bulat yang panjang" #: shared-bindings/wifi/Radio.c msgid "No network with that ssid" -msgstr "" +msgstr "Tidak ada jaringan dengan ssid tersebut" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No out in program" -msgstr "" +msgstr "Tidak ada out dalam program" #: ports/atmel-samd/common-hal/busio/I2C.c #: ports/espressif/common-hal/busio/I2C.c #: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nordic/common-hal/busio/I2C.c #: ports/raspberrypi/common-hal/busio/I2C.c msgid "No pull up found on SDA or SCL; check your wiring" -msgstr "" +msgstr "Tidak ditemukan pull up pada SDA atau SCL; periksa pengkabelan Anda" #: shared-module/touchio/TouchIn.c msgid "No pulldown on pin; 1Mohm recommended" msgstr "Tidak ada pull-down pada pin; 1Mohm direkomendasikan" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Tidak ada pullup pada pin; 1Mohm direkomendasikan" + #: py/moderrno.c msgid "No space left on device" msgstr "Tidak ada ruang yang tersisa di perangkat" #: py/moderrno.c msgid "No such device" -msgstr "" +msgstr "Perangkat tidak ada" #: py/moderrno.c msgid "No such file/directory" @@ -1517,15 +1632,15 @@ msgstr "Penghitung waktu tidak tersedia" #: shared-module/usb/core/Device.c msgid "No usb host port initialized" -msgstr "" +msgstr "Tidak ada port host usb yang diinisialisasi" #: ports/nordic/common-hal/_bleio/__init__.c msgid "Nordic system firmware out of memory" -msgstr "" +msgstr "Firmware sistem Nordic kehabisan memori" #: shared-bindings/ipaddress/IPv4Address.c shared-bindings/ipaddress/__init__.c msgid "Not a valid IP string" -msgstr "" +msgstr "Bukan string IP yang valid" #: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c @@ -1543,9 +1658,10 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Jumlah data_pins harus %d atau %d, bukan %d" #: shared-bindings/util.c msgid "" @@ -1559,17 +1675,17 @@ msgstr "Parity ganjil tidak didukung" #: supervisor/shared/bluetooth/bluetooth.c msgid "Off" -msgstr "" +msgstr "Mati" #: supervisor/shared/bluetooth/bluetooth.c msgid "Ok" -msgstr "" +msgstr "Ok" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c #, c-format msgid "Only 8 or 16 bit mono with %dx oversampling supported." -msgstr "" +msgstr "Hanya mono 8 atau 16 bit dengan oversampling %dx yang didukung." #: ports/espressif/common-hal/wifi/__init__.c #: ports/raspberrypi/common-hal/wifi/__init__.c @@ -1590,60 +1706,51 @@ msgstr "" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" -msgstr "" +msgstr "Hanya advertisement yang dapat terhubung yang dapat diarahkan" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Only edge detection is available on this hardware" -msgstr "" +msgstr "Hanya deteksi tepi yang tersedia pada perangkat keras ini" #: shared-bindings/ipaddress/__init__.c msgid "Only int or string supported for ip" -msgstr "" - -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Hanya monokrom, 4bpp atau 8bpp yang diindeks, dan 16bpp atau lebih yang " -"didukung: %d bpp diberikan" +msgstr "Hanya int atau string yang didukung untuk ip" #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." -msgstr "" +msgstr "Hanya satu %q yang dapat ditetapkan dalam deep sleep." #: ports/espressif/common-hal/espulp/ULPAlarm.c msgid "Only one %q can be set." -msgstr "" +msgstr "Hanya satu %q yang dapat ditetapkan." #: ports/espressif/common-hal/i2ctarget/I2CTarget.c #: ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c msgid "Only one address is allowed" -msgstr "" +msgstr "Hanya satu alamat yang diperbolehkan" #: ports/atmel-samd/common-hal/alarm/time/TimeAlarm.c #: ports/nordic/common-hal/alarm/time/TimeAlarm.c #: ports/stm/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set" -msgstr "" +msgstr "Hanya satu alarm alarm.time yang dapat ditetapkan" #: ports/espressif/common-hal/alarm/time/TimeAlarm.c #: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set." -msgstr "" +msgstr "Hanya satu alarm alarm.time yang dapat ditetapkan." #: shared-module/displayio/ColorConverter.c msgid "Only one color can be transparent at a time" -msgstr "" +msgstr "Hanya satu warna yang dapat transparan pada satu waktu" #: py/moderrno.c msgid "Operation not permitted" -msgstr "" +msgstr "Operasi tidak diizinkan" #: ports/espressif/common-hal/espidf/__init__.c msgid "Operation or feature not supported" -msgstr "" +msgstr "Operasi atau fitur tidak didukung" #: ports/espressif/common-hal/espidf/__init__.c msgid "Operation timed out" @@ -1651,7 +1758,7 @@ msgstr "Waktu habis" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Out of MDNS service slots" -msgstr "" +msgstr "Kehabisan slot layanan MDNS" #: ports/espressif/common-hal/espidf/__init__.c msgid "Out of memory" @@ -1659,28 +1766,33 @@ msgstr "Kehabisan memori" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Kehabisan socket" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out-buffer elements must be <= 4 bytes long" -msgstr "" +msgstr "Elemen out-buffer harus <= 4 byte panjangnya" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "PWM restart" -msgstr "" +msgstr "Restart PWM" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "PWM slice already in use" -msgstr "" +msgstr "Slice PWM sudah digunakan" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "PWM slice channel A already in use" -msgstr "" +msgstr "Channel A slice PWM sudah digunakan" + +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "Buffer paket untuk transfer SPI harus memiliki panjang yang sama." #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" -msgstr "" +msgstr "Kesalahan parameter" #: ports/espressif/common-hal/audiobusio/__init__.c msgid "Peripheral in use" @@ -1692,7 +1804,7 @@ msgstr "Izin ditolak" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Pin cannot wake from Deep Sleep" -msgstr "" +msgstr "Pin tidak dapat membangunkan dari Deep Sleep" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Pin count too large" @@ -1701,15 +1813,15 @@ msgstr "Jumlah pin terlalu besar" #: ports/stm/common-hal/alarm/pin/PinAlarm.c #: ports/stm/common-hal/pulseio/PulseIn.c msgid "Pin interrupt already in use" -msgstr "" +msgstr "Pin interupsi sudah digunakan" #: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c msgid "Pin is input only" -msgstr "" +msgstr "Pin hanya input" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "Pin must be on PWM Channel B" -msgstr "" +msgstr "Pin harus berada di Saluran PWM B" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -1728,15 +1840,15 @@ msgstr "Pin harus berurutan" #: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c msgid "Pins must be sequential GPIO pins" -msgstr "" +msgstr "Pin harus merupakan pin GPIO yang berurutan" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Pins must share PWM slice" -msgstr "" +msgstr "Pin harus berbagi potongan PWM" #: shared-module/usb/core/Device.c msgid "Pipe error" -msgstr "" +msgstr "Kesalahan pipe" #: py/builtinhelp.c msgid "Plus any modules on the filesystem\n" @@ -1744,11 +1856,11 @@ msgstr "Tambahkan module apapun pada filesystem\n" #: shared-module/vectorio/Polygon.c msgid "Polygon needs at least 3 points" -msgstr "" +msgstr "Poligon membutuhkan setidaknya 3 poin" #: supervisor/shared/safe_mode.c msgid "Power dipped. Make sure you are providing enough power." -msgstr "" +msgstr "Daya menurun. Pastikan Anda menyediakan daya yang cukup." #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" @@ -1762,23 +1874,27 @@ msgstr "" #: main.c msgid "Pretending to deep sleep until alarm, CTRL-C or file write.\n" -msgstr "" +msgstr "Berpura-pura deep sleep sampai alarm, CTRL-C atau penulisan file.\n" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Program does IN without loading ISR" -msgstr "" +msgstr "Program melakukan IN tanpa memuat ISR" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Program does OUT without loading OSR" -msgstr "" +msgstr "Program melakukan OUT tanpa memuat OSR" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Program size invalid" -msgstr "" +msgstr "Ukuran program tidak valid" #: ports/espressif/common-hal/espulp/ULP.c msgid "Program too long" -msgstr "" +msgstr "Program terlalu lama" + +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "Publisher hanya dapat dibuat dari node induk" #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." @@ -1786,11 +1902,11 @@ msgstr "Pull tidak digunakan saat arah output." #: ports/raspberrypi/common-hal/countio/Counter.c msgid "RISE_AND_FALL not available on this chip" -msgstr "" +msgstr "RISE_AND_FALL tidak tersedia pada chip ini" #: shared-module/displayio/OnDiskBitmap.c msgid "RLE-compressed BMP not supported" -msgstr "" +msgstr "BMP-terkompresi RLE tidak didukung" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" @@ -1800,10 +1916,30 @@ msgstr "Kesalahan DeInit RNG" msgid "RNG Init Error" msgstr "Kesalahan Init RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "ROS gagal diinisialisasi. Apakah agen terhubung?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "Kegagalan pengaturan internal ROS" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "Kegagalan alokator memori ROS" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "Node ROS gagal diinisialisasi" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "Topik ROS gagal diinisialisasi" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1831,11 +1967,11 @@ msgstr "sistem file (filesystem) bersifat Read-only" #: ports/espressif/common-hal/espidf/__init__.c msgid "Received response was invalid" -msgstr "" +msgstr "Respon yang diterima tidak valid" #: supervisor/shared/bluetooth/bluetooth.c msgid "Reconnecting" -msgstr "" +msgstr "Menghubungkan kembali" #: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Refresh too soon" @@ -1843,7 +1979,7 @@ msgstr "Segarkan terlalu cepat" #: shared-bindings/canio/RemoteTransmissionRequest.c msgid "RemoteTransmissionRequests limited to 8 bytes" -msgstr "" +msgstr "RemoteTransmissionRequests dibatasi hingga 8 byte" #: shared-bindings/aesio/aes.c msgid "Requested AES mode is unsupported" @@ -1851,7 +1987,7 @@ msgstr "Mode AES yang diminta tidak didukung" #: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" -msgstr "" +msgstr "Sumber yang diminta tidak ditemukan" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "Right channel unsupported" @@ -1859,56 +1995,56 @@ msgstr "Channel Kanan tidak didukung" #: shared-module/jpegio/JpegDecoder.c msgid "Right format but not supported" -msgstr "" +msgstr "Format benar tapi tidak didukung" #: main.c msgid "Running in safe mode! Not running saved code.\n" msgstr "" "Berjalan di mode aman(safe mode)! Tidak menjalankan kode yang disimpan.\n" -"Berjalan di mode aman(safe mode)! tidak menjalankan kode yang tersimpan.\n" #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" -msgstr "" +msgstr "Kartu SD Format CSD tidak didukung" #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" -msgstr "" +msgstr "Inisialisasi SDCard" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO GetCardInfo Error %d" -msgstr "" +msgstr "Kesalahan GetCardInfo SDIO %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "" +msgid "SDIO Init Error %x" +msgstr "Kesalahan Init SDIO %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "Konfigurasi SPI gagal" #: ports/stm/common-hal/busio/SPI.c msgid "SPI init error" -msgstr "" +msgstr "Kesalahan inisialisasi SPI" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" -msgstr "" +msgstr "Periferal SPI sedang digunakan" #: ports/stm/common-hal/busio/SPI.c msgid "SPI re-init" -msgstr "" +msgstr "Inisialisasi ulang SPI" #: shared-bindings/is31fl3741/FrameBuffer.c msgid "Scale dimensions must divide by 3" -msgstr "" +msgstr "Skala dimensi harus dibagi 3" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Scan already in progress. Stop with stop_scan." -msgstr "" +msgstr "Pemindaian sedang berjalan. Hentikan dengan stop_scan." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -1917,11 +2053,11 @@ msgstr "Serializer sedang digunakan" #: shared-bindings/ssl/SSLContext.c msgid "Server side context cannot have hostname" -msgstr "" +msgstr "Context server tidak mendukung hostname" #: ports/cxd56/common-hal/camera/Camera.c msgid "Size not supported" -msgstr "" +msgstr "Ukuran tidak didukung" #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c @@ -1932,13 +2068,15 @@ msgstr "Potongan dan nilai panjangnya berbeda." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Potongan tidak didukung" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" -msgstr "" +msgstr "SocketPool hanya dapat digunakan dengan wifi.radio" #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" @@ -1946,19 +2084,19 @@ msgstr "Buffer sumber dan tujuan harus memiliki panjang yang sama" #: shared-bindings/paralleldisplaybus/ParallelBus.c msgid "Specify exactly one of data0 or data_pins" -msgstr "" +msgstr "Pilih hanya satu antara data0 atau data_pins" #: supervisor/shared/safe_mode.c msgid "Stack overflow. Increase stack size." -msgstr "" +msgstr "Stack overflow. Tambahkan ukuran stack." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" -msgstr "" +msgstr "Berikan salah satu dari monotonic_time atau epoch_time" #: shared-bindings/gnss/GNSS.c msgid "System entry must be gnss.SatelliteSystem" -msgstr "" +msgstr "Entri sistem harus berupa gnss.SatelliteSystem" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Temperature read timed out" @@ -1966,51 +2104,44 @@ msgstr "Waktu baca suhu habis" #: supervisor/shared/safe_mode.c msgid "The `microcontroller` module was used to boot into safe mode." -msgstr "" +msgstr "Modul `microcontroller` digunakan untuk boot ke mode aman." #: py/obj.c msgid "The above exception was the direct cause of the following exception:" msgstr "" +"Pengecualian di atas adalah penyebab langsung dari pengecualian berikut:" #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Sampel bits_per_sampel tidak cocok dengan mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Jumlah saluran sampel tidak cocok dengan mixer" +msgstr "Panjang rgb_pins harus 6, 12, 18, 24, atau 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Tingkat sampel dari sampel tidak cocok dengan mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "signedness dari sampel tidak cocok dengan mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "Sampel punya %q yang tidak cocok" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." -msgstr "" +msgstr "Kesalahan fatal pada firmware pihak ketiga." #: shared-module/imagecapture/ParallelImageCapture.c msgid "This microcontroller does not support continuous capture." -msgstr "" +msgstr "Mikrokontroler ini tidak mendukung penangkapan berkelanjutan." #: shared-module/paralleldisplaybus/ParallelBus.c msgid "" "This microcontroller only supports data0=, not data_pins=, because it " "requires contiguous pins." msgstr "" +"Mikrokontroler ini hanya mendukung data0=, bukan data_pins=, karena " +"membutuhkan pin yang berurutan." #: shared-bindings/displayio/TileGrid.c msgid "Tile height must exactly divide bitmap height" msgstr "Tinggi tile harus persis membagi tinggi bitmap" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Indeks ubin di luar batas" @@ -2018,31 +2149,38 @@ msgstr "Indeks ubin di luar batas" msgid "Tile width must exactly divide bitmap width" msgstr "Lebar ubin harus persis membagi lebar bitmap" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper hanya dapat diikat ke TileGrid sekali" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." -msgstr "" +msgstr "Waktu sudah berlalu." #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c #, c-format msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +"Waktu tunggu terlalu lama: Panjang maksimum waktu tunggu adalah %d detik" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" -msgstr "" +msgstr "Sampel memiliki terlalu banyak saluran" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample." -msgstr "Terlalu banyak channel dalam sampel" +msgstr "Terlalu banyak channel dalam sampel." #: ports/espressif/common-hal/_bleio/Characteristic.c msgid "Too many descriptors" -msgstr "" +msgstr "Terlalu banyak deskriptor" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" msgstr "" +"Terlalu banyak jalur tampilan; mungkin kamu lupa untuk panggil displayio." +"release_displays()?" #: shared-module/displayio/__init__.c msgid "Too many displays" @@ -2051,12 +2189,12 @@ msgstr "Terlalu banyak tampilan" #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nordic/common-hal/_bleio/PacketBuffer.c msgid "Total data to write is larger than %q" -msgstr "" +msgstr "Total data yang akan ditulis lebih besar dari %q" #: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c #: ports/stm/common-hal/alarm/touch/TouchAlarm.c msgid "Touch alarms not available" -msgstr "" +msgstr "Alarm sentuh tidak tersedia" #: py/obj.c msgid "Traceback (most recent call last):\n" @@ -2064,44 +2202,44 @@ msgstr "Traceback (bagian terakhir dari panggilan terkini):\n" #: ports/stm/common-hal/busio/UART.c msgid "UART de-init" -msgstr "" +msgstr "De-inisialisasi UART" #: ports/cxd56/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c #: ports/stm/common-hal/busio/UART.c msgid "UART init" -msgstr "" +msgstr "Inisialisasi UART" #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" -msgstr "" +msgstr "Periferal UART sedang digunakan" #: ports/stm/common-hal/busio/UART.c msgid "UART re-init" -msgstr "" +msgstr "Inisialisasi ulang UART" #: ports/stm/common-hal/busio/UART.c msgid "UART write" -msgstr "" +msgstr "Penulisan UART" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" -msgstr "" +msgstr "USB sibuk" #: supervisor/shared/safe_mode.c msgid "USB devices need more endpoints than are available." -msgstr "" +msgstr "Perangkat USB butuh lebih banyak endpoint daripada yang tersedia." #: supervisor/shared/safe_mode.c msgid "USB devices specify too many interface names." -msgstr "" +msgstr "Perangkat USB menggunakan terlalu banyak nama antarmuka." #: shared-module/usb_hid/Device.c msgid "USB error" -msgstr "" +msgstr "Kesalahan USB" #: shared-bindings/_bleio/UUID.c msgid "UUID integer value must be 0-0xffff" @@ -2117,7 +2255,7 @@ msgstr "Nilai UUID bukan str, int atau byte buffer" #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to access unaligned IO register" -msgstr "" +msgstr "Tidak dapat mengakses register IO yang tidak teratur" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -2128,11 +2266,11 @@ msgstr "Tidak dapat mengalokasikan buffer untuk signed conversion" #: supervisor/shared/safe_mode.c msgid "Unable to allocate to the heap." -msgstr "" +msgstr "Tidak dapat mengalokasikan ke heap." #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" -msgstr "" +msgstr "Tidak dapat membuat kunci" #: shared-module/i2cdisplaybus/I2CDisplayBus.c #: shared-module/is31fl3741/IS31FL3741.c @@ -2148,10 +2286,14 @@ msgstr "Tidak dapat memulai parser" msgid "Unable to read color palette data" msgstr "Tidak dapat membaca data palet warna" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "Tidak dapat mengirim Pesan CAN: semua buffer pesan Tx sibuk" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" -msgstr "" +msgstr "Tidak dapat memulai kueri mDNS" #: shared-bindings/nvm/ByteArray.c msgid "Unable to write to nvm." @@ -2159,11 +2301,11 @@ msgstr "Tidak dapat menulis ke nvm." #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to write to read-only memory" -msgstr "" +msgstr "Tidak dapat menulis ke memori hanya-baca" #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." -msgstr "" +msgstr "Tidak dapat menulis ke sleep_memory." #: ports/nordic/common-hal/_bleio/UUID.c msgid "Unexpected nrfx uuid type" @@ -2172,23 +2314,23 @@ msgstr "Tipe urf nrfx tak sesuai" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown BLE error at %s:%d: %d" -msgstr "" +msgstr "Kesalahan BLE tidak diketahui di %s:%d: %d" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown BLE error: %d" -msgstr "" +msgstr "Kesalahan BLE tidak diketahui: %d" #: ports/espressif/common-hal/max3421e/Max3421E.c #: ports/raspberrypi/common-hal/wifi/__init__.c #, c-format msgid "Unknown error code %d" -msgstr "" +msgstr "Kode kesalahan tidak diketahui %d" #: shared-bindings/wifi/Radio.c #, c-format msgid "Unknown failure %d" -msgstr "" +msgstr "Kegagalan tidak diketahui %d" #: ports/nordic/common-hal/_bleio/__init__.c #, c-format @@ -2208,23 +2350,23 @@ msgstr "Kesalahan keamanan tidak dikenal: 0x%04x" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error at %s:%d: %d" -msgstr "" +msgstr "Kesalahan firmware sistem tidak dikenal di %s:%d: %d" #: ports/nordic/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error: %04x" -msgstr "" +msgstr "Kesalahan firmware sistem tidak diketahui: %04x" #: ports/espressif/common-hal/_bleio/__init__.c #, c-format msgid "Unknown system firmware error: %d" -msgstr "" +msgstr "Kesalahan firmware sistem tidak diketahui: %d" #: shared-bindings/adafruit_pixelbuf/PixelBuf.c #: shared-module/_pixelmap/PixelMap.c #, c-format msgid "Unmatched number of items on RHS (expected %d, got %d)." -msgstr "Jumlah item pada RHS tidak cocok (diharapkan %d, didapatkan %d)." +msgstr "Jumlah item pada RHS tidak cocok (diharapkan %d, didapatkan %d)." #: ports/nordic/common-hal/_bleio/__init__.c msgid "" @@ -2236,38 +2378,33 @@ msgstr "" #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" -msgstr "" +msgstr "Colorspace tidak didukung" #: shared-module/displayio/bus_core.c msgid "Unsupported display bus type" msgstr "Tipe bus tampilan tidak didukung" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Format tidak didukung" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" -msgstr "" +msgstr "Algoritma hash tidak didukung" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" -msgstr "" +msgstr "Jenis soket tidak didukung" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Pembaruan gagal" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Panjang nilai != Panjang tetap yang dibutuhkan" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2275,7 +2412,7 @@ msgstr "Panjang nilai > max_length" #: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" -msgstr "" +msgstr "Versi tidak valid" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Voltage read timed out" @@ -2288,6 +2425,7 @@ msgstr "PERINGATAN: Nama file kode anda mempunyai dua ekstensi\n" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "WatchDogTimer cannot be deinitialized once mode is set to RESET" msgstr "" +"WatchDogTimer tidak dapat dideinisialisasi setelah mode diatur ke RESET" #: py/builtinhelp.c #, c-format @@ -2298,18 +2436,25 @@ msgid "" "\n" "To list built-in modules type `help(\"modules\")`.\n" msgstr "" +"Selamat datang di Adafruit CircuitPython %s!\n" +"\n" +"Kunjungi circuitpython.org untuk informasi lebih lanjut.\n" +"\n" +"Untuk membuat daftar modul bawaan, ketik `help(\"modules\")`.\n" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi tidak diaktifkan" #: main.c msgid "Woken up by alarm.\n" -msgstr "" +msgstr "Dibangunkan oleh alarm.\n" #: ports/espressif/common-hal/_bleio/PacketBuffer.c #: ports/nordic/common-hal/_bleio/PacketBuffer.c @@ -2321,63 +2466,65 @@ msgstr "Menulis tidak didukung pada Karakteristik" #: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h #: ports/atmel-samd/boards/meowmeow/mpconfigboard.h msgid "You pressed both buttons at start up." -msgstr "" +msgstr "Anda menekan kedua tombol saat memulai." #: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." -msgstr "" +msgstr "Anda menekan tombol A saat memulai." #: ports/espressif/boards/m5stack_m5paper/mpconfigboard.h msgid "You pressed button DOWN at start up." -msgstr "" +msgstr "Anda menekan tombol DOWN saat memulai." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" -msgstr "" +msgstr "Anda menekan tombol BOOT saat memulai" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." -msgstr "" +msgstr "Anda menekan tombol BOOT saat memulai." #: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h msgid "You pressed the GPIO0 button at start up." -msgstr "" +msgstr "Anda menekan tombol GPIO0 saat memulai." #: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h msgid "You pressed the Rec button at start up." -msgstr "" +msgstr "Anda menekan tombol Rec saat memulai." #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "" +msgstr "Anda menekan tombol SW38 saat memulai." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h #: ports/espressif/boards/vidi_x/mpconfigboard.h msgid "You pressed the VOLUME button at start up." -msgstr "" +msgstr "Anda menekan tombol VOLUME saat memulai." #: ports/espressif/boards/m5stack_atom_echo/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_lite/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_u/mpconfigboard.h msgid "You pressed the central button at start up." -msgstr "" +msgstr "Anda menekan tombol tengah saat memulai." #: ports/nordic/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "" +msgstr "Anda menekan tombol kiri saat memulai." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "" +msgstr "Anda menekan tombol reset saat memulai." #: supervisor/shared/micropython.c msgid "[truncated due to length]" -msgstr "" +msgstr "[terpotong karena kepanjangan]" #: py/objtype.c msgid "__init__() should return None" @@ -2386,7 +2533,7 @@ msgstr "__init __() harus mengembalikan None" #: py/objtype.c #, c-format msgid "__init__() should return None, not '%s'" -msgstr "" +msgstr "__init__() harus mengembalikan None, bukan '%s'" #: py/objobject.c msgid "__new__ arg must be a user-type" @@ -2400,13 +2547,17 @@ msgstr "sebuah objek menyerupai byte (bytes-like) dibutuhkan" msgid "addresses is empty" msgstr "alamatnya kosong" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "sudah diputar" + #: py/compile.c msgid "annotation must be an identifier" -msgstr "" +msgstr "anotasi harus merupakan pengidentifikasi" #: extmod/ulab/code/numpy/create.c msgid "arange: cannot compute length" -msgstr "" +msgstr "arange: tidak dapat menghitung panjang" #: py/modbuiltins.c msgid "arg is an empty sequence" @@ -2414,7 +2565,7 @@ msgstr "arg berisi urutan kosong" #: py/objobject.c msgid "arg must be user-type" -msgstr "" +msgstr "arg harus bertipe user-type" #: extmod/ulab/code/numpy/numerical.c msgid "argsort argument must be an ndarray" @@ -2422,11 +2573,15 @@ msgstr "Argumen argsort harus berupa ndarray" #: extmod/ulab/code/numpy/numerical.c msgid "argsort is not implemented for flattened arrays" -msgstr "" +msgstr "argsort tidak diimplementasikan untuk array yang diratakan" + +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "argumen harus None, integer atau tuple integer" #: py/compile.c msgid "argument name reused" -msgstr "" +msgstr "nama argumen digunakan kembali" #: py/argcheck.c shared-bindings/_stage/__init__.c #: shared-bindings/digitalio/DigitalInOut.c @@ -2439,15 +2594,15 @@ msgstr "argumen harus berupa ndarrays" #: extmod/ulab/code/ndarray.c msgid "array and index length must be equal" -msgstr "" +msgstr "panjang array dan indeks harus sama" #: extmod/ulab/code/numpy/io/io.c msgid "array has too many dimensions" -msgstr "" +msgstr "array memiliki terlalu banyak dimensi" #: extmod/ulab/code/ndarray.c msgid "array is too big" -msgstr "" +msgstr "array terlalu besar" #: py/objarray.c shared-bindings/alarm/SleepMemory.c #: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c @@ -2456,15 +2611,15 @@ msgstr "diperlukan array/byte di sisi kanan" #: py/asmxtensa.c msgid "asm overflow" -msgstr "" +msgstr "asm overflow" #: py/compile.c msgid "async for/with outside async function" -msgstr "" +msgstr "async for/with di luar fungsi async" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get (arg)min/(arg)max of empty sequence" -msgstr "" +msgstr "percobaan untuk mendapatkan (arg)min/(arg)max dari urutan kosong" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get argmin/argmax of an empty sequence" @@ -2472,23 +2627,27 @@ msgstr "berusaha mendapatkan argmin/argmax dari urutan kosong" #: py/objstr.c msgid "attributes not supported" -msgstr "" +msgstr "atribut tidak didukung" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "format audio tidak didukung" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" -msgstr "" +msgstr "axis berada di luar batas" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c msgid "axis must be None, or an integer" -msgstr "" +msgstr "axis harus None, atau integer" #: extmod/ulab/code/numpy/numerical.c msgid "axis too long" -msgstr "" +msgstr "axis terlalu panjang" #: shared-bindings/bitmaptools/__init__.c msgid "background value out of range of target" -msgstr "" +msgstr "nilai latar belakang di luar jangkauan target" #: py/builtinevex.c msgid "bad compile mode" @@ -2500,7 +2659,7 @@ msgstr "specifier salah konversi" #: py/objstr.c msgid "bad format string" -msgstr "" +msgstr "string format salah" #: py/binary.c py/objarray.c msgid "bad typecode" @@ -2508,35 +2667,48 @@ msgstr "typecode buruk" #: py/emitnative.c msgid "binary op %q not implemented" -msgstr "" +msgstr "operasi biner %q tidak diimplementasikan" + +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth harus 8, 16, 24, atau 32." #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" -msgstr "" +msgstr "ukuran dan kedalaman bitmap harus cocok" #: shared-bindings/bitmaptools/__init__.c msgid "bitmap sizes must match" -msgstr "" +msgstr "ukuran bitmap harus cocok" #: extmod/modrandom.c msgid "bits must be 32 or less" -msgstr "" +msgstr "bit harus 32 atau kurang" + +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample harus 16" +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" -msgstr "" +msgstr "bits_per_sample harus 8 atau 16" #: py/emitinlinethumb.c msgid "branch not in range" -msgstr "" +msgstr "branch tidak dalam jangkauan" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer is smaller than requested size" -msgstr "" +msgstr "buffer lebih kecil dari ukuran yang diminta" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer size must be a multiple of element size" -msgstr "" +msgstr "ukuran buffer harus kelipatan dari ukuran elemen" #: shared-module/struct/__init__.c msgid "buffer size must match format" @@ -2544,27 +2716,27 @@ msgstr "ukuran buffer harus sesuai dengan format" #: shared-bindings/bitbangio/SPI.c shared-bindings/busio/SPI.c msgid "buffer slices must be of equal length" -msgstr "" +msgstr "potongan buffer harus memiliki panjang yang sama" #: py/modstruct.c shared-module/struct/__init__.c msgid "buffer too small" -msgstr "" +msgstr "buffer terlalu kecil" #: shared-bindings/socketpool/Socket.c shared-bindings/ssl/SSLSocket.c msgid "buffer too small for requested bytes" -msgstr "" +msgstr "buffer terlalu kecil untuk byte yang diminta" #: py/emitbc.c msgid "bytecode overflow" -msgstr "" +msgstr "bytecode overflow" #: py/objarray.c msgid "bytes length not a multiple of item size" -msgstr "" +msgstr "panjang bytes bukan kelipatan dari ukuran item" #: py/objstr.c msgid "bytes value out of range" -msgstr "" +msgstr "nilai bytes di luar jangkauan" #: ports/atmel-samd/bindings/samd/Clock.c msgid "calibration is out of range" @@ -2577,7 +2749,7 @@ msgstr "kalibrasi adalah read only" #: shared-module/vectorio/Circle.c shared-module/vectorio/Polygon.c #: shared-module/vectorio/Rectangle.c msgid "can only have one parent" -msgstr "" +msgstr "hanya dapat memiliki satu induk" #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" @@ -2585,15 +2757,15 @@ msgstr "hanya mampu memiliki hingga 4 parameter untuk Thumb assembly" #: py/emitinlinextensa.c msgid "can only have up to 4 parameters to Xtensa assembly" -msgstr "" +msgstr "hanya dapat memiliki hingga 4 parameter untuk assembly Xtensa" #: extmod/ulab/code/ndarray.c msgid "can only specify one unknown dimension" -msgstr "" +msgstr "hanya dapat menentukan satu dimensi yang tidak diketahui" #: py/objtype.c msgid "can't add special method to already-subclassed class" -msgstr "" +msgstr "tidak dapat menambahkan metode khusus ke kelas yang sudah di-subclass" #: py/compile.c msgid "can't assign to expression" @@ -2601,50 +2773,50 @@ msgstr "tidak dapat menetapkan ke ekspresi" #: extmod/modasyncio.c msgid "can't cancel self" -msgstr "" +msgstr "tidak dapat membatalkan diri sendiri" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" -msgstr "" +msgstr "tidak dapat mengonversi %q ke %q" #: py/obj.c #, c-format msgid "can't convert %s to complex" -msgstr "" +msgstr "tidak dapat mengonversi %s ke complex" #: py/obj.c #, c-format msgid "can't convert %s to float" -msgstr "" +msgstr "tidak dapat mengonversi %s ke float" #: py/objint.c py/runtime.c #, c-format msgid "can't convert %s to int" -msgstr "" +msgstr "tidak dapat mengonversi %s ke int" #: py/objstr.c msgid "can't convert '%q' object to %q implicitly" -msgstr "" +msgstr "tidak dapat mengonversi objek '%q' ke %q secara implisit" #: extmod/ulab/code/numpy/vector.c msgid "can't convert complex to float" -msgstr "" +msgstr "tidak dapat mengonversi complex ke float" #: py/obj.c msgid "can't convert to complex" -msgstr "" +msgstr "tidak dapat mengonversi ke complex" #: py/obj.c msgid "can't convert to float" -msgstr "" +msgstr "tidak dapat mengonversi ke float" #: py/runtime.c msgid "can't convert to int" -msgstr "" +msgstr "tidak dapat mengonversi ke int" #: py/objstr.c msgid "can't convert to str implicitly" -msgstr "" +msgstr "tidak dapat mengonversi ke str secara implisit" #: py/compile.c msgid "can't declare nonlocal in outer code" @@ -2656,93 +2828,95 @@ msgstr "tidak bisa menghapus ekspresi" #: py/emitnative.c msgid "can't do binary op between '%q' and '%q'" -msgstr "" +msgstr "tidak dapat melakukan operasi biner antara '%q' dan '%q'" + +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "tidak dapat melakukan operasi unary dari '%q'" #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" -msgstr "" +msgstr "tidak dapat mengonversi '%q' ke 'bool' secara implisit" #: py/runtime.c msgid "can't import name %q" -msgstr "" +msgstr "tidak dapat mengimpor nama %q" #: py/emitnative.c msgid "can't load from '%q'" -msgstr "" +msgstr "tidak dapat memuat dari '%q'" #: py/emitnative.c msgid "can't load with '%q' index" -msgstr "" +msgstr "tidak dapat memuat dengan indeks '%q'" #: py/builtinimport.c msgid "can't perform relative import" -msgstr "" +msgstr "tidak dapat melakukan impor relatif" #: py/objgenerator.c msgid "can't send non-None value to a just-started generator" -msgstr "" +msgstr "tidak dapat mengirim nilai non-None ke generator yang baru dimulai" #: shared-module/sdcardio/SDCard.c msgid "can't set 512 block size" -msgstr "" +msgstr "tidak dapat mengatur ukuran blok 512" #: py/objexcept.c py/objnamedtuple.c msgid "can't set attribute" -msgstr "" +msgstr "tidak dapat mengatur atribut" #: py/runtime.c msgid "can't set attribute '%q'" -msgstr "" +msgstr "tidak dapat mengatur atribut '%q'" #: py/emitnative.c msgid "can't store '%q'" -msgstr "" +msgstr "tidak dapat menyimpan '%q'" #: py/emitnative.c msgid "can't store to '%q'" -msgstr "" +msgstr "tidak dapat menyimpan ke '%q'" #: py/emitnative.c msgid "can't store with '%q' index" -msgstr "" +msgstr "tidak dapat menyimpan dengan indeks '%q'" #: py/objstr.c msgid "" "can't switch from automatic field numbering to manual field specification" msgstr "" +"tidak dapat beralih dari penomoran field otomatis ke spesifikasi field manual" #: py/objstr.c msgid "" "can't switch from manual field specification to automatic field numbering" msgstr "" +"tidak dapat beralih dari spesifikasi field manual ke penomoran field otomatis" #: py/objcomplex.c msgid "can't truncate-divide a complex number" -msgstr "" - -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" +msgstr "tidak dapat truncate-divide bilangan complex" #: extmod/modasyncio.c msgid "can't wait" -msgstr "" +msgstr "tidak dapat menunggu" #: extmod/ulab/code/ndarray.c msgid "cannot assign new shape" -msgstr "" +msgstr "tidak dapat menetapkan bentuk baru" #: extmod/ulab/code/ndarray_operators.c msgid "cannot cast output with casting rule" -msgstr "" +msgstr "tidak dapat melakukan cast output dengan aturan casting" #: extmod/ulab/code/ndarray.c msgid "cannot convert complex to dtype" -msgstr "" +msgstr "tidak dapat mengonversi complex ke dtype" #: extmod/ulab/code/ndarray.c msgid "cannot convert complex type" -msgstr "" +msgstr "tidak dapat mengonversi tipe complex" #: py/objtype.c msgid "cannot create '%q' instances" @@ -2750,71 +2924,71 @@ msgstr "" #: py/objtype.c msgid "cannot create instance" -msgstr "" +msgstr "tidak dapat membuat instance" #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" -msgstr "" +msgstr "tidak dapat menghapus elemen array" #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" -msgstr "" +msgstr "tidak dapat membentuk ulang array" #: py/emitnative.c msgid "casting" -msgstr "" +msgstr "casting" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "channel re-init" -msgstr "" +msgstr "inisialisasi ulang channel" #: shared-bindings/_stage/Text.c msgid "chars buffer too small" -msgstr "" +msgstr "buffer chars terlalu kecil" #: py/modbuiltins.c msgid "chr() arg not in range(0x110000)" -msgstr "" +msgstr "argumen chr() tidak dalam rentang(0x110000)" #: py/modbuiltins.c msgid "chr() arg not in range(256)" -msgstr "" +msgstr "argumen chr() tidak dalam rentang(256)" #: shared-bindings/bitmaptools/__init__.c msgid "clip point must be (x,y) tuple" -msgstr "" +msgstr "clip point harus berupa tuple (x,y)" #: shared-bindings/msgpack/ExtType.c msgid "code outside range 0~127" -msgstr "" +msgstr "kode di luar rentang 0~127" #: shared-bindings/displayio/Palette.c msgid "color buffer must be 3 bytes (RGB) or 4 bytes (RGB + pad byte)" -msgstr "" +msgstr "buffer warna harus 3 byte (RGB) atau 4 byte (RGB + pad byte)" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a buffer, tuple, list, or int" -msgstr "" +msgstr "buffer warna harus berupa buffer, tuple, list, atau int" #: shared-bindings/displayio/Palette.c msgid "color buffer must be a bytearray or array of type 'b' or 'B'" -msgstr "" +msgstr "buffer warna harus berupa bytearray atau array bertipe 'b' atau 'B'" #: shared-bindings/displayio/Palette.c msgid "color must be between 0x000000 and 0xffffff" -msgstr "" +msgstr "warna harus antara 0x000000 dan 0xffffff" #: py/emitnative.c msgid "comparison of int and uint" -msgstr "" +msgstr "perbandingan int dan uint" #: py/objcomplex.c msgid "complex divide by zero" -msgstr "" +msgstr "pembagian complex dengan nol" #: py/objfloat.c py/parsenum.c msgid "complex values not supported" -msgstr "" +msgstr "nilai complex tidak didukung" #: extmod/modzlib.c msgid "compression header" @@ -2822,56 +2996,56 @@ msgstr "kompresi header" #: py/emitnative.c msgid "conversion to object" -msgstr "" +msgstr "konversi ke objek" #: extmod/ulab/code/numpy/filter.c msgid "convolve arguments must be linear arrays" -msgstr "" +msgstr "argumen convolve harus berupa array linear" #: extmod/ulab/code/numpy/filter.c msgid "convolve arguments must be ndarrays" -msgstr "" +msgstr "argumen convolve harus berupa ndarray" #: extmod/ulab/code/numpy/filter.c msgid "convolve arguments must not be empty" -msgstr "" +msgstr "argumen convolve tidak boleh kosong" #: extmod/ulab/code/numpy/io/io.c msgid "corrupted file" -msgstr "" +msgstr "file rusak" #: extmod/ulab/code/numpy/poly.c msgid "could not invert Vandermonde matrix" -msgstr "" +msgstr "tidak dapat membalik matriks Vandermonde" #: shared-module/sdcardio/SDCard.c msgid "couldn't determine SD card version" -msgstr "" +msgstr "tidak dapat menentukan versi kartu SD" #: extmod/ulab/code/numpy/numerical.c msgid "cross is defined for 1D arrays of length 3" -msgstr "" +msgstr "cross didefinisikan untuk array 1D dengan panjang 3" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" -msgstr "" +msgstr "data harus dapat diiterasi" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be of equal length" -msgstr "" +msgstr "data harus memiliki panjang yang sama" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "data pin #%d in use" -msgstr "" +msgstr "pin data #%d sedang digunakan" #: extmod/ulab/code/ndarray.c msgid "data type not understood" -msgstr "" +msgstr "tipe data tidak dipahami" #: py/parsenum.c msgid "decimal numbers not supported" -msgstr "" +msgstr "angka desimal tidak didukung" #: py/compile.c msgid "default 'except' must be last" @@ -2879,60 +3053,62 @@ msgstr "'except' standar harus terakhir" #: shared-bindings/msgpack/__init__.c msgid "default is not a function" -msgstr "" +msgstr "default bukan fungsi" #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" msgstr "" +"buffer tujuan harus berupa bytearray atau array bertipe 'B' untuk bit_depth " +"= 8" #: shared-bindings/audiobusio/PDMIn.c msgid "destination buffer must be an array of type 'H' for bit_depth = 16" -msgstr "" +msgstr "buffer tujuan harus berupa array bertipe 'H' untuk bit_depth = 16" #: py/objdict.c msgid "dict update sequence has wrong length" -msgstr "" +msgstr "urutan pembaruan dict memiliki panjang yang salah" #: extmod/ulab/code/numpy/numerical.c msgid "diff argument must be an ndarray" -msgstr "" +msgstr "argumen diff harus berupa ndarray" #: extmod/ulab/code/numpy/numerical.c msgid "differentiation order out of range" -msgstr "" +msgstr "urutan diferensiasi di luar jangkauan" #: extmod/ulab/code/numpy/transform.c msgid "dimensions do not match" -msgstr "" +msgstr "dimensi tidak cocok" #: py/emitnative.c msgid "div/mod not implemented for uint" -msgstr "" +msgstr "div/mod tidak diimplementasikan untuk uint" #: extmod/ulab/code/numpy/create.c msgid "divide by zero" -msgstr "" +msgstr "pembagian dengan nol" #: py/runtime.c msgid "division by zero" -msgstr "" +msgstr "pembagian dengan nol" #: extmod/ulab/code/numpy/vector.c msgid "dtype must be float, or complex" -msgstr "" +msgstr "dtype harus float, atau complex" #: extmod/ulab/code/ndarray_operators.c msgid "dtype of int32 is not supported" -msgstr "" +msgstr "dtype int32 tidak didukung" #: py/objdeque.c msgid "empty" -msgstr "" +msgstr "kosong" #: extmod/ulab/code/numpy/io/io.c msgid "empty file" -msgstr "" +msgstr "file kosong" #: extmod/modasyncio.c extmod/modheapq.c msgid "empty heap" @@ -2940,19 +3116,19 @@ msgstr "heap kosong" #: py/objstr.c msgid "empty separator" -msgstr "" +msgstr "pemisah kosong" #: shared-bindings/random/__init__.c msgid "empty sequence" -msgstr "" +msgstr "urutan kosong" #: py/objstr.c msgid "end of format while looking for conversion specifier" -msgstr "" +msgstr "akhir format saat mencari spesifier konversi" #: shared-bindings/alarm/time/TimeAlarm.c msgid "epoch_time not supported on this board" -msgstr "" +msgstr "epoch_time tidak didukung pada board ini" #: ports/nordic/common-hal/busio/UART.c #, c-format @@ -2961,19 +3137,19 @@ msgstr "error = 0x%08lX" #: py/runtime.c msgid "exceptions must derive from BaseException" -msgstr "" +msgstr "exception harus diturunkan dari BaseException" #: py/objstr.c msgid "expected ':' after format specifier" -msgstr "" +msgstr "mengharapkan ':' setelah spesifier format" #: py/obj.c msgid "expected tuple/list" -msgstr "" +msgstr "mengharapkan tuple/list" #: py/modthread.c msgid "expecting a dict for keyword args" -msgstr "" +msgstr "mengharapkan dict untuk argumen keyword" #: py/compile.c msgid "expecting an assembler instruction" @@ -2989,7 +3165,7 @@ msgstr "key:value diharapkan untuk dict" #: shared-bindings/msgpack/__init__.c msgid "ext_hook is not a function" -msgstr "" +msgstr "ext_hook bukan fungsi" #: py/argcheck.c msgid "extra keyword arguments given" @@ -3003,11 +3179,11 @@ msgstr "argumen posisi ekstra telah diberikan" #: shared-bindings/displayio/OnDiskBitmap.c shared-bindings/gifio/OnDiskGif.c #: shared-bindings/synthio/__init__.c shared-module/gifio/GifWriter.c msgid "file must be a file opened in byte mode" -msgstr "" +msgstr "file harus berupa file yang dibuka dalam mode byte" #: shared-bindings/traceback/__init__.c msgid "file write is not available" -msgstr "" +msgstr "penulisan file tidak tersedia" #: shared-bindings/storage/__init__.c msgid "filesystem must provide mount method" @@ -3015,63 +3191,63 @@ msgstr "" #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" -msgstr "" +msgstr "argumen pertama harus dapat dipanggil" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "first argument must be a function" -msgstr "" +msgstr "argumen pertama harus berupa fungsi" #: extmod/ulab/code/numpy/create.c msgid "first argument must be a tuple of ndarrays" -msgstr "" +msgstr "argumen pertama harus berupa tuple ndarray" #: extmod/ulab/code/numpy/transform.c extmod/ulab/code/numpy/vector.c msgid "first argument must be an ndarray" -msgstr "" +msgstr "argumen pertama harus berupa ndarray" #: py/objtype.c msgid "first argument to super() must be type" -msgstr "" +msgstr "argumen pertama untuk super() harus bertipe type" #: extmod/ulab/code/scipy/linalg/linalg.c msgid "first two arguments must be ndarrays" -msgstr "" +msgstr "dua argumen pertama harus berupa ndarray" #: extmod/ulab/code/ndarray.c msgid "flattening order must be either 'C', or 'F'" -msgstr "" +msgstr "urutan perataan harus 'C', atau 'F'" #: extmod/ulab/code/numpy/numerical.c msgid "flip argument must be an ndarray" -msgstr "" +msgstr "argumen flip harus berupa ndarray" #: py/objint.c msgid "float too big" -msgstr "" +msgstr "float terlalu besar" #: py/nativeglue.c msgid "float unsupported" -msgstr "" +msgstr "float tidak didukung" #: shared-bindings/_stage/Text.c msgid "font must be 2048 bytes long" -msgstr "" +msgstr "font harus sepanjang 2048 byte" #: extmod/moddeflate.c msgid "format" -msgstr "" +msgstr "format" #: py/objstr.c -msgid "format requires a dict" -msgstr "" +msgid "format needs a dict" +msgstr "format memerlukan dict" #: py/objdeque.c msgid "full" -msgstr "" +msgstr "penuh" #: py/argcheck.c msgid "function doesn't take keyword arguments" -msgstr "" +msgstr "fungsi tidak menerima argumen keyword" #: py/argcheck.c #, c-format @@ -3084,15 +3260,15 @@ msgstr "fungsi mendapatkan nilai ganda untuk argumen '%q'" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "function has the same sign at the ends of interval" -msgstr "" +msgstr "fungsi memiliki tanda yang sama pada ujung interval" #: extmod/ulab/code/ndarray.c msgid "function is defined for ndarrays only" -msgstr "" +msgstr "fungsi didefinisikan hanya untuk ndarray" #: extmod/ulab/code/numpy/carray/carray.c msgid "function is implemented for ndarrays only" -msgstr "" +msgstr "fungsi diimplementasikan hanya untuk ndarray" #: py/argcheck.c #, c-format @@ -3112,30 +3288,31 @@ msgstr "fungsi kehilangan argumen keyword '%q' yang dibutuhkan" msgid "function missing required positional argument #%d" msgstr "fungsi kehilangan argumen posisi #%d yang dibutuhkan" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "fungsi mengambil posisi argumen %d tapi %d yang diberikan" #: py/objgenerator.c msgid "generator already executing" -msgstr "" +msgstr "generator sudah berjalan" #: py/objgenerator.c msgid "generator ignored GeneratorExit" -msgstr "" +msgstr "generator mengabaikan GeneratorExit" #: py/objgenerator.c py/runtime.c msgid "generator raised StopIteration" -msgstr "" +msgstr "generator memunculkan StopIteration" #: shared-bindings/_stage/Layer.c msgid "graphic must be 2048 bytes long" -msgstr "" +msgstr "grafik harus sepanjang 2048 byte" #: extmod/modhashlib.c msgid "hash is final" -msgstr "" +msgstr "hash bersifat final" #: extmod/modheapq.c msgid "heap must be a list" @@ -3151,23 +3328,23 @@ msgstr "identifier didefinisi ulang sebagai nonlocal" #: py/compile.c msgid "import * not at module level" -msgstr "" +msgstr "import * tidak pada tingkat modul" #: py/persistentcode.c msgid "incompatible .mpy arch" -msgstr "" +msgstr "arsitektur .mpy tidak kompatibel" #: py/persistentcode.c msgid "incompatible .mpy file" -msgstr "" +msgstr "file .mpy tidak kompatibel" #: py/objstr.c msgid "incomplete format" -msgstr "" +msgstr "format tidak lengkap" #: py/objstr.c msgid "incomplete format key" -msgstr "" +msgstr "kunci format tidak lengkap" #: extmod/modbinascii.c msgid "incorrect padding" @@ -3175,11 +3352,11 @@ msgstr "lapisan (padding) tidak benar" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/transform.c msgid "index is out of bounds" -msgstr "" +msgstr "indeks berada di luar batas" #: shared-bindings/_pixelmap/PixelMap.c msgid "index must be tuple or int" -msgstr "" +msgstr "indeks harus berupa tuple atau int" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c #: ports/espressif/common-hal/pulseio/PulseIn.c @@ -3189,23 +3366,19 @@ msgstr "index keluar dari jangkauan" #: py/obj.c msgid "indices must be integers" -msgstr "" +msgstr "indeks harus berupa integer" #: extmod/ulab/code/ndarray.c msgid "indices must be integers, slices, or Boolean lists" -msgstr "" - -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" +msgstr "indeks harus berupa integer, slice, atau list Boolean" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" -msgstr "" +msgstr "nilai awal harus dapat diiterasi" #: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c msgid "initial_value length is wrong" -msgstr "" +msgstr "panjang initial_value salah" #: py/compile.c msgid "inline assembler must be a function" @@ -3213,98 +3386,98 @@ msgstr "inline assembler harus sebuah fungsi" #: extmod/ulab/code/numpy/vector.c msgid "input and output dimensions differ" -msgstr "" +msgstr "dimensi input dan output berbeda" #: extmod/ulab/code/numpy/vector.c msgid "input and output shapes differ" -msgstr "" +msgstr "bentuk input dan output berbeda" #: extmod/ulab/code/numpy/create.c msgid "input argument must be an integer, a tuple, or a list" -msgstr "" +msgstr "argumen input harus berupa integer, tuple, atau list" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "input array length must be power of 2" -msgstr "" +msgstr "panjang array input harus pangkat 2" #: extmod/ulab/code/numpy/create.c msgid "input arrays are not compatible" -msgstr "" +msgstr "array input tidak kompatibel" #: extmod/ulab/code/numpy/poly.c msgid "input data must be an iterable" -msgstr "" +msgstr "data input harus dapat diiterasi" #: extmod/ulab/code/numpy/vector.c msgid "input dtype must be float or complex" -msgstr "" +msgstr "dtype input harus float atau complex" #: extmod/ulab/code/numpy/poly.c msgid "input is not iterable" -msgstr "" +msgstr "input tidak dapat diiterasi" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "input matrix is asymmetric" -msgstr "" +msgstr "matriks input asimetris" #: extmod/ulab/code/numpy/linalg/linalg.c #: extmod/ulab/code/scipy/linalg/linalg.c msgid "input matrix is singular" -msgstr "" +msgstr "matriks input singular" #: extmod/ulab/code/numpy/create.c msgid "input must be 1- or 2-d" -msgstr "" +msgstr "input harus 1- atau 2-d" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be a 1D ndarray" -msgstr "" +msgstr "input harus berupa ndarray 1D" #: extmod/ulab/code/scipy/linalg/linalg.c extmod/ulab/code/user/user.c msgid "input must be a dense ndarray" -msgstr "" +msgstr "input harus berupa ndarray padat" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" -msgstr "" +msgstr "input harus berupa ndarray" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be an ndarray, or a scalar" -msgstr "" +msgstr "input harus berupa ndarray, atau skalar" #: extmod/ulab/code/scipy/signal/signal.c msgid "input must be one-dimensional" -msgstr "" +msgstr "input harus satu dimensi" #: extmod/ulab/code/ulab_tools.c msgid "input must be square matrix" -msgstr "" +msgstr "input harus berupa matriks persegi" #: extmod/ulab/code/numpy/numerical.c msgid "input must be tuple, list, range, or ndarray" -msgstr "" +msgstr "input harus berupa tuple, list, range, atau ndarray" #: extmod/ulab/code/numpy/poly.c msgid "input vectors must be of equal length" -msgstr "" +msgstr "vektor input harus memiliki panjang yang sama" #: extmod/ulab/code/numpy/approx.c msgid "interp is defined for 1D iterables of equal length" -msgstr "" +msgstr "interp didefinisikan untuk iterable 1D dengan panjang yang sama" #: shared-bindings/_bleio/Adapter.c #, c-format msgid "interval must be in range %s-%s" -msgstr "" +msgstr "interval harus dalam rentang %s-%s" #: py/compile.c msgid "invalid arch" -msgstr "" +msgstr "arsitektur tidak valid" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid bits_per_pixel %d, must be, 1, 2, 4, 8, 16, 24, or 32" -msgstr "" +msgstr "bits_per_pixel %d tidak valid, harus 1, 2, 4, 8, 16, 24, atau 32" #: shared-module/ssl/SSLSocket.c msgid "invalid cert" @@ -3313,24 +3486,24 @@ msgstr "cert tidak valid" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element size %d for bits_per_pixel %d\n" -msgstr "" +msgstr "element size %d tidak valid untuk bits_per_pixel %d\n" #: shared-bindings/bitmaptools/__init__.c #, c-format msgid "invalid element_size %d, must be, 1, 2, or 4" -msgstr "" +msgstr "element_size %d tidak valid, harus 1, 2, atau 4" #: shared-bindings/traceback/__init__.c msgid "invalid exception" -msgstr "" +msgstr "exception tidak valid" #: py/objstr.c msgid "invalid format specifier" -msgstr "" +msgstr "spesifier format tidak valid" #: shared-bindings/wifi/Radio.c msgid "invalid hostname" -msgstr "" +msgstr "hostname tidak valid" #: shared-module/ssl/SSLSocket.c msgid "invalid key" @@ -3342,11 +3515,11 @@ msgstr "micropython decorator tidak valid" #: ports/espressif/common-hal/espcamera/Camera.c msgid "invalid setting" -msgstr "" +msgstr "pengaturan tidak valid" #: shared-bindings/random/__init__.c msgid "invalid step" -msgstr "" +msgstr "step tidak valid" #: py/compile.c py/parse.c msgid "invalid syntax" @@ -3354,146 +3527,144 @@ msgstr "syntax tidak valid" #: py/parsenum.c msgid "invalid syntax for integer" -msgstr "" +msgstr "sintaks tidak valid untuk integer" #: py/parsenum.c #, c-format msgid "invalid syntax for integer with base %d" -msgstr "" +msgstr "sintaks tidak valid untuk integer dengan basis %d" #: py/parsenum.c msgid "invalid syntax for number" -msgstr "" +msgstr "sintaks tidak valid untuk angka" #: py/objtype.c msgid "issubclass() arg 1 must be a class" -msgstr "" +msgstr "argumen 1 issubclass() harus berupa class" #: py/objtype.c msgid "issubclass() arg 2 must be a class or a tuple of classes" -msgstr "" +msgstr "argumen 2 issubclass() harus berupa class atau tuple class" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "iterations did not converge" -msgstr "" +msgstr "iterasi tidak konvergen" #: py/objstr.c msgid "join expects a list of str/bytes objects consistent with self object" -msgstr "" +msgstr "join mengharapkan list objek str/bytes yang konsisten dengan objek self" #: py/argcheck.c msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" +"argumen keyword tidak diimplementasikan - gunakan argumen normal sebagai " +"gantinya" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" -msgstr "" +msgstr "label '%q' tidak didefinisikan" #: py/compile.c msgid "label redefined" msgstr "label didefinis ulang" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" -msgstr "" +msgstr "lhs dan rhs harus kompatibel" #: py/emitnative.c msgid "local '%q' has type '%q' but source is '%q'" -msgstr "" +msgstr "lokal '%q' memiliki tipe '%q' tetapi sumber adalah '%q'" #: py/emitnative.c msgid "local '%q' used before type known" -msgstr "" +msgstr "lokal '%q' digunakan sebelum tipe diketahui" #: py/vm.c msgid "local variable referenced before assignment" -msgstr "" +msgstr "variabel lokal direferensikan sebelum penetapan" #: ports/espressif/common-hal/canio/CAN.c msgid "loopback + silent mode not supported by peripheral" -msgstr "" +msgstr "mode loopback + silent tidak didukung oleh periferal" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "mDNS already initialized" -msgstr "" +msgstr "mDNS sudah diinisialisasi" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "mDNS only works with built-in WiFi" -msgstr "" +msgstr "mDNS hanya bekerja dengan WiFi bawaan" #: py/parse.c msgid "malformed f-string" -msgstr "" +msgstr "f-string salah bentuk" #: shared-bindings/_stage/Layer.c msgid "map buffer too small" -msgstr "" +msgstr "buffer peta terlalu kecil" #: py/modmath.c shared-bindings/math/__init__.c msgid "math domain error" -msgstr "" +msgstr "kesalahan domain matematika" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "matrix is not positive definite" -msgstr "" +msgstr "matriks tidak definit positif" #: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c #, c-format msgid "max_length must be 0-%d when fixed_length is %s" -msgstr "" +msgstr "max_length harus 0-%d ketika fixed_length adalah %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " -msgstr "" +msgstr "jumlah maksimum dimensi adalah " #: py/runtime.c msgid "maximum recursion depth exceeded" -msgstr "" +msgstr "kedalaman rekursi maksimum terlampaui" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "maxiter must be > 0" -msgstr "" +msgstr "maxiter harus > 0" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "maxiter should be > 0" -msgstr "" +msgstr "maxiter harus > 0" #: extmod/ulab/code/numpy/numerical.c msgid "median argument must be an ndarray" -msgstr "" +msgstr "argumen median harus berupa ndarray" #: py/runtime.c #, c-format msgid "memory allocation failed, allocating %u bytes" -msgstr "" +msgstr "alokasi memori gagal, mengalokasikan %u byte" #: py/runtime.c msgid "memory allocation failed, heap is locked" -msgstr "" +msgstr "alokasi memori gagal, heap terkunci" #: py/objarray.c msgid "memoryview offset too large" -msgstr "" +msgstr "offset memoryview terlalu besar" #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" -msgstr "" +msgstr "memoryview: panjang bukan kelipatan dari itemsize" #: extmod/modtime.c msgid "mktime needs a tuple of length 8 or 9" -msgstr "" +msgstr "mktime memerlukan tuple dengan panjang 8 atau 9" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "mode must be complete, or reduced" -msgstr "" +msgstr "mode harus complete, atau reduced" #: py/builtinimport.c msgid "module not found" @@ -3501,11 +3672,11 @@ msgstr "modul tidak ditemukan" #: ports/espressif/common-hal/wifi/Monitor.c msgid "monitor init failed" -msgstr "" +msgstr "inisialisasi monitor gagal" #: extmod/ulab/code/numpy/poly.c msgid "more degrees of freedom than data points" -msgstr "" +msgstr "lebih banyak derajat kebebasan daripada titik data" #: py/compile.c msgid "multiple *x in assignment" @@ -3513,76 +3684,76 @@ msgstr "perkalian *x dalam assignment" #: py/objtype.c msgid "multiple bases have instance lay-out conflict" -msgstr "" +msgstr "beberapa basis memiliki konflik tata letak instance" #: py/objtype.c msgid "multiple inheritance not supported" -msgstr "" +msgstr "pewarisan berganda tidak didukung" #: py/emitnative.c msgid "must raise an object" -msgstr "" +msgstr "harus memunculkan objek" #: py/modbuiltins.c msgid "must use keyword argument for key function" -msgstr "" +msgstr "harus menggunakan argumen keyword untuk fungsi kunci" #: py/runtime.c -msgid "name '%q' is not defined" -msgstr "" +msgid "name '%q' isn't defined" +msgstr "nama '%q' tidak didefinisikan" #: py/runtime.c msgid "name not defined" -msgstr "" +msgstr "nama tidak didefinisikan" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "nama terlalu panjang" #: py/persistentcode.c msgid "native code in .mpy unsupported" -msgstr "" +msgstr "kode native dalam .mpy tidak didukung" #: py/asmthumb.c msgid "native method too big" -msgstr "" +msgstr "metode native terlalu besar" #: py/emitnative.c msgid "native yield" -msgstr "" +msgstr "yield native" #: extmod/ulab/code/ndarray.c msgid "ndarray length overflows" -msgstr "" +msgstr "panjang ndarray meluap" #: py/runtime.c #, c-format msgid "need more than %d values to unpack" -msgstr "" +msgstr "memerlukan lebih dari %d nilai untuk membongkar" #: py/modmath.c msgid "negative factorial" -msgstr "" +msgstr "faktorial negatif" #: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative power with no float support" -msgstr "" +msgstr "pangkat negatif tanpa dukungan float" #: py/objint_mpz.c py/runtime.c msgid "negative shift count" -msgstr "" +msgstr "jumlah shift negatif" #: shared-bindings/_pixelmap/PixelMap.c msgid "nested index must be int" -msgstr "" +msgstr "indeks bersarang harus int" #: shared-module/sdcardio/SDCard.c msgid "no SD card" -msgstr "" +msgstr "tidak ada kartu SD" #: py/vm.c msgid "no active exception to reraise" -msgstr "" +msgstr "tidak ada exception aktif untuk dimunculkan kembali" #: py/compile.c msgid "no binding for nonlocal found" @@ -3590,11 +3761,11 @@ msgstr "tidak ada ikatan/bind pada temuan nonlocal" #: shared-module/msgpack/__init__.c msgid "no default packer" -msgstr "" +msgstr "tidak ada packer default" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" -msgstr "" +msgstr "tidak ada seed default" #: py/builtinimport.c msgid "no module named '%q'" @@ -3602,16 +3773,16 @@ msgstr "tidak ada modul yang bernama '%q'" #: shared-module/sdcardio/SDCard.c msgid "no response from SD card" -msgstr "" +msgstr "tidak ada respons dari kartu SD" #: ports/espressif/common-hal/espcamera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" -msgstr "" +msgstr "atribut tidak ada" #: ports/espressif/common-hal/_bleio/Connection.c #: ports/nordic/common-hal/_bleio/Connection.c msgid "non-UUID found in service_uuids_whitelist" -msgstr "" +msgstr "non-UUID ditemukan dalam service_uuids_whitelist" #: py/compile.c msgid "non-default argument follows default argument" @@ -3623,19 +3794,19 @@ msgstr "digit non-hex ditemukan" #: ports/nordic/common-hal/_bleio/Adapter.c msgid "non-zero timeout must be > 0.01" -msgstr "" +msgstr "timeout non-nol harus > 0.01" #: shared-bindings/_bleio/Adapter.c msgid "non-zero timeout must be >= interval" -msgstr "" +msgstr "timeout non-nol harus >= interval" #: shared-bindings/_bleio/UUID.c msgid "not a 128-bit UUID" -msgstr "" +msgstr "bukan UUID 128-bit" #: py/parse.c msgid "not a constant" -msgstr "" +msgstr "bukan konstanta" #: py/objstr.c msgid "not all arguments converted during string formatting" @@ -3647,65 +3818,65 @@ msgstr "" #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" -msgstr "" +msgstr "tidak diimplementasikan untuk dtype complex" #: extmod/ulab/code/numpy/bitwise.c msgid "not supported for input types" -msgstr "" +msgstr "tidak didukung untuk tipe input" #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" -msgstr "" +msgstr "jumlah titik harus setidaknya 2" #: py/builtinhelp.c msgid "object " -msgstr "" +msgstr "objek " #: py/obj.c #, c-format msgid "object '%s' isn't a tuple or list" -msgstr "" +msgstr "objek '%s' bukan tuple atau list" #: py/obj.c msgid "object doesn't support item assignment" -msgstr "" +msgstr "objek tidak mendukung penetapan item" #: py/obj.c msgid "object doesn't support item deletion" -msgstr "" +msgstr "objek tidak mendukung penghapusan item" #: py/obj.c msgid "object has no len" -msgstr "" +msgstr "objek tidak memiliki len" #: py/obj.c msgid "object isn't subscriptable" -msgstr "" +msgstr "objek tidak dapat disubskripsikan" #: py/runtime.c msgid "object not an iterator" -msgstr "" +msgstr "objek bukan iterator" #: py/objtype.c py/runtime.c msgid "object not callable" -msgstr "" +msgstr "objek tidak dapat dipanggil" #: py/sequence.c shared-bindings/displayio/Group.c msgid "object not in sequence" -msgstr "" +msgstr "objek tidak dalam urutan" #: py/runtime.c msgid "object not iterable" -msgstr "" +msgstr "objek tidak dapat diiterasi" #: py/obj.c #, c-format msgid "object of type '%s' has no len()" -msgstr "" +msgstr "objek bertipe '%s' tidak memiliki len()" #: py/obj.c msgid "object with buffer protocol required" -msgstr "" +msgstr "objek dengan protokol buffer diperlukan" #: py/objstr.c msgid "odd-length string" @@ -3713,134 +3884,146 @@ msgstr "panjang data string memiliki keganjilan (odd-length)" #: supervisor/shared/web_workflow/web_workflow.c msgid "off" -msgstr "" +msgstr "mati" #: extmod/ulab/code/utils/utils.c msgid "offset is too large" -msgstr "" +msgstr "offset terlalu besar" #: shared-bindings/dualbank/__init__.c msgid "offset must be >= 0" -msgstr "" +msgstr "offset harus >= 0" #: extmod/ulab/code/numpy/create.c msgid "offset must be non-negative and no greater than buffer length" -msgstr "" +msgstr "offset harus non-negatif dan tidak lebih besar dari panjang buffer" #: ports/nordic/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only bit_depth=16 is supported" -msgstr "" +msgstr "hanya bit_depth=16 yang didukung" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only mono is supported" -msgstr "" +msgstr "hanya mono yang didukung" #: extmod/ulab/code/numpy/create.c msgid "only ndarrays can be concatenated" -msgstr "" +msgstr "hanya ndarray yang dapat digabungkan" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only oversample=64 is supported" -msgstr "" +msgstr "hanya oversample=64 yang didukung" #: ports/nordic/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only sample_rate=16000 is supported" -msgstr "" +msgstr "hanya sample_rate=16000 yang didukung" #: py/objarray.c py/objstr.c py/objstrunicode.c py/objtuple.c #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "only slices with step=1 (aka None) are supported" -msgstr "" +msgstr "hanya slice dengan step=1 (alias None) yang didukung" #: py/vm.c msgid "opcode" -msgstr "" +msgstr "opcode" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" -msgstr "" +msgstr "operan tidak dapat di-broadcast bersama" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "operation is defined for 2D arrays only" -msgstr "" +msgstr "operasi didefinisikan hanya untuk array 2D" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "operation is defined for ndarrays only" -msgstr "" +msgstr "operasi didefinisikan hanya untuk ndarray" #: extmod/ulab/code/ndarray.c msgid "operation is implemented for 1D Boolean arrays only" -msgstr "" +msgstr "operasi diimplementasikan hanya untuk array Boolean 1D" #: extmod/ulab/code/numpy/numerical.c msgid "operation is not implemented on ndarrays" -msgstr "" +msgstr "operasi tidak diimplementasikan pada ndarray" #: extmod/ulab/code/ndarray.c msgid "operation is not supported for given type" -msgstr "" +msgstr "operasi tidak didukung untuk tipe yang diberikan" #: extmod/ulab/code/ndarray_operators.c msgid "operation not supported for the input types" -msgstr "" +msgstr "operasi tidak didukung untuk tipe input" #: py/modbuiltins.c msgid "ord expects a character" -msgstr "" +msgstr "ord mengharapkan karakter" #: py/modbuiltins.c #, c-format msgid "ord() expected a character, but string of length %d found" -msgstr "" +msgstr "ord() mengharapkan karakter, tetapi string dengan panjang %d ditemukan" #: extmod/ulab/code/utils/utils.c msgid "out array is too small" -msgstr "" +msgstr "array out terlalu kecil" + +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "out memiliki tipe yang salah" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" -msgstr "" +msgstr "keyword out tidak didukung untuk dtype complex" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for function" -msgstr "" +msgstr "keyword out tidak didukung untuk fungsi" #: extmod/ulab/code/utils/utils.c msgid "out must be a float dense array" -msgstr "" +msgstr "out harus berupa array padat float" #: extmod/ulab/code/numpy/vector.c msgid "out must be an ndarray" -msgstr "" +msgstr "out harus berupa ndarray" #: extmod/ulab/code/numpy/vector.c msgid "out must be of float dtype" -msgstr "" +msgstr "out harus bertipe dtype float" #: shared-bindings/bitmaptools/__init__.c msgid "out of range of target" -msgstr "" +msgstr "di luar jangkauan target" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "array output memiliki tipe yang salah" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "array output harus berdekatan" #: py/objint_mpz.c msgid "overflow converting long int to machine word" -msgstr "" +msgstr "overflow saat mengonversi long int ke machine word" #: py/modstruct.c #, c-format msgid "pack expected %d items for packing (got %d)" -msgstr "" +msgstr "pack mengharapkan %d item untuk packing (mendapat %d)" #: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c msgid "palette must be 32 bytes long" -msgstr "" +msgstr "palet harus sepanjang 32 byte" #: py/emitinlinextensa.c msgid "parameters must be registers in sequence a2 to a5" -msgstr "" +msgstr "parameter harus berupa register dalam urutan a2 hingga a5" #: py/emitinlinethumb.c msgid "parameters must be registers in sequence r0 to r3" @@ -3848,7 +4031,7 @@ msgstr "parameter harus menjadi register dalam urutan r0 sampai r3" #: extmod/vfs_posix_file.c msgid "poll on file not available on win32" -msgstr "" +msgstr "poll pada file tidak tersedia di win32" #: ports/espressif/common-hal/pulseio/PulseIn.c msgid "pop from an empty PulseIn" @@ -3861,31 +4044,31 @@ msgstr "Muncul dari PulseIn yang kosong" #: ports/stm/common-hal/pulseio/PulseIn.c py/objdict.c py/objlist.c py/objset.c #: shared-bindings/ps2io/Ps2.c msgid "pop from empty %q" -msgstr "" +msgstr "pop dari %q kosong" #: shared-bindings/socketpool/Socket.c msgid "port must be >= 0" -msgstr "" +msgstr "port harus >= 0" #: py/compile.c msgid "positional arg after **" -msgstr "" +msgstr "argumen posisional setelah **" #: py/compile.c msgid "positional arg after keyword arg" -msgstr "" +msgstr "argumen posisional setelah argumen keyword" #: py/objint_mpz.c msgid "pow() 3rd argument cannot be 0" -msgstr "" +msgstr "argumen ketiga pow() tidak boleh 0" #: py/objint_mpz.c msgid "pow() with 3 arguments requires integers" -msgstr "" +msgstr "pow() dengan 3 argumen memerlukan integer" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "pull masks conflict with direction masks" -msgstr "" +msgstr "mask pull berkonflik dengan mask arah" #: py/parse.c msgid "raw f-strings are not supported" @@ -3893,20 +4076,20 @@ msgstr "" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" -msgstr "" +msgstr "bagian real dan imajiner harus memiliki panjang yang sama" #: py/builtinimport.c msgid "relative import" -msgstr "relative import" +msgstr "impor relatif" #: py/obj.c #, c-format msgid "requested length %d but object has length %d" -msgstr "" +msgstr "panjang yang diminta %d tetapi objek memiliki panjang %d" #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" -msgstr "" +msgstr "hasil tidak dapat di-cast ke tipe yang ditentukan" #: py/compile.c msgid "return annotation must be an identifier" @@ -3914,25 +4097,29 @@ msgstr "anotasi return harus sebuah identifier" #: py/emitnative.c msgid "return expected '%q' but got '%q'" -msgstr "" +msgstr "return mengharapkan '%q' tetapi mendapat '%q'" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "rgb_pins[%d] duplicates another pin assignment" -msgstr "" +msgstr "rgb_pins[%d] menduplikasi penetapan pin lain" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "rgb_pins[%d] is not on the same port as clock" -msgstr "" +msgstr "rgb_pins[%d] tidak pada port yang sama dengan clock" #: extmod/ulab/code/numpy/numerical.c msgid "roll argument must be an ndarray" -msgstr "" +msgstr "argumen roll harus berupa ndarray" #: py/objstr.c msgid "rsplit(None,n)" -msgstr "" +msgstr "rsplit(None,n)" + +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed harus true" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c @@ -3941,7 +4128,7 @@ msgstr "nilai sampling keluar dari jangkauan" #: py/modmicropython.c msgid "schedule queue full" -msgstr "" +msgstr "antrian jadwal penuh" #: py/builtinimport.c msgid "script compilation not supported" @@ -3949,35 +4136,43 @@ msgstr "kompilasi script tidak didukung" #: py/nativeglue.c msgid "set unsupported" -msgstr "" +msgstr "set tidak didukung" + +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "shape harus None, dan integer atau tuple integer" #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" -msgstr "" +msgstr "shape harus integer atau tuple integer" #: shared-module/msgpack/__init__.c msgid "short read" -msgstr "" +msgstr "pembacaan pendek" #: py/objstr.c msgid "sign not allowed in string format specifier" -msgstr "" +msgstr "tanda tidak diperbolehkan dalam spesifier format string" #: py/objstr.c msgid "sign not allowed with integer format specifier 'c'" -msgstr "" +msgstr "tanda tidak diperbolehkan dengan spesifier format integer 'c'" #: extmod/ulab/code/ulab_tools.c msgid "size is defined for ndarrays only" -msgstr "" +msgstr "size didefinisikan hanya untuk ndarray" + +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "size harus cocok dengan out.shape ketika digunakan bersama" #: py/nativeglue.c msgid "slice unsupported" -msgstr "" +msgstr "slice tidak didukung" #: py/objint.c py/sequence.c msgid "small int overflow" -msgstr "" +msgstr "overflow int kecil" #: main.c msgid "soft reboot\n" @@ -3985,39 +4180,39 @@ msgstr "memulai ulang software(soft reboot)\n" #: extmod/ulab/code/numpy/numerical.c msgid "sort argument must be an ndarray" -msgstr "" +msgstr "argumen sort harus berupa ndarray" #: extmod/ulab/code/scipy/signal/signal.c msgid "sos array must be of shape (n_section, 6)" -msgstr "" +msgstr "array sos harus berbentuk (n_section, 6)" #: extmod/ulab/code/scipy/signal/signal.c msgid "sos[:, 3] should be all ones" -msgstr "" +msgstr "sos[:, 3] harus semuanya satu" #: extmod/ulab/code/scipy/signal/signal.c msgid "sosfilt requires iterable arguments" -msgstr "" +msgstr "sosfilt memerlukan argumen yang dapat diiterasi" #: shared-bindings/bitmaptools/__init__.c msgid "source palette too large" -msgstr "" +msgstr "palet sumber terlalu besar" #: shared-bindings/bitmaptools/__init__.c msgid "source_bitmap must have value_count of 2 or 65536" -msgstr "" +msgstr "source_bitmap harus memiliki value_count 2 atau 65536" #: shared-bindings/bitmaptools/__init__.c msgid "source_bitmap must have value_count of 65536" -msgstr "" +msgstr "source_bitmap harus memiliki value_count 65536" #: shared-bindings/bitmaptools/__init__.c msgid "source_bitmap must have value_count of 8" -msgstr "" +msgstr "source_bitmap harus memiliki value_count 8" #: extmod/modre.c msgid "splitting with sub-captures" -msgstr "" +msgstr "pemisahan dengan sub-capture" #: py/objstr.c msgid "start/end indices" @@ -4025,40 +4220,28 @@ msgstr "" #: shared-bindings/random/__init__.c msgid "stop not reachable from start" -msgstr "" +msgstr "stop tidak dapat dijangkau dari start" #: py/stream.c shared-bindings/getpass/__init__.c msgid "stream operation not supported" -msgstr "" +msgstr "operasi stream tidak didukung" #: py/objarray.c py/objstr.c msgid "string argument without an encoding" -msgstr "" +msgstr "argumen string tanpa encoding" #: py/objstrunicode.c msgid "string index out of range" -msgstr "" +msgstr "indeks string di luar jangkauan" #: py/objstrunicode.c #, c-format msgid "string indices must be integers, not %s" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index keluar dari jangkauan" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: tidak ada fields" +msgstr "indeks string harus integer, bukan %s" #: py/objarray.c py/objstr.c msgid "substring not found" -msgstr "" +msgstr "substring tidak ditemukan" #: py/compile.c msgid "super() can't find self" @@ -4068,125 +4251,117 @@ msgstr "super() tidak dapat menemukan dirinya sendiri" msgid "syntax error in JSON" msgstr "sintaksis error pada JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "sintaksis error pada pendeskripsi uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" -msgstr "" +msgstr "overflow interval tick" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" -msgstr "" +msgstr "durasi timeout melebihi nilai maksimum yang didukung" #: ports/nordic/common-hal/_bleio/Adapter.c msgid "timeout must be < 655.35 secs" -msgstr "" +msgstr "timeout harus < 655.35 detik" #: ports/raspberrypi/common-hal/floppyio/__init__.c msgid "timeout waiting for flux" -msgstr "" +msgstr "timeout menunggu flux" #: ports/raspberrypi/common-hal/floppyio/__init__.c #: shared-module/floppyio/__init__.c msgid "timeout waiting for index pulse" -msgstr "" +msgstr "timeout menunggu pulsa indeks" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" -msgstr "" +msgstr "timeout menunggu kartu v1" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v2 card" -msgstr "" +msgstr "timeout menunggu kartu v2" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "timer re-init" -msgstr "" +msgstr "inisialisasi ulang timer" #: shared-bindings/time/__init__.c msgid "timestamp out of range for platform time_t" -msgstr "" +msgstr "timestamp di luar jangkauan untuk time_t platform" #: extmod/ulab/code/ndarray.c msgid "tobytes can be invoked for dense arrays only" -msgstr "" +msgstr "tobytes hanya dapat dipanggil untuk array padat" #: py/compile.c msgid "too many args" -msgstr "" +msgstr "terlalu banyak argumen" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/create.c msgid "too many dimensions" -msgstr "" +msgstr "terlalu banyak dimensi" #: extmod/ulab/code/ndarray.c msgid "too many indices" -msgstr "" +msgstr "terlalu banyak indeks" #: py/asmthumb.c msgid "too many locals for native method" -msgstr "" +msgstr "terlalu banyak lokal untuk metode native" #: py/runtime.c #, c-format msgid "too many values to unpack (expected %d)" -msgstr "" +msgstr "terlalu banyak nilai untuk dibongkar (diharapkan %d)" #: extmod/ulab/code/numpy/approx.c msgid "trapz is defined for 1D arrays of equal length" -msgstr "" +msgstr "trapz didefinisikan untuk array 1D dengan panjang yang sama" #: extmod/ulab/code/numpy/approx.c msgid "trapz is defined for 1D iterables" -msgstr "" +msgstr "trapz didefinisikan untuk iterable 1D" #: py/obj.c msgid "tuple/list has wrong length" -msgstr "" +msgstr "tuple/list memiliki panjang yang salah" #: ports/espressif/common-hal/canio/CAN.c #, c-format msgid "twai_driver_install returned esp-idf error #%d" -msgstr "" +msgstr "twai_driver_install mengembalikan kesalahan esp-idf #%d" #: ports/espressif/common-hal/canio/CAN.c #, c-format msgid "twai_start returned esp-idf error #%d" -msgstr "" +msgstr "twai_start mengembalikan kesalahan esp-idf #%d" #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" msgstr "tx dan rx keduanya tidak boleh kosong" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" -msgstr "" +msgid "type '%q' isn't an acceptable base type" +msgstr "tipe '%q' bukan tipe basis yang dapat diterima" #: py/objtype.c -msgid "type is not an acceptable base type" -msgstr "" +msgid "type isn't an acceptable base type" +msgstr "tipe bukan tipe basis yang dapat diterima" #: py/runtime.c msgid "type object '%q' has no attribute '%q'" -msgstr "" +msgstr "objek tipe '%q' tidak memiliki atribut '%q'" #: py/objtype.c msgid "type takes 1 or 3 arguments" -msgstr "" +msgstr "type memerlukan 1 atau 3 argumen" #: py/objint_longlong.c msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" +msgstr "ulonglong terlalu besar" #: py/parse.c msgid "unexpected indent" -msgstr "" +msgstr "indentasi tak terduga" #: py/bc.c msgid "unexpected keyword argument" @@ -4199,20 +4374,20 @@ msgstr "keyword argumen '%q' tidak diharapkan" #: py/lexer.c msgid "unicode name escapes" -msgstr "" +msgstr "escape nama unicode" #: py/parse.c msgid "unindent doesn't match any outer indent level" -msgstr "" +msgstr "unindent tidak cocok dengan tingkat indentasi luar mana pun" #: py/objstr.c #, c-format msgid "unknown conversion specifier %c" -msgstr "" +msgstr "spesifier konversi tidak dikenal %c" #: py/objstr.c msgid "unknown format code '%c' for object of type '%q'" -msgstr "" +msgstr "kode format tidak dikenal '%c' untuk objek bertipe '%q'" #: py/compile.c msgid "unknown type" @@ -4220,103 +4395,102 @@ msgstr "tipe tidak diketahui" #: py/compile.c msgid "unknown type '%q'" -msgstr "" +msgstr "tipe tidak dikenal '%q'" #: py/objstr.c #, c-format msgid "unmatched '%c' in format" -msgstr "" +msgstr "'%c' tidak cocok dalam format" #: py/objtype.c py/runtime.c msgid "unreadable attribute" -msgstr "" +msgstr "atribut tidak dapat dibaca" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" -msgstr "" +msgstr "tipe %q tidak didukung" #: py/emitinlinethumb.c #, c-format msgid "unsupported Thumb instruction '%s' with %d arguments" -msgstr "" +msgstr "instruksi Thumb tidak didukung '%s' dengan %d argumen" #: py/emitinlinextensa.c #, c-format msgid "unsupported Xtensa instruction '%s' with %d arguments" -msgstr "" +msgstr "instruksi Xtensa tidak didukung '%s' dengan %d argumen" #: shared-module/bitmapfilter/__init__.c msgid "unsupported bitmap depth" -msgstr "" +msgstr "kedalaman bitmap tidak didukung" #: shared-module/gifio/GifWriter.c msgid "unsupported colorspace for GifWriter" -msgstr "" +msgstr "colorspace tidak didukung untuk GifWriter" #: shared-bindings/bitmaptools/__init__.c msgid "unsupported colorspace for dither" -msgstr "" +msgstr "colorspace tidak didukung untuk dither" #: py/objstr.c #, c-format msgid "unsupported format character '%c' (0x%x) at index %d" -msgstr "" +msgstr "karakter format tidak didukung '%c' (0x%x) pada indeks %d" #: py/runtime.c msgid "unsupported type for %q: '%s'" -msgstr "" +msgstr "tipe tidak didukung untuk %q: '%s'" #: py/runtime.c msgid "unsupported type for operator" -msgstr "" +msgstr "tipe tidak didukung untuk operator" #: py/runtime.c msgid "unsupported types for %q: '%q', '%q'" -msgstr "" +msgstr "tipe tidak didukung untuk %q: '%q', '%q'" #: extmod/ulab/code/numpy/io/io.c msgid "usecols is too high" -msgstr "" +msgstr "usecols terlalu tinggi" #: extmod/ulab/code/numpy/io/io.c msgid "usecols keyword must be specified" -msgstr "" +msgstr "keyword usecols harus ditentukan" #: py/objint.c #, c-format msgid "value must fit in %d byte(s)" -msgstr "" +msgstr "nilai harus muat dalam %d byte" #: shared-bindings/bitmaptools/__init__.c msgid "value out of range of target" -msgstr "" +msgstr "nilai di luar jangkauan target" #: extmod/moddeflate.c msgid "wbits" -msgstr "" +msgstr "wbit" #: shared-bindings/bitmapfilter/__init__.c msgid "" "weights must be a sequence with an odd square number of elements (usually 9 " "or 25)" msgstr "" +"weights harus berupa urutan dengan jumlah persegi ganjil elemen (biasanya 9 " +"atau 25)" #: shared-bindings/bitmapfilter/__init__.c msgid "weights must be an object of type %q, %q, %q, or %q, not %q " -msgstr "" +msgstr "weights harus berupa objek bertipe %q, %q, %q, atau %q, bukan %q " #: shared-bindings/is31fl3741/FrameBuffer.c msgid "width must be greater than zero" -msgstr "" - -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "wifi tidak diaktifkan" +msgstr "lebar harus lebih besar dari nol" #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" -msgstr "" +msgstr "wifi.Monitor tidak tersedia" #: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" @@ -4332,11 +4506,11 @@ msgstr "sumbu yang ditentukan salah" #: extmod/ulab/code/numpy/io/io.c msgid "wrong dtype" -msgstr "" +msgstr "dtype salah" #: extmod/ulab/code/numpy/transform.c msgid "wrong index type" -msgstr "" +msgstr "tipe indeks salah" #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/create.c #: extmod/ulab/code/numpy/io/io.c extmod/ulab/code/numpy/transform.c @@ -4346,11 +4520,11 @@ msgstr "tipe input salah" #: extmod/ulab/code/numpy/transform.c msgid "wrong length of condition array" -msgstr "" +msgstr "panjang array kondisi salah" #: extmod/ulab/code/numpy/transform.c msgid "wrong length of index array" -msgstr "" +msgstr "panjang array indeks salah" #: extmod/ulab/code/numpy/create.c py/objarray.c py/objstr.c msgid "wrong number of arguments" @@ -4376,6 +4550,56 @@ msgstr "zi harus berjenis float" msgid "zi must be of shape (n_section, 2)" msgstr "Zi harus berbentuk (n_section, 2)" +#~ msgid "Unsupported format" +#~ msgstr "Format tidak didukung" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Wifi tidak diaktifkan" + +#~ msgid "wifi is not enabled" +#~ msgstr "wifi tidak diaktifkan" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Tidak dapat memasang kembali '/' saat terlihat melalui USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q harus berupa objek %q, %q, atau %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Potongan data harus mengikuti fmt chunk" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Hanya monokrom, 4bpp atau 8bpp yang diindeks, dan 16bpp atau lebih yang " +#~ "didukung: %d bpp diberikan" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Sampel bits_per_sampel tidak cocok dengan mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Jumlah saluran sampel tidak cocok dengan mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Tingkat sampel dari sampel tidak cocok dengan mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "signedness dari sampel tidak cocok dengan mixer" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Panjang buffer harus kelipatan 512" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index keluar dari jangkauan" + +#~ msgid "struct: no fields" +#~ msgstr "struct: tidak ada fields" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "sintaksis error pada pendeskripsi uctypes" + #~ msgid "Name too long" #~ msgstr "Nama terlalu panjang" @@ -4535,13 +4759,13 @@ msgstr "Zi harus berbentuk (n_section, 2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "Objek '%s' tidak mendukung penghapusan item" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "Objek '%s' bukan iterator" #~ msgid "'%s' object is not callable" #~ msgstr "Objek '%s' tidak dapat dipanggil" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' objek tidak dapat diulang" #~ msgid "'%s' object is not subscriptable" @@ -5351,7 +5575,7 @@ msgstr "Zi harus berbentuk (n_section, 2)" #~ msgid "frequency can only be either 80Mhz or 160MHz" #~ msgstr "frekuensi hanya bisa didefinisikan 80Mhz atau 160Mhz" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "fungsi tidak dapat mengambil argumen keyword" #~ msgid "impossible baudrate" @@ -5406,7 +5630,7 @@ msgstr "Zi harus berbentuk (n_section, 2)" #~ msgid "name must be a string" #~ msgstr "keyword harus berupa string" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "nama digunakan kembali untuk argumen" #~ msgid "non-keyword arg after */**" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 25d4a28312287..833991ac476e0 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -69,7 +69,7 @@ msgstr "" #: py/objstr.c #, c-format -msgid "%%c requires int or char" +msgid "%%c needs int or char" msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -78,11 +78,16 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "" @@ -99,14 +104,21 @@ msgid "%q contains duplicate pins" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -114,7 +126,8 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "" @@ -126,7 +139,9 @@ msgstr "" msgid "%q indices must be integers, not %s" msgstr "" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "" @@ -154,16 +169,12 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "" - #: py/argcheck.c msgid "%q must be %d" msgstr "" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -214,6 +225,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -223,6 +235,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -231,23 +244,29 @@ msgstr "" msgid "%q must be power of 2" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -268,7 +287,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -297,20 +317,20 @@ msgstr "" msgid "'%q' argument required" msgstr "" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" +msgid "'%q' object isn't callable" msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -414,6 +434,10 @@ msgstr "" msgid "'label' requires 1 argument" msgstr "" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "" @@ -438,6 +462,7 @@ msgstr "" msgid ", in %q\n" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -456,7 +481,7 @@ msgstr "" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "" @@ -491,7 +516,8 @@ msgstr "" msgid "All SPI peripherals are in use" msgstr "" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "" @@ -533,7 +559,6 @@ msgstr "" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "" @@ -546,6 +571,10 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -555,10 +584,11 @@ msgstr "" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "" @@ -581,6 +611,10 @@ msgstr "" msgid "Array values should be single bytes." msgstr "" +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -590,6 +624,12 @@ msgstr "" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -612,6 +652,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -629,20 +670,17 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "" @@ -657,12 +695,12 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" msgstr "" #: shared-bindings/_bleio/PacketBuffer.c @@ -685,10 +723,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "" - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "" @@ -721,6 +755,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -736,6 +774,10 @@ msgstr "" msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -766,10 +808,11 @@ msgid "Cannot record to a file" msgstr "" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "" @@ -782,6 +825,10 @@ msgstr "" msgid "Cannot subclass slice" msgstr "" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -816,6 +863,14 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "" @@ -828,6 +883,11 @@ msgstr "" msgid "Couldn't allocate decoder" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "" @@ -845,10 +905,6 @@ msgstr "" msgid "Data 0 pin must be byte aligned" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -887,6 +943,7 @@ msgstr "" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "" @@ -895,6 +952,7 @@ msgid "Done" msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "" @@ -906,8 +964,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -954,7 +1021,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -972,22 +1039,60 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "" @@ -996,12 +1101,13 @@ msgstr "" msgid "File exists" msgstr "" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1026,7 +1132,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "" @@ -1048,6 +1154,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1134,6 +1241,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1145,7 +1253,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1179,18 +1288,29 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1220,6 +1340,14 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1228,17 +1356,12 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "" @@ -1251,6 +1374,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1262,11 +1386,13 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "" @@ -1274,10 +1400,6 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "" @@ -1303,13 +1425,23 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1398,7 +1530,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1416,6 +1548,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1491,6 +1624,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -1526,17 +1663,14 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1589,13 +1723,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1633,6 +1760,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1646,6 +1774,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1665,6 +1794,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1762,7 +1895,12 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "" @@ -1782,6 +1920,27 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1860,9 +2019,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1873,6 +2033,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -1912,6 +2076,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1920,6 +2085,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -1956,20 +2125,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -1990,7 +2147,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -1998,6 +2157,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2008,11 +2171,16 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2051,6 +2219,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2059,6 +2231,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" @@ -2083,10 +2263,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2103,6 +2279,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2111,6 +2288,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "" @@ -2128,6 +2306,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2212,6 +2394,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "" @@ -2220,15 +2406,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2237,15 +2420,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2281,8 +2469,10 @@ msgstr "" msgid "Wi-Fi: " msgstr "" +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2305,6 +2495,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2318,6 +2509,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2374,10 +2566,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2402,6 +2602,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2432,10 +2636,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2452,6 +2652,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2488,6 +2692,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2500,6 +2708,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "" @@ -2557,6 +2774,10 @@ msgstr "" msgid "can only have one parent" msgstr "" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2581,7 +2802,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2624,6 +2845,14 @@ msgstr "" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2636,6 +2865,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2698,10 +2931,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2722,18 +2951,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -2888,7 +3113,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -2987,10 +3212,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3031,16 +3252,20 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3090,7 +3315,8 @@ msgstr "" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3107,10 +3333,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3173,18 +3395,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3242,7 +3456,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3275,6 +3489,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3371,10 +3589,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3428,7 +3642,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3473,6 +3687,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3506,7 +3724,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3521,10 +3739,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3546,7 +3760,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3570,7 +3784,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3596,7 +3810,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3615,14 +3829,6 @@ msgstr "" msgid "not a constant" msgstr "" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "" @@ -3631,6 +3837,10 @@ msgstr "" msgid "not supported for input types" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3644,6 +3854,10 @@ msgstr "" msgid "object '%s' isn't a tuple or list" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3685,10 +3899,6 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "" @@ -3737,6 +3947,30 @@ msgstr "" msgid "opcode" msgstr "" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3779,6 +4013,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3803,6 +4041,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3812,8 +4058,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3865,14 +4111,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3882,6 +4128,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3912,6 +4162,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3929,6 +4183,10 @@ msgstr "" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3949,6 +4207,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -3997,10 +4259,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4022,18 +4280,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4046,10 +4292,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4139,11 +4381,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4154,14 +4396,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4209,7 +4443,9 @@ msgstr "" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "" @@ -4287,11 +4523,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" diff --git a/locale/cs.po b/locale/cs.po index 5a97edcb95d65..14eb245b9b813 100644 --- a/locale/cs.po +++ b/locale/cs.po @@ -6,15 +6,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Scott Shawcroft \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: LANGUAGE \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -"X-Generator: Weblate 5.2\n" +"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -80,8 +80,8 @@ msgstr " výstup:\n" #: py/objstr.c #, c-format -msgid "%%c requires int or char" -msgstr "%%c vyžaduje int nebo char" +msgid "%%c needs int or char" +msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -89,11 +89,16 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "%d adresní pin, %d rgb pin a %d dlaždice indikuje výšku %d, ne %d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q a %q obsahují duplicitní piny" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q a %q musí být rozdílné" @@ -110,14 +115,21 @@ msgid "%q contains duplicate pins" msgstr "%q obsahuje duplicitní piny" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q: selhání %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q v %q musí být typu %q, ne %q" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -125,7 +137,8 @@ msgstr "%q v %q musí být typu %q, ne %q" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "%q se právě používá" @@ -137,7 +150,9 @@ msgstr "Index %q je mimo rozsah" msgid "%q indices must be integers, not %s" msgstr "Indexy %q musí být celá čísla, nikoli %s" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "Inicializace %q selhala" @@ -165,16 +180,12 @@ msgstr "Délka %q musí být <= %d" msgid "%q length must be >= %d" msgstr "Délka %q musí být >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "" - #: py/argcheck.c msgid "%q must be %d" msgstr "%q musí být %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -225,6 +236,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q musí být typu %q nebo %q, ne %q" @@ -234,6 +246,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q musí být typu %q, ne %q" @@ -242,23 +255,29 @@ msgstr "%q musí být typu %q, ne %q" msgid "%q must be power of 2" msgstr "%q musí být mocnina 2" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "%q je mimo hranice" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "%q je mimo rozsah" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q krok nemůže být nula" @@ -279,7 +298,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, a %q musí mít všechny shodnou délku" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -308,20 +328,20 @@ msgstr "%s chyba 0x%x" msgid "'%q' argument required" msgstr "Je vyžadován argument '%q'" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "Objekt '%q' nepodporuje '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "Objekt '%q' není iterátor" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" -msgstr "Objekt '%q' nelze zavolat" +msgid "'%q' object isn't callable" +msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "Objekt '%q' není iterovatelný" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -425,6 +445,10 @@ msgstr "'data' vyžaduje celočíselné argumenty" msgid "'label' requires 1 argument" msgstr "'label' vyžaduje 1 argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' je volán mimo funkci" @@ -449,6 +473,7 @@ msgstr "∗x musí být cíl přiřazení" msgid ", in %q\n" msgstr ", v% q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -467,7 +492,7 @@ msgstr "pow() nepodporuje 3 argumenty" msgid "AP could not be started" msgstr "AP nemohl být spuštěn" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Adresa musí být %d bajtů dlouhá" @@ -502,7 +527,8 @@ msgstr "Všechny RX FIFO jsou používány" msgid "All SPI peripherals are in use" msgstr "Všechny SPI periferie jsou používány" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Všechny UART periferie jsou používány" @@ -544,7 +570,6 @@ msgstr "Všechny časovače pro tento pin jsou používány" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Všechny časovače jsou používány" @@ -557,6 +582,10 @@ msgstr "Již propagujeme." msgid "Already have all-matches listener" msgstr "Již existuje posluchač pro všechny zprávy" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -566,10 +595,11 @@ msgstr "Již běží" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Již skenuje wifi sítě" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "Došlo k chybě při načítání '%s'\n" @@ -592,6 +622,10 @@ msgstr "Pole musí obsahovat poloviční slova (typ „H“)" msgid "Array values should be single bytes." msgstr "Hodnoty pole by měly být jednoduché bajty." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -601,6 +635,12 @@ msgstr "Pokus o alokování %d bloků" msgid "Audio conversion not implemented" msgstr "Konverze audia není implementována" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN nepoužívá heslo" @@ -625,6 +665,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudrate není podporován periférií" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -642,20 +683,17 @@ msgstr "Velikost bitmapy a počet bitů na hodnotu se musí shodovat" msgid "Boot device must be first (interface #0)." msgstr "Bootovací zařízení musí být první (rozhraní #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "RX a TX jsou vyžadovány pro kontrolu toku" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Jas není nastavitelný" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Vyrovnávací paměť + offset je příliš malý %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Prvky bufferu musí být 4 bajty dlouhé nebo méně" @@ -670,13 +708,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Délka vyrovnávací paměti %d je příliš velká. Musí být menší než %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Délka vyrovnávací paměti musí být násobkem 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Buffer musí být násobkem 512 bajtů" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -698,10 +736,6 @@ msgstr "Buffer příliš malý" msgid "Bus pin %d is already in use" msgstr "Sběrnicový pin %d je již používán" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Buffer musí být dlouhý 16 bajtů." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "Bloky CBC musí být násobky 16 bajtů" @@ -737,6 +771,10 @@ msgid "Can only alarm on two low pins from deep sleep." msgstr "" "Lze nastavit alarm na maximálně dvou pinech ve stavu low při hlubokém spánku." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -752,6 +790,10 @@ msgstr "Nelze změnit USB zařízení" msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "Není možné vytvořit nový adaptér; použití _bleio.adapter;" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -782,10 +824,11 @@ msgid "Cannot record to a file" msgstr "Nelze nahrávat do souboru" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Není možné znovu připojit '/', pokud je viditelné pomocí USB." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "Nelze nastavit hodnotu, když směr je vstup." @@ -798,6 +841,10 @@ msgstr "Nelze určit RTS nebo CTS v režimu RS485" msgid "Cannot subclass slice" msgstr "Nelze použít řez podtřídy" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Nelze probudit hranou na pinu, pouze úrovní" @@ -833,6 +880,14 @@ msgstr "Pole souřadnic mají různé délky" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Není možné nastavit adresu" @@ -845,6 +900,11 @@ msgstr "Nelze začít přerušení, RX je zaneprázdněn" msgid "Couldn't allocate decoder" msgstr "Dekodér nelze přiřadit" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Chyba inicializace kanálu DAC" @@ -862,10 +922,6 @@ msgstr "DAC se již používá" msgid "Data 0 pin must be byte aligned" msgstr "Datový pin 0 musí být zarovnán na bajty" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Datový blok musí následovat fmt blok" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -905,6 +961,7 @@ msgstr "Displej musí mít 16bitový barevný prostor." #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "Otočení displeje musí být po 90 stupních" @@ -913,6 +970,7 @@ msgid "Done" msgstr "Hotovo" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "" @@ -924,8 +982,17 @@ msgstr "Při zpracování uvedené výjimky nastala další výjimka:" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB operuje najednou pouze 16 bajtů" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF alokace paměti selhala" @@ -972,7 +1039,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "Chyba alokace %q bufferu" @@ -990,22 +1057,60 @@ msgstr "Nepodařilo se nabufferovat sample" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Připojení se nezdařilo: interní chyba" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Nepodařilo se připojit: časový limit" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Soubor MP3 se nepodařilo analyzovat" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Nepodařilo se uvolnit mutex, err 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Nepodařilo se zapsat do interní paměti." @@ -1014,12 +1119,13 @@ msgstr "Nepodařilo se zapsat do interní paměti." msgid "File exists" msgstr "soubor existuje" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "Soubor nenalezen" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filtry jsou příliš komplexní" @@ -1044,7 +1150,7 @@ msgstr "Pro barevný prostor L8 musí mít vstupní bitmapa 8 bitů na pixel" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "Pro barevný prostor RGB musí mít vstupní bitmapa 16 bitů na pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Formát není podporován" @@ -1068,6 +1174,7 @@ msgstr "Inicializace GNSS" msgid "Generic Failure" msgstr "Základní chyba" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1154,6 +1261,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Rozhraní musí být nastartováno" @@ -1165,7 +1273,8 @@ msgstr "Interní audio buffer je příliš malý" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Interní chyba" @@ -1199,18 +1308,29 @@ msgstr "Chyba přerušení." msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Špatný %s" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1240,6 +1360,14 @@ msgstr "Chybné BSSID" msgid "Invalid MAC address" msgstr "Chybná MAC adresa" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Neplatný argument" @@ -1248,17 +1376,12 @@ msgstr "Neplatný argument" msgid "Invalid bits per value" msgstr "" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "Špatný byte %.*s" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "Chybný data_pin[%d]" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "Špatný formát" @@ -1271,6 +1394,7 @@ msgid "Invalid hex password" msgstr "Špatné heslo v hex" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Chybná multicastová MAC adresa" @@ -1282,11 +1406,13 @@ msgstr "Chybná velikost" msgid "Invalid socket for TLS" msgstr "Chybný soket pro TLS" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Chybný stav" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "Neplatná unicode escape sekvence" @@ -1294,10 +1420,6 @@ msgstr "Neplatná unicode escape sekvence" msgid "Key must be 16, 24, or 32 bytes long" msgstr "Klíč musí být dlouhý 16, 24 nebo 32 bajtů" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "Klíč nenalezen" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "Mapování LED musí korespondovat s velikostí displeje" @@ -1323,13 +1445,23 @@ msgid "MAC address was invalid" msgstr "MAC adresa byla chybná" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1418,7 +1550,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "Žádný %q pin" @@ -1436,6 +1568,7 @@ msgstr "Žádný DAC na čipu" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "Nebyl nalezen žádný kanál DMA" @@ -1511,6 +1644,10 @@ msgstr "SDA nebo SCL zřejmě nemá pull up; zkontroluj zapojení" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Žádný pulldown na pinu; doporučeno 1Mohm" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "Na zařízení nezůstal žádný prostor" @@ -1546,18 +1683,15 @@ msgid "Not connected" msgstr "Nepřipojený" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "Nehraje" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Počet data_pins musí být 8 nebo 16, nikoli %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "" #: shared-bindings/util.c msgid "" @@ -1610,15 +1744,6 @@ msgstr "Na tomto hardware je dostupná pouze detekce hrany" msgid "Only int or string supported for ip" msgstr "Pro IP je podporován pouze int nebo string" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Podporovány jsou pouze černobílé, indexované 4 bpp nebo 8 bpp a 16 bpp nebo " -"vyšší BMP: bitmapa má %d bpp" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Pouze jeden %q lze nastavit v hlubokém spánku." @@ -1656,6 +1781,7 @@ msgid "Operation or feature not supported" msgstr "Operace nebo funkce není podporována" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "Časový limit operace vypršel" @@ -1669,6 +1795,7 @@ msgstr "Došla paměť" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Došly sockety" @@ -1688,6 +1815,10 @@ msgstr "PWM kanál je již využíván" msgid "PWM slice channel A already in use" msgstr "PWM kanál A je již využíván" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1787,7 +1918,12 @@ msgstr "Velikost programu je nesprávná" msgid "Program too long" msgstr "Program je příliš dlouhý" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "" @@ -1807,6 +1943,27 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1885,10 +2042,11 @@ msgstr "Inicializace SD karty" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo chyba %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "Inicializace SDIO chyba %d" +msgid "SDIO Init Error %x" +msgstr "" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1898,6 +2056,10 @@ msgstr "Konfigurace SPI selhala" msgid "SPI init error" msgstr "Chyba inicializace SPI" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "SPI periferie je používána" @@ -1937,6 +2099,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1945,6 +2108,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool je možné použít pouze s wifi.radio" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "Zdrojové a cílové buffery musí být stejné délky" @@ -1981,20 +2148,8 @@ msgstr "Výše uvedená výjimka byla přímá příčina následující výjimk msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Počet prvků rgb_pin musí být 6, 12, 18, 24, nebo 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -2015,7 +2170,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2023,6 +2180,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Čas je v minulosti." @@ -2033,11 +2194,16 @@ msgstr "Čas je v minulosti." msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Časový limit je příliš dlouhý: maximální limit je %d vteřin" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "V samplu je příliš mnoho kanálů" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2077,6 +2243,10 @@ msgstr "De-inicializace UART" msgid "UART init" msgstr "Inicializace UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "UART periférie je používána" @@ -2085,6 +2255,14 @@ msgstr "UART periférie je používána" msgid "UART re-init" msgstr "Opětovná inicializace UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "Zápis na UART" @@ -2109,10 +2287,6 @@ msgstr "USB zařízení používají příliš mnoho názvů rozhraní." msgid "USB error" msgstr "Chyba USB" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "UUID integer musí být 0-0xffff" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID řetězec neodpovídá 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" @@ -2129,6 +2303,7 @@ msgstr "Nelze přistupovat k nezarovnanému IO registru" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2137,6 +2312,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "Není možné vytvořit zámek" @@ -2154,6 +2330,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "Nelze číst data palety barev" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2238,6 +2418,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "Nepodporovaný barevný prostor" @@ -2246,15 +2430,12 @@ msgstr "Nepodporovaný barevný prostor" msgid "Unsupported display bus type" msgstr "Nepodporovaná sběrnice dispalye" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Nepodporovaný formát" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Nepodporovaný hash algoritmus" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2263,15 +2444,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2312,9 +2498,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "Wifi není povoleno" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "" #: main.c msgid "Woken up by alarm.\n" @@ -2336,6 +2524,7 @@ msgstr "Při spuštění jsi stiskl obě tlačítka." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Při spuštění jsi stiskl tlačítko A." @@ -2349,6 +2538,7 @@ msgstr "Při spuštění jsi stiskl tlačítko BOOT" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2405,10 +2595,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "anotace musí být identifikátor" @@ -2433,6 +2631,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "argsort není implementován pro zploštěná pole" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "jméno argumentu znovupoužito" @@ -2463,10 +2665,6 @@ msgstr "pole je příliš velké" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "přetečení v asm" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2483,6 +2681,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "osa je mimo rozsah" @@ -2519,6 +2721,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2531,6 +2737,15 @@ msgstr "velikosti bitmapy musí odpovídat" msgid "bits must be 32 or less" msgstr "počet bitů nesmí přesáhnout 32" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "" @@ -2588,6 +2803,10 @@ msgstr "" msgid "can only have one parent" msgstr "může mít pouze jednoho rodiče" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2612,7 +2831,7 @@ msgstr "" msgid "can't cancel self" msgstr "nelze zrušit sám sebe" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "není možné převést %q na %q" @@ -2655,6 +2874,14 @@ msgstr "nelze převést na int" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2667,6 +2894,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2729,10 +2960,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "nelze čekat" @@ -2753,18 +2980,14 @@ msgstr "nelze převést complex na dtype" msgid "cannot convert complex type" msgstr "nelze převést typ complex" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "nelze smazat prvky pole" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "nelze změnit rozměry pole" @@ -2919,7 +3142,7 @@ msgstr "dimenze nesouhlasí" msgid "div/mod not implemented for uint" msgstr "div/mod nejsou implementované pro uint" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "dělení nulou" @@ -3018,10 +3241,6 @@ msgstr "" msgid "file write is not available" msgstr "zápis do souboru není dostupný" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "První argument musí být zavolatelný" @@ -3062,16 +3281,20 @@ msgstr "" msgid "float unsupported" msgstr "float není podporován" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3121,7 +3344,8 @@ msgstr "funkci chybí argument specifikovaný klíčovým slovem" msgid "function missing required positional argument #%d" msgstr "funkci chybí požadovaný argument na pozici #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3138,10 +3362,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "generátor způsobil StopIteration" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "hash je konečný" @@ -3204,18 +3424,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "inicializace I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "výchozí hodnoty musí být iterovatelné" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "délka initial_value je chybná" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3273,7 +3485,7 @@ msgstr "vstup musí být 1D ndarray" msgid "input must be a dense ndarray" msgstr "vstup musí být hustý ndarray" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "vstup musí být ndarray" @@ -3306,6 +3518,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3402,10 +3618,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3459,7 +3671,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "maximální počet dimenzí je " @@ -3504,6 +3716,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3537,7 +3753,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3552,10 +3768,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3577,7 +3789,7 @@ msgstr "záporný faktoriál" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3601,7 +3813,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3627,7 +3839,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3646,14 +3858,6 @@ msgstr "" msgid "not a constant" msgstr "není konstanta" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "není implementováno pro komplexní dtype" @@ -3662,6 +3866,10 @@ msgstr "není implementováno pro komplexní dtype" msgid "not supported for input types" msgstr "není podporováno pro vstupní typy" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3675,6 +3883,10 @@ msgstr "objekt " msgid "object '%s' isn't a tuple or list" msgstr "objekt '%s' není tuple or nebo list" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3716,10 +3928,6 @@ msgstr "objekt typu '%s' nemá len()" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "vypnuto" @@ -3768,6 +3976,30 @@ msgstr "" msgid "opcode" msgstr "opcode" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3810,6 +4042,10 @@ msgstr "" msgid "out array is too small" msgstr "výstupní pole je příliš malé" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3834,6 +4070,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3843,8 +4087,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3896,14 +4140,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "surové f-stringy nesjou podporované" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3913,6 +4157,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3941,6 +4189,10 @@ msgstr "" #: py/objstr.c msgid "rsplit(None,n)" +msgstr "rsplit(None,n)" + +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -3960,6 +4212,10 @@ msgstr "" msgid "set unsupported" msgstr "set neoodporován" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "tvar musí být integer nebo tuple integerů" @@ -3980,6 +4236,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4028,10 +4288,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4053,18 +4309,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4077,10 +4321,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4170,11 +4410,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4185,14 +4425,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "neočekávané odsazení" @@ -4240,7 +4472,9 @@ msgstr "neshoduje se '%c' ve formátu" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "nepodporovaný typ% q" @@ -4318,11 +4552,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wifi.Monitor není dostupný" @@ -4385,6 +4614,76 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "asm overflow" +#~ msgstr "přetečení v asm" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Vyrovnávací paměť + offset je příliš malý %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Buffer musí být dlouhý 16 bajtů." + +#~ msgid "UUID integer value must be 0-0xffff" +#~ msgstr "UUID integer musí být 0-0xffff" + +#~ msgid "initial_value length is wrong" +#~ msgstr "délka initial_value je chybná" + +#, c-format +#~ msgid "Invalid byte %.*s" +#~ msgstr "Špatný byte %.*s" + +#~ msgid "Key not found" +#~ msgstr "Klíč nenalezen" + +#, c-format +#~ msgid "%%c requires int or char" +#~ msgstr "%%c vyžaduje int nebo char" + +#~ msgid "'%q' object is not callable" +#~ msgstr "Objekt '%q' nelze zavolat" + +#~ msgid "raw f-strings are not supported" +#~ msgstr "surové f-stringy nesjou podporované" + +#~ msgid "Unsupported format" +#~ msgstr "Nepodporovaný formát" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Wifi není povoleno" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Není možné znovu připojit '/', pokud je viditelné pomocí USB." + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Datový blok musí následovat fmt blok" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Podporovány jsou pouze černobílé, indexované 4 bpp nebo 8 bpp a 16 bpp " +#~ "nebo vyšší BMP: bitmapa má %d bpp" + +#~ msgid "init I2C" +#~ msgstr "inicializace I2C" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Délka vyrovnávací paměti musí být násobkem 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Buffer musí být násobkem 512 bajtů" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Počet data_pins musí být 8 nebo 16, nikoli %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "Inicializace SDIO chyba %d" + #~ msgid "Name too long" #~ msgstr "Jméno je příliš dlouhé" @@ -4570,7 +4869,7 @@ msgstr "" #~ msgid "'continue' outside loop" #~ msgstr "'continue' je volán mimo cyklus" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "Objekt 'coroutine' není iterátor" #~ msgid "64 bit types" @@ -4630,8 +4929,8 @@ msgstr "" #~ msgstr "IV musí být dlouhé %d bajtů" #~ msgid "" -#~ "Incompatible .mpy file. Please update all .mpy files. See http://adafru." -#~ "it/mpy-update for more info." +#~ "Incompatible .mpy file. Please update all .mpy files. See http://" +#~ "adafru.it/mpy-update for more info." #~ msgstr "" #~ "Nekompatibilní soubor .mpy. Aktualizujte prosím všechny soubory .mpy. " #~ "Další informace naleznete na adrese http://adafru.it/mpy-update." diff --git a/locale/de_DE.po b/locale/de_DE.po index 5e062be364ffe..1ac8df553147a 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -6,14 +6,14 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2024-06-18 19:09+0000\n" -"Last-Translator: Xfox20 <136956349+Xfox20@users.noreply.github.com>\n" +"PO-Revision-Date: 2025-06-29 13:01+0000\n" +"Last-Translator: MAE \n" "Language: de_DE\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.6-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -94,7 +94,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q und %q enthalten doppelte Pins" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q und %q müssen unterschiedlich sein" @@ -115,7 +115,11 @@ msgstr "%q enthält doppelte Pins" msgid "%q failure: %d" msgstr "%q Fehler: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q in %q muss vom Typ %q oder %q sein, nicht %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q in %q muss von Typ %q sein, nicht %q" @@ -167,7 +171,7 @@ msgstr "%q länge muss kleiner oder gleich %d sein" msgid "%q length must be >= %d" msgstr "%q länge muss größer oder gleich %d sein" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q von %q nach %q versetzt" @@ -228,6 +232,7 @@ msgstr "%q muss ein Vielfaches von 8 sein." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q muss von Typ %q oder %q sein, nicht %q" @@ -237,6 +242,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q muss vom Typ %q, %q oder %q sein, und nicht %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q muss von Typ %q sein, nicht %q" @@ -283,7 +289,8 @@ msgstr "%q() ohne %q()" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q und %q müssen alle die gleiche Länge haben" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -297,7 +304,7 @@ msgstr "%q[%u] schiebt mehr Bits raus als Pins vorhanden sind" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] uses extra pin" -msgstr "" +msgstr "%q[%u] verwendet zusätzlichen Pin" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "%q[%u] waits on input outside of count" @@ -317,7 +324,7 @@ msgid "'%q' object does not support '%q'" msgstr "'%q' Objekt unterstützt '%q' nicht" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "'%q' Objekt ist kein Iterator" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -325,7 +332,7 @@ msgid "'%q' object is not callable" msgstr "'%q' Objekt ist kein callable" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "'%q' Objekt ist nicht iterierbar" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -415,7 +422,7 @@ msgstr "'await' außerhalb einer Funktion" #: py/compile.c msgid "'break'/'continue' outside loop" -msgstr "'break'/'continue' ausserhalb einer Schleife" +msgstr "'break'/'continue' außerhalb der Schleife" #: py/compile.c msgid "'data' requires at least 2 arguments" @@ -429,6 +436,10 @@ msgstr "'data' erfordert Integer-Argumente" msgid "'label' requires 1 argument" msgstr "'label' erfordert genau ein Argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' nicht implementiert" + #: py/compile.c msgid "'return' outside function" msgstr "'return' außerhalb einer Funktion" @@ -484,7 +495,7 @@ msgstr "Adressbereich nicht erlaubt" #: shared-bindings/memorymap/AddressRange.c msgid "Address range wraps around" -msgstr "" +msgstr "Der Adressbereich umfasst folgende Bereiche" #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" @@ -548,7 +559,6 @@ msgstr "Alle Timer für diesen Pin werden bereits benutzt" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Alle Timer werden benutzt" @@ -561,6 +571,10 @@ msgstr "Bereits am Anbieten (advertising)." msgid "Already have all-matches listener" msgstr "All-Matchers-Listener bereits vorhanden" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Bereits in Arbeit" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,6 +584,7 @@ msgstr "Läuft bereits" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Sucht bereits nach Wifi-Netzwerken" @@ -596,6 +611,10 @@ msgstr "Array muss Halbwörter enthalten (type 'H')" msgid "Array values should be single bytes." msgstr "Array-Werte sollten aus Einzelbytes bestehen." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "Asynchroner SPI-Transfer auf diesem Bus im Gange, warten Sie weiter." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +624,11 @@ msgstr "Versuche %d Blöcke zu allokieren" msgid "Audio conversion not implemented" msgstr "Audio-Konvertierung nicht implementiert" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Audioquellenfehler" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN wird mit Passwort nicht verwendet" @@ -636,7 +660,7 @@ msgstr "Unterhalb der minimalen Frame Rate" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential GPIO pins" -msgstr "" +msgstr "Bittakt und Wortauswahl müssen aufeinanderfolgende GPIO-Pins sein" #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" @@ -674,13 +698,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Die Pufferlänge %d ist zu groß. Sie muss kleiner als %d sein" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Die Pufferlänge muss ein vielfaches von 512 sein" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Der Puffer muss ein vielfaches von 512 bytes sein" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Puffer muss ein Vielfaches von %d Bytes sein" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -740,6 +764,12 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "Kann nur auf zwei Pins Alarm als low aus Deep Sleep auslösen." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" +"AudioOut kann nicht erstellt werden, da ein kontinuierlicher Kanal bereits " +"geöffnet ist" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -786,8 +816,9 @@ msgid "Cannot record to a file" msgstr "Aufnahme in eine Datei nicht möglich" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "'/' kann nicht wiedereingehängt werden, wenn per USB sichtbar." +msgid "Cannot remount path when visible via USB." +msgstr "" +"Der Pfad kann nicht neu gemountet werden, wenn er über USB sichtbar ist." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -802,6 +833,10 @@ msgstr "RTS oder CTS können im RS485-Modus nicht angegeben werden" msgid "Cannot subclass slice" msgstr "Slice kann keine sub-klasse sein" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "GPIO0..15 kann nicht zusammen mit GPIO32..47 verwendet werden" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Kann nicht durch Flanke an Pin geweckt werden, sondern nur durch Pegel" @@ -838,6 +873,10 @@ msgstr "Koordinaten-Arrays haben unterschiedliche Längen" msgid "Coordinate arrays types have different sizes" msgstr "Typen der Koordinaten-Arrays haben unterschiedliche Längen" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "Kann nicht im ROS-Thema veröffentlicht werden" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Konnte Adresse nicht setzen" @@ -850,6 +889,11 @@ msgstr "Interrupt konnte nicht gestartet werden, RX beschäftigt" msgid "Couldn't allocate decoder" msgstr "Decoder konnte nicht zugeordnet werden" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Kritischer ROS-Fehler beim Soft-Reboot, Reset erforderlich: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DAC-Kanal-Initialisierungsfehler" @@ -867,10 +911,6 @@ msgstr "DAC wird schon benutzt" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 pin muss am Byte ausgerichtet sein" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Dem fmt Block muss ein Datenblock folgen" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "Datenformatfehler (Möglicherweise beschädigte Daten)" @@ -895,7 +935,7 @@ msgstr "Die Zielkapazität ist kleiner als destination_length." #: shared-module/jpegio/JpegDecoder.c msgid "Device error or wrong termination of input stream" -msgstr "" +msgstr "Gerätefehler oder falsche Terminierung des Eingangsstroms" #: ports/nordic/common-hal/audiobusio/I2SOut.c msgid "Device in use" @@ -972,12 +1012,14 @@ msgstr "Mutex konnte nicht akquiriert werden. Status: 0x%04x" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Failed to add service TXT record" -msgstr "" +msgstr "Fehler beim Hinzufügen des TXT-Diensteintrags" #: shared-bindings/mdns/Server.c msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" +"Fehler beim Hinzufügen des TXT-Diensteintrags; Nicht-Zeichenfolge oder Bytes " +"in txt_records gefunden" #: shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" @@ -1004,15 +1046,49 @@ msgstr "Verbindung fehlgeschlagen: interner Fehler" msgid "Failed to connect: timeout" msgstr "Verbindung nicht erfolgreich: timeout" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" +"Kontinuierliche Kanäle konnten nicht erstellt werden: ungültiges Argument" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" +"Kontinuierliche Kanäle konnten nicht erstellt werden: ungültiger Status" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Kontinuierliche Kanäle konnten nicht erstellt werden: kein Speicher" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Kontinuierliche Kanäle konnten nicht erstellt werden: nicht gefunden" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Kontinuierliche Aktivierung fehlgeschlagen" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "MP3-Datei konnte nicht analysiert werden" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Rückruf für kontinuierliche Ereignisse konnte nicht registriert werden" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Mutex konnte nicht freigegeben werden. Status: 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Hostname konnte nicht gesetzt werden" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Start von asynchronem Audio fehlgeschlagen" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Interner Flash konnte nicht geschrieben werden." @@ -1021,12 +1097,14 @@ msgstr "Interner Flash konnte nicht geschrieben werden." msgid "File exists" msgstr "Datei existiert" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Datei nicht gefunden" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filter zu komplex" @@ -1051,7 +1129,7 @@ msgstr "Für den L8-Farbraum muss die Eingabe-Bitmap 8 Bit pro Pixel aufweisen" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "Für RGB-Farbräume muss die Eingabe-Bitmap 16 Bit pro Pixel haben" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Format nicht unterstützt" @@ -1083,7 +1161,7 @@ msgstr "Gruppe schon benutzt" #: supervisor/shared/safe_mode.c msgid "Hard fault: memory access or instruction error." -msgstr "" +msgstr "Harter Fehler: Speicherzugriff- oder Anweisungsfehler." #: ports/mimxrt10xx/common-hal/busio/SPI.c #: ports/mimxrt10xx/common-hal/busio/UART.c ports/stm/common-hal/busio/I2C.c @@ -1162,9 +1240,10 @@ msgstr "Unzureichender Speicherpool für das Bild" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient stream input buffer" -msgstr "" +msgstr "Unzureichender Stream-Eingabepuffer" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Schnittstelle muss gestartet sein" @@ -1210,22 +1289,26 @@ msgstr "Interrupt Fehler." msgid "Interrupted by output function" msgstr "Unterbrochen durch Ausgabefunktion" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Ungültiger %q" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "Ungültiges %q und %q" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1251,6 +1334,10 @@ msgstr "Ungültige BSSID" msgid "Invalid MAC address" msgstr "Ungültige MAC-Adresse" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "Ungültige ROS-Domain ID" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Ungültiges Argument" @@ -1282,6 +1369,7 @@ msgid "Invalid hex password" msgstr "Ungültiges Hex-Passwort" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Ungültige Multicast-MAC-Adresse" @@ -1294,6 +1382,7 @@ msgid "Invalid socket for TLS" msgstr "Ungültiges Socket für TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Ungültiger Zustand" @@ -1328,14 +1417,22 @@ msgstr "Ebene muss eine Gruppe oder eine TileGrid Subklasse sein" #: shared-bindings/audiocore/RawSample.c msgid "Length of %q must be an even multiple of channel_count * type_size" msgstr "" +"Die Länge von %q muss ein gerades Vielfaches von channel_count * type_size " +"sein" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC Adresse war ungültig" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" -msgstr "" +msgstr "MITM-Sicherheit wird nicht unterstützt" + +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "MMC/SDIO-Taktfehler %x" #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" @@ -1380,9 +1477,10 @@ msgstr "jmp_pin fehlt. %q[%u] springt basierend auf dem Pin" #: shared-module/storage/__init__.c msgid "Mount point directory missing" -msgstr "" +msgstr "Einhängepunktverzeichnis fehlt" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Muss eine %q Unterklasse sein." @@ -1522,6 +1620,10 @@ msgstr "Kein Pull-up gefunden an SDA oder SCL; Verkabelung prüfen" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Kein Pulldown-Widerstand am Pin; 1 MOhm wird vorgeschlagen" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Kein Pullup-Widerstand am Pin; 1Mohm wird vorgeschlagen" + #: py/moderrno.c msgid "No space left on device" msgstr "Kein Speicherplatz mehr verfügbar auf dem Gerät" @@ -1540,7 +1642,7 @@ msgstr "Kein Timer verfügbar" #: shared-module/usb/core/Device.c msgid "No usb host port initialized" -msgstr "" +msgstr "Kein USB-Host-Port initialisiert" #: ports/nordic/common-hal/_bleio/__init__.c msgid "Nordic system firmware out of memory" @@ -1566,9 +1668,10 @@ msgid "Not supported JPEG standard" msgstr "Nicht unterstützter JPEG-Standard" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Anzahl von data_pins muss 8 oder 16 sein, nicht %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Die Anzahl der data_pins muss %d oder %d sein, nicht %d" #: shared-bindings/util.c msgid "" @@ -1624,15 +1727,6 @@ msgstr "Nur Edge Detection ist für diese Hardware verfügbar" msgid "Only int or string supported for ip" msgstr "Nur Int oder String werden unterstützt für IP" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs " -"unterstützt: %d bpp wurden gegeben" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Nur ein %q kann im Deep-Sleep gesetzt werden." @@ -1683,6 +1777,7 @@ msgstr "Kein Speicher mehr verfügbar" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Keine Sockets mehr verfügbar" @@ -1702,6 +1797,11 @@ msgstr "PWM-Stück wird bereits verwendet" msgid "PWM slice channel A already in use" msgstr "PWM-Stück-Kanal A wird bereits verwendet" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" +"Die Paketpuffer für eine SPI-Übertragung müssen die gleiche Länge haben." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "Parameter-Fehler" @@ -1760,7 +1860,7 @@ msgstr "Pins muss ein geteiltes PWM-Stück sein" #: shared-module/usb/core/Device.c msgid "Pipe error" -msgstr "" +msgstr "Pipe-Fehler" #: py/builtinhelp.c msgid "Plus any modules on the filesystem\n" @@ -1807,6 +1907,10 @@ msgstr "Programm-Größe ist ungültig" msgid "Program too long" msgstr "Programm zu lang" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "Herausgeber können nur aus einem übergeordneten Knoten erstellt werden" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull wird nicht verwendet, wenn die Richtung output ist." @@ -1827,6 +1931,26 @@ msgstr "RNG DeInit-Fehler" msgid "RNG Init Error" msgstr "RNG-Init-Fehler" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "ROS konnte nicht initialisiert werden. Ist der Agent verbunden?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "ROS interner Setup-Fehler" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "ROS-Speicherzuweisungsfehler" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "ROS-Knoten konnte nicht initialisiert werden" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "ROS-Thema konnte nicht initialisiert werden" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1905,10 +2029,11 @@ msgstr "SDCard-Initialisierung" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo-Fehler %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO-Init-Fehler %d" +msgid "SDIO Init Error %x" +msgstr "SDIO-Init-Fehler %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1957,11 +2082,13 @@ msgstr "Slice und Wert (value) haben unterschiedliche Längen." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Slices werden nicht unterstützt" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool kann nur mit wifi.radio verwendet werden" @@ -1975,7 +2102,7 @@ msgstr "Gib genau einen von data0 oder data_pins an" #: supervisor/shared/safe_mode.c msgid "Stack overflow. Increase stack size." -msgstr "" +msgstr "Stapelüberlauf. Stapelgröße erhöhen." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" @@ -2004,22 +2131,9 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Die Länge von rgb_pins muss 6, 12, 18, 24 oder 30 betragen" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" -"Das bits_per_sample des Samples stimmt nicht mit dem des Mixers überein" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Die Kanalanzahl des Samples stimmt nicht mit der des Mischers überein" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Die Abtastrate der Probe stimmt nicht mit der des Mischers überein" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Der Vorzeichentyp des Samples stimmt nicht mit dem des Mixers überein" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "Der %q-Wert der Probe stimmt nicht überein" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2041,7 +2155,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Die Kachelhöhe muss die Bitmaphöhe genau teilen" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Kachelindex außerhalb der Grenzen" @@ -2049,6 +2165,10 @@ msgstr "Kachelindex außerhalb der Grenzen" msgid "Tile width must exactly divide bitmap width" msgstr "Die Kachelbreite muss die Bitmap-Breite genau teilen" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper darf nur einmal an ein TileGrid gebunden werden" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Zeit liegt in der Vergangenheit." @@ -2070,7 +2190,7 @@ msgstr "Zu viele Kanäle im sample." #: ports/espressif/common-hal/_bleio/Characteristic.c msgid "Too many descriptors" -msgstr "" +msgstr "Zu viele Deskriptoren" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" @@ -2149,7 +2269,7 @@ msgstr "Der UUID-Wert ist kein str-, int- oder Byte-Puffer" #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to access unaligned IO register" -msgstr "" +msgstr "Zugriff auf nicht ausgerichtetes EA-Register nicht möglich" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -2160,7 +2280,7 @@ msgstr "Konnte keine Buffer für Vorzeichenumwandlung allozieren" #: supervisor/shared/safe_mode.c msgid "Unable to allocate to the heap." -msgstr "" +msgstr "Die Zuweisung zum Heap ist nicht möglich." #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" @@ -2180,6 +2300,12 @@ msgstr "Parser konnte nicht gestartet werden" msgid "Unable to read color palette data" msgstr "Konnte Farbpalettendaten nicht lesen" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" +"CAN-Nachricht kann nicht gesendet werden: alle Sende-Nachrichtenpuffer sind " +"belegt" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2276,32 +2402,27 @@ msgstr "Nicht unterstützter Farbraum" msgid "Unsupported display bus type" msgstr "Nicht unterstützter display bus type" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Nicht unterstütztes Format" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Hash Algorithmus wird nicht unterstützt" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" -msgstr "" +msgstr "Nicht unterstützter Sockeltyp" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Aktualisierung fehlgeschlagen" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Länge des Wertes != Erforderliche feste Länge" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2345,9 +2466,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "WLAN ist nicht aktiviert" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi ist nicht aktiviert" #: main.c msgid "Woken up by alarm.\n" @@ -2369,6 +2492,7 @@ msgstr "Beide Knöpfe wurden beim Starten gedrückt." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Knopf A wurde beim Starten gedrückt." @@ -2382,6 +2506,7 @@ msgstr "Der BOOT-Knopf wurde beim Starten gedrückt" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "Der BOOT-Knopf wurde beim Starten gedrückt." @@ -2442,6 +2567,10 @@ msgstr "ein Byte-ähnliches Objekt ist erforderlich" msgid "addresses is empty" msgstr "addresses ist leer" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "spielt bereits" + #: py/compile.c msgid "annotation must be an identifier" msgstr "Die Annotation muss ein Bezeichner sein" @@ -2466,6 +2595,11 @@ msgstr "Das Argument argsort muss ein ndarray sein" msgid "argsort is not implemented for flattened arrays" msgstr "argsort ist für flattened Arrays nicht implementiert" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" +"Das Argument muss None, eine Ganzzahl oder ein Tupel von Ganzzahlen sein" + #: py/compile.c msgid "argument name reused" msgstr "Name des Arguments wiederverwendet" @@ -2498,7 +2632,7 @@ msgstr "Array/Bytes auf der rechten Seite erforderlich" #: py/asmxtensa.c msgid "asm overflow" -msgstr "" +msgstr "ASM-Überlauf" #: py/compile.c msgid "async for/with outside async function" @@ -2516,6 +2650,10 @@ msgstr "Versuch, argmin/argmax einer leeren Sequenz zu ermitteln" msgid "attributes not supported" msgstr "Attribute werden nicht unterstützt" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "Audioformat wird nicht unterstützt" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "Achse außerhalb des Wertebereichs" @@ -2552,6 +2690,10 @@ msgstr "Falscher Typcode" msgid "binary op %q not implemented" msgstr "Der binäre Operator %q ist nicht implementiert" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth muss 8, 16, 24 oder 32 sein." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "Bitmap-Größen und -Tiefe müssen übereinstimmen" @@ -2564,6 +2706,15 @@ msgstr "Bitmap-Größen müssen übereinstimmen" msgid "bits must be 32 or less" msgstr "bits müssen 32 oder kleiner sein" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample muss 16 sein" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "Es müssen 8 oder 16 bits_per_sample sein" @@ -2598,7 +2749,7 @@ msgstr "Der Puffer ist zu klein für die angefragten Bytes" #: py/emitbc.c msgid "bytecode overflow" -msgstr "" +msgstr "Bytecode-Überlauf" #: py/objarray.c msgid "bytes length not a multiple of item size" @@ -2647,7 +2798,7 @@ msgstr "kann keinem Ausdruck zuweisen" msgid "can't cancel self" msgstr "kann self nicht abbrechen" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kann %q nicht zu %q konvertieren" @@ -2702,6 +2853,10 @@ msgstr "Ausdruck kann nicht gelöscht werden" msgid "can't do binary op between '%q' and '%q'" msgstr "Eine binäre Operation zwischen '%q' und '%q' ist nicht möglich" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "kann keine unäre Operation von '%q' durchführen" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "Kann '%q' nicht implizit nach 'bool' konvertieren" @@ -2768,11 +2923,7 @@ msgstr "" #: py/objcomplex.c msgid "can't truncate-divide a complex number" -msgstr "" - -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" +msgstr "kann eine komplexe Zahl nicht kürzen und dividieren" #: extmod/modasyncio.c msgid "can't wait" @@ -3116,7 +3267,7 @@ msgid "format" msgstr "Format" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "Format erfordert ein Wörterbuch (dict)" #: py/objdeque.c @@ -3166,7 +3317,8 @@ msgstr "Funktion vermisst benötigtes Schlüsselwort-Argumente '%q'" msgid "function missing required positional argument #%d" msgstr "Funktion vermisst benötigtes Argumente ohne Schlüsselwort #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3211,7 +3363,7 @@ msgstr "import * nicht auf Modulebene" #: py/persistentcode.c msgid "incompatible .mpy arch" -msgstr "" +msgstr "inkompatible .mpy-Architektur" #: py/persistentcode.c msgid "incompatible .mpy file" @@ -3251,10 +3403,6 @@ msgstr "Indizes müssen Integer sein" msgid "indices must be integers, slices, or Boolean lists" msgstr "Indizes müssen Integer, Slices oder Boolesche Listen sein" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "initialisiere I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "Ausgangswerte müssen iterierbar sein" @@ -3320,7 +3468,7 @@ msgstr "Eingabe muss ein 1D ndarray sein" msgid "input must be a dense ndarray" msgstr "Eingabe muss ein dichtes ndarray sein" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "Eingabe muss ein ndarray sein" @@ -3355,7 +3503,7 @@ msgstr "Das Intervall muss im Bereich %s-%s sein" #: py/compile.c msgid "invalid arch" -msgstr "" +msgstr "ungültige Architektur" #: shared-bindings/bitmaptools/__init__.c #, c-format @@ -3442,6 +3590,8 @@ msgstr "" #: py/argcheck.c msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" +"Schlüsselwortargument(e) nicht umgesetzt - nutze stattdessen normale " +"Argumente" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3451,10 +3601,6 @@ msgstr "Label '%q' nicht definiert" msgid "label redefined" msgstr "Label neu definiert" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "Der Pegel muss zwischen 0 und 1 liegen" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs und rhs sollten kompatibel sein" @@ -3510,7 +3656,7 @@ msgstr "Matrix ist nicht positiv definitiv" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length muss 0-%d sein, wenn fixed_length %s ist" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "Maximale Anzahl an Dimensionen ist " @@ -3588,7 +3734,7 @@ msgid "must use keyword argument for key function" msgstr "muss Schlüsselwortargument für key function verwenden" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "Name '%q' ist nirgends definiert worden (Schreibweise kontrollieren)" #: py/runtime.c @@ -3597,7 +3743,7 @@ msgstr "Dieser Name ist nirgends definiert worden (Schreibweise kontrollieren)" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "Name zu lang" #: py/persistentcode.c msgid "native code in .mpy unsupported" @@ -3652,7 +3798,7 @@ msgstr "Keine Bindung für nichtlokale Variable gefunden" msgid "no default packer" msgstr "kein Standard-Packer" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "kein Standard-Seed" @@ -3867,6 +4013,10 @@ msgstr "" msgid "out array is too small" msgstr "Ausgabe-Array ist zu klein" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "Ausgabe hat den falschen Typ" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "out-Schlüsselwort wird nicht unterstützt für komplexen dtype" @@ -3891,6 +4041,14 @@ msgstr "out muss vom Typ dtype sein" msgid "out of range of target" msgstr "Außerhalb des Bereichs des Ziels" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "Ausgabe-Array hat einen falschen Typ" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "Ausgabe-Array muss zusammenhängend sein" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "Überlauf beim konvertieren von long int zu machine word" @@ -3935,11 +4093,11 @@ msgstr "Port muss >= 0 sein" #: py/compile.c msgid "positional arg after **" -msgstr "" +msgstr "Positionsargument nach **" #: py/compile.c msgid "positional arg after keyword arg" -msgstr "" +msgstr "Positionsargument nach Schlüsselwortargument" #: py/objint_mpz.c msgid "pow() 3rd argument cannot be 0" @@ -4000,6 +4158,10 @@ msgstr "Roll-Argument muss ein ndarray sein" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed muss wahr sein" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4017,6 +4179,10 @@ msgstr "kompilieren von Skripten nicht unterstützt" msgid "set unsupported" msgstr "nicht unterstützt" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "Form muss Keine, eine Ganzzahl oder ein Tupel von Ganzenahlen sein" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "Form muss eine Ganzzahl oder ein Tupel von Ganzzahlen sein" @@ -4037,6 +4203,10 @@ msgstr "Vorzeichen mit ganzzahligem Formatbezeichner 'c' nicht erlaubt" msgid "size is defined for ndarrays only" msgstr "Größe ist nur für ndarrays definiert" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "size muss bei gemeinsamer Verwendung mit out.shape übereinstimmen" + #: py/nativeglue.c msgid "slice unsupported" msgstr "Slice nicht unterstützt" @@ -4083,7 +4253,7 @@ msgstr "source_bitmap muss value_count von 8 haben" #: extmod/modre.c msgid "splitting with sub-captures" -msgstr "" +msgstr "Aufteilung mit Untererfassungen" #: py/objstr.c msgid "start/end indices" @@ -4110,18 +4280,6 @@ msgstr "String index außerhalb des Bereiches" msgid "string indices must be integers, not %s" msgstr "String indizes müssen Integer sein, nicht %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct: kann nicht indiziert werden" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index außerhalb gültigen Bereichs" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: keine Felder" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "substring nicht gefunden" @@ -4134,13 +4292,9 @@ msgstr "super() kann self nicht finden" msgid "syntax error in JSON" msgstr "Syntaxfehler in JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "Syntaxfehler in uctypes Deskriptor" - #: extmod/modtime.c msgid "ticks interval overflow" -msgstr "" +msgstr "Ticks Intervallüberlauf" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" @@ -4152,12 +4306,12 @@ msgstr "timeout muss kleiner als 655.35 Sekunden sein" #: ports/raspberrypi/common-hal/floppyio/__init__.c msgid "timeout waiting for flux" -msgstr "" +msgstr "Zeitüberschreitung beim Warten auf Fluss" #: ports/raspberrypi/common-hal/floppyio/__init__.c #: shared-module/floppyio/__init__.c msgid "timeout waiting for index pulse" -msgstr "" +msgstr "Zeitüberschreitung beim Warten auf Indeximpuls" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" @@ -4227,11 +4381,11 @@ msgid "tx and rx cannot both be None" msgstr "tx und rx können nicht beide None sein" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "Typ '%q' ist kein akzeptierter Basis-Typ" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "Typ ist kein akzeptierter Basis-Typ" #: py/runtime.c @@ -4246,10 +4400,6 @@ msgstr "Typ akzeptiert 1 oder 3 Argumente" msgid "ulonglong too large" msgstr "ulonglong zu groß" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "Der unäre Operator %q ist nicht implementiert" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4299,7 +4449,9 @@ msgstr "'%c' in Format konnte nicht zugeordnet werden" msgid "unreadable attribute" msgstr "nicht lesbares Attribut" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "Nicht unterstützter %q-Typ" @@ -4379,11 +4531,6 @@ msgstr "Gewichte müssen ein Objekt des Typs %q, %q, %q, or %q, not %q sein " msgid "width must be greater than zero" msgstr "Breite muss größer als 0 sein" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "wifi ist nicht aktiviert" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wifi.Monitor nicht verfügbar" @@ -4446,6 +4593,82 @@ msgstr "zi muss eine Gleitkommazahl sein" msgid "zi must be of shape (n_section, 2)" msgstr "zi muss die Form (n_section, 2) haben" +#~ msgid "Unsupported format" +#~ msgstr "Nicht unterstütztes Format" + +#~ msgid "Wifi is not enabled" +#~ msgstr "WLAN ist nicht aktiviert" + +#~ msgid "wifi is not enabled" +#~ msgstr "wifi ist nicht aktiviert" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "'/' kann nicht wiedereingehängt werden, wenn per USB sichtbar." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q muss ein %q Objekt, %q, oder %q sein" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Dem fmt Block muss ein Datenblock folgen" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Nur monochrome, indizierte 4bpp oder 8bpp, und 16bpp oder größere BMPs " +#~ "unterstützt: %d bpp wurden gegeben" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "Der Pegel muss zwischen 0 und 1 liegen" + +#~ msgid "init I2C" +#~ msgstr "initialisiere I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "" +#~ "Das bits_per_sample des Samples stimmt nicht mit dem des Mixers überein" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "" +#~ "Die Kanalanzahl des Samples stimmt nicht mit der des Mischers überein" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Die Abtastrate der Probe stimmt nicht mit der des Mischers überein" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "" +#~ "Der Vorzeichentyp des Samples stimmt nicht mit dem des Mixers überein" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Die Pufferlänge muss ein vielfaches von 512 sein" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Der Puffer muss ein vielfaches von 512 bytes sein" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Anzahl von data_pins muss 8 oder 16 sein, nicht %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO-Init-Fehler %d" + +#~ msgid "struct: can't index" +#~ msgstr "struct: kann nicht indiziert werden" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index außerhalb gültigen Bereichs" + +#~ msgid "struct: no fields" +#~ msgstr "struct: keine Felder" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "Syntaxfehler in uctypes Deskriptor" + +#~ msgid "unary op %q not implemented" +#~ msgstr "Der unäre Operator %q ist nicht implementiert" + #~ msgid "Name too long" #~ msgstr "Name zu lang" @@ -4719,13 +4942,13 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' Objekt unterstützt das Löschen von Elementen nicht" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' Objekt ist kein Iterator" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' object ist nicht aufrufbar" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' Objekt nicht iterierbar" #~ msgid "'%s' object is not subscriptable" @@ -4744,7 +4967,7 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "'continue' outside loop" #~ msgstr "'continue' außerhalb einer Schleife" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "'coroutine' Objekt ist kein Iterator" #~ msgid "(x,y) integers required" @@ -6114,7 +6337,7 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "frequency is read-only for this board" #~ msgstr "Frequenz ist für dieses Board schreibgeschützt" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "Funktion akzeptiert keine Schlüsselwort-Argumente" #~ msgid "function is implemented for scalars and ndarrays only" @@ -6228,7 +6451,7 @@ msgstr "zi muss die Form (n_section, 2) haben" #~ msgid "name must be a string" #~ msgstr "name muss ein String sein" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "Name für Argumente wiederverwendet" #~ msgid "no available NIC" diff --git a/locale/el.po b/locale/el.po index f88fc9211b701..f298c5c17e32f 100644 --- a/locale/el.po +++ b/locale/el.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-12-04 01:08+0000\n" -"Last-Translator: Bill Sideris \n" +"PO-Revision-Date: 2025-06-29 13:02+0000\n" +"Last-Translator: MAE \n" "Language-Team: none\n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.3-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -83,8 +83,8 @@ msgstr " έξοδος:\n" #: py/objstr.c #, c-format -msgid "%%c requires int or char" -msgstr "%%c απαιτεί ακέραιο ή χαρακτήρα" +msgid "%%c needs int or char" +msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -93,11 +93,16 @@ msgid "" msgstr "" "%d pin διεύθυνσης, %d rgb ping και %d πλακίδια αναδεικνύουν ύψος %d, όχι %d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q και %q περιέχουν διπλότυπα pins" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q και %q πρεπει να είναι διαφορετικά" @@ -114,14 +119,21 @@ msgid "%q contains duplicate pins" msgstr "%q περιέχει διπλότυπα pins" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q αποτυχία: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q στο %q πρέπει να είναι τύπου %q, όχι %q" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -129,7 +141,8 @@ msgstr "%q στο %q πρέπει να είναι τύπου %q, όχι %q" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "%q είναι σε χρήση" @@ -141,7 +154,9 @@ msgstr "%q δείκτης εκτός εμβέλειας" msgid "%q indices must be integers, not %s" msgstr "%q δείκτες πρέπει να είναι ακέραιοι, όχι %s" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q εκκίνηση απέτυχε" @@ -169,16 +184,12 @@ msgstr "%q μήκος πρέπει να είναι <= %d" msgid "%q length must be >= %d" msgstr "%q μήκος πρέπει να είναι >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "%q μετακινήθηκε από το %q στο %q" - #: py/argcheck.c msgid "%q must be %d" msgstr "%q πρέπει να είναι %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -229,6 +240,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q πρέπει να είναι τύπου %q ή %q, όχι %q" @@ -238,6 +250,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q πρέπει να είναι τύπου %q, όχι %q" @@ -246,23 +259,29 @@ msgstr "%q πρέπει να είναι τύπου %q, όχι %q" msgid "%q must be power of 2" msgstr "%q πρέπει να είναι δύναμη του 2" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "%q εκτός ορίων" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "%q εκτός εμβέλειας" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "%q μεταονομάστηκε σε %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q βήμα δεν μπορεί να είναι μηδέν" @@ -283,7 +302,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, και %q πρέπει να είναι όλα του ιδίου μήκους" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -312,20 +332,20 @@ msgstr "%s σφάλμα 0x%x" msgid "'%q' argument required" msgstr "'%q' όρισμα απαιτείται" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "'%q' αντικείμενο δεν υποστηρίζει '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "'%q' αντικείμενο δεν είναι επαναλήπτης" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" -msgstr "'%q' αντικείμενο δεν καλείται" +msgid "'%q' object isn't callable" +msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "'%q' αντικείμενο δεν είναι επαναληπτικό" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -429,6 +449,10 @@ msgstr "'data' απαιτεί ακέραιες παραμέτρους" msgid "'label' requires 1 argument" msgstr "'label' απαιτεί ένα όρισμα" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' εκτός συνάρτησης" @@ -453,6 +477,7 @@ msgstr "*x πρέπει να είναι στόχος ανάθεσης" msgid ", in %q\n" msgstr ", στο %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -471,7 +496,7 @@ msgstr "pow() με 3 παραμέτρους δεν υποστηρίζεται" msgid "AP could not be started" msgstr "AP δεν μπόρεσε να εκκινηθεί" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Η διεύθυνση πρέπει να είναι %d bytes μεγάλη" @@ -506,7 +531,8 @@ msgstr "Όλα τα RX FIFOs είναι σε χρήση" msgid "All SPI peripherals are in use" msgstr "Όλα τα SPI περιφεριακά είναι σε χρήση" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Όλα τα UART περιφεριακά ειναι σε χρήση" @@ -548,7 +574,6 @@ msgstr "Όλοι οι χρονιστές για αυτό το pin χρησιμο #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Όλοι οι χρονιστές βρίσκονται σε χρήση" @@ -561,6 +586,10 @@ msgstr "Ήδη διαφημίζουμε." msgid "Already have all-matches listener" msgstr "Ύπάρχει ήδη all-matches ακροατής" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,10 +599,11 @@ msgstr "Τρέχει ήδη" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Ήδη γίνεται σάρωση για δίκτυα wifi" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "Παρουσιάστηκε σφάλμα κατά την ανάκτηση '%s':\n" @@ -596,6 +626,10 @@ msgstr "H παράταξη πρέπει να περιέχει halfwords (τύπ msgid "Array values should be single bytes." msgstr "Η τιμές της παράταξη πρέπει να είναι μονά bytes." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +639,12 @@ msgstr "Προσπάθεια να δεσμευτούν %d blocks" msgid "Audio conversion not implemented" msgstr "Η μετατροπή ήχου δεν υποστηρίζεται" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN δεν μπορεί να χρησιμοποιηθεί με κωδικό" @@ -629,6 +669,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudrate δεν υποστηρίζεται από την περιφεριακή συσκευή" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -646,20 +687,17 @@ msgstr "Το μέγεθος του bitmap και τα bits ανα τιμή πρ msgid "Boot device must be first (interface #0)." msgstr "Η συσκευή εκκίνησης πρέπει να επιλεχθεί πρώτα (διεπαφή #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Και RX και TX απαιτούνται για έλεγχο flow" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "H φωτεινότητα δεν μπορεί να προσαρμοστεί" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset είναι πολύ μικρά %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Στοιχεία του buffer πρέπει να είναι το πολύ 4 bytes" @@ -674,13 +712,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Το μήκος buffer %d είναι πολύ μεγάλο. Πρέπει ν α είναι λιγότερο απο %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Το μήκος buffer πρέπει να είναι πολλαπλάσιο του 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Buffer πρέπει να είναι πολλαπλάσιο των 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -702,10 +740,6 @@ msgstr "Buffer πολύ μικρός" msgid "Bus pin %d is already in use" msgstr "Bus pin %d είναι ήδη σε χρήση" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Byte buffer πρέπει να είναι 16 bytes." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC blocks πρέπει να είναι πολλαπλάσια του 16 bytes" @@ -739,6 +773,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "Μπορεί να γίνει alarm μόνο σε δύο low pins σε βαθύ ύπνο." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -755,6 +793,10 @@ msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "" "Δεν μπορεί να δημιουργηθεί νέο Adapter; χρησιμοποιείστε _bleio.adapter;" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -787,10 +829,11 @@ msgid "Cannot record to a file" msgstr "Δεν μπορεί να γίνει καταγραφή σε αρχείο" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Δεν μπορεί να γίνει remount του '/' όταν είναι ορατό μέσω USB." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "Δεν μπορεί να οριστεί τιμή οταν η κατεύθυνση είναι input." @@ -803,6 +846,10 @@ msgstr "Δεν μπορεί να οριστεί RTS ή CTS σε RS485 mode" msgid "Cannot subclass slice" msgstr "Δεν γίνεται υποκατηγορία ενός slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Δεν γίνεται αφύπνηση σε pin edge, αλλά μόνο σε level" @@ -839,6 +886,14 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Δεν μπόρεσε να ρυθμιστεί η διεύθυνση" @@ -851,6 +906,11 @@ msgstr "Δεν μπόρεσε να εκκινηθεί το interrupt, RX κατ msgid "Couldn't allocate decoder" msgstr "Δεν μπόρεσε να δεσμευτεί decoder" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Σφάλμα εκκίνησης καναλιού DAC" @@ -868,10 +928,6 @@ msgstr "DAC είναι ήδη σε χρήση" msgid "Data 0 pin must be byte aligned" msgstr "Το Data 0 pin πρέπει να είναι byte aligned" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Το data chunk πρέπει να ακολουθεί το fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -912,6 +968,7 @@ msgstr "Η οθόνη πρέπει να έχει 16 bit χρωματική ευ #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "Η περιστροφή της οθόνη πρέπει να γίνεται σε βήματα 90 μοιρών" @@ -920,6 +977,7 @@ msgid "Done" msgstr "Ολοκληρώθηκε" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "Ο τρόπος οδήγησης δεν χρησιμοποιείται όταν η κατεύθυνση είναι είσοδος." @@ -932,8 +990,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB δουλεύει μόνο σε 16 bytes κάθε φορά" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF δέσμευση μνήμης απέτυχε" @@ -980,7 +1047,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -998,22 +1065,60 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "" @@ -1022,12 +1127,13 @@ msgstr "" msgid "File exists" msgstr "" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1052,7 +1158,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "" @@ -1074,6 +1180,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1160,6 +1267,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1171,7 +1279,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1205,18 +1314,29 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1246,6 +1366,14 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1254,17 +1382,12 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "" @@ -1277,6 +1400,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1288,11 +1412,13 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "" @@ -1300,10 +1426,6 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "" @@ -1329,13 +1451,23 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1424,7 +1556,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1442,6 +1574,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1517,6 +1650,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -1552,17 +1689,14 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1615,13 +1749,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1659,6 +1786,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1672,6 +1800,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1691,6 +1820,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1790,7 +1923,12 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "" @@ -1810,10 +1948,31 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1888,9 +2047,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1901,6 +2061,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -1940,6 +2104,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1948,6 +2113,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -1984,20 +2153,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -2018,7 +2175,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2026,6 +2185,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2036,11 +2199,16 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2079,6 +2247,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2087,6 +2259,14 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" @@ -2111,10 +2291,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2131,6 +2307,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2139,6 +2316,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "" @@ -2156,6 +2334,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2240,6 +2422,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "" @@ -2248,15 +2434,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2265,15 +2448,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2307,10 +2495,12 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2333,6 +2523,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2346,6 +2537,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2402,10 +2594,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2430,6 +2630,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2460,10 +2664,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2480,6 +2680,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2516,6 +2720,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2528,6 +2736,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "" @@ -2585,6 +2802,10 @@ msgstr "" msgid "can only have one parent" msgstr "" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2609,7 +2830,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2652,6 +2873,14 @@ msgstr "" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2664,6 +2893,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2726,10 +2959,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2750,18 +2979,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -2916,7 +3141,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3015,10 +3240,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3059,16 +3280,20 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3118,7 +3343,8 @@ msgstr "" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3135,10 +3361,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3201,18 +3423,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3270,7 +3484,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3303,6 +3517,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3399,10 +3617,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3456,7 +3670,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3501,6 +3715,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3534,7 +3752,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3549,10 +3767,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3574,7 +3788,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3598,7 +3812,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3624,7 +3838,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3643,14 +3857,6 @@ msgstr "" msgid "not a constant" msgstr "" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "" @@ -3659,6 +3865,10 @@ msgstr "" msgid "not supported for input types" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3672,6 +3882,10 @@ msgstr "" msgid "object '%s' isn't a tuple or list" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3713,10 +3927,6 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "" @@ -3765,6 +3975,30 @@ msgstr "" msgid "opcode" msgstr "" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3807,6 +4041,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3831,6 +4069,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3840,8 +4086,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3893,14 +4139,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3910,6 +4156,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3940,6 +4190,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3957,6 +4211,10 @@ msgstr "" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3977,6 +4235,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4025,10 +4287,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4050,18 +4308,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4074,10 +4320,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4167,11 +4409,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4182,14 +4424,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4237,7 +4471,9 @@ msgstr "" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "" @@ -4315,11 +4551,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4382,6 +4613,38 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q renamed %q" +#~ msgstr "%q μεταονομάστηκε σε %q" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset είναι πολύ μικρά %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Byte buffer πρέπει να είναι 16 bytes." + +#~ msgid "%q moved from %q to %q" +#~ msgstr "%q μετακινήθηκε από το %q στο %q" + +#, c-format +#~ msgid "%%c requires int or char" +#~ msgstr "%%c απαιτεί ακέραιο ή χαρακτήρα" + +#~ msgid "'%q' object is not callable" +#~ msgstr "'%q' αντικείμενο δεν καλείται" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Δεν μπορεί να γίνει remount του '/' όταν είναι ορατό μέσω USB." + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Το data chunk πρέπει να ακολουθεί το fmt chunk" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Το μήκος buffer πρέπει να είναι πολλαπλάσιο του 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Buffer πρέπει να είναι πολλαπλάσιο των 512 bytes" + #~ msgid "Error: Failure to bind" #~ msgstr "Σφάλμα: Αποτυχία δέσμευσης" @@ -4490,7 +4753,7 @@ msgstr "" #~ msgid "'continue' outside loop" #~ msgstr "'continue' εκτός επανάληψης" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "" #~ "'coroutine' αντικείμενο δεν μπορεί να χρησιμοποιηθεί σαν επαναλήπτης" diff --git a/locale/en_GB.po b/locale/en_GB.po index 149aff76f4844..8d640a3c68058 100644 --- a/locale/en_GB.po +++ b/locale/en_GB.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-08-10 14:09+0000\n" +"PO-Revision-Date: 2025-06-15 23:04+0000\n" "Last-Translator: Andi Chandler \n" "Language-Team: none\n" "Language: en_GB\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.7-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: main.c msgid "" @@ -95,7 +95,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q and %q contain duplicate pins" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q and %q must be different" @@ -115,7 +115,11 @@ msgstr "%q contains duplicate pins" msgid "%q failure: %d" msgstr "%q failure: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q in %q must be of type %q or %q, not %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q in %q must be of type %q, not %q" @@ -167,7 +171,7 @@ msgstr "%q length must be <= %d" msgid "%q length must be >= %d" msgstr "%q length must be >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q moved from %q to %q" @@ -227,6 +231,7 @@ msgstr "%q must be multiple of 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q must be of type %q or %q, not %q" @@ -236,6 +241,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q must be of type %q, %q, or %q, not %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q must be of type %q, not %q" @@ -281,7 +287,8 @@ msgstr "%q() without %q()" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, and %q must all be the same length" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -315,16 +322,16 @@ msgid "'%q' object does not support '%q'" msgstr "'%q' object does not support '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" -msgstr "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" +msgstr "'%q' object isn't an iterator" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c msgid "'%q' object is not callable" msgstr "'%q' object is not callable" #: py/runtime.c -msgid "'%q' object is not iterable" -msgstr "'%q' object is not iterable" +msgid "'%q' object isn't iterable" +msgstr "'%q' object isn't iterable" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format @@ -427,6 +434,10 @@ msgstr "'data' requires integer arguments" msgid "'label' requires 1 argument" msgstr "'label' requires 1 argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' not implemented" + #: py/compile.c msgid "'return' outside function" msgstr "'return' outside function" @@ -546,7 +557,6 @@ msgstr "All timers for this pin are in use" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "All timers in use" @@ -559,6 +569,10 @@ msgstr "Already advertising." msgid "Already have all-matches listener" msgstr "Already have all-matches listener" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Already in progress" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -568,6 +582,7 @@ msgstr "Already running" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Already scanning for WiFi networks" @@ -594,6 +609,10 @@ msgstr "Array must contain halfwords (type 'H')" msgid "Array values should be single bytes." msgstr "Array values should be single bytes." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "Async SPI transfer in progress on this bus, keep awaiting." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -603,6 +622,11 @@ msgstr "Attempt to allocate %d blocks" msgid "Audio conversion not implemented" msgstr "Audio conversion not implemented" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Audio source error" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN is not used with password" @@ -672,13 +696,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Buffer length %d too big. It must be less than %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Buffer length must be a multiple of 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Buffer must be a multiple of 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Buffer must be a multiple of %d bytes" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -736,6 +760,10 @@ msgstr "Can only alarm on one low pin while others alarm high from deep sleep." msgid "Can only alarm on two low pins from deep sleep." msgstr "Can only alarm on two low pins from deep sleep." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "Can't construct AudioOut because continuous channel already open" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -781,8 +809,8 @@ msgid "Cannot record to a file" msgstr "Cannot record to a file" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." +msgstr "Cannot remount path when visible via USB." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -797,6 +825,10 @@ msgstr "Cannot specify RTS or CTS in RS485 mode" msgid "Cannot subclass slice" msgstr "Cannot subclass slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "Cannot use GPIO0..15 together with GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Cannot wake on pin edge, only level" @@ -833,6 +865,10 @@ msgstr "Coordinate arrays have different lengths" msgid "Coordinate arrays types have different sizes" msgstr "Coordinate arrays types have different sizes" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "Could not publish to ROS topic" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Could not set address" @@ -845,6 +881,11 @@ msgstr "Could not start interrupt, RX busy" msgid "Couldn't allocate decoder" msgstr "Couldn't allocate decoder" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Critical ROS failure during soft reboot, reset required: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DAC channel init error" @@ -862,10 +903,6 @@ msgstr "DAC already in use" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 pin must be byte aligned" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Data chunk must follow fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "Data format error (may be broken data)" @@ -997,15 +1034,47 @@ msgstr "Failed to connect: internal error" msgid "Failed to connect: timeout" msgstr "Failed to connect: timeout" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Failed to create continuous channels: invalid arg" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Failed to create continuous channels: invalid state" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Failed to create continuous channels: no mem" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Failed to create continuous channels: not found" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Failed to enable continuous" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Failed to parse MP3 file" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Failed to register continuous events callback" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Failed to release mutex, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Failed to set hostname" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Failed to start async audio" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Failed to write internal flash." @@ -1014,12 +1083,14 @@ msgstr "Failed to write internal flash." msgid "File exists" msgstr "File exists" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "File not found" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filters too complex" @@ -1044,7 +1115,7 @@ msgstr "For L8 colourspace, input bitmap must have 8 bits per pixel" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "For RGB colourspaces, input bitmap must have 16 bits per pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Format not supported" @@ -1153,6 +1224,7 @@ msgid "Insufficient stream input buffer" msgstr "Insufficient stream input buffer" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Interface must be started" @@ -1198,15 +1270,19 @@ msgstr "Interrupt error." msgid "Interrupted by output function" msgstr "Interrupted by output function" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Invalid %q" @@ -1239,6 +1315,10 @@ msgstr "Invalid BSSID" msgid "Invalid MAC address" msgstr "Invalid MAC address" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "Invalid ROS domain ID" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Invalid argument" @@ -1270,6 +1350,7 @@ msgid "Invalid hex password" msgstr "Invalid hex password" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Invalid multicast MAC address" @@ -1282,6 +1363,7 @@ msgid "Invalid socket for TLS" msgstr "Invalid socket for TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Invalid state" @@ -1322,9 +1404,15 @@ msgid "MAC address was invalid" msgstr "MAC address was invalid" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "MITM security is not supported" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "MMC/SDIO Clock Error %x" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "Mapping must be a tuple" @@ -1370,7 +1458,8 @@ msgstr "Missing jmp_pin. %q[%u] jumps on pin" msgid "Mount point directory missing" msgstr "Mount point directory missing" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Must be a %q subclass." @@ -1510,6 +1599,10 @@ msgstr "No pull up found on SDA or SCL; check your wiring" msgid "No pulldown on pin; 1Mohm recommended" msgstr "No pulldown on pin; 1Mohm recommended" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "No pullup on pin; 1Mohm recommended" + #: py/moderrno.c msgid "No space left on device" msgstr "No space left on device" @@ -1554,9 +1647,10 @@ msgid "Not supported JPEG standard" msgstr "Not supported JPEG standard" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Number of data_pins must be %d or %d, not %d" #: shared-bindings/util.c msgid "" @@ -1610,15 +1704,6 @@ msgstr "Only edge detection is available on this hardware" msgid "Only int or string supported for ip" msgstr "Only int or string supported for ip" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Only one %q can be set in deep sleep." @@ -1669,6 +1754,7 @@ msgstr "Out of memory" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Out of sockets" @@ -1688,6 +1774,10 @@ msgstr "PWM slice already in use" msgid "PWM slice channel A already in use" msgstr "PWM slice channel A already in use" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "Packet buffers for an SPI transfer must have the same length." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "Parameter error" @@ -1788,6 +1878,10 @@ msgstr "Program size invalid" msgid "Program too long" msgstr "Program too long" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "Publishers can only be created from a parent node" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull not used when direction is output." @@ -1808,6 +1902,26 @@ msgstr "RNG deinit Error" msgid "RNG Init Error" msgstr "RNG init Error" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "ROS failed to initialise. Is agent connected?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "ROS internal setup failure" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "ROS memory allocator failure" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "ROS node failed to initialise" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "ROS topic failed to initialise" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1886,10 +2000,11 @@ msgstr "SDCard init" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo error %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO init error %d" +msgid "SDIO Init Error %x" +msgstr "SDIO Init Error %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1938,11 +2053,13 @@ msgstr "Slice and value different lengths." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Slices not supported" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool can only be used with wifi.radio" @@ -1982,21 +2099,9 @@ msgstr "The above exception was the direct cause of the following exception:" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "The length of rgb_pins must be 6, 12, 18, 24, or 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "The sample's bits_per_sample does not match the mixer's" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "The sample's channel count does not match the mixer's" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "The sample's sample rate does not match the mixer's" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "The sample's %q does not match" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2018,7 +2123,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Tile height must exactly divide bitmap height" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Tile index out of bounds" @@ -2026,6 +2133,10 @@ msgstr "Tile index out of bounds" msgid "Tile width must exactly divide bitmap width" msgstr "Tile width must exactly divide bitmap width" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper may only be bound to a TileGrid once" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Time is in the past." @@ -2156,6 +2267,10 @@ msgstr "Unable to init parser" msgid "Unable to read color palette data" msgstr "Unable to read colour palette data" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "Unable to send CAN Message: all Tx message buffers are busy" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2250,15 +2365,12 @@ msgstr "Unsupported colourspace" msgid "Unsupported display bus type" msgstr "Unsupported display bus type" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Unsupported format" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Unsupported hash algorithm" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "Unsupported socket type" @@ -2268,14 +2380,12 @@ msgid "Update failed" msgstr "Update failed" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Value length != required fixed length" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2316,9 +2426,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi is not enabled" #: main.c msgid "Woken up by alarm.\n" @@ -2340,6 +2452,7 @@ msgstr "You pressed both buttons at start up." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "You pressed button A at start up." @@ -2353,6 +2466,7 @@ msgstr "You pressed the BOOT button at start up" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "You pressed the BOOT button at start up." @@ -2413,6 +2527,10 @@ msgstr "a bytes-like object is required" msgid "addresses is empty" msgstr "addresses is empty" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "already playing" + #: py/compile.c msgid "annotation must be an identifier" msgstr "annotation must be an identifier" @@ -2437,6 +2555,10 @@ msgstr "argsort argument must be an ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort is not implemented for flattened arrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "argument must be None, an integer or a tuple of integers" + #: py/compile.c msgid "argument name reused" msgstr "argument name reused" @@ -2487,6 +2609,10 @@ msgstr "attempt to get argmin/argmax of an empty sequence" msgid "attributes not supported" msgstr "attributes not supported" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "audio format not supported" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "axis is out of bounds" @@ -2523,6 +2649,10 @@ msgstr "bad typecode" msgid "binary op %q not implemented" msgstr "binary op %q not implemented" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth must be 8, 16, 24, or 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "bitmap size and depth must match" @@ -2535,6 +2665,15 @@ msgstr "bitmap sizes must match" msgid "bits must be 32 or less" msgstr "bits must be 32 or less" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample must be 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample must be 8 or 16" @@ -2616,7 +2755,7 @@ msgstr "Can't assign to expression" msgid "can't cancel self" msgstr "can't cancel self" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "Can't convert %q to %q" @@ -2671,6 +2810,10 @@ msgstr "Can't delete expression" msgid "can't do binary op between '%q' and '%q'" msgstr "Can't do binary op between '%q' and '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "can't do unary op of '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "can't implicitly convert '%q' to 'bool'" @@ -2735,10 +2878,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "can't truncate-divide a complex number" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "can't unambiguously get sizeof scalar" - #: extmod/modasyncio.c msgid "can't wait" msgstr "can't wait" @@ -3078,8 +3217,8 @@ msgid "format" msgstr "format" #: py/objstr.c -msgid "format requires a dict" -msgstr "format requires a dict" +msgid "format needs a dict" +msgstr "format needs a dict" #: py/objdeque.c msgid "full" @@ -3128,7 +3267,8 @@ msgstr "function missing required keyword argument '%q'" msgid "function missing required positional argument #%d" msgstr "function missing required positional argument #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "function takes %d positional arguments but %d were given" @@ -3211,10 +3351,6 @@ msgstr "indices must be integers" msgid "indices must be integers, slices, or Boolean lists" msgstr "indices must be integers, slices, or Boolean lists" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "init I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "initial values must be iterable" @@ -3280,7 +3416,7 @@ msgstr "input must be a 1D ndarray" msgid "input must be a dense ndarray" msgstr "input must be a dense ndarray" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "input must be an ndarray" @@ -3409,10 +3545,6 @@ msgstr "label '%q' not defined" msgid "label redefined" msgstr "label redefined" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "level must be between 0 and 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs and rhs should be compatible" @@ -3466,7 +3598,7 @@ msgstr "matrix is not positive definite" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length must be 0-%d when fixed_length is %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "maximum number of dimensions is " @@ -3544,8 +3676,8 @@ msgid "must use keyword argument for key function" msgstr "must use keyword argument for key function" #: py/runtime.c -msgid "name '%q' is not defined" -msgstr "name '%q' is not defined" +msgid "name '%q' isn't defined" +msgstr "name '%q' isn't defined" #: py/runtime.c msgid "name not defined" @@ -3553,7 +3685,7 @@ msgstr "name not defined" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "name too long" #: py/persistentcode.c msgid "native code in .mpy unsupported" @@ -3608,7 +3740,7 @@ msgstr "no binding for nonlocal found" msgid "no default packer" msgstr "no default packer" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "no default seed" @@ -3817,6 +3949,10 @@ msgstr "ord() expected a character, but string of length %d found" msgid "out array is too small" msgstr "out array is too small" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "out has wrong type" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "out keyword is not supported for complex dtype" @@ -3841,6 +3977,14 @@ msgstr "out must be of float dtype" msgid "out of range of target" msgstr "out of range of target" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "output array has wrong type" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "output array must be contiguous" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overflow converting long int to machine word" @@ -3950,6 +4094,10 @@ msgstr "roll argument must be an ndarray" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed must be true" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3967,6 +4115,10 @@ msgstr "script compilation not supported" msgid "set unsupported" msgstr "set unsupported" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "shape must be None, and integer or a tuple of integers" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "shape must be integer or tuple of integers" @@ -3987,6 +4139,10 @@ msgstr "sign not allowed with integer format specifier 'c'" msgid "size is defined for ndarrays only" msgstr "size is defined for ndarrays only" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "size must match out.shape when used together" + #: py/nativeglue.c msgid "slice unsupported" msgstr "slice unsupported" @@ -4060,18 +4216,6 @@ msgstr "string index out of range" msgid "string indices must be integers, not %s" msgstr "string indices must be integers, not %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct: can't index" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index out of range" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: no fields" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "substring not found" @@ -4084,10 +4228,6 @@ msgstr "super() can't find self" msgid "syntax error in JSON" msgstr "syntax error in JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "syntax error in uctypes descriptor" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "ticks interval overflow" @@ -4177,12 +4317,12 @@ msgid "tx and rx cannot both be None" msgstr "tx and rx cannot both be None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" -msgstr "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" +msgstr "type '%q' isn't an acceptable base type" #: py/objtype.c -msgid "type is not an acceptable base type" -msgstr "type is not an acceptable base type" +msgid "type isn't an acceptable base type" +msgstr "type isn't an acceptable base type" #: py/runtime.c msgid "type object '%q' has no attribute '%q'" @@ -4196,10 +4336,6 @@ msgstr "type takes 1 or 3 arguments" msgid "ulonglong too large" msgstr "ulonglong too large" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "unary op %q not implemented" - #: py/parse.c msgid "unexpected indent" msgstr "unexpected indent" @@ -4247,7 +4383,9 @@ msgstr "unmatched '%c' in format" msgid "unreadable attribute" msgstr "unreadable attribute" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "unsupported %q type" @@ -4327,11 +4465,6 @@ msgstr "weights must be an object of type %q, %q, %q, or %q, not %q " msgid "width must be greater than zero" msgstr "width must be greater than zero" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "WiFi is not enabled" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wifi.Monitor not available" @@ -4394,6 +4527,82 @@ msgstr "zi must be of float type" msgid "zi must be of shape (n_section, 2)" msgstr "zi must be of shape (n_section, 2)" +#~ msgid "Unsupported format" +#~ msgstr "Unsupported format" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Wifi is not enabled" + +#~ msgid "wifi is not enabled" +#~ msgstr "WiFi is not enabled" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Cannot remount '/' when visible via USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q must be a %q object, %q, or %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Data chunk must follow fmt chunk" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "level must be between 0 and 1" + +#~ msgid "init I2C" +#~ msgstr "init I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "The sample's bits_per_sample does not match the mixer's" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "The sample's channel count does not match the mixer's" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "The sample's sample rate does not match the mixer's" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "The sample's signedness does not match the mixer's" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Buffer length must be a multiple of 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Buffer must be a multiple of 512 bytes" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Number of data_pins must be 8 or 16, not %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO init error %d" + +#~ msgid "can't unambiguously get sizeof scalar" +#~ msgstr "can't unambiguously get sizeof scalar" + +#~ msgid "struct: can't index" +#~ msgstr "struct: can't index" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index out of range" + +#~ msgid "struct: no fields" +#~ msgstr "struct: no fields" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "syntax error in uctypes descriptor" + +#~ msgid "unary op %q not implemented" +#~ msgstr "unary op %q not implemented" + #~ msgid "Name too long" #~ msgstr "Name too long" @@ -4636,8 +4845,8 @@ msgstr "zi must be of shape (n_section, 2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' outside loop" -#~ msgid "'coroutine' object is not an iterator" -#~ msgstr "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" +#~ msgstr "'coroutine' object isn't an iterator" #~ msgid "(x,y) integers required" #~ msgstr "(x,y) integers required" @@ -5507,8 +5716,8 @@ msgstr "zi must be of shape (n_section, 2)" #~ msgid "first argument must be an iterable" #~ msgstr "first argument must be an iterable" -#~ msgid "function does not take keyword arguments" -#~ msgstr "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" +#~ msgstr "function doesn't take keyword arguments" #~ msgid "incompatible native .mpy architecture" #~ msgstr "incompatible native .mpy architecture" @@ -5573,8 +5782,8 @@ msgstr "zi must be of shape (n_section, 2)" #~ msgid "maximum number of dimensions is 4" #~ msgstr "maximum number of dimensions is 4" -#~ msgid "name reused for argument" -#~ msgstr "name reused for argument" +#~ msgid "argument name reused" +#~ msgstr "argument name reused" #~ msgid "no available NIC" #~ msgstr "no available NIC" diff --git a/locale/en_US.po b/locale/en_US.po index e9344480c7675..f621d0aa19aee 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -274,7 +274,7 @@ msgid "'%q' object does not support '%q'" msgstr "" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -282,7 +282,7 @@ msgid "'%q' object is not callable" msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3068,7 +3068,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "" #: py/objdeque.c @@ -3538,7 +3538,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -4166,11 +4166,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index f7b682d56266b..17cac9cb0fb22 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -274,7 +274,7 @@ msgid "'%q' object does not support '%q'" msgstr "" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -282,7 +282,7 @@ msgid "'%q' object is not callable" msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -3070,7 +3070,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "" #: py/objdeque.c @@ -3540,7 +3540,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -4168,11 +4168,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c diff --git a/locale/es.po b/locale/es.po index 38d6bf949b0eb..85a03408b7517 100644 --- a/locale/es.po +++ b/locale/es.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: RubenD \n" +"PO-Revision-Date: 2025-08-03 08:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -97,17 +97,17 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q y %q contienen pines duplicados" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q y %q deben ser diferentes" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "%q and %q must share a clock unit" -msgstr "" +msgstr "%q y %q deben compartir la misma unidad de tiempo" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "%q cannot be changed once mode is set to %q" -msgstr "" +msgstr "no se puede cambiar %q una vez que se establece el modo a %q" #: shared-bindings/microcontroller/Pin.c msgid "%q contains duplicate pins" @@ -117,7 +117,11 @@ msgstr "%q contiene pines duplicados" msgid "%q failure: %d" msgstr "%q fallo: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q en %q debe ser de tipo %q o %q, no %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q en %q debe ser del tipo %q, no %q" @@ -169,9 +173,9 @@ msgstr "%q longitud debe ser <= %d" msgid "%q length must be >= %d" msgstr "%q longitud debe ser >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" -msgstr "" +msgstr "%q movido de %q a %q" #: py/argcheck.c msgid "%q must be %d" @@ -196,7 +200,7 @@ msgstr "%q debe ser <= %d" #: ports/espressif/common-hal/watchdog/WatchDogTimer.c msgid "%q must be <= %u" -msgstr "" +msgstr "%q debe ser <= %u" #: py/argcheck.c msgid "%q must be >= %d" @@ -212,7 +216,7 @@ msgstr "%q debe ser un bytearray o array de tipo 'h', 'H', 'b', o 'B'" #: shared-bindings/warnings/__init__.c msgid "%q must be a subclass of %q" -msgstr "" +msgstr "%q debe ser una subclase de %q" #: ports/espressif/common-hal/analogbufio/BufferedIn.c msgid "%q must be array of type 'H'" @@ -224,20 +228,22 @@ msgstr "%q debe ser una matriz de tipo 'h'" #: shared-bindings/audiobusio/PDMIn.c msgid "%q must be multiple of 8." -msgstr "" +msgstr "%q debe ser múltiplo de 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q debe ser del tipo %q o %q, y no %q" #: shared-bindings/jpegio/JpegDecoder.c msgid "%q must be of type %q, %q, or %q, not %q" -msgstr "" +msgstr "%q debe ser de tipo %q, %q, o %q, no %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q debe ser del tipo %q, y no %q" @@ -261,7 +267,7 @@ msgstr "%q fuera de rango" #: py/objmodule.c py/runtime.c msgid "%q renamed %q" -msgstr "" +msgstr "%q renombrado %q" #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" @@ -269,7 +275,7 @@ msgstr "%q paso no puede ser cero" #: shared-module/bitbangio/I2C.c msgid "%q too long" -msgstr "" +msgstr "%q demasiado largo" #: py/bc.c py/objnamedtuple.c msgid "%q() takes %d positional arguments but %d were given" @@ -277,13 +283,14 @@ msgstr "%q() toma %d argumentos posicionales pero %d fueron dados" #: shared-module/jpegio/JpegDecoder.c msgid "%q() without %q()" -msgstr "" +msgstr "%q() sin %q()" #: shared-bindings/usb_hid/Device.c msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, y %q deben tener la misma longitud" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -317,7 +324,7 @@ msgid "'%q' object does not support '%q'" msgstr "objeto '%q' no tiene capacidad '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "objeto '%q' no es un iterador" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -325,7 +332,7 @@ msgid "'%q' object is not callable" msgstr "objeto '%q' no es llamable" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "objeto '%q' no es iterable" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -415,7 +422,7 @@ msgstr "'await' fuera de la función" #: py/compile.c msgid "'break'/'continue' outside loop" -msgstr "" +msgstr "'break'/'continue' fuera del bucle" #: py/compile.c msgid "'data' requires at least 2 arguments" @@ -429,6 +436,10 @@ msgstr "'data' requiere argumentos de tipo entero" msgid "'label' requires 1 argument" msgstr "'label' requiere 1 argumento" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' no implementado" + #: py/compile.c msgid "'return' outside function" msgstr "'return' fuera de una función" @@ -457,7 +468,7 @@ msgstr ", en %q\n" #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid ".show(x) removed. Use .root_group = x" -msgstr "" +msgstr ".show(x) eliminado. Utiliza .root_group = x" #: py/objcomplex.c msgid "0.0 to a complex power" @@ -469,7 +480,7 @@ msgstr "pow() con 3 argumentos no soportado" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "AP could not be started" -msgstr "" +msgstr "No se pudo iniciar el Punto de Acceso" #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c #, c-format @@ -484,7 +495,7 @@ msgstr "Rango de dirección no permitido" #: shared-bindings/memorymap/AddressRange.c msgid "Address range wraps around" -msgstr "" +msgstr "Rango de direcciones cubre alrededor" #: ports/espressif/common-hal/canio/CAN.c msgid "All CAN peripherals are in use" @@ -550,7 +561,6 @@ msgstr "Todos los timers para este pin están en uso" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Todos los timers en uso" @@ -563,6 +573,10 @@ msgstr "Ya se encuentra publicando." msgid "Already have all-matches listener" msgstr "Ya se tiene un escucha de todas las coincidencias" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Ya esta en progreso" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -572,6 +586,7 @@ msgstr "Ya está en ejecución" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Ya se están buscando redes wifi" @@ -598,6 +613,12 @@ msgstr "El array debe contener medias palabras (escriba 'H')" msgid "Array values should be single bytes." msgstr "Valores del array deben ser bytes individuales." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +#, fuzzy +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" +"Transferencia SPI asíncrona en curso en este canal, manténgase esperando." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -607,6 +628,11 @@ msgstr "Tratando de localizar %d bloques" msgid "Audio conversion not implemented" msgstr "Conversión de audio no está implementada" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Error de fuente de audio" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN no se usa con contraseña" @@ -638,7 +664,7 @@ msgstr "Por debajo de la tasa mínima de refrescamiento" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c msgid "Bit clock and word select must be sequential GPIO pins" -msgstr "" +msgstr "Reloj de bit y selección de palabra deben ser pines secuenciales GPIO" #: shared-bindings/bitmaptools/__init__.c msgid "Bitmap size and bits per value must match" @@ -677,13 +703,13 @@ msgstr "" "La longitud del buffer %d es demasiado grande. Tiene que ser menor a %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "El tamaño del buffer debe ser múltiplo de 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "El buffer deber ser un múltiplo de 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "El búfer debe ser múltiplo de %d bytes" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -743,6 +769,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "Solo puede alerta en dos low pines viniendo de deep sleep." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "No se puede construir AudioOut porque ya hay un canal continuo abierto" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -790,8 +820,8 @@ msgid "Cannot record to a file" msgstr "No se puede grabar en un archivo" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "No se puede remountar '/' cuanto se es visible vía USB." +msgid "Cannot remount path when visible via USB." +msgstr "No se puede volver a montar path mientras es visible a través de USB." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -806,6 +836,10 @@ msgstr "No se puede especificar RTS o CTS en modo RS485" msgid "Cannot subclass slice" msgstr "No se puede manejar la partición en una subclase" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "No se puede utilizar GPIO0..15 junto con GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "No puede ser despertado en transición de pin, only nivel" @@ -842,6 +876,10 @@ msgstr "Las matrices de coordenadas tienen diferentes longitudes" msgid "Coordinate arrays types have different sizes" msgstr "Las matrices de coordenadas tienen diferentes tamaños" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "No se pudo publicar al tema ROS" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "No se puede definir la dirección" @@ -854,6 +892,11 @@ msgstr "No se pudo iniciar la interrupción, RX ocupado" msgid "Couldn't allocate decoder" msgstr "No se pudo encontrar el decodificador" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Fallo ROS critico durante reinicio suave, se requiere reiniciar: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Error de inicio del canal DAC" @@ -871,13 +914,9 @@ msgstr "DAC ya está siendo utilizado" msgid "Data 0 pin must be byte aligned" msgstr "El pin Data 0 debe estar alineado a bytes" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Trozo de datos debe seguir fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" -msgstr "" +msgstr "Error de formato de datos (pueden ser datos incompletos)" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c @@ -900,7 +939,7 @@ msgstr "Capacidad de destino es mas pequeña que destination_length." #: shared-module/jpegio/JpegDecoder.c msgid "Device error or wrong termination of input stream" -msgstr "" +msgstr "Error de dispositivo o terminación errónea del flujo de entrada" #: ports/nordic/common-hal/audiobusio/I2SOut.c msgid "Device in use" @@ -974,12 +1013,14 @@ msgstr "No se puede adquirir el mutex, error 0x%04x" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Failed to add service TXT record" -msgstr "" +msgstr "Fallo al adicionar el servicio en el registro TXT" #: shared-bindings/mdns/Server.c msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" +"Fallo al adicionar el servicio en el registro TXT; fueron encontrados " +"elementos diferentes a cadena de caracteres o bytes en txt_records" #: shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" @@ -1006,15 +1047,48 @@ msgstr "Error al conectar: error interno" msgid "Failed to connect: timeout" msgstr "Error al conectar: tiempo de espera agotado" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Error al crear canales continuos: argumento no válido" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Error al crear canales continuos: estado no válido" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Error al crear canales continuos: Sin memoria" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Error al crear canales continuos: no encontrado" + +#: ports/espressif/common-hal/audioio/AudioOut.c +#, fuzzy +msgid "Failed to enable continuous" +msgstr "Fallo habilitando continous" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Error al analizar el archivo MP3" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Error al registrar la devolución de llamada de eventos continuos" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "No se puede liberar el mutex, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Fallo al establecer el nombre de host" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Error al iniciar audio asíncrono" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Error al escribir el flash interno." @@ -1023,12 +1097,14 @@ msgstr "Error al escribir el flash interno." msgid "File exists" msgstr "El archivo ya existe" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Archivo no encontrado" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filtros muy complejos" @@ -1056,7 +1132,7 @@ msgstr "" "Para espacios de colores RGB, el bitmap de entrada debe tener 16 bits por " "pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Sin capacidades para el formato" @@ -1152,7 +1228,7 @@ msgstr "La entrada está durando mucho tiempo" #: py/moderrno.c msgid "Input/output error" -msgstr "error Input/output" +msgstr "Error input/output" #: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c @@ -1166,13 +1242,14 @@ msgstr "Cifrado insuficiente" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient memory pool for the image" -msgstr "" +msgstr "Reserva de memoria insuficiente para la imagen" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient stream input buffer" -msgstr "" +msgstr "Búfer de flujo de entrada insuficiente" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "La interfaz debe ser iniciada" @@ -1204,7 +1281,7 @@ msgstr "Error interno #%d" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-bindings/pwmio/PWMOut.c msgid "Internal resource(s) in use" -msgstr "" +msgstr "Recurso(s) interno(s) en uso" #: supervisor/shared/safe_mode.c msgid "Internal watchdog timer expired." @@ -1216,24 +1293,28 @@ msgstr "Error de interrupción." #: shared-module/jpegio/JpegDecoder.c msgid "Interrupted by output function" -msgstr "" +msgstr "Interrumpido por resultado de función" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "%q inválido" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "%q y %q no válidos" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1259,6 +1340,10 @@ msgstr "BSSID inválido" msgid "Invalid MAC address" msgstr "Dirección MAC inválida" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "ID de dominio ROS invalido" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Argumento inválido" @@ -1270,7 +1355,7 @@ msgstr "Inválido bits por valor" #: shared-module/os/getenv.c #, c-format msgid "Invalid byte %.*s" -msgstr "byte %.*s Inválido" +msgstr "Byte %.*s no válido" #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format @@ -1290,6 +1375,7 @@ msgid "Invalid hex password" msgstr "Contraseña hexadecimal no válida" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Dirección MAC de multidifusión inválida" @@ -1299,9 +1385,10 @@ msgstr "Tamaño incorrecto" #: shared-module/ssl/SSLSocket.c msgid "Invalid socket for TLS" -msgstr "socket invalido para TLS" +msgstr "Socket invalido para TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Estado invalido" @@ -1336,14 +1423,21 @@ msgstr "El Layer debe ser un grupo o una subclase de TileGrid" #: shared-bindings/audiocore/RawSample.c msgid "Length of %q must be an even multiple of channel_count * type_size" msgstr "" +"La longitud de %q debe ser un múltiplo par de channel_count * type_size" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "La dirección MAC es incorrecta" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" -msgstr "" +msgstr "Seguridad MITM no compatible" + +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "Error de Reloj MMC/SDIO %x" #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" @@ -1388,15 +1482,16 @@ msgstr "Falta jmp_pin. %q[%u] salta en pin" #: shared-module/storage/__init__.c msgid "Mount point directory missing" -msgstr "" +msgstr "Falta el directorio de punto de montaje" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Debe de ser una subclase de %q." #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c msgid "Must provide 5/6/5 RGB pins" -msgstr "" +msgstr "Debe proporcionar los pines RGB 5/6/5" #: ports/mimxrt10xx/common-hal/busio/SPI.c shared-bindings/busio/SPI.c msgid "Must provide MISO or MOSI pin" @@ -1460,7 +1555,7 @@ msgstr "No se encontró el canal DMA" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "No DMA pacing timer found" -msgstr "timer por establecedor de paso DMA no encontrado" +msgstr "Temporizador DMA no encontrado" #: shared-module/adafruit_bus_device/i2c_device/I2CDevice.c #, c-format @@ -1475,7 +1570,7 @@ msgstr "No IP" #: ports/cxd56/common-hal/microcontroller/__init__.c #: ports/mimxrt10xx/common-hal/microcontroller/__init__.c msgid "No bootloader present" -msgstr "" +msgstr "Ningún bootloader presente" #: shared-module/usb/core/Device.c msgid "No configuration set" @@ -1530,6 +1625,10 @@ msgstr "No se encontró pull up en SDA or SCL; verifique su cableado" msgid "No pulldown on pin; 1Mohm recommended" msgstr "No hay pulldown en el pin; 1Mohm recomendado" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Sin pullup en el pin; 1Mohm recomendado" + #: py/moderrno.c msgid "No space left on device" msgstr "No queda espacio en el dispositivo" @@ -1571,12 +1670,13 @@ msgstr "No reproduciendo" #: shared-module/jpegio/JpegDecoder.c msgid "Not supported JPEG standard" -msgstr "" +msgstr "Estándar JPEG no compatible" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "El numero de pines de datos debe ser 8 o 16, no %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "El número de data_pins debe ser %d o %d, no %d" #: shared-bindings/util.c msgid "" @@ -1601,7 +1701,7 @@ msgstr "Ok" #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c #, c-format msgid "Only 8 or 16 bit mono with %dx oversampling supported." -msgstr "" +msgstr "Solamente 8 o 16 bit mono con %dx oversampling soportado." #: ports/espressif/common-hal/wifi/__init__.c #: ports/raspberrypi/common-hal/wifi/__init__.c @@ -1632,15 +1732,6 @@ msgstr "Este hardware solo tiene capacidad para detección de borde" msgid "Only int or string supported for ip" msgstr "Solamente int or string son permitados para una ip" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Solo se admiten BMP monocromáticos, indexados de 4 bpp u 8 bpp y 16 bpp o " -"más: %d bpp proporcionados" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Solamente un %q puede ser establecido en deep sleep." @@ -1691,6 +1782,7 @@ msgstr "Memoria agotada" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Se acabaron los enchufes" @@ -1710,9 +1802,14 @@ msgstr "Segmento PWM ya esta en uso" msgid "PWM slice channel A already in use" msgstr "Segmento del PWM canal A ya esta en uso" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" +"Búferes de paquetes para transferencia SPI deben de ser de igual longitud." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" -msgstr "" +msgstr "Error de parámetro" #: ports/espressif/common-hal/audiobusio/__init__.c msgid "Peripheral in use" @@ -1814,6 +1911,11 @@ msgstr "El tamaño del programa no es correcto" msgid "Program too long" msgstr "El programa es demasiado grande" +#: shared-bindings/rclcpy/Publisher.c +#, fuzzy +msgid "Publishers can only be created from a parent node" +msgstr "Publicadores solo pueden ser creados desde un nodo padre" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull no se usa cuando la dirección es output." @@ -1824,7 +1926,7 @@ msgstr "RISE_AND_FALL no esta disponible para este chip" #: shared-module/displayio/OnDiskBitmap.c msgid "RLE-compressed BMP not supported" -msgstr "" +msgstr "BMP RLE-comprimidos no estan soportados" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" @@ -1834,6 +1936,26 @@ msgstr "Error de desinicialización de RNG" msgid "RNG Init Error" msgstr "Error de inicialización de RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "Fallo al inicializar ROS, El agente esta conectado?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "Fallo interno de instalación ROS" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "Fallo de asignación de memoria ROS" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "Fallo al inicializar nodo ROS" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "Fallo al inicializar Tema ROS" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1893,7 +2015,7 @@ msgstr "Canal derecho no soportado" #: shared-module/jpegio/JpegDecoder.c msgid "Right format but not supported" -msgstr "" +msgstr "Formato correcto pero no compatible" #: main.c msgid "Running in safe mode! Not running saved code.\n" @@ -1913,10 +2035,11 @@ msgstr "Inicialización SDCard" msgid "SDIO GetCardInfo Error %d" msgstr "Error SDIO GetCardInfo %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "Error de iniciado de SDIO %d" +msgid "SDIO Init Error %x" +msgstr "Error de inicio de SDIO %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1965,11 +2088,13 @@ msgstr "Slice y value tienen tamaños diferentes." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Rebanadas no soportadas" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool solo se puede usar con wifi.radio" @@ -1983,7 +2108,7 @@ msgstr "Especifique exactamente uno de data0 or data_pins" #: supervisor/shared/safe_mode.c msgid "Stack overflow. Increase stack size." -msgstr "" +msgstr "Desbordamiento de pila. Aumenta el tamaño de pila." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" @@ -2010,21 +2135,9 @@ msgstr "La excepción fue la causa directa de la excepción siguiente:" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "La longitud de rgb_pins debe ser 6, 12, 18, 24, o 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Los bits_per_sample del sample no igualan a los del mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "La cuenta de canales del sample no iguala a las del mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "El sample rate del sample no iguala al del mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "El signo del sample no iguala al del mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "El %q de la muestra no concuerda" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2046,7 +2159,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "La altura del Tile debe dividir exacto la altura del bitmap" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Índice de mosaico fuera de límites" @@ -2054,6 +2169,11 @@ msgstr "Índice de mosaico fuera de límites" msgid "Tile width must exactly divide bitmap width" msgstr "Ancho del Tile debe dividir exactamente el ancho de mapa de bits" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +#, fuzzy +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "Tilepalettemapper sólo puede vincularse una vez a un TileGrid" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Tiempo suministrado esta en el pasado." @@ -2076,7 +2196,7 @@ msgstr "Demasiados canales en sample." #: ports/espressif/common-hal/_bleio/Characteristic.c msgid "Too many descriptors" -msgstr "" +msgstr "Demasiados descriptores" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" @@ -2156,7 +2276,7 @@ msgstr "UUID valor no es un str, int o byte buffer" #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to access unaligned IO register" -msgstr "" +msgstr "Incapaz de acceder al registro no alineado de IO" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -2167,7 +2287,7 @@ msgstr "No se pudieron asignar buffers para la conversión con signo" #: supervisor/shared/safe_mode.c msgid "Unable to allocate to the heap." -msgstr "" +msgstr "Imposible de asignar al heap." #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" @@ -2187,6 +2307,12 @@ msgstr "Incapaz de inicializar el parser" msgid "Unable to read color palette data" msgstr "No se pudo leer los datos de la paleta de colores" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" +"No se puede enviar mensaje CAN todos los búferes de mensajes Tx están " +"ocupados" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2198,7 +2324,7 @@ msgstr "Imposible escribir en nvm." #: ports/raspberrypi/common-hal/memorymap/AddressRange.c msgid "Unable to write to read-only memory" -msgstr "" +msgstr "Incapaz de escribir en memoria de solo lectura" #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." @@ -2281,32 +2407,27 @@ msgstr "Espacio de color no sportado" msgid "Unsupported display bus type" msgstr "Sin capacidad de bus tipo display" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Formato no soportado" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Algoritmo hash no soportado" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" -msgstr "" +msgstr "Tipo de socket no compatible" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Actualización fallida" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Tamaño del valor != del tamaño fijo requerido" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2348,9 +2469,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "Wifi no esta activado" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi no está habilitado" #: main.c msgid "Woken up by alarm.\n" @@ -2372,12 +2495,13 @@ msgstr "Usted presionó ambos botones al iniciar." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Usted presionó el botón A al iniciar." #: ports/espressif/boards/m5stack_m5paper/mpconfigboard.h msgid "You pressed button DOWN at start up." -msgstr "" +msgstr "Usted presionó el botón DOWN en el arranque." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" @@ -2385,8 +2509,9 @@ msgstr "Usted presionó el botón BOOT al iniciar" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." -msgstr "" +msgstr "Usted presionó el botón BOOT en el arranque." #: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h msgid "You pressed the GPIO0 button at start up." @@ -2445,6 +2570,10 @@ msgstr "se requiere un objeto bytes-like" msgid "addresses is empty" msgstr "addresses esta vacío" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "Ya se está reproduciendo" + #: py/compile.c msgid "annotation must be an identifier" msgstr "la anotación debe ser un identificador" @@ -2463,11 +2592,15 @@ msgstr "arg debe ser tipo-user" #: extmod/ulab/code/numpy/numerical.c msgid "argsort argument must be an ndarray" -msgstr "El argumento para argsort debe ser un ndarray" +msgstr "el argumento para argsort debe ser un ndarray" #: extmod/ulab/code/numpy/numerical.c msgid "argsort is not implemented for flattened arrays" -msgstr "El argot no está implementado para arrays aplanados" +msgstr "argsort no está implementado para arrays aplanados" + +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "el argumento debe ser None, un entero o una tupla de enteros" #: py/compile.c msgid "argument name reused" @@ -2484,11 +2617,11 @@ msgstr "argumentos deben ser ndarrays" #: extmod/ulab/code/ndarray.c msgid "array and index length must be equal" -msgstr "Longitud del array e índice tienen que ser iguales" +msgstr "las longitudes del array e índice deben ser iguales" #: extmod/ulab/code/numpy/io/io.c msgid "array has too many dimensions" -msgstr "La matriz tiene demasiadas dimensiones" +msgstr "la matriz tiene demasiadas dimensiones" #: extmod/ulab/code/ndarray.c msgid "array is too big" @@ -2505,11 +2638,11 @@ msgstr "desborde de asm" #: py/compile.c msgid "async for/with outside async function" -msgstr "" +msgstr "async for/with fuera de función async" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get (arg)min/(arg)max of empty sequence" -msgstr "Intendo de obteber (arg)min/(arg)max de secuencia vacía" +msgstr "intento de obtener (arg)min/(arg)max de secuencia vacía" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get argmin/argmax of an empty sequence" @@ -2517,23 +2650,27 @@ msgstr "intento de obtener argmin/argmax de una secuencia vacía" #: py/objstr.c msgid "attributes not supported" -msgstr "" +msgstr "atributos no compatibles" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "Formato de audio no compatible" #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" -msgstr "Eje está fuera de sus límites" +msgstr "eje está fuera de sus límites" #: extmod/ulab/code/numpy/numerical.c extmod/ulab/code/ulab_tools.c msgid "axis must be None, or an integer" -msgstr "Eje tiene que ser None, o un entero" +msgstr "eje debe ser None, o un entero" #: extmod/ulab/code/numpy/numerical.c msgid "axis too long" -msgstr "Eje demasiado largo" +msgstr "eje demasiado largo" #: shared-bindings/bitmaptools/__init__.c msgid "background value out of range of target" -msgstr "El valor del fondo esta fuera del rango del objectivo" +msgstr "el valor del fondo esta fuera del rango del objetivo" #: py/builtinevex.c msgid "bad compile mode" @@ -2555,18 +2692,31 @@ msgstr "typecode erroneo" msgid "binary op %q not implemented" msgstr "operacion binaria %q no implementada" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth debe ser de 8, 16, 24, or 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" -msgstr "" +msgstr "el tamaño y profundidad del mapa de bits deben coincidir" #: shared-bindings/bitmaptools/__init__.c msgid "bitmap sizes must match" -msgstr "Los tamaños de los bitmap deben coincidir" +msgstr "los tamaños de los bitmap deben coincidir" #: extmod/modrandom.c msgid "bits must be 32 or less" msgstr "los bits deben ser 32 o menos" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample debe ser 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample debe ser 8 ó 16" @@ -2577,11 +2727,11 @@ msgstr "la rama no está dentro del rango" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer is smaller than requested size" -msgstr "El buffer es mas pequeño que el requerido" +msgstr "el búfer es más pequeño que el tamaño solicitado" #: extmod/ulab/code/numpy/create.c extmod/ulab/code/utils/utils.c msgid "buffer size must be a multiple of element size" -msgstr "El tamaño del buffer debe ser un múltiplo del tamaño del elemento" +msgstr "el tamaño del búfer debe ser un múltiplo del tamaño del elemento" #: shared-module/struct/__init__.c msgid "buffer size must match format" @@ -2589,7 +2739,7 @@ msgstr "el tamaño del buffer debe de coincidir con el formato" #: shared-bindings/bitbangio/SPI.c shared-bindings/busio/SPI.c msgid "buffer slices must be of equal length" -msgstr "Las secciones del buffer necesitan tener longitud igual" +msgstr "las secciones del búfer deben tener la misma longitud" #: py/modstruct.c shared-module/struct/__init__.c msgid "buffer too small" @@ -2648,7 +2798,7 @@ msgstr "no se puede asignar a la expresión" msgid "can't cancel self" msgstr "no se puede cancelar a si mismo" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "no puede convertir %q a %q" @@ -2703,13 +2853,17 @@ msgstr "no se puede borrar la expresión" msgid "can't do binary op between '%q' and '%q'" msgstr "no se puede hacer una operacion binaria entre '%q' y '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "no puede ser unary op de '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "no se puede convertir implícitamente '%q' a 'bool'" #: py/runtime.c msgid "can't import name %q" -msgstr "" +msgstr "no se puede importar el nombre %q" #: py/emitnative.c msgid "can't load from '%q'" @@ -2768,11 +2922,7 @@ msgstr "" #: py/objcomplex.c msgid "can't truncate-divide a complex number" -msgstr "" - -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" +msgstr "no puede truncar-rendondear un numéro complejo" #: extmod/modasyncio.c msgid "can't wait" @@ -2784,7 +2934,7 @@ msgstr "no se puede asignar una nueva forma" #: extmod/ulab/code/ndarray_operators.c msgid "cannot cast output with casting rule" -msgstr "No se puede realizar cast de la salida sin una regla de cast" +msgstr "no se puede realizar cast de la salida sin una regla de cast" #: extmod/ulab/code/ndarray.c msgid "cannot convert complex to dtype" @@ -2824,15 +2974,15 @@ msgstr "chars buffer es demasiado pequeño" #: py/modbuiltins.c msgid "chr() arg not in range(0x110000)" -msgstr "El argumento de chr() esta fuera de rango(0x110000)" +msgstr "argumento chr() está fuera de rango(0x110000)" #: py/modbuiltins.c msgid "chr() arg not in range(256)" -msgstr "El argumento de chr() no esta en el rango(256)" +msgstr "argumento chr() no está en el rango(256)" #: shared-bindings/bitmaptools/__init__.c msgid "clip point must be (x,y) tuple" -msgstr "El punto de recorte debe ser una tupla (x, y)" +msgstr "el punto de recorte debe ser una tupla (x, y)" #: shared-bindings/msgpack/ExtType.c msgid "code outside range 0~127" @@ -2860,7 +3010,7 @@ msgstr "comparación entre int y uint" #: py/objcomplex.c msgid "complex divide by zero" -msgstr "" +msgstr "división compleja entre cero" #: py/objfloat.c py/parsenum.c msgid "complex values not supported" @@ -2888,7 +3038,7 @@ msgstr "los argumentos para convolve no deben estar vacíos" #: extmod/ulab/code/numpy/io/io.c msgid "corrupted file" -msgstr "Archivo corrompido" +msgstr "archivo corrompido" #: extmod/ulab/code/numpy/poly.c msgid "could not invert Vandermonde matrix" @@ -2900,7 +3050,7 @@ msgstr "no se pudo determinar la versión de la tarjeta SD" #: extmod/ulab/code/numpy/numerical.c msgid "cross is defined for 1D arrays of length 3" -msgstr "Cruce está definido para un array 1D de longitud 3" +msgstr "cruce está definido para un array 1D de longitud 3" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "data must be iterable" @@ -2948,11 +3098,11 @@ msgstr "la secuencia de actualizacion del dict tiene una longitud incorrecta" #: extmod/ulab/code/numpy/numerical.c msgid "diff argument must be an ndarray" -msgstr "El argumento diff debe ser un ndarray" +msgstr "el argumento diff debe ser un ndarray" #: extmod/ulab/code/numpy/numerical.c msgid "differentiation order out of range" -msgstr "Orden de diferenciación fuera de rango" +msgstr "órden de diferenciación fuera de rango" #: extmod/ulab/code/numpy/transform.c msgid "dimensions do not match" @@ -2976,7 +3126,7 @@ msgstr "dtype debe ser float, o complex" #: extmod/ulab/code/ndarray_operators.c msgid "dtype of int32 is not supported" -msgstr "" +msgstr "dtype de int32 no compatible" #: py/objdeque.c msgid "empty" @@ -3075,7 +3225,7 @@ msgstr "el primer argumento debe ser una función" #: extmod/ulab/code/numpy/create.c msgid "first argument must be a tuple of ndarrays" -msgstr "Primer argumento tiene que ser una tupla de ndarrays" +msgstr "el primer argumento debe ser una tupla de ndarrays" #: extmod/ulab/code/numpy/transform.c extmod/ulab/code/numpy/vector.c msgid "first argument must be an ndarray" @@ -3111,10 +3261,10 @@ msgstr "font debe ser 2048 bytes de largo" #: extmod/moddeflate.c msgid "format" -msgstr "" +msgstr "formato" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "format requiere un dict" #: py/objdeque.c @@ -3140,7 +3290,7 @@ msgstr "la función tiene el mismo signo a extremos del intervalo" #: extmod/ulab/code/ndarray.c msgid "function is defined for ndarrays only" -msgstr "Función solo definida para ndarrays" +msgstr "función solo definida para ndarrays" #: extmod/ulab/code/numpy/carray/carray.c msgid "function is implemented for ndarrays only" @@ -3164,7 +3314,8 @@ msgstr "la función requiere del argumento por palabra clave '%q'" msgid "function missing required positional argument #%d" msgstr "la función requiere del argumento posicional #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "la función toma %d argumentos posicionales pero le fueron dados %d" @@ -3247,10 +3398,6 @@ msgstr "indices deben ser enteros" msgid "indices must be integers, slices, or Boolean lists" msgstr "los índices deben ser enteros, particiones o listas de booleanos" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "inicializacion I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "los valores iniciales deben permitir iteración" @@ -3281,7 +3428,7 @@ msgstr "el tamaño del arreglo de entrada debe ser potencia de 2" #: extmod/ulab/code/numpy/create.c msgid "input arrays are not compatible" -msgstr "Arrays de entrada no son compactibles" +msgstr "matrices de entrada no son compatibles" #: extmod/ulab/code/numpy/poly.c msgid "input data must be an iterable" @@ -3314,11 +3461,11 @@ msgstr "entrada debe ser un ndarray de 1D" #: extmod/ulab/code/scipy/linalg/linalg.c extmod/ulab/code/user/user.c msgid "input must be a dense ndarray" -msgstr "Entrada tiene que ser un ndarray denso" +msgstr "la entrada debe ser un ndarray denso" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" -msgstr "Entrada tiene que ser un ndarray" +msgstr "la entrada debe ser un ndarray" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be an ndarray, or a scalar" @@ -3326,7 +3473,7 @@ msgstr "entrada debe ser una ndarray o un escalar" #: extmod/ulab/code/scipy/signal/signal.c msgid "input must be one-dimensional" -msgstr "Entrada tiene que ser unidimensional" +msgstr "la entrada debe ser unidimensional" #: extmod/ulab/code/ulab_tools.c msgid "input must be square matrix" @@ -3351,7 +3498,7 @@ msgstr "el intervalo debe ser der rango %s-%s" #: py/compile.c msgid "invalid arch" -msgstr "" +msgstr "arco no válido" #: shared-bindings/bitmaptools/__init__.c #, c-format @@ -3437,6 +3584,8 @@ msgstr "" #: py/argcheck.c msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" +"argumento(s) de palabras clave no implementado - en su lugar utiliza " +"argumentos normales" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3446,10 +3595,6 @@ msgstr "etiqueta '%q' no definida" msgid "label redefined" msgstr "etiqueta redefinida" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "el nivel debe ser entre 0 y 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs y rhs deben ser compatibles" @@ -3468,7 +3613,7 @@ msgstr "variable local referenciada antes de la asignación" #: ports/espressif/common-hal/canio/CAN.c msgid "loopback + silent mode not supported by peripheral" -msgstr "Loopback + modo silencioso no están soportados por periférico" +msgstr "bucle de retorno + modo silencioso no admitidos por periférico" #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c @@ -3503,7 +3648,7 @@ msgstr "matrix no es definida positiva" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length debe ser 0-%d cuando fixed_length es %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "el numero maximo de dimensiones es " @@ -3534,7 +3679,7 @@ msgstr "la asignación de memoria falló, el heap está bloqueado" #: py/objarray.c msgid "memoryview offset too large" -msgstr "" +msgstr "memory offset es demasiado grande" #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" @@ -3543,7 +3688,7 @@ msgstr "" #: extmod/modtime.c msgid "mktime needs a tuple of length 8 or 9" -msgstr "" +msgstr "mktime requiere una tupla de longitud 8 o 9" #: extmod/ulab/code/numpy/linalg/linalg.c msgid "mode must be complete, or reduced" @@ -3582,7 +3727,7 @@ msgid "must use keyword argument for key function" msgstr "debe utilizar argumento de palabra clave para la función clave" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "name '%q' no esta definido" #: py/runtime.c @@ -3591,11 +3736,11 @@ msgstr "name no definido" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "nombre demasiado largo" #: py/persistentcode.c msgid "native code in .mpy unsupported" -msgstr "" +msgstr "código nativo .mpy no compatible" #: py/asmthumb.c msgid "native method too big" @@ -3646,7 +3791,7 @@ msgstr "no se ha encontrado ningún enlace para nonlocal" msgid "no default packer" msgstr "no hay empaquetador por defecto" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "sin semilla por omisión" @@ -3841,7 +3986,7 @@ msgstr "la operación no es compatible para un tipo dado" #: extmod/ulab/code/ndarray_operators.c msgid "operation not supported for the input types" -msgstr "" +msgstr "operación no soportada para los tipos de entrada" #: py/modbuiltins.c msgid "ord expects a character" @@ -3854,7 +3999,11 @@ msgstr "ord() espera un carácter, pero encontró un string de longitud %d" #: extmod/ulab/code/utils/utils.c msgid "out array is too small" -msgstr "La matriz de salida es demasiado pequeña" +msgstr "la matriz de salida es demasiado pequeña" + +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "tipo de salida incorrecto" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" @@ -3880,6 +4029,14 @@ msgstr "el dtype de out debe ser float" msgid "out of range of target" msgstr "fuera de rango del objetivo" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "matriz de salida tiene el tipo erróneo" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "matriz de salida debe ser contiguo" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "desbordamiento convirtiendo long int a palabra de máquina" @@ -3983,12 +4140,16 @@ msgstr "rgb_pins[%d] no está en el mismo puerto que el reloj" #: extmod/ulab/code/numpy/numerical.c msgid "roll argument must be an ndarray" -msgstr "Argumento enrolado tiene que ser un ndarray" +msgstr "argumento enrolado tiene que ser un ndarray" #: py/objstr.c msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed debe ser true" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4006,6 +4167,10 @@ msgstr "script de compilación no soportado" msgid "set unsupported" msgstr "sin capacidades para el conjunto" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "shape debe ser None, un entero o una tupla de enteros" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "la forma debe ser un número entero o una tupla de números enteros" @@ -4026,6 +4191,10 @@ msgstr "signo no permitido con el especificador integer format 'c'" msgid "size is defined for ndarrays only" msgstr "el tamaño se define solo para ndarrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "out.shape y el tamaño deben coincidir cuando se usan juntos" + #: py/nativeglue.c msgid "slice unsupported" msgstr "sin capacidades para rebanado" @@ -4072,7 +4241,7 @@ msgstr "source_bitmap debe tener value_count de 8" #: extmod/modre.c msgid "splitting with sub-captures" -msgstr "" +msgstr "dividiendo con sub-capturas" #: py/objstr.c msgid "start/end indices" @@ -4088,7 +4257,7 @@ msgstr "operación stream no soportada" #: py/objarray.c py/objstr.c msgid "string argument without an encoding" -msgstr "" +msgstr "argumento de cadena de texto sin codificación" #: py/objstrunicode.c msgid "string index out of range" @@ -4099,18 +4268,6 @@ msgstr "string index fuera de rango" msgid "string indices must be integers, not %s" msgstr "índices de string deben ser enteros, no %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct: no puede indexar" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index fuera de rango" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: sin campos" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "substring no encontrado" @@ -4123,13 +4280,9 @@ msgstr "super() no puede encontrar self" msgid "syntax error in JSON" msgstr "error de sintaxis en JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "error de sintaxis en el descriptor uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" -msgstr "" +msgstr "desbordamiento de intervalo de ticks" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "timeout duration exceeded the maximum supported value" @@ -4142,12 +4295,12 @@ msgstr "timeout debe ser < 655.35 segundos" #: ports/raspberrypi/common-hal/floppyio/__init__.c msgid "timeout waiting for flux" -msgstr "" +msgstr "tiempo límite esperando por el flujo" #: ports/raspberrypi/common-hal/floppyio/__init__.c #: shared-module/floppyio/__init__.c msgid "timeout waiting for index pulse" -msgstr "" +msgstr "tiempo límite esperando por el pulso índice" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" @@ -4214,14 +4367,14 @@ msgstr "twai_start devolvió esp-idf error #%d" #: shared-bindings/busio/UART.c shared-bindings/canio/CAN.c msgid "tx and rx cannot both be None" -msgstr "Ambos tx y rx no pueden ser None" +msgstr "ambos tx y rx no pueden ser None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "type '%q' no es un tipo de base aceptable" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "type no es un tipo de base aceptable" #: py/runtime.c @@ -4236,10 +4389,6 @@ msgstr "type acepta 1 ó 3 argumentos" msgid "ulonglong too large" msgstr "ulonglong muy largo" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "Operación unica %q no implementada" - #: py/parse.c msgid "unexpected indent" msgstr "sangría inesperada" @@ -4287,7 +4436,9 @@ msgstr "no coteja '%c' en formato" msgid "unreadable attribute" msgstr "atributo no legible" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "tipo de %q no soportado" @@ -4303,7 +4454,7 @@ msgstr "instrucción Xtensa '%s' con %d argumentos no soportada" #: shared-module/bitmapfilter/__init__.c msgid "unsupported bitmap depth" -msgstr "" +msgstr "profundidad de mapa de bits no compatible" #: shared-module/gifio/GifWriter.c msgid "unsupported colorspace for GifWriter" @@ -4349,27 +4500,24 @@ msgstr "valor fuera de alcance al blanco" #: extmod/moddeflate.c msgid "wbits" -msgstr "" +msgstr "wbits" #: shared-bindings/bitmapfilter/__init__.c msgid "" "weights must be a sequence with an odd square number of elements (usually 9 " "or 25)" msgstr "" +"los pesos deben ser una secuencia con una raíz cuadrada impar de elementos " +"(usualmente 9 o 25)" #: shared-bindings/bitmapfilter/__init__.c msgid "weights must be an object of type %q, %q, %q, or %q, not %q " -msgstr "" +msgstr "los pesos deben ser un tipo de objetos %q, %q, %q, or %q, y no %q. " #: shared-bindings/is31fl3741/FrameBuffer.c msgid "width must be greater than zero" msgstr "el ancho debe ser mayor que cero" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "wifi no esta habilitado" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wifi.Monitor no esta disponible" @@ -4432,6 +4580,79 @@ msgstr "zi debe ser de tipo flotante" msgid "zi must be of shape (n_section, 2)" msgstr "zi debe ser una forma (n_section,2)" +#~ msgid "Unsupported format" +#~ msgstr "Formato no soportado" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Wifi no esta activado" + +#~ msgid "wifi is not enabled" +#~ msgstr "wifi no esta habilitado" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "No se puede remountar '/' cuanto se es visible vía USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q tiene que ser un %q objeto, %q, o %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Trozo de datos debe seguir fmt chunk" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Solo se admiten BMP monocromáticos, indexados de 4 bpp u 8 bpp y 16 bpp o " +#~ "más: %d bpp proporcionados" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "el nivel debe ser entre 0 y 1" + +#~ msgid "init I2C" +#~ msgstr "inicializacion I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Los bits_per_sample del sample no igualan a los del mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "La cuenta de canales del sample no iguala a las del mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "El sample rate del sample no iguala al del mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "El signo del sample no iguala al del mixer" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "El tamaño del buffer debe ser múltiplo de 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "El buffer deber ser un múltiplo de 512 bytes" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "El numero de pines de datos debe ser 8 o 16, no %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "Error de iniciado de SDIO %d" + +#~ msgid "struct: can't index" +#~ msgstr "struct: no puede indexar" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index fuera de rango" + +#~ msgid "struct: no fields" +#~ msgstr "struct: sin campos" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "error de sintaxis en el descriptor uctypes" + +#~ msgid "unary op %q not implemented" +#~ msgstr "Operación unica %q no implementada" + #~ msgid "Name too long" #~ msgstr "Nombre muy largo" @@ -4714,13 +4935,13 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "objeto '%s' no soporta la eliminación de elementos" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "objeto '%s' no es un iterator" #~ msgid "'%s' object is not callable" #~ msgstr "objeto '%s' no puede ser llamado" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "objeto '%s' no es iterable" #~ msgid "'%s' object is not subscriptable" @@ -4738,7 +4959,7 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' fuera de un bucle" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "el objeto 'coroutine' no es un iterador" #~ msgid "64 bit types" @@ -6198,7 +6419,7 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "frequency can only be either 80Mhz or 160MHz" #~ msgstr "la frecuencia solo puede ser 80MHz ó 160MHz" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "la función no tiene argumentos por palabra clave" #~ msgid "function is implemented for scalars and ndarrays only" @@ -6322,7 +6543,7 @@ msgstr "zi debe ser una forma (n_section,2)" #~ msgid "name must be a string" #~ msgstr "name debe de ser un string" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "name reusado para argumento" #~ msgid "no available NIC" diff --git a/locale/fil.po b/locale/fil.po index 0d1ae3f24e4cd..27d949a0615a4 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -6,8 +6,8 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Jeff Epler \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: fil\n" "Language: fil\n" "MIME-Version: 1.0\n" @@ -15,13 +15,15 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1 && n != 2 && n != 3 && (n % 10 == 4 " "|| n % 10 == 6 || n % 10 == 9);\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" "\n" "Code done running.\n" msgstr "" +"\n" +"Code ay tapos na sa pagtakbo\n" #: main.c msgid "" @@ -83,7 +85,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "" @@ -103,7 +105,11 @@ msgstr "" msgid "%q failure: %d" msgstr "" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" @@ -155,7 +161,7 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "" @@ -215,6 +221,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -224,6 +231,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -270,7 +278,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -304,7 +313,7 @@ msgid "'%q' object does not support '%q'" msgstr "" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -312,7 +321,7 @@ msgid "'%q' object is not callable" msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -416,6 +425,10 @@ msgstr "'data' kailangan ng integer arguments" msgid "'label' requires 1 argument" msgstr "'label' kailangan ng 1 argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' sa labas ng function" @@ -459,9 +472,9 @@ msgid "AP could not be started" msgstr "" #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c -#, fuzzy, c-format +#, c-format msgid "Address must be %d bytes long" -msgstr "ang palette ay dapat 32 bytes ang haba" +msgstr "Dapat na %d bytes ang haba ng address" #: ports/espressif/common-hal/memorymap/AddressRange.c #: ports/nordic/common-hal/memorymap/AddressRange.c @@ -536,7 +549,6 @@ msgstr "Lahat ng timers para sa pin na ito ay ginagamit" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Lahat ng timer ginagamit" @@ -549,6 +561,10 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -558,6 +574,7 @@ msgstr "" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "" @@ -584,6 +601,10 @@ msgstr "May halfwords (type 'H') dapat ang array" msgid "Array values should be single bytes." msgstr "Array values ay dapat single bytes." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -593,6 +614,11 @@ msgstr "" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -662,12 +688,12 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" msgstr "" #: shared-bindings/_bleio/PacketBuffer.c @@ -686,14 +712,13 @@ msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c #: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c #: ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c -#, fuzzy, c-format +#, c-format msgid "Bus pin %d is already in use" -msgstr "Ginagamit na ang DAC" +msgstr "Ginagamit na ang bus pin %d" #: shared-bindings/_bleio/UUID.c -#, fuzzy msgid "Byte buffer must be 16 bytes." -msgstr "buffer ay dapat bytes-like object" +msgstr "Ang byte buffer ay dapat na 16 byte." #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" @@ -727,6 +752,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -773,7 +802,7 @@ msgid "Cannot record to a file" msgstr "Hindi ma-record sa isang file" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c @@ -789,6 +818,10 @@ msgstr "" msgid "Cannot subclass slice" msgstr "Hindi magawa ang sublcass slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -823,6 +856,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "" @@ -835,6 +872,11 @@ msgstr "" msgid "Couldn't allocate decoder" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "" @@ -853,10 +895,6 @@ msgstr "Ginagamit na ang DAC" msgid "Data 0 pin must be byte aligned" msgstr "graphic ay dapat 2048 bytes ang haba" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Dapat sunurin ng Data chunk ang fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -951,9 +989,9 @@ msgid "Failed sending command." msgstr "" #: ports/nordic/sd_mutex.c -#, fuzzy, c-format +#, c-format msgid "Failed to acquire mutex, err 0x%04x" -msgstr "Nabigo sa pag kuha ng mutex, status: 0x%08lX" +msgstr "Nabigong makuha ang mutex, err 0x%04x" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Failed to add service TXT record" @@ -989,14 +1027,46 @@ msgstr "" msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c -#, fuzzy, c-format +#, c-format msgid "Failed to release mutex, err 0x%04x" -msgstr "Nabigo sa pagrelease ng mutex, status: 0x%08lX" +msgstr "Nabigong ilabas ang mutex, err 0x%04x" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." @@ -1006,12 +1076,14 @@ msgstr "" msgid "File exists" msgstr "Mayroong file" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1036,7 +1108,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "" @@ -1144,6 +1216,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1189,15 +1262,19 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "" @@ -1230,6 +1307,10 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Maling argumento" @@ -1261,6 +1342,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1273,6 +1355,7 @@ msgid "Invalid socket for TLS" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" @@ -1313,9 +1396,15 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -1361,7 +1450,8 @@ msgstr "" msgid "Mount point directory missing" msgstr "" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "" @@ -1501,6 +1591,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -1546,8 +1640,9 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1602,13 +1697,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1659,6 +1747,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1678,6 +1767,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1754,6 +1847,8 @@ msgstr "" #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload.\n" msgstr "" +"Pindutin ang kahit anong key para pumasok sa REPL. Gamitin ang CTRL-D para " +"mag-reload\n" #: main.c msgid "Pretending to deep sleep until alarm, CTRL-C or file write.\n" @@ -1775,30 +1870,54 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull hindi ginagamit kapag ang direksyon ay output." #: ports/raspberrypi/common-hal/countio/Counter.c msgid "RISE_AND_FALL not available on this chip" -msgstr "" +msgstr "RISE_AND_FALL ay hindi pwede sa chip na ito" #: shared-module/displayio/OnDiskBitmap.c msgid "RLE-compressed BMP not supported" -msgstr "" +msgstr "RLE-compressed BMP ay hindi suportado" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" -msgstr "" +msgstr "Error sa RNG DeInit" #: ports/stm/common-hal/os/__init__.c msgid "RNG Init Error" +msgstr "Error sa RNG Init" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" msgstr "" #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1830,11 +1949,11 @@ msgstr "" #: supervisor/shared/bluetooth/bluetooth.c msgid "Reconnecting" -msgstr "" +msgstr "Kumokonekta" #: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Refresh too soon" -msgstr "" +msgstr "sobrang aga mag-refresh" #: shared-bindings/canio/RemoteTransmissionRequest.c msgid "RemoteTransmissionRequests limited to 8 bytes" @@ -1846,7 +1965,7 @@ msgstr "" #: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" -msgstr "" +msgstr "Hiniling na resource ay hindi nakita" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "Right channel unsupported" @@ -1862,80 +1981,83 @@ msgstr "Tumatakbo sa safe mode! Hindi tumatakbo ang nai-save na code.\n" #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" -msgstr "" +msgstr "SD card CSD na format ay hindi suportado" #: ports/cxd56/common-hal/sdioio/SDCard.c msgid "SDCard init" -msgstr "" +msgstr "pag-init ng SDCard" #: ports/stm/common-hal/sdioio/SDCard.c #, c-format msgid "SDIO GetCardInfo Error %d" -msgstr "" +msgstr "Error ng SDIO GetCardInfo %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "" +msgid "SDIO Init Error %x" +msgstr "Error sa pag-init ng SDIO %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" -msgstr "" +msgstr "Nabigo sa SPI configuration" #: ports/stm/common-hal/busio/SPI.c msgid "SPI init error" -msgstr "" +msgstr "error sa pag-init ng SPI" #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" -msgstr "" +msgstr "SPI peripheral ay ginagamit" #: ports/stm/common-hal/busio/SPI.c msgid "SPI re-init" -msgstr "" +msgstr "pag re-init ng SPI" #: shared-bindings/is31fl3741/FrameBuffer.c msgid "Scale dimensions must divide by 3" -msgstr "" +msgstr "Scale dimensions ay kailangan i-divide sa 3" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Scan already in progress. Stop with stop_scan." -msgstr "" +msgstr "Scan ay kasalukuyang ginagawa. Patigilin gamit ang stop_scan." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c msgid "Serializer in use" -msgstr "Serializer ginagamit" +msgstr "Serializer ay ginagamit" #: shared-bindings/ssl/SSLContext.c msgid "Server side context cannot have hostname" -msgstr "" +msgstr "Server side context ay hindi pwede magkaroon ng hostname" #: ports/cxd56/common-hal/camera/Camera.c msgid "Size not supported" -msgstr "" +msgstr "Size ay hindi suportado" #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "Slice and value different lengths." -msgstr "Slice at value iba't ibang haba." +msgstr "Slice at value ay iba iba ang haba." #: shared-bindings/displayio/Bitmap.c shared-bindings/displayio/Group.c #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Hindi suportado ang Slices" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" -msgstr "" +msgstr "SocketPool ay pwede lang gamitin sa wifi.radio" #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" -msgstr "" +msgstr "Ang pinagmulan at patutunguhan ng buffer ay dapat na pareho ang haba" #: shared-bindings/paralleldisplaybus/ParallelBus.c msgid "Specify exactly one of data0 or data_pins" @@ -1969,21 +2091,9 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Ang bits_per_sample ng sample ay hindi tugma sa mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Ang channel count ng sample ay hindi tugma sa mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Ang sample rate ng sample ay hindi tugma sa mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Ang signedness ng sample hindi tugma sa mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2003,7 +2113,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2011,6 +2123,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2141,6 +2257,10 @@ msgstr "Hindi ma-init ang parser" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2235,15 +2355,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "Hindi supportadong tipo ng bitmap" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Hindi supportadong format" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2253,14 +2370,12 @@ msgid "Update failed" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2294,10 +2409,12 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2320,6 +2437,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2333,6 +2451,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2393,6 +2512,10 @@ msgstr "a bytes-like object ay kailangan" msgid "addresses is empty" msgstr "walang laman ang address" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2417,6 +2540,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2467,6 +2594,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2503,6 +2634,10 @@ msgstr "masamang typecode" msgid "binary op %q not implemented" msgstr "binary op %q hindi implemented" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2515,6 +2650,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample ay dapat 8 o 16" @@ -2598,7 +2742,7 @@ msgstr "hindi ma i-assign sa expression" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2610,7 +2754,7 @@ msgstr "hindi ma-convert %s sa complex" #: py/obj.c #, c-format msgid "can't convert %s to float" -msgstr "hindi ma-convert %s sa int" +msgstr "hindi ma-convert %s sa float" #: py/objint.c py/runtime.c #, c-format @@ -2653,6 +2797,10 @@ msgstr "hindi mabura ang expression" msgid "can't do binary op between '%q' and '%q'" msgstr "hindi magawa ang binary op sa gitna ng '%q' at '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "hindi maaaring ma-convert ang ' %q' sa 'bool'" @@ -2719,10 +2867,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2761,7 +2905,7 @@ msgstr "" #: py/emitnative.c msgid "casting" -msgstr "casting" +msgstr "paghahagis" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "channel re-init" @@ -3065,7 +3209,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "kailangan ng format ng dict" #: py/objdeque.c @@ -3115,7 +3259,8 @@ msgstr "function nangangailangan ng keyword argument '%q'" msgid "function missing required positional argument #%d" msgstr "function nangangailangan ng positional argument #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3199,10 +3344,6 @@ msgstr "ang mga indeks ay dapat na integer" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" @@ -3268,7 +3409,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3399,10 +3540,6 @@ msgstr "label '%d' kailangan na i-define" msgid "label redefined" msgstr "ang label ay na-define ulit" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs at rhs ay dapat magkasundo" @@ -3456,7 +3593,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3534,7 +3671,7 @@ msgid "must use keyword argument for key function" msgstr "dapat gumamit ng keyword argument para sa key function" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "name '%q' ay hindi defined" #: py/runtime.c @@ -3598,7 +3735,7 @@ msgstr "no binding para sa nonlocal, nahanap" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3807,6 +3944,10 @@ msgstr "ord() umaasa ng character pero string ng %d haba ang nakita" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3831,6 +3972,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overflow nagcoconvert ng long int sa machine word" @@ -3903,7 +4052,7 @@ msgstr "" #: py/builtinimport.c msgid "relative import" -msgstr "relative import" +msgstr "kamag-anak na import" #: py/obj.c #, c-format @@ -3940,6 +4089,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3957,6 +4110,10 @@ msgstr "script kompilasyon hindi supportado" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3977,13 +4134,17 @@ msgstr "sign hindi maari sa integer format specifier 'c'" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" #: py/objint.c py/sequence.c msgid "small int overflow" -msgstr "small int overflow" +msgstr "maliit na int overflow" #: main.c msgid "soft reboot\n" @@ -4050,18 +4211,6 @@ msgstr "indeks ng string wala sa sakop" msgid "string indices must be integers, not %s" msgstr "ang indeks ng string ay dapat na integer, hindi %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index hindi maabot" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: walang fields" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "substring hindi nahanap" @@ -4074,10 +4223,6 @@ msgstr "super() hindi mahanap ang sarili" msgid "syntax error in JSON" msgstr "sintaks error sa JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "may pagkakamali sa sintaks sa uctypes descriptor" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4167,11 +4312,11 @@ msgid "tx and rx cannot both be None" msgstr "tx at rx hindi pwedeng parehas na None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "hindi maari ang type na '%q' para sa base type" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "hindi puede ang type para sa base type" #: py/runtime.c @@ -4186,10 +4331,6 @@ msgstr "type kumuhuha ng 1 o 3 arguments" msgid "ulonglong too large" msgstr "ulonglong masyadong malaki" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "unary op %q hindi implemented" - #: py/parse.c msgid "unexpected indent" msgstr "hindi inaasahang indent" @@ -4237,7 +4378,9 @@ msgstr "" msgid "unreadable attribute" msgstr "hindi mabasa ang attribute" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "Hindi supportadong tipo ng %q" @@ -4315,11 +4458,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4382,6 +4520,36 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Unsupported format" +#~ msgstr "Hindi supportadong format" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Dapat sunurin ng Data chunk ang fmt chunk" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Ang bits_per_sample ng sample ay hindi tugma sa mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Ang channel count ng sample ay hindi tugma sa mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Ang sample rate ng sample ay hindi tugma sa mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Ang signedness ng sample hindi tugma sa mixer" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index hindi maabot" + +#~ msgid "struct: no fields" +#~ msgstr "struct: walang fields" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "may pagkakamali sa sintaks sa uctypes descriptor" + +#~ msgid "unary op %q not implemented" +#~ msgstr "unary op %q hindi implemented" + #~ msgid "EXTINT channel already in use" #~ msgstr "Ginagamit na ang EXTINT channel" @@ -4464,13 +4632,13 @@ msgstr "" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' object ay hindi sumusuporta sa pagtanggal ng item" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' object ay hindi iterator" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' object hindi matatawag" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' object ay hindi ma i-iterable" #~ msgid "'%s' object is not subscriptable" @@ -5141,7 +5309,7 @@ msgstr "" #~ msgid "frequency can only be either 80Mhz or 160MHz" #~ msgstr "ang frequency ay dapat 80Mhz or 160MHz lamang" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "ang function ay hindi kumukuha ng mga argumento ng keyword" #~ msgid "impossible baudrate" @@ -5211,7 +5379,7 @@ msgstr "" #~ msgid "name must be a string" #~ msgstr "ang keywords dapat strings" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "name muling ginamit para sa argument" #~ msgid "no available NIC" diff --git a/locale/fr.po b/locale/fr.po index a132f0a4922cd..f871c669f93ed 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-20 16:56+0000\n" -"Last-Translator: jessyjones \n" +"PO-Revision-Date: 2025-08-03 08:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -32,8 +32,7 @@ msgid "" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" "\n" -"Le code a été arrêté par l'actualisation automatique. Rechargement " -"prochain.\n" +"Code arreté par rehargement auto. Rechargement imminent.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -42,8 +41,7 @@ msgid "" "issues." msgstr "" "\n" -"Merci de créer un incident avec votre programme sur github.com/adafruit/" -"circuitpython/issues." +"Veuillez créer un incident sur github.com/adafruit/circuitpython/issues." #: supervisor/shared/safe_mode.c msgid "" @@ -51,7 +49,7 @@ msgid "" "Press reset to exit safe mode.\n" msgstr "" "\n" -"Appuyer sur reset pour sortir du mode sûr.\n" +"Appuyer sur reset pour sortir du mode sans échec.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -59,7 +57,7 @@ msgid "" "You are in safe mode because:\n" msgstr "" "\n" -"Le mode sûr est actif pour cette raison:\n" +"Le mode sans échec est actif pour cette raison:\n" #: py/obj.c msgid " File \"%q\"" @@ -91,24 +89,24 @@ msgstr "%%c nécessite un chiffre entier 'int' ou un caractère 'char'" msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" -"%d broches d'adresse, %d broches RGB et %d pour tile indique une hauteur de " -"%d, et non %d" +"%d broches d'adresse, %d broches RGB et %d pour 'tiles' indique une hauteur " +"de %d, et non %d" #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q et %q contiennent des broches en double" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q et %q doivent être différents" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "%q and %q must share a clock unit" -msgstr "" +msgstr "%q et %q doivent partager une unité d'horloge" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "%q cannot be changed once mode is set to %q" -msgstr "" +msgstr "%q ne peut être modifié lorsque le mode est configuré à %q" #: shared-bindings/microcontroller/Pin.c msgid "%q contains duplicate pins" @@ -118,7 +116,11 @@ msgstr "%q contient des broches en double" msgid "%q failure: %d" msgstr "Échec de %q : %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q dans %q doit être du type %q ou %q, pas %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q dans %q doit être de type %q, pas %q" @@ -170,7 +172,7 @@ msgstr "La longueur de %q doit être <= %d" msgid "%q length must be >= %d" msgstr "La longueur de %q doit être >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "% déplacé de %q à %q" @@ -225,20 +227,22 @@ msgstr "%q doit être un array de type 'h'" #: shared-bindings/audiobusio/PDMIn.c msgid "%q must be multiple of 8." -msgstr "" +msgstr "%q doit être un multiple de 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q doit être de type %q ou %q, pas %q" #: shared-bindings/jpegio/JpegDecoder.c msgid "%q must be of type %q, %q, or %q, not %q" -msgstr "" +msgstr "%q doit être de type %q, %q ou %q, pas %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q doit être de type %q, pas %q" @@ -270,7 +274,7 @@ msgstr "le pas ne peut être zéro dans %q" #: shared-module/bitbangio/I2C.c msgid "%q too long" -msgstr "" +msgstr "%q trop long" #: py/bc.c py/objnamedtuple.c msgid "%q() takes %d positional arguments but %d were given" @@ -278,13 +282,14 @@ msgstr "%q() prend %d paramètres de position mais %d ont été donnés" #: shared-module/jpegio/JpegDecoder.c msgid "%q() without %q()" -msgstr "" +msgstr "%q() sans %q()" #: shared-bindings/usb_hid/Device.c msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, et %q doivent tous être de la même longueur" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -320,7 +325,7 @@ msgid "'%q' object does not support '%q'" msgstr "l'objet '%q' ne supporte pas '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "l'objet '%q' n'est pas un itérateur" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -328,7 +333,7 @@ msgid "'%q' object is not callable" msgstr "l'objet '%q' ne peut pas être appelé" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "l'objet '%q' n'est pas itérable" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -426,12 +431,16 @@ msgstr "'data' nécessite au moins 2 paramètres" #: py/compile.c msgid "'data' requires integer arguments" -msgstr "'data' nécessite des paramètre de chiffres entiers" +msgstr "'data' nécessite des paramètre de types entiers" #: py/compile.c msgid "'label' requires 1 argument" msgstr "'label' nécessite 1 paramètre" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' n'est pas implémenté" + #: py/compile.c msgid "'return' outside function" msgstr "'return' dehors d'une fonction" @@ -459,9 +468,8 @@ msgstr ", dans %q\n" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c -#, fuzzy msgid ".show(x) removed. Use .root_group = x" -msgstr ".show(x) n'est plus disponible. Merci d'utiliser .root_group = x" +msgstr ".show(x) retiré. Utilisez .root_group = x" #: py/objcomplex.c msgid "0.0 to a complex power" @@ -473,7 +481,7 @@ msgstr "pow() non supporté avec 3 paramètres" #: ports/raspberrypi/common-hal/wifi/Radio.c msgid "AP could not be started" -msgstr "Le point d'accès n'a pas pu être démarré" +msgstr "Le point d'accès AP n'a pas pu être démarré" #: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c #, c-format @@ -504,7 +512,7 @@ msgstr "Tous les périphériques I2C sont utilisés" #: ports/espressif/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "All RX FIFOs in use" -msgstr "Tout les RX FIFOs sont utilisé" +msgstr "Tout les RX FIFOs sont utilisés" #: ports/espressif/common-hal/busio/SPI.c ports/nordic/common-hal/busio/SPI.c msgid "All SPI peripherals are in use" @@ -522,7 +530,7 @@ msgstr "Tout les canaux sont utilisés" #: ports/raspberrypi/common-hal/usb_host/Port.c msgid "All dma channels in use" -msgstr "Toutes les canals DMA sont utilisées" +msgstr "Tout les canaux DMA sont utilisés" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "All event channels in use" @@ -552,7 +560,6 @@ msgstr "Tous les minuteurs pour cette broche sont utilisés" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Tous les minuteurs sont utilisés" @@ -565,6 +572,10 @@ msgstr "S'annonce déjà." msgid "Already have all-matches listener" msgstr "Il y a déjà un auditeur all-matches" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Déjà en cours" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -574,8 +585,9 @@ msgstr "Déjà en cours d'exécution" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" -msgstr "Déjà à la recherche des réseaux wifi" +msgstr "Déjà à la recherche des réseaux WiFi" #: shared-module/os/getenv.c #, c-format @@ -598,7 +610,11 @@ msgstr "L'array doit contenir des demi-mots (type 'H')" #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c msgid "Array values should be single bytes." -msgstr "Les valeurs de l'array doivent être des octets singuliers." +msgstr "Les valeurs du tableau doivent être constituées d'un seul octet." + +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "Transfert Async SPI sur ce bus en cours, patientez." #: shared-module/memorymonitor/AllocationAlarm.c #, c-format @@ -609,6 +625,11 @@ msgstr "Tentative d'allocation de %d blocs" msgid "Audio conversion not implemented" msgstr "La conversion audio n'est pas implémentée" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Erreur source audio" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN n'est pas utilisé avec un mot de passe" @@ -626,8 +647,8 @@ msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -"Auto-chargement activé. Copiez ou sauvegardez les fichiers via USB pour les " -"lancer ou démarrez le REPL pour le désactiver.\n" +"Auto-chargement activé. Sauvegardez les fichiers via USB pour les lancer ou " +"démarrez le REPL pour le désactiver.\n" #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" @@ -678,13 +699,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "La longueur du tampon %d est trop grande. Il doit être inférieur à %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "La longueur de la mémoire tampon doit être un multiple de 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "La mémoire tampon doit être un multiple de 512" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Tampon doit être un multiple de %d octets" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -696,7 +717,7 @@ msgstr "Tampon trop court de %d octets" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/struct/__init__.c shared-module/struct/__init__.c msgid "Buffer too small" -msgstr "Tampon trop court" +msgstr "Tampon trop petit" #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c @@ -737,19 +758,24 @@ msgstr "L'alarme ne peut être que sur TRC IO depuis un sommeil profond." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on one low pin while others alarm high from deep sleep." msgstr "" -"L'alarme peut seulement être sur une broche basse tandis que d'autres " -"alarment sont sur des broches hautes depuis le sommeil profond." +"Ne peut déclencher l'alarme que sur une broche en état bas tandis que les " +"autres déclenchent l'alarme sur une broche à l'état haut à partir du sommeil " +"profond." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on two low pins from deep sleep." msgstr "" -"L'alarme peut seulement être sur deux broches basses depuis le sommeil " -"profond." +"Peut uniquement déclencher une alarme à partir de deux broches configurées " +"en niveau bas depuis le mode de sommeil profond." + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "Impossible de construire AudioOut , le canal est déja ouvert" #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" -msgstr "Impossible de définir CCCD sur une caractéristique locale" +msgstr "Impossible de définir BLE CCCD sur une caractéristique locale" #: shared-bindings/storage/__init__.c shared-bindings/usb_cdc/__init__.c #: shared-bindings/usb_hid/__init__.c shared-bindings/usb_midi/__init__.c @@ -760,7 +786,8 @@ msgstr "Impossible de changer de périphérique USB maintenant" #: shared-bindings/_bleio/Adapter.c msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "" -"Un nouveau Adapter ne peut être créé ; Adapter; utilisez _bleio.adapter;" +"Impossible de créer un nouvel adaptateur ; utilisez l'adaptateur existant " +"via _bleio.adapter. ;" #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c @@ -773,7 +800,8 @@ msgstr "Impossible de supprimer les valeurs" #: ports/nordic/common-hal/digitalio/DigitalInOut.c #: ports/raspberrypi/common-hal/digitalio/DigitalInOut.c msgid "Cannot get pull while in output mode" -msgstr "Ne peut être tiré ('pull') en mode sortie ('output')" +msgstr "" +"Une GPIO ne peut être en mode ('pull') si déja en mode de sortie ('output')" #: ports/nordic/common-hal/microcontroller/Processor.c msgid "Cannot get temperature" @@ -782,25 +810,25 @@ msgstr "Impossible de lire la température" #: shared-bindings/_bleio/Adapter.c msgid "Cannot have scan responses for extended, connectable advertisements." msgstr "" -"Impossible d'avoir des réponses d'analyse pour les publicités étendues et " -"connectables." +"Les publicités BLE étendues et connectables ne peuvent pas inclure de " +"réponses au scan." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot pull on input-only pin." -msgstr "Ne peut tirer ('pull') sur une broche d'entrée ('input') seule." +msgstr "Ne peut tirer ('pull') sur une broche d'entrée ('input') ." #: shared-bindings/audiobusio/PDMIn.c msgid "Cannot record to a file" msgstr "Impossible d'enregistrer vers un fichier" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Ne peut démonter '/' quand est visible par USB." +msgid "Cannot remount path when visible via USB." +msgstr "" +"Impossible de remonter le chemin d'accès lorsqu'il est visible via USB." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." -msgstr "" -"Impossible d'affecter une valeur quand la direction est entrante ('input')." +msgstr "Impossible d'affecter une valeur quand le GPIO est entrant ('input')." #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -809,18 +837,21 @@ msgstr "Impossible de spécifier RTS ou CTS en mode RS485" #: py/objslice.c msgid "Cannot subclass slice" -msgstr "On ne peut faire de sous-classes de tranches" +msgstr "On ne peut faire des tranches de sous-classes" + +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" +"Impossible d'utiliser en même temps les GPIO 0 à 15 et les GPIO 32 à 45" #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" -"Impossible de réveiller via une bordure d'une broche, seulement via un niveau" +"Impossible de réveiller par une broche , seulement via un changement d'état" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge. Only level." -msgstr "" -"Impossible de réveiller via une bordure d'une broche. Seulement via un " -"niveau." +msgstr "Impossible de réveiller via une broche. Seulement via un niveau." #: shared-bindings/_bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" @@ -828,11 +859,11 @@ msgstr "Ecriture sur 'CharacteristicBuffer' non fournie" #: supervisor/shared/safe_mode.c msgid "CircuitPython core code crashed hard. Whoops!\n" -msgstr "Le code principal de CircuitPython s'est complètement planté. Oups !\n" +msgstr "Le noyau CircuitPython est planté !\n" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Clock unit in use" -msgstr "Horloge en cours d'utilisation" +msgstr "Horloge en fonction" #: shared-bindings/_bleio/Connection.c msgid "" @@ -848,27 +879,36 @@ msgstr "Les tableaux de coordonnées sont de longueur différentes" #: shared-bindings/bitmaptools/__init__.c msgid "Coordinate arrays types have different sizes" -msgstr "Les types des matrices de coordonnées sont de longueur différentes" +msgstr "Les types des tableaux de coordonnées sont de longueur différentes" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "Ne peut publier sur le Topic ROS" #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" -msgstr "Impossible de définir l'adresse" +msgstr "Ne peux définir l'adresse" #: ports/stm/common-hal/busio/UART.c msgid "Could not start interrupt, RX busy" -msgstr "Impossible de démarrer l'interruption, RX occupé" +msgstr "Ne peux lancer l'interruption, RX occupé" #: shared-module/audiomp3/MP3Decoder.c msgid "Couldn't allocate decoder" -msgstr "Impossible d'allouer le décodeur" +msgstr "Ne peux allouer le décodeur" + +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Erreur critique lors du reboot à chaud, reset requis: %d" #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" -msgstr "Erreur d'initialisation du canal DAC" +msgstr "Erreur init du canal DAC" #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Device Init Error" -msgstr "Erreur d'initialisation du périphérique DAC" +msgstr "Erreur init périphérique DAC" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "DAC already in use" @@ -879,36 +919,33 @@ msgstr "DAC déjà utilisé" msgid "Data 0 pin must be byte aligned" msgstr "La broche 'Data 0' doit être aligné sur l'octet" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Un bloc de données doit suivre un bloc fmt" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" -msgstr "" +msgstr "Erreur de format de données (endommagées)" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Data not supported with directed advertising" -msgstr "Les données ne sont pas supportées avec les annonces directes" +msgstr "Données non supportées avec les annonces directes" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Data too large for advertisement packet" -msgstr "Données trop volumineuses pour un paquet d'avertissement" +msgstr "Données trop grandes pour un paquet d'avertissement" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Deep sleep pins must use a rising edge with pulldown" msgstr "" -"Les broches de sommeil profond doivent utiliser un montant avec un pulldown" +"Les broches de sommeil profond doivent utiliser un front montant avec " +"pulldown" #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." -msgstr "La capacité de destination est plus petite que 'destination_length'." +msgstr "La capacité de destination est inférieure à 'destination_length'." #: shared-module/jpegio/JpegDecoder.c msgid "Device error or wrong termination of input stream" -msgstr "" +msgstr "Erreur de l'appareil ou terminaison incorrecte du flux d'entrée" #: ports/nordic/common-hal/audiobusio/I2SOut.c msgid "Device in use" @@ -917,13 +954,13 @@ msgstr "Appareil utilisé" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display must have a 16 bit colorspace." -msgstr "L'affichage doit avoir un espace colorimétrique de 16 bits." +msgstr "L'affichage requier un espace colorimétrique de 16 bits." #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Display rotation must be in 90 degree increments" -msgstr "La rotation d'affichage doit se faire par incréments de 90 degrés" +msgstr "La rotation d'affichage se fait par incréments de 90 degrés" #: main.c msgid "Done" @@ -931,12 +968,11 @@ msgstr "Terminé" #: shared-bindings/digitalio/DigitalInOut.c msgid "Drive mode not used when direction is input." -msgstr "" -"Le mode Drive n'est pas utilisé quand la direction est entrante ('input')." +msgstr "Le mode Drive n'est pas utilisé en entrant ('input')." #: py/obj.c msgid "During handling of the above exception, another exception occurred:" -msgstr "Pendant la gestion de cette exception, un autre s'est produite:" +msgstr "Durant la gestion de cette exception, une autre s'est produite:" #: shared-bindings/aesio/aes.c msgid "ECB only operates on 16 bytes at a time" @@ -967,7 +1003,7 @@ msgstr "" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "FFT is defined for ndarrays only" -msgstr "La FFT est définie uniquement pour les ndarrays" +msgstr "La FFT n'est définie que pour les ndarrays" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "FFT is implemented for linear arrays only" @@ -975,7 +1011,7 @@ msgstr "FFT n'est implémenté que pour les arrays linéaires" #: shared-bindings/ps2io/Ps2.c msgid "Failed sending command." -msgstr "Échec de l'envoi de la commande." +msgstr "Échec envoi de la commande." #: ports/nordic/sd_mutex.c #, c-format @@ -990,8 +1026,8 @@ msgstr "Echec de l'ajout de l'enregistrement TXT" msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -"Echec de l'ajout de l'enregistrement TXT; caractères non-octets ni texte " -"trouvés dans txt_records" +"Echec d'enregistrement TXT; caractères mal formatés type string ou octets " +"dans txt_records" #: shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" @@ -999,33 +1035,65 @@ msgstr "Échec d'allocation du tampon %q" #: ports/espressif/common-hal/wifi/__init__.c msgid "Failed to allocate Wifi memory" -msgstr "Impossible d'allouer la mémoire pour Wifi" +msgstr "Echec allocation mémoire pour Wifi" #: ports/espressif/common-hal/wifi/ScannedNetworks.c msgid "Failed to allocate wifi scan memory" -msgstr "Impossible d'allouer la mémoire pour le scan wifi" +msgstr "Scan wifi: échec allocation mémoire" #: ports/stm/common-hal/audiopwmio/PWMAudioOut.c msgid "Failed to buffer the sample" -msgstr "Échec du tamponage de l'échantillon" +msgstr "Échec du tampon de l'échantillon" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" -msgstr "Impossible de se connecter : erreur interne" +msgstr "Connection impossible: erreur interne" #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" -msgstr "Impossible de se connecter: délai dépassé" +msgstr "Connection impossible: délai dépassé" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Échec de la création de canaux continus : argument invalide" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Échec de la création de canaux continus : état invalide" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Échec de la création de canaux continus : pas de mémoire" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Échec de la création de canaux continus : introuvable" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Impossible d'activer les canaux continus" #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" -msgstr "Impossible d'analyser le fichier MP3" +msgstr "Echec de parcours du fichier MP3" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Impossible d'enregistrer les 'events callback' des canaux continus" #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" -msgstr "Impossible de libérer mutex, err 0x%04x" +msgstr "Écchec de liberaton du mutex, err 0x%04x" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "hostname impossible à initialiser" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Impossible de lancer async audio" #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." @@ -1035,41 +1103,43 @@ msgstr "Échec de l'écriture vers flash interne." msgid "File exists" msgstr "Le fichier existe" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Fichier non trouvé" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filtres trop complexe" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is duplicate" -msgstr "Le logiciel est identique" +msgstr "Le Firmware est identique" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is invalid" -msgstr "Logiciel invalide" +msgstr "Firmware invalide" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is too big" -msgstr "Logiciel trop volumineux" +msgstr "Firmware trop grand" #: shared-bindings/bitmaptools/__init__.c msgid "For L8 colorspace, input bitmap must have 8 bits per pixel" msgstr "" -"Avec l'espace de couleur L8, l'image d'entrée doit avoir 8 bits par pixel" +"Pour l'espace de couleur L8, l'image bitmap doit avoir 8 bits par pixel" #: shared-bindings/bitmaptools/__init__.c msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -"Avec l'espace de couleur RVB, l'image d'entrée doit avoir 16 bits par pixel" +"Pour l'espace de couleur RVB, l'image d'entrée doit avoir 16 bits par pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" -msgstr "Format non pris en charge" +msgstr "Format non supporté" #: ports/mimxrt10xx/common-hal/microcontroller/Processor.c msgid "" @@ -1081,7 +1151,7 @@ msgstr "" #: shared-bindings/bitbangio/I2C.c shared-bindings/bitbangio/SPI.c #: shared-bindings/busio/I2C.c shared-bindings/busio/SPI.c msgid "Function requires lock" -msgstr "La fonction nécessite un verrou ('lock')" +msgstr "La fonction requier un verrou ('lock')" #: ports/cxd56/common-hal/gnss/GNSS.c msgid "GNSS init" @@ -1135,13 +1205,13 @@ msgstr "Taille de tampon incorrecte" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Init program size invalid" -msgstr "Taille du programme d'initialisation non valide" +msgstr "Taille du programme d'initialisation invalide" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin direction conflicts with initial out pin direction" msgstr "" -"Direction initiale de \"set pin\" est en conflit avec la direction initiale " -"de \"out pin\"" +"Direction initiale de \"set pin\" est en conflit avec la direction de \"out " +"pin\"" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Initial set pin state conflicts with initial out pin state" @@ -1152,8 +1222,7 @@ msgstr "" #, c-format msgid "Input buffer length (%d) must be a multiple of the strand count (%d)" msgstr "" -"La taille (%d) du tampon d'entrée doit être un multiple du nombre (%d) de " -"brins" +"La taille (%d) du tampon d'entrée doit être au modulo du nombre (%d) de brins" #: ports/atmel-samd/common-hal/pulseio/PulseIn.c msgid "Input taking too long" @@ -1175,13 +1244,14 @@ msgstr "Chiffrement insuffisant" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient memory pool for the image" -msgstr "" +msgstr "Le pool de mémoire est insuffisant pour l'image" #: shared-module/jpegio/JpegDecoder.c msgid "Insufficient stream input buffer" -msgstr "" +msgstr "Tampon de flux d'entrée insuffisant" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "L'interface doit être lancée" @@ -1213,7 +1283,7 @@ msgstr "Erreur interne #%d" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-bindings/pwmio/PWMOut.c msgid "Internal resource(s) in use" -msgstr "" +msgstr "Ressource(s) interne(s) en utilisation" #: supervisor/shared/safe_mode.c msgid "Internal watchdog timer expired." @@ -1225,24 +1295,28 @@ msgstr "Erreur d'interruption." #: shared-module/jpegio/JpegDecoder.c msgid "Interrupted by output function" -msgstr "" +msgstr "Interrompu par la fonction de sortie" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "%q invalide" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "%q et %q invalides" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1253,7 +1327,7 @@ msgstr "Broche invalide pour '%q'" #: ports/stm/common-hal/analogio/AnalogIn.c msgid "Invalid ADC Unit value" -msgstr "Valeur d'unité ADC non valide" +msgstr "Unité invalide pour l'ADC" #: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c @@ -1268,13 +1342,17 @@ msgstr "BSSID invalide" msgid "Invalid MAC address" msgstr "Adresse MAC invalide" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "ROS domain ID invalide" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Paramètre invalide" #: shared-module/displayio/Bitmap.c msgid "Invalid bits per value" -msgstr "Bits par valeur invalides" +msgstr "Bits invalides par valeur" #: shared-module/os/getenv.c #, c-format @@ -1292,15 +1370,16 @@ msgstr "Format invalide" #: shared-module/audiocore/WaveFile.c msgid "Invalid format chunk size" -msgstr "Taille de bloc de formatage invalide" +msgstr "Formatage de bloc invalide" #: shared-bindings/wifi/Radio.c msgid "Invalid hex password" -msgstr "Mot de passe hexadécimal invalide" +msgstr "Mot de passe hexa invalide" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" -msgstr "Adresse MAC multicast invalide" +msgstr "MAC address multicast invalide" #: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" @@ -1308,9 +1387,10 @@ msgstr "Taille invalide" #: shared-module/ssl/SSLSocket.c msgid "Invalid socket for TLS" -msgstr "Socket non valide pour TLS" +msgstr "Socket invalide pour TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "État invalide" @@ -1340,19 +1420,25 @@ msgstr "Ce calque est déjà dans un groupe" #: shared-module/displayio/Group.c msgid "Layer must be a Group or TileGrid subclass" -msgstr "Le calque doit être une sous-classe de Group ou TileGrid" +msgstr "La couche doit être une sous-classe de Group ou TileGrid" #: shared-bindings/audiocore/RawSample.c msgid "Length of %q must be an even multiple of channel_count * type_size" -msgstr "" +msgstr "Longueur de %q doit être un multiple pair de channel_count * type_size" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" -msgstr "Adresse physique (MAC) invalide" +msgstr "MAC Address invalide" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" -msgstr "" +msgstr "Sécurité MITM n'est pas supportée" + +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "Erreur d'horloge MMC/SDIO %x" #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" @@ -1361,7 +1447,7 @@ msgstr "Le mapping doit être un tuple" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" -msgstr "La taille des données ne correspond pas" +msgstr "Non correspondance de la taille des données" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched swap flag" @@ -1401,32 +1487,33 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Missing jmp_pin. %q[%u] jumps on pin" -msgstr "" +msgstr "Manque jmp_pin. %q[%u] passe à la broche suivante" #: shared-module/storage/__init__.c msgid "Mount point directory missing" -msgstr "" +msgstr "Point de montage manquant" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Doit être une sous-classe de %q." #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c msgid "Must provide 5/6/5 RGB pins" -msgstr "5/6/5 broches RGB doivent être fournies" +msgstr "broches RGB 5/6/5 requises" #: ports/mimxrt10xx/common-hal/busio/SPI.c shared-bindings/busio/SPI.c msgid "Must provide MISO or MOSI pin" -msgstr "Doit fournir une broche MISO ou MOSI" +msgstr "Fournir broches MISO ou MOSI" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "Must use a multiple of 6 rgb pins, not %d" -msgstr "Doit utiliser un multiple de 6 broches RVB, pas %d" +msgstr "Demande un multiple de 6 broches RVB, pas %d" #: supervisor/shared/safe_mode.c msgid "NLR jump failed. Likely memory corruption." -msgstr "Saut NLR échoué. Corruption de mémoire probable." +msgstr "Echec saut NLR . Mémoire probablement corompue." #: ports/espressif/common-hal/nvm/ByteArray.c msgid "NVS Error" @@ -1438,12 +1525,11 @@ msgstr "Nom ou service inconnu" #: shared-bindings/displayio/TileGrid.c msgid "New bitmap must be same size as old bitmap" -msgstr "La taille du nouveau bitmap doit être la même que l'ancien" +msgstr "La taille du nouveau bitmap doit être indentique à l'ancien" #: ports/espressif/common-hal/_bleio/__init__.c -#, fuzzy msgid "Nimble out of memory" -msgstr "Nimble n'a plus de mémoire" +msgstr "Mémoire nimble épuisée" #: ports/atmel-samd/common-hal/busio/UART.c #: ports/espressif/common-hal/busio/SPI.c @@ -1474,30 +1560,30 @@ msgstr "Pas de DAC sur la puce" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "No DMA channel found" -msgstr "Aucun canal DMA trouvé" +msgstr "Pas de canal DMA trouvé" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "No DMA pacing timer found" -msgstr "Aucun minuteur de rythme DMA trouvé" +msgstr "Aucun temporisateur de régulation DMA trouvé" #: shared-module/adafruit_bus_device/i2c_device/I2CDevice.c #, c-format msgid "No I2C device at address: 0x%x" -msgstr "Aucun périphérique I2S à l'adresse : 0x%x" +msgstr "Pas de périphérique I2S à l'adresse : 0x%x" #: supervisor/shared/web_workflow/web_workflow.c msgid "No IP" -msgstr "Aucune IP" +msgstr "Pas d' IP" #: ports/atmel-samd/common-hal/microcontroller/__init__.c #: ports/cxd56/common-hal/microcontroller/__init__.c #: ports/mimxrt10xx/common-hal/microcontroller/__init__.c msgid "No bootloader present" -msgstr "" +msgstr "Aucun bootloader présent" #: shared-module/usb/core/Device.c msgid "No configuration set" -msgstr "Pas de configuration définie" +msgstr "Aucune configuration" #: shared-bindings/_bleio/PacketBuffer.c msgid "No connection: length cannot be determined" @@ -1511,23 +1597,23 @@ msgstr "Pas de bus %q par défaut" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/atmel-samd/common-hal/touchio/TouchIn.c msgid "No free GCLKs" -msgstr "Pas de GCLK libre" +msgstr "Aucun GCLK libre" #: shared-bindings/os/__init__.c msgid "No hardware random available" -msgstr "Aucunes source de valeurs aléatoire matérielle disponible" +msgstr "Aucune source matérielle de valeurs aléatoires disponible" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in in program" -msgstr "Programme n'a pas de \"in\"" +msgstr "Programme sans \"in\"" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "No in or out in program" -msgstr "Programme n'a aucun \"in\" ni \"out\"" +msgstr "Programme sans \"in\" ni \"out\"" #: py/objint.c shared-bindings/time/__init__.c msgid "No long integer support" -msgstr "Pas de support pour chiffre entier long" +msgstr "Pas de support pour les entiers longs" #: shared-bindings/wifi/Radio.c msgid "No network with that ssid" @@ -1546,15 +1632,19 @@ msgstr "Aucun pull up trouvé sur SDA ou SCL; vérifiez votre câblage" #: shared-module/touchio/TouchIn.c msgid "No pulldown on pin; 1Mohm recommended" -msgstr "Pas de pulldown sur la broche ; 1Mohm recommandé" +msgstr "Pas de pulldown sur la broche ; 1Mohm requis" + +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Pas de pullup sur la broche ; 1Mohm recommandé" #: py/moderrno.c msgid "No space left on device" -msgstr "Aucun espace libre sur le dispositif" +msgstr "Plus d'espace libre sur le dispositif" #: py/moderrno.c msgid "No such device" -msgstr "Aucun périphérique correspondant" +msgstr "Périphérique introuvable" #: py/moderrno.c msgid "No such file/directory" @@ -1570,7 +1660,7 @@ msgstr "Pas de port usb hôte initialisé" #: ports/nordic/common-hal/_bleio/__init__.c msgid "Nordic system firmware out of memory" -msgstr "Logiciel système Nordic n'a plus de mémoire" +msgstr "Firmware Nordic : mémoire insuffisante" #: shared-bindings/ipaddress/IPv4Address.c shared-bindings/ipaddress/__init__.c msgid "Not a valid IP string" @@ -1589,19 +1679,18 @@ msgstr "Ne joue pas" #: shared-module/jpegio/JpegDecoder.c msgid "Not supported JPEG standard" -msgstr "" +msgstr "Standard JPEG non supporté" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Le nombre de data_pins doit être 8 ou 16, et non %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Nombre de data_pins doit être %d ou %d, pas %d" #: shared-bindings/util.c msgid "" "Object has been deinitialized and can no longer be used. Create a new object." -msgstr "" -"L'objet a été dés-initialisé et ne peut plus être utilisé. Créez un nouvel " -"objet." +msgstr "Objet désinitialisé et inutilisable. Créez-en un nouveau." #: ports/nordic/common-hal/busio/UART.c msgid "Odd parity is not supported" @@ -1620,23 +1709,24 @@ msgstr "OK" #, c-format msgid "Only 8 or 16 bit mono with %dx oversampling supported." msgstr "" +"Seuls 8 ou 16 bits mono avec suréchantillonnage %dx sont pris en charge." #: ports/espressif/common-hal/wifi/__init__.c #: ports/raspberrypi/common-hal/wifi/__init__.c msgid "Only IPv4 addresses supported" -msgstr "Seulement les adresses IPv4 sont supportées" +msgstr "Seules les IPv4 sont supportées" #: ports/raspberrypi/common-hal/socketpool/Socket.c msgid "Only IPv4 sockets supported" -msgstr "Seulement les sockets IPv4 sont supportés" +msgstr "Seuls les sockets IPv4 sont supportés" #: shared-module/displayio/OnDiskBitmap.c #, c-format msgid "" "Only Windows format, uncompressed BMP supported: given header size is %d" msgstr "" -"Seulement le format BMP Windows, non compressé est supporté : la taille de " -"l'entête fournie est %d" +"Seul le format BMP Windows, non compressé est supporté : taille de l'entête " +"fournie est %d" #: shared-bindings/_bleio/Adapter.c msgid "Only connectable advertisements can be directed" @@ -1648,20 +1738,11 @@ msgstr "Seule la détection des bords est disponible sur ce matériel" #: shared-bindings/ipaddress/__init__.c msgid "Only int or string supported for ip" -msgstr "Seulement les int et string sont supportés pour une adresse IP" - -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Seulement les BMP monochromes, 4 bpp ou 8 bpp, ou 16 bpp et plus sont " -"supportés: %d bpp fournis" +msgstr "Seul les types entiers et string sont utilisés pour une adresse IP" #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." -msgstr "Une seul %q autorisée en sommeil profond." +msgstr "Une seul %q est autorisée en sommeil profond." #: ports/espressif/common-hal/espulp/ULPAlarm.c msgid "Only one %q can be set." @@ -1676,12 +1757,12 @@ msgstr "Seulement une adresse est autorisée" #: ports/nordic/common-hal/alarm/time/TimeAlarm.c #: ports/stm/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set" -msgstr "Seule une alarme alarm.time peut être définie" +msgstr "Une seule alarm.time peut être définie" #: ports/espressif/common-hal/alarm/time/TimeAlarm.c #: ports/raspberrypi/common-hal/alarm/time/TimeAlarm.c msgid "Only one alarm.time alarm can be set." -msgstr "Seulement une alarme alarm.time peut être réglée." +msgstr "Une seule alarm.time peut être réglée." #: shared-module/displayio/ColorConverter.c msgid "Only one color can be transparent at a time" @@ -1709,8 +1790,9 @@ msgstr "Mémoire insuffisante" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" -msgstr "Plus de sockets" +msgstr "Plus de sockets disponibles" #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Out-buffer elements must be <= 4 bytes long" @@ -1728,9 +1810,13 @@ msgstr "PWM slice déja utilisée" msgid "PWM slice channel A already in use" msgstr "Canal A de PWM slice est utilisé" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "Les packets du buffer SPI transfert doivent être de la même taille." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" -msgstr "" +msgstr "Erreur de paramètre" #: ports/espressif/common-hal/audiobusio/__init__.c msgid "Peripheral in use" @@ -1755,7 +1841,7 @@ msgstr "L'interruption de cette broche est déjà utilisée" #: shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c msgid "Pin is input only" -msgstr "La broche est entrée uniquement" +msgstr "La broche est en entrée uniquement" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "Pin must be on PWM Channel B" @@ -1768,17 +1854,16 @@ msgid "" "bytes. If this cannot be avoided, pass allow_inefficient=True to the " "constructor" msgstr "" -"Le brochage utilise %d octets par élément, ce qui consomme plus que le %d " -"octets idéal. Si cela ne peut pas être évité, transmettez allow_inefficient " -"= True au constructeur" +"Le brochage utilise %d octets par élément, ce qui dépasse le seuil de %d " +"octets. Si cela est inévitable, passez allow_inefficient=True au constructeur" #: ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c msgid "Pins must be sequential" -msgstr "Les broches doivent être séquentielles" +msgstr "Les broches doivent être consécutives" #: ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c msgid "Pins must be sequential GPIO pins" -msgstr "Les broches doivent être des broches GPIO à la suite" +msgstr "Les broches doivent être des broches GPIO consécutives" #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c msgid "Pins must share PWM slice" @@ -1786,23 +1871,23 @@ msgstr "Les broches doivent partager la tranche PWM" #: shared-module/usb/core/Device.c msgid "Pipe error" -msgstr "Erreur de transfert" +msgstr "Erreur de canal" #: py/builtinhelp.c msgid "Plus any modules on the filesystem\n" -msgstr "Ainsi que tout autres modules présents sur le système de fichiers\n" +msgstr "Plus tout autres modules présents sur le système de fichiers\n" #: shared-module/vectorio/Polygon.c msgid "Polygon needs at least 3 points" -msgstr "Polygon a besoin d'au moins 3 points" +msgstr "Un polygone a besoin d'au moins 3 points" #: supervisor/shared/safe_mode.c msgid "Power dipped. Make sure you are providing enough power." -msgstr "Chute de puissance. Assurez-vous de fournir suffisament de puissance." +msgstr "Chute de puissance. Assurez-vous de fournir assez de puissance." #: shared-bindings/_bleio/Adapter.c msgid "Prefix buffer must be on the heap" -msgstr "Le tampon de préfixe doit être sur la pile" +msgstr "Le tampon de préfixe doit être sur le tas" #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload.\n" @@ -1832,9 +1917,14 @@ msgstr "Taille du programme invalide" msgid "Program too long" msgstr "Programme trop long" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "Les Publishers ne peuvent être créés qu'à partir du nœud parent" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." -msgstr "Le tirage 'pull' n'est pas utilisé quand la direction est 'output'." +msgstr "" +"L'attribut \"pull\" n'est pas utilisé quand la direction est \"output\"." #: ports/raspberrypi/common-hal/countio/Counter.c msgid "RISE_AND_FALL not available on this chip" @@ -1842,7 +1932,7 @@ msgstr "RISE_AND_FALL n'est pas disponible sur cette puce" #: shared-module/displayio/OnDiskBitmap.c msgid "RLE-compressed BMP not supported" -msgstr "" +msgstr "BMP avec compression RLE non supporté" #: ports/stm/common-hal/os/__init__.c msgid "RNG DeInit Error" @@ -1852,6 +1942,26 @@ msgstr "Erreur de désinitialisation du RNG" msgid "RNG Init Error" msgstr "Erreur d'initialisation du RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "L'agent est-il connecté? ROS échoue son initialisation" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "ROS échec de configuration interne" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "Erreur d'allocation mémoire ROS" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "ROS node échoue a s'initialiser" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "Le topic ROS échoue à s'initialiser" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1895,7 +2005,7 @@ msgstr "Rafraîchissement trop tôt" #: shared-bindings/canio/RemoteTransmissionRequest.c msgid "RemoteTransmissionRequests limited to 8 bytes" -msgstr "RemoteTransmissionRequests limité à 8 octets" +msgstr "Le RemoteTransmissionRequests est limité à 8 octets" #: shared-bindings/aesio/aes.c msgid "Requested AES mode is unsupported" @@ -1903,7 +2013,7 @@ msgstr "Le mode AES demandé n'est pas supporté" #: ports/espressif/common-hal/espidf/__init__.c msgid "Requested resource not found" -msgstr "Resource demandée non trouvée" +msgstr "Ressource demandée non trouvée" #: ports/atmel-samd/common-hal/audioio/AudioOut.c msgid "Right channel unsupported" @@ -1911,11 +2021,11 @@ msgstr "Canal droit non supporté" #: shared-module/jpegio/JpegDecoder.c msgid "Right format but not supported" -msgstr "" +msgstr "Format correct mais non supporté" #: main.c msgid "Running in safe mode! Not running saved code.\n" -msgstr "Mode sans-échec ! Le code sauvegardé n'est pas éxecuté.\n" +msgstr "Mode sans échec ! Le code sauvegardé n'est pas éxecuté.\n" #: shared-module/sdcardio/SDCard.c msgid "SD card CSD format not supported" @@ -1930,10 +2040,11 @@ msgstr "Initialisation SDCard" msgid "SDIO GetCardInfo Error %d" msgstr "Erreur de SDIO GetCardInfo %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "Erreur d'initialisation SDIO %d" +msgid "SDIO Init Error %x" +msgstr "Erreur d'initialisation SDIO %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1953,12 +2064,12 @@ msgstr "Ré-initialisation du SPI" #: shared-bindings/is31fl3741/FrameBuffer.c msgid "Scale dimensions must divide by 3" -msgstr "La dimension d'échelle doit être un multiple de 3" +msgstr "Les dimensions de l'échelle doivent être un multiple de 3" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c msgid "Scan already in progress. Stop with stop_scan." -msgstr "Scan déjà en cours. Arrêtez-le avec stop_scan." +msgstr "Scan en cours. Arrêtez-le avec stop_scan." #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -1967,7 +2078,7 @@ msgstr "Sérialiseur en cours d'utilisation" #: shared-bindings/ssl/SSLContext.c msgid "Server side context cannot have hostname" -msgstr "Un contexte niveau serveur ne peut avoir de hostname" +msgstr "Un contexte serveur ne peut pas posséder de nom d'hôte" #: ports/cxd56/common-hal/camera/Camera.c msgid "Size not supported" @@ -1982,11 +2093,13 @@ msgstr "Tranche et valeur de tailles différentes." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Tranches non supportées" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool ne s'utilise qu'avec wifi.radio" @@ -2000,11 +2113,11 @@ msgstr "Spécifiez une unique broche parmi data0 ou data_pins" #: supervisor/shared/safe_mode.c msgid "Stack overflow. Increase stack size." -msgstr "" +msgstr "Débordement de pile. Augmentez la taille de pile." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" -msgstr "Fournissez l'un de monotonic_time ou epoch_time" +msgstr "Fournir l'un des éléments : monotonic_time ou epoch_time" #: shared-bindings/gnss/GNSS.c msgid "System entry must be gnss.SatelliteSystem" @@ -2016,7 +2129,8 @@ msgstr "Délais de lecture de température dépassée" #: supervisor/shared/safe_mode.c msgid "The `microcontroller` module was used to boot into safe mode." -msgstr "Le module microcontroller a été utilisé pour démarrer en mode sûr." +msgstr "" +"Le module microcontroller a été utilisé pour démarrer en mode sans échec." #: py/obj.c msgid "The above exception was the direct cause of the following exception:" @@ -2026,22 +2140,9 @@ msgstr "L'exception précédente est la cause directe de l'exception suivante:" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "La taille de rgb_pins doit être 6, 12, 18, 24 ou 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" -"Le 'bits_per_sample' de l'échantillon ne correspond pas à celui du mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Le canal de l'échantillon ne correspond pas à celui du mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "L'échantillonage de l'échantillon ne correspond pas à celui du mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Le signe de l'échantillon ne correspond pas à celui du mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "Le %q de l'échantillon ne concorde pas" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2063,7 +2164,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "La hauteur de la tuile doit diviser exactement la hauteur de l'image" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Index des tuiles hors limites" @@ -2071,6 +2174,10 @@ msgstr "Index des tuiles hors limites" msgid "Tile width must exactly divide bitmap width" msgstr "La largeur de la tuile doit diviser exactement la largeur de l'image" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper ne peut être lié à un TileGrid qu'une seule fois" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "L'heure est dans le passé." @@ -2079,7 +2186,7 @@ msgstr "L'heure est dans le passé." #: ports/nordic/common-hal/_bleio/Adapter.c #, c-format msgid "Timeout is too long: Maximum timeout length is %d seconds" -msgstr "Le délai est trop long : le délai maximal est de %d secondes" +msgstr "Délai trop long : le délai maximal est de %d secondes" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" @@ -2091,7 +2198,7 @@ msgstr "Trop de canaux dans l'échantillon." #: ports/espressif/common-hal/_bleio/Characteristic.c msgid "Too many descriptors" -msgstr "" +msgstr "Trop de descripteurs" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" @@ -2146,11 +2253,13 @@ msgstr "L'USB est occupé" #: supervisor/shared/safe_mode.c msgid "USB devices need more endpoints than are available." -msgstr "Les appareils USB nécessitent plus de connexions que disponibles." +msgstr "" +"Les périphériques USB nécessitent plus de points de terminaison que ceux " +"disponibles." #: supervisor/shared/safe_mode.c msgid "USB devices specify too many interface names." -msgstr "Les appareils USB spécifient trop de noms d'interface." +msgstr "Les appareils USB donnent trop de noms d'interface." #: shared-module/usb_hid/Device.c msgid "USB error" @@ -2184,7 +2293,7 @@ msgstr "Impossible d'allouer des tampons pour une conversion signée" #: supervisor/shared/safe_mode.c msgid "Unable to allocate to the heap." -msgstr "" +msgstr "Impossible d'allouer sur le tas." #: ports/espressif/common-hal/busio/I2C.c msgid "Unable to create lock" @@ -2204,6 +2313,10 @@ msgstr "Impossible d'initialiser le parser" msgid "Unable to read color palette data" msgstr "Impossible de lire les données de la palette de couleurs" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "Echec envoit message CAN:tous les buffer TX sont occupés" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2299,32 +2412,27 @@ msgstr "Espace de couleur non supporté" msgid "Unsupported display bus type" msgstr "Type de bus d'affichage non supporté" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Format non pris en charge" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Algorithme de hachage non supporté" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" -msgstr "" +msgstr "Type de socket non supporté" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Échec de mise à jour" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Longueur de valeur != Longueur fixe requise" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2332,7 +2440,7 @@ msgstr "Longueur de la valeur > max_length" #: ports/espressif/common-hal/espidf/__init__.c msgid "Version was invalid" -msgstr "Version est invalide" +msgstr "La version est invalide" #: ports/stm/common-hal/microcontroller/Processor.c msgid "Voltage read timed out" @@ -2344,9 +2452,7 @@ msgstr "ATTENTION : le nom de fichier de votre code a deux extensions\n" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "WatchDogTimer cannot be deinitialized once mode is set to RESET" -msgstr "" -"WatchDogTimer ne peut pas être dés-initialisé une fois que le mode est réglé " -"sur RESET" +msgstr "Le WatchDogTimer ne peut pas être réinitialisé une fois en mode RESET" #: py/builtinhelp.c #, c-format @@ -2367,9 +2473,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi : " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "Le wifi n'est pas activé" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "Le WiFi n'est pas activé" #: main.c msgid "Woken up by alarm.\n" @@ -2385,14 +2493,15 @@ msgstr "Écritures non supporté vers les Characteristic" #: ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h #: ports/atmel-samd/boards/meowmeow/mpconfigboard.h msgid "You pressed both buttons at start up." -msgstr "Vous avez appuyé les deux boutons au démarrage." +msgstr "Vous avez appuyé sur les deux boutons au démarrage." #: ports/espressif/boards/m5stack_core_basic/mpconfigboard.h #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." -msgstr "Vous avez appuyé le bouton A au démarrage." +msgstr "Vous avez appuyé sur le bouton A au démarrage." #: ports/espressif/boards/m5stack_m5paper/mpconfigboard.h msgid "You pressed button DOWN at start up." @@ -2400,16 +2509,17 @@ msgstr "Vous avez appuyé sur le bouton DOWN au démarrage." #: supervisor/shared/safe_mode.c msgid "You pressed the BOOT button at start up" -msgstr "Vous avez appuyé le bouton BOOT au démarrage" +msgstr "Vous avez appuyé sur le bouton BOOT au démarrage" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." -msgstr "" +msgstr "Vous avez appuyé sur le bouton BOOT au démarrage." #: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h msgid "You pressed the GPIO0 button at start up." -msgstr "Vous avez appuyé le bouton GPIO0 au démarrage." +msgstr "Vous avez appuyé sur le bouton GPIO0 au démarrage." #: ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.h msgid "You pressed the Rec button at start up." @@ -2417,7 +2527,7 @@ msgstr "Vous avez appuyé sur le bouton Rec au démarrage." #: ports/espressif/boards/adafruit_feather_esp32_v2/mpconfigboard.h msgid "You pressed the SW38 button at start up." -msgstr "Vous avez appuyé le bouton SW38 au démarrage." +msgstr "Vous avez appuyé sur le bouton SW38 au démarrage." #: ports/espressif/boards/hardkernel_odroid_go/mpconfigboard.h #: ports/espressif/boards/vidi_x/mpconfigboard.h @@ -2429,15 +2539,15 @@ msgstr "Vous avez appuyé le bouton VOLUME au démarrage." #: ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.h #: ports/espressif/boards/m5stack_atom_u/mpconfigboard.h msgid "You pressed the central button at start up." -msgstr "Vous avez appuyé le bouton central au démarrage." +msgstr "Vous avez appuyé sur le bouton central au démarrage." #: ports/nordic/boards/aramcon2_badge/mpconfigboard.h msgid "You pressed the left button at start up." -msgstr "Vous avez appuyé le bouton gauche au démarrage." +msgstr "Vous avez appuyé sur le bouton gauche au démarrage." #: supervisor/shared/safe_mode.c msgid "You pressed the reset button during boot." -msgstr "Vous avez appuyé le bouton reset au démarrage." +msgstr "Vous avez appuyé sur le bouton reset au démarrage." #: supervisor/shared/micropython.c msgid "[truncated due to length]" @@ -2464,9 +2574,13 @@ msgstr "un objet 'bytes-like' est requis" msgid "addresses is empty" msgstr "adresses vides" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "en cours de lecture" + #: py/compile.c msgid "annotation must be an identifier" -msgstr "l'annotation doit être un identificateur" +msgstr "l'annotation doit être un indentifiant" #: extmod/ulab/code/numpy/create.c msgid "arange: cannot compute length" @@ -2488,6 +2602,11 @@ msgstr "le paramêtre argsort doit être un ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort n'est pas implémenté pour les arrays aplatis" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" +"Le paramètre doit être None, un nombre entier ou un tuple de nombres entiers" + #: py/compile.c msgid "argument name reused" msgstr "le nom de l'argument est réutilisé" @@ -2507,11 +2626,11 @@ msgstr "la taille de l'array et de l'index doivent être égaux" #: extmod/ulab/code/numpy/io/io.c msgid "array has too many dimensions" -msgstr "la tableau à trop de dimensions" +msgstr "le tableau à trop de dimensions" #: extmod/ulab/code/ndarray.c msgid "array is too big" -msgstr "array trop grand" +msgstr "Tableau trop grand" #: py/objarray.c shared-bindings/alarm/SleepMemory.c #: shared-bindings/memorymap/AddressRange.c shared-bindings/nvm/ByteArray.c @@ -2520,7 +2639,7 @@ msgstr "matrice/octets requis à la droite" #: py/asmxtensa.c msgid "asm overflow" -msgstr "débordement asm" +msgstr "Débordement asm" #: py/compile.c msgid "async for/with outside async function" @@ -2532,12 +2651,16 @@ msgstr "tentative d'obtenir (arg)min/(arg)max d'une séquence vide" #: extmod/ulab/code/numpy/numerical.c msgid "attempt to get argmin/argmax of an empty sequence" -msgstr "tenter d'obtenir argmin / argmax d'une séquence vide" +msgstr "Tentative d'obtention argmin / argmax d'une séquence vide" #: py/objstr.c msgid "attributes not supported" msgstr "attributs non pris en charge" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "format audio incomptatible" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "axis est hors limites" @@ -2552,11 +2675,11 @@ msgstr "axis trop long" #: shared-bindings/bitmaptools/__init__.c msgid "background value out of range of target" -msgstr "la valeur du fond est hors de l'intervalle de la cible" +msgstr "Valeur d'arrière-plan hors de la plage cible" #: py/builtinevex.c msgid "bad compile mode" -msgstr "mauvais mode de compilation" +msgstr "Mauvais mode de compilation" #: py/objstr.c msgid "bad conversion specifier" @@ -2574,9 +2697,13 @@ msgstr "mauvais code type" msgid "binary op %q not implemented" msgstr "opération binaire '%q' non implémentée" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth doit être 8, 16, 24 ou 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" -msgstr "" +msgstr "taille et profondeur du bitmap doivent correspondre" #: shared-bindings/bitmaptools/__init__.c msgid "bitmap sizes must match" @@ -2586,9 +2713,18 @@ msgstr "les tailles des images doivent correspondre" msgid "bits must be 32 or less" msgstr "les bits doivent être 32 ou moins" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample doit être de 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" -msgstr "'bits_per_sample' doivent être 8 ou 16" +msgstr "bits_per_sample doivent être 8 ou 16" #: py/emitinlinethumb.c msgid "branch not in range" @@ -2620,7 +2756,7 @@ msgstr "tampon trop petit pour le nombre d'octets demandé" #: py/emitbc.c msgid "bytecode overflow" -msgstr "" +msgstr "débordement du bytecode" #: py/objarray.c msgid "bytes length not a multiple of item size" @@ -2668,7 +2804,7 @@ msgstr "ne peut pas assigner à une expression" msgid "can't cancel self" msgstr "ne peut pas s'annuler soi-même" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "impossible de convertir %q en %q" @@ -2723,6 +2859,10 @@ msgstr "ne peut pas supprimer l'expression" msgid "can't do binary op between '%q' and '%q'" msgstr "opération binaire impossible entre '%q' et '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "impossible d'effectuer l'opération unaire de '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "impossible de convertir implicitement '%q' en 'bool'" @@ -2741,7 +2881,7 @@ msgstr "impossible de charger avec l'indice '%q'" #: py/builtinimport.c msgid "can't perform relative import" -msgstr "ne peut importer relativement" +msgstr "ne peut faire un import relatif" #: py/objgenerator.c msgid "can't send non-None value to a just-started generator" @@ -2751,7 +2891,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "can't set 512 block size" -msgstr "impossible de définir une taille de bloc de 512" +msgstr "Impossible de définir la taille de bloc à 512" #: py/objexcept.c py/objnamedtuple.c msgid "can't set attribute" @@ -2791,13 +2931,9 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "un nombre complexe ne peut pas être tronqué/divisé" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" -msgstr "impossible de mettre en attente" +msgstr "Impossible d'attendre" #: extmod/ulab/code/ndarray.c msgid "cannot assign new shape" @@ -2829,7 +2965,7 @@ msgstr "les éléments de la matrice ne peut être supprimés" #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" -msgstr "" +msgstr "Impossible de transformer le tableau" #: py/emitnative.c msgid "casting" @@ -2985,7 +3121,7 @@ msgstr "les dimensions ne correspondent pas" #: py/emitnative.c msgid "div/mod not implemented for uint" -msgstr "div/mod ne sont pas implémentés pour uint" +msgstr "div/Mod non implémenté pour uint" #: extmod/ulab/code/numpy/create.c msgid "divide by zero" @@ -2997,11 +3133,11 @@ msgstr "division par zéro" #: extmod/ulab/code/numpy/vector.c msgid "dtype must be float, or complex" -msgstr "le dtype doit être un flottant, ou un complexe" +msgstr "le dtype doit être de type flottant ou complexe" #: extmod/ulab/code/ndarray_operators.c msgid "dtype of int32 is not supported" -msgstr "dtype de int32 non pris en charge" +msgstr "dtype en int32 non supporté" #: py/objdeque.c msgid "empty" @@ -3025,11 +3161,12 @@ msgstr "séquence vide" #: py/objstr.c msgid "end of format while looking for conversion specifier" -msgstr "fin de format en cherchant une spécification de conversion" +msgstr "" +"fin du format atteinte lors de la recherche du spécificateur de conversion" #: shared-bindings/alarm/time/TimeAlarm.c msgid "epoch_time not supported on this board" -msgstr "epoch_time n'est pas supporté sur ce panneau" +msgstr "epoch_time n'est pas supporté sur cet plateforme" #: ports/nordic/common-hal/busio/UART.c #, c-format @@ -3046,7 +3183,7 @@ msgstr "':' attendu après la spécification de format" #: py/obj.c msgid "expected tuple/list" -msgstr "un tuple ou une liste est attendu" +msgstr "demande un tuple ou une liste" #: py/modthread.c msgid "expecting a dict for keyword args" @@ -3058,11 +3195,11 @@ msgstr "une instruction assembleur est attendue" #: py/compile.c msgid "expecting just a value for set" -msgstr "une simple valeur est attendue pour l'ensemble 'set'" +msgstr "au moins une valeur requise pour un 'set'" #: py/compile.c msgid "expecting key:value for dict" -msgstr "couple clef:valeur attendu pour un dictionnaire 'dict'" +msgstr "couple clef:valeur requis pour un dictionnaire 'dict'" #: shared-bindings/msgpack/__init__.c msgid "ext_hook is not a function" @@ -3084,11 +3221,11 @@ msgstr "le fichier doit être un fichier ouvert en mode 'byte'" #: shared-bindings/traceback/__init__.c msgid "file write is not available" -msgstr "l'écriture de fichier n'est pas disponible" +msgstr "écriture de fichier indisponible" #: shared-bindings/storage/__init__.c msgid "filesystem must provide mount method" -msgstr "le system de fichier doit fournir une méthode 'mount'" +msgstr "le system de fichier requier une méthode 'mount'" #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" @@ -3112,7 +3249,7 @@ msgstr "le premier argument de super() doit être un type" #: extmod/ulab/code/scipy/linalg/linalg.c msgid "first two arguments must be ndarrays" -msgstr "les deux premiers paramètres doivent être des ndarrays" +msgstr "les deux premiers arguments doivent être des ndarrays" #: extmod/ulab/code/ndarray.c msgid "flattening order must be either 'C', or 'F'" @@ -3124,23 +3261,23 @@ msgstr "le paramêtre flip doit être un ndarray" #: py/objint.c msgid "float too big" -msgstr "nombre à virgule flottante trop grand" +msgstr "nombre flottant trop grand" #: py/nativeglue.c msgid "float unsupported" -msgstr "valeures flotantes non supportées" +msgstr "flottant non supporté" #: shared-bindings/_stage/Text.c msgid "font must be 2048 bytes long" -msgstr "la police doit être longue de 2048 octets" +msgstr "la police doit être de 2048 octets" #: extmod/moddeflate.c msgid "format" msgstr "format" #: py/objstr.c -msgid "format requires a dict" -msgstr "le format nécessite un dict" +msgid "format needs a dict" +msgstr "le format requier un dict" #: py/objdeque.c msgid "full" @@ -3165,7 +3302,7 @@ msgstr "la fonction a le même signe aux extrémités de l'intervalle" #: extmod/ulab/code/ndarray.c msgid "function is defined for ndarrays only" -msgstr "fonction définie que pour les ndarrays" +msgstr "la fonction n'est définie que pour les ndarrays" #: extmod/ulab/code/numpy/carray/carray.c msgid "function is implemented for ndarrays only" @@ -3189,14 +3326,15 @@ msgstr "il manque l'argument nommé obligatoire '%q'" msgid "function missing required positional argument #%d" msgstr "il manque l'argument positionnel obligatoire #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "la fonction prend %d argument(s) positionnels mais %d ont été donné(s)" #: py/objgenerator.c msgid "generator already executing" -msgstr "générateur déjà en cours d'exécution" +msgstr "générateur déjà en exécution" #: py/objgenerator.c msgid "generator ignored GeneratorExit" @@ -3204,7 +3342,7 @@ msgstr "le générateur a ignoré GeneratorExit" #: py/objgenerator.c py/runtime.c msgid "generator raised StopIteration" -msgstr "générateur (generator) à surlevé StopIteration" +msgstr "le générateur a levé l'exception StopIteration" #: shared-bindings/_stage/Layer.c msgid "graphic must be 2048 bytes long" @@ -3212,7 +3350,7 @@ msgstr "graphic doit être long de 2048 octets" #: extmod/modhashlib.c msgid "hash is final" -msgstr "hash est final" +msgstr "le hachage est final" #: extmod/modheapq.c msgid "heap must be a list" @@ -3228,7 +3366,7 @@ msgstr "identifiant redéfini comme nonlocal" #: py/compile.c msgid "import * not at module level" -msgstr "import * n'est pas au niveau du module" +msgstr "import * non au niveau du module" #: py/persistentcode.c msgid "incompatible .mpy arch" @@ -3271,11 +3409,7 @@ msgstr "les indices doivent être des entiers" #: extmod/ulab/code/ndarray.c msgid "indices must be integers, slices, or Boolean lists" msgstr "" -"les indices doivent être des entiers, des tranches ou des listes booléennes" - -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "initialisation I2C" +"les indices doivent être des entiers, des tranches, des listes booléennes" #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" @@ -3291,16 +3425,15 @@ msgstr "l'assembleur doit être une fonction" #: extmod/ulab/code/numpy/vector.c msgid "input and output dimensions differ" -msgstr "les dimensions de sortie et d'entrée sont différentes" +msgstr "les dimensions d'entrée et de sortie diffèrent" #: extmod/ulab/code/numpy/vector.c msgid "input and output shapes differ" -msgstr "les formes d'entrée et de sortie sont différentes" +msgstr "Les dimensions d'entrée et de sortie diffèrent" #: extmod/ulab/code/numpy/create.c msgid "input argument must be an integer, a tuple, or a list" -msgstr "" -"le paramètre entrant doit être un nombre entier, un tuple, ou une liste" +msgstr "le paramètre entrant doit être un nombre entier, un tuple, une liste" #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "input array length must be power of 2" @@ -3343,13 +3476,13 @@ msgstr "l'entrée doit être un ndarray 1D" msgid "input must be a dense ndarray" msgstr "l'entrée doit être un ndarray dense" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "l'entrée doit être un ndarray" #: extmod/ulab/code/numpy/carray/carray.c msgid "input must be an ndarray, or a scalar" -msgstr "l'entrée doit être un ndarray, ou un scalaire" +msgstr "l'entrée doit être un ndarray, un scalaire" #: extmod/ulab/code/scipy/signal/signal.c msgid "input must be one-dimensional" @@ -3361,11 +3494,11 @@ msgstr "l'entrée doit être une matrice carrée" #: extmod/ulab/code/numpy/numerical.c msgid "input must be tuple, list, range, or ndarray" -msgstr "l'entrée 'input' doit être tuple, list, range ou ndarray" +msgstr "l'entrée 'input' doit être un tuple, list, range, ndarray" #: extmod/ulab/code/numpy/poly.c msgid "input vectors must be of equal length" -msgstr "les vecteurs d'entrée doivent être de longueur égale" +msgstr "les vecteurs d'entrée doivent être de même longueur" #: extmod/ulab/code/numpy/approx.c msgid "interp is defined for 1D iterables of equal length" @@ -3378,7 +3511,7 @@ msgstr "interval doit être dans la portée %s-%s" #: py/compile.c msgid "invalid arch" -msgstr "" +msgstr "arch invalide" #: shared-bindings/bitmaptools/__init__.c #, c-format @@ -3418,7 +3551,7 @@ msgstr "clé invalide" #: py/compile.c msgid "invalid micropython decorator" -msgstr "décorateur micropython invalide" +msgstr "décorateur Micropython invalide" #: ports/espressif/common-hal/espcamera/Camera.c msgid "invalid setting" @@ -3426,7 +3559,7 @@ msgstr "réglage invalide" #: shared-bindings/random/__init__.c msgid "invalid step" -msgstr "pas invalide" +msgstr "étape invalide" #: py/compile.c py/parse.c msgid "invalid syntax" @@ -3434,7 +3567,7 @@ msgstr "syntaxe invalide" #: py/parsenum.c msgid "invalid syntax for integer" -msgstr "syntaxe invalide pour un entier" +msgstr "Syntaxe entier invalide" #: py/parsenum.c #, c-format @@ -3461,12 +3594,13 @@ msgstr "les itérations n'ont pas convergé" #: py/objstr.c msgid "join expects a list of str/bytes objects consistent with self object" -msgstr "" -"'join' s'attend à une liste d'objets str/bytes cohérents avec l'objet self" +msgstr "'join' attend une liste d'objets str/bytes cohérents avec l'objet self" #: py/argcheck.c msgid "keyword argument(s) not implemented - use normal args instead" msgstr "" +"argument(s) de mot-clé non implémenté(s) - utilisez des arguments normaux à " +"la place" #: py/emitinlinethumb.c py/emitinlinextensa.c msgid "label '%q' not defined" @@ -3476,10 +3610,6 @@ msgstr "label '%q' non supporté" msgid "label redefined" msgstr "étiquette redéfinie" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "le niveau doit être compris entre 0 et 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "les parties gauches et droites doivent être compatibles" @@ -3490,7 +3620,7 @@ msgstr "la variable locale '%q' a le type '%q' mais la source est '%q'" #: py/emitnative.c msgid "local '%q' used before type known" -msgstr "variable locale '%q' utilisée avant d'en connaitre le type" +msgstr "variable locale '%q' utilisée avant que le type soit connu" #: py/vm.c msgid "local variable referenced before assignment" @@ -3516,7 +3646,7 @@ msgstr "f-string mal formé" #: shared-bindings/_stage/Layer.c msgid "map buffer too small" -msgstr "tampon trop petit" +msgstr "tampon de la matrice trop petit" #: py/modmath.c shared-bindings/math/__init__.c msgid "math domain error" @@ -3533,7 +3663,7 @@ msgstr "la matrice n'est pas définie positive" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length doit être 0-%d lorsque fixed_length est %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "le nombre maximal de dimensions est " @@ -3564,7 +3694,7 @@ msgstr "l'allocation de mémoire a échoué, le tas est vérrouillé" #: py/objarray.c msgid "memoryview offset too large" -msgstr "" +msgstr "décalage memoryview trop large" #: py/objarray.c msgid "memoryview: length is not a multiple of itemsize" @@ -3611,7 +3741,7 @@ msgid "must use keyword argument for key function" msgstr "doit utiliser un argument nommé pour une fonction key" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "nom '%q' non défini" #: py/runtime.c @@ -3620,7 +3750,7 @@ msgstr "nom non défini" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "nom trop long" #: py/persistentcode.c msgid "native code in .mpy unsupported" @@ -3665,7 +3795,7 @@ msgstr "pas de carte SD" #: py/vm.c msgid "no active exception to reraise" -msgstr "aucune exception active à relever" +msgstr "aucune exception active à lever à nouveau" #: py/compile.c msgid "no binding for nonlocal found" @@ -3673,11 +3803,11 @@ msgstr "pas de lien trouvé pour nonlocal" #: shared-module/msgpack/__init__.c msgid "no default packer" -msgstr "aucun emballeur par défault" +msgstr "pas de 'packer' par défaut" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" -msgstr "aucun seed par défaut" +msgstr "pas de 'seed' par défaut" #: py/builtinimport.c msgid "no module named '%q'" @@ -3685,11 +3815,11 @@ msgstr "pas de module '%q'" #: shared-module/sdcardio/SDCard.c msgid "no response from SD card" -msgstr "pas de réponse de la carte SD" +msgstr "la carte SD ne réponds pas" #: ports/espressif/common-hal/espcamera/Camera.c py/objobject.c py/runtime.c msgid "no such attribute" -msgstr "pas de tel attribut" +msgstr "aucun attribut" #: ports/espressif/common-hal/_bleio/Connection.c #: ports/nordic/common-hal/_bleio/Connection.c @@ -3703,15 +3833,15 @@ msgstr "" #: py/objstr.c msgid "non-hex digit found" -msgstr "chiffre non-héxadécimale trouvé" +msgstr "chiffre non-héxa trouvé" #: ports/nordic/common-hal/_bleio/Adapter.c msgid "non-zero timeout must be > 0.01" -msgstr "le délai non-zéro doit être > 0.01" +msgstr "le dépassement de délai non-zéro doit être > 0.01" #: shared-bindings/_bleio/Adapter.c msgid "non-zero timeout must be >= interval" -msgstr "le délai non-zéro doit être >= interval" +msgstr "le dépassement de délai non-zéro doit être >= interval" #: shared-bindings/_bleio/UUID.c msgid "not a 128-bit UUID" @@ -3736,24 +3866,24 @@ msgstr "n'est pas implémenté pour les dtype complexes" #: extmod/ulab/code/numpy/bitwise.c msgid "not supported for input types" -msgstr "non pris en charge pour types d'entrée" +msgstr "non supporté pour les types d'entrée" #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" -msgstr "le nombre de points doit être d'au moins 2" +msgstr "au moins 2 points" #: py/builtinhelp.c msgid "object " -msgstr "objet " +msgstr "objet . " #: py/obj.c #, c-format msgid "object '%s' isn't a tuple or list" -msgstr "l'objet '%s' n'est pas un tuple ou une liste" +msgstr "l'objet '%s' n'est pas un tuple, une liste" #: py/obj.c msgid "object doesn't support item assignment" -msgstr "les objets ne supportent pas l'assignation des éléments" +msgstr "l'objet ne supporte pas l'assignation d'élément" #: py/obj.c msgid "object doesn't support item deletion" @@ -3761,7 +3891,7 @@ msgstr "l'objet ne supporte pas la suppression d'éléments" #: py/obj.c msgid "object has no len" -msgstr "l'objet n'a pas de 'len'" +msgstr "l'objet n'a pas de longeur 'len'" #: py/obj.c msgid "object isn't subscriptable" @@ -3786,11 +3916,11 @@ msgstr "objet non itérable" #: py/obj.c #, c-format msgid "object of type '%s' has no len()" -msgstr "l'objet de type '%s' n'a pas de len()" +msgstr "l'objet de type '%s' n'a pas de longeur len()" #: py/obj.c msgid "object with buffer protocol required" -msgstr "un objet avec un protocole de tampon est nécessaire" +msgstr "un objet avec un protocole de buffer est requis" #: py/objstr.c msgid "odd-length string" @@ -3802,16 +3932,15 @@ msgstr "inactif" #: extmod/ulab/code/utils/utils.c msgid "offset is too large" -msgstr "offset est trop large" +msgstr "l'offset est trop large" #: shared-bindings/dualbank/__init__.c msgid "offset must be >= 0" -msgstr "offset doit être >= 0" +msgstr "l'offset doit être >= 0" #: extmod/ulab/code/numpy/create.c msgid "offset must be non-negative and no greater than buffer length" -msgstr "" -"offset ne doit pas être négatif, et pas plus grand que la taille du tampon" +msgstr "l'offset peu être négatif, et plus grand que la taille du tampon" #: ports/nordic/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c @@ -3828,7 +3957,7 @@ msgstr "seuls les ndarrays peuvent être concaténés" #: ports/stm/common-hal/audiobusio/PDMIn.c msgid "only oversample=64 is supported" -msgstr "seul oversample=64 supporté" +msgstr "seul oversample=64 est supporté" #: ports/nordic/common-hal/audiobusio/PDMIn.c #: ports/stm/common-hal/audiobusio/PDMIn.c @@ -3843,7 +3972,7 @@ msgstr "seules les tranches avec 'step=1' (cad None) sont supportées" #: py/vm.c msgid "opcode" -msgstr "opcode" +msgstr "" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c @@ -3886,32 +4015,44 @@ msgstr "" #: extmod/ulab/code/utils/utils.c msgid "out array is too small" -msgstr "matrice de sortie est trop petite" +msgstr "la matrice de sortie est trop petite" + +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "la sortie est de type incorrect" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" -msgstr "mot clé out non pris en charge pour dtype complexe" +msgstr "mot clé 'out' non pris en charge pour 'dtype' complexe" #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for function" -msgstr "mot clé out non pris en charge pour function" +msgstr "mot clé 'out 'non pris en charge pour 'function'" #: extmod/ulab/code/utils/utils.c msgid "out must be a float dense array" -msgstr "la matrice sortante doit être de type float" +msgstr "la matrice sortante doit être de type floattant" #: extmod/ulab/code/numpy/vector.c msgid "out must be an ndarray" -msgstr "out doit être un ndarray" +msgstr "'out' doit être un ndarray" #: extmod/ulab/code/numpy/vector.c msgid "out must be of float dtype" -msgstr "out doit être de dtype float" +msgstr "'out' doit être de dtype float" #: shared-bindings/bitmaptools/__init__.c msgid "out of range of target" msgstr "hors de l'intervalle de la cible" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "tableau de sortie est de type incorrect" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "tableau de sortie doit être contiguë" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "dépassement de capacité en convertissant un entier long en mot machine" @@ -3935,7 +4076,7 @@ msgstr "les paramètres doivent être des registres dans la séquence r0 à r3" #: extmod/vfs_posix_file.c msgid "poll on file not available on win32" -msgstr "le polling sur un fichier n'est pas disponible sous win32" +msgstr "Le 'polling' sur un fichier est indisponible sous Win32" #: ports/espressif/common-hal/pulseio/PulseIn.c msgid "pop from an empty PulseIn" @@ -3956,11 +4097,11 @@ msgstr "port doit être >= 0" #: py/compile.c msgid "positional arg after **" -msgstr "" +msgstr "paramètre de positionaprès **" #: py/compile.c msgid "positional arg after keyword arg" -msgstr "" +msgstr "argument de position après un argument mot clé" #: py/objint_mpz.c msgid "pow() 3rd argument cannot be 0" @@ -3972,7 +4113,7 @@ msgstr "pow() avec 3 arguments nécessite des entiers" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "pull masks conflict with direction masks" -msgstr "masque pull est en conflit avec les masques de direction" +msgstr "le masque pull est en conflit avec les masques de direction" #: py/parse.c msgid "raw f-strings are not supported" @@ -4006,7 +4147,7 @@ msgstr "return attendait '%q' mais a reçu '%q'" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format msgid "rgb_pins[%d] duplicates another pin assignment" -msgstr "rgb_pins[%d] duplique une autre affectation de broches" +msgstr "rgb_pins[%d] duplique une autre assignation de pin" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -4021,6 +4162,10 @@ msgstr "paramêtre roll doit être un ndarray" msgid "rsplit(None,n)" msgstr "rsplit(None, n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed doit être vrai" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4028,7 +4173,7 @@ msgstr "taux d'échantillonage hors intervalle" #: py/modmicropython.c msgid "schedule queue full" -msgstr "file de schédule pleine" +msgstr "file d'attente 'schedule ' de planification pleine" #: py/builtinimport.c msgid "script compilation not supported" @@ -4038,25 +4183,33 @@ msgstr "compilation de script non supportée" msgid "set unsupported" msgstr "set non-supporté" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "la forme doit être None, un entier ou un tuple d'entier" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "la forme doit être un entier ou un tuple d'entiers" #: shared-module/msgpack/__init__.c msgid "short read" -msgstr "donnée trop petite" +msgstr "lecture incomplète" #: py/objstr.c msgid "sign not allowed in string format specifier" -msgstr "signe non autorisé dans les spéc. de formats de chaînes de caractères" +msgstr "signe non autorisé dans le spécificateur de format de chaîne" #: py/objstr.c msgid "sign not allowed with integer format specifier 'c'" -msgstr "signe non autorisé avec la spéc. de format d'entier 'c'" +msgstr "signe non autorisé avec le spécificateur de format d'entier 'c'" #: extmod/ulab/code/ulab_tools.c msgid "size is defined for ndarrays only" -msgstr "la taille n'est définie que pour les ndarrays" +msgstr "la taille est définie uniquement pour les ndarrays" + +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "taille doit correspondre à out.shape lorsqu'employés ensemble" #: py/nativeglue.c msgid "slice unsupported" @@ -4064,7 +4217,7 @@ msgstr "slice non-supporté" #: py/objint.c py/sequence.c msgid "small int overflow" -msgstr "dépassement de capacité d'un entier court" +msgstr "dépassement d'un petit entier" #: main.c msgid "soft reboot\n" @@ -4076,7 +4229,7 @@ msgstr "le paramètre de «sort» doit être un ndarray" #: extmod/ulab/code/scipy/signal/signal.c msgid "sos array must be of shape (n_section, 6)" -msgstr "la matrice sos doit être de forme (n_section, 6)" +msgstr "la matrice 'sos' doit être de forme (n_section, 6)" #: extmod/ulab/code/scipy/signal/signal.c msgid "sos[:, 3] should be all ones" @@ -4104,7 +4257,7 @@ msgstr "source_bitmap doit avoir une value_count de 8" #: extmod/modre.c msgid "splitting with sub-captures" -msgstr "" +msgstr "scission avec sous-captures" #: py/objstr.c msgid "start/end indices" @@ -4124,25 +4277,13 @@ msgstr "arguments de type chaine de caractères sans encodage" #: py/objstrunicode.c msgid "string index out of range" -msgstr "index de chaîne hors gamme" +msgstr "indice de chaîne hors limites" #: py/objstrunicode.c #, c-format msgid "string indices must be integers, not %s" msgstr "les indices de chaîne de caractères doivent être des entiers, pas %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct ne peut être indexé" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct : index hors intervalle" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct : aucun champs" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "sous-chaîne non trouvée" @@ -4155,10 +4296,6 @@ msgstr "super() ne peut pas trouver self" msgid "syntax error in JSON" msgstr "erreur de syntaxe JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "erreur de syntaxe dans le descripteur d'uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "débordement de l'intervale des ticks" @@ -4173,20 +4310,20 @@ msgstr "le délai (timeout) doit être < 655.35 secondes" #: ports/raspberrypi/common-hal/floppyio/__init__.c msgid "timeout waiting for flux" -msgstr "" +msgstr "délai d'expiration en attente du flux" #: ports/raspberrypi/common-hal/floppyio/__init__.c #: shared-module/floppyio/__init__.c msgid "timeout waiting for index pulse" -msgstr "" +msgstr "délai d'expiration en attente de l'index de pulsation" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" -msgstr "délai d'expiration dépassé en attendant une carte v1" +msgstr "délai d'attente dépassé pour la carte v1" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v2 card" -msgstr "délai d'expiration dépassé en attendant une carte v2" +msgstr "délai d'attente dépassé pour la carte v2" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "timer re-init" @@ -4198,11 +4335,11 @@ msgstr "timestamp hors intervalle pour le 'time_t' de la plateforme" #: extmod/ulab/code/ndarray.c msgid "tobytes can be invoked for dense arrays only" -msgstr "tobytes ne peut être appelée que pour des matrices dense" +msgstr "'tobytes' ne peut être appelée que pour des matrices dense" #: py/compile.c msgid "too many args" -msgstr "args trop nombreux" +msgstr "argsuments trop nombreux" #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/create.c msgid "too many dimensions" @@ -4214,7 +4351,7 @@ msgstr "trop d'indices" #: py/asmthumb.c msgid "too many locals for native method" -msgstr "trop de locals pour une méthode native" +msgstr "trop de 'locals' pour une méthode native" #: py/runtime.c #, c-format @@ -4248,11 +4385,11 @@ msgid "tx and rx cannot both be None" msgstr "tx et rx ne peuvent être 'None' tous les deux" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "le type '%q' n'est pas un type de base accepté" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "le type n'est pas un type de base accepté" #: py/runtime.c @@ -4267,10 +4404,6 @@ msgstr "le type prend 1 ou 3 arguments" msgid "ulonglong too large" msgstr "ulonglong trop grand" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "opération unaire '%q' non implémentée" - #: py/parse.c msgid "unexpected indent" msgstr "indentation inattendue" @@ -4282,7 +4415,7 @@ msgstr "paramètre nommé inattendu" #: py/argcheck.c py/bc.c py/objnamedtuple.c #: shared-bindings/traceback/__init__.c msgid "unexpected keyword argument '%q'" -msgstr "paramètre nommé '%q' inattendu" +msgstr "mot clé nommé '%q' inattendu" #: py/lexer.c msgid "unicode name escapes" @@ -4290,7 +4423,7 @@ msgstr "échappements de nom unicode" #: py/parse.c msgid "unindent doesn't match any outer indent level" -msgstr "unindent ne correspond pas au niveau d'indentation parent" +msgstr "'unindent' ne correspond pas au niveau d'indentation parent" #: py/objstr.c #, c-format @@ -4318,7 +4451,9 @@ msgstr "'%c' sans correspondance dans le format" msgid "unreadable attribute" msgstr "attribut illisible" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "type %q non pris on charge" @@ -4334,7 +4469,7 @@ msgstr "instruction Xtensa '%s' non supportée avec %d paramètres" #: shared-module/bitmapfilter/__init__.c msgid "unsupported bitmap depth" -msgstr "" +msgstr "profondeur de bitmap non supportée" #: shared-module/gifio/GifWriter.c msgid "unsupported colorspace for GifWriter" @@ -4387,27 +4522,24 @@ msgid "" "weights must be a sequence with an odd square number of elements (usually 9 " "or 25)" msgstr "" +"le poids requier une séquence de nombre carré impair d'éléments " +"(habituellement 9 ou 25)" #: shared-bindings/bitmapfilter/__init__.c msgid "weights must be an object of type %q, %q, %q, or %q, not %q " -msgstr "" +msgstr "le poids requier un objet de type %q, %q, %q ou %q, pas %q. " #: shared-bindings/is31fl3741/FrameBuffer.c msgid "width must be greater than zero" -msgstr "width doit être plus que zero" - -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "wifi n'est pas activé" +msgstr "width doit être plus grand que zero" #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" -msgstr "wifi.Monitor non disponible" +msgstr "wifi.Monitor indisponible" #: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" -msgstr "la fenêtre (window) doit être <= intervalle (interval)" +msgstr "la fenêtre (window) doit être <= à l'intervalle (interval)" #: extmod/ulab/code/numpy/numerical.c msgid "wrong axis index" @@ -4415,7 +4547,7 @@ msgstr "index d'axe incorrecte" #: extmod/ulab/code/numpy/create.c msgid "wrong axis specified" -msgstr "axe incorrecte spécifiée" +msgstr "axe spécifiée incorrect" #: extmod/ulab/code/numpy/io/io.c msgid "wrong dtype" @@ -4463,6 +4595,83 @@ msgstr "zi doit être de type float" msgid "zi must be of shape (n_section, 2)" msgstr "zi doit être de forme (n_section, 2)" +#~ msgid "Unsupported format" +#~ msgstr "Format non pris en charge" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Le WiFi n'est pas activé" + +#~ msgid "wifi is not enabled" +#~ msgstr "le WiFi est inactif" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "" +#~ "Ne peut démonter '/' la racine du système de fichier quand elle est déja " +#~ "vue par le port USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q doit être un objet %q, %q ou %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Un bloc de données doit suivre un bloc fmt" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Seul les BMP monochromes, 4 bpp ou 8 bpp, ou 16 bpp et plus sont " +#~ "supportés: %d bpp fournis" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "le niveau doit être compris entre 0 et 1" + +#~ msgid "init I2C" +#~ msgstr "initialisation I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "" +#~ "Le 'bits_per_sample' de l'échantillon ne correspond pas à celui du mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Le canal de l'échantillon ne correspond pas à celui du mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "" +#~ "L'échantillonage de l'échantillon ne correspond pas à celui du mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Le signe de l'échantillon ne correspond pas à celui du mixer" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "La longueur de la mémoire tampon doit être un multiple de 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "La mémoire tampon doit être un multiple de 512" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Le nombre de data_pins doit être 8 ou 16, et non %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "Erreur d'initialisation SDIO %d" + +#~ msgid "struct: can't index" +#~ msgstr "struct ne peut être indexé" + +#~ msgid "struct: index out of range" +#~ msgstr "struct : index hors intervalle" + +#~ msgid "struct: no fields" +#~ msgstr "struct : aucun champs" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "erreur de syntaxe dans le descripteur d'uctypes" + +#~ msgid "unary op %q not implemented" +#~ msgstr "opération unaire '%q' non implémentée" + #~ msgid "Name too long" #~ msgstr "Nom trop long" @@ -4749,13 +4958,13 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "l'objet '%s' ne supporte pas la suppression d'éléments" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "l'objet '%s' n'est pas un itérateur" #~ msgid "'%s' object is not callable" #~ msgstr "l'objet '%s' n'est pas appelable" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "l'objet '%s' n'est pas itérable" #~ msgid "'%s' object is not subscriptable" @@ -4773,7 +4982,7 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' dehors d'une boucle" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "L'objet \"coroutine\" n'est pas un itérateur" #~ msgid "(x,y) integers required" @@ -6262,7 +6471,7 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "frequency is read-only for this board" #~ msgstr "la fréquence est en lecture seule pour cette carte" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "la fonction ne prend pas d'arguments nommés" #~ msgid "function is implemented for scalars and ndarrays only" @@ -6391,7 +6600,7 @@ msgstr "zi doit être de forme (n_section, 2)" #~ msgid "name must be a string" #~ msgstr "les noms doivent être des chaînes de caractère" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "nom réutilisé comme paramètre" #~ msgid "no available NIC" diff --git a/locale/hi.po b/locale/hi.po index 2fc5a00168b63..f9d7b898198f6 100644 --- a/locale/hi.po +++ b/locale/hi.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2025-06-29 13:02+0000\n" +"Last-Translator: MAE \n" "Language-Team: none\n" "Language: hi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -71,7 +71,7 @@ msgstr "" #: py/objstr.c #, c-format -msgid "%%c requires int or char" +msgid "%%c needs int or char" msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -80,11 +80,16 @@ msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "" @@ -101,14 +106,21 @@ msgid "%q contains duplicate pins" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -116,7 +128,8 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "" @@ -128,7 +141,9 @@ msgstr "" msgid "%q indices must be integers, not %s" msgstr "" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "" @@ -156,16 +171,12 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "" - #: py/argcheck.c msgid "%q must be %d" msgstr "" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -216,6 +227,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -225,6 +237,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -233,23 +246,29 @@ msgstr "" msgid "%q must be power of 2" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "" @@ -270,7 +289,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -299,20 +319,20 @@ msgstr "" msgid "'%q' argument required" msgstr "" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" +msgid "'%q' object isn't callable" msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -416,6 +436,10 @@ msgstr "" msgid "'label' requires 1 argument" msgstr "" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "" @@ -440,6 +464,7 @@ msgstr "" msgid ", in %q\n" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -458,7 +483,7 @@ msgstr "" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "" @@ -493,7 +518,8 @@ msgstr "" msgid "All SPI peripherals are in use" msgstr "" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "" @@ -535,7 +561,6 @@ msgstr "" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "" @@ -548,6 +573,10 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -557,10 +586,11 @@ msgstr "" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "" @@ -583,6 +613,10 @@ msgstr "" msgid "Array values should be single bytes." msgstr "" +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -592,6 +626,12 @@ msgstr "" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -614,6 +654,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -631,20 +672,17 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "" @@ -659,12 +697,12 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" msgstr "" #: shared-bindings/_bleio/PacketBuffer.c @@ -687,10 +725,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "" - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "" @@ -723,6 +757,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -738,6 +776,10 @@ msgstr "" msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -768,10 +810,11 @@ msgid "Cannot record to a file" msgstr "" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "" @@ -784,6 +827,10 @@ msgstr "" msgid "Cannot subclass slice" msgstr "" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -818,6 +865,14 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "" @@ -830,6 +885,11 @@ msgstr "" msgid "Couldn't allocate decoder" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "" @@ -847,10 +907,6 @@ msgstr "" msgid "Data 0 pin must be byte aligned" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -889,6 +945,7 @@ msgstr "" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "" @@ -897,6 +954,7 @@ msgid "Done" msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "" @@ -908,8 +966,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -956,7 +1023,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -974,22 +1041,60 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "" @@ -998,12 +1103,13 @@ msgstr "" msgid "File exists" msgstr "" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1028,7 +1134,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "" @@ -1050,6 +1156,7 @@ msgstr "" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1136,6 +1243,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1147,7 +1255,8 @@ msgstr "" msgid "Internal define error" msgstr "" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "" @@ -1181,18 +1290,29 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1222,6 +1342,14 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "" @@ -1230,17 +1358,12 @@ msgstr "" msgid "Invalid bits per value" msgstr "" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "" @@ -1253,6 +1376,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1264,11 +1388,13 @@ msgstr "" msgid "Invalid socket for TLS" msgstr "" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "" @@ -1276,10 +1402,6 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "" @@ -1305,13 +1427,23 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1400,7 +1532,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "" @@ -1418,6 +1550,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1493,6 +1626,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -1528,17 +1665,14 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1591,13 +1725,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1635,6 +1762,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1648,6 +1776,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1667,6 +1796,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1764,7 +1897,12 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "" @@ -1784,10 +1922,31 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1862,9 +2021,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1875,6 +2035,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -1914,6 +2078,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1922,6 +2087,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -1958,20 +2127,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -1992,7 +2149,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2000,6 +2159,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2010,11 +2173,16 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2053,6 +2221,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2061,13 +2233,21 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2085,10 +2265,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2105,6 +2281,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2113,6 +2290,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "" @@ -2130,6 +2308,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2214,6 +2396,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "" @@ -2222,15 +2408,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2239,15 +2422,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2281,10 +2469,12 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2307,6 +2497,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2320,6 +2511,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2376,10 +2568,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2404,6 +2604,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2434,10 +2638,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2454,6 +2654,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2490,6 +2694,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2502,6 +2710,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "" @@ -2559,6 +2776,10 @@ msgstr "" msgid "can only have one parent" msgstr "" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2583,7 +2804,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2626,6 +2847,14 @@ msgstr "" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2638,6 +2867,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2700,10 +2933,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2724,18 +2953,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -2890,7 +3115,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -2989,10 +3214,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3033,16 +3254,20 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3092,7 +3317,8 @@ msgstr "" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3109,10 +3335,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3175,18 +3397,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3244,7 +3458,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3277,6 +3491,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3373,10 +3591,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3430,7 +3644,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3475,6 +3689,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3508,7 +3726,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3523,10 +3741,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3548,7 +3762,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3572,7 +3786,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3598,7 +3812,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3617,14 +3831,6 @@ msgstr "" msgid "not a constant" msgstr "" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "" @@ -3633,6 +3839,10 @@ msgstr "" msgid "not supported for input types" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3646,6 +3856,10 @@ msgstr "" msgid "object '%s' isn't a tuple or list" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3687,10 +3901,6 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "" @@ -3739,6 +3949,30 @@ msgstr "" msgid "opcode" msgstr "" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3781,6 +4015,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3805,6 +4043,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3814,8 +4060,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3867,14 +4113,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3884,6 +4130,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3914,6 +4164,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3931,6 +4185,10 @@ msgstr "" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3951,6 +4209,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -3999,10 +4261,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4024,18 +4282,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4048,10 +4294,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4141,11 +4383,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4156,14 +4398,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4211,7 +4445,9 @@ msgstr "" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "" @@ -4289,11 +4525,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" diff --git a/locale/it_IT.po b/locale/it_IT.po index b557728d540a1..87e7f0e343dda 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -7,15 +7,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-12-06 22:06+0000\n" -"Last-Translator: deepserket \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: \n" "Language: it_IT\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.3-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -86,7 +86,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "" @@ -106,7 +106,11 @@ msgstr "" msgid "%q failure: %d" msgstr "%q fallito: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" @@ -158,7 +162,7 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "" @@ -218,6 +222,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -227,6 +232,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -272,7 +278,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -306,7 +313,7 @@ msgid "'%q' object does not support '%q'" msgstr "L'oggetto '%q' non supporta '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "L'oggetto '%q' non è un iteratore" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -314,7 +321,7 @@ msgid "'%q' object is not callable" msgstr "L'oggetto '%q' non è richiamabile" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "L'oggetto '%q' non è iterabile" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -418,6 +425,10 @@ msgstr "'data' richiede argomenti interi" msgid "'label' requires 1 argument" msgstr "'label' richiede 1 argomento" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' al di fuori della funzione" @@ -538,7 +549,6 @@ msgstr "Tutti i timer per questo pin sono in uso" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Tutti i timer utilizzati" @@ -551,6 +561,10 @@ msgstr "" msgid "Already have all-matches listener" msgstr "Già in possesso di tutti i listener abbinati" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -560,6 +574,7 @@ msgstr "Già in funzione" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Già in ricerca di collegamenti WiFi" @@ -586,6 +601,10 @@ msgstr "Array deve avere mezzoparole (typo 'H')" msgid "Array values should be single bytes." msgstr "I valori dell'Array dovrebbero essere bytes singoli." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -595,6 +614,11 @@ msgstr "Provo ad allocare %d blocchi" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -664,13 +688,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Lunghezza Buffer %d troppo grande. Deve essere meno di %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "La lunghezza del buffer deve essere un multiplo di 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Il buffer deve essere un multiplo di 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -728,6 +752,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -774,12 +802,12 @@ msgid "Cannot record to a file" msgstr "Impossibile registrare in un file" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." -msgstr "non si può impostare un valore quando direzione è input" +msgstr "non si può impostare un valore quando direzione è input." #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -790,6 +818,10 @@ msgstr "" msgid "Cannot subclass slice" msgstr "Impossibile subclasare slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -824,6 +856,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "" @@ -836,6 +872,11 @@ msgstr "" msgid "Couldn't allocate decoder" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "" @@ -854,10 +895,6 @@ msgstr "DAC già in uso" msgid "Data 0 pin must be byte aligned" msgstr "graphic deve essere lunga 2048 byte" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -869,9 +906,8 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c -#, fuzzy msgid "Data too large for advertisement packet" -msgstr "Impossibile inserire dati nel pacchetto di advertisement." +msgstr "Impossibile inserire dati nel pacchetto di advertisement" #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Deep sleep pins must use a rising edge with pulldown" @@ -953,7 +989,7 @@ msgstr "" #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to acquire mutex, err 0x%04x" -msgstr "Impossibile acquisire il mutex, err 0x%04x" +msgstr "Impossibile acquisire il mutex, err 0x%04x" #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Failed to add service TXT record" @@ -989,14 +1025,46 @@ msgstr "" msgid "Failed to connect: timeout" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" -msgstr "Impossibile rilasciare il mutex, err 0x%04x" +msgstr "Impossibile rilasciare il mutex, err 0x%04x" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." @@ -1006,12 +1074,14 @@ msgstr "" msgid "File exists" msgstr "File esistente" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1036,7 +1106,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "" @@ -1144,6 +1214,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1189,15 +1260,19 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "" @@ -1230,6 +1305,10 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Argomento non valido" @@ -1261,6 +1340,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1273,6 +1353,7 @@ msgid "Invalid socket for TLS" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" @@ -1313,9 +1394,15 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -1361,7 +1448,8 @@ msgstr "" msgid "Mount point directory missing" msgstr "" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "" @@ -1501,6 +1589,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "Non che spazio sul dispositivo" @@ -1546,8 +1638,9 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1603,13 +1696,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1660,6 +1746,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1679,6 +1766,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1737,9 +1828,8 @@ msgid "Pipe error" msgstr "" #: py/builtinhelp.c -#, fuzzy msgid "Plus any modules on the filesystem\n" -msgstr "Imposssibile rimontare il filesystem" +msgstr "Imposssibile rimontare il filesystem\n" #: shared-module/vectorio/Polygon.c msgid "Polygon needs at least 3 points" @@ -1777,6 +1867,10 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "" @@ -1797,10 +1891,30 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1875,9 +1989,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1927,11 +2042,13 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Slice non supportate" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" @@ -1971,20 +2088,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -2005,7 +2110,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2013,6 +2120,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2080,7 +2191,7 @@ msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2143,6 +2254,10 @@ msgstr "Inizilizzazione del parser non possibile" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2237,15 +2352,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "tipo di bitmap non supportato" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Formato non supportato" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2255,14 +2367,12 @@ msgid "Update failed" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2296,10 +2406,12 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2322,6 +2434,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2335,6 +2448,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2395,6 +2509,10 @@ msgstr "un oggetto byte-like è richiesto" msgid "addresses is empty" msgstr "gli indirizzi sono vuoti" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2419,6 +2537,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2469,6 +2591,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2505,6 +2631,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "operazione binaria %q non implementata" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2517,6 +2647,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c #, fuzzy msgid "bits_per_sample must be 8 or 16" @@ -2602,7 +2741,7 @@ msgstr "impossibile assegnare all'espressione" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2657,6 +2796,10 @@ msgstr "impossibile cancellare l'espessione" msgid "can't do binary op between '%q' and '%q'" msgstr "impossibile eseguire operazione binaria tra '%q' e '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "non è possibile convertire implicitamente '%q' in 'bool'" @@ -2719,10 +2862,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -3066,7 +3205,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "la formattazione richiede un dict" #: py/objdeque.c @@ -3116,7 +3255,8 @@ msgstr "argomento nominato '%q' mancante alla funzione" msgid "function missing required positional argument #%d" msgstr "mancante il #%d argomento posizonale obbligatorio della funzione" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3200,10 +3340,6 @@ msgstr "gli indici devono essere interi" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" @@ -3269,7 +3405,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3401,10 +3537,6 @@ msgstr "etichetta '%q' non definita" msgid "label redefined" msgstr "etichetta ridefinita" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs e rhs devono essere compatibili" @@ -3458,7 +3590,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3536,7 +3668,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "nome '%q'non definito" #: py/runtime.c @@ -3600,7 +3732,7 @@ msgstr "nessun binding per nonlocal trovato" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3812,6 +3944,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3836,6 +3972,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overflow convertendo long int in parola" @@ -3946,6 +4090,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3963,6 +4111,10 @@ msgstr "compilazione dello scrip non suportata" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3983,13 +4135,17 @@ msgstr "segno non permesso nello spcificatore di formato 'c' della stringa" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" #: py/objint.c py/sequence.c msgid "small int overflow" -msgstr "small int overflow" +msgstr "piccolo int overflow" #: main.c msgid "soft reboot\n" @@ -4056,18 +4212,6 @@ msgstr "indice della stringa fuori intervallo" msgid "string indices must be integers, not %s" msgstr "indici della stringa devono essere interi, non %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: indice fuori intervallo" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: nessun campo" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "sottostringa non trovata" @@ -4080,10 +4224,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "errore di sintassi nel JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "errore di sintassi nel descrittore uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4173,11 +4313,11 @@ msgid "tx and rx cannot both be None" msgstr "tx e rx non possono essere entrambi None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "il tipo '%q' non è un tipo di base accettabile" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "il tipo non è un tipo di base accettabile" #: py/runtime.c @@ -4192,10 +4332,6 @@ msgstr "tipo prende 1 o 3 argomenti" msgid "ulonglong too large" msgstr "ulonglong troppo grande" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "operazione unaria %q non implementata" - #: py/parse.c msgid "unexpected indent" msgstr "indentazione inaspettata" @@ -4243,7 +4379,9 @@ msgstr "" msgid "unreadable attribute" msgstr "attributo non leggibile" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "tipo di %q non supportato" @@ -4321,11 +4459,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4388,6 +4521,27 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Unsupported format" +#~ msgstr "Formato non supportato" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "La lunghezza del buffer deve essere un multiplo di 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Il buffer deve essere un multiplo di 512 bytes" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: indice fuori intervallo" + +#~ msgid "struct: no fields" +#~ msgstr "struct: nessun campo" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "errore di sintassi nel descrittore uctypes" + +#~ msgid "unary op %q not implemented" +#~ msgstr "operazione unaria %q non implementata" + #~ msgid "All PCNT units in use" #~ msgstr "Tutte le unità PCNT sono in uso" @@ -4523,13 +4677,13 @@ msgstr "" #~ msgid "'%s' object does not support item deletion" #~ msgstr "oggeto '%s' non supporta eliminamento di item" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "l'oggetto '%s' non è un iteratore" #~ msgid "'%s' object is not callable" #~ msgstr "oggeto '%s' non è chiamabile" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "l'oggetto '%s' non è iterabile" #~ msgid "'%s' object is not subscriptable" @@ -4545,7 +4699,7 @@ msgstr "" #~ msgid "'continue' outside loop" #~ msgstr "'continue' fuori del ciclo" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "L'oggetto 'coroutine' non è un iteratore" #~ msgid "64 bit types" @@ -5208,7 +5362,7 @@ msgstr "" #~ msgid "frequency can only be either 80Mhz or 160MHz" #~ msgstr "la frequenza può essere o 80Mhz o 160Mhz" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "la funzione non prende argomenti nominati" #~ msgid "impossible baudrate" @@ -5275,7 +5429,7 @@ msgstr "" #~ msgid "name must be a string" #~ msgstr "argomenti nominati devono essere stringhe" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "nome riutilizzato come argomento" #, fuzzy diff --git a/locale/ja.po b/locale/ja.po index e4426c64c8bbd..6e625e94a873d 100644 --- a/locale/ja.po +++ b/locale/ja.po @@ -8,15 +8,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2024-01-22 14:03+0000\n" -"Last-Translator: Nemoto \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: none\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.4-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -95,7 +95,7 @@ msgstr "%dアドレスピン、%dRGBピン、%dタイルは%dの高さを指示 msgid "%q and %q contain duplicate pins" msgstr "%q と %q に重複するピンがあります" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%qと%qが必ず異なるのは必要" @@ -115,7 +115,11 @@ msgstr "%q に重複するピンがあります" msgid "%q failure: %d" msgstr "%q 失敗: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q 内の %q は %q 型である必要があり、 %q 型は使用できません" @@ -167,7 +171,7 @@ msgstr "%q の長さは <= %d である必要があります" msgid "%q length must be >= %d" msgstr "%q の長さは >= %d である必要があります" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q は %q から %q へ移動しました" @@ -223,11 +227,12 @@ msgstr "%q は 'h' 型の array である必要があります" #: shared-bindings/audiobusio/PDMIn.c msgid "%q must be multiple of 8." -msgstr "%q は 8 の倍数である必要があります" +msgstr "%q は 8 の倍数である必要があります." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q は %q 型か %q 型である必要があります、 %q 型は使用できません" @@ -238,6 +243,7 @@ msgstr "" "%q は %q 型や %q 型または %q 型である必要があります、 %q 型は使用できません" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q は %q 型である必要があります、 %q 型は使用できません" @@ -283,7 +289,8 @@ msgstr "%q() に %q() がありません" msgid "%q, %q, and %q must all be the same length" msgstr "%q と %q および %q はすべて同じ長さである必要があります" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -317,7 +324,7 @@ msgid "'%q' object does not support '%q'" msgstr "'%q' オブジェクトは '%q' に対応していません" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "オブジェクト'%q'はイテレータではありません" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -325,7 +332,7 @@ msgid "'%q' object is not callable" msgstr "オブジェクト'%q'は呼び出し可能ではありません" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "オブジェクト'%q'はイテレート可能ではありません" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -429,6 +436,10 @@ msgstr "'data'には整数の引数が必要" msgid "'label' requires 1 argument" msgstr "'label'には1つの引数が必要" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "関数外でのreturn" @@ -548,7 +559,6 @@ msgstr "このピン用の全てのタイマが使用中" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "全てのタイマーが使用中" @@ -561,6 +571,10 @@ msgstr "すでにアドバータイズ中" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,6 +584,7 @@ msgstr "すでに実行中" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "" @@ -596,6 +611,10 @@ msgstr "array のタイプは16ビット ('H') でなければなりません" msgid "Array values should be single bytes." msgstr "Arrayの各値は1バイトでなければなりません" +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +624,11 @@ msgstr "%d個のブロックの確保を試みました" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -674,13 +698,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "バッファ長%dは大きすぎます。%d以下でなければなりません" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "バッファ長は512の倍数でなければなりません" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "バッファは512の倍数でなければなりません" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -740,6 +764,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -785,7 +813,7 @@ msgid "Cannot record to a file" msgstr "ファイルへ記録できません" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c @@ -801,6 +829,10 @@ msgstr "RS485モードにRTSまたはCTSを指定できません" msgid "Cannot subclass slice" msgstr "sliceをサブクラス化することはできません" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -835,6 +867,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "アドレスをセットできません" @@ -847,6 +883,11 @@ msgstr "割り込みをスタートできません。RXビジー" msgid "Couldn't allocate decoder" msgstr "デコーダを確保できません" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DACチャネル初期化エラー" @@ -864,10 +905,6 @@ msgstr "DACはすでに使用中" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 ピンは、バイト整列されていなければなりません" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "fmtチャンクの後にdataチャンクが続かなければなりません" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -998,15 +1035,47 @@ msgstr "接続失敗: 内部エラー" msgid "Failed to connect: timeout" msgstr "接続失敗: タイムアウト" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "MP3ファイルのパーズに失敗" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "ミューテックスの開放に失敗。エラー 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "内部フラッシュ書き込みに失敗" @@ -1015,12 +1084,14 @@ msgstr "内部フラッシュ書き込みに失敗" msgid "File exists" msgstr "ファイルが存在します" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1045,7 +1116,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "非対応の形式" @@ -1153,6 +1224,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1198,15 +1270,19 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "不正な %q" @@ -1239,6 +1315,10 @@ msgstr "不正なBSSID" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "不正な引数" @@ -1270,6 +1350,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1282,6 +1363,7 @@ msgid "Invalid socket for TLS" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "" @@ -1322,9 +1404,15 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -1370,7 +1458,8 @@ msgstr "" msgid "Mount point directory missing" msgstr "" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "%q のサブクラスでなければなりません" @@ -1510,6 +1599,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "ピンにプルダウンがありません。1Mオーム推奨" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "デバイスに空き容量が残っていません" @@ -1554,8 +1647,9 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1610,13 +1704,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1667,6 +1754,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1686,6 +1774,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1786,6 +1878,10 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "方向がoutputのときpullは使われません" @@ -1806,10 +1902,30 @@ msgstr "RNG解体エラー" msgid "RNG Init Error" msgstr "乱数生成器の初期化エラー" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1884,10 +2000,11 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO初期化エラー %d" +msgid "SDIO Init Error %x" +msgstr "" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1936,11 +2053,13 @@ msgstr "スライスと値の長さが一致しません" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "スライスは対応していません" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" @@ -1980,22 +2099,10 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "サンプルのbits_per_sampleがミキサーのそれと一致しません" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "サンプルレートがサンプルとミキサーで一致しません" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "符号の有無がサンプルとミキサーで一致しません" - #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." msgstr "" @@ -2014,7 +2121,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "タイルの高さはビットマップの高さを割り切れる値でなければなりません" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "タイルのインデクスが範囲外" @@ -2022,6 +2131,10 @@ msgstr "タイルのインデクスが範囲外" msgid "Tile width must exactly divide bitmap width" msgstr "タイルの幅はビットマップの幅を割り切れる値でなければなりません" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2153,6 +2266,10 @@ msgstr "パーザを初期化できません" msgid "Unable to read color palette data" msgstr "カラーパレットデータを読み込めません" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2245,15 +2362,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "非対応の形式" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2263,14 +2377,12 @@ msgid "Update failed" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2306,8 +2418,10 @@ msgstr "" msgid "Wi-Fi: " msgstr "" +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2330,6 +2444,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2343,6 +2458,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2403,6 +2519,10 @@ msgstr "bytes-likeオブジェクトが必要" msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2427,6 +2547,10 @@ msgstr "argsortの引数はndarrayでなければなりません" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2477,6 +2601,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2513,6 +2641,10 @@ msgstr "不正なtypecode" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2525,6 +2657,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sampleは8または16でなければなりません" @@ -2606,7 +2747,7 @@ msgstr "式には代入できません" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "%qを%qに変換できません" @@ -2661,6 +2802,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2723,10 +2868,6 @@ msgstr "手動と自動のフィールド指定は混在できません" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -3069,7 +3210,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "formatにはdictが必要" #: py/objdeque.c @@ -3119,7 +3260,8 @@ msgstr "必須のキーワード引数'%q'が与えられていません" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3203,10 +3345,6 @@ msgid "indices must be integers, slices, or Boolean lists" msgstr "" "インデクスは、整数、スライス、boolのリストのいずれかでなければなりません" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" @@ -3272,7 +3410,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3401,10 +3539,6 @@ msgstr "ラベル'%q'は定義されていません" msgid "label redefined" msgstr "ラベルの再定義" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "levelは0から1の間でなければなりません" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "左辺と右辺が互換でなければなりません" @@ -3458,7 +3592,7 @@ msgstr "正定値行列ではありません" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3536,7 +3670,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "名前 '%q' は定義されていません" #: py/runtime.c @@ -3600,7 +3734,7 @@ msgstr "nonlocalの対象が見つかりません" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3809,6 +3943,10 @@ msgstr "ord()は1文字を要求しますが、長さ %d の文字列が与え msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3833,6 +3971,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "long intをマシンのwordに変換する際にオーバーフローしました" @@ -3942,6 +4088,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3959,6 +4109,10 @@ msgstr "スクリプトのコンパイルは非対応" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3979,6 +4133,10 @@ msgstr "整数フォーマット指定子'c'で符号は使えません" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4052,18 +4210,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "部分文字列が見つかりません" @@ -4076,10 +4222,6 @@ msgstr "super()がselfを見つけられません" msgid "syntax error in JSON" msgstr "JSONに構文エラーがあります" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "uctypedディスクリプタの構文エラー" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4169,11 +4311,11 @@ msgid "tx and rx cannot both be None" msgstr "txとrxを両方ともNoneにできません" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "型'%q'はベース型として使えません" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "この型はベース型にできません" #: py/runtime.c @@ -4188,10 +4330,6 @@ msgstr "typeは1つか3つの引数をとります" msgid "ulonglong too large" msgstr "" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "単項演算子 %q は未実装" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4239,7 +4377,9 @@ msgstr "" msgid "unreadable attribute" msgstr "読み込み不可能な属性" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "非対応の型 %q" @@ -4317,11 +4457,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4384,6 +4519,40 @@ msgstr "ziはfloat値でなければなりません" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Unsupported format" +#~ msgstr "非対応の形式" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "fmtチャンクの後にdataチャンクが続かなければなりません" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "levelは0から1の間でなければなりません" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "サンプルのbits_per_sampleがミキサーのそれと一致しません" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "サンプルレートがサンプルとミキサーで一致しません" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "符号の有無がサンプルとミキサーで一致しません" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "バッファ長は512の倍数でなければなりません" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "バッファは512の倍数でなければなりません" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO初期化エラー %d" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "uctypedディスクリプタの構文エラー" + +#~ msgid "unary op %q not implemented" +#~ msgstr "単項演算子 %q は未実装" + #~ msgid "Name too long" #~ msgstr "名前が長すぎます" @@ -4517,7 +4686,7 @@ msgstr "" #~ msgid "'continue' outside loop" #~ msgstr "ループ外でのcontinue" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "'coroutine' オブジェクトはイテレータではありません" #~ msgid "Address type out of range" @@ -5117,7 +5286,7 @@ msgstr "" #~ msgid "n must be between 0, and 9" #~ msgstr "nは0から9まで" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "引数で名前が再利用されています" #~ msgid "no available NIC" diff --git a/locale/ko.po b/locale/ko.po index 66cd549c11c5d..9e570208d398a 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -7,15 +7,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-12-23 14:56+0000\n" -"Last-Translator: 오수아 \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: LANGUAGE \n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.4-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -81,8 +81,8 @@ msgstr " 산출:\n" #: py/objstr.c #, c-format -msgid "%%c requires int or char" -msgstr "%%c 전수(int)또는 캐릭터(char)필요합니다" +msgid "%%c needs int or char" +msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -91,11 +91,16 @@ msgid "" msgstr "" "%d 주소 핀들, %d rgb 핀들과 %d 타일 들은 높이가 %d임을 나타낸다, %d가 아니라" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q 및 %q에 중복된 핀이 포함" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q와 %q는 달라야 합니다" @@ -112,14 +117,21 @@ msgid "%q contains duplicate pins" msgstr "%q에 중복된 핀이 포함" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q 실패: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q의 %q는 %q가 아니라 %q 유형이어야 합니다" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -127,7 +139,8 @@ msgstr "%q의 %q는 %q가 아니라 %q 유형이어야 합니다" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "%q 사용 중입니다" @@ -139,7 +152,9 @@ msgstr "%q 인덱스 범위를 벗어났습니다" msgid "%q indices must be integers, not %s" msgstr "%q 인덱스는 %s 가 아닌 정수 여야합니다" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q 초기화 실패" @@ -167,17 +182,12 @@ msgstr "%q 길이는 <= %d>여야 합니다" msgid "%q length must be >= %d" msgstr "%q 길이는 >= %d이어야 합니다" -#: py/modsys.c py/objmodule.c py/runtime.c -#, fuzzy -msgid "%q moved from %q to %q" -msgstr "%q가 %q에서 %q로 이동했습니다" - #: py/argcheck.c msgid "%q must be %d" msgstr "%q는 %d이어야 합니다" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -233,6 +243,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q는 %q가 아닌 %q 또는 %q 유형이어야 합니다" @@ -242,6 +253,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q는 %q가 아니라 %q 유형이어야 합니다" @@ -250,25 +262,31 @@ msgstr "%q는 %q가 아니라 %q 유형이어야 합니다" msgid "%q must be power of 2" msgstr "%q는 2의 거듭제곱이어야 합니다" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c #, fuzzy msgid "%q out of bounds" msgstr "%q가 경계를 벗어남" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c #, fuzzy msgid "%q out of range" msgstr "%q가 범위를 벗어남" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "%q가 %q로 이름이 변경되었습니다" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c #, fuzzy msgid "%q step cannot be zero" @@ -291,7 +309,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q 및 %q의 길이는 모두 같아야 합니다" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -322,20 +341,20 @@ msgstr "%s 오류 0x%x" msgid "'%q' argument required" msgstr "'%q' 인수가 필요합니다" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "'%q' 개체가 '%q'를 지원하지 않습니다" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "'%q' 개체가 iterator가 아닙니다" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" -msgstr "'%q' 개체를 호출할 수 없습니다" +msgid "'%q' object isn't callable" +msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "'%q' 개체를 사용할 수 없습니다" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -442,6 +461,10 @@ msgstr "'data' 에는 정수 인수가 필요합니다" msgid "'label' requires 1 argument" msgstr "'label' 에는 1 개의 독립변수가 필요합니다" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' 는 함수 외부에 존재합니다" @@ -469,6 +492,7 @@ msgstr "*x는 할당 대상이어야 합니다" msgid ", in %q\n" msgstr ", 에서 %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -488,10 +512,10 @@ msgstr "pow() 는 3개의 인수를 지원하지 않습니다" msgid "AP could not be started" msgstr "AP를 시작할 수 없습니다" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" -msgstr "주소 길이는 % d 바이트 여야합니다" +msgstr "주소 길이는 %d 바이트 여야합니다" #: ports/espressif/common-hal/memorymap/AddressRange.c #: ports/nordic/common-hal/memorymap/AddressRange.c @@ -525,7 +549,8 @@ msgstr "모든 RX FIFOs가 사용 중입니다" msgid "All SPI peripherals are in use" msgstr "사용중인 모든 SPI주변 기기" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "사용중인 모든 UART주변 기기" @@ -570,7 +595,6 @@ msgstr "핀의 모든 타이머가 사용 중입니다" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "모든 타이머가 사용 중입니다" @@ -585,6 +609,10 @@ msgstr "이미 광고 중입니다." msgid "Already have all-matches listener" msgstr "이미 모든 일치 리스너가 있습니다" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -594,11 +622,12 @@ msgstr "이미 실행 중입니다" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c #, fuzzy msgid "Already scanning for wifi networks" msgstr "이미 wifi 네트워크를 찾고 있습니다" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "%s'을(를) 검색하는 동안 오류가 발생했습니다:\n" @@ -623,6 +652,10 @@ msgstr "배열은 하프워드(유형 'H')가 포함되어야 합니다" msgid "Array values should be single bytes." msgstr "배열 값은 1바이트 여야합니다." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -632,6 +665,12 @@ msgstr "%d 블록 할당 시도" msgid "Audio conversion not implemented" msgstr "오디오 변환이 구현되지 않음" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN은 암호와 함께 사용되지 않습니다" @@ -656,6 +695,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "주변 기기에서 전송 속도가 지원되지 않습니다" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -673,20 +713,17 @@ msgstr "비트맵 크기와 값 당 비트가 일치해야 합니다" msgid "Boot device must be first (interface #0)." msgstr "부팅 장치는 첫 번째(인터페이스 #0)여야 합니다." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "플로우 제어에 RX와 TX가 모두 필요합니다" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "밝기를 조절할 수 없습니다" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset이 너무 작습니다 %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "버퍼 요소는 4바이트 이하여야 합니다" @@ -701,13 +738,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "버퍼 길이 %d가 너무 큽니다. 그것은 %d보다 작아야 합니다" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "버퍼 길이는 512의 배수여야 합니다" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "버퍼는 512 바이트의 배수여야 합니다" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -729,10 +766,6 @@ msgstr "버퍼가 너무 작습니다" msgid "Bus pin %d is already in use" msgstr "Bus 핀 %d은 이미 사용 중입니다" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "잘못된 크기의 버퍼. 16 바이트 여야합니다." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC 블록은 16 바이트의 배수여야 합니다" @@ -766,6 +799,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -781,6 +818,10 @@ msgstr "현재 USB 디바이스를 변경할 수 없습니다" msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "_bleio.adapter를 사용해서; 새로운 Adapter를 만들 수 없습니다;" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -811,10 +852,11 @@ msgid "Cannot record to a file" msgstr "파일에 녹음 할 수 없습니다" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "USB를 통해 표시될 때 '/'은 다시 마운트할 수 없습니다." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "방향이 입력되면 값을 설정할 수 없습니다." @@ -827,6 +869,10 @@ msgstr "RS485 모드에서는 RTS 또는 CTS를 지정할 수 없습니다" msgid "Cannot subclass slice" msgstr "" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c #, fuzzy msgid "Cannot wake on pin edge, only level" @@ -863,6 +909,14 @@ msgstr "좌표 배열의 길이가 다릅니다" msgid "Coordinate arrays types have different sizes" msgstr "좌표 배열 유형은 크기가 다릅니다" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "주소를 설정할 수 없습니다" @@ -875,6 +929,11 @@ msgstr "인터럽트를 시작할 수 없습니다, RX가 사용 중입니다" msgid "Couldn't allocate decoder" msgstr "디코더를 할당할 수 없습니다" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DAC 채널 초기화 오류" @@ -892,10 +951,6 @@ msgstr "DAC가 현재 사용 중입니다" msgid "Data 0 pin must be byte aligned" msgstr "데이터 0 핀은 바이트 정렬되어야 합니다" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "데이터 청크는 fmt 청크를 따라야 합니다" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "데이터 형식 오류(손상된 데이터일 수 있습니다)" @@ -935,6 +990,7 @@ msgstr "디스플레이는 16 비트 색 공간을 가져야 합니다." #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "디스플레이 회전은 90도씩 증가해야 합니다" @@ -943,6 +999,7 @@ msgid "Done" msgstr "완료" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "방향을 입력할 때 드라이브 모드는 사용되지 않습니다." @@ -954,8 +1011,17 @@ msgstr "위 예외를 처리하는 동안, 또 다른 예외가 발생하였습 msgid "ECB only operates on 16 bytes at a time" msgstr "ECB는 한 번에 16 바이트에서만 작동합니다" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "ESP-IDF 메모리 할당에 실패하였습니다" @@ -1005,7 +1071,7 @@ msgstr "" "서비스 TXT 레코드를 추가하는 것에 실패했습니다; txt_records에서 비문자열 또" "는 바이트가 발견되었습니다" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "%q 버퍼 할당에 실패했습니다" @@ -1023,22 +1089,60 @@ msgstr "샘플 버퍼링에 실패했습니다" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "연결에 실패했습니다: 내부 오류" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "연결에 실패했습니다: 시간 초과" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "MP3 파일 분석에 실패했습니다" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "뮤텍스 해제에 실패했습니다, 오류 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c #, fuzzy msgid "Failed to write internal flash." @@ -1048,12 +1152,13 @@ msgstr "내부 플래시를 쓰는 것에 실패했습니다." msgid "File exists" msgstr "파일이 있습니다" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "파일을 찾을 수 없습니다" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "필터가 너무 복잡합니다" @@ -1078,7 +1183,7 @@ msgstr "L8 색상 공간의 경우, 입력 비트맵은 픽셀 당 8 비트를 msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "RGB 색상 공간의 경우, 입력 비트맵은 픽셀 당 16 비트를 가져야 합니다" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "지원되지 않는 형식입니다" @@ -1102,6 +1207,7 @@ msgstr "GNSS 초기화" msgid "Generic Failure" msgstr "일반 오류" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1188,6 +1294,7 @@ msgid "Insufficient stream input buffer" msgstr "불충분한 스트림 입력 버퍼" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "인터페이스를 시작해야 합니다" @@ -1199,7 +1306,8 @@ msgstr "내부 오디오 버퍼가 너무 작습니다" msgid "Internal define error" msgstr "내부 정의 오류" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "내부 오류" @@ -1233,18 +1341,29 @@ msgstr "인터럽트 오류." msgid "Interrupted by output function" msgstr "출력 함수로 인해 종료되었다" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "잘못된 %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1274,6 +1393,14 @@ msgstr "잘못된 BSSID" msgid "Invalid MAC address" msgstr "잘못된 MAC 주소" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "잘못된 인수" @@ -1282,17 +1409,12 @@ msgstr "잘못된 인수" msgid "Invalid bits per value" msgstr "값 당 잘못된 비트" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "잘못된 바이트 %.*s" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "잘못된 data_pins[%d]" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "잘못된 형식" @@ -1305,6 +1427,7 @@ msgid "Invalid hex password" msgstr "잘못된 16진수 패스워드" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "잘못된 멀티캐스트 MAC 주소" @@ -1316,11 +1439,13 @@ msgstr "잘못된 크기" msgid "Invalid socket for TLS" msgstr "TLS에 대한 잘못된 소켓" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "잘못된 상태" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "잘못된 유니코드 이스케이프" @@ -1328,10 +1453,6 @@ msgstr "잘못된 유니코드 이스케이프" msgid "Key must be 16, 24, or 32 bytes long" msgstr "키는 16, 24, 또는 32 바이트 길이여야 합니다" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "키를 찾을 수 없습니다" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "LED 매핑은 디스플레이 크기와 일치해야 합니다" @@ -1357,13 +1478,23 @@ msgid "MAC address was invalid" msgstr "MAC 주소는 잘못되었습니다" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "매핑은 투플이어야 합니다" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1456,7 +1587,7 @@ msgstr "빠른 메모리 부족" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "%q 핀이 없습니다" @@ -1474,6 +1605,7 @@ msgstr "칩에 DAC가 없습니다" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "DMA 채널을 찾을 수 없습니다" @@ -1552,6 +1684,10 @@ msgstr "SDA 또는 SCL에서 풀업을 찾을 수 없습니다; 케이블 연결 msgid "No pulldown on pin; 1Mohm recommended" msgstr "핀에 풀다운이 없습니다; 1Mohm를 권장합니다" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "장치에 남은 공간이 없습니다" @@ -1587,19 +1723,15 @@ msgid "Not connected" msgstr "연결되지 않았습니다" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "재생되지 않았습니다" -#: shared-module/jpegio/JpegDecoder.c -#, fuzzy -msgid "Not supported JPEG standard" -msgstr "지원되지 않는 JPEG 표준" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "data_pins은 %d이 아닌, 8 또는 16개 여야 합니다" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "" #: shared-bindings/util.c msgid "" @@ -1653,15 +1785,6 @@ msgstr "이 하드웨어에서는 에지 감지만 가능합니다" msgid "Only int or string supported for ip" msgstr "ip에는 정수 또는 문자열만 지원됩니다" -#: shared-module/displayio/OnDiskBitmap.c -#, fuzzy, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"흑백, 인덱싱된 4bpp 또는 8bpp, 그리고 16bpp 또는 그 이상의 BMP만 지원됩니다: " -"%d bpp가 지정되었습니다" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "딥 슬립에서는 하나의 %q만 설정할 수 있습니다." @@ -1702,6 +1825,7 @@ msgid "Operation or feature not supported" msgstr "작업 또는 기능이 지원되지 않습니다" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #, fuzzy msgid "Operation timed out" msgstr "작업 시간 초과되었습니다" @@ -1717,6 +1841,7 @@ msgstr "메모리 부족" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "소켓 부족" @@ -1739,6 +1864,10 @@ msgstr "PWM slice가 이미 사용 중입니다" msgid "PWM slice channel A already in use" msgstr "PWM slice channel A가 이미 사용 중입니다" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c #, fuzzy msgid "Parameter error" @@ -1840,7 +1969,12 @@ msgstr "프로그램 크기가 잘못되었습니다" msgid "Program too long" msgstr "프로그램이 너무 깁니다" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c #, fuzzy msgid "Pull not used when direction is output." msgstr "방향이 출력 될 때 풀은 사용되지 않습니다" @@ -1861,6 +1995,27 @@ msgstr "RNG DeInit 오류" msgid "RNG Init Error" msgstr "RNG 초기화 오류" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1939,9 +2094,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1952,6 +2108,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -1991,6 +2151,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1999,6 +2160,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -2035,20 +2200,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -2069,7 +2222,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2077,6 +2232,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2087,11 +2246,16 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2130,6 +2294,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2138,13 +2306,21 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2162,10 +2338,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID문자열이 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'형식이 아닙니다" @@ -2183,6 +2355,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2191,6 +2364,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "" @@ -2208,6 +2382,10 @@ msgstr "파서를 초기화(init) 할 수 없습니다" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2292,6 +2470,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "" @@ -2300,15 +2482,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2317,15 +2496,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2361,8 +2545,10 @@ msgstr "" msgid "Wi-Fi: " msgstr "" +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2385,6 +2571,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2398,6 +2585,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2454,10 +2642,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2482,6 +2678,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2512,10 +2712,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2532,6 +2728,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2568,6 +2768,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2580,9 +2784,18 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" -msgstr "bits_per_sample은 8 또는 16이어야합니다." +msgstr "bits_per_sample은 8 또는 16이어야합니다" #: py/emitinlinethumb.c msgid "branch not in range" @@ -2637,6 +2850,10 @@ msgstr "" msgid "can only have one parent" msgstr "" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2661,7 +2878,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2704,6 +2921,14 @@ msgstr "" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2716,6 +2941,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2778,10 +3007,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2802,18 +3027,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -2968,7 +3189,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3067,10 +3288,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3111,16 +3328,20 @@ msgstr "float이 너무 큽니다" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3170,7 +3391,8 @@ msgstr "" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3187,10 +3409,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3253,18 +3471,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3322,7 +3532,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3355,6 +3565,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3451,10 +3665,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3508,7 +3718,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3553,6 +3763,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3586,7 +3800,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3601,10 +3815,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3626,7 +3836,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3650,7 +3860,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3676,7 +3886,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3695,14 +3905,6 @@ msgstr "" msgid "not a constant" msgstr "" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "" @@ -3711,6 +3913,10 @@ msgstr "" msgid "not supported for input types" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3724,6 +3930,10 @@ msgstr "" msgid "object '%s' isn't a tuple or list" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3765,10 +3975,6 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "" @@ -3817,6 +4023,30 @@ msgstr "" msgid "opcode" msgstr "" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3859,6 +4089,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3883,6 +4117,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3892,8 +4134,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3945,14 +4187,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3962,6 +4204,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3992,6 +4238,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4009,6 +4259,10 @@ msgstr "" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -4029,6 +4283,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4077,10 +4335,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4102,18 +4356,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4126,10 +4368,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4219,11 +4457,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4234,14 +4472,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4289,7 +4519,9 @@ msgstr "" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "" @@ -4367,11 +4599,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4434,6 +4661,62 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "%q renamed %q" +#~ msgstr "%q가 %q로 이름이 변경되었습니다" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset이 너무 작습니다 %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "잘못된 크기의 버퍼. 16 바이트 여야합니다." + +#, c-format +#~ msgid "Invalid byte %.*s" +#~ msgstr "잘못된 바이트 %.*s" + +#~ msgid "Key not found" +#~ msgstr "키를 찾을 수 없습니다" + +#, fuzzy +#~ msgid "Not supported JPEG standard" +#~ msgstr "지원되지 않는 JPEG 표준" + +#, fuzzy +#~ msgid "%q moved from %q to %q" +#~ msgstr "%q가 %q에서 %q로 이동했습니다" + +#, c-format +#~ msgid "%%c requires int or char" +#~ msgstr "%%c 전수(int)또는 캐릭터(char)필요합니다" + +#~ msgid "'%q' object is not callable" +#~ msgstr "'%q' 개체를 호출할 수 없습니다" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "USB를 통해 표시될 때 '/'은 다시 마운트할 수 없습니다." + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "데이터 청크는 fmt 청크를 따라야 합니다" + +#, fuzzy, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "흑백, 인덱싱된 4bpp 또는 8bpp, 그리고 16bpp 또는 그 이상의 BMP만 지원됩니" +#~ "다: %d bpp가 지정되었습니다" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "버퍼 길이는 512의 배수여야 합니다" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "버퍼는 512 바이트의 배수여야 합니다" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "data_pins은 %d이 아닌, 8 또는 16개 여야 합니다" + #~ msgid "Name too long" #~ msgstr "이름이 너무 깁니다" @@ -4538,13 +4821,13 @@ msgstr "" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' 은 삭제할 수 없습니다" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' 은 수정할 수 없습니다" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' 을 검색 할 수 없습니다" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' 은 변경할 수 없습니다" #~ msgid "'break' outside loop" diff --git a/locale/nl.po b/locale/nl.po index 025ef1b3e0a8e..bafb415635e4d 100644 --- a/locale/nl.po +++ b/locale/nl.po @@ -6,15 +6,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Jeff Epler \n" +"PO-Revision-Date: 2025-07-13 16:01+0000\n" +"Last-Translator: Mirthe Winter \n" "Language-Team: none\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.2\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -49,7 +49,7 @@ msgstr "" #: py/obj.c msgid " File \"%q\"" -msgstr " Bestand" +msgstr " Bestand \"%q\"" #: py/obj.c msgid " File \"%q\", line %d" @@ -61,7 +61,7 @@ msgstr "" #: main.c msgid " not found.\n" -msgstr "" +msgstr " niet gevonden.\n" #: main.c msgid " output:\n" @@ -82,7 +82,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "" @@ -102,7 +102,11 @@ msgstr "" msgid "%q failure: %d" msgstr "%q fout: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" @@ -154,7 +158,7 @@ msgstr "" msgid "%q length must be >= %d" msgstr "" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "" @@ -214,6 +218,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -223,6 +228,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -268,7 +274,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "" @@ -302,7 +309,7 @@ msgid "'%q' object does not support '%q'" msgstr "'%q' object ondersteunt geen '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "'%q' object is geen iterator" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -310,7 +317,7 @@ msgid "'%q' object is not callable" msgstr "'%q' object is niet aanroepbaar" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "'%q' object is niet itereerbaar" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -414,6 +421,10 @@ msgstr "'data' vereist integer argumenten" msgid "'label' requires 1 argument" msgstr "'label' vereist 1 argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' buiten de functie" @@ -533,7 +544,6 @@ msgstr "Alle timers voor deze pin zijn in gebruik" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Alle timers zijn in gebruik" @@ -546,6 +556,10 @@ msgstr "Advertising is al bezig." msgid "Already have all-matches listener" msgstr "Heeft al een luisteraar voor 'all-matches'" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Al in uitvoering" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -555,6 +569,7 @@ msgstr "Wordt al uitgevoerd" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Zoekt al naar WiFi netwerken" @@ -581,6 +596,10 @@ msgstr "Array moet halfwords (type 'H') bevatten" msgid "Array values should be single bytes." msgstr "Array waardes moet enkele bytes zijn." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -590,6 +609,11 @@ msgstr "Poging om %d blokken toe te wijzen" msgid "Audio conversion not implemented" msgstr "" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Audiobronfout" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -607,8 +631,8 @@ msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -"Auto-herlaad staat aan. Sla bestanden simpelweg op over USB om uit te voeren " -"of start REPL om uit te schakelen.\n" +"Auto-herlaad staat aan. Sla bestanden simpelweg via USB op om ze uit te " +"voeren of start REPL om ze uit te schakelen.\n" #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" @@ -659,13 +683,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Buffer lengte %d te groot. Het moet kleiner zijn dan %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Buffer lengte moet een veelvoud van 512 zijn" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Buffer moet een veelvoud van 512 bytes zijn" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -677,7 +701,7 @@ msgstr "Buffer is %d bytes te klein" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/struct/__init__.c shared-module/struct/__init__.c msgid "Buffer too small" -msgstr "" +msgstr "Buffer te klein" #: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c @@ -723,6 +747,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -769,7 +797,7 @@ msgid "Cannot record to a file" msgstr "Kan niet opnemen naar een bestand" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c @@ -785,6 +813,10 @@ msgstr "Kan RTS of CTS niet specificeren in RS485 modus" msgid "Cannot subclass slice" msgstr "Kan slice niet subclasseren" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -821,6 +853,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Kan adres niet zetten" @@ -833,6 +869,11 @@ msgstr "Kan interrupt niet starten, RX is bezig" msgid "Couldn't allocate decoder" msgstr "Kan decoder niet alloceren" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DAC kanaal Init Fout" @@ -850,10 +891,6 @@ msgstr "DAC al in gebruik" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 pin moet byte uitgelijnd zijn" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Data chunk moet gevolgd worden door fmt chunk" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -897,7 +934,7 @@ msgstr "Beeldscherm rotatie moet in stappen van 90 graden" #: main.c msgid "Done" -msgstr "" +msgstr "Gedaan" #: shared-bindings/digitalio/DigitalInOut.c msgid "Drive mode not used when direction is input." @@ -984,15 +1021,47 @@ msgstr "Verbinding mislukt: interne fout" msgid "Failed to connect: timeout" msgstr "Verbinding mislukt: timeout" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Mislukt om MP3 bestand te ontleden" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Mislukt mutex los te laten, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Schrijven naar interne flash mislukt." @@ -1001,23 +1070,25 @@ msgstr "Schrijven naar interne flash mislukt." msgid "File exists" msgstr "Bestand bestaat" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" -msgstr "" +msgstr "Bestand niet gevonden" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filters zijn te complex" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is duplicate" -msgstr "" +msgstr "Firmware is duplicaat" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is invalid" -msgstr "" +msgstr "Firmware is ongeldig" #: ports/espressif/common-hal/dualbank/__init__.c msgid "Firmware is too big" @@ -1031,7 +1102,7 @@ msgstr "" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Formaat wordt niet ondersteund" @@ -1051,7 +1122,7 @@ msgstr "" #: ports/espressif/common-hal/espidf/__init__.c msgid "Generic Failure" -msgstr "" +msgstr "Generieke mislukking" #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c @@ -1139,6 +1210,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1152,7 +1224,7 @@ msgstr "Interne define fout" #: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c msgid "Internal error" -msgstr "" +msgstr "Interne fout" #: shared-module/rgbmatrix/RGBMatrix.c #, c-format @@ -1178,21 +1250,25 @@ msgstr "" #: supervisor/shared/safe_mode.c msgid "Interrupt error." -msgstr "" +msgstr "Interruptfout." #: shared-module/jpegio/JpegDecoder.c msgid "Interrupted by output function" msgstr "" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Ongeldige %q" @@ -1215,7 +1291,7 @@ msgstr "Ongeldige ADC Unit waarde" #: ports/espressif/common-hal/_bleio/__init__.c #: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid BLE parameter" -msgstr "" +msgstr "Ongeldige BLE-parameter" #: shared-bindings/wifi/Radio.c msgid "Invalid BSSID" @@ -1223,6 +1299,10 @@ msgstr "Ongeldig BSSID" #: shared-bindings/wifi/Radio.c msgid "Invalid MAC address" +msgstr "Ongeldig MAC-adres" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c @@ -1245,7 +1325,7 @@ msgstr "" #: shared-module/msgpack/__init__.c msgid "Invalid format" -msgstr "" +msgstr "Ongeldig formaat" #: shared-module/audiocore/WaveFile.c msgid "Invalid format chunk size" @@ -1256,24 +1336,26 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c msgid "Invalid size" -msgstr "" +msgstr "Ongeldige grootte" #: shared-module/ssl/SSLSocket.c msgid "Invalid socket for TLS" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" -msgstr "" +msgstr "Ongeldige staat" #: shared-module/os/getenv.c msgid "Invalid unicode escape" -msgstr "" +msgstr "Ongeldige unicode escape" #: shared-bindings/aesio/aes.c msgid "Key must be 16, 24, or 32 bytes long" @@ -1281,7 +1363,7 @@ msgstr "Sleutel moet 16, 24, of 32 bytes lang zijn" #: shared-module/os/getenv.c msgid "Key not found" -msgstr "" +msgstr "Sleutel niet gevonden" #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" @@ -1308,9 +1390,15 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -1356,7 +1444,8 @@ msgstr "" msgid "Mount point directory missing" msgstr "" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "%q moet een subklasse zijn." @@ -1435,7 +1524,7 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "No IP" -msgstr "" +msgstr "Geen IP" #: ports/atmel-samd/common-hal/microcontroller/__init__.c #: ports/cxd56/common-hal/microcontroller/__init__.c @@ -1496,6 +1585,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Geen pulldown op pin; 1MOhm aangeraden" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "Geen ruimte meer beschikbaar op apparaat" @@ -1540,8 +1633,9 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1598,15 +1692,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Alleen monochrome en 4bpp of 8bpp, en 16bpp of grotere geïndiceerde BMP's " -"zijn ondersteund: %d bpp is gegeven" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1657,6 +1742,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Geen sockets meer beschikbaar" @@ -1676,6 +1762,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1755,7 +1845,7 @@ msgstr "Prefix buffer moet op de heap zijn" #: main.c msgid "Press any key to enter the REPL. Use CTRL-D to reload.\n" msgstr "" -"Druk een willekeurige toets om de REPL te starten. Gebruik CTRL+D om te " +"Druk op een willekeurige toets om de REPL te starten. Gebruik CTRL+D om te " "herstarten.\n" #: main.c @@ -1778,6 +1868,10 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull niet gebruikt wanneer de richting output is." @@ -1798,10 +1892,30 @@ msgstr "RNG DeInit Fout" msgid "RNG Init Error" msgstr "RNG Init Fout" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1833,7 +1947,7 @@ msgstr "" #: supervisor/shared/bluetooth/bluetooth.c msgid "Reconnecting" -msgstr "" +msgstr "Opnieuw aansluiten" #: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Refresh too soon" @@ -1876,10 +1990,11 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo Fout %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO Init Fout %d" +msgid "SDIO Init Error %x" +msgstr "" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1928,11 +2043,13 @@ msgstr "Slice en waarde hebben verschillende lengtes." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Slices niet ondersteund" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool kan alleen met wifi.radio gebruikt worden" @@ -1972,21 +2089,9 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "De lengte van rgb_pins moet 6, 12, 18, 24 of 30 zijn" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "De sample's bits_per_sample komen niet overeen met die van de mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "De sample's kanaal aantal komt niet overeen met die van de mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "De sample's sample rate komt niet overeen met die van de mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "De sample's signature komt niet overeen met die van de mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2006,7 +2111,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Tile hoogte moet exact de bitmap hoogte verdelen" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Tile index buiten bereik" @@ -2014,6 +2121,10 @@ msgstr "Tile index buiten bereik" msgid "Tile width must exactly divide bitmap width" msgstr "Tile breedte moet exact de bitmap breedte verdelen" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Tijdstip ligt in het verleden." @@ -2081,7 +2192,7 @@ msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2144,6 +2255,10 @@ msgstr "Niet in staat om de parser te initialiseren" msgid "Unable to read color palette data" msgstr "Niet in staat kleurenpalet data te lezen" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2238,15 +2353,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "Niet-ondersteund beeldscherm bus type" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Niet-ondersteunde format" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2256,14 +2368,12 @@ msgid "Update failed" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Waarde lengte != vereist vaste lengte" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2299,11 +2409,13 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi is niet ingeschakeld" #: main.c msgid "Woken up by alarm.\n" @@ -2325,6 +2437,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2338,6 +2451,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2398,6 +2512,10 @@ msgstr "een bytes-achtig object is vereist" msgid "addresses is empty" msgstr "adressen zijn leeg" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2422,6 +2540,10 @@ msgstr "argsort argument moet een ndarray zijn" msgid "argsort is not implemented for flattened arrays" msgstr "argsort wordt niet geïmplementeerd voor vlakke arrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2472,6 +2594,10 @@ msgstr "poging om argmin/argmax van een lege sequentie te krijgen" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "as is buiten bereik" @@ -2508,6 +2634,10 @@ msgstr "verkeerde typecode" msgid "binary op %q not implemented" msgstr "binaire op %q niet geïmplementeerd" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2520,6 +2650,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample moet 8 of 16 zijn" @@ -2602,7 +2741,7 @@ msgstr "kan niet toewijzen aan expressie" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kan %q niet naar %q converteren" @@ -2657,6 +2796,10 @@ msgstr "kan expressie niet verwijderen" msgid "can't do binary op between '%q' and '%q'" msgstr "kan geen een binaire operatie doen tussen '%q' en '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "kan '%q niet impliciet converteren naar 'bool'" @@ -2719,10 +2862,6 @@ msgstr "kan niet schakelen tussen handmatige en automatische veld specificatie" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -3063,7 +3202,7 @@ msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "format vereist een dict" #: py/objdeque.c @@ -3113,7 +3252,8 @@ msgstr "functie mist vereist sleutelwoord argument \"%q" msgid "function missing required positional argument #%d" msgstr "functie mist vereist positie-argument #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3187,7 +3327,7 @@ msgstr "" #: ports/espressif/common-hal/pulseio/PulseIn.c #: shared-bindings/bitmaptools/__init__.c msgid "index out of range" -msgstr "index is buiten bereik" +msgstr "index buiten bereik" #: py/obj.c msgid "indices must be integers" @@ -3197,10 +3337,6 @@ msgstr "indices moeten integers zijn" msgid "indices must be integers, slices, or Boolean lists" msgstr "indices moeten integers, segmenten (slices) of Boolean lijsten zijn" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "oorspronkelijke waarden moeten itereerbaar zijn" @@ -3266,7 +3402,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "invoer moet een gesloten ndarray zijn" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "invoer moet een ndarray zijn" @@ -3397,10 +3533,6 @@ msgstr "label '%q' is niet gedefinieerd" msgid "label redefined" msgstr "label opnieuw gedefinieerd" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "level moet tussen 0 en 1 liggen" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs en rhs moeten compatibel zijn" @@ -3454,7 +3586,7 @@ msgstr "matrix is niet positief-definiet" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length moet 0-%d zijn als fixed_length %s is" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3532,7 +3664,7 @@ msgid "must use keyword argument for key function" msgstr "voor sleutelfunctie moet een trefwoordargument gebruikt worden" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "naam '%q' is niet gedefinieerd" #: py/runtime.c @@ -3596,7 +3728,7 @@ msgstr "geen binding voor nonlocal gevonden" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3805,6 +3937,10 @@ msgstr "ord() verwacht een teken (char) maar vond een string van lengte %d" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3829,6 +3965,14 @@ msgstr "" msgid "out of range of target" msgstr "buiten bereik van doel" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "overloop bij converteren van long int naar machine word" @@ -3938,6 +4082,10 @@ msgstr "roll argument moet een ndarray zijn" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3955,6 +4103,10 @@ msgstr "scriptcompilatie wordt niet ondersteund" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3975,6 +4127,10 @@ msgstr "teken niet toegestaan bij integer formaatspecificatie 'c'" msgid "size is defined for ndarrays only" msgstr "omvang is alleen voor ndarrays gedefinieerd" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4048,18 +4204,6 @@ msgstr "string index buiten bereik" msgid "string indices must be integers, not %s" msgstr "string indices moeten integer zijn, niet %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index buiten bereik" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: geen velden" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "deelreeks niet gevonden" @@ -4072,10 +4216,6 @@ msgstr "super() kan self niet vinden" msgid "syntax error in JSON" msgstr "syntaxisfout in JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "syntaxisfout in uctypes aanduiding" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4165,11 +4305,11 @@ msgid "tx and rx cannot both be None" msgstr "tx en rx kunnen niet beiden None zijn" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "type '%q' is geen aanvaardbaar basistype" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "type is geen aanvaardbaar basistype" #: py/runtime.c @@ -4184,10 +4324,6 @@ msgstr "type accepteert 1 of 3 argumenten" msgid "ulonglong too large" msgstr "ulonglong te groot" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "unair op %q niet geïmplementeerd" - #: py/parse.c msgid "unexpected indent" msgstr "onverwachte inspringing" @@ -4235,7 +4371,9 @@ msgstr "" msgid "unreadable attribute" msgstr "onleesbaar attribuut" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "niet ondersteund %q type" @@ -4313,14 +4451,9 @@ msgstr "" msgid "width must be greater than zero" msgstr "breedte moet groter dan nul zijn" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" -msgstr "" +msgstr "wifi.monitor niet beschikbaar" #: shared-bindings/_bleio/Adapter.c msgid "window must be <= interval" @@ -4380,6 +4513,57 @@ msgstr "zi moet van type float zijn" msgid "zi must be of shape (n_section, 2)" msgstr "zi moet vorm (n_section, 2) hebben" +#~ msgid "Unsupported format" +#~ msgstr "Niet-ondersteunde format" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Data chunk moet gevolgd worden door fmt chunk" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Alleen monochrome en 4bpp of 8bpp, en 16bpp of grotere geïndiceerde BMP's " +#~ "zijn ondersteund: %d bpp is gegeven" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "level moet tussen 0 en 1 liggen" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "De sample's bits_per_sample komen niet overeen met die van de mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "De sample's kanaal aantal komt niet overeen met die van de mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "De sample's sample rate komt niet overeen met die van de mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "De sample's signature komt niet overeen met die van de mixer" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Buffer lengte moet een veelvoud van 512 zijn" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Buffer moet een veelvoud van 512 bytes zijn" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO Init Fout %d" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index buiten bereik" + +#~ msgid "struct: no fields" +#~ msgstr "struct: geen velden" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "syntaxisfout in uctypes aanduiding" + +#~ msgid "unary op %q not implemented" +#~ msgstr "unair op %q niet geïmplementeerd" + #~ msgid "Name too long" #~ msgstr "Naam te lang" @@ -4557,13 +4741,13 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' object ondersteunt item verwijdering niet" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' object is geen iterator" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' object is niet aanroepbaar" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' object is niet itereerbaar" #~ msgid "'%s' object is not subscriptable" @@ -4581,7 +4765,7 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "'continue' outside loop" #~ msgstr "'continue' buiten de loop" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "'coroutine' object is geen iterator" #~ msgid "ADC2 is being used by WiFi" @@ -5358,7 +5542,7 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "firstbit must be MSB" #~ msgstr "het eerste bit moet het MSB zijn" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "functie accepteert geen keyword argumenten" #~ msgid "function is implemented for scalars and ndarrays only" @@ -5436,7 +5620,7 @@ msgstr "zi moet vorm (n_section, 2) hebben" #~ msgid "n must be between 0, and 9" #~ msgstr "n moet tussen 0 en 9 liggen" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "naam hergebruikt voor argument" #~ msgid "no available NIC" diff --git a/locale/pl.po b/locale/pl.po index 5ea20a2b1d79a..2e55f983e0027 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,16 +7,16 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2023-11-16 15:03+0000\n" -"Last-Translator: Szymon Jakubiak \n" +"PO-Revision-Date: 2025-08-06 18:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: pl\n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 5.2\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -31,6 +31,8 @@ msgid "" "\n" "Code stopped by auto-reload. Reloading soon.\n" msgstr "" +"\n" +"Wykonywanie zatrzymane przez auto-reload. Wkrótce nastąpi przeładowanie.\n" #: supervisor/shared/safe_mode.c msgid "" @@ -38,6 +40,9 @@ msgid "" "Please file an issue with your program at github.com/adafruit/circuitpython/" "issues." msgstr "" +"\n" +"Proszę dodaj problem z twoim programem na github.com/adafruit/circuitpython/" +"issues." #: supervisor/shared/safe_mode.c msgid "" @@ -85,22 +90,24 @@ msgstr "%%c wymaga int lub char" msgid "" "%d address pins, %d rgb pins and %d tiles indicate a height of %d, not %d" msgstr "" +"%d pinów adresowalnych, %d pinów rgb oraz %d płytek wskazują na wysokość %d, " +"nie %d" #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q oraz %q zawierają zduplikowane piny" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q and %q muszą być różne" #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "%q and %q must share a clock unit" -msgstr "" +msgstr "%q i %q muszą współdzielić jednostkę zegara" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "%q cannot be changed once mode is set to %q" -msgstr "" +msgstr "%q nie może zostać zmienione po ustawieniu trybu %q" #: shared-bindings/microcontroller/Pin.c msgid "%q contains duplicate pins" @@ -110,7 +117,11 @@ msgstr "%q zawiera zduplikowane piny" msgid "%q failure: %d" msgstr "%q niepowodzenie: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q w %q musi być typu %q lub %q, nie %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q w %q musi być typu %q, a nie %q" @@ -156,19 +167,19 @@ msgstr "długość %q musi być w zakresie od %d do %d" #: py/argcheck.c msgid "%q length must be <= %d" -msgstr "" +msgstr "długość %q musi być <= %d" #: py/argcheck.c msgid "%q length must be >= %d" -msgstr "" +msgstr "długość %q musi być >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "" #: py/argcheck.c msgid "%q must be %d" -msgstr "" +msgstr "%q musi być %d" #: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/displayio/Bitmap.c @@ -176,16 +187,16 @@ msgstr "" #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c msgid "%q must be %d-%d" -msgstr "" +msgstr "%q musi być %d-%d" #: shared-bindings/busdisplay/BusDisplay.c msgid "%q must be 1 when %q is True" -msgstr "" +msgstr "%q musi wynosić 1, gdy %q jest True" #: py/argcheck.c shared-bindings/gifio/GifWriter.c #: shared-module/gifio/OnDiskGif.c msgid "%q must be <= %d" -msgstr "" +msgstr "%q musi być <= %d" #: ports/espressif/common-hal/watchdog/WatchDogTimer.c msgid "%q must be <= %u" @@ -193,7 +204,7 @@ msgstr "" #: py/argcheck.c msgid "%q must be >= %d" -msgstr "" +msgstr "%q musi być >= %d" #: shared-bindings/analogbufio/BufferedIn.c msgid "%q must be a bytearray or array of type 'H' or 'B'" @@ -222,6 +233,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -231,6 +243,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q musi być typu %q, a nie %q" @@ -276,7 +289,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q oraz %q muszą być tej samej długośći" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -310,7 +324,7 @@ msgid "'%q' object does not support '%q'" msgstr "Obiekt '%q' nie wspiera '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "Obiekt '%q' nie jest iteratorem" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -318,7 +332,7 @@ msgid "'%q' object is not callable" msgstr "Obiekt '%q' nie jest wywoływalny" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "Obiekt '%q' nie jest iterowalny" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -422,6 +436,10 @@ msgstr "'data' wymaga całkowitych argumentów" msgid "'label' requires 1 argument" msgstr "'label' wymaga 1 argumentu" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "'return' poza funkcją" @@ -541,7 +559,6 @@ msgstr "Wszystkie timery tej nóżki w użyciu" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Wszystkie timery w użyciu" @@ -554,6 +571,10 @@ msgstr "" msgid "Already have all-matches listener" msgstr "" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Już trwa" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -563,6 +584,7 @@ msgstr "Już uruchomiony" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "" @@ -589,6 +611,10 @@ msgstr "Tablica musi zawierać pół-słowa (typ 'H')" msgid "Array values should be single bytes." msgstr "Wartości powinny być bajtami." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -598,6 +624,11 @@ msgstr "Próba przydzielenia %d bloków" msgid "Audio conversion not implemented" msgstr "Konwersja audio nie została zaimplementowana" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "" @@ -667,13 +698,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Długość %d bufora jest za duża. Musi być mniejsza niż %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Długość bufora musi być wielokrotnością 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Bufor musi być wielokrotnością 512 bajtów" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -733,6 +764,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -780,7 +815,7 @@ msgid "Cannot record to a file" msgstr "Nie można nagrać do pliku" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." +msgid "Cannot remount path when visible via USB." msgstr "" #: shared-bindings/digitalio/DigitalInOut.c @@ -796,6 +831,10 @@ msgstr "Nie można określić RTS ani CTS w trybie RS485" msgid "Cannot subclass slice" msgstr "Nie można dziedziczyć ze slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -832,6 +871,10 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Nie można ustawić adresu" @@ -844,6 +887,11 @@ msgstr "Nie można rozpocząć przerwania, RX jest zajęty" msgid "Couldn't allocate decoder" msgstr "Nie udało się przydzielić dekodera" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Błąd inicjalizacji kanału DAC" @@ -861,10 +909,6 @@ msgstr "DAC w użyciu" msgid "Data 0 pin must be byte aligned" msgstr "Nóżka data 0 musi być wyrównana do bajtu" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Fragment danych musi następować po fragmencie fmt" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -997,15 +1041,47 @@ msgstr "Nie udało się połączyć: błąd wewnętrzny" msgid "Failed to connect: timeout" msgstr "Nie udało się połączyć: upłynął limit czasu" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Nie można przeanalizować pliku MP3" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Nie udało się zwolnić blokady, błąd 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Nie udało się zapisać wewnętrznej pamięci flash." @@ -1014,12 +1090,14 @@ msgstr "Nie udało się zapisać wewnętrznej pamięci flash." msgid "File exists" msgstr "Plik istnieje" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Plik nie znaleziony" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "" @@ -1048,7 +1126,7 @@ msgstr "" "W bitmapie wejściowej dla przestrzeni kolorów RGB piksel musi składać się z " "16 bitów" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Nie wspierany format" @@ -1158,6 +1236,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "" @@ -1203,15 +1282,19 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Nieprawidłowe %q" @@ -1244,6 +1327,10 @@ msgstr "" msgid "Invalid MAC address" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Zły argument" @@ -1275,6 +1362,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "" @@ -1287,6 +1375,7 @@ msgid "Invalid socket for TLS" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Nieprawidłowy stan" @@ -1327,9 +1416,15 @@ msgid "MAC address was invalid" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "" @@ -1375,7 +1470,8 @@ msgstr "" msgid "Mount point directory missing" msgstr "" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Musi być podklasą %q." @@ -1515,6 +1611,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Brak rozwijanego menu na pinezce; 1Mohm zalecane" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "Brak miejsca" @@ -1559,8 +1659,9 @@ msgid "Not supported JPEG standard" msgstr "" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1613,15 +1714,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Obsługiwane są tylko monochromatyczne, indeksowane 4 bpp lub 8 bpp oraz 16 " -"bpp lub więcej BMP: podano %d bpp" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1672,6 +1764,7 @@ msgstr "Brak pamięci" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1681,7 +1774,7 @@ msgstr "" #: ports/stm/common-hal/pwmio/PWMOut.c msgid "PWM restart" -msgstr "" +msgstr "Ponowne uruchomienie PWM" #: ports/raspberrypi/common-hal/countio/Counter.c msgid "PWM slice already in use" @@ -1691,9 +1784,13 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" -msgstr "" +msgstr "Błąd parametru" #: ports/espressif/common-hal/audiobusio/__init__.c msgid "Peripheral in use" @@ -1790,6 +1887,10 @@ msgstr "" #: ports/espressif/common-hal/espulp/ULP.c msgid "Program too long" +msgstr "Program zbyt długi" + +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" msgstr "" #: shared-bindings/digitalio/DigitalInOut.c @@ -1812,10 +1913,30 @@ msgstr "Błąd RNG DeInit" msgid "RNG Init Error" msgstr "Błąd inicjalizacji RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1847,7 +1968,7 @@ msgstr "Otrzymana odpowiedź była nieprawidłowa" #: supervisor/shared/bluetooth/bluetooth.c msgid "Reconnecting" -msgstr "" +msgstr "Ponowne połączenie" #: shared-bindings/epaperdisplay/EPaperDisplay.c msgid "Refresh too soon" @@ -1890,9 +2011,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1931,7 +2053,7 @@ msgstr "" #: ports/cxd56/common-hal/camera/Camera.c msgid "Size not supported" -msgstr "" +msgstr "Rozmiar nieobsługiwany" #: shared-bindings/alarm/SleepMemory.c shared-bindings/memorymap/AddressRange.c #: shared-bindings/nvm/ByteArray.c @@ -1942,11 +2064,13 @@ msgstr "Fragment i wartość są różnych długości." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Fragmenty nieobsługiwane" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "" @@ -1986,21 +2110,9 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Wartość bits_per_sample nie pasuje do miksera" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Liczba kanałów nie pasuje do miksera" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Sample rate nie pasuje do miksera" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Znak nie pasuje do miksera" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2020,7 +2132,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Wysokość bitmapy musi być wielokrotnością wysokości kafelka" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2028,6 +2142,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "Szerokość bitmapy musi być wielokrotnością szerokości kafelka" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2066,7 +2184,7 @@ msgstr "" #: ports/raspberrypi/common-hal/alarm/touch/TouchAlarm.c #: ports/stm/common-hal/alarm/touch/TouchAlarm.c msgid "Touch alarms not available" -msgstr "" +msgstr "Alarmy dotykowe niedostępne" #: py/obj.c msgid "Traceback (most recent call last):\n" @@ -2095,7 +2213,7 @@ msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2111,7 +2229,7 @@ msgstr "" #: shared-module/usb_hid/Device.c msgid "USB error" -msgstr "" +msgstr "Błąd USB" #: shared-bindings/_bleio/UUID.c msgid "UUID integer value must be 0-0xffff" @@ -2158,6 +2276,10 @@ msgstr "Błąd ustawienia parsera" msgid "Unable to read color palette data" msgstr "Nie można odczytać danych palety" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2173,7 +2295,7 @@ msgstr "" #: shared-bindings/alarm/SleepMemory.c msgid "Unable to write to sleep_memory." -msgstr "" +msgstr "Nie można zapisać do sleep_memory." #: ports/nordic/common-hal/_bleio/UUID.c msgid "Unexpected nrfx uuid type" @@ -2252,32 +2374,27 @@ msgstr "" msgid "Unsupported display bus type" msgstr "Zły typ magistrali wyświetlaczy" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Zły format" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Aktualizacja nie powiodła się" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Długość wartości ! = Wymagana stała długość" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2308,14 +2425,21 @@ msgid "" "\n" "To list built-in modules type `help(\"modules\")`.\n" msgstr "" +"Witamy w Adafruit CircuitPython %s!\n" +"\n" +"Odwiedź circuitpython.org po więcej informacji.\n" +"\n" +"Aby wyświetlić listę wbudowanych modułów wpisz `help(„modules”)`.\n" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi nie jest włączone" #: main.c msgid "Woken up by alarm.\n" @@ -2337,6 +2461,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2350,6 +2475,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2410,6 +2536,10 @@ msgstr "wymagany obiekt typu bytes" msgid "addresses is empty" msgstr "adres jest pusty" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2434,6 +2564,10 @@ msgstr "Argument argsort musi być typu ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2484,6 +2618,10 @@ msgstr "próba uzyskania argmin / argmax pustej sekwencji" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2520,6 +2658,10 @@ msgstr "zły typecode" msgid "binary op %q not implemented" msgstr "brak dwu-argumentowego operatora %q" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth musi wynosić 8, 16, 24 lub 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2530,8 +2672,17 @@ msgstr "" #: extmod/modrandom.c msgid "bits must be 32 or less" -msgstr "" +msgstr "bitów musi wynosić 32 lub mniej" + +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample musi wynosić 16" +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample musi być 8 lub 16" @@ -2613,7 +2764,7 @@ msgstr "przypisanie do wyrażenia" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "nie można dokonać konwersji %q na %q" @@ -2668,6 +2819,10 @@ msgstr "nie można usunąć wyrażenia" msgid "can't do binary op between '%q' and '%q'" msgstr "nie można użyć operatora pomiędzy '%q' a '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "nie można automatyczne skonwertować '%q' do 'bool'" @@ -2730,13 +2885,9 @@ msgstr "nie można zmienić z ręcznego numerowaniu pól do automatycznego" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" -msgstr "" +msgstr "nie mogę się doczekać" #: extmod/ulab/code/ndarray.c msgid "cannot assign new shape" @@ -2923,7 +3074,7 @@ msgstr "" #: extmod/ulab/code/numpy/create.c msgid "divide by zero" -msgstr "" +msgstr "dziel przez zero" #: py/runtime.c msgid "division by zero" @@ -2943,7 +3094,7 @@ msgstr "puste" #: extmod/ulab/code/numpy/io/io.c msgid "empty file" -msgstr "" +msgstr "puste plik" #: extmod/modasyncio.c extmod/modheapq.c msgid "empty heap" @@ -3062,7 +3213,7 @@ msgstr "float zbyt wielki" #: py/nativeglue.c msgid "float unsupported" -msgstr "" +msgstr "float nieobsługiwany" #: shared-bindings/_stage/Text.c msgid "font must be 2048 bytes long" @@ -3070,10 +3221,10 @@ msgstr "font musi mieć 2048 bajtów długości" #: extmod/moddeflate.c msgid "format" -msgstr "" +msgstr "format" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "format wymaga słownika" #: py/objdeque.c @@ -3123,7 +3274,8 @@ msgstr "brak wymaganego argumentu nazwanego '%q' funkcji" msgid "function missing required positional argument #%d" msgstr "brak wymaganego argumentu pozycyjnego #%d funkcji" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "funkcja wymaga %d argumentów pozycyjnych, ale jest %d" @@ -3170,7 +3322,7 @@ msgstr "" #: py/persistentcode.c msgid "incompatible .mpy file" -msgstr "" +msgstr "niekompatybilny plik .mpy" #: py/objstr.c msgid "incomplete format" @@ -3207,10 +3359,6 @@ msgid "indices must be integers, slices, or Boolean lists" msgstr "" "indeksy muszą być liczbami całkowitymi, wycinkami lub listami boolowskimi" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "wartości początkowe muszą być iterowalne" @@ -3276,7 +3424,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3405,10 +3553,6 @@ msgstr "etykieta '%q' niezdefiniowana" msgid "label redefined" msgstr "etykieta przedefiniowana" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "poziom musi wynosić od 0 do 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lewa i prawa strona powinny być kompatybilne" @@ -3462,7 +3606,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "maksymalna długość musi wynosić 0-%d, gdy stała długość wynosi %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3540,7 +3684,7 @@ msgid "must use keyword argument for key function" msgstr "funkcja key musi być podana jako argument nazwany" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "nazwa '%q' niezdefiniowana" #: py/runtime.c @@ -3590,7 +3734,7 @@ msgstr "" #: shared-module/sdcardio/SDCard.c msgid "no SD card" -msgstr "" +msgstr "brak karty SD" #: py/vm.c msgid "no active exception to reraise" @@ -3604,7 +3748,7 @@ msgstr "brak wiązania dla zmiennej nielokalnej" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3671,7 +3815,7 @@ msgstr "liczba punktów musi wynosić co najmniej 2" #: py/builtinhelp.c msgid "object " -msgstr "" +msgstr "obiekt " #: py/obj.c #, c-format @@ -3725,7 +3869,7 @@ msgstr "łańcuch o nieparzystej długości" #: supervisor/shared/web_workflow/web_workflow.c msgid "off" -msgstr "" +msgstr "wył" #: extmod/ulab/code/utils/utils.c msgid "offset is too large" @@ -3813,6 +3957,10 @@ msgstr "ord() oczekuje znaku, a jest łańcuch od długości %d" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3837,6 +3985,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "przepełnienie przy konwersji long in to słowa maszynowego" @@ -3946,6 +4102,10 @@ msgstr "" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3963,6 +4123,10 @@ msgstr "kompilowanie skryptów nieobsługiwane" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3983,6 +4147,10 @@ msgstr "znak jest niedopuszczalny w specyfikacji 'c'" msgid "size is defined for ndarrays only" msgstr "rozmiar jest zdefiniowany tylko dla ndarrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4056,18 +4224,6 @@ msgstr "indeks łańcucha poza zakresem" msgid "string indices must be integers, not %s" msgstr "indeksy łańcucha muszą być całkowite, nie %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: indeks poza zakresem" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: brak pól" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "brak pod-łańcucha" @@ -4080,10 +4236,6 @@ msgstr "super() nie może znaleźć self" msgid "syntax error in JSON" msgstr "błąd składni w JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "błąd składni w deskryptorze uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4173,11 +4325,11 @@ msgid "tx and rx cannot both be None" msgstr "tx i rx nie mogą być oba None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "typ '%q' nie może być bazowy" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "typ nie może być bazowy" #: py/runtime.c @@ -4192,10 +4344,6 @@ msgstr "type wymaga 1 lub 3 argumentów" msgid "ulonglong too large" msgstr "ulonglong zbyt wielkie" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "operator unarny %q niezaimplementowany" - #: py/parse.c msgid "unexpected indent" msgstr "złe wcięcie" @@ -4243,7 +4391,9 @@ msgstr "" msgid "unreadable attribute" msgstr "nieczytelny atrybut" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "zły typ %q" @@ -4321,11 +4471,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "szerokość musi być większa niż zero" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4388,6 +4533,53 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#~ msgid "Unsupported format" +#~ msgstr "Zły format" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Fragment danych musi następować po fragmencie fmt" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Obsługiwane są tylko monochromatyczne, indeksowane 4 bpp lub 8 bpp oraz " +#~ "16 bpp lub więcej BMP: podano %d bpp" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "poziom musi wynosić od 0 do 1" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Wartość bits_per_sample nie pasuje do miksera" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Liczba kanałów nie pasuje do miksera" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Sample rate nie pasuje do miksera" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Znak nie pasuje do miksera" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Długość bufora musi być wielokrotnością 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Bufor musi być wielokrotnością 512 bajtów" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: indeks poza zakresem" + +#~ msgid "struct: no fields" +#~ msgstr "struct: brak pól" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "błąd składni w deskryptorze uctypes" + +#~ msgid "unary op %q not implemented" +#~ msgstr "operator unarny %q niezaimplementowany" + #~ msgid "Name too long" #~ msgstr "Za długa nazwa" @@ -4541,13 +4733,13 @@ msgstr "" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' obiekt nie wspiera usuwania elementów" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' obiekt nie jest iteratorem" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' nie można wywoływać obiektu" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' nie można iterować po obiekcie" #~ msgid "'%s' object is not subscriptable" @@ -5311,7 +5503,7 @@ msgstr "" #~ msgid "firstbit must be MSB" #~ msgstr "firstbit musi być MSB" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "funkcja nie bierze argumentów nazwanych" #~ msgid "int() arg 2 must be >= 2 and <= 36" @@ -5359,7 +5551,7 @@ msgstr "" #~ msgid "name must be a string" #~ msgstr "nazwa musi być łańcuchem" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "nazwa użyta ponownie jako argument" #~ msgid "no available NIC" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index 464292943430c..5bb98dc74c51f 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -6,15 +6,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2024-08-23 07:09+0000\n" -"Last-Translator: Wellington Terumi Uemura \n" +"PO-Revision-Date: 2025-06-09 12:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: \n" "Language: pt_BR\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 5.7.1-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: main.c msgid "" @@ -95,7 +95,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q e %q contêm pinos duplicados" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q e %q devem ser diferentes" @@ -115,7 +115,11 @@ msgstr "%q contém pinos duplicados" msgid "%q failure: %d" msgstr "%q falha: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q em %q deve ser do tipo %q ou %q, não %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q em %q deve ser do tipo %q e não %q" @@ -167,7 +171,7 @@ msgstr "o comprimento de %q deve ser <= %d" msgid "%q length must be >= %d" msgstr "o comprimento de %q deve ser >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q foi movido de %q para %q" @@ -227,6 +231,7 @@ msgstr "%q deve ser um múltiplo de 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q deve ser do tipo %q ou %q e não %q" @@ -236,6 +241,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q deve ser do tipo %q, %q ou %q e não %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q deve ser do tipo %q e não %q" @@ -281,7 +287,8 @@ msgstr "%q() sem %q()" msgid "%q, %q, and %q must all be the same length" msgstr "todos os %q, %q, e %q devem ter mesmo comprimento" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -315,7 +322,7 @@ msgid "'%q' object does not support '%q'" msgstr "O objeto '%q' não suporta '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "O objeto '%q' não é um iterador" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -323,7 +330,7 @@ msgid "'%q' object is not callable" msgstr "O objeto '%s' não é invocável" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "O objeto '%q' não é iterável" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -429,6 +436,10 @@ msgstr "'data' exige argumentos inteiros" msgid "'label' requires 1 argument" msgstr "'label' exige 1 argumento" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' não implementado" + #: py/compile.c msgid "'return' outside function" msgstr "função externa 'return'" @@ -548,7 +559,6 @@ msgstr "Todos os temporizadores para este pino estão em uso" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Todos os temporizadores em uso" @@ -561,6 +571,10 @@ msgstr "Já está anunciando." msgid "Already have all-matches listener" msgstr "Já há um ouvinte com todas as correspondências" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Já em andamento" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,6 +584,7 @@ msgstr "Já está em execução" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Já está em busca das redes de wifi" @@ -596,6 +611,12 @@ msgstr "Array deve conter meias palavras (tipo 'H')" msgid "Array values should be single bytes." msgstr "Os valores das matrizes devem ser bytes simples." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" +"Transferência SPI assíncrona em andamento nesse barramento, continue " +"aguardando." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +626,11 @@ msgstr "Tentativa de alocar %d blocos" msgid "Audio conversion not implemented" msgstr "A conversão de áudio ainda não foi implementada" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Erro na fonte de áudio" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "O AuthMode.OPEN não é usado com senha" @@ -674,13 +700,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "O tamanho do buffer %d é muito grande. Deve ser menor que %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "O comprimento do Buffer deve ser um múltiplo de 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "O buffer deve ser um múltiplo de 512 bytes" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "O buffer deve ser um múltiplo de %d bytes" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -741,6 +767,11 @@ msgid "Can only alarm on two low pins from deep sleep." msgstr "" "O alarme só é possível nos dois pinos com sinal baixo a partir do deep sleep." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" +"Não é possível construir o AudioOut porque o canal contínuo já está aberto" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -788,8 +819,8 @@ msgid "Cannot record to a file" msgstr "Não é possível gravar em um arquivo" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Não é possível montar '/' quando estiver visível pelo USB." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -804,6 +835,10 @@ msgstr "Não é possível definir o RTS ou CTS no modo RS485" msgid "Cannot subclass slice" msgstr "Não é possível subclassificar a fatia" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "Não é possível usar GPIO0..15 junto com GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Não é possível acordar na borda do pino, nível apenas" @@ -839,6 +874,10 @@ msgstr "As coordenadas das matrizes possuem comprimentos diferentes" msgid "Coordinate arrays types have different sizes" msgstr "Os tipos das coordenadas das matrizes possuem tamanhos diferentes" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Não foi possível definir o endereço" @@ -851,6 +890,11 @@ msgstr "Não foi possível iniciar a interrupção, RX ocupado" msgid "Couldn't allocate decoder" msgstr "Não foi possível alocar o decodificador" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Erro de Inicialização do Canal DAC" @@ -868,10 +912,6 @@ msgstr "DAC em uso" msgid "Data 0 pin must be byte aligned" msgstr "O pino de dados 0 deve ser alinhado por bytes" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Pedaço de dados deve seguir o pedaço de cortes" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "Erro no formato dos dados (os dados podem estar truncados)" @@ -1005,15 +1045,47 @@ msgstr "Falha ao conectar: erro interno" msgid "Failed to connect: timeout" msgstr "Falha ao conectar: tempo limite" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Houve uma falha ao criar canais contínuos: arg inválido" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Houve uma falha ao criar canais contínuos: estado inválido" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Houve uma falha ao criar canais contínuos: sem mem" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Houve uma falha ao criar canais contínuos: não encontrado" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Houve uma falha ao ativar o modo contínuo" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Falha ao analisar o arquivo MP3" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Houve uma falha ao registrar a chamada de retorno de eventos contínuos" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Houve uma falha ao liberar o mutex, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Houve uma falha ao definir o nome do host" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Houve uma falha ao iniciar o áudio assíncrono" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Falha ao gravar o flash interno." @@ -1022,12 +1094,14 @@ msgstr "Falha ao gravar o flash interno." msgid "File exists" msgstr "Arquivo já existe" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Arquivo não encontrado" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Os filtros são muito complexos" @@ -1053,7 +1127,7 @@ msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" "Para espaços de cor RGB, o bitmap da entrada deve ter 16 bits por pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "O formato não é suportado" @@ -1169,6 +1243,7 @@ msgid "Insufficient stream input buffer" msgstr "O buffer do fluxo de entrada é insuficiente" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "A interface deve ser iniciada" @@ -1214,15 +1289,19 @@ msgstr "Erro de interrupção." msgid "Interrupted by output function" msgstr "Interrompido pela função de saída" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "%q Inválido" @@ -1255,6 +1334,10 @@ msgstr "BSSID Inválido" msgid "Invalid MAC address" msgstr "Endereço MAC inválido" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Argumento inválido" @@ -1286,6 +1369,7 @@ msgid "Invalid hex password" msgstr "Senha hexadecimal inválida" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Endereço MAC multicast inválido" @@ -1298,6 +1382,7 @@ msgid "Invalid socket for TLS" msgstr "Soquete inválido para o TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Estado inválido" @@ -1339,9 +1424,15 @@ msgid "MAC address was invalid" msgstr "O endereço MAC era inválido" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "Não há suporte para segurança MITM" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "Erro de relógio MMC/SDIO %x" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "O mapeamento deve ser uma tupla" @@ -1387,7 +1478,8 @@ msgstr "Falta jmp_pin. %q[%u] jumper no pino" msgid "Mount point directory missing" msgstr "Falta o diretório do ponto de montagem" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Deve ser uma subclasse %q." @@ -1529,6 +1621,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Não há pulldown no pino; É recomendável utilizar um resistor de 1M ohm" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "Não resta espaço no dispositivo" @@ -1573,9 +1669,10 @@ msgid "Not supported JPEG standard" msgstr "Não é compatível com o padrão JPEG" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "A quantidade dos data_pins deve ser 8 ou 16, não %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "A quantidade de data_pins deve ser %d ou %d, e não %d" #: shared-bindings/util.c msgid "" @@ -1631,15 +1728,6 @@ msgstr "Apenas a detecção de borda está disponível neste hardware" msgid "Only int or string supported for ip" msgstr "Apenas int ou string é suportado para ip" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"São compatíveis apenas os BMPs monocromáticos, indexados em 4bpp ou 8bpp e " -"16bpp ou superior: determinado %d bpp" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Apenas um %q pode ser colocado em hibernação profunda." @@ -1690,6 +1778,7 @@ msgstr "Sem memória" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Sem soquetes" @@ -1709,6 +1798,12 @@ msgstr "A fatia do PWM já está em uso" msgid "PWM slice channel A already in use" msgstr "O canal A da fatia do PWM já está em uso" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" +"Os buffers de pacotes para uma transferência SPI devem ter o mesmo " +"comprimento." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "Erro de parâmetro" @@ -1815,6 +1910,10 @@ msgstr "O tamanho do programa é inválido" msgid "Program too long" msgstr "Programa muito longo" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "O Pull não foi usado quando a direção for gerada." @@ -1835,6 +1934,26 @@ msgstr "Erro DeInit RNG" msgid "RNG Init Error" msgstr "Houve um erro na inicialização do RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1913,10 +2032,11 @@ msgstr "Inicialização do cartão SD" msgid "SDIO GetCardInfo Error %d" msgstr "Erro SDIO GetCardInfo %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "Erro SDIO Init %d" +msgid "SDIO Init Error %x" +msgstr "Erro de inicialização %x do SDIO" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1965,11 +2085,13 @@ msgstr "Fatie e avalie os diferentes comprimentos." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Fatiamento não compatível" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "O SocketPool só pode ser usado com rádio wifi.radio" @@ -2010,21 +2132,9 @@ msgstr "A exceção acima foi a causa direta da seguinte exceção:" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "O comprimento dos rgb_pins devem ser 6, 12, 18, 24, ou 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "A amostragem bits_per_sample não coincide com a do mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "A contagem da amostragem dos canais não coincide com o a do mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "A taxa de amostragem da amostra não coincide com a do mixer" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "A amostragem \"signedness\" não coincide com a do mixer" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "Não há correspondência nas amostras %q" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2046,7 +2156,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "A altura do bloco deve dividir exatamente com a altura do bitmap" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "O índice do bloco está fora dos limites" @@ -2054,6 +2166,10 @@ msgstr "O índice do bloco está fora dos limites" msgid "Tile width must exactly divide bitmap width" msgstr "A largura do bloco deve dividir exatamente com a largura do bitmap" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "O tempo está no passado." @@ -2189,6 +2305,12 @@ msgstr "Não foi possível iniciar o analisador" msgid "Unable to read color palette data" msgstr "Não foi possível ler os dados da paleta de cores" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" +"Não é possível enviar uma mensagem CAN: todos os buffers de mensagens Tx " +"estão ocupados" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2283,15 +2405,12 @@ msgstr "Espaço de cor não compatível" msgid "Unsupported display bus type" msgstr "Não há suporte para o tipo do display bus" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Formato não suportado" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Sem compatibilidade com o algoritmo de hash" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "Tipo de soquete não suportado" @@ -2301,14 +2420,12 @@ msgid "Update failed" msgstr "A atualização falhou" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Comprimento do valor != comprimento fixo necessário" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2351,9 +2468,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "O Wi-Fi não está ativado" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "O WiFi não está habilitado" #: main.c msgid "Woken up by alarm.\n" @@ -2375,6 +2494,7 @@ msgstr "Você pressionou os dois botões durante a inicialização." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Você pressionou o botão A na inicialização." @@ -2388,6 +2508,7 @@ msgstr "Você pressionou o botão BOOT na inicialização" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "Você pressionou o botão BOOT ao iniciar." @@ -2448,6 +2569,10 @@ msgstr "é necessário objetos tipo bytes" msgid "addresses is empty" msgstr "os endereços estão vazios" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "já está tocando" + #: py/compile.c msgid "annotation must be an identifier" msgstr "a anotação deve ser um identificador" @@ -2472,6 +2597,11 @@ msgstr "O argumento argsort deve ser um ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort não é implementado para matrizes achatadas" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" +"O argumento deve ser None, um número inteiro ou uma tupla de números inteiros" + #: py/compile.c msgid "argument name reused" msgstr "nome do argumento reutilizado" @@ -2522,6 +2652,10 @@ msgstr "tente obter argmin/argmax de uma sequência vazia" msgid "attributes not supported" msgstr "atributos não compatíveis" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "formato de áudio não compatível" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "o eixo está fora dos limites" @@ -2558,6 +2692,10 @@ msgstr "typecode incorreto" msgid "binary op %q not implemented" msgstr "a operação binário %q não foi implementada" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "o bit_depth deve ser 8, 16, 24 ou 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "o tamanho e a profundidade do bitmap devem corresponder" @@ -2570,6 +2708,15 @@ msgstr "os tamanhos do bitmap devem coincidir" msgid "bits must be 32 or less" msgstr "bits deve ser 32 ou menos" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample deve ser 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample deve ser 8 ou 16" @@ -2651,7 +2798,7 @@ msgstr "a expressão não pode ser atribuída" msgid "can't cancel self" msgstr "não é possível cancelar a si mesmo" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "não é possível converter %q para %q" @@ -2706,6 +2853,10 @@ msgstr "não é possível excluir a expressão" msgid "can't do binary op between '%q' and '%q'" msgstr "não é possível executar uma operação binária entre '%q' e '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "não é possível fazer uma operação unária de '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "não é possível converter implicitamente '%q' em 'bool'" @@ -2772,10 +2923,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "não é possível truncar-dividir um número complexo" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "não é possível obter de forma inequívoca o tamanho do escalar" - #: extmod/modasyncio.c msgid "can't wait" msgstr "não vejo a hora" @@ -3119,7 +3266,7 @@ msgid "format" msgstr "formato" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "formato requer um dict" #: py/objdeque.c @@ -3169,7 +3316,8 @@ msgstr "falta apenas a palavra chave do argumento '%q' da função" msgid "function missing required positional argument #%d" msgstr "falta o argumento #%d da posição necessária da função" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "função leva %d argumentos posicionais, mas apenas %d foram passadas" @@ -3252,10 +3400,6 @@ msgstr "os índices devem ser inteiros" msgid "indices must be integers, slices, or Boolean lists" msgstr "os índices devem ser números inteiros, fatias ou listas booleanas" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "inicialização do I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "os valores iniciais devem ser iteráveis" @@ -3322,7 +3466,7 @@ msgstr "a entrada deve ser um 1D ndarray" msgid "input must be a dense ndarray" msgstr "a entrada deve ser um ndarray denso" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "a entrada deve ser um ndarray" @@ -3454,10 +3598,6 @@ msgstr "o rótulo '%q' não foi definido" msgid "label redefined" msgstr "o rótulo foi redefinido" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "o nível deve estar entre 0 e 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "o lhs e rhs devem ser compatíveis" @@ -3511,7 +3651,7 @@ msgstr "a matriz não é definitiva positiva" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "o max_length deve ser 0-%d quando Fixed_length for %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "a quantidade máxima de dimensões é " @@ -3591,7 +3731,7 @@ msgid "must use keyword argument for key function" msgstr "deve usar o argumento da palavra-chave para a função da chave" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "o nome '%q' não está definido" #: py/runtime.c @@ -3655,7 +3795,7 @@ msgstr "nenhuma ligação para nonlocal foi encontrada" msgid "no default packer" msgstr "nenhum empacotador padrão" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "nenhuma semente padrão" @@ -3867,6 +4007,10 @@ msgstr "" msgid "out array is too small" msgstr "a matriz externa é muito pequena" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "o out tem o tipo errado" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "a palavra-chave out não é compatível para o dtype complexo" @@ -3891,6 +4035,14 @@ msgstr "out deve ser do tipo float dtype" msgid "out of range of target" msgstr "fora do alcance do alvo" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "a matriz de saída tem o tipo errado" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "a matriz de saída deve ser contígua" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -4002,6 +4154,10 @@ msgstr "argumento de enrolar deve ser um ndarray" msgid "rsplit(None,n)" msgstr "rsplit(Nenhum,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed deve ser verdadeiro" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4019,6 +4175,11 @@ msgstr "compilação de script não suportada" msgid "set unsupported" msgstr "conjunto não suportado" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" +"shape deve ser None, um número inteiro ou uma tupla de números inteiros" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "a forma deve ser inteira ou tupla de inteiros" @@ -4039,6 +4200,10 @@ msgstr "sinal não permitido com o especificador no formato inteiro 'c'" msgid "size is defined for ndarrays only" msgstr "o tamanho é definido apenas para os ndarrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "O tamanho deve corresponder ao out.shape quando usado em conjunto" + #: py/nativeglue.c msgid "slice unsupported" msgstr "fatia não suportada" @@ -4112,18 +4277,6 @@ msgstr "o índice da string está fora do intervalo" msgid "string indices must be integers, not %s" msgstr "o índices das string devem ser números inteiros, não %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct: não é possível indexar" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: índice fora do intervalo" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: sem campos" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "a substring não foi encontrada" @@ -4136,10 +4289,6 @@ msgstr "o super() não consegue se encontrar" msgid "syntax error in JSON" msgstr "erro de sintaxe no JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "houve um erro de sintaxe no descritor uctypes" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "estouro do intervalo de ticks" @@ -4229,11 +4378,11 @@ msgid "tx and rx cannot both be None" msgstr "TX e RX não podem ser ambos" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "o tipo '%q' não é um tipo base aceitável" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "tipo não é um tipo base aceitável" #: py/runtime.c @@ -4248,10 +4397,6 @@ msgstr "o tipo usa 1 ou 3 argumentos" msgid "ulonglong too large" msgstr "ulonglong é muito grande" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "op %q unário não foi implementado" - #: py/parse.c msgid "unexpected indent" msgstr "recuo inesperado" @@ -4299,7 +4444,9 @@ msgstr "'%c' sem correspondência no formato" msgid "unreadable attribute" msgstr "atributo ilegível" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "tipo %q não suportado" @@ -4379,11 +4526,6 @@ msgstr "os pesos devem ser um objeto do tipo %q, %q, %q ou %q, e não %q " msgid "width must be greater than zero" msgstr "a largura deve ser maior que zero" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "o wifi não está ativo" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "O wifi.Monitor não está disponível" @@ -4446,6 +4588,82 @@ msgstr "zi deve ser de um tipo float" msgid "zi must be of shape (n_section, 2)" msgstr "zi deve estar na forma (n_section, 2)" +#~ msgid "Unsupported format" +#~ msgstr "Formato não suportado" + +#~ msgid "Wifi is not enabled" +#~ msgstr "O Wi-Fi não está ativado" + +#~ msgid "wifi is not enabled" +#~ msgstr "o wifi não está ativo" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Não é possível montar '/' quando estiver visível pelo USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q deve ser um objeto %q, %q ou %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Pedaço de dados deve seguir o pedaço de cortes" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "São compatíveis apenas os BMPs monocromáticos, indexados em 4bpp ou 8bpp " +#~ "e 16bpp ou superior: determinado %d bpp" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "o nível deve estar entre 0 e 1" + +#~ msgid "init I2C" +#~ msgstr "inicialização do I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "A amostragem bits_per_sample não coincide com a do mixer" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "A contagem da amostragem dos canais não coincide com o a do mixer" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "A taxa de amostragem da amostra não coincide com a do mixer" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "A amostragem \"signedness\" não coincide com a do mixer" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "O comprimento do Buffer deve ser um múltiplo de 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "O buffer deve ser um múltiplo de 512 bytes" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "A quantidade dos data_pins deve ser 8 ou 16, não %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "Erro SDIO Init %d" + +#~ msgid "can't unambiguously get sizeof scalar" +#~ msgstr "não é possível obter de forma inequívoca o tamanho do escalar" + +#~ msgid "struct: can't index" +#~ msgstr "struct: não é possível indexar" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: índice fora do intervalo" + +#~ msgid "struct: no fields" +#~ msgstr "struct: sem campos" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "houve um erro de sintaxe no descritor uctypes" + +#~ msgid "unary op %q not implemented" +#~ msgstr "op %q unário não foi implementado" + #~ msgid "Name too long" #~ msgstr "Nome muito longo" @@ -4759,13 +4977,13 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "O objeto '%s' não é compatível com exclusão do item" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "O objeto '%s' não é um iterador" #~ msgid "'%s' object is not callable" #~ msgstr "O objeto '%s' não é invocável" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "O objeto '%s' não é iterável" #~ msgid "'%s' object is not subscriptable" @@ -4785,7 +5003,7 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' fora do loop" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "O objeto 'corrotina' não é um iterador" #~ msgid "(x,y) integers required" @@ -6142,7 +6360,7 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "frequency is read-only for this board" #~ msgstr "nesta placa, a frequência é de apenas leitura" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "função não aceita argumentos de palavras-chave" #~ msgid "function is implemented for scalars and ndarrays only" @@ -6271,7 +6489,7 @@ msgstr "zi deve estar na forma (n_section, 2)" #~ msgid "name must be a string" #~ msgstr "heap deve ser uma lista" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "o nome foi reutilizado para o argumento" #~ msgid "no available NIC" diff --git a/locale/ru.po b/locale/ru.po index 4c1a468c61da4..0f7c6c0944b2f 100644 --- a/locale/ru.po +++ b/locale/ru.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-07-29 17:55+0000\n" -"Last-Translator: gfbdrgng \n" +"PO-Revision-Date: 2025-06-30 16:01+0000\n" +"Last-Translator: MAE \n" "Language-Team: none\n" "Language: ru\n" "MIME-Version: 1.0\n" @@ -16,7 +16,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Weblate 5.7-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -82,8 +82,8 @@ msgstr " вывод:\n" #: py/objstr.c #, c-format -msgid "%%c requires int or char" -msgstr "%%c требует int или char" +msgid "%%c needs int or char" +msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -93,11 +93,16 @@ msgstr "" "Адресные контакты %d, контакты rgb %d и плитки %d обозначают высоту %d, а не " "%d" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q и %q содержат пины дупликаты" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q и %q должны быть разными" @@ -114,14 +119,21 @@ msgid "%q contains duplicate pins" msgstr "%q содержит пины дупликаты" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q сбой: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q в %q должно быть типа %q, а не %q" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -129,7 +141,8 @@ msgstr "%q в %q должно быть типа %q, а не %q" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "%q используется" @@ -141,7 +154,9 @@ msgstr "Индекс %q вне диапазона" msgid "%q indices must be integers, not %s" msgstr "Индексы %q должны быть целыми числами, а не %s" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "Инициализация %q не удалась" @@ -169,16 +184,12 @@ msgstr "Длинна %q должна быть <= %d" msgid "%q length must be >= %d" msgstr "Длинна %q должна быть >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "%q переместился из %q в %q" - #: py/argcheck.c msgid "%q must be %d" msgstr "%q должно быть %d" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -229,6 +240,7 @@ msgstr "%q должно быть кратно 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q должно быть типа%q или%q, а не%q" @@ -238,6 +250,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q должен иметь тип %q, %q или %q, а не %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q должно быть типа %q, а не %q" @@ -246,23 +259,29 @@ msgstr "%q должно быть типа %q, а не %q" msgid "%q must be power of 2" msgstr "%q должен быть во 2-й степени" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "%q за пределом" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "%q вне диапазона" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "%q переименован %q" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "Шаг %q не может быть нулём" @@ -283,7 +302,8 @@ msgstr "%q() без %q()" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, и %q должны быть одной длинны" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -312,20 +332,20 @@ msgstr "%s ошибка 0x%x" msgid "'%q' argument required" msgstr "Требуется аргумент '%q'" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "Объект '%q' не поддерживает '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "Объект '%q' не является итератором" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" -msgstr "Объект '%q' не является вызываемым" +msgid "'%q' object isn't callable" +msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "Объект '%q' не является итерируемым" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -429,6 +449,10 @@ msgstr "«данные» требуют целочисленных аргуме msgid "'label' requires 1 argument" msgstr "«метка» требует 1 аргумент" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'не' не реализовано" + #: py/compile.c msgid "'return' outside function" msgstr "«возврат» внешняя функция" @@ -453,6 +477,7 @@ msgstr "*x должно быть целью назначения" msgid ", in %q\n" msgstr ", в %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -471,7 +496,7 @@ msgstr "Pow() с 3 аргументами не поддерживается" msgid "AP could not be started" msgstr "AP не может быть запущен" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Адрес должен быть длиной %d байт" @@ -506,7 +531,8 @@ msgstr "Все RX FIFO уже используются" msgid "All SPI peripherals are in use" msgstr "Все периферийные устройства SPI уже используются" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Все периферийные устройства UART уже используются" @@ -548,7 +574,6 @@ msgstr "Все таймеры для этого пина уже использу #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Все таймеры уже используются" @@ -561,6 +586,10 @@ msgstr "Уже реклама." msgid "Already have all-matches listener" msgstr "Уже есть универсальный слушатель" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Уже в процессе" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,10 +599,11 @@ msgstr "Уже запущен" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Поиск сетей wifi уже происходит" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "Произошла ошибка при получении '%s':\n" @@ -596,6 +626,10 @@ msgstr "Массив должен содержать полуслова (тип msgid "Array values should be single bytes." msgstr "Значения массива должны быть однобайтовыми." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +639,12 @@ msgstr "Попытка выделения %d блоков" msgid "Audio conversion not implemented" msgstr "Преобразование звука не реализовано" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "Режим авторизации.OPEN не используется с паролем" @@ -629,6 +669,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Скорость передачи данных не поддерживается периферийным устройством" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -647,20 +688,17 @@ msgstr "" msgid "Boot device must be first (interface #0)." msgstr "Загрузочное устройство должно быть первым (интерфейс #0)." +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Для управления потоком требуется как RX так и TX" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Яркость не регулируется" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Буфер + сдвиг слишком малы %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Элементы буфера должны иметь длину не более 4 байт" @@ -675,13 +713,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Размер буфера %d слишком большой. Он должен быть меньше чем %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Размер буфера должен быть кратен 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Буфер должен быть кратен 512" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Буфер должен быть кратен %d байт" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -703,10 +741,6 @@ msgstr "Слишком маленький буфер" msgid "Bus pin %d is already in use" msgstr "Вывод шины %d уже используется" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Буфер байтов должен быть размером 16 байтам." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "Блоки CBC должны быть кратны 16 байтам" @@ -742,6 +776,10 @@ msgid "Can only alarm on two low pins from deep sleep." msgstr "" "Из глубокого сна может сигнализировать только по двум низким контактам." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -757,6 +795,10 @@ msgstr "Невозможно изменить USB устройство сейч msgid "Cannot create a new Adapter; use _bleio.adapter;" msgstr "Невозможно создать новый Adapter; используйте _bleio.adapter;" +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" + #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c @@ -789,10 +831,11 @@ msgid "Cannot record to a file" msgstr "Невозможно записать в файл" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Невозможно перемонтировать '/' пока он виден через USB." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "Невозможно установить значение при вводе направления." @@ -805,6 +848,10 @@ msgstr "Невозможно указать RTS или CTS в режиме RS485 msgid "Cannot subclass slice" msgstr "Невозможно создать подкласс среза" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "Невозможно использовать GPIO0..15 вместе с GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -842,6 +889,14 @@ msgstr "Координатные массивы имеют разные длин msgid "Coordinate arrays types have different sizes" msgstr "Типы массивов координат имеют разные размеры" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Не удалось задать адрес" @@ -854,6 +909,11 @@ msgstr "Не удалось запустить прерывание, RX заня msgid "Couldn't allocate decoder" msgstr "Не удалось выделить место для декодера" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Ошибка инициализации канала DAC" @@ -871,10 +931,6 @@ msgstr "DAC уже используется" msgid "Data 0 pin must be byte aligned" msgstr "Пин data 0 должен быть байтово выровнен" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Блок данных должен следовать за блоком fmt" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "Ошибка формата данных (возможно, данные повреждены)" @@ -915,6 +971,7 @@ msgstr "Дисплей должен иметь 16 битное цветовое #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "Поворот дисплея должен осуществляться с шагом 90 градусов" @@ -923,6 +980,7 @@ msgid "Done" msgstr "Выполнено" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "Режим движения не используется при вводе направления." @@ -935,8 +993,17 @@ msgstr "" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB работает только с 16 байтами за раз" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "Ошибка выделения памяти ESP-IDF" @@ -985,7 +1052,7 @@ msgstr "" "Не удалось добавить служебную TXT-запись; в txt_records обнаружена нестрока " "или байт" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "Не удалось выделить буфер %q" @@ -1003,22 +1070,60 @@ msgstr "Не удалось выполнить буферизацию образ #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Не удалось подключиться: внутренняя ошибка" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Не удалось подключиться: таймаут" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Не удалось распарсить файл MP3" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Не удалось освободить mutex, ошибка 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Не удалось записать внутреннюю флэш-память." @@ -1027,12 +1132,13 @@ msgstr "Не удалось записать внутреннюю флэш-па msgid "File exists" msgstr "Файл существует" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "Файл не найден" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Фильтры слишком сложные" @@ -1061,7 +1167,7 @@ msgstr "" "Для цветовых пространств RGB входное растровое изображение должно иметь 16 " "бит на пиксель" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Формат не поддерживается" @@ -1085,6 +1191,7 @@ msgstr "Инициализация GNSS" msgid "Generic Failure" msgstr "Общий сбой" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1175,6 +1282,7 @@ msgid "Insufficient stream input buffer" msgstr "Недостаточный буфер ввода потока" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Интерфейс должен быть запущен" @@ -1186,7 +1294,8 @@ msgstr "Внутренний звуковой буфер слишком мал" msgid "Internal define error" msgstr "Внутренняя ошибка определения" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Внутренняя ошибка" @@ -1220,22 +1329,33 @@ msgstr "Прерванная ошибка." msgid "Interrupted by output function" msgstr "Прерывается функцией выхода" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Недопустимый %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "Недопустимые %q и %q" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1261,6 +1381,14 @@ msgstr "Неверный BSSID" msgid "Invalid MAC address" msgstr "Неверный MAC-адрес" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Недопустимый аргумент" @@ -1269,17 +1397,12 @@ msgstr "Недопустимый аргумент" msgid "Invalid bits per value" msgstr "Недопустимое бит-на-значение" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "Неверный байт %.*s" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "Неверный data_pins[%d]" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "Недопустимый формат" @@ -1292,6 +1415,7 @@ msgid "Invalid hex password" msgstr "Неверный шестнадцатеричный пароль" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Неверный MAC-адрес многоадресной рассылки" @@ -1303,11 +1427,13 @@ msgstr "Неверный размер" msgid "Invalid socket for TLS" msgstr "Неверный сокет для TLS" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Неверное состояние" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "Недопустимое экранирование Юникода" @@ -1315,10 +1441,6 @@ msgstr "Недопустимое экранирование Юникода" msgid "Key must be 16, 24, or 32 bytes long" msgstr "Ключ должен быть длинной 16, 24 или 32 байта" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "Ключ не найден" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "Светодиодные сопоставления должны соответствовать размеру дисплея" @@ -1344,13 +1466,23 @@ msgid "MAC address was invalid" msgstr "MAC адрес был недействительным" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "Защита от MITM не поддерживается" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "Сопоставление должно быть кортежом" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1441,7 +1573,7 @@ msgstr "Изображение памяти" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "Нет пина %q" @@ -1459,6 +1591,7 @@ msgstr "DAC отсутствует на чипе" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "Канал DMA не найден" @@ -1534,6 +1667,10 @@ msgstr "На SDA или SCL не обнаружено подтягивания; msgid "No pulldown on pin; 1Mohm recommended" msgstr "Отсутствует подтяжка к земле на пине; Рекомендуется 1 Мегаом" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "На устройстве не осталось свободного места" @@ -1569,18 +1706,15 @@ msgid "Not connected" msgstr "Не подключено" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "Не воспроизводится (Not playing)" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "Не поддерживается Стандарт JPEG" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Количество data_pins должно быть 8 или 16, а не %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Количество выводов_данных должно быть %d или %d, а не %d" #: shared-bindings/util.c msgid "" @@ -1636,15 +1770,6 @@ msgstr "На этом аппаратном обеспечении доступн msgid "Only int or string supported for ip" msgstr "Для IP поддерживаются только int или строка" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Только монохром, индексированный 4bpp или 8bpp, и 16bpp или больше BMP " -"поддерживаются: %d bpp" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Только один %q может быть переведен в режим глубокого сна." @@ -1682,6 +1807,7 @@ msgid "Operation or feature not supported" msgstr "Операция или функция, не поддерживаемые" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "Истекло время ожидания операции" @@ -1695,6 +1821,7 @@ msgstr "Не хватает памяти" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Вне розеток" @@ -1714,6 +1841,10 @@ msgstr "PWM уже используется" msgid "PWM slice channel A already in use" msgstr "PWM канал среза A уже используется" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "Ошибка параметра" @@ -1817,7 +1948,12 @@ msgstr "Недопустимый размер программы" msgid "Program too long" msgstr "Слишком длинная программа" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "Тяга не используется, когда выводится направление." @@ -1837,6 +1973,27 @@ msgstr "Ошибка деинициализации генератора слу msgid "RNG Init Error" msgstr "Ошибка инициализации RNG" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1915,10 +2072,11 @@ msgstr "Инициализация SD-карты" msgid "SDIO GetCardInfo Error %d" msgstr "Ошибка получения информации о карте SDIO %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "Ошибка инициализации SDIO %d" +msgid "SDIO Init Error %x" +msgstr "Ошибка инициализации SDIO %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1928,6 +2086,10 @@ msgstr "Сбой конфигурации SPI" msgid "SPI init error" msgstr "Ошибка инициализации SPI" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "Используемое периферийное устройство SPI" @@ -1967,6 +2129,7 @@ msgstr "Нарежьте и оцените разную длину." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Фрагменты не поддерживаются" @@ -1975,6 +2138,10 @@ msgstr "Фрагменты не поддерживаются" msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool можно использовать только с wifi.radio" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "Исходный и конечный буферы должны иметь одинаковую длину" @@ -2014,21 +2181,9 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Длина rgb_pins должна быть 6, 12, 18, 24 или 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Bits_per_sample сэмпла не соответствует битам микшера" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Количество каналов образца не совпадает с количеством каналов микшера" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Частота дискретизации семпла не соответствует частоте микшера" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Подпись семпла не совпадает с подписью микшера" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "%q образца не совпадает" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2050,7 +2205,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Высота плитки должна точно делить высоту растрового изображения" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Выход индекса плитки за пределы" @@ -2058,6 +2215,10 @@ msgstr "Выход индекса плитки за пределы" msgid "Tile width must exactly divide bitmap width" msgstr "Ширина плитки должна точно делить ширину растрового изображения" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Время в прошлом." @@ -2068,11 +2229,16 @@ msgstr "Время в прошлом." msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "Таймаут слишком длинный: максимальная длина таймаута %d секунд" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "Слишком много каналов в выборке" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "Слишком много каналов в выборке." @@ -2111,6 +2277,10 @@ msgstr "Деинициализация UART" msgid "UART init" msgstr "Инициализация UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "Используемое периферийное устройство UART" @@ -2119,6 +2289,14 @@ msgstr "Используемое периферийное устройство U msgid "UART re-init" msgstr "Повторная инициализация UART" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "Запись UART" @@ -2143,10 +2321,6 @@ msgstr "USB-устройства указывают слишком много и msgid "USB error" msgstr "Ошибка USB" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "Целое значение UUID должно быть равно 0-0xffff" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "UUID строка не 'xxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxx \"" @@ -2163,6 +2337,7 @@ msgstr "Невозможно получить доступ к невыровне #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "Не удается выделить буферы для подписанного преобразования" @@ -2171,6 +2346,7 @@ msgid "Unable to allocate to the heap." msgstr "Невозможно выделить место в куче." #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "Не удается создать блокировку" @@ -2188,6 +2364,10 @@ msgstr "Не удается инициировать синтаксически msgid "Unable to read color palette data" msgstr "Не удается прочитать данные цветовой палитры" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2275,6 +2455,10 @@ msgstr "" "Неуказанная проблема. Возможно, запрос на сопряжение на другом устройстве " "был отклонен или проигнорирован." +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "Неподдерживаемое цветовое пространство" @@ -2283,15 +2467,12 @@ msgstr "Неподдерживаемое цветовое пространств msgid "Unsupported display bus type" msgstr "Неподдерживаемый тип шины дисплея" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Неподдерживаемый формат" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Неподдерживаемый алгоритм хеширования" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "Неподдерживаемый тип сокета" @@ -2300,15 +2481,20 @@ msgstr "Неподдерживаемый тип сокета" msgid "Update failed" msgstr "Обновление не удалось" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Длина значения! = требуемая фиксированная длина" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2351,9 +2537,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "Wifi не включен" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "" #: main.c msgid "Woken up by alarm.\n" @@ -2375,6 +2563,7 @@ msgstr "Вы нажали обе кнопки при запуске." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Вы нажали кнопку A при запуске." @@ -2388,6 +2577,7 @@ msgstr "Вы нажали кнопку BOOT при запуске" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "При запуске вы нажали кнопку BOOT." @@ -2444,10 +2634,18 @@ msgstr "__new__ arg должен быть пользовательского т msgid "a bytes-like object is required" msgstr "Требуется байтоподобный объект" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "адреса пусты" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "Аннотация должна быть идентификатором" @@ -2472,6 +2670,10 @@ msgstr "аргумент сортировки должен быть аргуме msgid "argsort is not implemented for flattened arrays" msgstr "сортировка arg не реализована для сглаженных массивов" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "аргумент должен быть None, целым числом или кортежем целых чисел" + #: py/compile.c msgid "argument name reused" msgstr "Повторное использование имени аргумента" @@ -2502,10 +2704,6 @@ msgstr "массив слишком велик" msgid "array/bytes required on right side" msgstr "массив/байты, необходимые справа" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "Переполнение ASM" - #: py/compile.c msgid "async for/with outside async function" msgstr "async для/вместе с внешней async-функцией" @@ -2526,6 +2724,10 @@ msgstr "" msgid "attributes not supported" msgstr "Атрибуты не поддерживаются" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "Ось выходит за пределы" @@ -2562,6 +2764,10 @@ msgstr "Неверный шрифт" msgid "binary op %q not implemented" msgstr "двоичная операция %q не реализована" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "Глубина_бита должна быть равна 8, 16, 24 или 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "Размер и глубина растрового изображения должны совпадать" @@ -2574,6 +2780,15 @@ msgstr "Размеры растровых изображений должны с msgid "bits must be 32 or less" msgstr "биты должны быть 32 или менее" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample должно быть 8 или 16" @@ -2631,6 +2846,10 @@ msgstr "Калибровка доступна только для чтения" msgid "can only have one parent" msgstr "может иметь только одного родителя" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "может иметь только до 4 параметров для сборки большого пальца" @@ -2656,7 +2875,7 @@ msgstr "Не удается назначить выражение" msgid "can't cancel self" msgstr "Не могу отменить себя" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "Не удается преобразовать %q в %q" @@ -2699,6 +2918,14 @@ msgstr "Не удается преобразовать в int" msgid "can't convert to str implicitly" msgstr "не может превратиться в полосу неявно" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "не может объявить нелокальный во внешнем коде" @@ -2711,6 +2938,10 @@ msgstr "Не удается удалить выражение" msgid "can't do binary op between '%q' and '%q'" msgstr "Не могу выполнить двоичную операцию между '%q' и '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "Невозможно выполнить унарную операцию '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "не может неявно преобразовать '%q' в 'bool'" @@ -2777,10 +3008,6 @@ msgstr "не может переключаться с ручного поля н msgid "can't truncate-divide a complex number" msgstr "нельзя усекать и делить комплексное число" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "Невозможно однозначно получить sizeof скаляра" - #: extmod/modasyncio.c msgid "can't wait" msgstr "не может ждать" @@ -2801,18 +3028,14 @@ msgstr "не может превратить комплекс в dtype" msgid "cannot convert complex type" msgstr "Не удается преобразовать сложный тип" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "Не удается создать экземпляры '%q'" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "Не удается создать экземпляр" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "Не удается удалить элементы массива" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "Не удается изменить форму массива" @@ -2973,7 +3196,7 @@ msgstr "Размеры не совпадают" msgid "div/mod not implemented for uint" msgstr "div/mod не реализован для uint" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "Делим на ноль" @@ -3072,10 +3295,6 @@ msgstr "Файл должен быть файлом, открытым в бай msgid "file write is not available" msgstr "Запись файлов недоступна" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "Файловая система должна предусматривать метод монтирования" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "Первый аргумент должен быть вызываемым" @@ -3116,18 +3335,22 @@ msgstr "Поплавок слишком большой" msgid "float unsupported" msgstr "Плавающий без поддержки" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "Длина шрифта должна составлять 2048 байт" - #: extmod/moddeflate.c msgid "format" msgstr "формат" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "Формат требует диктата" +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" +msgstr "" + #: py/objdeque.c msgid "full" msgstr "полный" @@ -3175,7 +3398,8 @@ msgstr "В функции отсутствует обязательный арг msgid "function missing required positional argument #%d" msgstr "В функции отсутствует обязательный позиционный аргумент #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "функция принимает %d позиционные аргументы, но %d были заданы" @@ -3192,10 +3416,6 @@ msgstr "генератор проигнорировал Выход" msgid "generator raised StopIteration" msgstr "генератор поднят Остановить итерацию" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "Длина рисунка должна составлять 2048 байт" - #: extmod/modhashlib.c msgid "hash is final" msgstr "хэш является окончательным" @@ -3258,18 +3478,10 @@ msgstr "индексы должны быть целыми числами" msgid "indices must be integers, slices, or Boolean lists" msgstr "индексы должны быть целыми числами, срезами или логическими списками" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "инициализация I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "Начальные значения должны быть итерируемыми" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "длина первоначального_значения ошибочна" - #: py/compile.c msgid "inline assembler must be a function" msgstr "Встроенный ассемблер должен быть функцией" @@ -3327,7 +3539,7 @@ msgstr "Ввод должен быть 1D массивом ndarray" msgid "input must be a dense ndarray" msgstr "Ввод должен быть плотным массивом ndarray" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "Ввод должен быть массивом ndarray" @@ -3360,6 +3572,10 @@ msgstr "interp определен для 1D-итераций одинаково msgid "interval must be in range %s-%s" msgstr "Интервал должен находиться в диапазоне %s-%s" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "недействительная арка" @@ -3460,10 +3676,6 @@ msgstr "Метка '%q' не определена" msgid "label redefined" msgstr "Метка переопределена" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "уровень должен быть между 0 и 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs и rhs должны быть совместимыми" @@ -3519,7 +3731,7 @@ msgstr "матрица не является положительно опред msgid "max_length must be 0-%d when fixed_length is %s" msgstr "максимальная_длина должна быть 0-%d когда фиксированная длина %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "Максимальное количество измерений составляет " @@ -3564,6 +3776,10 @@ msgstr "mktime нужен кортеж длины 8 или 9" msgid "mode must be complete, or reduced" msgstr "Режим должен быть завершенным или уменьшенным" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "модуль не найден" @@ -3597,7 +3813,7 @@ msgid "must use keyword argument for key function" msgstr "Необходимо использовать аргумент ключевого слова для ключевой функции" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "Имя '%q' не определено" #: py/runtime.c @@ -3606,16 +3822,12 @@ msgstr "Имя не определено" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "слишком длинное имя" #: py/persistentcode.c msgid "native code in .mpy unsupported" msgstr "Нативный код в .mpy не поддерживается" -#: py/asmthumb.c -msgid "native method too big" -msgstr "родной метод слишком большой" - #: py/emitnative.c msgid "native yield" msgstr "родной урожай" @@ -3637,7 +3849,7 @@ msgstr "отрицательный факториал" msgid "negative power with no float support" msgstr "Отрицательная мощность без поплавковой опоры" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "Количество отрицательных сдвигов" @@ -3661,7 +3873,7 @@ msgstr "Привязка для нелокальных не найдена" msgid "no default packer" msgstr "Нет упаковщика по умолчанию" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "Нет начального числа по умолчанию" @@ -3689,8 +3901,8 @@ msgstr "" "умолчанию" #: py/objstr.c -msgid "non-hex digit found" -msgstr "Ненайдена шестнадцатеричная цифра" +msgid "non-hex digit" +msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c msgid "non-zero timeout must be > 0.01" @@ -3708,14 +3920,6 @@ msgstr "не 128-битный UUID" msgid "not a constant" msgstr "не константа" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "Не все аргументы преобразуются при форматировании строки" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "Недостаточно аргументов для строки форматирования" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "не реализовано для сложного типа d" @@ -3724,6 +3928,10 @@ msgstr "не реализовано для сложного типа d" msgid "not supported for input types" msgstr "Не поддерживается для типов ввода" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "Количество баллов должно быть не менее 2" @@ -3737,6 +3945,10 @@ msgstr "объект " msgid "object '%s' isn't a tuple or list" msgstr "Объект \"%s\" не является кортежом или списком" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "Объект не поддерживает назначение элементов" @@ -3778,10 +3990,6 @@ msgstr "объект типа «%s» не имеет len()" msgid "object with buffer protocol required" msgstr "Объект с обязательным буферным протоколом" -#: py/objstr.c -msgid "odd-length string" -msgstr "Строка нечетной длины" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "выключить" @@ -3830,6 +4038,30 @@ msgstr "поддерживаются только срезы с шагом = 1 ( msgid "opcode" msgstr "код операции" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3872,6 +4104,10 @@ msgstr "ord() ожидал символ, но строка длины %d най msgid "out array is too small" msgstr "Наш массив слишком мал" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "out имеет неправильный тип" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "Ключевое слово out не поддерживается для сложного типа d" @@ -3896,6 +4132,14 @@ msgstr "Выход должен быть поплавкового типа" msgid "out of range of target" msgstr "вне досягаемости цели" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "Выходной массив имеет неправильный тип" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "выходной массив должен быть непрерывным" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "переполнение преобразование длинного целого в машинное слово" @@ -3905,9 +4149,9 @@ msgstr "переполнение преобразование длинного msgid "pack expected %d items for packing (got %d)" msgstr "Упаковка ожидаемых %d товаров для упаковки (получил %d)" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" -msgstr "Длина палитры должна составлять 32 байта" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" +msgstr "" #: py/emitinlinextensa.c msgid "parameters must be registers in sequence a2 to a5" @@ -3958,14 +4202,14 @@ msgstr "pow() с 3 аргументами требует целых чисел" msgid "pull masks conflict with direction masks" msgstr "Маски вытягивания конфликтуют с масками направления" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "Необработанные F-строки не поддерживаются" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "реальные и воображаемые части должны быть одинаковой длины" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "Относительный импорт" @@ -3975,6 +4219,10 @@ msgstr "Относительный импорт" msgid "requested length %d but object has length %d" msgstr "запрашиваемая длина %d, но объект имеет длину %d" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "Результаты не могут быть приведены к указанному типу" @@ -4005,6 +4253,10 @@ msgstr "аргумент roll должен быть массивом ndarray" msgid "rsplit(None,n)" msgstr "rsplit(Нет;n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -4022,6 +4274,10 @@ msgstr "Компиляция скриптов не поддерживается" msgid "set unsupported" msgstr "Установить не поддерживается" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "форма должна быть None, целым числом или кортежем целых чисел" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "фигура должна быть целым числом или кортежом целых чисел" @@ -4042,6 +4298,10 @@ msgstr "Знак не разрешен со спецификатором цел msgid "size is defined for ndarrays only" msgstr "размер определен только для массива ndarrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "Размер должен соответствовать out.shape при совместном использовании" + #: py/nativeglue.c msgid "slice unsupported" msgstr "Фрагмент не поддерживается" @@ -4090,10 +4350,6 @@ msgstr "source_bitmap должен иметь значение_счет 8" msgid "splitting with sub-captures" msgstr "разделение с помощью подзахватов" -#: py/objstr.c -msgid "start/end indices" -msgstr "Начальные/конечные индексы" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "Остановка недоступна с начального запуска" @@ -4115,18 +4371,6 @@ msgstr "индекс строки выходит за пределы диапа msgid "string indices must be integers, not %s" msgstr "Индексы строк должны быть целыми числами, а не %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "структура: невозможно индексировать" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "структура: индекс вне диапазона" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "Структура: Нет полей" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "Подстрока не найдена" @@ -4139,10 +4383,6 @@ msgstr "super() не может найти себя" msgid "syntax error in JSON" msgstr "синтаксис ошибка в JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "Синтаксическая ошибка в дескрипторе UCTYPES" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "переполнение интервала тиков" @@ -4234,11 +4474,11 @@ msgid "tx and rx cannot both be None" msgstr "tx и rx не могут быть одновременно None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "Тип '%Q' не является допустимым базовым типом" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "Тип не является приемлемым базовым типом" #: py/runtime.c @@ -4249,14 +4489,6 @@ msgstr "тип объекта '%q' не имеет атрибута '%q \"" msgid "type takes 1 or 3 arguments" msgstr "тип занимает 1 или 3 аргумента" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "голова длинная слишком большая" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "унарная операция %q не реализована" - #: py/parse.c msgid "unexpected indent" msgstr "Неожиданный отступ" @@ -4304,7 +4536,9 @@ msgstr "Несовпадающий '%c' в формате" msgid "unreadable attribute" msgstr "Нечитаемый атрибут" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "Неподдерживаемый тип %Q" @@ -4365,9 +4599,8 @@ msgid "value out of range of target" msgstr "Величина выходящая за пределы диапазона цели" #: extmod/moddeflate.c -#, fuzzy msgid "wbits" -msgstr "wbits" +msgstr "" #: shared-bindings/bitmapfilter/__init__.c msgid "" @@ -4385,11 +4618,6 @@ msgstr "Веса должны быть объектом типа %q, %q, %q ил msgid "width must be greater than zero" msgstr "ширина должна быть больше нуля" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "Wi-Fi не включен" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "Wi-Fi. Монитор недоступен" @@ -4452,6 +4680,164 @@ msgstr "zi должно быть типа float" msgid "zi must be of shape (n_section, 2)" msgstr "zi должен иметь форму (n_section, 2)" +#~ msgid "%q renamed %q" +#~ msgstr "%q переименован %q" + +#~ msgid "asm overflow" +#~ msgstr "Переполнение ASM" + +#~ msgid "cannot create instance" +#~ msgstr "Не удается создать экземпляр" + +#~ msgid "native method too big" +#~ msgstr "родной метод слишком большой" + +#~ msgid "ulonglong too large" +#~ msgstr "голова длинная слишком большая" + +#~ msgid "font must be 2048 bytes long" +#~ msgstr "Длина шрифта должна составлять 2048 байт" + +#~ msgid "graphic must be 2048 bytes long" +#~ msgstr "Длина рисунка должна составлять 2048 байт" + +#~ msgid "palette must be 32 bytes long" +#~ msgstr "Длина палитры должна составлять 32 байта" + +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Буфер + сдвиг слишком малы %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Буфер байтов должен быть размером 16 байтам." + +#~ msgid "UUID integer value must be 0-0xffff" +#~ msgstr "Целое значение UUID должно быть равно 0-0xffff" + +#~ msgid "initial_value length is wrong" +#~ msgstr "длина первоначального_значения ошибочна" + +#, c-format +#~ msgid "Invalid byte %.*s" +#~ msgstr "Неверный байт %.*s" + +#~ msgid "Key not found" +#~ msgstr "Ключ не найден" + +#~ msgid "Not supported JPEG standard" +#~ msgstr "Не поддерживается Стандарт JPEG" + +#~ msgid "%q moved from %q to %q" +#~ msgstr "%q переместился из %q в %q" + +#~ msgid "filesystem must provide mount method" +#~ msgstr "Файловая система должна предусматривать метод монтирования" + +#~ msgid "start/end indices" +#~ msgstr "Начальные/конечные индексы" + +#, c-format +#~ msgid "%%c requires int or char" +#~ msgstr "%%c требует int или char" + +#~ msgid "'%q' object is not callable" +#~ msgstr "Объект '%q' не является вызываемым" + +#~ msgid "cannot create '%q' instances" +#~ msgstr "Не удается создать экземпляры '%q'" + +#~ msgid "non-hex digit found" +#~ msgstr "Ненайдена шестнадцатеричная цифра" + +#~ msgid "not all arguments converted during string formatting" +#~ msgstr "Не все аргументы преобразуются при форматировании строки" + +#~ msgid "not enough arguments for format string" +#~ msgstr "Недостаточно аргументов для строки форматирования" + +#~ msgid "odd-length string" +#~ msgstr "Строка нечетной длины" + +#~ msgid "raw f-strings are not supported" +#~ msgstr "Необработанные F-строки не поддерживаются" + +#~ msgid "Unsupported format" +#~ msgstr "Неподдерживаемый формат" + +#~ msgid "Wifi is not enabled" +#~ msgstr "Wifi не включен" + +#~ msgid "wifi is not enabled" +#~ msgstr "Wi-Fi не включен" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Невозможно перемонтировать '/' пока он виден через USB." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q должен быть объектом %q, %q или %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Блок данных должен следовать за блоком fmt" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Только монохром, индексированный 4bpp или 8bpp, и 16bpp или больше BMP " +#~ "поддерживаются: %d bpp" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "уровень должен быть между 0 и 1" + +#~ msgid "init I2C" +#~ msgstr "инициализация I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Bits_per_sample сэмпла не соответствует битам микшера" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "" +#~ "Количество каналов образца не совпадает с количеством каналов микшера" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Частота дискретизации семпла не соответствует частоте микшера" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Подпись семпла не совпадает с подписью микшера" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Размер буфера должен быть кратен 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Буфер должен быть кратен 512" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Количество data_pins должно быть 8 или 16, а не %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "Ошибка инициализации SDIO %d" + +#~ msgid "can't unambiguously get sizeof scalar" +#~ msgstr "Невозможно однозначно получить sizeof скаляра" + +#~ msgid "struct: can't index" +#~ msgstr "структура: невозможно индексировать" + +#~ msgid "struct: index out of range" +#~ msgstr "структура: индекс вне диапазона" + +#~ msgid "struct: no fields" +#~ msgstr "Структура: Нет полей" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "Синтаксическая ошибка в дескрипторе UCTYPES" + +#~ msgid "unary op %q not implemented" +#~ msgstr "унарная операция %q не реализована" + #~ msgid "Name too long" #~ msgstr "Имя слишком длинное" @@ -4651,7 +5037,7 @@ msgstr "zi должен иметь форму (n_section, 2)" #~ msgid "'continue' outside loop" #~ msgstr "«продолжить» вне цикла" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "Объект 'coroutine' не является итератором" #~ msgid "(x,y) integers required" @@ -4846,8 +5232,8 @@ msgstr "zi должен иметь форму (n_section, 2)" #~ msgstr "IV должен быть длиной %d байт" #~ msgid "" -#~ "Incompatible .mpy file. Please update all .mpy files. See http://adafru." -#~ "it/mpy-update for more info." +#~ "Incompatible .mpy file. Please update all .mpy files. See http://" +#~ "adafru.it/mpy-update for more info." #~ msgstr "" #~ "Несовместимый файл .mpy. Пожалуйста, обновите все файлы .mpy. См. http://" #~ "adafru.it/mpy-update для получения дополнительной информации." diff --git a/locale/sv.po b/locale/sv.po index 6a133cd4d0195..cfdbaa3064b8a 100644 --- a/locale/sv.po +++ b/locale/sv.po @@ -6,15 +6,15 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2024-01-15 16:06+0000\n" -"Last-Translator: Jonny Bergdahl \n" +"PO-Revision-Date: 2025-06-15 23:04+0000\n" +"Last-Translator: Jonny Bergdahl \n" "Language-Team: LANGUAGE \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.4-dev\n" +"X-Generator: Weblate 5.12-dev\n" #: main.c msgid "" @@ -94,7 +94,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q och %q innehåller duplicerade pinnar" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q och %q måste vara olika" @@ -104,7 +104,7 @@ msgstr "%q och %q måste dela klockenhet" #: ports/nordic/common-hal/watchdog/WatchDogTimer.c msgid "%q cannot be changed once mode is set to %q" -msgstr "" +msgstr "%q kan inte ändras efter att läge satts till %q" #: shared-bindings/microcontroller/Pin.c msgid "%q contains duplicate pins" @@ -114,7 +114,11 @@ msgstr "%q innehåller dubblettstift" msgid "%q failure: %d" msgstr "%q-fel: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q in %1 måste vara av typ %q eller %q, inte %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q i %q måste vara av typen %q, inte %q" @@ -166,7 +170,7 @@ msgstr "längden på %q måste vara <= %d" msgid "%q length must be >= %d" msgstr "längden på %q måste vara >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q flyttad från %q till %q" @@ -228,6 +232,7 @@ msgstr "%q måste vara en multipel av 8." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q måste vara av typen %q eller %q, inte %q" @@ -237,6 +242,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q måste vara av typen %q, %q, eller %q, inte %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q måste vara av typen %q, inte %q" @@ -282,7 +288,8 @@ msgstr "%q() utan %q()" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q och %q måste vara lika långa" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -316,7 +323,7 @@ msgid "'%q' object does not support '%q'" msgstr "Objektet '%q' stöder inte '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "Objektet '%q' är inte en iterator" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -324,13 +331,13 @@ msgid "'%q' object is not callable" msgstr "Objektet '%q' kan inte anropas" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "Objektet '%q' är inte itererbart" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format msgid "'%s' expects a label" -msgstr "'%s' förväntar sig en label" +msgstr "'%s' förväntar sig en etikett" #: py/emitinlinethumb.c py/emitinlinextensa.c #, c-format @@ -428,6 +435,10 @@ msgstr "'data' kräver heltalsargument" msgid "'label' requires 1 argument" msgstr "'label' kräver 1 argument" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' är inte implementerat" + #: py/compile.c msgid "'return' outside function" msgstr "'return' utanför funktion" @@ -450,7 +461,7 @@ msgstr "*x måste vara mål för tilldelning" #: py/obj.c msgid ", in %q\n" -msgstr ", i %q\n" +msgstr ", i%q\n" #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c @@ -547,7 +558,6 @@ msgstr "Alla timers för denna pinne är i bruk" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Alla timers används" @@ -560,6 +570,10 @@ msgstr "Annonserar redan." msgid "Already have all-matches listener" msgstr "Har redan lyssnare för all-matchningar" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "Pågår redan" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -569,6 +583,7 @@ msgstr "Kör redan" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Skannar redan efter WiFi-nätverk" @@ -595,6 +610,10 @@ msgstr "Matrisen måste innehålla halfwords (typ \"H\")" msgid "Array values should be single bytes." msgstr "Matrisvärden ska bestå av enstaka bytes." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "Async SPI-överföring pågår på denna buss, forsätter vänta." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -604,6 +623,11 @@ msgstr "Försök att tilldela %d block" msgid "Audio conversion not implemented" msgstr "Ljudkonvertering inte implementerad" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "Fel på ljudkälla" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN används inte med lösenord" @@ -621,8 +645,8 @@ msgid "" "Auto-reload is on. Simply save files over USB to run them or enter REPL to " "disable.\n" msgstr "" -"Autoladdning är på. Spara filer via USB för att köra dem eller ange REPL för " -"att inaktivera.\n" +"Autoladdning är på. Spara filer via USB för att köra dem eller gå till REPL " +"för att inaktivera.\n" #: ports/espressif/common-hal/canio/CAN.c msgid "Baudrate not supported by peripheral" @@ -673,13 +697,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Buffertlängd %d för stor. Den måste vara mindre än %d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Buffertlängd måste vara en multipel av 512" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Bufferten måste vara en multipel av 512 byte" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "Buffer måste vara multipel av %d byte" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -738,6 +762,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "Kan bara larma från djup sömn på två låga pinnar." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "Kan inte skapa AudioOut eftersom kontinuerlig kanal redan är öppen" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -784,8 +812,8 @@ msgid "Cannot record to a file" msgstr "Det går inte att spela in till en fil" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "Det går inte att montera om '/' när den är synlig via USB." +msgid "Cannot remount path when visible via USB." +msgstr "Kan inte montera sökväg när den är åtkomlig via USB." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -800,6 +828,10 @@ msgstr "Det går inte att specificera RTS eller CTS i RS485-läget" msgid "Cannot subclass slice" msgstr "Det går inte att subklassa slice" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "Kan inte använda GPIO0..15 tillsammans med GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "Kan inte vakna på pin edge, bara nivå" @@ -836,6 +868,10 @@ msgstr "Arrayer för koordinater har olika längd" msgid "Coordinate arrays types have different sizes" msgstr "Arrayer för koordinater har olika storlek" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "Kan inte publicera till ROS topic" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Kan inte ange adress" @@ -848,6 +884,11 @@ msgstr "Det gick inte att starta avbrott, RX upptagen" msgid "Couldn't allocate decoder" msgstr "Det gick inte att allokera avkodaren" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "Kritiskt ROS-fel vid mjuk omstart, reset krävs: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "Initieringsfel för DAC-kanal" @@ -865,10 +906,6 @@ msgstr "DAC används redan" msgid "Data 0 pin must be byte aligned" msgstr "Datapinne 0 måste vara bytejusterad" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Datasegmentet måste följa fmt-segmentet" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "Dataformatfel (kan var felaktig data)" @@ -1002,15 +1039,47 @@ msgstr "Det gick inte att ansluta: internt fel" msgid "Failed to connect: timeout" msgstr "Det gick inte att ansluta: timeout" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Kan inte skapa kontinuerliga kanaler: ogiltigt argument" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Det gick inte att skapa kontinuerliga kanaler: ogiltigt läge" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Det gick inte att skapa kontinuerliga kanaler: Inget minne" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Det gick inte att skapa kontinuerliga kanaler: inte funnen" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Kan inte skapa kontinuerlig" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Det gick inte att tolka MP3-filen" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Kan inte registrera kontinuerlig händelsers callback" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Det gick inte att frigöra mutex, fel 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "Kan inte sätta värdnamn" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Kan inte starta async audio" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Det gick inte att skriva till intern flash." @@ -1019,12 +1088,14 @@ msgstr "Det gick inte att skriva till intern flash." msgid "File exists" msgstr "Filen finns redan" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "Filen hittades inte" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filter för komplexa" @@ -1049,7 +1120,7 @@ msgstr "För L8-färgrymden måste indatabitmappen ha 8 bitar per pixel" msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "För RGB-färgrymder måste indatabitmappen ha 16 bitar per pixel" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Format stöds inte" @@ -1161,6 +1232,7 @@ msgid "Insufficient stream input buffer" msgstr "Otillräcklig buffer för inström" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Gränssnittet måste vara startat" @@ -1192,7 +1264,7 @@ msgstr "Internt fel #%d" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-bindings/pwmio/PWMOut.c msgid "Internal resource(s) in use" -msgstr "" +msgstr "Intern(a) resurs(er) används redan" #: supervisor/shared/safe_mode.c msgid "Internal watchdog timer expired." @@ -1206,22 +1278,26 @@ msgstr "Interrupt-fel." msgid "Interrupted by output function" msgstr "Avbruten av utgångsfunktion" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Ogiltig %q" #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" -msgstr "" +msgstr "Ogiltig %q och %q" #: ports/atmel-samd/common-hal/microcontroller/Pin.c #: ports/espressif/common-hal/dotclockframebuffer/DotClockFramebuffer.c @@ -1247,6 +1323,10 @@ msgstr "Ogiltig BSSID" msgid "Invalid MAC address" msgstr "Ogiltig MAC-adress" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "Ogiltigt ROS domän-id" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Ogiltigt argument" @@ -1278,6 +1358,7 @@ msgid "Invalid hex password" msgstr "Ogiltigt hex-lösenord" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Ogiltig MAC-adress för multicast" @@ -1290,6 +1371,7 @@ msgid "Invalid socket for TLS" msgstr "Ogiltig socket för TLS" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Ogiltigt tillstånd" @@ -1323,15 +1405,21 @@ msgstr "Layer måste vara en underklass av Group eller TileGrid" #: shared-bindings/audiocore/RawSample.c msgid "Length of %q must be an even multiple of channel_count * type_size" -msgstr "" +msgstr "Längden på %q måste vara en jämn multipel av channel_count * type_size" #: ports/espressif/common-hal/espidf/__init__.c msgid "MAC address was invalid" msgstr "MAC-adressen var ogiltig" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" -msgstr "" +msgstr "MITM-säkerhet stöds inte" + +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "Fel på MMC/SDIO-klocka: %x" #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" @@ -1376,9 +1464,10 @@ msgstr "Saknad jmp_pin. %q[%u] hoppar på pin" #: shared-module/storage/__init__.c msgid "Mount point directory missing" -msgstr "" +msgstr "Katalog för monteringspunkt saknas" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Måste vara en %q-subklass." @@ -1463,7 +1552,7 @@ msgstr "Ingen IP" #: ports/cxd56/common-hal/microcontroller/__init__.c #: ports/mimxrt10xx/common-hal/microcontroller/__init__.c msgid "No bootloader present" -msgstr "" +msgstr "Bootloader saknas" #: shared-module/usb/core/Device.c msgid "No configuration set" @@ -1518,6 +1607,10 @@ msgstr "Ingen pull-up hittades på SDA eller SCL; kontrollera inkopplingen" msgid "No pulldown on pin; 1Mohm recommended" msgstr "Ingen pulldown på pinnen; 1Mohm rekommenderas" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Pullup saknas på pinne; 1MOhm rekommenderas" + #: py/moderrno.c msgid "No space left on device" msgstr "Inget utrymme kvar på enheten" @@ -1562,9 +1655,10 @@ msgid "Not supported JPEG standard" msgstr "JPEG-standard stöds ej" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "Antal data_pins måste vara 8 eller 16, inte %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "Antal för data_pins måste vara %d eller %d, inte %d" #: shared-bindings/util.c msgid "" @@ -1619,15 +1713,6 @@ msgstr "Endast kantdetektering är tillgänglig för denna hårdvara" msgid "Only int or string supported for ip" msgstr "Endast int eller string stöds för ip" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Endast monokrom, indexerad 4 bpp eller 8 bpp och 16 bpp eller högre BMP: er " -"stöds: %d bpp angiven" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "Endast en %q kan sättas i djup sömn." @@ -1678,6 +1763,7 @@ msgstr "Slut på minne" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "Slut på sockets" @@ -1697,6 +1783,10 @@ msgstr "PWM-segment används redan" msgid "PWM slice channel A already in use" msgstr "PWM-segmentkanal A används redan" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "Paketbuffertar för en SPI-överföring måste ha samma längd." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "Parameterfel" @@ -1799,6 +1889,10 @@ msgstr "Programstorlek ogiltig" msgid "Program too long" msgstr "Programmet är för långt" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "Publicerare kan bara skapas from föräldranod" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Pull används inte när riktningen är output." @@ -1819,6 +1913,26 @@ msgstr "RNG DeInit-fel" msgid "RNG Init Error" msgstr "RNG Init-fel" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "Fel vid ROS initialisering, är agent ansluten?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "Fel vid ROS intern inställning" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "Fel vid ROS minnesallokering" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "Fel vid ROS-nods initialisering" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "Fel vid initialisering av ROS topic" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1897,10 +2011,11 @@ msgstr "SDCard start" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo-fel %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO Init-fel %d" +msgid "SDIO Init Error %x" +msgstr "SDIO Init Fel %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1949,11 +2064,13 @@ msgstr "Slice och värde har olika längd." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Slice stöds inte" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool kan endast användas med wifi.radio" @@ -1967,7 +2084,7 @@ msgstr "Ange en av data0 eller data_pins" #: supervisor/shared/safe_mode.c msgid "Stack overflow. Increase stack size." -msgstr "" +msgstr "Stack overflow. Öka stackstorleken." #: shared-bindings/alarm/time/TimeAlarm.c msgid "Supply one of monotonic_time or epoch_time" @@ -1993,21 +2110,9 @@ msgstr "Ovanstående undantag var den direkta orsaken till följande undantag:" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Längden på rgb_pins vara 6, 12, 18, 24 eller 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Samplingens bits_per_sample matchar inte mixerns" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Samplingens kanalantal matchar inte mixerns" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Samplingens frekvens matchar inte mixerns" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Samplingens signerad/osignerad stämmer inte med mixern" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "Prov %q matchar inte" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2029,7 +2134,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Tile-höjden måste vara jämnt delbar med höjd på bitmap" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Tile-index utanför gräns" @@ -2037,6 +2144,10 @@ msgstr "Tile-index utanför gräns" msgid "Tile width must exactly divide bitmap width" msgstr "Tile-bredd måste vara jämnt delbar med bredd på bitmap" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper får bara bindas till ett TileGrid en gång" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "Tid har passerats." @@ -2057,7 +2168,7 @@ msgstr "För många kanaler i sampling." #: ports/espressif/common-hal/_bleio/Characteristic.c msgid "Too many descriptors" -msgstr "" +msgstr "För många beskrivningar" #: shared-module/displayio/__init__.c msgid "Too many display busses; forgot displayio.release_displays() ?" @@ -2083,7 +2194,7 @@ msgstr "Traceback (senaste anrop):\n" #: ports/stm/common-hal/busio/UART.c msgid "UART de-init" -msgstr "UART omstart" +msgstr "Avinitiering av UART" #: ports/cxd56/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c #: ports/stm/common-hal/busio/UART.c @@ -2167,6 +2278,11 @@ msgstr "Kan inte initiera tolken" msgid "Unable to read color palette data" msgstr "Det går inte att läsa färgpalettdata" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" +"Kan inte skicka CAN-meddelande: alla Tx-meddelandebuffertar är upptagna" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2261,32 +2377,27 @@ msgstr "Färgrymd stöds inte" msgid "Unsupported display bus type" msgstr "Busstyp för display stöds inte" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Format stöds inte" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "Hash-algoritmen stöds inte" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" -msgstr "" +msgstr "Sockettyp stöds ej" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/espressif/common-hal/dualbank/__init__.c msgid "Update failed" -msgstr "" +msgstr "Uppdatering misslyckades" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Värdets längde ! = krävd fast längd" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2327,8 +2438,10 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "WiFi är inte aktiverat" #: main.c @@ -2351,6 +2464,7 @@ msgstr "Du tryckte ner båda knapparna vid start." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "Du tryckte ner knapp A vid start." @@ -2364,8 +2478,9 @@ msgstr "Du tryckte ner BOOT-knappen vid start" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." -msgstr "" +msgstr "Du tryckte på BOOT-knappen vid start." #: ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.h msgid "You pressed the GPIO0 button at start up." @@ -2424,6 +2539,10 @@ msgstr "ett bytesliknande objekt krävs" msgid "addresses is empty" msgstr "adresserna är tomma" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "spelas redan" + #: py/compile.c msgid "annotation must be an identifier" msgstr "Annoteringen måste vara en identifierare" @@ -2448,6 +2567,10 @@ msgstr "argumentet argsort måste vara en ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "argsort är inte implementerad för tillplattade matriser" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "argument måste vara None, en integer eller en tuple av heltal" + #: py/compile.c msgid "argument name reused" msgstr "argumentnamn återanvänt" @@ -2498,6 +2621,10 @@ msgstr "försök att få argmin/argmax för en tom sekvens" msgid "attributes not supported" msgstr "Attribut stöds ej" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "audioformatet stöds inte" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "axis är utanför gränsen" @@ -2534,9 +2661,13 @@ msgstr "Ogiltig typkod" msgid "binary op %q not implemented" msgstr "binär op %q är inte implementerad" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth måste vara 8, 16, 24, or 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" -msgstr "" +msgstr "bitmaps size och depth måste matcha" #: shared-bindings/bitmaptools/__init__.c msgid "bitmap sizes must match" @@ -2546,6 +2677,15 @@ msgstr "bitmappsstorlekar måste matcha" msgid "bits must be 32 or less" msgstr "bits måste vara 32 eller färre" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample måste vara 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "bits_per_sample måste vara 8 eller 16" @@ -2627,7 +2767,7 @@ msgstr "kan inte tilldela uttryck" msgid "can't cancel self" msgstr "kan inte avbryta sig själv" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "kan inte konvertera %q till %q" @@ -2682,6 +2822,10 @@ msgstr "kan inte ta bort uttryck" msgid "can't do binary op between '%q' and '%q'" msgstr "kan inte göra binära op mellan '%q' och '%q'" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "kan inte göra unary operation av '%q'" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "kan inte implicit konvertera '%q' till 'bool'" @@ -2746,10 +2890,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "kan inte trunker-dividera ett komplext tal" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "kan inte entydigt få fram storleken på skalären" - #: extmod/modasyncio.c msgid "can't wait" msgstr "kan inte vänta" @@ -3091,7 +3231,7 @@ msgid "format" msgstr "format" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "formatet kräver en dict" #: py/objdeque.c @@ -3141,7 +3281,8 @@ msgstr "funktionen saknar det obligatoriska nyckelordsargumentet '%q'" msgid "function missing required positional argument #%d" msgstr "funktionen saknar det obligatoriska positionsargumentet #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "funktionen kräver %d positionsargument men %d angavs" @@ -3224,10 +3365,6 @@ msgstr "index måste vara heltal" msgid "indices must be integers, slices, or Boolean lists" msgstr "index måste vara heltal, slices, eller Boolean-listor" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "I2C start" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "initialvärden måste vara iterable" @@ -3293,7 +3430,7 @@ msgstr "indata måste vara en 1D ndarray" msgid "input must be a dense ndarray" msgstr "indata måste vara en dense ndarray" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "indata måste vara en ndarray" @@ -3424,10 +3561,6 @@ msgstr "etiketten '%q' har inte definierats" msgid "label redefined" msgstr "etiketten omdefinierad" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "level ska ligga mellan 0 och 1" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs och rhs måste vara kompatibla" @@ -3481,7 +3614,7 @@ msgstr "matrisen är inte positiv bestämd" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length måste vara 0-%d när fixed_length är %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "maximalt antal dimensioner är " @@ -3559,7 +3692,7 @@ msgid "must use keyword argument for key function" msgstr "måste använda nyckelordsargument för nyckelfunktion" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "namnet '%q' är inte definierat" #: py/runtime.c @@ -3568,7 +3701,7 @@ msgstr "namn inte definierat" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "namn för långt" #: py/persistentcode.c msgid "native code in .mpy unsupported" @@ -3623,7 +3756,7 @@ msgstr "ingen bindning för ickelokal hittad" msgid "no default packer" msgstr "ingen standardpackare" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "inget standard seed" @@ -3832,6 +3965,10 @@ msgstr "ord() förväntade sig ett tecken, men en sträng med längden %d hittad msgid "out array is too small" msgstr "matrisen för out är för liten" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "out har fel typ" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "nyckelordet out stöds inte för komplex dtyp" @@ -3856,6 +3993,14 @@ msgstr "out måste vara av float dtype" msgid "out of range of target" msgstr "utanför räckvidd för target" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "output array har fel typ" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "output array måste vara kontinuerlig" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "Konvertering av long int till machine word överskred maxvärde" @@ -3965,6 +4110,10 @@ msgstr "argumentet roll måste vara en ndarray" msgid "rsplit(None,n)" msgstr "rsplit(None,n)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed måste vara sann" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3972,7 +4121,7 @@ msgstr "samplingsfrekvens utanför räckvidden" #: py/modmicropython.c msgid "schedule queue full" -msgstr "schemakön full" +msgstr "schemakö full" #: py/builtinimport.c msgid "script compilation not supported" @@ -3982,6 +4131,10 @@ msgstr "skriptkompilering stöds inte" msgid "set unsupported" msgstr "set stöds inte" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "shape måste vara None, integer eller en tuple av integers" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "shape måste vara ett heltal eller en tupel av heltal" @@ -4002,6 +4155,10 @@ msgstr "tecken tillåts inte med heltalsformatspecificeraren 'c'" msgid "size is defined for ndarrays only" msgstr "storlek är enbart definierad ndarrays" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "size måste matcha out.shape när dom används tillsammans" + #: py/nativeglue.c msgid "slice unsupported" msgstr "slice stöds inte" @@ -4075,18 +4232,6 @@ msgstr "strängindex utanför intervallet" msgid "string indices must be integers, not %s" msgstr "strängindex måste vara heltal, inte %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "struct: kan inte indexera" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "struct: index utanför intervallet" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "struct: inga fält" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "det gick inte att hitta delsträng" @@ -4099,10 +4244,6 @@ msgstr "super() kan inte hitta self" msgid "syntax error in JSON" msgstr "syntaxfel i JSON" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "syntaxfel i uctypes deskriptor" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "Överskridet tickintervall" @@ -4117,12 +4258,12 @@ msgstr "timeout måste vara < 655,35 sekunder" #: ports/raspberrypi/common-hal/floppyio/__init__.c msgid "timeout waiting for flux" -msgstr "" +msgstr "tidsgräns överskriden vid väntan på flux" #: ports/raspberrypi/common-hal/floppyio/__init__.c #: shared-module/floppyio/__init__.c msgid "timeout waiting for index pulse" -msgstr "" +msgstr "Tidsgräns överskriden vid väntan på indexpuls" #: shared-module/sdcardio/SDCard.c msgid "timeout waiting for v1 card" @@ -4192,11 +4333,11 @@ msgid "tx and rx cannot both be None" msgstr "tx och rx kan inte båda vara None" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "typ '%q' är inte en acceptabel bastyp" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "typ är inte en acceptabel bastyp" #: py/runtime.c @@ -4211,10 +4352,6 @@ msgstr "typen tar 1 eller 3 argument" msgid "ulonglong too large" msgstr "ulonglong för stor" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "binär op %q är inte implementerad" - #: py/parse.c msgid "unexpected indent" msgstr "oväntat indrag" @@ -4262,7 +4399,9 @@ msgstr "Omatchad '%c' i format" msgid "unreadable attribute" msgstr "attribut kan inte läsas" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "typ %q stöds inte" @@ -4278,7 +4417,7 @@ msgstr "Xtensa-instruktion '%s' med %d argument stöds inte" #: shared-module/bitmapfilter/__init__.c msgid "unsupported bitmap depth" -msgstr "" +msgstr "Bitmapps­djupet stöds inte" #: shared-module/gifio/GifWriter.c msgid "unsupported colorspace for GifWriter" @@ -4331,20 +4470,17 @@ msgid "" "weights must be a sequence with an odd square number of elements (usually 9 " "or 25)" msgstr "" +"vikterna måste vara en sekvens med ett udda kvadrattal antal element " +"(vanligtvis 9 eller 25)" #: shared-bindings/bitmapfilter/__init__.c msgid "weights must be an object of type %q, %q, %q, or %q, not %q " -msgstr "" +msgstr "Vikter måste vara ett objekt av typen %q, %q, %q eller %q, inte %q " #: shared-bindings/is31fl3741/FrameBuffer.c msgid "width must be greater than zero" msgstr "width måste vara större än noll" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "WiFi är inte aktiverat" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wifi.Monitor är inte tillgänglig" @@ -4407,6 +4543,79 @@ msgstr "zi måste vara av typ float" msgid "zi must be of shape (n_section, 2)" msgstr "zi måste vara i formen (n_section, 2)" +#~ msgid "Unsupported format" +#~ msgstr "Format stöds inte" + +#~ msgid "Wifi is not enabled" +#~ msgstr "WiFi är inte aktiverat" + +#~ msgid "wifi is not enabled" +#~ msgstr "WiFi är inte aktiverat" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "Det går inte att montera om '/' när den är synlig via USB." + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Datasegmentet måste följa fmt-segmentet" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Endast monokrom, indexerad 4 bpp eller 8 bpp och 16 bpp eller högre BMP: " +#~ "er stöds: %d bpp angiven" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "level ska ligga mellan 0 och 1" + +#~ msgid "init I2C" +#~ msgstr "I2C start" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Samplingens bits_per_sample matchar inte mixerns" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Samplingens kanalantal matchar inte mixerns" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Samplingens frekvens matchar inte mixerns" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Samplingens signerad/osignerad stämmer inte med mixern" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Buffertlängd måste vara en multipel av 512" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Bufferten måste vara en multipel av 512 byte" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "Antal data_pins måste vara 8 eller 16, inte %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO Init-fel %d" + +#~ msgid "can't unambiguously get sizeof scalar" +#~ msgstr "kan inte entydigt få fram storleken på skalären" + +#~ msgid "struct: can't index" +#~ msgstr "struct: kan inte indexera" + +#~ msgid "struct: index out of range" +#~ msgstr "struct: index utanför intervallet" + +#~ msgid "struct: no fields" +#~ msgstr "struct: inga fält" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "syntaxfel i uctypes deskriptor" + +#~ msgid "unary op %q not implemented" +#~ msgstr "binär op %q är inte implementerad" + #~ msgid "Name too long" #~ msgstr "Name är för långt" @@ -4714,13 +4923,13 @@ msgstr "zi måste vara i formen (n_section, 2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "Objektet '%s' stöder inte borttagning av objekt" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "Objektet '%s' är inte en iterator" #~ msgid "'%s' object is not callable" #~ msgstr "Objektet '%s' kan inte anropas" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "Objektet '%s' är inte itererable" #~ msgid "'%s' object is not subscriptable" @@ -4738,7 +4947,7 @@ msgstr "zi måste vara i formen (n_section, 2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' utanför loop" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "objektet 'coroutine\" är inte en iterator" #~ msgid "(x,y) integers required" @@ -5841,7 +6050,7 @@ msgstr "zi måste vara i formen (n_section, 2)" #~ msgid "frequency is read-only for this board" #~ msgstr "frekvens är skrivskyddad för detta kort" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "funktionen tar inte nyckelordsargument" #~ msgid "function is implemented for scalars and ndarrays only" @@ -5941,7 +6150,7 @@ msgstr "zi måste vara i formen (n_section, 2)" #~ msgid "n must be between 0, and 9" #~ msgstr "n måste vara mellan 0 och 9" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "namn återanvänt för argument" #~ msgid "no available NIC" diff --git a/locale/tr.po b/locale/tr.po index 5c62a1b0f1c65..1012dbf8b3937 100644 --- a/locale/tr.po +++ b/locale/tr.po @@ -7,15 +7,15 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2024-07-03 19:09+0000\n" -"Last-Translator: Hacı \n" +"PO-Revision-Date: 2025-06-30 16:02+0000\n" +"Last-Translator: MAE \n" "Language-Team: none\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 5.7-dev\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -80,8 +80,8 @@ msgstr " çıktı:\n" #: py/objstr.c #, c-format -msgid "%%c requires int or char" -msgstr "%%c int veya char tipine ihtiyaç duyar" +msgid "%%c needs int or char" +msgstr "" #: shared-bindings/rgbmatrix/RGBMatrix.c #, c-format @@ -91,11 +91,16 @@ msgstr "" "%d adres pinleri, %d RGB pinleri ve %d döşemeleri %d'nin yüksekliği " "gösterir, %d'nin değil" +#: py/emitinlinextensa.c +#, c-format +msgid "%d is not a multiple of %d" +msgstr "" + #: shared-bindings/microcontroller/Pin.c msgid "%q and %q contain duplicate pins" msgstr "%q ve %q yinelenen pinler içeriyor" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q ve %q farklı olmalılar" @@ -112,14 +117,21 @@ msgid "%q contains duplicate pins" msgstr "%q yinelenen pinler içeriyor" #: ports/atmel-samd/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "%q failure: %d" msgstr "%q hata: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "" #: ports/espressif/common-hal/espulp/ULP.c +#: ports/espressif/common-hal/mipidsi/Bus.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/usb_host/Port.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -127,7 +139,8 @@ msgstr "" #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/usb_host/Port.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/microcontroller/Pin.c shared-module/max3421e/Max3421E.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/microcontroller/Pin.c +#: shared-module/max3421e/Max3421E.c msgid "%q in use" msgstr "%q kullanımda" @@ -139,7 +152,9 @@ msgstr "%q indeksi aralık dışında" msgid "%q indices must be integers, not %s" msgstr "%q indeksleri integer olmalı, %s değil" -#: shared-module/bitbangio/SPI.c +#: ports/analog/common-hal/busio/SPI.c ports/analog/common-hal/busio/UART.c +#: shared-bindings/digitalio/DigitalInOutProtocol.c +#: shared-module/busdisplay/BusDisplay.c msgid "%q init failed" msgstr "%q init başarısız oldu" @@ -167,16 +182,12 @@ msgstr "%q boyutu <= %d olmalıdır" msgid "%q length must be >= %d" msgstr "%q boyutu >= %d olmalıdır" -#: py/modsys.c py/objmodule.c py/runtime.c -msgid "%q moved from %q to %q" -msgstr "" - #: py/argcheck.c msgid "%q must be %d" msgstr "%q, %d olmalıdır" -#: py/argcheck.c shared-bindings/busdisplay/BusDisplay.c -#: shared-bindings/displayio/Bitmap.c +#: ports/zephyr-cp/bindings/zephyr_display/Display.c py/argcheck.c +#: shared-bindings/busdisplay/BusDisplay.c shared-bindings/displayio/Bitmap.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-bindings/is31fl3741/FrameBuffer.c #: shared-bindings/rgbmatrix/RGBMatrix.c @@ -227,6 +238,7 @@ msgstr "" #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "" @@ -236,6 +248,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "" @@ -244,23 +257,29 @@ msgstr "" msgid "%q must be power of 2" msgstr "%q, 2'nin kuvveti olmalıdır" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' attribute" +msgstr "" + +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "%q object missing '%q' method" +msgstr "" + #: shared-bindings/wifi/Monitor.c msgid "%q out of bounds" msgstr "%q sınırların dışında" +#: ports/analog/common-hal/busio/SPI.c #: ports/atmel-samd/common-hal/pulseio/PulseIn.c #: ports/cxd56/common-hal/pulseio/PulseIn.c #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c #: ports/stm/common-hal/pulseio/PulseIn.c py/argcheck.c -#: shared-bindings/canio/Match.c shared-bindings/time/__init__.c +#: shared-bindings/bitmaptools/__init__.c shared-bindings/canio/Match.c +#: shared-bindings/time/__init__.c msgid "%q out of range" msgstr "%q aralık dışında" -#: py/objmodule.c py/runtime.c -msgid "%q renamed %q" -msgstr "" - #: py/objrange.c py/objslice.c shared-bindings/random/__init__.c msgid "%q step cannot be zero" msgstr "%q sıfır olamaz" @@ -281,7 +300,8 @@ msgstr "" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q ve %q aynı uzunlukta olmalıdır" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -310,20 +330,20 @@ msgstr "%s hatası 0x%x" msgid "'%q' argument required" msgstr "'%q' argümanı gerekli" -#: py/proto.c +#: py/proto.c shared-bindings/digitalio/DigitalInOutProtocol.c msgid "'%q' object does not support '%q'" msgstr "'%q' nesnesi '%q' öğesini desteklemiyor" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "'%q' nesnesi bir iteratör değildir" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c -msgid "'%q' object is not callable" -msgstr "'%q' nesnesi çağrılabilir değil" +msgid "'%q' object isn't callable" +msgstr "" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "'%q' nesnesi iterable değildir" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -427,6 +447,10 @@ msgstr "'data' integer tipinde argümanlara ihtiyaç duyar" msgid "'label' requires 1 argument" msgstr "'label' 1 argümana ihtiyaç duyar" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "" + #: py/compile.c msgid "'return' outside function" msgstr "fonksiyon dışında 'return'" @@ -451,6 +475,7 @@ msgstr "*x atama hedefi olmalıdır" msgid ", in %q\n" msgstr ", içinde %q\n" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c @@ -469,7 +494,7 @@ msgstr "3-argümanlı pow() desteklenmemektedir" msgid "AP could not be started" msgstr "" -#: shared-bindings/_bleio/Address.c shared-bindings/ipaddress/IPv4Address.c +#: shared-bindings/ipaddress/IPv4Address.c #, c-format msgid "Address must be %d bytes long" msgstr "Adres %d byte uzunluğunda olmalıdır" @@ -504,7 +529,8 @@ msgstr "Tüm RX FIFO'ları kullanımda" msgid "All SPI peripherals are in use" msgstr "Tüm SPI çevre birimleri kullanımda" -#: ports/espressif/common-hal/busio/UART.c ports/nordic/common-hal/busio/UART.c +#: ports/analog/common-hal/busio/UART.c ports/espressif/common-hal/busio/UART.c +#: ports/nordic/common-hal/busio/UART.c msgid "All UART peripherals are in use" msgstr "Tüm UART çevre birimleri kullanımda" @@ -546,7 +572,6 @@ msgstr "Bu pin için tüm zamanlayıcılar kullanımda" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "Tüm zamanlayıcılar kullanımda" @@ -559,6 +584,10 @@ msgstr "Halihazırda duyuruluyor." msgid "Already have all-matches listener" msgstr "Tüm eşleşmelerle eşleşen dinleyiciniz var" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -568,10 +597,11 @@ msgstr "Halihazırda çalışıyor" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "Halihazırda wifi ağları için tarama yapılıyor" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c #, c-format msgid "An error occurred while retrieving '%s':\n" msgstr "" @@ -594,6 +624,10 @@ msgstr "Dizi yarımsözcüklere sahip olmalıdır (tip 'H')" msgid "Array values should be single bytes." msgstr "Dizi değerleri tekil bytelar olmalıdır." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "" + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -603,6 +637,12 @@ msgstr "%d bloğun ayrılması girişimi" msgid "Audio conversion not implemented" msgstr "Ses dönüşümü implemente edilmedi" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c +msgid "Audio source error" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN bir şifre ile kullanılmadı" @@ -627,6 +667,7 @@ msgstr "" msgid "Baudrate not supported by peripheral" msgstr "Baudhızı, çevre birimi tarafından desteklenmiyor" +#: ports/zephyr-cp/common-hal/zephyr_display/Display.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c msgid "Below minimum frame rate" @@ -644,20 +685,17 @@ msgstr "Bitmap boyutu ve bit başına değer uyuşmalı" msgid "Boot device must be first (interface #0)." msgstr "" +#: ports/analog/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c msgid "Both RX and TX required for flow control" msgstr "Hem RX hem de TX akış kontrolü için gerekli" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c msgid "Brightness not adjustable" msgstr "Parlaklık ayarlanabilir değil" -#: shared-bindings/_bleio/UUID.c -#, c-format -msgid "Buffer + offset too small %d %d %d" -msgstr "Buffer + offset çok küçük %d %d %d" - #: ports/raspberrypi/bindings/rp2pio/StateMachine.c msgid "Buffer elements must be 4 bytes long or less" msgstr "Buffer elementleri 4 bit olmak zorunda" @@ -672,13 +710,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Mevcut arabellek boyutu %d çok büyük. En fazla %d kadar olmalı" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Arabellek boyutu 512'nin katı olmalı" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Buffer 512 bitin katı olmalı" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -700,10 +738,6 @@ msgstr "" msgid "Bus pin %d is already in use" msgstr "Veriyolu pini %d kullanımda" -#: shared-bindings/_bleio/UUID.c -msgid "Byte buffer must be 16 bytes." -msgstr "Bit buffer'ı 16bit olmalı." - #: shared-bindings/aesio/aes.c msgid "CBC blocks must be multiples of 16 bytes" msgstr "CBC blokları 16 baytın katları şeklinde olmalı" @@ -726,7 +760,7 @@ msgstr "" #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on RTC IO from deep sleep." -msgstr "" +msgstr "Sadece alarm RTC IO'yu uyandırabilir." #: ports/espressif/common-hal/alarm/pin/PinAlarm.c msgid "Can only alarm on one low pin while others alarm high from deep sleep." @@ -736,6 +770,10 @@ msgstr "" msgid "Can only alarm on two low pins from deep sleep." msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -749,7 +787,11 @@ msgstr "USB aygıtları şu an değiştirilemez" #: shared-bindings/_bleio/Adapter.c msgid "Cannot create a new Adapter; use _bleio.adapter;" -msgstr "yeni Adaptör oluşturulamadı, _bleio.adapter kullanın" +msgstr "yeni Adaptör oluşturulamadı; _bleio.adapter kullanın;" + +#: shared-module/i2cioexpander/IOExpander.c +msgid "Cannot deinitialize board IOExpander" +msgstr "" #: shared-bindings/displayio/Bitmap.c #: shared-bindings/memorymonitor/AllocationSize.c @@ -782,10 +824,11 @@ msgid "Cannot record to a file" msgstr "Dosyaya kayıt yapılamıyor" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "'/' USB ile görünür olduğunda, yeniden bağlanamaz." +msgid "Cannot remount path when visible via USB." +msgstr "" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Cannot set value when direction is input." msgstr "Yön, giriş olduğunda değer ayarlanamıyor." @@ -798,6 +841,10 @@ msgstr "RS485 modunda RTS veya CTS belirtilemez" msgid "Cannot subclass slice" msgstr "" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "" @@ -832,6 +879,14 @@ msgstr "" msgid "Coordinate arrays types have different sizes" msgstr "" +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-module/usb/core/Device.c +msgid "Could not allocate DMA capable buffer" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "Adres ayarlanamadı" @@ -844,6 +899,11 @@ msgstr "Kesinti başlatılamadı, RX kullanımda" msgid "Couldn't allocate decoder" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "" @@ -861,10 +921,6 @@ msgstr "DAC zaten kullanımda" msgid "Data 0 pin must be byte aligned" msgstr "Data 0 pini bite hizalı olmalı" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Veri öbeği, fmt yığınını takip etmelidir" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "" @@ -903,6 +959,7 @@ msgstr "Ekran 16 bitlik bir renk uzayına sahip olmalıdır." #: shared-bindings/busdisplay/BusDisplay.c #: shared-bindings/epaperdisplay/EPaperDisplay.c #: shared-bindings/framebufferio/FramebufferDisplay.c +#: shared-bindings/mipidsi/Display.c msgid "Display rotation must be in 90 degree increments" msgstr "Ekran dönüşü 90 derecelik artışlarla olmalıdır" @@ -911,6 +968,7 @@ msgid "Done" msgstr "Tamamlandı" #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Drive mode not used when direction is input." msgstr "Yön, giriş olduğunda sürüş modu kullanılmaz." @@ -922,8 +980,17 @@ msgstr "Yukarıdaki hatanın işlenmesi sırasında başka bir hata oluştu:" msgid "ECB only operates on 16 bytes at a time" msgstr "ECB aynı anda yalnızca 16 baytla çalışır" +#: py/asmxtensa.c +msgid "ERROR: %q %q not word-aligned" +msgstr "" + +#: py/asmxtensa.c +msgid "ERROR: xtensa %q out of range" +msgstr "" + #: ports/espressif/common-hal/busio/SPI.c #: ports/espressif/common-hal/canio/CAN.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "ESP-IDF memory allocation failed" msgstr "" @@ -970,7 +1037,7 @@ msgid "" "Failed to add service TXT record; non-string or bytes found in txt_records" msgstr "" -#: shared-module/rgbmatrix/RGBMatrix.c +#: ports/analog/common-hal/busio/UART.c shared-module/rgbmatrix/RGBMatrix.c msgid "Failed to allocate %q buffer" msgstr "" @@ -988,22 +1055,60 @@ msgstr "" #: ports/espressif/common-hal/_bleio/Adapter.c #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: internal error" msgstr "Bağlantı kurulamadı: internal error" #: ports/nordic/common-hal/_bleio/Adapter.c +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c msgid "Failed to connect: timeout" msgstr "Bağlantı kurulamadı: timeout" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "MP3 dosyası ayrıştırılamadı" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Muteks serbest bırakılamadı, err 0x%04x" +#: ports/analog/common-hal/busio/SPI.c +msgid "Failed to set SPI Clock Mode" +msgstr "" + +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Dahili flaş yazılamadı." @@ -1012,12 +1117,13 @@ msgstr "Dahili flaş yazılamadı." msgid "File exists" msgstr "Dosya var" -#: shared-module/os/getenv.c +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c msgid "File not found" msgstr "" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "Filtreler çok karmaşık" @@ -1044,7 +1150,7 @@ msgid "For RGB colorspaces, input bitmap must have 16 bits per pixel" msgstr "" "RGB renk uzayı için, giriş bitmap'i piksel başına 16 bayta sahip olmalıdır" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Format desteklenmiyor" @@ -1068,6 +1174,7 @@ msgstr "GNSS init" msgid "Generic Failure" msgstr "" +#: ports/zephyr-cp/bindings/zephyr_display/Display.c #: shared-bindings/framebufferio/FramebufferDisplay.c #: shared-module/busdisplay/BusDisplay.c #: shared-module/framebufferio/FramebufferDisplay.c @@ -1154,6 +1261,7 @@ msgid "Insufficient stream input buffer" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "Arayüz başlatılmalıdır" @@ -1165,7 +1273,8 @@ msgstr "Dahili ses arabelleği çok küçük" msgid "Internal define error" msgstr "Dahili tanımlama hatası" -#: shared-bindings/pwmio/PWMOut.c shared-module/os/getenv.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c shared-bindings/pwmio/PWMOut.c +#: supervisor/shared/settings.c msgid "Internal error" msgstr "Dahili hata" @@ -1199,18 +1308,29 @@ msgstr "" msgid "Interrupted by output function" msgstr "" +#: ports/analog/common-hal/busio/UART.c +#: ports/analog/peripherals/max32690/max32_i2c.c +#: ports/analog/peripherals/max32690/max32_spi.c +#: ports/analog/peripherals/max32690/max32_uart.c +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c +#: ports/espressif/common-hal/mipidsi/Display.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c -#: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/epaperdisplay/EPaperDisplay.c +#: shared-bindings/i2cioexpander/IOPin.c shared-bindings/mipidsi/Display.c +#: shared-bindings/pwmio/PWMOut.c shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "Geçersiz %q" +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c #: shared-module/aurora_epaper/aurora_framebuffer.c msgid "Invalid %q and %q" @@ -1240,6 +1360,14 @@ msgstr "Geçersiz BSSID" msgid "Invalid MAC address" msgstr "Geçersiz MAC adresi" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "" + +#: ports/zephyr-cp/common-hal/_bleio/Adapter.c +msgid "Invalid advertising data" +msgstr "" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Geçersiz argüman" @@ -1249,17 +1377,12 @@ msgstr "Geçersiz argüman" msgid "Invalid bits per value" msgstr "Geçersiz bit başına değer" -#: shared-module/os/getenv.c -#, c-format -msgid "Invalid byte %.*s" -msgstr "" - #: ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c #, c-format msgid "Invalid data_pins[%d]" msgstr "Geçersiz veri_pini [%d]" -#: shared-module/msgpack/__init__.c +#: shared-module/msgpack/__init__.c supervisor/shared/settings.c msgid "Invalid format" msgstr "" @@ -1272,6 +1395,7 @@ msgid "Invalid hex password" msgstr "" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "Geçersiz multicast MAC adresi" @@ -1283,11 +1407,13 @@ msgstr "Geçersiz boyut" msgid "Invalid socket for TLS" msgstr "TLS için geçersiz soket" +#: ports/analog/common-hal/busio/SPI.c #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "Geçersiz durum" -#: shared-module/os/getenv.c +#: supervisor/shared/settings.c msgid "Invalid unicode escape" msgstr "" @@ -1295,10 +1421,6 @@ msgstr "" msgid "Key must be 16, 24, or 32 bytes long" msgstr "Anahtar 16, 24 veya 32 bayt uzunluğunda olmalıdır" -#: shared-module/os/getenv.c -msgid "Key not found" -msgstr "" - #: shared-module/is31fl3741/FrameBuffer.c msgid "LED mappings must match display size" msgstr "LED eşlemeleri ekran boyutuyla eşleşmelidir" @@ -1324,13 +1446,23 @@ msgid "MAC address was invalid" msgstr "MAC adresi geçersiz" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "Map tuple olmalıdır" +#: py/persistentcode.c +msgid "MicroPython .mpy file; use CircuitPython mpy-cross" +msgstr "" + #: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/rp2pio/StateMachine.c msgid "Mismatched data size" @@ -1419,7 +1551,7 @@ msgstr "" #: ports/stm/common-hal/busio/UART.c shared-bindings/fourwire/FourWire.c #: shared-bindings/i2cdisplaybus/I2CDisplayBus.c #: shared-bindings/paralleldisplaybus/ParallelBus.c -#: shared-module/bitbangio/SPI.c +#: shared-bindings/qspibus/QSPIBus.c shared-module/bitbangio/SPI.c msgid "No %q pin" msgstr "%q pini yok" @@ -1437,6 +1569,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "No DMA channel found" msgstr "" @@ -1512,6 +1645,10 @@ msgstr "" msgid "No pulldown on pin; 1Mohm recommended" msgstr "" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "" + #: py/moderrno.c msgid "No space left on device" msgstr "" @@ -1547,17 +1684,14 @@ msgid "Not connected" msgstr "" #: shared-bindings/audiobusio/I2SOut.c shared-bindings/audioio/AudioOut.c -#: shared-bindings/audiopwmio/PWMAudioOut.c +#: shared-bindings/audiopwmio/PWMAudioOut.c shared-bindings/mcp4822/MCP4822.c msgid "Not playing" msgstr "" -#: shared-module/jpegio/JpegDecoder.c -msgid "Not supported JPEG standard" -msgstr "" - #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" +msgid "Number of data_pins must be %d or %d, not %d" msgstr "" #: shared-bindings/util.c @@ -1610,13 +1744,6 @@ msgstr "" msgid "Only int or string supported for ip" msgstr "" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "" @@ -1654,6 +1781,7 @@ msgid "Operation or feature not supported" msgstr "" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/espressif/common-hal/qspibus/QSPIBus.c msgid "Operation timed out" msgstr "" @@ -1667,6 +1795,7 @@ msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "" @@ -1686,6 +1815,10 @@ msgstr "" msgid "PWM slice channel A already in use" msgstr "" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "" @@ -1786,7 +1919,12 @@ msgstr "" msgid "Program too long" msgstr "" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "" + #: shared-bindings/digitalio/DigitalInOut.c +#: shared-bindings/i2cioexpander/IOPin.c msgid "Pull not used when direction is output." msgstr "" @@ -1806,10 +1944,31 @@ msgstr "" msgid "RNG Init Error" msgstr "" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" -msgstr "" +msgstr "RS485" #: ports/espressif/common-hal/busio/UART.c #: ports/mimxrt10xx/common-hal/busio/UART.c @@ -1884,9 +2043,10 @@ msgstr "" msgid "SDIO GetCardInfo Error %d" msgstr "" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" +msgid "SDIO Init Error %x" msgstr "" #: ports/espressif/common-hal/busio/SPI.c @@ -1897,6 +2057,10 @@ msgstr "" msgid "SPI init error" msgstr "" +#: ports/analog/common-hal/busio/SPI.c +msgid "SPI needs MOSI, MISO, and SCK" +msgstr "" + #: ports/raspberrypi/common-hal/busio/SPI.c msgid "SPI peripheral in use" msgstr "" @@ -1936,6 +2100,7 @@ msgstr "" #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "" @@ -1944,6 +2109,10 @@ msgstr "" msgid "SocketPool can only be used with wifi.radio" msgstr "" +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c +msgid "SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork" +msgstr "" + #: shared-bindings/aesio/aes.c msgid "Source and destination buffers must be the same length" msgstr "" @@ -1980,20 +2149,8 @@ msgstr "" msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" msgstr "" #: supervisor/shared/safe_mode.c @@ -2014,7 +2171,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "" @@ -2022,6 +2181,10 @@ msgstr "" msgid "Tile width must exactly divide bitmap width" msgstr "" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "" @@ -2032,11 +2195,16 @@ msgstr "" msgid "Timeout is too long: Maximum timeout length is %d seconds" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "Timeout must be < 100 seconds" +msgstr "" + #: ports/atmel-samd/common-hal/audiobusio/I2SOut.c msgid "Too many channels in sample" msgstr "" #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Too many channels in sample." msgstr "" @@ -2075,6 +2243,10 @@ msgstr "" msgid "UART init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART needs TX & RX" +msgstr "" + #: ports/raspberrypi/common-hal/busio/UART.c msgid "UART peripheral in use" msgstr "" @@ -2083,13 +2255,21 @@ msgstr "" msgid "UART re-init" msgstr "" +#: ports/analog/common-hal/busio/UART.c +msgid "UART read error" +msgstr "" + +#: ports/analog/common-hal/busio/UART.c +msgid "UART transaction timeout" +msgstr "" + #: ports/stm/common-hal/busio/UART.c msgid "UART write" msgstr "" #: main.c msgid "UID:" -msgstr "" +msgstr "UID:" #: shared-module/usb_hid/Device.c msgid "USB busy" @@ -2107,10 +2287,6 @@ msgstr "" msgid "USB error" msgstr "" -#: shared-bindings/_bleio/UUID.c -msgid "UUID integer value must be 0-0xffff" -msgstr "" - #: shared-bindings/_bleio/UUID.c msgid "UUID string not 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'" msgstr "" @@ -2127,6 +2303,7 @@ msgstr "" #: ports/atmel-samd/common-hal/audioio/AudioOut.c #: ports/raspberrypi/common-hal/audiobusio/I2SOut.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +#: ports/raspberrypi/common-hal/mcp4822/MCP4822.c msgid "Unable to allocate buffers for signed conversion" msgstr "" @@ -2135,6 +2312,7 @@ msgid "Unable to allocate to the heap." msgstr "" #: ports/espressif/common-hal/busio/I2C.c +#: ports/espressif/common-hal/busio/SPI.c msgid "Unable to create lock" msgstr "" @@ -2152,6 +2330,10 @@ msgstr "" msgid "Unable to read color palette data" msgstr "" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2236,6 +2418,10 @@ msgid "" "declined or ignored." msgstr "" +#: shared-module/jpegio/JpegDecoder.c +msgid "Unsupported JPEG (may be progressive)" +msgstr "" + #: shared-bindings/bitmaptools/__init__.c msgid "Unsupported colorspace" msgstr "" @@ -2244,15 +2430,12 @@ msgstr "" msgid "Unsupported display bus type" msgstr "" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "" @@ -2261,15 +2444,20 @@ msgstr "" msgid "Update failed" msgstr "" +#: ports/zephyr-cp/common-hal/audiobusio/I2SOut.c +#: ports/zephyr-cp/common-hal/busio/I2C.c +#: ports/zephyr-cp/common-hal/busio/SPI.c +#: ports/zephyr-cp/common-hal/busio/UART.c +msgid "Use device tree to define %q devices" +msgstr "" + #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2303,10 +2491,12 @@ msgstr "" #: supervisor/shared/web_workflow/web_workflow.c msgid "Wi-Fi: " -msgstr "" +msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" msgstr "" #: main.c @@ -2329,6 +2519,7 @@ msgstr "" #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "" @@ -2342,6 +2533,7 @@ msgstr "" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "" @@ -2398,10 +2590,18 @@ msgstr "" msgid "a bytes-like object is required" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "address out of range" +msgstr "" + #: shared-bindings/i2ctarget/I2CTarget.c msgid "addresses is empty" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "" + #: py/compile.c msgid "annotation must be an identifier" msgstr "" @@ -2426,6 +2626,10 @@ msgstr "" msgid "argsort is not implemented for flattened arrays" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "" + #: py/compile.c msgid "argument name reused" msgstr "" @@ -2456,10 +2660,6 @@ msgstr "" msgid "array/bytes required on right side" msgstr "" -#: py/asmxtensa.c -msgid "asm overflow" -msgstr "" - #: py/compile.c msgid "async for/with outside async function" msgstr "" @@ -2476,6 +2676,10 @@ msgstr "" msgid "attributes not supported" msgstr "" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "" @@ -2512,6 +2716,10 @@ msgstr "" msgid "binary op %q not implemented" msgstr "" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "" + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "" @@ -2524,6 +2732,15 @@ msgstr "" msgid "bits must be 32 or less" msgstr "" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "" @@ -2581,6 +2798,10 @@ msgstr "" msgid "can only have one parent" msgstr "" +#: py/emitinlinerv32.c +msgid "can only have up to 4 parameters for RV32 assembly" +msgstr "" + #: py/emitinlinethumb.c msgid "can only have up to 4 parameters to Thumb assembly" msgstr "" @@ -2605,7 +2826,7 @@ msgstr "" msgid "can't cancel self" msgstr "" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "" @@ -2648,6 +2869,14 @@ msgstr "" msgid "can't convert to str implicitly" msgstr "" +#: py/objtype.c +msgid "can't create '%q' instances" +msgstr "" + +#: py/objtype.c +msgid "can't create instance" +msgstr "" + #: py/compile.c msgid "can't declare nonlocal in outer code" msgstr "" @@ -2660,6 +2889,10 @@ msgstr "" msgid "can't do binary op between '%q' and '%q'" msgstr "" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "" @@ -2722,10 +2955,6 @@ msgstr "" msgid "can't truncate-divide a complex number" msgstr "" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "" - #: extmod/modasyncio.c msgid "can't wait" msgstr "" @@ -2746,18 +2975,14 @@ msgstr "" msgid "cannot convert complex type" msgstr "" -#: py/objtype.c -msgid "cannot create '%q' instances" -msgstr "" - -#: py/objtype.c -msgid "cannot create instance" -msgstr "" - #: extmod/ulab/code/ndarray.c msgid "cannot delete array elements" msgstr "" +#: py/compile.c +msgid "cannot emit native code for this architecture" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "cannot reshape array" msgstr "" @@ -2912,7 +3137,7 @@ msgstr "" msgid "div/mod not implemented for uint" msgstr "" -#: extmod/ulab/code/numpy/create.c +#: extmod/ulab/code/numpy/create.c py/objint_longlong.c py/objint_mpz.c msgid "divide by zero" msgstr "" @@ -3011,10 +3236,6 @@ msgstr "" msgid "file write is not available" msgstr "" -#: shared-bindings/storage/__init__.c -msgid "filesystem must provide mount method" -msgstr "" - #: extmod/ulab/code/numpy/vector.c msgid "first argument must be a callable" msgstr "" @@ -3055,16 +3276,20 @@ msgstr "" msgid "float unsupported" msgstr "" -#: shared-bindings/_stage/Text.c -msgid "font must be 2048 bytes long" -msgstr "" - #: extmod/moddeflate.c msgid "format" msgstr "" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" +msgstr "" + +#: py/objstr.c +msgid "format string didn't convert all arguments" +msgstr "" + +#: py/objstr.c +msgid "format string needs more arguments" msgstr "" #: py/objdeque.c @@ -3114,7 +3339,8 @@ msgstr "" msgid "function missing required positional argument #%d" msgstr "" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "" @@ -3131,10 +3357,6 @@ msgstr "" msgid "generator raised StopIteration" msgstr "" -#: shared-bindings/_stage/Layer.c -msgid "graphic must be 2048 bytes long" -msgstr "" - #: extmod/modhashlib.c msgid "hash is final" msgstr "" @@ -3197,18 +3419,10 @@ msgstr "" msgid "indices must be integers, slices, or Boolean lists" msgstr "" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "" -#: shared-bindings/_bleio/Characteristic.c shared-bindings/_bleio/Descriptor.c -msgid "initial_value length is wrong" -msgstr "" - #: py/compile.c msgid "inline assembler must be a function" msgstr "" @@ -3266,7 +3480,7 @@ msgstr "" msgid "input must be a dense ndarray" msgstr "" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "" @@ -3299,6 +3513,10 @@ msgstr "" msgid "interval must be in range %s-%s" msgstr "" +#: py/emitinlinerv32.c +msgid "invalid RV32 instruction '%q'" +msgstr "" + #: py/compile.c msgid "invalid arch" msgstr "" @@ -3395,10 +3613,6 @@ msgstr "" msgid "label redefined" msgstr "" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "" @@ -3452,7 +3666,7 @@ msgstr "" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "" @@ -3497,6 +3711,10 @@ msgstr "" msgid "mode must be complete, or reduced" msgstr "" +#: py/runtime.c +msgid "module '%q' has no attribute '%q'" +msgstr "" + #: py/builtinimport.c msgid "module not found" msgstr "" @@ -3530,7 +3748,7 @@ msgid "must use keyword argument for key function" msgstr "" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "" #: py/runtime.c @@ -3545,10 +3763,6 @@ msgstr "" msgid "native code in .mpy unsupported" msgstr "" -#: py/asmthumb.c -msgid "native method too big" -msgstr "" - #: py/emitnative.c msgid "native yield" msgstr "" @@ -3570,7 +3784,7 @@ msgstr "" msgid "negative power with no float support" msgstr "" -#: py/objint_mpz.c py/runtime.c +#: py/objint_longlong.c py/objint_mpz.c py/runtime.c msgid "negative shift count" msgstr "" @@ -3594,7 +3808,7 @@ msgstr "" msgid "no default packer" msgstr "" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "" @@ -3620,7 +3834,7 @@ msgid "non-default argument follows default argument" msgstr "" #: py/objstr.c -msgid "non-hex digit found" +msgid "non-hex digit" msgstr "" #: ports/nordic/common-hal/_bleio/Adapter.c @@ -3639,14 +3853,6 @@ msgstr "" msgid "not a constant" msgstr "" -#: py/objstr.c -msgid "not all arguments converted during string formatting" -msgstr "" - -#: py/objstr.c -msgid "not enough arguments for format string" -msgstr "" - #: extmod/ulab/code/numpy/carray/carray_tools.c msgid "not implemented for complex dtype" msgstr "" @@ -3655,6 +3861,10 @@ msgstr "" msgid "not supported for input types" msgstr "" +#: shared-bindings/i2cioexpander/IOExpander.c +msgid "num_pins must be 8 or 16" +msgstr "" + #: extmod/ulab/code/numpy/create.c msgid "number of points must be at least 2" msgstr "" @@ -3668,6 +3878,10 @@ msgstr "" msgid "object '%s' isn't a tuple or list" msgstr "" +#: shared-bindings/digitalio/DigitalInOutProtocol.c +msgid "object does not support DigitalInOut protocol" +msgstr "" + #: py/obj.c msgid "object doesn't support item assignment" msgstr "" @@ -3709,10 +3923,6 @@ msgstr "" msgid "object with buffer protocol required" msgstr "" -#: py/objstr.c -msgid "odd-length string" -msgstr "" - #: supervisor/shared/web_workflow/web_workflow.c msgid "off" msgstr "" @@ -3761,6 +3971,30 @@ msgstr "" msgid "opcode" msgstr "" +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: expecting %q" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: must not be zero" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: out of range" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: undefined label '%q'" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q' argument %d: unknown register" +msgstr "" + +#: py/emitinlinerv32.c +msgid "opcode '%q': expecting %d arguments" +msgstr "" + #: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/bitwise.c #: extmod/ulab/code/numpy/compare.c extmod/ulab/code/numpy/vector.c msgid "operands could not be broadcast together" @@ -3803,6 +4037,10 @@ msgstr "" msgid "out array is too small" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "" @@ -3827,6 +4065,14 @@ msgstr "" msgid "out of range of target" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "" @@ -3836,8 +4082,8 @@ msgstr "" msgid "pack expected %d items for packing (got %d)" msgstr "" -#: shared-bindings/_stage/Layer.c shared-bindings/_stage/Text.c -msgid "palette must be 32 bytes long" +#: py/emitinlinerv32.c +msgid "parameters must be registers in sequence a0 to a3" msgstr "" #: py/emitinlinextensa.c @@ -3889,14 +4135,14 @@ msgstr "" msgid "pull masks conflict with direction masks" msgstr "" -#: py/parse.c -msgid "raw f-strings are not supported" -msgstr "" - #: extmod/ulab/code/numpy/fft/fft_tools.c msgid "real and imaginary parts must be of equal length" msgstr "" +#: extmod/modre.c +msgid "regex too complex" +msgstr "" + #: py/builtinimport.c msgid "relative import" msgstr "" @@ -3906,6 +4152,10 @@ msgstr "" msgid "requested length %d but object has length %d" msgstr "" +#: py/objint_longlong.c py/parsenum.c +msgid "result overflows long long storage" +msgstr "" + #: extmod/ulab/code/ndarray_operators.c msgid "results cannot be cast to specified type" msgstr "" @@ -3934,6 +4184,10 @@ msgstr "" #: py/objstr.c msgid "rsplit(None,n)" +msgstr "rsplit(None,n)" + +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" msgstr "" #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -3953,6 +4207,10 @@ msgstr "" msgid "set unsupported" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "" @@ -3973,6 +4231,10 @@ msgstr "" msgid "size is defined for ndarrays only" msgstr "" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "" + #: py/nativeglue.c msgid "slice unsupported" msgstr "" @@ -4021,10 +4283,6 @@ msgstr "" msgid "splitting with sub-captures" msgstr "" -#: py/objstr.c -msgid "start/end indices" -msgstr "" - #: shared-bindings/random/__init__.c msgid "stop not reachable from start" msgstr "" @@ -4046,18 +4304,6 @@ msgstr "" msgid "string indices must be integers, not %s" msgstr "" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "" @@ -4070,10 +4316,6 @@ msgstr "" msgid "syntax error in JSON" msgstr "" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "" @@ -4163,11 +4405,11 @@ msgid "tx and rx cannot both be None" msgstr "" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "" #: py/runtime.c @@ -4178,14 +4420,6 @@ msgstr "" msgid "type takes 1 or 3 arguments" msgstr "" -#: py/objint_longlong.c -msgid "ulonglong too large" -msgstr "" - -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "" - #: py/parse.c msgid "unexpected indent" msgstr "" @@ -4233,7 +4467,9 @@ msgstr "" msgid "unreadable attribute" msgstr "" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "" @@ -4311,11 +4547,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "" @@ -4378,6 +4609,32 @@ msgstr "" msgid "zi must be of shape (n_section, 2)" msgstr "" +#, c-format +#~ msgid "Buffer + offset too small %d %d %d" +#~ msgstr "Buffer + offset çok küçük %d %d %d" + +#~ msgid "Byte buffer must be 16 bytes." +#~ msgstr "Bit buffer'ı 16bit olmalı." + +#, c-format +#~ msgid "%%c requires int or char" +#~ msgstr "%%c int veya char tipine ihtiyaç duyar" + +#~ msgid "'%q' object is not callable" +#~ msgstr "'%q' nesnesi çağrılabilir değil" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "'/' USB ile görünür olduğunda, yeniden bağlanamaz." + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Veri öbeği, fmt yığınını takip etmelidir" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Arabellek boyutu 512'nin katı olmalı" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Buffer 512 bitin katı olmalı" + #~ msgid "Name too long" #~ msgstr "İsim çok uzun" @@ -4500,7 +4757,7 @@ msgstr "" #~ msgid "'continue' outside loop" #~ msgstr "döngü dışında 'continue'" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "'coroutine' nesnesi bir iteratör değildir" #~ msgid "(x,y) integers required" @@ -4598,8 +4855,8 @@ msgstr "" #~ msgstr "IV %d bayt uzunluğunda olmalı" #~ msgid "" -#~ "Incompatible .mpy file. Please update all .mpy files. See http://adafru." -#~ "it/mpy-update for more info." +#~ "Incompatible .mpy file. Please update all .mpy files. See http://" +#~ "adafru.it/mpy-update for more info." #~ msgstr "" #~ "Uyumsuz .mpy dosyası. Lütfen tüm .mpy dosyalarını güncelleyin. Daha fazla " #~ "bilgi için http://adafru.it/mpy-update ." diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index 664855ee98a7f..f3f9483cc4c9a 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2021-01-04 12:55-0600\n" -"PO-Revision-Date: 2024-08-19 18:09+0000\n" +"PO-Revision-Date: 2025-07-15 00:01+0000\n" "Last-Translator: hexthat \n" "Language-Team: Chinese Hanyu Pinyin\n" "Language: zh_Latn_pinyin\n" @@ -15,7 +15,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Weblate 5.7\n" +"X-Generator: Weblate 5.13-dev\n" #: main.c msgid "" @@ -96,7 +96,7 @@ msgstr "" msgid "%q and %q contain duplicate pins" msgstr "%q hé %q bāo hán chóng fù yǐn jiǎo" -#: ports/atmel-samd/common-hal/audioio/AudioOut.c +#: shared-bindings/audioio/AudioOut.c msgid "%q and %q must be different" msgstr "%q hé %q bìxū bùtóng" @@ -116,7 +116,11 @@ msgstr "%q bāo hán chóng fù de yǐn jiǎo" msgid "%q failure: %d" msgstr "%q Shībài: %d" -#: py/argcheck.c +#: shared-module/audiodelays/MultiTapDelay.c +msgid "%q in %q must be of type %q or %q, not %q" +msgstr "%q zhōngde %q bìxū shì %q huò %q lèixíng, érbùshì %q" + +#: py/argcheck.c shared-module/audiofilters/Filter.c msgid "%q in %q must be of type %q, not %q" msgstr "%q zhōng de %q bì xū shì %q lèi xíng, ér bù shì %q" @@ -168,7 +172,7 @@ msgstr "%q chángdù bìxū <= %d" msgid "%q length must be >= %d" msgstr "%q chángdù bìxū >= %d" -#: py/modsys.c py/objmodule.c py/runtime.c +#: py/modsys.c py/runtime.c msgid "%q moved from %q to %q" msgstr "%q cóng %q yídòngdào %q" @@ -229,6 +233,7 @@ msgstr "%q bìxū shì 8 debèishù." #: ports/raspberrypi/bindings/cyw43/__init__.c py/argcheck.c py/objexcept.c #: shared-bindings/bitmapfilter/__init__.c shared-bindings/canio/CAN.c #: shared-bindings/digitalio/Pull.c shared-bindings/supervisor/__init__.c +#: shared-module/audiofilters/Filter.c shared-module/displayio/__init__.c #: shared-module/synthio/Synthesizer.c msgid "%q must be of type %q or %q, not %q" msgstr "%q de lèi xíng bì xū shì %q huò %q, ér bù shì %q" @@ -238,6 +243,7 @@ msgid "%q must be of type %q, %q, or %q, not %q" msgstr "%q bìxūshì %q, %q huò %q lèixíng, érbùshì %q" #: py/argcheck.c py/runtime.c shared-bindings/bitmapfilter/__init__.c +#: shared-module/audiodelays/MultiTapDelay.c shared-module/synthio/Note.c #: shared-module/synthio/__init__.c msgid "%q must be of type %q, not %q" msgstr "%q de lèi xíng bì xū shì %q, ér bù shì %q" @@ -283,7 +289,8 @@ msgstr "búdài %q() de %q()" msgid "%q, %q, and %q must all be the same length" msgstr "%q, %q, hé %q bì xū cháng dù xiāng tóng" -#: py/objint.c shared-bindings/storage/__init__.c +#: py/objint.c shared-bindings/_bleio/Connection.c +#: shared-bindings/storage/__init__.c msgid "%q=%q" msgstr "%q=%q" @@ -317,7 +324,7 @@ msgid "'%q' object does not support '%q'" msgstr "'%q' duì xiàng bù zhī chí '%q'" #: py/runtime.c -msgid "'%q' object is not an iterator" +msgid "'%q' object isn't an iterator" msgstr "%q' duìxiàng bùshì yígè diédàiqì" #: py/objtype.c py/runtime.c shared-module/atexit/__init__.c @@ -325,7 +332,7 @@ msgid "'%q' object is not callable" msgstr "%q' duìxiàng bù kě bèi diàoyòng" #: py/runtime.c -msgid "'%q' object is not iterable" +msgid "'%q' object isn't iterable" msgstr "%q' duìxiàng bù kě yòngyú diédài" #: py/emitinlinethumb.c py/emitinlinextensa.c @@ -429,6 +436,10 @@ msgstr "'data' xūyào zhěngshù cānshù" msgid "'label' requires 1 argument" msgstr "'label' xūyào 1 gè cānshù" +#: py/emitnative.c +msgid "'not' not implemented" +msgstr "'not' wèi shíxiàn" + #: py/compile.c msgid "'return' outside function" msgstr "'return' wèiyú hánshù zhīwài" @@ -548,7 +559,6 @@ msgstr "cǐ yǐnjiǎo de suǒyǒu jìshíqì dōu zài shǐyòng zhōng" #: ports/nordic/common-hal/pulseio/PulseIn.c #: ports/nordic/peripherals/nrf/timers.c #: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c -#: ports/stm/peripherals/timers.c msgid "All timers in use" msgstr "suǒyǒu jìshí qì dōu zài shǐyòng zhōng" @@ -561,6 +571,10 @@ msgstr "Mùqián zhèngzài guǎngbō." msgid "Already have all-matches listener" msgstr "yǐjīng yǒu all-matches jiāntīng qì" +#: ports/espressif/common-hal/_bleio/__init__.c +msgid "Already in progress" +msgstr "yǐzài jìnxíng zhōng" + #: ports/espressif/bindings/espnow/ESPNow.c #: ports/espressif/common-hal/espulp/ULP.c #: shared-module/memorymonitor/AllocationAlarm.c @@ -570,6 +584,7 @@ msgstr "yǐjīng zài yùnxíng" #: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Already scanning for wifi networks" msgstr "yǐjīng zài sǎomiáo WIFI wǎngluò" @@ -596,6 +611,10 @@ msgstr "Shùzǔ bìxū bāohán halfwords (type 'H')" msgid "Array values should be single bytes." msgstr "shùzǔ de zhí yīnggāi shì dān'gè zìjié." +#: ports/atmel-samd/common-hal/spitarget/SPITarget.c +msgid "Async SPI transfer in progress on this bus, keep awaiting." +msgstr "zài zhè gè qì chē shàng, jì xù děng." + #: shared-module/memorymonitor/AllocationAlarm.c #, c-format msgid "Attempt to allocate %d blocks" @@ -605,6 +624,11 @@ msgstr "shìtú fēnpèi %d blocks" msgid "Audio conversion not implemented" msgstr "yīnpín zhuǎnhuàn wèi bèi shíxiàn" +#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c +#: ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +msgid "Audio source error" +msgstr "yīnpín yuán cuòwù" + #: shared-bindings/wifi/Radio.c msgid "AuthMode.OPEN is not used with password" msgstr "AuthMode.OPEN wèi shǐyòng mìmǎ" @@ -674,13 +698,13 @@ msgid "Buffer length %d too big. It must be less than %d" msgstr "Huǎnchōng qū chángdù%d tài dà. Tā bìxū xiǎoyú%d" #: ports/atmel-samd/common-hal/sdioio/SDCard.c -#: ports/cxd56/common-hal/sdioio/SDCard.c shared-module/sdcardio/SDCard.c -msgid "Buffer length must be a multiple of 512" -msgstr "Huǎnchōngqū chángdù bìxū wéi 512 de bèishù" - +#: ports/cxd56/common-hal/sdioio/SDCard.c +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c shared-bindings/floppyio/__init__.c -msgid "Buffer must be a multiple of 512 bytes" -msgstr "Huǎnchōngqū bìxū shì 512 zìjié de bèishù" +#: shared-module/sdcardio/SDCard.c +#, c-format +msgid "Buffer must be a multiple of %d bytes" +msgstr "huǎnchōngqū bìxū shì %d zìjié de bèishù" #: shared-bindings/_bleio/PacketBuffer.c #, c-format @@ -741,6 +765,10 @@ msgid "Can only alarm on two low pins from deep sleep." msgstr "" "Zhǐ néng cóng shēndù shuìmián zhōng de liǎng gè dī yǐn jiǎo shàng bàojǐng." +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Can't construct AudioOut because continuous channel already open" +msgstr "wúfǎ gòuzào AudioOut, yīnwéi liánxù tōngdào yǐ dǎkāi" + #: ports/espressif/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Characteristic.c msgid "Can't set CCCD on local Characteristic" @@ -786,8 +814,8 @@ msgid "Cannot record to a file" msgstr "Wúfǎ jìlù dào wénjiàn" #: shared-module/storage/__init__.c -msgid "Cannot remount '/' when visible via USB." -msgstr "tōngguò USB kějiàn shí wúfǎ chóngxīn ānzhuāng '/'." +msgid "Cannot remount path when visible via USB." +msgstr "tōngguò USB kějiàn shí wúfǎ chóngxīn guàzǎi lùjìng." #: shared-bindings/digitalio/DigitalInOut.c msgid "Cannot set value when direction is input." @@ -802,6 +830,10 @@ msgstr "wúfǎ zài RS485 móshì xià zhǐdìng RTS huò CTS" msgid "Cannot subclass slice" msgstr "bùnéng zǐlèihuà qiēpiàn" +#: ports/raspberrypi/common-hal/rp2pio/StateMachine.c +msgid "Cannot use GPIO0..15 together with GPIO32..47" +msgstr "wúfǎ shǐyòng GPIO0..15 liántóng GPIO32..47" + #: ports/nordic/common-hal/alarm/pin/PinAlarm.c msgid "Cannot wake on pin edge, only level" msgstr "wúfǎ shǐyòng biānyuán huànxǐng, zhǐnéng shǐyòng diànpíng" @@ -836,6 +868,10 @@ msgstr "zuòbiāo shùzǔ jùyǒu bùtóng de chángdù" msgid "Coordinate arrays types have different sizes" msgstr "zuòbiāo shùzǔ lèixíng jùyǒu bùtóng de dàxiǎo" +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "Could not publish to ROS topic" +msgstr "wúfǎ fābù dào ROS zhǔtí" + #: shared-bindings/_bleio/Adapter.c msgid "Could not set address" msgstr "wúfǎ shèzhì dìzhǐ" @@ -848,6 +884,11 @@ msgstr "Wúfǎ qǐdòng zhōngduàn,RX máng" msgid "Couldn't allocate decoder" msgstr "wúfǎ fēnpèi jiěmǎ qì" +#: ports/espressif/common-hal/rclcpy/__init__.c +#, c-format +msgid "Critical ROS failure during soft reboot, reset required: %d" +msgstr "ruǎn chóngqǐ qījiān fāshēng guānjiàn de ROS gùzhàng, xūyàozhòngzhì: %d" + #: ports/stm/common-hal/analogio/AnalogOut.c msgid "DAC Channel Init Error" msgstr "DAC tōngdào chūshǐhuà cuòwù" @@ -865,10 +906,6 @@ msgstr "DAC zhèngzài bèi shǐyòng" msgid "Data 0 pin must be byte aligned" msgstr "shù jù 0 yǐn jiǎo bì xū shì zì jié duì qí de" -#: shared-module/audiocore/WaveFile.c -msgid "Data chunk must follow fmt chunk" -msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" - #: shared-module/jpegio/JpegDecoder.c msgid "Data format error (may be broken data)" msgstr "shùjù géshì cuòwù (kěnéngshì shùjù sǔnhuài)" @@ -1003,15 +1040,47 @@ msgstr "Liánjiē shībài: Nèibù cuòwù" msgid "Failed to connect: timeout" msgstr "Liánjiē shībài: Chāoshí" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid arg" +msgstr "Wúfǎ chuàngjiàn liánxù tōngdào: Cānshù wúxiào" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: invalid state" +msgstr "Wúfǎ chuàngjiàn liánxù tōngdào: Zhuàngtài wúxiào" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: no mem" +msgstr "Wúfǎ chuàngjiàn liánxù tōngdào: Wú nèicún" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to create continuous channels: not found" +msgstr "Wúfǎ chuàngjiàn liánxù tōngdào: Wèi zhǎodào" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to enable continuous" +msgstr "Wúfǎ qǐyòng liánxù" + #: shared-module/audiomp3/MP3Decoder.c msgid "Failed to parse MP3 file" msgstr "Wúfǎ jiěxī MP3 wénjiàn" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to register continuous events callback" +msgstr "Liánxù shìjiàn huítiáo zhùcè shībài" + #: ports/nordic/sd_mutex.c #, c-format msgid "Failed to release mutex, err 0x%04x" msgstr "Wúfǎ shìfàng mutex, err 0x%04x" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "Failed to set hostname" +msgstr "wúfǎ shèzhì zhǔjīmíng" + +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "Failed to start async audio" +msgstr "Wúfǎ qǐdòng yìbù yīnpín" + #: supervisor/shared/safe_mode.c msgid "Failed to write internal flash." msgstr "Wúfǎ xiě rù nèibù shǎncún." @@ -1020,12 +1089,14 @@ msgstr "Wúfǎ xiě rù nèibù shǎncún." msgid "File exists" msgstr "Wénjiàn cúnzài" +#: shared-bindings/supervisor/__init__.c shared-module/lvfontio/OnDiskFont.c #: shared-module/os/getenv.c msgid "File not found" msgstr "zhǎo bú dào wén jiàn" #: ports/atmel-samd/common-hal/canio/Listener.c #: ports/espressif/common-hal/canio/Listener.c +#: ports/mimxrt10xx/common-hal/canio/Listener.c #: ports/stm/common-hal/canio/Listener.c msgid "Filters too complex" msgstr "guò lǜ qì tài fù zá" @@ -1053,7 +1124,7 @@ msgstr "" "zài GRB sè yù zhōng, měi gè shū rù de xiàng sù bì xū shì 16 wèi (16 bit) shù " "jù" -#: ports/cxd56/common-hal/camera/Camera.c +#: ports/cxd56/common-hal/camera/Camera.c shared-module/audiocore/WaveFile.c msgid "Format not supported" msgstr "Bù zhīyuán géshì" @@ -1167,6 +1238,7 @@ msgid "Insufficient stream input buffer" msgstr "liú shūrù huǎnchōngqū bùzú" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Interface must be started" msgstr "jiē kǒu bì xū qǐ dòng" @@ -1212,15 +1284,19 @@ msgstr "zhōng duàn cuò wù." msgid "Interrupted by output function" msgstr "bèi shūchū gōngnéng zhōngduàn" +#: ports/espressif/common-hal/_bleio/Service.c #: ports/espressif/common-hal/espulp/ULP.c #: ports/espressif/common-hal/microcontroller/Processor.c #: ports/mimxrt10xx/common-hal/audiobusio/__init__.c #: ports/mimxrt10xx/common-hal/pwmio/PWMOut.c #: ports/raspberrypi/bindings/picodvi/Framebuffer.c +#: ports/raspberrypi/bindings/rp2pio/StateMachine.c #: ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c py/argcheck.c #: shared-bindings/digitalio/DigitalInOut.c #: shared-bindings/epaperdisplay/EPaperDisplay.c shared-bindings/pwmio/PWMOut.c +#: shared-bindings/supervisor/__init__.c #: shared-module/aurora_epaper/aurora_framebuffer.c +#: shared-module/lvfontio/OnDiskFont.c msgid "Invalid %q" msgstr "wú xiào %q" @@ -1253,6 +1329,10 @@ msgstr "Wúxiào de BSSID" msgid "Invalid MAC address" msgstr "wú xiào de MAC dì zhǐ" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "Invalid ROS domain ID" +msgstr "wúxiàode ROS yù ID" + #: ports/espressif/common-hal/espidf/__init__.c py/moderrno.c msgid "Invalid argument" msgstr "Wúxiào de cānshù" @@ -1284,6 +1364,7 @@ msgid "Invalid hex password" msgstr "Shíliù jìn zhì mìmǎ wúxiào" #: ports/espressif/common-hal/wifi/Radio.c +#: ports/zephyr-cp/common-hal/wifi/Radio.c msgid "Invalid multicast MAC address" msgstr "wú xiào de duō bō MAC dì zhǐ" @@ -1296,6 +1377,7 @@ msgid "Invalid socket for TLS" msgstr "TLS de chā zuò wú xiào" #: ports/espressif/common-hal/espidf/__init__.c +#: ports/nordic/common-hal/_bleio/__init__.c msgid "Invalid state" msgstr "wú xiào zhuàng tài" @@ -1336,9 +1418,15 @@ msgid "MAC address was invalid" msgstr "MAC dì zhǐ wú xiào" #: ports/espressif/common-hal/_bleio/Characteristic.c +#: ports/espressif/common-hal/_bleio/Descriptor.c msgid "MITM security not supported" msgstr "bù zhīchí MITM ānquánxìng" +#: ports/stm/common-hal/sdioio/SDCard.c +#, c-format +msgid "MMC/SDIO Clock Error %x" +msgstr "MMC/SDIO shízhōngcuòwù %x" + #: shared-bindings/is31fl3741/IS31FL3741.c msgid "Mapping must be a tuple" msgstr "yìng shè bì xū shì yuán zǔ" @@ -1384,7 +1472,8 @@ msgstr "quēshǎo jmp_pin. %q[%u] tiàodào yǐn jiǎoshàng" msgid "Mount point directory missing" msgstr "quēshǎo guàzǎi diǎn mùlù" -#: shared-bindings/busio/UART.c shared-bindings/displayio/Group.c +#: ports/zephyr-cp/bindings/zephyr_serial/UART.c shared-bindings/busio/UART.c +#: shared-bindings/displayio/Group.c msgid "Must be a %q subclass." msgstr "Bìxū shì %q zi lèi." @@ -1524,6 +1613,10 @@ msgstr "zài SDA huò SCL shàng wèi zhǎo dào shàng lā; jiǎn chá nín de msgid "No pulldown on pin; 1Mohm recommended" msgstr "Yǐn jiǎo shàng méiyǒu xiàlā; 1Mohm tuījiàn" +#: shared-module/touchio/TouchIn.c +msgid "No pullup on pin; 1Mohm recommended" +msgstr "Yǐn jiǎo shàng wú shàng lā diànzǔ; jiànyì shǐyòng 1Mohm" + #: py/moderrno.c msgid "No space left on device" msgstr "Shèbèi shàng méiyǒu kònggé" @@ -1568,9 +1661,10 @@ msgid "Not supported JPEG standard" msgstr "bù zhīchí JPEG biāozhǔn" #: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +#: ports/espressif/common-hal/sdioio/SDCard.c #, c-format -msgid "Number of data_pins must be 8 or 16, not %d" -msgstr "data_pins shù bì xū wéi 8 huò 16, ér bù shì %d" +msgid "Number of data_pins must be %d or %d, not %d" +msgstr "data_pins shù bìxū shì %d huò %d, érbùshì %d" #: shared-bindings/util.c msgid "" @@ -1625,15 +1719,6 @@ msgstr "cǐ yìng jiàn shàng jǐn tí gòng biān yuán jiǎn cè" msgid "Only int or string supported for ip" msgstr "jǐn zhī chí IP de zhěng shù huò zì fú chuàn" -#: shared-module/displayio/OnDiskBitmap.c -#, c-format -msgid "" -"Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: " -"%d bpp given" -msgstr "" -"Jǐn zhīchí dān sè, suǒyǐn wéi 4bpp huò 8bpp yǐjí 16bpp huò gèng gāo de BMP: " -"Gěi chū %d bpp" - #: ports/espressif/common-hal/alarm/touch/TouchAlarm.c msgid "Only one %q can be set in deep sleep." msgstr "zài shēn dù shuì mián zhōng zhǐ néng shè zhì yí gè %q." @@ -1684,6 +1769,7 @@ msgstr "nèi cún bù zú" #: ports/espressif/common-hal/socketpool/Socket.c #: ports/raspberrypi/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Out of sockets" msgstr "tào jiē zì wài" @@ -1703,6 +1789,11 @@ msgstr "yǐ jīng zài shǐ yòng de PWM qiē piàn" msgid "PWM slice channel A already in use" msgstr "PWM qiē piàn tōng dào A yǐ zài shǐ yòng zhōng" +#: shared-bindings/spitarget/SPITarget.c +msgid "Packet buffers for an SPI transfer must have the same length." +msgstr "" +"SPI chuánshū de shùjù bāo huǎnchōng qū bìxū jùyǒu xiāngtóng de chángdù." + #: shared-module/jpegio/JpegDecoder.c msgid "Parameter error" msgstr "cānshù cuòwù" @@ -1805,6 +1896,10 @@ msgstr "chéng xù dà xiǎo wú xiào" msgid "Program too long" msgstr "chéng xù tài cháng" +#: shared-bindings/rclcpy/Publisher.c +msgid "Publishers can only be created from a parent node" +msgstr "chūbǎnshāng zhǐ néngcóng fù jiédiǎn chuàngjiàn" + #: shared-bindings/digitalio/DigitalInOut.c msgid "Pull not used when direction is output." msgstr "Fāngxiàng shūchū shí Pull méiyǒu shǐyòng." @@ -1825,6 +1920,26 @@ msgstr "RNG qǔxiāo chūshǐhuà cuòwù" msgid "RNG Init Error" msgstr "RNG chūshǐhuà cuòwù" +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS failed to initialize. Is agent connected?" +msgstr "ROS chūshǐhuàshībài. dàilǐ yǐ liánjiē ma?" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS internal setup failure" +msgstr "ROS nèibù shèzhì shībài" + +#: ports/espressif/common-hal/rclcpy/__init__.c +msgid "ROS memory allocator failure" +msgstr "ROS nèicún fēnpèiqì shībài" + +#: ports/espressif/common-hal/rclcpy/Node.c +msgid "ROS node failed to initialize" +msgstr "ROS jiédiǎn chūshǐhuà shībài" + +#: ports/espressif/common-hal/rclcpy/Publisher.c +msgid "ROS topic failed to initialize" +msgstr "ROS zhǔtí chūshǐhuà shībài" + #: ports/atmel-samd/common-hal/busio/UART.c ports/cxd56/common-hal/busio/UART.c #: ports/nordic/common-hal/busio/UART.c ports/stm/common-hal/busio/UART.c msgid "RS485" @@ -1903,10 +2018,11 @@ msgstr "SDCard chūshǐhuà" msgid "SDIO GetCardInfo Error %d" msgstr "SDIO GetCardInfo Cuòwù %d" +#: ports/espressif/common-hal/sdioio/SDCard.c #: ports/stm/common-hal/sdioio/SDCard.c #, c-format -msgid "SDIO Init Error %d" -msgstr "SDIO Init Cuòwù %d" +msgid "SDIO Init Error %x" +msgstr "SDIO rècuòwù %x" #: ports/espressif/common-hal/busio/SPI.c msgid "SPI configuration failed" @@ -1955,11 +2071,13 @@ msgstr "Qiēpiàn hé zhí bùtóng chángdù." #: shared-bindings/displayio/TileGrid.c #: shared-bindings/memorymonitor/AllocationSize.c #: shared-bindings/pulseio/PulseIn.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c msgid "Slices not supported" msgstr "Qiēpiàn bù shòu zhīchí" #: ports/espressif/common-hal/socketpool/SocketPool.c #: ports/raspberrypi/common-hal/socketpool/SocketPool.c +#: ports/zephyr-cp/common-hal/socketpool/SocketPool.c msgid "SocketPool can only be used with wifi.radio" msgstr "SocketPool zhǐ néng yǔ wifi.Radio yīqǐ shǐyòng" @@ -1999,21 +2117,9 @@ msgstr "shàng shù yì cháng shì yǐ xià yì cháng de zhí jiē yuán yīn: msgid "The length of rgb_pins must be 6, 12, 18, 24, or 30" msgstr "Rgb_pins de chángdù bìxū wèi 6,12,18,24 huò 30" -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's bits_per_sample does not match the mixer's" -msgstr "Yàngběn de bits_per_sample yǔ hǔn yīn qì bù pǐpèi" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's channel count does not match the mixer's" -msgstr "Yàngběn de píndào jìshù yǔ hǔn yīn qì bù xiāngfú" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's sample rate does not match the mixer's" -msgstr "Yàngběn de yàngběn sùdù yǔ hǔn yīn qì de xiāngchà bù pǐpèi" - -#: shared-module/audiomixer/MixerVoice.c -msgid "The sample's signedness does not match the mixer's" -msgstr "Yàngběn de qiānmíng yǔ hǔn yīn qì de qiānmíng bù pǐpèi" +#: shared-module/audiocore/__init__.c +msgid "The sample's %q does not match" +msgstr "yàngběn de %q bù pǐpèi" #: supervisor/shared/safe_mode.c msgid "Third-party firmware fatal error." @@ -2035,7 +2141,9 @@ msgstr "" msgid "Tile height must exactly divide bitmap height" msgstr "Píng pū gāodù bìxū huàfēn wèi tú gāodù" -#: shared-bindings/displayio/TileGrid.c shared-module/displayio/TileGrid.c +#: shared-bindings/displayio/TileGrid.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-module/displayio/TileGrid.c msgid "Tile index out of bounds" msgstr "Píng pū zhǐshù chāochū fànwéi" @@ -2043,6 +2151,10 @@ msgstr "Píng pū zhǐshù chāochū fànwéi" msgid "Tile width must exactly divide bitmap width" msgstr "Píng pū kuāndù bìxū huàfēn wèi tú kuāndù" +#: shared-module/tilepalettemapper/TilePaletteMapper.c +msgid "TilePaletteMapper may only be bound to a TileGrid once" +msgstr "TilePaletteMapper zhǐnéng bǎngdìng dào yígè TileGrid shàngyícì" + #: shared-bindings/alarm/time/TimeAlarm.c msgid "Time is in the past." msgstr "shí jiān yǐ jīng guò qù." @@ -2173,6 +2285,10 @@ msgstr "Wúfǎ chūshǐhuà jiěxī qì" msgid "Unable to read color palette data" msgstr "Wúfǎ dúqǔ tiáosèbǎn shùjù" +#: ports/mimxrt10xx/common-hal/canio/CAN.c +msgid "Unable to send CAN Message: all Tx message buffers are busy" +msgstr "wúfǎ fāsòng CAN xiāoxi: suǒyǒuTx xiāoxi huǎnchōngqū dōumáng" + #: ports/espressif/common-hal/mdns/Server.c #: ports/raspberrypi/common-hal/mdns/Server.c msgid "Unable to start mDNS query" @@ -2267,15 +2383,12 @@ msgstr "bú zhī chí de sè cǎi kōng jiān" msgid "Unsupported display bus type" msgstr "Bù zhīchí de gōnggòng qìchē lèixíng" -#: shared-module/audiocore/WaveFile.c -msgid "Unsupported format" -msgstr "Bù zhīchí de géshì" - #: shared-bindings/hashlib/__init__.c msgid "Unsupported hash algorithm" msgstr "bù zhīchí de hā xī suànfǎ" #: ports/espressif/common-hal/socketpool/Socket.c +#: ports/zephyr-cp/common-hal/socketpool/Socket.c msgid "Unsupported socket type" msgstr "bù zhīchí de tàojiēzì lèixíng" @@ -2285,14 +2398,12 @@ msgid "Update failed" msgstr "gēngxīn shībài" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length != required fixed length" msgstr "Zhí chángdù != Suǒ xū de gùdìng chángdù" #: ports/espressif/common-hal/_bleio/Characteristic.c -#: ports/espressif/common-hal/_bleio/Descriptor.c #: ports/nordic/common-hal/_bleio/Characteristic.c #: ports/nordic/common-hal/_bleio/Descriptor.c msgid "Value length > max_length" @@ -2333,9 +2444,11 @@ msgstr "" msgid "Wi-Fi: " msgstr "Wi-Fi: " +#: ports/espressif/common-hal/wifi/Radio.c #: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "Wifi is not enabled" -msgstr "wú xiàn wǎng luò wèi qǐ yòng" +#: ports/zephyr-cp/common-hal/wifi/Radio.c +msgid "WiFi is not enabled" +msgstr "WiFi wèi qǐyòng" #: main.c msgid "Woken up by alarm.\n" @@ -2357,6 +2470,7 @@ msgstr "nín zài qǐ dòng shí àn xià le liǎng gè àn niǔ." #: ports/espressif/boards/m5stack_core_fire/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c/mpconfigboard.h #: ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.h +#: ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h msgid "You pressed button A at start up." msgstr "nín zài qǐ dòng shí àn xià le àn niǔ A." @@ -2370,6 +2484,7 @@ msgstr "nín zài qǐ dòng shí àn xià le qǐ dòng àn niǔ" #: ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.h #: ports/espressif/boards/adafruit_itsybitsy_esp32/mpconfigboard.h +#: ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h msgid "You pressed the BOOT button at start up." msgstr "nínzài qǐdòngshí ànxià le BOOTànniǔ." @@ -2430,6 +2545,10 @@ msgstr "xūyào yīgè zì jié lèi duìxiàng" msgid "addresses is empty" msgstr "dìzhǐ wèi kōng" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "already playing" +msgstr "yǐjīng zàiwán le" + #: py/compile.c msgid "annotation must be an identifier" msgstr "zhù shì bì xū shì biāo zhì fú" @@ -2454,6 +2573,10 @@ msgstr "argsort cānshù bìxū shì ndarray" msgid "argsort is not implemented for flattened arrays" msgstr "wèi wéi pīn hé shù zǔ shí xiàn argsort" +#: extmod/ulab/code/numpy/random/random.c +msgid "argument must be None, an integer or a tuple of integers" +msgstr "cānshù bìxū shì None, zhěngshù huò zhěngshù yuánzǔ" + #: py/compile.c msgid "argument name reused" msgstr "chóng fù shǐ yòng de cān shù míng chēng" @@ -2504,6 +2627,10 @@ msgstr "chángshì huòqǔ kōng xùliè de argmin/ argmax" msgid "attributes not supported" msgstr "bù zhīchí de shǔxìng" +#: ports/espressif/common-hal/audioio/AudioOut.c +msgid "audio format not supported" +msgstr "bù zhīchí yīnpín géshì" + #: extmod/ulab/code/ulab_tools.c msgid "axis is out of bounds" msgstr "zhóu chāo chū biān jiè" @@ -2540,6 +2667,10 @@ msgstr "cuòwù de dàimǎ lèixíng" msgid "binary op %q not implemented" msgstr "èrjìnzhì bǎn qián bǎn %q wèi zhíxíng" +#: ports/espressif/common-hal/audiobusio/PDMIn.c +msgid "bit_depth must be 8, 16, 24, or 32." +msgstr "bit_depth bìxū shì 8, 16, 24, huò 32." + #: shared-module/bitmapfilter/__init__.c msgid "bitmap size and depth must match" msgstr "wèitú dà xiǎohé shēndù bìxū pǐpèi" @@ -2552,6 +2683,15 @@ msgstr "wèi tú dà xiǎo bì xū pǐ pèi" msgid "bits must be 32 or less" msgstr "wèi bì xū shì 32 huò gèng shǎo" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "bits_per_sample must be 16" +msgstr "bits_per_sample bìxū wèi 16" + +#: shared-bindings/audiodelays/Chorus.c shared-bindings/audiodelays/Echo.c +#: shared-bindings/audiodelays/MultiTapDelay.c +#: shared-bindings/audiodelays/PitchShift.c +#: shared-bindings/audiofilters/Distortion.c +#: shared-bindings/audiofilters/Filter.c shared-bindings/audiofilters/Phaser.c #: shared-bindings/audiomixer/Mixer.c msgid "bits_per_sample must be 8 or 16" msgstr "měi jiàn yàngběn bìxū wèi 8 huò 16" @@ -2633,7 +2773,7 @@ msgstr "bùnéng fēnpèi dào biǎodá shì" msgid "can't cancel self" msgstr "bù néng qǔ xiāo zì wǒ" -#: shared-module/adafruit_pixelbuf/PixelBuf.c +#: py/obj.c shared-module/adafruit_pixelbuf/PixelBuf.c msgid "can't convert %q to %q" msgstr "Wúfǎ jiāng %q zhuǎnhuàn wèi %q" @@ -2688,6 +2828,10 @@ msgstr "bùnéng shānchú biǎodá shì" msgid "can't do binary op between '%q' and '%q'" msgstr "bùnéng zài '%q' hé '%q' zhī jiān jìnxíng èr yuán yùnsuàn" +#: py/emitnative.c +msgid "can't do unary op of '%q'" +msgstr "wúfǎ zhíxíng '%q' de yīyuán yùnsuàn" + #: py/emitnative.c msgid "can't implicitly convert '%q' to 'bool'" msgstr "bùnéng yǐn hán de jiāng '%q' zhuǎnhuàn wèi 'bool'" @@ -2750,10 +2894,6 @@ msgstr "wúfǎ cóng shǒudòng zìduàn guīgé qiēhuàn dào zìdòng zìduà msgid "can't truncate-divide a complex number" msgstr "shùliàng fùzá" -#: extmod/moductypes.c -msgid "can't unambiguously get sizeof scalar" -msgstr "Wúfǎ míngquè de huòdé biāoliàng de dàxiǎo" - #: extmod/modasyncio.c msgid "can't wait" msgstr "děngbùjí" @@ -3098,7 +3238,7 @@ msgid "format" msgstr "Géshì" #: py/objstr.c -msgid "format requires a dict" +msgid "format needs a dict" msgstr "géshì yāoqiú yīgè yǔjù" #: py/objdeque.c @@ -3148,7 +3288,8 @@ msgstr "hánshù quēshǎo suǒ xū guānjiàn zì cānshù '%q'" msgid "function missing required positional argument #%d" msgstr "hánshù quēshǎo suǒ xū de wèizhì cānshù #%d" -#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/time/__init__.c +#: py/argcheck.c py/bc.c py/objnamedtuple.c shared-bindings/_eve/__init__.c +#: shared-bindings/time/__init__.c #, c-format msgid "function takes %d positional arguments but %d were given" msgstr "hánshù xūyào %d gè wèizhì cānshù, dàn %d bèi gěi chū" @@ -3231,10 +3372,6 @@ msgstr "suǒyǐn bìxū shì zhěngshù" msgid "indices must be integers, slices, or Boolean lists" msgstr "suǒyǐn bìxū shì zhěngshù, qiēpiàn huò bù'ěr zhí lièbiǎo" -#: ports/espressif/common-hal/busio/I2C.c -msgid "init I2C" -msgstr "chūshǐhuà I2C" - #: extmod/ulab/code/scipy/optimize/optimize.c msgid "initial values must be iterable" msgstr "chūshǐ zhí bìxū shì kě diédài de" @@ -3300,7 +3437,7 @@ msgstr "shū rù bì xū shì 1D ndarray" msgid "input must be a dense ndarray" msgstr "shū rù bì xū shì mì jí de ndarray" -#: extmod/ulab/code/user/user.c +#: extmod/ulab/code/user/user.c shared-bindings/_eve/__init__.c msgid "input must be an ndarray" msgstr "shū rù bì xū shì ndarray" @@ -3430,10 +3567,6 @@ msgstr "biāoqiān '%q' wèi dìngyì" msgid "label redefined" msgstr "biāoqiān chóngxīn dìngyì" -#: shared-bindings/audiomixer/MixerVoice.c -msgid "level must be between 0 and 1" -msgstr "Level bìxū jiè yú 0 hé 1 zhī jiān" - #: py/objarray.c msgid "lhs and rhs should be compatible" msgstr "lhs hé rhs yīnggāi jiānróng" @@ -3487,7 +3620,7 @@ msgstr "jǔzhèn bùshì zhèngdìng de" msgid "max_length must be 0-%d when fixed_length is %s" msgstr "max_length bìxū shì 0-%d, dāng fixed_length shì %s" -#: extmod/ulab/code/ndarray.c +#: extmod/ulab/code/ndarray.c extmod/ulab/code/numpy/random/random.c msgid "maximum number of dimensions is " msgstr "zuìdà wéi shù shì " @@ -3565,7 +3698,7 @@ msgid "must use keyword argument for key function" msgstr "bìxū shǐyòng guānjiàn cí cānshù" #: py/runtime.c -msgid "name '%q' is not defined" +msgid "name '%q' isn't defined" msgstr "míngchēng '%q' wèi dìngyì" #: py/runtime.c @@ -3574,7 +3707,7 @@ msgstr "míngchēng wèi dìngyì" #: py/qstr.c msgid "name too long" -msgstr "" +msgstr "míngchēng tàicháng" #: py/persistentcode.c msgid "native code in .mpy unsupported" @@ -3629,7 +3762,7 @@ msgstr "zhǎo bù dào fēi běndì de bǎng dìng" msgid "no default packer" msgstr "wú mò rèn bāo zhuāng jī" -#: extmod/modrandom.c +#: extmod/modrandom.c extmod/ulab/code/numpy/random/random.c msgid "no default seed" msgstr "wú mò rèn zhǒng zi" @@ -3838,6 +3971,10 @@ msgstr "ord() yùqí zìfú, dàn chángdù zìfú chuàn %d" msgid "out array is too small" msgstr "chū zhèn liè tài xiǎo" +#: extmod/ulab/code/numpy/random/random.c +msgid "out has wrong type" +msgstr "out de lèixíng cuòwù" + #: extmod/ulab/code/numpy/vector.c msgid "out keyword is not supported for complex dtype" msgstr "fùzá de dtype bù zhīchí out guānjiànzì" @@ -3862,6 +3999,14 @@ msgstr "out bìxū shì fúdiǎn xíng dtype" msgid "out of range of target" msgstr "mù biāo fàn wéi wài" +#: extmod/ulab/code/numpy/random/random.c +msgid "output array has wrong type" +msgstr "output array de lèixíng cuòwù" + +#: extmod/ulab/code/numpy/random/random.c +msgid "output array must be contiguous" +msgstr "output array bìxū shì liánxù de" + #: py/objint_mpz.c msgid "overflow converting long int to machine word" msgstr "chāo gāo zhuǎnhuàn zhǎng zhěng shùzì shí" @@ -3971,6 +4116,10 @@ msgstr "gǔn dòng cān shù bì xū shì ndarray" msgid "rsplit(None,n)" msgstr "Rchāifēn(wú,N)" +#: shared-bindings/audiofreeverb/Freeverb.c +msgid "samples_signed must be true" +msgstr "samples_signed bìxū wéi zhēn" + #: ports/atmel-samd/common-hal/audiobusio/PDMIn.c #: ports/raspberrypi/common-hal/audiobusio/PDMIn.c msgid "sampling rate out of range" @@ -3988,6 +4137,10 @@ msgstr "bù zhīchí jiǎoběn biānyì" msgid "set unsupported" msgstr "shè zhì bù shòu zhī chí" +#: extmod/ulab/code/numpy/random/random.c +msgid "shape must be None, and integer or a tuple of integers" +msgstr "shape bìxū shì None, bìng qiěshì integer huò zhěngshù yuánzǔ" + #: extmod/ulab/code/ndarray.c msgid "shape must be integer or tuple of integers" msgstr "xíngzhuàng bìxū shì zhěngshù huò zhěngshù yuánzǔ" @@ -4008,6 +4161,10 @@ msgstr "zhěngshù géshì shuōmíng fú 'c' bù yǔnxǔ shǐyòng fúhào" msgid "size is defined for ndarrays only" msgstr "dàxiǎo jǐn wèi ndarrays dìngyì" +#: extmod/ulab/code/numpy/random/random.c +msgid "size must match out.shape when used together" +msgstr "yìqǐ shǐ yòngshí, size bìxū yǔ out.shape pǐpèi" + #: py/nativeglue.c msgid "slice unsupported" msgstr "qiē piàn bù shòu zhī chí" @@ -4084,18 +4241,6 @@ msgstr "zìfú chuàn suǒyǐn chāochū fànwéi" msgid "string indices must be integers, not %s" msgstr "zìfú chuàn zhǐshù bìxū shì zhěngshù, ér bùshì %s" -#: extmod/moductypes.c -msgid "struct: can't index" -msgstr "jié gòu: wú fǎ suǒ yǐn" - -#: extmod/moductypes.c -msgid "struct: index out of range" -msgstr "jiégòu: suǒyǐn chāochū fànwéi" - -#: extmod/moductypes.c -msgid "struct: no fields" -msgstr "jiégòu: méiyǒu zìduàn" - #: py/objarray.c py/objstr.c msgid "substring not found" msgstr "wèi zhǎodào zi zìfú chuàn" @@ -4108,10 +4253,6 @@ msgstr "chāojí() zhǎo bù dào zìjǐ" msgid "syntax error in JSON" msgstr "JSON yǔfǎ cuòwù" -#: extmod/moductypes.c -msgid "syntax error in uctypes descriptor" -msgstr "uctypes miáoshù fú zhōng de yǔfǎ cuòwù" - #: extmod/modtime.c msgid "ticks interval overflow" msgstr "fēnshí jiàngé yìchū" @@ -4201,11 +4342,11 @@ msgid "tx and rx cannot both be None" msgstr "tx hé rx bùnéng dōu shì wú" #: py/objtype.c -msgid "type '%q' is not an acceptable base type" +msgid "type '%q' isn't an acceptable base type" msgstr "lèixíng '%q' bùshì kě jiēshòu de jīchǔ lèixíng" #: py/objtype.c -msgid "type is not an acceptable base type" +msgid "type isn't an acceptable base type" msgstr "lèixíng bùshì kě jiēshòu de jīchǔ lèixíng" #: py/runtime.c @@ -4220,10 +4361,6 @@ msgstr "lèixíng wèi 1 huò 3 gè cānshù" msgid "ulonglong too large" msgstr "tài kuān" -#: py/emitnative.c -msgid "unary op %q not implemented" -msgstr "wèi zhíxíng %q" - #: py/parse.c msgid "unexpected indent" msgstr "wèi yùliào de suō jìn" @@ -4271,7 +4408,9 @@ msgstr "gé shì bù pǐ pèi de '%c'" msgid "unreadable attribute" msgstr "bùkě dú shǔxìng" -#: shared-bindings/displayio/TileGrid.c shared-bindings/vectorio/VectorShape.c +#: shared-bindings/displayio/TileGrid.c shared-bindings/terminalio/Terminal.c +#: shared-bindings/tilepalettemapper/TilePaletteMapper.c +#: shared-bindings/vectorio/VectorShape.c msgid "unsupported %q type" msgstr "bù zhīchí %q lèixíng" @@ -4352,11 +4491,6 @@ msgstr "" msgid "width must be greater than zero" msgstr "kuāndù bìxū dàyú líng" -#: ports/espressif/common-hal/wifi/Radio.c -#: ports/raspberrypi/common-hal/wifi/Radio.c -msgid "wifi is not enabled" -msgstr "wèi qǐ yòng WIFI" - #: ports/raspberrypi/common-hal/wifi/Monitor.c msgid "wifi.Monitor not available" msgstr "wú xiàn wǎng luò xiǎn shì qì bù kě yòng" @@ -4419,6 +4553,82 @@ msgstr "zi bìxū wèi fú diǎn xíng" msgid "zi must be of shape (n_section, 2)" msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" +#~ msgid "Unsupported format" +#~ msgstr "Bù zhīchí de géshì" + +#~ msgid "Wifi is not enabled" +#~ msgstr "wú xiàn wǎng luò wèi qǐ yòng" + +#~ msgid "wifi is not enabled" +#~ msgstr "wèi qǐ yòng WIFI" + +#~ msgid "Cannot remount '/' when visible via USB." +#~ msgstr "tōngguò USB kějiàn shí wúfǎ chóngxīn ānzhuāng '/'." + +#~ msgid "%q must be a %q object, %q, or %q" +#~ msgstr "%q bìxū shì %q duìxiàng, %q huò %q" + +#~ msgid "Data chunk must follow fmt chunk" +#~ msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" + +#, c-format +#~ msgid "" +#~ "Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs " +#~ "supported: %d bpp given" +#~ msgstr "" +#~ "Jǐn zhīchí dān sè, suǒyǐn wéi 4bpp huò 8bpp yǐjí 16bpp huò gèng gāo de " +#~ "BMP: Gěi chū %d bpp" + +#~ msgid "level must be between 0 and 1" +#~ msgstr "Level bìxū jiè yú 0 hé 1 zhī jiān" + +#~ msgid "init I2C" +#~ msgstr "chūshǐhuà I2C" + +#~ msgid "The sample's bits_per_sample does not match the mixer's" +#~ msgstr "Yàngběn de bits_per_sample yǔ hǔn yīn qì bù pǐpèi" + +#~ msgid "The sample's channel count does not match the mixer's" +#~ msgstr "Yàngběn de píndào jìshù yǔ hǔn yīn qì bù xiāngfú" + +#~ msgid "The sample's sample rate does not match the mixer's" +#~ msgstr "Yàngběn de yàngběn sùdù yǔ hǔn yīn qì de xiāngchà bù pǐpèi" + +#~ msgid "The sample's signedness does not match the mixer's" +#~ msgstr "Yàngběn de qiānmíng yǔ hǔn yīn qì de qiānmíng bù pǐpèi" + +#~ msgid "Buffer length must be a multiple of 512" +#~ msgstr "Huǎnchōngqū chángdù bìxū wéi 512 de bèishù" + +#~ msgid "Buffer must be a multiple of 512 bytes" +#~ msgstr "Huǎnchōngqū bìxū shì 512 zìjié de bèishù" + +#, c-format +#~ msgid "Number of data_pins must be 8 or 16, not %d" +#~ msgstr "data_pins shù bì xū wéi 8 huò 16, ér bù shì %d" + +#, c-format +#~ msgid "SDIO Init Error %d" +#~ msgstr "SDIO Init Cuòwù %d" + +#~ msgid "can't unambiguously get sizeof scalar" +#~ msgstr "Wúfǎ míngquè de huòdé biāoliàng de dàxiǎo" + +#~ msgid "struct: can't index" +#~ msgstr "jié gòu: wú fǎ suǒ yǐn" + +#~ msgid "struct: index out of range" +#~ msgstr "jiégòu: suǒyǐn chāochū fànwéi" + +#~ msgid "struct: no fields" +#~ msgstr "jiégòu: méiyǒu zìduàn" + +#~ msgid "syntax error in uctypes descriptor" +#~ msgstr "uctypes miáoshù fú zhōng de yǔfǎ cuòwù" + +#~ msgid "unary op %q not implemented" +#~ msgstr "wèi zhíxíng %q" + #~ msgid "Name too long" #~ msgstr "Míngchēng tài zhǎng" @@ -4716,13 +4926,13 @@ msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" #~ msgid "'%s' object does not support item deletion" #~ msgstr "'%s' duìxiàng bù zhīchí shānchú xiàngmù" -#~ msgid "'%s' object is not an iterator" +#~ msgid "'%s' object isn't an iterator" #~ msgstr "'%s' duìxiàng bùshì yīgè diédài qì" #~ msgid "'%s' object is not callable" #~ msgstr "'%s' duìxiàng wúfǎ diàoyòng" -#~ msgid "'%s' object is not iterable" +#~ msgid "'%s' object isn't iterable" #~ msgstr "'%s' duìxiàng bùnéng diédài" #~ msgid "'%s' object is not subscriptable" @@ -4738,7 +4948,7 @@ msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" #~ msgid "'continue' outside loop" #~ msgstr "'continue' wèiyú xúnhuán zhīwài" -#~ msgid "'coroutine' object is not an iterator" +#~ msgid "'coroutine' object isn't an iterator" #~ msgstr "'coroutine' duìxiàng búshì yígè diédàiqì" #~ msgid "(x,y) integers required" @@ -6086,7 +6296,7 @@ msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" #~ msgid "frequency is read-only for this board" #~ msgstr "cǐ zhǔ bǎn de pín lǜ wéi zhǐ dú" -#~ msgid "function does not take keyword arguments" +#~ msgid "function doesn't take keyword arguments" #~ msgstr "hánshù méiyǒu guānjiàn cí cānshù" #~ msgid "function is implemented for scalars and ndarrays only" @@ -6188,7 +6398,7 @@ msgstr "zi bìxū jùyǒu xíngzhuàng (n_section,2)" #~ msgid "name must be a string" #~ msgstr "míngchēng bìxū shì yīgè zìfú chuàn" -#~ msgid "name reused for argument" +#~ msgid "argument name reused" #~ msgstr "cān shǔ míngchēng bèi chóngxīn shǐyòng" #~ msgid "no available NIC" diff --git a/logo/vector-logo-2.ico b/logo/vector-logo-2.ico deleted file mode 100644 index 24b12812cf49e..0000000000000 Binary files a/logo/vector-logo-2.ico and /dev/null differ diff --git a/main.c b/main.c index a463fbe4afe6b..ce058cc49c4b5 100644 --- a/main.c +++ b/main.c @@ -21,6 +21,7 @@ #include "py/stackctrl.h" #include "shared/readline/readline.h" +#include "shared/runtime/gchelper.h" #include "shared/runtime/pyexec.h" #include "background.h" @@ -42,6 +43,7 @@ #include "supervisor/shared/external_flash/external_flash.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/supervisor/Runtime.h" @@ -111,8 +113,8 @@ uint8_t value_out = 0; #endif -#if MICROPY_ENABLE_PYSTACK && CIRCUITPY_OS_GETENV -#include "shared-module/os/__init__.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" #endif static void reset_devices(void) { @@ -123,23 +125,24 @@ static void reset_devices(void) { static uint8_t *_heap; static uint8_t *_pystack; +static volatile bool _vm_is_running = false; static const char line_clear[] = "\x1b[2K\x1b[0G"; #if MICROPY_ENABLE_PYSTACK || MICROPY_ENABLE_GC static uint8_t *_allocate_memory(safe_mode_t safe_mode, const char *env_key, size_t default_size, size_t *final_size) { *final_size = default_size; - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML if (safe_mode == SAFE_MODE_NONE) { - (void)common_hal_os_getenv_int(env_key, (mp_int_t *)final_size); - if (*final_size < 0) { - *final_size = default_size; + mp_int_t size; + if (settings_get_int(env_key, &size) == SETTINGS_OK && size > 0) { + *final_size = size; } } #endif uint8_t *ptr = port_malloc(*final_size, false); - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML if (ptr == NULL) { // Fallback to the build size. ptr = port_malloc(default_size, false); @@ -203,17 +206,37 @@ static void start_mp(safe_mode_t safe_mode) { mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib)); mp_obj_list_init((mp_obj_list_t *)mp_sys_argv, 0); + + // Always return to root + common_hal_os_chdir("/"); + + _vm_is_running = true; } static void stop_mp(void) { + _vm_is_running = false; #if MICROPY_VFS - mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); // Unmount all heap allocated vfs mounts. - while (gc_nbytes(vfs) > 0) { - vfs = vfs->next; + mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); + if (vfs != NULL) { + do { + if (gc_ptr_on_heap(vfs)) { + // mp_vfs_umount will splice out an unmounted vfs from the vfs_mount_table linked list. + mp_vfs_umount(vfs->obj); + // Start over at the beginning of the list since the first entry may have been removed. + vfs = MP_STATE_VM(vfs_mount_table); + continue; + } + vfs = vfs->next; + } while (vfs != NULL); + + // The last vfs is CIRCUITPY and the root directory. + vfs = MP_STATE_VM(vfs_mount_table); + while (vfs->next != NULL) { + vfs = vfs->next; + } } - MP_STATE_VM(vfs_mount_table) = vfs; MP_STATE_VM(vfs_cur) = vfs; #endif @@ -393,8 +416,13 @@ static void cleanup_after_vm(mp_obj_t exception) { // Free the heap last because other modules may reference heap memory and need to shut down. filesystem_flush(); + + // Runs finalisers while shutting down the heap. stop_mp(); + // Don't reset pins until finalisers have run. + reset_all_pins(); + // Let the workflows know we've reset in case they want to restart. supervisor_workflow_reset(); } @@ -458,9 +486,12 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s next_code_configuration->options &= ~SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET; next_code_options = next_code_configuration->options; if (next_code_configuration->filename[0] != '\0') { + if (next_code_configuration->working_directory != NULL) { + common_hal_os_chdir(next_code_configuration->working_directory); + } // This is where the user's python code is actually executed: const char *const filenames[] = { next_code_configuration->filename }; - found_main = maybe_run_list(filenames, MP_ARRAY_SIZE(filenames)); + found_main = maybe_run_list(filenames, 1); if (!found_main) { serial_write(next_code_configuration->filename); serial_write_compressed(MP_ERROR_TEXT(" not found.\n")); @@ -494,6 +525,7 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s // Finished executing python code. Cleanup includes filesystem flush and a board reset. + _vm_is_running = false; cleanup_after_vm(_exec_result.exception); _exec_result.exception = NULL; @@ -571,8 +603,8 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s size_t total_time = blink_time + LED_SLEEP_TIME_MS; #endif - // This loop is waits after code completes. It waits for fake sleeps to - // finish, user input or autoreloads. + // This loop is run after code completes. It waits for fake sleeps to + // finish, waits for user input, or waits for an autoreload. #if CIRCUITPY_ALARM bool fake_sleeping = false; #endif @@ -772,6 +804,9 @@ static bool __attribute__((noinline)) run_code_py(safe_mode_t safe_mode, bool *s #if CIRCUITPY_ALARM if (fake_sleeping) { board_init(); + #if CIRCUITPY_DISPLAYIO + common_hal_displayio_auto_primary_display(); + #endif // Pretend that the next run is the first run, as if we were reset. *simulate_reset = true; } @@ -841,6 +876,14 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { boot_output = &boot_text; #endif + // Get the base filesystem. + fs_user_mount_t *vfs = filesystem_circuitpy(); + FATFS *fs = &vfs->fatfs; + + // Allow boot.py access to CIRCUITPY, and allow writes to boot_out.txt. + // We can't use the regular flags for this, because they might get modified inside boot.py. + filesystem_set_ignore_write_protection(vfs, true); + // Write version info mp_printf(&mp_plat_print, "%s\nBoard ID:%s\n", MICROPY_FULL_VERSION_INFO, CIRCUITPY_BOARD_ID); #if CIRCUITPY_MICROCONTROLLER && COMMON_HAL_MCU_PROCESSOR_UID_LENGTH > 0 @@ -859,10 +902,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - // Get the base filesystem. - fs_user_mount_t *vfs = (fs_user_mount_t *)MP_STATE_VM(vfs_mount_table)->obj; - FATFS *fs = &vfs->fatfs; - boot_output = NULL; #if CIRCUITPY_STATUS_BAR supervisor_status_bar_resume(); @@ -884,9 +923,6 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { // in case power is momentary or will fail shortly due to, say a low, battery. mp_hal_delay_ms(1000); - // USB isn't up, so we can write the file. - // operating at the oofatfs (f_open) layer means the usb concurrent write permission - // is not even checked! f_open(fs, &boot_output_file, CIRCUITPY_BOOT_OUTPUT_FILE, FA_WRITE | FA_CREATE_ALWAYS); UINT chars_written; f_write(&boot_output_file, boot_text.buf, boot_text.len, &chars_written); @@ -894,14 +930,13 @@ static void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) { filesystem_flush(); } #endif - } - port_post_boot_py(true); + // Back to regular filesystem protections. + filesystem_set_ignore_write_protection(vfs, false); + } cleanup_after_vm(_exec_result.exception); _exec_result.exception = NULL; - - port_post_boot_py(false); } static int run_repl(safe_mode_t safe_mode) { @@ -974,13 +1009,23 @@ static int run_repl(safe_mode_t safe_mode) { return exit_code; } +#if defined(__ZEPHYR__) && __ZEPHYR__ == 1 +#include + +int circuitpython_main(void) { +#else int __attribute__((used)) main(void) { + #endif // initialise the cpu and peripherals set_safe_mode(port_init()); + // All ports need pins reset, after never-reset pins are marked in port_init(); + reset_all_pins(); + port_heap_init(); + // Turn on RX and TX LEDs if we have them. init_rxtx_leds(); @@ -1047,6 +1092,10 @@ int __attribute__((used)) main(void) { // displays init after filesystem, since they could share the flash SPI board_init(); + #if CIRCUITPY_DISPLAYIO + common_hal_displayio_auto_primary_display(); + #endif + mp_hal_stdout_tx_str(line_clear); // This is first time we are running CircuitPython after a reset or power-up. @@ -1092,9 +1141,6 @@ int __attribute__((used)) main(void) { } simulate_reset = false; - // Always return to root before trying to run files. - common_hal_os_chdir("/"); - if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { // If code.py did a fake deep sleep, pretend that we // are running code.py for the first time after a hard @@ -1103,7 +1149,7 @@ int __attribute__((used)) main(void) { } else { skip_repl = false; } - } else if (exit_code != 0) { + } else if (exit_code != PYEXEC_NORMAL_EXIT) { break; } @@ -1119,8 +1165,7 @@ int __attribute__((used)) main(void) { void gc_collect(void) { gc_collect_start(); - mp_uint_t regs[10]; - mp_uint_t sp = cpu_get_regs_and_sp(regs); + gc_helper_collect_regs_and_stack(); // This collects root pointers from the VFS mount table. Some of them may // have lost their references in the VM even though they are mounted. @@ -1154,28 +1199,25 @@ void gc_collect(void) { common_hal_wifi_gc_collect(); #endif - // This naively collects all object references from an approximate stack - // range. - gc_collect_root((void **)sp, ((mp_uint_t)port_stack_get_top() - sp) / sizeof(mp_uint_t)); gc_collect_end(); } -// Ports may provide an implementation of this function if it is needed -MP_WEAK void port_gc_collect() { -} - size_t gc_get_max_new_split(void) { return port_heap_get_largest_free_size(); } -void NORETURN nlr_jump_fail(void *val) { +void MP_NORETURN nlr_jump_fail(void *val) { reset_into_safe_mode(SAFE_MODE_NLR_JUMP_FAIL); while (true) { } } +bool vm_is_running(void) { + return _vm_is_running; +} + #ifndef NDEBUG -static void NORETURN __fatal_error(const char *msg) { +static void MP_NORETURN __fatal_error(const char *msg) { #if CIRCUITPY_DEBUG == 0 reset_into_safe_mode(SAFE_MODE_HARD_FAULT); #endif diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile index 9962e9bcbb246..bd9e0fb1f54d4 100644 --- a/mpy-cross/Makefile +++ b/mpy-cross/Makefile @@ -25,6 +25,12 @@ CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables # CIRCUITPY-CHANGE CFLAGS += -DCIRCUITPY +# Build a static executable. +# Useful for builds that must run on multiple operating system versions. Used for published mpy-cross versions. +ifdef STATIC_BUILD +CFLAGS += -static -static-libgcc -static-libstdc++ +endif + # Debugging/Optimization ifdef DEBUG CFLAGS += -g @@ -47,6 +53,10 @@ LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections endif LDFLAGS += $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA) +ifdef STATIC_BUILD +LDFLAGS += -static -static-libgcc -static-libstdc++ +endif + # source files # CIRCUITPY-CHANGE: extra files SRC_C = \ diff --git a/mpy-cross/fmode.c b/mpy-cross/fmode.c index f32a4af5d335b..3a761c8333cb1 100644 --- a/mpy-cross/fmode.c +++ b/mpy-cross/fmode.c @@ -10,7 +10,7 @@ // Workaround for setting file translation mode: we must distinguish toolsets // since mingw has no _set_fmode, and altering msvc's _fmode directly has no effect -STATIC int set_fmode_impl(int mode) { +static int set_fmode_impl(int mode) { #ifndef _MSC_VER _fmode = mode; return 0; diff --git a/mpy-cross/main.c b/mpy-cross/main.c index acbd30b64bbdf..add07c3d49b3e 100644 --- a/mpy-cross/main.c +++ b/mpy-cross/main.c @@ -34,38 +34,44 @@ #include "py/persistentcode.h" #include "py/runtime.h" #include "py/gc.h" -#include "py/stackctrl.h" +#include "py/parsenum.h" #include "genhdr/mpversion.h" #ifdef _WIN32 // CIRCUITPY-CHANGE #include "fmode.h" #endif +#if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 +#include "py/asmrv32.h" + +static asm_rv32_backend_options_t rv32_options = { 0 }; +#endif + // Command line options, with their defaults -STATIC uint emit_opt = MP_EMIT_OPT_NONE; +static uint emit_opt = MP_EMIT_OPT_NONE; mp_uint_t mp_verbose_flag = 0; // Heap size of GC heap (if enabled) // Make it larger on a 64 bit machine, because pointers are larger. long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); -STATIC void stdout_print_strn(void *env, const char *str, size_t len) { +static void stdout_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t dummy = write(STDOUT_FILENO, str, len); (void)dummy; } -STATIC const mp_print_t mp_stdout_print = {NULL, stdout_print_strn}; +const mp_print_t mp_stdout_print = {NULL, stdout_print_strn}; -STATIC void stderr_print_strn(void *env, const char *str, size_t len) { +static void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t dummy = write(STDERR_FILENO, str, len); (void)dummy; } -STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; +static const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; -STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) { +static int compile_and_save(const char *file, const char *output_file, const char *source_file) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex; @@ -82,13 +88,20 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha source_name = qstr_from_str(source_file); } - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_compiled_module_t cm; cm.context = m_new_obj(mp_module_context_t); + cm.arch_flags = 0; + #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC && mp_dynamic_compiler.backend_options != NULL) { + cm.arch_flags = ((asm_rv32_backend_options_t *)mp_dynamic_compiler.backend_options)->allowed_extensions; + } + #endif + mp_compile_to_raw_code(&parse_tree, source_name, false, &cm); if ((output_file != NULL && strcmp(output_file, "-") == 0) || @@ -118,7 +131,7 @@ STATIC int compile_and_save(const char *file, const char *output_file, const cha } } -STATIC int usage(char **argv) { +static int usage(char **argv) { printf( "usage: %s [] [-X ] [--] \n" "Options:\n" @@ -130,7 +143,11 @@ STATIC int usage(char **argv) { "\n" "Target specific options:\n" "-msmall-int-bits=number : set the maximum bits used to encode a small-int\n" - "-march= : set architecture for native emitter; x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin\n" + "-march= : set architecture for native emitter;\n" + " x86, x64, armv6, armv6m, armv7m, armv7em, armv7emsp,\n" + " armv7emdp, xtensa, xtensawin, rv32imc, rv64imc, host, debug\n" + "-march-flags= : set architecture-specific flags (can be either a dec/hex/bin value or a string)\n" + " supported flags for rv32imc: zba\n" "\n" "Implementation specific options:\n", argv[0] ); @@ -156,7 +173,7 @@ STATIC int usage(char **argv) { } // Process options which set interpreter init options -STATIC void pre_process_options(int argc, char **argv) { +static void pre_process_options(int argc, char **argv) { for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-X") == 0) { @@ -202,7 +219,7 @@ STATIC void pre_process_options(int argc, char **argv) { } } -STATIC char *backslash_to_forwardslash(char *path) { +static char *backslash_to_forwardslash(char *path) { for (char *p = path; p != NULL && *p != '\0'; ++p) { if (*p == '\\') { *p = '/'; @@ -211,9 +228,39 @@ STATIC char *backslash_to_forwardslash(char *path) { return path; } -MP_NOINLINE int main_(int argc, char **argv) { - mp_stack_set_limit(40000 * (sizeof(void *) / 4)); +// This will need to be reworked in case mpy-cross needs to set more bits than +// what its small int representation allows to fit in there. +static bool parse_integer(const char *value, mp_uint_t *integer) { + assert(value && "Attempting to parse a NULL string"); + assert(integer && "Attempting to store into a NULL integer buffer"); + + size_t value_length = strlen(value); + int base = 10; + if (value_length > 2 && value[0] == '0') { + if ((value[1] | 0x20) == 'b') { + base = 2; + } else if ((value[1] | 0x20) == 'x') { + base = 16; + } else { + return false; + } + } + + bool valid = false; + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t parsed = mp_parse_num_integer(value, value_length, base, NULL); + if (mp_obj_is_small_int(parsed)) { + *integer = MP_OBJ_SMALL_INT_VALUE(parsed); + valid = true; + } + nlr_pop(); + } + return valid; +} + +MP_NOINLINE int main_(int argc, char **argv) { pre_process_options(argc, argv); char *heap = malloc(heap_size); @@ -236,11 +283,13 @@ MP_NOINLINE int main_(int argc, char **argv) { // don't support native emitter unless -march is specified mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE; mp_dynamic_compiler.nlr_buf_num_regs = 0; + mp_dynamic_compiler.backend_options = NULL; const char *input_file = NULL; const char *output_file = NULL; const char *source_file = NULL; bool option_parsing_active = true; + const char *arch_flags = NULL; // parse main options for (int a = 1; a < argc; a++) { @@ -314,6 +363,15 @@ MP_NOINLINE int main_(int argc, char **argv) { } else if (strcmp(arch, "xtensawin") == 0) { mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN; + } else if (strcmp(arch, "rv32imc") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV32IMC; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV32I; + } else if (strcmp(arch, "rv64imc") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV64IMC; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV64I; + } else if (strcmp(arch, "debug") == 0) { + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_DEBUG; + mp_dynamic_compiler.nlr_buf_num_regs = 0; } else if (strcmp(arch, "host") == 0) { #if defined(__i386__) || defined(_M_IX86) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86; @@ -324,6 +382,9 @@ MP_NOINLINE int main_(int argc, char **argv) { #elif defined(__arm__) && !defined(__thumb2__) mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6; mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP; + #elif defined(__riscv) && (__riscv_xlen == 64) + mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_RV64IMC; + mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_RV64I; #else mp_printf(&mp_stderr_print, "unable to determine host architecture for -march=host\n"); exit(1); @@ -331,6 +392,8 @@ MP_NOINLINE int main_(int argc, char **argv) { } else { return usage(argv); } + } else if (strncmp(argv[a], "-march-flags=", sizeof("-march-flags=") - 1) == 0) { + arch_flags = argv[a] + sizeof("-march-flags=") - 1; } else if (strcmp(argv[a], "--") == 0) { option_parsing_active = false; } else { @@ -345,6 +408,38 @@ MP_NOINLINE int main_(int argc, char **argv) { } } + if (arch_flags && mp_dynamic_compiler.native_arch != MP_NATIVE_ARCH_NONE) { + bool processed = false; + #if MICROPY_EMIT_NATIVE && MICROPY_EMIT_RV32 + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_RV32IMC) { + mp_dynamic_compiler.backend_options = (void *)&rv32_options; + mp_uint_t raw_flags = 0; + if (parse_integer(arch_flags, &raw_flags)) { + if ((raw_flags & ~((mp_uint_t)RV32_EXT_ALL)) == 0) { + rv32_options.allowed_extensions = raw_flags; + processed = true; + } + } else if (strncmp(arch_flags, "zba", sizeof("zba") - 1) == 0) { + rv32_options.allowed_extensions |= RV32_EXT_ZBA; + processed = true; + } + } + #endif + if (!processed) { + mp_printf(&mp_stderr_print, "unrecognised arch flags\n"); + exit(1); + } + } + + #if MICROPY_EMIT_NATIVE + if ((MP_STATE_VM(default_emit_opt) == MP_EMIT_OPT_NATIVE_PYTHON + || MP_STATE_VM(default_emit_opt) == MP_EMIT_OPT_VIPER) + && mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_NONE) { + mp_printf(&mp_stderr_print, "arch not specified\n"); + exit(1); + } + #endif + if (input_file == NULL) { mp_printf(&mp_stderr_print, "no input file\n"); exit(1); @@ -364,7 +459,7 @@ MP_NOINLINE int main_(int argc, char **argv) { } int main(int argc, char **argv) { - mp_stack_ctrl_init(); + mp_cstack_init_with_sp_here(40000 * (sizeof(void *) / 4)); return main_(argc, argv); } diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index bdd10efdaea00..36bcbc113941c 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -50,11 +50,16 @@ #define MICROPY_EMIT_XTENSA (1) #define MICROPY_EMIT_INLINE_XTENSA (1) #define MICROPY_EMIT_XTENSAWIN (1) +#define MICROPY_EMIT_RV32 (1) +#define MICROPY_EMIT_INLINE_RV32 (1) +#define MICROPY_EMIT_NATIVE_DEBUG (1) +#define MICROPY_EMIT_NATIVE_DEBUG_PRINTER (&mp_stdout_print) #define MICROPY_DYNAMIC_COMPILER (1) #define MICROPY_COMP_CONST_FOLDING (1) #define MICROPY_COMP_MODULE_CONST (1) #define MICROPY_COMP_CONST (1) +#define MICROPY_COMP_CONST_FLOAT (1) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1) #define MICROPY_COMP_RETURN_IF_EXPR (1) @@ -86,11 +91,12 @@ #define MICROPY_GCREGS_SETJMP (1) #endif -#define MICROPY_PY___FILE__ (0) +#define MICROPY_MODULE___FILE__ (0) #define MICROPY_PY_ARRAY (0) #define MICROPY_PY_ATTRTUPLE (0) #define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) +#define MICROPY_PY_MATH (MICROPY_COMP_CONST_FLOAT) +#define MICROPY_PY_MATH_CONSTANTS (MICROPY_COMP_CONST_FLOAT) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_GC (0) #define MICROPY_PY_IO (0) @@ -98,23 +104,6 @@ // type definitions for the specific machine -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#elif defined(__MINGW32__) && defined(_WIN64) -#include -typedef __int64 mp_int_t; -typedef unsigned __int64 mp_uint_t; -#elif defined(_MSC_VER) && defined(_WIN64) -typedef __int64 mp_int_t; -typedef unsigned __int64 mp_uint_t; -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless for actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif - // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; @@ -139,7 +128,7 @@ typedef long mp_off_t; #ifdef _MSC_VER #define MP_ENDIANNESS_LITTLE (1) -#define NORETURN __declspec(noreturn) +#define MP_NORETURN __declspec(noreturn) #define MP_NOINLINE __declspec(noinline) #define MP_ALWAYSINLINE __forceinline #define MP_LIKELY(x) (x) @@ -169,3 +158,5 @@ typedef int ssize_t; typedef mp_off_t off_t; #endif + +extern const struct _mp_print_t mp_stdout_print; diff --git a/mpy-cross/mpy_cross/__init__.py b/mpy-cross/mpy_cross/__init__.py index 5020033e8c808..6d7002a3b89d2 100644 --- a/mpy-cross/mpy_cross/__init__.py +++ b/mpy-cross/mpy_cross/__init__.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import os import re import stat @@ -43,6 +42,8 @@ "NATIVE_ARCH_ARMV7EMDP": "armv7emdp", "NATIVE_ARCH_XTENSA": "xtensa", "NATIVE_ARCH_XTENSAWIN": "xtensawin", + "NATIVE_ARCH_RV32IMC": "rv32imc", + "NATIVE_ARCH_RV64IMC": "rv64imc", } globals().update(NATIVE_ARCHS) diff --git a/mpy-cross/mpy_cross/__main__.py b/mpy-cross/mpy_cross/__main__.py index 2b6b81c333362..fe78a9e077e77 100644 --- a/mpy-cross/mpy_cross/__main__.py +++ b/mpy-cross/mpy_cross/__main__.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import argparse import sys diff --git a/mpy-cross/windows-fmode.c b/mpy-cross/windows-fmode.c index a7976b87e32dc..128c951ec40cd 100644 --- a/mpy-cross/windows-fmode.c +++ b/mpy-cross/windows-fmode.c @@ -31,7 +31,7 @@ // Workaround for setting file translation mode: we must distinguish toolsets // since mingw has no _set_fmode, and altering msvc's _fmode directly has no effect -STATIC int set_fmode_impl(int mode) { +static int set_fmode_impl(int mode) { #ifndef _MSC_VER _fmode = mode; return 0; diff --git a/ports/analog/Makefile b/ports/analog/Makefile new file mode 100644 index 0000000000000..6b86bd7039636 --- /dev/null +++ b/ports/analog/Makefile @@ -0,0 +1,314 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +# SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +# +# SPDX-License-Identifier: MIT + +BOARD ?= apard32690 +CROSS_COMPILE = arm-none-eabi- + +# Includes mpconfigboard.mk & mpconfigport.mk, +# along with numerous other shared environment makefiles. +include ../../py/circuitpy_mkenv.mk + +# MCU_SERIES e.g. "max32" +# MCU_VARIANT e.g. "max32690" +# defined in mpconfigboard.mk +MCU_SERIES_LOWER := $(shell echo $(MCU_SERIES) | tr '[:upper:]' '[:lower:]') +MCU_SERIES_UPPER := $(shell echo $(MCU_SERIES) | tr '[:lower:]' '[:upper:]') +MCU_VARIANT_LOWER := $(shell echo $(MCU_VARIANT) | tr '[:upper:]' '[:lower:]') +MCU_VARIANT_UPPER := $(shell echo $(MCU_VARIANT) | tr '[:lower:]' '[:upper:]') + + +# ******************************************************************************* +#### MSDK INCLUDES #### +# Necessary for msdk makefiles +TARGET := $(MCU_VARIANT_UPPER) +TARGET_UC := $(MCU_VARIANT_UPPER) +TARGET_LC := $(MCU_VARIANT_LOWER) + +MSDK_ROOT = ./msdk +MSDK_LIBS = $(MSDK_ROOT)/Libraries +CMSIS_ROOT = $(MSDK_LIBS)/CMSIS +ADI_PERIPH = $(MSDK_ROOT)/Libraries/PeriphDrivers +ADI_MISC_DRIVERS_DIR ?= $(MSDK_LIBS)/MiscDrivers +ADI_BOARD_DIR = $(MSDK_LIBS)/Boards/$(MCU_VARIANT_UPPER)/$(BOARD) + +# For debugging the build +ifneq ($(BUILD_VERBOSE),"") +$(info MSDK_ROOT is $(MSDK_ROOT)) +$(info MSDK_LIBS is $(MSDK_LIBS)) +$(info CMSIS_ROOT is $(CMSIS_ROOT)) +$(info ADI_PERIPH is $(ADI_PERIPH)) +$(info ADI_MISC_DRIVERS_DIR is $(ADI_MISC_DRIVERS_DIR)) +$(info ADI_BOARD_DIR is $(ADI_BOARD_DIR)) +$(info MAXIM_PATH is $(MAXIM_PATH)) +endif + +# ----------------- +# Sources & Include +# ----------------- +# Define max32 die type for PeriphDriver Includes +# default to me18 for max32690 +# more info: +# https://analogdevicesinc.github.io/msdk//USERGUIDE/#die-types-to-part-numbers +ifeq ($(MCU_VARIANT_LOWER), "max32690") +DIE_TYPE=me18 +else +DIE_TYPE=me18 +endif + +PERIPH_SRC = $(ADI_PERIPH)/Source +PERIPH_INC = $(ADI_PERIPH)/Include/$(MCU_VARIANT_UPPER) + +INC += -I. +INC += -I../.. +INC += -I$(BUILD) +INC += -I$(BUILD)/genhdr +INC += -I./../../lib/cmsis/inc +INC += -I./boards/ +INC += -I./boards/$(BOARD) +INC += -I./peripherals/ +INC += -I../../lib/mp-readline + +INC += \ + -I$(TOP)/$(BOARD_PATH) \ + -I$(TOP)/lib/cmsis/inc \ + -I$(CMSIS_ROOT)/Include \ + -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Include \ + -I$(PERIPH_INC) \ + -I$(PERIPH_SRC)/SYS \ + -I$(PERIPH_SRC)/CTB \ + -I$(PERIPH_SRC)/DMA \ + -I$(PERIPH_SRC)/FLC \ + -I$(PERIPH_SRC)/GPIO \ + -I$(PERIPH_SRC)/ICC \ + -I$(PERIPH_SRC)/TMR \ + -I$(PERIPH_SRC)/RTC \ + -I$(PERIPH_SRC)/UART \ + -I$(PERIPH_SRC)/TRNG \ + -I$(PERIPH_SRC)/I2C \ + -I$(PERIPH_SRC)/SPI + +INC += -I$(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC + +SRC_MAX32 += \ + $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/heap.c \ + $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/system_$(MCU_VARIANT_LOWER).c \ + $(PERIPH_SRC)/SYS/mxc_assert.c \ + $(PERIPH_SRC)/SYS/mxc_delay.c \ + $(PERIPH_SRC)/SYS/mxc_lock.c \ + $(PERIPH_SRC)/SYS/nvic_table.c \ + $(PERIPH_SRC)/SYS/pins_$(DIE_TYPE).c \ + $(PERIPH_SRC)/SYS/sys_$(DIE_TYPE).c \ + $(PERIPH_SRC)/CTB/ctb_$(DIE_TYPE).c \ + $(PERIPH_SRC)/CTB/ctb_reva.c \ + $(PERIPH_SRC)/CTB/ctb_common.c \ + $(PERIPH_SRC)/DMA/dma_reva.c \ + $(PERIPH_SRC)/DMA/dma_$(DIE_TYPE).c \ + $(PERIPH_SRC)/FLC/flc_common.c \ + $(PERIPH_SRC)/FLC/flc_$(DIE_TYPE).c \ + $(PERIPH_SRC)/FLC/flc_reva.c \ + $(PERIPH_SRC)/GPIO/gpio_common.c \ + $(PERIPH_SRC)/GPIO/gpio_$(DIE_TYPE).c \ + $(PERIPH_SRC)/GPIO/gpio_reva.c \ + $(PERIPH_SRC)/ICC/icc_$(DIE_TYPE).c \ + $(PERIPH_SRC)/ICC/icc_reva.c \ + $(PERIPH_SRC)/RTC/rtc_$(DIE_TYPE).c \ + $(PERIPH_SRC)/RTC/rtc_reva.c \ + $(PERIPH_SRC)/TMR/tmr_common.c \ + $(PERIPH_SRC)/TMR/tmr_revb.c \ + $(PERIPH_SRC)/TMR/tmr_$(DIE_TYPE).c \ + $(PERIPH_SRC)/UART/uart_common.c \ + $(PERIPH_SRC)/UART/uart_$(DIE_TYPE).c \ + $(PERIPH_SRC)/UART/uart_revb.c \ + $(PERIPH_SRC)/TRNG/trng_revb.c \ + $(PERIPH_SRC)/TRNG/trng_$(DIE_TYPE).c \ + $(PERIPH_SRC)/I2C/i2c_$(DIE_TYPE).c \ + $(PERIPH_SRC)/I2C/i2c_reva.c \ + $(PERIPH_SRC)/SPI/spi_$(DIE_TYPE).c \ + $(PERIPH_SRC)/SPI/spi_reva1.c + +SRC_C += $(SRC_MAX32) \ + boards/$(BOARD)/board.c \ + boards/$(BOARD)/pins.c \ + peripherals/$(MCU_VARIANT_LOWER)/pins.c \ + peripherals/$(MCU_VARIANT_LOWER)/gpios.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_uart.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_i2c.c \ + peripherals/$(MCU_VARIANT_LOWER)/max32_spi.c + +# ******************************************************************************* +### Compiler & Linker Flags ### +COMPILER ?= GCC + +ifeq ($(COMPILER), GCC) + +STARTUPFILE = $(CMSIS_ROOT)/Device/Maxim/$(MCU_VARIANT_UPPER)/Source/GCC/startup_$(MCU_VARIANT_LOWER).s +# STARTUPFILE = $(ADI_BOARD_DIR)/Source/startup_$(MCU_VARIANT_LOWER).s + +# CircuitPython custom linkerfile (necessary for build steps & filesystems) +LINKERFILE = linking/$(MCU_VARIANT_LOWER)_cktpy.ld +LDFLAGS += -nostartfiles -specs=nano.specs +endif + +SRC_S += $(STARTUPFILE) +SRC_S += shared/runtime/gchelper_thumb2.s + +SRC_C += shared/runtime/gchelper_native.c + +# Needed to compile some MAX32 headers +CFLAGS += -D$(MCU_VARIANT_UPPER) \ + -DTARGET_REV=0x4131 \ + -DTARGET=$(MCU_VARIANT_UPPER) \ + -DIAR_PRAGMAS=0 \ + -DRISCV_LOAD=0 \ + -DCONFIG_TRUSTED_EXECUTION_SECURE=0 + +# todo: add these for linkerfiles later on so that it's easier to add new boards +# -DFLASH_ORIGIN \ +# -DFLASH_SIZE \ +# -DSRAM_ORIGIN \ +# -DSRAM_SIZE + +CPU_CORE=cortex-m4 +CFLAGS += -mthumb -mcpu=$(CPU_CORE) -mfloat-abi=softfp -mfpu=fpv4-sp-d16 + +# NOTE: Start with DEBUG=1 defaults for now +ifeq ($(DEBUG),) +DEBUG ?= 1 +endif + +ifeq ($(DEBUG),1) +COPT = -ggdb3 -Og -Os +else +COPT += -Os +endif + +# TinyUSB CFLAGS +CFLAGS += \ + -DCFG_TUSB_MCU=OPT_MCU_$(MCU_VARIANT_UPPER) \ + -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED \ + -DCFG_TUSB_OS=OPT_OS_NONE \ + -DCFG_TUD_CDC_TX_BUFSIZE=1024 \ + -DCFG_TUD_CDC_RX_BUFSIZE=1024 \ + -DCFG_TUD_MSC_BUFSIZE=4096 \ + -DCFG_TUD_MIDI_RX_BUFSIZE=128 \ + -DCFG_TUD_MIDI_TX_BUFSIZE=128 \ + -DCFG_TUD_VENDOR_RX_BUFSIZE=1024 \ + -DCFG_TUD_VENDOR_TX_BUFSIZE=1024 + +# Add TinyUSB sources +INC += -I../../lib/tinyusb/src +INC += -I../../supervisor/shared/usb +SRC_C += lib/tinyusb/src/portable/mentor/musb/dcd_musb.c + +# Add port sources incl. any board functions +SRC_C += \ + boards/$(BOARD)/board.c \ + background.c \ + mphalport.c \ + +CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostartfiles $(BASE_CFLAGS) $(COPT) + +# Suppress some errors for MSDK +# cast-align warning will be suppressed; +# it gets generated by CircuitPy's TLSF memory allocator lib +CFLAGS += -Wno-error=unused-parameter \ + -Wno-error=old-style-declaration \ + -Wno-error=sign-compare \ + -Wno-error=strict-prototypes \ + -Wno-error=cast-qual \ + -Wno-error=unused-variable \ + -Wno-error=lto-type-mismatch \ + -Wno-error=cast-align \ + -Wno-error=nested-externs \ + -Wno-error=sign-compare \ + -Wno-cast-align \ + -Wno-sign-compare \ + +ENTRY = Reset_Handler +LDFLAGS += $(CFLAGS) --entry $(ENTRY) -Wl,-nostdlib -Wl,-T,$(LINKERFILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections +LIBS := -lgcc -lc + +# If not using CKTPY mathlib, use toolchain mathlib +ifndef INTERNAL_LIBM +LIBS += -lm +endif + +# ******************************************************************************* +### PORT-DEFINED BUILD RULES ### +# This section attempts to build the Python core, the supervisor, and any +# port-provided source code. +# +# QSTR sources are provided for the initial build step, which generates +# Python constants to represent C data which gets passed into the GC. + +# OBJ includes +OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) +ifeq ($(INTERNAL_LIBM),1) +OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) +endif +OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) + +# List of sources for qstr extraction +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_CIRCUITPY_COMMON) \ + $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_MOD) +# Sources that only hold QSTRs after pre-processing. +SRC_QSTR_PREPROCESSOR += + +# Default build target +all: $(BUILD)/firmware.elf $(BUILD)/firmware.hex $(BUILD)/firmware.bin + +clean-all: + rm -rf build-* + +# Optional flash option when running within an installed MSDK to use OpenOCD +# Mainline OpenOCD does not yet have the MAX32's flash algorithm integrated. +# If the MSDK is installed, flash-msdk can be run to utilize the the modified +# openocd with the algorithms +MAXIM_PATH := $(subst \,/,$(MAXIM_PATH)) +OPENOCD ?= $(MAXIM_PATH)/Tools/OpenOCD/openocd +OPENOCD_SCRIPTS ?= $(MAXIM_PATH)/Tools/OpenOCD/scripts +flash-msdk: + $(OPENOCD) -s $(OPENOCD_SCRIPTS) \ + -f interface/cmsis-dap.cfg -f target/$(MCU_VARIANT_LOWER).cfg \ + -c "program $(BUILD)/firmware.elf verify; init; reset; exit" + +flash-openocd-jlink: + $(OPENOCD) -s $(OPENOCD_SCRIPTS) \ + -f interface/jlink.cfg -f target/$(MCU_VARIANT_LOWER).cfg \ + -c "program $(BUILD)/firmware.elf verify; init; reset; exit" + +# flash target using JLink +JLINK_DEVICE = $(MCU_VARIANT_LOWER) + +JLINKEXE ?= JLink.exe +JLINKEXE += -if SWD -device ${JLINK_DEVICE} -speed 4000 +COMMAND_FILE := tools/flash_max32.jlink + +flash-jlink: $(BUILD)/firmware.bin + @$(JLINKEXE) -device $(MCU_VARIANT_UPPER) -NoGui 1 -CommandFile ${COMMAND_FILE} + +$(BUILD)/firmware.elf: $(OBJ) + $(STEPECHO) "LINK $@" + $(Q)echo $^ > $(BUILD)/firmware.objs + $(Q)$(CC) -o $@ $(LDFLAGS) @$(BUILD)/firmware.objs -Wl,--print-memory-usage -Wl,--start-group $(LIBS) -Wl,--end-group + $(Q)$(SIZE) $@ | $(PYTHON) $(TOP)/tools/build_memory_info.py $(LINKERFILE) $(BUILD) + +$(BUILD)/firmware.hex: $(BUILD)/firmware.elf + $(STEPECHO) "Create $@" + $(Q)$(OBJCOPY) -O ihex $^ $@ + +$(BUILD)/firmware.bin: $(BUILD)/firmware.elf + $(STEPECHO) "Create $@" + $(Q)$(OBJCOPY) -O binary $^ $@ + +# ******************************************************************************* +### CKTPY BUILD RULES ### +include $(TOP)/py/mkrules.mk diff --git a/ports/analog/README.md b/ports/analog/README.md new file mode 100644 index 0000000000000..fa5ab1f4a7783 --- /dev/null +++ b/ports/analog/README.md @@ -0,0 +1,59 @@ +# Analog Devices "MAX32" MCUs + +This port brings CircuitPython to ADI's "MAX32" series of microcontrollers. These devices are mostly ARM Cortex-M4-based and focus on delivering performance at low-power levels. Currently this port only supports MAX32690. + +## Structure of this port + +- **`boards/:`** Board-specific definitions including pins, board initialization, etc. +- **`common-hal/:`** Port-specific implementations of CircuitPython common-hal APIs. When a new module is enabled, this is often where the implementation is found. Expected functions for modules in `common-hal` are usually found in `shared-bindings/` or `shared-module/` in the CircuitPy root directory. +- **`linking/:`** Linkerfiles customized for CircuitPython. These are distinct from the linkerfiles used in MSDK as they adopt the structure required by CircuitPython. They may also omit unused features and memory sections, e.g. Mailboxes, RISC-V Flash, & Hyperbus RAM for MAX32690. +- **`msdk:/`** SDK for MAX32 devices. More info on our GitHub: [Analog Devices MSDK GitHub](https://github.com/analogdevicesinc/msdk) +- **`peripherals:/`** Helper files for peripherals such as clocks, gpio, etc. These files tend to be specific to vendor SDKs and provide some useful functions for the common-hal interfaces. +- **`supervisor/:`** Implementation files for the CircuitPython supervisor. This includes port setup, usb, and a filesystem on a storage medium such as SD Card/eMMC, QSPI Flash, or internal flash memory. Currently the internal flash is used. This folder is the most important part of a port's core functionality for CircuitPython. +- **`supervisor/port.c:`** Port-specific startup code including clock initialization, console startup, etc. + +- `. :` Build system and high-level interface to the CircuitPython core for the ADI port. + +## Building for MAX32 devices + +Ensure CircuitPython dependencies are up-to-date by following the CircuitPython introduction on Adafruit's Website: [Building CircuitPython - Introduction](https://learn.adafruit.com/building-circuitpython/introduction). You will require the [ARM GNU Toolchain](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads), with ARM GCC >=13.x. It is also necessary to fetch all submodules and build the `mpy-cross` compiler, per the "Building CircuitPython" guide. + +Ensure the ARM toolchain is contained on your PATH. This can be done in MinGW or WSL by exporting a prefix to the PATH variable. The author's path is included below as an example: + + $ export ARM_GNU_PATH=C:/x-tools/arm-win/arm-none-eabi-w64-i686-13.3rel1/bin + $ export PATH=$ARM_GNU_PATH:$PATH + +This needs to be done each time you open a command environment to build CircuitPython. It can be useful to set up a simple shell script for this. + +Once you have built `mpy-cross` and set up your build system for CircuitPython, you can build for MAX32 devices using the following commands: + + $ cd ports/analog + $ make BOARD= + +Be aware the build may take a long time without parallelizing via the `-jN` flag, where N is the # of cores on your machine. + +## Flashing the board + +Universal instructions on flashing MAX32 devices this project can be found in the **[MSDK User Guide](https://analogdevicesinc.github.io/msdk/USERGUIDE/)**. + +In addition, a user may flash the device by calling `make` with the `flash-msdk` target from within the `ports/analog` directory, as below: + +``` +$ make BOARD= flash-msdk +``` + +This requires the following: +- A MAX32625PICO is connected to the PC via USB +- The PICO board shows up as a "DAPLINK" drive which implements the CMSIS-DAP interface. +- The PICO board is connected to the target board via a 10-pin SWD ribbon cable. + - If SWD connectors are not keyed, the P1 indicator (red line) on the SWD ribbon cable should match the P1 indicator on the board silkscreen near the 10-pin SWD connector. + +## Using the REPL + +Once the device is plugged in, it will enumerate via USB as both a USB Serial Device (CDC) and a Mass Storage Device (MSC). You can connect to the Python REPL with your favorite Serial Monitor program e.g. TeraTerm, VS Code, Putty, etc. Use any buadrate with 8-bit, No Parity, 1 Stop Bit (8N1) settings. From this point forward, you can run Python code on the MCU! If you want help with learning CircuitPython-specific code or learning Python in general, a good place to start is Adafruit's ["Welcome to CircuitPython"](https://learn.adafruit.com/welcome-to-circuitpython/) guide. + +## Editing code.py + +Python code may be executed from `code.py` the `CIRCUITPY:` drive. When editing this file, please be aware that some text editors will work better than others. A list of suggested text editors can be found at Adafruit's guide here: https://learn.adafruit.com/welcome-to-circuitpython/recommended-editors + +Once you save `code.py`, it gets written back to the device you are running Circuitpython on, and will automatically run and output it's result to the REPL. You can also automatically reload and run code.py any time from the REPL by pressing CTRL+D. diff --git a/ports/analog/background.c b/ports/analog/background.c new file mode 100644 index 0000000000000..ad840c6dcdabc --- /dev/null +++ b/ports/analog/background.c @@ -0,0 +1,43 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "supervisor/filesystem.h" +#include "supervisor/usb.h" +#include "supervisor/shared/stack.h" + +#include "max32_port.h" + +// From boards/$(BOARD)/board.c +extern const mxc_gpio_cfg_t pb_pin[]; +extern const int num_pbs; +extern const mxc_gpio_cfg_t led_pin[]; +extern const int num_leds; + +/** NOTE: ALL "ticks" refer to a 1/1024 s period */ +static int status_ticks = 0; + +// This function is where port-specific background +// tasks should be performed +// Execute port specific actions during background tick. Only if ticks are enabled. +void port_background_tick(void) { + status_ticks++; +} + +// Execute port specific actions during background tasks. This is before the +// background callback system and happens *very* often. Use +// port_background_tick() when possible. +void port_background_task(void) { +} + +// Take port specific actions at the beginning and end of background ticks. +// This is used e.g., to set a monitoring pin for debug purposes. "Actual +// work" should be done in port_background_tick() instead. +void port_start_background_tick(void) { +} +void port_finish_background_tick(void) { +} diff --git a/ports/analog/background.h b/ports/analog/background.h new file mode 100644 index 0000000000000..d32f2b0dc2c3d --- /dev/null +++ b/ports/analog/background.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_BACKGROUND_H +#define MICROPY_INCLUDED_BACKGROUND_H + +#endif // MICROPY_INCLUDED_BACKGROUND_H diff --git a/ports/analog/boards/apard32690/README.md b/ports/analog/boards/apard32690/README.md new file mode 100644 index 0000000000000..960a26a007f2f --- /dev/null +++ b/ports/analog/boards/apard32690/README.md @@ -0,0 +1,36 @@ +# AD-APARD32690-SL + +This board features the MAX32690, a dual-core ARM Cortex-M4/RISC-V MCU with 3MiB Flash, 1MiB SRAM. The board also has support for 10BASE-T1L Ethernet, Wifi, Bluetooth, USB, and Security via MAXQ1065. However, most of these features are not yet available for this CircuitPython port (USB will be added soon; others are currently unplanned). + +## Onboard connectors & peripherals + +This board comes in a form-factor similar to an Arduino Mega, enabling Arduino-style shield boards to be plugged in and evaluated with the MAX32690. This vastly opens up the options for easily plugging peripherals into the board, especially when combined with the two Pmod:tm: connectors, P8 (SPI) and P13 (I2C). + +## Product Resources + +For more info about AD-APARD32690-SL, visit our product webpages for datasheets, User Guides, Software, and Design Documents: + +[AD-APARD32690-SL Product Webpage](https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/ad-apard32690-sl.html) +[AD-APARD32690-SL User Guide](https://wiki.analog.com/resources/eval/user-guides/ad-apard32690-sl) + +### Building for this board + +To build for this board, ensure you are in the `ports/analog` directory and run the following command. Note that passing in the `-jN` flag, where N is the # of cores on your machine, can speed up compile times. + +``` +make BOARD=apard32690 +``` + +### Flashing this board + +To flash the board, run the following command if using the MAX32625PICO: + +``` +make BOARD=APARD flash-msdk +``` + +If using Segger JLink, please run the following command instead: + +``` +make BOARD=APARD flash-jlink +``` diff --git a/ports/analog/boards/apard32690/board.c b/ports/analog/boards/apard32690/board.c new file mode 100644 index 0000000000000..76c3e7f5591f4 --- /dev/null +++ b/ports/analog/boards/apard32690/board.c @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "supervisor/port.h" +#include "mpconfigboard.h" +#include "max32_port.h" + +/***** OPTIONAL BOARD-SPECIFIC FUNCTIONS from supervisor/board.h *****/ +// DEFAULT: Using the weak-defined supervisor/shared/board.c functions + +// Initializes board related state once on start up. +void board_init(void) { +} + +// Returns true if the user initiates safe mode in a board specific way. +// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific +// way. +// bool board_requests_safe_mode(void); + +// Reset the state of off MCU components such as neopixels. +// void reset_board(void); + +// Deinit the board. This should put the board in deep sleep durable, low power +// state. It should not prevent the user access method from working (such as +// disabling USB, BLE or flash) because CircuitPython may continue to run. +// void board_deinit(void); + +/*******************************************************************/ diff --git a/ports/analog/boards/apard32690/mpconfigboard.h b/ports/analog/boards/apard32690/mpconfigboard.h new file mode 100644 index 0000000000000..19b75a79d8103 --- /dev/null +++ b/ports/analog/boards/apard32690/mpconfigboard.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc. +// +// SPDX-License-Identifier: MIT + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "APARD32690" +#define MICROPY_HW_MCU_NAME "max32690" + +#define FLASH_SIZE (0x300000) // 3MiB +#define FLASH_PAGE_SIZE (0x4000) // 16384 byte pages (16 KiB) + +#define BOARD_HAS_CRYSTAL 1 +#define NUM_GPIO_PORTS 5 +#define CONSOLE_UART MXC_UART0 + +// #if INTERNAL_FLASH_FILESYSTEM +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x102E0000) // for MAX32690 +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (128 * 1024) // 64K + +#define MAX32_FLASH_SIZE 0x300000 // 3 MiB +#define INTERNAL_FLASH_FILESYSTEM_SIZE CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x102E0000 // Load into the last MiB of code/data storage + +// #else +// #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0) +// #endif + + #define MICROPY_HW_LED_STATUS (&pin_P2_01) diff --git a/ports/analog/boards/apard32690/mpconfigboard.mk b/ports/analog/boards/apard32690/mpconfigboard.mk new file mode 100644 index 0000000000000..0e62f25f3f859 --- /dev/null +++ b/ports/analog/boards/apard32690/mpconfigboard.mk @@ -0,0 +1,31 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +# +# SPDX-License-Identifier: MIT + +MCU_SERIES=max32 +MCU_VARIANT=max32690 + +INTERNAL_FLASH_FILESYSTEM=1 +# FLASH: 0x10000000 to 0x10300000 (ARM) +# SRAM: 0x20000000 to 0x20100000 + +#### USB CONFIGURATION +# Use 0x0456 for Analog Devices, Inc.; 0B6A for Maxim +USB_VID=0x0456 +# USB_VID=0x0B6A +USB_PID=0x003C +USB_MANUFACTURER="Analog Devices, Inc." +USB_PRODUCT="MAX32690 APARD" + +# NOTE: MAX32 devices do not support IN/OUT pairs on the same EP +USB_NUM_ENDPOINT_PAIRS=12 +### + +# define UID len for memory safety (buffer gets passed as a raw ptr) +COMMON_HAL_MCU_PROCESSOR_UID_LENGTH=30 + +# NOTE: Not implementing external flash for now +# CFLAGS+=-DEXT_FLASH_MX25 diff --git a/ports/analog/boards/apard32690/pins.c b/ports/analog/boards/apard32690/pins.c new file mode 100644 index 0000000000000..f4970aff7aebf --- /dev/null +++ b/ports/analog/boards/apard32690/pins.c @@ -0,0 +1,133 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + // P0 + { MP_ROM_QSTR(MP_QSTR_P0_0), MP_ROM_PTR(&pin_P0_00) }, + { MP_ROM_QSTR(MP_QSTR_P0_1), MP_ROM_PTR(&pin_P0_01) }, + { MP_ROM_QSTR(MP_QSTR_P0_2), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_P0_3), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_P0_4), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_P0_5), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_P0_6), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_P0_7), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_P0_8), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P0_9), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) }, + { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) }, + { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) }, + // P1 + { MP_ROM_QSTR(MP_QSTR_P1_0), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_P1_1), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_P1_2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_P1_3), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_P1_4), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_P1_5), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_P1_6), MP_ROM_PTR(&pin_P1_06) }, + { MP_ROM_QSTR(MP_QSTR_P1_7), MP_ROM_PTR(&pin_P1_07) }, + { MP_ROM_QSTR(MP_QSTR_P1_8), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_P1_9), MP_ROM_PTR(&pin_P1_09) }, + { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_P1_16), MP_ROM_PTR(&pin_P1_16) }, + { MP_ROM_QSTR(MP_QSTR_P1_17), MP_ROM_PTR(&pin_P1_17) }, + { MP_ROM_QSTR(MP_QSTR_P1_18), MP_ROM_PTR(&pin_P1_18) }, + { MP_ROM_QSTR(MP_QSTR_P1_19), MP_ROM_PTR(&pin_P1_19) }, + { MP_ROM_QSTR(MP_QSTR_P1_20), MP_ROM_PTR(&pin_P1_20) }, + { MP_ROM_QSTR(MP_QSTR_P1_21), MP_ROM_PTR(&pin_P1_21) }, + { MP_ROM_QSTR(MP_QSTR_P1_22), MP_ROM_PTR(&pin_P1_22) }, + { MP_ROM_QSTR(MP_QSTR_P1_23), MP_ROM_PTR(&pin_P1_23) }, + { MP_ROM_QSTR(MP_QSTR_P1_24), MP_ROM_PTR(&pin_P1_24) }, + { MP_ROM_QSTR(MP_QSTR_P1_25), MP_ROM_PTR(&pin_P1_25) }, + { MP_ROM_QSTR(MP_QSTR_P1_26), MP_ROM_PTR(&pin_P1_26) }, + { MP_ROM_QSTR(MP_QSTR_P1_27), MP_ROM_PTR(&pin_P1_27) }, + { MP_ROM_QSTR(MP_QSTR_P1_28), MP_ROM_PTR(&pin_P1_28) }, + { MP_ROM_QSTR(MP_QSTR_P1_29), MP_ROM_PTR(&pin_P1_29) }, + { MP_ROM_QSTR(MP_QSTR_P1_30), MP_ROM_PTR(&pin_P1_30) }, + { MP_ROM_QSTR(MP_QSTR_P1_31), MP_ROM_PTR(&pin_P1_31) }, + // P2 + { MP_ROM_QSTR(MP_QSTR_P2_0), MP_ROM_PTR(&pin_P2_00) }, + { MP_ROM_QSTR(MP_QSTR_P2_1), MP_ROM_PTR(&pin_P2_01) }, + { MP_ROM_QSTR(MP_QSTR_P2_2), MP_ROM_PTR(&pin_P2_02) }, + { MP_ROM_QSTR(MP_QSTR_P2_3), MP_ROM_PTR(&pin_P2_03) }, + { MP_ROM_QSTR(MP_QSTR_P2_4), MP_ROM_PTR(&pin_P2_04) }, + { MP_ROM_QSTR(MP_QSTR_P2_5), MP_ROM_PTR(&pin_P2_05) }, + { MP_ROM_QSTR(MP_QSTR_P2_6), MP_ROM_PTR(&pin_P2_06) }, + { MP_ROM_QSTR(MP_QSTR_P2_7), MP_ROM_PTR(&pin_P2_07) }, + { MP_ROM_QSTR(MP_QSTR_P2_8), MP_ROM_PTR(&pin_P2_08) }, + { MP_ROM_QSTR(MP_QSTR_P2_9), MP_ROM_PTR(&pin_P2_09) }, + { MP_ROM_QSTR(MP_QSTR_P2_10), MP_ROM_PTR(&pin_P2_10) }, + { MP_ROM_QSTR(MP_QSTR_P2_11), MP_ROM_PTR(&pin_P2_11) }, + { MP_ROM_QSTR(MP_QSTR_P2_12), MP_ROM_PTR(&pin_P2_12) }, + { MP_ROM_QSTR(MP_QSTR_P2_13), MP_ROM_PTR(&pin_P2_13) }, + { MP_ROM_QSTR(MP_QSTR_P2_14), MP_ROM_PTR(&pin_P2_14) }, + { MP_ROM_QSTR(MP_QSTR_P2_15), MP_ROM_PTR(&pin_P2_15) }, + { MP_ROM_QSTR(MP_QSTR_P2_16), MP_ROM_PTR(&pin_P2_16) }, + { MP_ROM_QSTR(MP_QSTR_P2_17), MP_ROM_PTR(&pin_P2_17) }, + { MP_ROM_QSTR(MP_QSTR_P2_18), MP_ROM_PTR(&pin_P2_18) }, + { MP_ROM_QSTR(MP_QSTR_P2_19), MP_ROM_PTR(&pin_P2_19) }, + { MP_ROM_QSTR(MP_QSTR_P2_20), MP_ROM_PTR(&pin_P2_20) }, + { MP_ROM_QSTR(MP_QSTR_P2_21), MP_ROM_PTR(&pin_P2_21) }, + { MP_ROM_QSTR(MP_QSTR_P2_22), MP_ROM_PTR(&pin_P2_22) }, + { MP_ROM_QSTR(MP_QSTR_P2_23), MP_ROM_PTR(&pin_P2_23) }, + { MP_ROM_QSTR(MP_QSTR_P2_24), MP_ROM_PTR(&pin_P2_24) }, + { MP_ROM_QSTR(MP_QSTR_P2_25), MP_ROM_PTR(&pin_P2_25) }, + { MP_ROM_QSTR(MP_QSTR_P2_26), MP_ROM_PTR(&pin_P2_26) }, + { MP_ROM_QSTR(MP_QSTR_P2_27), MP_ROM_PTR(&pin_P2_27) }, + { MP_ROM_QSTR(MP_QSTR_P2_28), MP_ROM_PTR(&pin_P2_28) }, + { MP_ROM_QSTR(MP_QSTR_P2_29), MP_ROM_PTR(&pin_P2_29) }, + { MP_ROM_QSTR(MP_QSTR_P2_30), MP_ROM_PTR(&pin_P2_30) }, + { MP_ROM_QSTR(MP_QSTR_P2_31), MP_ROM_PTR(&pin_P2_31) }, + // P3 + { MP_ROM_QSTR(MP_QSTR_P3_0), MP_ROM_PTR(&pin_P3_00) }, + { MP_ROM_QSTR(MP_QSTR_P3_1), MP_ROM_PTR(&pin_P3_01) }, + { MP_ROM_QSTR(MP_QSTR_P3_2), MP_ROM_PTR(&pin_P3_02) }, + { MP_ROM_QSTR(MP_QSTR_P3_3), MP_ROM_PTR(&pin_P3_03) }, + { MP_ROM_QSTR(MP_QSTR_P3_4), MP_ROM_PTR(&pin_P3_04) }, + { MP_ROM_QSTR(MP_QSTR_P3_5), MP_ROM_PTR(&pin_P3_05) }, + { MP_ROM_QSTR(MP_QSTR_P3_6), MP_ROM_PTR(&pin_P3_06) }, + { MP_ROM_QSTR(MP_QSTR_P3_7), MP_ROM_PTR(&pin_P3_07) }, + { MP_ROM_QSTR(MP_QSTR_P3_8), MP_ROM_PTR(&pin_P3_08) }, + { MP_ROM_QSTR(MP_QSTR_P3_9), MP_ROM_PTR(&pin_P3_09) }, + // P4 + { MP_ROM_QSTR(MP_QSTR_P4_0), MP_ROM_PTR(&pin_P4_00) }, + { MP_ROM_QSTR(MP_QSTR_P4_1), MP_ROM_PTR(&pin_P4_01) }, + + // Silkscreen aliases + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_P2_01) }, + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_S2), MP_ROM_PTR(&pin_P1_27) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/analog/boards/max32690evkit/board.c b/ports/analog/boards/max32690evkit/board.c new file mode 100644 index 0000000000000..76c3e7f5591f4 --- /dev/null +++ b/ports/analog/boards/max32690evkit/board.c @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "supervisor/port.h" +#include "mpconfigboard.h" +#include "max32_port.h" + +/***** OPTIONAL BOARD-SPECIFIC FUNCTIONS from supervisor/board.h *****/ +// DEFAULT: Using the weak-defined supervisor/shared/board.c functions + +// Initializes board related state once on start up. +void board_init(void) { +} + +// Returns true if the user initiates safe mode in a board specific way. +// Also add BOARD_USER_SAFE_MODE in mpconfigboard.h to explain the board specific +// way. +// bool board_requests_safe_mode(void); + +// Reset the state of off MCU components such as neopixels. +// void reset_board(void); + +// Deinit the board. This should put the board in deep sleep durable, low power +// state. It should not prevent the user access method from working (such as +// disabling USB, BLE or flash) because CircuitPython may continue to run. +// void board_deinit(void); + +/*******************************************************************/ diff --git a/ports/analog/boards/max32690evkit/mpconfigboard.h b/ports/analog/boards/max32690evkit/mpconfigboard.h new file mode 100644 index 0000000000000..e4395e8a0ae71 --- /dev/null +++ b/ports/analog/boards/max32690evkit/mpconfigboard.h @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc. +// +// SPDX-License-Identifier: MIT + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "MAX32690 EvKit" +#define MICROPY_HW_MCU_NAME "max32690" + +#define FLASH_SIZE (0x300000) // 3MiB +#define FLASH_PAGE_SIZE (0x4000) // 16384 byte pages (16 KiB) + +#define BOARD_HAS_CRYSTAL 1 +#define NUM_GPIO_PORTS 5 +#define CONSOLE_UART MXC_UART2 + +// #if INTERNAL_FLASH_FILESYSTEM +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR (0x102E0000) // for MAX32690 +#define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (128 * 1024) // 64K + +#define MAX32_FLASH_SIZE 0x300000 // 3 MiB +#define INTERNAL_FLASH_FILESYSTEM_SIZE CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x102E0000 // Load into the last MiB of code/data storage + +// #else +// #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE (0) +// #endif + +#define MICROPY_HW_LED_STATUS (&pin_P2_12) +#define MICROPY_HW_LED_STATUS_INVERTED 1 diff --git a/ports/analog/boards/max32690evkit/mpconfigboard.mk b/ports/analog/boards/max32690evkit/mpconfigboard.mk new file mode 100644 index 0000000000000..a97bc9ddacd0b --- /dev/null +++ b/ports/analog/boards/max32690evkit/mpconfigboard.mk @@ -0,0 +1,31 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +# +# SPDX-License-Identifier: MIT + +MCU_SERIES=max32 +MCU_VARIANT=max32690 + +INTERNAL_FLASH_FILESYSTEM=1 +# FLASH: 0x10000000 to 0x10300000 (ARM) +# SRAM: 0x20000000 to 0x20100000 + +#### USB CONFIGURATION +# Use 0x0456 for Analog Devices, Inc.; 0B6A for Maxim +USB_VID=0x0456 +# USB_VID=0x0B6A +USB_PID=0x003D +USB_MANUFACTURER="Analog Devices, Inc." +USB_PRODUCT="MAX32690 EvKit" + +# NOTE: MAX32 devices do not support IN/OUT pairs on the same EP +USB_NUM_ENDPOINT_PAIRS=12 +### + +# define UID len for memory safety (buffer gets passed as a raw ptr) +COMMON_HAL_MCU_PROCESSOR_UID_LENGTH=30 + +# NOTE: Not implementing external flash for now +# CFLAGS+=-DEXT_FLASH_MX25 diff --git a/ports/analog/boards/max32690evkit/pins.c b/ports/analog/boards/max32690evkit/pins.c new file mode 100644 index 0000000000000..3270e4d62b2a1 --- /dev/null +++ b/ports/analog/boards/max32690evkit/pins.c @@ -0,0 +1,131 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + // P0 + { MP_ROM_QSTR(MP_QSTR_P0_0), MP_ROM_PTR(&pin_P0_00) }, + { MP_ROM_QSTR(MP_QSTR_P0_1), MP_ROM_PTR(&pin_P0_01) }, + { MP_ROM_QSTR(MP_QSTR_P0_2), MP_ROM_PTR(&pin_P0_02) }, + { MP_ROM_QSTR(MP_QSTR_P0_3), MP_ROM_PTR(&pin_P0_03) }, + { MP_ROM_QSTR(MP_QSTR_P0_4), MP_ROM_PTR(&pin_P0_04) }, + { MP_ROM_QSTR(MP_QSTR_P0_5), MP_ROM_PTR(&pin_P0_05) }, + { MP_ROM_QSTR(MP_QSTR_P0_6), MP_ROM_PTR(&pin_P0_06) }, + { MP_ROM_QSTR(MP_QSTR_P0_7), MP_ROM_PTR(&pin_P0_07) }, + { MP_ROM_QSTR(MP_QSTR_P0_8), MP_ROM_PTR(&pin_P0_08) }, + { MP_ROM_QSTR(MP_QSTR_P0_9), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) }, + { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) }, + { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) }, + { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) }, + { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) }, + { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) }, + { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) }, + { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) }, + { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) }, + { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) }, + { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) }, + { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) }, + { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) }, + { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) }, + { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) }, + { MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) }, + { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) }, + { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) }, + { MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) }, + { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) }, + // P1 + { MP_ROM_QSTR(MP_QSTR_P1_0), MP_ROM_PTR(&pin_P1_00) }, + { MP_ROM_QSTR(MP_QSTR_P1_1), MP_ROM_PTR(&pin_P1_01) }, + { MP_ROM_QSTR(MP_QSTR_P1_2), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_P1_3), MP_ROM_PTR(&pin_P1_03) }, + { MP_ROM_QSTR(MP_QSTR_P1_4), MP_ROM_PTR(&pin_P1_04) }, + { MP_ROM_QSTR(MP_QSTR_P1_5), MP_ROM_PTR(&pin_P1_05) }, + { MP_ROM_QSTR(MP_QSTR_P1_6), MP_ROM_PTR(&pin_P1_06) }, + { MP_ROM_QSTR(MP_QSTR_P1_7), MP_ROM_PTR(&pin_P1_07) }, + { MP_ROM_QSTR(MP_QSTR_P1_8), MP_ROM_PTR(&pin_P1_08) }, + { MP_ROM_QSTR(MP_QSTR_P1_9), MP_ROM_PTR(&pin_P1_09) }, + { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) }, + { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) }, + { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) }, + { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) }, + { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_P1_16), MP_ROM_PTR(&pin_P1_16) }, + { MP_ROM_QSTR(MP_QSTR_P1_17), MP_ROM_PTR(&pin_P1_17) }, + { MP_ROM_QSTR(MP_QSTR_P1_18), MP_ROM_PTR(&pin_P1_18) }, + { MP_ROM_QSTR(MP_QSTR_P1_19), MP_ROM_PTR(&pin_P1_19) }, + { MP_ROM_QSTR(MP_QSTR_P1_20), MP_ROM_PTR(&pin_P1_20) }, + { MP_ROM_QSTR(MP_QSTR_P1_21), MP_ROM_PTR(&pin_P1_21) }, + { MP_ROM_QSTR(MP_QSTR_P1_22), MP_ROM_PTR(&pin_P1_22) }, + { MP_ROM_QSTR(MP_QSTR_P1_23), MP_ROM_PTR(&pin_P1_23) }, + { MP_ROM_QSTR(MP_QSTR_P1_24), MP_ROM_PTR(&pin_P1_24) }, + { MP_ROM_QSTR(MP_QSTR_P1_25), MP_ROM_PTR(&pin_P1_25) }, + { MP_ROM_QSTR(MP_QSTR_P1_26), MP_ROM_PTR(&pin_P1_26) }, + { MP_ROM_QSTR(MP_QSTR_P1_27), MP_ROM_PTR(&pin_P1_27) }, + { MP_ROM_QSTR(MP_QSTR_P1_28), MP_ROM_PTR(&pin_P1_28) }, + { MP_ROM_QSTR(MP_QSTR_P1_29), MP_ROM_PTR(&pin_P1_29) }, + { MP_ROM_QSTR(MP_QSTR_P1_30), MP_ROM_PTR(&pin_P1_30) }, + { MP_ROM_QSTR(MP_QSTR_P1_31), MP_ROM_PTR(&pin_P1_31) }, + // P2 + { MP_ROM_QSTR(MP_QSTR_P2_0), MP_ROM_PTR(&pin_P2_00) }, + { MP_ROM_QSTR(MP_QSTR_P2_1), MP_ROM_PTR(&pin_P2_01) }, + { MP_ROM_QSTR(MP_QSTR_P2_2), MP_ROM_PTR(&pin_P2_02) }, + { MP_ROM_QSTR(MP_QSTR_P2_3), MP_ROM_PTR(&pin_P2_03) }, + { MP_ROM_QSTR(MP_QSTR_P2_4), MP_ROM_PTR(&pin_P2_04) }, + { MP_ROM_QSTR(MP_QSTR_P2_5), MP_ROM_PTR(&pin_P2_05) }, + { MP_ROM_QSTR(MP_QSTR_P2_6), MP_ROM_PTR(&pin_P2_06) }, + { MP_ROM_QSTR(MP_QSTR_P2_7), MP_ROM_PTR(&pin_P2_07) }, + { MP_ROM_QSTR(MP_QSTR_P2_8), MP_ROM_PTR(&pin_P2_08) }, + { MP_ROM_QSTR(MP_QSTR_P2_9), MP_ROM_PTR(&pin_P2_09) }, + { MP_ROM_QSTR(MP_QSTR_P2_10), MP_ROM_PTR(&pin_P2_10) }, + { MP_ROM_QSTR(MP_QSTR_P2_11), MP_ROM_PTR(&pin_P2_11) }, + { MP_ROM_QSTR(MP_QSTR_P2_12), MP_ROM_PTR(&pin_P2_12) }, + { MP_ROM_QSTR(MP_QSTR_P2_13), MP_ROM_PTR(&pin_P2_13) }, + { MP_ROM_QSTR(MP_QSTR_P2_14), MP_ROM_PTR(&pin_P2_14) }, + { MP_ROM_QSTR(MP_QSTR_P2_15), MP_ROM_PTR(&pin_P2_15) }, + { MP_ROM_QSTR(MP_QSTR_P2_16), MP_ROM_PTR(&pin_P2_16) }, + { MP_ROM_QSTR(MP_QSTR_P2_17), MP_ROM_PTR(&pin_P2_17) }, + { MP_ROM_QSTR(MP_QSTR_P2_18), MP_ROM_PTR(&pin_P2_18) }, + { MP_ROM_QSTR(MP_QSTR_P2_19), MP_ROM_PTR(&pin_P2_19) }, + { MP_ROM_QSTR(MP_QSTR_P2_20), MP_ROM_PTR(&pin_P2_20) }, + { MP_ROM_QSTR(MP_QSTR_P2_21), MP_ROM_PTR(&pin_P2_21) }, + { MP_ROM_QSTR(MP_QSTR_P2_22), MP_ROM_PTR(&pin_P2_22) }, + { MP_ROM_QSTR(MP_QSTR_P2_23), MP_ROM_PTR(&pin_P2_23) }, + { MP_ROM_QSTR(MP_QSTR_P2_24), MP_ROM_PTR(&pin_P2_24) }, + { MP_ROM_QSTR(MP_QSTR_P2_25), MP_ROM_PTR(&pin_P2_25) }, + { MP_ROM_QSTR(MP_QSTR_P2_26), MP_ROM_PTR(&pin_P2_26) }, + { MP_ROM_QSTR(MP_QSTR_P2_27), MP_ROM_PTR(&pin_P2_27) }, + { MP_ROM_QSTR(MP_QSTR_P2_28), MP_ROM_PTR(&pin_P2_28) }, + { MP_ROM_QSTR(MP_QSTR_P2_29), MP_ROM_PTR(&pin_P2_29) }, + { MP_ROM_QSTR(MP_QSTR_P2_30), MP_ROM_PTR(&pin_P2_30) }, + { MP_ROM_QSTR(MP_QSTR_P2_31), MP_ROM_PTR(&pin_P2_31) }, + // P3 + { MP_ROM_QSTR(MP_QSTR_P3_0), MP_ROM_PTR(&pin_P3_00) }, + { MP_ROM_QSTR(MP_QSTR_P3_1), MP_ROM_PTR(&pin_P3_01) }, + { MP_ROM_QSTR(MP_QSTR_P3_2), MP_ROM_PTR(&pin_P3_02) }, + { MP_ROM_QSTR(MP_QSTR_P3_3), MP_ROM_PTR(&pin_P3_03) }, + { MP_ROM_QSTR(MP_QSTR_P3_4), MP_ROM_PTR(&pin_P3_04) }, + { MP_ROM_QSTR(MP_QSTR_P3_5), MP_ROM_PTR(&pin_P3_05) }, + { MP_ROM_QSTR(MP_QSTR_P3_6), MP_ROM_PTR(&pin_P3_06) }, + { MP_ROM_QSTR(MP_QSTR_P3_7), MP_ROM_PTR(&pin_P3_07) }, + { MP_ROM_QSTR(MP_QSTR_P3_8), MP_ROM_PTR(&pin_P3_08) }, + { MP_ROM_QSTR(MP_QSTR_P3_9), MP_ROM_PTR(&pin_P3_09) }, + // P4 + { MP_ROM_QSTR(MP_QSTR_P4_0), MP_ROM_PTR(&pin_P4_00) }, + { MP_ROM_QSTR(MP_QSTR_P4_1), MP_ROM_PTR(&pin_P4_01) }, + + // Board silkscreen Aliases + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_P0_14) }, + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_P2_12) }, + { MP_ROM_QSTR(MP_QSTR_PB0), MP_ROM_PTR(&pin_P4_00) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/analog/common-hal/board/__init__.c b/ports/analog/common-hal/board/__init__.c new file mode 100644 index 0000000000000..bcae8371c18cd --- /dev/null +++ b/ports/analog/common-hal/board/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT diff --git a/ports/analog/common-hal/busio/I2C.c b/ports/analog/common-hal/busio/I2C.c new file mode 100644 index 0000000000000..7ebe721b3f427 --- /dev/null +++ b/ports/analog/common-hal/busio/I2C.c @@ -0,0 +1,256 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/busio/I2C.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "max32_port.h" + +#define I2C_PRIORITY 1 + +// Set each bit to indicate an active I2c +static uint8_t i2c_active = 0; +static volatile int i2c_err; + +// I2C struct for configuring GPIO pins +extern const mxc_gpio_cfg_t i2c_maps[NUM_I2C]; + +// Construct I2C protocol, this function init i2c peripheral +void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, + const mcu_pin_obj_t *scl, + const mcu_pin_obj_t *sda, + uint32_t frequency, uint32_t timeout) { + // Check for NULL Pointers && valid I2C settings + assert(self); + + /* NOTE: The validate_obj_is_free_pin() calls in shared-bindings/busio/I2C.c + will ensure that scl and sda are both pins and cannot be null + ref: https://github.com/adafruit/circuitpython/pull/10413 + */ + + // Assign I2C ID based on pins + int i2c_id = pinsToI2c(sda, scl); + if (i2c_id == -1) { + return; + } else { + self->i2c_id = i2c_id; + self->i2c_regs = MXC_I2C_GET_I2C(i2c_id); + } + + // Check for valid I2C controller + assert((self->i2c_id >= 0) && (self->i2c_id < NUM_I2C)); + assert(!(i2c_active & (1 << self->i2c_id))); + + // Attach I2C pins + self->sda = sda; + self->scl = scl; + common_hal_mcu_pin_claim(self->sda); + common_hal_mcu_pin_claim(self->scl); + + // Clear all flags + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + // Init as master, no slave address + MXC_I2C_Shutdown(self->i2c_regs); + MXC_I2C_Init(self->i2c_regs, 1, 0); + + // Set frequency arg (CircuitPython shared-bindings validate) + MXC_I2C_SetFrequency(self->i2c_regs, frequency); + + // Indicate to this module that the I2C is active + i2c_active |= (1 << self->i2c_id); + + // Set the timeout to a default value + if (timeout > 100) { + self->timeout = 1; + } else { + self->timeout = timeout; + } + + return; +} + +// Never reset I2C obj when reload +void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { + common_hal_never_reset_pin(self->sda); + common_hal_never_reset_pin(self->scl); +} + +// Check I2C status, deinited or not +bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { + return self->sda == NULL; +} + +// Deinit i2c obj, reset I2C pin +void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { + MXC_I2C_Shutdown(self->i2c_regs); + + common_hal_reset_pin(self->sda); + common_hal_reset_pin(self->scl); + + self->sda = NULL; + self->scl = NULL; +} + +// Probe device in I2C bus +bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { + uint32_t int_fl0; + bool ret = 0; + + // If not in Master mode, error out (can happen in some error conditions) + if (!(self->i2c_regs->ctrl & MXC_F_I2C_CTRL_MST_MODE)) { + return false; + } + + // Clear FIFOs & all interrupt flags + MXC_I2C_ClearRXFIFO(self->i2c_regs); + MXC_I2C_ClearTXFIFO(self->i2c_regs); + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + // Pre-load target address into transmit FIFO + addr = (addr << 1); + self->i2c_regs->fifo = addr; + + // Set start bit & wait for it to clear + MXC_I2C_Start(self->i2c_regs); + + // wait for ACK/NACK + while (!(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_ACK) && + !(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_NACK_ERR)) { + } + + // Save interrupt flags for ACK/NACK checking + int_fl0 = self->i2c_regs->intfl0; + + // Set / Wait for stop + MXC_I2C_Stop(self->i2c_regs); + + // Wait for controller not busy, then clear flags + while (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + ; + } + MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF); + + if (int_fl0 & MXC_F_I2C_INTFL0_ADDR_ACK) { + ret = true; + } else { + ret = false; + } + return ret; +} + +// Lock I2C bus +bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + + if (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) { + return false; + } else { + self->has_lock = true; + return true; + } +} + +// Check I2C lock status +bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) { + return self->has_lock; +} + +// Unlock I2C bus +void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { + self->has_lock = false; +} + +// Write data to the device selected by address +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, + const uint8_t *data, size_t len) { + + int ret; + mxc_i2c_req_t wr_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = (uint8_t *)data, + .tx_len = len, + .rx_buf = NULL, + .rx_len = 0, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&wr_req); + if (ret) { + return -MP_EIO; + } + + return 0; +} + +// Read into buffer from the device selected by address +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, + uint16_t addr, + uint8_t *data, size_t len) { + + int ret; + mxc_i2c_req_t rd_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = NULL, + .tx_len = 0, + .rx_buf = data, + .rx_len = len, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&rd_req); + if (ret) { + // Return I/O error + return -MP_EIO; + } + + return 0; +} + +// Write the bytes from out_data to the device selected by address +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, + uint8_t *out_data, size_t out_len, + uint8_t *in_data, size_t in_len) { + + int ret; + mxc_i2c_req_t wr_rd_req = { + .addr = addr, + .i2c = self->i2c_regs, + .tx_buf = out_data, + .tx_len = out_len, + .rx_buf = in_data, + .rx_len = in_len, + .callback = NULL + }; + ret = MXC_I2C_MasterTransaction(&wr_rd_req); + if (ret) { + return -MP_EIO; + } + + return 0; +} diff --git a/ports/analog/common-hal/busio/I2C.h b/ports/analog/common-hal/busio/I2C.h new file mode 100644 index 0000000000000..55c230ee2f97f --- /dev/null +++ b/ports/analog/common-hal/busio/I2C.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +// HAL-specific +#include "i2c.h" +#include "gpio.h" + +// Define a struct for what BUSIO.I2C should carry +typedef struct { + mp_obj_base_t base; + + int i2c_id; + mxc_i2c_regs_t *i2c_regs; + const mcu_pin_obj_t *scl; + const mcu_pin_obj_t *sda; + const int frequency; + + uint32_t timeout; + bool has_lock; +} busio_i2c_obj_t; diff --git a/ports/analog/common-hal/busio/SPI.c b/ports/analog/common-hal/busio/SPI.c new file mode 100644 index 0000000000000..de3856b23b3f1 --- /dev/null +++ b/ports/analog/common-hal/busio/SPI.c @@ -0,0 +1,321 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shared-bindings/busio/SPI.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "supervisor/board.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "max32_port.h" +#include "spi_reva1.h" + +// Note that any bugs introduced in this file can cause crashes +// at startupfor chips using external SPI flash. + +#define SPI_PRIORITY 1 + +typedef enum { + SPI_FREE = 0, + SPI_BUSY, +} spi_status_t; + +// Set each bit to indicate an active SPI +static uint8_t spi_active = 0; +static spi_status_t spi_status[NUM_SPI]; +static volatile int spi_err; + +// Construct SPI protocol, this function init SPI peripheral +void common_hal_busio_spi_construct(busio_spi_obj_t *self, + const mcu_pin_obj_t *sck, + const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, + bool half_duplex) { + int err = 0; + + // Check for NULL Pointer + assert(self); + + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + + // Assign SPI ID based on pins + int spi_id = pinsToSpi(mosi, miso, sck); + if (spi_id == -1) { + return; + } else { + self->spi_id = spi_id; + self->spi_regs = MXC_SPI_GET_SPI(spi_id); + } + + // Other pins default to true + mxc_spi_pins_t spi_pins = { + .clock = TRUE, + .mosi = TRUE, + .miso = TRUE, + .ss0 = FALSE, + .ss1 = FALSE, + .ss2 = FALSE, + .vddioh = true, + .drvstr = MXC_GPIO_DRVSTR_0 + }; + + assert((self->spi_id >= 0) && (self->spi_id < NUM_SPI)); + + // Init SPI controller + if ((mosi != NULL) && (miso != NULL) && (sck != NULL)) { + // spi, mastermode, quadModeUsed, numSubs, ssPolarity, frequency + err = MXC_SPI_Init(self->spi_regs, MXC_SPI_TYPE_CONTROLLER, MXC_SPI_INTERFACE_STANDARD, + 1, 0x01, 1000000, spi_pins); + MXC_GPIO_SetVSSEL(MXC_GPIO_GET_GPIO(sck->port), MXC_GPIO_VSSEL_VDDIOH, (sck->mask | miso->mask | mosi->mask | MXC_GPIO_PIN_0)); + if (err) { + // NOTE: Reuse existing messages from locales/circuitpython.pot to save space + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_SPI); + } + } else { + mp_raise_NotImplementedError(MP_ERROR_TEXT("SPI needs MOSI, MISO, and SCK")); + } + + // Attach SPI pins + self->mosi = mosi; + self->miso = miso; + self->sck = sck; + common_hal_mcu_pin_claim(self->mosi); + common_hal_mcu_pin_claim(self->miso); + common_hal_mcu_pin_claim(self->sck); + + // Indicate to this module that the SPI is active + spi_active |= (1 << self->spi_id); + + return; +} + +// Never reset SPI when reload +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + common_hal_never_reset_pin(self->mosi); + common_hal_never_reset_pin(self->miso); + common_hal_never_reset_pin(self->sck); + common_hal_never_reset_pin(self->nss); +} + +// Check SPI status, deinited or not +bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { + return self->sck == NULL; +} + +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->sck = NULL; +} + +// Deinit SPI obj +void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { + + MXC_SPI_Shutdown(self->spi_regs); + common_hal_reset_pin(self->mosi); + common_hal_reset_pin(self->miso); + common_hal_reset_pin(self->sck); + common_hal_reset_pin(self->nss); + + self->mosi = NULL; + self->miso = NULL; + self->nss = NULL; + + common_hal_busio_spi_mark_deinit(self); +} + +// Configures the SPI bus. The SPI object must be locked. +bool common_hal_busio_spi_configure(busio_spi_obj_t *self, + uint32_t baudrate, + uint8_t polarity, + uint8_t phase, + uint8_t bits) { + + mxc_spi_clkmode_t clk_mode; + int ret; + + self->baudrate = baudrate; + self->polarity = polarity; + self->phase = phase; + self->bits = bits; + + switch ((polarity << 1) | (phase)) { + case 0b00: + clk_mode = MXC_SPI_CLKMODE_0; + break; + case 0b01: + clk_mode = MXC_SPI_CLKMODE_1; + break; + case 0b10: + clk_mode = MXC_SPI_CLKMODE_2; + break; + case 0b11: + clk_mode = MXC_SPI_CLKMODE_3; + break; + default: + // should not be reachable; validated in shared-bindings/busio/SPI.c + return false; + } + + ret = MXC_SPI_SetFrequency(self->spi_regs, baudrate); + if (ret) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_baudrate); + return false; + } + ret = MXC_SPI_SetDataSize(self->spi_regs, bits); + if (ret == E_BAD_PARAM) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_bits); + return false; + } else if (ret == E_BAD_STATE) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid state")); + } + ret = MXC_SPI_SetMode(self->spi_regs, clk_mode); + if (ret) { + mp_raise_ValueError(MP_ERROR_TEXT("Failed to set SPI Clock Mode")); + return false; + } + return true; +} + +// Lock SPI bus +bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (spi_status[self->spi_id] != SPI_BUSY) { + self->has_lock = true; + return true; + } else { + return false; + } +} + +// Check SPI lock status +bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) { + return self->has_lock; +} + +// Unlock SPI bus +void common_hal_busio_spi_unlock(busio_spi_obj_t *self) { + self->has_lock = false; +} + +// Write the data contained in buffer +bool common_hal_busio_spi_write(busio_spi_obj_t *self, + const uint8_t *data, + size_t len) { + int ret = 0; + + mxc_spi_req_t wr_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = (uint8_t *)data, + .txLen = len, + .rxData = NULL, + .rxLen = 0, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = 0xFF, + }; + ret = MXC_SPI_MasterTransaction(&wr_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Read data into buffer +bool common_hal_busio_spi_read(busio_spi_obj_t *self, + uint8_t *data, size_t len, + uint8_t write_value) { + + int ret = 0; + + mxc_spi_req_t rd_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = NULL, + .txLen = len, + .rxData = data, + .rxLen = len, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = write_value, + }; + ret = MXC_SPI_MasterTransaction(&rd_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Write out the data in data_out +// while simultaneously reading data into data_in +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, + const uint8_t *data_out, + uint8_t *data_in, + size_t len) { + + int ret = 0; + + mxc_spi_req_t rd_req = { + .spi = self->spi_regs, + .ssIdx = 0, + .txCnt = 0, + .rxCnt = 0, + .txData = (uint8_t *)data_out, + .txLen = len, + .rxData = data_in, + .rxLen = len, + .ssDeassert = 1, + .completeCB = NULL, + .txDummyValue = 0xFF, + }; + ret = MXC_SPI_MasterTransaction(&rd_req); + if (ret) { + return false; + } else { + return true; + } +} + +// Get SPI baudrate +uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) { + return self->baudrate; +} + +// Get SPI phase +uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t *self) { + return self->phase; +} + +// Get SPI polarity +uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) { + return self->polarity; +} diff --git a/ports/analog/common-hal/busio/SPI.h b/ports/analog/common-hal/busio/SPI.h new file mode 100644 index 0000000000000..d10601876fb5e --- /dev/null +++ b/ports/analog/common-hal/busio/SPI.h @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H +#define MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +// HAL-specific +#include "spi.h" + +// Define a struct for what BUSIO.SPI should carry +typedef struct { + mp_obj_base_t base; + + // Spi regs & pins + int spi_id; + mxc_spi_regs_t *spi_regs; + const mcu_pin_obj_t *sck; + const mcu_pin_obj_t *mosi; + const mcu_pin_obj_t *miso; + const mcu_pin_obj_t *nss; + + // Configuration + uint32_t baudrate; + uint16_t prescaler; + uint8_t polarity; + uint8_t phase; + uint8_t bits; + + // Synch data + bool has_lock; +} busio_spi_obj_t; + +void spi_reset(void); + +#endif // MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_SPI_H diff --git a/ports/analog/common-hal/busio/UART.c b/ports/analog/common-hal/busio/UART.c new file mode 100644 index 0000000000000..be7851f52a21c --- /dev/null +++ b/ports/analog/common-hal/busio/UART.c @@ -0,0 +1,460 @@ +/* + * This file is part of Adafruit for EFR32 project + * + * The MIT License (MIT) + * + * Copyright 2023 Silicon Laboratories Inc. www.silabs.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if CIRCUITPY_BUSIO_UART + +#include "mpconfigport.h" +#include "supervisor/shared/tick.h" + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/UART.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared/readline/readline.h" +#include "shared/runtime/interrupt_char.h" + +#include "py/gc.h" +#include "py/ringbuf.h" +#include "py/mperrno.h" +#include "py/mpprint.h" +#include "py/runtime.h" + +#include "max32_port.h" +#include "UART.h" +#include "nvic_table.h" + +// UART IRQ Priority +#define UART_PRIORITY 1 + +typedef enum { + UART_9600 = 9600, + UART_14400 = 14400, + UART_19200 = 19200, + UART_38400 = 38400, + UART_57600 = 57600, + UART_115200 = 115200, + UART_230400 = 230400, + UART_460800 = 460800, + UART_921600 = 921600, +} uart_valid_baudrates; + +typedef enum { + UART_FREE = 0, + UART_BUSY, + UART_NEVER_RESET, +} uart_status_t; + +static uint32_t timeout_ms = 0; + +// Set each bit to indicate an active UART +// will be checked by ISR Handler for which ones to call +static uint8_t uarts_active = 0; +static uart_status_t uart_status[NUM_UARTS]; +static volatile int uart_err; +static uint8_t uart_never_reset_mask = 0; +static busio_uart_obj_t *context; + +static bool isValidBaudrate(uint32_t baudrate) { + switch (baudrate) { + case UART_9600: + return true; + break; + case UART_14400: + return true; + break; + case UART_19200: + return true; + break; + case UART_38400: + return true; + break; + case UART_57600: + return true; + break; + case UART_115200: + return true; + break; + case UART_230400: + return true; + break; + case UART_460800: + return true; + break; + case UART_921600: + return true; + break; + default: + return false; + break; + } +} + +static mxc_uart_parity_t convertParity(busio_uart_parity_t busio_parity) { + switch (busio_parity) { + case BUSIO_UART_PARITY_NONE: + return MXC_UART_PARITY_DISABLE; + case BUSIO_UART_PARITY_EVEN: + return MXC_UART_PARITY_EVEN_0; + case BUSIO_UART_PARITY_ODD: + return MXC_UART_PARITY_ODD_0; + default: + // not reachable due to validation in shared-bindings/busio/SPI.c + return MXC_UART_PARITY_DISABLE; + } +} + +void uart_isr(void) { + for (int i = 0; i < NUM_UARTS; i++) { + if (uarts_active & (1 << i)) { + MXC_UART_AsyncHandler(MXC_UART_GET_UART(i)); + } + } +} + +// Callback gets called when AsyncRequest is COMPLETE +// (e.g. txLen == txCnt) +static volatile void uartCallback(mxc_uart_req_t *req, int error) { + uart_status[MXC_UART_GET_IDX(req->uart)] = UART_FREE; + uart_err = error; + + MXC_SYS_Crit_Enter(); + ringbuf_put_n(context->ringbuf, req->rxData, req->rxLen); + MXC_SYS_Crit_Exit(); +} + +// Construct an underlying UART object. +void common_hal_busio_uart_construct(busio_uart_obj_t *self, + const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, + const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, + const mcu_pin_obj_t *rs485_dir, bool rs485_invert, + uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size, byte *receiver_buffer, + bool sigint_enabled) { + int err, temp; + + // Check for NULL Pointers && valid UART settings + assert(self); + + // Assign UART ID based on pins + temp = pinsToUart(tx, rx); + if (temp == -1) { + // Error will be indicated by pinsToUart(tx, rx) function + return; + } else { + self->uart_id = temp; + self->uart_regs = MXC_UART_GET_UART(temp); + } + assert((self->uart_id >= 0) && (self->uart_id < NUM_UARTS)); + + // Check for size of ringbuffer, desire powers of 2 + // At least use 1 byte if no size is given + assert((receiver_buffer_size & (receiver_buffer_size - 1)) == 0); + if (receiver_buffer_size == 0) { + receiver_buffer_size += 1; + } + + // Indicate RS485 not implemented + if ((rs485_dir != NULL) || (rs485_invert)) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("RS485")); + } + + if ((rx != NULL) && (tx != NULL)) { + err = MXC_UART_Init(self->uart_regs, baudrate, MXC_UART_IBRO_CLK); + if (err != E_NO_ERROR) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_UART); + } + + // attach & configure pins + self->tx_pin = tx; + self->rx_pin = rx; + common_hal_mcu_pin_claim(self->tx_pin); + common_hal_mcu_pin_claim(self->rx_pin); + } else { + mp_raise_NotImplementedError(MP_ERROR_TEXT("UART needs TX & RX")); + } + + if ((cts) && (rts)) { + MXC_UART_SetFlowCtrl(self->uart_regs, MXC_UART_FLOW_EN, 8); + self->cts_pin = cts; + self->rts_pin = rts; + common_hal_mcu_pin_claim(self->cts_pin); + common_hal_mcu_pin_claim(self->rts_pin); + } else if (cts || rts) { + mp_raise_ValueError(MP_ERROR_TEXT("Both RX and TX required for flow control")); + } + + // Set stop bits & data size + assert((stop == 1) || (stop == 2)); + mp_arg_validate_int(bits, 8, MP_QSTR_bits); + MXC_UART_SetDataSize(self->uart_regs, bits); + MXC_UART_SetStopBits(self->uart_regs, stop); + + // Set parity + MXC_UART_SetParity(self->uart_regs, convertParity(parity)); + + // attach UART parameters + self->stop_bits = stop; // must be 1 or 2 + self->bits = bits; + self->parity = parity; + self->baudrate = baudrate; + self->error = E_NO_ERROR; + + // Indicate to this module that the UART is active + uarts_active |= (1 << self->uart_id); + + // Set the timeout to a default value + if (((timeout < 0.0) || (timeout > 100.0))) { + self->timeout = 1.0; + } else { + self->timeout = timeout; + } + + // Initialize ringbuffer + if (receiver_buffer == NULL) { + self->ringbuf = m_malloc_without_collect(receiver_buffer_size); + if (!ringbuf_alloc(self->ringbuf, receiver_buffer_size)) { + m_malloc_fail(receiver_buffer_size); + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("Failed to allocate %q buffer"), + MP_QSTR_UART); + } + } else { + if (!(ringbuf_init(self->ringbuf, receiver_buffer, receiver_buffer_size))) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("Failed to allocate %q buffer"), + MP_QSTR_UART); + } + } + + context = self; + + // Setup UART interrupt + NVIC_ClearPendingIRQ(MXC_UART_GET_IRQ(self->uart_id)); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + NVIC_SetPriority(MXC_UART_GET_IRQ(self->uart_id), UART_PRIORITY); + NVIC_SetVector(MXC_UART_GET_IRQ(self->uart_id), (uint32_t)uart_isr); + + NVIC_EnableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + + return; +} + +void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { + assert(self); + + if (!common_hal_busio_uart_deinited(self)) { + // First disable the ISR to avoid pre-emption + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + + // Shutdown the UART Controller + MXC_UART_Shutdown(self->uart_regs); + self->error = E_UNINITIALIZED; + + assert(self->rx_pin && self->tx_pin); + reset_pin_number(self->rx_pin->port, self->rx_pin->mask); + reset_pin_number(self->tx_pin->port, self->tx_pin->mask); + + if (self->cts_pin && self->rts_pin) { + reset_pin_number(self->cts_pin->port, self->cts_pin->mask); + reset_pin_number(self->rts_pin->port, self->rts_pin->mask); + } + + self->tx_pin = NULL; + self->rx_pin = NULL; + self->cts_pin = NULL; + self->rts_pin = NULL; + + ringbuf_deinit(self->ringbuf); + + // Indicate to this module that the UART is not active + uarts_active &= ~(1 << self->uart_id); + } +} + +bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { + if (uarts_active & (1 << self->uart_id)) { + return false; + } else { + return true; + }; +} + +// Read characters. len is in characters. +size_t common_hal_busio_uart_read(busio_uart_obj_t *self, + uint8_t *data, size_t len, int *errcode) { + int err; + uint32_t start_time = 0; + static size_t bytes_remaining; + + // Setup globals & status tracking + uart_err = E_NO_ERROR; + uarts_active |= (1 << self->uart_id); + uart_status[self->uart_id] = UART_BUSY; + bytes_remaining = len; + + mxc_uart_req_t uart_rd_req; + uart_rd_req.rxCnt = 0; + uart_rd_req.txCnt = 0; + uart_rd_req.rxData = data; + uart_rd_req.txData = NULL; + uart_rd_req.rxLen = bytes_remaining; + uart_rd_req.txLen = 0; + uart_rd_req.uart = self->uart_regs; + uart_rd_req.callback = (void *)uartCallback; + + // Initiate the read transaction + start_time = supervisor_ticks_ms64(); + err = MXC_UART_TransactionAsync(&uart_rd_req); + if (err != E_NO_ERROR) { + *errcode = err; + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("UART read error")); + } + + // Wait for transaction completion or timeout + while ((uart_status[self->uart_id] != UART_FREE) && + (supervisor_ticks_ms64() - start_time < (self->timeout * 1000))) { + } + + // If the timeout gets hit, abort and error out + if (uart_status[self->uart_id] != UART_FREE) { + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_RuntimeError(MP_ERROR_TEXT("UART transaction timeout")); + } + // Check for errors from the callback + else if (uart_err != E_NO_ERROR) { + mp_raise_RuntimeError(MP_ERROR_TEXT("UART read error")); + MXC_UART_AbortAsync(self->uart_regs); + } + + // Copy the data from the ringbuf (or return error) + MXC_SYS_Crit_Enter(); + err = ringbuf_get_n(context->ringbuf, data, len); + MXC_SYS_Crit_Exit(); + + return err; +} + +// Write characters. len is in characters NOT bytes! +// This function blocks until the timeout finishes +size_t common_hal_busio_uart_write(busio_uart_obj_t *self, + const uint8_t *data, size_t len, int *errcode) { + int err; + static size_t bytes_remaining; + + // Setup globals & status tracking + uart_err = E_NO_ERROR; + uarts_active |= (1 << self->uart_id); + uart_status[self->uart_id] = UART_BUSY; + bytes_remaining = len; + + mxc_uart_req_t uart_wr_req = {}; + + // Setup transaction + uart_wr_req.rxCnt = 0; + uart_wr_req.txCnt = 0; + uart_wr_req.rxData = NULL; + uart_wr_req.txData = data; + uart_wr_req.txLen = bytes_remaining; + uart_wr_req.rxLen = 0; + uart_wr_req.uart = self->uart_regs; + uart_wr_req.callback = (void *)uartCallback; + + // Start the transaction + err = MXC_UART_TransactionAsync(&uart_wr_req); + if (err != E_NO_ERROR) { + *errcode = err; + MXC_UART_AbortAsync(self->uart_regs); + NVIC_DisableIRQ(MXC_UART_GET_IRQ(self->uart_id)); + mp_raise_ValueError(MP_ERROR_TEXT("All UART peripherals are in use")); + } + + // Wait for transaction completion + while (uart_status[self->uart_id] != UART_FREE) { + // Call the handler and abort if errors + uart_err = MXC_UART_AsyncHandler(self->uart_regs); + if (uart_err != E_NO_ERROR) { + MXC_UART_AbortAsync(self->uart_regs); + } + } + // Check for errors from the callback + if (uart_err != E_NO_ERROR) { + MXC_UART_AbortAsync(self->uart_regs); + } + + return len; +} + +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + return self->baudrate; +} + +// Validate baudrate +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + if (isValidBaudrate(baudrate)) { + self->baudrate = baudrate; + } else { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_baudrate); + } +} + +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return self->timeout; +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + if (timeout > 100.0) { + mp_raise_ValueError(MP_ERROR_TEXT("Timeout must be < 100 seconds")); + } + + timeout_ms = 1000 * (uint32_t)timeout; + self->timeout = (uint32_t)timeout; + + return; +} + +uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { + return ringbuf_num_filled(self->ringbuf); +} + +void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { + MXC_UART_ClearRXFIFO(self->uart_regs); + ringbuf_clear(self->ringbuf); +} + +bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { + return !(MXC_UART_GetStatus(self->uart_regs) & (MXC_F_UART_STATUS_TX_BUSY)); +} + +void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { + common_hal_never_reset_pin(self->tx_pin); + common_hal_never_reset_pin(self->rx_pin); + common_hal_never_reset_pin(self->cts_pin); + common_hal_never_reset_pin(self->rts_pin); + uart_never_reset_mask |= (1 << (self->uart_id)); +} + +#endif // CIRCUITPY_BUSIO_UART diff --git a/ports/analog/common-hal/busio/UART.h b/ports/analog/common-hal/busio/UART.h new file mode 100644 index 0000000000000..296c738772e68 --- /dev/null +++ b/ports/analog/common-hal/busio/UART.h @@ -0,0 +1,39 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H +#define MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" +#include "py/ringbuf.h" + +#include "max32_port.h" + +// Define a struct for what BUSIO.UART should contain +typedef struct { + mp_obj_base_t base; + int error; + float timeout; + + int uart_id; + int uart_map; + mxc_uart_regs_t *uart_regs; + ringbuf_t *ringbuf; + bool parity; + uint8_t bits; + uint8_t stop_bits; + uint32_t baudrate; + + const mcu_pin_obj_t *rx_pin; + const mcu_pin_obj_t *tx_pin; + const mcu_pin_obj_t *rts_pin; + const mcu_pin_obj_t *cts_pin; +} busio_uart_obj_t; + +void uart_reset(void); + +#endif // MICROPY_INCLUDED_MAX32_COMMON_HAL_BUSIO_UART_H diff --git a/ports/analog/common-hal/busio/__init__.c b/ports/analog/common-hal/busio/__init__.c new file mode 100644 index 0000000000000..ff05be051bb25 --- /dev/null +++ b/ports/analog/common-hal/busio/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT diff --git a/ports/analog/common-hal/digitalio/DigitalInOut.c b/ports/analog/common-hal/digitalio/DigitalInOut.c new file mode 100644 index 0000000000000..93e2242fbb6f6 --- /dev/null +++ b/ports/analog/common-hal/digitalio/DigitalInOut.c @@ -0,0 +1,298 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE 1 +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "max32_port.h" +#include "gpio_reva.h" +#include "mxc_errors.h" + +extern mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS]; + +void common_hal_digitalio_digitalinout_never_reset( + digitalio_digitalinout_obj_t *self) { + common_hal_never_reset_pin(self->pin); +} + +bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) { + return self->pin == NULL; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_construct( + digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { + + common_hal_mcu_pin_claim(pin); + self->pin = pin; + self->open_drain = false; + self->vssel = MXC_GPIO_VSSEL_VDDIOH; + + mxc_gpio_cfg_t new_gpio_cfg = { + .port = gpio_ports[self->pin->port], + .mask = (self->pin->mask), + .vssel = self->vssel, + .func = MXC_GPIO_FUNC_IN, + .drvstr = MXC_GPIO_DRVSTR_0, + .pad = MXC_GPIO_PAD_NONE, + }; + MXC_GPIO_Config(&new_gpio_cfg); + + return DIGITALINOUT_OK; +} + +void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) { + if (common_hal_digitalio_digitalinout_deinited(self)) { + return; + } + + reset_pin_number(self->pin->port, self->pin->mask); + self->pin = NULL; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_input( + digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) { + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + int err = E_NO_ERROR; + + if (self->pin->port == 4) { + // Set GPIO(s) to input mode + MXC_MCR->gpio4_ctrl &= ~GPIO4_OUTEN_MASK(mask); + MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); + } else { + err = MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_IN, mask); + } + if (err != E_NO_ERROR) { + return DIGITALINOUT_PIN_BUSY; + } + return common_hal_digitalio_digitalinout_set_pull(self, pull); +} + +digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output( + digitalio_digitalinout_obj_t *self, bool value, + digitalio_drive_mode_t drive_mode) { + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + self->open_drain = (drive_mode == DRIVE_MODE_OPEN_DRAIN); + + // Set GPIO(s) to output mode + if (self->pin->port == 4) { + MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(mask); + MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); + } else { + MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_OUT, mask); + } + + common_hal_digitalio_digitalinout_set_value(self, value); + + return DIGITALINOUT_OK; +} + +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( + digitalio_digitalinout_obj_t *self) { + + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + // Open drain must be considered output for CircuitPython API to work properly + if (self->open_drain) { + return DIRECTION_OUTPUT; + } + + if (self->pin->port < 4) { + // Check that I/O mode is enabled and we don't have in AND out on at the same time + MP_STATIC_ASSERT_NONCONSTEXPR(!((port->en0 & mask) && (port->inen & mask) && (port->outen & mask))); + + if ((port->en0 & mask) && (port->outen & mask)) { + return DIRECTION_OUTPUT; + } else if ((port->en0 & mask) && (port->inen & mask)) { + return DIRECTION_INPUT; + // do not try to drive a pin which has an odd configuration here + } else { + return DIRECTION_INPUT; + } + } else { + if (MXC_MCR->gpio4_ctrl & GPIO4_OUTEN_MASK(mask)) { + return DIRECTION_OUTPUT; + } else { + return DIRECTION_INPUT; + } + } +} + +void common_hal_digitalio_digitalinout_set_value( + digitalio_digitalinout_obj_t *self, bool value) { + digitalio_direction_t dir = + common_hal_digitalio_digitalinout_get_direction(self); + + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + MXC_GPIO_SetVSSEL(port, self->vssel, mask); + + if (self->open_drain) { + // Open-drain can be done by setting to input mode, no pullup/pulldown + // when the value is high (no sink current into GPIO) + if (value) { + // set to input, no pull + common_hal_digitalio_digitalinout_switch_to_input(self, PULL_NONE); + } else { + // can't use common_hal_switch_to_output b/c it calls this function + // set the GPIO to output, low + if (self->pin->port == 4) { + MXC_MCR->gpio4_ctrl |= GPIO4_OUTEN_MASK(mask); + MXC_MCR->outen &= ~GPIO4_AFEN_MASK(mask); + } else { + MXC_GPIO_RevA_SetAF((mxc_gpio_reva_regs_t *)port, MXC_GPIO_FUNC_OUT, mask); + } + MXC_GPIO_OutClr(port, mask); + } + } else if (dir == DIRECTION_OUTPUT) { + if (value) { + MXC_GPIO_OutSet(port, mask); + } else { + MXC_GPIO_OutClr(port, mask); + } + } +} + +bool common_hal_digitalio_digitalinout_get_value(digitalio_digitalinout_obj_t *self) { + digitalio_direction_t dir = + common_hal_digitalio_digitalinout_get_direction(self); + + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + if (self->open_drain) { + return MXC_GPIO_InGet(port, mask) && mask; + } + + if (dir == DIRECTION_INPUT) { + if (self->pin->port == 4) { + return (bool)(MXC_MCR->gpio4_ctrl & GPIO4_DATAIN_MASK(mask)); + } + return MXC_GPIO_InGet(port, mask) && mask; + } else { + return MXC_GPIO_OutGet(port, mask) && mask; + } +} + +digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode( + digitalio_digitalinout_obj_t *self, digitalio_drive_mode_t drive_mode) { + + // Check what the current value is + bool value = common_hal_digitalio_digitalinout_get_value(self); + self->open_drain = (drive_mode == DRIVE_MODE_OPEN_DRAIN); + + // Re-set the value to account for different setting methods for drive types + // Switch to output will both set the output config + // AND set the value for the new drive type + common_hal_digitalio_digitalinout_switch_to_output(self, value, drive_mode); + + return DIGITALINOUT_OK; +} + +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( + digitalio_digitalinout_obj_t *self) { + if (self->open_drain) { + return DRIVE_MODE_OPEN_DRAIN; + } else { + return DRIVE_MODE_PUSH_PULL; + } +} + +digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( + digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) { + + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + // GPIO4 handling + if (self->pin->port == 4) { + switch (pull) { + case PULL_NONE: + // disable pullup/pulldown + MXC_MCR->gpio4_ctrl |= GPIO4_PULLDIS_MASK(mask); + break; + case PULL_UP: + // enable pullup/pulldown (clear the mask) + // then set output value to 1 + MXC_MCR->gpio4_ctrl &= ~(GPIO4_PULLDIS_MASK(mask)); + MXC_MCR->gpio4_ctrl |= GPIO4_DATAOUT_MASK(mask); + break; + case PULL_DOWN: + // enable pullup/pulldown (clear the mask) + // then clear output value to 0 + MXC_MCR->gpio4_ctrl &= ~(GPIO4_PULLDIS_MASK(mask)); + MXC_MCR->gpio4_ctrl &= ~(GPIO4_DATAOUT_MASK(mask)); + break; + default: + break; + } + return DIGITALINOUT_OK; + } else { + // padctrl registers only work in input mode + if ((mask & port->en0) & (mask & ~(port->outen))) { + // PULL_NONE, PULL_UP, or PULL_DOWN + switch (pull) { + case PULL_NONE: + port->padctrl0 &= ~(mask); + port->padctrl1 &= ~(mask); + break; + case PULL_UP: + port->padctrl0 |= mask; + port->padctrl1 &= ~(mask); + port->ps &= ~(mask); + break; + case PULL_DOWN: + port->padctrl0 &= ~mask; + port->padctrl1 |= mask; + port->ps &= ~mask; + break; + default: + break; + } + return DIGITALINOUT_OK; + } else { + return DIGITALINOUT_PIN_BUSY; + } + } +} + +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( + digitalio_digitalinout_obj_t *self) { + + mxc_gpio_regs_t *port = gpio_ports[self->pin->port]; + uint32_t mask = self->pin->mask; + + bool pin_padctrl0 = (port->padctrl0) & (mask); + bool pin_padctrl1 = (port->padctrl1) & (mask); + + if (self->pin->port == 4) { + if (MXC_MCR->gpio4_ctrl & GPIO4_PULLDIS_MASK(mask)) { + return PULL_NONE; + } else { + if (MXC_MCR->gpio4_ctrl & GPIO4_DATAOUT_MASK(mask)) { + return PULL_UP; + } else { + return PULL_DOWN; + } + } + } else { + if ((pin_padctrl0) && !(pin_padctrl1)) { + return PULL_UP; + } else if (!(pin_padctrl0) && pin_padctrl1) { + return PULL_DOWN; + } else if (!(pin_padctrl0) && !(pin_padctrl1)) { + return PULL_NONE; + } else { + return PULL_NONE; + } + } +} diff --git a/ports/analog/common-hal/digitalio/DigitalInOut.h b/ports/analog/common-hal/digitalio/DigitalInOut.h new file mode 100644 index 0000000000000..d10345fa3fa82 --- /dev/null +++ b/ports/analog/common-hal/digitalio/DigitalInOut.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + bool open_drain; + mxc_gpio_vssel_t vssel; +} digitalio_digitalinout_obj_t; diff --git a/ports/analog/common-hal/digitalio/__init__.c b/ports/analog/common-hal/digitalio/__init__.c new file mode 100644 index 0000000000000..fa222ed01f03d --- /dev/null +++ b/ports/analog/common-hal/digitalio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No digitalio module functions. diff --git a/ports/analog/common-hal/microcontroller/Pin.c b/ports/analog/common-hal/microcontroller/Pin.c new file mode 100644 index 0000000000000..83e2f3b9c3a76 --- /dev/null +++ b/ports/analog/common-hal/microcontroller/Pin.c @@ -0,0 +1,113 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/microcontroller/Pin.h" +#include "mpconfigboard.h" +#include "pins.h" + +#include "max32_port.h" + +#include "common-hal/microcontroller/Pin.h" + +static uint32_t claimed_pins[NUM_GPIO_PORTS]; + +// defined in board.c +extern mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS]; + +static uint32_t never_reset_pins[NUM_GPIO_PORTS]; + +#define INVALID_PIN 0xFF // id for invalid pin + +void reset_all_pins(void) { + // reset all pins except for never_reset_pins + for (int i = 0; i < NUM_GPIO_PORTS; i++) { + for (int j = 0; j < 32; j++) { + if (!(never_reset_pins[i] & (1 << j))) { + reset_pin_number(i, j); + } + } + // set claimed pins to never_reset pins + claimed_pins[i] = never_reset_pins[i]; + } +} + +void reset_pin_number(uint8_t pin_port, uint8_t pin_pad) { + if ((pin_port == INVALID_PIN) || (pin_port > NUM_GPIO_PORTS)) { + return; + } + + uint32_t mask = 1 << (pin_pad); + + /** START: RESET LOGIC for GPIOs */ + // Switch to I/O mode first + gpio_ports[pin_port]->en0_set = mask; + + // set GPIO configuration enable bits to I/O + gpio_ports[pin_port]->en0_clr = mask; + gpio_ports[pin_port]->en1_clr = mask; + gpio_ports[pin_port]->en2_clr = mask; + + // enable input mode GPIOn_INEN.pin = 1 + gpio_ports[pin_port]->inen |= mask; + + // High Impedance mode enable (GPIOn_PADCTRL1 = 0, _PADCTRL0 = 0), pu/pd disable + gpio_ports[pin_port]->padctrl0 &= ~mask; + gpio_ports[pin_port]->padctrl1 &= ~mask; + + // Output mode disable GPIOn_OUTEN = 0 + gpio_ports[pin_port]->outen |= mask; + + // Interrupt disable GPIOn_INTEN = 0 + gpio_ports[pin_port]->inten &= ~mask; + /** END: RESET LOGIC for GPIOs */ +} + +uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) { + if (pin == NULL) { + return INVALID_PIN; + } + + // most max32 gpio ports have 32 pins + // todo (low prior.): encode # of pins for each port, since some GPIO ports differ + return pin->port * 32 + pin->mask; +} + +bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { + if (pin == NULL) { + return true; + } + return !(claimed_pins[pin->port] & (pin->mask)); +} + +void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { + if ((pin != NULL) && (pin->mask != INVALID_PIN)) { + never_reset_pins[pin->port] |= (1 << pin->mask); + + // any never reset pin must also be claimed + claimed_pins[pin->port] |= (1 << pin->mask); + } +} + +void common_hal_reset_pin(const mcu_pin_obj_t *pin) { + if (pin == NULL) { + return; + } + + reset_pin_number(pin->port, pin->mask); +} + +void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { + if (pin == NULL) { + return; + } + claimed_pins[pin->port] |= (1 << pin->mask); +} + +void common_hal_mcu_pin_reset_number(uint8_t pin_no) { + reset_pin_number(pin_no / 32, pin_no & 32); +} diff --git a/ports/analog/common-hal/microcontroller/Pin.h b/ports/analog/common-hal/microcontroller/Pin.h new file mode 100644 index 0000000000000..169586e7e903d --- /dev/null +++ b/ports/analog/common-hal/microcontroller/Pin.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/mphal.h" + +#include "peripherals/pins.h" + +void reset_all_pins(void); +// reset_pin_number takes the pin number instead of the pointer so that objects don't +// need to store a full pointer. +void reset_pin_number(uint8_t pin_port, uint8_t pin_pad); diff --git a/ports/analog/common-hal/microcontroller/Processor.c b/ports/analog/common-hal/microcontroller/Processor.c new file mode 100644 index 0000000000000..87d8047ff2cbb --- /dev/null +++ b/ports/analog/common-hal/microcontroller/Processor.c @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include +#include "py/runtime.h" + +#if CIRCUITPY_ALARM +#include "common-hal/alarm/__init__.h" +#endif + +#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/ResetReason.h" + +#include "max32_port.h" + +// No means of getting core temperature for currently supported devices +float common_hal_mcu_processor_get_temperature(void) { + return NAN; +} + +// MAX32690 can measure VCORE +// TODO: (low prior.) Implement ADC API under "peripherals" and use API to measure VCORE +float common_hal_mcu_processor_get_voltage(void) { + return NAN; +} + +uint32_t common_hal_mcu_processor_get_frequency(void) { + return SystemCoreClock; +} + +// NOTE: COMMON_HAL_MCU_PROCESSOR_UID_LENGTH is defined in mpconfigboard.h +// Use this per device to make sure raw_id is an appropriate minimum number of bytes +void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { + MXC_SYS_GetUSN(raw_id, NULL); // NULL checksum will not be verified by AES + return; +} + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + #if CIRCUITPY_ALARM + // TODO: (low prior.) add reset reason in alarm / deepsleep cases (should require alarm peripheral API in "peripherals") + #endif + return RESET_REASON_UNKNOWN; +} diff --git a/ports/analog/common-hal/microcontroller/Processor.h b/ports/analog/common-hal/microcontroller/Processor.h new file mode 100644 index 0000000000000..aab7727550a9d --- /dev/null +++ b/ports/analog/common-hal/microcontroller/Processor.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 12 + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + // Stores no state currently. +} mcu_processor_obj_t; diff --git a/ports/analog/common-hal/microcontroller/__init__.c b/ports/analog/common-hal/microcontroller/__init__.c new file mode 100644 index 0000000000000..207ddbe52f375 --- /dev/null +++ b/ports/analog/common-hal/microcontroller/__init__.c @@ -0,0 +1,408 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SP3_X-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// SP3_X-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries +// SP3_X-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SP3_X-License-Identifier: MIT + +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/microcontroller/Processor.h" + +// #include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Processor.h" +#include "supervisor/port.h" +#include "supervisor/filesystem.h" +#include "supervisor/shared/safe_mode.h" + + +#include "max32690.h" +#include "mxc_delay.h" + +/** NOTE: It is not advised to directly include the below! + * These are includes taken care of by the core cmsis file. + * e.g. "max32690.h". Since CMSIS is compiled as lib, these are + * included there as for example. +*/ +// #include // For enable/disable interrupts +// #include // For NVIC_SystemReset +// #include // For __DMB Data Memory Barrier (flush DBUS activity) + +void common_hal_mcu_delay_us(uint32_t delay) { + + MXC_Delay(MXC_DELAY_USEC(delay)); +} + +volatile uint32_t nesting_count = 0; + +void common_hal_mcu_disable_interrupts(void) { + __disable_irq(); + __DMB(); + nesting_count++; +} + +void common_hal_mcu_enable_interrupts(void) { + if (nesting_count == 0) { + // This is very very bad because it means there was mismatched disable/enables. + reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR); + } + nesting_count--; + if (nesting_count > 0) { + return; + } + __DMB(); // flush internal DBUS before proceeding + __enable_irq(); +} + +static bool next_reset_to_bootloader = false; + +void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { + if (runmode == RUNMODE_SAFE_MODE) { + safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC); + } + if (runmode == RUNMODE_BOOTLOADER) { + next_reset_to_bootloader = true; + } +} + +void common_hal_mcu_reset(void) { + if (next_reset_to_bootloader) { + reset_to_bootloader(); + } else { + NVIC_SystemReset(); + } +} + +// The singleton microcontroller.Processor object, bound to microcontroller.cpu +// It currently only has properties, and no state. +const mcu_processor_obj_t common_hal_mcu_processor_obj = { + .base = { + .type = &mcu_processor_type, + }, +}; + +// This maps MCU pin names to pin objects. +static const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { + #if defined(PIN_P0_01) && !defined(IGNORE_PIN_P0_01) + { MP_ROM_QSTR(MP_QSTR_P0_01), MP_ROM_PTR(&pin_P0_01) }, + #endif + #if defined(PIN_P0_02) && !defined(IGNORE_PIN_P0_02) + { MP_ROM_QSTR(MP_QSTR_P0_02), MP_ROM_PTR(&pin_P0_02) }, + #endif + #if defined(PIN_P0_03) && !defined(IGNORE_PIN_P0_03) + { MP_ROM_QSTR(MP_QSTR_P0_03), MP_ROM_PTR(&pin_P0_03) }, + #endif + #if defined(PIN_P0_04) && !defined(IGNORE_PIN_P0_04) + { MP_ROM_QSTR(MP_QSTR_P0_04), MP_ROM_PTR(&pin_P0_04) }, + #endif + #if defined(PIN_P0_05) && !defined(IGNORE_PIN_P0_05) + { MP_ROM_QSTR(MP_QSTR_P0_05), MP_ROM_PTR(&pin_P0_05) }, + #endif + #if defined(PIN_P0_06) && !defined(IGNORE_PIN_P0_06) + { MP_ROM_QSTR(MP_QSTR_P0_06), MP_ROM_PTR(&pin_P0_06) }, + #endif + #if defined(PIN_P0_07) && !defined(IGNORE_PIN_P0_07) + { MP_ROM_QSTR(MP_QSTR_P0_07), MP_ROM_PTR(&pin_P0_07) }, + #endif + #if defined(PIN_P0_08) && !defined(IGNORE_PIN_P0_08) + { MP_ROM_QSTR(MP_QSTR_P0_08), MP_ROM_PTR(&pin_P0_08) }, + #endif + #if defined(PIN_P0_09) && !defined(IGNORE_PIN_P0_09) + { MP_ROM_QSTR(MP_QSTR_P0_09), MP_ROM_PTR(&pin_P0_09) }, + #endif + #if defined(PIN_P0_10) && !defined(IGNORE_PIN_P0_10) + { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) }, + #endif + #if defined(PIN_P0_11) && !defined(IGNORE_PIN_P0_11) + { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) }, + #endif + #if defined(PIN_P0_12) && !defined(IGNORE_PIN_P0_12) + { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) }, + #endif + #if defined(PIN_P0_13) && !defined(IGNORE_PIN_P0_13) + { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) }, + #endif + #if defined(PIN_P0_14) && !defined(IGNORE_PIN_P0_14) + { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) }, + #endif + #if defined(PIN_P0_15) && !defined(IGNORE_PIN_P0_15) + { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) }, + #endif + #if defined(PIN_P0_16) && !defined(IGNORE_PIN_P0_16) + { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) }, + #endif + #if defined(PIN_P0_17) && !defined(IGNORE_PIN_P0_17) + { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) }, + #endif + #if defined(PIN_P0_18) && !defined(IGNORE_PIN_P0_18) + { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) }, + #endif + #if defined(PIN_P0_19) && !defined(IGNORE_PIN_P0_19) + { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) }, + #endif + #if defined(PIN_P0_20) && !defined(IGNORE_PIN_P0_20) + { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) }, + #endif + #if defined(PIN_P0_21) && !defined(IGNORE_PIN_P0_21) + { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) }, + #endif + #if defined(PIN_P0_22) && !defined(IGNORE_PIN_P0_22) + { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) }, + #endif + #if defined(PIN_P0_23) && !defined(IGNORE_PIN_P0_23) + { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) }, + #endif + #if defined(PIN_P0_24) && !defined(IGNORE_PIN_P0_24) + { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) }, + #endif + #if defined(PIN_P0_25) && !defined(IGNORE_PIN_P0_25) + { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) }, + #endif + #if defined(PIN_P0_27) && !defined(IGNORE_PIN_P0_27) + { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) }, + #endif + #if defined(PIN_P0_28) && !defined(IGNORE_PIN_P0_28) + { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) }, + #endif + #if defined(PIN_P0_30) && !defined(IGNORE_PIN_P0_30) + { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) }, + #endif + #if defined(PIN_P0_31) && !defined(IGNORE_PIN_P0_31) + { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) }, + #endif + + #if defined(PIN_P1_01) && !defined(IGNORE_PIN_P1_01) + { MP_ROM_QSTR(MP_QSTR_P1_01), MP_ROM_PTR(&pin_P1_01) }, + #endif + #if defined(PIN_P1_02) && !defined(IGNORE_PIN_P1_02) + { MP_ROM_QSTR(MP_QSTR_P1_02), MP_ROM_PTR(&pin_P1_02) }, + #endif + #if defined(PIN_P1_03) && !defined(IGNORE_PIN_P1_03) + { MP_ROM_QSTR(MP_QSTR_P1_03), MP_ROM_PTR(&pin_P1_03) }, + #endif + #if defined(PIN_P1_04) && !defined(IGNORE_PIN_P1_04) + { MP_ROM_QSTR(MP_QSTR_P1_04), MP_ROM_PTR(&pin_P1_04) }, + #endif + #if defined(PIN_P1_05) && !defined(IGNORE_PIN_P1_05) + { MP_ROM_QSTR(MP_QSTR_P1_05), MP_ROM_PTR(&pin_P1_05) }, + #endif + #if defined(PIN_P1_06) && !defined(IGNORE_PIN_P1_06) + { MP_ROM_QSTR(MP_QSTR_P1_06), MP_ROM_PTR(&pin_P1_06) }, + #endif + #if defined(PIN_P1_07) && !defined(IGNORE_PIN_P1_07) + { MP_ROM_QSTR(MP_QSTR_P1_07), MP_ROM_PTR(&pin_P1_07) }, + #endif + #if defined(PIN_P1_08) && !defined(IGNORE_PIN_P1_08) + { MP_ROM_QSTR(MP_QSTR_P1_08), MP_ROM_PTR(&pin_P1_08) }, + #endif + #if defined(PIN_P1_09) && !defined(IGNORE_PIN_P1_09) + { MP_ROM_QSTR(MP_QSTR_P1_09), MP_ROM_PTR(&pin_P1_09) }, + #endif + #if defined(PIN_P1_10) && !defined(IGNORE_PIN_P1_10) + { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) }, + #endif + #if defined(PIN_P1_11) && !defined(IGNORE_PIN_P1_11) + { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) }, + #endif + #if defined(PIN_P1_12) && !defined(IGNORE_PIN_P1_12) + { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) }, + #endif + #if defined(PIN_P1_13) && !defined(IGNORE_PIN_P1_13) + { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) }, + #endif + #if defined(PIN_P1_14) && !defined(IGNORE_PIN_P1_14) + { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) }, + #endif + #if defined(PIN_P1_15) && !defined(IGNORE_PIN_P1_15) + { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) }, + #endif + #if defined(PIN_P1_16) && !defined(IGNORE_PIN_P1_16) + { MP_ROM_QSTR(MP_QSTR_P1_16), MP_ROM_PTR(&pin_P1_16) }, + #endif + #if defined(PIN_P1_17) && !defined(IGNORE_PIN_P1_17) + { MP_ROM_QSTR(MP_QSTR_P1_17), MP_ROM_PTR(&pin_P1_17) }, + #endif + #if defined(PIN_P1_18) && !defined(IGNORE_PIN_P1_18) + { MP_ROM_QSTR(MP_QSTR_P1_18), MP_ROM_PTR(&pin_P1_18) }, + #endif + #if defined(PIN_P1_19) && !defined(IGNORE_PIN_P1_19) + { MP_ROM_QSTR(MP_QSTR_P1_19), MP_ROM_PTR(&pin_P1_19) }, + #endif + #if defined(PIN_P1_20) && !defined(IGNORE_PIN_P1_20) + { MP_ROM_QSTR(MP_QSTR_P1_20), MP_ROM_PTR(&pin_P1_20) }, + #endif + #if defined(PIN_P1_21) && !defined(IGNORE_PIN_P1_21) + { MP_ROM_QSTR(MP_QSTR_P1_21), MP_ROM_PTR(&pin_P1_21) }, + #endif + #if defined(PIN_P1_22) && !defined(IGNORE_PIN_P1_22) + { MP_ROM_QSTR(MP_QSTR_P1_22), MP_ROM_PTR(&pin_P1_22) }, + #endif + #if defined(PIN_P1_23) && !defined(IGNORE_PIN_P1_23) + { MP_ROM_QSTR(MP_QSTR_P1_23), MP_ROM_PTR(&pin_P1_23) }, + #endif + #if defined(PIN_P1_24) && !defined(IGNORE_PIN_P1_24) + { MP_ROM_QSTR(MP_QSTR_P1_24), MP_ROM_PTR(&pin_P1_24) }, + #endif + #if defined(PIN_P1_25) && !defined(IGNORE_PIN_P1_25) + { MP_ROM_QSTR(MP_QSTR_P1_25), MP_ROM_PTR(&pin_P1_25) }, + #endif + #if defined(PIN_P1_26) && !defined(IGNORE_PIN_P1_26) + { MP_ROM_QSTR(MP_QSTR_P1_26), MP_ROM_PTR(&pin_P1_26) }, + #endif + #if defined(PIN_P1_27) && !defined(IGNORE_PIN_P1_27) + { MP_ROM_QSTR(MP_QSTR_P1_27), MP_ROM_PTR(&pin_P1_27) }, + #endif + #if defined(PIN_P1_28) && !defined(IGNORE_PIN_P1_28) + { MP_ROM_QSTR(MP_QSTR_P1_28), MP_ROM_PTR(&pin_P1_28) }, + #endif + #if defined(PIN_P1_29) && !defined(IGNORE_PIN_P1_29) + { MP_ROM_QSTR(MP_QSTR_P1_29), MP_ROM_PTR(&pin_P1_29) }, + #endif + #if defined(PIN_P1_30) && !defined(IGNORE_PIN_P1_30) + { MP_ROM_QSTR(MP_QSTR_P1_30), MP_ROM_PTR(&pin_P1_30) }, + #endif + #if defined(PIN_P1_31) && !defined(IGNORE_PIN_P1_31) + { MP_ROM_QSTR(MP_QSTR_P1_31), MP_ROM_PTR(&pin_P1_31) }, + #endif + + #if defined(PIN_P2_01) && !defined(IGNORE_PIN_P2_01) + { MP_ROM_QSTR(MP_QSTR_P2_01), MP_ROM_PTR(&pin_P2_01) }, + #endif + #if defined(PIN_P2_02) && !defined(IGNORE_PIN_P2_02) + { MP_ROM_QSTR(MP_QSTR_P2_02), MP_ROM_PTR(&pin_P2_02) }, + #endif + #if defined(PIN_P2_03) && !defined(IGNORE_PIN_P2_03) + { MP_ROM_QSTR(MP_QSTR_P2_03), MP_ROM_PTR(&pin_P2_03) }, + #endif + #if defined(PIN_P2_04) && !defined(IGNORE_PIN_P2_04) + { MP_ROM_QSTR(MP_QSTR_P2_04), MP_ROM_PTR(&pin_P2_04) }, + #endif + #if defined(PIN_P2_05) && !defined(IGNORE_PIN_P2_05) + { MP_ROM_QSTR(MP_QSTR_P2_05), MP_ROM_PTR(&pin_P2_05) }, + #endif + #if defined(PIN_P2_06) && !defined(IGNORE_PIN_P2_06) + { MP_ROM_QSTR(MP_QSTR_P2_06), MP_ROM_PTR(&pin_P2_06) }, + #endif + #if defined(PIN_P2_07) && !defined(IGNORE_PIN_P2_07) + { MP_ROM_QSTR(MP_QSTR_P2_07), MP_ROM_PTR(&pin_P2_07) }, + #endif + #if defined(PIN_P2_10) && !defined(IGNORE_PIN_P2_10) + { MP_ROM_QSTR(MP_QSTR_P2_10), MP_ROM_PTR(&pin_P2_10) }, + #endif + #if defined(PIN_P2_11) && !defined(IGNORE_PIN_P2_11) + { MP_ROM_QSTR(MP_QSTR_P2_11), MP_ROM_PTR(&pin_P2_11) }, + #endif + #if defined(PIN_P2_12) && !defined(IGNORE_PIN_P2_12) + { MP_ROM_QSTR(MP_QSTR_P2_12), MP_ROM_PTR(&pin_P2_12) }, + #endif + #if defined(PIN_P2_13) && !defined(IGNORE_PIN_P2_13) + { MP_ROM_QSTR(MP_QSTR_P2_13), MP_ROM_PTR(&pin_P2_13) }, + #endif + #if defined(PIN_P2_14) && !defined(IGNORE_PIN_P2_14) + { MP_ROM_QSTR(MP_QSTR_P2_14), MP_ROM_PTR(&pin_P2_14) }, + #endif + #if defined(PIN_P2_15) && !defined(IGNORE_PIN_P2_15) + { MP_ROM_QSTR(MP_QSTR_P2_15), MP_ROM_PTR(&pin_P2_15) }, + #endif + #if defined(PIN_P2_16) && !defined(IGNORE_PIN_P2_16) + { MP_ROM_QSTR(MP_QSTR_P2_16), MP_ROM_PTR(&pin_P2_16) }, + #endif + #if defined(PIN_P2_17) && !defined(IGNORE_PIN_P2_17) + { MP_ROM_QSTR(MP_QSTR_P2_17), MP_ROM_PTR(&pin_P2_17) }, + #endif + #if defined(PIN_P2_18) && !defined(IGNORE_PIN_P2_18) + { MP_ROM_QSTR(MP_QSTR_P2_18), MP_ROM_PTR(&pin_P2_18) }, + #endif + #if defined(PIN_P2_19) && !defined(IGNORE_PIN_P2_19) + { MP_ROM_QSTR(MP_QSTR_P2_19), MP_ROM_PTR(&pin_P2_19) }, + #endif + #if defined(PIN_P2_20) && !defined(IGNORE_PIN_P2_20) + { MP_ROM_QSTR(MP_QSTR_P2_20), MP_ROM_PTR(&pin_P2_20) }, + #endif + #if defined(PIN_P2_21) && !defined(IGNORE_PIN_P2_21) + { MP_ROM_QSTR(MP_QSTR_P2_21), MP_ROM_PTR(&pin_P2_21) }, + #endif + #if defined(PIN_P2_22) && !defined(IGNORE_PIN_P2_22) + { MP_ROM_QSTR(MP_QSTR_P2_22), MP_ROM_PTR(&pin_P2_22) }, + #endif + #if defined(PIN_P2_23) && !defined(IGNORE_PIN_P2_23) + { MP_ROM_QSTR(MP_QSTR_P2_23), MP_ROM_PTR(&pin_P2_23) }, + #endif + #if defined(PIN_P2_24) && !defined(IGNORE_PIN_P2_24) + { MP_ROM_QSTR(MP_QSTR_P2_24), MP_ROM_PTR(&pin_P2_24) }, + #endif + #if defined(PIN_P2_25) && !defined(IGNORE_PIN_P2_25) + { MP_ROM_QSTR(MP_QSTR_P2_25), MP_ROM_PTR(&pin_P2_25) }, + #endif + #if defined(PIN_P2_26) && !defined(IGNORE_PIN_P2_26) + { MP_ROM_QSTR(MP_QSTR_P2_26), MP_ROM_PTR(&pin_P2_26) }, + #endif + #if defined(PIN_P2_27) && !defined(IGNORE_PIN_P2_27) + { MP_ROM_QSTR(MP_QSTR_P2_27), MP_ROM_PTR(&pin_P2_27) }, + #endif + #if defined(PIN_P2_28) && !defined(IGNORE_PIN_P2_28) + { MP_ROM_QSTR(MP_QSTR_P2_28), MP_ROM_PTR(&pin_P2_28) }, + #endif + #if defined(PIN_P2_30) && !defined(IGNORE_PIN_P2_30) + { MP_ROM_QSTR(MP_QSTR_P2_30), MP_ROM_PTR(&pin_P2_30) }, + #endif + #if defined(PIN_P2_31) && !defined(IGNORE_PIN_P2_31) + { MP_ROM_QSTR(MP_QSTR_P2_31), MP_ROM_PTR(&pin_P2_31) }, + #endif + + #if defined(PIN_P3_01) && !defined(IGNORE_PIN_P3_01) + { MP_ROM_QSTR(MP_QSTR_P3_01), MP_ROM_PTR(&pin_P3_01) }, + #endif + #if defined(PIN_P3_02) && !defined(IGNORE_PIN_P3_02) + { MP_ROM_QSTR(MP_QSTR_P3_02), MP_ROM_PTR(&pin_P3_02) }, + #endif + #if defined(PIN_P3_03) && !defined(IGNORE_PIN_P3_03) + { MP_ROM_QSTR(MP_QSTR_P3_03), MP_ROM_PTR(&pin_P3_03) }, + #endif + #if defined(PIN_P3_04) && !defined(IGNORE_PIN_P3_04) + { MP_ROM_QSTR(MP_QSTR_P3_04), MP_ROM_PTR(&pin_P3_04) }, + #endif + #if defined(PIN_P3_05) && !defined(IGNORE_PIN_P3_05) + { MP_ROM_QSTR(MP_QSTR_P3_05), MP_ROM_PTR(&pin_P3_05) }, + #endif + #if defined(PIN_P3_06) && !defined(IGNORE_PIN_P3_06) + { MP_ROM_QSTR(MP_QSTR_P3_06), MP_ROM_PTR(&pin_P3_06) }, + #endif + #if defined(PIN_P3_07) && !defined(IGNORE_PIN_P3_07) + { MP_ROM_QSTR(MP_QSTR_P3_07), MP_ROM_PTR(&pin_P3_07) }, + #endif + #if defined(PIN_P3_08) && !defined(IGNORE_PIN_P3_08) + { MP_ROM_QSTR(MP_QSTR_P3_08), MP_ROM_PTR(&pin_P3_08) }, + #endif + #if defined(PIN_P3_09) && !defined(IGNORE_PIN_P3_09) + { MP_ROM_QSTR(MP_QSTR_P3_09), MP_ROM_PTR(&pin_P3_09) }, + #endif + + #if defined(PIN_P4_01) && !defined(IGNORE_PIN_P4_01) + { MP_ROM_QSTR(MP_QSTR_P4_01), MP_ROM_PTR(&pin_P4_02) }, + #endif + #if defined(PIN_P4_02) && !defined(IGNORE_PIN_P4_02) + { MP_ROM_QSTR(MP_QSTR_P4_01), MP_ROM_PTR(&pin_P4_02) }, + #endif + +}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); + + +/** NOTE: Not implemented yet */ +// #if CIRCUITPY_INTERNAL_NVM_SIZE > 0 +// // The singleton nvm.ByteArray object. +// const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { +// .base = { +// .type = &nvm_bytearray_type, +// }, +// .len = NVM_BYTEARRAY_BUFFER_SIZE, +// .start_address = (uint8_t *)(CIRCUITPY_INTERNAL_NVM_START_ADDR) +// }; +// #endif diff --git a/ports/analog/common-hal/os/__init__.c b/ports/analog/common-hal/os/__init__.c new file mode 100644 index 0000000000000..508b40798e22b --- /dev/null +++ b/ports/analog/common-hal/os/__init__.c @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "genhdr/mpversion.h" +#include "py/mpconfig.h" +#include "py/objstr.h" +#include "py/objtuple.h" + +#include "py/mperrno.h" +#include "py/runtime.h" + +// #include "peripherals/periph.h" + +// true random number generator, TRNG +#include "trng.h" + +bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) { + #if (HAS_TRNG) + // get a random number of "length" number of bytes + MXC_TRNG_Random(buffer, length); + return true; + #else + #endif + return false; +} diff --git a/ports/analog/common-hal/rtc/RTC.c b/ports/analog/common-hal/rtc/RTC.c new file mode 100644 index 0000000000000..c9d2258c1ece1 --- /dev/null +++ b/ports/analog/common-hal/rtc/RTC.c @@ -0,0 +1,42 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Nick Moore for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" +#include "shared/timeutils/timeutils.h" +#include "supervisor/port.h" + +// This is the time in seconds since 2000 that the RTC was started. +// TODO: Change the offset to ticks so that it can be a subsecond adjustment. +static uint32_t rtc_offset = 0; + +void common_hal_rtc_get_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024; + timeutils_seconds_since_2000_to_struct_time(rtc_offset + ticks_s, tm); +} + +void common_hal_rtc_set_time(timeutils_struct_time_t *tm) { + uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024; + uint32_t epoch_s = timeutils_seconds_since_2000( + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec + ); + rtc_offset = epoch_s - ticks_s; +} + +// the calibration function will be implemented in near future +// the RTC oscillator on my MAX32690-APARD is only off by 0.001 second +// the inaccuracy is still tolerable +int common_hal_rtc_get_calibration(void) { + return 0; +} + +void common_hal_rtc_set_calibration(int calibration) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_calibration); +} diff --git a/ports/analog/common-hal/rtc/RTC.h b/ports/analog/common-hal/rtc/RTC.h new file mode 100644 index 0000000000000..590bc93ab5231 --- /dev/null +++ b/ports/analog/common-hal/rtc/RTC.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Noralf Trønnes +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern void rtc_reset(void); diff --git a/ports/analog/common-hal/rtc/__init__.c b/ports/analog/common-hal/rtc/__init__.c new file mode 100644 index 0000000000000..ddf788bb0b5ad --- /dev/null +++ b/ports/analog/common-hal/rtc/__init__.c @@ -0,0 +1,6 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT diff --git a/ports/analog/linking/max32690_cktpy.ld b/ports/analog/linking/max32690_cktpy.ld new file mode 100644 index 0000000000000..9b32121a135a5 --- /dev/null +++ b/ports/analog/linking/max32690_cktpy.ld @@ -0,0 +1,186 @@ +/** This file is part of the CircuitPython project: https://circuitpython.org +* +* SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices Inc. +* +* SPDX-License-Identifier: MIT +*/ + +MEMORY { + ROM (rx) : ORIGIN = 0x00000000, LENGTH = 128K + FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 3M + FLASH_FIRMWARE (rx) : ORIGIN = 0x10000000, LENGTH = 2992K + FLASH_FS (rx) : ORIGIN = 0x102E0000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1M +} +/* Minimum flash page is 16K */ +/* FLASH FIRMWARE: 3072K [3MB] - 16K - 64K = 2992K */ + +SECTIONS { + .rom : + { + KEEP(*(.rom_vector*)) + KEEP(*(.rom_handlers*)) + } > ROM + + + /** FIXME: can't place this in its own section for some reason + * system doesn't exit ROM code unless *(.isr_vector) + * is placed in the beginning of .text, + * even if .text is moved upward and *(.isr_vector) is + * placed at 0x10000000. + **/ + + /* Place ISR vector in a separate flash section */ + /* .isr_vector : */ + /* { */ + /* ISR Vector beginning of .text */ + /* KEEP(*(.isr_vector)) */ + /* KEEP(*(.isr_vector*)) */ + /* } > FLASH_ISR */ + + .text : + { + . = ALIGN(4); + _text = .; + + /* ISR Vector beginning of .text */ + /** fixme: may want to move this to FLASH_ISR long-term */ + KEEP(*(.isr_vector)) + KEEP(*(.isr_vector*)) + + . = ALIGN(4); + + /* program code; exclude RISCV code */ + EXCLUDE_FILE (*riscv.o) *(.text*) + *(.rodata*) /* read-only data: "const" */ + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + /* C++ Exception handling */ + KEEP(*(.eh_frame*)) + . = ALIGN(4); + _etext = .; + } > FLASH_FIRMWARE + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH_FIRMWARE + + /* Binary import */ + .bin_storage : + { + FILL(0xFF) + _bin_start_ = .; + KEEP(*(.bin_storage_img)) + _bin_end_ = .; + . = ALIGN(4); + } > FLASH_FIRMWARE + + /* it's used for C++ exception handling */ + /* we need to keep this to avoid overlapping */ + .ARM.exidx : + { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > FLASH_FIRMWARE + + .data : + { + . = ALIGN(4); + _data = .; + _sdata = .; + + *(vtable) + *(.data*) /*read-write initialized data: initialized global variable*/ + + /* These array sections are used by __libc_init_array to call static C++ constructors */ + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + /* Run the flash programming functions from SRAM */ + *(.flashprog) + + . = ALIGN(4); + _edata = .; + } > RAM AT>FLASH_FIRMWARE + __load_data = LOADADDR(.data); + + .bss : + { + . = ALIGN(4); + _sbss = .; /* Provide _sbss for Cktpy */ + _bss = .; + + *(.bss*) /*read-write zero initialized data: uninitialized global variable*/ + *(COMMON) + + . = ALIGN(4); + _ebss = .; + _ezero = .; /* Provide _ezero /_ebss for CktPython (same as ebss) */ + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + + _stack = __StackTop; + _estack = __StackLimit; /* Provide _estack for CktPython */ + + .heap (COPY): + { + . = ALIGN(4); + _heap = .; + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + *(.heap*) + __HeapLimit = ABSOLUTE(__StackLimit); + } > RAM + + _eheap = __HeapLimit; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= _ebss, "region RAM overflowed with stack") +} diff --git a/ports/analog/max32_port.h b/ports/analog/max32_port.h new file mode 100644 index 0000000000000..89830e96b0a49 --- /dev/null +++ b/ports/analog/max32_port.h @@ -0,0 +1,79 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#ifndef MAX32_PORT_H +#define MAX32_PORT_H + +#include + +#include "mxc_assert.h" +#include "mxc_delay.h" +#include "mxc_device.h" +#include "mxc_pins.h" +#include "mxc_sys.h" +#include "mcr_regs.h" + +#include "gpio.h" + +#ifdef MAX32690 +#include "system_max32690.h" +#include "max32690.h" + +// UART Ports & pins +#include "peripherals/max32690/max32_uart.h" +#include "peripherals/max32690/max32_i2c.h" +#include "peripherals/max32690/max32_spi.h" + +/** START: GPIO4 Handling specific to MAX32690 */ + #define GPIO4_PIN_MASK 0x00000003 + #define GPIO4_RESET_MASK 0xFFFFFF77 + #define GPIO4_OUTEN_MASK(mask) \ + (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_OE_POS) | \ + ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_OE_POS - 1))) + #define GPIO4_PULLDIS_MASK(mask) \ + (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_PE_POS) | \ + ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_PE_POS - 1))) + #define GPIO4_DATAOUT_MASK(mask) \ + (((mask & (1 << 0)) << MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \ + ((mask & (1 << 1)) << (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1))) + #define GPIO4_DATAOUT_GET_MASK(mask) \ + ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_DO) >> MXC_F_MCR_GPIO4_CTRL_P40_DO_POS) | \ + ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_DO) >> \ + (MXC_F_MCR_GPIO4_CTRL_P41_DO_POS - 1))) & \ + mask) + #define GPIO4_DATAIN_MASK(mask) \ + ((((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P40_IN) >> MXC_F_MCR_GPIO4_CTRL_P40_IN_POS) | \ + ((MXC_MCR->gpio4_ctrl & MXC_F_MCR_GPIO4_CTRL_P41_IN) >> \ + (MXC_F_MCR_GPIO4_CTRL_P41_IN_POS - 1))) & \ + mask) + #define GPIO4_AFEN_MASK(mask) \ + (((mask & (1 << 0)) << MXC_F_MCR_OUTEN_PDOWN_OUT_EN_POS) | \ + ((mask & (1 << 1)) >> (MXC_F_MCR_OUTEN_SQWOUT_EN_POS + 1))) +/** END: GPIO4 Handling specific to MAX32690 */ + +#endif + +/** Linker variables defined.... + * _estack: end of the stack + * _ebss: end of BSS section + * _ezero: same as ebss (acc. to main.c) + */ +extern uint32_t _ezero; +extern uint32_t _estack; +extern uint32_t _ebss; // Stored at the end of the bss section (which includes the heap). +extern uint32_t __stack, __heap; + +extern uint32_t SystemCoreClock; + +// Tick timer should be 1/1024 s. RTC Oscillator is usually 32.768 kHz ERTCO. +#define TICKS_PER_SEC 1024 + +#ifdef MAX32690 +// 12-bit ssec register, ticks @ 4096 Hz +#define SUBSEC_PER_TICK 4 +#endif + +#endif // MAX32_PORT_H diff --git a/ports/analog/mpconfigport.h b/ports/analog/mpconfigport.h new file mode 100644 index 0000000000000..3296661fca787 --- /dev/null +++ b/ports/analog/mpconfigport.h @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2015 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// 24KiB stack +#define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 + +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + +// Also includes mpconfigboard.h +#include "py/circuitpy_mpconfig.h" + +// Board flags: +#ifndef BOARD_OVERWRITE_SWD +#define BOARD_OVERWRITE_SWD (0) +#endif +#ifndef BOARD_VTOR_DEFER +#define BOARD_VTOR_DEFER (0) +#endif +#ifndef BOARD_NO_VBUS_SENSE +#define BOARD_NO_VBUS_SENSE (0) +#endif +#ifndef BOARD_NO_USB_OTG_ID_SENSE +#define BOARD_NO_USB_OTG_ID_SENSE (0) +#endif diff --git a/ports/analog/mpconfigport.mk b/ports/analog/mpconfigport.mk new file mode 100644 index 0000000000000..f1cd0bb2901e9 --- /dev/null +++ b/ports/analog/mpconfigport.mk @@ -0,0 +1,74 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +# SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +# SPDX-FileCopyrightText: Copyright (c) 2025 Peggy Zhu, Analog Devices, Inc. +# +# SPDX-License-Identifier: MIT + +CHIP_FAMILY ?= max32 + +# Necessary to build CircuitPython +LONGINT_IMPL ?= MPZ +INTERNAL_LIBM ?= 1 + +# Req'd for OS; all max32 have TRNG +CFLAGS += -DHAS_TRNG=1 + +INTERNAL_FLASH_FILESYSTEM = 1 + +#################################################################################### +# Suggested config for first-time porting +#################################################################################### +# These modules are implemented in ports//common-hal: + +CIRCUITPY_BUSIO ?= 1 +CIRCUITPY_RTC ?= 1 + +# Other modules (may or may not implement): +CIRCUITPY_ANALOGIO ?= 0 +CIRCUITPY_AUDIOBUSIO ?= 0 +CIRCUITPY_AUDIOIO ?= 0 +CIRCUITPY_COUNTIO ?= 0 +CIRCUITPY_NEOPIXEL_WRITE ?= 0 +CIRCUITPY_FREQUENCYIO ?= 0 +CIRCUITPY_I2CTARGET ?= 0 +CIRCUITPY_PULSEIO ?= 0 +CIRCUITPY_PWMIO ?= 0 +CIRCUITPY_NVM ?= 0 +CIRCUITPY_ROTARYIO ?= 0 +CIRCUITPY_SDCARDIO ?= 0 +CIRCUITPY_FRAMEBUFFERIO ?= 0 +# Requires SPI, PulseIO (stub ok): +CIRCUITPY_DISPLAYIO ?= 0 + +# These modules are implemented in shared-module/ - they can be included in +# any port once their prerequisites in common-hal are complete. +# No requirements, but takes extra flash +CIRCUITPY_ULAB = 1 +# Requires DigitalIO: +CIRCUITPY_BITBANGIO ?= 1 +# Requires Microcontroller +CIRCUITPY_TOUCHIO ?= 1 +# Requires OS +CIRCUITPY_RANDOM ?= 1 +# Requires busio.UART +CIRCUITPY_CONSOLE_UART ?= 0 +# Does nothing without I2C +CIRCUITPY_REQUIRE_I2C_PULLUPS = 0 +# Requires neopixel_write or SPI (dotstar) +CIRCUITPY_PIXELBUF ?= 0 + +#################################################################################### +# Required for clean building (additional CircuitPython Defaults) +#################################################################################### + +# Depends on BUSIO +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_KEYPAD = 0 +CIRCUITPY_BUSDEVICE = 0 + +# For CircuitPython CI +CIRCUITPY_BUILD_EXTENSIONS ?= elf + +CIRCUITPY_PORT_SERIAL = 1 diff --git a/ports/analog/mphalport.c b/ports/analog/mphalport.c new file mode 100644 index 0000000000000..8f305d6325e59 --- /dev/null +++ b/ports/analog/mphalport.c @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "mphalport.h" +#include "py/mphal.h" + +// includes __enable/__disable interrupts +#include "mxc_sys.h" + +#include "shared-bindings/microcontroller/__init__.h" + +void mp_hal_delay_us(mp_uint_t delay) { + common_hal_mcu_delay_us(delay); +} + +void mp_hal_disable_all_interrupts(void) { + __disable_irq(); +} + +void mp_hal_enable_all_interrupts(void) { + __enable_irq(); +} diff --git a/ports/analog/mphalport.h b/ports/analog/mphalport.h new file mode 100644 index 0000000000000..3cd3e00c6e18f --- /dev/null +++ b/ports/analog/mphalport.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "lib/oofatfs/ff.h" +#include "supervisor/shared/tick.h" + +// Global millisecond tick count +static inline mp_uint_t mp_hal_ticks_ms(void) { + return supervisor_ticks_ms32(); +} + +void mp_hal_set_interrupt_char(int c); + +void mp_hal_disable_all_interrupts(void); +void mp_hal_enable_all_interrupts(void); diff --git a/ports/analog/msdk b/ports/analog/msdk new file mode 160000 index 0000000000000..db69388844d29 --- /dev/null +++ b/ports/analog/msdk @@ -0,0 +1 @@ +Subproject commit db69388844d29e727cd245b90b54279341f77401 diff --git a/ports/analog/peripherals/max32690/gpios.c b/ports/analog/peripherals/max32690/gpios.c new file mode 100644 index 0000000000000..d0dd3ad0fc19c --- /dev/null +++ b/ports/analog/peripherals/max32690/gpios.c @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "gpios.h" + +volatile mxc_gpio_regs_t *gpio_ports[NUM_GPIO_PORTS] = +{MXC_GPIO0, MXC_GPIO1, MXC_GPIO2, MXC_GPIO3, MXC_GPIO4}; diff --git a/ports/analog/peripherals/max32690/gpios.h b/ports/analog/peripherals/max32690/gpios.h new file mode 100644 index 0000000000000..fe91227728291 --- /dev/null +++ b/ports/analog/peripherals/max32690/gpios.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/mphal.h" + +// MSDK HAL includes +#include "gpio.h" +#include "gpio_regs.h" +#include "max32690.h" diff --git a/ports/analog/peripherals/max32690/max32_i2c.c b/ports/analog/peripherals/max32690/max32_i2c.c new file mode 100644 index 0000000000000..4b9ec8b4db264 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_i2c.c @@ -0,0 +1,75 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/I2C.h" +#include "max32_i2c.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + + +/* Note: The MAX32690 assigns the same alternate function to multiple sets + * of pins. The drivers will enable both sets so that either can be used. + * Users should ensure the unused set is left unconnected. + * + * See MAX32690 Rev A2 Errata #16: + * https://www.analog.com/media/en/technical-documentation/data-sheets/max32690_a2_errata_rev2.pdf + * + * Additionally, note that the TQFN package does not expose some of the duplicate pins. For this package, + * enabling the un-routed GPIOs has been shown to cause initialization issues with the I2C block. + * To work around this, "MAX32690GTK_PACKAGE_TQFN" can be defined by the build system. The recommend place + * to do it is in the "board.mk" file of the BSP. This will prevent the inaccessible pins from being configured. + */ + +const mxc_gpio_cfg_t i2c_maps[NUM_I2C] = { + // I2C0 + { MXC_GPIO2, (MXC_GPIO_PIN_7 | MXC_GPIO_PIN_8), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C1 + { MXC_GPIO0, (MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // I2C2 + { MXC_GPIO1, (MXC_GPIO_PIN_7 | MXC_GPIO_PIN_8), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, +}; +#ifndef MAX32690GTK_PACKAGE_TQFN +const mxc_gpio_cfg_t i2c_maps_extra[NUM_I2C] = { + // I2C0A + { MXC_GPIO0, (MXC_GPIO_PIN_30 | MXC_GPIO_PIN_31), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_PULL_UP, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, + // I2C1A + { MXC_GPIO2, (MXC_GPIO_PIN_17 | MXC_GPIO_PIN_18), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_PULL_UP, MXC_GPIO_VSSEL_VDDIOH, MXC_GPIO_DRVSTR_0 }, + // I2C2C + { MXC_GPIO0, (MXC_GPIO_PIN_13 | MXC_GPIO_PIN_14), MXC_GPIO_FUNC_ALT3, + MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; +#endif + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl) { + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + + // Additional for loop to cover alternate potential I2C maps + #ifndef MAX32690GTK_PACKAGE_TQFN + for (int i = 0; i < NUM_I2C; i++) { + if ((i2c_maps_extra[i].port == (MXC_GPIO_GET_GPIO(sda->port))) + && (i2c_maps_extra[i].mask == ((sda->mask) | (scl->mask)))) { + return i; + } + } + #endif + + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_i2c.h b/ports/analog/peripherals/max32690/max32_i2c.h new file mode 100644 index 0000000000000..b64cfd308dcf5 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_i2c.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "i2c_regs.h" +#include "mxc_sys.h" +#include "i2c.h" +#include "peripherals/pins.h" + +#define NUM_I2C 3 + +int pinsToI2c(const mcu_pin_obj_t *sda, const mcu_pin_obj_t *scl); diff --git a/ports/analog/peripherals/max32690/max32_spi.c b/ports/analog/peripherals/max32690/max32_spi.c new file mode 100644 index 0000000000000..c78fd64dbd705 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_spi.c @@ -0,0 +1,44 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/SPI.h" +#include "max32_spi.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t spi_maps[NUM_SPI] = { + // SPI0 + { MXC_GPIO2, (MXC_GPIO_PIN_27 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT2, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI1 + { MXC_GPIO1, (MXC_GPIO_PIN_26 | MXC_GPIO_PIN_28 | MXC_GPIO_PIN_29), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI2 + { MXC_GPIO2, (MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3 | MXC_GPIO_PIN_4), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI3 + { MXC_GPIO0, (MXC_GPIO_PIN_16 | MXC_GPIO_PIN_20 | MXC_GPIO_PIN_21), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + // SPI4 + { MXC_GPIO1, (MXC_GPIO_PIN_1 | MXC_GPIO_PIN_2 | MXC_GPIO_PIN_3), + MXC_GPIO_FUNC_ALT1, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, +}; + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck) { + for (int i = 0; i < NUM_SPI; i++) { + if ((spi_maps[i].port == (MXC_GPIO_GET_GPIO(mosi->port))) + && (spi_maps[i].mask == ((mosi->mask) | (miso->mask) | (sck->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_spi.h b/ports/analog/peripherals/max32690/max32_spi.h new file mode 100644 index 0000000000000..76bb48a59a7e5 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_spi.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "spi_regs.h" +#include "mxc_sys.h" +#include "spi.h" +#include "peripherals/pins.h" + +#define NUM_SPI 5 + +int pinsToSpi(const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, + const mcu_pin_obj_t *sck); diff --git a/ports/analog/peripherals/max32690/max32_uart.c b/ports/analog/peripherals/max32690/max32_uart.c new file mode 100644 index 0000000000000..7d37708797415 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_uart.c @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +#include "common-hal/busio/UART.h" +#include "max32_uart.h" +#include "max32690.h" + +#include "py/runtime.h" +#include "py/mperrno.h" + +const mxc_gpio_cfg_t uart_maps[NUM_UARTS] = { + { MXC_GPIO2, (MXC_GPIO_PIN_11 | MXC_GPIO_PIN_12), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO2, (MXC_GPIO_PIN_14 | MXC_GPIO_PIN_16), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO1, (MXC_GPIO_PIN_9 | MXC_GPIO_PIN_10), MXC_GPIO_FUNC_ALT1, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 }, + { MXC_GPIO3, (MXC_GPIO_PIN_0 | MXC_GPIO_PIN_1), MXC_GPIO_FUNC_ALT2, + MXC_GPIO_PAD_WEAK_PULL_UP, MXC_GPIO_VSSEL_VDDIO, MXC_GPIO_DRVSTR_0 } +}; + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx) { + for (int i = 0; i < NUM_UARTS; i++) { + if ((uart_maps[i].port == (MXC_GPIO_GET_GPIO(tx->port))) + && (uart_maps[i].mask == ((tx->mask) | (rx->mask)))) { + return i; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pins); + return -1; +} diff --git a/ports/analog/peripherals/max32690/max32_uart.h b/ports/analog/peripherals/max32690/max32_uart.h new file mode 100644 index 0000000000000..f03b500a3c507 --- /dev/null +++ b/ports/analog/peripherals/max32690/max32_uart.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "uart_regs.h" +#include "mxc_sys.h" +#include "uart.h" +#include "peripherals/pins.h" + +#define NUM_UARTS 4 + +int pinsToUart(const mcu_pin_obj_t *rx, const mcu_pin_obj_t *tx); diff --git a/ports/analog/peripherals/max32690/pins.c b/ports/analog/peripherals/max32690/pins.c new file mode 100644 index 0000000000000..7550dc549efa4 --- /dev/null +++ b/ports/analog/peripherals/max32690/pins.c @@ -0,0 +1,123 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" +#include "max32690.h" + +const mcu_pin_obj_t pin_P0_00 = PIN(0, 0); +const mcu_pin_obj_t pin_P0_01 = PIN(0, 1); +const mcu_pin_obj_t pin_P0_02 = PIN(0, 2); +const mcu_pin_obj_t pin_P0_03 = PIN(0, 3); +const mcu_pin_obj_t pin_P0_04 = PIN(0, 4); +const mcu_pin_obj_t pin_P0_05 = PIN(0, 5); +const mcu_pin_obj_t pin_P0_06 = PIN(0, 6); +const mcu_pin_obj_t pin_P0_07 = PIN(0, 7); +const mcu_pin_obj_t pin_P0_08 = PIN(0, 8); +const mcu_pin_obj_t pin_P0_09 = PIN(0, 9); +const mcu_pin_obj_t pin_P0_10 = PIN(0, 10); +const mcu_pin_obj_t pin_P0_11 = PIN(0, 11); +const mcu_pin_obj_t pin_P0_12 = PIN(0, 12); +const mcu_pin_obj_t pin_P0_13 = PIN(0, 13); +const mcu_pin_obj_t pin_P0_14 = PIN(0, 14); +const mcu_pin_obj_t pin_P0_15 = PIN(0, 15); +const mcu_pin_obj_t pin_P0_16 = PIN(0, 16); +const mcu_pin_obj_t pin_P0_17 = PIN(0, 17); +const mcu_pin_obj_t pin_P0_18 = PIN(0, 18); +const mcu_pin_obj_t pin_P0_19 = PIN(0, 19); +const mcu_pin_obj_t pin_P0_20 = PIN(0, 20); +const mcu_pin_obj_t pin_P0_21 = PIN(0, 21); +const mcu_pin_obj_t pin_P0_22 = PIN(0, 22); +const mcu_pin_obj_t pin_P0_23 = PIN(0, 23); +const mcu_pin_obj_t pin_P0_24 = PIN(0, 24); +const mcu_pin_obj_t pin_P0_25 = PIN(0, 25); +const mcu_pin_obj_t pin_P0_26 = PIN(0, 26); +const mcu_pin_obj_t pin_P0_27 = PIN(0, 27); +const mcu_pin_obj_t pin_P0_28 = PIN(0, 28); +const mcu_pin_obj_t pin_P0_29 = PIN(0, 29); +const mcu_pin_obj_t pin_P0_30 = PIN(0, 30); +const mcu_pin_obj_t pin_P0_31 = PIN(0, 31); + +const mcu_pin_obj_t pin_P1_00 = PIN(1, 0); +const mcu_pin_obj_t pin_P1_01 = PIN(1, 1); +const mcu_pin_obj_t pin_P1_02 = PIN(1, 2); +const mcu_pin_obj_t pin_P1_03 = PIN(1, 3); +const mcu_pin_obj_t pin_P1_04 = PIN(1, 4); +const mcu_pin_obj_t pin_P1_05 = PIN(1, 5); +const mcu_pin_obj_t pin_P1_06 = PIN(1, 6); +const mcu_pin_obj_t pin_P1_07 = PIN(1, 7); +const mcu_pin_obj_t pin_P1_08 = PIN(1, 8); +const mcu_pin_obj_t pin_P1_09 = PIN(1, 9); +const mcu_pin_obj_t pin_P1_10 = PIN(1, 10); +const mcu_pin_obj_t pin_P1_11 = PIN(1, 11); +const mcu_pin_obj_t pin_P1_12 = PIN(1, 12); +const mcu_pin_obj_t pin_P1_13 = PIN(1, 13); +const mcu_pin_obj_t pin_P1_14 = PIN(1, 14); +const mcu_pin_obj_t pin_P1_15 = PIN(1, 15); +const mcu_pin_obj_t pin_P1_16 = PIN(1, 16); +const mcu_pin_obj_t pin_P1_17 = PIN(1, 17); +const mcu_pin_obj_t pin_P1_18 = PIN(1, 18); +const mcu_pin_obj_t pin_P1_19 = PIN(1, 19); +const mcu_pin_obj_t pin_P1_20 = PIN(1, 20); +const mcu_pin_obj_t pin_P1_21 = PIN(1, 21); +const mcu_pin_obj_t pin_P1_22 = PIN(1, 22); +const mcu_pin_obj_t pin_P1_23 = PIN(1, 23); +const mcu_pin_obj_t pin_P1_24 = PIN(1, 24); +const mcu_pin_obj_t pin_P1_25 = PIN(1, 25); +const mcu_pin_obj_t pin_P1_26 = PIN(1, 26); +const mcu_pin_obj_t pin_P1_27 = PIN(1, 27); +const mcu_pin_obj_t pin_P1_28 = PIN(1, 28); +const mcu_pin_obj_t pin_P1_29 = PIN(1, 29); +const mcu_pin_obj_t pin_P1_30 = PIN(1, 30); +const mcu_pin_obj_t pin_P1_31 = PIN(1, 31); + +const mcu_pin_obj_t pin_P2_00 = PIN(2, 0); +const mcu_pin_obj_t pin_P2_01 = PIN(2, 1); +const mcu_pin_obj_t pin_P2_02 = PIN(2, 2); +const mcu_pin_obj_t pin_P2_03 = PIN(2, 3); +const mcu_pin_obj_t pin_P2_04 = PIN(2, 4); +const mcu_pin_obj_t pin_P2_05 = PIN(2, 5); +const mcu_pin_obj_t pin_P2_06 = PIN(2, 6); +const mcu_pin_obj_t pin_P2_07 = PIN(2, 7); +const mcu_pin_obj_t pin_P2_08 = PIN(2, 8); +const mcu_pin_obj_t pin_P2_09 = PIN(2, 9); +const mcu_pin_obj_t pin_P2_10 = PIN(2, 10); +const mcu_pin_obj_t pin_P2_11 = PIN(2, 11); +const mcu_pin_obj_t pin_P2_12 = PIN(2, 12); +const mcu_pin_obj_t pin_P2_13 = PIN(2, 13); +const mcu_pin_obj_t pin_P2_14 = PIN(2, 14); +const mcu_pin_obj_t pin_P2_15 = PIN(2, 15); +const mcu_pin_obj_t pin_P2_16 = PIN(2, 16); +const mcu_pin_obj_t pin_P2_17 = PIN(2, 17); +const mcu_pin_obj_t pin_P2_18 = PIN(2, 18); +const mcu_pin_obj_t pin_P2_19 = PIN(2, 19); +const mcu_pin_obj_t pin_P2_20 = PIN(2, 20); +const mcu_pin_obj_t pin_P2_21 = PIN(2, 21); +const mcu_pin_obj_t pin_P2_22 = PIN(2, 22); +const mcu_pin_obj_t pin_P2_23 = PIN(2, 23); +const mcu_pin_obj_t pin_P2_24 = PIN(2, 24); +const mcu_pin_obj_t pin_P2_25 = PIN(2, 25); +const mcu_pin_obj_t pin_P2_26 = PIN(2, 26); +const mcu_pin_obj_t pin_P2_27 = PIN(2, 27); +const mcu_pin_obj_t pin_P2_28 = PIN(2, 28); +const mcu_pin_obj_t pin_P2_29 = PIN(2, 29); +const mcu_pin_obj_t pin_P2_30 = PIN(2, 30); +const mcu_pin_obj_t pin_P2_31 = PIN(2, 31); + +const mcu_pin_obj_t pin_P3_00 = PIN(3, 0); +const mcu_pin_obj_t pin_P3_01 = PIN(3, 1); +const mcu_pin_obj_t pin_P3_02 = PIN(3, 2); +const mcu_pin_obj_t pin_P3_03 = PIN(3, 3); +const mcu_pin_obj_t pin_P3_04 = PIN(3, 4); +const mcu_pin_obj_t pin_P3_05 = PIN(3, 5); +const mcu_pin_obj_t pin_P3_06 = PIN(3, 6); +const mcu_pin_obj_t pin_P3_07 = PIN(3, 7); +const mcu_pin_obj_t pin_P3_08 = PIN(3, 8); +const mcu_pin_obj_t pin_P3_09 = PIN(3, 9); + +const mcu_pin_obj_t pin_P4_00 = PIN(4, 0); +const mcu_pin_obj_t pin_P4_01 = PIN(4, 1); diff --git a/ports/analog/peripherals/max32690/pins.h b/ports/analog/peripherals/max32690/pins.h new file mode 100644 index 0000000000000..44022decdf716 --- /dev/null +++ b/ports/analog/peripherals/max32690/pins.h @@ -0,0 +1,120 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern const mcu_pin_obj_t pin_P0_00; +extern const mcu_pin_obj_t pin_P0_01; +extern const mcu_pin_obj_t pin_P0_02; +extern const mcu_pin_obj_t pin_P0_03; +extern const mcu_pin_obj_t pin_P0_04; +extern const mcu_pin_obj_t pin_P0_05; +extern const mcu_pin_obj_t pin_P0_06; +extern const mcu_pin_obj_t pin_P0_07; +extern const mcu_pin_obj_t pin_P0_08; +extern const mcu_pin_obj_t pin_P0_09; +extern const mcu_pin_obj_t pin_P0_10; +extern const mcu_pin_obj_t pin_P0_11; +extern const mcu_pin_obj_t pin_P0_12; +extern const mcu_pin_obj_t pin_P0_13; +extern const mcu_pin_obj_t pin_P0_14; +extern const mcu_pin_obj_t pin_P0_15; +extern const mcu_pin_obj_t pin_P0_16; +extern const mcu_pin_obj_t pin_P0_17; +extern const mcu_pin_obj_t pin_P0_18; +extern const mcu_pin_obj_t pin_P0_19; +extern const mcu_pin_obj_t pin_P0_20; +extern const mcu_pin_obj_t pin_P0_21; +extern const mcu_pin_obj_t pin_P0_22; +extern const mcu_pin_obj_t pin_P0_23; +extern const mcu_pin_obj_t pin_P0_24; +extern const mcu_pin_obj_t pin_P0_25; +extern const mcu_pin_obj_t pin_P0_26; +extern const mcu_pin_obj_t pin_P0_27; +extern const mcu_pin_obj_t pin_P0_28; +extern const mcu_pin_obj_t pin_P0_29; +extern const mcu_pin_obj_t pin_P0_30; +extern const mcu_pin_obj_t pin_P0_31; + +extern const mcu_pin_obj_t pin_P1_00; +extern const mcu_pin_obj_t pin_P1_01; +extern const mcu_pin_obj_t pin_P1_02; +extern const mcu_pin_obj_t pin_P1_03; +extern const mcu_pin_obj_t pin_P1_04; +extern const mcu_pin_obj_t pin_P1_05; +extern const mcu_pin_obj_t pin_P1_06; +extern const mcu_pin_obj_t pin_P1_07; +extern const mcu_pin_obj_t pin_P1_08; +extern const mcu_pin_obj_t pin_P1_09; +extern const mcu_pin_obj_t pin_P1_10; +extern const mcu_pin_obj_t pin_P1_11; +extern const mcu_pin_obj_t pin_P1_12; +extern const mcu_pin_obj_t pin_P1_13; +extern const mcu_pin_obj_t pin_P1_14; +extern const mcu_pin_obj_t pin_P1_15; +extern const mcu_pin_obj_t pin_P1_16; +extern const mcu_pin_obj_t pin_P1_17; +extern const mcu_pin_obj_t pin_P1_18; +extern const mcu_pin_obj_t pin_P1_19; +extern const mcu_pin_obj_t pin_P1_20; +extern const mcu_pin_obj_t pin_P1_21; +extern const mcu_pin_obj_t pin_P1_22; +extern const mcu_pin_obj_t pin_P1_23; +extern const mcu_pin_obj_t pin_P1_24; +extern const mcu_pin_obj_t pin_P1_25; +extern const mcu_pin_obj_t pin_P1_26; +extern const mcu_pin_obj_t pin_P1_27; +extern const mcu_pin_obj_t pin_P1_28; +extern const mcu_pin_obj_t pin_P1_29; +extern const mcu_pin_obj_t pin_P1_30; +extern const mcu_pin_obj_t pin_P1_31; + +extern const mcu_pin_obj_t pin_P2_00; +extern const mcu_pin_obj_t pin_P2_01; +extern const mcu_pin_obj_t pin_P2_02; +extern const mcu_pin_obj_t pin_P2_03; +extern const mcu_pin_obj_t pin_P2_04; +extern const mcu_pin_obj_t pin_P2_05; +extern const mcu_pin_obj_t pin_P2_06; +extern const mcu_pin_obj_t pin_P2_07; +extern const mcu_pin_obj_t pin_P2_08; +extern const mcu_pin_obj_t pin_P2_09; +extern const mcu_pin_obj_t pin_P2_10; +extern const mcu_pin_obj_t pin_P2_11; +extern const mcu_pin_obj_t pin_P2_12; +extern const mcu_pin_obj_t pin_P2_13; +extern const mcu_pin_obj_t pin_P2_14; +extern const mcu_pin_obj_t pin_P2_15; +extern const mcu_pin_obj_t pin_P2_16; +extern const mcu_pin_obj_t pin_P2_17; +extern const mcu_pin_obj_t pin_P2_18; +extern const mcu_pin_obj_t pin_P2_19; +extern const mcu_pin_obj_t pin_P2_20; +extern const mcu_pin_obj_t pin_P2_21; +extern const mcu_pin_obj_t pin_P2_22; +extern const mcu_pin_obj_t pin_P2_23; +extern const mcu_pin_obj_t pin_P2_24; +extern const mcu_pin_obj_t pin_P2_25; +extern const mcu_pin_obj_t pin_P2_26; +extern const mcu_pin_obj_t pin_P2_27; +extern const mcu_pin_obj_t pin_P2_28; +extern const mcu_pin_obj_t pin_P2_29; +extern const mcu_pin_obj_t pin_P2_30; +extern const mcu_pin_obj_t pin_P2_31; + +extern const mcu_pin_obj_t pin_P3_00; +extern const mcu_pin_obj_t pin_P3_01; +extern const mcu_pin_obj_t pin_P3_02; +extern const mcu_pin_obj_t pin_P3_03; +extern const mcu_pin_obj_t pin_P3_04; +extern const mcu_pin_obj_t pin_P3_05; +extern const mcu_pin_obj_t pin_P3_06; +extern const mcu_pin_obj_t pin_P3_07; +extern const mcu_pin_obj_t pin_P3_08; +extern const mcu_pin_obj_t pin_P3_09; + +extern const mcu_pin_obj_t pin_P4_00; // BTLDR Stimulus +extern const mcu_pin_obj_t pin_P4_01; diff --git a/ports/analog/peripherals/pins.h b/ports/analog/peripherals/pins.h new file mode 100644 index 0000000000000..3bd7d02bf46d7 --- /dev/null +++ b/ports/analog/peripherals/pins.h @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +// STD includes +#include +#include + +// CktPy includes +#include "py/obj.h" + +// HAL includes +#include "gpio.h" +#include "gpio_regs.h" + +typedef struct { + mp_obj_base_t base; + uint8_t port; + uint32_t mask; // the pad # target e.g. P0.01 is Port=0, Mask=1 + mxc_gpio_vssel_t level; +} mcu_pin_obj_t; + +extern const mp_obj_type_t mcu_pin_type; + +#define PIN(pin_port, pin_mask) { {&mcu_pin_type}, .port = pin_port, .mask = 1UL << pin_mask, .level = MXC_GPIO_VSSEL_VDDIO } + +// for non-connected pins +#define NO_PIN 0xFF + +#ifdef MAX32690 +#include "max32690/pins.h" +#endif diff --git a/ports/analog/qstrdefsport.h b/ports/analog/qstrdefsport.h new file mode 100644 index 0000000000000..2d2c260923489 --- /dev/null +++ b/ports/analog/qstrdefsport.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// Do not use #pragma once in this file; it will cause a warning during qstr generation. + +// qstrs specific to this port +// *FORMAT-OFF* diff --git a/ports/analog/supervisor/internal_flash.c b/ports/analog/supervisor/internal_flash.c new file mode 100644 index 0000000000000..8518b235566c7 --- /dev/null +++ b/ports/analog/supervisor/internal_flash.c @@ -0,0 +1,246 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George +// SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "supervisor/internal_flash.h" + +#include +#include +#include + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#include "py/obj.h" +#include "py/mphal.h" +#include "py/runtime.h" + +#include "supervisor/filesystem.h" +#include "supervisor/flash.h" +#include "supervisor/shared/safe_mode.h" +#if CIRCUITPY_USB_DEVICE +#include "supervisor/usb.h" +#endif + +#include "mpconfigboard.h" + +// MAX32 HAL Includes +#include "flc.h" +#include "flc_reva.h" +#include "icc.h" // includes icc_.c for MSDK die type +#include "mxc_device.h" + +/** + * NOTE: + * ANY function which modifies flash contents must execute from a crit section. + * This is because FLC functions are loc'd in RAM, and an ISR executing + * from Flash will trigger a HardFault. + * + * An alternative would be to initialize with NVIC_SetRAM(), + * which makes ISRs execute from RAM. + * + * NOTE: + * Additionally, any code that modifies flash contents must disable the + * cache. Turn off ICC0 any time flash is to be modified. Remember to re-enable if using. + * + * For Maxim devices which include an additional RISC-V processor, this shall be ignored. + * Therefore only ICC0 need be used for the purpose of these functions. + */ + +typedef struct { + const uint32_t base_addr; + const uint32_t sector_size; + const uint32_t num_sectors; +} flash_layout_t; + +#ifdef MAX32690 +// struct layout is the actual layout of flash +// FS Code will use INTERNAL_FLASH_FILESYSTEM_START_ADDR +// and won't conflict with ISR vector in first 16 KiB of flash +static const flash_layout_t flash_layout[] = { + { 0x10000000, FLASH_PAGE_SIZE, 192}, + // { 0x10300000, 0x2000, 32 }, // RISC-V flash +}; +// must be able to hold a full page (for re-writing upon erase) +static uint32_t page_buffer[FLASH_PAGE_SIZE / 4] = {0x0}; + +#else +#error "Invalid BOARD. Please set BOARD equal to any board under 'boards/'." +#endif + +static inline int32_t block2addr(uint32_t block) { + if (block >= 0 && block < INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS) { + return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; + } else { + return -1; + } +} + +// Get index, start addr, & size of the flash sector where addr lies +int flash_get_sector_info(uint32_t addr, uint32_t *start_addr, uint32_t *size) { + // This function should return -1 in the event of errors. + if (addr >= flash_layout[0].base_addr) { + uint32_t sector_index = 0; + if (MP_ARRAY_SIZE(flash_layout) == 1) { + sector_index = (addr - flash_layout[0].base_addr) / flash_layout[0].sector_size; + if (sector_index >= flash_layout[0].num_sectors) { + return -1; // addr is not in flash + } + if (start_addr) { + *start_addr = flash_layout[0].base_addr + (sector_index * flash_layout[0].sector_size); + } else { + return -1; // start_addr is NULL + } + if (size) { + *size = flash_layout[0].sector_size; + } else { + return -1; // size is NULL + } + return sector_index; + } + + // algorithm for multiple flash sections + for (uint8_t i = 0; i < MP_ARRAY_SIZE(flash_layout); ++i) { + for (uint8_t j = 0; j < flash_layout[i].num_sectors; ++j) { + uint32_t sector_start_next = flash_layout[i].base_addr + + (j + 1) * flash_layout[i].sector_size; + if (addr < sector_start_next) { + if (start_addr) { + *start_addr = flash_layout[i].base_addr + + j * flash_layout[i].sector_size; + } + if (size) { + *size = flash_layout[i].sector_size; + } + return sector_index; + } + ++sector_index; + } + } + } + return -1; +} + +void supervisor_flash_init(void) { + // No initialization needed. + // Pay attention to the note at the top of this file! +} + +uint32_t supervisor_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +uint32_t supervisor_flash_get_block_count(void) { + return INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS; +} + +void port_internal_flash_flush(void) { + + // Flush all instruction cache + // ME18 has bug where top-level sysctrl flush bit only works one. + // Have to use low-level flush bits for each ICC instance. + MXC_ICC_Flush(MXC_ICC0); + MXC_ICC_Flush(MXC_ICC1); + + // Clear the line fill buffer by reading 2 pages from flash + volatile uint32_t *line_addr; + volatile uint32_t line; + line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE); + line = *line_addr; + line_addr = (uint32_t *)(MXC_FLASH_MEM_BASE + MXC_FLASH_PAGE_SIZE); + line = *line_addr; + (void)line; // Silence build warnings that this variable is not used. +} + +// Read flash blocks, using cache if it contains the right data +// return 0 on success, non-zero on error +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { + // Find the address of the block we want to read + int src_addr = block2addr(block); + if (src_addr == -1) { + // bad block num + return 1; + } + + uint32_t sector_size, sector_start; + if (flash_get_sector_info(src_addr, §or_start, §or_size) == -1) { + // bad sector idx + return 2; + } + + /** NOTE: The MXC_FLC_Read function executes from SRAM and does some more error checking + * than memcpy does. Will use it for now. + */ + MXC_FLC_Read(src_addr, dest, FILESYSTEM_BLOCK_SIZE * num_blocks); + + return 0; // success +} + +// Write to flash blocks +// return 0 on success, non-zero on error +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { + uint32_t error, blocks_left, count, page_start, page_size = 0; + + while (num_blocks > 0) { + int dest_addr = block2addr(block_num); + // bad block number passed in + if (dest_addr == -1) { + return 1; + } + + if (flash_get_sector_info(dest_addr, &page_start, &page_size) == -1) { + reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); + } + + // Find the number of blocks left within this sector + // BLOCKS_LEFT = (SECTOR_SIZE - BLOCK_OFFSET within sector)) / BLOCK_SIZE + blocks_left = (page_size - (dest_addr - page_start)) / FILESYSTEM_BLOCK_SIZE; + count = MIN(num_blocks, blocks_left); + + MXC_ICC_Disable(MXC_ICC0); + + // Buffer the page of flash to erase + MXC_FLC_Read(page_start, page_buffer, page_size); + + // Erase flash page + MXC_CRITICAL( + error = MXC_FLC_PageErase(dest_addr); + ); + if (error != E_NO_ERROR) { + // lock flash & reset + MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); + } + + // Copy new src data into the page buffer + // fill the new data in at the offset dest_addr - page_start + // account for uint32_t page_buffer vs uint8_t src + memcpy((page_buffer + (dest_addr - page_start) / 4), src, count * FILESYSTEM_BLOCK_SIZE); + + // Write new page buffer back into flash + MXC_CRITICAL( + error = MXC_FLC_Write(page_start, page_size, page_buffer); + ); + if (error != E_NO_ERROR) { + // lock flash & reset + MXC_FLC0->ctrl = (MXC_FLC0->ctrl & ~MXC_F_FLC_REVA_CTRL_UNLOCK) | MXC_S_FLC_REVA_CTRL_UNLOCK_LOCKED; + reset_into_safe_mode(SAFE_MODE_FLASH_WRITE_FAIL); + } + + MXC_ICC_Enable(MXC_ICC0); + + block_num += count; + src += count * FILESYSTEM_BLOCK_SIZE; + num_blocks -= count; + } + return 0; // success +} + +// Empty the fs cache +void supervisor_flash_release_cache(void) { + supervisor_flash_flush(); +} diff --git a/ports/analog/supervisor/internal_flash.h b/ports/analog/supervisor/internal_flash.h new file mode 100644 index 0000000000000..cc25f80be770a --- /dev/null +++ b/ports/analog/supervisor/internal_flash.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/mpconfig.h" + +#define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE) diff --git a/ports/analog/supervisor/port.c b/ports/analog/supervisor/port.c new file mode 100644 index 0000000000000..ee410a38148e9 --- /dev/null +++ b/ports/analog/supervisor/port.c @@ -0,0 +1,333 @@ +/****************************************************************************** + * + * Copyright (C) 2022-2023 Maxim Integrated Products, Inc. All Rights Reserved. + * (now owned by Analog Devices, Inc.), + * Copyright (C) 2023 Analog Devices, Inc. All Rights Reserved. This software + * is proprietary to Analog Devices, Inc. and its licensors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ******************************************************************************/ + +/** + * @file port.c + * @author Brandon Hurst @ Analog Devices, Inc. + * @brief Functions required for a basic CircuitPython port + * @date 2024-07-30 + * + * @copyright Copyright (c) 2024 + */ + +#include +#include +#include "supervisor/background_callback.h" +#include "supervisor/board.h" +#include "supervisor/port.h" + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/__init__.h" + +// Sys includes +#include "max32_port.h" +#include "nvic_table.h" + +// Timers +#include "mxc_delay.h" +#include "rtc.h" + +// true random number generator, TRNG +#include "trng.h" + +// msec to RTC subsec ticks (4 kHz) +/* Converts a time in milleseconds to equivalent RSSA register value */ +#define MSEC_TO_SS_ALARM(x) (0 - ((x * 4096) / 1000)) + +// Externs defined by linker .ld file +extern uint32_t _stack, _heap, _estack, _eheap; +extern uint32_t _ebss; + +// From boards/$(BOARD)/board.c +extern const mxc_gpio_cfg_t pb_pin[]; +extern const int num_pbs; +extern const mxc_gpio_cfg_t led_pin[]; +extern const int num_leds; + +// For saving rtc data for ticks +static uint32_t subsec, sec = 0; +static uint32_t tick_flag = 0; + +// defined by cmsis core files +extern void NVIC_SystemReset(void) MP_NORETURN; + +volatile uint32_t system_ticks = 0; + +void SysTick_Handler(void) { + system_ticks++; + + MXC_DelayHandler(); +} + + +safe_mode_t port_init(void) { + int err = E_NO_ERROR; + + // Set Vector Table to RAM & configure ARM core to use RAM-based ISRs + // This allows definition of ISRs with custom names + // + // Useful for mapping ISRs with names not related to a specific IRQn. + // Source: https://arm-software.github.io/CMSIS_5/Core/html/using_VTOR_pg.html + NVIC_SetRAM(); + + // 1ms tick timer + SysTick_Config(SystemCoreClock / 1000); + NVIC_EnableIRQ(SysTick_IRQn); + + // Enable GPIO (enables clocks + common init for ports) + for (int i = 0; i < MXC_CFG_GPIO_INSTANCES; i++) { + err = MXC_GPIO_Init(0x1 << i); + if (err) { + return SAFE_MODE_PROGRAMMATIC; + } + } + + // Enable clock to RTC peripheral + MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_ERTCO_EN; + while (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_ERTCO_RDY)) { + ; + } + + NVIC_EnableIRQ(RTC_IRQn); + NVIC_EnableIRQ(USB_IRQn); + + // Init RTC w/ 0sec, 0subsec + // Driven by 32.768 kHz ERTCO, with ssec= 1/4096 s + while (MXC_RTC_Init(0, 0) != E_SUCCESS) { + } + ; + + // enable 1 sec RTC SSEC alarm + MXC_RTC_DisableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + MXC_RTC_SetSubsecondAlarm(MSEC_TO_SS_ALARM(1000)); + MXC_RTC_EnableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + + // Enable RTC + while (MXC_RTC_Start() != E_SUCCESS) { + } + ; + + // enable TRNG (true random number generator) + #ifdef CIRCUITPY_RANDOM + MXC_TRNG_Init(); + #endif + + return SAFE_MODE_NONE; +} + +void TRNG_IRQHandler(void) { + MXC_TRNG_Handler(); +} + +void RTC_IRQHandler(void) { + // Read flags to clear + int flags = MXC_RTC_GetFlags(); + + switch (flags) { + case MXC_F_RTC_CTRL_SSEC_ALARM: + MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_SSEC_ALARM); + break; + case MXC_F_RTC_CTRL_TOD_ALARM: + MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_TOD_ALARM); + break; + case MXC_F_RTC_CTRL_RDY: + MXC_RTC_ClearFlags(MXC_F_RTC_CTRL_RDY); + break; + default: + break; + } + + tick_flag = 1; +} + +// Reset the MCU completely +void reset_cpu(void) { + // includes MCU reset request + awaits on memory bus + NVIC_SystemReset(); +} + +// Reset MCU state +void reset_port(void) { +} + +// Reset to the bootloader +// note: not implemented since max32 requires external signals to +// activate bootloaders +void reset_to_bootloader(void) { + NVIC_SystemReset(); + while (true) { + __NOP(); + } +} + +/** Acquire values of stack & heap starts & limits + * Return variables defined by linkerscript. + */ +uint32_t *port_stack_get_limit(void) { + // ignore array bounds GCC warnings + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" + + // NOTE: Only return how much stack we have allotted for CircuitPython + return port_stack_get_top() - (CIRCUITPY_DEFAULT_STACK_SIZE + CIRCUITPY_EXCEPTION_STACK_SIZE) / sizeof(uint32_t); + #pragma GCC diagnostic pop +} +uint32_t *port_stack_get_top(void) { + return &_stack; +} +uint32_t *port_heap_get_bottom(void) { + return &_heap; +} +uint32_t *port_heap_get_top(void) { + return port_stack_get_limit(); +} + +/** Save & retrieve a word from memory over a reset cycle. + * Used for safe mode + */ +void port_set_saved_word(uint32_t value) { + _ebss = value; +} +uint32_t port_get_saved_word(void) { + return _ebss; +} + +// Raw monotonic tick count since startup. +// NOTE (rollover): +// seconds reg is 32 bits, can hold up to 2^32-1 +// theref. rolls over after ~136 years +uint64_t port_get_raw_ticks(uint8_t *subticks) { + // Ensure we can read from ssec register as soon as we can + // MXC function does cross-tick / busy checking of RTC controller + if (MXC_RTC->ctrl & MXC_F_RTC_CTRL_EN) { + // NOTE: RTC_GetTime always returns BUSY if RTC is not running + while ((MXC_RTC_GetTime(&sec, &subsec)) != E_NO_ERROR) { + ; + } + } else { + sec = MXC_RTC->sec; + subsec = MXC_RTC->ssec; + } + + // Return ticks given total subseconds + // ticks = TICKS/s * s + subsec/ subs/tick + uint64_t raw_ticks = ((uint64_t)TICKS_PER_SEC) * sec + (subsec / SUBSEC_PER_TICK); + + if (subticks) { + // subticks may only be filled to a resn of 1/4096 in some cases + // e.g. multiply by 32 / 8 = 4 to get true 1/32768 subticks + *subticks = (32 / (SUBSEC_PER_TICK)) * (subsec - (subsec / SUBSEC_PER_TICK)); + } + + return raw_ticks; +} + +// Enable 1/1024 second tick. +void port_enable_tick(void) { + while (MXC_RTC_Start() == E_BUSY) { + ; + } +} + +// Disable 1/1024 second tick. +void port_disable_tick(void) { + while (MXC_RTC_Stop() == E_BUSY) { + ; + } +} + +// Wake the CPU after a given # of ticks or sooner +void port_interrupt_after_ticks(uint32_t ticks) { + uint32_t ticks_msec = 0; + + ticks_msec = (ticks / TICKS_PER_SEC) * 1000; + + // Disable RTC interrupts + MXC_RTC_DisableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE | + MXC_F_RTC_CTRL_TOD_ALARM_IE | MXC_F_RTC_CTRL_RDY_IE); + + // Stop RTC & store current time & ticks + port_get_raw_ticks(NULL); + + // Clear the flag to be set by the RTC Handler + tick_flag = 0; + + // Subsec alarm is the starting/reload value of the SSEC counter. + // ISR triggered when SSEC rolls over from 0xFFFF_FFFF to 0x0 + while (MXC_RTC_SetSubsecondAlarm(MSEC_TO_SS_ALARM(ticks_msec)) != E_SUCCESS) { + } + + MXC_RTC_EnableInt(MXC_F_RTC_CTRL_SSEC_ALARM_IE); + +} + +void port_idle_until_interrupt(void) { + #if CIRCUITPY_RTC + // Check if alarm triggers before we even got here + if (MXC_RTC_GetFlags() == (MXC_F_RTC_CTRL_TOD_ALARM | MXC_F_RTC_CTRL_SSEC_ALARM)) { + return; + } + #endif + + // Interrupts should be disabled to ensure the ISR queue is flushed + // WFI still returns as long as the interrupt flag toggles; + // only when we re-enable interrupts will the ISR function trigger + common_hal_mcu_disable_interrupts(); + if (!background_callback_pending()) { + __DSB(); + /** DEBUG: may comment out WFI for debugging port functions */ + // __WFI(); + } + common_hal_mcu_enable_interrupts(); +} + +__attribute__((used)) void MemManage_Handler(void) { + reset_into_safe_mode(SAFE_MODE_HARD_FAULT); + while (true) { + asm ("nop;"); + } +} + +__attribute__((used)) void BusFault_Handler(void) { + reset_into_safe_mode(SAFE_MODE_HARD_FAULT); + while (true) { + asm ("nop;"); + } +} + +__attribute__((used)) void UsageFault_Handler(void) { + reset_into_safe_mode(SAFE_MODE_HARD_FAULT); + while (true) { + asm ("nop;"); + } +} + +__attribute__((used)) void HardFault_Handler(void) { + reset_into_safe_mode(SAFE_MODE_HARD_FAULT); + while (true) { + asm ("nop;"); + } +} + +// Required by libc _init_array loops in startup code +// if we are compiling using "-nostdlib/-nostartfiles" +void _init(void) { +} diff --git a/ports/analog/supervisor/serial.c b/ports/analog/supervisor/serial.c new file mode 100644 index 0000000000000..bd4472875a010 --- /dev/null +++ b/ports/analog/supervisor/serial.c @@ -0,0 +1,88 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017, 2018 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) Brandon Hurst, Analog Devices, Inc. +// +// SPDX-License-Identifier: MIT + +#include "py/mphal.h" +#include +#include "supervisor/shared/serial.h" + +#include "uart.h" +#include "uart_regs.h" + +#ifndef MAX32_SERIAL +#define MAX32_SERIAL 0 +#endif + +#if MAX32_SERIAL +#ifdef MAX32690 +#define CONSOLE_UART MXC_UART0 +#endif +#endif + +void port_serial_early_init(void) { + +} + +void port_serial_init(void) { + #if MAX32_SERIAL + MXC_GCR->clkctrl |= MXC_F_GCR_CLKCTRL_IBRO_EN; + while (!(MXC_GCR->clkctrl & MXC_F_GCR_CLKCTRL_IBRO_RDY)) { + ; + } + MXC_UART_Init(CONSOLE_UART, 115200, MXC_UART_IBRO_CLK); + #endif +} + +bool port_serial_connected(void) { + return true; +} + +char port_serial_read(void) { + #if MAX32_SERIAL + // uint8_t data; + // HAL_UART_Receive(&huart2, &data, 1, 500); + // return data; + uint8_t rData; + + mxc_uart_req_t uart_req = { + .uart = CONSOLE_UART, + .rxCnt = 0, + .txCnt = 0, + .txData = NULL, + .rxData = &rData, + .txLen = 0, + .rxLen = 1 + }; + MXC_UART_Transaction(&uart_req); + return rData; + #else + return -1; + #endif +} + +uint32_t port_serial_bytes_available(void) { + #if MAX32_SERIAL + return MXC_UART_GetRXFIFOAvailable(CONSOLE_UART); + #else + return 0; + #endif +} + +void port_serial_write_substring(const char *text, uint32_t len) { + #if MAX32_SERIAL + mxc_uart_req_t uart_req = { + .uart = CONSOLE_UART, + .rxCnt = 0, + .txCnt = 0, + .txData = (const unsigned char *)text, + .rxData = NULL, + .txLen = len, + .rxLen = 0 + }; + MXC_UART_Transaction(&uart_req); + #endif +} diff --git a/ports/analog/supervisor/usb.c b/ports/analog/supervisor/usb.c new file mode 100644 index 0000000000000..1624359ab51f9 --- /dev/null +++ b/ports/analog/supervisor/usb.c @@ -0,0 +1,43 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 hathach for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Brandon Hurst, Analog Devices, Inc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/usb.h" +#include "common-hal/microcontroller/Pin.h" + +#include "py/mpconfig.h" + +#include "lib/tinyusb/src/device/usbd.h" + +// max32 includes +#include "mxc_sys.h" +#include "gcr_regs.h" +#include "mcr_regs.h" + +void init_usb_hardware(void) { + // USB GPIOs are non-configurable on MAX32 devices + // No need to add them to the never_reset list for mcu/Pin API. + + // 1 ms SysTick initialized in board.c + + // Enable requisite clocks & power for USB + MXC_SYS_ClockSourceEnable(MXC_SYS_CLOCK_IPO); + MXC_MCR->ldoctrl |= MXC_F_MCR_LDOCTRL_0P9EN; + MXC_SYS_ClockEnable(MXC_SYS_PERIPH_CLOCK_USB); + MXC_SYS_Reset_Periph(MXC_SYS_RESET0_USB); + + // Supervisor calls TinyUSB's dcd_init, + // which initializes the USB PHY. + // Depending on CIRCUITPY_TINYUSB and CIRCUITPY_USB_DEVICE + + // Interrupt enables are left to TUSB depending on the device class +} + +void USB_IRQHandler(void) { + // Schedules USB background callback + // appropriate to a given device class via TinyUSB lib + usb_irq_handler(0); +} diff --git a/ports/analog/tools/debug-dap.gdb b/ports/analog/tools/debug-dap.gdb new file mode 100644 index 0000000000000..d0aa7e2b13fa0 --- /dev/null +++ b/ports/analog/tools/debug-dap.gdb @@ -0,0 +1,3 @@ +target remote :3333 +break main +continue diff --git a/ports/analog/tools/debug-dap.sh b/ports/analog/tools/debug-dap.sh new file mode 100644 index 0000000000000..df2964fcb122a --- /dev/null +++ b/ports/analog/tools/debug-dap.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Primer on taking cmd line args in Linux shell scripts +# $0 is the script itself +# $1 $2 $3 are arg1, arg2, arg3, etc + +# Export OCD Path +### USER ACTION: Replace with your path to OpenOCD ### +OCD_PATH="~/MaximSDK/Tools/OpenOCD" + +# Call openocd to setup the debug server, storing the PID for OpenOCD +sh -c "openocd -s $OCD_PATH/scripts -f interface/cmsis-dap.cfg -f target/$1.cfg -c \"init; reset halt\" " & + +# Allow enough time for OCD server to set up +# + wait for the sleep to finish +sleep 3 & +wait $! + +# spawn the gdb process and store the gdb_pid +gdb-multiarch build-apard32690/firmware.elf -x "tools/debug-dap.gdb" + +# when gdb exits, kill all openocd processes +killall openocd diff --git a/ports/analog/tools/flash_max32.jlink b/ports/analog/tools/flash_max32.jlink new file mode 100644 index 0000000000000..0453f4cb077fd --- /dev/null +++ b/ports/analog/tools/flash_max32.jlink @@ -0,0 +1,7 @@ +selectinterface swd +erase +loadbin build-apard32690/firmware.bin 0x10000000 +reset +halt +go +exit diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 0c4eb38613095..0aaf6e3d849bf 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -107,7 +107,7 @@ else endif endif -CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes +CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition ifeq ($(CHIP_FAMILY), samd21) CFLAGS += \ @@ -117,7 +117,7 @@ CFLAGS += \ -msoft-float \ -mfloat-abi=soft \ -DSAMD21 -LIBS := libs/libgcc-12.1.0-Os-v6-m-nofp.a -lc +LIBS := libs/libgcc-14.2.0-Os-v6-m-nofp.a -lc else LIBS := -lgcc -lc endif @@ -169,7 +169,7 @@ LIBS += -lm endif ifeq ($(CHIP_FAMILY), samd21) -LDFLAGS += -mthumb -mcpu=cortex-m0plus -Lasf/thirdparty/CMSIS/Lib/GCC/ +LDFLAGS += -mthumb -mcpu=cortex-m0plus -Lasf/thirdparty/CMSIS/Lib/GCC/ # codespell:ignore thirdparty BOOTLOADER_SIZE := 0x2000 else ifeq ($(CHIP_FAMILY), samd51) LDFLAGS += -mthumb -mcpu=cortex-m4 @@ -284,6 +284,7 @@ SRC_C += \ lib/tinyusb/src/portable/microchip/samd/dcd_samd.c \ mphalport.c \ reset.c \ + shared/runtime/gchelper_native.c \ timer_handler.c \ $(SRC_PERIPHERALS) \ @@ -308,20 +309,11 @@ ifeq ($(CIRCUITPY_AUDIOBUSIO),1) SRC_C += peripherals/samd/i2s.c peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/i2s.c endif -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-module/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) - -SRC_S = supervisor/$(CHIP_FAMILY)_cpu.s +ifeq ($(CHIP_FAMILY), samd21) +SRC_S += shared/runtime/gchelper_thumb1.s +else +SRC_S += shared/runtime/gchelper_thumb2.s +endif OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_ASF:.c=.o)) @@ -343,7 +335,7 @@ OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/candata.h $(HEADER_BUILD)/candata.h: tools/mkcandata.py | $(HEADER_BUILD) $(Q)$(PYTHON) $< > $@ -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c diff --git a/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h index 5979d1ee9979f..157db0d3f7fbd 100644 --- a/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/samd21/hpl_sercom_config.h @@ -431,7 +431,7 @@ // <0x2=>8x arithmetic // <0x3=>8x fractional // <0x3=>3x -// How many over-sampling bits used when samling data state +// How many over-sampling bits used when sampling data state // usart_arch_sampr #ifndef CONF_SERCOM_2_USART_SAMPR #define CONF_SERCOM_2_USART_SAMPR 0x0 diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h index e05560e635823..6dd21277b78d0 100644 --- a/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/samd51/hpl_sercom_config.h @@ -431,7 +431,7 @@ // <0x2=>8x arithmetic // <0x3=>8x fractional // <0x3=>3x -// How many over-sampling bits used when samling data state +// How many over-sampling bits used when sampling data state // usart_arch_sampr #ifndef CONF_SERCOM_2_USART_SAMPR #define CONF_SERCOM_2_USART_SAMPR 0x0 diff --git a/ports/atmel-samd/asf4_conf/same51/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/same51/hpl_sercom_config.h index e05560e635823..6dd21277b78d0 100644 --- a/ports/atmel-samd/asf4_conf/same51/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/same51/hpl_sercom_config.h @@ -431,7 +431,7 @@ // <0x2=>8x arithmetic // <0x3=>8x fractional // <0x3=>3x -// How many over-sampling bits used when samling data state +// How many over-sampling bits used when sampling data state // usart_arch_sampr #ifndef CONF_SERCOM_2_USART_SAMPR #define CONF_SERCOM_2_USART_SAMPR 0x0 diff --git a/ports/atmel-samd/asf4_conf/same54/hpl_sercom_config.h b/ports/atmel-samd/asf4_conf/same54/hpl_sercom_config.h index e05560e635823..6dd21277b78d0 100644 --- a/ports/atmel-samd/asf4_conf/same54/hpl_sercom_config.h +++ b/ports/atmel-samd/asf4_conf/same54/hpl_sercom_config.h @@ -431,7 +431,7 @@ // <0x2=>8x arithmetic // <0x3=>8x fractional // <0x3=>3x -// How many over-sampling bits used when samling data state +// How many over-sampling bits used when sampling data state // usart_arch_sampr #ifndef CONF_SERCOM_2_USART_SAMPR #define CONF_SERCOM_2_USART_SAMPR 0x0 diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c index 39c9dde648e13..e39804015063b 100644 --- a/ports/atmel-samd/audio_dma.c +++ b/ports/atmel-samd/audio_dma.c @@ -30,9 +30,7 @@ static audio_dma_t *audio_dma_state[AUDIO_DMA_CHANNEL_COUNT]; // This cannot be in audio_dma_state because it's volatile. static volatile bool audio_dma_pending[AUDIO_DMA_CHANNEL_COUNT]; -static bool audio_dma_allocated[AUDIO_DMA_CHANNEL_COUNT]; - -uint8_t find_sync_event_channel_raise() { +uint8_t find_sync_event_channel_raise(void) { uint8_t event_channel = find_sync_event_channel(); if (event_channel >= EVSYS_SYNCH_NUM) { mp_raise_RuntimeError(MP_ERROR_TEXT("All sync event channels in use")); @@ -40,33 +38,15 @@ uint8_t find_sync_event_channel_raise() { return event_channel; } -uint8_t dma_allocate_channel(void) { - uint8_t channel; - for (channel = 0; channel < AUDIO_DMA_CHANNEL_COUNT; channel++) { - if (!audio_dma_allocated[channel]) { - audio_dma_allocated[channel] = true; - return channel; - } - } - return channel; // i.e., return failure -} - -void dma_free_channel(uint8_t channel) { - assert(channel < AUDIO_DMA_CHANNEL_COUNT); - assert(audio_dma_allocated[channel]); - audio_dma_disable_channel(channel); - audio_dma_allocated[channel] = false; -} - void audio_dma_disable_channel(uint8_t channel) { - if (channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (channel == NO_DMA_CHANNEL) { return; } dma_disable_channel(channel); } void audio_dma_enable_channel(uint8_t channel) { - if (channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (channel == NO_DMA_CHANNEL) { return; } dma_enable_channel(channel); @@ -191,8 +171,8 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, bool output_signed, uint32_t output_register_address, uint8_t dma_trigger_source) { - uint8_t dma_channel = dma_allocate_channel(); - if (dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + uint8_t dma_channel = dma_allocate_audio_channel(); + if (dma_channel == NO_DMA_CHANNEL) { return AUDIO_DMA_DMA_BUSY; } @@ -220,15 +200,27 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, } - dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], max_buffer_length); + dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + dma->buffer_length[0], // Old size + #endif + max_buffer_length); + dma->buffer_length[0] = max_buffer_length; + if (dma->buffer[0] == NULL) { return AUDIO_DMA_MEMORY_ERROR; } if (!dma->single_buffer) { - dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1], max_buffer_length); + dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1], + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + dma->buffer_length[1], // Old size + #endif + max_buffer_length); + dma->buffer_length[1] = max_buffer_length; + if (dma->buffer[1] == NULL) { return AUDIO_DMA_MEMORY_ERROR; } @@ -251,7 +243,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, } - if (audiosample_bits_per_sample(sample) == 16) { + if (audiosample_get_bits_per_sample(sample) == 16) { dma->beat_size = 2; dma->bytes_per_sample = 2; } else { @@ -262,7 +254,7 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, } } // Transfer both channels at once. - if (!single_channel_output && audiosample_channel_count(sample) == 2) { + if (!single_channel_output && audiosample_get_channel_count(sample) == 2) { dma->beat_size *= 2; } @@ -306,14 +298,14 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t *dma, void audio_dma_stop(audio_dma_t *dma) { uint8_t channel = dma->dma_channel; - if (channel < AUDIO_DMA_CHANNEL_COUNT) { + if (channel != NO_DMA_CHANNEL) { audio_dma_disable_channel(channel); disable_event_channel(dma->event_channel); MP_STATE_PORT(playing_audio)[channel] = NULL; audio_dma_state[channel] = NULL; dma_free_channel(dma->dma_channel); } - dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT; + dma->dma_channel = NO_DMA_CHANNEL; dma->playing_in_progress = false; } @@ -326,7 +318,7 @@ void audio_dma_resume(audio_dma_t *dma) { } bool audio_dma_get_paused(audio_dma_t *dma) { - if (dma->dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (dma->dma_channel == NO_DMA_CHANNEL) { return false; } uint32_t status = dma_transfer_status(dma->dma_channel); @@ -335,22 +327,21 @@ bool audio_dma_get_paused(audio_dma_t *dma) { } void audio_dma_init(audio_dma_t *dma) { - dma->dma_channel = AUDIO_DMA_CHANNEL_COUNT; + dma->dma_channel = NO_DMA_CHANNEL; } void audio_dma_reset(void) { for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) { audio_dma_state[i] = NULL; audio_dma_pending[i] = false; - audio_dma_allocated[i] = false; - audio_dma_disable_channel(i); + dma_free_channel(i); dma_descriptor(i)->BTCTRL.bit.VALID = false; MP_STATE_PORT(playing_audio)[i] = NULL; } } bool audio_dma_get_playing(audio_dma_t *dma) { - if (dma->dma_channel >= AUDIO_DMA_CHANNEL_COUNT) { + if (dma->dma_channel == NO_DMA_CHANNEL) { return false; } return dma->playing_in_progress; diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h index 284e2cbfd4f2b..7b42a7b6114dd 100644 --- a/ports/atmel-samd/audio_dma.h +++ b/ports/atmel-samd/audio_dma.h @@ -10,6 +10,7 @@ #include "py/obj.h" #include "shared-module/audiocore/RawSample.h" #include "shared-module/audiocore/WaveFile.h" +#include "shared-module/audiocore/__init__.h" #include "supervisor/background_callback.h" typedef struct { @@ -40,16 +41,9 @@ typedef enum { AUDIO_DMA_MEMORY_ERROR, } audio_dma_result; -uint32_t audiosample_sample_rate(mp_obj_t sample_obj); -uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); -uint8_t audiosample_channel_count(mp_obj_t sample_obj); - void audio_dma_init(audio_dma_t *dma); void audio_dma_reset(void); -uint8_t dma_allocate_channel(void); -void dma_free_channel(uint8_t channel); - // This sets everything up but doesn't start the timer. // Sample is the python object for the sample to play. // loop is true if we should loop the sample. diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c index 1564d65fc8c40..9610c6e8c3a39 100644 --- a/ports/atmel-samd/bindings/samd/Clock.c +++ b/ports/atmel-samd/bindings/samd/Clock.c @@ -74,6 +74,7 @@ MP_PROPERTY_GETTER(samd_clock_frequency_obj, //| calibration: int //| """Clock calibration. Not all clocks can be calibrated.""" //| +//| static mp_obj_t samd_clock_get_calibration(mp_obj_t self_in) { samd_clock_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int_from_uint(clock_get_calibration(self->type, self->index)); diff --git a/ports/atmel-samd/bindings/samd/__init__.c b/ports/atmel-samd/bindings/samd/__init__.c index 9f3ad1c3dd0ac..114a1e7b74c45 100644 --- a/ports/atmel-samd/bindings/samd/__init__.c +++ b/ports/atmel-samd/bindings/samd/__init__.c @@ -11,6 +11,7 @@ #include "bindings/samd/Clock.h" //| """SAMD implementation settings""" +//| //| """:mod:`samd.clock` --- samd clock names //| -------------------------------------------------------- diff --git a/ports/atmel-samd/boards/adafruit_trrs_trinkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/adafruit_trrs_trinkey_m0/mpconfigboard.h index 8e53129679f2a..7b206ddaf548a 100644 --- a/ports/atmel-samd/boards/adafruit_trrs_trinkey_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/adafruit_trrs_trinkey_m0/mpconfigboard.h @@ -40,3 +40,6 @@ // no PA29 #define IGNORE_PIN_PA30 1 #define IGNORE_PIN_PA31 1 + +// A couple Learn examples do `array.array('d', ...)` so enable it. +#define MICROPY_PY_DOUBLE_TYPECODE 1 diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/board.c b/ports/atmel-samd/boards/bdmicro_vina_d21/board.c deleted file mode 100644 index 019e4615653c3..0000000000000 --- a/ports/atmel-samd/boards/bdmicro_vina_d21/board.c +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#include "supervisor/board.h" -#include "mpconfigboard.h" - -void board_init(void) { - // struct port_config pin_conf; - // port_get_config_defaults(&pin_conf); - // - // pin_conf.direction = PORT_PIN_DIR_OUTPUT; - // port_pin_set_config(MICROPY_HW_LED_TX, &pin_conf); - // port_pin_set_output_level(MICROPY_HW_LED_TX, true); - // - // port_pin_set_config(MICROPY_HW_LED_RX, &pin_conf); - // port_pin_set_output_level(MICROPY_HW_LED_RX, true); -} - -// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.h b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.h deleted file mode 100644 index ddee00daff73c..0000000000000 --- a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.h +++ /dev/null @@ -1,35 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#define MICROPY_HW_BOARD_NAME "BDMICRO VINA-D21" -#define MICROPY_HW_MCU_NAME "samd21g18" - -#define SPI_FLASH_CS_PIN &pin_PA13 -#define SPI_FLASH_MISO_PIN &pin_PB03 -#define SPI_FLASH_MOSI_PIN &pin_PB22 -#define SPI_FLASH_SCK_PIN &pin_PB23 - -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define BOARD_HAS_CRYSTAL 1 - -#define DEFAULT_UART_BUS_TX (&pin_PA10) -#define DEFAULT_UART_BUS_RX (&pin_PA11) -#define DEFAULT_SPI_BUS_MISO (&pin_PA12) -#define DEFAULT_I2C_BUS_SDA (&pin_PA22) -#define DEFAULT_I2C_BUS_SCL (&pin_PA23) -#define MICROPY_HW_LED_TX (&pin_PA27) -#define MICROPY_HW_LED_STATUS (&pin_PA28) -#define MICROPY_HW_LED_RX (&pin_PA31) -#define DEFAULT_SPI_BUS_MOSI (&pin_PB10) -#define DEFAULT_SPI_BUS_SCK (&pin_PB11) - -// USB is always used internally so skip the pin objects for it. -#define IGNORE_PIN_PA24 1 -#define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk b/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk deleted file mode 100644 index 1a8cddfda7dc6..0000000000000 --- a/ports/atmel-samd/boards/bdmicro_vina_d21/mpconfigboard.mk +++ /dev/null @@ -1,11 +0,0 @@ -USB_VID = 0x31e2 -USB_PID = 0x2001 -USB_PRODUCT = "VINA-D21" -USB_MANUFACTURER = "BDMICRO LLC" - -CHIP_VARIANT = SAMD21G18A -CHIP_FAMILY = samd21 - -SPI_FLASH_FILESYSTEM = 1 -EXTERNAL_FLASH_DEVICES = "MX25L51245G","GD25S512MD" -LONGINT_IMPL = MPZ diff --git a/ports/atmel-samd/boards/bdmicro_vina_d21/pins.c b/ports/atmel-samd/boards/bdmicro_vina_d21/pins.c deleted file mode 100644 index d80b6df00df96..0000000000000 --- a/ports/atmel-samd/boards/bdmicro_vina_d21/pins.c +++ /dev/null @@ -1,46 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#include "shared-bindings/board/__init__.h" - -static const mp_rom_map_elem_t board_module_globals_table[] = { - CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - - { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, - { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, - { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, - { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) }, - { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) }, - { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, - { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) }, - { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) }, - { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) }, - { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) }, - { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, - { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, - { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, - { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, - { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA14) }, - { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA09) }, - { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) }, - { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) }, - { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) }, - { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) }, - { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, - { MP_ROM_QSTR(MP_QSTR_LED_STATUS), MP_ROM_PTR(&pin_PA28) }, - { MP_ROM_QSTR(MP_QSTR_LED_TX), MP_ROM_PTR(&pin_PA27) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) }, - { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) }, - { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) }, - { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) }, - { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) }, - { MP_ROM_QSTR(MP_QSTR_LED_RX), MP_ROM_PTR(&pin_PA31) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, -}; -MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/board.c b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/board.c new file mode 100644 index 0000000000000..b44a1ae51e04b --- /dev/null +++ b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.h b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.h new file mode 100644 index 0000000000000..cdd5c96aeba26 --- /dev/null +++ b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bradán Lane STUDIO +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Bradán Lane STUDIO Coin M0" +#define MICROPY_HW_MCU_NAME "samd21g18" + +#define MICROPY_HW_LED_STATUS (&pin_PA17) + +#define SPI_FLASH_MOSI_PIN &pin_PB22 +#define SPI_FLASH_MISO_PIN &pin_PB03 +#define SPI_FLASH_SCK_PIN &pin_PB23 +#define SPI_FLASH_CS_PIN &pin_PA27 + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 // USB_D+ +#define IGNORE_PIN_PA25 1 // USB_D- + +#define IGNORE_PIN_PA30 1 // SWCLK +#define IGNORE_PIN_PA31 1 // SWDIO diff --git a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk new file mode 100644 index 0000000000000..9a2cdcd668ed2 --- /dev/null +++ b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/mpconfigboard.mk @@ -0,0 +1,46 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2024 Bradán Lane STUDIO +# +# SPDX-License-Identifier: MIT + +# TODO new VID:PID not yet approved via pidcodes.github.com +USB_VID = 0x1209 +USB_PID = 0x5687 + +USB_PRODUCT = "Coin M0" +USB_MANUFACTURER = "Bradán Lane STUDIO" + +CHIP_VARIANT = SAMD21G18A +CHIP_FAMILY = samd21 + +#CIRCUITPY_BUILD_EXTENSIONS = bin,uf2 + +SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" +LONGINT_IMPL = MPZ + +# the M0 Coin has limited functionality and many modules can be eliminated + +# there may be more modules which are of no used but will require further digging + +# Disable modules that are unusable on this special-purpose board. + +CIRCUITPY_FULL_BUILD = 1 + +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_ONEWIREIO = 0 +CIRCUITPY_PULSEIO = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_RTC = 0 +CIRCUITPY_USB_HID = 1 +CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_NEOPIXEL_WRITE = 1 +CIRCUITPY_PIXELBUF = 1 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/atmel-samd/boards/bradanlanestudio_coin_m0/pins.c b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/pins.c new file mode 100644 index 0000000000000..7e74918ee465a --- /dev/null +++ b/ports/atmel-samd/boards/bradanlanestudio_coin_m0/pins.c @@ -0,0 +1,35 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Neopixels + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA07) }, + + // discrete LEDs + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) }, + + // on-board LED + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) }, // Analog only; no PWM + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH2), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH1), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH3), MP_ROM_PTR(&pin_PB02) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk index c647039bc8aaf..121becc472d36 100755 --- a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk @@ -10,4 +10,6 @@ SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ -CIRCUITPY_JPEGIO = 0 +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk index b470a2860e6a5..5c1cab422cb69 100755 --- a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk @@ -10,6 +10,9 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ, S25FL064L" LONGINT_IMPL = MPZ +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_PS2IO = 1 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_SPITARGET = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 diff --git a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk index 95123ae5b85da..2ad140094b310 100644 --- a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk @@ -9,5 +9,9 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q16JVxQ, W25Q16JVxM" LONGINT_IMPL = MPZ -CIRCUITPY_SYNTHIO = 0 + +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_SPITARGET = 0 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index c3b8f643139bd..1152fb4acc419 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -9,3 +9,7 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index 79285f8b3df3b..8fdf20f186b00 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -20,6 +20,8 @@ #define SPI_FLASH_SCK_PIN &pin_PA09 #define SPI_FLASH_CS_PIN &pin_PA13 +#define BOARD_HAS_CRYSTAL 1 + #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) @@ -30,6 +32,24 @@ #define DEFAULT_UART_BUS_RX (&pin_PA11) #define DEFAULT_UART_BUS_TX (&pin_PA10) +// Other some pins that do not appear in the pinout & are not used internally +// this list is not (yet) exhaustive +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB12 1 + // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 + +// USBHOSTEN on the schematic but not connected. +#define IGNORE_PIN_PA28 1 + +// SWD pins +#define IGNORE_PIN_PA30 1 +#define IGNORE_PIN_PA31 1 diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 811336885b86d..dd58e8d1ce5a7 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -9,3 +9,7 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL064L" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk index 57c1ac918f963..ee414b6e214b0 100644 --- a/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_can/mpconfigboard.mk @@ -13,9 +13,12 @@ LONGINT_IMPL = MPZ CIRCUITPY__EVE = 1 CIRCUITPY_BITMAPFILTER = 0 CIRCUITPY_CANIO = 1 -CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_GIFIO = 0 +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_PS2IO = 0 +CIRCUITPY_SYNTHIO = 0 CIRCUITPY_LTO_PARTITION = one diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h index 9bba71b56aff3..ff6256eea6dae 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -28,6 +28,21 @@ #define DEFAULT_UART_BUS_RX (&pin_PB17) #define DEFAULT_UART_BUS_TX (&pin_PB16) +// Used for 32 kHZ crystal +#define IGNORE_PIN_PA00 1 +#define IGNORE_PIN_PA01 1 + // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 + +// Not connected +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PA27 1 +#define IGNORE_PIN_PB00 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index 377e4f4f0f825..f780ea4aa3d0f 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -11,9 +11,12 @@ EXTERNAL_FLASH_DEVICES = "GD25Q16C,W25Q16JVxQ" LONGINT_IMPL = MPZ CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_SYNTHIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 # We don't have room for the fonts for terminalio for certain languages, # so turn off terminalio, and if it's off and displayio is on, diff --git a/ports/atmel-samd/boards/hallowing_m0_express/board.c b/ports/atmel-samd/boards/hallowing_m0_express/board.c index 637129a0e9d5e..fd5ad5485120f 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/board.c +++ b/ports/atmel-samd/boards/hallowing_m0_express/board.c @@ -54,9 +54,9 @@ void board_init(void) { common_hal_busio_spi_never_reset(spi); common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PA28, // Command or data - &pin_PA01, // Chip select - &pin_PA27, // Reset + MP_OBJ_FROM_PTR(&pin_PA28), // Command or data + MP_OBJ_FROM_PTR(&pin_PA01), // Chip select + MP_OBJ_FROM_PTR(&pin_PA27), // Reset 12000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/hallowing_m4_express/board.c b/ports/atmel-samd/boards/hallowing_m4_express/board.c index bfef5fbcd75dd..c7217b70b0a97 100644 --- a/ports/atmel-samd/boards/hallowing_m4_express/board.c +++ b/ports/atmel-samd/boards/hallowing_m4_express/board.c @@ -35,9 +35,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PB31, // TFT_DC Command or data - &pin_PA27, // TFT_CS Chip select - &pin_PB30, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PB31), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PA27), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PB30), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk index 3838baa53e8a2..76c60b4464639 100644 --- a/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m4_express/mpconfigboard.mk @@ -9,5 +9,15 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" LONGINT_IMPL = MPZ -CIRCUITPY_JPEGIO = 0 -CIRCUITPY_SYNTHIO = 0 + +CIRCUITPY_AESIO = 0 +CIRCUITPY_CODEOP = 0 +CIRCUITPY_EPAPERDISPLAY = 0 +CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_I2CDISPLAYBUS = 0 +CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_SHARPDISPLAY = 0 +CIRCUITPY_SPITARGET = 0 diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index 4c11a905baa50..be22cb94fae92 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -10,8 +10,22 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "GD25Q16C,W25Q16JVxQ" LONGINT_IMPL = MPZ +CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_GIFIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 CIRCUITPY_BITBANG_APA102 = 1 + +# We don't have room for the fonts for terminalio for certain languages, +# so turn off terminalio, and if it's off and displayio is on, +# force a clean build. +# Note that we cannot test $(CIRCUITPY_DISPLAYIO) directly with an +# ifeq, because it's not set yet. +ifneq (,$(filter $(TRANSLATION),ja ko ru)) +CIRCUITPY_TERMINALIO = 0 +RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO) +endif diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk index 9ca9259747726..ebe9403c34d75 100644 --- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk @@ -9,7 +9,7 @@ CHIP_FAMILY = samd51 INTERNAL_FLASH_FILESYSTEM = 1 LONGINT_IMPL = MPZ -# Not needed. +# Turn off to make fit. CIRCUITPY_AESIO = 0 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOCORE = 0 @@ -24,6 +24,7 @@ CIRCUITPY_PIXELMAP = 0 CIRCUITPY_GETPASS = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_MSGPACK = 0 +CIRCUITPY_PIXELBUF = 0 CIRCUITPY_PS2IO = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_RAINBOWIO = 0 @@ -31,6 +32,7 @@ CIRCUITPY_ROTARYIO = 0 CIRCUITPY_TOUCHIO = 0 CIRCUITPY_USB_HID = 0 CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_WARNINGS = 0 CIRCUITPY_ULAB = 0 diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index fc9230cb64350..d4801359cf8c5 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -9,3 +9,7 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk index 9022817f3e33d..cb7e690c6c02d 100644 --- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk @@ -10,10 +10,14 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ -CIRCUITPY__EVE = 1 +CIRCUITPY__EVE = 0 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 + # We don't have room for the fonts for terminalio for certain languages, # so turn off terminalio, and if it's off and displayio is on, diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index ebc8cae33f1c6..b7ca7986ded89 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -32,6 +32,21 @@ #define DEFAULT_UART_BUS_RX (&pin_PA23) #define DEFAULT_UART_BUS_TX (&pin_PA22) +// Used for 32 kHz crystal +#define IGNORE_PIN_PA00 1 +#define IGNORE_PIN_PA01 1 + // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 + +// Not connected +#define IGNORE_PIN_PA07 1 +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PB00 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index 4f01c141e4849..d5aef01a0374f 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -11,9 +11,12 @@ EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C, W25Q16JVxQ" LONGINT_IMPL = MPZ CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 # We don't have room for the fonts for terminalio for certain languages, # so turn off terminalio, and if it's off and displayio is on, diff --git a/ports/atmel-samd/boards/microchip_curiosity_circuitpython/board.c b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/board.c new file mode 100644 index 0000000000000..b44a1ae51e04b --- /dev/null +++ b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.h b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.h new file mode 100644 index 0000000000000..4416d8517d279 --- /dev/null +++ b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.h @@ -0,0 +1,33 @@ + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Microchip Curiosity CircuitPython" +#define MICROPY_HW_MCU_NAME "same51j20" +#define CIRCUITPY_MCU_FAMILY samd51 + +#define MICROPY_HW_LED_STATUS (&pin_PB23) +#define MICROPY_HW_NEOPIXEL (&pin_PB22) + +#define BOARD_HAS_CRYSTAL 1 + +// USB is always used internally so skip the pin objects for it. +#define IGNORE_PIN_PA24 1 +#define IGNORE_PIN_PA25 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_PB30) +#define DEFAULT_I2C_BUS_SDA (&pin_PB31) + +#define CIRCUITPY_BOARD_SPI (3) +// These correspond to the CIRCUITPY_BOARD_BUS_SINGLETON definitions in pins.c +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_PB03, .mosi = &pin_PB02, .miso = &pin_PB00}, /*board.SPI()*/ \ + {.clock = &pin_PA05, .mosi = &pin_PA04, .miso = NULL}, /*board.LCD_SPI()*/ \ + {.clock = &pin_PA17, .mosi = &pin_PA16, .miso = &pin_PA18}, /*board.SD_SPI()*/ \ +} + +#define DEFAULT_CAN_BUS_TX (&pin_PB12) +#define DEFAULT_CAN_BUS_RX (&pin_PB13) +#define DEFAULT_CAN_BUS_STDBY (&pin_PB17) + +#define DEFAULT_UART_BUS_RX (&pin_PA23) +#define DEFAULT_UART_BUS_TX (&pin_PA22) diff --git a/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.mk b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.mk new file mode 100644 index 0000000000000..985eb4c6a4465 --- /dev/null +++ b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x04D8 +USB_PID = 0xE52B +USB_PRODUCT = "Microchip Curiosity CircuitPython" +USB_MANUFACTURER = "Microchip Technology Inc" + +CHIP_VARIANT = SAME51J20A +CHIP_FAMILY = same51 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICES = "SST26VF016B,SST26VF032B,SST26VF064B" +LONGINT_IMPL = MPZ + +CIRCUITPY__EVE = 1 +CIRCUITPY_CANIO = 1 diff --git a/ports/atmel-samd/boards/microchip_curiosity_circuitpython/pins.c b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/pins.c new file mode 100644 index 0000000000000..49c7f7565e26e --- /dev/null +++ b/ports/atmel-samd/boards/microchip_curiosity_circuitpython/pins.c @@ -0,0 +1,91 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +// The singleton for board.SPI() is already defined. +// board.LCD_SPI() +CIRCUITPY_BOARD_BUS_SINGLETON(lcd_spi, spi, 1) +// board.SD_SPI() +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 2) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA20) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA21) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA27) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PB14) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PB15) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PB16) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PB23) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB23) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PB22) }, + + { MP_ROM_QSTR(MP_QSTR_VREF), MP_ROM_PTR(&pin_PA03) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PB04) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB05) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB06) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB07) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB09) }, + + { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pin_PA02) }, + + { MP_ROM_QSTR(MP_QSTR_CAP1), MP_ROM_PTR(&pin_PB09) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_PA06) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB30) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB31) }, + + { MP_ROM_QSTR(MP_QSTR_BLE_TX), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_BLE_RX), MP_ROM_PTR(&pin_PA13) }, + { MP_ROM_QSTR(MP_QSTR_BLE_CLR), MP_ROM_PTR(&pin_PA14) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_PA16) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_PA18) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_PA17) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PA19) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB00) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PB00) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT), MP_ROM_PTR(&pin_PB00) }, + + { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_IMU_ADDR), MP_ROM_PTR(&pin_PB01) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PB02) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PB03) }, + + { MP_ROM_QSTR(MP_QSTR_DEBUG_TX), MP_ROM_PTR(&pin_PA22) }, + { MP_ROM_QSTR(MP_QSTR_DEBUG_RX), MP_ROM_PTR(&pin_PA23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_CAN_RX), MP_ROM_PTR(&pin_PB13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_CAN_TX), MP_ROM_PTR(&pin_PB12) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_CAN_STDBY), MP_ROM_PTR(&pin_PB17) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PB17) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_lcd_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk index 73c56fb5fbab3..8fae53c0101f9 100644 --- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk @@ -10,9 +10,13 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q16JVxM, W25Q16JVxQ" LONGINT_IMPL = MPZ +CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 CIRCUITPY_BITBANG_APA102 = 1 diff --git a/ports/atmel-samd/boards/monster_m4sk/board.c b/ports/atmel-samd/boards/monster_m4sk/board.c index 1d4fd69b7f708..1c143ad92701f 100644 --- a/ports/atmel-samd/boards/monster_m4sk/board.c +++ b/ports/atmel-samd/boards/monster_m4sk/board.c @@ -35,9 +35,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PA07, // TFT_DC Command or data - &pin_PA06, // TFT_CS Chip select - &pin_PA04, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PA07), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PA06), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA04), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/openbook_m4/board.c b/ports/atmel-samd/boards/openbook_m4/board.c index 032ebe9f628a7..ebabfb84e9bfa 100644 --- a/ports/atmel-samd/boards/openbook_m4/board.c +++ b/ports/atmel-samd/boards/openbook_m4/board.c @@ -44,49 +44,33 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PB05, // EPD_DC Command or data - &pin_PB07, // EPD_CS Chip select - &pin_PA00, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_PB05), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_PB07), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA00), // EPD_RST Reset 1000000, // Baudrate 0, // Polarity 0); // Phase epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct(display, - bus, - start_sequence, - sizeof(start_sequence), - 0, // start up time - stop_sequence, - sizeof(stop_sequence), - 300, // width - 400, // height - 300, // RAM width - 400, // RAM height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x13, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command (can add this for grayscale eventually) - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, // refresh_display_sequence - sizeof(refresh_sequence), - 40, // refresh_time - &pin_PA01, // busy_pin - false, // busy_state - 5, // seconds_per_frame - false, // chip_select (don't always toggle chip select) - false, // grayscale - false, // acep - false, // two_byte_sequence_length - false); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = start_sequence; + args.start_sequence_len = sizeof(start_sequence); + args.stop_sequence = stop_sequence; + args.stop_sequence_len = sizeof(stop_sequence); + args.width = 300; + args.height = 400; + args.ram_width = 300; + args.ram_height = 400; + args.rotation = 270; + args.write_black_ram_command = 0x13; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 40.0; + args.busy_pin = &pin_PA01; + args.seconds_per_frame = 5.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk index c6eaa6bd64d54..2701fd249f955 100644 --- a/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk +++ b/ports/atmel-samd/boards/openbook_m4/mpconfigboard.mk @@ -10,6 +10,10 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ +CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_JPEGIO = 0 CIRCUITPY_KEYPAD = 1 CIRCUITPY_SYNTHIO = 0 -CIRCUITPY_JPEGIO = 0 +CIRCUITPY_TERMINALIO_VT100 = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 diff --git a/ports/atmel-samd/boards/pewpew_lcd/board.c b/ports/atmel-samd/boards/pewpew_lcd/board.c index 6a10132e11dc2..d60efd39bf752 100644 --- a/ports/atmel-samd/boards/pewpew_lcd/board.c +++ b/ports/atmel-samd/boards/pewpew_lcd/board.c @@ -54,9 +54,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PA19, // TFT_DC Command or data - &pin_PA17, // TFT_CS Chip select - &pin_PA18, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PA19), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PA17), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA18), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/pewpew_lcd/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_lcd/mpconfigboard.mk index 823f5698156cd..58047f2506e9a 100644 --- a/ports/atmel-samd/boards/pewpew_lcd/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pewpew_lcd/mpconfigboard.mk @@ -41,7 +41,8 @@ CIRCUITPY_BITBANG_APA102 = 0 CIRCUITPY_BITBANGIO = 0 CIRCUITPY_BITMAPFILTER = 0 CIRCUITPY_BITMAPTOOLS = 0 -CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 CIRCUITPY_BUSDEVICE = 0 CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FREQUENCYIO = 0 @@ -54,6 +55,7 @@ CIRCUITPY_PULSEIO = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_ROTARYIO = 0 CIRCUITPY_RTC = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 CIRCUITPY_ULAB = 0 CIRCUITPY_USB_HID = 0 CIRCUITPY_USB_MIDI = 0 diff --git a/ports/atmel-samd/boards/pewpew_m4/board.c b/ports/atmel-samd/boards/pewpew_m4/board.c index 2007d755c694a..ac67b82a3dc7a 100644 --- a/ports/atmel-samd/boards/pewpew_m4/board.c +++ b/ports/atmel-samd/boards/pewpew_m4/board.c @@ -83,9 +83,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PA16, // TFT_DC Command or data - &pin_PA11, // TFT_CS Chip select - &pin_PA17, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PA16), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PA11), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA17), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/pybadge/board.c b/ports/atmel-samd/boards/pybadge/board.c index 545918374e270..e938e96e19e3c 100644 --- a/ports/atmel-samd/boards/pybadge/board.c +++ b/ports/atmel-samd/boards/pybadge/board.c @@ -56,9 +56,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PB05, // TFT_DC Command or data - &pin_PB07, // TFT_CS Chip select - &pin_PA00, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PB05), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PB07), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA00), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk index 8005146114a47..70571b6c77dbd 100644 --- a/ports/atmel-samd/boards/pybadge/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pybadge/mpconfigboard.mk @@ -18,6 +18,17 @@ CIRCUITPY_I2CDISPLAYBUS = 0 CIRCUITPY_JPEGIO = 0 CIRCUITPY_KEYPAD = 1 CIRCUITPY_PARALLELDISPLAYBUS= 0 +CIRCUITPY_SPITARGET = 0 CIRCUITPY_STAGE = 1 FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pybadge + +# We don't have room for the fonts for terminalio for certain languages, +# so turn off terminalio, and if it's off and displayio is on, +# force a clean build. +# Note that we cannot test $(CIRCUITPY_DISPLAYIO) directly with an +# ifeq, because it's not set yet. +ifneq (,$(filter $(TRANSLATION),ja ko ru)) +CIRCUITPY_TERMINALIO = 0 +RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO) +endif diff --git a/ports/atmel-samd/boards/pycubed/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed/mpconfigboard.mk index 347462919f8c1..08d867c6e1cce 100644 --- a/ports/atmel-samd/boards/pycubed/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pycubed/mpconfigboard.mk @@ -27,8 +27,8 @@ CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_PS2IO = 0 -CIRCUITPY_BLEIO_HCI=0 -CIRCUITPY_BLEIO=0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk index ac8af21dcb6ee..52129f0b187ed 100644 --- a/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pycubed_mram/mpconfigboard.mk @@ -27,8 +27,8 @@ CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_PS2IO = 0 -CIRCUITPY_BLEIO_HCI=0 -CIRCUITPY_BLEIO=0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/atmel-samd/boards/pycubed_mram_v05/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed_mram_v05/mpconfigboard.mk index ac8af21dcb6ee..52129f0b187ed 100644 --- a/ports/atmel-samd/boards/pycubed_mram_v05/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pycubed_mram_v05/mpconfigboard.mk @@ -27,8 +27,8 @@ CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_PS2IO = 0 -CIRCUITPY_BLEIO_HCI=0 -CIRCUITPY_BLEIO=0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/atmel-samd/boards/pycubed_v05/mpconfigboard.mk b/ports/atmel-samd/boards/pycubed_v05/mpconfigboard.mk index 923ab2eaaef13..43d3b9f1f8386 100644 --- a/ports/atmel-samd/boards/pycubed_v05/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pycubed_v05/mpconfigboard.mk @@ -28,8 +28,8 @@ CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_PS2IO = 0 -CIRCUITPY_BLEIO_HCI=0 -CIRCUITPY_BLEIO=0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/atmel-samd/boards/pygamer/board.c b/ports/atmel-samd/boards/pygamer/board.c index 53275ac686a15..fcf6aff0e6556 100644 --- a/ports/atmel-samd/boards/pygamer/board.c +++ b/ports/atmel-samd/boards/pygamer/board.c @@ -57,9 +57,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PB05, // TFT_DC Command or data - &pin_PB12, // TFT_CS Chip select - &pin_PA00, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PB05), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PB12), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PA00), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk index 5149dda508fb4..0c6f16f8b6381 100644 --- a/ports/atmel-samd/boards/pygamer/mpconfigboard.mk +++ b/ports/atmel-samd/boards/pygamer/mpconfigboard.mk @@ -12,12 +12,24 @@ LONGINT_IMPL = MPZ CIRCUITPY_AESIO = 0 CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_EPAPERDISPLAY = 0 CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_GIFIO = 0 CIRCUITPY_I2CDISPLAYBUS = 0 CIRCUITPY_JPEGIO = 0 CIRCUITPY_KEYPAD = 1 CIRCUITPY_PARALLELDISPLAYBUS= 0 +CIRCUITPY_SPITARGET = 0 CIRCUITPY_STAGE = 1 FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pygamer + +# We don't have room for the fonts for terminalio for certain languages, +# so turn off terminalio, and if it's off and displayio is on, +# force a clean build. +# Note that we cannot test $(CIRCUITPY_DISPLAYIO) directly with an +# ifeq, because it's not set yet. +ifneq (,$(filter $(TRANSLATION),ja ko ru)) +CIRCUITPY_TERMINALIO = 0 +RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO) +endif diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c b/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c index d3d1ae3a956ff..1ee80c9878604 100644 --- a/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c +++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c @@ -52,9 +52,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PC06, // TFT_DC Command or data - &pin_PB21, // TFT_CS Chip select - &pin_PC07, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_PC06), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_PB21), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_PC07), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk index dd8afd51f6e60..4ade6a148315d 100644 --- a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk +++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk @@ -9,6 +9,14 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY__EVE = 1 +CIRCUITPY_CODEOP = 0 CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_JPEGIO = 0 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_SHARPDISPLAY = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_VECTORIO = 0 diff --git a/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk b/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk index 7c576a0376bdf..99c447b7a9df8 100644 --- a/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk +++ b/ports/atmel-samd/boards/silicognition-m4-shim/mpconfigboard.mk @@ -10,5 +10,8 @@ QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ +CIRCUITPY_I2CTARGET = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_SPITARGET = 0 CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 diff --git a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk index d19e606319b63..441853c554df9 100644 --- a/ports/atmel-samd/boards/snekboard/mpconfigboard.mk +++ b/ports/atmel-samd/boards/snekboard/mpconfigboard.mk @@ -9,3 +9,6 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.h b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.h index 3078c5794a47f..3fd421886911b 100644 --- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.h +++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.h @@ -38,6 +38,10 @@ #define DEFAULT_UART_BUS_RX (&pin_PA11) #define DEFAULT_UART_BUS_TX (&pin_PA10) +// These pins are connected to the external crystal. +#define IGNORE_PIN_PA00 1 +#define IGNORE_PIN_PA01 1 + // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 diff --git a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk index ef23e56022435..b34dfb3d2e624 100755 --- a/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk +++ b/ports/atmel-samd/boards/sparkfun_redboard_turbo/mpconfigboard.mk @@ -10,4 +10,6 @@ SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32FV" LONGINT_IMPL = MPZ +CIRCUITPY_CODEOP = 0 +CIRCUITPY_ERRNO = 0 CIRCUITPY_RAINBOWIO = 0 diff --git a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk index 1088ca1e8db76..d6071f4b66e10 100644 --- a/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk +++ b/ports/atmel-samd/boards/stackrduino_m0_pro/mpconfigboard.mk @@ -9,3 +9,6 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk index a93e1575b46d4..e29236ebc9162 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk @@ -12,5 +12,6 @@ LONGINT_IMPL = MPZ CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BITBANG_APA102 = 1 diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index bc157d6c86bb3..7eec1d64f8ef4 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -31,6 +31,43 @@ #define DEFAULT_UART_BUS_RX (&pin_PA07) #define DEFAULT_UART_BUS_TX (&pin_PA06) +#define IGNORE_PIN_PA03 1 +#define IGNORE_PIN_PA04 1 +#define IGNORE_PIN_PA12 1 +#define IGNORE_PIN_PA13 1 +#define IGNORE_PIN_PA14 1 +#define IGNORE_PIN_PA15 1 +#define IGNORE_PIN_PA18 1 +#define IGNORE_PIN_PA20 1 +#define IGNORE_PIN_PA21 1 +#define IGNORE_PIN_PA22 1 +#define IGNORE_PIN_PA23 1 // USB is always used internally so skip the pin objects for it. #define IGNORE_PIN_PA24 1 #define IGNORE_PIN_PA25 1 +#define IGNORE_PIN_PA27 1 +#define IGNORE_PIN_PA28 1 +#define IGNORE_PIN_PA30 1 +#define IGNORE_PIN_PA31 1 +#define IGNORE_PIN_PB01 1 +#define IGNORE_PIN_PB02 1 +#define IGNORE_PIN_PB03 1 +#define IGNORE_PIN_PB04 1 +#define IGNORE_PIN_PB05 1 +#define IGNORE_PIN_PB06 1 +#define IGNORE_PIN_PB07 1 +#define IGNORE_PIN_PB08 1 +#define IGNORE_PIN_PB09 1 +#define IGNORE_PIN_PB10 1 +#define IGNORE_PIN_PB11 1 +#define IGNORE_PIN_PB12 1 +#define IGNORE_PIN_PB13 1 +#define IGNORE_PIN_PB14 1 +#define IGNORE_PIN_PB15 1 +#define IGNORE_PIN_PB16 1 +#define IGNORE_PIN_PB17 1 +#define IGNORE_PIN_PB22 1 +#define IGNORE_PIN_PB23 1 +#define IGNORE_PIN_PB30 1 +#define IGNORE_PIN_PB31 1 +#define IGNORE_PIN_PB00 1 diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index 028114091ecb0..29b5865d419dd 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -9,3 +9,5 @@ CHIP_FAMILY = samd21 SPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = W25Q32BV LONGINT_IMPL = MPZ + +CIRCUITPY_CODEOP = 0 diff --git a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk index 1181abd9640dc..3ce42ed3a7e7e 100644 --- a/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk +++ b/ports/atmel-samd/boards/uartlogger2/mpconfigboard.mk @@ -9,5 +9,10 @@ CHIP_FAMILY = samd51 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" LONGINT_IMPL = MPZ + +CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_SPITARGET = 0 CIRCUITPY_SYNTHIO = 0 CIRCUITPY_JPEGIO = 0 +CIRCUITPY_TERMINALIO_VT100 = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 diff --git a/ports/atmel-samd/boards/ugame10/board.c b/ports/atmel-samd/boards/ugame10/board.c index bbf3839c516fb..78d03a3fd9a02 100644 --- a/ports/atmel-samd/boards/ugame10/board.c +++ b/ports/atmel-samd/boards/ugame10/board.c @@ -53,9 +53,9 @@ void board_init(void) { busio_spi_obj_t *spi = common_hal_board_create_spi(0); common_hal_fourwire_fourwire_construct(bus, spi, - &pin_PA09, // Command or data - &pin_PA08, // Chip select - NULL, // Reset + MP_OBJ_FROM_PTR(&pin_PA09), // Command or data + MP_OBJ_FROM_PTR(&pin_PA08), // Chip select + MP_OBJ_NULL, // Reset 24000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk index d23ce47f58fd3..e2f0ab661454a 100644 --- a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk +++ b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk @@ -21,7 +21,8 @@ CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_AUDIOBUSIO = 0 -CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE = 0 CIRCUITPY_DISPLAYIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_I2CTARGET = 0 diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk index 91334a68373ef..eabfd82df3ebb 100644 --- a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk +++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk @@ -15,6 +15,7 @@ EXTERNAL_FLASH_DEVICES = "GD25Q64C, W25Q32JVxQ" LONGINT_IMPL = MPZ # Disable modules that are unusable on this special-purpose board. +CIRCUITPY_AESIO = 0 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOIO = 0 CIRCUITPY_BITMAPFILTER = 0 diff --git a/ports/atmel-samd/common-hal/_pew/PewPew.c b/ports/atmel-samd/common-hal/_pew/PewPew.c index 84ff7bc16c734..c3f9330faaef9 100644 --- a/ports/atmel-samd/common-hal/_pew/PewPew.c +++ b/ports/atmel-samd/common-hal/_pew/PewPew.c @@ -38,7 +38,7 @@ void pewpew_interrupt_handler(uint8_t index) { tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; } -void pew_init() { +void pew_init(void) { pew_obj_t *pew = MP_STATE_VM(pew_singleton); common_hal_digitalio_digitalinout_switch_to_input(pew->buttons, PULL_UP); @@ -105,6 +105,6 @@ void pew_reset(void) { MP_STATE_VM(pew_singleton) = NULL; } -uint16_t pew_get_ticks() { +uint16_t pew_get_ticks(void) { return pewpew_ticks; } diff --git a/ports/atmel-samd/common-hal/alarm/__init__.c b/ports/atmel-samd/common-hal/alarm/__init__.c index 483aa1a9679ad..38ef58bea7659 100644 --- a/ports/atmel-samd/common-hal/alarm/__init__.c +++ b/ports/atmel-samd/common-hal/alarm/__init__.c @@ -133,7 +133,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); // port_disable_tick(); // TODO: Required for SAMD? diff --git a/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c b/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c index 44396fa8e8ab2..de98b7ec85ae6 100644 --- a/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c +++ b/ports/atmel-samd/common-hal/alarm/touch/TouchAlarm.c @@ -7,6 +7,6 @@ #include "shared-bindings/alarm/touch/TouchAlarm.h" #include "shared-bindings/microcontroller/__init__.h" -void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { +MP_NORETURN void common_hal_alarm_touch_touchalarm_construct(alarm_touch_touchalarm_obj_t *self, const mcu_pin_obj_t *pin) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_TouchAlarm); } diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c index c633cf44b678c..801ab18f7fd6d 100644 --- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c +++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c @@ -64,7 +64,7 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) { self->pin = NULL; } -void analogin_reset() { +void analogin_reset(void) { } uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c index b8c8e93e88d8e..178db2f07d040 100644 --- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c +++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c @@ -216,10 +216,10 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, mp_raise_RuntimeError(MP_ERROR_TEXT("Clock unit in use")); } #endif - uint8_t bits_per_sample = audiosample_bits_per_sample(sample); + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); // We always output stereo so output twice as many bits. uint16_t bits_per_sample_output = bits_per_sample * 2; - uint16_t divisor = 48000000 / (bits_per_sample_output * audiosample_sample_rate(sample)); + uint16_t divisor = 48000000 / (bits_per_sample_output * audiosample_get_sample_rate(sample)); // Find a free GCLK to generate the MCLK signal. uint8_t gclk = find_free_gclk(divisor); if (gclk > GCLK_GEN_NUM) { @@ -235,7 +235,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, } else { clkctrl |= I2S_CLKCTRL_FSOUTINV | I2S_CLKCTRL_BITDELAY_I2S; } - uint8_t channel_count = audiosample_channel_count(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); if (channel_count > 2) { mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample")); } @@ -245,7 +245,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, #ifdef SAM_D5X_E5X uint32_t serctrl = (self->clock_unit << I2S_RXCTRL_CLKSEL_Pos) | I2S_TXCTRL_TXSAME_SAME; #endif - if (audiosample_channel_count(sample) == 1) { + if (audiosample_get_channel_count(sample) == 1) { serctrl |= SERCTRL(MONO_MONO); } else { serctrl |= SERCTRL(MONO_STEREO); diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c index 3244d06979efb..f409563f5ed69 100644 --- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c +++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c @@ -364,7 +364,7 @@ static uint16_t filter_sample(uint32_t pdm_samples[4]) { // output_buffer_length is the number of slots, not the number of bytes. uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self, uint16_t *output_buffer, uint32_t output_buffer_length) { - uint8_t dma_channel = dma_allocate_channel(); + uint8_t dma_channel = dma_allocate_audio_channel(); pdmin_event_channel = find_sync_event_channel_raise(); pdmin_dma_block_done = false; diff --git a/ports/atmel-samd/common-hal/audioio/AudioOut.c b/ports/atmel-samd/common-hal/audioio/AudioOut.c index e6c90243fa566..f7af5e292a719 100644 --- a/ports/atmel-samd/common-hal/audioio/AudioOut.c +++ b/ports/atmel-samd/common-hal/audioio/AudioOut.c @@ -79,6 +79,9 @@ static void ramp_value(uint16_t start, uint16_t end) { // Caller validates that pins are free. void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self, const mcu_pin_obj_t *left_channel, const mcu_pin_obj_t *right_channel, uint16_t quiescent_value) { + + // The case of left_channel == right_channel is already disallowed in shared-bindings. + #ifdef SAM_D5X_E5X bool dac_clock_enabled = hri_mclk_get_APBDMASK_DAC_bit(MCLK); #endif @@ -107,10 +110,6 @@ void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self, if (right_channel != NULL && right_channel != &pin_PA02 && right_channel != &pin_PA05) { raise_ValueError_invalid_pin_name(MP_QSTR_right_channel); } - if (right_channel == left_channel) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("%q and %q must be different"), - MP_QSTR_left_channel, MP_QSTR_right_channel); - } claim_pin(left_channel); if (right_channel != NULL) { claim_pin(right_channel); @@ -333,7 +332,7 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self, common_hal_audioio_audioout_stop(self); } audio_dma_result result = AUDIO_DMA_OK; - uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); #ifdef SAMD21 const uint32_t max_sample_rate = 350000; #endif @@ -364,12 +363,12 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self, right_channel_reg = (uint32_t)&DAC->DATABUF[0].reg; } - size_t num_channels = audiosample_channel_count(sample); + size_t num_channels = audiosample_get_channel_count(sample); if (num_channels == 2 && // Are DAC channels sequential? left_channel_reg + 2 == right_channel_reg && - audiosample_bits_per_sample(sample) == 16) { + audiosample_get_bits_per_sample(sample) == 16) { result = audio_dma_setup_playback(&self->left_dma, sample, loop, false, 0, false /* output unsigned */, left_channel_reg, @@ -403,7 +402,7 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self, } } Tc *timer = tc_insts[self->tc_index]; - set_timer_frequency(timer, audiosample_sample_rate(sample)); + set_timer_frequency(timer, audiosample_get_sample_rate(sample)); timer->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_RETRIGGER; while (timer->COUNT16.STATUS.bit.STOP == 1) { } diff --git a/ports/atmel-samd/common-hal/busio/I2C.c b/ports/atmel-samd/common-hal/busio/I2C.c index 033c74c0a1ab0..d9da050dabeae 100644 --- a/ports/atmel-samd/common-hal/busio/I2C.c +++ b/ports/atmel-samd/common-hal/busio/I2C.c @@ -53,7 +53,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, uint32_t sda_pinmux, scl_pinmux; // Ensure the object starts in its deinit state. - self->sda_pin = NO_PIN; + common_hal_busio_i2c_mark_deinit(self); + Sercom *sercom = samd_i2c_get_sercom(scl, sda, &sercom_index, &sda_pinmux, &scl_pinmux); if (sercom == NULL) { raise_ValueError_invalid_pins(); @@ -108,33 +109,40 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, mp_arg_error_invalid(MP_QSTR_frequency); } + if (i2c_m_sync_enable(&self->i2c_desc) != ERR_NONE) { + common_hal_busio_i2c_deinit(self); + mp_raise_OSError(MP_EIO); + } + self->sda_pin = sda->number; self->scl_pin = scl->number; claim_pin(sda); claim_pin(scl); - if (i2c_m_sync_enable(&self->i2c_desc) != ERR_NONE) { - common_hal_busio_i2c_deinit(self); - mp_raise_OSError(MP_EIO); - } + // Prevent bulk sercom reset from resetting us. The finalizer will instead. + never_reset_sercom(self->i2c_desc.device.hw); } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { return self->sda_pin == NO_PIN; } +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->sda_pin = NO_PIN; +} + void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { if (common_hal_busio_i2c_deinited(self)) { return; } + allow_reset_sercom(self->i2c_desc.device.hw); i2c_m_sync_disable(&self->i2c_desc); i2c_m_sync_deinit(&self->i2c_desc); reset_pin_number(self->sda_pin); reset_pin_number(self->scl_pin); - self->sda_pin = NO_PIN; - self->scl_pin = NO_PIN; + common_hal_busio_i2c_mark_deinit(self); } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { @@ -147,6 +155,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; CRITICAL_SECTION_ENTER() if (!self->has_lock) { @@ -165,7 +176,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { self->has_lock = false; } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { uint16_t attempts = ATTEMPTS; @@ -186,17 +197,17 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, if (status == I2C_OK) { return 0; } else if (status == I2C_ERR_BAD_ADDRESS) { - return MP_ENODEV; + return -MP_ENODEV; } - return MP_EIO; + return -MP_EIO; } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { uint16_t attempts = ATTEMPTS; @@ -217,14 +228,14 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, if (status == ERR_NONE) { return 0; } else if (status == I2C_ERR_BAD_ADDRESS) { - return MP_ENODEV; + return -MP_ENODEV; } - return MP_EIO; + return -MP_EIO; } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } @@ -233,8 +244,6 @@ uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - never_reset_sercom(self->i2c_desc.device.hw); - never_reset_pin_number(self->scl_pin); never_reset_pin_number(self->sda_pin); } diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index 62772faff424d..19fd81e425d3e 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -17,11 +17,22 @@ #include "hal/include/hal_gpio.h" #include "hal/include/hal_spi_m_sync.h" -#include "hal/include/hpl_spi_m_sync.h" #include "samd/dma.h" #include "samd/sercom.h" + +static void setup_pin(const mcu_pin_obj_t *pin, uint32_t pinmux, const enum gpio_direction direction) { + gpio_set_pin_direction(pin->number, direction); + gpio_set_pin_pull_mode(pin->number, GPIO_PULL_OFF); + gpio_set_pin_function(pin->number, pinmux); + if (direction == GPIO_DIRECTION_OUT) { + // Use strong drive strength for SPI outputs. + hri_port_set_PINCFG_DRVSTR_bit(PORT, (enum gpio_port)GPIO_PORT(pin->number), GPIO_PIN(pin->number)); + } + claim_pin(pin); +} + void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { @@ -42,7 +53,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } // Ensure the object starts in its deinit state. - self->clock_pin = NO_PIN; + common_hal_busio_spi_mark_deinit(self); // Special case for SAMR21 boards. (feather_radiofruit_zigbee) #if defined(PIN_PC19F_SERCOM4_PAD0) @@ -76,6 +87,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) { continue; } + // find mosi_pad first, since it corresponds to dopo which takes limited values for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { if (!mosi_none) { if (sercom_index == mosi->sercom[j].index) { @@ -125,6 +137,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Pads must be set after spi_m_sync_init(), which uses default values from // the prototypical SERCOM. + + // Set to SPI host mode and choose pads. + hri_sercomspi_write_CTRLA_MODE_bf(sercom, 3); hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo); hri_sercomspi_write_CTRLA_DIPO_bf(sercom, miso_pad); @@ -137,30 +152,21 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_OSError(MP_EIO); } - gpio_set_pin_direction(clock->number, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(clock->number, GPIO_PULL_OFF); - gpio_set_pin_function(clock->number, clock_pinmux); - claim_pin(clock); + setup_pin(clock, clock_pinmux, GPIO_DIRECTION_OUT); self->clock_pin = clock->number; if (mosi_none) { self->MOSI_pin = NO_PIN; } else { - gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF); - gpio_set_pin_function(mosi->number, mosi_pinmux); + setup_pin(mosi, mosi_pinmux, GPIO_DIRECTION_OUT); self->MOSI_pin = mosi->number; - claim_pin(mosi); } if (miso_none) { self->MISO_pin = NO_PIN; } else { - gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF); - gpio_set_pin_function(miso->number, miso_pinmux); + setup_pin(miso, miso_pinmux, GPIO_DIRECTION_IN); self->MISO_pin = miso->number; - claim_pin(miso); } spi_m_sync_enable(&self->spi_desc); @@ -178,6 +184,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock_pin == NO_PIN; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock_pin = NO_PIN; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; @@ -189,7 +199,9 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { reset_pin_number(self->clock_pin); reset_pin_number(self->MOSI_pin); reset_pin_number(self->MISO_pin); - self->clock_pin = NO_PIN; + + // This smashes self->clock_pin, so don't do it before resetting the pin above. + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, @@ -222,6 +234,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; CRITICAL_SECTION_ENTER() if (!self->has_lock) { diff --git a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c index 05d5075e57862..56eb82678ec01 100644 --- a/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c +++ b/ports/atmel-samd/common-hal/imagecapture/ParallelImageCapture.c @@ -135,7 +135,8 @@ void common_hal_imagecapture_parallelimagecapture_singleshot_capture(imagecaptur mp_buffer_info_t bufinfo; mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_RW); - uint8_t dma_channel = dma_allocate_channel(); + // Allocate a permanent channel (not really audio). + uint8_t dma_channel = dma_allocate_audio_channel(); uint32_t *dest = bufinfo.buf; size_t count = bufinfo.len / 4; // PCC receives 4 bytes (2 pixels) at a time diff --git a/ports/atmel-samd/common-hal/os/__init__.c b/ports/atmel-samd/common-hal/os/__init__.c index 2c1de431c6635..89b5e85135d87 100644 --- a/ports/atmel-samd/common-hal/os/__init__.c +++ b/ports/atmel-samd/common-hal/os/__init__.c @@ -16,38 +16,6 @@ #include "hal/include/hal_rand_sync.h" #endif -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -#ifdef SAMD21 -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "samd21"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "samd21"); -#endif -#ifdef SAM_D5X_E5X -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "samd51"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "samd51"); -#endif -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { #ifdef SAM_D5X_E5X hri_mclk_set_APBCMASK_TRNG_bit(MCLK); diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c index 705f8ceeb8bec..e8434717c4269 100644 --- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c +++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c @@ -130,7 +130,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use")); } - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c index c6cd4605784ab..a8c87d82ed268 100644 --- a/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/atmel-samd/common-hal/rotaryio/IncrementalEncoder.c @@ -17,6 +17,10 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + if (!pin_a->has_extint) { raise_ValueError_invalid_pin_name(MP_QSTR_pin_a); } @@ -83,10 +87,13 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o turn_off_eic_channel(self->eic_channel_b); reset_pin_number(self->pin_a); - self->pin_a = NO_PIN; - reset_pin_number(self->pin_b); - self->pin_b = NO_PIN; + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + self->pin_a = NO_PIN; } void incrementalencoder_interrupt_handler(uint8_t channel) { diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.c b/ports/atmel-samd/common-hal/sdioio/SDCard.c index 071aada4962ac..e38a664ed48a8 100644 --- a/ports/atmel-samd/common-hal/sdioio/SDCard.c +++ b/ports/atmel-samd/common-hal/sdioio/SDCard.c @@ -9,6 +9,7 @@ #include "py/runtime.h" #include "common-hal/microcontroller/Pin.h" +#include "extmod/vfs.h" #include "shared-bindings/sdioio/SDCard.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" @@ -153,7 +154,7 @@ static void check_for_deinit(sdioio_sdcard_obj_t *self) { static void check_whole_block(mp_buffer_info_t *bufinfo) { if (bufinfo->len % 512) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } } @@ -170,43 +171,85 @@ static void debug_print_state(sdioio_sdcard_obj_t *self, const char *what, sd_mm #endif } -int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { - check_for_deinit(self); - check_whole_block(bufinfo); +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); wait_write_complete(self); self->state_programming = true; - sd_mmc_err_t r = sd_mmc_init_write_blocks(0, start_block, bufinfo->len / 512); + sd_mmc_err_t r = sd_mmc_init_write_blocks(0, start_block, num_blocks); if (r != SD_MMC_OK) { debug_print_state(self, "sd_mmc_init_write_blocks", r); - return -EIO; + return -MP_EIO; } - r = sd_mmc_start_write_blocks(bufinfo->buf, bufinfo->len / 512); + r = sd_mmc_start_write_blocks(buf, num_blocks); if (r != SD_MMC_OK) { debug_print_state(self, "sd_mmc_start_write_blocks", r); - return -EIO; + return -MP_EIO; } - // debug_print_state(self, "after writeblocks OK"); return 0; } -int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { check_for_deinit(self); check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); wait_write_complete(self); - sd_mmc_err_t r = sd_mmc_init_read_blocks(0, start_block, bufinfo->len / 512); + sd_mmc_err_t r = sd_mmc_init_read_blocks(0, start_block, num_blocks); if (r != SD_MMC_OK) { debug_print_state(self, "sd_mmc_init_read_blocks", r); - return -EIO; + return -MP_EIO; } - r = sd_mmc_start_read_blocks(bufinfo->buf, bufinfo->len / 512); + r = sd_mmc_start_read_blocks(buf, num_blocks); if (r != SD_MMC_OK) { debug_print_state(self, "sd_mmc_start_read_blocks", r); - return -EIO; + return -MP_EIO; } sd_mmc_wait_end_of_write_blocks(0); return 0; } +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + check_for_deinit(self); + check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, + mp_int_t *out_value) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + // SDIO operations are synchronous, no action needed + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdioio_sdcard_get_count(self); + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; // SD cards use 512-byte sectors + return true; + + default: + return false; // Unsupported command + } +} + bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) { check_for_deinit(self); return true; diff --git a/ports/atmel-samd/common-hal/spitarget/SPITarget.c b/ports/atmel-samd/common-hal/spitarget/SPITarget.c new file mode 100644 index 0000000000000..e5011b141fc12 --- /dev/null +++ b/ports/atmel-samd/common-hal/spitarget/SPITarget.c @@ -0,0 +1,245 @@ +#include "common-hal/spitarget/SPITarget.h" +#include "common-hal/busio/__init__.h" + +#include "shared-bindings/spitarget/SPITarget.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "py/mperrno.h" +#include "py/runtime.h" + +#include "hpl_sercom_config.h" +#include "peripheral_clk_config.h" + +#include "hal/include/hal_gpio.h" +#include "hal/include/hal_spi_m_sync.h" + +#include "hpl_sercom_config.h" +#include "samd/sercom.h" + +void common_hal_spitarget_spi_target_construct(spitarget_spi_target_obj_t *self, + const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss) { + Sercom *sercom = NULL; + uint8_t sercom_index; + uint32_t clock_pinmux = 0; + uint32_t mosi_pinmux = 0; + uint32_t miso_pinmux = 0; + uint32_t ss_pinmux = 0; + uint8_t clock_pad = 0; + uint8_t mosi_pad = 0; + uint8_t miso_pad = 0; + uint8_t dopo = 255; + + // Ensure the object starts in its deinit state. + self->clock_pin = NO_PIN; + + // Special case for SAMR21 boards. (feather_radiofruit_zigbee) + #if defined(PIN_PC19F_SERCOM4_PAD0) + if (miso == &pin_PC19) { + if (mosi == &pin_PB30 && sck == &pin_PC18) { + sercom = SERCOM4; + sercom_index = 4; + clock_pinmux = MUX_F; + mosi_pinmux = MUX_F; + miso_pinmux = MUX_F; + clock_pad = 3; + mosi_pad = 2; + miso_pad = 0; + dopo = samd_peripherals_get_spi_dopo(clock_pad, mosi_pad); + } + // Error, leave SERCOM unset to throw an exception later. + } else + #endif + { + for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { + sercom_index = sck->sercom[i].index; // 2 for SERCOM2, etc. + if (sercom_index >= SERCOM_INST_NUM) { + continue; + } + Sercom *potential_sercom = sercom_insts[sercom_index]; + if (potential_sercom->SPI.CTRLA.bit.ENABLE != 0) { + continue; + } + clock_pinmux = PINMUX(sck->number, (i == 0) ? MUX_C : MUX_D); + clock_pad = sck->sercom[i].pad; + if (!samd_peripherals_valid_spi_clock_pad(clock_pad)) { + continue; + } + // find miso_pad first, since it corresponds to dopo which takes limited values + for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { + if (sercom_index == miso->sercom[j].index) { + miso_pinmux = PINMUX(miso->number, (j == 0) ? MUX_C : MUX_D); + miso_pad = miso->sercom[j].pad; + dopo = samd_peripherals_get_spi_dopo(clock_pad, miso_pad); + if (dopo > 0x3) { + continue; // pad combination not possible + } + } else { + continue; + } + for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { + if (sercom_index == mosi->sercom[k].index) { + mosi_pinmux = PINMUX(mosi->number, (k == 0) ? MUX_C : MUX_D); + mosi_pad = mosi->sercom[k].pad; + for (int m = 0; m < NUM_SERCOMS_PER_PIN; m++) { + if (sercom_index == ss->sercom[m].index) { + ss_pinmux = PINMUX(ss->number, (m == 0) ? MUX_C : MUX_D); + sercom = potential_sercom; + break; + } + } + if (sercom != NULL) { + break; + } + } + } + if (sercom != NULL) { + break; + } + } + if (sercom != NULL) { + break; + } + } + } + if (sercom == NULL) { + raise_ValueError_invalid_pins(); + } + + // Set up SPI clocks on SERCOM. + samd_peripherals_sercom_clock_init(sercom, sercom_index); + + if (spi_m_sync_init(&self->spi_desc, sercom) != ERR_NONE) { + mp_raise_OSError(MP_EIO); + } + + // Pads must be set after spi_m_sync_init(), which uses default values from + // the prototypical SERCOM. + + hri_sercomspi_write_CTRLA_MODE_bf(sercom, 2); + hri_sercomspi_write_CTRLA_DOPO_bf(sercom, dopo); + hri_sercomspi_write_CTRLA_DIPO_bf(sercom, mosi_pad); + hri_sercomspi_write_CTRLB_PLOADEN_bit(sercom, 1); + + // Always start at 250khz which is what SD cards need. They are sensitive to + // SPI bus noise before they are put into SPI mode. + uint8_t baud_value = samd_peripherals_spi_baudrate_to_baud_reg_value(250000); + if (spi_m_sync_set_baudrate(&self->spi_desc, baud_value) != ERR_NONE) { + // spi_m_sync_set_baudrate does not check for validity, just whether the device is + // busy or not + mp_raise_OSError(MP_EIO); + } + + gpio_set_pin_direction(sck->number, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(sck->number, GPIO_PULL_OFF); + gpio_set_pin_function(sck->number, clock_pinmux); + claim_pin(sck); + self->clock_pin = sck->number; + + gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF); + gpio_set_pin_function(mosi->number, mosi_pinmux); + self->MOSI_pin = mosi->number; + claim_pin(mosi); + + gpio_set_pin_direction(miso->number, GPIO_DIRECTION_OUT); + gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF); + gpio_set_pin_function(miso->number, miso_pinmux); + self->MISO_pin = miso->number; + claim_pin(miso); + + gpio_set_pin_direction(ss->number, GPIO_DIRECTION_IN); + gpio_set_pin_pull_mode(ss->number, GPIO_PULL_OFF); + gpio_set_pin_function(ss->number, ss_pinmux); + self->SS_pin = ss->number; + claim_pin(ss); + + self->running_dma.failure = 1; // not started + self->mosi_packet = NULL; + self->miso_packet = NULL; + + spi_m_sync_enable(&self->spi_desc); +} + +bool common_hal_spitarget_spi_target_deinited(spitarget_spi_target_obj_t *self) { + return self->clock_pin == NO_PIN; +} + +void common_hal_spitarget_spi_target_deinit(spitarget_spi_target_obj_t *self) { + if (common_hal_spitarget_spi_target_deinited(self)) { + return; + } + allow_reset_sercom(self->spi_desc.dev.prvt); + + spi_m_sync_disable(&self->spi_desc); + spi_m_sync_deinit(&self->spi_desc); + reset_pin_number(self->clock_pin); + reset_pin_number(self->MOSI_pin); + reset_pin_number(self->MISO_pin); + reset_pin_number(self->SS_pin); + self->clock_pin = NO_PIN; +} + +void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t *self, + uint8_t *mosi_packet, const uint8_t *miso_packet, size_t len) { + if (len == 0) { + return; + } + if (self->running_dma.failure != 1) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Async SPI transfer in progress on this bus, keep awaiting.")); + } + + self->mosi_packet = mosi_packet; + self->miso_packet = miso_packet; + + Sercom *sercom = self->spi_desc.dev.prvt; + shared_dma_transfer_start(&self->running_dma, sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); + + // There is an issue where if an unexpected SPI transfer is received before the user calls "end" for the in-progress, expected + // transfer, the SERCOM has an error and gets confused. This can be detected from INTFLAG.ERROR. I think the code in + // ports/atmel-samd/peripherals/samd/dma.c at line 277 (as of this commit; it's the part that reads s->SPI.INTFLAG.bit.RXC and + // s->SPI.DATA.reg) is supposed to fix this, but experimentation seems to show that it does not in fact fix anything. Anyways, if + // the ERROR bit is set, let's just reset the peripheral and then setup the transfer again -- that seems to work. + if (hri_sercomspi_get_INTFLAG_ERROR_bit(sercom)) { + shared_dma_transfer_close(&self->running_dma); + + // disable the sercom + spi_m_sync_disable(&self->spi_desc); + hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK); + + // save configurations + hri_sercomspi_ctrla_reg_t ctrla_saved_val = hri_sercomspi_get_CTRLA_reg(sercom, -1); // -1 mask is all ones: save all bits + hri_sercomspi_ctrlb_reg_t ctrlb_saved_val = hri_sercomspi_get_CTRLB_reg(sercom, -1); // -1 mask is all ones: save all bits + hri_sercomspi_baud_reg_t baud_saved_val = hri_sercomspi_get_BAUD_reg(sercom, -1); // -1 mask is all ones: save all bits + // reset + hri_sercomspi_set_CTRLA_SWRST_bit(sercom); + hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK); + // re-write configurations + hri_sercomspi_write_CTRLA_reg(sercom, ctrla_saved_val); + hri_sercomspi_write_CTRLB_reg(sercom, ctrlb_saved_val); + hri_sercomspi_write_BAUD_reg(sercom, baud_saved_val); + hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK); + + // re-enable the sercom + spi_m_sync_enable(&self->spi_desc); + hri_sercomspi_wait_for_sync(sercom, SERCOM_SPI_SYNCBUSY_MASK); + + shared_dma_transfer_start(&self->running_dma, sercom, miso_packet, &sercom->SPI.DATA.reg, &sercom->SPI.DATA.reg, mosi_packet, len, 0); + } +} + +bool common_hal_spitarget_spi_target_transfer_is_finished(spitarget_spi_target_obj_t *self) { + return self->running_dma.failure == 1 || shared_dma_transfer_finished(&self->running_dma); +} + +int common_hal_spitarget_spi_target_transfer_close(spitarget_spi_target_obj_t *self) { + if (self->running_dma.failure == 1) { + return 0; + } + int res = shared_dma_transfer_close(&self->running_dma); + self->running_dma.failure = 1; + + self->mosi_packet = NULL; + self->miso_packet = NULL; + + return res; +} diff --git a/ports/atmel-samd/common-hal/spitarget/SPITarget.h b/ports/atmel-samd/common-hal/spitarget/SPITarget.h new file mode 100644 index 0000000000000..9fff23c174370 --- /dev/null +++ b/ports/atmel-samd/common-hal/spitarget/SPITarget.h @@ -0,0 +1,24 @@ +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H +#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H + +#include "common-hal/microcontroller/Pin.h" +#include "hal/include/hal_spi_m_sync.h" +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + + struct spi_m_sync_descriptor spi_desc; + + uint8_t clock_pin; + uint8_t MOSI_pin; + uint8_t MISO_pin; + uint8_t SS_pin; + + uint8_t *mosi_packet; + const uint8_t *miso_packet; + + dma_transfer_t running_dma; +} spitarget_spi_target_obj_t; + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_TARGET_H diff --git a/ports/atmel-samd/common-hal/spitarget/__init__.c b/ports/atmel-samd/common-hal/spitarget/__init__.c new file mode 100644 index 0000000000000..c0ce8cef9a164 --- /dev/null +++ b/ports/atmel-samd/common-hal/spitarget/__init__.c @@ -0,0 +1 @@ +// No spitarget module functions. diff --git a/ports/atmel-samd/common-hal/touchio/TouchIn.c b/ports/atmel-samd/common-hal/touchio/TouchIn.c index 05c3f3ee923d9..822d614a60298 100644 --- a/ports/atmel-samd/common-hal/touchio/TouchIn.c +++ b/ports/atmel-samd/common-hal/touchio/TouchIn.c @@ -12,6 +12,7 @@ #include "py/binary.h" #include "py/mphal.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/touchio/TouchIn.h" // Native touchio only exists for SAMD21 @@ -38,7 +39,7 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { } void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, - const mcu_pin_obj_t *pin) { + const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { if (!pin->has_touch) { raise_ValueError_invalid_pin(); } @@ -90,7 +91,7 @@ void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self) { self->config.pin = NO_PIN; } -void touchin_reset() { +void touchin_reset(void) { Ptc *ptc = ((Ptc *)PTC); if (ptc->CTRLA.bit.ENABLE == 1) { ptc->CTRLA.bit.ENABLE = 0; diff --git a/ports/atmel-samd/libs/libgcc-12.1.0-Os-v6-m-nofp.a b/ports/atmel-samd/libs/libgcc-12.1.0-Os-v6-m-nofp.a deleted file mode 100644 index 56692d5d05632..0000000000000 Binary files a/ports/atmel-samd/libs/libgcc-12.1.0-Os-v6-m-nofp.a and /dev/null differ diff --git a/ports/atmel-samd/libs/libgcc-14.2.0-Os-v6-m-nofp.a b/ports/atmel-samd/libs/libgcc-14.2.0-Os-v6-m-nofp.a new file mode 100644 index 0000000000000..6a708c1ffaa3c Binary files /dev/null and b/ports/atmel-samd/libs/libgcc-14.2.0-Os-v6-m-nofp.a differ diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index 4100230815aad..087e0bc7d6820 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -46,6 +46,14 @@ // Only support simpler HID descriptors on SAMD21. #define CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR (1) +// Avoid linker error: +// :(.text.nlr_push+0x20): relocation truncated to fit: R_ARM_THM_JUMP11 against symbol `nlr_push_tail' defined in .text.nlr_push_tail section in /tmp/ccvHNpPQ.ltrans0.ltrans.o +// See https://github.com/micropython/micropython/pull/11353 +#define MICROPY_NLR_THUMB_USE_LONG_JUMP (1) + +// Don't store qstr hashes and do string compares instead. +#define MICROPY_QSTR_BYTES_IN_HASH (0) + #endif // SAMD21 //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,8 +70,7 @@ #define MICROPY_PY_SYS_PLATFORM "MicroChip SAME54" #endif #define SPI_FLASH_MAX_BAUDRATE 24000000 -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_FUNCTION_ATTRS (1) + // MICROPY_PY_ERRNO_LIST - Use the default #endif // SAM_D5X_E5X @@ -95,6 +102,11 @@ #define CIRCUITPY_DEFAULT_STACK_SIZE 3584 #endif +#ifndef CIRCUITPY_PYSTACK_SIZE +// Default for most boards is 2048 starting with CircuitPython 10, but on SAMD21, keep it at previous lower value. +#define CIRCUITPY_PYSTACK_SIZE 1536 +#endif + #ifndef SAMD21_BOD33_LEVEL // Set brownout detection to ~2.7V. Default from factory is 1.7V, // which is too low for proper operation of external SPI flash chips diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index c3449485cf40e..b0947ea6f2529 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -12,6 +12,9 @@ CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 CIRCUITPY_LTO = 1 CIRCUITPY_KEYPAD_DEMUX ?= 0 +CIRCUITPY_LVFONTIO ?= 0 + +CIRCUITPY_DIGITALINOUT_PROTOCOL = 0 ###################################################################### # Put samd21-only choices here. @@ -45,10 +48,11 @@ CIRCUITPY_I2CTARGET ?= 0 CIRCUITPY_JSON ?= 0 CIRCUITPY_KEYPAD ?= 0 CIRCUITPY_MSGPACK ?= 0 -CIRCUITPY_OS_GETENV ?= 0 CIRCUITPY_PIXELMAP ?= 0 CIRCUITPY_RE ?= 0 CIRCUITPY_SDCARDIO ?= 0 +CIRCUITPY_SETTINGS_TOML ?= 0 +CIRCUITPY_SPITARGET ?= 0 CIRCUITPY_SYNTHIO ?= 0 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 CIRCUITPY_TRACEBACK ?= 0 @@ -58,6 +62,9 @@ CIRCUITPY_ZLIB = 0 # Turn off a few more things that don't fit in 192kB +CIRCUITPY_TERMINALIO_VT100 = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 + ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) CIRCUITPY_ONEWIREIO ?= 0 CIRCUITPY_SAFEMODE_PY ?= 0 @@ -118,6 +125,7 @@ CIRCUITPY_MAX3421E ?= $(HAS_1MB_FLASH) CIRCUITPY_PS2IO ?= 1 CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FRAMEBUFFERIO) CIRCUITPY_SAMD ?= 1 +CIRCUITPY_SPITARGET ?= 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12 CIRCUITPY_ULAB_OPTIMIZE_SIZE ?= 1 CIRCUITPY_WATCHDOG ?= 1 diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index 82e514b6e0d1a..da0a1d7dccb34 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit 82e514b6e0d1a2b09dc73be9973663b6b837a817 +Subproject commit da0a1d7dccb34b7fa07738e7a8ce25118c88d1a3 diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c index 9cacd4ab951ae..816e23e3251db 100644 --- a/ports/atmel-samd/reset.c +++ b/ports/atmel-samd/reset.c @@ -9,7 +9,7 @@ #include "reset.h" #include "supervisor/filesystem.h" -void NVIC_SystemReset(void) NORETURN; +void NVIC_SystemReset(void) MP_NORETURN; void reset(void) { filesystem_flush(); diff --git a/ports/atmel-samd/reset.h b/ports/atmel-samd/reset.h index c74d25fa01ea5..248d43779fdc9 100644 --- a/ports/atmel-samd/reset.h +++ b/ports/atmel-samd/reset.h @@ -16,6 +16,6 @@ extern uint32_t _bootloader_dbl_tap; -void reset_to_bootloader(void) NORETURN; -void reset(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; +void reset(void) MP_NORETURN; bool bootloader_available(void); diff --git a/ports/atmel-samd/sd_mmc/sd_mmc.c b/ports/atmel-samd/sd_mmc/sd_mmc.c index 60b4d9f8985a1..6724e88f42a7a 100644 --- a/ports/atmel-samd/sd_mmc/sd_mmc.c +++ b/ports/atmel-samd/sd_mmc/sd_mmc.c @@ -160,9 +160,9 @@ static struct sd_mmc_card sd_mmc_cards[CONF_SD_MMC_MEM_CNT]; /** HAL driver instance */ static void *sd_mmc_hal; -/** Index of current slot configurated */ +/** Index of current slot configured */ static uint8_t sd_mmc_slot_sel; -/** Pointer on current slot configurated */ +/** Pointer on current slot configured */ static struct sd_mmc_card *sd_mmc_card; /** Number of block to read or write on the current transfer */ static uint16_t sd_mmc_nb_block_to_tranfer = 0; @@ -238,7 +238,7 @@ static bool mmc_mci_op_cond(void) { uint32_t retry, resp; /* - * Timeout 1s = 400KHz / ((6+6)*8) cylces = 4200 retry + * Timeout 1s = 400KHz / ((6+6)*8) cycles = 4200 retry * 6 = cmd byte size * 6 = response byte size */ @@ -277,7 +277,7 @@ static bool sd_mci_op_cond(uint8_t v2) { uint32_t arg, retry, resp; /* - * Timeout 1s = 400KHz / ((6+6+6+6)*8) cylces = 2100 retry + * Timeout 1s = 400KHz / ((6+6+6+6)*8) cycles = 2100 retry * 6 = cmd byte size * 6 = response byte size * 6 = cmd byte size @@ -339,7 +339,7 @@ static bool sdio_op_cond(void) { /* * Wait card ready - * Timeout 1s = 400KHz / ((6+4)*8) cylces = 5000 retry + * Timeout 1s = 400KHz / ((6+4)*8) cycles = 5000 retry * 6 = cmd byte size * 4(SPI) 6(MCI) = response byte size */ @@ -1292,13 +1292,13 @@ static bool sd_mmc_mci_install_mmc(void) { void sd_mmc_init(void *hal, sd_mmc_detect_t *card_detects, sd_mmc_detect_t *wp_detects) { /* GPIO will be used to detect card and write protect. - * The related clocks and pinmux must be configurated in good + * The related clocks and pinmux must be configured in good * condition. */ for (uint8_t slot = 0; slot < CONF_SD_MMC_MEM_CNT; slot++) { sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD; } - sd_mmc_slot_sel = 0xFF; /* No slot configurated */ + sd_mmc_slot_sel = 0xFF; /* No slot configured */ sd_mmc_hal = hal; _cd = card_detects; _wp = wp_detects; diff --git a/ports/atmel-samd/sd_mmc/sd_mmc.h b/ports/atmel-samd/sd_mmc/sd_mmc.h index cdc98e7108e2e..7b70a631164d5 100644 --- a/ports/atmel-samd/sd_mmc/sd_mmc.h +++ b/ports/atmel-samd/sd_mmc/sd_mmc.h @@ -113,7 +113,7 @@ typedef struct sd_mmc_detect { uint16_t val; /**< Detection value */ } sd_mmc_detect_t; -/** This SD MMC stack uses the maximum block size autorized (512 bytes) */ +/** This SD MMC stack uses the maximum block size authorized (512 bytes) */ #define SD_MMC_BLOCK_SIZE 512 /** diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 8f5115789da2a..288446cf62e71 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -339,6 +339,7 @@ safe_mode_t port_init(void) { init_shared_dma(); // Reset everything into a known state before board_init. + // Pins are reset in main() after this routine returns. reset_port(); #ifdef SAMD21 @@ -411,8 +412,6 @@ void reset_port(void) { reset_ticks(); } - reset_all_pins(); - // Output clocks for debugging. // not supported by SAMD51G; uncomment for SAMD51J or update for 51G // #ifdef SAM_D5X_E5X @@ -686,7 +685,7 @@ void port_idle_until_interrupt(void) { /** * \brief Default interrupt handler for unused IRQs. */ -__attribute__((used)) void HardFault_Handler(void) { +__attribute__((used)) MP_NORETURN void HardFault_Handler(void) { #ifdef ENABLE_MICRO_TRACE_BUFFER // Turn off the micro trace buffer so we don't fill it up in the infinite // loop below. diff --git a/ports/atmel-samd/supervisor/samd21_cpu.s b/ports/atmel-samd/supervisor/samd21_cpu.s deleted file mode 100755 index 741bb21358ad2..0000000000000 --- a/ports/atmel-samd/supervisor/samd21_cpu.s +++ /dev/null @@ -1,35 +0,0 @@ -.syntax unified -.cpu cortex-m0 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0, #0] -str r5, [r0, #4] -str r6, [r0, #8] -str r7, [r0, #12] -push {r1} -mov r1, r8 -str r1, [r0, #16] -mov r1, r9 -str r1, [r0, #20] -mov r1, r10 -str r1, [r0, #24] -mov r1, r11 -str r1, [r0, #28] -mov r1, r12 -str r1, [r0, #32] -mov r1, r13 -str r1, [r0, #36] -pop {r1} - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/atmel-samd/supervisor/samd51_cpu.s b/ports/atmel-samd/supervisor/samd51_cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/atmel-samd/supervisor/samd51_cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/atmel-samd/supervisor/same51_cpu.s b/ports/atmel-samd/supervisor/same51_cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/atmel-samd/supervisor/same51_cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/atmel-samd/supervisor/same54_cpu.s b/ports/atmel-samd/supervisor/same54_cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/atmel-samd/supervisor/same54_cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/atmel-samd/tools/gen_pin_name_table.py b/ports/atmel-samd/tools/gen_pin_name_table.py deleted file mode 100644 index 16af2540bddb1..0000000000000 --- a/ports/atmel-samd/tools/gen_pin_name_table.py +++ /dev/null @@ -1,380 +0,0 @@ -# This file is part of the CircuitPython project: https://circuitpython.org -# -# SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -# This helper generates the pinout tables in ../README.rst. - -import os -import os.path - -pins = [ - "PA00", - "PA01", - "PA02", - "PA03", - "PB08", - "PB09", - "PA04", - "PA05", - "PA06", - "PA07", - "PA08", - "PA09", - "PA10", - "PA11", - "PB10", - "PB11", - "PA12", - "PA13", - "PA14", - "PA15", - "PA16", - "PA17", - "PA18", - "PA19", - "PA20", - "PA21", - "PA22", - "PA23", - "PA24", - "PA25", - "PB22", - "PB23", - "PA27", - "PA28", - "PA29", - "PA30", - "PA31", - "PB02", - "PB03", -] - -# Dictionary keys: [board][pin] = list of pin names -mapping = {} - -QSTR = " { MP_OBJ_NEW_QSTR(MP_QSTR_" - -for board in os.listdir("boards"): - if not os.path.isdir("boards/" + board): - continue - mapping[board] = {} - with open("boards/" + board + "/pins.c", "r") as f: - for line in f: - if line.startswith(QSTR): - board_name, _, pin = line.split(")") - board_name = board_name[len(QSTR) :] - pin = pin[-8:-4] - if pin not in mapping[board]: - mapping[board][pin] = [] - mapping[board][pin].append(board_name) - -column_width = {} -for board in mapping: - column_width[board] = len(board) - for pin in mapping[board]: - l = len(" / ".join("``" + x + "``" for x in mapping[board][pin])) - column_width[board] = max(l, column_width[board]) - -first_column_width = len("`microcontroller.pin`") -print("=" * first_column_width, end="") -total_board_width = -2 -for board in column_width: - column = " " + "=" * column_width[board] - total_board_width += len(column) - print(column, end="") - -print() -print("`microcontroller.pin` `board`") -print("-" * first_column_width + " " + "-" * total_board_width) - -print("Datasheet".ljust(first_column_width), end="") -for board in column_width: - print(" " + board.ljust(column_width[board]), end="") -print() - -print("=" * first_column_width, end="") -for board in column_width: - column = " " + "=" * column_width[board] - print(column, end="") -print() - -for pin in pins: - print(pin.ljust(first_column_width), end="") - for board in column_width: - if pin in mapping[board]: - names = " / ".join("``" + x + "``" for x in mapping[board][pin]) - print(" " + names.ljust(column_width[board]), end="") - else: - print(" " * (column_width[board] + 2), end="") - print() - -print("=" * first_column_width, end="") -for board in column_width: - column = " " + "=" * column_width[board] - print(column, end="") -print() - -print() -print() -# Generate pin capabilities too. - -ALL_BUT_USB = list(pins) -ALL_BUT_USB.remove("PA24") -ALL_BUT_USB.remove("PA25") - -# dictionary is [module][class] = [pins] -capabilities = { - "analogio": { - "AnalogIn": [ - "PA02", - "PA03", - "PB08", - "PB09", - "PA04", - "PA05", - "PA06", - "PA07", - "PA08", - "PA09", - "PA10", - "PA11", - "PB02", - "PB03", - ], - "AnalogOut": ["PA02"], - }, - "audioio": {"AudioOut": ["PA02"]}, - "bitbangio": {"I2C": ALL_BUT_USB, "SPI": ALL_BUT_USB}, - "busio": { - "I2C - SDA": ["PA00", "PB08", "PA08", "PA12", "PA16", "PA22", "PB02"], # SERCOM pad 0 - "I2C - SCL": ["PA01", "PB09", "PA09", "PA13", "PA17", "PA23", "PB03"], # SERCOM pad 1 - "SPI - MISO": [ - "PA00", - "PA01", - "PB08", - "PB09", - "PA04", - "PA05", - "PA06", - "PA07", - "PA08", - "PA09", - "PA10", - "PA11", - "PB10", - "PB11", - "PA12", - "PA13", - "PA14", - "PA15", - "PA16", - "PA17", - "PA18", - "PA19", - "PA20", - "PA21", - "PA22", - "PA23", - "PB22", - "PB23", - "PA30", - "PA31", - "PB02", - "PB03", - ], # any SERCOM pad - "SPI - MOSI": [ - "PA00", - "PB08", - "PA04", - "PA06", - "PA08", - "PA10", - "PA11", - "PB10", - "PB11", - "PA14", - "PA15", - "PA16", - "PA18", - "PA19", - "PA20", - "PA21", - "PA22", - "PB22", - "PB23", - "PA30", - "PA31", - "PB02", - ], # any pad but 1 - "SPI - SCK": [ - "PA01", - "PB09", - "PA05", - "PA07", - "PA09", - "PA11", - "PB11", - "PA13", - "PA15", - "PA17", - "PA19", - "PA21", - "PA23", - "PB23", - "PA31", - "PB03", - ], # 1 or 3 - "UART - RX": [ - "PA00", - "PA01", - "PB08", - "PB09", - "PA04", - "PA05", - "PA06", - "PA07", - "PA08", - "PA09", - "PA10", - "PA11", - "PB10", - "PB11", - "PA12", - "PA13", - "PA14", - "PA15", - "PA16", - "PA17", - "PA18", - "PA19", - "PA20", - "PA21", - "PA22", - "PA23", - "PB22", - "PB23", - "PA30", - "PA31", - "PB02", - "PB03", - ], # any pad - "UART - TX": [ - "PA00", - "PB08", - "PA04", - "PA06", - "PA08", - "PA10", - "PB10", - "PA12", - "PA14", - "PA16", - "PA18", - "PA20", - "PA22", - "PB22", - "PA30", - "PB02", - ], # pad 0 or 2 - }, - "digitalio": {"DigitalInOut": ALL_BUT_USB}, - "onewireio": {"OneWire": ALL_BUT_USB}, - "pulseio": { - "PulseIn": ALL_BUT_USB, - "PWMOut": [ - "PA01", - "PB09", - "PA04", - "PA05", - "PA06", - "PA07", - "PA08", - "PA09", - "PA10", - "PA11", - "PB10", - "PB11", - "PA12", - "PA13", - "PA14", - "PA15", - "PA16", - "PA17", - "PA18", - "PA19", - "PA20", - "PA21", - "PA22", - "PA23", - "PA30", - "PA31", - ], - }, - "ps2io": {"Ps2": ALL_BUT_USB}, - "touchio": { - "TouchIn": ["PA02", "PA03", "PB08", "PB09", "PA04", "PA05", "PA06", "PA07", "PB02", "PB03"] - }, -} - -column_width = {} -for module in capabilities: - for c in capabilities[module]: - column_width[module + c] = max(len("**Yes**"), len(c)) - -module_width = {} -for module in capabilities: - module_width[module] = 0 - for c in capabilities[module]: - module_width[module] += column_width[module + c] + 2 - module_width[module] -= 2 - - if module_width[module] < (len(module) + 2): - column_width[module + c] += len(module) + 2 - module_width[module] - module_width[module] = len(module) + 2 - -first_column_width = len("`microcontroller.pin`") -print("=" * first_column_width, end="") -for module in capabilities: - for c in capabilities[module]: - print(" " + "=" * column_width[module + c], end="") -print() - -print("`microcontroller.pin`", end="") -for module in capabilities: - print(" " + ("`" + module + "`").ljust(module_width[module]), end="") -print() - -print("-" * first_column_width, end="") -for module in capabilities: - print(" " + "-" * module_width[module], end="") -print() - -print("Datasheet".ljust(first_column_width), end="") -for module in capabilities: - for c in capabilities[module]: - print(" " + c.ljust(column_width[module + c]), end="") -print() - -print("=" * first_column_width, end="") -for module in capabilities: - for c in capabilities[module]: - print(" " + "=" * column_width[module + c], end="") -print() - -for pin in pins: - print(pin.ljust(first_column_width), end="") - for module in capabilities: - for c in capabilities[module]: - if pin in capabilities[module][c]: - print(" " + "**Yes**".ljust(column_width[module + c]), end="") - else: - print(" " * (column_width[module + c] + 2), end="") - print() - -print("=" * first_column_width, end="") -for module in capabilities: - for c in capabilities[module]: - print(" " + "=" * column_width[module + c], end="") -print() diff --git a/ports/atmel-samd/tools/mkcandata.py b/ports/atmel-samd/tools/mkcandata.py index d505c81bdc49d..06731a9154723 100755 --- a/ports/atmel-samd/tools/mkcandata.py +++ b/ports/atmel-samd/tools/mkcandata.py @@ -15,8 +15,8 @@ def defines(name, suffix): {{&pin_{pin}, {instance}, PIN_{pin}, {pinmux} & 0xffff}}, #endif""" ) - print(f"{{NULL, 0, 0}}") - print(f"}};") + print("{NULL, 0, 0}") + print("};") print() diff --git a/ports/atmel-samd/tools/mksdiodata.py b/ports/atmel-samd/tools/mksdiodata.py index bfdcd696c26a1..5e59c6249b1dc 100755 --- a/ports/atmel-samd/tools/mksdiodata.py +++ b/ports/atmel-samd/tools/mksdiodata.py @@ -14,8 +14,8 @@ def defines(name, function): {{&pin_{pin}, {instance}, PIN_{pin}, {pinmux} & 0xffff}}, #endif""" ) - print(f"{{NULL, 0, 0}}") - print(f"}};") + print("{NULL, 0, 0}") + print("};") print() diff --git a/ports/broadcom/Makefile b/ports/broadcom/Makefile index 56c8c3237443e..dda93c6fd7ce0 100644 --- a/ports/broadcom/Makefile +++ b/ports/broadcom/Makefile @@ -48,6 +48,7 @@ SRC_C += bindings/videocore/__init__.c \ lib/sdmmc/sdmmc_mmc.c \ lib/sdmmc/sdmmc_sd.c \ lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c \ + lib/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c \ peripherals/broadcom/caches.c \ peripherals/broadcom/gen/interrupt_handlers.c \ peripherals/broadcom/gen/pins.c \ @@ -58,18 +59,7 @@ SRC_C += bindings/videocore/__init__.c \ SRC_S = peripherals/broadcom/boot$(SUFFIX).s -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-modules/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) +SRC_C += shared/runtime/gchelper_generic.c OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) @@ -107,11 +97,11 @@ else endif -CFLAGS += $(INC) -Wall -Werror -std=gnu11 $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) +CFLAGS += $(INC) -Wall -Werror -std=gnu11 $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -Werror=old-style-definition $(BUILD)/lib/tlsf/tlsf.o: CFLAGS += -Wno-cast-align -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) LDFLAGS += $(CFLAGS) -T peripherals/broadcom/link$(SUFFIX).ld -Wl,--gc-sections -Wl,-Map=$@.map # -Wl,--cref diff --git a/ports/broadcom/bindings/videocore/Framebuffer.c b/ports/broadcom/bindings/videocore/Framebuffer.c index f5d8ab8d34b38..66135baa7fe35 100644 --- a/ports/broadcom/bindings/videocore/Framebuffer.c +++ b/ports/broadcom/bindings/videocore/Framebuffer.c @@ -26,6 +26,7 @@ //| //| A Framebuffer is often used in conjunction with a //| `framebufferio.FramebufferDisplay`.""" +//| static mp_obj_t videocore_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_width, ARG_height, }; @@ -51,6 +52,7 @@ static mp_obj_t videocore_framebuffer_make_new(const mp_obj_type_t *type, size_t //| rgbmatrix instance. After deinitialization, no further operations //| may be performed.""" //| ... +//| static mp_obj_t videocore_framebuffer_deinit(mp_obj_t self_in) { videocore_framebuffer_obj_t *self = (videocore_framebuffer_obj_t *)self_in; common_hal_videocore_framebuffer_deinit(self); @@ -79,6 +81,7 @@ MP_PROPERTY_GETTER(videocore_framebuffer_width_obj, //| height: int //| """The height of the display, in pixels""" //| +//| static mp_obj_t videocore_framebuffer_get_height(mp_obj_t self_in) { videocore_framebuffer_obj_t *self = (videocore_framebuffer_obj_t *)self_in; check_for_deinit(self); diff --git a/ports/broadcom/common-hal/busio/I2C.c b/ports/broadcom/common-hal/busio/I2C.c index 19f346595f738..7c1eafe281dc9 100644 --- a/ports/broadcom/common-hal/busio/I2C.c +++ b/ports/broadcom/common-hal/busio/I2C.c @@ -47,9 +47,14 @@ void reset_i2c(void) { void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + size_t instance_index = NUM_I2C; uint8_t scl_alt = 0; uint8_t sda_alt = 0; + for (scl_alt = 0; scl_alt < 6; scl_alt++) { if (scl->functions[scl_alt].type != PIN_FUNCTION_I2C || i2c_in_use[scl->functions[scl_alt].index] || @@ -90,17 +95,19 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { return self->sda_pin == NULL; } +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->sda_pin = NULL; +} + void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { if (common_hal_busio_i2c_deinited(self)) { return; } - never_reset_i2c[self->index] = false; i2c_in_use[self->index] = false; common_hal_reset_pin(self->sda_pin); common_hal_reset_pin(self->scl_pin); - self->sda_pin = NULL; - self->scl_pin = NULL; + common_hal_busio_i2c_mark_deinit(self); } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { @@ -109,6 +116,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; @@ -127,7 +137,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { // Discussion of I2C implementation is here: https://github.com/raspberrypi/linux/issues/254 -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { COMPLETE_MEMORY_READS; self->peripheral->S_b.DONE = true; @@ -172,7 +182,7 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, while (self->peripheral->S_b.ERR == 1) { RUN_BACKGROUND_TASKS; } - return MP_ENODEV; + return -MP_ENODEV; } if (loop_len < len) { @@ -182,19 +192,19 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, return 0; } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { COMPLETE_MEMORY_READS; self->peripheral->A_b.ADDR = addr; if (self->finish_write) { self->finish_write = false; if (self->peripheral->S_b.ERR == 1) { - return MP_ENODEV; + return -MP_ENODEV; } self->peripheral->FIFO_b.DATA = self->last_write_data; } else { @@ -226,15 +236,15 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, while (self->peripheral->S_b.ERR == 1) { RUN_BACKGROUND_TASKS; } - return MP_ENODEV; + return -MP_ENODEV; } return 0; } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } diff --git a/ports/broadcom/common-hal/busio/SPI.c b/ports/broadcom/common-hal/busio/SPI.c index f573d7b032991..9e4834e86f352 100644 --- a/ports/broadcom/common-hal/busio/SPI.c +++ b/ports/broadcom/common-hal/busio/SPI.c @@ -30,31 +30,8 @@ static SPI0_Type *spi[NUM_SPI] = {SPI0, NULL, NULL}; static SPI1_Type *aux_spi[NUM_SPI] = {NULL, SPI1, SPI2}; #endif -static bool never_reset_spi[NUM_SPI]; static bool spi_in_use[NUM_SPI]; -void reset_spi(void) { - for (size_t i = 0; i < NUM_SPI; i++) { - if (never_reset_spi[i]) { - continue; - } - - if (i == 1 || i == 2) { - if (i == 1) { - AUX->ENABLES_b.SPI_1 = false; - } else { - AUX->ENABLES_b.SPI_2 = false; - } - aux_spi[i]->CNTL0 = 0; - } else { - // Set CS back to default. All 0 except read enable. - spi[i]->CS = SPI0_CS_REN_Msk; - } - - spi_in_use[i] = false; - } -} - void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { @@ -67,6 +44,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_NotImplementedError(MP_ERROR_TEXT("Half duplex SPI is not implemented")); } + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + // BCM_VERSION != 2711 have 3 SPI but as listed in peripherals/gen/pins.c two are on // index 0, once one index 0 SPI is found the other will throw an invalid_pins error. for (size_t i = 0; i < NUM_SPI; i++) { @@ -118,8 +98,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - never_reset_spi[self->index] = true; - common_hal_never_reset_pin(self->clock); common_hal_never_reset_pin(self->MOSI); common_hal_never_reset_pin(self->MISO); @@ -129,16 +107,19 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock = NULL; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; } - never_reset_spi[self->index] = false; common_hal_reset_pin(self->clock); common_hal_reset_pin(self->MOSI); common_hal_reset_pin(self->MISO); - self->clock = NULL; + spi_in_use[self->index] = false; if (self->index == 1 || @@ -149,7 +130,12 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { } else if (self->index == 2) { AUX->ENABLES_b.SPI_2 = false; } + } else { + // Set CS back to default. All 0 except read enable. + spi[self->index]->CS = SPI0_CS_REN_Msk; } + + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, @@ -200,6 +186,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; diff --git a/ports/broadcom/common-hal/busio/SPI.h b/ports/broadcom/common-hal/busio/SPI.h index aec91263677c0..3d52b6b0a4488 100644 --- a/ports/broadcom/common-hal/busio/SPI.h +++ b/ports/broadcom/common-hal/busio/SPI.h @@ -23,5 +23,3 @@ typedef struct { uint8_t bits; uint8_t index; } busio_spi_obj_t; - -void reset_spi(void); diff --git a/ports/broadcom/common-hal/microcontroller/__init__.c b/ports/broadcom/common-hal/microcontroller/__init__.c index b0ed1fcb9ec6f..279be26f91a37 100644 --- a/ports/broadcom/common-hal/microcontroller/__init__.c +++ b/ports/broadcom/common-hal/microcontroller/__init__.c @@ -11,6 +11,7 @@ #include "common-hal/microcontroller/__init__.h" #include "peripherals/broadcom/defines.h" #include "peripherals/broadcom/interrupts.h" +#include "supervisor/port.h" #include "mphalport.h" @@ -39,6 +40,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { } void common_hal_mcu_reset(void) { + reset_cpu(); } // The singleton microcontroller.Processor object, bound to microcontroller.cpu diff --git a/ports/broadcom/common-hal/os/__init__.c b/ports/broadcom/common-hal/os/__init__.c index 72a9a07e9077e..c1c50234451ef 100644 --- a/ports/broadcom/common-hal/os/__init__.c +++ b/ports/broadcom/common-hal/os/__init__.c @@ -10,33 +10,6 @@ #include "py/objtuple.h" #include "py/qstr.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; - -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_HW_MCU_NAME); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_HW_MCU_NAME); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) { return false; } diff --git a/ports/broadcom/common-hal/sdioio/SDCard.c b/ports/broadcom/common-hal/sdioio/SDCard.c index f87d40cd8dcab..2c9e6a2bb587a 100644 --- a/ports/broadcom/common-hal/sdioio/SDCard.c +++ b/ports/broadcom/common-hal/sdioio/SDCard.c @@ -11,6 +11,7 @@ #include "py/runtime.h" #include "common-hal/microcontroller/Pin.h" +#include "extmod/vfs.h" #include "shared-bindings/sdioio/SDCard.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" @@ -304,44 +305,95 @@ static void check_whole_block(mp_buffer_info_t *bufinfo) { } } -int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!self->init) { - return -EIO; + return -MP_EIO; } - check_whole_block(bufinfo); self->state_programming = true; COMPLETE_MEMORY_READS; - sdmmc_err_t error = sdmmc_write_sectors(&self->card_info, bufinfo->buf, - start_block, bufinfo->len / 512); + sdmmc_err_t error = sdmmc_write_sectors(&self->card_info, buf, + start_block, num_blocks); COMPLETE_MEMORY_READS; if (error != SDMMC_OK) { mp_printf(&mp_plat_print, "write sectors result %d\n", error); - return -EIO; + return -MP_EIO; } return 0; } -int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { if (!self->init) { - return -EIO; + return -MP_EIO; } check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (!self->init) { + return -MP_EIO; + } COMPLETE_MEMORY_READS; - sdmmc_err_t error = sdmmc_read_sectors(&self->card_info, bufinfo->buf, - start_block, bufinfo->len / 512); + sdmmc_err_t error = sdmmc_read_sectors(&self->card_info, buf, + start_block, num_blocks); COMPLETE_MEMORY_READS; if (error != SDMMC_OK) { - mp_printf(&mp_plat_print, "read sectors result %d when reading block %d for %d\n", error, start_block, bufinfo->len / 512); - return -EIO; + mp_printf(&mp_plat_print, "read sectors result %d when reading block %d for %d\n", error, start_block, num_blocks); + return -MP_EIO; } return 0; } +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + if (!self->init) { + return -MP_EIO; + } + check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, + mp_int_t *out_value) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + // SDIO operations are synchronous, no action needed + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdioio_sdcard_get_count(self); + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; // SD cards use 512-byte sectors + return true; + + default: + return false; // Unsupported command + } +} + bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) { if (!self->init) { return false; diff --git a/ports/broadcom/mpconfigport.h b/ports/broadcom/mpconfigport.h index b9990be75ec06..73fae8295ded2 100644 --- a/ports/broadcom/mpconfigport.h +++ b/ports/broadcom/mpconfigport.h @@ -13,8 +13,7 @@ #define CIRCUITPY_MCU_FAMILY broadcom #define MICROPY_PY_SYS_PLATFORM "BROADCOM" -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1) -#define MICROPY_PY_FUNCTION_ATTRS (1) + #if BCM_VERSION == 2837 || BCM_VERSION == 2711 #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A) #elif BCM_VERSION == 2835 @@ -27,6 +26,8 @@ #define MICROPY_FATFS_EXFAT (1) #define MICROPY_FATFS_MKFS_FAT32 (1) +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + //////////////////////////////////////////////////////////////////////////////////////////////////// // This also includes mpconfigboard.h. diff --git a/ports/broadcom/mpconfigport.mk b/ports/broadcom/mpconfigport.mk index 543e174683617..844794b107a21 100644 --- a/ports/broadcom/mpconfigport.mk +++ b/ports/broadcom/mpconfigport.mk @@ -22,6 +22,11 @@ CIRCUITPY_VIDEOCORE = 1 INTERNAL_FLASH_FILESYSTEM = 1 USB_NUM_ENDPOINT_PAIRS = 8 -USB_HIGHSPEED = 1 CIRCUITPY_BUILD_EXTENSIONS ?= disk.img.zip,kernel8.img + +ifeq ($(CHIP_VARIANT), "bcm2711") +CIRCUITPY_MIN_GCC_VERSION ?= 14 +else ifeq ($(CHIP_VARIANT), "bcm2837") +CIRCUITPY_MIN_GCC_VERSION ?= 14 +endif diff --git a/ports/broadcom/supervisor/port.c b/ports/broadcom/supervisor/port.c index 33b20b7c8647a..a0f0be30dd758 100644 --- a/ports/broadcom/supervisor/port.c +++ b/ports/broadcom/supervisor/port.c @@ -67,7 +67,6 @@ safe_mode_t port_init(void) { void reset_port(void) { #if CIRCUITPY_BUSIO reset_i2c(); - reset_spi(); reset_uart(); #endif @@ -85,8 +84,6 @@ void reset_port(void) { #if CIRCUITPY_AUDIOCORE audio_dma_reset(); #endif - - reset_all_pins(); } void reset_to_bootloader(void) { @@ -143,7 +140,11 @@ uint64_t port_get_raw_ticks(uint8_t *subticks) { } COMPLETE_MEMORY_READS; uint64_t microseconds = hi << 32 | lo; - return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977; + int64_t all_subticks = microseconds * 512 / 15625; + if (subticks != NULL) { + *subticks = all_subticks % 32; + } + return all_subticks / 32; } void TIMER_1_IRQHandler(void) { diff --git a/ports/cxd56/Makefile b/ports/cxd56/Makefile index 30abb8bb47fdf..88c3921022061 100644 --- a/ports/cxd56/Makefile +++ b/ports/cxd56/Makefile @@ -74,7 +74,7 @@ CFLAGS += \ -fdata-sections \ -Wall \ -OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions +OPTIMIZATION_FLAGS ?= -O2 # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk CFLAGS += $(OPTIMIZATION_FLAGS) @@ -110,15 +110,9 @@ LDFLAGS = \ CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_CXD56 -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_MIDI_TX_BUFSIZE=512 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=512 $(CFLAGS_MOD) -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) +SRC_S = shared/runtime/gchelper_thumb2.s -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -SRC_S = supervisor/cpu.s +SRC_C += shared/runtime/gchelper_native.c SRC_C += \ background.c \ @@ -129,8 +123,7 @@ SRC_C += \ OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif @@ -138,7 +131,7 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/cxd56/boards/spresense/mpconfigboard.h b/ports/cxd56/boards/spresense/mpconfigboard.h index 2d334ef29b301..c9510771b1855 100644 --- a/ports/cxd56/boards/spresense/mpconfigboard.h +++ b/ports/cxd56/boards/spresense/mpconfigboard.h @@ -18,5 +18,3 @@ #define DEFAULT_UART_BUS_RX (&pin_UART2_RXD) #define DEFAULT_UART_BUS_TX (&pin_UART2_TXD) - -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) diff --git a/ports/cxd56/common-hal/busio/I2C.c b/ports/cxd56/common-hal/busio/I2C.c index 4cfa3f8467df7..8e846b2402dc3 100644 --- a/ports/cxd56/common-hal/busio/I2C.c +++ b/ports/cxd56/common-hal/busio/I2C.c @@ -16,6 +16,10 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + if (frequency != I2C_SPEED_STANDARD && frequency != I2C_SPEED_FAST) { mp_arg_error_invalid(MP_QSTR_frequency); } @@ -44,13 +48,22 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { reset_pin_number(self->scl_pin->number); reset_pin_number(self->sda_pin->number); + + common_hal_busio_i2c_mark_deinit(self); } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { return self->i2c_dev == NULL; } +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->i2c_dev = NULL; +} + bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; @@ -78,7 +91,7 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { return I2C_TRANSFER(self->i2c_dev, &msg, 1) < 0 ? false : true; } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t address, const uint8_t *data, size_t len, bool stop) { +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t address, const uint8_t *data, size_t len, bool stop) { struct i2c_msg_s msg; msg.frequency = self->frequency; @@ -89,12 +102,12 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addre return -I2C_TRANSFER(self->i2c_dev, &msg, 1); } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address, uint8_t *data, size_t len) { +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address, uint8_t *data, size_t len) { struct i2c_msg_s msg; msg.frequency = self->frequency; @@ -105,9 +118,9 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address, uint8 return -I2C_TRANSFER(self->i2c_dev, &msg, 1); } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } diff --git a/ports/cxd56/common-hal/busio/SPI.c b/ports/cxd56/common-hal/busio/SPI.c index 2e4ffbbbd183d..6c49e0f275066 100644 --- a/ports/cxd56/common-hal/busio/SPI.c +++ b/ports/cxd56/common-hal/busio/SPI.c @@ -54,7 +54,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { return; } - self->spi_dev = NULL; + common_hal_busio_spi_mark_deinit(self); reset_pin_number(self->clock_pin->number); reset_pin_number(self->mosi_pin->number); @@ -65,6 +65,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->spi_dev == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->spi_dev = NULL; +} + bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { uint8_t mode; @@ -96,6 +100,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; diff --git a/ports/cxd56/common-hal/camera/Camera.c b/ports/cxd56/common-hal/camera/Camera.c index c3c935a168d42..b9fa2787ef767 100644 --- a/ports/cxd56/common-hal/camera/Camera.c +++ b/ports/cxd56/common-hal/camera/Camera.c @@ -44,7 +44,7 @@ static const image_size_t isx019_image_size_table[] = { { VIDEO_HSIZE_QUADVGA, VIDEO_VSIZE_QUADVGA }, }; -static const char *get_imgsensor_name() { +static const char *get_imgsensor_name(void) { static struct v4l2_capability cap; ioctl(camera_dev.fd, VIDIOC_QUERYCAP, (unsigned long)&cap); @@ -113,7 +113,7 @@ static void camera_start_streaming(enum v4l2_buf_type type) { ioctl(camera_dev.fd, VIDIOC_STREAMON, (unsigned long)&type); } -static void camera_start_preview() { +static void camera_start_preview(void) { camera_set_format(V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_PIX_FMT_UYVY, VIDEO_HSIZE_QVGA, VIDEO_VSIZE_QVGA); v4l2_buffer_t buf; diff --git a/ports/cxd56/common-hal/microcontroller/__init__.c b/ports/cxd56/common-hal/microcontroller/__init__.c index fa872f2807ba0..f7ac0c174ae07 100644 --- a/ports/cxd56/common-hal/microcontroller/__init__.c +++ b/ports/cxd56/common-hal/microcontroller/__init__.c @@ -61,6 +61,8 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { void common_hal_mcu_reset(void) { filesystem_flush(); boardctl(BOARDIOC_RESET, 0); + // boardctl is noreturn in this case. + __builtin_unreachable(); } static const mp_rom_map_elem_t mcu_pin_globals_table[] = { diff --git a/ports/cxd56/common-hal/os/__init__.c b/ports/cxd56/common-hal/os/__init__.c index 7d211b3a79d06..e1024108b07dc 100644 --- a/ports/cxd56/common-hal/os/__init__.c +++ b/ports/cxd56/common-hal/os/__init__.c @@ -10,32 +10,6 @@ #include "py/objstr.h" #include "py/objtuple.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; - -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "spresense"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "spresense"); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { uint32_t i = 0; diff --git a/ports/cxd56/common-hal/pulseio/PulseIn.c b/ports/cxd56/common-hal/pulseio/PulseIn.c index f0063d3f0d8c9..0c45cf850328b 100644 --- a/ports/cxd56/common-hal/pulseio/PulseIn.c +++ b/ports/cxd56/common-hal/pulseio/PulseIn.c @@ -65,7 +65,7 @@ static int pulsein_interrupt_handler(int irq, FAR void *context, FAR void *arg) void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/cxd56/common-hal/sdioio/SDCard.c b/ports/cxd56/common-hal/sdioio/SDCard.c index 05cc0fa1efe9a..227011a88710f 100644 --- a/ports/cxd56/common-hal/sdioio/SDCard.c +++ b/ports/cxd56/common-hal/sdioio/SDCard.c @@ -8,6 +8,7 @@ #include #include +#include "extmod/vfs.h" #include "py/mperrno.h" #include "py/runtime.h" @@ -91,26 +92,77 @@ uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) { static void check_whole_block(mp_buffer_info_t *bufinfo) { if (bufinfo->len % 512) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } } -int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + int result = self->inode->u.i_bops->read(self->inode, buf, start_block, num_blocks); + if (result < 0) { + return -MP_EIO; + } + return 0; +} + +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { if (common_hal_sdioio_sdcard_deinited(self)) { raise_deinited_error(); } check_whole_block(bufinfo); - return self->inode->u.i_bops->read(self->inode, bufinfo->buf, start_block, bufinfo->len / 512); + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); } -int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + int result = self->inode->u.i_bops->write(self->inode, buf, start_block, num_blocks); + if (result < 0) { + return -MP_EIO; + } + return 0; +} + +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { if (common_hal_sdioio_sdcard_deinited(self)) { raise_deinited_error(); } check_whole_block(bufinfo); - return self->inode->u.i_bops->write(self->inode, bufinfo->buf, start_block, bufinfo->len / 512); + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, + mp_int_t *out_value) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + // SDIO operations are synchronous, no action needed + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdioio_sdcard_get_count(self); + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; // SD cards use 512-byte sectors + return true; + + default: + return false; // Unsupported command + } } void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) { diff --git a/ports/cxd56/mkspk/clefia.c b/ports/cxd56/mkspk/clefia.c index e946ee5348a5a..d36f638fa0b0d 100644 --- a/ports/cxd56/mkspk/clefia.c +++ b/ports/cxd56/mkspk/clefia.c @@ -466,16 +466,16 @@ int clefiakeyset(unsigned char *rk, const unsigned char *skey) { void clefiaencrypt(unsigned char *ct, const unsigned char *pt, const unsigned char *rk, const int r) { - unsigned char rin[16]; + unsigned char r_in[16]; unsigned char rout[16]; - bytecpy(rin, pt, 16); + bytecpy(r_in, pt, 16); - bytexor(rin + 4, rin + 4, rk + 0, 4); /* initial key whitening */ - bytexor(rin + 12, rin + 12, rk + 4, 4); + bytexor(r_in + 4, r_in + 4, rk + 0, 4); /* initial key whitening */ + bytexor(r_in + 12, r_in + 12, rk + 4, 4); rk += 8; - clefiagfn4(rout, rin, rk, r); /* GFN_{4,r} */ + clefiagfn4(rout, r_in, rk, r); /* GFN_{4,r} */ bytecpy(ct, rout, 16); bytexor(ct + 4, ct + 4, rk + r * 8 + 0, 4); /* final key whitening */ diff --git a/ports/cxd56/mpconfigport.h b/ports/cxd56/mpconfigport.h index 3bcb252868786..ec606a76547bc 100644 --- a/ports/cxd56/mpconfigport.h +++ b/ports/cxd56/mpconfigport.h @@ -8,6 +8,9 @@ #define MICROPY_PY_SYS_PLATFORM "CXD56" +// SD card socket on board is configured for sdioio, which is not supported for automatic USB presentation. +#define CIRCUITPY_SDCARD_USB (0) + // 64kiB stack #define CIRCUITPY_DEFAULT_STACK_SIZE (0x10000) @@ -20,6 +23,8 @@ #define USB_MSC_EP_NUM_OUT (5) #define USB_MSC_EP_NUM_IN (4) +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + #include "py/circuitpy_mpconfig.h" #define MICROPY_BYTES_PER_GC_BLOCK (32) diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk index cb54233a07e51..ebfaa91f251ae 100644 --- a/ports/cxd56/mpconfigport.mk +++ b/ports/cxd56/mpconfigport.mk @@ -1,5 +1,3 @@ -USB_HIGHSPEED = 1 - # Number of USB endpoint pairs. USB_NUM_ENDPOINT_PAIRS = 6 diff --git a/ports/cxd56/supervisor/cpu.s b/ports/cxd56/supervisor/cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/cxd56/supervisor/cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/cxd56/supervisor/port.c b/ports/cxd56/supervisor/port.c index 237013ff2bdab..3dc54df96fbb5 100644 --- a/ports/cxd56/supervisor/port.c +++ b/ports/cxd56/supervisor/port.c @@ -66,8 +66,6 @@ void reset_port(void) { #if CIRCUITPY_RTC rtc_reset(); #endif - - reset_all_pins(); } void reset_to_bootloader(void) { @@ -124,7 +122,9 @@ void board_timerhook(void) { uint64_t port_get_raw_ticks(uint8_t *subticks) { uint64_t count = cxd56_rtc_count(); - *subticks = count % 32; + if (subticks != NULL) { + *subticks = count % 32; + } return count / 32; } diff --git a/ports/cxd56/tools/flash_writer.py b/ports/cxd56/tools/flash_writer.py index fc15cf8c28979..9c53e1b56c738 100755 --- a/ports/cxd56/tools/flash_writer.py +++ b/ports/cxd56/tools/flash_writer.py @@ -595,11 +595,11 @@ def main(): if subprocess.call("cd " + sys.path[0] + "; ./reset_board.sh", shell=True) == 0: print("auto reset board success!!") do_wait_reset = False - bootrom_msg = writer.cancel_autoboot() + writer.cancel_autoboot() if ConfigArgs.DTR_RESET: do_wait_reset = False - bootrom_msg = writer.cancel_autoboot() + writer.cancel_autoboot() if ConfigArgs.WAIT_RESET is False and do_wait_reset is True: rx = writer.recv() @@ -617,7 +617,7 @@ def main(): # Wait to reset the board print("Please press RESET button on target board") sys.stdout.flush() - bootrom_msg = writer.cancel_autoboot() + writer.cancel_autoboot() # Remove files if ConfigArgs.ERASE_NAME: diff --git a/ports/espressif/CMakeLists.txt b/ports/espressif/CMakeLists.txt index 2a34574db05b9..387a18dac094d 100644 --- a/ports/espressif/CMakeLists.txt +++ b/ports/espressif/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16) set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf) # The component list here determines what options we get in menuconfig and what the ninja file can build. -set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_spi esp_driver_tsens esp_driver_uart esp-tls esp_adc_cal esp_event esp_netif esp_psram esp_wifi esptool_py freertos log lwip main mbedtls mdns soc ulp usb wpa_supplicant esp-camera esp_lcd vfs esp_vfs_console) +set(COMPONENTS bt driver esp_driver_dac esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_i2s esp_driver_ledc esp_driver_pcnt esp_driver_rmt esp_driver_spi esp_driver_tsens esp_driver_uart esp-tls esp_adc_cal esp_event esp_netif esp_psram esp_wifi esptool_py freertos log lwip main mbedtls mdns soc ulp usb wpa_supplicant esp-camera esp_lcd vfs esp_vfs_console sdmmc) set(EXTRA_COMPONENT_DIRS "esp-protocols/components/mdns" "esp-camera") include($ENV{IDF_PATH}/tools/cmake/project.cmake) diff --git a/ports/espressif/Makefile b/ports/espressif/Makefile index c188092037bb8..2545b33d22a39 100644 --- a/ports/espressif/Makefile +++ b/ports/espressif/Makefile @@ -6,25 +6,10 @@ include ../../py/circuitpy_mkenv.mk -ifeq ($(IDF_TARGET),esp32c2) -IDF_TARGET_ARCH = riscv -CROSS_COMPILE = riscv32-esp-elf- -else ifeq ($(IDF_TARGET),esp32c3) -IDF_TARGET_ARCH = riscv -CROSS_COMPILE = riscv32-esp-elf- -else ifeq ($(IDF_TARGET),esp32c6) -IDF_TARGET_ARCH = riscv -CROSS_COMPILE = riscv32-esp-elf- -else ifeq ($(IDF_TARGET),esp32h2) -IDF_TARGET_ARCH = riscv -CROSS_COMPILE = riscv32-esp-elf- -else -IDF_TARGET_ARCH = xtensa -CROSS_COMPILE = xtensa-$(IDF_TARGET)-elf- -endif - ifeq ($(IDF_TARGET),esp32s3) BT_IDF_TARGET = esp32c3 +else ifeq ($(IDF_TARGET),esp32c61) +BT_IDF_TARGET = esp32c6 else BT_IDF_TARGET = $(IDF_TARGET) endif @@ -62,7 +47,6 @@ INC += \ -isystem esp-idf/components/bt/host/nimble/nimble/porting/nimble/include \ -isystem esp-idf/components/bt/host/nimble/nimble/porting/npl/freertos/include \ -isystem esp-idf/components/bt/host/nimble/port/include \ - -isystem esp-idf/components/driver/i2c/include \ -isystem esp-idf/components/driver/touch_sensor/include \ -isystem esp-idf/components/driver/touch_sensor/$(IDF_TARGET)/include \ -isystem esp-idf/components/driver/twai/include \ @@ -82,21 +66,30 @@ INC += \ -isystem esp-idf/components/esp_driver_i2s/include \ -isystem esp-idf/components/esp_driver_$(IDF_TARGET)/include \ -isystem esp-idf/components/esp_driver_ledc/include \ + -isystem esp-idf/components/esp_driver_parlio/include \ -isystem esp-idf/components/esp_driver_pcnt/include \ -isystem esp-idf/components/esp_driver_rmt/include \ + -isystem esp-idf/components/esp_driver_sdio/include \ + -isystem esp-idf/components/esp_driver_sdmmc/include \ -isystem esp-idf/components/esp_driver_spi/include \ -isystem esp-idf/components/esp_driver_tsens/include \ -isystem esp-idf/components/esp_driver_uart/include \ -isystem esp-idf/components/esp_event/include \ -isystem esp-idf/components/esp_hw_support/dma/include \ + -isystem esp-idf/components/esp_hw_support/ldo/include \ -isystem esp-idf/components/esp_hw_support/include \ -isystem esp-idf/components/esp_hw_support/include/soc \ + -isystem esp-idf/components/esp_hw_support/port/$(IDF_TARGET)/private_include \ + -isystem esp-idf/components/esp_mm/include \ -isystem esp-idf/components/esp_netif/include \ -isystem esp-idf/components/esp_partition/include \ -isystem esp-idf/components/esp_pm/include \ -isystem esp-idf/components/esp_psram/include \ -isystem esp-idf/components/esp_ringbuf/include \ -isystem esp-idf/components/esp_rom/include \ + -isystem esp-idf/components/esp_rom/$(IDF_TARGET)/include \ + -isystem esp-idf/components/esp_rom/$(IDF_TARGET)/include/$(IDF_TARGET) \ + -isystem esp-idf/components/esp_security/include \ -isystem esp-idf/components/esp_system/include \ -isystem esp-idf/components/esp_timer/include \ -isystem esp-idf/components/esp_wifi/include \ @@ -125,8 +118,14 @@ INC += \ -isystem esp-idf/components/mbedtls/port/include \ -isystem esp-idf/components/newlib/platform_include \ -isystem esp-idf/components/nvs_flash/include \ + -isystem esp-idf/components/sdio/include \ + -isystem esp-idf/components/sdmmc/include \ -isystem esp-idf/components/soc/include \ -isystem esp-idf/components/soc/$(IDF_TARGET)/include \ + -isystem esp-idf/components/soc/$(IDF_TARGET)/register \ + -isystem esp-idf/components/soc/$(IDF_TARGET)/register/hw_ver3 \ + -isystem esp-idf/components/soc/$(IDF_TARGET)/register/hw_ver2 \ + -isystem esp-idf/components/soc/$(IDF_TARGET)/register/hw_ver1 \ -isystem esp-idf/components/spi_flash/include \ -isystem esp-idf/components/usb/include \ -isystem esp-idf/components/ulp/ulp_fsm/include \ @@ -155,9 +154,10 @@ CFLAGS += -DSTACK_CANARY_VALUE=0xa5a5a5a5 # one must provide `-u` arguments to state the symbols are missing. This would # normally happen implicitly by another function calling to these. REGISTRATION_FUNCTIONS = \ - -u newlib_include_pthread_impl \ -u ld_include_highint_hdl \ -u __cxx_fatal_exception \ + -u __cxx_init_dummy \ + -u __cxa_guard_dummy \ -u esp_app_desc \ -u esp_timer_init_include_func \ -u uart_vfs_include_dev_init \ @@ -165,12 +165,19 @@ REGISTRATION_FUNCTIONS = \ -u __ubsan_include \ -u esp_system_include_startup_funcs \ -u esp_efuse_startup_include_func \ - -u newlib_include_heap_impl \ - -u newlib_include_syscalls_impl \ - -u newlib_include_pthread_impl \ - -u newlib_include_assert_impl \ - -u newlib_include_getentropy_impl \ - -u newlib_include_init_funcs + -u esp_libc_include_heap_impl \ + -u esp_libc_include_reent_syscalls_impl \ + -u esp_libc_include_syscalls_impl \ + -u esp_libc_include_pthread_impl \ + -u esp_libc_include_assert_impl \ + -u esp_libc_include_getentropy_impl \ + -u esp_libc_include_init_funcs \ + -u esp_libc_init_funcs \ + -u include_esp_phy_override \ + -u vfs_include_syscalls_impl \ + -u esp_vfs_include_nullfs_register \ + -u usb_serial_jtag_vfs_include_dev_init + #Debugging/Optimization ifeq ($(DEBUG), 1) @@ -182,12 +189,12 @@ ifeq ($(DEBUG), 1) OPTIMIZATION_FLAGS ?= -Og CFLAGS += -DDEBUG endif - # You may want to enable these flags to make setting breakpoints easier. - # CFLAGS += -fno-inline -fno-ipa-sra +# You may want to enable these flags to make setting breakpoints easier. +# CFLAGS += -fno-inline -fno-ipa-sra else CFLAGS += -DNDEBUG - # RISC-V is larger than xtensa - # Use -Os for RISC-V when it overflows +# RISC-V is larger than xtensa +# Use -Os for RISC-V when it overflows ifeq ($(IDF_TARGET_ARCH),riscv) OPTIMIZATION_FLAGS ?= -Os else @@ -198,12 +205,11 @@ endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk CFLAGS += $(OPTIMIZATION_FLAGS) -CFLAGS += $(INC) -Werror -Wall -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes +CFLAGS += $(INC) -Werror -Wall -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition # Most current ESPs have nano versions of newlib in ROM so we use them. ifneq ($(IDF_TARGET),esp32c6) CFLAGS += --specs=nano.specs - LDFLAGS += -T$(IDF_TARGET).rom.newlib-nano.ld else LDFLAGS += -T$(IDF_TARGET).rom.newlib-normal.ld endif @@ -212,15 +218,29 @@ ifeq ($(IDF_TARGET_ARCH),xtensa) # Remove the last two flags once TinyUSB is updated with the `#include ` instead of # `#include "xtensa/xtensa_api.h"`. -CFLAGS += -mlongcalls -isystem esp-idf/components/xtensa/deprecated_include/ -Wno-error=cpp + CFLAGS += -mlongcalls -isystem esp-idf/components/xtensa/deprecated_include/ -Wno-error=cpp + CFLAGS += -DMICROPY_GCREGS_SETJMP=1 + +# Wrap longjmp with a patched version that protects register window update with a critical section + LDFLAGS += -Wl,--wrap=longjmp + + SRC_C += shared/runtime/gchelper_generic.c else ifeq ($(IDF_TARGET_ARCH),riscv) -CFLAGS += -march=rv32imac_zicsr_zifencei -LDFLAGS += \ - -Lesp-idf/components/riscv/ld \ - -Trom.api.ld + + ifeq ($(IDF_TARGET),esp32p4) + CFLAGS += -march=rv32imafc_zicsr_zifencei_xesppie -mabi=ilp32f + else + CFLAGS += -march=rv32imac_zicsr_zifencei + endif + + LDFLAGS += \ + -Lesp-idf/components/riscv/ld \ + -Trom.api.ld + + SRC_C += shared/runtime/gchelper_native.c + SRC_S = shared/runtime/gchelper_rv32i.s endif -$(BUILD)/lib/tlsf/tlsf.o: CFLAGS += -Wno-cast-align LDFLAGS += $(CFLAGS) -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref -Wl,--undefined=uxTopUsedPriority @@ -242,8 +262,9 @@ LDFLAGS += \ ifeq ($(IDF_TARGET),esp32) LDFLAGS += \ -Tesp32.rom.newlib-data.ld \ - -Tesp32.rom.newlib-funcs.ld \ - -Tesp32.rom.newlib-time.ld \ + -Tesp32.rom.syscalls.ld \ + -Tesp32.rom.libc-funcs.ld \ + -Tesp32.rom.newlib-reent-funcs.ld \ -Tesp32.rom.spiflash_legacy.ld CHIP_COMPONENTS = \ @@ -251,8 +272,11 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32c2) LDFLAGS += \ + -Tesp32c2.rom.ble.ld \ -Tesp32c2.rom.heap.ld \ + -Tesp32c2.rom.libc.ld \ -Tesp32c2.rom.newlib.ld \ + -Tesp32c2.rom.newlib-nano.ld \ -Tesp32c2.rom.version.ld \ -Tesp32c2.rom.systimer.ld \ -Tesp32c2.rom.wdt.ld @@ -265,9 +289,11 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32c3) LDFLAGS += \ -Tesp32c3.rom.newlib.ld \ - -Tesp32c3.rom.newlib-time.ld \ + -Tesp32c3.rom.libc.ld \ -Tesp32c3.rom.version.ld \ - -Tesp32c3.rom.eco3.ld + -Tesp32c3.rom.eco3_bt_funcs.ld \ + -Tesp32c3.rom.eco3.ld \ + -Tesp32c3.rom.bt_funcs.ld CHIP_COMPONENTS = \ esp_driver_tsens @@ -277,6 +303,7 @@ LDFLAGS += \ -Tesp32c6.rom.phy.ld \ -Tesp32c6.rom.pp.ld \ -Tesp32c6.rom.net80211.ld \ + -Tesp32c6.rom.libc.ld \ -Tesp32c6.rom.newlib.ld \ -Tesp32c6.rom.coexist.ld \ -Tesp32c6.rom.heap.ld \ @@ -287,9 +314,39 @@ LDFLAGS += \ CHIP_COMPONENTS = \ esp_driver_tsens +else ifeq ($(IDF_TARGET),esp32c61) +LDFLAGS += \ + -Tesp32c61.rom.phy.ld \ + -Tesp32c61.rom.pp.ld \ + -Tesp32c61.rom.net80211.ld \ + -Tesp32c61.rom.libc.ld \ + -Tesp32c61.rom.newlib.ld \ + -Tesp32c61.rom.version.ld \ + -Tesp32c61.rom.coexist.ld \ + -Tesp32c61.rom.heap.ld \ + -Tesp32c61.rom.systimer.ld \ + -Tesp32c61.rom.wdt.ld + + +CHIP_COMPONENTS = \ + esp_driver_tsens + +else ifeq ($(IDF_TARGET),esp32p4) +LDFLAGS += \ + -Tesp32p4.rom.libc.ld \ + -Tesp32p4.rom.newlib.ld \ + -Tesp32p4.rom.systimer.ld \ + -Tesp32p4.rom.wdt.ld + + +CHIP_COMPONENTS = \ + esp_driver_tsens \ + esp_driver_usb_serial_jtag + else ifeq ($(IDF_TARGET),esp32h2) LDFLAGS += \ -Tesp32h2.rom.heap.ld \ + -Tesp32h2.rom.libc.ld \ -Tesp32h2.rom.newlib.ld \ -Tesp32h2.rom.systimer.ld \ -Tesp32h2.rom.wdt.ld @@ -299,9 +356,9 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32s2) LDFLAGS += \ + -Tesp32s2.rom.libc-funcs.ld \ -Tesp32s2.rom.newlib-data.ld \ - -Tesp32s2.rom.newlib-funcs.ld \ - -Tesp32s2.rom.newlib-time.ld \ + -Tesp32s2.rom.newlib-reent-funcs.ld \ -Tesp32s2.rom.spiflash_legacy.ld CHIP_COMPONENTS = \ @@ -310,11 +367,12 @@ CHIP_COMPONENTS = \ else ifeq ($(IDF_TARGET),esp32s3) LDFLAGS += \ + -Tesp32s3.rom.libc.ld \ -Tesp32s3.rom.newlib.ld \ - -Tesp32s3.rom.newlib-time.ld \ -Tesp32s3.rom.version.ld \ -Tesp32s3.rom.systimer.ld \ - -Tesp32s3.rom.wdt.ld + -Tesp32s3.rom.wdt.ld \ + -Tesp32s3.rom.bt_funcs.ld CHIP_COMPONENTS = \ esp_driver_tsens @@ -338,6 +396,10 @@ else ifeq ($(IDF_TARGET),esp32c3) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C3 else ifeq ($(IDF_TARGET),esp32c6) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C6 +else ifeq ($(IDF_TARGET),esp32c61) +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32C61 +else ifeq ($(IDF_TARGET),esp32p4) +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32P4 else ifeq ($(IDF_TARGET),esp32h2) CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32H2 else ifeq ($(IDF_TARGET),esp32s2) @@ -351,10 +413,19 @@ CFLAGS += \ -DCFG_TUD_TASK_QUEUE_SZ=32 endif ifeq ($(CIRCUITPY_USB_DEVICE),1) +ifeq ($(IDF_TARGET),esp32s2) +# Make more room in internal RAM on the S2. +CFLAGS += \ + -DCFG_TUD_CDC_RX_BUFSIZE=128 \ + -DCFG_TUD_CDC_TX_BUFSIZE=128 \ + -DCFG_TUD_MSC_BUFSIZE=1024 +else CFLAGS += \ -DCFG_TUD_CDC_RX_BUFSIZE=1024 \ -DCFG_TUD_CDC_TX_BUFSIZE=1024 \ - -DCFG_TUD_MSC_BUFSIZE=4096 \ + -DCFG_TUD_MSC_BUFSIZE=4096 +endif +CFLAGS += \ -DCFG_TUD_MIDI_RX_BUFSIZE=128 \ -DCFG_TUD_MIDI_TX_BUFSIZE=128 \ -DCFG_TUD_VENDOR_RX_BUFSIZE=128 \ @@ -371,11 +442,10 @@ SRC_C += \ boards/$(BOARD)/board.c \ boards/$(BOARD)/pins.c \ shared/netutils/netutils.c \ - peripherals/i2c.c \ peripherals/$(IDF_TARGET)/pins.c ifeq ($(CIRCUITPY_SSL),1) -SRC_C += lib/mbedtls_config/crt_bundle.c +SRC_C += common-hal/ssl/crt_bundle.c endif SRC_C += $(wildcard common-hal/espidf/*.c) @@ -389,14 +459,16 @@ SRC_C += peripherals/touch.c endif ifneq ($(CIRCUITPY_USB_DEVICE),0) -SRC_C += lib/tinyusb/src/portable/espressif/esp32sx/dcd_esp32sx.c +SRC_C += \ + lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c \ + lib/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c endif ifneq ($(CIRCUITPY_AUDIOBUSIO),0) CHIP_COMPONENTS += esp_driver_i2s endif -ifneq ($(CIRCUITPY_BLEIO),0) +ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) SRC_C += common-hal/_bleio/ble_events.c endif @@ -407,6 +479,13 @@ CFLAGS += \ -isystem esp-idf/components/esp_lcd/rgb/include endif +ifneq ($(CIRCUITPY_MIPIDSI),0) +CFLAGS += \ + -isystem esp-idf/components/esp_lcd/include \ + -isystem esp-idf/components/esp_lcd/interface \ + -isystem esp-idf/components/esp_lcd/dsi/include +endif + ifneq ($(CIRCUITPY_ESPCAMERA),0) SRC_CAMERA := \ $(wildcard common-hal/espcamera/*.c) \ @@ -416,6 +495,55 @@ CFLAGS += -isystem esp-camera/driver/include CFLAGS += -isystem esp-camera/conversions/include endif +ifneq ($(CIRCUITPY_RCLCPY),0) +CFLAGS += -isystem microros-lib/include +CFLAGS += -isystem microros-lib/include/rcl +CFLAGS += -isystem microros-lib/include/statistics_msgs +CFLAGS += -isystem microros-lib/include/composition_interfaces +CFLAGS += -isystem microros-lib/include/example_interfaces +CFLAGS += -isystem microros-lib/include/rmw_microxrcedds_c +CFLAGS += -isystem microros-lib/include/test_msgs +CFLAGS += -isystem microros-lib/include/std_msgs +CFLAGS += -isystem microros-lib/include/rcutils +CFLAGS += -isystem microros-lib/include/lifecycle_msgs +CFLAGS += -isystem microros-lib/include/rosidl_typesupport_interface +CFLAGS += -isystem microros-lib/include/service_msgs +CFLAGS += -isystem microros-lib/include/visualization_msgs +CFLAGS += -isystem microros-lib/include/rosidl_dynamic_typesupport +CFLAGS += -isystem microros-lib/include/stereo_msgs +CFLAGS += -isystem microros-lib/include/ucdr +CFLAGS += -isystem microros-lib/include/rosidl_typesupport_c +CFLAGS += -isystem microros-lib/include/std_srvs +CFLAGS += -isystem microros-lib/include/rcl_lifecycle +CFLAGS += -isystem microros-lib/include/action_msgs +CFLAGS += -isystem microros-lib/include/micro_ros_utilities +CFLAGS += -isystem microros-lib/include/rcl_action +CFLAGS += -isystem microros-lib/include/rcl_logging_interface +CFLAGS += -isystem microros-lib/include/type_description_interfaces +CFLAGS += -isystem microros-lib/include/nav_msgs +CFLAGS += -isystem microros-lib/include/actionlib_msgs +CFLAGS += -isystem microros-lib/include/rmw +CFLAGS += -isystem microros-lib/include/rclc_parameter +CFLAGS += -isystem microros-lib/include/geometry_msgs +CFLAGS += -isystem microros-lib/include/sensor_msgs +CFLAGS += -isystem microros-lib/include/trajectory_msgs +CFLAGS += -isystem microros-lib/include/shape_msgs +CFLAGS += -isystem microros-lib/include/rosidl_runtime_c +CFLAGS += -isystem microros-lib/include/rclc +CFLAGS += -isystem microros-lib/include/rosgraph_msgs +CFLAGS += -isystem microros-lib/include/rclc_lifecycle +CFLAGS += -isystem microros-lib/include/rcl_interfaces +CFLAGS += -isystem microros-lib/include/diagnostic_msgs +CFLAGS += -isystem microros-lib/include/micro_ros_msgs +CFLAGS += -isystem microros-lib/include/rosidl_typesupport_introspection_c +CFLAGS += -isystem microros-lib/include/uxr +CFLAGS += -isystem microros-lib/include/unique_identifier_msgs +CFLAGS += -isystem microros-lib/include/rosidl_typesupport_microxrcedds_c +CFLAGS += -isystem microros-lib/include/builtin_interfaces +CFLAGS += -isystem microros-lib/include/tracetools +CFLAGS += -isystem microros-lib/include/rmw_microros +endif + ifneq ($(CIRCUITPY_ESPIDF),0) SRC_ESPIDF := \ $(wildcard common-hal/espidf/*.c) \ @@ -461,29 +589,19 @@ ifneq ($(CIRCUITPY_FREQUENCYIO),0) CHIP_COMPONENTS += esp_driver_pcnt endif -SRC_COMMON_HAL_EXPANDED = \ - $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = \ - $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - ifneq ($(FROZEN_MPY_DIR),) FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) endif OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os @@ -491,7 +609,7 @@ $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os $(BUILD)/lib/protomatter/src/core.o: CFLAGS += -DESP32 # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # IDF build commands IDF_PATH = $(realpath ./esp-idf) @@ -502,24 +620,34 @@ $(BUILD)/esp-idf: TARGET_SDKCONFIG = esp-idf-config/sdkconfig-$(IDF_TARGET).defaults +# Choose the correct partition layout, based on UF2 or not, flash size, etc. +UF2_BOOTLOADER ?= $(CIRCUITPY_USB_DEVICE) + ifeq ($(CIRCUITPY_ESP_FLASH_SIZE), 2MB) +# ..... No 2MB UF2 boards, so always no OTA, not UF2 FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota-no-uf2.defaults -else -UF2_BOOTLOADER ?= $(CIRCUITPY_USB_DEVICE) -ifeq ($(UF2_BOOTLOADER), 1) - FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE).defaults -else -ifeq ($(CIRCUITPY_ESP_FLASH_SIZE), 4MB) - ifeq ($(CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT), 1) - FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-uf2.defaults +else ifeq ($(CIRCUITPY_ESP_FLASH_SIZE), 4MB) + ifeq ($(UF2_BOOTLOADER), 1) +#............. ESP32-S2 and ESP32-S3 do not have an extra ota partition for OTA update. + FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota.defaults else - FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota-no-uf2.defaults +# ............. Non-UF2 4MB: C3, C6, etc. + ifeq ($(CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT), 1) +# .................... Some boards use a 2MB firmware and almost 2MB user filesystem, for historical reasons. + FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota-no-uf2-large-user_fs.defaults + else + FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota-no-uf2.defaults + endif endif else - FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-uf2.defaults -endif -endif +# ..... All the rest are >4MB flash + ifeq ($(UF2_BOOTLOADER), 1) + FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE).defaults + else + FLASH_SIZE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-uf2.defaults + endif endif + FLASH_MODE_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_MODE).defaults FLASH_SPEED_SDKCONFIG ?= esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_FREQ).defaults @@ -536,8 +664,12 @@ else DEBUG_SDKCONFIG = esp-idf-config/sdkconfig-opt.defaults endif +ifeq ($(ENABLE_JTAG), 1) + CFLAGS += -DENABLE_JTAG=1 +endif + SDKCONFIGS := esp-idf-config/sdkconfig.defaults;$(DEBUG_SDKCONFIG);$(FLASH_SIZE_SDKCONFIG);$(FLASH_MODE_SDKCONFIG);$(FLASH_SPEED_SDKCONFIG);$(PSRAM_SDKCONFIG);$(PSRAM_SIZE_SDKCONFIG);$(PSRAM_MODE_SDKCONFIG);$(PSRAM_SPEED_SDKCONFIG);$(TARGET_SDKCONFIG);boards/$(BOARD)/sdkconfig -ifneq ($(CIRCUITPY_BLEIO),0) +ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) SDKCONFIGS := esp-idf-config/sdkconfig-ble.defaults;$(SDKCONFIGS) endif # create the config headers @@ -578,9 +710,13 @@ update-board-sdkconfig: $(BUILD)/esp-idf/config/sdkconfig.h python tools/update_sdkconfig.py --board=$(BOARD) --debug=$(DEBUG) BINARY_WIFI_BLOBS = libcore.a libespnow.a libnet80211.a libpp.a libsmartconfig.a -BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a + +ifneq ($(IDF_TARGET),esp32p4) + BINARY_BLOBS = esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libphy.a +endif ifneq ($(CIRCUITPY_WIFI),0) - BINARY_BLOBS += esp-idf/components/esp_coex/lib/$(IDF_TARGET)/libcoexist.a $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) + BINARY_BLOBS += $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, $(BINARY_WIFI_BLOBS)) + BINARY_BLOBS += esp-idf/components/esp_coex/lib/$(IDF_TARGET)/libcoexist.a ifneq ($(IDF_TARGET),esp32c2) BINARY_BLOBS += $(addprefix esp-idf/components/esp_wifi/lib/$(IDF_TARGET)/, libmesh.a libwapi.a) endif @@ -590,23 +726,24 @@ ifeq ($(IDF_TARGET),esp32) BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/librtc.a endif -ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_gpio esp_driver_gptimer esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_hw_support esp_mm esp_partition esp_phy esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log newlib nvs_flash pthread soc spi_flash vfs esp_vfs_console +ESP_IDF_COMPONENTS_LINK = $(IDF_TARGET_ARCH) $(CHIP_COMPONENTS) app_update bootloader_support driver esp_driver_gpio esp_driver_gptimer esp_driver_i2c esp_driver_ledc esp_driver_spi esp_driver_uart efuse esp_adc esp_app_format esp_common esp_event esp_hw_support esp_mm esp_partition esp_pm esp_ringbuf esp_rom esp_system esp_timer freertos hal heap log newlib nvs_flash pthread soc spi_flash vfs esp_vfs_console ifneq ($(CIRCUITPY_WIFI),0) - ESP_IDF_COMPONENTS_LINK += esp_coex esp_netif esp-tls esp_wifi lwip mbedtls mdns wpa_supplicant + ESP_IDF_COMPONENTS_LINK += esp_coex esp_netif esp_security esp-tls esp_wifi lwip mbedtls mdns wpa_supplicant esp_phy endif -ifneq ($(CIRCUITPY_BLEIO),0) +ifneq ($(CIRCUITPY_BLEIO_NATIVE),0) BLE_IMPL_esp32 := esp32 BLE_IMPL_esp32s3 := esp32c3 BLE_IMPL_esp32c2 := libble BLE_IMPL_esp32c3 := esp32c3 BLE_IMPL_esp32c6 := libble + BLE_IMPL_esp32c61 := libble BLE_IMPL_esp32h2 := libble BLE_IMPL = $(BLE_IMPL_$(IDF_TARGET)) - ESP_IDF_COMPONENTS_LINK += bt + ESP_IDF_COMPONENTS_LINK += bt esp_phy esp_security ifeq ($(BLE_IMPL),esp32) - # BLE will hang the ESP32 and trigger an interrupt watchdog without this undefined symbol at - # link because a weak version of the interrupt that BLE uses will be linked incorrectly. +# BLE will hang the ESP32 and trigger an interrupt watchdog without this undefined symbol at +# link because a weak version of the interrupt that BLE uses will be linked incorrectly. REGISTRATION_FUNCTIONS += -u ld_include_hli_vectors_bt BINARY_BLOBS += esp-idf/components/bt/controller/lib_esp32/$(IDF_TARGET)/libbtdm_app.a endif @@ -617,9 +754,16 @@ ifneq ($(CIRCUITPY_BLEIO),0) endif ifeq ($(BLE_IMPL),libble) - BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a \ - esp-idf/components/bt/controller/lib_$(IDF_TARGET)/$(IDF_TARGET)-bt-lib/libble_app.a + BINARY_BLOBS += esp-idf/components/esp_phy/lib/$(IDF_TARGET)/libbtbb.a + ifeq ($(BT_IDF_TARGET),esp32c6) + BINARY_BLOBS += esp-idf/components/bt/controller/lib_$(BT_IDF_TARGET)/$(BT_IDF_TARGET)-bt-lib/$(IDF_TARGET)/libble_app.a + else + BINARY_BLOBS += esp-idf/components/bt/controller/lib_$(IDF_TARGET)/$(IDF_TARGET)-bt-lib/libble_app.a endif + endif +endif +ifeq ($(IDF_TARGET),esp32p4) + ESP_IDF_COMPONENTS_LINK += esp_security endif ifneq ($(CIRCUITPY_ESPULP),0) ESP_IDF_COMPONENTS_LINK += ulp @@ -630,12 +774,21 @@ endif ifneq ($(CIRCUITPY_DOTCLOCKFRAMEBUFFER),0) ESP_IDF_COMPONENTS_LINK += esp_lcd endif +ifneq ($(CIRCUITPY_MIPIDSI),0) + ESP_IDF_COMPONENTS_LINK += esp_lcd +endif ifneq ($(CIRCUITPY_PARALLELDISPLAYBUS),0) ESP_IDF_COMPONENTS_LINK += esp_lcd endif +ifneq ($(CIRCUITPY_QSPIBUS),0) + ESP_IDF_COMPONENTS_LINK += esp_lcd +endif ifneq ($(CIRCUITPY_USB_DEVICE),0) ESP_IDF_COMPONENTS_LINK += usb endif +ifneq ($(CIRCUITPY_SDIOIO),0) + ESP_IDF_COMPONENTS_LINK += sdmmc esp_driver_sdmmc +endif ESP_IDF_COMPONENTS_EXPANDED = $(foreach component, $(ESP_IDF_COMPONENTS_LINK), $(BUILD)/esp-idf/esp-idf/$(component)/lib$(component).a) @@ -652,6 +805,18 @@ ESP_IDF_COMPONENTS_EXPANDED += $(BUILD)/esp-idf/esp-idf/esp-camera/libesp-camera #$(error $(ESP_IDF_COMPONENTS_EXPANDED)) endif +ifneq ($(CIRCUITPY_RCLCPY),0) + ifeq ($(IDF_TARGET),esp32) + BINARY_BLOBS += microros-lib/esp32/libmicroros.a + else ifeq ($(IDF_TARGET),esp32s2) + BINARY_BLOBS+= microros-lib/esp32s2/libmicroros.a + else ifeq ($(IDF_TARGET),esp32s3) + BINARY_BLOBS += microros-lib/esp32s3/libmicroros.a + else + $(error Unsupported Espressif target for Micro-ROS: $(IDF_TARGET).) + endif +endif + ifneq ($(VALID_BOARD),) # From esp-idf/components/bootloader/Kconfig.projbuild # BOOTLOADER_OFFSET is determined by chip type, based on the ROM bootloader, and is not changeable. @@ -665,6 +830,10 @@ else ifeq ($(IDF_TARGET),esp32c3) BOOTLOADER_OFFSET = 0x0 else ifeq ($(IDF_TARGET),esp32c6) BOOTLOADER_OFFSET = 0x0 +else ifeq ($(IDF_TARGET),esp32c61) +BOOTLOADER_OFFSET = 0x0 +else ifeq ($(IDF_TARGET),esp32p4) +BOOTLOADER_OFFSET = 0x2000 else ifeq ($(IDF_TARGET),esp32s3) BOOTLOADER_OFFSET = 0x0 else ifeq ($(IDF_TARGET),esp32s2) @@ -676,7 +845,7 @@ endif IDF_CMAKE_TARGETS = \ bootloader/bootloader.bin \ - esp-idf/esp_system/__ldgen_output_sections.ld \ + __ldgen_output_sections.ld \ $(foreach component, $(ESP_IDF_COMPONENTS_LINK), esp-idf/$(component)/lib$(component).a) PARTITION_TABLE_OFFSET = 0x8000 @@ -735,6 +904,7 @@ endif UF2_FAMILY_ID_esp32s2 = 0xbfdd4eee UF2_FAMILY_ID_esp32s3 = 0xc47e5767 +UF2_FAMILY_ID_esp32p4 = 0x540ddf62 $(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin $(STEPECHO) "Create $@" diff --git a/ports/espressif/README.rst b/ports/espressif/README.rst index 93b793657724f..fe5542aafe46f 100644 --- a/ports/espressif/README.rst +++ b/ports/espressif/README.rst @@ -14,6 +14,7 @@ Support Status: ESP32-C2, "alpha" ESP32-C3, "beta" ESP32-C6, "alpha" + ESP32-P4, "alpha" ESP32-S2, "stable" ESP32-S3, "stable" @@ -221,4 +222,3 @@ And follow the Espressif GDB tutorial `instructions for connecting base.type = &espcamera_camera_type; + espcamera_camera_obj_t *self = mp_obj_malloc_with_finaliser(espcamera_camera_obj_t, &espcamera_camera_type); common_hal_espcamera_camera_construct( self, data_pins, @@ -144,6 +145,7 @@ static mp_obj_t espcamera_camera_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the camera and releases all memory resources for reuse.""" //| ... +//| static mp_obj_t espcamera_camera_deinit(mp_obj_t self_in) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_espcamera_camera_deinit(self); @@ -160,20 +162,19 @@ static void check_for_deinit(espcamera_camera_obj_t *self) { //| def __enter__(self) -> Camera: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t espcamera_camera_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return espcamera_camera_deinit(args[0]); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espcamera_camera___exit___obj, 4, 4, espcamera_camera_obj___exit__); +//| +// Provided by context manager helper. //| frame_available: bool //| """True if a frame is available, False otherwise""" +//| static mp_obj_t espcamera_camera_frame_available_get(const mp_obj_t self_in) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -194,6 +195,7 @@ MP_PROPERTY_GETTER(espcamera_camera_frame_available_obj, //| If `pixel_format` is `PixelFormat.JPEG`, the returned value is a read-only `memoryview`. //| Otherwise, the returned value is a read-only `displayio.Bitmap`. //| """ +//| static mp_obj_t espcamera_camera_take(size_t n_args, const mp_obj_t *args) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_float_t timeout = n_args < 2 ? MICROPY_FLOAT_CONST(0.25) : mp_obj_get_float(args[1]); @@ -230,6 +232,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espcamera_camera_take_obj, 1, 2, espc //| the other properties to set, they are set together in a single function call. //| //| If an argument is unspecified or None, then the setting is unchanged.""" +//| static mp_obj_t espcamera_camera_reconfigure(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -258,7 +261,7 @@ static mp_obj_t espcamera_camera_reconfigure(mp_uint_t n_args, const mp_obj_t *p args[ARG_grab_mode].u_obj != MP_ROM_NONE ? validate_grab_mode(args[ARG_grab_mode].u_obj, MP_QSTR_grab_mode) : common_hal_espcamera_camera_get_grab_mode(self); - bool framebuffer_count = + mp_int_t framebuffer_count = args[ARG_framebuffer_count].u_obj != MP_ROM_NONE ? mp_obj_get_int(args[ARG_framebuffer_count].u_obj) : common_hal_espcamera_camera_get_framebuffer_count(self); @@ -913,6 +916,7 @@ MP_PROPERTY_GETTER(espcamera_camera_grab_mode_obj, //| framebuffer_count: int //| """True if double buffering is used""" //| +//| static mp_obj_t espcamera_camera_get_framebuffer_count(const mp_obj_t self_in) { espcamera_camera_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -940,8 +944,8 @@ static const mp_rom_map_elem_t espcamera_camera_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_denoise), MP_ROM_PTR(&espcamera_camera_denoise_obj) }, { MP_ROM_QSTR(MP_QSTR_framebuffer_count), MP_ROM_PTR(&espcamera_camera_framebuffer_count_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&espcamera_camera_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espcamera_camera___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_exposure_ctrl), MP_ROM_PTR(&espcamera_camera_exposure_ctrl_obj) }, { MP_ROM_QSTR(MP_QSTR_frame_available), MP_ROM_PTR(&espcamera_camera_frame_available_obj) }, { MP_ROM_QSTR(MP_QSTR_frame_size), MP_ROM_PTR(&espcamera_camera_frame_size_obj) }, diff --git a/ports/espressif/bindings/espcamera/__init__.c b/ports/espressif/bindings/espcamera/__init__.c index 3443ccee42ba9..dbdb0ffb481ee 100644 --- a/ports/espressif/bindings/espcamera/__init__.c +++ b/ports/espressif/bindings/espcamera/__init__.c @@ -26,6 +26,7 @@ //| //| """ //| +//| //| class GrabMode: //| """Controls when a new frame is grabbed.""" @@ -36,6 +37,7 @@ //| LATEST: GrabMode //| """Except when 1 frame buffer is used, queue will always contain the last ``fb_count`` frames""" //| +//| MAKE_ENUM_VALUE(espcamera_grab_mode_type, grab_mode, WHEN_EMPTY, CAMERA_GRAB_WHEN_EMPTY); MAKE_ENUM_VALUE(espcamera_grab_mode_type, grab_mode, LATEST, CAMERA_GRAB_LATEST); @@ -65,6 +67,7 @@ camera_grab_mode_t validate_grab_mode(mp_obj_t obj, qstr arg_name) { //| JPEG: PixelFormat //| """A compressed format""" //| +//| MAKE_ENUM_VALUE(espcamera_pixel_format_type, pixel_format, RGB565, PIXFORMAT_RGB565); MAKE_ENUM_VALUE(espcamera_pixel_format_type, pixel_format, GRAYSCALE, PIXFORMAT_GRAYSCALE); @@ -153,6 +156,7 @@ pixformat_t validate_pixel_format(mp_obj_t obj, qstr arg_name) { //| QSXGA: FrameSize //| """2560x1920""" //| +//| MAKE_ENUM_VALUE(espcamera_frame_size_type, frame_size, R96X96, FRAMESIZE_96X96); MAKE_ENUM_VALUE(espcamera_frame_size_type, frame_size, R240X240, FRAMESIZE_240X240); @@ -222,6 +226,7 @@ framesize_t validate_frame_size(mp_obj_t obj, qstr arg_name) { //| GAIN_64X: GainCeiling //| GAIN_128X: GainCeiling //| +//| MAKE_ENUM_VALUE(espcamera_gain_ceiling_type, gain_ceiling, GAIN_2X, GAINCEILING_2X); MAKE_ENUM_VALUE(espcamera_gain_ceiling_type, gain_ceiling, GAIN_4X, GAINCEILING_4X); diff --git a/ports/espressif/bindings/espidf/__init__.c b/ports/espressif/bindings/espidf/__init__.c index 3d6321017f2e7..897da0eb5717b 100644 --- a/ports/espressif/bindings/espidf/__init__.c +++ b/ports/espressif/bindings/espidf/__init__.c @@ -20,11 +20,13 @@ //| that could be implemented by other frameworks. It should only include ESP-IDF specific //| things.""" //| +//| //| def heap_caps_get_total_size() -> int: //| """Return the total size of the ESP-IDF, which includes the CircuitPython heap.""" //| ... //| +//| static mp_obj_t espidf_heap_caps_get_total_size(void) { return MP_OBJ_NEW_SMALL_INT(heap_caps_get_total_size(MALLOC_CAP_8BIT)); @@ -35,6 +37,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(espidf_heap_caps_get_total_size_obj, espidf_heap_caps_ //| """Return total free memory in the ESP-IDF heap.""" //| ... //| +//| static mp_obj_t espidf_heap_caps_get_free_size(void) { return MP_OBJ_NEW_SMALL_INT(heap_caps_get_free_size(MALLOC_CAP_8BIT)); @@ -45,6 +48,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(espidf_heap_caps_get_free_size_obj, espidf_heap_caps_g //| """Return the size of largest free memory block in the ESP-IDF heap.""" //| ... //| +//| static mp_obj_t espidf_heap_caps_get_largest_free_block(void) { return MP_OBJ_NEW_SMALL_INT(heap_caps_get_largest_free_block(MALLOC_CAP_8BIT)); @@ -58,6 +62,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(espidf_heap_caps_get_largest_free_block_obj, espidf_he //| layout of data in nvs has changed. The old data will be lost when you perform this operation. //| """ //| +//| static mp_obj_t espidf_erase_nvs(void) { ESP_ERROR_CHECK(nvs_flash_deinit()); ESP_ERROR_CHECK(nvs_flash_erase()); @@ -84,6 +89,7 @@ static void espidf_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr //| //| ... //| +//| MP_DEFINE_CONST_OBJ_TYPE( mp_type_espidf_IDFError, MP_QSTR_IDFError, @@ -99,7 +105,8 @@ MP_DEFINE_CONST_OBJ_TYPE( //| //| ... //| -NORETURN void mp_raise_espidf_MemoryError(void) { +//| +MP_NORETURN void mp_raise_espidf_MemoryError(void) { nlr_raise(mp_obj_new_exception(&mp_type_espidf_MemoryError)); } @@ -116,6 +123,7 @@ MP_DEFINE_CONST_OBJ_TYPE( //| def get_total_psram() -> int: //| """Returns the number of bytes of psram detected, or 0 if psram is not present or not configured""" //| +//| static mp_obj_t espidf_get_total_psram(void) { return MP_OBJ_NEW_SMALL_INT(common_hal_espidf_get_total_psram()); } diff --git a/ports/espressif/bindings/espidf/__init__.h b/ports/espressif/bindings/espidf/__init__.h index 7c112abf7368c..92d2e0c276931 100644 --- a/ports/espressif/bindings/espidf/__init__.h +++ b/ports/espressif/bindings/espidf/__init__.h @@ -15,9 +15,9 @@ extern const mp_obj_type_t mp_type_espidf_IDFError; extern const mp_obj_type_t mp_type_espidf_MemoryError; -NORETURN void mp_raise_espidf_MemoryError(void); +MP_NORETURN void mp_raise_espidf_MemoryError(void); -void raise_esp_error(esp_err_t err) NORETURN; +void raise_esp_error(esp_err_t err) MP_NORETURN; #define CHECK_ESP_RESULT(x) do { int res = (x); if (res != ESP_OK) raise_esp_error(res); } while (0) size_t common_hal_espidf_get_total_psram(void); diff --git a/ports/espressif/bindings/espnow/ESPNow.c b/ports/espressif/bindings/espnow/ESPNow.c index 80dfac93c12f2..01cc06e3be48e 100644 --- a/ports/espressif/bindings/espnow/ESPNow.c +++ b/ports/espressif/bindings/espnow/ESPNow.c @@ -12,6 +12,7 @@ #include "py/stream.h" #include "shared-bindings/util.h" +#include "shared/runtime/context_manager_helpers.h" #include "bindings/espnow/ESPNow.h" #include "bindings/espnow/Peer.h" @@ -41,6 +42,7 @@ static void espnow_check_for_deinit(espnow_obj_t *self) { //| `wifi_phy_rate_t `_ //| """ //| ... +//| static mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer_size, ARG_phy_rate }; static const mp_arg_t allowed_args[] = { @@ -71,6 +73,7 @@ static mp_obj_t espnow_make_new(const mp_obj_type_t *type, size_t n_args, size_t //| def deinit(self) -> None: //| """Deinitializes ESP-NOW and releases it for another program.""" //| ... +//| static mp_obj_t espnow_deinit(mp_obj_t self_in) { espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); espnow_check_for_deinit(self); @@ -82,17 +85,15 @@ static MP_DEFINE_CONST_FUN_OBJ_1(espnow_deinit_obj, espnow_deinit); //| def __enter__(self) -> ESPNow: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t espnow_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return espnow_deinit(args[0]); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow___exit___obj, 4, 4, espnow_obj___exit__); +//| +// Provided by context manager helper. // --- Send and Read messages --- @@ -109,6 +110,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow___exit___obj, 4, 4, espnow_obj //| :param Peer peer: Send message to this peer. If `None`, send to all registered peers. //| """ //| ... +//| static mp_obj_t espnow_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_message, ARG_peer }; static const mp_arg_t allowed_args[] = { @@ -143,6 +145,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(espnow_send_obj, 2, espnow_send); //| //| :returns: An `ESPNowPacket` if available in the buffer, otherwise `None`.""" //| ... +//| static mp_obj_t espnow_read(mp_obj_t self_in) { espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); espnow_check_for_deinit(self); @@ -204,6 +207,7 @@ MP_PROPERTY_GETTER(espnow_read_failure_obj, //| //| :param ReadableBuffer pmk: The ESP-NOW Primary Master Key (length = 16 bytes).""" //| ... +//| static mp_obj_t espnow_set_pmk(mp_obj_t self_in, mp_obj_t key) { espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); espnow_check_for_deinit(self); @@ -263,8 +267,8 @@ MP_PROPERTY_GETTER(espnow_peers_obj, static const mp_rom_map_elem_t espnow_locals_dict_table[] = { // Context managers - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espnow___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Deinit the object { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espnow_deinit_obj) }, @@ -325,6 +329,7 @@ static const mp_stream_p_t espnow_stream_p = { //| """Return the number of `bytes` available to read. Used to implement ``len()``.""" //| ... //| +//| static mp_obj_t espnow_unary_op(mp_unary_op_t op, mp_obj_t self_in) { espnow_obj_t *self = MP_OBJ_TO_PTR(self_in); espnow_check_for_deinit(self); diff --git a/ports/espressif/bindings/espnow/ESPNowPacket.c b/ports/espressif/bindings/espnow/ESPNowPacket.c index c53ed9dc77cc6..3d85c88fc44c0 100644 --- a/ports/espressif/bindings/espnow/ESPNowPacket.c +++ b/ports/espressif/bindings/espnow/ESPNowPacket.c @@ -21,6 +21,7 @@ //| time: int //| """The time in milliseconds since the device last booted when the packet was received.""" //| +//| const mp_obj_namedtuple_type_t espnow_packet_type_obj = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ESPNowPacket), diff --git a/ports/espressif/bindings/espnow/Peer.c b/ports/espressif/bindings/espnow/Peer.c index 70600a4fb1d41..3e73184914427 100644 --- a/ports/espressif/bindings/espnow/Peer.c +++ b/ports/espressif/bindings/espnow/Peer.c @@ -32,6 +32,7 @@ //| :param bool encrypted: Whether or not to use encryption. //| """ //| ... +//| static mp_obj_t espnow_peer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_mac, ARG_lmk, ARG_channel, ARG_interface, ARG_encrypted }; static const mp_arg_t allowed_args[] = { @@ -167,6 +168,7 @@ MP_PROPERTY_GETSET(espnow_peer_interface_obj, //| encrypted: bool //| """Whether or not to use encryption.""" //| +//| static mp_obj_t espnow_peer_get_encrypted(const mp_obj_t self_in) { espnow_peer_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(self->peer_info.encrypt); diff --git a/ports/espressif/bindings/espnow/Peers.c b/ports/espressif/bindings/espnow/Peers.c index 2f168768c917c..57ab2d5f6c6ec 100644 --- a/ports/espressif/bindings/espnow/Peers.c +++ b/ports/espressif/bindings/espnow/Peers.c @@ -21,6 +21,7 @@ //| def __init__(self) -> None: //| """You cannot create an instance of `Peers`.""" //| ... +//| //| def append(self, peer: Peer) -> None: //| """Append peer. @@ -28,6 +29,7 @@ //| :param Peer peer: The peer object to append. //| """ //| ... +//| static mp_obj_t espnow_peers_append(mp_obj_t self_in, mp_obj_t arg) { espnow_peer_obj_t *peer = MP_OBJ_TO_PTR(mp_arg_validate_type(arg, &espnow_peer_type, MP_QSTR_Peer)); CHECK_ESP_RESULT(esp_now_add_peer(&peer->peer_info)); @@ -43,6 +45,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(espnow_peers_append_obj, espnow_peers_append); //| """ //| ... //| +//| static mp_obj_t espnow_peers_remove(mp_obj_t self_in, mp_obj_t arg) { espnow_peer_obj_t *peer = MP_OBJ_TO_PTR(mp_arg_validate_type(arg, &espnow_peer_type, MP_QSTR_Peer)); CHECK_ESP_RESULT(esp_now_del_peer(peer->peer_info.peer_addr)); diff --git a/ports/espressif/bindings/espnow/__init__.c b/ports/espressif/bindings/espnow/__init__.c index 79bc0b0f3a638..6415bf0d1e6eb 100644 --- a/ports/espressif/bindings/espnow/__init__.c +++ b/ports/espressif/bindings/espnow/__init__.c @@ -51,6 +51,7 @@ //| for packet in packets: //| print(packet) //| """ +//| //| ... //| diff --git a/ports/espressif/bindings/espulp/Architecture.c b/ports/espressif/bindings/espulp/Architecture.c index ee45035e89dfe..bcf094e7e11fb 100644 --- a/ports/espressif/bindings/espulp/Architecture.c +++ b/ports/espressif/bindings/espulp/Architecture.c @@ -20,6 +20,7 @@ MAKE_ENUM_VALUE(espulp_architecture_type, architecture, RISCV, RISCV); //| RISCV: Architecture //| """The ULP RISC-V Coprocessor.""" //| +//| MAKE_ENUM_MAP(espulp_architecture) { MAKE_ENUM_MAP_ENTRY(architecture, FSM), MAKE_ENUM_MAP_ENTRY(architecture, RISCV), diff --git a/ports/espressif/bindings/espulp/ULP.c b/ports/espressif/bindings/espulp/ULP.c index c660987aea5f8..294678cb1da65 100644 --- a/ports/espressif/bindings/espulp/ULP.c +++ b/ports/espressif/bindings/espulp/ULP.c @@ -6,6 +6,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/util.h" +#include "shared/runtime/context_manager_helpers.h" #include "bindings/espulp/ULP.h" #include "py/enum.h" @@ -13,7 +14,7 @@ #include "py/objproperty.h" //| class ULP: -//| def __init__(self, arch: Architecture = Architecture.FSM): +//| def __init__(self, arch: Architecture = Architecture.FSM) -> None: //| """The ultra-low-power processor. //| //| Raises an exception if another ULP has been instantiated. This @@ -22,6 +23,7 @@ //| :param Architecture arch: The ulp arch. //| """ //| ... +//| static mp_obj_t espulp_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_arch }; static const mp_arg_t allowed_args[] = { @@ -49,6 +51,7 @@ static void check_for_deinit(espulp_ulp_obj_t *self) { //| def deinit(self) -> None: //| """Deinitialises the ULP and releases it for another program.""" //| ... +//| static mp_obj_t espulp_ulp_deinit(mp_obj_t self_in) { espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_espulp_ulp_deinit(self); @@ -59,17 +62,15 @@ static MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_deinit_obj, espulp_ulp_deinit); //| def __enter__(self) -> ULP: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t espulp_ulp_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - return espulp_ulp_deinit(args[0]); -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espulp_ulp___exit___obj, 4, 4, espulp_ulp_obj___exit__); +//| +// Provided by context manager helper. //| def set_wakeup_period(self, period_index: int, period_us: int) -> None: //| """Sets the wakeup period for the ULP. @@ -79,6 +80,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espulp_ulp___exit___obj, 4, 4, espulp //| By default, the value stored in period index 0 is used. //| :param int period_us: The wakeup period given in microseconds.""" //| ... +//| static mp_obj_t espulp_ulp_set_wakeup_period(mp_obj_t self_in, mp_obj_t period_index, mp_obj_t period_us) { espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -95,7 +97,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(espulp_ulp_set_wakeup_period_obj, espulp_ulp_se //| program: ReadableBuffer, //| *, //| entrypoint: int = 0, -//| pins: Sequence[microcontroller.Pin] = () +//| pins: Sequence[microcontroller.Pin] = (), //| ) -> None: //| """Loads the program into ULP memory and then runs the program. //| @@ -107,6 +109,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(espulp_ulp_set_wakeup_period_obj, espulp_ulp_se //| :param Sequence[microcontroller.Pin] pins: Pins made available to the ULP. //| The pins are claimed and not reset until `halt()` is called.""" //| ... +//| static mp_obj_t espulp_ulp_run(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); check_for_deinit(self); @@ -155,6 +158,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(espulp_ulp_run_obj, 2, espulp_ulp_run); //| Note: for the FSM ULP, a running ULP program is not actually interrupted. //| Instead, only the wakeup timer is stopped.""" //| ... +//| static mp_obj_t espulp_ulp_halt(mp_obj_t self_in) { espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -167,6 +171,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(espulp_ulp_halt_obj, espulp_ulp_halt); //| arch: Architecture //| """The ulp architecture. (read-only)""" //| +//| static mp_obj_t espulp_ulp_get_arch(mp_obj_t self_in) { espulp_ulp_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -180,8 +185,8 @@ MP_PROPERTY_GETTER(espulp_ulp_arch_obj, static const mp_rom_map_elem_t espulp_ulp_locals_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&espulp_ulp_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&espulp_ulp___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&espulp_ulp_set_wakeup_period_obj) }, { MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&espulp_ulp_run_obj) }, { MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&espulp_ulp_halt_obj) }, diff --git a/ports/espressif/bindings/espulp/ULPAlarm.c b/ports/espressif/bindings/espulp/ULPAlarm.c index edff8e44b8e24..6c31137f9aec6 100644 --- a/ports/espressif/bindings/espulp/ULPAlarm.c +++ b/ports/espressif/bindings/espulp/ULPAlarm.c @@ -20,6 +20,7 @@ //| :param ULP ulp: The ulp instance""" //| ... //| +//| static mp_obj_t espulp_ulpalarm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_ulp }; static const mp_arg_t allowed_args[] = { diff --git a/ports/espressif/bindings/espulp/__init__.c b/ports/espressif/bindings/espulp/__init__.c index 59a3519868ce2..9808ab55f4293 100644 --- a/ports/espressif/bindings/espulp/__init__.c +++ b/ports/espressif/bindings/espulp/__init__.c @@ -33,14 +33,17 @@ //| print(shared_mem[0]) //| # ulp.halt() //| """ +//| //| ... //| +//| //| def get_rtc_gpio_number(pin: microcontroller.Pin) -> Optional[int]: //| """Return the RTC GPIO number of the given pin or None if not connected //| to RTC GPIO.""" //| ... //| +//| static mp_obj_t espulp_get_rtc_gpio_number(mp_obj_t pin_obj) { const mcu_pin_obj_t *pin = validate_obj_is_pin(pin_obj, MP_QSTR_pin); diff --git a/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.h b/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.h index bc02e85367b20..2fb1696000c89 100644 --- a/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.h +++ b/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.h @@ -18,3 +18,6 @@ // For entering safe mode #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) + +// Reduce wifi.radio.tx_power due to the antenna design of this board +#define CIRCUITPY_WIFI_DEFAULT_TX_POWER (11.0) diff --git a/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.mk b/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.mk index f0067c0d22b49..ad0e985cd6fab 100644 --- a/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.mk +++ b/ports/espressif/boards/01space_lcd042_esp32c3/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/01space_lcd042_esp32c3/sdkconfig b/ports/espressif/boards/01space_lcd042_esp32c3/sdkconfig index 3a08db70d5f03..e962866216039 100644 --- a/ports/espressif/boards/01space_lcd042_esp32c3/sdkconfig +++ b/ports/espressif/boards/01space_lcd042_esp32c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="01Space-LCD042-ESP32C3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_esp32s3_camera/board.c b/ports/espressif/boards/adafruit_esp32s3_camera/board.c index 027b7ca8b6e45..d8b0832d3d043 100644 --- a/ports/espressif/boards/adafruit_esp32s3_camera/board.c +++ b/ports/espressif/boards/adafruit_esp32s3_camera/board.c @@ -16,7 +16,6 @@ #include "esp_log.h" #include "esp_err.h" -#include "driver/i2c.h" #define DELAY 0x80 @@ -38,9 +37,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO40, // TFT_DC Command or data - &pin_GPIO39, // TFT_CS Chip select - &pin_GPIO38, // TFT_RESET Reset + MP_OBJ_FROM_PTR(&pin_GPIO40), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO39), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO38), // TFT_RESET Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk b/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk index 9f8acf042f679..d1b6d503125c0 100644 --- a/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_esp32s3_camera/mpconfigboard.mk @@ -13,13 +13,11 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -# No OTA partition: larger firmware partition -FLASH_SIZE_SDKCONFIG = esp-idf-config/sdkconfig-flash-$(CIRCUITPY_ESP_FLASH_SIZE)-no-ota.defaults +CIRCUITPY_ESPCAMERA = 1 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_CANIO = 0 CIRCUITPY_DUALBANK = 0 -CIRCUITPY_ESPCAMERA = 1 CIRCUITPY_FRAMEBUFFERIO = 0 CIRCUITPY_KEYPAD = 0 CIRCUITPY_ONEWIREIO = 0 diff --git a/ports/espressif/boards/adafruit_esp32s3_camera/sdkconfig b/ports/espressif/boards/adafruit_esp32s3_camera/sdkconfig index 1bddb7a89fbb7..a12cbe62f1487 100644 --- a/ports/espressif/boards/adafruit_esp32s3_camera/sdkconfig +++ b/ports/espressif/boards/adafruit_esp32s3_camera/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # diff --git a/ports/espressif/boards/adafruit_feather_esp32_v2/board.c b/ports/espressif/boards/adafruit_feather_esp32_v2/board.c index 6771be4444b7b..071ac2527277d 100644 --- a/ports/espressif/boards/adafruit_feather_esp32_v2/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32_v2/board.c @@ -13,8 +13,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 2) { // Turn on NeoPixel and I2C power by default. - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } diff --git a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/board.c b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/board.c index 493af37a79c24..77a197d3f7384 100644 --- a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/board.c @@ -12,8 +12,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 20) { // Turn on I2C power by default. - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } diff --git a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.mk index f39b1594eda7a..28821ed7b481e 100644 --- a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/mpconfigboard.mk @@ -6,3 +6,6 @@ IDF_TARGET = esp32c6 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/sdkconfig index 0cc38a499d0dc..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32c6_4mbflash_nopsram/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Adafruit-Feather-ESP32C6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/board.c b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/board.c index 5181e4af79b0a..1fe3fd6280021 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/board.c @@ -57,9 +57,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO40, // DC - &pin_GPIO42, // CS - &pin_GPIO41, // RST + MP_OBJ_FROM_PTR(&pin_GPIO40), // DC + MP_OBJ_FROM_PTR(&pin_GPIO42), // CS + MP_OBJ_FROM_PTR(&pin_GPIO41), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -103,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 7) { // Turn on TFT and I2C - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.h b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.h index 42b51434edfd3..f2ec187abde63 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.h @@ -23,7 +23,7 @@ #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) #define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) -#define DEFAULT_UART_BUS_RX (&pin_GPIO34) -#define DEFAULT_UART_BUS_TX (&pin_GPIO35) +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO39) #define DOUBLE_TAP_PIN (&pin_GPIO34) diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.mk index 06a1bf706d345..a0be8c7a5ca0a 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/mpconfigboard.mk @@ -13,3 +13,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Already have a display. +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/sdkconfig index e69de29bb2d1d..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32s2_reverse_tft/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c b/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c index d1dd856815887..22af4caa652b7 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32s2_tft/board.c @@ -57,9 +57,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO39, // DC - &pin_GPIO7, // CS - &pin_GPIO40, // RST + MP_OBJ_FROM_PTR(&pin_GPIO39), // DC + MP_OBJ_FROM_PTR(&pin_GPIO7), // CS + MP_OBJ_FROM_PTR(&pin_GPIO40), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -103,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 21) { // Turn on TFT and I2C - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk index 68abfe8cca7f0..6fafa82485ac6 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk @@ -12,7 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -OPTIMIZATION_FLAGS = -Os -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32s3_4mbflash_2mbpsram/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/mpconfigboard.mk index bf0dc3f320f50..cdf1657d8bea5 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32s3_nopsram/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/board.c b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/board.c index 5181e4af79b0a..1fe3fd6280021 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/board.c @@ -57,9 +57,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO40, // DC - &pin_GPIO42, // CS - &pin_GPIO41, // RST + MP_OBJ_FROM_PTR(&pin_GPIO40), // DC + MP_OBJ_FROM_PTR(&pin_GPIO42), // CS + MP_OBJ_FROM_PTR(&pin_GPIO41), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -103,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 7) { // Turn on TFT and I2C - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.h b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.h index c11780faf41ea..5053a1b2b589b 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.h @@ -23,7 +23,7 @@ #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) #define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) -#define DEFAULT_UART_BUS_RX (&pin_GPIO34) -#define DEFAULT_UART_BUS_TX (&pin_GPIO35) +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO39) #define DOUBLE_TAP_PIN (&pin_GPIO34) diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk index 0aebfea171307..a82ae6d4f04f7 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/mpconfigboard.mk @@ -14,5 +14,5 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 +# Already have a display. CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32s3_reverse_tft/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_tft/board.c b/ports/espressif/boards/adafruit_feather_esp32s3_tft/board.c index c772cc3827510..587c742a64f36 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_tft/board.c +++ b/ports/espressif/boards/adafruit_feather_esp32s3_tft/board.c @@ -57,9 +57,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO39, // DC - &pin_GPIO7, // CS - &pin_GPIO40, // RST + MP_OBJ_FROM_PTR(&pin_GPIO39), // DC + MP_OBJ_FROM_PTR(&pin_GPIO7), // CS + MP_OBJ_FROM_PTR(&pin_GPIO40), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -103,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 21) { // Turn on TFT and I2C - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk index c7d6c33a3fd4e..71ef6d222a2c9 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_esp32s3_tft/mpconfigboard.mk @@ -10,9 +10,9 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_PARALLELDISPLAYBUS = 0 - CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Already have a display. +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_feather_esp32s3_tft/sdkconfig b/ports/espressif/boards/adafruit_feather_esp32s3_tft/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_feather_esp32s3_tft/sdkconfig +++ b/ports/espressif/boards/adafruit_feather_esp32s3_tft/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk b/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk index 2715f5ca30622..f948521eb6d84 100644 --- a/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_feather_huzzah32/mpconfigboard.mk @@ -6,6 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_BLEIO = 0 -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_funhouse/board.c b/ports/espressif/boards/adafruit_funhouse/board.c index 061a6abf0d8ca..83499f5a49229 100644 --- a/ports/espressif/boards/adafruit_funhouse/board.c +++ b/ports/espressif/boards/adafruit_funhouse/board.c @@ -37,9 +37,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO39, // TFT_DC Command or data - &pin_GPIO40, // TFT_CS Chip select - &pin_GPIO41, // TFT_RESET Reset + MP_OBJ_FROM_PTR(&pin_GPIO39), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO40), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO41), // TFT_RESET Reset 5000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk b/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk index e956964776ca4..43045b4cd984d 100644 --- a/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_funhouse/mpconfigboard.mk @@ -9,6 +9,11 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Specialized board. CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_MAX3421E = 0 CIRCUITPY_PS2IO = 0 @@ -21,7 +26,3 @@ CIRCUITPY_FRAMEBUFFERIO = 0 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel - -CIRCUITPY_ESP_PSRAM_SIZE = 2MB -CIRCUITPY_ESP_PSRAM_MODE = qio -CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk index 24909715b9706..9b816b2ba2833 100644 --- a/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_huzzah32_breakout/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/adafruit_itsybitsy_esp32/board.c b/ports/espressif/boards/adafruit_itsybitsy_esp32/board.c index 1ba8890226475..6474622a6824a 100644 --- a/ports/espressif/boards/adafruit_itsybitsy_esp32/board.c +++ b/ports/espressif/boards/adafruit_itsybitsy_esp32/board.c @@ -12,8 +12,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 2) { // Turn on NeoPixel and I2C power by default. - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c index 321a5a1f2c7a0..1437f75165d89 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/board.c @@ -21,7 +21,7 @@ static const char *TAG = "board"; // This is an ILO373 control chip. The display is a 2.9" grayscale EInk. -const uint8_t display_start_sequence[] = { +const uint8_t il0373_display_start_sequence[] = { 0x01, 5, 0x03, 0x00, 0x2b, 0x2b, 0x13, // power setting 0x06, 3, 0x17, 0x17, 0x17, // booster soft start 0x04, DELAY, 200, // power on and wait 200 ms @@ -83,17 +83,143 @@ const uint8_t display_start_sequence[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -const uint8_t display_stop_sequence[] = { +const uint8_t il0373_display_stop_sequence[] = { 0x50, 0x01, 0x17, // CDI Setting 0x82, 0x01, 0x00, // VCM DC to -0.1V 0x02, 0x00 // Power off }; -const uint8_t refresh_sequence[] = { +const uint8_t il0373_display_refresh_sequence[] = { 0x12, 0x00 }; + +// This is an SSD1680 control chip. The display is a 2.9" grayscale EInk. +const uint8_t ssd1680_display_start_sequence[] = { + 0x12, DELAY, 0x00, 0x14, // soft reset and wait 20ms + 0x11, 0x00, 0x01, 0x03, // Ram data entry mode + 0x3c, 0x00, 0x01, 0x03, // border color + 0x2c, 0x00, 0x01, 0x28, // Set vcom voltage + 0x03, 0x00, 0x01, 0x17, // Set gate voltage + 0x04, 0x00, 0x03, 0x41, 0xae, 0x32, // Set source voltage + 0x4e, 0x00, 0x01, 0x01, // ram x count + 0x4f, 0x00, 0x02, 0x00, 0x00, // ram y count + 0x01, 0x00, 0x03, 0x27, 0x01, 0x00, // set display size + 0x32, 0x00, 0x99, // Update waveforms + 0x2a, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L0 + 0x20, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L1 + 0x28, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L2 + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L3 + 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L4 + 0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, // TP, SR, RP of Group0 + 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x01, // TP, SR, RP of Group1 + 0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00, // TP, SR, RP of Group2 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TP, SR, RP of Group11 + 0x24, 0x22, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00, // FR, XON + 0x22, 0x00, 0x01, 0xc7 // display update mode +}; + +const uint8_t ssd1680_display_stop_sequence[] = { + 0x10, DELAY, 0x01, 0x01, 0x64 +}; + +const uint8_t ssd1680_display_refresh_sequence[] = { + 0x20, 0x00, 0x00 +}; + + +typedef enum { + DISPLAY_IL0373, + DISPLAY_SSD1680_COLSTART_0, + DISPLAY_SSD1680_COLSTART_8, +} display_type_t; + +static display_type_t detect_display_type(void) { + // Bitbang 4-wire SPI with a bidirectional data line to read the first word of register 0x2e, + // which is the 10-byte USER ID. + // On the IL0373 it will return 0xff because it's not a valid register. + // With SSD1680, we have seen two types: + // 1. The first batch of displays, labeled "FPC-A005 20.06.15 TRX", which needs colstart=0. + // These have 10 byes of zeros in the User ID + // 2. Second batch, labeled "FPC-7619rev.b", which needs colstart=8. + // The USER ID for these boards is [0x44, 0x0, 0x4, 0x0, 0x25, 0x0, 0x1, 0x78, 0x2b, 0xe] + // So let's distinguish just by the first byte. + digitalio_digitalinout_obj_t data; + digitalio_digitalinout_obj_t clock; + digitalio_digitalinout_obj_t chip_select; + digitalio_digitalinout_obj_t data_command; + digitalio_digitalinout_obj_t reset; + data.base.type = &digitalio_digitalinout_type; + clock.base.type = &digitalio_digitalinout_type; + chip_select.base.type = &digitalio_digitalinout_type; + data_command.base.type = &digitalio_digitalinout_type; + reset.base.type = &digitalio_digitalinout_type; + + common_hal_digitalio_digitalinout_construct(&data, &pin_GPIO35); + common_hal_digitalio_digitalinout_construct(&clock, &pin_GPIO36); + common_hal_digitalio_digitalinout_construct(&chip_select, &pin_GPIO8); + common_hal_digitalio_digitalinout_construct(&data_command, &pin_GPIO7); + common_hal_digitalio_digitalinout_construct(&reset, &pin_GPIO6); + + // Set CS and DC low + common_hal_digitalio_digitalinout_switch_to_output(&chip_select, false, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(&data_command, false, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(&data, false, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(&reset, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(&clock, false, DRIVE_MODE_PUSH_PULL); + + uint8_t status_read = 0x2e; // SSD1680 User ID register. Not a valid register on IL0373. + for (int i = 0; i < 8; i++) { + common_hal_digitalio_digitalinout_set_value(&data, (status_read & (1 << (7 - i))) != 0); + common_hal_digitalio_digitalinout_set_value(&clock, true); + common_hal_digitalio_digitalinout_set_value(&clock, false); + } + + // Set DC high for data and switch to input with pull-up in case the SSD1680 doesn't send any + // data back (as it should.) + common_hal_digitalio_digitalinout_switch_to_input(&data, PULL_UP); + common_hal_digitalio_digitalinout_set_value(&data_command, true); + uint8_t status = 0; + for (int bit = 0; bit < 8; bit++) { + status <<= 1; + if (common_hal_digitalio_digitalinout_get_value(&data)) { + status |= 1; + } + common_hal_digitalio_digitalinout_set_value(&clock, true); + common_hal_digitalio_digitalinout_set_value(&clock, false); + } + + // Set CS high + common_hal_digitalio_digitalinout_set_value(&chip_select, true); + + common_hal_digitalio_digitalinout_deinit(&data); + common_hal_digitalio_digitalinout_deinit(&clock); + common_hal_digitalio_digitalinout_deinit(&chip_select); + common_hal_digitalio_digitalinout_deinit(&data_command); + common_hal_digitalio_digitalinout_deinit(&reset); + + switch (status) { + case 0xff: + return DISPLAY_IL0373; + default: // who knows? Just guess. + case 0x00: + return DISPLAY_SSD1680_COLSTART_0; + case 0x44: + return DISPLAY_SSD1680_COLSTART_8; + } +} + void board_init(void) { + display_type_t display_type = detect_display_type(); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; busio_spi_obj_t *spi = &bus->inline_bus; common_hal_busio_spi_construct(spi, &pin_GPIO36, &pin_GPIO35, NULL, false); @@ -102,47 +228,70 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO7, // EPD_DC Command or data - &pin_GPIO8, // EPD_CS Chip select - &pin_GPIO6, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO7), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO8), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO6), // EPD_RST Reset 4000000, // Baudrate 0, // Polarity 0); // Phase epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - 0x13, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), - 1.0, // refresh_time - &pin_GPIO5, // busy_pin - false, // busy_state - 5.0, // seconds_per_frame - false, // always_toggle_chip_select - true, // grayscale - false, // acep - false, // two_byte_sequence_length - false); // address_little_endian + + if (display_type == DISPLAY_IL0373) { + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = il0373_display_start_sequence; + args.start_sequence_len = sizeof(il0373_display_start_sequence); + args.stop_sequence = il0373_display_stop_sequence; + args.stop_sequence_len = sizeof(il0373_display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = 0x10; + args.write_color_ram_command = 0x13; + args.refresh_sequence = il0373_display_refresh_sequence; + args.refresh_sequence_len = sizeof(il0373_display_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO5; + args.seconds_per_frame = 5.0; + args.grayscale = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); + } else { + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + // Default colstart is 0. + if (display_type == DISPLAY_SSD1680_COLSTART_8) { + args.colstart = 8; + } + args.bus = bus; + args.start_sequence = ssd1680_display_start_sequence; + args.start_sequence_len = sizeof(ssd1680_display_start_sequence); + args.stop_sequence = ssd1680_display_stop_sequence; + args.stop_sequence_len = sizeof(ssd1680_display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 250; + args.ram_height = 296; + args.rotation = 270; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4e; + args.set_current_row_command = 0x4f; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.refresh_sequence = ssd1680_display_refresh_sequence; + args.refresh_sequence_len = sizeof(ssd1680_display_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO5; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.grayscale = true; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); + } } bool espressif_board_reset_pin_number(gpio_num_t pin_number) { diff --git a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk index 01b9ec73e9c34..582eb32eaef6f 100644 --- a/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_magtag_2.9_grayscale/mpconfigboard.mk @@ -9,7 +9,11 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_PARALLELDISPLAYBUS = 0 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager @@ -19,7 +23,3 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH - -CIRCUITPY_ESP_PSRAM_SIZE = 2MB -CIRCUITPY_ESP_PSRAM_MODE = qio -CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/adafruit_matrixportal_s3/mpconfigboard.mk b/ports/espressif/boards/adafruit_matrixportal_s3/mpconfigboard.mk index 51a03b346102b..e213980ccdfe0 100644 --- a/ports/espressif/boards/adafruit_matrixportal_s3/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_matrixportal_s3/mpconfigboard.mk @@ -13,7 +13,6 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 - # Not enough pins. +CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_matrixportal_s3/sdkconfig b/ports/espressif/boards/adafruit_matrixportal_s3/sdkconfig index db95a623aa926..e962866216039 100644 --- a/ports/espressif/boards/adafruit_matrixportal_s3/sdkconfig +++ b/ports/espressif/boards/adafruit_matrixportal_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="matrixportal-s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_metro_esp32s3/sdkconfig b/ports/espressif/boards/adafruit_metro_esp32s3/sdkconfig index 4b1cfa36412d5..e962866216039 100644 --- a/ports/espressif/boards/adafruit_metro_esp32s3/sdkconfig +++ b/ports/espressif/boards/adafruit_metro_esp32s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Metro-ESP32S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_mini_sparkle_motion/board.c b/ports/espressif/boards/adafruit_mini_sparkle_motion/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/adafruit_mini_sparkle_motion/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.h b/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.h new file mode 100644 index 0000000000000..9c83117fe55c3 --- /dev/null +++ b/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Adafruit Mini Sparkle Motion" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO12) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO18) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO19}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO25, .rx = &pin_GPIO26}} + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.mk b/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.mk new file mode 100644 index 0000000000000..25c857fc597f0 --- /dev/null +++ b/ports/espressif/boards/adafruit_mini_sparkle_motion/mpconfigboard.mk @@ -0,0 +1,12 @@ +CIRCUITPY_CREATOR_ID = 0x0000239A +CIRCUITPY_CREATION_ID = 0x00320007 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_mini_sparkle_motion/pins.c b/ports/espressif/boards/adafruit_mini_sparkle_motion/pins.c new file mode 100644 index 0000000000000..d8d42e8a2bc50 --- /dev/null +++ b/ports/espressif/boards/adafruit_mini_sparkle_motion/pins.c @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // External pins are in silkscreen order, from top to bottom, left side, then right side + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_D32), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/tests/extmod/ssl_poll.py.exp b/ports/espressif/boards/adafruit_mini_sparkle_motion/sdkconfig similarity index 100% rename from tests/extmod/ssl_poll.py.exp rename to ports/espressif/boards/adafruit_mini_sparkle_motion/sdkconfig diff --git a/ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.mk b/ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.mk index 4063a6395226c..a17418eff198e 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_qtpy_esp32c3/mpconfigboard.mk @@ -7,9 +7,8 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 # Not enough pins. CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 diff --git a/ports/espressif/boards/adafruit_qtpy_esp32c3/sdkconfig b/ports/espressif/boards/adafruit_qtpy_esp32c3/sdkconfig index aa82df2b813bf..e962866216039 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32c3/sdkconfig +++ b/ports/espressif/boards/adafruit_qtpy_esp32c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Adafruit-QTPy-ESP32C3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h index ad97ab057fb4d..9760bbfeb44aa 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.h @@ -25,3 +25,6 @@ #define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO5, .rx = &pin_GPIO16}} #define DOUBLE_TAP_PIN (&pin_GPIO10) + +// Reduce wifi.radio.tx_power due to the antenna design of this board +#define CIRCUITPY_WIFI_DEFAULT_TX_POWER (15) diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk index afc6e335c1a41..09571a63a59b9 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/mpconfigboard.mk @@ -13,6 +13,6 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 # Not enough pins. +CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/sdkconfig b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/sdkconfig +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_4mbflash_2mbpsram/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h index fcdefda3b4036..6073bd47d0e09 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.h @@ -25,3 +25,6 @@ #define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO5, .rx = &pin_GPIO16}} #define DOUBLE_TAP_PIN (&pin_GPIO10) + +// Reduce wifi.radio.tx_power due to the antenna design of this board +#define CIRCUITPY_WIFI_DEFAULT_TX_POWER (15) diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.mk b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.mk index 43ac269cd099f..053b15647c1a0 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/mpconfigboard.mk @@ -10,7 +10,5 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 - -# Not enough pins. +# Few pins. CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/sdkconfig b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/sdkconfig +++ b/ports/espressif/boards/adafruit_qtpy_esp32s3_nopsram/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_qualia_s3_rgb666/mpconfigboard.mk b/ports/espressif/boards/adafruit_qualia_s3_rgb666/mpconfigboard.mk index 65c872cf74b89..4e8c700f0f6b1 100644 --- a/ports/espressif/boards/adafruit_qualia_s3_rgb666/mpconfigboard.mk +++ b/ports/espressif/boards/adafruit_qualia_s3_rgb666/mpconfigboard.mk @@ -7,10 +7,10 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_SIZE = 16MB CIRCUITPY_ESP_FLASH_MODE = qio -CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_FREQ = 120m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi -CIRCUITPY_ESP_PSRAM_FREQ = 80m +CIRCUITPY_ESP_PSRAM_FREQ = 120m CIRCUITPY_DOTCLOCKFRAMEBUFFER = 1 diff --git a/ports/espressif/boards/adafruit_qualia_s3_rgb666/pins.c b/ports/espressif/boards/adafruit_qualia_s3_rgb666/pins.c index 524182126a164..96879ff037a43 100644 --- a/ports/espressif/boards/adafruit_qualia_s3_rgb666/pins.c +++ b/ports/espressif/boards/adafruit_qualia_s3_rgb666/pins.c @@ -7,14 +7,14 @@ #include "py/objtuple.h" #include "shared-bindings/board/__init__.h" -#define MP_DEFINE_BYTES_OBJ(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin} +#define MP_DEFINE_BYTES_OBJ_WITH_NULL(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin} static const char i2c_bus_init_sequence[] = { 2, 3, 0x78, // set GPIO direction 2, 2, 0, // disable all output inversion 0, // trailing NUL for python bytes() representation }; -static MP_DEFINE_BYTES_OBJ(i2c_init_byte_obj, i2c_bus_init_sequence); +static MP_DEFINE_BYTES_OBJ_WITH_NULL(i2c_init_byte_obj, i2c_bus_init_sequence); static const mp_rom_map_elem_t tft_io_expander_table[] = { { MP_ROM_QSTR(MP_QSTR_i2c_address), MP_ROM_INT(0x3f)}, diff --git a/ports/espressif/boards/adafruit_qualia_s3_rgb666/sdkconfig b/ports/espressif/boards/adafruit_qualia_s3_rgb666/sdkconfig index 8e26f268e76aa..e962866216039 100644 --- a/ports/espressif/boards/adafruit_qualia_s3_rgb666/sdkconfig +++ b/ports/espressif/boards/adafruit_qualia_s3_rgb666/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="qualia" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/adafruit_sparkle_motion/board.c b/ports/espressif/boards/adafruit_sparkle_motion/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.h b/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.h new file mode 100644 index 0000000000000..3f93d08033162 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Adafruit Sparkle Motion" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO4) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO2) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO13, .sda = &pin_GPIO14}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO9, .rx = &pin_GPIO10}} + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.mk b/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.mk new file mode 100644 index 0000000000000..2765a63cef621 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion/mpconfigboard.mk @@ -0,0 +1,12 @@ +CIRCUITPY_CREATOR_ID = 0x0000239A +CIRCUITPY_CREATION_ID = 0x00320006 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Very few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/adafruit_sparkle_motion/pins.c b/ports/espressif/boards/adafruit_sparkle_motion/pins.c new file mode 100644 index 0000000000000..d78c1e1c4c75c --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion/pins.c @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // External pins are in silkscreen order, from top to bottom, left side, then right side + { MP_ROM_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_D32), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_SIG1), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SIG2), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SIG3), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_SIG4), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/tests/feature_check/io_module.py.exp b/ports/espressif/boards/adafruit_sparkle_motion/sdkconfig similarity index 100% rename from tests/feature_check/io_module.py.exp rename to ports/espressif/boards/adafruit_sparkle_motion/sdkconfig diff --git a/ports/espressif/boards/adafruit_sparkle_motion_stick/board.c b/ports/espressif/boards/adafruit_sparkle_motion_stick/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion_stick/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.h b/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.h new file mode 100644 index 0000000000000..fdc289fb845f3 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Adafruit Sparkle Motion Stick" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO4) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO18) + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.mk b/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.mk new file mode 100644 index 0000000000000..d1bfe2f974274 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion_stick/mpconfigboard.mk @@ -0,0 +1,8 @@ +CIRCUITPY_CREATOR_ID = 0x0000239A +CIRCUITPY_CREATION_ID = 0x00320008 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB diff --git a/ports/espressif/boards/adafruit_sparkle_motion_stick/pins.c b/ports/espressif/boards/adafruit_sparkle_motion_stick/pins.c new file mode 100644 index 0000000000000..a5fdadac1e0f7 --- /dev/null +++ b/ports/espressif/boards/adafruit_sparkle_motion_stick/pins.c @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/adafruit_sparkle_motion_stick/sdkconfig b/ports/espressif/boards/adafruit_sparkle_motion_stick/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk index 515b6da5c07c4..da3e6a14496a8 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/mpconfigboard.mk @@ -9,4 +9,7 @@ CIRCUITPY_ESP_FLASH_SIZE = 2MB CIRCUITPY_DUALBANK = 0 +CIRCUITPY_JPEGIO = 0 +CIRCUITPY_CANIO = 0 + CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig index 411bc17724ae0..5fd531f274a6a 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig +++ b/ports/espressif/boards/ai_thinker_esp32-c3s-2m/sdkconfig @@ -7,9 +7,20 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="AIThinker-ESP32C3S-2M" # end of LWIP +# +# Wireless Coexistence +# +# CONFIG_ESP_COEX_SW_COEXIST_ENABLE is not set +# end of Wireless Coexistence + +# +# LibC +# +# CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS is not set +# end of LibC + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.mk b/ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.mk index f907853f2382e..9bcaa3473a2c2 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.mk +++ b/ports/espressif/boards/ai_thinker_esp32-c3s/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/ai_thinker_esp32-c3s/sdkconfig b/ports/espressif/boards/ai_thinker_esp32-c3s/sdkconfig index 435604eb4b8a6..e962866216039 100644 --- a/ports/espressif/boards/ai_thinker_esp32-c3s/sdkconfig +++ b/ports/espressif/boards/ai_thinker_esp32-c3s/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="AIThinker-ESP32C3S" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/arduino_nano_esp32s3/board.c b/ports/espressif/boards/arduino_nano_esp32s3/board.c index e385523892d81..9e3399f8bf7dc 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3/board.c +++ b/ports/espressif/boards/arduino_nano_esp32s3/board.c @@ -12,8 +12,14 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 13) { // Set D13 LED to input when not in use - gpio_set_direction(pin_number, GPIO_MODE_DEF_INPUT); - gpio_set_pull_mode(pin_number, GPIO_PULLDOWN_ONLY); + gpio_config_t cfg = { + .pin_bit_mask = BIT64(pin_number), + .mode = GPIO_MODE_INPUT, + .pull_up_en = false, + .pull_down_en = true, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); return true; } diff --git a/ports/espressif/boards/arduino_nano_esp32s3/mpconfigboard.mk b/ports/espressif/boards/arduino_nano_esp32s3/mpconfigboard.mk index 3abf3d9afcbb5..4974b7a9c89c6 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3/mpconfigboard.mk +++ b/ports/espressif/boards/arduino_nano_esp32s3/mpconfigboard.mk @@ -21,5 +21,3 @@ CIRCUITPY_ESP_PSRAM_FREQ = 80m INTERNAL_FLASH_FILESYSTEM = 0 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = GD25WQ128E - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/arduino_nano_esp32s3/sdkconfig b/ports/espressif/boards/arduino_nano_esp32s3/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3/sdkconfig +++ b/ports/espressif/boards/arduino_nano_esp32s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/board.c b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/board.c index e385523892d81..9e3399f8bf7dc 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/board.c +++ b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/board.c @@ -12,8 +12,14 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 13) { // Set D13 LED to input when not in use - gpio_set_direction(pin_number, GPIO_MODE_DEF_INPUT); - gpio_set_pull_mode(pin_number, GPIO_PULLDOWN_ONLY); + gpio_config_t cfg = { + .pin_bit_mask = BIT64(pin_number), + .mode = GPIO_MODE_INPUT, + .pull_up_en = false, + .pull_down_en = true, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); return true; } diff --git a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/mpconfigboard.mk b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/mpconfigboard.mk index 3abf3d9afcbb5..4974b7a9c89c6 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/mpconfigboard.mk +++ b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/mpconfigboard.mk @@ -21,5 +21,3 @@ CIRCUITPY_ESP_PSRAM_FREQ = 80m INTERNAL_FLASH_FILESYSTEM = 0 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = GD25WQ128E - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/sdkconfig b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/sdkconfig index b2e5c546b825a..e962866216039 100644 --- a/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/sdkconfig +++ b/ports/espressif/boards/arduino_nano_esp32s3_inverted_statusled/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="nano-esp32" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/artisense_rd00/sdkconfig b/ports/espressif/boards/artisense_rd00/sdkconfig index 36749a928bd1b..e962866216039 100644 --- a/ports/espressif/boards/artisense_rd00/sdkconfig +++ b/ports/espressif/boards/artisense_rd00/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="RD00-ESP32S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/atmegazero_esp32s2/sdkconfig b/ports/espressif/boards/atmegazero_esp32s2/sdkconfig index 0748a66c5ca17..e962866216039 100644 --- a/ports/espressif/boards/atmegazero_esp32s2/sdkconfig +++ b/ports/espressif/boards/atmegazero_esp32s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="ATMegaZero-Esp32s2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/autosportlabs_esp32_can_x2/sdkconfig b/ports/espressif/boards/autosportlabs_esp32_can_x2/sdkconfig index 30ffa1a82961d..e962866216039 100644 --- a/ports/espressif/boards/autosportlabs_esp32_can_x2/sdkconfig +++ b/ports/espressif/boards/autosportlabs_esp32_can_x2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="autosportlabs-esp32-can-x2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/barduino/board.c b/ports/espressif/boards/barduino/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/barduino/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/barduino/mpconfigboard.h b/ports/espressif/boards/barduino/mpconfigboard.h new file mode 100644 index 0000000000000..8aca38db236d4 --- /dev/null +++ b/ports/espressif/boards/barduino/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "BARDUINO 4.0.2" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO48) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO12) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO13) + + +#define DOUBLE_TAP_PIN (&pin_GPIO34) diff --git a/ports/espressif/boards/barduino/mpconfigboard.mk b/ports/espressif/boards/barduino/mpconfigboard.mk new file mode 100644 index 0000000000000..61c5feea811d4 --- /dev/null +++ b/ports/espressif/boards/barduino/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x303A +USB_PID = 0x8244 +USB_PRODUCT = "Barduino 4.0.2" +USB_MANUFACTURER = "Fablab Barcelona" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB diff --git a/ports/espressif/boards/barduino/pins.c b/ports/espressif/boards/barduino/pins.c new file mode 100644 index 0000000000000..8dc164aa702ec --- /dev/null +++ b/ports/espressif/boards/barduino/pins.c @@ -0,0 +1,82 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/barduino/sdkconfig b/ports/espressif/boards/barduino/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/barduino/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/beetle-esp32-c3/mpconfigboard.mk b/ports/espressif/boards/beetle-esp32-c3/mpconfigboard.mk index a03e6c32eb2c6..dfd6a665f3b10 100644 --- a/ports/espressif/boards/beetle-esp32-c3/mpconfigboard.mk +++ b/ports/espressif/boards/beetle-esp32-c3/mpconfigboard.mk @@ -1,4 +1,4 @@ -# TODO +# A better directory name for this board would be dfrobot_beetle_esp32_c3. CIRCUITPY_CREATOR_ID = 0x10101010 CIRCUITPY_CREATION_ID = 0x00C30001 @@ -8,6 +8,4 @@ CIRCUITPY_ESP_FLASH_MODE=qio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/beetle-esp32-c3/sdkconfig b/ports/espressif/boards/beetle-esp32-c3/sdkconfig index 2b4299082a22b..e962866216039 100644 --- a/ports/espressif/boards/beetle-esp32-c3/sdkconfig +++ b/ports/espressif/boards/beetle-esp32-c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="beetle-esp32-c3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/bpi_bit_s2/mpconfigboard.mk b/ports/espressif/boards/bpi_bit_s2/mpconfigboard.mk index e9dd3da71f462..a9bb35b51f7b4 100644 --- a/ports/espressif/boards/bpi_bit_s2/mpconfigboard.mk +++ b/ports/espressif/boards/bpi_bit_s2/mpconfigboard.mk @@ -9,9 +9,9 @@ CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=40m CIRCUITPY_ESP_FLASH_SIZE=4MB -# Include these Python libraries in firmware. -FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel - CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/bpi_bit_s2/sdkconfig b/ports/espressif/boards/bpi_bit_s2/sdkconfig index c9b6f75868d83..e962866216039 100644 --- a/ports/espressif/boards/bpi_bit_s2/sdkconfig +++ b/ports/espressif/boards/bpi_bit_s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="BPI-BIT-S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/bpi_leaf_s3/sdkconfig b/ports/espressif/boards/bpi_leaf_s3/sdkconfig index 6b3f2584c7124..e962866216039 100644 --- a/ports/espressif/boards/bpi_leaf_s3/sdkconfig +++ b/ports/espressif/boards/bpi_leaf_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="BPI-Leaf-S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/bpi_picow_s3/sdkconfig b/ports/espressif/boards/bpi_picow_s3/sdkconfig index 914b077264001..e962866216039 100644 --- a/ports/espressif/boards/bpi_picow_s3/sdkconfig +++ b/ports/espressif/boards/bpi_picow_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="BPI-PicoW-S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/brainboardz_neuron/sdkconfig b/ports/espressif/boards/brainboardz_neuron/sdkconfig index e553af17769f3..e962866216039 100755 --- a/ports/espressif/boards/brainboardz_neuron/sdkconfig +++ b/ports/espressif/boards/brainboardz_neuron/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="BrainBoardzNeuron" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/cezerio_dev_ESP32C6/board.c b/ports/espressif/boards/cezerio_dev_ESP32C6/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/cezerio_dev_ESP32C6/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.h b/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.h new file mode 100644 index 0000000000000..44171d1dc4ddf --- /dev/null +++ b/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "cezerio dev ESP32C6" +#define MICROPY_HW_MCU_NAME "ESP32C6" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO3) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO7) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO21) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO22) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO23) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO17) +#define DEFAULT_UART_BUS_TX (&pin_GPIO16) + +// For entering safe mode, use BOOT button +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) diff --git a/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.mk b/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.mk new file mode 100644 index 0000000000000..fe93c7a849a65 --- /dev/null +++ b/ports/espressif/boards/cezerio_dev_ESP32C6/mpconfigboard.mk @@ -0,0 +1,11 @@ +CIRCUITPY_CREATOR_ID = 0x11361206 +CIRCUITPY_CREATION_ID = 0x00C60001 + +IDF_TARGET = esp32c6 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/cezerio_dev_ESP32C6/pins.c b/ports/espressif/boards/cezerio_dev_ESP32C6/pins.c new file mode 100644 index 0000000000000..ed881ab1ac0c7 --- /dev/null +++ b/ports/espressif/boards/cezerio_dev_ESP32C6/pins.c @@ -0,0 +1,101 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_RGB), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IMUSC), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IMUSD), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_MATRIX), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_MO), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_MI), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/cezerio_dev_ESP32C6/sdkconfig b/ports/espressif/boards/cezerio_dev_ESP32C6/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/cezerio_dev_ESP32C6/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/circuitart_zero_s3/board.c b/ports/espressif/boards/circuitart_zero_s3/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/circuitart_zero_s3/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.h b/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.h new file mode 100644 index 0000000000000..973e611839353 --- /dev/null +++ b/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "CircuitART Zero S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO47) +// #define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO39) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO46) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO34) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO33) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define DOUBLE_TAP_PIN (&pin_GPIO45) + +#define DEFAULT_TF_CS (&pin_GPIO42) +#define DEFAULT_TFT_CS (&pin_GPIO39) +#define DEFAULT_TFT_DC (&pin_GPIO5) +#define DEFAULT_TFT_RST (&pin_GPIO40) diff --git a/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.mk b/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.mk new file mode 100644 index 0000000000000..6fbf3d4a7d17f --- /dev/null +++ b/ports/espressif/boards/circuitart_zero_s3/mpconfigboard.mk @@ -0,0 +1,21 @@ +USB_VID = 0x303A +USB_PID = 0x80DD +USB_PRODUCT = "ZeroS3" +USB_MANUFACTURER = "CircuitArt" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +#CIRCUITPY_BITBANG_NEOPIXEL = 1 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ST7789 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_AHTx0 diff --git a/ports/espressif/boards/circuitart_zero_s3/pins.c b/ports/espressif/boards/circuitart_zero_s3/pins.c new file mode 100644 index 0000000000000..164d37b4b77fc --- /dev/null +++ b/ports/espressif/boards/circuitart_zero_s3/pins.c @@ -0,0 +1,113 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_obj_tuple_t camera_data_tuple = { + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO6), + MP_ROM_PTR(&pin_GPIO7), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO13), + MP_ROM_PTR(&pin_GPIO14), + } +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // TFT + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO40) }, + + // sd card reader + { MP_ROM_QSTR(MP_QSTR_CARD_CS), MP_ROM_PTR(&pin_GPIO42) }, + + // Green LED + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO46) }, + + // NeoPixels x4 + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO47) }, + + // Camera LDO Enable + { MP_ROM_QSTR(MP_QSTR_CAM_LDO_EN), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA9), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA8), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA7), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA6), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA2), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA5), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA3), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA4), MP_ROM_PTR(&pin_GPIO8) }, + // { MP_ROM_QSTR(MP_QSTR_CAMERA_RESET), MP_ROM_PTR(&pin_GPIO47) }, + // { MP_ROM_QSTR(MP_QSTR_CAMERA_PWDN), MP_ROM_PTR(&pin_GPIO21) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // SPI + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/circuitart_zero_s3/sdkconfig b/ports/espressif/boards/circuitart_zero_s3/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/circuitart_zero_s3/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/columbia-dsl-sensor/mpconfigboard.mk b/ports/espressif/boards/columbia-dsl-sensor/mpconfigboard.mk index 9d11052ee5c55..f37fe88a4fcf1 100644 --- a/ports/espressif/boards/columbia-dsl-sensor/mpconfigboard.mk +++ b/ports/espressif/boards/columbia-dsl-sensor/mpconfigboard.mk @@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/columbia-dsl-sensor/sdkconfig b/ports/espressif/boards/columbia-dsl-sensor/sdkconfig index 05d2603dfbafb..e962866216039 100644 --- a/ports/espressif/boards/columbia-dsl-sensor/sdkconfig +++ b/ports/espressif/boards/columbia-dsl-sensor/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="columbia-dsl-sensor" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/crcibernetica-ideaboard/mpconfigboard.mk b/ports/espressif/boards/crcibernetica-ideaboard/mpconfigboard.mk index 3e7e54c9a63e8..861ae00b0f590 100644 --- a/ports/espressif/boards/crcibernetica-ideaboard/mpconfigboard.mk +++ b/ports/espressif/boards/crcibernetica-ideaboard/mpconfigboard.mk @@ -7,9 +7,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_BLEIO = 0 -CIRCUITPY_ESPCAMERA = 0 - # Include these Python libraries in firmware FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests diff --git a/ports/espressif/boards/crumpspace_crumps2/mpconfigboard.mk b/ports/espressif/boards/crumpspace_crumps2/mpconfigboard.mk index 86fefedfb9557..707687b5cf3fd 100644 --- a/ports/espressif/boards/crumpspace_crumps2/mpconfigboard.mk +++ b/ports/espressif/boards/crumpspace_crumps2/mpconfigboard.mk @@ -9,11 +9,11 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + CIRCUITPY_BITBANG_APA102 = 1 # Include these Python libraries in firmware. # FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DotStar - -CIRCUITPY_ESP_PSRAM_SIZE = 2MB -CIRCUITPY_ESP_PSRAM_MODE = qio -CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/crumpspace_crumps2/sdkconfig b/ports/espressif/boards/crumpspace_crumps2/sdkconfig index e1f568a2d8d25..e962866216039 100644 --- a/ports/espressif/boards/crumpspace_crumps2/sdkconfig +++ b/ports/espressif/boards/crumpspace_crumps2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="CrumpS2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/cytron_maker_feather_aiot_s3/board.c b/ports/espressif/boards/cytron_maker_feather_aiot_s3/board.c index a91e3fc3ec729..72d95a8768bf2 100644 --- a/ports/espressif/boards/cytron_maker_feather_aiot_s3/board.c +++ b/ports/espressif/boards/cytron_maker_feather_aiot_s3/board.c @@ -57,8 +57,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { void reset_board(void) { // Turn on VP by default. - gpio_set_direction(11, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(11, true); + config_pin_as_output_with_level(11, true); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/cytron_maker_feather_aiot_s3/sdkconfig b/ports/espressif/boards/cytron_maker_feather_aiot_s3/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/cytron_maker_feather_aiot_s3/sdkconfig +++ b/ports/espressif/boards/cytron_maker_feather_aiot_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/deneyap_kart/mpconfigboard.mk b/ports/espressif/boards/deneyap_kart/mpconfigboard.mk index df54649ec529d..69d81074fa7e5 100644 --- a/ports/espressif/boards/deneyap_kart/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_kart/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/deneyap_kart_1a/mpconfigboard.mk b/ports/espressif/boards/deneyap_kart_1a/mpconfigboard.mk index 17dfe4fe76863..b1b6c9eab4bf9 100644 --- a/ports/espressif/boards/deneyap_kart_1a/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_kart_1a/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/deneyap_kart_1a_v2/mpconfigboard.mk b/ports/espressif/boards/deneyap_kart_1a_v2/mpconfigboard.mk index cb994090192b5..5a2fd709a5e33 100644 --- a/ports/espressif/boards/deneyap_kart_1a_v2/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_kart_1a_v2/mpconfigboard.mk @@ -13,10 +13,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_BITMAPFILTER = 0 -CIRCUITPY_CODEOP = 0 -CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/deneyap_kart_1a_v2/sdkconfig b/ports/espressif/boards/deneyap_kart_1a_v2/sdkconfig index 2d5e06f98510c..e962866216039 100644 --- a/ports/espressif/boards/deneyap_kart_1a_v2/sdkconfig +++ b/ports/espressif/boards/deneyap_kart_1a_v2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="DeneyapKart1A_v2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/deneyap_kart_g/mpconfigboard.mk b/ports/espressif/boards/deneyap_kart_g/mpconfigboard.mk index 8aaea636b843c..46e0fbb3e2312 100644 --- a/ports/espressif/boards/deneyap_kart_g/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_kart_g/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/deneyap_kart_g/sdkconfig b/ports/espressif/boards/deneyap_kart_g/sdkconfig index f239c3140522c..e962866216039 100644 --- a/ports/espressif/boards/deneyap_kart_g/sdkconfig +++ b/ports/espressif/boards/deneyap_kart_g/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="DeneyapKartG" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/deneyap_mini/mpconfigboard.mk b/ports/espressif/boards/deneyap_mini/mpconfigboard.mk index 007b7ebc82abd..8f6257ff02b1e 100644 --- a/ports/espressif/boards/deneyap_mini/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_mini/mpconfigboard.mk @@ -9,7 +9,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/deneyap_mini/sdkconfig b/ports/espressif/boards/deneyap_mini/sdkconfig index 3bcde1ab9e689..e962866216039 100644 --- a/ports/espressif/boards/deneyap_mini/sdkconfig +++ b/ports/espressif/boards/deneyap_mini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="DeneyapMini" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/deneyap_mini_v2/mpconfigboard.mk b/ports/espressif/boards/deneyap_mini_v2/mpconfigboard.mk index 457d4b9316142..9712e8437f772 100644 --- a/ports/espressif/boards/deneyap_mini_v2/mpconfigboard.mk +++ b/ports/espressif/boards/deneyap_mini_v2/mpconfigboard.mk @@ -13,5 +13,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/deneyap_mini_v2/sdkconfig b/ports/espressif/boards/deneyap_mini_v2/sdkconfig index be30fb4463d91..e962866216039 100644 --- a/ports/espressif/boards/deneyap_mini_v2/sdkconfig +++ b/ports/espressif/boards/deneyap_mini_v2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="DeneyapMini_v2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/deshipu_ugame_s3/board.c b/ports/espressif/boards/deshipu_ugame_s3/board.c new file mode 100644 index 0000000000000..dc09786e74ce7 --- /dev/null +++ b/ports/espressif/boards/deshipu_ugame_s3/board.c @@ -0,0 +1,123 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#include "esp_log.h" +#include "esp_err.h" + +fourwire_fourwire_obj_t board_display_obj; + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 0x80, // Software reset then delay 0x80 (128ms) + 0xEF, 3, 0x03, 0x80, 0x02, + 0xCF, 3, 0x00, 0xC1, 0x30, + 0xED, 4, 0x64, 0x03, 0x12, 0x81, + 0xE8, 3, 0x85, 0x00, 0x78, + 0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, + 0xF7, 1, 0x20, + 0xEA, 2, 0x00, 0x00, + 0xc0, 1, 0x23, // Power control VRH[5:0] + 0xc1, 1, 0x10, // Power control SAP[2:0];BT[3:0] + 0xc5, 2, 0x3e, 0x28, // VCM control + 0xc7, 1, 0x86, // VCM control2 + 0x37, 1, 0x00, // Vertical scroll zero + 0x3a, 1, 0x55, // COLMOD: Pixel Format Set + 0xb1, 2, 0x00, 0x18, // Frame Rate Control (In Normal Mode/Full Colors) + 0xb6, 3, 0x08, 0x82, 0x27, // Display Function Control + 0xF2, 1, 0x00, // 3Gamma Function Disable + 0x26, 1, 0x01, // Gamma curve selected + 0xe0, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma + 0xe1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma + 0x11, 0 | DELAY, 0x78, // Exit Sleep then delay 0x78 (120ms) + 0x29, 0 | DELAY, 0x78, // Display on then delay 0x78 (120ms) + 0x36, 1, 0x38, +}; + + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO12, &pin_GPIO11, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO10), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO13), // TFT_RESET Reset + 48000000L, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 320, // Width (after rotation) + 240, // Height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // Color depth + false, // Grayscale + false, // Pixels in a byte share a row. Only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO21, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 20, // native_frames_per_second + true, // backlight_on_high + false, // not SH1107 + 50000); // backlight pwm frequency +} + +void board_deinit(void) { +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.h b/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.h new file mode 100644 index 0000000000000..da7c3b4e8a43c --- /dev/null +++ b/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.h @@ -0,0 +1,28 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2023 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define MICROPY_HW_BOARD_NAME "uGame S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" diff --git a/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.mk b/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.mk new file mode 100644 index 0000000000000..36a0ce040c509 --- /dev/null +++ b/ports/espressif/boards/deshipu_ugame_s3/mpconfigboard.mk @@ -0,0 +1,27 @@ +USB_VID = 0x1209 +USB_PID = 0xD187 +USB_PRODUCT = "uGameS3" +USB_MANUFACTURER = "deshipu" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_STAGE = 1 +CIRCUITPY_KEYPAD = 1 + +CIRCUITPY_CANIO = 0 +CIRCUITPY_DUALBANK = 0 +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_ROTARYIO = 0 + +FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/ugame_s3 diff --git a/ports/espressif/boards/deshipu_ugame_s3/pins.c b/ports/espressif/boards/deshipu_ugame_s3/pins.c new file mode 100644 index 0000000000000..54bd5dcdb4f0d --- /dev/null +++ b/ports/espressif/boards/deshipu_ugame_s3/pins.c @@ -0,0 +1,43 @@ +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_P1), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_O), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_Z), MP_ROM_PTR(&pin_GPIO47) }, + + { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO8) }, + + + { MP_ROM_QSTR(MP_QSTR_AUDIO_BCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_LRCLK), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_DATA), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_AUDIO_GAIN), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/deshipu_ugame_s3/sdkconfig b/ports/espressif/boards/deshipu_ugame_s3/sdkconfig new file mode 100644 index 0000000000000..1bddb7a89fbb7 --- /dev/null +++ b/ports/espressif/boards/deshipu_ugame_s3/sdkconfig @@ -0,0 +1,22 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" +# end of LWIP + +# +# Camera configuration +# +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_OV3660_SUPPORT is not set +# end of Camera configuration + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/doit_esp32_devkit_v1/mpconfigboard.mk b/ports/espressif/boards/doit_esp32_devkit_v1/mpconfigboard.mk index 9f657c6552dbe..01db9cff0901d 100644 --- a/ports/espressif/boards/doit_esp32_devkit_v1/mpconfigboard.mk +++ b/ports/espressif/boards/doit_esp32_devkit_v1/mpconfigboard.mk @@ -6,6 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/board.c b/ports/espressif/boards/elecrow_crowpanel_3.5/board.c new file mode 100755 index 0000000000000..0748e03fce88b --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/board.c @@ -0,0 +1,100 @@ +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +#include "common-hal/microcontroller/Pin.h" + +// reference: lv_micropython ili9XXX.py +// reference: ILI9488 datasheet + +#define DELAY_FLAG 0x80 + +#define COLORMODE_BGR 0b00001000 +#define ROTATION_Y_FLIP 0b10000000 +#define ROTATION_X_FLIP 0b01000000 +#define ROTATION_MV 0b00100000 + +// DBI type C (SPI) only has 3bit and 18bit format support, 3bit = 2 pixels per byte, 18bit = one color per byte +#define COLORFORMAT_3BIT 0b00000001 +#define COLORFORMAT_16BIT 0b00000101 +#define COLORFORMAT_18BIT 0b00000110 +#define COLORFORMAT_24BIT 0b00000111 + +static uint8_t display_init_sequence[] = { + 0x01, DELAY_FLAG | 0, 200, // Software Reset + 0x11, DELAY_FLAG | 0, 120, // Exit Sleep Mode + 0xE0, 15, 0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F, // Positive Gamma Control + 0xE1, 15, 0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F, // Negative Gamma Control + 0xC0, 2, 0x17, 0x15, // Power Control 1 + 0xC1, 1, 0x41, // Power Control 2 + 0xC2, 1, 0x44, // Power Control 3 / Normal Mode + 0xC5, 3, 0x00, 0x12, 0x80, // VCOM Control + 0x36, 1, ROTATION_Y_FLIP, // Colormode & Rotation + 0x3A, 1, COLORFORMAT_18BIT, // Interface pixel format + 0xB0, 1, 0x00, // Interface mode control + 0xB1, 1, 0xA0, // Frame Rate Control + 0xB4, 1, 0x02, // Display Inversion Control + 0xB6, 2, 0x02, 0x02, // Display Function Control + 0xE9, 1, 0x00, // Set Image Function + 0x53, 1, 0x28, // CTRL Display Value + 0x51, 1, 0x7F, // Display Brightness + 0xF7, 4, 0xA9, 0x51, 0x2C, 0x02, // Adjust Control 3 + 0x29, DELAY_FLAG | 0, 25 // Display ON +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO14, &pin_GPIO13, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select + NULL, // TFT_RST Reset + 20000000, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct(display, + bus, + 320, // Width (after rotation) + 480, // Height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 24, // Color depth + false, // grayscale + false, // pixels in byte share row. only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO27, // backlight pin + 0x51, // cmd to write brightness + 0.5f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000); // backlight pwm frequency +} + +void board_deinit(void) { + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.h b/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.h new file mode 100644 index 0000000000000..9c080fd322393 --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Chris Drake, independently providing these changes. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define MICROPY_HW_BOARD_NAME "Elecrow CrowPanel" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO21}} + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO23, .miso = &pin_GPIO19}, /* SD */ \ + {.clock = &pin_GPIO14, .mosi = &pin_GPIO13, .miso = &pin_GPIO12} /* LCD & touch */ } + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) + +#define CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP (1) diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.mk b/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.mk new file mode 100755 index 0000000000000..f92068909fb8f --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/mpconfigboard.mk @@ -0,0 +1,17 @@ +CIRCUITPY_CREATOR_ID = 0xDD500000 +CIRCUITPY_CREATION_ID = 0x00320000 + +IDF_TARGET = esp32 + +# This board doesn't have USB by default, it +# instead uses a CH340C USB-to-Serial chip +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/pins.c b/ports/espressif/boards/elecrow_crowpanel_3.5/pins.c new file mode 100755 index 0000000000000..147db0a346d7f --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/pins.c @@ -0,0 +1,72 @@ +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + // TFT and Touch Panel share the same SPI bus + { MP_ROM_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CLK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_TP_CS), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TP_IRQ), MP_ROM_PTR(&pin_GPIO36) }, + + // Version 2.2 hardware (Sep 2024) swaps MISO & touch CS pins + { MP_ROM_QSTR(MP_QSTR_TFT_MISO_ALT), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TP_CS_ALT), MP_ROM_PTR(&pin_GPIO12) }, + + // SD card SPI bus + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_ROM_QSTR(MP_QSTR_SPEAK), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/elecrow_crowpanel_3.5/sdkconfig b/ports/espressif/boards/elecrow_crowpanel_3.5/sdkconfig new file mode 100755 index 0000000000000..a571ec9cacbac --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_3.5/sdkconfig @@ -0,0 +1,9 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# +# Component config +# +# +# Hardware Settings diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c new file mode 100644 index 0000000000000..c292ea113aa3f --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/board.c @@ -0,0 +1,102 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +// SSD1683 EPD Driver chip +const uint8_t display_start_sequence[] = { + // Init + 0x12, 0x80, 0x0a, // Soft reset + 0x01, 0x03, 0x2b, 0x01, 0x00, // Set MUX as 300 + 0x21, 0x02, 0x40, 0x00, // Display update control + 0x3c, 0x01, 0x01, // Border waveform + 0x11, 0x01, 0x03, // X- mode + 0x44, 0x02, 0x00, 0x31, // Set RAM X Address Start/End Pos + 0x45, 0x04, 0x00, 0x00, 0x2b, 0x01, // Set RAM Y Address Start/End Pos + 0x4e, 0x01, 0x00, // Set RAM X Address counter + 0x4f, 0x02, 0x00, 0x00, // Set RAM Y Address counter +}; + +const uint8_t display_stop_sequence[] = { + 0x10, 0x01, 0x32, +}; + +const uint8_t refresh_sequence[] = { + 0x22, 0x01, 0xf7, // Display update sequence option + 0x20, 0x80, 0x0a, // Master activation +}; + +void board_init(void) { + + // Enable EPD with driver pin + digitalio_digitalinout_obj_t epd_enable_pin_obj; + epd_enable_pin_obj.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&epd_enable_pin_obj, &pin_GPIO7); + common_hal_digitalio_digitalinout_switch_to_output(&epd_enable_pin_obj, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&epd_enable_pin_obj); + + // Set up the SPI object used to control the display + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO12, &pin_GPIO11, NULL, false); + common_hal_busio_spi_never_reset(spi); + + // Set up the DisplayIO pin object + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO46), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO45), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO47), // EPD_RST Reset + 1000000, // Baudrate + 0, // Polarity + 0); // Phase + + // Set up the DisplayIO epaper object + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 400; + args.height = 300; + args.ram_width = 400; + args.ram_height = 300; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO48; + args.busy_state = true; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.h b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.h new file mode 100644 index 0000000000000..f3c494ed48379 --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "CrowPanel 4.2 EPaper" +#define MICROPY_HW_MCU_NAME "ESP32S3" +#define MICROPY_HW_LED_STATUS (&pin_GPIO41) +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_GPIO39, .mosi = &pin_GPIO40, .miso = &pin_GPIO13}, /*SD*/ \ + {.clock = &pin_GPIO12, .mosi = &pin_GPIO11}, /*EPD*/ \ +} + +// UART pins attached to the USB-serial converter chip +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX +#define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.mk b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.mk new file mode 100644 index 0000000000000..3f14971607b97 --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/mpconfigboard.mk @@ -0,0 +1,17 @@ +CIRCUITPY_CREATOR_ID = 0x1C350000 +CIRCUITPY_CREATION_ID = 0x00000001 + +# This board doesn't have USB by default, it +# instead uses a CH340C USB-to-Serial chip +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/pins.c b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/pins.c new file mode 100644 index 0000000000000..21a15d0732b65 --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/pins.c @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(tf_spi, spi, 0) +CIRCUITPY_BOARD_BUS_SINGLETON(epd_spi, spi, 1) + + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_EXIT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_MENU), MP_ROM_PTR(&pin_GPIO2) }, + + // Rocker Switch + { MP_ROM_QSTR(MP_QSTR_ROCKER_DOWN), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_ROCKER_CLICK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_ROCKER_UP), MP_ROM_PTR(&pin_GPIO6) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO41) }, + + // Device Control (Pins that, when activated, enable devices) + { MP_ROM_QSTR(MP_QSTR_EPD_ENABLE), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_TF_ENABLE), MP_ROM_PTR(&pin_GPIO42) }, + + // EPD + { MP_ROM_QSTR(MP_QSTR_EPD_BUSY), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_EPD_RES), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_EPD_DC), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CS), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CLK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_EPD_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + + // TF Slot + { MP_ROM_QSTR(MP_QSTR_TF_CS), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_TF_MOSI), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_TF_CLK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_TF_MISO), MP_ROM_PTR(&pin_GPIO13) }, + + // User accessible GPIO + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_TF_SPI), MP_ROM_PTR(&board_tf_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SPI), MP_ROM_PTR(&board_epd_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/sdkconfig b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/elecrow_crowpanel_4_2_epaper/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.mk b/ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.mk index dc73ae08f5562..6234a6b60cc0b 100644 --- a/ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.mk +++ b/ports/espressif/boards/electroniccats_bastwifi/mpconfigboard.mk @@ -5,9 +5,6 @@ USB_MANUFACTURER = "ElectronicCats" IDF_TARGET = esp32s2 -CIRCUITPY_NEOPIXEL_WRITE = 0 - CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/es3ink/sdkconfig b/ports/espressif/boards/es3ink/sdkconfig index b023c59d0357b..e962866216039 100644 --- a/ports/espressif/boards/es3ink/sdkconfig +++ b/ports/espressif/boards/es3ink/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="es3ink" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/esp32-wrover-dev-cam/pins.c b/ports/espressif/boards/esp32-wrover-dev-cam/pins.c index d6aee44a37390..6b47356a82153 100755 --- a/ports/espressif/boards/esp32-wrover-dev-cam/pins.c +++ b/ports/espressif/boards/esp32-wrover-dev-cam/pins.c @@ -3,7 +3,7 @@ CIRCUITPY_BOARD_BUS_SINGLETON(sscb_i2c, i2c, 2) // Camera sensor -STATIC const mp_rom_obj_tuple_t camera_data_tuple = { +static const mp_rom_obj_tuple_t camera_data_tuple = { // The order matters. They must be ordered from low to high (Y2, Y3 .. Y9). Do not include any of the control pins in here. {&mp_type_tuple}, 8, @@ -19,7 +19,7 @@ STATIC const mp_rom_obj_tuple_t camera_data_tuple = { } }; -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS // Red LED labelled IO2 on the front of the board diff --git a/ports/espressif/boards/espressif_esp32_devkitc_v4_wroom_32e/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_devkitc_v4_wroom_32e/mpconfigboard.mk index 766196f9b30fc..aa34430a34c88 100644 --- a/ports/espressif/boards/espressif_esp32_devkitc_v4_wroom_32e/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32_devkitc_v4_wroom_32e/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32_devkitc_v4_wrover/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_devkitc_v4_wrover/mpconfigboard.mk index 6ff7d4e519bd5..848c55d54c161 100644 --- a/ports/espressif/boards/espressif_esp32_devkitc_v4_wrover/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32_devkitc_v4_wrover/mpconfigboard.mk @@ -7,8 +7,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 - CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 40m diff --git a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk index 92d855842ff33..1980ff38ccdfd 100644 --- a/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32_eye/mpconfigboard.mk @@ -13,12 +13,5 @@ CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 40m -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_CANIO = 0 CIRCUITPY_NEOPIXEL_WRITE = 0 -CIRCUITPY_PIXELBUF = 0 -CIRCUITPY_PS2IO = 0 -CIRCUITPY_ROTARYIO = 0 -CIRCUITPY_TOUCHIO = 0 -CIRCUITPY_KEYPAD = 0 diff --git a/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk index 4865e85502399..664c24c358fb8 100644 --- a/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32_lyrat/mpconfigboard.mk @@ -10,7 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 4MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 40m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.mk index 5b4f4b7ead6d6..1bbb997a710d2 100644 --- a/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/sdkconfig b/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/sdkconfig index c4def86e69711..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/sdkconfig +++ b/ports/espressif/boards/espressif_esp32c3_devkitm_1_n4/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="ESP32-C3-DevKitM-1" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c b/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c new file mode 100644 index 0000000000000..b3b20cfe2d3f0 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h new file mode 100644 index 0000000000000..d38d4f4d09fdf --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "ESP32-C3-Lyra-V2" +#define MICROPY_HW_MCU_NAME "ESP32-C3N4" + +// Status LED +#define MICROPY_HW_NEOPIXEL (&pin_GPIO10) +#define MICROPY_HW_NEOPIXEL_COUNT (1) + +// Default bus pins +#define DEFAULT_UART_BUS_RX (&pin_GPIO20) +#define DEFAULT_UART_BUS_TX (&pin_GPIO21) + +// Serial over UART +#define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX +#define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk new file mode 100644 index 0000000000000..4b23a76ba6a15 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x00C3A000 + +IDF_TARGET = esp32c3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c b/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c new file mode 100644 index 0000000000000..5f7c3d084dd3f --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c3_lyra_v2/pins.c @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_MTMS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_MTDI), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_MTCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_MTDO), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32c3_lyra_v2/sdkconfig b/ports/espressif/boards/espressif_esp32c3_lyra_v2/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h new file mode 100644 index 0000000000000..d901bfb37ba28 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-C61-DevKitC-1-N8R2" +#define MICROPY_HW_MCU_NAME "ESP32C61" + +#define DEFAULT_UART_BUS_RX (&pin_GPIO10) +#define DEFAULT_UART_BUS_TX (&pin_GPIO11) diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk new file mode 100644 index 0000000000000..1092a874a6868 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/mpconfigboard.mk @@ -0,0 +1,13 @@ +CIRCUITPY_CREATOR_ID = 0x000C303A +CIRCUITPY_CREATION_ID = 0x00C61001 + +IDF_TARGET = esp32c61 +IDF_TARGET_ARCH = riscv + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c new file mode 100644 index 0000000000000..901e52166576b --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_IO24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_IO28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_IO29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32c61_devkitc_1_n8r2/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/espressif_esp32c6_devkitc_1_n8/sdkconfig b/ports/espressif/boards/espressif_esp32c6_devkitc_1_n8/sdkconfig index 54a5473075653..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32c6_devkitc_1_n8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32c6_devkitc_1_n8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32c6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/mpconfigboard.mk index 9685a7e62c59e..75e097afa84b8 100644 --- a/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32c6 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_AUDIOMP3 = 0 diff --git a/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/sdkconfig b/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/sdkconfig index 30a4bea2cc687..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/sdkconfig +++ b/ports/espressif/boards/espressif_esp32c6_devkitm_1_n4/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="ESP32-C6-DevKitM-1" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32h2_devkitm_1_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32h2_devkitm_1_n4/mpconfigboard.mk index 82eb611bdf3d3..d1458fecec5fe 100644 --- a/ports/espressif/boards/espressif_esp32h2_devkitm_1_n4/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32h2_devkitm_1_n4/mpconfigboard.mk @@ -6,3 +6,6 @@ IDF_TARGET = esp32h2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 48m CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/board.c b/ports/espressif/boards/espressif_esp32p4_function_ev/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4_function_ev/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.h b/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.h new file mode 100644 index 0000000000000..89a103e619625 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-P4-Function-EV" +#define MICROPY_HW_MCU_NAME "ESP32P4" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO37) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO8) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO7) + +// Use the second USB device (numbered 0 and 1) +#define CIRCUITPY_USB_DEVICE_INSTANCE 1 +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + +#define CIRCUITPY_USB_HOST_INSTANCE 0 diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.mk new file mode 100644 index 0000000000000..247a1371192f8 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4_function_ev/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x7013 +USB_PRODUCT = "ESP32-P4-Function-EV" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32p4 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 32MB +CIRCUITPY_ESP_PSRAM_MODE = hpi +CIRCUITPY_ESP_PSRAM_FREQ = 200m diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/pins.c b/ports/espressif/boards/espressif_esp32p4_function_ev/pins.c new file mode 100644 index 0000000000000..165ce711b736a --- /dev/null +++ b/ports/espressif/boards/espressif_esp32p4_function_ev/pins.c @@ -0,0 +1,90 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Header Block J1 + { MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_C6_WAKEUP), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_IO24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_C6_EN), MP_ROM_PTR(&pin_GPIO54) }, + { MP_ROM_QSTR(MP_QSTR_IO54), MP_ROM_PTR(&pin_GPIO54) }, + + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_PA_CTRL), MP_ROM_PTR(&pin_GPIO53) }, + { MP_ROM_QSTR(MP_QSTR_IO53), MP_ROM_PTR(&pin_GPIO53) }, + + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + + // I2S + { MP_ROM_QSTR(MP_QSTR_I2S_DSDIN), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_I2S_ASDOUT), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SCLK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO13) }, + + // Ethernet + { MP_ROM_QSTR(MP_QSTR_RMII_RXDV), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_RMII_RXD0), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_RMII_RXD1), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_MDC), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXD0), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXD1), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_RMII_TXEN), MP_ROM_PTR(&pin_GPIO49) }, + { MP_ROM_QSTR(MP_QSTR_RMII_CLK), MP_ROM_PTR(&pin_GPIO50) }, + { MP_ROM_QSTR(MP_QSTR_PHY_RSTN), MP_ROM_PTR(&pin_GPIO51) }, + { MP_ROM_QSTR(MP_QSTR_MDIO), MP_ROM_PTR(&pin_GPIO52) }, + + // SD Card + { MP_ROM_QSTR(MP_QSTR_SD_DATA0), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA1), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA2), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SD_DATA3), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SD_PWRN), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig b/ports/espressif/boards/espressif_esp32p4_function_ev/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk index 37f0450490c30..271e0fd8d958e 100644 --- a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig index 57f0da698aa1d..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/sdkconfig b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/sdkconfig index 57f0da698aa1d..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n4r2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n8r2/sdkconfig b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n8r2/sdkconfig index 57f0da698aa1d..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s2_devkitc_1_n8r2/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s2_devkitc_1_n8r2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_box/board.c b/ports/espressif/boards/espressif_esp32s3_box/board.c index 54edb47bac33d..a27411fd79c16 100644 --- a/ports/espressif/boards/espressif_esp32s3_box/board.c +++ b/ports/espressif/boards/espressif_esp32s3_box/board.c @@ -31,9 +31,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO4, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - &pin_GPIO48, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO4), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO48), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.mk index 765f9968a996e..6c117b1f67e61 100644 --- a/ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_box/mpconfigboard.mk @@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_box/sdkconfig b/ports/espressif/boards/espressif_esp32s3_box/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_box/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_box/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_box_lite/board.c b/ports/espressif/boards/espressif_esp32s3_box_lite/board.c index e675c0f915b6d..48a49e03bc3e6 100644 --- a/ports/espressif/boards/espressif_esp32s3_box_lite/board.c +++ b/ports/espressif/boards/espressif_esp32s3_box_lite/board.c @@ -32,9 +32,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO4, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - &pin_GPIO48, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO4), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO48), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/espressif_esp32s3_box_lite/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_box_lite/mpconfigboard.mk index fe83e2e34ddb6..e54f55fd642ee 100644 --- a/ports/espressif/boards/espressif_esp32s3_box_lite/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_box_lite/mpconfigboard.mk @@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_box_lite/sdkconfig b/ports/espressif/boards/espressif_esp32s3_box_lite/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_box_lite/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_box_lite/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/mpconfigboard.mk index 0a7925420f723..d182a14499253 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 16MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n16/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n32r8/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n32r8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n32r8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n32r8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.mk index bd2cd4c0a3374..ea5597d3702a7 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/board.c b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.h new file mode 100644 index 0000000000000..02fe72fe4a709 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup +#define MICROPY_HW_BOARD_NAME "ESP32-S3-DevKitC-1-N8R2 (ROS version)" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO48) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk new file mode 100644 index 0000000000000..336b9f4dd8926 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x303A +USB_PID = 0x7003 +USB_PRODUCT = "ESP32-S3-DevKitC-1-N8R2 CPY/ROS" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_RCLCPY = 1 diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/pins.c b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/pins.c new file mode 100644 index 0000000000000..3bb64f434d02f --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/pins.c @@ -0,0 +1,55 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r2_ros/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/board.c b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/board.c index 668c38d5fb7ff..f8435df23f71c 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/board.c +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/board.c @@ -77,11 +77,6 @@ static void display_init(void) { } void board_init(void) { - // Debug UART - #ifdef DEBUG - common_hal_never_reset_pin(&pin_GPIO43); - common_hal_never_reset_pin(&pin_GPIO44); - #endif display_init(); } diff --git a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/sdkconfig index 0452053c1ea38..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitc_1_n8r8_hacktablet/sdkconfig @@ -4,23 +4,9 @@ # # Component config # -# -# ESP System Settings -# -CONFIG_ESP_CONSOLE_UART_CUSTOM=y -# CONFIG_ESP_CONSOLE_NONE is not set -CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y -CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_TX_GPIO=43 -CONFIG_ESP_CONSOLE_UART_RX_GPIO=44 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -# end of ESP System Settings - # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3-hacktablet" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/mpconfigboard.mk index fdbd686e09022..5a410afaa06eb 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/sdkconfig b/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_devkitm_1_n8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_eye/board.c b/ports/espressif/boards/espressif_esp32s3_eye/board.c index c48c9428cf468..09a05cc72c446 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/board.c +++ b/ports/espressif/boards/espressif_esp32s3_eye/board.c @@ -56,8 +56,8 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO43, // DC - &pin_GPIO44, // CS + MP_OBJ_FROM_PTR(&pin_GPIO43), // DC + MP_OBJ_FROM_PTR(&pin_GPIO44), // CS NULL, // no reset pin 40000000, // baudrate 0, // polarity diff --git a/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig b/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig index eebef2db64d21..ac1c535717672 100644 --- a/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_eye/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3-eye" # end of LWIP CONFIG_OV2640_SUPPORT=y # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev/board.c b/ports/espressif/boards/espressif_esp32s3_lcd_ev/board.c index 5d13e5226f0c3..ce62bbfe207b3 100644 --- a/ports/espressif/boards/espressif_esp32s3_lcd_ev/board.c +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev/board.c @@ -15,7 +15,7 @@ #include "shared-module/displayio/__init__.h" #include "boards/espressif_esp32s3_lcd_ev/board.h" -#define MP_DEFINE_BYTES_OBJ(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin} +#define MP_DEFINE_BYTES_OBJ_WITH_NULL(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin} static const uint8_t display_init_sequence[] = { 0xf0, 5, 0x55, 0xaa, 0x52, 0x08, 0x00, @@ -66,14 +66,14 @@ static const uint8_t display_init_sequence[] = { 0x29, 0x0, 0, // trailing NUL for Python bytes() representation }; -MP_DEFINE_BYTES_OBJ(display_init_byte_obj, display_init_sequence); +MP_DEFINE_BYTES_OBJ_WITH_NULL(display_init_byte_obj, display_init_sequence); static const char i2c_bus_init_sequence[] = { 2, 3, 0xf1, // set GPIO direction 2, 2, 0, // disable all output inversion 0, // trailing NUL for Python bytes() representation }; -MP_DEFINE_BYTES_OBJ(i2c_init_byte_obj, i2c_bus_init_sequence); +MP_DEFINE_BYTES_OBJ_WITH_NULL(i2c_init_byte_obj, i2c_bus_init_sequence); static const mcu_pin_obj_t *red_pins[] = { &pin_GPIO1, &pin_GPIO2, &pin_GPIO42, &pin_GPIO41, &pin_GPIO40 diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev/sdkconfig b/ports/espressif/boards/espressif_esp32s3_lcd_ev/sdkconfig index ec582be223ac3..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_lcd_ev/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev/sdkconfig @@ -4,23 +4,9 @@ # # Component config # -# -# ESP System Settings -# -CONFIG_ESP_CONSOLE_UART_CUSTOM=y -# CONFIG_ESP_CONSOLE_NONE is not set -CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y -CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_TX_GPIO=43 -CONFIG_ESP_CONSOLE_UART_RX_GPIO=44 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -# end of ESP System Settings - # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="circuitpy" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.c b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.c new file mode 100644 index 0000000000000..bc8349b08323e --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.c @@ -0,0 +1,139 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h" +#include "shared-bindings/dotclockframebuffer/__init__.h" +#include "shared-bindings/framebufferio/FramebufferDisplay.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "boards/espressif_esp32s3_lcd_ev_v1.5/board.h" + +#define MP_DEFINE_BYTES_OBJ_WITH_NULL(obj_name, bin) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, sizeof(bin) - 1, (const byte *)bin} + +static const uint8_t display_init_sequence[] = { + 0xf0, 5, 0x55, 0xaa, 0x52, 0x08, 0x00, + 0xf6, 2, 0x5a, 0x87, + 0xc1, 1, 0x3f, + 0xc2, 1, 0x0e, + 0xc6, 1, 0xf8, + 0xc9, 1, 0x10, + 0xcd, 1, 0x25, + 0xf8, 1, 0x8a, + 0xac, 1, 0x45, + 0xa0, 1, 0xdd, + 0xa7, 1, 0x47, + 0xfa, 4, 0x00, 0x00, 0x00, 0x04, + 0x86, 4, 0x99, 0xa3, 0xa3, 0x51, + 0xa3, 1, 0xee, + 0xfd, 3, 0x3c, 0x3c, 0x00, + 0x71, 1, 0x48, + 0x72, 1, 0x48, + 0x73, 2, 0x00, 0x44, + 0x97, 1, 0xee, + 0x83, 1, 0x93, + 0x9a, 1, 0x72, + 0x9b, 1, 0x5a, + 0x82, 2, 0x2c, 0x2c, + 0xb1, 1, 0x10, + 0x6d, 32, 0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00, + 0x64, 16, 0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a, + 0x65, 16, 0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a, + 0x66, 16, 0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a, + 0x67, 16, 0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a, + 0x68, 13, 0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, + 0x60, 8, 0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a, + 0x63, 8, 0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a, + 0x69, 7, 0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08, + 0x6b, 1, 0x07, + 0x7a, 2, 0x08, 0x13, + 0x7b, 2, 0x08, 0x13, + 0xd1, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0xd2, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0xd3, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0xd4, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0xd5, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0xd6, 52, 0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff, + 0x3a, 1, 0x66, + 0x3a, 1, 0x66, + 0x11, 0x80, 120, + 0x29, 0x0, + 0, // trailing NUL for Python bytes() representation +}; +MP_DEFINE_BYTES_OBJ_WITH_NULL(display_init_byte_obj, display_init_sequence); + +static const char i2c_bus_init_sequence[] = { + 2, 3, 0xf1, // set GPIO direction + 2, 2, 0, // disable all output inversion + 0, // trailing NUL for Python bytes() representation +}; +MP_DEFINE_BYTES_OBJ_WITH_NULL(i2c_init_byte_obj, i2c_bus_init_sequence); + +static const mcu_pin_obj_t *red_pins[] = { + &pin_GPIO1, &pin_GPIO2, &pin_GPIO42, &pin_GPIO41, &pin_GPIO40 +}; +static const mcu_pin_obj_t *green_pins[] = { + &pin_GPIO21, &pin_GPIO8, &pin_GPIO18, &pin_GPIO45, &pin_GPIO38, &pin_GPIO39 +}; +static const mcu_pin_obj_t *blue_pins[] = { + &pin_GPIO10, &pin_GPIO11, &pin_GPIO12, &pin_GPIO13, &pin_GPIO14 +}; +void board_init(void) { + dotclockframebuffer_framebuffer_obj_t *framebuffer = &allocate_display_bus_or_raise()->dotclock; + framebuffer->base.type = &dotclockframebuffer_framebuffer_type; + + common_hal_dotclockframebuffer_framebuffer_construct( + framebuffer, + /* de */ &pin_GPIO17, + /* vsync */ &pin_GPIO3, + /* hsync */ &pin_GPIO46, + /* dclk */ &pin_GPIO9, + /* data */ red_pins, MP_ARRAY_SIZE(red_pins), green_pins, MP_ARRAY_SIZE(green_pins), blue_pins, MP_ARRAY_SIZE(blue_pins), + /* frequency */ 12000000, + /* width x height */ 480, 480, + /* horizontal: pulse, back & front porch, idle */ 13, 20, 40, false, + /* vertical: pulse, back & front porch, idle */ 15, 20, 40, false, + /* de_idle_high */ false, + /* pclk_active_high */ true, + /* pclk_idle_high */ false, + /* overscan_left */ 0 + ); + + framebufferio_framebufferdisplay_obj_t *disp = &allocate_display_or_raise()->framebuffer_display; + disp->base.type = &framebufferio_framebufferdisplay_type; + common_hal_framebufferio_framebufferdisplay_construct( + disp, + framebuffer, + 0, + true + ); + + busio_i2c_obj_t i2c; + i2c.base.type = &busio_i2c_type; + common_hal_busio_i2c_construct(&i2c, DEFAULT_I2C_BUS_SCL, DEFAULT_I2C_BUS_SDA, 400000, 255); + const int i2c_device_address = 32; + + dotclockframebuffer_ioexpander_spi_bus spibus = { + .bus = &i2c, + .i2c_device_address = i2c_device_address, + .i2c_write_size = 2, + .addr_reg_shadow = { .u32 = 1 }, // GPIO data at register 1 + .cs_mask = 0x100 << 1, // data payload is at byte 2 + .mosi_mask = 0x100 << 3, + .clk_mask = 0x100 << 2, + }; + + static const mp_buffer_info_t bufinfo_display_init = { (void *)display_init_sequence, sizeof(display_init_sequence) - 1 }; + static const mp_buffer_info_t bufinfo_i2c_bus_init = { (void *)i2c_bus_init_sequence, sizeof(i2c_bus_init_sequence) - 1 }; + dotclockframebuffer_ioexpander_send_init_sequence(&spibus, &bufinfo_i2c_bus_init, &bufinfo_display_init); + + common_hal_busio_i2c_deinit(&i2c); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.h b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.h new file mode 100644 index 0000000000000..d2fe572b61a63 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/board.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/objstr.h" + +extern mp_obj_str_t display_init_byte_obj, i2c_init_byte_obj; diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.h b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.h new file mode 100644 index 0000000000000..256d73ea1aeac --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Espressif-ESP32-S3-LCD-EV-Board_v1.5" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO4) + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO47) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO48) + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO43) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO44) diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.mk new file mode 100644 index 0000000000000..c1fa681ce1935 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x303A +USB_PID = 0x7011 +USB_PRODUCT = "ESP32-S3-EV-LCD-Board_v1.5" +USB_MANUFACTURER = "Espressif" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_DOTCLOCKFRAMEBUFFER = 1 +UF2_BOOTLOADER = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/pins.c b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/pins.c new file mode 100644 index 0000000000000..b7a7d65b04666 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/pins.c @@ -0,0 +1,116 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "boards/espressif_esp32s3_lcd_ev_v1.5/board.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t tft_io_expander_table[] = { + { MP_ROM_QSTR(MP_QSTR_i2c_address), MP_ROM_INT(0x20)}, + { MP_ROM_QSTR(MP_QSTR_gpio_address), MP_ROM_INT(1)}, + { MP_ROM_QSTR(MP_QSTR_gpio_data_len), MP_ROM_INT(1)}, + { MP_ROM_QSTR(MP_QSTR_gpio_data), MP_ROM_INT(0xF1)}, + { MP_ROM_QSTR(MP_QSTR_cs_bit), MP_ROM_INT(1)}, + { MP_ROM_QSTR(MP_QSTR_mosi_bit), MP_ROM_INT(3)}, + { MP_ROM_QSTR(MP_QSTR_clk_bit), MP_ROM_INT(2)}, + { MP_ROM_QSTR(MP_QSTR_i2c_init_sequence), &i2c_init_byte_obj}, +}; +MP_DEFINE_CONST_DICT(tft_io_expander_dict, tft_io_expander_table); + +static const mp_rom_obj_tuple_t tft_r_pins = { + {&mp_type_tuple}, + 5, + { + MP_ROM_PTR(&pin_GPIO1), + MP_ROM_PTR(&pin_GPIO2), + MP_ROM_PTR(&pin_GPIO42), + MP_ROM_PTR(&pin_GPIO41), + MP_ROM_PTR(&pin_GPIO40), + } +}; + +static const mp_rom_obj_tuple_t tft_g_pins = { + {&mp_type_tuple}, + 6, + { + MP_ROM_PTR(&pin_GPIO21), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO45), + MP_ROM_PTR(&pin_GPIO38), + MP_ROM_PTR(&pin_GPIO39), + } +}; + +static const mp_rom_obj_tuple_t tft_b_pins = { + {&mp_type_tuple}, + 5, + { + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO12), + MP_ROM_PTR(&pin_GPIO13), + MP_ROM_PTR(&pin_GPIO14), + } +}; + +static const mp_rom_map_elem_t tft_pins_table[] = { + { MP_ROM_QSTR(MP_QSTR_de), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_vsync), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_hsync), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_dclk), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_red), MP_ROM_PTR(&tft_r_pins) }, + { MP_ROM_QSTR(MP_QSTR_green), MP_ROM_PTR(&tft_g_pins) }, + { MP_ROM_QSTR(MP_QSTR_blue), MP_ROM_PTR(&tft_b_pins) }, +}; +MP_DEFINE_CONST_DICT(tft_pins_dict, tft_pins_table); + +static const mp_rom_map_elem_t tft_timings_table[] = { + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_INT(6500000) }, // nominal 16MHz, but display is unstable/tears at that frequency + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_INT(480) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_INT(480) }, + { MP_ROM_QSTR(MP_QSTR_hsync_pulse_width), MP_ROM_INT(13) }, + { MP_ROM_QSTR(MP_QSTR_hsync_front_porch), MP_ROM_INT(20) }, + { MP_ROM_QSTR(MP_QSTR_hsync_back_porch), MP_ROM_INT(40) }, + { MP_ROM_QSTR(MP_QSTR_hsync_idle_low), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_vsync_pulse_width), MP_ROM_INT(15) }, + { MP_ROM_QSTR(MP_QSTR_vsync_front_porch), MP_ROM_INT(20) }, + { MP_ROM_QSTR(MP_QSTR_vsync_back_porch), MP_ROM_INT(40) }, + { MP_ROM_QSTR(MP_QSTR_vsync_idle_low), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_de_idle_high), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_pclk_active_high), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_pclk_idle_high), MP_ROM_FALSE }, +}; +MP_DEFINE_CONST_DICT(tft_timings_dict, tft_timings_table); + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_TFT_PINS), MP_ROM_PTR(&tft_pins_dict) }, + { MP_ROM_QSTR(MP_QSTR_TFT_TIMINGS), MP_ROM_PTR(&tft_timings_dict) }, + { MP_ROM_QSTR(MP_QSTR_TFT_IO_EXPANDER), MP_ROM_PTR(&tft_io_expander_dict) }, + { MP_ROM_QSTR(MP_QSTR_TFT_INIT_SEQUENCE), &display_init_byte_obj}, + + { MP_ROM_QSTR(MP_QSTR_I2S_SCK), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WS), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SDO), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(DEFAULT_I2C_BUS_SCL) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(DEFAULT_I2C_BUS_SDA) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + + // boot mode button can be used in SW as well + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/sdkconfig b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/espressif_esp32s3_lcd_ev_v1.5/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c index 94d08bb56c817..3b5aa06b6767e 100644 --- a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c +++ b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/board.c @@ -59,9 +59,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO4, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - &pin_GPIO8, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO4), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO8), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/mpconfigboard.mk b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/mpconfigboard.mk index 947b689fafe6d..b0abc22141806 100644 --- a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/sdkconfig b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/sdkconfig +++ b/ports/espressif/boards/espressif_esp32s3_usb_otg_n8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/mpconfigboard.mk b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/mpconfigboard.mk index 0925e8de64d2b..3631493c26718 100644 --- a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/mpconfigboard.mk @@ -6,3 +6,6 @@ IDF_TARGET = esp32c2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 60m CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/pins.c b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/pins.c index 005342e42561b..e7bf8a7764b8c 100644 --- a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/pins.c +++ b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/pins.c @@ -1,6 +1,6 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/sdkconfig b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/sdkconfig index cf803dfc43aa8..f53dd7f8795bc 100644 --- a/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/sdkconfig +++ b/ports/espressif/boards/espressif_esp8684_devkitc_02_n4/sdkconfig @@ -32,7 +32,6 @@ CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp8684" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/espressif_saola_1_wroom/mpconfigboard.mk b/ports/espressif/boards/espressif_saola_1_wroom/mpconfigboard.mk index d00bf432c976f..cb766aa231236 100644 --- a/ports/espressif/boards/espressif_saola_1_wroom/mpconfigboard.mk +++ b/ports/espressif/boards/espressif_saola_1_wroom/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/firebeetle2_esp32s3/sdkconfig b/ports/espressif/boards/firebeetle2_esp32s3/sdkconfig index 6c5d1f1986610..49798548225eb 100644 --- a/ports/espressif/boards/firebeetle2_esp32s3/sdkconfig +++ b/ports/espressif/boards/firebeetle2_esp32s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" CONFIG_OV2640_SUPPORT=y CONFIG_OV7725_SUPPORT=y # end of LWIP diff --git a/ports/espressif/boards/franzininho_wifi_wroom/mpconfigboard.mk b/ports/espressif/boards/franzininho_wifi_wroom/mpconfigboard.mk index 1cc62cb69d4ce..7b4f1e9d1d232 100644 --- a/ports/espressif/boards/franzininho_wifi_wroom/mpconfigboard.mk +++ b/ports/espressif/boards/franzininho_wifi_wroom/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/gravitech_cucumber_m/mpconfigboard.mk b/ports/espressif/boards/gravitech_cucumber_m/mpconfigboard.mk index a06ac482090a8..a77626e5104ea 100644 --- a/ports/espressif/boards/gravitech_cucumber_m/mpconfigboard.mk +++ b/ports/espressif/boards/gravitech_cucumber_m/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/gravitech_cucumber_m/sdkconfig b/ports/espressif/boards/gravitech_cucumber_m/sdkconfig index ec6db5c72ea18..e962866216039 100644 --- a/ports/espressif/boards/gravitech_cucumber_m/sdkconfig +++ b/ports/espressif/boards/gravitech_cucumber_m/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="cucumber_m" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.mk b/ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.mk index 1cdf6273beeea..f593b77cfff5c 100644 --- a/ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.mk +++ b/ports/espressif/boards/gravitech_cucumber_ms/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/gravitech_cucumber_ms/sdkconfig b/ports/espressif/boards/gravitech_cucumber_ms/sdkconfig index f3cc39cc6780e..e962866216039 100644 --- a/ports/espressif/boards/gravitech_cucumber_ms/sdkconfig +++ b/ports/espressif/boards/gravitech_cucumber_ms/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="cucumber_ms" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/gravitech_cucumber_r/sdkconfig b/ports/espressif/boards/gravitech_cucumber_r/sdkconfig index e817a86205a12..e962866216039 100644 --- a/ports/espressif/boards/gravitech_cucumber_r/sdkconfig +++ b/ports/espressif/boards/gravitech_cucumber_r/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="cucumber_r" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/gravitech_cucumber_rs/sdkconfig b/ports/espressif/boards/gravitech_cucumber_rs/sdkconfig index 873eb7207a0f7..e962866216039 100644 --- a/ports/espressif/boards/gravitech_cucumber_rs/sdkconfig +++ b/ports/espressif/boards/gravitech_cucumber_rs/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="cucumber_rs" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/hardkernel_odroid_go/board.c b/ports/espressif/boards/hardkernel_odroid_go/board.c index 647fcd740eba3..5a8b6ccaefee9 100644 --- a/ports/espressif/boards/hardkernel_odroid_go/board.c +++ b/ports/espressif/boards/hardkernel_odroid_go/board.c @@ -51,8 +51,8 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO21, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO21), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select NULL, // TFT_RST Reset 40000000, // Baudrate 0, // Polarity diff --git a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/board.c b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/board.c index 317fb0d88a1f0..d0ae146504234 100644 --- a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/board.c +++ b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/board.c @@ -34,10 +34,10 @@ uint8_t display_init_sequence[] = { // SSD1306 digitalio_digitalinout_obj_t display_on; static void display_init(void) { - // Need to bring GPIO21 high or the screen doesn't get power + // Need to bring GPIO36 high or the screen doesn't get power // & the board can't see the i2c bus at all. - common_hal_digitalio_digitalinout_construct(&display_on, &pin_GPIO21); - common_hal_digitalio_digitalinout_switch_to_output(&display_on, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_construct(&display_on, &pin_GPIO36); + common_hal_digitalio_digitalinout_switch_to_output(&display_on, false, DRIVE_MODE_PUSH_PULL); common_hal_digitalio_digitalinout_never_reset(&display_on); busio_i2c_obj_t *i2c = common_hal_board_create_i2c(0); @@ -48,7 +48,7 @@ static void display_init(void) { bus, i2c, 0x3c, - NULL + &pin_GPIO21 // broken-out on V3 ); busdisplay_busdisplay_obj_t *display = &allocate_display()->display; diff --git a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/mpconfigboard.mk b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/mpconfigboard.mk index 633cca09823dc..d5cbac7ea59d4 100644 --- a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/mpconfigboard.mk +++ b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/mpconfigboard.mk @@ -20,10 +20,5 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_DISPLAYIO = 1 - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text -FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_RFM9x diff --git a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/sdkconfig b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/sdkconfig index ab4e9875add9e..a71099850d5ff 100644 --- a/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/sdkconfig +++ b/ports/espressif/boards/heltec_esp32s3_wifi_lora_v3/sdkconfig @@ -8,7 +8,6 @@ # LWIP # CONFIG_ESP_PHY_ENABLE_USB=n -CONFIG_LWIP_LOCAL_HOSTNAME="HELTEC-ESP32S3-V3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/heltec_vision_master_e290/board.c b/ports/espressif/boards/heltec_vision_master_e290/board.c new file mode 100644 index 0000000000000..5a102c7119bd0 --- /dev/null +++ b/ports/espressif/boards/heltec_vision_master_e290/board.c @@ -0,0 +1,107 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +const uint8_t display_start_sequence[] = { + 0x12, 0x80, 0x14, // Soft reset and wait 20ms + 0x11, 0x01, 0x03, // Ram data entry mode + 0x3c, 0x01, 0x05, // border color + 0x2c, 0x01, 0x36, // set vcom voltage + 0x03, 0x01, 0x17, // Set gate voltage + 0x04, 0x03, 0x41, 0x00, 0x32, // Set source voltage + 0x4e, 0x01, 0x01, // ram x count + 0x4f, 0x02, 0x00, 0x00, // ram y count + 0x01, 0x03, 0x27, 0x01, 0x00, // set display size + 0x22, 0x01, 0xf4, // display update mode +}; + +const uint8_t display_stop_sequence[] = { + 0x10, 0x81, 0x01, 0x64, // Deep sleep +}; + +const uint8_t refresh_sequence[] = { + 0x20, +}; + +void board_init(void) { + + // Set vext high to enable EPD + digitalio_digitalinout_obj_t vext_pin_obj; + vext_pin_obj.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&vext_pin_obj, &pin_GPIO18); + common_hal_digitalio_digitalinout_switch_to_output(&vext_pin_obj, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&vext_pin_obj); + + // Set up the SPI object used to control the display + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO2, &pin_GPIO1, NULL, false); + common_hal_busio_spi_never_reset(spi); + + // Set up the DisplayIO pin object + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO4), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO3), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO5), // EPD_RST Reset + 1000000, // Baudrate + 0, // Polarity + 0); // Phase + + // Set up the DisplayIO epaper object + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 250; + args.ram_height = 296; + args.colstart = 8; + args.rotation = 90; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4E; + args.set_current_row_command = 0x4F; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.highlight_color = 0xFF0000; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO6; + args.busy_state = true; + args.seconds_per_frame = 2.0; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.h b/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.h new file mode 100644 index 0000000000000..f46fcf30cd604 --- /dev/null +++ b/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Heltec Vison Master E290" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_GPIO2, .mosi = &pin_GPIO1, .miso = NULL}, \ + {.clock = &pin_GPIO9, .mosi = &pin_GPIO10, .miso = &pin_GPIO11}, \ +} + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN { \ + {.scl = &pin_GPIO38, .sda = &pin_GPIO39}, \ +} + +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) diff --git a/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.mk b/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.mk new file mode 100644 index 0000000000000..e5ab355fee9ec --- /dev/null +++ b/ports/espressif/boards/heltec_vision_master_e290/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x82C9 +USB_PRODUCT = "Vision Master E290" +USB_MANUFACTURER = "Heltec" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/heltec_vision_master_e290/pins.c b/ports/espressif/boards/heltec_vision_master_e290/pins.c new file mode 100644 index 0000000000000..9fb7b797fb1c7 --- /dev/null +++ b/ports/espressif/boards/heltec_vision_master_e290/pins.c @@ -0,0 +1,77 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(epd_spi, spi, 0) +CIRCUITPY_BOARD_BUS_SINGLETON(lora_spi, spi, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // User buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_GPIO21) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_GPIO45) }, + + // ADC (When ADC_CTRL is high, VBAT is connected to ADC_IN with 390K/100K voltage divider) + { MP_ROM_QSTR(MP_QSTR_ADC_CTRL), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_ADC_IN), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO7) }, + + // VEXT powers epd and lora antenna boost when high + { MP_ROM_QSTR(MP_QSTR_VEXT_CTRL), MP_ROM_PTR(&pin_GPIO18) }, + + // LORA SPI, Reset, and More + { MP_ROM_QSTR(MP_QSTR_LORA_CS), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LORA_SCK), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LORA_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LORA_MISO), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LORA_RESET), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LORA_BUSY), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LORA_DIO1), MP_ROM_PTR(&pin_GPIO14) }, + + // eInk Display + { MP_ROM_QSTR(MP_QSTR_EPD_MOSI), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SCK), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CS), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_EPD_DC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_EPD_RESET), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_EPD_BUSY), MP_ROM_PTR(&pin_GPIO6) }, + + // I2C on external connector P2 + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO39) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // User available pins on GPIO header + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT pin (IO0) is on header + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SPI), MP_ROM_PTR(&board_epd_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_LORA_SPI), MP_ROM_PTR(&board_lora_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/heltec_vision_master_e290/sdkconfig b/ports/espressif/boards/heltec_vision_master_e290/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/heltec_vision_master_e290/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/heltec_wireless_paper/board.c b/ports/espressif/boards/heltec_wireless_paper/board.c new file mode 100644 index 0000000000000..38f6472e085e6 --- /dev/null +++ b/ports/espressif/boards/heltec_wireless_paper/board.c @@ -0,0 +1,139 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +const uint8_t display_start_sequence[] = { + 0x04, 0x80, 0xc8, // power on + 0x00, 0x01, 0x1f, // panel setting + 0x50, 0x01, 0x97, // CDI setting + + // common voltage + 0x20, 0x2a, + 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, + 0x60, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x13, 0x0A, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // White to White + 0x21, 0x2a, + 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x10, 0x14, 0x0A, 0x00, 0x00, 0x01, + 0xA0, 0x13, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Black to White + 0x22, 0x2a, + 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x0A, 0x00, 0x00, 0x01, + 0x99, 0x0B, 0x04, 0x04, 0x01, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // White to Black + 0x23, 0x2a, + 0x40, 0x0A, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x00, 0x14, 0x0A, 0x00, 0x00, 0x01, + 0x99, 0x0C, 0x01, 0x03, 0x04, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Black to Black + 0x24, 0x2a, + 0x80, 0x0A, 0x00, 0x00, 0x00, 0x01, + 0x90, 0x14, 0x14, 0x00, 0x00, 0x01, + 0x20, 0x14, 0x0A, 0x00, 0x00, 0x01, + 0x50, 0x13, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const uint8_t display_stop_sequence[] = { + 0x50, 0x01, 0xf7, + 0x07, 0x01, 0xa5, +}; + +const uint8_t refresh_sequence[] = { + 0x12, +}; + +void board_init(void) { + + // Set vext on (active low) to enable EPD + digitalio_digitalinout_obj_t vext_pin_obj; + vext_pin_obj.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&vext_pin_obj, &pin_GPIO45); + common_hal_digitalio_digitalinout_switch_to_output(&vext_pin_obj, false, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&vext_pin_obj); + + // Set up the SPI object used to control the display + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO3, &pin_GPIO2, NULL, false); + common_hal_busio_spi_never_reset(spi); + + // Set up the DisplayIO pin object + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO5), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO4), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO6), // EPD_RST Reset + 1000000, // Baudrate + 0, // Polarity + 0); // Phase + + // Set up the DisplayIO epaper object + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 250; + args.height = 122; + args.ram_width = 128; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = 0x13; + args.write_color_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO7; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.h b/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.h new file mode 100644 index 0000000000000..0c54e3276c530 --- /dev/null +++ b/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Heltec Wireless Paper" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_GPIO3, .mosi = &pin_GPIO2, .miso = NULL}, \ + {.clock = &pin_GPIO9, .mosi = &pin_GPIO10, .miso = &pin_GPIO11}, \ +} + +// UART definition for UART connected to the CP210x +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +// Serial over UART +#define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX +#define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX diff --git a/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.mk b/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.mk new file mode 100644 index 0000000000000..35a9ac1402ed7 --- /dev/null +++ b/ports/espressif/boards/heltec_wireless_paper/mpconfigboard.mk @@ -0,0 +1,21 @@ +# Product URL: https://heltec.org/project/wifi-lora-32-v3/ +# Schematic: https://resource.heltec.cn/download/WiFi_LoRa32_V3/HTIT-WB32LA(F)_V3_Schematic_Diagram.pdf +# Datasheet: https://resource.heltec.cn/download/WiFi_LoRa32_V3/HTIT-WB32LA_V3(Rev1.1).pdf +# Pinout: https://resource.heltec.cn/download/WiFi_LoRa32_V3/HTIT-WB32LA(F)_V3.png + +CIRCUITPY_CREATOR_ID = 0x148E173C +CIRCUITPY_CREATION_ID = 0x00530002 + +USB_PRODUCT = "Heltec-Wireless-Paper" +USB_MANUFACTURER = "Heltec" + +IDF_TARGET = esp32s3 + +# This board doesn't have USB by default, it +# instead uses a CP2102 USB-to-Serial chip +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB diff --git a/ports/espressif/boards/heltec_wireless_paper/pins.c b/ports/espressif/boards/heltec_wireless_paper/pins.c new file mode 100644 index 0000000000000..908fd0f5dacbc --- /dev/null +++ b/ports/espressif/boards/heltec_wireless_paper/pins.c @@ -0,0 +1,55 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Sole programmable button + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_GPIO18) }, + + // ADC (When ADC_CTRL is low, VBAT is connected to ADC_IN with 10K/10K voltage divider) + { MP_ROM_QSTR(MP_QSTR_ADC_CTRL), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_ADC_IN), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO20) }, + + // VEXT powers epd and lora antenna boost when low + { MP_ROM_QSTR(MP_QSTR_VEXT_CTRL), MP_ROM_PTR(&pin_GPIO45) }, + + // UART that's connected to CP210x over USB + { MP_ROM_QSTR(MP_QSTR_DEBUG_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_DEBUG_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // LORA SPI, Reset, and More + { MP_ROM_QSTR(MP_QSTR_LORA_CS), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LORA_SCK), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LORA_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LORA_MISO), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LORA_RESET), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LORA_BUSY), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LORA_DIO1), MP_ROM_PTR(&pin_GPIO14) }, + + // eInk Display + { MP_ROM_QSTR(MP_QSTR_EPD_MOSI), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SCK), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_EPD_DC), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_EPD_RES), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_EPD_BUSY), MP_ROM_PTR(&pin_GPIO7) }, + + // objects + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/heltec_wireless_paper/sdkconfig b/ports/espressif/boards/heltec_wireless_paper/sdkconfig new file mode 100644 index 0000000000000..a71099850d5ff --- /dev/null +++ b/ports/espressif/boards/heltec_wireless_paper/sdkconfig @@ -0,0 +1,15 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +CONFIG_ESP_PHY_ENABLE_USB=n +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/hexky_s2/board.c b/ports/espressif/boards/hexky_s2/board.c index 2c076d58e1c28..41f97796be4fb 100644 --- a/ports/espressif/boards/hexky_s2/board.c +++ b/ports/espressif/boards/hexky_s2/board.c @@ -57,9 +57,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO34, // DC - &pin_GPIO33, // CS - &pin_GPIO41, // RST + MP_OBJ_FROM_PTR(&pin_GPIO34), // DC + MP_OBJ_FROM_PTR(&pin_GPIO33), // CS + MP_OBJ_FROM_PTR(&pin_GPIO41), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -103,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 21) { // Turn on TFT and I2C - gpio_set_direction(21, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(21, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/hexky_s2/mpconfigboard.mk b/ports/espressif/boards/hexky_s2/mpconfigboard.mk index 94d98aa8654d5..825d8721333bf 100644 --- a/ports/espressif/boards/hexky_s2/mpconfigboard.mk +++ b/ports/espressif/boards/hexky_s2/mpconfigboard.mk @@ -10,8 +10,8 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel - CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/hiibot_iots2/board.c b/ports/espressif/boards/hiibot_iots2/board.c index e9941cbc3685c..e4bff05822c33 100644 --- a/ports/espressif/boards/hiibot_iots2/board.c +++ b/ports/espressif/boards/hiibot_iots2/board.c @@ -62,8 +62,8 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO35, // DC - &pin_GPIO36, // CS + MP_OBJ_FROM_PTR(&pin_GPIO35), // DC + MP_OBJ_FROM_PTR(&pin_GPIO36), // CS NULL, // NO RST ? 40000000, // baudrate 0, // polarity diff --git a/ports/espressif/boards/hiibot_iots2/mpconfigboard.mk b/ports/espressif/boards/hiibot_iots2/mpconfigboard.mk index 743acf85a4587..3d3c584c7024b 100644 --- a/ports/espressif/boards/hiibot_iots2/mpconfigboard.mk +++ b/ports/espressif/boards/hiibot_iots2/mpconfigboard.mk @@ -8,7 +8,6 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -#CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio diff --git a/ports/espressif/boards/hiibot_iots2/sdkconfig b/ports/espressif/boards/hiibot_iots2/sdkconfig index b2b83eb6e6c47..e962866216039 100644 --- a/ports/espressif/boards/hiibot_iots2/sdkconfig +++ b/ports/espressif/boards/hiibot_iots2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="HiiBot_IoTs2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_tdeck/board.c b/ports/espressif/boards/lilygo_tdeck/board.c index f2b3ebb12c83e..a1008f2173f89 100644 --- a/ports/espressif/boards/lilygo_tdeck/board.c +++ b/ports/espressif/boards/lilygo_tdeck/board.c @@ -32,8 +32,8 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO11, // TFT_DC Command or data - &pin_GPIO12, // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO11), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO12), // TFT_CS Chip select NULL, // TFT_RST Reset 60000000, // Baudrate 0, // Polarity @@ -72,4 +72,13 @@ void board_init(void) { 50000); // backlight pwm frequency } +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + if (pin_number == 10) { + // Pull screen power high + config_pin_as_output_with_level(pin_number, true); + return true; + } + return false; +} + // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/lilygo_tdeck/mpconfigboard.h b/ports/espressif/boards/lilygo_tdeck/mpconfigboard.h index aca85d815e0ab..48bca4a2d0e48 100644 --- a/ports/espressif/boards/lilygo_tdeck/mpconfigboard.h +++ b/ports/espressif/boards/lilygo_tdeck/mpconfigboard.h @@ -8,7 +8,7 @@ // Micropython setup -#define MICROPY_HW_BOARD_NAME "LILYGO T-DECK" +#define MICROPY_HW_BOARD_NAME "LILYGO T-Deck (Plus)" #define MICROPY_HW_MCU_NAME "ESP32S3" #define DEFAULT_SPI_BUS_SCK (&pin_GPIO40) diff --git a/ports/espressif/boards/lilygo_tdeck/mpconfigboard.mk b/ports/espressif/boards/lilygo_tdeck/mpconfigboard.mk index 52399a81d664e..fc30e96c793aa 100644 --- a/ports/espressif/boards/lilygo_tdeck/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_tdeck/mpconfigboard.mk @@ -1,6 +1,6 @@ USB_VID = 0x303A USB_PID = 0x81B6 -USB_PRODUCT = "T DECK" +USB_PRODUCT = "T-Deck (Plus)" USB_MANUFACTURER = "LILYGO" IDF_TARGET = esp32s3 @@ -12,3 +12,13 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_MAX3421E = 0 +CIRCUITPY_PS2IO = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_ROTARYIO = 0 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FocalTouch +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/espressif/boards/lilygo_tdeck/pins.c b/ports/espressif/boards/lilygo_tdeck/pins.c index 256c1453149f0..fe489d4561a49 100644 --- a/ports/espressif/boards/lilygo_tdeck/pins.c +++ b/ports/espressif/boards/lilygo_tdeck/pins.c @@ -10,99 +10,117 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, - { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, - { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, - { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, - { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, - { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, - { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, - { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, - { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, - { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, - { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, - { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, - { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, - { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + // SPI + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO40) }, { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, - { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, - { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, - { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, - { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, - { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, - { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, - { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, - { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, - - { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, - { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, - // SPI control pins - { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO40) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, - // I2C control pins + // I2C { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - // TFT control pins + // Display { MP_ROM_QSTR(MP_QSTR_TFT_BKLT), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, - // SD card control pins + // SD card { MP_ROM_QSTR(MP_QSTR_SDCARD_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, // Input Interrupts { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_KEYBOARD_INT), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Trackball control pins { MP_ROM_QSTR(MP_QSTR_TRACKBALL_CLICK), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TRACKBALL_UP), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TRACKBALL_DOWN), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_TRACKBALL_LEFT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_TRACKBALL_RIGHT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, // Microphone control pins { MP_ROM_QSTR(MP_QSTR_MICROPHONE_SCK), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_WS), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DIN), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_MICROPHONE_MCK), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, // Speaker control pins { MP_ROM_QSTR(MP_QSTR_SPEAKER_SCK), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_WS), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_DOUT), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, // LoRa control pins { MP_ROM_QSTR(MP_QSTR_LORA_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LORA_DIO1), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_LORA_RST), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_LORA_BUSY), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, // Battery and Peripheral Power { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_POWER_ON), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, - { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + // Port, used for GPS + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, - { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) } }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/lilygo_tdeck/sdkconfig b/ports/espressif/boards/lilygo_tdeck/sdkconfig index 35bfb64a016c8..e962866216039 100644 --- a/ports/espressif/boards/lilygo_tdeck/sdkconfig +++ b/ports/espressif/boards/lilygo_tdeck/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="T-DECK" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_tdisplay_s3/board.c b/ports/espressif/boards/lilygo_tdisplay_s3/board.c index 74bdd4fa11e21..fe62edf1ed84b 100644 --- a/ports/espressif/boards/lilygo_tdisplay_s3/board.c +++ b/ports/espressif/boards/lilygo_tdisplay_s3/board.c @@ -101,8 +101,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Override the I2C/TFT power pin reset to prevent resetting the display. if (pin_number == 15) { // Turn on TFT - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/lilygo_tdisplay_s3/sdkconfig b/ports/espressif/boards/lilygo_tdisplay_s3/sdkconfig index 7c9743375931c..e962866216039 100644 --- a/ports/espressif/boards/lilygo_tdisplay_s3/sdkconfig +++ b/ports/espressif/boards/lilygo_tdisplay_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="T-DISPLAY-S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_tdisplay_s3_pro/board.c b/ports/espressif/boards/lilygo_tdisplay_s3_pro/board.c index ede20df200fa9..0782e2161ca8a 100644 --- a/ports/espressif/boards/lilygo_tdisplay_s3_pro/board.c +++ b/ports/espressif/boards/lilygo_tdisplay_s3_pro/board.c @@ -34,9 +34,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO9, // TFT_DC Command or data - &pin_GPIO39, // TFT_CS Chip select - &pin_GPIO47, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO39), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO47), // TFT_RST Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/lilygo_tdisplay_s3_pro/sdkconfig b/ports/espressif/boards/lilygo_tdisplay_s3_pro/sdkconfig index 03805d7f206cd..a12cbe62f1487 100644 --- a/ports/espressif/boards/lilygo_tdisplay_s3_pro/sdkconfig +++ b/ports/espressif/boards/lilygo_tdisplay_s3_pro/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="T-Display S3 Pro" # end of LWIP # diff --git a/ports/espressif/boards/lilygo_tdongle_s3/board.c b/ports/espressif/boards/lilygo_tdongle_s3/board.c new file mode 100644 index 0000000000000..ede75a5842e35 --- /dev/null +++ b/ports/espressif/boards/lilygo_tdongle_s3/board.c @@ -0,0 +1,111 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +#define DELAY 0x80 + +// display init sequence according to Adafruit_CircuitPython_ST7735R +// https://github.com/adafruit/Adafruit_CircuitPython_ST7735R +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 0x96, + // SLPOUT and Delay + 0x11, 0 | DELAY, 0xFF, + 0xB1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xB3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3 + 0xB4, 0x01, 0x07, // _INVCTR line inversion + 0xC0, 0x03, 0xA2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xC1, 0x01, 0xC5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xC2, 0x02, 0x0A, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xC3, 0x02, 0x8A, 0x2A, + 0xC4, 0x02, 0x8A, 0xEE, + 0xC5, 0x01, 0x0E, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x20, 0x00, // _INVOFF + 0x36, 0x01, 0x18, // _MADCTL bottom to top refresh + // 1 clk cycle nonoverlap, 2 cycle gate rise, 3 cycle osc equalie, + // fix on VTL + 0x3A, 0x01, 0x05, // COLMOD - 16bit color + 0xE0, 0x10, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma + 0xE1, 0x10, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1 + 0x13, 0 | DELAY, 0x0A, // _NORON + 0x29, 0 | DELAY, 0x64, // _DISPON + // 0x36, 0x01, 0xC0, // _MADCTL Default rotation plus BGR encoding + 0x36, 0x01, 0xC8, // _MADCTL Default rotation plus RGB encoding + 0x21, 0x00, // _INVON +}; + +static void display_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + + common_hal_busio_spi_construct( + spi, + &pin_GPIO5, // CLK + &pin_GPIO3, // MOSI + NULL, // MISO not connected + false); // Not half-duplex + + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO2), // DC + MP_OBJ_FROM_PTR(&pin_GPIO4), // CS + MP_OBJ_FROM_PTR(&pin_GPIO1), // RST + 10000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 160, // width (after rotation) + 80, // height (after rotation) + 26, // column start + 1, // row start + 90, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO38, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Display + display_init(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.h b/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.h new file mode 100644 index 0000000000000..0edea0bf63b40 --- /dev/null +++ b/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "LILYGO T-Dongle S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_APA102_MOSI (&pin_GPIO40) +#define MICROPY_HW_APA102_SCK (&pin_GPIO39) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO44) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO43) diff --git a/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.mk b/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.mk new file mode 100644 index 0000000000000..bc883366b5d8c --- /dev/null +++ b/ports/espressif/boards/lilygo_tdongle_s3/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x303a +USB_PID = 0x82C2 +USB_PRODUCT = "T-Dongle S3" +USB_MANUFACTURER = "LILYGO" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +# Few pins. +CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lilygo_tdongle_s3/pins.c b/ports/espressif/boards/lilygo_tdongle_s3/pins.c new file mode 100644 index 0000000000000..42fd1424cc688 --- /dev/null +++ b/ports/espressif/boards/lilygo_tdongle_s3/pins.c @@ -0,0 +1,65 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // 1 to 1 mappings + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + // Reset Button + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + + // RX and TX + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // Stemma port (if available) + { MP_ROM_QSTR(MP_QSTR_STEMMA_SDA), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_SCL), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // 0.96 inch LCD ST7735 + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DIN), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + + // APA102 control pins (Leds) + { MP_ROM_QSTR(MP_QSTR_APA102_CLK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_APA102_DI), MP_ROM_PTR(&pin_GPIO40) }, + + // SD card control pins + { MP_ROM_QSTR(MP_QSTR_SD_D0), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SD_D1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SD_D2), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SD_D3), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO16) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/lilygo_tdongle_s3/sdkconfig b/ports/espressif/boards/lilygo_tdongle_s3/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/lilygo_tdongle_s3/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/board.c b/ports/espressif/boards/lilygo_tembed_esp32s3/board.c index b8dfc4d5b1450..46e2ecf863c19 100644 --- a/ports/espressif/boards/lilygo_tembed_esp32s3/board.c +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/board.c @@ -17,8 +17,9 @@ uint8_t display_init_sequence[] = { 0x01, 0x80, 0x96, // _SWRESET and Delay 150ms 0x11, 0x80, 0xFF, // _SLPOUT and Delay 500ms 0x3A, 0x81, 0x55, 0x0A, // _COLMOD and Delay 10ms + 0x21, 0x80, 0xA, // _INVON 0x13, 0x80, 0x0A, // _NORON and Delay 10ms - 0x36, 0x01, 0xC8, // _MADCTL + 0x36, 0x01, 0xC0, // _MADCTL 0x29, 0x80, 0xFF, // _DISPON and Delay 500ms }; @@ -31,9 +32,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO13, // TFT_DC Command or data - &pin_GPIO10, // TFT_CS Chip select - &pin_GPIO9, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO13), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO10), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h index 18bf2ac67dee6..2ba9717b88d99 100644 --- a/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/mpconfigboard.h @@ -11,7 +11,9 @@ #define MICROPY_HW_BOARD_NAME "LILYGO TEMBED ESP32S3" #define MICROPY_HW_MCU_NAME "ESP32S3" -#define MICROPY_HW_NEOPIXEL (&pin_GPIO48) +#define MICROPY_HW_APA102_MOSI (&pin_GPIO42) +#define MICROPY_HW_APA102_SCK (&pin_GPIO45) +#define MICROPY_HW_APA102_COUNT (7) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) #define DEFAULT_SPI_BUS_SCK (&pin_GPIO12) diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c b/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c index 58cf8a71e27a8..7984a829b16fe 100644 --- a/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/pins.c @@ -46,7 +46,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, - { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO48) }, { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, diff --git a/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig b/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig +++ b/ports/espressif/boards/lilygo_tembed_esp32s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_tqt_pro_nopsram/board.c b/ports/espressif/boards/lilygo_tqt_pro_nopsram/board.c new file mode 100644 index 0000000000000..fe72222a22cbe --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_nopsram/board.c @@ -0,0 +1,100 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 150, + // sleep out + 0x11, 0 | DELAY, 255, + // normal display mode on + 0x13, 0, + // display and color format settings + 0x36, 1, 0x68, + 0xB6, 2, 0x0A, 0x82, + 0x3A, 1 | DELAY, 0x55, 10, + // ST7789V frame rate setting + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // voltages: VGH / VGL + 0xB7, 1, 0x35, + // ST7789V power setting + 0xBB, 1, 0x28, + 0xC0, 1, 0x0C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x10, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + // ST7789V gamma setting + 0xE0, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + 0xE1, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + 0x21, 0, + // display on + 0x29, 0 | DELAY, 255, +}; + + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO6), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO1), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 1, // column start + 2, // row start + 90, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO10, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + false, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} diff --git a/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.h b/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.h new file mode 100644 index 0000000000000..6aa9ea30b9ed2 --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "LILYGO T-QT PRO NO PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO44, .sda = &pin_GPIO43}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO3, .mosi = &pin_GPIO2}} diff --git a/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.mk b/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.mk new file mode 100644 index 0000000000000..5c7ff943cb31d --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_nopsram/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303a +USB_PID = 0x8154 +USB_PRODUCT = "T-QT PRO NO PSRAM" +USB_MANUFACTURER = "LILYGO" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Not enough pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/lilygo_tqt_pro_nopsram/pins.c b/ports/espressif/boards/lilygo_tqt_pro_nopsram/pins.c new file mode 100644 index 0000000000000..e26e885ef54ff --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_nopsram/pins.c @@ -0,0 +1,56 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // front buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + + // Left side top to bottom + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + + // Right side top to bottom + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // Stemma QT port + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // 0.85 inch LCD GC9107 + { MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/lilygo_tqt_pro_nopsram/sdkconfig b/ports/espressif/boards/lilygo_tqt_pro_nopsram/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/lilygo_tqt_pro_psram/board.c b/ports/espressif/boards/lilygo_tqt_pro_psram/board.c new file mode 100644 index 0000000000000..fe72222a22cbe --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_psram/board.c @@ -0,0 +1,100 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 150, + // sleep out + 0x11, 0 | DELAY, 255, + // normal display mode on + 0x13, 0, + // display and color format settings + 0x36, 1, 0x68, + 0xB6, 2, 0x0A, 0x82, + 0x3A, 1 | DELAY, 0x55, 10, + // ST7789V frame rate setting + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // voltages: VGH / VGL + 0xB7, 1, 0x35, + // ST7789V power setting + 0xBB, 1, 0x28, + 0xC0, 1, 0x0C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x10, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + // ST7789V gamma setting + 0xE0, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + 0xE1, 14, 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + 0x21, 0, + // display on + 0x29, 0 | DELAY, 255, +}; + + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO6), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO1), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 1, // column start + 2, // row start + 90, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO10, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + false, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} diff --git a/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.h b/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.h new file mode 100644 index 0000000000000..b0140b746ee0c --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "LILYGO T-QT PRO PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO44, .sda = &pin_GPIO43}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO3, .mosi = &pin_GPIO2}} diff --git a/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.mk b/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.mk new file mode 100644 index 0000000000000..2006f98fbd7d9 --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_psram/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x303a +USB_PID = 0x8154 +USB_PRODUCT = "T-QT PRO PSRAM" +USB_MANUFACTURER = "LILYGO" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 4MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Not enough pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/lilygo_tqt_pro_psram/pins.c b/ports/espressif/boards/lilygo_tqt_pro_psram/pins.c new file mode 100644 index 0000000000000..e26e885ef54ff --- /dev/null +++ b/ports/espressif/boards/lilygo_tqt_pro_psram/pins.c @@ -0,0 +1,56 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // front buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + + // Left side top to bottom + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + + // Right side top to bottom + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // Stemma QT port + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // 0.85 inch LCD GC9107 + { MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/lilygo_tqt_pro_psram/sdkconfig b/ports/espressif/boards/lilygo_tqt_pro_psram/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/lilygo_ttgo_t-01c3/mpconfigboard.mk b/ports/espressif/boards/lilygo_ttgo_t-01c3/mpconfigboard.mk index 0fd65d99d6eea..8550c526defc4 100644 --- a/ports/espressif/boards/lilygo_ttgo_t-01c3/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_ttgo_t-01c3/mpconfigboard.mk @@ -8,3 +8,6 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/lilygo_ttgo_t-01c3/sdkconfig b/ports/espressif/boards/lilygo_ttgo_t-01c3/sdkconfig index 54105bd51b394..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_t-01c3/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_t-01c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LILYGO TTGO T-01C3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_ttgo_t-oi-plus/mpconfigboard.mk b/ports/espressif/boards/lilygo_ttgo_t-oi-plus/mpconfigboard.mk index d7eba6ea262ce..35ac1d44c6230 100644 --- a/ports/espressif/boards/lilygo_ttgo_t-oi-plus/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_ttgo_t-oi-plus/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/lilygo_ttgo_t-oi-plus/sdkconfig b/ports/espressif/boards/lilygo_ttgo_t-oi-plus/sdkconfig index fc0f5c6edd200..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_t-oi-plus/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_t-oi-plus/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LILYGO TTGO T-OI PLUS" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_ttgo_t8_esp32_s2_wroom/mpconfigboard.mk b/ports/espressif/boards/lilygo_ttgo_t8_esp32_s2_wroom/mpconfigboard.mk index 0fbcf5c62bf77..8cacf57efdf35 100644 --- a/ports/espressif/boards/lilygo_ttgo_t8_esp32_s2_wroom/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_ttgo_t8_esp32_s2_wroom/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lilygo_ttgo_t8_s2/sdkconfig b/ports/espressif/boards/lilygo_ttgo_t8_s2/sdkconfig index 23f6593f1b23e..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_t8_s2/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_t8_s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="TTGO-T8-ESP32-S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/board.c b/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/board.c index 2b77e24b91e7b..6fcfb5c19a479 100644 --- a/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/board.c +++ b/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/board.c @@ -62,9 +62,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO37, // DC - &pin_GPIO34, // CS - &pin_GPIO38, // RST + MP_OBJ_FROM_PTR(&pin_GPIO37), // DC + MP_OBJ_FROM_PTR(&pin_GPIO34), // CS + MP_OBJ_FROM_PTR(&pin_GPIO38), // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/sdkconfig b/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/sdkconfig index 23f6593f1b23e..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_t8_s2_st7789/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="TTGO-T8-ESP32-S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/board.c b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/board.c index 97574398ca2c1..8ed5462a2d364 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/board.c +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/board.c @@ -42,9 +42,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO16, // DC - &pin_GPIO5, // CS - &pin_GPIO23, // RST + MP_OBJ_FROM_PTR(&pin_GPIO16), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO23), // RST 24000000, // baudrate (default from the driver) // 40000000, 0, // polarity diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/mpconfigboard.mk b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/mpconfigboard.mk index dd177ec1c900d..e76ffaba31020 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/mpconfigboard.mk @@ -6,5 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 16MB - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/sdkconfig b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/sdkconfig index 61beea449b11d..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_16m/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="TTGO-TDISPLAY" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/board.c b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/board.c index 2d3cb64d4559c..a90cc5eb66adb 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/board.c +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/board.c @@ -41,9 +41,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO16, // DC - &pin_GPIO5, // CS - &pin_GPIO23, // RST + MP_OBJ_FROM_PTR(&pin_GPIO16), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO23), // RST 24000000, // baudrate (default from the driver) // 40000000, 0, // polarity diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/mpconfigboard.mk b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/mpconfigboard.mk index af1bd8b178980..8e89a6a2b3aa4 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/sdkconfig b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/sdkconfig index 61beea449b11d..e962866216039 100644 --- a/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/sdkconfig +++ b/ports/espressif/boards/lilygo_ttgo_tdisplay_esp32_4m/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="TTGO-TDISPLAY" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lilygo_twatch_2020_v3/board.c b/ports/espressif/boards/lilygo_twatch_2020_v3/board.c index 3860ca61be66d..e88a82ea24f5b 100644 --- a/ports/espressif/boards/lilygo_twatch_2020_v3/board.c +++ b/ports/espressif/boards/lilygo_twatch_2020_v3/board.c @@ -46,8 +46,8 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO5, // CS + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS NULL, // RST 24000000, // baudrate 0, // polarity @@ -131,8 +131,7 @@ void board_init(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == MOTOR_PIN) { // no motor - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; diff --git a/ports/espressif/boards/lilygo_twatch_2020_v3/sdkconfig b/ports/espressif/boards/lilygo_twatch_2020_v3/sdkconfig index d1e302072ae37..e69de29bb2d1d 100644 --- a/ports/espressif/boards/lilygo_twatch_2020_v3/sdkconfig +++ b/ports/espressif/boards/lilygo_twatch_2020_v3/sdkconfig @@ -1,22 +0,0 @@ -# -# Espressif IoT Development Framework Configuration -# -# -# Component config -# -# -# ESP System Settings -# -CONFIG_ESP_CONSOLE_UART_CUSTOM=y -# CONFIG_ESP_CONSOLE_NONE is not set -CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y -CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_TX_GPIO=1 -CONFIG_ESP_CONSOLE_UART_RX_GPIO=3 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -# end of ESP System Settings - -# end of Component config - -# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/lilygo_twatch_s3/board.c b/ports/espressif/boards/lilygo_twatch_s3/board.c index 0b1f4f4b31dc2..801914a4991c0 100644 --- a/ports/espressif/boards/lilygo_twatch_s3/board.c +++ b/ports/espressif/boards/lilygo_twatch_s3/board.c @@ -7,6 +7,7 @@ #include "supervisor/board.h" #include "mpconfigboard.h" #include "shared-bindings/busio/SPI.h" +#include "shared-bindings/busio/I2C.h" #include "shared-bindings/fourwire/FourWire.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/displayio/__init__.h" @@ -48,8 +49,58 @@ uint8_t display_init_sequence[] = { 0x29, 0 | DELAY, 255, }; +#define AXP2101_I2C_ADDRESS 0x34 + +static void write_register8(busio_i2c_obj_t *i2c, uint8_t reg, uint8_t value) { + uint8_t buffer[2]; + buffer[0] = reg; + buffer[1] = value; + common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, buffer, 2); +} + +static void set_bit_in_register(busio_i2c_obj_t *i2c, uint8_t reg, uint8_t bitmask) { + uint8_t buffer[2]; + buffer[0] = reg; + buffer[1] = 0; + common_hal_busio_i2c_write_read(i2c, AXP2101_I2C_ADDRESS, &buffer[0], 1, &buffer[1], 1); + buffer[1] |= bitmask; + common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, buffer, 2); +} + +static void enable_ldo(busio_i2c_obj_t *i2c, uint8_t ldo) { + write_register8(i2c, ldo + 0x92, 0x1C); // 3300mV + set_bit_in_register(i2c, 0x90, 1 << ldo); +} + +static void enable_dldo(busio_i2c_obj_t *i2c, uint8_t ldo) { + if (ldo == 1) { + write_register8(i2c, 0x99, 0x1C); // 3300mV + set_bit_in_register(i2c, 0x90, 0x80); + } +} + +// Init the AXP2101 by hand as to not include XPOWERS lib. +static void pmic_init(busio_i2c_obj_t *i2c) { + enable_ldo(i2c, 0); // _aldo1 + enable_ldo(i2c, 1); // _aldo2 + enable_ldo(i2c, 2); // _aldo3 + enable_ldo(i2c, 3); // _aldo4 + enable_ldo(i2c, 5); // _bldo2 + enable_dldo(i2c, 1); // _dldo1 + write_register8(i2c, 0x18, 0x0F); // Enable charging of main Bat and Coin cell + write_register8(i2c, 0x27, 0x1F); // 2s on time + 10s off time + write_register8(i2c, 0x62, 0x0B); // 500mA Current limit + write_register8(i2c, 0x16, 0x04); // 1.5A INcurr limit + write_register8(i2c, 0x61, 0x06); // 150mA Precharge limit + write_register8(i2c, 0x64, 0x03); // 4.2V Voltage target + write_register8(i2c, 0x63, 0x11); // 25mA Charging termination current +} + void board_init(void) { + busio_i2c_obj_t *internal_i2c = common_hal_board_create_i2c(0); + pmic_init(internal_i2c); + busio_spi_obj_t *spi = common_hal_board_create_spi(0); fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; bus->base.type = &fourwire_fourwire_type; @@ -57,8 +108,8 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO38, // DC - &pin_GPIO12, // CS + MP_OBJ_FROM_PTR(&pin_GPIO38), // DC + MP_OBJ_FROM_PTR(&pin_GPIO12), // CS NULL, // RST 40000000, // baudrate 0, // polarity diff --git a/ports/espressif/boards/lilygo_twatch_s3/mpconfigboard.mk b/ports/espressif/boards/lilygo_twatch_s3/mpconfigboard.mk index 5d63032d5bf30..1d3154c18265f 100644 --- a/ports/espressif/boards/lilygo_twatch_s3/mpconfigboard.mk +++ b/ports/espressif/boards/lilygo_twatch_s3/mpconfigboard.mk @@ -10,6 +10,11 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Specialized board. CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_PARALLELDISPLAYBUS = 0 CIRCUITPY_MAX3421E = 0 @@ -19,10 +24,6 @@ CIRCUITPY_PS2IO = 0 CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_ROTARYIO = 0 -CIRCUITPY_ESP_PSRAM_SIZE = 8MB -CIRCUITPY_ESP_PSRAM_MODE = opi -CIRCUITPY_ESP_PSRAM_FREQ = 80m - # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FocalTouch FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_IRRemote diff --git a/ports/espressif/boards/lilygo_twatch_s3/sdkconfig b/ports/espressif/boards/lilygo_twatch_s3/sdkconfig index 08b2b772c5cd7..e962866216039 100644 --- a/ports/espressif/boards/lilygo_twatch_s3/sdkconfig +++ b/ports/espressif/boards/lilygo_twatch_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="t-watch-s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_c3_mini/mpconfigboard.mk b/ports/espressif/boards/lolin_c3_mini/mpconfigboard.mk index 36dc38883ff39..99c910e6d2456 100644 --- a/ports/espressif/boards/lolin_c3_mini/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_c3_mini/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=qio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/lolin_c3_mini/sdkconfig b/ports/espressif/boards/lolin_c3_mini/sdkconfig index 932a4a2cbd040..e962866216039 100644 --- a/ports/espressif/boards/lolin_c3_mini/sdkconfig +++ b/ports/espressif/boards/lolin_c3_mini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-mini" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk b/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk index 25027d4c97b8d..6778550a2d108 100644 --- a/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_c3_pico/mpconfigboard.mk @@ -7,12 +7,7 @@ CIRCUITPY_ESP_FLASH_MODE=qio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 -# Not enough flash -CIRCUITPY_SOCKETPOOL_IPV6 = 0 - # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/lolin_c3_pico/sdkconfig b/ports/espressif/boards/lolin_c3_pico/sdkconfig index ba2885933e792..e962866216039 100644 --- a/ports/espressif/boards/lolin_c3_pico/sdkconfig +++ b/ports/espressif/boards/lolin_c3_pico/sdkconfig @@ -7,8 +7,6 @@ # # LWIP # -# CONFIG_LWIP_IPV6 is not set -CONFIG_LWIP_LOCAL_HOSTNAME="lolin-c3-pico" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_s2_mini/sdkconfig b/ports/espressif/boards/lolin_s2_mini/sdkconfig index ac239ca333e6b..e962866216039 100644 --- a/ports/espressif/boards/lolin_s2_mini/sdkconfig +++ b/ports/espressif/boards/lolin_s2_mini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LS2Mini" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_s2_pico/sdkconfig b/ports/espressif/boards/lolin_s2_pico/sdkconfig index c2238c68143aa..e962866216039 100644 --- a/ports/espressif/boards/lolin_s2_pico/sdkconfig +++ b/ports/espressif/boards/lolin_s2_pico/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Lolin-S2Pico" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_s3/mpconfigboard.mk b/ports/espressif/boards/lolin_s3/mpconfigboard.mk index fbcdece670b4e..a86dd6578bd3d 100644 --- a/ports/espressif/boards/lolin_s3/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_s3/mpconfigboard.mk @@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lolin_s3/sdkconfig b/ports/espressif/boards/lolin_s3/sdkconfig index b90e3fa57edab..e962866216039 100644 --- a/ports/espressif/boards/lolin_s3/sdkconfig +++ b/ports/espressif/boards/lolin_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN-S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_s3_mini/mpconfigboard.mk b/ports/espressif/boards/lolin_s3_mini/mpconfigboard.mk index f58218d5e6b5b..fff6cae6d336e 100644 --- a/ports/espressif/boards/lolin_s3_mini/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_s3_mini/mpconfigboard.mk @@ -13,10 +13,5 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_BITMAPFILTER = 0 -CIRCUITPY_CODEOP = 0 -CIRCUITPY_PARALLELDISPLAYBUS = 0 - # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/lolin_s3_mini/sdkconfig b/ports/espressif/boards/lolin_s3_mini/sdkconfig index 36be9c760eddd..e962866216039 100644 --- a/ports/espressif/boards/lolin_s3_mini/sdkconfig +++ b/ports/espressif/boards/lolin_s3_mini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN-S3-MINI" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/lolin_s3_mini_pro/board.c b/ports/espressif/boards/lolin_s3_mini_pro/board.c new file mode 100644 index 0000000000000..39e645bc7b553 --- /dev/null +++ b/ports/espressif/boards/lolin_s3_mini_pro/board.c @@ -0,0 +1,84 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to ST7789 +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, 0 | DELAY, 0xff, // _SLPOUT and Delay 500ms + 0x3A, 1 | DELAY, 0x55, 0x0a, // _COLMOD and Delay 10ms + 0x36, 0x01, 0x08, // _MADCTL + 0x21, 0x80, 0x0A, // _INVON Hack and Delay 10ms + 0x13, 0x80, 0x0A, // _NORON and Delay 10ms + 0x29, 0 | DELAY, 0xff // _DISPON and Delay 500ms +}; + + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + // busio_spi_obj_t *spi = common_hal_board_create_spi(0); + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO40, &pin_GPIO38, NULL, false); + common_hal_busio_spi_never_reset(spi); + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO36), // DC + MP_OBJ_FROM_PTR(&pin_GPIO35), // CS + MP_OBJ_FROM_PTR(&pin_GPIO34), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 2, // column start + 1, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO33, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 200 // backlight pwm frequency + ); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.h b/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.h new file mode 100644 index 0000000000000..2fe5f4205dac0 --- /dev/null +++ b/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 David Sullivan +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "LOLIN S3 MINI PRO 4MB Flash 2MB PSRAM" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO8) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO11) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO12) + +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO38) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO39) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO40) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.mk b/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.mk new file mode 100644 index 0000000000000..f08c733e43a0c --- /dev/null +++ b/ports/espressif/boards/lolin_s3_mini_pro/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x303a +USB_PID = 0x8217 +USB_PRODUCT = "LOLIN S3 MINI PRO 4MB Flash 2MB PSRAM" +USB_MANUFACTURER = "WEMOS" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/lolin_s3_mini_pro/pins.c b/ports/espressif/boards/lolin_s3_mini_pro/pins.c new file mode 100644 index 0000000000000..595cdd489004c --- /dev/null +++ b/ports/espressif/boards/lolin_s3_mini_pro/pins.c @@ -0,0 +1,68 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 David Sullivan +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // User buttons + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON2), MP_ROM_PTR(&pin_GPIO48) }, + + // LEDs + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_ENABLE), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IR_LED), MP_ROM_PTR(&pin_GPIO9) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO12) }, + + // IMU QMI8658C + { MP_ROM_QSTR(MP_QSTR_IMU_INT1), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT2), MP_ROM_PTR(&pin_GPIO21) }, + + // TFT Display + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RES), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO33) }, + + // SPI + { MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO38) }, + + // User accessible GPIO + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/lolin_s3_mini_pro/sdkconfig b/ports/espressif/boards/lolin_s3_mini_pro/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/lolin_s3_mini_pro/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/lolin_s3_pro/mpconfigboard.mk b/ports/espressif/boards/lolin_s3_pro/mpconfigboard.mk index 9df3f3580cd7d..f20732df49c68 100755 --- a/ports/espressif/boards/lolin_s3_pro/mpconfigboard.mk +++ b/ports/espressif/boards/lolin_s3_pro/mpconfigboard.mk @@ -12,5 +12,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/lolin_s3_pro/sdkconfig b/ports/espressif/boards/lolin_s3_pro/sdkconfig index 4dfe8da3fb06f..e962866216039 100755 --- a/ports/espressif/boards/lolin_s3_pro/sdkconfig +++ b/ports/espressif/boards/lolin_s3_pro/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN-S3-PRO" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/luatos_core_esp32c3/mpconfigboard.mk b/ports/espressif/boards/luatos_core_esp32c3/mpconfigboard.mk index ea3c7a44621f1..03f5171a3102c 100644 --- a/ports/espressif/boards/luatos_core_esp32c3/mpconfigboard.mk +++ b/ports/espressif/boards/luatos_core_esp32c3/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/luatos_core_esp32c3/sdkconfig b/ports/espressif/boards/luatos_core_esp32c3/sdkconfig index 7d94db0b5b130..e962866216039 100644 --- a/ports/espressif/boards/luatos_core_esp32c3/sdkconfig +++ b/ports/espressif/boards/luatos_core_esp32c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="luatos-core-esp32c3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/luatos_core_esp32c3_ch343/mpconfigboard.mk b/ports/espressif/boards/luatos_core_esp32c3_ch343/mpconfigboard.mk index bb793f0f26297..9e777889c0f73 100644 --- a/ports/espressif/boards/luatos_core_esp32c3_ch343/mpconfigboard.mk +++ b/ports/espressif/boards/luatos_core_esp32c3_ch343/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/luatos_core_esp32c3_ch343/sdkconfig b/ports/espressif/boards/luatos_core_esp32c3_ch343/sdkconfig index 7d94db0b5b130..e962866216039 100644 --- a/ports/espressif/boards/luatos_core_esp32c3_ch343/sdkconfig +++ b/ports/espressif/boards/luatos_core_esp32c3_ch343/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="luatos-core-esp32c3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atom_echo/mpconfigboard.mk b/ports/espressif/boards/m5stack_atom_echo/mpconfigboard.mk index a40381f8a3487..c896ed0c8a4ab 100644 --- a/ports/espressif/boards/m5stack_atom_echo/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atom_echo/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atom_echo/sdkconfig b/ports/espressif/boards/m5stack_atom_echo/sdkconfig index 861e4ebad3970..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atom_echo/sdkconfig +++ b/ports/espressif/boards/m5stack_atom_echo/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskAtomEcho" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atom_lite/mpconfigboard.mk b/ports/espressif/boards/m5stack_atom_lite/mpconfigboard.mk index 215fd976df361..5ca1db04f3b50 100644 --- a/ports/espressif/boards/m5stack_atom_lite/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atom_lite/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atom_lite/sdkconfig b/ports/espressif/boards/m5stack_atom_lite/sdkconfig index eaaf716a15ef3..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atom_lite/sdkconfig +++ b/ports/espressif/boards/m5stack_atom_lite/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskAtomLite" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.mk b/ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.mk index 081750d143f9b..ace0e7f02cf89 100644 --- a/ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atom_matrix/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atom_matrix/sdkconfig b/ports/espressif/boards/m5stack_atom_matrix/sdkconfig index 730f17de0e196..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atom_matrix/sdkconfig +++ b/ports/espressif/boards/m5stack_atom_matrix/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskAtomMatrix" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atom_u/mpconfigboard.mk b/ports/espressif/boards/m5stack_atom_u/mpconfigboard.mk index abcd5f8724d8e..0f8ab59f7445d 100644 --- a/ports/espressif/boards/m5stack_atom_u/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atom_u/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atom_u/sdkconfig b/ports/espressif/boards/m5stack_atom_u/sdkconfig index 06d0f01693704..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atom_u/sdkconfig +++ b/ports/espressif/boards/m5stack_atom_u/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskAtomU" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atoms3/board.c b/ports/espressif/boards/m5stack_atoms3/board.c index df620976b61b4..3dbd8a1a2b8b6 100644 --- a/ports/espressif/boards/m5stack_atoms3/board.c +++ b/ports/espressif/boards/m5stack_atoms3/board.c @@ -39,9 +39,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO33, // DC - &pin_GPIO15, // CS - &pin_GPIO34, // RST + MP_OBJ_FROM_PTR(&pin_GPIO33), // DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // CS + MP_OBJ_FROM_PTR(&pin_GPIO34), // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk index 9bc53033a1f5d..7738713aa530c 100644 --- a/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atoms3/mpconfigboard.mk @@ -8,4 +8,6 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Few pins. CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atoms3/sdkconfig b/ports/espressif/boards/m5stack_atoms3/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atoms3/sdkconfig +++ b/ports/espressif/boards/m5stack_atoms3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atoms3_lite/mpconfigboard.mk b/ports/espressif/boards/m5stack_atoms3_lite/mpconfigboard.mk index 8bb5ab76d856d..736fb3222b57e 100644 --- a/ports/espressif/boards/m5stack_atoms3_lite/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atoms3_lite/mpconfigboard.mk @@ -8,4 +8,6 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Few pins. CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atoms3_lite/sdkconfig b/ports/espressif/boards/m5stack_atoms3_lite/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atoms3_lite/sdkconfig +++ b/ports/espressif/boards/m5stack_atoms3_lite/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_atoms3u/mpconfigboard.mk b/ports/espressif/boards/m5stack_atoms3u/mpconfigboard.mk index dc65fefc4bf86..e68f4efdc65e8 100644 --- a/ports/espressif/boards/m5stack_atoms3u/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_atoms3u/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_atoms3u/sdkconfig b/ports/espressif/boards/m5stack_atoms3u/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/m5stack_atoms3u/sdkconfig +++ b/ports/espressif/boards/m5stack_atoms3u/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_cardputer/board.c b/ports/espressif/boards/m5stack_cardputer/board.c index e529efe665f18..00630cd36d291 100644 --- a/ports/espressif/boards/m5stack_cardputer/board.c +++ b/ports/espressif/boards/m5stack_cardputer/board.c @@ -4,50 +4,19 @@ // // SPDX-License-Identifier: MIT -#include "keymap.h" +#include "mpconfigboard.h" #include "supervisor/board.h" #include "supervisor/shared/serial.h" -#include "mpconfigboard.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/displayio/__init__.h" #include "shared-module/displayio/mipi_constants.h" #include "shared-bindings/board/__init__.h" -#include "shared-bindings/keypad_demux/DemuxKeyMatrix.h" -#include "shared-bindings/keypad/EventQueue.h" -#include "shared-bindings/keypad/Event.h" -#include "supervisor/shared/reload.h" #include "py/runtime.h" #include "py/ringbuf.h" #include "shared/runtime/interrupt_char.h" -keypad_demux_demuxkeymatrix_obj_t board_keyboard; - -void update_keyboard(keypad_eventqueue_obj_t *queue); -void keyboard_seq(const char *seq); - -const mcu_pin_obj_t *row_addr_pins[] = { - &pin_GPIO8, - &pin_GPIO9, - &pin_GPIO11, -}; - -const mcu_pin_obj_t *column_pins[] = { - &pin_GPIO13, - &pin_GPIO15, - &pin_GPIO3, - &pin_GPIO4, - &pin_GPIO5, - &pin_GPIO6, - &pin_GPIO7 -}; - -keypad_event_obj_t event; - -char keystate[56]; -ringbuf_t keyqueue; -char keybuf[32]; #define DELAY 0x80 @@ -71,6 +40,7 @@ uint8_t display_init_sequence[] = { }; +// Overrides the weakly linked function from supervisor/shared/board.c void board_init(void) { busio_spi_obj_t *spi = common_hal_board_create_spi(0); fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; @@ -80,9 +50,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO34, // DC - &pin_GPIO37, // CS - &pin_GPIO33, // RST + MP_OBJ_FROM_PTR(&pin_GPIO34), // DC + MP_OBJ_FROM_PTR(&pin_GPIO37), // CS + MP_OBJ_FROM_PTR(&pin_GPIO33), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -122,106 +92,4 @@ void board_init(void) { ); } -void board_serial_init() { - ringbuf_init(&keyqueue, (uint8_t *)keybuf, sizeof(keybuf)); - common_hal_keypad_demux_demuxkeymatrix_construct( - &board_keyboard, // self - 3, // num_row_addr_pins - row_addr_pins, // row_addr_pins - 7, // num_column_pins - column_pins, // column_pins - 0.01f, // interval - 20, // max_events - 2 // debounce_threshold - ); - demuxkeymatrix_never_reset(&board_keyboard); - common_hal_keypad_eventqueue_set_event_handler(board_keyboard.events, update_keyboard); - -} - -bool board_serial_connected() { - return true; -} - -uint32_t board_serial_bytes_available() { - return ringbuf_num_filled(&keyqueue); -} - -void keyboard_seq(const char *seq) { - while (*seq) { - ringbuf_put(&keyqueue, *seq++); - } -} - -void update_keyboard(keypad_eventqueue_obj_t *queue) { - uint8_t ascii = 0; - - if (common_hal_keypad_eventqueue_get_length(queue) == 0) { - return; - } - - while (common_hal_keypad_eventqueue_get_into(queue, &event)) { - if (event.pressed) { - keystate[event.key_number] = 1; - - if (keystate[KEY_CTRL]) { - if (keystate[KEY_ALT] && keystate[KEY_BACKSPACE]) { - reload_initiate(RUN_REASON_REPL_RELOAD); - } - ascii = keymap[event.key_number]; - if (ascii >= 'a' && ascii <= 'z') { - ascii -= 'a' - 1; - } - - if (ascii == mp_interrupt_char) { - mp_sched_keyboard_interrupt(); - } - } else if (keystate[KEY_SHIFT]) { - ascii = keymap_shifted[event.key_number]; - } else if (keystate[KEY_FN] && event.key_number != KEY_FN) { - switch (event.key_number | FN_MOD) { - case KEY_DOWN: - keyboard_seq("\e[B"); - break; - case KEY_UP: - keyboard_seq("\e[A"); - break; - case KEY_DELETE: - keyboard_seq("\e[3~"); - break; - case KEY_LEFT: - keyboard_seq("\e[D"); - break; - case KEY_RIGHT: - keyboard_seq("\e[C"); - break; - case KEY_ESC: - ringbuf_put(&keyqueue, '\e'); - break; - } - } else { - ascii = keymap[event.key_number]; - } - - if (ascii > 0) { - if (keystate[KEY_ALT]) { - ringbuf_put(&keyqueue, '\e'); - } else if (keystate[KEY_OPT]) { - ringbuf_put(&keyqueue, '\x10'); - } - ringbuf_put(&keyqueue, ascii); - } - - } else { - keystate[event.key_number] = 0; - } - } -} - -char board_serial_read() { - return ringbuf_get(&keyqueue); -} - -// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. - // TODO: Should we turn off the display when asleep, in board_deinit() ? diff --git a/ports/espressif/boards/m5stack_cardputer/keymap.h b/ports/espressif/boards/m5stack_cardputer/keymap.h deleted file mode 100644 index 08c278bf82bf1..0000000000000 --- a/ports/espressif/boards/m5stack_cardputer/keymap.h +++ /dev/null @@ -1,214 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#define SHIFT_MOD 0x40 -#define FN_MOD 0x80 - -#define KEY_OPT 0 -#define KEY_Z 1 -#define KEY_C 2 -#define KEY_B 3 -#define KEY_M 4 -#define KEY_DOT 5 -#define KEY_SPACE 6 -#define KEY_SHIFT 7 -#define KEY_S 8 -#define KEY_F 9 -#define KEY_H 10 -#define KEY_K 11 -#define KEY_SEMICOLON 12 -#define KEY_ENTER 13 -#define KEY_Q 14 -#define KEY_E 15 -#define KEY_T 16 -#define KEY_U 17 -#define KEY_O 18 -#define KEY_LEFT_BRACKET 19 -#define KEY_BACKSLASH 20 -#define KEY_1 21 -#define KEY_3 22 -#define KEY_5 23 -#define KEY_7 24 -#define KEY_9 25 -#define KEY_UNDERSCORE 26 -#define KEY_BACKSPACE 27 -#define KEY_CTRL 28 -#define KEY_ALT 29 -#define KEY_X 30 -#define KEY_V 31 -#define KEY_N 32 -#define KEY_COMMA 33 -#define KEY_SLASH 34 -#define KEY_FN 35 -#define KEY_A 36 -#define KEY_D 37 -#define KEY_G 38 -#define KEY_J 39 -#define KEY_L 40 -#define KEY_APOSTROPHE 41 -#define KEY_TAB 42 -#define KEY_W 43 -#define KEY_R 44 -#define KEY_Y 45 -#define KEY_I 46 -#define KEY_P 47 -#define KEY_RIGHT_BRACKET 48 -#define KEY_GRAVE 49 -#define KEY_2 50 -#define KEY_4 51 -#define KEY_6 52 -#define KEY_8 53 -#define KEY_0 54 -#define KEY_EQUALS 55 - -#define KEY_GREATER (5 | SHIFT_MOD) -#define KEY_COLON (12 | SHIFT_MOD) -#define KEY_LEFT_CURLY_BRACKET (19 | SHIFT_MOD) -#define KEY_PIPE (20 | SHIFT_MOD) -#define KEY_EXCLAMATION (21 | SHIFT_MOD) -#define KEY_HASH (22 | SHIFT_MOD) -#define KEY_PERCENT (23 | SHIFT_MOD) -#define KEY_AMPERSAND (24 | SHIFT_MOD) -#define KEY_OPEN_PARENTHESIS (25 | SHIFT_MOD) -#define KEY_MINUS (26 | SHIFT_MOD) -#define KEY_LESS (33 | SHIFT_MOD) -#define KEY_QUESTION (34 | SHIFT_MOD) -#define KEY_DOUBLE_QUOTE (41 | SHIFT_MOD) -#define KEY_RIGHT_CURLY_BRACKET (48 | SHIFT_MOD) -#define KEY_TILDE (49 | SHIFT_MOD) -#define KEY_AT (50 | SHIFT_MOD) -#define KEY_DOLLAR (51 | SHIFT_MOD) -#define KEY_CARET (52 | SHIFT_MOD) -#define KEY_ASTERISK (53 | SHIFT_MOD) -#define KEY_CLOSE_PARENTHESIS (54 | SHIFT_MOD) -#define KEY_PLUS (55 | SHIFT_MOD) - -#define KEY_DOWN (5 | FN_MOD) -#define KEY_UP (12 | FN_MOD) -#define KEY_DELETE (27 | FN_MOD) -#define KEY_LEFT (33 | FN_MOD) -#define KEY_RIGHT (34 | FN_MOD) -#define KEY_ESC (49 | FN_MOD) - -int keymap[56] = { - 0, // KEY_OPT - 'z', // KEY_Z - 'c', // KEY_C - 'b', // KEY_B - 'm', // KEY_M - '.', // KEY_DOT - ' ', // KEY_SPACE - 0, // KEY_SHIFT - 's', // KEY_S - 'f', // KEY_F - 'h', // KEY_H - 'k', // KEY_K - ';', // KEY_SEMICOLON - '\r',// KEY_ENTER - 'q', // KEY_Q - 'e', // KEY_E - 't', // KEY_T - 'u', // KEY_U - 'o', // KEY_O - '[', // KEY_LEFT_BRACKET - '\\',// KEY_BACKSLASH - '1', // KEY_1 - '3', // KEY_3 - '5', // KEY_5 - '7', // KEY_7 - '9', // KEY_9 - '_', // KEY_UNDERSCORE - '\b',// KEY_BACKSPACE - 0, // KEY_CTRL - 0, // KEY_ALT - 'x', // KEY_X - 'v', // KEY_V - 'n', // KEY_N - ',', // KEY_COMMA - '/', // KEY_SLASH - 0, // KEY_FN - 'a', // KEY_A - 'd', // KEY_D - 'g', // KEY_G - 'j', // KEY_J - 'l', // KEY_L - '\'',// KEY_APOSTROPHE - '\t',// KEY_TAB - 'w', // KEY_W - 'r', // KEY_R - 'y', // KEY_Y - 'i', // KEY_I - 'p', // KEY_P - ']', // KEY_RIGHT_BRACKET - '`', // KEY_GRAVE - '2', // KEY_2 - '4', // KEY_4 - '6', // KEY_6 - '8', // KEY_8 - '0', // KEY_0 - '=' // KEY_EQUALS -}; - -int keymap_shifted[56] = { - 0, // KEY_OPT - 'Z', // KEY_Z - 'C', // KEY_C - 'B', // KEY_B - 'M', // KEY_M - '>', // KEY_DOT -> '>' - ' ', // KEY_SPACE - 0, // KEY_SHIFT - 'S', // KEY_S - 'F', // KEY_F - 'H', // KEY_H - 'K', // KEY_K - ':', // KEY_SEMICOLON -> ':' - '\r',// KEY_ENTER - 'Q', // KEY_Q - 'E', // KEY_E - 'T', // KEY_T - 'U', // KEY_U - 'O', // KEY_O - '{', // KEY_LEFT_BRACKET -> '{' - '|', // KEY_BACKSLASH -> '|' - '!', // KEY_1 -> '!' - '#', // KEY_3 -> '#' - '%', // KEY_5 -> '%' - '&', // KEY_7 -> '&' - '(', // KEY_9 -> '(' - '-', // KEY_UNDERSCORE -> '-' - '\b',// KEY_BACKSPACE - 0, // KEY_CTRL - 0, // KEY_ALT - 'X', // KEY_X - 'V', // KEY_V - 'N', // KEY_N - '<', // KEY_COMMA -> '<' - '?', // KEY_SLASH -> '?' - 0, // KEY_FN - 'A', // KEY_A - 'D', // KEY_D - 'G', // KEY_G - 'J', // KEY_J - 'L', // KEY_L - '"', // KEY_APOSTROPHE -> '"' - '\t',// KEY_TAB - 'W', // KEY_W - 'R', // KEY_R - 'Y', // KEY_Y - 'I', // KEY_I - 'P', // KEY_P - '}', // KEY_RIGHT_BRACKET -> '}' - '~', // KEY_GRAVE -> '~' - '@', // KEY_2 -> '@' - '$', // KEY_4 -> '$' - '^', // KEY_6 -> '^' - '*', // KEY_8 -> '*' - ')', // KEY_0 -> ')' - '+' // KEY_EQUALS -> '+' -}; diff --git a/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk b/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk index 35145f389672c..bc30ae3afd5e9 100644 --- a/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_cardputer/mpconfigboard.mk @@ -8,7 +8,9 @@ IDF_TARGET = esp32s3 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_GIFIO = 1 +# Very few pins. +CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_MAX3421E = 0 + +SRC_C += module/cardputer_keyboard.c diff --git a/ports/espressif/boards/m5stack_cardputer/pins.c b/ports/espressif/boards/m5stack_cardputer/pins.c index 38c5243e2517e..ba309e0dcbff1 100644 --- a/ports/espressif/boards/m5stack_cardputer/pins.c +++ b/ports/espressif/boards/m5stack_cardputer/pins.c @@ -80,6 +80,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_TFT_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, - { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} + // Display object + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_cardputer/sdkconfig b/ports/espressif/boards/m5stack_cardputer/sdkconfig index b48116f764dc6..e962866216039 100644 --- a/ports/espressif/boards/m5stack_cardputer/sdkconfig +++ b/ports/espressif/boards/m5stack_cardputer/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="m5stack-cardputer" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_cardputer_ros/board.c b/ports/espressif/boards/m5stack_cardputer_ros/board.c new file mode 100644 index 0000000000000..00630cd36d291 --- /dev/null +++ b/ports/espressif/boards/m5stack_cardputer_ros/board.c @@ -0,0 +1,95 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "mpconfigboard.h" +#include "supervisor/board.h" +#include "supervisor/shared/serial.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "py/runtime.h" +#include "py/ringbuf.h" +#include "shared/runtime/interrupt_char.h" + + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + // SWRESET and Delay 140ms + 0x01, 0 | DELAY, 140, + // SLPOUT and Delay 10ms + 0x11, 0 | DELAY, 10, + // COLMOD 65k colors and 16 bit 5-6-5 + 0x3A, 1, 0x55, + // INVON Iiversion on + 0x21, 0, + // NORON normal operation (full update) + 0x13, 0, + // MADCTL columns RTL, page/column reverse order + 0x36, 1, 0x60, + // RAMCTRL color word little endian + 0xB0, 2, 0x00, 0xF8, + // DIPON display on + 0x29, 0, +}; + + +// Overrides the weakly linked function from supervisor/shared/board.c +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + // see here for inspiration: https://github.com/m5stack/M5GFX/blob/33d7d3135e816a86a008fae8ab3757938cee95d2/src/M5GFX.cpp#L1350 + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO34), // DC + MP_OBJ_FROM_PTR(&pin_GPIO37), // CS + MP_OBJ_FROM_PTR(&pin_GPIO33), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 240, // width (after rotation) + 135, // height (after rotation) + 40, // column start + 53, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + false, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO38, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 350 // backlight pwm frequency + ); +} + +// TODO: Should we turn off the display when asleep, in board_deinit() ? diff --git a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.h b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.h new file mode 100644 index 0000000000000..4b62c7d76e6a1 --- /dev/null +++ b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack Cardputer (ROS version)" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO1) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO36, .mosi = &pin_GPIO35}, \ + {.clock = &pin_GPIO40, .mosi = &pin_GPIO14, .miso = &pin_GPIO39}} diff --git a/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk new file mode 100644 index 0000000000000..ede48c2f01523 --- /dev/null +++ b/ports/espressif/boards/m5stack_cardputer_ros/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x303A +USB_PID = 0x81DA +USB_PRODUCT = "M5Stack Cardputer - Circuitpython/ROS" +USB_MANUFACTURER = "M5STACK" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_RCLCPY = 1 + +# Very few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_MAX3421E = 0 + +SRC_C += module/cardputer_keyboard.c diff --git a/ports/espressif/boards/m5stack_cardputer_ros/pins.c b/ports/espressif/boards/m5stack_cardputer_ros/pins.c new file mode 100644 index 0000000000000..ba309e0dcbff1 --- /dev/null +++ b/ports/espressif/boards/m5stack_cardputer_ros/pins.c @@ -0,0 +1,86 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Port A + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_PORTA1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_G1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_PORTA2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_GPIO2) }, + + // Keyboard + { MP_ROM_QSTR(MP_QSTR_KB_COL_0), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_1), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_2), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_3), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_4), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_5), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_KB_COL_6), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_KB_A_0), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_KB_A_1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_KB_A_2), MP_ROM_PTR(&pin_GPIO11) }, + + // Neopixel + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, + + // Speaker + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO43) }, + + // Mic + { MP_ROM_QSTR(MP_QSTR_MIC_DATA), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_MIC_CLK), MP_ROM_PTR(&pin_GPIO43) }, + + // IR + { MP_ROM_QSTR(MP_QSTR_IR_TX), MP_ROM_PTR(&pin_GPIO44) }, + + // SD + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO12) }, + + + // Display + { MP_ROM_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RS), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DATA), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BL), MP_ROM_PTR(&pin_GPIO38) }, + + // Button + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + + // Battery + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO10) }, + + // Other + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_TFT_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, + + // Display object + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_cardputer_ros/sdkconfig b/ports/espressif/boards/m5stack_cardputer_ros/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_cardputer_ros/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/m5stack_core2/board.c b/ports/espressif/boards/m5stack_core2/board.c index 9d5c2bd650a51..2d63436235af1 100644 --- a/ports/espressif/boards/m5stack_core2/board.c +++ b/ports/espressif/boards/m5stack_core2/board.c @@ -318,9 +318,9 @@ static bool display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO15, // DC - &pin_GPIO5, // CS - NULL, // RST + MP_OBJ_FROM_PTR(&pin_GPIO15), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_NULL, // RST 32000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_core2/sdkconfig b/ports/espressif/boards/m5stack_core2/sdkconfig index c8ac5f43acf95..116258b906bf4 100644 --- a/ports/espressif/boards/m5stack_core2/sdkconfig +++ b/ports/espressif/boards/m5stack_core2/sdkconfig @@ -29,7 +29,6 @@ CONFIG_ESP_REV_MIN_FULL=300 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskCore2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_core_basic/board.c b/ports/espressif/boards/m5stack_core_basic/board.c index 87aa16024c473..5a18d33e52767 100644 --- a/ports/espressif/boards/m5stack_core_basic/board.c +++ b/ports/espressif/boards/m5stack_core_basic/board.c @@ -42,9 +42,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO14, // CS - &pin_GPIO33, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO14), // CS + MP_OBJ_FROM_PTR(&pin_GPIO33), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -89,8 +89,7 @@ void board_init(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Set speaker gpio to ground to prevent noise from the speaker if (pin_number == 25) { - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; diff --git a/ports/espressif/boards/m5stack_core_basic/mpconfigboard.mk b/ports/espressif/boards/m5stack_core_basic/mpconfigboard.mk index dedcde81e63b7..964f61a04f42e 100644 --- a/ports/espressif/boards/m5stack_core_basic/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_core_basic/mpconfigboard.mk @@ -6,4 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 16MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_core_basic/sdkconfig b/ports/espressif/boards/m5stack_core_basic/sdkconfig index 5b7ecf8709758..116258b906bf4 100644 --- a/ports/espressif/boards/m5stack_core_basic/sdkconfig +++ b/ports/espressif/boards/m5stack_core_basic/sdkconfig @@ -29,7 +29,6 @@ CONFIG_ESP_REV_MIN_FULL=300 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskCoreBasic" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_core_fire/board.c b/ports/espressif/boards/m5stack_core_fire/board.c index 87aa16024c473..5a18d33e52767 100644 --- a/ports/espressif/boards/m5stack_core_fire/board.c +++ b/ports/espressif/boards/m5stack_core_fire/board.c @@ -42,9 +42,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO14, // CS - &pin_GPIO33, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO14), // CS + MP_OBJ_FROM_PTR(&pin_GPIO33), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -89,8 +89,7 @@ void board_init(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Set speaker gpio to ground to prevent noise from the speaker if (pin_number == 25) { - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; diff --git a/ports/espressif/boards/m5stack_core_fire/mpconfigboard.mk b/ports/espressif/boards/m5stack_core_fire/mpconfigboard.mk index 591c596bbcfee..e62fd3d4e57d0 100644 --- a/ports/espressif/boards/m5stack_core_fire/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_core_fire/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_core_fire/sdkconfig b/ports/espressif/boards/m5stack_core_fire/sdkconfig index 0e7b9709383c5..116258b906bf4 100644 --- a/ports/espressif/boards/m5stack_core_fire/sdkconfig +++ b/ports/espressif/boards/m5stack_core_fire/sdkconfig @@ -29,7 +29,6 @@ CONFIG_ESP_REV_MIN_FULL=300 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskCoreFire" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_cores3/board.c b/ports/espressif/boards/m5stack_cores3/board.c index f49d634999730..c14be4ae0d142 100644 --- a/ports/espressif/boards/m5stack_cores3/board.c +++ b/ports/espressif/boards/m5stack_cores3/board.c @@ -45,9 +45,9 @@ static bool display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO35, // DC - &pin_GPIO3, // CS - NULL, // RST + MP_OBJ_FROM_PTR(&pin_GPIO35), // DC + MP_OBJ_FROM_PTR(&pin_GPIO3), // CS + MP_OBJ_NULL, // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/m5stack_cores3/pins.c b/ports/espressif/boards/m5stack_cores3/pins.c index 2ebb225277ded..8b40d9e84842a 100644 --- a/ports/espressif/boards/m5stack_cores3/pins.c +++ b/ports/espressif/boards/m5stack_cores3/pins.c @@ -28,42 +28,59 @@ CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - // M5 Bus (except I2S & PORT B) + // M5 Bus (except I2S) { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO37) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO35) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, { MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_PORTC_RX), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO12) }, - { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, - { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_PORTC_TX), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, - // Port B - { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, - { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) }, - { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, - // I2S { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO34) }, { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO33) }, - { MP_ROM_QSTR(MP_QSTR_IS2_DATA), MP_ROM_PTR(&pin_GPIO13) }, - { MP_ROM_QSTR(MP_QSTR_IS2_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_OUT), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_IN), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, // Camera { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, diff --git a/ports/espressif/boards/m5stack_cores3/sdkconfig b/ports/espressif/boards/m5stack_cores3/sdkconfig index 2eb2f0a850b32..7c3c05764ba7f 100644 --- a/ports/espressif/boards/m5stack_cores3/sdkconfig +++ b/ports/espressif/boards/m5stack_cores3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="m5stack-cores3" # end of LWIP # diff --git a/ports/espressif/boards/m5stack_cores3_se/board.c b/ports/espressif/boards/m5stack_cores3_se/board.c new file mode 100644 index 0000000000000..bf5ccd17f36fe --- /dev/null +++ b/ports/espressif/boards/m5stack_cores3_se/board.c @@ -0,0 +1,224 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "common-hal/microcontroller/Pin.h" + + +#define DELAY 0x80 +#define AXP2101_I2C_ADDRESS 0x34 +#define AW9523B_I2C_ADDRESS 0x58 + +uint8_t display_init_sequence[] = { + 0x01, DELAY, 0x80, // Software reset then delay 0x80 (128ms) + 0xC8, 0x03, 0xFF, 0x93, 0x42, // Turn on the external command + 0xC0, 0x02, 0x12, 0x12, // Power Control 1 + 0xC1, 0x01, 0x03, // Power Control 2 + 0xC5, 0x01, 0xF2, // VCOM Control 1 + 0xB0, 0x01, 0xE0, // RGB Interface SYNC Mode + 0xF6, 0x03, 0x01, 0x00, 0x00, // Interface control + 0XE0, 0x0F, 0x00, 0x0C, 0x11, 0x04, 0x11, 0x08, 0x37, 0x89, 0x4C, 0x06, 0x0C, 0x0A, 0x2E, 0x34, 0x0F, // Positive Gamma Correction + 0xE1, 0x0F, 0x00, 0x0B, 0x11, 0x05, 0x13, 0x09, 0x33, 0x67, 0x48, 0x07, 0x0E, 0x0B, 0x2E, 0x33, 0x0F, // Negative Gamma Correction + 0xB6, 0x04, 0x08, 0x82, 0x1D, 0x04, // Display Function Control + 0x3A, 0x01, 0x55, // COLMOD: Pixel Format Set 16 bit + 0x21, 0x00, // Display inversion ON + 0x36, 0x01, 0x08, // Memory Access Control: RGB order + 0x11, DELAY, 0x78, // Exit Sleep then delay 0x78 (120ms) + 0x29, DELAY, 0x78, // Display on then delay 0x78 (120ms) +}; + +static bool display_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO35), // DC + MP_OBJ_FROM_PTR(&pin_GPIO3), // CS + NULL, // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 320, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 61, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); + + return true; +} + +static bool axp2101_init(busio_i2c_obj_t *i2c) { + int rc; + uint8_t write_buf[2]; + + // 0x90 = 0b1011_0011 // LDOS ON/OFF control 0 + // Compared to CoreS3: ALDO2 (bit 2) and ALDO3 (bit 3) disabled (no ES7210/camera) + write_buf[0] = 0x90; + write_buf[1] = 0b10110011; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x92, 0x0D // ALDO1 set to 1.8v for AW88298 + write_buf[0] = 0x92; + write_buf[1] = 0x0D; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x95, 0x1C // ALDO4 set to 3.3v for TF card slot + write_buf[0] = 0x95; + write_buf[1] = 0x1C; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x99, 0x18 // DLDO1 set to 2.9v for TFT backlight + write_buf[0] = 0x99; + write_buf[1] = 0x18; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x27, 0x00 // PowerKey Hold=1sec / PowerOff=4sec + write_buf[0] = 0x27; + write_buf[1] = 0x00; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x69, 0x11 // CHGLED setting + write_buf[0] = 0x69; + write_buf[1] = 0x11; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x10, 0x30 // PMU common config + write_buf[0] = 0x10; + write_buf[1] = 0x30; + rc = common_hal_busio_i2c_write(i2c, AXP2101_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + return true; +} + +static bool aw9523b_init(busio_i2c_obj_t *i2c) { + int rc; + uint8_t write_buf[2]; + + // 0x02 = 0b0000_0111 // AW_RST, BUD_OUT_EN, TOUCH_RST + write_buf[0] = 0x02; + write_buf[1] = 0b00000111; + rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x03 = 0b1000_0011 // BOOST_EN, CAM_RST, LCD_RST + write_buf[0] = 0x03; + write_buf[1] = 0b10000011; + rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x04 = 0b0001_1000 // Set TF_SW, ES_INT as input + write_buf[0] = 0x04; + write_buf[1] = 0b00011000; + rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x05 = 0b0000_1100 // Set AW_INT, TOUCH_INT as input + write_buf[0] = 0x05; + write_buf[1] = 0b00001100; + rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + // 0x11 = 0b0001_0000 // Set P0 outputs in push pull mode + write_buf[0] = 0x11; + write_buf[1] = 0b00010000; + rc = common_hal_busio_i2c_write(i2c, AW9523B_I2C_ADDRESS, write_buf, sizeof(write_buf)); + if (rc != 0) { + return false; + } + + return true; +} + +void board_init(void) { + // Deselect SD card on shared SPI bus before display init (see #10536) + config_pin_as_output_with_level(GPIO_NUM_4, true); + + busio_i2c_obj_t *internal_i2c = common_hal_board_create_i2c(0); + + if (!axp2101_init(internal_i2c)) { + mp_printf(&mp_plat_print, "could not initialize AXP2101"); + return; + } + + if (!aw9523b_init(internal_i2c)) { + mp_printf(&mp_plat_print, "could not initialize AW9523B"); + return; + } + + if (!display_init()) { + mp_printf(&mp_plat_print, "could not initialize the display"); + return; + } +} diff --git a/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.h b/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.h new file mode 100644 index 0000000000000..070ccf9195e5b --- /dev/null +++ b/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack CoreS3 SE" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO5) + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO11, .sda = &pin_GPIO12}, \ + {.scl = &pin_GPIO1, .sda = &pin_GPIO2}} + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO37) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO35) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO18) +#define DEFAULT_UART_BUS_TX (&pin_GPIO17) diff --git a/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.mk b/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.mk new file mode 100644 index 0000000000000..2413c43cebea1 --- /dev/null +++ b/ports/espressif/boards/m5stack_cores3_se/mpconfigboard.mk @@ -0,0 +1,27 @@ +USB_VID = 0x303A +USB_PID = 0x8348 + +USB_PRODUCT = "M5Stack CoreS3 SE" +USB_MANUFACTURER = "M5Stack" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +OPTIMIZATION_FLAGS = -Os + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_FakeRequests +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests diff --git a/ports/espressif/boards/m5stack_cores3_se/pins.c b/ports/espressif/boards/m5stack_cores3_se/pins.c new file mode 100644 index 0000000000000..f0e20926bfa67 --- /dev/null +++ b/ports/espressif/boards/m5stack_cores3_se/pins.c @@ -0,0 +1,87 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // M5 Bus (except I2S) + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_PORTC_RX), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_A18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_PORTC_TX), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_A17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, + + // I2S + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_OUT), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA_IN), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MASTER_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, + + // Display + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO35) }, + + // Misc + { MP_ROM_QSTR(MP_QSTR_I2C_INTERRUPT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SDCARD_CS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_porta_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_cores3_se/sdkconfig b/ports/espressif/boards/m5stack_cores3_se/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_cores3_se/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/m5stack_dial/board.c b/ports/espressif/boards/m5stack_dial/board.c index b60ddc776be75..6214255612bd2 100644 --- a/ports/espressif/boards/m5stack_dial/board.c +++ b/ports/espressif/boards/m5stack_dial/board.c @@ -49,9 +49,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO4, // DC - &pin_GPIO7, // CS - &pin_GPIO8, // RST + MP_OBJ_FROM_PTR(&pin_GPIO4), // DC + MP_OBJ_FROM_PTR(&pin_GPIO7), // CS + MP_OBJ_FROM_PTR(&pin_GPIO8), // RST 40000000, // baudrate 0, // polarity 0 // phase @@ -92,11 +92,10 @@ void board_init(void) { } bool espressif_board_reset_pin_number(gpio_num_t pin_number) { - // Hold pind must be set high to avoid a power off when battery powered + // Hold pin must be set high to avoid a power off when battery powered if (pin_number == 46) { // Turn on hold output - gpio_set_direction(46, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(46, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/m5stack_dial/mpconfigboard.mk b/ports/espressif/boards/m5stack_dial/mpconfigboard.mk index cfdb0f1690541..b87b5e6f92543 100644 --- a/ports/espressif/boards/m5stack_dial/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_dial/mpconfigboard.mk @@ -10,7 +10,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB +# Very few pins. CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_PARALLELDISPLAYBUS = 0 - -OPTIMIZATION_FLAGS = -Os diff --git a/ports/espressif/boards/m5stack_dial/sdkconfig b/ports/espressif/boards/m5stack_dial/sdkconfig index 2938bb3bfa7f9..e962866216039 100644 --- a/ports/espressif/boards/m5stack_dial/sdkconfig +++ b/ports/espressif/boards/m5stack_dial/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="m5stack-dial" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_dinmeter/board.c b/ports/espressif/boards/m5stack_dinmeter/board.c new file mode 100644 index 0000000000000..37fafa994dc4d --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/board.c @@ -0,0 +1,107 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "mpconfigboard.h" +#include "supervisor/board.h" +#include "supervisor/shared/serial.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "py/runtime.h" +#include "py/ringbuf.h" +#include "shared/runtime/interrupt_char.h" + + +uint8_t display_init_sequence[] = { + 0x01, 0x80, 0x96, // SWRESET and Delay 150ms + 0x11, 0x80, 0xff, // SLPOUT and Delay + 0xb1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xb2, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR2 + 0xb3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3 + 0xb4, 0x01, 0x07, // _INVCTR line inversion + 0xc0, 0x03, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xc1, 0x01, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xc2, 0x02, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xc3, 0x02, 0x8a, 0x2a, + 0xc4, 0x02, 0x8a, 0xee, + 0xc5, 0x01, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x36, 0x01, 0xc8, // MADCTL Rotate display + 0x21, 0x00, // _INVON + 0x3a, 0x01, 0x05, // COLMOD - 16bit color + 0xe0, 0x10, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma + 0xe1, 0x10, 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1 + 0x13, 0x80, 0x0a, // _NORON + 0x29, 0x80, 0x64 // _DISPON +}; + + +// Overrides the weakly linked function from supervisor/shared/board.c +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + // see here for inspiration: https://github.com/m5stack/M5GFX/blob/33d7d3135e816a86a008fae8ab3757938cee95d2/src/M5GFX.cpp#L1350 + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO4), // DC + MP_OBJ_FROM_PTR(&pin_GPIO7), // CS + MP_OBJ_FROM_PTR(&pin_GPIO8), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 240, // width (after rotation) + 135, // height (after rotation) + 40, // column start + 52, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO9, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 80, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Hold pin must be set high to avoid a power off when battery powered + if (pin_number == 46) { + // Turn on hold output + config_pin_as_output_with_level(pin_number, true); + return true; + } + return false; +} + +// TODO: Should we turn off the display when asleep, in board_deinit() ? diff --git a/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h new file mode 100644 index 0000000000000..2d69e61ea950a --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 CDarius +// SPDX-FileCopyrightText: Copyright (c) 2025 juergenpabel +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack DinMeter" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO12, .sda = &pin_GPIO11}, \ + {.scl = &pin_GPIO15, .sda = &pin_GPIO13}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO6, .mosi = &pin_GPIO5}} + +#define CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP (1) diff --git a/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk new file mode 100644 index 0000000000000..81a23af1fe464 --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/mpconfigboard.mk @@ -0,0 +1,15 @@ +USB_VID = 0x303A +USB_PID = 0x830B + +USB_PRODUCT = "DinMeter" +USB_MANUFACTURER = "M5Stack" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Very few pins. +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_PARALLELDISPLAYBUS = 0 diff --git a/ports/espressif/boards/m5stack_dinmeter/pins.c b/ports/espressif/boards/m5stack_dinmeter/pins.c new file mode 100644 index 0000000000000..f75e05e848b0b --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/pins.c @@ -0,0 +1,61 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 Juergen Pabel +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(porta_i2c, i2c, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Port A + { MP_ROM_QSTR(MP_QSTR_PORTA_SCL), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_SDA), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + // Port B + { MP_ROM_QSTR(MP_QSTR_PORTB_IN), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_PORTB_OUT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + + // Encoder + { MP_ROM_QSTR(MP_QSTR_ENC_A), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_ENC_B), MP_ROM_PTR(&pin_GPIO40) }, + + // Button + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + + // Misc + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_KNOB_BUTTON), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_POWER_HOLD), MP_ROM_PTR(&pin_GPIO46) }, + + // Display + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_I2C), MP_ROM_PTR(&board_porta_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_dinmeter/sdkconfig b/ports/espressif/boards/m5stack_dinmeter/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_dinmeter/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/m5stack_m5paper/board.c b/ports/espressif/boards/m5stack_m5paper/board.c index fbf66fa5ccdf9..db68df79c4291 100644 --- a/ports/espressif/boards/m5stack_m5paper/board.c +++ b/ports/espressif/boards/m5stack_m5paper/board.c @@ -74,6 +74,7 @@ void board_init(void) { // false, // always_toggle_chip_select // false, // grayscale // true, // acep + // false, // spectra6 // false, // two_byte_sequence_length // false // address_little_endian // ); diff --git a/ports/espressif/boards/m5stack_m5paper/mpconfigboard.mk b/ports/espressif/boards/m5stack_m5paper/mpconfigboard.mk index bacf270a66387..bbc072632737b 100644 --- a/ports/espressif/boards/m5stack_m5paper/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_m5paper/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 16MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/m5stack_m5paper/sdkconfig b/ports/espressif/boards/m5stack_m5paper/sdkconfig index fbf94f27494a4..116258b906bf4 100644 --- a/ports/espressif/boards/m5stack_m5paper/sdkconfig +++ b/ports/espressif/boards/m5stack_m5paper/sdkconfig @@ -29,7 +29,6 @@ CONFIG_ESP_REV_MIN_FULL=300 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5Paper" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_stamp_c3/mpconfigboard.mk b/ports/espressif/boards/m5stack_stamp_c3/mpconfigboard.mk index 2c856c6fc0030..2f3b62f90fac9 100644 --- a/ports/espressif/boards/m5stack_stamp_c3/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_stamp_c3/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=qio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 diff --git a/ports/espressif/boards/m5stack_stamp_c3/sdkconfig b/ports/espressif/boards/m5stack_stamp_c3/sdkconfig index 87330ec13bd68..e962866216039 100644 --- a/ports/espressif/boards/m5stack_stamp_c3/sdkconfig +++ b/ports/espressif/boards/m5stack_stamp_c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="m5stack-stamp-c3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_stamp_s3/board.c b/ports/espressif/boards/m5stack_stamp_s3/board.c new file mode 100644 index 0000000000000..2978eb0ca1275 --- /dev/null +++ b/ports/espressif/boards/m5stack_stamp_s3/board.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: 2025 Stella Schwankl +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" diff --git a/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.h b/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.h new file mode 100644 index 0000000000000..568ba94be9a2e --- /dev/null +++ b/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: 2025 Stella Schwankl +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack Stamp-S3" +#define MICROPY_HW_MCU_NAME "ESP32-S3FN8" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO21) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO15) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO13) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.mk b/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.mk new file mode 100644 index 0000000000000..d2f1bc3c47167 --- /dev/null +++ b/ports/espressif/boards/m5stack_stamp_s3/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x303A +USB_PID = 0x816B +USB_PRODUCT = "M5Stack StampS3 - CircuitPython" +USB_MANUFACTURER = "M5STACK" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/m5stack_stamp_s3/pins.c b/ports/espressif/boards/m5stack_stamp_s3/pins.c new file mode 100644 index 0000000000000..11995b8c0f801 --- /dev/null +++ b/ports/espressif/boards/m5stack_stamp_s3/pins.c @@ -0,0 +1,152 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: 2025 Stella Schwankl +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Button + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_G0), MP_ROM_PTR(&pin_GPIO0) }, + + // GPIO + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_G1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_TCH1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_TCH2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_G3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TCH3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_TCH4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_G5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_TCH5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_G6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_TCH6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_G7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_TCH7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_G8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_TCH8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_G9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TCH9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_G10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_TCH10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_G11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_TCH11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_A12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_G12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TCH12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_A13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_G13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_TCH13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_A14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_G14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_TCH14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_A15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_G15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_G39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_G40), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_G41), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_G42), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_G43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_G44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_G46), MP_ROM_PTR(&pin_GPIO46) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + // Neopixel + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, + + // Display + { MP_ROM_QSTR(MP_QSTR_TFT_RST), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RS), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DAT), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DATA), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BL), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_TFT_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // Extended Port Pins + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_G16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_G17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_G18), MP_ROM_PTR(&pin_GPIO18) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_stamp_s3/sdkconfig b/ports/espressif/boards/m5stack_stamp_s3/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_stamp_s3/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/m5stack_stick_c/board.c b/ports/espressif/boards/m5stack_stick_c/board.c index ba864cd366a21..491ddead86035 100644 --- a/ports/espressif/boards/m5stack_stick_c/board.c +++ b/ports/espressif/boards/m5stack_stick_c/board.c @@ -154,9 +154,9 @@ static bool display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO23, // DC - &pin_GPIO5, // CS - &pin_GPIO18, // RST + MP_OBJ_FROM_PTR(&pin_GPIO23), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO18), // RST 10000000, // baudrate 0, // polarity 0 // phase @@ -216,8 +216,7 @@ void board_init(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Set IR led gpio high to prevent power drain from the led if (pin_number == 9) { - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/m5stack_stick_c/mpconfigboard.mk b/ports/espressif/boards/m5stack_stick_c/mpconfigboard.mk index ce94e71dff2a0..7f8b24c808105 100644 --- a/ports/espressif/boards/m5stack_stick_c/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_stick_c/mpconfigboard.mk @@ -6,8 +6,5 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 SRC_C += pmic/axp192/axp192.c diff --git a/ports/espressif/boards/m5stack_stick_c/sdkconfig b/ports/espressif/boards/m5stack_stick_c/sdkconfig index 2e72fdb21633b..e962866216039 100644 --- a/ports/espressif/boards/m5stack_stick_c/sdkconfig +++ b/ports/espressif/boards/m5stack_stick_c/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskStickC" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_stick_c_plus/board.c b/ports/espressif/boards/m5stack_stick_c_plus/board.c index 11fb729d80a92..8902521db8e3f 100644 --- a/ports/espressif/boards/m5stack_stick_c_plus/board.c +++ b/ports/espressif/boards/m5stack_stick_c_plus/board.c @@ -154,9 +154,9 @@ static bool display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO23, // DC - &pin_GPIO5, // CS - &pin_GPIO18, // RST + MP_OBJ_FROM_PTR(&pin_GPIO23), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO18), // RST 10000000, // baudrate 0, // polarity 0 // phase @@ -216,8 +216,7 @@ void board_init(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Set IR led gpio high to prevent power drain from the led if (pin_number == 9) { - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.mk b/ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.mk index bee1fc7e7811f..8960a568feb47 100644 --- a/ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_stick_c_plus/mpconfigboard.mk @@ -6,8 +6,5 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 SRC_C += pmic/axp192/axp192.c diff --git a/ports/espressif/boards/m5stack_stick_c_plus/sdkconfig b/ports/espressif/boards/m5stack_stick_c_plus/sdkconfig index 54f50db25c3ca..e962866216039 100644 --- a/ports/espressif/boards/m5stack_stick_c_plus/sdkconfig +++ b/ports/espressif/boards/m5stack_stick_c_plus/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StaskStickCPlus" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/m5stack_stick_c_plus2/board.c b/ports/espressif/boards/m5stack_stick_c_plus2/board.c new file mode 100644 index 0000000000000..d84faa1888d21 --- /dev/null +++ b/ports/espressif/boards/m5stack_stick_c_plus2/board.c @@ -0,0 +1,137 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "driver/gpio.h" +#include "common-hal/microcontroller/Pin.h" + +// display init sequence according to adafruit_st7735r.py library +uint8_t display_init_sequence[] = { + 0x01, 0x80, 0x96, // SWRESET and Delay 150ms + 0x11, 0x80, 0xff, // SLPOUT and Delay + 0xb1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xb2, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR2 + 0xb3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3 + 0xb4, 0x01, 0x07, // _INVCTR line inversion + 0xc0, 0x03, 0xa2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xc1, 0x01, 0xc5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xc2, 0x02, 0x0a, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xc3, 0x02, 0x8a, 0x2a, + 0xc4, 0x02, 0x8a, 0xee, + 0xc5, 0x01, 0x0e, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x36, 0x01, 0xc8, // MADCTL Rotate display + 0x21, 0x00, // _INVON + 0x3a, 0x01, 0x05, // COLMOD - 16bit color + 0xe0, 0x10, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma + 0xe1, 0x10, 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1 + 0x13, 0x80, 0x0a, // _NORON + 0x29, 0x80, 0x64 // _DISPON +}; + +static void display_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO13, &pin_GPIO15, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO14), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // RST + 10000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 135, // width (after rotation) + 240, // height (after rotation) + 40, // column start + 52, // row start + 1, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO27, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + display_init(); +} + +bool board_requests_safe_mode(void) { + // Enable HOLD early on + config_pin_as_output_with_level(GPIO_NUM_4, true); + + // Change the buttons to inputs + gpio_set_direction(GPIO_NUM_35, GPIO_MODE_INPUT); + gpio_set_pull_mode(GPIO_NUM_35, GPIO_FLOATING); + gpio_set_direction(GPIO_NUM_37, GPIO_MODE_INPUT); + gpio_set_pull_mode(GPIO_NUM_37, GPIO_FLOATING); + gpio_set_direction(GPIO_NUM_39, GPIO_MODE_INPUT); + gpio_set_pull_mode(GPIO_NUM_39, GPIO_FLOATING); + + // Let the pins settle + mp_hal_delay_ms(1); + + // Safe mode if BTN_A is held at boot (logic low) + return gpio_get_level(GPIO_NUM_37) == 0; // BTN_A +} + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + switch (pin_number) { + case GPIO_NUM_4: // HOLD + // HOLD(G4) pin must be set high to avoid a power off when battery powered + config_pin_as_output_with_level(pin_number, true); + return true; + + case GPIO_NUM_35: // BTN_C/PWR + case GPIO_NUM_37: // BTN_A + case GPIO_NUM_39: // BTN_B + gpio_set_direction(pin_number, GPIO_MODE_INPUT); + gpio_set_pull_mode(pin_number, GPIO_FLOATING); + return true; + + default: + return false; + } + return false; +} diff --git a/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h b/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h new file mode 100644 index 0000000000000..fd11ec3ff4f05 --- /dev/null +++ b/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack Stick C Plus2" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO19) + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO22, .sda = &pin_GPIO21}, \ + {.scl = &pin_GPIO33, .sda = &pin_GPIO32}} + +// For entering safe mode +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO37) + +// Explanation of how a user got into safe mode +#define BOARD_USER_SAFE_MODE_ACTION MP_ERROR_TEXT("You pressed button A at start up.") + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.mk b/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.mk new file mode 100644 index 0000000000000..ae0736c42085c --- /dev/null +++ b/ports/espressif/boards/m5stack_stick_c_plus2/mpconfigboard.mk @@ -0,0 +1,20 @@ +CIRCUITPY_CREATOR_ID = 0x10151015 +CIRCUITPY_CREATION_ID = 0x0032000C + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m +CIRCUITPY_ESP_PSRAM_SIZE = 2MB + +# The safe mode wait gets us very close to the 3s time for the board to shut +# down when BTN_C/PWR is held down. We skip the wait and instead enter safe +# mode if BTN_A is held down during boot with no timeout. +CIRCUITPY_SKIP_SAFE_MODE_WAIT = 1 + +# Enable PDMIn for the microphone +CIRCUITPY_AUDIOBUSIO_PDMIN = 1 diff --git a/ports/espressif/boards/m5stack_stick_c_plus2/pins.c b/ports/espressif/boards/m5stack_stick_c_plus2/pins.c new file mode 100644 index 0000000000000..7459482176576 --- /dev/null +++ b/ports/espressif/boards/m5stack_stick_c_plus2/pins.c @@ -0,0 +1,78 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 n0xa, 2025 bootc +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(grove_i2c, i2c, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Pin port on the top + { MP_ROM_QSTR(MP_QSTR_G26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_G36), MP_ROM_PTR(&pin_GPIO36) }, // G36/G25 pin + { MP_ROM_QSTR(MP_QSTR_G25), MP_ROM_PTR(&pin_GPIO25) }, // G36/G25 pin + { MP_ROM_QSTR(MP_QSTR_G0), MP_ROM_PTR(&pin_GPIO0) }, // also PDM_MIC_CLK + + // Grove port on the bottom + { MP_ROM_QSTR(MP_QSTR_G32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GROVE_SDA), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_G33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GROVE_SCL), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GROVE_I2C), MP_ROM_PTR(&board_grove_i2c_obj) }, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_G37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_BTN_A), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_G39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_BTN_B), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_G35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_BTN_C), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_BTN_PWR), MP_ROM_PTR(&pin_GPIO35) }, // also WAKE + + // Buzzer / Speaker + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO2) }, + + // Red and IR LED (single pin) + { MP_ROM_QSTR(MP_QSTR_G19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IR_LED), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO19) }, + + // LCD display + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + + // Battery voltage sense + { MP_ROM_QSTR(MP_QSTR_G38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO38) }, + + // Microphone + { MP_ROM_QSTR(MP_QSTR_PDM_MIC_CLK), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_G34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_PDM_MIC_DATA), MP_ROM_PTR(&pin_GPIO34) }, + + // Internal I2C (IMU and RTC) + { MP_ROM_QSTR(MP_QSTR_G21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SYS_SDA), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_G22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SYS_SCL), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Sleep/Wake signal + { MP_ROM_QSTR(MP_QSTR_WAKE), MP_ROM_PTR(&pin_GPIO35) }, + + // Power hold + { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_HOLD), MP_ROM_PTR(&pin_GPIO4) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_stick_c_plus2/sdkconfig b/ports/espressif/boards/m5stack_stick_c_plus2/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/m5stack_stick_c_plus2/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/m5stack_tab5/board.c b/ports/espressif/boards/m5stack_tab5/board.c new file mode 100644 index 0000000000000..7c7c768d5c154 --- /dev/null +++ b/ports/espressif/boards/m5stack_tab5/board.c @@ -0,0 +1,379 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/mipidsi/Bus.h" +#include "shared-bindings/mipidsi/Display.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/framebufferio/__init__.h" +#include "shared-module/framebufferio/FramebufferDisplay.h" +#include "ports/espressif/common-hal/microcontroller/Pin.h" + +// Statically allocate the MIPI DSI bus (only one DSI bus on ESP32-P4) +static mipidsi_bus_obj_t board_mipidsi_bus; + +// ILI9881C initialization sequence +static const uint8_t ili9881c_init_sequence[] = { + 0xff, 0x03, 0x98, 0x81, 0x00, + 0x01, 0x80, 0x78, // software reset + // CMD_Page 1 + 0xff, 0x03, 0x98, 0x81, 0x01, + 0xb7, 0x01, 0x03, // set 2 lane + // CMD Page 0 + 0xff, 0x03, 0x98, 0x81, 0x00, + 0x11, 0x80, 0x0a, // out of sleep + 0x36, 0x01, 0x00, // madctl + 0x3a, 0x01, 0x55, // colmod + // CMD_Page 3 + 0xff, 0x03, 0x98, 0x81, 0x03, + 0x01, 0x01, 0x00, + 0x02, 0x01, 0x00, + 0x03, 0x01, 0x73, + 0x04, 0x01, 0x00, + 0x05, 0x01, 0x00, + 0x06, 0x01, 0x08, + 0x07, 0x01, 0x00, + 0x08, 0x01, 0x00, + 0x09, 0x01, 0x1b, + 0x0a, 0x01, 0x01, + 0x0b, 0x01, 0x01, + 0x0c, 0x01, 0x0d, + 0x0d, 0x01, 0x01, + 0x0e, 0x01, 0x01, + 0x0f, 0x01, 0x26, + 0x10, 0x01, 0x26, + 0x11, 0x01, 0x00, + 0x12, 0x01, 0x00, + 0x13, 0x01, 0x02, + 0x14, 0x01, 0x00, + 0x15, 0x01, 0x00, + 0x16, 0x01, 0x00, + 0x17, 0x01, 0x00, + 0x18, 0x01, 0x00, + 0x19, 0x01, 0x00, + 0x1a, 0x01, 0x00, + 0x1b, 0x01, 0x00, + 0x1c, 0x01, 0x00, + 0x1d, 0x01, 0x00, + 0x1e, 0x01, 0x40, + 0x1f, 0x01, 0x00, + 0x20, 0x01, 0x06, + 0x21, 0x01, 0x01, + 0x22, 0x01, 0x00, + 0x23, 0x01, 0x00, + 0x24, 0x01, 0x00, + 0x25, 0x01, 0x00, + 0x26, 0x01, 0x00, + 0x27, 0x01, 0x00, + 0x28, 0x01, 0x33, + 0x29, 0x01, 0x03, + 0x2a, 0x01, 0x00, + 0x2b, 0x01, 0x00, + 0x2c, 0x01, 0x00, + 0x2d, 0x01, 0x00, + 0x2e, 0x01, 0x00, + 0x2f, 0x01, 0x00, + 0x30, 0x01, 0x00, + 0x31, 0x01, 0x00, + 0x32, 0x01, 0x00, + 0x33, 0x01, 0x00, + 0x34, 0x01, 0x00, + 0x35, 0x01, 0x00, + 0x36, 0x01, 0x00, + 0x37, 0x01, 0x00, + 0x38, 0x01, 0x00, + 0x39, 0x01, 0x00, + 0x3a, 0x01, 0x00, + 0x3b, 0x01, 0x00, + 0x3c, 0x01, 0x00, + 0x3d, 0x01, 0x00, + 0x3e, 0x01, 0x00, + 0x3f, 0x01, 0x00, + 0x40, 0x01, 0x00, + 0x41, 0x01, 0x00, + 0x42, 0x01, 0x00, + 0x43, 0x01, 0x00, + 0x44, 0x01, 0x00, + 0x50, 0x01, 0x01, + 0x51, 0x01, 0x23, + 0x52, 0x01, 0x45, + 0x53, 0x01, 0x67, + 0x54, 0x01, 0x89, + 0x55, 0x01, 0xab, + 0x56, 0x01, 0x01, + 0x57, 0x01, 0x23, + 0x58, 0x01, 0x45, + 0x59, 0x01, 0x67, + 0x5a, 0x01, 0x89, + 0x5b, 0x01, 0xab, + 0x5c, 0x01, 0xcd, + 0x5d, 0x01, 0xef, + 0x5e, 0x01, 0x11, + 0x5f, 0x01, 0x02, + 0x60, 0x01, 0x00, + 0x61, 0x01, 0x07, + 0x62, 0x01, 0x06, + 0x63, 0x01, 0x0e, + 0x64, 0x01, 0x0f, + 0x65, 0x01, 0x0c, + 0x66, 0x01, 0x0d, + 0x67, 0x01, 0x02, + 0x68, 0x01, 0x02, + 0x69, 0x01, 0x02, + 0x6a, 0x01, 0x02, + 0x6b, 0x01, 0x02, + 0x6c, 0x01, 0x02, + 0x6d, 0x01, 0x02, + 0x6e, 0x01, 0x02, + 0x6f, 0x01, 0x02, + 0x70, 0x01, 0x02, + 0x71, 0x01, 0x02, + 0x72, 0x01, 0x02, + 0x73, 0x01, 0x05, + 0x74, 0x01, 0x01, + 0x75, 0x01, 0x02, + 0x76, 0x01, 0x00, + 0x77, 0x01, 0x07, + 0x78, 0x01, 0x06, + 0x79, 0x01, 0x0e, + 0x7a, 0x01, 0x0f, + 0x7b, 0x01, 0x0c, + 0x7c, 0x01, 0x0d, + 0x7d, 0x01, 0x02, + 0x7e, 0x01, 0x02, + 0x7f, 0x01, 0x02, + 0x80, 0x01, 0x02, + 0x81, 0x01, 0x02, + 0x82, 0x01, 0x02, + 0x83, 0x01, 0x02, + 0x84, 0x01, 0x02, + 0x85, 0x01, 0x02, + 0x86, 0x01, 0x02, + 0x87, 0x01, 0x02, + 0x88, 0x01, 0x02, + 0x89, 0x01, 0x05, + 0x8a, 0x01, 0x01, + // CMD_Page 4 + 0xff, 0x03, 0x98, 0x81, 0x04, + 0x38, 0x01, 0x01, + 0x39, 0x01, 0x00, + 0x6c, 0x01, 0x15, + 0x6e, 0x01, 0x1a, + 0x6f, 0x01, 0x25, + 0x3a, 0x01, 0xa4, + 0x8d, 0x01, 0x20, + 0x87, 0x01, 0xba, + 0x3b, 0x01, 0x98, + // CMD_Page 1 + 0xff, 0x03, 0x98, 0x81, 0x01, + 0x22, 0x01, 0x0a, + 0x31, 0x01, 0x00, + 0x50, 0x01, 0x6b, + 0x51, 0x01, 0x66, + 0x53, 0x01, 0x73, + 0x55, 0x01, 0x8b, + 0x60, 0x01, 0x1b, + 0x61, 0x01, 0x01, + 0x62, 0x01, 0x0c, + 0x63, 0x01, 0x00, + // Gamma P + 0xa0, 0x01, 0x00, + 0xa1, 0x01, 0x15, + 0xa2, 0x01, 0x1f, + 0xa3, 0x01, 0x13, + 0xa4, 0x01, 0x11, + 0xa5, 0x01, 0x21, + 0xa6, 0x01, 0x17, + 0xa7, 0x01, 0x1b, + 0xa8, 0x01, 0x6b, + 0xa9, 0x01, 0x1e, + 0xaa, 0x01, 0x2b, + 0xab, 0x01, 0x5d, + 0xac, 0x01, 0x19, + 0xad, 0x01, 0x14, + 0xae, 0x01, 0x4b, + 0xaf, 0x01, 0x1d, + 0xb0, 0x01, 0x27, + 0xb1, 0x01, 0x49, + 0xb2, 0x01, 0x5d, + 0xb3, 0x01, 0x39, + // Gamma N + 0xc0, 0x01, 0x00, + 0xc1, 0x01, 0x01, + 0xc2, 0x01, 0x0c, + 0xc3, 0x01, 0x11, + 0xc4, 0x01, 0x15, + 0xc5, 0x01, 0x28, + 0xc6, 0x01, 0x1b, + 0xc7, 0x01, 0x1c, + 0xc8, 0x01, 0x62, + 0xc9, 0x01, 0x1c, + 0xca, 0x01, 0x29, + 0xcb, 0x01, 0x60, + 0xcc, 0x01, 0x16, + 0xcd, 0x01, 0x17, + 0xce, 0x01, 0x4a, + 0xcf, 0x01, 0x23, + 0xd0, 0x01, 0x24, + 0xd1, 0x01, 0x4f, + 0xd2, 0x01, 0x5f, + 0xd3, 0x01, 0x39, + // CMD_Page 0 + 0xff, 0x03, 0x98, 0x81, 0x00, + 0x35, 0x00, + 0xfe, 0x00, + 0x29, 0x00, +}; + +// I2C addresses +#define GOODIX_TOUCH_ADDRESS 0x14 +#define ST7123_ADDRESS 0x55 +#define I2C_DEV_ADDR_PI4IOE1 0x43 + +// PI4IOE GPIO expander registers +#define PI4IO_REG_CHIP_RESET 0x01 +#define PI4IO_REG_IO_DIR 0x03 +#define PI4IO_REG_OUT_SET 0x05 +#define PI4IO_REG_OUT_H_IM 0x07 +#define PI4IO_REG_PULL_SEL 0x0D +#define PI4IO_REG_PULL_EN 0x0B + +void board_init(void) { + // Initialize I2C for GPIO expander and display detection + busio_i2c_obj_t *i2c = common_hal_board_create_i2c(0); + + // Initialize PI4IOE GPIO expander to control LCD reset + uint8_t write_buf[2]; + + common_hal_busio_i2c_try_lock(i2c); + + // Chip reset + write_buf[0] = PI4IO_REG_CHIP_RESET; + write_buf[1] = 0xFF; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Set IO direction (bit 7 as output for LCD reset) + write_buf[0] = PI4IO_REG_IO_DIR; + write_buf[1] = 0b01111111; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Set output high-impedance mode + write_buf[0] = PI4IO_REG_OUT_H_IM; + write_buf[1] = 0b00000000; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Set pull select + write_buf[0] = PI4IO_REG_PULL_SEL; + write_buf[1] = 0b01111111; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Enable pull resistors + write_buf[0] = PI4IO_REG_PULL_EN; + write_buf[1] = 0b01111111; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Set output state (including LCD reset) + write_buf[0] = PI4IO_REG_OUT_SET; + write_buf[1] = 0b01110110; + common_hal_busio_i2c_write(i2c, I2C_DEV_ADDR_PI4IOE1, write_buf, 2); + + // Small delay for reset to take effect + mp_hal_delay_ms(100); + + // Probe I2C bus to detect which display is present + bool has_goodix = common_hal_busio_i2c_probe(i2c, GOODIX_TOUCH_ADDRESS); + bool has_st7123 = common_hal_busio_i2c_probe(i2c, ST7123_ADDRESS); + + common_hal_busio_i2c_unlock(i2c); + + // Configure display parameters based on detected hardware + uint32_t bus_frequency; + uint32_t pixel_clock_frequency; + const uint8_t *init_sequence; + size_t init_sequence_len; + uint32_t hsync_pulse_width, hsync_back_porch, hsync_front_porch; + uint32_t vsync_pulse_width, vsync_back_porch, vsync_front_porch; + + if (has_goodix) { + // ILI9881C display with Goodix touch + bus_frequency = 730000000; + pixel_clock_frequency = 60000000; + init_sequence = ili9881c_init_sequence; + init_sequence_len = sizeof(ili9881c_init_sequence); + hsync_pulse_width = 40; + hsync_back_porch = 140; + hsync_front_porch = 40; + vsync_pulse_width = 4; + vsync_back_porch = 20; + vsync_front_porch = 20; + } else if (has_st7123) { + // ST7123 display + bus_frequency = 965000000; + pixel_clock_frequency = 70000000; + init_sequence = NULL; // ST7123 doesn't use init sequence + init_sequence_len = 0; + hsync_pulse_width = 2; + hsync_back_porch = 40; + hsync_front_porch = 40; + vsync_pulse_width = 2; + vsync_back_porch = 8; + vsync_front_porch = 220; + + // Not tested now + return; + } else { + return; + } + + // Initialize the statically allocated MIPI DSI bus + board_mipidsi_bus.base.type = &mipidsi_bus_type; + common_hal_mipidsi_bus_construct(&board_mipidsi_bus, bus_frequency, 2); // 2 lanes + + // Allocate display bus for the display object + primary_display_bus_t *display_bus_obj = allocate_display_bus_or_raise(); + mipidsi_display_obj_t *display = &display_bus_obj->mipidsi; + display->base.type = &mipidsi_display_type; + + common_hal_mipidsi_display_construct( + display, + &board_mipidsi_bus, // Use statically allocated bus + init_sequence, + init_sequence_len, + 0, // virtual_channel + 720, // width + 1280, // height + 0, // rotation + 16, // color_depth + &pin_GPIO22, // backlight_pin (LCD_BL) + 0.1f, // brightness + 60, // native_frames_per_second + true, // backlight_on_high + hsync_pulse_width, + hsync_back_porch, + hsync_front_porch, + vsync_pulse_width, + vsync_back_porch, + vsync_front_porch, + pixel_clock_frequency + ); + + // Create framebuffer display + framebufferio_framebufferdisplay_obj_t *fb_display = &allocate_display()->framebuffer_display; + fb_display->base.type = &framebufferio_framebufferdisplay_type; + + common_hal_framebufferio_framebufferdisplay_construct( + fb_display, + MP_OBJ_FROM_PTR(display), + 0, // rotation + true // auto_refresh + ); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/m5stack_tab5/mpconfigboard.h b/ports/espressif/boards/m5stack_tab5/mpconfigboard.h new file mode 100644 index 0000000000000..6c748e93ecdbe --- /dev/null +++ b/ports/espressif/boards/m5stack_tab5/mpconfigboard.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "M5Stack Tab5" +#define MICROPY_HW_MCU_NAME "ESP32P4" + +// I2C bus for touch, IMU, RTC, power monitor, and GPIO expanders +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO32, .sda = &pin_GPIO31}} + +// UART +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO37) + +// SPI on M5-Bus +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO5) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO19) + +// Use the second USB device (numbered 0 and 1) +#define CIRCUITPY_USB_DEVICE_INSTANCE 0 +#define CIRCUITPY_ESP32P4_SWAP_LSFS (1) diff --git a/ports/espressif/boards/m5stack_tab5/mpconfigboard.mk b/ports/espressif/boards/m5stack_tab5/mpconfigboard.mk new file mode 100644 index 0000000000000..4871a259e7a48 --- /dev/null +++ b/ports/espressif/boards/m5stack_tab5/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x832B +USB_PRODUCT = "M5Stack Tab5" +USB_MANUFACTURER = "M5Stack" + +IDF_TARGET = esp32p4 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 32MB +CIRCUITPY_ESP_PSRAM_MODE = hpi +CIRCUITPY_ESP_PSRAM_FREQ = 200m diff --git a/ports/espressif/boards/m5stack_tab5/pins.c b/ports/espressif/boards/m5stack_tab5/pins.c new file mode 100644 index 0000000000000..c64d8803c02cf --- /dev/null +++ b/ports/espressif/boards/m5stack_tab5/pins.c @@ -0,0 +1,132 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // M5-Bus and general GPIO + { MP_ROM_QSTR(MP_QSTR_G2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_G3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_G4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_G6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_G7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_G16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_G17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_G35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_G45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_G47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_G48), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_G51), MP_ROM_PTR(&pin_GPIO51) }, + { MP_ROM_QSTR(MP_QSTR_G52), MP_ROM_PTR(&pin_GPIO52) }, + + // SPI (on M5-Bus) + { MP_ROM_QSTR(MP_QSTR_G5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_G18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_G19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO19) }, + + // UART (on M5-Bus) + { MP_ROM_QSTR(MP_QSTR_G37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_TXD0), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_G38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_RXD0), MP_ROM_PTR(&pin_GPIO38) }, + + // I2C (Touch, IMU, RTC, Power Monitor, GPIO Expanders) + { MP_ROM_QSTR(MP_QSTR_G31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_G32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO32) }, + + // Touch Panel + { MP_ROM_QSTR(MP_QSTR_G23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_TP_INT), MP_ROM_PTR(&pin_GPIO23) }, + + // LCD + { MP_ROM_QSTR(MP_QSTR_G22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO22) }, + + // Audio ES8388/ES7210 + { MP_ROM_QSTR(MP_QSTR_G26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DSDIN), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_G27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SCLK), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_G28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_I2S_ASDOUT), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_G29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCK), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_G30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO30) }, + + // Camera + { MP_ROM_QSTR(MP_QSTR_G36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_CAM_MCLK), MP_ROM_PTR(&pin_GPIO36) }, + + // microSD Card (SDIO mode) + { MP_ROM_QSTR(MP_QSTR_G39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT0), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_G40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT1), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_G41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT2), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_G42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT3), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_G43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_G44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO44) }, + + // RS485 + { MP_ROM_QSTR(MP_QSTR_G20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_RS485_TX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_G21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_RS485_RX), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_G34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_RS485_DIR), MP_ROM_PTR(&pin_GPIO34) }, + + // HY2.0-4P PORT.A + { MP_ROM_QSTR(MP_QSTR_G53), MP_ROM_PTR(&pin_GPIO53) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_Y), MP_ROM_PTR(&pin_GPIO53) }, + { MP_ROM_QSTR(MP_QSTR_G54), MP_ROM_PTR(&pin_GPIO54) }, + { MP_ROM_QSTR(MP_QSTR_PORTA_W), MP_ROM_PTR(&pin_GPIO54) }, + + // ESP32-C6 SDIO interface + { MP_ROM_QSTR(MP_QSTR_G8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_D3), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_G9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_D2), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_G10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_D1), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_G11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_G12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_CK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_G13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_C6_SDIO2_CMD), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_G14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_C6_IO2), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_G15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_C6_RESET), MP_ROM_PTR(&pin_GPIO15) }, + + // I2C and SPI objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/m5stack_tab5/sdkconfig b/ports/espressif/boards/m5stack_tab5/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/m5stack_timer_camera_x/board.c b/ports/espressif/boards/m5stack_timer_camera_x/board.c index 9842a0a53ee4a..004aaa092815b 100755 --- a/ports/espressif/boards/m5stack_timer_camera_x/board.c +++ b/ports/espressif/boards/m5stack_timer_camera_x/board.c @@ -18,8 +18,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { * when usb is disconnected or * the power button is released. */ - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } return false; diff --git a/ports/espressif/boards/m5stack_timer_camera_x/mpconfigboard.mk b/ports/espressif/boards/m5stack_timer_camera_x/mpconfigboard.mk index 4fcacd94d3d29..e17f5061d9e85 100644 --- a/ports/espressif/boards/m5stack_timer_camera_x/mpconfigboard.mk +++ b/ports/espressif/boards/m5stack_timer_camera_x/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = opi CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/m5stack_timer_camera_x/sdkconfig b/ports/espressif/boards/m5stack_timer_camera_x/sdkconfig index a600e00b31aac..116258b906bf4 100644 --- a/ports/espressif/boards/m5stack_timer_camera_x/sdkconfig +++ b/ports/espressif/boards/m5stack_timer_camera_x/sdkconfig @@ -29,7 +29,6 @@ CONFIG_ESP_REV_MIN_FULL=300 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="M5StackTimerX" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/magiclick_s3_n4r2/mpconfigboard.mk b/ports/espressif/boards/magiclick_s3_n4r2/mpconfigboard.mk index 6c2159c647844..fe2eb2c7a7690 100644 --- a/ports/espressif/boards/magiclick_s3_n4r2/mpconfigboard.mk +++ b/ports/espressif/boards/magiclick_s3_n4r2/mpconfigboard.mk @@ -14,5 +14,6 @@ CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB +# No pins. CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_DISPLAYIO = 1 diff --git a/ports/espressif/boards/magiclick_s3_n4r2/sdkconfig b/ports/espressif/boards/magiclick_s3_n4r2/sdkconfig index 3e9b8e2f17375..122e6f9024690 100644 --- a/ports/espressif/boards/magiclick_s3_n4r2/sdkconfig +++ b/ports/espressif/boards/magiclick_s3_n4r2/sdkconfig @@ -8,7 +8,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="MagiClick-ESP32S3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/maker_badge/mpconfigboard.mk b/ports/espressif/boards/maker_badge/mpconfigboard.mk index 979ae581e3dbe..13229c02dbf47 100644 --- a/ports/espressif/boards/maker_badge/mpconfigboard.mk +++ b/ports/espressif/boards/maker_badge/mpconfigboard.mk @@ -3,14 +3,12 @@ USB_PID = 0x2030 USB_PRODUCT = "Maker badge" USB_MANUFACTURER = "Czech maker" -CIRCUITPY_ESPCAMERA = 0 +IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=40m CIRCUITPY_ESP_FLASH_SIZE=4MB -IDF_TARGET = esp32s2 - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/maker_badge/sdkconfig b/ports/espressif/boards/maker_badge/sdkconfig index d62227df74f46..e962866216039 100644 --- a/ports/espressif/boards/maker_badge/sdkconfig +++ b/ports/espressif/boards/maker_badge/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Maker_badge" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/makerfabs_tft7/board.c b/ports/espressif/boards/makerfabs_tft7/board.c index 2ef34c8be8561..a994cfef38118 100644 --- a/ports/espressif/boards/makerfabs_tft7/board.c +++ b/ports/espressif/boards/makerfabs_tft7/board.c @@ -6,9 +6,95 @@ #include "supervisor/board.h" #include "mpconfigboard.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h" +#include "shared-bindings/dotclockframebuffer/__init__.h" +#include "shared-bindings/framebufferio/FramebufferDisplay.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/settings.h" + +static const mcu_pin_obj_t *blue_pins[] = { + &pin_GPIO8, + &pin_GPIO3, + &pin_GPIO46, + &pin_GPIO9, + &pin_GPIO1 +}; +static const mcu_pin_obj_t *green_pins[] = { + &pin_GPIO5, + &pin_GPIO6, + &pin_GPIO7, + &pin_GPIO15, + &pin_GPIO16, + &pin_GPIO4 +}; +static const mcu_pin_obj_t *red_pins[] = { + &pin_GPIO45, + &pin_GPIO48, + &pin_GPIO47, + &pin_GPIO21, + &pin_GPIO14 +}; + +static void display_init(void) { + + mp_int_t height = 0, width = 0, frequency = 0; + settings_err_t result; + + result = settings_get_int("CIRCUITPY_DISPLAY_WIDTH", &width); + if (result == SETTINGS_OK && width == 800) { + width = 800; + height = 480; + frequency = 6500000; + } else if (result == SETTINGS_OK && width == 1024) { + width = 1024; + height = 600; + frequency = 10000000; + } + + if (height == 0) { + width = 800; + height = 480; + frequency = 6500000; + } + + dotclockframebuffer_framebuffer_obj_t *framebuffer = &allocate_display_bus_or_raise()->dotclock; + framebuffer->base.type = &dotclockframebuffer_framebuffer_type; + + common_hal_dotclockframebuffer_framebuffer_construct( + framebuffer, + &pin_GPIO40, // de + &pin_GPIO41, // vsync + &pin_GPIO39, // hsync + &pin_GPIO42, // pclk + red_pins, MP_ARRAY_SIZE(red_pins), + green_pins, MP_ARRAY_SIZE(green_pins), + blue_pins, MP_ARRAY_SIZE(blue_pins), + frequency, // Frequency + width, // width + height, // height + 30, 16, 210, false, // horiz: pulse, back porch, front porch, idle low + 13, 10, 22, false, // vert: pulse, back porch, front porch, idle low + false, // DE idle high + false, // pclk active high + false, // pclk idle high + 0 // overscan left + ); + + framebufferio_framebufferdisplay_obj_t *display = &allocate_display_or_raise()->framebuffer_display; + display->base.type = &framebufferio_framebufferdisplay_type; + common_hal_framebufferio_framebufferdisplay_construct( + display, + framebuffer, + 0, // rotation + true // auto-refresh + ); +} void board_init(void) { + display_init(); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/makerfabs_tft7/pins.c b/ports/espressif/boards/makerfabs_tft7/pins.c index 9f9730c942399..ccc72b23e47b8 100644 --- a/ports/espressif/boards/makerfabs_tft7/pins.c +++ b/ports/espressif/boards/makerfabs_tft7/pins.c @@ -6,6 +6,7 @@ #include "py/objtuple.h" #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" static const mp_rom_obj_tuple_t tft_r_pins = { {&mp_type_tuple}, @@ -120,10 +121,11 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { // IO10 <> SD_CS is cut at factory (non-placed resistor position R34) and pulled up. // Permanent SDIO 1-bit mode? - // Until SDIO 1-bit mode is support on Espressif ports these pins aren't useful - // { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO11) }, - // { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO13) }, - // { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, // boot mode button can be used in SW as well { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO1) }, diff --git a/ports/espressif/boards/makerfabs_tft7/sdkconfig b/ports/espressif/boards/makerfabs_tft7/sdkconfig index e05ead7960290..e962866216039 100644 --- a/ports/espressif/boards/makerfabs_tft7/sdkconfig +++ b/ports/espressif/boards/makerfabs_tft7/sdkconfig @@ -4,23 +4,9 @@ # # Component config # -# -# ESP System Settings -# -CONFIG_ESP_CONSOLE_UART_CUSTOM=y -# CONFIG_ESP_CONSOLE_NONE is not set -CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_UART_CUSTOM_NUM_0=y -CONFIG_ESP_CONSOLE_UART_NUM=0 -CONFIG_ESP_CONSOLE_UART_TX_GPIO=43 -CONFIG_ESP_CONSOLE_UART_RX_GPIO=44 -CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -# end of ESP System Settings - # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="matouch-tft" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/makergo_esp32c3_supermini/mpconfigboard.mk b/ports/espressif/boards/makergo_esp32c3_supermini/mpconfigboard.mk index 37c27203af31c..d82f62df37791 100644 --- a/ports/espressif/boards/makergo_esp32c3_supermini/mpconfigboard.mk +++ b/ports/espressif/boards/makergo_esp32c3_supermini/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/makergo_esp32c3_supermini/sdkconfig b/ports/espressif/boards/makergo_esp32c3_supermini/sdkconfig index dc7f10a362f92..e962866216039 100644 --- a/ports/espressif/boards/makergo_esp32c3_supermini/sdkconfig +++ b/ports/espressif/boards/makergo_esp32c3_supermini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="makergo-esp32c3-supermini" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/makergo_esp32c6_supermini/board.c b/ports/espressif/boards/makergo_esp32c6_supermini/board.c new file mode 100644 index 0000000000000..8cb7168e0da8d --- /dev/null +++ b/ports/espressif/boards/makergo_esp32c6_supermini/board.c @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 bill88t +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "driver/gpio.h" +#include "common-hal/microcontroller/Pin.h" + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + if (pin_number == 15) { + // Turn on the spare led on boot as a power indicator. + config_pin_as_output_with_level(pin_number, true); + return true; + } + return false; +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.h b/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.h new file mode 100644 index 0000000000000..ed8dec14f0ae5 --- /dev/null +++ b/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris, independently providing these changes. +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "Maker Go ESP32C6 Supermini" +#define MICROPY_HW_MCU_NAME "ESP32-C6" + +// Status LED +#define MICROPY_HW_NEOPIXEL (&pin_GPIO8) +#define MICROPY_HW_NEOPIXEL_COUNT (1) + +// Default bus pins +#define DEFAULT_UART_BUS_TX (&pin_GPIO17) +#define DEFAULT_UART_BUS_RX (&pin_GPIO16) diff --git a/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.mk b/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.mk new file mode 100644 index 0000000000000..ca425c0159332 --- /dev/null +++ b/ports/espressif/boards/makergo_esp32c6_supermini/mpconfigboard.mk @@ -0,0 +1,11 @@ +CIRCUITPY_CREATOR_ID = 0x19981000 +CIRCUITPY_CREATION_ID = 0x00C60001 + +IDF_TARGET = esp32c6 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/makergo_esp32c6_supermini/pins.c b/ports/espressif/boards/makergo_esp32c6_supermini/pins.c new file mode 100644 index 0000000000000..b396e5bb1afa5 --- /dev/null +++ b/ports/espressif/boards/makergo_esp32c6_supermini/pins.c @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris, independently providing these changes. +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Left to Right top to bottom + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + + // Extras + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/makergo_esp32c6_supermini/sdkconfig b/ports/espressif/boards/makergo_esp32c6_supermini/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/makergo_esp32c6_supermini/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/microdev_micro_c3/mpconfigboard.mk b/ports/espressif/boards/microdev_micro_c3/mpconfigboard.mk index b2ea6005db53a..79821f7c0e5d1 100644 --- a/ports/espressif/boards/microdev_micro_c3/mpconfigboard.mk +++ b/ports/espressif/boards/microdev_micro_c3/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/microdev_micro_c3/sdkconfig b/ports/espressif/boards/microdev_micro_c3/sdkconfig index 9b13279bd385e..e962866216039 100644 --- a/ports/espressif/boards/microdev_micro_c3/sdkconfig +++ b/ports/espressif/boards/microdev_micro_c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="MicroDev-microC3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/microdev_micro_s2/sdkconfig b/ports/espressif/boards/microdev_micro_s2/sdkconfig index f6158eac3ecc1..e962866216039 100644 --- a/ports/espressif/boards/microdev_micro_s2/sdkconfig +++ b/ports/espressif/boards/microdev_micro_s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="MicroDev-microS2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk b/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk index 1d370fd30e712..9b96aa31c9eae 100644 --- a/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk +++ b/ports/espressif/boards/mixgo_ce_serial/mpconfigboard.mk @@ -9,12 +9,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_AESIO = 0 -CIRCUITPY_AUDIOBUSIO = 0 -CIRCUITPY_CANIO = 0 -CIRCUITPY_CODEOP = 0 -CIRCUITPY_ESPCAMERA = 0 - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk b/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk index 691da625e0358..d6447ee7134e8 100644 --- a/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk +++ b/ports/espressif/boards/mixgo_ce_udisk/mpconfigboard.mk @@ -9,10 +9,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_AESIO = 0 -CIRCUITPY_CODEOP = 0 -CIRCUITPY_ESPCAMERA = 0 - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ConnectionManager FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Requests FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/morpheans_morphesp-240/board.c b/ports/espressif/boards/morpheans_morphesp-240/board.c index 5b1c3f82bbbdb..44266cce6ed9f 100644 --- a/ports/espressif/boards/morpheans_morphesp-240/board.c +++ b/ports/espressif/boards/morpheans_morphesp-240/board.c @@ -138,9 +138,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO14, // DC - &pin_GPIO10, // CS - &pin_GPIO9, // RST + MP_OBJ_FROM_PTR(&pin_GPIO14), // DC + MP_OBJ_FROM_PTR(&pin_GPIO10), // CS + MP_OBJ_FROM_PTR(&pin_GPIO9), // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.mk b/ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.mk index 8a6b359d238c2..5c806cb69b281 100644 --- a/ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.mk +++ b/ports/espressif/boards/morpheans_morphesp-240/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/morpheans_morphesp-240/sdkconfig b/ports/espressif/boards/morpheans_morphesp-240/sdkconfig index b0a838eacc8b0..e962866216039 100644 --- a/ports/espressif/boards/morpheans_morphesp-240/sdkconfig +++ b/ports/espressif/boards/morpheans_morphesp-240/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="MORPHESP-240" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.mk b/ports/espressif/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.mk index bb3c0ea4d829c..b2540a8c3b872 100644 --- a/ports/espressif/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.mk +++ b/ports/espressif/boards/muselab_nanoesp32_s2_wroom/mpconfigboard.mk @@ -8,4 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/nodemcu_esp32c2/mpconfigboard.mk b/ports/espressif/boards/nodemcu_esp32c2/mpconfigboard.mk index dd90b325b6d3b..249dd80bebdd1 100644 --- a/ports/espressif/boards/nodemcu_esp32c2/mpconfigboard.mk +++ b/ports/espressif/boards/nodemcu_esp32c2/mpconfigboard.mk @@ -6,3 +6,6 @@ IDF_TARGET = esp32c2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 60m CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/nodemcu_esp32c2/pins.c b/ports/espressif/boards/nodemcu_esp32c2/pins.c index 04cd1b1929be5..046a3d2707b38 100644 --- a/ports/espressif/boards/nodemcu_esp32c2/pins.c +++ b/ports/espressif/boards/nodemcu_esp32c2/pins.c @@ -1,6 +1,6 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS // Module on top, from top to bottom, left to right diff --git a/ports/espressif/boards/nodemcu_esp32c2/sdkconfig b/ports/espressif/boards/nodemcu_esp32c2/sdkconfig index ed7abbdd59b03..f53dd7f8795bc 100644 --- a/ports/espressif/boards/nodemcu_esp32c2/sdkconfig +++ b/ports/espressif/boards/nodemcu_esp32c2/sdkconfig @@ -32,7 +32,6 @@ CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="nodemcu-esp32c2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/odt_pixelwing_esp32_s2/sdkconfig b/ports/espressif/boards/odt_pixelwing_esp32_s2/sdkconfig index 3017a9532f610..e962866216039 100644 --- a/ports/espressif/boards/odt_pixelwing_esp32_s2/sdkconfig +++ b/ports/espressif/boards/odt_pixelwing_esp32_s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="PixelWing-ESP32S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/oxocard_artwork/board.c b/ports/espressif/boards/oxocard_artwork/board.c index 600bc0c594360..5fe8e8145583a 100644 --- a/ports/espressif/boards/oxocard_artwork/board.c +++ b/ports/espressif/boards/oxocard_artwork/board.c @@ -43,9 +43,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO15, // CS - &pin_GPIO4, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // CS + MP_OBJ_FROM_PTR(&pin_GPIO4), // RST 24000000, // baudrate 0, // polarity 0 // phase @@ -60,7 +60,7 @@ static void display_init(void) { 240, // width (after rotation) 240, // height (after rotation) 0, // column start - 80, // row start + 0, // row start 0, // rotation 16, // color depth false, // grayscale diff --git a/ports/espressif/boards/oxocard_artwork/mpconfigboard.mk b/ports/espressif/boards/oxocard_artwork/mpconfigboard.mk index a7dfe8b8e33ae..61367774a2195 100644 --- a/ports/espressif/boards/oxocard_artwork/mpconfigboard.mk +++ b/ports/espressif/boards/oxocard_artwork/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/oxocard_connect/board.c b/ports/espressif/boards/oxocard_connect/board.c index 89be45c82262e..2c01381147437 100644 --- a/ports/espressif/boards/oxocard_connect/board.c +++ b/ports/espressif/boards/oxocard_connect/board.c @@ -44,9 +44,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO15, // CS - &pin_GPIO4, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // CS + MP_OBJ_FROM_PTR(&pin_GPIO4), // RST 24000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/oxocard_connect/mpconfigboard.mk b/ports/espressif/boards/oxocard_connect/mpconfigboard.mk index 49b8a4f4c879d..ea00787921d63 100644 --- a/ports/espressif/boards/oxocard_connect/mpconfigboard.mk +++ b/ports/espressif/boards/oxocard_connect/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/oxocard_connect/pins.c b/ports/espressif/boards/oxocard_connect/pins.c index dbee3e0c435eb..3a1a88786c14d 100644 --- a/ports/espressif/boards/oxocard_connect/pins.c +++ b/ports/espressif/boards/oxocard_connect/pins.c @@ -12,8 +12,8 @@ CIRCUITPY_BOARD_BUS_SINGLETON(stemma_i2c, i2c, 1) static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - { MP_ROM_QSTR(MP_QSTR_BTN5), MP_ROM_PTR(&pin_GPIO0) }, - { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BTN5), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO2) }, { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, { MP_ROM_QSTR(MP_QSTR_LCD_LED), MP_ROM_PTR(&pin_GPIO19) }, @@ -39,7 +39,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_IN06), MP_ROM_PTR(&pin_GPIO34) }, { MP_ROM_QSTR(MP_QSTR_IN07), MP_ROM_PTR(&pin_GPIO35) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, diff --git a/ports/espressif/boards/oxocard_galaxy/board.c b/ports/espressif/boards/oxocard_galaxy/board.c index 600bc0c594360..5fe8e8145583a 100644 --- a/ports/espressif/boards/oxocard_galaxy/board.c +++ b/ports/espressif/boards/oxocard_galaxy/board.c @@ -43,9 +43,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO15, // CS - &pin_GPIO4, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // CS + MP_OBJ_FROM_PTR(&pin_GPIO4), // RST 24000000, // baudrate 0, // polarity 0 // phase @@ -60,7 +60,7 @@ static void display_init(void) { 240, // width (after rotation) 240, // height (after rotation) 0, // column start - 80, // row start + 0, // row start 0, // rotation 16, // color depth false, // grayscale diff --git a/ports/espressif/boards/oxocard_galaxy/mpconfigboard.mk b/ports/espressif/boards/oxocard_galaxy/mpconfigboard.mk index 915d7cc5862a3..e4786df383ce8 100644 --- a/ports/espressif/boards/oxocard_galaxy/mpconfigboard.mk +++ b/ports/espressif/boards/oxocard_galaxy/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/oxocard_science/board.c b/ports/espressif/boards/oxocard_science/board.c index 600bc0c594360..5fe8e8145583a 100644 --- a/ports/espressif/boards/oxocard_science/board.c +++ b/ports/espressif/boards/oxocard_science/board.c @@ -43,9 +43,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO27, // DC - &pin_GPIO15, // CS - &pin_GPIO4, // RST + MP_OBJ_FROM_PTR(&pin_GPIO27), // DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // CS + MP_OBJ_FROM_PTR(&pin_GPIO4), // RST 24000000, // baudrate 0, // polarity 0 // phase @@ -60,7 +60,7 @@ static void display_init(void) { 240, // width (after rotation) 240, // height (after rotation) 0, // column start - 80, // row start + 0, // row start 0, // rotation 16, // color depth false, // grayscale diff --git a/ports/espressif/boards/oxocard_science/mpconfigboard.mk b/ports/espressif/boards/oxocard_science/mpconfigboard.mk index d31be7d799292..9d89108f39224 100644 --- a/ports/espressif/boards/oxocard_science/mpconfigboard.mk +++ b/ports/espressif/boards/oxocard_science/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h new file mode 100644 index 0000000000000..2114fecf373a4 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Prokyber Ai-On-The-Edge-Cam" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO12) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO48) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk new file mode 100644 index 0000000000000..82419bb80745c --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x1209 +USB_PID = 0xDABB +USB_PRODUCT = "AI-ON-THE-EDGE-CAM" +USB_MANUFACTURER = "Prokyber" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m +CIRCUITPY_ESP_PSRAM_SIZE = 8MB diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c new file mode 100644 index 0000000000000..68dc40781a480 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/pins.c @@ -0,0 +1,106 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" + +static const mp_rom_obj_tuple_t camera_data_tuple = { + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO47), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO17), + MP_ROM_PTR(&pin_GPIO16), + } +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_PER_EN), MP_ROM_PTR(&pin_GPIO46) }, + + // SD + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + + // Ethernet + { MP_ROM_QSTR(MP_QSTR_ETH_RST), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_INT), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_MOSI), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_MISO), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_CLK), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_ETH_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + + // LEDs + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA), MP_ROM_PTR(&camera_data_tuple) }, + + { MP_ROM_QSTR(MP_QSTR_CAMERA_VSYNC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_HREF), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA9), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_XCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA8), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA7), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_PCLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA6), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA2), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA5), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA3), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_DATA4), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOD), MP_ROM_PTR(&pin_GPIO4) }, // SDA + { MP_ROM_QSTR(MP_QSTR_CAMERA_SIOC), MP_ROM_PTR(&pin_GPIO5) }, // SCL + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig new file mode 100644 index 0000000000000..ac1c535717672 --- /dev/null +++ b/ports/espressif/boards/prokyber_ai_on_the_edge_cam/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP +CONFIG_OV2640_SUPPORT=y +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/red-s2-wroom/board.c b/ports/espressif/boards/red-s2-wroom/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/red-s2-wroom/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/red-s2-wroom/mpconfigboard.h b/ports/espressif/boards/red-s2-wroom/mpconfigboard.h new file mode 100644 index 0000000000000..24a5948e0c1a0 --- /dev/null +++ b/ports/espressif/boards/red-s2-wroom/mpconfigboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Red S2-WROOM" +#define MICROPY_HW_MCU_NAME "ESP32S2" diff --git a/ports/espressif/boards/red-s2-wroom/mpconfigboard.mk b/ports/espressif/boards/red-s2-wroom/mpconfigboard.mk new file mode 100644 index 0000000000000..33a83f954a7c4 --- /dev/null +++ b/ports/espressif/boards/red-s2-wroom/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x303A +USB_PID = 0x82C4 +USB_PRODUCT = "ESP32-S2-WROOM" +USB_MANUFACTURER = "Unknown" + +IDF_TARGET = esp32s2 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB diff --git a/ports/espressif/boards/red-s2-wroom/pins.c b/ports/espressif/boards/red-s2-wroom/pins.c new file mode 100644 index 0000000000000..1e0be2b4e8a09 --- /dev/null +++ b/ports/espressif/boards/red-s2-wroom/pins.c @@ -0,0 +1,55 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + + + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/red-s2-wroom/sdkconfig b/ports/espressif/boards/red-s2-wroom/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/seeed_xiao_esp32_s3_sense/board.c b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/board.c new file mode 100644 index 0000000000000..fea7fe2c3002e --- /dev/null +++ b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "mpconfigboard.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.h b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.h new file mode 100644 index 0000000000000..d7f24b255d69c --- /dev/null +++ b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Seeed Xiao ESP32-S3 Sense" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO7) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO9) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO8) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO6) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO5) diff --git a/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.mk b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.mk new file mode 100644 index 0000000000000..a4e08fb876735 --- /dev/null +++ b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x2886 +USB_PID = 0x8056 + +USB_PRODUCT = "Seeed Xiao ESP32-S3 Sense" +USB_MANUFACTURER = "Seeed Studio" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_ESPCAMERA = 1 +CIRCUITPY_AUDIOBUSIO = 1 diff --git a/ports/espressif/boards/seeed_xiao_esp32_s3_sense/pins.c b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/pins.c new file mode 100644 index 0000000000000..fbb6014685ca4 --- /dev/null +++ b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/pins.c @@ -0,0 +1,124 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sscb_i2c, i2c, 2) + +static const mp_rom_obj_tuple_t camera_data_tuple = { + // The order matters. + // They must be ordered from low to high (CAM_D0, CAM_D1...CAM_D7). + + // Do not include any of the control pins in here. + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO15), + MP_ROM_PTR(&pin_GPIO17), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO16), + MP_ROM_PTR(&pin_GPIO14), + MP_ROM_PTR(&pin_GPIO12), + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO48), + } +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SD), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_CAM_VSYNC), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_I2S_SCK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MTCK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_CAM_SCL), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WS), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_MTDO), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_CAM_SDA), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_MTDI), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_MIC_DATA), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_RX_1), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_MTMS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_MIC_CLK), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_TX_1), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_SCK_1), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_MISO_1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D5), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_MOSI_1), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D6), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SDCS), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_CAM_DATA), MP_ROM_PTR(&camera_data_tuple) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D0), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D2), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D3), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D4), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D7), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/seeed_xiao_esp32_s3_sense/sdkconfig b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/sdkconfig new file mode 100644 index 0000000000000..2d98e8225429b --- /dev/null +++ b/ports/espressif/boards/seeed_xiao_esp32_s3_sense/sdkconfig @@ -0,0 +1,17 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# +# Camera configuration +# +# CONFIG_OV7725_SUPPORT is not set +CONFIG_OV2640_SUPPORT=y +# end of Camera configuration + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/seeed_xiao_esp32c3/mpconfigboard.mk b/ports/espressif/boards/seeed_xiao_esp32c3/mpconfigboard.mk index b71a41ef6e31a..c5b266ca74435 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c3/mpconfigboard.mk +++ b/ports/espressif/boards/seeed_xiao_esp32c3/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/seeed_xiao_esp32c3/sdkconfig b/ports/espressif/boards/seeed_xiao_esp32c3/sdkconfig index a593f1d173688..e962866216039 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c3/sdkconfig +++ b/ports/espressif/boards/seeed_xiao_esp32c3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="seeed-xiao-esp32c3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/seeed_xiao_esp32c6/board.c b/ports/espressif/boards/seeed_xiao_esp32c6/board.c index 75d9ade589b03..7a013bc9d0b7e 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c6/board.c +++ b/ports/espressif/boards/seeed_xiao_esp32c6/board.c @@ -33,8 +33,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 16) { // Turn on I2C power by default. - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, true); + config_pin_as_output_with_level(pin_number, true); return true; } diff --git a/ports/espressif/boards/seeed_xiao_esp32c6/mpconfigboard.mk b/ports/espressif/boards/seeed_xiao_esp32c6/mpconfigboard.mk index e7ee13c027acd..ce6763afbcc3c 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c6/mpconfigboard.mk +++ b/ports/espressif/boards/seeed_xiao_esp32c6/mpconfigboard.mk @@ -7,4 +7,5 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/seeed_xiao_esp32c6/pins.c b/ports/espressif/boards/seeed_xiao_esp32c6/pins.c index 0cb7f64e4163a..1b62b37065eec 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c6/pins.c +++ b/ports/espressif/boards/seeed_xiao_esp32c6/pins.c @@ -1,6 +1,6 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, @@ -47,6 +47,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_MTCK), MP_ROM_PTR(&pin_GPIO6) }, { MP_ROM_QSTR(MP_QSTR_LP_I2C_SDA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LED_INVERTED), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_MTDO), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_LP_I2C_SCL), MP_ROM_PTR(&pin_GPIO7) }, diff --git a/ports/espressif/boards/seeed_xiao_esp32c6/sdkconfig b/ports/espressif/boards/seeed_xiao_esp32c6/sdkconfig index a69b0b6c770bc..e962866216039 100644 --- a/ports/espressif/boards/seeed_xiao_esp32c6/sdkconfig +++ b/ports/espressif/boards/seeed_xiao_esp32c6/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="seeed-xiao-esp32c6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/board.c b/ports/espressif/boards/sensebox_eye_esp32s3/board.c new file mode 100644 index 0000000000000..fea7fe2c3002e --- /dev/null +++ b/ports/espressif/boards/sensebox_eye_esp32s3/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "mpconfigboard.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h b/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h new file mode 100644 index 0000000000000..3908c492f1b01 --- /dev/null +++ b/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "senseBox-eye ESP32S3" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO45) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO1) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk b/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk new file mode 100644 index 0000000000000..55e822c5dea4a --- /dev/null +++ b/ports/espressif/boards/sensebox_eye_esp32s3/mpconfigboard.mk @@ -0,0 +1,21 @@ +USB_VID = 0x303A +USB_PID = 0x82D2 + +USB_PRODUCT = "senseBox-eye ESP32S3" +USB_MANUFACTURER = "senseBox" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_ESPCAMERA = 1 +CIRCUITPY_AUDIOBUSIO = 1 + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/pins.c b/ports/espressif/boards/sensebox_eye_esp32s3/pins.c new file mode 100644 index 0000000000000..c218fafa918ce --- /dev/null +++ b/ports/espressif/boards/sensebox_eye_esp32s3/pins.c @@ -0,0 +1,82 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sscb_i2c, i2c, 2) + +static const mp_rom_obj_tuple_t camera_data_tuple = { + // The order matters. + // They must be ordered from low to high (CAM_D0, CAM_D1...CAM_D7). + + // Do not include any of the control pins in here. + {&mp_type_tuple}, + 8, + { + MP_ROM_PTR(&pin_GPIO11), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO10), + MP_ROM_PTR(&pin_GPIO12), + MP_ROM_PTR(&pin_GPIO18), + MP_ROM_PTR(&pin_GPIO17), + MP_ROM_PTR(&pin_GPIO16), + } +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + {MP_ROM_QSTR(MP_QSTR_BUTTON_SW), MP_ROM_PTR(&pin_GPIO47) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_A14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_A48), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_D48), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_UART_ENABLE), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_CAM_DATA), MP_ROM_PTR(&camera_data_tuple) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D2), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D3), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D4), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D5), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D6), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D7), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAM_VSYNC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAM_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_CAM_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_PWDN), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCLK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_SD_ENABLE), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/sensebox_eye_esp32s3/sdkconfig b/ports/espressif/boards/sensebox_eye_esp32s3/sdkconfig new file mode 100644 index 0000000000000..919f4d9f345ff --- /dev/null +++ b/ports/espressif/boards/sensebox_eye_esp32s3/sdkconfig @@ -0,0 +1,19 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP +# Camera configuration +# +CONFIG_OV2640_SUPPORT=y +# CONFIG_OV7725_SUPPORT is not set +# CONFIG_OV3660_SUPPORT is not set +# end of Camera configuration +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/sensebox_mcu_esp32s2/mpconfigboard.mk b/ports/espressif/boards/sensebox_mcu_esp32s2/mpconfigboard.mk index a8c32ae88dfea..6b97c870cc032 100644 --- a/ports/espressif/boards/sensebox_mcu_esp32s2/mpconfigboard.mk +++ b/ports/espressif/boards/sensebox_mcu_esp32s2/mpconfigboard.mk @@ -1,7 +1,7 @@ USB_VID = 0x303A USB_PID = 0x81B9 USB_PRODUCT = "senseBox MCU-S2 ESP32S2" -USB_MANUFACTURER = "Espressif" +USB_MANUFACTURER = "senseBox" IDF_TARGET = esp32s2 @@ -9,8 +9,6 @@ CIRCUITPY_ESP_FLASH_SIZE = 4MB CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 - CIRCUITPY_REQUIRE_I2C_PULLUPS = 0 CIRCUITPY_I2C_ALLOW_STRAPPING_PINS = 1 diff --git a/ports/espressif/boards/sensebox_mcu_esp32s2/sdkconfig b/ports/espressif/boards/sensebox_mcu_esp32s2/sdkconfig index d8608c527c066..e962866216039 100644 --- a/ports/espressif/boards/sensebox_mcu_esp32s2/sdkconfig +++ b/ports/espressif/boards/sensebox_mcu_esp32s2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="senseBox MCU-S2 ESP32S2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/smartbeedesigns_bee_data_logger/mpconfigboard.mk b/ports/espressif/boards/smartbeedesigns_bee_data_logger/mpconfigboard.mk index 6ded5c4e1984a..6465252ac46c2 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_data_logger/mpconfigboard.mk +++ b/ports/espressif/boards/smartbeedesigns_bee_data_logger/mpconfigboard.mk @@ -9,10 +9,8 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DS3231 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/smartbeedesigns_bee_data_logger/sdkconfig b/ports/espressif/boards/smartbeedesigns_bee_data_logger/sdkconfig index deb1b88d7cac4..e962866216039 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_data_logger/sdkconfig +++ b/ports/espressif/boards/smartbeedesigns_bee_data_logger/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="smartbeedesigns_bee_data_logger" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/smartbeedesigns_bee_motion_s3/mpconfigboard.mk b/ports/espressif/boards/smartbeedesigns_bee_motion_s3/mpconfigboard.mk index 72ad30af2e0c4..5bfa7340d5687 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_motion_s3/mpconfigboard.mk +++ b/ports/espressif/boards/smartbeedesigns_bee_motion_s3/mpconfigboard.mk @@ -9,6 +9,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/smartbeedesigns_bee_motion_s3/sdkconfig b/ports/espressif/boards/smartbeedesigns_bee_motion_s3/sdkconfig index fe95b60d4c81f..e962866216039 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_motion_s3/sdkconfig +++ b/ports/espressif/boards/smartbeedesigns_bee_motion_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="smartbeedesigns_bee_motion_s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/smartbeedesigns_bee_s3/mpconfigboard.mk b/ports/espressif/boards/smartbeedesigns_bee_s3/mpconfigboard.mk index 095924385b7a7..fc11e4bd21c20 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_s3/mpconfigboard.mk +++ b/ports/espressif/boards/smartbeedesigns_bee_s3/mpconfigboard.mk @@ -9,6 +9,4 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 8MB - FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/smartbeedesigns_bee_s3/sdkconfig b/ports/espressif/boards/smartbeedesigns_bee_s3/sdkconfig index 2c7a057567fa8..e962866216039 100644 --- a/ports/espressif/boards/smartbeedesigns_bee_s3/sdkconfig +++ b/ports/espressif/boards/smartbeedesigns_bee_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="smartbeedesigns_bee_s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/board.c b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.h b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.h new file mode 100644 index 0000000000000..d6a8b734f6224 --- /dev/null +++ b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "ESP32-P4 Stamp XL" +#define MICROPY_HW_MCU_NAME "ESP32P4" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO38) +#define DEFAULT_UART_BUS_TX (&pin_GPIO37) + +#define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX +#define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.mk b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.mk new file mode 100644 index 0000000000000..ff633cbae2a9e --- /dev/null +++ b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x1209 +USB_PID = 0x0001 +USB_PRODUCT = "ESP32-P4 Stamp XL" +USB_MANUFACTURER = "Solder Party" + +IDF_TARGET = esp32p4 + +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 32MB +CIRCUITPY_ESP_PSRAM_MODE = hpi +CIRCUITPY_ESP_PSRAM_FREQ = 200m diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/pins.c b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/pins.c new file mode 100644 index 0000000000000..03f2d0dd2a3b1 --- /dev/null +++ b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/pins.c @@ -0,0 +1,49 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_IO25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_IO26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_IO27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_IO28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_IO29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_IO30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_IO31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_IO32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO49), MP_ROM_PTR(&pin_GPIO49) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig b/ports/espressif/boards/solderparty_esp32p4_stamp_xl/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/board.c b/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/board.c index 89bcbf6b8dd7f..f4288ae45ace5 100644 --- a/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/board.c +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/board.c @@ -42,9 +42,9 @@ static bool display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO0, // DC - &pin_GPIO2, // CS - &pin_GPIO5, // RST + MP_OBJ_FROM_PTR(&pin_GPIO0), // DC + MP_OBJ_FROM_PTR(&pin_GPIO2), // CS + MP_OBJ_FROM_PTR(&pin_GPIO5), // RST 10000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/sdkconfig b/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/sdkconfig index f3f2d53d3b869..e962866216039 100644 --- a/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/sdkconfig +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_44/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="spotpear-esp32c3-lcd-1-44" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/board.c b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/board.c new file mode 100644 index 0000000000000..30879e714045d --- /dev/null +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/board.c @@ -0,0 +1,84 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to ST7789 +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, 0 | DELAY, 0xff, // _SLPOUT and Delay 500ms + 0x3A, 1 | DELAY, 0x55, 0x0a, // _COLMOD and Delay 10ms + 0x36, 0x01, 0x08, // _MADCTL + 0x21, 0x80, 0x0A, // _INVON Hack and Delay 10ms + 0x13, 0x80, 0x0A, // _NORON and Delay 10ms + 0x29, 0 | DELAY, 0xff // _DISPON and Delay 500ms +}; + + +void board_init(void) { + + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO5, &pin_GPIO6, NULL, false); + common_hal_busio_spi_never_reset(spi); + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO2), // DC + MP_OBJ_FROM_PTR(&pin_GPIO3), // CS + MP_OBJ_FROM_PTR(&pin_GPIO10), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 280, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 20, // row start + 270, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 200 // backlight pwm frequency + ); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.h b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.h new file mode 100644 index 0000000000000..513ab48284c8a --- /dev/null +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 Neradoc +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "Spotpear ESP32C3 LCD 1.69" +#define MICROPY_HW_MCU_NAME "ESP32-C3FH4" + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO7, .sda = &pin_GPIO11}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO5, .mosi = &pin_GPIO6, .miso = &pin_GPIO4}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO21, .rx = &pin_GPIO20}} diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.mk b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.mk new file mode 100644 index 0000000000000..08f792b41360a --- /dev/null +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/mpconfigboard.mk @@ -0,0 +1,10 @@ +CIRCUITPY_CREATOR_ID = 0x18760000 +CIRCUITPY_CREATION_ID = 0x00DD0002 + +IDF_TARGET = esp32c3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/pins.c b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/pins.c new file mode 100644 index 0000000000000..666333b8ffa6a --- /dev/null +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/pins.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 CDarius +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // buttons + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO9) }, + + // buzzer + { MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO1) }, + + // SPI + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO6) }, + + // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO8) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO11) }, + + // Touch + { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_RST), MP_ROM_PTR(&pin_GPIO10) }, + + // UART (on unpopulated header) + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/sdkconfig b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/spotpear_esp32c3_lcd_1_69/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/sqfmi_watchy/board.c b/ports/espressif/boards/sqfmi_watchy/board.c index 3056dec86cc06..9cea4e9809598 100644 --- a/ports/espressif/boards/sqfmi_watchy/board.c +++ b/ports/espressif/boards/sqfmi_watchy/board.c @@ -150,9 +150,9 @@ void board_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO10, // EPD_DC Command or data - &pin_GPIO5, // EPD_CS Chip select - &pin_GPIO9, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO10), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO9), // EPD_RST Reset 2000000, // Baudrate 0, // Polarity 0 // Phase @@ -160,39 +160,33 @@ void board_init(void) { epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - (double)0.01, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 200, // width - 200, // height - 200, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 0, // rotation - 0x44, // set_column_window_command - 0x45, // set_row_window_command - 0x4E, // set_current_column_command - 0x4F, // set_current_row_command - 0x24, // write_black_ram_command - true, // black_bits_inverted - 0x26, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), - (double)1.0, // refresh_time - &pin_GPIO19, // busy_pin - true, // busy_state - (double)5.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // two_byte_sequence_length - true // address_little_endian - ); + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 0.01; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 200; + args.height = 200; + args.ram_width = 200; + args.ram_height = 296; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4E; + args.set_current_row_command = 0x4F; + args.write_black_ram_command = 0x24; + args.black_bits_inverted = true; + args.write_color_ram_command = 0x26; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO19; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } bool board_requests_safe_mode(void) { @@ -201,20 +195,16 @@ bool board_requests_safe_mode(void) { bool espressif_board_reset_pin_number(gpio_num_t pin_number) { if (pin_number == 13) { - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; } void reset_board(void) { - gpio_set_direction(13, GPIO_MODE_OUTPUT); - gpio_set_level(13, false); - + config_pin_as_output_with_level(13, false); } void board_deinit(void) { - gpio_set_direction(13, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(13, false); + config_pin_as_output_with_level(13, false); } diff --git a/ports/espressif/boards/sqfmi_watchy/mpconfigboard.mk b/ports/espressif/boards/sqfmi_watchy/mpconfigboard.mk index 520894ea70a11..b1c8c64f8ba34 100644 --- a/ports/espressif/boards/sqfmi_watchy/mpconfigboard.mk +++ b/ports/espressif/boards/sqfmi_watchy/mpconfigboard.mk @@ -1,13 +1,8 @@ CIRCUITPY_CREATOR_ID = 0x4496E3F4 CIRCUITPY_CREATION_ID = 0x00320024 - -CIRCUITPY_ESPCAMERA = 0 +IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE=dio CIRCUITPY_ESP_FLASH_FREQ=40m CIRCUITPY_ESP_FLASH_SIZE=4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -IDF_TARGET = esp32 diff --git a/ports/espressif/boards/sqfmi_watchy/sdkconfig b/ports/espressif/boards/sqfmi_watchy/sdkconfig index 0eb5e8d4cb13e..7d6572eeeee7d 100644 --- a/ports/espressif/boards/sqfmi_watchy/sdkconfig +++ b/ports/espressif/boards/sqfmi_watchy/sdkconfig @@ -1,5 +1,4 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="Watchy" # end of LWIP diff --git a/ports/espressif/boards/sunton_esp32_2424S012/board.c b/ports/espressif/boards/sunton_esp32_2424S012/board.c index c313ded863764..731694a4e1b8a 100644 --- a/ports/espressif/boards/sunton_esp32_2424S012/board.c +++ b/ports/espressif/boards/sunton_esp32_2424S012/board.c @@ -105,9 +105,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO2, // DC - &pin_GPIO10, // CS - NULL, // RST + MP_OBJ_FROM_PTR(&pin_GPIO2), // DC + MP_OBJ_FROM_PTR(&pin_GPIO10), // CS + MP_OBJ_NULL, // RST 80000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/sunton_esp32_2424S012/mpconfigboard.mk b/ports/espressif/boards/sunton_esp32_2424S012/mpconfigboard.mk index 2a84d801bc325..716a01084c118 100644 --- a/ports/espressif/boards/sunton_esp32_2424S012/mpconfigboard.mk +++ b/ports/espressif/boards/sunton_esp32_2424S012/mpconfigboard.mk @@ -7,6 +7,4 @@ CIRCUITPY_ESP_FLASH_MODE=qio CIRCUITPY_ESP_FLASH_FREQ=80m CIRCUITPY_ESP_FLASH_SIZE=4MB -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 diff --git a/ports/espressif/boards/sunton_esp32_2424S012/sdkconfig b/ports/espressif/boards/sunton_esp32_2424S012/sdkconfig index 5b7c8255a9763..e962866216039 100644 --- a/ports/espressif/boards/sunton_esp32_2424S012/sdkconfig +++ b/ports/espressif/boards/sunton_esp32_2424S012/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="sunton-esp32-2424S012" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/board.c b/ports/espressif/boards/sunton_esp32_2432S024C/board.c new file mode 100644 index 0000000000000..de7504a871532 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_2432S024C/board.c @@ -0,0 +1,112 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Olav Schettler +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "common-hal/microcontroller/Pin.h" +#include "driver/gpio.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "supervisor/shared/settings.h" + +uint8_t display_init_sequence[] = { + 0x01, 0x80, 0x80, // # Software reset then delay 0x80 (128ms) + 0xEF, 0x03, 0x03, 0x80, 0x02, + 0xCF, 0x03, 0x00, 0xC1, 0x30, + 0xED, 0x04, 0x64, 0x03, 0x12, 0x81, + 0xE8, 0x03, 0x85, 0x00, 0x78, + 0xCB, 0x05, 0x39, 0x2C, 0x00, 0x34, 0x02, + 0xF7, 0x01, 0x20, + 0xEA, 0x02, 0x00, 0x00, + 0xc0, 0x01, 0x23, // # Power control VRH[5:0] + 0xc1, 0x01, 0x10, // # Power control SAP[2:0];BT[3:0] + 0xc5, 0x02, 0x3e, 0x28, // # VCM control + 0xc7, 0x01, 0x86, // # VCM control2 + 0x36, 0x01, 0x38, // # Memory Access Control + 0x37, 0x01, 0x00, // # Vertical scroll zero + 0x3a, 0x01, 0x55, // # COLMOD: Pixel Format Set + 0xb1, 0x02, 0x00, 0x18, // # Frame Rate Control (In Normal Mode/Full Colors) + 0xb6, 0x03, 0x08, 0x82, 0x27, // # Display Function Control + 0xF2, 0x01, 0x00, // # 3Gamma Function Disable + 0x26, 0x01, 0x01, // # Gamma curve selected + 0xe0, 0x0f, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // # Set Gamma + 0xe1, 0x0f, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // # Set Gamma + 0x11, 0x80, 0x48, // # Exit Sleep then delay + 0x29, 0x80, 0x78, // # Display on then delay 0x78 (120ms) +}; + +static void display_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + mp_int_t rotation; + common_hal_busio_spi_construct(spi, &pin_GPIO14, &pin_GPIO13, &pin_GPIO12, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select + MP_OBJ_NULL, // TFT_RST Reset + 6000000, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + settings_err_t result = settings_get_int("CIRCUITPY_DISPLAY_ROTATION", &rotation); + if (result != SETTINGS_OK) { + rotation = 0; + } + + common_hal_busdisplay_busdisplay_construct(display, + bus, + 320, // Width + 240, // Height + 0, // column start + 0, // row start + rotation, // rotation + 16, // Color depth + false, // Grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO27, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000); // backlight pwm frequency +} + +void board_init(void) { + display_init(); +} + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + // Pull the speaker pin low to reduce noise on reset + if (pin_number == 26) { + // Turn on TFT + config_pin_as_output_with_level(pin_number, false); + return true; + } + return false; +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.h b/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.h new file mode 100644 index 0000000000000..501b06caa2853 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Olav Schettler +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "sunton_esp32_2432S024C" +#define MICROPY_HW_MCU_NAME "ESP32-D0WD-V3" +#define MICROPY_HW_LED_STATUS (&pin_GPIO17) // LED_BLUE + +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO33) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO32) + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN { \ + {.clock = &pin_GPIO18, .mosi = &pin_GPIO23, .miso = &pin_GPIO19}, /*SD*/ \ + {.clock = &pin_GPIO14, .mosi = &pin_GPIO13, .miso = &pin_GPIO12}, /*LCD*/ \ +} + +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.mk b/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.mk new file mode 100644 index 0000000000000..fcb3e98458e29 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_2432S024C/mpconfigboard.mk @@ -0,0 +1,8 @@ +CIRCUITPY_CREATOR_ID = 0x19991000 +CIRCUITPY_CREATION_ID = 0x00AA024C + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/pins.c b/ports/espressif/boards/sunton_esp32_2432S024C/pins.c new file mode 100644 index 0000000000000..6544017cd999c --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_2432S024C/pins.c @@ -0,0 +1,68 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Olav Schettler +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 0) +CIRCUITPY_BOARD_BUS_SINGLETON(lcd_spi, spi, 2) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Boot button + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + + // Blue LED + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO17) }, + + // RGB LED + { MP_ROM_QSTR(MP_QSTR_LED_GREEN), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_LED_RED), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_LED_BLUE), MP_ROM_PTR(&pin_GPIO17) }, + + // CDS Light sensor (Not present on all boards) + { MP_ROM_QSTR(MP_QSTR_LDR), MP_ROM_PTR(&pin_GPIO34) }, + + // Speaker pin + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO26) }, + + // User available GPIO + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, // P3 Pin 1 + { MP_ROM_QSTR(MP_QSTR_IO22), MP_ROM_PTR(&pin_GPIO22) }, // P3 Pin 2 + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, // P3 Pin 3 + + // i2c + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO32) }, + + // TF card slot + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO5) }, + + // ILI9341 display (spi) + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BCKL), MP_ROM_PTR(&pin_GPIO27) }, + + // Touch (CST820) + { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_RST), MP_ROM_PTR(&pin_GPIO25) }, + + // objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_lcd_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/sunton_esp32_2432S024C/sdkconfig b/ports/espressif/boards/sunton_esp32_2432S024C/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/sunton_esp32_2432S028/board.c b/ports/espressif/boards/sunton_esp32_2432S028/board.c index 4978e50c6f6c4..214e3b13e158c 100644 --- a/ports/espressif/boards/sunton_esp32_2432S028/board.c +++ b/ports/espressif/boards/sunton_esp32_2432S028/board.c @@ -6,13 +6,14 @@ #include "supervisor/board.h" #include "mpconfigboard.h" + +#include "common-hal/microcontroller/Pin.h" +#include "driver/gpio.h" #include "shared-bindings/board/__init__.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-module/displayio/__init__.h" #include "shared-module/displayio/mipi_constants.h" -#include "driver/gpio.h" -#include "common-hal/microcontroller/Pin.h" - +#include "supervisor/shared/settings.h" uint8_t display_init_sequence[] = { 0x01, 0x80, 0x80, // # Software reset then delay 0x80 (128ms) @@ -43,28 +44,34 @@ uint8_t display_init_sequence[] = { static void display_init(void) { fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; busio_spi_obj_t *spi = &bus->inline_bus; + mp_int_t rotation; common_hal_busio_spi_construct(spi, &pin_GPIO14, &pin_GPIO13, &pin_GPIO12, false); common_hal_busio_spi_never_reset(spi); bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO2, // TFT_DC Command or data - &pin_GPIO15, // TFT_CS Chip select - NULL, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS Chip select + MP_OBJ_NULL, // TFT_RST Reset 6000000, // Baudrate 0, // Polarity 0); // Phase busdisplay_busdisplay_obj_t *display = &allocate_display()->display; display->base.type = &busdisplay_busdisplay_type; + settings_err_t result = settings_get_int("CIRCUITPY_DISPLAY_ROTATION", &rotation); + if (result != SETTINGS_OK) { + rotation = 0; + } + common_hal_busdisplay_busdisplay_construct(display, bus, 320, // Width 240, // Height 0, // column start 0, // row start - 270, // rotation + rotation, // rotation 16, // Color depth false, // Grayscale false, // pixels in a byte share a row. Only valid for depths < 8 @@ -96,8 +103,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Pull the speaker pin low to reduce noise on reset if (pin_number == 26) { // Turn on TFT - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; diff --git a/ports/espressif/boards/sunton_esp32_2432S028/mpconfigboard.mk b/ports/espressif/boards/sunton_esp32_2432S028/mpconfigboard.mk index 444c80227ab01..d4c4fb94c71ca 100644 --- a/ports/espressif/boards/sunton_esp32_2432S028/mpconfigboard.mk +++ b/ports/espressif/boards/sunton_esp32_2432S028/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/sunton_esp32_2432S028/pins.c b/ports/espressif/boards/sunton_esp32_2432S028/pins.c index b852ab11e04c2..7791c1685eb38 100644 --- a/ports/espressif/boards/sunton_esp32_2432S028/pins.c +++ b/ports/espressif/boards/sunton_esp32_2432S028/pins.c @@ -45,7 +45,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO5) }, - // ILI9341 dsplay (spi) + // ILI9341 display (spi) { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO12) }, { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO14) }, diff --git a/ports/espressif/boards/sunton_esp32_2432S032C/board.c b/ports/espressif/boards/sunton_esp32_2432S032C/board.c index 62c10b30375f1..48e206040d819 100644 --- a/ports/espressif/boards/sunton_esp32_2432S032C/board.c +++ b/ports/espressif/boards/sunton_esp32_2432S032C/board.c @@ -43,9 +43,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO2, // TFT_DC - &pin_GPIO15, // TFT_CS - NULL, // TFT_RST + MP_OBJ_FROM_PTR(&pin_GPIO2), // TFT_DC + MP_OBJ_FROM_PTR(&pin_GPIO15), // TFT_CS + MP_OBJ_NULL, // TFT_RST 26600000, // Baudrate 0, // Polarity 0 // Phase @@ -92,8 +92,7 @@ bool espressif_board_reset_pin_number(gpio_num_t pin_number) { // Pull the speaker pin low to reduce noise on reset if (pin_number == 26) { // Turn on audio - gpio_set_direction(pin_number, GPIO_MODE_DEF_OUTPUT); - gpio_set_level(pin_number, false); + config_pin_as_output_with_level(pin_number, false); return true; } return false; diff --git a/ports/espressif/boards/sunton_esp32_2432S032C/mpconfigboard.mk b/ports/espressif/boards/sunton_esp32_2432S032C/mpconfigboard.mk index 15e3b102c9bf3..f36374a456aa9 100644 --- a/ports/espressif/boards/sunton_esp32_2432S032C/mpconfigboard.mk +++ b/ports/espressif/boards/sunton_esp32_2432S032C/mpconfigboard.mk @@ -6,5 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 40m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/sunton_esp32_8048S050/board.c b/ports/espressif/boards/sunton_esp32_8048S050/board.c new file mode 100644 index 0000000000000..a6f573a86e79b --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_8048S050/board.c @@ -0,0 +1,89 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/dotclockframebuffer/DotClockFramebuffer.h" +#include "shared-bindings/dotclockframebuffer/__init__.h" +#include "shared-bindings/framebufferio/FramebufferDisplay.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/settings.h" + +static const mcu_pin_obj_t *blue_pins[] = { + &pin_GPIO8, + &pin_GPIO3, + &pin_GPIO46, + &pin_GPIO9, + &pin_GPIO1 +}; +static const mcu_pin_obj_t *green_pins[] = { + &pin_GPIO5, + &pin_GPIO6, + &pin_GPIO7, + &pin_GPIO15, + &pin_GPIO16, + &pin_GPIO4 +}; +static const mcu_pin_obj_t *red_pins[] = { + &pin_GPIO45, + &pin_GPIO48, + &pin_GPIO47, + &pin_GPIO21, + &pin_GPIO14 +}; + +static void display_init(void) { + mp_int_t frequency; + + // Turn on backlight + gpio_set_direction(2, GPIO_MODE_DEF_OUTPUT); + gpio_set_level(2, true); + common_hal_never_reset_pin(&pin_GPIO2); + + dotclockframebuffer_framebuffer_obj_t *framebuffer = &allocate_display_bus_or_raise()->dotclock; + framebuffer->base.type = &dotclockframebuffer_framebuffer_type; + settings_err_t result = settings_get_int("CIRCUITPY_DISPLAY_FREQUENCY", &frequency); + if (result != SETTINGS_OK) { + frequency = 12500000; + } + + common_hal_dotclockframebuffer_framebuffer_construct( + framebuffer, + &pin_GPIO40, // de + &pin_GPIO41, // vsync + &pin_GPIO39, // hsync + &pin_GPIO42, // pclk + red_pins, MP_ARRAY_SIZE(red_pins), + green_pins, MP_ARRAY_SIZE(green_pins), + blue_pins, MP_ARRAY_SIZE(blue_pins), + frequency, // Frequency + 800, // width + 480, // height + 4, 8, 8, true, // horiz: pulse, back porch, front porch, idle low + 4, 8, 8, true, // vert: pulse, back porch, front porch, idle low + false, // DE idle high + false, // pclk active high + false, // pclk idle high + 0 // overscan left + ); + + framebufferio_framebufferdisplay_obj_t *display = &allocate_display_or_raise()->framebuffer_display; + display->base.type = &framebufferio_framebufferdisplay_type; + common_hal_framebufferio_framebufferdisplay_construct( + display, + framebuffer, + 0, // rotation + true // auto-refresh + ); +} + +void board_init(void) { + display_init(); +} +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.h b/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.h new file mode 100644 index 0000000000000..e3370bd6f0226 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Sunton-ESP32-8048S050" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO19) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO12) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO13) + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO43) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO44) diff --git a/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.mk b/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.mk new file mode 100644 index 0000000000000..7dedcd85ea26e --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_8048S050/mpconfigboard.mk @@ -0,0 +1,19 @@ +CIRCUITPY_CREATOR_ID = 0x19991000 +CIRCUITPY_CREATION_ID = 0x00AA0050 + +# This board doesn't have USB by default, it +# instead uses a CH340C USB-to-Serial chip +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_DOTCLOCKFRAMEBUFFER = 1 diff --git a/ports/espressif/boards/sunton_esp32_8048S050/pins.c b/ports/espressif/boards/sunton_esp32_8048S050/pins.c new file mode 100644 index 0000000000000..fa5a0fdfa37d4 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_8048S050/pins.c @@ -0,0 +1,136 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_obj_tuple_t tft_r_pins = { + {&mp_type_tuple}, + 5, + { + MP_ROM_PTR(&pin_GPIO45), + MP_ROM_PTR(&pin_GPIO48), + MP_ROM_PTR(&pin_GPIO47), + MP_ROM_PTR(&pin_GPIO21), + MP_ROM_PTR(&pin_GPIO14), + } +}; + +static const mp_rom_obj_tuple_t tft_g_pins = { + {&mp_type_tuple}, + 6, + { + MP_ROM_PTR(&pin_GPIO5), + MP_ROM_PTR(&pin_GPIO6), + MP_ROM_PTR(&pin_GPIO7), + MP_ROM_PTR(&pin_GPIO15), + MP_ROM_PTR(&pin_GPIO16), + MP_ROM_PTR(&pin_GPIO4), + } +}; + +static const mp_rom_obj_tuple_t tft_b_pins = { + {&mp_type_tuple}, + 5, + { + MP_ROM_PTR(&pin_GPIO8), + MP_ROM_PTR(&pin_GPIO3), + MP_ROM_PTR(&pin_GPIO46), + MP_ROM_PTR(&pin_GPIO9), + MP_ROM_PTR(&pin_GPIO1), + } +}; + +static const mp_rom_map_elem_t tft_pins_table[] = { + { MP_ROM_QSTR(MP_QSTR_de), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_vsync), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_hsync), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_dclk), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_red), MP_ROM_PTR(&tft_r_pins) }, + { MP_ROM_QSTR(MP_QSTR_green), MP_ROM_PTR(&tft_g_pins) }, + { MP_ROM_QSTR(MP_QSTR_blue), MP_ROM_PTR(&tft_b_pins) }, +}; +MP_DEFINE_CONST_DICT(tft_pins_dict, tft_pins_table); + +static const mp_rom_map_elem_t timings_table[] = { + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_INT(12500000) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_INT(800) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_INT(480) }, + { MP_ROM_QSTR(MP_QSTR_hsync_pulse_width), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_hsync_back_porch), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_hsync_front_porch), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_hsync_idle_low), MP_ROM_TRUE }, + { MP_ROM_QSTR(MP_QSTR_vsync_pulse_width), MP_ROM_INT(4) }, + { MP_ROM_QSTR(MP_QSTR_vsync_back_porch), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_vsync_front_porch), MP_ROM_INT(8) }, + { MP_ROM_QSTR(MP_QSTR_vsync_idle_low), MP_ROM_TRUE }, + { MP_ROM_QSTR(MP_QSTR_de_idle_high), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_pclk_active_high), MP_ROM_FALSE }, + { MP_ROM_QSTR(MP_QSTR_pclk_idle_high), MP_ROM_FALSE }, + +}; +MP_DEFINE_CONST_DICT(timings_dict, timings_table); + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Display constructs + { MP_ROM_QSTR(MP_QSTR_TFT_PINS), MP_ROM_PTR(&tft_pins_dict) }, + { MP_ROM_QSTR(MP_QSTR_TFT_TIMINGS), MP_ROM_PTR(&timings_dict) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO2) }, + + // User buttons + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + + // User accessible GPIO + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, // P2, External SPI plug + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, // P3 has 19&20 for I2C bus, plus 17&18 + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, // P4 & P5 are both 17,18,3.3v,G + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + + // UART pins + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO20) }, + + // SPI + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO13) }, + + // i2s amplifier + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DATA), MP_ROM_PTR(&pin_GPIO17) }, + + // Touch (GT911 I2C, XPT2046 SPI) + // There are two versions of this tablet, one with capacitive touch + // one with resistive. They use their respective bus as defined, + // with GPIO38 being reset on capacitive and cs on resistive. + { MP_ROM_QSTR(MP_QSTR_TOUCH_RESET), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_CS), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_GPIO18) }, + + // SD Slot (SPI) + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO10) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/sunton_esp32_8048S050/sdkconfig b/ports/espressif/boards/sunton_esp32_8048S050/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/sunton_esp32_8048S050/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/sunton_esp32_8048S070/sdkconfig b/ports/espressif/boards/sunton_esp32_8048S070/sdkconfig index 61e94a741ffd1..e962866216039 100644 --- a/ports/espressif/boards/sunton_esp32_8048S070/sdkconfig +++ b/ports/espressif/boards/sunton_esp32_8048S070/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="sunton-esp32-8048S070" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/targett_module_clip_wroom/mpconfigboard.mk b/ports/espressif/boards/targett_module_clip_wroom/mpconfigboard.mk index 2e0e84456cbd9..f273085b19234 100644 --- a/ports/espressif/boards/targett_module_clip_wroom/mpconfigboard.mk +++ b/ports/espressif/boards/targett_module_clip_wroom/mpconfigboard.mk @@ -8,5 +8,3 @@ IDF_TARGET = esp32s2 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/thingpulse_pendrive_s3/mpconfigboard.mk b/ports/espressif/boards/thingpulse_pendrive_s3/mpconfigboard.mk index 66f5a4aba7069..cb273b7a45d86 100644 --- a/ports/espressif/boards/thingpulse_pendrive_s3/mpconfigboard.mk +++ b/ports/espressif/boards/thingpulse_pendrive_s3/mpconfigboard.mk @@ -13,7 +13,8 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m +# No pins. CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_DISPLAYIO = 1 +CIRCUITPY_PARALLELDISPLAYBUS = 0 FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/thingpulse_pendrive_s3/sdkconfig b/ports/espressif/boards/thingpulse_pendrive_s3/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/thingpulse_pendrive_s3/sdkconfig +++ b/ports/espressif/boards/thingpulse_pendrive_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/ttgo_t8_v1_7/mpconfigboard.mk b/ports/espressif/boards/ttgo_t8_v1_7/mpconfigboard.mk index 6556b6881f315..aa9f2e1c1b391 100644 --- a/ports/espressif/boards/ttgo_t8_v1_7/mpconfigboard.mk +++ b/ports/espressif/boards/ttgo_t8_v1_7/mpconfigboard.mk @@ -7,4 +7,6 @@ CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB -CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_ESP_PSRAM_SIZE = 4MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/ttgo_t8_v1_7/pins.c b/ports/espressif/boards/ttgo_t8_v1_7/pins.c index 97175b2a4e5bc..9bb3d0a617a32 100644 --- a/ports/espressif/boards/ttgo_t8_v1_7/pins.c +++ b/ports/espressif/boards/ttgo_t8_v1_7/pins.c @@ -1,6 +1,6 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS // External pins are in silkscreen order, from top to bottom, left side, then right side diff --git a/ports/espressif/boards/unexpectedmaker_bling/sdkconfig b/ports/espressif/boards/unexpectedmaker_bling/sdkconfig index 8e693ad1cb4d2..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_bling/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_bling/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMBling" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_blizzard_s3/sdkconfig b/ports/espressif/boards/unexpectedmaker_blizzard_s3/sdkconfig index eea8c00b59b9d..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_blizzard_s3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_blizzard_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMBlizzardS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_edges3d/board.c b/ports/espressif/boards/unexpectedmaker_edges3d/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/unexpectedmaker_edges3d/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.h b/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.h new file mode 100644 index 0000000000000..27be4ffd1ceb7 --- /dev/null +++ b/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit +// Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "EDGES3D" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO4) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO7) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO5) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.mk b/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.mk new file mode 100644 index 0000000000000..01e2edc4164ac --- /dev/null +++ b/ports/espressif/boards/unexpectedmaker_edges3d/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x303A +USB_PID = 0x82DD +USB_PRODUCT = "EDGES3D" +USB_MANUFACTURER = "UnexpectedMaker" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_SIZE = 8MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +CIRCUITPY_STAGE = 1 diff --git a/ports/espressif/boards/unexpectedmaker_edges3d/pins.c b/ports/espressif/boards/unexpectedmaker_edges3d/pins.c new file mode 100644 index 0000000000000..b753ea207b179 --- /dev/null +++ b/ports/espressif/boards/unexpectedmaker_edges3d/pins.c @@ -0,0 +1,126 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit +// Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + {MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0)}, + {MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0)}, + + {MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1)}, + {MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO1)}, + {MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1)}, + + {MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2)}, + {MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO2)}, + {MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2)}, + + {MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3)}, + {MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO3)}, + {MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3)}, + + {MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4)}, + {MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO4)}, + {MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4)}, + + {MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5)}, + {MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO5)}, + {MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5)}, + + {MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6)}, + {MP_ROM_QSTR(MP_QSTR_FG_INT), MP_ROM_PTR(&pin_GPIO6)}, + + {MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7)}, + {MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO7)}, + {MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7)}, + + {MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8)}, + {MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8)}, + {MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO8)}, + {MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8)}, + + {MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9)}, + {MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9)}, + {MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO9)}, + {MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9)}, + + {MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10)}, + {MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO10)}, + {MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10)}, + + {MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11)}, + {MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO11)}, + {MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11)}, + + {MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12)}, + {MP_ROM_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_GPIO12)}, + {MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12)}, + + {MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13)}, + {MP_ROM_QSTR(MP_QSTR_A12), MP_ROM_PTR(&pin_GPIO13)}, + {MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13)}, + + {MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14)}, + {MP_ROM_QSTR(MP_QSTR_A13), MP_ROM_PTR(&pin_GPIO14)}, + {MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14)}, + + {MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15)}, + {MP_ROM_QSTR(MP_QSTR_A14), MP_ROM_PTR(&pin_GPIO15)}, + {MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15)}, + + {MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16)}, + {MP_ROM_QSTR(MP_QSTR_A15), MP_ROM_PTR(&pin_GPIO16)}, + {MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16)}, + + {MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17)}, + {MP_ROM_QSTR(MP_QSTR_A16), MP_ROM_PTR(&pin_GPIO17)}, + {MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17)}, + + {MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18)}, + {MP_ROM_QSTR(MP_QSTR_A17), MP_ROM_PTR(&pin_GPIO18)}, + {MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18)}, + + {MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21)}, + {MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21)}, + + {MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39)}, + {MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39)}, + {MP_ROM_QSTR(MP_QSTR_MTCK), MP_ROM_PTR(&pin_GPIO39)}, + + {MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40)}, + {MP_ROM_QSTR(MP_QSTR_D40), MP_ROM_PTR(&pin_GPIO40)}, + {MP_ROM_QSTR(MP_QSTR_MTDO), MP_ROM_PTR(&pin_GPIO40)}, + + {MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41)}, + {MP_ROM_QSTR(MP_QSTR_D41), MP_ROM_PTR(&pin_GPIO41)}, + {MP_ROM_QSTR(MP_QSTR_MTDI), MP_ROM_PTR(&pin_GPIO41)}, + + {MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42)}, + {MP_ROM_QSTR(MP_QSTR_D42), MP_ROM_PTR(&pin_GPIO42)}, + {MP_ROM_QSTR(MP_QSTR_MTMS), MP_ROM_PTR(&pin_GPIO42)}, + + {MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43)}, + {MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43)}, + {MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43)}, + + {MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44)}, + {MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44)}, + {MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44)}, + + {MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45)}, + {MP_ROM_QSTR(MP_QSTR_D45), MP_ROM_PTR(&pin_GPIO45)}, + + {MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46)}, + {MP_ROM_QSTR(MP_QSTR_D46), MP_ROM_PTR(&pin_GPIO46)}, + + {MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj)}, + {MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj)}, + {MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/unexpectedmaker_edges3d/sdkconfig b/ports/espressif/boards/unexpectedmaker_edges3d/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/unexpectedmaker_edges3d/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/unexpectedmaker_feathers2/sdkconfig b/ports/espressif/boards/unexpectedmaker_feathers2/sdkconfig index a1e5e03b76922..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers2/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_feathers2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_feathers2_neo/sdkconfig b/ports/espressif/boards/unexpectedmaker_feathers2_neo/sdkconfig index cc781c9a3dda4..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers2_neo/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_feathers2_neo/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS2Neo" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_feathers2_prerelease/sdkconfig b/ports/espressif/boards/unexpectedmaker_feathers2_prerelease/sdkconfig index a1e5e03b76922..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers2_prerelease/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_feathers2_prerelease/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_feathers3/sdkconfig b/ports/espressif/boards/unexpectedmaker_feathers3/sdkconfig index 3ccd3175c69d6..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_feathers3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_feathers3_neo/sdkconfig b/ports/espressif/boards/unexpectedmaker_feathers3_neo/sdkconfig index df8f15b54391c..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_feathers3_neo/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_feathers3_neo/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS3 Neo" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_nanos3/sdkconfig b/ports/espressif/boards/unexpectedmaker_nanos3/sdkconfig index 815f002d38295..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_nanos3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_nanos3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMNanoS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_omgs3/sdkconfig b/ports/espressif/boards/unexpectedmaker_omgs3/sdkconfig index 9de28080ff385..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_omgs3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_omgs3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMOMGS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_pros3/sdkconfig b/ports/espressif/boards/unexpectedmaker_pros3/sdkconfig index 21b91a2199af6..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_pros3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_pros3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMProS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_rgbtouch_mini/sdkconfig b/ports/espressif/boards/unexpectedmaker_rgbtouch_mini/sdkconfig index 8eae792a58381..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_rgbtouch_mini/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_rgbtouch_mini/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMRGBT" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_tinyc6/sdkconfig b/ports/espressif/boards/unexpectedmaker_tinyc6/sdkconfig index c989bb78dc71a..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_tinyc6/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_tinyc6/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyC6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_tinypico/mpconfigboard.mk b/ports/espressif/boards/unexpectedmaker_tinypico/mpconfigboard.mk index 4086abba11ea2..80acff0ca4905 100644 --- a/ports/espressif/boards/unexpectedmaker_tinypico/mpconfigboard.mk +++ b/ports/espressif/boards/unexpectedmaker_tinypico/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/unexpectedmaker_tinypico_nano/mpconfigboard.mk b/ports/espressif/boards/unexpectedmaker_tinypico_nano/mpconfigboard.mk index 550e0d4a76c32..c919aff8aef23 100644 --- a/ports/espressif/boards/unexpectedmaker_tinypico_nano/mpconfigboard.mk +++ b/ports/espressif/boards/unexpectedmaker_tinypico_nano/mpconfigboard.mk @@ -10,5 +10,3 @@ CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_PSRAM_SIZE = 8MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/unexpectedmaker_tinys2/sdkconfig b/ports/espressif/boards/unexpectedmaker_tinys2/sdkconfig index 647e33d8f5a9c..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_tinys2/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_tinys2/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS2" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_tinys3/sdkconfig b/ports/espressif/boards/unexpectedmaker_tinys3/sdkconfig index d08f76926e0de..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_tinys3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_tinys3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/unexpectedmaker_tinywatch_s3/sdkconfig b/ports/espressif/boards/unexpectedmaker_tinywatch_s3/sdkconfig index 12b5605f4e5d9..e962866216039 100644 --- a/ports/espressif/boards/unexpectedmaker_tinywatch_s3/sdkconfig +++ b/ports/espressif/boards/unexpectedmaker_tinywatch_s3/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyWATCHS3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/vidi_x/board.c b/ports/espressif/boards/vidi_x/board.c index e53dfd82ad9de..7ba7094b91778 100644 --- a/ports/espressif/boards/vidi_x/board.c +++ b/ports/espressif/boards/vidi_x/board.c @@ -51,9 +51,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO21, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - NULL, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO21), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_NULL, // TFT_RST Reset 40000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/espressif/boards/vidi_x/mpconfigboard.h b/ports/espressif/boards/vidi_x/mpconfigboard.h index e8478bedb7ac0..8ce6239e5f3d7 100644 --- a/ports/espressif/boards/vidi_x/mpconfigboard.h +++ b/ports/espressif/boards/vidi_x/mpconfigboard.h @@ -6,7 +6,7 @@ #pragma once -#define MICROPY_HW_BOARD_NAME "VIDI X" +#define MICROPY_HW_BOARD_NAME "VIDI X V1.1" #define MICROPY_HW_MCU_NAME "ESP32" #define MICROPY_HW_LED_STATUS (&pin_GPIO2) diff --git a/ports/espressif/boards/vidi_x/sdkconfig b/ports/espressif/boards/vidi_x/sdkconfig index bdd999b4fc91c..e962866216039 100644 --- a/ports/espressif/boards/vidi_x/sdkconfig +++ b/ports/espressif/boards/vidi_x/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="vidi-x" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/board.c b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/board.c new file mode 100644 index 0000000000000..e56c096e40371 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/board.c @@ -0,0 +1,99 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Benjamin Shockley +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + +// Driver is ST7789V3 +// Display Panel is LBS147TC-IF15 +// 172 X 320 Pixels RGB 18-bit + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 120, + 0x11, 0 | DELAY, 120, + 0x13, 0, + 0x36, 1, 0x00, + 0x3A, 1 | DELAY, 0x05, 10, + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + 0xB7, 1, 0x35, + 0xBB, 1, 0x20, + 0xC0, 1, 0x2C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x13, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + 0xE0, 14, 0xF0, 0x00, 0x04, 0x04, 0x04, 0x05, 0x29, 0x33, 0x3E, 0x38, 0x12, 0x12, 0x28, 0x30, + 0xE1, 14, 0xF0, 0x07, 0x0A, 0x0D, 0x0B, 0x07, 0x28, 0x33, 0x3E, 0x36, 0x14, 0x14, 0x29, 0x32, + 0x21, 0, + 0x29, 0 | DELAY, 255, +}; + +static void display_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO15), // DC + MP_OBJ_FROM_PTR(&pin_GPIO14), // CS + MP_OBJ_FROM_PTR(&pin_GPIO21), // RST + 80000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 172, // width (after rotation) + 320, // height (after rotation) + 34, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO22, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Display + display_init(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h new file mode 100644 index 0000000000000..322acaf84b8b3 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.h @@ -0,0 +1,33 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Benjamin Shockley +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-C6 LCD 1.47" +#define MICROPY_HW_MCU_NAME "ESP32-C6FH4" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO8) +#define MICROPY_HW_NEOPIXEL_ORDER_GRB (1) + +// I2C +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO0, .sda = &pin_GPIO1}} + +// SPI +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO7, .mosi = &pin_GPIO6, .miso = &pin_GPIO5}} + +// TXD0 and RXD0 +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO16, .rx = &pin_GPIO17}} + +// For entering safe mode, use BOOT button +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) + +// Explanation of how a user got into safe mode +#define BOARD_USER_SAFE_MODE_ACTION MP_ERROR_TEXT("You pressed the BOOT button at start up.") diff --git a/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.mk new file mode 100644 index 0000000000000..e838f8ad2e5e8 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/mpconfigboard.mk @@ -0,0 +1,11 @@ +CIRCUITPY_CREATOR_ID = 0x1BBB0000 +CIRCUITPY_CREATION_ID = 0x00C60002 + +IDF_TARGET = esp32c6 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +# Board was originally defined with a 2MB firmware, almost 2MB user filesystem. Leave it that way. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT = 1 diff --git a/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/pins.c b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/pins.c new file mode 100644 index 0000000000000..9b9b91d8f64d7 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/pins.c @@ -0,0 +1,70 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Benjamin Shockley +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_IO23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)} +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/sdkconfig b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_c6_lcd_1_47/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/board.c b/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/board.c index cb6fb3103382e..0bf710ec34c69 100644 --- a/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/board.c +++ b/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/board.c @@ -61,9 +61,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO18, // DC - &pin_GPIO9, // CS - &pin_GPIO21, // RST + MP_OBJ_FROM_PTR(&pin_GPIO18), // DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // CS + MP_OBJ_FROM_PTR(&pin_GPIO21), // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/sdkconfig b/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/sdkconfig index 7c86f9f8e37a3..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s2_pico_lcd/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="waveshare" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c new file mode 100644 index 0000000000000..7b57f48bcdbdd --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c @@ -0,0 +1,106 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include "shared-bindings/qspibus/QSPIBus.h" +#include "shared-bindings/busdisplay/BusDisplay.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +// RM690B0 AMOLED initialization sequence. +// Format: command byte, length | 0x80 (if delay), data bytes..., [delay ms] +// Based on vendor recommendations, tested with Waveshare 2.41" AMOLED panel. +// Non-const to match upstream common_hal_busdisplay_busdisplay_construct signature. +static uint8_t display_init_sequence[] = { + // Page select and configuration + 0xFE, 0x01, 0x20, // Enter user command mode + 0x26, 0x01, 0x0A, // Bias setting + 0x24, 0x01, 0x80, // Source output control + 0xFE, 0x01, 0x13, // Page 13 + 0xEB, 0x01, 0x0E, // Vendor command + 0xFE, 0x01, 0x00, // Return to page 0 + // Display configuration + 0x3A, 0x01, 0x55, // COLMOD: 16-bit RGB565 + 0xC2, 0x81, 0x00, 0x0A, // Vendor command + 10ms delay + 0x35, 0x00, // Tearing effect line on (no data) + 0x51, 0x81, 0x00, 0x0A, // Brightness control + 10ms delay + // Power on + 0x11, 0x80, 0x50, // Sleep out + 80ms delay + // Display window (MV=1: CASET→rows, RASET→cols) + 0x2A, 0x04, 0x00, 0x10, 0x01, 0xD1, // CASET: 16..465 (450px + 16 offset) + 0x2B, 0x04, 0x00, 0x00, 0x02, 0x57, // RASET: 0..599 (600px) + // Enable display + 0x29, 0x80, 0x0A, // Display on + 10ms delay + // Memory access: MV=1, ML=1 for landscape + 0x36, 0x81, 0x30, 0x0A, // MADCTL + 10ms delay + // Brightness + 0x51, 0x01, 0xFF, // Set brightness to maximum +}; + +void board_init(void) { + // 0. Enable display power before any bus/display init. + digitalio_digitalinout_obj_t power_pin; + power_pin.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&power_pin, CIRCUITPY_LCD_POWER); + common_hal_digitalio_digitalinout_set_value(&power_pin, true); + common_hal_digitalio_digitalinout_never_reset(&power_pin); + // Allow power rail to settle before reset/init. + mp_hal_delay_ms(200); + + // 1. Allocate and construct QSPI bus + qspibus_qspibus_obj_t *bus = &allocate_display_bus_or_raise()->qspi_bus; + bus->base.type = &qspibus_qspibus_type; + + common_hal_qspibus_qspibus_construct(bus, + CIRCUITPY_LCD_CLK, // clock + CIRCUITPY_LCD_D0, // data0 + CIRCUITPY_LCD_D1, // data1 + CIRCUITPY_LCD_D2, // data2 + CIRCUITPY_LCD_D3, // data3 + CIRCUITPY_LCD_CS, // cs + NULL, // dcx (not used, QSPI uses encoded commands) + CIRCUITPY_LCD_RESET, // reset + 40000000); // 40 MHz + + // 2. Allocate and construct BusDisplay with RM690B0 init sequence. + // Physical panel: 450 cols × 600 rows. + // MADCTL MV=1 swaps row/col → logical 600×450 landscape. + busdisplay_busdisplay_obj_t *display = &allocate_display_or_raise()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct(display, + bus, + 600, // width (logical, after MV=1 swap) + 450, // height (logical, after MV=1 swap) + 0, // colstart + 16, // rowstart (physical row offset) + 0, // rotation + 16, // color_depth (RGB565) + false, // grayscale + false, // pixels_in_byte_share_row + 1, // bytes_per_cell + false, // reverse_pixels_in_byte + false, // reverse_bytes_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set_column_command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set_row_command + MIPI_COMMAND_WRITE_MEMORY_START, // write_ram_command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight_pin (AMOLED — no backlight GPIO) + 0x51, // brightness_command + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000); // backlight_pwm_frequency +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h new file mode 100644 index 0000000000000..9ac461ee61dde --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Touch-AMOLED-2.41" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +// I2C bus - Disabled on boot to avoid conflicts. User must manually initialize I2C. +#define CIRCUITPY_BOARD_I2C (0) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}} + +// Display refresh buffer: 8192 bytes = 2048 uint32_t words on stack. +// ESP32-S3 main task stack is 24KB; verified safe with this board. +#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (8192) + +// AMOLED Display (displayio + qspibus path) - initialized in board_init() +#define CIRCUITPY_BOARD_DISPLAY (1) +#define CIRCUITPY_LCD_CS (&pin_GPIO9) +#define CIRCUITPY_LCD_CLK (&pin_GPIO10) +#define CIRCUITPY_LCD_D0 (&pin_GPIO11) +#define CIRCUITPY_LCD_D1 (&pin_GPIO12) +#define CIRCUITPY_LCD_D2 (&pin_GPIO13) +#define CIRCUITPY_LCD_D3 (&pin_GPIO14) +#define CIRCUITPY_LCD_RESET (&pin_GPIO21) +#define CIRCUITPY_LCD_POWER (&pin_GPIO16) + +// No default SPI bus — SD card uses SDIO, display uses QSPI. +#define CIRCUITPY_BOARD_SPI (0) + +// Default UART bus +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk new file mode 100644 index 0000000000000..f901246804cdf --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk @@ -0,0 +1,35 @@ +# This file is part of the CircuitPython project: https://circuitpython.org +# SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +# SPDX-License-Identifier: MIT + +USB_VID = 0x303A +USB_PID = 0x8278 +USB_MANUFACTURER = "Waveshare" +USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41" + +IDF_TARGET = esp32s3 + +# Flash configuration - 16MB QSPI Flash +CIRCUITPY_ESP_FLASH_SIZE = 16MB +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m + +# PSRAM configuration - 8MB Octal PSRAM +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +OPTIMIZATION_FLAGS = -Os + +# QSPI bus for RM690B0 AMOLED display +CIRCUITPY_QSPIBUS = 1 +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +# No camera on this board +CIRCUITPY_ESPCAMERA = 0 + +# Capacitive touch not available; board uses I2C touch controller +CIRCUITPY_TOUCHIO = 0 + +# SD card via SDMMC interface +CIRCUITPY_SDIOIO = 1 diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c new file mode 100644 index 0000000000000..8804cace06dcf --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c @@ -0,0 +1,109 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // ================================================================= + // ONBOARD PERIPHERALS - Functional Names + // ================================================================= + + // Boot/Control/Battery/Display Power + // NOTE: GPIO16 is shared between battery control circuitry and LCD power + // (see CIRCUITPY_QSPIBUS_PANEL_POWER_PIN in mpconfigboard.h). + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_LCD_POWER), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) }, + + // I2C Bus (shared by Touch, RTC, IMU, IO Expander) + // NOTE: board.I2C auto-initialization is disabled (CIRCUITPY_BOARD_I2C=0) + // to avoid boot conflicts. Users must manually create I2C bus: + // i2c = busio.I2C(board.SCL, board.SDA) + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // Touch Panel (FT6336U on I2C) + // NOTE: TP_INT is routed through the TCA9554 IO expander (EXIO2), + // not a direct ESP32-S3 GPIO — no TOUCH_INT alias is possible here. + { MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_TP_RESET), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_SCL), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_RST), MP_ROM_PTR(&pin_GPIO3) }, + + // RTC (PCF85063 on I2C) + { MP_ROM_QSTR(MP_QSTR_RTC_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_RTC_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // IMU (QMI8658 on I2C) + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // I/O Expander (TCA9554 on I2C) + { MP_ROM_QSTR(MP_QSTR_EXIO_SDA), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_EXIO_SCL), MP_ROM_PTR(&pin_GPIO48) }, + + // USB + { MP_ROM_QSTR(MP_QSTR_USB_D_N), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_USB_D_P), MP_ROM_PTR(&pin_GPIO20) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // QSPI Display (RM690B0) - canonical generic LCD aliases. + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) }, + + // Display Aliases + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D1), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) }, + + // SD Card (SDIO / SDMMC) + { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_D3), MP_ROM_PTR(&pin_GPIO2) }, + + // ================================================================= + // GENERAL PURPOSE I/O (IOxx - Espressif Convention) + // ================================================================= + // Only pins NOT dedicated to onboard peripherals are exposed here. + // Use functional names above for dedicated pins (e.g., SDA, SD_CS). + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT button (available when not holding BOOT) + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // TP_RESET (available if touch not used) + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // Available + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Available + + // Board display (initialized in board_init) + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig new file mode 100644 index 0000000000000..fa60cc4c2378e --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig @@ -0,0 +1,3 @@ +# +# Configuration file for the Waveshare ESP32-S3 Touch AMOLED 2.41 +# diff --git a/ports/espressif/boards/waveshare_esp32_s3_eth/board.c b/ports/espressif/boards/waveshare_esp32_s3_eth/board.c new file mode 100644 index 0000000000000..a3a9eec047145 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_eth/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.h new file mode 100644 index 0000000000000..037fa18c0be5f --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-ETH" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO21) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.mk new file mode 100644 index 0000000000000..f1f5128d26f1b --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_eth/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303a +USB_PID = 0x82a7 +USB_PRODUCT = "ESP32-S3-ETH" +USB_MANUFACTURER = "Waveshare Electronics" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m +CIRCUITPY_ESP_PSRAM_SIZE = 8MB diff --git a/ports/espressif/boards/waveshare_esp32_s3_eth/pins.c b/ports/espressif/boards/waveshare_esp32_s3_eth/pins.c new file mode 100644 index 0000000000000..ac2b3e3258d5d --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_eth/pins.c @@ -0,0 +1,80 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + + // SD + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + + // Ethernet + { MP_ROM_QSTR(MP_QSTR_ETH_RST), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_ETH_INT), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_ETH_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_ETH_MISO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_ETH_CLK), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_ETH_CS), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + + // USB - these pins are broken out on the header + // D_N + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + // D_P + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + + // NeoPixel + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_eth/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_eth/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_eth/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/waveshare_esp32_s3_geek/board.c b/ports/espressif/boards/waveshare_esp32_s3_geek/board.c index 71f742b51f423..0ce447532642c 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_geek/board.c +++ b/ports/espressif/boards/waveshare_esp32_s3_geek/board.c @@ -30,26 +30,17 @@ uint8_t display_init_sequence[] = { }; static void display_init(void) { - busio_spi_obj_t *spi = common_hal_board_create_spi(0); fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; - common_hal_busio_spi_construct( - spi, - &pin_GPIO12, // CLK - &pin_GPIO11, // MOSI - NULL, // MISO not connected - false); // Not half-duplex - - bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO8, // TFT_DC - &pin_GPIO10, // TFT_CS - &pin_GPIO9, // TFT_RST + MP_OBJ_FROM_PTR(&pin_GPIO8), // TFT_DC + MP_OBJ_FROM_PTR(&pin_GPIO10), // TFT_CS + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_RST 50000000, // Baudrate 0, // Polarity 0 // Phase diff --git a/ports/espressif/boards/waveshare_esp32_s3_geek/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_geek/mpconfigboard.h index 2da021447e39f..87ac391f5a0bf 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_geek/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_geek/mpconfigboard.h @@ -17,6 +17,6 @@ #define DEFAULT_I2C_BUS_SCL (&pin_GPIO17) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO16) -#define DEFAULT_SPI_BUS_SCK (&pin_GPIO36) -#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO35) -#define DEFAULT_SPI_BUS_MISO (&pin_GPIO37) +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO12, .mosi = &pin_GPIO11}, \ + {.clock = &pin_GPIO36, .mosi = &pin_GPIO35, .miso = &pin_GPIO37}} diff --git a/ports/espressif/boards/waveshare_esp32_s3_geek/pins.c b/ports/espressif/boards/waveshare_esp32_s3_geek/pins.c index 01c3baf8c9f8f..65d391ec9ea88 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_geek/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_geek/pins.c @@ -5,8 +5,10 @@ // SPDX-License-Identifier: MIT #include "shared-bindings/board/__init__.h" - #include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) + static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS @@ -64,11 +66,11 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, // SD Card - { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO36)}, - { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO35)}, - { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO37)}, - { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO34)}, - { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, // Pin 38 is for the SDIO interface, and therefore not included in the SPI object // LCD @@ -78,6 +80,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, }; diff --git a/ports/espressif/boards/waveshare_esp32_s3_geek/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_geek/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_geek/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_geek/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/board.c b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/board.c index 36990c8556691..ee47ccb0bc96e 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/board.c +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/board.c @@ -105,9 +105,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO8, // DC - &pin_GPIO9, // CS - &pin_GPIO12, // RST + MP_OBJ_FROM_PTR(&pin_GPIO8), // DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // RST 80000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/mpconfigboard.mk index a8ac3b5d24551..f4d1f33be7938 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/mpconfigboard.mk @@ -21,4 +21,5 @@ INTERNAL_FLASH_FILESYSTEM = 0 QSPI_FLASH_FILESYSTEM = 1 EXTERNAL_FLASH_DEVICES = W25Q128JVxQ +# Not enough pins. CIRCUITPY_ESPCAMERA = 0 diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/sdkconfig index bcfb4d48ffef5..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_28/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-lcd-1-28" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/board.c b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/board.c new file mode 100644 index 0000000000000..4ecf87948ad04 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/board.c @@ -0,0 +1,99 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Benjamin Shockley +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + +// Driver is ST7789V3 +// Display Panel is LBS147TC-IF15 +// 172 X 320 Pixels RGB 18-bit + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 120, + 0x11, 0 | DELAY, 120, + 0x13, 0, + 0x36, 1, 0x00, + 0x3A, 1 | DELAY, 0x05, 10, + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + 0xB7, 1, 0x35, + 0xBB, 1, 0x20, + 0xC0, 1, 0x2C, + 0xC2, 2, 0x01, 0xFF, + 0xC3, 1, 0x13, + 0xC4, 1, 0x20, + 0xC6, 1, 0x0F, + 0xD0, 2, 0xA4, 0xA1, + 0xE0, 14, 0xF0, 0x00, 0x04, 0x04, 0x04, 0x05, 0x29, 0x33, 0x3E, 0x38, 0x12, 0x12, 0x28, 0x30, + 0xE1, 14, 0xF0, 0x07, 0x0A, 0x0D, 0x0B, 0x07, 0x28, 0x33, 0x3E, 0x36, 0x14, 0x14, 0x29, 0x32, + 0x21, 0, + 0x29, 0 | DELAY, 255, +}; + +static void display_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO41), // DC + MP_OBJ_FROM_PTR(&pin_GPIO42), // CS + MP_OBJ_FROM_PTR(&pin_GPIO39), // RST + 80000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 172, // width (after rotation) + 320, // height (after rotation) + 34, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO48, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Display + display_init(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.h new file mode 100644 index 0000000000000..1999b7c9614f8 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Benjamin Shockley +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3 LCD 1.47" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO17) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO16) + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO40, .mosi = &pin_GPIO45}, \ + {.clock = &pin_GPIO14, .mosi = &pin_GPIO15, .miso = &pin_GPIO16}} diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.mk new file mode 100644 index 0000000000000..fbdc6a7a1ecab --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x828B +USB_PRODUCT = "ESP32-S3-LCD-1.47" +USB_MANUFACTURER = "Waveshare Electronics" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/pins.c b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/pins.c new file mode 100644 index 0000000000000..a2ebbb79a8735 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/pins.c @@ -0,0 +1,81 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Button + { MP_ROM_QSTR(MP_QSTR_BTN), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + + // RGB LED + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) }, + + // 7-12 LCD + // LCD Backlight + { MP_ROM_QSTR(MP_QSTR_GP48), MP_ROM_PTR(&pin_GPIO48) }, + // LCD DC + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + // LCD RST + { MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) }, + // LCD CS + { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + // LCD MOSI + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) }, + // LCD SCK + { MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + + // 14-21 SD + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + // 43-44 UART + { MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // SD Card + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, + // Pin 38 is for the SDIO interface, and therefore not included in the SPI object + + // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_lcd_1_47/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/board.c b/ports/espressif/boards/waveshare_esp32_s3_matrix/board.c new file mode 100644 index 0000000000000..5859571eefa0c --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 David Sullivan +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.h new file mode 100644 index 0000000000000..63595cb559ec8 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 David Sullivan +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Matrix" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.mk new file mode 100644 index 0000000000000..0378c23be699a --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x303a +USB_PID = 0x826E +USB_PRODUCT = "Waveshare ESP32-S3-Matrix" +USB_MANUFACTURER = "Waveshare Electronics" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 4MB + +CIRCUITPY_ESP_PSRAM_SIZE = 2MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 80m + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c b/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c new file mode 100644 index 0000000000000..e21f542179c83 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/pins.c @@ -0,0 +1,91 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 David Sullivan +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Top side of the board - left column + // (top to bottom, preceded by 5V, GND & 3.3V) + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_I01), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + // Top side of the board - right column (bottom to top) + { MP_ROM_QSTR(MP_QSTR_IO33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_D33), MP_ROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_IO34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_D34), MP_ROM_PTR(&pin_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_IO35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_D35), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_IO36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_D36), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_ROM_QSTR(MP_QSTR_IO37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_D37), MP_ROM_PTR(&pin_GPIO37) }, + + { MP_ROM_QSTR(MP_QSTR_IO38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_D38), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_ROM_QSTR(MP_QSTR_IO39), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_D39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_D40), MP_ROM_PTR(&pin_GPIO40) }, + + // Numbering breaks up for TX/RX but it's still the top side, right column + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_D44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // Neopixel + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO14) }, + + // QMI8658C IMU + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT1), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT2), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_matrix/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_matrix/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_matrix/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/waveshare_esp32_s3_pico/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_pico/mpconfigboard.h index 866fbdaea5584..90ef06f2a1210 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_pico/mpconfigboard.h +++ b/ports/espressif/boards/waveshare_esp32_s3_pico/mpconfigboard.h @@ -11,6 +11,7 @@ #define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Pico" #define MICROPY_HW_MCU_NAME "ESP32S3" +#define MICROPY_HW_NEOPIXEL_ORDER_GRB (1) #define MICROPY_HW_NEOPIXEL (&pin_GPIO21) #define DEFAULT_UART_BUS_RX (&pin_GPIO12) diff --git a/ports/espressif/boards/waveshare_esp32_s3_pico/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_pico/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_pico/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_pico/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny/pins.c b/ports/espressif/boards/waveshare_esp32_s3_tiny/pins.c index 62d132af683fe..917ef0506abf9 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_tiny/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig index 19f833ad74cea..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_tiny/sdkconfig @@ -7,8 +7,6 @@ # # LWIP # -# CONFIG_LWIP_IPV6 is not set -CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-tiny" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/board.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/board.c new file mode 100644 index 0000000000000..1bdd74e77ee68 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/board.c @@ -0,0 +1,145 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 natheihei +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + +// Driver is JD9853 +// 172 X 320 Pixels RGB 18-bit +// Init sequence converted from Arduino example + +uint8_t display_init_sequence[] = { + // Command: 0x11 (SLPOUT: Sleep Out) + // Description: Exits sleep mode. A 120ms delay is added for the power supply and clock circuits to stabilize. + 0x11, 0 | DELAY, 120, + + 0xDF, 2, 0x98, 0x53, + 0xB2, 1, 0x23, + + 0xB7, 4, 0x00, 0x47, 0x00, 0x6F, + 0xBB, 6, 0x1C, 0x1A, 0x55, 0x73, 0x63, 0xF0, + 0xC0, 2, 0x44, 0xA4, + 0xC1, 1, 0x16, + 0xC3, 8, 0x7D, 0x07, 0x14, 0x06, 0xCF, 0x71, 0x72, 0x77, + 0xC4, 12, 0x00, 0x00, 0xA0, 0x79, 0x0B, 0x0A, 0x16, 0x79, 0x0B, 0x0A, 0x16, 0x82, + + 0xC8, 32, 0x3F, 0x32, 0x29, 0x29, 0x27, 0x2B, 0x27, 0x28, 0x28, 0x26, 0x25, 0x17, 0x12, 0x0D, 0x04, 0x00, + 0x3F, 0x32, 0x29, 0x29, 0x27, 0x2B, 0x27, 0x28, 0x28, 0x26, 0x25, 0x17, 0x12, 0x0D, 0x04, 0x00, + + 0xD0, 5, 0x04, 0x06, 0x6B, 0x0F, 0x00, + 0xD7, 2, 0x00, 0x30, + 0xE6, 1, 0x14, + 0xDE, 1, 0x01, + + 0xB7, 5, 0x03, 0x13, 0xEF, 0x35, 0x35, + 0xC1, 3, 0x14, 0x15, 0xC0, + 0xC2, 2, 0x06, 0x3A, + 0xC4, 2, 0x72, 0x12, + 0xBE, 1, 0x00, + 0xDE, 1, 0x02, + + 0xE5, 3, 0x00, 0x02, 0x00, + 0xE5, 3, 0x01, 0x02, 0x00, + + 0xDE, 1, 0x00, + + // Command: 0x35 (TEON: Tearing Effect Line ON) + // Description: Turns on the Tearing Effect output signal. + 0x35, 1, 0x00, + + // Command: 0x3A (COLMOD: Pixel Format Set) + // Description: Sets the pixel format for the MCU interface. + 0x3A, 1, 0x05, + + // Command: 0x2A (CASET: Column Address Set) + // Description: Defines the accessible column range in frame memory. + 0x2A, 4, 0x00, 0x22, 0x00, 0xCD, + + // Command: 0x2B (PASET: Page Address Set) + // Description: Defines the accessible page (row) range. + 0x2B, 4, 0x00, 0x00, 0x01, 0x3F, + + 0xDE, 1, 0x02, + 0xE5, 3, 0x00, 0x02, 0x00, + 0xDE, 1, 0x00, + + // Command: 0x36 (MADCTL: Memory Access Control) + // Description: Sets the read/write scanning direction of the frame memory. + 0x36, 1, 0x00, + + // Command: 0x21 (INVON: Display Inversion ON) + // 0x21, 0 | DELAY, 10, + + // Command: 0x29 (DISPON: Display ON) + // Description: Turns the display on by enabling output from the frame memory. + 0x29, 0, +}; + +static void display_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO45), // DC + MP_OBJ_FROM_PTR(&pin_GPIO21), // CS + MP_OBJ_FROM_PTR(&pin_GPIO40), // RST + 80000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 172, // width (after rotation) + 320, // height (after rotation) + 34, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO46, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Display + display_init(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.h new file mode 100644 index 0000000000000..0dc2ad4a6616b --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 natheihei +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3 Touch LCD 1.47" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.rx = &pin_GPIO44, .tx = &pin_GPIO43}} + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO41, .sda = &pin_GPIO42}} /* for Touchscreen */ + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO38, .mosi = &pin_GPIO39}, /* for LCD display */ \ + {.clock = &pin_GPIO16, .mosi = &pin_GPIO15, .miso = &pin_GPIO17} /* for SD Card */} diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.mk new file mode 100644 index 0000000000000..b337b21149537 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x8325 +USB_PRODUCT = "ESP32-S3-Touch-LCD-1.47" +USB_MANUFACTURER = "Waveshare Electronics" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/pins.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/pins.c new file mode 100644 index 0000000000000..32c7d0dd21d7e --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/pins.c @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 natheihei +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(touch_i2c, i2c, 0) +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + // GPIO + { MP_ROM_QSTR(MP_QSTR_GPIO1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GPIO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GPIO3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GPIO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GPIO5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GPIO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GPIO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GPIO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GPIO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GPIO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GPIO11), MP_ROM_PTR(&pin_GPIO11) }, + + // I2C (occupied by Touch I2C) + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // SD Card + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SD_D0), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SD_D1), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SD_D2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_SD_D3), MP_ROM_PTR(&pin_GPIO14) }, + // CLK, CMD, D0 is also included in the SPI object as its MISO pin, MOSI pin, and SCK pin respectively + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, + + // AXS5106L Touch + { MP_ROM_QSTR(MP_QSTR_TOUCH_I2C), MP_ROM_PTR(&board_touch_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_RST), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_TOUCH_IRQ), MP_ROM_PTR(&pin_GPIO48) }, + + // JD9853 LCD Display + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_1_47/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/board.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/board.c new file mode 100644 index 0000000000000..71e2d745623b9 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/board.c @@ -0,0 +1,78 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + 0x01, DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, DELAY, 0xFF, // _SLPOUT and Delay 500ms + 0x3A, DELAY | 1, 0x55, 0x0A, // _COLMOD and Delay 10ms + 0x21, DELAY, 0x0A, // _INVON Hack and Delay 10ms + 0x13, DELAY, 0x0A, // _NORON and Delay 10ms + 0x36, 0x01, 0x60, // _MADCTL + 0x29, DELAY, 0xFF, // _DISPON and Delay 500ms +}; + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO42), // DC + MP_OBJ_FROM_PTR(&pin_GPIO45), // CS + MP_OBJ_FROM_PTR(&pin_GPIO0), // RST + // 24000000, + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 320, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO1, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.h new file mode 100644 index 0000000000000..b4009fdfd7f6b --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Neradoc +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32S3 Touch LCD 2" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO47, .sda = &pin_GPIO48}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO39, .mosi = &pin_GPIO38, .miso = &pin_GPIO40}} + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.mk new file mode 100644 index 0000000000000..a6c719bf50feb --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x82CE +USB_MANUFACTURER = "Waveshare Electronics" +USB_PRODUCT = "ESP32S3 Touch LCD 2" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/pins.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/pins.c new file mode 100644 index 0000000000000..015a7a33952f0 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/pins.c @@ -0,0 +1,94 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // User accessible GPIO + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_IO9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_IO16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_IO17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_IO48), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IO14), MP_ROM_PTR(&pin_GPIO14) }, + + // User button + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + + // Battery ADC + {MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_GPIO5)}, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO48) }, + + // CST816D Touch + { MP_ROM_QSTR(MP_QSTR_TOUCH_INT), MP_ROM_PTR(&pin_GPIO46) }, + + // QMI8658 IMU + { MP_ROM_QSTR(MP_QSTR_IMU_INT), MP_ROM_PTR(&pin_GPIO3) }, + + // SPI + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO40) }, + + // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(&pin_GPIO1) }, + + // SD Card slot + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO41) }, + + // Camera connector + { MP_ROM_QSTR(MP_QSTR_CAM_HREF), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_CAM_VSYNC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_CAM_XCLK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_CAM_PCLK), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_CAM_PWDN), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D0), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D1), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D2), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D3), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D4), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D5), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D6), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_CAM_D7), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_TWI_CLK), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_TWI_SDA), MP_ROM_PTR(&pin_GPIO21) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/board.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/board.c new file mode 100755 index 0000000000000..49177f48fe7d9 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/board.c @@ -0,0 +1,77 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + +// display init sequence according to LilyGO example app +uint8_t display_init_sequence[] = { + 0x01, DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, DELAY, 0xFF, // _SLPOUT and Delay 500ms + 0x3A, DELAY | 1, 0x55, 0x0A, // _COLMOD and Delay 10ms + 0x21, DELAY, 0x0A, // _INVON Hack and Delay 10ms + 0x13, DELAY, 0x0A, // _NORON and Delay 10ms + 0x36, 0x01, 0x60, // _MADCTL + 0x29, DELAY, 0xFF, // _DISPON and Delay 500ms +}; + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO41), // DC + MP_OBJ_FROM_PTR(&pin_GPIO42), // CS + MP_OBJ_FROM_PTR(&pin_GPIO39), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 320, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO5, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.h b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.h new file mode 100755 index 0000000000000..3e0db8bf494d5 --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Neradoc +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3 Touch LCD 2.8" +#define MICROPY_HW_MCU_NAME "ESP32S3" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO3, .sda = &pin_GPIO1}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO40, .mosi = &pin_GPIO45, .miso = &pin_GPIO46}} + +#define DEFAULT_UART_BUS_RX (&pin_GPIO44) +#define DEFAULT_UART_BUS_TX (&pin_GPIO43) diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.mk new file mode 100755 index 0000000000000..421a58976002a --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x303A +USB_PID = 0x825F +USB_MANUFACTURER = "Waveshare Electronics" +USB_PRODUCT = "ESP32-S3 Touch LCD 2.8" + +IDF_TARGET = esp32s3 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = opi +CIRCUITPY_ESP_PSRAM_FREQ = 80m diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/pins.c b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/pins.c new file mode 100755 index 0000000000000..0bfb3e940b4de --- /dev/null +++ b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/pins.c @@ -0,0 +1,86 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // LCD (SPI0) + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MISO), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO5) }, // PWM-capable + + // microSD (SPI1) + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO21) }, + + // Touch panel (I2C0) + { MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_TP_RST), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_TP_INT), MP_ROM_PTR(&pin_GPIO4) }, + + // IMU (I2C1) + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT2), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_IMU_INT1), MP_ROM_PTR(&pin_GPIO13) }, + + // I2S Audio + { MP_ROM_QSTR(MP_QSTR_I2S_BCK), MP_ROM_PTR(&pin_GPIO48) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DIN), MP_ROM_PTR(&pin_GPIO47) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCK), MP_ROM_PTR(&pin_GPIO38) }, + + // Battery management + { MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO7) }, // control pin + { MP_ROM_QSTR(MP_QSTR_BAT_PWR), MP_ROM_PTR(&pin_GPIO6) }, // Board name + { MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO6) }, // Schematics name + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO8) }, // VBAT sense (ADC) + + // UART header + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) }, + + // I2C header + { MP_ROM_QSTR(MP_QSTR_I2C_SCL), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_I2C_SDA), MP_ROM_PTR(&pin_GPIO11) }, + + // Boot/User button + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON0), MP_ROM_PTR(&pin_GPIO0) }, + + // Primary bus pins + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO40) }, // Primary SPI (LCD) + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO46) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) }, // Primary I2C (TP) + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO1) }, + + // Objects + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + + // User accessible + { MP_ROM_QSTR(MP_QSTR_IO10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_IO11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_IO19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_IO20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_IO43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_IO44), MP_ROM_PTR(&pin_GPIO44) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_touch_lcd_2_8/sdkconfig new file mode 100755 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/waveshare_esp32_s3_zero/mpconfigboard.mk b/ports/espressif/boards/waveshare_esp32_s3_zero/mpconfigboard.mk index e1f616dea12f1..6e386e70e1724 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_zero/mpconfigboard.mk +++ b/ports/espressif/boards/waveshare_esp32_s3_zero/mpconfigboard.mk @@ -13,10 +13,5 @@ CIRCUITPY_ESP_PSRAM_SIZE = 2MB CIRCUITPY_ESP_PSRAM_MODE = qio CIRCUITPY_ESP_PSRAM_FREQ = 80m -CIRCUITPY_ESPCAMERA = 0 -CIRCUITPY_BITMAPFILTER = 0 -CIRCUITPY_CODEOP = 0 -CIRCUITPY_PARALLELDISPLAYBUS = 0 - # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/espressif/boards/waveshare_esp32_s3_zero/pins.c b/ports/espressif/boards/waveshare_esp32_s3_zero/pins.c index c4cd4ab821959..15225b1c57c5d 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_zero/pins.c +++ b/ports/espressif/boards/waveshare_esp32_s3_zero/pins.c @@ -9,6 +9,11 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + // BOOT button labeled simply as "B" on silkscreen + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + // Top side of the board - left column // (top to bottom, preceded by 5V, GND & 3.3V) { MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, @@ -147,8 +152,7 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + // UART - using TX RX on silkscreen { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) } }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/waveshare_esp32_s3_zero/sdkconfig b/ports/espressif/boards/waveshare_esp32_s3_zero/sdkconfig index 608f7e6a11cdd..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32_s3_zero/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32_s3_zero/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="ESP32-S3-Zero" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig b/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig index 7c86f9f8e37a3..e962866216039 100644 --- a/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig +++ b/ports/espressif/boards/waveshare_esp32s2_pico/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="waveshare" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/weact_esp32c6_n4/mpconfigboard.mk b/ports/espressif/boards/weact_esp32c6_n4/mpconfigboard.mk index 45309d289048e..bdd407ef10d00 100644 --- a/ports/espressif/boards/weact_esp32c6_n4/mpconfigboard.mk +++ b/ports/espressif/boards/weact_esp32c6_n4/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32c6 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 - -CIRCUITPY_AUDIOMP3 = 0 diff --git a/ports/espressif/boards/weact_esp32c6_n4/sdkconfig b/ports/espressif/boards/weact_esp32c6_n4/sdkconfig index 63084f9368da1..e962866216039 100644 --- a/ports/espressif/boards/weact_esp32c6_n4/sdkconfig +++ b/ports/espressif/boards/weact_esp32c6_n4/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="WEACT-ESP32-C6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/weact_esp32c6_n8/sdkconfig b/ports/espressif/boards/weact_esp32c6_n8/sdkconfig index 63084f9368da1..e962866216039 100644 --- a/ports/espressif/boards/weact_esp32c6_n8/sdkconfig +++ b/ports/espressif/boards/weact_esp32c6_n8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="WEACT-ESP32-C6" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/wemos_lolin32_lite/mpconfigboard.mk b/ports/espressif/boards/wemos_lolin32_lite/mpconfigboard.mk index 3c456881819d1..83e2289e7290d 100644 --- a/ports/espressif/boards/wemos_lolin32_lite/mpconfigboard.mk +++ b/ports/espressif/boards/wemos_lolin32_lite/mpconfigboard.mk @@ -6,7 +6,3 @@ IDF_TARGET = esp32 CIRCUITPY_ESP_FLASH_MODE = qio CIRCUITPY_ESP_FLASH_FREQ = 80m CIRCUITPY_ESP_FLASH_SIZE = 4MB - -CIRCUITPY_ESPCAMERA = 0 - -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT = 1 diff --git a/ports/espressif/boards/wemos_lolin32_lite/sdkconfig b/ports/espressif/boards/wemos_lolin32_lite/sdkconfig index 72be49f97e8cf..e962866216039 100644 --- a/ports/espressif/boards/wemos_lolin32_lite/sdkconfig +++ b/ports/espressif/boards/wemos_lolin32_lite/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="LOLIN32Lite" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/xteink_x4/board.c b/ports/espressif/boards/xteink_x4/board.c new file mode 100644 index 0000000000000..b5b193c65fec6 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/board.c @@ -0,0 +1,130 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/board.h" + +#define DELAY 0x80 + +// SSD1677 controller driving a GDEQ0426T82 4.26" 800x480 E-Ink display. + +const uint8_t ssd1677_display_start_sequence[] = { + // Software Reset + 0x12, DELAY, 0x00, 0x14, + + // Temperature Sensor Control (use internal sensor) + 0x18, 0x00, 0x01, 0x80, + + // Booster Soft Start + 0x0C, 0x00, 0x05, 0xAE, 0xC7, 0xC3, 0xC0, 0x40, + + // Driver Output Control: 480 gates, GD=0, SM=1, TB=0 = 0x02 + 0x01, 0x00, 0x03, 0xDF, 0x01, 0x02, + + // Data Entry Mode: X increment, Y decrement = 0x01 + 0x11, 0x00, 0x01, 0x01, + + // Border Waveform Control + 0x3C, 0x00, 0x01, 0x01, + + // Set RAM X Address Start/End: 0 to 799 + 0x44, 0x00, 0x04, 0x00, 0x00, 0x1F, 0x03, + + // Set RAM Y Address Start/End: 479 down to 0 + 0x45, 0x00, 0x04, 0xDF, 0x01, 0x00, 0x00, + + // Set RAM X Counter to 0 + 0x4E, 0x00, 0x02, 0x00, 0x00, + + // Set RAM Y Counter to 479 + 0x4F, 0x00, 0x02, 0xDF, 0x01, + + // Auto Write BW RAM (clear to white) + 0x46, DELAY, 0x01, 0xF7, 0xFF, + + // Display Update Control 1: bypass RED + 0x21, 0x00, 0x02, 0x40, 0x00, + + // Display Update Control 2: full refresh with OTP LUT + 0x22, 0x00, 0x01, 0xF7, +}; + +const uint8_t ssd1677_display_stop_sequence[] = { + 0x22, 0x00, 0x01, 0x83, + 0x20, 0x00, 0x00, + 0x10, 0x00, 0x01, 0x01, +}; + +const uint8_t ssd1677_display_refresh_sequence[] = { + 0x20, 0x00, 0x00, +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO8, &pin_GPIO10, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO4), + MP_OBJ_FROM_PTR(&pin_GPIO21), + MP_OBJ_FROM_PTR(&pin_GPIO5), + 40000000, + 0, + 0); + + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = ssd1677_display_start_sequence; + args.start_sequence_len = sizeof(ssd1677_display_start_sequence); + args.stop_sequence = ssd1677_display_stop_sequence; + args.stop_sequence_len = sizeof(ssd1677_display_stop_sequence); + args.width = 800; + args.height = 480; + args.ram_width = 800; + args.ram_height = 480; + args.rotation = 0; + args.write_black_ram_command = 0x24; + args.black_bits_inverted = false; + args.refresh_sequence = ssd1677_display_refresh_sequence; + args.refresh_sequence_len = sizeof(ssd1677_display_refresh_sequence); + args.refresh_time = 1.6; + args.busy_pin = &pin_GPIO6; + args.busy_state = true; + args.seconds_per_frame = 5.0; + args.grayscale = false; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +bool espressif_board_reset_pin_number(gpio_num_t pin_number) { + return false; +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/espressif/boards/xteink_x4/mpconfigboard.h b/ports/espressif/boards/xteink_x4/mpconfigboard.h new file mode 100644 index 0000000000000..5d4bb37222826 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Board setup +#define MICROPY_HW_BOARD_NAME "Xteink X4" +#define MICROPY_HW_MCU_NAME "ESP32-C3" + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO8, .mosi = &pin_GPIO10, .miso = &pin_GPIO7}} + +// For entering safe mode +#define CIRCUITPY_BOOT_BUTTON (&pin_GPIO3) diff --git a/ports/espressif/boards/xteink_x4/mpconfigboard.mk b/ports/espressif/boards/xteink_x4/mpconfigboard.mk new file mode 100644 index 0000000000000..8668aad18180c --- /dev/null +++ b/ports/espressif/boards/xteink_x4/mpconfigboard.mk @@ -0,0 +1,29 @@ +CIRCUITPY_CREATOR_ID = 0x0EEE0000 +CIRCUITPY_CREATION_ID = 0x00C30001 + +IDF_TARGET = esp32c3 + +CIRCUITPY_ESP_FLASH_MODE = dio +CIRCUITPY_ESP_FLASH_FREQ = 40m +CIRCUITPY_ESP_FLASH_SIZE = 16MB + +CIRCUITPY_ESP_USB_SERIAL_JTAG = 1 + +CIRCUITPY_PARALLELDISPLAYBUS = 0 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOCORE = 0 +CIRCUITPY_AUDIOMIXER = 0 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_CAMERA = 0 +CIRCUITPY_CANIO = 0 +CIRCUITPY_DOTCLOCKFRAMEBUFFER = 0 +CIRCUITPY_KEYPAD = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_USB_HID = 0 +CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_ULAB = 0 +CIRCUITPY_PULSEIO = 0 +CIRCUITPY_PWMIO = 0 +CIRCUITPY_RAINBOWIO = 0 +CIRCUITPY_SYNTHIO = 0 diff --git a/ports/espressif/boards/xteink_x4/pins.c b/ports/espressif/boards/xteink_x4/pins.c new file mode 100644 index 0000000000000..6b8232d4cb3a6 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/pins.c @@ -0,0 +1,52 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// SPDX-FileCopyrightText: Copyright (c) 2021 skieast/Bruce Segal +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BOOT0), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_ADC_1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_ADC_2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_EPD_MOSI), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_EPD_SCK), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_EPD_BUSY), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_EPD_RESET), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_EPD_DC), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_EPD_CS), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/espressif/boards/xteink_x4/sdkconfig b/ports/espressif/boards/xteink_x4/sdkconfig new file mode 100644 index 0000000000000..e962866216039 --- /dev/null +++ b/ports/espressif/boards/xteink_x4/sdkconfig @@ -0,0 +1,14 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# LWIP +# +# end of LWIP + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/boards/yd_esp32_s3_n16r8/sdkconfig b/ports/espressif/boards/yd_esp32_s3_n16r8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/yd_esp32_s3_n16r8/sdkconfig +++ b/ports/espressif/boards/yd_esp32_s3_n16r8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/yd_esp32_s3_n8r8/sdkconfig b/ports/espressif/boards/yd_esp32_s3_n8r8/sdkconfig index f5ef79768114c..e962866216039 100644 --- a/ports/espressif/boards/yd_esp32_s3_n8r8/sdkconfig +++ b/ports/espressif/boards/yd_esp32_s3_n8r8/sdkconfig @@ -7,7 +7,6 @@ # # LWIP # -CONFIG_LWIP_LOCAL_HOSTNAME="espressif-esp32s3" # end of LWIP # end of Component config diff --git a/ports/espressif/boards/yoto_mini_2024/board.c b/ports/espressif/boards/yoto_mini_2024/board.c new file mode 100644 index 0000000000000..fb6a96a957d06 --- /dev/null +++ b/ports/espressif/boards/yoto_mini_2024/board.c @@ -0,0 +1,203 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "board.h" + +#include "supervisor/board.h" + +#include "extmod/vfs_fat.h" + +#include "py/mpstate.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/i2cioexpander/IOExpander.h" +#include "shared-bindings/i2cioexpander/IOPin.h" +#include "shared-bindings/sdioio/SDCard.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +#include "supervisor/filesystem.h" + +static sdioio_sdcard_obj_t sdmmc; +static mp_vfs_mount_t _sdcard_vfs; +static fs_user_mount_t _sdcard_usermount; +static i2cioexpander_ioexpander_obj_t ioexpander; + +#define DELAY 0x80 + +// This is a GC9306. +uint8_t display_init_sequence[] = { + 0xfe, 0, + 0xef, 0, + + // // sw reset + // 0x01, 0 | DELAY, 150, + // normal display mode on + // 0x13, 0, + // display and color format settings + 0x36, 1, 0x48, // Memory access control. mini does 0x48, not 0, 2, 3, 4 or 6 + 0x3A, 1 | DELAY, 0x55, 10, // COLMOD. mini does 0x06 + 0xa4, 2, 0x44, 0x44, // power control 7 + 0xa5, 2, 0x42, 0x42, + 0xaa, 2, 0x88, 0x88, + 0xae, 1, 0x2b, + 0xe8, 2, 0x22, 0x0b, // frame rate + 0xe3, 2, 0x01, 0x10, + 0xff, 1, 0x61, + 0xac, 1, 0x00, + 0xad, 1, 0x33, + 0xaf, 1, 0x77, + 0xa6, 2, 0x1c, 0x1c, // power control 2 + 0xa7, 2, 0x1c, 0x1c, // power control 3 + 0xa8, 2, 0x10, 0x10, // power control 4 + 0xa9, 2, 0x0d, 0x0d, // power control 5 + 0xf0, 6, 0x02, 0x01, 0x00, 0x00, 0x00, 0x05, // Gamma settings + 0xf1, 6, 0x01, 0x02, 0x00, 0x06, 0x10, 0x0e, + 0xf2, 6, 0x03, 0x11, 0x28, 0x02, 0x00, 0x48, + 0xf3, 6, 0x0c, 0x11, 0x30, 0x00, 0x00, 0x46, + 0xf4, 6, 0x05, 0x1f, 0x1f, 0x36, 0x30, 0x0f, + 0xf5, 6, 0x04, 0x1d, 0x1a, 0x38, 0x3f, 0x0f, // Last gamma setting + 0x35, 1, 0x00, + 0x44, 2, 0x00, 0x0a, // set tear scan line + 0x21, 0, // display inversion on + // sleep out + 0x11, 0 | DELAY, 255, + + // display on + 0x29, 0 | DELAY, 255, +}; + +void board_init(void) { + // Wait for everything to start + mp_hal_delay_ms(300); + + // Initialize the board's peripherals here. + busio_i2c_obj_t *i2c = MP_OBJ_TO_PTR(common_hal_board_create_i2c(0)); + + // Initialize the IOExpander + ioexpander.base.type = &i2cioexpander_ioexpander_type; + common_hal_i2cioexpander_ioexpander_construct( + &ioexpander, + MP_OBJ_FROM_PTR(i2c), + 0x20, // I2C address + 16, // Number of pins + 2, // Output register + 0, // Input register + 6); // Direction register + + board_set(MP_QSTR_IOEXPANDER, MP_OBJ_FROM_PTR(&ioexpander)); + board_set(MP_QSTR_PLUG_STATUS, ioexpander.pins->items[8 + 5]); + board_set(MP_QSTR_CHARGE_STATUS, ioexpander.pins->items[8 + 7]); + board_set(MP_QSTR_POWER_BUTTON, ioexpander.pins->items[8 + 3]); + board_set(MP_QSTR_ENC1_BUTTON, ioexpander.pins->items[5]); + board_set(MP_QSTR_ENC2_BUTTON, ioexpander.pins->items[4]); + board_set(MP_QSTR_HEADPHONE_DETECT, ioexpander.pins->items[8 + 1]); + board_set(MP_QSTR_PACTRL, ioexpander.pins->items[6]); + board_set(MP_QSTR_DISPLAY_CS, ioexpander.pins->items[0]); + board_set(MP_QSTR_DISPLAY_DC, ioexpander.pins->items[1]); + board_set(MP_QSTR_DISPLAY_RESET, ioexpander.pins->items[2]); + + board_set(MP_QSTR_LEVEL_CONVERTER, ioexpander.pins->items[3]); + board_set(MP_QSTR_LEVEL_POWER_ENABLE, ioexpander.pins->items[8 + 4]); + board_set(MP_QSTR_LEVEL_VINHOLD, ioexpander.pins->items[8 + 6]); + + board_set(MP_QSTR_TILT, ioexpander.pins->items[8 + 2]); + + // Only on some variants + board_set(MP_QSTR_RTC_INT, ioexpander.pins->items[7]); + + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander.pins->items[2]), true, DRIVE_MODE_PUSH_PULL); + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander.pins->items[3]), true, DRIVE_MODE_PUSH_PULL); + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander.pins->items[6]), true, DRIVE_MODE_PUSH_PULL); + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander.pins->items[14]), true, DRIVE_MODE_PUSH_PULL); + + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + ioexpander.pins->items[1], // DC + ioexpander.pins->items[0], // CS + ioexpander.pins->items[2], // RST + 25000000, // baudrate + 0, // polarity + 0 // phase + ); + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 240, // width (after rotation) + 240, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO26, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); + + digitalinout_result_t sd_enable_res = common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander.pins->items[12]), false, DRIVE_MODE_PUSH_PULL); + if (sd_enable_res != DIGITALINOUT_OK) { + mp_printf(&mp_plat_print, "Failed to initialize IOExpander. Skipping SD card\n"); + return; + } + + sdmmc.base.type = &sdioio_SDCard_type; + const mcu_pin_obj_t *data_pins[4] = {MP_ROM_PTR(&pin_GPIO2), MP_ROM_PTR(&pin_GPIO4), MP_ROM_PTR(&pin_GPIO12), MP_ROM_PTR(&pin_GPIO13)}; + common_hal_sdioio_sdcard_construct(&sdmmc, MP_ROM_PTR(&pin_GPIO14), MP_ROM_PTR(&pin_GPIO15), 4, data_pins, 25 * 1000000); + + fs_user_mount_t *vfs = &_sdcard_usermount; + vfs->base.type = &mp_fat_vfs_type; + vfs->fatfs.drv = vfs; + + // Initialise underlying block device + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE + mp_vfs_blockdev_init(&vfs->blockdev, &sdmmc); + + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res != FR_OK) { + common_hal_sdioio_sdcard_deinit(&sdmmc); + return; + } + common_hal_sdioio_sdcard_never_reset(&sdmmc); + + filesystem_set_concurrent_write_protection(vfs, true); + filesystem_set_writable_by_usb(vfs, false); + + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; + sdcard_vfs->str = "/sd"; + sdcard_vfs->len = 3; + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; +} diff --git a/ports/espressif/boards/yoto_mini_2024/board.h b/ports/espressif/boards/yoto_mini_2024/board.h new file mode 100644 index 0000000000000..1e40b62b047db --- /dev/null +++ b/ports/espressif/boards/yoto_mini_2024/board.h @@ -0,0 +1,3 @@ +#include "py/obj.h" + +extern void board_set(qstr key, mp_obj_t value); diff --git a/ports/espressif/boards/yoto_mini_2024/mpconfigboard.h b/ports/espressif/boards/yoto_mini_2024/mpconfigboard.h new file mode 100644 index 0000000000000..4fcc2afaae870 --- /dev/null +++ b/ports/espressif/boards/yoto_mini_2024/mpconfigboard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Yoto Mini 2024" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define CIRCUITPY_MUTABLE_BOARD (1) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO25, .sda = &pin_GPIO21}} +#define CIRCUITPY_BOARD_I2C_SPEED (400000) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO23, .mosi = &pin_GPIO22, .miso = NULL}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}} + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/yoto_mini_2024/mpconfigboard.mk b/ports/espressif/boards/yoto_mini_2024/mpconfigboard.mk new file mode 100644 index 0000000000000..356e7015a04fa --- /dev/null +++ b/ports/espressif/boards/yoto_mini_2024/mpconfigboard.mk @@ -0,0 +1,14 @@ +CIRCUITPY_CREATOR_ID = 0x40100000 +CIRCUITPY_CREATION_ID = 0x00320002 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 40m + +CIRCUITPY_I2CIOEXPANDER = 1 diff --git a/ports/espressif/boards/yoto_mini_2024/pins.c b/ports/espressif/boards/yoto_mini_2024/pins.c new file mode 100644 index 0000000000000..d4ff3b4863fb5 --- /dev/null +++ b/ports/espressif/boards/yoto_mini_2024/pins.c @@ -0,0 +1,79 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT +// + +#include "board.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static mp_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_MUTABLE_BOARD_DICT_STANDARD_ITEMS + + // External pins are in silkscreen order, from top to bottom, left side, then right side + { MP_ROM_QSTR(MP_QSTR_ENC1A), MP_OBJ_FROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_ENC1B), MP_OBJ_FROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_ENC2A), MP_OBJ_FROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_ENC2B), MP_OBJ_FROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_OBJ_FROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_OBJ_FROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_OBJ_FROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_MOSI), MP_OBJ_FROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_NFC_IN), MP_OBJ_FROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_OBJ_FROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_NFC_OUT), MP_OBJ_FROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_OBJ_FROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_OBJ_FROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_OBJ_FROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_OBJ_FROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_OBJ_FROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCLK), MP_OBJ_FROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_OBJ_FROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_IOEXPANDER_INT), MP_OBJ_FROM_PTR(&pin_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_OBJ_FROM_PTR(&displays[0].display)}, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_OBJ_FROM_PTR(&board_i2c_obj) }, + + // Filled in by board_init() + { MP_ROM_QSTR(MP_QSTR_IOEXPANDER), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_PLUG_STATUS), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_CHARGE_STATUS), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_POWER_BUTTON), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_ENC1_BUTTON), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_ENC2_BUTTON), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_HEADPHONE_DETECT), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_PACTRL), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_DC), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_RESET), mp_const_none }, + + { MP_ROM_QSTR(MP_QSTR_LEVEL_CONVERTER), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_LEVEL_POWER_ENABLE), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_LEVEL_VINHOLD), mp_const_none }, + + { MP_ROM_QSTR(MP_QSTR_TILT), mp_const_none }, + + // Only on some variants + { MP_ROM_QSTR(MP_QSTR_RTC_INT), mp_const_none }, + +}; +MP_DEFINE_MUTABLE_DICT(board_module_globals, board_module_globals_table); + +void board_set(qstr q, mp_obj_t value) { + mp_obj_t key = MP_OBJ_NEW_QSTR(q); + for (size_t i = 0; i < MP_ARRAY_SIZE(board_module_globals_table); i++) { + if (board_module_globals_table[i].key == key) { + board_module_globals_table[i].value = value; + return; + } + } +} diff --git a/ports/espressif/boards/yoto_mini_2024/sdkconfig b/ports/espressif/boards/yoto_mini_2024/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/boards/yoto_player_v3/board.c b/ports/espressif/boards/yoto_player_v3/board.c new file mode 100644 index 0000000000000..fd6ee40b9f32e --- /dev/null +++ b/ports/espressif/boards/yoto_player_v3/board.c @@ -0,0 +1,148 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "board.h" + +#include "supervisor/board.h" + +#include "extmod/vfs_fat.h" + +#include "py/mpstate.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/i2cioexpander/IOExpander.h" +#include "shared-bindings/i2cioexpander/IOPin.h" +#include "shared-bindings/sdioio/SDCard.h" + +#include "supervisor/filesystem.h" + +static sdioio_sdcard_obj_t sdmmc; +static mp_vfs_mount_t _sdcard_vfs; +static fs_user_mount_t _sdcard_usermount; +static i2cioexpander_ioexpander_obj_t ioexpander0; // First chip (p0/p1) +static i2cioexpander_ioexpander_obj_t ioexpander1; // Second chip (p2/p3) + +void board_init(void) { + // Wait for everything to start + mp_hal_delay_ms(300); + + // Initialize the board's peripherals here. + busio_i2c_obj_t *i2c = MP_OBJ_TO_PTR(common_hal_board_create_i2c(0)); + + // Initialize the IOExpanders + // V3/V3-E uses two PI4IOE5V6416 chips (16 pins each) + // First chip (0x20): p0 (pins 0-7), p1 (pins 8-15) + ioexpander0.base.type = &i2cioexpander_ioexpander_type; + common_hal_i2cioexpander_ioexpander_construct( + &ioexpander0, + MP_OBJ_FROM_PTR(i2c), + 0x20, // I2C address for first chip + 16, // Number of pins + 2, // Output register + 0, // Input register + 6); // Direction register + + // Second chip (0x21): p2 (pins 0-7), p3 (pins 8-15) + ioexpander1.base.type = &i2cioexpander_ioexpander_type; + common_hal_i2cioexpander_ioexpander_construct( + &ioexpander1, + MP_OBJ_FROM_PTR(i2c), + 0x21, // I2C address for second chip + 16, // Number of pins + 2, // Output register + 0, // Input register + 6); // Direction register + + board_set(MP_QSTR_IOEXPANDER0, MP_OBJ_FROM_PTR(&ioexpander0)); + board_set(MP_QSTR_IOEXPANDER1, MP_OBJ_FROM_PTR(&ioexpander1)); + + // Battery and charging (from first chip - p0/p1) + board_set(MP_QSTR_BATTERY_ALERT, ioexpander0.pins->items[6]); // IOX.0.6 + board_set(MP_QSTR_QI_STATUS, ioexpander0.pins->items[7]); // IOX.0.7 + board_set(MP_QSTR_QI_I2C_INT, ioexpander0.pins->items[0]); // IOX.0.0 + board_set(MP_QSTR_USB_STATUS, ioexpander0.pins->items[8 + 0]); // IOX.1.0 + board_set(MP_QSTR_CHARGE_STATUS, ioexpander0.pins->items[8 + 4]); // IOX.1.4 + + // Buttons (from first chip - p0/p1) + board_set(MP_QSTR_POWER_BUTTON, ioexpander0.pins->items[8 + 3]); // IOX.1.3 + board_set(MP_QSTR_ENC1_BUTTON, ioexpander0.pins->items[5]); // IOX.0.5 + board_set(MP_QSTR_ENC2_BUTTON, ioexpander0.pins->items[4]); // IOX.0.4 + + // Audio (from first chip - p0/p1 and second chip - p2/p3) + board_set(MP_QSTR_HEADPHONE_DETECT, ioexpander0.pins->items[8 + 1]); // IOX.1.1 + board_set(MP_QSTR_PACTRL, ioexpander1.pins->items[4]); // IOX.2.4 + + // Display - V3/V3-E uses ht16d35x with 4 CS lines (from second chip - p2) + board_set(MP_QSTR_DISPLAY_CS0, ioexpander1.pins->items[0]); // IOX.2.0 + board_set(MP_QSTR_DISPLAY_CS1, ioexpander1.pins->items[1]); // IOX.2.1 + board_set(MP_QSTR_DISPLAY_CS2, ioexpander1.pins->items[2]); // IOX.2.2 + board_set(MP_QSTR_DISPLAY_CS3, ioexpander1.pins->items[3]); // IOX.2.3 + + // Power control (from second chip - p2/p3) + board_set(MP_QSTR_LEVEL_CONVERTER, ioexpander1.pins->items[8 + 0]); // IOX.3.0 + board_set(MP_QSTR_LEVEL_POWER_ENABLE, ioexpander1.pins->items[5]); // IOX.2.5 + board_set(MP_QSTR_LEVEL_VINHOLD, ioexpander1.pins->items[8 + 1]); // IOX.3.1 + board_set(MP_QSTR_LEVEL_VOUTEN, ioexpander1.pins->items[8 + 3]); // IOX.3.3 + + // Sensors (from first chip - p0/p1) + board_set(MP_QSTR_TILT, ioexpander0.pins->items[8 + 2]); // IOX.1.2 + board_set(MP_QSTR_RTC_INT, ioexpander0.pins->items[1]); // IOX.0.1 + + // Qi charging control (V3-E, from second chip - p2/p3) + board_set(MP_QSTR_QI_CHARGE_ENABLE, ioexpander1.pins->items[6]); // IOX.2.6 + board_set(MP_QSTR_USB_CHARGE_ENABLE, ioexpander1.pins->items[7]); // IOX.2.7 + board_set(MP_QSTR_QI_ENABLE_5W, ioexpander1.pins->items[8 + 5]); // IOX.3.5 + + // Output pin 3 high. Not clear why. + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander0.pins->items[3]), true, DRIVE_MODE_PUSH_PULL); + + // Initialize output pins + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[0]), true, DRIVE_MODE_PUSH_PULL); // DISPLAY_CS0 (IOX.2.0) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[1]), true, DRIVE_MODE_PUSH_PULL); // DISPLAY_CS1 (IOX.2.1) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[2]), true, DRIVE_MODE_PUSH_PULL); // DISPLAY_CS2 (IOX.2.2) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[3]), true, DRIVE_MODE_PUSH_PULL); // DISPLAY_CS3 (IOX.2.3) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[4]), true, DRIVE_MODE_PUSH_PULL); // PACTRL (IOX.2.4) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[5]), false, DRIVE_MODE_PUSH_PULL); // LEVEL_POWER_ENABLE (IOX.2.5) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[6]), true, DRIVE_MODE_PUSH_PULL); // QI_CHARGE_ENABLE + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[7]), false, DRIVE_MODE_PUSH_PULL); // USB_CHARGE_ENABLE + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[8 + 0]), true, DRIVE_MODE_PUSH_PULL); // LEVEL_CONVERTER (IOX.3.0) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[8 + 1]), true, DRIVE_MODE_PUSH_PULL); // VINHOLD (IOX.3.1) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[8 + 3]), true, DRIVE_MODE_PUSH_PULL); // VOUTEN (IOX.3.3) + common_hal_i2cioexpander_iopin_switch_to_output(MP_OBJ_TO_PTR(ioexpander1.pins->items[8 + 5]), false, DRIVE_MODE_PUSH_PULL); // QI_ENABLE_5W (IOX.3.5) + + // Initialize SD card + // V3/V3-E uses single-line SD (sd1 mode), not 4-line (sd4 mode) like Mini + sdmmc.base.type = &sdioio_SDCard_type; + const mcu_pin_obj_t *data_pins[1] = {MP_ROM_PTR(&pin_GPIO2)}; + common_hal_sdioio_sdcard_construct(&sdmmc, MP_ROM_PTR(&pin_GPIO14), MP_ROM_PTR(&pin_GPIO15), 1, data_pins, 25 * 1000000); + + fs_user_mount_t *vfs = &_sdcard_usermount; + vfs->base.type = &mp_fat_vfs_type; + vfs->fatfs.drv = vfs; + + // Initialise underlying block device + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE + mp_vfs_blockdev_init(&vfs->blockdev, &sdmmc); + + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res != FR_OK) { + common_hal_sdioio_sdcard_deinit(&sdmmc); + return; + } + common_hal_sdioio_sdcard_never_reset(&sdmmc); + + filesystem_set_concurrent_write_protection(vfs, true); + filesystem_set_writable_by_usb(vfs, false); + + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; + sdcard_vfs->str = "/sd"; + sdcard_vfs->len = 3; + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; +} diff --git a/ports/espressif/boards/yoto_player_v3/board.h b/ports/espressif/boards/yoto_player_v3/board.h new file mode 100644 index 0000000000000..1e40b62b047db --- /dev/null +++ b/ports/espressif/boards/yoto_player_v3/board.h @@ -0,0 +1,3 @@ +#include "py/obj.h" + +extern void board_set(qstr key, mp_obj_t value); diff --git a/ports/espressif/boards/yoto_player_v3/mpconfigboard.h b/ports/espressif/boards/yoto_player_v3/mpconfigboard.h new file mode 100644 index 0000000000000..1660c4881f98a --- /dev/null +++ b/ports/espressif/boards/yoto_player_v3/mpconfigboard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Yoto Player V3" +#define MICROPY_HW_MCU_NAME "ESP32" + +#define CIRCUITPY_MUTABLE_BOARD (1) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO25, .sda = &pin_GPIO21}} +#define CIRCUITPY_BOARD_I2C_SPEED (400000) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO23, .mosi = &pin_GPIO22, .miso = &pin_GPIO26}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO17, .rx = &pin_GPIO16}} + +// UART pins attached to the USB-serial converter chip +#define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO1) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO3) diff --git a/ports/espressif/boards/yoto_player_v3/mpconfigboard.mk b/ports/espressif/boards/yoto_player_v3/mpconfigboard.mk new file mode 100644 index 0000000000000..a1b940316c40a --- /dev/null +++ b/ports/espressif/boards/yoto_player_v3/mpconfigboard.mk @@ -0,0 +1,14 @@ +CIRCUITPY_CREATOR_ID = 0x40100000 +CIRCUITPY_CREATION_ID = 0x00320001 + +IDF_TARGET = esp32 + +CIRCUITPY_ESP_FLASH_MODE = qio +CIRCUITPY_ESP_FLASH_FREQ = 80m +CIRCUITPY_ESP_FLASH_SIZE = 8MB + +CIRCUITPY_ESP_PSRAM_SIZE = 8MB +CIRCUITPY_ESP_PSRAM_MODE = qio +CIRCUITPY_ESP_PSRAM_FREQ = 40m + +CIRCUITPY_I2CIOEXPANDER = 1 diff --git a/ports/espressif/boards/yoto_player_v3/pins.c b/ports/espressif/boards/yoto_player_v3/pins.c new file mode 100644 index 0000000000000..0862a020fdfce --- /dev/null +++ b/ports/espressif/boards/yoto_player_v3/pins.c @@ -0,0 +1,104 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT +// + +#include "board.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static mp_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_MUTABLE_BOARD_DICT_STANDARD_ITEMS + + // External pins are in silkscreen order, from top to bottom, left side, then right side + // Encoder 1: V3-E uses GPIO26/13, V3 uses GPIO35/13 + { MP_ROM_QSTR(MP_QSTR_ENC1A), MP_OBJ_FROM_PTR(&pin_GPIO26) }, // V3-E: GPIO26, V3: GPIO35 + { MP_ROM_QSTR(MP_QSTR_ENC1A_V3), MP_OBJ_FROM_PTR(&pin_GPIO35) }, // V3-E: GPIO26, V3: GPIO35 + { MP_ROM_QSTR(MP_QSTR_ENC1B), MP_OBJ_FROM_PTR(&pin_GPIO13) }, + + // Encoder 2: Both V3 and V3-E use GPIO27/4 + { MP_ROM_QSTR(MP_QSTR_ENC2A), MP_OBJ_FROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_ENC2B), MP_OBJ_FROM_PTR(&pin_GPIO4) }, + + // Light sensor (V3/V3-E) + { MP_ROM_QSTR(MP_QSTR_LIGHT_SENSOR), MP_OBJ_FROM_PTR(&pin_GPIO36) }, + + // Temperature sensors (V3/V3-E) + { MP_ROM_QSTR(MP_QSTR_TEMP_SENSOR), MP_OBJ_FROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_QI_RX_TEMP_SENSOR), MP_OBJ_FROM_PTR(&pin_GPIO35) }, // V3-E only + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_OBJ_FROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_OBJ_FROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_OBJ_FROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_OBJ_FROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_MOSI), MP_OBJ_FROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_OBJ_FROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_MISO), MP_OBJ_FROM_PTR(&pin_GPIO26) }, // V3/V3-E have MISO + { MP_ROM_QSTR(MP_QSTR_MISO), MP_OBJ_FROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_NFC_IN), MP_OBJ_FROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_OBJ_FROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_NFC_OUT), MP_OBJ_FROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_OBJ_FROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_OBJ_FROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_OBJ_FROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_OBJ_FROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_OBJ_FROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCLK), MP_OBJ_FROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_OBJ_FROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_IOEXPANDER_INT), MP_OBJ_FROM_PTR(&pin_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_OBJ_FROM_PTR(&board_i2c_obj) }, + + // Filled in by board_init() + { MP_ROM_QSTR(MP_QSTR_IOEXPANDER0), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_IOEXPANDER1), mp_const_none }, + { MP_ROM_QSTR(MP_QSTR_BATTERY_ALERT), mp_const_none }, // IOX.0.6 + { MP_ROM_QSTR(MP_QSTR_QI_STATUS), mp_const_none }, // IOX.0.7 + { MP_ROM_QSTR(MP_QSTR_USB_STATUS), mp_const_none }, // IOX.1.0 + { MP_ROM_QSTR(MP_QSTR_CHARGE_STATUS), mp_const_none }, // IOX.1.4 + { MP_ROM_QSTR(MP_QSTR_POWER_BUTTON), mp_const_none }, // IOX.1.3 + { MP_ROM_QSTR(MP_QSTR_ENC1_BUTTON), mp_const_none }, // IOX.0.5 + { MP_ROM_QSTR(MP_QSTR_ENC2_BUTTON), mp_const_none }, // IOX.0.4 + { MP_ROM_QSTR(MP_QSTR_HEADPHONE_DETECT), mp_const_none }, // IOX.1.1 + { MP_ROM_QSTR(MP_QSTR_PACTRL), mp_const_none }, // IOX.2.4 + // V3/V3-E use ht16d35x display with 4 CS lines + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS0), mp_const_none }, // IOX.2.0 + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS1), mp_const_none }, // IOX.2.1 + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS2), mp_const_none }, // IOX.2.2 + { MP_ROM_QSTR(MP_QSTR_DISPLAY_CS3), mp_const_none }, // IOX.2.3 + + { MP_ROM_QSTR(MP_QSTR_LEVEL_CONVERTER), mp_const_none }, // IOX.3.0 + { MP_ROM_QSTR(MP_QSTR_LEVEL_POWER_ENABLE), mp_const_none }, // IOX.2.5 + { MP_ROM_QSTR(MP_QSTR_LEVEL_VINHOLD), mp_const_none }, // IOX.3.1 + { MP_ROM_QSTR(MP_QSTR_LEVEL_VOUTEN), mp_const_none }, // IOX.3.3 + + { MP_ROM_QSTR(MP_QSTR_TILT), mp_const_none }, // IOX.1.2 + { MP_ROM_QSTR(MP_QSTR_RTC_INT), mp_const_none }, // IOX.0.1 + + // Qi charging pins (V3-E) + { MP_ROM_QSTR(MP_QSTR_QI_CHARGE_ENABLE), mp_const_none }, // IOX.2.6 + { MP_ROM_QSTR(MP_QSTR_QI_ENABLE_5W), mp_const_none }, // IOX.3.5 + { MP_ROM_QSTR(MP_QSTR_QI_I2C_INT), mp_const_none }, // IOX.0.0 + + // USB-C charging pins (V3/V3-E) + { MP_ROM_QSTR(MP_QSTR_USB_CHARGE_ENABLE), mp_const_none }, // IOX.2.7 + +}; +MP_DEFINE_MUTABLE_DICT(board_module_globals, board_module_globals_table); + +void board_set(qstr q, mp_obj_t value) { + mp_obj_t key = MP_OBJ_NEW_QSTR(q); + for (size_t i = 0; i < MP_ARRAY_SIZE(board_module_globals_table); i++) { + if (board_module_globals_table[i].key == key) { + board_module_globals_table[i].value = value; + return; + } + } +} diff --git a/ports/espressif/boards/yoto_player_v3/sdkconfig b/ports/espressif/boards/yoto_player_v3/sdkconfig new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/common-hal/_bleio/Adapter.c b/ports/espressif/common-hal/_bleio/Adapter.c index 21cdd88b1dbcb..aca3f8c2042ca 100644 --- a/ports/espressif/common-hal/_bleio/Adapter.c +++ b/ports/espressif/common-hal/_bleio/Adapter.c @@ -44,8 +44,8 @@ #include "esp_nimble_hci.h" #include "nvs_flash.h" -#if CIRCUITPY_OS_GETENV -#include "shared-module/os/__init__.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" #endif // Status variables used while busy-waiting for events. @@ -85,7 +85,7 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable // ble_hs_cfg.reset_cb = blecent_on_reset; ble_hs_cfg.sync_cb = _on_sync; - // ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; ble_hs_cfg.sm_io_cap = BLE_SM_IO_CAP_NO_IO; ble_hs_cfg.sm_bonding = 1; @@ -105,10 +105,10 @@ void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enable ble_svc_gatt_init(); ble_svc_ans_init(); - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML char ble_name[1 + MYNEWT_VAL_BLE_SVC_GAP_DEVICE_NAME_MAX_LENGTH]; - os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); - if (result == GETENV_OK) { + settings_err_t result = settings_get_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + if (result == SETTINGS_OK) { ble_svc_gap_device_name_set(ble_name); } else #endif @@ -384,7 +384,7 @@ static int _connect_event(struct ble_gap_event *event, void *self_in) { // connection and need a new tuple. self->connection_objs = NULL; } else { - // The loop waiting for the connection to be comnpleted will stop when _connection_status changes. + // The loop waiting for the connection to be completed will stop when _connection_status changes. _connection_status = -event->connect.status; } break; @@ -733,7 +733,7 @@ void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { } bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { - return ble_gap_adv_active(); + return common_hal_bleio_adapter_get_enabled(self) && ble_gap_adv_active(); } bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { diff --git a/ports/espressif/common-hal/_bleio/Characteristic.c b/ports/espressif/common-hal/_bleio/Characteristic.c index 342c729baf4fb..736c61c650eb4 100644 --- a/ports/espressif/common-hal/_bleio/Characteristic.c +++ b/ports/espressif/common-hal/_bleio/Characteristic.c @@ -16,38 +16,13 @@ #include "shared-bindings/_bleio/PacketBuffer.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/time/__init__.h" +#include "supervisor/shared/safe_mode.h" #include "common-hal/_bleio/Adapter.h" #include "common-hal/_bleio/Service.h" static int characteristic_on_ble_gap_evt(struct ble_gap_event *event, void *param); -static volatile int _completion_status; -static uint64_t _timeout_start_time; - -static void _reset_completion_status(void) { - _completion_status = 0; -} - -// Wait for a status change, recorded in a callback. -// Try twice because sometimes we get a BLE_HS_EAGAIN. -// Maybe we should try more than twice. -static int _wait_for_completion(uint32_t timeout_msecs) { - for (int tries = 1; tries <= 2; tries++) { - _timeout_start_time = common_hal_time_monotonic_ms(); - while ((_completion_status == 0) && - (common_hal_time_monotonic_ms() < _timeout_start_time + timeout_msecs) && - !mp_hal_is_interrupted()) { - RUN_BACKGROUND_TASKS; - } - if (_completion_status != BLE_HS_EAGAIN) { - // Quit, because either the status is either zero (OK) or it's an error. - break; - } - } - return _completion_status; -} - void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, @@ -100,27 +75,26 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->flags |= BLE_GATT_CHR_F_WRITE_AUTHEN; } - if (initial_value_bufinfo != NULL) { - // Copy the initial value if it's on the heap. Otherwise it's internal and we may not be able - // to allocate. - self->current_value_len = initial_value_bufinfo->len; + // If max_length is 0, then no storage is allocated. + if (max_length > 0) { if (gc_alloc_possible()) { - self->current_value = m_malloc(max_length); - self->current_value_alloc = max_length; - if (gc_nbytes(initial_value_bufinfo->buf) > 0) { - memcpy(self->current_value, initial_value_bufinfo->buf, self->current_value_len); - } + self->current_value = m_malloc_without_collect(max_length); } else { - self->current_value = initial_value_bufinfo->buf; - assert(self->current_value_len == max_length); - } - } else { - self->current_value = port_malloc(max_length, false); - if (self->current_value != NULL) { - self->current_value_alloc = max_length; - self->current_value_len = 0; + self->current_value = port_malloc(max_length, false); + if (self->current_value == NULL) { + reset_into_safe_mode(SAFE_MODE_NO_HEAP); + } } } + self->current_value_alloc = max_length; + self->current_value_len = 0; + + self->max_length = max_length; + self->fixed_length = fixed_length; + + if (initial_value_bufinfo != NULL) { + common_hal_bleio_characteristic_set_value(self, initial_value_bufinfo); + } if (gc_alloc_possible()) { self->descriptor_list = mp_obj_new_list(0, NULL); @@ -128,9 +102,6 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, self->descriptor_list = NULL; } - self->max_length = max_length; - self->fixed_length = fixed_length; - if (service->is_remote) { // If the service is remote, we're buffering incoming notifications and indications. self->handle = handle; @@ -140,6 +111,28 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->handle == BLEIO_HANDLE_INVALID; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + if (self->current_value != NULL) { + if (gc_ptr_on_heap(self->current_value)) { + m_free(self->current_value); + } else { + port_free(self->current_value); + } + + self->current_value = NULL; + } + + // Used to indicate deinit. + self->handle = BLEIO_HANDLE_INVALID; +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { if (self->descriptor_list == NULL) { return mp_const_empty_tuple; @@ -151,35 +144,7 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character return self->service; } -typedef struct { - uint8_t *buf; - uint16_t len; -} _read_info_t; - -static int _read_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) { - _read_info_t *read_info = (_read_info_t *)arg; - switch (error->status) { - case 0: { - int len = MIN(read_info->len, OS_MBUF_PKTLEN(attr->om)); - os_mbuf_copydata(attr->om, attr->offset, len, read_info->buf); - read_info->len = len; - } - MP_FALLTHROUGH; - - default: - #if CIRCUITPY_VERBOSE_BLE - // For debugging. - mp_printf(&mp_plat_print, "Read status: %d\n", error->status); - #endif - break; - } - _completion_status = error->status; - return 0; -} size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len) { // Do GATT operations only if this characteristic has been added to a registered service. @@ -188,14 +153,7 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel } uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { - _read_info_t read_info = { - .buf = buf, - .len = len - }; - _reset_completion_status(); - CHECK_NIMBLE_ERROR(ble_gattc_read(conn_handle, self->handle, _read_cb, &read_info)); - CHECK_NIMBLE_ERROR(_wait_for_completion(2000)); - return read_info.len; + return bleio_gattc_read(conn_handle, self->handle, buf, len); } else { len = MIN(self->current_value_len, len); memcpy(buf, self->current_value, len); @@ -209,28 +167,16 @@ size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t return self->max_length; } -static int _write_cb(uint16_t conn_handle, - const struct ble_gatt_error *error, - struct ble_gatt_attr *attr, - void *arg) { - _completion_status = error->status; - - return 0; -} - void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { if (common_hal_bleio_service_get_is_remote(self->service)) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if ((self->props & CHAR_PROP_WRITE_NO_RESPONSE) != 0) { CHECK_NIMBLE_ERROR(ble_gattc_write_no_rsp_flat(conn_handle, self->handle, bufinfo->buf, bufinfo->len)); } else { - _reset_completion_status(); - CHECK_NIMBLE_ERROR(ble_gattc_write_flat(conn_handle, self->handle, bufinfo->buf, bufinfo->len, _write_cb, NULL)); - CHECK_NIMBLE_ERROR(_wait_for_completion(2000)); + bleio_gattc_write(conn_handle, self->handle, bufinfo->buf, bufinfo->len); } } else { // Validate data length for local characteristics only. - // TODO: Test this once we can get servers going. if (self->fixed_length && bufinfo->len != self->max_length) { mp_raise_ValueError(MP_ERROR_TEXT("Value length != required fixed length")); } @@ -245,21 +191,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, } self->current_value_len = bufinfo->len; - // If we've already allocated an internal buffer or the provided buffer - // is on the heap, then copy into the internal buffer. - if (self->current_value_alloc > 0 || gc_nbytes(bufinfo->buf) > 0) { - if (self->current_value_alloc < bufinfo->len) { - self->current_value = m_realloc(self->current_value, bufinfo->len); - // Get the number of bytes from the heap because it may be more - // than the len due to gc block size. - self->current_value_alloc = gc_nbytes(self->current_value); - } - memcpy(self->current_value, bufinfo->buf, bufinfo->len); - } else { - // Otherwise, use the provided buffer to delay any heap allocation. - self->current_value = bufinfo->buf; - self->current_value_alloc = 0; - } + memcpy(self->current_value, bufinfo->buf, self->current_value_len); ble_gatts_chr_updated(self->handle); } @@ -388,15 +320,13 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? 1 << 0 : 0) | (indicate ? 1 << 1: 0); - _reset_completion_status(); - CHECK_NIMBLE_ERROR(ble_gattc_write_flat(conn_handle, self->cccd_handle, &cccd_value, 2, _write_cb, NULL)); - CHECK_NIMBLE_ERROR(_wait_for_completion(2000)); + bleio_gattc_write(conn_handle, self->cccd_handle, (uint8_t *)&cccd_value, 2); } void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) { diff --git a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c index 082cd492a9190..3c0cbf323f3e2 100644 --- a/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/espressif/common-hal/_bleio/CharacteristicBuffer.c @@ -26,6 +26,7 @@ void bleio_characteristic_buffer_extend(bleio_characteristic_buffer_obj_t *self, for (uint16_t i = 0; i < len; i++) { if (data[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&self->ringbuf); } else { ringbuf_put(&self->ringbuf, data[i]); } @@ -53,7 +54,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL, false); } diff --git a/ports/espressif/common-hal/_bleio/Connection.h b/ports/espressif/common-hal/_bleio/Connection.h index 326eca02ecd8a..5f33eb43b5df9 100644 --- a/ports/espressif/common-hal/_bleio/Connection.h +++ b/ports/espressif/common-hal/_bleio/Connection.h @@ -64,6 +64,7 @@ void bleio_connection_clear(bleio_connection_internal_t *self); int bleio_connection_event_cb(struct ble_gap_event *event, void *connection_in); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/ports/espressif/common-hal/_bleio/Descriptor.c b/ports/espressif/common-hal/_bleio/Descriptor.c index 345dd542eb021..3f2870740f176 100644 --- a/ports/espressif/common-hal/_bleio/Descriptor.c +++ b/ports/espressif/common-hal/_bleio/Descriptor.c @@ -10,6 +10,7 @@ #include "py/runtime.h" #include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Attribute.h" #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" @@ -24,6 +25,31 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_c self->write_perm = write_perm; self->initial_value = mp_obj_new_bytes(initial_value_bufinfo->buf, initial_value_bufinfo->len); + // Map CP's property values to Nimble's flag values. + self->flags = 0; + if (read_perm != SECURITY_MODE_NO_ACCESS) { + self->flags |= BLE_ATT_F_READ; + } + if (write_perm != SECURITY_MODE_NO_ACCESS) { + self->flags |= BLE_ATT_F_WRITE; + } + if (read_perm == SECURITY_MODE_ENC_WITH_MITM || write_perm == SECURITY_MODE_ENC_WITH_MITM || + read_perm == SECURITY_MODE_SIGNED_WITH_MITM || write_perm == SECURITY_MODE_SIGNED_WITH_MITM) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("MITM security not supported")); + } + if (read_perm == SECURITY_MODE_ENC_NO_MITM) { + self->flags |= BLE_ATT_F_READ_ENC; + } + if (read_perm == SECURITY_MODE_SIGNED_NO_MITM) { + self->flags |= BLE_ATT_F_READ_AUTHEN; + } + if (write_perm == SECURITY_MODE_ENC_NO_MITM) { + self->flags |= BLE_ATT_F_WRITE_ENC; + } + if (write_perm == SECURITY_MODE_SIGNED_NO_MITM) { + self->flags |= BLE_ATT_F_WRITE_AUTHEN; + } + const mp_int_t max_length_max = BLE_ATT_ATTR_MAX_LEN; if (max_length < 0 || max_length > max_length_max) { mp_raise_ValueError_varg(MP_ERROR_TEXT("max_length must be 0-%d when fixed_length is %s"), @@ -42,38 +68,35 @@ bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio } size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t *buf, size_t len) { - // Do GATT operations only if this descriptor has been registered - if (self->handle != BLEIO_HANDLE_INVALID) { + if (self->characteristic == NULL) { + return 0; + } + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); - (void)conn_handle; + return bleio_gattc_read(conn_handle, self->handle, buf, len); + } else { + mp_buffer_info_t bufinfo; + mp_get_buffer(self->initial_value, &bufinfo, MP_BUFFER_READ); + len = MIN(bufinfo.len, len); + memcpy(buf, bufinfo.buf, len); + return len; } - // TODO: Implement this. - return 0; } void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { - // TODO: Implement this. - // Do GATT operations only if this descriptor has been registered. - if (self->handle != BLEIO_HANDLE_INVALID) { - // uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); - if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - // false means WRITE_REQ, not write-no-response - // common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); - } else { - // Validate data length for local descriptors only. - if (self->fixed_length && bufinfo->len != self->max_length) { - mp_raise_ValueError(MP_ERROR_TEXT("Value length != required fixed length")); - } - if (bufinfo->len > self->max_length) { - mp_raise_ValueError(MP_ERROR_TEXT("Value length > max_length")); - } - - // common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); - } + if (self->characteristic == NULL) { + return; } + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); + bleio_gattc_write(conn_handle, self->handle, bufinfo->buf, bufinfo->len); + } else { + // Descriptor values should be set via the initial_value when used locally. + mp_raise_NotImplementedError(NULL); + } } int bleio_descriptor_access_cb(uint16_t conn_handle, uint16_t attr_handle, diff --git a/ports/espressif/common-hal/_bleio/PacketBuffer.c b/ports/espressif/common-hal/_bleio/PacketBuffer.c index cf362d89e92cc..db035157ceb6b 100644 --- a/ports/espressif/common-hal/_bleio/PacketBuffer.c +++ b/ports/espressif/common-hal/_bleio/PacketBuffer.c @@ -240,17 +240,17 @@ void common_hal_bleio_packet_buffer_construct( uint32_t *incoming_buffer = NULL; if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } uint32_t *outgoing1 = NULL; uint32_t *outgoing2 = NULL; if (outgoing) { - outgoing1 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); // Only allocate the second buffer if we are doing writes with responses. // Without responses, we just write as quickly as we can. if (outgoing == CHAR_PROP_WRITE || outgoing == CHAR_PROP_INDICATE) { - outgoing2 = m_malloc(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } } _common_hal_bleio_packet_buffer_construct(self, characteristic, @@ -436,6 +436,11 @@ void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { return; } bleio_characteristic_clear_observer(self->characteristic); + self->characteristic = NULL; ble_event_remove_handler(packet_buffer_on_ble_client_evt, self); ringbuf_deinit(&self->ringbuf); } + +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self) { + return !common_hal_bleio_packet_buffer_deinited(self) && self->conn_handle != BLEIO_HANDLE_INVALID; +} diff --git a/ports/espressif/common-hal/_bleio/Service.c b/ports/espressif/common-hal/_bleio/Service.c index 166580b067684..3afbeb2a684de 100644 --- a/ports/espressif/common-hal/_bleio/Service.c +++ b/ports/espressif/common-hal/_bleio/Service.c @@ -86,6 +86,10 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, const char *user_description) { mp_obj_list_append(self->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); + if (user_description != NULL) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_user_description); + } + // Delete the old version of the service. if (self->characteristic_list->len > 1) { ble_gatts_delete_svc(&self->uuid->nimble_ble_uuid.u); diff --git a/ports/espressif/common-hal/_bleio/__init__.c b/ports/espressif/common-hal/_bleio/__init__.c index eb51e9f456700..4fdd0a48a2000 100644 --- a/ports/espressif/common-hal/_bleio/__init__.c +++ b/ports/espressif/common-hal/_bleio/__init__.c @@ -9,6 +9,8 @@ #include #include "py/runtime.h" +#include "shared/runtime/interrupt_char.h" + #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" #include "shared-bindings/_bleio/Characteristic.h" @@ -16,6 +18,7 @@ #include "shared-bindings/_bleio/Descriptor.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" +#include "shared-bindings/time/__init__.h" #include "supervisor/shared/bluetooth/bluetooth.h" #include "common-hal/_bleio/__init__.h" @@ -23,10 +26,12 @@ #include "nvs_flash.h" +static volatile int _completion_status; +static uint64_t _timeout_start_time; background_callback_t bleio_background_callback; -void bleio_user_reset() { +void bleio_user_reset(void) { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj); @@ -38,7 +43,7 @@ void bleio_user_reset() { } // Turn off BLE on a reset or reload. -void bleio_reset() { +void bleio_reset(void) { // Set this explicitly to save data. if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { return; @@ -98,6 +103,9 @@ void check_nimble_error(int rc, const char *file, size_t line) { case BLE_HS_ENOTCONN: mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); return; + case BLE_HS_EALREADY: + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Already in progress")); + return; default: #if CIRCUITPY_VERBOSE_BLE || CIRCUITPY_DEBUG if (file) { @@ -147,8 +155,88 @@ void check_notify(BaseType_t result) { mp_raise_msg(&mp_type_TimeoutError, NULL); } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLEIO_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } } + +static void _reset_completion_status(void) { + _completion_status = 0; +} + +// Wait for a status change, recorded in a callback. +// Try twice because sometimes we get a BLE_HS_EAGAIN. +// Maybe we should try more than twice. +static int _wait_for_completion(uint32_t timeout_msecs) { + for (int tries = 1; tries <= 2; tries++) { + _timeout_start_time = common_hal_time_monotonic_ms(); + while ((_completion_status == 0) && + (common_hal_time_monotonic_ms() < _timeout_start_time + timeout_msecs) && + !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } + if (_completion_status != BLE_HS_EAGAIN) { + // Quit, because either the status is either zero (OK) or it's an error. + break; + } + } + return _completion_status; +} + +typedef struct { + uint8_t *buf; + uint16_t len; +} _read_info_t; + +static int _read_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) { + _read_info_t *read_info = (_read_info_t *)arg; + switch (error->status) { + case 0: { + int len = MIN(read_info->len, OS_MBUF_PKTLEN(attr->om)); + os_mbuf_copydata(attr->om, attr->offset, len, read_info->buf); + read_info->len = len; + } + MP_FALLTHROUGH; + + default: + #if CIRCUITPY_VERBOSE_BLE + // For debugging. + mp_printf(&mp_plat_print, "Read status: %d\n", error->status); + #endif + break; + } + _completion_status = error->status; + + return 0; +} + +int bleio_gattc_read(uint16_t conn_handle, uint16_t value_handle, uint8_t *buf, size_t len) { + _read_info_t read_info = { + .buf = buf, + .len = len + }; + _reset_completion_status(); + CHECK_NIMBLE_ERROR(ble_gattc_read(conn_handle, value_handle, _read_cb, &read_info)); + CHECK_NIMBLE_ERROR(_wait_for_completion(2000)); + return read_info.len; +} + + +static int _write_cb(uint16_t conn_handle, + const struct ble_gatt_error *error, + struct ble_gatt_attr *attr, + void *arg) { + _completion_status = error->status; + + return 0; +} + +void bleio_gattc_write(uint16_t conn_handle, uint16_t value_handle, uint8_t *buf, size_t len) { + _reset_completion_status(); + CHECK_NIMBLE_ERROR(ble_gattc_write_flat(conn_handle, value_handle, buf, len, _write_cb, NULL)); + CHECK_NIMBLE_ERROR(_wait_for_completion(2000)); +} diff --git a/ports/espressif/common-hal/_bleio/__init__.h b/ports/espressif/common-hal/_bleio/__init__.h index a10083a24b761..d0f9ce5561ac6 100644 --- a/ports/espressif/common-hal/_bleio/__init__.h +++ b/ports/espressif/common-hal/_bleio/__init__.h @@ -43,3 +43,6 @@ void check_notify(BaseType_t result); #define UNIT_1_MS (1000) #define UNIT_1_25_MS (1250) #define UNIT_10_MS (10000) + +int bleio_gattc_read(uint16_t conn_handle, uint16_t value_handle, uint8_t *buf, size_t len); +void bleio_gattc_write(uint16_t conn_handle, uint16_t value_handle, uint8_t *buf, size_t len); diff --git a/ports/espressif/common-hal/_bleio/ble_events.c b/ports/espressif/common-hal/_bleio/ble_events.c index 6a616819a8bd3..5b9eb649c977e 100644 --- a/ports/espressif/common-hal/_bleio/ble_events.c +++ b/ports/espressif/common-hal/_bleio/ble_events.c @@ -64,7 +64,7 @@ void ble_event_add_handler(ble_gap_event_fn *func, void *param) { } // Add a new handler to the front of the list - ble_event_handler_entry_t *handler = m_new(ble_event_handler_entry_t, 1); + ble_event_handler_entry_t *handler = m_new_obj(ble_event_handler_entry_t); ble_event_add_handler_entry(handler, func, param); } diff --git a/ports/espressif/common-hal/alarm/__init__.c b/ports/espressif/common-hal/alarm/__init__.c index 629f976039fd1..4f8e7e530425a 100644 --- a/ports/espressif/common-hal/alarm/__init__.c +++ b/ports/espressif/common-hal/alarm/__init__.c @@ -189,7 +189,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); #if CIRCUITPY_ALARM_TOUCH alarm_touch_touchalarm_prepare_for_deep_sleep(); diff --git a/ports/espressif/common-hal/alarm/pin/PinAlarm.c b/ports/espressif/common-hal/alarm/pin/PinAlarm.c index 45f676fa5993f..97ad3b2a94255 100644 --- a/ports/espressif/common-hal/alarm/pin/PinAlarm.c +++ b/ports/espressif/common-hal/alarm/pin/PinAlarm.c @@ -14,10 +14,12 @@ #include "esp_sleep.h" #include "hal/gpio_ll.h" +#include "driver/gpio.h" #include "esp_debug_helpers.h" #ifdef SOC_PM_SUPPORT_EXT0_WAKEUP #include "soc/rtc_cntl_reg.h" +#include "soc/rtc_io_reg.h" #endif #include "driver/rtc_io.h" @@ -108,7 +110,17 @@ mp_obj_t alarm_pin_pinalarm_record_wake_alarm(void) { #ifdef SOC_PM_SUPPORT_EXT0_WAKEUP if (cause == ESP_SLEEP_WAKEUP_EXT0) { - pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL); + int rtc_io_pin_number = REG_GET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL); + // Look up the GPIO equivalent pin for this RTC GPIO pin. On ESP32, the numbering + // is different for RTC_GPIO and regular GPIO, and there's no mapping table. + // The RTC and GPIO pin numbers match for all other current chips, so we could skip this + // for those chips, but it's not expensive, and maybe there will be another mismatch in the future. + for (gpio_num_t gpio_num = 0; gpio_num < SOC_GPIO_PIN_COUNT; gpio_num++) { + if (rtc_io_number_get(gpio_num) == rtc_io_pin_number) { + pin_number = gpio_num; + break; + } + } } else { #endif #ifdef SOC_PM_SUPPORT_EXT1_WAKEUP @@ -348,38 +360,40 @@ void alarm_pin_pinalarm_set_alarms(bool deep_sleep, size_t n_alarms, const mp_ob if (gpio_isr_register(gpio_interrupt, NULL, 0, &gpio_interrupt_handle) != ESP_OK) { mp_raise_ValueError(MP_ERROR_TEXT("Can only alarm on RTC IO from deep sleep.")); } - for (size_t i = 0; i < 64; i++) { - uint64_t mask = 1ull << i; + for (gpio_num_t pin = 0; pin < SOC_GPIO_PIN_COUNT; pin++) { + uint64_t mask = 1ULL << pin; bool high = (high_alarms & mask) != 0; bool low = (low_alarms & mask) != 0; bool pull = (pull_pins & mask) != 0; if (!(high || low)) { continue; } - if (rtc_gpio_is_valid_gpio(i)) { + if (rtc_gpio_is_valid_gpio(pin)) { #ifdef SOC_PM_SUPPORT_RTC_PERIPH_PD - rtc_gpio_deinit(i); + rtc_gpio_deinit(pin); #endif } - gpio_int_type_t interrupt_mode = GPIO_INTR_DISABLE; - gpio_pull_mode_t pull_mode = GPIO_FLOATING; + gpio_set_direction(pin, GPIO_MODE_INPUT); + if (pull) { + if (high) { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_PULLDOWN_ONLY)); + } else { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_PULLUP_ONLY)); + } + } else { + ESP_ERROR_CHECK(gpio_set_pull_mode(pin, GPIO_FLOATING)); + } + gpio_int_type_t intr = GPIO_INTR_DISABLE; if (high) { - interrupt_mode = GPIO_INTR_HIGH_LEVEL; - pull_mode = GPIO_PULLDOWN_ONLY; + intr = GPIO_INTR_HIGH_LEVEL; } if (low) { - interrupt_mode = GPIO_INTR_LOW_LEVEL; - pull_mode = GPIO_PULLUP_ONLY; - } - gpio_set_direction(i, GPIO_MODE_DEF_INPUT); - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[i], PIN_FUNC_GPIO); - if (pull) { - gpio_set_pull_mode(i, pull_mode); + intr = GPIO_INTR_LOW_LEVEL; } - never_reset_pin_number(i); - // Sets interrupt type and wakeup bits. - gpio_wakeup_enable(i, interrupt_mode); - gpio_intr_enable(i); + never_reset_pin_number(pin); + gpio_wakeup_enable(pin, intr); + gpio_set_intr_type(pin, intr); + gpio_intr_enable(pin); } // Wait for any pulls to settle. mp_hal_delay_ms(50); diff --git a/ports/espressif/common-hal/analogbufio/BufferedIn.c b/ports/espressif/common-hal/analogbufio/BufferedIn.c index 305bd10a37fe2..20c5c060574aa 100644 --- a/ports/espressif/common-hal/analogbufio/BufferedIn.c +++ b/ports/espressif/common-hal/analogbufio/BufferedIn.c @@ -33,7 +33,7 @@ #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define ADC_RESULT_BYTE 2 #define ADC_CONV_LIMIT_EN 0 -#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) +#elif defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61) #define ADC_RESULT_BYTE 4 #define ADC_CONV_LIMIT_EN 0 #elif defined(CONFIG_IDF_TARGET_ESP32S3) diff --git a/ports/espressif/common-hal/analogio/AnalogIn.c b/ports/espressif/common-hal/analogio/AnalogIn.c index 9b1b14f07c3a4..34cd5b846cf22 100644 --- a/ports/espressif/common-hal/analogio/AnalogIn.c +++ b/ports/espressif/common-hal/analogio/AnalogIn.c @@ -32,6 +32,10 @@ #define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32C6) #define DATA_WIDTH ADC_BITWIDTH_12 +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#define DATA_WIDTH ADC_BITWIDTH_12 +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#define DATA_WIDTH ADC_BITWIDTH_12 #elif defined(CONFIG_IDF_TARGET_ESP32S2) #define DATA_WIDTH ADC_BITWIDTH_13 #elif defined(CONFIG_IDF_TARGET_ESP32S3) @@ -86,7 +90,6 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { adc_cali_check_scheme(&supported_schemes); adc_cali_scheme_ver_t calibration_scheme = 0; adc_cali_handle_t calibration; - #if defined(ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED) && ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED adc_cali_curve_fitting_config_t config = { .unit_id = self->pin->adc_index, @@ -136,7 +139,6 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { int voltage; adc_cali_raw_to_voltage(calibration, adc_reading, &voltage); - #if defined(ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED) && ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED if (calibration_scheme == ADC_CALI_SCHEME_VER_CURVE_FITTING) { adc_cali_delete_scheme_curve_fitting(calibration); diff --git a/ports/espressif/common-hal/audiobusio/PDMIn.c b/ports/espressif/common-hal/audiobusio/PDMIn.c index 72d32ef2b2c5d..c9d28ad7071d1 100644 --- a/ports/espressif/common-hal/audiobusio/PDMIn.c +++ b/ports/espressif/common-hal/audiobusio/PDMIn.c @@ -3,3 +3,127 @@ // SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC // // SPDX-License-Identifier: MIT + + +#include "bindings/espidf/__init__.h" + +#include "common-hal/audiobusio/PDMIn.h" +#include "py/mpprint.h" +#include "py/runtime.h" +#include "shared-bindings/audiobusio/PDMIn.h" + + +#include "driver/i2s_pdm.h" + + + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + + + +/** + Note: I think this function needs an additional parameter for the word select + pin. It takes `mono`, a boolean indicating if it should be mono or + stereo, but without a word select pin, I don't think one can get + the other channel. +*/ + +void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self, + const mcu_pin_obj_t *clock_pin, + const mcu_pin_obj_t *data_pin, + uint32_t sample_rate, + uint8_t bit_depth, + bool mono, + uint8_t oversample) { + + if (bit_depth != I2S_DATA_BIT_WIDTH_8BIT + && bit_depth != I2S_DATA_BIT_WIDTH_16BIT + && bit_depth != I2S_DATA_BIT_WIDTH_24BIT + && bit_depth != I2S_DATA_BIT_WIDTH_32BIT) { + mp_raise_ValueError(MP_ERROR_TEXT("bit_depth must be 8, 16, 24, or 32.")); + } + + i2s_chan_config_t chanConfig = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); + esp_err_t err = i2s_new_channel(&chanConfig, NULL, &self->rx_chan); + CHECK_ESP_RESULT(err); + + i2s_pdm_rx_config_t pdm_rx_cfg = { + .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(sample_rate), + .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(bit_depth, mono ? I2S_SLOT_MODE_MONO : I2S_SLOT_MODE_STEREO), + .gpio_cfg = + { + .clk = clock_pin->number, + .din = data_pin->number, + .invert_flags = + { + .clk_inv = false, + }, + }, + }; + err = i2s_channel_init_pdm_rx_mode(self->rx_chan, &pdm_rx_cfg); + CHECK_ESP_RESULT(err); + + err = i2s_channel_enable(self->rx_chan); + CHECK_ESP_RESULT(err); + + self->clock_pin = clock_pin; + self->data_pin = data_pin; + claim_pin(clock_pin); + claim_pin(data_pin); + + self->sample_rate = sample_rate; + self->bit_depth = bit_depth; +} + +bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t *self) { + return self->clock_pin == NULL; +} + +void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t *self) { + if (common_hal_audiobusio_pdmin_deinited(self)) { + return; + } + + esp_err_t err = i2s_channel_disable(self->rx_chan); + CHECK_ESP_RESULT(err); + err = i2s_del_channel(self->rx_chan); + CHECK_ESP_RESULT(err); + + // common_hal_audiobusio_i2sout_stop(self); + + if (self->clock_pin) { + reset_pin_number(self->clock_pin->number); + } + self->clock_pin = NULL; + + if (self->data_pin) { + reset_pin_number(self->data_pin->number); + } + self->data_pin = NULL; +} + +/** + `length` is the buffer element count, not the byte count. +*/ + +uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self, + uint16_t *buffer, + uint32_t length) { +// mp_printf(MP_PYTHON_PRINTER, "Copying bytes to buffer\n"); + + size_t result = 0; + size_t elementSize = common_hal_audiobusio_pdmin_get_bit_depth(self) / 8; + esp_err_t err = i2s_channel_read(self->rx_chan, buffer, length * elementSize, &result, 100); + CHECK_ESP_RESULT(err); + return result; +} + +uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t *self) { + return self->bit_depth; +} + +uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t *self) { + return self->sample_rate; +} + +#endif diff --git a/ports/espressif/common-hal/audiobusio/PDMIn.h b/ports/espressif/common-hal/audiobusio/PDMIn.h index c9069db9fd7d5..d64142b6fb0f3 100644 --- a/ports/espressif/common-hal/audiobusio/PDMIn.h +++ b/ports/espressif/common-hal/audiobusio/PDMIn.h @@ -5,3 +5,21 @@ // SPDX-License-Identifier: MIT #pragma once + +#include "py/obj.h" + +#include "common-hal/audiobusio/__init__.h" +#include "common-hal/microcontroller/Pin.h" + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + +typedef struct { + i2s_t i2s; + i2s_chan_handle_t rx_chan; + const mcu_pin_obj_t *clock_pin; + const mcu_pin_obj_t *data_pin; + uint32_t sample_rate; + uint8_t bit_depth; +} audiobusio_pdmin_obj_t; + +#endif diff --git a/ports/espressif/common-hal/audiobusio/__init__.c b/ports/espressif/common-hal/audiobusio/__init__.c index 0841ab1d2eada..d07a0b521ba9b 100644 --- a/ports/espressif/common-hal/audiobusio/__init__.c +++ b/ports/espressif/common-hal/audiobusio/__init__.c @@ -149,8 +149,8 @@ void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) { port_i2s_pause(self); self->sample = sample; self->loop = loop; - self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; - self->channel_count = audiosample_channel_count(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8; + self->channel_count = audiosample_get_channel_count(sample); bool single_buffer; bool samples_signed; uint32_t max_buffer_length; @@ -164,7 +164,7 @@ void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) { audiosample_reset_buffer(self->sample, false, 0); - uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); i2s_std_clk_config_t clk_config = I2S_STD_CLK_DEFAULT_CONFIG(sample_rate); CHECK_ESP_RESULT(i2s_channel_reconfig_std_clock(self->handle, &clk_config)); @@ -184,7 +184,7 @@ void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) { self->next_buffer_size = sizeof(starting_frame); i2s_fill_buffer(self); i2s_channel_preload_data(self->handle, &starting_frame, sizeof(uint32_t), &bytes_loaded); - preloaded += 1; + preloaded += bytes_loaded; } // enable the channel diff --git a/ports/espressif/common-hal/audioio/AudioOut.c b/ports/espressif/common-hal/audioio/AudioOut.c new file mode 100644 index 0000000000000..fb8c862ba0701 --- /dev/null +++ b/ports/espressif/common-hal/audioio/AudioOut.c @@ -0,0 +1,642 @@ + +#include + +#include "py/runtime.h" + +#include "common-hal/audioio/AudioOut.h" +#include "shared-bindings/audioio/AudioOut.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" + +#include "driver/dac_continuous.h" + +#if defined(CONFIG_IDF_TARGET_ESP32) +#define pin_CHANNEL_0 pin_GPIO25 +#define pin_CHANNEL_1 pin_GPIO26 +#elif defined(CONFIG_IDF_TARGET_ESP32S2) +#define pin_CHANNEL_0 pin_GPIO17 +#define pin_CHANNEL_1 pin_GPIO18 +#endif + +static dac_continuous_handle_t _active_handle; + +#define INCREMENT_BUF_IDX(idx) ((idx + 1) % (NUM_DMA_BUFFERS + 1)) + +static bool audioout_convert_noop( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + *out_buffer = in_buffer; + *out_buffer_size = in_buffer_size; + return false; +} + +static bool audioout_convert_u8s_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_u8s_u8m(*out_buffer, (uint8_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +static bool audioout_convert_u8m_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size * 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size * 2); + buffer_changed = true; + } + audiosample_convert_u8m_u8s(*out_buffer, (uint8_t *)in_buffer, in_buffer_size); + *out_buffer_size = in_buffer_size * 2; + return buffer_changed; +} + +static bool audioout_convert_s8m_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size); + buffer_changed = true; + } + audiosample_convert_s8m_u8m(*out_buffer, (int8_t *)in_buffer, in_buffer_size); + *out_buffer_size = in_buffer_size; + return buffer_changed; +} + +static bool audioout_convert_s8s_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_s8s_u8m(*out_buffer, (int8_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +static bool audioout_convert_s8m_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size * 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size * 2); + buffer_changed = true; + } + audiosample_convert_s8m_u8s(*out_buffer, (int8_t *)in_buffer, in_buffer_size); + *out_buffer_size = in_buffer_size * 2; + return buffer_changed; +} + +static bool audioout_convert_s8s_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size); + buffer_changed = true; + } + audiosample_convert_s8s_u8s(*out_buffer, (int8_t *)in_buffer, in_buffer_size); + *out_buffer_size = in_buffer_size; + return buffer_changed; +} + +static bool audioout_convert_u16m_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_u16m_u8m(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +static bool audioout_convert_u16m_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size); + buffer_changed = true; + } + audiosample_convert_u16m_u8s(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size; + return buffer_changed; +} + +static bool audioout_convert_u16s_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 4 > *out_buffer_size) { + *out_buffer = m_malloc(in_buffer_size / 4); + buffer_changed = true; + } + audiosample_convert_u16s_u8m(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 4); + *out_buffer_size = in_buffer_size / 4; + return buffer_changed; +} + +static bool audioout_convert_u16s_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_u16s_u8s(*out_buffer, (uint16_t *)in_buffer, in_buffer_size / 4); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +static bool audioout_convert_s16m_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_s16m_u8m(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +static bool audioout_convert_s16m_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size); + buffer_changed = true; + } + audiosample_convert_s16m_u8s(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 2); + *out_buffer_size = in_buffer_size; + return buffer_changed; +} + +static bool audioout_convert_s16s_u8m( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 4 > *out_buffer_size) { + *out_buffer = m_malloc(in_buffer_size / 4); + buffer_changed = true; + } + audiosample_convert_s16s_u8m(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 4); + *out_buffer_size = in_buffer_size / 4; + return buffer_changed; +} + +static bool audioout_convert_s16s_u8s( + void *in_buffer, + size_t in_buffer_size, + uint8_t **out_buffer, + uint32_t *out_buffer_size) { + + bool buffer_changed = false; + if (in_buffer_size / 2 > *out_buffer_size) { + *out_buffer = m_malloc_without_collect(in_buffer_size / 2); + buffer_changed = true; + } + audiosample_convert_s16s_u8s(*out_buffer, (int16_t *)in_buffer, in_buffer_size / 4); + *out_buffer_size = in_buffer_size / 2; + return buffer_changed; +} + +#define CONV_MATCH(bps, sign, ichans, ochans) ((bps & 0xf) | ((sign & 0x1) << 4) | ((ichans & 0x3) << 5) | ((ochans & 0x3) << 7)) + +static audioout_sample_convert_func_t audioout_get_samples_convert_func( + size_t in_bits_per_sample, + int in_channels, + bool in_signed, + int out_channels) { + + switch CONV_MATCH(in_bits_per_sample, in_signed, in_channels, out_channels) { + case CONV_MATCH(8, false, 1, 1): + case CONV_MATCH(8, false, 2, 2): + return audioout_convert_noop; + case CONV_MATCH(8, false, 2, 1): + return audioout_convert_u8s_u8m; + case CONV_MATCH(8, false, 1, 2): + return audioout_convert_u8m_u8s; + case CONV_MATCH(8, true, 1, 1): + return audioout_convert_s8m_u8m; + case CONV_MATCH(8, true, 2, 1): + return audioout_convert_s8s_u8m; + case CONV_MATCH(8, true, 1, 2): + return audioout_convert_s8m_u8s; + case CONV_MATCH(8, true, 2, 2): + return audioout_convert_s8s_u8s; + case CONV_MATCH(16, false, 1, 1): + return audioout_convert_u16m_u8m; + case CONV_MATCH(16, false, 1, 2): + return audioout_convert_u16m_u8s; + case CONV_MATCH(16, false, 2, 1): + return audioout_convert_u16s_u8m; + case CONV_MATCH(16, false, 2, 2): + return audioout_convert_u16s_u8s; + case CONV_MATCH(16, true, 1, 1): + return audioout_convert_s16m_u8m; + case CONV_MATCH(16, true, 1, 2): + return audioout_convert_s16m_u8s; + case CONV_MATCH(16, true, 2, 1): + return audioout_convert_s16s_u8m; + case CONV_MATCH(16, true, 2, 2): + return audioout_convert_s16s_u8s; + default: + mp_raise_RuntimeError(MP_ERROR_TEXT("audio format not supported")); + } +} + +static void audioio_audioout_start(audioio_audioout_obj_t *self) { + esp_err_t ret; + + self->playing = true; + self->paused = false; + + ret = dac_continuous_start_async_writing(self->handle); + if (ret != ESP_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to start async audio")); + } +} + +static void audioio_audioout_stop(audioio_audioout_obj_t *self, bool full_stop) { + dac_continuous_stop_async_writing(self->handle); + if (full_stop) { + self->get_buffer_index = 0; + self->put_buffer_index = 0; + self->sample_buffer = NULL; + self->sample = NULL; + self->playing = false; + self->paused = false; + } else { + self->paused = true; + } +} + +static bool audioout_fill_buffer(audioio_audioout_obj_t *self) { + if (!self->playing) { + return false; + } + + audioio_get_buffer_result_t get_buffer_result; + + uint8_t dma_buf_idx = self->get_buffer_index; + + if (dma_buf_idx == self->put_buffer_index) { + return false; + } + + uint8_t *dma_buf = self->dma_buffers[dma_buf_idx].ptr; + size_t dma_buf_size = self->dma_buffers[dma_buf_idx].size; + + self->get_buffer_index = INCREMENT_BUF_IDX(dma_buf_idx); + + bool single_channel_output = true; // whether or not we have 1 or 2 output channels + uint8_t channel = 0; // which channel right now? + uint8_t *raw_sample_buf; // raw audio sample buffer + uint32_t raw_sample_buf_size; // raw audio sample buffer len + uint8_t *sample_buf = self->scratch_buffer; // converted audio sample buffer + uint32_t sample_buf_size = self->scratch_buffer_size; // converted audio sample buffer len + size_t bytes_loaded; + esp_err_t ret; + + if (self->sample_buffer != NULL && self->sample_buffer_size > 0) { + sample_buf = self->sample_buffer; + sample_buf_size = self->sample_buffer_size; + get_buffer_result = self->sample_buffer_result; + } else { + get_buffer_result = audiosample_get_buffer(self->sample, + single_channel_output, + channel, + &raw_sample_buf, &raw_sample_buf_size); + + if (get_buffer_result == GET_BUFFER_ERROR) { + audioio_audioout_stop(self, true); + return false; + } + + bool buffer_changed; + buffer_changed = self->samples_convert( + raw_sample_buf, + raw_sample_buf_size, + &sample_buf, + &sample_buf_size); + + if (buffer_changed) { + if (self->scratch_buffer != NULL) { + m_free(self->scratch_buffer); + } + self->scratch_buffer = sample_buf; + self->scratch_buffer_size = sample_buf_size; + } + } + + if (sample_buf_size > 0) { + ret = dac_continuous_write_asynchronously(self->handle, + dma_buf, dma_buf_size, + sample_buf, sample_buf_size, + &bytes_loaded); + + if (ret != ESP_OK) { + return false; + } + } + + sample_buf_size -= bytes_loaded; + if (sample_buf_size == 0) { + sample_buf = NULL; + } else { + sample_buf += bytes_loaded; + } + + self->sample_buffer = sample_buf; + self->sample_buffer_size = sample_buf_size; + self->sample_buffer_result = get_buffer_result; + + if (get_buffer_result == GET_BUFFER_DONE && sample_buf_size == 0) { + if (self->looping) { + audiosample_reset_buffer(self->sample, true, 0); + } else { + // TODO: figure out if it is ok to call this here or do we need + // to somehow wait for all of the samples to be flushed + audioio_audioout_stop(self, true); + return false; + } + } + + return true; +} + +static void audioout_fill_buffers(audioio_audioout_obj_t *self) { + while (audioout_fill_buffer(self)) { + ; + } +} + +static void audioout_buf_callback_fun(void *user_data) { + audioio_audioout_obj_t *self = (audioio_audioout_obj_t *)user_data; + audioout_fill_buffers(self); +} + +static bool IRAM_ATTR handle_convert_done(dac_continuous_handle_t handle, const dac_event_data_t *event, void *user_data) { + audioio_audioout_obj_t *self = (audioio_audioout_obj_t *)user_data; + + uint8_t *newly_freed_dma_buf = event->buf; + size_t newly_freed_dma_buf_size = event->buf_size; + + uint8_t get_buf_idx = self->get_buffer_index; + uint8_t put_buf_idx = self->put_buffer_index; + uint8_t new_put_buf_idx = INCREMENT_BUF_IDX(put_buf_idx); + + // if the ring buffer of dma buffers is full then drop this one + if (get_buf_idx == new_put_buf_idx) { + return false; + } + + self->dma_buffers[put_buf_idx].ptr = newly_freed_dma_buf; + self->dma_buffers[put_buf_idx].size = newly_freed_dma_buf_size; + + self->put_buffer_index = new_put_buf_idx; + + background_callback_add(&self->callback, audioout_buf_callback_fun, user_data); + + return false; +} + +static void audioout_init(audioio_audioout_obj_t *self) { + dac_continuous_digi_clk_src_t clk_src = DAC_DIGI_CLK_SRC_DEFAULT; + if (self->freq_hz < 19600) { + clk_src = DAC_DIGI_CLK_SRC_APLL; + } + + dac_continuous_config_t cfg = { + .chan_mask = self->channel_mask, + .desc_num = NUM_DMA_BUFFERS, + .buf_size = DMA_BUFFER_SIZE, + .freq_hz = self->freq_hz, + .offset = 0, + .clk_src = clk_src, + .chan_mode = self->channel_mode, + }; + + esp_err_t ret; + + ret = dac_continuous_new_channels(&cfg, &self->handle); + if (ret == ESP_ERR_INVALID_ARG) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to create continuous channels: invalid arg")); + } else if (ret == ESP_ERR_INVALID_STATE) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to create continuous channels: invalid state")); + } else if (ret == ESP_ERR_NOT_FOUND) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to create continuous channels: not found")); + } else if (ret == ESP_ERR_NO_MEM) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to create continuous channels: no mem")); + } + + _active_handle = self->handle; + + dac_event_callbacks_t callbacks = { + .on_convert_done = handle_convert_done, + .on_stop = NULL, + }; + + ret = dac_continuous_register_event_callback(self->handle, &callbacks, (void *)self); + if (ret != ESP_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to register continuous events callback")); + } + + ret = dac_continuous_enable(self->handle); + if (ret != ESP_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to enable continuous")); + } +} + +void common_hal_audioio_audioout_construct(audioio_audioout_obj_t *self, + const mcu_pin_obj_t *left_channel_pin, const mcu_pin_obj_t *right_channel_pin, uint16_t quiescent_value) { + + if (_active_handle != NULL) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Can't construct AudioOut because continuous channel already open")); + } + + self->playing = false; + self->paused = false; + self->freq_hz = DEFAULT_SAMPLE_RATE; + + // The case of left_channel == right_channel is already disallowed in shared-bindings. + + if ((left_channel_pin == &pin_CHANNEL_0 && + right_channel_pin == &pin_CHANNEL_1) || + (left_channel_pin == &pin_CHANNEL_1 && + right_channel_pin == &pin_CHANNEL_0)) { + self->channel_mask = DAC_CHANNEL_MASK_ALL; + self->num_channels = 2; + self->channel_mode = DAC_CHANNEL_MODE_ALTER; + } else if (left_channel_pin == &pin_CHANNEL_0 && + right_channel_pin == NULL) { + self->channel_mask = DAC_CHANNEL_MASK_CH0; + self->num_channels = 1; + self->channel_mode = DAC_CHANNEL_MODE_SIMUL; + } else if (left_channel_pin == &pin_CHANNEL_1 && + right_channel_pin == NULL) { + self->channel_mask = DAC_CHANNEL_MASK_CH1; + self->num_channels = 1; + self->channel_mode = DAC_CHANNEL_MODE_SIMUL; + } else { + raise_ValueError_invalid_pin(); + } + + audioout_init(self); +} + +bool common_hal_audioio_audioout_deinited(audioio_audioout_obj_t *self) { + return self->handle == NULL; +} + +void common_hal_audioio_audioout_deinit(audioio_audioout_obj_t *self) { + if (common_hal_audioio_audioout_deinited(self)) { + return; + } + + if (self->playing) { + common_hal_audioio_audioout_stop(self); + } + dac_continuous_disable(self->handle); + dac_continuous_del_channels(self->handle); + if (self->scratch_buffer != NULL) { + m_free(self->scratch_buffer); + self->scratch_buffer = NULL; + self->scratch_buffer_size = 0; + } + self->handle = NULL; + _active_handle = NULL; +} + +void common_hal_audioio_audioout_play(audioio_audioout_obj_t *self, + mp_obj_t sample, bool loop) { + + if (self->playing) { + mp_raise_RuntimeError(MP_ERROR_TEXT("already playing")); + } + + size_t samples_size; + uint8_t channel_count; + bool samples_signed; + bool _single_buffer; + uint32_t _max_buffer_length; + uint8_t _spacing; + uint32_t freq_hz; + + audiosample_reset_buffer(sample, true, 0); + + self->sample = sample; + self->looping = loop; + freq_hz = audiosample_get_sample_rate(self->sample); + + // Workaround: always reset the DAC completely between plays, + // due to a bug that causes the left and right channels to be swapped randomly. + // See https://github.com/espressif/esp-idf/issues/11425 + // TODO: Remove the `true` when this issue is fixed. + if (true || freq_hz != self->freq_hz) { + common_hal_audioio_audioout_deinit(self); + self->freq_hz = freq_hz; + audioout_init(self); + } + + samples_size = audiosample_get_bits_per_sample(self->sample); + channel_count = audiosample_get_channel_count(self->sample); + audiosample_get_buffer_structure(self->sample, false, + &_single_buffer, &samples_signed, + &_max_buffer_length, &_spacing); + + self->samples_convert = audioout_get_samples_convert_func( + samples_size, + channel_count, + samples_signed, + self->num_channels); + + audioio_audioout_start(self); +} + +void common_hal_audioio_audioout_pause(audioio_audioout_obj_t *self) { + if (!self->playing || self->paused) { + return; + } + audioio_audioout_stop(self, false); +} + +void common_hal_audioio_audioout_resume(audioio_audioout_obj_t *self) { + if (!self->playing || !self->paused) { + return; + } + audioio_audioout_start(self); +} + +bool common_hal_audioio_audioout_get_paused(audioio_audioout_obj_t *self) { + return self->playing && self->paused; +} + +void common_hal_audioio_audioout_stop(audioio_audioout_obj_t *self) { + if (!self->playing) { + return; + } + audioio_audioout_stop(self, true); +} + +bool common_hal_audioio_audioout_get_playing(audioio_audioout_obj_t *self) { + return self->playing && !self->paused; +} diff --git a/ports/espressif/common-hal/audioio/AudioOut.h b/ports/espressif/common-hal/audioio/AudioOut.h new file mode 100644 index 0000000000000..b35d9ffdcf7f9 --- /dev/null +++ b/ports/espressif/common-hal/audioio/AudioOut.h @@ -0,0 +1,47 @@ + +#pragma once + +#include "common-hal/microcontroller/Pin.h" + +#include "py/obj.h" + +#include "supervisor/background_callback.h" +#include "shared-module/audiocore/__init__.h" + +#include "driver/dac_continuous.h" + + +#define NUM_DMA_BUFFERS 6 +#define DMA_BUFFER_SIZE 512 + +#define DEFAULT_SAMPLE_RATE 32000 + +typedef bool (*audioout_sample_convert_func_t)(void *in_buffer, size_t in_buffer_size, uint8_t **out_buffer, uint32_t *out_buffer_size); + +typedef struct { + uint8_t *ptr; + size_t size; +} buf_info_t; + +typedef struct { + mp_obj_base_t base; + dac_continuous_handle_t handle; + dac_channel_mask_t channel_mask; + uint32_t freq_hz; + uint8_t num_channels; + dac_continuous_channel_mode_t channel_mode; + mp_obj_t sample; + bool playing; + bool paused; + bool looping; + uint8_t *sample_buffer; + size_t sample_buffer_size; + audioio_get_buffer_result_t sample_buffer_result; + uint8_t get_buffer_index; + uint8_t put_buffer_index; + buf_info_t dma_buffers[NUM_DMA_BUFFERS + 1]; + background_callback_t callback; + uint8_t *scratch_buffer; + size_t scratch_buffer_size; + audioout_sample_convert_func_t samples_convert; +} audioio_audioout_obj_t; diff --git a/ports/espressif/common-hal/audioio/__init__.c b/ports/espressif/common-hal/audioio/__init__.c new file mode 100644 index 0000000000000..f7af773c4b839 --- /dev/null +++ b/ports/espressif/common-hal/audioio/__init__.c @@ -0,0 +1,2 @@ + +#include "common-hal/audioio/__init__.h" diff --git a/ports/espressif/common-hal/audioio/__init__.h b/ports/espressif/common-hal/audioio/__init__.h new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/common-hal/busio/I2C.c b/ports/espressif/common-hal/busio/I2C.c index d9ad880d22dec..890f9339c2254 100644 --- a/ports/espressif/common-hal/busio/I2C.c +++ b/ports/espressif/common-hal/busio/I2C.c @@ -6,15 +6,21 @@ #include "shared-bindings/busio/I2C.h" #include "py/mperrno.h" +#include "py/mphal.h" #include "py/runtime.h" #include "components/driver/i2c/include/driver/i2c.h" +#include "bindings/espidf/__init__.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, - const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout_us) { + + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + // Pins 45 and 46 are "strapping" pins that impact start up behavior. They usually need to // be pulled-down so pulling them up for I2C is a bad idea. To make this hard, we don't // support I2C on these pins. @@ -60,48 +66,47 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, } #endif + + i2c_master_bus_config_t config = { + .i2c_port = -1, // auto + .sda_io_num = sda->number, + .scl_io_num = scl->number, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .flags = { + #if CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP + .enable_internal_pullup = true, /*!< Internal GPIO pull mode for I2C sda signal*/ + #else + .enable_internal_pullup = false, /*!< Internal GPIO pull mode for I2C sda signal*/ + #endif + } + }; + esp_err_t result = i2c_new_master_bus(&config, &self->handle); + + if (result == ESP_ERR_NOT_FOUND) { + mp_raise_ValueError(MP_ERROR_TEXT("All I2C peripherals are in use")); + } + CHECK_ESP_RESULT(result); + self->xSemaphore = xSemaphoreCreateMutex(); if (self->xSemaphore == NULL) { + i2c_del_master_bus(self->handle); + self->handle = NULL; mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to create lock")); } self->sda_pin = sda; self->scl_pin = scl; - self->i2c_num = peripherals_i2c_get_free_num(); - self->has_lock = 0; - - if (self->i2c_num == I2C_NUM_MAX) { - mp_raise_ValueError(MP_ERROR_TEXT("All I2C peripherals are in use")); - } - - // Delete any previous driver. - i2c_driver_delete(self->i2c_num); - - const i2c_config_t i2c_conf = { - .mode = I2C_MODE_MASTER, - .sda_io_num = self->sda_pin->number, - .scl_io_num = self->scl_pin->number, - #if CIRCUITPY_I2C_ALLOW_INTERNAL_PULL_UP - .sda_pullup_en = GPIO_PULLUP_ENABLE, /*!< Internal GPIO pull mode for I2C sda signal*/ - .scl_pullup_en = GPIO_PULLUP_ENABLE, /*!< Internal GPIO pull mode for I2C scl signal*/ - #else - .sda_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C sda signal*/ - .scl_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C scl signal*/ - #endif - - .master = { - .clk_speed = frequency, - } - }; + self->has_lock = false; + self->frequency = frequency; - // Initialize I2C. - esp_err_t err = peripherals_i2c_init(self->i2c_num, &i2c_conf); - if (err != ESP_OK) { - if (err == ESP_FAIL) { - mp_raise_OSError(MP_EIO); - } else { - mp_raise_RuntimeError(MP_ERROR_TEXT("init I2C")); - } - } + // Ignore the passed-in clock-stretching timeout. It is not used, as documented in shared-bindings. + // Instead use 1000 ms, which is standard across ports. + // self->timeout_ms = timeout_us / 1000; + // // Round up timeout to nearest ms. + // if (timeout_us % 1000 != 0) { + // self->timeout_ms += 1; + // } + self->timeout_ms = 1000; claim_pin(sda); claim_pin(scl); @@ -111,36 +116,44 @@ bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { return self->sda_pin == NULL; } +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->sda_pin = NULL; +} + void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { if (common_hal_busio_i2c_deinited(self)) { return; } - peripherals_i2c_deinit(self->i2c_num); + i2c_del_master_bus(self->handle); + self->handle = NULL; + + // Release the mutex before we delete it. Otherwise FreeRTOS gets unhappy. + xSemaphoreGive(self->xSemaphore); + vSemaphoreDelete(self->xSemaphore); + self->xSemaphore = NULL; + self->has_lock = false; common_hal_reset_pin(self->sda_pin); common_hal_reset_pin(self->scl_pin); - self->sda_pin = NULL; - self->scl_pin = NULL; -} - -static esp_err_t i2c_zero_length_write(busio_i2c_obj_t *self, uint8_t addr, TickType_t timeout) { - // i2c_master_write_to_device() won't do zero-length writes, so we do it by hand. - i2c_cmd_handle_t cmd = i2c_cmd_link_create(); - i2c_master_start(cmd); - i2c_master_write_byte(cmd, addr << 1, true); - i2c_master_stop(cmd); - esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, timeout); - i2c_cmd_link_delete(cmd); - return result; + common_hal_busio_i2c_mark_deinit(self); } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { - esp_err_t result = i2c_zero_length_write(self, addr, 1); + esp_err_t result = i2c_master_probe(self->handle, addr, 10); + + #if defined(CONFIG_IDF_TARGET_ESP32S2) + // ESP32-S2 gives spurious results when probe is called multiple times in succession without this delay. + mp_hal_delay_ms(1); + #endif + return result == ESP_OK; } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } if (self->has_lock) { return false; } @@ -153,45 +166,74 @@ bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) { } void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return; + } xSemaphoreGive(self->xSemaphore); self->has_lock = false; } -static uint8_t convert_esp_err(esp_err_t result) { +static mp_negative_errno_t convert_esp_err(esp_err_t result) { switch (result) { case ESP_OK: return 0; case ESP_FAIL: - return MP_ENODEV; + return -MP_ENODEV; case ESP_ERR_TIMEOUT: - return MP_ETIMEDOUT; + return -MP_ETIMEDOUT; default: - return MP_EIO; + return -MP_EIO; } } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { - return convert_esp_err(len == 0 - ? i2c_zero_length_write(self, addr, 100) - : i2c_master_write_to_device(self->i2c_num, (uint8_t)addr, data, len, 100 /* wait in ticks */) - ); +static size_t _transaction_duration_ms(size_t frequency, size_t len) { + size_t khz = frequency / 1000; + size_t bytes_per_ms = khz / 8; + // + 1 for the address byte + return (len + 1) / bytes_per_ms + 1000; +} + +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { + i2c_device_config_t dev_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = addr, + .scl_speed_hz = self->frequency + }; + i2c_master_dev_handle_t dev_handle; + CHECK_ESP_RESULT(i2c_master_bus_add_device(self->handle, &dev_config, &dev_handle)); + esp_err_t result = i2c_master_transmit(dev_handle, data, len, _transaction_duration_ms(self->frequency, len) + self->timeout_ms); + CHECK_ESP_RESULT(i2c_master_bus_rm_device(dev_handle)); + return convert_esp_err(result); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { - return convert_esp_err( - i2c_master_read_from_device(self->i2c_num, (uint8_t)addr, data, len, 100 /* wait in ticks */)); +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { + i2c_device_config_t dev_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = addr, + .scl_speed_hz = self->frequency + }; + i2c_master_dev_handle_t dev_handle; + CHECK_ESP_RESULT(i2c_master_bus_add_device(self->handle, &dev_config, &dev_handle)); + esp_err_t result = i2c_master_receive(dev_handle, data, len, _transaction_duration_ms(self->frequency, len) + self->timeout_ms); + CHECK_ESP_RESULT(i2c_master_bus_rm_device(dev_handle)); + return convert_esp_err(result); } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - return convert_esp_err( - i2c_master_write_read_device(self->i2c_num, (uint8_t)addr, - out_data, out_len, in_data, in_len, 100 /* wait in ticks */)); + i2c_device_config_t dev_config = { + .dev_addr_length = I2C_ADDR_BIT_LEN_7, + .device_address = addr, + .scl_speed_hz = self->frequency + }; + i2c_master_dev_handle_t dev_handle; + CHECK_ESP_RESULT(i2c_master_bus_add_device(self->handle, &dev_config, &dev_handle)); + esp_err_t result = i2c_master_transmit_receive(dev_handle, out_data, out_len, in_data, in_len, _transaction_duration_ms(self->frequency, out_len) + _transaction_duration_ms(self->frequency, in_len) + self->timeout_ms); + CHECK_ESP_RESULT(i2c_master_bus_rm_device(dev_handle)); + return convert_esp_err(result); } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - never_reset_i2c(self->i2c_num); - common_hal_never_reset_pin(self->scl_pin); common_hal_never_reset_pin(self->sda_pin); } diff --git a/ports/espressif/common-hal/busio/I2C.h b/ports/espressif/common-hal/busio/I2C.h index 6e040224ece20..25d9791f2521d 100644 --- a/ports/espressif/common-hal/busio/I2C.h +++ b/ports/espressif/common-hal/busio/I2C.h @@ -13,13 +13,15 @@ #include "freertos/semphr.h" #include "py/obj.h" -#include "peripherals/i2c.h" +#include "driver/i2c_master.h" typedef struct { mp_obj_base_t base; const mcu_pin_obj_t *scl_pin; const mcu_pin_obj_t *sda_pin; - i2c_port_t i2c_num; + size_t timeout_ms; + size_t frequency; + i2c_master_bus_handle_t handle; SemaphoreHandle_t xSemaphore; bool has_lock; } busio_i2c_obj_t; diff --git a/ports/espressif/common-hal/busio/SPI.c b/ports/espressif/common-hal/busio/SPI.c index 6439ca4112993..21dc8c383794e 100644 --- a/ports/espressif/common-hal/busio/SPI.c +++ b/ports/espressif/common-hal/busio/SPI.c @@ -16,26 +16,12 @@ #define SPI_MAX_DMA_BITS (SPI_MAX_DMA_LEN * 8) #define MAX_SPI_TRANSACTIONS 10 -static bool spi_never_reset[SOC_SPI_PERIPH_NUM]; static spi_device_handle_t spi_handle[SOC_SPI_PERIPH_NUM]; -static StaticSemaphore_t spi_mutex[SOC_SPI_PERIPH_NUM]; static bool spi_bus_is_free(spi_host_device_t host_id) { return spi_bus_get_attr(host_id) == NULL; } -void spi_reset(void) { - for (spi_host_device_t host_id = SPI2_HOST; host_id < SOC_SPI_PERIPH_NUM; host_id++) { - if (spi_never_reset[host_id]) { - continue; - } - if (!spi_bus_is_free(host_id)) { - spi_bus_remove_device(spi_handle[host_id]); - spi_bus_free(host_id); - } - } -} - static void set_spi_config(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { // 128 is a 50% duty cycle. @@ -61,6 +47,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + const spi_bus_config_t bus_config = { .mosi_io_num = mosi != NULL ? mosi->number : -1, .miso_io_num = miso != NULL ? miso->number : -1, @@ -90,6 +79,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, raise_ValueError_invalid_pins(); } + self->mutex = xSemaphoreCreateMutex(); + if (self->mutex == NULL) { + spi_bus_free(self->host_id); + mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to create lock")); + } + set_spi_config(self, 250000, 0, 0, 8); self->MOSI = mosi; @@ -103,12 +98,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, claim_pin(miso); } claim_pin(clock); - - self->mutex = xSemaphoreCreateMutexStatic(&spi_mutex[self->host_id]); } void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - spi_never_reset[self->host_id] = true; common_hal_never_reset_pin(self->clock); if (self->MOSI != NULL) { common_hal_never_reset_pin(self->MOSI); @@ -122,6 +114,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock = NULL; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; @@ -132,11 +128,10 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { RUN_BACKGROUND_TASKS; } - // Mark us as deinit early in case we are used in an interrupt. + // Mark as deinit early in case we are used in an interrupt. common_hal_reset_pin(self->clock); - self->clock = NULL; + common_hal_busio_spi_mark_deinit(self); - spi_never_reset[self->host_id] = false; spi_bus_remove_device(spi_handle[self->host_id]); spi_bus_free(self->host_id); @@ -162,19 +157,27 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, return true; } -bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { +// Wait as long as needed for the lock. This is used by SD card access from USB. +// Overrides the default busy-wait implementation in shared-bindings/busio/SPI.c +bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms) { if (common_hal_busio_spi_deinited(self)) { return false; } - return xSemaphoreTake(self->mutex, 1) == pdTRUE; + return xSemaphoreTake(self->mutex, pdMS_TO_TICKS(timeout_ms)) == pdTRUE; +} + +bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + return common_hal_busio_spi_wait_for_lock(self, 0); } bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) { - return self->mutex != NULL && xSemaphoreGetMutexHolder(self->mutex) == xTaskGetCurrentTaskHandle(); + return (self->mutex != NULL) && (xSemaphoreGetMutexHolder(self->mutex) == xTaskGetCurrentTaskHandle()); } void common_hal_busio_spi_unlock(busio_spi_obj_t *self) { - xSemaphoreGive(self->mutex); + if (self->mutex != NULL) { + xSemaphoreGive(self->mutex); + } } bool common_hal_busio_spi_write(busio_spi_obj_t *self, diff --git a/ports/espressif/common-hal/busio/SPI.h b/ports/espressif/common-hal/busio/SPI.h index 820f29333c756..ac2f404042b2f 100644 --- a/ports/espressif/common-hal/busio/SPI.h +++ b/ports/espressif/common-hal/busio/SPI.h @@ -25,5 +25,3 @@ typedef struct { SemaphoreHandle_t mutex; } busio_spi_obj_t; - -void spi_reset(void); diff --git a/ports/espressif/common-hal/busio/UART.c b/ports/espressif/common-hal/busio/UART.c index cf29b50cfe542..ad5e6fcef1bbf 100644 --- a/ports/espressif/common-hal/busio/UART.c +++ b/ports/espressif/common-hal/busio/UART.c @@ -106,9 +106,22 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, self->timeout_ms = timeout * 1000; self->uart_num = UART_NUM_MAX; - for (uart_port_t num = 0; num < UART_NUM_MAX; num++) { + + // ESP32-C6 and ESP32-P4 both have a single LP (low power) UART, which is + // limited in what it can do and which pins it can use. Ignore it for now. + // Its UART number is higher than the numbers for the regular ("HP", high-power) UARTs. + + // SOC_UART_LP_NUM is not defined for chips without an LP UART. + #if defined(SOC_UART_LP_NUM) && (SOC_UART_LP_NUM >= 1) + #define UART_LIMIT LP_UART_NUM_0 + #else + #define UART_LIMIT UART_NUM_MAX + #endif + + for (uart_port_t num = 0; num < UART_LIMIT; num++) { if (!uart_is_driver_installed(num)) { self->uart_num = num; + break; } } if (self->uart_num == UART_NUM_MAX) { @@ -224,6 +237,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, int rx_num = -1; int rts_num = -1; int cts_num = -1; + if (have_tx) { claim_pin(tx); self->tx_pin = tx; @@ -254,9 +268,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self, self->rts_pin = rs485_dir; rts_num = rs485_dir->number; } + if (uart_set_pin(self->uart_num, tx_num, rx_num, rts_num, cts_num) != ESP_OK) { + // Uninstall driver and clean up. + common_hal_busio_uart_deinit(self); raise_ValueError_invalid_pins(); } + if (have_rx) { // On ESP32-C3 and ESP32-S3 (at least), a junk byte with zero or more consecutive 1's can be // generated, even if the pin is pulled high (normal UART resting state) to begin with. diff --git a/ports/espressif/common-hal/digitalio/DigitalInOut.c b/ports/espressif/common-hal/digitalio/DigitalInOut.c index ed537419405b3..e4272ba1ff5ff 100644 --- a/ports/espressif/common-hal/digitalio/DigitalInOut.c +++ b/ports/espressif/common-hal/digitalio/DigitalInOut.c @@ -11,8 +11,11 @@ #include "hal/gpio_hal.h" static bool _pin_is_input(uint8_t pin_number) { - const uint32_t iomux = READ_PERI_REG(GPIO_PIN_MUX_REG[pin_number]); - return (iomux & FUN_IE) != 0; + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)pin_number, &config) != ESP_OK) { + return false; + } + return config.ie; } void digitalio_digitalinout_preserve_for_deep_sleep(size_t n_dios, digitalio_digitalinout_obj_t *preserve_dios[]) { @@ -113,10 +116,12 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode( digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( digitalio_digitalinout_obj_t *self) { - if (GPIO_HAL_GET_HW(GPIO_PORT_0)->pin[self->pin->number].pad_driver == 1) { + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)self->pin->number, &config) != ESP_OK) { + // Should it fail closed or open? return DRIVE_MODE_OPEN_DRAIN; } - return DRIVE_MODE_PUSH_PULL; + return config.od ? DRIVE_MODE_OPEN_DRAIN : DRIVE_MODE_PUSH_PULL; } digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( @@ -134,11 +139,10 @@ digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( digitalio_digitalinout_obj_t *self) { - gpio_num_t gpio_num = self->pin->number; - if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU)) { - return PULL_UP; - } else if (REG_GET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD)) { - return PULL_DOWN; + gpio_io_config_t config; + if (gpio_get_io_config((gpio_num_t)self->pin->number, &config) != ESP_OK) { + // Should it fail closed or open? + return PULL_NONE; } - return PULL_NONE; + return config.pd ? PULL_DOWN : PULL_UP; } diff --git a/ports/espressif/common-hal/espcamera/Camera.c b/ports/espressif/common-hal/espcamera/Camera.c index bcf4732fcd8b2..5b45a26951edc 100644 --- a/ports/espressif/common-hal/espcamera/Camera.c +++ b/ports/espressif/common-hal/espcamera/Camera.c @@ -77,13 +77,16 @@ void common_hal_espcamera_camera_construct( self->i2c = i2c; - self->camera_config.pin_pwdn = common_hal_mcu_pin_number(powerdown_pin); - self->camera_config.pin_reset = common_hal_mcu_pin_number(reset_pin); - self->camera_config.pin_xclk = common_hal_mcu_pin_number(external_clock_pin); + // These pins might be NULL because they were not specified. + // Note that common_hal_mcu_pin_number() returns NO_PIN (- =1) if pass NULL, but as a `uint8_t`, + // so it becomes 255. The camera driver expects non-specified pins to be < 0. + // So we have to set the pins to NO_PIN explicitly, + // instead of relying on the return value from common_hal_mcu_pin_number(). + self->camera_config.pin_pwdn = powerdown_pin ? common_hal_mcu_pin_number(powerdown_pin) : NO_PIN; + self->camera_config.pin_reset = reset_pin ? common_hal_mcu_pin_number(reset_pin) : NO_PIN; + self->camera_config.pin_xclk = external_clock_pin ? common_hal_mcu_pin_number(external_clock_pin) : NO_PIN; - self->camera_config.pin_sccb_sda = NO_PIN; - self->camera_config.pin_sccb_scl = NO_PIN; - /* sccb i2c port set below */ + self->camera_config.sccb_i2c_master_bus_handle = self->i2c->handle; self->camera_config.pin_d7 = data_pins[7]; self->camera_config.pin_d6 = data_pins[6]; @@ -106,7 +109,7 @@ void common_hal_espcamera_camera_construct( self->camera_config.fb_count = framebuffer_count; self->camera_config.grab_mode = grab_mode; - self->camera_config.sccb_i2c_port = i2c->i2c_num; + i2c_lock(self); esp_err_t result = esp_camera_init(&self->camera_config); @@ -122,6 +125,7 @@ extern void common_hal_espcamera_camera_deinit(espcamera_camera_obj_t *self) { common_hal_pwmio_pwmout_deinit(&self->pwm); + // Does nothing if pin is NO_PIN (-1). reset_pin_number(self->camera_config.pin_pwdn); reset_pin_number(self->camera_config.pin_reset); reset_pin_number(self->camera_config.pin_xclk); diff --git a/ports/espressif/common-hal/espidf/__init__.c b/ports/espressif/common-hal/espidf/__init__.c index 8af0318fed018..83e30657750dd 100644 --- a/ports/espressif/common-hal/espidf/__init__.c +++ b/ports/espressif/common-hal/espidf/__init__.c @@ -27,7 +27,11 @@ static size_t psram_size_usable(void) { #ifdef CONFIG_SPIRAM /* PSRAM chip may be larger than the size we can map into address space */ + #ifdef CONFIG_IDF_TARGET_ESP32P4 + size_t s = esp_psram_get_size(); + #else size_t s = MIN(esp_psram_get_size(), SOC_EXTRAM_DATA_SIZE); + #endif return s - esp_himem_reserved_area_size(); #else return 0; diff --git a/ports/espressif/common-hal/espnow/ESPNow.c b/ports/espressif/common-hal/espnow/ESPNow.c index 79bded96fb41d..ae11db250321c 100644 --- a/ports/espressif/common-hal/espnow/ESPNow.c +++ b/ports/espressif/common-hal/espnow/ESPNow.c @@ -56,7 +56,7 @@ typedef struct { // Callback triggered when a sent packet is acknowledged by the peer (or not). // Just count the number of responses and number of failures. // These are used in the send() logic. -static void send_cb(const uint8_t *mac, esp_now_send_status_t status) { +static void send_cb(const esp_now_send_info_t *tx_info, esp_now_send_status_t status) { espnow_obj_t *self = MP_STATE_PORT(espnow_singleton); if (status == ESP_NOW_SEND_SUCCESS) { self->send_success++; diff --git a/ports/espressif/common-hal/frequencyio/FrequencyIn.c b/ports/espressif/common-hal/frequencyio/FrequencyIn.c index 9664434850489..72fb36e0b9171 100644 --- a/ports/espressif/common-hal/frequencyio/FrequencyIn.c +++ b/ports/espressif/common-hal/frequencyio/FrequencyIn.c @@ -117,7 +117,7 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t self->pin = pin->number; self->capture_period_ms = capture_period_ms; - self->internal_data = heap_caps_malloc(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL, sizeof(_internal_data_t)); + self->internal_data = heap_caps_malloc(sizeof(_internal_data_t), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); if (self->internal_data == NULL) { raise_esp_error(ESP_ERR_NO_MEM); } diff --git a/ports/espressif/common-hal/mdns/Server.c b/ports/espressif/common-hal/mdns/Server.c index 81a4415cecd86..e8c34ee0885ce 100644 --- a/ports/espressif/common-hal/mdns/Server.c +++ b/ports/espressif/common-hal/mdns/Server.c @@ -33,10 +33,9 @@ void mdns_server_construct(mdns_server_obj_t *self, bool workflow) { } _active_object = self; - uint8_t mac[6]; - esp_netif_get_mac(common_hal_wifi_radio_obj.netif, mac); - snprintf(self->default_hostname, sizeof(self->default_hostname), "cpy-%02x%02x%02x", mac[3], mac[4], mac[5]); - common_hal_mdns_server_set_hostname(self, self->default_hostname); + // Match the netif hostname set when `import wifi` was called. + esp_netif_get_hostname(common_hal_wifi_radio_obj.netif, &self->hostname); + common_hal_mdns_server_set_hostname(self, self->hostname); self->inited = true; diff --git a/ports/espressif/common-hal/mdns/Server.h b/ports/espressif/common-hal/mdns/Server.h index 42ffd878d13ae..f364a539c9179 100644 --- a/ports/espressif/common-hal/mdns/Server.h +++ b/ports/espressif/common-hal/mdns/Server.h @@ -12,7 +12,6 @@ typedef struct { mp_obj_base_t base; const char *hostname; const char *instance_name; - char default_hostname[sizeof("cpy-XXXXXX")]; // Track if this object owns access to the underlying MDNS service. bool inited; } mdns_server_obj_t; diff --git a/ports/espressif/common-hal/microcontroller/Pin.c b/ports/espressif/common-hal/microcontroller/Pin.c index 897d21e476c0a..f995e65545d3c 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.c +++ b/ports/espressif/common-hal/microcontroller/Pin.c @@ -77,6 +77,15 @@ static uint64_t _in_use_pin_mask; #define GPIO_SEL_47 ((uint64_t)PIN_BIT(47)) /*!< Pin 47 selected */ #define GPIO_SEL_48 ((uint64_t)PIN_BIT(48)) /*!< Pin 48 selected */ #endif +#if SOC_GPIO_PIN_COUNT > 49 +#define GPIO_SEL_49 ((uint64_t)PIN_BIT(49)) /*!< Pin 49 selected */ +#define GPIO_SEL_50 ((uint64_t)PIN_BIT(50)) /*!< Pin 50 selected */ +#define GPIO_SEL_51 ((uint64_t)PIN_BIT(51)) /*!< Pin 51 selected */ +#define GPIO_SEL_52 ((uint64_t)PIN_BIT(52)) /*!< Pin 52 selected */ +#define GPIO_SEL_53 ((uint64_t)PIN_BIT(53)) /*!< Pin 53 selected */ +#define GPIO_SEL_54 ((uint64_t)PIN_BIT(54)) /*!< Pin 54 selected */ +#define GPIO_SEL_55 ((uint64_t)PIN_BIT(55)) /*!< Pin 55 selected */ +#endif // Bit mask of all pins that should never EVER be reset. // Typically these are SPI flash and PSRAM control pins, and communication pins. @@ -146,6 +155,29 @@ static const uint64_t pin_mask_reset_forbidden = #endif #endif // ESP32C6 + #if defined(CONFIG_IDF_TARGET_ESP32C61) + // Never ever reset pins used to communicate with SPI flash. + GPIO_SEL_15 | // SPICS0 (flash CS#) + GPIO_SEL_16 | // SPIQ (MISO/SIO1) + GPIO_SEL_17 | // SPIWP (WP#/SIO2) + GPIO_SEL_19 | // SPIHD (HOLD#/SIO3) + GPIO_SEL_20 | // SPICLK (CLK) + GPIO_SEL_21 | // SPID (MOSI/SIO0) + #if CIRCUITPY_ESP_USB_SERIAL_JTAG + // Never ever reset serial/JTAG communication pins. + GPIO_SEL_12 | // USB D- + GPIO_SEL_13 | // USB D+ + #endif + #if defined(CONFIG_SPIRAM) + GPIO_SEL_14 | // SPICS1 (PSRAM CS#); keep if PSRAM in use + #endif + #if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) && CONFIG_ESP_CONSOLE_UART_DEFAULT && CONFIG_ESP_CONSOLE_UART_NUM == 0 + // Never reset debug UART/console pins. + GPIO_SEL_10 | + GPIO_SEL_11 | + #endif + #endif // ESP32C6 + #if defined(CONFIG_IDF_TARGET_ESP32H2) // Never ever reset pins used to communicate with the in-package SPI flash. GPIO_SEL_15 | @@ -171,6 +203,36 @@ static const uint64_t pin_mask_reset_forbidden = #endif #endif // ESP32H2 + #if defined(CONFIG_IDF_TARGET_ESP32P4) + // SPI flash is on dedicated pins. + + // USB is on the FS OTG + #if CIRCUITPY_USB_DEVICE_INSTANCE == 0 + #if CIRCUITPY_ESP32P4_SWAP_LSFS == 1 + // We leave 24 and 25 alone in addition to 26 and 27 when swapped. It doesn't work otherwise. (Not sure why.) + GPIO_SEL_24 | // USB D- + GPIO_SEL_25 | // USB D+ + #endif + GPIO_SEL_26 | // USB D- + GPIO_SEL_27 | // USB D+ + #endif + #if CIRCUITPY_ESP_USB_SERIAL_JTAG || (defined(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) && CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG) + // Never ever reset serial/JTAG communication pins. + #if CIRCUITPY_ESP32P4_SWAP_LSFS == 1 + GPIO_SEL_26 | // USB D- + GPIO_SEL_27 | // USB D+ + #else + GPIO_SEL_24 | // USB D- + GPIO_SEL_25 | // USB D+ + #endif + #endif + #if defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) && CONFIG_ESP_CONSOLE_UART_DEFAULT && CONFIG_ESP_CONSOLE_UART_NUM == 0 + // Never reset debug UART/console pins. + GPIO_SEL_37 | + GPIO_SEL_38 | + #endif + #endif // ESP32P4 + #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) #if CIRCUITPY_USB_DEVICE // Never ever reset USB pins. @@ -350,9 +412,8 @@ void reset_all_pins(void) { gpio_deep_sleep_hold_dis(); #endif - for (uint8_t i = 0; i < GPIO_PIN_COUNT; i++) { - uint32_t iomux_address = GPIO_PIN_MUX_REG[i]; - if (iomux_address == 0 || + for (gpio_num_t i = 0; i < SOC_GPIO_PIN_COUNT; i++) { + if (!GPIO_IS_VALID_GPIO(i) || _never_reset(i) || _skip_reset_once(i) || _preserved_pin(i)) { @@ -393,3 +454,16 @@ bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t *pin) { return pin ? pin->number : NO_PIN; } + +void config_pin_as_output_with_level(gpio_num_t pin_number, bool level) { + gpio_config_t cfg = { + .pin_bit_mask = BIT64(pin_number), + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = false, + .pull_down_en = false, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); + + gpio_set_level(pin_number, level); +} diff --git a/ports/espressif/common-hal/microcontroller/Pin.h b/ports/espressif/common-hal/microcontroller/Pin.h index 662a3a84eb9b0..aba7fa6832384 100644 --- a/ports/espressif/common-hal/microcontroller/Pin.h +++ b/ports/espressif/common-hal/microcontroller/Pin.h @@ -36,3 +36,7 @@ extern void clear_pin_preservations(void); // Return true to indicate that the pin was reset. Returning false will lead to // the port-default reset behavior. extern bool espressif_board_reset_pin_number(gpio_num_t pin_number); + +// Configure the IOMUX for the pin as GPIO, set the pin as output, and then set output the level. +// This ensures the IOMUX setting is correct. +extern void config_pin_as_output_with_level(gpio_num_t pin_number, bool level); diff --git a/ports/espressif/common-hal/microcontroller/Processor.c b/ports/espressif/common-hal/microcontroller/Processor.c index 97b41a97c3aed..0056465f1c5cd 100644 --- a/ports/espressif/common-hal/microcontroller/Processor.c +++ b/ports/espressif/common-hal/microcontroller/Processor.c @@ -59,7 +59,7 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { // If the requested frequency is not supported by the hardware, return the next lower supported frequency static uint32_t get_valid_cpu_frequency(uint32_t requested_freq_mhz) { - #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) uint32_t valid_cpu_frequencies[] = {20, 40, 80, 160}; #elif defined(CONFIG_IDF_TARGET_ESP32C2) uint32_t valid_cpu_frequencies[] = {20, 40, 80, 120}; @@ -107,11 +107,14 @@ void common_hal_mcu_processor_set_frequency(mcu_processor_obj_t *self, uint32_t } #endif +#ifndef CONFIG_IDF_TARGET_ESP32P4 static uint8_t swap_nibbles(uint8_t v) { return ((v << 4) | (v >> 4)) & 0xff; } +#endif void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { + #ifndef CONFIG_IDF_TARGET_ESP32P4 memset(raw_id, 0, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH); uint8_t *ptr = &raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH - 1]; @@ -123,6 +126,8 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SYS_0_REG); #elif defined(CONFIG_IDF_TARGET_ESP32C2) uint32_t mac_address_part = REG_READ(EFUSE_RD_BLK2_DATA0_REG); + #elif defined(CONFIG_IDF_TARGET_ESP32C61) + uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SYS0_REG); #else uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_0_REG); #endif @@ -142,6 +147,8 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { mac_address_part = REG_READ(EFUSE_RD_MAC_SYS_1_REG); #elif defined(CONFIG_IDF_TARGET_ESP32C2) mac_address_part = REG_READ(EFUSE_RD_BLK2_DATA1_REG); + #elif defined(CONFIG_IDF_TARGET_ESP32C61) + mac_address_part = REG_READ(EFUSE_RD_MAC_SYS1_REG); #else mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_1_REG); #endif @@ -149,6 +156,10 @@ void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8; *ptr-- = swap_nibbles(mac_address_part & 0xff); + #else + // TODO: Get UID for ESP32-P4. + return; + #endif } mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { diff --git a/ports/espressif/common-hal/microcontroller/__init__.c b/ports/espressif/common-hal/microcontroller/__init__.c index 4375f942f5504..9b50cd7b5d286 100644 --- a/ports/espressif/common-hal/microcontroller/__init__.c +++ b/ports/espressif/common-hal/microcontroller/__init__.c @@ -36,6 +36,11 @@ #elif defined(CONFIG_IDF_TARGET_ESP32C6) #include "soc/lp_aon_reg.h" #include "esp32c6/rom/rtc.h" +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#include "soc/lp_aon_reg.h" +#include "esp32c61/rom/rtc.h" +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#include "esp32p4/rom/rtc.h" #elif defined(CONFIG_IDF_TARGET_ESP32S2) #include "soc/rtc_cntl_reg.h" #include "esp32s2/rom/rtc.h" @@ -81,7 +86,7 @@ void common_hal_mcu_enable_interrupts(void) { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { switch (runmode) { case RUNMODE_UF2: - #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) + #if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32C61) mp_arg_error_invalid(MP_QSTR_run_mode); #else // 0x11F2 is APP_REQUEST_UF2_RESET_HINT & is defined by TinyUF2 @@ -93,18 +98,22 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) REG_WRITE(RTC_RESET_CAUSE_REG, 0); // reset uf2 #endif - #ifdef SOC_LP_AON_SUPPORTED + #if defined(CONFIG_IDF_TARGET_ESP32P4) + REG_WRITE(LP_SYSTEM_REG_LP_STORE15_REG, 0); + #elif defined(SOC_LP_AON_SUPPORTED) REG_WRITE(LP_AON_STORE0_REG, 0); // reset safe mode #else REG_WRITE(RTC_CNTL_STORE0_REG, 0); // reset safe mode #endif - #if !defined(CONFIG_IDF_TARGET_ESP32) - #ifdef SOC_LP_AON_SUPPORTED + #if defined(CONFIG_IDF_TARGET_ESP32) + // No UF2 bootloader. + #elif defined(CONFIG_IDF_TARGET_ESP32P4) + REG_WRITE(LP_SYSTEM_REG_SYS_CTRL_REG, 0); + #elif defined(SOC_LP_AON_SUPPORTED) REG_WRITE(LP_AON_SYS_CFG_REG, 0); // reset bootloader #else REG_WRITE(RTC_CNTL_OPTION1_REG, 0); // reset bootloader #endif - #endif break; case RUNMODE_SAFE_MODE: // enter safe mode on next boot @@ -118,7 +127,10 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) chip_usb_set_persist_flags(USBDC_BOOT_DFU); #endif - #ifdef SOC_LP_AON_SUPPORTED + + #if defined(CONFIG_IDF_TARGET_ESP32P4) + REG_WRITE(LP_SYSTEM_REG_SYS_CTRL_REG, LP_SYSTEM_REG_FORCE_DOWNLOAD_BOOT); + #elif defined(SOC_LP_AON_SUPPORTED) REG_WRITE(LP_AON_SYS_CFG_REG, LP_AON_FORCE_DOWNLOAD_BOOT); #else REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); @@ -130,7 +142,7 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { } } -void NORETURN common_hal_mcu_reset(void) { +void MP_NORETURN common_hal_mcu_reset(void) { filesystem_flush(); // TODO: implement as part of flash improvements esp_restart(); } @@ -314,5 +326,23 @@ static const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #ifdef GPIO48_EXISTS { MP_ROM_QSTR(MP_QSTR_GPIO48), MP_ROM_PTR(&pin_GPIO48) }, #endif + #ifdef GPIO49_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO49), MP_ROM_PTR(&pin_GPIO49) }, + #endif + #ifdef GPIO50_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO50), MP_ROM_PTR(&pin_GPIO50) }, + #endif + #ifdef GPIO51_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO51), MP_ROM_PTR(&pin_GPIO51) }, + #endif + #ifdef GPIO52_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO52), MP_ROM_PTR(&pin_GPIO52) }, + #endif + #ifdef GPIO53_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO53), MP_ROM_PTR(&pin_GPIO53) }, + #endif + #ifdef GPIO54_EXISTS + { MP_ROM_QSTR(MP_QSTR_GPIO54), MP_ROM_PTR(&pin_GPIO54) }, + #endif }; MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/ports/espressif/common-hal/mipidsi/Bus.c b/ports/espressif/common-hal/mipidsi/Bus.c new file mode 100644 index 0000000000000..dbb559ea30f22 --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/Bus.c @@ -0,0 +1,69 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/mipidsi/Bus.h" +#include "bindings/espidf/__init__.h" +#include "py/runtime.h" +#include + +void common_hal_mipidsi_bus_construct(mipidsi_bus_obj_t *self, mp_uint_t frequency, uint8_t num_lanes) { + self->frequency = frequency; + self->num_data_lanes = num_lanes; + self->bus_handle = NULL; + + if (self->use_count > 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q in use"), MP_QSTR_mipidsi); + } + + esp_ldo_channel_handle_t ldo_mipi_phy = NULL; + esp_ldo_channel_config_t ldo_mipi_phy_config = { + .chan_id = 3, + .voltage_mv = 2500, + }; + ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy)); + + // Create the DSI bus + esp_lcd_dsi_bus_config_t bus_config = { + .bus_id = 0, + .num_data_lanes = num_lanes, + .phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT, + .lane_bit_rate_mbps = frequency / 1000000, // Convert Hz to MHz + }; + + CHECK_ESP_RESULT(esp_lcd_new_dsi_bus(&bus_config, &self->bus_handle)); +} + +void common_hal_mipidsi_bus_deinit(mipidsi_bus_obj_t *self) { + if (self->use_count > 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q in use"), MP_QSTR_Bus); + } + if (common_hal_mipidsi_bus_deinited(self)) { + return; + } + + // Delete the DSI bus + if (self->bus_handle != NULL) { + esp_lcd_del_dsi_bus(self->bus_handle); + self->bus_handle = NULL; + } + + self->frequency = 0; + self->num_data_lanes = 0; +} + +bool common_hal_mipidsi_bus_deinited(mipidsi_bus_obj_t *self) { + return self->bus_handle == NULL; +} + +void mipidsi_bus_increment_use_count(mipidsi_bus_obj_t *self) { + self->use_count++; +} +void mipidsi_bus_decrement_use_count(mipidsi_bus_obj_t *self) { + self->use_count--; + if (self->use_count == 0) { + common_hal_mipidsi_bus_deinit(self); + } +} diff --git a/ports/espressif/common-hal/mipidsi/Bus.h b/ports/espressif/common-hal/mipidsi/Bus.h new file mode 100644 index 0000000000000..b6257fd7223dd --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/Bus.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include + +typedef struct { + mp_obj_base_t base; + mp_uint_t frequency; + esp_lcd_dsi_bus_handle_t bus_handle; + uint8_t num_data_lanes; + uint8_t use_count; // Up to 4 displays +} mipidsi_bus_obj_t; + +void mipidsi_bus_increment_use_count(mipidsi_bus_obj_t *self); +void mipidsi_bus_decrement_use_count(mipidsi_bus_obj_t *self); diff --git a/ports/espressif/common-hal/mipidsi/Display.c b/ports/espressif/common-hal/mipidsi/Display.c new file mode 100644 index 0000000000000..46ef46ed60185 --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/Display.c @@ -0,0 +1,291 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/mipidsi/Display.h" +#include "shared-bindings/mipidsi/Bus.h" +#include "shared-bindings/pwmio/PWMOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/time/__init__.h" +#include "bindings/espidf/__init__.h" +#include +#include +#include "py/runtime.h" + +// Cache write-back function (should be from rom/cache.h but it's not always available) +extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size); + +void common_hal_mipidsi_display_construct(mipidsi_display_obj_t *self, + mipidsi_bus_obj_t *bus, + const uint8_t *init_sequence, + size_t init_sequence_len, + mp_uint_t virtual_channel, + mp_uint_t width, + mp_uint_t height, + mp_int_t rotation, + mp_uint_t color_depth, + const mcu_pin_obj_t *backlight_pin, + mp_float_t brightness, + mp_uint_t native_frames_per_second, + bool backlight_on_high, + mp_uint_t hsync_pulse_width, + mp_uint_t hsync_back_porch, + mp_uint_t hsync_front_porch, + mp_uint_t vsync_pulse_width, + mp_uint_t vsync_back_porch, + mp_uint_t vsync_front_porch, + mp_uint_t pixel_clock_frequency) { + self->bus = bus; + self->virtual_channel = virtual_channel; + self->width = width; + self->height = height; + self->rotation = rotation; + self->color_depth = color_depth; + self->native_frames_per_second = native_frames_per_second; + self->backlight_on_high = backlight_on_high; + self->framebuffer = NULL; + self->dbi_io_handle = NULL; + self->dpi_panel_handle = NULL; + + // Create the DBI interface for sending commands + esp_lcd_dbi_io_config_t dbi_config = { + .virtual_channel = virtual_channel, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + + CHECK_ESP_RESULT(esp_lcd_new_panel_io_dbi(bus->bus_handle, &dbi_config, &self->dbi_io_handle)); + + // Determine the pixel format based on color depth + lcd_color_format_t color_format; + if (color_depth == 16) { + color_format = LCD_COLOR_FMT_RGB565; + } else if (color_depth == 24) { + color_format = LCD_COLOR_FMT_RGB888; + } else { + common_hal_mipidsi_display_deinit(self); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_color_depth); + } + + // Create the DPI panel for sending pixel data + esp_lcd_dpi_panel_config_t dpi_config = { + .virtual_channel = virtual_channel, + .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, + .dpi_clock_freq_mhz = pixel_clock_frequency / 1000000, + .in_color_format = color_format, + .num_fbs = 1, + .video_timing = { + .h_size = width, + .v_size = height, + .hsync_pulse_width = hsync_pulse_width, + .hsync_back_porch = hsync_back_porch, + .hsync_front_porch = hsync_front_porch, + .vsync_pulse_width = vsync_pulse_width, + .vsync_back_porch = vsync_back_porch, + .vsync_front_porch = vsync_front_porch, + }, + .flags = { + .use_dma2d = false, + .disable_lp = false, + }, + }; + + esp_err_t ret = esp_lcd_new_panel_dpi(bus->bus_handle, &dpi_config, &self->dpi_panel_handle); + if (ret != ESP_OK) { + common_hal_mipidsi_display_deinit(self); + CHECK_ESP_RESULT(ret); + } + + // Get the framebuffer allocated by the driver + void *fb = NULL; + ret = esp_lcd_dpi_panel_get_frame_buffer(self->dpi_panel_handle, 1, &fb); + if (ret != ESP_OK || fb == NULL) { + common_hal_mipidsi_display_deinit(self); + CHECK_ESP_RESULT(ret); + } + + self->framebuffer = (uint8_t *)fb; + self->framebuffer_size = width * height * (color_depth / 8); + + // Send initialization sequence (format matches busdisplay) + #define DELAY 0x80 + uint32_t i = 0; + while (i < init_sequence_len) { + const uint8_t *cmd = init_sequence + i; + uint8_t data_size = *(cmd + 1); + bool delay = (data_size & DELAY) != 0; + data_size &= ~DELAY; + const uint8_t *data = cmd + 2; + esp_lcd_panel_io_tx_param(self->dbi_io_handle, cmd[0], data, data_size); + + uint16_t delay_length_ms = 0; + if (delay) { + data_size++; + delay_length_ms = *(cmd + 1 + data_size); + if (delay_length_ms == 255) { + delay_length_ms = 500; + } + } + common_hal_time_delay_ms(delay_length_ms); + i += 2 + data_size; + } + + // Initialize the panel after sending init commands + ret = esp_lcd_panel_init(self->dpi_panel_handle); + if (ret != ESP_OK) { + common_hal_mipidsi_display_deinit(self); + CHECK_ESP_RESULT(ret); + } + + // Setup backlight PWM if pin is provided + self->backlight_inout.base.type = &mp_type_NoneType; + if (backlight_pin != NULL && common_hal_mcu_pin_is_free(backlight_pin)) { + #if (CIRCUITPY_PWMIO) + pwmout_result_t result = common_hal_pwmio_pwmout_construct(&self->backlight_pwm, backlight_pin, 0, 50000, false); + if (result != PWMOUT_OK) { + self->backlight_inout.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin); + common_hal_never_reset_pin(backlight_pin); + } else { + self->backlight_pwm.base.type = &pwmio_pwmout_type; + common_hal_pwmio_pwmout_never_reset(&self->backlight_pwm); + } + #else + self->backlight_inout.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&self->backlight_inout, backlight_pin); + common_hal_never_reset_pin(backlight_pin); + #endif + + // Set initial brightness + #if (CIRCUITPY_PWMIO) + if (self->backlight_pwm.base.type == &pwmio_pwmout_type) { + common_hal_pwmio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t)(brightness * 0xFFFF)); + } else + #endif + if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + bool on = brightness > 0; + if (!backlight_on_high) { + on = !on; + } + common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, on); + } + } + mipidsi_bus_increment_use_count(self->bus); +} + +void common_hal_mipidsi_display_deinit(mipidsi_display_obj_t *self) { + if (common_hal_mipidsi_display_deinited(self)) { + return; + } + + // Cleanup backlight + #if (CIRCUITPY_PWMIO) + if (self->backlight_pwm.base.type == &pwmio_pwmout_type) { + common_hal_pwmio_pwmout_deinit(&self->backlight_pwm); + } else + #endif + if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + common_hal_digitalio_digitalinout_deinit(&self->backlight_inout); + } + + // Delete the DPI panel + if (self->dpi_panel_handle != NULL) { + esp_lcd_panel_del(self->dpi_panel_handle); + self->dpi_panel_handle = NULL; + } + + // Delete the DBI interface + if (self->dbi_io_handle != NULL) { + esp_lcd_panel_io_del(self->dbi_io_handle); + self->dbi_io_handle = NULL; + } + + mipidsi_bus_decrement_use_count(self->bus); + self->bus = NULL; + self->framebuffer = NULL; +} + +bool common_hal_mipidsi_display_deinited(mipidsi_display_obj_t *self) { + return self->dpi_panel_handle == NULL; +} + +void common_hal_mipidsi_display_refresh(mipidsi_display_obj_t *self) { + // Drawing the framebuffer we got from the IDF will flush the cache(s) so + // DMA can see our changes. It won't cause an extra copy. + esp_lcd_panel_draw_bitmap(self->dpi_panel_handle, 0, 0, self->width, self->height, self->framebuffer); + + // The DPI panel will automatically refresh from the framebuffer + // No explicit refresh call is needed as the DSI hardware continuously + // sends data from the framebuffer to the display +} + +mp_float_t common_hal_mipidsi_display_get_brightness(mipidsi_display_obj_t *self) { + return self->current_brightness; +} + +bool common_hal_mipidsi_display_set_brightness(mipidsi_display_obj_t *self, mp_float_t brightness) { + if (!self->backlight_on_high) { + brightness = 1.0 - brightness; + } + bool ok = false; + + // Avoid PWM types and functions when the module isn't enabled + #if (CIRCUITPY_PWMIO) + bool ispwm = (self->backlight_pwm.base.type == &pwmio_pwmout_type) ? true : false; + #else + bool ispwm = false; + #endif + + if (ispwm) { + #if (CIRCUITPY_PWMIO) + common_hal_pwmio_pwmout_set_duty_cycle(&self->backlight_pwm, (uint16_t)(0xffff * brightness)); + ok = true; + #else + ok = false; + #endif + } else if (self->backlight_inout.base.type == &digitalio_digitalinout_type) { + common_hal_digitalio_digitalinout_set_value(&self->backlight_inout, brightness > 0.99); + ok = true; + } + if (ok) { + self->current_brightness = brightness; + } + return ok; +} + +int common_hal_mipidsi_display_get_width(mipidsi_display_obj_t *self) { + return self->width; +} + +int common_hal_mipidsi_display_get_height(mipidsi_display_obj_t *self) { + return self->height; +} + +int common_hal_mipidsi_display_get_row_stride(mipidsi_display_obj_t *self) { + return self->width * (self->color_depth / 8); +} + +int common_hal_mipidsi_display_get_color_depth(mipidsi_display_obj_t *self) { + return self->color_depth; +} + +int common_hal_mipidsi_display_get_native_frames_per_second(mipidsi_display_obj_t *self) { + return self->native_frames_per_second; +} + +bool common_hal_mipidsi_display_get_grayscale(mipidsi_display_obj_t *self) { + return false; +} + +mp_int_t common_hal_mipidsi_display_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { + mipidsi_display_obj_t *self = (mipidsi_display_obj_t *)self_in; + + bufinfo->buf = self->framebuffer; + bufinfo->len = self->framebuffer_size; + bufinfo->typecode = 'B'; + + return 0; +} diff --git a/ports/espressif/common-hal/mipidsi/Display.h b/ports/espressif/common-hal/mipidsi/Display.h new file mode 100644 index 0000000000000..cbc87e268dc80 --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/Display.h @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/mipidsi/Bus.h" +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/digitalio/DigitalInOut.h" +#include "common-hal/pwmio/PWMOut.h" +#include +#include + +typedef struct { + mp_obj_base_t base; + mipidsi_bus_obj_t *bus; + mp_uint_t virtual_channel; + mp_uint_t width; + mp_uint_t height; + mp_int_t rotation; + mp_uint_t color_depth; + mp_uint_t native_frames_per_second; + uint8_t *framebuffer; + esp_lcd_panel_io_handle_t dbi_io_handle; + esp_lcd_panel_handle_t dpi_panel_handle; + size_t framebuffer_size; + union { + digitalio_digitalinout_obj_t backlight_inout; + #if CIRCUITPY_PWMIO + pwmio_pwmout_obj_t backlight_pwm; + #endif + }; + bool backlight_on_high; + mp_float_t current_brightness; +} mipidsi_display_obj_t; diff --git a/ports/espressif/common-hal/mipidsi/__init__.c b/ports/espressif/common-hal/mipidsi/__init__.c new file mode 100644 index 0000000000000..173f2146e87ac --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/mipidsi/__init__.h" diff --git a/ports/espressif/common-hal/mipidsi/__init__.h b/ports/espressif/common-hal/mipidsi/__init__.h new file mode 100644 index 0000000000000..972a7c082fd7b --- /dev/null +++ b/ports/espressif/common-hal/mipidsi/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/espressif/common-hal/nvm/ByteArray.c b/ports/espressif/common-hal/nvm/ByteArray.c index adea91411b6f7..971f9bc7991be 100644 --- a/ports/espressif/common-hal/nvm/ByteArray.c +++ b/ports/espressif/common-hal/nvm/ByteArray.c @@ -46,7 +46,7 @@ static esp_err_t get_bytes(nvs_handle_t handle, uint8_t **buf_out) { *buf_out = NULL; return result; } - buf = m_malloc(size); // this SHOULD be the same as + buf = m_malloc_without_collect(size); // this SHOULD be the same as if (result == ESP_OK) { result = nvs_get_blob(handle, "data", buf, &size); } else { diff --git a/ports/espressif/common-hal/os/__init__.c b/ports/espressif/common-hal/os/__init__.c index 4063090fe1f96..fff89c8476d8d 100644 --- a/ports/espressif/common-hal/os/__init__.c +++ b/ports/espressif/common-hal/os/__init__.c @@ -15,32 +15,6 @@ #include "esp_system.h" #include "esp_random.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_HW_MCU_NAME); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_HW_MCU_NAME); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { uint32_t i = 0; while (i < length) { diff --git a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c index 17ec77700c206..52c4b67bf4efe 100644 --- a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c +++ b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c @@ -18,7 +18,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/runtime.h" -#include "driver/gpio.h" +#include /* * Current pin limitations for ESP32-S2 ParallelBus: @@ -36,7 +36,7 @@ void common_hal_paralleldisplaybus_parallelbus_construct_nonsequential(paralleld const mcu_pin_obj_t *write, const mcu_pin_obj_t *read, const mcu_pin_obj_t *reset, uint32_t frequency) { if (n_pins != 8 && n_pins != 16) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Number of data_pins must be 8 or 16, not %d"), n_pins); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Number of data_pins must be %d or %d, not %d"), 8, 16, n_pins); } for (uint8_t i = 0; i < n_pins; i++) { diff --git a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h index 4724ba7231a4e..114a1e527a6d5 100644 --- a/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h +++ b/ports/espressif/common-hal/paralleldisplaybus/ParallelBus.h @@ -8,7 +8,7 @@ #include "common-hal/digitalio/DigitalInOut.h" -#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include typedef struct { mp_obj_base_t base; diff --git a/ports/espressif/common-hal/pulseio/PulseIn.c b/ports/espressif/common-hal/pulseio/PulseIn.c index cf24b42a052f1..f7e500790562a 100644 --- a/ports/espressif/common-hal/pulseio/PulseIn.c +++ b/ports/espressif/common-hal/pulseio/PulseIn.c @@ -74,14 +74,14 @@ static bool _done_callback(rmt_channel_handle_t rx_chan, void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } // We add one to the maxlen version to ensure that two symbols at lease are // captured because we may skip the first portion of a symbol. self->raw_symbols_size = MIN(64, maxlen / 2 + 1) * sizeof(rmt_symbol_word_t); - self->raw_symbols = (rmt_symbol_word_t *)m_malloc(self->raw_symbols_size); + self->raw_symbols = (rmt_symbol_word_t *)m_malloc_without_collect(self->raw_symbols_size); if (self->raw_symbols == NULL) { m_free(self->buffer); m_malloc_fail(self->raw_symbols_size); @@ -127,6 +127,9 @@ bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t *self) { } void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t *self) { + if (common_hal_pulseio_pulsein_deinited(self)) { + return; + } rmt_disable(self->channel); reset_pin_number(self->pin->number); rmt_del_channel(self->channel); diff --git a/ports/espressif/common-hal/pulseio/PulseOut.c b/ports/espressif/common-hal/pulseio/PulseOut.c index b76c84385596c..8995043b8259c 100644 --- a/ports/espressif/common-hal/pulseio/PulseOut.c +++ b/ports/espressif/common-hal/pulseio/PulseOut.c @@ -54,6 +54,9 @@ bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t *self) { } void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t *self) { + if (common_hal_pulseio_pulseout_deinited(self)) { + return; + } rmt_disable(self->channel); rmt_del_encoder(self->encoder); rmt_del_channel(self->channel); @@ -66,7 +69,7 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t *self, uint16_t *pu // Circuitpython allows 16 bit pulse values, while ESP32 only allows 15 bits // Thus, we use entire items for one pulse, rather than switching inside each item for (size_t i = 0; i < length; i++) { - // Setting the RMT duration to 0 has undefined behavior, so avoid that pre-emptively. + // Setting the RMT duration to 0 has undefined behavior, so avoid that preemptively. if (pulses[i] == 0) { continue; } diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.c b/ports/espressif/common-hal/qspibus/QSPIBus.c new file mode 100644 index 0000000000000..6fb872248e2a6 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.c @@ -0,0 +1,571 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" + +#include "py/gc.h" +#include "py/runtime.h" + +#include "driver/gpio.h" +#include "esp_heap_caps.h" +#include "soc/soc_caps.h" +#include + +#define QSPI_OPCODE_WRITE_CMD (0x02U) +#define QSPI_OPCODE_WRITE_COLOR (0x32U) +#define LCD_CMD_RAMWR (0x2CU) +#define LCD_CMD_RAMWRC (0x3CU) +#define LCD_CMD_DISPOFF (0x28U) +#define LCD_CMD_SLPIN (0x10U) +#define QSPI_DMA_BUFFER_COUNT (2U) +#define QSPI_DMA_BUFFER_SIZE (16U * 1024U) +#define QSPI_COLOR_TIMEOUT_MS (1000U) +static void qspibus_release_dma_buffers(qspibus_qspibus_obj_t *self) { + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + if (self->dma_buffer[i] != NULL) { + heap_caps_free(self->dma_buffer[i]); + self->dma_buffer[i] = NULL; + } + } + self->dma_buffer_size = 0; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; +} + +static bool qspibus_allocate_dma_buffers(qspibus_qspibus_obj_t *self) { + const size_t candidates[] = { + QSPI_DMA_BUFFER_SIZE, + QSPI_DMA_BUFFER_SIZE / 2, + QSPI_DMA_BUFFER_SIZE / 4, + }; + + for (size_t c = 0; c < MP_ARRAY_SIZE(candidates); c++) { + size_t size = candidates[c]; + bool ok = true; + for (size_t i = 0; i < QSPI_DMA_BUFFER_COUNT; i++) { + self->dma_buffer[i] = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + if (self->dma_buffer[i] == NULL) { + ok = false; + break; + } + } + if (ok) { + self->dma_buffer_size = size; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->transfer_in_progress = false; + return true; + } + qspibus_release_dma_buffers(self); + } + return false; +} + +// Reset transfer bookkeeping after timeout/error. Drains any stale semaphore +// tokens that late ISR completions may have posted after the timeout expired. +static void qspibus_reset_transfer_state(qspibus_qspibus_obj_t *self) { + self->inflight_transfers = 0; + self->transfer_in_progress = false; + if (self->transfer_done_sem != NULL) { + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + } +} + +static bool qspibus_wait_one_transfer_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + if (self->inflight_transfers == 0) { + self->transfer_in_progress = false; + return true; + } + + if (xSemaphoreTake(self->transfer_done_sem, timeout) != pdTRUE) { + return false; + } + self->inflight_transfers--; + self->transfer_in_progress = (self->inflight_transfers > 0); + return true; +} + +static bool qspibus_wait_all_transfers_done(qspibus_qspibus_obj_t *self, TickType_t timeout) { + while (self->inflight_transfers > 0) { + if (!qspibus_wait_one_transfer_done(self, timeout)) { + return false; + } + } + return true; +} + +static void qspibus_send_command_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)command << 8); + esp_err_t err = esp_lcd_panel_io_tx_param(self->io_handle, packed_cmd, data, len); + if (err != ESP_OK) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } +} + +static void qspibus_send_color_bytes( + qspibus_qspibus_obj_t *self, + uint8_t command, + const uint8_t *data, + size_t len) { + + if (!self->bus_initialized) { + raise_deinited_error(); + } + + if (len == 0) { + qspibus_send_command_bytes(self, command, NULL, 0); + return; + } + + // RAMWR must transition to RAMWRC for continued payload chunks. + uint8_t chunk_command = command; + const uint8_t *cursor = data; + size_t remaining = len; + + // Drain stale semaphore tokens that late ISR completions may have + // posted after a previous qspibus_reset_transfer_state(). Without + // this, a stale token could satisfy a future wait, causing the next + // transfer to skip its real DMA-done wait. + if (self->inflight_transfers == 0 && self->transfer_done_sem != NULL) { + while (xSemaphoreTake(self->transfer_done_sem, 0) == pdTRUE) { + } + } + + while (remaining > 0) { + // inflight_transfers is only modified in task context (never from ISR), + // so no atomic/critical section is needed. The ISR only signals the + // counting semaphore; all counter bookkeeping happens task-side. + if (self->inflight_transfers >= QSPI_DMA_BUFFER_COUNT) { + if (!qspibus_wait_one_transfer_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } + + size_t chunk = remaining; + if (chunk > self->dma_buffer_size) { + chunk = self->dma_buffer_size; + } + + uint8_t *buffer = self->dma_buffer[self->active_buffer]; + memcpy(buffer, cursor, chunk); + + uint32_t packed_cmd = ((uint32_t)QSPI_OPCODE_WRITE_COLOR << 24) | ((uint32_t)chunk_command << 8); + esp_err_t err = esp_lcd_panel_io_tx_color(self->io_handle, packed_cmd, buffer, chunk); + if (err != ESP_OK) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } + + self->inflight_transfers++; + self->transfer_in_progress = true; + self->active_buffer = (self->active_buffer + 1) % QSPI_DMA_BUFFER_COUNT; + + if (chunk_command == LCD_CMD_RAMWR) { + chunk_command = LCD_CMD_RAMWRC; + } + + cursor += chunk; + remaining -= chunk; + } + + // Let DMA complete asynchronously. The next begin_transaction() will + // wait for all in-flight transfers, allowing fill_area() computation + // to overlap with DMA. The explicit wait is only needed for the + // Python write_data() API path where callers expect the transfer to + // be finished on return. +} + +static bool qspibus_is_color_payload_command(uint8_t command) { + return command == LCD_CMD_RAMWR || command == LCD_CMD_RAMWRC; +} + +static void qspibus_panel_sleep_best_effort(qspibus_qspibus_obj_t *self) { + if (!self->bus_initialized || self->io_handle == NULL) { + return; + } + + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + } + + // If a command is buffered, flush it first so the panel state machine + // doesn't get a truncated transaction before sleep. + if (self->has_pending_command) { + uint32_t pending = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)self->pending_command << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, pending, NULL, 0); + self->has_pending_command = false; + } + + uint32_t disp_off = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_DISPOFF << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, disp_off, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(20)); + + uint32_t sleep_in = ((uint32_t)QSPI_OPCODE_WRITE_CMD << 24) | ((uint32_t)LCD_CMD_SLPIN << 8); + (void)esp_lcd_panel_io_tx_param(self->io_handle, sleep_in, NULL, 0); + vTaskDelay(pdMS_TO_TICKS(120)); +} + +static bool IRAM_ATTR qspibus_on_color_trans_done( + esp_lcd_panel_io_handle_t io_handle, + esp_lcd_panel_io_event_data_t *event_data, + void *user_ctx) { + (void)io_handle; + (void)event_data; + + qspibus_qspibus_obj_t *self = (qspibus_qspibus_obj_t *)user_ctx; + if (self->transfer_done_sem == NULL) { + return false; + } + BaseType_t x_higher_priority_task_woken = pdFALSE; + + xSemaphoreGiveFromISR(self->transfer_done_sem, &x_higher_priority_task_woken); + return x_higher_priority_task_woken == pdTRUE; +} + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, + const mcu_pin_obj_t *reset, + uint32_t frequency) { + + self->io_handle = NULL; + self->host_id = SPI2_HOST; + self->clock_pin = clock->number; + self->data0_pin = data0->number; + self->data1_pin = data1->number; + self->data2_pin = data2->number; + self->data3_pin = data3->number; + self->cs_pin = cs->number; + self->dcx_pin = (dcx != NULL) ? dcx->number : -1; + self->reset_pin = (reset != NULL) ? reset->number : -1; + self->frequency = frequency; + self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; + self->transfer_in_progress = false; + self->active_buffer = 0; + self->inflight_transfers = 0; + self->dma_buffer_size = 0; + self->dma_buffer[0] = NULL; + self->dma_buffer[1] = NULL; + self->transfer_done_sem = NULL; + + self->transfer_done_sem = xSemaphoreCreateCounting(QSPI_DMA_BUFFER_COUNT, 0); + if (self->transfer_done_sem == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("ESP-IDF memory allocation failed")); + } + + if (!qspibus_allocate_dma_buffers(self)) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + } + + const spi_bus_config_t bus_config = { + .sclk_io_num = self->clock_pin, + .mosi_io_num = self->data0_pin, + .miso_io_num = self->data1_pin, + .quadwp_io_num = self->data2_pin, + .quadhd_io_num = self->data3_pin, + .max_transfer_sz = self->dma_buffer_size, + .flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_GPIO_PINS, + }; + + esp_err_t err = spi_bus_initialize(self->host_id, &bus_config, SPI_DMA_CH_AUTO); + if (err != ESP_OK) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q in use"), MP_QSTR_SPI); + } + + // Mark bus as initialized so deinit knows to call spi_bus_free(). + self->bus_initialized = true; + + const esp_lcd_panel_io_spi_config_t io_config = { + .cs_gpio_num = self->cs_pin, + .dc_gpio_num = -1, + .spi_mode = 0, + .pclk_hz = self->frequency, + .trans_queue_depth = QSPI_DMA_BUFFER_COUNT, + .on_color_trans_done = qspibus_on_color_trans_done, + .user_ctx = self, + .lcd_cmd_bits = 32, + .lcd_param_bits = 8, + .flags = { + .quad_mode = 1, + }, + }; + + err = esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)self->host_id, &io_config, &self->io_handle); + if (err != ESP_OK) { + common_hal_qspibus_qspibus_deinit(self); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("%q failure: %d"), MP_QSTR_QSPI, (int)err); + } + + claim_pin(clock); + claim_pin(data0); + claim_pin(data1); + claim_pin(data2); + claim_pin(data3); + claim_pin(cs); + if (dcx != NULL) { + claim_pin(dcx); + gpio_set_direction((gpio_num_t)self->dcx_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->dcx_pin, 1); + } + + if (reset != NULL) { + claim_pin(reset); + + gpio_set_direction((gpio_num_t)self->reset_pin, GPIO_MODE_OUTPUT); + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + } +} + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self) { + if (self->bus_initialized) { + qspibus_panel_sleep_best_effort(self); + self->in_transaction = false; + + if (self->io_handle != NULL) { + esp_lcd_panel_io_del(self->io_handle); + self->io_handle = NULL; + } + + spi_bus_free(self->host_id); + self->bus_initialized = false; + } + + if (self->transfer_done_sem != NULL) { + // Set NULL before delete so late ISR callbacks (if any) see NULL and skip. + SemaphoreHandle_t sem = self->transfer_done_sem; + self->transfer_done_sem = NULL; + vSemaphoreDelete(sem); + } + + qspibus_release_dma_buffers(self); + + reset_pin_number(self->clock_pin); + reset_pin_number(self->data0_pin); + reset_pin_number(self->data1_pin); + reset_pin_number(self->data2_pin); + reset_pin_number(self->data3_pin); + reset_pin_number(self->cs_pin); + if (self->dcx_pin >= 0) { + reset_pin_number(self->dcx_pin); + } + if (self->reset_pin >= 0) { + reset_pin_number(self->reset_pin); + } + + self->bus_initialized = false; + self->in_transaction = false; + self->has_pending_command = false; + self->pending_command = 0; + self->transfer_in_progress = false; + self->inflight_transfers = 0; +} + +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self) { + return !self->bus_initialized; +} + +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command) { + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + // If caller stages command-only operations repeatedly, flush the previous + // pending command as no-data before replacing it. + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + + self->pending_command = command; + self->has_pending_command = true; +} + +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len) { + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + if (len == 0) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + return; + } + if (!self->has_pending_command) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, len); + // Python API: wait for DMA to finish so callers see the transfer as + // complete on return. The internal displayio path skips this wait + // to allow fill_area/DMA overlap. + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + mp_raise_OSError_msg(MP_ERROR_TEXT("Operation timed out")); + } + } else { + qspibus_send_command_bytes(self, self->pending_command, data, len); + } + self->has_pending_command = false; +} + +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->reset_pin < 0) { + return false; + } + + gpio_set_level((gpio_num_t)self->reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level((gpio_num_t)self->reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(120)); + return true; +} + +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + return self->bus_initialized && !self->in_transaction && !self->transfer_in_progress && !self->has_pending_command; +} + +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized || self->in_transaction || self->has_pending_command) { + return false; + } + // Wait for any in-flight DMA to complete before starting a new + // transaction. This replaces the old non-blocking bus_free() check + // and enables fill_area()/DMA overlap: the CPU fills the next + // subrectangle while the previous DMA runs, and this wait only + // blocks when we actually need the bus for the next send. + if (self->transfer_in_progress) { + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + return false; + } + } + self->in_transaction = true; + return true; +} + +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + (void)chip_select; + if (!self->bus_initialized) { + raise_deinited_error(); + } + if (!self->in_transaction) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (data_type == DISPLAY_COMMAND) { + for (uint32_t i = 0; i < data_length; i++) { + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + } + self->pending_command = data[i]; + self->has_pending_command = true; + } + return; + } + + if (!self->has_pending_command) { + if (data_length == 0) { + // Zero-length data write after a no-data command is benign. + return; + } + mp_raise_RuntimeError(MP_ERROR_TEXT("Internal error")); + } + + if (data_length == 0) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + return; + } + + if (qspibus_is_color_payload_command(self->pending_command)) { + qspibus_send_color_bytes(self, self->pending_command, data, data_length); + } else { + qspibus_send_command_bytes(self, self->pending_command, data, data_length); + } + self->has_pending_command = false; +} + +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized) { + return; + } + if (self->has_pending_command) { + qspibus_send_command_bytes(self, self->pending_command, NULL, 0); + self->has_pending_command = false; + } + self->in_transaction = false; +} + +void common_hal_qspibus_qspibus_flush(mp_obj_t obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(obj); + if (!self->bus_initialized) { + return; + } + if (!qspibus_wait_all_transfers_done(self, pdMS_TO_TICKS(QSPI_COLOR_TIMEOUT_MS))) { + qspibus_reset_transfer_state(self); + } +} + +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj) { + (void)obj; +} diff --git a/ports/espressif/common-hal/qspibus/QSPIBus.h b/ports/espressif/common-hal/qspibus/QSPIBus.h new file mode 100644 index 0000000000000..eaaa971a79c49 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/QSPIBus.h @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include +#include + +#include "py/obj.h" + +#include "esp-idf/components/esp_lcd/include/esp_lcd_panel_io.h" +#include "driver/spi_master.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" + +typedef struct { + mp_obj_base_t base; + + // ESP LCD panel IO handle used for QSPI transactions. + esp_lcd_panel_io_handle_t io_handle; + + // SPI host (SPI2_HOST on ESP32-S3). + spi_host_device_t host_id; + + // Claimed GPIO numbers. + int8_t clock_pin; + int8_t data0_pin; + int8_t data1_pin; + int8_t data2_pin; + int8_t data3_pin; + int8_t cs_pin; + int8_t dcx_pin; // -1 when optional DCX line is not provided. + int8_t reset_pin; // -1 when reset line is not provided. + + uint32_t frequency; + bool bus_initialized; + bool in_transaction; + bool has_pending_command; + uint8_t pending_command; + bool transfer_in_progress; + uint8_t active_buffer; + uint8_t inflight_transfers; + size_t dma_buffer_size; + uint8_t *dma_buffer[2]; + + // Signaled from ISR when panel IO transfer completes. + SemaphoreHandle_t transfer_done_sem; +} qspibus_qspibus_obj_t; diff --git a/ports/espressif/common-hal/qspibus/__init__.c b/ports/espressif/common-hal/qspibus/__init__.c new file mode 100644 index 0000000000000..2f763b218cb43 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.c @@ -0,0 +1,3 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/qspibus/__init__.h b/ports/espressif/common-hal/qspibus/__init__.h new file mode 100644 index 0000000000000..2f763b218cb43 --- /dev/null +++ b/ports/espressif/common-hal/qspibus/__init__.h @@ -0,0 +1,3 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT diff --git a/ports/espressif/common-hal/rclcpy/Node.c b/ports/espressif/common-hal/rclcpy/Node.c new file mode 100644 index 0000000000000..f68daa44fc34d --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/Node.c @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/rclcpy/Node.h" +#include "shared-bindings/rclcpy/__init__.h" + +#include "esp_log.h" + +void common_hal_rclcpy_node_construct(rclcpy_node_obj_t *self, + const char *node_name, const char *node_namespace) { + + rclc_node_init_default(&self->rcl_node, node_name, node_namespace, &rclcpy_default_context.rcl_support); + if (!rcl_node_is_valid(&self->rcl_node)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS node failed to initialize")); + } + self->deinited = false; +} + +bool common_hal_rclcpy_node_deinited(rclcpy_node_obj_t *self) { + return self->deinited; +} + +void common_hal_rclcpy_node_deinit(rclcpy_node_obj_t *self) { + if (common_hal_rclcpy_node_deinited(self)) { + return; + } + // Clean up Micro-ROS object + rcl_ret_t ret = rcl_node_fini(&self->rcl_node); + if (ret != RCL_RET_OK) { + // TODO: node_fini returns a fail here, but doesn't impede microros + // from restarting. Debug left for future investigation. + ESP_LOGW("RCLCPY", "Node cleanup error: %d", ret); + // rclcpy_default_context.critical_fail=RCLCPY_NODE_FAIL; + } + self->deinited = true; +} + +const char *common_hal_rclcpy_node_get_name(rclcpy_node_obj_t *self) { + return rcl_node_get_name(&self->rcl_node); +} + +const char *common_hal_rclcpy_node_get_namespace(rclcpy_node_obj_t *self) { + return rcl_node_get_namespace(&self->rcl_node); +} diff --git a/ports/espressif/common-hal/rclcpy/Node.h b/ports/espressif/common-hal/rclcpy/Node.h new file mode 100644 index 0000000000000..c019a654e5add --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/Node.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/runtime.h" + +#include +#include +#include +#include +#include + + +typedef struct { + mp_obj_base_t base; + bool deinited; + rcl_node_t rcl_node; +} rclcpy_node_obj_t; diff --git a/ports/espressif/common-hal/rclcpy/Publisher.c b/ports/espressif/common-hal/rclcpy/Publisher.c new file mode 100644 index 0000000000000..81df154687ace --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/Publisher.c @@ -0,0 +1,64 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/rclcpy/Publisher.h" + +#include "esp_log.h" + +void common_hal_rclcpy_publisher_construct(rclcpy_publisher_obj_t *self, rclcpy_node_obj_t *node, + const char *topic_name) { + + // Create Int32 type object + // TODO: support other message types through class imports + const rosidl_message_type_support_t *type_support = ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32); + + // Creates a reliable Int32 publisher + rcl_ret_t rc = rclc_publisher_init_default( + &self->rcl_publisher, &node->rcl_node, + type_support, topic_name); + if (RCL_RET_OK != rc) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS topic failed to initialize")); + } + + self->node = node; +} + +bool common_hal_rclcpy_publisher_deinited(rclcpy_publisher_obj_t *self) { + return self->node == NULL; +} + +void common_hal_rclcpy_publisher_deinit(rclcpy_publisher_obj_t *self) { + if (common_hal_rclcpy_publisher_deinited(self)) { + return; + } + // Clean up Micro-ROS object + rcl_ret_t ret = rcl_publisher_fini(&self->rcl_publisher, &self->node->rcl_node); + if (ret != RCL_RET_OK) { + // TODO: publisher_fini returns a fail here, but doesn't impede microros + // from restarting. Debug left for future investigation. + ESP_LOGW("RCLCPY", "Publisher cleanup error: %d", ret); + // rclcpy_default_context.critical_fail=RCLCPY_PUB_FAIL; + } + self->node = NULL; +} + +void common_hal_rclcpy_publisher_publish_int32(rclcpy_publisher_obj_t *self, int32_t data) { + // Int32 message object + std_msgs__msg__Int32 msg; + + // Set message value + msg.data = data; + + // Publish message + rcl_ret_t rc = rcl_publish(&self->rcl_publisher, &msg, NULL); + if (RCL_RET_OK != rc) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Could not publish to ROS topic")); + } +} + +const char *common_hal_rclcpy_publisher_get_topic_name(rclcpy_publisher_obj_t *self) { + return rcl_publisher_get_topic_name(&self->rcl_publisher); +} diff --git a/ports/espressif/common-hal/rclcpy/Publisher.h b/ports/espressif/common-hal/rclcpy/Publisher.h new file mode 100644 index 0000000000000..fdc45293cd270 --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/Publisher.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "common-hal/rclcpy/Node.h" +#include "common-hal/rclcpy/__init__.h" + +#include +#include +#include +#include +#include +#include + + +typedef struct { + mp_obj_base_t base; + rclcpy_node_obj_t *node; + rcl_publisher_t rcl_publisher; +} rclcpy_publisher_obj_t; diff --git a/ports/espressif/common-hal/rclcpy/__init__.c b/ports/espressif/common-hal/rclcpy/__init__.c new file mode 100644 index 0000000000000..e0e6fd8b4f4fc --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/__init__.c @@ -0,0 +1,122 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/rclcpy/__init__.h" + +#include "esp_log.h" + +#define RCLCPY_SUPPORT_FAIL 1 +#define RCLCPY_OPTIONS_FAIL 2 + +rclcpy_context_t rclcpy_default_context = { + .initialized = false, + .critical_fail = 0, +}; + +static void *microros_allocate(size_t size, void *state) { + (void)state; + return m_malloc(size); +} + +static void microros_deallocate(void *pointer, void *state) { + (void)state; + m_free(pointer); +} + +static void *microros_reallocate(void *pointer, size_t size, void *state) { + (void)state; + return m_realloc(pointer, size); +} + +static void *microros_zero_allocate(size_t number_of_elements, size_t size_of_element, void *state) { + (void)state; + size_t total_size = number_of_elements * size_of_element; + void *ptr = m_malloc(total_size); + if (ptr != NULL) { + memset(ptr, 0, total_size); + } + return ptr; +} + +void rclcpy_reset(void) { + if (rclcpy_default_context.initialized) { + // Clean up micro-ROS objects + rcl_ret_t ret = rclc_support_fini(&rclcpy_default_context.rcl_support); + if (ret != RCL_RET_OK) { + // ESP_LOGW("RCLCPY", "Support cleanup error: %d", ret); + rclcpy_default_context.critical_fail = RCLCPY_SUPPORT_FAIL; + } + ret = rcl_init_options_fini(&rclcpy_default_context.init_options); + if (ret != RCL_RET_OK) { + // ESP_LOGW("RCLCPY", "Init options cleanup error: %d", ret); + rclcpy_default_context.critical_fail = RCLCPY_OPTIONS_FAIL; + } + + // Reset context state + memset(&rclcpy_default_context, 0, sizeof(rclcpy_default_context)); + rclcpy_default_context.initialized = false; + } +} + +void common_hal_rclcpy_init(const char *agent_ip, const char *agent_port, int16_t domain_id) { + if (rclcpy_default_context.critical_fail != 0) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("Critical ROS failure during soft reboot, reset required: %d"), rclcpy_default_context.critical_fail); + } + + // Set up circuitpython-friendly allocator + rcl_allocator_t custom_allocator = rcutils_get_zero_initialized_allocator(); + custom_allocator.allocate = microros_allocate; + custom_allocator.deallocate = microros_deallocate; + custom_allocator.reallocate = microros_reallocate; + custom_allocator.zero_allocate = microros_zero_allocate; + if (!rcutils_set_default_allocator(&custom_allocator)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS memory allocator failure")); + } + rclcpy_default_context.rcl_allocator = custom_allocator; + + rcl_ret_t ret; + + // Micro-ROS options initialization + rclcpy_default_context.init_options = rcl_get_zero_initialized_init_options(); + ret = rcl_init_options_init(&rclcpy_default_context.init_options, rclcpy_default_context.rcl_allocator); + if (ret != RCL_RET_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS internal setup failure")); + } + if (domain_id < 0) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid ROS domain ID")); + } + ret = rcl_init_options_set_domain_id(&rclcpy_default_context.init_options, domain_id); + if (ret != RCL_RET_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS internal setup failure")); + } + + // Set up Micro-ROS Agent + rclcpy_default_context.rmw_options = rcl_init_options_get_rmw_init_options(&rclcpy_default_context.init_options); + ret = rmw_uros_options_set_udp_address(agent_ip, agent_port, rclcpy_default_context.rmw_options); + if (ret != RCL_RET_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS internal setup failure")); + } + + // Final support object init requires a connected agent + ret = rclc_support_init_with_options(&rclcpy_default_context.rcl_support, + 0, + NULL, + &rclcpy_default_context.init_options, + &rclcpy_default_context.rcl_allocator); + if (ret != RCL_RET_OK) { + mp_raise_RuntimeError(MP_ERROR_TEXT("ROS failed to initialize. Is agent connected?")); + } else { + rclcpy_default_context.initialized = true; + } +} + +rclcpy_context_t *common_hal_rclcpy_get_default_context(void) { + return &rclcpy_default_context; +} + +bool common_hal_rclcpy_default_context_is_initialized(void) { + return rclcpy_default_context.initialized; +} diff --git a/ports/espressif/common-hal/rclcpy/__init__.h b/ports/espressif/common-hal/rclcpy/__init__.h new file mode 100644 index 0000000000000..f3ebd4787e757 --- /dev/null +++ b/ports/espressif/common-hal/rclcpy/__init__.h @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/runtime.h" + +#include +#include +#include +#include +#include +#include + + +typedef struct { + bool initialized; + uint8_t critical_fail; + rcl_allocator_t rcl_allocator; + rclc_support_t rcl_support; + rcl_init_options_t init_options; + rmw_init_options_t *rmw_options; +} rclcpy_context_t; + +extern rclcpy_context_t rclcpy_default_context; +void rclcpy_reset(void); diff --git a/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c b/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c index ba8b70221b729..f65c7fdd9f110 100644 --- a/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/espressif/common-hal/rotaryio/IncrementalEncoder.c @@ -21,6 +21,10 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode // // These routines also implicitly configure the weak internal pull-ups, as expected // in CircuitPython. + + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + pcnt_unit_config_t unit_config = { // Set counter limit .low_limit = INT16_MIN, @@ -87,6 +91,10 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o pcnt_del_channel(self->channel_a); pcnt_del_channel(self->channel_b); pcnt_del_unit(self->unit); + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->unit = NULL; } diff --git a/ports/espressif/common-hal/sdioio/SDCard.c b/ports/espressif/common-hal/sdioio/SDCard.c new file mode 100644 index 0000000000000..102f4a4048e48 --- /dev/null +++ b/ports/espressif/common-hal/sdioio/SDCard.c @@ -0,0 +1,301 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jacob Rigby +// +// SPDX-License-Identifier: MIT + +#include +#include "esp_err.h" + +#include "driver/sdmmc_host.h" +#include "ports/espressif/esp-idf/components/sdmmc/include/sdmmc_cmd.h" + +#include "extmod/vfs.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "shared-bindings/sdioio/SDCard.h" +#include "py/mperrno.h" +#include "py/runtime.h" + +#include "esp_log.h" +static const char *TAG = "SDCard.c"; + +static bool slot_in_use[2]; +static bool never_reset_sdio[2] = { false, false }; + +static void common_hal_sdioio_sdcard_check_for_deinit(sdioio_sdcard_obj_t *self) { + if (common_hal_sdioio_sdcard_deinited(self)) { + raise_deinited_error(); + } +} + +static int check_pins(const mcu_pin_obj_t *clock, const mcu_pin_obj_t *command, const uint8_t num_data, const mcu_pin_obj_t **data) { + #ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX + // ESP32-S3 and P4 can use any pin for any SDMMC func in either slot + // Default to SLOT_1 for SD cards + ESP_LOGI(TAG, "Using chip with CONFIG_SOC_SDMMC_USE_GPIO_MATRIX"); + if (!slot_in_use[1]) { + return SDMMC_HOST_SLOT_1; + } else if (!slot_in_use[0]) { + return SDMMC_HOST_SLOT_0; + } + #else + if (command->number == GPIO_NUM_11 && clock->number == GPIO_NUM_6 && data[0]->number == GPIO_NUM_7) { + // Might be slot 0 + if (num_data == 1 || (num_data == 4 && data[1]->number == GPIO_NUM_8 && data[2]->number == GPIO_NUM_9 && data[3]->number == GPIO_NUM_10)) { + return SDMMC_HOST_SLOT_0; + } + } else if (command->number == GPIO_NUM_15 && clock->number == GPIO_NUM_14 && data[0]->number == 2) { + // Might be slot 1 + if (num_data == 1 || (num_data == 4 && data[1]->number == GPIO_NUM_4 && data[2]->number == GPIO_NUM_12 && data[3]->number == GPIO_NUM_13)) { + return SDMMC_HOST_SLOT_1; + } + } + #endif + return -1; +} + +uint8_t get_slot_index(sdioio_sdcard_obj_t *self) { + if (self->slot == SDMMC_HOST_SLOT_0) { + return 0; + } else { + return 1; + } +} + +void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *command, + uint8_t num_data, const mcu_pin_obj_t **data, uint32_t frequency) { + if (num_data != 4 && num_data != 1) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Number of data_pins must be %d or %d, not %d"), 1, 4, num_data); + } + + self->num_data = num_data; + int sd_slot = check_pins(clock, command, num_data, data); + if (sd_slot != SDMMC_HOST_SLOT_0 && sd_slot != SDMMC_HOST_SLOT_1) { + // Bad pin combo + raise_ValueError_invalid_pins(); + } + + // max 40Mhz frequency + mp_arg_validate_int_max(frequency, 40000000, MP_QSTR_frequency); + ESP_LOGI(TAG, "Using slot %d", sd_slot); + self->slot = (uint8_t)sd_slot; + esp_err_t err = ESP_OK; + + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + host.max_freq_khz = frequency / 1000; + + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + slot_config.width = num_data; + slot_config.clk = clock->number; + self->clock = clock->number; + slot_config.cmd = command->number; + self->command = command->number; + slot_config.d0 = data[0]->number; + self->data[0] = data[0]->number; + if (num_data == 4) { + slot_config.d1 = data[1]->number; + self->data[1] = data[1]->number; + slot_config.d2 = data[2]->number; + self->data[2] = data[2]->number; + slot_config.d3 = data[3]->number; + self->data[3] = data[3]->number; + } + + ESP_LOGI(TAG, "slot_config:\nwidth: %d, clk: %d, cmd: %d\nd0: %d, d1: %d, d2: %d, d3: %d", + slot_config.width, slot_config.clk, slot_config.cmd, + slot_config.d0, slot_config.d1, slot_config.d2, slot_config.d3); + + if (!slot_in_use[0] && !slot_in_use[1]) { + err = sdmmc_host_init(); + if (err != ESP_OK) { + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err); + } + } + + err = sdmmc_host_init_slot(sd_slot, &slot_config); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to initialize SDMMC slot: %x", err); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err); + } + // sdmmc_card_t card; + // self->card = malloc(sizeof(sdmmc_card_t)); + err = sdmmc_card_init(&host, &self->card); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to initialize SDMMC card: %x", err); + mp_raise_OSError_msg_varg(MP_ERROR_TEXT("SDIO Init Error %x"), err); + } + + common_hal_sdioio_sdcard_check_for_deinit(self); + + slot_in_use[get_slot_index(self)] = true; + + claim_pin(clock); + claim_pin(command); + for (size_t i = 0; i < num_data; i++) { + claim_pin(data[i]); + } + + ESP_LOGI(TAG, "Initialized SD card with ID %d:%d-%s", + self->card.cid.mfg_id, self->card.cid.oem_id, self->card.cid.name); + + ESP_LOGI(TAG, "Number of sectors: %d with sector_size: %d", + self->card.csd.capacity, self->card.csd.sector_size); + + self->frequency = self->card.real_freq_khz; + ESP_LOGI(TAG, "Real frequency is %lu", self->frequency); + self->capacity = self->card.csd.capacity; // Reported number of sectors + ESP_LOGI(TAG, "Reported capacity is %lu", self->capacity); + + return; +} + +uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) { + return self->capacity; +} + +uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t *self) { + return self->frequency; +} + +uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) { + return self->num_data; +} + +static void check_whole_block(mp_buffer_info_t *bufinfo, int sector_size) { + if (bufinfo->len % sector_size) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), sector_size); + } +} + +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + ESP_LOGI(TAG, "in sdioio_sdcard_writeblocks"); + esp_err_t err = sdmmc_write_sectors(&self->card, buf, start_block, num_blocks); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to write blocks with err 0x%X", err); + return -MP_EIO; + } + return 0; +} + +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + common_hal_sdioio_sdcard_check_for_deinit(self); + check_whole_block(bufinfo, self->card.csd.sector_size); + + uint32_t num_blocks = bufinfo->len / self->card.csd.sector_size; + return sdioio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + ESP_LOGI(TAG, "in sdioio_sdcard_readblocks"); + esp_err_t err = sdmmc_read_sectors(&self->card, buf, start_block, num_blocks); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Failed to read blocks with err 0x%X", err); + return -MP_EIO; + } + return 0; +} + +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + common_hal_sdioio_sdcard_check_for_deinit(self); + check_whole_block(bufinfo, self->card.csd.sector_size); + + uint32_t num_blocks = bufinfo->len / self->card.csd.sector_size; + return sdioio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, + mp_int_t *out_value) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + // SDIO operations are synchronous, no action needed + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdioio_sdcard_get_count(self); + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; // SD cards use 512-byte sectors + return true; + + default: + return false; // Unsupported command + } +} + +bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) { + return true; +} + +bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) { + return self->command == COMMON_HAL_MCU_NO_PIN; +} + +void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) { + if (common_hal_sdioio_sdcard_deinited(self)) { + return; + } + + never_reset_sdio[get_slot_index(self)] = false; + slot_in_use[get_slot_index(self)] = false; + + if (!slot_in_use[0] && !slot_in_use[1]) { + sdmmc_host_deinit(); + } + + reset_pin_number(self->command); + self->command = COMMON_HAL_MCU_NO_PIN; + reset_pin_number(self->clock); + self->clock = COMMON_HAL_MCU_NO_PIN; + for (size_t i = 0; i < self->num_data; i++) { + reset_pin_number(self->data[i]); + self->data[i] = COMMON_HAL_MCU_NO_PIN; + } + + return; +} + +void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) { + if (common_hal_sdioio_sdcard_deinited(self)) { + return; + } + + if (never_reset_sdio[get_slot_index(self)]) { + return; + } + + never_reset_sdio[get_slot_index(self)] = true; + + never_reset_pin_number(self->command); + never_reset_pin_number(self->clock); + + for (size_t i = 0; i < self->num_data; i++) { + never_reset_pin_number(self->data[i]); + } +} + +void sdioio_reset(void) { + for (size_t i = 0; i < MP_ARRAY_SIZE(slot_in_use); i++) { + if (!never_reset_sdio[i]) { + slot_in_use[i] = false; + } + } + if (!slot_in_use[0] && !slot_in_use[1]) { + sdmmc_host_deinit(); + } + + return; +} diff --git a/ports/espressif/common-hal/sdioio/SDCard.h b/ports/espressif/common-hal/sdioio/SDCard.h new file mode 100644 index 0000000000000..03fb82b37d545 --- /dev/null +++ b/ports/espressif/common-hal/sdioio/SDCard.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jacob Rigby +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "driver/sdmmc_types.h" + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + sdmmc_card_t card; + uint8_t slot; + uint8_t num_data : 3, state_programming : 1, has_lock : 1; + uint8_t command; + uint8_t clock; + uint8_t data[4]; + uint32_t frequency; + uint32_t capacity; +} sdioio_sdcard_obj_t; + +void sdioio_reset(void); + +uint8_t get_slot_index(sdioio_sdcard_obj_t *); diff --git a/ports/espressif/common-hal/sdioio/__init__.c b/ports/espressif/common-hal/sdioio/__init__.c new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/common-hal/sdioio/__init__.h b/ports/espressif/common-hal/sdioio/__init__.h new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/espressif/common-hal/socketpool/Socket.c b/ports/espressif/common-hal/socketpool/Socket.c index 9fc04728a4d4c..5128e93c8589e 100644 --- a/ports/espressif/common-hal/socketpool/Socket.c +++ b/ports/espressif/common-hal/socketpool/Socket.c @@ -260,8 +260,7 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_ mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type")); } - socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); - sock->base.type = &socketpool_socket_type; + socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, &socketpool_socket_type); if (!_socketpool_socket(self, family, type, proto, sock)) { mp_raise_RuntimeError(MP_ERROR_TEXT("Out of sockets")); @@ -326,7 +325,9 @@ int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, } socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) { - socketpool_socket_obj_t *sock = m_new_obj_with_finaliser(socketpool_socket_obj_t); + // Set the socket type only after the socketpool_socket_accept succeeds, so that the + // finaliser is not called on a bad socket. + socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, NULL); int newsoc = socketpool_socket_accept(self, peer_out, NULL); if (newsoc > 0) { @@ -482,7 +483,7 @@ void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, socklen_t socklen = sizeof(error_code); result = getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen); if (result < 0 || error_code != 0) { - mp_raise_OSError(errno); + mp_raise_OSError(error_code); } self->connected = true; return; diff --git a/ports/espressif/common-hal/ssl/crt_bundle.c b/ports/espressif/common-hal/ssl/crt_bundle.c new file mode 100644 index 0000000000000..53a07f4db1b2c --- /dev/null +++ b/ports/espressif/common-hal/ssl/crt_bundle.c @@ -0,0 +1,37 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// In ESP-IDF v5.4, Espressif changed the format of the in-flash cert bundle, which +// made lib/mbedtls_config/crt_bundle.c no longer work. Rather than update that, +// just wrap those functions and use the ESP-IDF versions. + +#include "py/mperrno.h" +#include "mbedtls/x509_crt.h" +#include "lib/mbedtls_config/crt_bundle.h" +#include "esp_crt_bundle.h" + +static int convert_esp_err(esp_err_t ret) { + switch (ret) { + case ESP_OK: + return 0; + default: + // Right now esp_crt_bundle.c doesn't return very specific errors. + case ESP_ERR_INVALID_ARG: + return -MP_EINVAL; + } +} + +int crt_bundle_attach(mbedtls_ssl_config *ssl_conf) { + return convert_esp_err(esp_crt_bundle_attach(ssl_conf)); +} + +void crt_bundle_detach(mbedtls_ssl_config *conf) { + esp_crt_bundle_detach(conf); +} + +int crt_bundle_set(const uint8_t *x509_bundle, size_t bundle_size) { + return convert_esp_err(esp_crt_bundle_set(x509_bundle, bundle_size)); +} diff --git a/ports/espressif/common-hal/touchio/TouchIn.c b/ports/espressif/common-hal/touchio/TouchIn.c index 2a37e6e526fb8..147acb2cfbf19 100644 --- a/ports/espressif/common-hal/touchio/TouchIn.c +++ b/ports/espressif/common-hal/touchio/TouchIn.c @@ -9,9 +9,10 @@ #include "py/runtime.h" #include "peripherals/touch.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, - const mcu_pin_obj_t *pin) { + const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { if (pin->touch_channel == NO_TOUCH_CHANNEL) { raise_ValueError_invalid_pin(); } diff --git a/ports/espressif/common-hal/wifi/Radio.c b/ports/espressif/common-hal/wifi/Radio.c index 1e499b9d1d60b..dc5311bb8adc8 100644 --- a/ports/espressif/common-hal/wifi/Radio.c +++ b/ports/espressif/common-hal/wifi/Radio.c @@ -139,23 +139,44 @@ void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t esp_wifi_set_max_tx_power(tx_power * 4.0f); } -mp_int_t common_hal_wifi_radio_get_listen_interval(wifi_radio_obj_t *self) { - wifi_config_t *config = &self->sta_config; - return config->sta.listen_interval; +wifi_power_management_t common_hal_wifi_radio_get_power_management(wifi_radio_obj_t *self) { + wifi_ps_type_t ps; + esp_err_t ret = esp_wifi_get_ps(&ps); + if (ret == ESP_OK) { + switch (ps) { + case WIFI_PS_MIN_MODEM: + return POWER_MANAGEMENT_MIN; + case WIFI_PS_MAX_MODEM: + return POWER_MANAGEMENT_MAX; + case WIFI_PS_NONE: + return POWER_MANAGEMENT_NONE; + } + } + return POWER_MANAGEMENT_MIN; } -void common_hal_wifi_radio_set_listen_interval(wifi_radio_obj_t *self, const mp_int_t listen_interval) { - wifi_config_t *config = &self->sta_config; - config->sta.listen_interval = listen_interval; - if (listen_interval == 1) { - esp_wifi_set_ps(WIFI_PS_MIN_MODEM); - } else if (listen_interval > 1) { - esp_wifi_set_ps(WIFI_PS_MAX_MODEM); - } else { - esp_wifi_set_ps(WIFI_PS_NONE); - } - esp_wifi_set_config(ESP_IF_WIFI_STA, config); +void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_power_management_t power_management) { + switch (power_management) { + case POWER_MANAGEMENT_MIN: + esp_wifi_set_ps(WIFI_PS_MIN_MODEM); + break; + case POWER_MANAGEMENT_MAX: { + // listen_interval is only used in this case. + wifi_config_t *config = &self->sta_config; + // This is a typical value seen in various examples. + config->sta.listen_interval = 3; + esp_wifi_set_ps(WIFI_PS_MAX_MODEM); + esp_wifi_set_config(ESP_IF_WIFI_STA, config); + } + break; + case POWER_MANAGEMENT_NONE: + esp_wifi_set_ps(WIFI_PS_NONE); + break; + case POWER_MANAGEMENT_UNKNOWN: + // This should be prevented in shared-bindings. + break; + } } mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) { @@ -179,7 +200,7 @@ mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, u mp_raise_RuntimeError(MP_ERROR_TEXT("Already scanning for wifi networks")); } if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } set_mode_station(self, true); @@ -298,7 +319,7 @@ mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self) { wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) { if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } wifi_config_t *config = &self->sta_config; diff --git a/ports/espressif/common-hal/wifi/__init__.c b/ports/espressif/common-hal/wifi/__init__.c index c2a63ceede72a..0eacd2bab3ec0 100644 --- a/ports/espressif/common-hal/wifi/__init__.c +++ b/ports/espressif/common-hal/wifi/__init__.c @@ -40,6 +40,8 @@ wifi_radio_obj_t common_hal_wifi_radio_obj; #include "nvs_flash.h" #endif +#define MAC_ADDRESS_LENGTH 6 + static const char *TAG = "CP wifi"; static void schedule_background_on_cp_core(void *arg) { @@ -144,8 +146,8 @@ void common_hal_wifi_init(bool user_initiated) { common_hal_wifi_radio_obj.base.type = &wifi_radio_type; if (!wifi_ever_inited) { - ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(esp_netif_init()); wifi_ever_inited = true; } @@ -173,6 +175,7 @@ void common_hal_wifi_init(bool user_initiated) { &self->handler_instance_got_ip)); wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT(); + esp_err_t result = esp_wifi_init(&config); #ifdef CONFIG_ESP32_WIFI_NVS_ENABLED // Generally we don't use this because we store ssid and passwords ourselves in the filesystem. esp_err_t err = nvs_flash_init(); @@ -183,8 +186,10 @@ void common_hal_wifi_init(bool user_initiated) { err = nvs_flash_init(); } ESP_ERROR_CHECK(err); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH)); + #else + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); #endif - esp_err_t result = esp_wifi_init(&config); if (result == ESP_ERR_NO_MEM) { if (gc_alloc_possible()) { mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Failed to allocate Wifi memory")); @@ -197,6 +202,23 @@ void common_hal_wifi_init(bool user_initiated) { ESP_LOGE(TAG, "WiFi error code: %x", result); return; } + // Set the default lwip_local_hostname capped at 32 characters. We trim off + // the start of the board name (likely manufacturer) because the end is + // often more unique to the board. + size_t board_len = MIN(32 - ((MAC_ADDRESS_LENGTH * 2) + 6), strlen(CIRCUITPY_BOARD_ID)); + size_t board_trim = strlen(CIRCUITPY_BOARD_ID) - board_len; + // Avoid double _ in the hostname. + if (CIRCUITPY_BOARD_ID[board_trim] == '_') { + board_trim++; + } + + char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; + uint8_t mac[MAC_ADDRESS_LENGTH]; + esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); + snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + const char *default_lwip_local_hostname = cpy_default_hostname; + ESP_ERROR_CHECK(esp_netif_set_hostname(self->netif, default_lwip_local_hostname)); // set station mode to avoid the default SoftAP common_hal_wifi_radio_start_station(self); // start wifi diff --git a/ports/espressif/esp-camera b/ports/espressif/esp-camera index d529ebdffb841..243560e94997c 160000 --- a/ports/espressif/esp-camera +++ b/ports/espressif/esp-camera @@ -1 +1 @@ -Subproject commit d529ebdffb84131b1aadaec32a7373b319b70391 +Subproject commit 243560e94997c262565ed537154b0578b8ce2197 diff --git a/ports/espressif/esp-idf b/ports/espressif/esp-idf index aa149243fa332..1d2c73f641af7 160000 --- a/ports/espressif/esp-idf +++ b/ports/espressif/esp-idf @@ -1 +1 @@ -Subproject commit aa149243fa332f46799aa9c9b4cc6be92d7c4cda +Subproject commit 1d2c73f641af70c24274e2d3e74641592bee97e5 diff --git a/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2-large-user_fs.csv b/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2-large-user_fs.csv new file mode 100644 index 0000000000000..59e0d9d1212bf --- /dev/null +++ b/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2-large-user_fs.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size +# bootloader, app, boot, 0x1000/0x0, 28/32K +# partition_table, data, table, 0x8000, 4K +nvs, data, nvs, 0x9000, 20K +otadata, data, ota, 0xe000, 8K +ota_0, app, ota_0, 0x10000, 2048K +user_fs, data, fat, 0x210000, 1984K diff --git a/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2.csv b/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2.csv index 59e0d9d1212bf..49d043d767252 100644 --- a/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2.csv +++ b/ports/espressif/esp-idf-config/partitions-4MB-no-ota-no-uf2.csv @@ -3,5 +3,5 @@ # partition_table, data, table, 0x8000, 4K nvs, data, nvs, 0x9000, 20K otadata, data, ota, 0xe000, 8K -ota_0, app, ota_0, 0x10000, 2048K -user_fs, data, fat, 0x210000, 1984K +ota_0, app, ota_0, 0x10000, 2816K +user_fs, data, fat, 0x2d0000, 1216K diff --git a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults index 064813abe8482..368ba81bb4aa7 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-debug.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-debug.defaults @@ -7,6 +7,21 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # end of Compiler options +# Bootloader config +# +# +# Log +# +# +# Format +# +CONFIG_BOOTLOADER_LOG_COLORS=y +# end of Format + +# end of Log + +# end of Bootloader config + # # Component config # @@ -15,8 +30,21 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y # CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y CONFIG_ESP_PANIC_HANDLER_IRAM=y +CONFIG_ESP_CONSOLE_SECONDARY_NONE=y +# CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is not set # end of ESP System Settings +# +# Log +# +# +# Format +# +CONFIG_LOG_COLORS=y +# end of Format + +# end of Log + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults index bf9e57494c73e..19c73ca5ee5ca 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c2.defaults @@ -1,6 +1,10 @@ # # Espressif IoT Development Framework Configuration # +# Compiler options +# +CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y +# end of Compiler options # # Component config # diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults index bf9e57494c73e..19c73ca5ee5ca 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c3.defaults @@ -1,6 +1,10 @@ # # Espressif IoT Development Framework Configuration # +# Compiler options +# +CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS=y +# end of Compiler options # # Component config # diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults index 85dde905f3caa..63f42cac95244 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c6.defaults @@ -49,6 +49,12 @@ CONFIG_ESP_PHY_ENABLE_USB=y CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 # end of Wi-Fi +# +# mbedTLS +# +# CONFIG_MBEDTLS_HARDWARE_SHA is not set +# end of mbedTLS + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults new file mode 100644 index 0000000000000..85dde905f3caa --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32c61.defaults @@ -0,0 +1,54 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y +# +# NimBLE Options +# +CONFIG_BT_NIMBLE_LOG_LEVEL_NONE=y +CONFIG_BT_NIMBLE_NVS_PERSIST=y +# +# Memory Settings +# +CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=20 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 +# end of Memory Settings + +CONFIG_BT_NIMBLE_EXT_ADV=y +# end of NimBLE Options + +# end of Bluetooth + +# +# Driver Configurations +# +# +# PCNT Configuration +# +CONFIG_PCNT_CTRL_FUNC_IN_IRAM=y +# end of PCNT Configuration + +# end of Driver Configurations + +# +# PHY +# +CONFIG_ESP_PHY_ENABLE_USB=y +# end of PHY + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=4 +# end of Wi-Fi + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32p4.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32p4.defaults new file mode 100644 index 0000000000000..0806066e20bcc --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32p4.defaults @@ -0,0 +1,21 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Component config +# +# +# Bluetooth +# +# CONFIG_BT_ENABLED is not set +# end of Bluetooth + +# +# mbedTLS +# +# CONFIG_MBEDTLS_CMAC_C is not set +# end of mbedTLS + +# end of Component config + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults index 66e06667a1a81..101f90f9fa4fe 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s2.defaults @@ -55,9 +55,15 @@ CONFIG_ULP_COPROC_ENABLED=y CONFIG_ULP_COPROC_TYPE_FSM=y CONFIG_ULP_COPROC_TYPE_RISCV=y # Note: enabling both ULPs simultaneously only works due to a modification of adafruit/esp-idf # (see adafruit/esp-idf/pull/16) until espressif/esp-idf/issues/12999 is fixed. -CONFIG_ULP_COPROC_RESERVE_MEM=8176 +CONFIG_ULP_COPROC_RESERVE_MEM=8144 # end of Ultra Low Power (ULP) Co-processor +# +# FreeRTOS +# +CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y +# end of FreeRTOS + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults index fe3c3e0a2da88..2553c648018bd 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-esp32s3.defaults @@ -95,7 +95,7 @@ CONFIG_ULP_COPROC_ENABLED=y CONFIG_ULP_COPROC_TYPE_FSM=y CONFIG_ULP_COPROC_TYPE_RISCV=y # Note: enabling both ULPs simultaneously only works due to a modification of adafruit/esp-idf # (see adafruit/esp-idf/pull/16) until espressif/esp-idf/issues/12999 is fixed. -CONFIG_ULP_COPROC_RESERVE_MEM=8176 +CONFIG_ULP_COPROC_RESERVE_MEM=8144 # end of Ultra Low Power (ULP) Co-processor # end of Component config diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults new file mode 100644 index 0000000000000..6a2285a2936aa --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-120m.defaults @@ -0,0 +1,2 @@ +CONFIG_ESPTOOLPY_FLASHFREQ_120M=y +CONFIG_SPI_FLASH_UNDER_HIGH_FREQ=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-40m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-40m.defaults index 235a62a57ee0a..ffc4b5c1cb8fe 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-40m.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-40m.defaults @@ -1,14 +1 @@ -# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_64M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_60M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_48M is not set CONFIG_ESPTOOLPY_FLASHFREQ_40M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_32M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_30M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_24M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_16M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_15M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_80M_DEFAULT is not set diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-48m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-48m.defaults index b710fd22554e1..f6838e88703b7 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-48m.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-48m.defaults @@ -1,14 +1 @@ -# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_64M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_60M is not set CONFIG_ESPTOOLPY_FLASHFREQ_48M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_32M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_30M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_24M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_16M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_15M is not set -CONFIG_ESPTOOLPY_FLASHFREQ_48M_DEFAULT=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-4MB-no-ota-no-uf2-large-user_fs.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-4MB-no-ota-no-uf2-large-user_fs.defaults new file mode 100644 index 0000000000000..0a585e9d523e5 --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-4MB-no-ota-no-uf2-large-user_fs.defaults @@ -0,0 +1,25 @@ +# +# Espressif IoT Development Framework Configuration +# +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# end of Serial flasher config + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-4MB-no-ota-no-uf2-large-user_fs.csv" +CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-4MB-no-ota-no-uf2-large-user_fs.csv" +# end of Partition Table + +# end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-60m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-60m.defaults index 7068d0ce74082..797665f527fb9 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-60m.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-60m.defaults @@ -1,14 +1 @@ -# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_80M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_64M is not set CONFIG_ESPTOOLPY_FLASHFREQ_60M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_48M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_32M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_30M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_24M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_16M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_15M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_80M_DEFAULT is not set diff --git a/ports/espressif/esp-idf-config/sdkconfig-flash-80m.defaults b/ports/espressif/esp-idf-config/sdkconfig-flash-80m.defaults index 2ea4419003797..7014fa95495b2 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-flash-80m.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-flash-80m.defaults @@ -1,14 +1 @@ -# CONFIG_ESPTOOLPY_FLASHFREQ_120M is not set CONFIG_ESPTOOLPY_FLASHFREQ_80M=y -# CONFIG_ESPTOOLPY_FLASHFREQ_64M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_60M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_48M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_32M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_30M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_24M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_16M is not set -# CONFIG_ESPTOOLPY_FLASHFREQ_15M is not set -CONFIG_ESPTOOLPY_FLASHFREQ_80M_DEFAULT=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults index 16f5b990386a1..0da23e8122762 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-opt.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-opt.defaults @@ -38,6 +38,24 @@ CONFIG_ESP_CONSOLE_SECONDARY_NONE=y CONFIG_LOG_DEFAULT_LEVEL_NONE=y # end of Log output +# +# Log +# +# +# Log Level +# +# +# Level Settings +# +# CONFIG_LOG_DYNAMIC_LEVEL_CONTROL is not set +CONFIG_LOG_TAG_LEVEL_IMPL_NONE=y +# CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST is not set +# end of Level Settings + +# end of Log Level + +# end of Log + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig-psram-200m.defaults b/ports/espressif/esp-idf-config/sdkconfig-psram-200m.defaults new file mode 100644 index 0000000000000..8fdb028c734ed --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-psram-200m.defaults @@ -0,0 +1,4 @@ +# For ESP32-P4 +CONFIG_SPIRAM_SPEED_200M=y +# CONFIG_SPIRAM_SPEED_20M is not set +CONFIG_SPIRAM_SPEED=200 diff --git a/ports/espressif/esp-idf-config/sdkconfig-psram-32MB.defaults b/ports/espressif/esp-idf-config/sdkconfig-psram-32MB.defaults new file mode 100644 index 0000000000000..9494e7dece8c6 --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-psram-32MB.defaults @@ -0,0 +1,4 @@ +# CONFIG_SPIRAM_TYPE_AUTO is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set +# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set +CONFIG_SPIRAM_TYPE_AUTO=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-psram-hpi.defaults b/ports/espressif/esp-idf-config/sdkconfig-psram-hpi.defaults new file mode 100644 index 0000000000000..4795ee78772a4 --- /dev/null +++ b/ports/espressif/esp-idf-config/sdkconfig-psram-hpi.defaults @@ -0,0 +1,3 @@ +# CONFIG_SPIRAM_MODE_QUAD is not set +# CONFIG_SPIRAM_MODE_OCT is not set +CONFIG_SPIRAM_MODE_HEX=y diff --git a/ports/espressif/esp-idf-config/sdkconfig-psram.defaults b/ports/espressif/esp-idf-config/sdkconfig-psram.defaults index 3d4dc69178edb..6dafa51ed1d38 100644 --- a/ports/espressif/esp-idf-config/sdkconfig-psram.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig-psram.defaults @@ -22,6 +22,11 @@ CONFIG_SPIRAM_USE_CAPS_ALLOC=y CONFIG_ESP_WIFI_CACHE_TX_BUFFER_NUM=16 # end of Wi-Fi +# +# mbedTLS +# +CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y + # end of Component config # end of Espressif IoT Development Framework Configuration diff --git a/ports/espressif/esp-idf-config/sdkconfig.defaults b/ports/espressif/esp-idf-config/sdkconfig.defaults index c4b427cb49622..5c4d6a31a62c1 100644 --- a/ports/espressif/esp-idf-config/sdkconfig.defaults +++ b/ports/espressif/esp-idf-config/sdkconfig.defaults @@ -20,6 +20,12 @@ CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y CONFIG_GPTIMER_ISR_IRAM_SAFE=y # end of GPTimer Configuration +# +# Touch Configuration +# +CONFIG_TOUCH_SUPPRESS_DEPRECATE_WARN=y +# end of Touch Configuration + # end of Driver Configurations # @@ -39,6 +45,7 @@ CONFIG_PM_ENABLE=y # required for CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 # CONFIG_ESP_TASK_WDT_INIT is not set # CONFIG_ESP_DEBUG_OCDAWARE is not set +# CONFIG_ESP_SYSTEM_HW_STACK_GUARD is not set # end of ESP System Settings @@ -58,6 +65,13 @@ CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 CONFIG_FREERTOS_HZ=1000 # end of Kernel +# +# LibC +# +# end of LWIP +CONFIG_LIBC_OPTIMIZED_MISALIGNED_ACCESS=y +# end of LibC + # # LWIP # @@ -67,19 +81,9 @@ CONFIG_LWIP_SO_RCVBUF=y # IPv6 # CONFIG_LWIP_IPV6_AUTOCONFIG=y -CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 +CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=0 CONFIG_LWIP_IPV6_DHCP6=y # -# TCP -# -CONFIG_LWIP_MAX_ACTIVE_TCP=4 -CONFIG_LWIP_MAX_LISTENING_TCP=4 -CONFIG_LWIP_TCP_SYNMAXRTX=6 -CONFIG_LWIP_TCP_SND_BUF_DEFAULT=2880 -CONFIG_LWIP_TCP_WND_DEFAULT=2880 -CONFIG_LWIP_TCP_RTO_TIME=3000 -# end of TCP - # end of LWIP # @@ -95,9 +99,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048 # # Certificate Bundle # -CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y -CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y -CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH="../../lib/certificates/data/roots.pem" +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y # end of Certificate Bundle # CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER is not set @@ -123,6 +125,7 @@ CONFIG_MBEDTLS_SSL_PROTO_DTLS=y # CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED is not set # CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED is not set # CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_ERROR_STRINGS is not set # end of mbedTLS # diff --git a/ports/espressif/esp-protocols b/ports/espressif/esp-protocols index ea54eef0d0fe5..2f492c0228901 160000 --- a/ports/espressif/esp-protocols +++ b/ports/espressif/esp-protocols @@ -1 +1 @@ -Subproject commit ea54eef0d0fe59bd53a49c916f87065518b957eb +Subproject commit 2f492c02289015ecbb36851dd1bd04e0eb0a9937 diff --git a/ports/espressif/microros-lib b/ports/espressif/microros-lib new file mode 160000 index 0000000000000..4b2a696dec7f0 --- /dev/null +++ b/ports/espressif/microros-lib @@ -0,0 +1 @@ +Subproject commit 4b2a696dec7f0f865e014ea4b83f2332df7e9560 diff --git a/ports/espressif/module/cardputer_keyboard.c b/ports/espressif/module/cardputer_keyboard.c new file mode 100644 index 0000000000000..548275001acc5 --- /dev/null +++ b/ports/espressif/module/cardputer_keyboard.c @@ -0,0 +1,239 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/objstr.h" +#include "py/runtime.h" + +#include "supervisor/shared/serial.h" +#include "shared-bindings/keypad/EventQueue.h" +#include "shared-bindings/keypad_demux/DemuxKeyMatrix.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/keypad/EventQueue.h" +#include "shared-module/keypad_demux/DemuxKeyMatrix.h" +#include "supervisor/shared/reload.h" + +#include "cardputer_keymap.h" + +//| """M5Stack Cardputer keyboard integration. +//| """ +//| +//| """The KEYBOARD object is an instance of DemuxKeyMatrix, configured with correct pins. +//| The pins cannot be used for any other purposes (even though exposed in the board module). +//| By default all keyboard events are consumed and routed to the standard input - there is +//| not much use of the KEYBOARD object in this configuration - just read the input via sys.stdin. +//| +//| If you need to manually process individual key up / key down events via KEYBOARD.events, +//| call `detach_serial()`. +//| """" +//| KEYBOARD: keypad_demux.DemuxKeymatrix +//| + +keypad_demux_demuxkeymatrix_obj_t cardputer_keyboard; +static bool cardputer_keyboard_serial_attached = false; + +// Forward declarations. +static void keyboard_seq(const char *seq); +static void update_keyboard(keypad_eventqueue_obj_t *queue); + +//| def detach_serial() -> None: +//| """Stops consuming keyboard events and routing them to sys.stdin.""" +//| ... +//| +static mp_obj_t detach_serial(void) { + cardputer_keyboard_serial_attached = false; + common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard.events, NULL); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(detach_serial_obj, detach_serial); + +//| def attach_serial() -> None: +//| """Starts consuming keyboard events and routing them to sys.stdin.""" +//| ... +//| +static mp_obj_t attach_serial(void) { + common_hal_keypad_eventqueue_set_event_handler(cardputer_keyboard.events, update_keyboard); + cardputer_keyboard_serial_attached = true; + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_0(attach_serial_obj, attach_serial); + +//| def key_to_char(key: int, shifted: bool) -> str | None: +//| """Converts a key index to the respective key (with or without shift modifier). +//| Returns None for functional & modifier keys or whenever not 0 <= key < 56. +//| """ +//| ... +//| +static mp_obj_t key_to_char(mp_obj_t key_obj, mp_obj_t shifted_obj) { + mp_int_t key = mp_obj_get_int(key_obj); + if (key < 0 || key > (mp_int_t)(sizeof keymap / sizeof *keymap) || keymap[key] == 0) { + return mp_const_none; + } else if (shifted_obj == mp_const_true) { + return mp_obj_new_str(&keymap_shifted[key], 1); + } else { + return mp_obj_new_str(&keymap[key], 1); + } +} +static MP_DEFINE_CONST_FUN_OBJ_2(key_to_char_obj, key_to_char); + +// Ring buffer of characters consumed from keyboard events (when serial attached) +static ringbuf_t keyqueue; +static char keybuf[32]; + +keypad_event_obj_t event; +static char keystate[56] = {0}; + +// Keyboard pins +static const mcu_pin_obj_t *row_addr_pins[] = { + &pin_GPIO8, + &pin_GPIO9, + &pin_GPIO11, +}; + +static const mcu_pin_obj_t *column_pins[] = { + &pin_GPIO13, + &pin_GPIO15, + &pin_GPIO3, + &pin_GPIO4, + &pin_GPIO5, + &pin_GPIO6, + &pin_GPIO7 +}; + +static void cardputer_keyboard_init(void) { + common_hal_keypad_demux_demuxkeymatrix_construct( + &cardputer_keyboard, // self + MP_ARRAY_SIZE(row_addr_pins), // num_row_addr_pins + row_addr_pins, // row_addr_pins + MP_ARRAY_SIZE(column_pins), // num_column_pins + column_pins, // column_pins + true, // columns_to_anodes + false, // transpose + 0.01f, // interval + 20, // max_events + 2, // debounce_threshold + false // use_gc_allocator + ); + + demuxkeymatrix_never_reset(&cardputer_keyboard); + ringbuf_init(&keyqueue, (uint8_t *)keybuf, sizeof(keybuf)); + attach_serial(); +} + +// Overrides the weakly linked function from supervisor/shared/serial.c +void board_serial_init(void) { + cardputer_keyboard_init(); +} + +// Overrides the weakly linked function from supervisor/shared/serial.c +bool board_serial_connected(void) { + return cardputer_keyboard_serial_attached; +} + +// Overrides the weakly linked function from supervisor/shared/serial.c +uint32_t board_serial_bytes_available(void) { + if (cardputer_keyboard_serial_attached) { + return ringbuf_num_filled(&keyqueue); + } else { + return 0; + } +} + +// Overrides the weakly linked function from supervisor/shared/serial.c +char board_serial_read(void) { + if (cardputer_keyboard_serial_attached) { + return ringbuf_get(&keyqueue); + } else { + return 0; + } +} + +static void keyboard_seq(const char *seq) { + while (*seq) { + ringbuf_put(&keyqueue, *seq++); + } +} + +static void update_keyboard(keypad_eventqueue_obj_t *queue) { + uint8_t ascii = 0; + + if (common_hal_keypad_eventqueue_get_length(queue) == 0) { + return; + } + + while (common_hal_keypad_eventqueue_get_into(queue, &event)) { + if (event.pressed) { + keystate[event.key_number] = 1; + + if (keystate[KEY_CTRL]) { + if (keystate[KEY_ALT] && keystate[KEY_BACKSPACE]) { + reload_initiate(RUN_REASON_REPL_RELOAD); + } + ascii = keymap[event.key_number]; + if (ascii >= 'a' && ascii <= 'z') { + ascii -= 'a' - 1; + } + + if (ascii == mp_interrupt_char) { + mp_sched_keyboard_interrupt(); + } + } else if (keystate[KEY_SHIFT]) { + ascii = keymap_shifted[event.key_number]; + } else if (keystate[KEY_FN] && event.key_number != KEY_FN) { + switch (event.key_number | FN_MOD) + { + case KEY_DOWN: + keyboard_seq("\e[B"); + break; + case KEY_UP: + keyboard_seq("\e[A"); + break; + case KEY_DELETE: + keyboard_seq("\e[3~"); + break; + case KEY_LEFT: + keyboard_seq("\e[D"); + break; + case KEY_RIGHT: + keyboard_seq("\e[C"); + break; + case KEY_ESC: + ringbuf_put(&keyqueue, '\e'); + break; + } + } else { + ascii = keymap[event.key_number]; + } + + if (ascii > 0) { + if (keystate[KEY_ALT]) { + ringbuf_put(&keyqueue, '\e'); + } else if (keystate[KEY_OPT]) { + ringbuf_put(&keyqueue, '\x10'); + } + ringbuf_put(&keyqueue, ascii); + } + } else { + keystate[event.key_number] = 0; + } + } +} + +static const mp_rom_map_elem_t cardputer_keyboard_module_globals_table[] = { + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cardputer_keyboard)}, + {MP_ROM_QSTR(MP_QSTR_KEYBOARD), MP_ROM_PTR(&cardputer_keyboard)}, + {MP_ROM_QSTR(MP_QSTR_attach_serial), MP_ROM_PTR(&attach_serial_obj)}, + {MP_ROM_QSTR(MP_QSTR_detach_serial), MP_ROM_PTR(&detach_serial_obj)}, + {MP_ROM_QSTR(MP_QSTR_key_to_char), MP_ROM_PTR(&key_to_char_obj)}, +}; +MP_DEFINE_CONST_DICT(cardputer_keyboard_module_globals, cardputer_keyboard_module_globals_table); + +const mp_obj_module_t cardputer_keyboard_module = { + .base = {&mp_type_module}, + .globals = (mp_obj_dict_t *)&cardputer_keyboard_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_cardputer_keyboard, cardputer_keyboard_module); diff --git a/ports/espressif/module/cardputer_keymap.h b/ports/espressif/module/cardputer_keymap.h new file mode 100644 index 0000000000000..0256fafaa0f57 --- /dev/null +++ b/ports/espressif/module/cardputer_keymap.h @@ -0,0 +1,214 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define SHIFT_MOD 0x40 +#define FN_MOD 0x80 + +#define KEY_OPT 0 +#define KEY_Z 1 +#define KEY_C 2 +#define KEY_B 3 +#define KEY_M 4 +#define KEY_DOT 5 +#define KEY_SPACE 6 +#define KEY_SHIFT 7 +#define KEY_S 8 +#define KEY_F 9 +#define KEY_H 10 +#define KEY_K 11 +#define KEY_SEMICOLON 12 +#define KEY_ENTER 13 +#define KEY_Q 14 +#define KEY_E 15 +#define KEY_T 16 +#define KEY_U 17 +#define KEY_O 18 +#define KEY_LEFT_BRACKET 19 +#define KEY_BACKSLASH 20 +#define KEY_1 21 +#define KEY_3 22 +#define KEY_5 23 +#define KEY_7 24 +#define KEY_9 25 +#define KEY_UNDERSCORE 26 +#define KEY_BACKSPACE 27 +#define KEY_CTRL 28 +#define KEY_ALT 29 +#define KEY_X 30 +#define KEY_V 31 +#define KEY_N 32 +#define KEY_COMMA 33 +#define KEY_SLASH 34 +#define KEY_FN 35 +#define KEY_A 36 +#define KEY_D 37 +#define KEY_G 38 +#define KEY_J 39 +#define KEY_L 40 +#define KEY_APOSTROPHE 41 +#define KEY_TAB 42 +#define KEY_W 43 +#define KEY_R 44 +#define KEY_Y 45 +#define KEY_I 46 +#define KEY_P 47 +#define KEY_RIGHT_BRACKET 48 +#define KEY_GRAVE 49 +#define KEY_2 50 +#define KEY_4 51 +#define KEY_6 52 +#define KEY_8 53 +#define KEY_0 54 +#define KEY_EQUALS 55 + +#define KEY_GREATER (5 | SHIFT_MOD) +#define KEY_COLON (12 | SHIFT_MOD) +#define KEY_LEFT_CURLY_BRACKET (19 | SHIFT_MOD) +#define KEY_PIPE (20 | SHIFT_MOD) +#define KEY_EXCLAMATION (21 | SHIFT_MOD) +#define KEY_HASH (22 | SHIFT_MOD) +#define KEY_PERCENT (23 | SHIFT_MOD) +#define KEY_AMPERSAND (24 | SHIFT_MOD) +#define KEY_OPEN_PARENTHESIS (25 | SHIFT_MOD) +#define KEY_MINUS (26 | SHIFT_MOD) +#define KEY_LESS (33 | SHIFT_MOD) +#define KEY_QUESTION (34 | SHIFT_MOD) +#define KEY_DOUBLE_QUOTE (41 | SHIFT_MOD) +#define KEY_RIGHT_CURLY_BRACKET (48 | SHIFT_MOD) +#define KEY_TILDE (49 | SHIFT_MOD) +#define KEY_AT (50 | SHIFT_MOD) +#define KEY_DOLLAR (51 | SHIFT_MOD) +#define KEY_CARET (52 | SHIFT_MOD) +#define KEY_ASTERISK (53 | SHIFT_MOD) +#define KEY_CLOSE_PARENTHESIS (54 | SHIFT_MOD) +#define KEY_PLUS (55 | SHIFT_MOD) + +#define KEY_DOWN (5 | FN_MOD) +#define KEY_UP (12 | FN_MOD) +#define KEY_DELETE (27 | FN_MOD) +#define KEY_LEFT (33 | FN_MOD) +#define KEY_RIGHT (34 | FN_MOD) +#define KEY_ESC (49 | FN_MOD) + +const char keymap[56] = { + 0, // KEY_OPT + 'z', // KEY_Z + 'c', // KEY_C + 'b', // KEY_B + 'm', // KEY_M + '.', // KEY_DOT + ' ', // KEY_SPACE + 0, // KEY_SHIFT + 's', // KEY_S + 'f', // KEY_F + 'h', // KEY_H + 'k', // KEY_K + ';', // KEY_SEMICOLON + '\r',// KEY_ENTER + 'q', // KEY_Q + 'e', // KEY_E + 't', // KEY_T + 'u', // KEY_U + 'o', // KEY_O + '[', // KEY_LEFT_BRACKET + '\\',// KEY_BACKSLASH + '1', // KEY_1 + '3', // KEY_3 + '5', // KEY_5 + '7', // KEY_7 + '9', // KEY_9 + '_', // KEY_UNDERSCORE + '\b',// KEY_BACKSPACE + 0, // KEY_CTRL + 0, // KEY_ALT + 'x', // KEY_X + 'v', // KEY_V + 'n', // KEY_N + ',', // KEY_COMMA + '/', // KEY_SLASH + 0, // KEY_FN + 'a', // KEY_A + 'd', // KEY_D + 'g', // KEY_G + 'j', // KEY_J + 'l', // KEY_L + '\'',// KEY_APOSTROPHE + '\t',// KEY_TAB + 'w', // KEY_W + 'r', // KEY_R + 'y', // KEY_Y + 'i', // KEY_I + 'p', // KEY_P + ']', // KEY_RIGHT_BRACKET + '`', // KEY_GRAVE + '2', // KEY_2 + '4', // KEY_4 + '6', // KEY_6 + '8', // KEY_8 + '0', // KEY_0 + '=' // KEY_EQUALS +}; + +const char keymap_shifted[56] = { + 0, // KEY_OPT + 'Z', // KEY_Z + 'C', // KEY_C + 'B', // KEY_B + 'M', // KEY_M + '>', // KEY_DOT -> '>' + ' ', // KEY_SPACE + 0, // KEY_SHIFT + 'S', // KEY_S + 'F', // KEY_F + 'H', // KEY_H + 'K', // KEY_K + ':', // KEY_SEMICOLON -> ':' + '\r',// KEY_ENTER + 'Q', // KEY_Q + 'E', // KEY_E + 'T', // KEY_T + 'U', // KEY_U + 'O', // KEY_O + '{', // KEY_LEFT_BRACKET -> '{' + '|', // KEY_BACKSLASH -> '|' + '!', // KEY_1 -> '!' + '#', // KEY_3 -> '#' + '%', // KEY_5 -> '%' + '&', // KEY_7 -> '&' + '(', // KEY_9 -> '(' + '-', // KEY_UNDERSCORE -> '-' + '\b',// KEY_BACKSPACE + 0, // KEY_CTRL + 0, // KEY_ALT + 'X', // KEY_X + 'V', // KEY_V + 'N', // KEY_N + '<', // KEY_COMMA -> '<' + '?', // KEY_SLASH -> '?' + 0, // KEY_FN + 'A', // KEY_A + 'D', // KEY_D + 'G', // KEY_G + 'J', // KEY_J + 'L', // KEY_L + '"', // KEY_APOSTROPHE -> '"' + '\t',// KEY_TAB + 'W', // KEY_W + 'R', // KEY_R + 'Y', // KEY_Y + 'I', // KEY_I + 'P', // KEY_P + '}', // KEY_RIGHT_BRACKET -> '}' + '~', // KEY_GRAVE -> '~' + '@', // KEY_2 -> '@' + '$', // KEY_4 -> '$' + '^', // KEY_6 -> '^' + '*', // KEY_8 -> '*' + ')', // KEY_0 -> ')' + '+' // KEY_EQUALS -> '+' +}; diff --git a/ports/espressif/mpconfigport.h b/ports/espressif/mpconfigport.h index 98c1986240b73..7f1a581571eb2 100644 --- a/ports/espressif/mpconfigport.h +++ b/ports/espressif/mpconfigport.h @@ -22,9 +22,12 @@ #define MICROPY_NLR_SETJMP (1) #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 +// PSRAM can require more stack space for GC. +#define MICROPY_ALLOC_GC_STACK_SIZE (128) + // Nearly all boards have this because it is used to enter the ROM bootloader. #ifndef CIRCUITPY_BOOT_BUTTON - #if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) + #if defined(CONFIG_IDF_TARGET_ESP32C2) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6) || defined(CONFIG_IDF_TARGET_ESP32H2) || defined(CONFIG_IDF_TARGET_ESP32C61) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO9) #elif !defined(CONFIG_IDF_TARGET_ESP32) #define CIRCUITPY_BOOT_BUTTON (&pin_GPIO0) @@ -65,3 +68,7 @@ extern portMUX_TYPE background_task_mutex; #ifndef CIRCUITPY_WIFI_DEFAULT_TX_POWER #define CIRCUITPY_WIFI_DEFAULT_TX_POWER (20) #endif + +#ifndef CIRCUITPY_ESP32P4_SWAP_LSFS +#define CIRCUITPY_ESP32P4_SWAP_LSFS (0) +#endif diff --git a/ports/espressif/mpconfigport.mk b/ports/espressif/mpconfigport.mk index e1bbea5c12eee..67f8ca2987bd8 100644 --- a/ports/espressif/mpconfigport.mk +++ b/ports/espressif/mpconfigport.mk @@ -1,18 +1,50 @@ -# Use internal flash for CIRCUITPY drive +# This file is part of the CircuitPython project: https://circuitpython.org +# +# SPDX-FileCopyrightText: Copyright (c) 2025 Adafruit Industries +# +# SPDX-License-Identifier: MIT + + +ifeq ($(IDF_TARGET),esp32c2) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32c3) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32p4) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32c6) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32c61) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else ifeq ($(IDF_TARGET),esp32h2) +IDF_TARGET_ARCH = riscv +CROSS_COMPILE = riscv32-esp-elf- +else +IDF_TARGET_ARCH = xtensa +CROSS_COMPILE = xtensa-$(IDF_TARGET)-elf- +endif + +# Use "internal flash" for CIRCUITPY drive. +# Even thought it's an external flash chip, it appears as internal. INTERNAL_FLASH_FILESYSTEM = 1 # Internal math library is substantially smaller than toolchain one INTERNAL_LIBM = 0 -# Longints can be implemented as mpz, as longlong, or not +# Longints can be implemented as MPZ, as LONGLONG, or NONE LONGINT_IMPL = MPZ # Default to no-psram CIRCUITPY_ESP_PSRAM_SIZE ?= 0 -# New 4MB boards will not have OTA support but more room for alarm, ble and other -# newer features. -CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT ?= 0 +# Some 4MB non-USB boards were initially defined with 2MB firmware, almost 2MB user_fs partitions. +# Others were defined with 1.4M+1.4M (now a single 2.8MB) firmware partitions / 1.2MB user_fs. +# Keep the former as is, so that the user filesystem will be unchanged. +CIRCUITPY_4MB_FLASH_LARGE_USER_FS_LAYOUT ?= 0 # Enable more features CIRCUITPY_FULL_BUILD ?= 1 @@ -20,19 +52,25 @@ CIRCUITPY_FULL_BUILD ?= 1 # If SSL is enabled, it's mbedtls CIRCUITPY_SSL_MBEDTLS = 1 -# Wifi Power Save -CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL = 1 +# Never use our copy of MBEDTLS +CIRCUITPY_HASHLIB_MBEDTLS_ONLY = 0 +CIRCUITPY_PORT_SERIAL = 1 + +CIRCUITPY_LIB_TLSF = 0 + +CIRCUITPY_LIBC_STRING0 = 0 # These modules are implemented in ports//common-hal: +CIRCUITPY__EVE ?= 1 CIRCUITPY_ALARM ?= 1 CIRCUITPY_ALARM_TOUCH ?= 0 CIRCUITPY_ANALOGBUFIO ?= 1 CIRCUITPY_AUDIOBUSIO ?= 1 CIRCUITPY_AUDIOBUSIO_PDMIN ?= 0 -CIRCUITPY_AUDIOIO ?= 0 -CIRCUITPY_BLEIO ?= 1 +CIRCUITPY_AUDIOIO ?= 1 CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BLEIO_NATIVE ?= 1 CIRCUITPY_CANIO ?= 1 CIRCUITPY_COUNTIO ?= 1 CIRCUITPY_ESPCAMERA ?= 1 @@ -44,33 +82,35 @@ CIRCUITPY_HASHLIB ?= 1 CIRCUITPY_I2CTARGET ?= 0 CIRCUITPY_MAX3421E ?= 1 CIRCUITPY_MEMORYMAP ?= 1 +CIRCUITPY_RCLCPY ?= 0 CIRCUITPY_NVM ?= 1 CIRCUITPY_PARALLELDISPLAYBUS ?= 1 CIRCUITPY_PS2IO ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_ROTARYIO ?= 1 +CIRCUITPY_SDIOIO ?= 1 +CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY ?= 1 CIRCUITPY_SYNTHIO_MAX_CHANNELS ?= 12 CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1 CIRCUITPY_WATCHDOG ?= 1 CIRCUITPY_WIFI ?= 1 CIRCUITPY_SOCKETPOOL_IPV6 ?= 1 -# Enable _eve module -CIRCUITPY__EVE ?= 1 - -# Conditionally turn off modules/features +# Conditionally turn off modules/features per chip type +#### esp32 ############################################################ ifeq ($(IDF_TARGET),esp32) # Modules CIRCUITPY_ALARM_TOUCH = 1 CIRCUITPY_RGBMATRIX = 0 -# Features +# Has no USB CIRCUITPY_USB_DEVICE = 0 +#### esp32c2 ########################################################## else ifeq ($(IDF_TARGET),esp32c2) -# C2 ROM spits out the UART at 74880 when connected to a 26mhz crystal! Debug -# prints will default to that too. +# C2 ROM spits out the UART at 74880 when connected to a 26mhz crystal! +# Debug prints will default to that too. # Modules CIRCUITPY_ESPCAMERA = 0 CIRCUITPY_ESPULP = 0 @@ -93,17 +133,24 @@ CIRCUITPY_ANALOGBUFIO = 0 # No I2S CIRCUITPY_AUDIOBUSIO = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No RMT CIRCUITPY_NEOPIXEL_WRITE = 0 CIRCUITPY_PULSEIO = 0 CIRCUITPY_RGBMATRIX = 0 +# No SDMMC +CIRCUITPY_SDIOIO = 0 + CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG = 0 +#### esp32c3 ########################################################## else ifeq ($(IDF_TARGET),esp32c3) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -113,17 +160,24 @@ CIRCUITPY_MEMORYMAP = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No PCNT peripheral CIRCUITPY_FREQUENCYIO = 0 CIRCUITPY_COUNTIO = 0 CIRCUITPY_ROTARYIO = 0 +# No SDMMC +CIRCUITPY_SDIOIO = 0 + CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 +#### esp32c6 ########################################################## else ifeq ($(IDF_TARGET),esp32c6) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -131,18 +185,64 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + +# No space for this +CIRCUITPY_AUDIOBUSIO = 0 + +# No I80 support from the IDF +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +# No SDMMC +CIRCUITPY_SDIOIO = 0 + +CIRCUITPY_TOUCHIO ?= 1 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 +# Features +CIRCUITPY_USB_DEVICE = 0 +CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 + +#### esp32c6 ########################################################## +else ifeq ($(IDF_TARGET),esp32c61) +# Modules +CIRCUITPY_ESPCAMERA = 0 +CIRCUITPY_ESPULP = 0 +CIRCUITPY_MEMORYMAP = 0 +CIRCUITPY_RGBMATRIX = 0 + +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No space for this CIRCUITPY_AUDIOBUSIO = 0 # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 +# No SDMMC +CIRCUITPY_SDIOIO = 0 + CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE = 0 # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 +# No TWAI on chip +CIRCUITPY_CANIO = 0 + +# No RMT on chip +CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_PULSEIO = 0 +CIRCUITPY_RGBMATRIX = 0 + +# No PCNT on chip +CIRCUITPY_COUNTIO = 0 +CIRCUITPY_ROTARYIO = 0 +CIRCUITPY_FREQUENCYIO = 0 + +#### esp32h2 ########################################################## else ifeq ($(IDF_TARGET),esp32h2) # Modules CIRCUITPY_ESPCAMERA = 0 @@ -150,12 +250,18 @@ CIRCUITPY_ESPULP = 0 CIRCUITPY_MEMORYMAP = 0 CIRCUITPY_RGBMATRIX = 0 +# No DAC +CIRCUITPY_AUDIOIO = 0 + # No I80 support from the IDF CIRCUITPY_PARALLELDISPLAYBUS = 0 +# No SDMMC +CIRCUITPY_SDIOIO = 0 + CIRCUITPY_TOUCHIO ?= 1 CIRCUITPY_TOUCHIO_USE_NATIVE = 0 -CIRCUITPY_HASHLIB_MBEDTLS_ONLY = 0 + # Features CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 1 @@ -163,62 +269,99 @@ CIRCUITPY_WIFI = 0 CIRCUITPY_MAX3421E = 0 +#### esp32p4 ########################################################## +else ifeq ($(IDF_TARGET),esp32p4) + +# No DAC +CIRCUITPY_AUDIOIO = 0 + +# No wifi +# TODO: Support ESP32-C6 coprocessor on some boards. +CIRCUITPY_BLEIO_NATIVE = 0 +CIRCUITPY_WIFI = 0 +CIRCUITPY_SSL = 0 + +CIRCUITPY_TOUCHIO = 1 +CIRCUITPY_TOUCHIO_USE_NATIVE = 0 + +# Second stage bootloader doesn't work when the factory partition is empty due to +# UF2 missing. +UF2_BOOTLOADER = 0 +CIRCUITPY_USB_HID = 0 +CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_TUSB_MEM_ALIGN = 64 + +CIRCUITPY_MAX3421E = 0 + +# Update this for the 40mhz processor. +CIRCUITPY_ESPULP = 0 + +# Update this for multiple TWAI? +CIRCUITPY_CANIO = 0 + +# Protomatter needs an update +CIRCUITPY_RGBMATRIX = 0 + +# No I80 support from the IDF +CIRCUITPY_PARALLELDISPLAYBUS = 0 + +# Library doesn't support P4 yet it seems +CIRCUITPY_ESPCAMERA = 0 + +# P4 has MIPI-DSI +CIRCUITPY_MIPIDSI = 1 + +#### esp32s2 ########################################################## else ifeq ($(IDF_TARGET),esp32s2) # Modules -CIRCUITPY_ALARM_TOUCH = 1 +CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) +CIRCUITPY_AUDIOIO ?= 1 + # No BLE in hw -CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_NATIVE = 0 + +# No SDMMC +CIRCUITPY_SDIOIO = 0 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 +#### esp32s3 ########################################################## else ifeq ($(IDF_TARGET),esp32s3) + # Modules -CIRCUITPY_ALARM_TOUCH = 1 +CIRCUITPY_ALARM_TOUCH = $(CIRCUITPY_ALARM) +CIRCUITPY_AUDIOBUSIO_PDMIN = 1 CIRCUITPY_ESP_USB_SERIAL_JTAG ?= 0 -# No room for _bleio on boards with 4MB flash -ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),4MB) -CIRCUITPY_BLEIO = 0 -endif +# No DAC +CIRCUITPY_AUDIOIO = 0 endif +#### end chip-specific choices ######################################## -# bitmapfilter does not fit on 4MB boards unless they are set up as camera boards -ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),4MB) -CIRCUITPY_BITMAPFILTER ?= 0 -OPTIMIZATION_FLAGS ?= -Os -CIRCUITPY_DUALBANK ?= 0 -else -CIRCUITPY_DUALBANK ?= 1 -endif - -# We used to default to OTA partition layout but are moving away from it so that -# BLE and alarm can be included. This setting prevents the partition layout from -# changing. -ifeq ($(CIRCUITPY_LEGACY_4MB_FLASH_LAYOUT), 1) -ifeq ($(IDF_TARGET_ARCH), xtensa) - CIRCUITPY_ALARM ?= 1 -else -CIRCUITPY_ALARM = 0 -endif -CIRCUITPY_DUALBANK = 1 -CIRCUITPY_BLEIO = 0 +# No room for large modules on 2MB boards +# 2MB boards have a single firmware partition, and can't do dualbank. +ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),2MB) +CIRCUITPY__EVE = 0 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_BITMAPFILTER = 0 +CIRCUITPY_BLEIO_NATIVE = 0 +CIRCUITPY_DUALBANK = 0 +CIRCUITPY_MAX3421E = 0 +CIRCUITPY_RGBMATRIX = 0 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 0 -else -CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1 +OPTIMIZATION_FLAGS ?= -Os endif -# No room for dualbank or mp3 on boards with 2MB flash -ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),2MB) -CIRCUITPY_BITMAPFILTER ?= 0 +# 4MB boards have a single firmware partition, and can't do dualbank. +ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),4MB) CIRCUITPY_DUALBANK = 0 -CIRCUITPY_AUDIOMP3 = 0 -CIRCUITPY_BLEIO = 0 +OPTIMIZATION_FLAGS ?= -Os endif -# No room for _eve on boards with 4MB flash -ifeq ($(CIRCUITPY_ESP_FLASH_SIZE),4MB) -CIRCUITPY__EVE = 0 +# espcamera does not work on boards without SPIRAM +ifeq ($(CIRCUITPY_ESP_PSRAM_SIZE),0) +CIRCUITPY_ESPCAMERA = 0 endif # Modules dependent on other modules @@ -227,8 +370,8 @@ CIRCUITPY_GIFIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_JPEGIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_QRIO ?= $(CIRCUITPY_ESPCAMERA) -CIRCUITPY_BLE_FILE_SERVICE ?= $(CIRCUITPY_BLEIO) -CIRCUITPY_SERIAL_BLE ?= $(CIRCUITPY_BLEIO) +CIRCUITPY_BLE_FILE_SERVICE ?= $(CIRCUITPY_BLEIO_NATIVE) +CIRCUITPY_SERIAL_BLE ?= $(CIRCUITPY_BLEIO_NATIVE) # Features dependent on other features ifneq ($(CIRCUITPY_USB_DEVICE),0) @@ -251,6 +394,3 @@ USB_NUM_IN_ENDPOINTS = 5 # Usually lots of flash space available CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 1 - -CIRCUITPY_AUDIOMP3 ?= 1 -CIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR ?= 1 diff --git a/ports/espressif/mphalport.c b/ports/espressif/mphalport.c index 7c7ec5481c081..9046bbf7b102f 100644 --- a/ports/espressif/mphalport.c +++ b/ports/espressif/mphalport.c @@ -8,23 +8,7 @@ #include "py/mphal.h" #include "supervisor/cpu.h" -#if defined(CONFIG_IDF_TARGET_ESP32) -#include "components/esp_rom/include/esp32/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C2) -#include "components/esp_rom/include/esp32c2/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C3) -#include "components/esp_rom/include/esp32c3/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C6) -#include "components/esp_rom/include/esp32c6/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32H2) -#include "components/esp_rom/include/esp32h2/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32S2) -#include "components/esp_rom/include/esp32s2/rom/ets_sys.h" -#elif defined(CONFIG_IDF_TARGET_ESP32S3) -#include "components/esp_rom/include/esp32s3/rom/ets_sys.h" -#else -#error Unknown CONFIG_IDF_TARGET_xxx -#endif +#include "rom/ets_sys.h" #include "esp_attr.h" @@ -37,7 +21,6 @@ void IRAM_ATTR mp_hal_delay_us(mp_uint_t delay) { // This is provided by the esp-idf/components/xtensa/esp32s2/libhal.a binary blob. #ifndef CONFIG_IDF_TARGET_ARCH_RISCV extern void xthal_window_spill(void); -#endif mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) { // xtensa has more registers than an instruction can address. The 16 that @@ -53,8 +36,7 @@ mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) { // there is a HAL call to do it. There is a bit of a race condition here // because the register value could change after it's been restored but that // is unlikely to happen with a heap pointer while we do a GC. - #ifndef CONFIG_IDF_TARGET_ARCH_RISCV xthal_window_spill(); - #endif - return (mp_uint_t)__builtin_frame_address(0); + return (mp_uint_t)__builtin_stack_address(); } +#endif diff --git a/ports/espressif/peripherals/esp32c61/pins.c b/ports/espressif/peripherals/esp32c61/pins.c new file mode 100644 index 0000000000000..a32e1e8da9856 --- /dev/null +++ b/ports/espressif/peripherals/esp32c61/pins.c @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO1 = PIN(1, ADC_UNIT_1, ADC_CHANNEL_0, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, ADC_UNIT_1, ADC_CHANNEL_1, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, ADC_UNIT_1, ADC_CHANNEL_2, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, ADC_UNIT_1, ADC_CHANNEL_3, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO15 = PIN(15, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO16 = PIN(16, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO17 = PIN(17, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO18 = PIN(18, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO19 = PIN(19, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO20 = PIN(20, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO21 = PIN(21, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO22 = PIN(22, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO23 = PIN(23, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO24 = PIN(24, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO25 = PIN(25, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO26 = PIN(26, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO27 = PIN(27, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO28 = PIN(28, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO29 = PIN(29, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32c61/pins.h b/ports/espressif/peripherals/esp32c61/pins.h new file mode 100644 index 0000000000000..908c9fe29f0e2 --- /dev/null +++ b/ports/espressif/peripherals/esp32c61/pins.h @@ -0,0 +1,72 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// DO NOT include this file directly. +// Use shared-bindings/microcontroller/Pin.h instead. +// This ensures that all necessary includes are already included. + +#pragma once + +#define GPIO0_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO0; +#define GPIO1_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO1; +#define GPIO2_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO2; +#define GPIO3_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO3; +#define GPIO4_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO4; +#define GPIO5_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO5; +#define GPIO6_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO6; +#define GPIO7_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO7; +#define GPIO8_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO8; +#define GPIO9_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO9; +#define GPIO10_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO10; +#define GPIO11_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO11; +#define GPIO12_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO12; +#define GPIO13_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO13; +#define GPIO14_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO14; +#define GPIO15_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO15; +#define GPIO16_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO16; +#define GPIO17_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO17; +#define GPIO18_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO18; +#define GPIO19_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO19; +#define GPIO20_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO20; +#define GPIO21_EXISTS 0 +extern const mcu_pin_obj_t pin_GPIO21; +#define GPIO22_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO22; +#define GPIO23_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO23; +#define GPIO24_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO24; +#define GPIO25_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO25; +#define GPIO26_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO26; +#define GPIO27_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO27; +#define GPIO28_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO28; +#define GPIO29_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO29; diff --git a/ports/espressif/peripherals/esp32p4/pins.c b/ports/espressif/peripherals/esp32p4/pins.c new file mode 100644 index 0000000000000..24e509d40c6e1 --- /dev/null +++ b/ports/espressif/peripherals/esp32p4/pins.c @@ -0,0 +1,63 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include "peripherals/pins.h" + +const mcu_pin_obj_t pin_GPIO0 = PIN(0, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO1 = PIN(1, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO2 = PIN(2, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM0); +const mcu_pin_obj_t pin_GPIO3 = PIN(3, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM1); +const mcu_pin_obj_t pin_GPIO4 = PIN(4, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM2); +const mcu_pin_obj_t pin_GPIO5 = PIN(5, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM3); +const mcu_pin_obj_t pin_GPIO6 = PIN(6, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM4); +const mcu_pin_obj_t pin_GPIO7 = PIN(7, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM5); +const mcu_pin_obj_t pin_GPIO8 = PIN(8, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM6); +const mcu_pin_obj_t pin_GPIO9 = PIN(9, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM7); +const mcu_pin_obj_t pin_GPIO10 = PIN(10, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM8); +const mcu_pin_obj_t pin_GPIO11 = PIN(11, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM9); +const mcu_pin_obj_t pin_GPIO12 = PIN(12, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM10); +const mcu_pin_obj_t pin_GPIO13 = PIN(13, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM11); +const mcu_pin_obj_t pin_GPIO14 = PIN(14, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM12); +const mcu_pin_obj_t pin_GPIO15 = PIN(15, NO_ADC, NO_ADC_CHANNEL, TOUCH_PAD_NUM13); +const mcu_pin_obj_t pin_GPIO16 = PIN(16, ADC_UNIT_1, ADC_CHANNEL_0, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO17 = PIN(17, ADC_UNIT_1, ADC_CHANNEL_1, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO18 = PIN(18, ADC_UNIT_1, ADC_CHANNEL_2, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO19 = PIN(19, ADC_UNIT_1, ADC_CHANNEL_3, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO20 = PIN(20, ADC_UNIT_1, ADC_CHANNEL_4, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO21 = PIN(21, ADC_UNIT_1, ADC_CHANNEL_5, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO22 = PIN(22, ADC_UNIT_1, ADC_CHANNEL_6, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO23 = PIN(23, ADC_UNIT_1, ADC_CHANNEL_7, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO24 = PIN(24, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO25 = PIN(25, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO26 = PIN(26, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO27 = PIN(27, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO28 = PIN(28, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO29 = PIN(29, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO30 = PIN(30, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO31 = PIN(31, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO32 = PIN(32, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO33 = PIN(33, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO34 = PIN(34, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO35 = PIN(35, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO36 = PIN(36, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO37 = PIN(37, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO38 = PIN(38, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO39 = PIN(39, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO40 = PIN(40, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO41 = PIN(41, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO42 = PIN(42, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO43 = PIN(43, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO44 = PIN(44, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO45 = PIN(45, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO46 = PIN(46, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO47 = PIN(47, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO48 = PIN(48, NO_ADC, NO_ADC_CHANNEL, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO49 = PIN(49, ADC_UNIT_2, ADC_CHANNEL_2, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO50 = PIN(50, ADC_UNIT_2, ADC_CHANNEL_3, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO51 = PIN(51, ADC_UNIT_2, ADC_CHANNEL_4, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO52 = PIN(52, ADC_UNIT_2, ADC_CHANNEL_5, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO53 = PIN(53, ADC_UNIT_2, ADC_CHANNEL_6, NO_TOUCH_CHANNEL); +const mcu_pin_obj_t pin_GPIO54 = PIN(54, ADC_UNIT_2, ADC_CHANNEL_7, NO_TOUCH_CHANNEL); diff --git a/ports/espressif/peripherals/esp32p4/pins.h b/ports/espressif/peripherals/esp32p4/pins.h new file mode 100644 index 0000000000000..59cf4258a40b4 --- /dev/null +++ b/ports/espressif/peripherals/esp32p4/pins.h @@ -0,0 +1,122 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +// DO NOT include this file directly. +// Use shared-bindings/microcontroller/Pin.h instead. +// This ensures that all necessary includes are already included. + +#pragma once + +#define GPIO0_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO0; +#define GPIO1_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO1; +#define GPIO2_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO2; +#define GPIO3_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO3; +#define GPIO4_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO4; +#define GPIO5_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO5; +#define GPIO6_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO6; +#define GPIO7_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO7; +#define GPIO8_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO8; +#define GPIO9_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO9; +#define GPIO10_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO10; +#define GPIO11_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO11; +#define GPIO12_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO12; +#define GPIO13_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO13; +#define GPIO14_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO14; +#define GPIO15_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO15; +#define GPIO16_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO16; +#define GPIO17_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO17; +#define GPIO18_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO18; +#define GPIO19_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO19; +#define GPIO20_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO20; +#define GPIO21_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO21; +#define GPIO22_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO22; +#define GPIO23_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO23; +#define GPIO24_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO24; +#define GPIO25_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO25; +#define GPIO26_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO26; +#define GPIO27_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO27; +#define GPIO28_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO28; +#define GPIO29_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO29; +#define GPIO30_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO30; +#define GPIO31_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO31; +#define GPIO32_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO32; +#define GPIO33_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO33; +#define GPIO34_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO34; +#define GPIO35_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO35; +#define GPIO36_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO36; +#define GPIO37_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO37; +#define GPIO38_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO38; +#define GPIO39_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO39; +#define GPIO40_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO40; +#define GPIO41_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO41; +#define GPIO42_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO42; +#define GPIO43_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO43; +#define GPIO44_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO44; +#define GPIO45_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO45; +#define GPIO46_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO46; +#define GPIO47_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO47; +#define GPIO48_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO48; +#define GPIO49_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO49; +#define GPIO50_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO50; +#define GPIO51_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO51; +#define GPIO52_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO52; +#define GPIO53_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO53; +#define GPIO54_EXISTS 1 +extern const mcu_pin_obj_t pin_GPIO54; diff --git a/ports/espressif/peripherals/i2c.c b/ports/espressif/peripherals/i2c.c deleted file mode 100644 index 744aa07f43d24..0000000000000 --- a/ports/espressif/peripherals/i2c.c +++ /dev/null @@ -1,65 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 microDev -// -// SPDX-License-Identifier: MIT - -#include "peripherals/i2c.h" - -typedef enum { - STATUS_FREE = 0, - STATUS_IN_USE, - STATUS_NEVER_RESET -} i2c_status_t; - -static i2c_status_t i2c_status[I2C_NUM_MAX]; - -void i2c_reset(void) { - for (i2c_port_t num = 0; num < (i2c_port_t)I2C_NUM_MAX; num++) { - if (i2c_status[num] == STATUS_IN_USE) { - i2c_driver_delete(num); - i2c_status[num] = STATUS_FREE; - } - } -} - -void never_reset_i2c(i2c_port_t num) { - i2c_status[num] = STATUS_NEVER_RESET; -} - -esp_err_t peripherals_i2c_init(i2c_port_t num, const i2c_config_t *i2c_conf) { - esp_err_t err = i2c_param_config(num, i2c_conf); - if (err != ESP_OK) { - return err; - } - size_t rx_buf_len = 0; - size_t tx_buf_len = 0; - #ifdef SOC_I2C_SUPPORT_SLAVE - if (i2c_conf->mode == I2C_MODE_SLAVE) { - rx_buf_len = 256; - tx_buf_len = 256; - } - #endif - return i2c_driver_install(num, i2c_conf->mode, rx_buf_len, tx_buf_len, 0); -} - -void peripherals_i2c_deinit(i2c_port_t num) { - i2c_reset_rx_fifo(num); - i2c_reset_tx_fifo(num); - i2c_driver_delete(num); - i2c_status[num] = STATUS_FREE; -} - -i2c_port_t peripherals_i2c_get_free_num(void) { - i2c_port_t i2c_num = I2C_NUM_MAX; - for (i2c_port_t num = 0; num < (int)I2C_NUM_MAX; num++) { - if (i2c_status[num] == STATUS_FREE) { - i2c_num = num; - break; - } - } - if (i2c_num != I2C_NUM_MAX) { - i2c_status[i2c_num] = STATUS_IN_USE; - } - return i2c_num; -} diff --git a/ports/espressif/peripherals/i2c.h b/ports/espressif/peripherals/i2c.h deleted file mode 100644 index a97889fe5acfa..0000000000000 --- a/ports/espressif/peripherals/i2c.h +++ /dev/null @@ -1,15 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2020 microDev -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include "driver/i2c.h" - -extern void i2c_reset(void); -extern void never_reset_i2c(i2c_port_t num); -extern esp_err_t peripherals_i2c_init(i2c_port_t num, const i2c_config_t *i2c_conf); -extern void peripherals_i2c_deinit(i2c_port_t num); -extern i2c_port_t peripherals_i2c_get_free_num(void); diff --git a/ports/espressif/peripherals/pins.h b/ports/espressif/peripherals/pins.h index 30bb21cdec70f..bbe42be1bcae2 100644 --- a/ports/espressif/peripherals/pins.h +++ b/ports/espressif/peripherals/pins.h @@ -14,7 +14,7 @@ #include "components/hal/include/hal/gpio_types.h" #include "components/hal/include/hal/adc_types.h" -#include "components/hal/include/hal/touch_sensor_types.h" +#include "components/hal/include/hal/touch_sensor_legacy_types.h" typedef struct { mp_obj_base_t base; @@ -52,6 +52,10 @@ extern const mp_obj_type_t mcu_pin_type; #include "esp32c3/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32C6) #include "esp32c6/pins.h" +#elif defined(CONFIG_IDF_TARGET_ESP32C61) +#include "esp32c61/pins.h" +#elif defined(CONFIG_IDF_TARGET_ESP32P4) +#include "esp32p4/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32H2) #include "esp32h2/pins.h" #elif defined(CONFIG_IDF_TARGET_ESP32S2) diff --git a/ports/espressif/supervisor/port.c b/ports/espressif/supervisor/port.c index 0b39302675bc2..d2aafb99f0bd6 100644 --- a/ports/espressif/supervisor/port.c +++ b/ports/espressif/supervisor/port.c @@ -24,7 +24,6 @@ #include "bindings/espulp/__init__.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/analogio/AnalogOut.h" -#include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/busio/UART.h" #include "common-hal/dualbank/__init__.h" @@ -40,11 +39,15 @@ #include "shared-bindings/socketpool/__init__.h" #include "shared-module/os/__init__.h" +#if CIRCUITPY_SDIOIO +#include "common-hal/sdioio/SDCard.h" +#endif + #if CIRCUITPY_TOUCHIO_USE_NATIVE #include "peripherals/touch.h" #endif -#if CIRCUITPY_BLEIO +#if CIRCUITPY_BLEIO_NATIVE #include "shared-bindings/_bleio/__init__.h" #endif @@ -52,14 +55,27 @@ #include "esp_camera.h" #endif +#if CIRCUITPY_RCLCPY +#include "common-hal/rclcpy/__init__.h" +#endif + #include "soc/efuse_reg.h" #if defined(SOC_LP_AON_SUPPORTED) #include "soc/lp_aon_reg.h" #define CP_SAVED_WORD_REGISTER LP_AON_STORE0_REG #else +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#include "soc/lp_system_reg.h" +#define CP_SAVED_WORD_REGISTER LP_SYSTEM_REG_LP_STORE15_REG + +#else +// To-do idf v5.0: remove following include #include "soc/rtc_cntl_reg.h" #define CP_SAVED_WORD_REGISTER RTC_CNTL_STORE0_REG #endif + +#endif + #include "soc/spi_pins.h" #include "bootloader_flash_config.h" @@ -87,7 +103,7 @@ static esp_timer_handle_t _sleep_timer; TaskHandle_t circuitpython_task = NULL; -extern void esp_restart(void) NORETURN; +extern void esp_restart(void) MP_NORETURN; static void tick_on_cp_core(void *arg) { supervisor_tick(); @@ -178,8 +194,8 @@ static void _never_reset_spi_ram_flash(void) { const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info(); if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) { - never_reset_pin_number(SPI_IOMUX_PIN_NUM_CLK); - never_reset_pin_number(SPI_IOMUX_PIN_NUM_CS); + never_reset_pin_number(MSPI_IOMUX_PIN_NUM_CLK); + never_reset_pin_number(MSPI_IOMUX_PIN_NUM_CS0); never_reset_pin_number(PSRAM_SPIQ_SD0_IO); never_reset_pin_number(PSRAM_SPID_SD1_IO); never_reset_pin_number(PSRAM_SPIWP_SD3_IO); @@ -200,6 +216,11 @@ static void _never_reset_spi_ram_flash(void) { never_reset_pin_number(bootloader_flash_get_wp_pin()); } #endif // CONFIG_IDF_TARGET_ESP32 + #if defined(CONFIG_IDF_TARGET_ESP32C61) + #if defined(CONFIG_SPIRAM) + common_hal_never_reset_pin(&pin_GPIO14); + #endif + #endif } safe_mode_t port_init(void) { @@ -223,33 +244,19 @@ safe_mode_t port_init(void) { #endif // Send the ROM output out of the UART. This includes early logs. - #if DEBUG + #if DEBUG && (defined(CONFIG_ESP_CONSOLE_UART_DEFAULT) && CONFIG_ESP_CONSOLE_UART_DEFAULT) esp_rom_install_uart_printf(); #endif #define pin_GPIOn(n) pin_GPIO##n #define pin_GPIOn_EXPAND(x) pin_GPIOn(x) - #ifdef CONFIG_CONSOLE_UART_TX_GPIO - common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_TX_GPIO)); + #ifdef CONFIG_ESP_CONSOLE_UART_TX_GPIO + common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_ESP_CONSOLE_UART_TX_GPIO)); #endif - #ifdef CONFIG_CONSOLE_UART_RX_GPIO - common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_CONSOLE_UART_RX_GPIO)); - #endif - - #if DEBUG - // debug UART - #if defined(CONFIG_IDF_TARGET_ESP32C3) - common_hal_never_reset_pin(&pin_GPIO20); - common_hal_never_reset_pin(&pin_GPIO21); - #elif defined(CONFIG_IDF_TARGET_ESP32C6) - common_hal_never_reset_pin(&pin_GPIO16); - common_hal_never_reset_pin(&pin_GPIO17); - #elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) - common_hal_never_reset_pin(&pin_GPIO43); - common_hal_never_reset_pin(&pin_GPIO44); - #endif + #ifdef CONFIG_ESP_CONSOLE_UART_RX_GPIO + common_hal_never_reset_pin(&pin_GPIOn_EXPAND(CONFIG_ESP_CONSOLE_UART_RX_GPIO)); #endif #ifndef ENABLE_JTAG @@ -269,6 +276,11 @@ safe_mode_t port_init(void) { common_hal_never_reset_pin(&pin_GPIO40); common_hal_never_reset_pin(&pin_GPIO41); common_hal_never_reset_pin(&pin_GPIO42); + #elif defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32C61) + common_hal_never_reset_pin(&pin_GPIO3); + common_hal_never_reset_pin(&pin_GPIO4); + common_hal_never_reset_pin(&pin_GPIO5); + common_hal_never_reset_pin(&pin_GPIO6); #endif #endif @@ -289,6 +301,10 @@ safe_mode_t port_init(void) { break; } + if (board_requests_safe_mode()) { + return SAFE_MODE_USER; + } + return SAFE_MODE_NONE; } @@ -297,18 +313,18 @@ void port_heap_init(void) { } void *port_malloc(size_t size, bool dma_capable) { - size_t caps = MALLOC_CAP_8BIT; if (dma_capable) { - caps |= MALLOC_CAP_DMA; + // SPIRAM is not DMA-capable, so don't bother to ask for it. + return heap_caps_malloc(size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA); } void *ptr = NULL; - // Try SPIRAM first when available. + // Try SPIRAM first if available. #ifdef CONFIG_SPIRAM - ptr = heap_caps_malloc(size, caps | MALLOC_CAP_SPIRAM); + ptr = heap_caps_malloc(size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); #endif if (ptr == NULL) { - ptr = heap_caps_malloc(size, caps); + ptr = heap_caps_malloc(size, MALLOC_CAP_8BIT); } return ptr; } @@ -317,8 +333,12 @@ void port_free(void *ptr) { heap_caps_free(ptr); } -void *port_realloc(void *ptr, size_t size) { - return heap_caps_realloc(ptr, size, MALLOC_CAP_8BIT); +void *port_realloc(void *ptr, size_t size, bool dma_capable) { + size_t caps = MALLOC_CAP_8BIT; + if (dma_capable) { + caps |= MALLOC_CAP_DMA; + } + return heap_caps_realloc(ptr, size, caps); } size_t port_heap_get_largest_free_size(void) { @@ -336,18 +356,18 @@ void reset_port(void) { ssl_reset(); #endif - reset_all_pins(); - #if CIRCUITPY_ANALOGIO analogout_reset(); #endif #if CIRCUITPY_BUSIO - i2c_reset(); - spi_reset(); uart_reset(); #endif + #if CIRCUITPY_SDIOIO + sdioio_reset(); + #endif + #if CIRCUITPY_DUALBANK dualbank_reset(); #endif @@ -364,6 +384,10 @@ void reset_port(void) { ps2_reset(); #endif + #if CIRCUITPY_RCLCPY + rclcpy_reset(); + #endif + #if CIRCUITPY_RTC rtc_reset(); #endif @@ -380,8 +404,8 @@ void reset_port(void) { watchdog_reset(); #endif - // Yield so the idle task can run and do any IDF cleanup needed. - port_yield(); + // Yield so the idle task, at priority 0, can run and do any IDF cleanup needed. + port_task_sleep_ms(4); } void reset_to_bootloader(void) { @@ -447,11 +471,11 @@ void port_disable_tick(void) { esp_timer_stop(_tick_timer); } -void port_wake_main_task() { +void port_wake_main_task(void) { xTaskNotifyGive(circuitpython_task); } -void port_wake_main_task_from_isr() { +void port_wake_main_task_from_isr(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(circuitpython_task, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken == pdTRUE) { @@ -459,8 +483,13 @@ void port_wake_main_task_from_isr() { } } -void port_yield() { - vTaskDelay(4); +// Yield to other tasks at the same priority. +void port_task_yield(void) { + vTaskDelay(0); +} + +void port_task_sleep_ms(uint32_t msecs) { + vTaskDelay(pdMS_TO_TICKS(msecs)); } void sleep_timer_cb(void *arg) { @@ -483,19 +512,15 @@ void port_idle_until_interrupt(void) { } } -void port_post_boot_py(bool heap_valid) { - if (!heap_valid && filesystem_present()) { +#if CIRCUITPY_WIFI +void port_boot_info(void) { + uint8_t mac[6]; + esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); + mp_printf(&mp_plat_print, "MAC"); + for (int i = 0; i < 6; i++) { + mp_printf(&mp_plat_print, ":%02X", mac[i]); } -} - - -#if CIRCUITPY_CONSOLE_UART -static int vprintf_adapter(const char *fmt, va_list ap) { - return mp_vprintf(&mp_plat_print, fmt, ap); -} - -void port_serial_early_init(void) { - esp_log_set_vprintf(vprintf_adapter); + mp_printf(&mp_plat_print, "\n"); } #endif diff --git a/ports/espressif/supervisor/serial.c b/ports/espressif/supervisor/serial.c index 1d2fc58683a6c..e9277008a3cfb 100644 --- a/ports/espressif/supervisor/serial.c +++ b/ports/espressif/supervisor/serial.c @@ -15,6 +15,9 @@ #include "supervisor/usb_serial_jtag.h" #endif +void port_serial_early_init(void) { +} + void port_serial_init(void) { #if CIRCUITPY_ESP_USB_SERIAL_JTAG usb_serial_jtag_init(); diff --git a/ports/espressif/supervisor/usb.c b/ports/espressif/supervisor/usb.c index 3cd070e7c5d2b..e4d34ee7694f3 100644 --- a/ports/espressif/supervisor/usb.c +++ b/ports/espressif/supervisor/usb.c @@ -2,6 +2,7 @@ // // SPDX-FileCopyrightText: Copyright (c) 2018 hathach for Adafruit Industries // SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries +// SPDX-FileContributor: 2025 Nicolai Electronics // // SPDX-License-Identifier: MIT @@ -20,21 +21,17 @@ #include "driver/gpio.h" #include "esp_private/periph_ctrl.h" -#if defined(CONFIG_IDF_TARGET_ESP32C3) -#include "components/esp_rom/include/esp32c3/rom/gpio.h" -#elif defined(CONFIG_IDF_TARGET_ESP32C6) -#include "components/esp_rom/include/esp32c6/rom/gpio.h" -#elif defined(CONFIG_IDF_TARGET_ESP32S2) -#include "components/esp_rom/include/esp32s2/rom/gpio.h" -#elif defined(CONFIG_IDF_TARGET_ESP32S3) -#include "components/esp_rom/include/esp32s3/rom/gpio.h" -#endif +#include "rom/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "tusb.h" +#ifdef CONFIG_IDF_TARGET_ESP32P4 +#include "hal/usb_serial_jtag_ll.h" +#endif + #if CIRCUITPY_USB_DEVICE #ifdef CFG_TUSB_DEBUG #define USBD_STACK_SIZE (3 * configMINIMAL_STACK_SIZE) @@ -45,7 +42,7 @@ StackType_t usb_device_stack[USBD_STACK_SIZE]; StaticTask_t usb_device_taskdef; -static usb_phy_handle_t phy_hdl; +static usb_phy_handle_t device_phy_hdl; // USB Device Driver task // This top level thread process all usb events and invoke callbacks @@ -59,34 +56,10 @@ static void usb_device_task(void *param) { tud_task(); tud_cdc_write_flush(); } - vTaskDelay(1); - } -} - -/** - * Callback invoked when received an "wanted" char. - * @param itf Interface index (for multiple cdc interfaces) - * @param wanted_char The wanted char (set previously) - */ -void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { - (void)itf; // not used - // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB. - // So, we must notify the other task when a CTRL-C is received. - port_wake_main_task(); - // Workaround for using shared/runtime/interrupt_char.c - // Compare mp_interrupt_char with wanted_char and ignore if not matched - if (mp_interrupt_char == wanted_char) { - tud_cdc_read_flush(); // flush read fifo - mp_sched_keyboard_interrupt(); + // Yield with zero delay to switch to any other tasks at same priority. + port_task_yield(); } } - -void tud_cdc_rx_cb(uint8_t itf) { - (void)itf; - // Workaround for "press any key to enter REPL" response being delayed on espressif. - // Wake main task when any key is pressed. - port_wake_main_task(); -} #endif // CIRCUITPY_USB_DEVICE void init_usb_hardware(void) { @@ -94,9 +67,45 @@ void init_usb_hardware(void) { // Configure USB PHY usb_phy_config_t phy_conf = { .controller = USB_PHY_CTRL_OTG, + #if defined(CONFIG_IDF_TARGET_ESP32P4) && CIRCUITPY_USB_DEVICE_INSTANCE == 1 + .target = USB_PHY_TARGET_UTMI, + #else + .target = USB_PHY_TARGET_INT, + #endif .otg_mode = USB_OTG_MODE_DEVICE, + #if defined(CONFIG_IDF_TARGET_ESP32P4) && CIRCUITPY_USB_DEVICE_INSTANCE == 0 + .otg_speed = USB_PHY_SPEED_FULL, + #else + // https://github.com/hathach/tinyusb/issues/2943#issuecomment-2601888322 + // Set speed to undefined (auto-detect) to avoid timing/race issue with S3 with host such as macOS + .otg_speed = USB_PHY_SPEED_UNDEFINED, + #endif }; - usb_new_phy(&phy_conf, &phy_hdl); + usb_new_phy(&phy_conf, &device_phy_hdl); + + #if CIRCUITPY_ESP32P4_SWAP_LSFS == 1 + #ifndef CONFIG_IDF_TARGET_ESP32P4 + #error "LSFS swap is only supported on ESP32P4" + #endif + // Switch the USB PHY + const usb_serial_jtag_pull_override_vals_t override_disable_usb = { + .dm_pd = true, .dm_pu = false, .dp_pd = true, .dp_pu = false + }; + const usb_serial_jtag_pull_override_vals_t override_enable_usb = { + .dm_pd = false, .dm_pu = false, .dp_pd = false, .dp_pu = true + }; + + // Drop off the bus by removing the pull-up on USB DP + usb_serial_jtag_ll_phy_enable_pull_override(&override_disable_usb); + + // Select USB mode by swapping and un-swapping the two PHYs + vTaskDelay(pdMS_TO_TICKS(500)); // Wait for disconnect before switching to device + usb_serial_jtag_ll_phy_select(1); + + // Put the device back onto the bus by re-enabling the pull-up on USB DP + usb_serial_jtag_ll_phy_enable_pull_override(&override_enable_usb); + usb_serial_jtag_ll_phy_disable_pull_override(); + #endif // Pin the USB task to the same core as CircuitPython. This way we leave // the other core for networking. @@ -104,7 +113,7 @@ void init_usb_hardware(void) { "usbd", USBD_STACK_SIZE, NULL, - 5, + 1, usb_device_stack, &usb_device_taskdef, xPortGetCoreID()); diff --git a/ports/espressif/supervisor/usb_serial_jtag.c b/ports/espressif/supervisor/usb_serial_jtag.c index 1a5282de8e939..b4cb91b7d7eb1 100644 --- a/ports/espressif/supervisor/usb_serial_jtag.c +++ b/ports/espressif/supervisor/usb_serial_jtag.c @@ -46,6 +46,7 @@ static void _copy_out_of_fifo(void) { for (size_t i = 0; i < len; ++i) { if (rx_buf[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&ringbuf); } else { ringbuf_put(&ringbuf, rx_buf[i]); } diff --git a/ports/espressif/tools/build_memory_info.py b/ports/espressif/tools/build_memory_info.py index fa97bb9ed611e..0cf609c4d63f4 100644 --- a/ports/espressif/tools/build_memory_info.py +++ b/ports/espressif/tools/build_memory_info.py @@ -38,6 +38,13 @@ ("Internal SRAM 1", (0x3FC8_0000, 0x4037_8000), 416 * 1024), ("Internal SRAM 2", (0x3FCF_0000,), 64 * 1024), ], + "esp32p4": [ + # Name, Start, Length + ("HP RAM", (0x3010_0000,), 8 * 1024), + ("PSRAM", (0x4800_0000,), 64 * 1024 * 1024), + ("L2MEM", (0x4FF0_0000,), 768 * 1024), + ("LP RAM", (0x5010_8000,), 32 * 1024), + ], "esp32c2": [ # Name, Start, Length ("Internal SRAM 0", (0x4037_C000,), 16 * 1024), @@ -54,6 +61,12 @@ ("LP SRAM", (0x5000_0000,), 16 * 1024), ("HP SRAM", (0x4080_0000,), 512 * 1024), ], + "esp32c61": [ + # Name, Start, Length + ("LP SRAM", (0x5000_0000,), 16 * 1024), + ("HP SRAM", (0x4080_0000,), 320 * 1024), + ("PSRAM", (0x4200_0000,), 2 * 1024 * 1024), + ], "esp32h2": [ # Name, Start, Length ("LP SRAM", (0x5000_0000,), 4 * 1024), diff --git a/ports/espressif/tools/check-sdkconfig.py b/ports/espressif/tools/check-sdkconfig.py index 8a7ef8821770e..12254a71d0109 100755 --- a/ports/espressif/tools/check-sdkconfig.py +++ b/ports/espressif/tools/check-sdkconfig.py @@ -29,7 +29,7 @@ def validate(sdk_config, circuitpy_config): if circuitpy_config.get(var): with open(partition_table) as f: content = f.read() - if not "ota_1" in content: + if "ota_1" not in content: raise SystemExit( f"{var} is incompatible with {partition_table=} (no ota_1 partition)" ) diff --git a/ports/espressif/tools/decode_backtrace.py b/ports/espressif/tools/decode_backtrace.py index 6d2772d39f77b..16cef9e0822cc 100644 --- a/ports/espressif/tools/decode_backtrace.py +++ b/ports/espressif/tools/decode_backtrace.py @@ -1,10 +1,10 @@ """Simple script that translates "Backtrace:" lines from the ESP output to files - and line numbers. +and line numbers. - Run with: python3 tools/decode_backtrace.py +Run with: python3 tools/decode_backtrace.py - Enter the backtrace line at the "? " prompt. CTRL-C to exit the script. - """ +Enter the backtrace line at the "? " prompt. CTRL-C to exit the script. +""" import subprocess import sys @@ -12,20 +12,41 @@ board = sys.argv[1] print(board) +elfs = [ + f"build-{board}/firmware.elf", + # Add additional ELF files here such as the ROM ELF files from: + # https://github.com/espressif/esp-rom-elfs/releases + # "/home/tannewt/Downloads/esp-rom-elfs-20241011/esp32c6_rev0_rom.elf", +] + while True: + print('"Backtrace:" or "Stack memory:". CTRL-D to finish multiline paste') addresses = input("? ") if addresses.startswith("Backtrace:"): addresses = addresses[len("Backtrace:") :] - if addresses.startswith("Stack memory:"): - addresses = addresses[len("Stack memory:") :] - addresses = addresses.strip().split() - addresses = [address.split(":")[0] for address in addresses] + addresses = addresses.strip().split() + addresses = [address.split(":")[0] for address in addresses] + elif addresses.startswith("Stack memory:"): + addresses = [] + extra_lines = sys.stdin.readlines() + for line in extra_lines: + if not line.strip(): + continue + addresses.extend(line.split(":")[1].strip().split()) for address in addresses: - result = subprocess.run( - ["xtensa-esp32s2-elf-addr2line", "-aipfe", "build-{}/firmware.elf".format(board)] - + [address], - capture_output=True, - ) - stdout = result.stdout.decode("utf-8") - if "?? ??" not in stdout: - print(stdout.strip()) + if address == "0xa5a5a5a5": + # Skip stack fill value. + continue + for elf in elfs: + result = subprocess.run( + ["riscv32-esp-elf-addr2line", "-aipfe", elf, address], + capture_output=True, + ) + stdout = result.stdout.decode("utf-8") + if not stdout: + continue + if "?? ??" not in stdout: + print(stdout.strip()) + break + + print("loop") diff --git a/ports/espressif/tools/update_sdkconfig.py b/ports/espressif/tools/update_sdkconfig.py index 6d1ded619bd15..d40614edb75d8 100644 --- a/ports/espressif/tools/update_sdkconfig.py +++ b/ports/espressif/tools/update_sdkconfig.py @@ -1,5 +1,5 @@ """This script updates the sdkconfigs based on the menuconfig results in a given - build.""" +build.""" import pathlib import click @@ -76,9 +76,7 @@ "CONFIG_ESPTOOLPY_FLASH_SAMBLE_MODE_", ] -FLASH_FREQ_SETTINGS = [ - "CONFIG_ESPTOOLPY_FLASHFREQ_", -] +FLASH_FREQ_SETTINGS = ["CONFIG_ESPTOOLPY_FLASHFREQ_", "CONFIG_SPI_FLASH_UNDER_HIGH_FREQ"] PSRAM_SETTINGS = ["CONFIG_SPIRAM"] @@ -141,10 +139,9 @@ def sym_default(sym): # to n or the symbol to m in those cases). if ( sym.choice - and not sym.choice.is_optional and sym.choice._selection_from_defaults() is sym - and sym.orig_type is kconfiglib.core.BOOL - and sym.tri_value == 2 + and sym.orig_type == kconfiglib.core.BOOL + and sym.bool_value == 2 ): return True @@ -160,7 +157,7 @@ def sym_default(sym): default=False, help="Updates the sdkconfigs outside of the board directory.", ) -def update(debug, board, update_all): +def update(debug, board, update_all): # noqa: C901 too complex """Updates related sdkconfig files based on the build directory version that was likely modified by menuconfig.""" @@ -194,7 +191,7 @@ def update(debug, board, update_all): psram_freq = value elif key == "UF2_BOOTLOADER": uf2_bootloader = not (value == "0") - elif key == "CIRCUITPY_BLEIO": + elif key == "CIRCUITPY_BLEIO_NATIVE": ble_enabled = not (value == "0") os.environ["IDF_TARGET"] = target @@ -205,7 +202,7 @@ def update(debug, board, update_all): kconfig_path = pathlib.Path(f"build-{board}/esp-idf/kconfigs.in") - kconfig_path = pathlib.Path(f"esp-idf/Kconfig") + kconfig_path = pathlib.Path("esp-idf/Kconfig") kconfig = kconfiglib.Kconfig(kconfig_path) input_config = pathlib.Path(f"build-{board}/esp-idf/sdkconfig") @@ -233,7 +230,7 @@ def update(debug, board, update_all): sdkconfigs.extend((flash_size_config, flash_mode_config, flash_freq_config)) if psram_size != "0": - psram_config = pathlib.Path(f"esp-idf-config/sdkconfig-psram.defaults") + psram_config = pathlib.Path("esp-idf-config/sdkconfig-psram.defaults") psram_size_config = pathlib.Path(f"esp-idf-config/sdkconfig-psram-{psram_size}.defaults") psram_mode_config = pathlib.Path(f"esp-idf-config/sdkconfig-psram-{psram_mode}.defaults") psram_freq_config = pathlib.Path(f"esp-idf-config/sdkconfig-psram-{psram_freq}.defaults") @@ -241,7 +238,7 @@ def update(debug, board, update_all): target_config = pathlib.Path(f"esp-idf-config/sdkconfig-{target}.defaults") sdkconfigs.append(target_config) if ble_enabled: - ble_config = pathlib.Path(f"esp-idf-config/sdkconfig-ble.defaults") + ble_config = pathlib.Path("esp-idf-config/sdkconfig-ble.defaults") sdkconfigs.append(ble_config) board_config = pathlib.Path(f"boards/{board}/sdkconfig") # Don't include the board file in cp defaults. The board may have custom @@ -324,7 +321,7 @@ def update(debug, board, update_all): if print_debug: print(" " * len(current_group), i, config_string.strip()) - # Some files are `rsource`d into another kconfig with $IDF_TARGET as + # Some files are `rsource`d into another kconfig with $IDF_TARGET as # codespell:ignore rsource # part of the path. kconfiglib doesn't show this as a reference so # we have to look ourselves. target_reference = target in item.name_and_loc diff --git a/ports/litex/Makefile b/ports/litex/Makefile index 4e20b3c4ca195..cc813a49f8e70 100644 --- a/ports/litex/Makefile +++ b/ports/litex/Makefile @@ -32,13 +32,13 @@ ifeq ($(DEBUG), 1) OPTIMIZATION_FLAGS ?= -Og else CFLAGS += -DNDEBUG -ggdb3 - OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions + OPTIMIZATION_FLAGS ?= -O2 endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk CFLAGS += $(OPTIMIZATION_FLAGS) -CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes +CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition # TODO: check this CFLAGS += -D__START=main -DFOMU @@ -77,16 +77,12 @@ ifneq ($(CIRCUITPY_USB),0) SRC_C += lib/tinyusb/src/portable/valentyusb/eptri/dcd_eptri.c endif -SRC_S = \ +SRC_S_UPPER = \ crt0-vexriscv.S -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) +SRC_S = shared/runtime/gchelper_rv32i.s -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) +SRC_C += shared/runtime/gchelper_native.c $(BUILD)/lib/tlsf/tlsf.o: CFLAGS += -Wno-cast-align @@ -96,20 +92,20 @@ FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) endif OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_S:.S=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/litex/common-hal/microcontroller/Pin.c b/ports/litex/common-hal/microcontroller/Pin.c index dea848f1ec3f3..bb3636c5b3faa 100644 --- a/ports/litex/common-hal/microcontroller/Pin.c +++ b/ports/litex/common-hal/microcontroller/Pin.c @@ -11,6 +11,10 @@ static uint8_t claimed_pins[1]; +void reset_all_pins(void) { + // TODO +} + // Mark pin as free and return it to a quiescent state. void reset_pin_number(uint8_t pin_port, uint8_t pin_number) { if (pin_port == 0x0F) { diff --git a/ports/litex/common-hal/microcontroller/Pin.h b/ports/litex/common-hal/microcontroller/Pin.h index 542f3e979b5bc..860a8c9ccadb6 100644 --- a/ports/litex/common-hal/microcontroller/Pin.h +++ b/ports/litex/common-hal/microcontroller/Pin.h @@ -7,6 +7,7 @@ #pragma once #include "py/mphal.h" +#include "py/obj.h" typedef struct { diff --git a/ports/litex/common-hal/os/__init__.c b/ports/litex/common-hal/os/__init__.c index e6da1904da522..659411187fafb 100644 --- a/ports/litex/common-hal/os/__init__.c +++ b/ports/litex/common-hal/os/__init__.c @@ -12,32 +12,6 @@ #include "shared-bindings/os/__init__.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "litex"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "litex"); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { return false; } diff --git a/ports/litex/mpconfigport.h b/ports/litex/mpconfigport.h index 8e7537af6a63a..7ac34a44336cf 100644 --- a/ports/litex/mpconfigport.h +++ b/ports/litex/mpconfigport.h @@ -9,7 +9,6 @@ #define CIRCUITPY_INTERNAL_NVM_SIZE (0) #define MICROPY_NLR_THUMB (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #include "py/circuitpy_mpconfig.h" diff --git a/ports/litex/mpconfigport.mk b/ports/litex/mpconfigport.mk index d8dc4eef1edcd..a93a3890bbc9a 100644 --- a/ports/litex/mpconfigport.mk +++ b/ports/litex/mpconfigport.mk @@ -31,3 +31,4 @@ CIRCUITPY_USB_HID = 1 CIRCUITPY_USB_MIDI = 1 CIRCUITPY_BUILD_EXTENSIONS ?= dfu +CIRCUITPY_MIN_GCC_VERSION ?= 8 diff --git a/ports/litex/mphalport.c b/ports/litex/mphalport.c index cc74762a14f14..b94699e81e705 100644 --- a/ports/litex/mphalport.c +++ b/ports/litex/mphalport.c @@ -54,9 +54,3 @@ void isr(void) { // Decrease the "nesting count". Note: This should be going from 1 -> 0. nesting_count -= 1; } - -mp_uint_t cpu_get_regs_and_sp(mp_uint_t *regs) { - unsigned long __tmp; - asm volatile ("mv %0, x2" : "=r" (__tmp)); - return __tmp; -} diff --git a/ports/litex/supervisor/port.c b/ports/litex/supervisor/port.c index 7009956c317ab..7f9aab7f7ffb4 100644 --- a/ports/litex/supervisor/port.c +++ b/ports/litex/supervisor/port.c @@ -59,7 +59,6 @@ extern uint32_t _heap_start; extern uint32_t _estack; void reset_port(void) { - // reset_all_pins(); // i2c_reset(); // spi_reset(); // uart_reset(); @@ -114,6 +113,9 @@ uint64_t port_get_raw_ticks(uint8_t *subticks) { common_hal_mcu_disable_interrupts(); uint64_t raw_tick_snapshot = raw_ticks; common_hal_mcu_enable_interrupts(); + if (subticks != NULL) { + *subticks = 0; + } return raw_tick_snapshot; } diff --git a/ports/mimxrt10xx/Makefile b/ports/mimxrt10xx/Makefile index f13207451e6c2..74667fd3d6446 100644 --- a/ports/mimxrt10xx/Makefile +++ b/ports/mimxrt10xx/Makefile @@ -45,7 +45,7 @@ ifeq ($(DEBUG), 1) CFLAGS += -fno-ipa-sra endif -CFLAGS += $(INC) -ggdb -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes +CFLAGS += $(INC) -ggdb -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition # TODO: add these when -Werror is applied # Disable some warnings, as do most ports. NXP SDK causes undef, tinyusb causes cast-align @@ -126,6 +126,10 @@ SRC_SDK += drivers/adc_12b1msps_sar/fsl_adc.c \ drivers/tempmon/fsl_tempmon.c endif +ifeq ($(CIRCUITPY_CANIO), 1) +SRC_SDK += drivers/flexcan/fsl_flexcan.c +endif + ifeq ($(CHIP_FAMILY), MIMXRT1176) SRC_SDK += devices/$(CHIP_FAMILY)/drivers/fsl_anatop_ai.c \ devices/$(CHIP_FAMILY)/drivers/fsl_dcdc.c \ @@ -157,30 +161,25 @@ SRC_C += \ endif -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) +SRC_S_UPPER = \ + sdk/devices/$(CHIP_FAMILY)/gcc/startup_$(CHIP_CORE).S -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) +SRC_S = shared/runtime/gchelper_thumb2.s -SRC_S = \ - sdk/devices/$(CHIP_FAMILY)/gcc/startup_$(CHIP_CORE).S \ - supervisor/cpu.S +SRC_C += shared/runtime/gchelper_native.c OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_SDK:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_S:.S=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2 $(BUILD)/firmware.hex diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/README.md b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/README.md new file mode 100644 index 0000000000000..ce484fc846588 --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/README.md @@ -0,0 +1,26 @@ +# Makerdiary iMX RT1011 Nano Kit + +## Introduction + +[iMX RT1011 Nano Kit](https://makerdiary.com/products/imxrt1011-nanokit) is a small, high-performing prototyping kit designed around NXP's iMX RT1011 Crossover MCU based on the Arm Cortex-M7 core, which operates at speeds up to 500 MHz to provide high CPU performance and best real-time response. It has 128 KB on-chip RAM that can be flexibly configured as TCM or general-purpose as well as numerous peripherals including high speed USB, UART, SPI, I2C, SAI, PWM, GPIO, ADC and etc to support a wide range of applications. + +The design provides external 128 Mbit QSPI flash with XIP support, flexible power management, programmable LED and Button, easy-to-use form factor with USB-C and dual-row 40 pins in DIP/SMT type, including up to 33 multi-function GPIO pins (15 can be configured as ADC inputs) and Serial Wire Debug (SWD) port. Available with loose or pre-soldered headers, for even more flexibility in your projects. + +It's shipped with UF2 Bootloader for easy firmware update, which means you can easily install CircuitPython firmware by just copying the .uf2-format images to the flash drive without using an external programmer. + +Refer to [iMX RT1011 Nano Kit Documentation](https://wiki.makerdiary.com/imxrt1011-nanokit/) for more details. + +![](https://wiki.makerdiary.com/imxrt1011-nanokit/assets/images/imxrt1011-nanokit-hero.png) + +## Hardware Diagram + +The following figure illustrates the iMX RT1011 Nano Kit hardware diagram. The design is available with loose or pre-soldered pin headers. For more details, refer to the [Hardware description](https://wiki.makerdiary.com/imxrt1011-nanokit/hardware/) section. + +[![](https://wiki.makerdiary.com/imxrt1011-nanokit/assets/images/imxrt1011-nanokit-pinout_reva.png)](https://wiki.makerdiary.com/imxrt1011-nanokit/assets/attachments/imxrt1011-nanokit-pinout_reva.pdf) + +## Get Involved + +We think the best way to learn is by doing. And to help you get started, we have provided an extensive set of documentation. Find the details below: + +- [Getting started with CircuitPython](https://wiki.makerdiary.com/imxrt1011-nanokit/guides/python/getting-started/) +- [CircuitPython Samples for iMX RT1011 Nano Kit](https://wiki.makerdiary.com/imxrt1011-nanokit/guides/python/samples/) diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/board.c b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/board.c new file mode 100644 index 0000000000000..7ff52b5842a92 --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/board.c @@ -0,0 +1,45 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2024 Makerdiary +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "shared-bindings/microcontroller/Pin.h" + +// These pins should never ever be reset; doing so could interfere with basic operation. +// Used in common-hal/microcontroller/Pin.c +const mcu_pin_obj_t *mimxrt10xx_reset_forbidden_pins[] = { + // SWD Pins + &pin_GPIO_AD_13,// SWDIO + &pin_GPIO_AD_12,// SWCLK + + // FLEX flash + &pin_GPIO_SD_12, + &pin_GPIO_SD_11, + &pin_GPIO_SD_10, + &pin_GPIO_SD_09, + &pin_GPIO_SD_08, + &pin_GPIO_SD_07, + &pin_GPIO_SD_06, + NULL, // Must end in NULL. +}; + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. + +bool mimxrt10xx_board_reset_pin_number(const mcu_pin_obj_t *pin) { + #if CIRCUITPY_SWO_TRACE + if (pin == &pin_GPIO_AD_09) { + IOMUXC_SetPinMux( /* Add these lines*/ + IOMUXC_GPIO_AD_09_ARM_TRACE_SWO, + 0U); + IOMUXC_SetPinConfig( /* Add these lines*/ + IOMUXC_GPIO_AD_09_ARM_TRACE_SWO, + 0x00F9U); + return true; + } + #endif + return false; +} diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/flash_config.c b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/flash_config.c new file mode 100644 index 0000000000000..9073741ed4888 --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/flash_config.c @@ -0,0 +1,153 @@ +/* + * Copyright 2017 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "boards/flash_config.h" + +#include "xip/fsl_flexspi_nor_boot.h" + +// Config for W25Q128JV with QSPI routed. +__attribute__((section(".boot_hdr.conf"))) +const flexspi_nor_config_t qspiflash_config = { + .pageSize = 256u, + .sectorSize = 4u * 1024u, + .ipcmdSerialClkFreq = kFLEXSPISerialClk_133MHz, + .blockSize = 0x00010000, + .isUniformBlockSize = false, + .memConfig = + { + .tag = FLEXSPI_CFG_BLK_TAG, + .version = FLEXSPI_CFG_BLK_VERSION, + .readSampleClkSrc = kFLEXSPIReadSampleClk_LoopbackFromSckPad, + .csHoldTime = 3u, + .csSetupTime = 3u, + + .busyOffset = 0u, // Status bit 0 indicates busy. + .busyBitPolarity = 0u, // Busy when the bit is 1. + + .deviceModeCfgEnable = 1u, + .deviceModeType = kDeviceConfigCmdType_QuadEnable, + .deviceModeSeq = { + .seqId = 4u, + .seqNum = 1u, + }, + .deviceModeArg = 0x0200, + .configCmdEnable = 1u, + .configModeType[0] = kDeviceConfigCmdType_Generic, + .configCmdSeqs[0] = { + .seqId = 2u, + .seqNum = 1u, + }, + .deviceType = kFLEXSPIDeviceType_SerialNOR, + .sflashPadType = kSerialFlash_4Pads, + .serialClkFreq = kFLEXSPISerialClk_133MHz, + .sflashA1Size = FLASH_SIZE, + .lookupTable = + { + // FSL_ROM_FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) + // The high 16 bits is command 1 and the low are command 0. + // Within a command, the top 6 bits are the opcode, the next two are the number + // of pads and then last byte is the operand. The operand's meaning changes + // per opcode. + + // Indices with ROM should always have the same function because the ROM + // bootloader uses it. + + // 0: ROM: Read LUTs + // Quad version + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB /* the command to send */, + RADDR_SDR, FLEXSPI_4PAD, 24 /* bits to transmit */), + FSL_ROM_FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 6 /* 6 dummy cycles, 2 for M7-0 and 4 dummy */, + READ_SDR, FLEXSPI_4PAD, 0x04), + // Single fast read version, good for debugging. + // FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x0B /* the command to send */, + // RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */), + // FSL_ROM_FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_1PAD, 8 /* 8 dummy clocks */, + // READ_SDR, FLEXSPI_1PAD, 0x04), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 1: ROM: Read status + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05 /* the command to send */, + READ_SDR, FLEXSPI_1PAD, 0x02), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 2: Empty + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x35 /* the command to send */, + DUMMY_SDR, FLEXSPI_1PAD, 8), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 3: ROM: Write Enable + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06 /* the command to send */, + STOP, FLEXSPI_1PAD, 0x00), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 4: Config: Write Status + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x01 /* the command to send */, + WRITE_SDR, FLEXSPI_1PAD, 0x02), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 5: ROM: Erase Sector + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x20 /* the command to send */, + RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 6: Empty + EMPTY_SEQUENCE, + + // 7: Empty + EMPTY_SEQUENCE, + + // 8: Block Erase + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xD8 /* the command to send */, + RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 9: ROM: Page program + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x02 /* the command to send */, + RADDR_SDR, FLEXSPI_1PAD, 24 /* bits to transmit */), + + FSL_ROM_FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x04 /* data out */, + STOP, FLEXSPI_1PAD, 0), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 10: Empty + EMPTY_SEQUENCE, + + // 11: ROM: Chip erase + SEQUENCE(FSL_ROM_FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x60 /* the command to send */, + STOP, FLEXSPI_1PAD, 0), + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS, + TWO_EMPTY_STEPS), + + // 12: Empty + EMPTY_SEQUENCE, + + // 13: ROM: Read SFDP + EMPTY_SEQUENCE, + + // 14: ROM: Restore no cmd + EMPTY_SEQUENCE, + + // 15: ROM: Dummy + EMPTY_SEQUENCE + }, + }, +}; diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.h b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.h new file mode 100644 index 0000000000000..e921946cc0531 --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.h @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2024 Makerdiary +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "iMX RT1011 Nano Kit" +#define MICROPY_HW_MCU_NAME "IMXRT1011DAE5A" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO_00) + +// If you change this, then make sure to update the linker scripts as well to +// make sure you don't overwrite code +#define CIRCUITPY_INTERNAL_NVM_SIZE 0 + +#define BOARD_FLASH_SIZE (16 * 1024 * 1024) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO_02) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO_01) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO_AD_06) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO_AD_04) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO_AD_03) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO_09) +#define DEFAULT_UART_BUS_TX (&pin_GPIO_10) diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.mk b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.mk new file mode 100644 index 0000000000000..3f8a4682fa067 --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2886 +USB_PID = 0xF004 +USB_PRODUCT = "iMX RT1011 Nano Kit" +USB_MANUFACTURER = "Makerdiary" + +CHIP_VARIANT = MIMXRT1011DAE5A +CHIP_FAMILY = MIMXRT1011 +FLASH = W25Q128JV + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID diff --git a/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/pins.c b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/pins.c new file mode 100644 index 0000000000000..a573e1bc75bea --- /dev/null +++ b/ports/mimxrt10xx/boards/makerdiary_imxrt1011_nanokit/pins.c @@ -0,0 +1,83 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2024 Makerdiary +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +#include "supervisor/board.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Analog + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO_AD_00) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO_AD_01) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO_AD_02) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO_AD_03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO_AD_04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO_AD_05) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO_AD_06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO_AD_07) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_GPIO_AD_08) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_GPIO_AD_09) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_GPIO_AD_10) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_GPIO_AD_11) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A14), MP_ROM_PTR(&pin_GPIO_AD_14) }, + + // Digital + { MP_OBJ_NEW_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO_00) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO_01) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO_02) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO_03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO_04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO_05) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO_06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO_07) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO_08) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO_09) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO_10) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO_11) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO_12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO_13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD0), MP_ROM_PTR(&pin_GPIO_SD_00) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD1), MP_ROM_PTR(&pin_GPIO_SD_01) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD2), MP_ROM_PTR(&pin_GPIO_SD_02) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD3), MP_ROM_PTR(&pin_GPIO_SD_03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD4), MP_ROM_PTR(&pin_GPIO_SD_04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD5), MP_ROM_PTR(&pin_GPIO_SD_05) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD13), MP_ROM_PTR(&pin_GPIO_SD_13) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO_SD_04) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_USR_BTN), MP_ROM_PTR(&pin_GPIO_SD_03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DCDC_MODE), MP_ROM_PTR(&pin_GPIO_SD_13) }, + + // SPI + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO_AD_06) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO_AD_03) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO_AD_04) }, + + // I2C + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO_01) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO_02) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO_00) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_WORD_SELECT), MP_ROM_PTR(&pin_GPIO_06) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WSEL), MP_ROM_PTR(&pin_GPIO_06) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_BIT_CLOCK), MP_ROM_PTR(&pin_GPIO_07) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO_07) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_DATA), MP_ROM_PTR(&pin_GPIO_04) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_ROM_PTR(&pin_GPIO_04) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/mimxrt10xx/boards/teensy40/mpconfigboard.h b/ports/mimxrt10xx/boards/teensy40/mpconfigboard.h index e7565d64438f6..e6931752e3e58 100644 --- a/ports/mimxrt10xx/boards/teensy40/mpconfigboard.h +++ b/ports/mimxrt10xx/boards/teensy40/mpconfigboard.h @@ -25,3 +25,6 @@ #define DEFAULT_UART_BUS_RX (&pin_GPIO_AD_B0_03) #define DEFAULT_UART_BUS_TX (&pin_GPIO_AD_B0_02) + +#define CIRCUITPY_USB_DEVICE_INSTANCE 0 +#define CIRCUITPY_USB_HOST_INSTANCE 1 diff --git a/ports/mimxrt10xx/boards/teensy40/mpconfigboard.mk b/ports/mimxrt10xx/boards/teensy40/mpconfigboard.mk index 9cb1e636b6f33..f26f8dbd72b79 100644 --- a/ports/mimxrt10xx/boards/teensy40/mpconfigboard.mk +++ b/ports/mimxrt10xx/boards/teensy40/mpconfigboard.mk @@ -7,4 +7,5 @@ CHIP_VARIANT = MIMXRT1062DVJ6A CHIP_FAMILY = MIMXRT1062 FLASH = W25Q16JV CIRCUITPY__EVE = 1 +CIRCUITPY_USB_HOST = 1 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1 diff --git a/ports/mimxrt10xx/boards/teensy40/pins.c b/ports/mimxrt10xx/boards/teensy40/pins.c index 7aacdf95e15ff..dc8b07605b256 100644 --- a/ports/mimxrt10xx/boards/teensy40/pins.c +++ b/ports/mimxrt10xx/boards/teensy40/pins.c @@ -120,6 +120,10 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { {MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj)}, {MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj)}, + // USB Host (pads) + {MP_ROM_QSTR(MP_QSTR_USB_HOST_DP), MP_ROM_PTR(&pin_USB_OTG2_DP)}, + {MP_ROM_QSTR(MP_QSTR_USB_HOST_DM), MP_ROM_PTR(&pin_USB_OTG2_DN)}, + // other i2c ports defined {MP_OBJ_NEW_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO_AD_B1_06)}, {MP_OBJ_NEW_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO_AD_B1_07)}, diff --git a/ports/mimxrt10xx/boards/teensy41/mpconfigboard.mk b/ports/mimxrt10xx/boards/teensy41/mpconfigboard.mk index 7d16b797c5223..6d1f802d6e358 100644 --- a/ports/mimxrt10xx/boards/teensy41/mpconfigboard.mk +++ b/ports/mimxrt10xx/boards/teensy41/mpconfigboard.mk @@ -7,5 +7,6 @@ CHIP_VARIANT = MIMXRT1062DVJ6A CHIP_FAMILY = MIMXRT1062 FLASH = W25Q64JV CIRCUITPY__EVE = 1 +CIRCUITPY_CANIO = 1 CIRCUITPY_USB_HOST = 1 CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1 diff --git a/ports/mimxrt10xx/boards/teensy41/pins.c b/ports/mimxrt10xx/boards/teensy41/pins.c index 64eac9e4b70c8..84236382330d6 100644 --- a/ports/mimxrt10xx/boards/teensy41/pins.c +++ b/ports/mimxrt10xx/boards/teensy41/pins.c @@ -179,5 +179,23 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { {MP_OBJ_NEW_QSTR(MP_QSTR_TX7), MP_ROM_PTR(&pin_GPIO_EMC_31)}, {MP_OBJ_NEW_QSTR(MP_QSTR_RX8), MP_ROM_PTR(&pin_GPIO_B1_13)}, {MP_OBJ_NEW_QSTR(MP_QSTR_TX8), MP_ROM_PTR(&pin_GPIO_B1_12)}, + + // CAN and CAN-FD + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN1_RX), MP_ROM_PTR(&pin_GPIO_AD_B1_09)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN1_TX), MP_ROM_PTR(&pin_GPIO_AD_B1_08)}, + + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN2_RX), MP_ROM_PTR(&pin_GPIO_AD_B0_03)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN2_TX), MP_ROM_PTR(&pin_GPIO_AD_B0_02)}, + + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN3_RX), MP_ROM_PTR(&pin_GPIO_EMC_37)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN3_TX), MP_ROM_PTR(&pin_GPIO_EMC_36)}, + + // "CAN" is an alias for CAN1 + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN_RX), MP_ROM_PTR(&pin_GPIO_AD_B1_09)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_CAN_TX), MP_ROM_PTR(&pin_GPIO_AD_B1_08)}, + + // "CANFD" is an alias for CAN3 + {MP_OBJ_NEW_QSTR(MP_QSTR_CANFD_RX), MP_ROM_PTR(&pin_GPIO_EMC_37)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_CANFD_TX), MP_ROM_PTR(&pin_GPIO_EMC_36)}, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/mimxrt10xx/common-hal/audiobusio/__init__.c b/ports/mimxrt10xx/common-hal/audiobusio/__init__.c index fcedf34ef72ea..f1030bfcd848c 100644 --- a/ports/mimxrt10xx/common-hal/audiobusio/__init__.c +++ b/ports/mimxrt10xx/common-hal/audiobusio/__init__.c @@ -309,7 +309,7 @@ void port_i2s_initialize(i2s_t *self, int instance, sai_transceiver_t *config) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_I2SOut); } for (size_t i = 0; i < MP_ARRAY_SIZE(self->buffers); i++) { - self->buffers[i] = m_malloc(AUDIO_BUFFER_FRAME_COUNT * sizeof(uint32_t)); + self->buffers[i] = m_malloc_without_collect(AUDIO_BUFFER_FRAME_COUNT * sizeof(uint32_t)); } self->peripheral = peripheral; SAI_Init(self->peripheral); @@ -374,11 +374,11 @@ static void set_sai_clocking_for_sample_rate(uint32_t sample_rate) { void port_i2s_play(i2s_t *self, mp_obj_t sample, bool loop) { self->sample = sample; self->loop = loop; - self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; - self->channel_count = audiosample_channel_count(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8; + self->channel_count = audiosample_get_channel_count(sample); int instance = SAI_GetInstance(self->peripheral); i2s_playing |= (1 << instance); - uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); if (sample_rate != self->sample_rate) { if (__builtin_popcount(i2s_playing) <= 1) { // as this is the first/only i2s instance playing audio, we can @@ -439,6 +439,6 @@ void port_i2s_resume(i2s_t *self) { self->paused = false; } -void i2s_reset() { +void i2s_reset(void) { // this port relies on object finalizers for reset } diff --git a/ports/mimxrt10xx/common-hal/busio/I2C.c b/ports/mimxrt10xx/common-hal/busio/I2C.c index 10394a3908c71..93c0ab301235b 100644 --- a/ports/mimxrt10xx/common-hal/busio/I2C.c +++ b/ports/mimxrt10xx/common-hal/busio/I2C.c @@ -27,16 +27,6 @@ // arrays use 0 based numbering: I2C1 is stored at index 0 static bool reserved_i2c[MP_ARRAY_SIZE(mcu_i2c_banks)]; -static bool never_reset_i2c[MP_ARRAY_SIZE(mcu_i2c_banks)]; - -void i2c_reset(void) { - for (uint i = 0; i < MP_ARRAY_SIZE(mcu_i2c_banks); i++) { - if (!never_reset_i2c[i]) { - reserved_i2c[i] = false; - LPI2C_MasterDeinit(mcu_i2c_banks[i]); - } - } -} static void config_periph_pin(const mcu_periph_obj_t *periph) { IOMUXC_SetPinMux( @@ -76,6 +66,9 @@ static void i2c_check_pin_config(const mcu_pin_obj_t *pin, uint32_t pull) { void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + #if CIRCUITPY_REQUIRE_I2C_PULLUPS // Test that the pins are in a high state. (Hopefully indicating they are pulled up.) IOMUXC_SetPinMux(sda->mux_reg, IOMUXC_SW_MUX_CTL_PAD_MUX_MODE_ALT5, 0, 0, 0, 0); @@ -153,8 +146,6 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - never_reset_i2c[self->sda->bank_idx - 1] = true; - common_hal_never_reset_pin(self->sda->pin); common_hal_never_reset_pin(self->scl->pin); } @@ -168,15 +159,17 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { return; } reserved_i2c[self->sda->bank_idx - 1] = false; - never_reset_i2c[self->sda->bank_idx - 1] = false; LPI2C_MasterDeinit(self->i2c); common_hal_reset_pin(self->sda->pin); common_hal_reset_pin(self->scl->pin); + common_hal_busio_i2c_mark_deinit(self); +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { self->sda = NULL; - self->scl = NULL; } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { @@ -187,6 +180,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; // CRITICAL_SECTION_ENTER() if (!self->has_lock) { @@ -205,7 +201,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { self->has_lock = false; } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { lpi2c_master_transfer_t xfer = { 0 }; @@ -219,15 +215,15 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, return 0; } - return MP_EIO; + return -MP_EIO; } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { lpi2c_master_transfer_t xfer = { 0 }; @@ -241,12 +237,12 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, return 0; } - return MP_EIO; + return -MP_EIO; } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } diff --git a/ports/mimxrt10xx/common-hal/busio/I2C.h b/ports/mimxrt10xx/common-hal/busio/I2C.h index 06b86cd2d3401..153c2541090aa 100644 --- a/ports/mimxrt10xx/common-hal/busio/I2C.h +++ b/ports/mimxrt10xx/common-hal/busio/I2C.h @@ -19,5 +19,3 @@ typedef struct { const mcu_periph_obj_t *scl; const mcu_periph_obj_t *sda; } busio_i2c_obj_t; - -void i2c_reset(void); diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.c b/ports/mimxrt10xx/common-hal/busio/SPI.c index 118638af13882..90695be4b4e6d 100644 --- a/ports/mimxrt10xx/common-hal/busio/SPI.c +++ b/ports/mimxrt10xx/common-hal/busio/SPI.c @@ -26,7 +26,6 @@ // arrays use 0 based numbering: SPI1 is stored at index 0 static bool reserved_spi[MP_ARRAY_SIZE(mcu_spi_banks)]; -static bool never_reset_spi[MP_ARRAY_SIZE(mcu_spi_banks)]; #if IMXRT11XX static const clock_ip_name_t s_lpspiClocks[] = LPSPI_CLOCKS; @@ -53,22 +52,6 @@ static void config_periph_pin(const mcu_periph_obj_t *periph) { | IOMUXC_SW_PAD_CTL_PAD_SRE(0)); } -void spi_reset(void) { - for (uint i = 0; i < MP_ARRAY_SIZE(mcu_spi_banks); i++) { - if (!never_reset_spi[i]) { - reserved_spi[i] = false; - #if IMXRT11XX - // Skip resetting SPIs that aren't clocked. Doing so generates a bus fault. - if ((CCM->LPCG[s_lpspiClocks[i + 1]].STATUS0 & CCM_LPCG_STATUS0_ON_MASK) == ((uint32_t)kCLOCK_Off & CCM_LPCG_STATUS0_ON_MASK)) { - continue; - } - #endif - - LPSPI_Deinit(mcu_spi_banks[i]); - } - } -} - void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { @@ -82,6 +65,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex); } + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + for (uint i = 0; i < sck_count; i++) { if (mcu_spi_sck_list[i].pin != clock) { continue; @@ -200,7 +186,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - never_reset_spi[self->clock->bank_idx - 1] = true; common_hal_never_reset_pin(self->clock->pin); if (self->mosi != NULL) { common_hal_never_reset_pin(self->mosi->pin); @@ -214,21 +199,25 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock = NULL; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; } LPSPI_Deinit(self->spi); reserved_spi[self->clock->bank_idx - 1] = false; - never_reset_spi[self->clock->bank_idx - 1] = false; common_hal_reset_pin(self->clock->pin); common_hal_reset_pin(self->mosi->pin); common_hal_reset_pin(self->miso->pin); - self->clock = NULL; self->mosi = NULL; self->miso = NULL; + + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, @@ -272,6 +261,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; // CRITICAL_SECTION_ENTER() if (!self->has_lock) { diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.h b/ports/mimxrt10xx/common-hal/busio/SPI.h index 67801078261c1..d86489428ec78 100644 --- a/ports/mimxrt10xx/common-hal/busio/SPI.h +++ b/ports/mimxrt10xx/common-hal/busio/SPI.h @@ -21,5 +21,3 @@ typedef struct { const mcu_periph_obj_t *mosi; const mcu_periph_obj_t *miso; } busio_spi_obj_t; - -void spi_reset(void); diff --git a/ports/mimxrt10xx/common-hal/canio/CAN.c b/ports/mimxrt10xx/common-hal/canio/CAN.c new file mode 100644 index 0000000000000..0b598af1521f0 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/CAN.c @@ -0,0 +1,445 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// SPDX-FileCopyrightText: Copyright (c) 2025 SamantazFox +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/runtime.h" +#include "py/mperrno.h" + +#include "common-hal/canio/CAN.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "supervisor/port.h" +#include "supervisor/shared/tick.h" + +#include "sdk/drivers/flexcan/fsl_flexcan.h" + + +// Be verbose +#define MIMXRT_CANIO_CAN_DEBUG(...) (void)0 +// #define MIMXRT_CANIO_CAN_DEBUG(...) mp_printf(&mp_plat_print, __VA_ARGS__) + +#define MIMXRT_CANIO_CAN_CALLBACK_DEBUG(...) (void)0 +// #define MIMXRT_CANIO_CAN_CALLBACK_DEBUG(...) mp_printf(&mp_plat_print, __VA_ARGS__) + + +static CAN_Type *const flexcan_bases[] = CAN_BASE_PTRS; // e.g.: { (CAN_Type *)0u, CAN1, CAN2, CAN3 } +static canio_can_obj_t *can_objs[MP_ARRAY_SIZE(mcu_can_banks)]; + +// Get frequency of flexcan clock. +#define MIMXRT10XX_FLEXCAN_CLK_FREQ ((CLOCK_GetFreq(kCLOCK_Usb1PllClk) / 8) / (CLOCK_GetDiv(kCLOCK_CanDiv) + 1)) + +static void config_periph_pin(const mcu_periph_obj_t *periph) { + if (!periph) { + return; + } + IOMUXC_SetPinMux( + periph->pin->mux_reg, periph->mux_mode, + periph->input_reg, periph->input_idx, + 0, + 0); + + IOMUXC_SetPinConfig(0, 0, 0, 0, + periph->pin->cfg_reg, + IOMUXC_SW_PAD_CTL_PAD_PUS(0) // Pull Up/Down Config. Field: 100K Ohm Pull Down + #if IMXRT10XX + | IOMUXC_SW_PAD_CTL_PAD_HYS(0) // Hyst. Enable Field: Hysteresis Disabled + | IOMUXC_SW_PAD_CTL_PAD_PKE(1) // Pull/Keep Enable Field: Pull/Keeper Enabled + | IOMUXC_SW_PAD_CTL_PAD_SPEED(2) // Speed Field: medium (100MHz) + #endif + | IOMUXC_SW_PAD_CTL_PAD_PUE(0) // Pull/Keep Select Field: Keeper + | IOMUXC_SW_PAD_CTL_PAD_ODE(0) // Open Drain Enable Field: Open Drain Disabled + | IOMUXC_SW_PAD_CTL_PAD_DSE(6) // Drive Strength Field: R0/6 + | IOMUXC_SW_PAD_CTL_PAD_SRE(0)); // Slew Rate Field: Slow Slew Rate +} + +static uint8_t mimxrt10xx_flexcan_get_free_tx_mbid(canio_can_obj_t *self) { + // Get the next free tx message buffer atomically so that an interrupt can't occur while + // doing bit search. + // + // The idea here is that in an integer each bit acts as a boolean telling us if a + // tx message buffer is in use or not. + // If a free message buffer is found then we set it as used and return it's index. + bool found_free_tx_mb = false; + int8_t tx_array_id = 0; + mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + for ( ; tx_array_id < MIMXRT10XX_FLEXCAN_TX_MB_NUM; ++tx_array_id) + { + uint64_t tx_array_id_bit = (1UL << tx_array_id); + if (!(self->data->tx_state & tx_array_id_bit)) { + // Found a free tx array id. Mark it as used. + MIMXRT_CANIO_CAN_DEBUG("canio: Found free Tx MB: %d\n", tx_array_id); + self->data->tx_state |= tx_array_id_bit; + found_free_tx_mb = true; + break; + } + } + MICROPY_END_ATOMIC_SECTION(atomic_state); + + if (!found_free_tx_mb) { + mp_raise_ValueError(MP_ERROR_TEXT("Unable to send CAN Message: all Tx message buffers are busy")); + } + + return MIMXRT10XX_FLEXCAN_TX_ARRID_TO_MBID(tx_array_id); +} + +static void mimxrt10xx_flexcan_set_tx_mb_free_by_mbid(canio_can_obj_t *self, uint8_t mb_idx) { + // We simply set the Nth bit zero. This means that that message buffer is free to use. + uint64_t tx_array_id_bit = (1UL << MIMXRT10XX_FLEXCAN_TX_MBID_TO_ARRID(mb_idx)); + self->data->tx_state &= ~(tx_array_id_bit); +} + +static void mimxrt10xx_flexcan_set_tx_mb_busy_by_mbid(canio_can_obj_t *self, uint8_t mb_idx) { + // We simply set the Nth bit 1. This means that that message buffer is busy and cannot be used. + uint64_t tx_array_id_bit = (1UL << MIMXRT10XX_FLEXCAN_TX_MBID_TO_ARRID(mb_idx)); + self->data->tx_state |= tx_array_id_bit; +} + +static void mimxrt10xx_flexcan_abort_tx_frames(canio_can_obj_t *self) { + for (uint8_t tx_array_id = 0; tx_array_id < MIMXRT10XX_FLEXCAN_TX_MB_NUM; ++tx_array_id) + { + uint64_t tx_array_id_bit = (1UL << tx_array_id); + if (self->data->tx_state & tx_array_id_bit) { + // Found a used/busy tx message buffer. Abort it. + FLEXCAN_TransferAbortSend(self->data->base, &self->data->handle, MIMXRT10XX_FLEXCAN_TX_ARRID_TO_MBID(tx_array_id)); + + self->data->tx_state &= ~(tx_array_id_bit); // Mark tx message buffer as free. + } + } +} + +static void mimxrt10xx_flexcan_handle_error(canio_can_obj_t *self) { + canio_bus_state_t state = common_hal_canio_can_state_get(self); + if (state == BUS_STATE_OFF) { + // Abort any pending tx and rx in case of bus-off. + mimxrt10xx_flexcan_abort_tx_frames(self); + FLEXCAN_TransferAbortReceiveFifo(self->data->base, &self->data->handle); + } +} + +static FLEXCAN_CALLBACK(mimxrt10xx_flexcan_callback) +{ + (void)base; // unused variable + (void)handle; // unused variable + // The result field can either be a message buffer index or a status flags value. + + canio_can_obj_t *self = (canio_can_obj_t *)userData; + + switch (status) { + + // Process rx message buffer is idle event. + case kStatus_FLEXCAN_RxIdle: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxIdle\n"); + // We don't control any rx message buffers 'manually'. The rx fifo has control. + break; + + // Process tx message buffer is idle event. + case kStatus_FLEXCAN_TxIdle: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = TxIdle\n"); + mimxrt10xx_flexcan_set_tx_mb_free_by_mbid(self, result); + break; + + // Process tx message buffer is busy event. + case kStatus_FLEXCAN_TxBusy: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = TxBusy\n"); + mimxrt10xx_flexcan_set_tx_mb_busy_by_mbid(self, result); + break; + + // Process remote message is send out and message buffer changed to receive one event. + case kStatus_FLEXCAN_TxSwitchToRx: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = TxSwitchToRx\n"); + mimxrt10xx_flexcan_set_tx_mb_free_by_mbid(self, result); + break; + + // Process rx message buffer is busy event. + case kStatus_FLEXCAN_RxBusy: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxBusy\n"); + break; + + // Process rx message buffer is overflowed event. + case kStatus_FLEXCAN_RxOverflow: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxOverflow\n"); + break; + + // Process rx message fifo is busy event. + case kStatus_FLEXCAN_RxFifoBusy: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxFifoBusy\n"); + break; + + // Process rx message fifo is idle event. + case kStatus_FLEXCAN_RxFifoIdle: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxFifoIdle\n"); + break; + + // Process rx message fifo is overflowed event. + case kStatus_FLEXCAN_RxFifoOverflow: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxFifoOverflow\n"); + break; + + // Process rx message fifo is almost overflowed event. + case kStatus_FLEXCAN_RxFifoWarning: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxFifoWarning\n"); + break; + + // Process rx message fifo is disabled during reading event. + case kStatus_FLEXCAN_RxFifoDisabled: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = RxFifoDisabled\n"); + break; + + // Process FlexCAN is waken up from stop mode event. + case kStatus_FLEXCAN_WakeUp: + MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = WakeUp\n"); + break; + + // Process unhandled interrupt asserted event. + case kStatus_FLEXCAN_UnHandled: + // Process FlexCAN module error and status event. + case kStatus_FLEXCAN_ErrorStatus: + // This is *very* verbose when the bus is disconnected! + // MIMXRT_CANIO_CAN_CALLBACK_DEBUG("canio: callback got status = UnHandled or ErrorStatus"); + + // We could do some fancy statistics update, but canio does not have. + mimxrt10xx_flexcan_handle_error(self); + break; + } +} + +void common_hal_canio_can_construct(canio_can_obj_t *self, const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, int baudrate, bool loopback, bool silent) { + + int instance = -1; + const mcu_periph_obj_t *rx_periph = find_pin_function(mcu_can_rx_list, rx, &instance, MP_QSTR_rx); + const mcu_periph_obj_t *tx_periph = find_pin_function(mcu_can_tx_list, tx, &instance, MP_QSTR_tx); + + MIMXRT_CANIO_CAN_DEBUG("canio: init instance: %d\n", instance); + MIMXRT_CANIO_CAN_DEBUG("canio: init loopback: %d\n", loopback ? 1 : 0); + MIMXRT_CANIO_CAN_DEBUG("canio: init silent: %d\n", silent ? 1 : 0); + MIMXRT_CANIO_CAN_DEBUG("canio: init baudrate: %d\n", baudrate); + + self->rx_pin = rx; + self->tx_pin = tx; + config_periph_pin(rx_periph); + config_periph_pin(tx_periph); + + self->loopback = loopback; + self->silent = silent; + self->baudrate = baudrate; + + self->data = m_malloc_without_collect(sizeof(mimxrt10xx_flexcan_data_t)); + self->data->base = flexcan_bases[instance]; // 'flexcan_bases' start indexing from 1. (The first element is NULL) + self->data->tx_state = 0; + + // Get flexcan module default configuration. + flexcan_config_t config; + FLEXCAN_GetDefaultConfig(&config); + + // Change default flexcan module configuration based on canio constructor parameters. + config.clkSrc = CLOCK_GetMux(kCLOCK_CanMux); + config.baudRate = baudrate; + config.enableLoopBack = loopback; + config.enableListenOnlyMode = silent; + config.maxMbNum = 64; + config.enableIndividMask = true; // required to enable matching using a 'Listener' + // config.disableSelfReception = true; // TODO: do we want to disable this? + + #if (defined(MIMXRT10XX_FLEXCAN_USE_IMPROVED_TIMING_CONFIG) && MIMXRT10XX_FLEXCAN_USE_IMPROVED_TIMING_CONFIG) + // If improved timing configuration is enabled then tell the SDK to calculate it. + flexcan_timing_config_t timing_config; + memset(&timing_config, 0, sizeof(flexcan_timing_config_t)); + if (FLEXCAN_CalculateImprovedTimingValues(self->data->base, config.baudRate, MIMXRT10XX_FLEXCAN_CLK_FREQ, &timing_config)) { + // SDK could calculate the improved timing configuration. Yay! + // Let's update our flexcan module config to use it. + memcpy(&(config.timingConfig), &timing_config, sizeof(flexcan_timing_config_t)); + } + #endif + + // Initialize the flexcan module with user-defined settings. + FLEXCAN_Init(self->data->base, &config, MIMXRT10XX_FLEXCAN_CLK_FREQ); + + // Create FlexCAN handle structure and set call back function. + // As callback data we set 'self'. In callback we can cast it back to 'canio_can_obj_t'. + FLEXCAN_TransferCreateHandle(self->data->base, &self->data->handle, mimxrt10xx_flexcan_callback, (void *)self); + + // Set rx mask to don't care on all bits. + flexcan_rx_fifo_config_t fifo_config; + fifo_config.idFilterNum = 0; + fifo_config.idFilterTable = self->data->rx_fifo_filter; + fifo_config.idFilterType = kFLEXCAN_RxFifoFilterTypeA; + fifo_config.priority = kFLEXCAN_RxFifoPrioHigh; + FLEXCAN_SetRxFifoConfig(self->data->base, &fifo_config, true); + + claim_pin(rx); + claim_pin(tx); + + can_objs[instance] = self; +} + +bool common_hal_canio_can_loopback_get(canio_can_obj_t *self) { + return self->loopback; +} + +int common_hal_canio_can_baudrate_get(canio_can_obj_t *self) { + return self->baudrate; +} + +int common_hal_canio_can_transmit_error_count_get(canio_can_obj_t *self) { + uint8_t tx_err_cnt; // Transmit error counter. + FLEXCAN_GetBusErrCount(self->data->base, &tx_err_cnt, NULL); + return tx_err_cnt; +} + +int common_hal_canio_can_receive_error_count_get(canio_can_obj_t *self) { + uint8_t rx_err_cnt; // Transmit error counter. + FLEXCAN_GetBusErrCount(self->data->base, NULL, &rx_err_cnt); + return rx_err_cnt; +} + +canio_bus_state_t common_hal_canio_can_state_get(canio_can_obj_t *self) { + uint64_t status_flags = FLEXCAN_GetStatusFlags(self->data->base); + if ((status_flags & CAN_ESR1_FLTCONF(2)) != 0U) { + return BUS_STATE_OFF; + } + if ((status_flags & CAN_ESR1_FLTCONF(1)) != 0U) { + return BUS_STATE_ERROR_PASSIVE; + } + if ((status_flags & (kFLEXCAN_TxErrorWarningFlag | kFLEXCAN_RxErrorWarningFlag)) != 0) { + return BUS_STATE_ERROR_WARNING; + } + return BUS_STATE_ERROR_ACTIVE; +} + +void common_hal_canio_can_restart(canio_can_obj_t *self) { + // Supposedly the felxcan SDK has built in recovery. + // But I will leave this code here just in case. + + canio_bus_state_t state = common_hal_canio_can_state_get(self); + if (state != BUS_STATE_OFF) { + return; + } + + self->data->base->CTRL1 &= ~CAN_CTRL1_BOFFREC_MASK; + + // Hard coded wait time for bus to recover. + uint64_t deadline = supervisor_ticks_ms64() + 100; // 100ms timeout + do { + if (supervisor_ticks_ms64() > deadline) { + break; + } + RUN_BACKGROUND_TASKS; + } while (common_hal_canio_can_state_get(self) == BUS_STATE_OFF); + + self->data->base->CTRL1 |= CAN_CTRL1_BOFFREC_MASK; +} + +bool common_hal_canio_can_auto_restart_get(canio_can_obj_t *self) { + return self->auto_restart; +} + +void common_hal_canio_can_auto_restart_set(canio_can_obj_t *self, bool value) { + self->auto_restart = value; +} + +static void maybe_auto_restart(canio_can_obj_t *self) { + if (self->auto_restart) { + common_hal_canio_can_restart(self); + } +} + +void common_hal_canio_can_send(canio_can_obj_t *self, mp_obj_t message_in) { + maybe_auto_restart(self); + + canio_bus_state_t state = common_hal_canio_can_state_get(self); + if (state == BUS_STATE_OFF) { + // Bus is off. Transmit failed. + mp_raise_OSError(MP_ENODEV); + } + + canio_message_obj_t *message = message_in; + + flexcan_frame_t tx_frame; + memset(&tx_frame, 0, sizeof(tx_frame)); // Zero out output. + + if (message->extended) { + tx_frame.id = FLEXCAN_ID_EXT(message->id); + tx_frame.format = kFLEXCAN_FrameFormatExtend; + } else { + tx_frame.id = FLEXCAN_ID_STD(message->id); + tx_frame.format = kFLEXCAN_FrameFormatStandard; + } + + if (message->base.type == &canio_remote_transmission_request_type) { + tx_frame.type = kFLEXCAN_FrameTypeRemote; + } else { + tx_frame.type = kFLEXCAN_FrameTypeData; + } + + tx_frame.length = message->size; + + // We can safely copy all bytes, as both flexcan_frame_t and + // canio_message_obj_t define the data array as 8 bytes long, + // even if the actual DLC is shorter. + tx_frame.dataByte0 = message->data[0]; + tx_frame.dataByte1 = message->data[1]; + tx_frame.dataByte2 = message->data[2]; + tx_frame.dataByte3 = message->data[3]; + tx_frame.dataByte4 = message->data[4]; + tx_frame.dataByte5 = message->data[5]; + tx_frame.dataByte6 = message->data[6]; + tx_frame.dataByte7 = message->data[7]; + + flexcan_mb_transfer_t tx_xfer; + tx_xfer.mbIdx = mimxrt10xx_flexcan_get_free_tx_mbid(self); + tx_xfer.frame = &tx_frame; + + // Setup tx message buffer. + FLEXCAN_SetTxMbConfig(self->data->base, tx_xfer.mbIdx, true); + + if (FLEXCAN_TransferSendNonBlocking(self->data->base, &self->data->handle, &tx_xfer) != kStatus_Success) { + mp_raise_OSError(MP_EIO); + } +} + +bool common_hal_canio_can_silent_get(canio_can_obj_t *self) { + return self->silent; +} + +bool common_hal_canio_can_deinited(canio_can_obj_t *self) { + return !self->data; +} + +void common_hal_canio_can_check_for_deinit(canio_can_obj_t *self) { + if (common_hal_canio_can_deinited(self)) { + raise_deinited_error(); + } +} + +void common_hal_canio_can_deinit(canio_can_obj_t *self) { + if (self->data) { + mimxrt10xx_flexcan_abort_tx_frames(self); + FLEXCAN_TransferAbortReceiveFifo(self->data->base, &self->data->handle); + + FLEXCAN_Deinit(self->data->base); + + // Free can data by doing nothing and letting gc take care of it. + // If the VM has finished already, this will be safe. + self->data = NULL; + } + + common_hal_reset_pin(self->rx_pin); + common_hal_reset_pin(self->tx_pin); + + self->rx_pin = NULL; + self->tx_pin = NULL; +} + +void common_hal_canio_reset(void) { + for (size_t i = 0; i < MP_ARRAY_SIZE(can_objs); i++) { + if (can_objs[i]) { + common_hal_canio_can_deinit(can_objs[i]); + can_objs[i] = NULL; + } + } +} diff --git a/ports/mimxrt10xx/common-hal/canio/CAN.h b/ports/mimxrt10xx/common-hal/canio/CAN.h new file mode 100644 index 0000000000000..11c77c9d4a4f5 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/CAN.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/canio/__init__.h" +#include "shared-bindings/canio/CAN.h" +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/canio/__init__.h" + +typedef struct canio_can_obj { + mp_obj_base_t base; + mimxrt10xx_flexcan_data_t *data; + int baudrate; + const mcu_pin_obj_t *rx_pin; + const mcu_pin_obj_t *tx_pin; + bool loopback : 1; + bool silent : 1; + bool auto_restart : 1; +} canio_can_obj_t; diff --git a/ports/mimxrt10xx/common-hal/canio/Listener.c b/ports/mimxrt10xx/common-hal/canio/Listener.c new file mode 100644 index 0000000000000..e635549983411 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/Listener.c @@ -0,0 +1,171 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// SPDX-FileCopyrightText: Copyright (c) 2025 SamantazFox +// +// SPDX-License-Identifier: MIT + + +#include +#include + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mperrno.h" + +#include "shared/runtime/interrupt_char.h" + +#include "common-hal/canio/__init__.h" +#include "common-hal/canio/Listener.h" +#include "shared-bindings/canio/Listener.h" +#include "shared-bindings/util.h" +#include "supervisor/shared/tick.h" +#include "sdk/drivers/flexcan/fsl_flexcan.h" + + +// Convert from back from FLEXCAN IDs to normal CAN IDs. +#define FLEXCAN_ID_TO_CAN_ID_STD(id) \ + ((uint32_t)((((uint32_t)(id)) & CAN_ID_STD_MASK) >> CAN_ID_STD_SHIFT)) + +#define FLEXCAN_ID_TO_CAN_ID_EXT(id) \ + ((uint32_t)((((uint32_t)(id)) & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK)) \ + >> CAN_ID_EXT_SHIFT)) + + +void common_hal_canio_listener_construct(canio_listener_obj_t *self, canio_can_obj_t *can, size_t nmatch, canio_match_obj_t **matches, float timeout) { + + common_hal_canio_listener_set_timeout(self, timeout); + + if (nmatch > MIMXRT10XX_FLEXCAN_RX_FILTER_COUNT) { + mp_raise_ValueError(MP_ERROR_TEXT("Filters too complex")); + } + + self->can = can; + + // Init configuration variables + flexcan_rx_fifo_config_t fifo_config; + fifo_config.idFilterNum = nmatch; + fifo_config.idFilterTable = self->can->data->rx_fifo_filter; + fifo_config.idFilterType = kFLEXCAN_RxFifoFilterTypeA; + fifo_config.priority = kFLEXCAN_RxFifoPrioHigh; + + if (nmatch == 0) { + // If the user has provided no matches, we need to set at least one + // filter that instructs the system to ignore all bits. + fifo_config.idFilterNum = 1; + self->can->data->rx_fifo_filter[0] = 0x0; + FLEXCAN_SetRxIndividualMask(self->can->data->base, 0, 0x0); + } else { + // Required to touch any CAN registers + FLEXCAN_EnterFreezeMode(self->can->data->base); + + for (size_t i = 0; i < nmatch; i++) { + if (matches[i]->extended) { + self->can->data->rx_fifo_filter[i] = FLEXCAN_RX_FIFO_EXT_FILTER_TYPE_A(matches[i]->id, 0, 1); + self->can->data->base->RXIMR[i] = FLEXCAN_RX_FIFO_EXT_MASK_TYPE_A(matches[i]->mask, 0, 1); + } else { + self->can->data->rx_fifo_filter[i] = FLEXCAN_RX_FIFO_STD_FILTER_TYPE_A(matches[i]->id, 0, 0); + self->can->data->base->RXIMR[i] = FLEXCAN_RX_FIFO_STD_MASK_TYPE_A(matches[i]->mask, 0, 0); + } + } + + // For consistency, even though FLEXCAN_SetRxFifoConfig() below will + // enter and exit freeze mode again anyway + FLEXCAN_ExitFreezeMode(self->can->data->base); + } + + FLEXCAN_SetRxFifoConfig(self->can->data->base, &fifo_config, true); +} + +void common_hal_canio_listener_set_timeout(canio_listener_obj_t *self, float timeout) { + self->timeout_ms = (int)MICROPY_FLOAT_C_FUN(ceil)(timeout * 1000); +} + +float common_hal_canio_listener_get_timeout(canio_listener_obj_t *self) { + return self->timeout_ms / 1000.0f; +} + +void common_hal_canio_listener_check_for_deinit(canio_listener_obj_t *self) { + if (!self->can) { + raise_deinited_error(); + } + common_hal_canio_can_check_for_deinit(self->can); +} + +int common_hal_canio_listener_in_waiting(canio_listener_obj_t *self) { + if (FLEXCAN_GetMbStatusFlags(self->can->data->base, kFLEXCAN_RxFifoFrameAvlFlag)) { + return 1; + } + return 0; +} + +mp_obj_t common_hal_canio_listener_receive(canio_listener_obj_t *self) { + if (!common_hal_canio_listener_in_waiting(self)) { + uint64_t deadline = supervisor_ticks_ms64() + self->timeout_ms; + do { + if (supervisor_ticks_ms64() > deadline) { + return NULL; + } + RUN_BACKGROUND_TASKS; + // Allow user to break out of a timeout with a KeyboardInterrupt. + if (mp_hal_is_interrupted()) { + return NULL; + } + } while (!common_hal_canio_listener_in_waiting(self)); + } + + flexcan_frame_t rx_frame; + if (FLEXCAN_ReadRxFifo(self->can->data->base, &rx_frame) != kStatus_Success) { + mp_raise_OSError(MP_EIO); + } + + // We've read from the FIFO, clear the "frame available" flag, which + // allows the CPU to serve the next FIFO entry + FLEXCAN_ClearMbStatusFlags(self->can->data->base, (uint32_t)kFLEXCAN_RxFifoFrameAvlFlag); + + const mp_obj_type_t *type; + if (rx_frame.type == kFLEXCAN_FrameTypeRemote) { + type = &canio_remote_transmission_request_type; + } else { + type = &canio_message_type; + } + canio_message_obj_t *message = mp_obj_malloc(canio_message_obj_t, type); + memset(message, 0, sizeof(canio_message_obj_t)); + + if (rx_frame.format == kFLEXCAN_FrameFormatExtend) { + message->extended = true; + message->id = rx_frame.id; + } else { + message->extended = false; + message->id = rx_frame.id >> 18; // standard ids are left-aligned + } + + + message->size = rx_frame.length; + + // We can safely copy all bytes, as both flexcan_frame_t and + // canio_message_obj_t define the data array as 8 bytes long. + message->data[0] = rx_frame.dataByte0; + message->data[1] = rx_frame.dataByte1; + message->data[2] = rx_frame.dataByte2; + message->data[3] = rx_frame.dataByte3; + message->data[4] = rx_frame.dataByte4; + message->data[5] = rx_frame.dataByte5; + message->data[6] = rx_frame.dataByte6; + message->data[7] = rx_frame.dataByte7; + + return message; +} + +void common_hal_canio_listener_deinit(canio_listener_obj_t *self) { + if (self->can) { + // Clear all filters. + flexcan_rx_fifo_config_t fifo_config; + fifo_config.idFilterNum = 0; + fifo_config.idFilterTable = self->can->data->rx_fifo_filter; + fifo_config.idFilterType = kFLEXCAN_RxFifoFilterTypeA; + fifo_config.priority = kFLEXCAN_RxFifoPrioHigh; + FLEXCAN_SetRxFifoConfig(self->can->data->base, &fifo_config, true); + } + self->can = NULL; +} diff --git a/ports/mimxrt10xx/common-hal/canio/Listener.h b/ports/mimxrt10xx/common-hal/canio/Listener.h new file mode 100644 index 0000000000000..2c1c1c82d50c5 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/Listener.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/canio/CAN.h" +#include "shared-module/canio/Match.h" + +typedef struct canio_listener_obj { + mp_obj_base_t base; + canio_can_obj_t *can; + uint32_t timeout_ms; +} canio_listener_obj_t; diff --git a/ports/mimxrt10xx/common-hal/canio/__init__.c b/ports/mimxrt10xx/common-hal/canio/__init__.c new file mode 100644 index 0000000000000..aaae9be4d4c77 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/__init__.c @@ -0,0 +1,8 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// SPDX-FileCopyrightText: Copyright (c) 2025 SamantazFox +// +// SPDX-License-Identifier: MIT + +#include "common-hal/canio/__init__.h" diff --git a/ports/mimxrt10xx/common-hal/canio/__init__.h b/ports/mimxrt10xx/common-hal/canio/__init__.h new file mode 100644 index 0000000000000..8f63b6c2f1174 --- /dev/null +++ b/ports/mimxrt10xx/common-hal/canio/__init__.h @@ -0,0 +1,54 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox +// SPDX-FileCopyrightText: Copyright (c) 2025 SamantazFox +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/canio/Message.h" +#include "sdk/drivers/flexcan/fsl_flexcan.h" + +// There are 64 message buffers in each mimxrt10xx chip. +// Rx fifo will use the message buffers at the front (from index zero). +// As far as I can see rx fifo uses message buffer 0 to 5. +// Also id filter table might occupy message buffer memory area 6 to 37. +// +// Let's use the last few message buffers for sending. +// +// We use 8 (tx) message buffers in total. +// This makes tracking the state (free/busy) of each (tx) message buffer easy. +// We can use a single byte, where each bit represent the state. +// Zero means the message buffer can be used for sending. +// One means the message buffer is busy sending. +// If you make this larger then you have to change the type of 'tx_state' in struct 'mimxrt10xx_flexcan_data_t'. +#define MIMXRT10XX_FLEXCAN_TX_MB_NUM (8) + +// For safety we use SDK provided macro to get the last message buffer index instead of hard coding it. +#define MIMXRT10XX_FLEXCAN_TX_MBID_MAX (FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(0)) +#define MIMXRT10XX_FLEXCAN_TX_MBID_MIN (MIMXRT10XX_FLEXCAN_TX_MBID_MAX - MIMXRT10XX_FLEXCAN_TX_MB_NUM) + +// Convert from tx message buffer index to frame array index. +#define MIMXRT10XX_FLEXCAN_TX_MBID_TO_ARRID(x) (x - MIMXRT10XX_FLEXCAN_TX_MBID_MIN) + +// Convert from frame array index to tx message buffer index. +#define MIMXRT10XX_FLEXCAN_TX_ARRID_TO_MBID(x) (x + MIMXRT10XX_FLEXCAN_TX_MBID_MIN) + +// We limit the amount of filter+mask pairs to 8 because above that the filters +// are impacted by the global mask rather than individual masks alone, which is +// not compatible with the current canio implementation. +// +// See Table 44-22 of the i.MX RT1060 Processor Reference Manual, Rev. 3 +// for more details. +#define MIMXRT10XX_FLEXCAN_RX_FILTER_COUNT (8) + +// Enables/disables SDK calculated "improved" timing configuration. +#define MIMXRT10XX_FLEXCAN_USE_IMPROVED_TIMING_CONFIG (1) + +typedef struct { + CAN_Type *base; // FlexCAN peripheral base address. + flexcan_handle_t handle; // FlexCAN handle which can be used for FlexCAN transactional APIs. + uint8_t tx_state; + uint32_t rx_fifo_filter[MIMXRT10XX_FLEXCAN_RX_FILTER_COUNT]; +} mimxrt10xx_flexcan_data_t; diff --git a/ports/mimxrt10xx/common-hal/os/__init__.c b/ports/mimxrt10xx/common-hal/os/__init__.c index 79ae228dc4240..ac168f2ed09b3 100644 --- a/ports/mimxrt10xx/common-hal/os/__init__.c +++ b/ports/mimxrt10xx/common-hal/os/__init__.c @@ -17,31 +17,6 @@ #include "sdk/drivers/trng/fsl_trng.h" #endif -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "mimxrt10xx"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "mimxrt10xx"); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { #if CIRCUITPY_RANDOM trng_config_t trngConfig; diff --git a/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c b/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c index c71f8b212e183..211b5c186f3fa 100644 --- a/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/mimxrt10xx/common-hal/rotaryio/IncrementalEncoder.c @@ -26,6 +26,9 @@ static void encoder_change(void *self_in) { void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + self->pin_a = pin_a; self->pin_b = pin_b; @@ -49,7 +52,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode } bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { - return !self->pin_a; + return self->pin_a == NULL; } void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self) { @@ -62,6 +65,9 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o common_hal_reset_pin(self->pin_a); common_hal_reset_pin(self->pin_b); + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->pin_a = NULL; - self->pin_b = NULL; } diff --git a/ports/mimxrt10xx/common-hal/usb_host/Port.c b/ports/mimxrt10xx/common-hal/usb_host/Port.c index 31af4ed582332..a7e73ab5b5c49 100644 --- a/ports/mimxrt10xx/common-hal/usb_host/Port.c +++ b/ports/mimxrt10xx/common-hal/usb_host/Port.c @@ -47,5 +47,8 @@ usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp, self->dp = dp; self->dm = dm; + claim_pin(dp); + claim_pin(dm); + return self; } diff --git a/ports/mimxrt10xx/mpconfigport.h b/ports/mimxrt10xx/mpconfigport.h index 4f9acd7a9fd30..df634dc73282e 100644 --- a/ports/mimxrt10xx/mpconfigport.h +++ b/ports/mimxrt10xx/mpconfigport.h @@ -17,10 +17,6 @@ extern uint8_t _ld_filesystem_end; extern uint8_t _ld_default_stack_size; #define CIRCUITPY_DEFAULT_STACK_SIZE ((uint32_t)&_ld_default_stack_size) -#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (0) -#define MICROPY_PY_FUNCTION_ATTRS (0) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) - #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR ((uint32_t)&_ld_filesystem_start) #define CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE ((uint32_t)(&_ld_filesystem_end - &_ld_filesystem_start)) @@ -29,6 +25,8 @@ extern uint8_t _ld_default_stack_size; // are aligned to cache lines. #define MICROPY_BYTES_PER_GC_BLOCK (32) +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED (1) + #include "py/circuitpy_mpconfig.h" // TODO: diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk index 20d802eb3548e..b3f078c7ecf98 100644 --- a/ports/mimxrt10xx/mpconfigport.mk +++ b/ports/mimxrt10xx/mpconfigport.mk @@ -2,8 +2,6 @@ LD_FILE = $(FLASH).ld $(CHIP_FAMILY).ld imxrt10xx.ld INTERNAL_LIBM = 1 -USB_HIGHSPEED = 1 - # Number of USB endpoint pairs. USB_NUM_ENDPOINT_PAIRS = 8 # Align buffers on the cache boundary so we don't inadvertently load them early. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/pin_names.h index 1d6a9cafaf841..3cf071f62caa9 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1011/pin_names.h @@ -6,8 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once - +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1015/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1015/pin_names.h index ee8b47b61afe9..a0bb59e547957 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1015/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1015/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/pin_names.h index 1218cd8ed8db6..45203c59968a8 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1021/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/pin_names.h index 42f03e02f9119..8a98f4560a6c5 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1042/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/pin_names.h index 5483206f94f37..41d2d67f81adb 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1052/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/clocks.c b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/clocks.c index 9385c9cc4c712..86ae09f7ca028 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/clocks.c +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/clocks.c @@ -167,9 +167,9 @@ void clocks_init(void) { CLOCK_DisableClock(kCLOCK_Can2S); CLOCK_DisableClock(kCLOCK_Can3S); /* Set CAN_CLK_PODF. */ - CLOCK_SetDiv(kCLOCK_CanDiv, 1); + CLOCK_SetDiv(kCLOCK_CanDiv, 2); // Clock divider for master flexcan clock source /* Set Can clock source. */ - CLOCK_SetMux(kCLOCK_CanMux, 2); + CLOCK_SetMux(kCLOCK_CanMux, 0); // Select 60M clock divided by USB1 PLL (480 MHz) as master flexcan clock source /* Disable UART clock gate. */ CLOCK_DisableClock(kCLOCK_Lpuart1); CLOCK_DisableClock(kCLOCK_Lpuart2); diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.c b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.c index 4d5e909bede07..cc19dc137b6a5 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.c +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.c @@ -276,6 +276,40 @@ const mcu_periph_obj_t mcu_mqs_right_list[3] = { PERIPH_PIN(3, 2, 0, 0, &pin_GPIO_B0_00), }; +CAN_Type *const mcu_can_banks[3] = { CAN1, CAN2, CAN3 }; + +const mcu_periph_obj_t mcu_can_rx_list[11] = { + PERIPH_PIN(1, 4, kIOMUXC_FLEXCAN1_RX_SELECT_INPUT, 0, &pin_GPIO_SD_B1_03), + PERIPH_PIN(1, 3, kIOMUXC_FLEXCAN1_RX_SELECT_INPUT, 1, &pin_GPIO_EMC_18), + PERIPH_PIN(1, 2, kIOMUXC_FLEXCAN1_RX_SELECT_INPUT, 2, &pin_GPIO_AD_B1_09), + PERIPH_PIN(1, 2, kIOMUXC_FLEXCAN1_RX_SELECT_INPUT, 3, &pin_GPIO_B0_03), + + PERIPH_PIN(2, 3, kIOMUXC_FLEXCAN2_RX_SELECT_INPUT, 0, &pin_GPIO_EMC_10), + PERIPH_PIN(2, 0, kIOMUXC_FLEXCAN2_RX_SELECT_INPUT, 1, &pin_GPIO_AD_B0_03), + PERIPH_PIN(2, 6, kIOMUXC_FLEXCAN2_RX_SELECT_INPUT, 2, &pin_GPIO_AD_B0_15), + PERIPH_PIN(2, 6, kIOMUXC_FLEXCAN2_RX_SELECT_INPUT, 3, &pin_GPIO_B1_09), + + PERIPH_PIN(3, 9, 0, 0, &pin_GPIO_EMC_37), + PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_AD_B0_11), + PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_AD_B0_15), +}; + +const mcu_periph_obj_t mcu_can_tx_list[11] = { + PERIPH_PIN(1, 3, 0, 0, &pin_GPIO_EMC_17), + PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_AD_B1_08), + PERIPH_PIN(1, 2, 0, 0, &pin_GPIO_B0_02), + PERIPH_PIN(1, 4, 0, 0, &pin_GPIO_SD_B1_02), + + PERIPH_PIN(2, 3, 0, 0, &pin_GPIO_EMC_09), + PERIPH_PIN(2, 0, 0, 0, &pin_GPIO_AD_B0_02), + PERIPH_PIN(2, 6, 0, 0, &pin_GPIO_AD_B0_14), + PERIPH_PIN(2, 6, 0, 0, &pin_GPIO_B1_08), + + PERIPH_PIN(3, 9, 0, 0, &pin_GPIO_EMC_36), + PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_AD_B0_10), + PERIPH_PIN(3, 8, 0, 0, &pin_GPIO_AD_B0_14), +}; + const mcu_pwm_obj_t mcu_pwm_list[67] = { PWM_PIN(PWM1, kPWM_Module_0, kPWM_PwmA, IOMUXC_GPIO_EMC_23_FLEXPWM1_PWMA00, &pin_GPIO_EMC_23), PWM_PIN(PWM1, kPWM_Module_0, kPWM_PwmA, IOMUXC_GPIO_SD_B0_00_FLEXPWM1_PWMA00, &pin_GPIO_SD_B0_00), diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h index ab1355ae55a51..9c41e563c4827 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/periph.h @@ -41,4 +41,8 @@ extern const mcu_periph_obj_t mcu_i2s_mclk_list[7]; extern const mcu_periph_obj_t mcu_mqs_left_list[3]; extern const mcu_periph_obj_t mcu_mqs_right_list[3]; +extern CAN_Type *const mcu_can_banks[3]; +extern const mcu_periph_obj_t mcu_can_rx_list[11]; +extern const mcu_periph_obj_t mcu_can_tx_list[11]; + extern const mcu_pwm_obj_t mcu_pwm_list[67]; diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/pin_names.h index 5483206f94f37..41d2d67f81adb 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1062/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1176/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1176/pin_names.h index ec23d603de7d0..b5a5b86b4ddf8 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1176/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/MIMXRT1176/pin_names.h @@ -6,7 +6,7 @@ // // SPDX-License-Identifier: MIT -#pragma once +// OK to include more than once because FORMAT_PIN may be different. // define FORMAT_PIN(pin_name) and then include this file. diff --git a/ports/mimxrt10xx/peripherals/mimxrt10xx/pin_names.h b/ports/mimxrt10xx/peripherals/mimxrt10xx/pin_names.h index 22fa6c572964e..ffaa74edc3887 100644 --- a/ports/mimxrt10xx/peripherals/mimxrt10xx/pin_names.h +++ b/ports/mimxrt10xx/peripherals/mimxrt10xx/pin_names.h @@ -5,8 +5,6 @@ // // SPDX-License-Identifier: MIT -#pragma once - // OK to include more than once because FORMAT_PIN may be different. #ifdef MIMXRT1011_SERIES diff --git a/ports/mimxrt10xx/reset.h b/ports/mimxrt10xx/reset.h index 04c951221e9e5..cae838556bce3 100644 --- a/ports/mimxrt10xx/reset.h +++ b/ports/mimxrt10xx/reset.h @@ -16,6 +16,6 @@ #define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set #define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef -void reset_to_bootloader(void) NORETURN; -void reset(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; +void reset(void) MP_NORETURN; bool bootloader_available(void); diff --git a/ports/mimxrt10xx/supervisor/cpu.S b/ports/mimxrt10xx/supervisor/cpu.S deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/mimxrt10xx/supervisor/cpu.S +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c b/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c index 3ccd67096a7df..1c7559292706f 100644 --- a/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c +++ b/ports/mimxrt10xx/supervisor/flexspi_nor_flash_ops.c @@ -13,9 +13,9 @@ #include "supervisor/internal_flash.h" #include "supervisor/linker.h" -STATIC uint8_t _busy_bit_shift; -STATIC bool _busy_bit_polarity; -STATIC bool _inited = false; +static uint8_t _busy_bit_shift; +static bool _busy_bit_polarity; +static bool _inited = false; void flexspi_nor_init(void) { // Copy busy bit info into RAM so we can use if when flash isn't available. @@ -24,7 +24,7 @@ void flexspi_nor_init(void) { _inited = true; } -STATIC status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type * base, uint32_t baseAddr) +static status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type * base, uint32_t baseAddr) { flexspi_transfer_t flashXfer; status_t status; @@ -41,7 +41,7 @@ STATIC status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type * base, uin return status; } -STATIC status_t PLACE_IN_ITCM(flexspi_nor_wait_bus_busy)(FLEXSPI_Type * base) +static status_t PLACE_IN_ITCM(flexspi_nor_wait_bus_busy)(FLEXSPI_Type * base) { /* Wait status ready. */ bool isBusy; diff --git a/ports/mimxrt10xx/supervisor/port.c b/ports/mimxrt10xx/supervisor/port.c index fe7ee14a3b7ac..62d2569cfde4f 100644 --- a/ports/mimxrt10xx/supervisor/port.c +++ b/ports/mimxrt10xx/supervisor/port.c @@ -22,7 +22,6 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/rtc/RTC.h" -#include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "shared-bindings/microcontroller/__init__.h" @@ -426,11 +425,6 @@ safe_mode_t port_init(void) { } void reset_port(void) { - #if CIRCUITPY_BUSIO - i2c_reset(); - spi_reset(); - #endif - #if CIRCUITPY_AUDIOIO audio_dma_reset(); #endif @@ -452,8 +446,6 @@ void reset_port(void) { #endif // reset_event_system(); - - reset_all_pins(); } void reset_to_bootloader(void) { diff --git a/ports/mimxrt10xx/tools/gen_peripherals_data.py b/ports/mimxrt10xx/tools/gen_peripherals_data.py index e255ed844a5e2..e9ceeb63f2d90 100644 --- a/ports/mimxrt10xx/tools/gen_peripherals_data.py +++ b/ports/mimxrt10xx/tools/gen_peripherals_data.py @@ -1,4 +1,5 @@ import sys +import re import pathlib import xml.etree.ElementTree as ET @@ -8,6 +9,7 @@ "LPUART": ["RX", "TX", "RTS", "CTS"], "I2S": ["RX_DATA0", "RX_SYNC", "TX_BCLK", "TX_DATA0", "TX_SYNC", "MCLK"], "MQS": ["LEFT", "RIGHT"], + "CAN": ["RX", "TX"], } SIGNAL_RENAME = { @@ -21,6 +23,23 @@ "RX_DATA": "RX_DATA0", } +INSTANCE_RENAME = {"FLEXCAN": "CAN"} + +INSTANCE_RE = re.compile("([a-zA-Z0-9]+?)([0-9]+)$") + + +def rename_instance(instance: str) -> str: + instance_match = INSTANCE_RE.match(instance) + if instance_match is None: + return instance + instance_res = instance_match.groups() + if len(instance_res) < 2: + return instance + instance_name = str(instance_res[0]) + instance_id = str(instance_res[1]) + return INSTANCE_RENAME.get(instance_name, instance_name) + instance_id + + SKIP_LPSR = True svd_folder = pathlib.Path(sys.argv[1]) @@ -37,6 +56,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries // SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec // SPDX-FileCopyrightText: Copyright (c) 2023 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2023 qutefox // // SPDX-License-Identifier: MIT """ @@ -54,6 +74,7 @@ print(device) autogen_warning = autogen_warning_template.format(device) svd_fn = svd_folder / device / (device + ".xml") + if not svd_fn.exists(): svd_fn = svd_folder / device / (device + "_cm7.xml") @@ -144,8 +165,10 @@ if name.endswith("SELECT_INPUT"): name_split = name.split("_") instance = name_split[0] + instance = rename_instance(instance) signal = "_".join(name_split[1:-2]) signal = SIGNAL_RENAME.get(signal, signal) + if instance not in peripheral_inputs: peripheral_inputs[instance] = {} if signal not in peripheral_inputs[instance]: @@ -232,6 +255,7 @@ print("skipping", pin_name, connection) continue instance, signal = connection.split("_", maxsplit=1) + instance = rename_instance(instance) signal = SIGNAL_RENAME.get(signal, signal) if instance not in peripheral_inputs: peripheral_inputs[instance] = {} @@ -264,7 +288,7 @@ pins_h.append("// Pads can be reset. Other pins like USB cannot be.") pins_h.append(f"#define PAD_COUNT ({pin_number})") pins_h.append(f"#define PIN_COUNT (PAD_COUNT + {len(usb_pins)})") - pins_h.append(f"extern const mcu_pin_obj_t mcu_pin_list[PIN_COUNT];") + pins_h.append("extern const mcu_pin_obj_t mcu_pin_list[PIN_COUNT];") pins_h.append("") out_dir.mkdir(exist_ok=True) @@ -283,11 +307,12 @@ "", ] - for ptype in SIGNALS: + for ptype, signals in SIGNALS: instances = all_peripherals[ptype] short_name = ptype.lower() if short_name.startswith("lp"): short_name = short_name[2:] + # Only one MQS exists and it is related to SAI3 if ptype != "MQS": periph_h.append( @@ -298,7 +323,7 @@ f"{ptype}_Type *const mcu_{short_name}_banks[{len(instances)}] = {{ {joined_instances} }};" ) periph_c.append("") - for signal in SIGNALS[ptype]: + for signal in signals: pin_count = 0 for instance in instances: if instance not in peripheral_inputs or signal not in peripheral_inputs[instance]: @@ -332,8 +357,8 @@ periph_c.append( f" PERIPH_PIN({instance_number}, {alt}, {select_input}, {input_value}, &pin_{pin_name})," ) - periph_c.append(f"}};") - periph_c.append(f"") + periph_c.append("};") + periph_c.append("") periph_h.append("") pwm_outputs.sort(key=lambda x: x[:3]) @@ -348,7 +373,7 @@ periph_c.append( f" PWM_PIN(PWM{pwm_instance}, kPWM_Module_{module}, kPWM_Pwm{channel}, IOMUXC_{pin_name}_{connection}, &pin_{pin_name})," ) - periph_c.append(f"}};") + periph_c.append("};") periph_c.append("") periph_h.append("") diff --git a/ports/nordic/Makefile b/ports/nordic/Makefile index 85acb9d8b4e08..1e283fc699c7f 100755 --- a/ports/nordic/Makefile +++ b/ports/nordic/Makefile @@ -36,8 +36,8 @@ ifeq ($(DEBUG), 1) CFLAGS += -ggdb3 OPTIMIZATION_FLAGS = -Og else - OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions - CFLAGS += -DNDEBUG -ggdb3 + OPTIMIZATION_FLAGS ?= -O2 + CFLAGS += -DNDEBUG endif ifeq ($(NRF_DEBUG_PRINT), 1) @@ -47,7 +47,7 @@ endif # option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk CFLAGS += $(OPTIMIZATION_FLAGS) -CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes +CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) -Werror=missing-prototypes -Werror=old-style-definition # Nordic Softdevice SDK header files contains inline assembler that has # broken constraints. As a result the IPA-modref pass, introduced in gcc-11, @@ -146,20 +146,9 @@ SRC_C += $(SRC_DCD) $(patsubst %.c,$(BUILD)/%.o,$(SRC_DCD)): CFLAGS += -Wno-missing-prototypes endif # CIRCUITPY_USB_DEVICE -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) +SRC_S = shared/runtime/gchelper_thumb2.s -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-module/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) - -SRC_S = supervisor/cpu.s +SRC_C += shared/runtime/gchelper_native.c OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_NRFX:.c=.o)) @@ -180,7 +169,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/nordic/boards/TG-Watch/mpconfigboard.h b/ports/nordic/boards/TG-Watch/mpconfigboard.h index 8ebb88f6f86b5..4016b1ea84cf9 100644 --- a/ports/nordic/boards/TG-Watch/mpconfigboard.h +++ b/ports/nordic/boards/TG-Watch/mpconfigboard.h @@ -13,7 +13,7 @@ #define MICROPY_HW_MCU_NAME "nRF52840" // TG-Gui requires a deeper call stack than normal CircuitPython, this is intentional overkill -#define CIRCUITPY_PYSTACK_SIZE 8192 // 1536 is the normal size, (32 bytes/frame * 48 frames) +#define CIRCUITPY_PYSTACK_SIZE 8192 // the board has a 32mhz crystal but NOT a 32khz one #define BOARD_HAS_32KHZ_XTAL 0 diff --git a/ports/nordic/boards/bluemicro833/mpconfigboard.mk b/ports/nordic/boards/bluemicro833/mpconfigboard.mk index de12d6ee1fee3..3fcb7cdbb07ac 100644 --- a/ports/nordic/boards/bluemicro833/mpconfigboard.mk +++ b/ports/nordic/boards/bluemicro833/mpconfigboard.mk @@ -7,10 +7,12 @@ MCU_CHIP = nrf52833 INTERNAL_FLASH_FILESYSTEM = 1 +CIRCUITPY_AESIO = 0 CIRCUITPY_AUDIOBUSIO = 0 CIRCUITPY_AUDIOPWMIO = 0 CIRCUITPY_AUDIOMIXER = 0 CIRCUITPY_KEYPAD = 1 +CIRCUITPY_KEYPAD_DEMUX = 0 CIRCUITPY_NVM = 0 CIRCUITPY_ONEWIREIO = 0 CIRCUITPY_PIXELBUF = 1 diff --git a/ports/nordic/boards/circuitplayground_bluefruit/mpconfigboard.h b/ports/nordic/boards/circuitplayground_bluefruit/mpconfigboard.h index 91cf68095d27d..d63a9ccd5d8d5 100644 --- a/ports/nordic/boards/circuitplayground_bluefruit/mpconfigboard.h +++ b/ports/nordic/boards/circuitplayground_bluefruit/mpconfigboard.h @@ -50,3 +50,7 @@ #define DEFAULT_UART_BUS_TX (&pin_P0_14) #define SPEAKER_ENABLE_PIN (&pin_P1_04) + +// Uncomment to allow debugging over console UART +// #define CIRCUITPY_CONSOLE_UART_TX (&pin_P0_14) +// #define CIRCUITPY_CONSOLE_UART_RX (&pin_P0_30) diff --git a/ports/nordic/boards/clue_nrf52840_express/board.c b/ports/nordic/boards/clue_nrf52840_express/board.c index e2cd8a324bab7..0b331b63a9612 100644 --- a/ports/nordic/boards/clue_nrf52840_express/board.c +++ b/ports/nordic/boards/clue_nrf52840_express/board.c @@ -34,9 +34,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_P0_13, // TFT_DC Command or data - &pin_P0_12, // TFT_CS Chip select - &pin_P1_03, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_P0_13), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_P0_12), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_P1_03), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/nordic/boards/electronut_labs_blip/mpconfigboard.mk b/ports/nordic/boards/electronut_labs_blip/mpconfigboard.mk index 0e3b1b9048950..fc59a101e454f 100644 --- a/ports/nordic/boards/electronut_labs_blip/mpconfigboard.mk +++ b/ports/nordic/boards/electronut_labs_blip/mpconfigboard.mk @@ -11,3 +11,4 @@ INTERNAL_FLASH_FILESYSTEM = 1 CIRCUITPY_AUDIOIO = 0 CIRCUITPY_DISPLAYIO = 1 CIRCUITPY_STAGE = 1 +CIRCUITPY_DIGITALINOUT_PROTOCOL = 0 diff --git a/ports/nordic/boards/hiibot_bluefi/board.c b/ports/nordic/boards/hiibot_bluefi/board.c index 73430d675eb2d..7a681140ddbc4 100644 --- a/ports/nordic/boards/hiibot_bluefi/board.c +++ b/ports/nordic/boards/hiibot_bluefi/board.c @@ -34,9 +34,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_P0_27, // TFT_DC Command or data - &pin_P0_05, // TFT_CS Chip select - NULL, // no TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_P0_27), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_P0_05), // TFT_CS Chip select + MP_OBJ_NULL, // no TFT_RST Reset // &pin_P1_14, // TFT_RST Reset 60000000, // Baudrate 0, // Polarity diff --git a/ports/nordic/boards/makerdiary_nrf52840_m2_devkit/board.c b/ports/nordic/boards/makerdiary_nrf52840_m2_devkit/board.c index 64199b98009f0..4f9c051478ac3 100644 --- a/ports/nordic/boards/makerdiary_nrf52840_m2_devkit/board.c +++ b/ports/nordic/boards/makerdiary_nrf52840_m2_devkit/board.c @@ -35,9 +35,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_P0_08, // TFT_DC Command or data - &pin_P0_06, // TFT_CS Chip select - &pin_P1_09, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_P0_08), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_P0_06), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_P1_09), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/nordic/boards/ohs2020_badge/board.c b/ports/nordic/boards/ohs2020_badge/board.c index ea716006cb4bf..d16d99473f014 100644 --- a/ports/nordic/boards/ohs2020_badge/board.c +++ b/ports/nordic/boards/ohs2020_badge/board.c @@ -34,9 +34,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_P0_08, // TFT_DC Command or data - &pin_P0_14, // TFT_CS Chip select - &pin_P0_13, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_P0_08), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_P0_14), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_P0_13), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/nordic/boards/omnimo_nrf52840/board.c b/ports/nordic/boards/omnimo_nrf52840/board.c new file mode 100644 index 0000000000000..b44a1ae51e04b --- /dev/null +++ b/ports/nordic/boards/omnimo_nrf52840/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.h b/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.h new file mode 100644 index 0000000000000..301df3ff9f46b --- /dev/null +++ b/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.h @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "nrfx/hal/nrf_gpio.h" + +#define MICROPY_HW_BOARD_NAME "OMNIMO nRF52840" +#define MICROPY_HW_MCU_NAME "nRF52840" + +#define MICROPY_HW_NEOPIXEL (&pin_P0_16) + +#define CIRCUITPY_STATUS_LED_POWER (&pin_P1_10) + + +#define MICROPY_HW_LED_STATUS (&pin_P1_15) + +#if QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20) +#endif + +#if SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_17 +#define SPI_FLASH_MISO_PIN &pin_P0_22 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_20 +#endif + +#define BOARD_HAS_CRYSTAL 1 + +#define DEFAULT_I2C_BUS_SCL (&pin_P0_11) +#define DEFAULT_I2C_BUS_SDA (&pin_P0_12) + +#define DEFAULT_SPI_BUS_SCK (&pin_P0_14) +#define DEFAULT_SPI_BUS_MOSI (&pin_P0_13) +#define DEFAULT_SPI_BUS_MISO (&pin_P0_15) + +#define DEFAULT_UART_BUS_RX (&pin_P0_24) +#define DEFAULT_UART_BUS_TX (&pin_P0_25) diff --git a/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.mk b/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.mk new file mode 100644 index 0000000000000..e73be61d7282e --- /dev/null +++ b/ports/nordic/boards/omnimo_nrf52840/mpconfigboard.mk @@ -0,0 +1,9 @@ +USB_VID = 0x1209 +USB_PID = 0xCECE +USB_PRODUCT = "OMNIMO nRF52840" +USB_MANUFACTURER = "eAFAQ" + +MCU_CHIP = nrf52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q16C, W25Q16JVxQ" diff --git a/ports/nordic/boards/omnimo_nrf52840/pins.c b/ports/nordic/boards/omnimo_nrf52840/pins.c new file mode 100644 index 0000000000000..8016037a0aef4 --- /dev/null +++ b/ports/nordic/boards/omnimo_nrf52840/pins.c @@ -0,0 +1,115 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) }, // Feather + { MP_ROM_QSTR(MP_QSTR_PMOD4), MP_ROM_PTR(&pin_P0_04) }, // PMOD + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) }, // Feather + { MP_ROM_QSTR(MP_QSTR_PMOD3), MP_ROM_PTR(&pin_P0_05) }, // PMOD + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_30) }, // Feather + { MP_ROM_QSTR(MP_QSTR_PMOD2), MP_ROM_PTR(&pin_P0_30) }, // PMOD + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_28) }, // Feather + { MP_ROM_QSTR(MP_QSTR_PMOD1), MP_ROM_PTR(&pin_P0_28) }, // PMOD + + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) }, // Feather + + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) }, // Feather + + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_P0_29) }, + { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_P0_29) }, + + { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) }, + { MP_ROM_QSTR(MP_QSTR_BTN1), MP_ROM_PTR(&pin_P1_02) }, + + { MP_ROM_QSTR(MP_QSTR_BTN2), MP_ROM_PTR(&pin_P1_07) }, + + { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) }, + { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P1_09) }, // Feather + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_08) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_TX), MP_ROM_PTR(&pin_P1_08) }, // mikroBUS + + + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_07) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_RX), MP_ROM_PTR(&pin_P0_07) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_26) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_INT), MP_ROM_PTR(&pin_P0_26) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_27) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_PWM), MP_ROM_PTR(&pin_P0_27) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P1_14) }, // Feather + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P1_13) }, // Feather + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_12) }, // Feather + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_16) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_14) }, // Feather + + { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_P0_31) }, + { MP_ROM_QSTR(MP_QSTR_mikroBUS_AN), MP_ROM_PTR(&pin_P0_31) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_13) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_RST), MP_ROM_PTR(&pin_P0_13) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_15) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_CS), MP_ROM_PTR(&pin_P0_15) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_25) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_MISO), MP_ROM_PTR(&pin_P0_25) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_SCK), MP_ROM_PTR(&pin_P0_24) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_11) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_SCL), MP_ROM_PTR(&pin_P0_11) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_12) }, // Feather + { MP_ROM_QSTR(MP_QSTR_mikroBUS_SDA), MP_ROM_PTR(&pin_P0_12) }, // mikroBUS + + { MP_ROM_QSTR(MP_QSTR_PMOD5), MP_ROM_PTR(&pin_P1_11) }, // PMOD + { MP_ROM_QSTR(MP_QSTR_PMOD6), MP_ROM_PTR(&pin_P1_01) }, // PMOD + { MP_ROM_QSTR(MP_QSTR_PMOD7), MP_ROM_PTR(&pin_P1_03) }, // PMOD + { MP_ROM_QSTR(MP_QSTR_PMOD8), MP_ROM_PTR(&pin_P1_05) }, // PMOD + + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_10) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_10) }, + + { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_P1_15) }, + { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_15) }, + + { MP_ROM_QSTR(MP_QSTR_QWIIC_SCL), MP_ROM_PTR(&pin_P0_06) }, + + { MP_ROM_QSTR(MP_QSTR_QWIIC_SDA), MP_ROM_PTR(&pin_P0_08) }, + + { MP_ROM_QSTR(MP_QSTR_VOUTEN), MP_ROM_PTR(&pin_P1_04) }, + + { MP_ROM_QSTR(MP_QSTR_D43), MP_ROM_PTR(&pin_P1_06) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + /// For Qwiic + { MP_ROM_QSTR(MP_QSTR_QWIIC), MP_ROM_PTR(&board_i2c_obj) }, + +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/nordic/boards/particle_boron/mpconfigboard.mk b/ports/nordic/boards/particle_boron/mpconfigboard.mk index 26fe7b83db604..e0ee123c99a90 100644 --- a/ports/nordic/boards/particle_boron/mpconfigboard.mk +++ b/ports/nordic/boards/particle_boron/mpconfigboard.mk @@ -6,4 +6,4 @@ USB_MANUFACTURER = "Particle" MCU_CHIP = nrf52840 QSPI_FLASH_FILESYSTEM = 1 -EXTERNAL_FLASH_DEVICES = "MX25L3233F" +EXTERNAL_FLASH_DEVICES = "MX25L3233F,MX25R6435F" diff --git a/ports/nordic/common-hal/_bleio/Adapter.c b/ports/nordic/common-hal/_bleio/Adapter.c index b252cc49e58e2..2ca9df897107e 100644 --- a/ports/nordic/common-hal/_bleio/Adapter.c +++ b/ports/nordic/common-hal/_bleio/Adapter.c @@ -32,9 +32,8 @@ #include "supervisor/usb.h" #endif -#if CIRCUITPY_OS_GETENV -#include "shared-bindings/os/__init__.h" -#include "shared-module/os/__init__.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" #endif #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) @@ -324,11 +323,11 @@ static void bleio_adapter_reset_name(bleio_adapter_obj_t *self) { default_ble_name[len - 1] = nibble_to_hex_lower[addr.addr[0] & 0xf]; default_ble_name[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML char ble_name[32]; - os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); - if (result == GETENV_OK) { + settings_err_t result = settings_get_str("CIRCUITPY_BLE_NAME", ble_name, sizeof(ble_name)); + if (result == SETTINGS_OK) { common_hal_bleio_adapter_set_name(self, ble_name); return; } @@ -524,7 +523,7 @@ mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t } self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); size_t max_packet_size = extended ? BLE_GAP_SCAN_BUFFER_EXTENDED_MAX_SUPPORTED : BLE_GAP_SCAN_BUFFER_MAX; - uint8_t *raw_data = m_malloc(sizeof(ble_data_t) + max_packet_size); + uint8_t *raw_data = m_malloc_without_collect(sizeof(ble_data_t) + max_packet_size); ble_data_t *sd_data = (ble_data_t *)raw_data; self->scan_results->common_hal_data = sd_data; sd_data->len = max_packet_size; diff --git a/ports/nordic/common-hal/_bleio/Attribute.h b/ports/nordic/common-hal/_bleio/Attribute.h index 5fa6b4d637767..9a58e16bb862e 100644 --- a/ports/nordic/common-hal/_bleio/Attribute.h +++ b/ports/nordic/common-hal/_bleio/Attribute.h @@ -6,6 +6,15 @@ #pragma once +#include + +#include "py/obj.h" + #include "shared-module/_bleio/Attribute.h" extern void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode); + +size_t bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); +void bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); +size_t bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); +void bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); diff --git a/ports/nordic/common-hal/_bleio/Characteristic.c b/ports/nordic/common-hal/_bleio/Characteristic.c index f3238f2fd5015..2e6042e48e7fb 100644 --- a/ports/nordic/common-hal/_bleio/Characteristic.c +++ b/ports/nordic/common-hal/_bleio/Characteristic.c @@ -80,8 +80,8 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, // to allocate. self->initial_value_len = initial_value_bufinfo->len; if (gc_alloc_possible()) { - if (gc_nbytes(initial_value_bufinfo->buf) > 0) { - uint8_t *initial_value = m_malloc(self->initial_value_len); + if (gc_ptr_on_heap(initial_value_bufinfo->buf)) { + uint8_t *initial_value = m_malloc_without_collect(self->initial_value_len); memcpy(initial_value, initial_value_bufinfo->buf, self->initial_value_len); self->initial_value = initial_value; } else { @@ -109,6 +109,19 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->handle == BLE_GATT_HANDLE_INVALID; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + return; + } + self->handle = BLE_GATT_HANDLE_INVALID; + // TODO: Can we remove this from the soft device? Right now we assume the + // reset clears things. +} + mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { if (self->descriptor_list == NULL) { return mp_const_empty_tuple; @@ -125,10 +138,10 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); if (common_hal_bleio_service_get_is_remote(self->service)) { - return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); + return bleio_gattc_read(self->handle, conn_handle, buf, len); } else { // conn_handle is ignored for non-system attributes. - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + return bleio_gatts_read(self->handle, conn_handle, buf, len); } } @@ -146,7 +159,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, if (common_hal_bleio_service_get_is_remote(self->service)) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); // Last argument is true if write-no-reponse desired. - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, + bleio_gattc_write(self->handle, conn_handle, bufinfo, (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); } else { // Validate data length for local characteristics only. @@ -159,7 +172,7 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, // Always write the value locally even if no connections are active. // conn_handle is ignored for non-system attributes, so we use BLE_CONN_HANDLE_INVALID. - common_hal_bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); + bleio_gatts_write(self->handle, BLE_CONN_HANDLE_INVALID, bufinfo); // Check to see if we need to notify or indicate any active connections. for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { bleio_connection_internal_t *connection = &bleio_connections[i]; @@ -242,7 +255,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, } const uint16_t conn_handle = bleio_connection_get_conn_handle(self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); uint16_t cccd_value = (notify ? BLE_GATT_HVX_NOTIFICATION : 0) | diff --git a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c index 4374907adf4e8..6d1b9b550efc1 100644 --- a/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/nordic/common-hal/_bleio/CharacteristicBuffer.c @@ -29,6 +29,7 @@ static void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *d for (uint16_t i = 0; i < len; i++) { if (data[i] == mp_interrupt_char) { mp_sched_keyboard_interrupt(); + ringbuf_clear(&self->ringbuf); } else { ringbuf_put(&self->ringbuf, data[i]); } @@ -96,7 +97,7 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe bleio_characteristic_obj_t *characteristic, mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, buffer, buffer_size, NULL, false); } diff --git a/ports/nordic/common-hal/_bleio/Connection.h b/ports/nordic/common-hal/_bleio/Connection.h index 110677dc78b41..ea1edf1760311 100644 --- a/ports/nordic/common-hal/_bleio/Connection.h +++ b/ports/nordic/common-hal/_bleio/Connection.h @@ -65,6 +65,7 @@ typedef struct { void bleio_connection_clear(bleio_connection_internal_t *self); bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); bleio_connection_internal_t *bleio_conn_handle_to_connection(uint16_t conn_handle); diff --git a/ports/nordic/common-hal/_bleio/Descriptor.c b/ports/nordic/common-hal/_bleio/Descriptor.c index 959c8e5c9c0c0..0d27ca5dc2edf 100644 --- a/ports/nordic/common-hal/_bleio/Descriptor.c +++ b/ports/nordic/common-hal/_bleio/Descriptor.c @@ -43,9 +43,9 @@ size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8 if (self->handle != BLE_GATT_HANDLE_INVALID) { uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - return common_hal_bleio_gattc_read(self->handle, conn_handle, buf, len); + return bleio_gattc_read(self->handle, conn_handle, buf, len); } else { - return common_hal_bleio_gatts_read(self->handle, conn_handle, buf, len); + return bleio_gatts_read(self->handle, conn_handle, buf, len); } } @@ -58,7 +58,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff uint16_t conn_handle = bleio_connection_get_conn_handle(self->characteristic->service->connection); if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { // false means WRITE_REQ, not write-no-response - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); + bleio_gattc_write(self->handle, conn_handle, bufinfo, false); } else { // Validate data length for local descriptors only. if (self->fixed_length && bufinfo->len != self->max_length) { @@ -68,7 +68,7 @@ void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buff mp_raise_ValueError(MP_ERROR_TEXT("Value length > max_length")); } - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + bleio_gatts_write(self->handle, conn_handle, bufinfo); } } diff --git a/ports/nordic/common-hal/_bleio/PacketBuffer.c b/ports/nordic/common-hal/_bleio/PacketBuffer.c index f3058f6c23d9c..6b3e86e3b7aac 100644 --- a/ports/nordic/common-hal/_bleio/PacketBuffer.c +++ b/ports/nordic/common-hal/_bleio/PacketBuffer.c @@ -278,14 +278,14 @@ void common_hal_bleio_packet_buffer_construct( uint32_t *incoming_buffer = NULL; if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } uint32_t *outgoing1 = NULL; uint32_t *outgoing2 = NULL; if (outgoing) { - outgoing1 = m_malloc(max_packet_size); - outgoing2 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } _common_hal_bleio_packet_buffer_construct(self, characteristic, incoming_buffer, incoming_buffer_size, @@ -485,3 +485,7 @@ void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { ringbuf_deinit(&self->ringbuf); } } + +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self) { + return !common_hal_bleio_packet_buffer_deinited(self) && self->conn_handle != BLE_CONN_HANDLE_INVALID; +} diff --git a/ports/nordic/common-hal/_bleio/Service.c b/ports/nordic/common-hal/_bleio/Service.c index edd67a5fe739d..1bd75f8a48114 100644 --- a/ports/nordic/common-hal/_bleio/Service.c +++ b/ports/nordic/common-hal/_bleio/Service.c @@ -131,7 +131,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, BLE_GAP_CONN_SEC_MODE_SET_OPEN(&user_desc_md.read_perm); // If the description is on the Python heap, then have the SD copy it. If not, assume it's // static and will live for longer than the SD. - user_desc_md.vloc = gc_nbytes(user_description) > 0 ? BLE_GATTS_VLOC_STACK : BLE_GATTS_VLOC_USER; + user_desc_md.vloc = gc_ptr_on_heap(user_description) ? BLE_GATTS_VLOC_STACK : BLE_GATTS_VLOC_USER; char_md.p_user_desc_md = &user_desc_md; char_md.p_char_user_desc = (const uint8_t *)user_description; char_md.char_user_desc_max_size = strlen(user_description); diff --git a/ports/nordic/common-hal/_bleio/__init__.c b/ports/nordic/common-hal/_bleio/__init__.c index 8c5a46d036e0b..9dc58d7687c90 100644 --- a/ports/nordic/common-hal/_bleio/__init__.c +++ b/ports/nordic/common-hal/_bleio/__init__.c @@ -35,6 +35,9 @@ void check_nrf_error(uint32_t err_code) { case NRF_ERROR_INVALID_PARAM: mp_raise_ValueError(MP_ERROR_TEXT("Invalid BLE parameter")); return; + case NRF_ERROR_INVALID_STATE: + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Invalid state")); + return; case BLE_ERROR_INVALID_CONN_HANDLE: mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); return; @@ -77,7 +80,7 @@ void check_sec_status(uint8_t sec_status) { void common_hal_bleio_init(void) { } -void bleio_user_reset() { +void bleio_user_reset(void) { if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); @@ -91,7 +94,7 @@ void bleio_user_reset() { } // Turn off BLE on a reset or reload. -void bleio_reset() { +void bleio_reset(void) { // Set this explicitly to save data. common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { @@ -109,14 +112,14 @@ void bleio_reset() { // It currently only has properties and no state. Inited by bleio_reset bleio_adapter_obj_t common_hal_bleio_adapter_obj; -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } } // GATTS read of a Characteristic or Descriptor. -size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { +size_t bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { // conn_handle is ignored unless this is a system attribute. // If we're not connected, that's OK, because we can still read and write the local value. @@ -130,7 +133,7 @@ size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_ return gatts_value.len; } -void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { +void bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { // conn_handle is ignored unless this is a system attribute. // If we're not connected, that's OK, because we can still read and write the local value. @@ -185,8 +188,8 @@ static bool _on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { return true; } -size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { - common_hal_bleio_check_connected(conn_handle); +size_t bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len) { + bleio_check_connected(conn_handle); read_info_t read_info; read_info.buf = buf; @@ -210,15 +213,15 @@ size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_ RUN_BACKGROUND_TASKS; } // Test if we were disconnected while reading - common_hal_bleio_check_connected(read_info.conn_handle); + bleio_check_connected(read_info.conn_handle); ble_drv_remove_event_handler(_on_gattc_read_rsp_evt, &read_info); check_gatt_status(read_info.status); return read_info.final_len; } -void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { - common_hal_bleio_check_connected(conn_handle); +void bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { + bleio_check_connected(conn_handle); ble_gattc_write_params_t write_params = { .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, diff --git a/ports/nordic/common-hal/alarm/__init__.c b/ports/nordic/common-hal/alarm/__init__.c index 9753b0321fd06..026e117b9a67a 100644 --- a/ports/nordic/common-hal/alarm/__init__.c +++ b/ports/nordic/common-hal/alarm/__init__.c @@ -240,7 +240,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala #define PRESCALER_VALUE_IN_DEEP_SLEEP (1024) -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); diff --git a/ports/nordic/common-hal/alarm/__init__.h b/ports/nordic/common-hal/alarm/__init__.h index 91d717ccce273..336447689ff4e 100644 --- a/ports/nordic/common-hal/alarm/__init__.h +++ b/ports/nordic/common-hal/alarm/__init__.h @@ -13,7 +13,7 @@ #include "common-hal/alarm/touch/TouchAlarm.h" typedef enum { - NRF_SLEEP_WAKEUP_UNDEFINED, + NRF_SLEEP_WAKEUP_UNDEFINED = 0, NRF_SLEEP_WAKEUP_GPIO, NRF_SLEEP_WAKEUP_TIMER, NRF_SLEEP_WAKEUP_TOUCHPAD, @@ -33,8 +33,9 @@ extern const alarm_sleep_memory_obj_t alarm_sleep_memory_obj; enum { SLEEPMEM_WAKEUP_BY_NONE = 0, - SLEEPMEM_WAKEUP_BY_PIN = 1, - SLEEPMEM_WAKEUP_BY_TIMER = 2, + SLEEPMEM_WAKEUP_BY_PIN, + SLEEPMEM_WAKEUP_BY_TIMER, + SLEEPMEM_WAKEUP_BY_TOUCH, }; #define WAKEUP_PIN_UNDEF 0xFF extern uint8_t sleepmem_wakeup_event; diff --git a/ports/nordic/common-hal/audiobusio/I2SOut.c b/ports/nordic/common-hal/audiobusio/I2SOut.c index 6e8fc2088134c..249b4f9d116f7 100644 --- a/ports/nordic/common-hal/audiobusio/I2SOut.c +++ b/ports/nordic/common-hal/audiobusio/I2SOut.c @@ -240,8 +240,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, self->sample = sample; self->loop = loop; - uint32_t sample_rate = audiosample_sample_rate(sample); - self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; + uint32_t sample_rate = audiosample_get_sample_rate(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8; uint32_t max_buffer_length; bool single_buffer, samples_signed; @@ -269,8 +269,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, self->buffer_length = sample_rate * buffer_length_ms * self->bytes_per_sample * self->channel_count / 1000; self->buffer_length = (self->buffer_length + 3) & ~3; - self->buffers[0] = m_malloc(self->buffer_length); - self->buffers[1] = m_malloc(self->buffer_length); + self->buffers[0] = m_malloc_without_collect(self->buffer_length); + self->buffers[1] = m_malloc_without_collect(self->buffer_length); audiosample_reset_buffer(self->sample, false, 0); diff --git a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c index 89c83bc0669f4..b48a03e09c601 100644 --- a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.c @@ -136,7 +136,7 @@ static void audiopwmout_background_obj(audiopwmio_pwmaudioout_obj_t *self) { } } -void audiopwmout_background() { +void audiopwmout_background(void) { // Check the NVIC first because it is part of the CPU and fast to read. if (!NVIC_GetPendingIRQ(PWM0_IRQn) && !NVIC_GetPendingIRQ(PWM1_IRQn) && @@ -188,6 +188,26 @@ bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t *se return !self->pwm; } +static void free_buffers(audiopwmio_pwmaudioout_obj_t *self) { + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(self->buffers[0], self->buffer_size[0]); + self->buffer_size[0] = 0; + #else + m_free(self->buffers[0]); + #endif + + self->buffers[0] = NULL; + + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(self->buffers[1], self->buffer_size[1]); + self->buffer_size[1] = 0; + #else + m_free(self->buffers[1]); + #endif + + self->buffers[1] = NULL; +} + void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t *self) { if (common_hal_audiopwmio_pwmaudioout_deinited(self)) { return; @@ -209,11 +229,7 @@ void common_hal_audiopwmio_pwmaudioout_deinit(audiopwmio_pwmaudioout_obj_t *self self->pwm = NULL; - m_free(self->buffers[0]); - self->buffers[0] = NULL; - - m_free(self->buffers[1]); - self->buffers[1] = NULL; + free_buffers(self); } void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, mp_obj_t sample, bool loop) { @@ -223,22 +239,30 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, self->sample = sample; self->loop = loop; - uint32_t sample_rate = audiosample_sample_rate(sample); - self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; + uint32_t sample_rate = audiosample_get_sample_rate(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8; uint32_t max_buffer_length; uint8_t spacing; audiosample_get_buffer_structure(sample, /* single channel */ false, &self->single_buffer, &self->signed_to_unsigned, &max_buffer_length, &spacing); - self->sample_channel_count = audiosample_channel_count(sample); + self->sample_channel_count = audiosample_get_channel_count(sample); mp_arg_validate_length_max(max_buffer_length, UINT16_MAX, MP_QSTR_buffer); - uint16_t buffer_length = (uint16_t)max_buffer_length; - self->buffers[0] = m_malloc(buffer_length * 2 * sizeof(uint16_t)); + size_t buffer_size = (size_t)max_buffer_length * 2 * sizeof(uint16_t); + + self->buffers[0] = m_malloc_without_collect(buffer_size); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->buffer_size[0] = buffer_size; + #endif + if (!self->single_buffer) { - self->buffers[1] = m_malloc(buffer_length * 2 * sizeof(uint16_t)); + self->buffers[1] = m_malloc_without_collect(buffer_size); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->buffer_size[1] = buffer_size; + #endif } @@ -274,11 +298,7 @@ void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t *self) self->stopping = false; self->paused = false; - m_free(self->buffers[0]); - self->buffers[0] = NULL; - - m_free(self->buffers[1]); - self->buffers[1] = NULL; + free_buffers(self); } bool common_hal_audiopwmio_pwmaudioout_get_playing(audiopwmio_pwmaudioout_obj_t *self) { diff --git a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.h b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.h index 9569811ccd9f5..da0761441f857 100644 --- a/ports/nordic/common-hal/audiopwmio/PWMAudioOut.h +++ b/ports/nordic/common-hal/audiopwmio/PWMAudioOut.h @@ -12,7 +12,11 @@ typedef struct { mp_obj_base_t base; mp_obj_t *sample; NRF_PWM_Type *pwm; + uint16_t *buffers[2]; + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + size_t buffer_size[2]; // Keeps track of allocated size + #endif uint16_t quiescent_value; uint16_t scale; diff --git a/ports/nordic/common-hal/busio/I2C.c b/ports/nordic/common-hal/busio/I2C.c index b0956e7d20ab0..999737f632bba 100644 --- a/ports/nordic/common-hal/busio/I2C.c +++ b/ports/nordic/common-hal/busio/I2C.c @@ -21,7 +21,8 @@ // all TWI instances have the same max size // 16 bits for 840, 10 bits for 810, 8 bits for 832 #define I2C_MAX_XFER_LEN MIN(((1UL << TWIM0_EASYDMA_MAXCNT_SIZE) - 1), 1024) -#define I2C_TIMEOUT 1000 // 1 second timeout +// 1 second timeout +#define I2C_TIMEOUT 1000 static twim_peripheral_t twim_peripherals[] = { #if NRFX_CHECK(NRFX_TWIM0_ENABLED) @@ -40,42 +41,24 @@ static twim_peripheral_t twim_peripherals[] = { #endif }; -static bool never_reset[MP_ARRAY_SIZE(twim_peripherals)]; - -void i2c_reset(void) { - for (size_t i = 0; i < MP_ARRAY_SIZE(twim_peripherals); i++) { - if (never_reset[i]) { - continue; - } - nrfx_twim_uninit(&twim_peripherals[i].twim); - twim_peripherals[i].in_use = false; - } -} void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - for (size_t i = 0; i < MP_ARRAY_SIZE(twim_peripherals); i++) { - if (self->twim_peripheral == &twim_peripherals[i]) { - never_reset[i] = true; - - never_reset_pin_number(self->scl_pin_number); - never_reset_pin_number(self->sda_pin_number); - break; - } - } + never_reset_pin_number(self->scl_pin_number); + never_reset_pin_number(self->sda_pin_number); } -static uint8_t twi_error_to_mp(const nrfx_err_t err) { +static mp_negative_errno_t twi_error_to_mp(const nrfx_err_t err) { switch (err) { case NRFX_ERROR_DRV_TWI_ERR_ANACK: - return MP_ENODEV; + return -MP_ENODEV; case NRFX_ERROR_BUSY: - return MP_EBUSY; + return -MP_EBUSY; case NRFX_ERROR_INVALID_ADDR: case NRFX_ERROR_DRV_TWI_ERR_DNACK: case NRFX_ERROR_DRV_TWI_ERR_OVERRUN: - return MP_EIO; + return -MP_EIO; case NRFX_ERROR_TIMEOUT: - return MP_ETIMEDOUT; + return -MP_ETIMEDOUT; default: break; } @@ -91,6 +74,10 @@ static void twim_event_handler(nrfx_twim_evt_t const *p_event, void *p_context) } void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + if (scl->number == sda->number) { raise_ValueError_invalid_pins(); } @@ -172,10 +159,13 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { reset_pin_number(self->sda_pin_number); reset_pin_number(self->scl_pin_number); - self->sda_pin_number = NO_PIN; - self->scl_pin_number = NO_PIN; self->twim_peripheral->in_use = false; + common_hal_busio_i2c_mark_deinit(self); +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->sda_pin_number = NO_PIN; } // nrfx_twim_tx doesn't support 0-length data so we fall back to the hal API @@ -216,6 +206,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; // NRFX_CRITICAL_SECTION_ENTER(); if (!self->has_lock) { @@ -265,9 +258,9 @@ static nrfx_err_t _twim_xfer_with_timeout(busio_i2c_obj_t *self, nrfx_twim_xfer_ } } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) { +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool stopBit) { if (len == 0) { - return common_hal_busio_i2c_probe(self, addr) ? 0 : MP_ENODEV; + return common_hal_busio_i2c_probe(self, addr) ? 0 : -MP_ENODEV; } nrfx_err_t err = NRFX_SUCCESS; @@ -293,11 +286,11 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, return twi_error_to_mp(err); } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { if (len == 0) { return 0; } @@ -324,9 +317,9 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t return twi_error_to_mp(err); } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } diff --git a/ports/nordic/common-hal/busio/I2C.h b/ports/nordic/common-hal/busio/I2C.h index d94ff6929bc4e..c1c1839f892d4 100644 --- a/ports/nordic/common-hal/busio/I2C.h +++ b/ports/nordic/common-hal/busio/I2C.h @@ -25,5 +25,3 @@ typedef struct { uint8_t scl_pin_number; uint8_t sda_pin_number; } busio_i2c_obj_t; - -void i2c_reset(void); diff --git a/ports/nordic/common-hal/busio/SPI.c b/ports/nordic/common-hal/busio/SPI.c index 23e06c6481d1c..de54dd08a2783 100644 --- a/ports/nordic/common-hal/busio/SPI.c +++ b/ports/nordic/common-hal/busio/SPI.c @@ -59,26 +59,13 @@ static const spim_peripheral_t spim_peripherals[] = { #endif }; -static bool never_reset[MP_ARRAY_SIZE(spim_peripherals)]; - // Separate RAM area for SPIM3 transmit buffer to avoid SPIM3 hardware errata. // https://infocenter.nordicsemi.com/index.jsp?topic=%2Ferrata_nRF52840_Rev2%2FERR%2FnRF52840%2FRev2%2Flatest%2Fanomaly_840_198.html static uint8_t *spim3_transmit_buffer = (uint8_t *)SPIM3_BUFFER_RAM_START_ADDR; -void spi_reset(void) { - for (size_t i = 0; i < MP_ARRAY_SIZE(spim_peripherals); i++) { - if (never_reset[i]) { - continue; - } - nrfx_spim_uninit(&spim_peripherals[i].spim); - } -} - void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { for (size_t i = 0; i < MP_ARRAY_SIZE(spim_peripherals); i++) { if (self->spim_peripheral == &spim_peripherals[i]) { - never_reset[i] = true; - never_reset_pin_number(self->clock_pin_number); never_reset_pin_number(self->MOSI_pin_number); never_reset_pin_number(self->MISO_pin_number); @@ -125,6 +112,9 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + if (half_duplex) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex); } @@ -178,6 +168,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock_pin_number == NO_PIN; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock_pin_number = NO_PIN; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; @@ -188,6 +182,8 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { reset_pin_number(self->clock_pin_number); reset_pin_number(self->MOSI_pin_number); reset_pin_number(self->MISO_pin_number); + + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { @@ -213,6 +209,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; // NRFX_CRITICAL_SECTION_ENTER(); if (!self->has_lock) { diff --git a/ports/nordic/common-hal/busio/SPI.h b/ports/nordic/common-hal/busio/SPI.h index 7bfddd9625dcb..3260c5c27dee2 100644 --- a/ports/nordic/common-hal/busio/SPI.h +++ b/ports/nordic/common-hal/busio/SPI.h @@ -23,5 +23,3 @@ typedef struct { uint8_t MOSI_pin_number; uint8_t MISO_pin_number; } busio_spi_obj_t; - -void spi_reset(void); diff --git a/ports/nordic/common-hal/busio/UART.c b/ports/nordic/common-hal/busio/UART.c index c9b0024db921d..6939486a5e673 100644 --- a/ports/nordic/common-hal/busio/UART.c +++ b/ports/nordic/common-hal/busio/UART.c @@ -122,7 +122,7 @@ void uart_reset(void) { void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { // Don't never reset objects on the heap. - if (gc_alloc_possible() && gc_nbytes(self) > 0) { + if (gc_alloc_possible() && gc_ptr_on_heap(self)) { return; } for (size_t i = 0; i < MP_ARRAY_SIZE(nrfx_uartes); i++) { @@ -325,7 +325,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, if (!nrfx_is_in_ram(data)) { // Allocate long strings on the heap. if (len > 128 && gc_alloc_possible()) { - tx_buf = (uint8_t *)m_malloc(len); + tx_buf = (uint8_t *)m_malloc_without_collect(len); } else { tx_buf = alloca(len); } @@ -346,7 +346,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, RUN_BACKGROUND_TASKS; } - if (!nrfx_is_in_ram(data) && gc_alloc_possible() && gc_nbytes(tx_buf) > 0) { + if (!nrfx_is_in_ram(data) && gc_alloc_possible() && gc_ptr_on_heap(tx_buf)) { gc_free(tx_buf); } diff --git a/ports/nordic/common-hal/microcontroller/__init__.c b/ports/nordic/common-hal/microcontroller/__init__.c index 69024cbb296e0..fbb40afe0449d 100644 --- a/ports/nordic/common-hal/microcontroller/__init__.c +++ b/ports/nordic/common-hal/microcontroller/__init__.c @@ -8,6 +8,10 @@ #include "py/obj.h" #include "py/runtime.h" +#if CIRCUITPY_ALARM +#include "common-hal/alarm/__init__.h" +#endif + #include "common-hal/microcontroller/Pin.h" #include "common-hal/microcontroller/Processor.h" @@ -21,6 +25,7 @@ #include "supervisor/shared/safe_mode.h" #include "nrfx_glue.h" #include "nrf_nvic.h" +#include "nrf_power.h" // This routine should work even when interrupts are disabled. Used by OneWire // for precise timing. @@ -30,7 +35,7 @@ void common_hal_mcu_delay_us(uint32_t delay) { static volatile uint32_t nesting_count = 0; static uint8_t is_nested_critical_region; -void common_hal_mcu_disable_interrupts() { +void common_hal_mcu_disable_interrupts(void) { if (nesting_count == 0) { // Unlike __disable_irq(), this should only be called the first time // "is_nested_critical_region" is sd's equivalent of our nesting count @@ -46,7 +51,7 @@ void common_hal_mcu_disable_interrupts() { nesting_count++; } -void common_hal_mcu_enable_interrupts() { +void common_hal_mcu_enable_interrupts(void) { if (nesting_count == 0) { // This is very very bad because it means there was mismatched disable/enables. reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR); @@ -61,10 +66,14 @@ void common_hal_mcu_enable_interrupts() { void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { enum { DFU_MAGIC_UF2_RESET = 0x57 }; + uint8_t new_value = 0; if (runmode == RUNMODE_BOOTLOADER || runmode == RUNMODE_UF2) { - sd_power_gpregret_set(0, DFU_MAGIC_UF2_RESET); - } else { - sd_power_gpregret_set(0, 0); + new_value = DFU_MAGIC_UF2_RESET; + } + int err_code = sd_power_gpregret_set(0, DFU_MAGIC_UF2_RESET); + if (err_code != NRF_SUCCESS) { + // Set it without the soft device if the SD failed. (It may be off.) + nrf_power_gpregret_set(NRF_POWER, new_value); } if (runmode == RUNMODE_SAFE_MODE) { safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC); @@ -73,6 +82,14 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { void common_hal_mcu_reset(void) { filesystem_flush(); + + // Clear any saved info about last deep sleep wakeup, + // to avoid confusing this software reset with a real deep sleep reset. + // See logic in common_hal_mcu_processor_get_reset_reason(). + #if CIRCUITPY_ALARM + sleepmem_wakeup_event = SLEEPMEM_WAKEUP_BY_NONE; + #endif + reset_cpu(); } diff --git a/ports/nordic/common-hal/os/__init__.c b/ports/nordic/common-hal/os/__init__.c index 78aa1e040cf8e..54b8ad026a7de 100644 --- a/ports/nordic/common-hal/os/__init__.c +++ b/ports/nordic/common-hal/os/__init__.c @@ -17,32 +17,6 @@ #include "nrf_rng.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "nrf52"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "nrf52"); - -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { #ifdef BLUETOOTH_SD uint8_t sd_en = 0; diff --git a/ports/nordic/common-hal/pulseio/PulseIn.c b/ports/nordic/common-hal/pulseio/PulseIn.c index 0a2286090e0ed..dce3a9c96c1f5 100644 --- a/ports/nordic/common-hal/pulseio/PulseIn.c +++ b/ports/nordic/common-hal/pulseio/PulseIn.c @@ -98,7 +98,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu } _objs[idx] = self; - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } diff --git a/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c b/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c index b0617fae7e566..2e8b308ff64d9 100644 --- a/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/nordic/common-hal/rotaryio/IncrementalEncoder.c @@ -32,6 +32,9 @@ static void _intr_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + self->pin_a = pin_a->number; self->pin_b = pin_b->number; @@ -78,6 +81,10 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o nrfx_gpiote_in_uninit(self->pin_b); reset_pin_number(self->pin_a); reset_pin_number(self->pin_b); + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { self->pin_a = NO_PIN; - self->pin_b = NO_PIN; } diff --git a/ports/nordic/mpconfigport.h b/ports/nordic/mpconfigport.h index ed6c2827000ca..33fcfa371e0bd 100644 --- a/ports/nordic/mpconfigport.h +++ b/ports/nordic/mpconfigport.h @@ -13,8 +13,6 @@ #include "nrf_sdm.h" // for SD_FLASH_SIZE #include "peripherals/nrf/nvm.h" // for FLASH_PAGE_SIZE -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) #define MICROPY_PY_SYS_STDIO_BUFFER (1) // 24kiB stack diff --git a/ports/nordic/mpconfigport.mk b/ports/nordic/mpconfigport.mk index 58700817d5178..48536ec2acd7b 100644 --- a/ports/nordic/mpconfigport.mk +++ b/ports/nordic/mpconfigport.mk @@ -25,7 +25,7 @@ CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12 # Native BLEIO is not compatible with HCI _bleio. CIRCUITPY_BLEIO_HCI = 0 -CIRCUITPY_BLEIO ?= 1 +CIRCUITPY_BLEIO_NATIVE ?= 1 # No I2CPeripheral implementation CIRCUITPY_I2CTARGET = 0 @@ -63,6 +63,8 @@ CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_RGBMATRIX ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= 1 +CIRCUITPY_HASHLIB ?= 1 + CIRCUITPY_COUNTIO ?= 1 CIRCUITPY_WATCHDOG ?= 1 diff --git a/ports/nordic/peripherals/nrf/pins.h b/ports/nordic/peripherals/nrf/pins.h index 096568e87c3da..96810764de99d 100644 --- a/ports/nordic/peripherals/nrf/pins.h +++ b/ports/nordic/peripherals/nrf/pins.h @@ -12,6 +12,8 @@ #include #include +#include "py/obj.h" + #include "nrf_gpio.h" typedef struct { diff --git a/ports/nordic/supervisor/cpu.s b/ports/nordic/supervisor/cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/nordic/supervisor/cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/nordic/supervisor/port.c b/ports/nordic/supervisor/port.c index 759cb8ed42592..1eabfcbe2166b 100644 --- a/ports/nordic/supervisor/port.c +++ b/ports/nordic/supervisor/port.c @@ -27,7 +27,6 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/alarm/time/TimeAlarm.h" #include "common-hal/analogio/AnalogIn.h" -#include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/busio/UART.h" #include "common-hal/rtc/RTC.h" @@ -190,8 +189,6 @@ safe_mode_t port_init(void) { void reset_port(void) { #if CIRCUITPY_BUSIO - i2c_reset(); - spi_reset(); uart_reset(); #endif @@ -218,8 +215,6 @@ void reset_port(void) { nrfx_gpiote_uninit(); } nrfx_gpiote_init(NRFX_GPIOTE_CONFIG_IRQ_PRIORITY); - - reset_all_pins(); } void reset_to_bootloader(void) { diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index fd4da22ea08fd..cef2806c87497 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -12,6 +12,7 @@ HAL_DIR=hal/$(MCU_SERIES) ifeq ($(CIRCUITPY_CYW43),1) INC_CYW43 := \ + -isystem lib/cyw43-driver \ -isystem lib/cyw43-driver/firmware \ -isystem lib/cyw43-driver/src \ -isystem lib/lwip/src/include \ @@ -21,7 +22,21 @@ INC_CYW43 := \ -isystem sdk/src/rp2_common/pico_lwip/include/ \ -isystem sdk/src/rp2_common/pico_rand/include/ \ -CFLAGS_CYW43 := -DCYW43_LWIP=1 -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 -DCYW43_USE_SPI -DIGNORE_GPIO25 -DIGNORE_GPIO23 -DIGNORE_GPIO24 -DCYW43_LOGIC_DEBUG=0 -DCYW43_USE_STATS=0 -DPICO_BUILD -DCYW43_ENABLE_BLUETOOTH=0 -DPICO_CYW43_ARCH_POLL=0 +CFLAGS_CYW43 := \ + -DCYW43_LWIP=1 \ + -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND=1 \ + -DCYW43_USE_SPI=1 \ + -DUSE_SDIOIT=0 \ + -DIGNORE_GPIO25 \ + -DIGNORE_GPIO23 \ + -DIGNORE_GPIO24 \ + -DCYW43_LOGIC_DEBUG=0 \ + -DCYW43_USE_STATS=0 \ + -DPICO_BUILD \ + -DCYW43_ENABLE_BLUETOOTH=0 \ + -DCIRCUITPY_CYW43_INIT_DELAY=$(CIRCUITPY_CYW43_INIT_DELAY) \ + -DPICO_CYW43_ARCH_POLL=0 + SRC_SDK_CYW43 := \ src/common/pico_sync/sem.c \ src/rp2_common/pico_async_context/async_context_base.c \ @@ -79,8 +94,6 @@ INC += \ -I../shared/timeutils \ -Iboards/$(BOARD) \ -Iboards/ \ - -isystem ./../../lib/cmsis/inc \ - -isystem sdk/ \ -isystem sdk/src/common/boot_picobin_headers/include/ \ -isystem sdk/src/common/boot_picoboot_headers/include/ \ -isystem sdk/src/common/hardware_claim/include/ \ @@ -93,6 +106,9 @@ INC += \ -isystem sdk/src/$(CHIP_VARIANT_LOWER)/hardware_regs/include/ \ -isystem sdk/src/$(CHIP_VARIANT_LOWER)/hardware_structs/include/ \ -isystem sdk/src/$(CHIP_VARIANT_LOWER)/pico_platform/include/ \ + -isystem sdk/src/rp2_common/boot_bootrom_headers/include/ \ + -isystem sdk/src/rp2_common/cmsis/stub/CMSIS/Core/Include/ \ + -isystem sdk/src/rp2_common/cmsis/stub/CMSIS/Device/${CHIP_VARIANT}/Include \ -isystem sdk/src/rp2_common/cmsis/ \ -isystem sdk/src/rp2_common/hardware_adc/include/ \ -isystem sdk/src/rp2_common/hardware_base/include/ \ @@ -110,6 +126,7 @@ INC += \ -isystem sdk/src/rp2_common/hardware_powman/include/ \ -isystem sdk/src/rp2_common/hardware_pwm/include/ \ -isystem sdk/src/rp2_common/hardware_resets/include/ \ + -isystem sdk/src/rp2_common/hardware_rcp/include/ \ -isystem sdk/src/rp2_common/hardware_rtc/include/ \ -isystem sdk/src/rp2_common/hardware_spi/include/ \ -isystem sdk/src/rp2_common/hardware_sync/include/ \ @@ -120,10 +137,12 @@ INC += \ -isystem sdk/src/rp2_common/hardware_vreg/include/ \ -isystem sdk/src/rp2_common/hardware_watchdog/include/ \ -isystem sdk/src/rp2_common/hardware_xosc/include/ \ + -isystem sdk/src/rp2_common/hardware_xip_cache/include/ \ -isystem sdk/src/rp2_common/pico_aon_timer/include/ \ -isystem sdk/src/rp2_common/pico_atomic/include/ \ -isystem sdk/src/rp2_common/pico_bootrom/include/ \ -isystem sdk/src/rp2_common/pico_double/include/ \ + -isystem sdk/src/rp2_common/pico_flash/include/ \ -isystem sdk/src/rp2_common/pico_mem_ops/include/ \ -isystem sdk/src/rp2_common/pico_multicore/include/ \ -isystem sdk/src/rp2_common/pico_fix/rp2040_usb_device_enumeration/include/ \ @@ -132,12 +151,13 @@ INC += \ -isystem sdk/src/rp2_common/pico_float/include/ \ -isystem sdk/src/rp2_common/pico_runtime/include/ \ -isystem sdk/src/rp2_common/pico_runtime_init/include/ \ + -isystem sdk/src/rp2_common/pico_platform_common/include/ \ -isystem sdk/src/rp2_common/pico_platform_compiler/include/ \ -isystem sdk/src/rp2_common/pico_platform_sections/include/ \ -isystem sdk/src/rp2_common/pico_platform_panic/include/ \ -isystem sdk/src/rp2_common/pico_time_adapter/include/ \ -isystem sdk/src/rp2_common/pico_unique_id/include/ \ -$(INC_CYW43) \ + $(INC_CYW43) \ -Isdk_config \ -I../../lib/tinyusb/src \ -I../../supervisor/shared/usb \ @@ -158,7 +178,7 @@ CFLAGS += \ -DPICO_DOUBLE_ROM=1 \ -DPICO_FLOAT_ROM=1 \ -DPICO_BITS_IN_RAM=0 \ - -DPICO_DIVIDER_IN_RAM=0 \ + -DPICO_DIVIDER_IN_RAM=1 \ -DPICO_DOUBLE_PROPAGATE_NANS=0 \ -DPICO_DOUBLE_IN_RAM=0 \ -DPICO_MEM_IN_RAM=0 \ @@ -192,7 +212,7 @@ CFLAGS += $(OPTIMIZATION_FLAGS) CFLAGS += $(CFLAGS_CYW43) #Debugging/Optimization ifeq ($(DEBUG), 1) - CFLAGS += -ggdb3 -O3 + CFLAGS += -ggdb3 -Og # No LTO because we may place some functions in RAM instead of flash. else CFLAGS += -DNDEBUG @@ -204,10 +224,9 @@ else endif endif -# Remove -Wno-stringop-overflow after we can test with CI's GCC 10. Mac's looks weird. -DISABLE_WARNINGS = -Wno-stringop-overflow -Wno-cast-align +DISABLE_WARNINGS = -Wno-cast-align -CFLAGS += $(INC) -Wall -Werror -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -Werror=missing-prototypes +CFLAGS += $(INC) -Wtype-limits -Wall -Werror -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -Werror=missing-prototypes -Wold-style-definition PICO_LDFLAGS = --specs=nosys.specs --specs=nano.specs @@ -377,6 +396,8 @@ OTHER_PICO_FLAGS := \ -Wl,--wrap=__aeabi_uidivmod \ -Wl,--wrap=__aeabi_uldivmod +SRC_S = shared/runtime/gchelper_thumb1.s + ifeq ($(CHIP_VARIANT),RP2040) CFLAGS += \ -march=armv6-m \ @@ -415,12 +436,12 @@ UF2_ID = 0xE48BFF56 DOUBLE_EABI = rp2040 endif ifeq ($(CHIP_VARIANT),RP2350) -CFLAGS += \ - -march=armv8-m.main+fp+dsp \ +AFLAGS = -march=armv8-m.main+fp+dsp \ -mthumb \ - -mabi=aapcs-linux \ -mcpu=cortex-m33 \ -mfloat-abi=softfp +CFLAGS += $(AFLAGS) \ + -mabi=aapcs-linux # ARM Secure family id UF2_ID = 0xe48bff59 @@ -440,7 +461,7 @@ SRC_S_UPPER_CHIP_VARIANT := \ sdk/src/rp2_common/pico_double/double_fma_dcp.S \ sdk/src/rp2_common/pico_double/double_sci_m33.S \ sdk/src/rp2_common/pico_float/float_sci_m33_vfp.S \ - sdk/src/rp2_common/pico_float/float_conv_m33.S \ + sdk/src/rp2_common/pico_float/float_common_m33.S \ PICO_LDFLAGS += $(PICO_WRAP_FLOAT_SCI_FLAGS) $(PICO_WRAP_DOUBLE_FLAGS) @@ -454,6 +475,7 @@ endif endif +SRC_C += shared/runtime/gchelper_native.c SRC_SDK := \ src/common/hardware_claim/claim.c \ @@ -483,6 +505,7 @@ SRC_SDK := \ src/rp2_common/hardware_uart/uart.c \ src/rp2_common/hardware_vreg/vreg.c \ src/rp2_common/hardware_watchdog/watchdog.c \ + src/rp2_common/hardware_xip_cache/xip_cache.c \ src/rp2_common/hardware_xosc/xosc.c \ src/rp2_common/pico_aon_timer/aon_timer.c \ src/rp2_common/pico_atomic/atomic.c \ @@ -541,15 +564,19 @@ ifeq ($(CIRCUITPY_PICODVI),1) SRC_C += \ bindings/picodvi/__init__.c \ bindings/picodvi/Framebuffer.c \ + common-hal/picodvi/__init__.c \ common-hal/picodvi/Framebuffer_$(CHIP_VARIANT).c \ ifeq ($(CHIP_VARIANT),RP2040) -SRC_C += \ +SRC_PICODVI := \ lib/PicoDVI/software/libdvi/dvi.c \ lib/PicoDVI/software/libdvi/dvi_serialiser.c \ lib/PicoDVI/software/libdvi/dvi_timing.c \ lib/PicoDVI/software/libdvi/tmds_encode.c \ +SRC_C += $(SRC_PICODVI) +$(patsubst %.c,$(BUILD)/%.o,$(SRC_PICODVI))): CFLAGS += -Wno-old-style-definition + endif endif @@ -634,7 +661,7 @@ CFLAGS += \ -isystem $(TOP)/lib/mbedtls/include \ -DMBEDTLS_CONFIG_FILE='"$(TOP)/lib/mbedtls_config/mbedtls_config.h"' \ -$(BUILD)/x509_crt_bundle.S: $(TOP)/lib/certificates/data/roots.pem $(TOP)/tools/gen_crt_bundle.py +$(BUILD)/x509_crt_bundle.S: $(TOP)/lib/certificates/data/roots-full.pem $(TOP)/tools/gen_crt_bundle.py $(Q)$(PYTHON) $(TOP)/tools/gen_crt_bundle.py -i $< -o $@ --asm OBJ_MBEDTLS := $(BUILD)/x509_crt_bundle.o $(patsubst %.c,$(BUILD)/%.o,$(SRC_MBEDTLS))): CFLAGS += -Wno-suggest-attribute=format @@ -642,21 +669,6 @@ else OBJ_MBEDTLS := endif - -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-module/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) - -SRC_S = supervisor/$(CHIP_FAMILY)_cpu.s BOOT2_S_CFLAGS ?= -DPICO_FLASH_SPI_CLKDIV=4 SRC_S_UPPER = sdk/src/rp2_common/hardware_irq/irq_handler_chain.S \ sdk/src/rp2_common/pico_bit_ops/bit_ops_aeabi.S \ @@ -714,7 +726,7 @@ $(BUILD)/boot2.elf: $(BUILD)/stage2.c $(Q)$(CC) $(CFLAGS) $(BOOT2_S_CFLAGS) -Os -ggdb3 -I. -fPIC --specs=nosys.specs -nostartfiles -Wl,-T,boot_stage2/$(CHIP_VARIANT).ld -Wl,-Map=$@.map -o $@ $< $(Q)$(SIZE) $@ -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) all: $(BUILD)/firmware.uf2 diff --git a/ports/raspberrypi/audio_dma.c b/ports/raspberrypi/audio_dma.c index c837bc116d48d..ae3997a128f8e 100644 --- a/ports/raspberrypi/audio_dma.c +++ b/ports/raspberrypi/audio_dma.c @@ -15,7 +15,7 @@ #include "py/mpstate.h" #include "py/runtime.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "hardware/irq.h" #include "hardware/regs/intctrl.h" // For isr_ macro. @@ -118,6 +118,7 @@ static size_t audio_dma_convert_samples(audio_dma_t *dma, uint8_t *input, uint32 // buffer_idx is 0 or 1. static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) { + assert(dma->channel[buffer_idx] < NUM_DMA_CHANNELS); size_t dma_channel = dma->channel[buffer_idx]; audioio_get_buffer_result_t get_buffer_result; @@ -128,6 +129,7 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) { if (get_buffer_result == GET_BUFFER_ERROR) { audio_dma_stop(dma); + dma->dma_result = AUDIO_DMA_SOURCE_ERROR; return; } @@ -157,10 +159,16 @@ static void audio_dma_load_next_block(audio_dma_t *dma, size_t buffer_idx) { !dma_channel_is_busy(dma->channel[1])) { // No data has been read, and both DMA channels have now finished, so it's safe to stop. audio_dma_stop(dma); - dma->playing_in_progress = false; + dma->dma_result = AUDIO_DMA_OK; + return; } } } + // Enable the channel so that it can be played. + if (!dma->paused) { + dma_hw->ch[dma_channel].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS; + } + dma->dma_result = AUDIO_DMA_OK; } // Playback should be shutdown before calling this. @@ -201,7 +209,7 @@ audio_dma_result audio_dma_setup_playback( dma->output_signed = output_signed; dma->sample_spacing = 1; dma->output_resolution = output_resolution; - dma->sample_resolution = audiosample_bits_per_sample(sample); + dma->sample_resolution = audiosample_get_bits_per_sample(sample); dma->output_register_address = output_register_address; dma->swap_channel = swap_channel; @@ -225,15 +233,33 @@ audio_dma_result audio_dma_setup_playback( max_buffer_length /= dma->sample_spacing; } - dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], max_buffer_length); + #ifdef PICO_RP2350 + dma->buffer[0] = (uint8_t *)port_realloc(dma->buffer[0], max_buffer_length, true); + #else + dma->buffer[0] = (uint8_t *)m_realloc(dma->buffer[0], + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + dma->buffer_length[0], // Old size + #endif + max_buffer_length); + #endif dma->buffer_length[0] = max_buffer_length; + if (dma->buffer[0] == NULL) { return AUDIO_DMA_MEMORY_ERROR; } if (!single_buffer) { - dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1], max_buffer_length); + #ifdef PICO_RP2350 + dma->buffer[1] = (uint8_t *)port_realloc(dma->buffer[1], max_buffer_length, true); + #else + dma->buffer[1] = (uint8_t *)m_realloc(dma->buffer[1], + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + dma->buffer_length[1], // Old size + #endif + max_buffer_length); + #endif dma->buffer_length[1] = max_buffer_length; + if (dma->buffer[1] == NULL) { return AUDIO_DMA_MEMORY_ERROR; } @@ -248,7 +274,7 @@ audio_dma_result audio_dma_setup_playback( dma->output_size = 1; } // Transfer both channels at once. - if (!single_channel_output && audiosample_channel_count(sample) == 2) { + if (!single_channel_output && audiosample_get_channel_count(sample) == 2) { dma->output_size *= 2; } enum dma_channel_transfer_size dma_size = DMA_SIZE_8; @@ -277,10 +303,18 @@ audio_dma_result audio_dma_setup_playback( MP_STATE_PORT(playing_audio)[dma->channel[0]] = dma; MP_STATE_PORT(playing_audio)[dma->channel[1]] = dma; + dma->paused = false; + // Load the first two blocks up front. audio_dma_load_next_block(dma, 0); + if (dma->dma_result != AUDIO_DMA_OK) { + return dma->dma_result; + } if (!single_buffer) { audio_dma_load_next_block(dma, 1); + if (dma->dma_result != AUDIO_DMA_OK) { + return dma->dma_result; + } } // Special case the DMA for a single buffer. It's commonly used for a single wave length of sound @@ -301,6 +335,8 @@ audio_dma_result audio_dma_setup_playback( 1, // transaction count false); // trigger } else { + // Clear any latent interrupts so that we don't immediately disable channels. + dma_hw->ints0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]); // Enable our DMA channels on DMA_IRQ_0 to the CPU. This will wake us up when // we're WFI. dma_hw->inte0 |= (1 << dma->channel[0]) | (1 << dma->channel[1]); @@ -314,6 +350,8 @@ audio_dma_result audio_dma_setup_playback( } void audio_dma_stop(audio_dma_t *dma) { + dma->paused = true; + // Disable our interrupts. uint32_t channel_mask = 0; if (dma->channel[0] < NUM_DMA_CHANNELS) { @@ -333,12 +371,13 @@ void audio_dma_stop(audio_dma_t *dma) { for (size_t i = 0; i < 2; i++) { size_t channel = dma->channel[i]; + dma->channel[i] = NUM_DMA_CHANNELS; if (channel == NUM_DMA_CHANNELS) { // Channel not in use. continue; } - dma_channel_config c = dma_channel_get_default_config(dma->channel[i]); + dma_channel_config c = dma_channel_get_default_config(channel); channel_config_set_enable(&c, false); dma_channel_set_config(channel, &c, false /* trigger */); @@ -351,7 +390,6 @@ void audio_dma_stop(audio_dma_t *dma) { dma_channel_set_trans_count(channel, 0, false /* trigger */); dma_channel_unclaim(channel); MP_STATE_PORT(playing_audio)[channel] = NULL; - dma->channel[i] = NUM_DMA_CHANNELS; } dma->playing_in_progress = false; @@ -363,6 +401,7 @@ void audio_dma_stop(audio_dma_t *dma) { void audio_dma_pause(audio_dma_t *dma) { dma_hw->ch[dma->channel[0]].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; dma_hw->ch[dma->channel[1]].al1_ctrl &= ~DMA_CH1_CTRL_TRIG_EN_BITS; + dma->paused = true; } void audio_dma_resume(audio_dma_t *dma) { @@ -375,15 +414,14 @@ void audio_dma_resume(audio_dma_t *dma) { dma_hw->ch[dma->channel[0]].al1_ctrl |= DMA_CH0_CTRL_TRIG_EN_BITS; dma_hw->ch[dma->channel[1]].al1_ctrl |= DMA_CH1_CTRL_TRIG_EN_BITS; } + dma->paused = false; } bool audio_dma_get_paused(audio_dma_t *dma) { if (dma->channel[0] >= NUM_DMA_CHANNELS) { return false; } - uint32_t control = dma_hw->ch[dma->channel[0]].ctrl_trig; - - return (control & DMA_CH0_CTRL_TRIG_EN_BITS) == 0; + return dma->playing_in_progress && dma->paused; } uint32_t audio_dma_pause_all(void) { @@ -411,16 +449,40 @@ void audio_dma_init(audio_dma_t *dma) { dma->buffer[0] = NULL; dma->buffer[1] = NULL; + dma->buffer_length[0] = 0; + dma->buffer_length[1] = 0; + dma->channel[0] = NUM_DMA_CHANNELS; dma->channel[1] = NUM_DMA_CHANNELS; + + dma->playing_in_progress = false; + dma->paused = false; } void audio_dma_deinit(audio_dma_t *dma) { + #ifdef PICO_RP2350 + port_free(dma->buffer[0]); + #else + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(dma->buffer[0], dma->buffer_length[0]); + #else m_free(dma->buffer[0]); + #endif + #endif dma->buffer[0] = NULL; - + dma->buffer_length[0] = 0; + + #ifdef PICO_RP2350 + port_free(dma->buffer[1]); + #else + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(dma->buffer[1], dma->buffer_length[1]); + #else m_free(dma->buffer[1]); + #endif + #endif dma->buffer[1] = NULL; + dma->buffer_length[1] = 0; } bool audio_dma_get_playing(audio_dma_t *dma) { @@ -435,6 +497,8 @@ bool audio_dma_get_playing(audio_dma_t *dma) { // NOTE(dhalbert): I successfully printed from here while debugging. // So it's possible, but be careful. static void dma_callback_fun(void *arg) { + // Any audio interrupts that happen below will requeue the background task + // after updating channels_to_load_mask. audio_dma_t *dma = arg; if (dma == NULL) { return; @@ -442,29 +506,36 @@ static void dma_callback_fun(void *arg) { common_hal_mcu_disable_interrupts(); uint32_t channels_to_load_mask = dma->channels_to_load_mask; + // This can be 0 if the background task was queued between the call to + // dma_callback_fun and the above read of channels_to_load_mask. dma->channels_to_load_mask = 0; common_hal_mcu_enable_interrupts(); - // Load the blocks for the requested channels. - uint32_t channel = 0; - while (channels_to_load_mask) { - if (channels_to_load_mask & 1) { - if (dma->channel[0] == channel) { - audio_dma_load_next_block(dma, 0); - } - if (dma->channel[1] == channel) { - audio_dma_load_next_block(dma, 1); - } - } - channels_to_load_mask >>= 1; - channel++; + uint8_t first_filled_channel = NUM_DMA_CHANNELS; + size_t filled_count = 0; + if (dma->channel[0] != NUM_DMA_CHANNELS && (channels_to_load_mask & (1 << dma->channel[0]))) { + audio_dma_load_next_block(dma, 0); + first_filled_channel = dma->channel[0]; + filled_count++; + } + if (dma->channel[1] != NUM_DMA_CHANNELS && (channels_to_load_mask & (1 << dma->channel[1]))) { + audio_dma_load_next_block(dma, 1); + first_filled_channel = dma->channel[1]; + filled_count++; + } + + // Restart if the other channel has been queued while we were filling the first or we filled two + // now. (Two get filled if the second buffer completes while the first is waiting in the + // background task queue.) + if (first_filled_channel != NUM_DMA_CHANNELS && (dma->channels_to_load_mask != 0 || filled_count == 2)) { + dma_channel_start(first_filled_channel); } } void __not_in_flash_func(isr_dma_0)(void) { for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) { uint32_t mask = 1 << i; - if ((dma_hw->intr & mask) == 0) { + if ((dma_hw->ints0 & mask) == 0) { continue; } // acknowledge interrupt early. Doing so late means that you could lose an @@ -476,11 +547,18 @@ void __not_in_flash_func(isr_dma_0)(void) { audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i]; // Record all channels whose DMA has completed; they need loading. dma->channels_to_load_mask |= mask; + // Disable the channel so that we don't play it without filling it. + dma_hw->ch[i].al1_ctrl &= ~DMA_CH0_CTRL_TRIG_EN_BITS; + // This is a noop if the callback is already queued. background_callback_add(&dma->callback, dma_callback_fun, (void *)dma); } - if (MP_STATE_PORT(background_pio)[i] != NULL) { - rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio)[i]; - rp2pio_statemachine_dma_complete(pio, i); + if (MP_STATE_PORT(background_pio_read)[i] != NULL) { + rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio_read)[i]; + rp2pio_statemachine_dma_complete_read(pio, i); + } + if (MP_STATE_PORT(background_pio_write)[i] != NULL) { + rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio_write)[i]; + rp2pio_statemachine_dma_complete_write(pio, i); } } } diff --git a/ports/raspberrypi/audio_dma.h b/ports/raspberrypi/audio_dma.h index 7c33a9e2ac319..cd892f5151b5c 100644 --- a/ports/raspberrypi/audio_dma.h +++ b/ports/raspberrypi/audio_dma.h @@ -9,11 +9,18 @@ #include "py/obj.h" #include "supervisor/background_callback.h" -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" +#include "hardware/dma.h" + +typedef enum { + AUDIO_DMA_OK, + AUDIO_DMA_DMA_BUSY, + AUDIO_DMA_MEMORY_ERROR, + AUDIO_DMA_SOURCE_ERROR, +} audio_dma_result; typedef struct { mp_obj_t sample; - uint8_t *buffer[2]; + uint8_t *buffer[2]; // Allocated through port_malloc on RP2350 so they are dma-able size_t buffer_length[2]; uint32_t channels_to_load_mask; uint32_t output_register_address; @@ -24,22 +31,17 @@ typedef struct { uint8_t sample_spacing; uint8_t output_resolution; // in bits uint8_t sample_resolution; // in bits + audio_dma_result dma_result; bool loop; bool single_channel_output; bool signed_to_unsigned; bool unsigned_to_signed; bool output_signed; bool playing_in_progress; + bool paused; bool swap_channel; } audio_dma_t; -typedef enum { - AUDIO_DMA_OK, - AUDIO_DMA_DMA_BUSY, - AUDIO_DMA_MEMORY_ERROR, -} audio_dma_result; - - void audio_dma_init(audio_dma_t *dma); void audio_dma_deinit(audio_dma_t *dma); void audio_dma_reset(void); diff --git a/ports/raspberrypi/bindings/cyw43/__init__.c b/ports/raspberrypi/bindings/cyw43/__init__.c index 83aacdc48aedd..93755d6ce1e04 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.c +++ b/ports/raspberrypi/bindings/cyw43/__init__.c @@ -12,11 +12,11 @@ #include "shared-bindings/microcontroller/Pin.h" #include "bindings/cyw43/__init__.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "lib/cyw43-driver/src/cyw43.h" -static int power_management_value = PM_DISABLED; +static uint32_t power_management_value = CONST_CYW43_DEFAULT_PM; void cyw43_enter_deep_sleep(void) { #define WL_REG_ON 23 @@ -35,6 +35,7 @@ void bindings_cyw43_wifi_enforce_pm(void) { //| in :py:mod:`board`. A `CywPin` can be used as a DigitalInOut, but not with other //| peripherals such as `PWMOut`.""" //| +//| MP_DEFINE_CONST_OBJ_TYPE( cyw43_pin_type, MP_QSTR_CywPin, @@ -42,14 +43,24 @@ MP_DEFINE_CONST_OBJ_TYPE( print, shared_bindings_microcontroller_pin_print ); +uint32_t cyw43_get_power_management_value(void) { + return power_management_value; +} + +void cyw43_set_power_management_value(uint32_t value) { + power_management_value = value; + bindings_cyw43_wifi_enforce_pm(); +} + //| PM_STANDARD: int -//| """The standard power management mode""" +//| """The default power management mode; same as PM_PERFORMANCE""" //| PM_AGGRESSIVE: int //| """Aggressive power management mode for optimal power usage at the cost of performance""" //| PM_PERFORMANCE: int //| """Performance power management mode where more power is used to increase performance""" //| PM_DISABLED: int -//| """Disable power management and always use highest power mode. CircuitPython sets this value at reset time, because it provides the best connectivity reliability.""" +//| """Disable power management and always use highest power mode.""" +//| //| //| def set_power_management(value: int) -> None: //| """Set the power management register @@ -80,10 +91,10 @@ MP_DEFINE_CONST_OBJ_TYPE( //| usage. //| """ //| +//| static mp_obj_t cyw43_set_power_management(const mp_obj_t value_in) { mp_int_t value = mp_obj_get_int(value_in); - power_management_value = value; - bindings_cyw43_wifi_enforce_pm(); + cyw43_set_power_management_value(value); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_1(cyw43_set_power_management_obj, cyw43_set_power_management); @@ -91,7 +102,8 @@ static MP_DEFINE_CONST_FUN_OBJ_1(cyw43_set_power_management_obj, cyw43_set_power //| def get_power_management() -> int: //| """Retrieve the power management register""" //| -static mp_obj_t cyw43_get_power_management() { +//| +static mp_obj_t cyw43_get_power_management(void) { return mp_obj_new_int(power_management_value); } static MP_DEFINE_CONST_FUN_OBJ_0(cyw43_get_power_management_obj, cyw43_get_power_management); @@ -122,10 +134,10 @@ static const mp_rom_map_elem_t cyw43_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_CywPin), MP_ROM_PTR(&cyw43_pin_type) }, { MP_ROM_QSTR(MP_QSTR_set_power_management), &cyw43_set_power_management_obj }, { MP_ROM_QSTR(MP_QSTR_get_power_management), &cyw43_get_power_management_obj }, - { MP_ROM_QSTR(MP_QSTR_PM_STANDARD), MP_ROM_INT(PM_STANDARD) }, - { MP_ROM_QSTR(MP_QSTR_PM_AGGRESSIVE), MP_ROM_INT(PM_AGGRESSIVE) }, - { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(PM_PERFORMANCE) }, - { MP_ROM_QSTR(MP_QSTR_PM_DISABLED), MP_ROM_INT(PM_DISABLED) }, + { MP_ROM_QSTR(MP_QSTR_PM_STANDARD), MP_ROM_INT(CONST_CYW43_DEFAULT_PM) }, + { MP_ROM_QSTR(MP_QSTR_PM_AGGRESSIVE), MP_ROM_INT(CONST_CYW43_AGGRESSIVE_PM) }, + { MP_ROM_QSTR(MP_QSTR_PM_PERFORMANCE), MP_ROM_INT(CONST_CYW43_PERFORMANCE_PM) }, + { MP_ROM_QSTR(MP_QSTR_PM_DISABLED), MP_ROM_INT(CONST_CYW43_NONE_PM) }, }; static MP_DEFINE_CONST_DICT(cyw43_module_globals, cyw43_module_globals_table); diff --git a/ports/raspberrypi/bindings/cyw43/__init__.h b/ports/raspberrypi/bindings/cyw43/__init__.h index 51657b075d263..70f9ec294fb30 100644 --- a/ports/raspberrypi/bindings/cyw43/__init__.h +++ b/ports/raspberrypi/bindings/cyw43/__init__.h @@ -16,21 +16,25 @@ const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj, qstr const mcu_pin_obj_t *validate_obj_is_free_pin_or_gpio29(mp_obj_t obj, qstr arg_name); const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj, qstr arg_name); -#define CONSTANT_CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \ +// This is equivalent to the code in cyw43.h, except that the values are computed at compile time. +// A `CONST_` prefix has been added to the computation function (expressed as a macro) and the values. + +#define CONST_cyw43_pm_value(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \ (li_assoc << 20 | /* listen interval sent to ap */ \ li_dtim_period << 16 | \ li_beacon_period << 12 | \ (pm2_sleep_ret_ms / 10) << 4 | /* cyw43_ll_wifi_pm multiplies this by 10 */ \ pm_mode /* CYW43_PM2_POWERSAVE_MODE etc */) -// CYW43_DEFAULT_PM (except a compile-time constant) -#define PM_STANDARD CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10) -// CYW43_AGGRESSIVE_PM (except a compile-time constant) -#define PM_AGGRESSIVE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 2000, 1, 1, 10) -// CYW43_PERFORMANCE_PM (except a compile-time constant) -#define PM_PERFORMANCE CONSTANT_CYW43_PM_VALUE(CYW43_PM2_POWERSAVE_MODE, 20, 1, 1, 1) -// The 0xa11140 magic value -#define PM_DISABLED CONSTANT_CYW43_PM_VALUE(CYW43_NO_POWERSAVE_MODE, 200, 1, 1, 10) +#define CONST_CYW43_DEFAULT_PM (CONST_CYW43_PERFORMANCE_PM) + +#define CONST_CYW43_NONE_PM (CONST_cyw43_pm_value(CYW43_NO_POWERSAVE_MODE, 10, 0, 0, 0)) + +#define CONST_CYW43_AGGRESSIVE_PM (CONST_cyw43_pm_value(CYW43_PM1_POWERSAVE_MODE, 10, 0, 0, 0)) + +#define CONST_CYW43_PERFORMANCE_PM (CONST_cyw43_pm_value(CYW43_PM2_POWERSAVE_MODE, 200, 1, 1, 10)) +extern uint32_t cyw43_get_power_management_value(void); +extern void cyw43_set_power_management_value(uint32_t value); extern void bindings_cyw43_wifi_enforce_pm(void); void cyw43_enter_deep_sleep(void); diff --git a/ports/raspberrypi/bindings/picodvi/Framebuffer.c b/ports/raspberrypi/bindings/picodvi/Framebuffer.c index 7a8ca40f9f61c..9cd66ad7e2a7b 100644 --- a/ports/raspberrypi/bindings/picodvi/Framebuffer.c +++ b/ports/raspberrypi/bindings/picodvi/Framebuffer.c @@ -41,28 +41,40 @@ //| This allocates a very large framebuffer and is most likely to succeed //| the earlier it is attempted. //| -//| Each dp and dn pair of pins must be neighboring, such as 19 and 20. -//| They must also be ordered the same way. In other words, dp must be -//| less than dn for all pairs or dp must be greater than dn for all pairs. +//| On RP2040, each dp and dn pair of pins must be neighboring, such as +//| 19 and 20. They must also be ordered the same way. In other words, +//| dp must be less than dn for all pairs or dp must be greater than dn +//| for all pairs. +//| +//| On RP2350, all pins must be an HSTX output but can be in any order. //| //| The framebuffer pixel format varies depending on color_depth: //| //| * 1 - Each bit is a pixel. Either white (1) or black (0). -//| * 2 - Each 2 bits is a pixels. Grayscale between white (0x3) and black (0x0). -//| * 4 - Each nibble is a pixels in RGB format. The fourth bit is ignored. (RP2350 only) -//| * 8 - Each byte is a pixels in RGB332 format. -//| * 16 - Each two bytes are a pixel in RGB565 format. +//| * 2 - Each two bits is a pixel. Grayscale between white (0x3) and black (0x0). +//| * 4 - Each nibble is a pixel in RGB format. The fourth bit is ignored. (RP2350 only) +//| * 8 - Each byte is a pixel in RGB332 format. +//| * 16 - Each two bytes is a pixel in RGB565 format. +//| * 32 - Each four bytes is a pixel in RGB888 format. The top byte is ignored. +//| +//| Output resolution support varies between the RP2040 and RP2350. +//| +//| On RP2040, two output resolutions are currently supported, 640x480 +//| and 800x480. Monochrome framebuffers (color_depth=1 or 2) must be +//| full resolution. Color framebuffers must be half resolution (320x240 +//| or 400x240) and pixels will be duplicated to create the signal. //| -//| Two output resolutions are currently supported, 640x480 and 800x480. -//| Monochrome framebuffers (color_depth=1 or 2) must be full resolution. -//| Color framebuffers must be half resolution (320x240 or 400x240) and -//| pixels will be duplicated to create the signal. +//| On RP2350, output resolution is either 640x480 or 720x400. Monochrome +//| framebuffers (color_depth=1 or 2) must be full resolution. 4-bit +//| color must also be full resolution. 8-bit color can be quarter, half +//| or full resolution. 16-bit color and 32-bit color must be quarter or +//| half resolution due to internal RAM limitations. //| //| A Framebuffer is often used in conjunction with a //| `framebufferio.FramebufferDisplay`. //| -//| :param int width: the width of the target display signal. Only 320, 400, 640 or 800 is currently supported depending on color_depth. -//| :param int height: the height of the target display signal. Only 240 or 480 is currently supported depending on color_depth. +//| :param int width: the width of the source framebuffer. Support varies with chipset. +//| :param int height: the height of the source framebuffer. Support varies with chipset. //| :param ~microcontroller.Pin clk_dp: the positive clock signal pin //| :param ~microcontroller.Pin clk_dn: the negative clock signal pin //| :param ~microcontroller.Pin red_dp: the positive red signal pin @@ -72,8 +84,9 @@ //| :param ~microcontroller.Pin blue_dp: the positive blue signal pin //| :param ~microcontroller.Pin blue_dn: the negative blue signal pin //| :param int color_depth: the color depth of the framebuffer in bits. 1, 2 for grayscale -//| and 8 or 16 for color +//| and 4 (RP2350 only), 8 or 16 for color, 32 for color (RP2350 only) //| """ +//| static mp_obj_t picodvi_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_width, ARG_height, ARG_clk_dp, ARG_clk_dn, ARG_red_dp, ARG_red_dn, ARG_green_dp, @@ -102,7 +115,7 @@ static mp_obj_t picodvi_framebuffer_make_new(const mp_obj_type_t *type, size_t n mp_uint_t width = (mp_uint_t)mp_arg_validate_int_min(args[ARG_width].u_int, 0, MP_QSTR_width); mp_uint_t height = (mp_uint_t)mp_arg_validate_int_min(args[ARG_height].u_int, 0, MP_QSTR_height); mp_uint_t color_depth = args[ARG_color_depth].u_int; - if (color_depth != 1 && color_depth != 2 && color_depth != 4 && color_depth != 8 && color_depth != 16) { + if (color_depth != 1 && color_depth != 2 && color_depth != 4 && color_depth != 8 && color_depth != 16 && color_depth != 32) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_color_depth); } common_hal_picodvi_framebuffer_construct(self, @@ -125,6 +138,7 @@ static mp_obj_t picodvi_framebuffer_make_new(const mp_obj_type_t *type, size_t n //| `picodvi.Framebuffer` instance. After deinitialization, no further operations //| may be performed.""" //| ... +//| static mp_obj_t picodvi_framebuffer_deinit(mp_obj_t self_in) { picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in; common_hal_picodvi_framebuffer_deinit(self); @@ -153,6 +167,7 @@ MP_PROPERTY_GETTER(picodvi_framebuffer_width_obj, //| height: int //| """The width of the framebuffer, in pixels. It may be doubled for output.""" //| +//| static mp_obj_t picodvi_framebuffer_get_height(mp_obj_t self_in) { picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in; check_for_deinit(self); @@ -163,11 +178,24 @@ MP_DEFINE_CONST_FUN_OBJ_1(picodvi_framebuffer_get_height_obj, picodvi_framebuffe MP_PROPERTY_GETTER(picodvi_framebuffer_height_obj, (mp_obj_t)&picodvi_framebuffer_get_height_obj); +//| color_depth: int +//| """The color depth of the framebuffer.""" +static mp_obj_t picodvi_framebuffer_get_color_depth(mp_obj_t self_in) { + picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in; + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_picodvi_framebuffer_get_color_depth(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(picodvi_framebuffer_get_color_depth_obj, picodvi_framebuffer_get_color_depth); +MP_PROPERTY_GETTER(picodvi_framebuffer_color_depth_obj, + (mp_obj_t)&picodvi_framebuffer_get_color_depth_obj); + + static const mp_rom_map_elem_t picodvi_framebuffer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&picodvi_framebuffer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&picodvi_framebuffer_width_obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&picodvi_framebuffer_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_color_depth), MP_ROM_PTR(&picodvi_framebuffer_color_depth_obj) }, }; static MP_DEFINE_CONST_DICT(picodvi_framebuffer_locals_dict, picodvi_framebuffer_locals_dict_table); @@ -207,7 +235,7 @@ static int picodvi_framebuffer_get_bytes_per_cell_proto(mp_obj_t self_in) { } static int picodvi_framebuffer_get_native_frames_per_second_proto(mp_obj_t self_in) { - return 60; + return common_hal_picodvi_framebuffer_get_native_frames_per_second(self_in); } static bool picodvi_framebuffer_get_pixels_in_byte_share_row_proto(mp_obj_t self_in) { diff --git a/ports/raspberrypi/bindings/picodvi/Framebuffer.h b/ports/raspberrypi/bindings/picodvi/Framebuffer.h index 7cb335e91e767..7eb7780ee49b8 100644 --- a/ports/raspberrypi/bindings/picodvi/Framebuffer.h +++ b/ports/raspberrypi/bindings/picodvi/Framebuffer.h @@ -12,6 +12,9 @@ extern const mp_obj_type_t picodvi_framebuffer_type; +bool common_hal_picodvi_framebuffer_preflight( + mp_uint_t width, mp_uint_t height, + mp_uint_t color_depth); void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, mp_uint_t width, mp_uint_t height, const mcu_pin_obj_t *clk_dp, const mcu_pin_obj_t *clk_dn, @@ -26,5 +29,6 @@ int common_hal_picodvi_framebuffer_get_width(picodvi_framebuffer_obj_t *self); int common_hal_picodvi_framebuffer_get_height(picodvi_framebuffer_obj_t *self); int common_hal_picodvi_framebuffer_get_row_stride(picodvi_framebuffer_obj_t *self); int common_hal_picodvi_framebuffer_get_color_depth(picodvi_framebuffer_obj_t *self); +int common_hal_picodvi_framebuffer_get_native_frames_per_second(picodvi_framebuffer_obj_t *self); bool common_hal_picodvi_framebuffer_get_grayscale(picodvi_framebuffer_obj_t *self); mp_int_t common_hal_picodvi_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.c b/ports/raspberrypi/bindings/rp2pio/StateMachine.c index 032b67db15949..398685be8a07b 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.c +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.c @@ -21,7 +21,18 @@ #include "py/objproperty.h" #include "py/runtime.h" - +//| import memorymap +//| +//| FifoType = Literal["auto", "txrx", "tx", "rx", "txput", "txget", "putget"] +//| """A type representing one of the strings ``"auto"``, ``"txrx"``, ``"tx"``, ``"rx"``, ``"txput"``, ``"txget"`` or ``"putget"``. These values are supported on RP2350. For type-checking only, not actually defined in CircuitPython.""" +//| FifoType_piov0 = Literal["auto", "txrx", "tx", "rx"] +//| """A type representing one of the strings ``"auto"``, ``"txrx"``, ``"tx"``, or ``"rx"``. These values are supported on both RP2350 and RP2040. For type-checking only, not actually defined in CircuitPython.""" +//| MovStatusType = Literal["txfifo", "rxfifo", "irq"] +//| """A type representing one of the strings ``"txfifo"``, ``"rxfifo"``, or ``"irq"``. These values are supported on RP2350. For type-checking only, not actually defined in CircuitPython.""" +//| MovStatusType_piov0 = Literal["txfifo", "rxfifo"] +//| """A type representing one of the strings ``"txfifo"``, ``"rxfifo"``. These values are supported on RP2350 and RP2040. For type-checking only, not actually defined in CircuitPython.""" +//| +//| //| class StateMachine: //| """A single PIO StateMachine //| @@ -41,6 +52,7 @@ //| program: ReadableBuffer, //| frequency: int, //| *, +//| pio_version: int = 0, //| may_exec: Optional[ReadableBuffer] = None, //| init: Optional[ReadableBuffer] = None, //| first_out_pin: Optional[microcontroller.Pin] = None, @@ -57,6 +69,7 @@ //| initial_set_pin_direction: int = 0x1F, //| first_sideset_pin: Optional[microcontroller.Pin] = None, //| sideset_pin_count: int = 1, +//| sideset_pindirs: bool = False, //| initial_sideset_pin_state: int = 0, //| initial_sideset_pin_direction: int = 0x1F, //| sideset_enable: bool = False, @@ -74,9 +87,14 @@ //| wrap_target: int = 0, //| wrap: int = -1, //| offset: int = -1, +//| fifo_type: FifoType = "auto", +//| mov_status_type: MovStatusType = "txfifo", +//| mov_status_n: int = 0, //| ) -> None: //| """Construct a StateMachine object on the given pins with the given program. //| +//| The following parameters are usually supplied directly: +//| //| :param ReadableBuffer program: the program to run with the state machine //| :param int frequency: the target clock frequency of the state machine. Actual may be less. Use 0 for system clock speed. //| :param ReadableBuffer init: a program to run once at start up. This is run after program @@ -86,65 +104,85 @@ //| for instance, if there is no ``in`` or ``push`` instruction, then the `StateMachine` is configured without a receive FIFO. //| In this case, passing a ``may_exec`` program containing an ``in`` instruction such as ``in x``, a receive FIFO will be configured. //| :param ~microcontroller.Pin first_out_pin: the first pin to use with the OUT instruction -//| :param int out_pin_count: the count of consecutive pins to use with OUT starting at first_out_pin //| :param int initial_out_pin_state: the initial output value for out pins starting at first_out_pin //| :param int initial_out_pin_direction: the initial output direction for out pins starting at first_out_pin //| :param ~microcontroller.Pin first_in_pin: the first pin to use with the IN instruction -//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin //| :param int pull_in_pin_up: a 1-bit in this mask sets pull up on the corresponding in pin //| :param int pull_in_pin_down: a 1-bit in this mask sets pull down on the corresponding in pin. Setting both pulls enables a "bus keep" function, i.e. a weak pull to whatever is current high/low state of GPIO. //| :param ~microcontroller.Pin first_set_pin: the first pin to use with the SET instruction -//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin //| :param int initial_set_pin_state: the initial output value for set pins starting at first_set_pin //| :param int initial_set_pin_direction: the initial output direction for set pins starting at first_set_pin //| :param ~microcontroller.Pin first_sideset_pin: the first pin to use with a side set -//| :param int sideset_pin_count: the count of consecutive pins to use with a side set starting at first_sideset_pin. Does not include sideset enable //| :param int initial_sideset_pin_state: the initial output value for sideset pins starting at first_sideset_pin //| :param int initial_sideset_pin_direction: the initial output direction for sideset pins starting at first_sideset_pin //| :param bool sideset_enable: True when the top sideset bit is to enable. This should be used with the ".side_set # opt" directive //| :param ~microcontroller.Pin jmp_pin: the pin which determines the branch taken by JMP PIN instructions //| :param ~digitalio.Pull jmp_pin_pull: The pull value for the jmp pin, default is no pull. //| :param bool exclusive_pin_use: When True, do not share any pins with other state machines. Pins are never shared with other peripherals -//| :param bool auto_pull: When True, automatically load data from the tx FIFO into the -//| output shift register (OSR) when an OUT instruction shifts more than pull_threshold bits -//| :param int pull_threshold: Number of bits to shift before loading a new value into the OSR from the tx FIFO -//| :param bool out_shift_right: When True, data is shifted out the right side (LSB) of the -//| OSR. It is shifted out the left (MSB) otherwise. NOTE! This impacts data alignment -//| when the number of bytes is not a power of two (1, 2 or 4 bytes). //| :param bool wait_for_txstall: When True, writing data out will block until the TX FIFO and OSR are empty //| and an instruction is stalled waiting for more data. When False, data writes won't //| wait for the OSR to empty (only the TX FIFO) so make sure you give enough time before //| deiniting or stopping the state machine. -//| :param bool auto_push: When True, automatically save data from input shift register -//| (ISR) into the rx FIFO when an IN instruction shifts more than push_threshold bits -//| :param int push_threshold: Number of bits to shift before saving the ISR value to the RX FIFO -//| :param bool in_shift_right: When True, data is shifted into the right side (LSB) of the -//| ISR. It is shifted into the left (MSB) otherwise. NOTE! This impacts data alignment -//| when the number of bytes is not a power of two (1, 2 or 4 bytes). //| :param bool user_interruptible: When True (the default), //| `write()`, `readinto()`, and `write_readinto()` can be interrupted by a ctrl-C. //| This is useful when developing a PIO program: if there is an error in the program //| that causes an infinite loop, you will be able to interrupt the loop. //| However, if you are writing to a device that can get into a bad state if a read or write //| is interrupted, you may want to set this to False after your program has been vetted. +//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded. +//| The default value, -1, allows the program to be loaded at any offset. +//| This is appropriate for most programs. +//| +//| The following parameters are usually set via assembler directives and passed using a ``**program.pio_kwargs`` argument but may also be specified directly: +//| +//| :param int out_pin_count: the count of consecutive pins to use with OUT starting at first_out_pin +//| :param int in_pin_count: the count of consecutive pins to use with IN starting at first_in_pin +//| :param int set_pin_count: the count of consecutive pins to use with SET starting at first_set_pin +//| :param int sideset_pin_count: the count of consecutive pins to use with a side set starting at first_sideset_pin. Does not include sideset enable +//| :param bool sideset_pindirs: `True` to indicate that the side set values should be applied to the PINDIRs and not the PINs +//| :param int pio_version: The version of the PIO peripheral required by the program. The constructor will raise an error if the actual hardware is not compatible with this program version. +//| :param bool auto_push: When True, automatically save data from input shift register +//| (ISR) into the rx FIFO when an IN instruction shifts more than push_threshold bits +//| :param int push_threshold: Number of bits to shift before saving the ISR value to the RX FIFO +//| :param bool in_shift_right: When True, data is shifted into the right side (LSB) of the +//| ISR. It is shifted into the left (MSB) otherwise. NOTE! This impacts data alignment +//| when the number of bytes is not a power of two (1, 2 or 4 bytes). +//| :param bool auto_pull: When True, automatically load data from the tx FIFO into the +//| output shift register (OSR) when an OUT instruction shifts more than pull_threshold bits +//| :param int pull_threshold: Number of bits to shift before loading a new value into the OSR from the tx FIFO +//| :param bool out_shift_right: When True, data is shifted out the right side (LSB) of the +//| OSR. It is shifted out the left (MSB) otherwise. NOTE! This impacts data alignment +//| when the number of bytes is not a power of two (1, 2 or 4 bytes). //| :param int wrap_target: The target instruction number of automatic wrap. Defaults to the first instruction of the program. //| :param int wrap: The instruction after which to wrap to the ``wrap`` //| instruction. As a special case, -1 (the default) indicates the //| last instruction of the program. -//| :param int offset: A specific offset in the state machine's program memory where the program must be loaded. -//| The default value, -1, allows the program to be loaded at any offset. -//| This is appropriate for most programs. +//| :param FifoType fifo_type: How the program accessess the FIFOs. PIO version 0 in the RP2040 only supports a subset of values, `FifoType_piov0`. +//| :param MovStatusType mov_status_type: What condition the ``mov status`` instruction checks. PIO version 0 in the RP2040 only supports a subset of values, `MovStatusType_piov0`. +//| :param MovStatusType mov_status_n: The FIFO depth or IRQ the ``mov status`` instruction checks for. For ``mov_status irq`` this includes the encoding of the ``next``/``prev`` selection bits. //| """ //| ... +//| + +static int one_of(qstr_short_t what, mp_obj_t arg, size_t n_options, const qstr_short_t options[], const int values[]) { + for (size_t i = 0; i < n_options; i++) { + mp_obj_t option_str = MP_OBJ_NEW_QSTR(options[i]); + if (mp_obj_equal(arg, option_str)) { + return values[i]; + } + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), what); +} static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { rp2pio_statemachine_obj_t *self = mp_obj_malloc(rp2pio_statemachine_obj_t, &rp2pio_statemachine_type); - enum { ARG_program, ARG_frequency, ARG_init, ARG_may_exec, + enum { ARG_program, ARG_frequency, ARG_init, ARG_pio_version, ARG_may_exec, ARG_first_out_pin, ARG_out_pin_count, ARG_initial_out_pin_state, ARG_initial_out_pin_direction, ARG_first_in_pin, ARG_in_pin_count, ARG_pull_in_pin_up, ARG_pull_in_pin_down, ARG_first_set_pin, ARG_set_pin_count, ARG_initial_set_pin_state, ARG_initial_set_pin_direction, - ARG_first_sideset_pin, ARG_sideset_pin_count, ARG_initial_sideset_pin_state, ARG_initial_sideset_pin_direction, + ARG_first_sideset_pin, ARG_sideset_pin_count, ARG_sideset_pindirs, + ARG_initial_sideset_pin_state, ARG_initial_sideset_pin_direction, ARG_sideset_enable, ARG_jmp_pin, ARG_jmp_pin_pull, ARG_exclusive_pin_use, @@ -154,11 +192,15 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n ARG_user_interruptible, ARG_wrap_target, ARG_wrap, - ARG_offset, }; + ARG_offset, + ARG_fifo_type, + ARG_mov_status_type, + ARG_mov_status_n, }; static const mp_arg_t allowed_args[] = { { MP_QSTR_program, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_frequency, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_init, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_pio_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_may_exec, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_first_out_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -178,6 +220,7 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n { MP_QSTR_first_sideset_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_sideset_pin_count, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_sideset_pindirs, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_initial_sideset_pin_state, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_initial_sideset_pin_direction, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x1f} }, @@ -198,11 +241,18 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n { MP_QSTR_wrap_target, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_wrap, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + + { MP_QSTR_offset, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PIO_ANY_OFFSET} }, + + { MP_QSTR_fifo_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_ROM_QSTR(MP_QSTR_auto) } }, + { MP_QSTR_mov_status_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_ROM_QSTR(MP_QSTR_txfifo) } }, + { MP_QSTR_mov_status_n, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + (void)mp_arg_validate_int_max(args[ARG_pio_version].u_int, PICO_PIO_VERSION, MP_QSTR_out_pin_count); + mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_program].u_obj, &bufinfo, MP_BUFFER_READ); @@ -254,30 +304,62 @@ static mp_obj_t rp2pio_statemachine_make_new(const mp_obj_type_t *type, size_t n int wrap = args[ARG_wrap].u_int; int wrap_target = args[ARG_wrap_target].u_int; + const qstr_short_t fifo_alternatives[] = { MP_QSTR_auto, MP_QSTR_txrx, MP_QSTR_tx, MP_QSTR_rx, + #if PICO_PIO_VERSION > 0 + MP_QSTR_txput, MP_QSTR_txget, MP_QSTR_putget + #endif + }; + const int fifo_values[] = { PIO_FIFO_JOIN_AUTO, PIO_FIFO_JOIN_NONE, PIO_FIFO_JOIN_TX, PIO_FIFO_JOIN_RX, + #if PICO_PIO_VERSION > 0 + PIO_FIFO_JOIN_TXPUT, PIO_FIFO_JOIN_TXGET, PIO_FIFO_JOIN_PUTGET + #endif + }; + MP_STATIC_ASSERT(MP_ARRAY_SIZE(fifo_alternatives) == MP_ARRAY_SIZE(fifo_values)); + + int fifo_type = one_of(MP_QSTR_fifo_type, args[ARG_fifo_type].u_obj, MP_ARRAY_SIZE(fifo_alternatives), fifo_alternatives, fifo_values); + + const qstr_short_t mov_status_alternatives[] = { MP_QSTR_txfifo, MP_QSTR_rxfifo, + #if PICO_PIO_VERSION > 0 + MP_QSTR_IRQ + #endif + }; + const int mov_status_values[] = { STATUS_TX_LESSTHAN, STATUS_RX_LESSTHAN, + #if PICO_PIO_VERSION > 0 + STATUS_IRQ_SET + #endif + }; + MP_STATIC_ASSERT(MP_ARRAY_SIZE(mov_status_alternatives) == MP_ARRAY_SIZE(mov_status_values)); + int mov_status_type = one_of(MP_QSTR_mov_status_type, args[ARG_mov_status_type].u_obj, MP_ARRAY_SIZE(mov_status_alternatives), mov_status_alternatives, mov_status_values); + common_hal_rp2pio_statemachine_construct(self, bufinfo.buf, bufinfo.len / 2, args[ARG_frequency].u_int, init_bufinfo.buf, init_bufinfo.len / 2, may_exec_bufinfo.buf, may_exec_bufinfo.len / 2, - first_out_pin, out_pin_count, args[ARG_initial_out_pin_state].u_int, args[ARG_initial_out_pin_direction].u_int, - first_in_pin, in_pin_count, args[ARG_pull_in_pin_up].u_int, args[ARG_pull_in_pin_down].u_int, - first_set_pin, set_pin_count, args[ARG_initial_set_pin_state].u_int, args[ARG_initial_set_pin_direction].u_int, - first_sideset_pin, sideset_pin_count, args[ARG_initial_sideset_pin_state].u_int, args[ARG_initial_sideset_pin_direction].u_int, + first_out_pin, out_pin_count, PIO_PINMASK32_FROM_VALUE(args[ARG_initial_out_pin_state].u_int), PIO_PINMASK32_FROM_VALUE(args[ARG_initial_out_pin_direction].u_int), + first_in_pin, in_pin_count, PIO_PINMASK32_FROM_VALUE(args[ARG_pull_in_pin_up].u_int), PIO_PINMASK32_FROM_VALUE(args[ARG_pull_in_pin_down].u_int), + first_set_pin, set_pin_count, PIO_PINMASK32_FROM_VALUE(args[ARG_initial_set_pin_state].u_int), PIO_PINMASK32_FROM_VALUE(args[ARG_initial_set_pin_direction].u_int), + first_sideset_pin, sideset_pin_count, args[ARG_sideset_pindirs].u_bool, + PIO_PINMASK32_FROM_VALUE(args[ARG_initial_sideset_pin_state].u_int), PIO_PINMASK32_FROM_VALUE(args[ARG_initial_sideset_pin_direction].u_int), args[ARG_sideset_enable].u_bool, jmp_pin, jmp_pin_pull, - 0, + PIO_PINMASK_FROM_VALUE(0), // wait_gpio_mask args[ARG_exclusive_pin_use].u_bool, args[ARG_auto_pull].u_bool, pull_threshold, args[ARG_out_shift_right].u_bool, args[ARG_wait_for_txstall].u_bool, args[ARG_auto_push].u_bool, push_threshold, args[ARG_in_shift_right].u_bool, args[ARG_user_interruptible].u_bool, - wrap_target, wrap, args[ARG_offset].u_int); + wrap_target, wrap, args[ARG_offset].u_int, + fifo_type, + mov_status_type, args[ARG_mov_status_n].u_int + ); return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Turn off the state machine and release its resources.""" //| ... +//| static mp_obj_t rp2pio_statemachine_obj_deinit(mp_obj_t self_in) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_rp2pio_statemachine_deinit(self); @@ -289,17 +371,13 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_deinit_obj, rp2pio_statemachine_ob //| """No-op used by Context Managers. //| Provided by context manager helper.""" //| ... +//| //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t rp2pio_statemachine_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_rp2pio_statemachine_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2pio_statemachine_obj___exit___obj, 4, 4, rp2pio_statemachine_obj___exit__); +//| static void check_for_deinit(rp2pio_statemachine_obj_t *self) { @@ -311,6 +389,7 @@ static void check_for_deinit(rp2pio_statemachine_obj_t *self) { //| def restart(self) -> None: //| """Resets this state machine, runs any init and enables the clock.""" //| ... +//| // TODO: "and any others given. They must share an underlying PIO. An exception will be raised otherwise."" static mp_obj_t rp2pio_statemachine_restart(mp_obj_t self_obj) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_obj); @@ -329,6 +408,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_restart_obj, rp2pio_statemachine_r //| This can be used to output internal state to the RX FIFO and then //| read with `readinto`.""" //| ... +//| static mp_obj_t rp2pio_statemachine_run(mp_obj_t self_obj, mp_obj_t instruction_obj) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_obj); check_for_deinit(self); @@ -347,6 +427,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(rp2pio_statemachine_run_obj, rp2pio_statemachine_run); //| def stop(self) -> None: //| """Stops the state machine clock. Use `restart` to enable it.""" //| ... +//| static mp_obj_t rp2pio_statemachine_stop(mp_obj_t self_obj) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_obj); check_for_deinit(self); @@ -378,6 +459,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_obj, rp2pio_statemachine_stop //| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)`` //| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order""" //| ... +//| static mp_obj_t rp2pio_statemachine_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_swap }; static const mp_arg_t allowed_args[] = { @@ -426,6 +508,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine //| once: Optional[ReadableBuffer] = None, //| *, //| loop: Optional[ReadableBuffer] = None, +//| loop2: Optional[ReadableBuffer] = None, //| swap: bool = False, //| ) -> None: //| """Write data to the TX fifo in the background, with optional looping. @@ -434,7 +517,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine //| This means that any ``once`` or ``loop`` buffer will be written at least once. //| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns. //| The ``once`` buffer (if specified) will be written just once. -//| Finally, the ``loop`` buffer (if specified) will continue being looped indefinitely. +//| Finally, the ``loop`` and/or ``loop2`` buffer (if specified) will continue being looped indefinitely. If both ``loop`` and ``loop2`` are specified, they will alternate. //| //| Writes to the FIFO will match the input buffer's element size. For example, bytearray elements //| will perform 8 bit writes to the PIO FIFO. The RP2040's memory bus will duplicate the value into @@ -461,14 +544,16 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_obj, 2, rp2pio_statemachine //| //| :param ~Optional[circuitpython_typing.ReadableBuffer] once: Data to be written once //| :param ~Optional[circuitpython_typing.ReadableBuffer] loop: Data to be written repeatedly +//| :param ~Optional[circuitpython_typing.ReadableBuffer] loop2: Data to be written repeatedly //| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order //| """ //| ... +//| -static void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_bytes) { +static void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_bytes, mp_uint_t direction) { if (obj != mp_const_none) { info->obj = obj; - mp_get_buffer_raise(obj, &info->info, MP_BUFFER_READ); + mp_get_buffer_raise(obj, &info->info, direction); size_t stride = mp_binary_get_size('@', info->info.typecode, NULL); if (stride > 4) { mp_raise_ValueError(MP_ERROR_TEXT("Buffer elements must be 4 bytes long or less")); @@ -483,27 +568,29 @@ static void fill_buf_info(sm_buf_info *info, mp_obj_t obj, size_t *stride_in_byt } static mp_obj_t rp2pio_statemachine_background_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_once, ARG_loop, ARG_swap }; + enum { ARG_once, ARG_loop, ARG_loop2, ARG_swap }; static const mp_arg_t allowed_args[] = { { MP_QSTR_once, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_loop, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, - { MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_loop2, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); check_for_deinit(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - sm_buf_info once_info; - sm_buf_info loop_info; size_t stride_in_bytes = 0; - fill_buf_info(&once_info, args[ARG_once].u_obj, &stride_in_bytes); - fill_buf_info(&loop_info, args[ARG_loop].u_obj, &stride_in_bytes); + + fill_buf_info(&self->once_write_buf_info, args[ARG_once].u_obj, &stride_in_bytes, MP_BUFFER_READ); + fill_buf_info(&self->loop_write_buf_info, args[ARG_loop].u_obj, &stride_in_bytes, MP_BUFFER_READ); + fill_buf_info(&self->loop2_write_buf_info, args[ARG_loop2].u_obj, &stride_in_bytes, MP_BUFFER_READ); + if (!stride_in_bytes) { return mp_const_none; } - bool ok = common_hal_rp2pio_statemachine_background_write(self, &once_info, &loop_info, stride_in_bytes, args[ARG_swap].u_bool); + bool ok = common_hal_rp2pio_statemachine_background_write(self, stride_in_bytes, args[ARG_swap].u_bool); if (mp_hal_is_interrupted()) { return mp_const_none; @@ -519,6 +606,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_background_write_obj, 1, rp2pio_s //| """Immediately stop a background write, if one is in progress. Any //| DMA in progress is halted, but items already in the TX FIFO are not //| affected.""" +//| static mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); bool ok = common_hal_rp2pio_statemachine_stop_background_write(self); @@ -532,6 +620,7 @@ static mp_obj_t rp2pio_statemachine_obj_stop_background_write(mp_obj_t self_in) } MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_background_write_obj, rp2pio_statemachine_obj_stop_background_write); + //| writing: bool //| """Returns True if a background write is in progress""" static mp_obj_t rp2pio_statemachine_obj_get_writing(mp_obj_t self_in) { @@ -540,30 +629,154 @@ static mp_obj_t rp2pio_statemachine_obj_get_writing(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_writing_obj, rp2pio_statemachine_obj_get_writing); -const mp_obj_property_t rp2pio_statemachine_writing_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&rp2pio_statemachine_get_writing_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; - +MP_PROPERTY_GETTER(rp2pio_statemachine_writing_obj, + (mp_obj_t)&rp2pio_statemachine_get_writing_obj); +//| pending_write: int //| pending: int //| """Returns the number of pending buffers for background writing. //| -//| If the number is 0, then a `StateMachine.background_write` call will not block.""" -static mp_obj_t rp2pio_statemachine_obj_get_pending(mp_obj_t self_in) { +//| If the number is 0, then a `StateMachine.background_write` call will not block. +//| Note that `pending` is a deprecated alias for `pending_write` and will be removed +//| in a future version of CircuitPython.""" +//| + + +static mp_obj_t rp2pio_statemachine_obj_get_pending_write(mp_obj_t self_in) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_rp2pio_statemachine_get_pending(self)); + return mp_obj_new_int(common_hal_rp2pio_statemachine_get_pending_write(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pending_obj, rp2pio_statemachine_obj_get_pending); +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pending_write_obj, rp2pio_statemachine_obj_get_pending_write); -const mp_obj_property_t rp2pio_statemachine_pending_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&rp2pio_statemachine_get_pending_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; +MP_PROPERTY_GETTER(rp2pio_statemachine_pending_obj, + (mp_obj_t)&rp2pio_statemachine_get_pending_write_obj); + +MP_PROPERTY_GETTER(rp2pio_statemachine_pending_write_obj, + (mp_obj_t)&rp2pio_statemachine_get_pending_write_obj); + + +// ================================================================================================================================= + +//| def background_read( +//| self, +//| once: Optional[WriteableBuffer] = None, +//| *, +//| loop: Optional[WriteableBuffer] = None, +//| loop2: Optional[WriteableBuffer] = None, +//| swap: bool = False, +//| ) -> None: +//| """Read data from the RX fifo in the background, with optional looping. +//| +//| First, if any previous ``once`` or ``loop`` buffer has not been started, this function blocks until they have been started. +//| This means that any ``once`` or ``loop`` buffer will be read at least once. +//| Then the ``once`` and/or ``loop`` buffers are queued. and the function returns. +//| The ``once`` buffer (if specified) will be read just once. +//| Finally, the ``loop`` and/or ``loop2`` buffer (if specified) will continue being read indefinitely. If both ``loop`` and ``loop2`` are specified, they will alternate. +//| +//| Reads from the FIFO will match the input buffer's element size. For example, bytearray elements +//| will perform 8 bit reads from the PIO FIFO. The RP2040's memory bus will duplicate the value into +//| the other byte positions. So, pulling more data in the PIO assembly will read the duplicated values. +//| +//| To perform 16 or 32 bits reads from the FIFO use an `array.array` with a type code of the desired +//| size, or use `memoryview.cast` to change the interpretation of an +//| existing buffer. To receive just part of a larger buffer, slice a `memoryview` +//| of it. +//| +//| Most use cases will probably only use one of ``once`` or ``loop``. +//| +//| Having neither ``once`` nor ``loop`` terminates an existing +//| background looping read after exactly a whole loop. This is in contrast to +//| `stop_background_read`, which interrupts an ongoing DMA operation. +//| +//| :param ~Optional[circuitpython_typing.WriteableBuffer] once: Data to be read once +//| :param ~Optional[circuitpython_typing.WriteableBuffer] loop: Data to be read repeatedly +//| :param ~Optional[circuitpython_typing.WriteableBuffer] loop2: Data to be read repeatedly +//| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order +//| """ +//| ... +//| + + +static mp_obj_t rp2pio_statemachine_background_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_once, ARG_loop, ARG_loop2, ARG_swap }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_once, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_loop, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_loop2, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_swap, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + size_t stride_in_bytes = 0; + + fill_buf_info(&self->once_read_buf_info, args[ARG_once].u_obj, &stride_in_bytes, MP_BUFFER_WRITE); + fill_buf_info(&self->loop_read_buf_info, args[ARG_loop].u_obj, &stride_in_bytes, MP_BUFFER_WRITE); + fill_buf_info(&self->loop2_read_buf_info, args[ARG_loop2].u_obj, &stride_in_bytes, MP_BUFFER_WRITE); + + if (!stride_in_bytes) { + return mp_const_none; + } + + bool ok = common_hal_rp2pio_statemachine_background_read(self, stride_in_bytes, args[ARG_swap].u_bool); + + if (mp_hal_is_interrupted()) { + return mp_const_none; + } + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_background_read_obj, 1, rp2pio_statemachine_background_read); + +//| def stop_background_read(self) -> None: +//| """Immediately stop a background read, if one is in progress. Any +//| DMA in progress is halted, but items already in the RX FIFO are not +//| affected.""" +//| +static mp_obj_t rp2pio_statemachine_obj_stop_background_read(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool ok = common_hal_rp2pio_statemachine_stop_background_read(self); + if (mp_hal_is_interrupted()) { + return mp_const_none; + } + if (!ok) { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_stop_background_read_obj, rp2pio_statemachine_obj_stop_background_read); + +//| reading: bool +//| """Returns True if a background read is in progress""" +static mp_obj_t rp2pio_statemachine_obj_get_reading(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_bool(common_hal_rp2pio_statemachine_get_reading(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_reading_obj, rp2pio_statemachine_obj_get_reading); + +MP_PROPERTY_GETTER(rp2pio_statemachine_reading_obj, + (mp_obj_t)&rp2pio_statemachine_get_reading_obj); + +//| pending_read: int +//| """Returns the number of pending buffers for background reading. +//| +//| If the number is 0, then a `StateMachine.background_read` call will not block.""" +//| +static mp_obj_t rp2pio_statemachine_obj_get_pending_read(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_int(common_hal_rp2pio_statemachine_get_pending_read(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pending_read_obj, rp2pio_statemachine_obj_get_pending_read); + +MP_PROPERTY_GETTER(rp2pio_statemachine_pending_read_obj, + (mp_obj_t)&rp2pio_statemachine_get_pending_read_obj); + + +// ================================================================================================================================= //| def readinto( //| self, @@ -589,6 +802,7 @@ const mp_obj_property_t rp2pio_statemachine_pending_obj = { //| :param int end: End of the slice; this index is not included. Defaults to ``len(buffer)`` //| :param bool swap: For 2- and 4-byte elements, swap (reverse) the byte order""" //| ... +//| static mp_obj_t rp2pio_statemachine_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_swap }; @@ -659,6 +873,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_readinto_obj, 2, rp2pio_statemach //| :param bool swap_in: For 2- and 4-rx elements, swap (reverse) the byte order for the buffer being received (read) //| """ //| ... +//| static mp_obj_t rp2pio_statemachine_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer_out, ARG_buffer_in, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end, ARG_swap_out, ARG_swap_in }; @@ -724,6 +939,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(rp2pio_statemachine_write_readinto_obj, 2, rp2pio_sta //| def clear_rxfifo(self) -> None: //| """Clears any unread bytes in the rxfifo.""" //| ... +//| static mp_obj_t rp2pio_statemachine_obj_clear_rxfifo(mp_obj_t self_in) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_rp2pio_statemachine_clear_rxfifo(self); @@ -734,6 +950,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_clear_rxfifo_obj, rp2pio_statemach //| def clear_txstall(self) -> None: //| """Clears the txstall flag.""" //| ... +//| static mp_obj_t rp2pio_statemachine_obj_clear_txstall(mp_obj_t self_in) { rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_rp2pio_statemachine_clear_txstall(self); @@ -777,13 +994,8 @@ static mp_obj_t rp2pio_statemachine_obj_get_txstall(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_txstall_obj, rp2pio_statemachine_obj_get_txstall); -const mp_obj_property_t rp2pio_statemachine_txstall_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&rp2pio_statemachine_get_txstall_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; - +MP_PROPERTY_GETTER(rp2pio_statemachine_txstall_obj, + (mp_obj_t)&rp2pio_statemachine_get_txstall_obj); //| rxstall: bool //| """True when the state machine has stalled due to a full RX FIFO since the last @@ -813,10 +1025,102 @@ MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_in_waiting_obj, rp2pio_statema MP_PROPERTY_GETTER(rp2pio_statemachine_in_waiting_obj, (mp_obj_t)&rp2pio_statemachine_get_in_waiting_obj); +//| offset: int +//| """The instruction offset where the program was actually loaded""" +//| + +static mp_obj_t rp2pio_statemachine_obj_get_offset(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_rp2pio_statemachine_get_offset(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_offset_obj, rp2pio_statemachine_obj_get_offset); + +MP_PROPERTY_GETTER(rp2pio_statemachine_offset_obj, + (mp_obj_t)&rp2pio_statemachine_get_offset_obj); + +//| pc: int +//| """The current program counter of the state machine""" +//| + +static mp_obj_t rp2pio_statemachine_obj_get_pc(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_rp2pio_statemachine_get_pc(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_pc_obj, rp2pio_statemachine_obj_get_pc); + +MP_PROPERTY_GETTER(rp2pio_statemachine_pc_obj, + (mp_obj_t)&rp2pio_statemachine_get_pc_obj); + +//| rxfifo: memorymap.AddressRange +//| """Access the state machine's rxfifo directly +//| +//| If the state machine's fifo mode is ``txput`` then accessing this object +//| reads values stored by the ``mov rxfifo[], isr`` PIO instruction, and the +//| result of modifying it is undefined. +//| +//| If the state machine's fifo mode is ``txget`` then modifying this object +//| writes values accessed by the ``mov osr, rxfifo[]`` PIO instruction, and +//| the result of accessing it is undefined. +//| +//| If this state machine's mode is something else, then the property's value is `None`. +//| +//| Note: Since the ``txput`` and ``txget`` fifo mode does not exist on RP2040, this property will always be `None`.""" +//| + +static mp_obj_t rp2pio_statemachine_obj_get_rxfifo(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return common_hal_rp2pio_statemachine_get_rxfifo(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_rxfifo_obj, rp2pio_statemachine_obj_get_rxfifo); + +MP_PROPERTY_GETTER(rp2pio_statemachine_rxfifo_obj, + (mp_obj_t)&rp2pio_statemachine_get_rxfifo_obj); + + +//| last_read: array.array +//| """Returns the buffer most recently filled by background reads. +//| +//| This property is self-clearing -- once read, subsequent reads +//| will return a zero-length buffer until the background read buffer +//| changes or restarts. +//| """ +static mp_obj_t rp2pio_statemachine_obj_get_last_read(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return common_hal_rp2pio_statemachine_get_last_read(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_last_read_obj, rp2pio_statemachine_obj_get_last_read); + +MP_PROPERTY_GETTER(rp2pio_statemachine_last_read_obj, + (mp_obj_t)&rp2pio_statemachine_get_last_read_obj); + + +//| last_write: array.array +//| """Returns the buffer most recently emptied by background writes. +//| +//| This property is self-clearing -- once read, subsequent reads +//| will return a zero-length buffer until the background write buffer +//| changes or restarts. +//| """ +//| +//| +static mp_obj_t rp2pio_statemachine_obj_get_last_write(mp_obj_t self_in) { + rp2pio_statemachine_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return common_hal_rp2pio_statemachine_get_last_write(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2pio_statemachine_get_last_write_obj, rp2pio_statemachine_obj_get_last_write); + +MP_PROPERTY_GETTER(rp2pio_statemachine_last_write_obj, + (mp_obj_t)&rp2pio_statemachine_get_last_write_obj); + static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2pio_statemachine_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rp2pio_statemachine_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&rp2pio_statemachine_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&rp2pio_statemachine_restart_obj) }, @@ -827,15 +1131,31 @@ static const mp_rom_map_elem_t rp2pio_statemachine_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&rp2pio_statemachine_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&rp2pio_statemachine_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&rp2pio_statemachine_write_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_background_write), MP_ROM_PTR(&rp2pio_statemachine_background_write_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_background_write), MP_ROM_PTR(&rp2pio_statemachine_stop_background_write_obj) }, { MP_ROM_QSTR(MP_QSTR_writing), MP_ROM_PTR(&rp2pio_statemachine_writing_obj) }, - { MP_ROM_QSTR(MP_QSTR_pending), MP_ROM_PTR(&rp2pio_statemachine_pending_obj) }, + { MP_ROM_QSTR(MP_QSTR_pending), MP_ROM_PTR(&rp2pio_statemachine_pending_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_pending_write), MP_ROM_PTR(&rp2pio_statemachine_pending_write_obj) }, + + { MP_ROM_QSTR(MP_QSTR_background_read), MP_ROM_PTR(&rp2pio_statemachine_background_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_background_read), MP_ROM_PTR(&rp2pio_statemachine_stop_background_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_reading), MP_ROM_PTR(&rp2pio_statemachine_reading_obj) }, + { MP_ROM_QSTR(MP_QSTR_pending_read), MP_ROM_PTR(&rp2pio_statemachine_pending_read_obj) }, { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&rp2pio_statemachine_frequency_obj) }, { MP_ROM_QSTR(MP_QSTR_rxstall), MP_ROM_PTR(&rp2pio_statemachine_rxstall_obj) }, { MP_ROM_QSTR(MP_QSTR_txstall), MP_ROM_PTR(&rp2pio_statemachine_txstall_obj) }, { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&rp2pio_statemachine_in_waiting_obj) }, + + { MP_ROM_QSTR(MP_QSTR_offset), MP_ROM_PTR(&rp2pio_statemachine_offset_obj) }, + { MP_ROM_QSTR(MP_QSTR_pc), MP_ROM_PTR(&rp2pio_statemachine_pc_obj) }, + + { MP_ROM_QSTR(MP_QSTR_rxfifo), MP_ROM_PTR(&rp2pio_statemachine_rxfifo_obj) }, + + { MP_ROM_QSTR(MP_QSTR_last_read), MP_ROM_PTR(&rp2pio_statemachine_last_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_last_write), MP_ROM_PTR(&rp2pio_statemachine_last_write_obj) }, + }; static MP_DEFINE_CONST_DICT(rp2pio_statemachine_locals_dict, rp2pio_statemachine_locals_dict_table); diff --git a/ports/raspberrypi/bindings/rp2pio/StateMachine.h b/ports/raspberrypi/bindings/rp2pio/StateMachine.h index ce14d634097c1..16f884bcfca32 100644 --- a/ports/raspberrypi/bindings/rp2pio/StateMachine.h +++ b/ports/raspberrypi/bindings/rp2pio/StateMachine.h @@ -21,23 +21,28 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, size_t frequency, const uint16_t *init, size_t init_len, const uint16_t *may_exec, size_t may_exec_len, - const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, uint32_t initial_out_pin_state, uint32_t initial_out_pin_direction, - const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, uint32_t pull_pin_up, uint32_t pull_pin_down, - const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction, - const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction, + const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, pio_pinmask32_t initial_out_pin_state, pio_pinmask32_t initial_out_pin_direction, + const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, pio_pinmask32_t in_pull_pin_up, pio_pinmask32_t in_pull_pin_down, + const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, pio_pinmask32_t initial_set_pin_state, pio_pinmask32_t initial_set_pin_direction, + const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, bool sideset_pindirs, + pio_pinmask32_t initial_sideset_pin_state, pio_pinmask32_t initial_sideset_pin_direction, bool sideset_enable, const mcu_pin_obj_t *jmp_pin, digitalio_pull_t jmp_pin_pull, - uint32_t wait_gpio_mask, + pio_pinmask_t wait_gpio_mask, bool exclusive_pin_use, bool auto_pull, uint8_t pull_threshold, bool out_shift_right, bool wait_for_txstall, bool auto_push, uint8_t push_threshold, bool in_shift_right, bool user_interruptible, - int wrap_taget, int wrap, - int offset); + int wrap_target, int wrap, + int offset, + int fifo_type, + int mov_status_type, + int mov_status_n); void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self); bool common_hal_rp2pio_statemachine_deinited(rp2pio_statemachine_obj_t *self); +void common_hal_rp2pio_statemachine_mark_deinit(rp2pio_statemachine_obj_t *self); void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self); @@ -47,10 +52,22 @@ void common_hal_rp2pio_statemachine_run(rp2pio_statemachine_obj_t *self, const u // Lengths are in bytes. bool common_hal_rp2pio_statemachine_write(rp2pio_statemachine_obj_t *self, const uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap); -bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once_obj, const sm_buf_info *loop_obj, uint8_t stride_in_bytes, bool swap); + +bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, + uint8_t stride_in_bytes, bool swap); + +bool common_hal_rp2pio_statemachine_background_read(rp2pio_statemachine_obj_t *self, + uint8_t stride_in_bytes, bool swap); + bool common_hal_rp2pio_statemachine_stop_background_write(rp2pio_statemachine_obj_t *self); -mp_int_t common_hal_rp2pio_statemachine_get_pending(rp2pio_statemachine_obj_t *self); +bool common_hal_rp2pio_statemachine_stop_background_read(rp2pio_statemachine_obj_t *self); + +mp_int_t common_hal_rp2pio_statemachine_get_pending_write(rp2pio_statemachine_obj_t *self); +mp_int_t common_hal_rp2pio_statemachine_get_pending_read(rp2pio_statemachine_obj_t *self); + bool common_hal_rp2pio_statemachine_get_writing(rp2pio_statemachine_obj_t *self); +bool common_hal_rp2pio_statemachine_get_reading(rp2pio_statemachine_obj_t *self); + bool common_hal_rp2pio_statemachine_readinto(rp2pio_statemachine_obj_t *self, uint8_t *data, size_t len, uint8_t stride_in_bytes, bool swap); bool common_hal_rp2pio_statemachine_write_readinto(rp2pio_statemachine_obj_t *self, const uint8_t *data_out, size_t out_len, uint8_t out_stride_in_bytes, @@ -62,8 +79,17 @@ void common_hal_rp2pio_statemachine_set_frequency(rp2pio_statemachine_obj_t *sel bool common_hal_rp2pio_statemachine_get_rxstall(rp2pio_statemachine_obj_t *self); void common_hal_rp2pio_statemachine_clear_rxfifo(rp2pio_statemachine_obj_t *self); + bool common_hal_rp2pio_statemachine_get_txstall(rp2pio_statemachine_obj_t *self); void common_hal_rp2pio_statemachine_clear_txstall(rp2pio_statemachine_obj_t *self); size_t common_hal_rp2pio_statemachine_get_in_waiting(rp2pio_statemachine_obj_t *self); +int common_hal_rp2pio_statemachine_get_offset(rp2pio_statemachine_obj_t *self); +int common_hal_rp2pio_statemachine_get_pc(rp2pio_statemachine_obj_t *self); + void common_hal_rp2pio_statemachine_set_interrupt_handler(rp2pio_statemachine_obj_t *self, void (*handler)(void *), void *arg, int mask); + +mp_obj_t common_hal_rp2pio_statemachine_get_rxfifo(rp2pio_statemachine_obj_t *self); + +mp_obj_t common_hal_rp2pio_statemachine_get_last_read(rp2pio_statemachine_obj_t *self); +mp_obj_t common_hal_rp2pio_statemachine_get_last_write(rp2pio_statemachine_obj_t *self); diff --git a/ports/raspberrypi/bindings/rp2pio/__init__.c b/ports/raspberrypi/bindings/rp2pio/__init__.c index 285919e0fd87e..e68c376ae80cb 100644 --- a/ports/raspberrypi/bindings/rp2pio/__init__.c +++ b/ports/raspberrypi/bindings/rp2pio/__init__.c @@ -17,13 +17,20 @@ //| introduction and guide to working with PIO in CircuitPython, see `this //| Learn guide `_. //| +//| .. warning:: Using PIO inputs on Raspberry Pi RP2350 A2 stepping has some limitations +//| due to a GPIO hardware issue that causes excessive leakage current (~120uA). +//| A pin can read as high even when driven or pulled low, if the input signal is high +//| impedance or if an attached pull-down resistor is too weak (has too high a value). +//| See the warning in `digitalio` for more information. //| """ //| +//| //| def pins_are_sequential(pins: List[microcontroller.Pin]) -> bool: //| """Return True if the pins have sequential GPIO numbers, False otherwise""" //| ... //| +//| static mp_obj_t rp2pio_pins_are_sequential(mp_obj_t pins_obj) { size_t len; mp_obj_t *items; diff --git a/ports/raspberrypi/boards/0xcb_gemini/board.c b/ports/raspberrypi/boards/0xcb_gemini/board.c new file mode 100644 index 0000000000000..ebb56e8a47409 --- /dev/null +++ b/ports/raspberrypi/boards/0xcb_gemini/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Conor Burns for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.h b/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.h new file mode 100644 index 0000000000000..7321c6fb5f9b4 --- /dev/null +++ b/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Conor Burns for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "0xCB Gemini" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO16) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO7) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.mk b/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.mk new file mode 100644 index 0000000000000..f5ff14edc8d1e --- /dev/null +++ b/ports/raspberrypi/boards/0xcb_gemini/mpconfigboard.mk @@ -0,0 +1,9 @@ +USB_VID = 0x1209 +USB_PID = 0xCB65 +USB_PRODUCT = "Gemini" +USB_MANUFACTURER = "0xCB" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" diff --git a/ports/raspberrypi/boards/0xcb_gemini/pico-sdk-configboard.h b/ports/raspberrypi/boards/0xcb_gemini/pico-sdk-configboard.h new file mode 100644 index 0000000000000..cd0307c5a9a5f --- /dev/null +++ b/ports/raspberrypi/boards/0xcb_gemini/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Conor Burns for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/0xcb_gemini/pins.c b/ports/raspberrypi/boards/0xcb_gemini/pins.c new file mode 100644 index 0000000000000..3250a37835ee5 --- /dev/null +++ b/ports/raspberrypi/boards/0xcb_gemini/pins.c @@ -0,0 +1,71 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Conor Burns for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Right side top to bottom + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDI), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SDO), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + + // Bottom side right to left + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + + // Left side bottom to top + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + // Backside bottom to top + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + // VBUS sense voltage divider when jumper connected https://docs.keeb.supply/0xcb-gemini/guide/#split-capability + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/42keebs_frood/pins.c b/ports/raspberrypi/boards/42keebs_frood/pins.c index 4543625051869..2e7ac22475b22 100644 --- a/ports/raspberrypi/boards/42keebs_frood/pins.c +++ b/ports/raspberrypi/boards/42keebs_frood/pins.c @@ -49,6 +49,9 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO19) }, diff --git a/ports/raspberrypi/boards/8086_rp2040_interfacer/board.c b/ports/raspberrypi/boards/8086_rp2040_interfacer/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/8086_rp2040_interfacer/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.h b/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.h new file mode 100644 index 0000000000000..860ca65321c00 --- /dev/null +++ b/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "8086 RP2040 Interfacer" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO16) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO27) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO26) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO13) +#define DEFAULT_UART_BUS_TX (&pin_GPIO12) + +// #define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX +// #define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX diff --git a/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.mk b/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.mk new file mode 100644 index 0000000000000..644d7d7520fd3 --- /dev/null +++ b/ports/raspberrypi/boards/8086_rp2040_interfacer/mpconfigboard.mk @@ -0,0 +1,9 @@ +USB_VID = 0x3171 +USB_PID = 0x010D +USB_PRODUCT = "RP2040 Interfacer" +USB_MANUFACTURER = "8086 Consultancy" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" diff --git a/ports/raspberrypi/boards/8086_rp2040_interfacer/pico-sdk-configboard.h b/ports/raspberrypi/boards/8086_rp2040_interfacer/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/8086_rp2040_interfacer/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/8086_rp2040_interfacer/pins.c b/ports/raspberrypi/boards/8086_rp2040_interfacer/pins.c new file mode 100644 index 0000000000000..07ff7fbe31ad5 --- /dev/null +++ b/ports/raspberrypi/boards/8086_rp2040_interfacer/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_PULL_SDA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_PULL_SCL), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_LED_UART), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_LED_STQW), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350/board.c b/ports/raspberrypi/boards/adafruit_feather_rp2350/board.c index e6a868ab21226..fddd2572c1fcd 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2350/board.c +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350/board.c @@ -4,6 +4,13 @@ // // SPDX-License-Identifier: MIT +#include "py/obj.h" #include "supervisor/board.h" +#include "common-hal/picodvi/__init__.h" + // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. + +void board_init(void) { + picodvi_autoconstruct(); +} diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h index 1e238789a3dde..d0c114a97e4ef 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.h @@ -20,3 +20,12 @@ #define DEFAULT_UART_BUS_TX (&pin_GPIO0) #define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) + +#define DEFAULT_DVI_BUS_CLK_DN (&pin_GPIO15) +#define DEFAULT_DVI_BUS_CLK_DP (&pin_GPIO14) +#define DEFAULT_DVI_BUS_RED_DN (&pin_GPIO19) +#define DEFAULT_DVI_BUS_RED_DP (&pin_GPIO18) +#define DEFAULT_DVI_BUS_GREEN_DN (&pin_GPIO17) +#define DEFAULT_DVI_BUS_GREEN_DP (&pin_GPIO16) +#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO13) +#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO12) diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.mk index 021e382264ba9..0816bebd093bc 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350/mpconfigboard.mk @@ -8,8 +8,3 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" - -CIRCUITPY_ALARM = 0 - -CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_PICODVI = 1 diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350/pins.c b/ports/raspberrypi/boards/adafruit_feather_rp2350/pins.c index 8e74da883dc56..064411271e2b4 100644 --- a/ports/raspberrypi/boards/adafruit_feather_rp2350/pins.c +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, @@ -30,7 +30,9 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO7) }, { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO7) }, diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/board.c b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.h new file mode 100644 index 0000000000000..b77664cf85c11 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Adafruit Feather RP2350 Adalogger" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO21) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO22) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO23) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO20) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) + +#define DEFAULT_SD_SCK (&pin_GPIO14) +#define DEFAULT_SD_MOSI (&pin_GPIO15) +#define DEFAULT_SD_MISO (&pin_GPIO16) +#define DEFAULT_SD_CS (&pin_GPIO19) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO13) +#define DEFAULT_SD_CARD_INSERTED false diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk new file mode 100644 index 0000000000000..88cce7c4a4ce9 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x239A +USB_PID = 0x816E +USB_PRODUCT = "Feather RP2350 Adalogger" +USB_MANUFACTURER = "Adafruit" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pico-sdk-configboard.h b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pico-sdk-configboard.h new file mode 100644 index 0000000000000..2d9283a9192f2 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pico-sdk-configboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pins.c b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pins.c new file mode 100644 index 0000000000000..ac9a29abaad96 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_feather_rp2350_adalogger/pins.c @@ -0,0 +1,69 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_IO4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO7) }, + + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CARD_DETECT), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_SD_CLK), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SD_CMD), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT0), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_SD_DAT1), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT2), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_SD_DAT3), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c index 0750411dafc26..882bc9a1a9e0b 100644 --- a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/board.c @@ -34,9 +34,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO25, // TFT_DC Command or data - &pin_GPIO29, // TFT_CS Chip select - NULL, // TFT_RESET Reset + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_DC), + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_CS), + MP_OBJ_NULL, // TFT_RESET Reset 40000000, // Baudrate 0, // Polarity 0); // Phase @@ -62,7 +62,7 @@ void board_init(void) { MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command display_init_sequence, sizeof(display_init_sequence), - &pin_GPIO28, // backlight pin + CIRCUITPY_BOARD_TFT_BACKLIGHT, NO_BRIGHTNESS_COMMAND, 1.0f, // brightness false, // single_byte_bounds diff --git a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/mpconfigboard.h index 6f41981e24896..57c2be2207b68 100644 --- a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/mpconfigboard.h @@ -9,10 +9,14 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Floppsy RP2040" #define MICROPY_HW_MCU_NAME "rp2040" -#define MICROPY_HW_NEOPIXEL (&pin_GPIO15) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO22) #define DEFAULT_I2C_BUS_SCL (&pin_GPIO17) #define DEFAULT_I2C_BUS_SDA (&pin_GPIO16) +#define CIRCUITPY_BOARD_TFT_DC (&pin_GPIO23) +#define CIRCUITPY_BOARD_TFT_CS (&pin_GPIO24) +#define CIRCUITPY_BOARD_TFT_BACKLIGHT (&pin_GPIO25) + #define CIRCUITPY_BOARD_SPI (1) -#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO26, .mosi = &pin_GPIO27}} +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO20 }} diff --git a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/pins.c b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/pins.c index 800962637e5fc..cfeb426e31ad4 100644 --- a/ports/raspberrypi/boards/adafruit_floppsy_rp2040/pins.c +++ b/ports/raspberrypi/boards/adafruit_floppsy_rp2040/pins.c @@ -6,45 +6,57 @@ #include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - { MP_OBJ_NEW_QSTR(MP_QSTR_DENSITY), MP_ROM_PTR(&pin_GPIO0) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SELECT), MP_ROM_PTR(&pin_GPIO1) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MOTOR), MP_ROM_PTR(&pin_GPIO2) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_DIRECTION), MP_ROM_PTR(&pin_GPIO3) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_STEP), MP_ROM_PTR(&pin_GPIO4) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WRDATA), MP_ROM_PTR(&pin_GPIO5) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WRGATE), MP_ROM_PTR(&pin_GPIO6) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SIDE), MP_ROM_PTR(&pin_GPIO7) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_FLOPPY_DIRECTION), MP_ROM_PTR(&pin_GPIO8) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_INDEX), MP_ROM_PTR(&pin_GPIO9) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_TRACK0), MP_ROM_PTR(&pin_GPIO10) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WRPROT), MP_ROM_PTR(&pin_GPIO11) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_RDDATA), MP_ROM_PTR(&pin_GPIO12) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_READY), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PERIPH_RESET), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_DENSITY), MP_ROM_PTR(&pin_GPIO1) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SELECT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOTOR), MP_ROM_PTR(&pin_GPIO3) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DIRECTION), MP_ROM_PTR(&pin_GPIO4) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_STEP), MP_ROM_PTR(&pin_GPIO5) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WRDATA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WRGATE), MP_ROM_PTR(&pin_GPIO7) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SIDE), MP_ROM_PTR(&pin_GPIO8) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_FLOPPY_DIRECTION), MP_ROM_PTR(&pin_GPIO9) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_INDEX), MP_ROM_PTR(&pin_GPIO10) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TRACK0), MP_ROM_PTR(&pin_GPIO11) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WRPROT), MP_ROM_PTR(&pin_GPIO12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RDDATA), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_READY), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_FLOPPY_ENABLE), MP_ROM_PTR(&pin_GPIO15) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO16) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO17) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_AW9523_SD_CD), MP_ROM_INT(15) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AW9523_BUTTON_LEFT), MP_ROM_INT(0) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AW9523_BUTTON_UP), MP_ROM_INT(1) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AW9523_BUTTON_RIGHT), MP_ROM_INT(2) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_AW9523_BUTTON_DOWN), MP_ROM_INT(3) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CD), MP_ROM_PTR(&pin_GPIO24) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO19) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO20) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO21) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO19) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO19) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_DC) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_CS) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_BACKLIGHT) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO20) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO20) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO21) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO22) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO23) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].framebuffer_display)}, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/board.c b/ports/raspberrypi/boards/adafruit_fruit_jam/board.c new file mode 100644 index 0000000000000..a868bc02b7167 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/board.c @@ -0,0 +1,57 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "common-hal/microcontroller/Pin.h" +#include "hardware/gpio.h" +#include "py/mphal.h" +#include "shared-bindings/usb_host/Port.h" +#include "supervisor/board.h" + +#include "common-hal/picodvi/__init__.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. + +#define I2S_RESET_PIN_NUMBER 22 + +bool board_reset_pin_number(uint8_t pin_number) { + #if defined(DEFAULT_USB_HOST_5V_POWER) + if (pin_number == DEFAULT_USB_HOST_5V_POWER->number) { + // doing this (rather than gpio_init) in this specific order ensures no + // glitch if pin was already configured as a high output. gpio_init() temporarily + // configures the pin as an input, so the power enable value would potentially + // glitch. + gpio_put(pin_number, 1); + gpio_set_dir(pin_number, GPIO_OUT); + gpio_set_function(pin_number, GPIO_FUNC_SIO); + + return true; + } + #endif + // Set I2S out of reset. + if (pin_number == I2S_RESET_PIN_NUMBER) { + gpio_put(pin_number, 1); + gpio_set_dir(pin_number, GPIO_OUT); + gpio_set_function(pin_number, GPIO_FUNC_SIO); + + return true; + } + return false; +} + +void board_init(void) { + // Reset the DAC to put it in a known state. + gpio_put(I2S_RESET_PIN_NUMBER, 0); + gpio_set_dir(I2S_RESET_PIN_NUMBER, GPIO_OUT); + gpio_set_function(I2S_RESET_PIN_NUMBER, GPIO_FUNC_SIO); + mp_hal_delay_us(1); + board_reset_pin_number(I2S_RESET_PIN_NUMBER); + + #if defined(DEFAULT_USB_HOST_DATA_PLUS) + common_hal_usb_host_port_construct(DEFAULT_USB_HOST_DATA_PLUS, DEFAULT_USB_HOST_DATA_MINUS); + #endif + + picodvi_autoconstruct(); +} diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.h new file mode 100644 index 0000000000000..08c3271552c58 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.h @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Adafruit Fruit Jam" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO32) +#define MICROPY_HW_NEOPIXEL_COUNT (5) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO30) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO31) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO28) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO9) +#define DEFAULT_UART_BUS_TX (&pin_GPIO8) + +#define DEFAULT_USB_HOST_DATA_PLUS (&pin_GPIO1) +#define DEFAULT_USB_HOST_DATA_MINUS (&pin_GPIO2) +#define DEFAULT_USB_HOST_5V_POWER (&pin_GPIO11) + +#define DEFAULT_DVI_BUS_CLK_DN (&pin_GPIO12) +#define DEFAULT_DVI_BUS_CLK_DP (&pin_GPIO13) +#define DEFAULT_DVI_BUS_RED_DN (&pin_GPIO14) +#define DEFAULT_DVI_BUS_RED_DP (&pin_GPIO15) +#define DEFAULT_DVI_BUS_GREEN_DN (&pin_GPIO16) +#define DEFAULT_DVI_BUS_GREEN_DP (&pin_GPIO17) +#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO18) +#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO19) + +#define DEFAULT_SD_SCK (&pin_GPIO34) +#define DEFAULT_SD_MOSI (&pin_GPIO35) +#define DEFAULT_SD_MISO (&pin_GPIO36) +#define DEFAULT_SD_CS (&pin_GPIO39) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO33) +#define DEFAULT_SD_CARD_INSERTED true + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO47) + +// #define CIRCUITPY_CONSOLE_UART_TX (&pin_GPIO44) +// #define CIRCUITPY_CONSOLE_UART_RX (&pin_GPIO45) + +// #define CIRCUITPY_DEBUG_TINYUSB 0 + +#define CIRCUITPY_SAVES_PARTITION_SIZE (2 * 1024 * 1024) diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.mk new file mode 100644 index 0000000000000..31c4b130d0e2d --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x239A +USB_PID = 0x816C +USB_PRODUCT = "Fruit Jam" +USB_MANUFACTURER = "Adafruit" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +# CIRCUITPY_DISPLAY_FONT = $(TOP)/tools/fonts/unifont-16.0.02-all.bdf +# CIRCUITPY_FONT_EXTRA_CHARACTERS = "🖮🖱️" diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/pico-sdk-configboard.h b/ports/raspberrypi/boards/adafruit_fruit_jam/pico-sdk-configboard.h new file mode 100644 index 0000000000000..2d9283a9192f2 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/pico-sdk-configboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/adafruit_fruit_jam/pins.c b/ports/raspberrypi/boards/adafruit_fruit_jam/pins.c new file mode 100644 index 0000000000000..82c4d19eb387e --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_fruit_jam/pins.c @@ -0,0 +1,106 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + + // On JST PH connector. + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + + // On header + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_GPIO0) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON2), MP_ROM_PTR(&pin_GPIO4) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON3), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO28) }, + + // Shared with ESP TX/RX. + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_GPIO46) }, + // was GPIO0 on ESP32. Used for IRQ and mode switching. + { MP_ROM_QSTR(MP_QSTR_ESP_IRQ), MP_ROM_PTR(&pin_GPIO23) }, + // BUSY is also known as READY, and is RTS for BLE mode. + { MP_ROM_QSTR(MP_QSTR_ESP_BUSY), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_GPIO22) }, + // TX and RX are from the point of view of the RP2350. + { MP_ROM_QSTR(MP_QSTR_ESP_TX), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_ESP_RX), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_CKN), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_CKP), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D0N), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D0P), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D1N), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D1P), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D2N), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D2P), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_PERIPH_RESET), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_DIN), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_I2S_WS), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_I2S_IRQ), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO34) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_GPIO34) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO36) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO37) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO38) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CARD_DETECT), MP_ROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_PLUS), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_MINUS), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_5V_POWER), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + // Shared with ESP TX/RX. + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c b/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c index 60f3fc7317a85..ec37b398e229f 100644 --- a/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c +++ b/ports/raspberrypi/boards/adafruit_macropad_rp2040/board.c @@ -10,7 +10,7 @@ #include "shared-module/displayio/mipi_constants.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/board.h" #include "supervisor/shared/board.h" @@ -29,7 +29,7 @@ uint8_t display_init_sequence[] = { 0xda, 1, 0x12, // com pins 0x81, 1, 0xff, // contrast 255 0xd9, 1, 0x1f, // pre/dis-charge 2DCLKs/2CLKs - 0xdb, 1, 0x20, // VCOM deslect 0.770 + 0xdb, 1, 0x20, // VCOM select 0.770 0x20, 1, 0x20, 0x33, 0, // VPP 9V 0xa6, 0, // not inverted @@ -46,9 +46,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO24, // Command or data - &pin_GPIO22, // Chip select - &pin_GPIO23, // Reset + MP_OBJ_FROM_PTR(&pin_GPIO24), // Command or data + MP_OBJ_FROM_PTR(&pin_GPIO22), // Chip select + MP_OBJ_FROM_PTR(&pin_GPIO23), // Reset 10000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/adafruit_metro_rp2350/board.c b/ports/raspberrypi/boards/adafruit_metro_rp2350/board.c index e6a868ab21226..f85d1076c0b4f 100644 --- a/ports/raspberrypi/boards/adafruit_metro_rp2350/board.c +++ b/ports/raspberrypi/boards/adafruit_metro_rp2350/board.c @@ -4,6 +4,36 @@ // // SPDX-License-Identifier: MIT +#include "common-hal/microcontroller/Pin.h" +#include "hardware/gpio.h" +#include "shared-bindings/usb_host/Port.h" #include "supervisor/board.h" +#include "common-hal/picodvi/__init__.h" + // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. + + +#if defined(DEFAULT_USB_HOST_5V_POWER) +bool board_reset_pin_number(uint8_t pin_number) { + if (pin_number == DEFAULT_USB_HOST_5V_POWER->number) { + // doing this (rather than gpio_init) in this specific order ensures no + // glitch if pin was already configured as a high output. gpio_init() temporarily + // configures the pin as an input, so the power enable value would potentially + // glitch. + gpio_put(pin_number, 1); + gpio_set_dir(pin_number, GPIO_OUT); + gpio_set_function(pin_number, GPIO_FUNC_SIO); + + return true; + } + return false; +} +#endif + +void board_init(void) { + #if defined(DEFAULT_USB_HOST_DATA_PLUS) + common_hal_usb_host_port_construct(DEFAULT_USB_HOST_DATA_PLUS, DEFAULT_USB_HOST_DATA_MINUS); + #endif + picodvi_autoconstruct(); +} diff --git a/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h index 22be24aacdf9b..1a583046416ff 100644 --- a/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h +++ b/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.h @@ -5,16 +5,16 @@ // SPDX-License-Identifier: MIT #define MICROPY_HW_BOARD_NAME "Adafruit Metro RP2350" -#define MICROPY_HW_MCU_NAME "rp2350a" +#define MICROPY_HW_MCU_NAME "rp2350b" -#define MICROPY_HW_NEOPIXEL (&pin_GPIO14) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO25) -#define DEFAULT_I2C_BUS_SCL (&pin_GPIO24) -#define DEFAULT_I2C_BUS_SDA (&pin_GPIO25) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) -#define DEFAULT_SPI_BUS_SCK (&pin_GPIO22) -#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO23) -#define DEFAULT_SPI_BUS_MISO (&pin_GPIO20) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO30) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO31) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO28) #define DEFAULT_UART_BUS_RX (&pin_GPIO1) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) @@ -22,4 +22,23 @@ // #define CIRCUITPY_CONSOLE_UART_RX DEFAULT_UART_BUS_RX // #define CIRCUITPY_CONSOLE_UART_TX DEFAULT_UART_BUS_TX -#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) +#define DEFAULT_USB_HOST_DATA_PLUS (&pin_GPIO32) +#define DEFAULT_USB_HOST_DATA_MINUS (&pin_GPIO33) +#define DEFAULT_USB_HOST_5V_POWER (&pin_GPIO29) +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO47) + +#define DEFAULT_DVI_BUS_CLK_DN (&pin_GPIO15) +#define DEFAULT_DVI_BUS_CLK_DP (&pin_GPIO14) +#define DEFAULT_DVI_BUS_RED_DN (&pin_GPIO19) +#define DEFAULT_DVI_BUS_RED_DP (&pin_GPIO18) +#define DEFAULT_DVI_BUS_GREEN_DN (&pin_GPIO17) +#define DEFAULT_DVI_BUS_GREEN_DP (&pin_GPIO16) +#define DEFAULT_DVI_BUS_BLUE_DN (&pin_GPIO13) +#define DEFAULT_DVI_BUS_BLUE_DP (&pin_GPIO12) + +#define DEFAULT_SD_SCK (&pin_GPIO34) +#define DEFAULT_SD_MOSI (&pin_GPIO35) +#define DEFAULT_SD_MISO (&pin_GPIO36) +#define DEFAULT_SD_CS (&pin_GPIO39) +#define DEFAULT_SD_CARD_DETECT (&pin_GPIO40) +#define DEFAULT_SD_CARD_INSERTED false diff --git a/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.mk index d668b709ba0d7..e43a8dcf2a307 100644 --- a/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/adafruit_metro_rp2350/mpconfigboard.mk @@ -4,9 +4,7 @@ USB_PRODUCT = "Metro RP2350" USB_MANUFACTURER = "Adafruit" CHIP_VARIANT = RP2350 -CHIP_PACKAGE = A +CHIP_PACKAGE = B CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" - -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/adafruit_metro_rp2350/pins.c b/ports/raspberrypi/boards/adafruit_metro_rp2350/pins.c index d89f2877fddd7..3fa135b179677 100644 --- a/ports/raspberrypi/boards/adafruit_metro_rp2350/pins.c +++ b/ports/raspberrypi/boards/adafruit_metro_rp2350/pins.c @@ -6,16 +6,15 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS - { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, - - { MP_OBJ_NEW_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO24) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO45) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO46) }, // On-board switch reverses D0 and D1 connections to RX and TX. @@ -37,20 +36,60 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, { MP_OBJ_NEW_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, { MP_OBJ_NEW_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO23) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO24) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_CKN), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_CKP), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D0N), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D0P), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D1N), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D1P), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D2N), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D2P), MP_ROM_PTR(&pin_GPIO12) }, + + // GPIO's on HSTX connector + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO34) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_GPIO34) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO35) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO36) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO36) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO37) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO38) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO24) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO25) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO39) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO39) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CARD_DETECT), MP_ROM_PTR(&pin_GPIO40) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO22) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO23) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO20) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_PLUS), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_MINUS), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_5V_POWER), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, diff --git a/ports/raspberrypi/boards/adafruit_qt2040_trinkey/board.c b/ports/raspberrypi/boards/adafruit_qt2040_trinkey/board.c index 5a44f1167f0d9..ae948d089b51b 100644 --- a/ports/raspberrypi/boards/adafruit_qt2040_trinkey/board.c +++ b/ports/raspberrypi/boards/adafruit_qt2040_trinkey/board.c @@ -7,6 +7,6 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c new file mode 100644 index 0000000000000..fddd2572c1fcd --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/board.c @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "supervisor/board.h" + +#include "common-hal/picodvi/__init__.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. + +void board_init(void) { + picodvi_autoconstruct(); +} diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.h b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.h new file mode 100644 index 0000000000000..958ab01a0b6a8 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Adafruit Tinychad RP2350" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO17) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO19) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO18) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO10) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO12) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk new file mode 100644 index 0000000000000..8d2a9c2f5273f --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x239A +USB_PID = 0x8170 +USB_PRODUCT = "Tinychad RP2350" +USB_MANUFACTURER = "Adafruit" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pico-sdk-configboard.h new file mode 100644 index 0000000000000..2d9283a9192f2 --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pico-sdk-configboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pins.c b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pins.c new file mode 100644 index 0000000000000..0d769fd4d565d --- /dev/null +++ b/ports/raspberrypi/boards/adafruit_tinychad_rp2350/pins.c @@ -0,0 +1,54 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/archi/pins.c b/ports/raspberrypi/boards/archi/pins.c index 60d391a8fe622..43805f6e4daa1 100644 --- a/ports/raspberrypi/boards/archi/pins.c +++ b/ports/raspberrypi/boards/archi/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/boardsource_blok/board.c b/ports/raspberrypi/boards/boardsource_blok/board.c index 0c7574ea8a89d..5d714c242b5ee 100644 --- a/ports/raspberrypi/boards/boardsource_blok/board.c +++ b/ports/raspberrypi/boards/boardsource_blok/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void board_init(void) { diff --git a/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c b/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c index 60efe1e282259..f091c4b05a8ad 100644 --- a/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c +++ b/ports/raspberrypi/boards/bradanlanestudio_explorer_rp2040/board.c @@ -26,9 +26,9 @@ #include "shared-module/displayio/__init__.h" #include "supervisor/shared/board.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" -#include "src/rp2_common/hardware_adc/include/hardware/adc.h" +#include "hardware/adc.h" #define ADC_FIRST_PIN_NUMBER 26 #define ADC_PIN_COUNT 4 extern void common_hal_mcu_delay_us(uint32_t); @@ -212,9 +212,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO11, // DEFAULT_SPI_BUS_DC, // EPD_DC Command or data - &pin_GPIO13, // DEFAULT_SPI_BUS_CS, // EPD_CS Chip select - &pin_GPIO10, // DEFAULT_SPI_BUS_RESET, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO11), // DEFAULT_SPI_BUS_DC, // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO13), // DEFAULT_SPI_BUS_CS, // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO10), // DEFAULT_SPI_BUS_RESET, // EPD_RST Reset 1000000, // Baudrate 0, // Polarity 0); // Phase @@ -251,71 +251,62 @@ void board_init(void) { if ((vid_setting == 1) || // DCNextGen SSD1681 BWR rotated 270 (vid_setting == 3) || // Explorer SSD1681 BW rotated 0 (vid_setting == 4)) { // Explorer SSD1681 BWR rotated 0 - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - _start_sequence_ssd1681, sizeof(_start_sequence_ssd1681), - 1.0, // start up time - _stop_sequence_ssd1681, sizeof(_stop_sequence_ssd1681), - WIDTH, // width - HEIGHT, // height - WIDTH, // ram_width - HEIGHT + 0x60, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits - 0, // colstart - 0, // rowstart - rotation, // rotation - SSD_SET_RAMXPOS, // set_column_window_command - SSD_SET_RAMYPOS, // set_row_window_command - SSD_SET_RAMXCOUNT, // set_current_column_command - SSD_SET_RAMYCOUNT, // set_current_row_command - SSD_WRITE_RAM_BLK, // write_black_ram_command - false, // black_bits_inverted - SSD_WRITE_RAM_RED, // write_color_ram_command - false, // color_bits_inverted - 0xFF0000, // highlight_color (RED for tri-color display) - _refresh_sequence_ssd1681, sizeof(_refresh_sequence_ssd1681), // refresh_display_command - refresh_time, // refresh_time - &pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin - true, // busy_state - seconds_per_frame, // seconds_per_frame (does not seem the user can change this) - true, // always_toggle_chip_select - false, // not grayscale - false, // not acep - false, // not two_byte_sequence_length - true); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence_ssd1681; + args.start_sequence_len = sizeof(_start_sequence_ssd1681); + args.start_up_time = 1.0; + args.stop_sequence = _stop_sequence_ssd1681; + args.stop_sequence_len = sizeof(_stop_sequence_ssd1681); + args.width = WIDTH; + args.height = HEIGHT; + args.ram_width = WIDTH; + args.ram_height = HEIGHT + 0x60; + args.rotation = rotation; + args.set_column_window_command = SSD_SET_RAMXPOS; + args.set_row_window_command = SSD_SET_RAMYPOS; + args.set_current_column_command = SSD_SET_RAMXCOUNT; + args.set_current_row_command = SSD_SET_RAMYCOUNT; + args.write_black_ram_command = SSD_WRITE_RAM_BLK; + args.write_color_ram_command = SSD_WRITE_RAM_RED; + args.highlight_color = 0xFF0000; + args.refresh_sequence = _refresh_sequence_ssd1681; + args.refresh_sequence_len = sizeof(_refresh_sequence_ssd1681); + args.refresh_time = refresh_time; + args.busy_pin = &pin_GPIO9; + args.busy_state = true; + args.seconds_per_frame = seconds_per_frame; + args.always_toggle_chip_select = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else if (vid_setting == 2) { // Explorer SSD1608 BW - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - _start_sequence_ssd1608, sizeof(_start_sequence_ssd1608), - 1.0, // start up time - _stop_sequence_ssd1608, sizeof(_stop_sequence_ssd1608), - WIDTH, // width - HEIGHT, // height - WIDTH, // ram_width - HEIGHT /* + 0x60 */, // ram_height RAM is actually only 200 bits high but we use 296 to match the 9 bits - 0, // colstart - 0, // rowstart - rotation, // rotation - SSD_SET_RAMXPOS, // set_column_window_command - SSD_SET_RAMYPOS, // set_row_window_command - SSD_SET_RAMXCOUNT, // set_current_column_command - SSD_SET_RAMYCOUNT, // set_current_row_command - SSD_WRITE_RAM_BLK, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color (RED for tri-color display) - _refresh_sequence_ssd1608, sizeof(_refresh_sequence_ssd1608), // refresh_display_command - refresh_time, // refresh_time - &pin_GPIO9, // DEFAULT_SPI_BUS_BUSY, // busy_pin - true, // busy_state - seconds_per_frame, // seconds_per_frame (does not seem the user can change this) - true, // always_toggle_chip_select - false, // not grayscale - false, // not acep - false, // not two_byte_sequence_length - true); // address_little_endian + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence_ssd1608; + args.start_sequence_len = sizeof(_start_sequence_ssd1608); + args.start_up_time = 1.0; + args.stop_sequence = _stop_sequence_ssd1608; + args.stop_sequence_len = sizeof(_stop_sequence_ssd1608); + args.width = WIDTH; + args.height = HEIGHT; + args.ram_width = WIDTH; + args.ram_height = HEIGHT; + args.rotation = rotation; + args.set_column_window_command = SSD_SET_RAMXPOS; + args.set_row_window_command = SSD_SET_RAMYPOS; + args.set_current_column_command = SSD_SET_RAMXCOUNT; + args.set_current_row_command = SSD_SET_RAMYCOUNT; + args.write_black_ram_command = SSD_WRITE_RAM_BLK; + args.write_color_ram_command = NO_COMMAND; + args.refresh_sequence = _refresh_sequence_ssd1608; + args.refresh_sequence_len = sizeof(_refresh_sequence_ssd1608); + args.refresh_time = refresh_time; + args.busy_pin = &pin_GPIO9; + args.busy_state = true; + args.seconds_per_frame = seconds_per_frame; + args.always_toggle_chip_select = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } else { // what should happen if this firmware is installed on some other board? // currently, we mark the display as None diff --git a/ports/raspberrypi/boards/challenger_rp2350_bconnect/board.c b/ports/raspberrypi/boards/challenger_rp2350_bconnect/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_bconnect/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.h b/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.h new file mode 100644 index 0000000000000..4c2eea646b8df --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Challenger+ RP2350 BConnect" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO22) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_SS (&pin_GPIO17) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO13) +#define DEFAULT_UART_BUS_TX (&pin_GPIO12) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.mk b/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.mk new file mode 100644 index 0000000000000..44e9b4929590f --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_bconnect/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x2e8a +USB_PID = 0x109b +USB_PRODUCT = "Challenger+ RP2350 BConnect" +USB_MANUFACTURER = "Invector Labs" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_ALARM = 0 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/raspberrypi/boards/challenger_rp2350_bconnect/pico-sdk-configboard.h b/ports/raspberrypi/boards/challenger_rp2350_bconnect/pico-sdk-configboard.h new file mode 100644 index 0000000000000..66b57dfd13dc2 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_bconnect/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/challenger_rp2350_bconnect/pins.c b/ports/raspberrypi/boards/challenger_rp2350_bconnect/pins.c new file mode 100644 index 0000000000000..2902b2212f9c1 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_bconnect/pins.c @@ -0,0 +1,63 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/board.c b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.h b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.h new file mode 100644 index 0000000000000..882104dd30dbd --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Challenger+ RP2350 WiFi6/BLE5" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_SS (&pin_GPIO17) +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO13) +#define DEFAULT_UART_BUS_TX (&pin_GPIO12) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk new file mode 100644 index 0000000000000..d4f2cdb90d0f8 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x2e8a +USB_PID = 0x109a +USB_PRODUCT = "Challenger+ RP2350 WiFi6/BLE5" +USB_MANUFACTURER = "Invector Labs" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_ALARM = 0 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pico-sdk-configboard.h b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pico-sdk-configboard.h new file mode 100644 index 0000000000000..66b57dfd13dc2 --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pins.c b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pins.c new file mode 100644 index 0000000000000..2cdc34869ca6d --- /dev/null +++ b/ports/raspberrypi/boards/challenger_rp2350_wifi6_ble5/pins.c @@ -0,0 +1,71 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_ESP_TX), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_ESP_RX), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_ESP_MISO), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_ESP_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_ESP_SCK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_ESP_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_ESP_BOOT), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_ESP_DRDY), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_ESP_RESET), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_ESP_HS), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/cytron_edu_pico_w/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_edu_pico_w/mpconfigboard.mk index c3c387f8130e9..384b0060df87e 100644 --- a/ports/raspberrypi/boards/cytron_edu_pico_w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/cytron_edu_pico_w/mpconfigboard.mk @@ -20,10 +20,23 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 1 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' +# The default is -O3. Change to -O2 because the build was overflowing. +OPTIMIZATION_FLAGS = -O2 + # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/board.c b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/link.ld b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.h b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.h new file mode 100644 index 0000000000000..8eab7e5a52557 --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Cytron EDU PICO 2" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_CYW0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO16}} diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk new file mode 100644 index 0000000000000..ac0bb6d6f2736 --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/mpconfigboard.mk @@ -0,0 +1,54 @@ +USB_VID = 0x2E8A +USB_PID = 0x107E +USB_PRODUCT = "Cytron EDU PICO 2 for Pico 2W" +USB_MANUFACTURER = "Cytron" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY_SDCARDIO = 1 + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + -DCYW43_PIO_CLOCK_DIV_INT=3 + +# The default is -O3. +OPTIMIZATION_FLAGS = -Os + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Motor +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SimpleIO +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_framebuf +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_OPT4048 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SSD1306 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ImageLoad +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_AHTx0 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HTTPServer +FROZEN_MPY_DIRS += $(TOP)/frozen/CircuitPython_edupico2_paj7620 + +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pico-sdk-configboard.h b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pins.c b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pins.c new file mode 100644 index 0000000000000..83b93e7268596 --- /dev/null +++ b/ports/raspberrypi/boards/cytron_edu_v2_pico_2w/pins.c @@ -0,0 +1,86 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + // Motor Controls + { MP_ROM_QSTR(MP_QSTR_M1A), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_M1B), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_M2A), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_M2B), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_LOG_SWITCH), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + // SPI Pins for SD Card + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_USB_RELAY), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_CYW1) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_CYW0) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_PLUS), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_DATA_MINUS), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_USB_HOST_POWER), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_spi_obj) }, + + + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/cytron_iriv_io_controller/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_iriv_io_controller/mpconfigboard.mk index 73e6954977e84..56fc00d097397 100644 --- a/ports/raspberrypi/boards/cytron_iriv_io_controller/mpconfigboard.mk +++ b/ports/raspberrypi/boards/cytron_iriv_io_controller/mpconfigboard.mk @@ -10,7 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SimpleIO diff --git a/ports/raspberrypi/boards/cytron_iriv_io_controller/pins.c b/ports/raspberrypi/boards/cytron_iriv_io_controller/pins.c index 050ce66ff30ff..5e7f2fad65ff7 100644 --- a/ports/raspberrypi/boards/cytron_iriv_io_controller/pins.c +++ b/ports/raspberrypi/boards/cytron_iriv_io_controller/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_OBJ_NEW_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c index 53fae76ac1b4f..dbfc713930b6e 100644 --- a/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c +++ b/ports/raspberrypi/boards/cytron_maker_pi_rp2040/pins.c @@ -62,6 +62,8 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VBATT), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, diff --git a/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk b/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk index 35d16884bdf1e..0ac939ce6a265 100644 --- a/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk +++ b/ports/raspberrypi/boards/cytron_motion_2350_pro/mpconfigboard.mk @@ -10,7 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 # Include these Python libraries in firmware. FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/raspberrypi/boards/cytron_motion_2350_pro/pins.c b/ports/raspberrypi/boards/cytron_motion_2350_pro/pins.c index 27f26a1519ee4..b1e63858563d9 100644 --- a/ports/raspberrypi/boards/cytron_motion_2350_pro/pins.c +++ b/ports/raspberrypi/boards/cytron_motion_2350_pro/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_OBJ_NEW_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/board.c b/ports/raspberrypi/boards/datanoise_picoadk_v2/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.h b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.h new file mode 100644 index 0000000000000..d14f625d61851 --- /dev/null +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Datanoise PicoADK V2" +#define MICROPY_HW_MCU_NAME "rp2350a" + + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO6) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO13) +#define DEFAULT_UART_BUS_TX (&pin_GPIO12) diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk new file mode 100644 index 0000000000000..1b5c6c5d548cc --- /dev/null +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x2E8A +USB_PID = 0x10AE +USB_PRODUCT = "PicoADK V2" +USB_MANUFACTURER = "Datanoise" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "GD25Q32C,W25Q32JVxQ" + +# Include these Python libraries in firmware. +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SD diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/pico-sdk-configboard.h b/ports/raspberrypi/boards/datanoise_picoadk_v2/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/datanoise_picoadk_v2/pins.c b/ports/raspberrypi/boards/datanoise_picoadk_v2/pins.c new file mode 100644 index 0000000000000..39c6c60548820 --- /dev/null +++ b/ports/raspberrypi/boards/datanoise_picoadk_v2/pins.c @@ -0,0 +1,57 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_CS0), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_MIDI_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_DIN), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_I2S_DOUT), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCLK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_MCLK), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/hack_club_sprig/board.c b/ports/raspberrypi/boards/hack_club_sprig/board.c index 89b1b3b75b7bf..94c5a7c5be9ec 100644 --- a/ports/raspberrypi/boards/hack_club_sprig/board.c +++ b/ports/raspberrypi/boards/hack_club_sprig/board.c @@ -10,7 +10,7 @@ #include "shared-bindings/fourwire/FourWire.h" #include "shared-module/displayio/__init__.h" #include "shared-module/displayio/mipi_constants.h" -#include "supervisor/shared/board.h" +#include "shared-bindings/board/__init__.h" // display init sequence from CircuitPython library https://github.com/adafruit/Adafruit_CircuitPython_ST7735R/blob/dfae353330cf051d1f31db9e4b681c8d70900cc5/adafruit_st7735r.py @@ -57,17 +57,14 @@ uint8_t display_init_sequence[] = { void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; - busio_spi_obj_t *spi = &bus->inline_bus; - common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, &pin_GPIO16, false); - common_hal_busio_spi_never_reset(spi); - bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO22, // DC - &pin_GPIO20, // CS - &pin_GPIO26, // RST + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_DC), + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_CS), + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_TFT_RESET), 30000000, 0, 0); @@ -92,7 +89,7 @@ void board_init(void) { MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command display_init_sequence, sizeof(display_init_sequence), - &pin_GPIO17, // backlight pin + CIRCUITPY_BOARD_TFT_BACKLIGHT, NO_BRIGHTNESS_COMMAND, 1.0f, // brightness false, // single_byte_bounds @@ -104,4 +101,8 @@ void board_init(void) { 50000); // backlight pwm frequency } +void board_deinit(void) { + common_hal_displayio_release_displays(); +} + // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/hack_club_sprig/mpconfigboard.h b/ports/raspberrypi/boards/hack_club_sprig/mpconfigboard.h index 041aca6d45eb7..bfc0469a71178 100644 --- a/ports/raspberrypi/boards/hack_club_sprig/mpconfigboard.h +++ b/ports/raspberrypi/boards/hack_club_sprig/mpconfigboard.h @@ -10,3 +10,11 @@ #define MICROPY_HW_MCU_NAME "rp2040" #define MICROPY_HW_LED_STATUS (&pin_GPIO4) + +#define CIRCUITPY_BOARD_TFT_DC (&pin_GPIO22) +#define CIRCUITPY_BOARD_TFT_CS (&pin_GPIO20) +#define CIRCUITPY_BOARD_TFT_RESET (&pin_GPIO26) +#define CIRCUITPY_BOARD_TFT_BACKLIGHT (&pin_GPIO17) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO16 }} diff --git a/ports/raspberrypi/boards/hack_club_sprig/pins.c b/ports/raspberrypi/boards/hack_club_sprig/pins.c index e5ce147839890..7802ef5466d1d 100644 --- a/ports/raspberrypi/boards/hack_club_sprig/pins.c +++ b/ports/raspberrypi/boards/hack_club_sprig/pins.c @@ -60,7 +60,6 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, - // Start Sprig-specific definitions { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_GPIO4) }, @@ -79,18 +78,23 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_BUTTON_K), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_BUTTON_L), MP_ROM_PTR(&pin_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_CARD_CS), MP_ROM_PTR(&pin_GPIO21) }, - { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_GPIO22) }, - { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_DC) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_CS) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_RESET) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_BACKLIGHT) }, + { MP_ROM_QSTR(MP_QSTR_TFT_LITE), MP_ROM_PTR(CIRCUITPY_BOARD_TFT_BACKLIGHT) }, + { MP_ROM_QSTR(MP_QSTR_WHITE_LED), MP_ROM_PTR(&pin_GPIO28) }, { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/heiafr_picomo_v2/board.c b/ports/raspberrypi/boards/heiafr_picomo_v2/board.c index 8c60341489fa1..3824c5959f5ee 100644 --- a/ports/raspberrypi/boards/heiafr_picomo_v2/board.c +++ b/ports/raspberrypi/boards/heiafr_picomo_v2/board.c @@ -51,9 +51,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO16, // TFT_DC Command or data - &pin_GPIO17, // TFT_CS Chip select - NULL, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO16), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // TFT_CS Chip select + MP_OBJ_NULL, // TFT_RST Reset 62500000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/board.c b/ports/raspberrypi/boards/heiafr_picomo_v3/board.c new file mode 100644 index 0000000000000..3824c5959f5ee --- /dev/null +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/board.c @@ -0,0 +1,93 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "supervisor/shared/board.h" + + +#define DELAY 0x80 + +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 150, // SWRESET + + 0x36, 1, 0x04, // MADCTL + 0x35, 1, 0x00, // TEON + 0xB2, 5, 0x0c, 0x0c, 0x00, 0x33, 0x33, // FRMCTR2 + 0x3A, 1, 0x05, // COLMOD + 0xB7, 1, 0x14, // GCTRL + 0xBB, 1, 0x37, // VCOMS + 0xC0, 1, 0x2c, // LCMCTRL + 0xC2, 1, 0x01, // VDVVRHEN + 0xC3, 1, 0x12, // VRHS + 0xC4, 1, 0x20, // VDVS + 0xD0, 2, 0xa4, 0xa1, // PWRCTRL1 + 0xC6, 1, 0x0f, // FRCTRL2 + 0xE0, 14, 0xd0, 0x04, 0x0d, 0x11, 0x13, 0x2b, 0x3f, 0x54, 0x4c, 0x18, 0x0d, 0x0b, 0x1f, 0x23, // GMCTRP1 + 0xE1, 14, 0xd0, 0x04, 0x0c, 0x11, 0x13, 0x2c, 0x3f, 0x44, 0x51, 0x2f, 0x1f, 0x1f, 0x20, 0x23, // GMCTRN1 + 0x21, 0, // INVON + + 0x11, 0 | DELAY, 255, // SLPOUT + 0x29, 0 | DELAY, 100, // DISPON + + 0x2a, 4, 0x00, 0, 0x00, 0xfe, // CASET + 0x2b, 4, 0x00, 0, 0x00, 0xfe, // RASET + 0x2c, 0, // RAMWR +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO16), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // TFT_CS Chip select + MP_OBJ_NULL, // TFT_RST Reset + 62500000, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct(display, + bus, + 240, // Width + 280, // Height + 0, // column start + 20, // row start + 0, // rotation + 16, // Color depth + false, // Grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_bytes_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command + MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // no backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 0); // backlight pwm frequency +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.h b/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.h new file mode 100644 index 0000000000000..39094f8972d81 --- /dev/null +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "HEIA-FR Picomo V3" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO10) +#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO9) +#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO8) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.mk b/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.mk new file mode 100644 index 0000000000000..2ee1fad50c9bc --- /dev/null +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x2E8A +USB_PID = 0x10C4 + +USB_PRODUCT = "Picomo V3" +USB_MANUFACTURER = "HEIA-FR" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY__EVE = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Register +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ST7789 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ProgressBar diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/pico-sdk-configboard.h b/ports/raspberrypi/boards/heiafr_picomo_v3/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/heiafr_picomo_v3/pins.c b/ports/raspberrypi/boards/heiafr_picomo_v3/pins.c new file mode 100644 index 0000000000000..eb1a1ec1d41db --- /dev/null +++ b/ports/raspberrypi/boards/heiafr_picomo_v3/pins.c @@ -0,0 +1,110 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + {MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0)}, + {MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1)}, + {MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2)}, + + {MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO3)}, + {MP_ROM_QSTR(MP_QSTR_S1), MP_ROM_PTR(&pin_GPIO3)}, + {MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3)}, + + {MP_ROM_QSTR(MP_QSTR_SW_MID), MP_ROM_PTR(&pin_GPIO4)}, + {MP_ROM_QSTR(MP_QSTR_S5), MP_ROM_PTR(&pin_GPIO4)}, + {MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4)}, + + {MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO5)}, + {MP_ROM_QSTR(MP_QSTR_S2), MP_ROM_PTR(&pin_GPIO5)}, + {MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5)}, + + {MP_ROM_QSTR(MP_QSTR_SW_TOPR), MP_ROM_PTR(&pin_GPIO6)}, + {MP_ROM_QSTR(MP_QSTR_BOOTSEL), MP_ROM_PTR(&pin_GPIO6)}, + {MP_ROM_QSTR(MP_QSTR_S7), MP_ROM_PTR(&pin_GPIO6)}, + {MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6)}, + + {MP_ROM_QSTR(MP_QSTR_SW_RIGHT), MP_ROM_PTR(&pin_GPIO7)}, + {MP_ROM_QSTR(MP_QSTR_S4), MP_ROM_PTR(&pin_GPIO7)}, + {MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7)}, + + {MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO8)}, + {MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8)}, + + {MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO9)}, + {MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9)}, + + {MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO10)}, + {MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10)}, + + {MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11)}, + + {MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12)}, + {MP_ROM_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_GPIO12)}, + + {MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13)}, + {MP_ROM_QSTR(MP_QSTR_VER_MSB), MP_ROM_PTR(&pin_GPIO13)}, + + {MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14)}, + {MP_ROM_QSTR(MP_QSTR_VER_LSB), MP_ROM_PTR(&pin_GPIO14)}, + + {MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15)}, + + {MP_ROM_QSTR(MP_QSTR_DISP_DC), MP_ROM_PTR(&pin_GPIO16)}, + {MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16)}, + + {MP_ROM_QSTR(MP_QSTR_DISP_CS), MP_ROM_PTR(&pin_GPIO17)}, + {MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17)}, + + {MP_ROM_QSTR(MP_QSTR_DISP_SCL), MP_ROM_PTR(&pin_GPIO18)}, + {MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18)}, + + {MP_ROM_QSTR(MP_QSTR_DISP_SDA), MP_ROM_PTR(&pin_GPIO19)}, + {MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19)}, + + {MP_ROM_QSTR(MP_QSTR_TEMP_SDA), MP_ROM_PTR(&pin_GPIO20)}, + {MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20)}, + + {MP_ROM_QSTR(MP_QSTR_TEMP_SCL), MP_ROM_PTR(&pin_GPIO21)}, + {MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21)}, + + {MP_ROM_QSTR(MP_QSTR_SW_LEFT), MP_ROM_PTR(&pin_GPIO22)}, + {MP_ROM_QSTR(MP_QSTR_S3), MP_ROM_PTR(&pin_GPIO22)}, + {MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22)}, + + {MP_ROM_QSTR(MP_QSTR_SW_TOPL), MP_ROM_PTR(&pin_GPIO23)}, + {MP_ROM_QSTR(MP_QSTR_S6), MP_ROM_PTR(&pin_GPIO23)}, + {MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23)}, + + {MP_ROM_QSTR(MP_QSTR_USB_OVCUR), MP_ROM_PTR(&pin_GPIO24)}, + {MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24)}, + + {MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25)}, + + {MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26)}, + {MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26)}, + {MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26)}, + + {MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27)}, + {MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27)}, + {MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27)}, + + {MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28)}, + {MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28)}, + {MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28)}, + + {MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29)}, + {MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29)}, + + {MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj)}, + {MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj)}, + {MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/hxr_sao_dmm/board.c b/ports/raspberrypi/boards/hxr_sao_dmm/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/hxr_sao_dmm/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.h b/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.h new file mode 100644 index 0000000000000..3b20682ee3093 --- /dev/null +++ b/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "HXR.DK SAO Digital Multimeter" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO15) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO14) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_BOARD_I2C (2) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}, \ + {.scl = &pin_GPIO15, .sda = &pin_GPIO14}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO0, .rx = &pin_GPIO1}} diff --git a/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.mk b/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.mk new file mode 100644 index 0000000000000..f841b1818b441 --- /dev/null +++ b/ports/raspberrypi/boards/hxr_sao_dmm/mpconfigboard.mk @@ -0,0 +1,17 @@ +USB_VID = 0x1209 +USB_PID = 0xFD42 +USB_PRODUCT = "SAO Digital Multimeter" +USB_MANUFACTURER = "HXR.DK" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_PICODVI = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Bitmap_Font +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Shapes +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 diff --git a/ports/raspberrypi/boards/hxr_sao_dmm/pico-sdk-configboard.h b/ports/raspberrypi/boards/hxr_sao_dmm/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/hxr_sao_dmm/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/hxr_sao_dmm/pins.c b/ports/raspberrypi/boards/hxr_sao_dmm/pins.c new file mode 100644 index 0000000000000..1457f47eb2a15 --- /dev/null +++ b/ports/raspberrypi/boards/hxr_sao_dmm/pins.c @@ -0,0 +1,103 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sao_i2c, i2c, 1) + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SAO_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDA0), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_SAO_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SCL0), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SDA), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SDA1), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY_SCL), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SCL1), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_ENC_A), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_ENC_B), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON_FN), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_BUZZER_A), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_PWM3_A), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_BUZZER_B), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_PWM3_B), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_SAO_GPIO1), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_SAO_GPIO2), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_MEASURE_RES), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_MEASURE_VIN), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SAO_I2C), MP_ROM_PTR(&board_sao_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/jpconstantineau_encoderpad_rp2040/board.c b/ports/raspberrypi/boards/jpconstantineau_encoderpad_rp2040/board.c index 559800e34d962..d3c80c5cb87d9 100644 --- a/ports/raspberrypi/boards/jpconstantineau_encoderpad_rp2040/board.c +++ b/ports/raspberrypi/boards/jpconstantineau_encoderpad_rp2040/board.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" #include "supervisor/board.h" diff --git a/ports/raspberrypi/boards/jpconstantineau_pykey18/board.c b/ports/raspberrypi/boards/jpconstantineau_pykey18/board.c index c123fd785c944..2bb2d06dcad4f 100644 --- a/ports/raspberrypi/boards/jpconstantineau_pykey18/board.c +++ b/ports/raspberrypi/boards/jpconstantineau_pykey18/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void reset_board(void) { diff --git a/ports/raspberrypi/boards/jpconstantineau_pykey44/board.c b/ports/raspberrypi/boards/jpconstantineau_pykey44/board.c index f0a3953335557..743e9b14b52a2 100644 --- a/ports/raspberrypi/boards/jpconstantineau_pykey44/board.c +++ b/ports/raspberrypi/boards/jpconstantineau_pykey44/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void reset_board(void) { diff --git a/ports/raspberrypi/boards/jpconstantineau_pykey60/board.c b/ports/raspberrypi/boards/jpconstantineau_pykey60/board.c index 360f18e382ed0..ab07a4aaaed27 100644 --- a/ports/raspberrypi/boards/jpconstantineau_pykey60/board.c +++ b/ports/raspberrypi/boards/jpconstantineau_pykey60/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void reset_board(void) { diff --git a/ports/raspberrypi/boards/jpconstantineau_pykey87/board.c b/ports/raspberrypi/boards/jpconstantineau_pykey87/board.c index 751726a065da3..b9fa212c96d91 100644 --- a/ports/raspberrypi/boards/jpconstantineau_pykey87/board.c +++ b/ports/raspberrypi/boards/jpconstantineau_pykey87/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void reset_board(void) { diff --git a/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c b/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c index 78cc912130e79..67e63daed1d67 100644 --- a/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c +++ b/ports/raspberrypi/boards/lilygo_t_display_rp2040/board.c @@ -63,9 +63,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO1, // DC - &pin_GPIO5, // CS - NULL, // RST (Reset pin tie to 0, do not set here) + MP_OBJ_FROM_PTR(&pin_GPIO1), // DC + MP_OBJ_FROM_PTR(&pin_GPIO5), // CS + MP_OBJ_NULL, // RST (Reset pin tie to 0, do not set here) 40000000, // baudrate 1, // polarity 0 // phase diff --git a/ports/raspberrypi/boards/mtm_computer/board.c b/ports/raspberrypi/boards/mtm_computer/board.c new file mode 100644 index 0000000000000..4fec0cd5b8b59 --- /dev/null +++ b/ports/raspberrypi/boards/mtm_computer/board.c @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "peripherals/pins.h" +#include "py/runtime.h" + +// board.DAC() — factory function that constructs an mcp4822.MCP4822 with +// the MTM Workshop Computer's DAC pins (GP18=SCK, GP19=SDI, GP21=CS). + +static mp_obj_t board_dac_singleton = MP_OBJ_NULL; + +static mp_obj_t board_dac_factory(void) { + if (board_dac_singleton == MP_OBJ_NULL) { + mcp4822_mcp4822_obj_t *dac = mp_obj_malloc_with_finaliser( + mcp4822_mcp4822_obj_t, &mcp4822_mcp4822_type); + common_hal_mcp4822_mcp4822_construct( + dac, + &pin_GPIO18, // clock (SCK) + &pin_GPIO19, // mosi (SDI) + &pin_GPIO21, // cs + 1); // gain 1x + board_dac_singleton = MP_OBJ_FROM_PTR(dac); + } + return board_dac_singleton; +} +MP_DEFINE_CONST_FUN_OBJ_0(board_dac_obj, board_dac_factory); + +void board_deinit(void) { + if (board_dac_singleton != MP_OBJ_NULL) { + common_hal_mcp4822_mcp4822_deinit(MP_OBJ_TO_PTR(board_dac_singleton)); + board_dac_singleton = MP_OBJ_NULL; + } +} +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/mtm_computer/mpconfigboard.h b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.h new file mode 100644 index 0000000000000..1825cef28e5eb --- /dev/null +++ b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.h @@ -0,0 +1,14 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Music Thing Modular Workshop Computer" +#define MICROPY_HW_MCU_NAME "rp2040" + + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk new file mode 100644 index 0000000000000..45c99711d72a3 --- /dev/null +++ b/ports/raspberrypi/boards/mtm_computer/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x2E8A +USB_PID = 0x10C1 +USB_PRODUCT = "Workshop Computer" +USB_MANUFACTURER = "Music Thing Modular" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY_AUDIOEFFECTS = 1 +CIRCUITPY_IMAGECAPTURE = 0 +CIRCUITPY_PICODVI = 0 +CIRCUITPY_MCP4822 = 1 diff --git a/ports/raspberrypi/boards/mtm_computer/pico-sdk-configboard.h b/ports/raspberrypi/boards/mtm_computer/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/mtm_computer/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/mtm_computer/pins.c b/ports/raspberrypi/boards/mtm_computer/pins.c new file mode 100644 index 0000000000000..ffdf2687702c6 --- /dev/null +++ b/ports/raspberrypi/boards/mtm_computer/pins.c @@ -0,0 +1,114 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +extern const mp_obj_fun_builtin_fixed_t board_dac_obj; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_UART_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_UART_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_PULSE_1_IN), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_PULSE_2_IN), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_NORM_PROBE), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + + // GPIO 5,6,7 are ID bits: 0,0,0 = Proto1.2 (pins floating), 1,0,0 = Proto 2.0 + { MP_ROM_QSTR(MP_QSTR_ID0), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_ID1), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_ID2), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_PULSE_1_OUT), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_PULSE_2_OUT), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_LED4), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_LED5), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_LED6), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_EEPROM_SDA), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_EEPROM_SCL), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_DAC_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_DAC_SDI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + // GP20 is unused + // { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_DAC_CS), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_CV_2_OUT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_CV_1_OUT), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_MUX_A), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_MUX_B), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_AUDIO_R_IN), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_AUDIO_L_IN), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_MUX_1), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_MUX_2), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + + // Factory function: dac = board.DAC() returns a configured mcp4822.MCP4822 + { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&board_dac_obj) }, + + // { MP_ROM_QSTR(MP_QSTR_EEPROM_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/orpheus_pico/board.c b/ports/raspberrypi/boards/orpheus_pico/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/orpheus_pico/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.h b/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.h new file mode 100644 index 0000000000000..8c6269771fdfc --- /dev/null +++ b/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.h @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Orpheus Pico" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO25) +#define MICROPY_HW_LED_STATUS (&pin_GPIO23) diff --git a/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.mk b/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.mk new file mode 100644 index 0000000000000..9b570211c8f77 --- /dev/null +++ b/ports/raspberrypi/boards/orpheus_pico/mpconfigboard.mk @@ -0,0 +1,11 @@ +USB_VID = 0x2E8A +USB_PID = 0x10D0 +USB_PRODUCT = "Orpheus Pico" +USB_MANUFACTURER = "Hack Club" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q64JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/orpheus_pico/pico-sdk-configboard.h b/ports/raspberrypi/boards/orpheus_pico/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/orpheus_pico/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/orpheus_pico/pins.c b/ports/raspberrypi/boards/orpheus_pico/pins.c new file mode 100644 index 0000000000000..24d656c18c9e0 --- /dev/null +++ b/ports/raspberrypi/boards/orpheus_pico/pins.c @@ -0,0 +1,57 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pajenicko_picopad/board.c b/ports/raspberrypi/boards/pajenicko_picopad/board.c index 0ca13b3ec2e1b..d8f9392262383 100644 --- a/ports/raspberrypi/boards/pajenicko_picopad/board.c +++ b/ports/raspberrypi/boards/pajenicko_picopad/board.c @@ -51,9 +51,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO17, // TFT_DC Command or data - &pin_GPIO21, // TFT_CS Chip select - &pin_GPIO20, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO17), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO21), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO20), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk b/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk index 5f5de1180a730..764e41d4d9154 100644 --- a/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pajenicko_picopad/mpconfigboard.mk @@ -28,6 +28,16 @@ CIRCUITPY_PICODVI = 1 # Pimoroni PicoSystem peripherals are compatible, we can use of existing ugame.py FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/picosystem -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_badger2040/board.c b/ports/raspberrypi/boards/pimoroni_badger2040/board.c index 457bff33b4433..80eddb49e1330 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040/board.c +++ b/ports/raspberrypi/boards/pimoroni_badger2040/board.c @@ -263,9 +263,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO20, // EPD_DC Command or data - &pin_GPIO17, // EPD_CS Chip select - &pin_GPIO21, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO20), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO21), // EPD_RST Reset 1200000, // Baudrate 0, // Polarity 0); // Phase @@ -273,38 +273,27 @@ void board_init(void) { // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - DTM2, // write_black_ram_command - true, // black_bits_inverted - DTM1, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO26, // busy_pin - false, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = DTM2; + args.black_bits_inverted = true; + args.write_color_ram_command = DTM1; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO26; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/raspberrypi/boards/pimoroni_badger2040w/board.c b/ports/raspberrypi/boards/pimoroni_badger2040w/board.c index 30c05273b9478..ef5da7ceabcb7 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040w/board.c +++ b/ports/raspberrypi/boards/pimoroni_badger2040w/board.c @@ -263,9 +263,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO20, // EPD_DC Command or data - &pin_GPIO17, // EPD_CS Chip select - &pin_GPIO21, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO20), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO21), // EPD_RST Reset 1200000, // Baudrate 0, // Polarity 0); // Phase @@ -273,38 +273,27 @@ void board_init(void) { // Set up the DisplayIO epaper object epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 296, // width - 128, // height - 160, // ram_width - 296, // ram_height - 0, // colstart - 0, // rowstart - 270, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - DTM2, // write_black_ram_command - true, // black_bits_inverted - DTM1, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), // refresh_display_command - 1.0, // refresh_time - &pin_GPIO26, // busy_pin - false, // busy_state - 2.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - false, // acep - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 296; + args.height = 128; + args.ram_width = 160; + args.ram_height = 296; + args.rotation = 270; + args.write_black_ram_command = DTM2; + args.black_bits_inverted = true; + args.write_color_ram_command = DTM1; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO26; + args.seconds_per_frame = 2.0; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } void board_deinit(void) { diff --git a/ports/raspberrypi/boards/pimoroni_badger2040w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_badger2040w/mpconfigboard.mk index 65b9b9bfc86ad..dc70c55195913 100644 --- a/ports/raspberrypi/boards/pimoroni_badger2040w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_badger2040w/mpconfigboard.mk @@ -22,7 +22,17 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 0 CIRCUITPY_USB_HOST = 0 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h b/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h new file mode 100644 index 0000000000000..4cc67efd4df7e --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/badger2350-shared.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +extern digitalio_digitalinout_obj_t i2c_power_en_pin_obj; +extern const mp_obj_fun_builtin_fixed_t set_update_speed_obj; +extern const mp_obj_fun_builtin_fixed_t get_reset_state_obj; +extern const mp_obj_fun_builtin_fixed_t on_reset_pressed_obj; diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/board.c b/ports/raspberrypi/boards/pimoroni_badger2350/board.c new file mode 100644 index 0000000000000..1da13b8033995 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/board.c @@ -0,0 +1,225 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" + +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/board.h" +#include "supervisor/board.h" +#include "badger2350-shared.h" + +#include "hardware/gpio.h" +#include "hardware/structs/iobank0.h" + +digitalio_digitalinout_obj_t i2c_power_en_pin_obj; +static volatile uint32_t reset_button_state = 0; + +// Forward declaration to satisfy -Wmissing-prototypes +static void preinit_button_state(void) __attribute__((constructor(101))); + + +// pin definitions +// Button pin definitions for Badger2350 +#define SW_A_PIN 7 +#define SW_B_PIN 9 +#define SW_C_PIN 10 +#define SW_DOWN_PIN 6 +#define SW_UP_PIN 11 + +static const uint8_t _sw_pin_nrs[] = { + SW_A_PIN, SW_B_PIN, SW_C_PIN, SW_DOWN_PIN, SW_UP_PIN +}; + +// Mask of all front button pins +#define SW_MASK ((1 << SW_A_PIN) | (1 << SW_B_PIN) | (1 << SW_C_PIN) | \ + (1 << SW_DOWN_PIN) | (1 << SW_UP_PIN)) + +// This function runs BEFORE main() via constructor attribute! +// This is the key to fast button state detection. +// Priority 101 = runs very early + +static void preinit_button_state(void) { + // Configure button pins as inputs with pull-downs using direct register access + // This is faster than SDK functions and works before full init + + for (size_t i = 0; i < sizeof(_sw_pin_nrs); i++) { + uint8_t pin_nr = _sw_pin_nrs[i]; + // Set as input + sio_hw->gpio_oe_clr = 1u << pin_nr; + // enable pull-ups + pads_bank0_hw->io[pin_nr] = PADS_BANK0_GPIO0_IE_BITS | + PADS_BANK0_GPIO0_PUE_BITS; + // Set GPIO function + iobank0_hw->io[pin_nr].ctrl = 5; // SIO function + } + + // Small delay for pins to settle (just a few cycles) + for (volatile int i = 0; i < 100; i++) { + __asm volatile ("nop"); + } + + // Capture button states NOW - before anything else runs + reset_button_state = ~sio_hw->gpio_in & SW_MASK; +} + +static mp_obj_t _get_reset_state(void) { + return mp_obj_new_int(reset_button_state); +} +MP_DEFINE_CONST_FUN_OBJ_0(get_reset_state_obj, _get_reset_state); + +static mp_obj_t _on_reset_pressed(mp_obj_t pin_in) { + mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_in); + return mp_obj_new_bool( + (reset_button_state & (1 << pin->number)) != 0); +} +MP_DEFINE_CONST_FUN_OBJ_1(on_reset_pressed_obj, _on_reset_pressed); + +// The display uses an SSD1680 control chip. +uint8_t _start_sequence[] = { + 0x12, 0x80, 0x00, 0x14, // soft reset and wait 20ms + 0x11, 0x00, 0x01, 0x03, // Ram data entry mode + 0x3c, 0x00, 0x01, 0x03, // border color + 0x2c, 0x00, 0x01, 0x28, // Set vcom voltage + 0x03, 0x00, 0x01, 0x17, // Set gate voltage + 0x04, 0x00, 0x03, 0x41, 0xae, 0x32, // Set source voltage + 0x4e, 0x00, 0x01, 0x00, // ram x count + 0x4f, 0x00, 0x02, 0x00, 0x00, // ram y count + 0x01, 0x00, 0x03, 0x07, 0x01, 0x00, // set display size + 0x32, 0x00, 0x99, // Update waveforms + + // offset 44 + 0x40, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L0 + 0xA0, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L1 + 0xA8, 0x65, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L2 + 0xAA, 0x65, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VS L4 + + // offset 104 + 0x02, 0x00, 0x00, 0x05, 0x0A, 0x00, 0x03, // Group0 (with default speed==0) + // offset 111 + 0x19, 0x19, 0x00, 0x02, 0x00, 0x00, 0x03, // Group1 (with default speed==0) + // offset 118 + 0x05, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x03, // Group2 (with default speed==0) + + // offset 125 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group5 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Group11 + 0x44, 0x42, 0x22, 0x22, 0x23, 0x32, 0x00, // Config + 0x00, 0x00, // FR, XON + + 0x22, 0x00, 0x01, 0xc7, // display update mode + +}; + +const uint8_t _stop_sequence[] = { + 0x10, 0x00, 0x01, 0x01 // DSM deep sleep mode 1 +}; + +const uint8_t _refresh_sequence[] = { + 0x20, 0x00, 0x00 // ADUS +}; + +// Change update speed. This changes the repeat-count in the LUTs +// Pimoroni uses: 0 == slow ... 3 == fast +// and calculates the LUT repeat count as 3-speed + +#define SPEED_OFFSET_1 110 +#define SPEED_OFFSET_2 117 +#define SPEED_OFFSET_3 124 + +static mp_obj_t _set_update_speed(mp_obj_t speed_in) { + mp_int_t speed = mp_obj_get_int(speed_in); + uint8_t count = (uint8_t)3 - (uint8_t)(speed & 3); + _start_sequence[SPEED_OFFSET_1] = count; + _start_sequence[SPEED_OFFSET_2] = count; + _start_sequence[SPEED_OFFSET_3] = count; + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_1(set_update_speed_obj, _set_update_speed); + +void board_init(void) { + // Drive the I2C_POWER_EN pin high + i2c_power_en_pin_obj.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct( + &i2c_power_en_pin_obj, &pin_GPIO27); + common_hal_digitalio_digitalinout_switch_to_output( + &i2c_power_en_pin_obj, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_never_reset(&i2c_power_en_pin_obj); + + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct(spi, &pin_GPIO18, &pin_GPIO19, NULL, false); + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO20), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO21), // EPD_RST Reset + 12000000, // Baudrate + 0, // Polarity + 0); // Phase + + // create and configure display + epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; + display->base.type = &epaperdisplay_epaperdisplay_type; + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = _start_sequence; + args.start_sequence_len = sizeof(_start_sequence); + args.stop_sequence = _stop_sequence; + args.stop_sequence_len = sizeof(_stop_sequence); + args.width = 264; + args.height = 176; + args.ram_width = 250; + args.ram_height = 296; + args.rotation = 270; + args.set_column_window_command = 0x44; + args.set_row_window_command = 0x45; + args.set_current_column_command = 0x4e; + args.set_current_row_command = 0x4f; + args.write_black_ram_command = 0x24; + args.write_color_ram_command = 0x26; + args.color_bits_inverted = true; + args.refresh_sequence = _refresh_sequence; + args.refresh_sequence_len = sizeof(_refresh_sequence); + args.refresh_time = 1.0; + args.busy_pin = &pin_GPIO16; + args.busy_state = true; + args.seconds_per_frame = 3.0; + args.grayscale = true; + args.two_byte_sequence_length = true; + args.address_little_endian = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); +} + +void board_deinit(void) { + epaperdisplay_epaperdisplay_obj_t *display = &displays[0].epaper_display; + if (display->base.type == &epaperdisplay_epaperdisplay_type) { + while (common_hal_epaperdisplay_epaperdisplay_get_busy(display)) { + RUN_BACKGROUND_TASKS; + } + } + common_hal_displayio_release_displays(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/link.ld b/ports/raspberrypi/boards/pimoroni_badger2350/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h new file mode 100644 index 0000000000000..6cffd190ad606 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Bernhard Bablok +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Pimoroni Badger 2350" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_GPIO0) + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk new file mode 100644 index 0000000000000..0157ccf149960 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/mpconfigboard.mk @@ -0,0 +1,38 @@ +USB_VID = 0x2E8A +USB_PID = 0x1100 +USB_PRODUCT = "Pimoroni Badger 2350" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +# PIO clock divider set to 2 (default), consider changing if TM2 gSPI +# becomes unreliable. +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_PIO_CLOCK_DIV_INT=2 \ + -DCYW43_PIO_CLOCK_DIV_FRAC=0 +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' + +FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-pcf85063a diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h new file mode 100644 index 0000000000000..42e0612bf8ba6 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_badger2350/pins.c b/ports/raspberrypi/boards/pimoroni_badger2350/pins.c new file mode 100644 index 0000000000000..1a66961e68fcf --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_badger2350/pins.c @@ -0,0 +1,135 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "badger2350-shared.h" + + +// LUT manipulation +static const mp_rom_map_elem_t lut_update_table[] = { + { MP_ROM_QSTR(MP_QSTR_SET_UPDATE_SPEED), (mp_obj_t)&set_update_speed_obj }, + { MP_ROM_QSTR(MP_QSTR_SPEED_SLOW), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FAST), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FASTER), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FASTEST), MP_ROM_INT(3) }, +}; +MP_DEFINE_CONST_DICT(lut_update_dict, lut_update_table); + +const mp_obj_module_t display_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&lut_update_dict, +}; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&display_module) }, + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_LED0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LED3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SW_DOWN), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO7) }, + + // GP8 is reserved for PSRAM chip select + + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_SW_C), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_SW_UP), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_RTC_ALARM), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SW_RESET), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SW_INT), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_INKY_BUSY), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_INKY_CS), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_INKY_DC), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_INKY_RST), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SW_HOME), MP_ROM_PTR(&pin_GPIO22) }, + + // GP23, GP24, GP25, and GP29 are reserved for RM2 gSPI + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_VBAT_SENSE), MP_ROM_PTR(&pin_GPIO26) }, + + // GP27 is the used for I2C power-enable, driven high by board.c + { MP_ROM_QSTR(MP_QSTR_I2C_POWER_EN), MP_ROM_PTR(&i2c_power_en_pin_obj) }, + + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_SENSE_1V1), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // Pins accessed though the RM2 module (CYW43439) + // CYW0, CYW1 is unconnected + { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].epaper_display)}, + + // button-state on reset + // Use `board.RESET_STATE()` to query the state of all buttons at reset. + // To detect individual key-presses, `board.ON_RESET_PRESSED()` + // is simpler. + { MP_ROM_QSTR(MP_QSTR_RESET_STATE), (mp_obj_t)&get_reset_state_obj }, + + // Use `board.ON_RESET_PRESSED(board.SW_A)` to check if `SW_A` was pressed + // during reset. + { MP_ROM_QSTR(MP_QSTR_ON_RESET_PRESSED), (mp_obj_t)&on_reset_pressed_obj }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/board.c b/ports/raspberrypi/boards/pimoroni_explorer2350/board.c new file mode 100644 index 0000000000000..d0c6d9a57ce9f --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/board.c @@ -0,0 +1,145 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/paralleldisplaybus/ParallelBus.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "hardware/gpio.h" + +// Display pins from Pimoroni Explorer parallel bus: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26} +#define LCD_BACKLIGHT_PIN 26 +#define LCD_CS_PIN 27 +#define LCD_DC_PIN 28 +#define LCD_WR_PIN 30 +#define LCD_RD_PIN 31 +#define LCD_D0_PIN 32 // Data pins are GPIO32-39 (8 consecutive pins) + +#define DELAY 0x80 + +// ST7789V display init sequence for 320x240 parallel bus +// Based on Pimoroni's pimoroni-pico ST7789 driver configuration +uint8_t display_init_sequence[] = { + // Software reset + 0x01, 0 | DELAY, 150, + // Sleep out + 0x11, 0 | DELAY, 255, + // Tearing effect line on (frame sync) + 0x35, 1, 0x00, + // COLMOD: 16-bit color (5-6-5 RGB) + 0x3A, 1, 0x55, + // Porch control (PORCTRL) + 0xB2, 5, 0x0C, 0x0C, 0x00, 0x33, 0x33, + // Gate control (GCTRL) - VGH=13.26V, VGL=-10.43V + 0xB7, 1, 0x35, + // VCOM setting (VCOMS) + 0xBB, 1, 0x1F, + // LCM control (LCMCTRL) + 0xC0, 1, 0x2C, + // VDV and VRH command enable (VDVVRHEN) + 0xC2, 1, 0x01, + // VRH set (VRHS) + 0xC3, 1, 0x12, + // VDV set (VDVS) + 0xC4, 1, 0x20, + // Frame rate control (FRCTRL2) + 0xC6, 1, 0x0F, + // Power control 1 (PWCTRL1) + 0xD0, 2, 0xA4, 0xA1, + // RAM control (RAMCTRL) - for proper endianness + 0xB0, 2, 0x00, 0xC0, + // Positive gamma correction + 0xE0, 14, 0xD0, 0x08, 0x11, 0x08, 0x0C, 0x15, 0x39, 0x33, 0x50, 0x36, 0x13, 0x14, 0x29, 0x2D, + // Negative gamma correction + 0xE1, 14, 0xD0, 0x08, 0x10, 0x08, 0x06, 0x06, 0x39, 0x44, 0x51, 0x0B, 0x16, 0x14, 0x2F, 0x31, + // Inversion on + 0x21, 0, + // Normal display mode on + 0x13, 0 | DELAY, 10, + // MADCTL: MX=0, MY=1, MV=1, ML=1 (COL_ORDER | SWAP_XY | SCAN_ORDER) = 0x70 + // This configures the 320x240 display in landscape orientation + 0x36, 1, 0x70, + // Display on + 0x29, 0 | DELAY, 100, +}; + +static void display_init(void) { + paralleldisplaybus_parallelbus_obj_t *bus = &allocate_display_bus()->parallel_bus; + bus->base.type = ¶lleldisplaybus_parallelbus_type; + + common_hal_paralleldisplaybus_parallelbus_construct(bus, + &pin_GPIO32, // Data0 (D0) - data pins are sequential GPIO32-39 + &pin_GPIO28, // Command/Data (DC) + &pin_GPIO27, // Chip select (CS) + &pin_GPIO30, // Write (WR) + &pin_GPIO31, // Read (RD) + NULL, // Reset (directly connected to board reset) + 15000000); // Frequency - ST7789 min clock cycle ~66ns = ~15MHz + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct(display, + bus, + 320, // Width + 240, // Height + 0, // column start + 0, // row start + 0, // rotation + 16, // Color depth + false, // grayscale + false, // pixels_in_byte_share_row + 1, // bytes per cell + false, // reverse_pixels_in_byte + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO26, // Backlight pin (BL) + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Ensure backlight is on before display init + board_reset_pin_number(LCD_BACKLIGHT_PIN); + display_init(); +} + +// Prevent the backlight pin from being reset, keeping display visible across soft resets +bool board_reset_pin_number(uint8_t pin_number) { + if (pin_number == LCD_BACKLIGHT_PIN) { + // Keep backlight on - set high output without glitching + gpio_put(pin_number, 1); + gpio_set_dir(pin_number, GPIO_OUT); + gpio_set_function(pin_number, GPIO_FUNC_SIO); + return true; + } + return false; +} + +void reset_board(void) { + // Keep backlight on during reset + board_reset_pin_number(LCD_BACKLIGHT_PIN); +} + +void board_deinit(void) { + // Backlight will be handled by board_reset_pin_number +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h new file mode 100644 index 0000000000000..dd269aa6b844a --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Pimoroni Explorer" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO21, .sda = &pin_GPIO20}} + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk new file mode 100644 index 0000000000000..4e4882910c8ab --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x2E8A +USB_PID = 0x10C0 +USB_PRODUCT = "Explorer" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h new file mode 100644 index 0000000000000..66b57dfd13dc2 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c b/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c new file mode 100644 index 0000000000000..8154a43de005d --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_explorer2350/pins.c @@ -0,0 +1,124 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // User GPIOs (accent connector) + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + // Servo pins + { MP_ROM_QSTR(MP_QSTR_SERVO1), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SERVO2), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SERVO3), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SERVO4), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + // Audio + { MP_ROM_QSTR(MP_QSTR_AUDIO), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_AMP_EN), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_SW_C), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_SW_B), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SW_X), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_SW_Y), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_SW_Z), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + // User button + { MP_ROM_QSTR(MP_QSTR_SW_USER), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + // LED? + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + // Display parallel bus pins (ST7789V 320x240) + // Pins from Pimoroni: {cs=27, dc=28, wr=30, rd=31, d0=32, bl=26} + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_LCD_WR), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_GP30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RD), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_GP31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D4), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D5), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_GP37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D6), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_LCD_D7), MP_ROM_PTR(&pin_GPIO39) }, + { MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) }, + + // ADC pins (RP2350B extended GPIOs) + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_ADC0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_ADC1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_ADC2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_ADC3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_ADC4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_ADC5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) }, + + // I2C object + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Display object + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c index 650d307711e8e..58c54334d59af 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/board.c @@ -58,47 +58,35 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO28, // EPD_DC Command or data - &pin_GPIO17, // EPD_CS Chip select - &pin_GPIO27, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO28), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO27), // EPD_RST Reset 1000000, // Baudrate 0, // Polarity 0); // Phase epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 1.0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 600, // width - 448, // height - 640, // ram_width - 480, // ram_height - 0, // colstart - 0, // rowstart - 0, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), - 28.0, // refresh_time - NULL, // busy_pin - false, // busy_state - 40.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - true, // acep - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 600; + args.height = 448; + args.ram_width = 640; + args.ram_height = 480; + args.write_black_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 28.0; + args.busy_pin = NULL; + args.seconds_per_frame = 40.0; + args.acep = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h index d2547cc161568..a8c404c422501 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.h @@ -14,8 +14,8 @@ #define MICROPY_HW_LED_STATUS (&pin_GPIO6) -#define DEFAULT_I2C_BUS_SCL (&pin_GPIO4) -#define DEFAULT_I2C_BUS_SDA (&pin_GPIO5) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) #define DEFAULT_UART_BUS_RX (&pin_GPIO1) diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk index c0f67869a086c..69b23a72be738 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_5_7/mpconfigboard.mk @@ -20,7 +20,17 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 0 CIRCUITPY_USB_HOST = 0 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c index a24c91e546da9..fc6ca67f3ae65 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/board.c @@ -117,47 +117,36 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO28, // EPD_DC Command or data - &pin_GPIO17, // EPD_CS Chip select - &pin_GPIO27, // EPD_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO28), // EPD_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO17), // EPD_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO27), // EPD_RST Reset 1000000, // Baudrate 0, // Polarity 0); // Phase epaperdisplay_epaperdisplay_obj_t *display = &allocate_display()->epaper_display; display->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - display, - bus, - display_start_sequence, sizeof(display_start_sequence), - 1.0, // start up time - display_stop_sequence, sizeof(display_stop_sequence), - 800, // width - 480, // height - 800, // ram_width - 480, // ram_height - 0, // colstart - 0, // rowstart - 180, // rotation - NO_COMMAND, // set_column_window_command - NO_COMMAND, // set_row_window_command - NO_COMMAND, // set_current_column_command - NO_COMMAND, // set_current_row_command - 0x10, // write_black_ram_command - false, // black_bits_inverted - NO_COMMAND, // write_color_ram_command - false, // color_bits_inverted - 0x000000, // highlight_color - refresh_sequence, sizeof(refresh_sequence), - 28.0, // refresh_time - NULL, // busy_pin - false, // busy_state - 30.0, // seconds_per_frame - false, // always_toggle_chip_select - false, // grayscale - true, // acep - false, // two_byte_sequence_length - false); // address_little_endian + + epaperdisplay_construct_args_t args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + args.bus = bus; + args.start_sequence = display_start_sequence; + args.start_sequence_len = sizeof(display_start_sequence); + args.start_up_time = 1.0; + args.stop_sequence = display_stop_sequence; + args.stop_sequence_len = sizeof(display_stop_sequence); + args.width = 800; + args.height = 480; + args.ram_width = 800; + args.ram_height = 480; + args.rotation = 180; + args.write_black_ram_command = 0x10; + args.refresh_sequence = refresh_sequence; + args.refresh_sequence_len = sizeof(refresh_sequence); + args.refresh_time = 28.0; + args.busy_pin = NULL; + args.seconds_per_frame = 30.0; + args.acep = true; + common_hal_epaperdisplay_epaperdisplay_construct(display, &args); } // Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.h index 42cb1196a5475..32477b12c299f 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.h +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.h @@ -14,8 +14,8 @@ #define MICROPY_HW_LED_STATUS (&pin_GPIO6) -#define DEFAULT_I2C_BUS_SCL (&pin_GPIO4) -#define DEFAULT_I2C_BUS_SDA (&pin_GPIO5) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) #define DEFAULT_UART_BUS_RX (&pin_GPIO1) diff --git a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.mk index ca57f8419ef70..ee04517499ee5 100644 --- a/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_inky_frame_7_3/mpconfigboard.mk @@ -20,7 +20,17 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 0 CIRCUITPY_USB_HOST = 0 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_pga2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_pga2350/mpconfigboard.mk index 5015062767d78..4091f6d1b0bc9 100644 --- a/ports/raspberrypi/boards/pimoroni_pga2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_pga2350/mpconfigboard.mk @@ -10,4 +10,3 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/pimoroni_pga2350/pins.c b/ports/raspberrypi/boards/pimoroni_pga2350/pins.c index 1a5d87a0c1b9e..47756d81b41c8 100644 --- a/ports/raspberrypi/boards/pimoroni_pga2350/pins.c +++ b/ports/raspberrypi/boards/pimoroni_pga2350/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/pimoroni_pico_dv_base_w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_pico_dv_base_w/mpconfigboard.mk index a1ab3b2939eca..9218192d08333 100644 --- a/ports/raspberrypi/boards/pimoroni_pico_dv_base_w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_pico_dv_base_w/mpconfigboard.mk @@ -20,7 +20,17 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 1 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_pico_plus2/mpconfigboard.mk index a6f18a3bf15cf..d47f28d64fb80 100644 --- a/ports/raspberrypi/boards/pimoroni_pico_plus2/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2/mpconfigboard.mk @@ -10,4 +10,3 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2/pins.c b/ports/raspberrypi/boards/pimoroni_pico_plus2/pins.c index fe4e4cdd92e54..1a8663d9a7e40 100644 --- a/ports/raspberrypi/boards/pimoroni_pico_plus2/pins.c +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, @@ -61,17 +61,25 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO45) }, { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO45) }, - { MP_ROM_QSTR(MP_QSTR_SPICE_CS), MP_ROM_PTR(&pin_GPIO33) }, - { MP_ROM_QSTR(MP_QSTR_SPICE_SCK), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_SPCE_CS), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) }, + + { MP_ROM_QSTR(MP_QSTR_SPCE_SCK), MP_ROM_PTR(&pin_GPIO34) }, { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO34) }, - { MP_ROM_QSTR(MP_QSTR_SPICE_TX), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) }, + + { MP_ROM_QSTR(MP_QSTR_SPCE_MOSI), MP_ROM_PTR(&pin_GPIO35) }, { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) }, - { MP_ROM_QSTR(MP_QSTR_SPICE_RX), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) }, + + { MP_ROM_QSTR(MP_QSTR_SPCE_MISO), MP_ROM_PTR(&pin_GPIO32) }, { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO32) }, - { MP_ROM_QSTR(MP_QSTR_SPICE_BL), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) }, + + { MP_ROM_QSTR(MP_QSTR_SPCE_BL), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) }, { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_GPIO36) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/board.c b/ports/raspberrypi/boards/pimoroni_pico_plus2w/board.c new file mode 100644 index 0000000000000..4878f16e66e5c --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/link.ld b/ports/raspberrypi/boards/pimoroni_pico_plus2w/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.h new file mode 100644 index 0000000000000..28f19c762f1fd --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Pimoroni Pico Plus 2 W" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_CYW0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO47) diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.mk new file mode 100644 index 0000000000000..b06c1246d3521 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/mpconfigboard.mk @@ -0,0 +1,37 @@ +USB_VID = 0x2E8A +USB_PID = 0x10BD +USB_PRODUCT = "Pico Plus 2 W" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +# PIO clock divider set to 2 (default), consider changing if TM2 gSPI +# becomes unreliable. +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 \ + -DCYW43_PIO_CLOCK_DIV_INT=2 \ + -DCYW43_PIO_CLOCK_DIV_FRAC=0 +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_pico_plus2w/pico-sdk-configboard.h new file mode 100644 index 0000000000000..42e0612bf8ba6 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_pico_plus2w/pins.c b/ports/raspberrypi/boards/pimoroni_pico_plus2w/pins.c new file mode 100644 index 0000000000000..718e9b978131c --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_pico_plus2w/pins.c @@ -0,0 +1,76 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + // GP23, GP24, GP25, and GP29 are reserved for RM2 gSPI + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + + // GP30 through GP39 are unconnected + + // GP40 through GP47 have analog input capability + { MP_ROM_QSTR(MP_QSTR_GP40_A0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_GP41_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_GP42_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO43) }, + + // GP44 is unconnected + + { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO45) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO45) }, + + // GP46 is unconnected + // GP47 is reserved for PSRAM chip select + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Pins accessed though the RM2 module (CYW43439) + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_CYW0) }, + // CYW1 is unconnected + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_picosystem/board.c b/ports/raspberrypi/boards/pimoroni_picosystem/board.c index 40756b56426e4..e5956e43ed110 100644 --- a/ports/raspberrypi/boards/pimoroni_picosystem/board.c +++ b/ports/raspberrypi/boards/pimoroni_picosystem/board.c @@ -51,9 +51,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO9, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - &pin_GPIO4, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO4), // TFT_RST Reset 60000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/pimoroni_plasma2040w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_plasma2040w/mpconfigboard.mk index 26a0ab6f83200..442991fa12622 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2040w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_plasma2040w/mpconfigboard.mk @@ -20,7 +20,17 @@ CIRCUITPY_WIFI = 1 CIRCUITPY_PICODVI = 0 CIRCUITPY_USB_HOST = 0 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h index 72b1e1d04399f..097cbd8baa301 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h +++ b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.h @@ -5,7 +5,7 @@ // SPDX-License-Identifier: MIT #define MICROPY_HW_BOARD_NAME "Pimoroni Plasma 2350" -#define MICROPY_HW_MCU_NAME "rp2350b" +#define MICROPY_HW_MCU_NAME "rp2350a" #define CIRCUITPY_RGB_STATUS_INVERTED_PWM #define CIRCUITPY_RGB_STATUS_R (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk index 6e7b7497f5d77..56fd7b641de3a 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_plasma2350/mpconfigboard.mk @@ -10,4 +10,3 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350/pins.c b/ports/raspberrypi/boards/pimoroni_plasma2350/pins.c index 1c1ab4def7779..5aca457df80cf 100644 --- a/ports/raspberrypi/boards/pimoroni_plasma2350/pins.c +++ b/ports/raspberrypi/boards/pimoroni_plasma2350/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/board.c b/ports/raspberrypi/boards/pimoroni_plasma2350w/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/link.ld b/ports/raspberrypi/boards/pimoroni_plasma2350w/link.ld new file mode 100644 index 0000000000000..d1edd9567c56a --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/link.ld @@ -0,0 +1 @@ +firmware_size = 3064k; diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h new file mode 100644 index 0000000000000..576299d939cfb --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Pimoroni Plasma 2350W" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_RGB_STATUS_INVERTED_PWM +#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO16) +#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO17) +#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO18) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO21, .sda = &pin_GPIO20}} + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO21) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO20) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO10) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO11) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO8) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk new file mode 100644 index 0000000000000..8563f0d0034c3 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/mpconfigboard.mk @@ -0,0 +1,35 @@ +USB_VID = 0x2E8A +USB_PID = 0x10BF +USB_PRODUCT = "Plasma 2350 W" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 +CIRCUITPY_PICODVI = 0 +CIRCUITPY_USB_HOST = 0 + +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(3064 * 1024)' diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_plasma2350w/pico-sdk-configboard.h new file mode 100644 index 0000000000000..66b57dfd13dc2 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_plasma2350w/pins.c b/ports/raspberrypi/boards/pimoroni_plasma2350w/pins.c new file mode 100644 index 0000000000000..e49812ba803a5 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_plasma2350w/pins.c @@ -0,0 +1,78 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + // GPIO2 through GPIO11 are unconnected + + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_SW_A), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO12) }, + + // GPIO13 is unconnected + + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_CLK), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_DATA), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_SW_BOOT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO22) }, + + // GPIO23 through GPIO25 are connected to the RM2 module + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + // GPIO29 is connected to the RM2 module + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk index 04569b08cfb3d..9ffdf263003f7 100644 --- a/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/pimoroni_tiny2350/mpconfigboard.mk @@ -10,4 +10,3 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/pimoroni_tiny2350/pins.c b/ports/raspberrypi/boards/pimoroni_tiny2350/pins.c index ae026f69fcabc..63f83ca9373df 100644 --- a/ports/raspberrypi/boards/pimoroni_tiny2350/pins.c +++ b/ports/raspberrypi/boards/pimoroni_tiny2350/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/pimoroni_tinyfx/board.c b/ports/raspberrypi/boards/pimoroni_tinyfx/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_tinyfx/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.h b/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.h new file mode 100644 index 0000000000000..3d4cfd59652ed --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Pimoroni Tiny FX" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define CIRCUITPY_RGB_STATUS_INVERTED_PWM +#define CIRCUITPY_RGB_STATUS_R (&pin_GPIO13) +#define CIRCUITPY_RGB_STATUS_G (&pin_GPIO14) +#define CIRCUITPY_RGB_STATUS_B (&pin_GPIO15) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO17) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.mk b/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.mk new file mode 100644 index 0000000000000..7708e8f264ca5 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_tinyfx/mpconfigboard.mk @@ -0,0 +1,13 @@ +USB_VID = 0x2E8A +USB_PID = 0x10A2 +USB_PRODUCT = "Tiny FX" +USB_MANUFACTURER = "Pimoroni" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_PICODVI = 0 +CIRCUITPY_USB_HOST = 0 diff --git a/ports/raspberrypi/boards/pimoroni_tinyfx/pico-sdk-configboard.h b/ports/raspberrypi/boards/pimoroni_tinyfx/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_tinyfx/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/pimoroni_tinyfx/pins.c b/ports/raspberrypi/boards/pimoroni_tinyfx/pins.c new file mode 100644 index 0000000000000..1ca4c38049548 --- /dev/null +++ b/ports/raspberrypi/boards/pimoroni_tinyfx/pins.c @@ -0,0 +1,45 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_LED_1), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_LED_2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_LED_3), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_LED_4), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_LED_5), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LED_6), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_I2S_DATA), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_I2S_BCLK), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_I2S_LRCLK), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_AMP_EN), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_USER_SW), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SENSOR), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_CURRENT_SENSE), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/proveskit_rp2040_v4/board.c b/ports/raspberrypi/boards/proveskit_rp2040_v4/board.c new file mode 100644 index 0000000000000..6dc59205e4eb0 --- /dev/null +++ b/ports/raspberrypi/boards/proveskit_rp2040_v4/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "common-hal/microcontroller/Pin.h" diff --git a/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.h b/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.h new file mode 100644 index 0000000000000..4c2f9a93b0743 --- /dev/null +++ b/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "PROVES Kit v4" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO24) + +#define CIRCUITPY_DRIVE_LABEL "PROVESKIT" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO3) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO2) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO10) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO8) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO11) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.mk b/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.mk new file mode 100644 index 0000000000000..7ae012032f711 --- /dev/null +++ b/ports/raspberrypi/boards/proveskit_rp2040_v4/mpconfigboard.mk @@ -0,0 +1,9 @@ +USB_VID = 0x1209 +USB_PID = 0xE004 +USB_PRODUCT = "ProvesKit RP2040 v4" +USB_MANUFACTURER = "Bronco Space" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "GD25Q64C,W25Q64JVxQ" diff --git a/ports/raspberrypi/boards/proveskit_rp2040_v4/pico-sdk-configboard.h b/ports/raspberrypi/boards/proveskit_rp2040_v4/pico-sdk-configboard.h new file mode 100644 index 0000000000000..d109816d1382f --- /dev/null +++ b/ports/raspberrypi/boards/proveskit_rp2040_v4/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/proveskit_rp2040_v4/pins.c b/ports/raspberrypi/boards/proveskit_rp2040_v4/pins.c new file mode 100644 index 0000000000000..cb3861010fccb --- /dev/null +++ b/ports/raspberrypi/boards/proveskit_rp2040_v4/pins.c @@ -0,0 +1,55 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "supervisor/board.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_SPI0_CS1), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_NEO_PWR), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_SPI0_CS2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_I2C1_SDA), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_I2C1_SCL), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_I2C0_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_I2C0_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_PC), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_VS), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_SPI0_MISO), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_SPI0_CS0), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_SPI0_SCK), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_SPI0_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_RF1_RST), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_WDT_WDI), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_RF1_IO4), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_RF1_IO0), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIX), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_HS), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2/mpconfigboard.mk b/ports/raspberrypi/boards/raspberry_pi_pico2/mpconfigboard.mk index 7a684716674db..43328dd47094d 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico2/mpconfigboard.mk +++ b/ports/raspberrypi/boards/raspberry_pi_pico2/mpconfigboard.mk @@ -10,4 +10,3 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2/pins.c b/ports/raspberrypi/boards/raspberry_pi_pico2/pins.c index c618a8b1b0605..d3626838f8266 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico2/pins.c +++ b/ports/raspberrypi/boards/raspberry_pi_pico2/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/board.c b/ports/raspberrypi/boards/raspberry_pi_pico2_w/board.c new file mode 100644 index 0000000000000..299f32da04f8c --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/link.ld b/ports/raspberrypi/boards/raspberry_pi_pico2_w/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.h b/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.h new file mode 100644 index 0000000000000..4f13dd13efc6c --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico 2 W" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_CYW0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.mk b/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.mk new file mode 100644 index 0000000000000..e1407c16854a4 --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/mpconfigboard.mk @@ -0,0 +1,35 @@ +USB_VID = 0x239A +USB_PID = 0x8162 +USB_PRODUCT = "Pico 2 W" +USB_MANUFACTURER = "Raspberry Pi" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 \ + -DCYW43_PIO_CLOCK_DIV_INT=3 + +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/pico-sdk-configboard.h b/ports/raspberrypi/boards/raspberry_pi_pico2_w/pico-sdk-configboard.h new file mode 100644 index 0000000000000..945802d1ab116 --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/raspberry_pi_pico2_w/pins.c b/ports/raspberrypi/boards/raspberry_pi_pico2_w/pins.c new file mode 100644 index 0000000000000..7ec6b40972423 --- /dev/null +++ b/ports/raspberrypi/boards/raspberry_pi_pico2_w/pins.c @@ -0,0 +1,59 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_CYW1) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_CYW0) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk index 157c0eb03be3f..e658db65f4da5 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk +++ b/ports/raspberrypi/boards/raspberry_pi_pico_w/mpconfigboard.mk @@ -21,6 +21,16 @@ CIRCUITPY_SOCKETPOOL = 1 CIRCUITPY_WIFI = 1 -CFLAGS += -DCYW43_PIN_WL_HOST_WAKE=24 -DCYW43_PIN_WL_REG_ON=23 -DCYW43_WL_GPIO_COUNT=3 -DCYW43_WL_GPIO_LED_PIN=0 +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + # Must be accompanied by a linker script change CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/board.c b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/board.c new file mode 100644 index 0000000000000..8faea076dc9c6 --- /dev/null +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.h b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.h new file mode 100644 index 0000000000000..3adcc169f6dbf --- /dev/null +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Seeeduino XIAO RP2350" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO22) +#define CIRCUITPY_STATUS_LED_POWER (&pin_GPIO23) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO7) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO6) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO2) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk new file mode 100644 index 0000000000000..d5f866bd89e92 --- /dev/null +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/mpconfigboard.mk @@ -0,0 +1,10 @@ +USB_VID = 0x2886 +USB_PID = 0x0058 +USB_PRODUCT = "Seeeduino XIAO RP2350" +USB_MANUFACTURER = "Seeed" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "P25Q16H" diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pins.c b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pins.c new file mode 100644 index 0000000000000..ae50e5ffa2669 --- /dev/null +++ b/ports/raspberrypi/boards/seeeduino_xiao_rp2350/pins.c @@ -0,0 +1,68 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_BAT_ADC_EN), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO3) }, + + // Expansion pads + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL_POWER), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/solderparty_rp2350_stamp/mpconfigboard.mk b/ports/raspberrypi/boards/solderparty_rp2350_stamp/mpconfigboard.mk index 1e98eb99a0bb1..7f050ee335239 100644 --- a/ports/raspberrypi/boards/solderparty_rp2350_stamp/mpconfigboard.mk +++ b/ports/raspberrypi/boards/solderparty_rp2350_stamp/mpconfigboard.mk @@ -10,8 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 -CIRCUITPY_PICODVI = 1 FROZEN_MPY_DIRS += $(TOP)/ports/raspberrypi/boards/solderparty_rp2040_stamp FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID diff --git a/ports/raspberrypi/boards/solderparty_rp2350_stamp/pins.c b/ports/raspberrypi/boards/solderparty_rp2350_stamp/pins.c index 8bea812108899..cf17933536094 100644 --- a/ports/raspberrypi/boards/solderparty_rp2350_stamp/pins.c +++ b/ports/raspberrypi/boards/solderparty_rp2350_stamp/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/mpconfigboard.mk b/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/mpconfigboard.mk index 1e9480dcb7a8d..92486e16d5748 100644 --- a/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/mpconfigboard.mk +++ b/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/mpconfigboard.mk @@ -10,8 +10,6 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" CIRCUITPY__EVE = 1 -CIRCUITPY_ALARM = 0 -CIRCUITPY_PICODVI = 1 FROZEN_MPY_DIRS += $(TOP)/ports/raspberrypi/boards/solderparty_rp2040_stamp FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID diff --git a/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/pins.c b/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/pins.c index 6e81890751d28..81811367c2f41 100644 --- a/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/pins.c +++ b/ports/raspberrypi/boards/solderparty_rp2350_stamp_xl/pins.c @@ -6,7 +6,7 @@ #include "shared-bindings/board/__init__.h" -STATIC const mp_rom_map_elem_t board_module_globals_table[] = { +static const mp_rom_map_elem_t board_module_globals_table[] = { CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, diff --git a/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk index c1c10b82dc6e1..e5d6e1b8ff8f6 100644 --- a/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk +++ b/ports/raspberrypi/boards/sparkfun_pro_micro_rp2350/mpconfigboard.mk @@ -8,10 +8,3 @@ CHIP_PACKAGE = A CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" - -CIRCUITPY_ALARM = 0 -CIRCUITPY_RGBMATRIX = 0 -CIRCUITPY_USB_HOST = 0 - -CIRCUITPY_FLOPPYIO = 0 -CIRCUITPY_PICODVI = 1 diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/board.c b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/link.ld b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.h b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.h new file mode 100644 index 0000000000000..86891e2dca583 --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "SparkFun Thing Plus RP2350" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO14) + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO7) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO6) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO2) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO3) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO4) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO8) + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_CYW0) diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk new file mode 100644 index 0000000000000..6e81a229961da --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/mpconfigboard.mk @@ -0,0 +1,39 @@ +USB_VID = 0x1B4F +USB_PID = 0x0038 +USB_PRODUCT = "Thing Plus RP2350" +USB_MANUFACTURER = "SparkFun" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel/ + +CIRCUITPY_USB_HOST = 0 + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + + +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 + +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pico-sdk-configboard.h b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pico-sdk-configboard.h new file mode 100644 index 0000000000000..2d9283a9192f2 --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pico-sdk-configboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pins.c b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pins.c new file mode 100644 index 0000000000000..3710272e1f0ac --- /dev/null +++ b/ports/raspberrypi/boards/sparkfun_thing_plus_rp2350/pins.c @@ -0,0 +1,65 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_D28), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_CYW0) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/board.c b/ports/raspberrypi/boards/studiolab_picoexpander/board.c new file mode 100644 index 0000000000000..299f32da04f8c --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/link.ld b/ports/raspberrypi/boards/studiolab_picoexpander/link.ld new file mode 100644 index 0000000000000..e814bead4c51e --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/link.ld @@ -0,0 +1 @@ +firmware_size = 1532k; diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.h b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.h new file mode 100644 index 0000000000000..ea475f6822261 --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "Studiolab Pico Expander" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE (1) + +#define MICROPY_HW_LED_STATUS (&pin_CYW0) +#define MICROPY_HW_NEOPIXEL (&pin_GPIO2) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO16}} diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk new file mode 100644 index 0000000000000..eabc2c41e0722 --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/mpconfigboard.mk @@ -0,0 +1,35 @@ +USB_VID = 0x1209 +USB_PID = 0xC1C1 +USB_PRODUCT = "StudioLab Pico Expander" +USB_MANUFACTURER = "Raspberry Pi" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 + +CIRCUITPY_CYW43 = 1 +CIRCUITPY_SSL = 1 +CIRCUITPY_HASHLIB = 1 +CIRCUITPY_WEB_WORKFLOW = 1 +CIRCUITPY_MDNS = 1 +CIRCUITPY_SOCKETPOOL = 1 +CIRCUITPY_WIFI = 1 + +CFLAGS += \ + -DCYW43_PIN_WL_DYNAMIC=0 \ + -DCYW43_DEFAULT_PIN_WL_HOST_WAKE=24 \ + -DCYW43_DEFAULT_PIN_WL_REG_ON=23 \ + -DCYW43_DEFAULT_PIN_WL_CLOCK=29 \ + -DCYW43_DEFAULT_PIN_WL_DATA_IN=24 \ + -DCYW43_DEFAULT_PIN_WL_DATA_OUT=24 \ + -DCYW43_DEFAULT_PIN_WL_CS=25 \ + -DCYW43_WL_GPIO_COUNT=3 \ + -DCYW43_WL_GPIO_LED_PIN=0 \ + -DCYW43_PIO_CLOCK_DIV_INT=3 + +# Must be accompanied by a linker script change +CFLAGS += -DCIRCUITPY_FIRMWARE_SIZE='(1536 * 1024)' diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/pico-sdk-configboard.h b/ports/raspberrypi/boards/studiolab_picoexpander/pico-sdk-configboard.h new file mode 100644 index 0000000000000..945802d1ab116 --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/studiolab_picoexpander/pins.c b/ports/raspberrypi/boards/studiolab_picoexpander/pins.c new file mode 100644 index 0000000000000..6faafbfd177ea --- /dev/null +++ b/ports/raspberrypi/boards/studiolab_picoexpander/pins.c @@ -0,0 +1,113 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + + { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + + { MP_ROM_QSTR(MP_QSTR_BTN), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_A26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_A27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_A28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_CYW1) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_CYW0) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_CYW2) }, + + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/board.c b/ports/raspberrypi/boards/tinycircuits_thumby/board.c new file mode 100644 index 0000000000000..3a306b35f0d76 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/board.c @@ -0,0 +1,81 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +uint8_t display_init_sequence[] = { + 0xAE, 0, // DISPLAY_OFF + 0x20, 1, 0x00, // Set memory addressing to horizontal mode. + 0x81, 1, 0xcf, // set contrast control + 0xA1, 0, // Column 127 is segment 0 + 0xA6, 0, // Normal display + 0xc8, 0, // Normal display + 0xA8, 1, 0x3f, // Mux ratio is 1/64 + 0xd5, 1, 0x80, // Set divide ratio + 0xd9, 1, 0xf1, // Set pre-charge period + 0xda, 1, 0x12, // Set com configuration + 0xdb, 1, 0x40, // Set vcom configuration + 0x8d, 1, 0x14, // Enable charge pump + 0xAF, 0, // DISPLAY_ON +}; + +void board_init(void) { + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + bus->base.type = &fourwire_fourwire_type; + common_hal_fourwire_fourwire_construct(bus, + spi, + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_DC), // Command or data + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_CS), // Chip select + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_OLED_RESET), // Reset + 10000000, // Baudrate + 0, // Polarity + 0); // Phase + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 72, // Width (after rotation) + 40, // Height (after rotation) + 28, // column start + 28, // row start + 0, // rotation + 1, // Color depth + true, // grayscale + false, // pixels in byte share row. only used for depth < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + 0x21, // Set column command + 0x22, // Set row command + 44, // Write memory command + display_init_sequence, + sizeof(display_init_sequence), + NULL, // backlight pin + 0x81, + 1.0f, // brightness + true, // single_byte_bounds + true, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 0); // backlight pwm frequency +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h new file mode 100644 index 0000000000000..cec0fc10f55b1 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_OLED_DC (&pin_GPIO17) +#define CIRCUITPY_BOARD_OLED_CS (&pin_GPIO16) +#define CIRCUITPY_BOARD_OLED_RESET (&pin_GPIO20) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk new file mode 100644 index 0000000000000..d8140e6cb0a13 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x1209 +USB_PID = 0x3500 +USB_PRODUCT = "Thumby" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_framebuf +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_SSD1306 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h new file mode 100644 index 0000000000000..ce5a7645b4e22 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pico-sdk-configboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. + +// Allow extra time for xosc to start. +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c new file mode 100644 index 0000000000000..0a087bb8db8a9 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby/pins.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Link Cable (ASR00074) + { MP_ROM_QSTR(MP_QSTR_EXT_TX), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_EXT), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_EXT_PU), MP_ROM_PTR(&pin_GPIO1) }, + + // 0.42 inch OLED AST1042 + { MP_ROM_QSTR(MP_QSTR_OLED_CS), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_CS) }, + { MP_ROM_QSTR(MP_QSTR_OLED_DC), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_DC) }, + { MP_ROM_QSTR(MP_QSTR_OLED_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_OLED_RESET) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}, + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_1), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_2), MP_ROM_PTR(&pin_GPIO27) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO28) }, + + // Hardware revision ID pins + { MP_OBJ_NEW_QSTR(MP_QSTR_ID3), MP_ROM_PTR(&pin_GPIO12) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID2), MP_ROM_PTR(&pin_GPIO13) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID1), MP_ROM_PTR(&pin_GPIO14) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ID0), MP_ROM_PTR(&pin_GPIO15) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO26) } +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c new file mode 100644 index 0000000000000..17c512cb2a637 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/board.c @@ -0,0 +1,108 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/fourwire/FourWire.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + + +#define DELAY 0x80 + +// display init sequence according to TinyCircuits-Tiny-Game-Engine +uint8_t display_init_sequence[] = { + 0xFE, 0, // inter register enable 1 + 0xEF, 0, // inter register enable 2 + 0xB0, 1, 0xC0, + 0xB1, 1, 0x80, + 0xB2, 1, 0x2F, + 0xB3, 1, 0x03, + 0xB7, 1, 0x01, + 0xB6, 1, 0x19, + 0xAC, 1, 0xC8, // Complement Principle of RGB 5, 6, 5 + 0xAB, 1, 0x0f, // ? + 0x3A, 1, 0x05, // COLMOD: Pixel Format Set + 0xB4, 1, 0x04, // ? + 0xA8, 1, 0x07, // Frame Rate Set + 0xB8, 1, 0x08, // ? + 0xE7, 1, 0x5A, // VREG_CTL + 0xE8, 1, 0x23, // VGH_SET + 0xE9, 1, 0x47, // VGL_SET + 0xEA, 1, 0x99, // VGH_VGL_CLK + 0xC6, 1, 0x30, // ? + 0xC7, 1, 0x1F, // ? + 0xF0, 14, 0x05, 0x1D, 0x51, 0x2F, 0x85, 0x2A, 0x11, 0x62, 0x00, 0x07, 0x07, 0x0F, 0x08, 0x1F, // SET_GAMMA1 + 0xF1, 14, 0x2E, 0x41, 0x62, 0x56, 0xA5, 0x3A, 0x3f, 0x60, 0x0F, 0x07, 0x0A, 0x18, 0x18, 0x1D, // SET_GAMMA2 + 0x11, 0 | DELAY, 120, + 0x29, 0 | DELAY, 10, // display on +}; + +void board_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct( + spi, + DEFAULT_SPI_BUS_SCK, // CLK + DEFAULT_SPI_BUS_MOSI, // MOSI + NULL, // MISO not connected + false // Not half-duplex + ); + + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_DC), // DC + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_CS), // CS + MP_OBJ_FROM_PTR(CIRCUITPY_BOARD_LCD_RESET), // RST + 80000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 128, // width (after rotation) + 128, // height (after rotation) + 0, // column start + 0, // row start + 0, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + CIRCUITPY_BOARD_LCD_BACKLIGHT, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void reset_board(void) { +} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h new file mode 100644 index 0000000000000..fc76138bb8a0b --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "TinyCircuits Thumby Color" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO9) +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO8) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = DEFAULT_I2C_BUS_SCL, .sda = DEFAULT_I2C_BUS_SDA}} + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) + +#define CIRCUITPY_BOARD_LCD_DC (&pin_GPIO16) +#define CIRCUITPY_BOARD_LCD_CS (&pin_GPIO17) +#define CIRCUITPY_BOARD_LCD_RESET (&pin_GPIO4) +#define CIRCUITPY_BOARD_LCD_BACKLIGHT (&pin_GPIO7) + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = DEFAULT_SPI_BUS_SCK, .mosi = DEFAULT_SPI_BUS_MOSI, .miso = NULL}} diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk new file mode 100644 index 0000000000000..828d4a638d5ab --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/mpconfigboard.mk @@ -0,0 +1,15 @@ +USB_VID = 0x1209 +USB_PID = 0x3501 +USB_PRODUCT = "Thumby Color" +USB_MANUFACTURER = "TinyCircuits" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY_STAGE = 1 +CIRCUITPY_AUDIOIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 +CIRCUITPY_KEYPAD = 1 diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c new file mode 100644 index 0000000000000..d0e63512d7ab6 --- /dev/null +++ b/ports/raspberrypi/boards/tinycircuits_thumby_color/pins.c @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // Buttons + { MP_ROM_QSTR(MP_QSTR_BUTTON_UP), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_LEFT), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_DOWN), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_RIGHT), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_LEFT), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_BUMPER_RIGHT), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_MENU), MP_ROM_PTR(&pin_GPIO26) }, + + // LED + { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_GPIO12) }, + + // Rumble + { MP_ROM_QSTR(MP_QSTR_RUMBLE), MP_ROM_PTR(&pin_GPIO5) }, + + // Mono PWM Speaker + { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_SPEAKER_ENABLE), MP_ROM_PTR(&pin_GPIO20) }, + + // 0.85 inch TFT GC9107 + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_CS) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_DC) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_RESET) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(CIRCUITPY_BOARD_LCD_BACKLIGHT) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SCK), MP_ROM_PTR(DEFAULT_SPI_BUS_SCK) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(DEFAULT_SPI_BUS_MOSI) }, + + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + + // RTC I2C + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(DEFAULT_I2C_BUS_SDA) }, + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(DEFAULT_I2C_BUS_SCL) }, + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_CHARGE_STAT), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/ugame22/board.c b/ports/raspberrypi/boards/ugame22/board.c index a208326a09439..ed17a13ebc105 100644 --- a/ports/raspberrypi/boards/ugame22/board.c +++ b/ports/raspberrypi/boards/ugame22/board.c @@ -7,7 +7,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/fourwire/FourWire.h" @@ -52,9 +52,9 @@ void board_init(void) { bus->base.type = &fourwire_fourwire_type; common_hal_fourwire_fourwire_construct(bus, spi, - &pin_GPIO4, // TFT_DC Command or data - &pin_GPIO5, // TFT_CS Chip select - &pin_GPIO1, // TFT_RST Reset + MP_OBJ_FROM_PTR(&pin_GPIO4), // TFT_DC Command or data + MP_OBJ_FROM_PTR(&pin_GPIO5), // TFT_CS Chip select + MP_OBJ_FROM_PTR(&pin_GPIO1), // TFT_RST Reset 80000000L, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/raspberrypi/boards/waveshare_rp2040_geek/board.c b/ports/raspberrypi/boards/waveshare_rp2040_geek/board.c index 71269f0d1852f..431840fb0c5c1 100644 --- a/ports/raspberrypi/boards/waveshare_rp2040_geek/board.c +++ b/ports/raspberrypi/boards/waveshare_rp2040_geek/board.c @@ -37,9 +37,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO8, // TFT_DC - &pin_GPIO9, // TFT_CS - &pin_GPIO12, // TFT_RST + MP_OBJ_FROM_PTR(&pin_GPIO8), // TFT_DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // TFT_RST 50000000, // Baudrate 0, // Polarity 0 // Phase diff --git a/ports/raspberrypi/boards/waveshare_rp2040_lcd_0_96/board.c b/ports/raspberrypi/boards/waveshare_rp2040_lcd_0_96/board.c index f17ca53d72464..44d279da43fed 100644 --- a/ports/raspberrypi/boards/waveshare_rp2040_lcd_0_96/board.c +++ b/ports/raspberrypi/boards/waveshare_rp2040_lcd_0_96/board.c @@ -60,9 +60,9 @@ static void display_init(void) { common_hal_fourwire_fourwire_construct( bus, spi, - &pin_GPIO8, // DC - &pin_GPIO9, // CS - &pin_GPIO12, // RST + MP_OBJ_FROM_PTR(&pin_GPIO8), // DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // RST 40000000, // baudrate 0, // polarity 0 // phase diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/board.c b/ports/raspberrypi/boards/waveshare_rp2350_geek/board.c new file mode 100644 index 0000000000000..431840fb0c5c1 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/board.c @@ -0,0 +1,86 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + + +#include "mpconfigboard.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" +#include "shared-bindings/board/__init__.h" + +#define DELAY 0x80 + + +// display init sequence according to https://github.com/adafruit/Adafruit_CircuitPython_ST7789 +uint8_t display_init_sequence[] = { + 0x01, 0 | DELAY, 0x96, // _SWRESET and Delay 150ms + 0x11, 0 | DELAY, 0xFF, // _SLPOUT and Delay 500ms + 0x3A, 0x81, 0x55, 0x0A, // _COLMOD and Delay 10ms + 0x36, 0x01, 0x08, // _MADCTL + 0x21, 0 | DELAY, 0x0A, // _INVON Hack and Delay 10ms + 0x13, 0 | DELAY, 0x0A, // _NORON and Delay 10ms + 0x36, 0x01, 0xC0, // _MADCTL + 0x29, 0 | DELAY, 0xFF, // _DISPON and Delay 500ms +}; + +static void display_init(void) { + + busio_spi_obj_t *spi = common_hal_board_create_spi(0); + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO8), // TFT_DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // TFT_CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // TFT_RST + 50000000, // Baudrate + 0, // Polarity + 0 // Phase + + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 240, // Width + 135, // Height + 53, // column start + 40, // row start + 270, // rotation + 16, // Color depth + false, // Grayscale + false, // Pixels in a byte share a row + 1, // bytes per cell + false, // reverse_pixels_in_byte + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO25, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 1000 // backlight pwm frequency + ); +} + +void board_init(void) { + display_init(); +} diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.h new file mode 100644 index 0000000000000..2578897311547 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-GEEK" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO29, .sda = &pin_GPIO28}} + +#define CIRCUITPY_BOARD_SPI (2) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO10, .mosi = &pin_GPIO11}, \ + {.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO20}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO4, .rx = &pin_GPIO5}} diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk new file mode 100644 index 0000000000000..38b69c182c778 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B6 +USB_PRODUCT = "RP2350-GEEK" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_geek/pico-sdk-configboard.h new file mode 100644 index 0000000000000..a2e741ef9e5fe --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_geek/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_geek/pins.c new file mode 100644 index 0000000000000..8fa4f56051e40 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_geek/pins.c @@ -0,0 +1,78 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +CIRCUITPY_BOARD_BUS_SINGLETON(sd_spi, spi, 1) +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + // 2-3 DEBUG + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + // 4-5 UART + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + // 8-12 LCD + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + // 16-17 I2C + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + // 18-23 SD Card + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + // 25 LCD Backlight + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + // 28-29 I2C + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + + // UART + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + + // I2C + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + + // SPI SD Card + { MP_ROM_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_GPIO18)}, + { MP_ROM_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_GPIO19)}, + { MP_ROM_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_GPIO20)}, + { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_GPIO23)}, + { MP_ROM_QSTR(MP_QSTR_SD_SPI), MP_ROM_PTR(&board_sd_spi_obj) }, + + // SDIO SD Card + { MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO18)}, + { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_GPIO19)}, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA0), MP_ROM_PTR(&pin_GPIO20)}, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA1), MP_ROM_PTR(&pin_GPIO21)}, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA2), MP_ROM_PTR(&pin_GPIO22)}, + { MP_ROM_QSTR(MP_QSTR_SDIO_DATA3), MP_ROM_PTR(&pin_GPIO23)}, + + // LCD + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_MOSI), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BACKLIGHT), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_LCD_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/board.c b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/board.c new file mode 100644 index 0000000000000..44d279da43fed --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/board.c @@ -0,0 +1,109 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/displayio/mipi_constants.h" + +#define DELAY 0x80 + + +// display init sequence according to Adafruit_CircuitPython_ST7735R +// https://github.com/adafruit/Adafruit_CircuitPython_ST7735R +uint8_t display_init_sequence[] = { + // sw reset + 0x01, 0 | DELAY, 0x96, + // SLPOUT and Delay + 0x11, 0 | DELAY, 0xFF, + 0xB1, 0x03, 0x01, 0x2C, 0x2D, // _FRMCTR1 + 0xB3, 0x06, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D, // _FRMCTR3 + 0xB4, 0x01, 0x07, // _INVCTR line inversion + 0xC0, 0x03, 0xA2, 0x02, 0x84, // _PWCTR1 GVDD = 4.7V, 1.0uA + 0xC1, 0x01, 0xC5, // _PWCTR2 VGH=14.7V, VGL=-7.35V + 0xC2, 0x02, 0x0A, 0x00, // _PWCTR3 Opamp current small, Boost frequency + 0xC3, 0x02, 0x8A, 0x2A, + 0xC4, 0x02, 0x8A, 0xEE, + 0xC5, 0x01, 0x0E, // _VMCTR1 VCOMH = 4V, VOML = -1.1V + 0x20, 0x00, // _INVOFF + 0x36, 0x01, 0x18, // _MADCTL bottom to top refresh + // 1 clk cycle nonoverlap, 2 cycle gate rise, 3 cycle osc equalie, + // fix on VTL + 0x3A, 0x01, 0x05, // COLMOD - 16bit color + 0xE0, 0x10, 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10, // _GMCTRP1 Gamma + 0xE1, 0x10, 0x03, 0x1D, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10, // _GMCTRN1 + 0x13, 0 | DELAY, 0x0A, // _NORON + 0x29, 0 | DELAY, 0x64, // _DISPON + // 0x36, 0x01, 0xC0, // _MADCTL Default rotation plus BGR encoding + 0x36, 0x01, 0xC8, // _MADCTL Default rotation plus RGB encoding + 0x21, 0x00, // _INVON +}; + +static void display_init(void) { + fourwire_fourwire_obj_t *bus = &allocate_display_bus()->fourwire_bus; + busio_spi_obj_t *spi = &bus->inline_bus; + common_hal_busio_spi_construct( + spi, + &pin_GPIO10, // CLK + &pin_GPIO11, // MOSI + NULL, // MISO not connected + false // Not half-duplex + ); + + common_hal_busio_spi_never_reset(spi); + + bus->base.type = &fourwire_fourwire_type; + + common_hal_fourwire_fourwire_construct( + bus, + spi, + MP_OBJ_FROM_PTR(&pin_GPIO8), // DC + MP_OBJ_FROM_PTR(&pin_GPIO9), // CS + MP_OBJ_FROM_PTR(&pin_GPIO12), // RST + 40000000, // baudrate + 0, // polarity + 0 // phase + ); + + busdisplay_busdisplay_obj_t *display = &allocate_display()->display; + display->base.type = &busdisplay_busdisplay_type; + common_hal_busdisplay_busdisplay_construct( + display, + bus, + 160, // width (after rotation) + 80, // height (after rotation) + 26, // column start + 1, // row start + 90, // rotation + 16, // color depth + false, // grayscale + false, // pixels in a byte share a row. Only valid for depths < 8 + 1, // bytes per cell. Only valid for depths < 8 + false, // reverse_pixels_in_byte. Only valid for depths < 8 + true, // reverse_pixels_in_word + MIPI_COMMAND_SET_COLUMN_ADDRESS, // set column command + MIPI_COMMAND_SET_PAGE_ADDRESS, // set row command + MIPI_COMMAND_WRITE_MEMORY_START, // write memory command + display_init_sequence, + sizeof(display_init_sequence), + &pin_GPIO25, // backlight pin + NO_BRIGHTNESS_COMMAND, + 1.0f, // brightness + false, // single_byte_bounds + false, // data_as_commands + true, // auto_refresh + 60, // native_frames_per_second + true, // backlight_on_high + false, // SH1107_addressing + 50000 // backlight pwm frequency + ); +} + +void board_init(void) { + // Display + display_init(); +} +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.h new file mode 100644 index 0000000000000..53f913d7c091f --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-LCD-0.96" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO21, .sda = &pin_GPIO20}} + +#define CIRCUITPY_BOARD_SPI (1) +#define CIRCUITPY_BOARD_SPI_PIN {{.clock = &pin_GPIO18, .mosi = &pin_GPIO19, .miso = &pin_GPIO16}} + +#define CIRCUITPY_BOARD_UART (1) +#define CIRCUITPY_BOARD_UART_PIN {{.tx = &pin_GPIO0, .rx = &pin_GPIO1}} diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.mk new file mode 100644 index 0000000000000..62861864bbb03 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B7 +USB_PRODUCT = "Waveshare RP2350-LCD-0.96" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "P25Q32SH" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pins.c new file mode 100644 index 0000000000000..bd3a831034501 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_0_96/pins.c @@ -0,0 +1,63 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + + // ADC + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + + // 0.96 inch LCD ST7735s + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_LCD_DIN), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) }, + + // Power pins + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/board.c b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.h new file mode 100644 index 0000000000000..0fc7bb372b159 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-LCD-1.28" +#define MICROPY_HW_MCU_NAME "rp2350" diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk new file mode 100644 index 0000000000000..8f703c5a93254 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B3 +USB_PRODUCT = "Waveshare RP2350-LCD-1.28" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "P25Q32SH" + +CIRCUITPY__EVE = 1 + +# TODO: Add custom QMI8658 driver +# FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_qmi8658 + +# TODO: Add custom GC9A01 driver +# FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_gc9a01 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pins.c new file mode 100644 index 0000000000000..78e40ad32653f --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_lcd_1_28/pins.c @@ -0,0 +1,76 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_DIN), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + + + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_INT1), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_INT2), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO29) }, // Battery voltage readout, 0.50 bias +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/board.c b/ports/raspberrypi/boards/waveshare_rp2350_one/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.h new file mode 100644 index 0000000000000..d8efe2396e036 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-One" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) + +#define DEFAULT_I2C_BUS_SDA (&pin_GPIO4) +#define DEFAULT_I2C_BUS_SCL (&pin_GPIO5) + +#define DEFAULT_SPI_BUS_CK (&pin_GPIO6) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO7) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO8) + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk new file mode 100644 index 0000000000000..75398b3269b42 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B5 +USB_PRODUCT = "RP2350-One" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_one/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_one/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_one/pins.c new file mode 100644 index 0000000000000..5b172616aba2e --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_one/pins.c @@ -0,0 +1,62 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_plus/board.c b/ports/raspberrypi/boards/waveshare_rp2350_plus/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_plus/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.h new file mode 100644 index 0000000000000..a8df27661d354 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-Plus" +#define MICROPY_HW_MCU_NAME "rp2350" diff --git a/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.mk new file mode 100644 index 0000000000000..d70259ab2717a --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_plus/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B1 +USB_PRODUCT = "RP2350-Plus" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_plus/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_plus/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_plus/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_plus/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_plus/pins.c new file mode 100644 index 0000000000000..1263586686ba0 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_plus/pins.c @@ -0,0 +1,60 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/board.c b/ports/raspberrypi/boards/waveshare_rp2350_tiny/board.c new file mode 100644 index 0000000000000..a019bac42556b --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.h new file mode 100644 index 0000000000000..f4a9e0231de25 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-Tiny" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk new file mode 100644 index 0000000000000..464c7aff28386 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B2 +USB_PRODUCT = "RP2350-Tiny" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "P25Q32SH" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_tiny/pico-sdk-configboard.h new file mode 100644 index 0000000000000..307388439fa71 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_tiny/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_tiny/pins.c new file mode 100644 index 0000000000000..9b6f5331336c9 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_tiny/pins.c @@ -0,0 +1,53 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Bill Sideris +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/board.c b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.h new file mode 100644 index 0000000000000..4bf2cdfac6ec6 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-TOUCH-LCD-1.28" +#define MICROPY_HW_MCU_NAME "rp2350" diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk new file mode 100644 index 0000000000000..11e927c748517 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B4 +USB_PRODUCT = "Waveshare RP2350-TOUCH-LCD-1.28" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 + +# TODO: Add custom QMI8658 driver +# FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_qmi8658 + +# TODO: Add custom GC9A01 driver +# FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython_gc9a01 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pins.c new file mode 100644 index 0000000000000..c14fdb6e23b48 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_touch_lcd_1_28/pins.c @@ -0,0 +1,76 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_DIN), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_INT1), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_IMU_INT2), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO29) }, // Battery voltage readout, 0.50 bias +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/board.c b/ports/raspberrypi/boards/waveshare_rp2350_zero/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.h b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.h new file mode 100644 index 0000000000000..c1517f08c1054 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "Waveshare RP2350-Zero" +#define MICROPY_HW_MCU_NAME "rp2350" + +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO16) diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk new file mode 100644 index 0000000000000..444850776a606 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x2E8A +USB_PID = 0x10B0 +USB_PRODUCT = "RP2350-Zero" +USB_MANUFACTURER = "Waveshare Electronics" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "P25Q32SH" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/pico-sdk-configboard.h b/ports/raspberrypi/boards/waveshare_rp2350_zero/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/waveshare_rp2350_zero/pins.c b/ports/raspberrypi/boards/waveshare_rp2350_zero/pins.c new file mode 100644 index 0000000000000..5b172616aba2e --- /dev/null +++ b/ports/raspberrypi/boards/waveshare_rp2350_zero/pins.c @@ -0,0 +1,62 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO0) }, + + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO1) }, + + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c b/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h new file mode 100644 index 0000000000000..95a81334c73d5 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#define MICROPY_HW_BOARD_NAME "WeAct Studio RP2350B Core" +#define MICROPY_HW_MCU_NAME "rp2350b" + +#define CIRCUITPY_PSRAM_CHIP_SELECT (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk new file mode 100644 index 0000000000000..d86f28280f3a0 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/mpconfigboard.mk @@ -0,0 +1,12 @@ +USB_VID = 0x1209 +USB_PID = 0xDEC1 +USB_PRODUCT = "RP2350B Core" +USB_MANUFACTURER = "WeAct Studio" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = B +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h new file mode 100644 index 0000000000000..66b57dfd13dc2 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pico-sdk-configboard.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c new file mode 100644 index 0000000000000..d6a82becfdd47 --- /dev/null +++ b/ports/raspberrypi/boards/weact_studio_rp2350b_core/pins.c @@ -0,0 +1,91 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP30), MP_ROM_PTR(&pin_GPIO30) }, + { MP_ROM_QSTR(MP_QSTR_GP31), MP_ROM_PTR(&pin_GPIO31) }, + { MP_ROM_QSTR(MP_QSTR_GP32), MP_ROM_PTR(&pin_GPIO32) }, + { MP_ROM_QSTR(MP_QSTR_GP33), MP_ROM_PTR(&pin_GPIO33) }, + { MP_ROM_QSTR(MP_QSTR_GP34), MP_ROM_PTR(&pin_GPIO34) }, + { MP_ROM_QSTR(MP_QSTR_GP35), MP_ROM_PTR(&pin_GPIO35) }, + { MP_ROM_QSTR(MP_QSTR_GP36), MP_ROM_PTR(&pin_GPIO36) }, + { MP_ROM_QSTR(MP_QSTR_GP37), MP_ROM_PTR(&pin_GPIO37) }, + { MP_ROM_QSTR(MP_QSTR_GP38), MP_ROM_PTR(&pin_GPIO38) }, + { MP_ROM_QSTR(MP_QSTR_GP39), MP_ROM_PTR(&pin_GPIO39) }, + + { MP_ROM_QSTR(MP_QSTR_GP40), MP_ROM_PTR(&pin_GPIO40) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO40) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP40_A0), MP_ROM_PTR(&pin_GPIO40) }, + + { MP_ROM_QSTR(MP_QSTR_GP41), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO41) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP41_A1), MP_ROM_PTR(&pin_GPIO41) }, + + { MP_ROM_QSTR(MP_QSTR_GP42), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO42) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP42_A2), MP_ROM_PTR(&pin_GPIO42) }, + + { MP_ROM_QSTR(MP_QSTR_GP43), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO43) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP43_A3), MP_ROM_PTR(&pin_GPIO43) }, + + { MP_ROM_QSTR(MP_QSTR_GP44), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO44) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP44_A4), MP_ROM_PTR(&pin_GPIO44) }, + + { MP_ROM_QSTR(MP_QSTR_GP45), MP_ROM_PTR(&pin_GPIO45) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO45) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP45_A5), MP_ROM_PTR(&pin_GPIO45) }, + + { MP_ROM_QSTR(MP_QSTR_GP46), MP_ROM_PTR(&pin_GPIO46) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_GPIO46) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP46_A6), MP_ROM_PTR(&pin_GPIO46) }, + + { MP_ROM_QSTR(MP_QSTR_GP47), MP_ROM_PTR(&pin_GPIO47) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_GPIO47) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GP47_A7), MP_ROM_PTR(&pin_GPIO47) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/_aic3105.py b/ports/raspberrypi/boards/weenoisemakers_noisenugget/_aic3105.py new file mode 100644 index 0000000000000..06923e374b71b --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/_aic3105.py @@ -0,0 +1,564 @@ +from adafruit_bus_device import i2c_device + +import time + +# Page select register +AIC3X_PAGE_SELECT = 0 +# Software reset register +AIC3X_RESET = 1 +# Codec Sample rate select register +AIC3X_SAMPLE_RATE_SEL_REG = 2 +# PLL progrramming register A +AIC3X_PLL_PROGA_REG = 3 +# PLL progrramming register B +AIC3X_PLL_PROGB_REG = 4 +# PLL progrramming register C +AIC3X_PLL_PROGC_REG = 5 +# PLL progrramming register D +AIC3X_PLL_PROGD_REG = 6 +# Codec datapath setup register +AIC3X_CODEC_DATAPATH_REG = 7 +# Audio serial data interface control register A +AIC3X_ASD_INTF_CTRLA = 8 +# Audio serial data interface control register B +AIC3X_ASD_INTF_CTRLB = 9 +# Audio serial data interface control register C +AIC3X_ASD_INTF_CTRLC = 10 +# Audio overflow status and PLL R value programming register +AIC3X_OVRF_STATUS_AND_PLLR_REG = 11 +# Audio codec digital filter control register +AIC3X_CODEC_DFILT_CTRL = 12 +# Headset/button press detection register +AIC3X_HEADSET_DETECT_CTRL_A = 13 +AIC3X_HEADSET_DETECT_CTRL_B = 14 +# ADC PGA Gain control registers +LADC_VOL = 15 +RADC_VOL = 16 +# MIC3 control registers +MIC3LR_2_LADC_CTRL = 17 +MIC3LR_2_RADC_CTRL = 18 +# Line1 Input control registers +LINE1L_2_LADC_CTRL = 19 +LINE1R_2_LADC_CTRL = 21 +LINE1R_2_RADC_CTRL = 22 +LINE1L_2_RADC_CTRL = 24 +# Line2 Input control registers +LINE2L_2_LADC_CTRL = 20 +LINE2R_2_RADC_CTRL = 23 +# MICBIAS Control Register +MICBIAS_CTRL = 25 + +# AGC Control Registers A, B, C +LAGC_CTRL_A = 26 +LAGC_CTRL_B = 27 +LAGC_CTRL_C = 28 +RAGC_CTRL_A = 29 +RAGC_CTRL_B = 30 +RAGC_CTRL_C = 31 + +# DAC Power and Left High Power Output control registers +DAC_PWR = 37 +HPLCOM_CFG = 37 +# Right High Power Output control registers +HPRCOM_CFG = 38 +# High Power Output Stage Control Register +HPOUT_SC = 40 +# DAC Output Switching control registers +DAC_LINE_MUX = 41 +# High Power Output Driver Pop Reduction registers +HPOUT_POP_REDUCTION = 42 +# DAC Digital control registers +LDAC_VOL = 43 +RDAC_VOL = 44 +# Left High Power Output control registers +LINE2L_2_HPLOUT_VOL = 45 +PGAL_2_HPLOUT_VOL = 46 +DACL1_2_HPLOUT_VOL = 47 +LINE2R_2_HPLOUT_VOL = 48 +PGAR_2_HPLOUT_VOL = 49 +DACR1_2_HPLOUT_VOL = 50 +HPLOUT_CTRL = 51 +# Left High Power COM control registers +LINE2L_2_HPLCOM_VOL = 52 +PGAL_2_HPLCOM_VOL = 53 +DACL1_2_HPLCOM_VOL = 54 +LINE2R_2_HPLCOM_VOL = 55 +PGAR_2_HPLCOM_VOL = 56 +DACR1_2_HPLCOM_VOL = 57 +HPLCOM_CTRL = 58 +# Right High Power Output control registers +LINE2L_2_HPROUT_VOL = 59 +PGAL_2_HPROUT_VOL = 60 +DACL1_2_HPROUT_VOL = 61 +LINE2R_2_HPROUT_VOL = 62 +PGAR_2_HPROUT_VOL = 63 +DACR1_2_HPROUT_VOL = 64 +HPROUT_CTRL = 65 +# Right High Power COM control registers +LINE2L_2_HPRCOM_VOL = 66 +PGAL_2_HPRCOM_VOL = 67 +DACL1_2_HPRCOM_VOL = 68 +LINE2R_2_HPRCOM_VOL = 69 +PGAR_2_HPRCOM_VOL = 70 +DACR1_2_HPRCOM_VOL = 71 +HPRCOM_CTRL = 72 +# Mono Line Output Plus/Minus control registers +LINE2L_2_MONOLOPM_VOL = 73 +PGAL_2_MONOLOPM_VOL = 74 +DACL1_2_MONOLOPM_VOL = 75 +LINE2R_2_MONOLOPM_VOL = 76 +PGAR_2_MONOLOPM_VOL = 77 +DACR1_2_MONOLOPM_VOL = 78 +MONOLOPM_CTRL = 79 +# Left Line Output Plus/Minus control registers +LINE2L_2_LLOPM_VOL = 80 +PGAL_2_LLOPM_VOL = 81 +DACL1_2_LLOPM_VOL = 82 +LINE2R_2_LLOPM_VOL = 83 +PGAR_2_LLOPM_VOL = 84 +DACR1_2_LLOPM_VOL = 85 +LLOPM_CTRL = 86 +# Right Line Output Plus/Minus control registers +LINE2L_2_RLOPM_VOL = 87 +PGAL_2_RLOPM_VOL = 88 +DACL1_2_RLOPM_VOL = 89 +LINE2R_2_RLOPM_VOL = 90 +PGAR_2_RLOPM_VOL = 91 +DACR1_2_RLOPM_VOL = 92 +RLOPM_CTRL = 93 + +MODULE_POWER_STATUS = 94 + +# GPIO/IRQ registers +AIC3X_STICKY_IRQ_FLAGS_REG = 96 +AIC3X_RT_IRQ_FLAGS_REG = 97 + +AIC3X_CLOCK_REG = 101 +# Clock generation control register +AIC3X_CLKGEN_CTRL_REG = 102 +# New AGC registers +LAGCN_ATTACK = 103 +LAGCN_DECAY = 104 +RAGCN_ATTACK = 105 +RAGCN_DECAY = 106 +# New Programmable ADC Digital Path and I2C Bus Condition Register +NEW_ADC_DIGITALPATH = 107 +# Passive Analog Signal Bypass Selection During Powerdown Register +PASSIVE_BYPASS = 108 +# DAC Quiescent Current Adjustment Register +DAC_ICC_ADJ = 109 + + +# My kingdom for enums, and strong typing... +LINE2_L = 0 +PGA_L = 1 +DAC_L1 = 2 +LINE2_R = 3 +PGA_R = 4 +DAC_R1 = 5 + +# Don't use the same values for the sink and source "enums", this way a runtime +# error will tell us when we mix the two. +HP_L_OUT = 10 +HP_L_COM = 11 +HP_R_OUT = 12 +HP_R_COM = 13 +LINE_OUT_L = 14 +LINE_OUT_R = 15 + + +class AIC3105: + def __init__(self, i2c_bus, sample_rate, address=0x18): + self.i2c_device = i2c_device.I2CDevice(i2c_bus, address) + self._buf = bytearray(2) + self._sample_rate = sample_rate + + self._registers_copy = [ + 0b00000000, # 0 + 0b00000000, # 1 + 0b00000000, # 2 + 0b00010000, # 3 + 0b00000010, # 4 + 0b00000000, # 5 + 0b00000000, # 6 + 0b00000000, # 7 + 0b00000000, # 8 + 0b00000000, # 9 + 0b00000000, # 10 + 0b00000001, # 11 + 0b00000000, # 12 + 0b00000000, # 13 + 0b00000000, # 14 + 0b10000000, # 15 + 0b10000000, # 16 + 0b11111111, # 17 + 0b11111111, # 18 + 0b01111000, # 19 + 0b01111000, # 20 + 0b01111000, # 21 + 0b01111000, # 22 + 0b01111000, # 23 + 0b01111000, # 24 + 0b00000000, # 25 + 0b00000000, # 26 + 0b11111110, # 27 + 0b00000000, # 28 + 0b00000000, # 29 + 0b11111110, # 30 + 0b00000000, # 31 + 0b00000000, # 32 + 0b00000000, # 33 + 0b00000000, # 34 + 0b00000000, # 35 + 0b00000000, # 36 + 0b00000000, # 37 + 0b00000000, # 38 + 0b00000000, # 39 + 0b00000000, # 40 + 0b00000000, # 41 + 0b00000000, # 42 + 0b10000000, # 43 + 0b10000000, # 44 + 0b00000000, # 45 + 0b00000000, # 46 + 0b00000000, # 47 + 0b00000000, # 48 + 0b00000000, # 49 + 0b00000000, # 50 + 0b00000110, # 51 + 0b00000000, # 52 + 0b00000000, # 53 + 0b00000000, # 54 + 0b00000000, # 55 + 0b00000000, # 56 + 0b00000000, # 57 + 0b00000110, # 58 + 0b00000000, # 59 + 0b00000000, # 60 + 0b00000000, # 61 + 0b00000000, # 62 + 0b00000000, # 63 + 0b00000000, # 64 + 0b00000010, # 65 + 0b00000000, # 66 + 0b00000000, # 67 + 0b00000000, # 68 + 0b00000000, # 69 + 0b00000000, # 70 + 0b00000000, # 71 + 0b00000010, # 72 + 0b00000000, # 73 + 0b00000000, # 74 + 0b00000000, # 75 + 0b00000000, # 76 + 0b00000000, # 77 + 0b00000000, # 78 + 0b00000000, # 79 + 0b00000000, # 80 + 0b00000000, # 81 + 0b00000000, # 82 + 0b00000000, # 83 + 0b00000000, # 84 + 0b00000000, # 85 + 0b00000010, # 86 + 0b00000000, # 87 + 0b00000000, # 88 + 0b00000000, # 89 + 0b00000000, # 90 + 0b00000000, # 91 + 0b00000000, # 92 + 0b00000010, # 93 + 0b00000000, # 94 + 0b00000000, # 95 + 0b00000000, # 96 + 0b00000000, # 97 + 0b00000000, # 98 + 0b00000000, # 99 + 0b00000000, # 100 + 0b00000000, # 101 + 0b00000010, # 102 + 0b00000000, # 103 + 0b00000000, # 104 + 0b00000000, # 105 + 0b00000000, # 106 + 0b00000000, # 107 + 0b00000000, # 108 + 0b00000000, + ] # 109 + + def _write_register(self, reg, value): + self._buf[0] = reg & 0xFF + self._buf[1] = value & 0xFF + # print("_write_register reg:0x{:02x} value:0x{:02x}".format(reg, value)) + with self.i2c_device as i2c: + i2c.write(self._buf) + self._registers_copy[reg] = value + + def _write_bit(self, reg, pos, value): + current = self._registers_copy[reg] + mask = 1 << pos + + if value == 0: + new = current & (~mask) + else: + new = current | mask + self._write_register(reg, new) + + def _write_multi(self, reg, msb, lsb, value): + new = self._registers_copy[reg] + + # Clear bits for the range we case about + for x in range(lsb, msb + 1): + new = new & (~(1 << x)) + + new = new | (value << lsb) + + self._write_register(reg, new) + + def sink_base_register(self, sink): + if sink == HP_L_OUT: + return 45 + if sink == HP_L_COM: + return 52 + if sink == HP_R_OUT: + return 59 + if sink == HP_R_COM: + return 66 + if sink == LINE_OUT_L: + return 80 + if sink == LINE_OUT_R: + return 87 + + raise RuntimeError("invalid sink") + + def source_register_offset(self, source): + if source == LINE2_L: + return 0 + if source == PGA_L: + return 1 + if source == DAC_L1: + return 2 + if source == LINE2_R: + return 3 + if source == PGA_R: + return 4 + if source == DAC_R1: + return 5 + raise RuntimeError("invalid source") + + def power_on(self, sink): + reg = self.sink_base_register(sink) + 6 + self._write_bit(reg, 0, 1) + + def power_off(self, sink): + reg = self.sink_base_register(sink) + 6 + self._write_bit(reg, 0, 0) + + def mute(self, sink): + reg = self.sink_base_register(sink) + 6 + self._write_bit(reg, 3, 0) + + def unmute(self, sink): + reg = self.sink_base_register(sink) + 6 + self._write_bit(reg, 3, 1) + + def route(self, source, sink): + reg = self.sink_base_register(sink) + self.source_register_offset(source) + self._write_bit(reg, 7, 1) + + def unroute(self, source, sink): + reg = self.sink_base_register(sink) + self.source_register_offset(source) + self._write_bit(reg, 7, 0) + + def volume_convert(self, volume, min, max, mute_value): + if volume == 0.0 or volume < 0.0: + return mute_value + elif volume > 1.0: + volume = 1.0 + + if max > min: + amplitude = max - min + val = volume * amplitude + return int(min + val) + else: + amplitude = min - max + val = (1.0 - volume) * amplitude + return int(max + val) + + def PGA_volume(self, volume): + return self.volume_convert(volume, 0, 0b1111111, 0) + + def output_stage_volume(self, volume): + return self.volume_convert(volume, 117, 0, 118) + + def set_volume(self, source, sink, volume): + vol = self.output_stage_volume(volume) + reg = self.sink_base_register(sink) + self.source_register_offset(source) + self._write_multi(reg, 6, 0, vol) + + def set_HP_volume(self, left, right): + self.set_volume(DAC_L1, HP_L_OUT, left) + self.set_volume(DAC_R1, HP_R_OUT, right) + + def enable_line_out(self, left, right): + if left: + self.power_on(LINE_OUT_L) + self.route(DAC_L1, LINE_OUT_L) + self.route(DAC_L1, LINE_OUT_R) + self.unmute(LINE_OUT_L) + else: + self.power_off(LINE_OUT_L) + self.unroute(DAC_L1, LINE_OUT_L) + self.unroute(DAC_L1, LINE_OUT_R) + self.mute(LINE_OUT_L) + + if right: + self.power_on(LINE_OUT_R) + self.route(DAC_R1, LINE_OUT_L) + self.route(DAC_R1, LINE_OUT_R) + self.unmute(LINE_OUT_R) + else: + self.power_off(LINE_OUT_R) + self.unroute(DAC_R1, LINE_OUT_L) + self.unroute(DAC_R1, LINE_OUT_R) + self.mute(LINE_OUT_R) + + def set_line_out_volume( + self, left_to_left, right_to_right, left_to_right=0.0, right_to_left=0.0 + ): + self.set_volume(DAC_L1, LINE_OUT_L, left_to_left) + self.set_volume(DAC_L1, LINE_OUT_R, left_to_right) + self.set_volume(DAC_R1, LINE_OUT_R, right_to_right) + self.set_volume(DAC_R1, LINE_OUT_L, right_to_left) + + def enable_mic_bias(self): + self._write_multi(MICBIAS_CTRL, 7, 6, 0b10) + + def start_i2s_out(self): + if self._sample_rate == 8000: + cfg = [5, 4613, 1, 8] + elif self._sample_rate == 16000: + cfg = [5, 4613, 1, 4] + elif self._sample_rate == 22050: + cfg = [7, 5264, 1, 4] + elif self._sample_rate == 32000: + cfg = [5, 4613, 1, 2] + elif self._sample_rate == 44100: + cfg = [7, 5264, 1, 2] + elif self._sample_rate == 48000: + cfg = [8, 1920, 1, 2] + else: + raise RuntimeError("invalid sample rate: " + str(self._sample_rate)) + + J = cfg[0] + D = cfg[1] + R = cfg[2] + P = cfg[3] + + # Select Page 0 + self._write_bit(AIC3X_PAGE_SELECT, 0, 0) + + # Soft reset + self._write_bit(AIC3X_RESET, 7, 1) + + # Let's start with clock configuration. + + # PLL P = 2 + self._write_multi(AIC3X_PLL_PROGA_REG, 2, 0, P) + + # PLL R = 1 + self._write_multi(AIC3X_OVRF_STATUS_AND_PLLR_REG, 3, 0, R) + + # PLL J = 7 + self._write_multi(AIC3X_PLL_PROGB_REG, 7, 2, J) + + # PLL D = 5264 + PLL_D = D + REG_C = PLL_D >> 6 + REG_D = PLL_D & 0x3F + self._write_multi(AIC3X_PLL_PROGC_REG, 7, 0, REG_C) + self._write_multi(AIC3X_PLL_PROGD_REG, 7, 2, REG_D) + + # Select the PLLCLK_IN source. 0: MCLK, 1: GPIO2, 2: BCLK + self._write_multi(AIC3X_CLKGEN_CTRL_REG, 5, 4, 2) + + # Select the CLKDIV_IN source. 0: MCLK, 1: GPIO2, 2: BCLK + # + # Note: When PLL is used CLKDIV_IN still needs some kind of clock + # signal. So if there's no MCLK, BCLK should be used here as well + self._write_multi(AIC3X_CLKGEN_CTRL_REG, 6, 7, 0) + + # Enable PLL + self._write_bit(AIC3X_PLL_PROGA_REG, 7, 1) + + # Set FS(ref) value for AGC time constants to 44.1KHz + self._write_bit(AIC3X_CODEC_DATAPATH_REG, 7, 1) + + # CODEC_CLKIN Source Selection. 0: PLLDIV_OUT. 1: CLKDIV_OUT + self._write_bit(AIC3X_CLOCK_REG, 0, 0) + + # Note: We leave the ADC Sample Rate Select and DAC Sample Rate Select + # at the default value: fs(ref) / 1 + + # Audio Serial Data Interface at the default settings: I2S + # mode, 16bits words, + self._write_multi(AIC3X_ASD_INTF_CTRLB, 7, 6, 0b00) + + # Output Driver Power-On Delay Control + self._write_multi(HPOUT_POP_REDUCTION, 7, 4, 0b1000) + + # Driver Ramp-Up Step Timing Control + self._write_multi(HPOUT_POP_REDUCTION, 3, 2, 0b01) + + # Power outputs + self.power_on(HP_L_OUT) + self.power_on(HP_R_OUT) + + # L and R DACs Power On + self._write_multi(DAC_PWR, 7, 6, 0b11) + + # Left DAC plays left input data + self._write_multi(AIC3X_CODEC_DATAPATH_REG, 4, 3, 0b01) + # Right DAC plays right input data + self._write_multi(AIC3X_CODEC_DATAPATH_REG, 2, 1, 0b01) + + # Unmute L DAC + self._write_bit(LDAC_VOL, 7, 0) + # Unmute R DAC + self._write_bit(RDAC_VOL, 7, 0) + + # Left-DAC output selects DAC_L1 path. + self._write_multi(DAC_LINE_MUX, 7, 6, 0) + # Right-DAC output selects DAC_R1 path. + self._write_multi(DAC_LINE_MUX, 5, 4, 0) + + # DAC to HP + self.route(DAC_L1, HP_L_OUT) + self.route(DAC_R1, HP_R_OUT) + + # DAC to Line-Out + self.route(DAC_L1, LINE_OUT_L) + self.route(DAC_R1, LINE_OUT_R) + + # Enable Left ADC + self._write_bit(LINE1L_2_LADC_CTRL, 2, 1) + # Enable Right ADC + self._write_bit(LINE1R_2_RADC_CTRL, 2, 1) + + # Unmute L ADC PGA + self._write_bit(LADC_VOL, 7, 0) + # Unmute R ADC PGA + self._write_bit(RADC_VOL, 7, 0) + + # Programs high-power outputs for ac-coupled driver configuration + self._write_bit(AIC3X_HEADSET_DETECT_CTRL_B, 7, 1) + + # HPLCOM configured as independent single-ended output + self._write_multi(HPLCOM_CFG, 5, 4, 2) + + # HPRCOM configured as independent single-ended output + self._write_multi(HPRCOM_CFG, 5, 3, 1) + + # Unmute outputs + self.unmute(HP_L_OUT) + self.unmute(HP_R_OUT) diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/_tca6408.py b/ports/raspberrypi/boards/weenoisemakers_noisenugget/_tca6408.py new file mode 100644 index 0000000000000..6b3d90b5de5de --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/_tca6408.py @@ -0,0 +1,65 @@ +from adafruit_bus_device import i2c_device + +IO_EXP_SPK_Enable_L_Mask = 0b00000001 +IO_EXP_SPK_Enable_R_Mask = 0b00000010 +IO_EXP_SPK_Gain_0_Mask = 0b00000100 +IO_EXP_SPK_Gain_1_Mask = 0b00001000 +IO_EXP_DAC_Not_Reset_Mask = 0b00010000 +IO_EXP_Jack_Detect_Mask = 0b00100000 + +IO_EXP_INPUT_REG = 0 +IO_EXP_OUTPUT_REG = 1 +IO_EXP_CONFIG_REG = 3 + +IO_EXP_CONFIG_REG_INIT = IO_EXP_Jack_Detect_Mask +IO_EXP_OUTPUT_REG_INIT = 0b00000000 + + +class TCA6408: + def __init__(self, i2c_bus, address=0x20): + self._i2c_device = i2c_device.I2CDevice(i2c_bus, address) + self._buf = bytearray(2) + self._reg_state = IO_EXP_OUTPUT_REG_INIT + + self._write_register(IO_EXP_OUTPUT_REG, self._reg_state) + self._write_register(IO_EXP_CONFIG_REG, IO_EXP_CONFIG_REG_INIT) + + def _write_register(self, reg, value): + self._buf[0] = reg & 0xFF + self._buf[1] = value & 0xFF + with self._i2c_device as i2c: + i2c.write(self._buf) + + def _set_out(self, new_state): + self._write_register(IO_EXP_OUTPUT_REG, new_state) + self._reg_state = new_state + + def enable_codec(self): + self._set_out(self._reg_state | IO_EXP_DAC_Not_Reset_Mask) + + def enable_speakers(self, left, right): + new_state = self._reg_state + if left: + new_state = new_state | IO_EXP_SPK_Enable_L_Mask + else: + new_state = new_state & ~IO_EXP_SPK_Enable_L_Mask + + if right: + new_state = new_state | IO_EXP_SPK_Enable_R_Mask + else: + new_state = new_state & ~IO_EXP_SPK_Enable_R_Mask + + self._set_out(new_state) + + def set_speakers_gain(self, g0, g1): + new_state = self._reg_state + + if g0: + new_state = new_state | IO_EXP_SPK_Gain_0_Mask + else: + new_state = new_state & ~IO_EXP_SPK_Gain_0_Mask + + if g1: + new_state = new_state | IO_EXP_SPK_Gain_1_Mask + else: + new_state = new_state & ~IO_EXP_SPK_Gain_1_Mask diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/board.c b/ports/raspberrypi/boards/weenoisemakers_noisenugget/board.c new file mode 100644 index 0000000000000..331653173ecd1 --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/board.c @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Scott Shawcroft for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.h b/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.h new file mode 100644 index 0000000000000..ddebab5b8a313 --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.h @@ -0,0 +1,2 @@ +#define MICROPY_HW_BOARD_NAME "Noise Nugget 2040" +#define MICROPY_HW_MCU_NAME "rp2040" diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.mk b/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.mk new file mode 100644 index 0000000000000..a90f1a3db45fb --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x2E8A +USB_PID = 0x1090 +USB_PRODUCT = "Noise Nugget 2040" +USB_MANUFACTURER = "Wee Noise Makers" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q128JVxQ" + +CIRCUITPY__EVE = 1 + +FROZEN_MPY_DIRS += $(TOP)/ports/raspberrypi/boards/weenoisemakers_noisenugget +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_ImageLoad +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_DisplayIO_SSD1306 +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Display_Text +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_MIDI diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/noise_nugget.py b/ports/raspberrypi/boards/weenoisemakers_noisenugget/noise_nugget.py new file mode 100644 index 0000000000000..02dab040e5f1c --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/noise_nugget.py @@ -0,0 +1,115 @@ +from board import * +import audiobusio +import busio +import time +import _aic3105 +import _tca6408 + +_AUDIO = None +_DAC = None +_I2C = None +_IO_EXP = None +_SAMPLE_RATE = 22050 + + +def io_exp(): + global _IO_EXP + + if not _IO_EXP: + _IO_EXP = _tca6408.TCA6408(i2c()) + + return _IO_EXP + + +def i2c(): + global _I2C + + if not _I2C: + SCL = GP7 + SDA = GP6 + _I2C = busio.I2C(SCL, SDA) + + return _I2C + + +def _init_dac(sample_rate): + global _DAC + global _SAMPLE_RATE + + if not _DAC: + _SAMPLE_RATE = sample_rate + + _DAC = _aic3105.AIC3105(i2c(), sample_rate) + _DAC.start_i2s_out() + + return _DAC + + +def audio(sample_rate=22050): + global _AUDIO + global _DAC + + if not _AUDIO: + i2s_out = GP1 + i2s_lrclk = GP2 + i2s_bclk = GP3 + + io_exp().enable_codec() + + time.sleep(0.1) + + # Must init the dac here + _init_dac(sample_rate) + _DAC.set_HP_volume(0.5, 0.5) + + _AUDIO = audiobusio.I2SOut(i2s_bclk, i2s_lrclk, i2s_out, left_justified=False) + + return _AUDIO + + +def sample_rate(): + return _SAMPLE_RATE + + +def _check_dac_init(): + global _DAC + if not _DAC: + raise RuntimeError("audio not initialized. Call noise_nugget.audio() first.") + + +def set_HP_volume(left, right): + global _DAC + + _check_dac_init() + + _DAC.set_HP_volume(left, right) + + +def enable_speakers(left, right): + global _DAC + + _check_dac_init() + + _DAC.enable_line_out(left, right) + io_exp().enable_speakers(left, right) + + +def set_speakers_volume(left_to_left, right_to_right, left_to_right=0.0, right_to_left=0.0): + global _DAC + + _check_dac_init() + + _DAC.set_line_out_volume(left_to_left, right_to_right, left_to_right, right_to_left) + + +def set_speakers_gain(gain): + if gain == 0: + io_exp().set_speakers_gain(False, False) + elif gain == 1: + io_exp().set_speakers_gain(True, False) + elif gain == 2: + io_exp().set_speakers_gain(False, True) + elif gain == 3: + io_exp().set_speakers_gain(True, True) + else: + raise RuntimeError("invalid speaker gain " + str(gain) + " (must be between 0 and 3)") diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/pgb1.py b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pgb1.py new file mode 100644 index 0000000000000..6e822e75c8c8e --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pgb1.py @@ -0,0 +1,320 @@ +from board import * +import busio +import displayio +import adafruit_displayio_ssd1306 +from fourwire import FourWire +from neopixel import NeoPixel +import pwmio +from digitalio import DigitalInOut, Direction, Pull + +_DISPLAY = None +_LEDS = None +_KEYBOARD_STATE = 0 +_KEYBOARD_PREV_STATE = 0 + +VOLTAGE_MONITOR = A2 +BATTERY = A2 + +K_TRACK = 0x10000000 +K_STEP = 0x08000000 +K_PLAY = 0x02000000 +K_REC = 0x04000000 +K_ALT = 0x00040000 +K_PATT = 0x00001000 +K_SONG = 0x00000040 +K_MENU = 0x00000020 + +K_UP = 0x00020000 +K_DOWN = 0x00800000 +K_RIGHT = 0x00000800 +K_LEFT = 0x20000000 +K_A = 0x01000000 +K_B = 0x00000001 + +K_1 = 0x00400000 +K_2 = 0x00010000 +K_3 = 0x00000400 +K_4 = 0x00000010 +K_5 = 0x00000002 +K_6 = 0x00000080 +K_7 = 0x00002000 +K_8 = 0x00080000 +K_9 = 0x00200000 +K_10 = 0x00008000 +K_11 = 0x00000200 +K_12 = 0x00000008 +K_13 = 0x00000004 +K_14 = 0x00000100 +K_15 = 0x00004000 +K_16 = 0x00100000 + +KEY_LIST = [ + K_TRACK, + K_STEP, + K_PLAY, + K_REC, + K_ALT, + K_PATT, + K_SONG, + K_MENU, + K_UP, + K_DOWN, + K_RIGHT, + K_LEFT, + K_A, + K_B, + K_1, + K_2, + K_3, + K_4, + K_5, + K_6, + K_7, + K_8, + K_9, + K_10, + K_11, + K_12, + K_13, + K_14, + K_15, + K_16, +] + +KEY_NAME = { + K_TRACK: "Track", + K_STEP: "Step", + K_PLAY: "Play", + K_REC: "Rec", + K_ALT: "Alt", + K_PATT: "Pattern", + K_SONG: "Song", + K_MENU: "Menu", + K_UP: "Up", + K_DOWN: "Down", + K_RIGHT: "Right", + K_LEFT: "Left", + K_A: "A", + K_B: "B", + K_1: "1", + K_2: "2", + K_3: "3", + K_4: "4", + K_5: "5", + K_6: "6", + K_7: "7", + K_8: "8", + K_9: "9", + K_10: "10", + K_11: "11", + K_12: "12", + K_13: "13", + K_14: "14", + K_15: "15", + K_16: "16", +} + +LED_MENU = 0 +LED_SONG = 1 +LED_PATT = 2 +LED_ALT = 3 +LED_TRACK = 4 +LED_K_1 = 5 +LED_K_2 = 6 +LED_K_3 = 7 +LED_K_4 = 8 +LED_K_5 = 9 +LED_K_6 = 10 +LED_K_7 = 11 +LED_K_8 = 12 +LED_PLAY = 13 +LED_STEP = 14 +LED_K_9 = 15 +LED_K_10 = 16 +LED_K_11 = 17 +LED_K_12 = 18 +LED_K_13 = 19 +LED_K_14 = 20 +LED_K_15 = 21 +LED_K_16 = 22 +LED_REC = 23 + +_KEY_COL = [ + DigitalInOut(GP21), + DigitalInOut(GP22), + DigitalInOut(GP26), + DigitalInOut(GP23), + DigitalInOut(GP29), +] +_KEY_ROW = [ + DigitalInOut(GP20), + DigitalInOut(GP18), + DigitalInOut(GP19), + DigitalInOut(GP24), + DigitalInOut(GP25), + DigitalInOut(GP27), +] + +for pin in _KEY_COL: + pin.direction = Direction.OUTPUT + pin.value = False + +for pin in _KEY_ROW: + pin.direction = Direction.INPUT + pin.pull = Pull.DOWN + + +def scan_keyboard(): + global _KEYBOARD_STATE + global _KEYBOARD_PREV_STATE + + val = 0 + for col in _KEY_COL: + col.value = True + for row in _KEY_ROW: + val = val << 1 + if row.value: + val = val | 1 + col.value = False + _KEYBOARD_PREV_STATE = _KEYBOARD_STATE + _KEYBOARD_STATE = val + + +def pressed(keys): + global _KEYBOARD_STATE + + return (_KEYBOARD_STATE & keys) != 0 + + +def falling(keys): + global _KEYBOARD_STATE + global _KEYBOARD_PREV_STATE + + all_falling_keys = _KEYBOARD_STATE & ~_KEYBOARD_PREV_STATE + return (all_falling_keys & keys) != 0 + + +def raising(keys): + global _KEYBOARD_STATE + global _KEYBOARD_PREV_STATE + + all_raising_keys = ~_KEYBOARD_STATE & _KEYBOARD_PREV_STATE + return (all_raising_keys & keys) != 0 + + +def display(spi_frequency=1000000): + global _DISPLAY + + if not _DISPLAY: + displayio.release_displays() + + spi = busio.SPI(GP10, GP11) + cs = None + dc = GP12 + reset = GP13 + + display_bus = FourWire( + spi, command=dc, chip_select=cs, reset=reset, baudrate=spi_frequency + ) + _DISPLAY = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=64) + + return _DISPLAY + + +def neopixel(brightness=0.1): + global _LEDS + + if not _LEDS: + _LEDS = NeoPixel(GP14, 24, brightness=brightness) + + return _LEDS + + +def key_to_led(key): + map = { + K_TRACK: LED_TRACK, + K_STEP: LED_STEP, + K_PLAY: LED_PLAY, + K_REC: LED_REC, + K_ALT: LED_ALT, + K_PATT: LED_PATT, + K_SONG: LED_SONG, + K_MENU: LED_MENU, + K_1: LED_K_1, + K_2: LED_K_2, + K_3: LED_K_3, + K_4: LED_K_4, + K_5: LED_K_5, + K_6: LED_K_6, + K_7: LED_K_7, + K_8: LED_K_8, + K_9: LED_K_9, + K_10: LED_K_10, + K_11: LED_K_11, + K_12: LED_K_12, + K_13: LED_K_13, + K_14: LED_K_14, + K_15: LED_K_15, + K_16: LED_K_16, + } + return map[key] + + +def simple_synth(synth, verbose=False): + base_note = 60 + + leds = neopixel() + + keys = [ + (K_9, 0), + (K_2, 1), + (K_10, 2), + (K_3, 3), + (K_11, 4), + (K_12, 5), + (K_5, 6), + (K_13, 7), + (K_6, 8), + (K_14, 9), + (K_7, 10), + (K_15, 11), + (K_16, 12), + ] + + for key, _ in keys: + leds[key_to_led(key)] = (0, 0, 255) + leds[key_to_led(K_1)] = (255, 255, 0) + leds[key_to_led(K_8)] = (255, 255, 0) + leds.show() + + while True: + scan_keyboard() + + # Lower base note 1 octave down + if falling(K_1) and base_note > 12: + # Turn off any potentially on notes + for _, offset in keys: + synth.release(base_note + offset) + base_note -= 12 + if verbose: + print("Octave down") + + # Raise base note 1 octave up + if falling(K_8) and base_note <= 96: + # Turn off any potentially on notes + for _, offset in keys: + synth.release(base_note + offset) + base_note += 12 + if verbose: + print("Octave up") + + for key, offset in keys: + note = base_note + offset + if falling(key): + if verbose: + print("On " + str(note)) + synth.press(note) + if raising(key): + if verbose: + print("Off " + str(note)) + synth.release(note) diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/pico-sdk-configboard.h b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pico-sdk-configboard.h new file mode 100644 index 0000000000000..36da55d457197 --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pico-sdk-configboard.h @@ -0,0 +1 @@ +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/weenoisemakers_noisenugget/pins.c b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pins.c new file mode 100644 index 0000000000000..bbd3105956bf0 --- /dev/null +++ b/ports/raspberrypi/boards/weenoisemakers_noisenugget/pins.c @@ -0,0 +1,54 @@ +#include "shared-bindings/board/__init__.h" + +const mcu_pin_obj_t pin_GPIO_fake; + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_GP29_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_GP29), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.h b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.h index ba60f5f72d233..b3ff46a70d769 100644 --- a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.h +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.h @@ -9,9 +9,14 @@ #define MICROPY_HW_BOARD_NAME "W5100S-EVB-Pico" #define MICROPY_HW_MCU_NAME "rp2040" +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + #define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) #define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) #define DEFAULT_UART_BUS_RX (&pin_GPIO1) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.mk index c7b6f312fc558..3ab04a098335f 100644 --- a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/mpconfigboard.mk @@ -9,3 +9,9 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 +CIRCUITPY_FLOPPYIO = 0 +CIRCUITPY_SSL = 1 +CIRCUITPY_USB_HOST = 0 + +# The default is -O3. Change to -O2 because the build was overflowing. +OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/pins.c b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/pins.c index 1263586686ba0..969affad78510 100644 --- a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/pins.c +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico/pins.c @@ -25,12 +25,25 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MISO), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_CS), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SCK), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MOSI), MP_ROM_PTR(&pin_GPIO19) }, { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO20) }, { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_INT), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, @@ -56,5 +69,9 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/board.c b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.h b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.h new file mode 100644 index 0000000000000..f8d7378c2d989 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "W5100S-EVB-Pico2" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk new file mode 100644 index 0000000000000..3e3542120e362 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x2E8A +USB_PID = 0x109E +USB_PRODUCT = "W5100S-EVB-Pico2" +USB_MANUFACTURER = "WIZnet" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_SSL = 1 + +# The default is -O3. Change to -O2 because the build was overflowing. +OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pico-sdk-configboard.h b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pins.c b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pins.c new file mode 100644 index 0000000000000..dbc4e9ad76d46 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5100s_evb_pico2/pins.c @@ -0,0 +1,77 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_CS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_INT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.h b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.h index 7aeca9bdb2cd1..95cd9be2cce85 100644 --- a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.h +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.h @@ -9,9 +9,14 @@ #define MICROPY_HW_BOARD_NAME "W5500-EVB-Pico" #define MICROPY_HW_MCU_NAME "rp2040" +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + #define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) #define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) #define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) #define DEFAULT_UART_BUS_RX (&pin_GPIO1) #define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.mk index 127cdaba380e6..4a8343963bc98 100644 --- a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/mpconfigboard.mk @@ -9,4 +9,9 @@ CHIP_FAMILY = rp2 EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 +CIRCUITPY_FLOPPYIO = 0 CIRCUITPY_SSL = 1 +CIRCUITPY_USB_HOST = 0 + +# The default is -O3. Change to -O2 because the build was overflowing. +OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/pins.c b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/pins.c index a24ff3f3a6091..969affad78510 100644 --- a/ports/raspberrypi/boards/wiznet_w5500_evb_pico/pins.c +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico/pins.c @@ -26,22 +26,22 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, - { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_W5K_MISO), MP_ROM_PTR(&pin_GPIO16) }, { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, - { MP_ROM_QSTR(MP_QSTR_W5500_CS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_W5K_CS), MP_ROM_PTR(&pin_GPIO17) }, { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, - { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_W5K_SCK), MP_ROM_PTR(&pin_GPIO18) }, { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, - { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_W5K_MOSI), MP_ROM_PTR(&pin_GPIO19) }, { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, - { MP_ROM_QSTR(MP_QSTR_W5500_RST), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO20) }, { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, - { MP_ROM_QSTR(MP_QSTR_W5500_INT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_W5K_INT), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, @@ -55,12 +55,10 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, - { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, - { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, @@ -72,8 +70,8 @@ static const mp_rom_map_elem_t board_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_W5K_SPI), MP_ROM_PTR(&board_spi_obj) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, }; MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/board.c b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/board.c new file mode 100644 index 0000000000000..e6a868ab21226 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/board.c @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.h b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.h new file mode 100644 index 0000000000000..6523d82a38d74 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "W5500-EVB-Pico2" +#define MICROPY_HW_MCU_NAME "rp2350a" + +#define MICROPY_HW_LED_STATUS (&pin_GPIO25) + +#define DEFAULT_SPI_BUS_SCK (&pin_GPIO18) +#define DEFAULT_SPI_BUS_MOSI (&pin_GPIO19) +#define DEFAULT_SPI_BUS_MISO (&pin_GPIO16) + +#define DEFAULT_UART_BUS_RX (&pin_GPIO1) +#define DEFAULT_UART_BUS_TX (&pin_GPIO0) + +#define CIRCUITPY_BOARD_I2C (1) +#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO5, .sda = &pin_GPIO4}} diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk new file mode 100644 index 0000000000000..c10c7aa7eb892 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/mpconfigboard.mk @@ -0,0 +1,16 @@ +USB_VID = 0x2E8A +USB_PID = 0x109F +USB_PRODUCT = "W5500-EVB-Pico2" +USB_MANUFACTURER = "WIZnet" + +CHIP_VARIANT = RP2350 +CHIP_PACKAGE = A +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q32JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_SSL = 1 + +# The default is -O3. Change to -O2 because the build was overflowing. +OPTIMIZATION_FLAGS = -O2 diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pico-sdk-configboard.h b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pins.c b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pins.c new file mode 100644 index 0000000000000..dbc4e9ad76d46 --- /dev/null +++ b/ports/raspberrypi/boards/wiznet_w5500_evb_pico2/pins.c @@ -0,0 +1,77 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_GP0), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_GP1), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_GP2), MP_ROM_PTR(&pin_GPIO2) }, + { MP_ROM_QSTR(MP_QSTR_GP3), MP_ROM_PTR(&pin_GPIO3) }, + { MP_ROM_QSTR(MP_QSTR_GP4), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_GP5), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_GP6), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_GP7), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_GP8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_GP9), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_GP10), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_GP11), MP_ROM_PTR(&pin_GPIO11) }, + { MP_ROM_QSTR(MP_QSTR_GP12), MP_ROM_PTR(&pin_GPIO12) }, + { MP_ROM_QSTR(MP_QSTR_GP13), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_GP14), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_GP15), MP_ROM_PTR(&pin_GPIO15) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MISO), MP_ROM_PTR(&pin_GPIO16) }, + { MP_ROM_QSTR(MP_QSTR_GP16), MP_ROM_PTR(&pin_GPIO16) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_CS), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_GP17), MP_ROM_PTR(&pin_GPIO17) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SCK), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_GP18), MP_ROM_PTR(&pin_GPIO18) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_MOSI), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_GP19), MP_ROM_PTR(&pin_GPIO19) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_RST), MP_ROM_PTR(&pin_GPIO20) }, + { MP_ROM_QSTR(MP_QSTR_GP20), MP_ROM_PTR(&pin_GPIO20) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_INT), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_GP21), MP_ROM_PTR(&pin_GPIO21) }, + + { MP_ROM_QSTR(MP_QSTR_GP22), MP_ROM_PTR(&pin_GPIO22) }, + + { MP_ROM_QSTR(MP_QSTR_SMPS_MODE), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_GP23), MP_ROM_PTR(&pin_GPIO23) }, + + { MP_ROM_QSTR(MP_QSTR_VBUS_SENSE), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_GP24), MP_ROM_PTR(&pin_GPIO24) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_GP25), MP_ROM_PTR(&pin_GPIO25) }, + + { MP_ROM_QSTR(MP_QSTR_GP26_A0), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_GP26), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO26) }, + + { MP_ROM_QSTR(MP_QSTR_GP27_A1), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_GP27), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO27) }, + + { MP_ROM_QSTR(MP_QSTR_GP28_A2), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) }, + + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) }, + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) }, + + { MP_ROM_QSTR(MP_QSTR_W5K_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, + { MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/wk-50/board.c b/ports/raspberrypi/boards/wk-50/board.c new file mode 100644 index 0000000000000..2ea197d2b2e5b --- /dev/null +++ b/ports/raspberrypi/boards/wk-50/board.c @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "hardware/gpio.h" +#include "supervisor/shared/board.h" + +void reset_board(void) { + // turn off any left over LED + board_reset_user_neopixels(&pin_GPIO0, 58); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/raspberrypi/boards/wk-50/mpconfigboard.h b/ports/raspberrypi/boards/wk-50/mpconfigboard.h new file mode 100644 index 0000000000000..24a93618948a8 --- /dev/null +++ b/ports/raspberrypi/boards/wk-50/mpconfigboard.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#define MICROPY_HW_BOARD_NAME "WK-50 Trackball Keyboard" +#define MICROPY_HW_MCU_NAME "rp2040" + +#define MICROPY_HW_NEOPIXEL (&pin_GPIO0) diff --git a/ports/raspberrypi/boards/wk-50/mpconfigboard.mk b/ports/raspberrypi/boards/wk-50/mpconfigboard.mk new file mode 100644 index 0000000000000..aca3a41473f15 --- /dev/null +++ b/ports/raspberrypi/boards/wk-50/mpconfigboard.mk @@ -0,0 +1,14 @@ +USB_VID = 0x1209 +USB_PID = 0x6036 +USB_PRODUCT = "WK-50" +USB_MANUFACTURER = "Weekin" + +CHIP_VARIANT = RP2040 +CHIP_FAMILY = rp2 + +EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" + +CIRCUITPY__EVE = 1 +CIRCUITPY_PICODVI = 1 + +FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel diff --git a/ports/raspberrypi/boards/wk-50/pico-sdk-configboard.h b/ports/raspberrypi/boards/wk-50/pico-sdk-configboard.h new file mode 100644 index 0000000000000..110195b779498 --- /dev/null +++ b/ports/raspberrypi/boards/wk-50/pico-sdk-configboard.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Put board-specific pico-sdk definitions here. This file must exist. diff --git a/ports/raspberrypi/boards/wk-50/pins.c b/ports/raspberrypi/boards/wk-50/pins.c new file mode 100644 index 0000000000000..c1a4935f12531 --- /dev/null +++ b/ports/raspberrypi/boards/wk-50/pins.c @@ -0,0 +1,38 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_GPIO0) }, + { MP_ROM_QSTR(MP_QSTR_COL13), MP_ROM_PTR(&pin_GPIO1) }, + { MP_ROM_QSTR(MP_QSTR_COL12), MP_ROM_PTR(&pin_GPIO4) }, + { MP_ROM_QSTR(MP_QSTR_COL11), MP_ROM_PTR(&pin_GPIO5) }, + { MP_ROM_QSTR(MP_QSTR_COL10), MP_ROM_PTR(&pin_GPIO6) }, + { MP_ROM_QSTR(MP_QSTR_COL9), MP_ROM_PTR(&pin_GPIO7) }, + { MP_ROM_QSTR(MP_QSTR_COL8), MP_ROM_PTR(&pin_GPIO8) }, + { MP_ROM_QSTR(MP_QSTR_COL7), MP_ROM_PTR(&pin_GPIO9) }, + { MP_ROM_QSTR(MP_QSTR_COL6), MP_ROM_PTR(&pin_GPIO10) }, + { MP_ROM_QSTR(MP_QSTR_ROW1), MP_ROM_PTR(&pin_GPIO13) }, + { MP_ROM_QSTR(MP_QSTR_ROW0), MP_ROM_PTR(&pin_GPIO14) }, + { MP_ROM_QSTR(MP_QSTR_ENC1), MP_ROM_PTR(&pin_GPIO15) }, + { MP_ROM_QSTR(MP_QSTR_ENC0), MP_ROM_PTR(&pin_GPIO17) }, + { MP_ROM_QSTR(MP_QSTR_ROW2), MP_ROM_PTR(&pin_GPIO18) }, + { MP_ROM_QSTR(MP_QSTR_ROW3), MP_ROM_PTR(&pin_GPIO19) }, + { MP_ROM_QSTR(MP_QSTR_XY_NCS), MP_ROM_PTR(&pin_GPIO21) }, + { MP_ROM_QSTR(MP_QSTR_XY_SCLK), MP_ROM_PTR(&pin_GPIO22) }, + { MP_ROM_QSTR(MP_QSTR_XY_SDIO), MP_ROM_PTR(&pin_GPIO23) }, + { MP_ROM_QSTR(MP_QSTR_COL5), MP_ROM_PTR(&pin_GPIO24) }, + { MP_ROM_QSTR(MP_QSTR_COL4), MP_ROM_PTR(&pin_GPIO25) }, + { MP_ROM_QSTR(MP_QSTR_COL3), MP_ROM_PTR(&pin_GPIO26) }, + { MP_ROM_QSTR(MP_QSTR_COL2), MP_ROM_PTR(&pin_GPIO27) }, + { MP_ROM_QSTR(MP_QSTR_COL1), MP_ROM_PTR(&pin_GPIO28) }, + { MP_ROM_QSTR(MP_QSTR_COL0), MP_ROM_PTR(&pin_GPIO29) }, + +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/raspberrypi/boards/zrichard_rp2.65-f/board.c b/ports/raspberrypi/boards/zrichard_rp2.65-f/board.c index 415a7b3b3e8ff..f8e9958433b08 100644 --- a/ports/raspberrypi/boards/zrichard_rp2.65-f/board.c +++ b/ports/raspberrypi/boards/zrichard_rp2.65-f/board.c @@ -6,7 +6,7 @@ #include "supervisor/board.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include "supervisor/shared/board.h" void reset_board(void) { diff --git a/ports/raspberrypi/boot_stage2/RP2040.c.jinja b/ports/raspberrypi/boot_stage2/RP2040.c.jinja index 4c001525dcc2f..c00b35fa662c6 100644 --- a/ports/raspberrypi/boot_stage2/RP2040.c.jinja +++ b/ports/raspberrypi/boot_stage2/RP2040.c.jinja @@ -1,7 +1,7 @@ -#include "sdk/src/rp2040/hardware_structs/include/hardware/structs/ssi.h" -#include "sdk/src/rp2040/hardware_structs/include/hardware/structs/pads_qspi.h" -#include "sdk/src/rp2040/hardware_regs/include/hardware/regs/addressmap.h" -#include "sdk/src/rp2040/hardware_regs/include/hardware/regs/m0plus.h" +#include "hardware/structs/ssi.h" +#include "hardware/structs/pads_qspi.h" +#include "hardware/regs/addressmap.h" +#include "hardware/regs/m0plus.h" // "Mode bits" are 8 special bits sent immediately after // the address bits in a "Read Data Fast Quad I/O" command sequence. diff --git a/ports/raspberrypi/common-hal/alarm/__init__.c b/ports/raspberrypi/common-hal/alarm/__init__.c index 35af165510085..a72b3a368d407 100644 --- a/ports/raspberrypi/common-hal/alarm/__init__.c +++ b/ports/raspberrypi/common-hal/alarm/__init__.c @@ -141,6 +141,10 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj mp_obj_t wake_alarm = mp_const_none; + // Save current clocks. + uint32_t saved_sleep_en0 = clocks_hw->sleep_en0; + uint32_t saved_sleep_en1 = clocks_hw->sleep_en1; + while (!mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; // Detect if interrupt was alarm or ctrl-C interrupt. @@ -163,21 +167,25 @@ mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const mp_obj break; } - // Prune the clock for sleep + // Prune the clocks for sleep. clocks_hw->sleep_en0 &= RP_LIGHTSLEEP_EN0_MASK; clocks_hw->sleep_en1 = RP_LIGHTSLEEP_EN1_MASK; // Enable System Control Block (SCB) deep sleep - uint save = scb_hw->scr; - scb_hw->scr = save | M0PLUS_SCR_SLEEPDEEP_BITS; + scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS; __wfi(); } + // Restore clocks so other wfi() uses, like time.sleep(), won't use the light-sleep settings. + clocks_hw->sleep_en0 = saved_sleep_en0; + clocks_hw->sleep_en1 = saved_sleep_en1; + if (mp_hal_is_interrupted()) { return mp_const_none; // Shouldn't be given to python code because exception handling should kick in. } + alarm_reset(); return wake_alarm; } @@ -189,7 +197,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { bool timealarm_set = alarm_time_timealarm_is_set(); #if CIRCUITPY_CYW43 diff --git a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c index ecebb072775ed..350306390eefb 100644 --- a/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c +++ b/ports/raspberrypi/common-hal/alarm/pin/PinAlarm.c @@ -39,7 +39,7 @@ static void gpio_callback(uint gpio, uint32_t events) { } } -void alarm_pin_pinalarm_entering_deep_sleep() { +void alarm_pin_pinalarm_entering_deep_sleep(void) { _not_yet_deep_sleeping = false; } diff --git a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c index 7385b21ea95e3..fe74f3213927c 100644 --- a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c +++ b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.c @@ -11,20 +11,25 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared/runtime/interrupt_char.h" #include "py/runtime.h" -#include "src/rp2_common/hardware_adc/include/hardware/adc.h" -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" -#include "src/common/pico_stdlib_headers/include/pico/stdlib.h" - -#define ADC_FIRST_PIN_NUMBER 26 -#define ADC_PIN_COUNT 4 +#include "hardware/adc.h" +#include "hardware/dma.h" +#include "pico/stdlib.h" #define ADC_CLOCK_INPUT 48000000 #define ADC_MAX_CLOCK_DIV (1 << (ADC_DIV_INT_MSB - ADC_DIV_INT_LSB + 1)) void common_hal_analogbufio_bufferedin_construct(analogbufio_bufferedin_obj_t *self, const mcu_pin_obj_t *pin, uint32_t sample_rate) { // Make sure pin number is in range for ADC - if (pin->number < ADC_FIRST_PIN_NUMBER || pin->number >= (ADC_FIRST_PIN_NUMBER + ADC_PIN_COUNT)) { - raise_ValueError_invalid_pins(); + if ((pin->number < ADC_BASE_PIN) + || (pin->number > ADC_BASE_PIN + NUM_ADC_CHANNELS - 1) + // On many boards with a CYW43 radio co-processor, CYW43_DEFAULT_PIN_WL_CLOCK (usually GPIO29), + // is both a voltage monitor and also SPI SCK to the CYW43. + // Disallow its use for BufferedIn. + #if defined(CIRCUITPY_CYW43) && defined(CYW43_DEFAULT_PIN_WL_CLOCK) + || (pin->number == CYW43_DEFAULT_PIN_WL_CLOCK) + #endif + ) { + raise_ValueError_invalid_pin(); } // Validate sample rate here @@ -35,7 +40,7 @@ void common_hal_analogbufio_bufferedin_construct(analogbufio_bufferedin_obj_t *s claim_pin(pin); // TODO: find a way to accept ADC4 for temperature - self->chan = pin->number - ADC_FIRST_PIN_NUMBER; + self->chan = pin->number - ADC_BASE_PIN; // Init GPIO for analogue use: hi-Z, no pulls, disable digital input buffer. // TODO: Make sure we share the ADC well. Right now we just assume it is diff --git a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.h b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.h index f0c536f392159..587668c1a7bf6 100644 --- a/ports/raspberrypi/common-hal/analogbufio/BufferedIn.h +++ b/ports/raspberrypi/common-hal/analogbufio/BufferedIn.h @@ -8,7 +8,7 @@ #pragma once #include "common-hal/microcontroller/Pin.h" -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" +#include "hardware/dma.h" #include "py/obj.h" diff --git a/ports/raspberrypi/common-hal/analogio/AnalogIn.c b/ports/raspberrypi/common-hal/analogio/AnalogIn.c index 301b965c86c15..2a9c2d1d42d3c 100644 --- a/ports/raspberrypi/common-hal/analogio/AnalogIn.c +++ b/ports/raspberrypi/common-hal/analogio/AnalogIn.c @@ -10,22 +10,14 @@ #include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" -#include "src/rp2_common/hardware_adc/include/hardware/adc.h" +#include "hardware/adc.h" -#define ADC_PIN_COUNT (NUM_ADC_CHANNELS - 1) - -#if ADC_PIN_COUNT == 4 -#define ADC_FIRST_PIN_NUMBER 26 -#else -#define ADC_FIRST_PIN_NUMBER 40 -#endif - -// Voltage monitor is special on Pico W, because this pin is shared between the -// voltage monitor function and the wifi function. Special handling is required -// to read the analog voltage. +// On many boards with a CYW43 radio co-processor, CYW43_DEFAULT_PIN_WL_CLOCK (usually GPIO29), +// is both a voltage monitor and also SPI SCK to the CYW43. +// Special handling is required to read the analog voltage. #if CIRCUITPY_CYW43 #include "bindings/cyw43/__init__.h" -#define SPECIAL_PIN(pin) (pin->number == 29) +#define SPECIAL_PIN(pin) (pin->number == CYW43_DEFAULT_PIN_WL_CLOCK) const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t obj) { return validate_obj_is_free_pin_or_gpio29(obj, MP_QSTR_pin); @@ -35,7 +27,7 @@ const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t obj) { #endif void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin) { - if (pin->number < ADC_FIRST_PIN_NUMBER || pin->number > ADC_FIRST_PIN_NUMBER + ADC_PIN_COUNT) { + if (pin->number < ADC_BASE_PIN || pin->number > ADC_BASE_PIN + NUM_ADC_CHANNELS - 1) { raise_ValueError_invalid_pin(); } @@ -70,7 +62,7 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { uint32_t old_pad = pads_bank0_hw->io[self->pin->number]; uint32_t old_ctrl = io_bank0_hw->io[self->pin->number].ctrl; adc_gpio_init(self->pin->number); - adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER); + adc_select_input(self->pin->number - ADC_BASE_PIN); common_hal_mcu_delay_us(100); value = adc_read(); gpio_init(self->pin->number); @@ -78,7 +70,7 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) { io_bank0_hw->io[self->pin->number].ctrl = old_ctrl; common_hal_mcu_enable_interrupts(); } else { - adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER); + adc_select_input(self->pin->number - ADC_BASE_PIN); value = adc_read(); } // Stretch 12-bit ADC reading to 16-bit range diff --git a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c index f3c23400db28e..d29f50b06b827 100644 --- a/ports/raspberrypi/common-hal/audiobusio/I2SOut.c +++ b/ports/raspberrypi/common-hal/audiobusio/I2SOut.c @@ -19,122 +19,152 @@ #include "bindings/rp2pio/StateMachine.h" const uint16_t i2s_program[] = { -// ; Load the next set of samples -// ; /--- LRCLK -// ; |/-- BCLK -// ; || -// pull noblock side 0b01 ; Loads OSR with the next FIFO value or X - 0x8880, -// mov x osr side 0b01 ; Save the new value in case we need it again - 0xa827, -// set y 14 side 0b01 - 0xe84e, -// bitloop1: -// out pins 1 side 0b00 [2] - 0x6201, -// jmp y-- bitloop1 side 0b01 [2] - 0x0a83, -// out pins 1 side 0b10 [2] - 0x7201, -// set y 14 side 0b11 [2] - 0xfa4e, -// bitloop0: -// out pins 1 side 0b10 [2] - 0x7201, -// jmp y-- bitloop0 side 0b11 [2] - 0x1a87, -// out pins 1 side 0b00 [2] - 0x6201 + +/* From i2s.pio: + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- LRCLK + ; |/-- BCLK + ; || + pull noblock side 0b11 ; Loads OSR with the next FIFO value or X + mov x osr side 0b11 ; Save the new value in case we need it again + set y 14 side 0b11 +bitloop1: + out pins 1 side 0b10 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b00 [2] + set y 14 side 0b01 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b01 [2] + out pins 1 side 0b10 [2] +*/ + // Above assembled with pioasm. + 0x9880, // 0: pull noblock side 3 + 0xb827, // 1: mov x, osr side 3 + 0xf84e, // 2: set y, 14 side 3 + 0x7201, // 3: out pins, 1 side 2 [2] + 0x1a83, // 4: jmp y--, 3 side 3 [2] + 0x6201, // 5: out pins, 1 side 0 [2] + 0xea4e, // 6: set y, 14 side 1 [2] + 0x6201, // 7: out pins, 1 side 0 [2] + 0x0a87, // 8: jmp y--, 7 side 1 [2] + 0x7201, // 9: out pins, 1 side 2 [2] }; + const uint16_t i2s_program_left_justified[] = { -// ; Load the next set of samples -// ; /--- LRCLK -// ; |/-- BCLK -// ; || -// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X - 0x9880, -// mov x osr side 0b11 ; Save the new value in case we need it again - 0xb827, -// set y 14 side 0b11 - 0xf84e, -// bitloop1: -// out pins 1 side 0b00 [2] - 0x6201, -// jmp y-- bitloop1 side 0b01 [2] - 0x0a83, -// out pins 1 side 0b00 [2] - 0x6201, -// set y 14 side 0b01 [2] - 0xea4e, -// bitloop0: -// out pins 1 side 0b10 [2] - 0x7201, -// jmp y-- bitloop0 side 0b11 [2] - 0x1a87, -// out pins 1 side 0b10 [2] - 0x7201 +/* From i2s_left.pio: + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- LRCLK + ; |/-- BCLK + ; || + pull noblock side 0b01 ; Loads OSR with the next FIFO value or X + mov x osr side 0b01 ; Save the new value in case we need it again + set y 14 side 0b01 +bitloop1: + out pins 1 side 0b10 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b10 [2] + set y 14 side 0b11 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b01 [2] + out pins 1 side 0b00 [2] +*/ + // Above assembled with pioasm. + 0x8880, // 0: pull noblock side 1 + 0xa827, // 1: mov x, osr side 1 + 0xe84e, // 2: set y, 14 side 1 + 0x7201, // 3: out pins, 1 side 2 [2] + 0x1a83, // 4: jmp y--, 3 side 3 [2] + 0x7201, // 5: out pins, 1 side 2 [2] + 0xfa4e, // 6: set y, 14 side 3 [2] + 0x6201, // 7: out pins, 1 side 0 [2] + 0x0a87, // 8: jmp y--, 7 side 1 [2] + 0x6201, // 9: out pins, 1 side 0 [2] }; // Another version of i2s_program with the LRCLC and BCLK pin swapped const uint16_t i2s_program_swap[] = { -// ; Load the next set of samples -// ; /--- BCLK -// ; |/-- LRCLK -// ; || -// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X - 0x9880, -// mov x osr side 0b11 ; Save the new value in case we need it again - 0xb827, -// set y 14 side 0b11 - 0xf84e, -// bitloop1: -// out pins 1 side 0b01 [2] - 0x6a01, -// jmp y-- bitloop1 side 0b11 [2] - 0x1a83, -// out pins 1 side 0b00 [2] - 0x6201, -// set y 14 side 0b10 [2] - 0xf24e, -// bitloop0: -// out pins 1 side 0b00 [2] - 0x6201, -// jmp y-- bitloop0 side 0b10 [2] - 0x1287, -// out pins 1 side 0b01 [2] - 0x6a01 +/* From i2s_swap.pio: + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- BCLK + ; |/-- LRCLK + ; || + pull noblock side 0b11 ; Loads OSR with the next FIFO value or X + mov x osr side 0b11 ; Save the new value in case we need it again + set y 14 side 0b11 +bitloop1: + out pins 1 side 0b01 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b00 [2] + set y 14 side 0b10 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b10 [2] + out pins 1 side 0b01 [2] +*/ + // Above assembled with pioasm. + 0x9880, // 0: pull noblock side 3 + 0xb827, // 1: mov x, osr side 3 + 0xf84e, // 2: set y, 14 side 3 + 0x6a01, // 3: out pins, 1 side 1 [2] + 0x1a83, // 4: jmp y--, 3 side 3 [2] + 0x6201, // 5: out pins, 1 side 0 [2] + 0xf24e, // 6: set y, 14 side 2 [2] + 0x6201, // 7: out pins, 1 side 0 [2] + 0x1287, // 8: jmp y--, 7 side 2 [2] + 0x6a01, // 9: out pins, 1 side 1 [2] }; // Another version of i2s_program_left_justified with the LRCLC and BCLK pin // swapped. const uint16_t i2s_program_left_justified_swap[] = { -// ; Load the next set of samples -// ; /--- BCLK -// ; |/-- LRCLK -// ; || -// pull noblock side 0b11 ; Loads OSR with the next FIFO value or X - 0x9880, -// mov x osr side 0b11 ; Save the new value in case we need it again - 0xb827, -// set y 14 side 0b11 - 0xf84e, -// bitloop1: -// out pins 1 side 0b00 [2] - 0x6201, -// jmp y-- bitloop1 side 0b10 [2] - 0x1283, -// out pins 1 side 0b00 [2] - 0x6201, -// set y 14 side 0b10 [2] - 0xf24e, -// bitloop0: -// out pins 1 side 0b01 [2] - 0x6a01, -// jmp y-- bitloop0 side 0b11 [2] - 0x1a87, -// out pins 1 side 0b01 [2] - 0x6a01 +/* From i2s_swap_left.pio: + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- BCLK + ; |/-- LRCLK + ; || + pull noblock side 0b10 ; Loads OSR with the next FIFO value or X + mov x osr side 0b10 ; Save the new value in case we need it again + set y 14 side 0b10 +bitloop1: + out pins 1 side 0b01 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b01 [2] + set y 14 side 0b11 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b10 [2] + out pins 1 side 0b00 [2] +*/ + // Above assembled with pioasm. + 0x9080, // 0: pull noblock side 2 + 0xb027, // 1: mov x, osr side 2 + 0xf04e, // 2: set y, 14 side 2 + 0x6a01, // 3: out pins, 1 side 1 [2] + 0x1a83, // 4: jmp y--, 3 side 3 [2] + 0x6a01, // 5: out pins, 1 side 1 [2] + 0xfa4e, // 6: set y, 14 side 3 [2] + 0x6201, // 7: out pins, 1 side 0 [2] + 0x1287, // 8: jmp y--, 7 side 2 [2] + 0x6201, // 9: out pins, 1 side 0 [2] }; void i2sout_reset(void) { @@ -184,21 +214,25 @@ void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self, 44100 * 32 * 6, // Clock at 44.1 khz to warm the DAC up. NULL, 0, // init NULL, 0, // may_exec - data, 1, 0, 0xffffffff, // out pin + data, 1, PIO_PINMASK32_NONE, PIO_PINMASK32_ALL, // out pin NULL, 0, // in pins - 0, 0, // in pulls - NULL, 0, 0, 0x1f, // set pins - sideset_pin, 2, 0, 0x1f, // sideset pins + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // in pulls + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // set pins + sideset_pin, 2, false, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // sideset pins false, // No sideset enable NULL, PULL_NONE, // jump pin - 0, // wait gpio pins + PIO_PINMASK_NONE, // wait gpio pins true, // exclusive pin use false, 32, false, // shift out left to start with MSB false, // Wait for txstall false, 32, false, // in settings false, // Not user-interruptible. 0, -1, // wrap settings - PIO_ANY_OFFSET); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, + PIO_MOV_N_DEFAULT + ); self->playing = false; audio_dma_init(&self->dma); @@ -228,7 +262,7 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, common_hal_audiobusio_i2sout_stop(self); } - uint8_t bits_per_sample = audiosample_bits_per_sample(sample); + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); // Make sure we transmit a minimum of 16 bits. // TODO: Maybe we need an intermediate object to upsample instead. This is // only needed for some I2S devices that expect at least 8. @@ -238,8 +272,8 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, // We always output stereo so output twice as many bits. uint16_t bits_per_sample_output = bits_per_sample * 2; size_t clocks_per_bit = 6; - uint32_t frequency = bits_per_sample_output * audiosample_sample_rate(sample); - uint8_t channel_count = audiosample_channel_count(sample); + uint32_t frequency = bits_per_sample_output * audiosample_get_sample_rate(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); if (channel_count > 2) { mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample.")); } @@ -270,6 +304,9 @@ void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, } else if (result == AUDIO_DMA_MEMORY_ERROR) { common_hal_audiobusio_i2sout_stop(self); mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion")); + } else if (result == AUDIO_DMA_SOURCE_ERROR) { + common_hal_audiobusio_i2sout_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error")); } self->playing = true; diff --git a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c index 11f239e4009ae..b436469d09098 100644 --- a/ports/raspberrypi/common-hal/audiobusio/PDMIn.c +++ b/ports/raspberrypi/common-hal/audiobusio/PDMIn.c @@ -43,26 +43,29 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self, // Use the state machine to manage pins. common_hal_rp2pio_statemachine_construct(&self->state_machine, pdmin, MP_ARRAY_SIZE(pdmin), - sample_rate * 32 * 2, // Frequency based on sample rate + sample_rate * OVERSAMPLING * 2, // Frequency based on sample rate NULL, 0, NULL, 0, // may_exec - NULL, 1, 0, 0xffffffff, // out pin + NULL, 1, PIO_PINMASK32_NONE, PIO_PINMASK32_ALL, // out pin data_pin, 1, // in pins - 0, 0, // in pulls - NULL, 0, 0, 0x1f, // set pins - clock_pin, 1, 0, 0x1f, // sideset pins + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // in pulls + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // set pins + clock_pin, 1, false, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // sideset pins false, // No sideset enable NULL, PULL_NONE, // jump pin - 0, // wait gpio pins + PIO_PINMASK_NONE, // wait gpio pins true, // exclusive pin use false, 32, false, // out settings false, // Wait for txstall false, 32, true, // in settings false, // Not user-interruptible. 0, -1, // wrap settings - PIO_ANY_OFFSET); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); uint32_t actual_frequency = common_hal_rp2pio_statemachine_get_frequency(&self->state_machine); - if (actual_frequency < MIN_MIC_CLOCK) { + if (actual_frequency < 2 * MIN_MIC_CLOCK) { // 2 PIO samples per audio clock + common_hal_audiobusio_pdmin_deinit(self); mp_raise_ValueError(MP_ERROR_TEXT("sampling rate out of range")); } diff --git a/ports/raspberrypi/common-hal/audiobusio/README.pio b/ports/raspberrypi/common-hal/audiobusio/README.pio new file mode 100644 index 0000000000000..53c73fbc19954 --- /dev/null +++ b/ports/raspberrypi/common-hal/audiobusio/README.pio @@ -0,0 +1,7 @@ +.pio files right now are compiled by hand with pico-sdk/tools/pioasm and inserted into I2SOut.c + +i2s.pio regular pin order, not left_justified +i2s_left.pio regular pin order, left_justified + +i2s_swap.pio swapped pin order, not left_justified +i2s_swap_left.pio swapped pin order, left_justified diff --git a/ports/raspberrypi/common-hal/audiobusio/i2s.pio b/ports/raspberrypi/common-hal/audiobusio/i2s.pio new file mode 100644 index 0000000000000..b3557eeb918a9 --- /dev/null +++ b/ports/raspberrypi/common-hal/audiobusio/i2s.pio @@ -0,0 +1,25 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- LRCLK + ; |/-- BCLK + ; || + pull noblock side 0b11 ; Loads OSR with the next FIFO value or X + mov x osr side 0b11 ; Save the new value in case we need it again + set y 14 side 0b11 +bitloop1: + out pins 1 side 0b10 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b00 [2] + set y 14 side 0b01 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b01 [2] + out pins 1 side 0b10 [2] diff --git a/ports/raspberrypi/common-hal/audiobusio/i2s_left.pio b/ports/raspberrypi/common-hal/audiobusio/i2s_left.pio new file mode 100644 index 0000000000000..4830ec420782d --- /dev/null +++ b/ports/raspberrypi/common-hal/audiobusio/i2s_left.pio @@ -0,0 +1,25 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- LRCLK + ; |/-- BCLK + ; || + pull noblock side 0b01 ; Loads OSR with the next FIFO value or X + mov x osr side 0b01 ; Save the new value in case we need it again + set y 14 side 0b01 +bitloop1: + out pins 1 side 0b10 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b10 [2] + set y 14 side 0b11 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b01 [2] + out pins 1 side 0b00 [2] diff --git a/ports/raspberrypi/common-hal/audiobusio/i2s_swap.pio b/ports/raspberrypi/common-hal/audiobusio/i2s_swap.pio new file mode 100644 index 0000000000000..a7ecf94c764bc --- /dev/null +++ b/ports/raspberrypi/common-hal/audiobusio/i2s_swap.pio @@ -0,0 +1,25 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- BCLK + ; |/-- LRCLK + ; || + pull noblock side 0b11 ; Loads OSR with the next FIFO value or X + mov x osr side 0b11 ; Save the new value in case we need it again + set y 14 side 0b11 +bitloop1: + out pins 1 side 0b01 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b00 [2] + set y 14 side 0b10 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b10 [2] + out pins 1 side 0b01 [2] diff --git a/ports/raspberrypi/common-hal/audiobusio/i2s_swap_left.pio b/ports/raspberrypi/common-hal/audiobusio/i2s_swap_left.pio new file mode 100644 index 0000000000000..4e6373dd65a1e --- /dev/null +++ b/ports/raspberrypi/common-hal/audiobusio/i2s_swap_left.pio @@ -0,0 +1,25 @@ +; This file is part of the CircuitPython project: https://circuitpython.org +; +; SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +; +; SPDX-License-Identifier: MIT + +.program i2s +.side_set 2 + +; Load the next set of samples + ; /--- BCLK + ; |/-- LRCLK + ; || + pull noblock side 0b10 ; Loads OSR with the next FIFO value or X + mov x osr side 0b10 ; Save the new value in case we need it again + set y 14 side 0b10 +bitloop1: + out pins 1 side 0b01 [2] ; Right channel first + jmp y-- bitloop1 side 0b11 [2] + out pins 1 side 0b01 [2] + set y 14 side 0b11 [2] +bitloop0: + out pins 1 side 0b00 [2] ; Then left channel + jmp y-- bitloop0 side 0b10 [2] + out pins 1 side 0b00 [2] diff --git a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c index d4cf161e61977..6fa5bf02c1486 100644 --- a/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/raspberrypi/common-hal/audiopwmio/PWMAudioOut.c @@ -20,8 +20,8 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Processor.h" -#include "src/rp2040/hardware_structs/include/hardware/structs/dma.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" +#include "hardware/structs/dma.h" +#include "hardware/pwm.h" // The PWM clock frequency is base_clock_rate / PWM_TOP, typically 125_000_000 / PWM_TOP. // We pick BITS_PER_SAMPLE so we get a clock frequency that is above what would cause aliasing. @@ -187,7 +187,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, // to trigger the DMA. Each has a 16 bit fractional divisor system clock * X / Y where X and Y // are 16-bit. - uint32_t sample_rate = audiosample_sample_rate(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); uint32_t system_clock = common_hal_mcu_processor_get_frequency(); uint32_t best_denominator; @@ -214,6 +214,10 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, common_hal_audiopwmio_pwmaudioout_stop(self); mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion")); } + if (result == AUDIO_DMA_SOURCE_ERROR) { + common_hal_audiopwmio_pwmaudioout_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error")); + } // OK! We got all of the resources we need and dma is ready. } diff --git a/ports/raspberrypi/common-hal/busio/I2C.c b/ports/raspberrypi/common-hal/busio/I2C.c index b7db4064b15d7..1441a2a7a0668 100644 --- a/ports/raspberrypi/common-hal/busio/I2C.c +++ b/ports/raspberrypi/common-hal/busio/I2C.c @@ -13,7 +13,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/bitbangio/I2C.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" // Synopsys DW_apb_i2c (v2.01) IP @@ -22,21 +22,14 @@ // One second #define BUS_TIMEOUT_US 1000000 -static bool never_reset_i2c[2]; static i2c_inst_t *i2c[2] = {i2c0, i2c1}; -void reset_i2c(void) { - for (size_t i = 0; i < 2; i++) { - if (never_reset_i2c[i]) { - continue; - } - - i2c_deinit(i2c[i]); - } -} - void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + + // Ensure object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + self->peripheral = NULL; // I2C pins have a regular pattern. SCL is always odd and SDA is even. They match up in pairs // so we can divide by two to get the instance. This pattern repeats. @@ -93,7 +86,7 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, // // Do not use the default supplied clock stretching timeout here. // It is too short for some devices. Use the busio timeout instead. - shared_module_bitbangio_i2c_construct(&self->bitbangio_i2c, scl, sda, + shared_module_bitbangio_i2c_construct(&self->bitbangio_i2c, MP_OBJ_FROM_PTR(scl), MP_OBJ_FROM_PTR(sda), frequency, BUS_TIMEOUT_US); self->baudrate = i2c_init(self->peripheral, frequency); @@ -115,14 +108,16 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { if (common_hal_busio_i2c_deinited(self)) { return; } - never_reset_i2c[i2c_hw_index(self->peripheral)] = false; i2c_deinit(self->peripheral); reset_pin_number(self->sda_pin); reset_pin_number(self->scl_pin); + common_hal_busio_i2c_mark_deinit(self); +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { self->sda_pin = NO_PIN; - self->scl_pin = NO_PIN; } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { @@ -130,6 +125,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; @@ -146,7 +144,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { self->has_lock = false; } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { if (len == 0) { // The RP2040 I2C peripheral will not perform 0 byte writes. @@ -176,20 +174,20 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, } switch (result) { case PICO_ERROR_GENERIC: - return MP_ENODEV; + return -MP_ENODEV; case PICO_ERROR_TIMEOUT: - return MP_ETIMEDOUT; + return -MP_ETIMEDOUT; default: - return MP_EIO; + return -MP_EIO; } } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { size_t result = i2c_read_timeout_us(self->peripheral, addr, data, len, false, BUS_TIMEOUT_US); if (result == len) { @@ -197,17 +195,17 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, } switch (result) { case PICO_ERROR_GENERIC: - return MP_ENODEV; + return -MP_ENODEV; case PICO_ERROR_TIMEOUT: - return MP_ETIMEDOUT; + return -MP_ETIMEDOUT; default: - return MP_EIO; + return -MP_EIO; } } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } @@ -216,8 +214,6 @@ uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - never_reset_i2c[i2c_hw_index(self->peripheral)] = true; - never_reset_pin_number(self->scl_pin); never_reset_pin_number(self->sda_pin); } diff --git a/ports/raspberrypi/common-hal/busio/I2C.h b/ports/raspberrypi/common-hal/busio/I2C.h index 9d97025c48e2c..7a6fd1b9d1f37 100644 --- a/ports/raspberrypi/common-hal/busio/I2C.h +++ b/ports/raspberrypi/common-hal/busio/I2C.h @@ -11,7 +11,7 @@ #include "py/obj.h" -#include "src/rp2_common/hardware_i2c/include/hardware/i2c.h" +#include "hardware/i2c.h" typedef struct { mp_obj_base_t base; @@ -22,5 +22,3 @@ typedef struct { uint8_t scl_pin; uint8_t sda_pin; } busio_i2c_obj_t; - -void reset_i2c(void); diff --git a/ports/raspberrypi/common-hal/busio/SPI.c b/ports/raspberrypi/common-hal/busio/SPI.c index 65a9d7ba95f62..aeb06d919ae45 100644 --- a/ports/raspberrypi/common-hal/busio/SPI.c +++ b/ports/raspberrypi/common-hal/busio/SPI.c @@ -14,29 +14,19 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/dma.h" +#include "hardware/gpio.h" #define NO_INSTANCE 0xff -static bool never_reset_spi[2]; -static spi_inst_t *spi[2] = {spi0, spi1}; - -void reset_spi(void) { - for (size_t i = 0; i < 2; i++) { - if (never_reset_spi[i]) { - continue; - } - - spi_deinit(spi[i]); - } -} - void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { size_t instance_index = NO_INSTANCE; + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + if (half_duplex) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_half_duplex); } @@ -96,8 +86,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, } void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - never_reset_spi[spi_get_index(self->peripheral)] = true; - common_hal_never_reset_pin(self->clock); common_hal_never_reset_pin(self->MOSI); common_hal_never_reset_pin(self->MISO); @@ -107,17 +95,21 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->clock = NULL; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; } - never_reset_spi[spi_get_index(self->peripheral)] = false; spi_deinit(self->peripheral); common_hal_reset_pin(self->clock); common_hal_reset_pin(self->MOSI); common_hal_reset_pin(self->MISO); - self->clock = NULL; + + common_hal_busio_spi_mark_deinit(self); } bool common_hal_busio_spi_configure(busio_spi_obj_t *self, @@ -150,6 +142,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; @@ -179,7 +174,10 @@ static bool _transfer(busio_spi_obj_t *self, chan_tx = dma_claim_unused_channel(false); chan_rx = dma_claim_unused_channel(false); } - bool use_dma = chan_rx >= 0 && chan_tx >= 0; + bool has_dma_channels = chan_rx >= 0 && chan_tx >= 0; + // Only use DMA if both data buffers are in SRAM. Otherwise, we'll stall the DMA with PSRAM or flash cache misses. + bool data_in_sram = data_in >= (uint8_t *)SRAM_BASE && data_out >= (uint8_t *)SRAM_BASE; + bool use_dma = has_dma_channels && data_in_sram; if (use_dma) { dma_channel_config c = dma_channel_get_default_config(chan_tx); channel_config_set_transfer_data_size(&c, DMA_SIZE_8); diff --git a/ports/raspberrypi/common-hal/busio/SPI.h b/ports/raspberrypi/common-hal/busio/SPI.h index 27d4cf6f3c72b..3d43c1eff0072 100644 --- a/ports/raspberrypi/common-hal/busio/SPI.h +++ b/ports/raspberrypi/common-hal/busio/SPI.h @@ -10,7 +10,7 @@ #include "py/obj.h" -#include "src/rp2_common/hardware_spi/include/hardware/spi.h" +#include "hardware/spi.h" typedef struct { mp_obj_base_t base; @@ -25,5 +25,3 @@ typedef struct { uint8_t phase; uint8_t bits; } busio_spi_obj_t; - -void reset_spi(void); diff --git a/ports/raspberrypi/common-hal/busio/UART.c b/ports/raspberrypi/common-hal/busio/UART.c index aeb0ff4bea289..17fcfa172293d 100644 --- a/ports/raspberrypi/common-hal/busio/UART.c +++ b/ports/raspberrypi/common-hal/busio/UART.c @@ -14,8 +14,8 @@ #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/irq.h" +#include "hardware/gpio.h" #define NO_PIN 0xff diff --git a/ports/raspberrypi/common-hal/busio/UART.h b/ports/raspberrypi/common-hal/busio/UART.h index ca75235ddf879..3709907633cb0 100644 --- a/ports/raspberrypi/common-hal/busio/UART.h +++ b/ports/raspberrypi/common-hal/busio/UART.h @@ -9,7 +9,7 @@ #include "py/obj.h" #include "py/ringbuf.h" -#include "src/rp2_common/hardware_uart/include/hardware/uart.h" +#include "hardware/uart.h" typedef struct { mp_obj_base_t base; diff --git a/ports/raspberrypi/common-hal/countio/Counter.c b/ports/raspberrypi/common-hal/countio/Counter.c index 1a270bf882070..ba82ca8e7ab9d 100644 --- a/ports/raspberrypi/common-hal/countio/Counter.c +++ b/ports/raspberrypi/common-hal/countio/Counter.c @@ -13,9 +13,9 @@ #include "shared-bindings/digitalio/Pull.h" #include "common-hal/pwmio/PWMOut.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "hardware/gpio.h" +#include "hardware/pwm.h" +#include "hardware/irq.h" void common_hal_countio_counter_construct(countio_counter_obj_t *self, diff --git a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c index 60849eb120af8..f20facdad7dfc 100644 --- a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c +++ b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c @@ -14,7 +14,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #if CIRCUITPY_CYW43 #include "pico/cyw43_arch.h" diff --git a/ports/raspberrypi/common-hal/floppyio/__init__.c b/ports/raspberrypi/common-hal/floppyio/__init__.c index 570e5c7a98c1e..3f76e892da8d4 100644 --- a/ports/raspberrypi/common-hal/floppyio/__init__.c +++ b/ports/raspberrypi/common-hal/floppyio/__init__.c @@ -77,7 +77,8 @@ int common_hal_floppyio_flux_readinto(void *buf, size_t len, digitalio_digitalin memset(buf, 0, len); - uint32_t pins_we_use = 1 << data->pin->number; + + pio_pinmask_t pins_we_use = PIO_PINMASK_FROM_PIN(data->pin->number); rp2pio_statemachine_obj_t state_machine; bool ok = rp2pio_statemachine_construct(&state_machine, @@ -86,10 +87,10 @@ int common_hal_floppyio_flux_readinto(void *buf, size_t len, digitalio_digitalin NULL, 0, // init program NULL, 0, // out index->pin, 1, // in - 1, 0, // in pull up/down + PIO_PINMASK_FROM_PIN(index->pin->number), PIO_PINMASK_FROM_VALUE(0), // pull up/down NULL, 0, // set - NULL, 0, // sideset - 0, 0, // initial pin state + NULL, 0, false, // sideset + PIO_PINMASK_FROM_VALUE(0), PIO_PINMASK_FROM_VALUE(0), // initial pin state data->pin, // jump pin pins_we_use, false, true, true, 32, false, // TX setting we don't use @@ -99,7 +100,9 @@ int common_hal_floppyio_flux_readinto(void *buf, size_t len, digitalio_digitalin false, // Not user-interruptible. false, // No sideset enable 0, -1, // wrap - PIO_ANY_OFFSET // offset + PIO_ANY_OFFSET, // offset + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT ); if (!ok) { mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use")); diff --git a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c index 4f226fe56e957..a40f6e26608a9 100644 --- a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c +++ b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.c @@ -14,7 +14,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "py/runtime.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" static i2c_inst_t *i2c[2] = {i2c0, i2c1}; @@ -85,6 +85,13 @@ void common_hal_i2ctarget_i2c_target_deinit(i2ctarget_i2c_target_obj_t *self) { } int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *self, uint8_t *address, bool *is_read, bool *is_restart) { + // Interrupt bits must be cleared by software. Clear the STOP and + // RESTART interrupt bits after an I2C transaction finishes. + if (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) { + self->peripheral->hw->clr_stop_det; + self->peripheral->hw->clr_restart_det; + } + if (!((self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RX_FULL_BITS) || (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_RD_REQ_BITS))) { return 0; } @@ -98,12 +105,20 @@ int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *sel } int common_hal_i2ctarget_i2c_target_read_byte(i2ctarget_i2c_target_obj_t *self, uint8_t *data) { - if (self->peripheral->hw->status & I2C_IC_STATUS_RFNE_BITS) { - *data = (uint8_t)self->peripheral->hw->data_cmd; - return 1; - } else { - return 0; + // Wait for data to arrive or a STOP condition indicating the transfer is over. + // Without this wait, the CPU can drain the FIFO faster than bytes arrive on the + // I2C bus, causing transfers to be split into multiple partial reads. + for (int t = 0; t < 100; t++) { + if (self->peripheral->hw->status & I2C_IC_STATUS_RFNE_BITS) { + *data = (uint8_t)self->peripheral->hw->data_cmd; + return 1; + } + if (self->peripheral->hw->raw_intr_stat & I2C_IC_INTR_STAT_R_STOP_DET_BITS) { + break; + } + mp_hal_delay_us(10); } + return 0; } int common_hal_i2ctarget_i2c_target_write_byte(i2ctarget_i2c_target_obj_t *self, uint8_t data) { diff --git a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.h b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.h index 0b6c2875e3f40..5d4e0690cbffd 100644 --- a/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.h +++ b/ports/raspberrypi/common-hal/i2ctarget/I2CTarget.h @@ -8,7 +8,7 @@ #include "py/obj.h" #include "common-hal/microcontroller/Pin.h" -#include "src/rp2_common/hardware_i2c/include/hardware/i2c.h" +#include "hardware/i2c.h" typedef struct { mp_obj_base_t base; diff --git a/ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c b/ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c index a05307313b6d0..d0a7a1d7b08a1 100644 --- a/ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c +++ b/ports/raspberrypi/common-hal/imagecapture/ParallelImageCapture.c @@ -18,8 +18,8 @@ #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/__init__.h" -#include "src/rp2_common/hardware_pio/include/hardware/pio.h" -#include "src/rp2_common/hardware_pio/include/hardware/pio_instructions.h" +#include "hardware/pio.h" +#include "hardware/pio_instructions.h" // Define this to (1), and you can scope the instruction-pointer of the state machine on D26..28 (note the weird encoding though!) #define DEBUG_STATE_MACHINE (0) @@ -83,25 +83,28 @@ void common_hal_imagecapture_parallelimagecapture_construct(imagecapture_paralle common_hal_mcu_processor_get_frequency(), // full speed (4 instructions per loop -> max pclk 30MHz @ 120MHz) 0, 0, // init NULL, 0, // may_exec - NULL, 0, 0, 0, // out pins + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // out pins pin_from_number(data_pins[0]), data_count, // in pins - 0, 0, // in pulls - NULL, 0, 0, 0, // set pins + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // in pulls + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // set pins #if DEBUG_STATE_MACHINE - &pin_GPIO26, 3, 7, 7, // sideset pins + &pin_GPIO26, 3, PIO_PINMASK32_FROM_VALUE(7), PIO_PINMASK32_FROM_VALUE(7), // sideset pins #else - NULL, 0, 0, 0, // sideset pins + NULL, 0, false, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // sideset pins #endif false, // No sideset enable NULL, PULL_NONE, // jump pin - (1 << vertical_sync->number) | (1 << horizontal_reference->number) | (1 << data_clock->number), // wait gpio pins + PIO_PINMASK_OR3(PIO_PINMASK_FROM_PIN(vertical_sync->number), PIO_PINMASK_FROM_PIN(horizontal_reference->number), PIO_PINMASK_FROM_PIN(data_clock->number)), + // wait gpio pins true, // exclusive pin use false, 32, false, // out settings false, // wait for txstall true, 32, true, // in settings false, // Not user-interruptible. 2, 5, // wrap settings - PIO_ANY_OFFSET); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); } void common_hal_imagecapture_parallelimagecapture_deinit(imagecapture_parallelimagecapture_obj_t *self) { diff --git a/ports/raspberrypi/common-hal/max3421e/Max3421E.c b/ports/raspberrypi/common-hal/max3421e/Max3421E.c index 20ce701b9f3cc..0077b460ed0a0 100644 --- a/ports/raspberrypi/common-hal/max3421e/Max3421E.c +++ b/ports/raspberrypi/common-hal/max3421e/Max3421E.c @@ -10,7 +10,7 @@ #include "shared-bindings/busio/SPI.h" #include "supervisor/usb.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" static max3421e_max3421e_obj_t *active_max = NULL; diff --git a/ports/raspberrypi/common-hal/mcp4822/MCP4822.c b/ports/raspberrypi/common-hal/mcp4822/MCP4822.c new file mode 100644 index 0000000000000..7a8ad7d4df29c --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/MCP4822.c @@ -0,0 +1,286 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT +// +// MCP4822 dual-channel 12-bit SPI DAC audio output. +// Uses PIO + DMA for non-blocking audio playback, mirroring audiobusio.I2SOut. + +#include +#include + +#include "mpconfigport.h" + +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "common-hal/mcp4822/MCP4822.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" +#include "bindings/rp2pio/StateMachine.h" + +// ───────────────────────────────────────────────────────────────────────────── +// PIO program for MCP4822 SPI DAC +// ───────────────────────────────────────────────────────────────────────────── +// +// Pin assignment: +// OUT pin (1) = MOSI — serial data out +// SET pins (N) = MOSI through CS — for CS control & command-bit injection +// SIDE-SET pin (1) = SCK — serial clock +// +// SET PINS bit mapping (bit0=MOSI, ..., bit N=CS): +// 0 = CS low, MOSI low 1 = CS low, MOSI high +// (1 << cs_bit_pos) = CS high, MOSI low +// +// SIDE-SET (1 pin, SCK): side 0 = SCK low, side 1 = SCK high +// +// MCP4822 16-bit command word: +// [15] channel (0=A, 1=B) [14] don't care [13] gain (1=1x, 0=2x) +// [12] output enable (1) [11:0] 12-bit data +// +// DMA feeds unsigned 16-bit audio samples. RP2040 narrow-write replication +// fills both halves of the 32-bit PIO FIFO entry with the same value, +// giving mono→stereo for free. +// +// The PIO pulls 32 bits, then sends two SPI transactions: +// Channel A: cmd nibble, then all 16 sample bits from upper half-word +// Channel B: cmd nibble, then all 16 sample bits from lower half-word +// The MCP4822 captures exactly 16 bits per CS frame (4 cmd + 12 data), +// so only the top 12 of the 16 sample bits become DAC data. The bottom +// 4 sample bits clock out harmlessly after the DAC has latched. +// This gives correct 16-bit → 12-bit scaling (effectively sample >> 4). +// +// PIO instruction encoding with .side_set 1 (no opt): +// [15:13] opcode [12] side-set [11:8] delay [7:0] operands +// +// Total: 26 instructions, 86 PIO clocks per audio sample. +// ───────────────────────────────────────────────────────────────────────────── + +static const uint16_t mcp4822_pio_program[] = { + // side SCK + // 0: pull noblock side 0 ; Get 32 bits or keep X if FIFO empty + 0x8080, + // 1: mov x, osr side 0 ; Save for pull-noblock fallback + 0xA027, + + // ── Channel A: command nibble 0b0011 (1x gain) ──────────────────────── + // 2: set pins, 0 side 0 ; CS low, MOSI=0 (bit15=0: channel A) + 0xE000, + // 3: nop side 1 ; SCK high — latch bit 15 + 0xB042, + // 4: set pins, 0 side 0 ; MOSI=0 (bit14=0: don't care) + 0xE000, + // 5: nop side 1 ; SCK high + 0xB042, + // 6: set pins, 1 side 0 ; MOSI=1 (bit13=1: gain 1x) [patched for 2x] + 0xE001, + // 7: nop side 1 ; SCK high + 0xB042, + // 8: set pins, 1 side 0 ; MOSI=1 (bit12=1: output active) + 0xE001, + // 9: nop side 1 ; SCK high + 0xB042, + // 10: set y, 15 side 0 ; Loop counter: 16 sample bits + 0xE04F, + // 11: out pins, 1 side 0 ; Data bit → MOSI; SCK low (bitloopA) + 0x6001, + // 12: jmp y--, 11 side 1 ; SCK high, loop back + 0x108B, + // 13: set pins, 4 side 0 ; CS high — DAC A latches + 0xE004, + + // ── Channel B: command nibble 0b1011 (1x gain) ──────────────────────── + // 14: set pins, 1 side 0 ; CS low, MOSI=1 (bit15=1: channel B) + 0xE001, + // 15: nop side 1 ; SCK high + 0xB042, + // 16: set pins, 0 side 0 ; MOSI=0 (bit14=0) + 0xE000, + // 17: nop side 1 ; SCK high + 0xB042, + // 18: set pins, 1 side 0 ; MOSI=1 (bit13=1: gain 1x) [patched for 2x] + 0xE001, + // 19: nop side 1 ; SCK high + 0xB042, + // 20: set pins, 1 side 0 ; MOSI=1 (bit12=1: output active) + 0xE001, + // 21: nop side 1 ; SCK high + 0xB042, + // 22: set y, 15 side 0 ; Loop counter: 16 sample bits + 0xE04F, + // 23: out pins, 1 side 0 ; Data bit → MOSI; SCK low (bitloopB) + 0x6001, + // 24: jmp y--, 23 side 1 ; SCK high, loop back + 0x1097, + // 25: set pins, 4 side 0 ; CS high — DAC B latches + 0xE004, +}; + +// Clocks per sample: 2 (pull+mov) + 42 (chanA) + 42 (chanB) = 86 +// Per channel: 8(4 cmd bits × 2 clks) + 1(set y) + 32(16 bits × 2 clks) + 1(cs high) = 42 +#define MCP4822_CLOCKS_PER_SAMPLE 86 + +// MCP4822 gain bit (bit 13) position in the PIO program: +// Instruction 6 = channel A gain bit +// Instruction 18 = channel B gain bit +// 1x gain: set pins, 1 (0xE001) — bit 13 = 1 +// 2x gain: set pins, 0 (0xE000) — bit 13 = 0 +#define MCP4822_PIO_GAIN_INSTR_A 6 +#define MCP4822_PIO_GAIN_INSTR_B 18 +#define MCP4822_PIO_GAIN_1X 0xE001 // set pins, 1 +#define MCP4822_PIO_GAIN_2X 0xE000 // set pins, 0 + +void mcp4822_reset(void) { +} + +// Caller validates that pins are free. +void common_hal_mcp4822_mcp4822_construct(mcp4822_mcp4822_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *cs, uint8_t gain) { + + // The SET pin group spans from MOSI to CS. + // MOSI must have a lower GPIO number than CS, gap at most 4. + if (cs->number <= mosi->number || (cs->number - mosi->number) > 4) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q and %q"), MP_QSTR_CS, MP_QSTR_MOSI); + } + + uint8_t set_count = cs->number - mosi->number + 1; + + // Build a mutable copy of the PIO program and patch the gain bit + uint16_t program[MP_ARRAY_SIZE(mcp4822_pio_program)]; + memcpy(program, mcp4822_pio_program, sizeof(mcp4822_pio_program)); + uint16_t gain_instr = (gain == 2) ? MCP4822_PIO_GAIN_2X : MCP4822_PIO_GAIN_1X; + program[MCP4822_PIO_GAIN_INSTR_A] = gain_instr; + program[MCP4822_PIO_GAIN_INSTR_B] = gain_instr; + + // Initial SET pin state: CS high (bit at CS position), others low + uint32_t cs_bit_position = cs->number - mosi->number; + pio_pinmask32_t initial_set_state = PIO_PINMASK32_FROM_VALUE(1u << cs_bit_position); + pio_pinmask32_t initial_set_dir = PIO_PINMASK32_FROM_VALUE((1u << set_count) - 1); + + common_hal_rp2pio_statemachine_construct( + &self->state_machine, + program, MP_ARRAY_SIZE(mcp4822_pio_program), + 44100 * MCP4822_CLOCKS_PER_SAMPLE, // Initial frequency; play() adjusts + NULL, 0, // No init program + NULL, 0, // No may_exec + mosi, 1, // OUT: MOSI, 1 pin + PIO_PINMASK32_NONE, PIO_PINMASK32_ALL, // OUT state=low, dir=output + NULL, 0, // IN: none + PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // IN pulls: none + mosi, set_count, // SET: MOSI..CS + initial_set_state, initial_set_dir, // SET state (CS high), dir=output + clock, 1, false, // SIDE-SET: SCK, 1 pin, not pindirs + PIO_PINMASK32_NONE, // SIDE-SET state: SCK low + PIO_PINMASK32_FROM_VALUE(0x1), // SIDE-SET dir: output + false, // No sideset enable + NULL, PULL_NONE, // No jump pin + PIO_PINMASK_NONE, // No wait GPIO + true, // Exclusive pin use + false, 32, false, // OUT shift: no autopull, 32-bit, shift left + false, // Don't wait for txstall + false, 32, false, // IN shift (unused) + false, // Not user-interruptible + 0, -1, // Wrap: whole program + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, + PIO_MOV_N_DEFAULT + ); + + self->playing = false; + audio_dma_init(&self->dma); +} + +bool common_hal_mcp4822_mcp4822_deinited(mcp4822_mcp4822_obj_t *self) { + return common_hal_rp2pio_statemachine_deinited(&self->state_machine); +} + +void common_hal_mcp4822_mcp4822_deinit(mcp4822_mcp4822_obj_t *self) { + if (common_hal_mcp4822_mcp4822_deinited(self)) { + return; + } + if (common_hal_mcp4822_mcp4822_get_playing(self)) { + common_hal_mcp4822_mcp4822_stop(self); + } + common_hal_rp2pio_statemachine_deinit(&self->state_machine); + audio_dma_deinit(&self->dma); +} + +void common_hal_mcp4822_mcp4822_play(mcp4822_mcp4822_obj_t *self, + mp_obj_t sample, bool loop) { + + if (common_hal_mcp4822_mcp4822_get_playing(self)) { + common_hal_mcp4822_mcp4822_stop(self); + } + + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); + if (bits_per_sample < 16) { + bits_per_sample = 16; + } + + uint32_t sample_rate = audiosample_get_sample_rate(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); + if (channel_count > 2) { + mp_raise_ValueError(MP_ERROR_TEXT("Too many channels in sample.")); + } + + // PIO clock = sample_rate × clocks_per_sample + common_hal_rp2pio_statemachine_set_frequency( + &self->state_machine, + (uint32_t)sample_rate * MCP4822_CLOCKS_PER_SAMPLE); + common_hal_rp2pio_statemachine_restart(&self->state_machine); + + audio_dma_result result = audio_dma_setup_playback( + &self->dma, + sample, + loop, + false, // single_channel_output + 0, // audio_channel + false, // output_signed = false (unsigned for MCP4822) + bits_per_sample, // output_resolution + (uint32_t)&self->state_machine.pio->txf[self->state_machine.state_machine], + self->state_machine.tx_dreq, + false); // swap_channel + + if (result == AUDIO_DMA_DMA_BUSY) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("No DMA channel found")); + } else if (result == AUDIO_DMA_MEMORY_ERROR) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Unable to allocate buffers for signed conversion")); + } else if (result == AUDIO_DMA_SOURCE_ERROR) { + common_hal_mcp4822_mcp4822_stop(self); + mp_raise_RuntimeError(MP_ERROR_TEXT("Audio source error")); + } + + self->playing = true; +} + +void common_hal_mcp4822_mcp4822_pause(mcp4822_mcp4822_obj_t *self) { + audio_dma_pause(&self->dma); +} + +void common_hal_mcp4822_mcp4822_resume(mcp4822_mcp4822_obj_t *self) { + audio_dma_resume(&self->dma); +} + +bool common_hal_mcp4822_mcp4822_get_paused(mcp4822_mcp4822_obj_t *self) { + return audio_dma_get_paused(&self->dma); +} + +void common_hal_mcp4822_mcp4822_stop(mcp4822_mcp4822_obj_t *self) { + audio_dma_stop(&self->dma); + common_hal_rp2pio_statemachine_stop(&self->state_machine); + self->playing = false; +} + +bool common_hal_mcp4822_mcp4822_get_playing(mcp4822_mcp4822_obj_t *self) { + bool playing = audio_dma_get_playing(&self->dma); + if (!playing && self->playing) { + common_hal_mcp4822_mcp4822_stop(self); + } + return playing; +} diff --git a/ports/raspberrypi/common-hal/mcp4822/MCP4822.h b/ports/raspberrypi/common-hal/mcp4822/MCP4822.h new file mode 100644 index 0000000000000..53c8e862b63c5 --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/MCP4822.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/rp2pio/StateMachine.h" + +#include "audio_dma.h" +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + rp2pio_statemachine_obj_t state_machine; + audio_dma_t dma; + bool playing; +} mcp4822_mcp4822_obj_t; + +void mcp4822_reset(void); diff --git a/ports/raspberrypi/common-hal/mcp4822/__init__.c b/ports/raspberrypi/common-hal/mcp4822/__init__.c new file mode 100644 index 0000000000000..48981fc88a713 --- /dev/null +++ b/ports/raspberrypi/common-hal/mcp4822/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +// No module-level init needed. diff --git a/ports/raspberrypi/common-hal/mdns/Server.c b/ports/raspberrypi/common-hal/mdns/Server.c index 4c87dd4664077..ac0c73389b1a5 100644 --- a/ports/raspberrypi/common-hal/mdns/Server.c +++ b/ports/raspberrypi/common-hal/mdns/Server.c @@ -211,7 +211,7 @@ static void alloc_search_result_cb(struct mdns_answer *answer, const char *varpa if ((flags & MDNS_SEARCH_RESULT_FIRST) != 0) { // first - mdns_remoteservice_obj_t *service = m_malloc(sizeof(mdns_remoteservice_obj_t)); + mdns_remoteservice_obj_t *service = m_malloc_maybe(sizeof(mdns_remoteservice_obj_t)); if (service == NULL) { // alloc fails mdns_search_stop(state->request_id); diff --git a/ports/raspberrypi/common-hal/microcontroller/Pin.c b/ports/raspberrypi/common-hal/microcontroller/Pin.c index 4ea7516d70915..3c5286d36c4e9 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Pin.c +++ b/ports/raspberrypi/common-hal/microcontroller/Pin.c @@ -9,7 +9,7 @@ #include "common-hal/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" static uint64_t gpio_bank0_pin_claimed; diff --git a/ports/raspberrypi/common-hal/microcontroller/Processor.c b/ports/raspberrypi/common-hal/microcontroller/Processor.c index 678ceefbf92ff..a3ea890d9aff3 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Processor.c +++ b/ports/raspberrypi/common-hal/microcontroller/Processor.c @@ -15,31 +15,26 @@ #include "shared-bindings/time/__init__.h" #include "pico/stdlib.h" -#include "src/rp2_common/hardware_adc/include/hardware/adc.h" -#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h" -#include "src/rp2_common/hardware_vreg/include/hardware/vreg.h" -#include "src/rp2_common/hardware_watchdog/include/hardware/watchdog.h" +#include "hardware/adc.h" +#include "hardware/clocks.h" +#include "hardware/vreg.h" +#include "hardware/watchdog.h" #ifdef PICO_RP2040 -#include "src/rp2040/hardware_regs/include/hardware/regs/vreg_and_chip_reset.h" +#include "hardware/regs/vreg_and_chip_reset.h" +#include "hardware/structs/vreg_and_chip_reset.h" #endif #ifdef PICO_RP2350 -#include "src/rp2350/hardware_regs/include/hardware/regs/powman.h" +#include "hardware/regs/powman.h" +#include "hardware/structs/powman.h" #endif -#include "src/rp2040/hardware_regs/include/hardware/regs/watchdog.h" - -#ifdef PICO_RP2040 -#include "src/rp2040/hardware_structs/include/hardware/structs/vreg_and_chip_reset.h" -#endif -#ifdef PICO_RP2350 -#include "src/rp2350/hardware_structs/include/hardware/structs/powman.h" -#endif -#include "src/rp2040/hardware_structs/include/hardware/structs/watchdog.h" +#include "hardware/regs/watchdog.h" +#include "hardware/structs/watchdog.h" float common_hal_mcu_processor_get_temperature(void) { adc_init(); adc_set_temp_sensor_enabled(true); - adc_select_input(4); + adc_select_input(ADC_TEMPERATURE_CHANNEL_NUM); uint16_t value = adc_read(); adc_set_temp_sensor_enabled(false); float voltage = value * 3.3 / (1 << 12); diff --git a/ports/raspberrypi/common-hal/microcontroller/Processor.h b/ports/raspberrypi/common-hal/microcontroller/Processor.h index 31f89f58fd308..df1e1cf2333b9 100644 --- a/ports/raspberrypi/common-hal/microcontroller/Processor.h +++ b/ports/raspberrypi/common-hal/microcontroller/Processor.h @@ -6,7 +6,7 @@ #pragma once -#include "src/rp2_common/pico_unique_id/include/pico/unique_id.h" +#include "pico/unique_id.h" #define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH PICO_UNIQUE_BOARD_ID_SIZE_BYTES diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.c b/ports/raspberrypi/common-hal/microcontroller/__init__.c index 7911c21e3cc10..e287e551710b6 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.c +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.c @@ -19,16 +19,18 @@ #include "supervisor/port.h" #include "supervisor/shared/safe_mode.h" -#include "src/rp2040/hardware_structs/include/hardware/structs/sio.h" -#include "src/rp2_common/hardware_sync/include/hardware/sync.h" +#include "hardware/structs/sio.h" +#include "hardware/sync.h" #include "hardware/watchdog.h" +#include "hardware/irq.h" void common_hal_mcu_delay_us(uint32_t delay) { mp_hal_delay_us(delay); } volatile uint32_t nesting_count = 0; +#ifdef PICO_RP2040 void common_hal_mcu_disable_interrupts(void) { // We don't use save_and_disable_interrupts() from the sdk because we don't want to worry about PRIMASK. // This is what we do on the SAMD21 via CMSIS. @@ -48,6 +50,40 @@ void common_hal_mcu_enable_interrupts(void) { __dmb(); asm volatile ("cpsie i" : : : "memory"); } +#else +#include "RP2350.h" +#define PICO_ELEVATED_IRQ_PRIORITY (0x60) // between PICO_DEFAULT and PIOCO_HIGHEST_IRQ_PRIORITY +static uint32_t oldBasePri = 0; // 0 (default) masks nothing, other values mask equal-or-larger priority values +void common_hal_mcu_disable_interrupts(void) { + uint32_t my_interrupts = save_and_disable_interrupts(); + if (nesting_count == 0) { + // We must keep DMA_IRQ_1 (reserved for pico dvi) enabled at all times, + // including during flash writes. Do this by setting the priority mask (BASEPRI + // register). + // grab old base priority + oldBasePri = __get_BASEPRI(); + // and set the new one + __set_BASEPRI_MAX(PICO_ELEVATED_IRQ_PRIORITY); + __isb(); // Instruction synchronization barrier + } + nesting_count++; + restore_interrupts(my_interrupts); +} + +void common_hal_mcu_enable_interrupts(void) { + uint32_t my_interrupts = save_and_disable_interrupts(); + if (nesting_count == 0) { + reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR); + } + nesting_count--; + if (nesting_count == 0) { + // return to the old priority setting + __set_BASEPRI(oldBasePri); + __isb(); // Instruction synchronization barrier + } + restore_interrupts(my_interrupts); +} +#endif static bool next_reset_to_bootloader = false; diff --git a/ports/raspberrypi/common-hal/microcontroller/__init__.h b/ports/raspberrypi/common-hal/microcontroller/__init__.h index e9a7602bc040c..8798c857404c5 100644 --- a/ports/raspberrypi/common-hal/microcontroller/__init__.h +++ b/ports/raspberrypi/common-hal/microcontroller/__init__.h @@ -6,7 +6,7 @@ #pragma once -#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h" +#include "hardware/platform_defs.h" #include "peripherals/pins.h" const mcu_pin_obj_t *mcu_get_pin_by_number(int); diff --git a/ports/raspberrypi/common-hal/neopixel_write/__init__.c b/ports/raspberrypi/common-hal/neopixel_write/__init__.c index 4753c17e5fe6c..76db28a41e129 100644 --- a/ports/raspberrypi/common-hal/neopixel_write/__init__.c +++ b/ports/raspberrypi/common-hal/neopixel_write/__init__.c @@ -40,17 +40,17 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, // TODO: Cache the state machine after we create it once. We'll need a way to // change the pins then though. - uint32_t pins_we_use = 1 << digitalinout->pin->number; + pio_pinmask_t pins_we_use = PIO_PINMASK_FROM_PIN(digitalinout->pin->number); bool ok = rp2pio_statemachine_construct(&state_machine, neopixel_program, MP_ARRAY_SIZE(neopixel_program), 12800000, // 12.8MHz, to get appropriate sub-bit times in PIO program. NULL, 0, // init program NULL, 1, // out NULL, 1, // in - 0, 0, // in pulls + PIO_PINMASK_NONE, PIO_PINMASK_NONE, // gpio pulls NULL, 1, // set - digitalinout->pin, 1, // sideset - 0, pins_we_use, // initial pin state + digitalinout->pin, 1, false, // sideset + PIO_PINMASK_NONE, pins_we_use, // initial pin state NULL, // jump pin pins_we_use, true, false, true, 8, false, // TX, auto pull every 8 bits. shift left to output msb first @@ -60,8 +60,9 @@ void common_hal_neopixel_write(const digitalio_digitalinout_obj_t *digitalinout, false, // Not user-interruptible. false, // No sideset enable 0, -1, // wrap - PIO_ANY_OFFSET // offset - ); + PIO_ANY_OFFSET, // offset + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); if (!ok) { // Do nothing. Maybe bitbang? return; diff --git a/ports/raspberrypi/common-hal/nvm/ByteArray.c b/ports/raspberrypi/common-hal/nvm/ByteArray.c index 541f1a34bd7cf..558f38240ce4f 100644 --- a/ports/raspberrypi/common-hal/nvm/ByteArray.c +++ b/ports/raspberrypi/common-hal/nvm/ByteArray.c @@ -10,8 +10,9 @@ #include #include "py/runtime.h" -#include "src/rp2_common/hardware_flash/include/hardware/flash.h" +#include "hardware/flash.h" #include "shared-bindings/microcontroller/__init__.h" +#include "supervisor/internal_flash.h" extern uint32_t __flash_binary_start; static const uint32_t flash_binary_start = (uint32_t)&__flash_binary_start; @@ -26,17 +27,16 @@ static void write_page(uint32_t page_addr, uint32_t offset, uint32_t len, uint8_ // Write a whole page to flash, buffering it first and then erasing and rewriting it // since we can only write a whole page at a time. if (offset == 0 && len == FLASH_PAGE_SIZE) { - // disable interrupts to prevent core hang on rp2040 - common_hal_mcu_disable_interrupts(); + supervisor_flash_pre_write(); flash_range_program(RMV_OFFSET(page_addr), bytes, FLASH_PAGE_SIZE); - common_hal_mcu_enable_interrupts(); + supervisor_flash_post_write(); } else { uint8_t buffer[FLASH_PAGE_SIZE]; memcpy(buffer, (uint8_t *)page_addr, FLASH_PAGE_SIZE); memcpy(buffer + offset, bytes, len); - common_hal_mcu_disable_interrupts(); + supervisor_flash_pre_write(); flash_range_program(RMV_OFFSET(page_addr), buffer, FLASH_PAGE_SIZE); - common_hal_mcu_enable_interrupts(); + supervisor_flash_post_write(); } } @@ -57,8 +57,10 @@ static void erase_and_write_sector(uint32_t address, uint32_t len, uint8_t *byte memcpy(buffer + address, bytes, len); // disable interrupts to prevent core hang on rp2040 common_hal_mcu_disable_interrupts(); + supervisor_flash_pre_write(); flash_range_erase(RMV_OFFSET(CIRCUITPY_INTERNAL_NVM_START_ADDR), FLASH_SECTOR_SIZE); flash_range_program(RMV_OFFSET(CIRCUITPY_INTERNAL_NVM_START_ADDR), buffer, FLASH_SECTOR_SIZE); + supervisor_flash_post_write(); common_hal_mcu_enable_interrupts(); } diff --git a/ports/raspberrypi/common-hal/os/__init__.c b/ports/raspberrypi/common-hal/os/__init__.c index 28c8ed946717e..d2a8da4caefdd 100644 --- a/ports/raspberrypi/common-hal/os/__init__.c +++ b/ports/raspberrypi/common-hal/os/__init__.c @@ -18,61 +18,159 @@ #include -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "rp2040"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "rp2040"); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} +#ifdef HAS_RP2350_TRNG +#include "hardware/structs/trng.h" +#include "hardware/sync.h" +#endif // NIST Special Publication 800-90B (draft) recommends several extractors, // including the SHA hash family and states that if the amount of entropy input // is twice the number of bits output from them, that output can be considered -// essentially fully random. If every RANDOM_SAFETY_MARGIN bits from -// `rosc_hw->randombit` have at least 1 bit of entropy, then this criterion is met. +// essentially fully random. +// +// This works by seeding `random_state` with entropy from hardware sources +// (SHA-256 as the conditioning function), then using that state as a counter +// input (SHA-256 as a CSPRNG), re-seeding at least every 256 blocks (8kB). // -// This works by seeding the `random_state` with plenty of random bits (SHA256 -// as entropy harvesting function), then using that state it as a counter input -// (SHA256 as a CSPRNG), re-seeding at least every 256 blocks (8kB). +// On RP2350, entropy comes from both the dedicated TRNG peripheral and the +// ROSC. On RP2040, the ROSC is the only available source. // // In practice, `PractRand` doesn't detect any gross problems with the output // random numbers on samples of 1 to 8 megabytes, no matter the setting of -// RANDOM_SAFETY_MARGIN. (it does detect "unusual" results from time to time, +// ROSC_SAFETY_MARGIN. (it does detect "unusual" results from time to time, // as it will with any RNG) -#define RANDOM_SAFETY_MARGIN (4) + +// Number of ROSC collection rounds on RP2040. Each round feeds +// SHA256_BLOCK_SIZE bytes into the hash; we do 2*N rounds so the +// raw-to-output ratio satisfies 800-90B's 2:1 minimum. +#define ROSC_SAFETY_MARGIN (4) static BYTE random_state[SHA256_BLOCK_SIZE]; + +// Collect `count` bytes from the ROSC, one bit per read. +static void rosc_random_bytes(BYTE *buf, size_t count) { + for (size_t i = 0; i < count; i++) { + buf[i] = rosc_hw->randombit & 1; + for (int k = 0; k < 8; k++) { + buf[i] = (buf[i] << 1) ^ (rosc_hw->randombit & 1); + } + } +} + +#ifdef HAS_RP2350_TRNG + +// TRNG_DEBUG_CONTROL bypass bits: +// +// bit 1 VNC_BYPASS Von Neumann corrector +// bit 2 TRNG_CRNGT_BYPASS Continuous Random Number Generator Test +// bit 3 AUTO_CORRELATE_BYPASS Autocorrelation test +// +// We bypass Von Neumann and autocorrelation but keep CRNGT. +// +// Von Neumann (bypassed): ~4x throughput cost for bias removal. +// Redundant here because SHA-256 conditioning already handles +// biased input -- that's what the 2:1 oversampling ratio is for. +// +// Autocorrelation (bypassed): has a non-trivial false-positive rate +// at high sampling speeds and halts the TRNG until SW reset on +// failure. SHA-256 is not bothered by correlated input. ARM's own +// TZ-TRNG 90B reference configuration also bypasses it (0x0A). +// +// CRNGT (kept): compares consecutive 192-bit EHR outputs. Flags if +// identical -- false-positive rate 2^-192, throughput cost zero. +// This is our early warning for a stuck oscillator or a successful +// injection lock to a fixed state. +#define TRNG_BYPASS_BITS \ + (TRNG_TRNG_DEBUG_CONTROL_VNC_BYPASS_BITS | \ + TRNG_TRNG_DEBUG_CONTROL_AUTO_CORRELATE_BYPASS_BITS) + +// Collect 192 raw bits (6 x 32-bit words) from the TRNG. +// Returns false on CRNGT failure (consecutive identical EHR outputs). +// +// Holds PICO_SPINLOCK_ID_RAND (the SDK's lock for this peripheral) +// with interrupts disabled for the duration of the collection, which +// takes ~192 ROSC cycles (~24us at 8MHz). +static bool trng_collect_192(uint32_t out[6]) { + spin_lock_t *lock = spin_lock_instance(PICO_SPINLOCK_ID_RAND); + uint32_t save = spin_lock_blocking(lock); + + trng_hw->trng_debug_control = TRNG_BYPASS_BITS; + // One rng_clk cycle between samples. The SDK uses 0 here, but it + // also sets debug_control = -1u (full bypass). The behavior of + // sample_cnt1 = 0 with health tests still active is undocumented, + // so we use 1 to be safe. + trng_hw->sample_cnt1 = 1; + trng_hw->rnd_source_enable = 1; + trng_hw->rng_icr = 0xFFFFFFFF; + + while (trng_hw->trng_busy) { + } + + if (trng_hw->rng_isr & TRNG_RNG_ISR_CRNGT_ERR_BITS) { + // Drain ehr_data so the hardware starts a fresh collection. + // (Reading the last word clears the valid flag.) + for (int i = 0; i < 6; i++) { + (void)trng_hw->ehr_data[i]; + } + trng_hw->rng_icr = TRNG_RNG_ISR_CRNGT_ERR_BITS; + spin_unlock(lock, save); + return false; + } + + for (int i = 0; i < 6; i++) { + out[i] = trng_hw->ehr_data[i]; + } + + // Switch the inverter chain length for the next collection, using + // bits from the sample we just read. Only bits [1:0] matter -- they + // select one of four chain lengths, changing the ROSC frequency. + // This is borrowed from pico_rand's injection-locking countermeasure. + // (The SDK uses its PRNG state here instead of raw output; either + // works since the real defense is SHA-256 conditioning, not this.) + trng_hw->trng_config = out[0]; + + spin_unlock(lock, save); + return true; +} + +#endif // HAS_RP2350_TRNG + static void seed_random_bits(BYTE out[SHA256_BLOCK_SIZE]) { CRYAL_SHA256_CTX context; sha256_init(&context); - for (int i = 0; i < 2 * RANDOM_SAFETY_MARGIN; i++) { - for (int j = 0; j < SHA256_BLOCK_SIZE; j++) { - out[j] = rosc_hw->randombit & 1; - for (int k = 0; k < 8; k++) { - out[j] = (out[j] << 1) ^ (rosc_hw->randombit & 1); + + #ifdef HAS_RP2350_TRNG + // 384 bits from TRNG + 384 bits from ROSC = 768 bits into the hash, + // giving a 3:1 ratio over the 256-bit output (800-90B wants >= 2:1). + // Two independent sources so a failure in one doesn't zero the input. + + // TRNG: 2 x 192 bits. + for (int i = 0; i < 2; i++) { + uint32_t trng_buf[6] = {0}; + for (int attempt = 0; attempt < 3; attempt++) { + if (trng_collect_192(trng_buf)) { + break; } + // CRNGT failure. If all 3 retries fail, trng_buf stays zeroed + // and we rely entirely on the ROSC contribution below. } + sha256_update(&context, (const BYTE *)trng_buf, sizeof(trng_buf)); + } + + // ROSC: 2 x 24 bytes = 384 bits. + for (int i = 0; i < 2; i++) { + BYTE rosc_buf[24]; + rosc_random_bytes(rosc_buf, sizeof(rosc_buf)); + sha256_update(&context, rosc_buf, sizeof(rosc_buf)); + } + #else + // RP2040: ROSC is the only entropy source. + for (int i = 0; i < 2 * ROSC_SAFETY_MARGIN; i++) { + rosc_random_bytes(out, SHA256_BLOCK_SIZE); sha256_update(&context, out, SHA256_BLOCK_SIZE); } + #endif + sha256_final(&context, out); } @@ -87,10 +185,11 @@ static void get_random_bits(BYTE out[SHA256_BLOCK_SIZE]) { } bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { -#define ROSC_POWER_SAVE (1) // assume ROSC is not necessarily active all the time + #define ROSC_POWER_SAVE (1) // assume ROSC is not necessarily active all the time #if ROSC_POWER_SAVE uint32_t old_rosc_ctrl = rosc_hw->ctrl; - rosc_hw->ctrl = (old_rosc_ctrl & ~ROSC_CTRL_ENABLE_BITS) | (ROSC_CTRL_ENABLE_VALUE_ENABLE << 12); + rosc_hw->ctrl = (old_rosc_ctrl & ~ROSC_CTRL_ENABLE_BITS) + | (ROSC_CTRL_ENABLE_VALUE_ENABLE << ROSC_CTRL_ENABLE_LSB); #endif while (length) { size_t n = MIN(length, SHA256_BLOCK_SIZE); diff --git a/ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c b/ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c index 7efa2740a0cfb..517d960b7650c 100644 --- a/ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c +++ b/ports/raspberrypi/common-hal/paralleldisplaybus/ParallelBus.c @@ -79,20 +79,22 @@ void common_hal_paralleldisplaybus_parallelbus_construct(paralleldisplaybus_para frequency * 2, // frequency multiplied by 2 as 2 PIO instructions NULL, 0, // init NULL, 0, // may_exec - data0, 8, 0, 255, // first out pin, # out pins - NULL, 0, 0, 0, // first in pin, # in pins - NULL, 0, 0, 0, // first set pin - write, 1, 0, 1, // first sideset pin + data0, 8, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(255), // first out pin, # out pins + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first in pin, # in pins + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first set pin + write, 1, false, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(1), // first sideset pin false, // No sideset enable NULL, PULL_NONE, // jump pin - 0, // wait gpio pins + PIO_PINMASK_NONE, // wait gpio pins true, // exclusive pin usage true, 8, true, // TX, auto pull every 8 bits. shift left to output msb first false, // wait for TX stall false, 32, true, // RX setting we don't use false, // Not user-interruptible. 0, -1, // wrap settings - PIO_ANY_OFFSET); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); common_hal_rp2pio_statemachine_never_reset(&self->state_machine); } diff --git a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c index b244fb8bbd015..788f10d6df6ac 100644 --- a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c +++ b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2040.c @@ -13,20 +13,18 @@ #include "common-hal/rp2pio/StateMachine.h" #include "supervisor/port.h" -#include "src/common/pico_stdlib_headers/include/pico/stdlib.h" -#include "src/rp2040/hardware_structs/include/hardware/structs/mpu.h" -#include "src/rp2_common/cmsis/stub/CMSIS/Device/RP2040/Include/RP2040.h" -#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" -#include "src/rp2_common/hardware_vreg/include/hardware/vreg.h" -#include "src/rp2_common/pico_multicore/include/pico/multicore.h" +#include "pico/stdlib.h" +#include "hardware/structs/mpu.h" +#include "RP2040.h" // (cmsis) +#include "hardware/clocks.h" +#include "hardware/pwm.h" +#include "hardware/vreg.h" +#include "pico/multicore.h" #include "lib/PicoDVI/software/libdvi/tmds_encode.h" picodvi_framebuffer_obj_t *active_picodvi = NULL; -static PIO pio_instances[2] = {pio0, pio1}; - static void __not_in_flash_func(core1_main)(void) { // The MPU is reset before this starts. @@ -143,7 +141,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, // If the width is > 400, then it must not be color frame buffer and vice // versa. - if ((width > 400) == color_framebuffer || color_depth == 4) { + if ((width > 400) == color_framebuffer || color_depth == 4 || color_depth == 32) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_color_depth); } @@ -184,7 +182,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, size_t pio_index = NUM_PIOS; int free_state_machines[4]; // We may find all four free. We only use the first three. for (size_t i = 0; i < NUM_PIOS; i++) { - PIO pio = pio_instances[i]; + PIO pio = pio_get_instance(i); uint8_t free_count = 0; for (size_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) { if (!pio_sm_is_claimed(pio, sm)) { @@ -244,7 +242,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, } for (size_t i = 0; i < 3; i++) { - rp2pio_statemachine_never_reset(pio_instances[pio_index], free_state_machines[i]); + rp2pio_statemachine_never_reset(pio_get_instance(pio_index), free_state_machines[i]); } // For the output. @@ -253,7 +251,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, self->color_depth = color_depth; self->dvi.timing = timing; - self->dvi.ser_cfg.pio = pio_instances[pio_index]; + self->dvi.ser_cfg.pio = pio_get_instance(pio_index); self->dvi.ser_cfg.sm_tmds[0] = free_state_machines[0]; self->dvi.ser_cfg.sm_tmds[1] = free_state_machines[1]; self->dvi.ser_cfg.sm_tmds[2] = free_state_machines[2]; @@ -387,6 +385,10 @@ int common_hal_picodvi_framebuffer_get_color_depth(picodvi_framebuffer_obj_t *se return self->color_depth; } +int common_hal_picodvi_framebuffer_get_native_frames_per_second(picodvi_framebuffer_obj_t *self) { + return 60; +} + bool common_hal_picodvi_framebuffer_get_grayscale(picodvi_framebuffer_obj_t *self) { return self->color_depth < 8; } diff --git a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c index 3e3804fbc5148..2dc19558314cb 100644 --- a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c +++ b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.c @@ -31,14 +31,14 @@ #include "shared-bindings/time/__init__.h" #include "supervisor/port.h" -#include "src/common/pico_stdlib_headers/include/pico/stdlib.h" +#include "pico/stdlib.h" // This is from: https://github.com/raspberrypi/pico-examples-rp2350/blob/a1/hstx/dvi_out_hstx_encoder/dvi_out_hstx_encoder.c -#include "sdk/src/rp2_common/hardware_dma/include/hardware/dma.h" -#include "sdk/src/rp2350/hardware_structs/include/hardware/structs/bus_ctrl.h" -#include "sdk/src/rp2350/hardware_structs/include/hardware/structs/hstx_ctrl.h" -#include "sdk/src/rp2350/hardware_structs/include/hardware/structs/hstx_fifo.h" +#include "hardware/dma.h" +#include "hardware/structs/bus_ctrl.h" +#include "hardware/structs/hstx_ctrl.h" +#include "hardware/structs/hstx_fifo.h" // ---------------------------------------------------------------------------- // DVI constants @@ -53,25 +53,37 @@ #define SYNC_V1_H0 (TMDS_CTRL_10 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20)) #define SYNC_V1_H1 (TMDS_CTRL_11 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20)) -#define MODE_H_SYNC_POLARITY 0 -#define MODE_H_FRONT_PORCH 16 -#define MODE_H_SYNC_WIDTH 96 -#define MODE_H_BACK_PORCH 48 -#define MODE_H_ACTIVE_PIXELS 640 - -#define MODE_V_SYNC_POLARITY 0 -#define MODE_V_FRONT_PORCH 10 -#define MODE_V_SYNC_WIDTH 2 -#define MODE_V_BACK_PORCH 33 -#define MODE_V_ACTIVE_LINES 480 - -#define MODE_H_TOTAL_PIXELS ( \ - MODE_H_FRONT_PORCH + MODE_H_SYNC_WIDTH + \ - MODE_H_BACK_PORCH + MODE_H_ACTIVE_PIXELS \ +#define MODE_720_H_SYNC_POLARITY 0 +#define MODE_720_H_FRONT_PORCH 8 +#define MODE_720_H_SYNC_WIDTH 32 +#define MODE_720_H_BACK_PORCH 40 +#define MODE_720_H_ACTIVE_PIXELS 720 + +#define MODE_720_V_SYNC_POLARITY 0 +#define MODE_720_V_FRONT_PORCH 3 +#define MODE_720_V_SYNC_WIDTH 4 +#define MODE_720_V_BACK_PORCH 218 +#define MODE_720_V_ACTIVE_LINES 400 + +#define MODE_640_H_SYNC_POLARITY 0 +#define MODE_640_H_FRONT_PORCH 16 +#define MODE_640_H_SYNC_WIDTH 96 +#define MODE_640_H_BACK_PORCH 48 +#define MODE_640_H_ACTIVE_PIXELS 640 + +#define MODE_640_V_SYNC_POLARITY 0 +#define MODE_640_V_FRONT_PORCH 10 +#define MODE_640_V_SYNC_WIDTH 2 +#define MODE_640_V_BACK_PORCH 133 +#define MODE_640_V_ACTIVE_LINES 480 + +#define MODE_720_V_TOTAL_LINES ( \ + MODE_720_V_FRONT_PORCH + MODE_720_V_SYNC_WIDTH + \ + MODE_720_V_BACK_PORCH + MODE_720_V_ACTIVE_LINES \ ) -#define MODE_V_TOTAL_LINES ( \ - MODE_V_FRONT_PORCH + MODE_V_SYNC_WIDTH + \ - MODE_V_BACK_PORCH + MODE_V_ACTIVE_LINES \ +#define MODE_640_V_TOTAL_LINES ( \ + MODE_640_V_FRONT_PORCH + MODE_640_V_SYNC_WIDTH + \ + MODE_640_V_BACK_PORCH + MODE_640_V_ACTIVE_LINES \ ) #define HSTX_CMD_RAW (0x0u << 12) @@ -83,34 +95,67 @@ // ---------------------------------------------------------------------------- // HSTX command lists -static uint32_t vblank_line_vsync_off[] = { - HSTX_CMD_RAW_REPEAT | MODE_H_FRONT_PORCH, +#define VSYNC_LEN 6 +#define VACTIVE_LEN 9 + +static uint32_t vblank_line640_vsync_off[VSYNC_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_640_H_FRONT_PORCH, + SYNC_V1_H1, + HSTX_CMD_RAW_REPEAT | MODE_640_H_SYNC_WIDTH, + SYNC_V1_H0, + HSTX_CMD_RAW_REPEAT | (MODE_640_H_BACK_PORCH + MODE_640_H_ACTIVE_PIXELS), + SYNC_V1_H1 +}; + +static uint32_t vblank_line640_vsync_on[VSYNC_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_640_H_FRONT_PORCH, + SYNC_V0_H1, + HSTX_CMD_RAW_REPEAT | MODE_640_H_SYNC_WIDTH, + SYNC_V0_H0, + HSTX_CMD_RAW_REPEAT | (MODE_640_H_BACK_PORCH + MODE_640_H_ACTIVE_PIXELS), + SYNC_V0_H1 +}; + +static uint32_t vactive_line640[VACTIVE_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_640_H_FRONT_PORCH, + SYNC_V1_H1, + HSTX_CMD_NOP, + HSTX_CMD_RAW_REPEAT | MODE_640_H_SYNC_WIDTH, + SYNC_V1_H0, + HSTX_CMD_NOP, + HSTX_CMD_RAW_REPEAT | MODE_640_H_BACK_PORCH, + SYNC_V1_H1, + HSTX_CMD_TMDS | MODE_640_H_ACTIVE_PIXELS +}; + +static uint32_t vblank_line720_vsync_off[VSYNC_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_720_H_FRONT_PORCH, SYNC_V1_H1, - HSTX_CMD_RAW_REPEAT | MODE_H_SYNC_WIDTH, + HSTX_CMD_RAW_REPEAT | MODE_720_H_SYNC_WIDTH, SYNC_V1_H0, - HSTX_CMD_RAW_REPEAT | (MODE_H_BACK_PORCH + MODE_H_ACTIVE_PIXELS), + HSTX_CMD_RAW_REPEAT | (MODE_720_H_BACK_PORCH + MODE_720_H_ACTIVE_PIXELS), SYNC_V1_H1 }; -static uint32_t vblank_line_vsync_on[] = { - HSTX_CMD_RAW_REPEAT | MODE_H_FRONT_PORCH, +static uint32_t vblank_line720_vsync_on[VSYNC_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_720_H_FRONT_PORCH, SYNC_V0_H1, - HSTX_CMD_RAW_REPEAT | MODE_H_SYNC_WIDTH, + HSTX_CMD_RAW_REPEAT | MODE_720_H_SYNC_WIDTH, SYNC_V0_H0, - HSTX_CMD_RAW_REPEAT | (MODE_H_BACK_PORCH + MODE_H_ACTIVE_PIXELS), + HSTX_CMD_RAW_REPEAT | (MODE_720_H_BACK_PORCH + MODE_720_H_ACTIVE_PIXELS), SYNC_V0_H1 }; -static uint32_t vactive_line[] = { - HSTX_CMD_RAW_REPEAT | MODE_H_FRONT_PORCH, +static uint32_t vactive_line720[VACTIVE_LEN] = { + HSTX_CMD_RAW_REPEAT | MODE_720_H_FRONT_PORCH, SYNC_V1_H1, HSTX_CMD_NOP, - HSTX_CMD_RAW_REPEAT | MODE_H_SYNC_WIDTH, + HSTX_CMD_RAW_REPEAT | MODE_720_H_SYNC_WIDTH, SYNC_V1_H0, HSTX_CMD_NOP, - HSTX_CMD_RAW_REPEAT | MODE_H_BACK_PORCH, + HSTX_CMD_RAW_REPEAT | MODE_720_H_BACK_PORCH, SYNC_V1_H1, - HSTX_CMD_TMDS | MODE_H_ACTIVE_PIXELS + HSTX_CMD_TMDS | MODE_720_H_ACTIVE_PIXELS }; picodvi_framebuffer_obj_t *active_picodvi = NULL; @@ -120,15 +165,49 @@ static void __not_in_flash_func(dma_irq_handler)(void) { return; } uint ch_num = active_picodvi->dma_pixel_channel; - dma_channel_hw_t *ch = &dma_hw->ch[ch_num]; dma_hw->intr = 1u << ch_num; // Set the read_addr back to the start and trigger the first transfer (which // will trigger the pixel channel). - ch = &dma_hw->ch[active_picodvi->dma_command_channel]; + dma_channel_hw_t *ch = &dma_hw->ch[active_picodvi->dma_command_channel]; ch->al3_read_addr_trig = (uintptr_t)active_picodvi->dma_commands; } +bool common_hal_picodvi_framebuffer_preflight( + mp_uint_t width, mp_uint_t height, + mp_uint_t color_depth) { + + // These modes don't duplicate pixels so we can do sub-byte colors. They + // take too much ram for more than 8bit color though. + bool full_resolution = color_depth == 1 || color_depth == 2 || color_depth == 4 || color_depth == 8; + // These modes rely on the memory transfer to duplicate values across bytes. + bool doubled = color_depth == 8 || color_depth == 16 || color_depth == 32; + + // for each supported resolution, check the color depth is supported + if (width == 640 && height == 480) { + return full_resolution; + } + if (width == 320 && height == 240) { + return doubled; + } + if (width == 160 && height == 120) { + return doubled; + } + + if (width == 720 && height == 400) { + return full_resolution; + } + + if (width == 360 && height == 200) { + return doubled; + } + + if (width == 180 && height == 100) { + return doubled; + } + return false; +} + void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, mp_uint_t width, mp_uint_t height, const mcu_pin_obj_t *clk_dp, const mcu_pin_obj_t *clk_dn, @@ -140,11 +219,19 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, mp_raise_msg_varg(&mp_type_RuntimeError, MP_ERROR_TEXT("%q in use"), MP_QSTR_picodvi); } - if (!(width == 640 && height == 480) && !(width == 320 && height == 240 && color_depth == 16)) { + if (!common_hal_picodvi_framebuffer_preflight(width, height, color_depth)) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q and %q"), MP_QSTR_width, MP_QSTR_height); } - bool pixel_doubled = width == 320 && height == 240; + self->dma_command_channel = -1; + self->dma_pixel_channel = -1; + + if (width % 160 == 0) { + self->output_width = 640; + } else { + self->output_width = 720; + } + size_t output_scaling = self->output_width / width; size_t all_allocated = 0; int8_t pins[8] = { @@ -173,68 +260,86 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, self->width = width; self->height = height; - self->pitch = (self->width * color_depth) / 8; self->color_depth = color_depth; - // Align each row to words. - if (self->pitch % sizeof(uint32_t) != 0) { - self->pitch += sizeof(uint32_t) - (self->pitch % sizeof(uint32_t)); - } - self->pitch /= sizeof(uint32_t); + // Pitch is number of 32-bit words per line. We round up pitch_bytes to the nearest word + // so that each scanline begins on a natural 32-bit word boundary. + size_t pitch_bytes = (self->width * color_depth) / 8; + self->pitch = (pitch_bytes + sizeof(uint32_t) - 1) / sizeof(uint32_t); size_t framebuffer_size = self->pitch * self->height; // We check that allocations aren't in PSRAM because we haven't added XIP // streaming support. self->framebuffer = (uint32_t *)port_malloc(framebuffer_size * sizeof(uint32_t), true); if (self->framebuffer == NULL || ((size_t)self->framebuffer & 0xf0000000) == 0x10000000) { + common_hal_picodvi_framebuffer_deinit(self); m_malloc_fail(framebuffer_size * sizeof(uint32_t)); return; } + memset(self->framebuffer, 0, framebuffer_size * sizeof(uint32_t)); // We compute all DMA transfers needed for a single frame. This ensure we don't have any super // quick interrupts that we need to respond to. Each transfer takes two words, trans_count and // read_addr. Active pixel lines need two transfers due to different read addresses. When pixel // doubling, then we must also set transfer size. size_t dma_command_size = 2; - if (pixel_doubled) { + if (output_scaling > 1) { dma_command_size = 4; } - self->dma_commands_len = (MODE_V_FRONT_PORCH + MODE_V_SYNC_WIDTH + MODE_V_BACK_PORCH + 2 * MODE_V_ACTIVE_LINES + 1) * dma_command_size; + + if (self->output_width == 640) { + self->dma_commands_len = (MODE_640_V_FRONT_PORCH + MODE_640_V_SYNC_WIDTH + MODE_640_V_BACK_PORCH + 2 * MODE_640_V_ACTIVE_LINES + 1) * dma_command_size; + } else { + self->dma_commands_len = (MODE_720_V_FRONT_PORCH + MODE_720_V_SYNC_WIDTH + MODE_720_V_BACK_PORCH + 2 * MODE_720_V_ACTIVE_LINES + 1) * dma_command_size; + } self->dma_commands = (uint32_t *)port_malloc(self->dma_commands_len * sizeof(uint32_t), true); - if (self->dma_commands == NULL || ((size_t)self->framebuffer & 0xf0000000) == 0x10000000) { - port_free(self->framebuffer); + if (self->dma_commands == NULL || ((size_t)self->dma_commands & 0xf0000000) == 0x10000000) { + common_hal_picodvi_framebuffer_deinit(self); m_malloc_fail(self->dma_commands_len * sizeof(uint32_t)); return; } - int dma_pixel_channel_maybe = dma_claim_unused_channel(false); - if (dma_pixel_channel_maybe < 0) { + // The command channel and the pixel channel form a pipeline that feeds combined HSTX + // commands and pixel data to the HSTX FIFO. The command channel reads a pre-computed + // list of control/status words from the dma_commands buffer and writes them to the + // pixel channel's control/status registers. Under control of the command channel, the + // pixel channel smears/swizzles pixel data from the framebuffer and combines + // it with HSTX commands, forwarding the combined stream to the HSTX FIFO. + + self->dma_pixel_channel = dma_claim_unused_channel(false); + self->dma_command_channel = dma_claim_unused_channel(false); + if (self->dma_pixel_channel < 0 || self->dma_command_channel < 0) { + common_hal_picodvi_framebuffer_deinit(self); mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use")); return; } - int dma_command_channel_maybe = dma_claim_unused_channel(false); - if (dma_command_channel_maybe < 0) { - dma_channel_unclaim((uint)dma_pixel_channel_maybe); - mp_raise_RuntimeError(MP_ERROR_TEXT("Internal resource(s) in use")); - return; + size_t command_word = 0; + size_t frontporch_start; + if (self->output_width == 640) { + frontporch_start = MODE_640_V_TOTAL_LINES - MODE_640_V_FRONT_PORCH; + } else { + frontporch_start = MODE_720_V_TOTAL_LINES - MODE_720_V_FRONT_PORCH; } - self->dma_pixel_channel = dma_pixel_channel_maybe; - self->dma_command_channel = dma_command_channel_maybe; - - size_t words_per_line; - if (self->color_depth > 8) { - words_per_line = (self->width * (self->color_depth / 8)) / sizeof(uint32_t); + size_t frontporch_end = frontporch_start; + if (self->output_width == 640) { + frontporch_end += MODE_640_V_FRONT_PORCH; } else { - words_per_line = (self->width / (8 / self->color_depth)) / sizeof(uint32_t); + frontporch_end += MODE_720_V_FRONT_PORCH; } - - size_t command_word = 0; - size_t frontporch_start = MODE_V_TOTAL_LINES - MODE_V_FRONT_PORCH; - size_t frontporch_end = frontporch_start + MODE_V_FRONT_PORCH; size_t vsync_start = 0; - size_t vsync_end = vsync_start + MODE_V_SYNC_WIDTH; + size_t vsync_end = vsync_start; + if (self->output_width == 640) { + vsync_end += MODE_640_V_SYNC_WIDTH; + } else { + vsync_end += MODE_720_V_SYNC_WIDTH; + } size_t backporch_start = vsync_end; - size_t backporch_end = backporch_start + MODE_V_BACK_PORCH; + size_t backporch_end = backporch_start; + if (self->output_width == 640) { + backporch_end += MODE_640_V_BACK_PORCH; + } else { + backporch_end += MODE_720_V_BACK_PORCH; + } size_t active_start = backporch_end; uint32_t dma_ctrl = self->dma_command_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB | @@ -243,11 +348,16 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, DMA_CH0_CTRL_TRIG_INCR_READ_BITS | DMA_CH0_CTRL_TRIG_EN_BITS; uint32_t dma_pixel_ctrl; - // We do 16 bit transfers when pixel doubling and the memory bus will - // duplicate the 16 bits to produce 32 bits for the HSTX. HSTX config is the - // same. - if (pixel_doubled) { - dma_pixel_ctrl = dma_ctrl | DMA_SIZE_16 << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB; + if (output_scaling > 1) { + // We do color_depth size transfers when pixel doubling. The memory bus will + // duplicate the bytes read to produce 32 bits for the HSTX. + if (color_depth == 32) { + dma_pixel_ctrl = dma_ctrl | DMA_SIZE_32 << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB; + } else if (color_depth == 16) { + dma_pixel_ctrl = dma_ctrl | DMA_SIZE_16 << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB; + } else { + dma_pixel_ctrl = dma_ctrl | DMA_SIZE_8 << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB; + } } else { dma_pixel_ctrl = dma_ctrl | DMA_SIZE_32 << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB; } @@ -260,34 +370,48 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, // Write ctrl and write_addr once when not pixel doubling because they don't // change. (write_addr doesn't change when pixel doubling either but we need // to rewrite it because it is after the ctrl register.) - if (!pixel_doubled) { + if (output_scaling == 1) { dma_channel_hw_addr(self->dma_pixel_channel)->al1_ctrl = dma_ctrl; dma_channel_hw_addr(self->dma_pixel_channel)->al1_write_addr = dma_write_addr; } - for (size_t v_scanline = 0; v_scanline < MODE_V_TOTAL_LINES; v_scanline++) { - if (pixel_doubled) { + + uint32_t *vblank_line_vsync_on = self->output_width == 640 ? vblank_line640_vsync_on : vblank_line720_vsync_on; + uint32_t *vblank_line_vsync_off = self->output_width == 640 ? vblank_line640_vsync_off : vblank_line720_vsync_off; + uint32_t *vactive_line = self->output_width == 640 ? vactive_line640 : vactive_line720; + + size_t mode_v_total_lines; + if (self->output_width == 640) { + mode_v_total_lines = MODE_640_V_TOTAL_LINES; + } else { + mode_v_total_lines = MODE_720_V_TOTAL_LINES; + } + + for (size_t v_scanline = 0; v_scanline < mode_v_total_lines; v_scanline++) { + if (output_scaling > 1) { self->dma_commands[command_word++] = dma_ctrl; self->dma_commands[command_word++] = dma_write_addr; } if (vsync_start <= v_scanline && v_scanline < vsync_end) { - self->dma_commands[command_word++] = count_of(vblank_line_vsync_on); + self->dma_commands[command_word++] = VSYNC_LEN; self->dma_commands[command_word++] = (uintptr_t)vblank_line_vsync_on; } else if (backporch_start <= v_scanline && v_scanline < backporch_end) { - self->dma_commands[command_word++] = count_of(vblank_line_vsync_off); + self->dma_commands[command_word++] = VSYNC_LEN; self->dma_commands[command_word++] = (uintptr_t)vblank_line_vsync_off; } else if (frontporch_start <= v_scanline && v_scanline < frontporch_end) { - self->dma_commands[command_word++] = count_of(vblank_line_vsync_off); + self->dma_commands[command_word++] = VSYNC_LEN; self->dma_commands[command_word++] = (uintptr_t)vblank_line_vsync_off; } else { - self->dma_commands[command_word++] = count_of(vactive_line); + self->dma_commands[command_word++] = VACTIVE_LEN; self->dma_commands[command_word++] = (uintptr_t)vactive_line; size_t row = v_scanline - active_start; - size_t transfer_count = words_per_line; - if (pixel_doubled) { + size_t transfer_count = self->pitch; + if (output_scaling > 1) { self->dma_commands[command_word++] = dma_pixel_ctrl; self->dma_commands[command_word++] = dma_write_addr; - row /= 2; - transfer_count *= 2; + row /= output_scaling; + // When pixel scaling, we do one transfer per pixel and it gets + // mirrored into the rest of the word. + transfer_count = self->width; } self->dma_commands[command_word++] = transfer_count; uint32_t *row_start = &self->framebuffer[row * self->pitch]; @@ -295,7 +419,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, } } // Last command is NULL which will trigger an IRQ. - if (pixel_doubled) { + if (output_scaling > 1) { self->dma_commands[command_word++] = DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS | DMA_CH0_CTRL_TRIG_EN_BITS; self->dma_commands[command_word++] = 0; @@ -303,7 +427,16 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, self->dma_commands[command_word++] = 0; self->dma_commands[command_word++] = 0; - if (color_depth == 16) { + if (color_depth == 32) { + // Configure HSTX's TMDS encoder for RGB888 + hstx_ctrl_hw->expand_tmds = + 7 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB | + 16 << HSTX_CTRL_EXPAND_TMDS_L2_ROT_LSB | + 7 << HSTX_CTRL_EXPAND_TMDS_L1_NBITS_LSB | + 8 << HSTX_CTRL_EXPAND_TMDS_L1_ROT_LSB | + 7 << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB | + 0 << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB; + } else if (color_depth == 16) { // Configure HSTX's TMDS encoder for RGB565 hstx_ctrl_hw->expand_tmds = 4 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB | @@ -341,11 +474,25 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, (color_depth - 1) << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB | rot << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB; } + size_t pixels_per_word; + if (output_scaling == 1) { + pixels_per_word = 32 / color_depth; + } else { + pixels_per_word = 1; + } + + size_t shifts_before_empty = (pixels_per_word % 32); + if (output_scaling > 1) { + shifts_before_empty *= output_scaling; + } + + size_t shift_amount = color_depth % 32; + // Pixels come in 32 bits at a time. color_depth dictates the number // of pixels per word. Control symbols (RAW) are an entire 32-bit word. hstx_ctrl_hw->expand_shift = - ((32 / color_depth) % 32) << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB | - color_depth << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB | + shifts_before_empty << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB | + shift_amount << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB | 1 << HSTX_CTRL_EXPAND_SHIFT_RAW_N_SHIFTS_LSB | 0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB; @@ -398,7 +545,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, // This wraps the transfer back to the start of the write address. size_t wrap = 3; // 8 bytes because we write two DMA registers. volatile uint32_t *write_addr = &dma_hw->ch[self->dma_pixel_channel].al3_transfer_count; - if (pixel_doubled) { + if (output_scaling > 1) { wrap = 4; // 16 bytes because we write all four DMA registers. write_addr = &dma_hw->ch[self->dma_pixel_channel].al3_ctrl; } @@ -418,6 +565,7 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, dma_hw->inte1 = (1u << self->dma_pixel_channel); irq_set_exclusive_handler(DMA_IRQ_1, dma_irq_handler); irq_set_enabled(DMA_IRQ_1, true); + irq_set_priority(DMA_IRQ_1, PICO_HIGHEST_IRQ_PRIORITY); bus_ctrl_hw->priority = BUSCTRL_BUS_PRIORITY_DMA_W_BITS | BUSCTRL_BUS_PRIORITY_DMA_R_BITS; @@ -430,7 +578,10 @@ void common_hal_picodvi_framebuffer_construct(picodvi_framebuffer_obj_t *self, dma_irq_handler(); } -STATIC void _turn_off_dma(uint8_t channel) { +static void _turn_off_dma(int channel) { + if (channel < 0) { + return; + } dma_channel_config c = dma_channel_get_default_config(channel); channel_config_set_enable(&c, false); dma_channel_set_config(channel, &c, false /* trigger */); @@ -453,6 +604,8 @@ void common_hal_picodvi_framebuffer_deinit(picodvi_framebuffer_obj_t *self) { _turn_off_dma(self->dma_pixel_channel); _turn_off_dma(self->dma_command_channel); + self->dma_pixel_channel = -1; + self->dma_command_channel = -1; active_picodvi = NULL; @@ -484,6 +637,10 @@ int common_hal_picodvi_framebuffer_get_color_depth(picodvi_framebuffer_obj_t *se return self->color_depth; } +int common_hal_picodvi_framebuffer_get_native_frames_per_second(picodvi_framebuffer_obj_t *self) { + return self->output_width == 640 ? 60 : 70; +} + bool common_hal_picodvi_framebuffer_get_grayscale(picodvi_framebuffer_obj_t *self) { return self->color_depth < 4; } @@ -491,7 +648,13 @@ bool common_hal_picodvi_framebuffer_get_grayscale(picodvi_framebuffer_obj_t *sel mp_int_t common_hal_picodvi_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { picodvi_framebuffer_obj_t *self = (picodvi_framebuffer_obj_t *)self_in; bufinfo->buf = self->framebuffer; - bufinfo->typecode = self->color_depth > 8 ? 'H' : 'B'; + if (self->color_depth == 32) { + bufinfo->typecode = 'I'; + } else if (self->color_depth == 16) { + bufinfo->typecode = 'H'; + } else { + bufinfo->typecode = 'B'; + } bufinfo->len = self->framebuffer_len * sizeof(uint32_t); return 0; } diff --git a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.h b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.h index abb75dc27825e..fa08bc77d93c3 100644 --- a/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.h +++ b/ports/raspberrypi/common-hal/picodvi/Framebuffer_RP2350.h @@ -36,8 +36,9 @@ typedef struct { size_t dma_commands_len; // in words mp_uint_t width; mp_uint_t height; + mp_uint_t output_width; uint16_t pitch; // Number of words between rows. (May be more than a width's worth.) uint8_t color_depth; - uint8_t dma_pixel_channel; - uint8_t dma_command_channel; + int dma_pixel_channel; + int dma_command_channel; } picodvi_framebuffer_obj_t; diff --git a/ports/raspberrypi/common-hal/picodvi/__init__.c b/ports/raspberrypi/common-hal/picodvi/__init__.c new file mode 100644 index 0000000000000..c2d4b297b39ba --- /dev/null +++ b/ports/raspberrypi/common-hal/picodvi/__init__.c @@ -0,0 +1,169 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "common-hal/picodvi/__init__.h" +#include "common-hal/picodvi/Framebuffer.h" +#include "bindings/picodvi/Framebuffer.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/board/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/settings.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "supervisor/port_heap.h" + +#if defined(DEFAULT_DVI_BUS_CLK_DP) +static bool picodvi_autoconstruct_enabled(mp_int_t *default_width, mp_int_t *default_height) { + char buf[sizeof("detect")]; + buf[0] = 0; + + // (any failure leaves the content of buf untouched: an empty nul-terminated string + (void)settings_get_str("CIRCUITPY_PICODVI_ENABLE", buf, sizeof(buf)); + + if (!strcasecmp(buf, "never")) { + return false; + } + if (!strcasecmp(buf, "always")) { + return true; + } + + // It's "detect" or else an invalid value which is treated the same as "detect". + + // check if address 0x50 is live on the I2C bus + busio_i2c_obj_t *i2c = common_hal_board_create_i2c(0); + if (!i2c) { + return false; + } + if (!common_hal_busio_i2c_try_lock(i2c)) { + return false; + } + bool probed = common_hal_busio_i2c_probe(i2c, 0x50); + if (probed) { + uint8_t edid[128]; + uint8_t out[1] = {0}; + common_hal_busio_i2c_write_read(i2c, 0x50, out, 1, edid, sizeof(edid)); + bool edid_ok = true; + if (edid[0] != 0x00 || edid[1] != 0xFF || edid[2] != 0xFF || edid[3] != 0xFF || edid[4] != 0xFF || edid[5] != 0xFF || edid[6] != 0xFF || edid[7] != 0x00) { + edid_ok = false; + } + uint8_t checksum = 0; + for (size_t i = 0; i < sizeof(edid); i++) { + checksum += edid[i]; + } + if (checksum != 0) { + edid_ok = false; + } + + if (edid_ok) { + uint8_t established_timings = edid[35]; + if ((established_timings & 0xa0) == 0) { + // Check that 720x400@70Hz or 640x480@60Hz is supported. If not + // and we read EDID ok, then don't autostart. + probed = false; + } else { + size_t offset = 54; + uint16_t preferred_pixel_clock = edid[offset] | (edid[offset + 1] << 8); + if (preferred_pixel_clock != 0) { + size_t preferred_width = ((edid[offset + 4] & 0xf0) << 4) | edid[offset + 2]; + size_t preferred_height = ((edid[offset + 7] & 0xf0) << 4) | edid[offset + 5]; + // Use 720x400 on 1080p, 4k and 8k displays. + if ((established_timings & 0x80) != 0 && + preferred_width % 1920 == 0 && + preferred_height % 1080 == 0) { + *default_width = 720; + *default_height = 400; + } else { + *default_width = 640; + *default_height = 480; + } + } + } + } + } + common_hal_busio_i2c_unlock(i2c); + return probed; +} + +// For picodvi_autoconstruct to work, the 8 DVI/HSTX pin names must be defined, AND +// i2c bus 0 must also be connected to DVI with on-board pull ups +void picodvi_autoconstruct(void) { + if (get_safe_mode() != SAFE_MODE_NONE) { + return; + } + + mp_int_t default_width = 640; + mp_int_t default_height = 480; + if (!picodvi_autoconstruct_enabled(&default_width, &default_height)) { + return; + } + + mp_int_t width = default_width; + mp_int_t height = 0; + mp_int_t color_depth = 8; + mp_int_t rotation = 0; + + (void)settings_get_int("CIRCUITPY_DISPLAY_WIDTH", &width); + (void)settings_get_int("CIRCUITPY_DISPLAY_HEIGHT", &height); + (void)settings_get_int("CIRCUITPY_DISPLAY_COLOR_DEPTH", &color_depth); + (void)settings_get_int("CIRCUITPY_DISPLAY_ROTATION", &rotation); + + if (height == 0) { + switch (width) { + case 720: + height = 400; + break; + case 640: + height = 480; + break; + case 320: + height = 240; + break; + case 360: + height = 200; + break; + } + } + + if (rotation != 0 && rotation != 90 && rotation != 180 && rotation != 270) { + // invalid rotation + rotation = 0; + } + + if (!common_hal_picodvi_framebuffer_preflight(width, height, color_depth)) { + // invalid configuration, set back to default + width = default_width; + height = default_height; + color_depth = 8; + } + + // construct framebuffer and display + picodvi_framebuffer_obj_t *fb = &allocate_display_bus_or_raise()->picodvi; + fb->base.type = &picodvi_framebuffer_type; + common_hal_picodvi_framebuffer_construct(fb, + width, height, + DEFAULT_DVI_BUS_CLK_DP, + DEFAULT_DVI_BUS_CLK_DN, + DEFAULT_DVI_BUS_RED_DP, + DEFAULT_DVI_BUS_RED_DN, + DEFAULT_DVI_BUS_GREEN_DP, + DEFAULT_DVI_BUS_GREEN_DN, + DEFAULT_DVI_BUS_BLUE_DP, + DEFAULT_DVI_BUS_BLUE_DN, + color_depth); + + framebufferio_framebufferdisplay_obj_t *display = &allocate_display()->framebuffer_display; + display->base.type = &framebufferio_framebufferdisplay_type; + common_hal_framebufferio_framebufferdisplay_construct( + display, + MP_OBJ_FROM_PTR(fb), + rotation, + true); +} +#else +void picodvi_autoconstruct(void) { +} +#endif diff --git a/ports/raspberrypi/common-hal/picodvi/__init__.h b/ports/raspberrypi/common-hal/picodvi/__init__.h new file mode 100644 index 0000000000000..41f3656339a50 --- /dev/null +++ b/ports/raspberrypi/common-hal/picodvi/__init__.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern void picodvi_autoconstruct(void); diff --git a/ports/raspberrypi/common-hal/pulseio/PulseIn.c b/ports/raspberrypi/common-hal/pulseio/PulseIn.c index ee4aa79af0ce3..a2bfeec6c6a23 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseIn.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseIn.c @@ -4,7 +4,7 @@ // // SPDX-License-Identifier: MIT -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" +#include "hardware/gpio.h" #include @@ -26,7 +26,7 @@ static const uint16_t pulsein_program[] = { void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu_pin_obj_t *pin, uint16_t maxlen, bool idle_state) { - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { m_malloc_fail(maxlen * sizeof(uint16_t)); } @@ -41,20 +41,22 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, 1000000, // frequency NULL, 0, // init, init_len NULL, 0, // may_exec - NULL, 0, 0, 0, // first out pin, # out pins, initial_out_pin_state - pin, 1, 0, 0, // first in pin, # in pins - NULL, 0, 0, 0, // first set pin - NULL, 0, 0, 0, // first sideset pin + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first out pin, # out pins, initial_out_pin_state + pin, 1, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first in pin, # in pins + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first set pin + NULL, 0, false, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // first sideset pin false, // No sideset enable NULL, PULL_NONE, // jump pin, jmp_pull - 0, // wait gpio pins + PIO_PINMASK_NONE, // wait gpio pins true, // exclusive pin usage false, 8, false, // TX, setting we don't use false, // wait for TX stall true, 32, true, // RX auto pull every 32 bits. shift left to output msb first false, // Not user-interruptible. 0, -1, // wrap settings - PIO_ANY_OFFSET); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); common_hal_pulseio_pulsein_pause(self); diff --git a/ports/raspberrypi/common-hal/pulseio/PulseIn.h b/ports/raspberrypi/common-hal/pulseio/PulseIn.h index cca1dedfabca9..369d7b8f450fe 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseIn.h +++ b/ports/raspberrypi/common-hal/pulseio/PulseIn.h @@ -7,7 +7,7 @@ #pragma once #include "common-hal/microcontroller/Pin.h" -#include "src/rp2_common/hardware_pio/include/hardware/pio.h" +#include "hardware/pio.h" #include "common-hal/rp2pio/StateMachine.h" #include "py/obj.h" diff --git a/ports/raspberrypi/common-hal/pulseio/PulseOut.c b/ports/raspberrypi/common-hal/pulseio/PulseOut.c index 114bff13979f9..84d02e20cce15 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseOut.c +++ b/ports/raspberrypi/common-hal/pulseio/PulseOut.c @@ -14,9 +14,9 @@ #include "shared-bindings/microcontroller/__init__.h" #include "common-hal/pwmio/PWMOut.h" #include "hardware/structs/pwm.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" -#include "src/common/pico_time/include/pico/time.h" +#include "hardware/gpio.h" +#include "hardware/pwm.h" +#include "pico/time.h" volatile alarm_id_t cur_alarm = 0; diff --git a/ports/raspberrypi/common-hal/pulseio/PulseOut.h b/ports/raspberrypi/common-hal/pulseio/PulseOut.h index fa264c36b7f68..cff82f2c28c72 100644 --- a/ports/raspberrypi/common-hal/pulseio/PulseOut.h +++ b/ports/raspberrypi/common-hal/pulseio/PulseOut.h @@ -8,7 +8,7 @@ #include "common-hal/microcontroller/Pin.h" #include "common-hal/pwmio/PWMOut.h" -#include "src/common/pico_time/include/pico/time.h" +#include "pico/time.h" #include "py/obj.h" diff --git a/ports/raspberrypi/common-hal/pwmio/PWMOut.c b/ports/raspberrypi/common-hal/pwmio/PWMOut.c index e0572eccd9e44..9ceb5a0185d92 100644 --- a/ports/raspberrypi/common-hal/pwmio/PWMOut.c +++ b/ports/raspberrypi/common-hal/pwmio/PWMOut.c @@ -12,10 +12,10 @@ #include "shared-bindings/pwmio/PWMOut.h" #include "shared-bindings/microcontroller/Processor.h" -#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h" -#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" +#include "hardware/platform_defs.h" +#include "hardware/clocks.h" +#include "hardware/gpio.h" +#include "hardware/pwm.h" uint32_t target_slice_frequencies[NUM_PWM_SLICES]; uint32_t slice_variable_frequency; diff --git a/ports/raspberrypi/common-hal/rgbmatrix/RGBMatrix.c b/ports/raspberrypi/common-hal/rgbmatrix/RGBMatrix.c index 029e2b2755ea0..875da3432510a 100644 --- a/ports/raspberrypi/common-hal/rgbmatrix/RGBMatrix.c +++ b/ports/raspberrypi/common-hal/rgbmatrix/RGBMatrix.c @@ -12,8 +12,8 @@ #include "shared-bindings/pwmio/PWMOut.h" #include "shared-module/rgbmatrix/RGBMatrix.h" -#include "src/rp2_common/hardware_pwm/include/hardware/pwm.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "hardware/pwm.h" +#include "hardware/irq.h" void *common_hal_rgbmatrix_timer_allocate(rgbmatrix_rgbmatrix_obj_t *self) { // Choose a PWM channel based on the first RGB pin diff --git a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c index a31312b6436b7..d71ff60b2ebc3 100644 --- a/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c +++ b/ports/raspberrypi/common-hal/rotaryio/IncrementalEncoder.c @@ -43,6 +43,9 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { const mcu_pin_obj_t *pins[] = { pin_a, pin_b }; + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + // Start out with swapped to match behavior with other ports. self->swapped = true; if (!common_hal_rp2pio_pins_are_sequential(2, pins)) { @@ -62,22 +65,23 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode 1000000, encoder_init, MP_ARRAY_SIZE(encoder_init), // init NULL, 0, // may_exec - NULL, 0, 0, 0, // out pin + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_NONE, // out pin pins[0], 2, // in pins - 3, 0, // in pulls - NULL, 0, 0, 0x1f, // set pins - NULL, 0, 0, 0x1f, // sideset pins + PIO_PINMASK32_FROM_VALUE(3), PIO_PINMASK32_NONE, // in pulls + NULL, 0, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // set pins + NULL, 0, false, PIO_PINMASK32_NONE, PIO_PINMASK32_FROM_VALUE(0x1f), // sideset pins false, // No sideset enable NULL, PULL_NONE, // jump pin - 0, // wait gpio pins + PIO_PINMASK_NONE, // wait gpio pins true, // exclusive pin use false, 32, false, // out settings false, // Wait for txstall false, 32, false, // in settings false, // Not user-interruptible. 0, MP_ARRAY_SIZE(encoder) - 1, // wrap settings - PIO_ANY_OFFSET - ); + PIO_ANY_OFFSET, + PIO_FIFO_TYPE_DEFAULT, + PIO_MOV_STATUS_DEFAULT, PIO_MOV_N_DEFAULT); // We're guaranteed by the init code that some output will be available promptly uint8_t quiescent_state; @@ -88,6 +92,7 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode } bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { + // Use the deinit state of the PIO state machine. return common_hal_rp2pio_statemachine_deinited(&self->state_machine); } @@ -99,6 +104,11 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o common_hal_rp2pio_statemachine_deinit(&self->state_machine); } +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + // Use the deinit state of the PIO state machine. + common_hal_rp2pio_statemachine_mark_deinit(&self->state_machine); +} + static void incrementalencoder_interrupt_handler(void *self_in) { rotaryio_incrementalencoder_obj_t *self = self_in; diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c index 602f9223f4cd9..71050677f225f 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.c +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.c @@ -12,13 +12,14 @@ #include "shared-bindings/digitalio/Pull.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/memorymap/AddressRange.h" -#include "src/rp2040/hardware_regs/include/hardware/platform_defs.h" -#include "src/rp2_common/hardware_clocks/include/hardware/clocks.h" -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" -#include "src/rp2_common/hardware_pio/include/hardware/pio_instructions.h" -#include "src/rp2040/hardware_structs/include/hardware/structs/iobank0.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "hardware/platform_defs.h" +#include "hardware/structs/iobank0.h" +#include "hardware/clocks.h" +#include "hardware/dma.h" +#include "hardware/pio_instructions.h" +#include "hardware/irq.h" #include "shared/runtime/interrupt_char.h" #include "py/obj.h" @@ -34,57 +35,73 @@ static uint8_t _current_program_offset[NUM_PIOS][NUM_PIO_STATE_MACHINES]; static uint8_t _current_program_len[NUM_PIOS][NUM_PIO_STATE_MACHINES]; static bool _never_reset[NUM_PIOS][NUM_PIO_STATE_MACHINES]; -static uint32_t _current_pins[NUM_PIOS]; -static uint32_t _current_sm_pins[NUM_PIOS][NUM_PIO_STATE_MACHINES]; -static int8_t _sm_dma_plus_one[NUM_PIOS][NUM_PIO_STATE_MACHINES]; +static pio_pinmask_t _current_pins[NUM_PIOS]; +static pio_pinmask_t _current_sm_pins[NUM_PIOS][NUM_PIO_STATE_MACHINES]; -#define SM_DMA_ALLOCATED(pio_index, sm) (_sm_dma_plus_one[(pio_index)][(sm)] != 0) -#define SM_DMA_GET_CHANNEL(pio_index, sm) (_sm_dma_plus_one[(pio_index)][(sm)] - 1) -#define SM_DMA_CLEAR_CHANNEL(pio_index, sm) (_sm_dma_plus_one[(pio_index)][(sm)] = 0) -#define SM_DMA_SET_CHANNEL(pio_index, sm, channel) (_sm_dma_plus_one[(pio_index)][(sm)] = (channel) + 1) +static int8_t _sm_dma_plus_one_write[NUM_PIOS][NUM_PIO_STATE_MACHINES]; +static int8_t _sm_dma_plus_one_read[NUM_PIOS][NUM_PIO_STATE_MACHINES]; + +#define SM_DMA_ALLOCATED_WRITE(pio_index, sm) (_sm_dma_plus_one_write[(pio_index)][(sm)] != 0) +#define SM_DMA_GET_CHANNEL_WRITE(pio_index, sm) (_sm_dma_plus_one_write[(pio_index)][(sm)] - 1) +#define SM_DMA_CLEAR_CHANNEL_WRITE(pio_index, sm) (_sm_dma_plus_one_write[(pio_index)][(sm)] = 0) +#define SM_DMA_SET_CHANNEL_WRITE(pio_index, sm, channel) (_sm_dma_plus_one_write[(pio_index)][(sm)] = (channel) + 1) + +#define SM_DMA_ALLOCATED_READ(pio_index, sm) (_sm_dma_plus_one_read[(pio_index)][(sm)] != 0) +#define SM_DMA_GET_CHANNEL_READ(pio_index, sm) (_sm_dma_plus_one_read[(pio_index)][(sm)] - 1) +#define SM_DMA_CLEAR_CHANNEL_READ(pio_index, sm) (_sm_dma_plus_one_read[(pio_index)][(sm)] = 0) +#define SM_DMA_SET_CHANNEL_READ(pio_index, sm, channel) (_sm_dma_plus_one_read[(pio_index)][(sm)] = (channel) + 1) -static PIO pio_instances[NUM_PIOS] = { - pio0, - pio1 - #if NUM_PIOS == 3 - , pio2 - #endif -}; typedef void (*interrupt_handler_type)(void *); static interrupt_handler_type _interrupt_handler[NUM_PIOS][NUM_PIO_STATE_MACHINES]; static void *_interrupt_arg[NUM_PIOS][NUM_PIO_STATE_MACHINES]; static void rp2pio_statemachine_interrupt_handler(void); -static void rp2pio_statemachine_set_pull(uint32_t pull_pin_up, uint32_t pull_pin_down, uint32_t pins_we_use) { +static void rp2pio_statemachine_set_pull(pio_pinmask_t pull_pin_up, pio_pinmask_t pull_pin_down, pio_pinmask_t pins_we_use) { for (size_t i = 0; i < NUM_BANK0_GPIOS; i++) { - bool used = pins_we_use & (1 << i); + bool used = PIO_PINMASK_IS_SET(pins_we_use, i); if (used) { - bool pull_up = pull_pin_up & (1 << i); - bool pull_down = pull_pin_down & (1 << i); + bool pull_up = PIO_PINMASK_IS_SET(pull_pin_up, i); + bool pull_down = PIO_PINMASK_IS_SET(pull_pin_down, i); gpio_set_pulls(i, pull_up, pull_down); } } } -static void rp2pio_statemachine_clear_dma(int pio_index, int sm) { - if (SM_DMA_ALLOCATED(pio_index, sm)) { - int channel = SM_DMA_GET_CHANNEL(pio_index, sm); - uint32_t channel_mask = 1u << channel; - dma_hw->inte0 &= ~channel_mask; +static void rp2pio_statemachine_clear_dma_write(int pio_index, int sm) { + if (SM_DMA_ALLOCATED_WRITE(pio_index, sm)) { + int channel_write = SM_DMA_GET_CHANNEL_WRITE(pio_index, sm); + uint32_t channel_mask_write = 1u << channel_write; + dma_hw->inte0 &= ~channel_mask_write; if (!dma_hw->inte0) { irq_set_mask_enabled(1 << DMA_IRQ_0, false); } - MP_STATE_PORT(background_pio)[channel] = NULL; - dma_channel_abort(channel); - dma_channel_unclaim(channel); + MP_STATE_PORT(background_pio_write)[channel_write] = NULL; + dma_channel_abort(channel_write); + dma_channel_unclaim(channel_write); } - SM_DMA_CLEAR_CHANNEL(pio_index, sm); + SM_DMA_CLEAR_CHANNEL_WRITE(pio_index, sm); +} + +static void rp2pio_statemachine_clear_dma_read(int pio_index, int sm) { + if (SM_DMA_ALLOCATED_READ(pio_index, sm)) { + int channel_read = SM_DMA_GET_CHANNEL_READ(pio_index, sm); + uint32_t channel_mask_read = 1u << channel_read; + dma_hw->inte0 &= ~channel_mask_read; + if (!dma_hw->inte0) { + irq_set_mask_enabled(1 << DMA_IRQ_0, false); + } + MP_STATE_PORT(background_pio_read)[channel_read] = NULL; + dma_channel_abort(channel_read); + dma_channel_unclaim(channel_read); + } + SM_DMA_CLEAR_CHANNEL_READ(pio_index, sm); } static void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) { uint8_t pio_index = pio_get_index(pio); - rp2pio_statemachine_clear_dma(pio_index, sm); + rp2pio_statemachine_clear_dma_write(pio_index, sm); + rp2pio_statemachine_clear_dma_read(pio_index, sm); uint32_t program_id = _current_program_id[pio_index][sm]; if (program_id == 0) { return; @@ -105,9 +122,9 @@ static void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) { pio_remove_program(pio, &program_struct, offset); } - uint32_t pins = _current_sm_pins[pio_index][sm]; + pio_pinmask_t pins = _current_sm_pins[pio_index][sm]; for (size_t pin_number = 0; pin_number < NUM_BANK0_GPIOS; pin_number++) { - if ((pins & (1 << pin_number)) == 0) { + if (!PIO_PINMASK_IS_SET(pins, pin_number)) { continue; } _pin_reference_count[pin_number]--; @@ -115,17 +132,17 @@ static void _reset_statemachine(PIO pio, uint8_t sm, bool leave_pins) { if (!leave_pins) { reset_pin_number(pin_number); } - _current_pins[pio_index] &= ~(1 << pin_number); + PIO_PINMASK_CLEAR(_current_pins[pio_index], pin_number); } } - _current_sm_pins[pio_index][sm] = 0; + _current_sm_pins[pio_index][sm] = PIO_PINMASK_NONE; pio->inte0 &= ~((PIO_IRQ0_INTF_SM0_RXNEMPTY_BITS | PIO_IRQ0_INTF_SM0_TXNFULL_BITS | PIO_IRQ0_INTF_SM0_BITS) << sm); pio_sm_unclaim(pio, sm); } void reset_rp2pio_statemachine(void) { for (size_t i = 0; i < NUM_PIOS; i++) { - PIO pio = pio_instances[i]; + PIO pio = pio_get_instance(i); for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) { if (_never_reset[i][j]) { continue; @@ -142,8 +159,8 @@ void reset_rp2pio_statemachine(void) { } } -static uint32_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pin_count, bool exclusive_pin_use) { - uint32_t pins_we_use = 0; +static pio_pinmask_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pin_count, bool exclusive_pin_use) { + pio_pinmask_t pins_we_use = PIO_PINMASK_NONE; if (first_pin != NULL) { for (size_t i = 0; i < pin_count; i++) { uint8_t pin_number = first_pin->number + i; @@ -158,26 +175,81 @@ static uint32_t _check_pins_free(const mcu_pin_obj_t *first_pin, uint8_t pin_cou if (exclusive_pin_use || _pin_reference_count[pin_number] == 0) { assert_pin_free(pin); } - pins_we_use |= 1 << pin_number; + PIO_PINMASK_SET(pins_we_use, pin_number); } } return pins_we_use; } -static bool can_add_program(PIO pio, const pio_program_t *program, int offset) { - if (offset == -1) { - return pio_can_add_program(pio, program); +static enum pio_fifo_join compute_fifo_type(int fifo_type_in, bool rx_fifo, bool tx_fifo) { + if (fifo_type_in != PIO_FIFO_JOIN_AUTO) { + return fifo_type_in; + } + if (!rx_fifo) { + return PIO_FIFO_JOIN_TX; + } + if (!tx_fifo) { + return PIO_FIFO_JOIN_RX; } - return pio_can_add_program_at_offset(pio, program, offset); + return PIO_FIFO_JOIN_NONE; +} + +static int compute_fifo_depth(enum pio_fifo_join join) { + if (join == PIO_FIFO_JOIN_TX || join == PIO_FIFO_JOIN_RX) { + return 8; + } + + #if PICO_PIO_VERSION > 0 + if (join == PIO_FIFO_JOIN_PUTGET) { + return 0; + } + #endif + + return 4; +} + + +// from pico-sdk/src/rp2_common/hardware_pio/pio.c +static bool is_gpio_compatible(PIO pio, uint32_t used_gpio_ranges) { + #if PICO_PIO_VERSION > 0 + bool gpio_base = pio_get_gpio_base(pio); + return !((gpio_base && (used_gpio_ranges & 1)) || + (!gpio_base && (used_gpio_ranges & 4))); + #else + ((void)pio); + ((void)used_gpio_ranges); + return true; + #endif } -static uint add_program(PIO pio, const pio_program_t *program, int offset) { - if (offset == -1) { - return pio_add_program(pio, program); +static bool use_existing_program(PIO *pio_out, int *sm_out, int *offset_inout, uint32_t program_id, size_t program_len, uint gpio_base, uint gpio_count) { + uint32_t required_gpio_ranges; + if (gpio_count) { + required_gpio_ranges = (1u << (gpio_base >> 4)) | + (1u << ((gpio_base + gpio_count - 1) >> 4)); } else { - pio_add_program_at_offset(pio, program, offset); - return offset; + required_gpio_ranges = 0; } + + for (size_t i = 0; i < NUM_PIOS; i++) { + PIO pio = pio_get_instance(i); + if (!is_gpio_compatible(pio, required_gpio_ranges)) { + continue; + } + for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) { + if (_current_program_id[i][j] == program_id && + _current_program_len[i][j] == program_len && + (*offset_inout == -1 || *offset_inout == _current_program_offset[i][j])) { + *sm_out = pio_claim_unused_sm(pio, false); + if (*sm_out >= 0) { + *pio_out = pio; + *offset_inout = _current_program_offset[i][j]; + return true; + } + } + } + } + return false; } bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, @@ -186,12 +258,12 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, const uint16_t *init, size_t init_len, const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, - uint32_t pull_pin_up, uint32_t pull_pin_down, + pio_pinmask_t pull_pin_up, pio_pinmask_t pull_pin_down, // GPIO numbering const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, - const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, - uint32_t initial_pin_state, uint32_t initial_pin_direction, + const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, bool sideset_pindirs, + pio_pinmask_t initial_pin_state, pio_pinmask_t initial_pin_direction, const mcu_pin_obj_t *jmp_pin, - uint32_t pins_we_use, bool tx_fifo, bool rx_fifo, + pio_pinmask_t pins_we_use, bool tx_fifo, bool rx_fifo, bool auto_pull, uint8_t pull_threshold, bool out_shift_right, bool wait_for_txstall, bool auto_push, uint8_t push_threshold, bool in_shift_right, @@ -199,75 +271,84 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, bool user_interruptible, bool sideset_enable, int wrap_target, int wrap, - int offset + int offset, + int fifo_type, + int mov_status_type, int mov_status_n ) { // Create a program id that isn't the pointer so we can store it without storing the original object. uint32_t program_id = ~((uint32_t)program); + uint gpio_base = 0, gpio_count = 0; + #if NUM_BANK0_GPIOS > 32 + if (PIO_PINMASK_VALUE(pins_we_use) >> 32) { + if (PIO_PINMASK_VALUE(pins_we_use) & 0xffff) { + // Uses pins from 0-15 and 32-47. not possible + return false; + } + } + + pio_pinmask_value_t v = PIO_PINMASK_VALUE(pins_we_use); + if (v) { + while (!(v & 1)) { + gpio_base++; + v >>= 1; + } + while (v) { + gpio_count++; + v >>= 1; + } + } + #endif + // Next, find a PIO and state machine to use. - size_t pio_index = NUM_PIOS; - uint8_t program_offset = 32; pio_program_t program_struct = { .instructions = (uint16_t *)program, .length = program_len, - .origin = -1 + .origin = offset, }; - for (size_t i = 0; i < NUM_PIOS; i++) { - PIO pio = pio_instances[i]; - uint8_t free_count = 0; - for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) { - if (_current_program_id[i][j] == program_id && - _current_program_len[i][j] == program_len && - (offset == -1 || offset == _current_program_offset[i][j])) { - program_offset = _current_program_offset[i][j]; - } - if (!pio_sm_is_claimed(pio, j)) { - free_count++; - } - } - if (free_count > 0 && (program_offset < 32 || can_add_program(pio, &program_struct, offset))) { - pio_index = i; - if (program_offset < 32) { - break; - } + PIO pio; + int state_machine; + bool added = false; + + if (!use_existing_program(&pio, &state_machine, &offset, program_id, program_len, gpio_base, gpio_count)) { + uint program_offset; + bool r = pio_claim_free_sm_and_add_program_for_gpio_range(&program_struct, &pio, (uint *)&state_machine, &program_offset, gpio_base, gpio_count, true); + if (!r) { + return false; } - // Reset program offset if we weren't able to find a free state machine - // on that PIO. (We would have broken the loop otherwise.) - program_offset = 32; + offset = program_offset; + added = true; } - size_t state_machine = NUM_PIO_STATE_MACHINES; - if (pio_index < NUM_PIOS) { - PIO pio = pio_instances[pio_index]; - for (size_t i = 0; i < NUM_PIOS; i++) { - if (i == pio_index) { - continue; - } - if ((_current_pins[i] & pins_we_use) != 0) { - // Pin in use by another PIO already. - return false; + size_t pio_index = pio_get_index(pio); + for (size_t i = 0; i < NUM_PIOS; i++) { + if (i == pio_index) { + continue; + } + pio_pinmask_t intersection = PIO_PINMASK_AND(_current_pins[i], pins_we_use); + if (PIO_PINMASK_VALUE(intersection) != 0) { + if (added) { + pio_remove_program(pio, &program_struct, offset); } + pio_sm_unclaim(pio, state_machine); + // Pin in use by another PIO already. + return false; } - state_machine = pio_claim_unused_sm(pio, false); - } - if (pio_index == NUM_PIOS || state_machine < 0 || state_machine >= NUM_PIO_STATE_MACHINES) { - return false; } - self->pio = pio_instances[pio_index]; + // Sanity check that state_machine number is valid. + assert(state_machine >= 0); + self->pio = pio; self->state_machine = state_machine; - if (program_offset == 32) { - program_offset = add_program(self->pio, &program_struct, offset); - } - self->offset = program_offset; + self->offset = offset; _current_program_id[pio_index][state_machine] = program_id; _current_program_len[pio_index][state_machine] = program_len; - _current_program_offset[pio_index][state_machine] = program_offset; + _current_program_offset[pio_index][state_machine] = offset; _current_sm_pins[pio_index][state_machine] = pins_we_use; - _current_pins[pio_index] |= pins_we_use; + PIO_PINMASK_MERGE(_current_pins[pio_index], pins_we_use); - pio_sm_set_pins_with_mask(self->pio, state_machine, initial_pin_state, pins_we_use); - pio_sm_set_pindirs_with_mask(self->pio, state_machine, initial_pin_direction, pins_we_use); + pio_sm_set_pins_with_mask64(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_state), PIO_PINMASK_VALUE(pins_we_use)); + pio_sm_set_pindirs_with_mask64(self->pio, state_machine, PIO_PINMASK_VALUE(initial_pin_direction), PIO_PINMASK_VALUE(pins_we_use)); rp2pio_statemachine_set_pull(pull_pin_up, pull_pin_down, pins_we_use); self->initial_pin_state = initial_pin_state; self->initial_pin_direction = initial_pin_direction; @@ -275,11 +356,12 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, self->pull_pin_down = pull_pin_down; for (size_t pin_number = 0; pin_number < NUM_BANK0_GPIOS; pin_number++) { - if ((pins_we_use & (1 << pin_number)) == 0) { + if (!PIO_PINMASK_IS_SET(pins_we_use, pin_number)) { continue; } const mcu_pin_obj_t *pin = mcu_get_pin_by_number(pin_number); if (!pin) { + // TODO: should be impossible, but free resources here anyway return false; } _pin_reference_count[pin_number]++; @@ -297,7 +379,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, gpio_set_drive_strength(pin_number, GPIO_DRIVE_STRENGTH_2MA); } - pio_sm_config c = {0, 0, 0}; + pio_sm_config c = pio_get_default_sm_config(); if (frequency == 0) { frequency = clock_get_hz(clk_sys); @@ -324,7 +406,7 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, if (sideset_enable) { total_sideset_bits += 1; } - sm_config_set_sideset(&c, total_sideset_bits, sideset_enable, false /* pin direction */); + sm_config_set_sideset(&c, total_sideset_bits, sideset_enable, sideset_pindirs); sm_config_set_sideset_pins(&c, first_sideset_pin->number); } if (jmp_pin != NULL) { @@ -338,20 +420,32 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, mp_arg_validate_int_range(wrap_target, 0, program_len - 1, MP_QSTR_wrap_target); - wrap += program_offset; - wrap_target += program_offset; + wrap += offset; + wrap_target += offset; sm_config_set_wrap(&c, wrap_target, wrap); sm_config_set_in_shift(&c, in_shift_right, auto_push, push_threshold); + #if PICO_PIO_VERSION > 0 + sm_config_set_in_pin_count(&c, in_pin_count); + #endif + sm_config_set_out_shift(&c, out_shift_right, auto_pull, pull_threshold); + sm_config_set_out_pin_count(&c, out_pin_count); - enum pio_fifo_join join = PIO_FIFO_JOIN_NONE; - if (!rx_fifo) { - join = PIO_FIFO_JOIN_TX; - } else if (!tx_fifo) { - join = PIO_FIFO_JOIN_RX; + sm_config_set_set_pin_count(&c, set_pin_count); + + enum pio_fifo_join join = compute_fifo_type(fifo_type, rx_fifo, tx_fifo); + + self->fifo_depth = compute_fifo_depth(join); + + #if PICO_PIO_VERSION > 0 + if (fifo_type == PIO_FIFO_JOIN_TXPUT || fifo_type == PIO_FIFO_JOIN_TXGET) { + self->rxfifo_obj.base.type = &memorymap_addressrange_type; + common_hal_memorymap_addressrange_construct(&self->rxfifo_obj, (uint8_t *)self->pio->rxf_putget[self->state_machine], 4 * sizeof(uint32_t)); + } else { + self->rxfifo_obj.base.type = NULL; } - self->fifo_depth = (join == PIO_FIFO_JOIN_NONE) ? 4 : 8; + #endif if (rx_fifo) { self->rx_dreq = pio_get_dreq(self->pio, self->state_machine, false); @@ -370,12 +464,19 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, self->init_len = init_len; sm_config_set_fifo_join(&c, join); + + sm_config_set_mov_status(&c, mov_status_type, mov_status_n); + + // TODO: these arguments + // int set_count, int out_count + self->sm_config = c; // no DMA allocated - SM_DMA_CLEAR_CHANNEL(pio_index, state_machine); + SM_DMA_CLEAR_CHANNEL_READ(pio_index, state_machine); + SM_DMA_CLEAR_CHANNEL_WRITE(pio_index, state_machine); - pio_sm_init(self->pio, self->state_machine, program_offset, &c); + pio_sm_init(self->pio, self->state_machine, offset, &c); common_hal_rp2pio_statemachine_run(self, init, init_len); common_hal_rp2pio_statemachine_set_frequency(self, frequency); @@ -383,18 +484,20 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, return true; } -static uint32_t mask_and_rotate(const mcu_pin_obj_t *first_pin, uint32_t bit_count, uint32_t value) { +static pio_pinmask_t mask_and_shift(const mcu_pin_obj_t *first_pin, uint32_t bit_count, pio_pinmask32_t value_in) { if (!first_pin) { - return 0; + return PIO_PINMASK_NONE; } - value = value & ((1 << bit_count) - 1); - uint32_t shift = first_pin->number; - return value << shift | value >> (32 - shift); + pio_pinmask_value_t mask = (PIO_PINMASK_C(1) << bit_count) - 1; + pio_pinmask_value_t value = (pio_pinmask_value_t)PIO_PINMASK32_VALUE(value_in); + int shift = first_pin->number; + return PIO_PINMASK_FROM_VALUE((value & mask) << shift); } typedef struct { struct { - uint32_t pins_we_use, in_pin_count, out_pin_count; + pio_pinmask_t pins_we_use; + uint8_t in_pin_count, out_pin_count, pio_gpio_offset; bool has_jmp_pin, auto_push, auto_pull, has_in_pin, has_out_pin, has_set_pin; } inputs; struct { @@ -420,12 +523,12 @@ static void consider_instruction(introspect_t *state, uint16_t full_instruction, } } if (instruction == pio_instr_bits_wait) { - uint16_t wait_source = (full_instruction & 0x0060) >> 5; - uint16_t wait_index = full_instruction & 0x001f; - if (wait_source == 0 && (state->inputs.pins_we_use & (1 << wait_index)) == 0) { // GPIO + const uint16_t wait_source = (full_instruction & 0x0060) >> 5; + const uint16_t wait_index = full_instruction & 0x001f; + const uint16_t wait_pin = wait_index + state->inputs.pio_gpio_offset; + if (wait_source == 0 && !PIO_PINMASK_IS_SET(state->inputs.pins_we_use, wait_pin)) { // GPIO mp_raise_ValueError_varg(MP_ERROR_TEXT("%q[%u] uses extra pin"), what_program, i); - } - if (wait_source == 1) { // Input pin + } else if (wait_source == 1) { // Input pin if (!state->inputs.has_in_pin) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Missing first_in_pin. %q[%u] waits based on pin"), what_program, i); } @@ -505,34 +608,52 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, size_t frequency, const uint16_t *init, size_t init_len, const uint16_t *may_exec, size_t may_exec_len, - const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, uint32_t initial_out_pin_state, uint32_t initial_out_pin_direction, + const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, pio_pinmask32_t initial_out_pin_state32, pio_pinmask32_t initial_out_pin_direction32, const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, - uint32_t pull_pin_up, uint32_t pull_pin_down, - const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, uint32_t initial_set_pin_state, uint32_t initial_set_pin_direction, - const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, uint32_t initial_sideset_pin_state, uint32_t initial_sideset_pin_direction, + pio_pinmask32_t in_pull_pin_up32, pio_pinmask32_t in_pull_pin_down32, // relative to first_in_pin + const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, pio_pinmask32_t initial_set_pin_state32, pio_pinmask32_t initial_set_pin_direction32, + const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, bool sideset_pindirs, + pio_pinmask32_t initial_sideset_pin_state32, pio_pinmask32_t initial_sideset_pin_direction32, bool sideset_enable, const mcu_pin_obj_t *jmp_pin, digitalio_pull_t jmp_pull, - uint32_t wait_gpio_mask, + pio_pinmask_t wait_gpio_mask, bool exclusive_pin_use, bool auto_pull, uint8_t pull_threshold, bool out_shift_right, bool wait_for_txstall, bool auto_push, uint8_t push_threshold, bool in_shift_right, bool user_interruptible, int wrap_target, int wrap, - int offset) { + int offset, + int fifo_type, + int mov_status_type, + int mov_status_n) { + + // Ensure object starts in its deinit state. + common_hal_rp2pio_statemachine_mark_deinit(self); // First, check that all pins are free OR already in use by any PIO if exclusive_pin_use is false. - uint32_t pins_we_use = wait_gpio_mask; - pins_we_use |= _check_pins_free(first_out_pin, out_pin_count, exclusive_pin_use); - pins_we_use |= _check_pins_free(first_in_pin, in_pin_count, exclusive_pin_use); - pins_we_use |= _check_pins_free(first_set_pin, set_pin_count, exclusive_pin_use); - pins_we_use |= _check_pins_free(first_sideset_pin, sideset_pin_count, exclusive_pin_use); - pins_we_use |= _check_pins_free(jmp_pin, 1, exclusive_pin_use); + pio_pinmask_t pins_we_use = wait_gpio_mask; + PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(first_out_pin, out_pin_count, exclusive_pin_use)); + PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(first_in_pin, in_pin_count, exclusive_pin_use)); + PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(first_set_pin, set_pin_count, exclusive_pin_use)); + PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(first_sideset_pin, sideset_pin_count, exclusive_pin_use)); + PIO_PINMASK_MERGE(pins_we_use, _check_pins_free(jmp_pin, 1, exclusive_pin_use)); + + int pio_gpio_offset = 0; + #if NUM_BANK0_GPIOS > 32 + if (PIO_PINMASK_VALUE(pins_we_use) >> 32) { + pio_gpio_offset = 16; + if (PIO_PINMASK_VALUE(pins_we_use) & 0xffff) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Cannot use GPIO0..15 together with GPIO32..47")); + } + } + #endif // Look through the program to see what we reference and make sure it was provided. introspect_t state = { .inputs = { .pins_we_use = pins_we_use, + .pio_gpio_offset = pio_gpio_offset, .has_jmp_pin = jmp_pin != NULL, .has_in_pin = first_in_pin != NULL, .has_out_pin = first_out_pin != NULL, @@ -554,43 +675,54 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, mp_raise_ValueError_varg(MP_ERROR_TEXT("Program does OUT without loading OSR")); } - uint32_t initial_pin_state = mask_and_rotate(first_out_pin, out_pin_count, initial_out_pin_state); - uint32_t initial_pin_direction = mask_and_rotate(first_out_pin, out_pin_count, initial_out_pin_direction); - initial_set_pin_state = mask_and_rotate(first_set_pin, set_pin_count, initial_set_pin_state); - initial_set_pin_direction = mask_and_rotate(first_set_pin, set_pin_count, initial_set_pin_direction); - uint32_t set_out_overlap = mask_and_rotate(first_out_pin, out_pin_count, 0xffffffff) & - mask_and_rotate(first_set_pin, set_pin_count, 0xffffffff); + pio_pinmask_t initial_pin_state = mask_and_shift(first_out_pin, out_pin_count, initial_out_pin_state32); + pio_pinmask_t initial_pin_direction = mask_and_shift(first_out_pin, out_pin_count, initial_out_pin_direction32); + pio_pinmask_t initial_set_pin_state = mask_and_shift(first_set_pin, set_pin_count, initial_set_pin_state32); + pio_pinmask_t initial_set_pin_direction = mask_and_shift(first_set_pin, set_pin_count, initial_set_pin_direction32); + pio_pinmask_t set_out_overlap = PIO_PINMASK_AND(mask_and_shift(first_out_pin, out_pin_count, PIO_PINMASK32_ALL), + mask_and_shift(first_set_pin, set_pin_count, PIO_PINMASK32_ALL)); // Check that OUT and SET settings agree because we don't have a way of picking one over the other. - if ((initial_pin_state & set_out_overlap) != (initial_set_pin_state & set_out_overlap)) { + if (!PIO_PINMASK_EQUAL( + PIO_PINMASK_AND(initial_pin_state, set_out_overlap), + PIO_PINMASK_AND(initial_set_pin_state, set_out_overlap))) { mp_raise_ValueError(MP_ERROR_TEXT("Initial set pin state conflicts with initial out pin state")); } - if ((initial_pin_direction & set_out_overlap) != (initial_set_pin_direction & set_out_overlap)) { + if (!PIO_PINMASK_EQUAL( + PIO_PINMASK_AND(initial_pin_direction, set_out_overlap), + PIO_PINMASK_AND(initial_set_pin_direction, set_out_overlap))) { mp_raise_ValueError(MP_ERROR_TEXT("Initial set pin direction conflicts with initial out pin direction")); } - initial_pin_state |= initial_set_pin_state; - initial_pin_direction |= initial_set_pin_direction; + PIO_PINMASK_MERGE(initial_pin_state, initial_set_pin_state); + PIO_PINMASK_MERGE(initial_pin_direction, initial_set_pin_direction); // Sideset overrides OUT or SET so we always use its values. - uint32_t sideset_mask = mask_and_rotate(first_sideset_pin, sideset_pin_count, 0x1f); - initial_pin_state = (initial_pin_state & ~sideset_mask) | mask_and_rotate(first_sideset_pin, sideset_pin_count, initial_sideset_pin_state); - initial_pin_direction = (initial_pin_direction & ~sideset_mask) | mask_and_rotate(first_sideset_pin, sideset_pin_count, initial_sideset_pin_direction); + pio_pinmask_t sideset_mask = mask_and_shift(first_sideset_pin, sideset_pin_count, PIO_PINMASK32_FROM_VALUE(0x1f)); + initial_pin_state = PIO_PINMASK_OR( + PIO_PINMASK_AND_NOT(initial_pin_state, sideset_mask), + mask_and_shift(first_sideset_pin, sideset_pin_count, initial_sideset_pin_state32)); + initial_pin_direction = PIO_PINMASK_OR( + PIO_PINMASK_AND_NOT(initial_pin_direction, sideset_mask), + mask_and_shift(first_sideset_pin, sideset_pin_count, initial_sideset_pin_direction32)); // Deal with pull up/downs - uint32_t pull_up = mask_and_rotate(first_in_pin, in_pin_count, pull_pin_up); - uint32_t pull_down = mask_and_rotate(first_in_pin, in_pin_count, pull_pin_down); + pio_pinmask_t pull_up = mask_and_shift(first_in_pin, in_pin_count, in_pull_pin_up32); + pio_pinmask_t pull_down = mask_and_shift(first_in_pin, in_pin_count, in_pull_pin_down32); if (jmp_pin) { - uint32_t jmp_mask = mask_and_rotate(jmp_pin, 1, 0x1f); + pio_pinmask_t jmp_mask = mask_and_shift(jmp_pin, 1, PIO_PINMASK32_FROM_VALUE(0x1f)); if (jmp_pull == PULL_UP) { - pull_up |= jmp_mask; + PIO_PINMASK_MERGE(pull_up, jmp_mask); } if (jmp_pull == PULL_DOWN) { - pull_up |= jmp_mask; + PIO_PINMASK_MERGE(pull_down, jmp_mask); } } - if (initial_pin_direction & (pull_up | pull_down)) { + if (PIO_PINMASK_VALUE( + PIO_PINMASK_AND(initial_pin_direction, + PIO_PINMASK_OR(pull_up, pull_down)))) { mp_raise_ValueError(MP_ERROR_TEXT("pull masks conflict with direction masks")); } + bool ok = rp2pio_statemachine_construct( self, program, program_len, @@ -600,7 +732,7 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, first_in_pin, in_pin_count, pull_up, pull_down, first_set_pin, set_pin_count, - first_sideset_pin, sideset_pin_count, + first_sideset_pin, sideset_pin_count, sideset_pindirs, initial_pin_state, initial_pin_direction, jmp_pin, pins_we_use, state.outputs.tx_fifo, state.outputs.rx_fifo, @@ -610,8 +742,12 @@ void common_hal_rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, true /* claim pins */, user_interruptible, sideset_enable, - wrap_target, wrap, offset); + wrap_target, wrap, offset, + fifo_type, + mov_status_type, mov_status_n); if (!ok) { + // indicate state machine never inited + common_hal_rp2pio_statemachine_mark_deinit(self); mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use")); } } @@ -623,9 +759,9 @@ void common_hal_rp2pio_statemachine_restart(rp2pio_statemachine_obj_t *self) { pio_sm_exec(self->pio, self->state_machine, self->offset); pio_sm_restart(self->pio, self->state_machine); uint8_t pio_index = pio_get_index(self->pio); - uint32_t pins_we_use = _current_sm_pins[pio_index][self->state_machine]; - pio_sm_set_pins_with_mask(self->pio, self->state_machine, self->initial_pin_state, pins_we_use); - pio_sm_set_pindirs_with_mask(self->pio, self->state_machine, self->initial_pin_direction, pins_we_use); + pio_pinmask_t pins_we_use = _current_sm_pins[pio_index][self->state_machine]; + pio_sm_set_pins_with_mask64(self->pio, self->state_machine, PIO_PINMASK_VALUE(self->initial_pin_state), PIO_PINMASK_VALUE(pins_we_use)); + pio_sm_set_pindirs_with_mask64(self->pio, self->state_machine, PIO_PINMASK_VALUE(self->initial_pin_direction), PIO_PINMASK_VALUE(pins_we_use)); rp2pio_statemachine_set_pull(self->pull_pin_up, self->pull_pin_down, pins_we_use); common_hal_rp2pio_statemachine_run(self, self->init, self->init_len); pio_sm_set_enabled(self->pio, self->state_machine, true); @@ -694,6 +830,10 @@ void common_hal_rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self) { rp2pio_statemachine_deinit(self, false); } +void common_hal_rp2pio_statemachine_mark_deinit(rp2pio_statemachine_obj_t *self) { + self->state_machine = NUM_PIO_STATE_MACHINES; +} + void common_hal_rp2pio_statemachine_never_reset(rp2pio_statemachine_obj_t *self) { rp2pio_statemachine_never_reset(self->pio, self->state_machine); // TODO: never reset all the pins @@ -721,25 +861,64 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, // This implementation is based on SPI but varies because the tx and rx buffers // may be different lengths and occur at different times or speeds. - // Use DMA for large transfers if channels are available. - // Don't exceed FIFO size. - const size_t dma_min_size_threshold = self->fifo_depth; int chan_tx = -1; int chan_rx = -1; size_t len = MAX(out_len, in_len); bool tx = data_out != NULL; bool rx = data_in != NULL; - bool use_dma = len >= dma_min_size_threshold || swap_out || swap_in; + bool free_data_out = false; + bool free_data_in = false; + uint8_t *sram_data_out = (uint8_t *)data_out; + uint8_t *sram_data_in = data_in; + bool tx_fits_in_fifo = (out_len / out_stride_in_bytes) <= self->fifo_depth; + bool rx_fits_in_fifo = (in_len / in_stride_in_bytes) <= self->fifo_depth; + bool use_dma = !(tx_fits_in_fifo && rx_fits_in_fifo) || swap_out || swap_in; + if (use_dma) { - // Use DMA channels to service the two FIFOs + // We can only reliably use DMA for SRAM buffers. So, if we're given PSRAM buffers, + // then copy them to SRAM first. If we can't, then fail. + // Use DMA channels to service the two FIFOs. Fail if we can't allocate DMA channels. if (tx) { + if (data_out < (uint8_t *)SRAM_BASE) { + // Try to allocate a temporary buffer for DMA transfer + uint8_t *temp_buffer = (uint8_t *)port_malloc(len, true); + if (temp_buffer == NULL) { + mp_printf(&mp_plat_print, "Failed to allocate temporary buffer for DMA tx\n"); + return false; + } + memcpy(temp_buffer, data_out, len); + sram_data_out = temp_buffer; + free_data_out = true; + } chan_tx = dma_claim_unused_channel(false); // DMA allocation failed... if (chan_tx < 0) { + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + port_free(sram_data_in); + } return false; } } if (rx) { + if (data_in < (uint8_t *)SRAM_BASE) { + // Try to allocate a temporary buffer for DMA transfer + uint8_t *temp_buffer = (uint8_t *)port_malloc(len, true); + if (temp_buffer == NULL) { + mp_printf(&mp_plat_print, "Failed to allocate temporary buffer for DMA rx\n"); + if (chan_tx >= 0) { + dma_channel_unclaim(chan_tx); + } + if (free_data_out) { + port_free(sram_data_out); + } + return false; + } + sram_data_in = temp_buffer; + free_data_in = true; + } chan_rx = dma_claim_unused_channel(false); // DMA allocation failed... if (chan_rx < 0) { @@ -747,6 +926,12 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, if (chan_tx >= 0) { dma_channel_unclaim(chan_tx); } + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + port_free(sram_data_in); + } return false; } } @@ -778,7 +963,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, channel_config_set_bswap(&c, swap_out); dma_channel_configure(chan_tx, &c, tx_destination, - data_out, + sram_data_out, out_len / out_stride_in_bytes, false); channel_mask |= 1u << chan_tx; @@ -791,7 +976,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, channel_config_set_write_increment(&c, true); channel_config_set_bswap(&c, swap_in); dma_channel_configure(chan_rx, &c, - data_in, + sram_data_in, rx_source, in_len / in_stride_in_bytes, false); @@ -818,8 +1003,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, self->pio->fdebug = stall_mask; } - // If we have claimed only one channel successfully, we should release immediately. This also - // releases the DMA after use_dma has been done. + // Release the DMA channels after use_dma has been done. if (chan_rx >= 0) { dma_channel_unclaim(chan_rx); } @@ -828,31 +1012,31 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, } if (!use_dma && !(self->user_interruptible && mp_hal_is_interrupted())) { - // Use software for small transfers, or if couldn't claim two DMA channels + // Use software for small transfers size_t rx_remaining = in_len / in_stride_in_bytes; size_t tx_remaining = out_len / out_stride_in_bytes; while (rx_remaining || tx_remaining) { while (tx_remaining && !pio_sm_is_tx_fifo_full(self->pio, self->state_machine)) { if (out_stride_in_bytes == 1) { - *tx_destination = *data_out; + *tx_destination = *sram_data_out; } else if (out_stride_in_bytes == 2) { - *((uint16_t *)tx_destination) = *((uint16_t *)data_out); + *((uint16_t *)tx_destination) = *((uint16_t *)sram_data_out); } else if (out_stride_in_bytes == 4) { - *((uint32_t *)tx_destination) = *((uint32_t *)data_out); + *((uint32_t *)tx_destination) = *((uint32_t *)sram_data_out); } - data_out += out_stride_in_bytes; + sram_data_out += out_stride_in_bytes; --tx_remaining; } while (rx_remaining && !pio_sm_is_rx_fifo_empty(self->pio, self->state_machine)) { if (in_stride_in_bytes == 1) { - *data_in = (uint8_t)*rx_source; + *sram_data_in = (uint8_t)*rx_source; } else if (in_stride_in_bytes == 2) { - *((uint16_t *)data_in) = *((uint16_t *)rx_source); + *((uint16_t *)sram_data_in) = *((uint16_t *)rx_source); } else if (in_stride_in_bytes == 4) { - *((uint32_t *)data_in) = *((uint32_t *)rx_source); + *((uint32_t *)sram_data_in) = *((uint32_t *)rx_source); } - data_in += in_stride_in_bytes; + sram_data_in += in_stride_in_bytes; --rx_remaining; } RUN_BACKGROUND_TASKS; @@ -864,7 +1048,7 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, self->pio->fdebug = stall_mask; } // Wait for the state machine to finish transmitting the data we've queued - // up. + // up (either from the CPU or via DMA.) if (tx) { while (!pio_sm_is_tx_fifo_empty(self->pio, self->state_machine) || (self->wait_for_txstall && (self->pio->fdebug & stall_mask) == 0)) { @@ -874,6 +1058,14 @@ static bool _transfer(rp2pio_statemachine_obj_t *self, } } } + if (free_data_out) { + port_free(sram_data_out); + } + if (free_data_in) { + // Copy the data from the SRAM buffer to the user PSRAM buffer. + memcpy(data_in, sram_data_in, len); + port_free(sram_data_in); + } return true; } @@ -952,7 +1144,7 @@ void common_hal_rp2pio_statemachine_set_interrupt_handler(rp2pio_statemachine_ob static void rp2pio_statemachine_interrupt_handler(void) { for (size_t pio_index = 0; pio_index < NUM_PIOS; pio_index++) { - PIO pio = pio_instances[pio_index]; + PIO pio = pio_get_instance(pio_index); for (size_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) { if (!_interrupt_handler[pio_index][sm]) { continue; @@ -971,16 +1163,49 @@ uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self) { return _current_program_offset[pio_index][sm]; } -bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, const sm_buf_info *once, const sm_buf_info *loop, uint8_t stride_in_bytes, bool swap) { +bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t *self, uint8_t stride_in_bytes, bool swap) { + uint8_t pio_index = pio_get_index(self->pio); uint8_t sm = self->state_machine; - int pending_buffers = (once->info.len != 0) + (loop->info.len != 0); - if (!once->info.len) { - once = loop; + self->switched_write_buffers = false; + + int pending_buffers_write = (self->once_write_buf_info.info.len != 0) + (self->loop_write_buf_info.info.len != 0) + (self->loop2_write_buf_info.info.len != 0); + + // If all buffer arguments have nonzero length, write once_write_buf, loop_write_buf, loop2_write_buf and repeat last two forever + + if (!(self->once_write_buf_info.info.len)) { + if (!self->loop_write_buf_info.info.len) { + // If once_write_buf and loop_write_buf have zero length, write loop2_write_buf forever + self->once_write_buf_info = self->loop2_write_buf_info; + self->loop_write_buf_info = self->loop2_write_buf_info; + } else { + if (!(self->loop2_write_buf_info.info.len)) { + // If once_write_buf and loop2_write_buf have zero length, write loop_write_buf forever + self->once_write_buf_info = self->loop_write_buf_info; + self->loop2_write_buf_info = self->loop_write_buf_info; + } else { + // If only once_write_buf has zero length, write loop_write_buf, loop2_write_buf, and repeat last two forever + self->once_write_buf_info = self->loop_write_buf_info; + self->loop_write_buf_info = self->loop2_write_buf_info; + self->loop2_write_buf_info = self->once_write_buf_info; + } + } + } else { + if (!(self->loop_write_buf_info.info.len)) { + // If once_write_buf has nonzero length and loop_write_buf has zero length, write once_write_buf, loop2_write_buf and repeat last buf forever + self->loop_write_buf_info = self->loop2_write_buf_info; + } else { + if (!self->loop2_write_buf_info.info.len) { + // If once_write_buf has nonzero length and loop2_write_buf have zero length, write once_write_buf, loop_write_buf and repeat last buf forever + self->loop2_write_buf_info = self->loop_write_buf_info; + } + } } - if (SM_DMA_ALLOCATED(pio_index, sm)) { + // if DMA is already going (i.e. this is not the first call to background_write), + // block until once_write_buf and loop_write_buf have each been written at least once + if (SM_DMA_ALLOCATED_WRITE(pio_index, sm)) { if (stride_in_bytes != self->background_stride_in_bytes) { mp_raise_ValueError(MP_ERROR_TEXT("Mismatched data size")); } @@ -988,7 +1213,7 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t * mp_raise_ValueError(MP_ERROR_TEXT("Mismatched swap flag")); } - while (self->pending_buffers) { + while (self->pending_buffers_write) { RUN_BACKGROUND_TASKS; if (self->user_interruptible && mp_hal_is_interrupted()) { return false; @@ -996,13 +1221,14 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t * } common_hal_mcu_disable_interrupts(); - self->once = *once; - self->loop = *loop; - self->pending_buffers = pending_buffers; - - if (self->dma_completed && self->once.info.len) { - rp2pio_statemachine_dma_complete(self, SM_DMA_GET_CHANNEL(pio_index, sm)); - self->dma_completed = false; + self->next_write_buf_1 = self->once_write_buf_info; + self->next_write_buf_2 = self->loop_write_buf_info; + self->next_write_buf_3 = self->loop2_write_buf_info; + self->pending_buffers_write = pending_buffers_write; + + if (self->dma_completed_write && self->next_write_buf_1.info.len) { + rp2pio_statemachine_dma_complete_write(self, SM_DMA_GET_CHANNEL_WRITE(pio_index, sm)); + self->dma_completed_write = false; } common_hal_mcu_enable_interrupts(); @@ -1010,84 +1236,301 @@ bool common_hal_rp2pio_statemachine_background_write(rp2pio_statemachine_obj_t * return true; } - int channel = dma_claim_unused_channel(false); - if (channel == -1) { + int channel_write = dma_claim_unused_channel(false); + if (channel_write == -1) { return false; } - SM_DMA_SET_CHANNEL(pio_index, sm, channel); + SM_DMA_SET_CHANNEL_WRITE(pio_index, sm, channel_write); volatile uint8_t *tx_destination = (volatile uint8_t *)&self->pio->txf[self->state_machine]; self->tx_dreq = pio_get_dreq(self->pio, self->state_machine, true); - dma_channel_config c; + dma_channel_config c_write; + + self->current_write_buf = self->once_write_buf_info; + self->next_write_buf_1 = self->loop_write_buf_info; + self->next_write_buf_2 = self->loop2_write_buf_info; + self->next_write_buf_3 = self->loop_write_buf_info; + + self->pending_buffers_write = pending_buffers_write; + self->dma_completed_write = false; - self->current = *once; - self->once = *loop; - self->loop = *loop; - self->pending_buffers = pending_buffers; - self->dma_completed = false; self->background_stride_in_bytes = stride_in_bytes; self->byteswap = swap; - c = dma_channel_get_default_config(channel); - channel_config_set_transfer_data_size(&c, _stride_to_dma_size(stride_in_bytes)); - channel_config_set_dreq(&c, self->tx_dreq); - channel_config_set_read_increment(&c, true); - channel_config_set_write_increment(&c, false); - channel_config_set_bswap(&c, swap); - dma_channel_configure(channel, &c, + c_write = dma_channel_get_default_config(channel_write); + channel_config_set_transfer_data_size(&c_write, _stride_to_dma_size(stride_in_bytes)); + channel_config_set_dreq(&c_write, self->tx_dreq); + channel_config_set_read_increment(&c_write, true); + channel_config_set_write_increment(&c_write, false); + channel_config_set_bswap(&c_write, swap); + dma_channel_configure(channel_write, &c_write, tx_destination, - once->info.buf, - once->info.len / stride_in_bytes, + self->once_write_buf_info.info.buf, + self->once_write_buf_info.info.len / stride_in_bytes, false); common_hal_mcu_disable_interrupts(); - MP_STATE_PORT(background_pio)[channel] = self; - dma_hw->inte0 |= 1u << channel; + + // Acknowledge any previous pending interrupt + dma_hw->ints0 |= 1u << channel_write; + MP_STATE_PORT(background_pio_write)[channel_write] = self; + dma_hw->inte0 |= 1u << channel_write; + irq_set_mask_enabled(1 << DMA_IRQ_0, true); - dma_start_channel_mask(1u << channel); + dma_start_channel_mask(1u << channel_write); common_hal_mcu_enable_interrupts(); return true; } -void rp2pio_statemachine_dma_complete(rp2pio_statemachine_obj_t *self, int channel) { - self->current = self->once; - self->once = self->loop; +void rp2pio_statemachine_dma_complete_write(rp2pio_statemachine_obj_t *self, int channel_write) { + self->current_write_buf = self->next_write_buf_1; + self->next_write_buf_1 = self->next_write_buf_2; + self->next_write_buf_2 = self->next_write_buf_3; + self->next_write_buf_3 = self->next_write_buf_1; - if (self->current.info.buf) { - if (self->pending_buffers > 0) { - self->pending_buffers--; + if (self->current_write_buf.info.buf) { + if (self->pending_buffers_write > 0) { + self->pending_buffers_write--; } - dma_channel_set_read_addr(channel, self->current.info.buf, false); - dma_channel_set_trans_count(channel, self->current.info.len / self->background_stride_in_bytes, true); + dma_channel_set_read_addr(channel_write, self->current_write_buf.info.buf, false); + dma_channel_set_trans_count(channel_write, self->current_write_buf.info.len / self->background_stride_in_bytes, true); } else { - self->dma_completed = true; - self->pending_buffers = 0; // should be a no-op + self->dma_completed_write = true; + self->pending_buffers_write = 0; // should be a no-op } + + self->switched_write_buffers = true; } bool common_hal_rp2pio_statemachine_stop_background_write(rp2pio_statemachine_obj_t *self) { uint8_t pio_index = pio_get_index(self->pio); uint8_t sm = self->state_machine; - rp2pio_statemachine_clear_dma(pio_index, sm); - memset(&self->current, 0, sizeof(self->current)); - memset(&self->once, 0, sizeof(self->once)); - memset(&self->loop, 0, sizeof(self->loop)); - self->pending_buffers = 0; + rp2pio_statemachine_clear_dma_write(pio_index, sm); + memset(&self->current_write_buf, 0, sizeof(self->current_write_buf)); + memset(&self->next_write_buf_1, 0, sizeof(self->next_write_buf_1)); + memset(&self->next_write_buf_2, 0, sizeof(self->next_write_buf_2)); + memset(&self->next_write_buf_3, 0, sizeof(self->next_write_buf_3)); + self->pending_buffers_write = 0; return true; } bool common_hal_rp2pio_statemachine_get_writing(rp2pio_statemachine_obj_t *self) { - return !self->dma_completed; + return !self->dma_completed_write; +} + +int common_hal_rp2pio_statemachine_get_pending_write(rp2pio_statemachine_obj_t *self) { + return self->pending_buffers_write; +} + +// ================================================================================= + +bool common_hal_rp2pio_statemachine_background_read(rp2pio_statemachine_obj_t *self, uint8_t stride_in_bytes, bool swap) { + + uint8_t pio_index = pio_get_index(self->pio); + uint8_t sm = self->state_machine; + + self->switched_read_buffers = false; + + int pending_buffers_read = (self->once_read_buf_info.info.len != 0) + (self->loop_read_buf_info.info.len != 0) + (self->loop2_read_buf_info.info.len != 0); + + // If all buffer arguments have nonzero length, read once_read_buf, loop_read_buf, loop2_read_buf and repeat last two forever + + if (!(self->once_read_buf_info.info.len)) { + if (!(self->loop_read_buf_info.info.len)) { + // If once_read_buf and loop_read_buf have zero length, read loop2_read_buf forever + self->once_read_buf_info = self->loop2_read_buf_info; + self->loop_read_buf_info = self->loop2_read_buf_info; + } else { + if (!(self->loop2_read_buf_info.info.len)) { + // If once_read_buf and loop2_read_buf have zero length, read loop_read_buf forever + self->once_read_buf_info = self->loop_read_buf_info; + self->loop2_read_buf_info = self->loop_read_buf_info; + } else { + // If only once_read_buf has zero length, read loop_read_buf, loop2_read_buf, and repeat last two forever + self->once_read_buf_info = self->loop_read_buf_info; + self->loop_read_buf_info = self->loop2_read_buf_info; + self->loop2_read_buf_info = self->once_read_buf_info; + } + } + } else { + if (!(self->loop_read_buf_info.info.len)) { + // If once_read_buf has nonzero length and loop_read_buf has zero length, read once_read_buf, loop2_read_buf and repeat last buf forever + self->loop_read_buf_info = self->loop2_read_buf_info; + } else { + if (!(self->loop2_read_buf_info.info.len)) { + // If once_read_buf has nonzero length and loop2_read_buf have zero length, read once_read_buf, loop_read_buf and repeat last buf forever + self->loop2_read_buf_info = self->loop_read_buf_info; + + } + } + } + + if (SM_DMA_ALLOCATED_READ(pio_index, sm)) { + if (stride_in_bytes != self->background_stride_in_bytes) { + mp_raise_ValueError(MP_ERROR_TEXT("Mismatched data size")); + } + if (swap != self->byteswap) { + mp_raise_ValueError(MP_ERROR_TEXT("Mismatched swap flag")); + } + + while (self->pending_buffers_read) { + RUN_BACKGROUND_TASKS; + if (self->user_interruptible && mp_hal_is_interrupted()) { + return false; + } + } + + common_hal_mcu_disable_interrupts(); + self->next_read_buf_1 = self->once_read_buf_info; + self->next_read_buf_2 = self->loop_read_buf_info; + self->next_read_buf_3 = self->loop2_read_buf_info; + self->pending_buffers_read = pending_buffers_read; + + if (self->dma_completed_read && self->next_read_buf_1.info.len) { + rp2pio_statemachine_dma_complete_read(self, SM_DMA_GET_CHANNEL_READ(pio_index, sm)); + self->dma_completed_read = false; + } + + common_hal_mcu_enable_interrupts(); + + return true; + } + + int channel_read = dma_claim_unused_channel(false); + if (channel_read == -1) { + return false; + } + SM_DMA_SET_CHANNEL_READ(pio_index, sm, channel_read); + + // set up receive DMA + + volatile uint8_t *rx_source = (volatile uint8_t *)&self->pio->rxf[self->state_machine]; + + self->rx_dreq = pio_get_dreq(self->pio, self->state_machine, false); + + dma_channel_config c_read; + + self->current_read_buf = self->once_read_buf_info; + self->next_read_buf_1 = self->loop_read_buf_info; + self->next_read_buf_2 = self->loop2_read_buf_info; + self->next_read_buf_3 = self->loop_read_buf_info; + + self->pending_buffers_read = pending_buffers_read; + self->dma_completed_read = false; + + self->background_stride_in_bytes = stride_in_bytes; + self->byteswap = swap; + + c_read = dma_channel_get_default_config(channel_read); + channel_config_set_transfer_data_size(&c_read, _stride_to_dma_size(stride_in_bytes)); + channel_config_set_dreq(&c_read, self->rx_dreq); + channel_config_set_read_increment(&c_read, false); + channel_config_set_write_increment(&c_read, true); + channel_config_set_bswap(&c_read, swap); + dma_channel_configure(channel_read, &c_read, + self->once_read_buf_info.info.buf, + rx_source, + self->once_read_buf_info.info.len / stride_in_bytes, + false); + + common_hal_mcu_disable_interrupts(); + // Acknowledge any previous pending interrupt + dma_hw->ints0 |= 1u << channel_read; + MP_STATE_PORT(background_pio_read)[channel_read] = self; + dma_hw->inte0 |= 1u << channel_read; + irq_set_mask_enabled(1 << DMA_IRQ_0, true); + dma_start_channel_mask((1u << channel_read)); + common_hal_mcu_enable_interrupts(); + + return true; +} + +void rp2pio_statemachine_dma_complete_read(rp2pio_statemachine_obj_t *self, int channel_read) { + + self->current_read_buf = self->next_read_buf_1; + self->next_read_buf_1 = self->next_read_buf_2; + self->next_read_buf_2 = self->next_read_buf_3; + self->next_read_buf_3 = self->next_read_buf_1; + + if (self->current_read_buf.info.buf) { + if (self->pending_buffers_read > 0) { + self->pending_buffers_read--; + } + dma_channel_set_write_addr(channel_read, self->current_read_buf.info.buf, false); + dma_channel_set_trans_count(channel_read, self->current_read_buf.info.len / self->background_stride_in_bytes, true); + } else { + self->dma_completed_read = true; + self->pending_buffers_read = 0; // should be a no-op + } + + self->switched_read_buffers = true; +} + +bool common_hal_rp2pio_statemachine_stop_background_read(rp2pio_statemachine_obj_t *self) { + uint8_t pio_index = pio_get_index(self->pio); + uint8_t sm = self->state_machine; + rp2pio_statemachine_clear_dma_read(pio_index, sm); + memset(&self->current_read_buf, 0, sizeof(self->current_read_buf)); + memset(&self->next_read_buf_1, 0, sizeof(self->next_read_buf_1)); + memset(&self->next_read_buf_2, 0, sizeof(self->next_read_buf_2)); + memset(&self->next_read_buf_3, 0, sizeof(self->next_read_buf_3)); + self->pending_buffers_read = 0; + return true; } -int common_hal_rp2pio_statemachine_get_pending(rp2pio_statemachine_obj_t *self) { - return self->pending_buffers; +bool common_hal_rp2pio_statemachine_get_reading(rp2pio_statemachine_obj_t *self) { + return !self->dma_completed_read; } +int common_hal_rp2pio_statemachine_get_pending_read(rp2pio_statemachine_obj_t *self) { + return self->pending_buffers_read; +} + +int common_hal_rp2pio_statemachine_get_offset(rp2pio_statemachine_obj_t *self) { + uint8_t pio_index = pio_get_index(self->pio); + uint8_t sm = self->state_machine; + uint8_t offset = _current_program_offset[pio_index][sm]; + return offset; +} + +int common_hal_rp2pio_statemachine_get_pc(rp2pio_statemachine_obj_t *self) { + uint8_t pio_index = pio_get_index(self->pio); + PIO pio = pio_get_instance(pio_index); + uint8_t sm = self->state_machine; + return pio_sm_get_pc(pio, sm); +} + +mp_obj_t common_hal_rp2pio_statemachine_get_rxfifo(rp2pio_statemachine_obj_t *self) { + #if PICO_PIO_VERSION > 0 + if (self->rxfifo_obj.base.type) { + return MP_OBJ_FROM_PTR(&self->rxfifo_obj); + } + #endif + return mp_const_none; +} + +mp_obj_t common_hal_rp2pio_statemachine_get_last_read(rp2pio_statemachine_obj_t *self) { + if (self->switched_read_buffers) { + self->switched_read_buffers = false; + return self->next_read_buf_1.obj; + } + return mp_const_empty_bytes; +} + +mp_obj_t common_hal_rp2pio_statemachine_get_last_write(rp2pio_statemachine_obj_t *self) { + if (self->switched_write_buffers) { + self->switched_write_buffers = false; + return self->next_write_buf_1.obj; + } + return mp_const_empty_bytes; +} + + // Use a compile-time constant for MP_REGISTER_POINTER so the preprocessor will // not split the expansion across multiple lines. -MP_REGISTER_ROOT_POINTER(mp_obj_t background_pio[enum_NUM_DMA_CHANNELS]); +MP_REGISTER_ROOT_POINTER(mp_obj_t background_pio_read[enum_NUM_DMA_CHANNELS]); +MP_REGISTER_ROOT_POINTER(mp_obj_t background_pio_write[enum_NUM_DMA_CHANNELS]); diff --git a/ports/raspberrypi/common-hal/rp2pio/StateMachine.h b/ports/raspberrypi/common-hal/rp2pio/StateMachine.h index fcb86f783ac12..c7ef12e1b0177 100644 --- a/ports/raspberrypi/common-hal/rp2pio/StateMachine.h +++ b/ports/raspberrypi/common-hal/rp2pio/StateMachine.h @@ -9,26 +9,101 @@ #include "py/obj.h" #include "common-hal/microcontroller/Pin.h" -#include "src/rp2_common/hardware_pio/include/hardware/pio.h" +#include "common-hal/memorymap/AddressRange.h" +#include "hardware/pio.h" + +// pio_pinmask_t can hold ANY pin masks, so it is used before selection of gpiobase +#if NUM_BANK0_GPIOS > 32 +typedef struct { uint64_t value; +} pio_pinmask_t; +typedef uint64_t pio_pinmask_value_t; +#define PIO_PINMASK_C(c) UINT64_C(c) +#define PIO_PINMASK_BIT (64) +#define PIO_PINMASK(i) (UINT64_C(1) << (i)) +#define PIO_PINMASK_PRINT(p) mp_printf(&mp_plat_print, \ + "%s:%d: %s = %08x %08x\n", \ + __FILE__, __LINE__, #p, \ + (uint32_t)(PIO_PINMASK_VALUE(p) >> 32), \ + (uint32_t)PIO_PINMASK_VALUE(p)); +#define PIO_PINMASK_ALL PIO_PINMASK_FROM_VALUE(~UINT64_C(0)) +#else +typedef struct { uint32_t value; +} pio_pinmask_t; +typedef uint32_t pio_pinmask_value_t; +#define PIO_PINMASK_C(c) UINT32_C(c) +#define PIO_PINMASK_BIT (32) +#define PIO_PINMASK(i) (UINT32_C(1) << (i)) +#define PIO_PINMASK_PRINT(p) mp_printf(&mp_plat_print, "%s:%d: %s = %08x\n", \ + __FILE__, __LINE__, #p, \ + (uint32_t)(PIO_PINMASK_VALUE(p))); +#define PIO_PINMASK_ALL PIO_PINMASK_FROM_VALUE(~UINT32_C(0)) +#endif +#define PIO_PINMASK_VALUE(p) ((p).value) +#define PIO_PINMASK_FROM_VALUE(v) ((pio_pinmask_t) {(v)}) +#define PIO_PINMASK_FROM_PIN(i) ((pio_pinmask_t) {(PIO_PINMASK(i))}) +#define PIO_PINMASK_NONE PIO_PINMASK_FROM_VALUE(0) +#define PIO_PINMASK_SET(p, i) ((p).value |= PIO_PINMASK(i)) +#define PIO_PINMASK_CLEAR(p, i) ((p).value &= ~PIO_PINMASK(i)) +#define PIO_PINMASK_IS_SET(p, i) (((p).value & PIO_PINMASK(i)) != 0) +#define PIO_PINMASK_BINOP(op, p, q) PIO_PINMASK_FROM_VALUE((p).value op(q).value) +#define PIO_PINMASK_BINOP_ASSIGN(op, p, q) ((p).value op(q).value) +#define PIO_PINMASK_EQUAL(p, q) ((p).value == (q).value) +#define PIO_PINMASK_AND(p, q) PIO_PINMASK_BINOP(&, (p), (q)) +#define PIO_PINMASK_AND_NOT(p, q) PIO_PINMASK_BINOP(&~, (p), (q)) +#define PIO_PINMASK_OR(p, q) PIO_PINMASK_BINOP(|, (p), (q)) +#define PIO_PINMASK_OR3(p, q, r) PIO_PINMASK_OR((p), PIO_PINMASK_OR((q), (r))) +#define PIO_PINMASK_INTERSECT(p, q) PIO_PINMASK_BINOP_ASSIGN( &=, (p), (q)) +#define PIO_PINMASK_DIFFERENCE(p, q) PIO_PINMASK_BINOP_ASSIGN( &= ~, (p), (q)) +#define PIO_PINMASK_MERGE(p, q) PIO_PINMASK_BINOP_ASSIGN( |=, (p), (q)) + +// pio peripheral registers only work 32 bits at a time and depend on the selection of base +// (0 only on RP2040 & RP2350A; 0 or 16 on RP2350B) +typedef struct { uint32_t value32; +} pio_pinmask32_t; +#define PIO_PINMASK32(i) (1u << (i)) +#define PIO_PINMASK32_C(c) UINT32_C(c) +#define PIO_PINMASK32_NONE PIO_PINMASK32_FROM_VALUE(0) +#define PIO_PINMASK32_ALL PIO_PINMASK32_FROM_VALUE(~UINT32_C(0)) +#define PIO_PINMASK32_BASE(i, base) PIO_PINMASK32((i) - (base)) +#define PIO_PINMASK32_VALUE(p) ((p).value32) +#define PIO_PINMASK32_FROM_VALUE(v) ((pio_pinmask32_t) {(v)}) +#define PIO_PINMASK32_SET(p, i) ((p).value32 |= PIO_PINMASK32_VALUE(i)) +#define PIO_PINMASK32_CLEAR(p, i) ((p).value32 &= ~PIO_PINMASK32_VALUE(i)) +#define PIO_PINMASK32_IS_SET(p, i) (((p).value32 & PIO_PINMASK32_VALUE(i)) != 0) +#define PIO_PINMASK32_BINOP(op, p, q) PIO_PINMASK32_FROM_VALUE((p).value32 op(q).value32) +#define PIO_PINMASK32_AND(p, q) PIO_PINMASK32_BINOP(&, (p), (q)) +#define PIO_PINMASK32_AND_NOT(p, q) PIO_PINMASK32_BINOP(&~, (p), (q)) +#define PIO_PINMASK32_OR(p, q) PIO_PINMASK32_BINOP(|, (p), (q)) +#define PIO_PINMASK32_OR3(p, q, r) PIO_PINMASK32_OR((p), PIO_PINMASK32_OR((q), (r))) +#define PIO_PINMASK32_INTERSECT(p, q) PIO_PINMASK32_BINOP( &=, (p), (q)) +#define PIO_PINMASK32_DIFFERENCE(p, q) PIO_PINMASK32_BINOP( &= ~, (p), (q)) +#define PIO_PINMASK32_MERGE(p, q) PIO_PINMASK32_BINOP( |=, (p), (q)) +#define PIO_PINMASK32_FROM_PINMASK_WITH_OFFSET(p, gpio_offset) PIO_PINMASK32_FROM_VALUE(PIO_PINMASK_VALUE((p)) >> (gpio_offset)) +#define PIO_PINMASK_FROM_PINMASK32_WITH_OFFSET(p, gpio_offset) PIO_PINMASK_FROM_VALUE(PIO_PINMASK32_VALUE((p)) << (gpio_offset)) enum { PIO_ANY_OFFSET = -1 }; +enum { PIO_FIFO_JOIN_AUTO = -1, PIO_FIFO_TYPE_DEFAULT = PIO_FIFO_JOIN_AUTO }; +enum { PIO_MOV_STATUS_DEFAULT = STATUS_TX_LESSTHAN }; +enum { PIO_MOV_N_DEFAULT = 0 }; typedef struct sm_buf_info { mp_obj_t obj; mp_buffer_info_t info; } sm_buf_info; +#define RP2PIO_STATEMACHINE_N_BUFS 3 + typedef struct { mp_obj_base_t base; - uint32_t pins; // Bitmask of what pins this state machine uses. + pio_pinmask32_t pins; // Bitmask of what pins this state machine uses. int state_machine; PIO pio; const uint16_t *init; size_t init_len; - uint32_t initial_pin_state; - uint32_t initial_pin_direction; - uint32_t pull_pin_up; - uint32_t pull_pin_down; + pio_pinmask_t initial_pin_state; + pio_pinmask_t initial_pin_direction; + pio_pinmask_t pull_pin_up; + pio_pinmask_t pull_pin_down; uint tx_dreq; uint rx_dreq; uint32_t actual_frequency; @@ -39,14 +114,32 @@ typedef struct { bool out_shift_right; bool in_shift_right; bool user_interruptible; + #if NUM_BANK0_GPIOS > 32 + uint8_t pio_gpio_offset; + #endif uint8_t offset; uint8_t fifo_depth; // Either 4 if FIFOs are not joined, or 8 if they are. // dma-related items - volatile int pending_buffers; - sm_buf_info current, once, loop; + volatile int pending_buffers_write; + volatile int pending_buffers_read; + int write_buf_index, read_buf_index; + sm_buf_info write_buf[RP2PIO_STATEMACHINE_N_BUFS]; + sm_buf_info read_buf[RP2PIO_STATEMACHINE_N_BUFS]; + + sm_buf_info once_read_buf_info, loop_read_buf_info, loop2_read_buf_info; + sm_buf_info current_read_buf, next_read_buf_1, next_read_buf_2, next_read_buf_3; + sm_buf_info once_write_buf_info, loop_write_buf_info, loop2_write_buf_info; + sm_buf_info current_write_buf, next_write_buf_1, next_write_buf_2, next_write_buf_3; + + bool switched_write_buffers, switched_read_buffers; + int background_stride_in_bytes; - bool dma_completed, byteswap; + bool dma_completed_write, byteswap; + bool dma_completed_read; + #if PICO_PIO_VERSION > 0 + memorymap_addressrange_obj_t rxfifo_obj; + #endif } rp2pio_statemachine_obj_t; void reset_rp2pio_statemachine(void); @@ -58,24 +151,28 @@ bool rp2pio_statemachine_construct(rp2pio_statemachine_obj_t *self, const uint16_t *init, size_t init_len, const mcu_pin_obj_t *first_out_pin, uint8_t out_pin_count, const mcu_pin_obj_t *first_in_pin, uint8_t in_pin_count, - uint32_t pull_pin_up, uint32_t pull_pin_down, + pio_pinmask_t pull_pin_up, pio_pinmask_t pull_pin_down, const mcu_pin_obj_t *first_set_pin, uint8_t set_pin_count, - const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, - uint32_t initial_pin_state, uint32_t initial_pin_direction, + const mcu_pin_obj_t *first_sideset_pin, uint8_t sideset_pin_count, bool sideset_pindirs, + pio_pinmask_t initial_pin_state, pio_pinmask_t initial_pin_direction, const mcu_pin_obj_t *jmp_pin, - uint32_t pins_we_use, bool tx_fifo, bool rx_fifo, + pio_pinmask_t pins_we_use, bool tx_fifo, bool rx_fifo, bool auto_pull, uint8_t pull_threshold, bool out_shift_right, bool wait_for_txstall, bool auto_push, uint8_t push_threshold, bool in_shift_right, bool claim_pins, bool interruptible, bool sideset_enable, - int wrap_target, int wrap, int offset); + int wrap_target, int wrap, int offset, + int fifo_type, + int mov_status_type, int mov_status_n + ); uint8_t rp2pio_statemachine_program_offset(rp2pio_statemachine_obj_t *self); void rp2pio_statemachine_deinit(rp2pio_statemachine_obj_t *self, bool leave_pins); -void rp2pio_statemachine_dma_complete(rp2pio_statemachine_obj_t *self, int channel); +void rp2pio_statemachine_dma_complete_write(rp2pio_statemachine_obj_t *self, int channel); +void rp2pio_statemachine_dma_complete_read(rp2pio_statemachine_obj_t *self, int channel); void rp2pio_statemachine_reset_ok(PIO pio, int sm); void rp2pio_statemachine_never_reset(PIO pio, int sm); diff --git a/ports/raspberrypi/common-hal/rtc/RTC.c b/ports/raspberrypi/common-hal/rtc/RTC.c index 3bdf599d2701f..67935502ad322 100644 --- a/ports/raspberrypi/common-hal/rtc/RTC.c +++ b/ports/raspberrypi/common-hal/rtc/RTC.c @@ -11,8 +11,8 @@ #include "py/runtime.h" #include "shared/timeutils/timeutils.h" -#include "src/common/pico_util/include/pico/util/datetime.h" -#include "src/rp2_common/pico_aon_timer/include/pico/aon_timer.h" +#include "pico/util/datetime.h" +#include "pico/aon_timer.h" void common_hal_rtc_init(void) { // We start the RTC at 0 which mark as January 1, 2000. diff --git a/ports/raspberrypi/common-hal/socketpool/Socket.c b/ports/raspberrypi/common-hal/socketpool/Socket.c index 84d8bbd5149e0..0543fd53dc3e5 100644 --- a/ports/raspberrypi/common-hal/socketpool/Socket.c +++ b/ports/raspberrypi/common-hal/socketpool/Socket.c @@ -35,7 +35,7 @@ #include "lwip/timeouts.h" #include "lwip/udp.h" -#include "sdk/src/rp2_common/pico_cyw43_arch/include/pico/cyw43_arch.h" +#include "pico/cyw43_arch.h" mp_obj_t socketpool_ip_addr_to_str(const ip_addr_t *addr) { char ip_str[IPADDR_STRLEN_MAX]; // big enough for any supported address type @@ -89,7 +89,7 @@ static mp_obj_t socketpool_ip_addr_and_port_to_tuple(const ip_addr_t *addr, int // socket API. // Extension to lwIP error codes -// Matches lwIP 2.0.3 +// Matches lwIP 2.2.1 #undef _ERR_BADF #define _ERR_BADF -17 static const int error_lookup_table[] = { @@ -251,7 +251,7 @@ static void _lwip_tcp_err_unaccepted(void *arg, err_t err) { // because it's only ever used by lwIP if tcp_connect is called on the TCP PCB. socketpool_socket_obj_t *socket = (socketpool_socket_obj_t *)pcb->connected; - // Array is not volatile because thiss callback is executed within the lwIP context + // Array is not volatile because this callback is executed within the lwIP context uint8_t alloc = socket->incoming.connection.alloc; struct tcp_pcb **tcp_array = (struct tcp_pcb **)lwip_socket_incoming_array(socket); @@ -473,7 +473,12 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, MICROPY_PY_LWIP_ENTER - u16_t available = tcp_sndbuf(socket->pcb.tcp); + // If the socket is still connecting then don't let data be written to it. + // Otherwise, get the number of available bytes in the output buffer. + u16_t available = 0; + if (socket->state != STATE_CONNECTING) { + available = tcp_sndbuf(socket->pcb.tcp); + } if (available == 0) { // Non-blocking socket @@ -490,7 +495,8 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, // If peer fully closed socket, we would have socket->state set to ERR_RST (connection // reset) by error callback. // Avoid sending too small packets, so wait until at least 16 bytes available - while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) { + while (socket->state == STATE_CONNECTING + || (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16)) { MICROPY_PY_LWIP_EXIT if (socket->timeout != (unsigned)-1 && mp_hal_ticks_ms() - start > socket->timeout) { *_errno = MP_ETIMEDOUT; @@ -531,9 +537,10 @@ static mp_uint_t lwip_tcp_send(socketpool_socket_obj_t *socket, const byte *buf, MICROPY_PY_LWIP_REENTER } - // If the output buffer is getting full then send the data to the lower layers - if (err == ERR_OK && tcp_sndbuf(socket->pcb.tcp) < TCP_SND_BUF / 4) { - err = tcp_output(socket->pcb.tcp); + // Use nagle algorithm to determine when to send segment buffer (can be + // disabled with TCP_NODELAY socket option) + if (err == ERR_OK) { + err = tcp_output_nagle(socket->pcb.tcp); } MICROPY_PY_LWIP_EXIT @@ -551,6 +558,12 @@ static mp_uint_t lwip_tcp_receive(socketpool_socket_obj_t *socket, byte *buf, mp // Check for any pending errors STREAM_ERROR_CHECK(socket); + if (socket->state == STATE_LISTENING) { + // original socket in listening state, not the accepted connection. + *_errno = MP_ENOTCONN; + return -1; + } + if (socket->incoming.pbuf == NULL) { // Non-blocking socket @@ -746,8 +759,7 @@ socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_ mp_raise_NotImplementedError(MP_ERROR_TEXT("Only IPv4 sockets supported")); } - socketpool_socket_obj_t *socket = m_new_obj_with_finaliser(socketpool_socket_obj_t); - socket->base.type = &socketpool_socket_type; + socketpool_socket_obj_t *socket = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, &socketpool_socket_type); if (!socketpool_socket(self, family, type, proto, socket)) { mp_raise_RuntimeError(MP_ERROR_TEXT("Out of sockets")); @@ -849,7 +861,8 @@ socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_o mp_obj_t *peer_out) { // Create new socket object, do it here because we must not raise an out-of-memory // exception when the LWIP concurrency lock is held - socketpool_socket_obj_t *accepted = m_new_obj_with_finaliser(socketpool_socket_obj_t); + // Don't set the type field: socketpool_socket_reset() will do that when checking for already reset. + socketpool_socket_obj_t *accepted = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, NULL); socketpool_socket_reset(accepted); int ret = socketpool_socket_accept(socket, peer_out, accepted); @@ -1071,7 +1084,8 @@ bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *socket, int ba socket->incoming.connection.tcp.item = NULL; } else { socket->incoming.connection.alloc = backlog; - socket->incoming.connection.tcp.array = m_new0(struct tcp_pcb *, backlog); + socket->incoming.connection.tcp.array = m_malloc_without_collect(sizeof(struct tcp_pcb *) * backlog); + memset(socket->incoming.connection.tcp.array, 0, sizeof(struct tcp_pcb *) * backlog); } socket->incoming.connection.iget = 0; socket->incoming.connection.iput = 0; diff --git a/ports/raspberrypi/common-hal/usb_host/Port.c b/ports/raspberrypi/common-hal/usb_host/Port.c index 5fb4506a145ef..b8a49725030ea 100644 --- a/ports/raspberrypi/common-hal/usb_host/Port.c +++ b/ports/raspberrypi/common-hal/usb_host/Port.c @@ -11,17 +11,16 @@ #include "supervisor/shared/serial.h" #include "supervisor/usb.h" -#include "src/common/pico_time/include/pico/time.h" +#include "pico/time.h" +#include "hardware/structs/mpu.h" #ifdef PICO_RP2040 -#include "src/rp2040/hardware_structs/include/hardware/structs/mpu.h" -#include "src/rp2_common/cmsis/stub/CMSIS/Device/RP2040/Include/RP2040.h" +#include "RP2040.h" // (cmsis) #endif #ifdef PICO_RP2350 -#include "src/rp2350/hardware_structs/include/hardware/structs/mpu.h" -#include "src/rp2_common/cmsis/stub/CMSIS/Device/RP2350/Include/RP2350.h" +#include "RP2350.h" // (cmsis) #endif -#include "src/rp2_common/hardware_dma/include/hardware/dma.h" -#include "src/rp2_common/pico_multicore/include/pico/multicore.h" +#include "hardware/dma.h" +#include "pico/multicore.h" #include "py/runtime.h" @@ -33,7 +32,6 @@ usb_host_port_obj_t usb_host_instance; -static PIO pio_instances[2] = {pio0, pio1}; volatile bool _core1_ready = false; static void __not_in_flash_func(core1_main)(void) { @@ -76,7 +74,7 @@ static void __not_in_flash_func(core1_main)(void) { } static uint8_t _sm_free_count(uint8_t pio_index) { - PIO pio = pio_instances[pio_index]; + PIO pio = pio_get_instance(pio_index); uint8_t free_count = 0; for (size_t j = 0; j < NUM_PIO_STATE_MACHINES; j++) { if (!pio_sm_is_claimed(pio, j)) { @@ -87,7 +85,7 @@ static uint8_t _sm_free_count(uint8_t pio_index) { } static bool _has_program_room(uint8_t pio_index, uint8_t program_size) { - PIO pio = pio_instances[pio_index]; + PIO pio = pio_get_instance(pio_index); pio_program_t program_struct = { .instructions = NULL, .length = program_size, @@ -96,8 +94,26 @@ static bool _has_program_room(uint8_t pio_index, uint8_t program_size) { return pio_can_add_program(pio, &program_struct); } +// As of 0.6.1, the PIO resource requirement is 1 PIO with 3 state machines & +// 32 instructions. Since there are only 32 instructions in a state machine, it should +// be impossible to have an allocated state machine but 32 instruction slots available; +// go ahead and check for it anyway. +// +// Since we check that ALL state machines are available, it's not possible for the GPIO +// ranges to mismatch on rp2350b +static size_t get_usb_pio(void) { + for (size_t i = 0; i < NUM_PIOS; i++) { + if (_has_program_room(i, 32) && _sm_free_count(i) == NUM_PIO_STATE_MACHINES) { + return i; + } + } + mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use")); +} + + usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp, const mcu_pin_obj_t *dm) { - if (dp->number + 1 != dm->number) { + if ((dp->number + 1 != dm->number) + && (dp->number - 1 != dm->number)) { raise_ValueError_invalid_pins(); } usb_host_port_obj_t *self = &usb_host_instance; @@ -116,39 +132,32 @@ usb_host_port_obj_t *common_hal_usb_host_port_construct(const mcu_pin_obj_t *dp, pio_usb_configuration_t pio_cfg = PIO_USB_DEFAULT_CONFIG; pio_cfg.skip_alarm_pool = true; pio_cfg.pin_dp = dp->number; - // Allocating the peripherals like this works on Pico W, where the - // "preferred PIO" for the cyw43 wifi chip is PIO 1. - pio_cfg.pio_tx_num = 1; // uses 22 instructions and 1 SM - pio_cfg.pio_rx_num = 0; // uses 31 instructions and 2 SM. - if (!_has_program_room(pio_cfg.pio_tx_num, 22) || _sm_free_count(pio_cfg.pio_tx_num) < 1 || - !_has_program_room(pio_cfg.pio_rx_num, 31) || _sm_free_count(pio_cfg.pio_rx_num) < 2) { - mp_raise_RuntimeError(MP_ERROR_TEXT("All state machines in use")); + if (dp->number - 1 == dm->number) { + pio_cfg.pinout = PIO_USB_PINOUT_DMDP; } - pio_cfg.tx_ch = dma_claim_unused_channel(false); // DMA channel - if (pio_cfg.tx_ch < 0) { + pio_cfg.pio_tx_num = get_usb_pio(); + pio_cfg.pio_rx_num = pio_cfg.pio_tx_num; + int dma_ch = dma_claim_unused_channel(false); + if (dma_ch < 0) { mp_raise_RuntimeError(MP_ERROR_TEXT("All dma channels in use")); } + pio_cfg.tx_ch = dma_ch; self->base.type = &usb_host_port_type; self->dp = dp; self->dm = dm; + claim_pin(dp); + claim_pin(dm); - PIO tx_pio = pio_instances[pio_cfg.pio_tx_num]; - pio_cfg.sm_tx = pio_claim_unused_sm(tx_pio, false); - PIO rx_pio = pio_instances[pio_cfg.pio_rx_num]; - pio_cfg.sm_rx = pio_claim_unused_sm(rx_pio, false); - pio_cfg.sm_eop = pio_claim_unused_sm(rx_pio, false); + PIO pio = pio_get_instance(pio_cfg.pio_tx_num); // Unclaim everything so that the library can. dma_channel_unclaim(pio_cfg.tx_ch); - pio_sm_unclaim(tx_pio, pio_cfg.sm_tx); - pio_sm_unclaim(rx_pio, pio_cfg.sm_rx); - pio_sm_unclaim(rx_pio, pio_cfg.sm_eop); // Set all of the state machines to never reset. - rp2pio_statemachine_never_reset(tx_pio, pio_cfg.sm_tx); - rp2pio_statemachine_never_reset(rx_pio, pio_cfg.sm_rx); - rp2pio_statemachine_never_reset(rx_pio, pio_cfg.sm_eop); + rp2pio_statemachine_never_reset(pio, pio_cfg.sm_tx); + rp2pio_statemachine_never_reset(pio, pio_cfg.sm_rx); + rp2pio_statemachine_never_reset(pio, pio_cfg.sm_eop); common_hal_never_reset_pin(dp); common_hal_never_reset_pin(dm); diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c index 3250ed4d7c7f9..73e7794ecc2dc 100644 --- a/ports/raspberrypi/common-hal/wifi/Radio.c +++ b/ports/raspberrypi/common-hal/wifi/Radio.c @@ -5,6 +5,7 @@ // SPDX-License-Identifier: MIT #include "supervisor/port.h" +#include "shared-bindings/wifi/PowerManagement.h" #include "shared-bindings/wifi/Radio.h" #include "shared-bindings/wifi/Network.h" @@ -47,7 +48,7 @@ static inline void nw_put_le32(uint8_t *buf, uint32_t x) { buf[3] = x >> 24; } -NORETURN static void ro_attribute(qstr attr) { +MP_NORETURN static void ro_attribute(qstr attr) { mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q is read-only for this board"), attr); } @@ -107,6 +108,41 @@ void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t cyw43_ioctl(&cyw43_state, CYW43_IOCTL_SET_VAR, 9 + 4, buf, CYW43_ITF_AP); } +wifi_power_management_t common_hal_wifi_radio_get_power_management(wifi_radio_obj_t *self) { + uint32_t pm_value = cyw43_get_power_management_value(); + + switch (pm_value) { + case CONST_CYW43_PERFORMANCE_PM: + return POWER_MANAGEMENT_MIN; + case CONST_CYW43_AGGRESSIVE_PM: + return POWER_MANAGEMENT_MAX; + case CONST_CYW43_NONE_PM: + return POWER_MANAGEMENT_NONE; + default: + return POWER_MANAGEMENT_UNKNOWN; + } +} + + +void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_power_management_t power_management) { + uint32_t pm_setting = CONST_CYW43_DEFAULT_PM; + switch (power_management) { + case POWER_MANAGEMENT_MIN: + pm_setting = CONST_CYW43_PERFORMANCE_PM; + break; + case POWER_MANAGEMENT_MAX: + pm_setting = CONST_CYW43_AGGRESSIVE_PM; + break; + case POWER_MANAGEMENT_NONE: + pm_setting = CONST_CYW43_NONE_PM; + break; + default: + // Should not get here. + break; + } + cyw43_set_power_management_value(pm_setting); +} + mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) { return common_hal_wifi_radio_get_mac_address(self); } @@ -121,7 +157,7 @@ mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, u mp_raise_RuntimeError(MP_ERROR_TEXT("Already scanning for wifi networks")); } if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } wifi_scannednetworks_obj_t *scan = mp_obj_malloc(wifi_scannednetworks_obj_t, &wifi_scannednetworks_type); mp_obj_t args[] = { mp_const_empty_tuple, MP_OBJ_NEW_SMALL_INT(16) }; @@ -157,7 +193,7 @@ void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) { void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint32_t authmode, uint8_t max_connections) { if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } /* TODO: If the AP is stopped once it cannot be restarted. @@ -207,7 +243,7 @@ bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) { void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } cyw43_arch_disable_ap_mode(); @@ -285,7 +321,7 @@ static bool connection_unchanged(wifi_radio_obj_t *self, const uint8_t *ssid, si wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) { if (!common_hal_wifi_radio_get_enabled(self)) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Wifi is not enabled")); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); } if (ssid_len > 32) { @@ -574,7 +610,7 @@ void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_ob addr.addr = IPADDR_NONE; } else { mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL); - socketpool_resolve_host_raise(dns_addr_obj, &addr); + socketpool_resolve_host_raise(mp_obj_str_get_str(dns_addr_obj), &addr); } dns_setserver(0, &addr); } diff --git a/ports/raspberrypi/common-hal/wifi/__init__.h b/ports/raspberrypi/common-hal/wifi/__init__.h index 73988e8437987..4005c48a3cde2 100644 --- a/ports/raspberrypi/common-hal/wifi/__init__.h +++ b/ports/raspberrypi/common-hal/wifi/__init__.h @@ -11,7 +11,7 @@ #include "lwip/ip_addr.h" void wifi_reset(void); -NORETURN void raise_cyw_error(int err); +MP_NORETURN void raise_cyw_error(int err); #define CHECK_CYW_RESULT(x) do { int res = (x); if (res != 0) raise_cyw_error(res); } while (0) void ipaddress_ipaddress_to_lwip(mp_obj_t ip_address, ip_addr_t *lwip_ip_address); diff --git a/ports/raspberrypi/cyw43_configport.h b/ports/raspberrypi/cyw43_configport.h index 62666bee42c23..c1769436ae497 100644 --- a/ports/raspberrypi/cyw43_configport.h +++ b/ports/raspberrypi/cyw43_configport.h @@ -12,7 +12,7 @@ #include "supervisor/port.h" -#include "sdk/src/rp2_common/pico_cyw43_driver/include/cyw43_configport.h" +#include_next "cyw43_configport.h" #define CYW43_NETUTILS (1) diff --git a/ports/raspberrypi/gen_stage2.py b/ports/raspberrypi/gen_stage2.py index 759384e17f3be..005994dc107c7 100644 --- a/ports/raspberrypi/gen_stage2.py +++ b/ports/raspberrypi/gen_stage2.py @@ -45,8 +45,6 @@ def all_match(nvms, key, default=None): quad_ok = quad_enable_status_byte is not None and quad_enable_bit_mask is not None - max_clock_speed_mhz = min((x.get("max_clock_speed_mhz", 1000) for x in flashes["nvm"])) - default_power_of_two = None for nvm in flashes["nvm"]: capacity = nvm.get("capacity", 0) diff --git a/ports/raspberrypi/lib/Pico-PIO-USB b/ports/raspberrypi/lib/Pico-PIO-USB index 0a14a34f7f31e..675543bcc9baa 160000 --- a/ports/raspberrypi/lib/Pico-PIO-USB +++ b/ports/raspberrypi/lib/Pico-PIO-USB @@ -1 +1 @@ -Subproject commit 0a14a34f7f31efb03c8435ade7f9f7122b19936c +Subproject commit 675543bcc9baa8170f868ab7ba316d418dbcf41f diff --git a/ports/raspberrypi/lib/cyw43-driver b/ports/raspberrypi/lib/cyw43-driver index 9f6405f0b3260..dd7568229f3bf 160000 --- a/ports/raspberrypi/lib/cyw43-driver +++ b/ports/raspberrypi/lib/cyw43-driver @@ -1 +1 @@ -Subproject commit 9f6405f0b3260968306d782e1c5ac275a46dc65d +Subproject commit dd7568229f3bf7a37737b9e1ef250c26efe75b23 diff --git a/ports/raspberrypi/lib/lwip b/ports/raspberrypi/lib/lwip index d26459c32c83a..bd522fde94093 160000 --- a/ports/raspberrypi/lib/lwip +++ b/ports/raspberrypi/lib/lwip @@ -1 +1 @@ -Subproject commit d26459c32c83aa14a6d4e30237d91cee36e0adbd +Subproject commit bd522fde9409398297b4e3244c92576b86ef16ec diff --git a/ports/raspberrypi/link-rp2040.ld b/ports/raspberrypi/link-rp2040.ld index 5f2798623db15..6e7bd15a7b644 100644 --- a/ports/raspberrypi/link-rp2040.ld +++ b/ports/raspberrypi/link-rp2040.ld @@ -84,7 +84,7 @@ SECTIONS *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *interp.o *divider.o *tusb_fifo.o *mem_ops_aeabi.o *usbh.o) .text*) /* Allow everything in usbh.o except tuh_task_event_ready because we read it from core 1. */ - *usbh.o (.text.[_uphc]* .text.tuh_[cmvied]* .text.tuh_task_ext*) + *usbh.o (.text.[_uphc]* .text.tuh_[cmved]* .text.tuh_task_ext*) *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) diff --git a/ports/raspberrypi/link-rp2350.ld b/ports/raspberrypi/link-rp2350.ld index 19f7f05253680..a2cc62909e638 100644 --- a/ports/raspberrypi/link-rp2350.ld +++ b/ports/raspberrypi/link-rp2350.ld @@ -65,7 +65,7 @@ SECTIONS *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a: *interp.o *divider.o *tusb_fifo.o *mem_ops_aeabi.o *usbh.o *string0.o) .text*) /* Allow everything in usbh.o except tuh_task_event_ready because we read it from core 1. */ - *usbh.o (.text.[_uphc]* .text.tuh_[cmvied]* .text.tuh_task_ext*) + *usbh.o (.text.[_uphc]* .text.tuh_[cmved]* .text.tuh_task_ext*) *(.fini) /* Pull all c'tors into .text */ *crtbegin.o(.ctors) diff --git a/ports/raspberrypi/lwip_inc/lwip_mem.h b/ports/raspberrypi/lwip_inc/lwip_mem.h new file mode 100644 index 0000000000000..3e5c91a8bb048 --- /dev/null +++ b/ports/raspberrypi/lwip_inc/lwip_mem.h @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +void *lwip_heap_malloc(size_t size); +void lwip_heap_free(void *ptr); +void *lwip_heap_calloc(size_t num, size_t size); diff --git a/ports/raspberrypi/lwip_inc/lwipopts.h b/ports/raspberrypi/lwip_inc/lwipopts.h index 06df7f13181d1..21d415fad214e 100644 --- a/ports/raspberrypi/lwip_inc/lwipopts.h +++ b/ports/raspberrypi/lwip_inc/lwipopts.h @@ -5,6 +5,8 @@ // Common settings used in most of the pico_w examples // (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details) +#include "lwip_mem.h" + // allow override in some examples #ifndef NO_SYS #define NO_SYS 1 @@ -20,14 +22,62 @@ #define MEM_LIBC_MALLOC 0 #endif #define MEM_ALIGNMENT 4 -#define MEM_SIZE 4000 -#define MEMP_NUM_TCP_SEG 32 -#define MEMP_NUM_ARP_QUEUE 10 -#define PBUF_POOL_SIZE 24 +// MEM_USE_POOLS: mem_malloc uses pools of fixed size memory blocks. Default is 0. +#define MEM_USE_POOLS 0 +// MEM_USE_POOLS_TRY_BIGGER_POOL: if one pool is empty, try the next bigger pool. Default is 0. +#define MEM_USE_POOLS_TRY_BIGGER_POOL 0 +// MEMP_USE_CUSTOM_POOLS: Use custom pools defined in lwippools.h. Default is 0. +#define MEMP_USE_CUSTOM_POOLS 0 +// MEMP_MEM_MALLOC: Use mem_malloc() for pool memory. Default is 0. +#define MEMP_MEM_MALLOC 1 +#define MEM_CUSTOM_ALLOCATOR 1 +#define MEM_CUSTOM_FREE lwip_heap_free +#define MEM_CUSTOM_MALLOC lwip_heap_malloc +#define MEM_CUSTOM_CALLOC lwip_heap_calloc + +// MEM_SIZE: The LWIP heap size. Memory for mem_malloc and mem_calloc are allocated from +// this heap. If MEMP_MEM_MALLOC is set to 1, memory for memp_malloc is also allocated from +// this heap; if it is 0, memory is statically pre-allocated for each pool. +// Default is 1600. +#define MEM_SIZE 1600 +// MEMP_NUM_PBUF: memp pbufs used when sending from static memory. Default is 16. +#define MEMP_NUM_PBUF 16 +// MEMP_NUM_RAW_PCB: Number of raw connection PCBs. Default is 4. +#define MEMP_NUM_RAW_PCB 4 +// MEMP_NUM_UDP_PCB: Number of UDP PCBs. Default is 4. +#define MEMP_NUM_UDP_PCB 4 +// MEMP_NUM_TCP_PCB: Number of simultaneously active TCP connections. Default is 5. +#define MEMP_NUM_TCP_PCB 5 +// MEMP_NUM_TCP_PCB_LISTEN: Number of listening TCP PCBs. Default is 8. +#define MEMP_NUM_TCP_PCB_LISTEN 8 +// MEMP_NUM_TCP_SEG: Number of simultaneously queued TCP segments. Default is 16. +#define MEMP_NUM_TCP_SEG 16 +// MEMP_NUM_ALTCP_PCB: Number of simultaneously active altcp connections. Default is 5. +#define MEMP_NUM_ALTCP_PCB 5 +// MEMP_NUM_REASSDATA: Number of simultaneously IP packets queued for reassembly. Default is 5. +#define MEMP_NUM_REASSDATA 5 +// MEMP_NUM_FRAG_PBUF: Number of simultaneously IP fragments. Default is 15. +#define MEMP_NUM_FRAG_PBUF 15 +// MEMP_NUM_ARP_QUEUE: Number of simultaneously queued ARP packets. Default is 30. +#define MEMP_NUM_ARP_QUEUE 30 +// MEMP_NUM_IGMP_GROUP: Number of simultaneously active IGMP groups. Default is 8. +#define MEMP_NUM_IGMP_GROUP 8 +// MEMP_NUM_SYS_TIMEOUT: Number of simultaneously active timeouts. +// Use calculated default based on enabled modules. + +// PBUF_POOL_SIZE: Number of pbufs in the pbuf pool. Default is 16. +#define PBUF_POOL_SIZE 16 + +// LWIP's default 250 ms periodic timer interval is too long, resulting in network +// performance issues. We reduce it to 25 ms giving a slow-timer of 50 ms and a +// fast-timer of 25 ms. +#define TCP_TMR_INTERVAL 25 + #define LWIP_ARP 1 #define LWIP_ETHERNET 1 #define LWIP_ICMP 1 #define LWIP_RAW 1 + #define TCP_WND (8 * TCP_MSS) #define TCP_MSS 1460 #define TCP_SND_BUF (8 * TCP_MSS) @@ -61,6 +111,7 @@ #define LWIP_NETIF_EXT_STATUS_CALLBACK 1 #define MDNS_MAX_SECONDARY_HOSTNAMES 1 #define MEMP_NUM_SYS_TIMEOUT (8 + 3 * (LWIP_IPV4 + LWIP_IPV6)) +#define MDNS_MAX_SERVICES 25 #endif #ifndef NDEBUG diff --git a/ports/raspberrypi/lwip_src/lwip_mem.c b/ports/raspberrypi/lwip_src/lwip_mem.c new file mode 100644 index 0000000000000..23b185354b072 --- /dev/null +++ b/ports/raspberrypi/lwip_src/lwip_mem.c @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Bob Abeles +// +// SPDX-License-Identifier: MIT + +#include +#include +#include "lib/tlsf/tlsf.h" +#include "lwip_mem.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "supervisor/port_heap.h" + +void *lwip_heap_malloc(size_t size) { + void *ptr = port_malloc(size, true); + return ptr; +} + +void lwip_heap_free(void *ptr) { + port_free(ptr); +} + +void *lwip_heap_calloc(size_t num, size_t size) { + void *ptr = lwip_heap_malloc(num * size); + if (ptr != NULL) { + memset(ptr, 0, num * size); + } + return ptr; +} diff --git a/ports/raspberrypi/mpconfigport.h b/ports/raspberrypi/mpconfigport.h index 1181517fdf9a0..c4253937c986c 100644 --- a/ports/raspberrypi/mpconfigport.h +++ b/ports/raspberrypi/mpconfigport.h @@ -14,6 +14,9 @@ #ifdef PICO_RP2350 #define MICROPY_PY_SYS_PLATFORM "RP2350" + +// PSRAM can require more stack space for GC. +#define MICROPY_ALLOC_GC_STACK_SIZE (128) #endif // Setting a non-default value also requires a non-default link.ld @@ -33,6 +36,9 @@ #define CIRCUITPY_PROCESSOR_COUNT (2) +// For RP2 boards we use a custom way to read BOOTSEL +#define CIRCUITPY_BOOT_BUTTON_NO_GPIO (1) + #if CIRCUITPY_USB_HOST #define CIRCUITPY_USB_HOST_INSTANCE 1 #endif diff --git a/ports/raspberrypi/mpconfigport.mk b/ports/raspberrypi/mpconfigport.mk index ab72ddc4f05bc..90be1afd10922 100644 --- a/ports/raspberrypi/mpconfigport.mk +++ b/ports/raspberrypi/mpconfigport.mk @@ -5,24 +5,25 @@ CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 1 # CYW43 support does not provide settable MAC addresses for station or AP. CIRCUITPY_WIFI_RADIO_SETTABLE_MAC_ADDRESS = 0 -CIRCUITPY_ALARM ?= 1 CIRCUITPY_RP2PIO ?= 1 CIRCUITPY_NEOPIXEL_WRITE ?= $(CIRCUITPY_RP2PIO) CIRCUITPY_FLOPPYIO ?= 1 CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_FULL_BUILD ?= 1 CIRCUITPY_AUDIOMP3 ?= 1 +CIRCUITPY_AUDIOSPEED ?= 1 CIRCUITPY_BITOPS ?= 1 CIRCUITPY_HASHLIB ?= 1 CIRCUITPY_HASHLIB_MBEDTLS ?= 1 CIRCUITPY_IMAGECAPTURE ?= 1 CIRCUITPY_MAX3421E ?= 0 +CIRCUITPY_MCP4822 ?= 0 CIRCUITPY_MEMORYMAP ?= 1 CIRCUITPY_PWMIO ?= 1 CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_DISPLAYIO) CIRCUITPY_ROTARYIO ?= 1 CIRCUITPY_ROTARYIO_SOFTENCODER = 1 -CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12 +CIRCUITPY_SYNTHIO_MAX_CHANNELS = 24 CIRCUITPY_USB_HOST ?= 1 CIRCUITPY_USB_VIDEO ?= 1 @@ -31,6 +32,7 @@ CIRCUITPY_FREQUENCYIO = 0 # Use PWM internally CIRCUITPY_I2CTARGET = 1 +CIRCUITPY_I2CIOEXPANDER = 1 CIRCUITPY_NVM = 1 # Use PIO internally CIRCUITPY_PULSEIO ?= 1 @@ -47,6 +49,34 @@ CIRCUITPY_AUDIOPWMIO ?= 1 CIRCUITPY_AUDIOMIXER ?= 1 +ifeq ($(CHIP_VARIANT),RP2040) +CIRCUITPY_ALARM ?= 1 + +# Default PICODVI off because it uses RAM to store code run on the second CPU for RP2040. +CIRCUITPY_PICODVI ?= 0 + +CIRCUITPY_TOUCHIO ?= 1 + +# delay in ms before calling cyw43_arch_init_with_country +CIRCUITPY_CYW43_INIT_DELAY ?= 1000 +endif + +ifeq ($(CHIP_VARIANT),RP2350) +# RP2350 has PSRAM that is not DMA-capable +CIRCUITPY_ALL_MEMORY_DMA_CAPABLE = 0 + +# This needs to be implemented. +CIRCUITPY_ALARM = 0 +# Default PICODVI on because it doesn't require much code in RAM to talk to HSTX. +CIRCUITPY_PICODVI ?= 1 + +# delay in ms before calling cyw43_arch_init_with_country +CIRCUITPY_CYW43_INIT_DELAY ?= 0 + +# Audio effects +CIRCUITPY_AUDIOEFFECTS ?= 1 +endif + INTERNAL_LIBM = 1 CIRCUITPY_BUILD_EXTENSIONS ?= uf2 diff --git a/ports/raspberrypi/mphalport.c b/ports/raspberrypi/mphalport.c index 3258c4de4f3b6..3d322ba6bca45 100644 --- a/ports/raspberrypi/mphalport.c +++ b/ports/raspberrypi/mphalport.c @@ -19,7 +19,7 @@ #include "mphalport.h" #include "supervisor/shared/tick.h" -#include "src/rp2_common/hardware_timer/include/hardware/timer.h" +#include "hardware/timer.h" extern uint32_t common_hal_mcu_processor_get_frequency(void); diff --git a/ports/raspberrypi/sdk b/ports/raspberrypi/sdk index efe2103f9b284..a1438dff1d38b 160000 --- a/ports/raspberrypi/sdk +++ b/ports/raspberrypi/sdk @@ -1 +1 @@ -Subproject commit efe2103f9b28458a1615ff096054479743ade236 +Subproject commit a1438dff1d38bd9c65dbd693f0e5db4b9ae91779 diff --git a/ports/raspberrypi/sdk_config/pico/config_autogen.h b/ports/raspberrypi/sdk_config/pico/config_autogen.h index 899aaa5028d2e..673fc17f2d3f8 100644 --- a/ports/raspberrypi/sdk_config/pico/config_autogen.h +++ b/ports/raspberrypi/sdk_config/pico/config_autogen.h @@ -1,3 +1,5 @@ #pragma once #include "include/cmsis/rename_exceptions.h" + +#include "pico-sdk-configboard.h" diff --git a/ports/raspberrypi/sdk_config/pico/version.h b/ports/raspberrypi/sdk_config/pico/version.h index 0596c75dd0738..b5803bb98c9d5 100644 --- a/ports/raspberrypi/sdk_config/pico/version.h +++ b/ports/raspberrypi/sdk_config/pico/version.h @@ -12,8 +12,8 @@ #define _PICO_VERSION_H #define PICO_SDK_VERSION_MAJOR 2 -#define PICO_SDK_VERSION_MINOR 0 +#define PICO_SDK_VERSION_MINOR 1 #define PICO_SDK_VERSION_REVISION 0 -#define PICO_SDK_VERSION_STRING "2.0.0" +#define PICO_SDK_VERSION_STRING "2.1.0" #endif diff --git a/ports/raspberrypi/supervisor/internal_flash.c b/ports/raspberrypi/supervisor/internal_flash.c index 6502aa08b055a..9d5e13348aac2 100644 --- a/ports/raspberrypi/supervisor/internal_flash.c +++ b/ports/raspberrypi/supervisor/internal_flash.c @@ -24,11 +24,11 @@ #include "supervisor/usb.h" #ifdef PICO_RP2350 -#include "src/rp2350/hardware_structs/include/hardware/structs/qmi.h" +#include "hardware/structs/qmi.h" #endif -#include "src/rp2040/hardware_structs/include/hardware/structs/sio.h" -#include "src/rp2_common/hardware_flash/include/hardware/flash.h" -#include "src/common/pico_binary_info/include/pico/binary_info.h" +#include "hardware/structs/sio.h" +#include "hardware/flash.h" +#include "pico/binary_info.h" #if !defined(TOTAL_FLASH_MINIMUM) #define TOTAL_FLASH_MINIMUM (2 * 1024 * 1024) @@ -40,30 +40,26 @@ static uint8_t _cache[SECTOR_SIZE]; static uint32_t _cache_lba = NO_CACHE; static uint32_t _flash_size = 0; - -#ifdef PICO_RP2350 -static uint32_t m1_rfmt; -static uint32_t m1_timing; +#if CIRCUITPY_AUDIOCORE +static uint32_t _audio_channel_mask; #endif -static void save_psram_settings(void) { - #ifdef PICO_RP2350 - // We're about to invalidate the XIP cache, clean it first to commit any dirty writes to PSRAM - uint8_t *maintenance_ptr = (uint8_t *)XIP_MAINTENANCE_BASE; - for (int i = 1; i < 16 * 1024; i += 8) { - maintenance_ptr[i] = 0; - } - - m1_timing = qmi_hw->m[1].timing; - m1_rfmt = qmi_hw->m[1].rfmt; +void supervisor_flash_pre_write(void) { + // Disable interrupts. XIP accesses will fault during flash writes. + common_hal_mcu_disable_interrupts(); + #if CIRCUITPY_AUDIOCORE + // Pause audio DMA to avoid noise while interrupts are disabled. + _audio_channel_mask = audio_dma_pause_all(); #endif } -static void restore_psram_settings(void) { - #ifdef PICO_RP2350 - qmi_hw->m[1].timing = m1_timing; - qmi_hw->m[1].rfmt = m1_rfmt; +void supervisor_flash_post_write(void) { + #if CIRCUITPY_AUDIOCORE + // Unpause audio DMA. + audio_dma_unpause_mask(_audio_channel_mask); #endif + // Re-enable interrupts. + common_hal_mcu_enable_interrupts(); } void supervisor_flash_init(void) { @@ -80,9 +76,9 @@ void supervisor_flash_init(void) { // Read the RDID register to get the flash capacity. uint8_t cmd[] = {0x9f, 0, 0, 0}; uint8_t data[4]; - save_psram_settings(); + supervisor_flash_pre_write(); flash_do_cmd(cmd, data, 4); - restore_psram_settings(); + supervisor_flash_post_write(); uint8_t power_of_two = FLASH_DEFAULT_POWER_OF_TWO; // Flash must be at least 2MB (1 << 21) because we use the first 1MB for the // CircuitPython core. We validate the range because Adesto Tech flash chips @@ -106,21 +102,11 @@ void port_internal_flash_flush(void) { if (_cache_lba == NO_CACHE) { return; } - // Make sure we don't have an interrupt while we do flash operations. - common_hal_mcu_disable_interrupts(); - // and audio DMA must be paused as well - #if CIRCUITPY_AUDIOCORE - uint32_t channel_mask = audio_dma_pause_all(); - #endif - save_psram_settings(); + supervisor_flash_pre_write(); flash_range_erase(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, SECTOR_SIZE); flash_range_program(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, _cache, SECTOR_SIZE); - restore_psram_settings(); _cache_lba = NO_CACHE; - #if CIRCUITPY_AUDIOCORE - audio_dma_unpause_mask(channel_mask); - #endif - common_hal_mcu_enable_interrupts(); + supervisor_flash_post_write(); } mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { diff --git a/ports/raspberrypi/supervisor/internal_flash.h b/ports/raspberrypi/supervisor/internal_flash.h index 01acbf02b4de4..a7941b17c470f 100644 --- a/ports/raspberrypi/supervisor/internal_flash.h +++ b/ports/raspberrypi/supervisor/internal_flash.h @@ -9,6 +9,10 @@ #include "mpconfigport.h" +// These must be called before and after doing a low-level flash write. +void supervisor_flash_pre_write(void); +void supervisor_flash_post_write(void); + // #define INTERNAL_FLASH_PART1_NUM_BLOCKS (CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE) // #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms diff --git a/ports/raspberrypi/supervisor/port.c b/ports/raspberrypi/supervisor/port.c index 9a52501196332..0316e34ad951c 100644 --- a/ports/raspberrypi/supervisor/port.c +++ b/ports/raspberrypi/supervisor/port.c @@ -4,6 +4,7 @@ // // SPDX-License-Identifier: MIT +#include #include #include @@ -13,7 +14,6 @@ #include "bindings/rp2pio/StateMachine.h" #include "genhdr/mpversion.h" -#include "shared-bindings/busio/I2C.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/countio/Counter.h" #include "shared-bindings/microcontroller/__init__.h" @@ -38,25 +38,37 @@ #include "supervisor/shared/stack.h" #include "supervisor/shared/tick.h" -#include "src/rp2040/hardware_structs/include/hardware/structs/watchdog.h" -#include "src/rp2_common/hardware_gpio/include/hardware/gpio.h" -#include "src/rp2_common/hardware_uart/include/hardware/uart.h" -#include "src/rp2_common/hardware_sync/include/hardware/sync.h" -#include "src/rp2_common/hardware_timer/include/hardware/timer.h" +#include "hardware/structs/watchdog.h" +#include "hardware/gpio.h" +#include "hardware/uart.h" +#include "hardware/sync.h" +#include "hardware/timer.h" #if CIRCUITPY_CYW43 #include "py/mphal.h" #include "pico/cyw43_arch.h" #endif -#include "src/common/pico_time/include/pico/time.h" -#include "src/common/pico_binary_info/include/pico/binary_info.h" +#include "pico/time.h" +#include "pico/binary_info.h" #include "pico/bootrom.h" #include "hardware/watchdog.h" +#ifdef PICO_RP2350 +#include "RP2350.h" // CMSIS +#endif + +#if CIRCUITPY_BOOT_BUTTON_NO_GPIO +#include "hardware/gpio.h" +#include "hardware/sync.h" +#include "hardware/structs/ioqspi.h" +#include "hardware/structs/sio.h" +#endif + #include "supervisor/shared/serial.h" #include "tusb.h" #include +#include "lib/tlsf/tlsf.h" critical_section_t background_queue_lock; @@ -84,20 +96,17 @@ extern uint32_t _ld_itcm_destination; extern uint32_t _ld_itcm_size; extern uint32_t _ld_itcm_flash_copy; -#ifdef CIRCUITPY_PSRAM_CHIP_SELECT - -#include "lib/tlsf/tlsf.h" - -#include "src/rp2350/hardware_regs/include/hardware/regs/qmi.h" -#include "src/rp2350/hardware_regs/include/hardware/regs/xip.h" -#include "src/rp2350/hardware_structs/include/hardware/structs/qmi.h" -#include "src/rp2350/hardware_structs/include/hardware/structs/xip_ctrl.h" - static tlsf_t _heap = NULL; -static pool_t _ram_pool = NULL; -static pool_t _psram_pool = NULL; +static tlsf_t _psram_heap = NULL; static size_t _psram_size = 0; +#ifdef CIRCUITPY_PSRAM_CHIP_SELECT + +#include "hardware/regs/qmi.h" +#include "hardware/regs/xip.h" +#include "hardware/structs/qmi.h" +#include "hardware/structs/xip_ctrl.h" + static void __no_inline_not_in_flash_func(setup_psram)(void) { gpio_set_function(CIRCUITPY_PSRAM_CHIP_SELECT->number, GPIO_FUNC_XIP_CS1); _psram_size = 0; @@ -237,31 +246,70 @@ static void __no_inline_not_in_flash_func(setup_psram)(void) { return; } } +#endif -void port_heap_init(void) { +static void _port_heap_init(void) { uint32_t *heap_bottom = port_heap_get_bottom(); uint32_t *heap_top = port_heap_get_top(); size_t size = (heap_top - heap_bottom) * sizeof(uint32_t); - _heap = tlsf_create_with_pool(heap_bottom, size, 64 * 1024 * 1024); - _ram_pool = tlsf_get_pool(_heap); + _heap = tlsf_create_with_pool(heap_bottom, size, size); if (_psram_size > 0) { - _psram_pool = tlsf_add_pool(_heap, (void *)0x11000004, _psram_size - 4); + _psram_heap = tlsf_create_with_pool((void *)0x11000000, _psram_size, _psram_size); } } +void port_heap_init(void) { + // We call _port_heap_init from port_init to initialize the heap early. +} + void *port_malloc(size_t size, bool dma_capable) { + if (!dma_capable && _psram_size > 0) { + common_hal_mcu_disable_interrupts(); + void *block = tlsf_malloc(_psram_heap, size); + common_hal_mcu_enable_interrupts(); + if (block) { + return block; + } + } + common_hal_mcu_disable_interrupts(); void *block = tlsf_malloc(_heap, size); + common_hal_mcu_enable_interrupts(); return block; } void port_free(void *ptr) { - tlsf_free(_heap, ptr); + common_hal_mcu_disable_interrupts(); + if (((size_t)ptr) < SRAM_BASE) { + tlsf_free(_psram_heap, ptr); + } else { + tlsf_free(_heap, ptr); + } + common_hal_mcu_enable_interrupts(); } -void *port_realloc(void *ptr, size_t size) { - return tlsf_realloc(_heap, ptr, size); +void *port_realloc(void *ptr, size_t size, bool dma_capable) { + if (_psram_size > 0 && ((ptr != NULL && ((size_t)ptr) < SRAM_BASE) || (ptr == NULL && !dma_capable))) { + common_hal_mcu_disable_interrupts(); + void *block = tlsf_realloc(_psram_heap, ptr, size); + common_hal_mcu_enable_interrupts(); + if (block) { + return block; + } + } + common_hal_mcu_disable_interrupts(); + void *new_ptr = tlsf_realloc(_heap, ptr, size); + common_hal_mcu_enable_interrupts(); + return new_ptr; } +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +bool port_buffer_is_dma_capable(const void *ptr) { + // For RP2350, DMA can only access SRAM, not PSRAM + // PSRAM addresses are below SRAM_BASE + return ptr != NULL && ((size_t)ptr) >= SRAM_BASE; +} +#endif + static bool max_size_walker(void *ptr, size_t size, int used, void *user) { size_t *max_size = (size_t *)user; if (!used && *max_size < size) { @@ -272,14 +320,14 @@ static bool max_size_walker(void *ptr, size_t size, int used, void *user) { size_t port_heap_get_largest_free_size(void) { size_t max_size = 0; - tlsf_walk_pool(_ram_pool, max_size_walker, &max_size); - if (_psram_pool != NULL) { - tlsf_walk_pool(_psram_pool, max_size_walker, &max_size); + tlsf_walk_pool(tlsf_get_pool(_heap), max_size_walker, &max_size); + max_size = tlsf_fit_size(_heap, max_size); + if (_psram_heap != NULL) { + tlsf_walk_pool(tlsf_get_pool(_psram_heap), max_size_walker, &max_size); + max_size = tlsf_fit_size(_psram_heap, max_size); } - // IDF does this. Not sure why. - return tlsf_fit_size(_heap, max_size); + return max_size; } -#endif safe_mode_t port_init(void) { _binary_info(); @@ -318,21 +366,15 @@ safe_mode_t port_init(void) { critical_section_init(&background_queue_lock); #if CIRCUITPY_CYW43 - never_reset_pin_number(23); - never_reset_pin_number(24); - never_reset_pin_number(25); - never_reset_pin_number(29); + never_reset_pin_number(CYW43_DEFAULT_PIN_WL_REG_ON); + never_reset_pin_number(CYW43_DEFAULT_PIN_WL_DATA_IN); + never_reset_pin_number(CYW43_DEFAULT_PIN_WL_CS); + never_reset_pin_number(CYW43_DEFAULT_PIN_WL_CLOCK); #endif // Reset everything into a known state before board_init. reset_port(); - serial_early_init(); - - #ifdef CIRCUITPY_PSRAM_CHIP_SELECT - setup_psram(); - #endif - // Initialize RTC #if CIRCUITPY_RTC common_hal_rtc_init(); @@ -342,6 +384,18 @@ safe_mode_t port_init(void) { hardware_alarm_claim(0); hardware_alarm_set_callback(0, _tick_callback); + // RP2 port-specific early serial initialization for psram debug. + // The RTC must already be initialized, otherwise the serial UART + // will hang. + serial_early_init(); + + #ifdef CIRCUITPY_PSRAM_CHIP_SELECT + setup_psram(); + #endif + + // Initialize heap early to allow for early allocation. + _port_heap_init(); + // Check brownout. #if CIRCUITPY_CYW43 @@ -349,7 +403,8 @@ safe_mode_t port_init(void) { // initializing the cyw43 chip. Delays inside cyw43_arch_init_with_country // are intended to meet the power on timing requirements, but apparently // are inadequate. We'll back off this long delay based on future testing. - mp_hal_delay_ms(1000); + mp_hal_delay_ms(CIRCUITPY_CYW43_INIT_DELAY); + // Change this as a placeholder as to how to init with country code. // Default country code is CYW43_COUNTRY_WORLDWIDE) if (cyw43_arch_init_with_country(PICO_CYW43_ARCH_DEFAULT_COUNTRY_CODE)) { @@ -367,8 +422,6 @@ safe_mode_t port_init(void) { void reset_port(void) { #if CIRCUITPY_BUSIO - reset_i2c(); - reset_spi(); reset_uart(); #endif @@ -399,8 +452,6 @@ void reset_port(void) { #if CIRCUITPY_WIFI wifi_reset(); #endif - - reset_all_pins(); } void reset_to_bootloader(void) { @@ -456,11 +507,11 @@ static volatile bool ticks_enabled; static volatile bool _woken_up; uint64_t port_get_raw_ticks(uint8_t *subticks) { - uint64_t microseconds = time_us_64(); + int64_t all_subticks = time_us_64() * 512 / 15625; if (subticks != NULL) { - *subticks = (uint8_t)(((microseconds % 1000000) % 977) / 31); + *subticks = all_subticks % 32; } - return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977; + return all_subticks / 32; } static void _tick_callback(uint alarm_num) { @@ -496,6 +547,7 @@ void port_interrupt_after_ticks(uint32_t ticks) { } void port_idle_until_interrupt(void) { + #ifdef PICO_RP2040 common_hal_mcu_disable_interrupts(); #if CIRCUITPY_USB_HOST if (!background_callback_pending() && !tud_task_event_ready() && !tuh_task_event_ready() && !_woken_up) { @@ -506,12 +558,37 @@ void port_idle_until_interrupt(void) { __WFI(); } common_hal_mcu_enable_interrupts(); + #else + // because we use interrupt priority, don't use + // common_hal_mcu_disable_interrupts (because an interrupt masked by + // BASEPRI will not occur) + uint32_t state = save_and_disable_interrupts(); + + // Ensure BASEPRI is at 0... + uint32_t oldBasePri = __get_BASEPRI(); + __set_BASEPRI(0); + __isb(); + #if CIRCUITPY_USB_HOST + if (!background_callback_pending() && !tud_task_event_ready() && !tuh_task_event_ready() && !_woken_up) { + #else + if (!background_callback_pending() && !tud_task_event_ready() && !_woken_up) { + #endif + __DSB(); + __WFI(); + } + + // and restore basepri before reenabling interrupts + __set_BASEPRI(oldBasePri); + __isb(); + + restore_interrupts(state); + #endif } /** * \brief Default interrupt handler for unused IRQs. */ -extern void isr_hardfault(void); // provide a prototype to avoid a missing-prototypes diagnostic +extern MP_NORETURN void isr_hardfault(void); // provide a prototype to avoid a missing-prototypes diagnostic __attribute__((used)) void __not_in_flash_func(isr_hardfault)(void) { // Only safe mode from core 0 which is running CircuitPython. Core 1 faulting // should not be fatal to CP. (Fingers crossed.) @@ -523,7 +600,7 @@ __attribute__((used)) void __not_in_flash_func(isr_hardfault)(void) { } } -void port_yield() { +void port_task_yield(void) { #if CIRCUITPY_CYW43 cyw43_arch_poll(); #endif @@ -538,3 +615,53 @@ void port_boot_info(void) { mp_printf(&mp_plat_print, "\n"); #endif } + +#if CIRCUITPY_BOOT_BUTTON_NO_GPIO +bool __no_inline_not_in_flash_func(port_boot_button_pressed)(void) { + // Sense the state of the boot button. Because this function + // disables flash, it cannot be safely called once the second + // core has been started. When the BOOTSEL button is sensed as + // pressed, return is delayed until the button is released and + // a delay has passed in order to debounce the button. + const uint32_t CS_PIN_INDEX = 1; + #if defined(PICO_RP2040) + const uint32_t CS_BIT = 1u << 1; + #else + const uint32_t CS_BIT = SIO_GPIO_HI_IN_QSPI_CSN_BITS; + #endif + uint32_t int_state = save_and_disable_interrupts(); + // Wait for any outstanding XIP activity to finish. Flash + // must be quiescent before disabling the chip select. Since + // there's no XIP busy indication we can test, we delay a + // generous 5 ms to allow any XIP activity to finish. + busy_wait_us(5000); + // Float the flash chip select pin. The line will HI-Z due to + // the external 10K pull-up resistor. + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, + GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + // Delay 100 us to allow the CS line to stabilize. If BOOTSEL is + // pressed, the line will be pulled low by the button and its + // 1K external resistor to ground. + busy_wait_us(100); + bool button_pressed = !(sio_hw->gpio_hi_in & CS_BIT); + // Wait for the button to be released. + if (button_pressed) { + while (!(sio_hw->gpio_hi_in & CS_BIT)) { + tight_loop_contents(); + } + // Wait for 50 ms to debounce the button. + busy_wait_us(50000); + } + // Restore the flash chip select pin to its original state. + hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, + GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, + IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); + // Delay 5 ms to allow the flash chip to re-enable and for the + // flash CS pin to stabilize. + busy_wait_us(5000); + // Restore the interrupt state. + restore_interrupts(int_state); + return button_pressed; +} +#endif diff --git a/ports/raspberrypi/supervisor/rp2_cpu.s b/ports/raspberrypi/supervisor/rp2_cpu.s deleted file mode 100755 index 741bb21358ad2..0000000000000 --- a/ports/raspberrypi/supervisor/rp2_cpu.s +++ /dev/null @@ -1,35 +0,0 @@ -.syntax unified -.cpu cortex-m0 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0, #0] -str r5, [r0, #4] -str r6, [r0, #8] -str r7, [r0, #12] -push {r1} -mov r1, r8 -str r1, [r0, #16] -mov r1, r9 -str r1, [r0, #20] -mov r1, r10 -str r1, [r0, #24] -mov r1, r11 -str r1, [r0, #28] -mov r1, r12 -str r1, [r0, #32] -mov r1, r13 -str r1, [r0, #36] -pop {r1} - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/raspberrypi/supervisor/usb.c b/ports/raspberrypi/supervisor/usb.c index 97933d5651ea5..398f3f448a1d5 100644 --- a/ports/raspberrypi/supervisor/usb.c +++ b/ports/raspberrypi/supervisor/usb.c @@ -7,9 +7,9 @@ #include "lib/tinyusb/src/device/usbd.h" #include "supervisor/background_callback.h" #include "supervisor/usb.h" -#include "src/rp2_common/hardware_irq/include/hardware/irq.h" +#include "hardware/irq.h" #include "pico/platform.h" -#include "src/rp2040/hardware_regs/include/hardware/regs/intctrl.h" +#include "hardware/regs/intctrl.h" void init_usb_hardware(void) { } diff --git a/ports/renode/Makefile b/ports/renode/Makefile index 98fe04f4713c0..c4ce66194e9d1 100644 --- a/ports/renode/Makefile +++ b/ports/renode/Makefile @@ -21,7 +21,7 @@ INC += \ CFLAGS += -ggdb3 -Os DISABLE_WARNINGS = -Wno-cast-align -CFLAGS += $(INC) -Wall -Werror -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -Werror=missing-prototypes +CFLAGS += $(INC) -Wall -Werror -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT) $(DISABLE_WARNINGS) -Werror=missing-prototypes -Werror=old-style-definition CFLAGS += \ -march=armv6-m \ @@ -45,21 +45,9 @@ SRC_C += \ background.c \ mphalport.c \ +SRC_S = shared/runtime/gchelper_thumb1.s -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-module/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) - -SRC_S = supervisor/$(CPU)_cpu.s +SRC_C += shared/runtime/gchelper_native.c OBJ = $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) @@ -68,14 +56,13 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif OBJ += $(addprefix $(BUILD)/, $(SRC_CIRCUITPY_COMMON:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_S_UPPER:.S=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o)) $(BUILD)/%.o: $(BUILD)/%.S $(STEPECHO) "CC $<" $(Q)$(CC) $(CFLAGS) -c -o $@ $< -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) all: $(BUILD)/firmware.elf $(BUILD)/circuitpy.img diff --git a/ports/renode/common-hal/busio/I2C.c b/ports/renode/common-hal/busio/I2C.c index def78d632cd68..41649f180b3d9 100644 --- a/ports/renode/common-hal/busio/I2C.c +++ b/ports/renode/common-hal/busio/I2C.c @@ -31,6 +31,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } return false; } @@ -41,19 +44,19 @@ bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) { void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return 0; } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { - return MP_EIO; + return -MP_EIO; } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - return MP_EIO; + return -MP_EIO; } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { diff --git a/ports/renode/common-hal/busio/SPI.c b/ports/renode/common-hal/busio/SPI.c index 42b12d1fb29c8..1f66fc5ec4af1 100644 --- a/ports/renode/common-hal/busio/SPI.c +++ b/ports/renode/common-hal/busio/SPI.c @@ -21,6 +21,9 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return true; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; @@ -33,6 +36,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } return false; } diff --git a/ports/renode/common-hal/os/__init__.c b/ports/renode/common-hal/os/__init__.c index 334742bb594e3..14e22960469fa 100644 --- a/ports/renode/common-hal/os/__init__.c +++ b/ports/renode/common-hal/os/__init__.c @@ -12,32 +12,6 @@ #include "shared-bindings/os/__init__.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, "renode"); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, "renode"); -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { return false; } diff --git a/ports/renode/supervisor/cortex-m0+_cpu.s b/ports/renode/supervisor/cortex-m0+_cpu.s deleted file mode 100755 index 741bb21358ad2..0000000000000 --- a/ports/renode/supervisor/cortex-m0+_cpu.s +++ /dev/null @@ -1,35 +0,0 @@ -.syntax unified -.cpu cortex-m0 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0, #0] -str r5, [r0, #4] -str r6, [r0, #8] -str r7, [r0, #12] -push {r1} -mov r1, r8 -str r1, [r0, #16] -mov r1, r9 -str r1, [r0, #20] -mov r1, r10 -str r1, [r0, #24] -mov r1, r11 -str r1, [r0, #28] -mov r1, r12 -str r1, [r0, #32] -mov r1, r13 -str r1, [r0, #36] -pop {r1} - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/renode/supervisor/port.c b/ports/renode/supervisor/port.c index dae32b7bb8f2d..a40e222d34df3 100644 --- a/ports/renode/supervisor/port.c +++ b/ports/renode/supervisor/port.c @@ -210,7 +210,7 @@ __attribute__((used)) void HardFault_Handler(void) { } } -void port_yield() { +void port_task_yield(void) { } void port_boot_info(void) { diff --git a/ports/silabs/Makefile b/ports/silabs/Makefile index 8c7663718e370..810ab53f1f331 100644 --- a/ports/silabs/Makefile +++ b/ports/silabs/Makefile @@ -71,7 +71,7 @@ ifeq ($(DEBUG), 1) CFLAGS += -fno-inline -fno-ipa-sra -Og else CFLAGS += -DNDEBUG - OPTIMIZATION_FLAGS ?= -Os -fno-inline-functions + OPTIMIZATION_FLAGS ?= -Os CFLAGS += -g endif @@ -90,20 +90,10 @@ ifneq (,$(wildcard boards/$(BOARD)/sensor.c)) SRC_C += boards/$(BOARD)/sensor.c endif -SRC_S = boards/mp_efr32xg24_gchelper.s +AFLAGS = -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard +SRC_S = shared/runtime/gchelper_thumb1.s -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - -# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, -# because a few modules have files both in common-hal/ and shared-module/. -# Doing a $(sort ...) removes duplicates as part of sorting. -SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) +SRC_C += shared/runtime/gchelper_native.c OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) @@ -118,7 +108,7 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += diff --git a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c index 2adfd67c4bf78..1c991a4caafc7 100644 --- a/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c +++ b/ports/silabs/boards/devkit_xg24_brd2601b/sensor.c @@ -36,7 +36,7 @@ #include "sl_sensor_hall.h" #include "sl_sensor_pressure.h" -STATIC mp_obj_t sensor_init(mp_obj_t i2c_in) { +static mp_obj_t sensor_init(mp_obj_t i2c_in) { // busio_i2c_obj_t *i2c = MP_OBJ_TO_PTR(i2c_in); sl_status_t sc; @@ -75,7 +75,7 @@ STATIC mp_obj_t sensor_init(mp_obj_t i2c_in) { return mp_const_true; } -STATIC mp_obj_t sensor_deinit() { +static mp_obj_t sensor_deinit(void) { sl_sensor_hall_deinit(); sl_sensor_lux_deinit(); @@ -87,7 +87,7 @@ STATIC mp_obj_t sensor_deinit() { return mp_const_true; } -STATIC mp_obj_t sensor_get_temperature(void) { +static mp_obj_t sensor_get_temperature(void) { sl_status_t sc; uint32_t rh; int32_t t; @@ -100,7 +100,7 @@ STATIC mp_obj_t sensor_get_temperature(void) { return mp_obj_new_float((float)t / 1000.0f); } -STATIC mp_obj_t sensor_get_humidity(void) { +static mp_obj_t sensor_get_humidity(void) { sl_status_t sc; uint32_t rh; int32_t t; @@ -112,7 +112,7 @@ STATIC mp_obj_t sensor_get_humidity(void) { return mp_obj_new_float((float)rh / 1000.0f); } -STATIC mp_obj_t sensor_get_lux(void) { +static mp_obj_t sensor_get_lux(void) { sl_status_t sc; float lux; sc = sl_sensor_lux_get(&lux); @@ -123,7 +123,7 @@ STATIC mp_obj_t sensor_get_lux(void) { return mp_obj_new_float(lux); } -STATIC mp_obj_t sensor_get_hall(void) { +static mp_obj_t sensor_get_hall(void) { sl_status_t sc; float field_strength; bool alert; @@ -136,7 +136,7 @@ STATIC mp_obj_t sensor_get_hall(void) { return mp_obj_new_float(field_strength); } -STATIC mp_obj_t sensor_get_pressure(void) { +static mp_obj_t sensor_get_pressure(void) { sl_status_t sc; float pressure; sc = sl_sensor_pressure_get(&pressure); @@ -147,7 +147,7 @@ STATIC mp_obj_t sensor_get_pressure(void) { return mp_obj_new_float(pressure); } -STATIC mp_obj_t sensor_imu_get(void) { +static mp_obj_t sensor_imu_get(void) { sl_status_t sc; int16_t ovec[3]; int16_t avec[3]; @@ -172,7 +172,7 @@ STATIC mp_obj_t sensor_imu_get(void) { return mp_obj_new_tuple(2, ret); } -STATIC mp_obj_t sensor_imu_calibrate(void) { +static mp_obj_t sensor_imu_calibrate(void) { sl_status_t sc; sc = sl_sensor_imu_calibrate(); if (sc != SL_STATUS_OK) { @@ -181,18 +181,18 @@ STATIC mp_obj_t sensor_imu_calibrate(void) { return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(sensor_init_obj, sensor_init); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_deinit_obj, sensor_deinit); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_temperature_obj, sensor_get_temperature); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_humidity_obj, sensor_get_humidity); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_lux_obj, sensor_get_lux); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_hall_obj, sensor_get_hall); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_pressure_obj, sensor_get_pressure); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_get_obj, sensor_imu_get); -STATIC MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_calibrate_obj, sensor_imu_calibrate); +static MP_DEFINE_CONST_FUN_OBJ_1(sensor_init_obj, sensor_init); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_deinit_obj, sensor_deinit); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_temperature_obj, sensor_get_temperature); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_humidity_obj, sensor_get_humidity); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_lux_obj, sensor_get_lux); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_hall_obj, sensor_get_hall); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_get_pressure_obj, sensor_get_pressure); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_get_obj, sensor_imu_get); +static MP_DEFINE_CONST_FUN_OBJ_0(sensor_imu_calibrate_obj, sensor_imu_calibrate); -STATIC const mp_rom_map_elem_t sensor_globals_table[] = { +static const mp_rom_map_elem_t sensor_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_sensor) }, { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&sensor_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sensor_deinit_obj) }, @@ -204,7 +204,7 @@ STATIC const mp_rom_map_elem_t sensor_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_imu), MP_ROM_PTR(&sensor_imu_get_obj) }, { MP_ROM_QSTR(MP_QSTR_imu_calibrate), MP_ROM_PTR(&sensor_imu_calibrate_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(sensor_module_globals, sensor_globals_table); +static MP_DEFINE_CONST_DICT(sensor_module_globals, sensor_globals_table); const mp_obj_module_t sensor_module = { .base = { &mp_type_module }, diff --git a/ports/silabs/common-hal/_bleio/Adapter.c b/ports/silabs/common-hal/_bleio/Adapter.c index d469172ae981f..14b1dac8207a9 100644 --- a/ports/silabs/common-hal/_bleio/Adapter.c +++ b/ports/silabs/common-hal/_bleio/Adapter.c @@ -376,7 +376,7 @@ uint32_t _common_hal_bleio_adapter_start_advertising( } // Check size of packet advertising to send -STATIC void check_data_fit(size_t data_len, bool connectable) { +static void check_data_fit(size_t data_len, bool connectable) { if (data_len > BLE_EXT_ADV_MAX_SIZE || (connectable && data_len > BLE_EXT_ADV_MAX_SIZE)) { mp_raise_ValueError( @@ -451,7 +451,7 @@ bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { } // Convert mac address of remote device to connect -STATIC void _convert_address(const bleio_address_obj_t *address, +static void _convert_address(const bleio_address_obj_t *address, bd_addr *sd_address, uint8_t *addr_type) { mp_buffer_info_t address_buf_info; *addr_type = address->type; diff --git a/ports/silabs/common-hal/_bleio/Characteristic.c b/ports/silabs/common-hal/_bleio/Characteristic.c index f065a939a6016..9ccc6ad9c364e 100644 --- a/ports/silabs/common-hal/_bleio/Characteristic.c +++ b/ports/silabs/common-hal/_bleio/Characteristic.c @@ -76,7 +76,7 @@ bool set_characteristic_value_on_ble_evt(uint8_t conn_handle, } // Get the characteristic data object -STATIC bool get_characteristic_value(uint8_t conn_handle, +static bool get_characteristic_value(uint8_t conn_handle, uint16_t char_handle, uint8_t *data, size_t *data_len) { @@ -155,6 +155,13 @@ void common_hal_bleio_characteristic_construct( } } +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return false; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { +} + // A tuple of Descriptor that describe this characteristic mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors( bleio_characteristic_obj_t *self) { @@ -242,7 +249,7 @@ size_t common_hal_bleio_characteristic_get_value( return 0; } -// Get max length of charateristic +// Get max length of characteristic size_t common_hal_bleio_characteristic_get_max_length( bleio_characteristic_obj_t *self) { return self->max_length; @@ -366,7 +373,7 @@ void common_hal_bleio_characteristic_add_descriptor( // This indicates the new added descriptor shall be started. sc = sl_bt_gattdb_start_characteristic(gattdb_session, self->handle); if (SL_STATUS_OK != sc) { - mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Start charateristic fail.")); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Start characteristic fail.")); return; } @@ -388,7 +395,7 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, const uint16_t conn_handle = bleio_connection_get_conn_handle( self->service->connection); - common_hal_bleio_check_connected(conn_handle); + bleio_check_connected(conn_handle); notify = 1; indicate = 0; if (notify) { diff --git a/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c b/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c index 2acb6b00fcab9..d08fa765c4f71 100644 --- a/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c +++ b/ports/silabs/common-hal/_bleio/CharacteristicBuffer.c @@ -87,7 +87,7 @@ void common_hal_bleio_characteristic_buffer_construct( mp_float_t timeout, size_t buffer_size) { - uint8_t *buffer = m_malloc(buffer_size); + uint8_t *buffer = m_malloc_without_collect(buffer_size); _common_hal_bleio_characteristic_buffer_construct(self, characteristic, timeout, @@ -156,7 +156,7 @@ bool common_hal_bleio_characteristic_buffer_connected( common_hal_bleio_connection_get_connected(self->characteristic->service->connection))); } -void reset_characteristic_buffer_list() { +void reset_characteristic_buffer_list(void) { // Remove characteristic_buffer list memset(bleio_characteristic_buffer_list.data, 0, sizeof(bleio_characteristic_buffer_list.data)); diff --git a/ports/silabs/common-hal/_bleio/Connection.h b/ports/silabs/common-hal/_bleio/Connection.h index 56872024c932c..148caecba1101 100644 --- a/ports/silabs/common-hal/_bleio/Connection.h +++ b/ports/silabs/common-hal/_bleio/Connection.h @@ -85,6 +85,7 @@ typedef struct void bleio_connection_clear(bleio_connection_internal_t *self); +void bleio_check_connected(uint16_t conn_handle); uint16_t bleio_connection_get_conn_handle(bleio_connection_obj_t *self); mp_obj_t bleio_connection_new_from_internal( diff --git a/ports/silabs/common-hal/_bleio/PacketBuffer.c b/ports/silabs/common-hal/_bleio/PacketBuffer.c index 6cb3e58121cbb..881cf1622eba7 100644 --- a/ports/silabs/common-hal/_bleio/PacketBuffer.c +++ b/ports/silabs/common-hal/_bleio/PacketBuffer.c @@ -41,7 +41,7 @@ bleio_packet_buffer_obj_list_t bleio_packet_buffer_list; // Write data to ringbuf of packet buffer -STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, +static void write_to_ringbuf(bleio_packet_buffer_obj_t *self, uint8_t *data, uint16_t len) { @@ -70,7 +70,7 @@ STATIC void write_to_ringbuf(bleio_packet_buffer_obj_t *self, } // Write characteristic or attribute value -STATIC int queue_next_write(bleio_packet_buffer_obj_t *self) { +static int queue_next_write(bleio_packet_buffer_obj_t *self) { self->packet_queued = false; uint32_t sc = SL_STATUS_OK; @@ -145,7 +145,7 @@ void _common_hal_bleio_packet_buffer_construct( uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size, - ble_event_handler_t static_handler_entry) { + ble_event_handler_t *static_handler_entry) { bleio_characteristic_properties_t temp_prop; self->characteristic = characteristic; @@ -223,12 +223,12 @@ void common_hal_bleio_packet_buffer_construct( if (incoming) { incoming_buffer_size = buffer_size * (sizeof(uint16_t) + max_packet_size); - incoming_buffer = m_malloc(incoming_buffer_size); + incoming_buffer = m_malloc_without_collect(incoming_buffer_size); } if (outgoing) { - outgoing1 = m_malloc(max_packet_size); - outgoing2 = m_malloc(max_packet_size); + outgoing1 = m_malloc_without_collect(max_packet_size); + outgoing2 = m_malloc_without_collect(max_packet_size); } _common_hal_bleio_packet_buffer_construct(self, characteristic, incoming_buffer, incoming_buffer_size, @@ -391,7 +391,7 @@ void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { } // Remove packet_buffer list when reload -void reset_packet_buffer_list() { +void reset_packet_buffer_list(void) { // Remove packet_buffer list memset(bleio_packet_buffer_list.data, 0, sizeof(bleio_packet_buffer_list.data)); diff --git a/ports/silabs/common-hal/_bleio/Service.c b/ports/silabs/common-hal/_bleio/Service.c index 694841e66284f..50f0c4593a67e 100644 --- a/ports/silabs/common-hal/_bleio/Service.c +++ b/ports/silabs/common-hal/_bleio/Service.c @@ -128,7 +128,7 @@ bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { return self->uuid; } -// Get tuple charateristic of service +// Get tuple characteristic of service mp_obj_tuple_t *common_hal_bleio_service_get_characteristics( bleio_service_obj_t *self) { return mp_obj_new_tuple(self->characteristic_list->len, @@ -210,19 +210,19 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, } if (SL_STATUS_OK != sc) { - mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Add charateristic fail.")); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Add characteristic fail.")); } sc = sl_bt_gattdb_start_characteristic(gattdb_session, characteristic->handle); if (SL_STATUS_OK != sc) { - mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Start charateristic fail.")); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Start characteristic fail.")); return; } sc = sl_bt_gattdb_commit(gattdb_session); if (SL_STATUS_OK != sc) { - mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Commit charateristic fail.")); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Commit characteristic fail.")); return; } mp_obj_list_append(self->characteristic_list, @@ -230,7 +230,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, } // Remove dynamic service when reload -void reset_dynamic_service() { +void reset_dynamic_service(void) { uint16_t gattdb_session; uint8_t svc_index; diff --git a/ports/silabs/common-hal/_bleio/__init__.c b/ports/silabs/common-hal/_bleio/__init__.c index 6191a88904a91..4c5ce1f045d72 100644 --- a/ports/silabs/common-hal/_bleio/__init__.c +++ b/ports/silabs/common-hal/_bleio/__init__.c @@ -38,7 +38,7 @@ #include "supervisor/shared/bluetooth/bluetooth.h" #include "common-hal/_bleio/__init__.h" -STATIC conn_state_t conn_state; +static conn_state_t conn_state; osMutexId_t bluetooth_connection_mutex_id; bleio_adapter_obj_t common_hal_bleio_adapter_obj; uint8_t ble_bonding_handle = 0xFF; @@ -54,7 +54,7 @@ const osMutexAttr_t bluetooth_connection_mutex_attr = { void common_hal_bleio_init(void) { } -void bleio_user_reset() { +void bleio_user_reset(void) { // Stop any user scanning or advertising. common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj); @@ -63,7 +63,7 @@ void bleio_user_reset() { supervisor_bluetooth_background(); } -void bleio_reset() { +void bleio_reset(void) { reset_dynamic_service(); reset_packet_buffer_list(); reset_characteristic_buffer_list(); @@ -102,7 +102,7 @@ void check_ble_error(int error_code) { } } -void common_hal_bleio_check_connected(uint16_t conn_handle) { +void bleio_check_connected(uint16_t conn_handle) { if (conn_handle == BLEIO_HANDLE_INVALID) { mp_raise_ConnectionError(MP_ERROR_TEXT("Not connected")); } @@ -112,8 +112,8 @@ void common_hal_bleio_check_connected(uint16_t conn_handle) { void sl_bt_on_event(sl_bt_msg_t *evt) { bd_addr address; uint8_t address_type = 0; - STATIC uint8_t serv_idx = 0; - STATIC uint8_t device_name[16]; + static uint8_t serv_idx = 0; + static uint8_t device_name[16]; bleio_connection_internal_t *connection; bleio_service_obj_t *service; @@ -194,8 +194,7 @@ void sl_bt_on_event(sl_bt_msg_t *evt) { uuid = m_new_obj_maybe(bleio_uuid_obj_t); if (NULL == uuid) { osMutexRelease(bluetooth_connection_mutex_id); - mp_raise_bleio_BluetoothError( - MP_ERROR_TEXT("Create new service uuid obj fail")); + m_malloc_fail(sizeof(bleio_uuid_obj_t)); break; } uuid->base.type = &bleio_uuid_type; diff --git a/ports/silabs/common-hal/analogio/AnalogIn.c b/ports/silabs/common-hal/analogio/AnalogIn.c index dc2846ff41a33..57749b2551790 100644 --- a/ports/silabs/common-hal/analogio/AnalogIn.c +++ b/ports/silabs/common-hal/analogio/AnalogIn.c @@ -38,10 +38,10 @@ // Number of scan channels #define NUM_INPUTS 8 -STATIC uint8_t num_current_input = 0; -STATIC volatile uint16_t scan_result[NUM_INPUTS]; -STATIC volatile uint8_t scan_flag = 0; -STATIC IADC_ScanTable_t init_scan_table = IADC_SCANTABLE_DEFAULT; // Scan Table +static uint8_t num_current_input = 0; +static volatile uint16_t scan_result[NUM_INPUTS]; +static volatile uint8_t scan_flag = 0; +static IADC_ScanTable_t init_scan_table = IADC_SCANTABLE_DEFAULT; // Scan Table // Construct analogin pin. This function is called when init AnalogIn void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, diff --git a/ports/silabs/common-hal/busio/I2C.c b/ports/silabs/common-hal/busio/I2C.c index 4875501f7bbc9..6c2b04d821d7c 100644 --- a/ports/silabs/common-hal/busio/I2C.c +++ b/ports/silabs/common-hal/busio/I2C.c @@ -30,17 +30,8 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" -STATIC I2CSPM_Init_TypeDef i2cspm_init; -STATIC bool in_used = false; -STATIC bool never_reset = false; - -// Reser I2C peripheral -void i2c_reset(void) { - if ((!never_reset) && in_used) { - I2C_Reset(DEFAULT_I2C_PERIPHERAL); - in_used = false; - } -} +static I2CSPM_Init_TypeDef i2cspm_init; +static bool in_used = false; // Construct I2C protocol, this function init i2c peripheral void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, @@ -48,6 +39,9 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + if ((scl != NULL) && (sda != NULL)) { if (scl->function_list[ DEFAULT_I2C_PERIPHERAL == I2C1? FN_I2C1_SCL : FN_I2C0_SCL] == 1 && @@ -80,7 +74,6 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, // Never reset I2C obj when reload void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - never_reset = true; common_hal_never_reset_pin(self->sda); common_hal_never_reset_pin(self->scl); } @@ -98,10 +91,13 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { I2C_Reset(self->i2cspm); common_hal_reset_pin(self->sda); common_hal_reset_pin(self->scl); - self->sda = NULL; - self->scl = NULL; self->i2cspm = NULL; in_used = false; + common_hal_busio_i2c_mark_deinit(self); +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + self->sda = NULL; } // Probe device in I2C bus @@ -125,6 +121,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { // Lock I2C bus bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { @@ -146,7 +145,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { } // Write data to the device selected by address -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { I2C_TransferSeq_TypeDef seq; @@ -160,13 +159,13 @@ uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, ret = I2CSPM_Transfer(self->i2cspm, &seq); if (ret != i2cTransferDone) { - return MP_EIO; + return -MP_EIO; } return 0; } // Read into buffer from the device selected by address -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { @@ -181,13 +180,13 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, ret = I2CSPM_Transfer(self->i2cspm, &seq); if (ret != i2cTransferDone) { - return MP_EIO; + return -MP_EIO; } return 0; } // Write the bytes from out_data to the device selected by address, -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { @@ -205,7 +204,7 @@ uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, ret = I2CSPM_Transfer(self->i2cspm, &seq); if (ret != i2cTransferDone) { - return MP_EIO; + return -MP_EIO; } return 0; } diff --git a/ports/silabs/common-hal/busio/I2C.h b/ports/silabs/common-hal/busio/I2C.h index 14f879ee445ad..a225299280a8d 100644 --- a/ports/silabs/common-hal/busio/I2C.h +++ b/ports/silabs/common-hal/busio/I2C.h @@ -24,8 +24,7 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H -#define MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H +#pragma once #include "common-hal/microcontroller/Pin.h" #include "peripherals/periph.h" @@ -40,7 +39,3 @@ typedef struct { const mcu_pin_obj_t *scl; const mcu_pin_obj_t *sda; } busio_i2c_obj_t; - -void i2c_reset(void); - -#endif // MICROPY_INCLUDED_EFR32_COMMON_HAL_BUSIO_I2C_H diff --git a/ports/silabs/common-hal/busio/SPI.c b/ports/silabs/common-hal/busio/SPI.c index ff41b89054774..fb3b7c4fd20c7 100644 --- a/ports/silabs/common-hal/busio/SPI.c +++ b/ports/silabs/common-hal/busio/SPI.c @@ -34,19 +34,9 @@ // Note that any bugs introduced in this file can cause crashes // at startupfor chips using external SPI flash. -STATIC SPIDRV_HandleData_t spidrv_eusart_handle; -STATIC SPIDRV_Init_t spidrv_eusart_init = SPIDRV_MASTER_EUSART1; -STATIC bool in_used = false; -STATIC bool never_reset = false; - -// Reset SPI when reload -void spi_reset(void) { - if (!never_reset && in_used) { - SPIDRV_DeInit(&spidrv_eusart_handle); - in_used = false; - } - return; -} +static SPIDRV_HandleData_t spidrv_eusart_handle; +static SPIDRV_Init_t spidrv_eusart_init = SPIDRV_MASTER_EUSART1; +static bool in_used = false; // Construct SPI protocol, this function init SPI peripheral void common_hal_busio_spi_construct(busio_spi_obj_t *self, @@ -61,6 +51,9 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, MP_ERROR_TEXT("Half duplex SPI is not implemented")); } + // Ensure the object starts in its deinit state. + common_hal_busio_spi_mark_deinit(self); + if ((sck != NULL) && (mosi != NULL) && (miso != NULL)) { if (sck->function_list[FN_EUSART1_SCLK] == 1 && miso->function_list[FN_EUSART1_RX] == 1 @@ -108,7 +101,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, // Never reset SPI when reload void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - never_reset = true; common_hal_never_reset_pin(self->mosi); common_hal_never_reset_pin(self->miso); common_hal_never_reset_pin(self->sck); @@ -119,6 +111,10 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->sck == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->sck = NULL; +} + // Deinit SPI obj void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { @@ -132,13 +128,14 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { } in_used = false; - self->sck = NULL; self->mosi = NULL; self->miso = NULL; self->handle = NULL; common_hal_reset_pin(self->mosi); common_hal_reset_pin(self->miso); common_hal_reset_pin(self->sck); + + common_hal_busio_spi_mark_deinit(self); } // Configures the SPI bus. The SPI object must be locked. @@ -186,6 +183,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, // Lock SPI bus bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; if (!self->has_lock) { grabbed_lock = true; diff --git a/ports/silabs/common-hal/busio/UART.c b/ports/silabs/common-hal/busio/UART.c index 8a598cfb9030a..cfc87b6b6f828 100644 --- a/ports/silabs/common-hal/busio/UART.c +++ b/ports/silabs/common-hal/busio/UART.c @@ -42,10 +42,10 @@ DEFINE_BUF_QUEUE(UARTDRV_USART_BUFFER_SIZE, uartdrv_usart_rx_buffer); DEFINE_BUF_QUEUE(UARTDRV_USART_BUFFER_SIZE, uartdrv_usart_tx_buffer); -STATIC UARTDRV_HandleData_t uartdrv_usart_handle; -STATIC UARTDRV_InitUart_t uartdrv_usart_init; -STATIC bool in_used = false; -STATIC bool never_reset = false; +static UARTDRV_HandleData_t uartdrv_usart_handle; +static UARTDRV_InitUart_t uartdrv_usart_init; +static bool in_used = false; +static bool never_reset = false; busio_uart_obj_t *context; volatile Ecode_t errflag; // Used to restart read halts diff --git a/ports/silabs/common-hal/digitalio/DigitalInOut.h b/ports/silabs/common-hal/digitalio/DigitalInOut.h index 23a5a235378fb..a69eb48df33c1 100644 --- a/ports/silabs/common-hal/digitalio/DigitalInOut.h +++ b/ports/silabs/common-hal/digitalio/DigitalInOut.h @@ -1,29 +1,6 @@ /* * This file is part of Adafruit for EFR32 project - * - * The MIT License (MIT) - * - * Copyright 2023 Silicon Laboratories Inc. www.silabs.com - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. */ - #ifndef MICROPY_INCLUDED_EFR32_COMMON_HAL_DIGITALIO_DIGITALINOUT_H #define MICROPY_INCLUDED_EFR32_COMMON_HAL_DIGITALIO_DIGITALINOUT_H diff --git a/ports/silabs/common-hal/microcontroller/Pin.c b/ports/silabs/common-hal/microcontroller/Pin.c index d22485c40d642..249bc5ac482f2 100644 --- a/ports/silabs/common-hal/microcontroller/Pin.c +++ b/ports/silabs/common-hal/microcontroller/Pin.c @@ -32,8 +32,8 @@ #define GPIO_PORT_COUNT (MP_ARRAY_SIZE(ports)) GPIO_Port_TypeDef ports[] = {gpioPortA, gpioPortB, gpioPortC, gpioPortD}; -STATIC uint16_t claimed_pins[GPIO_PORT_COUNT]; -STATIC uint16_t __ALIGNED(4) never_reset_pins[GPIO_PORT_COUNT]; +static uint16_t claimed_pins[GPIO_PORT_COUNT]; +static uint16_t __ALIGNED(4) never_reset_pins[GPIO_PORT_COUNT]; // Reset all pin except pin in never_reset_pins list void reset_all_pins(void) { diff --git a/ports/silabs/common-hal/microcontroller/__init__.c b/ports/silabs/common-hal/microcontroller/__init__.c index b1472fcf43725..7244af6619dd6 100644 --- a/ports/silabs/common-hal/microcontroller/__init__.c +++ b/ports/silabs/common-hal/microcontroller/__init__.c @@ -60,6 +60,9 @@ void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { } } +// CHIP_Reset does not return, but is not declared as such in the SDK. +void __attribute__ ((noreturn)) CHIP_Reset(void); + void common_hal_mcu_reset(void) { filesystem_flush(); // TODO: implement as part of flash improvements CHIP_Reset(); diff --git a/ports/silabs/common-hal/nvm/ByteArray.c b/ports/silabs/common-hal/nvm/ByteArray.c index e8b56f7c725da..5a5fa0e36db4c 100644 --- a/ports/silabs/common-hal/nvm/ByteArray.c +++ b/ports/silabs/common-hal/nvm/ByteArray.c @@ -33,7 +33,7 @@ #include "nvm3_default_config.h" uint8_t nvm_array[NVM_BYTEARRAY_BUFFER_SIZE]; -STATIC bool isInitialized = false; +static bool isInitialized = false; #define NVM_KEY 98 // Get length of nvm bytearray diff --git a/ports/silabs/common-hal/os/__init__.c b/ports/silabs/common-hal/os/__init__.c index d4841556defdd..79e79875fd541 100644 --- a/ports/silabs/common-hal/os/__init__.c +++ b/ports/silabs/common-hal/os/__init__.c @@ -35,31 +35,6 @@ #include "peripherals/periph.h" #define RNG_TIMEOUT 5 -STATIC const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, EFR32_SERIES_LOWER); -STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, EFR32_SERIES_LOWER); - -STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - -STATIC MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) { return false; diff --git a/ports/silabs/mpconfigport.h b/ports/silabs/mpconfigport.h index ce7739cccaea4..26fe7dfc2f0b5 100644 --- a/ports/silabs/mpconfigport.h +++ b/ports/silabs/mpconfigport.h @@ -29,9 +29,6 @@ #include -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) - // 24kiB stack #define CIRCUITPY_DEFAULT_STACK_SIZE 0x6000 diff --git a/ports/silabs/mpconfigport.mk b/ports/silabs/mpconfigport.mk index 7c00338955f17..7192be3f4151f 100644 --- a/ports/silabs/mpconfigport.mk +++ b/ports/silabs/mpconfigport.mk @@ -3,7 +3,7 @@ INTERNAL_LIBM ?= 1 USB_NUM_ENDPOINT_PAIRS = 0 CIRCUITPY_ANALOGIO ?= 1 -CIRCUITPY_BLEIO ?= 1 +CIRCUITPY_BLEIO_NATIVE ?= 1 CIRCUITPY_BUSDEVICE ?= 1 CIRCUITPY_BUSIO ?= 1 CIRCUITPY_DIGITALIO ?= 1 @@ -15,6 +15,8 @@ CIRCUITPY_RTC ?= 1 CIRCUITPY_USB_DEVICE = 0 CIRCUITPY_WATCHDOG ?=1 +CIRCUITPY_PORT_SERIAL = 1 + ifeq ($(MCU_SERIES),MG24) # Not yet implemented common-hal modules: CIRCUITPY_AUDIOIO ?= 0 diff --git a/ports/silabs/qstrdefsport.h b/ports/silabs/qstrdefsport.h index 3ba897069bf73..00d3e2ae3c555 100644 --- a/ports/silabs/qstrdefsport.h +++ b/ports/silabs/qstrdefsport.h @@ -1 +1,2 @@ // qstrs specific to this port +// *FORMAT-OFF* diff --git a/ports/silabs/supervisor/internal_flash.c b/ports/silabs/supervisor/internal_flash.c index bb2b16726d30d..5cb60d220f510 100644 --- a/ports/silabs/supervisor/internal_flash.c +++ b/ports/silabs/supervisor/internal_flash.c @@ -51,7 +51,7 @@ uint8_t _flash_cache[FLASH_PAGE_SIZE] __attribute__((aligned(4))); uint32_t _flash_page_addr = NO_CACHE; -STATIC inline uint32_t lba2addr(uint32_t block) { +static inline uint32_t lba2addr(uint32_t block) { return CIRCUITPY_INTERNAL_FLASH_FILESYSTEM_START_ADDR + block * FILESYSTEM_BLOCK_SIZE; } diff --git a/ports/silabs/supervisor/port.c b/ports/silabs/supervisor/port.c index 19a35da5a9fc2..85a6e0f92a5ec 100644 --- a/ports/silabs/supervisor/port.c +++ b/ports/silabs/supervisor/port.c @@ -33,7 +33,6 @@ #include "shared-bindings/microcontroller/__init__.h" #if CIRCUITPY_BUSIO -#include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/busio/UART.h" #endif @@ -88,20 +87,20 @@ uint32_t _ebss; uint32_t *heap; uint32_t heap_size; -STATIC sl_sleeptimer_timer_handle_t _tick_timer; -STATIC sl_sleeptimer_timer_handle_t _sleep_timer; +static sl_sleeptimer_timer_handle_t _tick_timer; +static sl_sleeptimer_timer_handle_t _sleep_timer; // CircuitPython stack thread -STATIC void circuitpython_thread(void *p_arg); -STATIC osThreadId_t tid_thread_circuitpython; +static void circuitpython_thread(void *p_arg); +static osThreadId_t tid_thread_circuitpython; __ALIGNED(8) -STATIC uint8_t thread_circuitpython_stk[(CIRCUITPY_DEFAULT_STACK_SIZE + +static uint8_t thread_circuitpython_stk[(CIRCUITPY_DEFAULT_STACK_SIZE + SL_CIRCUITPYTHON_TASK_STACK_EXTRA_SIZE) & 0xFFFFFFF8u]; __ALIGNED(4) -STATIC uint8_t thread_circuitpython_cb[osThreadCbSize]; +static uint8_t thread_circuitpython_cb[osThreadCbSize]; -STATIC const osThreadAttr_t thread_circuitpython_attr = { +static const osThreadAttr_t thread_circuitpython_attr = { .name = "CircuitPython stack", .stack_mem = thread_circuitpython_stk, .stack_size = sizeof(thread_circuitpython_stk), @@ -110,7 +109,7 @@ STATIC const osThreadAttr_t thread_circuitpython_attr = { .priority = (osPriority_t)SL_CIRCUITPYTHON_TASK_PRIORITY }; -STATIC bool isSchedulerStarted = false; +static bool isSchedulerStarted = false; safe_mode_t port_init(void) { #if defined(SL_CATALOG_KERNEL_PRESENT) @@ -157,11 +156,7 @@ safe_mode_t port_init(void) { } void reset_port(void) { - reset_all_pins(); - #if CIRCUITPY_BUSIO - i2c_reset(); - spi_reset(); uart_reset(); #endif @@ -223,7 +218,7 @@ uint64_t port_get_raw_ticks(uint8_t *subticks) { } // Periodic tick timer callback -STATIC void on_tick_timer_timeout(sl_sleeptimer_timer_handle_t *handle, +static void on_tick_timer_timeout(sl_sleeptimer_timer_handle_t *handle, void *data) { (void)&handle; (void)&data; @@ -255,7 +250,7 @@ void port_wake_main_task(void) { osThreadFlagsSet(tid_thread_circuitpython, 0x0001); } -STATIC void on_sleep_timer_timeout(sl_sleeptimer_timer_handle_t *handle, +static void on_sleep_timer_timeout(sl_sleeptimer_timer_handle_t *handle, void *data) { port_wake_main_task(); } diff --git a/ports/silabs/supervisor/serial.c b/ports/silabs/supervisor/serial.c index e19bde8965afd..25dc86c1da9b3 100644 --- a/ports/silabs/supervisor/serial.c +++ b/ports/silabs/supervisor/serial.c @@ -48,9 +48,9 @@ #define EUSART_VCOM_RX_PORT gpioPortA #define EUSART_VCOM_RX_PIN 6 -STATIC ringbuf_t con_uart_rx_ringbuf; -STATIC byte con_uart_rx_buf[CONSOLE_RCV_BUFFER_SIZE]; -STATIC volatile uint8_t received_data; +static ringbuf_t con_uart_rx_ringbuf; +static byte con_uart_rx_buf[CONSOLE_RCV_BUFFER_SIZE]; +static volatile uint8_t received_data; // USART0 RX interrupt handler , put characters to ring buffer one by one void EUSART0_RX_IRQHandler(void) { diff --git a/ports/silabs/tools/make_pins.py b/ports/silabs/tools/make_pins.py index bd4973d3e098c..9ae370bf6dee2 100644 --- a/ports/silabs/tools/make_pins.py +++ b/ports/silabs/tools/make_pins.py @@ -53,7 +53,7 @@ def make_mcu_dict_entry2(pin): def make_mcu_dict(pins): """Create the mcu dictionary""" - decl = "\n\nSTATIC const mp_rom_map_elem_t board_module_globals_table[] = {\n" + decl = "\n\nstatic const mp_rom_map_elem_t board_module_globals_table[] = {\n" decl += "\tCIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS\n" for pin in pins.values(): decl += "\t" + make_mcu_dict_entry(pin) + "\n" @@ -124,7 +124,7 @@ def make_pin_function_lists(functions, pins): fcn_list[pin][i] = 1 i += 1 for pin in pins.keys(): - if not pin in fcn_list: + if pin not in fcn_list: fcn_list[pin] = [] decl += make_pin_function_list_decl(pin, fcn_list[pin]) diff --git a/ports/stm/Makefile b/ports/stm/Makefile index d42ebdc727612..2ed3bddb5b7fb 100755 --- a/ports/stm/Makefile +++ b/ports/stm/Makefile @@ -38,8 +38,7 @@ ifeq ($(DEBUG), 1) CFLAGS += -fno-inline -fno-ipa-sra else CFLAGS += -DNDEBUG - OPTIMIZATION_FLAGS ?= -O2 -fno-inline-functions - CFLAGS += -ggdb3 + OPTIMIZATION_FLAGS ?= -O2 endif # to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk @@ -48,10 +47,10 @@ CFLAGS += $(OPTIMIZATION_FLAGS) # Add -ftree-vrp optimization and checking to all builds. It's not enabled for -Os by default. CFLAGS += -ftree-vrp -# MCU Series is defined by the HAL package and doesn't need to be specified here -C_DEFS = -D$(MCU_PACKAGE) -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -D$(MCU_VARIANT) +# STM32 MCU series must be defined. See supervisor/linker.h +C_DEFS = -D$(MCU_PACKAGE) -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -D$(MCU_VARIANT) -DSTM32$(MCU_SERIES) -CFLAGS += $(INC) -Werror -Wall -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -nostdlib -nostartfiles +CFLAGS += $(INC) -Werror -Wall -std=gnu11 -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT) -nostdlib -nostartfiles -Werror=old-style-definition # Undo some warnings. # STM32 HAL uses undefined preprocessor variables, shadowed variables, casts that change alignment reqs @@ -73,7 +72,7 @@ CFLAGS += -DSTM32_HAL_H="" CFLAGS += -DSTM32_SERIES_LOWER='"stm32$(MCU_SERIES_LOWER)"' # Floating point settings -ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F765xx STM32F767xx STM32F769xx STM32H743xx)) +ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F765xx STM32F767xx STM32F769xx STM32H743xx STM32H750xx)) CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard else CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -165,10 +164,17 @@ endif # Need this to avoid UART linker problems. TODO: rewrite to use registered callbacks. # Does not exist for F4 and lower -ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F765xx STM32F767xx STM32F769xx STM32H743xx STM32L4R5xx)) +ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F765xx STM32F767xx STM32F769xx STM32H743xx STM32H750xx STM32L4R5xx STM32L433xx)) SRC_STM32 += $(HAL_DIR)/Src/stm32$(MCU_SERIES_LOWER)xx_hal_uart_ex.c endif +ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32H750xx)) + C_DEFS += -DHAL_SDRAM_MODULE_ENABLED + SRC_STM32 += st_driver/stm32$(MCU_SERIES_LOWER)xx_hal_driver/Src/stm32h7xx_hal_sdram.c + SRC_STM32 += st_driver/stm32$(MCU_SERIES_LOWER)xx_hal_driver/Src/stm32h7xx_ll_fmc.c + SRC_C += peripherals/sdram.c +endif + SRC_STM32 += boards/system_stm32$(MCU_SERIES_LOWER)xx.c SRC_C += \ @@ -197,21 +203,19 @@ ifneq ($(CIRCUITPY_AUDIOBUSIO_PDMIN),0) endif ifneq ($(CIRCUITPY_USB),0) -SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c + ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32L433xx)) + SRC_C += lib/tinyusb/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c + else + SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c + SRC_C += lib/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c + endif endif SRC_S = \ - supervisor/cpu.s \ + shared/runtime/gchelper_thumb1.s \ st_driver/cmsis_device_$(MCU_SERIES_LOWER)/Source/Templates/gcc/startup_$(MCU_VARIANT_LOWER).s -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ - $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) - +SRC_C += shared/runtime/gchelper_native.c ifneq ($(FROZEN_MPY_DIR),) FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') @@ -220,8 +224,7 @@ endif OBJ += $(PY_O) $(SUPERVISOR_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_STM32:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) -OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED:.c=.o)) ifeq ($(INTERNAL_LIBM),1) OBJ += $(addprefix $(BUILD)/, $(SRC_LIBM:.c=.o)) endif @@ -233,12 +236,12 @@ $(BUILD)/$(FATFS_DIR)/ff.o: COPT += -Os $(filter $(PY_BUILD)/../extmod/vfs_fat_%.o, $(PY_O)): COPT += -Os # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) +SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_MOD) $(SRC_COMMON_HAL_SHARED_MODULE_EXPANDED) $(SRC_CIRCUITPY_COMMON) # Sources that only hold QSTRs after pre-processing. SRC_QSTR_PREPROCESSOR += # Bin section settings specific to the STM32H7 -ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32H743xx)) +ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32H743xx STM32H750xx)) MCU_SECTIONS = -j .isr_vector -j .text -j .data -j .itcm -j .dtcm_data $^ $@ else MCU_SECTIONS = $^ $@ diff --git a/ports/stm/boards/STM32H750.ld b/ports/stm/boards/STM32H750.ld new file mode 100644 index 0000000000000..e10a2ce91f705 --- /dev/null +++ b/ports/stm/boards/STM32H750.ld @@ -0,0 +1,34 @@ +/* + GNU linker script for STM32H750 +*/ + +/* Entry Point */ +ENTRY(Reset_Handler) + +_ld_default_stack_size = 24K; + +/* Specify the memory areas -- CircuitPython is loaded on the external QSPI flash */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x90000000, LENGTH = 8M /* 8M */ + FLASH_ISR (rx) : ORIGIN = 0x90000000, LENGTH = 4K /* sector 0 */ + FLASH_FIRMWARE (rx) : ORIGIN = 0x90001000, LENGTH = 8M-4K + DTCM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K + RAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K /* AXI SRAM */ + SRAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K /* AHB1 SRAM */ + SRAM_D3 (xrw) : ORIGIN = 0x30040000, LENGTH = 64K /* AHB2 SRAM */ + ITCM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 24K; /*TODO: this can probably be bigger, but how big?*/ +_minimum_heap_size = 16K; + +/* Define tho top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(DTCM) + LENGTH(DTCM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); diff --git a/ports/stm/boards/STM32L433_boot.ld b/ports/stm/boards/STM32L433_boot.ld new file mode 100644 index 0000000000000..686547a8ce6e7 --- /dev/null +++ b/ports/stm/boards/STM32L433_boot.ld @@ -0,0 +1,27 @@ +/* + GNU linker script for STM32L433 with bootloader +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256k /* entire flash */ + FLASH_ISR (rx) : ORIGIN = 0x08010000, LENGTH = 4K /* ISR vector. Kind of wasteful. */ + FLASH_FIRMWARE (rx) : ORIGIN = 0x08011000, LENGTH = 192K-64K-4K + FLASH_FS (rw) : ORIGIN = 0x08030000, LENGTH = 60K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 640K +} + + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 24K; +_minimum_heap_size = 16K; + +/* Define the top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); diff --git a/ports/stm/boards/STM32L433_default.ld b/ports/stm/boards/STM32L433_default.ld new file mode 100644 index 0000000000000..886a1b8827a20 --- /dev/null +++ b/ports/stm/boards/STM32L433_default.ld @@ -0,0 +1,29 @@ +/* + GNU linker script for STM32L433 with filesystem +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K /* entire flash */ + FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* ISR vector. */ + FLASH_FS (rw) : ORIGIN = 0x08004000, LENGTH = 48K + FLASH_FIRMWARE (rx) : ORIGIN = 0x08010000, LENGTH = 256K - 48K - 16K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 24K; +_minimum_heap_size = 16K; + +/* Define the top end of the stack. The stack is full descending so begins just + above last byte of RAM. Note that EABI requires the stack to be 8-byte + aligned for a call. */ +_estack = ORIGIN(RAM) + LENGTH(RAM); + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +/* ensure the firmware is within bounds */ +ASSERT ( (ORIGIN(FLASH_FIRMWARE) + LENGTH(FLASH_FIRMWARE)) <= (ORIGIN(FLASH)+LENGTH(FLASH)), "FLASH_FIRMWARE out of bounds" ); diff --git a/ports/stm/boards/blues_cygnet/board.c b/ports/stm/boards/blues_cygnet/board.c new file mode 100644 index 0000000000000..f6650fb8f9c33 --- /dev/null +++ b/ports/stm/boards/blues_cygnet/board.c @@ -0,0 +1,79 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/board.h" +#include "mpconfigboard.h" + +#include "stm32l4xx.h" +#include "stm32l433xx.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "board.h" + +digitalio_digitalinout_obj_t power_pin = { .base.type = &digitalio_digitalinout_type }; +digitalio_digitalinout_obj_t discharge_pin = { .base.type = &digitalio_digitalinout_type }; + +void initialize_discharge_pin(void) { + /* Initialize the 3V3 discharge to be OFF and the output power to be ON */ + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + + common_hal_digitalio_digitalinout_construct(&power_pin, &pin_PH00); + common_hal_digitalio_digitalinout_construct(&discharge_pin, &pin_PH01); + common_hal_digitalio_digitalinout_never_reset(&power_pin); + common_hal_digitalio_digitalinout_never_reset(&discharge_pin); + + GPIO_InitTypeDef GPIO_InitStruct; + + /* Set DISCHARGE_3V3 as well as the pins we're not initially using to FLOAT */ + GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Pin = GPIO_PIN_1; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); /* PH1 DISCHARGE_3V3 */ + GPIO_InitStruct.Pin = GPIO_PIN_3; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* PB3 is USB_DETECT */ + GPIO_InitStruct.Pin = GPIO_PIN_15; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* PA15 is CHARGE_DETECT */ + GPIO_InitStruct.Pin = GPIO_PIN_4; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* PA4 is BAT_VOLTAGE */ + + /* Turn on the 3V3 regulator */ + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Pin = GPIO_PIN_0; + HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOH, GPIO_InitStruct.Pin, GPIO_PIN_SET); +} + +void board_init(void) { + // enable the debugger while sleeping. Todo move somewhere more central (kind of generally useful in a debug build) + SET_BIT(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); + + // Set tick interrupt priority, default HAL value is intentionally invalid + // Without this, USB does not function. + HAL_InitTick((1UL << __NVIC_PRIO_BITS) - 1UL); + + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_LOW; + GPIO_InitStruct.Pin = GPIO_PIN_8; + HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET); + HAL_Delay(50); + HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET); +} + +void reset_board(void) { + initialize_discharge_pin(); +} + +// Use the MP_WEAK supervisor/shared/board.c versions of routines not defined here. diff --git a/ports/stm/boards/blues_cygnet/board.h b/ports/stm/boards/blues_cygnet/board.h new file mode 100644 index 0000000000000..ce199359ba496 --- /dev/null +++ b/ports/stm/boards/blues_cygnet/board.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/digitalio/DigitalInOut.h" + +extern digitalio_digitalinout_obj_t power_pin; +extern digitalio_digitalinout_obj_t discharge_pin; diff --git a/ports/stm/boards/blues_cygnet/mpconfigboard.h b/ports/stm/boards/blues_cygnet/mpconfigboard.h new file mode 100644 index 0000000000000..f3b1fcc2eb72c --- /dev/null +++ b/ports/stm/boards/blues_cygnet/mpconfigboard.h @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Blues Wireless Contributors. +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "Cygnet" +#define MICROPY_HW_MCU_NAME "STM32L433CCT6" + +#define MICROPY_PY_SYS_PLATFORM MICROPY_HW_BOARD_NAME + +#define STM32L433XX +#define BOARD_CYGNET + +#define LSE_VALUE ((uint32_t)32768) +#define BOARD_HAS_LOW_SPEED_CRYSTAL (1) +#define BOARD_HAS_HIGH_SPEED_CRYSTAL (0) + +// Increase drive strength of 32kHz external crystal, in line with calculations specified in ST AN2867 sections 3.3, 3.4, and STM32L4 datasheet DS12023 Table 58. LSE oscillator characteristics. +// The drive strength RCC_LSEDRIVE_LOW is marginal for the 32kHz crystal oscillator stability, and RCC_LSEDRIVE_MEDIUMLOW meets the calculated drive strength with a small margin for parasitic capacitance. +#define BOARD_LSE_DRIVE_LEVEL RCC_LSEDRIVE_MEDIUMLOW + +// Bootloader only +#ifdef UF2_BOOTLOADER_ENABLED + #define BOARD_VTOR_DEFER (1) // Leave VTOR relocation to bootloader +#endif + +#define BOARD_NO_VBUS_SENSE (1) +#define BOARD_NO_USB_OTG_ID_SENSE (1) + +#define DEFAULT_I2C_BUS_SCL (&pin_PB06) +#define DEFAULT_I2C_BUS_SDA (&pin_PB07) + +#define DEFAULT_SPI_BUS_SS (&pin_PB08) +#define DEFAULT_SPI_BUS_SCK (&pin_PA05) +#define DEFAULT_SPI_BUS_MOSI (&pin_PB05) +#define DEFAULT_SPI_BUS_MISO (&pin_PB06) + +#define DEFAULT_UART_BUS_RX (&pin_PA10) +#define DEFAULT_UART_BUS_TX (&pin_PA09) + +#define CYGNET_DISCHARGE_3V3 (&pin_PH01) +#define CYGNET_ENABLE_3V3 (&pin_PH00) diff --git a/ports/stm/boards/blues_cygnet/mpconfigboard.mk b/ports/stm/boards/blues_cygnet/mpconfigboard.mk new file mode 100644 index 0000000000000..48e8241c7a6b8 --- /dev/null +++ b/ports/stm/boards/blues_cygnet/mpconfigboard.mk @@ -0,0 +1,105 @@ +USB_VID = 0x30A4 +USB_PID = 0x03 +USB_PRODUCT = "Cygnet" +USB_MANUFACTURER = "Blues Inc." + +MCU_SERIES = L4 +MCU_VARIANT = STM32L433xx +MCU_PACKAGE = LQFP48 + +LD_COMMON = boards/common_default.ld +LD_DEFAULT = boards/STM32L433_default.ld +UF2_OFFSET = 0x8000000 +UF2_BOOTLOADER ?= 0 +CIRCUITPY_BUILD_EXTENSIONS = bin + +INTERNAL_FLASH_FILESYSTEM = 1 +LONGINT_IMPL = NONE +CIRCUITPY_FULL_BUILD = 0 + +CIRCUITPY_AESIO = 0 +CIRCUITPY_ALARM = 0 +CIRCUITPY_ANALOGIO = 1 +CIRCUITPY_ATEXIT = 0 +CIRCUITPY_AUDIOBUSIO = 0 +CIRCUITPY_AUDIOBUSIO_I2SOUT = 0 +CIRCUITPY_AUDIOBUSIO_PDMIN = 0 +CIRCUITPY_AUDIOMIXER = 0 +CIRCUITPY_AUDIOMP3 = 0 +CIRCUITPY_AUDIOPWMIO = 0 +CIRCUITPY_BITBANGIO = 1 +CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_BINASCII = 0 +CIRCUITPY_BITMAPFILTER = 0 +CIRCUITPY_BITMAPTOOLS = 0 +CIRCUITPY_BUILTINS_POW3 = 0 +CIRCUITPY_BUSDEVICE = 0 +CIRCUITPY_BUSIO = 1 +CIRCUITPY_CANIO = 0 +CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE = 1 +CIRCUITPY_COUNTIO = 0 +CIRCUITPY_DIGITALIO = 1 +CIRCUITPY_DISPLAYIO = 0 +CIRCUITPY_ENABLE_MPY_NATIVE = 0 +CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_FREQUENCYIO = 0 +CIRCUITPY_FUTURE= 0 +CIRCUITPY_GETPASS = 0 +CIRCUITPY_GIFIO = 0 +CIRCUITPY_I2CTARGET = 0 +CIRCUITPY_JSON = 0 +CIRCUITPY_KEYPAD = 0 +CIRCUITPY_KEYPAD_DEMUX = 0 +CIRCUITPY_LTO = 1 +CIRCUITPY_MICROCONTROLLER = 1 +CIRCUITPY_MSGPACK = 0 +CIRCUITPY_NEOPIXEL_WRITE = 0 +CIRCUITPY_NVM = 0 +CIRCUITPY_ONEWIREIO = 0 +CIRCUITPY_OS = 1 +CIRCUITPY_PIXELBUF = 0 +CIRCUITPY_PIXELMAP = 0 +CIRCUITPY_PULSEIO = 1 +CIRCUITPY_PWMIO = 1 +CIRCUITPY_RANDOM = 0 +CIRCUITPY_RAINBOWIO = 0 +CIRCUITPY_RE = 0 +CIRCUITPY_REQUIRE_I2C_PULLUPS = 0 +CIRCUITPY_ROTARYIO_SOFTENCODER = 1 +CIRCUITPY_RGBMATRIX = 0 +CIRCUITPY_RTC = 0 +CIRCUITPY_SAFEMODE_PY = 0 +CIRCUITPY_SDCARDIO = 0 +CIRCUITPY_STATUS_BAR= 0 +CIRCUITPY_STORAGE = 1 +CIRCUITPY_SUPERVISOR = 1 +CIRCUITPY_SYNTHIO = 0 +CIRCUITPY_TERMINALIO = 0 +CIRCUITPY_TOUCHIO = 0 +CIRCUITPY_TOUCHIO_USE_NATIVE = 1 +CIRCUITPY_TRACEBACK = 0 +CIRCUITPY_ULAB = 0 +CIRCUITPY_USB_CDC = 1 +CIRCUITPY_USB_HID = 0 +CIRCUITPY_USB_IDENTIFICATION = 1 +CIRCUITPY_USB_MIDI = 0 +CIRCUITPY_USB_MIDI_ENABLED_DEFAULT= 0 +CIRCUITPY_USB_MSC = 1 +CIRCUITPY_USB_VENDOR = 0 +CIRCUITPY_WIFI_RADIO_SETTABLE_MAC_ADDRESS= 0 +CIRCUITPY_VECTORIO = 0 +CIRCUITPY_ZLIB = 0 + +MICROPY_PY_ASYNC_AWAIT = 0 + +RELEASE_NEEDS_CLEAN_BUILD = 0 + +SUPEROPT_GC = 0 +SUPEROPT_VM = 0 + +CIRCUITPY_LTO_PARTITION = one + +OPTIMIZATION_FLAGS = -Os + +CFLAGS_BOARD = -fweb -frename-registers diff --git a/ports/stm/boards/blues_cygnet/pins.c b/ports/stm/boards/blues_cygnet/pins.c new file mode 100644 index 0000000000000..f644160e4fd2a --- /dev/null +++ b/ports/stm/boards/blues_cygnet/pins.c @@ -0,0 +1,52 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// #include "py/objtuple.h" +#include "shared-bindings/board/__init__.h" +#include "board.h" + +// Core Feather Pins +static const mp_rom_map_elem_t board_module_globals_table[] = { + CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + + { MP_ROM_QSTR(MP_QSTR_ENABLE_3V3), &power_pin }, + { MP_ROM_QSTR(MP_QSTR_DISCHARGE_3V3), &discharge_pin }, + + { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PA07) }, + + { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_BUTTON_USR), MP_ROM_PTR(&pin_PC13) }, + + { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB14) }, + { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PB15) }, + + { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB04) }, // ADC, PWM, DAC2 output also + + { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PB07) }, // PWM + { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PB06) }, // PWM + + { MP_ROM_QSTR(MP_QSTR_SS), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA13) }, + { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB05) }, + + { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA09) }, // ADC, PWM + { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA10) }, // PWM + + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) }, + { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) }, +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm/boards/common_tcm.ld b/ports/stm/boards/common_tcm.ld index d7be64d6679bc..6301dbf315b8f 100644 --- a/ports/stm/boards/common_tcm.ld +++ b/ports/stm/boards/common_tcm.ld @@ -134,6 +134,16 @@ SECTIONS } > DTCM _ld_stack_top = ORIGIN(DTCM) + LENGTH(DTCM); + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >FLASH_FIRMWARE + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH_FIRMWARE .ARM.attributes 0 : { *(.ARM.attributes) } } diff --git a/ports/stm/boards/daisy_seed_with_sdram/board.c b/ports/stm/boards/daisy_seed_with_sdram/board.c new file mode 100644 index 0000000000000..f135bcbc2e0ab --- /dev/null +++ b/ports/stm/boards/daisy_seed_with_sdram/board.c @@ -0,0 +1,60 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT +#include STM32_HAL_H + +#include "supervisor/board.h" +#include "supervisor/stm.h" +#include "sdram.h" + + +/** SDRAM banks configuration. */ +static const struct stm32_sdram_bank_config bank_config[] = { + { .init = { + .SDBank = FMC_SDRAM_BANK1, + .ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9, + .RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13, + .MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32, + .InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4, + .CASLatency = FMC_SDRAM_CAS_LATENCY_3, + .WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE, + .SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2, + .ReadBurst = FMC_SDRAM_RBURST_ENABLE, + .ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0 + }, + .timing = { + .LoadToActiveDelay = 2, + .ExitSelfRefreshDelay = 8, + .SelfRefreshTime = 5, + .RowCycleDelay = 6, + .WriteRecoveryTime = 3, + .RPDelay = 2, + .RCDDelay = 2 + }} +}; + +/* SDRAM configuration. */ +static const struct stm32_sdram_config config = { + .sdram = FMC_SDRAM_DEVICE, + .power_up_delay = 100, + .num_auto_refresh = 8, + .mode_register = SDRAM_MODEREG_BURST_LENGTH_4 | + SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | + SDRAM_MODEREG_CAS_LATENCY_3 | + SDRAM_MODEREG_WRITEBURST_MODE_SINGLE, + /* Set the device refresh rate based on the RM0433 STM reference manual + refresh_rate = [(SDRAM self refresh time / number of rows) x SDRAM CLK] – 20 + = [(64ms/8192) * 100MHz] - 20 = 781.25 - 20 + */ + .refresh_rate = (64 * 100000 / 8192 - 20), + .banks = bank_config, + .banks_len = 1, +}; + +void board_init(void) { + sdram_init(&config); +// sdram_test(true); + stm_add_sdram_to_heap(); +} diff --git a/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.h b/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.h new file mode 100644 index 0000000000000..4951072d9100b --- /dev/null +++ b/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +// Micropython setup + +#define MICROPY_HW_BOARD_NAME "DAISY_SEED" +#define MICROPY_HW_MCU_NAME "STM32H750xx" + +#define MICROPY_HW_LED_STATUS (&pin_PC07) + +// H7 and F7 MPU definitions +#define CPY_FLASH_REGION_SIZE ARM_MPU_REGION_SIZE_8MB +#define CPY_ITCM_REGION_SIZE ARM_MPU_REGION_SIZE_64KB +#define CPY_DTCM_REGION_SIZE ARM_MPU_REGION_SIZE_128KB +#define CPY_SRAM_REGION_SIZE ARM_MPU_REGION_SIZE_512KB +#define CPY_SRAM_SUBMASK 0x00 +#define CPY_SRAM_START_ADDR 0x24000000 + +#define HSE_VALUE ((uint32_t)16000000) +#define BOARD_HSE_SOURCE (RCC_HSE_ON) // use external oscillator +#define BOARD_HAS_LOW_SPEED_CRYSTAL (0) + +#define CIRCUITPY_CONSOLE_UART_TX (&pin_PB09) +#define CIRCUITPY_CONSOLE_UART_RX (&pin_PB08) + +// USB +#define BOARD_NO_USB_OTG_ID_SENSE (1) + +// for RNG not audio +#define CPY_CLK_USB_USES_AUDIOPLL (1) + +// SDRAM and MPU region + +#define CIRCUITPY_HW_SDRAM_SIZE (64 * 1024 * 1024) // 64 MByte + +#define CPY_SDRAM_REGION MPU_REGION_NUMBER10 +#define CPY_SDRAM_REGION_SIZE MPU_REGION_SIZE_64MB diff --git a/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.mk b/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.mk new file mode 100644 index 0000000000000..a43c4ed177b6a --- /dev/null +++ b/ports/stm/boards/daisy_seed_with_sdram/mpconfigboard.mk @@ -0,0 +1,18 @@ +USB_VID = 0x0483 +USB_PID = 0x5740 +USB_PRODUCT = "Daisy Seed" +USB_MANUFACTURER = "STMicroelectronics" + +# Small FS created on half of the internal flash -- other half is reserved for the H750 bootloader +INTERNAL_FLASH_FILESYSTEM = 1 + +MCU_SERIES = H7 +MCU_VARIANT = STM32H750xx +MCU_PACKAGE = UFBGA176 + +LD_COMMON = boards/common_tcm.ld +LD_FILE = boards/STM32H750.ld + +CIRCUITPY_SDIOIO = 1 +CIRCUITPY_PWMIO = 1 +CIRCUITPY_AUDIOPWMIO = 1 diff --git a/ports/stm/boards/daisy_seed_with_sdram/pins.c b/ports/stm/boards/daisy_seed_with_sdram/pins.c new file mode 100644 index 0000000000000..b8f8f05b901c7 --- /dev/null +++ b/ports/stm/boards/daisy_seed_with_sdram/pins.c @@ -0,0 +1,61 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/board/__init__.h" + +// See pinout on Daisy Seed product page +// https://electro-smith.com/products/daisy-seed?variant=45234245108004 +static const mp_rom_map_elem_t board_module_globals_table[] = { + {MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PC07)}, + {MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_PG03)}, + {MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB12)}, + {MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PC11)}, + {MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PC10)}, + {MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PC09)}, + {MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PC08)}, + {MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PD02)}, + {MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PC12)}, + {MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PG10)}, + {MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PG11)}, + {MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PB04)}, + {MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PB05)}, + {MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PB08)}, + {MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PB09)}, + {MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PB06)}, + {MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PB07)}, + + {MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_PC00)}, + {MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PC00)}, + {MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_PA03)}, + {MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA03)}, + {MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_PB01)}, + {MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB01)}, + {MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_PA07)}, + {MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07)}, + {MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_PA06)}, + {MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA06)}, + {MP_ROM_QSTR(MP_QSTR_D20), MP_ROM_PTR(&pin_PC01)}, + {MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PC01)}, + {MP_ROM_QSTR(MP_QSTR_D21), MP_ROM_PTR(&pin_PC04)}, + {MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PC04)}, + {MP_ROM_QSTR(MP_QSTR_D22), MP_ROM_PTR(&pin_PA05)}, + {MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PA05)}, + {MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_PA04)}, + {MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA04)}, + {MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_PA01)}, + {MP_ROM_QSTR(MP_QSTR_A9), MP_ROM_PTR(&pin_PA01)}, + {MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_PA00)}, + {MP_ROM_QSTR(MP_QSTR_A10), MP_ROM_PTR(&pin_PA00)}, + {MP_ROM_QSTR(MP_QSTR_D26), MP_ROM_PTR(&pin_PD11)}, + {MP_ROM_QSTR(MP_QSTR_D27), MP_ROM_PTR(&pin_PG09)}, + {MP_ROM_QSTR(MP_QSTR_D28), MP_ROM_PTR(&pin_PA02)}, + {MP_ROM_QSTR(MP_QSTR_A11), MP_ROM_PTR(&pin_PA02)}, + {MP_ROM_QSTR(MP_QSTR_D29), MP_ROM_PTR(&pin_PB14)}, + {MP_ROM_QSTR(MP_QSTR_D30), MP_ROM_PTR(&pin_PB15)}, + +}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); diff --git a/ports/stm/boards/espruino_pico/README.md b/ports/stm/boards/espruino_pico/README.md index 86df1ad32a380..d930e9aeca30c 100644 --- a/ports/stm/boards/espruino_pico/README.md +++ b/ports/stm/boards/espruino_pico/README.md @@ -12,4 +12,4 @@ The Espruino Pico is normally updated via a bootloader activated by the Espruino - Restart the board. -To reinstall Espruino, follow the same steps with the latest Espruino Pico binary from espruino.com/binaries. This will reinstall the usual Espruino bootloader. You must un-short the BOOT0/BTN jumper to re-use the original Espruino Bootloader again. If you used a Pencil mark then you may need to use cleaning fluid and a small brush to totally clear out the graphite. +To reinstall Espruino, follow the same steps with the latest Espruino Pico binary from espruino.com/binaries. This will reinstall the usual Espruino bootloader. You must un-short the BOOT0/BTN jumper to reuse the original Espruino Bootloader again. If you used a Pencil mark then you may need to use cleaning fluid and a small brush to totally clear out the graphite. diff --git a/ports/stm/boards/espruino_wifi/README.MD b/ports/stm/boards/espruino_wifi/README.MD index cc78811f1c7e0..cebe99bf6d1a8 100644 --- a/ports/stm/boards/espruino_wifi/README.MD +++ b/ports/stm/boards/espruino_wifi/README.MD @@ -12,4 +12,4 @@ The Espruino Wifi is normally updated via a bootloader activated by the Espruino - Restart the board. -To reinstall Espruino, follow the same steps with the latest Espruino Wifi binary from espruino.com/binaries. This will reinstall the usual Espruino bootloader. You must un-short the BOOT0/BTN jumper to re-use the original Espruino Bootloader again. If you used a Pencil mark then you may need to use cleaning fluid and a small brush to totally clear out the graphite. +To reinstall Espruino, follow the same steps with the latest Espruino Wifi binary from espruino.com/binaries. This will reinstall the usual Espruino bootloader. You must un-short the BOOT0/BTN jumper to reuse the original Espruino Bootloader again. If you used a Pencil mark then you may need to use cleaning fluid and a small brush to totally clear out the graphite. diff --git a/ports/stm/boards/meowbit_v121/board.c b/ports/stm/boards/meowbit_v121/board.c index 181f433a372b9..c3c745f64a14d 100644 --- a/ports/stm/boards/meowbit_v121/board.c +++ b/ports/stm/boards/meowbit_v121/board.c @@ -55,9 +55,9 @@ void board_init(void) { busio_spi_obj_t *internal_spi = &supervisor_flash_spi_bus; common_hal_fourwire_fourwire_construct(bus, internal_spi, - &pin_PA08, // Command or data - &pin_PB12, // Chip select - &pin_PB10, // Reset + MP_OBJ_FROM_PTR(&pin_PA08), // Command or data + MP_OBJ_FROM_PTR(&pin_PB12), // Chip select + MP_OBJ_FROM_PTR(&pin_PB10), // Reset 24000000, // Baudrate 0, // Polarity 0); // Phase diff --git a/ports/stm/boards/meowbit_v121/mpconfigboard.mk b/ports/stm/boards/meowbit_v121/mpconfigboard.mk index 1dfda9a1759a5..419f073b5ea2c 100644 --- a/ports/stm/boards/meowbit_v121/mpconfigboard.mk +++ b/ports/stm/boards/meowbit_v121/mpconfigboard.mk @@ -23,12 +23,22 @@ LD_FILE = boards/STM32F401xe_boot.ld # LD_FILE = boards/STM32F401xe_fs.ld CIRCUITPY_AESIO = 0 +CIRCUITPY_CODEOP = 0 CIRCUITPY_BITMAPFILTER = 0 CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_BLEIO_HCI = 0 -CIRCUITPY_GIFIO = 0 +CIRCUITPY_EPAPERDISPLAY = 0 +CIRCUITPY_FRAMEBUFFERIO = 0 +CIRCUITPY_I2CDISPLAYBUS = 0 +CIRCUITPY_KEYPAD_DEMUX = 0 +CIRCUITPY_PIXELMAP = 0 +CIRCUITPY_SHARPDISPLAY = 0 +CIRCUITPY_TILEPALETTEMAPPER = 0 CIRCUITPY_ULAB = 0 -CIRCUITPY_STAGE = 1 CIRCUITPY_ZLIB = 0 +CIRCUITPY_STAGE = 1 + +CIRCUITPY_DIGITALINOUT_PROTOCOL = 0 + FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/meowbit diff --git a/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk b/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk index d1df685c6764e..31c2b7e2874f9 100644 --- a/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk +++ b/ports/stm/boards/sparkfun_stm32f405_micromod/mpconfigboard.mk @@ -1,5 +1,5 @@ USB_VID = 0X1B4F -USB_PID = 0x0027 +USB_PID = 0x0029 USB_PRODUCT = "SparkFun STM32 MicroMod Processor" USB_MANUFACTURER = "SparkFun Electronics" diff --git a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk index 64be6f4f14242..c46a270df652a 100644 --- a/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk +++ b/ports/stm/boards/stm32f411ce_blackpill_with_flash/mpconfigboard.mk @@ -9,6 +9,7 @@ EXTERNAL_FLASH_DEVICES = GD25Q16C,W25Q16JVxQ,W25Q64FV,W25Q32JVxQ,W25Q64JVxQ LONGINT_IMPL = MPZ INTERNAL_FLASH_FILESYSTEM = 0 +OPTIMIZATION_FLAGS = -Os MCU_SERIES = F4 MCU_VARIANT = STM32F411xE diff --git a/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk b/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk index e17fa4d1b7457..98d13f592ffcb 100644 --- a/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk +++ b/ports/stm/boards/stm32f411ve_discovery/mpconfigboard.mk @@ -9,14 +9,18 @@ MCU_SERIES = F4 MCU_VARIANT = STM32F411xE MCU_PACKAGE = LQFP100_f4 +OPTIMIZATION_FLAGS = -Os + LD_COMMON = boards/common_default.ld LD_FILE = boards/STM32F411_fs.ld # Too big for the flash +CIRCUITPY_AESIO = 0 CIRCUITPY_AUDIOCORE = 0 CIRCUITPY_AUDIOPWMIO = 0 CIRCUITPY_BITMAPFILTER = 0 CIRCUITPY_BITMAPTOOLS = 0 CIRCUITPY_BLEIO_HCI = 0 +CIRCUITPY_CODEOP = 0 CIRCUITPY_MSGPACK = 0 CIRCUITPY_VECTORIO = 0 diff --git a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.h b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.h index e771532437f6b..b068b8e2d517c 100644 --- a/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.h +++ b/ports/stm/boards/stm32f412zg_discovery/mpconfigboard.h @@ -9,7 +9,7 @@ // Micropython setup #define MICROPY_HW_BOARD_NAME "STM32F412G_DISCO" -#define MICROPY_HW_MCU_NAME "STM32F412xGS" +#define MICROPY_HW_MCU_NAME "STM32F412xG" #define FLASH_SIZE (0x100000) #define FLASH_PAGE_SIZE (0x4000) diff --git a/ports/stm/boards/swan_r5/mpconfigboard.mk b/ports/stm/boards/swan_r5/mpconfigboard.mk index ea4125e02b8cf..353f96cca7829 100644 --- a/ports/stm/boards/swan_r5/mpconfigboard.mk +++ b/ports/stm/boards/swan_r5/mpconfigboard.mk @@ -24,7 +24,7 @@ CIRCUITPY_AUDIOBUSIO_I2SOUT = 0 CIRCUITPY_AUDIOBUSIO_PDMIN = 1 CIRCUITPY_AUDIOPWMIO = 1 CIRCUITPY_BITBANGIO = 1 -CIRCUITPY_BLEIO = 0 +CIRCUITPY_BLEIO_NATIVE = 0 CIRCUITPY_BLEIO_HCI = 0 CIRCUITPY_BUSDEVICE = 0 CIRCUITPY_BUSIO = 1 diff --git a/ports/stm/boards/swan_r5/tests/analog_output.py b/ports/stm/boards/swan_r5/tests/analog_output.py index 6af931e65d6fa..f2ef97dc2cf4f 100644 --- a/ports/stm/boards/swan_r5/tests/analog_output.py +++ b/ports/stm/boards/swan_r5/tests/analog_output.py @@ -31,7 +31,7 @@ def test_dac_digital(p_in, p_out): def test_dual(pair1, pair2): # verifies that the DACs can be set independently - print(f"Running pair test\n") + print("Running pair test\n") pin1_in = analogio.AnalogIn(pair1[0]) pin1_out = analogio.AnalogOut(pair1[1]) pin2_in = analogio.AnalogIn(pair2[0]) diff --git a/ports/stm/boards/swan_r5/tests/enable_3v3.py b/ports/stm/boards/swan_r5/tests/enable_3v3.py index c32bbc58b80ec..fecd05a3c5de9 100644 --- a/ports/stm/boards/swan_r5/tests/enable_3v3.py +++ b/ports/stm/boards/swan_r5/tests/enable_3v3.py @@ -13,9 +13,9 @@ # Then the symbol "board.DISCHARGE_3V3" is defined assert board.DISCHARGE_3V3 is not None # And the symbol "board.DISABLE_DISCHARGING" is defined to be "True" -assert board.DISABLE_DISCHARGING is not None and board.DISABLE_DISCHARGING == True +assert board.DISABLE_DISCHARGING is not None and board.DISABLE_DISCHARGING # And the symbol "board.ENABLE_DISCHARGING" is defined to be "False" -assert board.ENABLE_DISCHARGING is not None and board.ENABLE_DISCHARGING == False +assert board.ENABLE_DISCHARGING is not None and not board.ENABLE_DISCHARGING # Scenario: Toggle ENBLE_3V3 # Given I have a LED connected between the 3V3 and GND pins diff --git a/ports/stm/boards/thunderpack_v11/mpconfigboard.mk b/ports/stm/boards/thunderpack_v11/mpconfigboard.mk index 4fede00dc07ea..0107bbb1c1777 100644 --- a/ports/stm/boards/thunderpack_v11/mpconfigboard.mk +++ b/ports/stm/boards/thunderpack_v11/mpconfigboard.mk @@ -13,6 +13,8 @@ MCU_SERIES = F4 MCU_VARIANT = STM32F411xE MCU_PACKAGE = UFQFPN48 +OPTIMIZATION_FLAGS = -Os + LD_COMMON = boards/common_nvm.ld LD_FILE = boards/STM32F411_nvm.ld diff --git a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk index 276cf6d011050..353d0733e6483 100644 --- a/ports/stm/boards/thunderpack_v12/mpconfigboard.mk +++ b/ports/stm/boards/thunderpack_v12/mpconfigboard.mk @@ -25,11 +25,7 @@ MCU_SERIES = F4 MCU_VARIANT = STM32F411xE MCU_PACKAGE = UFQFPN48 +OPTIMIZATION_FLAGS = -Os + LD_COMMON = boards/common_nvm.ld LD_FILE = boards/STM32F411_nvm_nofs.ld - -# Disable TERMINALIO on translations with missing characters. -ifneq (,$(filter $(TRANSLATION),ja ko ru)) -CIRCUITPY_TERMINALIO = 0 -RELEASE_NEEDS_CLEAN_BUILD = $(CIRCUITPY_DISPLAYIO) -endif diff --git a/ports/stm/common-hal/alarm/__init__.c b/ports/stm/common-hal/alarm/__init__.c index 3d6c4466882b4..1be8f8dc10d09 100644 --- a/ports/stm/common-hal/alarm/__init__.c +++ b/ports/stm/common-hal/alarm/__init__.c @@ -135,7 +135,7 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala _setup_sleep_alarms(true, n_alarms, alarms); } -void NORETURN common_hal_alarm_enter_deep_sleep(void) { +void MP_NORETURN common_hal_alarm_enter_deep_sleep(void) { alarm_set_wakeup_reason(STM_WAKEUP_UNDEF); alarm_pin_pinalarm_prepare_for_deep_sleep(); alarm_time_timealarm_prepare_for_deep_sleep(); diff --git a/ports/stm/common-hal/audiopwmio/PWMAudioOut.c b/ports/stm/common-hal/audiopwmio/PWMAudioOut.c index 9a82398aeb6f9..a5cc11965fabb 100644 --- a/ports/stm/common-hal/audiopwmio/PWMAudioOut.c +++ b/ports/stm/common-hal/audiopwmio/PWMAudioOut.c @@ -206,6 +206,11 @@ void common_hal_audiopwmio_pwmaudioout_construct(audiopwmio_pwmaudioout_obj_t *s self->buffer[0] = NULL; self->buffer[1] = NULL; + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->buffer_size[0] = 0; + self->buffer_size[1] = 0; + #endif + self->quiescent_value = quiescent_value; } @@ -214,9 +219,22 @@ bool common_hal_audiopwmio_pwmaudioout_deinited(audiopwmio_pwmaudioout_obj_t *se } static void free_buffers(audiopwmio_pwmaudioout_obj_t *self) { + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(self->buffer[0], self->buffer_size[0]); + self->buffer_size[0] = 0; + #else m_free(self->buffer[0]); + #endif + self->buffer[0] = NULL; + + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(self->buffer[1], self->buffer_size[1]); + self->buffer_size[1] = 0; + #else m_free(self->buffer[1]); + #endif + self->buffer[1] = NULL; } @@ -240,8 +258,8 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, self->sample = sample; self->loop = loop; - uint32_t sample_rate = audiosample_sample_rate(sample); - self->bytes_per_sample = audiosample_bits_per_sample(sample) / 8; + uint32_t sample_rate = audiosample_get_sample_rate(sample); + self->bytes_per_sample = audiosample_get_bits_per_sample(sample) / 8; uint32_t max_buffer_length; uint8_t spacing; @@ -249,7 +267,7 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, bool samples_signed; audiosample_get_buffer_structure(sample, /* single channel */ false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); - self->sample_channel_count = audiosample_channel_count(sample); + self->sample_channel_count = audiosample_get_channel_count(sample); self->sample_offset = (samples_signed ? 0x8000 : 0) - self->quiescent_value; free_buffers(self); @@ -257,11 +275,21 @@ void common_hal_audiopwmio_pwmaudioout_play(audiopwmio_pwmaudioout_obj_t *self, if (max_buffer_length > UINT16_MAX) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer length %d too big. It must be less than %d"), max_buffer_length, UINT16_MAX); } + uint16_t buffer_length = (uint16_t)max_buffer_length / self->bytes_per_sample; - self->buffer[0] = m_malloc(buffer_length * sizeof(uint16_t)); + size_t buffer_size = buffer_length * sizeof(uint16_t); + + self->buffer[0] = m_malloc_without_collect(buffer_size); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->buffer_size[0] = buffer_size; + #endif self->buffer_ptr[0] = self->buffer_length[0] = 0; + if (self->pin[1]) { - self->buffer[1] = m_malloc(buffer_length * sizeof(uint16_t)); + self->buffer[1] = m_malloc_without_collect(buffer_size); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->buffer_size[1] = buffer_size; + #endif self->buffer_ptr[1] = self->buffer_length[1] = 0; } @@ -314,7 +342,6 @@ void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t *self) tim_handle.Instance->CR1 &= ~TIM_CR1_CEN; stm_peripherals_timer_free(tim_handle.Instance); - active_audio = NULL; self->stopping = false; self->paused = false; @@ -324,6 +351,8 @@ void common_hal_audiopwmio_pwmaudioout_stop(audiopwmio_pwmaudioout_obj_t *self) set_pin(1, GPIO_PIN_RESET); } + active_audio = NULL; + // Cannot free buffers here because we may be called from // the interrupt handler, and the heap is not reentrant. } diff --git a/ports/stm/common-hal/audiopwmio/PWMAudioOut.h b/ports/stm/common-hal/audiopwmio/PWMAudioOut.h index be31e87d177d0..b41ef44b17f09 100644 --- a/ports/stm/common-hal/audiopwmio/PWMAudioOut.h +++ b/ports/stm/common-hal/audiopwmio/PWMAudioOut.h @@ -14,6 +14,9 @@ typedef struct { uint16_t quiescent_value; uint16_t *buffer[2]; + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + uint16_t buffer_size[2]; // Keeps track of allocated size + #endif uint16_t buffer_length[2]; uint16_t buffer_ptr[2]; diff --git a/ports/stm/common-hal/busio/I2C.c b/ports/stm/common-hal/busio/I2C.c index d7919cbd7ada0..7f7eb990e4d07 100644 --- a/ports/stm/common-hal/busio/I2C.c +++ b/ports/stm/common-hal/busio/I2C.c @@ -41,28 +41,18 @@ #define MAX_I2C 4 static bool reserved_i2c[MAX_I2C]; -static bool never_reset_i2c[MAX_I2C]; #define ALL_CLOCKS 0xFF static void i2c_clock_enable(uint8_t mask); static void i2c_clock_disable(uint8_t mask); static void i2c_assign_irq(busio_i2c_obj_t *self, I2C_TypeDef *I2Cx); -void i2c_reset(void) { - uint16_t never_reset_mask = 0x00; - for (int i = 0; i < MAX_I2C; i++) { - if (!never_reset_i2c[i]) { - reserved_i2c[i] = false; - } else { - never_reset_mask |= 1 << i; - } - } - i2c_clock_disable(ALL_CLOCKS & ~(never_reset_mask)); -} - void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, uint32_t timeout) { + // Ensure the object starts in its deinit state. + common_hal_busio_i2c_mark_deinit(self); + // Match pins to I2C objects I2C_TypeDef *I2Cx; uint8_t sda_len = MP_ARRAY_SIZE(mcu_i2c_sda_list); @@ -163,15 +153,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, } void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { - for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_i2c_banks); i++) { - if (self->handle.Instance == mcu_i2c_banks[i]) { - never_reset_i2c[i] = true; - - never_reset_pin_number(self->scl->pin->port, self->scl->pin->number); - never_reset_pin_number(self->sda->pin->port, self->sda->pin->number); - break; - } - } + never_reset_pin_number(self->scl->pin->port, self->scl->pin->number); + never_reset_pin_number(self->sda->pin->port, self->sda->pin->number); } bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { @@ -185,12 +168,14 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { i2c_clock_disable(1 << (self->sda->periph_index - 1)); reserved_i2c[self->sda->periph_index - 1] = false; - never_reset_i2c[self->sda->periph_index - 1] = false; reset_pin_number(self->sda->pin->port, self->sda->pin->number); reset_pin_number(self->scl->pin->port, self->scl->pin->number); + common_hal_busio_i2c_mark_deinit(self); +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { self->sda = NULL; - self->scl = NULL; } bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { @@ -198,6 +183,9 @@ bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { } bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } bool grabbed_lock = false; // Critical section code that may be required at some point. @@ -224,7 +212,7 @@ void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { self->has_lock = false; } -static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +static mp_negative_errno_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { HAL_StatusTypeDef result; if (!transmit_stop_bit) { @@ -246,19 +234,19 @@ static uint8_t _common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, result = HAL_I2C_Master_Transmit(&(self->handle), (uint16_t)(addr << 1), (uint8_t *)data, (uint16_t)len, 500); } - return result == HAL_OK ? 0 : MP_EIO; + return result == HAL_OK ? 0 : -MP_EIO; } -uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len) { return _common_hal_busio_i2c_write(self, addr, data, len, true); } -uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { if (!self->frame_in_prog) { return HAL_I2C_Master_Receive(&(self->handle), (uint16_t)(addr << 1), data, (uint16_t)len, 500) - == HAL_OK ? 0 : MP_EIO; + == HAL_OK ? 0 : -MP_EIO; } else { HAL_StatusTypeDef result = HAL_I2C_Master_Seq_Receive_IT(&(self->handle), (uint16_t)(addr << 1), (uint8_t *)data, @@ -271,9 +259,9 @@ uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, } } -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { - uint8_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); + mp_negative_errno_t result = _common_hal_busio_i2c_write(self, addr, out_data, out_len, false); if (result != 0) { return result; } diff --git a/ports/stm/common-hal/busio/I2C.h b/ports/stm/common-hal/busio/I2C.h index ff78ddb35af38..c79a077dcabaf 100644 --- a/ports/stm/common-hal/busio/I2C.h +++ b/ports/stm/common-hal/busio/I2C.h @@ -22,5 +22,3 @@ typedef struct { const mcu_periph_obj_t *scl; const mcu_periph_obj_t *sda; } busio_i2c_obj_t; - -void i2c_reset(void); diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c index e47708d94594e..24b65fbf54c0c 100644 --- a/ports/stm/common-hal/busio/SPI.c +++ b/ports/stm/common-hal/busio/SPI.c @@ -19,7 +19,6 @@ #define MAX_SPI 6 static bool reserved_spi[MAX_SPI]; -static bool never_reset_spi[MAX_SPI]; #define ALL_CLOCKS 0xFF static void spi_clock_enable(uint8_t mask); @@ -76,18 +75,6 @@ static uint32_t stm32_baud_to_spi_div(uint32_t baudrate, uint16_t *prescaler, ui return SPI_BAUDRATEPRESCALER_256; } -void spi_reset(void) { - uint16_t never_reset_mask = 0x00; - for (int i = 0; i < MAX_SPI; i++) { - if (!never_reset_spi[i]) { - reserved_spi[i] = false; - } else { - never_reset_mask |= 1 << i; - } - } - spi_clock_disable(ALL_CLOCKS & ~(never_reset_mask)); -} - static const mcu_periph_obj_t *find_pin_function(const mcu_periph_obj_t *table, size_t sz, const mcu_pin_obj_t *pin, int periph_index) { for (size_t i = 0; i < sz; i++, table++) { if (periph_index == table->periph_index && pin == table->pin) { @@ -149,6 +136,10 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, bool half_duplex) { + // Ensure the object starts in its deinit state before check_pins sets + // self->sck, self->mosi, and self->miso. + common_hal_busio_spi_mark_deinit(self); + int periph_index = check_pins(self, sck, mosi, miso); SPI_TypeDef *SPIx = mcu_spi_banks[periph_index - 1]; @@ -224,7 +215,6 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { - never_reset_spi[self->sck->periph_index - 1] = true; never_reset_pin_number(self->sck->pin->port, self->sck->pin->number); if (self->mosi != NULL) { never_reset_pin_number(self->mosi->pin->port, self->mosi->pin->number); @@ -238,13 +228,16 @@ bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->sck == NULL; } +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + self->sck = NULL; +} + void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { if (common_hal_busio_spi_deinited(self)) { return; } spi_clock_disable(1 << (self->sck->periph_index - 1)); reserved_spi[self->sck->periph_index - 1] = false; - never_reset_spi[self->sck->periph_index - 1] = false; reset_pin_number(self->sck->pin->port, self->sck->pin->number); if (self->mosi != NULL) { @@ -297,6 +290,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, } bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } bool grabbed_lock = false; // Critical section code that may be required at some point. diff --git a/ports/stm/common-hal/microcontroller/Pin.c b/ports/stm/common-hal/microcontroller/Pin.c index e0ff3f138dfc2..bdf5e5fb16cd6 100644 --- a/ports/stm/common-hal/microcontroller/Pin.c +++ b/ports/stm/common-hal/microcontroller/Pin.c @@ -11,6 +11,8 @@ #if defined(TFBGA216) GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK}; +#elif defined(UFBGA176) +GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH, GPIOI}; #elif defined(LQFP144) || defined(WLCSP144) GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG}; #elif defined(LQFP100_f4) || (LQFP100_x7) @@ -19,6 +21,8 @@ GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD, GPIOE}; GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC, GPIOD}; #elif defined(UFQFPN48) GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC}; +#elif defined(LQFP48) +GPIO_TypeDef *ports[] = {GPIOA, GPIOB, GPIOC}; #else #error Unknown package type #endif diff --git a/ports/stm/common-hal/microcontroller/__init__.c b/ports/stm/common-hal/microcontroller/__init__.c index 5a0f0ed929451..a9c9b76849de3 100644 --- a/ports/stm/common-hal/microcontroller/__init__.c +++ b/ports/stm/common-hal/microcontroller/__init__.c @@ -31,12 +31,14 @@ void common_hal_mcu_delay_us(uint32_t delay) { SysTick->CTRL = 0UL; } -volatile uint32_t nesting_count = 0; +static volatile uint32_t nesting_count = 0; +// 32-bit increments void common_hal_mcu_disable_interrupts(void) { - __disable_irq(); - __DMB(); - nesting_count++; + if (++nesting_count == 1) { + __disable_irq(); + __DMB(); + } } void common_hal_mcu_enable_interrupts(void) { @@ -44,12 +46,10 @@ void common_hal_mcu_enable_interrupts(void) { // This is very very bad because it means there was mismatched disable/enables. reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR); } - nesting_count--; - if (nesting_count > 0) { - return; + if (--nesting_count == 0) { + __DMB(); + __enable_irq(); } - __DMB(); - __enable_irq(); } static bool next_reset_to_bootloader = false; diff --git a/ports/stm/common-hal/os/__init__.c b/ports/stm/common-hal/os/__init__.c index b3d9e67d98893..d654f844b1767 100644 --- a/ports/stm/common-hal/os/__init__.c +++ b/ports/stm/common-hal/os/__init__.c @@ -15,32 +15,6 @@ #include STM32_HAL_H #include "peripherals/periph.h" -static const qstr os_uname_info_fields[] = { - MP_QSTR_sysname, MP_QSTR_nodename, - MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine -}; -static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, STM32_SERIES_LOWER); -static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, STM32_SERIES_LOWER); - -static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); -static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); -static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); - -static MP_DEFINE_ATTRTUPLE( - os_uname_info_obj, - os_uname_info_fields, - 5, - (mp_obj_t)&os_uname_info_sysname_obj, - (mp_obj_t)&os_uname_info_nodename_obj, - (mp_obj_t)&os_uname_info_release_obj, - (mp_obj_t)&os_uname_info_version_obj, - (mp_obj_t)&os_uname_info_machine_obj - ); - -mp_obj_t common_hal_os_uname(void) { - return (mp_obj_t)&os_uname_info_obj; -} - #define RNG_TIMEOUT 5 bool common_hal_os_urandom(uint8_t *buffer, uint32_t length) { diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c index 593e01f9bb911..86d304af5f1d4 100644 --- a/ports/stm/common-hal/pulseio/PulseIn.c +++ b/ports/stm/common-hal/pulseio/PulseIn.c @@ -84,7 +84,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t *self, const mcu } // Allocate pulse buffer - self->buffer = (uint16_t *)m_malloc(maxlen * sizeof(uint16_t)); + self->buffer = (uint16_t *)m_malloc_without_collect(maxlen * sizeof(uint16_t)); if (self->buffer == NULL) { // TODO: free the EXTI here? m_malloc_fail(maxlen * sizeof(uint16_t)); diff --git a/ports/stm/common-hal/sdioio/SDCard.c b/ports/stm/common-hal/sdioio/SDCard.c index ab0f8bb7dfce6..2d24f24d82504 100644 --- a/ports/stm/common-hal/sdioio/SDCard.c +++ b/ports/stm/common-hal/sdioio/SDCard.c @@ -6,6 +6,8 @@ #include #include "shared-bindings/sdioio/SDCard.h" + +#include "extmod/vfs.h" #include "py/mperrno.h" #include "py/runtime.h" @@ -104,7 +106,11 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, uint8_t num_data, const mcu_pin_obj_t **data, uint32_t frequency) { int periph_index = check_pins(self, clock, command, num_data, data); + #ifdef STM32H750xx + SDMMC_TypeDef *SDMMCx = mcu_sdio_banks[periph_index - 1]; + #else SDIO_TypeDef *SDIOx = mcu_sdio_banks[periph_index - 1]; + #endif GPIO_InitTypeDef GPIO_InitStruct = {0}; @@ -128,6 +134,25 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, GPIO_InitStruct.Pin = pin_mask(clock->number); HAL_GPIO_Init(pin_port(clock->port), &GPIO_InitStruct); + #ifdef STM32H750xx + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SDMMC; + PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("MMC/SDIO Clock Error %x")); + } + __HAL_RCC_SDMMC1_CLK_ENABLE(); + + self->handle.Init.ClockDiv = SDMMC_NSPEED_CLK_DIV; + self->handle.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; + self->handle.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; + self->handle.Init.BusWide = SDMMC_BUS_WIDE_1B; + // For the SDMMC controller Hardware Flow Control needs to be enabled + // at the default speed of 25MHz, in order to avoid FIFO underrun (TX mode) + // and overrun (RX mode) errors. + self->handle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_ENABLE; + self->handle.Instance = SDMMCx; + #else __HAL_RCC_SDIO_CLK_ENABLE(); self->handle.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV; @@ -137,10 +162,11 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, self->handle.Init.BusWide = SDIO_BUS_WIDE_1B; self->handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; self->handle.Instance = SDIOx; + #endif HAL_StatusTypeDef r = HAL_SD_Init(&self->handle); if (r != HAL_OK) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("SDIO Init Error %d"), (int)r); + mp_raise_ValueError_varg(MP_ERROR_TEXT("SDIO Init Error %x"), (unsigned int)r); } HAL_SD_CardInfoTypeDef info; @@ -150,9 +176,14 @@ void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self, } self->num_data = 1; + #ifdef STM32H750xx + uint32_t bus_wide_opt = SDMMC_BUS_WIDE_4B; + #else + uint32_t bus_wide_opt = SDIO_BUS_WIDE_4B; + #endif if (num_data == 4) { - if ((r = HAL_SD_ConfigWideBusOperation(&self->handle, SDIO_BUS_WIDE_4B)) == HAL_SD_ERROR_NONE) { - self->handle.Init.BusWide = SDIO_BUS_WIDE_4B; + if ((r = HAL_SD_ConfigWideBusOperation(&self->handle, bus_wide_opt)) == HAL_SD_ERROR_NONE) { + self->handle.Init.BusWide = bus_wide_opt; self->num_data = 4; } else { } @@ -186,7 +217,7 @@ uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) { static void check_whole_block(mp_buffer_info_t *bufinfo) { if (bufinfo->len % 512) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } } @@ -210,33 +241,90 @@ static void check_for_deinit(sdioio_sdcard_obj_t *self) { } } -int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { - check_for_deinit(self); - check_whole_block(bufinfo); +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); wait_write_complete(self); self->state_programming = true; common_hal_mcu_disable_interrupts(); - HAL_StatusTypeDef r = HAL_SD_WriteBlocks(&self->handle, bufinfo->buf, start_block, bufinfo->len / 512, 1000); + #ifdef STM32H750xx + // longer timeouts needed because code executing from QSPI is slower + uint32_t time_out = SDMMC_DATATIMEOUT; + #else + uint32_t time_out = 1000; + #endif + HAL_StatusTypeDef r = HAL_SD_WriteBlocks(&self->handle, buf, start_block, num_blocks, time_out); common_hal_mcu_enable_interrupts(); if (r != HAL_OK) { - return -EIO; + return -MP_EIO; } return 0; } -int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { check_for_deinit(self); check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, + uint32_t start_block, uint32_t num_blocks) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); wait_write_complete(self); common_hal_mcu_disable_interrupts(); - HAL_StatusTypeDef r = HAL_SD_ReadBlocks(&self->handle, bufinfo->buf, start_block, bufinfo->len / 512, 1000); + #ifdef STM32H750xx + // longer timeouts needed because code executing from QSPI is slower + uint32_t time_out = SDMMC_DATATIMEOUT; + #else + uint32_t time_out = 1000; + #endif + HAL_StatusTypeDef r = HAL_SD_ReadBlocks(&self->handle, buf, start_block, num_blocks, time_out); common_hal_mcu_enable_interrupts(); if (r != HAL_OK) { - return -EIO; + return -MP_EIO; } return 0; } +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) { + check_for_deinit(self); + check_whole_block(bufinfo); + + uint32_t num_blocks = bufinfo->len / 512; + return sdioio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), bufinfo->buf, + start_block, num_blocks); +} + +// Native function for VFS blockdev layer +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, + mp_int_t *out_value) { + sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); + *out_value = 0; + + switch (cmd) { + case MP_BLOCKDEV_IOCTL_DEINIT: + case MP_BLOCKDEV_IOCTL_SYNC: + // SDIO operations are synchronous, no action needed + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = common_hal_sdioio_sdcard_get_count(self); + return true; + + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = 512; // SD cards use 512-byte sectors + return true; + + default: + return false; // Unsupported command + } +} + bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) { check_for_deinit(self); return true; @@ -297,7 +385,7 @@ void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) { } } -void sdioio_reset() { +void sdioio_reset(void) { for (size_t i = 0; i < MP_ARRAY_SIZE(reserved_sdio); i++) { if (!never_reset_sdio[i]) { reserved_sdio[i] = false; diff --git a/ports/stm/mpconfigport.h b/ports/stm/mpconfigport.h index ed36b49ffb92f..afa9aa3685c9a 100644 --- a/ports/stm/mpconfigport.h +++ b/ports/stm/mpconfigport.h @@ -9,9 +9,6 @@ #include -#define MICROPY_PY_FUNCTION_ATTRS (1) -#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1) - extern uint8_t _ld_default_stack_size; // 24kiB stack diff --git a/ports/stm/mpconfigport.mk b/ports/stm/mpconfigport.mk index 3266212962738..96724a5296090 100644 --- a/ports/stm/mpconfigport.mk +++ b/ports/stm/mpconfigport.mk @@ -10,6 +10,10 @@ ifeq ($(MCU_VARIANT),$(filter $(MCU_VARIANT),STM32F405xx STM32F407xx)) USB_NUM_ENDPOINT_PAIRS = 4 endif +ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) + OPTIMIZATION_FLAGS ?= -Os +endif + ifeq ($(MCU_VARIANT),STM32F407xx) UF2_FAMILY_ID ?= 0x6d0922fa endif @@ -28,6 +32,7 @@ ifeq ($(MCU_SERIES),F4) CIRCUITPY_NVM ?= 0 CIRCUITPY_ROTARYIO ?= 0 CIRCUITPY_RTC ?= 1 + CIRCUITPY_PORT_SERIAL ?= 1 USB_NUM_ENDPOINT_PAIRS = 4 UF2_FAMILY_ID ?= 0x57755a57 endif @@ -80,11 +85,18 @@ ifeq ($(MCU_SERIES),L4) CIRCUITPY_NVM ?= 0 CIRCUITPY_ROTARYIO ?= 0 CIRCUITPY_RTC ?= 1 + UF2_FAMILY_ID ?= 0x00ff6919 +endif + +ifeq ($(MCU_VARIANT),STM32L4R5xx) # todo - this varies between devices in the series # This slide deck https://www.st.com/content/ccc/resource/training/technical/product_training/98/89/c8/6c/3e/e9/49/79/STM32L4_Peripheral_USB.pdf/files/STM32L4_Peripheral_USB.pdf/jcr:content/translations/en.STM32L4_Peripheral_USB.pdf # cites 16 endpoints, 8 endpoint pairs, while section 3.39 of the L4R5 datasheet states 6 endpoint pairs. USB_NUM_ENDPOINT_PAIRS = 6 - UF2_FAMILY_ID ?= 0x00ff6919 +endif + +ifeq ($(MCU_VARIANT),STM32L433xx) + USB_NUM_ENDPOINT_PAIRS = 4 endif CIRCUITPY_PARALLELDISPLAYBUS := 0 diff --git a/ports/stm/mpconfigport_nanbox.h b/ports/stm/mpconfigport_nanbox.h deleted file mode 100644 index 164850112e01f..0000000000000 --- a/ports/stm/mpconfigport_nanbox.h +++ /dev/null @@ -1,25 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George -// -// SPDX-License-Identifier: MIT - -#pragma once - -// select nan-boxing object model -#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D) - -// native emitters don't work with nan-boxing -#define MICROPY_EMIT_X86 (0) -#define MICROPY_EMIT_X64 (0) -#define MICROPY_EMIT_THUMB (0) -#define MICROPY_EMIT_ARM (0) - -#include - -typedef int64_t mp_int_t; -typedef uint64_t mp_uint_t; -#define UINT_FMT "%llu" -#define INT_FMT "%lld" - -#include diff --git a/ports/stm/packages/LQFP100_f4.c b/ports/stm/packages/LQFP100_f4.c index f1c3cc36761bf..9a15d92a0a7e8 100644 --- a/ports/stm/packages/LQFP100_f4.c +++ b/ports/stm/packages/LQFP100_f4.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-25 { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) }, { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) }, diff --git a/ports/stm/packages/LQFP100_x7.c b/ports/stm/packages/LQFP100_x7.c index 77a887b0d8db1..9a2a1203da5fb 100644 --- a/ports/stm/packages/LQFP100_x7.c +++ b/ports/stm/packages/LQFP100_x7.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-25 { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) }, { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) }, diff --git a/ports/stm/packages/LQFP144.c b/ports/stm/packages/LQFP144.c index a08d160863684..341715b9682f4 100644 --- a/ports/stm/packages/LQFP144.c +++ b/ports/stm/packages/LQFP144.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-36 { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) }, { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) }, diff --git a/ports/stm/packages/LQFP48.c b/ports/stm/packages/LQFP48.c new file mode 100644 index 0000000000000..46b737adeb8e3 --- /dev/null +++ b/ports/stm/packages/LQFP48.c @@ -0,0 +1,63 @@ +#include "shared-bindings/microcontroller/__init__.h" +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { +// Pins 1-12 + /* VBAT -------------------------------------------*/ + { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, + // PC14 OSC32_IN ----------------------------------*/ + // PC15 OSC32_OUT ---------------------------------*/ + // { MP_ROM_QSTR(MP_QSTR_PH00), MP_ROM_PTR(&pin_PH00) }, PH00 OSC_IN + // { MP_ROM_QSTR(MP_QSTR_PH01), MP_ROM_PTR(&pin_PH01) }, PH01 OSC_OUT + // NRST -------------------------------------------*/ + // VSSA -------------------------------------------*/ + // VDDA -------------------------------------------*/ + { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) }, + +// Pins 13-24 + { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) }, + { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, + // VSS --------------------------------------------*/ + // VDD --------------------------------------------*/ + +// Pins 25-36 + { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, + { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, + { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, + { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, + { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) }, + { MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) }, + { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) }, + { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) }, + { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) }, + { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) }, + // VSS --------------------------------------------*/ + // VDD --------------------------------------------*/ + +// Pins 37-48 + { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, + { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, + { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, + { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, + // BOOT0 ------------------------------------------*/ + { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, + // VSS --------------------------------------------*/ + // VDD --------------------------------------------*/ + +}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_globals_table); diff --git a/ports/stm/packages/LQFP64.c b/ports/stm/packages/LQFP64.c index 71e8be978e6c3..4fec4ab157f9e 100644 --- a/ports/stm/packages/LQFP64.c +++ b/ports/stm/packages/LQFP64.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-16 /* VBAT -------------------------------------------*/ { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, diff --git a/ports/stm/packages/UFBGA176.c b/ports/stm/packages/UFBGA176.c new file mode 100644 index 0000000000000..2f9c3002f5944 --- /dev/null +++ b/ports/stm/packages/UFBGA176.c @@ -0,0 +1,183 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/microcontroller/__init__.h" +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { +// Row A + { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) }, + { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) }, + { MP_ROM_QSTR(MP_QSTR_PE01), MP_ROM_PTR(&pin_PE01) }, + { MP_ROM_QSTR(MP_QSTR_PE00), MP_ROM_PTR(&pin_PE00) }, + { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, + { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, + { MP_ROM_QSTR(MP_QSTR_PG14), MP_ROM_PTR(&pin_PG14) }, + { MP_ROM_QSTR(MP_QSTR_PG13), MP_ROM_PTR(&pin_PG13) }, + { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, + { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) }, + { MP_ROM_QSTR(MP_QSTR_PD07), MP_ROM_PTR(&pin_PD07) }, + { MP_ROM_QSTR(MP_QSTR_PC12), MP_ROM_PTR(&pin_PC12) }, + { MP_ROM_QSTR(MP_QSTR_PA15), MP_ROM_PTR(&pin_PA15) }, + { MP_ROM_QSTR(MP_QSTR_PA14), MP_ROM_PTR(&pin_PA14) }, + { MP_ROM_QSTR(MP_QSTR_PA13), MP_ROM_PTR(&pin_PA13) }, + +// Row B + { MP_ROM_QSTR(MP_QSTR_PE04), MP_ROM_PTR(&pin_PE04) }, + { MP_ROM_QSTR(MP_QSTR_PE05), MP_ROM_PTR(&pin_PE05) }, + { MP_ROM_QSTR(MP_QSTR_PE06), MP_ROM_PTR(&pin_PE06) }, + { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, + { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, + { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, + { MP_ROM_QSTR(MP_QSTR_PG15), MP_ROM_PTR(&pin_PG15) }, + { MP_ROM_QSTR(MP_QSTR_PG12), MP_ROM_PTR(&pin_PG12) }, + { MP_ROM_QSTR(MP_QSTR_PG11), MP_ROM_PTR(&pin_PG11) }, + { MP_ROM_QSTR(MP_QSTR_PG10), MP_ROM_PTR(&pin_PG10) }, + { MP_ROM_QSTR(MP_QSTR_PD06), MP_ROM_PTR(&pin_PD06) }, + { MP_ROM_QSTR(MP_QSTR_PD00), MP_ROM_PTR(&pin_PD00) }, + { MP_ROM_QSTR(MP_QSTR_PC11), MP_ROM_PTR(&pin_PC11) }, + { MP_ROM_QSTR(MP_QSTR_PC10), MP_ROM_PTR(&pin_PC10) }, + { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) }, + +// Row C + { MP_ROM_QSTR(MP_QSTR_PI07), MP_ROM_PTR(&pin_PI07) }, + { MP_ROM_QSTR(MP_QSTR_PI06), MP_ROM_PTR(&pin_PI06) }, + { MP_ROM_QSTR(MP_QSTR_PI05), MP_ROM_PTR(&pin_PI05) }, + { MP_ROM_QSTR(MP_QSTR_PG09), MP_ROM_PTR(&pin_PG09) }, + { MP_ROM_QSTR(MP_QSTR_PD05), MP_ROM_PTR(&pin_PD05) }, + { MP_ROM_QSTR(MP_QSTR_PD01), MP_ROM_PTR(&pin_PD01) }, + { MP_ROM_QSTR(MP_QSTR_PI03), MP_ROM_PTR(&pin_PI03) }, + { MP_ROM_QSTR(MP_QSTR_PI02), MP_ROM_PTR(&pin_PI02) }, + { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) }, + +// Row D + { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, + { MP_ROM_QSTR(MP_QSTR_PI08), MP_ROM_PTR(&pin_PI08) }, + { MP_ROM_QSTR(MP_QSTR_PI09), MP_ROM_PTR(&pin_PI09) }, + { MP_ROM_QSTR(MP_QSTR_PI04), MP_ROM_PTR(&pin_PI04) }, + { MP_ROM_QSTR(MP_QSTR_PD04), MP_ROM_PTR(&pin_PD04) }, + { MP_ROM_QSTR(MP_QSTR_PD03), MP_ROM_PTR(&pin_PD03) }, + { MP_ROM_QSTR(MP_QSTR_PD02), MP_ROM_PTR(&pin_PD02) }, + { MP_ROM_QSTR(MP_QSTR_PH15), MP_ROM_PTR(&pin_PH15) }, + { MP_ROM_QSTR(MP_QSTR_PI01), MP_ROM_PTR(&pin_PI01) }, + { MP_ROM_QSTR(MP_QSTR_PA10), MP_ROM_PTR(&pin_PA10) }, + +// Row E +// { MP_ROM_QSTR(MP_QSTR_PC14), MP_ROM_PTR(&pin_PC14) }, + { MP_ROM_QSTR(MP_QSTR_PF00), MP_ROM_PTR(&pin_PF00) }, + { MP_ROM_QSTR(MP_QSTR_PI10), MP_ROM_PTR(&pin_PI10) }, + { MP_ROM_QSTR(MP_QSTR_PI11), MP_ROM_PTR(&pin_PI11) }, + { MP_ROM_QSTR(MP_QSTR_PH13), MP_ROM_PTR(&pin_PH13) }, + { MP_ROM_QSTR(MP_QSTR_PH14), MP_ROM_PTR(&pin_PH14) }, + { MP_ROM_QSTR(MP_QSTR_PI00), MP_ROM_PTR(&pin_PI00) }, + { MP_ROM_QSTR(MP_QSTR_PA09), MP_ROM_PTR(&pin_PA09) }, + +// Row F +// { MP_ROM_QSTR(MP_QSTR_PC15), MP_ROM_PTR(&pin_PC15) }, + { MP_ROM_QSTR(MP_QSTR_PH02), MP_ROM_PTR(&pin_PH02) }, + { MP_ROM_QSTR(MP_QSTR_PC09), MP_ROM_PTR(&pin_PC09) }, + { MP_ROM_QSTR(MP_QSTR_PA08), MP_ROM_PTR(&pin_PA08) }, + +// Row G +// { MP_ROM_QSTR(MP_QSTR_PH00), MP_ROM_PTR(&pin_PH00) }, + { MP_ROM_QSTR(MP_QSTR_PH03), MP_ROM_PTR(&pin_PH03) }, + { MP_ROM_QSTR(MP_QSTR_PC08), MP_ROM_PTR(&pin_PC08) }, + { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) }, + +// Row H +// { MP_ROM_QSTR(MP_QSTR_PH01), MP_ROM_PTR(&pin_PH01) }, + { MP_ROM_QSTR(MP_QSTR_PF02), MP_ROM_PTR(&pin_PF02) }, + { MP_ROM_QSTR(MP_QSTR_PF01), MP_ROM_PTR(&pin_PF01) }, + { MP_ROM_QSTR(MP_QSTR_PH04), MP_ROM_PTR(&pin_PH04) }, + { MP_ROM_QSTR(MP_QSTR_PG08), MP_ROM_PTR(&pin_PG08) }, + { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) }, + +// Row J + { MP_ROM_QSTR(MP_QSTR_PF03), MP_ROM_PTR(&pin_PF03) }, + { MP_ROM_QSTR(MP_QSTR_PF04), MP_ROM_PTR(&pin_PF04) }, + { MP_ROM_QSTR(MP_QSTR_PH05), MP_ROM_PTR(&pin_PH05) }, + { MP_ROM_QSTR(MP_QSTR_PG07), MP_ROM_PTR(&pin_PG07) }, + { MP_ROM_QSTR(MP_QSTR_PG06), MP_ROM_PTR(&pin_PG06) }, + +// Row K + { MP_ROM_QSTR(MP_QSTR_PF07), MP_ROM_PTR(&pin_PF07) }, + { MP_ROM_QSTR(MP_QSTR_PF06), MP_ROM_PTR(&pin_PF06) }, + { MP_ROM_QSTR(MP_QSTR_PF05), MP_ROM_PTR(&pin_PF05) }, + { MP_ROM_QSTR(MP_QSTR_PH12), MP_ROM_PTR(&pin_PH12) }, + { MP_ROM_QSTR(MP_QSTR_PG05), MP_ROM_PTR(&pin_PG05) }, + { MP_ROM_QSTR(MP_QSTR_PG04), MP_ROM_PTR(&pin_PG04) }, + { MP_ROM_QSTR(MP_QSTR_PG03), MP_ROM_PTR(&pin_PG03) }, + +// Row L + { MP_ROM_QSTR(MP_QSTR_PF10), MP_ROM_PTR(&pin_PF10) }, + { MP_ROM_QSTR(MP_QSTR_PF09), MP_ROM_PTR(&pin_PF09) }, + { MP_ROM_QSTR(MP_QSTR_PF08), MP_ROM_PTR(&pin_PF08) }, + { MP_ROM_QSTR(MP_QSTR_PH11), MP_ROM_PTR(&pin_PH11) }, + { MP_ROM_QSTR(MP_QSTR_PH10), MP_ROM_PTR(&pin_PH10) }, + { MP_ROM_QSTR(MP_QSTR_PD15), MP_ROM_PTR(&pin_PD15) }, + { MP_ROM_QSTR(MP_QSTR_PG02), MP_ROM_PTR(&pin_PG02) }, + +// Row M + { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) }, + { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) }, +// { MP_ROM_QSTR(MP_QSTR_PC02C), MP_ROM_PTR(&pin_PC02C) }, +// { MP_ROM_QSTR(MP_QSTR_PC03C), MP_ROM_PTR(&pin_PC03C) }, + { MP_ROM_QSTR(MP_QSTR_PB02), MP_ROM_PTR(&pin_PB02) }, + { MP_ROM_QSTR(MP_QSTR_PG01), MP_ROM_PTR(&pin_PG01) }, + { MP_ROM_QSTR(MP_QSTR_PH06), MP_ROM_PTR(&pin_PH06) }, + { MP_ROM_QSTR(MP_QSTR_PH08), MP_ROM_PTR(&pin_PH08) }, + { MP_ROM_QSTR(MP_QSTR_PH09), MP_ROM_PTR(&pin_PH09) }, + { MP_ROM_QSTR(MP_QSTR_PD14), MP_ROM_PTR(&pin_PD14) }, + { MP_ROM_QSTR(MP_QSTR_PD13), MP_ROM_PTR(&pin_PD13) }, + +// Row N + { MP_ROM_QSTR(MP_QSTR_PA01), MP_ROM_PTR(&pin_PA01) }, + { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) }, + { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) }, + { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) }, + { MP_ROM_QSTR(MP_QSTR_PF13), MP_ROM_PTR(&pin_PF13) }, + { MP_ROM_QSTR(MP_QSTR_PG00), MP_ROM_PTR(&pin_PG00) }, + { MP_ROM_QSTR(MP_QSTR_PE13), MP_ROM_PTR(&pin_PE13) }, + { MP_ROM_QSTR(MP_QSTR_PH07), MP_ROM_PTR(&pin_PH07) }, + { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) }, + { MP_ROM_QSTR(MP_QSTR_PD11), MP_ROM_PTR(&pin_PD11) }, + { MP_ROM_QSTR(MP_QSTR_PD10), MP_ROM_PTR(&pin_PD10) }, + +// Row P + { MP_ROM_QSTR(MP_QSTR_PA02), MP_ROM_PTR(&pin_PA02) }, + { MP_ROM_QSTR(MP_QSTR_PA06), MP_ROM_PTR(&pin_PA06) }, + { MP_ROM_QSTR(MP_QSTR_PA05), MP_ROM_PTR(&pin_PA05) }, + { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) }, + { MP_ROM_QSTR(MP_QSTR_PF12), MP_ROM_PTR(&pin_PF12) }, + { MP_ROM_QSTR(MP_QSTR_PF15), MP_ROM_PTR(&pin_PF15) }, + { MP_ROM_QSTR(MP_QSTR_PE08), MP_ROM_PTR(&pin_PE08) }, + { MP_ROM_QSTR(MP_QSTR_PE09), MP_ROM_PTR(&pin_PE09) }, + { MP_ROM_QSTR(MP_QSTR_PE11), MP_ROM_PTR(&pin_PE11) }, + { MP_ROM_QSTR(MP_QSTR_PE14), MP_ROM_PTR(&pin_PE14) }, + { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, + { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, + { MP_ROM_QSTR(MP_QSTR_PD09), MP_ROM_PTR(&pin_PD09) }, + { MP_ROM_QSTR(MP_QSTR_PD08), MP_ROM_PTR(&pin_PD08) }, + +// Row R + { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) }, + { MP_ROM_QSTR(MP_QSTR_PA07), MP_ROM_PTR(&pin_PA07) }, + { MP_ROM_QSTR(MP_QSTR_PB01), MP_ROM_PTR(&pin_PB01) }, + { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) }, + { MP_ROM_QSTR(MP_QSTR_PF11), MP_ROM_PTR(&pin_PF11) }, + { MP_ROM_QSTR(MP_QSTR_PF14), MP_ROM_PTR(&pin_PF14) }, + { MP_ROM_QSTR(MP_QSTR_PE07), MP_ROM_PTR(&pin_PE07) }, + { MP_ROM_QSTR(MP_QSTR_PE10), MP_ROM_PTR(&pin_PE10) }, + { MP_ROM_QSTR(MP_QSTR_PE12), MP_ROM_PTR(&pin_PE12) }, + { MP_ROM_QSTR(MP_QSTR_PE15), MP_ROM_PTR(&pin_PE15) }, + { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, + { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, + { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, + { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, + +}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_globals_table); diff --git a/ports/stm/packages/UFQFPN48.c b/ports/stm/packages/UFQFPN48.c index b45fc9c985326..1092b8df15f52 100644 --- a/ports/stm/packages/UFQFPN48.c +++ b/ports/stm/packages/UFQFPN48.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-12 /* VBAT -------------------------------------------*/ { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, diff --git a/ports/stm/packages/WLCSP144.c b/ports/stm/packages/WLCSP144.c index a08d160863684..341715b9682f4 100644 --- a/ports/stm/packages/WLCSP144.c +++ b/ports/stm/packages/WLCSP144.c @@ -2,7 +2,7 @@ #include "common-hal/microcontroller/Pin.h" #include "py/obj.h" -STATIC const mp_rom_map_elem_t mcu_pin_globals_table[] = { +static const mp_rom_map_elem_t mcu_pin_globals_table[] = { // Pins 1-36 { MP_ROM_QSTR(MP_QSTR_PE02), MP_ROM_PTR(&pin_PE02) }, { MP_ROM_QSTR(MP_QSTR_PE03), MP_ROM_PTR(&pin_PE03) }, diff --git a/ports/stm/peripherals/periph.h b/ports/stm/peripherals/periph.h index 438db7938672e..24ed9966a0a8f 100644 --- a/ports/stm/peripherals/periph.h +++ b/ports/stm/peripherals/periph.h @@ -30,7 +30,7 @@ typedef struct { // Timer Peripheral typedef struct { - uint8_t tim_index : 4; + uint8_t tim_index : 5; uint8_t altfn_index : 4; uint8_t channel_index : 4; const mcu_pin_obj_t *pin; @@ -84,6 +84,13 @@ typedef struct { #include "stm32l4/stm32l4r5xx/periph.h" #endif +#ifdef STM32L433xx +#define HAS_DAC 1 +#define HAS_TRNG 1 +#define HAS_BASIC_TIM 1 +#include "stm32l4/stm32l433xx/periph.h" +#endif + #ifdef STM32F405xx #define HAS_DAC 1 #define HAS_TRNG 1 @@ -130,3 +137,14 @@ typedef struct { #define HAS_BASIC_TIM 0 #include "stm32h7/stm32h743xx/periph.h" #endif + +#ifdef STM32H750xx +#define HAS_DAC 1 +#define HAS_TRNG 1 +#define HAS_BASIC_TIM 1 +#include "stm32h7/stm32h750xx/periph.h" +#endif + +#if !defined(HAS_DAC) +#error Unknown MCU +#endif diff --git a/ports/stm/peripherals/pins.h b/ports/stm/peripherals/pins.h index 999f8172d9713..42ddefdc40624 100644 --- a/ports/stm/peripherals/pins.h +++ b/ports/stm/peripherals/pins.h @@ -70,6 +70,9 @@ extern const mp_obj_type_t mcu_pin_type; #ifdef STM32L4R5xx #include "stm32l4/stm32l4r5xx/pins.h" #endif +#ifdef STM32L433xx +#include "stm32l4/stm32l433xx/pins.h" +#endif #ifdef STM32F405xx #include "stm32f4/stm32f405xx/pins.h" #endif @@ -92,3 +95,7 @@ extern const mp_obj_type_t mcu_pin_type; #ifdef STM32H743xx #include "stm32h7/stm32h743xx/pins.h" #endif + +#ifdef STM32H750xx +#include "stm32h7/stm32h750xx/pins.h" +#endif diff --git a/ports/stm/peripherals/sdram.c b/ports/stm/peripherals/sdram.c new file mode 100644 index 0000000000000..6179197fa95c9 --- /dev/null +++ b/ports/stm/peripherals/sdram.c @@ -0,0 +1,293 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 snkYmkrct +// +// based on implementation from https://github.com/micropython/micropython/blob/master/ports/stm32/sdram.c +// +// SPDX-License-Identifier: MIT + +#include +#include +#include +#include +#include STM32_HAL_H +#include "common-hal/microcontroller/Pin.h" +#include "peripherals/periph.h" +#if defined(STM32H7) +#include "stm32h7xx_ll_fmc.h" +#include "stm32h7xx_hal_sdram.h" +#include "stm32h7xx_hal_gpio.h" +#include "stm32h7xx_hal_cortex.h" +#endif +#ifdef STM32H750xx +#include "stm32h7/stm32h750xx/periph.h" +#endif + + +#include "sdram.h" + + +#if MICROPY_DEBUG_VERBOSE // print debugging info +#define DEBUG_PRINT (1) +#define DEBUG_printf DEBUG_printf +#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__) +#else // don't print debugging info +#define DEBUG_printf(...) (void)0 +#define DEBUG_OP_printf(...) (void)0 +#endif + +#define SDRAM_TIMEOUT ((uint32_t)0xFFFF) +#define CIRCUITPY_HW_SDRAM_STARTUP_TEST (0) + +static uint8_t FMC_Initialized = 0; +static SDRAM_HandleTypeDef hsdram = {0}; +static uint32_t sdram_start_address = 0; + + +static void sdram_init_seq(const struct stm32_sdram_config *config); + +void sdram_init(const struct stm32_sdram_config *config) { + FMC_SDRAM_TimingTypeDef SDRAM_Timing = {0}; + + if (!FMC_Initialized) { + + RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; + + /** Initializes the peripherals clock + */ + PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_FMC; + PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_D1HCLK; + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + DEBUG_printf("sdram: %s", "periph init clock error"); + } + /* Peripheral clock enable */ + __HAL_RCC_FMC_CLK_ENABLE(); + FMC_Initialized = 1; + for (uint i = 0; i < MP_ARRAY_SIZE(sdram_pin_list); i++) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + GPIO_InitStruct.Pin = pin_mask(sdram_pin_list[i].pin->number); + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_FMC; + HAL_GPIO_Init(pin_port(sdram_pin_list[i].pin->port), &GPIO_InitStruct); + never_reset_pin_number(sdram_pin_list[i].pin->port, sdram_pin_list[i].pin->number); + } + } + + /* SDRAM device configuration */ + hsdram.Instance = config->sdram; + + for (size_t i = 0U; i < config->banks_len; i++) { + hsdram.State = HAL_SDRAM_STATE_RESET; + + memcpy(&hsdram.Init, &config->banks[i].init, sizeof(hsdram.Init)); + + memcpy(&SDRAM_Timing, &config->banks[i].timing, sizeof(SDRAM_Timing)); + + /* Initialize the SDRAM controller */ + if (HAL_SDRAM_Init(&hsdram, &SDRAM_Timing) != HAL_OK) { + DEBUG_printf("sdram bank[%d]: %s", i, "init error"); + } + } + + sdram_init_seq(config); + +} +void sdram_deinit(void) { + FMC_SDRAM_CommandTypeDef command = {0}; + if (FMC_Initialized) { + /* Send the module into powerdown mode */ + command.CommandMode = FMC_SDRAM_CMD_POWERDOWN_MODE; + command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + command.AutoRefreshNumber = 1; + command.ModeRegisterDefinition = 0; + + /* Send the command */ + if (HAL_SDRAM_SendCommand(&hsdram, &command, HAL_MAX_DELAY) != HAL_OK) { + DEBUG_printf("sdram power off error:%s:%d", __func__, __LINE__); + } + } +} + +void *sdram_start(void) { + return (void *)sdram_start_address; +} + +void *sdram_end(void) { + return (void *)(sdram_start_address + CIRCUITPY_HW_SDRAM_SIZE); +} + +uint32_t sdram_size(void) { + return CIRCUITPY_HW_SDRAM_SIZE; +} + +static void sdram_init_seq(const struct stm32_sdram_config *config) { + FMC_SDRAM_CommandTypeDef command = {0}; + /* Program the SDRAM external device */ + + command.AutoRefreshNumber = config->num_auto_refresh; + command.ModeRegisterDefinition = config->mode_register; + if (config->banks_len == 2U) { + command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1_2; + sdram_start_address = 0xC0000000; + } else if (config->banks[0].init.SDBank == FMC_SDRAM_BANK1) { + command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; + sdram_start_address = 0xC0000000; + } else { + command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; + sdram_start_address = 0xD0000000; + + } + + /* Configure a clock configuration enable command */ + command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; + HAL_SDRAM_SendCommand(&hsdram, &command, HAL_MAX_DELAY); + + HAL_Delay(config->power_up_delay); + + /* Configure a PALL (precharge all) command */ + command.CommandMode = FMC_SDRAM_CMD_PALL; + HAL_SDRAM_SendCommand(&hsdram, &command, HAL_MAX_DELAY); + + /* Configure a Auto-Refresh command */ + command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; + HAL_SDRAM_SendCommand(&hsdram, &command, HAL_MAX_DELAY); + + command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE; + /* load mode */ + HAL_SDRAM_SendCommand(&hsdram, &command, HAL_MAX_DELAY); + + /* program refresh count */ + HAL_SDRAM_ProgramRefreshRate(&hsdram, config->refresh_rate); + + #if defined(STM32F7) || defined(STM32H7) + __disable_irq(); + MPU_Region_InitTypeDef MPU_InitStruct = {0}; + /** Enable caching for SDRAM to support non-alligned access. + */ + MPU_InitStruct.Enable = MPU_REGION_ENABLE; + MPU_InitStruct.Number = CPY_SDRAM_REGION; + MPU_InitStruct.BaseAddress = sdram_start_address; + MPU_InitStruct.Size = CPY_SDRAM_REGION_SIZE; + MPU_InitStruct.SubRegionDisable = 0x0; + MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; + MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; + MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; + MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; + MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; + MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; + + HAL_MPU_ConfigRegion(&MPU_InitStruct); + __ISB(); + __DSB(); + __DMB(); + __enable_irq(); + + #endif + +} + +#if defined(CIRCUITPY_HW_SDRAM_STARTUP_TEST) && (CIRCUITPY_HW_SDRAM_STARTUP_TEST == 1) + +bool __attribute__((optimize("Os"))) sdram_test(bool exhaustive) { + uint8_t const pattern = 0xaa; + uint8_t const antipattern = 0x55; + volatile uint8_t *const mem_base = (uint8_t *)sdram_start(); + + char error_buffer[1024]; + + DEBUG_printf("sdram: %s\n", "sdram test started"); + + #if (__DCACHE_PRESENT == 1) + bool i_cache_disabled = false; + bool d_cache_disabled = false; + + // Disable caches for testing. + if (SCB->CCR & (uint32_t)SCB_CCR_IC_Msk) { + SCB_DisableICache(); + i_cache_disabled = true; + } + + if (SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) { + SCB_DisableDCache(); + d_cache_disabled = true; + } + #endif + + // Test data bus + for (uint32_t i = 0; i < hsdram.Init.MemoryDataWidth; i++) { + *((volatile uint32_t *)mem_base) = (1u << i); + __DSB(); + if (*((volatile uint32_t *)mem_base) != (1u << i)) { + snprintf(error_buffer, sizeof(error_buffer), + "Data bus test failed at 0x%p expected 0x%x found 0x%lx", + &mem_base[0], (1 << i), ((volatile uint32_t *)mem_base)[0]); + DEBUG_printf("error: %s\n", error_buffer); + return false; + } + } + + // Test address bus + for (uint32_t i = 1; i < CIRCUITPY_HW_SDRAM_SIZE; i <<= 1) { + mem_base[i] = pattern; + __DSB(); + if (mem_base[i] != pattern) { + snprintf(error_buffer, sizeof(error_buffer), + "Address bus test failed at 0x%p expected 0x%x found 0x%x", + &mem_base[i], pattern, mem_base[i]); + DEBUG_printf("error: %s\n", error_buffer); + return false; + } + } + + // Check for aliasing (overlapping addresses) + mem_base[0] = antipattern; + __DSB(); + for (uint32_t i = 1; i < CIRCUITPY_HW_SDRAM_SIZE; i <<= 1) { + if (mem_base[i] != pattern) { + snprintf(error_buffer, sizeof(error_buffer), + "Address bus overlap at 0x%p expected 0x%x found 0x%x", + &mem_base[i], pattern, mem_base[i]); + DEBUG_printf("error: %s\n", error_buffer); + return false; + } + } + + // Test all RAM cells + if (exhaustive) { + // Write all memory first then compare, so even if the cache + // is enabled, it's not just writing and reading from cache. + // Note: This test should also detect refresh rate issues. + for (uint32_t i = 0; i < CIRCUITPY_HW_SDRAM_SIZE; i++) { + mem_base[i] = ((i % 2) ? pattern : antipattern); + } + + for (uint32_t i = 0; i < CIRCUITPY_HW_SDRAM_SIZE; i++) { + if (mem_base[i] != ((i % 2) ? pattern : antipattern)) { + snprintf(error_buffer, sizeof(error_buffer), + "Address bus slow test failed at 0x%p expected 0x%x found 0x%x", + &mem_base[i], ((i % 2) ? pattern : antipattern), mem_base[i]); + DEBUG_printf("error: %s\n", error_buffer); + return false; + } + } + } + + #if (__DCACHE_PRESENT == 1) + // Re-enable caches if they were enabled before the test started. + if (i_cache_disabled) { + SCB_EnableICache(); + } + + if (d_cache_disabled) { + SCB_EnableDCache(); + } + #endif + + DEBUG_printf("sdram: %s\n", "sdram test successfully!"); + + return true; +} + +#endif // sdram_test diff --git a/ports/stm/peripherals/sdram.h b/ports/stm/peripherals/sdram.h new file mode 100644 index 0000000000000..46343b6861e43 --- /dev/null +++ b/ports/stm/peripherals/sdram.h @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "stm32h7xx_ll_fmc.h" +#include +#include + +#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001) +#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002) +#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004) +#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000) +#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008) +#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020) +#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030) +#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000) +#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200) + +/** FMC SDRAM controller bank configuration fields. */ +struct stm32_sdram_bank_config { + FMC_SDRAM_InitTypeDef init; + FMC_SDRAM_TimingTypeDef timing; +}; + +/** FMC SDRAM controller configuration fields. */ +struct stm32_sdram_config { + FMC_SDRAM_TypeDef *sdram; + uint32_t power_up_delay; + uint8_t num_auto_refresh; + uint16_t mode_register; + uint16_t refresh_rate; + const struct stm32_sdram_bank_config *banks; + size_t banks_len; +}; + +void sdram_init(const struct stm32_sdram_config *config); +void sdram_deinit(void); +void *sdram_start(void); +void *sdram_end(void); +uint32_t sdram_size(void); +bool sdram_test(bool exhaustive); diff --git a/ports/stm/peripherals/stm32h7/clocks.c b/ports/stm/peripherals/stm32h7/clocks.c index 8c63031859c4f..717840040dbb7 100644 --- a/ports/stm/peripherals/stm32h7/clocks.c +++ b/ports/stm/peripherals/stm32h7/clocks.c @@ -13,6 +13,10 @@ #include "stm32h7/stm32h743xx/clocks.h" #endif +#ifdef STM32H750xx +#include "stm32h7/stm32h750xx/clocks.h" +#endif + void stm32_peripherals_clocks_init(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; @@ -42,16 +46,16 @@ void stm32_peripherals_clocks_init(void) { RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; #endif RCC_OscInitStruct.HSEState = BOARD_HSE_SOURCE; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; - RCC_OscInitStruct.PLL.PLLM = HSE_VALUE / 2000000; + RCC_OscInitStruct.PLL.PLLState = BOARD_PLL_STATE; + RCC_OscInitStruct.PLL.PLLSource = BOARD_PLL_SOURCE; + RCC_OscInitStruct.PLL.PLLM = CPY_CLK_PLLM; RCC_OscInitStruct.PLL.PLLN = CPY_CLK_PLLN; RCC_OscInitStruct.PLL.PLLP = CPY_CLK_PLLP; RCC_OscInitStruct.PLL.PLLQ = CPY_CLK_PLLQ; - RCC_OscInitStruct.PLL.PLLR = 2; - RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1; - RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE; - RCC_OscInitStruct.PLL.PLLFRACN = 0; + RCC_OscInitStruct.PLL.PLLR = CPY_CLK_PLLR; + RCC_OscInitStruct.PLL.PLLRGE = CPY_CLK_PLLRGE; + RCC_OscInitStruct.PLL.PLLVCOSEL = CPY_CLK_PLLVCOSEL; + RCC_OscInitStruct.PLL.PLLFRACN = CPY_CLK_PLLFRACN; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { // Clock issues are too problematic to even attempt recovery. // If you end up here, check whether your LSE settings match your board. @@ -88,8 +92,28 @@ void stm32_peripherals_clocks_init(void) { #else PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL; #endif - HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); - + #ifdef STM32H750xx + // USB + PeriphClkInitStruct.PLL3.PLL3M = 1; + PeriphClkInitStruct.PLL3.PLL3N = 12; + PeriphClkInitStruct.PLL3.PLL3P = 2; + PeriphClkInitStruct.PLL3.PLL3Q = 4; + PeriphClkInitStruct.PLL3.PLL3R = 2; + PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_3; + PeriphClkInitStruct.PLL3.PLL3FRACN = 0; + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3; + // RNG + PeriphClkInitStruct.PeriphClockSelection = PeriphClkInitStruct.PeriphClockSelection | RCC_PERIPHCLK_RNG; + PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_HSI48; + // RTC + PeriphClkInitStruct.PeriphClockSelection = PeriphClkInitStruct.PeriphClockSelection | RCC_PERIPHCLK_RTC; + PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI; + #endif + if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { + while (1) { + ; + } + } // Enable USB Voltage detector HAL_PWREx_EnableUSBVoltageDetector(); } diff --git a/ports/stm/peripherals/stm32h7/stm32h743xx/clocks.h b/ports/stm/peripherals/stm32h7/stm32h743xx/clocks.h index 56bb598ab74a6..d59e51686de3f 100644 --- a/ports/stm/peripherals/stm32h7/stm32h743xx/clocks.h +++ b/ports/stm/peripherals/stm32h7/stm32h743xx/clocks.h @@ -16,6 +16,9 @@ #ifndef CPY_CLK_VSCALE #define CPY_CLK_VSCALE (PWR_REGULATOR_VOLTAGE_SCALE0) #endif +#ifndef CPY_CLK_PLLM +#define CPY_CLK_PLLM (HSE_VALUE / 2000000) +#endif #ifndef CPY_CLK_PLLN #define CPY_CLK_PLLN (480) #endif @@ -25,6 +28,18 @@ #ifndef CPY_CLK_PLLQ #define CPY_CLK_PLLQ (20) #endif +#ifndef CPY_CLK_PLLR +#define CPY_CLK_PLLR (2) +#endif +#ifndef CPY_CLK_PLLRGE +#define CPY_CLK_PLLRGE (RCC_PLL1VCIRANGE_1) +#endif +#ifndef CPY_CLK_PLLVCOSEL +#define CPY_CLK_PLLVCOSEL (RCC_PLL1VCOWIDE) +#endif +#ifndef CPY_CLK_PLLFRACN +#define CPY_CLK_PLLFRACN (0) +#endif #ifndef CPY_CLK_AHBDIV #define CPY_CLK_AHBDIV (RCC_HCLK_DIV2) #endif @@ -49,3 +64,9 @@ #ifndef BOARD_HSE_SOURCE #define BOARD_HSE_SOURCE (RCC_HSE_ON) #endif +#ifndef BOARD_PLL_STATE +#define BOARD_PLL_STATE (RCC_PLL_ON) +#endif +#ifndef BOARD_PLL_SOURCE +#define BOARD_PLL_SOURCE (RCC_PLLSOURCE_HSE) +#endif diff --git a/ports/stm/peripherals/stm32h7/stm32h743xx/periph.h b/ports/stm/peripherals/stm32h7/stm32h743xx/periph.h index fa4ec7f6e5621..2ff49c8503ce5 100644 --- a/ports/stm/peripherals/stm32h7/stm32h743xx/periph.h +++ b/ports/stm/peripherals/stm32h7/stm32h743xx/periph.h @@ -30,3 +30,4 @@ extern const mcu_periph_obj_t mcu_uart_rx_list[26]; #define TIM_BANK_ARRAY_LEN 14 #define TIM_PIN_ARRAY_LEN 58 extern TIM_TypeDef *mcu_tim_banks[TIM_BANK_ARRAY_LEN]; +extern const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN]; diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/clocks.h b/ports/stm/peripherals/stm32h7/stm32h750xx/clocks.h new file mode 100644 index 0000000000000..25f4d9cc9a0e2 --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/clocks.h @@ -0,0 +1,70 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "stm32h7xx_hal.h" + +// Chip: STM32H750 +// Line Type: Single-Core +// Speed: 480MHz (MAX) + +// Defaults: +#ifndef CPY_CLK_VSCALE +#define CPY_CLK_VSCALE (PWR_REGULATOR_VOLTAGE_SCALE0) +#endif +#ifndef CPY_CLK_PLLM +#define CPY_CLK_PLLM (1) +#endif +#ifndef CPY_CLK_PLLN +#define CPY_CLK_PLLN (50) +#endif +#ifndef CPY_CLK_PLLP +#define CPY_CLK_PLLP (2) +#endif +#ifndef CPY_CLK_PLLQ +#define CPY_CLK_PLLQ (4) +#endif +#ifndef CPY_CLK_PLLR +#define CPY_CLK_PLLR (2) +#endif +#ifndef CPY_CLK_PLLRGE +#define CPY_CLK_PLLRGE (RCC_PLL1VCIRANGE_3) +#endif +#ifndef CPY_CLK_PLLVCOSEL +#define CPY_CLK_PLLVCOSEL (RCC_PLL1VCOWIDE) +#endif +#ifndef CPY_CLK_PLLFRACN +#define CPY_CLK_PLLFRACN (0) +#endif +#ifndef CPY_CLK_AHBDIV +#define CPY_CLK_AHBDIV (RCC_HCLK_DIV2) +#endif +#ifndef CPY_CLK_APB1DIV +#define CPY_CLK_APB1DIV (RCC_APB1_DIV2) +#endif +#ifndef CPY_CLK_APB2DIV +#define CPY_CLK_APB2DIV (RCC_APB2_DIV2) +#endif +#ifndef CPY_CLK_APB3DIV +#define CPY_CLK_APB3DIV (RCC_APB3_DIV2) +#endif +#ifndef CPY_CLK_APB4DIV +#define CPY_CLK_APB4DIV (RCC_APB4_DIV2) +#endif +#ifndef CPY_CLK_FLASH_LATENCY +#define CPY_CLK_FLASH_LATENCY (FLASH_LATENCY_2) +#endif +#ifndef CPY_CLK_USB_USES_AUDIOPLL +#define CPY_CLK_USB_USES_AUDIOPLL (0) +#endif +#ifndef BOARD_HSE_SOURCE +#define BOARD_HSE_SOURCE (RCC_HSE_ON) +#endif +#ifndef BOARD_PLL_STATE +#define BOARD_PLL_STATE (RCC_PLL_ON) +#endif +#ifndef BOARD_PLL_SOURCE +#define BOARD_PLL_SOURCE (RCC_PLLSOURCE_HSE) +#endif diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/gpio.c b/ports/stm/peripherals/stm32h7/stm32h750xx/gpio.c new file mode 100644 index 0000000000000..f5ad843c9a61b --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/gpio.c @@ -0,0 +1,35 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "gpio.h" +#include "common-hal/microcontroller/Pin.h" + +void stm32_peripherals_gpio_init(void) { + // Enable all GPIO for now + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + __HAL_RCC_GPIOE_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_GPIOG_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + __HAL_RCC_GPIOI_CLK_ENABLE(); + +// Never reset pins + never_reset_pin_number(7, 0); // PH00 OSC32_IN + never_reset_pin_number(7, 1); // PH01 OSC32_OUT + never_reset_pin_number(0, 13); // PA13 SWDIO + never_reset_pin_number(0, 14); // PA14 SWCLK + // qspi flash pins for the Daisy Seed -- TODO ? + never_reset_pin_number(5, 6); // PF06 QSPI IO3 + never_reset_pin_number(5, 7); // PF07 QSPI IO2 + never_reset_pin_number(5, 8); // PF08 QSPI IO0 + never_reset_pin_number(5, 9); // PF09 QSPI IO1 + never_reset_pin_number(5, 10); // PF10 QSPI CLK + never_reset_pin_number(6, 6); // PG06 QSPI NCS + +} diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/periph.c b/ports/stm/peripherals/stm32h7/stm32h750xx/periph.c new file mode 100644 index 0000000000000..023e06ee32245 --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/periph.c @@ -0,0 +1,385 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" +#include "peripherals/periph.h" + +// See alternate functions tables in the STM32H750xx datasheet + +// I2C +I2C_TypeDef *mcu_i2c_banks[MAX_I2C] = {I2C1, I2C2, I2C3, I2C4}; + +const mcu_periph_obj_t mcu_i2c_sda_list[12] = { + PERIPH(1, 4, &pin_PB07), + PERIPH(4, 6, &pin_PB07), + PERIPH(1, 4, &pin_PB09), + PERIPH(4, 6, &pin_PB09), + PERIPH(2, 4, &pin_PB11), + PERIPH(3, 4, &pin_PC09), + PERIPH(4, 4, &pin_PD13), + PERIPH(2, 4, &pin_PF00), + PERIPH(4, 4, &pin_PF15), + PERIPH(2, 4, &pin_PH05), + PERIPH(3, 4, &pin_PH08), + PERIPH(4, 4, &pin_PH12) +}; + +const mcu_periph_obj_t mcu_i2c_scl_list[12] = { + PERIPH(3, 4, &pin_PA08), + PERIPH(1, 4, &pin_PB06), + PERIPH(4, 6, &pin_PB06), + PERIPH(1, 4, &pin_PB08), + PERIPH(4, 6, &pin_PB08), + PERIPH(2, 4, &pin_PB10), + PERIPH(4, 4, &pin_PD12), + PERIPH(2, 4, &pin_PF01), + PERIPH(4, 4, &pin_PF14), + PERIPH(2, 4, &pin_PH04), + PERIPH(3, 4, &pin_PH07), + PERIPH(4, 4, &pin_PH11) +}; + +// SPI + +SPI_TypeDef *mcu_spi_banks[MAX_SPI] = {SPI1, SPI2, SPI3, SPI4, SPI5, SPI6}; + +const mcu_periph_obj_t mcu_spi_sck_list[18] = { + PERIPH(1, 5, &pin_PA05), + PERIPH(6, 8, &pin_PA05), + PERIPH(2, 5, &pin_PA09), + PERIPH(2, 5, &pin_PA12), + PERIPH(1, 5, &pin_PB03), + PERIPH(3, 6, &pin_PB03), + PERIPH(6, 8, &pin_PB03), + PERIPH(2, 5, &pin_PB10), + PERIPH(2, 5, &pin_PB13), + PERIPH(3, 6, &pin_PC10), + PERIPH(2, 5, &pin_PD03), + PERIPH(4, 5, &pin_PE02), + PERIPH(4, 5, &pin_PE12), + PERIPH(5, 5, &pin_PF07), + PERIPH(1, 5, &pin_PG11), + PERIPH(6, 5, &pin_PG13), + PERIPH(5, 5, &pin_PH06), + PERIPH(2, 5, &pin_PI01), +}; + +const mcu_periph_obj_t mcu_spi_mosi_list[18] = { + PERIPH(1, 5, &pin_PA07), + PERIPH(6, 8, &pin_PA07), + PERIPH(3, 7, &pin_PB02), + PERIPH(1, 5, &pin_PB05), + PERIPH(3, 7, &pin_PB05), + PERIPH(6, 8, &pin_PB05), + PERIPH(2, 5, &pin_PB15), + PERIPH(2, 5, &pin_PC01), + PERIPH(2, 5, &pin_PC03), + PERIPH(3, 6, &pin_PC12), + PERIPH(3, 5, &pin_PD06), + PERIPH(1, 5, &pin_PD07), + PERIPH(4, 5, &pin_PE06), + PERIPH(4, 5, &pin_PE14), + PERIPH(5, 5, &pin_PF09), + PERIPH(5, 5, &pin_PF11), + PERIPH(6, 5, &pin_PG14), + PERIPH(2, 5, &pin_PI03), +}; + +const mcu_periph_obj_t mcu_spi_miso_list[15] = { + PERIPH(1, 5, &pin_PA06), + PERIPH(6, 8, &pin_PA06), + PERIPH(1, 5, &pin_PB04), + PERIPH(3, 6, &pin_PB04), + PERIPH(6, 8, &pin_PB04), + PERIPH(2, 5, &pin_PB14), + PERIPH(2, 5, &pin_PC02), + PERIPH(3, 6, &pin_PC11), + PERIPH(4, 5, &pin_PE05), + PERIPH(4, 5, &pin_PE13), + PERIPH(5, 5, &pin_PF08), + PERIPH(1, 5, &pin_PG09), + PERIPH(6, 5, &pin_PG12), + PERIPH(5, 5, &pin_PH07), + PERIPH(2, 5, &pin_PI02), +}; + +// UART + +USART_TypeDef *mcu_uart_banks[MAX_UART] = {USART1, USART2, USART3, UART4, UART5, USART6, UART7, UART8}; +// circuitpython doesn't implement USART +// bool mcu_uart_has_usart[MAX_UART] = {true, true, true, false, false, true, false, false, false}; + +const mcu_periph_obj_t mcu_uart_tx_list[24] = { + PERIPH(4, 8, &pin_PA00), + PERIPH(2, 7, &pin_PA02), + PERIPH(1, 7, &pin_PA09), + PERIPH(4, 6, &pin_PA12), + PERIPH(7, 11, &pin_PA15), + PERIPH(7, 11, &pin_PB04), + PERIPH(1, 7, &pin_PB06), + PERIPH(5, 14, &pin_PB06), + PERIPH(4, 8, &pin_PB09), + PERIPH(3, 7, &pin_PB10), + PERIPH(5, 14, &pin_PB13), + PERIPH(1, 4, &pin_PB14), + PERIPH(6, 7, &pin_PC06), + PERIPH(3, 7, &pin_PC10), + PERIPH(4, 8, &pin_PC10), + PERIPH(5, 8, &pin_PC12), + PERIPH(4, 8, &pin_PD01), + PERIPH(2, 7, &pin_PD05), + PERIPH(3, 7, &pin_PD08), + PERIPH(8, 8, &pin_PE01), + PERIPH(7, 7, &pin_PE08), + PERIPH(7, 7, &pin_PF07), + PERIPH(6, 7, &pin_PG14), + PERIPH(4, 8, &pin_PH13), +}; + +const mcu_periph_obj_t mcu_uart_rx_list[25] = { + PERIPH(4, 8, &pin_PA01), + PERIPH(2, 7, &pin_PA03), + PERIPH(7, 11, &pin_PA08), + PERIPH(1, 7, &pin_PA10), + PERIPH(4, 6, &pin_PA11), + PERIPH(7, 11, &pin_PB03), + PERIPH(5, 14, &pin_PB05), + PERIPH(1, 7, &pin_PB07), + PERIPH(4, 8, &pin_PB08), + PERIPH(3, 7, &pin_PB11), + PERIPH(5, 14, &pin_PB12), + PERIPH(1, 4, &pin_PB15), + PERIPH(6, 7, &pin_PC07), + PERIPH(3, 7, &pin_PC11), + PERIPH(4, 8, &pin_PC11), + PERIPH(4, 8, &pin_PD00), + PERIPH(5, 8, &pin_PD02), + PERIPH(2, 7, &pin_PD06), + PERIPH(3, 7, &pin_PD09), + PERIPH(8, 8, &pin_PE00), + PERIPH(7, 7, &pin_PE07), + PERIPH(7, 7, &pin_PF06), + PERIPH(6, 7, &pin_PG09), + PERIPH(4, 8, &pin_PH14), + PERIPH(4, 8, &pin_PI09), +}; + +// Timers +// TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins +TIM_TypeDef *mcu_tim_banks[TIM_BANK_ARRAY_LEN] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, + NULL, NULL, NULL, TIM12, TIM13, TIM14, TIM15, TIM16, TIM17}; +const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN] = { + TIM(2, 1, 1, &pin_PA00), + TIM(5, 2, 1, &pin_PA00), + TIM(2, 1, 2, &pin_PA01), + TIM(5, 2, 2, &pin_PA01), + TIM(2, 1, 3, &pin_PA02), + TIM(5, 2, 3, &pin_PA02), + TIM(15, 4, 1, &pin_PA02), + TIM(2, 1, 4, &pin_PA03), + TIM(5, 2, 4, &pin_PA03), + TIM(15, 4, 2, &pin_PA03), + TIM(2, 1, 1, &pin_PA05), + TIM(3, 2, 1, &pin_PA06), + TIM(13, 9, 1, &pin_PA06), + TIM(3, 2, 2, &pin_PA07), + TIM(14, 9, 1, &pin_PA07), + TIM(1, 1, 1, &pin_PA08), + TIM(1, 1, 2, &pin_PA09), + TIM(1, 1, 3, &pin_PA10), + TIM(1, 1, 4, &pin_PA11), + TIM(2, 1, 1, &pin_PA15), + TIM(3, 2, 3, &pin_PB00), + TIM(3, 2, 4, &pin_PB01), + TIM(2, 1, 2, &pin_PB03), + TIM(3, 2, 1, &pin_PB04), + TIM(3, 2, 2, &pin_PB05), + TIM(4, 2, 1, &pin_PB06), + TIM(4, 2, 2, &pin_PB07), + TIM(4, 2, 3, &pin_PB08), + TIM(4, 2, 4, &pin_PB09), + TIM(2, 1, 3, &pin_PB10), + TIM(2, 1, 4, &pin_PB11), + TIM(12, 2, 1, &pin_PB14), + TIM(12, 2, 2, &pin_PB15), + TIM(3, 2, 1, &pin_PC06), + TIM(8, 3, 1, &pin_PC06), + TIM(3, 2, 2, &pin_PC07), + TIM(8, 3, 2, &pin_PC07), + TIM(3, 2, 3, &pin_PC08), + TIM(8, 3, 3, &pin_PC08), + TIM(3, 2, 4, &pin_PC09), + TIM(8, 3, 4, &pin_PC09), + TIM(4, 2, 1, &pin_PD12), + TIM(4, 2, 2, &pin_PD13), + TIM(4, 2, 3, &pin_PD14), + TIM(4, 2, 4, &pin_PD15), + TIM(15, 4, 1, &pin_PE05), + TIM(15, 4, 2, &pin_PE06), + TIM(1, 1, 1, &pin_PE09), + TIM(1, 1, 2, &pin_PE11), + TIM(1, 1, 3, &pin_PE13), + TIM(1, 1, 4, &pin_PE14), + TIM(16, 1, 1, &pin_PF06), + TIM(17, 1, 1, &pin_PF07), + TIM(13, 9, 1, &pin_PF08), + TIM(14, 9, 1, &pin_PF09), + TIM(12, 2, 1, &pin_PH06), + TIM(12, 2, 2, &pin_PH09), + TIM(5, 2, 1, &pin_PH10), + TIM(5, 2, 2, &pin_PH11), + TIM(5, 2, 3, &pin_PH12), + TIM(5, 2, 4, &pin_PI00), + TIM(8, 3, 4, &pin_PI02), + TIM(8, 3, 1, &pin_PI05), + TIM(8, 3, 2, &pin_PI06), + TIM(8, 3, 3, &pin_PI07), +}; + +// SDIO - H750 has a MMC interface that includes SDIO +SDMMC_TypeDef *mcu_sdio_banks[1] = {SDMMC1}; + +const mcu_periph_obj_t mcu_sdio_clock_list[1] = { + PERIPH(1, 12, &pin_PC12), +}; +const mcu_periph_obj_t mcu_sdio_command_list[1] = { + PERIPH(1, 12, &pin_PD02), +}; +const mcu_periph_obj_t mcu_sdio_data0_list[1] = { + PERIPH(1, 12, &pin_PC08), +}; +const mcu_periph_obj_t mcu_sdio_data1_list[1] = { + PERIPH(1, 12, &pin_PC09), +}; +const mcu_periph_obj_t mcu_sdio_data2_list[1] = { + PERIPH(1, 12, &pin_PC10), +}; +const mcu_periph_obj_t mcu_sdio_data3_list[1] = { + PERIPH(1, 12, &pin_PC11), +}; + + +/** FMC GPIO Configuration + PE1 ------> FMC_NBL1 + PE0 ------> FMC_NBL0 + PG15 ------> FMC_SDNCAS + PD0 ------> FMC_D2 + PI7 ------> FMC_D29 + PI6 ------> FMC_D28 + PI5 ------> FMC_NBL3 + PD1 ------> FMC_D3 + PI3 ------> FMC_D27 + PI2 ------> FMC_D26 + PI9 ------> FMC_D30 + PI4 ------> FMC_NBL2 + PH15 ------> FMC_D23 + PI1 ------> FMC_D25 + PF0 ------> FMC_A0 + PI10 ------> FMC_D31 + PH13 ------> FMC_D21 + PH14 ------> FMC_D22 + PI0 ------> FMC_D24 + PH2 ------> FMC_SDCKE0 + PH3 ------> FMC_SDNE0 + PF2 ------> FMC_A2 + PF1 ------> FMC_A1 + PG8 ------> FMC_SDCLK + PF3 ------> FMC_A3 + PF4 ------> FMC_A4 + PH5 ------> FMC_SDNWE + PF5 ------> FMC_A5 + PH12 ------> FMC_D20 + PG5 ------> FMC_BA1 + PG4 ------> FMC_BA0 + PH11 ------> FMC_D19 + PH10 ------> FMC_D18 + PD15 ------> FMC_D1 + PG2 ------> FMC_A12 + PG1 ------> FMC_A11 + PH8 ------> FMC_D16 + PH9 ------> FMC_D17 + PD14 ------> FMC_D0 + PF13 ------> FMC_A7 + PG0 ------> FMC_A10 + PE13 ------> FMC_D10 + PD10 ------> FMC_D15 + PF12 ------> FMC_A6 + PF15 ------> FMC_A9 + PE8 ------> FMC_D5 + PE9 ------> FMC_D6 + PE11 ------> FMC_D8 + PE14 ------> FMC_D11 + PD9 ------> FMC_D14 + PD8 ------> FMC_D13 + PF11 ------> FMC_SDNRAS + PF14 ------> FMC_A8 + PE7 ------> FMC_D4 + PE10 ------> FMC_D7 + PE12 ------> FMC_D9 + PE15 ------> FMC_D12 + */ + +const mcu_periph_obj_t sdram_pin_list[57] = { + PERIPH(4, 12, &pin_PE01), + PERIPH(4, 12, &pin_PE00), + PERIPH(6, 12, &pin_PG15), + PERIPH(3, 12, &pin_PD00), + PERIPH(8, 12, &pin_PI07), + PERIPH(8, 12, &pin_PI06), + PERIPH(8, 12, &pin_PI05), + PERIPH(3, 12, &pin_PD01), + PERIPH(8, 12, &pin_PI03), + PERIPH(8, 12, &pin_PI02), + PERIPH(8, 12, &pin_PI09), + PERIPH(8, 12, &pin_PI04), + PERIPH(7, 12, &pin_PH15), + PERIPH(8, 12, &pin_PI01), + PERIPH(5, 12, &pin_PF00), + PERIPH(8, 12, &pin_PI10), + PERIPH(7, 12, &pin_PH13), + PERIPH(7, 12, &pin_PH14), + PERIPH(8, 12, &pin_PI00), + PERIPH(7, 12, &pin_PH02), + PERIPH(7, 12, &pin_PH03), + PERIPH(5, 12, &pin_PF02), + PERIPH(5, 12, &pin_PF01), + PERIPH(6, 12, &pin_PG08), + PERIPH(5, 12, &pin_PF03), + PERIPH(5, 12, &pin_PF04), + PERIPH(7, 12, &pin_PH05), + PERIPH(5, 12, &pin_PF05), + PERIPH(7, 12, &pin_PH12), + PERIPH(6, 12, &pin_PG05), + PERIPH(6, 12, &pin_PG04), + PERIPH(7, 12, &pin_PH11), + PERIPH(7, 12, &pin_PH10), + PERIPH(3, 12, &pin_PD15), + PERIPH(6, 12, &pin_PG02), + PERIPH(6, 12, &pin_PG01), + PERIPH(7, 12, &pin_PH08), + PERIPH(7, 12, &pin_PH09), + PERIPH(3, 12, &pin_PD14), + PERIPH(5, 12, &pin_PF13), + PERIPH(6, 12, &pin_PG00), + PERIPH(4, 12, &pin_PE13), + PERIPH(3, 12, &pin_PD10), + PERIPH(5, 12, &pin_PF12), + PERIPH(5, 12, &pin_PF15), + PERIPH(4, 12, &pin_PE08), + PERIPH(4, 12, &pin_PE09), + PERIPH(4, 12, &pin_PE11), + PERIPH(4, 12, &pin_PE14), + PERIPH(3, 12, &pin_PD09), + PERIPH(3, 12, &pin_PD08), + PERIPH(5, 12, &pin_PF11), + PERIPH(5, 12, &pin_PF14), + PERIPH(4, 12, &pin_PE07), + PERIPH(4, 12, &pin_PE10), + PERIPH(4, 12, &pin_PE12), + PERIPH(4, 12, &pin_PE15), +}; diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/periph.h b/ports/stm/peripherals/stm32h7/stm32h750xx/periph.h new file mode 100644 index 0000000000000..f90f55071804d --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/periph.h @@ -0,0 +1,45 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#pragma once + +// I2C +extern I2C_TypeDef *mcu_i2c_banks[MAX_I2C]; + +extern const mcu_periph_obj_t mcu_i2c_sda_list[12]; +extern const mcu_periph_obj_t mcu_i2c_scl_list[12]; + +// SPI +extern SPI_TypeDef *mcu_spi_banks[MAX_SPI]; + +extern const mcu_periph_obj_t mcu_spi_sck_list[18]; +extern const mcu_periph_obj_t mcu_spi_mosi_list[18]; +extern const mcu_periph_obj_t mcu_spi_miso_list[15]; + +// UART +extern USART_TypeDef *mcu_uart_banks[MAX_UART]; +extern bool mcu_uart_has_usart[MAX_UART]; + +extern const mcu_periph_obj_t mcu_uart_tx_list[24]; +extern const mcu_periph_obj_t mcu_uart_rx_list[25]; + +// Timers +#define TIM_PIN_ARRAY_LEN 65 +extern const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN]; +#define TIM_BANK_ARRAY_LEN 17 +extern TIM_TypeDef *mcu_tim_banks[TIM_BANK_ARRAY_LEN]; + +// SDIO - H750 has a MMC interface that includes SDIO +extern SDMMC_TypeDef *mcu_sdio_banks[1]; + +extern const mcu_periph_obj_t mcu_sdio_clock_list[1]; +extern const mcu_periph_obj_t mcu_sdio_command_list[1]; +extern const mcu_periph_obj_t mcu_sdio_data0_list[1]; +extern const mcu_periph_obj_t mcu_sdio_data1_list[1]; +extern const mcu_periph_obj_t mcu_sdio_data2_list[1]; +extern const mcu_periph_obj_t mcu_sdio_data3_list[1]; +// SDRam +extern const mcu_periph_obj_t sdram_pin_list[57]; diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/pins.c b/ports/stm/peripherals/stm32h7/stm32h750xx/pins.c new file mode 100644 index 0000000000000..bd0485b03f561 --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/pins.c @@ -0,0 +1,164 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" + +// ADC added only to pins exposed on Daisy Seed board + +const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_1, 16)); +const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_1, 17)); +const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_12, 14)); +const mcu_pin_obj_t pin_PA03 = PIN(0, 3, ADC_INPUT(ADC_12, 15)); +const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_12, 18)); +const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_12, 19)); +const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_12, 3)); +const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_12, 7)); +const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC); +const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC); +const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC); +const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC); +const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC); +const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC); +const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC); +const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC); + +const mcu_pin_obj_t pin_PB00 = PIN(1, 0, NO_ADC); +const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_12, 5)); +const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC); +const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC); +const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC); +const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC); +const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC); +const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC); +const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC); +const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC); +const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC); +const mcu_pin_obj_t pin_PB11 = PIN(1, 11, NO_ADC); +const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC); +const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC); +const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC); +const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC); + +const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_12, 10)); +const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_123, 11)); +const mcu_pin_obj_t pin_PC02 = PIN(2, 2, NO_ADC); +const mcu_pin_obj_t pin_PC03 = PIN(2, 3, NO_ADC); +const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_12, 4)); +const mcu_pin_obj_t pin_PC05 = PIN(2, 5, NO_ADC); +const mcu_pin_obj_t pin_PC06 = PIN(2, 6, NO_ADC); +const mcu_pin_obj_t pin_PC07 = PIN(2, 7, NO_ADC); +const mcu_pin_obj_t pin_PC08 = PIN(2, 8, NO_ADC); +const mcu_pin_obj_t pin_PC09 = PIN(2, 9, NO_ADC); +const mcu_pin_obj_t pin_PC10 = PIN(2, 10, NO_ADC); +const mcu_pin_obj_t pin_PC11 = PIN(2, 11, NO_ADC); +const mcu_pin_obj_t pin_PC12 = PIN(2, 12, NO_ADC); +const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); +const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); +const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); + +const mcu_pin_obj_t pin_PD00 = PIN(3, 0, NO_ADC); +const mcu_pin_obj_t pin_PD01 = PIN(3, 1, NO_ADC); +const mcu_pin_obj_t pin_PD02 = PIN(3, 2, NO_ADC); +const mcu_pin_obj_t pin_PD03 = PIN(3, 3, NO_ADC); +const mcu_pin_obj_t pin_PD04 = PIN(3, 4, NO_ADC); +const mcu_pin_obj_t pin_PD05 = PIN(3, 5, NO_ADC); +const mcu_pin_obj_t pin_PD06 = PIN(3, 6, NO_ADC); +const mcu_pin_obj_t pin_PD07 = PIN(3, 7, NO_ADC); +const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC); +const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC); +const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC); +const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC); +const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC); +const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC); +const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC); +const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC); + +const mcu_pin_obj_t pin_PE00 = PIN(4, 0, NO_ADC); +const mcu_pin_obj_t pin_PE01 = PIN(4, 1, NO_ADC); +const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC); +const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC); +const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC); +const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC); +const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC); +const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC); +const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC); +const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC); +const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC); +const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC); +const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC); +const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC); +const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC); +const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC); + +const mcu_pin_obj_t pin_PF00 = PIN(5, 0, NO_ADC); +const mcu_pin_obj_t pin_PF01 = PIN(5, 1, NO_ADC); +const mcu_pin_obj_t pin_PF02 = PIN(5, 2, NO_ADC); +const mcu_pin_obj_t pin_PF03 = PIN(5, 3, NO_ADC); +const mcu_pin_obj_t pin_PF04 = PIN(5, 4, NO_ADC); +const mcu_pin_obj_t pin_PF05 = PIN(5, 5, NO_ADC); +const mcu_pin_obj_t pin_PF06 = PIN(5, 6, NO_ADC); +const mcu_pin_obj_t pin_PF07 = PIN(5, 7, NO_ADC); +const mcu_pin_obj_t pin_PF08 = PIN(5, 8, NO_ADC); +const mcu_pin_obj_t pin_PF09 = PIN(5, 9, NO_ADC); +const mcu_pin_obj_t pin_PF10 = PIN(5, 10, NO_ADC); +const mcu_pin_obj_t pin_PF11 = PIN(5, 11, NO_ADC); +const mcu_pin_obj_t pin_PF12 = PIN(5, 12, NO_ADC); +const mcu_pin_obj_t pin_PF13 = PIN(5, 13, NO_ADC); +const mcu_pin_obj_t pin_PF14 = PIN(5, 14, NO_ADC); +const mcu_pin_obj_t pin_PF15 = PIN(5, 15, NO_ADC); + +const mcu_pin_obj_t pin_PG00 = PIN(6, 0, NO_ADC); +const mcu_pin_obj_t pin_PG01 = PIN(6, 1, NO_ADC); +const mcu_pin_obj_t pin_PG02 = PIN(6, 2, NO_ADC); +const mcu_pin_obj_t pin_PG03 = PIN(6, 3, NO_ADC); +const mcu_pin_obj_t pin_PG04 = PIN(6, 4, NO_ADC); +const mcu_pin_obj_t pin_PG05 = PIN(6, 5, NO_ADC); +const mcu_pin_obj_t pin_PG06 = PIN(6, 6, NO_ADC); +const mcu_pin_obj_t pin_PG07 = PIN(6, 7, NO_ADC); +const mcu_pin_obj_t pin_PG08 = PIN(6, 8, NO_ADC); +const mcu_pin_obj_t pin_PG09 = PIN(6, 9, NO_ADC); +const mcu_pin_obj_t pin_PG10 = PIN(6, 10, NO_ADC); +const mcu_pin_obj_t pin_PG11 = PIN(6, 11, NO_ADC); +const mcu_pin_obj_t pin_PG12 = PIN(6, 12, NO_ADC); +const mcu_pin_obj_t pin_PG13 = PIN(6, 13, NO_ADC); +const mcu_pin_obj_t pin_PG14 = PIN(6, 14, NO_ADC); +const mcu_pin_obj_t pin_PG15 = PIN(6, 15, NO_ADC); + +const mcu_pin_obj_t pin_PH00 = PIN(7, 0, NO_ADC); +const mcu_pin_obj_t pin_PH01 = PIN(7, 1, NO_ADC); +const mcu_pin_obj_t pin_PH02 = PIN(7, 2, NO_ADC); +const mcu_pin_obj_t pin_PH03 = PIN(7, 3, NO_ADC); +const mcu_pin_obj_t pin_PH04 = PIN(7, 4, NO_ADC); +const mcu_pin_obj_t pin_PH05 = PIN(7, 5, NO_ADC); +const mcu_pin_obj_t pin_PH06 = PIN(7, 6, NO_ADC); +const mcu_pin_obj_t pin_PH07 = PIN(7, 7, NO_ADC); +const mcu_pin_obj_t pin_PH08 = PIN(7, 8, NO_ADC); +const mcu_pin_obj_t pin_PH09 = PIN(7, 9, NO_ADC); +const mcu_pin_obj_t pin_PH10 = PIN(7, 10, NO_ADC); +const mcu_pin_obj_t pin_PH11 = PIN(7, 11, NO_ADC); +const mcu_pin_obj_t pin_PH12 = PIN(7, 12, NO_ADC); +const mcu_pin_obj_t pin_PH13 = PIN(7, 13, NO_ADC); +const mcu_pin_obj_t pin_PH14 = PIN(7, 14, NO_ADC); +const mcu_pin_obj_t pin_PH15 = PIN(7, 15, NO_ADC); + +const mcu_pin_obj_t pin_PI00 = PIN(8, 0, NO_ADC); +const mcu_pin_obj_t pin_PI01 = PIN(8, 1, NO_ADC); +const mcu_pin_obj_t pin_PI02 = PIN(8, 2, NO_ADC); +const mcu_pin_obj_t pin_PI03 = PIN(8, 3, NO_ADC); +const mcu_pin_obj_t pin_PI04 = PIN(8, 4, NO_ADC); +const mcu_pin_obj_t pin_PI05 = PIN(8, 5, NO_ADC); +const mcu_pin_obj_t pin_PI06 = PIN(8, 6, NO_ADC); +const mcu_pin_obj_t pin_PI07 = PIN(8, 7, NO_ADC); +const mcu_pin_obj_t pin_PI08 = PIN(8, 8, NO_ADC); +const mcu_pin_obj_t pin_PI09 = PIN(8, 9, NO_ADC); +const mcu_pin_obj_t pin_PI10 = PIN(8, 10, NO_ADC); +const mcu_pin_obj_t pin_PI11 = PIN(8, 11, NO_ADC); +const mcu_pin_obj_t pin_PI12 = PIN(8, 12, NO_ADC); +const mcu_pin_obj_t pin_PI13 = PIN(8, 13, NO_ADC); +const mcu_pin_obj_t pin_PI14 = PIN(8, 14, NO_ADC); +const mcu_pin_obj_t pin_PI15 = PIN(8, 15, NO_ADC); diff --git a/ports/stm/peripherals/stm32h7/stm32h750xx/pins.h b/ports/stm/peripherals/stm32h7/stm32h750xx/pins.h new file mode 100644 index 0000000000000..7cd2631f3deb1 --- /dev/null +++ b/ports/stm/peripherals/stm32h7/stm32h750xx/pins.h @@ -0,0 +1,152 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern const mcu_pin_obj_t pin_PA00; +extern const mcu_pin_obj_t pin_PA01; +extern const mcu_pin_obj_t pin_PA02; +extern const mcu_pin_obj_t pin_PA03; +extern const mcu_pin_obj_t pin_PA04; +extern const mcu_pin_obj_t pin_PA05; +extern const mcu_pin_obj_t pin_PA06; +extern const mcu_pin_obj_t pin_PA07; +extern const mcu_pin_obj_t pin_PA08; +extern const mcu_pin_obj_t pin_PA09; +extern const mcu_pin_obj_t pin_PA10; +extern const mcu_pin_obj_t pin_PA11; +extern const mcu_pin_obj_t pin_PA12; +extern const mcu_pin_obj_t pin_PA13; +extern const mcu_pin_obj_t pin_PA14; +extern const mcu_pin_obj_t pin_PA15; +extern const mcu_pin_obj_t pin_PB00; +extern const mcu_pin_obj_t pin_PB01; +extern const mcu_pin_obj_t pin_PB02; +extern const mcu_pin_obj_t pin_PB03; +extern const mcu_pin_obj_t pin_PB04; +extern const mcu_pin_obj_t pin_PB05; +extern const mcu_pin_obj_t pin_PB06; +extern const mcu_pin_obj_t pin_PB07; +extern const mcu_pin_obj_t pin_PB08; +extern const mcu_pin_obj_t pin_PB09; +extern const mcu_pin_obj_t pin_PB10; +extern const mcu_pin_obj_t pin_PB11; +extern const mcu_pin_obj_t pin_PB12; +extern const mcu_pin_obj_t pin_PB13; +extern const mcu_pin_obj_t pin_PB14; +extern const mcu_pin_obj_t pin_PB15; +extern const mcu_pin_obj_t pin_PC00; +extern const mcu_pin_obj_t pin_PC01; +extern const mcu_pin_obj_t pin_PC02; +extern const mcu_pin_obj_t pin_PC03; +extern const mcu_pin_obj_t pin_PC04; +extern const mcu_pin_obj_t pin_PC05; +extern const mcu_pin_obj_t pin_PC06; +extern const mcu_pin_obj_t pin_PC07; +extern const mcu_pin_obj_t pin_PC08; +extern const mcu_pin_obj_t pin_PC09; +extern const mcu_pin_obj_t pin_PC10; +extern const mcu_pin_obj_t pin_PC11; +extern const mcu_pin_obj_t pin_PC12; +extern const mcu_pin_obj_t pin_PC13; +extern const mcu_pin_obj_t pin_PC14; +extern const mcu_pin_obj_t pin_PC15; +extern const mcu_pin_obj_t pin_PD00; +extern const mcu_pin_obj_t pin_PD01; +extern const mcu_pin_obj_t pin_PD02; +extern const mcu_pin_obj_t pin_PD03; +extern const mcu_pin_obj_t pin_PD04; +extern const mcu_pin_obj_t pin_PD05; +extern const mcu_pin_obj_t pin_PD06; +extern const mcu_pin_obj_t pin_PD07; +extern const mcu_pin_obj_t pin_PD08; +extern const mcu_pin_obj_t pin_PD09; +extern const mcu_pin_obj_t pin_PD10; +extern const mcu_pin_obj_t pin_PD11; +extern const mcu_pin_obj_t pin_PD12; +extern const mcu_pin_obj_t pin_PD13; +extern const mcu_pin_obj_t pin_PD14; +extern const mcu_pin_obj_t pin_PD15; +extern const mcu_pin_obj_t pin_PE00; +extern const mcu_pin_obj_t pin_PE01; +extern const mcu_pin_obj_t pin_PE02; +extern const mcu_pin_obj_t pin_PE03; +extern const mcu_pin_obj_t pin_PE04; +extern const mcu_pin_obj_t pin_PE05; +extern const mcu_pin_obj_t pin_PE06; +extern const mcu_pin_obj_t pin_PE07; +extern const mcu_pin_obj_t pin_PE08; +extern const mcu_pin_obj_t pin_PE09; +extern const mcu_pin_obj_t pin_PE10; +extern const mcu_pin_obj_t pin_PE11; +extern const mcu_pin_obj_t pin_PE12; +extern const mcu_pin_obj_t pin_PE13; +extern const mcu_pin_obj_t pin_PE14; +extern const mcu_pin_obj_t pin_PE15; +extern const mcu_pin_obj_t pin_PF00; +extern const mcu_pin_obj_t pin_PF01; +extern const mcu_pin_obj_t pin_PF02; +extern const mcu_pin_obj_t pin_PF03; +extern const mcu_pin_obj_t pin_PF04; +extern const mcu_pin_obj_t pin_PF05; +extern const mcu_pin_obj_t pin_PF06; +extern const mcu_pin_obj_t pin_PF07; +extern const mcu_pin_obj_t pin_PF08; +extern const mcu_pin_obj_t pin_PF09; +extern const mcu_pin_obj_t pin_PF10; +extern const mcu_pin_obj_t pin_PF11; +extern const mcu_pin_obj_t pin_PF12; +extern const mcu_pin_obj_t pin_PF13; +extern const mcu_pin_obj_t pin_PF14; +extern const mcu_pin_obj_t pin_PF15; +extern const mcu_pin_obj_t pin_PG00; +extern const mcu_pin_obj_t pin_PG01; +extern const mcu_pin_obj_t pin_PG02; +extern const mcu_pin_obj_t pin_PG03; +extern const mcu_pin_obj_t pin_PG04; +extern const mcu_pin_obj_t pin_PG05; +extern const mcu_pin_obj_t pin_PG06; +extern const mcu_pin_obj_t pin_PG07; +extern const mcu_pin_obj_t pin_PG08; +extern const mcu_pin_obj_t pin_PG09; +extern const mcu_pin_obj_t pin_PG10; +extern const mcu_pin_obj_t pin_PG11; +extern const mcu_pin_obj_t pin_PG12; +extern const mcu_pin_obj_t pin_PG13; +extern const mcu_pin_obj_t pin_PG14; +extern const mcu_pin_obj_t pin_PG15; +extern const mcu_pin_obj_t pin_PH00; +extern const mcu_pin_obj_t pin_PH01; +extern const mcu_pin_obj_t pin_PH02; +extern const mcu_pin_obj_t pin_PH03; +extern const mcu_pin_obj_t pin_PH04; +extern const mcu_pin_obj_t pin_PH05; +extern const mcu_pin_obj_t pin_PH06; +extern const mcu_pin_obj_t pin_PH07; +extern const mcu_pin_obj_t pin_PH08; +extern const mcu_pin_obj_t pin_PH09; +extern const mcu_pin_obj_t pin_PH10; +extern const mcu_pin_obj_t pin_PH11; +extern const mcu_pin_obj_t pin_PH12; +extern const mcu_pin_obj_t pin_PH13; +extern const mcu_pin_obj_t pin_PH14; +extern const mcu_pin_obj_t pin_PH15; +extern const mcu_pin_obj_t pin_PI00; +extern const mcu_pin_obj_t pin_PI01; +extern const mcu_pin_obj_t pin_PI02; +extern const mcu_pin_obj_t pin_PI03; +extern const mcu_pin_obj_t pin_PI04; +extern const mcu_pin_obj_t pin_PI05; +extern const mcu_pin_obj_t pin_PI06; +extern const mcu_pin_obj_t pin_PI07; +extern const mcu_pin_obj_t pin_PI08; +extern const mcu_pin_obj_t pin_PI09; +extern const mcu_pin_obj_t pin_PI10; +extern const mcu_pin_obj_t pin_PI11; +extern const mcu_pin_obj_t pin_PI12; +extern const mcu_pin_obj_t pin_PI13; +extern const mcu_pin_obj_t pin_PI14; +extern const mcu_pin_obj_t pin_PI15; diff --git a/ports/stm/peripherals/stm32l4/clocks.c b/ports/stm/peripherals/stm32l4/clocks.c index a005c2bf7908f..4a7adc62de746 100644 --- a/ports/stm/peripherals/stm32l4/clocks.c +++ b/ports/stm/peripherals/stm32l4/clocks.c @@ -9,8 +9,10 @@ #include // L4 Series -#ifdef STM32L4R5xx +#if defined(STM32L4R5xx) #include "stm32l4/stm32l4r5xx/clocks.h" +#elif defined(STM32L433xx) +#include "stm32l4/stm32l433xx/clocks.h" #else #error Please add other MCUs here so that they are not silently ignored due to #define typos #endif @@ -44,49 +46,86 @@ void stm32_peripherals_clocks_init(void) { /** Configure the main internal regulator output voltage */ + #if defined(STM32L4R5xx) if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) != HAL_OK) { Error_Handler(); } - + #elif defined(STM32L433xx) + if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { + Error_Handler(); + } + #endif /* Activate PLL with MSI , stabilizied via PLL by LSE */ + #if defined(STM32L4R5xx) RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.LSEState = RCC_LSE_ON; - RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; RCC_OscInitStruct.PLL.PLLM = 6; RCC_OscInitStruct.PLL.PLLN = 30; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV5; RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + #elif defined(STM32L433xx) + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_HSI48 | RCC_OSCILLATORTYPE_MSI; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + RCC_OscInitStruct.MSIState = RCC_MSI_ON; + RCC_OscInitStruct.LSEState = RCC_LSE_ON; + RCC_OscInitStruct.MSICalibrationValue = 0; + RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; + RCC_OscInitStruct.PLL.PLLM = 1; + RCC_OscInitStruct.PLL.PLLN = 40; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + #else + #error Unknown MCU + #endif + HAL_CHECK(HAL_RCC_OscConfig(&RCC_OscInitStruct)); + #ifdef STM32L4R5xx /* Enable MSI Auto-calibration through LSE */ HAL_RCCEx_EnableMSIPLLMode(); + #endif /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - // Avoid overshoot and start with HCLK 60 MHz RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + #if defined(STM32L4R5xx) HAL_CHECK(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3)); + #elif defined(STM32L433xx) + HAL_CHECK(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4)); + #else + #error Please expand the conditional compilation to set the default flash latency + #endif /* AHB prescaler divider at 1 as second step */ + #ifdef STM32L4R5xx RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; HAL_CHECK(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5)); + #endif /* Select MSI output as USB clock source */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB | RCC_PERIPHCLK_RTC | RCC_PERIPHCLK_ADC; + #if defined(STM32L4R5xx) PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; + #elif defined(STM32L433xx) + PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + #endif PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_SYSCLK; - HAL_CHECK(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)); + HAL_CHECK(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)); } diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/clocks.h b/ports/stm/peripherals/stm32l4/stm32l433xx/clocks.h new file mode 100644 index 0000000000000..a01cae704d6b6 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/clocks.h @@ -0,0 +1,49 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "stm32l4xx_hal.h" + +// Chip: STM32L433 +// Line Type: Foundation Line +// Speed: 80MHz (MAX) + +// Defaults: +#ifndef CPY_CLK_VSCALE +#define CPY_CLK_VSCALE (PWR_REGULATOR_VOLTAGE_SCALE1) // up to 80MHz +#endif +#ifndef CPY_CLK_PLLM +#define CPY_CLK_PLLM (1) +#endif +#ifndef CPY_CLK_PLLN +#define CPY_CLK_PLLN (40) +#endif +#ifndef CPY_CLK_PLLP +#define CPY_CLK_PLLP (RCC_PLLP_DIV7) +#endif +#ifndef CPY_CLK_PLLQ +#define CPY_CLK_PLLQ (2) +#endif +#ifndef CPY_CLK_AHBDIV +#define CPY_CLK_AHBDIV (RCC_SYSCLK_DIV1) +#endif +#ifndef CPY_CLK_APB1DIV +#define CPY_CLK_APB1DIV (RCC_HCLK_DIV1) +#endif +#ifndef CPY_CLK_APB2DIV +#define CPY_CLK_APB2DIV (RCC_HCLK_DIV1) +#endif +#ifndef CPY_CLK_FLASH_LATENCY +#define CPY_CLK_FLASH_LATENCY (FLASH_LATENCY_4) +#endif +#ifndef CPY_CLK_USB_USES_AUDIOPLL +#define CPY_CLK_USB_USES_AUDIOPLL (0) +#endif + +#ifndef BOARD_HAS_HIGH_SPEED_CRYSTAL +#define BOARD_HAS_HIGH_SPEED_CRYSTAL (1) +#endif diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/gpio.c b/ports/stm/peripherals/stm32l4/stm32l433xx/gpio.c new file mode 100644 index 0000000000000..eb8914b5585c1 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/gpio.c @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#include "peripherals/gpio.h" +#include "common-hal/microcontroller/Pin.h" + +void stm32_peripherals_gpio_init(void) { + // Enable all GPIO for now + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_GPIOB_CLK_ENABLE(); + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOH_CLK_ENABLE(); + + // Never reset pins + never_reset_pin_number(2, 14); // PC14 OSC32_IN + never_reset_pin_number(2, 15); // PC15 OSC32_OUT + never_reset_pin_number(0, 13); // PA13 SWDIO + never_reset_pin_number(0, 14); // PA14 SWCLK +} + +void stm32l4_peripherals_status_led(uint8_t led, uint8_t state) { + +} diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/periph.c b/ports/stm/peripherals/stm32l4/stm32l433xx/periph.c new file mode 100644 index 0000000000000..e98c192c68517 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/periph.c @@ -0,0 +1,91 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" +#include "peripherals/periph.h" + +I2C_TypeDef *mcu_i2c_banks[I2C_BANK_ARRAY_LEN] = {I2C1, I2C2}; + +const mcu_periph_obj_t mcu_i2c_sda_list[I2C_SDA_ARRAY_LEN] = { + PERIPH(1, 4, &pin_PA10), + PERIPH(2, 4, &pin_PB14), +}; + +const mcu_periph_obj_t mcu_i2c_scl_list[I2C_SCL_ARRAY_LEN] = { + PERIPH(1, 4, &pin_PA09), + PERIPH(2, 4, &pin_PB13), +}; + +SPI_TypeDef *mcu_spi_banks[SPI_BANK_ARRAY_LEN] = {SPI1}; + +const mcu_periph_obj_t mcu_spi_sck_list[SPI_SCK_ARRAY_LEN] = { + PERIPH(1, 5, &pin_PB03), +}; +const mcu_periph_obj_t mcu_spi_mosi_list[SPI_MOSI_ARRAY_LEN] = { + PERIPH(1, 5, &pin_PA12), +}; +const mcu_periph_obj_t mcu_spi_miso_list[SPI_MISO_ARRAY_LEN] = { + PERIPH(1, 5, &pin_PA11), +}; +const mcu_periph_obj_t mcu_spi_nss_list[SPI_NSS_ARRAY_LEN] = { + PERIPH(1, 5, &pin_PA15), +}; + +USART_TypeDef *mcu_uart_banks[MAX_UART] = {USART1, USART2, USART3}; +bool mcu_uart_has_usart[MAX_UART] = {true, true, true, false, false}; + +const mcu_periph_obj_t mcu_uart_tx_list[UART_TX_ARRAY_LEN] = { + PERIPH(2, 7, &pin_PA02), + PERIPH(1, 7, &pin_PA09), + PERIPH(1, 7, &pin_PB06), + PERIPH(3, 7, &pin_PB10), +}; +const mcu_periph_obj_t mcu_uart_rx_list[UART_RX_ARRAY_LEN] = { + PERIPH(2, 7, &pin_PA03), + PERIPH(1, 7, &pin_PA10), + PERIPH(2, 7, &pin_PA15), + PERIPH(1, 7, &pin_PB07), + PERIPH(3, 7, &pin_PB11), +}; + +// Timers +TIM_TypeDef *mcu_tim_banks[TIM_BANK_ARRAY_LEN] = {TIM1, TIM2, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, TIM15, TIM16, NULL}; + +const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN] = { + TIM(2, 1, 1, &pin_PA00), + TIM(2, 1, 2, &pin_PA01), + TIM(2, 1, 3, &pin_PA02), + TIM(15, 15, 1, &pin_PA02), + TIM(2, 1, 4, &pin_PA03), + TIM(15, 15, 2, &pin_PA03), + TIM(2, 1, 1, &pin_PA05), + TIM(16, 15, 1, &pin_PA06), + TIM(1, 1, 1, &pin_PA08), + TIM(1, 1, 2, &pin_PA09), + TIM(1, 1, 3, &pin_PA10), + TIM(1, 1, 4, &pin_PA11), + TIM(2, 1, 1, &pin_PA15), + TIM(2, 1, 2, &pin_PB03), + TIM(16, 15, 1, &pin_PB08), + TIM(2, 1, 3, &pin_PB10), + TIM(2, 1, 4, &pin_PB11), + TIM(15, 15, 1, &pin_PB14), + TIM(15, 15, 2, &pin_PB15), +}; + +// CAN +CAN_TypeDef *mcu_can_banks[] = {CAN1}; + +const mcu_periph_obj_t mcu_can_tx_list[2] = { + PERIPH(1, 10, &pin_PA12), + PERIPH(1, 10, &pin_PB09), +}; +const mcu_periph_obj_t mcu_can_rx_list[2] = { + PERIPH(1, 10, &pin_PA11), + PERIPH(1, 10, &pin_PB08), +}; diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/periph.h b/ports/stm/peripherals/stm32l4/stm32l433xx/periph.h new file mode 100644 index 0000000000000..6bf0add01fef4 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/periph.h @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#pragma once + +// I2C +#define I2C_BANK_ARRAY_LEN 2 +#define I2C_SDA_ARRAY_LEN 2 +#define I2C_SCL_ARRAY_LEN 2 +extern I2C_TypeDef *mcu_i2c_banks[I2C_BANK_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_i2c_sda_list[I2C_SDA_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_i2c_scl_list[I2C_SCL_ARRAY_LEN]; + +// SPI +#define SPI_BANK_ARRAY_LEN 1 +#define SPI_SCK_ARRAY_LEN 1 +#define SPI_MOSI_ARRAY_LEN 1 +#define SPI_MISO_ARRAY_LEN 1 +#define SPI_NSS_ARRAY_LEN 1 +extern SPI_TypeDef *mcu_spi_banks[SPI_BANK_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_spi_sck_list[SPI_SCK_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_spi_mosi_list[SPI_MOSI_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_spi_miso_list[SPI_MISO_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_spi_nss_list[SPI_NSS_ARRAY_LEN]; + +// UART +#define UART_TX_ARRAY_LEN 4 +#define UART_RX_ARRAY_LEN 5 +extern USART_TypeDef *mcu_uart_banks[MAX_UART]; +extern bool mcu_uart_has_usart[MAX_UART]; +extern const mcu_periph_obj_t mcu_uart_tx_list[UART_TX_ARRAY_LEN]; +extern const mcu_periph_obj_t mcu_uart_rx_list[UART_RX_ARRAY_LEN]; + +// Timers +#define TIM_BANK_ARRAY_LEN 17 +#define TIM_PIN_ARRAY_LEN 19 +extern TIM_TypeDef *mcu_tim_banks[TIM_BANK_ARRAY_LEN]; +extern const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN]; + +// CAN +extern CAN_TypeDef *mcu_can_banks[1]; +extern const mcu_periph_obj_t mcu_can_tx_list[2]; +extern const mcu_periph_obj_t mcu_can_rx_list[2]; diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/pins.c b/ports/stm/peripherals/stm32l4/stm32l433xx/pins.c new file mode 100644 index 0000000000000..060f53031bb44 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/pins.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/mphal.h" +#include "peripherals/pins.h" + +#include STM32_HAL_H + +const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_1, 5)); +const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_1, 6)); +const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_1, 7)); +const mcu_pin_obj_t pin_PA03 = PIN(0, 3, ADC_INPUT(ADC_1, 8)); +const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_1, 9)); +const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_1, 10)); +const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_1, 11)); +const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_1, 12)); +const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC); +const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC); +const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC); +const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC); +const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC); +const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC); +const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC); +const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC); +const mcu_pin_obj_t pin_PB00 = PIN(1, 0, ADC_INPUT(ADC_1, 15)); +const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_1, 16)); +const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC); +const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC); +const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC); +const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC); +const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC); +const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC); +const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC); +const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC); +const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC); +const mcu_pin_obj_t pin_PB11 = PIN(1, 11, NO_ADC); +const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC); +const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC); +const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC); +const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC); +const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); +const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); +const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); +const mcu_pin_obj_t pin_PH00 = PIN(5, 0, NO_ADC); +const mcu_pin_obj_t pin_PH01 = PIN(5, 1, NO_ADC); +const mcu_pin_obj_t pin_PH03 = PIN(5, 3, NO_ADC); diff --git a/ports/stm/peripherals/stm32l4/stm32l433xx/pins.h b/ports/stm/peripherals/stm32l4/stm32l433xx/pins.h new file mode 100644 index 0000000000000..93a175ddbad81 --- /dev/null +++ b/ports/stm/peripherals/stm32l4/stm32l433xx/pins.h @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Blues Wireless Contributors +// +// SPDX-License-Identifier: MIT + +#pragma once + +extern const mcu_pin_obj_t pin_PA00; +extern const mcu_pin_obj_t pin_PA01; +extern const mcu_pin_obj_t pin_PA02; +extern const mcu_pin_obj_t pin_PA03; +extern const mcu_pin_obj_t pin_PA04; +extern const mcu_pin_obj_t pin_PA05; +extern const mcu_pin_obj_t pin_PA06; +extern const mcu_pin_obj_t pin_PA07; +extern const mcu_pin_obj_t pin_PA08; +extern const mcu_pin_obj_t pin_PA09; +extern const mcu_pin_obj_t pin_PA10; +extern const mcu_pin_obj_t pin_PA11; +extern const mcu_pin_obj_t pin_PA12; +extern const mcu_pin_obj_t pin_PA13; +extern const mcu_pin_obj_t pin_PA14; +extern const mcu_pin_obj_t pin_PA15; +extern const mcu_pin_obj_t pin_PB00; +extern const mcu_pin_obj_t pin_PB01; +extern const mcu_pin_obj_t pin_PB02; +extern const mcu_pin_obj_t pin_PB03; +extern const mcu_pin_obj_t pin_PB04; +extern const mcu_pin_obj_t pin_PB05; +extern const mcu_pin_obj_t pin_PB06; +extern const mcu_pin_obj_t pin_PB07; +extern const mcu_pin_obj_t pin_PB08; +extern const mcu_pin_obj_t pin_PB09; +extern const mcu_pin_obj_t pin_PB10; +extern const mcu_pin_obj_t pin_PB11; +extern const mcu_pin_obj_t pin_PB12; +extern const mcu_pin_obj_t pin_PB13; +extern const mcu_pin_obj_t pin_PB14; +extern const mcu_pin_obj_t pin_PB15; +extern const mcu_pin_obj_t pin_PC13; +extern const mcu_pin_obj_t pin_PC14; +extern const mcu_pin_obj_t pin_PC15; +extern const mcu_pin_obj_t pin_PH00; +extern const mcu_pin_obj_t pin_PH01; +extern const mcu_pin_obj_t pin_PH03; diff --git a/ports/stm/peripherals/stm32l4/stm32l4r5xx/gpio.c b/ports/stm/peripherals/stm32l4/stm32l4r5xx/gpio.c index 18fe8b760a267..a4adc58e42a0a 100644 --- a/ports/stm/peripherals/stm32l4/stm32l4r5xx/gpio.c +++ b/ports/stm/peripherals/stm32l4/stm32l4r5xx/gpio.c @@ -17,7 +17,7 @@ void stm32_peripherals_gpio_init(void) { __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); - // These ports are not used on the Swan R5 but may need to be enabeld on other boards + // These ports are not used on the Swan R5 but may need to be enabled on other boards // __HAL_RCC_GPIOH_CLK_ENABLE(); // __HAL_RCC_GPIOI_CLK_ENABLE(); diff --git a/ports/stm/peripherals/timers.c b/ports/stm/peripherals/timers.c index 9d963487a04d1..25cb9efcde03e 100644 --- a/ports/stm/peripherals/timers.c +++ b/ports/stm/peripherals/timers.c @@ -5,14 +5,16 @@ // SPDX-License-Identifier: MIT #include "timers.h" -#include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" +#include "ports/stm/peripherals/periph.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/microcontroller/Pin.h" +#ifdef STM32H7 +#include "stm32h7xx_hal_rcc.h" +#endif -#if !(CPY_STM32H7) #define ALL_CLOCKS 0xFFFF #define NULL_IRQ 0xFF @@ -161,17 +163,29 @@ uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef *timer) { // TIM{1,8,9,10,11} are on APB2 source = HAL_RCC_GetPCLK2Freq(); // 0b0xx means not divided; 0b100 is divide by 2; 0b101 by 4; 0b110 by 8; 0b111 by 16. + #ifdef STM32H7 + clk_div = (RCC->D2CFGR & RCC_D2CFGR_D2PPRE2) >> RCC_D2CFGR_D2PPRE2_Pos; + #else clk_div = (RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos; + #endif } else { // TIM{2,3,4,5,6,7,12,13,14} are on APB1 source = HAL_RCC_GetPCLK1Freq(); // 0b0xx means not divided; 0b100 is divide by 2; 0b101 by 4; 0b110 by 8; 0b111 by 16. + #ifdef STM32H7 + clk_div = (RCC->D1CFGR & RCC_D1CFGR_D1PPRE) >> RCC_D1CFGR_D1PPRE_Pos; + #else clk_div = (RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos; + #endif } // Only some STM32's have TIMPRE. #if defined(RCC_CFGR_TIMPRE) + #ifdef STM32H7 + uint32_t timpre = RCC->CFGR & RCC_CFGR_TIMPRE; + #else uint32_t timpre = RCC->DCKCFGR & RCC_CFGR_TIMPRE; + #endif if (timpre == 0) { if (clk_div >= 0b100) { source *= 2; @@ -287,7 +301,7 @@ size_t stm_peripherals_timer_get_index(TIM_TypeDef *instance) { return ~(size_t)0; } -void tim_clock_enable(uint16_t mask) { +void tim_clock_enable(uint32_t mask) { #ifdef TIM1 if (mask & (1 << 0)) { __HAL_RCC_TIM1_CLK_ENABLE(); @@ -349,9 +363,28 @@ void tim_clock_enable(uint16_t mask) { __HAL_RCC_TIM14_CLK_ENABLE(); } #endif + + #ifdef STM32H750xx + // only enabled on the H750 board for now + #ifdef TIM15 + if (mask & (1 << 14)) { + __HAL_RCC_TIM15_CLK_ENABLE(); + } + #endif + #ifdef TIM16 + if (mask & (1 << 15)) { + __HAL_RCC_TIM16_CLK_ENABLE(); + } + #endif + #ifdef TIM17 + if (mask & (1 << 16)) { + __HAL_RCC_TIM17_CLK_ENABLE(); + } + #endif + #endif } -void tim_clock_disable(uint16_t mask) { +void tim_clock_disable(uint32_t mask) { #ifdef TIM1 if (mask & (1 << 0)) { __HAL_RCC_TIM1_CLK_DISABLE(); @@ -413,6 +446,26 @@ void tim_clock_disable(uint16_t mask) { __HAL_RCC_TIM14_CLK_DISABLE(); } #endif + + #ifdef STM32H750xx + // only enabled on the H750 board for now + #ifdef TIM15 + if (mask & (1 << 14)) { + __HAL_RCC_TIM15_CLK_DISABLE(); + } + #endif + #ifdef TIM16 + if (mask & (1 << 15)) { + __HAL_RCC_TIM16_CLK_DISABLE(); + } + #endif + #ifdef TIM17 + if (mask & (1 << 16)) { + __HAL_RCC_TIM17_CLK_DISABLE(); + } + #endif + #endif + } static void callback_router(size_t index) { @@ -421,75 +474,108 @@ static void callback_router(size_t index) { } } +#ifdef TIM1 void TIM1_CC_IRQHandler(void) { // Advanced timer callback_router(1); } +#endif +#ifdef TIM2 void TIM2_IRQHandler(void) { callback_router(2); } +#endif +#ifdef TIM3 void TIM3_IRQHandler(void) { callback_router(3); } +#endif +#ifdef TIM4 void TIM4_IRQHandler(void) { callback_router(4); } +#endif +#ifdef TIM5 void TIM5_IRQHandler(void) { callback_router(5); } +#endif +#ifdef TIM6 void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC) callback_router(6); } +#endif +#ifdef TIM7 void TIM7_IRQHandler(void) { // Basic timer callback_router(7); } +#endif +#ifdef TIM8 void TIM8_CC_IRQHandler(void) { // Advanced timer callback_router(8); } +#endif // Advanced timer interrupts are currently unused. +#ifdef TIM9 void TIM1_BRK_TIM9_IRQHandler(void) { callback_router(9); } +#endif +#ifdef TIM10 void TIM1_UP_TIM10_IRQHandler(void) { callback_router(10); } +#endif +#ifdef TIM11 void TIM1_TRG_COM_TIM11_IRQHandler(void) { callback_router(11); } +#endif +#ifdef TIM12 void TIM8_BRK_TIM12_IRQHandler(void) { callback_router(12); } +#endif +#ifdef TIM13 void TIM8_UP_TIM13_IRQHandler(void) { callback_router(13); } +#endif +#ifdef TIM14 void TIM8_TRG_COM_TIM14_IRQHandler(void) { callback_router(14); } +#endif -#if (CPY_STM32H7) +#ifdef STM32H750xx +// only enabled on the H750 board for now +#ifdef TIM15 void TIM15_IRQHandler(void) { callback_router(15); } +#endif +#ifdef TIM16 void TIM16_IRQHandler(void) { callback_router(16); } +#endif +#ifdef TIM17 void TIM17_IRQHandler(void) { callback_router(17); } #endif - #endif diff --git a/ports/stm/peripherals/timers.h b/ports/stm/peripherals/timers.h index db3f9472e1e9c..00c198250cbd3 100644 --- a/ports/stm/peripherals/timers.h +++ b/ports/stm/peripherals/timers.h @@ -7,13 +7,12 @@ #pragma once #include -#include "py/mphal.h" -#include "peripherals/periph.h" +#include #include STM32_HAL_H -void tim_clock_enable(uint16_t mask); -void tim_clock_disable(uint16_t mask); +void tim_clock_enable(uint32_t mask); +void tim_clock_disable(uint32_t mask); uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef *timer); size_t stm_peripherals_timer_get_irqnum(TIM_TypeDef *instance); void timers_reset(void); diff --git a/ports/stm/supervisor/cpu.s b/ports/stm/supervisor/cpu.s deleted file mode 100755 index 9e6807a5e2e99..0000000000000 --- a/ports/stm/supervisor/cpu.s +++ /dev/null @@ -1,27 +0,0 @@ -.syntax unified -.cpu cortex-m4 -.thumb -.text -.align 2 - -@ uint cpu_get_regs_and_sp(r0=uint regs[10]) -.global cpu_get_regs_and_sp -.thumb -.thumb_func -.type cpu_get_regs_and_sp, %function -cpu_get_regs_and_sp: -@ store registers into given array -str r4, [r0], #4 -str r5, [r0], #4 -str r6, [r0], #4 -str r7, [r0], #4 -str r8, [r0], #4 -str r9, [r0], #4 -str r10, [r0], #4 -str r11, [r0], #4 -str r12, [r0], #4 -str r13, [r0], #4 - -@ return the sp -mov r0, sp -bx lr diff --git a/ports/stm/supervisor/internal_flash.c b/ports/stm/supervisor/internal_flash.c index 273af300a80b3..240dbba996085 100644 --- a/ports/stm/supervisor/internal_flash.c +++ b/ports/stm/supervisor/internal_flash.c @@ -64,23 +64,34 @@ static uint8_t _flash_cache[0x8000] __attribute__((aligned(4))); #endif #elif defined(STM32H7) +#if defined(STM32H750xx) +static const flash_layout_t flash_layout[] = { + { 0x08000000, 0x20000, 1 }, +}; +#else static const flash_layout_t flash_layout[] = { { 0x08000000, 0x20000, 16 }, }; +#endif static uint8_t _flash_cache[0x20000] __attribute__((aligned(4))); -#elif defined(STM32L4) +#elif defined(STM32L4R5xx) static const flash_layout_t flash_layout[] = { { 0x08100000, 0x1000, 256 }, }; static uint8_t _flash_cache[0x1000] __attribute__((aligned(4))); +#elif defined(STM32L433xx) +static const flash_layout_t flash_layout[] = { + { 0x08000000, 0x0800, 128 }, +}; +static uint8_t _flash_cache[0x0800] __attribute__((aligned(4))); + #else #error Unsupported processor #endif #define NO_CACHE 0xffffffff -#define MAX_CACHE 0x4000 static uint32_t _cache_flash_addr = NO_CACHE; @@ -88,6 +99,10 @@ static uint32_t _cache_flash_addr = NO_CACHE; #if defined(STM32H7) // get the bank of a given flash address static uint32_t get_bank(uint32_t addr) { + #if defined(STM32H750xx) // H750 only has 1 bank + return FLASH_BANK_1; + #else + if (READ_BIT(FLASH->OPTCR, FLASH_OPTCR_SWAP_BANK) == 0) { // no bank swap if (addr < (FLASH_BASE + FLASH_BANK_SIZE)) { @@ -103,6 +118,7 @@ static uint32_t get_bank(uint32_t addr) { return FLASH_BANK_1; } } + #endif } #endif @@ -175,8 +191,13 @@ void port_internal_flash_flush(void) { // set up for erase FLASH_EraseInitTypeDef EraseInitStruct = {}; #if CPY_STM32L4 + #if defined(STM32L4R5xx) + EraseInitStruct.TypeErase = TYPEERASE_PAGES; + EraseInitStruct.Banks = FLASH_BANK_2; // filesystem stored in upper 1MB of flash in dual bank mode + #elif defined(STM32L433xx) EraseInitStruct.TypeErase = TYPEERASE_PAGES; - EraseInitStruct.Banks = FLASH_BANK_2; // filesystem stored in upper 1MB of flash in dual bank mode + EraseInitStruct.Banks = FLASH_BANK_1; + #endif #else EraseInitStruct.TypeErase = TYPEERASE_SECTORS; EraseInitStruct.VoltageRange = VOLTAGE_RANGE_3; // voltage range needs to be 2.7V to 3.6V @@ -186,6 +207,9 @@ void port_internal_flash_flush(void) { uint32_t sector_start_addr = 0xffffffff; #if defined(STM32H7) EraseInitStruct.Banks = get_bank(_cache_flash_addr); + #if defined(STM32H750xx) + EraseInitStruct.NbSectors = 1; + #endif #endif #if CPY_STM32L4 EraseInitStruct.Page = flash_get_sector_info(_cache_flash_addr, §or_start_addr, §or_size); diff --git a/ports/stm/supervisor/internal_flash.h b/ports/stm/supervisor/internal_flash.h index 68704805f3399..473a495cd7c6e 100644 --- a/ports/stm/supervisor/internal_flash.h +++ b/ports/stm/supervisor/internal_flash.h @@ -81,12 +81,24 @@ #define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08020000 #endif +#ifdef STM32H750xx +#define STM32_FLASH_SIZE 0x20000 +#define INTERNAL_FLASH_FILESYSTEM_SIZE 0x10000 +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x8010000 +#endif + #ifdef STM32L4R5xx #define STM32_FLASH_SIZE 0x200000 // 2MB #define INTERNAL_FLASH_FILESYSTEM_SIZE 0x100000 // 1024KiB #define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08100000 #endif +#ifdef STM32L433xx +#define STM32_FLASH_SIZE 0x40000 // 256KiB +#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 // 48KiB +#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000 +#endif + #define INTERNAL_FLASH_FILESYSTEM_NUM_BLOCKS (INTERNAL_FLASH_FILESYSTEM_SIZE / FILESYSTEM_BLOCK_SIZE) #define STM32_FLASH_OFFSET 0x8000000 // All STM32 chips map to this flash location diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c index 5b903044b61cd..1ffc8656a888e 100644 --- a/ports/stm/supervisor/port.c +++ b/ports/stm/supervisor/port.c @@ -14,7 +14,6 @@ #include "shared-bindings/microcontroller/__init__.h" #if CIRCUITPY_BUSIO -#include "common-hal/busio/I2C.h" #include "common-hal/busio/SPI.h" #include "common-hal/busio/UART.h" #endif @@ -40,9 +39,18 @@ #include STM32_HAL_H -void NVIC_SystemReset(void) NORETURN; +void NVIC_SystemReset(void) MP_NORETURN; #if (CPY_STM32H7) || (CPY_STM32F7) +#if defined(CIRCUITPY_HW_SDRAM_SIZE) +#include "stm.h" +#include "sdram.h" +#include +#include +#include "lib/tlsf/tlsf.h" +// internal SRAM + external SDRAM +#define CIRCUITPY_RAM_DEVICE_COUNT (2) +#endif // Device memories must be accessed in order. #define DEVICE 2 @@ -135,8 +143,31 @@ __attribute__((used, naked)) void Reset_Handler(void) { for (uint32_t i = 0; i < ((size_t)&_ld_d1_ram_bss_size) / 4; i++) { (&_ld_d1_ram_bss_start)[i] = 0; } + #ifdef STM32H750xx + __DMB(); /* ARM says to use a DMB instruction before relocating VTOR */ + SCB->VTOR = 0x90000000u; /* We relocate vector table to the QSPI sector 1 */ + __DSB(); /* ARM says to use a DSB instruction just after relocating VTOR */ + /* + Since the STM32H750 microcontroller has only 128kB internal flash, + CircuitPython has to run from an external flash (QSPI or FMC). + This means a custom bootloader, like tinyUF2, is needed on the internal + flash to initialize the clocks, PLLs and (QSPI) controller, and to + start execution of the firmware from the external flash. + It also makes the SystemInit() call not necessary for this chip. + */ + #if defined(__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U) + /* Enable I cache. */ + SCB_EnableICache(); + #endif /* __ICACHE_PRESENT */ + + #if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U) + /* Enable D cache. */ + SCB_EnableDCache(); + #endif /* __DCACHE_PRESENT */ + #else SystemInit(); + #endif __enable_irq(); main(); } @@ -145,6 +176,62 @@ __attribute__((used, naked)) void Reset_Handler(void) { // Low power clock variables static volatile uint32_t systick_ms; +#if defined(CIRCUITPY_HW_SDRAM_SIZE) +static tlsf_t _heap = NULL; +static pool_t pools[CIRCUITPY_RAM_DEVICE_COUNT] = {NULL}; + + +void port_heap_init(void) { + // heap init in _port_heap_init called from port_init +} + +void stm_add_sdram_to_heap(void) { + size_t sdram_memory_size = sdram_size(); + pools[1] = tlsf_add_pool(_heap, sdram_start(), sdram_memory_size); +} + +static void _port_heap_init(void) { + uint32_t *heap_bottom = port_heap_get_bottom(); + uint32_t *heap_top = port_heap_get_top(); + size_t size = (heap_top - heap_bottom) * sizeof(uint32_t); + size_t sdram_memory_size = sdram_size(); + + _heap = tlsf_create_with_pool(heap_bottom, size, size + sdram_memory_size); + pools[0] = tlsf_get_pool(_heap); +} + +static bool max_size_walker(void *ptr, size_t size, int used, void *user) { + size_t *max_size = (size_t *)user; + if (!used && *max_size < size) { + *max_size = size; + } + return true; +} + +size_t port_heap_get_largest_free_size(void) { + size_t max_size = 0; + for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { + if (pools[i]) { + tlsf_walk_pool(pools[i], max_size_walker, &max_size); + } + } + return tlsf_fit_size(_heap, max_size); +} + +void *port_malloc(size_t size, bool dma_capable) { + void *block = tlsf_malloc(_heap, size); + return block; +} + +void port_free(void *ptr) { + tlsf_free(_heap, ptr); +} + +void *port_realloc(void *ptr, size_t size, bool dma_capable) { + return tlsf_realloc(_heap, ptr, size); +} +#endif + safe_mode_t port_init(void) { HAL_Init(); // Turns on SysTick __HAL_RCC_SYSCFG_CLK_ENABLE(); @@ -178,6 +265,9 @@ safe_mode_t port_init(void) { __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); stm32_peripherals_rtc_reset_alarms(); + #if defined(CIRCUITPY_HW_SDRAM_SIZE) + _port_heap_init(); + #endif // Turn off SysTick SysTick->CTRL = 0; @@ -195,7 +285,7 @@ void HAL_Delay(uint32_t delay_ms) { } } -uint32_t HAL_GetTick() { +uint32_t HAL_GetTick(void) { if (SysTick->CTRL != 0) { return systick_ms; } else { @@ -212,15 +302,11 @@ void SysTick_Handler(void) { } void reset_port(void) { - reset_all_pins(); - #if CIRCUITPY_RTC rtc_reset(); #endif #if CIRCUITPY_BUSIO - i2c_reset(); - spi_reset(); uart_reset(); #endif #if CIRCUITPY_SDIOIO @@ -286,8 +372,9 @@ uint32_t *port_heap_get_bottom(void) { return &_ld_heap_start; } +// heap memory can be set in SRAM and stack can be set in DTCM uint32_t *port_heap_get_top(void) { - return port_stack_get_limit(); + return &_ld_heap_end; } uint32_t *port_stack_get_limit(void) { diff --git a/ports/stm/supervisor/serial.c b/ports/stm/supervisor/serial.c index 2f3dd66b26609..380f5ceca5944 100644 --- a/ports/stm/supervisor/serial.c +++ b/ports/stm/supervisor/serial.c @@ -16,6 +16,10 @@ UART_HandleTypeDef huart2; #endif +void port_serial_early_init(void) { + +} + void port_serial_init(void) { #if CPY_STM32F4 huart2.Instance = USART2; diff --git a/ports/stm/supervisor/stm.h b/ports/stm/supervisor/stm.h new file mode 100644 index 0000000000000..6d3342137fb98 --- /dev/null +++ b/ports/stm/supervisor/stm.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 snkYmkrct +// +// SPDX-License-Identifier: MIT + +#pragma once + + +void stm_add_sdram_to_heap(void); diff --git a/ports/stm/supervisor/usb.c b/ports/stm/supervisor/usb.c index 61a7d54f08b74..7c782f61d0d9b 100644 --- a/ports/stm/supervisor/usb.c +++ b/ports/stm/supervisor/usb.c @@ -29,7 +29,7 @@ static void init_usb_vbus_sense(void) { // B-peripheral session valid override enable USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOEN; USB_OTG_FS->GOTGCTL |= USB_OTG_GOTGCTL_BVALOVAL; - #else + #elif !defined(STM32L433xx) && !defined(STM32L4R5xx) USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS; USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_VBUSBSEN; USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_VBUSASEN; @@ -56,7 +56,7 @@ void init_usb_hardware(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /**USB_OTG_FS GPIO Configuration - PA10 ------> USB_OTG_FS_ID + PA10 ------> USB_OTG_FS_ID (not present on STM32L433) PA11 ------> USB_OTG_FS_DM PA12 ------> USB_OTG_FS_DP */ @@ -69,10 +69,15 @@ void init_usb_hardware(void) { GPIO_InitStruct.Pull = GPIO_NOPULL; #if CPY_STM32H7 GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS; - #elif CPY_STM32F4 || CPY_STM32F7 || CPY_STM32L4 + #elif CPY_STM32F4 || CPY_STM32F7 || defined(STM32L4R5xx) GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; + #elif defined(STM32L433xx) + GPIO_InitStruct.Alternate = GPIO_AF10_USB_FS; + #else + #error Unknown MCU #endif HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); + never_reset_pin_number(0, 11); never_reset_pin_number(0, 12); claim_pin(0, 11); @@ -117,15 +122,21 @@ void init_usb_hardware(void) { #if CPY_STM32H7 HAL_PWREx_EnableUSBVoltageDetector(); __HAL_RCC_USB2_OTG_FS_CLK_ENABLE(); - #else + #elif CPY_STM32F4 || CPY_STM32F7 || defined(STM32L4R5xx) /* Peripheral clock enable */ __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); + #else + __HAL_RCC_USB_CLK_ENABLE(); #endif - init_usb_vbus_sense(); } -void OTG_FS_IRQHandler(void) { +#if defined(STM32L433xx) +void USB_IRQHandler(void) +#else +void OTG_FS_IRQHandler(void) +#endif +{ usb_irq_handler(0); } diff --git a/ports/stm/tools/parse_pins_csv.py b/ports/stm/tools/parse_pins_csv.py index 91903bd7e4657..a26517254cdfe 100644 --- a/ports/stm/tools/parse_pins_csv.py +++ b/ports/stm/tools/parse_pins_csv.py @@ -18,7 +18,7 @@ csv_reader = csv.reader(csv_file, delimiter=",") line_count = 0 - print("STATIC const mp_rom_map_elem_t board_module_globals_table[] = {") + print("static const mp_rom_map_elem_t board_module_globals_table[] = {") print(" { MP_ROM_QSTR(MP_QSTR_ID), MP_ROM_PTR(&board_module_id_obj) },") for row in csv_reader: diff --git a/ports/unix/Makefile b/ports/unix/Makefile index 526955b1ea5c9..32e3b44b2273a 100644 --- a/ports/unix/Makefile +++ b/ports/unix/Makefile @@ -4,8 +4,9 @@ ifdef VARIANT_DIR # the path as the variant name. VARIANT ?= $(notdir $(VARIANT_DIR:/=)) else -# If not given on the command line, then default to standard. -VARIANT ?= standard +# CIRCUITPY-CHANGE: default variant is coverage +# If not given on the command line, then default to coverage. +VARIANT ?= coverage VARIANT_DIR ?= variants/$(VARIANT) endif @@ -26,6 +27,9 @@ FROZEN_MANIFEST ?= variants/manifest.py # This should be configured by the mpconfigvariant.mk PROG ?= micropython +# For use in test rules below +ABS_PROG = $(abspath $(BUILD)/$(PROG)) + # qstr definitions (must come before including py.mk) QSTR_DEFS += qstrdefsport.h QSTR_GLOBAL_DEPENDENCIES += $(VARIANT_DIR)/mpconfigvariant.h @@ -45,9 +49,18 @@ INC += -I$(BUILD) # compiler settings CWARN = -Wall -Werror -CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion +// CIRCUITPY-CHANGE: add -Wno-missing-field-initializers +CWARN += -Wextra -Wno-unused-parameter -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -Wno-missing-field-initializers CFLAGS += $(INC) $(CWARN) -std=gnu99 -DUNIX $(COPT) -I$(VARIANT_DIR) $(CFLAGS_EXTRA) +# Force the use of 64-bits for file sizes in C library functions on 32-bit platforms. +# This option has no effect on 64-bit builds. +CFLAGS += -D_FILE_OFFSET_BITS=64 + +# Force the use of 64-bits for time_t in C library functions on 32-bit platforms. +# This option has no effect on 64-bit builds. +CFLAGS += -D_TIME_BITS=64 + # Debugging/Optimization ifdef DEBUG COPT ?= -Og @@ -134,7 +147,11 @@ ifeq ($(MICROPY_PY_SOCKET),1) CFLAGS += -DMICROPY_PY_SOCKET=1 endif ifeq ($(MICROPY_PY_THREAD),1) +ifeq ($(MICROPY_PY_THREAD_GIL),1) +CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=1 +else CFLAGS += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0 +endif LDFLAGS += $(LIBPTHREAD) endif @@ -168,7 +185,7 @@ ifeq ($(MICROPY_STANDALONE),1) # Build libffi from source. GIT_SUBMODULES += lib/libffi DEPLIBS += libffi -LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/out/lib/libffi-*/include) +LIBFFI_CFLAGS := -I$(shell ls -1d $(BUILD)/lib/libffi/include) ifeq ($(MICROPY_FORCE_32BIT),1) LIBFFI_LDFLAGS = $(BUILD)/lib/libffi/out/lib32/libffi.a else @@ -203,6 +220,8 @@ SRC_C += \ input.c \ alloc.c \ fatfs_port.c \ + shared-module/os/__init__.c \ + supervisor/shared/settings.c \ supervisor/stub/filesystem.c \ supervisor/stub/safe_mode.c \ supervisor/stub/stack.c \ @@ -218,6 +237,7 @@ $(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.gener SHARED_SRC_C += $(addprefix shared/,\ runtime/gchelper_generic.c \ + runtime/pyexec.c \ timeutils/timeutils.c \ $(SHARED_SRC_C_EXTRA) \ ) @@ -273,7 +293,7 @@ print-failures clean-failures: TEST_ARGS ?= test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) - cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py $(TEST_ARGS) + cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) ./run-tests.py test_full: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py $(eval DIRNAME=ports/$(notdir $(CURDIR))) diff --git a/ports/unix/README.md b/ports/unix/README.md index 21661dc877241..ee983a882cc83 100644 --- a/ports/unix/README.md +++ b/ports/unix/README.md @@ -1,17 +1,59 @@ -The Unix version -================ +MicroPython Unix port +===================== + +The "unix" port runs in standard Unix-like environments including Linux, BSD, +macOS, and Windows Subsystem for Linux. -The "unix" port requires a standard Unix-like environment with gcc and GNU -make. This includes Linux, BSD, macOS, and Windows Subsystem for Linux. The -x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well as -ARM and MIPS. Making a full-featured port to another architecture requires +The x86 and x64 architectures are supported (i.e. x86 32- and 64-bit), as well +as ARM and MIPS. Extending the unix port to another architecture requires writing some assembly code for the exception handling and garbage collection. Alternatively, a fallback implementation based on setjmp/longjmp can be used. -To build (see section below for required dependencies): +Building +-------- + +### Dependencies + +To build the unix port locally then you will need: + +* git command line executable, unless you downloaded a source .tar.xz file from + https://micropython.org/download/ +* gcc (or clang for macOS) toolchain +* GNU Make +* Python 3.x + +To build the default "standard" variant and configuration, then you will also +need: + +* `pkg-config` tool +* `libffi` library and headers + +On Debian/Ubuntu/Mint and related Linux distros, you can install all these +dependencies with a command like: + +``` +# apt install build-essential git python3 pkg-config libffi-dev +``` + +(See below for steps to build either a standalone or minimal MicroPython +executable that doesn't require system `libffi` or `pkg-config`.) + +### Default build steps + +To set up the environment for building (not needed every time), starting from +the top-level MicroPython directory: $ cd ports/unix + $ make -C ../../mpy-cross $ make submodules + +The `mpy-cross` step builds the [MicroPython +cross-compiler](https://github.com/micropython/micropython/?tab=readme-ov-file#the-micropython-cross-compiler-mpy-cross). +The `make submodules` step can be skipped if you didn't clone the MicroPython +source from git. + +Next, to build the actual executable (still in the `ports/unix` directory): + $ make Then to give it a try: @@ -30,6 +72,14 @@ To run the complete testsuite, use: $ make test +There are other make targets to interact with the testsuite: + + $ make test//int # Run all tests matching the pattern "int" + $ make test/ports/unix # Run all tests in ports/unix + $ make test-failures # Re-run only the failed tests + $ make print-failures # print the differences for failed tests + $ make clean-failures # delete the .exp and .out files from failed tests + The Unix port comes with a built-in package manager called `mip`, e.g.: $ ./build-standard/micropython -m mip install hmac @@ -45,44 +95,89 @@ Browse available modules at [Package management](https://docs.micropython.org/en/latest/reference/packages.html) for more information about `mip`. -External dependencies -===================== - -The `libffi` library and `pkg-config` tool are required. On Debian/Ubuntu/Mint -derivative Linux distros, install `build-essential`(includes toolchain and -make), `libffi-dev`, and `pkg-config` packages. +### Minimal Variant -Other dependencies can be built together with MicroPython. This may -be required to enable extra features or capabilities, and in recent -versions of MicroPython, these may be enabled by default. To build -these additional dependencies, in the unix port directory first execute: +The "standard" variant of MicroPython is the default. It enables most features, +including external modules interfaced using `libffi`. To instead build the +"minimal" variant, which disables almost all optional features and modules: + $ cd ports/unix $ make submodules + $ make VARIANT=minimal + +The executable will be built at `build-minimal/micropython`. + +Additional variants can be found in the `variants` sub-directory of the port, +although these are mostly of interest to MicroPython maintainers. + +### Standalone build + +By default, the "standard" variant uses `pkg-config` to link to the system's +shared `libffi` library. + +It is possible to instead build a standalone MicroPython where `libffi` is built +from source and linked statically into the `micropython` executable. This is +mostly useful for embedded or cross-compiled applications. + +Building standalone requires `autoconf` and `libtool` to also be installed. + +To build standalone: -This will fetch all the relevant git submodules (sub repositories) that -the port needs. Use the same command to get the latest versions of -submodules as they are updated from time to time. After that execute: + $ export MICROPY_STANDALONE=1 + $ make submodules # fetches libffi submodule + $ make deplibs # build just the external libraries + $ make # build MicroPython itself - $ make deplibs +`make deplibs` causes all supported external libraries (currently only `libffi`) +to be built inside the build directory, so it needs to run again only after +`make clean`. -This will build all available dependencies (regardless whether they are used -or not). If you intend to build MicroPython with additional options -(like cross-compiling), the same set of options should be passed to `make -deplibs`. To actually enable/disable use of dependencies, edit the +If you intend to build MicroPython with additional options (like +cross-compiling), the same set of options should be passed to both `make +deplibs` and `make`. + +### Other dependencies + +To actually enable/disable use of dependencies, edit the `ports/unix/mpconfigport.mk` file, which has inline descriptions of the options. For example, to build the SSL module, `MICROPY_PY_SSL` should be set to 1. -Debug Symbols -------------- +### Debug Symbols By default, builds are stripped of symbols and debug information to save size. -To build a debuggable version of the Unix port, there are two options +To build a debuggable version of the Unix port, there are two options: 1. Run `make [other arguments] DEBUG=1`. Note setting `DEBUG` also reduces the - optimisation level, so it's not a good option for builds that also want the - best performance. + optimisation level and enables assertions, so it's not a good option for + builds that also want the best performance. 2. Run `make [other arguments] STRIP=`. Note that the value of `STRIP` is empty. This will skip the build step that strips symbols and debug information, but changes nothing else in the build configuration. + +### Optimisation Level + +The default compiler optimisation level is -Os, or -Og if `DEBUG=1` is set. + +Setting the variable `COPT` will explicitly set the optimisation level. For +example `make [other arguments] COPT=-O0 DEBUG=1` will build a binary with no +optimisations, assertions enabled, and debug symbols. + +### Sanitizers + +Sanitizers are extra runtime checks supported by gcc and clang. The CI process +supports building with the "undefined behavior" (UBSan) or "address" (ASan) +sanitizers. The script `tools/ci.sh` is the source of truth about how to build +and run in these modes. + +Several classes of checks are disabled via compiler flags: + +* In the undefined behavior sanitizer, checks based on the presence of the + `non_null` attribute are disabled because the code makes technically incorrect + calls like `memset(NULL, 0, 0)`. A future C standard is likely to permit such + calls. +* In the address sanitizer, `detect_stack_use_after_return` is disabled. This + check is intended to make sure locals in a "returned from" stack frame are not + used. However, this mode interferes with various assumptions that + MicroPython's stack checking, NLR, and GC rely on. diff --git a/ports/unix/alloc.c b/ports/unix/alloc.c index e9cf521583d99..9ab2ca04ebc97 100644 --- a/ports/unix/alloc.c +++ b/ports/unix/alloc.c @@ -31,9 +31,8 @@ #include #include "py/mpstate.h" -#include "py/gc.h" -#if MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) +#if MICROPY_EMIT_NATIVE #if defined(__OpenBSD__) || defined(__MACH__) #define MAP_ANONYMOUS MAP_ANON @@ -79,31 +78,6 @@ void mp_unix_free_exec(void *ptr, size_t size) { } } -void mp_unix_mark_exec(void) { - for (mmap_region_t *rg = MP_STATE_VM(mmap_region_head); rg != NULL; rg = rg->next) { - gc_collect_root(rg->ptr, rg->len / sizeof(mp_uint_t)); - } -} - -#if MICROPY_FORCE_PLAT_ALLOC_EXEC -// Provide implementation of libffi ffi_closure_* functions in terms -// of the functions above. On a normal Linux system, this save a lot -// of code size. -void *ffi_closure_alloc(size_t size, void **code); -void ffi_closure_free(void *ptr); - -void *ffi_closure_alloc(size_t size, void **code) { - size_t dummy; - mp_unix_alloc_exec(size, code, &dummy); - return *code; -} - -void ffi_closure_free(void *ptr) { - (void)ptr; - // TODO -} -#endif - MP_REGISTER_ROOT_POINTER(void *mmap_region_head); -#endif // MICROPY_EMIT_NATIVE || (MICROPY_PY_FFI && MICROPY_FORCE_PLAT_ALLOC_EXEC) +#endif // MICROPY_EMIT_NATIVE diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 2670db3402dd7..49426f0f3e865 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -4,8 +4,10 @@ #include "py/obj.h" #include "py/objfun.h" +#include "py/objint.h" #include "py/objstr.h" #include "py/runtime.h" +#include "py/stackctrl.h" #include "py/gc.h" #include "py/repl.h" #include "py/mpz.h" @@ -31,7 +33,7 @@ typedef struct _mp_obj_streamtest_t { int error_code; } mp_obj_streamtest_t; -STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { +static mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); @@ -41,16 +43,16 @@ STATIC mp_obj_t stest_set_buf(mp_obj_t o_in, mp_obj_t buf_in) { o->pos = 0; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf); +static MP_DEFINE_CONST_FUN_OBJ_2(stest_set_buf_obj, stest_set_buf); -STATIC mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) { +static mp_obj_t stest_set_error(mp_obj_t o_in, mp_obj_t err_in) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); o->error_code = mp_obj_get_int(err_in); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error); +static MP_DEFINE_CONST_FUN_OBJ_2(stest_set_error_obj, stest_set_error); -STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); if (o->pos < o->len) { if (size > o->len - o->pos) { @@ -67,7 +69,7 @@ STATIC mp_uint_t stest_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errco } } -STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); (void)buf; (void)size; @@ -75,7 +77,7 @@ STATIC mp_uint_t stest_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int return MP_STREAM_ERROR; } -STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_streamtest_t *o = MP_OBJ_TO_PTR(o_in); (void)arg; (void)request; @@ -87,7 +89,7 @@ STATIC mp_uint_t stest_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, in return 0; } -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { +static const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_set_buf), MP_ROM_PTR(&stest_set_buf_obj) }, { MP_ROM_QSTR(MP_QSTR_set_error), MP_ROM_PTR(&stest_set_error_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, @@ -95,19 +97,20 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write1), MP_ROM_PTR(&mp_stream_write1_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto1), MP_ROM_PTR(&mp_stream_readinto1_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); +static MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); -STATIC const mp_stream_p_t fileio_stream_p = { +static const mp_stream_p_t fileio_stream_p = { .read = stest_read, .write = stest_write, .ioctl = stest_ioctl, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_stest_fileio, MP_QSTR_stest_fileio, MP_TYPE_FLAG_NONE, @@ -116,7 +119,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); // stream read returns non-blocking error -STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { (void)o_in; (void)buf; (void)size; @@ -124,19 +127,19 @@ STATIC mp_uint_t stest_read2(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc return MP_STREAM_ERROR; } -STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { +static const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); +static MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); -STATIC const mp_stream_p_t textio_stream_p2 = { +static const mp_stream_p_t textio_stream_p2 = { .read = stest_read2, .write = NULL, .is_text = true, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_stest_textio2, MP_QSTR_stest_textio2, MP_TYPE_FLAG_NONE, @@ -145,15 +148,15 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); // str/bytes objects without a valid hash -STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"}; -STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte *)"0123456789"}; +static const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte *)"0123456789"}; +static const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte *)"0123456789"}; -STATIC int pairheap_lt(mp_pairheap_t *a, mp_pairheap_t *b) { +static int pairheap_lt(mp_pairheap_t *a, mp_pairheap_t *b) { return (uintptr_t)a < (uintptr_t)b; } // ops array contain operations: x>=0 means push(x), x<0 means delete(-x) -STATIC void pairheap_test(size_t nops, int *ops) { +static void pairheap_test(size_t nops, int *ops) { mp_pairheap_t node[8]; for (size_t i = 0; i < MP_ARRAY_SIZE(node); ++i) { mp_pairheap_init_node(pairheap_lt, &node[i]); @@ -169,30 +172,57 @@ STATIC void pairheap_test(size_t nops, int *ops) { if (mp_pairheap_is_empty(pairheap_lt, heap)) { mp_printf(&mp_plat_print, " -"); } else { - mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]); + mp_printf(&mp_plat_print, " %d", (int)(mp_pairheap_peek(pairheap_lt, heap) - &node[0])); ; } } mp_printf(&mp_plat_print, "\npop all:"); while (!mp_pairheap_is_empty(pairheap_lt, heap)) { - mp_printf(&mp_plat_print, " %d", mp_pairheap_peek(pairheap_lt, heap) - &node[0]); + mp_printf(&mp_plat_print, " %d", (int)(mp_pairheap_peek(pairheap_lt, heap) - &node[0])); ; heap = mp_pairheap_pop(pairheap_lt, heap); } mp_printf(&mp_plat_print, "\n"); } +// CIRCUITPY-CHANGE: not turned on in CircuitPython +#if MICROPY_SCHEDULER_STATIC_NODES +static mp_sched_node_t mp_coverage_sched_node; +static bool coverage_sched_function_continue; + +static void coverage_sched_function(mp_sched_node_t *node) { + (void)node; + mp_printf(&mp_plat_print, "scheduled function\n"); + if (coverage_sched_function_continue) { + // Re-scheduling node will cause it to run again next time scheduled functions are run + mp_sched_schedule_node(&mp_coverage_sched_node, coverage_sched_function); + } +} +#endif + // function to run extra tests for things that can't be checked by scripts -STATIC mp_obj_t extra_coverage(void) { +static mp_obj_t extra_coverage(void) { // mp_printf (used by ports that don't have a native printf) { mp_printf(&mp_plat_print, "# mp_printf\n"); mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding - mp_printf(&mp_plat_print, "%ld\n", 123); // long - mp_printf(&mp_plat_print, "%lx\n", 0x123); // long hex - mp_printf(&mp_plat_print, "%X\n", 0x1abcdef); // capital hex - mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", MP_QSTR_True, MP_QSTR_True); // fixed string precision + mp_printf(&mp_plat_print, "%ld\n", 123l); // long + mp_printf(&mp_plat_print, "%lx\n", 0x123fl); // long hex + mp_printf(&mp_plat_print, "%lX\n", 0x123fl); // capital long hex + if (sizeof(mp_int_t) == 8) { + mp_printf(&mp_plat_print, "%llx\n", LLONG_MAX); // long long hex + mp_printf(&mp_plat_print, "%llX\n", LLONG_MAX); // capital long long hex + mp_printf(&mp_plat_print, "%llu\n", ULLONG_MAX); // unsigned long long + } else { + // fake for platforms without narrower mp_int_t + mp_printf(&mp_plat_print, "7fffffffffffffff\n"); + mp_printf(&mp_plat_print, "7FFFFFFFFFFFFFFF\n"); + mp_printf(&mp_plat_print, "18446744073709551615\n"); + } + mp_printf(&mp_plat_print, "%p\n", (void *)0x789f); // pointer + mp_printf(&mp_plat_print, "%P\n", (void *)0x789f); // pointer uppercase + mp_printf(&mp_plat_print, "%.2s %.3s '%4.4s' '%5.5q' '%.3q'\n", "abc", "abc", "abc", (qstr)MP_QSTR_True, (qstr)MP_QSTR_True); // fixed string precision mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools #ifndef NDEBUG @@ -202,10 +232,36 @@ STATIC mp_obj_t extra_coverage(void) { #endif mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "%X\n", 0x80000000); // should print unsigned - mp_printf(&mp_plat_print, "abc\n%"); // string ends in middle of format specifier + mp_printf(&mp_plat_print, "%x\n", 0x8000000f); // should print unsigned + mp_printf(&mp_plat_print, "%X\n", 0x8000000f); // should print unsigned + // note: storing the string in a variable is enough to prevent the + // format string checker from checking this format string. Otherwise, + // it would be a compile time diagnostic under the format string + // checker. + const char msg[] = "abc\n%"; + mp_printf(&mp_plat_print, msg); // string ends in middle of format specifier mp_printf(&mp_plat_print, "%%\n"); // literal % character + mp_printf(&mp_plat_print, ".%-3s.\n", "a"); // left adjust + + // Check that all kinds of mp_printf arguments are parsed out + // correctly, by having a char argument before and after each main type + // of value that can be formatted. + mp_printf(&mp_plat_print, "%c%%%c\n", '<', '>'); + mp_printf(&mp_plat_print, "%c%p%c\n", '<', (void *)0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%b%c\n", '<', true, '>'); + mp_printf(&mp_plat_print, "%c%d%c\n", '<', 0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%ld%c\n", '<', 0xaaaal, '>'); + mp_printf(&mp_plat_print, "%c" INT_FMT "%c\n", '<', (mp_int_t)0xaaaa, '>'); + mp_printf(&mp_plat_print, "%c%s%c\n", '<', "test", '>'); + mp_printf(&mp_plat_print, "%c%f%c\n", '<', MICROPY_FLOAT_CONST(1000.), '>'); + mp_printf(&mp_plat_print, "%c%q%c\n", '<', (qstr)MP_QSTR_True, '>'); + if (sizeof(mp_int_t) == 8) { + mp_printf(&mp_plat_print, "%c%lld%c\n", '<', LLONG_MAX, '>'); + } else { + mp_printf(&mp_plat_print, "<9223372036854775807>\n"); + } + + } // GC @@ -218,11 +274,11 @@ STATIC mp_obj_t extra_coverage(void) { gc_unlock(); // using gc_realloc to resize to 0, which means free the memory - void *p = gc_alloc(4, false); + void *p = gc_alloc(4, 0); mp_printf(&mp_plat_print, "%p\n", gc_realloc(p, 0, false)); // calling gc_nbytes with a non-heap pointer - mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL)); + mp_printf(&mp_plat_print, "%d\n", (int)gc_nbytes(NULL)); } // GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE @@ -283,7 +339,7 @@ STATIC mp_obj_t extra_coverage(void) { } ptrs[i][j] = j; } - mp_printf(&mp_plat_print, "%d %d\n", i, all_zero); + mp_printf(&mp_plat_print, "%d %d\n", (int)i, (int)all_zero); // hide the pointer from the GC and collect ptrs[i] = FLIP_POINTER(ptrs[i]); @@ -299,7 +355,7 @@ STATIC mp_obj_t extra_coverage(void) { break; } } - mp_printf(&mp_plat_print, "%d %d\n", i, correct_contents); + mp_printf(&mp_plat_print, "%d %d\n", (int)i, (int)correct_contents); } // free the memory blocks @@ -388,7 +444,7 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "# str\n"); // intern string - mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str("intern me", 9)))); + mp_printf(&mp_plat_print, "%d\n", mp_obj_is_qstr(mp_obj_str_intern(mp_obj_new_str_from_cstr("intern me")))); } // bytearray @@ -398,7 +454,7 @@ STATIC mp_obj_t extra_coverage(void) { // create a bytearray via mp_obj_new_bytearray mp_buffer_info_t bufinfo; mp_get_buffer_raise(mp_obj_new_bytearray(4, "data"), &bufinfo, MP_BUFFER_RW); - mp_printf(&mp_plat_print, "%.*s\n", bufinfo.len, bufinfo.buf); + mp_printf(&mp_plat_print, "%.*s\n", (int)bufinfo.len, bufinfo.buf); } // mpz @@ -455,6 +511,45 @@ STATIC mp_obj_t extra_coverage(void) { mpz_mul_inpl(&mpz, &mpz2, &mpz); mpz_as_uint_checked(&mpz, &value); mp_printf(&mp_plat_print, "%d\n", (int)value); + + // mpz_not_inpl with argument==0, testing ~0 + mpz_set_from_int(&mpz, 0); + mpz_not_inpl(&mpz, &mpz); + mp_int_t value_signed; + mpz_as_int_checked(&mpz, &value_signed); + mp_printf(&mp_plat_print, "%d\n", (int)value_signed); + + // hash the zero mpz integer + mpz_set_from_int(&mpz, 0); + mp_printf(&mp_plat_print, "%d\n", (int)mpz_hash(&mpz)); + + // convert the mpz zero integer to int + mp_printf(&mp_plat_print, "%d\n", mpz_as_int_checked(&mpz, &value_signed)); + mp_printf(&mp_plat_print, "%d\n", (int)value_signed); + + // mpz_set_from_float with 0 as argument + mpz_set_from_float(&mpz, 0); + mp_printf(&mp_plat_print, "%f\n", mpz_as_float(&mpz)); + + // convert a large integer value (stored in a mpz) to mp_uint_t and to ll; + mp_obj_t obj_bigint = mp_obj_new_int_from_uint((mp_uint_t)0xdeadbeef); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + obj_bigint = mp_obj_new_int_from_ll(0xc0ffee777c0ffeell); + long long value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); + + // convert a large integer value (stored via a struct object) to uint and to ll + // `deadbeef` global is an uctypes.struct defined by extra_coverage.py + obj_bigint = mp_load_global(MP_QSTR_deadbeef); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); + + // convert a smaller integer value to mp_uint_t and to ll + obj_bigint = mp_obj_new_int_from_uint(0xc0ffee); + mp_printf(&mp_plat_print, "%x\n", (int)mp_obj_get_uint(obj_bigint)); + value_ll = mp_obj_get_ll(obj_bigint); + mp_printf(&mp_plat_print, "%x%08x\n", (uint32_t)(value_ll >> 32), (uint32_t)value_ll); } // runtime utils @@ -464,12 +559,15 @@ STATIC mp_obj_t extra_coverage(void) { // call mp_call_function_1_protected mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), MP_OBJ_NEW_SMALL_INT(1)); // call mp_call_function_1_protected with invalid args - mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str("abc", 3)); + mp_call_function_1_protected(MP_OBJ_FROM_PTR(&mp_builtin_abs_obj), mp_obj_new_str_from_cstr("abc")); // call mp_call_function_2_protected mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), MP_OBJ_NEW_SMALL_INT(1), MP_OBJ_NEW_SMALL_INT(1)); // call mp_call_function_2_protected with invalid args - mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str("abc", 3), mp_obj_new_str("abc", 3)); + mp_call_function_2_protected(MP_OBJ_FROM_PTR(&mp_builtin_divmod_obj), mp_obj_new_str_from_cstr("abc"), mp_obj_new_str_from_cstr("abc")); + + // mp_obj_int_get_checked with mp_obj_int_t that has a value that is a small integer + mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_checked(MP_OBJ_FROM_PTR(mp_obj_int_new_mpz()))); // mp_obj_int_get_uint_checked with non-negative small-int mp_printf(&mp_plat_print, "%d\n", (int)mp_obj_int_get_uint_checked(MP_OBJ_NEW_SMALL_INT(1))); @@ -494,6 +592,22 @@ STATIC mp_obj_t extra_coverage(void) { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } + // mp_obj_get_uint from a non-int object (should raise exception) + if (nlr_push(&nlr) == 0) { + mp_obj_get_uint(mp_const_none); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + + // mp_obj_int_get_ll from a non-int object (should raise exception) + if (nlr_push(&nlr) == 0) { + mp_obj_get_ll(mp_const_none); + nlr_pop(); + } else { + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + } + // call mp_obj_new_exception_args (it's a part of the public C API and not used in the core) mp_obj_print_exception(&mp_plat_print, mp_obj_new_exception_args(&mp_type_ValueError, 0, NULL)); } @@ -503,26 +617,6 @@ STATIC mp_obj_t extra_coverage(void) { mp_emitter_warning(MP_PASS_CODE_SIZE, "test"); } - // format float - { - mp_printf(&mp_plat_print, "# format float\n"); - - // format with inadequate buffer size - char buf[5]; - mp_format_float(1, buf, sizeof(buf), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf); - - // format with just enough buffer so that precision must be - // set from 0 to 1 twice - char buf2[8]; - mp_format_float(1, buf2, sizeof(buf2), 'g', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - - // format where precision is trimmed to avoid buffer overflow - mp_format_float(1, buf2, sizeof(buf2), 'e', 0, '+'); - mp_printf(&mp_plat_print, "%s\n", buf2); - } - // binary { mp_printf(&mp_plat_print, "# binary\n"); @@ -546,14 +640,26 @@ STATIC mp_obj_t extra_coverage(void) { fun_bc.context = &context; fun_bc.child_table = NULL; fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state + #if MICROPY_PY_SYS_SETTRACE + struct _mp_raw_code_t rc = {}; + fun_bc.rc = &rc; + #endif mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, state, mp_obj_t, 1); code_state->fun_bc = &fun_bc; code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode code_state->sp = &code_state->state[0]; code_state->exc_sp_idx = 0; code_state->old_globals = NULL; + #if MICROPY_STACKLESS + code_state->prev = NULL; + #endif + #if MICROPY_PY_SYS_SETTRACE + code_state->prev_state = NULL; + code_state->frame = NULL; + #endif + mp_vm_return_kind_t ret = mp_execute_bytecode(code_state, MP_OBJ_NULL); - mp_printf(&mp_plat_print, "%d %d\n", ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); + mp_printf(&mp_plat_print, "%d %d\n", (int)ret, mp_obj_get_type(code_state->state[0]) == &mp_type_NotImplementedError); } // scheduler @@ -610,9 +716,25 @@ STATIC mp_obj_t extra_coverage(void) { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); } mp_handle_pending(true); + + // CIRCUITPY-CHANGE: not turned on in CircuitPython + #if MICROPY_SCHEDULER_STATIC_NODES + coverage_sched_function_continue = true; + mp_sched_schedule_node(&mp_coverage_sched_node, coverage_sched_function); + for (int i = 0; i < 3; ++i) { + mp_printf(&mp_plat_print, "loop\n"); + mp_handle_pending(true); + } + // Clear this flag to prevent the function scheduling itself again + coverage_sched_function_continue = false; + // Will only run the first time through this loop, then not scheduled again + for (int i = 0; i < 3; ++i) { + mp_handle_pending(true); + } + #endif } - // CIRCUITPY-CHANGE: ringbuf is different + // CIRCUITPY-CHANGE: ringbuf is quite different // ringbuf { #define RINGBUF_SIZE 99 @@ -624,36 +746,36 @@ STATIC mp_obj_t extra_coverage(void) { mp_printf(&mp_plat_print, "# ringbuf\n"); // Single-byte put/get with empty ringbuf. - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); ringbuf_put(&ringbuf, 22); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_get(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put/get with empty ringbuf. ringbuf_put16(&ringbuf, 0xaa55); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put with full ringbuf. for (int i = 0; i < RINGBUF_SIZE; ++i) { ringbuf_put(&ringbuf, i); } - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x11bb)); // Two-byte put with one byte free. ringbuf_get(&ringbuf); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0x3377)); ringbuf_get(&ringbuf); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); mp_printf(&mp_plat_print, "%d\n", ringbuf_put16(&ringbuf, 0xcc99)); for (int i = 0; i < RINGBUF_SIZE - 2; ++i) { ringbuf_get(&ringbuf); } mp_printf(&mp_plat_print, "%04x\n", ringbuf_get16(&ringbuf)); - mp_printf(&mp_plat_print, "%d %d\n", ringbuf_num_empty(&ringbuf), ringbuf_num_filled(&ringbuf)); + mp_printf(&mp_plat_print, "%d %d\n", (int)ringbuf_num_empty(&ringbuf), (int)ringbuf_num_filled(&ringbuf)); // Two-byte put with wrap around on first byte: ringbuf_clear(&ringbuf); @@ -723,12 +845,38 @@ STATIC mp_obj_t extra_coverage(void) { // mp_obj_is_integer accepts ints and booleans mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_integer(mp_obj_new_int_from_ll(1))); mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_const_true), mp_obj_is_integer(mp_const_false)); - mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str("1", 1)), mp_obj_is_integer(mp_const_none)); + mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_integer(mp_obj_new_str_from_cstr("1")), mp_obj_is_integer(mp_const_none)); // mp_obj_is_int accepts small int and object ints mp_printf(&mp_plat_print, "%d %d\n", mp_obj_is_int(MP_OBJ_NEW_SMALL_INT(1)), mp_obj_is_int(mp_obj_new_int_from_ll(1))); } + // Legacy stackctrl.h API, this has been replaced by cstack.h + { + mp_printf(&mp_plat_print, "# stackctrl\n"); + char *old_stack_top = MP_STATE_THREAD(stack_top); + size_t old_stack_limit = 0; + size_t new_stack_limit = SIZE_MAX; + #if MICROPY_STACK_CHECK + old_stack_limit = MP_STATE_THREAD(stack_limit); + MP_STACK_CHECK(); + #endif + + mp_stack_ctrl_init(); // Will set stack top incorrectly + mp_stack_set_top(old_stack_top); // ... and restore it + + #if MICROPY_STACK_CHECK + mp_stack_set_limit(MP_STATE_THREAD(stack_limit)); + MP_STACK_CHECK(); + new_stack_limit = MP_STATE_THREAD(stack_limit); + #endif + + // Nothing should have changed + mp_printf(&mp_plat_print, "%d %d\n", + old_stack_top == MP_STATE_THREAD(stack_top), + MICROPY_STACK_CHECK == 0 || old_stack_limit == new_stack_limit); + } + mp_printf(&mp_plat_print, "# end coverage.c\n"); mp_obj_streamtest_t *s = mp_obj_malloc(mp_obj_streamtest_t, &mp_type_stest_fileio); @@ -739,7 +887,7 @@ STATIC mp_obj_t extra_coverage(void) { mp_obj_streamtest_t *s2 = mp_obj_malloc(mp_obj_streamtest_t, &mp_type_stest_textio2); // return a tuple of data for testing on the Python side - mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj, MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; + mp_obj_t items[] = {MP_OBJ_FROM_PTR(&str_no_hash_obj), MP_OBJ_FROM_PTR(&bytes_no_hash_obj), MP_OBJ_FROM_PTR(s), MP_OBJ_FROM_PTR(s2)}; return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items); } MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage); diff --git a/ports/unix/coveragecpp.cpp b/ports/unix/coveragecpp.cpp index ea7418e1dd46a..8ba308f6468f3 100644 --- a/ports/unix/coveragecpp.cpp +++ b/ports/unix/coveragecpp.cpp @@ -1,11 +1,77 @@ extern "C" { -#include "py/obj.h" +// Include the complete public API to verify everything compiles as C++. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include } +// Invoke all (except one, see below) public API macros which initialize structs to make sure +// they are C++-compatible, meaning they explicitly initialize all struct members. +mp_obj_t f0(); +MP_DEFINE_CONST_FUN_OBJ_0(f0_obj, f0); +mp_obj_t f1(mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_1(f1_obj, f1); +mp_obj_t f2(mp_obj_t, mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_2(f2_obj, f2); +mp_obj_t f3(mp_obj_t, mp_obj_t, mp_obj_t); +MP_DEFINE_CONST_FUN_OBJ_3(f3_obj, f3); +mp_obj_t fvar(size_t, const mp_obj_t *); +MP_DEFINE_CONST_FUN_OBJ_VAR(fvar_obj, 1, fvar); +mp_obj_t fvarbetween(size_t, const mp_obj_t *); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fvarbetween_obj, 1, 2, fvarbetween); +mp_obj_t fkw(size_t, const mp_obj_t *, mp_map_t *); +MP_DEFINE_CONST_FUN_OBJ_KW(fkw_obj, 1, fkw); + +static const mp_rom_map_elem_t table[] = { + { MP_ROM_QSTR(MP_QSTR_f0), MP_ROM_PTR(&f0_obj) }, +}; +MP_DEFINE_CONST_MAP(map, table); +MP_DEFINE_CONST_DICT(dict, table); + +static const qstr attrtuple_fields[] = { + MP_QSTR_f0, +}; +MP_DEFINE_ATTRTUPLE(attrtuple, attrtuple_fields, 1, MP_ROM_PTR(&f0_obj)); + +void nlr_cb(void *); +void nlr_cb(void *){ +} + +// The MP_DEFINE_CONST_OBJ_TYPE macro is not C++-compatible because each of the +// MP_DEFINE_CONST_OBJ_TYPE_NARGS_X macros only initializes some of _mp_obj_type_t's +// .slot_index_xxx members but that cannot be fixed to be done in a deterministic way. + + #if defined(MICROPY_UNIX_COVERAGE) // Just to test building of C++ code. -STATIC mp_obj_t extra_cpp_coverage_impl() { +static mp_obj_t extra_cpp_coverage_impl() { + MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, nlr_cb, (void *) nlr_cb); + + // To avoid 'error: unused variable [-Werror,-Wunused-const-variable]'. + (void) ctx; + (void) f0_obj; + (void) f1_obj; + (void) f2_obj; + (void) f3_obj; + (void) fvar_obj; + (void) fvarbetween_obj; + (void) fkw_obj; + (void) map; + (void) dict; + (void) attrtuple; return mp_const_none; } diff --git a/ports/unix/displayio_min.c b/ports/unix/displayio_min.c index 3d0d5efc3ce66..06b57d04df230 100644 --- a/ports/unix/displayio_min.c +++ b/ports/unix/displayio_min.c @@ -74,3 +74,16 @@ const mp_obj_module_t displayio_module = { }; MP_REGISTER_MODULE(MP_QSTR_displayio, displayio_module); + +displayio_buffer_transform_t null_transform = { + .x = 0, + .y = 0, + .dx = 1, + .dy = 1, + .scale = 1, + .width = 0, + .height = 0, + .mirror_x = false, + .mirror_y = false, + .transpose_xy = false +}; diff --git a/ports/unix/gccollect.c b/ports/unix/gccollect.c index 94c9c61ea4d6a..8f0f5a6769d3d 100644 --- a/ports/unix/gccollect.c +++ b/ports/unix/gccollect.c @@ -39,9 +39,6 @@ void gc_collect(void) { #if MICROPY_PY_THREAD mp_thread_gc_others(); #endif - #if MICROPY_EMIT_NATIVE - mp_unix_mark_exec(); - #endif gc_collect_end(); } diff --git a/ports/unix/input.c b/ports/unix/input.c index c5bf7197388cc..260e9eac8c9db 100644 --- a/ports/unix/input.c +++ b/ports/unix/input.c @@ -43,6 +43,7 @@ char *prompt(char *p) { // simple read string static char buf[256]; fputs(p, stdout); + fflush(stdout); char *s = fgets(buf, sizeof(buf), stdin); if (!s) { return NULL; @@ -103,6 +104,9 @@ void prompt_write_history(void) { #if MICROPY_USE_READLINE == 1 char *home = getenv("HOME"); if (home != NULL) { + if (MP_STATE_THREAD(gc_lock_depth) != 0) { + return; + } vstr_t vstr; vstr_init(&vstr, 50); vstr_printf(&vstr, "%s/.micropython.history", home); diff --git a/ports/unix/main.c b/ports/unix/main.c index c7e85a3c63cb8..e42400fe5f9a3 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -44,7 +44,8 @@ #include "py/repl.h" #include "py/gc.h" #include "py/objstr.h" -#include "py/stackctrl.h" +#include "py/cstack.h" +#include "py/mperrno.h" #include "py/mphal.h" #include "py/mpthread.h" #include "extmod/misc.h" @@ -53,39 +54,12 @@ #include "extmod/vfs_posix.h" #include "genhdr/mpversion.h" #include "input.h" - -// CIRCUITPY-CHANGE -#if defined(MICROPY_UNIX_COVERAGE) -#include "py/objstr.h" -typedef int os_getenv_err_t; -mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); -os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); -os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); - -STATIC mp_obj_t mod_os_getenv_int(mp_obj_t var_in) { - mp_int_t value; - os_getenv_err_t result = common_hal_os_getenv_int(mp_obj_str_get_str(var_in), &value); - if (result == 0) { - return mp_obj_new_int(value); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_int_obj, mod_os_getenv_int); - -STATIC mp_obj_t mod_os_getenv_str(mp_obj_t var_in) { - char buf[4096]; - os_getenv_err_t result = common_hal_os_getenv_str(mp_obj_str_get_str(var_in), buf, sizeof(buf)); - if (result == 0) { - return mp_obj_new_str_copy(&mp_type_str, (byte *)buf, strlen(buf)); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(mod_os_getenv_str_obj, mod_os_getenv_str); -#endif +#include "stack_size.h" +#include "shared/runtime/pyexec.h" // Command line options, with their defaults -STATIC bool compile_only = false; -STATIC uint emit_opt = MP_EMIT_OPT_NONE; +bool mp_compile_only = false; +static uint emit_opt = MP_EMIT_OPT_NONE; #if MICROPY_ENABLE_GC // Heap size of GC heap (if enabled) @@ -106,7 +80,7 @@ long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4); #error "The unix port requires MICROPY_PY_SYS_ARGV=1" #endif -STATIC void stderr_print_strn(void *env, const char *str, size_t len) { +static void stderr_print_strn(void *env, const char *str, size_t len) { (void)env; ssize_t ret; MP_HAL_RETRY_SYSCALL(ret, write(STDERR_FILENO, str, len), {}); @@ -118,11 +92,12 @@ STATIC void stderr_print_strn(void *env, const char *str, size_t len) { const mp_print_t mp_stderr_print = {NULL, stderr_print_strn}; -#define FORCED_EXIT (0x100) +// CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT +// #define FORCED_EXIT (0x100) // If exc is SystemExit, return value where FORCED_EXIT bit set, // and lower 8 bits are SystemExit value. For all other exceptions, // return 1. -STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { +static int handle_uncaught_exception(mp_obj_base_t *exc) { // check for SystemExit if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // None is an exit value of 0; an int is its value; anything else is 1 @@ -131,7 +106,8 @@ STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { val = 1; } - return FORCED_EXIT | (val & 255); + // CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT + return PYEXEC_FORCED_EXIT | (val & 255); } // Report all other exceptions @@ -140,14 +116,12 @@ STATIC int handle_uncaught_exception(mp_obj_base_t *exc) { } #define LEX_SRC_STR (1) -#define LEX_SRC_VSTR (2) -#define LEX_SRC_FILENAME (3) #define LEX_SRC_STDIN (4) // Returns standard error codes: 0 for success, 1 for all other errors, // except if FORCED_EXIT bit is set then script raised SystemExit and the // value of the exit is in the lower 8 bits of the return value -STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { +static int execute_from_lexer(int source_kind, const void *source, mp_parse_input_kind_t input_kind, bool is_repl) { mp_hal_set_interrupt_char(CHAR_CTRL_C); nlr_buf_t nlr; @@ -157,19 +131,13 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu if (source_kind == LEX_SRC_STR) { const char *line = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, line, strlen(line), false); - } else if (source_kind == LEX_SRC_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, false); - } else if (source_kind == LEX_SRC_FILENAME) { - const char *filename = (const char *)source; - lex = mp_lexer_new_from_file(qstr_from_str(filename)); } else { // LEX_SRC_STDIN lex = mp_lexer_new_from_fd(MP_QSTR__lt_stdin_gt_, 0, false); } qstr source_name = lex->source_name; - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } @@ -188,7 +156,7 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu mp_obj_t module_fun = mp_compile(&parse_tree, source_name, is_repl); - if (!compile_only) { + if (!mp_compile_only) { // execute it mp_call_function_0(module_fun); } @@ -209,7 +177,7 @@ STATIC int execute_from_lexer(int source_kind, const void *source, mp_parse_inpu #if MICROPY_USE_READLINE == 1 #include "shared/readline/readline.h" #else -STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { +static char *strjoin(const char *s1, int sep_char, const char *s2) { int l1 = strlen(s1); int l2 = strlen(s2); char *s = malloc(l1 + l2 + 2); @@ -224,93 +192,33 @@ STATIC char *strjoin(const char *s1, int sep_char, const char *s2) { } #endif -STATIC int do_repl(void) { - mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION); - mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE); - mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); - +static int do_repl(void) { #if MICROPY_USE_READLINE == 1 - // use MicroPython supplied readline + // use MicroPython supplied readline-based REPL - vstr_t line; - vstr_init(&line, 16); + int ret = 0; for (;;) { - mp_hal_stdio_mode_raw(); - - input_restart: - vstr_reset(&line); - int ret = readline(&line, mp_repl_get_ps1()); - mp_parse_input_kind_t parse_input_kind = MP_PARSE_SINGLE_INPUT; - - if (ret == CHAR_CTRL_C) { - // cancel input - mp_hal_stdout_tx_str("\r\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // EOF - printf("\n"); - mp_hal_stdio_mode_orig(); - vstr_clear(&line); - return 0; - } else if (ret == CHAR_CTRL_E) { - // paste mode - mp_hal_stdout_tx_str("\npaste mode; Ctrl-C to cancel, Ctrl-D to finish\n=== "); - vstr_reset(&line); - for (;;) { - char c = mp_hal_stdin_rx_chr(); - if (c == CHAR_CTRL_C) { - // cancel everything - mp_hal_stdout_tx_str("\n"); - goto input_restart; - } else if (c == CHAR_CTRL_D) { - // end of input - mp_hal_stdout_tx_str("\n"); - break; - } else { - // add char to buffer and echo - vstr_add_byte(&line, c); - if (c == '\r') { - mp_hal_stdout_tx_str("\n=== "); - } else { - mp_hal_stdout_tx_strn(&c, 1); - } - } - } - parse_input_kind = MP_PARSE_FILE_INPUT; - } else if (line.len == 0) { - if (ret != 0) { - printf("\n"); + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if ((ret = pyexec_raw_repl()) != 0) { + break; } - goto input_restart; } else { - // got a line with non-zero length, see if it needs continuing - while (mp_repl_continue_with_input(vstr_null_terminated_str(&line))) { - vstr_add_byte(&line, '\n'); - ret = readline(&line, mp_repl_get_ps2()); - if (ret == CHAR_CTRL_C) { - // cancel everything - printf("\n"); - goto input_restart; - } else if (ret == CHAR_CTRL_D) { - // stop entering compound statement - break; - } + if ((ret = pyexec_friendly_repl()) != 0) { + break; } } - - mp_hal_stdio_mode_orig(); - - ret = execute_from_lexer(LEX_SRC_VSTR, &line, parse_input_kind, true); - if (ret & FORCED_EXIT) { - return ret; - } } + return ret; #else // use simple readline + mp_hal_stdout_tx_str(MICROPY_BANNER_NAME_AND_VERSION); + mp_hal_stdout_tx_str("; " MICROPY_BANNER_MACHINE); + mp_hal_stdout_tx_str("\nUse Ctrl-D to exit, Ctrl-E for paste mode\n"); + for (;;) { char *line = prompt((char *)mp_repl_get_ps1()); if (line == NULL) { @@ -330,7 +238,8 @@ STATIC int do_repl(void) { int ret = execute_from_lexer(LEX_SRC_STR, line, MP_PARSE_SINGLE_INPUT, true); free(line); - if (ret & FORCED_EXIT) { + // CIRCUITPY-CHANGE: be consistent about using PYEXEC_FORCED_EXIT + if (ret & PYEXEC_FORCED_EXIT) { return ret; } } @@ -338,18 +247,51 @@ STATIC int do_repl(void) { #endif } -STATIC int do_file(const char *file) { - return execute_from_lexer(LEX_SRC_FILENAME, file, MP_PARSE_FILE_INPUT, false); +static inline int convert_pyexec_result(int ret) { + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + // With exit code handling enabled: + // pyexec returns exit code with PYEXEC_FORCED_EXIT flag set for SystemExit + // Unix port expects: 0 for success, non-zero for error/exit + if (ret & PYEXEC_FORCED_EXIT) { + // SystemExit: extract exit code from lower bits + return ret & 0xFF; + } + // Normal execution or exception: return as-is (0 for success, 1 for exception) + return ret; + #else + // pyexec returns 1 for success, 0 for exception, PYEXEC_FORCED_EXIT for SystemExit + // Convert to unix port's expected codes: 0 for success, 1 for exception, FORCED_EXIT|val for SystemExit + if (ret == 1) { + return 0; // success + } else if (ret & PYEXEC_FORCED_EXIT) { + return ret; // SystemExit with exit value in lower 8 bits + } else { + return 1; // exception + } + #endif +} + +static int do_file(const char *file) { + // CIRCUITPY-CHANGE: pyexec_file result arg + pyexec_result_t pyexec_result; + return convert_pyexec_result(pyexec_file(file, &pyexec_result)); } -STATIC int do_str(const char *str) { - return execute_from_lexer(LEX_SRC_STR, str, MP_PARSE_FILE_INPUT, false); +static int do_str(const char *str) { + vstr_t vstr; + vstr.buf = (char *)str; + vstr.len = strlen(str); + // CIRCUITPY-CHANGE: pyexec_vstr result arg + pyexec_result_t pyexec_result; + int ret = pyexec_vstr(&vstr, true, &pyexec_result); + return convert_pyexec_result(ret); } -STATIC void print_help(char **argv) { +static void print_help(char **argv) { printf( "usage: %s [] [-X ] [-c | -m | ]\n" "Options:\n" + "--version : show version information\n" "-h : print this help message\n" "-i : enable inspection via REPL after running command/module/file\n" #if MICROPY_DEBUG_PRINTERS @@ -385,13 +327,13 @@ STATIC void print_help(char **argv) { } } -STATIC int invalid_args(void) { +static int invalid_args(void) { fprintf(stderr, "Invalid command line arguments. Use -h option for help.\n"); return 1; } // Process options which set interpreter init options -STATIC void pre_process_options(int argc, char **argv) { +static void pre_process_options(int argc, char **argv) { for (int a = 1; a < argc; a++) { if (argv[a][0] == '-') { if (strcmp(argv[a], "-c") == 0 || strcmp(argv[a], "-m") == 0) { @@ -401,13 +343,17 @@ STATIC void pre_process_options(int argc, char **argv) { print_help(argv); exit(0); } + if (strcmp(argv[a], "--version") == 0) { + printf(MICROPY_BANNER_NAME_AND_VERSION "; " MICROPY_BANNER_MACHINE "\n"); + exit(0); + } if (strcmp(argv[a], "-X") == 0) { if (a + 1 >= argc) { exit(invalid_args()); } if (0) { } else if (strcmp(argv[a + 1], "compile-only") == 0) { - compile_only = true; + mp_compile_only = true; } else if (strcmp(argv[a + 1], "emit=bytecode") == 0) { emit_opt = MP_EMIT_OPT_BYTECODE; #if MICROPY_EMIT_NATIVE @@ -471,7 +417,7 @@ STATIC void pre_process_options(int argc, char **argv) { } } -STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { +static void set_sys_argv(char *argv[], int argc, int start_arg) { for (int i = start_arg; i < argc; i++) { mp_obj_list_append(mp_sys_argv, MP_OBJ_NEW_QSTR(qstr_from_str(argv[i]))); } @@ -479,10 +425,13 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { #if MICROPY_PY_SYS_EXECUTABLE extern mp_obj_str_t mp_sys_executable_obj; -STATIC char executable_path[MICROPY_ALLOC_PATH_MAX]; +static char *executable_path = NULL; -STATIC void sys_set_excecutable(char *argv0) { - if (realpath(argv0, executable_path)) { +static void sys_set_excecutable(char *argv0) { + if (executable_path == NULL) { + executable_path = realpath(argv0, NULL); + } + if (executable_path != NULL) { mp_obj_str_set_data(&mp_sys_executable_obj, (byte *)executable_path, strlen(executable_path)); } } @@ -500,12 +449,16 @@ int main(int argc, char **argv) { #if MICROPY_PY_THREAD mp_thread_init(); #endif + + // Define a reasonable stack limit to detect stack overflow. + mp_uint_t stack_size = 40000 * UNIX_STACK_MULTIPLIER; + // We should capture stack top ASAP after start, and it should be // captured guaranteedly before any other stack variables are allocated. // For this, actual main (renamed main_) should not be inlined into // this function. main_() itself may have other functions inlined (with // their own stack variables), that's why we need this main/main_ split. - mp_stack_ctrl_init(); + mp_cstack_init_with_sp_here(stack_size); return main_(argc, argv); } @@ -524,14 +477,6 @@ MP_NOINLINE int main_(int argc, char **argv) { signal(SIGPIPE, SIG_IGN); #endif - // Define a reasonable stack limit to detect stack overflow. - mp_uint_t stack_limit = 40000 * (sizeof(void *) / 4); - #if defined(__arm__) && !defined(__thumb2__) - // ARM (non-Thumb) architectures require more stack. - stack_limit *= 2; - #endif - mp_stack_set_limit(stack_limit); - pre_process_options(argc, argv); #if MICROPY_ENABLE_GC @@ -575,7 +520,14 @@ MP_NOINLINE int main_(int argc, char **argv) { MP_OBJ_NEW_QSTR(MP_QSTR__slash_), }; mp_vfs_mount(2, args, (mp_map_t *)&mp_const_empty_map); + + // Make sure the root that was just mounted is the current VFS (it's always at + // the end of the linked list). Can't use chdir('/') because that will change + // the current path within the VfsPosix object. MP_STATE_VM(vfs_cur) = MP_STATE_VM(vfs_mount_table); + while (MP_STATE_VM(vfs_cur)->next != NULL) { + MP_STATE_VM(vfs_cur) = MP_STATE_VM(vfs_cur)->next; + } } #endif @@ -594,7 +546,12 @@ MP_NOINLINE int main_(int argc, char **argv) { // First entry is empty. We've already added an empty entry to sys.path, so skip it. ++path; } - bool path_remaining = *path; + // GCC targeting RISC-V 64 reports a warning about `path_remaining` being clobbered by + // either setjmp or vfork if that variable it is allocated on the stack. This may + // probably be a compiler error as it occurs on a few recent GCC releases (up to 14.1.0) + // but LLVM doesn't report any warnings. + static bool path_remaining; + path_remaining = *path; while (path_remaining) { char *path_entry_end = strchr(path, PATHLIST_SEP_CHAR); if (path_entry_end == NULL) { @@ -627,24 +584,9 @@ MP_NOINLINE int main_(int argc, char **argv) { // CIRCUITPY-CHANGE: test native base classes work as needed by CircuitPython libraries. extern const mp_obj_type_t native_base_class_type; mp_store_global(MP_QSTR_NativeBaseClass, MP_OBJ_FROM_PTR(&native_base_class_type)); - mp_store_global(MP_QSTR_getenv_int, MP_OBJ_FROM_PTR(&mod_os_getenv_int_obj)); - mp_store_global(MP_QSTR_getenv_str, MP_OBJ_FROM_PTR(&mod_os_getenv_str_obj)); } #endif - // Here is some example code to create a class and instance of that class. - // First is the Python, then the C code. - // - // class TestClass: - // pass - // test_obj = TestClass() - // test_obj.attr = 42 - // - // mp_obj_t test_class_type, test_class_instance; - // test_class_type = mp_obj_new_type(qstr_from_str("TestClass"), mp_const_empty_tuple, mp_obj_new_dict(0)); - // mp_store_name(qstr_from_str("test_obj"), test_class_instance = mp_call_function_0(test_class_type)); - // mp_store_attr(test_class_instance, qstr_from_str("attr"), mp_obj_new_int(42)); - /* printf("bytes:\n"); printf(" total %d\n", m_get_total_bytes_allocated()); @@ -676,7 +618,7 @@ MP_NOINLINE int main_(int argc, char **argv) { return invalid_args(); } mp_obj_t import_args[4]; - import_args[0] = mp_obj_new_str(argv[a + 1], strlen(argv[a + 1])); + import_args[0] = mp_obj_new_str_from_cstr(argv[a + 1]); import_args[1] = import_args[2] = mp_const_none; // Ask __import__ to handle imported module specially - set its __name__ // to __main__, and also return this leaf module, not top-level package @@ -698,12 +640,18 @@ MP_NOINLINE int main_(int argc, char **argv) { subpkg_tried = false; reimport: + mp_hal_set_interrupt_char(CHAR_CTRL_C); if (nlr_push(&nlr) == 0) { mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args); + mp_hal_set_interrupt_char(-1); + mp_handle_pending(true); nlr_pop(); } else { // uncaught exception - return handle_uncaught_exception(nlr.ret_val) & 0xff; + mp_hal_set_interrupt_char(-1); + mp_handle_pending(false); + ret = handle_uncaught_exception(nlr.ret_val) & 0xff; + break; } // If this module is a package, see if it has a `__main__.py`. @@ -740,11 +688,9 @@ MP_NOINLINE int main_(int argc, char **argv) { return invalid_args(); } } else { - char *pathbuf = malloc(PATH_MAX); - char *basedir = realpath(argv[a], pathbuf); + char *basedir = realpath(argv[a], NULL); if (basedir == NULL) { mp_printf(&mp_stderr_print, "%s: can't open file '%s': [Errno %d] %s\n", argv[0], argv[a], errno, strerror(errno)); - free(pathbuf); // CPython exits with 2 in such case ret = 2; break; @@ -753,7 +699,7 @@ MP_NOINLINE int main_(int argc, char **argv) { // Set base dir of the script as first entry in sys.path. char *p = strrchr(basedir, '/'); mp_obj_list_store(mp_sys_path, MP_OBJ_NEW_SMALL_INT(0), mp_obj_new_str_via_qstr(basedir, p - basedir)); - free(pathbuf); + free(basedir); set_sys_argv(argv, argc, a); ret = do_file(argv[a]); @@ -793,7 +739,7 @@ MP_NOINLINE int main_(int argc, char **argv) { #endif #if MICROPY_PY_BLUETOOTH - void mp_bluetooth_deinit(void); + int mp_bluetooth_deinit(void); mp_bluetooth_deinit(); #endif @@ -819,8 +765,20 @@ MP_NOINLINE int main_(int argc, char **argv) { #endif #endif + #if MICROPY_PY_SYS_EXECUTABLE && !defined(NDEBUG) + // Again, make memory leak detector happy + free(executable_path); + #endif + // printf("total bytes = %d\n", m_get_total_bytes_allocated()); - return ret & 0xff; + + // CIRCUITPY-CHANGE: handle PYEXEC_EXCEPTION + if (ret & PYEXEC_EXCEPTION) { + // Return exit status code 1 so the invoker knows there was an uncaught exception. + return 1; + } else { + return ret & 0xff; + } } void nlr_jump_fail(void *val) { @@ -830,3 +788,22 @@ void nlr_jump_fail(void *val) { fprintf(stderr, "FATAL: uncaught NLR %p\n", val); exit(1); } + +#if MICROPY_VFS_ROM_IOCTL + +static uint8_t romfs_buf[4] = { 0xd2, 0xcd, 0x31, 0x00 }; // empty ROMFS +static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, sizeof(romfs_buf), romfs_buf); + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + switch (mp_obj_get_int(args[0])) { + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&romfs_obj); + } + + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); +} + +#endif diff --git a/ports/unix/mbedtls/mbedtls_config.h b/ports/unix/mbedtls/mbedtls_config.h deleted file mode 100644 index 629064abcf297..0000000000000 --- a/ports/unix/mbedtls/mbedtls_config.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018-2019 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H -#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H - -// Set mbedtls configuration -#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_CRYPTOLIB_CTR - -// Enable mbedtls modules -#define MBEDTLS_HAVEGE_C -#define MBEDTLS_TIMING_C - -// Include common mbedtls configuration. -#include "extmod/mbedtls/mbedtls_config_common.h" - -#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/unix/mbedtls/mbedtls_config_port.h b/ports/unix/mbedtls/mbedtls_config_port.h new file mode 100644 index 0000000000000..aec65e6581e73 --- /dev/null +++ b/ports/unix/mbedtls/mbedtls_config_port.h @@ -0,0 +1,49 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018-2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_MBEDTLS_CONFIG_H +#define MICROPY_INCLUDED_MBEDTLS_CONFIG_H + +// Set mbedtls configuration +#define MBEDTLS_CIPHER_MODE_CTR // needed for MICROPY_PY_CRYPTOLIB_CTR + +// Enable mbedtls modules +#define MBEDTLS_TIMING_C + +#if defined(MICROPY_UNIX_COVERAGE) +// Test the "bare metal" memory management in the coverage build +#define MICROPY_MBEDTLS_CONFIG_BARE_METAL (1) +#endif + +// Include common mbedtls configuration. +#include "extmod/mbedtls/mbedtls_config_common.h" + +#if defined(MICROPY_UNIX_COVERAGE) +// See comment above, but fall back to the default platform entropy functions +#undef MBEDTLS_ENTROPY_HARDWARE_ALT +#undef MBEDTLS_NO_PLATFORM_ENTROPY +#endif + +#endif /* MICROPY_INCLUDED_MBEDTLS_CONFIG_H */ diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c index bc585f8647bc6..b469e932e0d5a 100644 --- a/ports/unix/modffi.c +++ b/ports/unix/modffi.c @@ -107,13 +107,13 @@ typedef struct _mp_obj_fficallback_t { ffi_type *params[]; } mp_obj_fficallback_t; -// STATIC const mp_obj_type_t opaque_type; -STATIC const mp_obj_type_t ffimod_type; -STATIC const mp_obj_type_t ffifunc_type; -STATIC const mp_obj_type_t fficallback_type; -STATIC const mp_obj_type_t ffivar_type; +// static const mp_obj_type_t opaque_type; +static const mp_obj_type_t ffimod_type; +static const mp_obj_type_t ffifunc_type; +static const mp_obj_type_t fficallback_type; +static const mp_obj_type_t ffivar_type; -STATIC ffi_type *char2ffi_type(char c) { +static ffi_type *char2ffi_type(char c) { switch (c) { case 'b': return &ffi_type_schar; @@ -154,7 +154,7 @@ STATIC ffi_type *char2ffi_type(char c) { } } -STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { +static ffi_type *get_ffi_type(mp_obj_t o_in) { if (mp_obj_is_str(o_in)) { const char *s = mp_obj_str_get_str(o_in); ffi_type *t = char2ffi_type(*s); @@ -167,14 +167,14 @@ STATIC ffi_type *get_ffi_type(mp_obj_t o_in) { mp_raise_TypeError(MP_ERROR_TEXT("unknown type")); } -STATIC mp_obj_t return_ffi_value(ffi_union_t *val, char type) { +static mp_obj_t return_ffi_value(ffi_union_t *val, char type) { switch (type) { case 's': { const char *s = (const char *)(intptr_t)val->ffi; if (!s) { return mp_const_none; } - return mp_obj_new_str(s, strlen(s)); + return mp_obj_new_str_from_cstr(s); } case 'v': return mp_const_none; @@ -190,10 +190,13 @@ STATIC mp_obj_t return_ffi_value(ffi_union_t *val, char type) { case 'h': case 'i': case 'l': - return mp_obj_new_int((signed)val->ffi); + return mp_obj_new_int((ffi_sarg)val->ffi); + case 'I': + // On RV64, 32-bit values are stored as signed integers inside the + // holding register. + return mp_obj_new_int_from_uint(val->ffi & 0xFFFFFFFF); case 'B': case 'H': - case 'I': case 'L': return mp_obj_new_int_from_uint(val->ffi); case 'q': @@ -209,25 +212,25 @@ STATIC mp_obj_t return_ffi_value(ffi_union_t *val, char type) { // FFI module -STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->handle); } -STATIC mp_obj_t ffimod_close(mp_obj_t self_in) { +static mp_obj_t ffimod_close(mp_obj_t self_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); dlclose(self->handle); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ffimod_close_obj, ffimod_close); +static MP_DEFINE_CONST_FUN_OBJ_1(ffimod_close_obj, ffimod_close); -STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) { +static mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) { const char *rettype = mp_obj_str_get_str(rettype_in); const char *argtypes = mp_obj_str_get_str(argtypes_in); mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(argtypes_in)); - mp_obj_ffifunc_t *o = mp_obj_malloc_var(mp_obj_ffifunc_t, ffi_type *, nparams, &ffifunc_type); + mp_obj_ffifunc_t *o = mp_obj_malloc_var(mp_obj_ffifunc_t, params, ffi_type *, nparams, &ffifunc_type); o->func = func; o->rettype = *rettype; @@ -249,7 +252,7 @@ STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in) return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) { +static mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) { (void)n_args; // always 4 mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(args[0]); const char *symname = mp_obj_str_get_str(args[2]); @@ -262,13 +265,13 @@ STATIC mp_obj_t ffimod_func(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ffimod_func_obj, 4, 4, ffimod_func); -STATIC mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) { +static mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) { void *addr = (void *)MP_OBJ_TO_PTR(mp_obj_int_get_truncated(addr_in)); return make_func(rettype, addr, argtypes); } MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_func_obj, mod_ffi_func); -STATIC void call_py_func(ffi_cif *cif, void *ret, void **args, void *user_data) { +static void call_py_func(ffi_cif *cif, void *ret, void **args, void *user_data) { mp_obj_t pyargs[cif->nargs]; mp_obj_fficallback_t *o = user_data; mp_obj_t pyfunc = o->pyfunc; @@ -283,7 +286,7 @@ STATIC void call_py_func(ffi_cif *cif, void *ret, void **args, void *user_data) } } -STATIC void call_py_func_with_lock(ffi_cif *cif, void *ret, void **args, void *user_data) { +static void call_py_func_with_lock(ffi_cif *cif, void *ret, void **args, void *user_data) { mp_obj_t pyargs[cif->nargs]; mp_obj_fficallback_t *o = user_data; mp_obj_t pyfunc = o->pyfunc; @@ -316,7 +319,7 @@ STATIC void call_py_func_with_lock(ffi_cif *cif, void *ret, void **args, void *u #endif } -STATIC mp_obj_t mod_ffi_callback(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mod_ffi_callback(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // first 3 args are positional: retttype, func, paramtypes. mp_obj_t rettype_in = pos_args[0]; mp_obj_t func_in = pos_args[1]; @@ -334,7 +337,8 @@ STATIC mp_obj_t mod_ffi_callback(size_t n_args, const mp_obj_t *pos_args, mp_map const char *rettype = mp_obj_str_get_str(rettype_in); mp_int_t nparams = MP_OBJ_SMALL_INT_VALUE(mp_obj_len_maybe(paramtypes_in)); - mp_obj_fficallback_t *o = mp_obj_malloc_var(mp_obj_fficallback_t, ffi_type *, nparams, &fficallback_type); + mp_obj_fficallback_t *o = (mp_obj_fficallback_t *)m_tracked_calloc(offsetof(mp_obj_fficallback_t, params) + sizeof(ffi_type *) * nparams, sizeof(uint8_t)); + o->base.type = &fficallback_type; o->clo = ffi_closure_alloc(sizeof(ffi_closure), &o->func); @@ -364,7 +368,7 @@ STATIC mp_obj_t mod_ffi_callback(size_t n_args, const mp_obj_t *pos_args, mp_map } MP_DEFINE_CONST_FUN_OBJ_KW(mod_ffi_callback_obj, 3, mod_ffi_callback); -STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) { +static mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); const char *rettype = mp_obj_str_get_str(vartype_in); const char *symname = mp_obj_str_get_str(symname_in); @@ -381,7 +385,7 @@ STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symna } MP_DEFINE_CONST_FUN_OBJ_3(ffimod_var_obj, ffimod_var); -STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) { +static mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) { mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in); const char *symname = mp_obj_str_get_str(symname_in); @@ -393,7 +397,7 @@ STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) { } MP_DEFINE_CONST_FUN_OBJ_2(ffimod_addr_obj, ffimod_addr); -STATIC mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_args; (void)n_kw; @@ -411,16 +415,16 @@ STATIC mp_obj_t ffimod_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(o); } -STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = { +static const mp_rom_map_elem_t ffimod_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_func), MP_ROM_PTR(&ffimod_func_obj) }, { MP_ROM_QSTR(MP_QSTR_var), MP_ROM_PTR(&ffimod_var_obj) }, { MP_ROM_QSTR(MP_QSTR_addr), MP_ROM_PTR(&ffimod_addr_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&ffimod_close_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); +static MP_DEFINE_CONST_DICT(ffimod_locals_dict, ffimod_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( ffimod_type, MP_QSTR_ffimod, MP_TYPE_FLAG_NONE, @@ -431,13 +435,13 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // FFI function -STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->func); } -STATIC unsigned long long ffi_get_int_value(mp_obj_t o) { +static unsigned long long ffi_get_int_value(mp_obj_t o) { if (mp_obj_is_small_int(o)) { return MP_OBJ_SMALL_INT_VALUE(o); } else { @@ -447,7 +451,7 @@ STATIC unsigned long long ffi_get_int_value(mp_obj_t o) { } } -STATIC ffi_union_t ffi_int_obj_to_ffi_union(mp_obj_t o, const char argtype) { +static ffi_union_t ffi_int_obj_to_ffi_union(mp_obj_t o, const char argtype) { ffi_union_t ret; if ((argtype | 0x20) == 'q') { ret.Q = ffi_get_int_value(o); @@ -479,7 +483,7 @@ STATIC ffi_union_t ffi_int_obj_to_ffi_union(mp_obj_t o, const char argtype) { return ret; } -STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_kw; mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in); assert(n_kw == 0); @@ -530,7 +534,7 @@ STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_raise_TypeError(MP_ERROR_TEXT("don't know how to pass object to native function")); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( ffifunc_type, MP_QSTR_ffifunc, MP_TYPE_FLAG_NONE, @@ -540,24 +544,24 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // FFI callback for Python function -STATIC void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void fficallback_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_fficallback_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", self->func); } -STATIC mp_obj_t fficallback_cfun(mp_obj_t self_in) { +static mp_obj_t fficallback_cfun(mp_obj_t self_in) { mp_obj_fficallback_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int_from_ull((uintptr_t)self->func); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(fficallback_cfun_obj, fficallback_cfun); +static MP_DEFINE_CONST_FUN_OBJ_1(fficallback_cfun_obj, fficallback_cfun); -STATIC const mp_rom_map_elem_t fficallback_locals_dict_table[] = { +static const mp_rom_map_elem_t fficallback_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_cfun), MP_ROM_PTR(&fficallback_cfun_obj) } }; -STATIC MP_DEFINE_CONST_DICT(fficallback_locals_dict, fficallback_locals_dict_table); +static MP_DEFINE_CONST_DICT(fficallback_locals_dict, fficallback_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( fficallback_type, MP_QSTR_fficallback, MP_TYPE_FLAG_NONE, @@ -567,34 +571,34 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // FFI variable -STATIC void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void ffivar_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); // Variable value printed as cast to int mp_printf(print, "", self->var, *(int *)self->var); } -STATIC mp_obj_t ffivar_get(mp_obj_t self_in) { +static mp_obj_t ffivar_get(mp_obj_t self_in) { mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); return mp_binary_get_val_array(self->type, self->var, 0); } MP_DEFINE_CONST_FUN_OBJ_1(ffivar_get_obj, ffivar_get); -STATIC mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) { +static mp_obj_t ffivar_set(mp_obj_t self_in, mp_obj_t val_in) { mp_obj_ffivar_t *self = MP_OBJ_TO_PTR(self_in); mp_binary_set_val_array(self->type, self->var, 0, val_in); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(ffivar_set_obj, ffivar_set); -STATIC const mp_rom_map_elem_t ffivar_locals_dict_table[] = { +static const mp_rom_map_elem_t ffivar_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); +static MP_DEFINE_CONST_DICT(ffivar_locals_dict, ffivar_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( ffivar_type, MP_QSTR_ffivar, MP_TYPE_FLAG_NONE, @@ -605,7 +609,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( // Generic opaque storage object (unused) /* -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( opaque_type, MP_QSTR_opaqueval, MP_TYPE_FLAG_NONE, @@ -613,17 +617,17 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); */ -STATIC mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_ffi_open(size_t n_args, const mp_obj_t *args) { return ffimod_make_new(&ffimod_type, n_args, 0, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_ffi_open_obj, 1, 2, mod_ffi_open); -STATIC mp_obj_t mod_ffi_as_bytearray(mp_obj_t ptr, mp_obj_t size) { +static mp_obj_t mod_ffi_as_bytearray(mp_obj_t ptr, mp_obj_t size) { return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void *)(uintptr_t)mp_obj_int_get_truncated(ptr)); } MP_DEFINE_CONST_FUN_OBJ_2(mod_ffi_as_bytearray_obj, mod_ffi_as_bytearray); -STATIC const mp_rom_map_elem_t mp_module_ffi_globals_table[] = { +static const mp_rom_map_elem_t mp_module_ffi_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ffi) }, { MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_ffi_open_obj) }, { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&mod_ffi_callback_obj) }, @@ -631,7 +635,7 @@ STATIC const mp_rom_map_elem_t mp_module_ffi_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_as_bytearray), MP_ROM_PTR(&mod_ffi_as_bytearray_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_ffi_globals, mp_module_ffi_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_ffi_globals, mp_module_ffi_globals_table); const mp_obj_module_t mp_module_ffi = { .base = { &mp_type_module }, diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c index a1cfca81495f4..dbce61aec1135 100644 --- a/ports/unix/modjni.c +++ b/ports/unix/modjni.c @@ -59,13 +59,13 @@ static jmethodID List_size_mid; static jclass IndexException_class; -STATIC const mp_obj_type_t jobject_type; -STATIC const mp_obj_type_t jmethod_type; +static const mp_obj_type_t jobject_type; +static const mp_obj_type_t jmethod_type; -STATIC mp_obj_t new_jobject(jobject jo); -STATIC mp_obj_t new_jclass(jclass jc); -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args); -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); +static mp_obj_t new_jobject(jobject jo); +static mp_obj_t new_jclass(jclass jc); +static mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args); +static bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); typedef struct _mp_obj_jclass_t { mp_obj_base_t base; @@ -87,7 +87,7 @@ typedef struct _mp_obj_jmethod_t { // Utility functions -STATIC bool is_object_type(const char *jtypesig) { +static bool is_object_type(const char *jtypesig) { while (*jtypesig != ' ' && *jtypesig) { if (*jtypesig == '.') { return true; @@ -97,7 +97,7 @@ STATIC bool is_object_type(const char *jtypesig) { return false; } -STATIC void check_exception(void) { +static void check_exception(void) { jobject exc = JJ1(ExceptionOccurred); if (exc) { // JJ1(ExceptionDescribe); @@ -110,7 +110,7 @@ STATIC void check_exception(void) { } } -STATIC void print_jobject(const mp_print_t *print, jobject obj) { +static void print_jobject(const mp_print_t *print, jobject obj) { jobject str_o = JJ(CallObjectMethod, obj, Object_toString_mid); const char *str = JJ(GetStringUTFChars, str_o, NULL); mp_printf(print, str); @@ -119,7 +119,7 @@ STATIC void print_jobject(const mp_print_t *print, jobject obj) { // jclass -STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in); if (kind == PRINT_REPR) { mp_printf(print, "cls); @@ -130,7 +130,7 @@ STATIC void jclass_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin } } -STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { +static void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_jclass_t *self = MP_OBJ_TO_PTR(self_in); @@ -156,7 +156,7 @@ STATIC void jclass_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { } } -STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { if (n_kw != 0) { mp_raise_TypeError(MP_ERROR_TEXT("kwargs not supported")); } @@ -167,14 +167,14 @@ STATIC mp_obj_t jclass_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return call_method(self->cls, NULL, methods, true, n_args, args); } -STATIC const mp_rom_map_elem_t jclass_locals_dict_table[] = { +static const mp_rom_map_elem_t jclass_locals_dict_table[] = { // { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&ffivar_get_obj) }, // { MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&ffivar_set_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); +static MP_DEFINE_CONST_DICT(jclass_locals_dict, jclass_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( jclass_type, MP_QSTR_jclass, MP_TYPE_FLAG_NONE, @@ -184,7 +184,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &jclass_locals_dict ); -STATIC mp_obj_t new_jclass(jclass jc) { +static mp_obj_t new_jclass(jclass jc) { mp_obj_jclass_t *o = mp_obj_malloc(mp_obj_jclass_t, &jclass_type); o->cls = jc; return MP_OBJ_FROM_PTR(o); @@ -192,7 +192,7 @@ STATIC mp_obj_t new_jclass(jclass jc) { // jobject -STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); if (kind == PRINT_REPR) { mp_printf(print, "obj); @@ -203,7 +203,7 @@ STATIC void jobject_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki } } -STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { +static void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); @@ -233,7 +233,7 @@ STATIC void jobject_attr(mp_obj_t self_in, qstr attr_in, mp_obj_t *dest) { } } -STATIC void get_jclass_name(jobject obj, char *buf) { +static void get_jclass_name(jobject obj, char *buf) { jclass obj_class = JJ(GetObjectClass, obj); jstring name = JJ(CallObjectMethod, obj_class, Class_getName_mid); jint len = JJ(GetStringLength, name); @@ -241,7 +241,7 @@ STATIC void get_jclass_name(jobject obj, char *buf) { check_exception(); } -STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t idx = mp_obj_get_int(index); char class_name[64]; @@ -291,7 +291,7 @@ STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) return MP_OBJ_NULL; } -STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_jobject_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: @@ -309,19 +309,19 @@ STATIC mp_obj_t jobject_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // TODO: subscr_load_adaptor & subscr_getiter convenience functions // should be moved to common location for reuse. -STATIC mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { +static mp_obj_t subscr_load_adaptor(mp_obj_t self_in, mp_obj_t index_in) { return mp_obj_subscr(self_in, index_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(subscr_load_adaptor_obj, subscr_load_adaptor); // .getiter special method which returns iterator which works in terms // of object subscription. -STATIC mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t subscr_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_t dest[2] = {MP_OBJ_FROM_PTR(&subscr_load_adaptor_obj), self_in}; return mp_obj_new_getitem_iter(dest, iter_buf); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( jobject_type, MP_QSTR_jobject, MP_TYPE_FLAG_ITER_IS_GETITER, @@ -332,12 +332,12 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( iter, subscr_getiter ); -STATIC mp_obj_t new_jobject(jobject jo) { +static mp_obj_t new_jobject(jobject jo) { if (jo == NULL) { return mp_const_none; } else if (JJ(IsInstanceOf, jo, String_class)) { const char *s = JJ(GetStringUTFChars, jo, NULL); - mp_obj_t ret = mp_obj_new_str(s, strlen(s)); + mp_obj_t ret = mp_obj_new_str_from_cstr(s); JJ(ReleaseStringUTFChars, jo, s); return ret; } else if (JJ(IsInstanceOf, jo, Class_class)) { @@ -353,7 +353,7 @@ STATIC mp_obj_t new_jobject(jobject jo) { // jmethod -STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_jmethod_t *self = MP_OBJ_TO_PTR(self_in); // Variable value printed as cast to int @@ -368,14 +368,14 @@ STATIC void jmethod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki } \ arg_type += sizeof(java_type_name) - 1; -STATIC const char *strprev(const char *s, char c) { +static const char *strprev(const char *s, char c) { while (*s != c) { s--; } return s; } -STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { +static bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { const char *arg_type = *jtypesig; const mp_obj_type_t *type = mp_obj_get_type(arg); @@ -442,7 +442,7 @@ STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out) { // perspective, it's aggregate object which may require passing via stack // instead of registers. Work that around by passing jobject and typecasting // it. -STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { +static mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { if (arg == NULL || MATCH(jtypesig, "void")) { return mp_const_none; } else if (MATCH(jtypesig, "boolean")) { @@ -460,7 +460,7 @@ STATIC mp_obj_t jvalue2py(const char *jtypesig, jobject arg) { } #endif -STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args) { +static mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, size_t n_args, const mp_obj_t *args) { jvalue jargs[n_args]; // printf("methods=%p\n", methods); jsize num_methods = JJ(GetArrayLength, methods); @@ -550,7 +550,7 @@ STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool } -STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { if (n_kw != 0) { mp_raise_TypeError(MP_ERROR_TEXT("kwargs not supported")); } @@ -568,7 +568,7 @@ STATIC mp_obj_t jmethod_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return call_method(self->obj, name, methods, false, n_args, args); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( jmethod_type, MP_QSTR_jmethod, MP_TYPE_FLAG_NONE, @@ -582,7 +582,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( #define LIBJVM_SO "libjvm.so" #endif -STATIC void create_jvm(void) { +static void create_jvm(void) { JavaVMInitArgs args; JavaVMOption options; options.optionString = "-Djava.class.path=."; @@ -635,7 +635,7 @@ STATIC void create_jvm(void) { IndexException_class = JJ(FindClass, "java/lang/IndexOutOfBoundsException"); } -STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { +static mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { const char *cls_name = mp_obj_str_get_str(cls_name_in); if (!env) { create_jvm(); @@ -648,7 +648,7 @@ STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls); -STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { +static mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { if (!env) { create_jvm(); } @@ -696,19 +696,19 @@ STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array); -STATIC mp_obj_t mod_jni_env(void) { +static mp_obj_t mod_jni_env(void) { return mp_obj_new_int((mp_int_t)(uintptr_t)env); } MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env); -STATIC const mp_rom_map_elem_t mp_module_jni_globals_table[] = { +static const mp_rom_map_elem_t mp_module_jni_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_jni) }, { MP_ROM_QSTR(MP_QSTR_cls), MP_ROM_PTR(&mod_jni_cls_obj) }, { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mod_jni_array_obj) }, { MP_ROM_QSTR(MP_QSTR_env), MP_ROM_PTR(&mod_jni_env_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_jni_globals, mp_module_jni_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_jni_globals, mp_module_jni_globals_table); const mp_obj_module_t mp_module_jni = { .base = { &mp_type_module }, diff --git a/ports/unix/modmachine.c b/ports/unix/modmachine.c index 40d08d9111422..d1cdbe8619aba 100644 --- a/ports/unix/modmachine.c +++ b/ports/unix/modmachine.c @@ -36,9 +36,6 @@ #define MICROPY_PAGE_MASK (MICROPY_PAGE_SIZE - 1) #endif -// This variable is needed for machine.soft_reset(), but the variable is otherwise unused. -int pyexec_system_exit = 0; - uintptr_t mod_machine_mem_get_addr(mp_obj_t addr_o, uint align) { uintptr_t addr = mp_obj_get_int_truncated(addr_o); if ((addr & (align - 1)) != 0) { @@ -70,7 +67,7 @@ uintptr_t mod_machine_mem_get_addr(mp_obj_t addr_o, uint align) { return addr; } -STATIC void mp_machine_idle(void) { +static void mp_machine_idle(void) { #ifdef MICROPY_UNIX_MACHINE_IDLE MICROPY_UNIX_MACHINE_IDLE #else diff --git a/ports/unix/modos.c b/ports/unix/modos.c index 4a821a4b417ab..af8a1cc4da871 100644 --- a/ports/unix/modos.c +++ b/ports/unix/modos.c @@ -32,16 +32,15 @@ #include "py/runtime.h" #include "py/mphal.h" -// CIRCUITPY-CHANGE: enhanced getenv +// CIRCUITPY-CHANGE: use shared-module os getenv #if defined(MICROPY_UNIX_COVERAGE) #include "py/objstr.h" -typedef int os_getenv_err_t; +#include "shared-module/os/__init__.h" +#include "supervisor/shared/settings.h" mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); -os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); -os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); #endif -STATIC mp_obj_t mp_os_getenv(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_os_getenv(size_t n_args, const mp_obj_t *args) { mp_obj_t var_in = args[0]; #if defined(MICROPY_UNIX_COVERAGE) mp_obj_t result = common_hal_os_getenv(mp_obj_str_get_str(var_in), mp_const_none); @@ -56,34 +55,11 @@ STATIC mp_obj_t mp_os_getenv(size_t n_args, const mp_obj_t *args) { } return mp_const_none; } - return mp_obj_new_str(s, strlen(s)); + return mp_obj_new_str_from_cstr(s); } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_getenv_obj, 1, 2, mp_os_getenv); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_getenv_obj, 1, 2, mp_os_getenv); -// CIRCUITPY-CHANGE: getenv differences -#if defined(MICROPY_UNIX_COVERAGE) -STATIC mp_obj_t mp_os_getenv_int(mp_obj_t var_in) { - mp_int_t value; - os_getenv_err_t result = common_hal_os_getenv_int(mp_obj_str_get_str(var_in), &value); - if (result == 0) { - return mp_obj_new_int(value); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(mp_os_getenv_int_obj, mp_os_getenv_int); - -STATIC mp_obj_t mp_os_getenv_str(mp_obj_t var_in) { - char buf[4096]; - os_getenv_err_t result = common_hal_os_getenv_str(mp_obj_str_get_str(var_in), buf, sizeof(buf)); - if (result == 0) { - return mp_obj_new_str_copy(&mp_type_str, (byte *)buf, strlen(buf)); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(mp_os_getenv_str_obj, mp_os_getenv_str); -#endif - -STATIC mp_obj_t mp_os_putenv(mp_obj_t key_in, mp_obj_t value_in) { +static mp_obj_t mp_os_putenv(mp_obj_t key_in, mp_obj_t value_in) { const char *key = mp_obj_str_get_str(key_in); const char *value = mp_obj_str_get_str(value_in); int ret; @@ -99,9 +75,9 @@ STATIC mp_obj_t mp_os_putenv(mp_obj_t key_in, mp_obj_t value_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_os_putenv_obj, mp_os_putenv); +static MP_DEFINE_CONST_FUN_OBJ_2(mp_os_putenv_obj, mp_os_putenv); -STATIC mp_obj_t mp_os_unsetenv(mp_obj_t key_in) { +static mp_obj_t mp_os_unsetenv(mp_obj_t key_in) { const char *key = mp_obj_str_get_str(key_in); int ret; @@ -116,9 +92,9 @@ STATIC mp_obj_t mp_os_unsetenv(mp_obj_t key_in) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_unsetenv_obj, mp_os_unsetenv); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_os_unsetenv_obj, mp_os_unsetenv); -STATIC mp_obj_t mp_os_system(mp_obj_t cmd_in) { +static mp_obj_t mp_os_system(mp_obj_t cmd_in) { const char *cmd = mp_obj_str_get_str(cmd_in); MP_THREAD_GIL_EXIT(); @@ -129,18 +105,18 @@ STATIC mp_obj_t mp_os_system(mp_obj_t cmd_in) { return MP_OBJ_NEW_SMALL_INT(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_system_obj, mp_os_system); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_os_system_obj, mp_os_system); -STATIC mp_obj_t mp_os_urandom(mp_obj_t num) { +static mp_obj_t mp_os_urandom(mp_obj_t num) { mp_int_t n = mp_obj_get_int(num); vstr_t vstr; vstr_init_len(&vstr, n); mp_hal_get_random(n, vstr.buf); return mp_obj_new_bytes_from_vstr(&vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_os_urandom_obj, mp_os_urandom); -STATIC mp_obj_t mp_os_errno(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_os_errno(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(errno); } @@ -148,4 +124,4 @@ STATIC mp_obj_t mp_os_errno(size_t n_args, const mp_obj_t *args) { errno = mp_obj_get_int(args[0]); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_errno_obj, 0, 1, mp_os_errno); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_os_errno_obj, 0, 1, mp_os_errno); diff --git a/ports/unix/modtermios.c b/ports/unix/modtermios.c index 4f9751e274378..d7b94038aa138 100644 --- a/ports/unix/modtermios.c +++ b/ports/unix/modtermios.c @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#if MICROPY_PY_TERMIOS + #include #include #include @@ -33,9 +35,7 @@ #include "py/runtime.h" #include "py/mphal.h" -#if MICROPY_PY_TERMIOS - -STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { +static mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { struct termios term; int fd = mp_obj_get_int(fd_in); @@ -65,9 +65,9 @@ STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) { } return MP_OBJ_FROM_PTR(r); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr); -STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t attrs_in) { +static mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t attrs_in) { struct termios term; int fd = mp_obj_get_int(fd_in); int when = mp_obj_get_int(when_in); @@ -105,9 +105,9 @@ STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t RAISE_ERRNO(res, errno); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(mod_termios_tcsetattr_obj, mod_termios_tcsetattr); +static MP_DEFINE_CONST_FUN_OBJ_3(mod_termios_tcsetattr_obj, mod_termios_tcsetattr); -STATIC mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { +static mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { struct termios term; int fd = mp_obj_get_int(fd_in); int res = tcgetattr(fd, &term); @@ -123,9 +123,9 @@ STATIC mp_obj_t mod_termios_setraw(mp_obj_t fd_in) { RAISE_ERRNO(res, errno); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_setraw_obj, mod_termios_setraw); +static MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_setraw_obj, mod_termios_setraw); -STATIC const mp_rom_map_elem_t mp_module_termios_globals_table[] = { +static const mp_rom_map_elem_t mp_module_termios_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_termios) }, { MP_ROM_QSTR(MP_QSTR_tcgetattr), MP_ROM_PTR(&mod_termios_tcgetattr_obj) }, { MP_ROM_QSTR(MP_QSTR_tcsetattr), MP_ROM_PTR(&mod_termios_tcsetattr_obj) }, @@ -141,10 +141,31 @@ STATIC const mp_rom_map_elem_t mp_module_termios_globals_table[] = { #ifdef B115200 C(B115200), #endif + #ifdef B230400 + C(B230400), + #endif + #ifdef B460800 + C(B460800), + #endif + #ifdef B500000 + C(B500000), + #endif + #ifdef B576000 + C(B576000), + #endif + #ifdef B921600 + C(B921600), + #endif + #ifdef B1000000 + C(B1000000), + #endif + #ifdef B1152000 + C(B1152000) + #endif #undef C }; -STATIC MP_DEFINE_CONST_DICT(mp_module_termios_globals, mp_module_termios_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_termios_globals, mp_module_termios_globals_table); const mp_obj_module_t mp_module_termios = { .base = { &mp_type_module }, diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index b6fbae0d1c24b..4f0550dbea765 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -34,6 +34,7 @@ #include "py/mphal.h" #include "py/runtime.h" +#include "shared/timeutils/timeutils.h" #ifdef _WIN32 static inline int msec_sleep_tv(struct timeval *tv) { @@ -61,7 +62,7 @@ static inline int msec_sleep_tv(struct timeval *tv) { #error Unsupported clock() implementation #endif -STATIC mp_obj_t mp_time_time_get(void) { +static mp_obj_t mp_time_time_get(void) { #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE struct timeval tv; gettimeofday(&tv, NULL); @@ -73,7 +74,7 @@ STATIC mp_obj_t mp_time_time_get(void) { } // Note: this is deprecated since CPy3.3, but pystone still uses it. -STATIC mp_obj_t mod_time_clock(void) { +static mp_obj_t mod_time_clock(void) { #if MICROPY_PY_BUILTINS_FLOAT // float cannot represent full range of int32 precisely, so we pre-divide // int to reduce resolution, and then actually do float division hoping @@ -83,9 +84,9 @@ STATIC mp_obj_t mod_time_clock(void) { return mp_obj_new_int((mp_int_t)clock()); #endif } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_time_clock_obj, mod_time_clock); -STATIC mp_obj_t mp_time_sleep(mp_obj_t arg) { +static mp_obj_t mp_time_sleep(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT struct timeval tv; mp_float_t val = mp_obj_get_float(arg); @@ -125,17 +126,12 @@ STATIC mp_obj_t mp_time_sleep(mp_obj_t arg) { return mp_const_none; } -STATIC mp_obj_t mod_time_gm_local_time(size_t n_args, const mp_obj_t *args, struct tm *(*time_func)(const time_t *timep)) { +static mp_obj_t mod_time_gm_local_time(size_t n_args, const mp_obj_t *args, struct tm *(*time_func)(const time_t *timep)) { time_t t; if (n_args == 0) { t = time(NULL); } else { - #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE - mp_float_t val = mp_obj_get_float(args[0]); - t = (time_t)MICROPY_FLOAT_C_FUN(trunc)(val); - #else - t = mp_obj_get_int(args[0]); - #endif + t = (time_t)timeutils_obj_get_timestamp(args[0]); } struct tm *tm = time_func(&t); @@ -159,17 +155,17 @@ STATIC mp_obj_t mod_time_gm_local_time(size_t n_args, const mp_obj_t *args, stru return ret; } -STATIC mp_obj_t mod_time_gmtime(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_time_gmtime(size_t n_args, const mp_obj_t *args) { return mod_time_gm_local_time(n_args, args, gmtime); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_gmtime_obj, 0, 1, mod_time_gmtime); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_gmtime_obj, 0, 1, mod_time_gmtime); -STATIC mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_time_localtime(size_t n_args, const mp_obj_t *args) { return mod_time_gm_local_time(n_args, args, localtime); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_time_localtime_obj, 0, 1, mod_time_localtime); -STATIC mp_obj_t mod_time_mktime(mp_obj_t tuple) { +static mp_obj_t mod_time_mktime(mp_obj_t tuple) { size_t len; mp_obj_t *elem; mp_obj_get_array(tuple, &len, &elem); @@ -193,10 +189,10 @@ STATIC mp_obj_t mod_time_mktime(mp_obj_t tuple) { time.tm_isdst = -1; // auto-detect } time_t ret = mktime(&time); - if (ret == -1) { + if (ret == (time_t)-1) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("invalid mktime usage")); } - return mp_obj_new_int(ret); + return timeutils_obj_from_timestamp(ret); } MP_DEFINE_CONST_FUN_OBJ_1(mod_time_mktime_obj, mod_time_mktime); diff --git a/ports/unix/mpbthciport.c b/ports/unix/mpbthciport.c index 8813ce147c1ee..765146677e8c5 100644 --- a/ports/unix/mpbthciport.c +++ b/ports/unix/mpbthciport.c @@ -54,7 +54,7 @@ uint8_t mp_bluetooth_hci_cmd_buf[4 + 256]; -STATIC int uart_fd = -1; +static int uart_fd = -1; // Must be provided by the stack bindings (e.g. mpnimbleport.c or mpbtstackport.c). extern bool mp_bluetooth_hci_poll(void); @@ -68,9 +68,9 @@ extern bool mp_bluetooth_hci_poll(void); extern bool mp_bluetooth_hci_active(void); // Prevent double-enqueuing of the scheduled task. -STATIC volatile bool events_task_is_scheduled = false; +static volatile bool events_task_is_scheduled = false; -STATIC mp_obj_t run_events_scheduled_task(mp_obj_t none_in) { +static mp_obj_t run_events_scheduled_task(mp_obj_t none_in) { (void)none_in; MICROPY_PY_BLUETOOTH_ENTER events_task_is_scheduled = false; @@ -78,14 +78,14 @@ STATIC mp_obj_t run_events_scheduled_task(mp_obj_t none_in) { mp_bluetooth_hci_poll(); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task); +static MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task); #endif // MICROPY_PY_BLUETOOTH_USE_SYNC_EVENTS -STATIC const useconds_t UART_POLL_INTERVAL_US = 1000; -STATIC pthread_t hci_poll_thread_id; +static const useconds_t UART_POLL_INTERVAL_US = 1000; +static pthread_t hci_poll_thread_id; -STATIC void *hci_poll_thread(void *arg) { +static void *hci_poll_thread(void *arg) { (void)arg; DEBUG_printf("hci_poll_thread: starting\n"); @@ -118,7 +118,7 @@ STATIC void *hci_poll_thread(void *arg) { return NULL; } -STATIC int configure_uart(void) { +static int configure_uart(void) { struct termios toptions; // Get existing config. @@ -196,10 +196,7 @@ int mp_bluetooth_hci_uart_init(uint32_t port, uint32_t baudrate) { } // Create a thread to run the polling loop. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&hci_poll_thread_id, &attr, &hci_poll_thread, NULL); + pthread_create(&hci_poll_thread_id, NULL, &hci_poll_thread, NULL); return 0; } diff --git a/ports/unix/mpbtstackport_h4.c b/ports/unix/mpbtstackport_h4.c index dacfff9a498af..14d418c63f229 100644 --- a/ports/unix/mpbtstackport_h4.c +++ b/ports/unix/mpbtstackport_h4.c @@ -24,14 +24,16 @@ * THE SOFTWARE. */ +#include "py/mpconfig.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_H4 + #include #include "py/runtime.h" #include "py/mperrno.h" #include "py/mphal.h" -#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_H4 - #include "lib/btstack/src/hci_transport_h4.h" #include "lib/btstack/chipset/zephyr/btstack_chipset_zephyr.h" @@ -42,7 +44,7 @@ #define DEBUG_printf(...) // printf(__VA_ARGS__) -STATIC hci_transport_config_uart_t hci_transport_config_uart = { +static hci_transport_config_uart_t hci_transport_config_uart = { .type = HCI_TRANSPORT_CONFIG_UART, .baudrate_init = 1000000, .baudrate_main = 0, diff --git a/ports/unix/mpbtstackport_usb.c b/ports/unix/mpbtstackport_usb.c index b8c7b758d93e6..a924fc3ca912a 100644 --- a/ports/unix/mpbtstackport_usb.c +++ b/ports/unix/mpbtstackport_usb.c @@ -24,6 +24,10 @@ * THE SOFTWARE. */ +#include "py/mpconfig.h" + +#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_USB + #include #include @@ -31,8 +35,6 @@ #include "py/mperrno.h" #include "py/mphal.h" -#if MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_USB - #include "lib/btstack/src/btstack.h" #include "lib/btstack/src/hci_transport_usb.h" #include "lib/btstack/platform/embedded/btstack_run_loop_embedded.h" @@ -47,7 +49,7 @@ #error Unix btstack requires MICROPY_PY_THREAD #endif -STATIC const useconds_t USB_POLL_INTERVAL_US = 1000; +static const useconds_t USB_POLL_INTERVAL_US = 1000; void mp_bluetooth_btstack_port_init_usb(void) { // MICROPYBTUSB can be a ':'' or '-' separated port list. @@ -71,7 +73,7 @@ void mp_bluetooth_btstack_port_init_usb(void) { hci_init(hci_transport_usb_instance(), NULL); } -STATIC pthread_t bstack_thread_id; +static pthread_t bstack_thread_id; void mp_bluetooth_btstack_port_deinit(void) { hci_power_control(HCI_POWER_OFF); @@ -84,7 +86,7 @@ void mp_bluetooth_btstack_port_deinit(void) { // Provided by mpbstackport_common.c. extern bool mp_bluetooth_hci_poll(void); -STATIC void *btstack_thread(void *arg) { +static void *btstack_thread(void *arg) { (void)arg; hci_power_control(HCI_POWER_ON); @@ -108,10 +110,7 @@ STATIC void *btstack_thread(void *arg) { void mp_bluetooth_btstack_port_start(void) { // Create a thread to run the btstack loop. - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - pthread_create(&bstack_thread_id, &attr, &btstack_thread, NULL); + pthread_create(&bstack_thread_id, NULL, &btstack_thread, NULL); } #endif // MICROPY_PY_BLUETOOTH && MICROPY_BLUETOOTH_BTSTACK && MICROPY_BLUETOOTH_BTSTACK_USB diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h index 3e7ea77f71a1b..815be76b4e90c 100644 --- a/ports/unix/mpconfigport.h +++ b/ports/unix/mpconfigport.h @@ -32,6 +32,9 @@ // features to work on Unix-like systems, see mpconfigvariant.h (and // mpconfigvariant_common.h) for feature enabling. +// For time_t, needed by MICROPY_TIMESTAMP_IMPL_TIME_T. +#include + // For size_t and ssize_t #include @@ -41,6 +44,8 @@ // CIRCUITPY-CHANGE #define CIRCUITPY_MICROPYTHON_ADVANCED (1) #define MICROPY_PY_ASYNC_AWAIT (1) +#define MICROPY_PY_DOUBLE_TYPECODE (1) +#define MICROPY_PY_UCTYPES (0) #ifndef MICROPY_CONFIG_ROM_LEVEL #define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_CORE_FEATURES) @@ -77,21 +82,6 @@ #define MICROPY_EMIT_ARM (1) #endif -// Type definitions for the specific machine based on the word size. -#ifndef MICROPY_OBJ_REPR -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif -#else -// Assume that if we already defined the obj repr then we also defined types. -#endif - // Cannot include , as it may lead to symbol name clashes #if _FILE_OFFSET_BITS == 64 && !defined(__LP64__) typedef long long mp_off_t; @@ -111,8 +101,10 @@ typedef long mp_off_t; // Always enable GC. #define MICROPY_ENABLE_GC (1) +// CIRCUITPY-CHANGE +#define MICROPY_ENABLE_SELECTIVE_COLLECT (1) -#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__)) +#if !(defined(MICROPY_GCREGS_SETJMP) || defined(__x86_64__) || defined(__i386__) || defined(__thumb2__) || defined(__thumb__) || defined(__arm__) || (defined(__riscv) && (__riscv_xlen == 64))) // Fall back to setjmp() implementation for discovery of GC pointers in registers. #define MICROPY_GCREGS_SETJMP (1) #endif @@ -124,13 +116,17 @@ typedef long mp_off_t; #define MICROPY_HELPER_LEXER_UNIX (1) #define MICROPY_VFS_POSIX (1) #define MICROPY_READER_POSIX (1) +// CIRCUITPY-CHANGE: define no matter what #ifndef MICROPY_TRACKED_ALLOC -#define MICROPY_TRACKED_ALLOC (MICROPY_BLUETOOTH_BTSTACK) +#define MICROPY_TRACKED_ALLOC (MICROPY_PY_FFI || MICROPY_BLUETOOTH_BTSTACK) #endif // VFS stat functions should return time values relative to 1970/1/1 #define MICROPY_EPOCH_IS_1970 (1) +// port modtime functions use time_t +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_TIME_T) + // Assume that select() call, interrupted with a signal, and erroring // with EINTR, updates remaining timeout value. #define MICROPY_SELECT_REMAINING_TIME (1) @@ -141,6 +137,9 @@ typedef long mp_off_t; #define MICROPY_STACKLESS_STRICT (0) #endif +// Recursive mutex is needed when threading is enabled, regardless of GIL setting. +#define MICROPY_PY_THREAD_RECURSIVE_MUTEX (MICROPY_PY_THREAD) + // Implementation of the machine module. #define MICROPY_PY_MACHINE_INCLUDEFILE "ports/unix/modmachine.c" @@ -168,6 +167,12 @@ typedef long mp_off_t; // Enable sys.executable. #define MICROPY_PY_SYS_EXECUTABLE (1) +// Enable support for compile-only mode. +#define MICROPY_PYEXEC_COMPILE_ONLY (1) + +// Enable handling of sys.exit() exit codes. +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + #define MICROPY_PY_SOCKET_LISTEN_BACKLOG_DEFAULT (SOMAXCONN < 128 ? SOMAXCONN : 128) // Bare-metal ports don't have stderr. Printing debug to stderr may give tests @@ -179,14 +184,8 @@ extern const struct _mp_print_t mp_stderr_print; // For the native emitter configure how to mark a region as executable. void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size); void mp_unix_free_exec(void *ptr, size_t size); -void mp_unix_mark_exec(void); #define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size) #define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size) -#ifndef MICROPY_FORCE_PLAT_ALLOC_EXEC -// Use MP_PLAT_ALLOC_EXEC for any executable memory allocation, including for FFI -// (overriding libffi own implementation) -#define MICROPY_FORCE_PLAT_ALLOC_EXEC (1) -#endif // If enabled, configure how to seed random on init. #ifdef MICROPY_PY_RANDOM_SEED_INIT_FUNC @@ -232,12 +231,6 @@ static inline unsigned long mp_random_seed_init(void) { #include #endif -// In lieu of a WFI(), slow down polling from being a tight loop. -// -// Note that we don't delay for the full TIMEOUT_MS, as execution -// can't be woken from the delay. -#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) mp_hal_delay_us(500) - // Configure the implementation of machine.idle(). #include #define MICROPY_UNIX_MACHINE_IDLE sched_yield(); diff --git a/ports/unix/mpconfigport.mk b/ports/unix/mpconfigport.mk index d6b57ca88601a..c836663cd2339 100644 --- a/ports/unix/mpconfigport.mk +++ b/ports/unix/mpconfigport.mk @@ -14,6 +14,7 @@ MICROPY_PY_BTREE = 0 # _thread module using pthreads MICROPY_PY_THREAD = 1 +MICROPY_PY_THREAD_GIL = 0 # Subset of CPython termios module MICROPY_PY_TERMIOS = 1 @@ -41,7 +42,7 @@ MICROPY_PY_JNI = 0 # Avoid using system libraries, use copies bundled with MicroPython # as submodules (currently affects only libffi). -MICROPY_STANDALONE = 0 +MICROPY_STANDALONE ?= 0 # CIRCUITPY-CHANGE: not used MICROPY_ROM_TEXT_COMPRESSION = 0 diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h index 7f71217632a8e..d9cd05b3de82b 100644 --- a/ports/unix/mphalport.h +++ b/ports/unix/mphalport.h @@ -25,7 +25,6 @@ */ #include #include -// CIRCUITPY-CHANGE: extra include #include #ifndef CHAR_CTRL_C @@ -38,6 +37,20 @@ #define MICROPY_END_ATOMIC_SECTION(x) (void)x; mp_thread_unix_end_atomic_section() #endif +// In lieu of a WFI(), slow down polling from being a tight loop. +// +// Note that we don't delay for the full TIMEOUT_MS, as execution +// can't be woken from the delay. +#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) \ + do { \ + MP_THREAD_GIL_EXIT(); \ + mp_hal_delay_us(500); \ + MP_THREAD_GIL_ENTER(); \ + } while (0) + +// The port provides `mp_hal_stdio_mode_raw()` and `mp_hal_stdio_mode_orig()`. +#define MICROPY_HAL_HAS_STDIO_MODE_SWITCH (1) + // CIRCUITPY-CHANGE: mp_hal_set_interrupt_char(int) instead of char void mp_hal_set_interrupt_char(int c); bool mp_hal_is_interrupted(void); @@ -110,3 +123,6 @@ enum { void mp_hal_get_mac(int idx, uint8_t buf[6]); #endif + +// Global variable to control compile-only mode. +extern bool mp_compile_only; diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c index 2190bf4ad1ba3..a41b3ec9f4701 100644 --- a/ports/unix/mpthreadport.c +++ b/ports/unix/mpthreadport.c @@ -31,6 +31,7 @@ #include "py/runtime.h" #include "py/mpthread.h" #include "py/gc.h" +#include "stack_size.h" #if MICROPY_PY_THREAD @@ -45,8 +46,14 @@ // potential conflict with other uses of the more commonly used SIGUSR1. #ifdef SIGRTMIN #define MP_THREAD_GC_SIGNAL (SIGRTMIN + 5) +#ifdef __ANDROID__ +#define MP_THREAD_TERMINATE_SIGNAL (SIGRTMIN + 6) +#endif #else #define MP_THREAD_GC_SIGNAL (SIGUSR1) +#ifdef __ANDROID__ +#define MP_THREAD_TERMINATE_SIGNAL (SIGUSR2) +#endif #endif // This value seems to be about right for both 32-bit and 64-bit builds. @@ -60,33 +67,33 @@ typedef struct _mp_thread_t { struct _mp_thread_t *next; } mp_thread_t; -STATIC pthread_key_t tls_key; +static pthread_key_t tls_key; // The mutex is used for any code in this port that needs to be thread safe. // Specifically for thread management, access to the linked list is one example. // But also, e.g. scheduler state. -STATIC pthread_mutex_t thread_mutex; -STATIC mp_thread_t *thread; +static mp_thread_recursive_mutex_t thread_mutex; +static mp_thread_t *thread; // this is used to synchronise the signal handler of the thread // it's needed because we can't use any pthread calls in a signal handler #if defined(__APPLE__) -STATIC char thread_signal_done_name[25]; -STATIC sem_t *thread_signal_done_p; +static char thread_signal_done_name[25]; +static sem_t *thread_signal_done_p; #else -STATIC sem_t thread_signal_done; +static sem_t thread_signal_done; #endif void mp_thread_unix_begin_atomic_section(void) { - pthread_mutex_lock(&thread_mutex); + mp_thread_recursive_mutex_lock(&thread_mutex, true); } void mp_thread_unix_end_atomic_section(void) { - pthread_mutex_unlock(&thread_mutex); + mp_thread_recursive_mutex_unlock(&thread_mutex); } // this signal handler is used to scan the regs and stack of a thread -STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { +static void mp_thread_gc(int signo, siginfo_t *info, void *context) { (void)info; // unused (void)context; // unused if (signo == MP_THREAD_GC_SIGNAL) { @@ -107,16 +114,25 @@ STATIC void mp_thread_gc(int signo, siginfo_t *info, void *context) { } } +// On Android, pthread_cancel and pthread_setcanceltype are not implemented. +// To achieve that result a new signal handler responding on either +// (SIGRTMIN + 6) or SIGUSR2 is installed on every child thread. The sole +// purpose of this new signal handler is to terminate the thread in a safe +// asynchronous manner. + +#ifdef __ANDROID__ +static void mp_thread_terminate(int signo, siginfo_t *info, void *context) { + pthread_exit(NULL); +} +#endif + void mp_thread_init(void) { pthread_key_create(&tls_key, NULL); pthread_setspecific(tls_key, &mp_state_ctx.thread); // Needs to be a recursive mutex to emulate the behavior of // BEGIN_ATOMIC_SECTION on bare metal. - pthread_mutexattr_t thread_mutex_attr; - pthread_mutexattr_init(&thread_mutex_attr); - pthread_mutexattr_settype(&thread_mutex_attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&thread_mutex, &thread_mutex_attr); + mp_thread_recursive_mutex_init(&thread_mutex); // create first entry in linked list of all threads thread = malloc(sizeof(mp_thread_t)); @@ -138,6 +154,14 @@ void mp_thread_init(void) { sa.sa_sigaction = mp_thread_gc; sigemptyset(&sa.sa_mask); sigaction(MP_THREAD_GC_SIGNAL, &sa, NULL); + + // Install a signal handler for asynchronous termination if needed. + #if defined(__ANDROID__) + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = mp_thread_terminate; + sigemptyset(&sa.sa_mask); + sigaction(MP_THREAD_TERMINATE_SIGNAL, &sa, NULL); + #endif } void mp_thread_deinit(void) { @@ -145,7 +169,11 @@ void mp_thread_deinit(void) { while (thread->next != NULL) { mp_thread_t *th = thread; thread = thread->next; + #if defined(__ANDROID__) + pthread_kill(th->id, MP_THREAD_TERMINATE_SIGNAL); + #else pthread_cancel(th->id); + #endif free(th); } mp_thread_unix_end_atomic_section(); @@ -203,7 +231,9 @@ void mp_thread_start(void) { } #endif + #if !defined(__ANDROID__) pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); + #endif mp_thread_unix_begin_atomic_section(); for (mp_thread_t *th = thread; th != NULL; th = th->next) { if (th->id == pthread_self()) { @@ -215,14 +245,14 @@ void mp_thread_start(void) { } mp_uint_t mp_thread_create(void *(*entry)(void *), void *arg, size_t *stack_size) { - // default stack size is 8k machine-words + // default stack size if (*stack_size == 0) { - *stack_size = 8192 * sizeof(void *); + *stack_size = 32768 * UNIX_STACK_MULTIPLIER; } // minimum stack size is set by pthreads - if (*stack_size < PTHREAD_STACK_MIN) { - *stack_size = PTHREAD_STACK_MIN; + if (*stack_size < (size_t)PTHREAD_STACK_MIN) { + *stack_size = (size_t)PTHREAD_STACK_MIN; } // ensure there is enough stack to include a stack-overflow margin @@ -321,6 +351,26 @@ void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { // TODO check return value } +#if MICROPY_PY_THREAD_RECURSIVE_MUTEX + +void mp_thread_recursive_mutex_init(mp_thread_recursive_mutex_t *mutex) { + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(mutex, &attr); + pthread_mutexattr_destroy(&attr); +} + +int mp_thread_recursive_mutex_lock(mp_thread_recursive_mutex_t *mutex, int wait) { + return mp_thread_mutex_lock(mutex, wait); +} + +void mp_thread_recursive_mutex_unlock(mp_thread_recursive_mutex_t *mutex) { + mp_thread_mutex_unlock(mutex); +} + +#endif // MICROPY_PY_THREAD_RECURSIVE_MUTEX + #endif // MICROPY_PY_THREAD // this is used even when MICROPY_PY_THREAD is disabled diff --git a/ports/unix/mpthreadport.h b/ports/unix/mpthreadport.h index b365f200edf97..a38223e720b45 100644 --- a/ports/unix/mpthreadport.h +++ b/ports/unix/mpthreadport.h @@ -28,6 +28,7 @@ #include typedef pthread_mutex_t mp_thread_mutex_t; +typedef pthread_mutex_t mp_thread_recursive_mutex_t; void mp_thread_init(void); void mp_thread_deinit(void); diff --git a/ports/unix/native_base_class.c b/ports/unix/native_base_class.c index 28fd572eaf1f6..e333843e20df0 100644 --- a/ports/unix/native_base_class.c +++ b/ports/unix/native_base_class.c @@ -14,7 +14,7 @@ typedef struct { const mp_obj_type_t native_base_class_type; -STATIC mp_obj_t native_base_class_make_new(const mp_obj_type_t *type, size_t n_args, +static mp_obj_t native_base_class_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_test }; static const mp_arg_t allowed_args[] = { @@ -35,13 +35,13 @@ static native_base_class_obj_t *native_base(mp_obj_t unknown_obj) { return MP_OBJ_TO_PTR(native_obj); } -STATIC mp_obj_t native_base_class_obj_get_test(mp_obj_t self_in) { +static mp_obj_t native_base_class_obj_get_test(mp_obj_t self_in) { native_base_class_obj_t *self = native_base(self_in); return self->test; } MP_DEFINE_CONST_FUN_OBJ_1(native_base_class_get_test_obj, native_base_class_obj_get_test); -STATIC mp_obj_t native_base_class_obj_set_test(mp_obj_t self_in, mp_obj_t value) { +static mp_obj_t native_base_class_obj_set_test(mp_obj_t self_in, mp_obj_t value) { mp_printf(&mp_plat_print, "native base class .test set to: "); mp_obj_print_helper(&mp_plat_print, value, PRINT_REPR); mp_printf(&mp_plat_print, "\n"); @@ -55,7 +55,7 @@ MP_PROPERTY_GETSET(native_base_class_test_obj, (mp_obj_t)&native_base_class_get_test_obj, (mp_obj_t)&native_base_class_set_test_obj); -STATIC mp_obj_t native_base_class_obj_print_subclass_attr(mp_obj_t self_in, mp_obj_t attr_name_obj) { +static mp_obj_t native_base_class_obj_print_subclass_attr(mp_obj_t self_in, mp_obj_t attr_name_obj) { if (!mp_obj_is_str(attr_name_obj)) { mp_raise_TypeError(NULL); } @@ -68,15 +68,15 @@ STATIC mp_obj_t native_base_class_obj_print_subclass_attr(mp_obj_t self_in, mp_o } MP_DEFINE_CONST_FUN_OBJ_2(native_base_class_print_subclass_attr_obj, native_base_class_obj_print_subclass_attr); -STATIC const mp_rom_map_elem_t native_base_class_locals_dict_table[] = { +static const mp_rom_map_elem_t native_base_class_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_test), MP_ROM_PTR(&native_base_class_test_obj) }, { MP_ROM_QSTR(MP_QSTR_print_subclass_attr), MP_ROM_PTR(&native_base_class_print_subclass_attr_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(native_base_class_locals_dict, native_base_class_locals_dict_table); +static MP_DEFINE_CONST_DICT(native_base_class_locals_dict, native_base_class_locals_dict_table); -STATIC mp_obj_t native_base_class_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { +static mp_obj_t native_base_class_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { mp_obj_t attribute_value = mp_load_attr(self_in, MP_QSTR_new_attribute); mp_printf(&mp_plat_print, "native base class subscr .new_attribute set to: "); mp_obj_print_helper(&mp_plat_print, attribute_value, PRINT_REPR); diff --git a/ports/unix/stack_size.h b/ports/unix/stack_size.h new file mode 100644 index 0000000000000..f6159bb69d529 --- /dev/null +++ b/ports/unix/stack_size.h @@ -0,0 +1,54 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_UNIX_STACK_SIZE_H +#define MICROPY_INCLUDED_UNIX_STACK_SIZE_H + +#include "py/misc.h" + +// Define scaling factors for the stack size (also applies to main thread) +#ifndef UNIX_STACK_MULTIPLIER + +#if defined(__arm__) && !defined(__thumb2__) +// ARM (non-Thumb) architectures require more stack. +#define UNIX_STACK_MUL_ARM 2 +#else +#define UNIX_STACK_MUL_ARM 1 +#endif + +#if MP_SANITIZER_BUILD +// Sanitizer features consume significant stack in some cases +// This multiplier can probably be removed when using GCC 12 or newer. +#define UNIX_STACK_MUL_SANITIZERS 4 +#else +#define UNIX_STACK_MUL_SANITIZERS 1 +#endif + +// Double the stack size for 64-bit builds, plus additional scaling +#define UNIX_STACK_MULTIPLIER ((sizeof(void *) / 4) * UNIX_STACK_MUL_ARM * UNIX_STACK_MUL_SANITIZERS) + +#endif // UNIX_STACK_MULTIPLIER + +#endif // MICROPY_INCLUDED_UNIX_STACK_SIZE_H diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c index 6e9ad5705368e..238d1cb5ee8a1 100644 --- a/ports/unix/unix_mphal.c +++ b/ports/unix/unix_mphal.c @@ -46,7 +46,7 @@ #ifndef _WIN32 #include -STATIC void sighandler(int signum) { +static void sighandler(int signum) { if (signum == SIGINT) { #if MICROPY_ASYNC_KBD_INTR #if MICROPY_PY_THREAD_GIL diff --git a/ports/unix/variants/coverage/frzmpy/frzmpy4.py b/ports/unix/variants/coverage/frzmpy/frzmpy4.py new file mode 100644 index 0000000000000..669b37535b0f7 --- /dev/null +++ b/ports/unix/variants/coverage/frzmpy/frzmpy4.py @@ -0,0 +1,16 @@ +# Test importing frozen functions. + +# A simple bytecode function with no children. +def f(): + return 1 + + +print(__name__, f()) + + +# A simple bytecode generator with no children. +def g(): + yield 2 + + +print(__name__, next(g())) diff --git a/ports/unix/variants/coverage/manifest.py b/ports/unix/variants/coverage/manifest.py index 7c3d9a6b64d69..37f2531a842f8 100644 --- a/ports/unix/variants/coverage/manifest.py +++ b/ports/unix/variants/coverage/manifest.py @@ -1,3 +1,5 @@ +add_library("unix-ffi", "$(MPY_LIB_DIR)/unix-ffi") freeze_as_str("frzstr") freeze_as_mpy("frzmpy") freeze_mpy("$(MPY_DIR)/tests/frozen") +require("ssl") diff --git a/ports/unix/variants/coverage/mpconfigvariant.h b/ports/unix/variants/coverage/mpconfigvariant.h index 67b1f3c8037df..03f77ec14c6db 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.h +++ b/ports/unix/variants/coverage/mpconfigvariant.h @@ -39,10 +39,29 @@ // Enable additional features. #define MICROPY_DEBUG_PARSE_RULE_NAME (1) +// CIRCUITPY-CHANGE: off +#define MICROPY_PY_SYS_SETTRACE (0) #define MICROPY_TRACKED_ALLOC (1) #define MICROPY_WARNINGS_CATEGORY (1) +#undef MICROPY_VFS_ROM_IOCTL +#define MICROPY_VFS_ROM_IOCTL (1) +#define MICROPY_PY_CRYPTOLIB_CTR (1) +// CIRCUITPY-CHANGE: off +#define MICROPY_SCHEDULER_STATIC_NODES (0) + +// Enable os.uname for attrtuple coverage test +#define MICROPY_PY_OS_UNAME (1) +#define MICROPY_HW_BOARD_NAME "a machine" +#define MICROPY_HW_MCU_NAME MICROPY_PY_SYS_PLATFORM +// Keep the standard banner message +#define MICROPY_BANNER_MACHINE MICROPY_PY_SYS_PLATFORM " [" MICROPY_PLATFORM_COMPILER "] version" // CIRCUITPY-CHANGE: Disable things never used in circuitpython -#define MICROPY_PY_CRYPTOLIB (0) -#define MICROPY_PY_CRYPTOLIB_CTR (0) -#define MICROPY_PY_STRUCT (0) // uses shared-bindings struct +#define MICROPY_PY_CRYPTOLIB (0) +#undef MICROPY_PY_CRYPTOLIB_CTR +#define MICROPY_PY_CRYPTOLIB_CTR (0) +#define MICROPY_PY_MICROPYTHON_RINGIO (0) +// CircuitPython uses shared-bindings struct +#define MICROPY_PY_STRUCT (0) +#undef MICROPY_VFS_ROM_IOCTL +#define MICROPY_VFS_ROM_IOCTL (0) diff --git a/ports/unix/variants/coverage/mpconfigvariant.mk b/ports/unix/variants/coverage/mpconfigvariant.mk index 9721c2803e25c..292e4de81699f 100644 --- a/ports/unix/variants/coverage/mpconfigvariant.mk +++ b/ports/unix/variants/coverage/mpconfigvariant.mk @@ -12,7 +12,8 @@ CFLAGS += \ LDFLAGS += -fprofile-arcs -ftest-coverage FROZEN_MANIFEST ?= $(VARIANT_DIR)/manifest.py -USER_C_MODULES = $(TOP)/examples/usercmodule +# CIRCUITPY-CHANGE: don't include user C modules +# USER_C_MODULES = $(TOP)/examples/usercmodule # CIRCUITPY-CHANGE: use CircuitPython bindings and implementations SRC_QRIO := $(patsubst ../../%,%,$(wildcard ../../shared-bindings/qrio/*.c ../../shared-module/qrio/*.c ../../lib/quirc/lib/*.c)) @@ -33,6 +34,17 @@ SRC_BITMAP := \ shared-bindings/audiocore/__init__.c \ shared-bindings/audiocore/RawSample.c \ shared-bindings/audiocore/WaveFile.c \ + shared-bindings/audiodelays/Echo.c \ + shared-bindings/audiodelays/Chorus.c \ + shared-bindings/audiodelays/PitchShift.c \ + shared-bindings/audiodelays/MultiTapDelay.c \ + shared-bindings/audiodelays/__init__.c \ + shared-bindings/audiofilters/Distortion.c \ + shared-bindings/audiofilters/Filter.c \ + shared-bindings/audiofilters/Phaser.c \ + shared-bindings/audiofilters/__init__.c \ + shared-bindings/audiofreeverb/Freeverb.c \ + shared-bindings/audiofreeverb/__init__.c \ shared-bindings/audiomixer/__init__.c \ shared-bindings/audiomixer/Mixer.c \ shared-bindings/audiomixer/MixerVoice.c \ @@ -59,12 +71,28 @@ SRC_BITMAP := \ shared-bindings/synthio/Synthesizer.c \ shared-bindings/traceback/__init__.c \ shared-bindings/util.c \ + shared-bindings/vectorio/Circle.c \ + shared-bindings/vectorio/__init__.c \ + shared-bindings/vectorio/Polygon.c \ + shared-bindings/vectorio/Rectangle.c \ + shared-bindings/vectorio/VectorShape.c \ shared-bindings/zlib/__init__.c \ shared-module/aesio/aes.c \ shared-module/aesio/__init__.c \ shared-module/audiocore/__init__.c \ shared-module/audiocore/RawSample.c \ shared-module/audiocore/WaveFile.c \ + shared-module/audiodelays/Echo.c \ + shared-module/audiodelays/Chorus.c \ + shared-module/audiodelays/PitchShift.c \ + shared-module/audiodelays/MultiTapDelay.c \ + shared-module/audiodelays/__init__.c \ + shared-module/audiofilters/Distortion.c \ + shared-module/audiofilters/Filter.c \ + shared-module/audiofilters/Phaser.c \ + shared-module/audiofilters/__init__.c \ + shared-module/audiofreeverb/Freeverb.c \ + shared-module/audiofreeverb/__init__.c \ shared-module/audiomixer/__init__.c \ shared-module/audiomp3/MP3Decoder.c \ shared-module/audiomixer/Mixer.c \ @@ -78,7 +106,6 @@ SRC_BITMAP := \ shared-module/floppyio/__init__.c \ shared-module/jpegio/__init__.c \ shared-module/jpegio/JpegDecoder.c \ - shared-module/os/getenv.c \ shared-module/rainbowio/__init__.c \ shared-module/struct/__init__.c \ shared-module/synthio/__init__.c \ @@ -88,6 +115,12 @@ SRC_BITMAP := \ shared-module/synthio/Note.c \ shared-module/synthio/Biquad.c \ shared-module/synthio/Synthesizer.c \ + shared-bindings/vectorio/Circle.c \ + shared-module/vectorio/Circle.c \ + shared-module/vectorio/__init__.c \ + shared-module/vectorio/Polygon.c \ + shared-module/vectorio/Rectangle.c \ + shared-module/vectorio/VectorShape.c \ shared-module/traceback/__init__.c \ shared-module/zlib/__init__.c \ @@ -116,9 +149,11 @@ $(BUILD)/lib/mp3/src/buffers.o: CFLAGS += -include "shared-module/audiomp3/__ini CFLAGS += \ -DCIRCUITPY_AESIO=1 \ -DCIRCUITPY_AUDIOCORE=1 \ + -DCIRCUITPY_AUDIOEFFECTS=1 \ + -DCIRCUITPY_AUDIODELAYS=1 \ + -DCIRCUITPY_AUDIOFILTERS=1 \ -DCIRCUITPY_AUDIOMIXER=1 \ -DCIRCUITPY_AUDIOMP3=1 \ - -DCIRCUITPY_AUDIOMP3_USE_PORT_ALLOCATOR=0 \ -DCIRCUITPY_AUDIOCORE_DEBUG=1 \ -DCIRCUITPY_BITMAPTOOLS=1 \ -DCIRCUITPY_CODEOP=1 \ @@ -128,12 +163,13 @@ CFLAGS += \ -DCIRCUITPY_GIFIO=1 \ -DCIRCUITPY_JPEGIO=1 \ -DCIRCUITPY_LOCALE=1 \ - -DCIRCUITPY_OS_GETENV=1 \ -DCIRCUITPY_RAINBOWIO=1 \ + -DCIRCUITPY_SETTINGS_TOML=1 \ -DCIRCUITPY_STRUCT=1 \ -DCIRCUITPY_SYNTHIO=1 \ -DCIRCUITPY_SYNTHIO_MAX_CHANNELS=14 \ -DCIRCUITPY_TRACEBACK=1 \ + -DCIRCUITPY_VECTORIO=1 \ -DCIRCUITPY_ZLIB=1 # CIRCUITPY-CHANGE: test native base classes. diff --git a/ports/unix/variants/longlong/mpconfigvariant.h b/ports/unix/variants/longlong/mpconfigvariant.h new file mode 100644 index 0000000000000..d50d360b1fe5c --- /dev/null +++ b/ports/unix/variants/longlong/mpconfigvariant.h @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This config exists to test that the MICROPY_LONGINT_IMPL_LONGLONG variant +// (i.e. minimal form of "big integer" that's backed by 64-bit int only) builds +// and passes tests. + +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) + +// We build it on top of REPR C, which uses memory-efficient floating point +// objects encoded directly mp_obj_t (30 bits only). +// Therefore this variant should be built using MICROPY_FORCE_32BIT=1 + +#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C) +#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) + +// Set base feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/longlong/mpconfigvariant.mk b/ports/unix/variants/longlong/mpconfigvariant.mk new file mode 100644 index 0000000000000..2d2c3706469fb --- /dev/null +++ b/ports/unix/variants/longlong/mpconfigvariant.mk @@ -0,0 +1,8 @@ +# build interpreter with "bigints" implemented as "longlong" + +# otherwise, small int is essentially 64-bit +MICROPY_FORCE_32BIT := 1 + +MICROPY_PY_FFI := 0 + +MPY_TOOL_FLAGS = -mlongint-impl longlong diff --git a/ports/unix/variants/manifest.py b/ports/unix/variants/manifest.py index f8e8f250ac653..649b1e4c464fb 100644 --- a/ports/unix/variants/manifest.py +++ b/ports/unix/variants/manifest.py @@ -1 +1,3 @@ +add_library("unix-ffi", "$(MPY_LIB_DIR)/unix-ffi") require("mip-cmdline") +require("ssl") diff --git a/ports/unix/variants/minimal/mpconfigvariant.h b/ports/unix/variants/minimal/mpconfigvariant.h index 0dbfbb3d1cd43..0e280a8f73058 100644 --- a/ports/unix/variants/minimal/mpconfigvariant.h +++ b/ports/unix/variants/minimal/mpconfigvariant.h @@ -49,6 +49,7 @@ #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1) #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_ENABLE_EXTERNAL_IMPORT (1) +#define MICROPY_STACK_CHECK (1) #define MICROPY_FULL_CHECKS (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_KBD_EXCEPTION (1) @@ -61,9 +62,5 @@ #define MICROPY_PY_BUILTINS_RANGE_ATTRS (1) #define MICROPY_PY_GENERATOR_PEND_THROW (1) -// Enable just the sys and os built-in modules. -#define MICROPY_PY_SYS (1) +// Add just the os built-in module. #define MICROPY_PY_OS (1) - -// The minimum sets this to 1 to save flash. -#define MICROPY_QSTR_BYTES_IN_HASH (2) diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h index 981babca9f10b..1ac59c95572dd 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -29,7 +29,7 @@ // Send raise KeyboardInterrupt directly from the signal handler rather than // scheduling it into the VM. -#define MICROPY_ASYNC_KBD_INTR (1) +#define MICROPY_ASYNC_KBD_INTR (!MICROPY_PY_THREAD_GIL) // Enable helpers for printing debugging information. #ifndef MICROPY_DEBUG_PRINTERS @@ -41,6 +41,11 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #endif +// Don't use native _Float16 because it increases code size by a lot. +#ifndef MICROPY_FLOAT_USE_NATIVE_FLT16 +#define MICROPY_FLOAT_USE_NATIVE_FLT16 (0) +#endif + // Enable arbitrary precision long-int by default. #ifndef MICROPY_LONGINT_IMPL #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) @@ -90,7 +95,6 @@ #define MICROPY_PY_OS_INCLUDEFILE "ports/unix/modos.c" #define MICROPY_PY_OS_ERRNO (1) #define MICROPY_PY_OS_GETENV_PUTENV_UNSETENV (1) -#define MICROPY_PY_OS_SEP (1) #define MICROPY_PY_OS_SYSTEM (1) #define MICROPY_PY_OS_URANDOM (1) @@ -100,12 +104,6 @@ #define MICROPY_PY_TIME_CUSTOM_SLEEP (1) #define MICROPY_PY_TIME_INCLUDEFILE "ports/unix/modtime.c" -#if MICROPY_PY_SSL -#define MICROPY_PY_HASHLIB_MD5 (1) -#define MICROPY_PY_HASHLIB_SHA1 (1) -#define MICROPY_PY_CRYPTOLIB (1) -#endif - // The "select" module is enabled by default, but disable select.select(). #define MICROPY_PY_SELECT_POSIX_OPTIMISATIONS (1) #define MICROPY_PY_SELECT_SELECT (0) @@ -117,3 +115,6 @@ #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PIN_BASE (1) + +#define MICROPY_VFS_ROM (1) +#define MICROPY_VFS_ROM_IOCTL (0) diff --git a/ports/unix/variants/nanbox/mpconfigvariant.h b/ports/unix/variants/nanbox/mpconfigvariant.h index 7b13b7dc6ce4e..c9e9c1f63d95d 100644 --- a/ports/unix/variants/nanbox/mpconfigvariant.h +++ b/ports/unix/variants/nanbox/mpconfigvariant.h @@ -41,10 +41,3 @@ #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_ARM (0) - -#include - -typedef int64_t mp_int_t; -typedef uint64_t mp_uint_t; -#define UINT_FMT "%llu" -#define INT_FMT "%lld" diff --git a/ports/zephyr-cp/.gitignore b/ports/zephyr-cp/.gitignore new file mode 100644 index 0000000000000..65d8deaa722ac --- /dev/null +++ b/ports/zephyr-cp/.gitignore @@ -0,0 +1,7 @@ +# West manages these folders. +bootloader +build +modules +tools +zephyr +.west diff --git a/ports/zephyr-cp/AGENTS.md b/ports/zephyr-cp/AGENTS.md new file mode 100644 index 0000000000000..58a3912e2ba05 --- /dev/null +++ b/ports/zephyr-cp/AGENTS.md @@ -0,0 +1,7 @@ +- Build a board by doing `make BOARD=_`. +- The corresponding configuration files are in `boards//` +- The files (not folders) in `boards/` directory are used by Zephyr. +- To flash it on a board do `make BOARD=_ flash`. +- Zephyr board docs are at `zephyr/boards//`. +- Run zephyr-cp tests with `make test`. +- Do not add new translatable error strings (`MP_ERROR_TEXT`). Instead, use `raise_zephyr_error()` or `CHECK_ZEPHYR_RESULT()` from `bindings/zephyr_kernel/__init__.h` to convert Zephyr errno values into Python exceptions. diff --git a/ports/zephyr-cp/CLAUDE.md b/ports/zephyr-cp/CLAUDE.md new file mode 100644 index 0000000000000..43c994c2d3617 --- /dev/null +++ b/ports/zephyr-cp/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/ports/zephyr-cp/CMakeLists.txt b/ports/zephyr-cp/CMakeLists.txt new file mode 100644 index 0000000000000..9d115f1e17688 --- /dev/null +++ b/ports/zephyr-cp/CMakeLists.txt @@ -0,0 +1,73 @@ +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS lib/zephyr) +project(circuitpython) + +target_sources(app PRIVATE zephyr_main.c) + +# Add I2C emulator control for native_sim testing +if(CONFIG_BOARD_NATIVE_SIM) + target_sources(app PRIVATE native_sim_i2c_emul_control.c) +endif() + +if(CONFIG_TRACING_PERFETTO) + zephyr_include_directories(${ZEPHYR_BINARY_DIR}/subsys/tracing/perfetto/proto) +endif() + +# From: https://github.com/zephyrproject-rtos/zephyr/blob/main/samples/application_development/external_lib/CMakeLists.txt +# The external static library that we are linking with does not know +# how to build for this platform so we export all the flags used in +# this zephyr build to the external build system. +# +# Other external build systems may be self-contained enough that they +# do not need any build information from zephyr. Or they may be +# incompatible with certain zephyr options and need them to be +# filtered out. +zephyr_get_include_directories_for_lang_as_string( C includes) +zephyr_get_system_include_directories_for_lang_as_string(C system_includes) +zephyr_get_compile_definitions_for_lang_as_string( C definitions) +zephyr_get_compile_options_for_lang_as_string( C options) + +if(DEFINED CMAKE_C_COMPILER_TARGET) + set(target_flag "--target=${CMAKE_C_COMPILER_TARGET}") +endif() + +set(external_project_cflags + "${target_flag} ${includes} ${definitions} ${options} ${system_includes}" + ) + +zephyr_get(TRANSLATION SYSBUILD GLOBAL) +zephyr_get(CONFIG_LTO SYSBUILD GLOBAL) +zephyr_get(BOARD_ALIAS SYSBUILD GLOBAL) + +ExternalProject_Add(circuitpython + DOWNLOAD_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/cptools/build_circuitpython.py + CC=${CMAKE_C_COMPILER} + AR=${CMAKE_AR} + CFLAGS=${external_project_cflags} + BOARD=${BOARD} + BOARD_ALIAS=${BOARD_ALIAS} + BOARD_REVISION=${BOARD_REVISION} + BOARD_QUALIFIERS=${BOARD_QUALIFIERS} + SOC_DIRECTORIES=${SOC_DIRECTORIES} + OUTPUT_FILE=${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a + PORT_SRC_DIR=${CMAKE_CURRENT_SOURCE_DIR} + TRANSLATION=${TRANSLATION} + LTO=${CONFIG_LTO} + BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a + BUILD_JOB_SERVER_AWARE TRUE + BUILD_ALWAYS TRUE + DEPENDS zephyr + INSTALL_COMMAND "" + ) + +add_library(circuitpython_wrapper STATIC IMPORTED GLOBAL) +add_dependencies( + circuitpython_wrapper + circuitpython + ) +set_target_properties(circuitpython_wrapper PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/libcircuitpython.a) +target_link_libraries(circuitpython_wrapper INTERFACE kernel) +target_link_libraries(app PRIVATE circuitpython_wrapper) diff --git a/ports/zephyr-cp/Kconfig.sysbuild b/ports/zephyr-cp/Kconfig.sysbuild new file mode 100644 index 0000000000000..11b49446f422f --- /dev/null +++ b/ports/zephyr-cp/Kconfig.sysbuild @@ -0,0 +1,16 @@ +# Copyright 2023-2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk/nrf5340/cpunet" if $(BOARD) = "nrf5340dk" + default "nrf7002dk/nrf5340/cpunet" if $(BOARD) = "nrf7002dk" + default "nrf5340_audio_dk/nrf5340/cpunet" if $(BOARD) = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD) = "nrf5340bsim" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/ports/zephyr-cp/Makefile b/ports/zephyr-cp/Makefile new file mode 100644 index 0000000000000..12f22d7c3ae83 --- /dev/null +++ b/ports/zephyr-cp/Makefile @@ -0,0 +1,99 @@ +ALL_BOARDS_IN_PORT := $($(wildcard boards/*/*):boards/=:/=) +# An incorrect BOARD might have been specified, so check against the list. +# There is deliberately no space after the := +VALID_BOARD :=$(filter $(BOARD),$(ALL_BOARDS_IN_PORT)) + +# If the build directory is not given, make it reflect the board name. +BUILD ?= build-$(BOARD) + +TRANSLATION ?= en_US + +# Compute shield args once. Command-line SHIELD/SHIELDS values override board defaults from circuitpython.toml. +ifneq ($(strip $(BOARD)),) +WEST_SHIELD_ARGS := $(shell SHIELD_ORIGIN="$(origin SHIELD)" SHIELDS_ORIGIN="$(origin SHIELDS)" SHIELD="$(SHIELD)" SHIELDS="$(SHIELDS)" python cptools/get_west_shield_args.py $(BOARD)) +endif + +WEST_CMAKE_ARGS := -DZEPHYR_BOARD_ALIASES=$(CURDIR)/boards/board_aliases.cmake -Dzephyr-cp_TRANSLATION=$(TRANSLATION) + +# When DEBUG=1, apply additional Kconfig fragments for debug-friendly settings. +DEBUG_CONF_FILE ?= $(CURDIR)/debug.conf +ifeq ($(DEBUG),1) +WEST_CMAKE_ARGS += -Dzephyr-cp_EXTRA_CONF_FILE=$(DEBUG_CONF_FILE) +endif + +.PHONY: $(BUILD)/zephyr-cp/zephyr/zephyr.elf flash recover debug debug-jlink debugserver attach run run-sim clean menuconfig all clean-all sim clean-sim test fetch-port-submodules + +$(BUILD)/zephyr-cp/zephyr/zephyr.elf: + python cptools/pre_zephyr_build_prep.py $(BOARD) + west build -b $(BOARD) -d $(BUILD) $(WEST_SHIELD_ARGS) --sysbuild -- $(WEST_CMAKE_ARGS) + +$(BUILD)/firmware.elf: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + cp $^ $@ + +$(BUILD)/firmware.hex: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + cp $(BUILD)/zephyr-cp/zephyr/zephyr.hex $@ + +$(BUILD)/firmware.exe: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + cp $(BUILD)/zephyr-cp/zephyr/zephyr.exe $@ + +$(BUILD)/firmware.uf2: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + cp $(BUILD)/zephyr-cp/zephyr/zephyr.uf2 $@ + +flash: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west flash -d $(BUILD) + +recover: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west flash --recover -d $(BUILD) + +debug: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west debug -d $(BUILD) + +debug-jlink: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west debug --runner jlink -d $(BUILD) + +debugserver: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west debugserver -d $(BUILD) + +attach: $(BUILD)/zephyr-cp/zephyr/zephyr.elf + west attach -d $(BUILD) + +run: $(BUILD)/firmware.exe + $^ + +run-sim: + $(MAKE) BOARD=native_native_sim BUILD=build-native_native_sim build-native_native_sim/firmware.exe + truncate -s 2M build-native_native_sim/flash.bin + mformat -i build-native_native_sim/flash.bin :: + @if [ -d CIRCUITPY ] && [ -n "$$(find CIRCUITPY -mindepth 1 -print -quit)" ]; then \ + echo "Populating build-native_native_sim/flash.bin from ./CIRCUITPY"; \ + mcopy -s -i build-native_native_sim/flash.bin CIRCUITPY/* ::; \ + fi + build-native_native_sim/firmware.exe --flash=build-native_native_sim/flash.bin --flash_rm -wait_uart -rt --i2s_capture=build-native_native_sim/i2s_capture.wav + +menuconfig: + west build $(WEST_SHIELD_ARGS) --sysbuild -d $(BUILD) -t menuconfig -- $(WEST_CMAKE_ARGS) + +clean: + rm -rf $(BUILD) + +fetch-port-submodules: + python ../../tools/ci_fetch_deps.py zephyr-cp + +# Build all boards. The + prefix allows jobserver file descriptors to be passed through. +# This enables parallel builds across all boards when invoked with `make -jN all`. +all: + +python cptools/build_all_boards.py --continue-on-error + +clean-all: + rm -rf build build-* + +# Build all sim boards concurrently using the same jobserver as `make all`. +sim: + +python cptools/build_all_boards.py --vendor native --continue-on-error + +clean-sim: + rm -rf $(wildcard build-native_*) + +test: build-native_native_sim/zephyr-cp/zephyr/zephyr.exe + pytest cptools/tests + pytest tests/ -v diff --git a/ports/zephyr-cp/README.md b/ports/zephyr-cp/README.md new file mode 100644 index 0000000000000..162ed90bcc8b7 --- /dev/null +++ b/ports/zephyr-cp/README.md @@ -0,0 +1,118 @@ +# Zephyr + +This is an initial port of CircuitPython onto Zephyr. We intend on migrating all +existing boards onto Zephyr. To start, we'll only support new boards. Existing +boards will be switched as the Zephyr port reaches parity with the existing +implementation. + +## Getting Started + +First, install Zephyr tools (see [Zephyr's Getting Started Guide](https://docs.zephyrproject.org/4.0.0/develop/getting_started/index.html)). (These are `fish` commands because that's what Scott uses.) + + +```sh +pip install west +west init -l zephyr-config +west update +west zephyr-export +pip install -r zephyr/scripts/requirements.txt +west sdk install +``` + +Now to build from `ports/zephyr-cp`: + +```sh +make BOARD=nordic_nrf7002dk +``` + +This uses Zephyr's cmake to generate Makefiles that then delegate to +`tools/cpbuild/build_circuitpython.py` to build the CircuitPython bits in parallel. + +## Native simulator build container + +Building the native sim requires `libsdl2-dev:i386` and other 32bit dependencies that +can cause conflicts on 64bit systems resulting in the removal of 64bit versions of critical +software such as the display manager and network manager. A Containerfile and a few scripts +are provided to set up a container to make the native sim build inside without affecting the +host system. + +The container automatically mounts this instance of the circuitpython repo inside at +`/home/dev/circuitpython`. Changes made in the repo inside the container and on the host PC +will sync automatically between host and container. + +To use the container file: + +1. Build the container with `podman build -t zephyr-cp-dev -f native_sim_build_Containerfile .` +2. Run/Start the container by running `./native_sim_build_run_container.sh` on the host PC. + The script will automatically run or start based on whether the container has been run before. +3. Init requirements inside the container with `./native_sim_build_init_container.sh` + +To delete the container and cleanup associated files: +```sh +podman ps -a --filter ancestor=zephyr-cp-dev -q | xargs -r podman rm -f +podman rmi zephyr-cp-dev +podman image prune -f +podman rm -f zcp +``` + +## Running the native simulator + +From `ports/zephyr-cp`, run: + +```sh +make run-sim +``` + +`run-sim` starts the native simulator in realtime. +It prints the PTY path to connect to the simulator REPL. +If a local `./CIRCUITPY/` folder exists, its files are used as the simulator's CIRCUITPY drive. + +Edit files in `./CIRCUITPY` (for example `code.py`) and rerun `make run-sim` to test changes. + +## Shields + +Board defaults can be set in `boards///circuitpython.toml`: + +```toml +SHIELDS = ["shield1", "shield2"] +``` + +For example, `boards/renesas/ek_ra8d1/circuitpython.toml` enables: + +```toml +SHIELDS = ["rtkmipilcdb00000be"] +``` + +You can override shield selection from the command line: + +```sh +# Single shield +make BOARD=renesas_ek_ra8d1 SHIELD=rtkmipilcdb00000be + +# Multiple shields (comma, semicolon, or space separated) +make BOARD=my_vendor_my_board SHIELDS="shield1,shield2" +``` + +Behavior and precedence: + +- If `SHIELD` or `SHIELDS` is explicitly provided, it overrides board defaults. +- If neither is provided, defaults from `circuitpython.toml` are used. +- Use `SHIELD=` (empty) to disable a board default shield for one build. + +## Testing other boards + +[Any Zephyr board](https://docs.zephyrproject.org/latest/boards/index.html#) can +be used with CircuitPython. To test a different board, use `west` directly to +build the board. The build will do its best to support as much as possible. By +default the Zephyr console will be used for output. USB support is limited by +initialization support in `supervisor/usb.c`. Only flash regions not used by +Zephyr are used for CIRCUITPY. A manual `circuitpython` partition can be +specified instead. + +For example, to test the `nrf52840dk` board: + +```sh +west build -b nrf52840dk/nrf52840 +``` + +This is already supported in `ports/nordic` as `pca10056`. diff --git a/ports/zephyr-cp/app.overlay b/ports/zephyr-cp/app.overlay new file mode 100644 index 0000000000000..0f34d64a80f1b --- /dev/null +++ b/ports/zephyr-cp/app.overlay @@ -0,0 +1,10 @@ +&zephyr_udc0 { + cdc_acm_console: cdc_acm_console { + compatible = "zephyr,cdc-acm-uart"; + label = "CircuitPython Console"; + }; + cdc_acm_data: cdc_acm_data { + compatible = "zephyr,cdc-acm-uart"; + label = "CircuitPython Data"; + }; +}; diff --git a/ports/zephyr-cp/background.c b/ports/zephyr-cp/background.c new file mode 100644 index 0000000000000..56e9e98f1f245 --- /dev/null +++ b/ports/zephyr-cp/background.c @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "background.h" + +#include "py/runtime.h" +#include "supervisor/port.h" + +#include + +void port_start_background_tick(void) { +} + +void port_finish_background_tick(void) { +} + +void port_background_tick(void) { + // No, ticks. We use Zephyr threads instead. +} + +void port_background_task(void) { + // Make sure time advances in the simulator. + #if defined(CONFIG_ARCH_POSIX) + k_busy_wait(100); + #endif +} diff --git a/ports/zephyr-cp/background.h b/ports/zephyr-cp/background.h new file mode 100644 index 0000000000000..5712b054193d8 --- /dev/null +++ b/ports/zephyr-cp/background.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +void board_background_task(void); diff --git a/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c new file mode 100644 index 0000000000000..fc0fb9ecc4f8f --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.c @@ -0,0 +1,37 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/hostnetwork/HostNetwork.h" + +#include "py/runtime.h" + +//| class HostNetwork: +//| """Native networking for the host simulator.""" +//| +//| def __init__(self) -> None: +//| """Create a HostNetwork instance.""" +//| ... +//| +static mp_obj_t hostnetwork_hostnetwork_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + hostnetwork_hostnetwork_obj_t *self = mp_obj_malloc(hostnetwork_hostnetwork_obj_t, &hostnetwork_hostnetwork_type); + common_hal_hostnetwork_hostnetwork_construct(self); + return MP_OBJ_FROM_PTR(self); +} + +static const mp_rom_map_elem_t hostnetwork_hostnetwork_locals_dict_table[] = { +}; +static MP_DEFINE_CONST_DICT(hostnetwork_hostnetwork_locals_dict, hostnetwork_hostnetwork_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + hostnetwork_hostnetwork_type, + MP_QSTR_HostNetwork, + MP_TYPE_FLAG_NONE, + make_new, hostnetwork_hostnetwork_make_new, + locals_dict, &hostnetwork_hostnetwork_locals_dict + ); diff --git a/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h new file mode 100644 index 0000000000000..009d8c0608743 --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/HostNetwork.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} hostnetwork_hostnetwork_obj_t; + +extern const mp_obj_type_t hostnetwork_hostnetwork_type; + +void common_hal_hostnetwork_hostnetwork_construct(hostnetwork_hostnetwork_obj_t *self); diff --git a/ports/zephyr-cp/bindings/hostnetwork/__init__.c b/ports/zephyr-cp/bindings/hostnetwork/__init__.c new file mode 100644 index 0000000000000..92302b67d0e97 --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/__init__.c @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" + +#include "bindings/hostnetwork/__init__.h" +#include "bindings/hostnetwork/HostNetwork.h" + +//| """Host networking support for the native simulator.""" +//| + +static const mp_rom_map_elem_t hostnetwork_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_hostnetwork) }, + { MP_ROM_QSTR(MP_QSTR_HostNetwork), MP_ROM_PTR(&hostnetwork_hostnetwork_type) }, +}; +static MP_DEFINE_CONST_DICT(hostnetwork_module_globals, hostnetwork_module_globals_table); + +const mp_obj_module_t hostnetwork_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&hostnetwork_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_hostnetwork, hostnetwork_module); diff --git a/ports/zephyr-cp/bindings/hostnetwork/__init__.h b/ports/zephyr-cp/bindings/hostnetwork/__init__.h new file mode 100644 index 0000000000000..a6731546bdef1 --- /dev/null +++ b/ports/zephyr-cp/bindings/hostnetwork/__init__.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "bindings/hostnetwork/HostNetwork.h" + +extern hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj; diff --git a/ports/zephyr-cp/bindings/zephyr_display/Display.c b/ports/zephyr-cp/bindings/zephyr_display/Display.c new file mode 100644 index 0000000000000..0923618c50a7f --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/Display.c @@ -0,0 +1,195 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/zephyr_display/Display.h" + +#include "py/objproperty.h" +#include "py/objtype.h" +#include "py/runtime.h" +#include "shared-bindings/displayio/Group.h" +#include "shared-module/displayio/__init__.h" + +static mp_obj_t zephyr_display_display_make_new(const mp_obj_type_t *type, + size_t n_args, + size_t n_kw, + const mp_obj_t *all_args) { + (void)type; + (void)n_args; + (void)n_kw; + (void)all_args; + mp_raise_NotImplementedError(NULL); + return mp_const_none; +} + +static zephyr_display_display_obj_t *native_display(mp_obj_t display_obj) { + mp_obj_t native = mp_obj_cast_to_native_base(display_obj, &zephyr_display_display_type); + mp_obj_assert_native_inited(native); + return MP_OBJ_TO_PTR(native); +} + +static mp_obj_t zephyr_display_display_obj_show(mp_obj_t self_in, mp_obj_t group_in) { + (void)self_in; + (void)group_in; + mp_raise_AttributeError(MP_ERROR_TEXT(".show(x) removed. Use .root_group = x")); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_show_obj, zephyr_display_display_obj_show); + +static mp_obj_t zephyr_display_display_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_target_frames_per_second, + ARG_minimum_frames_per_second, + }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_target_frames_per_second, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_minimum_frames_per_second, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + zephyr_display_display_obj_t *self = native_display(pos_args[0]); + + uint32_t maximum_ms_per_real_frame = NO_FPS_LIMIT; + mp_int_t minimum_frames_per_second = args[ARG_minimum_frames_per_second].u_int; + if (minimum_frames_per_second > 0) { + maximum_ms_per_real_frame = 1000 / minimum_frames_per_second; + } + + uint32_t target_ms_per_frame; + if (args[ARG_target_frames_per_second].u_obj == mp_const_none) { + target_ms_per_frame = NO_FPS_LIMIT; + } else { + target_ms_per_frame = 1000 / mp_obj_get_int(args[ARG_target_frames_per_second].u_obj); + } + + return mp_obj_new_bool(common_hal_zephyr_display_display_refresh( + self, + target_ms_per_frame, + maximum_ms_per_real_frame)); +} +MP_DEFINE_CONST_FUN_OBJ_KW(zephyr_display_display_refresh_obj, 1, zephyr_display_display_obj_refresh); + +static mp_obj_t zephyr_display_display_obj_get_auto_refresh(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return mp_obj_new_bool(common_hal_zephyr_display_display_get_auto_refresh(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_auto_refresh_obj, zephyr_display_display_obj_get_auto_refresh); + +static mp_obj_t zephyr_display_display_obj_set_auto_refresh(mp_obj_t self_in, mp_obj_t auto_refresh) { + zephyr_display_display_obj_t *self = native_display(self_in); + common_hal_zephyr_display_display_set_auto_refresh(self, mp_obj_is_true(auto_refresh)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_auto_refresh_obj, zephyr_display_display_obj_set_auto_refresh); + +MP_PROPERTY_GETSET(zephyr_display_display_auto_refresh_obj, + (mp_obj_t)&zephyr_display_display_get_auto_refresh_obj, + (mp_obj_t)&zephyr_display_display_set_auto_refresh_obj); + +static mp_obj_t zephyr_display_display_obj_get_brightness(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + mp_float_t brightness = common_hal_zephyr_display_display_get_brightness(self); + if (brightness < 0) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Brightness not adjustable")); + } + return mp_obj_new_float(brightness); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_brightness_obj, zephyr_display_display_obj_get_brightness); + +static mp_obj_t zephyr_display_display_obj_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) { + zephyr_display_display_obj_t *self = native_display(self_in); + mp_float_t brightness = mp_obj_get_float(brightness_obj); + if (brightness < 0.0f || brightness > 1.0f) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q must be %d-%d"), MP_QSTR_brightness, 0, 1); + } + bool ok = common_hal_zephyr_display_display_set_brightness(self, brightness); + if (!ok) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Brightness not adjustable")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_brightness_obj, zephyr_display_display_obj_set_brightness); + +MP_PROPERTY_GETSET(zephyr_display_display_brightness_obj, + (mp_obj_t)&zephyr_display_display_get_brightness_obj, + (mp_obj_t)&zephyr_display_display_set_brightness_obj); + +static mp_obj_t zephyr_display_display_obj_get_width(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_width(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_width_obj, zephyr_display_display_obj_get_width); +MP_PROPERTY_GETTER(zephyr_display_display_width_obj, (mp_obj_t)&zephyr_display_display_get_width_obj); + +static mp_obj_t zephyr_display_display_obj_get_height(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_height(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_height_obj, zephyr_display_display_obj_get_height); +MP_PROPERTY_GETTER(zephyr_display_display_height_obj, (mp_obj_t)&zephyr_display_display_get_height_obj); + +static mp_obj_t zephyr_display_display_obj_get_rotation(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_zephyr_display_display_get_rotation(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_rotation_obj, zephyr_display_display_obj_get_rotation); + +static mp_obj_t zephyr_display_display_obj_set_rotation(mp_obj_t self_in, mp_obj_t value) { + zephyr_display_display_obj_t *self = native_display(self_in); + common_hal_zephyr_display_display_set_rotation(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_rotation_obj, zephyr_display_display_obj_set_rotation); + +MP_PROPERTY_GETSET(zephyr_display_display_rotation_obj, + (mp_obj_t)&zephyr_display_display_get_rotation_obj, + (mp_obj_t)&zephyr_display_display_set_rotation_obj); + +static mp_obj_t zephyr_display_display_obj_get_root_group(mp_obj_t self_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + return common_hal_zephyr_display_display_get_root_group(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(zephyr_display_display_get_root_group_obj, zephyr_display_display_obj_get_root_group); + +static mp_obj_t zephyr_display_display_obj_set_root_group(mp_obj_t self_in, mp_obj_t group_in) { + zephyr_display_display_obj_t *self = native_display(self_in); + displayio_group_t *group = NULL; + if (group_in != mp_const_none) { + group = MP_OBJ_TO_PTR(native_group(group_in)); + } + + bool ok = common_hal_zephyr_display_display_set_root_group(self, group); + if (!ok) { + mp_raise_ValueError(MP_ERROR_TEXT("Group already used")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(zephyr_display_display_set_root_group_obj, zephyr_display_display_obj_set_root_group); + +MP_PROPERTY_GETSET(zephyr_display_display_root_group_obj, + (mp_obj_t)&zephyr_display_display_get_root_group_obj, + (mp_obj_t)&zephyr_display_display_set_root_group_obj); + +static const mp_rom_map_elem_t zephyr_display_display_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&zephyr_display_display_show_obj) }, + { MP_ROM_QSTR(MP_QSTR_refresh), MP_ROM_PTR(&zephyr_display_display_refresh_obj) }, + + { MP_ROM_QSTR(MP_QSTR_auto_refresh), MP_ROM_PTR(&zephyr_display_display_auto_refresh_obj) }, + { MP_ROM_QSTR(MP_QSTR_brightness), MP_ROM_PTR(&zephyr_display_display_brightness_obj) }, + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&zephyr_display_display_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&zephyr_display_display_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_rotation), MP_ROM_PTR(&zephyr_display_display_rotation_obj) }, + { MP_ROM_QSTR(MP_QSTR_root_group), MP_ROM_PTR(&zephyr_display_display_root_group_obj) }, +}; +static MP_DEFINE_CONST_DICT(zephyr_display_display_locals_dict, zephyr_display_display_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + zephyr_display_display_type, + MP_QSTR_Display, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, zephyr_display_display_make_new, + locals_dict, &zephyr_display_display_locals_dict); diff --git a/ports/zephyr-cp/bindings/zephyr_display/Display.h b/ports/zephyr-cp/bindings/zephyr_display/Display.h new file mode 100644 index 0000000000000..a50dda8fe8b69 --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/Display.h @@ -0,0 +1,37 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/displayio/Group.h" +#include "common-hal/zephyr_display/Display.h" + +extern const mp_obj_type_t zephyr_display_display_type; + +#define NO_FPS_LIMIT 0xffffffff + +void common_hal_zephyr_display_display_construct_from_device(zephyr_display_display_obj_t *self, + const struct device *device, + uint16_t rotation, + bool auto_refresh); + +bool common_hal_zephyr_display_display_refresh(zephyr_display_display_obj_t *self, + uint32_t target_ms_per_frame, + uint32_t maximum_ms_per_real_frame); + +bool common_hal_zephyr_display_display_get_auto_refresh(zephyr_display_display_obj_t *self); +void common_hal_zephyr_display_display_set_auto_refresh(zephyr_display_display_obj_t *self, bool auto_refresh); + +uint16_t common_hal_zephyr_display_display_get_width(zephyr_display_display_obj_t *self); +uint16_t common_hal_zephyr_display_display_get_height(zephyr_display_display_obj_t *self); +uint16_t common_hal_zephyr_display_display_get_rotation(zephyr_display_display_obj_t *self); +void common_hal_zephyr_display_display_set_rotation(zephyr_display_display_obj_t *self, int rotation); + +mp_float_t common_hal_zephyr_display_display_get_brightness(zephyr_display_display_obj_t *self); +bool common_hal_zephyr_display_display_set_brightness(zephyr_display_display_obj_t *self, mp_float_t brightness); + +mp_obj_t common_hal_zephyr_display_display_get_root_group(zephyr_display_display_obj_t *self); +bool common_hal_zephyr_display_display_set_root_group(zephyr_display_display_obj_t *self, displayio_group_t *root_group); diff --git a/ports/zephyr-cp/bindings/zephyr_display/__init__.c b/ports/zephyr-cp/bindings/zephyr_display/__init__.c new file mode 100644 index 0000000000000..eecfeeaec58ae --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/__init__.c @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "bindings/zephyr_display/Display.h" + +static const mp_rom_map_elem_t zephyr_display_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_zephyr_display) }, + { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&zephyr_display_display_type) }, +}; + +static MP_DEFINE_CONST_DICT(zephyr_display_module_globals, zephyr_display_module_globals_table); + +const mp_obj_module_t zephyr_display_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&zephyr_display_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_zephyr_display, zephyr_display_module); diff --git a/ports/zephyr-cp/bindings/zephyr_display/__init__.h b/ports/zephyr-cp/bindings/zephyr_display/__init__.h new file mode 100644 index 0000000000000..4256bfac2fe16 --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_display/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/zephyr-cp/bindings/zephyr_kernel/__init__.c b/ports/zephyr-cp/bindings/zephyr_kernel/__init__.c new file mode 100644 index 0000000000000..e37bd247495c2 --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_kernel/__init__.c @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" +#include "py/mphal.h" + + +#include "bindings/zephyr_kernel/__init__.h" diff --git a/ports/zephyr-cp/bindings/zephyr_kernel/__init__.h b/ports/zephyr-cp/bindings/zephyr_kernel/__init__.h new file mode 100644 index 0000000000000..3215711bbf346 --- /dev/null +++ b/ports/zephyr-cp/bindings/zephyr_kernel/__init__.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/mpconfig.h" +#include "py/obj.h" + +#include "common-hal/zephyr_kernel/__init__.h" + +void raise_zephyr_error(int err); +#define CHECK_ZEPHYR_RESULT(x) do { int res = (x); if (res < 0) raise_zephyr_error(res); } while (0) diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..989332a143103 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather Bluefruit Sense" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = false +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = false diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..eacb0f9607df9 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_sense_zephyr/circuitpython.toml @@ -0,0 +1,4 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +USB_VID=0x239A +USB_PID=0x8088 +NAME="Feather Bluefruit Sense" diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..51c02dad4cf30 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather nRF52840 Express" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..c4d1099a77e1d --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_nrf52840_zephyr/circuitpython.toml @@ -0,0 +1,4 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +USB_VID=0x239A +USB_PID=0x802A +NAME="Feather nRF52840 Express" diff --git a/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..c1d6e2ed3ce8f --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Adafruit Industries LLC Feather RP2040" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..9d3c229ed1b45 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit/feather_rp2040_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf new file mode 100644 index 0000000000000..20176b34be052 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_USE_DT_CODE_PARTITION=y + +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay new file mode 100644 index 0000000000000..e01ebd6df1f51 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_nrf52840_sense_uf2.overlay @@ -0,0 +1,46 @@ +/ { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + }; +}; + +&zephyr_udc0 { + /delete-node/ board_cdc_acm_uart; +}; + + +&gd25q16 { + /delete-node/ partitions; +}; + +/delete-node/ &storage_partition; +/delete-node/ &code_partition; + +&flash0 { + partitions { + code_partition: partition@26000 { + label = "Application"; + reg = <0x00026000 0x000c4000>; + }; + + storage_partition: partition@ea000 { + label = "storage"; + reg = <0x000ea000 0x00008000>; + }; + + nvm_partition: partition@f2000 { + label = "nvm"; + reg = <0x000f2000 0x00002000>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf new file mode 100644 index 0000000000000..20176b34be052 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.conf @@ -0,0 +1,10 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_USE_DT_CODE_PARTITION=y + +CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n diff --git a/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay new file mode 100644 index 0000000000000..e01ebd6df1f51 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_nrf52840_uf2.overlay @@ -0,0 +1,46 @@ +/ { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-mcumgr = &uart0; + zephyr,bt-mon-uart = &uart0; + zephyr,bt-c2h-uart = &uart0; + }; +}; + +&zephyr_udc0 { + /delete-node/ board_cdc_acm_uart; +}; + + +&gd25q16 { + /delete-node/ partitions; +}; + +/delete-node/ &storage_partition; +/delete-node/ &code_partition; + +&flash0 { + partitions { + code_partition: partition@26000 { + label = "Application"; + reg = <0x00026000 0x000c4000>; + }; + + storage_partition: partition@ea000 { + label = "storage"; + reg = <0x000ea000 0x00008000>; + }; + + nvm_partition: partition@f2000 { + label = "nvm"; + reg = <0x000f2000 0x00002000>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf b/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf new file mode 100644 index 0000000000000..91c3c15b37d1e --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_rp2040.conf @@ -0,0 +1 @@ +CONFIG_GPIO=y diff --git a/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay b/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay new file mode 100644 index 0000000000000..ce9083dd62d42 --- /dev/null +++ b/ports/zephyr-cp/boards/adafruit_feather_rp2040.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(2) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/board_aliases.cmake b/ports/zephyr-cp/boards/board_aliases.cmake new file mode 100644 index 0000000000000..ad0c1b5a57acf --- /dev/null +++ b/ports/zephyr-cp/boards/board_aliases.cmake @@ -0,0 +1,53 @@ +# Workaround for Zephyr alias handling with BOARD_QUALIFIERS in newer Zephyr. +# +# Instead of using _BOARD_ALIAS variables, translate BOARD directly so +# we don't end up with a spurious trailing '/' in BOARD_QUALIFIERS. +macro(cp_board_alias alias target) + if(BOARD STREQUAL "${alias}") + if(NOT "${target}" MATCHES "^([^@/]+)(@[^@/]+)?(/([^@]+))?$") + message(FATAL_ERROR "Invalid alias target '${target}'") + endif() + + set(BOARD_ALIAS "${alias}" CACHE STRING "Board alias, provided by user") + set(BOARD "${CMAKE_MATCH_1}") + + if(CMAKE_MATCH_2) + string(REPLACE "@" "" _rev "${CMAKE_MATCH_2}") + set(BOARD_REVISION "${_rev}") + else() + unset(BOARD_REVISION) + endif() + + if(CMAKE_MATCH_4) + set(BOARD_QUALIFIERS "${CMAKE_MATCH_4}") + else() + unset(BOARD_QUALIFIERS) + endif() + endif() +endmacro() + +cp_board_alias(pca10056 nrf52840dk/nrf52840) +cp_board_alias(adafruit_feather_nrf52840_zephyr adafruit_feather_nrf52840/nrf52840/uf2) +cp_board_alias(adafruit_feather_nrf52840_sense_zephyr adafruit_feather_nrf52840/nrf52840/sense/uf2) +cp_board_alias(adafruit_feather_rp2040_zephyr adafruit_feather_rp2040/rp2040) +cp_board_alias(renesas_ek_ra6m5 ek_ra6m5) +cp_board_alias(renesas_ek_ra8d1 ek_ra8d1) +cp_board_alias(renesas_da14695_dk_usb da14695_dk_usb) +cp_board_alias(native_native_sim native_sim/native) +cp_board_alias(native_nrf5340bsim nrf5340bsim/nrf5340/cpuapp) +cp_board_alias(nordic_nrf54l15dk nrf54l15dk/nrf54l15/cpuapp) +cp_board_alias(nordic_nrf54h20dk nrf54h20dk/nrf54h20/cpuapp) +cp_board_alias(nordic_nrf5340dk nrf5340dk/nrf5340/cpuapp) +cp_board_alias(nordic_nrf7002dk nrf7002dk/nrf5340/cpuapp) +cp_board_alias(nxp_frdm_mcxn947 frdm_mcxn947/mcxn947/cpu0) +cp_board_alias(nxp_frdm_rw612 frdm_rw612) +cp_board_alias(nxp_mimxrt1170_evk mimxrt1170_evk@A/mimxrt1176/cm7) +cp_board_alias(st_stm32h7b3i_dk stm32h7b3i_dk) +cp_board_alias(st_stm32h750b_dk stm32h750b_dk/stm32h750xx/ext_flash_app) +cp_board_alias(st_stm32wba65i_dk1 stm32wba65i_dk1) +cp_board_alias(st_nucleo_u575zi_q nucleo_u575zi_q/stm32u575xx) +cp_board_alias(raspberrypi_rpi_pico_zephyr rpi_pico/rp2040) +cp_board_alias(raspberrypi_rpi_pico_w_zephyr rpi_pico/rp2040/w) +cp_board_alias(raspberrypi_rpi_pico2_zephyr rpi_pico2/rp2350a/m33) +cp_board_alias(raspberrypi_rpi_pico2_w_zephyr rpi_pico2/rp2350a/m33/w) +cp_board_alias(st_nucleo_n657x0_q nucleo_n657x0_q/stm32n657xx) diff --git a/ports/zephyr-cp/boards/da14695_dk_usb.conf b/ports/zephyr-cp/boards/da14695_dk_usb.conf new file mode 100644 index 0000000000000..145a93934070f --- /dev/null +++ b/ports/zephyr-cp/boards/da14695_dk_usb.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/da14695_dk_usb.overlay b/ports/zephyr-cp/boards/da14695_dk_usb.overlay new file mode 100644 index 0000000000000..fbc1817c759c6 --- /dev/null +++ b/ports/zephyr-cp/boards/da14695_dk_usb.overlay @@ -0,0 +1,10 @@ +&flash0 { + partitions{ + circuitpy_partition: partition@118000 { + label = "circuitpy"; + reg = <0x118000 (DT_SIZE_M(4) - DT_SIZE_K(1120))>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/ek_ra8d1.conf b/ports/zephyr-cp/boards/ek_ra8d1.conf new file mode 100644 index 0000000000000..f979d31e751f1 --- /dev/null +++ b/ports/zephyr-cp/boards/ek_ra8d1.conf @@ -0,0 +1,3 @@ + +# Enable Zephyr display subsystem so DT chosen zephyr,display creates a device. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/ek_ra8d1.overlay b/ports/zephyr-cp/boards/ek_ra8d1.overlay new file mode 100644 index 0000000000000..c13dfc457f508 --- /dev/null +++ b/ports/zephyr-cp/boards/ek_ra8d1.overlay @@ -0,0 +1,5 @@ +&s28hl512t { + /delete-node/ partitions; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf new file mode 100644 index 0000000000000..61f2d18ca3c78 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.conf @@ -0,0 +1 @@ +CONFIG_DMA_TCD_QUEUE_SIZE=4 diff --git a/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 0000000000000..83242201c5b12 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,5 @@ +&w25q64jvssiq { + /delete-node/ partitions; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/frdm_rw612.conf b/ports/zephyr-cp/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..ac9a43646a18c --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612.conf @@ -0,0 +1,47 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_RSA_C=y +CONFIG_MBEDTLS_PKCS1_V15=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y +CONFIG_MBEDTLS_CTR_DRBG_C=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n + +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=8 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 + +CONFIG_UDC_WORKQUEUE_STACK_SIZE=1024 diff --git a/ports/zephyr-cp/boards/frdm_rw612.overlay b/ports/zephyr-cp/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..c6a021d999956 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612.overlay @@ -0,0 +1,11 @@ +&w25q512jvfiq { + partitions { + /delete-node/ partition@620000; + circuitpy_partition: partition@620000 { + label = "circuitpy"; + reg = <0x00620000 (DT_SIZE_M(58) - DT_SIZE_K(128))>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay b/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay new file mode 100644 index 0000000000000..9c517e4325514 --- /dev/null +++ b/ports/zephyr-cp/boards/frdm_rw612_rw612_cpu0.overlay @@ -0,0 +1,12 @@ +&w25q512jvfiq { + partitions { + /delete-node/ storage_partition; + circuitpy_partition: partition@620000 { + label = "circuitpy"; + reg = <0x00620000 (DT_SIZE_M(58) - DT_SIZE_K(128))>; + }; + } + +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 0000000000000..61f2d18ca3c78 --- /dev/null +++ b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1 @@ +CONFIG_DMA_TCD_QUEUE_SIZE=4 diff --git a/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay new file mode 100644 index 0000000000000..ac6fdd8654e29 --- /dev/null +++ b/ports/zephyr-cp/boards/mimxrt1170_evk_mimxrt1176_cm7.overlay @@ -0,0 +1,15 @@ +&is25wp128 { + partitions { + /delete-node/ partition@e20000; + circuitpy_partition: partition@e20000 { + label = "circuitpy"; + reg = <0x00e20000 (DT_SIZE_M(2) - DT_SIZE_K(128))>; + }; + }; +}; + +&sai1 { + mclk-output; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml b/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml new file mode 100644 index 0000000000000..b293424b539fc --- /dev/null +++ b/ports/zephyr-cp/boards/native/native_sim/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "POSIX/Native Boards Native simulator - native_sim" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio +audioio = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has displayio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = true # Zephyr board has hostnetwork +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = true # Zephyr board has audiobusio +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = true # Zephyr board has zephyr_display +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml b/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml new file mode 100644 index 0000000000000..fbda7c563b835 --- /dev/null +++ b/ports/zephyr-cp/boards/native/native_sim/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "exe"] diff --git a/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml b/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml new file mode 100644 index 0000000000000..6d6d5841bbc5f --- /dev/null +++ b/ports/zephyr-cp/boards/native/nrf5340bsim/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "POSIX/Native Boards nRF5340 simulated boards (BabbleSim)" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml b/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml new file mode 100644 index 0000000000000..3272dd4c5f319 --- /dev/null +++ b/ports/zephyr-cp/boards/native/nrf5340bsim/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/native_sim.conf b/ports/zephyr-cp/boards/native_sim.conf new file mode 100644 index 0000000000000..e02cd0ac84eb2 --- /dev/null +++ b/ports/zephyr-cp/boards/native_sim.conf @@ -0,0 +1,43 @@ +CONFIG_EMUL=y +CONFIG_GPIO=y +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=n + +# So we can test safe mode +CONFIG_NATIVE_SIM_REBOOT=y + +CONFIG_TRACING=y +CONFIG_TRACING_PERFETTO=y +CONFIG_TRACING_SYNC=y +CONFIG_TRACING_BACKEND_POSIX=y +CONFIG_TRACING_GPIO=y + +# I2C emulation for testing +CONFIG_I2C_EMUL=y + +# Display emulation for display/terminal golden tests. +CONFIG_DISPLAY=y +CONFIG_SDL_DISPLAY=y + +# EEPROM emulation for testing +CONFIG_EEPROM=y +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT2X_EMUL=y + +# I2S SDL emulation for audio testing +CONFIG_I2S_SDL=y + +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_ETH_NATIVE_TAP=n +CONFIG_NET_DRIVERS=y +CONFIG_NET_SOCKETS_OFFLOAD=y +CONFIG_NET_NATIVE_OFFLOADED_SOCKETS=y +CONFIG_HEAP_MEM_POOL_SIZE=1024 + +CONFIG_NET_LOG=y + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_SHA256=y diff --git a/ports/zephyr-cp/boards/native_sim.overlay b/ports/zephyr-cp/boards/native_sim.overlay new file mode 100644 index 0000000000000..aee9d17f9d099 --- /dev/null +++ b/ports/zephyr-cp/boards/native_sim.overlay @@ -0,0 +1,56 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Device tree overlay for CircuitPython on native_sim. + * Adds simulated SRAM region required by CircuitPython build system. + */ + +#include + +/ { + sram0: memory@20000000 { + device_type = "memory"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_M(1)>; + zephyr,memory-region = "SRAM"; + }; + + chosen { + zephyr,sram = &sram0; + /delete-property/ zephyr,flash; + /delete-property/ zephyr,code-partition; + }; +}; + +&flash0 { + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + circuitpy_partition: partition@0 { + label = "circuitpy"; + reg = <0x00000000 DT_SIZE_K(2040)>; + }; + + nvm_partition: partition@1fe000 { + label = "nvm"; + reg = <0x001fe000 0x00002000>; + }; + }; +}; + +/* Add emulated I2C devices for testing */ +&i2c0 { + at24_eeprom: eeprom@50 { + compatible = "atmel,at24"; + reg = <0x50>; + size = <256>; + pagesize = <8>; + address-width = <8>; + timeout = <5>; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml new file mode 100644 index 0000000000000..b5d36e615669b --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf5340dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Nordic Semiconductor nRF5340 DK" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio +audioio = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = true # Zephyr board has audiobusio +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf5340dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf5340dk/circuitpython.toml new file mode 100644 index 0000000000000..bf17d26d91bc8 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf5340dk/circuitpython.toml @@ -0,0 +1,3 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +USB_VID=0x239A +USB_PID=0x8166 diff --git a/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml new file mode 100644 index 0000000000000..2c72ba1570de2 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf54h20dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Nordic Semiconductor nRF54H20 DK" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml new file mode 100644 index 0000000000000..3272dd4c5f319 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf54h20dk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml new file mode 100644 index 0000000000000..d981883bf65d2 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf54l15dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Nordic Semiconductor nRF54L15 DK" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nordic/nrf54l15dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf54l15dk/circuitpython.toml new file mode 100644 index 0000000000000..3272dd4c5f319 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf54l15dk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml b/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml new file mode 100644 index 0000000000000..5faed268cdb7d --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf7002dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Nordic Semiconductor nRF7002 DK" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = false +adafruit_pixelbuf = false +aesio = false +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = false diff --git a/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml b/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml new file mode 100644 index 0000000000000..191ed9d2d2c52 --- /dev/null +++ b/ports/zephyr-cp/boards/nordic/nrf7002dk/circuitpython.toml @@ -0,0 +1,5 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +USB_VID=0x239A +USB_PID=0x8168 +BLOBS=["nrf_wifi"] +DISABLED_MODULES=["aesio", "adafruit_bus_device", "zlib"] diff --git a/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..57628a61e2057 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,35 @@ +# Configuration for nrf5340bsim simulated board +# Mirror settings from native_sim.conf for compatibility + +CONFIG_GPIO=y + +# Enable Bluetooth stack - bsim is for BT simulation +CONFIG_BT=y +CONFIG_BT_HCI=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_BROADCASTER=y + +CONFIG_BT_L2CAP_TX_MTU=253 +CONFIG_BT_BUF_CMD_TX_COUNT=2 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_HCI_VS=y +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 + +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 + +# Ensure the network core image starts when using native simulator +CONFIG_NATIVE_SIMULATOR_AUTOSTART_MCU=y + +CONFIG_TRACING=y +CONFIG_TRACING_PERFETTO=y +CONFIG_TRACING_SYNC=y +CONFIG_TRACING_BACKEND_POSIX=y +CONFIG_TRACING_GPIO=y diff --git a/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..eeb043c6f3ce3 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340bsim_nrf5340_cpuapp.overlay @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/ { + chosen { + zephyr,sram = &sram0; + }; +}; + +&sram0 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "SRAM"; +}; + +&flash0 { + /delete-node/ partitions; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + circuitpy_partition: partition@0 { + label = "circuitpy"; + reg = <0x00000000 DT_SIZE_K(1024)>; + }; + }; +}; + +/* Note: bsim doesn't have USB, so we don't include app.overlay */ diff --git a/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..145a93934070f --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..eb899df8cc9ea --- /dev/null +++ b/ports/zephyr-cp/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,24 @@ +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + , + ; + }; + }; +}; + +&clock { + hfclkaudio-frequency = <11289600>; +}; + +i2s_rxtx: &i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; + clock-source = "ACLK"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 0000000000000..a55b90c50e747 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,8 @@ +CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE=4096 + +# Reduce flash usage for this board. +CONFIG_LOG=y +CONFIG_LOG_MAX_LEVEL=2 +CONFIG_ASSERT=n +CONFIG_FRAME_POINTER=n +CONFIG_HW_STACK_PROTECTION=n diff --git a/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..a70eede551ed8 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,47 @@ +&gpio6 { + status = "okay"; + zephyr,pm-device-runtime-auto; +}; + +&exmif { + status = "okay"; + zephyr,pm-device-runtime-auto; +}; + +&mx25uw63 { + status = "okay"; +}; + +/* + * SDA = P2.11 + * SCL = P2.10 + */ + +&pinctrl { + i2c130_default: i2c130_default { + group1 { + psels = , + ; + }; + }; + + i2c130_sleep: i2c130_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c130 { + clock-frequency = ; + pinctrl-0 = <&i2c130_default>; + pinctrl-1 = <&i2c130_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + memory-regions = <&cpuapp_dma_region>; + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/ports/zephyr-cp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..39db1e981afe7 --- /dev/null +++ b/ports/zephyr-cp/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1 @@ +// No app.overlay because it doesn't have USB. diff --git a/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf b/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..afb546a980d2f --- /dev/null +++ b/ports/zephyr-cp/boards/nrf7002dk_nrf5340_cpuapp.conf @@ -0,0 +1,20 @@ +CONFIG_NETWORKING=y +CONFIG_WIFI=y + +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 + +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_LOG=n +CONFIG_ASSERT=n +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml new file mode 100644 index 0000000000000..8105f7731daae --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "NXP Semiconductors FRDM-MCXN947" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio +audioio = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = true # Zephyr board has audiobusio +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nxp/frdm_mcxn947/circuitpython.toml b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/circuitpython.toml new file mode 100644 index 0000000000000..3272dd4c5f319 --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_mcxn947/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml new file mode 100644 index 0000000000000..a23bc81503c2d --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_rw612/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "NXP Semiconductors FRDM-RW612" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml b/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml new file mode 100644 index 0000000000000..9bceea470cab1 --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/frdm_rw612/circuitpython.toml @@ -0,0 +1,5 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +BLOBS=["hal_nxp"] + +[blob_fetch_args] +hal_nxp = ["--allow-regex", "^rw61x/"] diff --git a/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml new file mode 100644 index 0000000000000..e97292fee76cb --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "NXP Semiconductors MIMXRT1170-EVK" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = true # Zephyr board has audiobusio +audiocore = true # Zephyr board has audiobusio +audiodelays = true # Zephyr board has audiobusio +audiofilters = true # Zephyr board has audiobusio +audiofreeverb = true # Zephyr board has audiobusio +audioio = false +audiomixer = true # Zephyr board has audiobusio +audiomp3 = true # Zephyr board has audiobusio +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = true # Zephyr board has audiobusio +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/circuitpython.toml b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/circuitpython.toml new file mode 100644 index 0000000000000..3272dd4c5f319 --- /dev/null +++ b/ports/zephyr-cp/boards/nxp/mimxrt1170_evk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..83b54ae2fa269 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico 2" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..0f901d1149ea3 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_w_zephyr/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +BLOBS=["hal_infineon"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..65c5bc003aea5 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico 2" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..9d3c229ed1b45 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico2_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..97288095e000f --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true # Zephyr networking enabled +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = true # Zephyr networking enabled +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = true # Zephyr networking enabled +spitarget = false +ssl = true # Zephyr networking enabled +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = true # Zephyr board has wifi +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..0f901d1149ea3 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_w_zephyr/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] +BLOBS=["hal_infineon"] diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml new file mode 100644 index 0000000000000..18e1fc835657b --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Raspberry Pi Foundation Raspberry Pi Pico" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = true # Zephyr board has nvm +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml new file mode 100644 index 0000000000000..9d3c229ed1b45 --- /dev/null +++ b/ports/zephyr-cp/boards/raspberrypi/rpi_pico_zephyr/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf", "uf2"] diff --git a/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml new file mode 100644 index 0000000000000..529254cfec271 --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Renesas Electronics Corporation DA14695 Development Kit USB" + +[modules] +__future__ = true +_bleio = true # Zephyr board has _bleio +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml new file mode 100644 index 0000000000000..f7fad6bc4443a --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/da14695_dk_usb/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +BLOBS=["hal_renesas"] diff --git a/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml new file mode 100644 index 0000000000000..7a1c0bfd21e31 --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/ek_ra6m5/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Renesas Electronics Corporation RA6M5 Evaluation Kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/ek_ra6m5/circuitpython.toml b/ports/zephyr-cp/boards/renesas/ek_ra6m5/circuitpython.toml new file mode 100644 index 0000000000000..13ff40aa042db --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/ek_ra6m5/circuitpython.toml @@ -0,0 +1,3 @@ +# TX is on pin P411. RX is on pin P410. + +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] diff --git a/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml b/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml new file mode 100644 index 0000000000000..185859b080756 --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/ek_ra8d1/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "Renesas Electronics Corporation RA8D1 Evaluation Kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has displayio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = true # Zephyr board has zephyr_display +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml b/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml new file mode 100644 index 0000000000000..0e19d8d71574e --- /dev/null +++ b/ports/zephyr-cp/boards/renesas/ek_ra8d1/circuitpython.toml @@ -0,0 +1,2 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["elf"] +SHIELDS = ["rtkmipilcdb00000be"] diff --git a/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf b/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf new file mode 100644 index 0000000000000..145a93934070f --- /dev/null +++ b/ports/zephyr-cp/boards/renesas_da14695_dk_usb.conf @@ -0,0 +1,20 @@ +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay new file mode 100644 index 0000000000000..eb94fe7de675a --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33.overlay @@ -0,0 +1,25 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + code_partition: partition@0 { + label = "code-partition"; + reg = <0x0 0x180000>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(4) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf new file mode 100644 index 0000000000000..1a0d0010dca2a --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.conf @@ -0,0 +1,24 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_RSA_C=y +CONFIG_MBEDTLS_PKCS1_V15=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y +CONFIG_MBEDTLS_CTR_DRBG_C=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n diff --git a/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay new file mode 100644 index 0000000000000..eb94fe7de675a --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico2_rp2350a_m33_w.overlay @@ -0,0 +1,25 @@ +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + code_partition: partition@0 { + label = "code-partition"; + reg = <0x0 0x180000>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(4) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay b/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay new file mode 100644 index 0000000000000..ce9083dd62d42 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(2) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf new file mode 100644 index 0000000000000..11d26d946b16d --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.conf @@ -0,0 +1,26 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_NET_SOCKETS=y + +CONFIG_WIFI=y +CONFIG_NET_L2_WIFI_MGMT=y +CONFIG_NET_MGMT_EVENT=y +CONFIG_NET_MGMT_EVENT_INFO=y + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_RSA_C=y +CONFIG_MBEDTLS_PKCS1_V15=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED=y +CONFIG_MBEDTLS_ENTROPY_C=y +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y +CONFIG_MBEDTLS_CTR_DRBG_C=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n + +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay new file mode 100644 index 0000000000000..ce9083dd62d42 --- /dev/null +++ b/ports/zephyr-cp/boards/rpi_pico_rp2040_w.overlay @@ -0,0 +1,34 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + second_stage_bootloader: partition@0 { + label = "second_stage_bootloader"; + reg = <0x00000000 0x100>; + read-only; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (0x180000 - 0x100)>; + read-only; + }; + + nvm_partition: partition@180000 { + label = "nvm"; + reg = <0x180000 0x1000>; + }; + + circuitpy_partition: partition@181000 { + label = "circuitpy"; + reg = <0x181000 (DT_SIZE_M(2) - 0x181000)>; + }; + }; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml new file mode 100644 index 0000000000000..7686dbf320bce --- /dev/null +++ b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics Nucleo N657X0-Q" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/nucleo_n657x0_q/circuitpython.toml b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/circuitpython.toml new file mode 100644 index 0000000000000..83e6bcd39c4f9 --- /dev/null +++ b/ports/zephyr-cp/boards/st/nucleo_n657x0_q/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml new file mode 100644 index 0000000000000..4037dac0481ea --- /dev/null +++ b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics Nucleo U575ZI Q" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/nucleo_u575zi_q/circuitpython.toml b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/circuitpython.toml new file mode 100644 index 0000000000000..3ca45dd798b7b --- /dev/null +++ b/ports/zephyr-cp/boards/st/nucleo_u575zi_q/circuitpython.toml @@ -0,0 +1,3 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] +USB_VID=0x239A +USB_PID=0x816A diff --git a/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml new file mode 100644 index 0000000000000..1a97bb3616350 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h750b_dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics STM32H750B Discovery Kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has displayio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = false +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = true # Zephyr board has zephyr_display +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml b/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml new file mode 100644 index 0000000000000..83e6bcd39c4f9 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h750b_dk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml new file mode 100644 index 0000000000000..4723617a5a7f9 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics STM32H7B3I Discovery kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has displayio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = true # Zephyr board has flash +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = true # Zephyr board has zephyr_display +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32h7b3i_dk/circuitpython.toml b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/circuitpython.toml new file mode 100644 index 0000000000000..83e6bcd39c4f9 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32h7b3i_dk/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml new file mode 100644 index 0000000000000..749b040b6d43e --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/autogen_board_info.toml @@ -0,0 +1,120 @@ +# This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info. +name = "STMicroelectronics STM32WBA65I Discovery kit" + +[modules] +__future__ = true +_bleio = false +_eve = false +_pew = false +_pixelmap = false +_stage = false +adafruit_bus_device = true +adafruit_pixelbuf = false +aesio = true +alarm = false +analogbufio = false +analogio = false +atexit = false +audiobusio = false +audiocore = false +audiodelays = false +audiofilters = false +audiofreeverb = false +audioio = false +audiomixer = false +audiomp3 = false +audiopwmio = false +audiospeed = false +aurora_epaper = false +bitbangio = false +bitmapfilter = true # Zephyr board has busio +bitmaptools = true # Zephyr board has busio +bitops = false +board = false +busdisplay = true # Zephyr board has busio +busio = true # Zephyr board has busio +camera = false +canio = false +codeop = false +countio = false +digitalio = true +displayio = true # Zephyr board has busio +dotclockframebuffer = false +dualbank = false +epaperdisplay = true # Zephyr board has busio +floppyio = false +fontio = true # Zephyr board has busio +fourwire = true # Zephyr board has busio +framebufferio = true # Zephyr board has busio +frequencyio = false +getpass = false +gifio = false +gnss = false +hashlib = true +hostnetwork = false +i2cdisplaybus = true # Zephyr board has busio +i2cioexpander = false +i2ctarget = false +imagecapture = false +ipaddress = false +is31fl3741 = false +jpegio = false +keypad = false +keypad_demux = false +locale = false +lvfontio = true # Zephyr board has busio +math = true +max3421e = false +mcp4822 = false +mdns = false +memorymap = false +memorymonitor = false +microcontroller = true +mipidsi = false +msgpack = true +neopixel_write = false +nvm = false +onewireio = false +os = true +paralleldisplaybus = false +ps2io = false +pulseio = false +pwmio = false +qrio = false +qspibus = false +rainbowio = true +random = true +rclcpy = false +rgbmatrix = false +rotaryio = true # Zephyr board has rotaryio +rtc = false +sdcardio = true # Zephyr board has busio +sdioio = false +sharpdisplay = true # Zephyr board has busio +socketpool = false +spitarget = false +ssl = false +storage = false +struct = true +supervisor = true +synthio = false +terminalio = true # Zephyr board has busio +tilepalettemapper = true # Zephyr board has busio +time = true +touchio = false +traceback = true +uheap = false +usb = false +usb_cdc = true +usb_hid = false +usb_host = false +usb_midi = false +usb_video = false +ustack = false +vectorio = true # Zephyr board has busio +warnings = true +watchdog = false +wifi = false +zephyr_display = false +zephyr_kernel = false +zlib = true diff --git a/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml new file mode 100644 index 0000000000000..83e6bcd39c4f9 --- /dev/null +++ b/ports/zephyr-cp/boards/st/stm32wba65i_dk1/circuitpython.toml @@ -0,0 +1 @@ +CIRCUITPY_BUILD_EXTENSIONS = ["hex"] diff --git a/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf new file mode 100644 index 0000000000000..24afffb8e88ee --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.conf @@ -0,0 +1,2 @@ +# Enable Zephyr display subsystem so the built-in LTDC panel is available. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay new file mode 100644 index 0000000000000..fdb4960477b77 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h750b_dk_stm32h750xx_ext_flash_app.overlay @@ -0,0 +1,14 @@ +&ext_flash { + partitions { + /delete-node/ partition@7800000; + + circuitpy_partition: partition@7800000 { + label = "circuitpy"; + reg = <0x7800000 DT_SIZE_M(8)>; + }; + }; +}; + +&rng { + status = "okay"; +}; diff --git a/ports/zephyr-cp/boards/stm32h7b3i_dk.conf b/ports/zephyr-cp/boards/stm32h7b3i_dk.conf new file mode 100644 index 0000000000000..24afffb8e88ee --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h7b3i_dk.conf @@ -0,0 +1,2 @@ +# Enable Zephyr display subsystem so the built-in LTDC panel is available. +CONFIG_DISPLAY=y diff --git a/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay b/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay new file mode 100644 index 0000000000000..c2b5f3129c48a --- /dev/null +++ b/ports/zephyr-cp/boards/stm32h7b3i_dk.overlay @@ -0,0 +1,29 @@ +&mx25lm51245 { + /delete-node/ partitions; +}; + +&sram5 { + status = "disabled"; +}; + +&rng { + status = "okay"; +}; + +&fdcan1 { + status = "disabled"; +}; + +/ { + chosen { + /delete-property/ zephyr,canbus; + }; +}; + +zephyr_udc0: &usbotg_hs { + pinctrl-0 = <&usb_otg_hs_dm_pa11 &usb_otg_hs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/boards/stm32wba65i_dk1.conf b/ports/zephyr-cp/boards/stm32wba65i_dk1.conf new file mode 100644 index 0000000000000..55d951959e669 --- /dev/null +++ b/ports/zephyr-cp/boards/stm32wba65i_dk1.conf @@ -0,0 +1,24 @@ +# USB OTG on STM32WBA requires VOS Range 1. Keep HCLK > 16 MHz. +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=32000000 + +# Bluetooth doesn't start up for some reason. +# CONFIG_BT=y +# CONFIG_BT_PERIPHERAL=y +# CONFIG_BT_CENTRAL=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_STM32WBA_USE_TEMP_BASED_CALIB=n + +CONFIG_BT_DEVICE_APPEARANCE_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_DYNAMIC=y +CONFIG_BT_DEVICE_NAME_MAX=28 +CONFIG_BT_L2CAP_TX_MTU=253 + +# BT Buffers +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=1 +CONFIG_BT_BUF_ACL_RX_SIZE=255 diff --git a/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay b/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay new file mode 100644 index 0000000000000..3b72ffc99845c --- /dev/null +++ b/ports/zephyr-cp/boards/stm32wba65i_dk1.overlay @@ -0,0 +1,61 @@ +&flash0 { + /delete-node/ partitions; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(928)>; + }; + + storage_partition: partition@f80000 { + label = "storage"; + reg = <0x001e0000 DT_SIZE_K(64)>; + }; + + circuitpy_partition: partition@108000 { + label = "circuitpy"; + reg = <0x00108000 DT_SIZE_K(992)>; + }; + }; +}; + +&rng { + status = "okay"; +}; + +/* + * USB on STM32WBA requires VOS Range 1. Zephyr selects VOS from HCLK, and + * 16 MHz keeps it in Range 2, which trips an assertion in udc_stm32. + * Run SYSCLK from full 32 MHz HSE so VOS is set to Range 1. + */ +&clk_hse { + /delete-property/ hse-div2; +}; + +&rcc { + clock-frequency = ; + ahb5-prescaler = <1>; +}; + +zephyr_udc0: &usbotg_hs { + status = "okay"; +}; + +&otghs_phy { + /* OTG HS clock source is 32 MHz HSE */ + clocks = <&rcc STM32_CLOCK(AHB2, 15)>, + <&rcc STM32_SRC_HSE OTGHS_SEL(0)>; + clock-reference = "SYSCFG_OTG_HS_PHY_CLK_32MHz"; + status = "okay"; +}; + +#include "../app.overlay" diff --git a/ports/zephyr-cp/common-hal/_bleio/Adapter.c b/ports/zephyr-cp/common-hal/_bleio/Adapter.c new file mode 100644 index 0000000000000..d1410f02e1b12 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Adapter.c @@ -0,0 +1,679 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "py/gc.h" +#include "py/runtime.h" +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "shared-bindings/_bleio/Address.h" +#include "shared-module/_bleio/Address.h" +#include "shared-module/_bleio/ScanResults.h" +#include "supervisor/shared/tick.h" + +bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +static bool scan_callbacks_registered = false; +static bleio_scanresults_obj_t *active_scan_results = NULL; +static struct bt_le_scan_cb scan_callbacks; +static bool ble_advertising = false; +static bool ble_adapter_enabled = true; + +#define BLEIO_ADV_MAX_FIELDS 16 +#define BLEIO_ADV_MAX_DATA_LEN 31 +static struct bt_data adv_data[BLEIO_ADV_MAX_FIELDS]; +static struct bt_data scan_resp_data[BLEIO_ADV_MAX_FIELDS]; +static uint8_t adv_data_storage[BLEIO_ADV_MAX_DATA_LEN]; +static uint8_t scan_resp_storage[BLEIO_ADV_MAX_DATA_LEN]; + +static uint8_t bleio_address_type_from_zephyr(const bt_addr_le_t *addr) { + if (addr == NULL) { + return BLEIO_ADDRESS_TYPE_PUBLIC; + } + + switch (addr->type) { + case BT_ADDR_LE_PUBLIC: + case BT_ADDR_LE_PUBLIC_ID: + return BLEIO_ADDRESS_TYPE_PUBLIC; + case BT_ADDR_LE_RANDOM: + case BT_ADDR_LE_RANDOM_ID: + case BT_ADDR_LE_UNRESOLVED: + if (BT_ADDR_IS_RPA(&addr->a)) { + return BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_RESOLVABLE; + } + if (BT_ADDR_IS_NRPA(&addr->a)) { + return BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE; + } + return BLEIO_ADDRESS_TYPE_RANDOM_STATIC; + default: + return BLEIO_ADDRESS_TYPE_PUBLIC; + } +} + +static uint8_t bleio_address_type_to_zephyr(uint8_t type) { + switch (type) { + case BLEIO_ADDRESS_TYPE_PUBLIC: + return BT_ADDR_LE_PUBLIC; + case BLEIO_ADDRESS_TYPE_RANDOM_STATIC: + case BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_RESOLVABLE: + case BLEIO_ADDRESS_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE: + return BT_ADDR_LE_RANDOM; + default: + return BT_ADDR_LE_PUBLIC; + } +} + +static bleio_connection_internal_t *bleio_connection_find_by_conn(const struct bt_conn *conn) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn == conn) { + return connection; + } + } + + return NULL; +} + +static bleio_connection_internal_t *bleio_connection_track(struct bt_conn *conn) { + bleio_connection_internal_t *connection = bleio_connection_find_by_conn(conn); + if (connection == NULL) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *candidate = &bleio_connections[i]; + if (candidate->conn == NULL) { + connection = candidate; + break; + } + } + } + + if (connection == NULL) { + return NULL; + } + + if (connection->conn == NULL) { + connection->conn = bt_conn_ref(conn); + } + + return connection; +} + +static void bleio_connection_clear(bleio_connection_internal_t *self) { + if (self == NULL) { + return; + } + + if (self->conn != NULL) { + bt_conn_unref(self->conn); + self->conn = NULL; + } + + self->connection_obj = mp_const_none; +} + +static void bleio_connection_release(bleio_connection_internal_t *connection, uint8_t reason) { + if (connection == NULL) { + return; + } + + if (connection->connection_obj != mp_const_none) { + bleio_connection_obj_t *connection_obj = MP_OBJ_TO_PTR(connection->connection_obj); + connection_obj->connection = NULL; + connection_obj->disconnect_reason = reason; + } + + bleio_connection_clear(connection); + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +static void bleio_connected_cb(struct bt_conn *conn, uint8_t err) { + if (err != 0) { + return; + } + + if (bleio_connection_track(conn) == NULL) { + bt_conn_disconnect(conn, BT_HCI_ERR_CONN_LIMIT_EXCEEDED); + return; + } + + // When connectable advertising results in a connection, the controller + // auto-stops advertising. Clear our flag to match (we cannot call + // stop_advertising() here because this callback runs in Zephyr's BT + // thread context). + ble_advertising = false; + + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +static void bleio_disconnected_cb(struct bt_conn *conn, uint8_t reason) { + printk("disconnected %p\n", conn); + bleio_connection_release(bleio_connection_find_by_conn(conn), reason); +} + +BT_CONN_CB_DEFINE(bleio_connection_callbacks) = { + .connected = bleio_connected_cb, + .disconnected = bleio_disconnected_cb, +}; + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf) { + if (active_scan_results == NULL || info == NULL || buf == NULL) { + return; + } + + const bool connectable = (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0; + const bool scan_response = (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0; + const bt_addr_le_t *addr = info->addr; + + uint8_t addr_bytes[NUM_BLEIO_ADDRESS_BYTES] = {0}; + if (addr != NULL) { + memcpy(addr_bytes, addr->a.val, sizeof(addr_bytes)); + } + + shared_module_bleio_scanresults_append(active_scan_results, + supervisor_ticks_ms64(), + connectable, + scan_response, + info->rssi, + addr_bytes, + bleio_address_type_from_zephyr(addr), + buf->data, + buf->len); +} + +static void scan_timeout_cb(void) { + if (active_scan_results == NULL) { + return; + } + shared_module_bleio_scanresults_set_done(active_scan_results, true); + active_scan_results = NULL; +} + +// We need to disassemble the full advertisement packet because the Zephyr takes +// in each ADT in an array. +static size_t bleio_parse_adv_data(const uint8_t *raw, size_t raw_len, struct bt_data *out, + size_t out_len, uint8_t *storage, size_t storage_len) { + size_t count = 0; + size_t offset = 0; + size_t storage_offset = 0; + + while (offset < raw_len) { + uint8_t field_len = raw[offset]; + if (field_len == 0) { + offset++; + continue; + } + uint8_t data_len = field_len - 1; + if (offset + field_len + 1 > raw_len || + count >= out_len || + field_len < 1 || + storage_offset + data_len > storage_len) { + mp_raise_ValueError(MP_ERROR_TEXT("Invalid advertising data")); + } + uint8_t type = raw[offset + 1]; + memcpy(storage + storage_offset, raw + offset + 2, data_len); + out[count].type = type; + out[count].data_len = data_len; + out[count].data = storage + storage_offset; + storage_offset += data_len; + count++; + offset += field_len + 1; + } + + return count; +} + +static uint16_t bleio_validate_and_convert_timeout(mp_float_t timeout) { + mp_arg_validate_float_range(timeout, 0, UINT16_MAX, MP_QSTR_timeout); + + if (timeout <= 0.0f) { + return 0; + } + + const mp_int_t timeout_units = + mp_arg_validate_int_range((mp_int_t)(timeout * 100.0f + 0.5f), 1, UINT16_MAX, MP_QSTR_timeout); + + return (uint16_t)timeout_units; +} + +void common_hal_bleio_adapter_set_enabled(bleio_adapter_obj_t *self, bool enabled) { + if (enabled == ble_adapter_enabled) { + return; + } + if (enabled) { + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_clear(&bleio_connections[i]); + } + if (!bt_is_ready()) { + int err = bt_enable(NULL); + if (err != 0) { + raise_zephyr_error(err); + } + } + ble_adapter_enabled = true; + return; + } + + // On Zephyr bsim + HCI IPC, disabling and immediately re-enabling BLE can + // race endpoint rebinding during soft reload. Keep the controller running, + // but present adapter.enabled=False to CircuitPython code. + common_hal_bleio_adapter_stop_scan(self); + common_hal_bleio_adapter_stop_advertising(self); + ble_adapter_enabled = false; +} + +bool common_hal_bleio_adapter_get_enabled(bleio_adapter_obj_t *self) { + return ble_adapter_enabled; +} + +mp_int_t common_hal_bleio_adapter_get_tx_power(bleio_adapter_obj_t *self) { + struct bt_hci_cp_vs_read_tx_power_level *cp; + struct bt_hci_rp_vs_read_tx_power_level *rp; + struct net_buf *buf, *rsp = NULL; + + buf = bt_hci_cmd_alloc(K_MSEC(1000)); + if (!buf) { + mp_raise_msg(&mp_type_MemoryError, NULL); + } + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle_type = BT_HCI_VS_LL_HANDLE_TYPE_ADV; + cp->handle = 0; + + int err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL, buf, &rsp); + if (err) { + raise_zephyr_error(err); + } + + rp = (void *)rsp->data; + int8_t power = rp->tx_power_level; + net_buf_unref(rsp); + return power; +} + +void common_hal_bleio_adapter_set_tx_power(bleio_adapter_obj_t *self, mp_int_t tx_power) { + struct bt_hci_cp_vs_write_tx_power_level *cp; + struct net_buf *buf, *rsp = NULL; + + buf = bt_hci_cmd_alloc(K_MSEC(3000)); + if (!buf) { + mp_raise_msg(&mp_type_MemoryError, NULL); + } + cp = net_buf_add(buf, sizeof(*cp)); + cp->handle_type = BT_HCI_VS_LL_HANDLE_TYPE_ADV; + cp->handle = 0; + cp->tx_power_level = (int8_t)tx_power; + + int err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL, buf, &rsp); + if (err) { + raise_zephyr_error(err); + } + + net_buf_unref(rsp); +} + +bleio_address_obj_t *common_hal_bleio_adapter_get_address(bleio_adapter_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_adapter_set_address(bleio_adapter_obj_t *self, bleio_address_obj_t *address) { + mp_raise_NotImplementedError(NULL); +} + +mp_obj_str_t *common_hal_bleio_adapter_get_name(bleio_adapter_obj_t *self) { + (void)self; + const char *name = bt_get_name(); + return mp_obj_new_str(name, strlen(name)); +} + +void common_hal_bleio_adapter_set_name(bleio_adapter_obj_t *self, const char *name) { + (void)self; + size_t len = strlen(name); + int err = 0; + if (len > CONFIG_BT_DEVICE_NAME_MAX) { + char truncated[CONFIG_BT_DEVICE_NAME_MAX + 1]; + memcpy(truncated, name, CONFIG_BT_DEVICE_NAME_MAX); + truncated[CONFIG_BT_DEVICE_NAME_MAX] = '\0'; + err = bt_set_name(truncated); + } else { + err = bt_set_name(name); + } + if (err != 0) { + raise_zephyr_error(err); + } +} + +void common_hal_bleio_adapter_start_advertising(bleio_adapter_obj_t *self, + bool connectable, bool anonymous, uint32_t timeout, mp_float_t interval, + mp_buffer_info_t *advertising_data_bufinfo, + mp_buffer_info_t *scan_response_data_bufinfo, + mp_int_t tx_power, const bleio_address_obj_t *directed_to) { + (void)directed_to; + (void)interval; + + if (advertising_data_bufinfo->len > BLEIO_ADV_MAX_DATA_LEN || + scan_response_data_bufinfo->len > BLEIO_ADV_MAX_DATA_LEN) { + mp_raise_NotImplementedError(NULL); + } + + if (timeout != 0) { + mp_raise_NotImplementedError(NULL); + } + + if (ble_advertising) { + raise_zephyr_error(-EALREADY); + } + + bt_addr_le_t id_addrs[CONFIG_BT_ID_MAX]; + size_t id_count = CONFIG_BT_ID_MAX; + bt_id_get(id_addrs, &id_count); + if (id_count == 0 || bt_addr_le_eq(&id_addrs[BT_ID_DEFAULT], BT_ADDR_LE_ANY)) { + int id = bt_id_create(NULL, NULL); + if (id < 0) { + printk("Failed to create identity address: %d\n", id); + raise_zephyr_error(id); + } + } + + size_t adv_count = bleio_parse_adv_data(advertising_data_bufinfo->buf, + advertising_data_bufinfo->len, + adv_data, + BLEIO_ADV_MAX_FIELDS, + adv_data_storage, + sizeof(adv_data_storage)); + + size_t scan_resp_count = 0; + if (scan_response_data_bufinfo->len > 0) { + scan_resp_count = bleio_parse_adv_data(scan_response_data_bufinfo->buf, + scan_response_data_bufinfo->len, + scan_resp_data, + BLEIO_ADV_MAX_FIELDS, + scan_resp_storage, + sizeof(scan_resp_storage)); + } + + if (anonymous) { + mp_raise_NotImplementedError(NULL); + } + + struct bt_le_adv_param adv_params; + if (connectable) { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + BT_LE_ADV_OPT_CONN, + BT_GAP_ADV_FAST_INT_MIN_1, + BT_GAP_ADV_FAST_INT_MAX_1, + NULL); + } else if (scan_resp_count > 0) { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + BT_LE_ADV_OPT_SCANNABLE, + BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, + NULL); + } else { + adv_params = (struct bt_le_adv_param)BT_LE_ADV_PARAM_INIT( + 0, + BT_GAP_ADV_FAST_INT_MIN_2, + BT_GAP_ADV_FAST_INT_MAX_2, + NULL); + } + + common_hal_bleio_adapter_set_tx_power(self, tx_power); + + raise_zephyr_error(bt_le_adv_start(&adv_params, + adv_data, + adv_count, + scan_resp_count > 0 ? scan_resp_data : NULL, + scan_resp_count)); + + ble_advertising = true; +} + +void common_hal_bleio_adapter_stop_advertising(bleio_adapter_obj_t *self) { + (void)self; + if (!ble_advertising) { + return; + } + bt_le_adv_stop(); + ble_advertising = false; +} + +bool common_hal_bleio_adapter_get_advertising(bleio_adapter_obj_t *self) { + (void)self; + return ble_advertising; +} + +mp_obj_t common_hal_bleio_adapter_start_scan(bleio_adapter_obj_t *self, uint8_t *prefixes, size_t prefix_length, bool extended, mp_int_t buffer_size, mp_float_t timeout, mp_float_t interval, mp_float_t window, mp_int_t minimum_rssi, bool active) { + (void)extended; + + if (self->scan_results != NULL) { + if (!shared_module_bleio_scanresults_get_done(self->scan_results)) { + common_hal_bleio_adapter_stop_scan(self); + } else { + self->scan_results = NULL; + } + } + + int err = 0; + + self->scan_results = shared_module_bleio_new_scanresults(buffer_size, prefixes, prefix_length, minimum_rssi); + active_scan_results = self->scan_results; + + if (!scan_callbacks_registered) { + scan_callbacks.recv = scan_recv_cb; + scan_callbacks.timeout = scan_timeout_cb; + err = bt_le_scan_cb_register(&scan_callbacks); + if (err != 0) { + self->scan_results = NULL; + active_scan_results = NULL; + raise_zephyr_error(err); + } + scan_callbacks_registered = true; + } + + uint16_t interval_units = (uint16_t)((interval / 0.000625f) + 0.5f); + uint16_t window_units = (uint16_t)((window / 0.000625f) + 0.5f); + uint16_t timeout_units = bleio_validate_and_convert_timeout(timeout); + + struct bt_le_scan_param scan_params = { + .type = active ? BT_LE_SCAN_TYPE_ACTIVE : BT_LE_SCAN_TYPE_PASSIVE, + .options = BT_LE_SCAN_OPT_FILTER_DUPLICATE, + .interval = interval_units, + .window = window_units, + .timeout = (uint16_t)timeout_units, + .interval_coded = 0, + .window_coded = 0, + }; + + err = bt_le_scan_start(&scan_params, NULL); + if (err != 0) { + self->scan_results = NULL; + active_scan_results = NULL; + raise_zephyr_error(err); + } + + return MP_OBJ_FROM_PTR(self->scan_results); +} + +void common_hal_bleio_adapter_stop_scan(bleio_adapter_obj_t *self) { + if (self->scan_results == NULL) { + return; + } + bt_le_scan_stop(); + shared_module_bleio_scanresults_set_done(self->scan_results, true); + active_scan_results = NULL; + self->scan_results = NULL; +} + +bool common_hal_bleio_adapter_get_connected(bleio_adapter_obj_t *self) { + if (!ble_adapter_enabled) { + return false; + } + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + if (bleio_connections[i].conn != NULL) { + return true; + } + } + + return false; +} + +mp_obj_t common_hal_bleio_adapter_get_connections(bleio_adapter_obj_t *self) { + if (!ble_adapter_enabled) { + self->connection_objs = NULL; + return mp_const_empty_tuple; + } + + if (self->connection_objs != NULL) { + return self->connection_objs; + } + + size_t total_connected = 0; + mp_obj_t items[BLEIO_TOTAL_CONNECTION_COUNT]; + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn == NULL) { + continue; + } + + if (connection->connection_obj == mp_const_none) { + connection->connection_obj = bleio_connection_new_from_internal(connection); + } + + items[total_connected] = connection->connection_obj; + total_connected++; + } + + self->connection_objs = mp_obj_new_tuple(total_connected, items); + return self->connection_objs; +} + +mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { + common_hal_bleio_adapter_stop_scan(self); + + const uint16_t timeout_units = bleio_validate_and_convert_timeout(timeout); + + mp_buffer_info_t address_bufinfo; + mp_get_buffer_raise(address->bytes, &address_bufinfo, MP_BUFFER_READ); + + bt_addr_le_t peer = { + .type = bleio_address_type_to_zephyr(address->type), + }; + memcpy(peer.a.val, address_bufinfo.buf, NUM_BLEIO_ADDRESS_BYTES); + + struct bt_conn_le_create_param create_params = BT_CONN_LE_CREATE_PARAM_INIT( + BT_CONN_LE_OPT_NONE, + BT_GAP_SCAN_FAST_INTERVAL, + BT_GAP_SCAN_FAST_INTERVAL); + create_params.timeout = timeout_units; + + struct bt_conn *conn = NULL; + int err = bt_conn_le_create(&peer, &create_params, BT_LE_CONN_PARAM_DEFAULT, &conn); + if (err != 0) { + raise_zephyr_error(err); + } + + while (true) { + struct bt_conn_info info; + err = bt_conn_get_info(conn, &info); + if (err == 0) { + if (info.state == BT_CONN_STATE_CONNECTED) { + break; + } + + if (info.state == BT_CONN_STATE_DISCONNECTED) { + bt_conn_unref(conn); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: timeout")); + } + } else if (err != -ENOTCONN) { + bt_conn_unref(conn); + raise_zephyr_error(err); + } + + RUN_BACKGROUND_TASKS; + } + + bleio_connection_internal_t *connection = bleio_connection_find_by_conn(conn); + if (connection == NULL) { + connection = bleio_connection_track(conn); + } + + if (connection == NULL) { + bt_conn_unref(conn); + mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Failed to connect: internal error")); + } + + // bt_conn_le_create() gave us a ref in `conn`; `connection` keeps its own + // ref via bleio_connection_track(). Drop the create ref now. + bt_conn_unref(conn); + + self->connection_objs = NULL; + return bleio_connection_new_from_internal(connection); +} + +void common_hal_bleio_adapter_erase_bonding(bleio_adapter_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_adapter_is_bonded_to_central(bleio_adapter_obj_t *self) { + return false; +} + +void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter) { + gc_collect_root((void **)adapter, sizeof(bleio_adapter_obj_t) / sizeof(size_t)); + gc_collect_root((void **)bleio_connections, sizeof(bleio_connections) / sizeof(size_t)); +} + +void bleio_adapter_reset(bleio_adapter_obj_t *adapter) { + if (adapter == NULL) { + return; + } + + common_hal_bleio_adapter_stop_scan(adapter); + common_hal_bleio_adapter_stop_advertising(adapter); + + for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) { + bleio_connection_internal_t *connection = &bleio_connections[i]; + if (connection->conn != NULL) { + bt_conn_disconnect(connection->conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + } + if (connection->connection_obj != MP_OBJ_NULL && + connection->connection_obj != mp_const_none) { + bleio_connection_obj_t *connection_obj = MP_OBJ_TO_PTR(connection->connection_obj); + connection_obj->connection = NULL; + connection_obj->disconnect_reason = BT_HCI_ERR_REMOTE_USER_TERM_CONN; + } + bleio_connection_clear(connection); + } + + adapter->scan_results = NULL; + adapter->connection_objs = NULL; + active_scan_results = NULL; + ble_advertising = false; + ble_adapter_enabled = bt_is_ready(); +} + +bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void) { + return &common_hal_bleio_adapter_obj; +} + +uint16_t bleio_adapter_get_name(char *buf, uint16_t len) { + const char *name = bt_get_name(); + uint16_t full_len = strlen(name); + if (len > 0) { + uint16_t copy_len = len < full_len ? len : full_len; + memcpy(buf, name, copy_len); + } + return full_len; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Adapter.h b/ports/zephyr-cp/common-hal/_bleio/Adapter.h new file mode 100644 index 0000000000000..c15c698e2a525 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Adapter.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objtuple.h" + +#include "shared-bindings/_bleio/Connection.h" +#include "shared-bindings/_bleio/ScanResults.h" + +#define BLEIO_TOTAL_CONNECTION_COUNT CONFIG_BT_MAX_CONN + +extern bleio_connection_internal_t bleio_connections[BLEIO_TOTAL_CONNECTION_COUNT]; + +typedef struct { + mp_obj_base_t base; + bleio_scanresults_obj_t *scan_results; + mp_obj_t name; + mp_obj_tuple_t *connection_objs; + bool user_advertising; +} bleio_adapter_obj_t; + +void bleio_adapter_gc_collect(bleio_adapter_obj_t *adapter); +void bleio_adapter_reset(bleio_adapter_obj_t *adapter); diff --git a/ports/zephyr-cp/common-hal/_bleio/Attribute.c b/ports/zephyr-cp/common-hal/_bleio/Attribute.c new file mode 100644 index 0000000000000..6312f3d46b80f --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Attribute.c @@ -0,0 +1,8 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Attribute is defined in shared-module, no port-specific implementation needed diff --git a/ports/zephyr-cp/common-hal/_bleio/Attribute.h b/ports/zephyr-cp/common-hal/_bleio/Attribute.h new file mode 100644 index 0000000000000..24b0f78a106e5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Attribute.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/_bleio/Attribute.h" diff --git a/ports/zephyr-cp/common-hal/_bleio/Characteristic.c b/ports/zephyr-cp/common-hal/_bleio/Characteristic.c new file mode 100644 index 0000000000000..386be6004d2a1 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Characteristic.c @@ -0,0 +1,67 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Characteristic.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Service.h" + +bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) { + return self->props; +} + +mp_obj_tuple_t *common_hal_bleio_characteristic_get_descriptors(bleio_characteristic_obj_t *self) { + return mp_obj_new_tuple(self->descriptor_list->len, self->descriptor_list->items); +} + +bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { + return self->service; +} + +bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) { + return self->uuid; +} + +size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristic_obj_t *self) { + return self->max_length; +} + +size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self) { + return self->service == NULL; +} + +void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self) { + // Nothing to do +} + +void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + mp_raise_NotImplementedError(NULL); +} + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer) { + self->observer = observer; +} + +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self) { + self->observer = mp_const_none; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Characteristic.h b/ports/zephyr-cp/common-hal/_bleio/Characteristic.h new file mode 100644 index 0000000000000..b710a9f2662b8 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Characteristic.h @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objlist.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "shared-module/_bleio/Characteristic.h" +#include "common-hal/_bleio/Descriptor.h" +#include "common-hal/_bleio/Service.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct _bleio_characteristic_obj { + mp_obj_base_t base; + bleio_service_obj_t *service; + bleio_uuid_obj_t *uuid; + mp_obj_t observer; + uint8_t *current_value; + uint16_t current_value_len; + uint16_t current_value_alloc; + uint16_t max_length; + uint16_t def_handle; + uint16_t handle; + bleio_characteristic_properties_t props; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + mp_obj_list_t *descriptor_list; + uint16_t user_desc_handle; + uint16_t cccd_handle; + uint16_t sccd_handle; + bool fixed_length; +} bleio_characteristic_obj_t; + +void bleio_characteristic_set_observer(bleio_characteristic_obj_t *self, mp_obj_t observer); +void bleio_characteristic_clear_observer(bleio_characteristic_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c new file mode 100644 index 0000000000000..17e000e905eb7 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.c @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/_bleio/CharacteristicBuffer.h" + +void _common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + uint8_t *buffer, size_t buffer_size, + void *static_handler_entry, + bool watch_for_interrupt_char) { + (void)self; + (void)characteristic; + (void)timeout; + (void)buffer; + (void)buffer_size; + (void)static_handler_entry; + (void)watch_for_interrupt_char; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffer_obj_t *self, + bleio_characteristic_obj_t *characteristic, + mp_float_t timeout, + size_t buffer_size) { + (void)self; + (void)characteristic; + (void)timeout; + (void)buffer_size; + mp_raise_NotImplementedError(NULL); +} + +uint32_t common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) { + (void)self; + (void)data; + (void)len; + if (errcode != NULL) { + *errcode = MP_EAGAIN; + } + mp_raise_NotImplementedError(NULL); +} + +uint32_t common_hal_bleio_characteristic_buffer_rx_characters_available(bleio_characteristic_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_characteristic_buffer_clear_rx_buffer(bleio_characteristic_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_characteristic_buffer_deinited(bleio_characteristic_buffer_obj_t *self) { + return self->deinited; +} + +void common_hal_bleio_characteristic_buffer_deinit(bleio_characteristic_buffer_obj_t *self) { + if (self == NULL) { + return; + } + self->deinited = true; +} + +bool common_hal_bleio_characteristic_buffer_connected(bleio_characteristic_buffer_obj_t *self) { + (void)self; + return false; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h new file mode 100644 index 0000000000000..91ea262945af5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/CharacteristicBuffer.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" +#include "shared-bindings/_bleio/Characteristic.h" + +typedef struct { + mp_obj_base_t base; + bleio_characteristic_obj_t *characteristic; + bool deinited; +} bleio_characteristic_buffer_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/Connection.c b/ports/zephyr-cp/common-hal/_bleio/Connection.c new file mode 100644 index 0000000000000..938359c79caf7 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Connection.c @@ -0,0 +1,97 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include +#include + +#include "py/runtime.h" +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Connection.h" + +void common_hal_bleio_connection_pair(bleio_connection_internal_t *self, bool bond) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_connection_disconnect(bleio_connection_internal_t *self) { + if (self == NULL || self->conn == NULL) { + return; + } + + int err = bt_conn_disconnect(self->conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0 && err != -ENOTCONN) { + raise_zephyr_error(err); + } + + // The connection may now be disconnecting; force connections tuple rebuild. + common_hal_bleio_adapter_obj.connection_objs = NULL; +} + +bool common_hal_bleio_connection_get_connected(bleio_connection_obj_t *self) { + if (self == NULL || self->connection == NULL) { + return false; + } + + bleio_connection_internal_t *connection = self->connection; + if (connection->conn == NULL) { + return false; + } + + struct bt_conn_info info; + if (bt_conn_get_info(connection->conn, &info) != 0) { + return false; + } + + return info.state == BT_CONN_STATE_CONNECTED || info.state == BT_CONN_STATE_DISCONNECTING; +} + +mp_int_t common_hal_bleio_connection_get_max_packet_length(bleio_connection_internal_t *self) { + if (self == NULL || self->conn == NULL) { + return 20; + } + + uint16_t mtu = bt_gatt_get_mtu(self->conn); + if (mtu < 3) { + return 20; + } + return mtu - 3; +} + +bool common_hal_bleio_connection_get_paired(bleio_connection_obj_t *self) { + return false; +} + +mp_obj_tuple_t *common_hal_bleio_connection_discover_remote_services(bleio_connection_obj_t *self, mp_obj_t service_uuids_whitelist) { + mp_raise_NotImplementedError(NULL); +} + +mp_float_t common_hal_bleio_connection_get_connection_interval(bleio_connection_internal_t *self) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_connection_set_connection_interval(bleio_connection_internal_t *self, mp_float_t new_interval) { + mp_raise_NotImplementedError(NULL); +} + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection) { + if (connection == NULL) { + return mp_const_none; + } + + if (connection->connection_obj != mp_const_none) { + return connection->connection_obj; + } + + bleio_connection_obj_t *connection_obj = mp_obj_malloc(bleio_connection_obj_t, &bleio_connection_type); + connection_obj->connection = connection; + connection_obj->disconnect_reason = 0; + connection->connection_obj = MP_OBJ_FROM_PTR(connection_obj); + + return connection->connection_obj; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Connection.h b/ports/zephyr-cp/common-hal/_bleio/Connection.h new file mode 100644 index 0000000000000..dc14125db5f7c --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Connection.h @@ -0,0 +1,27 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +struct bt_conn; + +typedef struct { + struct bt_conn *conn; + mp_obj_t connection_obj; +} bleio_connection_internal_t; + +typedef struct { + mp_obj_base_t base; + bleio_connection_internal_t *connection; + uint8_t disconnect_reason; +} bleio_connection_obj_t; + +mp_obj_t bleio_connection_new_from_internal(bleio_connection_internal_t *connection); diff --git a/ports/zephyr-cp/common-hal/_bleio/Descriptor.c b/ports/zephyr-cp/common-hal/_bleio/Descriptor.c new file mode 100644 index 0000000000000..a3e65a5e006f6 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Descriptor.c @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Descriptor.h" +#include "shared-bindings/_bleio/Characteristic.h" + +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_characteristic_obj_t *characteristic, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo) { + mp_raise_NotImplementedError(NULL); +} + +bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { + return self->uuid; +} + +bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { + mp_raise_NotImplementedError(NULL); +} + +size_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self, uint8_t *buf, size_t len) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Descriptor.h b/ports/zephyr-cp/common-hal/_bleio/Descriptor.h new file mode 100644 index 0000000000000..1d29cb27a509b --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Descriptor.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/_bleio/Attribute.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct _bleio_descriptor_obj { + mp_obj_base_t base; + bleio_uuid_obj_t *uuid; + uint16_t handle; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; + uint16_t max_length; + bool fixed_length; + uint8_t *value; + uint16_t value_length; +} bleio_descriptor_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c new file mode 100644 index 0000000000000..82fe8a3d1760c --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.c @@ -0,0 +1,66 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/PacketBuffer.h" + +void common_hal_bleio_packet_buffer_construct( + bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, + size_t buffer_size, size_t max_packet_size) { + (void)self; + (void)characteristic; + (void)buffer_size; + (void)max_packet_size; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, const uint8_t *data, size_t len, uint8_t *header, size_t header_len) { + (void)self; + (void)data; + (void)len; + (void)header; + (void)header_len; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len) { + (void)self; + (void)data; + (void)len; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self) { + (void)self; + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self) { + return self->deinited; +} + +void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self) { + if (self == NULL) { + return; + } + self->deinited = true; +} + +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self) { + (void)self; + return false; +} diff --git a/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h new file mode 100644 index 0000000000000..c8cd763fd6146 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/PacketBuffer.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +typedef struct _bleio_characteristic_obj bleio_characteristic_obj_t; + +typedef void *ble_event_handler_t; + +typedef struct { + mp_obj_base_t base; + bool deinited; +} bleio_packet_buffer_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/Service.c b/ports/zephyr-cp/common-hal/_bleio/Service.c new file mode 100644 index 0000000000000..cefc85b6df655 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Service.c @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/Service.h" +#include "shared-bindings/_bleio/Characteristic.h" + +uint32_t _common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary, mp_obj_list_t *characteristic_list) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, bool is_secondary) { + mp_raise_NotImplementedError(NULL); +} + +void common_hal_bleio_service_deinit(bleio_service_obj_t *self) { + // Nothing to do +} + +void common_hal_bleio_service_from_remote_service(bleio_service_obj_t *self, bleio_connection_obj_t *connection, bleio_uuid_obj_t *uuid, bool is_secondary) { + mp_raise_NotImplementedError(NULL); +} + +bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { + return self->uuid; +} + +mp_obj_tuple_t *common_hal_bleio_service_get_characteristics(bleio_service_obj_t *self) { + return mp_obj_new_tuple(self->characteristic_list->len, self->characteristic_list->items); +} + +bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) { + return self->is_remote; +} + +bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { + return self->is_secondary; +} + +void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *initial_value_bufinfo, const char *user_description) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/Service.h b/ports/zephyr-cp/common-hal/_bleio/Service.h new file mode 100644 index 0000000000000..86727d3b0f73b --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/Service.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "py/objlist.h" +#include "common-hal/_bleio/UUID.h" + +typedef struct bleio_service_obj { + mp_obj_base_t base; + bleio_uuid_obj_t *uuid; + mp_obj_t connection; + mp_obj_list_t *characteristic_list; + uint16_t start_handle; + uint16_t end_handle; + bool is_remote; + bool is_secondary; +} bleio_service_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/UUID.c b/ports/zephyr-cp/common-hal/_bleio/UUID.c new file mode 100644 index 0000000000000..916eedb2c4745 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/UUID.c @@ -0,0 +1,52 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/runtime.h" +#include "shared-bindings/_bleio/UUID.h" + +void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, mp_int_t uuid16, const uint8_t uuid128[16]) { + if (uuid16 != 0) { + // 16-bit UUID + self->size = 16; + // Convert 16-bit UUID to 128-bit + // Bluetooth Base UUID: 00000000-0000-1000-8000-00805F9B34FB + const uint8_t base_uuid[16] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + memcpy(self->uuid128, base_uuid, 16); + self->uuid128[12] = (uuid16 & 0xff); + self->uuid128[13] = (uuid16 >> 8) & 0xff; + } else { + // 128-bit UUID + self->size = 128; + memcpy(self->uuid128, uuid128, 16); + } +} + +uint32_t common_hal_bleio_uuid_get_uuid16(bleio_uuid_obj_t *self) { + if (self->size == 16) { + return (self->uuid128[13] << 8) | self->uuid128[12]; + } + return 0; +} + +void common_hal_bleio_uuid_get_uuid128(bleio_uuid_obj_t *self, uint8_t uuid128[16]) { + memcpy(uuid128, self->uuid128, 16); +} + +uint32_t common_hal_bleio_uuid_get_size(bleio_uuid_obj_t *self) { + return self->size; +} + +void common_hal_bleio_uuid_pack_into(bleio_uuid_obj_t *self, uint8_t *buf) { + if (self->size == 16) { + buf[0] = self->uuid128[12]; + buf[1] = self->uuid128[13]; + } else { + memcpy(buf, self->uuid128, 16); + } +} diff --git a/ports/zephyr-cp/common-hal/_bleio/UUID.h b/ports/zephyr-cp/common-hal/_bleio/UUID.h new file mode 100644 index 0000000000000..386f5a7b8b971 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/UUID.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t uuid128[16]; + uint8_t size; +} bleio_uuid_obj_t; diff --git a/ports/zephyr-cp/common-hal/_bleio/__init__.c b/ports/zephyr-cp/common-hal/_bleio/__init__.c new file mode 100644 index 0000000000000..719564c1cd47e --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/__init__.c @@ -0,0 +1,51 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "shared-bindings/_bleio/__init__.h" +#include "shared-bindings/_bleio/Adapter.h" +#include "common-hal/_bleio/Adapter.h" +#include "supervisor/shared/bluetooth/bluetooth.h" + +// The singleton _bleio.Adapter object +bleio_adapter_obj_t common_hal_bleio_adapter_obj; + +void common_hal_bleio_init(void) { + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; + bleio_adapter_reset(&common_hal_bleio_adapter_obj); +} + +void bleio_user_reset(void) { + if (common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + // Stop any user scanning or advertising. + common_hal_bleio_adapter_stop_scan(&common_hal_bleio_adapter_obj); + common_hal_bleio_adapter_stop_advertising(&common_hal_bleio_adapter_obj); + } + + // Maybe start advertising the BLE workflow. + supervisor_bluetooth_background(); +} + +void bleio_reset(void) { + common_hal_bleio_adapter_obj.base.type = &bleio_adapter_type; + if (!common_hal_bleio_adapter_get_enabled(&common_hal_bleio_adapter_obj)) { + return; + } + + supervisor_stop_bluetooth(); + bleio_adapter_reset(&common_hal_bleio_adapter_obj); + common_hal_bleio_adapter_set_enabled(&common_hal_bleio_adapter_obj, false); + supervisor_start_bluetooth(); +} + +void common_hal_bleio_gc_collect(void) { + bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj); +} + +void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) { + mp_raise_NotImplementedError(NULL); +} diff --git a/ports/zephyr-cp/common-hal/_bleio/__init__.h b/ports/zephyr-cp/common-hal/_bleio/__init__.h new file mode 100644 index 0000000000000..1502767c61597 --- /dev/null +++ b/ports/zephyr-cp/common-hal/_bleio/__init__.h @@ -0,0 +1,10 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2018 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Placeholder for Zephyr-specific BLE defines diff --git a/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c new file mode 100644 index 0000000000000..e858552c524c0 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.c @@ -0,0 +1,299 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiobusio/I2SOut.h" + +#include +#include +#include +#include +#include + +#include "bindings/zephyr_kernel/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" +#include "py/runtime.h" + +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +#define AUDIO_THREAD_STACK_SIZE 2048 +#define AUDIO_THREAD_PRIORITY 5 + +// Forward declarations +static void fill_buffer(audiobusio_i2sout_obj_t *self, uint8_t *buffer, size_t buffer_size); +static void audio_thread_func(void *self_in, void *unused1, void *unused2); + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_audiobusio_i2sout_construct_from_device(audiobusio_i2sout_obj_t *self, const struct device *i2s_device) { + self->base.type = &audiobusio_i2sout_type; + self->i2s_dev = i2s_device; + self->left_justified = false; + self->playing = false; + self->paused = false; + self->sample = NULL; + self->slab_buffer = NULL; + self->thread_stack = NULL; + self->thread_id = NULL; + self->block_size = 0; + + return MP_OBJ_FROM_PTR(self); +} + +// Standard audiobusio construct - not used in Zephyr port (devices come from device tree) +void common_hal_audiobusio_i2sout_construct(audiobusio_i2sout_obj_t *self, + const mcu_pin_obj_t *bit_clock, const mcu_pin_obj_t *word_select, + const mcu_pin_obj_t *data, const mcu_pin_obj_t *main_clock, bool left_justified) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Use device tree to define %q devices"), MP_QSTR_I2S); +} + +bool common_hal_audiobusio_i2sout_deinited(audiobusio_i2sout_obj_t *self) { + return self->i2s_dev == NULL; +} + +void common_hal_audiobusio_i2sout_deinit(audiobusio_i2sout_obj_t *self) { + if (common_hal_audiobusio_i2sout_deinited(self)) { + return; + } + + // Stop playback (which will free buffers) + common_hal_audiobusio_i2sout_stop(self); + + // Note: Pins and I2S device are managed by Zephyr, not released here + self->i2s_dev = NULL; +} + +static void fill_buffer(audiobusio_i2sout_obj_t *self, uint8_t *buffer, size_t buffer_size) { + if (self->sample == NULL || self->paused || self->stopping) { + // Fill with silence + memset(buffer, 0, buffer_size); + return; + } + + uint32_t bytes_filled = 0; + while (bytes_filled < buffer_size) { + uint8_t *sample_buffer; + uint32_t sample_buffer_length; + + audioio_get_buffer_result_t result = audiosample_get_buffer( + self->sample, false, 0, &sample_buffer, &sample_buffer_length); + + if (result == GET_BUFFER_ERROR) { + // Error getting buffer, stop playback + self->stopping = true; + memset(buffer + bytes_filled, 0, buffer_size - bytes_filled); + return; + } + + if (result == GET_BUFFER_DONE) { + if (self->loop) { + // Reset to beginning + audiosample_reset_buffer(self->sample, false, 0); + } else { + // Done playing, fill rest with silence + self->stopping = true; + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DRAIN); + memset(buffer + bytes_filled, 0, buffer_size - bytes_filled); + return; + } + } + + // Copy data to buffer + uint32_t bytes_to_copy = sample_buffer_length; + if (bytes_filled + bytes_to_copy > buffer_size) { + bytes_to_copy = buffer_size - bytes_filled; + } + + memcpy(buffer + bytes_filled, sample_buffer, bytes_to_copy); + bytes_filled += bytes_to_copy; + } +} + +static void audio_thread_func(void *self_in, void *unused1, void *unused2) { + audiobusio_i2sout_obj_t *self = (audiobusio_i2sout_obj_t *)self_in; + + while (!self->stopping) { + uint8_t *next_buffer = NULL; + // Wait until I2S has freed the buffer it is sending. + if (k_mem_slab_alloc(&self->mem_slab, (void **)&next_buffer, K_FOREVER) != 0) { + break; + } + if (self->stopping) { + // Stopping so break. + k_mem_slab_free(&self->mem_slab, next_buffer); + break; + } + fill_buffer(self, next_buffer, self->block_size); + + // Write to I2S + int ret = i2s_write(self->i2s_dev, next_buffer, self->block_size); + if (ret < 0) { + printk("i2s_write failed: %d\n", ret); + k_mem_slab_free(&self->mem_slab, next_buffer); + // Error writing, stop playback + self->playing = false; + break; + } + } +} + +void common_hal_audiobusio_i2sout_play(audiobusio_i2sout_obj_t *self, + mp_obj_t sample, bool loop) { + // Stop any existing playback + if (self->playing) { + common_hal_audiobusio_i2sout_stop(self); + } + + // Get sample information + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); + uint32_t sample_rate = audiosample_get_sample_rate(sample); + uint8_t channel_count = audiosample_get_channel_count(sample); + + // Store sample parameters + self->sample = sample; + self->loop = loop; + self->bytes_per_sample = bits_per_sample / 8; + self->channel_count = channel_count; + self->stopping = false; + + // Get buffer structure from the sample + bool single_buffer, samples_signed; + uint32_t max_buffer_length; + uint8_t sample_spacing; + audiosample_get_buffer_structure(sample, /* single_channel_output */ false, + &single_buffer, &samples_signed, &max_buffer_length, &sample_spacing); + + // Use max_buffer_length from the sample as the block size + self->block_size = max_buffer_length; + if (channel_count == 1) { + // Make room for stereo samples. + self->block_size *= 2; + } + size_t block_size = self->block_size; + uint32_t num_blocks = 4; // Use 4 blocks for buffering + + // Allocate memory slab buffer + self->slab_buffer = m_malloc(self->block_size * num_blocks); + + // Initialize memory slab + int ret = k_mem_slab_init(&self->mem_slab, self->slab_buffer, block_size, num_blocks); + CHECK_ZEPHYR_RESULT(ret); + + // Configure I2S + struct i2s_config config; + config.word_size = bits_per_sample; + config.channels = 2; + config.format = self->left_justified ? I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED : I2S_FMT_DATA_FORMAT_I2S; + config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER; + config.frame_clk_freq = sample_rate; + config.mem_slab = &self->mem_slab; + config.block_size = block_size; + config.timeout = 1000; // Not a k_timeout_t. In milliseconds. + + // Configure returns EINVAL if the I2S device is not ready. We loop on this + // because it should be ready after it comes to a complete stop. + ret = -EAGAIN; + while (ret == -EAGAIN) { + ret = i2s_configure(self->i2s_dev, I2S_DIR_TX, &config); + } + if (ret != 0) { + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + + // Fill every slab before starting playback to avoid underruns. + for (uint32_t i = 0; i < num_blocks; i++) { + uint8_t *buf = NULL; + k_mem_slab_alloc(&self->mem_slab, (void **)&buf, K_NO_WAIT); + fill_buffer(self, buf, block_size); + ret = i2s_write(self->i2s_dev, buf, block_size); + if (ret < 0) { + printk("i2s_write failed: %d\n", ret); + k_mem_slab_free(&self->mem_slab, buf); + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + } + + // Allocate thread stack with proper MPU alignment for HW stack protection + self->thread_stack = k_thread_stack_alloc(AUDIO_THREAD_STACK_SIZE, 0); + + // Create and start audio processing thread + self->thread_id = k_thread_create(&self->thread, self->thread_stack, + AUDIO_THREAD_STACK_SIZE, + audio_thread_func, + self, NULL, NULL, + AUDIO_THREAD_PRIORITY, 0, K_NO_WAIT); + // Start I2S + ret = i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START); + if (ret < 0) { + common_hal_audiobusio_i2sout_stop(self); + raise_zephyr_error(ret); + } + + self->playing = true; +} + +void common_hal_audiobusio_i2sout_stop(audiobusio_i2sout_obj_t *self) { + if (!self->playing) { + return; + } + + self->playing = false; + self->paused = false; + self->stopping = true; + + // Stop I2S + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP); + + // Wait for thread to finish + if (self->thread_id != NULL) { + k_thread_join(self->thread_id, K_FOREVER); + self->thread_id = NULL; + } + + // Free thread stack + if (self->thread_stack != NULL) { + k_thread_stack_free(self->thread_stack); + self->thread_stack = NULL; + } + + // Free buffers + if (self->slab_buffer != NULL) { + m_free(self->slab_buffer); + self->slab_buffer = NULL; + } + + self->sample = NULL; +} + +bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t *self) { + return self->playing; +} + +void common_hal_audiobusio_i2sout_pause(audiobusio_i2sout_obj_t *self) { + if (!self->playing || self->paused) { + return; + } + + self->paused = true; + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_STOP); +} + +void common_hal_audiobusio_i2sout_resume(audiobusio_i2sout_obj_t *self) { + if (!self->playing || !self->paused) { + return; + } + + self->paused = false; + // Thread will automatically resume filling buffers + i2s_trigger(self->i2s_dev, I2S_DIR_TX, I2S_TRIGGER_START); +} + +bool common_hal_audiobusio_i2sout_get_paused(audiobusio_i2sout_obj_t *self) { + return self->paused; +} + +#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT diff --git a/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h new file mode 100644 index 0000000000000..916471fa83328 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/I2SOut.h @@ -0,0 +1,47 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" +#include "shared-module/audiocore/__init__.h" + +#include +#include +#include + +#if CIRCUITPY_AUDIOBUSIO_I2SOUT + +typedef struct { + mp_obj_base_t base; + const struct device *i2s_dev; + const mcu_pin_obj_t *bit_clock; + const mcu_pin_obj_t *word_select; + const mcu_pin_obj_t *data; + const mcu_pin_obj_t *main_clock; + mp_obj_t sample; + struct k_mem_slab mem_slab; + char *slab_buffer; + struct k_thread thread; + k_thread_stack_t *thread_stack; + k_tid_t thread_id; + size_t block_size; + bool left_justified; + bool playing; + bool paused; + bool loop; + bool stopping; + bool single_buffer; + uint8_t bytes_per_sample; + uint8_t channel_count; +} audiobusio_i2sout_obj_t; + +mp_obj_t common_hal_audiobusio_i2sout_construct_from_device(audiobusio_i2sout_obj_t *self, const struct device *i2s_device); + +void i2sout_reset(void); + +#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT diff --git a/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c new file mode 100644 index 0000000000000..3d3cfef525849 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.c @@ -0,0 +1,39 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiobusio/PDMIn.h" + +#include "py/runtime.h" + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + +void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t *self, + const mcu_pin_obj_t *clock_pin, const mcu_pin_obj_t *data_pin, + uint32_t sample_rate, uint8_t bit_depth, bool mono, uint8_t oversample) { + mp_raise_NotImplementedError(NULL); +} + +bool common_hal_audiobusio_pdmin_deinited(audiobusio_pdmin_obj_t *self) { + return true; +} + +void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t *self) { +} + +uint8_t common_hal_audiobusio_pdmin_get_bit_depth(audiobusio_pdmin_obj_t *self) { + return 0; +} + +uint32_t common_hal_audiobusio_pdmin_get_sample_rate(audiobusio_pdmin_obj_t *self) { + return 0; +} + +uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t *self, + uint16_t *output_buffer, uint32_t output_buffer_length) { + return 0; +} + +#endif // CIRCUITPY_AUDIOBUSIO_PDMIN diff --git a/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h new file mode 100644 index 0000000000000..195a436f3cf61 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/PDMIn.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "common-hal/microcontroller/Pin.h" + +#if CIRCUITPY_AUDIOBUSIO_PDMIN + +typedef struct { + mp_obj_base_t base; +} audiobusio_pdmin_obj_t; + +#endif // CIRCUITPY_AUDIOBUSIO_PDMIN diff --git a/ports/zephyr-cp/common-hal/audiobusio/__init__.c b/ports/zephyr-cp/common-hal/audiobusio/__init__.c new file mode 100644 index 0000000000000..5d2e802904d01 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// No special initialization required for audiobusio diff --git a/ports/zephyr-cp/common-hal/audiobusio/__init__.h b/ports/zephyr-cp/common-hal/audiobusio/__init__.h new file mode 100644 index 0000000000000..8ba7882bf9474 --- /dev/null +++ b/ports/zephyr-cp/common-hal/audiobusio/__init__.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// No common definitions needed for audiobusio diff --git a/ports/zephyr-cp/common-hal/busio/I2C.c b/ports/zephyr-cp/common-hal/busio/I2C.c new file mode 100644 index 0000000000000..84e95721b2736 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/I2C.c @@ -0,0 +1,152 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/busio/I2C.h" +#include "py/mperrno.h" +#include "py/runtime.h" + +#include +#include +#include + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_busio_i2c_construct_from_device(busio_i2c_obj_t *self, const struct device *i2c_device) { + self->base.type = &busio_i2c_type; + self->i2c_device = i2c_device; + k_mutex_init(&self->mutex); + self->has_lock = false; + return MP_OBJ_FROM_PTR(self); +} + +// Standard busio construct - not used in Zephyr port (devices come from device tree) +void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, + const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, + uint32_t frequency, uint32_t timeout_ms) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Use device tree to define %q devices"), MP_QSTR_I2C); +} + +bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) { + // Always leave it active (managed by Zephyr) + return false; +} + +void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return; + } + // Always leave it active (managed by Zephyr) +} + +void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self) { + // Not needed for Zephyr port +} + +bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } + + // Try a zero-length write to probe for device + uint8_t dummy; + int ret = i2c_write(self->i2c_device, &dummy, 0, addr); + return ret == 0; +} + +bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) { + if (common_hal_busio_i2c_deinited(self)) { + return false; + } + + self->has_lock = k_mutex_lock(&self->mutex, K_NO_WAIT) == 0; + return self->has_lock; +} + +bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) { + return self->has_lock; +} + +void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) { + self->has_lock = false; + k_mutex_unlock(&self->mutex); +} + +mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr, + const uint8_t *data, size_t len) { + + if (common_hal_busio_i2c_deinited(self)) { + return -MP_EIO; + } + + int ret = i2c_write(self->i2c_device, data, len, addr); + if (ret != 0) { + // Map Zephyr error codes to errno + if (ret == -ENOTSUP) { + return -MP_EOPNOTSUPP; + } else if (ret == -EIO || ret == -ENXIO) { + return -MP_EIO; + } else if (ret == -EBUSY) { + return -MP_EBUSY; + } + return -MP_EIO; + } + + return 0; +} + +mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr, + uint8_t *data, size_t len) { + + if (common_hal_busio_i2c_deinited(self)) { + return -MP_EIO; + } + + if (len == 0) { + return 0; + } + + int ret = i2c_read(self->i2c_device, data, len, addr); + if (ret != 0) { + // Map Zephyr error codes to errno + if (ret == -ENOTSUP) { + return -MP_EOPNOTSUPP; + } else if (ret == -EIO || ret == -ENXIO) { + return -MP_EIO; + } else if (ret == -EBUSY) { + return -MP_EBUSY; + } + return -MP_EIO; + } + + return 0; +} + +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t addr, + uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len) { + + if (common_hal_busio_i2c_deinited(self)) { + return -MP_EIO; + } + + // Use i2c_write_read for combined transaction with repeated start + int ret = i2c_write_read(self->i2c_device, addr, out_data, out_len, in_data, in_len); + if (ret != 0) { + // Map Zephyr error codes to errno + if (ret == -ENOTSUP) { + return -MP_EOPNOTSUPP; + } else if (ret == -EIO || ret == -ENXIO) { + return -MP_EIO; + } else if (ret == -EBUSY) { + return -MP_EBUSY; + } + return -MP_EIO; + } + + return 0; +} + +void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) { + // Not needed for Zephyr port (devices are managed by Zephyr) +} diff --git a/ports/zephyr-cp/common-hal/busio/I2C.h b/ports/zephyr-cp/common-hal/busio/I2C.h new file mode 100644 index 0000000000000..4fa877739b781 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/I2C.h @@ -0,0 +1,20 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include + +typedef struct { + mp_obj_base_t base; + const struct device *i2c_device; + struct k_mutex mutex; + bool has_lock; +} busio_i2c_obj_t; + +// Helper function to construct from Zephyr device tree device +mp_obj_t common_hal_busio_i2c_construct_from_device(busio_i2c_obj_t *self, const struct device *i2c_device); diff --git a/ports/zephyr-cp/common-hal/busio/SPI.c b/ports/zephyr-cp/common-hal/busio/SPI.c new file mode 100644 index 0000000000000..2864c90b49092 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/SPI.c @@ -0,0 +1,281 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/busio/SPI.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "py/gc.h" +#include "shared/runtime/interrupt_char.h" +#include "supervisor/port.h" + +#include +#include +#include + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_busio_spi_construct_from_device(busio_spi_obj_t *self, const struct device *spi_device) { + self->base.type = &busio_spi_type; + self->spi_device = spi_device; + k_mutex_init(&self->mutex); + self->has_lock = false; + self->active_config = 0; + + k_poll_signal_init(&self->signal); + + // Default configuration for both config slots + self->config[0].frequency = 100000; + self->config[0].operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE; + self->config[1].frequency = 100000; + self->config[1].operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | SPI_LINES_SINGLE; + + return MP_OBJ_FROM_PTR(self); +} + +// Standard busio construct - not used in Zephyr port (devices come from device tree) +void common_hal_busio_spi_construct(busio_spi_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *miso, bool half_duplex) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Use device tree to define %q devices"), MP_QSTR_SPI); +} + +bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { + // Always leave it active + return false; +} + +void common_hal_busio_spi_deinit(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return; + } + // Always leave it active +} + +void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self) { + // Not needed for Zephyr port +} + +bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } + + self->has_lock = k_mutex_lock(&self->mutex, K_NO_WAIT) == 0; + return self->has_lock; +} + +bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) { + return self->has_lock; +} + +void common_hal_busio_spi_unlock(busio_spi_obj_t *self) { + self->has_lock = false; + k_mutex_unlock(&self->mutex); +} + +bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } + + // Set operation mode based on polarity and phase + uint16_t operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(bits) | SPI_LINES_SINGLE; + + if (polarity) { + operation |= SPI_MODE_CPOL; + } + if (phase) { + operation |= SPI_MODE_CPHA; + } + + // Check if settings have changed. We must switch to the other config slot if they have because + // Zephyr drivers are allowed to use the pointer value to know if it has changed. + struct spi_config *current_config = &self->config[self->active_config]; + if (current_config->frequency != baudrate || current_config->operation != operation) { + // Settings changed, switch to the other config slot + self->active_config = 1 - self->active_config; + + // Update the new active configuration + self->config[self->active_config].frequency = baudrate; + self->config[self->active_config].operation = operation; + } + + return true; +} + +bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size_t len) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } + + if (len == 0) { + return true; + } + + const struct spi_buf tx_buf = { + .buf = (void *)data, + .len = len + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + + // Initialize the signal for async operation + k_poll_signal_reset(&self->signal); + + int ret = spi_transceive_signal(self->spi_device, &self->config[self->active_config], &tx, NULL, &self->signal); + if (ret != 0) { + return false; + } + + // Wait for the transfer to complete while running background tasks + int signaled = 0; + int result = 0; + while (!signaled && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + k_poll_signal_check(&self->signal, &signaled, &result); + } + + return signaled && result == 0; +} + +bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } + + if (len == 0) { + return true; + } + + // For read, we need to write dummy bytes + // We'll allocate a temporary buffer if write_value is not 0 + uint8_t *tx_data = NULL; + bool need_free = false; + bool used_port_malloc = false; + + if (write_value != 0) { + // Use port_malloc if GC isn't active, otherwise use m_malloc + if (gc_alloc_possible()) { + tx_data = m_malloc(len); + } else { + tx_data = port_malloc(len, false); + used_port_malloc = true; + } + if (tx_data == NULL) { + return false; + } + memset(tx_data, write_value, len); + need_free = true; + } + + const struct spi_buf tx_buf = { + .buf = tx_data, + .len = tx_data ? len : 0 + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = tx_data ? 1 : 0 + }; + + const struct spi_buf rx_buf = { + .buf = data, + .len = len + }; + const struct spi_buf_set rx = { + .buffers = &rx_buf, + .count = 1 + }; + + // Initialize the signal for async operation + k_poll_signal_reset(&self->signal); + + int ret = spi_transceive_signal(self->spi_device, &self->config[self->active_config], &tx, &rx, &self->signal); + + if (need_free) { + if (used_port_malloc) { + port_free(tx_data); + } else { + m_free(tx_data); + } + } + + if (ret != 0) { + return false; + } + + // Wait for the transfer to complete while running background tasks + int signaled = 0; + int result = 0; + while (!signaled && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + k_poll_signal_check(&self->signal, &signaled, &result); + } + + return signaled && result == 0; +} + +bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) { + if (common_hal_busio_spi_deinited(self)) { + return false; + } + + if (len == 0) { + return true; + } + + const struct spi_buf tx_buf = { + .buf = (void *)data_out, + .len = len + }; + const struct spi_buf_set tx = { + .buffers = &tx_buf, + .count = 1 + }; + + const struct spi_buf rx_buf = { + .buf = data_in, + .len = len + }; + const struct spi_buf_set rx = { + .buffers = &rx_buf, + .count = 1 + }; + + // Initialize the signal for async operation + k_poll_signal_reset(&self->signal); + + int ret = spi_transceive_signal(self->spi_device, &self->config[self->active_config], &tx, &rx, &self->signal); + if (ret != 0) { + return false; + } + + // Wait for the transfer to complete while running background tasks + int signaled = 0; + int result = 0; + while (!signaled && !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + k_poll_signal_check(&self->signal, &signaled, &result); + } + + return signaled && result == 0; +} + +uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t *self) { + return self->config[self->active_config].frequency; +} + +uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t *self) { + return (self->config[self->active_config].operation & SPI_MODE_CPHA) ? 1 : 0; +} + +uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self) { + return (self->config[self->active_config].operation & SPI_MODE_CPOL) ? 1 : 0; +} + +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + // Not needed for Zephyr port (devices are managed by Zephyr) +} diff --git a/ports/zephyr-cp/common-hal/busio/SPI.h b/ports/zephyr-cp/common-hal/busio/SPI.h new file mode 100644 index 0000000000000..87411c9825ce6 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/SPI.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include +#include + +typedef struct { + mp_obj_base_t base; + const struct device *spi_device; + struct k_mutex mutex; + bool has_lock; + struct spi_config config[2]; // Two configs for pointer comparison by driver + uint8_t active_config; // Index of currently active config (0 or 1) + struct k_poll_signal signal; +} busio_spi_obj_t; + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_busio_spi_construct_from_device(busio_spi_obj_t *self, const struct device *spi_device); diff --git a/ports/zephyr-cp/common-hal/busio/UART.c b/ports/zephyr-cp/common-hal/busio/UART.c new file mode 100644 index 0000000000000..9940853da50a5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/UART.c @@ -0,0 +1,158 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/busio/UART.h" + +#include "shared/runtime/interrupt_char.h" +#include "py/mpconfig.h" +#include "py/gc.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "py/stream.h" + +#include +#include + +#include +#include +LOG_MODULE_REGISTER(busio_uart); + +/* + * Read characters from UART until line end is detected. Afterwards push the + * data to the message queue. + */ +static void serial_cb(const struct device *dev, void *user_data) { + busio_uart_obj_t *self = (busio_uart_obj_t *)user_data; + + uint8_t c; + + if (!uart_irq_update(dev)) { + return; + } + + if (!uart_irq_rx_ready(dev)) { + return; + } + + /* read until FIFO empty */ + while (uart_fifo_read(dev, &c, 1) == 1) { + if (mp_interrupt_char == c) { + common_hal_busio_uart_clear_rx_buffer(self); + mp_sched_keyboard_interrupt(); + } else if (!self->rx_paused) { + if (k_msgq_put(&self->msgq, &c, K_NO_WAIT) != 0) { + self->rx_paused = true; + } + } + } +} + +void common_hal_busio_uart_never_reset(busio_uart_obj_t *self) { + // Not needed for Zephyr port (devices are managed by Zephyr) +} + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_busio_uart_construct_from_device(busio_uart_obj_t *self, const struct device *uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer) { + self->base.type = &busio_uart_type; + self->uart_device = uart_device; + int ret = uart_irq_callback_user_data_set(uart_device, serial_cb, self); + + if (ret < 0) { + LOG_ERR("Failed to set UART IRQ callback: %d", ret); + } + + k_msgq_init(&self->msgq, receiver_buffer, 1, receiver_buffer_size); + + self->timeout = K_FOREVER; + self->write_timeout = K_FOREVER; + self->rx_paused = false; + uart_irq_rx_enable(uart_device); + + return MP_OBJ_FROM_PTR(self); +} + +// Standard busio construct - not used in Zephyr port (devices come from device tree) +void common_hal_busio_uart_construct(busio_uart_obj_t *self, + const mcu_pin_obj_t *tx, const mcu_pin_obj_t *rx, + const mcu_pin_obj_t *rts, const mcu_pin_obj_t *cts, + const mcu_pin_obj_t *rs485_dir, bool rs485_invert, + uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop, + mp_float_t timeout, uint16_t receiver_buffer_size, byte *receiver_buffer, + bool sigint_enabled) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("Use device tree to define %q devices"), MP_QSTR_UART); +} + +bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) { + return !device_is_ready(self->uart_device); +} + +void common_hal_busio_uart_deinit(busio_uart_obj_t *self) { + // Leave it active (managed by Zephyr) +} + +// Read characters. +size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) { + size_t count = 0; + while (count < len && k_msgq_get(&self->msgq, data + count, self->timeout) == 0) { + count++; + } + if (count > 0) { + self->rx_paused = false; + } + + return count; +} + +// Write characters. +size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) { + for (int i = 0; i < len; i++) { + uart_poll_out(self->uart_device, data[i]); + } + + return len; +} + +uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) { + struct uart_config config; + uart_config_get(self->uart_device, &config); + return config.baudrate; +} + +void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) { + struct uart_config config; + uart_config_get(self->uart_device, &config); + config.baudrate = baudrate; + uart_configure(self->uart_device, &config); +} + +mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) { + return (mp_float_t)self->timeout.ticks / 1000000.0; +} + +void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) { + self->timeout = K_USEC((uint64_t)(timeout * 1000000)); +} + +mp_float_t common_hal_busio_uart_get_write_timeout(busio_uart_obj_t *self) { + return (mp_float_t)self->write_timeout.ticks / 1000000.0; +} + +void common_hal_busio_uart_set_write_timeout(busio_uart_obj_t *self, mp_float_t write_timeout) { + self->write_timeout = K_USEC((uint64_t)(write_timeout * 1000000)); +} + +uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) { + return k_msgq_num_used_get(&self->msgq); +} + +void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) { + k_msgq_purge(&self->msgq); +} + +bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) { + return true; +} diff --git a/ports/zephyr-cp/common-hal/busio/UART.h b/ports/zephyr-cp/common-hal/busio/UART.h new file mode 100644 index 0000000000000..25e767c5b285a --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/UART.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include + +typedef struct { + mp_obj_base_t base; + + const struct device *uart_device; + struct k_msgq msgq; + + k_timeout_t timeout; + k_timeout_t write_timeout; + + bool rx_paused; // set by irq if no space in rbuf +} busio_uart_obj_t; + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_busio_uart_construct_from_device(busio_uart_obj_t *self, const struct device *uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer); + +// Internal helper for clearing buffer +void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/busio/__init__.c b/ports/zephyr-cp/common-hal/busio/__init__.c new file mode 100644 index 0000000000000..135a53f490734 --- /dev/null +++ b/ports/zephyr-cp/common-hal/busio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No busio module functions. diff --git a/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.c b/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.c new file mode 100644 index 0000000000000..0da16a9b72076 --- /dev/null +++ b/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.c @@ -0,0 +1,129 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include +#include + +void common_hal_digitalio_digitalinout_never_reset( + digitalio_digitalinout_obj_t *self) { +} + +digitalinout_result_t common_hal_digitalio_digitalinout_construct( + digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { + claim_pin(pin); + self->pin = pin; + + if (!device_is_ready(pin->port)) { + printk("Port device not ready\n"); + return DIGITALINOUT_PIN_BUSY; + } + + if (gpio_pin_configure(pin->port, pin->number, GPIO_INPUT) != 0) { + return DIGITALINOUT_PIN_BUSY; + } + self->direction = DIRECTION_INPUT; + + return DIGITALINOUT_OK; +} + +bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) { + return self->pin == NULL; +} + +void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) { + if (common_hal_digitalio_digitalinout_deinited(self)) { + return; + } + + reset_pin(self->pin); + self->pin = NULL; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_input( + digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) { + self->direction = DIRECTION_INPUT; + common_hal_digitalio_digitalinout_set_pull(self, pull); + return DIGITALINOUT_OK; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_switch_to_output( + digitalio_digitalinout_obj_t *self, bool value, + digitalio_drive_mode_t drive_mode) { + + self->direction = DIRECTION_OUTPUT; + common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode); + common_hal_digitalio_digitalinout_set_value(self, value); + return DIGITALINOUT_OK; +} + +digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( + digitalio_digitalinout_obj_t *self) { + return self->direction; +} + +void common_hal_digitalio_digitalinout_set_value( + digitalio_digitalinout_obj_t *self, bool value) { + int res = gpio_pin_set(self->pin->port, self->pin->number, value); + if (res != 0) { + printk("Failed to set value %d\n", res); + } + // Not all MCUs can read back the output value, so store it. + self->value = value; +} + +bool common_hal_digitalio_digitalinout_get_value( + digitalio_digitalinout_obj_t *self) { + if (self->direction == DIRECTION_OUTPUT) { + return self->value; + } + return gpio_pin_get(self->pin->port, self->pin->number) == 1; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_set_drive_mode( + digitalio_digitalinout_obj_t *self, + digitalio_drive_mode_t drive_mode) { + // Also INPUT so we can read the value back. + gpio_flags_t flags = GPIO_OUTPUT; + if (drive_mode == DRIVE_MODE_OPEN_DRAIN) { + flags |= GPIO_OPEN_DRAIN; + } + int res = gpio_pin_configure(self->pin->port, self->pin->number, flags); + if (res != 0) { + // TODO: Fake open drain. + printk("Failed to set drive mode %d\n", res); + return DIGITALINOUT_INVALID_DRIVE_MODE; + } + self->drive_mode = drive_mode; + return DIGITALINOUT_OK; +} + +digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode( + digitalio_digitalinout_obj_t *self) { + return self->drive_mode; +} + +digitalinout_result_t common_hal_digitalio_digitalinout_set_pull( + digitalio_digitalinout_obj_t *self, digitalio_pull_t pull) { + gpio_flags_t pull_flags = 0; + if (pull == PULL_UP) { + pull_flags = GPIO_PULL_UP; + } else if (pull == PULL_DOWN) { + pull_flags = GPIO_PULL_DOWN; + } + if (gpio_pin_configure(self->pin->port, self->pin->number, GPIO_INPUT | pull_flags) != 0) { + return DIGITALINOUT_INVALID_PULL; + } + self->pull = pull; + + return DIGITALINOUT_OK; +} + +digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( + digitalio_digitalinout_obj_t *self) { + return self->pull; +} diff --git a/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.h b/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.h new file mode 100644 index 0000000000000..9e0c326526852 --- /dev/null +++ b/ports/zephyr-cp/common-hal/digitalio/DigitalInOut.h @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/digitalio/Pull.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + digitalio_direction_t direction; + bool value; + digitalio_drive_mode_t drive_mode; + digitalio_pull_t pull; +} digitalio_digitalinout_obj_t; diff --git a/ports/zephyr-cp/common-hal/digitalio/__init__.c b/ports/zephyr-cp/common-hal/digitalio/__init__.c new file mode 100644 index 0000000000000..fa222ed01f03d --- /dev/null +++ b/ports/zephyr-cp/common-hal/digitalio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No digitalio module functions. diff --git a/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c new file mode 100644 index 0000000000000..494b21cb02db9 --- /dev/null +++ b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.c @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/hostnetwork/HostNetwork.h" + +hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj = { + .base = { &hostnetwork_hostnetwork_type }, +}; + +void common_hal_hostnetwork_hostnetwork_construct(hostnetwork_hostnetwork_obj_t *self) { + (void)self; +} diff --git a/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h new file mode 100644 index 0000000000000..a6731546bdef1 --- /dev/null +++ b/ports/zephyr-cp/common-hal/hostnetwork/HostNetwork.h @@ -0,0 +1,11 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "bindings/hostnetwork/HostNetwork.h" + +extern hostnetwork_hostnetwork_obj_t common_hal_hostnetwork_obj; diff --git a/ports/zephyr-cp/common-hal/microcontroller/Pin.c b/ports/zephyr-cp/common-hal/microcontroller/Pin.c new file mode 100644 index 0000000000000..66882b6b5f032 --- /dev/null +++ b/ports/zephyr-cp/common-hal/microcontroller/Pin.c @@ -0,0 +1,73 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#include "py/mphal.h" + +// Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two. +// static uint32_t claimed_pins[GPIO_COUNT]; +// static uint32_t never_reset_pins[GPIO_COUNT]; + +void reset_all_pins(void) { + // for (size_t i = 0; i < GPIO_COUNT; i++) { + // claimed_pins[i] = never_reset_pins[i]; + // } + + // for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) { + // if ((never_reset_pins[nrf_pin_port(pin)] & (1 << nrf_relative_pin_number(pin))) != 0) { + // continue; + // } + // nrf_gpio_cfg_default(pin); + // } + + // // After configuring SWD because it may be shared. + // reset_speaker_enable_pin(); +} + +// Mark pin as free and return it to a quiescent state. +void reset_pin(const mcu_pin_obj_t *pin) { + + // Clear claimed bit. + // claimed_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number)); + // never_reset_pins[nrf_pin_port(pin_number)] &= ~(1 << nrf_relative_pin_number(pin_number)); +} + + +void never_reset_pin_number(uint8_t pin_number) { + // never_reset_pins[nrf_pin_port(pin_number)] |= 1 << nrf_relative_pin_number(pin_number); +} + +void common_hal_never_reset_pin(const mcu_pin_obj_t *pin) { + never_reset_pin_number(pin->number); +} + +void common_hal_reset_pin(const mcu_pin_obj_t *pin) { + if (pin == NULL) { + return; + } + reset_pin(pin); +} + +void claim_pin(const mcu_pin_obj_t *pin) { + // Set bit in claimed_pins bitmask. + // claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); +} + + +bool pin_number_is_free(uint8_t pin_number) { + return false; // !(claimed_pins[nrf_pin_port(pin_number)] & (1 << nrf_relative_pin_number(pin_number))); +} + +bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t *pin) { + return true; + +} + +void common_hal_mcu_pin_claim(const mcu_pin_obj_t *pin) { + claim_pin(pin); +} diff --git a/ports/zephyr-cp/common-hal/microcontroller/Pin.h b/ports/zephyr-cp/common-hal/microcontroller/Pin.h new file mode 100644 index 0000000000000..d38ab9bd2009c --- /dev/null +++ b/ports/zephyr-cp/common-hal/microcontroller/Pin.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/mphal.h" +#include "py/obj.h" + +#include + +typedef struct { + mp_obj_base_t base; + const struct device *port; + gpio_pin_t number; +} mcu_pin_obj_t; + +#include "autogen-pins.h" + +void reset_all_pins(void); +void reset_pin(const mcu_pin_obj_t *pin); +void claim_pin(const mcu_pin_obj_t *pin); diff --git a/ports/zephyr-cp/common-hal/microcontroller/Processor.c b/ports/zephyr-cp/common-hal/microcontroller/Processor.c new file mode 100644 index 0000000000000..9f512a686ec14 --- /dev/null +++ b/ports/zephyr-cp/common-hal/microcontroller/Processor.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" + +#include "common-hal/microcontroller/Processor.h" +#include "shared-bindings/microcontroller/Processor.h" + +#include "shared-bindings/microcontroller/ResetReason.h" + +#include +#include + + +float common_hal_mcu_processor_get_temperature(void) { + return 0.0; +} + +extern uint32_t SystemCoreClock; +uint32_t common_hal_mcu_processor_get_frequency(void) { + #ifdef __ARM__ + return SystemCoreClock; + #else + return CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + #endif +} + +float common_hal_mcu_processor_get_voltage(void) { + return 3.3f; +} + +void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { + ssize_t len = hwinfo_get_device_id(raw_id, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH); + if (len < 0) { + printk("UID retrieval failed: %d\n", len); + len = 0; + } + if (len < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH) { + printk("UID shorter %d than defined length %d\n", len, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH); + memset(raw_id + len, 0, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH - len); + } +} + +mcu_reset_reason_t common_hal_mcu_processor_get_reset_reason(void) { + mcu_reset_reason_t r = RESET_REASON_UNKNOWN; + return r; +} diff --git a/ports/zephyr-cp/common-hal/microcontroller/Processor.h b/ports/zephyr-cp/common-hal/microcontroller/Processor.h new file mode 100644 index 0000000000000..f47f582a1cef2 --- /dev/null +++ b/ports/zephyr-cp/common-hal/microcontroller/Processor.h @@ -0,0 +1,23 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#if CONFIG_HWINFO_NRF +#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 8 +#else +// Extra long and the remainder will be left empty. Will print out the actual length. +#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 32 +#endif + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + // Stores no state currently. +} mcu_processor_obj_t; + +extern uint32_t reset_reason_saved; diff --git a/ports/zephyr-cp/common-hal/microcontroller/__init__.c b/ports/zephyr-cp/common-hal/microcontroller/__init__.c new file mode 100644 index 0000000000000..be33cd26c9ace --- /dev/null +++ b/ports/zephyr-cp/common-hal/microcontroller/__init__.c @@ -0,0 +1,114 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/microcontroller/Processor.h" + +#include "shared-bindings/nvm/ByteArray.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/microcontroller/Processor.h" + +#include "supervisor/filesystem.h" +#include "supervisor/port.h" +#include "supervisor/shared/safe_mode.h" + +#include + +// This routine should work even when interrupts are disabled. Used by OneWire +// for precise timing. +void common_hal_mcu_delay_us(uint32_t delay) { +} + +static uint32_t _irq_key; + +static volatile uint32_t nesting_count = 0; +void common_hal_mcu_disable_interrupts() { + if (nesting_count == 0) { + // Unlike __disable_irq(), this should only be called the first time + // "is_nested_critical_region" is sd's equivalent of our nesting count + // so a nested call would store 0 in the global and make the later + // exit call not actually re-enable interrupts + // + // This only disables interrupts of priority 2 through 7; levels 0, 1, + // and 4, are exclusive to softdevice and should never be used, so + // this limitation is not important. + // sd_nvic_critical_region_enter(&is_nested_critical_region); + if (!k_is_in_isr()) { + k_sched_lock(); + } + _irq_key = irq_lock(); + } + nesting_count++; +} + +void common_hal_mcu_enable_interrupts() { + if (nesting_count == 0) { + // This is very very bad because it means there was mismatched disable/enables. + reset_into_safe_mode(SAFE_MODE_INTERRUPT_ERROR); + } + nesting_count--; + if (nesting_count > 0) { + return; + } + irq_unlock(_irq_key); + if (!k_is_in_isr()) { + k_sched_unlock(); + } +} + +void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) { + enum { DFU_MAGIC_UF2_RESET = 0x57 }; + uint8_t new_value = 0; + if (runmode == RUNMODE_BOOTLOADER || runmode == RUNMODE_UF2) { + new_value = DFU_MAGIC_UF2_RESET; + } + // int err_code = sd_power_gpregret_set(0, DFU_MAGIC_UF2_RESET); + // if (err_code != NRF_SUCCESS) { + // // Set it without the soft device if the SD failed. (It may be off.) + // nrf_power_gpregret_set(NRF_POWER, new_value); + // } + if (runmode == RUNMODE_SAFE_MODE) { + safe_mode_on_next_reset(SAFE_MODE_PROGRAMMATIC); + } +} + +void common_hal_mcu_reset(void) { + filesystem_flush(); + reset_cpu(); +} + +// The singleton microcontroller.Processor object, bound to microcontroller.cpu +// It currently only has properties, and no state. +const mcu_processor_obj_t common_hal_mcu_processor_obj = { + .base = { + .type = &mcu_processor_type, + }, +}; + +#if CIRCUITPY_NVM +// The singleton nvm.ByteArray object. +const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { + .base = { + .type = &nvm_bytearray_type, + }, +}; +#endif + +#if CIRCUITPY_WATCHDOG +// The singleton watchdog.WatchDogTimer object. +watchdog_watchdogtimer_obj_t common_hal_mcu_watchdogtimer_obj = { + .base = { + .type = &watchdog_watchdogtimer_type, + }, + .timeout = 0.0f, + .mode = WATCHDOGMODE_NONE, +}; +#endif diff --git a/ports/zephyr-cp/common-hal/nvm/ByteArray.c b/ports/zephyr-cp/common-hal/nvm/ByteArray.c new file mode 100644 index 0000000000000..b8f552d677389 --- /dev/null +++ b/ports/zephyr-cp/common-hal/nvm/ByteArray.c @@ -0,0 +1,103 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/runtime.h" +#include "common-hal/nvm/ByteArray.h" +#include "shared-bindings/nvm/ByteArray.h" + +#include + +#include +#include + +#define NVM_PARTITION nvm_partition + +#if FIXED_PARTITION_EXISTS(NVM_PARTITION) + +static const struct flash_area *nvm_area = NULL; +static size_t nvm_erase_size = 0; + +static bool ensure_nvm_open(void) { + if (nvm_area != NULL) { + return true; + } + int rc = flash_area_open(FIXED_PARTITION_ID(NVM_PARTITION), &nvm_area); + if (rc != 0) { + return false; + } + + const struct device *dev = flash_area_get_device(nvm_area); + struct flash_pages_info info; + flash_get_page_info_by_offs(dev, nvm_area->fa_off, &info); + nvm_erase_size = info.size; + + return true; +} + +uint32_t common_hal_nvm_bytearray_get_length(const nvm_bytearray_obj_t *self) { + if (!ensure_nvm_open()) { + return 0; + } + return nvm_area->fa_size; +} + +bool common_hal_nvm_bytearray_set_bytes(const nvm_bytearray_obj_t *self, + uint32_t start_index, uint8_t *values, uint32_t len) { + if (!ensure_nvm_open()) { + return false; + } + + uint32_t address = start_index; + while (len > 0) { + uint32_t page_offset = address % nvm_erase_size; + uint32_t page_start = address - page_offset; + uint32_t write_len = MIN(len, nvm_erase_size - page_offset); + + uint8_t *buffer = m_malloc(nvm_erase_size); + if (buffer == NULL) { + return false; + } + + // Read the full erase page. + int rc = flash_area_read(nvm_area, page_start, buffer, nvm_erase_size); + if (rc != 0) { + m_free(buffer); + return false; + } + + // Modify the relevant bytes. + memcpy(buffer + page_offset, values, write_len); + + // Erase the page. + rc = flash_area_erase(nvm_area, page_start, nvm_erase_size); + if (rc != 0) { + m_free(buffer); + return false; + } + + // Write the page back. + rc = flash_area_write(nvm_area, page_start, buffer, nvm_erase_size); + m_free(buffer); + if (rc != 0) { + return false; + } + + address += write_len; + values += write_len; + len -= write_len; + } + return true; +} + +void common_hal_nvm_bytearray_get_bytes(const nvm_bytearray_obj_t *self, + uint32_t start_index, uint32_t len, uint8_t *values) { + if (!ensure_nvm_open()) { + return; + } + flash_area_read(nvm_area, start_index, values, len); +} + +#endif // FIXED_PARTITION_EXISTS(NVM_PARTITION) diff --git a/ports/zephyr-cp/common-hal/nvm/ByteArray.h b/ports/zephyr-cp/common-hal/nvm/ByteArray.h new file mode 100644 index 0000000000000..9c771aaa3a950 --- /dev/null +++ b/ports/zephyr-cp/common-hal/nvm/ByteArray.h @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} nvm_bytearray_obj_t; diff --git a/ports/zephyr-cp/common-hal/os/__init__.c b/ports/zephyr-cp/common-hal/os/__init__.c new file mode 100644 index 0000000000000..2f37ba40f47a6 --- /dev/null +++ b/ports/zephyr-cp/common-hal/os/__init__.c @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "genhdr/mpversion.h" +#include "py/mpconfig.h" +#include "py/objstr.h" +#include "py/objtuple.h" + +#include "shared-bindings/os/__init__.h" + +#include + +bool common_hal_os_urandom(uint8_t *buffer, mp_uint_t length) { + #if !DT_HAS_CHOSEN(zephyr_entropy) + return false; + #else + return sys_csrand_get(buffer, length) == 0; + #endif +} diff --git a/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c new file mode 100644 index 0000000000000..d36b571535afe --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.c @@ -0,0 +1,129 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#include "common-hal/rotaryio/IncrementalEncoder.h" +#include "shared-bindings/rotaryio/IncrementalEncoder.h" +#include "shared-module/rotaryio/IncrementalEncoder.h" + +#include "bindings/zephyr_kernel/__init__.h" +#include "py/runtime.h" + +#include +#include +#include +#include + +static void incrementalencoder_gpio_callback(const struct device *port, + struct gpio_callback *cb, gpio_port_pins_t pins) { + (void)port; + (void)pins; + rotaryio_incrementalencoder_gpio_callback_t *callback = + CONTAINER_OF(cb, rotaryio_incrementalencoder_gpio_callback_t, callback); + rotaryio_incrementalencoder_obj_t *self = callback->encoder; + if (self == NULL || self->pin_a == NULL) { + return; + } + + int a = gpio_pin_get(self->pin_a->port, self->pin_a->number); + int b = gpio_pin_get(self->pin_b->port, self->pin_b->number); + if (a < 0 || b < 0) { + return; + } + uint8_t new_state = ((uint8_t)a << 1) | (uint8_t)b; + shared_module_softencoder_state_update(self, new_state); +} + +void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, + const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) { + // Ensure object starts in its deinit state. + common_hal_rotaryio_incrementalencoder_mark_deinit(self); + + self->pin_a = pin_a; + self->pin_b = pin_b; + self->divisor = 4; + + if (!device_is_ready(pin_a->port) || !device_is_ready(pin_b->port)) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(-ENODEV); + } + + int result = gpio_pin_configure(pin_a->port, pin_a->number, GPIO_INPUT | GPIO_PULL_UP); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_configure(pin_b->port, pin_b->number, GPIO_INPUT | GPIO_PULL_UP); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + self->callback_a.encoder = self; + gpio_init_callback(&self->callback_a.callback, incrementalencoder_gpio_callback, + BIT(pin_a->number)); + result = gpio_add_callback(pin_a->port, &self->callback_a.callback); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + self->callback_b.encoder = self; + gpio_init_callback(&self->callback_b.callback, incrementalencoder_gpio_callback, + BIT(pin_b->number)); + result = gpio_add_callback(pin_b->port, &self->callback_b.callback); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_interrupt_configure(pin_a->port, pin_a->number, GPIO_INT_EDGE_BOTH); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + result = gpio_pin_interrupt_configure(pin_b->port, pin_b->number, GPIO_INT_EDGE_BOTH); + if (result != 0) { + common_hal_rotaryio_incrementalencoder_deinit(self); + raise_zephyr_error(result); + } + + int a = gpio_pin_get(pin_a->port, pin_a->number); + int b = gpio_pin_get(pin_b->port, pin_b->number); + uint8_t quiescent_state = ((uint8_t)(a > 0) << 1) | (uint8_t)(b > 0); + shared_module_softencoder_state_init(self, quiescent_state); + + claim_pin(pin_a); + claim_pin(pin_b); +} + +bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self) { + return self->pin_a == NULL; +} + +void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self) { + if (common_hal_rotaryio_incrementalencoder_deinited(self)) { + return; + } + + // Best-effort cleanup. During failed construct(), some of these may not be + // initialized yet. Ignore cleanup errors. + gpio_pin_interrupt_configure(self->pin_a->port, self->pin_a->number, GPIO_INT_DISABLE); + gpio_pin_interrupt_configure(self->pin_b->port, self->pin_b->number, GPIO_INT_DISABLE); + gpio_remove_callback(self->pin_a->port, &self->callback_a.callback); + gpio_remove_callback(self->pin_b->port, &self->callback_b.callback); + + reset_pin(self->pin_a); + reset_pin(self->pin_b); + + common_hal_rotaryio_incrementalencoder_mark_deinit(self); +} + +void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self) { + self->pin_a = NULL; + self->pin_b = NULL; +} diff --git a/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h new file mode 100644 index 0000000000000..a0d2bb392e264 --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/IncrementalEncoder.h @@ -0,0 +1,31 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "common-hal/microcontroller/Pin.h" +#include "py/obj.h" + +typedef struct rotaryio_incrementalencoder_obj rotaryio_incrementalencoder_obj_t; + +typedef struct { + struct gpio_callback callback; + rotaryio_incrementalencoder_obj_t *encoder; +} rotaryio_incrementalencoder_gpio_callback_t; + +struct rotaryio_incrementalencoder_obj { + mp_obj_base_t base; + const mcu_pin_obj_t *pin_a; + const mcu_pin_obj_t *pin_b; + rotaryio_incrementalencoder_gpio_callback_t callback_a; + rotaryio_incrementalencoder_gpio_callback_t callback_b; + uint8_t state; // + int8_t sub_count; // count intermediate transitions between detents + int8_t divisor; // Number of quadrature edges required per count + mp_int_t position; +}; diff --git a/ports/zephyr-cp/common-hal/rotaryio/__init__.c b/ports/zephyr-cp/common-hal/rotaryio/__init__.c new file mode 100644 index 0000000000000..67cae26a8b7fe --- /dev/null +++ b/ports/zephyr-cp/common-hal/rotaryio/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC +// +// SPDX-License-Identifier: MIT + +// No rotaryio module functions. diff --git a/ports/zephyr-cp/common-hal/socketpool/Socket.c b/ports/zephyr-cp/common-hal/socketpool/Socket.c new file mode 100644 index 0000000000000..ca8ba4198394a --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/Socket.c @@ -0,0 +1,675 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/socketpool/Socket.h" + +#include "shared/runtime/interrupt_char.h" +#include "py/mperrno.h" +#include "py/runtime.h" +#include "shared-bindings/socketpool/SocketPool.h" +#include "common-hal/socketpool/__init__.h" +#include "common-hal/wifi/__init__.h" +#if CIRCUITPY_SSL +#include "shared-bindings/ssl/SSLSocket.h" +#include "shared-module/ssl/SSLSocket.h" +#endif +#include "supervisor/port.h" +#include "supervisor/shared/tick.h" +#include "supervisor/workflow.h" + +#include +#include +#include +#include +#include + +#include +#include + +#define SOCKETPOOL_IP_STR_LEN 48 + +static mp_obj_t _format_address(const struct sockaddr *addr, int family) { + char ip_str[SOCKETPOOL_IP_STR_LEN]; + const struct sockaddr_in *a = (void *)addr; + + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case AF_INET6: + zsock_inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); + break; + #endif + default: + case AF_INET: + zsock_inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); + break; + } + return mp_obj_new_str(ip_str, strlen(ip_str)); +} + +static mp_obj_t _sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { + mp_obj_t args[4] = { + _format_address((const struct sockaddr *)sockaddr, sockaddr->ss_family), + }; + int n = 2; + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (sockaddr->ss_family == AF_INET6) { + const struct sockaddr_in6 *addr6 = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(ntohs(addr6->sin6_port)); + args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo); + args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id); + n = 4; + } else + #endif + { + const struct sockaddr_in *addr = (const void *)sockaddr; + args[1] = MP_OBJ_NEW_SMALL_INT(ntohs(addr->sin_port)); + } + return mp_obj_new_tuple(n, args); +} + +static void socketpool_resolve_host_or_throw(int family, int type, const char *hostname, struct sockaddr_storage *addr, int port) { + const struct zsock_addrinfo hints = { + .ai_family = family, + .ai_socktype = type, + }; + struct zsock_addrinfo *result_i = NULL; + char service_buf[6]; + + snprintf(service_buf, sizeof(service_buf), "%d", port); + + int error = zsock_getaddrinfo(hostname, service_buf, &hints, &result_i); + if (error != 0 || result_i == NULL) { + common_hal_socketpool_socketpool_raise_gaierror_noname(); + } + + memcpy(addr, result_i->ai_addr, sizeof(struct sockaddr_storage)); + zsock_freeaddrinfo(result_i); +} + +static void resolve_host_or_throw(socketpool_socket_obj_t *self, const char *hostname, struct sockaddr_storage *addr, int port) { + socketpool_resolve_host_or_throw(self->family, self->type, hostname, addr, port); +} + +// How long to wait between checks for a socket to connect. +#define SOCKET_CONNECT_POLL_INTERVAL_MS 100 + +void socket_user_reset(void) { + // User sockets are heap objects with __del__ bound to close(). + // During VM shutdown/reset, gc_sweep_all() runs finalizers, so sockets + // are closed there rather than being tracked and closed explicitly here. +} + +static struct k_work_delayable socketpool_poll_work; +static bool socketpool_poll_work_initialized; + +static void socketpool_poll_work_handler(struct k_work *work) { + (void)work; + supervisor_workflow_request_background(); +} + +// Unblock select task (ok if not blocked yet) +void socketpool_socket_poll_resume(void) { + if (!socketpool_poll_work_initialized) { + k_work_init_delayable(&socketpool_poll_work, socketpool_poll_work_handler); + socketpool_poll_work_initialized = true; + } + k_work_schedule(&socketpool_poll_work, K_MSEC(10)); +} + +static bool _socketpool_socket(socketpool_socketpool_obj_t *self, + socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, + int proto, + socketpool_socket_obj_t *sock) { + int addr_family; + int ipproto; + + if (family == SOCKETPOOL_AF_INET) { + addr_family = AF_INET; + ipproto = IPPROTO_IP; + #if CIRCUITPY_SOCKETPOOL_IPV6 + } else { // INET6 + addr_family = AF_INET6; + ipproto = IPPROTO_IPV6; + #endif + } + + int socket_type; + if (type == SOCKETPOOL_SOCK_STREAM) { + socket_type = SOCK_STREAM; + } else if (type == SOCKETPOOL_SOCK_DGRAM) { + socket_type = SOCK_DGRAM; + } else { // SOCKETPOOL_SOCK_RAW + socket_type = SOCK_RAW; + ipproto = proto; + } + sock->type = socket_type; + sock->family = addr_family; + sock->ipproto = ipproto; + sock->pool = self; + sock->timeout_ms = (uint)-1; + + int socknum = zsock_socket(sock->family, sock->type, sock->ipproto); + if (socknum < 0) { + return false; + } + + sock->num = socknum; + + // Enable address reuse by default to avoid bind failures on recently-used ports. + int reuseaddr = 1; + if (zsock_setsockopt(socknum, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)) < 0) { + // Ignore if SO_REUSEADDR is unsupported. + } + + // Sockets should be nonblocking in most cases. + if (zsock_fcntl(socknum, F_SETFL, O_NONBLOCK) < 0) { + // Ignore if non-blocking is unsupported. + } + + return true; +} + +// special entry for workflow listener (register system socket) +bool socketpool_socket(socketpool_socketpool_obj_t *self, + socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, + int proto, socketpool_socket_obj_t *sock) { + + if (!_socketpool_socket(self, family, type, proto, sock)) { + return false; + } + + return true; +} + +socketpool_socket_obj_t *common_hal_socketpool_socket(socketpool_socketpool_obj_t *self, + socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto) { + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case SOCKETPOOL_AF_INET6: + #endif + case SOCKETPOOL_AF_INET: + break; + default: + mp_raise_NotImplementedError(MP_ERROR_TEXT("Unsupported socket type")); + } + + socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, &socketpool_socket_type); + + if (!_socketpool_socket(self, family, type, proto, sock)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Out of sockets")); + } + return sock; +} + +int socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out, socketpool_socket_obj_t *accepted) { + struct sockaddr_storage peer_addr; + socklen_t socklen = sizeof(peer_addr); + int newsoc = -1; + bool timed_out = false; + uint64_t start_ticks = supervisor_ticks_ms64(); + + // Allow timeouts and interrupts + while (newsoc == -1 && !timed_out) { + if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + #if CIRCUITPY_HOSTNETWORK + if (self->timeout_ms == 0) { + struct zsock_timeval tv = { + .tv_sec = 0, + .tv_usec = 1000, + }; + zsock_setsockopt(self->num, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + } + #endif + newsoc = zsock_accept(self->num, (struct sockaddr *)&peer_addr, &socklen); + // In non-blocking mode, fail instead of timing out + if (newsoc == -1 && (self->timeout_ms == 0 || mp_hal_is_interrupted())) { + return -MP_EAGAIN; + } + if (newsoc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { + return -errno; + } + } + + if (timed_out) { + return -ETIMEDOUT; + } + + if (newsoc < 0) { + return -MP_EBADF; + } + + // We got a socket. New client socket will not be non-blocking by default, so make it non-blocking. + if (zsock_fcntl(newsoc, F_SETFL, O_NONBLOCK) < 0) { + // Ignore if non-blocking is unsupported. + } + + if (accepted != NULL) { + // Error if called with open socket object. + assert(common_hal_socketpool_socket_get_closed(accepted)); + + // Replace the old accepted socket with the new one. + accepted->num = newsoc; + accepted->pool = self->pool; + accepted->connected = true; + accepted->type = self->type; + } + + if (peer_out) { + *peer_out = _sockaddr_to_tuple(&peer_addr); + } + + return newsoc; +} + +socketpool_socket_obj_t *common_hal_socketpool_socket_accept(socketpool_socket_obj_t *self, mp_obj_t *peer_out) { + // Set the socket type only after the socketpool_socket_accept succeeds, so that the + // finaliser is not called on a bad socket. + socketpool_socket_obj_t *sock = mp_obj_malloc_with_finaliser(socketpool_socket_obj_t, NULL); + int newsoc = socketpool_socket_accept(self, peer_out, NULL); + + if (newsoc > 0) { + // Create the socket + sock->base.type = &socketpool_socket_type; + sock->num = newsoc; + sock->pool = self->pool; + sock->connected = true; + sock->type = self->type; + + return sock; + } else { + mp_raise_OSError(-newsoc); + return NULL; + } +} + +size_t common_hal_socketpool_socket_bind(socketpool_socket_obj_t *self, + const char *host, size_t hostlen, uint32_t port) { + struct sockaddr_storage bind_addr; + const char *broadcast = ""; + uint32_t local_port = port; + + memset(&bind_addr, 0, sizeof(bind_addr)); + bind_addr.ss_family = self->family; + + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (self->family == AF_INET6) { + struct sockaddr_in6 *addr6 = (void *)&bind_addr; + addr6->sin6_port = htons(local_port); + // no ipv6 broadcast + if (hostlen == 0) { + memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr)); + } else { + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, local_port); + } + } else + #endif + { + struct sockaddr_in *addr4 = (void *)&bind_addr; + addr4->sin_port = htons(local_port); + if (hostlen == 0) { + addr4->sin_addr.s_addr = htonl(INADDR_ANY); + } else if (hostlen == strlen(broadcast) && + memcmp(host, broadcast, strlen(broadcast)) == 0) { + addr4->sin_addr.s_addr = htonl(INADDR_BROADCAST); + } else { + socketpool_resolve_host_or_throw(self->family, self->type, host, &bind_addr, local_port); + } + } + + int result = zsock_bind(self->num, (struct sockaddr *)&bind_addr, sizeof(bind_addr)); + if (result == 0) { + return 0; + } + return errno; +} + +void socketpool_socket_close(socketpool_socket_obj_t *self) { + #if CIRCUITPY_SSL + if (self->ssl_socket) { + ssl_sslsocket_obj_t *ssl_socket = self->ssl_socket; + self->ssl_socket = NULL; + common_hal_ssl_sslsocket_close(ssl_socket); + return; + } + #endif + self->connected = false; + int fd = self->num; + if (fd >= 0) { + zsock_shutdown(fd, ZSOCK_SHUT_RDWR); + zsock_close(fd); + } + self->num = -1; +} + +void common_hal_socketpool_socket_close(socketpool_socket_obj_t *self) { + socketpool_socket_close(self); +} + +void common_hal_socketpool_socket_connect(socketpool_socket_obj_t *self, + const char *host, size_t hostlen, uint32_t port) { + (void)hostlen; + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); + + int result = zsock_connect(self->num, (struct sockaddr *)&addr, sizeof(addr)); + + if (result == 0) { + // Connected immediately. + self->connected = true; + return; + } + + if (result < 0 && errno != EINPROGRESS) { + // Some error happened; error is in errno. + mp_raise_OSError(errno); + return; + } + + // Keep checking, using poll(), until timeout expires, at short intervals. + // This allows ctrl-C interrupts to be detected and background tasks to run. + mp_uint_t timeout_left = self->timeout_ms; + + while (timeout_left > 0) { + RUN_BACKGROUND_TASKS; + // Allow ctrl-C interrupt + if (mp_hal_is_interrupted()) { + return; + } + + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLOUT, + }; + int poll_timeout = SOCKET_CONNECT_POLL_INTERVAL_MS; + if (self->timeout_ms == (uint)-1) { + poll_timeout = -1; + } else if (timeout_left < SOCKET_CONNECT_POLL_INTERVAL_MS) { + poll_timeout = timeout_left; + } + + result = zsock_poll(&fd, 1, poll_timeout); + if (result == 0) { + if (self->timeout_ms == (uint)-1) { + continue; + } + if (timeout_left < SOCKET_CONNECT_POLL_INTERVAL_MS) { + timeout_left = 0; + } else { + timeout_left -= SOCKET_CONNECT_POLL_INTERVAL_MS; + } + continue; + } + + if (result < 0) { + mp_raise_OSError(errno); + } + + int error_code = 0; + socklen_t socklen = sizeof(error_code); + result = zsock_getsockopt(self->num, SOL_SOCKET, SO_ERROR, &error_code, &socklen); + if (result < 0 || error_code != 0) { + mp_raise_OSError(error_code != 0 ? error_code : errno); + } + self->connected = true; + return; + } + + // No connection after timeout. The connection attempt is not stopped. + // This imitates what happens in Python. + mp_raise_OSError(ETIMEDOUT); +} + +bool common_hal_socketpool_socket_get_closed(socketpool_socket_obj_t *self) { + return self->num < 0; +} + +bool common_hal_socketpool_socket_get_connected(socketpool_socket_obj_t *self) { + return self->connected; +} + +bool common_hal_socketpool_socket_listen(socketpool_socket_obj_t *self, int backlog) { + return zsock_listen(self->num, backlog) == 0; +} + +mp_uint_t common_hal_socketpool_socket_recvfrom_into(socketpool_socket_obj_t *self, + uint8_t *buf, uint32_t len, mp_obj_t *source_out) { + + struct sockaddr_storage source_addr; + socklen_t socklen = sizeof(source_addr); + + uint64_t start_ticks = supervisor_ticks_ms64(); + int received = -1; + bool timed_out = false; + while (received == -1 && + !timed_out && + !mp_hal_is_interrupted()) { + if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + received = zsock_recvfrom(self->num, buf, len, ZSOCK_MSG_DONTWAIT, (struct sockaddr *)&source_addr, &socklen); + + if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + mp_raise_OSError(errno); + } + + if (received == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + // In non-blocking mode, fail instead of looping + if (self->timeout_ms == 0) { + mp_raise_OSError(MP_EAGAIN); + } + continue; + } + } + + if (timed_out) { + mp_raise_OSError(ETIMEDOUT); + } + + if (received < 0) { + mp_raise_BrokenPipeError(); + return 0; + } + + if (source_out) { + *source_out = _sockaddr_to_tuple(&source_addr); + } + + return received; +} + +int socketpool_socket_recv_into(socketpool_socket_obj_t *self, + const uint8_t *buf, uint32_t len) { + int received = 0; + bool timed_out = false; + + if (self->num != -1) { + uint64_t start_ticks = supervisor_ticks_ms64(); + received = -1; + while (received == -1 && + !timed_out) { + if (self->timeout_ms != (uint)-1 && self->timeout_ms != 0) { + timed_out = supervisor_ticks_ms64() - start_ticks >= self->timeout_ms; + } + RUN_BACKGROUND_TASKS; + received = zsock_recv(self->num, (void *)buf, len, ZSOCK_MSG_DONTWAIT); + if (received < 0 && errno != EAGAIN && errno != EWOULDBLOCK) { + return -errno; + } + if (received < 1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { + if (self->timeout_ms == 0) { + return -MP_EAGAIN; + } + continue; + } + // In non-blocking mode, fail instead of looping + if (received < 1 && self->timeout_ms == 0) { + if ((received == 0) || (errno == ENOTCONN)) { + self->connected = false; + return -MP_ENOTCONN; + } + return -MP_EAGAIN; + } + // Check this after going through the loop once so it can make + // progress while interrupted. + if (mp_hal_is_interrupted()) { + if (received == -1) { + return -MP_EAGAIN; + } + break; + } + } + } else { + return -MP_EBADF; + } + + if (timed_out) { + return -ETIMEDOUT; + } + return received; +} + +mp_uint_t common_hal_socketpool_socket_recv_into(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) { + int received = socketpool_socket_recv_into(self, buf, len); + if (received < 0) { + mp_raise_OSError(-received); + } + return received; +} + +int socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) { + int sent = -1; + if (self->num != -1) { + sent = zsock_send(self->num, buf, len, 0); + } else { + sent = -MP_EBADF; + } + + if (sent < 0) { + if (errno == ECONNRESET || errno == ENOTCONN) { + self->connected = false; + } + return -errno; + } + + return sent; +} + +mp_uint_t common_hal_socketpool_socket_send(socketpool_socket_obj_t *self, const uint8_t *buf, uint32_t len) { + int sent = socketpool_socket_send(self, buf, len); + + if (sent < 0) { + mp_raise_OSError(-sent); + } + return sent; +} + +mp_uint_t common_hal_socketpool_socket_sendto(socketpool_socket_obj_t *self, + const char *host, size_t hostlen, uint32_t port, const uint8_t *buf, uint32_t len) { + + (void)hostlen; + struct sockaddr_storage addr; + resolve_host_or_throw(self, host, &addr, port); + + int bytes_sent = zsock_sendto(self->num, buf, len, 0, (struct sockaddr *)&addr, sizeof(addr)); + if (bytes_sent < 0) { + mp_raise_BrokenPipeError(); + return 0; + } + return bytes_sent; +} + +void common_hal_socketpool_socket_settimeout(socketpool_socket_obj_t *self, uint32_t timeout_ms) { + self->timeout_ms = timeout_ms; +} + +mp_int_t common_hal_socketpool_socket_get_type(socketpool_socket_obj_t *self) { + return self->type; +} + + +int common_hal_socketpool_socket_setsockopt(socketpool_socket_obj_t *self, int level, int optname, const void *value, size_t optlen) { + int zephyr_level = level; + int zephyr_optname = optname; + + switch (level) { + case SOCKETPOOL_SOL_SOCKET: + zephyr_level = SOL_SOCKET; + break; + case SOCKETPOOL_IPPROTO_IP: + zephyr_level = IPPROTO_IP; + break; + case SOCKETPOOL_IPPROTO_TCP: + zephyr_level = IPPROTO_TCP; + break; + case SOCKETPOOL_IPPROTO_UDP: + zephyr_level = IPPROTO_UDP; + break; + #if CIRCUITPY_SOCKETPOOL_IPV6 + case SOCKETPOOL_IPPROTO_IPV6: + zephyr_level = IPPROTO_IPV6; + break; + #endif + } + + if (zephyr_level == SOL_SOCKET) { + switch (optname) { + case SOCKETPOOL_SO_REUSEADDR: + zephyr_optname = SO_REUSEADDR; + break; + } + } else if (zephyr_level == IPPROTO_TCP) { + switch (optname) { + case SOCKETPOOL_TCP_NODELAY: + zephyr_optname = TCP_NODELAY; + break; + } + } + + int err = zsock_setsockopt(self->num, zephyr_level, zephyr_optname, value, optlen); + if (err != 0) { + return -errno; + } + return 0; +} + +bool common_hal_socketpool_readable(socketpool_socket_obj_t *self) { + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLIN, + }; + + int num_triggered = zsock_poll(&fd, 1, 0); + return num_triggered > 0; +} + +bool common_hal_socketpool_writable(socketpool_socket_obj_t *self) { + struct zsock_pollfd fd = { + .fd = self->num, + .events = ZSOCK_POLLOUT, + }; + + int num_triggered = zsock_poll(&fd, 1, 0); + return num_triggered > 0; +} + +void socketpool_socket_move(socketpool_socket_obj_t *self, socketpool_socket_obj_t *sock) { + *sock = *self; + self->connected = false; + self->num = -1; +} + +void socketpool_socket_reset(socketpool_socket_obj_t *self) { + if (self->base.type == &socketpool_socket_type) { + return; + } + self->base.type = &socketpool_socket_type; + self->connected = false; + self->num = -1; +} diff --git a/ports/zephyr-cp/common-hal/socketpool/Socket.h b/ports/zephyr-cp/common-hal/socketpool/Socket.h new file mode 100644 index 0000000000000..a093eea83f600 --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/Socket.h @@ -0,0 +1,29 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "common-hal/socketpool/SocketPool.h" + +typedef struct ssl_sslsocket_obj ssl_sslsocket_obj_t; + +typedef struct { + mp_obj_base_t base; + int num; + int type; + int family; + int ipproto; + bool connected; + socketpool_socketpool_obj_t *pool; + ssl_sslsocket_obj_t *ssl_socket; + mp_uint_t timeout_ms; +} socketpool_socket_obj_t; + +void socket_user_reset(void); +// Unblock workflow socket select thread (platform specific) +void socketpool_socket_poll_resume(void); diff --git a/ports/zephyr-cp/common-hal/socketpool/SocketPool.c b/ports/zephyr-cp/common-hal/socketpool/SocketPool.c new file mode 100644 index 0000000000000..c9a3f008321a1 --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/SocketPool.c @@ -0,0 +1,123 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/socketpool/SocketPool.h" +#include "common-hal/socketpool/Socket.h" + +#include "py/runtime.h" +#if CIRCUITPY_HOSTNETWORK +#include "bindings/hostnetwork/__init__.h" +#endif +#if CIRCUITPY_WIFI +#include "shared-bindings/wifi/__init__.h" +#endif +#include "common-hal/socketpool/__init__.h" + +#include +#include + +#include + +void common_hal_socketpool_socketpool_construct(socketpool_socketpool_obj_t *self, mp_obj_t radio) { + bool is_wifi = false; + #if CIRCUITPY_WIFI + is_wifi = radio == MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj); + #endif + bool is_hostnetwork = false; + #if CIRCUITPY_HOSTNETWORK + is_hostnetwork = mp_obj_is_type(radio, &hostnetwork_hostnetwork_type); + #endif + if (!(is_wifi || is_hostnetwork)) { + mp_raise_ValueError(MP_ERROR_TEXT("SocketPool can only be used with wifi.radio or hostnetwork.HostNetwork")); + } +} + +// common_hal_socketpool_socket is in socketpool/Socket.c to centralize open socket tracking. + +static int socketpool_getaddrinfo_common(const char *host, int service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res) { + char service_buf[6]; + snprintf(service_buf, sizeof(service_buf), "%d", service); + + return zsock_getaddrinfo(host, service_buf, hints, res); +} + +#define SOCKETPOOL_IP_STR_LEN 48 + +static mp_obj_t format_address(const struct sockaddr *addr, int family) { + char ip_str[SOCKETPOOL_IP_STR_LEN]; + const struct sockaddr_in *a = (void *)addr; + + switch (family) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + case AF_INET6: + zsock_inet_ntop(family, &((const struct sockaddr_in6 *)a)->sin6_addr, ip_str, sizeof(ip_str)); + break; + #endif + default: + case AF_INET: + zsock_inet_ntop(family, &((const struct sockaddr_in *)a)->sin_addr, ip_str, sizeof(ip_str)); + break; + } + return mp_obj_new_str(ip_str, strlen(ip_str)); +} + +static mp_obj_t convert_sockaddr(const struct zsock_addrinfo *ai, int port) { + #if CIRCUITPY_SOCKETPOOL_IPV6 + mp_int_t n_tuple = ai->ai_family == AF_INET6 ? 4 : 2; + #else + mp_int_t n_tuple = 2; + #endif + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_tuple, NULL)); + result->items[0] = format_address(ai->ai_addr, ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(port); + #if CIRCUITPY_SOCKETPOOL_IPV6 + if (ai->ai_family == AF_INET6) { + const struct sockaddr_in6 *ai6 = (void *)ai->ai_addr; + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_flowinfo); + result->items[3] = MP_OBJ_NEW_SMALL_INT(ai6->sin6_scope_id); + } + #endif + return result; +} + +static mp_obj_t convert_addrinfo(const struct zsock_addrinfo *ai, int port) { + mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL)); + result->items[0] = MP_OBJ_NEW_SMALL_INT(ai->ai_family); + result->items[1] = MP_OBJ_NEW_SMALL_INT(ai->ai_socktype); + result->items[2] = MP_OBJ_NEW_SMALL_INT(ai->ai_protocol); + result->items[3] = ai->ai_canonname ? mp_obj_new_str(ai->ai_canonname, strlen(ai->ai_canonname)) : MP_OBJ_NEW_QSTR(MP_QSTR_); + result->items[4] = convert_sockaddr(ai, port); + return result; +} + +mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags) { + const struct zsock_addrinfo hints = { + .ai_flags = flags, + .ai_family = family, + .ai_protocol = proto, + .ai_socktype = type, + }; + + struct zsock_addrinfo *res = NULL; + int err = socketpool_getaddrinfo_common(host, port, &hints, &res); + if (err != 0 || res == NULL) { + common_hal_socketpool_socketpool_raise_gaierror_noname(); + } + + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t result = mp_obj_new_list(0, NULL); + for (struct zsock_addrinfo *ai = res; ai; ai = ai->ai_next) { + mp_obj_list_append(result, convert_addrinfo(ai, port)); + } + nlr_pop(); + zsock_freeaddrinfo(res); + return result; + } else { + zsock_freeaddrinfo(res); + nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); + } +} diff --git a/ports/zephyr-cp/common-hal/socketpool/SocketPool.h b/ports/zephyr-cp/common-hal/socketpool/SocketPool.h new file mode 100644 index 0000000000000..7891a8b8e4820 --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/SocketPool.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; +} socketpool_socketpool_obj_t; diff --git a/ports/zephyr-cp/common-hal/socketpool/__init__.c b/ports/zephyr-cp/common-hal/socketpool/__init__.c new file mode 100644 index 0000000000000..c8558f9b80a3b --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/__init__.c @@ -0,0 +1,13 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/socketpool/__init__.h" + +#include "common-hal/socketpool/Socket.h" + +void socketpool_user_reset(void) { + socket_user_reset(); +} diff --git a/ports/zephyr-cp/common-hal/socketpool/__init__.h b/ports/zephyr-cp/common-hal/socketpool/__init__.h new file mode 100644 index 0000000000000..f7ccde7f3678a --- /dev/null +++ b/ports/zephyr-cp/common-hal/socketpool/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/zephyr-cp/common-hal/usb_cdc/Serial.c b/ports/zephyr-cp/common-hal/usb_cdc/Serial.c new file mode 100644 index 0000000000000..272a78b31419e --- /dev/null +++ b/ports/zephyr-cp/common-hal/usb_cdc/Serial.c @@ -0,0 +1,68 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared/runtime/interrupt_char.h" +#include "shared-bindings/usb_cdc/Serial.h" +#include "shared-bindings/busio/UART.h" +#include "supervisor/shared/tick.h" + +mp_obj_t common_hal_usb_cdc_serial_construct_from_device(usb_cdc_serial_obj_t *self, const struct device *uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer) { + common_hal_busio_uart_construct_from_device(self, uart_device, receiver_buffer_size, receiver_buffer); + self->base.type = &usb_cdc_serial_type; + return MP_OBJ_FROM_PTR(self); +} + +size_t common_hal_usb_cdc_serial_read(usb_cdc_serial_obj_t *self, uint8_t *data, size_t len, int *errcode) { + return common_hal_busio_uart_read(self, data, len, errcode); +} + +size_t common_hal_usb_cdc_serial_write(usb_cdc_serial_obj_t *self, const uint8_t *data, size_t len, int *errcode) { + return common_hal_busio_uart_write(self, data, len, errcode); +} + +uint32_t common_hal_usb_cdc_serial_get_in_waiting(usb_cdc_serial_obj_t *self) { + return common_hal_busio_uart_rx_characters_available(self); +} + +uint32_t common_hal_usb_cdc_serial_get_out_waiting(usb_cdc_serial_obj_t *self) { + // Return number of FIFO bytes currently occupied. + // return CFG_TUD_CDC_TX_BUFSIZE - tud_cdc_n_write_available(self->idx); + return 0; +} + +void common_hal_usb_cdc_serial_reset_input_buffer(usb_cdc_serial_obj_t *self) { + common_hal_busio_uart_clear_rx_buffer(self); +} + +uint32_t common_hal_usb_cdc_serial_reset_output_buffer(usb_cdc_serial_obj_t *self) { + // return tud_cdc_n_write_clear(self->idx); + return 0; +} + +uint32_t common_hal_usb_cdc_serial_flush(usb_cdc_serial_obj_t *self) { + // return tud_cdc_n_write_flush(self->idx); + return 0; +} + +bool common_hal_usb_cdc_serial_get_connected(usb_cdc_serial_obj_t *self) { + return !common_hal_busio_uart_deinited(self); +} + +mp_float_t common_hal_usb_cdc_serial_get_timeout(usb_cdc_serial_obj_t *self) { + return common_hal_busio_uart_get_timeout(self); +} + +void common_hal_usb_cdc_serial_set_timeout(usb_cdc_serial_obj_t *self, mp_float_t timeout) { + common_hal_busio_uart_set_timeout(self, timeout); +} + +mp_float_t common_hal_usb_cdc_serial_get_write_timeout(usb_cdc_serial_obj_t *self) { + return common_hal_busio_uart_get_write_timeout(self); +} + +void common_hal_usb_cdc_serial_set_write_timeout(usb_cdc_serial_obj_t *self, mp_float_t write_timeout) { + common_hal_busio_uart_set_write_timeout(self, write_timeout); +} diff --git a/ports/zephyr-cp/common-hal/usb_cdc/Serial.h b/ports/zephyr-cp/common-hal/usb_cdc/Serial.h new file mode 100644 index 0000000000000..9a110545a3700 --- /dev/null +++ b/ports/zephyr-cp/common-hal/usb_cdc/Serial.h @@ -0,0 +1,14 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-bindings/busio/UART.h" + +typedef busio_uart_obj_t usb_cdc_serial_obj_t; + +// Helper function for Zephyr-specific initialization from device tree +mp_obj_t common_hal_usb_cdc_serial_construct_from_device(usb_cdc_serial_obj_t *self, const struct device *uart_device, uint16_t receiver_buffer_size, byte *receiver_buffer); diff --git a/ports/zephyr-cp/common-hal/usb_cdc/__init__.c b/ports/zephyr-cp/common-hal/usb_cdc/__init__.c new file mode 100644 index 0000000000000..7bcae39673320 --- /dev/null +++ b/ports/zephyr-cp/common-hal/usb_cdc/__init__.c @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/gc.h" +#include "py/obj.h" +#include "py/mphal.h" +#include "py/runtime.h" +#include "py/objtuple.h" +#include "shared-bindings/usb_cdc/__init__.h" +#include "shared-bindings/usb_cdc/Serial.h" +#include "supervisor/usb.h" + +static bool usb_cdc_console_is_enabled; +static bool usb_cdc_data_is_enabled; + +void usb_cdc_set_defaults(void) { + common_hal_usb_cdc_enable(true, + false); +} + +bool usb_cdc_console_enabled(void) { + return usb_cdc_console_is_enabled; +} + +bool usb_cdc_data_enabled(void) { + return usb_cdc_data_is_enabled; +} + +bool common_hal_usb_cdc_disable(void) { + return common_hal_usb_cdc_enable(false, false); +} + +bool common_hal_usb_cdc_enable(bool console, bool data) { + usb_cdc_console_is_enabled = console; + usb_cdc_data_is_enabled = data; + return true; +} diff --git a/ports/zephyr-cp/common-hal/usb_cdc/__init__.h b/ports/zephyr-cp/common-hal/usb_cdc/__init__.h new file mode 100644 index 0000000000000..daf06d580ad63 --- /dev/null +++ b/ports/zephyr-cp/common-hal/usb_cdc/__init__.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/mpconfig.h" +#include "py/objtuple.h" +#include "supervisor/usb.h" + +bool usb_cdc_console_enabled(void); +bool usb_cdc_data_enabled(void); + +void usb_cdc_set_defaults(void); diff --git a/ports/zephyr-cp/common-hal/wifi/Monitor.c b/ports/zephyr-cp/common-hal/wifi/Monitor.c new file mode 100644 index 0000000000000..7cacb8b520a96 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Monitor.c @@ -0,0 +1,146 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/mpstate.h" +#include "py/runtime.h" + +#include "shared-bindings/wifi/Monitor.h" +#include "shared-bindings/wifi/Packet.h" + +#define MONITOR_PAYLOAD_FCS_LEN (4) +#define MONITOR_QUEUE_TIMEOUT_TICK (0) + +typedef struct { + void *payload; + unsigned channel; + uint32_t length; + signed rssi; +} monitor_packet_t; + +// static void wifi_monitor_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type) { +// wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)recv_buf; + +// // prepare packet +// monitor_packet_t packet = { +// .channel = pkt->rx_ctrl.channel, +// .length = pkt->rx_ctrl.sig_len, +// .rssi = pkt->rx_ctrl.rssi, +// }; + +// // for now, the monitor only dumps the length of the MISC type frame +// if (type != WIFI_PKT_MISC && !pkt->rx_ctrl.rx_state) { +// packet.length -= MONITOR_PAYLOAD_FCS_LEN; +// packet.payload = malloc(packet.length); +// if (packet.payload) { +// memcpy(packet.payload, pkt->payload, packet.length); +// wifi_monitor_obj_t *self = MP_STATE_VM(wifi_monitor_singleton); +// if (self->queue) { +// // send packet +// if (xQueueSendFromISR(self->queue, &packet, NULL) != pdTRUE) { +// self->lost++; +// free(packet.payload); +// ESP_LOGE(TAG, "packet queue full"); +// } +// } +// } else { +// ESP_LOGE(TAG, "not enough memory for packet"); +// } +// } +// } + +void common_hal_wifi_monitor_construct(wifi_monitor_obj_t *self, uint8_t channel, size_t queue) { + // mp_rom_error_text_t monitor_mode_init_error = MP_ERROR_TEXT("monitor init failed"); + + // self->queue = xQueueCreate(queue, sizeof(monitor_packet_t)); + // if (!self->queue) { + // mp_raise_RuntimeError(monitor_mode_init_error); + // } + + // // start wifi promicuous mode + // wifi_promiscuous_filter_t wifi_filter = { + // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT, + // }; + // esp_wifi_set_promiscuous_filter(&wifi_filter); + // esp_wifi_set_promiscuous_rx_cb(wifi_monitor_cb); + // if (esp_wifi_set_promiscuous(true) != ESP_OK) { + // mp_raise_RuntimeError(monitor_mode_init_error); + // } + // esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); + + // self->channel = channel; + // self->queue_length = queue; +} + +bool common_hal_wifi_monitor_deinited(void) { + // bool enabled; + // return (esp_wifi_get_promiscuous(&enabled) == ESP_ERR_WIFI_NOT_INIT) ? true : !enabled; + return true; +} + +void common_hal_wifi_monitor_deinit(wifi_monitor_obj_t *self) { + if (common_hal_wifi_monitor_deinited()) { + return; + } + + // // disable wifi promiscuous mode + // esp_wifi_set_promiscuous(false); + + // // make sure to free all resources in the left items + // UBaseType_t left_items = uxQueueMessagesWaiting(self->queue); + // monitor_packet_t packet; + // while (left_items--) { + // xQueueReceive(self->queue, &packet, MONITOR_QUEUE_TIMEOUT_TICK); + // free(packet.payload); + // } + // vQueueDelete(self->queue); + // self->queue = NULL; +} + +void common_hal_wifi_monitor_set_channel(wifi_monitor_obj_t *self, uint8_t channel) { + self->channel = channel; + // esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); +} + +mp_obj_t common_hal_wifi_monitor_get_channel(wifi_monitor_obj_t *self) { + return MP_OBJ_NEW_SMALL_INT(self->channel); +} + +mp_obj_t common_hal_wifi_monitor_get_queue(wifi_monitor_obj_t *self) { + return mp_obj_new_int_from_uint(self->queue_length); +} + +mp_obj_t common_hal_wifi_monitor_get_lost(wifi_monitor_obj_t *self) { + size_t lost = self->lost; + self->lost = 0; + return mp_obj_new_int_from_uint(lost); +} + +mp_obj_t common_hal_wifi_monitor_get_queued(wifi_monitor_obj_t *self) { + return mp_obj_new_int_from_uint(0); // uxQueueMessagesWaiting(self->queue)); +} + +mp_obj_t common_hal_wifi_monitor_get_packet(wifi_monitor_obj_t *self) { + monitor_packet_t packet; + + // if (xQueueReceive(self->queue, &packet, MONITOR_QUEUE_TIMEOUT_TICK) != pdTRUE) { + // return (mp_obj_t)&mp_const_empty_dict_obj; + // } + + mp_obj_dict_t *dict = MP_OBJ_TO_PTR(mp_obj_new_dict(4)); + + mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_CH), MP_OBJ_NEW_SMALL_INT(packet.channel)); + + mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_LEN), MP_OBJ_NEW_SMALL_INT(packet.length)); + + mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_RAW), mp_obj_new_bytes(packet.payload, packet.length)); + free(packet.payload); + + mp_obj_dict_store(dict, cp_enum_find(&wifi_packet_type, PACKET_RSSI), MP_OBJ_NEW_SMALL_INT(packet.rssi)); + + return MP_OBJ_FROM_PTR(dict); +} diff --git a/ports/zephyr-cp/common-hal/wifi/Monitor.h b/ports/zephyr-cp/common-hal/wifi/Monitor.h new file mode 100644 index 0000000000000..e0cdd7b619fc8 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Monitor.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + uint8_t channel; + size_t lost; + size_t queue_length; + // QueueHandle_t queue; +} wifi_monitor_obj_t; diff --git a/ports/zephyr-cp/common-hal/wifi/Network.c b/ports/zephyr-cp/common-hal/wifi/Network.c new file mode 100644 index 0000000000000..44c049f88c1db --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Network.c @@ -0,0 +1,75 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/wifi/Network.h" +#include "shared-bindings/wifi/AuthMode.h" + +mp_obj_t common_hal_wifi_network_get_ssid(wifi_network_obj_t *self) { + const char *cstr = (const char *)self->scan_result.ssid; + return mp_obj_new_str(cstr, self->scan_result.ssid_length); +} + +mp_obj_t common_hal_wifi_network_get_bssid(wifi_network_obj_t *self) { + return mp_obj_new_bytes(self->scan_result.mac, self->scan_result.mac_length); +} + +mp_obj_t common_hal_wifi_network_get_rssi(wifi_network_obj_t *self) { + return mp_obj_new_int(self->scan_result.rssi); +} + +mp_obj_t common_hal_wifi_network_get_channel(wifi_network_obj_t *self) { + return mp_obj_new_int(self->scan_result.channel); +} + +mp_obj_t common_hal_wifi_network_get_country(wifi_network_obj_t *self) { + // const char *cstr = (const char *)self->record.country.cc; + // 2 instead of strlen(cstr) as this gives us only the country-code + // return mp_obj_new_str(cstr, 2); + return mp_const_none; +} + +mp_obj_t common_hal_wifi_network_get_authmode(wifi_network_obj_t *self) { + uint32_t authmode_mask = 0; + // switch (self->record.authmode) { + // case WIFI_AUTH_OPEN: + // authmode_mask = AUTHMODE_OPEN; + // break; + // case WIFI_AUTH_WEP: + // authmode_mask = AUTHMODE_WEP; + // break; + // case WIFI_AUTH_WPA_PSK: + // authmode_mask = AUTHMODE_WPA | AUTHMODE_PSK; + // break; + // case WIFI_AUTH_WPA2_PSK: + // authmode_mask = AUTHMODE_WPA2 | AUTHMODE_PSK; + // break; + // case WIFI_AUTH_WPA_WPA2_PSK: + // authmode_mask = AUTHMODE_WPA | AUTHMODE_WPA2 | AUTHMODE_PSK; + // break; + // case WIFI_AUTH_WPA2_ENTERPRISE: + // authmode_mask = AUTHMODE_WPA2 | AUTHMODE_ENTERPRISE; + // break; + // case WIFI_AUTH_WPA3_PSK: + // authmode_mask = AUTHMODE_WPA3 | AUTHMODE_PSK; + // break; + // case WIFI_AUTH_WPA2_WPA3_PSK: + // authmode_mask = AUTHMODE_WPA2 | AUTHMODE_WPA3 | AUTHMODE_PSK; + // break; + // default: + // break; + // } + mp_obj_t authmode_list = mp_obj_new_list(0, NULL); + if (authmode_mask != 0) { + for (uint8_t i = 0; i < 32; i++) { + if ((authmode_mask >> i) & 1) { + mp_obj_list_append(authmode_list, cp_enum_find(&wifi_authmode_type, 1 << i)); + } + } + } + return authmode_list; +} diff --git a/ports/zephyr-cp/common-hal/wifi/Network.h b/ports/zephyr-cp/common-hal/wifi/Network.h new file mode 100644 index 0000000000000..bd6bc07ea1e55 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Network.h @@ -0,0 +1,16 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include + +typedef struct { + mp_obj_base_t base; + struct wifi_scan_result scan_result; +} wifi_network_obj_t; diff --git a/ports/zephyr-cp/common-hal/wifi/Radio.c b/ports/zephyr-cp/common-hal/wifi/Radio.c new file mode 100644 index 0000000000000..35a0b76a36268 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Radio.c @@ -0,0 +1,780 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/wifi/Radio.h" +#include "ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h" +#include "shared-bindings/wifi/Network.h" + +#include + +#include "common-hal/wifi/__init__.h" +#include "shared/runtime/interrupt_char.h" +#include "py/gc.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "shared-bindings/ipaddress/IPv4Address.h" +#include "shared-bindings/wifi/ScannedNetworks.h" +#include "shared-bindings/wifi/AuthMode.h" +#include "shared-bindings/time/__init__.h" +#include "shared-module/ipaddress/__init__.h" +#include "common-hal/socketpool/__init__.h" + +#include "bindings/zephyr_kernel/__init__.h" + +#include +#include +#include +#include + +#if CIRCUITPY_MDNS +#include "common-hal/mdns/Server.h" +#endif + +#define MAC_ADDRESS_LENGTH 6 + +// static void set_mode_station(wifi_radio_obj_t *self, bool state) { +// wifi_mode_t next_mode; +// if (state) { +// if (self->ap_mode) { +// next_mode = WIFI_MODE_APSTA; +// } else { +// next_mode = WIFI_MODE_STA; +// } +// } else { +// if (self->ap_mode) { +// next_mode = WIFI_MODE_AP; +// } else { +// next_mode = WIFI_MODE_NULL; +// } +// } +// esp_wifi_set_mode(next_mode); +// self->sta_mode = state; +// } + +// static void set_mode_ap(wifi_radio_obj_t *self, bool state) { +// wifi_mode_t next_mode; +// if (state) { +// if (self->sta_mode) { +// next_mode = WIFI_MODE_APSTA; +// } else { +// next_mode = WIFI_MODE_AP; +// } +// } else { +// if (self->sta_mode) { +// next_mode = WIFI_MODE_STA; +// } else { +// next_mode = WIFI_MODE_NULL; +// } +// } +// esp_wifi_set_mode(next_mode); +// self->ap_mode = state; +// } + +bool common_hal_wifi_radio_get_enabled(wifi_radio_obj_t *self) { + return self->started; +} + +void common_hal_wifi_radio_set_enabled(wifi_radio_obj_t *self, bool enabled) { + if (self->started && !enabled) { + if (self->current_scan != NULL) { + common_hal_wifi_radio_stop_scanning_networks(self); + } + // #if CIRCUITPY_MDNS + // mdns_server_deinit_singleton(); + // #endif + printk("net_if_down\n"); + int res = net_if_down(self->sta_netif); + if (res < 0 && res != -EALREADY) { + raise_zephyr_error(res); + } + self->started = false; + return; + } + if (!self->started && enabled) { + printk("net_if_up\n"); + int res = net_if_up(self->sta_netif); + if (res < 0 && res != -EALREADY) { + raise_zephyr_error(res); + } + self->started = true; + self->current_scan = NULL; + // common_hal_wifi_radio_set_tx_power(self, CIRCUITPY_WIFI_DEFAULT_TX_POWER); + return; + } +} + +mp_obj_t common_hal_wifi_radio_get_hostname(wifi_radio_obj_t *self) { + const char *hostname = net_hostname_get(); + return mp_obj_new_str(hostname, strlen(hostname)); +} + +void common_hal_wifi_radio_set_hostname(wifi_radio_obj_t *self, const char *hostname) { + if (net_hostname_set((char *)hostname, strlen(hostname)) != 0) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Failed to set hostname")); + } +} + +mp_obj_t common_hal_wifi_radio_get_mac_address(wifi_radio_obj_t *self) { + uint8_t mac[MAC_ADDRESS_LENGTH]; + // esp_wifi_get_mac(ESP_IF_WIFI_STA, mac); + return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH); +} + +void common_hal_wifi_radio_set_mac_address(wifi_radio_obj_t *self, const uint8_t *mac) { + if (!self->sta_mode) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Interface must be started")); + } + if ((mac[0] & 0b1) == 0b1) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address")); + } + // esp_wifi_set_mac(ESP_IF_WIFI_STA, mac); +} + +mp_float_t common_hal_wifi_radio_get_tx_power(wifi_radio_obj_t *self) { + int8_t tx_power = 0; + // esp_wifi_get_max_tx_power(&tx_power); + return tx_power / 4.0f; +} + +void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t tx_power) { + // esp_wifi_set_max_tx_power(tx_power * 4.0f); +} + +wifi_power_management_t common_hal_wifi_radio_get_power_management(wifi_radio_obj_t *self) { + // wifi_ps_type_t ps; + // esp_err_t ret = esp_wifi_get_ps(&ps); + // if (ret == ESP_OK) { + // switch (ps) { + // case WIFI_PS_MIN_MODEM: + // return POWER_MANAGEMENT_MIN; + // case WIFI_PS_MAX_MODEM: + // return POWER_MANAGEMENT_MAX; + // case WIFI_PS_NONE: + // return POWER_MANAGEMENT_NONE; + // } + // } + return POWER_MANAGEMENT_UNKNOWN; +} + + +void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_power_management_t power_management) { + // switch (power_management) { + // case POWER_MANAGEMENT_MIN: + // esp_wifi_set_ps(WIFI_PS_MIN_MODEM); + // break; + // case POWER_MANAGEMENT_MAX: { + // // listen_interval is only used in this case. + // wifi_config_t *config = &self->sta_config; + // // This is a typical value seen in various examples. + // config->sta.listen_interval = 3; + // esp_wifi_set_ps(WIFI_PS_MAX_MODEM); + // esp_wifi_set_config(ESP_IF_WIFI_STA, config); + // } + // break; + // case POWER_MANAGEMENT_NONE: + // esp_wifi_set_ps(WIFI_PS_NONE); + // break; + // case POWER_MANAGEMENT_UNKNOWN: + // // This should be prevented in shared-bindings. + // break; + // } +} + +void common_hal_wifi_radio_set_listen_interval(wifi_radio_obj_t *self, const mp_int_t listen_interval) { + // wifi_config_t *config = &self->sta_config; + // config->sta.listen_interval = listen_interval; + // if (listen_interval == 1) { + // esp_wifi_set_ps(WIFI_PS_MIN_MODEM); + // } else if (listen_interval > 1) { + // esp_wifi_set_ps(WIFI_PS_MAX_MODEM); + // } else { + // esp_wifi_set_ps(WIFI_PS_NONE); + // } + + // esp_wifi_set_config(ESP_IF_WIFI_STA, config); +} + +mp_obj_t common_hal_wifi_radio_get_mac_address_ap(wifi_radio_obj_t *self) { + uint8_t mac[MAC_ADDRESS_LENGTH]; + // esp_wifi_get_mac(ESP_IF_WIFI_AP, mac); + return mp_obj_new_bytes(mac, MAC_ADDRESS_LENGTH); +} + +void common_hal_wifi_radio_set_mac_address_ap(wifi_radio_obj_t *self, const uint8_t *mac) { + if (!self->ap_mode) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Interface must be started")); + } + if ((mac[0] & 0b1) == 0b1) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid multicast MAC address")); + } + // esp_wifi_set_mac(ESP_IF_WIFI_AP, mac); +} + +mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, uint8_t start_channel, uint8_t stop_channel) { + printk("common_hal_wifi_radio_start_scanning_networks\n"); + if (self->current_scan != NULL) { + printk("Already scanning for wifi networks\n"); + mp_raise_RuntimeError(MP_ERROR_TEXT("Already scanning for wifi networks")); + } + if (!common_hal_wifi_radio_get_enabled(self)) { + printk("WiFi is not enabled\n"); + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); + } + + wifi_scannednetworks_obj_t *scan = mp_obj_malloc(wifi_scannednetworks_obj_t, &wifi_scannednetworks_type); + self->current_scan = scan; + scan->current_channel_index = 0; + scan->start_channel = start_channel; + scan->end_channel = stop_channel; + scan->done = false; + scan->channel_scan_in_progress = false; + scan->netif = self->sta_netif; + + k_msgq_init(&scan->msgq, scan->msgq_buffer, sizeof(struct wifi_scan_result), MAX_BUFFERED_SCAN_RESULTS); + k_fifo_init(&scan->fifo); + + k_poll_event_init(&scan->events[0], + K_POLL_TYPE_SEM_AVAILABLE, + K_POLL_MODE_NOTIFY_ONLY, + &mp_interrupt_sem); + + k_poll_event_init(&scan->events[1], + K_POLL_TYPE_MSGQ_DATA_AVAILABLE, + K_POLL_MODE_NOTIFY_ONLY, + &scan->msgq); + wifi_scannednetworks_scan_next_channel(scan); + printk("common_hal_wifi_radio_start_scanning_networks done %p\n", scan); + return scan; +} + +void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self) { + printk("common_hal_wifi_radio_stop_scanning_networks\n"); + // Return early if self->current_scan is NULL to avoid hang + if (self->current_scan == NULL) { + return; + } + // Free the memory used to store the found aps. + wifi_scannednetworks_deinit(self->current_scan); + self->current_scan = NULL; +} + +void common_hal_wifi_radio_start_station(wifi_radio_obj_t *self) { + // set_mode_station(self, true); +} + +void common_hal_wifi_radio_stop_station(wifi_radio_obj_t *self) { + // set_mode_station(self, false); +} + +void common_hal_wifi_radio_start_ap(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, uint32_t authmode, uint8_t max_connections) { + // set_mode_ap(self, true); + + // uint8_t esp_authmode = 0; + // switch (authmode) { + // case AUTHMODE_OPEN: + // esp_authmode = WIFI_AUTH_OPEN; + // break; + // case AUTHMODE_WPA | AUTHMODE_PSK: + // esp_authmode = WIFI_AUTH_WPA_PSK; + // break; + // case AUTHMODE_WPA2 | AUTHMODE_PSK: + // esp_authmode = WIFI_AUTH_WPA2_PSK; + // break; + // case AUTHMODE_WPA | AUTHMODE_WPA2 | AUTHMODE_PSK: + // esp_authmode = WIFI_AUTH_WPA_WPA2_PSK; + // break; + // default: + // mp_arg_error_invalid(MP_QSTR_authmode); + // break; + // } + + // wifi_config_t *config = &self->ap_config; + // memcpy(&config->ap.ssid, ssid, ssid_len); + // config->ap.ssid[ssid_len] = 0; + // memcpy(&config->ap.password, password, password_len); + // config->ap.password[password_len] = 0; + // config->ap.channel = channel; + // config->ap.authmode = esp_authmode; + + // mp_arg_validate_int_range(max_connections, 0, 10, MP_QSTR_max_connections); + + // config->ap.max_connection = max_connections; + + // esp_wifi_set_config(WIFI_IF_AP, config); +} + +bool common_hal_wifi_radio_get_ap_active(wifi_radio_obj_t *self) { + // return self->ap_mode && esp_netif_is_netif_up(self->ap_netif); + return false; +} + +void common_hal_wifi_radio_stop_ap(wifi_radio_obj_t *self) { + // set_mode_ap(self, false); +} + +mp_obj_t common_hal_wifi_radio_get_stations_ap(wifi_radio_obj_t *self) { + // wifi_sta_list_t esp_sta_list; + // esp_err_t result; + + // result = esp_wifi_ap_get_sta_list(&esp_sta_list); + // if (result != ESP_OK) { + // return mp_const_none; + // } + + // esp_netif_pair_mac_ip_t mac_ip_pair[esp_sta_list.num]; + // for (int i = 0; i < esp_sta_list.num; i++) { + // memcpy(mac_ip_pair[i].mac, esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH); + // mac_ip_pair[i].ip.addr = 0; + // } + + // result = esp_netif_dhcps_get_clients_by_mac(self->ap_netif, esp_sta_list.num, mac_ip_pair); + // if (result != ESP_OK) { + // return mp_const_none; + // } + + mp_obj_t mp_sta_list = mp_obj_new_list(0, NULL); + // for (int i = 0; i < esp_sta_list.num; i++) { + // mp_obj_t elems[3] = { + // mp_obj_new_bytes(esp_sta_list.sta[i].mac, MAC_ADDRESS_LENGTH), + // MP_OBJ_NEW_SMALL_INT(esp_sta_list.sta[i].rssi), + // mp_const_none + // }; + + // if (mac_ip_pair[i].ip.addr) { + // elems[2] = common_hal_ipaddress_new_ipv4address(mac_ip_pair[i].ip.addr); + // } + + // mp_obj_list_append(mp_sta_list, namedtuple_make_new((const mp_obj_type_t *)&wifi_radio_station_type, 3, 0, elems)); + // } + + return mp_sta_list; +} + +wifi_radio_error_t common_hal_wifi_radio_connect(wifi_radio_obj_t *self, uint8_t *ssid, size_t ssid_len, uint8_t *password, size_t password_len, uint8_t channel, mp_float_t timeout, uint8_t *bssid, size_t bssid_len) { + if (!common_hal_wifi_radio_get_enabled(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("WiFi is not enabled")); + } + // wifi_config_t *config = &self->sta_config; + + // size_t timeout_ms = timeout * 1000; + // uint32_t start_time = common_hal_time_monotonic_ms(); + // uint32_t end_time = start_time + timeout_ms; + + // EventBits_t bits; + // // can't block since both bits are false after wifi_init + // // both bits are true after an existing connection stops + // bits = xEventGroupWaitBits(self->event_group_handle, + // WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT, + // pdTRUE, + // pdTRUE, + // 0); + // bool connected = ((bits & WIFI_CONNECTED_BIT) != 0) && + // !((bits & WIFI_DISCONNECTED_BIT) != 0); + // if (connected) { + // // SSIDs are up to 32 bytes. Assume it is null terminated if it is less. + // if (memcmp(ssid, config->sta.ssid, ssid_len) == 0 && + // (ssid_len == 32 || strlen((const char *)config->sta.ssid) == ssid_len)) { + // // Already connected to the desired network. + // return WIFI_RADIO_ERROR_NONE; + // } else { + // xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT); + // // Trying to switch networks so disconnect first. + // esp_wifi_disconnect(); + // do { + // RUN_BACKGROUND_TASKS; + // bits = xEventGroupWaitBits(self->event_group_handle, + // WIFI_DISCONNECTED_BIT, + // pdTRUE, + // pdTRUE, + // 0); + // } while ((bits & WIFI_DISCONNECTED_BIT) == 0 && !mp_hal_is_interrupted()); + // } + // } + // // explicitly clear bits since xEventGroupWaitBits may have timed out + // xEventGroupClearBits(self->event_group_handle, WIFI_CONNECTED_BIT); + // xEventGroupClearBits(self->event_group_handle, WIFI_DISCONNECTED_BIT); + // set_mode_station(self, true); + + // memcpy(&config->sta.ssid, ssid, ssid_len); + // if (ssid_len < 32) { + // config->sta.ssid[ssid_len] = 0; + // } + // memcpy(&config->sta.password, password, password_len); + // config->sta.password[password_len] = 0; + // config->sta.channel = channel; + // // From esp_wifi_types.h: + // // Generally, station_config.bssid_set needs to be 0; and it needs + // // to be 1 only when users need to check the MAC address of the AP + // if (bssid_len > 0) { + // memcpy(&config->sta.bssid, bssid, bssid_len); + // config->sta.bssid[bssid_len] = 0; + // config->sta.bssid_set = true; + // } else { + // config->sta.bssid_set = false; + // } + // // If channel is 0 (default/unset) and BSSID is not given, do a full scan instead of fast scan + // // This will ensure that the best AP in range is chosen automatically + // if ((config->sta.bssid_set == 0) && (config->sta.channel == 0)) { + // config->sta.scan_method = WIFI_ALL_CHANNEL_SCAN; + // } else { + // config->sta.scan_method = WIFI_FAST_SCAN; + // } + // esp_wifi_set_config(ESP_IF_WIFI_STA, config); + // self->starting_retries = 5; + // self->retries_left = 5; + // esp_wifi_connect(); + + // do { + // RUN_BACKGROUND_TASKS; + // bits = xEventGroupWaitBits(self->event_group_handle, + // WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT, + // pdTRUE, + // pdTRUE, + // 0); + // // Don't retry anymore if we're over our time budget. + // if (self->retries_left > 0 && common_hal_time_monotonic_ms() > end_time) { + // self->retries_left = 0; + // } + // } while ((bits & (WIFI_CONNECTED_BIT | WIFI_DISCONNECTED_BIT)) == 0 && !mp_hal_is_interrupted()); + + // if ((bits & WIFI_DISCONNECTED_BIT) != 0) { + // if ( + // (self->last_disconnect_reason == WIFI_REASON_AUTH_FAIL) || + // (self->last_disconnect_reason == WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT) || + // (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND_W_COMPATIBLE_SECURITY) || + // (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND_IN_AUTHMODE_THRESHOLD) + // ) { + // return WIFI_RADIO_ERROR_AUTH_FAIL; + // } else if (self->last_disconnect_reason == WIFI_REASON_NO_AP_FOUND) { + // return WIFI_RADIO_ERROR_NO_AP_FOUND; + // } + // return self->last_disconnect_reason; + // } else { + // // We're connected, allow us to retry if we get disconnected. + // self->retries_left = self->starting_retries; + // } + return WIFI_RADIO_ERROR_NONE; +} + +bool common_hal_wifi_radio_get_connected(wifi_radio_obj_t *self) { + // return self->sta_mode && esp_netif_is_netif_up(self->netif); + return false; +} + +mp_obj_t common_hal_wifi_radio_get_ap_info(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + // } + + // // Make sure the interface is in STA mode + // if (!self->sta_mode) { + // return mp_const_none; + // } + + // wifi_network_obj_t *ap_info = mp_obj_malloc(wifi_network_obj_t, &wifi_network_type); + // // From esp_wifi.h, the possible return values (typos theirs): + // // ESP_OK: succeed + // // ESP_ERR_WIFI_CONN: The station interface don't initialized + // // ESP_ERR_WIFI_NOT_CONNECT: The station is in disconnect status + // if (esp_wifi_sta_get_ap_info(&self->ap_info.record) != ESP_OK) { + // return mp_const_none; + // } else { + // if (strlen(self->ap_info.record.country.cc) == 0) { + // // Workaround to fill country related information in ap_info until ESP-IDF carries a fix + // // esp_wifi_sta_get_ap_info does not appear to fill wifi_country_t (e.g. country.cc) details + // // (IDFGH-4437) #6267 + // // Note: It is possible that Wi-Fi APs don't have a CC set, then even after this workaround + // // the element would remain empty. + // memset(&self->ap_info.record.country, 0, sizeof(wifi_country_t)); + // if (esp_wifi_get_country(&self->ap_info.record.country) != ESP_OK) { + // return mp_const_none; + // } + // } + // memcpy(&ap_info->record, &self->ap_info.record, sizeof(wifi_ap_record_t)); + // return MP_OBJ_FROM_PTR(ap_info); + // } +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_gateway(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + // } + // esp_netif_get_ip_info(self->netif, &self->ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ip_info.gw.addr); +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_gateway_ap(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->ap_netif)) { + return mp_const_none; + // } + // esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.gw.addr); +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_subnet(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + return mp_const_none; + // } + // esp_netif_get_ip_info(self->netif, &self->ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ip_info.netmask.addr); +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_subnet_ap(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->ap_netif)) { + return mp_const_none; + // } + // esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.netmask.addr); +} + +// static mp_obj_t common_hal_wifi_radio_get_addresses_netif(wifi_radio_obj_t *self, esp_netif_t *netif) { +// if (!esp_netif_is_netif_up(netif)) { +// return mp_const_empty_tuple; +// } +// esp_netif_ip_info_t ip_info; +// esp_netif_get_ip_info(netif, &ip_info); +// int n_addresses4 = ip_info.ip.addr != INADDR_NONE; + +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// esp_ip6_addr_t addresses[LWIP_IPV6_NUM_ADDRESSES]; +// int n_addresses6 = esp_netif_get_all_ip6(netif, &addresses[0]); +// #else +// int n_addresses6 = 0; +// #endif +// int n_addresses = n_addresses4 + n_addresses6; +// mp_obj_tuple_t *result = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_addresses, NULL)); + +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// for (int i = 0; i < n_addresses6; i++) { +// result->items[i] = espaddr6_to_str(&addresses[i]); +// } +// #endif + +// if (n_addresses4) { +// result->items[n_addresses6] = espaddr4_to_str(&ip_info.ip); +// } + +// return MP_OBJ_FROM_PTR(result); +// return mp_const_empty_tuple; +// } + +mp_obj_t common_hal_wifi_radio_get_addresses(wifi_radio_obj_t *self) { + // return common_hal_wifi_radio_get_addresses_netif(self, self->netif); + return mp_const_none; +} + +mp_obj_t common_hal_wifi_radio_get_addresses_ap(wifi_radio_obj_t *self) { + // return common_hal_wifi_radio_get_addresses_netif(self, self->ap_netif); + return mp_const_none; +} + +uint32_t wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + // return 0; + // } + // esp_netif_get_ip_info(self->netif, &self->ip_info); + // return self->ip_info.ip.addr; + return 0; +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_address(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + // return mp_const_none; + // } + // esp_netif_get_ip_info(self->netif, &self->ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ip_info.ip.addr); + return mp_const_none; +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_address_ap(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->ap_netif)) { + // return mp_const_none; + // } + // esp_netif_get_ip_info(self->ap_netif, &self->ap_ip_info); + // return common_hal_ipaddress_new_ipv4address(self->ap_ip_info.ip.addr); + return mp_const_none; +} + +mp_obj_t common_hal_wifi_radio_get_ipv4_dns(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + // return mp_const_none; + // } + + // esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info); + + // if (self->dns_info.ip.type != ESP_IPADDR_TYPE_V4) { + // return mp_const_none; + // } + // // dns_info is of type esp_netif_dns_info_t, which is just ever so slightly + // // different than esp_netif_ip_info_t used for + // // common_hal_wifi_radio_get_ipv4_address (includes both ipv4 and 6), + // // so some extra jumping is required to get to the actual address + // return common_hal_ipaddress_new_ipv4address(self->dns_info.ip.u_addr.ip4.addr); + return mp_const_none; +} + +void common_hal_wifi_radio_set_ipv4_dns(wifi_radio_obj_t *self, mp_obj_t ipv4_dns_addr) { + // esp_netif_dns_info_t dns_addr; + // ipaddress_ipaddress_to_esp_idf_ip4(ipv4_dns_addr, &dns_addr.ip.u_addr.ip4); + // esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_addr); +} + +void common_hal_wifi_radio_start_dhcp_client(wifi_radio_obj_t *self, bool ipv4, bool ipv6) { + // if (ipv4) { + // esp_netif_dhcpc_start(self->netif); + // } else { + // esp_netif_dhcpc_stop(self->netif); + // } + // #if LWIP_IPV6_DHCP6 + // if (ipv6) { + // esp_netif_create_ip6_linklocal(self->netif); + // dhcp6_enable_stateless(esp_netif_get_netif_impl(self->netif)); + // } else { + // dhcp6_disable(esp_netif_get_netif_impl(self->netif)); + // } + // #else + // if (ipv6) { + // mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_ipv6); + // } + // #endif +} + +void common_hal_wifi_radio_stop_dhcp_client(wifi_radio_obj_t *self) { + // esp_netif_dhcpc_stop(self->netif); + // #if LWIP_IPV6_DHCP6 + // dhcp6_disable(esp_netif_get_netif_impl(self->netif)); + // #endif +} + +void common_hal_wifi_radio_start_dhcp_server(wifi_radio_obj_t *self) { + // esp_netif_dhcps_start(self->ap_netif); +} + +void common_hal_wifi_radio_stop_dhcp_server(wifi_radio_obj_t *self) { + // esp_netif_dhcps_stop(self->ap_netif); +} + +void common_hal_wifi_radio_set_ipv4_address(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway, mp_obj_t ipv4_dns) { + // common_hal_wifi_radio_stop_dhcp_client(self); // Must stop station DHCP to set a manual address + + // esp_netif_ip_info_t ip_info; + // ipaddress_ipaddress_to_esp_idf_ip4(ipv4, &ip_info.ip); + // ipaddress_ipaddress_to_esp_idf_ip4(netmask, &ip_info.netmask); + // ipaddress_ipaddress_to_esp_idf_ip4(gateway, &ip_info.gw); + + // esp_netif_set_ip_info(self->netif, &ip_info); + + // if (ipv4_dns != MP_OBJ_NULL) { + // common_hal_wifi_radio_set_ipv4_dns(self, ipv4_dns); + // } +} + +void common_hal_wifi_radio_set_ipv4_address_ap(wifi_radio_obj_t *self, mp_obj_t ipv4, mp_obj_t netmask, mp_obj_t gateway) { + // common_hal_wifi_radio_stop_dhcp_server(self); // Must stop access point DHCP to set a manual address + + // esp_netif_ip_info_t ip_info; + // ipaddress_ipaddress_to_esp_idf_ip4(ipv4, &ip_info.ip); + // ipaddress_ipaddress_to_esp_idf_ip4(netmask, &ip_info.netmask); + // ipaddress_ipaddress_to_esp_idf_ip4(gateway, &ip_info.gw); + + // esp_netif_set_ip_info(self->ap_netif, &ip_info); + + // common_hal_wifi_radio_start_dhcp_server(self); // restart access point DHCP +} + +// static void ping_success_cb(esp_ping_handle_t hdl, void *args) { +// wifi_radio_obj_t *self = (wifi_radio_obj_t *)args; +// esp_ping_get_profile(hdl, ESP_PING_PROF_TIMEGAP, &self->ping_elapsed_time, sizeof(self->ping_elapsed_time)); +// } + +mp_int_t common_hal_wifi_radio_ping(wifi_radio_obj_t *self, mp_obj_t ip_address, mp_float_t timeout) { + // esp_ping_config_t ping_config = ESP_PING_DEFAULT_CONFIG(); + // ipaddress_ipaddress_to_esp_idf(ip_address, &ping_config.target_addr); + // ping_config.count = 1; + + // // We must fetch ping information using the callback mechanism, because the session storage is freed when + // // the ping session is done, even before esp_ping_delete_session(). + // esp_ping_callbacks_t ping_callbacks = { + // .on_ping_success = ping_success_cb, + // .cb_args = (void *)self, + // }; + + // size_t timeout_ms = timeout * 1000; + + // // ESP-IDF creates a task to do the ping session. It shuts down when done, but only after a one second delay. + // // Calling common_hal_wifi_radio_ping() too fast will cause resource exhaustion. + // esp_ping_handle_t ping; + // if (esp_ping_new_session(&ping_config, &ping_callbacks, &ping) != ESP_OK) { + // // Wait for old task to go away and then try again. + // // Empirical testing shows we have to wait at least two seconds, despite the task + // // having a one-second timeout. + // common_hal_time_delay_ms(2000); + // // Return if interrupted now, to show the interruption as KeyboardInterrupt instead of the + // // IDF error. + // if (mp_hal_is_interrupted()) { + // return (uint32_t)(-1); + // } + // CHECK_ESP_RESULT(esp_ping_new_session(&ping_config, &ping_callbacks, &ping)); + // } + + // // Use all ones as a flag that the elapsed time was not set (ping failed or timed out). + // self->ping_elapsed_time = (uint32_t)(-1); + + // esp_ping_start(ping); + + // uint32_t start_time = common_hal_time_monotonic_ms(); + // while ((self->ping_elapsed_time == (uint32_t)(-1)) && + // (common_hal_time_monotonic_ms() - start_time < timeout_ms) && + // !mp_hal_is_interrupted()) { + // RUN_BACKGROUND_TASKS; + // } + // esp_ping_stop(ping); + // esp_ping_delete_session(ping); + + // return (mp_int_t)self->ping_elapsed_time; + return 0; +} + +void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self) { + // Only bother to scan the actual object references. + gc_collect_ptr(self->current_scan); +} + +mp_obj_t common_hal_wifi_radio_get_dns(wifi_radio_obj_t *self) { + // if (!esp_netif_is_netif_up(self->netif)) { + // return mp_const_empty_tuple; + // } + + // esp_netif_get_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &self->dns_info); + + // if (self->dns_info.ip.type == ESP_IPADDR_TYPE_V4 && self->dns_info.ip.u_addr.ip4.addr == INADDR_NONE) { + // return mp_const_empty_tuple; + // } + + // mp_obj_t args[] = { + // espaddr_to_str(&self->dns_info.ip), + // }; + + // return mp_obj_new_tuple(1, args); + return mp_const_empty_tuple; +} + +void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_obj) { + // mp_int_t len = mp_obj_get_int(mp_obj_len(dns_addrs_obj)); + // mp_arg_validate_length_max(len, 1, MP_QSTR_dns); + // esp_netif_dns_info_t dns_info; + // if (len == 0) { + // // clear DNS server + // dns_info.ip.type = ESP_IPADDR_TYPE_V4; + // dns_info.ip.u_addr.ip4.addr = INADDR_NONE; + // } else { + // mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL); + // struct sockaddr_storage addr_storage; + // socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(dns_addr_obj), &addr_storage, 1); + // sockaddr_to_espaddr(&addr_storage, &dns_info.ip); + // } + // esp_netif_set_dns_info(self->netif, ESP_NETIF_DNS_MAIN, &dns_info); +} diff --git a/ports/zephyr-cp/common-hal/wifi/Radio.h b/ports/zephyr-cp/common-hal/wifi/Radio.h new file mode 100644 index 0000000000000..f177f493685b1 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/Radio.h @@ -0,0 +1,43 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +#include "shared-bindings/wifi/ScannedNetworks.h" +#include "shared-bindings/wifi/Network.h" + +#include + +// Event bits for the Radio event group. +#define WIFI_SCAN_DONE_BIT BIT0 +#define WIFI_CONNECTED_BIT BIT1 +#define WIFI_DISCONNECTED_BIT BIT2 + +typedef struct { + mp_obj_base_t base; + wifi_scannednetworks_obj_t *current_scan; + // StaticEventGroup_t event_group; + // EventGroupHandle_t event_group_handle; + // wifi_config_t sta_config; + // wifi_network_obj_t ap_info; + // esp_netif_ip_info_t ip_info; + // esp_netif_dns_info_t dns_info; + struct net_if *sta_netif; + // uint32_t ping_elapsed_time; + // wifi_config_t ap_config; + // esp_netif_ip_info_t ap_ip_info; + struct net_if *ap_netif; + bool started; + bool ap_mode; + bool sta_mode; + uint8_t retries_left; + uint8_t starting_retries; + uint8_t last_disconnect_reason; +} wifi_radio_obj_t; + +extern void common_hal_wifi_radio_gc_collect(wifi_radio_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c new file mode 100644 index 0000000000000..3a6c21c5b8397 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.c @@ -0,0 +1,127 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec +// SPDX-FileCopyrightText: Copyright (c) 2017 Glenn Ruben Bakke +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/interrupt_char.h" +#include "py/gc.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/wifi/__init__.h" +#include "shared-bindings/wifi/Network.h" +#include "shared-bindings/wifi/Radio.h" +#include "shared-bindings/wifi/ScannedNetworks.h" + +#include +#include + + +void wifi_scannednetworks_scan_result(wifi_scannednetworks_obj_t *self, struct wifi_scan_result *result) { + if (k_msgq_put(&self->msgq, result, K_NO_WAIT) != 0) { + printk("Dropping scan result!\n"); + } +} + +static void wifi_scannednetworks_done(wifi_scannednetworks_obj_t *self) { + self->done = true; +} + +static bool wifi_scannednetworks_wait_for_scan(wifi_scannednetworks_obj_t *self) { + + return !mp_hal_is_interrupted(); +} + +mp_obj_t common_hal_wifi_scannednetworks_next(wifi_scannednetworks_obj_t *self) { + if (self->done) { + return mp_const_none; + } + // If we don't have any results queued, then wait until we do. + while (k_fifo_is_empty(&self->fifo) && k_msgq_num_used_get(&self->msgq) == 0) { + k_poll(self->events, ARRAY_SIZE(self->events), K_FOREVER); + if (mp_hal_is_interrupted()) { + wifi_scannednetworks_done(self); + } + if (k_msgq_num_used_get(&self->msgq) > 0) { + // We found something. + break; + } + int signaled; + int result; + k_poll_signal_check(&self->channel_done, &signaled, &result); + if (signaled) { + wifi_scannednetworks_scan_next_channel(self); + } + if (self->done) { + return mp_const_none; + } + } + // Copy everything out of the message queue into the FIFO because it's a + // fixed size. + while (k_msgq_num_used_get(&self->msgq) > 0) { + wifi_network_obj_t *entry = mp_obj_malloc(wifi_network_obj_t, &wifi_network_type); + k_msgq_get(&self->msgq, &entry->scan_result, K_NO_WAIT); + // This will use the base python object space for the linked list. We + // need to reset it before returning this memory as a Python object. + k_fifo_put(&self->fifo, entry); + } + + wifi_network_obj_t *entry = k_fifo_get(&self->fifo, K_NO_WAIT); + entry->base.type = &wifi_network_type; + return MP_OBJ_FROM_PTR(entry); +} + +// We don't do a linear scan so that we look at a variety of spectrum up front. +static uint8_t scan_pattern[] = {6, 1, 11, 3, 9, 13, 2, 4, 8, 12, 5, 7, 10, 14, 0}; + +void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self) { + // There is no channel 0, so use that as a flag to indicate we've run out of channels to scan. + uint8_t next_channel = 0; + while (self->current_channel_index < sizeof(scan_pattern)) { + next_channel = scan_pattern[self->current_channel_index]; + self->current_channel_index++; + // Scan only channels that are in the specified range. + if (self->start_channel <= next_channel && next_channel <= self->end_channel) { + break; + } + } + k_poll_signal_init(&self->channel_done); + k_poll_event_init(&self->events[2], + K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, + &self->channel_done); + + struct wifi_scan_params params = { 0 }; + params.band_chan[0].band = WIFI_FREQ_BAND_2_4_GHZ; + params.band_chan[0].channel = next_channel; + if (next_channel == 0) { + wifi_scannednetworks_done(self); + } else { + int res = net_mgmt(NET_REQUEST_WIFI_SCAN, self->netif, ¶ms, sizeof(params)); + if (res != 0) { + printk("Failed to start wifi scan %d\n", res); + raise_zephyr_error(res); + wifi_scannednetworks_done(self); + } else { + self->channel_scan_in_progress = true; + } + } +} + +void wifi_scannednetworks_deinit(wifi_scannednetworks_obj_t *self) { + // Free any results we don't need. + while (!k_fifo_is_empty(&self->fifo)) { + wifi_network_obj_t *entry = k_fifo_get(&self->fifo, K_NO_WAIT); + + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(entry, sizeof(wifi_network_obj_t)); + #else + m_free(entry); + #endif + } + wifi_scannednetworks_done(self); +} diff --git a/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h new file mode 100644 index 0000000000000..14211f3955072 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/ScannedNetworks.h @@ -0,0 +1,43 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2018 Artur Pacholec +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +#include +#include + +#define MAX_BUFFERED_SCAN_RESULTS 10 + +typedef struct { + mp_obj_base_t base; + uint8_t current_channel_index; + struct k_poll_signal channel_done; + struct k_poll_event events[3]; + + // Hold results as they move from the callback to the CP thread. + char msgq_buffer[MAX_BUFFERED_SCAN_RESULTS * sizeof(struct wifi_scan_result)]; + struct k_msgq msgq; + // Buffer the scan results before we return them. They are stored on the CP heap. + struct k_fifo fifo; + + // Limits on what channels to scan. + uint8_t start_channel; + uint8_t end_channel; // Inclusive + + struct net_if *netif; + + bool done; + bool channel_scan_in_progress; +} wifi_scannednetworks_obj_t; + +void wifi_scannednetworks_scan_result(wifi_scannednetworks_obj_t *self, struct wifi_scan_result *result); +void wifi_scannednetworks_scan_next_channel(wifi_scannednetworks_obj_t *self); +void wifi_scannednetworks_deinit(wifi_scannednetworks_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/wifi/__init__.c b/ports/zephyr-cp/common-hal/wifi/__init__.c new file mode 100644 index 0000000000000..f9e02be247600 --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/__init__.c @@ -0,0 +1,470 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "common-hal/wifi/__init__.h" +#include "shared-bindings/wifi/__init__.h" + +#include "shared-bindings/ipaddress/IPv4Address.h" +#include "shared-bindings/wifi/Monitor.h" +#include "shared-bindings/wifi/Radio.h" +#include "bindings/zephyr_kernel/__init__.h" +#include "common-hal/socketpool/__init__.h" + +#include "py/gc.h" +#include "py/mpstate.h" +#include "py/runtime.h" + +wifi_radio_obj_t common_hal_wifi_radio_obj; + +#include "supervisor/port.h" +#include "supervisor/workflow.h" + +#if CIRCUITPY_STATUS_BAR +#include "supervisor/shared/status_bar.h" +#endif + +#include +#include + +#include + +#define MAC_ADDRESS_LENGTH 6 + +static void schedule_background_on_cp_core(void *arg) { + #if CIRCUITPY_STATUS_BAR + supervisor_status_bar_request_update(false); + #endif + + // CircuitPython's VM is run in a separate FreeRTOS task from wifi callbacks. So, we have to + // notify the main task every time in case it's waiting for us. + port_wake_main_task(); +} + +static struct net_mgmt_event_callback wifi_cb; +static struct net_mgmt_event_callback ipv4_cb; + +static void _event_handler(struct net_mgmt_event_callback *cb, uint64_t mgmt_event, struct net_if *iface) { + wifi_radio_obj_t *self = &common_hal_wifi_radio_obj; + (void)iface; + + switch (mgmt_event) { + case NET_EVENT_WIFI_SCAN_RESULT: { + printk("NET_EVENT_WIFI_SCAN_RESULT\n"); + const struct wifi_scan_result *result = cb->info; + if (result != NULL && self->current_scan != NULL) { + wifi_scannednetworks_scan_result(self->current_scan, result); + } + break; + } + case NET_EVENT_WIFI_SCAN_DONE: + printk("NET_EVENT_WIFI_SCAN_DONE (thread: %s prio=%d)\n", + k_thread_name_get(k_current_get()), + k_thread_priority_get(k_current_get())); + if (self->current_scan != NULL) { + k_poll_signal_raise(&self->current_scan->channel_done, 0); + } + break; + case NET_EVENT_WIFI_CONNECT_RESULT: + printk("NET_EVENT_WIFI_CONNECT_RESULT\n"); + break; + case NET_EVENT_WIFI_DISCONNECT_RESULT: + printk("NET_EVENT_WIFI_DISCONNECT_RESULT\n"); + break; + case NET_EVENT_WIFI_IFACE_STATUS: + printk("NET_EVENT_WIFI_IFACE_STATUS\n"); + break; + case NET_EVENT_WIFI_TWT: + printk("NET_EVENT_WIFI_TWT\n"); + break; + case NET_EVENT_WIFI_TWT_SLEEP_STATE: + printk("NET_EVENT_WIFI_TWT_SLEEP_STATE\n"); + break; + case NET_EVENT_WIFI_RAW_SCAN_RESULT: + printk("NET_EVENT_WIFI_RAW_SCAN_RESULT\n"); + break; + case NET_EVENT_WIFI_DISCONNECT_COMPLETE: + printk("NET_EVENT_WIFI_DISCONNECT_COMPLETE\n"); + break; + case NET_EVENT_WIFI_SIGNAL_CHANGE: + printk("NET_EVENT_WIFI_SIGNAL_CHANGE\n"); + break; + case NET_EVENT_WIFI_NEIGHBOR_REP_COMP: + printk("NET_EVENT_WIFI_NEIGHBOR_REP_COMP\n"); + break; + case NET_EVENT_WIFI_AP_ENABLE_RESULT: + printk("NET_EVENT_WIFI_AP_ENABLE_RESULT\n"); + break; + case NET_EVENT_WIFI_AP_DISABLE_RESULT: + printk("NET_EVENT_WIFI_AP_DISABLE_RESULT\n"); + break; + case NET_EVENT_WIFI_AP_STA_CONNECTED: + printk("NET_EVENT_WIFI_AP_STA_CONNECTED\n"); + break; + case NET_EVENT_WIFI_AP_STA_DISCONNECTED: + printk("NET_EVENT_WIFI_AP_STA_DISCONNECTED\n"); + break; + default: + printk("unhandled net event %x\n", mgmt_event); + break; + } +} + +// static void event_handler(void *arg, esp_event_base_t event_base, +// int32_t event_id, void *event_data) { +// // This runs on the PRO CORE! It cannot share CP interrupt enable/disable +// // directly. +// wifi_radio_obj_t *radio = arg; +// if (event_base == WIFI_EVENT) { +// switch (event_id) { +// case WIFI_EVENT_SCAN_DONE: +// ESP_LOGW(TAG, "scan"); +// xEventGroupSetBits(radio->event_group_handle, WIFI_SCAN_DONE_BIT); +// break; +// case WIFI_EVENT_AP_START: +// ESP_LOGW(TAG, "ap start"); +// break; +// case WIFI_EVENT_AP_STOP: +// ESP_LOGW(TAG, "ap stop"); +// break; +// case WIFI_EVENT_AP_STACONNECTED: +// break; +// case WIFI_EVENT_AP_STADISCONNECTED: +// break; +// case WIFI_EVENT_STA_START: +// ESP_LOGW(TAG, "sta start"); +// break; +// case WIFI_EVENT_STA_STOP: +// ESP_LOGW(TAG, "sta stop"); +// break; +// case WIFI_EVENT_STA_CONNECTED: +// ESP_LOGW(TAG, "connected"); +// break; +// case WIFI_EVENT_STA_DISCONNECTED: { +// ESP_LOGW(TAG, "disconnected"); +// wifi_event_sta_disconnected_t *d = (wifi_event_sta_disconnected_t *)event_data; +// uint8_t reason = d->reason; +// ESP_LOGW(TAG, "reason %d 0x%02x", reason, reason); +// if (radio->retries_left > 0 && +// reason != WIFI_REASON_AUTH_FAIL && +// reason != WIFI_REASON_NO_AP_FOUND && +// reason != WIFI_REASON_ASSOC_LEAVE) { +// radio->retries_left--; +// ESP_LOGI(TAG, "Retrying connect. %d retries remaining", radio->retries_left); +// esp_wifi_connect(); +// return; +// } + +// radio->last_disconnect_reason = reason; +// xEventGroupSetBits(radio->event_group_handle, WIFI_DISCONNECTED_BIT); +// break; +// } + +// // Cases to handle later. +// // case WIFI_EVENT_STA_AUTHMODE_CHANGE: +// default: { +// ESP_LOGW(TAG, "event %ld 0x%02ld", event_id, event_id); +// break; +// } +// } +// } + +// if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { +// ESP_LOGW(TAG, "got ip"); +// radio->retries_left = radio->starting_retries; +// xEventGroupSetBits(radio->event_group_handle, WIFI_CONNECTED_BIT); +// } +// // Use IPC to ensure we run schedule background on the same core as CircuitPython. +// #if defined(CONFIG_FREERTOS_UNICORE) && CONFIG_FREERTOS_UNICORE +// schedule_background_on_cp_core(NULL); +// #else +// // This only blocks until the start of the function. That's ok since the PRO +// // core shouldn't care what we do. +// esp_ipc_call(CONFIG_ESP_MAIN_TASK_AFFINITY, schedule_background_on_cp_core, NULL); +// #endif +// } + +static bool wifi_inited; +static bool wifi_ever_inited; +static bool wifi_user_initiated; + +void common_hal_wifi_init(bool user_initiated) { + wifi_radio_obj_t *self = &common_hal_wifi_radio_obj; + printk("common_hal_wifi_init\n"); + + if (wifi_inited) { + if (user_initiated && !wifi_user_initiated) { + common_hal_wifi_radio_set_enabled(self, true); + } + return; + } + wifi_inited = true; + wifi_user_initiated = user_initiated; + self->base.type = &wifi_radio_type; + + // struct net_if *default_iface = net_if_get_default(); + // printk("default interface %p\n", default_iface); + // printk("listing network interfaces\n"); + // for (int i = 0; i < 10; i++) { + // struct net_if* iface = net_if_get_by_index(i); + // if (iface == NULL) { + // printk("iface %d is NULL\n", i); + // continue; + // } + // char name[32]; + // net_if_get_name(iface, name, 32); + // printk("iface %d %s\n", i, name); + // } + self->sta_netif = net_if_get_wifi_sta(); + self->ap_netif = net_if_get_wifi_sap(); + printk("sta_netif %p\n", self->sta_netif); + printk("ap_netif %p\n", self->ap_netif); + + + struct wifi_iface_status status = { 0 }; + if (self->sta_netif != NULL) { + CHECK_ZEPHYR_RESULT(net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, self->sta_netif, &status, + sizeof(struct wifi_iface_status))); + if (net_if_is_up(self->sta_netif)) { + printk("STA is up\n"); + } else { + printk("STA is down\n"); + } + if (net_if_is_carrier_ok(self->sta_netif)) { + printk("STA carrier is ok\n"); + } else { + printk("STA carrier is not ok\n"); + } + if (net_if_is_dormant(self->sta_netif)) { + printk("STA is dormant\n"); + } else { + printk("STA is not dormant\n"); + } + } + if (self->ap_netif != NULL) { + int res = net_mgmt(NET_REQUEST_WIFI_IFACE_STATUS, self->ap_netif, &status, + sizeof(struct wifi_iface_status)); + printk("AP status request response %d\n", res); + if (net_if_is_up(self->ap_netif)) { + printk("AP is up\n"); + } else { + printk("AP is down\n"); + } + if (net_if_is_carrier_ok(self->ap_netif)) { + printk("AP carrier is ok\n"); + } else { + printk("AP carrier is not ok\n"); + } + if (net_if_is_dormant(self->ap_netif)) { + printk("AP is dormant\n"); + } else { + printk("AP is not dormant\n"); + } + } + + // self->started = false; + + // // Even though we just called esp_netif_create_default_wifi_sta, + // // station mode isn't actually ready for use until esp_wifi_set_mode() + // // is called and the configuration is loaded via esp_wifi_set_config(). + // // Set both convenience flags to false so it's not forgotten. + // self->sta_mode = 0; + // self->ap_mode = 0; + + net_mgmt_init_event_callback(&wifi_cb, _event_handler, + NET_EVENT_WIFI_SCAN_DONE | + NET_EVENT_WIFI_CONNECT_RESULT | + NET_EVENT_WIFI_DISCONNECT_RESULT | + NET_EVENT_WIFI_TWT | + NET_EVENT_WIFI_RAW_SCAN_RESULT | + NET_EVENT_WIFI_AP_ENABLE_RESULT | + NET_EVENT_WIFI_AP_DISABLE_RESULT | + NET_EVENT_WIFI_AP_STA_CONNECTED | + NET_EVENT_WIFI_AP_STA_DISCONNECTED); + + net_mgmt_init_event_callback(&ipv4_cb, _event_handler, NET_EVENT_IPV4_ADDR_ADD); + + net_mgmt_add_event_callback(&wifi_cb); + net_mgmt_add_event_callback(&ipv4_cb); + + #if defined(CONFIG_NET_HOSTNAME) + // Set the default hostname capped at NET_HOSTNAME_MAX_LEN characters. We trim off + // the start of the board name (likely manufacturer) because the end is + // often more unique to the board. + size_t board_len = MIN(NET_HOSTNAME_MAX_LEN - ((MAC_ADDRESS_LENGTH * 2) + 6), strlen(CIRCUITPY_BOARD_ID)); + size_t board_trim = strlen(CIRCUITPY_BOARD_ID) - board_len; + // Avoid double _ in the hostname. + if (CIRCUITPY_BOARD_ID[board_trim] == '_') { + board_trim++; + } + + char cpy_default_hostname[board_len + (MAC_ADDRESS_LENGTH * 2) + 6]; + struct net_linkaddr *mac = net_if_get_link_addr(self->sta_netif); + if (mac->len < MAC_ADDRESS_LENGTH) { + printk("MAC address too short"); + } + snprintf(cpy_default_hostname, sizeof(cpy_default_hostname), "cpy-%s-%02x%02x%02x%02x%02x%02x", CIRCUITPY_BOARD_ID + board_trim, mac->addr[0], mac->addr[1], mac->addr[2], mac->addr[3], mac->addr[4], mac->addr[5]); + + CHECK_ZEPHYR_RESULT(net_hostname_set(cpy_default_hostname, strlen(cpy_default_hostname))); + #else + printk("Hostname support disabled in Zephyr config\n"); + #endif + // set station mode to avoid the default SoftAP + common_hal_wifi_radio_start_station(self); + // start wifi + common_hal_wifi_radio_set_enabled(self, true); + + printk("common_hal_wifi_init done\n"); +} + +void wifi_user_reset(void) { + if (wifi_user_initiated) { + wifi_reset(); + wifi_user_initiated = false; + } +} + +void wifi_reset(void) { + printk("wifi_reset\n"); + if (!wifi_inited) { + return; + } + common_hal_wifi_monitor_deinit(MP_STATE_VM(wifi_monitor_singleton)); + wifi_radio_obj_t *radio = &common_hal_wifi_radio_obj; + common_hal_wifi_radio_set_enabled(radio, false); + // #ifndef CONFIG_IDF_TARGET_ESP32 + // ESP_ERROR_CHECK(esp_event_handler_instance_unregister(WIFI_EVENT, + // ESP_EVENT_ANY_ID, + // radio->handler_instance_all_wifi)); + // ESP_ERROR_CHECK(esp_event_handler_instance_unregister(IP_EVENT, + // IP_EVENT_STA_GOT_IP, + // radio->handler_instance_got_ip)); + // ESP_ERROR_CHECK(esp_wifi_deinit()); + // esp_netif_destroy(radio->netif); + // radio->netif = NULL; + // esp_netif_destroy(radio->ap_netif); + // radio->ap_netif = NULL; + // wifi_inited = false; + // #endif + supervisor_workflow_request_background(); +} + +// void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address) { +// if (mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { +// ipaddress_ipaddress_to_esp_idf_ip4(ip_address, (esp_ip4_addr_t *)esp_ip_address); +// #if LWIP_IPV6 +// esp_ip_address->type = IPADDR_TYPE_V4; +// #endif +// } else { +// struct sockaddr_storage addr_storage; +// socketpool_resolve_host_or_throw(AF_UNSPEC, SOCK_STREAM, mp_obj_str_get_str(ip_address), &addr_storage, 1); +// sockaddr_to_espaddr(&addr_storage, (esp_ip_addr_t *)esp_ip_address); +// } +// } + +// void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address) { +// if (!mp_obj_is_type(ip_address, &ipaddress_ipv4address_type)) { +// mp_raise_ValueError(MP_ERROR_TEXT("Only IPv4 addresses supported")); +// } +// mp_obj_t packed = common_hal_ipaddress_ipv4address_get_packed(ip_address); +// size_t len; +// const char *bytes = mp_obj_str_get_data(packed, &len); +// esp_netif_set_ip4_addr(esp_ip_address, bytes[0], bytes[1], bytes[2], bytes[3]); +// } + +void common_hal_wifi_gc_collect(void) { + common_hal_wifi_radio_gc_collect(&common_hal_wifi_radio_obj); +} + +// static mp_obj_t espaddrx_to_str(const void *espaddr, uint8_t esptype) { +// char buf[IPADDR_STRLEN_MAX]; +// inet_ntop(esptype == ESP_IPADDR_TYPE_V6 ? AF_INET6 : AF_INET, espaddr, buf, sizeof(buf)); +// return mp_obj_new_str(buf, strlen(buf)); +// } + +// mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr) { +// return espaddrx_to_str(espaddr, espaddr->type); +// } + +// mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr) { +// return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V4); +// } + +// mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr) { +// return espaddrx_to_str(espaddr, ESP_IPADDR_TYPE_V6); +// } + +// mp_obj_t sockaddr_to_str(const struct sockaddr_storage *sockaddr) { +// char buf[IPADDR_STRLEN_MAX]; +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// if (sockaddr->ss_family == AF_INET6) { +// const struct sockaddr_in6 *addr6 = (const void *)sockaddr; +// inet_ntop(AF_INET6, &addr6->sin6_addr, buf, sizeof(buf)); +// } else +// #endif +// { +// const struct sockaddr_in *addr = (const void *)sockaddr; +// inet_ntop(AF_INET, &addr->sin_addr, buf, sizeof(buf)); +// } +// return mp_obj_new_str(buf, strlen(buf)); +// } + +// mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *sockaddr) { +// mp_obj_t args[4] = { +// sockaddr_to_str(sockaddr), +// }; +// int n = 2; +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// if (sockaddr->ss_family == AF_INET6) { +// const struct sockaddr_in6 *addr6 = (const void *)sockaddr; +// args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr6->sin6_port)); +// args[2] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_flowinfo); +// args[3] = MP_OBJ_NEW_SMALL_INT(addr6->sin6_scope_id); +// n = 4; +// } else +// #endif +// { +// const struct sockaddr_in *addr = (const void *)sockaddr; +// args[1] = MP_OBJ_NEW_SMALL_INT(htons(addr->sin_port)); +// } +// return mp_obj_new_tuple(n, args); +// } + +// void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr) { +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// MP_STATIC_ASSERT(IPADDR_TYPE_V4 == ESP_IPADDR_TYPE_V4); +// MP_STATIC_ASSERT(IPADDR_TYPE_V6 == ESP_IPADDR_TYPE_V6); +// MP_STATIC_ASSERT(sizeof(ip_addr_t) == sizeof(esp_ip_addr_t)); +// MP_STATIC_ASSERT(offsetof(ip_addr_t, u_addr) == offsetof(esp_ip_addr_t, u_addr)); +// MP_STATIC_ASSERT(offsetof(ip_addr_t, type) == offsetof(esp_ip_addr_t, type)); +// if (sockaddr->ss_family == AF_INET6) { +// const struct sockaddr_in6 *addr6 = (const void *)sockaddr; +// MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip6.addr) == sizeof(addr6->sin6_addr)); +// memcpy(&espaddr->u_addr.ip6.addr, &addr6->sin6_addr, sizeof(espaddr->u_addr.ip6.addr)); +// espaddr->u_addr.ip6.zone = addr6->sin6_scope_id; +// espaddr->type = ESP_IPADDR_TYPE_V6; +// } else +// #endif +// { +// const struct sockaddr_in *addr = (const void *)sockaddr; +// MP_STATIC_ASSERT(sizeof(espaddr->u_addr.ip4.addr) == sizeof(addr->sin_addr)); +// memcpy(&espaddr->u_addr.ip4.addr, &addr->sin_addr, sizeof(espaddr->u_addr.ip4.addr)); +// espaddr->type = ESP_IPADDR_TYPE_V4; +// } +// } + +// void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port) { +// #if CIRCUITPY_SOCKETPOOL_IPV6 +// if (espaddr->type == ESP_IPADDR_TYPE_V6) { +// struct sockaddr_in6 *addr6 = (void *)sockaddr; +// memcpy(&addr6->sin6_addr, &espaddr->u_addr.ip6.addr, sizeof(espaddr->u_addr.ip6.addr)); +// addr6->sin6_scope_id = espaddr->u_addr.ip6.zone; +// } else +// #endif +// { +// struct sockaddr_in *addr = (void *)sockaddr; +// memcpy(&addr->sin_addr, &espaddr->u_addr.ip4.addr, sizeof(espaddr->u_addr.ip4.addr)); +// } +// } diff --git a/ports/zephyr-cp/common-hal/wifi/__init__.h b/ports/zephyr-cp/common-hal/wifi/__init__.h new file mode 100644 index 0000000000000..dab519b1a5f2e --- /dev/null +++ b/ports/zephyr-cp/common-hal/wifi/__init__.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +struct sockaddr_storage; + +void wifi_reset(void); + +// void ipaddress_ipaddress_to_esp_idf(mp_obj_t ip_address, ip_addr_t *esp_ip_address); +// void ipaddress_ipaddress_to_esp_idf_ip4(mp_obj_t ip_address, esp_ip4_addr_t *esp_ip_address); + +mp_obj_t sockaddr_to_str(const struct sockaddr_storage *addr); +mp_obj_t sockaddr_to_tuple(const struct sockaddr_storage *addr); +// mp_obj_t espaddr_to_str(const esp_ip_addr_t *espaddr); +// mp_obj_t espaddr4_to_str(const esp_ip4_addr_t *espaddr); +// mp_obj_t espaddr6_to_str(const esp_ip6_addr_t *espaddr); +// void sockaddr_to_espaddr(const struct sockaddr_storage *sockaddr, esp_ip_addr_t *espaddr); +// void espaddr_to_sockaddr(const esp_ip_addr_t *espaddr, struct sockaddr_storage *sockaddr, int port); diff --git a/ports/zephyr-cp/common-hal/zephyr_display/Display.c b/ports/zephyr-cp/common-hal/zephyr_display/Display.c new file mode 100644 index 0000000000000..d1585b5f291d5 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_display/Display.c @@ -0,0 +1,440 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/zephyr_display/Display.h" + +#include + +#include "bindings/zephyr_kernel/__init__.h" +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/time/__init__.h" +#include "shared-module/displayio/__init__.h" +#include "supervisor/shared/display.h" +#include "supervisor/shared/tick.h" + +static const displayio_area_t *zephyr_display_get_refresh_areas(zephyr_display_display_obj_t *self) { + if (self->core.full_refresh) { + self->core.area.next = NULL; + return &self->core.area; + } else if (self->core.current_group != NULL) { + return displayio_group_get_refresh_areas(self->core.current_group, NULL); + } + return NULL; +} + +static enum display_pixel_format zephyr_display_select_pixel_format(const struct display_capabilities *caps) { + uint32_t formats = caps->supported_pixel_formats; + + if (formats & PIXEL_FORMAT_RGB_565) { + return PIXEL_FORMAT_RGB_565; + } + if (formats & PIXEL_FORMAT_RGB_888) { + return PIXEL_FORMAT_RGB_888; + } + if (formats & PIXEL_FORMAT_ARGB_8888) { + return PIXEL_FORMAT_ARGB_8888; + } + if (formats & PIXEL_FORMAT_RGB_565X) { + return PIXEL_FORMAT_RGB_565X; + } + if (formats & PIXEL_FORMAT_L_8) { + return PIXEL_FORMAT_L_8; + } + if (formats & PIXEL_FORMAT_AL_88) { + return PIXEL_FORMAT_AL_88; + } + if (formats & PIXEL_FORMAT_MONO01) { + return PIXEL_FORMAT_MONO01; + } + if (formats & PIXEL_FORMAT_MONO10) { + return PIXEL_FORMAT_MONO10; + } + return caps->current_pixel_format; +} + +static void zephyr_display_select_colorspace(zephyr_display_display_obj_t *self, + uint16_t *color_depth, + uint8_t *bytes_per_cell, + bool *grayscale, + bool *pixels_in_byte_share_row, + bool *reverse_pixels_in_byte, + bool *reverse_bytes_in_word) { + *color_depth = 16; + *bytes_per_cell = 2; + *grayscale = false; + *pixels_in_byte_share_row = false; + *reverse_pixels_in_byte = false; + *reverse_bytes_in_word = false; + + if (self->pixel_format == PIXEL_FORMAT_RGB_565X) { + // RGB_565X is big-endian RGB_565, so byte-swap from native LE. + *reverse_bytes_in_word = true; + } else if (self->pixel_format == PIXEL_FORMAT_RGB_888) { + *color_depth = 24; + *bytes_per_cell = 3; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_ARGB_8888) { + *color_depth = 32; + *bytes_per_cell = 4; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_L_8 || + self->pixel_format == PIXEL_FORMAT_AL_88) { + *color_depth = 8; + *bytes_per_cell = 1; + *grayscale = true; + *reverse_bytes_in_word = false; + } else if (self->pixel_format == PIXEL_FORMAT_MONO01 || + self->pixel_format == PIXEL_FORMAT_MONO10) { + bool vtiled = self->capabilities.screen_info & SCREEN_INFO_MONO_VTILED; + bool msb_first = self->capabilities.screen_info & SCREEN_INFO_MONO_MSB_FIRST; + *color_depth = 1; + *bytes_per_cell = 1; + *grayscale = true; + *pixels_in_byte_share_row = !vtiled; + *reverse_pixels_in_byte = msb_first; + *reverse_bytes_in_word = false; + } +} + +void common_hal_zephyr_display_display_construct_from_device(zephyr_display_display_obj_t *self, + const struct device *device, + uint16_t rotation, + bool auto_refresh) { + self->auto_refresh = false; + + if (device == NULL || !device_is_ready(device)) { + raise_zephyr_error(-ENODEV); + } + + self->device = device; + display_get_capabilities(self->device, &self->capabilities); + + self->pixel_format = zephyr_display_select_pixel_format(&self->capabilities); + if (self->pixel_format != self->capabilities.current_pixel_format) { + (void)display_set_pixel_format(self->device, self->pixel_format); + display_get_capabilities(self->device, &self->capabilities); + self->pixel_format = self->capabilities.current_pixel_format; + } + + uint16_t color_depth; + uint8_t bytes_per_cell; + bool grayscale; + bool pixels_in_byte_share_row; + bool reverse_pixels_in_byte; + bool reverse_bytes_in_word; + zephyr_display_select_colorspace(self, &color_depth, &bytes_per_cell, + &grayscale, &pixels_in_byte_share_row, &reverse_pixels_in_byte, + &reverse_bytes_in_word); + + displayio_display_core_construct( + &self->core, + self->capabilities.x_resolution, + self->capabilities.y_resolution, + 0, + color_depth, + grayscale, + pixels_in_byte_share_row, + bytes_per_cell, + reverse_pixels_in_byte, + reverse_bytes_in_word); + + self->native_frames_per_second = 60; + self->native_ms_per_frame = 1000 / self->native_frames_per_second; + self->first_manual_refresh = !auto_refresh; + + if (rotation != 0) { + common_hal_zephyr_display_display_set_rotation(self, rotation); + } + + (void)display_blanking_off(self->device); + + displayio_display_core_set_root_group(&self->core, &circuitpython_splash); + common_hal_zephyr_display_display_set_auto_refresh(self, auto_refresh); +} + +uint16_t common_hal_zephyr_display_display_get_width(zephyr_display_display_obj_t *self) { + return displayio_display_core_get_width(&self->core); +} + +uint16_t common_hal_zephyr_display_display_get_height(zephyr_display_display_obj_t *self) { + return displayio_display_core_get_height(&self->core); +} + +mp_float_t common_hal_zephyr_display_display_get_brightness(zephyr_display_display_obj_t *self) { + (void)self; + return -1; +} + +bool common_hal_zephyr_display_display_set_brightness(zephyr_display_display_obj_t *self, mp_float_t brightness) { + (void)self; + (void)brightness; + return false; +} + +static bool zephyr_display_refresh_area(zephyr_display_display_obj_t *self, const displayio_area_t *area) { + uint16_t buffer_size = CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE / sizeof(uint32_t); + + displayio_area_t clipped; + if (!displayio_display_core_clip_area(&self->core, area, &clipped)) { + return true; + } + + uint16_t rows_per_buffer = displayio_area_height(&clipped); + uint8_t pixels_per_word = (sizeof(uint32_t) * 8) / self->core.colorspace.depth; + // For AL_88, displayio fills at 1 byte/pixel (L_8) but output needs 2 bytes/pixel, + // so halve the effective pixels_per_word for buffer sizing. + uint8_t effective_pixels_per_word = pixels_per_word; + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + effective_pixels_per_word = sizeof(uint32_t) / 2; + } + uint16_t pixels_per_buffer = displayio_area_size(&clipped); + uint16_t subrectangles = 1; + + // When pixels_in_byte_share_row is false (mono vtiled), 8 vertical pixels + // pack into one column byte. The byte layout needs width * ceil(height/8) + // bytes, which can exceed the pixel-count-based buffer size. + bool vtiled = self->core.colorspace.depth < 8 && + !self->core.colorspace.pixels_in_byte_share_row; + + bool needs_subdivision = displayio_area_size(&clipped) > buffer_size * effective_pixels_per_word; + if (vtiled && !needs_subdivision) { + uint16_t width = displayio_area_width(&clipped); + uint16_t height = displayio_area_height(&clipped); + uint32_t vtiled_bytes = (uint32_t)width * ((height + 7) / 8); + needs_subdivision = vtiled_bytes > buffer_size * sizeof(uint32_t); + } + + if (needs_subdivision) { + rows_per_buffer = buffer_size * effective_pixels_per_word / displayio_area_width(&clipped); + if (vtiled) { + rows_per_buffer = (rows_per_buffer / 8) * 8; + if (rows_per_buffer == 0) { + rows_per_buffer = 8; + } + } + if (rows_per_buffer == 0) { + rows_per_buffer = 1; + } + subrectangles = displayio_area_height(&clipped) / rows_per_buffer; + if (displayio_area_height(&clipped) % rows_per_buffer != 0) { + subrectangles++; + } + pixels_per_buffer = rows_per_buffer * displayio_area_width(&clipped); + buffer_size = pixels_per_buffer / pixels_per_word; + if (pixels_per_buffer % pixels_per_word) { + buffer_size += 1; + } + // Ensure buffer is large enough for vtiled packing. + if (vtiled) { + uint16_t width = displayio_area_width(&clipped); + uint16_t vtiled_words = (width * ((rows_per_buffer + 7) / 8) + sizeof(uint32_t) - 1) / sizeof(uint32_t); + if (vtiled_words > buffer_size) { + buffer_size = vtiled_words; + } + } + // Ensure buffer is large enough for AL_88 expansion. + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + uint16_t al88_words = (pixels_per_buffer * 2 + sizeof(uint32_t) - 1) / sizeof(uint32_t); + if (al88_words > buffer_size) { + buffer_size = al88_words; + } + } + } + + uint32_t buffer[buffer_size]; + uint32_t mask_length = (pixels_per_buffer / 32) + 1; + uint32_t mask[mask_length]; + + uint16_t remaining_rows = displayio_area_height(&clipped); + + for (uint16_t j = 0; j < subrectangles; j++) { + displayio_area_t subrectangle = { + .x1 = clipped.x1, + .y1 = clipped.y1 + rows_per_buffer * j, + .x2 = clipped.x2, + .y2 = clipped.y1 + rows_per_buffer * (j + 1), + }; + + if (remaining_rows < rows_per_buffer) { + subrectangle.y2 = subrectangle.y1 + remaining_rows; + } + remaining_rows -= rows_per_buffer; + + memset(mask, 0, mask_length * sizeof(mask[0])); + memset(buffer, 0, buffer_size * sizeof(buffer[0])); + + displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); + + uint16_t width = displayio_area_width(&subrectangle); + uint16_t height = displayio_area_height(&subrectangle); + size_t pixel_count = (size_t)width * (size_t)height; + + if (self->pixel_format == PIXEL_FORMAT_MONO10) { + uint8_t *bytes = (uint8_t *)buffer; + size_t byte_count = (pixel_count + 7) / 8; + for (size_t i = 0; i < byte_count; i++) { + bytes[i] = ~bytes[i]; + } + } + + if (self->pixel_format == PIXEL_FORMAT_AL_88) { + uint8_t *bytes = (uint8_t *)buffer; + for (size_t i = pixel_count; i > 0; i--) { + bytes[(i - 1) * 2 + 1] = 0xFF; + bytes[(i - 1) * 2] = bytes[i - 1]; + } + } + + // Compute buf_size based on the Zephyr pixel format. + uint32_t buf_size_bytes; + if (self->pixel_format == PIXEL_FORMAT_MONO01 || + self->pixel_format == PIXEL_FORMAT_MONO10) { + buf_size_bytes = (pixel_count + 7) / 8; + } else if (self->pixel_format == PIXEL_FORMAT_AL_88) { + buf_size_bytes = pixel_count * 2; + } else { + buf_size_bytes = pixel_count * (self->core.colorspace.depth / 8); + } + + struct display_buffer_descriptor desc = { + .buf_size = buf_size_bytes, + .width = width, + .height = height, + .pitch = width, + .frame_incomplete = false, + }; + + int err = display_write(self->device, subrectangle.x1, subrectangle.y1, &desc, buffer); + if (err < 0) { + return false; + } + + RUN_BACKGROUND_TASKS; + } + + return true; +} + +static void zephyr_display_refresh(zephyr_display_display_obj_t *self) { + if (!displayio_display_core_start_refresh(&self->core)) { + return; + } + + const displayio_area_t *current_area = zephyr_display_get_refresh_areas(self); + while (current_area != NULL) { + if (!zephyr_display_refresh_area(self, current_area)) { + break; + } + current_area = current_area->next; + } + + displayio_display_core_finish_refresh(&self->core); +} + +void common_hal_zephyr_display_display_set_rotation(zephyr_display_display_obj_t *self, int rotation) { + bool transposed = (self->core.rotation == 90 || self->core.rotation == 270); + bool will_transposed = (rotation == 90 || rotation == 270); + if (transposed != will_transposed) { + int tmp = self->core.width; + self->core.width = self->core.height; + self->core.height = tmp; + } + + displayio_display_core_set_rotation(&self->core, rotation); + + if (self == &displays[0].zephyr_display) { + supervisor_stop_terminal(); + supervisor_start_terminal(self->core.width, self->core.height); + } + + if (self->core.current_group != NULL) { + displayio_group_update_transform(self->core.current_group, &self->core.transform); + } +} + +uint16_t common_hal_zephyr_display_display_get_rotation(zephyr_display_display_obj_t *self) { + return self->core.rotation; +} + +bool common_hal_zephyr_display_display_refresh(zephyr_display_display_obj_t *self, + uint32_t target_ms_per_frame, + uint32_t maximum_ms_per_real_frame) { + if (!self->auto_refresh && !self->first_manual_refresh && (target_ms_per_frame != NO_FPS_LIMIT)) { + uint64_t current_time = supervisor_ticks_ms64(); + uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh; + if (current_ms_since_real_refresh > maximum_ms_per_real_frame) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Below minimum frame rate")); + } + uint32_t current_ms_since_last_call = current_time - self->last_refresh_call; + self->last_refresh_call = current_time; + if (current_ms_since_last_call > target_ms_per_frame) { + return false; + } + uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame); + while (supervisor_ticks_ms64() - self->last_refresh_call < remaining_time) { + RUN_BACKGROUND_TASKS; + } + } + self->first_manual_refresh = false; + zephyr_display_refresh(self); + return true; +} + +bool common_hal_zephyr_display_display_get_auto_refresh(zephyr_display_display_obj_t *self) { + return self->auto_refresh; +} + +void common_hal_zephyr_display_display_set_auto_refresh(zephyr_display_display_obj_t *self, bool auto_refresh) { + self->first_manual_refresh = !auto_refresh; + if (auto_refresh != self->auto_refresh) { + if (auto_refresh) { + supervisor_enable_tick(); + } else { + supervisor_disable_tick(); + } + } + self->auto_refresh = auto_refresh; +} + +void zephyr_display_display_background(zephyr_display_display_obj_t *self) { + if (self->auto_refresh && (supervisor_ticks_ms64() - self->core.last_refresh) > self->native_ms_per_frame) { + zephyr_display_refresh(self); + } +} + +void release_zephyr_display(zephyr_display_display_obj_t *self) { + common_hal_zephyr_display_display_set_auto_refresh(self, false); + release_display_core(&self->core); + self->device = NULL; + self->base.type = &mp_type_NoneType; +} + +void zephyr_display_display_collect_ptrs(zephyr_display_display_obj_t *self) { + (void)self; + displayio_display_core_collect_ptrs(&self->core); +} + +void zephyr_display_display_reset(zephyr_display_display_obj_t *self) { + if (self->device != NULL && device_is_ready(self->device)) { + common_hal_zephyr_display_display_set_auto_refresh(self, true); + displayio_display_core_set_root_group(&self->core, &circuitpython_splash); + self->core.full_refresh = true; + } else { + release_zephyr_display(self); + } +} + +mp_obj_t common_hal_zephyr_display_display_get_root_group(zephyr_display_display_obj_t *self) { + if (self->core.current_group == NULL) { + return mp_const_none; + } + return self->core.current_group; +} + +bool common_hal_zephyr_display_display_set_root_group(zephyr_display_display_obj_t *self, displayio_group_t *root_group) { + return displayio_display_core_set_root_group(&self->core, root_group); +} diff --git a/ports/zephyr-cp/common-hal/zephyr_display/Display.h b/ports/zephyr-cp/common-hal/zephyr_display/Display.h new file mode 100644 index 0000000000000..bdec1e96ba5f3 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_display/Display.h @@ -0,0 +1,31 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "shared-module/displayio/display_core.h" + +typedef struct { + mp_obj_base_t base; + displayio_display_core_t core; + const struct device *device; + struct display_capabilities capabilities; + enum display_pixel_format pixel_format; + uint64_t last_refresh_call; + uint16_t native_frames_per_second; + uint16_t native_ms_per_frame; + bool auto_refresh; + bool first_manual_refresh; +} zephyr_display_display_obj_t; + +void zephyr_display_display_background(zephyr_display_display_obj_t *self); +void zephyr_display_display_collect_ptrs(zephyr_display_display_obj_t *self); +void zephyr_display_display_reset(zephyr_display_display_obj_t *self); +void release_zephyr_display(zephyr_display_display_obj_t *self); diff --git a/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c new file mode 100644 index 0000000000000..178f33e028d73 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.c @@ -0,0 +1,62 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "bindings/zephyr_kernel/__init__.h" +#include "py/runtime.h" +#include + +#include +#include + +void raise_zephyr_error(int err) { + if (err == 0) { + return; + } + switch (-err) { + case EALREADY: + printk("EALREADY\n"); + break; + case EDESTADDRREQ: + printk("EDESTADDRREQ\n"); + break; + case EMSGSIZE: + printk("EMSGSIZE\n"); + break; + case EPROTONOSUPPORT: + printk("EPROTONOSUPPORT\n"); + break; + case EADDRNOTAVAIL: + printk("EADDRNOTAVAIL\n"); + break; + case ENETRESET: + printk("ENETRESET\n"); + break; + case EISCONN: + printk("EISCONN\n"); + break; + case ENOTCONN: + printk("ENOTCONN\n"); + break; + case ENOTSUP: + printk("ENOTSUP\n"); + break; + case EADDRINUSE: + printk("EADDRINUSE\n"); + break; + case EIO: + printk("EIO\n"); + break; + case ENOSYS: + printk("ENOSYS\n"); + break; + case EINVAL: + printk("EINVAL\n"); + break; + default: + printk("Zephyr error %d\n", err); + } + mp_raise_OSError(-err); +} diff --git a/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.h b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.h new file mode 100644 index 0000000000000..d6e483b9d3e38 --- /dev/null +++ b/ports/zephyr-cp/common-hal/zephyr_kernel/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/ports/zephyr-cp/cptools/board_tools.py b/ports/zephyr-cp/cptools/board_tools.py new file mode 100644 index 0000000000000..305abab3f19b5 --- /dev/null +++ b/ports/zephyr-cp/cptools/board_tools.py @@ -0,0 +1,37 @@ +import tomllib + + +def find_mpconfigboard(portdir, board_id): + next_underscore = board_id.find("_") + while next_underscore != -1: + vendor = board_id[:next_underscore] + board = board_id[next_underscore + 1 :] + p = portdir / f"boards/{vendor}/{board}/circuitpython.toml" + if p.exists(): + return p + next_underscore = board_id.find("_", next_underscore + 1) + return None + + +def load_mpconfigboard(portdir, board_id): + mpconfigboard_path = find_mpconfigboard(portdir, board_id) + if mpconfigboard_path is None or not mpconfigboard_path.exists(): + return None, {} + + with mpconfigboard_path.open("rb") as f: + return mpconfigboard_path, tomllib.load(f) + + +def get_shields(mpconfigboard): + shields = mpconfigboard.get("SHIELDS") + if shields is None: + shields = mpconfigboard.get("SHIELD") + + if shields is None: + return [] + if isinstance(shields, str): + return [shields] + if isinstance(shields, (list, tuple)): + return [str(shield) for shield in shields] + + return [str(shields)] diff --git a/ports/zephyr-cp/cptools/build_all_boards.py b/ports/zephyr-cp/cptools/build_all_boards.py new file mode 100755 index 0000000000000..8505e732efe71 --- /dev/null +++ b/ports/zephyr-cp/cptools/build_all_boards.py @@ -0,0 +1,520 @@ +#!/usr/bin/env python3 +""" +Build all CircuitPython boards for the Zephyr port. + +This script discovers all boards by finding circuitpython.toml files +and builds them in parallel while sharing a single jobserver across +all builds. + +This is agent generated and works. Don't bother reading too closely because it +is just a tool for us. +""" + +import argparse +import concurrent.futures +import os +import pathlib +import shlex +import subprocess +import sys +import time + + +class Jobserver: + def __init__(self, read_fd, write_fd, jobs=None, owns_fds=False): + self.read_fd = read_fd + self.write_fd = write_fd + self.jobs = jobs + self.owns_fds = owns_fds + + def acquire(self): + while True: + try: + os.read(self.read_fd, 1) + return + except InterruptedError: + continue + + def release(self): + while True: + try: + os.write(self.write_fd, b"+") + return + except InterruptedError: + continue + + def pass_fds(self): + return (self.read_fd, self.write_fd) + + def close(self): + if self.owns_fds: + os.close(self.read_fd) + os.close(self.write_fd) + + +def _parse_makeflags_jobserver(makeflags): + jobserver_auth = None + jobs = None + + for token in shlex.split(makeflags): + if token == "-j" or token == "--jobs": + continue + if token.startswith("-j") and token != "-j": + try: + jobs = int(token[2:]) + except ValueError: + pass + elif token.startswith("--jobs="): + try: + jobs = int(token.split("=", 1)[1]) + except ValueError: + pass + elif token.startswith("--jobserver-auth=") or token.startswith("--jobserver-fds="): + jobserver_auth = token.split("=", 1)[1] + + if not jobserver_auth: + return None, jobs, False + + if jobserver_auth.startswith("fifo:"): + fifo_path = jobserver_auth[len("fifo:") :] + read_fd = os.open(fifo_path, os.O_RDONLY) + write_fd = os.open(fifo_path, os.O_WRONLY) + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + return (read_fd, write_fd), jobs, True + + if "," in jobserver_auth: + read_fd, write_fd = jobserver_auth.split(",", 1) + return (int(read_fd), int(write_fd)), jobs, False + + return None, jobs, False + + +def _create_jobserver(jobs): + read_fd, write_fd = os.pipe() + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + for _ in range(jobs): + os.write(write_fd, b"+") + return Jobserver(read_fd, write_fd, jobs=jobs, owns_fds=True) + + +def _jobserver_from_env(): + makeflags = os.environ.get("MAKEFLAGS", "") + fds, jobs, owns_fds = _parse_makeflags_jobserver(makeflags) + if not fds: + return None, jobs + read_fd, write_fd = fds + os.set_inheritable(read_fd, True) + os.set_inheritable(write_fd, True) + return Jobserver(read_fd, write_fd, jobs=jobs, owns_fds=owns_fds), jobs + + +def discover_boards(port_dir): + """ + Discover all boards by finding circuitpython.toml files. + + Returns a list of (vendor, board) tuples. + """ + boards = [] + boards_dir = port_dir / "boards" + + # Find all circuitpython.toml files + for toml_file in boards_dir.glob("*/*/circuitpython.toml"): + # Extract vendor and board from path: boards/vendor/board/circuitpython.toml + parts = toml_file.relative_to(boards_dir).parts + if len(parts) == 3: + vendor = parts[0] + board = parts[1] + boards.append((vendor, board)) + + return sorted(boards) + + +def build_board( + port_dir, + vendor, + board, + extra_args=None, + jobserver=None, + env=None, + log_dir=None, +): + """ + Build a single board using make. + + Args: + port_dir: Path to the zephyr-cp port directory + vendor: Board vendor name + board: Board name + extra_args: Additional arguments to pass to make + jobserver: Jobserver instance to limit parallel builds + env: Environment variables for the subprocess + log_dir: Directory to write build logs + + Returns: + (success: bool, elapsed_time: float, output: str, log_path: pathlib.Path) + """ + board_id = f"{vendor}_{board}" + start_time = time.time() + log_path = None + + cmd = ["make", f"BOARD={board_id}"] + + # Add extra arguments (like -j) + if extra_args: + cmd.extend(extra_args) + + if jobserver: + jobserver.acquire() + + try: + result = subprocess.run( + cmd, + cwd=port_dir, + # Inherit stdin alongside jobserver file descriptors + stdin=sys.stdin, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + env=env, + pass_fds=jobserver.pass_fds() if jobserver else (), + ) + elapsed = time.time() - start_time + output = result.stdout or "" + if log_dir: + log_path = log_dir / f"{board_id}.log" + log_path.write_text(output) + return result.returncode == 0, elapsed, output, log_path + except KeyboardInterrupt: + raise + finally: + if jobserver: + jobserver.release() + + +def _format_status(status): + state = status["state"] + elapsed = status.get("elapsed") + if state == "queued": + return "QUEUED" + if state == "running": + return f"RUNNING {elapsed:.1f}s" + if state == "success": + return f"SUCCESS {elapsed:.1f}s" + if state == "failed": + return f"FAILED {elapsed:.1f}s" + if state == "skipped": + return "SKIPPED" + return state.upper() + + +def _build_status_table(boards, statuses, start_time, stop_submitting): + from rich.table import Table + from rich.text import Text + + elapsed = time.time() - start_time + title = f"Building {len(boards)} boards | Elapsed: {elapsed:.1f}s" + if stop_submitting: + title += " | STOPPING AFTER FAILURE" + + table = Table(title=title) + table.add_column("#", justify="right") + table.add_column("Board", no_wrap=True) + table.add_column("Status", no_wrap=True) + + for i, (vendor, board) in enumerate(boards): + board_id = f"{vendor}_{board}" + status_text = _format_status(statuses[i]) + state = statuses[i]["state"] + style = None + if state == "success": + style = "green" + elif state == "failed": + style = "red" + table.add_row( + f"{i + 1}/{len(boards)}", + board_id, + Text(status_text, style=style) if style else status_text, + ) + + return table + + +def _run_builds_tui( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + continue_on_error, +): + from rich.live import Live + + statuses = [ + {"state": "queued", "elapsed": 0.0, "start": None, "log_path": None} for _ in boards + ] + results = [] + futures = {} + next_index = 0 + stop_submitting = False + start_time = time.time() + + with Live( + _build_status_table(boards, statuses, start_time, stop_submitting), + refresh_per_second=4, + transient=False, + ) as live: + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + while next_index < len(boards) and len(futures) < max_workers: + vendor, board = boards[next_index] + statuses[next_index]["state"] = "running" + statuses[next_index]["start"] = time.time() + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = next_index + next_index += 1 + + while futures: + for status in statuses: + if status["state"] == "running": + status["elapsed"] = time.time() - status["start"] + + live.update(_build_status_table(boards, statuses, start_time, stop_submitting)) + + done, _ = concurrent.futures.wait( + futures, + timeout=0.1, + return_when=concurrent.futures.FIRST_COMPLETED, + ) + for future in done: + index = futures.pop(future) + vendor, board = boards[index] + success, elapsed, _output, log_path = future.result() + statuses[index]["elapsed"] = elapsed + statuses[index]["log_path"] = log_path + statuses[index]["state"] = "success" if success else "failed" + results.append((vendor, board, success, elapsed)) + + if not success and not continue_on_error: + stop_submitting = True + + if not stop_submitting and next_index < len(boards): + vendor, board = boards[next_index] + statuses[next_index]["state"] = "running" + statuses[next_index]["start"] = time.time() + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = next_index + next_index += 1 + + if stop_submitting: + for index in range(next_index, len(boards)): + if statuses[index]["state"] == "queued": + statuses[index]["state"] = "skipped" + + live.update(_build_status_table(boards, statuses, start_time, stop_submitting)) + + return results, stop_submitting + + +def _run_builds_plain( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + continue_on_error, +): + results = [] + futures = {} + next_index = 0 + stop_submitting = False + + with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor: + while next_index < len(boards) and len(futures) < max_workers: + vendor, board = boards[next_index] + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = (vendor, board) + next_index += 1 + + while futures: + done, _ = concurrent.futures.wait( + futures, + return_when=concurrent.futures.FIRST_COMPLETED, + ) + for future in done: + vendor, board = futures.pop(future) + success, elapsed, _output, _log_path = future.result() + board_id = f"{vendor}_{board}" + status = "SUCCESS" if success else "FAILURE" + print(f"{board_id}: {status} ({elapsed:.1f}s)") + results.append((vendor, board, success, elapsed)) + + if not success and not continue_on_error: + stop_submitting = True + + if not stop_submitting and next_index < len(boards): + vendor, board = boards[next_index] + future = executor.submit( + build_board, + port_dir, + vendor, + board, + extra_args, + jobserver, + env, + log_dir, + ) + futures[future] = (vendor, board) + next_index += 1 + + return results, stop_submitting + + +def main(): + parser = argparse.ArgumentParser( + description="Build all CircuitPython boards for the Zephyr port", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Build all boards in parallel with 32 jobserver slots + %(prog)s -j32 + + # Build all boards using make's jobserver (recommended) + make -j32 all +""", + ) + parser.add_argument( + "-j", + "--jobs", + type=int, + default=None, + help="Number of shared jobserver slots across all board builds", + ) + parser.add_argument( + "--continue-on-error", + action="store_true", + help="Continue building remaining boards even if one fails", + ) + parser.add_argument( + "--vendor", + type=str, + default=None, + help="Only build boards from this vendor (e.g. 'native' for sim boards)", + ) + + args = parser.parse_args() + + if args.jobs is not None and args.jobs < 1: + print("ERROR: --jobs must be at least 1") + return 2 + + # Get the port directory + port_dir = pathlib.Path(__file__).parent.resolve().parent + + # Discover all boards + boards = discover_boards(port_dir) + + if args.vendor: + boards = [(v, b) for v, b in boards if v == args.vendor] + + if not boards: + print("ERROR: No boards found!") + return 1 + + # Prepare jobserver and extra make arguments + jobserver, detected_jobs = _jobserver_from_env() + env = os.environ.copy() + + extra_args = [] + jobserver_jobs = detected_jobs + + if not jobserver: + jobserver_jobs = args.jobs if args.jobs else (os.cpu_count() or 1) + jobserver = _create_jobserver(jobserver_jobs) + env["MAKEFLAGS"] = ( + f"-j{jobserver_jobs} --jobserver-auth={jobserver.read_fd},{jobserver.write_fd}" + ) + + max_workers = jobserver_jobs + if max_workers is None: + max_workers = min(len(boards), os.cpu_count() or 1) + max_workers = max(1, min(len(boards), max_workers)) + + # Build all boards + log_dir = port_dir / "build-logs" + log_dir.mkdir(parents=True, exist_ok=True) + + try: + use_tui = sys.stdout.isatty() + if use_tui: + try: + import rich # noqa: F401 + except ImportError: + use_tui = False + + if use_tui: + results, stop_submitting = _run_builds_tui( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + args.continue_on_error, + ) + else: + results, stop_submitting = _run_builds_plain( + port_dir, + boards, + extra_args, + jobserver, + env, + log_dir, + max_workers, + args.continue_on_error, + ) + except KeyboardInterrupt: + print("\n\nBuild interrupted by user.") + return 130 # Standard exit code for SIGINT + finally: + if jobserver: + jobserver.close() + + failed = [r for r in results if not r[2]] + return 0 if len(failed) == 0 else 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ports/zephyr-cp/cptools/build_circuitpython.py b/ports/zephyr-cp/cptools/build_circuitpython.py new file mode 100644 index 0000000000000..1a55997974635 --- /dev/null +++ b/ports/zephyr-cp/cptools/build_circuitpython.py @@ -0,0 +1,699 @@ +import asyncio +import logging +import os +import pathlib +import pickle +import sys + +import board_tools +import colorlog +import cpbuild +import tomlkit +import tomllib +import yaml + +logger = logging.getLogger(__name__) + +# print("hello zephyr", sys.argv) + +# print(os.environ) +cmake_args = {} +for var in sys.argv[1:]: + key, value = var.split("=", 1) + cmake_args[key] = value + +# Path to ports/zephyr-cp +portdir = pathlib.Path(cmake_args["PORT_SRC_DIR"]) + +# Path to CP root +srcdir = portdir.parent.parent + +# Path to where CMake wants to put our build output. +builddir = pathlib.Path.cwd() + +zephyrdir = portdir / "zephyr" + +# Path to where CMake puts Zephyr's build output. +zephyrbuilddir = builddir / ".." / ".." / ".." / "zephyr" + +sys.path.append(str(portdir / "zephyr/scripts/dts/python-devicetree/src/")) +from zephyr2cp import zephyr_dts_to_cp_board + +compiler = cpbuild.Compiler(srcdir, builddir, cmake_args) + +ALWAYS_ON_MODULES = ["sys", "collections"] +DEFAULT_MODULES = [ + "__future__", + "time", + "os", + "microcontroller", + "struct", + "array", + "json", + "random", + "digitalio", + "rotaryio", + "rainbowio", + "traceback", + "warnings", + "supervisor", + "errno", + "io", + "math", + "msgpack", + "aesio", + "hashlib", + "zlib", + "adafruit_bus_device", +] +# Flags that don't match with with a *bindings module. Some used by adafruit_requests +MPCONFIG_FLAGS = ["array", "errno", "io", "json", "math"] + +# List of other modules (the value) that can be enabled when another one (the key) is. +REVERSE_DEPENDENCIES = { + "audiobusio": ["audiocore"], + "audiocore": [ + "audiodelays", + "audiofilters", + "audiofreeverb", + "audiomixer", + "audiomp3", + "synthio", + ], + "busio": ["fourwire", "i2cdisplaybus", "sdcardio", "sharpdisplay"], + "fourwire": ["displayio", "busdisplay", "epaperdisplay"], + "i2cdisplaybus": ["displayio", "busdisplay", "epaperdisplay"], + # Zephyr display backends need displayio and, by extension, terminalio so + # the REPL console appears on the display by default. + "zephyr_display": ["displayio"], + "displayio": [ + "vectorio", + "bitmapfilter", + "bitmaptools", + "terminalio", + "lvfontio", + "tilepalettemapper", + "fontio", + ], + "sharpdisplay": ["framebufferio"], + "framebufferio": ["displayio"], +} + +# Other flags to set when a module is enabled +EXTRA_FLAGS = { + "audiobusio": {"AUDIOBUSIO_I2SOUT": 1, "AUDIOBUSIO_PDMIN": 0}, + "busio": {"BUSIO_SPI": 1, "BUSIO_I2C": 1}, + "rotaryio": {"ROTARYIO_SOFTENCODER": 1}, + "synthio": {"SYNTHIO_MAX_CHANNELS": 12}, +} + +# Library sources. Will be globbed from the top level directory +# No QSTR processing or CIRCUITPY specific flags +LIBRARY_SOURCE = { + "audiomp3": ["lib/mp3/src/*.c"], + "zlib": [ + "lib/uzlib/tinflate.c", + "lib/uzlib/tinfzlib.c", + "lib/uzlib/tinfgzip.c", + "lib/uzlib/adler32.c", + "lib/uzlib/crc32.c", + ], +} + +SHARED_MODULE_AND_COMMON_HAL = ["_bleio", "os", "rotaryio"] + +# Mapping from module directory name to the flag name used in CIRCUITPY_ +MODULE_FLAG_NAMES = { + "__future__": "FUTURE", + "_bleio": "BLEIO", +} + + +async def preprocess_and_split_defs(compiler, source_file, build_path, flags): + build_file = source_file.with_suffix(".pp") + build_file = build_path / (build_file.relative_to(srcdir)) + await compiler.preprocess(source_file, build_file, flags=flags) + async with asyncio.TaskGroup() as tg: + for mode in ("qstr", "module", "root_pointer"): + split_file = build_file.relative_to(build_path).with_suffix(f".{mode}") + split_file = build_path / "genhdr" / mode / split_file + split_file.parent.mkdir(exist_ok=True, parents=True) + tg.create_task( + cpbuild.run_command( + [ + "python", + srcdir / "py/makeqstrdefs.py", + "split", + mode, + build_file, + build_path / "genhdr" / mode, + split_file, + ], + srcdir, + ) + ) + + +async def collect_defs(mode, build_path): + output_file = build_path / f"{mode}defs.collected" + splitdir = build_path / "genhdr" / mode + to_collect = list(splitdir.glob(f"**/*.{mode}")) + batch_size = 50 + await cpbuild.run_command( + ["cat", "-s", *to_collect[:batch_size], ">", output_file], + splitdir, + ) + for i in range(0, len(to_collect), batch_size): + await cpbuild.run_command( + ["cat", "-s", *to_collect[i : i + batch_size], ">>", output_file], + splitdir, + ) + return output_file + + +async def generate_qstr_headers(build_path, compiler, flags, translation): + collected = await collect_defs("qstr", build_path) + generated = build_path / "genhdr" / "qstrdefs.generated.h" + + await cpbuild.run_command( + ["python", srcdir / "py" / "makeqstrdata.py", collected, ">", generated], + srcdir, + ) + + compression_level = 9 + + # TODO: Do this alongside qstr stuff above. + await cpbuild.run_command( + [ + "python", + srcdir / "tools" / "msgfmt.py", + "-o", + build_path / f"{translation}.mo", + srcdir / "locale" / f"{translation}.po", + ], + srcdir, + ) + + await cpbuild.run_command( + [ + "python", + srcdir / "py" / "maketranslationdata.py", + "--compression_filename", + build_path / "genhdr" / "compressed_translations.generated.h", + "--translation", + build_path / f"{translation}.mo", + "--translation_filename", + build_path / f"translations-{translation}.c", + "--qstrdefs_filename", + generated, + "--compression_level", + compression_level, + generated, + ], + srcdir, + ) + + +async def generate_module_header(build_path): + collected = await collect_defs("module", build_path) + await cpbuild.run_command( + [ + "python", + srcdir / "py" / "makemoduledefs.py", + collected, + ">", + build_path / "genhdr" / "moduledefs.h", + ], + srcdir, + ) + + +async def generate_root_pointer_header(build_path): + collected = await collect_defs("root_pointer", build_path) + await cpbuild.run_command( + [ + "python", + srcdir / "py" / "make_root_pointers.py", + collected, + ">", + build_path / "genhdr" / "root_pointers.h", + ], + srcdir, + ) + + +async def generate_display_resources(output_path, translation, font, extra_characters): + await cpbuild.run_command( + [ + "python", + srcdir / "tools" / "gen_display_resources.py", + "--font", + srcdir / font, + "--sample_file", + srcdir / "locale" / f"{translation}.po", + "--extra_characters", + repr(extra_characters), + "--output_c_file", + output_path, + ], + srcdir, + check_hash=[output_path], + ) + + +async def generate_web_workflow_static(output_path, static_files): + await cpbuild.run_command( + [ + "python", + srcdir / "tools" / "gen_web_workflow_static.py", + "--output_c_file", + output_path, + *static_files, + ], + srcdir, + check_hash=[output_path], + ) + + +def determine_enabled_modules(board_info, portdir, srcdir): + """Determine which CircuitPython modules should be enabled based on board capabilities. + + Args: + board_info: Dictionary containing board hardware capabilities + portdir: Path to the port directory (ports/zephyr-cp) + srcdir: Path to the CircuitPython source root + + Returns: + tuple: (enabled_modules set, module_reasons dict) + """ + enabled_modules = set(DEFAULT_MODULES) + module_reasons = {} + + if board_info["wifi"]: + enabled_modules.add("wifi") + module_reasons["wifi"] = "Zephyr board has wifi" + + if board_info["flash_count"] > 0: + enabled_modules.add("storage") + module_reasons["storage"] = "Zephyr board has flash" + + network_enabled = board_info.get("wifi", False) or board_info.get("hostnetwork", False) + + if network_enabled: + enabled_modules.add("ipaddress") + module_reasons["ipaddress"] = "Zephyr networking enabled" + enabled_modules.add("socketpool") + module_reasons["socketpool"] = "Zephyr networking enabled" + enabled_modules.add("hashlib") + module_reasons["hashlib"] = "Zephyr networking enabled" + + if board_info.get("wifi", False) or board_info.get("ethernet", False): + enabled_modules.add("ssl") + module_reasons["ssl"] = "Zephyr networking enabled" + + for port_module in (portdir / "bindings").iterdir(): + if not board_info.get(port_module.name, False): + continue + enabled_modules.add(port_module.name) + module_reasons[port_module.name] = f"Zephyr board has {port_module.name}" + + for shared_module in (srcdir / "shared-bindings").iterdir(): + if not board_info.get(shared_module.name, False) or not shared_module.glob("*.c"): + continue + enabled_modules.add(shared_module.name) + module_reasons[shared_module.name] = f"Zephyr board has {shared_module.name}" + + more_modules = [] + more_modules.extend(REVERSE_DEPENDENCIES.get(shared_module.name, [])) + while more_modules: + reverse_dependency = more_modules.pop(0) + if reverse_dependency in enabled_modules: + continue + logger.debug(f"Enabling {reverse_dependency} because {shared_module.name} is enabled") + enabled_modules.add(reverse_dependency) + more_modules.extend(REVERSE_DEPENDENCIES.get(reverse_dependency, [])) + module_reasons[reverse_dependency] = f"Zephyr board has {shared_module.name}" + + return enabled_modules, module_reasons + + +async def build_circuitpython(): + circuitpython_flags = ["-DCIRCUITPY"] + port_flags = [] + enable_mpy_native = False + full_build = True + usb_host = False + zephyr_board = cmake_args["BOARD"] + board = cmake_args["BOARD_ALIAS"] + if not board: + board = zephyr_board + translation = cmake_args["TRANSLATION"] + if not translation: + translation = "en_US" + for module in ALWAYS_ON_MODULES: + circuitpython_flags.append(f"-DCIRCUITPY_{module.upper()}=1") + lto = cmake_args.get("LTO", "n") == "y" + circuitpython_flags.append(f"-DCIRCUITPY_ENABLE_MPY_NATIVE={1 if enable_mpy_native else 0}") + circuitpython_flags.append(f"-DCIRCUITPY_FULL_BUILD={1 if full_build else 0}") + circuitpython_flags.append(f"-DCIRCUITPY_SETTINGS_TOML={1 if full_build else 0}") + circuitpython_flags.append("-DCIRCUITPY_STATUS_BAR=1") + circuitpython_flags.append(f"-DCIRCUITPY_USB_HOST={1 if usb_host else 0}") + circuitpython_flags.append(f"-DCIRCUITPY_BOARD_ID='\"{board}\"'") + circuitpython_flags.append(f"-DCIRCUITPY_TRANSLATE_OBJECT={1 if lto else 0}") + circuitpython_flags.append("-DINTERNAL_FLASH_FILESYSTEM") + circuitpython_flags.append("-DLONGINT_IMPL_MPZ") + circuitpython_flags.append("-DCIRCUITPY_SSL_MBEDTLS") + circuitpython_flags.append("-DFFCONF_H='\"lib/oofatfs/ffconf.h\"'") + circuitpython_flags.append( + "-D_DEFAULT_SOURCE" + ) # To get more from picolibc to match newlib such as M_PI + circuitpython_flags.extend(("-I", srcdir)) + circuitpython_flags.extend(("-I", builddir)) + circuitpython_flags.extend(("-I", portdir)) + + genhdr = builddir / "genhdr" + genhdr.mkdir(exist_ok=True, parents=True) + version_header = genhdr / "mpversion.h" + mpconfigboard_fn = board_tools.find_mpconfigboard(portdir, board) + mpconfigboard = {"USB_VID": 0x1209, "USB_PID": 0x000C, "USB_INTERFACE_NAME": "CircuitPython"} + if mpconfigboard_fn is not None and mpconfigboard_fn.exists(): + with mpconfigboard_fn.open("rb") as f: + mpconfigboard.update(tomllib.load(f)) + async with asyncio.TaskGroup() as tg: + tg.create_task( + cpbuild.run_command( + [ + "python", + srcdir / "py" / "makeversionhdr.py", + version_header, + "&&", + "touch", + version_header, + ], + srcdir, + check_hash=[version_header], + ) + ) + + board_autogen_task = tg.create_task( + zephyr_dts_to_cp_board(zephyr_board, portdir, builddir, zephyrbuilddir, mpconfigboard) + ) + board_info = board_autogen_task.result() + if mpconfigboard_fn is None: + mpconfigboard_fn = ( + portdir / "boards" / board_info["vendor_id"] / board / "circuitpython.toml" + ) + logging.warning( + f"Could not find board config at: boards/{board_info['vendor_id']}/{board}" + ) + + autogen_board_info_fn = mpconfigboard_fn.parent / "autogen_board_info.toml" + + creator_id = mpconfigboard.get("CIRCUITPY_CREATOR_ID", mpconfigboard.get("USB_VID", 0x1209)) + creation_id = mpconfigboard.get("CIRCUITPY_CREATION_ID", mpconfigboard.get("USB_PID", 0x000C)) + circuitpython_flags.append(f"-DCIRCUITPY_CREATOR_ID=0x{creator_id:08x}") + circuitpython_flags.append(f"-DCIRCUITPY_CREATION_ID=0x{creation_id:08x}") + + vendor = mpconfigboard.get("VENDOR", board_info["vendor"]) + name = mpconfigboard.get("NAME", board_info["name"]) + + enabled_modules, module_reasons = determine_enabled_modules(board_info, portdir, srcdir) + for m in mpconfigboard.get("DISABLED_MODULES", []): + enabled_modules.discard(m) + + web_workflow_enabled = board_info.get("wifi", False) or board_info.get("hostnetwork", False) + + circuitpython_flags.extend(board_info["cflags"]) + circuitpython_flags.append(f"-DCIRCUITPY_WEB_WORKFLOW={1 if web_workflow_enabled else 0}") + supervisor_source = [ + "main.c", + "extmod/modjson.c", + "extmod/vfs_fat.c", + "lib/tlsf/tlsf.c", + portdir / "background.c", + portdir / "common-hal/microcontroller/__init__.c", + portdir / "common-hal/microcontroller/Pin.c", + portdir / "common-hal/microcontroller/Processor.c", + portdir / "common-hal/os/__init__.c", + "shared/readline/readline.c", + "shared/runtime/buffer_helper.c", + "shared/runtime/context_manager_helpers.c", + "shared/runtime/gchelper_generic.c", + "shared/runtime/gchelper_native.c", + "shared/runtime/pyexec.c", + "shared/runtime/interrupt_char.c", + "shared/runtime/stdout_helpers.c", + "shared/runtime/sys_stdio_mphal.c", + "shared-bindings/board/__init__.c", + "shared-bindings/supervisor/Runtime.c", + "shared-bindings/microcontroller/Pin.c", + "shared-bindings/util.c", + "shared-module/board/__init__.c", + "extmod/vfs_reader.c", + "extmod/vfs_blockdev.c", + "extmod/vfs_fat_file.c", + ] + top = srcdir + supervisor_source = [pathlib.Path(p) for p in supervisor_source] + supervisor_source.extend(board_info["source_files"]) + supervisor_source.extend(top.glob("supervisor/shared/*.c")) + if "_bleio" in enabled_modules: + supervisor_source.append(top / "supervisor/shared/bluetooth/bluetooth.c") + supervisor_source.append(top / "supervisor/shared/translate/translate.c") + if web_workflow_enabled: + supervisor_source.extend(top.glob("supervisor/shared/web_workflow/*.c")) + + usb_ok = board_info.get("usb_device", False) + circuitpython_flags.append(f"-DCIRCUITPY_USB_DEVICE={1 if usb_ok else 0}") + + if usb_ok: + enabled_modules.add("usb_cdc") + + for macro in ("USB_PID", "USB_VID"): + print(f"Setting {macro} to {mpconfigboard.get(macro)}") + circuitpython_flags.append(f"-D{macro}=0x{mpconfigboard.get(macro):04x}") + circuitpython_flags.append( + f"-DUSB_INTERFACE_NAME='\"{mpconfigboard['USB_INTERFACE_NAME']}\"'" + ) + for macro, limit, value in ( + ("USB_PRODUCT", 16, name), + ("USB_MANUFACTURER", 8, vendor), + ): + circuitpython_flags.append(f"-D{macro}='\"{value}\"'") + circuitpython_flags.append(f"-D{macro}_{limit}='\"{value[:limit]}\"'") + + circuitpython_flags.append("-DCIRCUITPY_USB_CDC_CONSOLE_ENABLED_DEFAULT=1") + circuitpython_flags.append("-DCIRCUITPY_USB_CDC_DATA_ENABLED_DEFAULT=0") + + supervisor_source.extend( + (portdir / "supervisor/usb.c", srcdir / "supervisor/shared/usb.c") + ) + + creator_id = mpconfigboard.get("CIRCUITPY_CREATOR_ID", mpconfigboard.get("USB_VID")) + creation_id = mpconfigboard.get("CIRCUITPY_CREATION_ID", mpconfigboard.get("USB_PID")) + if creator_id is not None: + circuitpython_flags.append(f"-DCIRCUITPY_CREATOR_ID=0x{creator_id:08x}") + if creation_id is not None: + circuitpython_flags.append(f"-DCIRCUITPY_CREATION_ID=0x{creation_id:08x}") + + # Always use port serial. It'll switch between USB and UART automatically. + circuitpython_flags.append("-DCIRCUITPY_PORT_SERIAL=1") + + if "hashlib" in enabled_modules: + circuitpython_flags.append("-DCIRCUITPY_HASHLIB_MBEDTLS=1") + if "ssl" not in enabled_modules: + circuitpython_flags.append("-DCIRCUITPY_HASHLIB_MBEDTLS_ONLY=1") + + if "ssl" in enabled_modules or "hashlib" in enabled_modules: + # TODO: Figure out how to get these paths from zephyr + circuitpython_flags.append("-DMBEDTLS_CONFIG_FILE='\"config-mbedtls.h\"'") + circuitpython_flags.extend( + ("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "include") + ) + circuitpython_flags.extend( + ("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "configs") + ) + circuitpython_flags.extend( + ("-isystem", portdir / "modules" / "crypto" / "mbedtls" / "include") + ) + circuitpython_flags.extend(("-isystem", zephyrdir / "modules" / "mbedtls" / "configs")) + if "ssl" in enabled_modules: + supervisor_source.append(top / "lib" / "mbedtls_config" / "crt_bundle.c") + + # Make sure all modules have a setting by filling in defaults. + hal_source = [] + library_sources = [] + autogen_board_info = tomlkit.document() + autogen_board_info.add( + tomlkit.comment( + "This file is autogenerated when a board is built. Do not edit. Do commit it to git. Other scripts use its info." + ) + ) + autogen_board_info.add("name", vendor + " " + name) + autogen_modules = tomlkit.table() + autogen_board_info.add("modules", autogen_modules) + for module in sorted( + list(top.glob("shared-bindings/*")) + list(portdir.glob("bindings/*")), + key=lambda x: x.name, + ): + # Skip files and directories without C source files (like artifacts from a docs build) + if not module.is_dir() or len(list(module.glob("*.c"))) == 0: + continue + enabled = module.name in enabled_modules + # print(f"Module {module.name} enabled: {enabled}") + v = tomlkit.item(enabled) + if module.name in module_reasons: + v.comment(module_reasons[module.name]) + autogen_modules.add(module.name, v) + flag_name = MODULE_FLAG_NAMES.get(module.name, module.name.upper()) + circuitpython_flags.append(f"-DCIRCUITPY_{flag_name}={1 if enabled else 0}") + + if enabled: + if module.name in EXTRA_FLAGS: + for flag, value in EXTRA_FLAGS[module.name].items(): + circuitpython_flags.append(f"-DCIRCUITPY_{flag}={value}") + + if enabled: + hal_source.extend(portdir.glob(f"bindings/{module.name}/*.c")) + len_before = len(hal_source) + hal_source.extend(top.glob(f"ports/zephyr-cp/common-hal/{module.name}/*.c")) + # Only include shared-module/*.c if no common-hal/*.c files were found + if len(hal_source) == len_before or module.name in SHARED_MODULE_AND_COMMON_HAL: + hal_source.extend(top.glob(f"shared-module/{module.name}/**/*.c")) + hal_source.extend(top.glob(f"shared-bindings/{module.name}/**/*.c")) + if module.name in LIBRARY_SOURCE: + for library_source in LIBRARY_SOURCE[module.name]: + library_sources.extend(top.glob(library_source)) + + if os.environ.get("CI", "false") == "true": + # Warn if it isn't up to date. + if ( + not autogen_board_info_fn.exists() + or autogen_board_info_fn.read_text() != tomlkit.dumps(autogen_board_info) + ): + logger.warning( + f"autogen_board_info.toml is missing or out of date. Please run `make BOARD={board}` locally and commit {autogen_board_info_fn}." + ) + if autogen_board_info_fn.parent.exists(): + autogen_board_info_fn.write_text(tomlkit.dumps(autogen_board_info)) + + for mpflag in MPCONFIG_FLAGS: + enabled = mpflag in DEFAULT_MODULES + circuitpython_flags.append(f"-DCIRCUITPY_{mpflag.upper()}={1 if enabled else 0}") + + source_files = supervisor_source + hal_source + ["extmod/vfs.c"] + assembly_files = [] + for file in top.glob("py/*.c"): + source_files.append(file) + qstr_flags = "-DNO_QSTR" + async with asyncio.TaskGroup() as tg: + for source_file in source_files: + tg.create_task( + preprocess_and_split_defs( + compiler, + top / source_file, + builddir, + [qstr_flags, *circuitpython_flags, *port_flags], + ) + ) + + if "ssl" in enabled_modules: + crt_bundle = builddir / "x509_crt_bundle.S" + roots_pem = srcdir / "lib/certificates/data/roots-full.pem" + generator = srcdir / "tools/gen_crt_bundle.py" + tg.create_task( + cpbuild.run_command( + [ + "python", + generator, + "-i", + roots_pem, + "-o", + crt_bundle, + "--asm", + ], + srcdir, + ) + ) + assembly_files.append(crt_bundle) + + async with asyncio.TaskGroup() as tg: + board_build = builddir + tg.create_task( + generate_qstr_headers( + board_build, compiler, [qstr_flags, *circuitpython_flags, *port_flags], translation + ) + ) + tg.create_task(generate_module_header(board_build)) + tg.create_task(generate_root_pointer_header(board_build)) + + if "terminalio" in enabled_modules: + output_path = board_build / f"autogen_display_resources-{translation}.c" + font_path = srcdir / mpconfigboard.get( + "CIRCUITPY_DISPLAY_FONT", "tools/fonts/ter-u12n.bdf" + ) + extra_characters = mpconfigboard.get("CIRCUITPY_FONT_EXTRA_CHARACTERS", "") + tg.create_task( + generate_display_resources(output_path, translation, font_path, extra_characters) + ) + source_files.append(output_path) + + if web_workflow_enabled: + output_path = board_build / "autogen_web_workflow_static.c" + static_files = sorted((srcdir / "supervisor/shared/web_workflow/static").glob("*")) + tg.create_task(generate_web_workflow_static(output_path, static_files)) + source_files.append(output_path) + + # This file is generated by the QSTR/translation process. + source_files.append(builddir / f"translations-{translation}.c") + # These files don't include unique QSTRs. They just need to be compiled. + source_files.append(portdir / "supervisor" / "flash.c") + source_files.append(portdir / "supervisor" / "port.c") + source_files.append(portdir / "supervisor" / "serial.c") + source_files.append(srcdir / "lib" / "oofatfs" / "ff.c") + source_files.append(srcdir / "lib" / "oofatfs" / "ffunicode.c") + source_files.append(srcdir / "extmod" / "vfs_fat_diskio.c") + source_files.append(srcdir / "shared/timeutils/timeutils.c") + source_files.append(srcdir / "shared-module/time/__init__.c") + source_files.append(srcdir / "shared-module/os/__init__.c") + source_files.append(srcdir / "shared-module/supervisor/__init__.c") + source_files.append(portdir / "bindings/zephyr_kernel/__init__.c") + source_files.append(portdir / "common-hal/zephyr_kernel/__init__.c") + # source_files.append(srcdir / "ports" / port / "peripherals" / "nrf" / "nrf52840" / "pins.c") + + source_files.extend(assembly_files) + + objects = [] + async with asyncio.TaskGroup() as tg: + for source_file in library_sources: + source_file = top / source_file + build_file = source_file.with_suffix(".o") + object_file = builddir / (build_file.relative_to(top)) + objects.append(object_file) + tg.create_task(compiler.compile(source_file, object_file)) + for source_file in source_files: + source_file = top / source_file + build_file = source_file.with_suffix(".o") + object_file = builddir / (build_file.relative_to(top)) + objects.append(object_file) + tg.create_task( + compiler.compile(source_file, object_file, [*circuitpython_flags, *port_flags]) + ) + + await compiler.archive(objects, pathlib.Path(cmake_args["OUTPUT_FILE"])) + + +async def main(): + try: + await build_circuitpython() + except* RuntimeError as e: + logger.error(e) + sys.exit(len(e.exceptions)) + + +handler = colorlog.StreamHandler() +handler.setFormatter(colorlog.ColoredFormatter("%(log_color)s%(levelname)s:%(name)s:%(message)s")) + +logging.basicConfig(level=logging.INFO, handlers=[handler]) + +asyncio.run(main()) diff --git a/ports/zephyr-cp/cptools/compat2driver.py b/ports/zephyr-cp/cptools/compat2driver.py new file mode 100644 index 0000000000000..7da74ffcf18c5 --- /dev/null +++ b/ports/zephyr-cp/cptools/compat2driver.py @@ -0,0 +1,3038 @@ +# This file was generated by gen_compat2driver.py +COMPAT_TO_DRIVER = { + # adc + "adi_ad4050_adc": "adc", + "adi_ad4052_adc": "adc", + "adi_ad4114_adc": "adc", + "adi_ad4130_adc": "adc", + "adi_ad4170_adc": "adc", + "adi_ad4190_adc": "adc", + "adi_ad4195_adc": "adc", + "adi_ad559x_adc": "adc", + "adi_ad7124_adc": "adc", + "adi_max32_adc": "adc", + "ambiq_adc": "adc", + "atmel_sam0_adc": "adc", + "atmel_sam_adc": "adc", + "atmel_sam_afec": "adc", + "bflb_adc": "adc", + "ene_kb106x_adc": "adc", + "ene_kb1200_adc": "adc", + "espressif_esp32_adc": "adc", + "gd_gd32_adc": "adc", + "infineon_adc": "adc", + "infineon_autanalog_sar_adc": "adc", + "infineon_hppass_sar_adc": "adc", + "infineon_sar_adc": "adc", + "infineon_xmc4xxx_adc": "adc", + "ite_it51xxx_adc": "adc", + "ite_it8xxx2_adc": "adc", + "lltc_ltc2451": "adc", + "maxim_max11102": "adc", + "maxim_max11103": "adc", + "maxim_max11105": "adc", + "maxim_max11106": "adc", + "maxim_max11110": "adc", + "maxim_max11111": "adc", + "maxim_max11115": "adc", + "maxim_max11116": "adc", + "maxim_max11117": "adc", + "maxim_max11253": "adc", + "maxim_max11254": "adc", + "microchip_adc_g1": "adc", + "microchip_mcp356xr": "adc", + "microchip_xec_adc": "adc", + "nordic_nrf_adc": "adc", + "nordic_nrf_saadc": "adc", + "nuvoton_npcx_adc": "adc", + "nuvoton_numaker_adc": "adc", + "nxp_adc12": "adc", + "nxp_gau_adc": "adc", + "nxp_kinetis_adc16": "adc", + "nxp_lpc_lpadc": "adc", + "nxp_mcux_12b1msps_sar": "adc", + "nxp_s32_adc_sar": "adc", + "nxp_sar_adc": "adc", + "nxp_vf610_adc": "adc", + "raspberrypi_pico_adc": "adc", + "realtek_rts5912_adc": "adc", + "renesas_ra_adc12": "adc", + "renesas_ra_adc16": "adc", + "renesas_rx_adc": "adc", + "renesas_rz_adc": "adc", + "renesas_rz_adc_c": "adc", + "renesas_rz_adc_e": "adc", + "renesas_rza2m_adc": "adc", + "renesas_smartbond_adc": "adc", + "renesas_smartbond_sdadc": "adc", + "sifli_sf32lb_gpadc": "adc", + "silabs_gecko_adc": "adc", + "silabs_iadc": "adc", + "silabs_siwx91x_adc": "adc", + "st_stm32_adc": "adc", + "st_stm32wb0_adc": "adc", + "telink_b91_adc": "adc", + "ti_ads1013": "adc", + "ti_ads1014": "adc", + "ti_ads1015": "adc", + "ti_ads1112": "adc", + "ti_ads1113": "adc", + "ti_ads1114": "adc", + "ti_ads1115": "adc", + "ti_ads1119": "adc", + "ti_ads114s06": "adc", + "ti_ads114s08": "adc", + "ti_ads124s06": "adc", + "ti_ads124s08": "adc", + "ti_ads131m02": "adc", + "ti_ads7052": "adc", + "ti_ads7950": "adc", + "ti_ads7951": "adc", + "ti_ads7952": "adc", + "ti_ads7953": "adc", + "ti_ads7954": "adc", + "ti_ads7955": "adc", + "ti_ads7956": "adc", + "ti_ads7957": "adc", + "ti_ads7958": "adc", + "ti_ads7959": "adc", + "ti_ads7960": "adc", + "ti_ads7961": "adc", + "ti_am335x_adc": "adc", + "ti_cc13xx_cc26xx_adc": "adc", + "ti_cc23x0_adc": "adc", + "ti_cc32xx_adc": "adc", + "ti_lmp90077": "adc", + "ti_lmp90078": "adc", + "ti_lmp90079": "adc", + "ti_lmp90080": "adc", + "ti_lmp90097": "adc", + "ti_lmp90098": "adc", + "ti_lmp90099": "adc", + "ti_lmp90100": "adc", + "ti_tla2021": "adc", + "ti_tla2022": "adc", + "ti_tla2024": "adc", + "vnd_adc": "adc", + "wch_adc": "adc", + "zephyr_adc_emul": "adc", + # + # audio + "ambiq_pdm": "audio", + "cirrus_cs43l22": "audio", + "dlg_da7212": "audio", + "maxim_max98091": "audio", + "nordic_nrf_pdm": "audio", + "nxp_dmic": "audio", + "nxp_micfil": "audio", + "sifli_sf32lb_audcodec": "audio", + "st_mpxxdtyy": "audio", + "ti_pcm1681": "audio", + "ti_tas6422dac": "audio", + "ti_tlv320aic3110": "audio", + "ti_tlv320dac": "audio", + "wolfson_wm8904": "audio", + "wolfson_wm8962": "audio", + # + # audio/mic_privacy/intel + "intel_adsp_mic_privacy": "audio/mic_privacy/intel", + # + # auxdisplay + "gpio_7_segment": "auxdisplay", + "hit_hd44780": "auxdisplay", + "jhd_jhd1313": "auxdisplay", + "noritake_itron": "auxdisplay", + "ptc_pt6314": "auxdisplay", + "sparkfun_serlcd": "auxdisplay", + "titanmec_tm1637": "auxdisplay", + # + # bbram + "ite_it8xxx2_bbram": "bbram", + "microchip_xec_bbram": "bbram", + "motorola_mc146818_bbram": "bbram", + "nuvoton_npcx_bbram": "bbram", + "realtek_rts5912_bbram": "bbram", + "st_stm32_bbram": "bbram", + "zephyr_bbram_emul": "bbram", + # + # biometrics + "adh_tech_gt5x": "biometrics", + "zephyr_biometrics_emul": "biometrics", + "zhiantec_zfm_x0": "biometrics", + # + # bluetooth/hci + "ambiq_bt_hci_spi": "bluetooth/hci", + "espressif_esp32_bt_hci": "bluetooth/hci", + "infineon_bless_hci": "bluetooth/hci", + "infineon_bt_hci_uart": "bluetooth/hci", + "infineon_cyw208xx_hci": "bluetooth/hci", + "nxp_bt_hci_uart": "bluetooth/hci", + "nxp_hci_ble": "bluetooth/hci", + "renesas_bt_hci_da1453x": "bluetooth/hci", + "renesas_bt_hci_da1469x": "bluetooth/hci", + "sifli_sf32lb_mailbox": "bluetooth/hci", + "silabs_bt_hci_efr32": "bluetooth/hci", + "silabs_siwx91x_bt_hci": "bluetooth/hci", + "st_hci_spi_v1": "bluetooth/hci", + "st_hci_spi_v2": "bluetooth/hci", + "st_hci_stm32wb0": "bluetooth/hci", + "st_hci_stm32wba": "bluetooth/hci", + "st_stm32wb_rf": "bluetooth/hci", + "zephyr_bt_hci_3wire_uart": "bluetooth/hci", + "zephyr_bt_hci_ipc": "bluetooth/hci", + "zephyr_bt_hci_spi": "bluetooth/hci", + "zephyr_bt_hci_uart": "bluetooth/hci", + "zephyr_bt_hci_userchan": "bluetooth/hci", + # + # cache + "bflb_l1c": "cache", + # + # can + "adi_max32_can": "can", + "atmel_sam0_can": "can", + "atmel_sam_can": "can", + "espressif_esp32_twai": "can", + "infineon_xmc4xxx_can_node": "can", + "kvaser_pcican": "can", + "microchip_mcp2515": "can", + "microchip_mcp251xfd": "can", + "nordic_nrf_can": "can", + "nuvoton_numaker_canfd": "can", + "nxp_flexcan": "can", + "nxp_lpc_mcan": "can", + "nxp_s32_canxl": "can", + "renesas_ra_canfd": "can", + "renesas_rcar_can": "can", + "renesas_rz_canfd": "can", + "st_stm32_bxcan": "can", + "st_stm32_fdcan": "can", + "st_stm32h7_fdcan": "can", + "ti_tcan4x5x": "can", + "zephyr_can_loopback": "can", + "zephyr_fake_can": "can", + "zephyr_native_linux_can": "can", + # + # can/transceiver + "can_transceiver_gpio": "can/transceiver", + # + # charger + "maxim_max20335_charger": "charger", + "nxp_pca9422_charger": "charger", + "nxp_pf1550_charger": "charger", + "sbs_sbs_charger": "charger", + "ti_bq24190": "charger", + "ti_bq25180": "charger", + "ti_bq25186": "charger", + "ti_bq25188": "charger", + "ti_bq25713": "charger", + "x_powers_axp2101_charger": "charger", + "zephyr_charger_gpio": "charger", + # + # clock_control + "adi_max32_gcr": "clock_control", + "alif_clockctrl": "clock_control", + "ambiq_clkctrl": "clock_control", + "arm_beetle_syscon": "clock_control", + "arm_scmi_clock": "clock_control", + "aspeed_ast10x0_clock": "clock_control", + "atmel_sam_pmc": "clock_control", + "bflb_bl60x_clock_controller": "clock_control", + "bflb_bl61x_clock_controller": "clock_control", + "bflb_bl70x_clock_controller": "clock_control", + "espressif_esp32_clock": "clock_control", + "fixed_clock": "clock_control", + "focaltech_ft9001_cpm": "clock_control", + "gd_gd32_cctl": "clock_control", + "infineon_fixed_clock": "clock_control", + "infineon_fixed_factor_clock": "clock_control", + "infineon_peri_div": "clock_control", + "intel_agilex5_clock": "clock_control", + "ite_it51xxx_ecpm": "clock_control", + "microchip_pic32cm_jh_clock": "clock_control", + "microchip_pic32cm_pl_clock": "clock_control", + "microchip_pic32cz_ca_clock": "clock_control", + "microchip_sam_d5x_e5x_clock": "clock_control", + "microchip_sam_pmc": "clock_control", + "microchip_sama7g5_sckc": "clock_control", + "microchip_xec_pcr": "clock_control", + "nordic_nrf54h_hfxo": "clock_control", + "nordic_nrf_auxpll": "clock_control", + "nordic_nrf_clock": "clock_control", + "nordic_nrf_fll16m": "clock_control", + "nordic_nrf_hsfll_global": "clock_control", + "nordic_nrf_hsfll_local": "clock_control", + "nordic_nrf_iron_hsfll_local": "clock_control", + "nordic_nrf_lfclk": "clock_control", + "nordic_nrfs_audiopll": "clock_control", + "nuvoton_npcm_pcc": "clock_control", + "nuvoton_npcx_pcc": "clock_control", + "nuvoton_numaker_scc": "clock_control", + "nxp_imx_ccm": "clock_control", + "nxp_imx_ccm_rev2": "clock_control", + "nxp_kinetis_mcg": "clock_control", + "nxp_kinetis_pcc": "clock_control", + "nxp_kinetis_scg": "clock_control", + "nxp_kinetis_sim": "clock_control", + "nxp_lpc11u6x_syscon": "clock_control", + "nxp_lpc_syscon": "clock_control", + "nxp_mc_cgm": "clock_control", + "nxp_s32_clock": "clock_control", + "nxp_scg_k4": "clock_control", + "openisa_rv32m1_pcc": "clock_control", + "pwm_clock": "clock_control", + "raspberrypi_pico_clock_controller": "clock_control", + "realtek_bee_cctl": "clock_control", + "realtek_rts5817_clock": "clock_control", + "realtek_rts5912_sccon": "clock_control", + "renesas_r8a7795_cpg_mssr": "clock_control", + "renesas_r8a779f0_cpg_mssr": "clock_control", + "renesas_ra_cgc_subclk": "clock_control", + "renesas_rx_cgc_pclk": "clock_control", + "renesas_rx_cgc_pll": "clock_control", + "renesas_rx_cgc_root_clock": "clock_control", + "renesas_rz_cgc": "clock_control", + "renesas_rz_cpg": "clock_control", + "renesas_rza2m_cpg": "clock_control", + "sifli_sf32lb_hxt48": "clock_control", + "sifli_sf32lb_rcc_clk": "clock_control", + "silabs_series_clock": "clock_control", + "silabs_si32_ahb": "clock_control", + "silabs_si32_apb": "clock_control", + "silabs_si32_pll": "clock_control", + "silabs_siwx91x_clock": "clock_control", + "smartbond_clock": "clock_control", + "st_stm32_clock_mco": "clock_control", + "st_stm32_clock_mux": "clock_control", + "st_stm32f1_clock_mco": "clock_control", + "ti_k2g_sci_clk": "clock_control", + "wch_rcc": "clock_control", + # + # comparator + "ite_it51xxx_vcmp": "comparator", + "microchip_ac_g1_comparator": "comparator", + "nordic_nrf_comp": "comparator", + "nordic_nrf_lpcomp": "comparator", + "nxp_acomp": "comparator", + "nxp_cmp": "comparator", + "nxp_hscmp": "comparator", + "renesas_ra_acmphs": "comparator", + "renesas_ra_lvd": "comparator", + "renesas_rx_lvd": "comparator", + "silabs_acmp": "comparator", + "st_stm32_comp": "comparator", + "zephyr_fake_comp": "comparator", + # + # coredump + "zephyr_coredump": "coredump", + # + # counter + "adi_max32_counter": "counter", + "adi_max32_rtc_counter": "counter", + "adi_max32_wut": "counter", + "ambiq_counter": "counter", + "andestech_atcpit100": "counter", + "arm_cmsdk_dtimer": "counter", + "arm_cmsdk_timer": "counter", + "atmel_sam0_tc32": "counter", + "atmel_sam_tc": "counter", + "espressif_esp32_counter": "counter", + "espressif_esp32_rtc_timer": "counter", + "gd_gd32_timer": "counter", + "infineon_counter": "counter", + "infineon_tcpwm_counter": "counter", + "ite_it51xxx_counter": "counter", + "ite_it8xxx2_counter": "counter", + "maxim_ds3231": "counter", + "microchip_mcp7940n": "counter", + "microchip_sam_pit64b_counter": "counter", + "microchip_tc_g1_counter": "counter", + "microchip_tcc_g1_counter": "counter", + "microchip_xec_timer": "counter", + "microcrystal_rv3032_counter": "counter", + "neorv32_gptmr": "counter", + "nordic_nrf_rtc": "counter", + "nordic_nrf_timer": "counter", + "nuvoton_npck_lct": "counter", + "nuvoton_npcx_lct_v1": "counter", + "nuvoton_npcx_lct_v2": "counter", + "nxp_ftm": "counter", + "nxp_imx_epit": "counter", + "nxp_imx_gpt": "counter", + "nxp_imx_qtmr": "counter", + "nxp_imx_snvs_rtc": "counter", + "nxp_imx_tmr": "counter", + "nxp_lpc_ctimer": "counter", + "nxp_lpc_rtc": "counter", + "nxp_lpc_rtc_highres": "counter", + "nxp_lpit": "counter", + "nxp_mrt": "counter", + "nxp_pit": "counter", + "nxp_rtc": "counter", + "nxp_rtc_jdp": "counter", + "nxp_s32_sys_timer": "counter", + "nxp_stm": "counter", + "nxp_tpm_timer": "counter", + "raspberrypi_pico_pit": "counter", + "raspberrypi_pico_pit_channel": "counter", + "raspberrypi_pico_timer": "counter", + "realtek_rts5912_slwtimer": "counter", + "realtek_rts5912_timer": "counter", + "renesas_ra_agt_counter": "counter", + "renesas_rz_cmtw_counter": "counter", + "renesas_rz_gtm_counter": "counter", + "renesas_smartbond_timer": "counter", + "silabs_burtc_counter": "counter", + "silabs_gecko_rtcc": "counter", + "silabs_timer_counter": "counter", + "snps_dw_timers": "counter", + "st_stm32_counter": "counter", + "ti_cc23x0_lgpt": "counter", + "ti_cc23x0_rtc": "counter", + "ti_mspm0_timer_counter": "counter", + "xlnx_xps_timer_1_00_a": "counter", + "zephyr_native_sim_counter": "counter", + # + # crc + "nxp_crc": "crc", + "nxp_lpc_crc": "crc", + "renesas_ra_crc": "crc", + "sifli_sf32lb_crc": "crc", + # + # crypto + "atmel_ataes132a": "crypto", + "espressif_esp32_aes": "crypto", + "espressif_esp32_sha": "crypto", + "intel_adsp_sha": "crypto", + "ite_it51xxx_sha": "crypto", + "ite_it8xxx2_sha": "crypto", + "ite_it8xxx2_sha_v2": "crypto", + "microchip_sha_g1_crypto": "crypto", + "microchip_xec_symcr": "crypto", + "nordic_nrf_ecb": "crypto", + "nuvoton_npcx_sha": "crypto", + "nxp_mcux_dcp": "crypto", + "nxp_s32_crypto_hse_mu": "crypto", + "raspberrypi_pico_sha256": "crypto", + "realtek_rts5912_sha": "crypto", + "renesas_smartbond_crypto": "crypto", + "silabs_si32_aes": "crypto", + "st_stm32_aes": "crypto", + "st_stm32_cryp": "crypto", + "st_stm32_hash": "crypto", + "ti_cc23x0_aes": "crypto", + # + # dac + "adi_ad559x_dac": "dac", + "adi_ad5601": "dac", + "adi_ad5611": "dac", + "adi_ad5621": "dac", + "adi_ad5628": "dac", + "adi_ad5648": "dac", + "adi_ad5668": "dac", + "adi_ad5672": "dac", + "adi_ad5674": "dac", + "adi_ad5676": "dac", + "adi_ad5679": "dac", + "adi_ad5684": "dac", + "adi_ad5686": "dac", + "adi_ad5687": "dac", + "adi_ad5689": "dac", + "adi_ad5691": "dac", + "adi_ad5692": "dac", + "adi_ad5693": "dac", + "adi_max22017_dac": "dac", + "atmel_sam0_dac": "dac", + "atmel_sam_dac": "dac", + "atmel_samd5x_dac": "dac", + "espressif_esp32_dac": "dac", + "gd_gd32_dac": "dac", + "microchip_dac_g1": "dac", + "microchip_mcp4725": "dac", + "microchip_mcp4728": "dac", + "nxp_dac12": "dac", + "nxp_gau_dac": "dac", + "nxp_kinetis_dac": "dac", + "nxp_kinetis_dac32": "dac", + "nxp_lpdac": "dac", + "renesas_ra_dac": "dac", + "silabs_vdac": "dac", + "st_stm32_dac": "dac", + "ti_dac161s997": "dac", + "ti_dacx0501": "dac", + "vnd_dac": "dac", + # + # dai/intel/alh + "intel_alh_dai": "dai/intel/alh", + # + # dai/intel/dmic + "intel_dai_dmic": "dai/intel/dmic", + # + # dai/intel/hda + "intel_hda_dai": "dai/intel/hda", + # + # dai/intel/ssp + "intel_ssp_dai": "dai/intel/ssp", + # + # dai/nxp/esai + "nxp_dai_esai": "dai/nxp/esai", + # + # dai/nxp/micfil + "nxp_dai_micfil": "dai/nxp/micfil", + # + # dai/nxp/sai + "nxp_dai_sai": "dai/nxp/sai", + # + # debug + "nordic_coresight_nrf": "debug", + "silabs_pti": "debug", + # + # disk + "st_stm32_sdmmc": "disk", + "zephyr_flash_disk": "disk", + "zephyr_mmc_disk": "disk", + "zephyr_ram_disk": "disk", + "zephyr_sdmmc_disk": "disk", + # + # disk/nvme + "nvme_controller": "disk/nvme", + # + # display + "chipone_co5300": "display", + "frida_nt35510": "display", + "galaxycore_gc9x01x": "display", + "himax_hx8379c": "display", + "himax_hx8394": "display", + "ilitek_ili9806e_dsi": "display", + "intel_multiboot_framebuffer": "display", + "istech_ist3931": "display", + "jdi_lpm013m126": "display", + "led_strip_matrix": "display", + "maxim_max7219": "display", + "nxp_dcnano_lcdif": "display", + "nxp_imx_elcdif": "display", + "nxp_imx_lcdifv3": "display", + "orisetech_otm8009a": "display", + "raydium_rm67162": "display", + "raydium_rm68200": "display", + "renesas_ra_glcdc": "display", + "renesas_smartbond_display": "display", + "sharp_ls0xx": "display", + "sitronix_st75256": "display", + "sitronix_st7701": "display", + "sitronix_st7735r": "display", + "sitronix_st7789v": "display", + "sitronix_st7796s": "display", + "solomon_ssd1322": "display", + "st_stm32_ltdc": "display", + "waveshare_dsi2dpi": "display", + "zephyr_dummy_dc": "display", + "zephyr_hub12": "display", + "zephyr_sdl_dc": "display", + # + # dma + "adi_max32_dma": "dma", + "altr_msgdma": "dma", + "andestech_atcdmacx00": "dma", + "arm_dma_pl330": "dma", + "atmel_sam0_dmac": "dma", + "atmel_sam_xdmac": "dma", + "bflb_dma": "dma", + "brcm_iproc_pax_dma_v1": "dma", + "brcm_iproc_pax_dma_v2": "dma", + "espressif_esp32_gdma": "dma", + "gd_gd32_dma": "dma", + "gd_gd32_dma_v1": "dma", + "infineon_dma": "dma", + "infineon_xmc4xxx_dma": "dma", + "intel_adsp_gpdma": "dma", + "intel_adsp_hda_host_in": "dma", + "intel_adsp_hda_host_out": "dma", + "intel_adsp_hda_link_in": "dma", + "intel_adsp_hda_link_out": "dma", + "intel_lpss": "dma", + "intel_sedi_dma": "dma", + "microchip_dmac_g1_dma": "dma", + "microchip_xec_dmac": "dma", + "nuvoton_npcx_gdma": "dma", + "nxp_4ch_dma": "dma", + "nxp_edma": "dma", + "nxp_lpc_dma": "dma", + "nxp_mcux_edma": "dma", + "nxp_pxp": "dma", + "nxp_sdma": "dma", + "nxp_smartdma": "dma", + "nxp_sof_host_dma": "dma", + "raspberrypi_pico_dma": "dma", + "renesas_ra_dma": "dma", + "renesas_rz_dmac": "dma", + "renesas_rz_dmac_b": "dma", + "renesas_smartbond_dma": "dma", + "sifli_sf32lb_dmac": "dma", + "silabs_gpdma": "dma", + "silabs_ldma": "dma", + "silabs_si32_dma": "dma", + "silabs_siwx91x_dma": "dma", + "snps_designware_dma": "dma", + "snps_designware_dma_axi": "dma", + "st_stm32_bdma": "dma", + "st_stm32_dma_v1": "dma", + "st_stm32_dma_v2": "dma", + "st_stm32_dma_v2bis": "dma", + "st_stm32_dmamux": "dma", + "st_stm32u5_dma": "dma", + "ti_cc23x0_dma": "dma", + "wch_wch_dma": "dma", + "xlnx_axi_dma_1_00_a": "dma", + "xlnx_eth_dma": "dma", + "zephyr_dma_emul": "dma", + # + # dp + "zephyr_swdp_gpio": "dp", + # + # edac + "intel_ibecc": "edac", + "nxp_erm": "edac", + "xlnx_zynqmp_ddrc_2_40a": "edac", + # + # eeprom + "atmel_at24": "eeprom", + "fujitsu_mb85rcxx": "eeprom", + "fujitsu_mb85rsxx": "eeprom", + "infineon_fm25xxx": "eeprom", + "microchip_xec_eeprom": "eeprom", + "nxp_lpc11u6x_eeprom": "eeprom", + "st_stm32_eeprom": "eeprom", + "ti_tmp11x_eeprom": "eeprom", + "zephyr_emu_eeprom": "eeprom", + "zephyr_fake_eeprom": "eeprom", + "zephyr_sim_eeprom": "eeprom", + # + # entropy + "adi_max32_trng": "entropy", + "adi_maxq10xx_trng": "entropy", + "ambiq_puf_trng": "entropy", + "atmel_sam_trng": "entropy", + "brcm_iproc_rng200": "entropy", + "espressif_esp32_trng": "entropy", + "gd_gd32_trng": "entropy", + "litex_prbs": "entropy", + "microchip_trng_g1_entropy": "entropy", + "neorv32_trng": "entropy", + "nordic_nrf_cracen_ctrdrbg": "entropy", + "nordic_nrf_rng": "entropy", + "nuvoton_npcx_drbg": "entropy", + "nxp_ele_trng": "entropy", + "nxp_imx_caam": "entropy", + "nxp_kinetis_rnga": "entropy", + "nxp_kinetis_trng": "entropy", + "nxp_lpc_rng": "entropy", + "openisa_rv32m1_trng": "entropy", + "raspberrypi_pico_rng": "entropy", + "renesas_smartbond_trng": "entropy", + "sensry_sy1xx_trng": "entropy", + "sifli_sf32lb_trng": "entropy", + "silabs_gecko_semailbox": "entropy", + "silabs_gecko_trng": "entropy", + "silabs_siwx91x_rng": "entropy", + "st_stm32_rng": "entropy", + "st_stm32_rng_noirq": "entropy", + "telink_b91_trng": "entropy", + "ti_cc13xx_cc26xx_trng": "entropy", + "ti_mspm0_trng": "entropy", + "virtio_device4": "entropy", + "zephyr_bt_hci_entropy": "entropy", + "zephyr_native_sim_rng": "entropy", + "zephyr_psa_crypto_rng": "entropy", + # + # espi + "ite_it8xxx2_espi": "espi", + "microchip_xec_espi": "espi", + "microchip_xec_espi_host_dev": "espi", + "microchip_xec_espi_saf": "espi", + "microchip_xec_espi_saf_v2": "espi", + "microchip_xec_espi_v2": "espi", + "nuvoton_npcx_espi": "espi", + "nuvoton_npcx_espi_taf": "espi", + "nuvoton_npcx_host_sub": "espi", + "realtek_rts5912_espi": "espi", + "zephyr_espi_emul_controller": "espi", + # + # ethernet + "adi_adin1110": "ethernet", + "adi_adin2111": "ethernet", + "atmel_sam0_gmac": "ethernet", + "atmel_sam_gmac": "ethernet", + "espressif_esp32_eth": "ethernet", + "infineon_xmc4xxx_ethernet": "ethernet", + "intel_e1000": "ethernet", + "litex_liteeth": "ethernet", + "microchip_enc28j60": "ethernet", + "microchip_enc424j600": "ethernet", + "microchip_lan865x": "ethernet", + "microchip_lan9250": "ethernet", + "nuvoton_numaker_ethernet": "ethernet", + "nxp_enet": "ethernet", + "nxp_enet1g": "ethernet", + "nxp_enet_mac": "ethernet", + "nxp_s32_gmac": "ethernet", + "nxp_s32_netc_psi": "ethernet", + "nxp_s32_netc_vsi": "ethernet", + "renesas_ra_ethernet": "ethernet", + "sensry_sy1xx_mac": "ethernet", + "siemens_ivshmem_eth": "ethernet", + "silabs_gecko_ethernet": "ethernet", + "smsc_lan91c111": "ethernet", + "smsc_lan91c111_mdio": "ethernet", + "smsc_lan9220": "ethernet", + "snps_designware_ethernet": "ethernet", + "snps_ethernet_cyclonev": "ethernet", + "st_stm32_ethernet": "ethernet", + "ti_stellaris_ethernet": "ethernet", + "virtio_net": "ethernet", + "vnd_ethernet": "ethernet", + "wiznet_w5500": "ethernet", + "wiznet_w6100": "ethernet", + "xlnx_axi_ethernet_1_00_a": "ethernet", + "xlnx_gem": "ethernet", + "xlnx_xps_ethernetlite_1_00_a_mac": "ethernet", + "xlnx_xps_ethernetlite_3_00_a_mac": "ethernet", + # + # ethernet/dsa + "microchip_ksz8463": "ethernet/dsa", + "microchip_ksz8794": "ethernet/dsa", + "microchip_ksz8863": "ethernet/dsa", + "nxp_netc_switch": "ethernet/dsa", + # + # ethernet/dwc_xgmac + "snps_dwcxgmac": "ethernet/dwc_xgmac", + # + # ethernet/eth_nxp_enet_qos + "nxp_enet_qos": "ethernet/eth_nxp_enet_qos", + "nxp_enet_qos_mac": "ethernet/eth_nxp_enet_qos", + # + # ethernet/intel + "intel_eth_plat": "ethernet/intel", + "intel_igc_mac": "ethernet/intel", + # + # ethernet/mdio + "adi_adin2111_mdio": "ethernet/mdio", + "atmel_sam_mdio": "ethernet/mdio", + "espressif_esp32_mdio": "ethernet/mdio", + "infineon_xmc4xxx_mdio": "ethernet/mdio", + "intel_igc_mdio": "ethernet/mdio", + "litex_liteeth_mdio": "ethernet/mdio", + "microchip_lan865x_mdio": "ethernet/mdio", + "nxp_enet_mdio": "ethernet/mdio", + "nxp_enet_qos_mdio": "ethernet/mdio", + "nxp_imx_netc_emdio": "ethernet/mdio", + "nxp_s32_gmac_mdio": "ethernet/mdio", + "nxp_s32_netc_emdio": "ethernet/mdio", + "renesas_ra_mdio": "ethernet/mdio", + "sensry_sy1xx_mdio": "ethernet/mdio", + "snps_dwcxgmac_mdio": "ethernet/mdio", + "st_stm32_mdio": "ethernet/mdio", + "xlnx_axi_ethernet_1_00_a_mdio": "ethernet/mdio", + "xlnx_xps_ethernetlite_1_00_a_mdio": "ethernet/mdio", + "xlnx_xps_ethernetlite_3_00_a_mdio": "ethernet/mdio", + "zephyr_mdio_gpio": "ethernet/mdio", + # + # ethernet/nxp_imx_netc + "nxp_imx_netc_blk_ctrl": "ethernet/nxp_imx_netc", + "nxp_imx_netc_psi": "ethernet/nxp_imx_netc", + # + # ethernet/phy + "adi_adin1100_phy": "ethernet/phy", + "adi_adin2111_phy": "ethernet/phy", + "davicom_dm8806_phy": "ethernet/phy", + "ethernet_phy": "ethernet/phy", + "ethernet_phy_fixed_link": "ethernet/phy", + "microchip_ksz8081": "ethernet/phy", + "microchip_ksz9131": "ethernet/phy", + "microchip_lan8742": "ethernet/phy", + "microchip_t1s_phy": "ethernet/phy", + "microchip_vsc8541": "ethernet/phy", + "motorcomm_yt8521": "ethernet/phy", + "nxp_tja1103": "ethernet/phy", + "nxp_tja11xx": "ethernet/phy", + "qca_ar8031": "ethernet/phy", + "realtek_rtl8211f": "ethernet/phy", + "ti_dp83825": "ethernet/phy", + "ti_dp83867": "ethernet/phy", + # + # firmware/scmi + "arm_scmi": "firmware/scmi", + "arm_scmi_shmem": "firmware/scmi", + # + # firmware/tisci + "ti_k2g_sci": "firmware/tisci", + # + # flash + "adi_max32_flash_controller": "flash", + "adi_max32_spixf_nor": "flash", + "ambiq_flash_controller": "flash", + "andestech_qspi_nor": "flash", + "andestech_qspi_nor_xip": "flash", + "atmel_at25xv021a": "flash", + "atmel_at45": "flash", + "atmel_sam0_nvmctrl": "flash", + "atmel_sam_flash_controller": "flash", + "bflb_flash_controller": "flash", + "cdns_nand": "flash", + "cdns_qspi_nor": "flash", + "espressif_esp32_flash_controller": "flash", + "gd_gd32_flash_controller": "flash", + "infineon_flash_controller": "flash", + "infineon_qspi_flash": "flash", + "infineon_xmc4xxx_flash_controller": "flash", + "ite_it51xxx_manual_flash_1k": "flash", + "ite_it8xxx2_flash_controller": "flash", + "jedec_mspi_nor": "flash", + "jedec_spi_nand": "flash", + "jedec_spi_nor": "flash", + "microchip_nvmctrl_g1_flash": "flash", + "mspi_atxp032": "flash", + "mspi_is25xx0xx": "flash", + "netsol_s3axx04": "flash", + "nordic_mram": "flash", + "nordic_nrf51_flash_controller": "flash", + "nordic_nrf52_flash_controller": "flash", + "nordic_nrf53_flash_controller": "flash", + "nordic_nrf91_flash_controller": "flash", + "nordic_nrf_mramc": "flash", + "nordic_qspi_nor": "flash", + "nordic_rram_controller": "flash", + "nuvoton_npcx_fiu_nor": "flash", + "nuvoton_npcx_fiu_qspi": "flash", + "nuvoton_numaker_fmc": "flash", + "nuvoton_numaker_rmc": "flash", + "nxp_c40_flash_controller": "flash", + "nxp_iap_fmc11": "flash", + "nxp_iap_fmc54": "flash", + "nxp_iap_fmc55": "flash", + "nxp_iap_fmc553": "flash", + "nxp_imx_flexspi_hyperflash": "flash", + "nxp_imx_flexspi_mx25um51345g": "flash", + "nxp_imx_flexspi_nor": "flash", + "nxp_kinetis_ftfa": "flash", + "nxp_kinetis_ftfc": "flash", + "nxp_kinetis_ftfe": "flash", + "nxp_kinetis_ftfl": "flash", + "nxp_msf1": "flash", + "nxp_s32_qspi_hyperflash": "flash", + "nxp_s32_qspi_nor": "flash", + "nxp_s32_xspi_hyperram": "flash", + "nxp_xspi_nor": "flash", + "openisa_rv32m1_ftfe": "flash", + "raspberrypi_pico_flash_controller": "flash", + "realtek_rts5912_flash_controller": "flash", + "renesas_ra_flash_hp_controller": "flash", + "renesas_ra_flash_lp_controller": "flash", + "renesas_ra_mram_controller": "flash", + "renesas_ra_ospi_b_nor": "flash", + "renesas_ra_qspi_nor": "flash", + "renesas_rx_flash": "flash", + "renesas_rz_qspi_spibsc": "flash", + "renesas_rz_qspi_xspi": "flash", + "renesas_smartbond_flash_controller": "flash", + "sifli_sf32lb_mpi_qspi_nor": "flash", + "silabs_gecko_flash_controller": "flash", + "silabs_series2_flash_controller": "flash", + "silabs_si32_flash_controller": "flash", + "silabs_siwx91x_flash_controller": "flash", + "st_stm32_flash_controller": "flash", + "st_stm32_ospi_nor": "flash", + "st_stm32_qspi_nor": "flash", + "st_stm32_xspi_nor": "flash", + "st_stm32h7_flash_controller": "flash", + "st_stm32wb0_flash_controller": "flash", + "st_stm32wba_flash_controller": "flash", + "telink_b91_flash_controller": "flash", + "ti_cc13xx_cc26xx_flash_controller": "flash", + "ti_cc23x0_flash_controller": "flash", + "zephyr_mspi_emul_flash": "flash", + "zephyr_sim_flash": "flash", + # + # fpga + "altr_socfpga_agilex_bridge": "fpga", + "lattice_ice40_fpga": "fpga", + "lattice_ice40_fpga_bitbang": "fpga", + "microchip_mpfs_mailbox": "fpga", + "renesas_slg47105": "fpga", + "renesas_slg47115": "fpga", + "xlnx_fpga": "fpga", + # + # fuel_gauge/axp2101 + "x_powers_axp2101_fuel_gauge": "fuel_gauge/axp2101", + # + # fuel_gauge/bq27z746 + "ti_bq27z746": "fuel_gauge/bq27z746", + # + # fuel_gauge/bq40z50 + "ti_bq40z50": "fuel_gauge/bq40z50", + # + # fuel_gauge/composite + "zephyr_fuel_gauge_composite": "fuel_gauge/composite", + # + # fuel_gauge/hy4245 + "hycon_hy4245": "fuel_gauge/hy4245", + # + # fuel_gauge/lc709203f + "onnn_lc709203f": "fuel_gauge/lc709203f", + # + # fuel_gauge/ltc2959 + "adi_ltc2959": "fuel_gauge/ltc2959", + # + # fuel_gauge/max17048 + "maxim_max17048": "fuel_gauge/max17048", + # + # fuel_gauge/sbs_gauge + "sbs_sbs_gauge": "fuel_gauge/sbs_gauge", + "sbs_sbs_gauge_new_api": "fuel_gauge/sbs_gauge", + # + # fuel_gauge/sy24561 + "silergy_sy24561": "fuel_gauge/sy24561", + # + # gnss + "gnss_nmea_generic": "gnss", + "luatos_air530z": "gnss", + "quectel_lc26g": "gnss", + "quectel_lc76g": "gnss", + "quectel_lc86g": "gnss", + "zephyr_gnss_emul": "gnss", + # + # gnss/u_blox + "u_blox_f9p": "gnss/u_blox", + "u_blox_m8": "gnss/u_blox", + # + # gpio + "adi_ad559x_gpio": "gpio", + "adi_adp5585_gpio": "gpio", + "adi_max14906_gpio": "gpio", + "adi_max14915_gpio": "gpio", + "adi_max14916_gpio": "gpio", + "adi_max14917_gpio": "gpio", + "adi_max22017_gpio": "gpio", + "adi_max22190_gpio": "gpio", + "adi_max22199_gpio": "gpio", + "adi_max32_gpio": "gpio", + "aesc_gpio": "gpio", + "altr_pio_1_0": "gpio", + "ambiq_gpio_bank": "gpio", + "andestech_atcgpio100": "gpio", + "arm_cmsdk_gpio": "gpio", + "arm_mmio32_gpio": "gpio", + "atmel_sam0_gpio": "gpio", + "atmel_sam4l_gpio": "gpio", + "atmel_sam_gpio": "gpio", + "awinic_aw9523b_gpio": "gpio", + "bflb_bl60x_70x_gpio": "gpio", + "bflb_bl61x_gpio": "gpio", + "brcm_bcm2711_gpio": "gpio", + "brcm_brcmstb_gpio": "gpio", + "brcm_iproc_gpio": "gpio", + "cypress_cy8c95xx_gpio_port": "gpio", + "cypress_psoc6_gpio": "gpio", + "efinix_sapphire_gpio": "gpio", + "ene_kb106x_gpio": "gpio", + "ene_kb1200_gpio": "gpio", + "espressif_esp32_gpio": "gpio", + "espressif_esp32_lpgpio": "gpio", + "fcs_fxl6408": "gpio", + "gaisler_grgpio": "gpio", + "gd_gd32_gpio": "gpio", + "infineon_gpio": "gpio", + "infineon_tle9104_gpio": "gpio", + "infineon_xmc4xxx_gpio": "gpio", + "intel_gpio": "gpio", + "intel_sedi_gpio": "gpio", + "ite_it51xxx_gpio": "gpio", + "ite_it8801_gpio": "gpio", + "ite_it8xxx2_gpio": "gpio", + "ite_it8xxx2_gpio_v2": "gpio", + "ite_it8xxx2_gpiokscan": "gpio", + "litex_gpio": "gpio", + "microchip_mcp23008": "gpio", + "microchip_mcp23009": "gpio", + "microchip_mcp23016": "gpio", + "microchip_mcp23017": "gpio", + "microchip_mcp23018": "gpio", + "microchip_mcp23s08": "gpio", + "microchip_mcp23s09": "gpio", + "microchip_mcp23s17": "gpio", + "microchip_mcp23s18": "gpio", + "microchip_mpfs_gpio": "gpio", + "microchip_port_g1_gpio": "gpio", + "microchip_sam_pio4": "gpio", + "microchip_xec_gpio": "gpio", + "neorv32_gpio": "gpio", + "nordic_npm1300_gpio": "gpio", + "nordic_npm1304_gpio": "gpio", + "nordic_npm2100_gpio": "gpio", + "nordic_npm6001_gpio": "gpio", + "nordic_nrf_gpio": "gpio", + "nuvoton_nct38xx_gpio": "gpio", + "nuvoton_nct38xx_gpio_alert": "gpio", + "nuvoton_nct38xx_gpio_port": "gpio", + "nuvoton_npcx_gpio": "gpio", + "nuvoton_numaker_gpio": "gpio", + "nuvoton_numicro_gpio": "gpio", + "nxp_imx_gpio": "gpio", + "nxp_imx_rgpio": "gpio", + "nxp_kinetis_gpio": "gpio", + "nxp_lpc11u6x_gpio": "gpio", + "nxp_lpc_gpio_port": "gpio", + "nxp_pca6408": "gpio", + "nxp_pca6416": "gpio", + "nxp_pca9538": "gpio", + "nxp_pca9539": "gpio", + "nxp_pca9554": "gpio", + "nxp_pca9555": "gpio", + "nxp_pca95xx": "gpio", + "nxp_pcal6408": "gpio", + "nxp_pcal6408a": "gpio", + "nxp_pcal6416": "gpio", + "nxp_pcal6416a": "gpio", + "nxp_pcal6524": "gpio", + "nxp_pcal6534": "gpio", + "nxp_pcal9538": "gpio", + "nxp_pcal9539": "gpio", + "nxp_pcal9722": "gpio", + "nxp_pcf857x": "gpio", + "nxp_sc18im704_gpio": "gpio", + "nxp_sc18is606_gpio": "gpio", + "nxp_siul2_gpio": "gpio", + "openisa_rv32m1_gpio": "gpio", + "quicklogic_eos_s3_gpio": "gpio", + "raspberrypi_pico_gpio_port": "gpio", + "raspberrypi_rp1_gpio": "gpio", + "realtek_ameba_gpio": "gpio", + "realtek_bee_gpio": "gpio", + "realtek_rts5912_gpio": "gpio", + "renesas_ra_gpio_ioport": "gpio", + "renesas_rcar_gpio": "gpio", + "renesas_rx_gpio": "gpio", + "renesas_rz_gpio": "gpio", + "renesas_rza2m_gpio": "gpio", + "renesas_rzt2m_gpio": "gpio", + "renesas_smartbond_gpio": "gpio", + "richtek_rt1718s": "gpio", + "richtek_rt1718s_gpio_port": "gpio", + "rohm_bd8lb600fs_gpio": "gpio", + "semtech_sx1509b": "gpio", + "sensry_sy1xx_gpio": "gpio", + "sifive_gpio0": "gpio", + "sifli_sf32lb_gpio": "gpio", + "silabs_gecko_gpio_port": "gpio", + "silabs_gpio": "gpio", + "silabs_si32_gpio": "gpio", + "silabs_siwx91x_gpio": "gpio", + "silabs_siwx91x_gpio_uulp": "gpio", + "snps_creg_gpio": "gpio", + "snps_designware_gpio": "gpio", + "st_mfxstm32l152": "gpio", + "st_stm32_gpio": "gpio", + "st_stmpe1600": "gpio", + "telink_b91_gpio": "gpio", + "ti_ads1x4s0x_gpio": "gpio", + "ti_cc13xx_cc26xx_gpio": "gpio", + "ti_cc23x0_gpio": "gpio", + "ti_cc32xx_gpio": "gpio", + "ti_davinci_gpio": "gpio", + "ti_lmp90xxx_gpio": "gpio", + "ti_mspm0_gpio": "gpio", + "ti_sn74hc595": "gpio", + "ti_stellaris_gpio": "gpio", + "ti_tca6424a": "gpio", + "ti_tca9538": "gpio", + "vnd_gpio": "gpio", + "wch_gpio": "gpio", + "x_powers_axp192_gpio": "gpio", + "xlnx_ps_gpio": "gpio", + "xlnx_ps_gpio_bank": "gpio", + "xlnx_xps_gpio_1_00_a": "gpio", + "zephyr_gpio_emul": "gpio", + "zephyr_gpio_emul_sdl": "gpio", + # + # haptics/cirrus + "cirrus_cs40l5x": "haptics/cirrus", + # + # haptics/ti + "ti_drv2605": "haptics/ti", + # + # hdlc_rcp_if + "nxp_hdlc_rcp_if": "hdlc_rcp_if", + "spi_hdlc_rcp_if": "hdlc_rcp_if", + "uart_hdlc_rcp_if": "hdlc_rcp_if", + # + # hwinfo + "atmel_sam0_id": "hwinfo", + "atmel_sam4l_uid": "hwinfo", + "atmel_sam_rstc": "hwinfo", + "cypress_psoc6_uid": "hwinfo", + "litex_dna0": "hwinfo", + "nxp_imx_src": "hwinfo", + "nxp_imx_src_rev2": "hwinfo", + "nxp_lpc_uid": "hwinfo", + # + # hwspinlock + "nxp_sema42": "hwspinlock", + "sqn_hwspinlock": "hwspinlock", + "vnd_hwspinlock": "hwspinlock", + # + # i2c + "adi_max32_i2c": "i2c", + "altr_nios2_i2c": "i2c", + "ambiq_i2c": "i2c", + "andestech_atciic100": "i2c", + "arm_versatile_i2c": "i2c", + "atmel_sam0_i2c": "i2c", + "atmel_sam_i2c_twi": "i2c", + "atmel_sam_i2c_twihs": "i2c", + "atmel_sam_i2c_twim": "i2c", + "bflb_i2c": "i2c", + "brcm_iproc_i2c": "i2c", + "cdns_i2c": "i2c", + "ene_kb1200_i2c": "i2c", + "espressif_esp32_i2c": "i2c", + "fsl_imx21_i2c": "i2c", + "gd_gd32_i2c": "i2c", + "gpio_i2c": "i2c", + "gpio_i2c_switch": "i2c", + "infineon_i2c": "i2c", + "infineon_xmc4xxx_i2c": "i2c", + "intel_sedi_i2c": "i2c", + "ite_enhance_i2c": "i2c", + "ite_it51xxx_i2c": "i2c", + "ite_it8xxx2_i2c": "i2c", + "litex_i2c": "i2c", + "litex_litei2c": "i2c", + "microchip_mpfs_i2c": "i2c", + "microchip_sercom_g1_i2c": "i2c", + "microchip_xec_i2c": "i2c", + "microchip_xec_i2c_v2": "i2c", + "nordic_nrf_twi": "i2c", + "nordic_nrf_twim": "i2c", + "nordic_nrf_twis": "i2c", + "nuvoton_npcx_i2c_ctrl": "i2c", + "nuvoton_npcx_i2c_port": "i2c", + "nuvoton_numaker_i2c": "i2c", + "nxp_ii2c": "i2c", + "nxp_kinetis_i2c": "i2c", + "nxp_lpc11u6x_i2c": "i2c", + "nxp_lpc_i2c": "i2c", + "nxp_lpi2c": "i2c", + "nxp_sc18im704_i2c": "i2c", + "openisa_rv32m1_lpi2c": "i2c", + "realtek_rts5912_i2c": "i2c", + "renesas_ra_i2c_sci": "i2c", + "renesas_ra_i2c_sci_b": "i2c", + "renesas_ra_iic": "i2c", + "renesas_rcar_i2c": "i2c", + "renesas_rx_i2c": "i2c", + "renesas_rz_iic": "i2c", + "renesas_rz_riic": "i2c", + "renesas_rza2m_riic": "i2c", + "renesas_smartbond_i2c": "i2c", + "sensry_sy1xx_i2c": "i2c", + "sifive_i2c0": "i2c", + "sifli_sf32lb_i2c": "i2c", + "silabs_gecko_i2c": "i2c", + "silabs_i2c": "i2c", + "snps_designware_i2c": "i2c", + "st_stm32_i2c_v1": "i2c", + "st_stm32_i2c_v2": "i2c", + "telink_b91_i2c": "i2c", + "ti_cc13xx_cc26xx_i2c": "i2c", + "ti_cc23x0_i2c": "i2c", + "ti_cc32xx_i2c": "i2c", + "ti_omap_i2c": "i2c", + "ti_tca9544a": "i2c", + "ti_tca9546a": "i2c", + "ti_tca9548a": "i2c", + "vnd_i2c": "i2c", + "wch_i2c": "i2c", + "xlnx_xps_iic_2_00_a": "i2c", + "xlnx_xps_iic_2_1": "i2c", + "zephyr_i2c_emul_controller": "i2c", + # + # i2c/target + "zephyr_i2c_target_eeprom": "i2c/target", + # + # i2s + "adi_max32_i2s": "i2s", + "ambiq_i2s": "i2s", + "atmel_sam_ssc": "i2s", + "espressif_esp32_i2s": "i2s", + "infineon_i2s": "i2s", + "nordic_nrf_i2s": "i2s", + "nxp_lpc_i2s": "i2s", + "nxp_mcux_i2s": "i2s", + "renesas_ra_i2s_ssie": "i2s", + "silabs_siwx91x_i2s": "i2s", + "st_stm32_i2s": "i2s", + "st_stm32_sai": "i2s", + "vnd_i2s": "i2s", + "zephyr_i2s_sdl": "i2s", + # + # i3c + "adi_max32_i3c": "i3c", + "cdns_i3c": "i3c", + "ite_it51xxx_i3cm": "i3c", + "ite_it51xxx_i3cs": "i3c", + "nuvoton_npcx_i3c": "i3c", + "nxp_mcux_i3c": "i3c", + "renesas_ra_i3c": "i3c", + "snps_designware_i3c": "i3c", + "st_stm32_i3c": "i3c", + "vnd_i3c": "i3c", + # + # ieee802154 + "atmel_rf2xx": "ieee802154", + "decawave_dw1000": "ieee802154", + "espressif_esp32_ieee802154": "ieee802154", + "nordic_nrf_ieee802154": "ieee802154", + "nxp_kw41z_ieee802154": "ieee802154", + "nxp_mcr20a": "ieee802154", + "nxp_mcxw_ieee802154": "ieee802154", + "st_stm32wba_ieee802154": "ieee802154", + "telink_b91_zb": "ieee802154", + "ti_cc1200": "ieee802154", + "ti_cc13xx_cc26xx_ieee802154": "ieee802154", + "ti_cc13xx_cc26xx_ieee802154_subghz": "ieee802154", + "ti_cc2520": "ieee802154", + "zephyr_ieee802154_uart_pipe": "ieee802154", + # + # input + "adc_keys": "input", + "analog_axis": "input", + "arduino_modulino_buttons": "input", + "bflb_irx": "input", + "chipsemi_chsc5x": "input", + "chipsemi_chsc6x": "input", + "cirque_pinnacle": "input", + "cypress_cy8cmbr3xxx": "input", + "espressif_esp32_touch": "input", + "focaltech_ft5336": "input", + "focaltech_ft6146": "input", + "futaba_sbus": "input", + "goodix_gt911": "input", + "gpio_kbd_matrix": "input", + "gpio_keys": "input", + "gpio_qdec": "input", + "hynitron_cst816s": "input", + "ilitek_ili2132a": "input", + "ite_it51xxx_kbd": "input", + "ite_it8801_kbd": "input", + "ite_it8xxx2_kbd": "input", + "microchip_cap12xx": "input", + "microchip_xec_kbd": "input", + "nintendo_nunchuk": "input", + "nuvoton_npcx_kbd": "input", + "nxp_mcux_kpp": "input", + "parade_tma525b": "input", + "pixart_pat912x": "input", + "pixart_paw32xx": "input", + "pixart_pmw3610": "input", + "realtek_rts5912_kbd": "input", + "renesas_ra_ctsu": "input", + "renesas_ra_ctsu_button": "input", + "renesas_ra_ctsu_slider": "input", + "renesas_ra_ctsu_wheel": "input", + "renesas_rx_ctsu": "input", + "sitronix_cf1133": "input", + "st_stm32_tsc": "input", + "st_stmpe811": "input", + "vishay_vs1838b": "input", + "wch_ch9350l": "input", + "xptek_xpt2046": "input", + "zephyr_input_sdl_touch": "input", + "zephyr_native_linux_evdev": "input", + # + # interrupt_controller + "adi_max32_rv32_intc": "interrupt_controller", + "arm_gic_v1": "interrupt_controller", + "arm_gic_v2": "interrupt_controller", + "arm_gic_v3": "interrupt_controller", + "arm_gic_v3_its": "interrupt_controller", + "atmel_sam0_eic": "interrupt_controller", + "gaisler_irqmp": "interrupt_controller", + "gd_gd32_exti": "interrupt_controller", + "hazard3_hazard3_intc": "interrupt_controller", + "infineon_xmc4xxx_intc": "interrupt_controller", + "intel_ace_intc": "interrupt_controller", + "intel_cavs_intc": "interrupt_controller", + "intel_ioapic": "interrupt_controller", + "intel_loapic": "interrupt_controller", + "intel_vt_d": "interrupt_controller", + "ite_it51xxx_wuc": "interrupt_controller", + "ite_it8xxx2_wuc": "interrupt_controller", + "litex_vexriscv_intc0": "interrupt_controller", + "mediatek_adsp_intc": "interrupt_controller", + "microchip_eic_g1_intc": "interrupt_controller", + "microchip_xec_ecia": "interrupt_controller", + "nuclei_eclic": "interrupt_controller", + "nuvoton_npcx_miwu": "interrupt_controller", + "nxp_gint": "interrupt_controller", + "nxp_irqsteer_intc": "interrupt_controller", + "nxp_pint": "interrupt_controller", + "nxp_s32_wkpu": "interrupt_controller", + "nxp_siul2_eirq": "interrupt_controller", + "openisa_rv32m1_intmux": "interrupt_controller", + "renesas_rx_grp_intc": "interrupt_controller", + "renesas_rx_icu": "interrupt_controller", + "renesas_rz_ext_irq": "interrupt_controller", + "renesas_rz_tint": "interrupt_controller", + "riscv_clic": "interrupt_controller", + "riscv_imsic": "interrupt_controller", + "shared_irq": "interrupt_controller", + "sifive_plic_1_0_0": "interrupt_controller", + "snps_arcv2_intc": "interrupt_controller", + "snps_designware_intc": "interrupt_controller", + "st_stm32wb0_gpio_intc": "interrupt_controller", + "swerv_pic": "interrupt_controller", + "ti_vim": "interrupt_controller", + "wch_exti": "interrupt_controller", + "wch_pfic": "interrupt_controller", + # + # ipm + "arm_mhu": "ipm", + "espressif_esp32_ipm": "ipm", + "intel_sedi_ipm": "ipm", + "linaro_ivshmem_ipm": "ipm", + "nordic_nrf_ipc": "ipm", + "nxp_imx_mu": "ipm", + "nxp_lpc_mailbox": "ipm", + "st_stm32_hsem_mailbox": "ipm", + "st_stm32_ipcc_mailbox": "ipm", + "xlnx_zynqmp_ipi_mailbox": "ipm", + "zephyr_mbox_ipm": "ipm", + # + # led + "arduino_modulino_buttons_leds": "led", + "dac_leds": "led", + "gpio_leds": "led", + "holtek_ht16k33": "led", + "issi_is31fl3194": "led", + "issi_is31fl3216a": "led", + "issi_is31fl3733": "led", + "leds_group_multicolor": "led", + "microchip_xec_bbled": "led", + "nordic_npm1300_led": "led", + "nordic_npm1304_led": "led", + "nxp_pca9533": "led", + "nxp_pca9633": "led", + "onnn_ncp5623": "led", + "pwm_leds": "led", + "sct_sct2024": "led", + "ti_lp3943": "led", + "ti_lp5009": "led", + "ti_lp5012": "led", + "ti_lp5018": "led", + "ti_lp5024": "led", + "ti_lp5030": "led", + "ti_lp5036": "led", + "ti_lp5562": "led", + "ti_lp5569": "led", + "ti_tlc59108": "led", + # + # led_strip + "apa_apa102": "led_strip", + "arduino_modulino_pixels": "led_strip", + "greeled_lpd8803": "led_strip", + "greeled_lpd8806": "led_strip", + "ti_tlc5971": "led_strip", + "ti_tlc59731": "led_strip", + "worldsemi_ws2812_gpio": "led_strip", + "worldsemi_ws2812_i2s": "led_strip", + "worldsemi_ws2812_rpi_pico_pio": "led_strip", + "worldsemi_ws2812_spi": "led_strip", + "worldsemi_ws2812_uart": "led_strip", + # + # lora + "reyax_rylrxxx": "lora", + # + # lora/loramac-node + "semtech_sx1272": "lora/loramac-node", + "semtech_sx1276": "lora/loramac-node", + # + # lora/native/sx126x + "semtech_sx1261": "lora/native/sx126x", + "semtech_sx1262": "lora/native/sx126x", + "st_stm32wl_subghz_radio": "lora/native/sx126x", + # + # mbox + "andestech_mbox_plic_sw": "mbox", + "arm_mhuv3": "mbox", + "espressif_mbox_esp32": "mbox", + "linaro_ivshmem_mbox": "mbox", + "nordic_mbox_nrf_ipc": "mbox", + "nordic_nrf_bellboard_rx": "mbox", + "nordic_nrf_bellboard_tx": "mbox", + "nordic_nrf_vevif_event_rx": "mbox", + "nordic_nrf_vevif_event_tx": "mbox", + "nordic_nrf_vevif_task_rx": "mbox", + "nordic_nrf_vevif_task_tx": "mbox", + "nxp_mbox_imx_mu": "mbox", + "nxp_mbox_mailbox": "mbox", + "nxp_s32_mru": "mbox", + "raspberrypi_pico_mbox": "mbox", + "renesas_ra_ipc_mbox": "mbox", + "renesas_rz_mhu_mbox": "mbox", + "st_mbox_stm32_hsem": "mbox", + "ti_omap_mailbox": "mbox", + "ti_secure_proxy": "mbox", + "xlnx_mbox_versal_ipi_mailbox": "mbox", + # + # memc + "adi_max32_hpb": "memc", + "atmel_sam_smc": "memc", + "bflb_bl61x_psram": "memc", + "mspi_aps6404l": "memc", + "mspi_aps_z8": "memc", + "nxp_imx_flexspi": "memc", + "nxp_imx_flexspi_is66wvs8m8": "memc", + "nxp_imx_flexspi_s27ks0641": "memc", + "nxp_imx_flexspi_w956a8mbya": "memc", + "nxp_s32_qspi": "memc", + "nxp_s32_xspi": "memc", + "nxp_xspi": "memc", + "nxp_xspi_psram": "memc", + "renesas_ra_sdram": "memc", + "renesas_smartbond_nor_psram": "memc", + "sifive_fu740_c000_ddr": "memc", + "silabs_siwx91x_qspi_memory": "memc", + "st_stm32_fmc": "memc", + "st_stm32_fmc_nor_psram": "memc", + "st_stm32_fmc_sdram": "memc", + "st_stm32_ospi_psram": "memc", + "st_stm32_xspi_psram": "memc", + "st_stm32h7_fmc": "memc", + # + # mfd + "adi_ad559x": "mfd", + "adi_adp5585": "mfd", + "adi_max22017": "mfd", + "adi_maxq10xx": "mfd", + "awinic_aw9523b": "mfd", + "infineon_tle9104": "mfd", + "ite_it8801_altctrl": "mfd", + "ite_it8801_mfd": "mfd", + "maxim_ds3231_mfd": "mfd", + "maxim_max20335": "mfd", + "maxim_max31790": "mfd", + "microchip_sam_flexcom": "mfd", + "microcrystal_rv3032_mfd": "mfd", + "motorola_mc146818_mfd": "mfd", + "nordic_npm1300": "mfd", + "nordic_npm1304": "mfd", + "nordic_npm2100": "mfd", + "nordic_npm6001": "mfd", + "nuvoton_nct38xx": "mfd", + "nxp_lp_flexcomm": "mfd", + "nxp_pca9422": "mfd", + "nxp_pf1550": "mfd", + "nxp_sc18is606": "mfd", + "rohm_bd8lb600fs": "mfd", + # + # mipi_dbi + "bflb_dbi": "mipi_dbi", + "espressif_esp32_lcd_cam_mipi_dbi": "mipi_dbi", + "nxp_lcdic": "mipi_dbi", + "nxp_mipi_dbi_dcnano_lcdif": "mipi_dbi", + "nxp_mipi_dbi_flexio_lcdif": "mipi_dbi", + "raspberrypi_pico_mipi_dbi_pio": "mipi_dbi", + "renesas_smartbond_mipi_dbi": "mipi_dbi", + "sifli_sf32lb_lcdc_mipi_dbi": "mipi_dbi", + "st_stm32_fmc_mipi_dbi": "mipi_dbi", + "zephyr_mipi_dbi_bitbang": "mipi_dbi", + "zephyr_mipi_dbi_spi": "mipi_dbi", + # + # mipi_dsi + "nxp_imx_mipi_dsi": "mipi_dsi", + "nxp_mipi_dsi_2l": "mipi_dsi", + "nxp_mipi_dsi_dwc": "mipi_dsi", + "renesas_ra_mipi_dsi": "mipi_dsi", + "st_stm32_mipi_dsi": "mipi_dsi", + "vnd_mipi_dsi": "mipi_dsi", + # + # misc/devmux + "zephyr_devmux": "misc/devmux", + # + # misc/ethos_u + "arm_ethos_u": "misc/ethos_u", + "nuvoton_numaker_npu": "misc/ethos_u", + "renesas_ra_npu": "misc/ethos_u", + # + # misc/ft8xx + "ftdi_ft800": "misc/ft8xx", + # + # misc/grove_lcd_rgb + "seeed_grove_lcd_rgb": "misc/grove_lcd_rgb", + # + # misc/interconn/renesas_elc + "renesas_ra_elc": "misc/interconn/renesas_elc", + # + # misc/mcux_flexio + "nxp_flexio": "misc/mcux_flexio", + # + # misc/nordic_vpr_launcher + "nordic_nrf_vpr_coprocessor": "misc/nordic_vpr_launcher", + # + # misc/nxp_imx93_mediamix + "nxp_imx93_mediamix": "misc/nxp_imx93_mediamix", + # + # misc/nxp_rtxxx_dsp_ctrl + "nxp_rt600_dsp_ctrl": "misc/nxp_rtxxx_dsp_ctrl", + "nxp_rt700_dsp_ctrl_hifi4": "misc/nxp_rtxxx_dsp_ctrl", + # + # misc/nxp_s32_emios + "nxp_s32_emios": "misc/nxp_s32_emios", + # + # misc/pio_rpi_pico + "raspberrypi_pico_pio": "misc/pio_rpi_pico", + # + # misc/renesas_ra_external_interrupt + "renesas_ra_external_interrupt": "misc/renesas_ra_external_interrupt", + # + # misc/renesas_rx_dtc + "renesas_rx_dtc": "misc/renesas_rx_dtc", + # + # misc/renesas_rx_external_interrupt + "renesas_rx_external_interrupt": "misc/renesas_rx_external_interrupt", + # + # misc/stm32n6_axisram + "st_stm32n6_ramcfg": "misc/stm32n6_axisram", + # + # misc/timeaware_gpio + "intel_timeaware_gpio": "misc/timeaware_gpio", + # + # mm + "intel_adsp_mtl_tlb": "mm", + "intel_adsp_tlb": "mm", + # + # modem + "nordic_nrf91_slm": "modem", + "quectel_bg95": "modem", + "quectel_bg96": "modem", + "quectel_bg9x": "modem", + "quectel_eg25_g": "modem", + "quectel_eg800q": "modem", + "simcom_a76xx": "modem", + "sqn_gm02s": "modem", + "st_st87mxx": "modem", + "telit_me310g1": "modem", + "telit_me910g1": "modem", + "u_blox_lara_r6": "modem", + "u_blox_sara_r4": "modem", + "u_blox_sara_r5": "modem", + "wnc_m14a2a": "modem", + # + # modem/hl78xx + "swir_hl7800": "modem/hl78xx", + "swir_hl7800_gnss": "modem/hl78xx", + "swir_hl7800_offload": "modem/hl78xx", + "swir_hl7812": "modem/hl78xx", + "swir_hl7812_gnss": "modem/hl78xx", + "swir_hl7812_offload": "modem/hl78xx", + # + # modem/simcom/sim7080 + "simcom_sim7080": "modem/simcom/sim7080", + # + # mspi + "ambiq_mspi_controller": "mspi", + "snps_designware_ssi": "mspi", + "st_stm32_ospi_controller": "mspi", + "st_stm32_qspi_controller": "mspi", + "st_stm32_xspi_controller": "mspi", + "zephyr_mspi_emul_controller": "mspi", + # + # opamp + "nxp_opamp": "opamp", + "nxp_opamp_fast": "opamp", + "st_stm32_opamp": "opamp", + # + # otp + "nxp_ocotp": "otp", + "sifli_sf32lb_efuse": "otp", + "st_stm32_bsec": "otp", + "zephyr_otp_emul": "otp", + # + # pcie/controller + "brcm_brcmstb_pcie": "pcie/controller", + # + # pcie/endpoint + "brcm_iproc_pcie_ep": "pcie/endpoint", + # + # pcie/host + "pci_host_ecam_generic": "pcie/host", + "pcie_controller": "pcie/host", + "ptm_root": "pcie/host", + # + # peci + "ite_it8xxx2_peci": "peci", + "microchip_xec_peci": "peci", + "nuvoton_npcx_peci": "peci", + # + # pinctrl + "alif_pinctrl": "pinctrl", + "brcm_bcm2711_pinctrl": "pinctrl", + "ene_kb106x_pinctrl": "pinctrl", + "ene_kb1200_pinctrl": "pinctrl", + "infineon_xmc4xxx_pinctrl": "pinctrl", + "ite_it8xxx2_pinctrl_func": "pinctrl", + "microchip_xec_pinctrl": "pinctrl", + "nuvoton_numaker_pinctrl": "pinctrl", + "nuvoton_numicro_pinctrl": "pinctrl", + "nxp_port_pinmux": "pinctrl", + "openisa_rv32m1_pinmux": "pinctrl", + "quicklogic_eos_s3_pinctrl": "pinctrl", + "realtek_rts5912_pinctrl": "pinctrl", + "sensry_sy1xx_pinctrl": "pinctrl", + "sifive_pinctrl": "pinctrl", + "sifli_sf32lb52x_pinmux": "pinctrl", + "silabs_dbus_pinctrl": "pinctrl", + "silabs_siwx91x_pinctrl": "pinctrl", + "snps_emsdp_pinctrl": "pinctrl", + "telink_b91_pinctrl": "pinctrl", + "ti_cc13xx_cc26xx_pinctrl": "pinctrl", + "ti_cc23x0_pinctrl": "pinctrl", + "ti_cc32xx_pinctrl": "pinctrl", + "ti_k3_pinctrl": "pinctrl", + "ti_mspm0_pinctrl": "pinctrl", + "wch_00x_afio": "pinctrl", + "wch_20x_30x_afio": "pinctrl", + "wch_afio": "pinctrl", + "xlnx_pinctrl_zynq": "pinctrl", + "xlnx_pinctrl_zynqmp": "pinctrl", + # + # pinctrl/renesas/rcar + "renesas_rcar_pfc": "pinctrl/renesas/rcar", + # + # pinctrl/renesas/rz + "renesas_rza2m_pinctrl": "pinctrl/renesas/rz", + "renesas_rzt2m_pinctrl": "pinctrl/renesas/rz", + # + # pm_cpu_ops + "arm_fvp_pwrc": "pm_cpu_ops", + "arm_psci_0_2": "pm_cpu_ops", + "arm_psci_1_1": "pm_cpu_ops", + # + # power_domain + "arm_scmi_power_domain": "power_domain", + "intel_adsp_power_domain": "power_domain", + "nordic_nrfs_gdpwr": "power_domain", + "nordic_nrfs_swext": "power_domain", + "nxp_scu_pd": "power_domain", + "power_domain_gpio": "power_domain", + "power_domain_gpio_monitor": "power_domain", + "power_domain_soc_state_change": "power_domain", + "silabs_siwx91x_power_domain": "power_domain", + "ti_sci_pm_domain": "power_domain", + # + # ps2 + "ite_it51xxx_ps2": "ps2", + "microchip_xec_ps2": "ps2", + "nuvoton_npcx_ps2_channel": "ps2", + "nuvoton_npcx_ps2_ctrl": "ps2", + # + # psi5 + "nxp_s32_psi5": "psi5", + # + # ptp_clock + "nxp_enet_ptp_clock": "ptp_clock", + "nxp_netc_ptp_clock": "ptp_clock", + # + # pwm + "adi_max32_pwm": "pwm", + "ambiq_ctimer_pwm": "pwm", + "ambiq_timer_pwm": "pwm", + "atmel_sam0_tc_pwm": "pwm", + "atmel_sam0_tcc_pwm": "pwm", + "atmel_sam_pwm": "pwm", + "bflb_pwm_1": "pwm", + "bflb_pwm_2": "pwm", + "ene_kb106x_pwm": "pwm", + "ene_kb1200_pwm": "pwm", + "espressif_esp32_ledc": "pwm", + "espressif_esp32_mcpwm": "pwm", + "fsl_imx27_pwm": "pwm", + "gd_gd32_pwm": "pwm", + "infineon_tcpwm_pwm": "pwm", + "infineon_xmc4xxx_ccu4_pwm": "pwm", + "infineon_xmc4xxx_ccu8_pwm": "pwm", + "intel_blinky_pwm": "pwm", + "ite_it51xxx_pwm": "pwm", + "ite_it8801_pwm": "pwm", + "ite_it8xxx2_pwm": "pwm", + "litex_pwm": "pwm", + "maxim_max31790_pwm": "pwm", + "microchip_tc_g1_pwm": "pwm", + "microchip_tcc_g1_pwm": "pwm", + "microchip_xec_pwm": "pwm", + "microchip_xec_pwmbbled": "pwm", + "neorv32_pwm": "pwm", + "nordic_nrf_pwm": "pwm", + "nordic_nrf_sw_pwm": "pwm", + "nuvoton_npcx_pwm": "pwm", + "nuvoton_numaker_pwm": "pwm", + "nxp_ctimer_pwm": "pwm", + "nxp_flexio_pwm": "pwm", + "nxp_ftm_pwm": "pwm", + "nxp_imx_pwm": "pwm", + "nxp_kinetis_pwt": "pwm", + "nxp_kinetis_tpm": "pwm", + "nxp_pca9685_pwm": "pwm", + "nxp_qtmr_pwm": "pwm", + "nxp_s32_emios_pwm": "pwm", + "nxp_sctimer_pwm": "pwm", + "openisa_rv32m1_tpm": "pwm", + "raspberrypi_pico_pwm": "pwm", + "realtek_rts5912_pwm": "pwm", + "renesas_pwm_rcar": "pwm", + "renesas_ra_pwm": "pwm", + "renesas_rx_mtu_pwm": "pwm", + "renesas_rz_gpt_pwm": "pwm", + "renesas_rz_mtu_pwm": "pwm", + "renesas_rza2m_gpt_pwm": "pwm", + "sifive_pwm0": "pwm", + "sifli_sf32lb_atim_pwm": "pwm", + "sifli_sf32lb_gpt_pwm": "pwm", + "silabs_gecko_pwm": "pwm", + "silabs_letimer_pwm": "pwm", + "silabs_siwx91x_pwm": "pwm", + "silabs_timer_pwm": "pwm", + "st_stm32_pwm": "pwm", + "telink_b91_pwm": "pwm", + "ti_cc13xx_cc26xx_timer_pwm": "pwm", + "ti_cc23x0_lgpt_pwm": "pwm", + "ti_mspm0_timer_pwm": "pwm", + "vnd_pwm": "pwm", + "wch_gptm_pwm": "pwm", + "xlnx_xps_timer_1_00_a_pwm": "pwm", + "zephyr_fake_pwm": "pwm", + # + # regulator + "adi_adp5360_regulator": "regulator", + "cirrus_cp9314": "regulator", + "maxim_max20335_regulator": "regulator", + "mps_mpm54304": "regulator", + "nordic_npm1100": "regulator", + "nordic_npm1300_regulator": "regulator", + "nordic_npm1304_regulator": "regulator", + "nordic_npm2100_regulator": "regulator", + "nordic_npm6001_regulator": "regulator", + "nxp_pca9420": "regulator", + "nxp_pca9422_regulator": "regulator", + "nxp_pf1550_regulator": "regulator", + "nxp_vref": "regulator", + "nxp_vrefv1": "regulator", + "raspberrypi_core_supply_regulator": "regulator", + "regulator_fixed": "regulator", + "regulator_gpio": "regulator", + "renesas_smartbond_regulator": "regulator", + "st_stm32_vrefbuf": "regulator", + "ti_tps55287": "regulator", + "zephyr_fake_regulator": "regulator", + # + # reset + "aspeed_ast10x0_reset": "reset", + "focaltech_ft9001_cpm_rctl": "reset", + "gd_gd32_rctl": "reset", + "intel_socfpga_reset": "reset", + "microchip_mpfs_reset": "reset", + "microchip_rstc_g1_reset": "reset", + "nuvoton_npcx_rst": "reset", + "nuvoton_numaker_rst": "reset", + "nxp_lpc_syscon_reset": "reset", + "nxp_mrcc_reset": "reset", + "nxp_rstctl": "reset", + "raspberrypi_pico_reset": "reset", + "realtek_rts5817_reset": "reset", + "reset_mmio": "reset", + "sifli_sf32lb_rcc_rctl": "reset", + "st_stm32_rcc_rctl": "reset", + # + # retained_mem + "nordic_nrf_gpregret": "retained_mem", + "silabs_buram": "retained_mem", + "zephyr_retained_ram": "retained_mem", + "zephyr_retained_reg": "retained_mem", + # + # rtc + "adi_max31331": "rtc", + "ambiq_am1805": "rtc", + "ambiq_rtc": "rtc", + "atmel_sam_rtc": "rtc", + "epson_rx8130ce_rtc": "rtc", + "infineon_rtc": "rtc", + "infineon_xmc4xxx_rtc": "rtc", + "maxim_ds1302": "rtc", + "maxim_ds1307": "rtc", + "maxim_ds1337": "rtc", + "maxim_ds3231_rtc": "rtc", + "microchip_rtc_g1": "rtc", + "microchip_rtc_g2": "rtc", + "microcrystal_rv3028": "rtc", + "microcrystal_rv3032": "rtc", + "microcrystal_rv8803": "rtc", + "microcrystal_rv_8263_c8": "rtc", + "motorola_mc146818": "rtc", + "nuvoton_numaker_rtc": "rtc", + "nxp_irtc": "rtc", + "nxp_pcf2123": "rtc", + "nxp_pcf85063a": "rtc", + "nxp_pcf8523": "rtc", + "nxp_pcf8563": "rtc", + "raspberrypi_pico_rtc": "rtc", + "realtek_rts5912_rtc": "rtc", + "renesas_ra_rtc": "rtc", + "renesas_smartbond_rtc": "rtc", + "sifli_sf32lb_rtc": "rtc", + "silabs_siwx91x_rtc": "rtc", + "st_stm32_rtc": "rtc", + "ti_bq32002": "rtc", + "ti_mspm0_rtc": "rtc", + "zephyr_fake_rtc": "rtc", + "zephyr_rtc_counter": "rtc", + "zephyr_rtc_emul": "rtc", + # + # sdhc + "adi_max32_sdhc": "sdhc", + "ambiq_sdio": "sdhc", + "atmel_sam_hsmci": "sdhc", + "cdns_sdhc": "sdhc", + "espressif_esp32_sdhc_slot": "sdhc", + "infineon_sdhc_sdio": "sdhc", + "intel_emmc_host": "sdhc", + "microchip_sama7g5_sdmmc": "sdhc", + "nxp_imx_usdhc": "sdhc", + "nxp_lpc_sdif": "sdhc", + "renesas_ra_sdhc": "sdhc", + "renesas_rcar_mmc": "sdhc", + "st_stm32_sdio": "sdhc", + "xlnx_versal_8_9a": "sdhc", + "zephyr_sdhc_spi_slot": "sdhc", + # + # sensor/a01nyub + "dfrobot_a01nyub": "sensor/a01nyub", + # + # sensor/adi/ad2s1210 + "adi_ad2s1210": "sensor/adi/ad2s1210", + # + # sensor/adi/ade7978 + "adi_ade7978": "sensor/adi/ade7978", + # + # sensor/adi/adltc2990 + "adi_adltc2990": "sensor/adi/adltc2990", + # + # sensor/adi/adt7310 + "adi_adt7310": "sensor/adi/adt7310", + # + # sensor/adi/adt7420 + "adi_adt7420": "sensor/adi/adt7420", + # + # sensor/adi/adxl345 + "adi_adxl345": "sensor/adi/adxl345", + # + # sensor/adi/adxl362 + "adi_adxl362": "sensor/adi/adxl362", + # + # sensor/adi/adxl367 + "adi_adxl366": "sensor/adi/adxl367", + "adi_adxl367": "sensor/adi/adxl367", + # + # sensor/adi/adxl372 + "adi_adxl372": "sensor/adi/adxl372", + # + # sensor/adi/max30210 + "adi_max30210": "sensor/adi/max30210", + # + # sensor/adi/max32664c + "maxim_max32664c": "sensor/adi/max32664c", + # + # sensor/als31300 + "allegro_als31300": "sensor/als31300", + # + # sensor/amd_sb_tsi + "amd_sb_tsi": "sensor/amd_sb_tsi", + # + # sensor/amg88xx + "panasonic_amg88xx": "sensor/amg88xx", + # + # sensor/ams/ams_as5048 + "ams_as5048": "sensor/ams/ams_as5048", + # + # sensor/ams/ams_as5600 + "ams_as5600": "sensor/ams/ams_as5600", + # + # sensor/ams/ams_iAQcore + "ams_iaqcore": "sensor/ams/ams_iAQcore", + # + # sensor/ams/ccs811 + "ams_ccs811": "sensor/ams/ccs811", + # + # sensor/ams/ens210 + "ams_ens210": "sensor/ams/ens210", + # + # sensor/ams/tcs3400 + "ams_tcs3400": "sensor/ams/tcs3400", + # + # sensor/ams/tmd2620 + "ams_tmd2620": "sensor/ams/tmd2620", + # + # sensor/ams/tsl2540 + "ams_tsl2540": "sensor/ams/tsl2540", + # + # sensor/ams/tsl2561 + "ams_tsl2561": "sensor/ams/tsl2561", + # + # sensor/ams/tsl2591 + "ams_tsl2591": "sensor/ams/tsl2591", + # + # sensor/aosong/ags10 + "aosong_ags10": "sensor/aosong/ags10", + # + # sensor/aosong/dht + "aosong_dht": "sensor/aosong/dht", + # + # sensor/aosong/dht20 + "aosong_aht20": "sensor/aosong/dht20", + "aosong_am2301b": "sensor/aosong/dht20", + "aosong_dht20": "sensor/aosong/dht20", + # + # sensor/apds9253 + "avago_apds9253": "sensor/apds9253", + # + # sensor/apds9306 + "avago_apds9306": "sensor/apds9306", + # + # sensor/apds9960 + "avago_apds9960": "sensor/apds9960", + # + # sensor/asahi_kasei/ak8975 + "asahi_kasei_ak8975": "sensor/asahi_kasei/ak8975", + # + # sensor/asahi_kasei/akm09918c + "asahi_kasei_akm09918c": "sensor/asahi_kasei/akm09918c", + # + # sensor/bosch/bma280 + "bosch_bma280": "sensor/bosch/bma280", + # + # sensor/bosch/bma4xx + "bosch_bma4xx": "sensor/bosch/bma4xx", + # + # sensor/bosch/bmc150_magn + "bosch_bmc150_magn": "sensor/bosch/bmc150_magn", + # + # sensor/bosch/bme280 + "bosch_bme280": "sensor/bosch/bme280", + # + # sensor/bosch/bme680 + "bosch_bme680": "sensor/bosch/bme680", + # + # sensor/bosch/bmg160 + "bosch_bmg160": "sensor/bosch/bmg160", + # + # sensor/bosch/bmi08x + "bosch_bmi08x_accel": "sensor/bosch/bmi08x", + "bosch_bmi08x_gyro": "sensor/bosch/bmi08x", + # + # sensor/bosch/bmi160 + "bosch_bmi160": "sensor/bosch/bmi160", + # + # sensor/bosch/bmi270 + "bosch_bmi270": "sensor/bosch/bmi270", + # + # sensor/bosch/bmi323 + "bosch_bmi323": "sensor/bosch/bmi323", + # + # sensor/bosch/bmm150 + "bosch_bmm150": "sensor/bosch/bmm150", + # + # sensor/bosch/bmm350 + "bosch_bmm350": "sensor/bosch/bmm350", + # + # sensor/bosch/bmp180 + "bosch_bmp180": "sensor/bosch/bmp180", + # + # sensor/bosch/bmp388 + "bosch_bmp388": "sensor/bosch/bmp388", + "bosch_bmp390": "sensor/bosch/bmp388", + # + # sensor/bosch/bmp581 + "bosch_bmp581": "sensor/bosch/bmp581", + # + # sensor/broadcom/afbr_s50 + "brcm_afbr_s50": "sensor/broadcom/afbr_s50", + # + # sensor/current_amp + "current_sense_amplifier": "sensor/current_amp", + # + # sensor/ene_tach_kb1200 + "ene_kb1200_tach": "sensor/ene_tach_kb1200", + # + # sensor/ens160 + "sciosense_ens160": "sensor/ens160", + # + # sensor/espressif/esp32_temp + "espressif_esp32_temp": "sensor/espressif/esp32_temp", + # + # sensor/espressif/pcnt_esp32 + "espressif_esp32_pcnt": "sensor/espressif/pcnt_esp32", + # + # sensor/everlight/als_pt19 + "everlight_als_pt19": "sensor/everlight/als_pt19", + # + # sensor/explorir_m + "gss_explorir_m": "sensor/explorir_m", + # + # sensor/f75303 + "fintek_f75303": "sensor/f75303", + # + # sensor/fcx_mldx5 + "ap_fcx_mldx5": "sensor/fcx_mldx5", + # + # sensor/grow_r502a + "hzgrow_r502a": "sensor/grow_r502a", + "hzgrow_r502a_led": "sensor/grow_r502a", + # + # sensor/hc_sr04 + "hc_sr04": "sensor/hc_sr04", + # + # sensor/honeywell/hmc5883l + "honeywell_hmc5883l": "sensor/honeywell/hmc5883l", + # + # sensor/honeywell/mpr + "honeywell_mpr": "sensor/honeywell/mpr", + # + # sensor/honeywell/sm351lt + "honeywell_sm351lt": "sensor/honeywell/sm351lt", + # + # sensor/hp206c + "hoperf_hp206c": "sensor/hp206c", + # + # sensor/infineon/dps310 + "infineon_dps310": "sensor/infineon/dps310", + # + # sensor/infineon/tle9104 + "infineon_tle9104_diagnostics": "sensor/infineon/tle9104", + # + # sensor/infineon/xmc4xxx_temp + "infineon_xmc4xxx_temp": "sensor/infineon/xmc4xxx_temp", + # + # sensor/ist8310 + "isentek_ist8310": "sensor/ist8310", + # + # sensor/ite/ite_tach_it51xxx + "ite_it51xxx_tach": "sensor/ite/ite_tach_it51xxx", + # + # sensor/ite/ite_tach_it8xxx2 + "ite_it8xxx2_tach": "sensor/ite/ite_tach_it8xxx2", + # + # sensor/ite/ite_vcmp_it8xxx2 + "ite_it8xxx2_vcmp": "sensor/ite/ite_vcmp_it8xxx2", + # + # sensor/jedec/jc42 + "jedec_jc_42_4_temp": "sensor/jedec/jc42", + # + # sensor/liteon/ltrf216a + "liteon_ltrf216a": "sensor/liteon/ltrf216a", + # + # sensor/lm35 + "lm35": "sensor/lm35", + # + # sensor/lm75 + "lm75": "sensor/lm75", + # + # sensor/lm77 + "lm77": "sensor/lm77", + # + # sensor/maxim/ds18b20 + "maxim_ds18b20": "sensor/maxim/ds18b20", + "maxim_ds18s20": "sensor/maxim/ds18b20", + # + # sensor/maxim/ds3231 + "maxim_ds3231_sensor": "sensor/maxim/ds3231", + # + # sensor/maxim/max17055 + "maxim_max17055": "sensor/maxim/max17055", + # + # sensor/maxim/max17262 + "maxim_max17262": "sensor/maxim/max17262", + # + # sensor/maxim/max30101 + "maxim_max30101": "sensor/maxim/max30101", + # + # sensor/maxim/max31790 + "maxim_max31790_fan_fault": "sensor/maxim/max31790", + "maxim_max31790_fan_speed": "sensor/maxim/max31790", + # + # sensor/maxim/max31855 + "maxim_max31855": "sensor/maxim/max31855", + # + # sensor/maxim/max31865 + "maxim_max31865": "sensor/maxim/max31865", + # + # sensor/maxim/max31875 + "maxim_max31875": "sensor/maxim/max31875", + # + # sensor/maxim/max44009 + "maxim_max44009": "sensor/maxim/max44009", + # + # sensor/maxim/max6675 + "maxim_max6675": "sensor/maxim/max6675", + # + # sensor/mb7040 + "maxbotix_mb7040": "sensor/mb7040", + # + # sensor/meas/ms5607 + "meas_ms5607": "sensor/meas/ms5607", + # + # sensor/meas/ms5837 + "meas_ms5837_02ba": "sensor/meas/ms5837", + "meas_ms5837_30ba": "sensor/meas/ms5837", + # + # sensor/melexis/mlx90394 + "melexis_mlx90394": "sensor/melexis/mlx90394", + # + # sensor/memsic/mc3419 + "memsic_mc3419": "sensor/memsic/mc3419", + # + # sensor/memsic/mmc56x3 + "memsic_mmc56x3": "sensor/memsic/mmc56x3", + # + # sensor/mhz19b + "winsen_mhz19b": "sensor/mhz19b", + # + # sensor/microchip/mchp_tach_xec + "microchip_xec_tach": "sensor/microchip/mchp_tach_xec", + # + # sensor/microchip/mcp9600 + "microchip_mcp9600": "sensor/microchip/mcp9600", + # + # sensor/microchip/mcp970x + "microchip_mcp970x": "sensor/microchip/mcp970x", + # + # sensor/microchip/mtch9010 + "microchip_mtch9010": "sensor/microchip/mtch9010", + # + # sensor/microchip/tcn75a + "microchip_tcn75a": "sensor/microchip/tcn75a", + # + # sensor/nct75 + "onnn_nct75": "sensor/nct75", + # + # sensor/nordic/npm13xx_charger + "nordic_npm1300_charger": "sensor/nordic/npm13xx_charger", + "nordic_npm1304_charger": "sensor/nordic/npm13xx_charger", + # + # sensor/nordic/npm2100_vbat + "nordic_npm2100_vbat": "sensor/nordic/npm2100_vbat", + # + # sensor/nordic/qdec_nrfx + "nordic_nrf_qdec": "sensor/nordic/qdec_nrfx", + # + # sensor/nordic/temp + "nordic_nrf_temp": "sensor/nordic/temp", + "nordic_nrf_temp_nrfs": "sensor/nordic/temp", + # + # sensor/ntc_thermistor + "epcos_b57861s0103a039": "sensor/ntc_thermistor", + "murata_ncp15wb473": "sensor/ntc_thermistor", + "murata_ncp15xh103": "sensor/ntc_thermistor", + "ntc_thermistor_generic": "sensor/ntc_thermistor", + "tdk_ntcg163jf103ft1": "sensor/ntc_thermistor", + # + # sensor/nuvoton/nuvoton_adc_cmp_npcx + "nuvoton_adc_cmp": "sensor/nuvoton/nuvoton_adc_cmp_npcx", + # + # sensor/nuvoton/nuvoton_adc_v2t_npcx + "nuvoton_npcx_adc_v2t": "sensor/nuvoton/nuvoton_adc_v2t_npcx", + # + # sensor/nuvoton/nuvoton_tach_npcx + "nuvoton_npcx_tach": "sensor/nuvoton/nuvoton_tach_npcx", + # + # sensor/nxp/fxas21002 + "nxp_fxas21002": "sensor/nxp/fxas21002", + # + # sensor/nxp/fxls8974 + "nxp_fxls8974": "sensor/nxp/fxls8974", + # + # sensor/nxp/fxos8700 + "nxp_fxos8700": "sensor/nxp/fxos8700", + # + # sensor/nxp/mcux_acmp + "nxp_kinetis_acmp": "sensor/nxp/mcux_acmp", + # + # sensor/nxp/mcux_lpcmp + "nxp_lpcmp": "sensor/nxp/mcux_lpcmp", + # + # sensor/nxp/nxp_kinetis_temp + "nxp_kinetis_temperature": "sensor/nxp/nxp_kinetis_temp", + # + # sensor/nxp/nxp_lpadc_temp40 + "nxp_lpadc_temp40": "sensor/nxp/nxp_lpadc_temp40", + # + # sensor/nxp/nxp_pmc_tmpsns + "nxp_pmc_tmpsns": "sensor/nxp/nxp_pmc_tmpsns", + # + # sensor/nxp/nxp_tempmon + "nxp_tempmon": "sensor/nxp/nxp_tempmon", + # + # sensor/nxp/nxp_tempsense + "nxp_tempsense": "sensor/nxp/nxp_tempsense", + # + # sensor/nxp/nxp_tmpsns + "nxp_tmpsns": "sensor/nxp/nxp_tmpsns", + # + # sensor/nxp/p3t1755 + "nxp_p3t1755": "sensor/nxp/p3t1755", + # + # sensor/nxp/qdec_mcux + "nxp_mcux_qdec": "sensor/nxp/qdec_mcux", + # + # sensor/nxp/qdec_nxp_s32 + "nxp_qdec_s32": "sensor/nxp/qdec_nxp_s32", + # + # sensor/nxp/qdec_tpm + "nxp_tpm_qdec": "sensor/nxp/qdec_tpm", + # + # sensor/omron/2smpb_02e + "omron_2smpb_02e": "sensor/omron/2smpb_02e", + # + # sensor/omron/d6f + "omron_d6f_p0001": "sensor/omron/d6f", + "omron_d6f_p0010": "sensor/omron/d6f", + # + # sensor/pixart/paa3905 + "pixart_paa3905": "sensor/pixart/paa3905", + # + # sensor/pixart/paj7620 + "pixart_paj7620": "sensor/pixart/paj7620", + # + # sensor/pixart/pat9136 + "pixart_pat9136": "sensor/pixart/pat9136", + # + # sensor/pms7003 + "plantower_pms7003": "sensor/pms7003", + # + # sensor/pni/rm3100 + "pni_rm3100": "sensor/pni/rm3100", + # + # sensor/pzem004t + "peacefair_pzem004t": "sensor/pzem004t", + # + # sensor/qdec_sam + "atmel_sam_tc_qdec": "sensor/qdec_sam", + # + # sensor/realtek/rts5912 + "realtek_rts5912_tach": "sensor/realtek/rts5912", + # + # sensor/renesas/hs300x + "renesas_hs300x": "sensor/renesas/hs300x", + # + # sensor/renesas/hs400x + "renesas_hs400x": "sensor/renesas/hs400x", + # + # sensor/renesas/isl29035 + "isil_isl29035": "sensor/renesas/isl29035", + # + # sensor/rohm/bd8lb600fs + "rohm_bd8lb600fs_diagnostics": "sensor/rohm/bd8lb600fs", + # + # sensor/rohm/bh1730 + "rohm_bh1730": "sensor/rohm/bh1730", + # + # sensor/rohm/bh1750 + "rohm_bh1750": "sensor/rohm/bh1750", + # + # sensor/rohm/bh1790 + "rohm_bh1790": "sensor/rohm/bh1790", + # + # sensor/rpi_pico_temp + "raspberrypi_pico_temp": "sensor/rpi_pico_temp", + # + # sensor/rv3032_temp + "microcrystal_rv3032_temp": "sensor/rv3032_temp", + # + # sensor/s11059 + "hamamatsu_s11059": "sensor/s11059", + # + # sensor/seeed/grove + "seeed_grove_light": "sensor/seeed/grove", + "seeed_grove_temperature": "sensor/seeed/grove", + # + # sensor/seeed/hm330x + "seeed_hm330x": "sensor/seeed/hm330x", + # + # sensor/sensirion/scd4x + "sensirion_scd40": "sensor/sensirion/scd4x", + "sensirion_scd41": "sensor/sensirion/scd4x", + # + # sensor/sensirion/sgp40 + "sensirion_sgp40": "sensor/sensirion/sgp40", + # + # sensor/sensirion/sht3xd + "sensirion_sht3xd": "sensor/sensirion/sht3xd", + # + # sensor/sensirion/sht4x + "sensirion_sht4x": "sensor/sensirion/sht4x", + # + # sensor/sensirion/shtcx + "sensirion_shtcx": "sensor/sensirion/shtcx", + # + # sensor/sensirion/sts4x + "sensirion_sts4x": "sensor/sensirion/sts4x", + # + # sensor/sifli/sf32lb_tsen + "sifli_sf32lb_tsen": "sensor/sifli/sf32lb_tsen", + # + # sensor/silabs/si7006 + "sensirion_sht21": "sensor/silabs/si7006", + "silabs_si7006": "sensor/silabs/si7006", + # + # sensor/silabs/si7055 + "silabs_si7055": "sensor/silabs/si7055", + # + # sensor/silabs/si7060 + "silabs_si7060": "sensor/silabs/si7060", + # + # sensor/silabs/si7210 + "silabs_si7210": "sensor/silabs/si7210", + # + # sensor/st/hts221 + "st_hts221": "sensor/st/hts221", + # + # sensor/st/i3g4250d + "st_i3g4250d": "sensor/st/i3g4250d", + # + # sensor/st/iis2dh + "st_iis2dh": "sensor/st/iis2dh", + # + # sensor/st/iis2dlpc + "st_iis2dlpc": "sensor/st/iis2dlpc", + # + # sensor/st/iis2iclx + "st_iis2iclx": "sensor/st/iis2iclx", + # + # sensor/st/iis2mdc + "st_iis2mdc": "sensor/st/iis2mdc", + # + # sensor/st/iis328dq + "st_iis328dq": "sensor/st/iis328dq", + # + # sensor/st/iis3dhhc + "st_iis3dhhc": "sensor/st/iis3dhhc", + # + # sensor/st/iis3dwb + "st_iis3dwb": "sensor/st/iis3dwb", + # + # sensor/st/ism330dhcx + "st_ism330dhcx": "sensor/st/ism330dhcx", + # + # sensor/st/lis2de12 + "st_lis2de12": "sensor/st/lis2de12", + # + # sensor/st/lis2dh + "st_lis2dh": "sensor/st/lis2dh", + # + # sensor/st/lis2ds12 + "st_lis2ds12": "sensor/st/lis2ds12", + # + # sensor/st/lis2du12 + "st_lis2du12": "sensor/st/lis2du12", + # + # sensor/st/lis2dux12 + "st_lis2dux12": "sensor/st/lis2dux12", + "st_lis2duxs12": "sensor/st/lis2dux12", + # + # sensor/st/lis2dw12 + "st_lis2dw12": "sensor/st/lis2dw12", + # + # sensor/st/lis2mdl + "st_lis2mdl": "sensor/st/lis2mdl", + # + # sensor/st/lis3mdl + "st_lis3mdl_magn": "sensor/st/lis3mdl", + # + # sensor/st/lps22hb + "st_lps22hb_press": "sensor/st/lps22hb", + # + # sensor/st/lps22hh + "st_lps22hh": "sensor/st/lps22hh", + # + # sensor/st/lps25hb + "st_lps25hb_press": "sensor/st/lps25hb", + # + # sensor/st/lps2xdf + "st_ilps22qs": "sensor/st/lps2xdf", + "st_lps22df": "sensor/st/lps2xdf", + "st_lps28dfw": "sensor/st/lps2xdf", + # + # sensor/st/lsm303dlhc_magn + "st_lsm303dlhc_magn": "sensor/st/lsm303dlhc_magn", + # + # sensor/st/lsm6ds0 + "st_lsm6ds0": "sensor/st/lsm6ds0", + # + # sensor/st/lsm6dsl + "st_lsm6dsl": "sensor/st/lsm6dsl", + # + # sensor/st/lsm6dso + "st_lsm6dso": "sensor/st/lsm6dso", + "st_lsm6dso32": "sensor/st/lsm6dso", + # + # sensor/st/lsm6dso16is + "st_lsm6dso16is": "sensor/st/lsm6dso16is", + # + # sensor/st/lsm6dsv16x + "DT_DRV_COMPAT_LSM6DSV16X": "sensor/st/lsm6dsv16x", + "DT_DRV_COMPAT_LSM6DSV32X": "sensor/st/lsm6dsv16x", + "st_lsm6dsv16x": "sensor/st/lsm6dsv16x", + "st_lsm6dsv32x": "sensor/st/lsm6dsv16x", + # + # sensor/st/lsm6dsvxxx + "st_ism6hg256x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsv320x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsv80x": "sensor/st/lsm6dsvxxx", + "st_lsm6dsvxxx": "sensor/st/lsm6dsvxxx", + # + # sensor/st/lsm9ds0_gyro + "st_lsm9ds0_gyro": "sensor/st/lsm9ds0_gyro", + # + # sensor/st/lsm9ds0_mfd + "st_lsm9ds0_mfd": "sensor/st/lsm9ds0_mfd", + # + # sensor/st/lsm9ds1 + "st_lsm9ds1": "sensor/st/lsm9ds1", + # + # sensor/st/lsm9ds1_mag + "st_lsm9ds1_mag": "sensor/st/lsm9ds1_mag", + # + # sensor/st/qdec_stm32 + "st_stm32_qdec": "sensor/st/qdec_stm32", + # + # sensor/st/stm32_digi_temp + "st_stm32_digi_temp": "sensor/st/stm32_digi_temp", + # + # sensor/st/stm32_temp + "st_stm32_temp": "sensor/st/stm32_temp", + "st_stm32_temp_cal": "sensor/st/stm32_temp", + "st_stm32c0_temp_cal": "sensor/st/stm32_temp", + # + # sensor/st/stm32_vbat + "st_stm32_vbat": "sensor/st/stm32_vbat", + # + # sensor/st/stm32_vref + "st_stm32_vref": "sensor/st/stm32_vref", + # + # sensor/st/stts22h + "st_stts22h": "sensor/st/stts22h", + # + # sensor/st/stts751 + "st_stts751": "sensor/st/stts751", + # + # sensor/st/vl53l0x + "st_vl53l0x": "sensor/st/vl53l0x", + # + # sensor/st/vl53l1x + "st_vl53l1x": "sensor/st/vl53l1x", + # + # sensor/sx9500 + "semtech_sx9500": "sensor/sx9500", + # + # sensor/tach_gpio + "zephyr_tach_gpio": "sensor/tach_gpio", + # + # sensor/tdk/icm40627 + "invensense_icm40627": "sensor/tdk/icm40627", + # + # sensor/tdk/icm42605 + "invensense_icm42605": "sensor/tdk/icm42605", + # + # sensor/tdk/icm4268x + "invensense_icm42688": "sensor/tdk/icm4268x", + "invensense_icm4268x": "sensor/tdk/icm4268x", + # + # sensor/tdk/icm42x70 + "invensense_icm42370p": "sensor/tdk/icm42x70", + "invensense_icm42670p": "sensor/tdk/icm42x70", + "invensense_icm42670s": "sensor/tdk/icm42x70", + # + # sensor/tdk/icm45686 + "invensense_icm45605": "sensor/tdk/icm45686", + "invensense_icm45605s": "sensor/tdk/icm45686", + "invensense_icm45686": "sensor/tdk/icm45686", + "invensense_icm45686s": "sensor/tdk/icm45686", + "invensense_icm45688p": "sensor/tdk/icm45686", + # + # sensor/tdk/icp101xx + "invensense_icp101xx": "sensor/tdk/icp101xx", + # + # sensor/tdk/icp201xx + "invensense_icp201xx": "sensor/tdk/icp201xx", + # + # sensor/tdk/mpu6050 + "invensense_mpu6050": "sensor/tdk/mpu6050", + # + # sensor/tdk/mpu9250 + "invensense_mpu9250": "sensor/tdk/mpu9250", + # + # sensor/th02 + "hoperf_th02": "sensor/th02", + # + # sensor/ti/bq274xx + "ti_bq274xx": "sensor/ti/bq274xx", + # + # sensor/ti/fdc2x1x + "ti_fdc2x1x": "sensor/ti/fdc2x1x", + # + # sensor/ti/ina219 + "ti_ina219": "sensor/ti/ina219", + # + # sensor/ti/ina2xx + "ti_ina226": "sensor/ti/ina2xx", + "ti_ina228": "sensor/ti/ina2xx", + "ti_ina230": "sensor/ti/ina2xx", + "ti_ina232": "sensor/ti/ina2xx", + "ti_ina236": "sensor/ti/ina2xx", + "ti_ina237": "sensor/ti/ina2xx", + # + # sensor/ti/ina3221 + "ti_ina3221": "sensor/ti/ina3221", + # + # sensor/ti/ina7xx + "ti_ina7xx": "sensor/ti/ina7xx", + # + # sensor/ti/lm95234 + "national_lm95234": "sensor/ti/lm95234", + # + # sensor/ti/opt300x + "ti_opt3001": "sensor/ti/opt300x", + "ti_opt3004": "sensor/ti/opt300x", + "ti_opt300x": "sensor/ti/opt300x", + # + # sensor/ti/ti_hdc + "ti_hdc": "sensor/ti/ti_hdc", + # + # sensor/ti/ti_hdc302x + "ti_hdc302x": "sensor/ti/ti_hdc302x", + # + # sensor/ti/tmag5170 + "ti_tmag5170": "sensor/ti/tmag5170", + # + # sensor/ti/tmp007 + "ti_tmp007": "sensor/ti/tmp007", + # + # sensor/ti/tmp1075 + "ti_tmp1075": "sensor/ti/tmp1075", + # + # sensor/ti/tmp108 + "ams_as6212": "sensor/ti/tmp108", + "ams_as6221": "sensor/ti/tmp108", + "ti_tmp108": "sensor/ti/tmp108", + # + # sensor/ti/tmp112 + "ti_tmp112": "sensor/ti/tmp112", + # + # sensor/ti/tmp114 + "ti_tmp114": "sensor/ti/tmp114", + # + # sensor/ti/tmp11x + "ti_tmp11x": "sensor/ti/tmp11x", + # + # sensor/ti/tmp435 + "ti_tmp435": "sensor/ti/tmp435", + # + # sensor/tsic_xx6 + "ist_tsic_xx6": "sensor/tsic_xx6", + # + # sensor/veaa_x_3 + "festo_veaa_x_3": "sensor/veaa_x_3", + # + # sensor/vishay/vcnl36825t + "vishay_vcnl36825t": "sensor/vishay/vcnl36825t", + # + # sensor/vishay/vcnl4040 + "vishay_vcnl4040": "sensor/vishay/vcnl4040", + # + # sensor/vishay/veml6031 + "vishay_veml6031": "sensor/vishay/veml6031", + # + # sensor/vishay/veml6046 + "vishay_veml6046": "sensor/vishay/veml6046", + # + # sensor/vishay/veml7700 + "vishay_veml7700": "sensor/vishay/veml7700", + # + # sensor/voltage_divider + "voltage_divider": "sensor/voltage_divider", + # + # sensor/wsen/wsen_hids_2525020210002 + "we_wsen_hids_2525020210002": "sensor/wsen/wsen_hids_2525020210002", + # + # sensor/wsen/wsen_isds_2536030320001 + "we_wsen_isds_2536030320001": "sensor/wsen/wsen_isds_2536030320001", + # + # sensor/wsen/wsen_itds_2533020201601 + "we_wsen_itds_2533020201601": "sensor/wsen/wsen_itds_2533020201601", + # + # sensor/wsen/wsen_pads_2511020213301 + "we_wsen_pads_2511020213301": "sensor/wsen/wsen_pads_2511020213301", + # + # sensor/wsen/wsen_pdms_25131308XXX05 + "we_wsen_pdms_25131308xxx05": "sensor/wsen/wsen_pdms_25131308XXX05", + # + # sensor/wsen/wsen_pdus_25131308XXXXX + "we_wsen_pdus_25131308xxxxx": "sensor/wsen/wsen_pdus_25131308XXXXX", + # + # sensor/wsen/wsen_tids_2521020222501 + "we_wsen_tids_2521020222501": "sensor/wsen/wsen_tids_2521020222501", + # + # sensor/xbr818 + "phosense_xbr818": "sensor/xbr818", + # + # sent + "nxp_s32_sent": "sent", + # + # serial + "SBSA_COMPAT": "serial", + "adi_max32_uart": "serial", + "aesc_uart": "serial", + "altr_jtag_uart": "serial", + "altr_uart": "serial", + "ambiq_uart": "serial", + "arm_cmsdk_uart": "serial", + "arm_pl011": "serial", + "atmel_sam0_uart": "serial", + "atmel_sam_uart": "serial", + "atmel_sam_usart": "serial", + "bflb_uart": "serial", + "brcm_bcm2711_aux_uart": "serial", + "cdns_uart": "serial", + "cypress_psoc6_uart": "serial", + "efinix_sapphire_uart0": "serial", + "ene_kb106x_uart": "serial", + "ene_kb1200_uart": "serial", + "espressif_esp32_lpuart": "serial", + "espressif_esp32_uart": "serial", + "espressif_esp32_usb_serial": "serial", + "focaltech_ft9001_usart": "serial", + "gaisler_apbuart": "serial", + "gd_gd32_usart": "serial", + "infineon_uart": "serial", + "infineon_xmc4xxx_uart": "serial", + "intel_lw_uart": "serial", + "intel_sedi_uart": "serial", + "ite_it51xxx_uart": "serial", + "ite_it8xxx2_uart": "serial", + "litex_uart": "serial", + "lowrisc_opentitan_uart": "serial", + "microchip_coreuart": "serial", + "microchip_sercom_g1_uart": "serial", + "microchip_xec_uart": "serial", + "neorv32_uart": "serial", + "nordic_nrf_uart": "serial", + "ns16550": "serial", + "nuvoton_npcx_uart": "serial", + "nuvoton_numaker_uart": "serial", + "nuvoton_numicro_uart": "serial", + "nxp_imx_iuart": "serial", + "nxp_imx_uart": "serial", + "nxp_kinetis_lpsci": "serial", + "nxp_kinetis_uart": "serial", + "nxp_lpc11u6x_uart": "serial", + "nxp_lpc_usart": "serial", + "nxp_lpuart": "serial", + "nxp_s32_linflexd": "serial", + "openisa_rv32m1_lpuart": "serial", + "quicklogic_usbserialport_s3b": "serial", + "raspberrypi_pico_uart_pio": "serial", + "realtek_ameba_loguart": "serial", + "realtek_bee_uart": "serial", + "realtek_rts5912_uart": "serial", + "renesas_ra8_uart_sci_b": "serial", + "renesas_ra_sci_uart": "serial", + "renesas_rcar_hscif": "serial", + "renesas_rcar_scif": "serial", + "renesas_rx_uart_sci": "serial", + "renesas_rx_uart_sci_qemu": "serial", + "renesas_rz_sci_b_uart": "serial", + "renesas_rz_sci_uart": "serial", + "renesas_rz_scif_uart": "serial", + "renesas_rza2m_scif_uart": "serial", + "renesas_rzt2m_uart": "serial", + "renesas_smartbond_uart": "serial", + "segger_rtt_uart": "serial", + "sensry_sy1xx_uart": "serial", + "sifive_uart0": "serial", + "sifli_sf32lb_usart": "serial", + "silabs_eusart_uart": "serial", + "silabs_gecko_leuart": "serial", + "silabs_gecko_uart": "serial", + "silabs_gecko_usart": "serial", + "silabs_si32_usart": "serial", + "silabs_usart_uart": "serial", + "snps_hostlink_uart": "serial", + "st_stm32_uart": "serial", + "telink_b91_uart": "serial", + "ti_cc13xx_cc26xx_uart": "serial", + "ti_cc23x0_uart": "serial", + "ti_cc32xx_uart": "serial", + "ti_msp432p4xx_uart": "serial", + "ti_mspm0_uart": "serial", + "ti_stellaris_uart": "serial", + "virtio_console": "serial", + "vnd_serial": "serial", + "wch_usart": "serial", + "xen_hvc_consoleio": "serial", + "xlnx_xps_uartlite_1_00_a": "serial", + "xlnx_xuartps": "serial", + "zephyr_native_pty_uart": "serial", + "zephyr_native_tty_uart": "serial", + "zephyr_nus_uart": "serial", + "zephyr_uart_bitbang": "serial", + "zephyr_uart_bridge": "serial", + "zephyr_uart_emul": "serial", + # + # sip_svc + "intel_socfpga_agilex_sip_smc": "sip_svc", + # + # smbus + "intel_pch_smbus": "smbus", + "st_stm32_smbus": "smbus", + # + # spi + "adi_max32_spi": "spi", + "ambiq_spi": "spi", + "ambiq_spi_bleif": "spi", + "ambiq_spid": "spi", + "andestech_atcspi200": "spi", + "arm_pl022": "spi", + "atmel_sam0_spi": "spi", + "atmel_sam_spi": "spi", + "bflb_spi": "spi", + "cdns_spi": "spi", + "cypress_psoc6_spi": "spi", + "egis_et171_spi": "spi", + "espressif_esp32_spi": "spi", + "gaisler_spimctrl": "spi", + "gd_gd32_spi": "spi", + "infineon_spi": "spi", + "infineon_xmc4xxx_spi": "spi", + "intel_penwell_spi": "spi", + "intel_sedi_spi": "spi", + "ite_it51xxx_spi": "spi", + "ite_it8xxx2_spi": "spi", + "litex_spi": "spi", + "litex_spi_litespi": "spi", + "lowrisc_opentitan_spi": "spi", + "microchip_mpfs_qspi": "spi", + "microchip_mpfs_spi": "spi", + "microchip_sercom_g1_spi": "spi", + "microchip_xec_qmspi": "spi", + "microchip_xec_qmspi_ldma": "spi", + "nordic_nrf_spi": "spi", + "nordic_nrf_spim": "spi", + "nuvoton_npcx_spip": "spi", + "nuvoton_numaker_spi": "spi", + "nxp_dspi": "spi", + "nxp_flexio_spi": "spi", + "nxp_imx_ecspi": "spi", + "nxp_lpc_spi": "spi", + "nxp_s32_spi": "spi", + "nxp_sc18is606_spi": "spi", + "opencores_spi_simple": "spi", + "openisa_rv32m1_lpspi": "spi", + "raspberrypi_pico_spi_pio": "spi", + "realtek_rts5912_spi": "spi", + "renesas_ra8_spi_b": "spi", + "renesas_ra_spi": "spi", + "renesas_ra_spi_sci": "spi", + "renesas_ra_spi_sci_b": "spi", + "renesas_rx_rspi": "spi", + "renesas_rz_rspi": "spi", + "renesas_rz_spi": "spi", + "renesas_smartbond_spi": "spi", + "sensry_sy1xx_spi": "spi", + "sifive_spi0": "spi", + "sifli_sf32lb_spi": "spi", + "silabs_eusart_spi": "spi", + "silabs_gspi": "spi", + "silabs_usart_spi": "spi", + "snps_designware_spi": "spi", + "st_stm32_spi": "spi", + "telink_b91_spi": "spi", + "ti_cc13xx_cc26xx_spi": "spi", + "ti_cc23x0_spi": "spi", + "ti_omap_mcspi": "spi", + "vnd_spi": "spi", + "wch_spi": "spi", + "xlnx_xps_spi_2_00_a": "spi", + "zephyr_spi_bitbang": "spi", + "zephyr_spi_emul_controller": "spi", + # + # spi/spi_nxp_lpspi + "nxp_lpspi": "spi/spi_nxp_lpspi", + # + # stepper + "zephyr_fake_stepper_ctrl": "stepper", + "zephyr_fake_stepper_driver": "stepper", + # + # stepper/adi_tmc/tmc22xx + "adi_tmc2209": "stepper/adi_tmc/tmc22xx", + # + # stepper/adi_tmc/tmc50xx + "adi_tmc50xx": "stepper/adi_tmc/tmc50xx", + "adi_tmc50xx_stepper_ctrl": "stepper/adi_tmc/tmc50xx", + "adi_tmc50xx_stepper_driver": "stepper/adi_tmc/tmc50xx", + # + # stepper/adi_tmc/tmc51xx + "adi_tmc51xx": "stepper/adi_tmc/tmc51xx", + "adi_tmc51xx_stepper_ctrl": "stepper/adi_tmc/tmc51xx", + "adi_tmc51xx_stepper_driver": "stepper/adi_tmc/tmc51xx", + # + # stepper/allegro + "allegro_a4979": "stepper/allegro", + # + # stepper/gpio_stepper + "zephyr_gpio_step_dir_stepper_ctrl": "stepper/gpio_stepper", + "zephyr_h_bridge_stepper_ctrl": "stepper/gpio_stepper", + # + # stepper/ti + "ti_drv84xx": "stepper/ti", + # + # syscon + "bflb_efuse": "syscon", + "syscon": "syscon", + # + # tee/optee + "linaro_optee_tz": "tee/optee", + # + # timer + "adi_max32_rv32_sys_timer": "timer", + "ambiq_stimer": "timer", + "atmel_sam0_rtc": "timer", + "gaisler_gptimer": "timer", + "infineon_lp_timer": "timer", + "intel_adsp_timer": "timer", + "intel_hpet": "timer", + "ite_it51xxx_timer": "timer", + "ite_it8xxx2_timer": "timer", + "litex_timer0": "timer", + "microchip_sam_pit64b": "timer", + "microchip_xec_rtos_timer": "timer", + "nuvoton_npcx_itim_timer": "timer", + "nxp_gpt_hw_timer": "timer", + "nxp_lptmr": "timer", + "nxp_os_timer": "timer", + "openisa_rv32m1_lptmr": "timer", + "realtek_rts5912_rtmr": "timer", + "renesas_ra_ulpt_timer": "timer", + "renesas_rcar_cmt": "timer", + "renesas_rx_timer_cmt": "timer", + "renesas_rz_gtm_os_timer": "timer", + "renesas_rza2m_ostm": "timer", + "riscv_machine_timer": "timer", + "silabs_gecko_burtc": "timer", + "st_stm32_lptim": "timer", + "sy1xx_sys_timer": "timer", + "ti_am654_timer": "timer", + "ti_cc13xx_cc26xx_rtc_timer": "timer", + "ti_cc23x0_rtc_timer": "timer", + "ti_cc23x0_systim_timer": "timer", + "wch_systick": "timer", + "xlnx_ttcps": "timer", + # + # usb/bc12 + "diodes_pi3usb9201": "usb/bc12", + # + # usb/common/stm32 + "*/": "usb/common/stm32", + "st_stm32u5_otghs_phy": "usb/common/stm32", + # + # usb/device + "atmel_sam_usbc": "usb/device", + "atmel_sam_usbhs": "usb/device", + # + # usb/udc + "adi_max32_usbhs": "usb/udc", + "ambiq_usb": "usb/udc", + "atmel_sam0_usb": "usb/udc", + "ite_it82xx2_usb": "usb/udc", + "nordic_nrf_usbd": "usb/udc", + "nuvoton_numaker_hsusbd": "usb/udc", + "nuvoton_numaker_usbd": "usb/udc", + "nxp_ehci": "usb/udc", + "nxp_kinetis_usbd": "usb/udc", + "nxp_lpcip3511": "usb/udc", + "raspberrypi_pico_usbd": "usb/udc", + "renesas_ra_udc": "usb/udc", + "renesas_smartbond_usbd": "usb/udc", + "snps_dwc2": "usb/udc", + "st_stm32_otgfs": "usb/udc", + "st_stm32_otghs": "usb/udc", + "st_stm32_usb": "usb/udc", + "zephyr_udc_skeleton": "usb/udc", + "zephyr_udc_virtual": "usb/udc", + # + # usb/uhc + "maxim_max3421e_spi": "usb/uhc", + "nxp_uhc_ehci": "usb/uhc", + "nxp_uhc_ip3516hs": "usb/uhc", + "nxp_uhc_khci": "usb/uhc", + "nxp_uhc_ohci": "usb/uhc", + "zephyr_uhc_virtual": "usb/uhc", + # + # usb_c/ppc + "nuvoton_numaker_ppc": "usb_c/ppc", + "nxp_nx20p3483": "usb_c/ppc", + # + # usb_c/tcpc + "nuvoton_numaker_tcpc": "usb_c/tcpc", + "onnn_fusb307_tcpc": "usb_c/tcpc", + "parade_ps8xxx": "usb_c/tcpc", + "richtek_rt1715": "usb_c/tcpc", + "st_stm32_ucpd": "usb_c/tcpc", + # + # usb_c/vbus + "nuvoton_numaker_vbus": "usb_c/vbus", + "zephyr_usb_c_vbus_adc": "usb_c/vbus", + "zephyr_usb_c_vbus_tcpci": "usb_c/vbus", + # + # video + "aptina_mt9m114": "video", + "espressif_esp32_lcd_cam_dvp": "video", + "galaxycore_gc2145": "video", + "himax_hm01b0": "video", + "himax_hm0360": "video", + "nxp_imx_csi": "video", + "nxp_mipi_csi2rx": "video", + "nxp_video_smartdma": "video", + "ovti_ov2640": "video", + "ovti_ov5640": "video", + "ovti_ov5642": "video", + "ovti_ov7670": "video", + "ovti_ov7675": "video", + "ovti_ov7725": "video", + "ovti_ov9655": "video", + "renesas_ra_ceu": "video", + "sony_imx335": "video", + "st_mipid02": "video", + "st_stm32_dcmi": "video", + "st_stm32_dcmipp": "video", + "st_stm32_jpeg": "video", + "st_stm32_venc": "video", + "zephyr_video_emul_imager": "video", + "zephyr_video_emul_rx": "video", + "zephyr_video_sw_generator": "video", + # + # virtio + "virtio_mmio": "virtio", + "virtio_pci": "virtio", + # + # virtualization + "qemu_ivshmem": "virtualization", + # + # w1 + "adi_max32_w1": "w1", + "maxim_ds2482_800": "w1", + "maxim_ds2482_800_channel": "w1", + "maxim_ds2484": "w1", + "maxim_ds2485": "w1", + "vnd_w1": "w1", + "zephyr_w1_gpio": "w1", + "zephyr_w1_serial": "w1", + # + # watchdog + "adi_max32_watchdog": "watchdog", + "adi_max42500_watchdog": "watchdog", + "ambiq_watchdog": "watchdog", + "andestech_atcwdt200": "watchdog", + "arm_cmsdk_watchdog": "watchdog", + "atmel_sam0_watchdog": "watchdog", + "atmel_sam4l_watchdog": "watchdog", + "atmel_sam_watchdog": "watchdog", + "bflb_wdt": "watchdog", + "ene_kb106x_watchdog": "watchdog", + "ene_kb1200_watchdog": "watchdog", + "espressif_esp32_watchdog": "watchdog", + "espressif_esp32_xt_wdt": "watchdog", + "gd_gd32_fwdgt": "watchdog", + "gd_gd32_wwdgt": "watchdog", + "infineon_watchdog": "watchdog", + "infineon_xmc4xxx_watchdog": "watchdog", + "intel_adsp_watchdog": "watchdog", + "intel_tco_wdt": "watchdog", + "ite_it51xxx_watchdog": "watchdog", + "ite_it8xxx2_watchdog": "watchdog", + "litex_watchdog": "watchdog", + "lowrisc_opentitan_aontimer": "watchdog", + "microchip_wdt_g1": "watchdog", + "microchip_xec_watchdog": "watchdog", + "nordic_npm1300_wdt": "watchdog", + "nordic_npm1304_wdt": "watchdog", + "nordic_npm2100_wdt": "watchdog", + "nordic_npm6001_wdt": "watchdog", + "nordic_nrf_wdt": "watchdog", + "nuvoton_npcx_watchdog": "watchdog", + "nuvoton_numaker_wwdt": "watchdog", + "nxp_cop": "watchdog", + "nxp_ewm": "watchdog", + "nxp_fs26_wdog": "watchdog", + "nxp_imx_wdog": "watchdog", + "nxp_kinetis_wdog": "watchdog", + "nxp_lpc_wwdt": "watchdog", + "nxp_rtwdog": "watchdog", + "nxp_s32_swt": "watchdog", + "nxp_wdog32": "watchdog", + "raspberrypi_pico_watchdog": "watchdog", + "realtek_rts5817_watchdog": "watchdog", + "realtek_rts5912_watchdog": "watchdog", + "renesas_rx_iwdt": "watchdog", + "renesas_rz_wdt": "watchdog", + "renesas_smartbond_watchdog": "watchdog", + "sifive_wdt": "watchdog", + "sifli_sf32lb_wdt": "watchdog", + "silabs_gecko_wdog": "watchdog", + "silabs_siwx91x_wdt": "watchdog", + "snps_designware_watchdog": "watchdog", + "st_stm32_watchdog": "watchdog", + "st_stm32_window_watchdog": "watchdog", + "ti_cc13xx_cc26xx_watchdog": "watchdog", + "ti_cc23x0_wdt": "watchdog", + "ti_cc32xx_watchdog": "watchdog", + "ti_j7_rti_wdt": "watchdog", + "ti_tps382x": "watchdog", + "wch_iwdg": "watchdog", + "xlnx_versal_wwdt": "watchdog", + "xlnx_xps_timebase_wdt_1_00_a": "watchdog", + # + # wifi/esp32/src + "espressif_esp32_wifi": "wifi/esp32/src", + # + # wifi/esp_at + "espressif_esp_at": "wifi/esp_at", + # + # wifi/esp_hosted + "espressif_esp_hosted": "wifi/esp_hosted", + # + # wifi/eswifi + "inventek_eswifi": "wifi/eswifi", + "inventek_eswifi_uart": "wifi/eswifi", + # + # wifi/infineon + "infineon_airoc_wifi": "wifi/infineon", + # + # wifi/nrf_wifi/off_raw_tx/src + "nordic_wlan": "wifi/nrf_wifi/off_raw_tx/src", + # + # wifi/nxp + "nxp_wifi": "wifi/nxp", + # + # wifi/siwx91x + "silabs_siwx91x_wifi": "wifi/siwx91x", + # + # wifi/winc1500 + "atmel_winc1500": "wifi/winc1500", +} diff --git a/ports/zephyr-cp/cptools/cpbuild.py b/ports/zephyr-cp/cptools/cpbuild.py new file mode 100644 index 0000000000000..edaf020c264a0 --- /dev/null +++ b/ports/zephyr-cp/cptools/cpbuild.py @@ -0,0 +1,428 @@ +import asyncio +import atexit +import hashlib +import json +import logging +import os +import pathlib +import re +import tempfile +import time +from typing import Optional + +logger = logging.getLogger(__name__) + +shared_semaphore = None + +trace_entries = [] +LAST_BUILD_TIMES = {} +ALREADY_RUN = {} +_last_build_times = pathlib.Path("last_build_times.json") +if _last_build_times.exists(): + with open(_last_build_times) as f: + LAST_BUILD_TIMES = json.load(f) + logger.info("Build times loaded.") +else: + logger.warning( + "No last build times found. This is normal if you're running this for the first time." + ) + + +def save_trace(): + with open("trace.json", "w") as f: + json.dump(trace_entries, f) + with open("last_build_times.json", "w") as f: + json.dump(LAST_BUILD_TIMES, f) + logger.info("wrote trace %s", pathlib.Path(".").absolute() / "trace.json") + logger.info("wrote build times %s", pathlib.Path(".").absolute() / "last_build_times.json") + + +atexit.register(save_trace) + + +class _TokenProtocol(asyncio.Protocol): + def __init__(self, client): + self.client = client + + def data_received(self, data): + # Data can be multiple tokens at once. + for i, _ in enumerate(data): + self.client.new_token(data[i : i + 1]) + + +class _MakeJobClient: + def __init__(self, fifo_path=None, read_fd=None, write_fd=None): + self.fifo_path = fifo_path + if fifo_path is not None: + self.writer = open(fifo_path, "wb") + self.reader = open(fifo_path, "rb") + self.tokens_in_use = [] + self.pending_futures = [] + + self.read_transport: asyncio.ReadTransport | None = None + self.read_protocol = None + + self.started = None + + def new_token(self, token): + # Keep a token and reuse it. Ignore cancelled Futures. + if self.pending_futures: + future = self.pending_futures.pop(0) + while future.cancelled() and self.pending_futures: + future = self.pending_futures.pop(0) + if not future.cancelled(): + future.set_result(token) + return + self.read_transport.pause_reading() + self.writer.write(token) + self.writer.flush() + + async def __aenter__(self): + loop = asyncio.get_event_loop() + if self.started is None: + self.started = asyncio.Event() + self.read_transport, self.read_protocol = await loop.connect_read_pipe( + lambda: _TokenProtocol(self), self.reader + ) + self.started.set() + await self.started.wait() + future = loop.create_future() + self.pending_futures.append(future) + self.read_transport.resume_reading() + self.tokens_in_use.append(await future) + + async def __aexit__(self, exc_type, exc, tb): + token = self.tokens_in_use.pop() + self.new_token(token) + + +def _create_semaphore(): + match = re.search(r"fifo:([^\s]+)", os.environ.get("MAKEFLAGS", "")) + fifo_path = None + if match: + fifo_path = match.group(1) + return _MakeJobClient(fifo_path=fifo_path) + return asyncio.BoundedSemaphore(1) + + +shared_semaphore = _create_semaphore() +tracks = [] +max_track = 0 + + +async def run_command( + command, + working_directory, + description=None, + check_hash=[], + extradeps=[], + responsefile: Optional[pathlib.Path] = None, +): + """ + Runs a command asynchronously. The command should ideally be a list of strings + and pathlib.Path objects. If all of the paths haven't been modified since the last + time the command was run, then it'll be skipped. (The last time a command was run + is stored based on the hash of the command.) + + The command is run from the working_directory and the paths are made relative to it. + + Description is used for logging only. If None, the command itself is logged. + + Paths in check_hash are hashed before and after the command. If the hash is + the same, then the old mtimes are reset. This is helpful if a command may produce + the same result and you don't want the rest of the build impacted + + responsefile is used to store the command line arguments if they are too long for the OS. + The arguments will be replaced with @ and tried again. + If None, commands that are too long will fail. + """ + paths = [] + responsefile_contents = None + if isinstance(command, list): + for i, part in enumerate(command): + if isinstance(part, pathlib.Path): + paths.append(part) + part = part.relative_to(working_directory, walk_up=True) + + command[i] = str(part) + command_string = " ".join(command) + + # When on windows, use a responsefile if the command string is >= 8192 + if responsefile is not None and os.name == "nt" and len(command_string) >= 8192: + # Escape backslashes + responsefile_contents = "\n".join(part.replace("\\", "\\\\") for part in command[1:]) + responsefile.write_text(responsefile_contents) + command_string = f"{command[0]} -v @{responsefile}" + else: + command_string = command + + command_hash = hashlib.sha3_256(command_string.encode("utf-8")) + command_hash.update(str(working_directory).encode("utf-8")) + command_hash = command_hash.hexdigest() + + # If a command is run multiple times, then wait for the first one to continue. Don't run it again. + if command_hash in ALREADY_RUN: + logger.debug(f"Already running {command_hash} {command_string}") + await ALREADY_RUN[command_hash].wait() + return + ALREADY_RUN[command_hash] = asyncio.Event() + + run_reason = None + # If the path inputs are all older than the last time we ran them, then we don't have anything to do. + if command_hash in LAST_BUILD_TIMES and all((p.exists() for p in paths)): + last_build_time = LAST_BUILD_TIMES[command_hash] + # Check all paths in the command because one must be modified by the command. + newest_file = max((0 if p.is_dir() else p.stat().st_mtime_ns for p in paths)) + nothing_newer = newest_file <= last_build_time + logger.debug(f"Last build time {last_build_time} Newest file {newest_file}") + if nothing_newer: + # Escape early if an extra dep is newer. + for p in extradeps: + if p.stat().st_mtime_ns > last_build_time: + run_reason = f"{p.relative_to(working_directory, walk_up=True)} is newer" + nothing_newer = False + break + else: + for p in paths: + if p.stat().st_mtime_ns == newest_file: + run_reason = f"{p.relative_to(working_directory, walk_up=True)} is newer" + break + if nothing_newer: + logger.debug(f"Nothing newer {command_string[-32:]}") + ALREADY_RUN[command_hash].set() + return + else: + run_reason = "no previous build time" + newest_file = 0 + + file_hashes = {} + for path in check_hash: + if not path.exists(): + continue + with path.open("rb") as f: + digest = hashlib.file_digest(f, "sha256") + stat = path.stat() + mtimes = (stat.st_atime, stat.st_mtime) + mtimes_ns = (stat.st_atime_ns, stat.st_mtime_ns) + file_hashes[path] = (digest, mtimes, mtimes_ns) + + cancellation = None + async with shared_semaphore: + global max_track + if not tracks: + max_track += 1 + tracks.append(max_track) + track = tracks.pop() + start_time = time.perf_counter_ns() // 1000 + process = await asyncio.create_subprocess_shell( + command_string, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + cwd=working_directory, + ) + + try: + stdout, stderr = await process.communicate() + except asyncio.CancelledError as e: + cancellation = e + stdout, stderr = await process.communicate() + end_time = time.perf_counter_ns() // 1000 + trace_entries.append( + { + "name": command if not description else description, + "ph": "X", + "pid": 0, + "tid": track, + "ts": start_time, + "dur": end_time - start_time, + } + ) + tracks.append(track) + + if process.returncode == 0: + old_newest_file = newest_file + newest_file = max((p.stat().st_mtime_ns for p in paths)) + LAST_BUILD_TIMES[command_hash] = newest_file + ALREADY_RUN[command_hash].set() + + for path in check_hash: + if path not in file_hashes: + continue + with path.open("rb") as f: + digest = hashlib.file_digest(f, "sha256") + old_digest, _, old_mtimes_ns = file_hashes[path] + if old_digest.digest() == digest.digest(): + logger.debug(f"{path} is unchanged") + os.utime(path, ns=old_mtimes_ns) + + # If something has failed and we've been canceled, hide our success so + # the error is clear. + if cancellation: + raise cancellation + if description: + logger.info(f"{description} ({run_reason})") + logger.debug(command_string) + else: + logger.info(f"{command_string} ({run_reason})") + if old_newest_file == newest_file: + logger.error("No files were modified by the command.") + raise RuntimeError() + else: + if command_hash in LAST_BUILD_TIMES: + del LAST_BUILD_TIMES[command_hash] + logger.error(command_string) + if responsefile_contents: + logger.error(f"Response file contents:\n{responsefile_contents}") + logger.error(f"Return code: {process.returncode}") + if stdout: + logger.info(stdout.decode("utf-8").strip()) + if stderr: + logger.warning(stderr.decode("utf-8").strip()) + if not stdout and not stderr: + logger.warning("No output") + if cancellation: + raise cancellation + raise RuntimeError() + + +async def run_function( + function, + positional, + named, + description=None, +): + async with shared_semaphore: + global max_track + if not tracks: + max_track += 1 + tracks.append(max_track) + track = tracks.pop() + start_time = time.perf_counter_ns() // 1000 + result = await asyncio.to_thread(function, *positional, **named) + + end_time = time.perf_counter_ns() // 1000 + trace_entries.append( + { + "name": str(function) if not description else description, + "ph": "X", + "pid": 0, + "tid": track, + "ts": start_time, + "dur": end_time - start_time, + } + ) + tracks.append(track) + + if description: + logger.info(description) + logger.debug(function) + else: + logger.info(function) + return result + + +def run_in_thread(function): + def wrapper(*positional, **named): + return run_function(function, positional, named) + + return wrapper + + +cwd = pathlib.Path.cwd() + + +def parse_depfile(f): + depfile_contents = f.read_text().split() + extradeps = [] + for dep in depfile_contents: + if dep == "\\" or dep[-1] == ":": + continue + if dep.startswith("/"): + extradeps.append(pathlib.Path(dep)) + else: + raise RuntimeError(f"Unexpected depfile entry {dep}") + + +class Compiler: + def __init__(self, srcdir: pathlib.Path, builddir: pathlib.Path, cmake_args): + self.c_compiler = cmake_args["CC"] + self.ar = cmake_args["AR"] + self.cflags = cmake_args.get("CFLAGS", "") + + self.srcdir = srcdir + self.builddir = builddir + + async def preprocess( + self, source_file: pathlib.Path, output_file: pathlib.Path, flags: list[pathlib.Path] + ): + output_file.parent.mkdir(parents=True, exist_ok=True) + depfile = output_file.parent / (output_file.name + ".d") + responsefile = output_file.parent / (output_file.name + ".rsp") + + await run_command( + [ + self.c_compiler, + "-E", + "-MMD", + "-MF", + depfile, + "-c", + source_file, + self.cflags, + *flags, + "-o", + output_file, + ], + description=f"Preprocess {source_file.relative_to(self.srcdir)} -> {output_file.relative_to(self.builddir)}", + working_directory=self.srcdir, + check_hash=[output_file], + responsefile=responsefile, + ) + + async def compile( + self, source_file: pathlib.Path, output_file: pathlib.Path, flags: list[pathlib.Path] = [] + ): + if isinstance(source_file, str): + source_file = self.srcdir / source_file + if isinstance(output_file, str): + output_file = self.builddir / output_file + output_file.parent.mkdir(parents=True, exist_ok=True) + depfile = output_file.with_suffix(".d") + responsefile = output_file.with_suffix(".rsp") + extradeps = [] + if depfile.exists(): + depfile_contents = depfile.read_text().split() + for dep in depfile_contents: + if dep == "\\" or dep[-1] == ":": + continue + if dep.startswith("/"): + extradeps.append(pathlib.Path(dep)) + else: + extradeps.append(self.srcdir / dep) + + await run_command( + [ + self.c_compiler, + self.cflags, + "-MMD", + "-c", + source_file, + *flags, + "-o", + output_file, + ], + description=f"Compile {source_file.relative_to(self.srcdir)} -> {output_file.relative_to(self.builddir)}", + working_directory=self.srcdir, + extradeps=extradeps, + responsefile=responsefile, + ) + + async def archive(self, objects: list[pathlib.Path], output_file: pathlib.Path): + output_file.parent.mkdir(parents=True, exist_ok=True) + responsefile = output_file.with_suffix(".rsp") + await run_command( + [self.ar, "rvs", output_file, *objects], + description=f"Create archive {output_file.relative_to(self.srcdir)}", + working_directory=self.srcdir, + responsefile=responsefile, + ) diff --git a/ports/zephyr-cp/cptools/gen_compat2driver.py b/ports/zephyr-cp/cptools/gen_compat2driver.py new file mode 100644 index 0000000000000..ffe8da185969f --- /dev/null +++ b/ports/zephyr-cp/cptools/gen_compat2driver.py @@ -0,0 +1,27 @@ +import pathlib + +mapping = {} + +drivers = pathlib.Path("zephyr/drivers") +for p in drivers.glob("**/*.[ch]"): + for line in p.open(): + if line.startswith("#define DT_DRV_COMPAT"): + compat = line.rsplit(None, 1)[-1].strip() + driver = str(p.parent.relative_to(drivers)) + print(compat, "->", driver) + mapping[compat] = driver + +with open("cptools/compat2driver.py", "w") as f: + f.write("# This file was generated by gen_compat2driver.py\n") + f.write("COMPAT_TO_DRIVER = {\n") + # Replaces make it pass lint. + last_driver = None + for key in sorted(mapping.keys(), key=lambda x: (mapping[x], x)): + driver = mapping[key] + if driver != last_driver: + if last_driver: + f.write(" #\n") + f.write(f" # {driver}\n") + last_driver = driver + f.write(f' "{key}": "{mapping[key]}",\n') + f.write("}\n") diff --git a/ports/zephyr-cp/cptools/get_west_shield_args.py b/ports/zephyr-cp/cptools/get_west_shield_args.py new file mode 100644 index 0000000000000..deda6bf5f26f8 --- /dev/null +++ b/ports/zephyr-cp/cptools/get_west_shield_args.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""Resolve shield arguments for west build. + +Priority: +1. SHIELD / SHIELDS make variables (if explicitly provided) +2. SHIELD / SHIELDS from boards///circuitpython.toml +""" + +import argparse +import os +import pathlib +import re +import shlex + +import board_tools + + +def split_shields(raw): + if not raw: + return [] + + return [shield for shield in re.split(r"[,;\s]+", raw.strip()) if shield] + + +def dedupe(values): + deduped = [] + seen = set() + + for value in values: + if value in seen: + continue + seen.add(value) + deduped.append(value) + + return deduped + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("board") + args = parser.parse_args() + + portdir = pathlib.Path(__file__).resolve().parent.parent + + _, mpconfigboard = board_tools.load_mpconfigboard(portdir, args.board) + + shield_origin = os.environ.get("SHIELD_ORIGIN", "undefined") + shields_origin = os.environ.get("SHIELDS_ORIGIN", "undefined") + + shield_override = os.environ.get("SHIELD", "") + shields_override = os.environ.get("SHIELDS", "") + + override_requested = shield_origin != "undefined" or shields_origin != "undefined" + + if override_requested: + shields = split_shields(shield_override) + split_shields(shields_override) + else: + shields = board_tools.get_shields(mpconfigboard) + + shields = dedupe(shields) + + west_shield_args = [] + for shield in shields: + west_shield_args.extend(("--shield", shield)) + + print(shlex.join(west_shield_args)) + + +if __name__ == "__main__": + main() diff --git a/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py b/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py new file mode 100644 index 0000000000000..f42fc1a3a8547 --- /dev/null +++ b/ports/zephyr-cp/cptools/pre_zephyr_build_prep.py @@ -0,0 +1,28 @@ +# Called by the Makefile before calling out to `west`. +import pathlib +import subprocess +import sys + +import board_tools + +portdir = pathlib.Path(__file__).resolve().parent.parent + +board = sys.argv[-1] + +_, mpconfigboard = board_tools.load_mpconfigboard(portdir, board) +if not mpconfigboard: + # Assume it doesn't need any prep. + sys.exit(0) + +blobs = mpconfigboard.get("BLOBS", []) +blob_fetch_args = mpconfigboard.get("blob_fetch_args", {}) +for blob in blobs: + args = blob_fetch_args.get(blob, []) + subprocess.run(["west", "blobs", "fetch", blob, *args], check=True) + +if board.endswith("bsim"): + subprocess.run( + ["make", "everything", "-j", "8"], + cwd=portdir / "tools" / "bsim", + check=True, + ) diff --git a/ports/zephyr-cp/cptools/tests/README.md b/ports/zephyr-cp/cptools/tests/README.md new file mode 100644 index 0000000000000..6bc8aa43ce694 --- /dev/null +++ b/ports/zephyr-cp/cptools/tests/README.md @@ -0,0 +1,28 @@ +# Zephyr2CP Tests + +This directory contains unit tests for the `zephyr2cp.py` module using real device tree parsing and pytest. + +## Running Tests + +To run all tests: +```bash +cd /home/tannewt/repos/circuitpython/ports/zephyr-cp +make test +``` + +For verbose output: +```bash +pytest test_zephyr2cp.py -v +``` + +To run specific test classes: +```bash +pytest test_zephyr2cp.py::TestFindFlashDevices -v +pytest test_zephyr2cp.py::TestFindRAMRegions -v +pytest test_zephyr2cp.py::TestIntegration -v +``` + +To run a specific test: +```bash +pytest test_zephyr2cp.py::TestFindFlashDevices::test_valid_flash_device -v +``` diff --git a/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py b/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py new file mode 100644 index 0000000000000..b147ae0605ed1 --- /dev/null +++ b/ports/zephyr-cp/cptools/tests/test_zephyr2cp.py @@ -0,0 +1,589 @@ +import sys +import pathlib +import tempfile + +# Add devicetree library to path +portdir = pathlib.Path(__file__).parent.parent.parent +sys.path.append(str(portdir / "zephyr/scripts/dts/python-devicetree/src/")) + +from devicetree import dtlib + +# Add parent directory to path to import zephyr2cp +sys.path.insert(0, str(pathlib.Path(__file__).parent.parent)) + +# Mock cpbuild before importing +sys.modules["cpbuild"] = type(sys)("cpbuild") +sys.modules["cpbuild"].run_in_thread = lambda x: x + +from zephyr2cp import find_flash_devices, find_ram_regions, BLOCKED_FLASH_COMPAT, MINIMUM_RAM_SIZE + + +def parse_dts_string(dts_content): + """ + Parse a device tree string and return the dtlib.DT object. + + Args: + dts_content: String containing device tree source + + Returns: + dtlib.DT object with parsed device tree + """ + with tempfile.NamedTemporaryFile(mode="w", suffix=".dts", delete=False) as f: + f.write(dts_content) + f.flush() + temp_path = f.name + + try: + dt = dtlib.DT(temp_path) + return dt + finally: + pathlib.Path(temp_path).unlink() + + +class TestFindFlashDevices: + """Test suite for find_flash_devices function.""" + + def test_no_compatible_returns_empty(self): + """Test that device tree with no flash devices returns empty list.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + memory@0 { + reg = <0x0 0x100000>; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert result == [] + + def test_chosen_flash_excluded(self): + """Test that chosen flash nodes are excluded.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 0x100000>; + }; + + chosen { + zephyr,flash = &flash0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert result == [], "Chosen flash should be excluded" + + def test_blocked_compat_excluded(self): + """Test that blocked compatible strings are excluded.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + qspi0: qspi@40000 { + compatible = "renesas,ra-qspi"; + reg = <0x40000 0x1000>; + }; + + spi0: spi@50000 { + compatible = "nordic,nrf-spim"; + reg = <0x50000 0x1000>; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert result == [], "Blocked flash controllers should be excluded" + + def test_valid_flash_device(self): + """Test that valid flash device is detected.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0 0x100000>; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert len(result) == 1 + assert result[0] == "flash0" + + def test_valid_flash_device_multiple_drivers(self): + """Test that valid flash device is detected.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "other,driver", "jedec,spi-nor"; + reg = <0x0 0x100000>; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert len(result) == 1 + assert result[0] == "flash0" + + def test_external_flash_not_chosen(self): + """Test external flash is included when internal is chosen.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + internal_flash: flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 0x100000>; + }; + + external_flash: flash@1000000 { + compatible = "jedec,spi-nor"; + reg = <0x1000000 0x800000>; + }; + + chosen { + zephyr,flash = &internal_flash; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + + # Should only include external flash, not chosen internal flash + assert len(result) == 1 + assert "external_flash" in result[0] + assert "internal_flash" not in result[0] + + def test_disabled_flash_excluded(self): + """Test that disabled flash devices are excluded.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0 0x100000>; + status = "disabled"; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_flash_devices(dt) + assert result == [], "Disabled flash should be excluded" + + +class TestFindRAMRegions: + """Test suite for find_ram_regions function.""" + + def test_no_ram_returns_empty(self): + """Test that device tree with no RAM returns empty list.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 0x100000>; + }; + + chosen { + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + assert result == [] + + def test_chosen_sram_basic(self): + """Test chosen sram region is detected correctly.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + + chosen { + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + + assert len(result) == 1 + label, start, end, size, path = result[0] + + assert label == "sram0" + assert start == "z_mapped_end" + assert ( + end + == "(uint32_t*) (DT_REG_ADDR(DT_NODELABEL(sram0)) + DT_REG_SIZE(DT_NODELABEL(sram0)))" + ) + assert size == 0x40000 + + def test_memory_region_with_custom_name(self): + """Test memory region with zephyr,memory-region property.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + + reserved_mem: memory@30000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x30000000 0x10000>; + zephyr,memory-region = "CUSTOM_REGION"; + }; + + chosen { + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + + # Should have both regions, chosen first + assert len(result) == 2 + + # First should be chosen SRAM + assert result[0][0] == "sram0" + + # Second should be custom region + label, start, end, size, path = result[1] + assert label == "reserved_mem" + assert start == "__CUSTOM_REGION_end" + + def test_memory_region_requires_sram_or_device_type(self): + """Test memory regions require mmio-sram compatibility or device_type=memory.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + + reserved_mem: memory@30000000 { + compatible = "zephyr,memory-region"; + reg = <0x30000000 0x10000>; + zephyr,memory-region = "CUSTOM_REGION"; + }; + + external_mem: memory@40000000 { + compatible = "zephyr,memory-region"; + device_type = "memory"; + reg = <0x40000000 0x20000>; + zephyr,memory-region = "EXT_REGION"; + }; + + chosen { + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + + assert len(result) == 2 + assert result[0][0] == "sram0" + assert result[1][0] == "external_mem" + + def test_disabled_ram_excluded(self): + """Test that disabled RAM regions are excluded.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + + sram1: memory@30000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x30000000 0x10000>; + status = "disabled"; + zephyr,memory-region = "CUSTOM_REGION"; + }; + + chosen { + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + result = find_ram_regions(dt) + + # Should only have chosen SRAM, not disabled one + assert len(result) == 1 + assert result[0][0] == "sram0" + + +class TestIntegration: + """Integration tests with realistic device tree configurations.""" + + def test_typical_nrf_board_configuration(self): + """Test typical Nordic nRF board with internal and external flash.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0x0 0x100000>; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 0x40000>; + }; + }; + + external_flash: spi_flash@0 { + compatible = "jedec,spi-nor"; + reg = <0x0 0x800000>; + }; + + chosen { + zephyr,flash = &flash0; + zephyr,sram = &sram0; + }; +}; +""" + dt = parse_dts_string(dts) + + # Test flash detection + flashes = find_flash_devices(dt) + assert len(flashes) == 1, "Should find external flash only" + assert "external_flash" in flashes[0] + + # Test RAM detection + rams = find_ram_regions(dt) + assert len(rams) == 1, "Should find chosen SRAM only" + assert rams[0][0] == "sram0" + + def test_board_with_nrf5340_regions(self): + """Test that RAM subregions are included with the right addresses.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { + zephyr,sram = &sram0_image; + }; + /* node '/soc/peripheral@50000000/qspi@2b000' defined in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:475 */ + qspi: qspi@2b000 { + compatible = "nordic,nrf-qspi"; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:476 */ + #address-cells = < 0x1 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:477 */ + #size-cells = < 0x0 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:478 */ + reg = < 0x2b000 0x1000 >, + < 0x10000000 0x10000000 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:479 */ + reg-names = "qspi", + "qspi_mm"; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:480 */ + interrupts = < 0x2b 0x1 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_peripherals.dtsi:481 */ + status = "okay"; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:118 */ + + /* node '/soc/peripheral@50000000/qspi@2b000/mx25r6435f@0' defined in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:123 */ + mx25r64: mx25r6435f@0 { + compatible = "nordic,qspi-nor"; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:124 */ + reg = < 0x0 >; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:125 */ + writeoc = "pp4io"; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:127 */ + readoc = "read4io"; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:129 */ + sck-frequency = < 0x7a1200 >; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:130 */ + jedec-id = [ C2 28 17 ]; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:131 */ + sfdp-bfp = [ E5 20 F1 FF FF FF FF 03 44 EB 08 6B 08 3B 04 BB EE FF FF FF FF FF 00 FF FF FF 00 + FF 0C 20 0F 52 10 D8 00 FF 23 72 F5 00 82 ED 04 CC 44 83 68 44 30 B0 30 B0 F7 C4 + D5 5C 00 BE 29 FF F0 D0 FF FF ]; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:132 */ + size = < 0x4000000 >; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:136 */ + has-dpd; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:137 */ + t-enter-dpd = < 0x2710 >; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:138 */ + t-exit-dpd = < 0x88b8 >; /* in zephyr/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi:139 */ + }; + }; + + /* node '/soc/memory@20000000' defined in zephyr/dts/arm/nordic/nrf5340_cpuapp.dtsi:55 */ + sram0: memory@20000000 { + compatible = "mmio-sram"; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp.dtsi:56 */ + #address-cells = < 0x1 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp.dtsi:57 */ + #size-cells = < 0x1 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp.dtsi:58 */ + reg = < 0x20000000 0x80000 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi:15 */ + ranges = < 0x0 0x20000000 0x80000 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi:16 */ + + /* node '/soc/memory@20000000/sram@0' defined in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:16 */ + sram0_image: sram@0 { + reg = < 0x0 0x70000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:18 */ + ranges = < 0x0 0x0 0x70000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:19 */ + #address-cells = < 0x1 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:20 */ + #size-cells = < 0x1 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:21 */ + + /* node '/soc/memory@20000000/sram@0/sram0_image@0' defined in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:23 */ + sram0_s: sram0_image@0 { + reg = < 0x0 0x40000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:25 */ + }; + }; + + /* node '/soc/memory@20000000/sram@40000' defined in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:33 */ + sram0_ns: sram@40000 { + reg = < 0x40000 0x40000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:35 */ + ranges = < 0x0 0x40000 0x40000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:36 */ + #address-cells = < 0x1 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:37 */ + #size-cells = < 0x1 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:38 */ + + /* node '/soc/memory@20000000/sram@40000/sram0_ns@0' defined in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:40 */ + sram0_ns_app: sram0_ns@0 { + reg = < 0x0 0x30000 >; /* in zephyr/dts/vendor/nordic/nrf5340_sram_partition.dtsi:42 */ + }; + }; + + /* node '/soc/memory@20000000/sram@70000' defined in zephyr/dts/vendor/nordic/nrf5340_shared_sram_partition.dtsi:27 */ + sram0_shared: sram@70000 { + reg = < 0x70000 0x10000 >; /* in zephyr/dts/vendor/nordic/nrf5340_shared_sram_partition.dtsi:29 */ + phandle = < 0x11 >; /* in zephyr/dts/arm/nordic/nrf5340_cpuapp_ipc.dtsi:9 */ + }; + }; +}; +""" + dt = parse_dts_string(dts) + flashes = find_flash_devices(dt) + rams = find_ram_regions(dt) + + # Should only get chosen SRAM + assert len(rams) == 1 + assert rams[0][0] == "sram0_image" + + assert len(flashes) == 1 + assert flashes[0] == "mx25r64" + + def test_board_with_chosen_memory_region(self): + """Test that RAM subregions are included with the right addresses.""" + dts = """ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + chosen { + zephyr,sram = &axisram2; /* in zephyr/boards/st/nucleo_n657x0_q/nucleo_n657x0_q_common.dtsi:18 */ + }; + + + /* node '/memory@34000000' defined in zephyr/dts/arm/st/n6/stm32n6.dtsi:42 */ + axisram1: memory@34000000 { + compatible = "zephyr,memory-region", + "mmio-sram"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:43 */ + zephyr,memory-region = "AXISRAM1"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:44 */ + reg = < 0x34000000 0x200000 >; /* in zephyr/dts/arm/st/n6/stm32n657X0.dtsi:12 */ + }; + + /* node '/memory@34180400' defined in zephyr/dts/arm/st/n6/stm32n6.dtsi:47 */ + axisram2: memory@34180400 { + compatible = "zephyr,memory-region", + "mmio-sram"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:48 */ + zephyr,memory-region = "AXISRAM2"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:49 */ + reg = < 0x34180400 0x7fc00 >; /* in zephyr/dts/arm/st/n6/stm32n657X0.dtsi:17 */ + }; + + /* node '/soc/ramcfg@42023100' defined in zephyr/dts/arm/st/n6/stm32n6.dtsi:251 */ + ramcfg_sram3_axi: ramcfg@42023100 { + compatible = "st,stm32n6-ramcfg"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:252 */ + #address-cells = < 0x1 >; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:253 */ + #size-cells = < 0x1 >; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:254 */ + reg = < 0x42023100 0x80 >; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:255 */ + + /* node '/soc/ramcfg@42023100/memory@34200000' defined in zephyr/dts/arm/st/n6/stm32n6.dtsi:259 */ + axisram3: memory@34200000 { + compatible = "zephyr,memory-region", + "mmio-sram"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:260 */ + zephyr,memory-region = "AXISRAM3"; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:261 */ + zephyr,memory-attr = < 0x100000 >; /* in zephyr/dts/arm/st/n6/stm32n6.dtsi:262 */ + reg = < 0x34200000 0x70000 >; /* in zephyr/dts/arm/st/n6/stm32n657X0.dtsi:23 */ + status = "disabled"; /* in zephyr/dts/arm/st/n6/stm32n657X0.dtsi:24 */ + }; + }; +}; +""" + dt = parse_dts_string(dts) + rams = find_ram_regions(dt) + + print(rams) + + # Should only get chosen SRAM + assert len(rams) == 2 + assert rams[0][0] == "axisram2" + assert rams[1][0] == "axisram1" diff --git a/ports/zephyr-cp/cptools/update_board_info.py b/ports/zephyr-cp/cptools/update_board_info.py new file mode 100755 index 0000000000000..935fc07c17d3a --- /dev/null +++ b/ports/zephyr-cp/cptools/update_board_info.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 + +import pathlib +import sys +import tomlkit + + +def find_modules(top_dir, port_dir): + """Find all available modules in shared-bindings and port bindings.""" + modules = set() + for module in sorted( + list(top_dir.glob("shared-bindings/*")) + list(port_dir.glob("bindings/*")), + key=lambda x: x.name, + ): + if not module.is_dir(): + continue + modules.add(module.name) + return sorted(modules) + + +def find_board_info_files(port_dir): + """Find all autogen_board_info.toml files in the port directory.""" + return list(port_dir.glob("boards/**/autogen_board_info.toml")) + + +def update_board_info(board_info_path, available_modules): + """Update board info file with new modules set to false.""" + if not board_info_path.exists(): + print(f"Error: Board info file {board_info_path} does not exist", file=sys.stderr) + return False + + # Load existing board info + with open(board_info_path, "r", encoding="utf-8") as f: + board_info = tomlkit.load(f) + + # Get current modules + current_modules = set(board_info.get("modules", {})) + + # Find new modules + new_modules = set(available_modules) - current_modules + if not new_modules: + print( + f"No new modules found for {board_info_path.relative_to(board_info_path.parents[3])}" + ) + return True + + # Add new modules as disabled in alphabetical order + modules_table = board_info["modules"] + # Get all modules (existing and new) and sort them + all_modules = list(current_modules | new_modules) + all_modules.sort() + + # Create a new table with sorted modules + sorted_table = tomlkit.table() + for module in all_modules: + if module in modules_table: + # TODO: Use modules_table.item once tomlkit is released with changes from January 2025 + sorted_table[module] = modules_table._value.item(module) + else: + sorted_table[module] = tomlkit.item(False) + + # Replace the modules table with the sorted one + board_info["modules"] = sorted_table + + # Write updated board info + with open(board_info_path, "w", encoding="utf-8") as f: + tomlkit.dump(board_info, f) + + print( + f"Updated {board_info_path.relative_to(board_info_path.parents[3])} with {len(new_modules)} new modules:" + ) + for module in sorted(new_modules): + print(f" - {module}") + return True + + +def main(): + # Get repo paths + script_dir = pathlib.Path(__file__).parent + top_dir = script_dir.parents[2] # circuitpython root + port_dir = script_dir.parent # zephyr-cp directory + + # Get available modules once + available_modules = find_modules(top_dir, port_dir) + + # Update all board info files + board_info_files = find_board_info_files(port_dir) + if not board_info_files: + print("No board info files found") + sys.exit(1) + + success = True + for board_info_path in board_info_files: + if not update_board_info(board_info_path, available_modules): + success = False + + sys.exit(0 if success else 1) + + +if __name__ == "__main__": + main() diff --git a/ports/zephyr-cp/cptools/zephyr2cp.py b/ports/zephyr-cp/cptools/zephyr2cp.py new file mode 100644 index 0000000000000..d40501f1d1d00 --- /dev/null +++ b/ports/zephyr-cp/cptools/zephyr2cp.py @@ -0,0 +1,974 @@ +import logging +import pathlib + +import cpbuild +import yaml +from compat2driver import COMPAT_TO_DRIVER +from devicetree import dtlib + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + +# GPIO flags defined here: include/zephyr/dt-bindings/gpio/gpio.h +GPIO_ACTIVE_LOW = 1 << 0 + +MINIMUM_RAM_SIZE = 1024 + +MANUAL_COMPAT_TO_DRIVER = { + "renesas_ra_nv_flash": "flash", + "soc_nv_flash": "flash", + "nordic_nrf_uarte": "serial", + "nordic_nrf_uart": "serial", + "nordic_nrf_twim": "i2c", + "nordic_nrf_twi": "i2c", + "nordic_nrf_spim": "spi", + "nordic_nrf_spi": "spi", + "nordic_nrf_i2s": "i2s", +} + +# These are controllers, not the flash devices themselves. +BLOCKED_FLASH_COMPAT = ( + "renesas,ra-qspi", + "renesas,ra-ospi-b", + "nordic,nrf-spim", +) + +BUSIO_CLASSES = {"serial": "UART", "i2c": "I2C", "spi": "SPI"} + +AUDIOBUSIO_CLASSES = {"i2s": "I2SOut"} + +CONNECTORS = { + "mikro-bus": [ + "AN", + "RST", + "CS", + "SCK", + "MISO", + "MOSI", + "PWM", + "INT", + "RX", + "TX", + "SCL", + "SDA", + ], + "arduino-header-r3": [ + "A0", + "A1", + "A2", + "A3", + "A4", + "A5", + "D0", + "D1", + "D2", + "D3", + "D4", + "D5", + "D6", + "D7", + "D8", + "D9", + "D10", + "D11", + "D12", + "D13", + "D14", + "D15", + ], + "adafruit-feather-header": [ + "A0", + "A1", + "A2", + "A3", + "A4", + "A5", + "SCK", + "MOSI", + "MISO", + "RX", + "TX", + "D4", + "SDA", + "SCL", + "D5", + "D6", + "D9", + "D10", + "D11", + "D12", + "D13", + ], + "nordic,expansion-board-header": [ + "P1_04", + "P1_05", + "P1_06", + "P1_07", + "P1_08", + "P1_09", + "P1_10", + "P1_11", + "P1_12", + "P1_13", + "P1_14", + ], + "arducam,dvp-20pin-connector": [ + "SCL", + "SDA", + "VS", + "HS", + "PCLK", + "XCLK", + "D7", + "D6", + "D5", + "D4", + "D3", + "D2", + "D1", + "D0", + "PEN", + "PDN", + "GPIO0", + "GPIO1", + ], + "nxp,cam-44pins-connector": ["CAM_RESETB", "CAM_PWDN"], + "nxp,lcd-8080": [ + "TOUCH_SCL", + "TOUCH_SDA", + "TOUCH_INT", + "BACKLIGHT", + "RESET", + "LCD_DC", + "LCD_CS", + "LCD_WR", + "LCD_RD", + "LCD_TE", + "LCD_D0", + "LCD_D1", + "LCD_D2", + "LCD_D3", + "LCD_D4", + "LCD_D5", + "LCD_D6", + "LCD_D7", + "LCD_D8", + "LCD_D9", + "LCD_D10", + "LCD_D11", + "LCD_D12", + "LCD_D13", + "LCD_D14", + "LCD_D15", + ], + "nxp,lcd-pmod": [ + "LCD_WR", + "TOUCH_SCL", + "LCD_DC", + "TOUCH_SDA", + "LCD_MOSI", + "TOUCH_RESET", + "LCD_CS", + "TOUCH_INT", + ], + "raspberrypi,csi-connector": [ + "CSI_D0_N", + "CSI_D0_P", + "CSI_D1_N", + "CSI_D1_P", + "CSI_CK_N", + "CSI_CK_P", + "CSI_D2_N", + "CSI_D2_P", + "CSI_D3_N", + "CSI_D3_P", + "IO0", + "IO1", + "I2C_SCL", + "I2C_SDA", + ], + "renesas,ra-gpio-mipi-header": [ + "IIC_SDA", + "DISP_BLEN", + "IIC_SCL", + "DISP_INT", + "DISP_RST", + ], + "renesas,ra-parallel-graphics-header": [ + "DISP_BLEN", + "IIC_SDA", + "DISP_INT", + "IIC_SCL", + "DISP_RST", + "LCDC_TCON0", + "LCDC_CLK", + "LCDC_TCON2", + "LCDC_TCON1", + "LCDC_EXTCLK", + "LCDC_TCON3", + "LCDC_DATA01", + "LCDC_DATA00", + "LCDC_DATA03", + "LCDC_DATA02", + "LCDC_DATA05", + "LCDC_DATA04", + "LCDC_DATA07", + "LCDC_DATA16", + "LCDC_DATA09", + "LCDC_DATA08", + "LCDC_DATA11", + "LCDC_DATA10", + "LCDC_DATA13", + "LCDC_DATA12", + "LCDC_DATA15", + "LCDC_DATA14", + "LCDC_DATA17", + "LCDC_DATA16", + "LCDC_DATA19", + "LCDC_DATA18", + "LCDC_DATA21", + "LCDC_DATA20", + "LCDC_DATA23", + "LCDC_DATA22", + ], + "st,stm32-dcmi-camera-fpu-330zh": [ + "SCL", + "SDA", + "RESET", + "PEN", + "VS", + "HS", + "PCLK", + "D7", + "D6", + "D5", + "D4", + "D3", + "D2", + "D1", + "D0", + ], + "raspberrypi,pico-header": [ + "GP0", + "GP1", + "GP2", + "GP3", + "GP4", + "GP5", + "GP6", + "GP7", + "GP8", + "GP9", + "GP10", + "GP11", + "GP12", + "GP13", + "GP14", + "GP15", + "GP16", + "GP17", + "GP18", + "GP19", + "GP20", + "GP21", + "GP22", + ["GP26_A0", "GP26", "A0"], + ["GP27_A1", "GP27", "A1"], + ["GP28_A2", "GP28", "A2"], + ], +} + +EXCEPTIONAL_DRIVERS = ["entropy", "gpio", "led"] + + +def find_flash_devices(device_tree): + """ + Find all flash devices from a device tree. + + Args: + device_tree: Parsed device tree (dtlib.DT object) + + Returns: + List of device tree flash device reference strings + """ + # Build path2chosen mapping + path2chosen = {} + for k in device_tree.root.nodes["chosen"].props: + value = device_tree.root.nodes["chosen"].props[k] + path2chosen[value.to_path()] = k + + flashes = [] + logger.debug("Flash devices:") + + # Traverse all nodes in the device tree + remaining_nodes = set([device_tree.root]) + while remaining_nodes: + node = remaining_nodes.pop() + remaining_nodes.update(node.nodes.values()) + + # Get compatible strings + compatible = [] + if "compatible" in node.props: + compatible = node.props["compatible"].to_strings() + + # Get status + status = node.props.get("status", None) + if status is None: + status = "okay" + else: + status = status.to_string() + + # Check if this is a flash device + if not compatible or status != "okay": + continue + + # Check for flash driver via compat2driver + drivers = [] + for c in compatible: + underscored = c.replace(",", "_").replace("-", "_") + driver = COMPAT_TO_DRIVER.get(underscored, None) + if not driver: + driver = MANUAL_COMPAT_TO_DRIVER.get(underscored, None) + if driver: + drivers.append(driver) + logger.debug(f" {node.labels[0] if node.labels else node.name} drivers: {drivers}") + + if "flash" not in drivers: + continue + + # Skip chosen nodes because they are used by Zephyr + if node in path2chosen: + logger.debug( + f" skipping flash {node.labels[0] if node.labels else node.name} (chosen)" + ) + continue + + # Skip blocked flash compatibles (controllers, not actual flash devices) + if compatible[0] in BLOCKED_FLASH_COMPAT: + logger.debug( + f" skipping flash {node.labels[0] if node.labels else node.name} (blocked compat)" + ) + continue + + if node.labels: + flashes.append(node.labels[0]) + + logger.debug("Flash devices:") + for flash in flashes: + logger.debug(f" {flash}") + + return flashes + + +def _label_to_end(label): + return f"(uint32_t*) (DT_REG_ADDR(DT_NODELABEL({label})) + DT_REG_SIZE(DT_NODELABEL({label})))" + + +def find_ram_regions(device_tree): + """ + Find all RAM regions from a device tree. Includes the zephyr,sram node and + any zephyr,memory-region nodes. + + Returns: + List of RAM region info tuples: (label, start, end, size, path) + """ + rams = [] + chosen = None + # Get the chosen SRAM node directly + if "zephyr,sram" in device_tree.root.nodes["chosen"].props: + chosen = device_tree.root.nodes["chosen"].props["zephyr,sram"].to_path() + label = chosen.labels[0] + size = chosen.props["reg"].to_nums()[1] + logger.debug(f"Found chosen SRAM node: {label} with size {size}") + rams.append((label, "z_mapped_end", _label_to_end(label), size, chosen.path)) + + # Traverse all nodes in the device tree to find memory-region nodes + remaining_nodes = set([device_tree.root]) + while remaining_nodes: + node = remaining_nodes.pop() + + # Check status first so we don't add child nodes that aren't active. + status = node.props.get("status", None) + if status is None: + status = "okay" + else: + status = status.to_string() + + if status != "okay": + continue + + if node == chosen: + continue + + remaining_nodes.update(node.nodes.values()) + + if "compatible" not in node.props or not node.labels: + continue + + compatible = node.props["compatible"].to_strings() + + if "zephyr,memory-region" not in compatible or "zephyr,memory-region" not in node.props: + continue + + is_mmio_sram = "mmio-sram" in compatible + device_type = node.props.get("device_type") + has_memory_device_type = device_type and device_type.to_string() == "memory" + if not (is_mmio_sram or has_memory_device_type): + continue + + size = node.props["reg"].to_nums()[1] + + start = "__" + node.props["zephyr,memory-region"].to_string() + "_end" + end = _label_to_end(node.labels[0]) + + # Filter by minimum size + if size >= MINIMUM_RAM_SIZE: + logger.debug( + f"Adding extra RAM info: ({node.labels[0]}, {start}, {end}, {size}, {node.path})" + ) + info = (node.labels[0], start, end, size, node.path) + rams.append(info) + + return rams + + +@cpbuild.run_in_thread +def zephyr_dts_to_cp_board(board_id, portdir, builddir, zephyrbuilddir, mpconfigboard=None): # noqa: C901 + board_dir = builddir / "board" + # Auto generate board files from device tree. + + board_info = { + "wifi": False, + "usb_device": False, + "_bleio": False, + "hostnetwork": board_id in ["native_sim"], + "audiobusio": False, + } + + config_bt_enabled = False + config_bt_found = False + config_present = True + config = zephyrbuilddir / ".config" + if not config.exists(): + config_present = False + else: + for line in config.read_text().splitlines(): + if line.startswith("CONFIG_BT="): + config_bt_enabled = line.strip().endswith("=y") + config_bt_found = True + break + if line.startswith("# CONFIG_BT is not set"): + config_bt_enabled = False + config_bt_found = True + break + + runners = zephyrbuilddir / "runners.yaml" + runners = yaml.safe_load(runners.read_text()) + zephyr_board_dir = pathlib.Path(runners["config"]["board_dir"]) + board_yaml = zephyr_board_dir / "board.yml" + board_yaml = yaml.safe_load(board_yaml.read_text()) + if "board" not in board_yaml and "boards" in board_yaml: + for board in board_yaml["boards"]: + if board["name"] == board_id: + board_yaml = board + break + else: + board_yaml = board_yaml["board"] + board_info["vendor_id"] = board_yaml["vendor"] + vendor_index = zephyr_board_dir.parent / "index.rst" + if vendor_index.exists(): + vendor_index = vendor_index.read_text() + vendor_index = vendor_index.split("\n") + vendor_name = vendor_index[2].strip() + else: + vendor_name = board_info["vendor_id"] + board_info["vendor"] = vendor_name + soc_name = board_yaml["socs"][0]["name"] + board_info["soc"] = soc_name + board_name = board_yaml["full_name"] + if mpconfigboard and "NAME" in mpconfigboard: + board_name = mpconfigboard["NAME"] + board_info["name"] = board_name + # board_id_yaml = zephyr_board_dir / (zephyr_board_dir.name + ".yaml") + # board_id_yaml = yaml.safe_load(board_id_yaml.read_text()) + # print(board_id_yaml) + # board_name = board_id_yaml["name"] + + dts = zephyrbuilddir / "zephyr.dts" + device_tree = dtlib.DT(dts) + node2alias = {} + for alias in device_tree.alias2node: + node = device_tree.alias2node[alias] + if node not in node2alias: + node2alias[node] = [] + node2alias[node].append(alias) + ioports = {} + all_ioports = [] + board_names = {} + status_led = None + status_led_inverted = False + path2chosen = {} + chosen2path = {} + + # Find flash and RAM regions using extracted functions + flashes = find_flash_devices(device_tree) + rams = find_ram_regions(device_tree) # Returns filtered and sorted list + + # Store active Zephyr device labels per-driver so that we can make them available via board. + active_zephyr_devices = {} + usb_num_endpoint_pairs = 0 + ble_hardware_present = False + for k in device_tree.root.nodes["chosen"].props: + value = device_tree.root.nodes["chosen"].props[k] + path2chosen[value.to_path()] = k + chosen2path[k] = value.to_path() + + chosen_display = chosen2path.get("zephyr,display") + if chosen_display is not None: + status = chosen_display.props.get("status", None) + if status is None or status.to_string() == "okay": + board_info["zephyr_display"] = True + board_info["displayio"] = True + + remaining_nodes = set([device_tree.root]) + while remaining_nodes: + node = remaining_nodes.pop() + remaining_nodes.update(node.nodes.values()) + gpio = node.props.get("gpio-controller", False) + gpio_map = node.props.get("gpio-map", []) + status = node.props.get("status", None) + if status is None: + status = "okay" + else: + status = status.to_string() + + compatible = [] + if "compatible" in node.props: + compatible = node.props["compatible"].to_strings() + logger.debug(f"{node.name}: {status}") + logger.debug(f"compatible: {compatible}") + chosen = None + if node in path2chosen: + chosen = path2chosen[node] + logger.debug(f" chosen: {chosen}") + for c in compatible: + underscored = c.replace(",", "_").replace("-", "_") + driver = COMPAT_TO_DRIVER.get(underscored, None) + if not driver: + driver = MANUAL_COMPAT_TO_DRIVER.get(underscored, None) + logger.debug(f" {c} -> {underscored} -> {driver}") + if not driver or status != "okay": + continue + if driver == "flash": + pass # Handled by find_flash_devices() + elif driver == "usb/udc" or "zephyr_udc0" in node.labels: + board_info["usb_device"] = True + props = node.props + if "num-bidir-endpoints" not in props: + props = node.parent.props + usb_num_endpoint_pairs = 0 + if "num-bidir-endpoints" in props: + usb_num_endpoint_pairs = props["num-bidir-endpoints"].to_num() + single_direction_endpoints = [] + for d in ("in", "out"): + eps = f"num-{d}-endpoints" + single_direction_endpoints.append(props[eps].to_num() if eps in props else 0) + # Count separate in/out pairs as bidirectional. + usb_num_endpoint_pairs += min(single_direction_endpoints) + elif driver.startswith("wifi"): + board_info["wifi"] = True + elif driver == "bluetooth/hci": + ble_hardware_present = True + elif driver in AUDIOBUSIO_CLASSES: + # audiobusio driver (i2s, audio/dmic) + board_info["audiobusio"] = True + logger.info(f"Supported audiobusio driver: {driver}") + if driver not in active_zephyr_devices: + active_zephyr_devices[driver] = [] + active_zephyr_devices[driver].append(node.labels) + elif driver in EXCEPTIONAL_DRIVERS: + pass + elif driver in BUSIO_CLASSES: + # busio driver (i2c, spi, uart) + board_info["busio"] = True + logger.info(f"Supported busio driver: {driver}") + if driver not in active_zephyr_devices: + active_zephyr_devices[driver] = [] + active_zephyr_devices[driver].append(node.labels) + else: + logger.warning(f"Unsupported driver: {driver}") + + if gpio: + if "ngpios" in node.props: + ngpios = node.props["ngpios"].to_num() + else: + ngpios = 32 + all_ioports.append(node.labels[0]) + if status == "okay": + ioports[node.labels[0]] = set(range(0, ngpios)) + if gpio_map and compatible and compatible[0] != "gpio-nexus": + connector_pins = CONNECTORS.get(compatible[0], None) + if connector_pins is None: + logger.warning(f"Unsupported connector mapping compatible: {compatible[0]}") + else: + i = 0 + for offset, t, label in gpio_map._markers: + if not label: + continue + if i >= len(connector_pins): + logger.warning( + f"Connector mapping for {compatible[0]} has more pins than names; " + f"stopping at {len(connector_pins)}" + ) + break + num = int.from_bytes(gpio_map.value[offset + 4 : offset + 8], "big") + if (label, num) not in board_names: + board_names[(label, num)] = [] + pin_entry = connector_pins[i] + if isinstance(pin_entry, list): + board_names[(label, num)].extend(pin_entry) + else: + board_names[(label, num)].append(pin_entry) + i += 1 + if "gpio-leds" in compatible: + for led in node.nodes: + led = node.nodes[led] + props = led.props + ioport = props["gpios"]._markers[1][2] + num = int.from_bytes(props["gpios"].value[4:8], "big") + flags = int.from_bytes(props["gpios"].value[8:12], "big") + if "label" in props: + if (ioport, num) not in board_names: + board_names[(ioport, num)] = [] + board_names[(ioport, num)].append(props["label"].to_string()) + if led in node2alias: + if (ioport, num) not in board_names: + board_names[(ioport, num)] = [] + if "led0" in node2alias[led]: + board_names[(ioport, num)].append("LED") + status_led = (ioport, num) + status_led_inverted = flags & GPIO_ACTIVE_LOW + board_names[(ioport, num)].extend(node2alias[led]) + + if "gpio-keys" in compatible: + for key in node.nodes: + props = node.nodes[key].props + ioport = props["gpios"]._markers[1][2] + num = int.from_bytes(props["gpios"].value[4:8], "big") + + if (ioport, num) not in board_names: + board_names[(ioport, num)] = [] + board_names[(ioport, num)].append(props["label"].to_string()) + if key in node2alias: + if "sw0" in node2alias[key]: + board_names[(ioport, num)].append("BUTTON") + board_names[(ioport, num)].extend(node2alias[key]) + + if len(all_ioports) > 1: + a, b = all_ioports[:2] + i = 0 + max_i = min(len(a), len(b)) + while i < max_i and a[i] == b[i]: + i += 1 + shared_prefix = a[:i] + for ioport in ioports: + if not ioport.startswith(shared_prefix): + shared_prefix = "" + break + elif all_ioports: + shared_prefix = all_ioports[0] + else: + shared_prefix = "" + + pin_defs = [] + pin_declarations = ["#pragma once"] + mcu_pin_mapping = [] + board_pin_mapping = [] + for ioport in sorted(ioports.keys()): + for num in ioports[ioport]: + pin_object_name = f"P{ioport[len(shared_prefix) :].upper()}_{num:02d}" + if status_led and (ioport, num) == status_led: + status_led = pin_object_name + pin_defs.append( + f"const mcu_pin_obj_t pin_{pin_object_name} = {{ .base.type = &mcu_pin_type, .port = DEVICE_DT_GET(DT_NODELABEL({ioport})), .number = {num}}};" + ) + pin_declarations.append(f"extern const mcu_pin_obj_t pin_{pin_object_name};") + mcu_pin_mapping.append( + f"{{ MP_ROM_QSTR(MP_QSTR_{pin_object_name}), MP_ROM_PTR(&pin_{pin_object_name}) }}," + ) + board_pin_names = board_names.get((ioport, num), []) + + for board_pin_name in board_pin_names: + board_pin_name = ( + board_pin_name.upper() + .replace(" ", "_") + .replace("-", "_") + .replace("(", "") + .replace(")", "") + ) + board_pin_mapping.append( + f"{{ MP_ROM_QSTR(MP_QSTR_{board_pin_name}), MP_ROM_PTR(&pin_{pin_object_name}) }}," + ) + + pin_defs = "\n".join(pin_defs) + pin_declarations = "\n".join(pin_declarations) + board_pin_mapping = "\n ".join(board_pin_mapping) + mcu_pin_mapping = "\n ".join(mcu_pin_mapping) + + zephyr_binding_headers = [] + zephyr_binding_objects = [] + zephyr_binding_labels = [] + i2sout_instance_names = [] + for driver, instances in active_zephyr_devices.items(): + # Determine if this is busio or audiobusio + if driver in BUSIO_CLASSES: + module = "busio" + driverclass = BUSIO_CLASSES[driver] + elif driver in AUDIOBUSIO_CLASSES: + module = "audiobusio" + driverclass = AUDIOBUSIO_CLASSES[driver] + else: + continue + + zephyr_binding_headers.append(f'#include "shared-bindings/{module}/{driverclass}.h"') + + # Designate a main device such as board.I2C or board.I2S. + if len(instances) == 1: + instances[0].append(driverclass) + else: + # Check to see if a main device has already been designated + found_main = False + for labels in instances: + for label in labels: + if label == driverclass: + found_main = True + if not found_main: + for priority_label in (f"zephyr_{driver}", f"arduino_{driver}"): + for labels in instances: + if priority_label in labels: + labels.append(driverclass) + found_main = True + break + if found_main: + break + for labels in instances: + instance_name = f"{driver.replace('/', '_')}_{labels[0]}" + c_function_name = f"_{instance_name}" + singleton_ptr = f"{c_function_name}_singleton" + function_object = f"{c_function_name}_obj" + obj_type = f"{module}_{driverclass.lower()}" + + # Handle special cases for different drivers + if driver == "serial": + # UART needs a receiver buffer + buffer_decl = f"static byte {instance_name}_buffer[128];" + construct_call = f"common_hal_busio_uart_construct_from_device(&{instance_name}_obj, DEVICE_DT_GET(DT_NODELABEL({labels[0]})), 128, {instance_name}_buffer)" + else: + # Default case (I2C, SPI, I2S) + buffer_decl = "" + construct_call = f"common_hal_{module}_{driverclass.lower()}_construct_from_device(&{instance_name}_obj, DEVICE_DT_GET(DT_NODELABEL({labels[0]})))" + + if driver == "i2s": + i2sout_instance_names.append(instance_name) + + zephyr_binding_objects.append( + f"""{buffer_decl} +static {obj_type}_obj_t {instance_name}_obj; +static mp_obj_t {singleton_ptr} = mp_const_none; +static mp_obj_t {c_function_name}(void) {{ + if ({singleton_ptr} != mp_const_none) {{ + return {singleton_ptr}; + }} + {singleton_ptr} = {construct_call}; + return {singleton_ptr}; +}} +static MP_DEFINE_CONST_FUN_OBJ_0({function_object}, {c_function_name});""".lstrip() + ) + for label in labels: + zephyr_binding_labels.append( + f"{{ MP_ROM_QSTR(MP_QSTR_{label.upper()}), MP_ROM_PTR(&{function_object}) }}," + ) + zephyr_binding_headers = "\n".join(zephyr_binding_headers) + zephyr_binding_objects = "\n".join(zephyr_binding_objects) + zephyr_binding_labels = "\n".join(zephyr_binding_labels) + + # Generate i2sout_reset() that stops all board I2SOut instances + if i2sout_instance_names: + stop_calls = "\n ".join( + f"common_hal_audiobusio_i2sout_stop(&{name}_obj);" for name in i2sout_instance_names + ) + i2sout_reset_func = f""" +void i2sout_reset(void) {{ + {stop_calls} +}}""" + else: + i2sout_reset_func = "" + + zephyr_display_header = "" + zephyr_display_object = "" + zephyr_display_board_entry = "" + if board_info.get("zephyr_display", False): + zephyr_display_header = """ +#include +#include +#include "shared-module/displayio/__init__.h" +#include "bindings/zephyr_display/Display.h" + """.strip() + zephyr_display_object = """ +void board_init(void) { +#if CIRCUITPY_ZEPHYR_DISPLAY && DT_HAS_CHOSEN(zephyr_display) + // Always allocate a display slot so board.DISPLAY is at least a valid + // NoneType object even if the underlying Zephyr display is unavailable. + primary_display_t *display_obj = allocate_display(); + if (display_obj == NULL) { + return; + } + + zephyr_display_display_obj_t *display = &display_obj->zephyr_display; + display->base.type = &mp_type_NoneType; + + const struct device *display_dev = device_get_binding(DEVICE_DT_NAME(DT_CHOSEN(zephyr_display))); + if (display_dev == NULL || !device_is_ready(display_dev)) { + return; + } + + display->base.type = &zephyr_display_display_type; + common_hal_zephyr_display_display_construct_from_device(display, display_dev, 0, true); +#endif +} + """.strip() + zephyr_display_board_entry = ( + "{ MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].zephyr_display) }," + ) + + board_dir.mkdir(exist_ok=True, parents=True) + header = board_dir / "mpconfigboard.h" + if status_led: + status_led = f"#define MICROPY_HW_LED_STATUS (&pin_{status_led})\n" + status_led_inverted = ( + f"#define MICROPY_HW_LED_STATUS_INVERTED ({'1' if status_led_inverted else '0'})\n" + ) + else: + status_led = "" + status_led_inverted = "" + ram_list = [] + ram_externs = [] + max_size = 0 + for ram in rams: + device, start, end, size, path = ram + max_size = max(max_size, size) + # We always start at the end of a Zephyr linker section so we need the externs and &. + # Native/simulated boards don't have real memory-mapped RAM, so we allocate static arrays. + if board_id in ["native_sim"] or "bsim" in board_id: + ram_externs.append("// This is a native board so we provide all of RAM for our heaps.") + ram_externs.append(f"static uint32_t _{device}[{size // 4}]; // {path}") + start = f"(const uint32_t *) (_{device})" + end = f"(const uint32_t *)(_{device} + {size // 4})" + else: + ram_externs.append(f"extern uint32_t {start};") + start = "&" + start + ram_list.append(f" {start}, {end}, // {path}") + ram_list = "\n".join(ram_list) + ram_externs = "\n".join(ram_externs) + + flashes = [f"DEVICE_DT_GET(DT_NODELABEL({flash}))" for flash in flashes] + + new_header_content = f"""#pragma once + +#define MICROPY_HW_BOARD_NAME "{board_name}" +#define MICROPY_HW_MCU_NAME "{soc_name}" +#define CIRCUITPY_RAM_DEVICE_COUNT {len(rams)} +{status_led} +{status_led_inverted} + """ + if not header.exists() or header.read_text() != new_header_content: + header.write_text(new_header_content) + + pins = board_dir / "autogen-pins.h" + if not pins.exists() or pins.read_text() != pin_declarations: + pins.write_text(pin_declarations) + + board_c = board_dir / "board.c" + hostnetwork_include = "" + hostnetwork_entry = "" + if board_info.get("hostnetwork", False): + hostnetwork_include = ( + '#if CIRCUITPY_HOSTNETWORK\n#include "bindings/hostnetwork/__init__.h"\n#endif\n' + ) + hostnetwork_entry = ( + "#if CIRCUITPY_HOSTNETWORK\n" + " { MP_ROM_QSTR(MP_QSTR_NETWORK), MP_ROM_PTR(&common_hal_hostnetwork_obj) },\n" + "#endif\n" + ) + + new_board_c_content = f""" + // This file is autogenerated by build_circuitpython.py + +#include "shared-bindings/board/__init__.h" + +{hostnetwork_include} + +#include + +#include "py/obj.h" +#include "py/mphal.h" + +{zephyr_binding_headers} +{zephyr_display_header} + +const struct device* const flashes[] = {{ {", ".join(flashes)} }}; +const int circuitpy_flash_device_count = {len(flashes)}; + +{ram_externs} +const uint32_t* const ram_bounds[] = {{ +{ram_list} +}}; +const size_t circuitpy_max_ram_size = {max_size}; + +{pin_defs} + +{zephyr_binding_objects} +{zephyr_display_object} +{i2sout_reset_func} + +static const mp_rom_map_elem_t mcu_pin_globals_table[] = {{ +{mcu_pin_mapping} +}}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_globals_table); + +static const mp_rom_map_elem_t board_module_globals_table[] = {{ +CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS + +{hostnetwork_entry} +{zephyr_display_board_entry} +{board_pin_mapping} + +{zephyr_binding_labels} + +}}; + +MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table); +""" + board_c.write_text(new_board_c_content) + if ble_hardware_present: + if not config_present: + raise RuntimeError( + "Missing Zephyr .config; CONFIG_BT must be set explicitly when BLE hardware is present." + ) + if not config_bt_found: + raise RuntimeError( + "CONFIG_BT is missing from Zephyr .config; set it explicitly when BLE hardware is present." + ) + + board_info["_bleio"] = ble_hardware_present and config_bt_enabled + board_info["source_files"] = [board_c] + board_info["cflags"] = ("-I", board_dir) + board_info["flash_count"] = len(flashes) + board_info["rotaryio"] = bool(ioports) + board_info["usb_num_endpoint_pairs"] = usb_num_endpoint_pairs + + # Detect NVM partition from the device tree. + nvm_node = device_tree.label2node.get("nvm_partition") + board_info["nvm"] = nvm_node is not None + + return board_info diff --git a/ports/zephyr-cp/debug.conf b/ports/zephyr-cp/debug.conf new file mode 100644 index 0000000000000..90c1f52d4db6b --- /dev/null +++ b/ports/zephyr-cp/debug.conf @@ -0,0 +1,15 @@ +CONFIG_DEBUG=y +CONFIG_DEBUG_OPTIMIZATIONS=y +CONFIG_LOG_MAX_LEVEL=4 + +CONFIG_STACK_SENTINEL=y +CONFIG_DEBUG_THREAD_INFO=y +CONFIG_DEBUG_INFO=y +CONFIG_EXCEPTION_STACK_TRACE=y + +CONFIG_ASSERT=y +CONFIG_LOG_BLOCK_IN_THREAD=y +CONFIG_FRAME_POINTER=y + +CONFIG_FLASH_LOG_LEVEL_DBG=y +CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/ports/zephyr-cp/docs/perfetto-tracing.md b/ports/zephyr-cp/docs/perfetto-tracing.md new file mode 100644 index 0000000000000..ff35d361f70bd --- /dev/null +++ b/ports/zephyr-cp/docs/perfetto-tracing.md @@ -0,0 +1,150 @@ +# Perfetto Tracing + +The Zephyr port supports Perfetto tracing for performance analysis. This document +describes how to capture, validate, and view traces. + +## Capturing Traces + +Traces are written to `circuitpython.perfetto-trace` in the port directory when +running with tracing enabled (e.g., on native_sim). + +## Validating Traces + +### Using trace_processor + +The Perfetto trace_processor tool can validate and query trace files: + +```bash +~/repos/perfetto/tools/trace_processor circuitpython.perfetto-trace +``` + +This will download the trace_processor binary if needed and open an interactive +SQL shell. If the trace loads successfully, you can query it: + +```sql +SELECT COUNT(*) FROM slice; +``` + +### Using the Perfetto UI + +Open https://ui.perfetto.dev and drag your trace file onto the page. + +## Debugging Invalid Traces + +### Common Error: Packets Skipped Due to Invalid Incremental State + +If trace_processor reports packets being skipped with messages like: + +``` +packet_skipped_seq_needs_incremental_state_invalid +``` + +This means packets have `SEQ_NEEDS_INCREMENTAL_STATE` (value 2) set but no +prior packet set `SEQ_INCREMENTAL_STATE_CLEARED` (value 1) to initialize the +incremental state. + +**Root Cause**: The process descriptor packet (which sets `SEQ_INCREMENTAL_STATE_CLEARED`) +must be emitted before any other trace packets. + +**Diagnosis**: Use protoc to inspect the raw trace: + +```bash +protoc --decode_raw < circuitpython.perfetto-trace | head -100 +``` + +Look for field 13 (sequence_flags) in the first few packets: + +- `13: 1` = SEQ_INCREMENTAL_STATE_CLEARED (good - should be first) +- `13: 2` = SEQ_NEEDS_INCREMENTAL_STATE (requires prior cleared packet) + +A valid trace should have the process descriptor with `13: 1` as one of the +first packets. + +**Fix**: Ensure `perfetto_start()` is called before any trace events are emitted. +The descriptor emit functions in `perfetto_encoder.c` should check: + +```c +if (!started) { + perfetto_start(); +} +``` + +### Analyzing Raw Trace Structure + +To understand the trace structure: + +```bash +# Count total packets +protoc --decode_raw < circuitpython.perfetto-trace | grep -c "^1 {" + +# Find all sequence_flags values +protoc --decode_raw < circuitpython.perfetto-trace | grep "13:" | sort | uniq -c + +# Look for track descriptors (field 60) +protoc --decode_raw < circuitpython.perfetto-trace | grep -A20 "60 {" + +# Look for process descriptors (field 3 inside track_descriptor) +protoc --decode_raw < circuitpython.perfetto-trace | grep -B5 "3 {" +``` + +### Key Protobuf Field Numbers + +TracePacket fields: + +| Field | Description | +|-------|-------------| +| 8 | timestamp | +| 10 | trusted_packet_sequence_id | +| 11 | track_event | +| 12 | interned_data | +| 13 | sequence_flags | +| 60 | track_descriptor | + +TrackDescriptor fields (inside field 60): + +| Field | Description | +|-------|-------------| +| 1 | uuid | +| 2 | name | +| 3 | process (ProcessDescriptor) | +| 4 | thread (ThreadDescriptor) | +| 5 | parent_uuid | + +## Build Verification + +After modifying tracing code, verify the build is updated: + +```bash +# Check source vs object file timestamps +ls -la zephyr/subsys/tracing/perfetto/perfetto_encoder.c +ls -la zephyr/build/zephyr/subsys/tracing/perfetto/CMakeFiles/subsys__tracing__perfetto.dir/perfetto_encoder.c.obj +``` + +The object file timestamp must be newer than the source file timestamp. If not, +rebuild the project before capturing a new trace. + +## Architecture + +The tracing implementation consists of: + +- `perfetto_encoder.c`: Encodes trace packets using nanopb +- `perfetto_top.c`: Implements Zephyr tracing hooks (sys_trace_*) +- `perfetto_encoder.h`: Public API and UUID definitions + +Key UUIDs: + +| Constant | Value | Description | +|----------|-------|-------------| +| PROCESS_UUID | 1 | Root process track | +| ISR_TRACK_UUID | 2 | Interrupt service routine track | +| TRACE_TRACK_UUID | 3 | Top-level trace track | + +### Initialization Flow + +1. `SYS_INIT` calls `perfetto_init()` at POST_KERNEL priority 0 +2. `perfetto_init()` calls `perfetto_encoder_init()` +3. `perfetto_initialized` is set to true +4. Thread hooks start firing +5. First emit function calls `perfetto_start()` +6. `perfetto_start()` emits process descriptor with `SEQ_INCREMENTAL_STATE_CLEARED` +7. Subsequent packets use `SEQ_NEEDS_INCREMENTAL_STATE` diff --git a/ports/zephyr-cp/mpconfigport.h b/ports/zephyr-cp/mpconfigport.h new file mode 100644 index 0000000000000..9e7bc62c0fe40 --- /dev/null +++ b/ports/zephyr-cp/mpconfigport.h @@ -0,0 +1,31 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2015 Glenn Ruben Bakke +// SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// 24kiB stack +#define CIRCUITPY_DEFAULT_STACK_SIZE (24 * 1024) + +#define MICROPY_PY_SYS_PLATFORM "Zephyr" + +#define CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL (1) +#define DIGITALINOUT_INVALID_DRIVE_MODE (1) + +#define CIRCUITPY_DEBUG_TINYUSB 0 + +// NVM size is determined at runtime from the Zephyr partition table. +#define CIRCUITPY_INTERNAL_NVM_SIZE 1 + +// Disable native _Float16 handling for host builds. +#define MICROPY_FLOAT_USE_NATIVE_FLT16 (0) + +#define MICROPY_NLR_THUMB_USE_LONG_JUMP (1) + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// This also includes mpconfigboard.h. +#include "py/circuitpy_mpconfig.h" diff --git a/ports/zephyr-cp/mphalport.h b/ports/zephyr-cp/mphalport.h new file mode 100644 index 0000000000000..ee696a4f04370 --- /dev/null +++ b/ports/zephyr-cp/mphalport.h @@ -0,0 +1,24 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2015 Glenn Ruben Bakke +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "shared/runtime/interrupt_char.h" +#include "py/mpconfig.h" +#include "supervisor/shared/tick.h" + +#include + +#define mp_hal_ticks_ms() ((mp_uint_t)supervisor_ticks_ms32()) + +static inline void mp_hal_delay_us(mp_uint_t us) { + k_busy_wait((uint32_t)us); +} + +bool mp_hal_stdin_any(void); diff --git a/ports/zephyr-cp/native_sim_build_Containerfile b/ports/zephyr-cp/native_sim_build_Containerfile new file mode 100644 index 0000000000000..3cd1a677da351 --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_Containerfile @@ -0,0 +1,40 @@ +FROM ubuntu:24.04 +ENV DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC +ENV PKG_CONFIG_PATH=/usr/lib/i386-linux-gnu/pkgconfig + +RUN dpkg --add-architecture i386 && apt-get update && apt-get install -y --no-install-recommends \ + git cmake ninja-build gperf ccache dfu-util device-tree-compiler \ + wget python3 python3-dev python3-pip python3-venv python3-setuptools \ + python3-tk python3-wheel xz-utils file make gcc \ + gcc-multilib g++-multilib libc6-dev-i386 \ + libsdl2-dev:i386 libsdl2-image-dev:i386 \ + libmagic1 mtools pkg-config ca-certificates unzip \ + protobuf-compiler sudo \ + && rm -rf /var/lib/apt/lists/* + +# Remove the default ubuntu:24.04 'ubuntu' user (UID 1000) so 'dev' can take +# UID 1000 — required for --userns=keep-id to map host UID 1000 to 'dev'. +RUN userdel -r ubuntu 2>/dev/null || true \ + && useradd -m -u 1000 -s /bin/bash dev \ + && echo 'dev ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/dev \ + && chmod 440 /etc/sudoers.d/dev +USER dev +WORKDIR /home/dev + +RUN python3 -m venv /home/dev/.venv +ENV PATH="/home/dev/.venv/bin:${PATH}" +RUN pip install --no-cache-dir west pytest pyelftools pyyaml intelhex protobuf grpcio-tools + +# The repo is expected to be bind-mounted here at runtime: +# podman run -v ~/circuitpython:/home/dev/circuitpython:Z --userns=keep-id ... +# On first run, inside the container do: +# cd ~/circuitpython/ports/zephyr-cp +# west init -l zephyr-config +# west update +# west zephyr-export +# pip install -r zephyr/scripts/requirements.txt +# pip install -r ../../requirements-dev.txt +# west sdk install -t x86_64-zephyr-elf +# python ../../tools/ci_fetch_deps.py zephyr-cp +WORKDIR /home/dev/circuitpython/ports/zephyr-cp +CMD ["/bin/bash"] diff --git a/ports/zephyr-cp/native_sim_build_init_container.sh b/ports/zephyr-cp/native_sim_build_init_container.sh new file mode 100755 index 0000000000000..19831e1fcc28a --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_init_container.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +# One-time setup to run INSIDE the zephyr-cp-dev container on the first +# launch against a fresh bind-mounted circuitpython checkout. +# +# Usage (inside the container): +# cd ~/circuitpython/ports/zephyr-cp +# ./native_sim_build_init_container.sh +# +# Safe to re-run; west/pip/etc. are idempotent. +set -euo pipefail + +git config --global --add safe.directory /home/dev/circuitpython + +cd "$(dirname "${BASH_SOURCE[0]}")" + +echo "==> west init" +if [ ! -d .west ]; then + west init -l zephyr-config +else + echo " (already initialized, skipping)" +fi + +echo "==> west update" +west update + +echo "==> west zephyr-export" +west zephyr-export + +echo "==> pip install Zephyr requirements" +pip install -r zephyr/scripts/requirements.txt + +echo "==> pip install CircuitPython dev requirements" +pip install -r ../../requirements-dev.txt + +echo "==> west sdk install (x86_64-zephyr-elf)" +west sdk install -t x86_64-zephyr-elf + +echo "==> fetch port submodules" +python ../../tools/ci_fetch_deps.py zephyr-cp + +echo +echo "First-run setup complete." +echo "You can now build with: make BOARD=native_native_sim" diff --git a/ports/zephyr-cp/native_sim_build_run_container.sh b/ports/zephyr-cp/native_sim_build_run_container.sh new file mode 100755 index 0000000000000..e30aca22b46a7 --- /dev/null +++ b/ports/zephyr-cp/native_sim_build_run_container.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Launch (or re-attach to) the zephyr-cp-dev container with the enclosing +# circuitpython checkout bind-mounted at /home/dev/circuitpython. Works from +# any CWD — the mount is resolved relative to this script's location. +# +# On first invocation, creates a persistent container named "zcp". On +# subsequent invocations, re-starts the same container so installed state +# (e.g. the Zephyr SDK under /home/dev/zephyr-sdk-*) survives across sessions. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +CONTAINER_NAME="zcp" +IMAGE="zephyr-cp-dev" + +if podman container exists "$CONTAINER_NAME"; then + exec podman start -ai "$CONTAINER_NAME" +else + exec podman run -it --name "$CONTAINER_NAME" \ + -v "$REPO_ROOT:/home/dev/circuitpython:Z" \ + --userns=keep-id \ + "$IMAGE" "$@" +fi diff --git a/ports/zephyr-cp/native_sim_i2c_emul_control.c b/ports/zephyr-cp/native_sim_i2c_emul_control.c new file mode 100644 index 0000000000000..de467122a7bf5 --- /dev/null +++ b/ports/zephyr-cp/native_sim_i2c_emul_control.c @@ -0,0 +1,169 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Command-line control for enabling/disabling emulated I2C devices + * on native_sim. This allows testing device hot-plug and error scenarios. + */ + +#include +#include +#include +#include +#include +#include + +#include "nsi_cmdline.h" +#include "posix_native_task.h" + +LOG_MODULE_REGISTER(i2c_emul_control, LOG_LEVEL_INF); + +#define MAX_DISABLED_DEVICES 16 + +struct disabled_device { + const char *name; + const struct emul *emul; + struct i2c_emul_api mock_api; + bool disabled; +}; + +static struct disabled_device disabled_devices[MAX_DISABLED_DEVICES]; +static int num_disabled_devices = 0; + +static char *disabled_device_args[MAX_DISABLED_DEVICES]; +static int num_disabled_device_args = 0; + +/* + * Mock transfer function that returns -EIO (NACK) when device is disabled, + * or -ENOSYS to fall back to the real emulator. + */ +static int disabled_device_transfer(const struct emul *target, + struct i2c_msg *msgs, + int num_msgs, + int addr) { + ARG_UNUSED(msgs); + ARG_UNUSED(num_msgs); + ARG_UNUSED(addr); + + for (int i = 0; i < num_disabled_devices; i++) { + if (disabled_devices[i].emul == target) { + if (disabled_devices[i].disabled) { + LOG_DBG("Device %s is disabled, returning -EIO", + disabled_devices[i].name); + return -EIO; + } + break; + } + } + /* Fall back to normal emulator behavior */ + return -ENOSYS; +} + +int i2c_emul_control_disable_device(const char *name) { + const struct emul *emul = emul_get_binding(name); + if (!emul) { + LOG_ERR("Emulator '%s' not found", name); + return -ENODEV; + } + + if (emul->bus_type != EMUL_BUS_TYPE_I2C) { + LOG_ERR("Emulator '%s' is not an I2C device", name); + return -EINVAL; + } + + /* Find existing entry or create new one */ + int idx = -1; + for (int i = 0; i < num_disabled_devices; i++) { + if (disabled_devices[i].emul == emul) { + idx = i; + break; + } + } + + if (idx < 0) { + if (num_disabled_devices >= MAX_DISABLED_DEVICES) { + LOG_ERR("Too many disabled devices"); + return -ENOMEM; + } + idx = num_disabled_devices++; + disabled_devices[idx].name = name; + disabled_devices[idx].emul = emul; + disabled_devices[idx].mock_api.transfer = disabled_device_transfer; + + /* Install our mock_api to intercept transfers */ + emul->bus.i2c->mock_api = &disabled_devices[idx].mock_api; + } + + disabled_devices[idx].disabled = true; + LOG_INF("Disabled I2C emulator: %s", name); + return 0; +} + +int i2c_emul_control_enable_device(const char *name) { + for (int i = 0; i < num_disabled_devices; i++) { + if (strcmp(disabled_devices[i].name, name) == 0) { + disabled_devices[i].disabled = false; + LOG_INF("Enabled I2C emulator: %s", name); + return 0; + } + } + LOG_ERR("Device '%s' not in disabled list", name); + return -ENODEV; +} + +bool i2c_emul_control_is_disabled(const char *name) { + for (int i = 0; i < num_disabled_devices; i++) { + if (strcmp(disabled_devices[i].name, name) == 0) { + return disabled_devices[i].disabled; + } + } + return false; +} + +/* Command-line option handler */ +static void cmd_disable_i2c_device(char *argv, int offset) { + /* The value is at argv + offset (after the '=' in --disable-i2c=value) */ + char *value = argv + offset; + if (num_disabled_device_args < MAX_DISABLED_DEVICES) { + disabled_device_args[num_disabled_device_args++] = value; + } else { + printk("i2c_emul_control: Too many --disable-i2c arguments, ignoring: %s\n", value); + } +} + +static struct args_struct_t i2c_emul_args[] = { + { + .option = "disable-i2c", + .name = "device", + .type = 's', + .call_when_found = cmd_disable_i2c_device, + .descript = "Disable an emulated I2C device by name (can be repeated). " + "Example: --disable-i2c=bmi160" + }, + ARG_TABLE_ENDMARKER +}; + +static void register_cmdline_opts(void) { + nsi_add_command_line_opts(i2c_emul_args); +} + +/* Register command-line options early in boot */ +NATIVE_TASK(register_cmdline_opts, PRE_BOOT_1, 0); + +static int apply_disabled_devices(void) { + LOG_DBG("Applying %d disabled device(s)", num_disabled_device_args); + for (int i = 0; i < num_disabled_device_args; i++) { + int rc = i2c_emul_control_disable_device(disabled_device_args[i]); + if (rc != 0) { + LOG_WRN("Failed to disable I2C device '%s': %d", + disabled_device_args[i], rc); + } + } + return 0; +} + +/* + * Apply after emulators are initialized. + * I2C emulators are registered at POST_KERNEL level, so we need to run + * at APPLICATION level to ensure they exist. + */ +SYS_INIT(apply_disabled_devices, APPLICATION, 99); diff --git a/ports/zephyr-cp/prj.conf b/ports/zephyr-cp/prj.conf new file mode 100644 index 0000000000000..893ff259a97c7 --- /dev/null +++ b/ports/zephyr-cp/prj.conf @@ -0,0 +1,56 @@ +CONFIG_SYS_HEAP_RUNTIME_STATS=n +CONFIG_FLASH=y +CONFIG_FLASH_MAP=y + +CONFIG_DYNAMIC_INTERRUPTS=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +CONFIG_FLASH_MAP_LABELS=y +CONFIG_MAIN_STACK_SIZE=24288 + +CONFIG_THREAD_STACK_INFO=y +CONFIG_STACK_SENTINEL=n +CONFIG_DEBUG_THREAD_INFO=n +CONFIG_EXCEPTION_STACK_TRACE=n + +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_CDC_ACM_CLASS=y +CONFIG_USBD_MSC_STACK_SIZE=1536 +CONFIG_CDC_ACM_SERIAL_INITIALIZE_AT_BOOT=n + +CONFIG_USBD_MSC_CLASS=y +CONFIG_USBD_MSC_LUNS_PER_INSTANCE=1 + +CONFIG_HWINFO=y +CONFIG_REBOOT=y +CONFIG_ENTROPY_GENERATOR=y + +CONFIG_ASSERT=n +CONFIG_LOG_BLOCK_IN_THREAD=n + +CONFIG_EVENTS=y + +CONFIG_SERIAL=y +CONFIG_UART_LINE_CTRL=y + +CONFIG_I2C=y +CONFIG_SPI=y +CONFIG_SPI_ASYNC=y + +CONFIG_LOG=y +CONFIG_LOG_MAX_LEVEL=2 +CONFIG_FRAME_POINTER=n + +CONFIG_NET_HOSTNAME_ENABLE=y +CONFIG_NET_HOSTNAME_DYNAMIC=y +CONFIG_NET_HOSTNAME="circuitpython" + +CONFIG_I2S=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_SHA256=y diff --git a/ports/zephyr-cp/socs/nrf52840.conf b/ports/zephyr-cp/socs/nrf52840.conf new file mode 100644 index 0000000000000..bf70997d83f29 --- /dev/null +++ b/ports/zephyr-cp/socs/nrf52840.conf @@ -0,0 +1,4 @@ + +CONFIG_NRFX_UARTE0=y +CONFIG_NRFX_UARTE1=y +CONFIG_NRFX_POWER=y diff --git a/ports/zephyr-cp/socs/nrf5340_cpuapp.conf b/ports/zephyr-cp/socs/nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..734d26db8e939 --- /dev/null +++ b/ports/zephyr-cp/socs/nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ + +CONFIG_NRFX_UARTE=y +CONFIG_NRFX_POWER=y diff --git a/ports/zephyr-cp/socs/nrf5340_cpunet.conf b/ports/zephyr-cp/socs/nrf5340_cpunet.conf new file mode 100644 index 0000000000000..a364a3b5b4bcf --- /dev/null +++ b/ports/zephyr-cp/socs/nrf5340_cpunet.conf @@ -0,0 +1,10 @@ +CONFIG_BT_ISO_PERIPHERAL=n +CONFIG_BT_ISO_CENTRAL=n +CONFIG_BT_ISO_BROADCASTER=n +CONFIG_BT_ISO_SYNC_RECEIVER=n +CONFIG_BT_PER_ADV=n +CONFIG_BT_PER_ADV_SYNC=n +CONFIG_BT_CTLR_ADV_EXT=n + +CONFIG_LOG=n +CONFIG_CONSOLE=n diff --git a/ports/zephyr-cp/socs/r7fa8d1bhecbd.conf b/ports/zephyr-cp/socs/r7fa8d1bhecbd.conf new file mode 100644 index 0000000000000..14a93b52ce802 --- /dev/null +++ b/ports/zephyr-cp/socs/r7fa8d1bhecbd.conf @@ -0,0 +1 @@ +CONFIG_MEMC=y diff --git a/ports/zephyr-cp/socs/stm32h7b3xx.conf b/ports/zephyr-cp/socs/stm32h7b3xx.conf new file mode 100644 index 0000000000000..14a93b52ce802 --- /dev/null +++ b/ports/zephyr-cp/socs/stm32h7b3xx.conf @@ -0,0 +1 @@ +CONFIG_MEMC=y diff --git a/ports/zephyr-cp/socs/stm32u575xx.conf b/ports/zephyr-cp/socs/stm32u575xx.conf new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/zephyr-cp/supervisor/flash.c b/ports/zephyr-cp/supervisor/flash.c new file mode 100644 index 0000000000000..a13bb3cffcb20 --- /dev/null +++ b/ports/zephyr-cp/supervisor/flash.c @@ -0,0 +1,591 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George +// +// SPDX-License-Identifier: MIT +#include "supervisor/flash.h" + +#include +#include + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#include +#include +#include +#include + +#define CIRCUITPY_PARTITION circuitpy_partition +static const struct flash_area *filesystem_area = NULL; + +#if !FIXED_PARTITION_EXISTS(CIRCUITPY_PARTITION) +static struct flash_area _dynamic_area; +#endif + +// Auto generated in pins.c +extern const struct device *const flashes[]; +extern const int circuitpy_flash_device_count; + +// Size of an erase page. +static size_t _page_size; + +// The value a flash byte has after being erased (usually 0xFF, but can differ). +static uint8_t _erase_value; + +// Number of FILESYSTEM_BLOCK_SIZE blocks in an erase page. +static size_t _blocks_per_page; +static uint32_t _page_mask; + +#define NO_PAGE_LOADED 0xFFFFFFFF + +// The currently cached sector in the cache, ram or flash based. +static uint32_t _current_page_address; + +static uint32_t _scratch_page_address; + +// Per-block flags packed into a uint8_t array (one byte per block). +#define ROW_LOADED 0x01 // Block data is present in the cache. +#define ROW_DIRTY 0x02 // Block has been modified since last flush. +#define ROW_ERASED 0x04 // Block is all 0xFF; no need to write after erase. + +static uint8_t *_row_flags = NULL; + +static inline void _clear_row_flags(void) { + if (_row_flags != NULL) { + memset(_row_flags, 0, _blocks_per_page); + } +} + +static inline bool _any_dirty(void) { + for (size_t i = 0; i < _blocks_per_page; i++) { + if (_row_flags[i] & ROW_DIRTY) { + return true; + } + } + return false; +} + +// Check if a buffer is entirely the erase value. +static bool _buffer_is_erased(const uint8_t *buf, size_t len) { + for (size_t i = 0; i < len; i++) { + if (buf[i] != _erase_value) { + return false; + } + } + return true; +} + +// Table of pointers to each cached block. Should be zero'd after allocation. +#define FLASH_CACHE_TABLE_NUM_ENTRIES (_blocks_per_page) +#define FLASH_CACHE_TABLE_SIZE (FLASH_CACHE_TABLE_NUM_ENTRIES * sizeof(uint8_t *)) +static uint8_t **flash_cache_table = NULL; + +static K_MUTEX_DEFINE(_mutex); + +static void fa_cb(const struct flash_area *fa, void *user_data) { + bool *covered_by_areas = user_data; + + const char *fa_label = flash_area_label(fa); + + if (fa_label == NULL) { + fa_label = "-"; + } + printk("%s %p %d dev %p\n", fa_label, fa, fa->fa_id, fa->fa_dev); + + for (int i = 0; i < circuitpy_flash_device_count; i++) { + const struct device *d = flashes[i]; + + if (d == fa->fa_dev) { + covered_by_areas[i] = true; + } + } + + uint32_t count = 10; + struct flash_sector sectors[count]; + if (flash_area_get_sectors(fa->fa_id, &count, sectors) != 0) { + printk("Unable to get sectors\n"); + } else { + for (int i = 0; i < count; i++) { + printk(" 0x%lx 0x%x\n", sectors[i].fs_off, sectors[i].fs_size); + } + } +} + +void supervisor_flash_init(void) { + if (filesystem_area != NULL) { + return; + } + + #if FIXED_PARTITION_EXISTS(CIRCUITPY_PARTITION) + int open_res = flash_area_open(FIXED_PARTITION_ID(CIRCUITPY_PARTITION), &filesystem_area); + if (open_res != 0) { + printk("Unable to open CIRCUITPY flash area: %d\n", open_res); + } + #else + // Use spi_nor if it exists and no + // flash_area_open(FIXED_PARTITION_ID(storage_partition), &filesystem_area); + // printk("flash area %d %d\n", filesystem_area->fa_id, filesystem_area->fa_size); + printk("hello from flash init\n"); + bool covered_by_areas[circuitpy_flash_device_count]; + flash_area_foreach(fa_cb, covered_by_areas); + for (int i = 0; i < circuitpy_flash_device_count; i++) { + const struct device *d = flashes[i]; + + printk("flash %p %s\n", d, d->name); + if (!device_is_ready(d)) { + printk(" not ready\n"); + continue; + } + if (covered_by_areas[i]) { + printk(" covered by flash area\n"); + continue; + } + if (d->api == NULL) { + printk(" no api\n"); + continue; + } + size_t page_count = flash_get_page_count(d); + printk(" %d pages\n", page_count); + if (page_count == 0) { + continue; + } + struct flash_pages_info first_info; + flash_get_page_info_by_idx(d, 0, &first_info); + printk(" page 0: %lx %x\n", first_info.start_offset, first_info.size); + struct flash_pages_info last_info; + flash_get_page_info_by_idx(d, page_count - 1, &last_info); + printk(" page %d: %lx %x\n", page_count - 1, last_info.start_offset, last_info.size); + + // Assume uniform page sizes if the first and last are the same size. + size_t uniform_page_count; + if (first_info.size == last_info.size) { + uniform_page_count = page_count; + } else { + for (size_t i = 1; i < page_count; i++) { + struct flash_pages_info info; + flash_get_page_info_by_idx(d, i, &info); + if (info.size != first_info.size) { + uniform_page_count = i; + break; + } + } + } + if (uniform_page_count * first_info.size < 64 * 1024) { + printk("Uniform region too small\n"); + continue; + } + + printk(" %d uniform pages\n", uniform_page_count); + _page_size = first_info.size; + + _dynamic_area.fa_dev = d; + _dynamic_area.fa_id = 0; + _dynamic_area.fa_off = 0; + _dynamic_area.fa_size = uniform_page_count * first_info.size; + filesystem_area = &_dynamic_area; + printk("setup flash\n"); + break; + } + #endif + if (filesystem_area == NULL) { + printk("no flash found for filesystem\n"); + return; + } + + struct flash_pages_info first_info; + const struct device *d = flash_area_get_device(filesystem_area); + const struct flash_parameters *fp = flash_get_parameters(d); + _erase_value = fp->erase_value; + flash_get_page_info_by_offs(d, filesystem_area->fa_off, &first_info); + struct flash_pages_info last_info; + flash_get_page_info_by_offs(d, filesystem_area->fa_off + filesystem_area->fa_size - FILESYSTEM_BLOCK_SIZE, &last_info); + _page_size = first_info.size; + if (_page_size < FILESYSTEM_BLOCK_SIZE) { + _page_size = FILESYSTEM_BLOCK_SIZE; + } + _blocks_per_page = _page_size / FILESYSTEM_BLOCK_SIZE; + _page_mask = ~(_page_size - 1); + printk(" erase page size %d\n", _page_size); + printk(" blocks per page %d\n", _blocks_per_page); + + _row_flags = port_malloc(_blocks_per_page, false); + if (_row_flags == NULL) { + printk("Unable to allocate row flags (%d bytes)\n", _blocks_per_page); + filesystem_area = NULL; + return; + } + memset(_row_flags, 0, _blocks_per_page); + + // The last page is the scratch sector. + _scratch_page_address = last_info.start_offset - filesystem_area->fa_off; + _current_page_address = NO_PAGE_LOADED; +} + +uint32_t supervisor_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +uint32_t supervisor_flash_get_block_count(void) { + if (filesystem_area == NULL) { + return 0; + } + return _scratch_page_address / FILESYSTEM_BLOCK_SIZE; +} + + +// Read data_length's worth of bytes starting at address into data. +static bool read_flash(uint32_t address, uint8_t *data, uint32_t data_length) { + int res = flash_area_read(filesystem_area, address, data, data_length); + if (res != 0) { + printk("flash read failed: %d\n", res); + printk(" address %x length %d\n", address, data_length); + } + return res == 0; +} + +// Writes data_length's worth of bytes starting at address from data. Assumes +// that the sector that address resides in has already been erased. So make sure +// to run erase_page. +static bool write_flash(uint32_t address, const uint8_t *data, uint32_t data_length) { + int res = flash_area_write(filesystem_area, address, data, data_length); + if (res != 0) { + printk("flash write failed: %d\n", res); + printk(" address %x length %d\n", address, data_length); + } + return res == 0; +} + +static bool block_erased(uint32_t sector_address) { + uint8_t short_buffer[4]; + if (read_flash(sector_address, short_buffer, 4)) { + if (!_buffer_is_erased(short_buffer, 4)) { + return false; + } + } else { + return false; + } + + // Now check the full length. + uint8_t full_buffer[FILESYSTEM_BLOCK_SIZE]; + if (read_flash(sector_address, full_buffer, FILESYSTEM_BLOCK_SIZE)) { + if (!_buffer_is_erased(full_buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; + } + } else { + return false; + } + return true; +} + +// Erases the given sector. Make sure you copied all of the data out of it you +// need! Also note, sector_address is really 24 bits. +static bool erase_page(uint32_t sector_address) { + int res = flash_area_erase(filesystem_area, sector_address, _page_size); + if (res != 0) { + printk("Erase of %d failed: %d\n", sector_address, res); + } + return res == 0; +} + +static bool copy_block(uint32_t src_address, uint32_t dest_address) { + uint8_t buffer[FILESYSTEM_BLOCK_SIZE]; + if (!read_flash(src_address, buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; + } + if (!write_flash(dest_address, buffer, FILESYSTEM_BLOCK_SIZE)) { + return false; + } + return true; +} + +// Load a block into the ram cache and set its flags. Returns false on read error. +static bool _load_block_into_cache(size_t block_index) { + if (!read_flash(_current_page_address + block_index * FILESYSTEM_BLOCK_SIZE, + flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE)) { + return false; + } + _row_flags[block_index] |= ROW_LOADED; + if (_buffer_is_erased(flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE)) { + _row_flags[block_index] |= ROW_ERASED; + } + return true; +} + +// Flush the cache that was written to the scratch portion of flash. Only used +// when ram is tight. +static bool flush_scratch_flash(void) { + if (_current_page_address == NO_PAGE_LOADED) { + return true; + } + // First, copy out any blocks that we haven't touched from the sector we've + // cached. + bool copy_to_scratch_ok = true; + for (size_t i = 0; i < _blocks_per_page; i++) { + if (!(_row_flags[i] & ROW_DIRTY)) { + copy_to_scratch_ok = copy_to_scratch_ok && + copy_block(_current_page_address + i * FILESYSTEM_BLOCK_SIZE, + _scratch_page_address + i * FILESYSTEM_BLOCK_SIZE); + } + _row_flags[i] |= ROW_LOADED; + } + if (!copy_to_scratch_ok) { + // TODO(tannewt): Do more here. We opted to not erase and copy bad data + // in. We still risk losing the data written to the scratch sector. + return false; + } + // Second, erase the current sector. + erase_page(_current_page_address); + // Finally, copy the new version into it. + for (size_t i = 0; i < _blocks_per_page; i++) { + copy_block(_scratch_page_address + i * FILESYSTEM_BLOCK_SIZE, + _current_page_address + i * FILESYSTEM_BLOCK_SIZE); + } + return true; +} + +// Free all entries in the partially or completely filled flash_cache_table, and then free the table itself. +static void release_ram_cache(void) { + if (flash_cache_table == NULL) { + return; + } + + for (size_t i = 0; i < FLASH_CACHE_TABLE_NUM_ENTRIES; i++) { + // Table may not be completely full. Stop at first NULL entry. + if (flash_cache_table[i] == NULL) { + break; + } + port_free(flash_cache_table[i]); + } + port_free(flash_cache_table); + flash_cache_table = NULL; + _current_page_address = NO_PAGE_LOADED; + _clear_row_flags(); +} + +// Attempts to allocate a new set of page buffers for caching a full sector in +// ram. Each page is allocated separately so that the GC doesn't need to provide +// one huge block. We can free it as we write if we want to also. +static bool allocate_ram_cache(void) { + flash_cache_table = port_malloc(FLASH_CACHE_TABLE_SIZE, false); + if (flash_cache_table == NULL) { + printk("Unable to allocate ram cache table\n"); + return false; + } + + // Clear all the entries so it's easy to find the last entry. + memset(flash_cache_table, 0, FLASH_CACHE_TABLE_SIZE); + + bool success = true; + for (size_t i = 0; i < _blocks_per_page && success; i++) { + uint8_t *block_cache = port_malloc(FILESYSTEM_BLOCK_SIZE, false); + if (block_cache == NULL) { + success = false; + break; + } + flash_cache_table[i] = block_cache; + } + + // We couldn't allocate enough so give back what we got. + if (!success) { + printk("Unable to allocate ram cache pages\n"); + release_ram_cache(); + } + _clear_row_flags(); + _current_page_address = NO_PAGE_LOADED; + return success; +} + +// Flush the cached sector from ram onto the flash. We'll free the cache unless +// keep_cache is true. +static bool flush_ram_cache(bool keep_cache) { + if (flash_cache_table == NULL) { + // Nothing to flush because there is no cache. + return true; + } + + if (_current_page_address == NO_PAGE_LOADED || !_any_dirty()) { + if (!keep_cache) { + release_ram_cache(); + } + return true; + } + // First, copy out any blocks that we haven't touched from the sector + // we've cached. If we don't do this we'll erase the data during the sector + // erase below. + bool copy_to_ram_ok = true; + for (size_t i = 0; i < _blocks_per_page; i++) { + if (!(_row_flags[i] & ROW_LOADED)) { + if (!_load_block_into_cache(i)) { + copy_to_ram_ok = false; + break; + } + } + } + + if (!copy_to_ram_ok) { + return false; + } + // Second, erase the current sector. + erase_page(_current_page_address); + // Lastly, write all the data in ram that we've cached. + for (size_t i = 0; i < _blocks_per_page; i++) { + // Skip blocks that are entirely erased — the page erase already + // set them to 0xFF so writing would be redundant. + if (_row_flags[i] & ROW_ERASED) { + continue; + } + write_flash(_current_page_address + i * FILESYSTEM_BLOCK_SIZE, + flash_cache_table[i], + FILESYSTEM_BLOCK_SIZE); + } + // Nothing is dirty anymore. Clear dirty but keep loaded and erased. + for (size_t i = 0; i < _blocks_per_page; i++) { + _row_flags[i] &= ~ROW_DIRTY; + } + + // We're done with the cache for now so give it back. + if (!keep_cache) { + release_ram_cache(); + } + return true; +} + +// Delegates to the correct flash flush method depending on the existing cache. +// TODO Don't blink the status indicator if we don't actually do any writing (hard to tell right now). +static void _flush_keep_cache(bool keep_cache) { + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, true); + #endif + // If we've cached to the flash itself flush from there. + if (flash_cache_table == NULL) { + flush_scratch_flash(); + } else { + flush_ram_cache(keep_cache); + } + #ifdef MICROPY_HW_LED_MSC + port_pin_set_output_level(MICROPY_HW_LED_MSC, false); + #endif +} + +void port_internal_flash_flush(void) { + if (filesystem_area == NULL) { + return; + } + k_mutex_lock(&_mutex, K_FOREVER); + _flush_keep_cache(true); + k_mutex_unlock(&_mutex); +} + +void supervisor_flash_release_cache(void) { + if (filesystem_area == NULL) { + return; + } + k_mutex_lock(&_mutex, K_FOREVER); + _flush_keep_cache(false); + k_mutex_unlock(&_mutex); +} + +static int32_t convert_block_to_flash_addr(uint32_t block) { + if (0 <= block && block < supervisor_flash_get_block_count()) { + // a block in partition 1 + return block * FILESYSTEM_BLOCK_SIZE; + } + // bad block + return -1; +} + +static bool _flash_read_block(uint8_t *dest, uint32_t block) { + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; + } + + // Mask out the lower bits that designate the address within the sector. + uint32_t page_address = address & _page_mask; + size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % _blocks_per_page; + // We're reading from the currently cached sector. + if (_current_page_address == page_address && (_row_flags[block_index] & ROW_LOADED)) { + if (flash_cache_table != NULL) { + memcpy(dest, flash_cache_table[block_index], FILESYSTEM_BLOCK_SIZE); + return true; + } + uint32_t scratch_block_address = _scratch_page_address + block_index * FILESYSTEM_BLOCK_SIZE; + return read_flash(scratch_block_address, dest, FILESYSTEM_BLOCK_SIZE); + } + return read_flash(address, dest, FILESYSTEM_BLOCK_SIZE); +} + +static bool _flash_write_block(const uint8_t *data, uint32_t block) { + // Non-MBR block, copy to cache + int32_t address = convert_block_to_flash_addr(block); + if (address == -1) { + // bad block number + return false; + } + // Mask out the lower bits that designate the address within the sector. + uint32_t page_address = address & _page_mask; + size_t block_index = (address / FILESYSTEM_BLOCK_SIZE) % _blocks_per_page; + // Flush the cache if we're moving onto a different page. + if (_current_page_address != page_address) { + // Check to see if we'd write to an erased block and aren't writing to + // our cache. In that case we can write directly. + if (block_erased(address)) { + return write_flash(address, data, FILESYSTEM_BLOCK_SIZE); + } + if (_current_page_address != NO_PAGE_LOADED) { + supervisor_flash_flush(); + } + if (flash_cache_table == NULL && !allocate_ram_cache()) { + erase_page(_scratch_page_address); + } + _current_page_address = page_address; + _clear_row_flags(); + } + _row_flags[block_index] = ROW_DIRTY | ROW_LOADED; + // Copy the block to the appropriate cache. + if (flash_cache_table != NULL) { + memcpy(flash_cache_table[block_index], data, FILESYSTEM_BLOCK_SIZE); + return true; + } else { + uint32_t scratch_block_address = _scratch_page_address + block_index * FILESYSTEM_BLOCK_SIZE; + return write_flash(scratch_block_address, data, FILESYSTEM_BLOCK_SIZE); + } +} + +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { + if (filesystem_area == NULL) { + return 1; + } + k_mutex_lock(&_mutex, K_FOREVER); + for (size_t i = 0; i < num_blocks; i++) { + if (!_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block + i)) { + k_mutex_unlock(&_mutex); + printk("error reading block %04d\n", block + i); + return 1; // error + } + } + k_mutex_unlock(&_mutex); + return 0; // success +} + +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block, uint32_t num_blocks) { + if (filesystem_area == NULL) { + return 1; + } + k_mutex_lock(&_mutex, K_FOREVER); + for (size_t i = 0; i < num_blocks; i++) { + if (!_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block + i)) { + printk("error writing block %04d\n", block + i); + k_mutex_unlock(&_mutex); + return 1; // error + } + } + k_mutex_unlock(&_mutex); + return 0; // success +} diff --git a/ports/zephyr-cp/supervisor/internal_flash.h b/ports/zephyr-cp/supervisor/internal_flash.h new file mode 100644 index 0000000000000..32a77a63a9bbd --- /dev/null +++ b/ports/zephyr-cp/supervisor/internal_flash.h @@ -0,0 +1,14 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George +// +// SPDX-License-Identifier: MIT +#pragma once + +#include +#include + +#include "py/mpconfig.h" + +#define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms +#define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) diff --git a/ports/zephyr-cp/supervisor/port.c b/ports/zephyr-cp/supervisor/port.c new file mode 100644 index 0000000000000..047a4efe8bf01 --- /dev/null +++ b/ports/zephyr-cp/supervisor/port.c @@ -0,0 +1,397 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/port.h" + +#include "mpconfigboard.h" +#include "supervisor/shared/tick.h" + +#if CIRCUITPY_AUDIOBUSIO_I2SOUT +#include "common-hal/audiobusio/I2SOut.h" +#endif + +#include +#include +#include +#include + +#if defined(CONFIG_ARCH_POSIX) +#include +#include + +#include "cmdline.h" +#include "posix_board_if.h" +#include "posix_native_task.h" +#endif + +#include "lib/tlsf/tlsf.h" +#include +#include + +#if defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +#include "perfetto_encoder.h" +#include +#define CIRCUITPY_PERFETTO_TRACK_GROUP_UUID 0x3000ULL +#define CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID 0x3001ULL +#define CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID 0x3002ULL +#endif + +static tlsf_t heap; +static size_t tlsf_heap_used = 0; + +// Auto generated in pins.c +extern const struct device *const rams[]; +extern const uint32_t *const ram_bounds[]; +extern const size_t circuitpy_max_ram_size; + +static pool_t pools[CIRCUITPY_RAM_DEVICE_COUNT]; +static uint8_t valid_pool_count = 0; +static bool zephyr_malloc_active = false; +static void *zephyr_malloc_top = NULL; +static void *zephyr_malloc_bottom = NULL; + +static K_EVENT_DEFINE(main_needed); + +static struct k_timer tick_timer; + +#if defined(CONFIG_ARCH_POSIX) +// Number of VM runs before exiting. +// <= 0 means run forever. +// INT32_MAX means option was not provided. +static int32_t native_sim_vm_runs = INT32_MAX; +static uint32_t native_sim_reset_port_count = 0; + +static struct args_struct_t native_sim_reset_port_args[] = { + { + .option = "vm-runs", + .name = "count", + .type = 'i', + .dest = &native_sim_vm_runs, + .descript = "Exit native_sim after this many VM runs. " + "Example: --vm-runs=2" + }, + ARG_TABLE_ENDMARKER +}; + +static void native_sim_register_cmdline_opts(void) { + native_add_command_line_opts(native_sim_reset_port_args); +} + +NATIVE_TASK(native_sim_register_cmdline_opts, PRE_BOOT_1, 0); +#endif + +#if defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +static bool perfetto_circuitpython_tracks_emitted; + +static void perfetto_emit_outer_heap_stats(void) { + if (!perfetto_start()) { + return; + } + size_t total = tlsf_heap_used; + #if defined(CONFIG_COMMON_LIBC_MALLOC) && defined(CONFIG_SYS_HEAP_RUNTIME_STATS) + extern int malloc_runtime_stats_get(struct sys_memory_stats *stats); + struct sys_memory_stats stats; + if (malloc_runtime_stats_get(&stats) == 0) { + total += stats.allocated_bytes; + } + #endif + perfetto_emit_counter(CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID, (int64_t)total); + Z_SPIN_DELAY(1); +} + +static void perfetto_emit_circuitpython_tracks(void) { + if (perfetto_circuitpython_tracks_emitted) { + return; + } + if (!perfetto_start()) { + return; + } + perfetto_emit_track_descriptor(CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + perfetto_get_process_uuid(), + "CircuitPython"); + perfetto_emit_counter_track_descriptor(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, + CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + "VM Heap Used", + PERFETTO_COUNTER_UNIT_BYTES); + perfetto_emit_counter_track_descriptor(CIRCUITPY_PERFETTO_OUTER_HEAP_USED_UUID, + CIRCUITPY_PERFETTO_TRACK_GROUP_UUID, + "Outer Heap Used", + PERFETTO_COUNTER_UNIT_BYTES); + perfetto_circuitpython_tracks_emitted = true; +} +#else +static inline void perfetto_emit_outer_heap_stats(void) { +} + +static inline void perfetto_emit_circuitpython_tracks(void) { +} +#endif + +static void _tick_function(struct k_timer *timer_id) { + supervisor_tick(); +} + +safe_mode_t port_init(void) { + // We run CircuitPython at the lowest priority (just higher than idle.) + // This allows networking and USB to preempt us. + k_thread_priority_set(k_current_get(), CONFIG_NUM_PREEMPT_PRIORITIES - 1); + k_timer_init(&tick_timer, _tick_function, NULL); + perfetto_emit_circuitpython_tracks(); + return SAFE_MODE_NONE; +} + +// Reset the microcontroller completely. +void reset_cpu(void) { + // Try a warm reboot first. It won't return if it works but isn't always + // implemented. + sys_reboot(SYS_REBOOT_WARM); + sys_reboot(SYS_REBOOT_COLD); + printk("Failed to reboot. Looping.\n"); + while (true) { + } +} + +void reset_port(void) { + #if CIRCUITPY_AUDIOBUSIO_I2SOUT + i2sout_reset(); + #endif + + #if defined(CONFIG_ARCH_POSIX) + native_sim_reset_port_count++; + if (native_sim_vm_runs != INT32_MAX && + native_sim_vm_runs > 0 && + native_sim_reset_port_count >= (uint32_t)(native_sim_vm_runs + 1)) { + printk("posix: exiting after %d VM runs\n", native_sim_vm_runs); + posix_exit(0); + } + #endif +} + +void reset_to_bootloader(void) { + reset_cpu(); +} + +void port_wake_main_task(void) { + k_event_set(&main_needed, 1); +} + +void port_wake_main_task_from_isr(void) { + k_event_set(&main_needed, 1); +} + +void port_task_yield(void) { + k_yield(); +} + +void port_task_sleep_ms(uint32_t msecs) { + k_msleep(msecs); +} + +void port_boot_info(void) { +} + +// Get stack limit address +uint32_t *port_stack_get_limit(void) { + return (uint32_t *)k_current_get()->stack_info.start; +} + +// Get stack top address +uint32_t *port_stack_get_top(void) { + _thread_stack_info_t stack_info = k_current_get()->stack_info; + + return (uint32_t *)(stack_info.start + stack_info.size - stack_info.delta); +} + +// Save and retrieve a word from memory that is preserved over reset. Used for safe mode. +void port_set_saved_word(uint32_t) { + +} +uint32_t port_get_saved_word(void) { + return 0; +} + +uint64_t port_get_raw_ticks(uint8_t *subticks) { + // Make sure time advances in the simulator. + #if defined(CONFIG_ARCH_POSIX) + k_busy_wait(100); + #endif + int64_t uptime = k_uptime_ticks() * 32768 / CONFIG_SYS_CLOCK_TICKS_PER_SEC; + if (subticks != NULL) { + *subticks = uptime % 32; + } + return uptime / 32; +} + +// Enable 1/1024 second tick. +void port_enable_tick(void) { + k_timer_start(&tick_timer, K_USEC(1000000 / 1024), K_USEC(1000000 / 1024)); +} + +// Disable 1/1024 second tick. +void port_disable_tick(void) { + k_timer_stop(&tick_timer); +} + +static k_timeout_t next_timeout; +static k_timepoint_t next_timepoint; + +void port_interrupt_after_ticks(uint32_t ticks) { + size_t zephyr_ticks = ticks * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1024; + k_timeout_t maybe_next_timeout = K_TIMEOUT_ABS_TICKS(k_uptime_ticks() + zephyr_ticks); + k_timepoint_t maybe_next_timepoint = sys_timepoint_calc(maybe_next_timeout); + if (sys_timepoint_cmp(maybe_next_timepoint, next_timepoint) < 0) { + next_timeout = maybe_next_timeout; + next_timepoint = maybe_next_timepoint; + } +} + +void port_idle_until_interrupt(void) { + k_event_wait(&main_needed, 0xffffffff, true, next_timeout); + next_timeout = K_FOREVER; + next_timepoint = sys_timepoint_calc(next_timeout); +} + +// Zephyr doesn't maintain one multi-heap. So, make our own using TLSF. +void port_heap_init(void) { + // Do a test malloc to determine if Zephyr has an outer heap that may + // overlap with a memory region we've identified in ram_bounds. We'll + // corrupt each other if we both use it. + #ifdef CONFIG_COMMON_LIBC_MALLOC + uint32_t *test_malloc = malloc(32); + free(test_malloc); // Free right away so we don't forget. We don't actually write it anyway. + zephyr_malloc_active = test_malloc != NULL; + #endif + + for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { + uint32_t *heap_bottom = ram_bounds[2 * i]; + uint32_t *heap_top = ram_bounds[2 * i + 1]; + size_t size = (heap_top - heap_bottom) * sizeof(uint32_t); + // The linker script may fill up a region we thought we could use at + // build time. (The ram_bounds values are sometimes determined by the + // linker.) So, we need to guard against regions that aren't actually + // free. + if (size < 1024) { + printk("Skipping region because the linker filled it up.\n"); + continue; + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + // Skip a ram region if our test malloc is within it. We'll use Zephyr's + // malloc to share that space with Zephyr. + if (heap_bottom <= test_malloc && test_malloc < heap_top) { + zephyr_malloc_top = heap_top; + zephyr_malloc_bottom = heap_bottom; + printk("Skipping region because Zephyr malloc is within bounds\n"); + pools[i] = NULL; + continue; + } + #endif + + printk("Init heap at %p - %p with size %d\n", heap_bottom, heap_top, size); + // If this crashes, then make sure you've enabled all of the Kconfig needed for the drivers. + if (valid_pool_count == 0) { + heap = tlsf_create_with_pool(heap_bottom, size, circuitpy_max_ram_size); + pools[i] = tlsf_get_pool(heap); + } else { + pools[i] = tlsf_add_pool(heap, heap_bottom + 1, size - sizeof(uint32_t)); + } + valid_pool_count++; + } + perfetto_emit_outer_heap_stats(); + #if !DT_HAS_CHOSEN(zephyr_sram) + #error "No SRAM!" + #endif +} + +void *port_malloc(size_t size, bool dma_capable) { + void *block = NULL; + if (valid_pool_count > 0) { + block = tlsf_malloc(heap, size); + } + if (block != NULL) { + tlsf_heap_used += tlsf_block_size(block); + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + if (block == NULL) { + block = malloc(size); + } + #endif + if (block != NULL) { + perfetto_emit_outer_heap_stats(); + } + return block; +} + +void port_free(void *ptr) { + if (ptr == NULL) { + return; + } + if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top)) { + tlsf_heap_used -= tlsf_block_size(ptr); + tlsf_free(heap, ptr); + } else { + #ifdef CONFIG_COMMON_LIBC_MALLOC + free(ptr); + #endif + } + perfetto_emit_outer_heap_stats(); +} + +void *port_realloc(void *ptr, size_t size, bool dma_capable) { + if (ptr == NULL) { + return port_malloc(size, dma_capable); + } + if (valid_pool_count > 0 && !(ptr >= zephyr_malloc_bottom && ptr < zephyr_malloc_top)) { + size_t old_size = tlsf_block_size(ptr); + void *new_block = tlsf_realloc(heap, ptr, size); + if (new_block != NULL) { + tlsf_heap_used = tlsf_heap_used - old_size + tlsf_block_size(new_block); + perfetto_emit_outer_heap_stats(); + } + return new_block; + } + #ifdef CONFIG_COMMON_LIBC_MALLOC + void *new_block = realloc(ptr, size); + if (new_block != NULL) { + perfetto_emit_outer_heap_stats(); + } + return new_block; + #endif + return NULL; +} + +static bool max_size_walker(void *ptr, size_t size, int used, void *user) { + size_t *max_size = (size_t *)user; + if (!used && *max_size < size) { + *max_size = size; + } + return true; +} + +size_t port_heap_get_largest_free_size(void) { + size_t max_size = 0; + if (valid_pool_count > 0) { + for (size_t i = 0; i < CIRCUITPY_RAM_DEVICE_COUNT; i++) { + if (pools[i] == NULL) { + continue; + } + tlsf_walk_pool(pools[i], max_size_walker, &max_size); + } + // IDF does this. Not sure why. + return tlsf_fit_size(heap, max_size); + } + return 64 * 1024; +} + +void assert_post_action(const char *file, unsigned int line) { + // printk("Assertion failed at %s:%u\n", file, line); + // Check that this is arm + #if defined(__arm__) + __asm__ ("bkpt"); + #endif + while (1) { + ; + } +} diff --git a/ports/zephyr-cp/supervisor/serial.c b/ports/zephyr-cp/supervisor/serial.c new file mode 100644 index 0000000000000..3ae3e73fa10c1 --- /dev/null +++ b/ports/zephyr-cp/supervisor/serial.c @@ -0,0 +1,85 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/shared/serial.h" + +#include "supervisor/zephyr-cp.h" + +#if CIRCUITPY_USB_DEVICE == 1 +#include "shared-bindings/usb_cdc/Serial.h" +usb_cdc_serial_obj_t *usb_console; +#else +#include "shared-bindings/busio/UART.h" +static busio_uart_obj_t uart_console; +static uint8_t buffer[64]; +#endif + +void port_serial_early_init(void) { + #if CIRCUITPY_USB_DEVICE == 0 + uart_console.base.type = &busio_uart_type; + common_hal_busio_uart_construct_from_device(&uart_console, DEVICE_DT_GET(DT_CHOSEN(zephyr_console)), sizeof(buffer), buffer); + #endif +} + +void port_serial_init(void) { + #if CIRCUITPY_USB_DEVICE == 1 + usb_console = usb_cdc_serial_get_console(); + #endif +} + +bool port_serial_connected(void) { + #if CIRCUITPY_USB_DEVICE == 1 + if (usb_console == NULL) { + return false; + } + return common_hal_usb_cdc_serial_get_connected(usb_console); + #else + return true; + #endif +} + +char port_serial_read(void) { + #if CIRCUITPY_USB_DEVICE == 1 + if (usb_console == NULL) { + return -1; + } + char buf[1]; + size_t count = common_hal_usb_cdc_serial_read(usb_console, buf, 1, NULL); + if (count == 0) { + return -1; + } + return buf[0]; + #else + char buf[1]; + size_t count = common_hal_busio_uart_read(&uart_console, buf, 1, NULL); + if (count == 0) { + return -1; + } + return buf[0]; + #endif +} + +uint32_t port_serial_bytes_available(void) { + #if CIRCUITPY_USB_DEVICE == 1 + if (usb_console == NULL) { + return 0; + } + return common_hal_usb_cdc_serial_get_in_waiting(usb_console); + #else + return common_hal_busio_uart_rx_characters_available(&uart_console); + #endif +} + +void port_serial_write_substring(const char *text, uint32_t length) { + #if CIRCUITPY_USB_DEVICE == 1 + if (usb_console == NULL) { + return; + } + common_hal_usb_cdc_serial_write(usb_console, text, length, NULL); + #else + common_hal_busio_uart_write(&uart_console, text, length, NULL); + #endif +} diff --git a/ports/zephyr-cp/supervisor/usb.c b/ports/zephyr-cp/supervisor/usb.c new file mode 100644 index 0000000000000..a42a5192f4f30 --- /dev/null +++ b/ports/zephyr-cp/supervisor/usb.c @@ -0,0 +1,380 @@ +#include "supervisor/usb.h" + +#include "shared-bindings/usb_cdc/__init__.h" +#include "shared-bindings/usb_cdc/Serial.h" + +#include "supervisor/zephyr-cp.h" + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "lib/oofatfs/diskio.h" +#include "lib/oofatfs/ff.h" + +#include +#include +#include +#include +#include +#include + +#include "shared-module/storage/__init__.h" +#include "supervisor/filesystem.h" +#include "supervisor/shared/reload.h" + +#include +LOG_MODULE_REGISTER(cpusb, CONFIG_LOG_DEFAULT_LEVEL); + +#define USB_DEVICE DT_NODELABEL(zephyr_udc0) + +USBD_DEVICE_DEFINE(main_usbd, + DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), + USB_VID, USB_PID); + +USBD_DESC_LANG_DEFINE(main_lang); +USBD_DESC_MANUFACTURER_DEFINE(main_mfr, USB_MANUFACTURER); +USBD_DESC_PRODUCT_DEFINE(main_product, USB_PRODUCT); + +USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration"); +USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration"); + +/* doc configuration instantiation start */ +static const uint8_t attributes = 0; + +USBD_CONFIGURATION_DEFINE(main_fs_config, + attributes, + 100, &fs_cfg_desc); + +USBD_CONFIGURATION_DEFINE(main_hs_config, + attributes, + 100, &hs_cfg_desc); + +static usb_cdc_serial_obj_t usb_cdc_console_obj; +static usb_cdc_serial_obj_t usb_cdc_data_obj; + +#ifndef USBD_DEFINE_MSC_LUN +#error "MSC not enabled" +#endif + +#define LUN_COUNT 1 +#define MSC_FLASH_BLOCK_SIZE 512 + +// The ellipsis range in the designated initializer of `ejected` is not standard C, +// but it works in both gcc and clang. +static bool locked[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; + +// Set to true if a write was in a file data or metadata area, +// as opposed to in the filesystem metadata area (e.g., dirty bit). +// Used to determine if an auto-reload is warranted. +static bool content_write[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; + +int _zephyr_disk_init(struct disk_info *disk); +int _zephyr_disk_status(struct disk_info *disk); +int _zephyr_disk_read(struct disk_info *disk, uint8_t *data_buf, uint32_t start_sector, uint32_t num_sector); +int _zephyr_disk_write(struct disk_info *disk, const uint8_t *data_buf, uint32_t start_sector, uint32_t num_sector); +int _zephyr_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff); + +static const struct disk_operations disk_ops = { + .init = _zephyr_disk_init, + .status = _zephyr_disk_status, + .read = _zephyr_disk_read, + .write = _zephyr_disk_write, + .ioctl = _zephyr_disk_ioctl, +}; + +static struct disk_info circuitpy_disk = { + .name = "CIRCUITPY", + .ops = &disk_ops, + .dev = NULL +}; + +USBD_DEFINE_MSC_LUN(circuitpy_lun, "CIRCUITPY", "Zephyr", "FlashDisk", "0.00"); + + +int _zephyr_disk_init(struct disk_info *disk) { + printk("Initializing disk\n"); + return 0; +} + +int _zephyr_disk_status(struct disk_info *disk) { + fs_user_mount_t *root = filesystem_circuitpy(); + int lun = 0; + if (root == NULL) { + printk("Status: No media\n"); + return DISK_STATUS_NOMEDIA; + } + if (!filesystem_is_writable_by_usb(root)) { + printk("Status: Read-only\n"); + return DISK_STATUS_WR_PROTECT; + } + // Lock the blockdev once we say we're writable. + if (!locked[lun] && !blockdev_lock(root)) { + printk("Status: Locked\n"); + return DISK_STATUS_WR_PROTECT; + } + locked[lun] = true; + return DISK_STATUS_OK; +} + +int _zephyr_disk_read(struct disk_info *disk, uint8_t *data_buf, uint32_t start_sector, uint32_t num_sector) { + fs_user_mount_t *root = filesystem_circuitpy(); + + uint32_t disk_block_count; + disk_ioctl(root, GET_SECTOR_COUNT, &disk_block_count); + + if (start_sector + num_sector > disk_block_count) { + return -EIO; + } + disk_read(root, data_buf, start_sector, num_sector); + return 0; +} + +int _zephyr_disk_write(struct disk_info *disk, const uint8_t *data_buf, uint32_t start_sector, uint32_t num_sector) { + fs_user_mount_t *root = filesystem_circuitpy(); + int lun = 0; + autoreload_suspend(AUTORELOAD_SUSPEND_USB); + disk_write(root, data_buf, start_sector, num_sector); + // Since by getting here we assume the mount is read-only to + // CircuitPython let's update the cached FatFs sector if it's the one + // we just wrote. + if + #if FF_MAX_SS != FF_MIN_SS + (root->fatfs.ssize == MSC_FLASH_BLOCK_SIZE) + #else + // The compiler can optimize this away. + (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE) + #endif + { + if (start_sector == root->fatfs.winsect && start_sector > 0) { + memcpy(root->fatfs.win, + data_buf + MSC_FLASH_BLOCK_SIZE * (root->fatfs.winsect - start_sector), + MSC_FLASH_BLOCK_SIZE); + } + } + + // A write to an lba below fatbase is in the filesystem metadata (BPB) area or the "Reserved Region", + // and is probably setting or clearing the dirty bit. This should not trigger auto-reload. + // All other writes will trigger auto-reload. + if (start_sector >= root->fatfs.fatbase) { + content_write[lun] = true; + } + return 0; +} + +int _zephyr_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) { + + fs_user_mount_t *root = filesystem_circuitpy(); + int lun = 0; + switch (cmd) { + case DISK_IOCTL_GET_SECTOR_COUNT: + disk_ioctl(root, GET_SECTOR_COUNT, buff); + return 0; + case DISK_IOCTL_GET_SECTOR_SIZE: + disk_ioctl(root, GET_SECTOR_SIZE, buff); + return 0; + case DISK_IOCTL_CTRL_SYNC: + disk_ioctl(root, CTRL_SYNC, buff); + autoreload_resume(AUTORELOAD_SUSPEND_USB); + + // This write is complete; initiate an autoreload if this was a file data or metadata write, + // not just a dirty-bit write. + if (content_write[lun] && lun == 0) { + autoreload_trigger(); + content_write[lun] = false; + } + return 0; + default: + printk("Unsupported disk ioctl %02x\n", cmd); + return -ENOTSUP; + } + return 0; +} + +static void _msg_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) { + LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); + + if (usbd_can_detect_vbus(ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(ctx)) { + LOG_ERR("Failed to enable device support"); + } + } + + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(ctx)) { + LOG_ERR("Failed to disable device support"); + } + } + } +} + +void usb_init(void) { + printk("Initializing USB\n"); + int err; + + printk("Adding language descriptor\n"); + err = usbd_add_descriptor(&main_usbd, &main_lang); + if (err) { + LOG_ERR("Failed to initialize language descriptor (%d)", err); + return; + } + + err = usbd_add_descriptor(&main_usbd, &main_mfr); + if (err) { + LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err); + return; + } + + err = usbd_add_descriptor(&main_usbd, &main_product); + if (err) { + LOG_ERR("Failed to initialize product descriptor (%d)", err); + return; + } + + bool console = usb_cdc_console_enabled(); + if (console) { + uint8_t *receiver_buffer = port_malloc(128, true); + if (receiver_buffer != NULL) { + common_hal_usb_cdc_serial_construct_from_device(&usb_cdc_console_obj, DEVICE_DT_GET(DT_NODELABEL(cdc_acm_console)), 128, receiver_buffer); + } else { + console = false; + } + } + usb_cdc_set_console(console ? MP_OBJ_FROM_PTR(&usb_cdc_console_obj) : mp_const_none); + + bool data = usb_cdc_data_enabled(); + if (data) { + uint8_t *receiver_buffer = port_malloc(128, true); + if (receiver_buffer != NULL) { + common_hal_usb_cdc_serial_construct_from_device(&usb_cdc_data_obj, DEVICE_DT_GET(DT_NODELABEL(cdc_acm_data)), 128, receiver_buffer); + } else { + data = false; + } + } + usb_cdc_set_data(data ? MP_OBJ_FROM_PTR(&usb_cdc_data_obj) : mp_const_none); + + err = disk_access_register(&circuitpy_disk); + if (err) { + printk("Failed to register disk access %d\n", err); + return; + } + + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_caps_speed(&main_usbd) == USBD_SPEED_HS) { + printk("Adding High-Speed configuration\n"); + err = usbd_add_configuration(&main_usbd, USBD_SPEED_HS, + &main_hs_config); + if (err) { + LOG_ERR("Failed to add High-Speed configuration"); + return; + } + + printk("Registering High-Speed cdc_acm class\n"); + if (usb_cdc_console_enabled()) { + err = usbd_register_class(&main_usbd, "cdc_acm_0", USBD_SPEED_HS, 1); + if (err) { + printk("Failed to add register classes %d\n", err); + return; + } + } + + if (usb_cdc_data_enabled()) { + err = usbd_register_class(&main_usbd, "cdc_acm_1", USBD_SPEED_HS, 1); + if (err) { + printk("Failed to add register classes %d\n", err); + return; + } + } + + err = usbd_register_class(&main_usbd, "msc_0", USBD_SPEED_HS, 1); + if (err) { + printk("Failed to add register MSC class %d\n", err); + return; + } else { + printk("Registered MSC class for high speed\n"); + } + + usbd_device_set_code_triple(&main_usbd, USBD_SPEED_HS, + USB_BCC_MISCELLANEOUS, 0x02, 0x01); + } + + /* doc configuration register start */ + printk("Adding Full-Speed configuration\n"); + err = usbd_add_configuration(&main_usbd, USBD_SPEED_FS, + &main_fs_config); + if (err) { + LOG_ERR("Failed to add Full-Speed configuration"); + return; + } + /* doc configuration register end */ + + /* doc functions register start */ + + if (usb_cdc_console_enabled()) { + printk("Registering Full-Speed cdc_acm class\n"); + err = usbd_register_class(&main_usbd, "cdc_acm_0", USBD_SPEED_FS, 1); + if (err) { + printk("Failed to add register classes\n"); + return; + } + } + + if (usb_cdc_data_enabled()) { + printk("Registering Full-Speed cdc_acm class\n"); + err = usbd_register_class(&main_usbd, "cdc_acm_1", USBD_SPEED_FS, 1); + if (err) { + printk("Failed to add register classes\n"); + return; + } + } + + err = usbd_register_class(&main_usbd, "msc_0", USBD_SPEED_FS, 1); + if (err) { + printk("Failed to add register MSC class %d\n", err); + return; + } + /* doc functions register end */ + + usbd_device_set_code_triple(&main_usbd, USBD_SPEED_FS, + USB_BCC_MISCELLANEOUS, 0x02, 0x01); + printk("Setting self powered\n"); + usbd_self_powered(&main_usbd, attributes & USB_SCD_SELF_POWERED); + + printk("Registering callback\n"); + err = usbd_msg_register_cb(&main_usbd, _msg_cb); + if (err) { + LOG_ERR("Failed to register message callback"); + return; + } + + printk("usbd_init\n"); + err = usbd_init(&main_usbd); + if (err) { + LOG_ERR("Failed to initialize device support"); + return; + } + + printk("USB initialized\n"); + + if (!usbd_can_detect_vbus(&main_usbd)) { + err = usbd_enable(&main_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return; + } + printk("usbd enabled\n"); + } +} + +bool usb_connected(void) { + return false; +} + +void usb_disconnect(void) { +} + +usb_cdc_serial_obj_t *usb_cdc_serial_get_console(void) { + if (usb_cdc_console_enabled()) { + return &usb_cdc_console_obj; + } + return NULL; +} diff --git a/ports/zephyr-cp/supervisor/zephyr-cp.h b/ports/zephyr-cp/supervisor/zephyr-cp.h new file mode 100644 index 0000000000000..ecf7d42e3b48c --- /dev/null +++ b/ports/zephyr-cp/supervisor/zephyr-cp.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/usb_cdc/Serial.h" + +usb_cdc_serial_obj_t *usb_cdc_serial_get_console(void); diff --git a/ports/zephyr-cp/sysbuild.cmake b/ports/zephyr-cp/sysbuild.cmake new file mode 100644 index 0000000000000..3c3acf0a803c7 --- /dev/null +++ b/ports/zephyr-cp/sysbuild.cmake @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) + native_simulator_set_final_executable(${DEFAULT_IMAGE}) +endif() diff --git a/ports/zephyr-cp/sysbuild.conf b/ports/zephyr-cp/sysbuild.conf new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/ports/zephyr-cp/tests/TEST_IDEAS.md b/ports/zephyr-cp/tests/TEST_IDEAS.md new file mode 100644 index 0000000000000..6ef71d7a5a041 --- /dev/null +++ b/ports/zephyr-cp/tests/TEST_IDEAS.md @@ -0,0 +1,623 @@ +# CircuitPython Simulator Test Ideas + +Test ideas for the native_sim simulator, organized by module/category. + +## Core Python / Interpreter + +### 1. Multiple file priority +Test that boot.py runs before code.py, and main.py is used as fallback when code.py doesn't exist. + +```python +# boot.py +print("boot.py ran") + +# code.py +print("code.py ran") +``` + +Expected output order: "boot.py ran" then "code.py ran" + +### 2. Exception handling +Verify tracebacks print correctly with file/line info, and exception types propagate properly. + +```python +def inner(): + raise ValueError("test error") + +def outer(): + inner() + +outer() +``` + +### 3. Memory / gc module +Test `gc.collect()`, `gc.mem_free()`, `gc.mem_alloc()`, and behavior under memory pressure. + +```python +import gc +gc.collect() +free_before = gc.mem_free() +data = [0] * 1000 +free_after = gc.mem_free() +assert free_after < free_before +del data +gc.collect() +free_final = gc.mem_free() +print("done") +``` + +### 4. Import system +Test importing frozen modules vs filesystem modules, verify import errors are clear. + +```python +import sys +import board +import digitalio +print(f"modules loaded: {len(sys.modules)}") +print("done") +``` + +--- + +## digitalio + +### 5. Input mode +Test reading GPIO input state. May require trace file injection or loopback configuration. + +```python +import board +import digitalio + +pin = digitalio.DigitalInOut(board.D0) +pin.direction = digitalio.Direction.INPUT +value = pin.value +print(f"input value: {value}") +print("done") +``` + +### 6. Pull resistors +Verify pull-up/pull-down configuration affects input readings. + +```python +import board +import digitalio + +pin = digitalio.DigitalInOut(board.D0) +pin.direction = digitalio.Direction.INPUT +pin.pull = digitalio.Pull.UP +value_up = pin.value +pin.pull = digitalio.Pull.DOWN +value_down = pin.value +print(f"pull-up: {value_up}, pull-down: {value_down}") +print("done") +``` + +### 7. Direction switching +Switch same pin between input/output modes multiple times. + +```python +import board +import digitalio + +pin = digitalio.DigitalInOut(board.D0) +pin.direction = digitalio.Direction.OUTPUT +pin.value = True +pin.direction = digitalio.Direction.INPUT +_ = pin.value +pin.direction = digitalio.Direction.OUTPUT +pin.value = False +print("done") +``` + +--- + +## time module + +### 8. time.sleep() precision +Verify sleep timing via Perfetto trace timestamps. Use GPIO transitions as timing markers. + +```python +import time +import board +import digitalio + +led = digitalio.DigitalInOut(board.LED) +led.direction = digitalio.Direction.OUTPUT + +led.value = True +time.sleep(0.05) # 50ms +led.value = False +time.sleep(0.1) # 100ms +led.value = True +time.sleep(0.05) # 50ms +led.value = False +print("done") +``` + +Verify trace shows: 50ms high, 100ms low, 50ms high pattern. + +### 9. time.monotonic() +Test monotonic clock increments correctly and never goes backward. + +```python +import time + +samples = [] +for _ in range(10): + samples.append(time.monotonic()) + time.sleep(0.01) + +# Verify monotonic increase +for i in range(1, len(samples)): + assert samples[i] > samples[i-1], "monotonic went backward!" + +elapsed = samples[-1] - samples[0] +assert 0.08 < elapsed < 0.15, f"unexpected elapsed: {elapsed}" +print("done") +``` + +### 10. time.localtime / struct_time +Test time structure operations if available. + +```python +import time + +t = time.localtime() +print(f"year: {t.tm_year}") +print(f"month: {t.tm_mon}") +print(f"day: {t.tm_mday}") +print("done") +``` + +--- + +## microcontroller + +### 11. microcontroller.cpu properties +Test frequency, temperature, UID properties. + +```python +import microcontroller + +print(f"frequency: {microcontroller.cpu.frequency}") +print(f"uid: {microcontroller.cpu.uid.hex()}") +print("done") +``` + +### 12. Safe mode +Trigger and verify safe mode entry (requires CONFIG_NATIVE_SIM_REBOOT=y). + +```python +import microcontroller +# This would trigger safe mode - test carefully +# microcontroller.on_next_reset(microcontroller.RunMode.SAFE_MODE) +# microcontroller.reset() +print("done") +``` + +### 13. Reset reason +Test microcontroller.reset_reason after various reset types. + +```python +import microcontroller + +reason = microcontroller.reset_reason +print(f"reset reason: {reason}") +print("done") +``` + +--- + +## os module + +### 14. os.uname() +Verify returns correct system info for native_sim. + +```python +import os + +info = os.uname() +print(f"sysname: {info.sysname}") +print(f"machine: {info.machine}") +print(f"release: {info.release}") +print("done") +``` + +### 15. Filesystem operations +Test os.listdir(), os.stat(), os.remove(). + +```python +import os + +# List root +files = os.listdir("/") +print(f"root files: {files}") + +# Stat a file +if "code.py" in files: + stat = os.stat("/code.py") + print(f"code.py size: {stat[6]}") + +print("done") +``` + +### 16. os.getenv() +Test environment variable reading. + +```python +import os + +# May return None if not set +path = os.getenv("PATH") +print(f"PATH exists: {path is not None}") +print("done") +``` + +--- + +## board module + +### 17. board.board_id +Verify board ID matches expected value. + +```python +import board + +print(f"board_id: {board.board_id}") +assert board.board_id == "native_native_sim" +print("done") +``` + +### 18. Pin availability +Test that board.LED and other defined pins exist. + +```python +import board + +assert hasattr(board, "LED"), "board.LED missing" +print(f"LED pin: {board.LED}") +print("done") +``` + +--- + +## Filesystem + +### 19. File read/write +Create, read, and modify files on CIRCUITPY. + +```python +# Write a test file +with open("/test.txt", "w") as f: + f.write("hello world") + +# Read it back +with open("/test.txt", "r") as f: + content = f.read() + +assert content == "hello world" +print("done") +``` + +### 20. Directory operations +Test mkdir, rmdir, nested paths. + +```python +import os + +# Create directory +os.mkdir("/testdir") +assert "testdir" in os.listdir("/") + +# Create file in directory +with open("/testdir/file.txt", "w") as f: + f.write("nested") + +# Clean up +os.remove("/testdir/file.txt") +os.rmdir("/testdir") +assert "testdir" not in os.listdir("/") +print("done") +``` + +### 21. Large file handling +Test with larger files approaching flash limits. + +```python +import gc + +# Write 10KB file +data = "x" * 10240 +with open("/large.txt", "w") as f: + f.write(data) + +# Verify size +import os +stat = os.stat("/large.txt") +assert stat[6] == 10240 + +# Clean up +os.remove("/large.txt") +gc.collect() +print("done") +``` + +--- + +## Error Conditions + +### 22. Syntax error in code.py +Verify graceful error message when code.py has syntax error. + +```python +# code.py with intentional syntax error: +def broken( + print("missing close paren" +``` + +Expected: Clear syntax error message with line number. + +### 23. Runtime error +Verify traceback format shows file, line, and function. + +```python +def cause_error(): + x = 1 / 0 + +cause_error() +``` + +Expected: Traceback showing ZeroDivisionError with line info. + +### 24. Keyboard interrupt +Test Ctrl+C handling via PTY if applicable. + +```python +import time + +print("starting long loop") +for i in range(100): + print(f"iteration {i}") + time.sleep(0.1) +print("done") +``` + +Send Ctrl+C during execution, verify clean KeyboardInterrupt. + +--- + +## busio (if emulation available) + +### 25. busio.UART +Basic UART operations if configured. + +```python +import board +import busio + +# Check if UART pins exist +if hasattr(board, "TX") and hasattr(board, "RX"): + uart = busio.UART(board.TX, board.RX, baudrate=115200) + uart.write(b"test") + uart.deinit() +print("done") +``` + +### 26. busio.I2C scan +Scan for emulated I2C devices. + +```python +import board +import busio + +if hasattr(board, "SCL") and hasattr(board, "SDA"): + i2c = busio.I2C(board.SCL, board.SDA) + while not i2c.try_lock(): + pass + devices = i2c.scan() + print(f"I2C devices: {[hex(d) for d in devices]}") + i2c.unlock() + i2c.deinit() +print("done") +``` + +### 27. busio.SPI +Basic SPI transfer to emulated device. + +```python +import board +import busio + +if hasattr(board, "SCK") and hasattr(board, "MOSI"): + spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=getattr(board, "MISO", None)) + while not spi.try_lock(): + pass + spi.configure(baudrate=1000000) + result = bytearray(4) + spi.write_readinto(b"\x00\x00\x00\x00", result) + spi.unlock() + spi.deinit() +print("done") +``` + +--- + +## Serial/PTY Input + +These tests require extending conftest.py to support writing to the PTY, not just reading. + +### 28. Basic serial input +Test reading single characters from serial via PTY write. + +```python +import sys + +print("ready") +char = sys.stdin.read(1) +print(f"received: {repr(char)}") +print("done") +``` + +**Test harness**: After seeing "ready", write "A" to PTY, verify output shows "received: 'A'". + +### 29. input() function +Test the built-in input() function with PTY input. + +```python +print("ready") +name = input("Enter name: ") +print(f"hello {name}") +print("done") +``` + +**Test harness**: After seeing "Enter name:", write "World\n" to PTY, verify "hello World". + +### 30. Serial line buffering +Test reading a complete line with newline termination. + +```python +import sys + +print("ready") +line = sys.stdin.readline() +print(f"got: {repr(line)}") +print("done") +``` + +**Test harness**: Write "test line\n" to PTY, verify complete line received. + +### 31. usb_cdc.console data read +Test reading from usb_cdc.console.data if available. + +```python +import usb_cdc + +print("ready") +if usb_cdc.console: + while not usb_cdc.console.in_waiting: + pass + data = usb_cdc.console.read(usb_cdc.console.in_waiting) + print(f"console got: {data}") +print("done") +``` + +**Test harness**: Write bytes to PTY, verify they're received via usb_cdc.console. + +### 32. REPL interaction +Test entering REPL mode and executing commands interactively. + +```python +# No code.py - boots to REPL +``` + +**Test harness**: +1. Boot with empty/no code.py to get REPL prompt +2. Write "1 + 1\r\n" to PTY +3. Verify output contains "2" +4. Write "print('hello')\r\n" +5. Verify output contains "hello" + +### 33. Ctrl+C interrupt via PTY +Test sending Ctrl+C (0x03) to interrupt running code. + +```python +import time + +print("starting") +for i in range(100): + print(f"loop {i}") + time.sleep(0.1) +print("completed") # Should not reach this +``` + +**Test harness**: +1. Wait for "loop 5" in output +2. Write b"\x03" (Ctrl+C) to PTY +3. Verify KeyboardInterrupt raised +4. Verify "completed" NOT in output + +### 34. Ctrl+D soft reload via PTY +Test sending Ctrl+D (0x04) to trigger soft reload. + +```python +print("first run") +import time +time.sleep(10) # Long sleep to allow interrupt +print("done") +``` + +**Test harness**: +1. Wait for "first run" +2. Write b"\x04" (Ctrl+D) to PTY +3. Verify code restarts (see "first run" again or reload message) + +### 35. Serial input timeout +Test behavior when waiting for input with timeout. + +```python +import sys +import select + +print("ready") +# Poll for input with timeout +readable, _, _ = select.select([sys.stdin], [], [], 0.5) +if readable: + data = sys.stdin.read(1) + print(f"got: {repr(data)}") +else: + print("timeout") +print("done") +``` + +**Test harness**: Don't send anything, verify "timeout" appears. + +--- + +## Fixture Changes for PTY Input + +The `run_circuitpython` fixture in conftest.py needs to be extended: + +```python +@dataclass +class SimulatorResult: + output: str + trace_file: Path + pty_write_fd: int # New: file descriptor for writing to PTY + +def _run(code: str | None, timeout: float = 5.0, ...) -> SimulatorResult: + # Open PTY for both read AND write + pty_fd = os.open(pty_path, os.O_RDWR | os.O_NONBLOCK) + # ... +``` + +Or provide a callback/queue mechanism: + +```python +def _run(code, timeout=5.0, input_sequence=None): + """ + input_sequence: list of (trigger_text, bytes_to_send) tuples + When trigger_text is seen in output, send bytes_to_send to PTY + """ +``` + +--- + +## Implementation Priority + +Suggested order for implementation: + +### Phase 1: Basic module tests (no fixture changes) +1. **#17 board.board_id** - Quick sanity check +2. **#14 os.uname()** - Tests another module, simple +3. **#9 time.monotonic()** - Core timing functionality +4. **#8 time.sleep() precision** - Builds on GPIO trace infrastructure +5. **#1 Multiple file priority** - Tests interpreter boot sequence +6. **#19 File read/write** - Tests filesystem layer +7. **#3 Memory / gc** - Tests memory management +8. **#2 Exception handling** - Tests error reporting + +### Phase 2: PTY input tests (requires fixture extension) +9. **#28 Basic serial input** - Foundation for all input tests +10. **#33 Ctrl+C interrupt** - Important for interactive use +11. **#29 input() function** - Common user pattern +12. **#32 REPL interaction** - Tests interactive mode diff --git a/ports/zephyr-cp/tests/__init__.py b/ports/zephyr-cp/tests/__init__.py new file mode 100644 index 0000000000000..e9039dd88b346 --- /dev/null +++ b/ports/zephyr-cp/tests/__init__.py @@ -0,0 +1,162 @@ +from pathlib import Path + +import serial +import subprocess +import threading +import time + + +class StdSerial: + def __init__(self, stdin, stdout): + self.stdin = stdin + self.stdout = stdout + + def read(self, amount=None): + data = self.stdout.read(amount) + if data == b"": + raise EOFError("stdout closed") + return data + + def write(self, buf): + if self.stdin is None: + return + self.stdin.write(buf) + self.stdin.flush() + + def close(self): + if self.stdin is not None: + self.stdin.close() + self.stdout.close() + + @property + def in_waiting(self): + if self.stdout is None: + return 0 + return len(self.stdout.peek()) + + +class SerialSaver: + """Capture serial output in a background thread so output isn't missed.""" + + def __init__(self, serial_obj, name="serial"): + self.all_output = "" + self.all_input = "" + self.serial = serial_obj + self.name = name + + self._stop = threading.Event() + self._lock = threading.Lock() + self._cv = threading.Condition(self._lock) + self._reader = threading.Thread(target=self._reader_loop, daemon=True) + self._reader.start() + + def _reader_loop(self): + while not self._stop.is_set(): + try: + read = self.serial.read(1) + except Exception: + # Serial port closed or device disconnected. + break + + if read == b"": + # Timeout with no data — keep waiting. Only a real + # exception or an explicit stop should end the loop. + continue + + text = read.decode("utf-8", errors="replace") + with self._cv: + self.all_output += text + self._cv.notify_all() + in_waiting = 0 + try: + in_waiting = self.serial.in_waiting + except OSError: + pass + if in_waiting > 0: + self.all_output += self.serial.read().decode("utf-8", errors="replace") + + def wait_for(self, text, timeout=10): + with self._cv: + while text not in self.all_output and self._reader.is_alive(): + if not self._cv.wait(timeout=timeout): + break + if text not in self.all_output: + tail = self.all_output[-400:] + raise TimeoutError( + f"Timed out waiting for {text!r} on {self.name}. Output tail:\n{tail}" + ) + + def read(self, amount=None): + # Kept for compatibility with existing callers. + return + + def close(self): + if not self.serial: + return + + self._stop.set() + self._reader.join(timeout=1.0) + try: + self.serial.close() + except Exception: + pass + self.serial = None + + def write(self, text): + self.all_input += text + self.serial.write(text.encode("utf-8")) + + +class NativeSimProcess: + def __init__(self, cmd, timeout=5, trace_file=None, env=None, flash_file=None): + if trace_file: + cmd.append(f"--trace-file={trace_file}") + + self._timeout = timeout + self.trace_file = trace_file + self.flash_file = flash_file + print("Running", " ".join(cmd)) + self._proc = subprocess.Popen( + cmd, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=None, + env=env, + ) + if self._proc.stdout is None: + raise RuntimeError("Failed to capture simulator stdout") + + # Discard the test warning + uart_pty_line = self._proc.stdout.readline().decode("utf-8") + if "connected to pseudotty:" not in uart_pty_line: + raise RuntimeError("Failed to connect to UART") + pty_path = uart_pty_line.strip().rsplit(":", maxsplit=1)[1].strip() + self.serial = SerialSaver( + serial.Serial(pty_path, baudrate=115200, timeout=0.05, write_timeout=0), + name="uart0", + ) + self.debug_serial = SerialSaver( + StdSerial(self._proc.stdin, self._proc.stdout), name="debug" + ) + + def shutdown(self): + if self._proc.poll() is None: + self._proc.terminate() + self._proc.wait(timeout=self._timeout) + + self.serial.close() + self.debug_serial.close() + + def display_capture_paths(self) -> list[Path]: + """Return paths to numbered PNG capture files produced by trace-driven capture.""" + pattern = getattr(self, "_capture_png_pattern", None) + count = getattr(self, "_capture_count", 0) + if not pattern or count == 0: + return [] + return [Path(pattern % i) for i in range(count)] + + def wait_until_done(self): + start_time = time.monotonic() + while self._proc.poll() is None and time.monotonic() - start_time < self._timeout: + time.sleep(0.01) + self.shutdown() diff --git a/ports/zephyr-cp/tests/bsim/__init__.py b/ports/zephyr-cp/tests/bsim/__init__.py new file mode 100644 index 0000000000000..75136bccf43ae --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/__init__.py @@ -0,0 +1,3 @@ +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") diff --git a/ports/zephyr-cp/tests/bsim/conftest.py b/ports/zephyr-cp/tests/bsim/conftest.py new file mode 100644 index 0000000000000..493f4c92b3ba0 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/conftest.py @@ -0,0 +1,227 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Pytest fixtures for CircuitPython bsim testing.""" + +import logging +import os +import shutil +import subprocess +from pathlib import Path + +import pytest + +from .. import SerialSaver, StdSerial + +logger = logging.getLogger(__name__) + +ZEPHYR_CP = Path(__file__).resolve().parents[2] +BSIM_BUILD_DIR = ZEPHYR_CP / "build-native_nrf5340bsim" +BSIM_SYSBUILD_BINARY = BSIM_BUILD_DIR / "zephyr/zephyr.exe" +BSIM_BINARY = BSIM_BUILD_DIR / "zephyr-cp/zephyr/zephyr.exe" +BSIM_ROOT = ZEPHYR_CP / "tools/bsim" +BSIM_PHY_BINARY = BSIM_ROOT / "bin/bs_2G4_phy_v1" + + +@pytest.fixture +def native_sim_env() -> dict[str, str]: + env = os.environ.copy() + env["BSIM_OUT_PATH"] = str(BSIM_ROOT) + env["BSIM_COMPONENTS_PATH"] = str(BSIM_ROOT / "components") + lib_path = str(BSIM_ROOT / "lib") + existing = env.get("LD_LIBRARY_PATH", "") + env["LD_LIBRARY_PATH"] = f"{lib_path}:{existing}" if existing else lib_path + return env + + +@pytest.fixture +def bsim_binary(): + """Return path to nrf5340bsim binary, skip if not built.""" + if BSIM_SYSBUILD_BINARY.exists(): + return BSIM_SYSBUILD_BINARY + if not BSIM_BINARY.exists(): + pytest.skip(f"nrf5340bsim not built: {BSIM_BINARY}") + return BSIM_BINARY + + +@pytest.fixture +def bsim_phy_binary(): + """Return path to BabbleSim PHY binary, skip if not present.""" + if not BSIM_PHY_BINARY.exists(): + pytest.skip(f"bs_2G4_phy_v1 not found: {BSIM_PHY_BINARY}") + return BSIM_PHY_BINARY + + +class BsimPhyInstance: + def __init__(self, proc: subprocess.Popen, serial: SerialSaver, timeout: float): + self.proc = proc + self.serial = serial + self.timeout = timeout + + def finish_sim(self) -> None: + self.serial.wait_for("Cleaning up", timeout=self.timeout + 5) + + def shutdown(self) -> None: + if self.proc.poll() is None: + self.proc.terminate() + self.proc.wait(timeout=2) + self.serial.close() + + +class ZephyrSampleProcess: + def __init__(self, proc: subprocess.Popen, timeout: float): + self._proc = proc + self._timeout = timeout + if proc.stdout is None: + raise RuntimeError("Failed to capture Zephyr sample stdout") + self.serial = SerialSaver(StdSerial(None, proc.stdout), name="zephyr sample") + + def shutdown(self) -> None: + if self._proc.poll() is None: + self._proc.terminate() + self._proc.wait(timeout=self._timeout) + self.serial.close() + + +@pytest.fixture +def bsim_phy(request, bsim_phy_binary, native_sim_env, sim_id): + duration_marker = request.node.get_closest_marker("duration") + duration = float(duration_marker.args[0]) if duration_marker else 20.0 + + devices = 1 + if "circuitpython2" in request.fixturenames or "zephyr_sample" in request.fixturenames: + devices = 2 + + sample_marker = request.node.get_closest_marker("zephyr_sample") + if sample_marker is not None: + sample_device_id = int(sample_marker.kwargs.get("device_id", 1)) + devices = max(devices, sample_device_id + 1) + + # Do not pass -sim_length: if the PHY exits on simulated time, device 0 can + # still be flushing UART output and test output can get truncated. Instead, + # let pytest own process lifetime and terminate the PHY at fixture teardown. + cmd = [ + "stdbuf", + "-oL", + str(bsim_phy_binary), + "-v=9", # Cleaning up level is on 9. Connecting is 7. + f"-s={sim_id}", + f"-D={devices}", + "-argschannel", + "-at=40", # 40 dB attenuation (default 60) so RSSI ~ -40 dBm + ] + print("Running:", " ".join(cmd)) + proc = subprocess.Popen( + cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=native_sim_env, + cwd=BSIM_ROOT / "bin", + ) + if proc.stdout is None: + raise RuntimeError("Failed to capture bsim phy stdout") + + # stdbuf -oL forces line-buffered stdout so SerialSaver can + # stream-read PHY output in real time. Wrapping in StdSerial + # ensures the reader thread exits on EOF when the PHY process + # terminates, rather than spinning on empty timeout reads. + phy_output = SerialSaver(StdSerial(None, proc.stdout), name="bsim phy") + try: + phy_output.wait_for("Connecting", timeout=2) + except TimeoutError: + if proc.poll() is not None: + print(phy_output.all_output) + raise RuntimeError("bsim PHY exited immediately") + # Assume bsim is running + + phy = BsimPhyInstance(proc, phy_output, timeout=duration) + yield phy + phy.shutdown() + + print("bsim phy output:") + print(phy_output.all_output) + + +def _build_zephyr_sample(build_dir: Path, source_dir: Path, board: str) -> Path: + if shutil.which("west") is None: + raise RuntimeError("west not found") + + cmd = [ + "west", + "build", + "-b", + board, + "-d", + str(build_dir), + "-p=auto", + str(source_dir), + ] + logger.info("Building Zephyr sample: %s", " ".join(cmd)) + subprocess.run(cmd, check=True, cwd=ZEPHYR_CP) + + return build_dir / "zephyr/zephyr.exe" + + +@pytest.fixture +def zephyr_sample(request, bsim_phy, native_sim_env, sim_id): + marker = request.node.get_closest_marker("zephyr_sample") + if marker is None or len(marker.args) != 1: + raise RuntimeError( + "zephyr_sample fixture requires @pytest.mark.zephyr_sample('')" + ) + + sample = marker.args[0] + board = marker.kwargs.get("board", "nrf52_bsim") + device_id = int(marker.kwargs.get("device_id", 1)) + timeout = float(marker.kwargs.get("timeout", 10.0)) + + sample_rel = str(sample).removeprefix("zephyr/samples/") + source_dir = ZEPHYR_CP / "zephyr/samples" / sample_rel + if not source_dir.exists(): + pytest.skip(f"Zephyr sample not found: {source_dir}") + + build_name = f"build-bsim-sample-{sample_rel.replace('/', '_')}-{board}" + build_dir = ZEPHYR_CP / build_name + binary = build_dir / "zephyr/zephyr.exe" + + if not binary.exists(): + try: + binary = _build_zephyr_sample(build_dir, source_dir, board) + except (subprocess.CalledProcessError, RuntimeError) as exc: + pytest.skip(f"Failed to build Zephyr sample {sample_rel}: {exc}") + + if not binary.exists(): + pytest.skip(f"Zephyr sample binary not found: {binary}") + + cmd = [ + str(binary), + f"-s={sim_id}", + f"-d={device_id}", + "-disconnect_on_exit=1", + ] + logger.info("Running: %s", " ".join(cmd)) + proc = subprocess.Popen( + cmd, + stdin=subprocess.DEVNULL, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=native_sim_env, + ) + sample_proc = ZephyrSampleProcess(proc, timeout=timeout) + yield sample_proc + sample_proc.shutdown() + + print("Zephyr sample output:") + print(sample_proc.serial.all_output) + + +# pytest markers are defined inside out meaning the bottom one is first in the +# list and the top is last. So use negative indices to reverse them. +@pytest.fixture +def circuitpython1(circuitpython): + return circuitpython[-1] + + +@pytest.fixture +def circuitpython2(circuitpython): + return circuitpython[-2] diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_basics.py b/ports/zephyr-cp/tests/bsim/test_bsim_basics.py new file mode 100644 index 0000000000000..477292ddd5465 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_basics.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Basic BabbleSim connectivity tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_CODE = """\ +print("bsim ready") +""" + + +@pytest.mark.circuitpy_drive({"code.py": BSIM_CODE}) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CODE}) +@pytest.mark.duration(3) +def test_bsim_dual_instance_connect(bsim_phy, circuitpython1, circuitpython2): + """Run two bsim instances on the same sim id and verify UART output.""" + + # Wait for both devices to complete before checking output. + circuitpython1.wait_until_done() + circuitpython2.wait_until_done() + + output0 = circuitpython1.serial.all_output + output1 = circuitpython2.serial.all_output + + assert "Board ID:native_nrf5340bsim" in output0 + assert "Board ID:native_nrf5340bsim" in output1 + assert "bsim ready" in output0 + assert "bsim ready" in output1 diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py new file mode 100644 index 0000000000000..33680fe2506f5 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_advertising.py @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE advertising tests for nrf5340bsim.""" + +import logging +import re + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +logger = logging.getLogger(__name__) + +BSIM_ADV_CODE = """\ +import _bleio +import time + +name = b"CPADV" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +adapter = _bleio.adapter +print("adv start") +adapter.start_advertising(advertisement, connectable=False) +print("adv started") +time.sleep(4) +adapter.stop_advertising() +print("adv stop") +""" + +BSIM_ADV_INTERRUPT_RELOAD_CODE = """\ +import _bleio +import time + +name = b"CPADV" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +adapter = _bleio.adapter +print("adv run start") +adapter.start_advertising(advertisement, connectable=False) +print("adv running") +time.sleep(10) +adapter.stop_advertising() +print("adv run done") +""" + + +BSIM_TX_POWER_DEFAULT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +name = b"CPTXPWR" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("advertising default") +adapter.start_advertising(advertisement) +time.sleep(4) +adapter.stop_advertising() +print("done") +""" + +BSIM_TX_POWER_LOW_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +name = b"CPTXPWR" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("advertising low") +adapter.start_advertising(advertisement, tx_power=-20) +time.sleep(4) +adapter.stop_advertising() +print("done") +""" + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_ADV_CODE}) +def test_bsim_advertise_and_scan(bsim_phy, circuitpython, zephyr_sample): + """Advertise from CircuitPython and verify Zephyr observer sees traffic.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + observer_output = observer.serial.all_output + assert "adv start" in cp_output + assert "adv started" in cp_output + assert "adv stop" in cp_output + assert "Device found:" in observer_output + assert "AD data len 10" in observer_output + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(25) +@pytest.mark.circuitpy_drive({"code.py": BSIM_ADV_INTERRUPT_RELOAD_CODE}) +def test_bsim_advertise_ctrl_c_reload(bsim_phy, circuitpython, zephyr_sample): + """Ensure advertising resumes after Ctrl-C and a reload.""" + observer = zephyr_sample + + circuitpython.serial.wait_for("adv running") + observer.serial.wait_for("Device found:") + observer_count_before = observer.serial.all_output.count("Device found:") + + circuitpython.serial.write("\x03") + circuitpython.serial.wait_for("KeyboardInterrupt") + + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + observer_output = observer.serial.all_output + logger.info(observer_output) + logger.info(cp_output) + + assert "adv run start" in cp_output + assert "KeyboardInterrupt" in cp_output + assert cp_output.count("adv running") >= 2 + assert cp_output.count("adv run done") >= 1 + assert observer_output.count("Device found:") >= observer_count_before + 1 + assert "Already advertising" not in cp_output + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_TX_POWER_DEFAULT_CODE}) +def test_bsim_tx_power_default_rssi(bsim_phy, circuitpython, zephyr_sample): + """Verify default TX power produces expected RSSI.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + obs_output = observer.serial.all_output + + assert "advertising default" in cp_output + assert "done" in cp_output + + # Observer: "Device found: (RSSI ), type , AD data len " + # Advertisement is 12 bytes: flags (3) + name (9). + # With 40 dB channel attenuation and 0 dBm TX → RSSI ~ -39 + rssi_pattern = re.compile(r"RSSI (-?\d+)\), type \d+, AD data len 12") + all_rssi = [int(m.group(1)) for m in rssi_pattern.finditer(obs_output)] + logger.info("RSSI values: %s", all_rssi) + + assert len(all_rssi) > 0, "Observer saw no advertisements" + assert all_rssi[0] == -39, f"Expected RSSI -39 (0 dBm TX), got {all_rssi[0]}" + + +@pytest.mark.zephyr_sample("bluetooth/observer") +@pytest.mark.circuitpy_drive({"code.py": BSIM_TX_POWER_LOW_CODE}) +def test_bsim_tx_power_low_rssi(bsim_phy, circuitpython, zephyr_sample): + """Verify low TX power reduces RSSI.""" + observer = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + obs_output = observer.serial.all_output + + assert "advertising low" in cp_output + assert "done" in cp_output + + # With 40 dB channel attenuation and -20 dBm TX → RSSI ~ -59 + rssi_pattern = re.compile(r"RSSI (-?\d+)\), type \d+, AD data len 12") + all_rssi = [int(m.group(1)) for m in rssi_pattern.finditer(obs_output)] + logger.info("RSSI values: %s", all_rssi) + + assert len(all_rssi) > 0, "Observer saw no advertisements" + assert all_rssi[0] < -39, f"Expected lower RSSI with -20 dBm TX, got {all_rssi[0]}" diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py new file mode 100644 index 0000000000000..21cfeaf79da50 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_connect.py @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE central connection tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_CONNECT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("connect start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable: + target = entry.address + print("found target") + break +adapter.stop_scan() +print("have target", target is not None) + +if target is None: + raise RuntimeError("No connectable target found") + +connection = adapter.connect(target, timeout=5.0) +print("connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +for _ in range(40): + if not connection.connected and not adapter.connected: + break + time.sleep(0.1) + +print("disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + +BSIM_RECONNECT_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("run start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable: + target = entry.address + print("run found target") + break +adapter.stop_scan() +print("run have target", target is not None) + +if target is None: + raise RuntimeError("No connectable target found") + +connection = adapter.connect(target, timeout=5.0) +print("run connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +for _ in range(50): + if not connection.connected and not adapter.connected and len(adapter.connections) == 0: + break + time.sleep(0.1) + +print("run disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + + +@pytest.mark.zephyr_sample("bluetooth/peripheral") +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CONNECT_CODE}) +def test_bsim_connect_zephyr_peripheral(bsim_phy, circuitpython, zephyr_sample): + """Connect to the Zephyr peripheral sample and disconnect cleanly.""" + peripheral = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + peripheral_output = peripheral.serial.all_output + + assert "connect start" in cp_output + assert "found target" in cp_output + assert "have target True" in cp_output + assert "connected True True 1" in cp_output + assert "disconnected False False 0" in cp_output + + assert "Advertising successfully started" in peripheral_output + assert "Connected" in peripheral_output + + +@pytest.mark.zephyr_sample("bluetooth/peripheral_sc_only") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(26) +@pytest.mark.circuitpy_drive({"code.py": BSIM_RECONNECT_CODE}) +def test_bsim_reconnect_zephyr_peripheral(bsim_phy, circuitpython, zephyr_sample): + """Connect/disconnect, soft reload, then connect/disconnect again.""" + peripheral = zephyr_sample + + circuitpython.serial.wait_for("run disconnected") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + peripheral_output = peripheral.serial.all_output + + assert cp_output.count("run start") >= 2 + assert cp_output.count("run found target") >= 2 + assert cp_output.count("run have target True") >= 2 + assert cp_output.count("run connected True True 1") >= 2 + assert cp_output.count("run disconnected False False 0") >= 2 + + assert "Advertising successfully started" in peripheral_output + assert peripheral_output.count("Connected") >= 2 diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py new file mode 100644 index 0000000000000..69435d3825624 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_name.py @@ -0,0 +1,25 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE name tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_NAME_CODE = """\ +import _bleio + +adapter = _bleio.adapter +adapter.enabled = True +adapter.name = "CPNAME" +print("name", adapter.name) +""" + + +@pytest.mark.circuitpy_drive({"code.py": BSIM_NAME_CODE}) +def test_bsim_set_name(bsim_phy, circuitpython): + """Set the BLE name and read it back on bsim.""" + circuitpython.wait_until_done() + + assert "name CPNAME" in circuitpython.serial.all_output diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py new file mode 100644 index 0000000000000..7a4bbfaecd942 --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_peripheral.py @@ -0,0 +1,120 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE peripheral connection tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_PERIPHERAL_CODE = """\ +import _bleio +import time +import sys + +adapter = _bleio.adapter + +name = b"CPPERIPH" +advertisement = bytes((2, 0x01, 0x06, len(name) + 1, 0x09)) + name + +print("peripheral start") +adapter.start_advertising(advertisement, connectable=True) +print("advertising", adapter.advertising) + +was_connected = False +timeout = time.monotonic() + 8.0 +while not was_connected and time.monotonic() < timeout: + time.sleep(0.01) + was_connected = adapter.connected + +if not was_connected: + print("connect timed out") + sys.exit(-1) + +print("connected", was_connected, "advertising", adapter.advertising) + +if was_connected: + timeout = time.monotonic() + 8.0 + while adapter.connected and time.monotonic() < timeout: + time.sleep(0.1) + +print("disconnected", adapter.connected, len(adapter.connections)) +""" + +BSIM_CENTRAL_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("central start") +target = None +for entry in adapter.start_scan(timeout=6.0, active=True): + if entry.connectable and b"CPPERIPH" in entry.advertisement_bytes: + target = entry.address + print("found peripheral") + break +adapter.stop_scan() +print("have target", target is not None) + +if target is None: + raise RuntimeError("No connectable peripheral found") + +connection = adapter.connect(target, timeout=5.0) +print("connected", connection.connected, adapter.connected, len(adapter.connections)) +connection.disconnect() + +timeout = time.monotonic() + 4.0 +while (connection.connected or adapter.connected) and time.monotonic() < timeout: + time.sleep(0.1) + +print("disconnected", connection.connected, adapter.connected, len(adapter.connections)) +""" + + +@pytest.mark.zephyr_sample("bluetooth/central") +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_PERIPHERAL_CODE}) +def test_bsim_peripheral_zephyr_central(bsim_phy, circuitpython, zephyr_sample): + """Advertise as connectable from CP; Zephyr central connects and disconnects.""" + central = zephyr_sample + + circuitpython.wait_until_done() + + cp_output = circuitpython.serial.all_output + central_output = central.serial.all_output + + assert "peripheral start" in cp_output + assert "advertising True" in cp_output + assert "connected True advertising False" in cp_output + assert "disconnected False 0" in cp_output + + assert "Scanning successfully started" in central_output + assert "Connected:" in central_output + assert "Disconnected:" in central_output + + +@pytest.mark.duration(14) +@pytest.mark.circuitpy_drive({"code.py": BSIM_PERIPHERAL_CODE}) +@pytest.mark.circuitpy_drive({"code.py": BSIM_CENTRAL_CODE}) +def test_bsim_peripheral_cp_central(bsim_phy, circuitpython1, circuitpython2): + """Two CP instances: device 0 peripheral, device 1 central.""" + peripheral = circuitpython1 + central = circuitpython2 + + central.wait_until_done() + peripheral.wait_until_done() + + periph_output = peripheral.serial.all_output + central_output = central.serial.all_output + + assert "peripheral start" in periph_output + assert "advertising True" in periph_output + assert "connected True advertising False" in periph_output + assert "disconnected False 0" in periph_output + + assert "central start" in central_output + assert "found peripheral" in central_output + assert "have target True" in central_output + assert "connected True True 1" in central_output + assert "disconnected False False 0" in central_output diff --git a/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py b/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py new file mode 100644 index 0000000000000..19455b7bfa3fc --- /dev/null +++ b/ports/zephyr-cp/tests/bsim/test_bsim_ble_scan.py @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""BLE scanning tests for nrf5340bsim.""" + +import pytest + +pytestmark = pytest.mark.circuitpython_board("native_nrf5340bsim") + +BSIM_SCAN_CODE = """\ +import _bleio + +adapter = _bleio.adapter +print("scan start") +scan = adapter.start_scan(timeout=4.0, active=True) +found = False +for entry in scan: + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon") + found = True + break +adapter.stop_scan() +print("scan done", found) +""" + +BSIM_SCAN_RELOAD_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("scan run start") +found = False +for entry in adapter.start_scan(active=True): + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon run") + found = True + break +adapter.stop_scan() +print("scan run done", found) +""" + +BSIM_SCAN_RELOAD_NO_STOP_CODE = """\ +import _bleio +import time + +adapter = _bleio.adapter + +print("scan run start") +found = False +for entry in adapter.start_scan(active=True): + if b"zephyrproject" in entry.advertisement_bytes: + print("found beacon run") + found = True + break +print("scan run done", found) +""" + + +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_CODE}) +def test_bsim_scan_zephyr_beacon(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon sample advertisement using bsim.""" + _ = zephyr_sample + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "scan start" in output + assert "found beacon" in output + assert "scan done True" in output + + +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(4) +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_RELOAD_CODE}) +def test_bsim_scan_zephyr_beacon_reload(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon, soft reload, and scan again.""" + _ = zephyr_sample + + circuitpython.serial.wait_for("scan run done") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert output.count("scan run start") >= 2 + assert output.count("found beacon run") >= 2 + assert output.count("scan run done True") >= 2 + + +@pytest.mark.xfail(strict=False, reason="scan without stop_scan may fail on reload") +@pytest.mark.zephyr_sample("bluetooth/beacon") +@pytest.mark.code_py_runs(2) +@pytest.mark.duration(8) +@pytest.mark.circuitpy_drive({"code.py": BSIM_SCAN_RELOAD_NO_STOP_CODE}) +def test_bsim_scan_zephyr_beacon_reload_no_stop(bsim_phy, circuitpython, zephyr_sample): + """Scan for Zephyr beacon without explicit stop, soft reload, and scan again.""" + _ = zephyr_sample + + circuitpython.serial.wait_for("scan run done") + circuitpython.serial.wait_for("Press any key to enter the REPL") + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert output.count("scan run start") >= 2 + assert output.count("found beacon run") >= 2 + assert output.count("scan run done True") >= 2 diff --git a/ports/zephyr-cp/tests/conftest.py b/ports/zephyr-cp/tests/conftest.py new file mode 100644 index 0000000000000..03451048324de --- /dev/null +++ b/ports/zephyr-cp/tests/conftest.py @@ -0,0 +1,381 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Pytest fixtures for CircuitPython native_sim testing.""" + +import logging +import os +import subprocess +from pathlib import Path + +import pytest +import serial + +from .perfetto_input_trace import write_input_trace + +from perfetto.trace_processor import TraceProcessor + +from . import NativeSimProcess + +logger = logging.getLogger(__name__) + + +def pytest_addoption(parser): + parser.addoption( + "--update-goldens", + action="store_true", + default=False, + help="Overwrite golden images with captured output instead of comparing.", + ) + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "circuitpy_drive(files): run CircuitPython with files in the flash image" + ) + config.addinivalue_line( + "markers", "disable_i2c_devices(*names): disable native_sim I2C emulator devices" + ) + config.addinivalue_line( + "markers", "circuitpython_board(board_id): which board id to use in the test" + ) + config.addinivalue_line( + "markers", + "zephyr_sample(sample, board='nrf52_bsim', device_id=1): build and run a Zephyr sample for bsim tests", + ) + config.addinivalue_line( + "markers", + "duration(seconds): native_sim timeout and bsim PHY simulation duration", + ) + config.addinivalue_line( + "markers", + "code_py_runs(count): stop native_sim after count code.py runs (default: 1)", + ) + config.addinivalue_line( + "markers", + "input_trace(trace): inject input signal trace data into native_sim", + ) + config.addinivalue_line( + "markers", + "native_sim_rt: run native_sim in realtime mode (-rt instead of -no-rt)", + ) + config.addinivalue_line( + "markers", + "display(capture_times_ns=None): run test with SDL display; " + "capture_times_ns is a list of nanosecond timestamps for trace-triggered captures", + ) + config.addinivalue_line( + "markers", + "display_pixel_format(format): override the display pixel format " + "(e.g. 'RGB_565', 'ARGB_8888')", + ) + config.addinivalue_line( + "markers", + "display_mono_vtiled(value): override the mono vtiled screen_info flag (True or False)", + ) + config.addinivalue_line( + "markers", + "flash_config(erase_block_size=N, total_size=N): override flash simulator parameters", + ) + + +ZEPHYR_CP = Path(__file__).parent.parent +BUILD_DIR = ZEPHYR_CP / "build-native_native_sim" +BINARY = BUILD_DIR / "zephyr-cp/zephyr/zephyr.exe" + + +def _iter_uart_tx_slices(trace_file: Path) -> list[tuple[int, int, str, str]]: + """Return UART TX slices as (timestamp_ns, duration_ns, text, device_name).""" + tp = TraceProcessor(file_path=str(trace_file)) + result = tp.query( + """ + SELECT s.ts, s.dur, s.name, dev.name AS device_name + FROM slice s + JOIN track tx ON s.track_id = tx.id + JOIN track dev ON tx.parent_id = dev.id + JOIN track uart ON dev.parent_id = uart.id + WHERE tx.name = "TX" AND uart.name = "UART" + ORDER BY s.ts + """ + ) + return [ + (int(row.ts), int(row.dur or 0), row.name or "", row.device_name or "UART") + for row in result + ] + + +def log_uart_trace_output(trace_file: Path) -> None: + """Log UART TX output from Perfetto trace with timestamps for line starts.""" + if not logger.isEnabledFor(logging.INFO): + return + slices = _iter_uart_tx_slices(trace_file) + if not slices: + return + + buffers: dict[str, list[str]] = {} + line_start_ts: dict[str, int | None] = {} + + for ts, dur, text, device in slices: + if device not in buffers: + buffers[device] = [] + line_start_ts[device] = None + + if not text: + continue + + char_step = dur / max(len(text), 1) if dur > 0 else 0.0 + for idx, ch in enumerate(text): + if line_start_ts[device] is None: + line_start_ts[device] = int(ts + idx * char_step) + buffers[device].append(ch) + if ch == "\n": + line_text = "".join(buffers[device]).rstrip("\n") + logger.info( + "UART trace %s @%d ns: %s", + device, + line_start_ts[device], + repr(line_text), + ) + buffers[device] = [] + line_start_ts[device] = None + + for device, buf in buffers.items(): + if buf: + logger.info( + "UART trace %s @%d ns (partial): %s", + device, + line_start_ts[device] or 0, + repr("".join(buf)), + ) + + +@pytest.fixture +def board(request): + board = request.node.get_closest_marker("circuitpython_board") + if board is not None: + board = board.args[0] + else: + board = "native_native_sim" + return board + + +@pytest.fixture +def native_sim_binary(request, board): + """Return path to native_sim binary, skip if not built.""" + build_dir = ZEPHYR_CP / f"build-{board}" + binary = build_dir / "zephyr-cp/zephyr/zephyr.exe" + + if not binary.exists(): + pytest.skip(f"binary not built: {binary}") + return binary + + +@pytest.fixture +def native_sim_env() -> dict[str, str]: + return {} + + +PIXEL_FORMAT_BITMASK = { + "RGB_888": 1 << 0, + "MONO01": 1 << 1, + "MONO10": 1 << 2, + "ARGB_8888": 1 << 3, + "RGB_565": 1 << 4, + "BGR_565": 1 << 5, + "L_8": 1 << 6, + "AL_88": 1 << 7, +} + + +@pytest.fixture +def pixel_format(request) -> str: + """Indirect-parametrize fixture: adds display_pixel_format marker.""" + fmt = request.param + request.node.add_marker(pytest.mark.display_pixel_format(fmt)) + return fmt + + +@pytest.fixture +def sim_id(request) -> str: + return request.node.nodeid.replace("/", "_") + + +@pytest.fixture +def circuitpython(request, board, sim_id, native_sim_binary, native_sim_env, tmp_path): + """Run CircuitPython with given code string and return PTY output.""" + + instance_count = 1 + if "circuitpython1" in request.fixturenames and "circuitpython2" in request.fixturenames: + instance_count = 2 + + drives = list(request.node.iter_markers_with_node("circuitpy_drive")) + if len(drives) != instance_count: + raise RuntimeError(f"not enough drives for {instance_count} instances") + + input_trace_markers = list(request.node.iter_markers_with_node("input_trace")) + if len(input_trace_markers) > 1: + raise RuntimeError("expected at most one input_trace marker") + + input_trace = None + if input_trace_markers and len(input_trace_markers[0][1].args) == 1: + input_trace = input_trace_markers[0][1].args[0] + + input_trace_file = None + if input_trace is not None: + input_trace_file = tmp_path / "input.perfetto" + write_input_trace(input_trace_file, input_trace) + + marker = request.node.get_closest_marker("duration") + if marker is None: + timeout = 10 + else: + timeout = marker.args[0] + + runs_marker = request.node.get_closest_marker("code_py_runs") + if runs_marker is None: + code_py_runs = 1 + else: + code_py_runs = int(runs_marker.args[0]) + + display_marker = request.node.get_closest_marker("display") + if display_marker is None: + display_marker = request.node.get_closest_marker("display_capture") + + capture_times_ns = None + if display_marker is not None: + capture_times_ns = display_marker.kwargs.get("capture_times_ns", None) + + pixel_format_marker = request.node.get_closest_marker("display_pixel_format") + pixel_format = None + if pixel_format_marker is not None and pixel_format_marker.args: + pixel_format = pixel_format_marker.args[0] + + mono_vtiled_marker = request.node.get_closest_marker("display_mono_vtiled") + mono_vtiled = None + if mono_vtiled_marker is not None and mono_vtiled_marker.args: + mono_vtiled = mono_vtiled_marker.args[0] + + # If capture_times_ns is set, merge display_capture track into input trace. + if capture_times_ns is not None: + if input_trace is None: + input_trace = {} + else: + input_trace = dict(input_trace) + input_trace["display_capture"] = list(capture_times_ns) + if input_trace_file is None: + input_trace_file = tmp_path / "input.perfetto" + write_input_trace(input_trace_file, input_trace) + + use_realtime = request.node.get_closest_marker("native_sim_rt") is not None + + flash_config_marker = request.node.get_closest_marker("flash_config") + flash_total_size = 2 * 1024 * 1024 # default 2MB + flash_erase_block_size = None + flash_write_block_size = None + if flash_config_marker: + flash_total_size = flash_config_marker.kwargs.get("total_size", flash_total_size) + flash_erase_block_size = flash_config_marker.kwargs.get("erase_block_size", None) + flash_write_block_size = flash_config_marker.kwargs.get("write_block_size", None) + + procs = [] + for i in range(instance_count): + flash = tmp_path / f"flash-{i}.bin" + flash.write_bytes(b"\xff" * flash_total_size) + files = None + if len(drives[i][1].args) == 1: + files = drives[i][1].args[0] + if files is not None: + subprocess.run(["mformat", "-i", str(flash), "::"], check=True) + tmp_drive = tmp_path / f"drive{i}" + tmp_drive.mkdir(exist_ok=True) + + for name, content in files.items(): + src = tmp_drive / name + if isinstance(content, bytes): + src.write_bytes(content) + else: + src.write_text(content) + subprocess.run(["mcopy", "-i", str(flash), str(src), f"::{name}"], check=True) + + trace_file = tmp_path / f"trace-{i}.perfetto" + + if "bsim" in board: + cmd = [str(native_sim_binary), f"--flash_app={flash}"] + if instance_count > 1: + cmd.append("-disconnect_on_exit=1") + cmd.extend( + ( + f"-s={sim_id}", + f"-d={i}", + "-uart0_pty", + "-uart0_pty_wait_for_readers", + "-uart_pty_wait", + f"--vm-runs={code_py_runs + 1}", + ) + ) + else: + cmd = [str(native_sim_binary), f"--flash={flash}"] + # native_sim vm-runs includes the boot VM setup run. + realtime_flag = "-rt" if use_realtime else "-no-rt" + cmd.extend( + ( + realtime_flag, + "-display_headless", + "-i2s_earless", + "-wait_uart", + f"--vm-runs={code_py_runs + 1}", + ) + ) + + if flash_erase_block_size is not None: + cmd.append(f"--flash_erase_block_size={flash_erase_block_size}") + if flash_write_block_size is not None: + cmd.append(f"--flash_write_block_size={flash_write_block_size}") + if flash_config_marker and "total_size" in flash_config_marker.kwargs: + cmd.append(f"--flash_total_size={flash_total_size}") + + if input_trace_file is not None: + cmd.append(f"--input-trace={input_trace_file}") + + marker = request.node.get_closest_marker("disable_i2c_devices") + if marker and len(marker.args) > 0: + for device in marker.args: + cmd.append(f"--disable-i2c={device}") + + if pixel_format is not None: + cmd.append(f"--display_pixel_format={PIXEL_FORMAT_BITMASK[pixel_format]}") + + if mono_vtiled is not None: + cmd.append(f"--display_mono_vtiled={'true' if mono_vtiled else 'false'}") + + env = os.environ.copy() + env.update(native_sim_env) + + capture_png_pattern = None + if capture_times_ns is not None: + if instance_count == 1: + capture_png_pattern = str(tmp_path / "frame_%d.png") + else: + capture_png_pattern = str(tmp_path / f"frame-{i}_%d.png") + cmd.append(f"--display_capture_png={capture_png_pattern}") + + logger.info("Running: %s", " ".join(cmd)) + proc = NativeSimProcess(cmd, timeout, trace_file, env, flash_file=flash) + proc.display_dump = None + proc._capture_png_pattern = capture_png_pattern + proc._capture_count = len(capture_times_ns) if capture_times_ns is not None else 0 + procs.append(proc) + if instance_count == 1: + yield procs[0] + else: + yield procs + for i, proc in enumerate(procs): + if instance_count > 1: + print(f"---------- Instance {i} -----------") + proc.shutdown() + + print("All serial output:") + print(proc.serial.all_output) + print() + print("All debug serial output:") + print(proc.debug_serial.all_output) diff --git a/ports/zephyr-cp/tests/docs/babblesim.md b/ports/zephyr-cp/tests/docs/babblesim.md new file mode 100644 index 0000000000000..75d45079b2e68 --- /dev/null +++ b/ports/zephyr-cp/tests/docs/babblesim.md @@ -0,0 +1,81 @@ +# BabbleSim testing + +This document describes how to build and run CircuitPython tests against the +BabbleSim (bsim) nRF5340 board. + +## Board target + +We use the Zephyr BabbleSim board for the nRF5340 application core: + +- Zephyr board: `nrf5340bsim/nrf5340/cpuapp` +- CircuitPython board alias: `native_nrf5340bsim` + +The tests expect two bsim instances to run in the same simulation, which allows +future BLE/802.15.4 multi-node tests. + +## Prerequisites + +BabbleSim needs to be available to Zephyr. Either: + +- Use the repo-provided `tools/bsim` checkout (if present) +- Or set environment variables: + +``` +export BSIM_COMPONENTS_PATH=/path/to/bsim/components +export BSIM_OUT_PATH=/path/to/bsim +``` + +## Build + +``` +CCACHE_TEMPDIR=/tmp/ccache-tmp make -j BOARD=native_nrf5340bsim +``` + +If you do not use ccache, you can omit `CCACHE_TEMPDIR`. + +## Run the bsim test + +``` +pytest tests/test_bsim_basics.py -v +``` + +## BLE scan + advertising tests + +The BLE tests run multiple bsim instances and build Zephyr samples on-demand: + +- `tests/test_bsim_ble_scan.py` scans for the Zephyr beacon sample +- `tests/test_bsim_ble_advertising.py` advertises from CircuitPython while the + Zephyr observer sample scans + +The fixtures build the Zephyr samples if missing: + +- Beacon: `zephyr/samples/bluetooth/beacon` (board `nrf52_bsim`) +- Observer: `zephyr/samples/bluetooth/observer` (board `nrf52_bsim`) + +Run the tests with: + +``` +pytest tests/test_bsim_ble_scan.py -v +pytest tests/test_bsim_ble_advertising.py -v +``` + +## Pytest markers + +For bsim-specific test tuning: + +- `@pytest.mark.duration(seconds)` controls simulation runtime/timeout. + +Example: + +```py +pytestmark = pytest.mark.duration(30.0) +``` + +## Notes + +- The bsim test spawns two instances that share a sim id. It only checks UART + output for now, but is the base for BLE/Thread multi-node tests. +- The BLE tests rely on the sysbuild HCI IPC net-core image for the nRF5340 + simulator (enabled via `sysbuild.conf`). +- The board uses a custom devicetree overlay to provide the SRAM region and + CircuitPython flash partition expected by the port. diff --git a/ports/zephyr-cp/tests/docs/i2c_emulator_cmdline_control.md b/ports/zephyr-cp/tests/docs/i2c_emulator_cmdline_control.md new file mode 100644 index 0000000000000..8ee2925915c83 --- /dev/null +++ b/ports/zephyr-cp/tests/docs/i2c_emulator_cmdline_control.md @@ -0,0 +1,306 @@ +# Command-Line Control of Emulated I2C Devices in native_sim + +This document describes an approach for enabling/disabling emulated I2C devices +at runtime via command-line options in Zephyr's native_sim environment. + +## Background + +Zephyr's I2C emulation framework (`zephyr,i2c-emul-controller`) provides: + +1. **Bus emulation** - Fake I2C controller that routes transfers to emulated devices +2. **Device emulators** - Software implementations of I2C peripherals (sensors, etc.) +3. **Backend APIs** - Test interfaces for manipulating emulator state + +However, there's no built-in mechanism to enable/disable emulated devices from the +command line. This capability would be useful for: + +- Testing device hot-plug scenarios +- Simulating hardware failures +- Testing error handling paths in CircuitPython + +## Relevant Zephyr APIs + +### I2C Emulator Structure + +From `include/zephyr/drivers/i2c_emul.h`: + +```c +struct i2c_emul { + sys_snode_t node; + const struct emul *target; + const struct i2c_emul_api *api; + struct i2c_emul_api *mock_api; // If non-NULL, takes precedence + uint16_t addr; +}; + +struct i2c_emul_api { + i2c_emul_transfer_t transfer; +}; +``` + +Key insight: The `mock_api` field allows overriding the normal transfer function. +If `mock_api->transfer()` returns `-ENOSYS`, it falls back to the real API. + +### Command-Line Registration + +From `boards/native/native_sim/cmdline.h`: + +```c +void native_add_command_line_opts(struct args_struct_t *args); +``` + +### Emulator Lookup + +From `include/zephyr/drivers/emul.h`: + +```c +const struct emul *emul_get_binding(const char *name); +``` + +## Implementation Approach + +### 1. Create a Disabled Device Registry + +Track which devices are "disabled" (should NACK all transactions): + +```c +// i2c_emul_cmdline.c + +#include +#include +#include +#include "nsi_cmdline.h" + +#define MAX_DISABLED_DEVICES 16 + +static struct { + const char *name; + const struct emul *emul; + struct i2c_emul_api mock_api; + struct i2c_emul_api *original_mock_api; + bool disabled; +} disabled_devices[MAX_DISABLED_DEVICES]; + +static int num_disabled_devices = 0; +``` + +### 2. Mock Transfer Function + +Return `-EIO` (simulates NACK) when device is disabled: + +```c +static int disabled_device_transfer(const struct emul *target, + struct i2c_msg *msgs, + int num_msgs, + int addr) +{ + // Find this device in our registry + for (int i = 0; i < num_disabled_devices; i++) { + if (disabled_devices[i].emul == target) { + if (disabled_devices[i].disabled) { + // Device is disabled - simulate NACK + return -EIO; + } + break; + } + } + // Fall back to normal emulator behavior + return -ENOSYS; +} +``` + +### 3. Enable/Disable Functions + +```c +int i2c_emul_cmdline_disable_device(const char *name) +{ + const struct emul *emul = emul_get_binding(name); + if (!emul || emul->bus_type != EMUL_BUS_TYPE_I2C) { + return -ENODEV; + } + + // Find or create registry entry + int idx = -1; + for (int i = 0; i < num_disabled_devices; i++) { + if (disabled_devices[i].emul == emul) { + idx = i; + break; + } + } + + if (idx < 0) { + if (num_disabled_devices >= MAX_DISABLED_DEVICES) { + return -ENOMEM; + } + idx = num_disabled_devices++; + disabled_devices[idx].name = name; + disabled_devices[idx].emul = emul; + disabled_devices[idx].mock_api.transfer = disabled_device_transfer; + + // Save and replace mock_api + disabled_devices[idx].original_mock_api = emul->bus.i2c->mock_api; + emul->bus.i2c->mock_api = &disabled_devices[idx].mock_api; + } + + disabled_devices[idx].disabled = true; + return 0; +} + +int i2c_emul_cmdline_enable_device(const char *name) +{ + for (int i = 0; i < num_disabled_devices; i++) { + if (strcmp(disabled_devices[i].name, name) == 0) { + disabled_devices[i].disabled = false; + return 0; + } + } + return -ENODEV; +} +``` + +### 4. Command-Line Option Registration + +```c +static char *disabled_device_args[MAX_DISABLED_DEVICES]; +static int num_disabled_device_args = 0; + +static void cmd_disable_i2c_device(char *argv, int offset) +{ + ARG_UNUSED(offset); + if (num_disabled_device_args < MAX_DISABLED_DEVICES) { + disabled_device_args[num_disabled_device_args++] = argv; + } +} + +static struct args_struct_t i2c_emul_args[] = { + { + .option = "disable-i2c", + .name = "device_name", + .type = 's', + .call_when_found = cmd_disable_i2c_device, + .descript = "Disable an emulated I2C device (can be repeated)" + }, + ARG_TABLE_ENDMARKER +}; + +static void register_cmdline_opts(void) +{ + native_add_command_line_opts(i2c_emul_args); +} + +// Hook into native_sim initialization +NATIVE_TASK(register_cmdline_opts, PRE_BOOT_1, 0); + +static void apply_disabled_devices(void) +{ + for (int i = 0; i < num_disabled_device_args; i++) { + int rc = i2c_emul_cmdline_disable_device(disabled_device_args[i]); + if (rc != 0) { + printk("Warning: Failed to disable I2C device '%s': %d\n", + disabled_device_args[i], rc); + } + } +} + +// Apply after emulators are initialized +NATIVE_TASK(apply_disabled_devices, PRE_BOOT_3, 0); +``` + +### 5. Usage + +After building with this code: + +```bash +# Disable a sensor at startup +./build/zephyr/zephyr.exe --disable-i2c=bmi160@68 + +# Disable multiple devices +./build/zephyr/zephyr.exe --disable-i2c=bmi160@68 --disable-i2c=sht4x@44 +``` + +## Runtime Control Extension + +For runtime enable/disable (not just at startup), you could: + +### Option A: Use a Named Pipe / FIFO + +```c +// Create a FIFO that accepts commands +// "disable bmi160@68" or "enable bmi160@68" +static void *cmdline_control_thread(void *arg) +{ + int fd = open("/tmp/i2c_emul_control", O_RDONLY); + char buf[256]; + while (read(fd, buf, sizeof(buf)) > 0) { + if (strncmp(buf, "disable ", 8) == 0) { + i2c_emul_cmdline_disable_device(buf + 8); + } else if (strncmp(buf, "enable ", 7) == 0) { + i2c_emul_cmdline_enable_device(buf + 7); + } + } + return NULL; +} +``` + +### Option B: Signal Handler + +Use `SIGUSR1`/`SIGUSR2` with a config file that specifies which device to toggle. + +### Option C: Shared Memory + +Map a shared memory region that external tools can write to for device state. + +## Integration with CircuitPython Tests + +For pytest-based tests, you could: + +```python +import subprocess +import os + +class NativeSimProcess: + def __init__(self, exe_path): + self.exe_path = exe_path + self.control_fifo = "/tmp/i2c_emul_control" + + def start(self, disabled_devices=None): + args = [self.exe_path] + if disabled_devices: + for dev in disabled_devices: + args.extend(["--disable-i2c", dev]) + self.proc = subprocess.Popen(args, ...) + + def disable_device(self, name): + """Runtime disable via FIFO""" + with open(self.control_fifo, 'w') as f: + f.write(f"disable {name}\n") + + def enable_device(self, name): + """Runtime enable via FIFO""" + with open(self.control_fifo, 'w') as f: + f.write(f"enable {name}\n") +``` + +## Alternative: Device Tree Approach + +For compile-time configuration, use device tree overlays: + +```dts +// boards/native_sim_no_bmi160.overlay +&bmi160 { + status = "disabled"; +}; +``` + +Build separate variants: +```bash +west build -b native_sim -- -DDTC_OVERLAY_FILE=boards/native_sim_no_bmi160.overlay +``` + +## References + +- Zephyr I2C Emulation: `zephyr/drivers/i2c/i2c_emul.c` +- Emulator Framework: `zephyr/doc/hardware/emulator/bus_emulators.rst` +- Native Sim Docs: `zephyr/boards/native/native_sim/doc/index.rst` +- Command-line handling: `zephyr/boards/native/native_sim/cmdline.c` +- Example mock API usage: `zephyr/tests/drivers/sensor/bmi160/src/i2c.c` diff --git a/ports/zephyr-cp/tests/docs/web_workflow.md b/ports/zephyr-cp/tests/docs/web_workflow.md new file mode 100644 index 0000000000000..eb6742b8a3ec6 --- /dev/null +++ b/ports/zephyr-cp/tests/docs/web_workflow.md @@ -0,0 +1,37 @@ +# Web Workflow native_sim Tests + +These tests validate CircuitPython's web workflow support in the Zephyr native_sim port, including filesystem write behavior with and without USB-style write protection. + +## Coverage + +- `test_web_workflow_hostnetwork`: Verifies the web workflow HTTP server responds and enforces authentication (`/edit/` returns `401 Unauthorized`). +- `test_web_workflow_write_code_py_conflict`: Exercises a write attempt while the filesystem is protected (no `boot.py` remount). The DELETE request should return `409 Conflict`. +- `test_web_workflow_write_code_py_remount`: Uses a `boot.py` remount to allow CircuitPython to write. A PUT request updates `code.py`, and a subsequent GET verifies the contents. + +## Filesystem Setup + +The tests create a flash image with: + +- `settings.toml` containing `CIRCUITPY_WEB_API_PASSWORD="testpass"` so the web workflow starts using the on-device settings file. +- `boot.py` (for the remount test only) with: + ```python + import storage + storage.remount("/", readonly=False) + ``` + This disables concurrent write protection so the web workflow can write to CIRCUITPY. + +## Running the Tests + +Build native_sim (if needed): + +```bash +make BOARD=native_native_sim +``` + +Run the tests: + +```bash +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_hostnetwork -vv +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_write_code_py_conflict -vv +pytest -q ports/zephyr-cp/tests/test_web_workflow.py::test_web_workflow_write_code_py_remount -vv +``` diff --git a/ports/zephyr-cp/tests/perfetto_input_trace.py b/ports/zephyr-cp/tests/perfetto_input_trace.py new file mode 100644 index 0000000000000..494c9cdcadf69 --- /dev/null +++ b/ports/zephyr-cp/tests/perfetto_input_trace.py @@ -0,0 +1,159 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Utilities for creating Perfetto input trace files for native_sim tests. + +This module can be used directly from Python or from the command line: + + python -m tests.perfetto_input_trace input_trace.json output.perfetto + +Input JSON format — counter tracks use [timestamp, value] pairs, instant +tracks use bare timestamps: + +{ + "gpio_emul.01": [[8000000000, 0], [9000000000, 1], [10000000000, 0]], + "display_capture": [500000000, 1000000000] +} +""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Mapping, Sequence + +# Counter tracks: list of (timestamp, value) pairs. +# Instant tracks: list of timestamps (bare ints). +InputTraceData = Mapping[str, Sequence[tuple[int, int] | int]] + + +def _load_perfetto_pb2(): + from perfetto.protos.perfetto.trace import perfetto_trace_pb2 as perfetto_pb2 + + return perfetto_pb2 + + +def _is_instant_track(events: Sequence) -> bool: + """Return True if *events* is a list of bare timestamps (instant track).""" + if not events: + return False + return isinstance(events[0], int) + + +def build_input_trace(trace_data: InputTraceData, *, sequence_id: int = 1): + """Build a Perfetto Trace protobuf for input replay counter and instant tracks.""" + perfetto_pb2 = _load_perfetto_pb2() + trace = perfetto_pb2.Trace() + + seq_incremental_state_cleared = 1 + seq_needs_incremental_state = 2 + + for idx, (track_name, events) in enumerate(trace_data.items()): + track_uuid = 1001 + idx + instant = _is_instant_track(events) + + desc_packet = trace.packet.add() + desc_packet.timestamp = 0 + desc_packet.trusted_packet_sequence_id = sequence_id + if idx == 0: + desc_packet.sequence_flags = seq_incremental_state_cleared + desc_packet.track_descriptor.uuid = track_uuid + desc_packet.track_descriptor.name = track_name + if not instant: + desc_packet.track_descriptor.counter.unit = ( + perfetto_pb2.CounterDescriptor.Unit.UNIT_COUNT + ) + + if instant: + for ts in events: + event_packet = trace.packet.add() + event_packet.timestamp = ts + event_packet.trusted_packet_sequence_id = sequence_id + event_packet.sequence_flags = seq_needs_incremental_state + event_packet.track_event.type = perfetto_pb2.TrackEvent.Type.TYPE_INSTANT + event_packet.track_event.track_uuid = track_uuid + else: + for ts, value in events: + event_packet = trace.packet.add() + event_packet.timestamp = ts + event_packet.trusted_packet_sequence_id = sequence_id + event_packet.sequence_flags = seq_needs_incremental_state + event_packet.track_event.type = perfetto_pb2.TrackEvent.Type.TYPE_COUNTER + event_packet.track_event.track_uuid = track_uuid + event_packet.track_event.counter_value = value + + return trace + + +def write_input_trace( + trace_file: Path, trace_data: InputTraceData, *, sequence_id: int = 1 +) -> None: + """Write input replay data to a Perfetto trace file.""" + trace = build_input_trace(trace_data, sequence_id=sequence_id) + trace_file.parent.mkdir(parents=True, exist_ok=True) + trace_file.write_bytes(trace.SerializeToString()) + + +def _parse_trace_json(data: object) -> dict[str, list[tuple[int, int]] | list[int]]: + if not isinstance(data, dict): + raise ValueError("top-level JSON value must be an object") + + parsed: dict[str, list[tuple[int, int]] | list[int]] = {} + for track_name, events in data.items(): + if not isinstance(track_name, str): + raise ValueError("track names must be strings") + if not isinstance(events, list): + raise ValueError(f"track {track_name!r} must map to a list of events") + + if not events: + parsed[track_name] = [] + continue + + # Distinguish instant (bare ints) vs counter ([ts, value] pairs). + if isinstance(events[0], (int, float)): + parsed[track_name] = [int(ts) for ts in events] + else: + parsed_events: list[tuple[int, int]] = [] + for event in events: + if not isinstance(event, (list, tuple)) or len(event) != 2: + raise ValueError( + f"track {track_name!r} events must be [timestamp, value] pairs " + "or bare timestamps" + ) + timestamp_ns, value = event + parsed_events.append((int(timestamp_ns), int(value))) + parsed[track_name] = parsed_events + + return parsed + + +def _build_arg_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser( + description="Generate a Perfetto input trace file used by native_sim --input-trace" + ) + parser.add_argument("input_json", type=Path, help="Path to input trace JSON") + parser.add_argument("output_trace", type=Path, help="Output .perfetto file path") + parser.add_argument( + "--sequence-id", + type=int, + default=1, + help="trusted_packet_sequence_id to use (default: 1)", + ) + return parser + + +def main(argv: Sequence[str] | None = None) -> int: + parser = _build_arg_parser() + args = parser.parse_args(argv) + + trace_json = json.loads(args.input_json.read_text()) + trace_data = _parse_trace_json(trace_json) + write_input_trace(args.output_trace, trace_data, sequence_id=args.sequence_id) + + print(f"Wrote {args.output_trace} ({len(trace_data)} tracks)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ports/zephyr-cp/tests/test_adafruit_bus_device.py b/ports/zephyr-cp/tests/test_adafruit_bus_device.py new file mode 100644 index 0000000000000..3022838506e77 --- /dev/null +++ b/ports/zephyr-cp/tests/test_adafruit_bus_device.py @@ -0,0 +1,236 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test adafruit_bus_device.i2c_device.I2CDevice against the AT24 EEPROM emulator.""" + +import pytest + + +PROBE_OK_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) +print(f"device created: {type(device).__name__}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_OK_CODE}) +def test_i2cdevice_probe_success(circuitpython): + """Constructing I2CDevice with probe=True succeeds when AT24 is present at 0x50.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "device created: I2CDevice" in output + assert "done" in output + + +PROBE_FAIL_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +try: + device = I2CDevice(i2c, 0x51) + print("unexpected_success") +except ValueError as e: + print(f"probe_failed: {e}") +except OSError as e: + print(f"probe_failed: {e}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_FAIL_CODE}) +def test_i2cdevice_probe_failure(circuitpython): + """Constructing I2CDevice with probe=True raises when no device responds.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "probe_failed" in output + assert "unexpected_success" not in output + assert "done" in output + + +PROBE_DISABLED_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +# probe=False should not raise even without a device at this address +device = I2CDevice(i2c, 0x51, probe=False) +print(f"device created: {type(device).__name__}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": PROBE_DISABLED_CODE}) +def test_i2cdevice_probe_disabled(circuitpython): + """Constructing I2CDevice with probe=False succeeds regardless of device presence.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "device created: I2CDevice" in output + assert "done" in output + + +READ_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Read first byte by writing the memory address, then reading. +buf = bytearray(1) +with device: + device.write(bytes([0x00])) + device.readinto(buf) +print(f"AT24 byte 0: 0x{buf[0]:02X}") +if buf[0] == 0xFF: + print("eeprom_valid") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": READ_CODE}) +def test_i2cdevice_write_then_readinto_separate(circuitpython): + """write() followed by readinto() inside a single context manager block reads EEPROM data.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "AT24 byte 0: 0xFF" in output + assert "eeprom_valid" in output + assert "done" in output + + +WRITE_THEN_READINTO_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +out_buf = bytes([0x00]) +in_buf = bytearray(4) +with device: + device.write_then_readinto(out_buf, in_buf) +print(f"first 4 bytes: {[hex(b) for b in in_buf]}") +if all(b == 0xFF for b in in_buf): + print("eeprom_valid") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_THEN_READINTO_CODE}) +def test_i2cdevice_write_then_readinto_atomic(circuitpython): + """write_then_readinto() performs an atomic write+read against the EEPROM.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "first 4 bytes:" in output + assert "eeprom_valid" in output + assert "done" in output + + +WRITE_READBACK_CODE = """\ +import board +import time +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Write four bytes starting at EEPROM address 0x10. +payload = bytes([0xDE, 0xAD, 0xBE, 0xEF]) +with device: + device.write(bytes([0x10]) + payload) + +# EEPROM needs a moment to commit the write internally. +time.sleep(0.01) + +readback = bytearray(4) +with device: + device.write_then_readinto(bytes([0x10]), readback) +print(f"readback: {[hex(b) for b in readback]}") +if bytes(readback) == payload: + print("readback_ok") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READBACK_CODE}) +def test_i2cdevice_write_then_read_roundtrip(circuitpython): + """Writing bytes to the EEPROM and reading them back returns the written values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "readback_ok" in output + assert "done" in output + + +SLICE_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +device = I2CDevice(i2c, 0x50) + +# Use start/end kwargs to send only a slice of the outgoing buffer. +out = bytearray([0xAA, 0x00, 0xBB]) +dest = bytearray(4) +with device: + # Only send the middle byte (the memory address 0x00). + device.write_then_readinto(out, dest, out_start=1, out_end=2, in_start=0, in_end=2) +print(f"partial read: {[hex(b) for b in dest]}") +# Only the first two entries should have been written by the read. +if dest[0] == 0xFF and dest[1] == 0xFF and dest[2] == 0x00 and dest[3] == 0x00: + print("slice_ok") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SLICE_CODE}) +def test_i2cdevice_buffer_slices(circuitpython): + """write_then_readinto honors out_start/out_end and in_start/in_end bounds.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "slice_ok" in output + assert "done" in output + + +DISABLED_CODE = """\ +import board +from adafruit_bus_device.i2c_device import I2CDevice + +i2c = board.I2C() +try: + device = I2CDevice(i2c, 0x50) + print("unexpected_success") +except (ValueError, OSError) as e: + print(f"probe_failed: {e}") +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": DISABLED_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2cdevice_probe_fails_when_device_disabled(circuitpython): + """Probe fails when the AT24 emulator device is disabled on the bus.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "probe_failed" in output + assert "unexpected_success" not in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_aesio.py b/ports/zephyr-cp/tests/test_aesio.py new file mode 100644 index 0000000000000..3ae016ac8e346 --- /dev/null +++ b/ports/zephyr-cp/tests/test_aesio.py @@ -0,0 +1,223 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the aesio module.""" + +import pytest + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + + +KEY = b"Sixteen byte key" +PLAINTEXT = b"CircuitPython!!!" # 16 bytes + + +ECB_CODE = """\ +import aesio + +key = b'Sixteen byte key' +inp = b'CircuitPython!!!' +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_ECB) +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +decrypted = bytearray(len(outp)) +cipher.decrypt_into(bytes(outp), decrypted) +print(f"decrypted: {bytes(decrypted)}") +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": ECB_CODE}) +def test_aesio_ecb(circuitpython): + """AES-ECB round-trips and matches CPython cryptography's output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.ECB()).encryptor() + expected_hex = (encryptor.update(PLAINTEXT) + encryptor.finalize()).hex() + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +IV = b"InitializationVe" # 16 bytes +CBC_PLAINTEXT = b"CircuitPython!!!" * 2 # 32 bytes, multiple of 16 +CTR_PLAINTEXT = b"CircuitPython is fun to use!" # 28 bytes, arbitrary length + + +CBC_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +inp = b'CircuitPython!!!' * 2 +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_CBC, iv) +print(f"mode: {cipher.mode}") +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +# Re-create cipher to reset IV state for decryption. +cipher2 = aesio.AES(key, aesio.MODE_CBC, iv) +decrypted = bytearray(len(outp)) +cipher2.decrypt_into(bytes(outp), decrypted) +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CBC_CODE}) +def test_aesio_cbc(circuitpython): + """AES-CBC round-trips and matches CPython cryptography's output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.CBC(IV)).encryptor() + expected_hex = (encryptor.update(CBC_PLAINTEXT) + encryptor.finalize()).hex() + assert "mode: 2" in output + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +CTR_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +inp = b'CircuitPython is fun to use!' +outp = bytearray(len(inp)) +cipher = aesio.AES(key, aesio.MODE_CTR, iv) +print(f"mode: {cipher.mode}") +cipher.encrypt_into(inp, outp) +print(f"ciphertext_hex: {outp.hex()}") + +cipher2 = aesio.AES(key, aesio.MODE_CTR, iv) +decrypted = bytearray(len(outp)) +cipher2.decrypt_into(bytes(outp), decrypted) +print(f"decrypted: {bytes(decrypted)}") +print(f"match: {bytes(decrypted) == inp}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": CTR_CODE}) +def test_aesio_ctr(circuitpython): + """AES-CTR handles arbitrary-length buffers and matches CPython output.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + encryptor = Cipher(algorithms.AES(KEY), modes.CTR(IV)).encryptor() + expected_hex = (encryptor.update(CTR_PLAINTEXT) + encryptor.finalize()).hex() + assert "mode: 6" in output + assert f"ciphertext_hex: {expected_hex}" in output + assert "match: True" in output + assert "done" in output + + +REKEY_CODE = """\ +import aesio + +key1 = b'Sixteen byte key' +key2 = b'Another 16 byte!' +inp = b'CircuitPython!!!' + +cipher = aesio.AES(key1, aesio.MODE_ECB) +out1 = bytearray(16) +cipher.encrypt_into(inp, out1) +print(f"ct1_hex: {out1.hex()}") + +cipher.rekey(key2) +out2 = bytearray(16) +cipher.encrypt_into(inp, out2) +print(f"ct2_hex: {out2.hex()}") +print(f"different: {bytes(out1) != bytes(out2)}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": REKEY_CODE}) +def test_aesio_rekey(circuitpython): + """rekey() switches the active key; ciphertexts match CPython for both keys.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + enc1 = Cipher(algorithms.AES(b"Sixteen byte key"), modes.ECB()).encryptor() + ct1 = (enc1.update(PLAINTEXT) + enc1.finalize()).hex() + enc2 = Cipher(algorithms.AES(b"Another 16 byte!"), modes.ECB()).encryptor() + ct2 = (enc2.update(PLAINTEXT) + enc2.finalize()).hex() + assert f"ct1_hex: {ct1}" in output + assert f"ct2_hex: {ct2}" in output + assert "different: True" in output + assert "done" in output + + +MODE_PROPERTY_CODE = """\ +import aesio + +key = b'Sixteen byte key' +iv = b'InitializationVe' +cipher = aesio.AES(key, aesio.MODE_ECB) +print(f"initial: {cipher.mode}") +print(f"ECB={aesio.MODE_ECB} CBC={aesio.MODE_CBC} CTR={aesio.MODE_CTR}") + +for name, m in (("ECB", aesio.MODE_ECB), ("CBC", aesio.MODE_CBC), ("CTR", aesio.MODE_CTR)): + cipher.mode = m + print(f"set_{name}: {cipher.mode}") + +try: + cipher.mode = 99 +except NotImplementedError as e: + print(f"bad_mode: NotImplementedError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": MODE_PROPERTY_CODE}) +def test_aesio_mode_property(circuitpython): + """The mode property is readable, writable, and rejects unsupported values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "initial: 1" in output + assert "ECB=1 CBC=2 CTR=6" in output + assert "set_ECB: 1" in output + assert "set_CBC: 2" in output + assert "set_CTR: 6" in output + assert "bad_mode: NotImplementedError" in output + assert "done" in output + + +KEY_LENGTHS_CODE = """\ +import aesio + +inp = b'CircuitPython!!!' +for key in (b'A' * 16, b'B' * 24, b'C' * 32): + cipher = aesio.AES(key, aesio.MODE_ECB) + out = bytearray(16) + cipher.encrypt_into(inp, out) + print(f"len{len(key)}: {out.hex()}") + +try: + aesio.AES(b'too short', aesio.MODE_ECB) +except ValueError: + print("bad_key: ValueError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": KEY_LENGTHS_CODE}) +def test_aesio_key_lengths(circuitpython): + """AES-128/192/256 keys all work and match CPython; bad key length raises.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + for key in (b"A" * 16, b"B" * 24, b"C" * 32): + encryptor = Cipher(algorithms.AES(key), modes.ECB()).encryptor() + expected = (encryptor.update(PLAINTEXT) + encryptor.finalize()).hex() + assert f"len{len(key)}: {expected}" in output + assert "bad_key: ValueError" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_audiobusio.py b/ports/zephyr-cp/tests/test_audiobusio.py new file mode 100644 index 0000000000000..5a899139c2210 --- /dev/null +++ b/ports/zephyr-cp/tests/test_audiobusio.py @@ -0,0 +1,216 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test audiobusio I2SOut functionality on native_sim.""" + +from pathlib import Path + +import pytest +from perfetto.trace_processor import TraceProcessor + + +I2S_PLAY_CODE = """\ +import array +import math +import audiocore +import board +import time + +# Generate a 440 Hz sine wave, 16-bit signed stereo at 16000 Hz +sample_rate = 16000 +length = sample_rate // 440 # ~36 samples per period +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) # left + values.append(v) # right + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +print("playing") +dac.play(sample, loop=True) +time.sleep(0.5) +dac.stop() +print("stopped") +print("done") +""" + + +def parse_i2s_trace(trace_file: Path, track_name: str) -> list[tuple[int, int]]: + """Parse I2S counter trace from Perfetto trace file.""" + tp = TraceProcessor(file_path=str(trace_file)) + result = tp.query( + f""" + SELECT c.ts, c.value + FROM counter c + JOIN track t ON c.track_id = t.id + WHERE t.name LIKE "%{track_name}" + ORDER BY c.ts + """ + ) + return [(int(row.ts), int(row.value)) for row in result] + + +@pytest.mark.duration(10) +@pytest.mark.circuitpy_drive({"code.py": I2S_PLAY_CODE}) +def test_i2s_play_and_stop(circuitpython): + """Test I2SOut play and stop produce expected output and correct waveform traces.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "playing" in output + assert "stopped" in output + assert "done" in output + + # Check that Perfetto trace has I2S counter tracks with data + left_trace = parse_i2s_trace(circuitpython.trace_file, "Left") + right_trace = parse_i2s_trace(circuitpython.trace_file, "Right") + + # Should have counter events (initial zero + audio data) + assert len(left_trace) > 10, f"Expected many Left channel events, got {len(left_trace)}" + assert len(right_trace) > 10, f"Expected many Right channel events, got {len(right_trace)}" + + # Verify timestamps are spread out (not all the same) + left_timestamps = [ts for ts, _ in left_trace] + assert left_timestamps[-1] > left_timestamps[1], "Timestamps should increase over time" + time_span_ns = left_timestamps[-1] - left_timestamps[1] + # We play for 0.5s, so span should be at least 100ms + assert time_span_ns > 100_000_000, f"Expected >100ms time span, got {time_span_ns / 1e6:.1f}ms" + + # Audio data should contain non-zero values (sine wave) + # Skip the initial zero value + left_values = [v for _, v in left_trace if v != 0] + right_values = [v for _, v in right_trace if v != 0] + assert len(left_values) > 5, "Left channel has too few non-zero values" + assert len(right_values) > 5, "Right channel has too few non-zero values" + + # Sine wave should have both positive and negative values + assert any(v > 0 for v in left_values), "Left channel has no positive values" + assert any(v < 0 for v in left_values), "Left channel has no negative values" + + # Verify amplitude is in the expected range (we generate with amplitude 30000) + max_left = max(left_values) + min_left = min(left_values) + assert max_left > 20000, f"Left max {max_left} too low, expected >20000" + assert min_left < -20000, f"Left min {min_left} too high, expected <-20000" + + # Left and right should match (we write the same value to both channels) + # Compare a subset of matching timestamps + left_by_ts = dict(left_trace) + right_by_ts = dict(right_trace) + common_ts = sorted(set(left_by_ts.keys()) & set(right_by_ts.keys())) + mismatches = 0 + for ts in common_ts[:100]: + if left_by_ts[ts] != right_by_ts[ts]: + mismatches += 1 + assert mismatches == 0, ( + f"{mismatches} L/R mismatches in first {min(100, len(common_ts))} common timestamps" + ) + + +I2S_PLAY_NO_STOP_CODE = """\ +import array +import math +import audiocore +import board +import time + +sample_rate = 16000 +length = sample_rate // 440 +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) + values.append(v) + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +dac.play(sample, loop=True) +print("playing") +time.sleep(0.2) +# Exit without calling dac.stop() — reset_port should clean up +print("exiting") +""" + + +@pytest.mark.duration(15) +@pytest.mark.code_py_runs(2) +@pytest.mark.circuitpy_drive({"code.py": I2S_PLAY_NO_STOP_CODE}) +def test_i2s_stops_on_code_exit(circuitpython): + """Test I2S is stopped by reset_port when code.py exits without explicit stop.""" + # First run: plays audio then exits without stopping + circuitpython.serial.wait_for("exiting") + circuitpython.serial.wait_for("Press any key to enter the REPL") + # Trigger soft reload + circuitpython.serial.write("\x04") + + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + # Should see "playing" and "exiting" at least twice (once per run) + assert output.count("playing") >= 2 + assert output.count("exiting") >= 2 + + +I2S_PAUSE_RESUME_CODE = """\ +import array +import math +import audiocore +import board +import time + +sample_rate = 16000 +length = sample_rate // 440 +values = [] +for i in range(length): + v = int(math.sin(math.pi * 2 * i / length) * 30000) + values.append(v) + values.append(v) + +sample = audiocore.RawSample( + array.array("h", values), + sample_rate=sample_rate, + channel_count=2, +) + +dac = board.I2S0() +dac.play(sample, loop=True) +print("playing") +time.sleep(0.2) + +dac.pause() +print("paused") +assert dac.paused +time.sleep(0.1) + +dac.resume() +print("resumed") +assert not dac.paused +time.sleep(0.2) + +dac.stop() +print("done") +""" + + +@pytest.mark.duration(10) +@pytest.mark.circuitpy_drive({"code.py": I2S_PAUSE_RESUME_CODE}) +def test_i2s_pause_resume(circuitpython): + """Test I2SOut pause and resume work correctly.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "playing" in output + assert "paused" in output + assert "resumed" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_basics.py b/ports/zephyr-cp/tests/test_basics.py new file mode 100644 index 0000000000000..84b31849a8e81 --- /dev/null +++ b/ports/zephyr-cp/tests/test_basics.py @@ -0,0 +1,117 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test basic native_sim functionality.""" + +import pytest + + +@pytest.mark.circuitpy_drive(None) +def test_blank_flash_hello_world(circuitpython): + """Test that an erased flash shows code.py output header.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "Board ID:native_native_sim" in output + assert "UID:" in output + assert "code.py output:" in output + assert "Hello World" in output + assert "done" in output + + +# --- PTY Input Tests --- + + +INPUT_CODE = """\ +import sys + +print("ready") +char = sys.stdin.read(1) +print(f"received: {repr(char)}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": INPUT_CODE}) +def test_basic_serial_input(circuitpython): + """Test reading single character from serial via PTY write.""" + circuitpython.serial.wait_for("ready") + circuitpython.serial.write("A") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "ready" in output + assert "received: 'A'" in output + assert "done" in output + + +INPUT_FUNC_CODE = """\ +print("ready") +name = input("Enter name: ") +print(f"hello {name}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": INPUT_FUNC_CODE}) +def test_input_function(circuitpython): + """Test the built-in input() function with PTY input.""" + circuitpython.serial.wait_for("Enter name:") + circuitpython.serial.write("World\r") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "ready" in output + assert "Enter name:" in output + assert "hello World" in output + assert "done" in output + + +INTERRUPT_CODE = """\ +import time + +print("starting") +for i in range(100): + print(f"loop {i}") + time.sleep(0.1) +print("completed") +""" + + +@pytest.mark.circuitpy_drive({"code.py": INTERRUPT_CODE}) +def test_ctrl_c_interrupt(circuitpython): + """Test sending Ctrl+C (0x03) to interrupt running code.""" + circuitpython.serial.wait_for("loop 5") + circuitpython.serial.write("\x03") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "starting" in output + assert "loop 5" in output + assert "KeyboardInterrupt" in output + assert "completed" not in output + + +RELOAD_CODE = """\ +print("first run") +import time +time.sleep(1) +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": RELOAD_CODE}) +@pytest.mark.code_py_runs(2) +def test_ctrl_d_soft_reload(circuitpython): + """Test sending Ctrl+D (0x04) to trigger soft reload.""" + circuitpython.serial.wait_for("first run") + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + # Should see "first run" appear multiple times due to reload + # or see a soft reboot message + output = circuitpython.serial.all_output + assert "first run" in output + # The soft reload should restart the code before "done" is printed + assert "done" in output + assert output.count("first run") > 1 diff --git a/ports/zephyr-cp/tests/test_digitalio.py b/ports/zephyr-cp/tests/test_digitalio.py new file mode 100644 index 0000000000000..22c64f7b83fd7 --- /dev/null +++ b/ports/zephyr-cp/tests/test_digitalio.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test digitalio functionality on native_sim.""" + +import re +from pathlib import Path + +import pytest +from perfetto.trace_processor import TraceProcessor + + +DIGITALIO_INPUT_TRACE_READ_CODE = """\ +import time +import digitalio +import microcontroller + +pin = digitalio.DigitalInOut(microcontroller.pin.P_01) +pin.direction = digitalio.Direction.INPUT + +start = time.monotonic() +last = pin.value +print(f"t_abs={time.monotonic():.3f} initial={last}") + +# Poll long enough to observe a high pulse injected through input trace. +while time.monotonic() - start < 8.0: + value = pin.value + if value != last: + print(f"t_abs={time.monotonic():.3f} edge={value}") + last = value + time.sleep(0.05) + +print(f"t_abs={time.monotonic():.3f} done") +""" + + +DIGITALIO_INPUT_TRACE = { + "gpio_emul.01": [ + (8_000_000_000, 0), + (9_000_000_000, 1), + (10_000_000_000, 0), + ], +} + + +@pytest.mark.duration(14.0) +@pytest.mark.circuitpy_drive({"code.py": DIGITALIO_INPUT_TRACE_READ_CODE}) +@pytest.mark.input_trace(DIGITALIO_INPUT_TRACE) +def test_digitalio_reads_input_trace(circuitpython): + """Test DigitalInOut input reads values injected via input trace.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + + initial_match = re.search(r"t_abs=([0-9]+\.[0-9]+) initial=False", output) + edge_match = re.search(r"t_abs=([0-9]+\.[0-9]+) edge=True", output) + done_match = re.search(r"t_abs=([0-9]+\.[0-9]+) done", output) + + assert initial_match is not None + assert edge_match is not None + assert done_match is not None + + initial_abs = float(initial_match.group(1)) + edge_abs = float(edge_match.group(1)) + done_abs = float(done_match.group(1)) + + # Input trace edge is at 9.0s for gpio_emul.01. + assert 8.5 <= edge_abs <= 9.5 + assert initial_abs <= edge_abs <= done_abs + + +BLINK_CODE = """\ +import time +import board +import digitalio + +led = digitalio.DigitalInOut(board.LED) +led.direction = digitalio.Direction.OUTPUT + +for i in range(3): + print(f"LED on {i}") + led.value = True + time.sleep(0.1) + print(f"LED off {i}") + led.value = False + time.sleep(0.1) + +print("done") +""" + + +def parse_gpio_trace(trace_file: Path, pin_name: str = "gpio_emul.00") -> list[tuple[int, int]]: + """Parse GPIO trace from Perfetto trace file.""" + tp = TraceProcessor(file_path=str(trace_file)) + result = tp.query( + f''' + SELECT c.ts, c.value + FROM counter c + JOIN track t ON c.track_id = t.id + WHERE t.name = "{pin_name}" + ORDER BY c.ts + ''' + ) + return [(row.ts, int(row.value)) for row in result] + + +@pytest.mark.circuitpy_drive({"code.py": BLINK_CODE}) +def test_digitalio_blink_output(circuitpython): + """Test blink program produces expected output and GPIO traces.""" + circuitpython.wait_until_done() + + # Check serial output + output = circuitpython.serial.all_output + assert "LED on 0" in output + assert "LED off 0" in output + assert "LED on 2" in output + assert "LED off 2" in output + assert "done" in output + + # Check GPIO traces - LED is on gpio_emul.00 + gpio_trace = parse_gpio_trace(circuitpython.trace_file, "gpio_emul.00") + + # Deduplicate by timestamp (keep last value at each timestamp) + by_timestamp = {} + for ts, val in gpio_trace: + by_timestamp[ts] = val + sorted_trace = sorted(by_timestamp.items()) + + # Find transition points (where value changes), skipping initialization at ts=0 + transitions = [] + for i in range(1, len(sorted_trace)): + prev_ts, prev_val = sorted_trace[i - 1] + curr_ts, curr_val = sorted_trace[i] + if prev_val != curr_val and curr_ts > 0: + transitions.append((curr_ts, curr_val)) + + # We expect at least 6 transitions (3 on + 3 off) from the blink loop + assert len(transitions) >= 6, f"Expected at least 6 transitions, got {len(transitions)}" + + # Verify timing between consecutive transitions + # Each sleep is 0.1s = 100ms = 100,000,000 ns + expected_interval_ns = 100_000_000 + tolerance_ns = 20_000_000 # 20ms tolerance + + # Find a sequence of 6 consecutive transitions with ~100ms intervals (the blink loop) + # This filters out initialization and cleanup noise + blink_transitions = [] + for i in range(len(transitions) - 1): + interval = transitions[i + 1][0] - transitions[i][0] + if abs(interval - expected_interval_ns) < tolerance_ns: + if not blink_transitions: + blink_transitions.append(transitions[i]) + blink_transitions.append(transitions[i + 1]) + elif blink_transitions: + # Found end of blink sequence + break + + assert len(blink_transitions) >= 6, ( + f"Expected at least 6 blink transitions with ~100ms intervals, got {len(blink_transitions)}" + ) + + # Verify timing between blink transitions + for i in range(1, min(6, len(blink_transitions))): + prev_ts = blink_transitions[i - 1][0] + curr_ts = blink_transitions[i][0] + interval = curr_ts - prev_ts + assert abs(interval - expected_interval_ns) < tolerance_ns, ( + f"Transition interval {interval / 1_000_000:.1f}ms deviates from " + f"expected {expected_interval_ns / 1_000_000:.1f}ms by more than " + f"{tolerance_ns / 1_000_000:.1f}ms tolerance" + ) diff --git a/ports/zephyr-cp/tests/test_flash.py b/ports/zephyr-cp/tests/test_flash.py new file mode 100644 index 0000000000000..e2e5f4de14f81 --- /dev/null +++ b/ports/zephyr-cp/tests/test_flash.py @@ -0,0 +1,171 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test flash filesystem with various erase block sizes.""" + +import subprocess + +import pytest + + +def read_file_from_flash(flash_file, path): + """Extract a file from the FAT filesystem in the flash image.""" + result = subprocess.run( + ["mcopy", "-i", str(flash_file), f"::{path}", "-"], + capture_output=True, + ) + if result.returncode != 0: + raise FileNotFoundError( + f"Failed to read ::{path} from {flash_file}: {result.stderr.decode()}" + ) + return result.stdout.decode() + + +WRITE_READ_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/test.txt", "w") as f: + f.write("hello flash") +with open("/test.txt", "r") as f: + content = f.read() +print(f"content: {content}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +def test_flash_default_erase_size(circuitpython): + """Test filesystem write/read with default 4KB erase blocks.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +@pytest.mark.flash_config(erase_block_size=65536) +def test_flash_64k_erase_blocks(circuitpython): + """Test filesystem write/read with 64KB erase blocks (128 blocks per page).""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +@pytest.mark.circuitpy_drive({"code.py": WRITE_READ_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_erase_blocks(circuitpython): + """Test filesystem write/read with 256KB erase blocks (like RA8D1 OSPI).""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "content: hello flash" in output + assert "done" in output + + content = read_file_from_flash(circuitpython.flash_file, "test.txt") + assert content == "hello flash" + + +MULTI_FILE_CODE = """\ +import storage +storage.remount("/", readonly=False) +for i in range(5): + name = f"/file{i}.txt" + with open(name, "w") as f: + f.write(f"data{i}" * 100) +print("multi_file_ok") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": MULTI_FILE_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_multi_file(circuitpython): + """Test multiple file writes with 256KB erase blocks to exercise cache flushing.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "multi_file_ok" in output + + for i in range(5): + content = read_file_from_flash(circuitpython.flash_file, f"file{i}.txt") + assert content == f"data{i}" * 100, f"file{i}.txt mismatch" + + +EXISTING_DATA_CODE = """\ +import storage +storage.remount("/", readonly=False) + +# Write a file to populate the erase page. +original_data = "A" * 4000 +with open("/original.txt", "w") as f: + f.write(original_data) + +# Force a flush so the data is written to flash. +storage.remount("/", readonly=True) +storage.remount("/", readonly=False) + +# Now write a small new file. This updates FAT metadata and directory +# entries that share an erase page with original.txt, exercising the +# read-modify-write cycle on the cached page. +with open("/small.txt", "w") as f: + f.write("tiny") + +# Read back original to check it survived. +with open("/original.txt", "r") as f: + readback = f.read() +if readback == original_data: + print("existing_data_ok") +else: + print(f"MISMATCH: got {len(readback)} bytes") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXISTING_DATA_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_existing_data_survives(circuitpython): + """Test that existing data in an erase page survives when new data is written. + + With 256KB erase blocks (512 blocks per page), writing to any block in + the page triggers an erase-rewrite of the entire page. Existing blocks + must be preserved through the read-modify-write cycle. + """ + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "existing_data_ok" in output + + # Verify both files survived on the actual flash image. + original = read_file_from_flash(circuitpython.flash_file, "original.txt") + assert original == "A" * 4000, f"original.txt corrupted: got {len(original)} bytes" + + small = read_file_from_flash(circuitpython.flash_file, "small.txt") + assert small == "tiny" + + +OVERWRITE_CODE = """\ +import storage +storage.remount("/", readonly=False) +with open("/overwrite.txt", "w") as f: + f.write("first version") +with open("/overwrite.txt", "w") as f: + f.write("second version") +print("overwrite_ok") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": OVERWRITE_CODE}) +@pytest.mark.flash_config(erase_block_size=262144, total_size=4 * 1024 * 1024) +def test_flash_256k_overwrite(circuitpython): + """Test overwriting a file with 256KB erase blocks to exercise erase-rewrite cycle.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + assert "overwrite_ok" in output + + content = read_file_from_flash(circuitpython.flash_file, "overwrite.txt") + assert content == "second version" diff --git a/ports/zephyr-cp/tests/test_hashlib.py b/ports/zephyr-cp/tests/test_hashlib.py new file mode 100644 index 0000000000000..94463ba1e991a --- /dev/null +++ b/ports/zephyr-cp/tests/test_hashlib.py @@ -0,0 +1,152 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the hashlib module against CPython hashlib.""" + +import hashlib + +import pytest + + +SHORT_DATA = b"CircuitPython!" +CHUNK_A = b"Hello, " +CHUNK_B = b"CircuitPython world!" +LONG_DATA = b"The quick brown fox jumps over the lazy dog." * 64 + + +SHA256_CODE = """\ +import hashlib + +h = hashlib.new("sha256", b"CircuitPython!") +print(f"digest_size: {h.digest_size}") +print(f"digest_hex: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SHA256_CODE}) +def test_hashlib_sha256_basic(circuitpython): + """sha256 digest on a small buffer matches CPython hashlib.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha256(SHORT_DATA).hexdigest() + assert "digest_size: 32" in output + assert f"digest_hex: {expected}" in output + assert "done" in output + + +SHA1_CODE = """\ +import hashlib + +h = hashlib.new("sha1", b"CircuitPython!") +print(f"digest_size: {h.digest_size}") +print(f"digest_hex: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": SHA1_CODE}) +def test_hashlib_sha1_basic(circuitpython): + """sha1 digest on a small buffer matches CPython hashlib.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha1(SHORT_DATA).hexdigest() + assert "digest_size: 20" in output + assert f"digest_hex: {expected}" in output + assert "done" in output + + +UPDATE_CODE = """\ +import hashlib + +h = hashlib.new("sha256") +h.update(b"Hello, ") +h.update(b"CircuitPython world!") +print(f"chunked_hex: {h.digest().hex()}") + +h2 = hashlib.new("sha256", b"Hello, CircuitPython world!") +print(f"oneshot_hex: {h2.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": UPDATE_CODE}) +def test_hashlib_sha256_update_chunks(circuitpython): + """Multiple update() calls produce the same digest as a single buffer, and match CPython.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + expected = hashlib.sha256(CHUNK_A + CHUNK_B).hexdigest() + assert f"chunked_hex: {expected}" in output + assert f"oneshot_hex: {expected}" in output + assert "done" in output + + +LONG_CODE = """\ +import hashlib + +data = b"The quick brown fox jumps over the lazy dog." * 64 +h = hashlib.new("sha256", data) +print(f"sha256_hex: {h.digest().hex()}") + +h1 = hashlib.new("sha1", data) +print(f"sha1_hex: {h1.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": LONG_CODE}) +def test_hashlib_long_input(circuitpython): + """Digests of a multi-block input match CPython for both sha1 and sha256.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"sha256_hex: {hashlib.sha256(LONG_DATA).hexdigest()}" in output + assert f"sha1_hex: {hashlib.sha1(LONG_DATA).hexdigest()}" in output + assert "done" in output + + +EMPTY_CODE = """\ +import hashlib + +h = hashlib.new("sha256", b"") +print(f"empty256: {h.digest().hex()}") + +h = hashlib.new("sha1", b"") +print(f"empty1: {h.digest().hex()}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EMPTY_CODE}) +def test_hashlib_empty_input(circuitpython): + """Empty-input digests match CPython well-known values.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"empty256: {hashlib.sha256(b'').hexdigest()}" in output + assert f"empty1: {hashlib.sha1(b'').hexdigest()}" in output + assert "done" in output + + +BAD_ALGO_CODE = """\ +import hashlib + +try: + hashlib.new("md5", b"data") +except ValueError: + print("bad_algo: ValueError") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": BAD_ALGO_CODE}) +def test_hashlib_unsupported_algorithm(circuitpython): + """Unsupported algorithm names raise ValueError.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "bad_algo: ValueError" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_i2c.py b/ports/zephyr-cp/tests/test_i2c.py new file mode 100644 index 0000000000000..ec5229faa2f26 --- /dev/null +++ b/ports/zephyr-cp/tests/test_i2c.py @@ -0,0 +1,102 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test I2C functionality on native_sim.""" + +import pytest + +I2C_SCAN_CODE = """\ +import board + +i2c = board.I2C() +while not i2c.try_lock(): + pass +devices = i2c.scan() +print(f"I2C devices: {[hex(d) for d in devices]}") +i2c.unlock() +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": I2C_SCAN_CODE}) +def test_i2c_scan(circuitpython): + """Test I2C bus scanning finds emulated devices. + + The AT24 EEPROM emulator responds to zero-length probe writes, + so it should appear in scan results at address 0x50. + """ + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "I2C devices:" in output + # AT24 EEPROM should be at address 0x50 + assert "0x50" in output + assert "done" in output + + +AT24_READ_CODE = """\ +import board + +i2c = board.I2C() +while not i2c.try_lock(): + pass + +# AT24 EEPROM at address 0x50 +AT24_ADDR = 0x50 + +# Read first byte from address 0 +result = bytearray(1) +try: + i2c.writeto_then_readfrom(AT24_ADDR, bytes([0x00]), result) + value = result[0] + print(f"AT24 byte 0: 0x{value:02X}") + # Fresh EEPROM should be 0xFF + if value == 0xFF: + print("eeprom_valid") + else: + print(f"unexpected value: expected 0xFF, got 0x{value:02X}") +except OSError as e: + print(f"I2C error: {e}") + +i2c.unlock() +i2c.deinit() +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": AT24_READ_CODE}) +def test_i2c_at24_read(circuitpython): + """Test reading from AT24 EEPROM emulator.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "AT24 byte 0: 0xFF" in output + assert "eeprom_valid" in output + assert "done" in output + + +@pytest.mark.circuitpy_drive({"code.py": I2C_SCAN_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2c_device_disabled(circuitpython): + """Test that disabled I2C device doesn't appear in scan.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "I2C devices:" in output + # AT24 at 0x50 should NOT appear when disabled + assert "0x50" not in output + assert "done" in output + + +@pytest.mark.circuitpy_drive({"code.py": AT24_READ_CODE}) +@pytest.mark.disable_i2c_devices("eeprom@50") +def test_i2c_device_disabled_communication_fails(circuitpython): + """Test that communication with disabled I2C device fails.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + # Should get an I2C error when trying to communicate + assert "I2C error" in output + assert "eeprom_valid" not in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_msgpack.py b/ports/zephyr-cp/tests/test_msgpack.py new file mode 100644 index 0000000000000..09bed35209c0a --- /dev/null +++ b/ports/zephyr-cp/tests/test_msgpack.py @@ -0,0 +1,137 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the msgpack module.""" + +import pytest + + +ROUNDTRIP_CODE = """\ +import msgpack +from io import BytesIO + +obj = {"list": [True, False, None, 1, 3.125], "str": "blah"} +b = BytesIO() +msgpack.pack(obj, b) +encoded = b.getvalue() +print(f"encoded_len: {len(encoded)}") +print(f"encoded_hex: {encoded.hex()}") + +b.seek(0) +decoded = msgpack.unpack(b) +print(f"decoded: {decoded}") +print(f"match: {decoded == obj}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": ROUNDTRIP_CODE}) +def test_msgpack_roundtrip(circuitpython): + """Pack and unpack a dict containing the basic msgpack types.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "match: True" in output + assert "done" in output + + +USE_LIST_CODE = """\ +import msgpack +from io import BytesIO + +b = BytesIO() +msgpack.pack([1, 2, 3], b) + +b.seek(0) +as_list = msgpack.unpack(b) +print(f"as_list: {as_list} type={type(as_list).__name__}") + +b.seek(0) +as_tuple = msgpack.unpack(b, use_list=False) +print(f"as_tuple: {as_tuple} type={type(as_tuple).__name__}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": USE_LIST_CODE}) +def test_msgpack_use_list(circuitpython): + """use_list=False should return a tuple instead of a list.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "as_list: [1, 2, 3] type=list" in output + assert "as_tuple: (1, 2, 3) type=tuple" in output + assert "done" in output + + +EXTTYPE_CODE = """\ +from msgpack import pack, unpack, ExtType +from io import BytesIO + +class MyClass: + def __init__(self, val): + self.value = val + +data = MyClass(b"my_value") + +def encoder(obj): + if isinstance(obj, MyClass): + return ExtType(1, obj.value) + return f"no encoder for {obj}" + +def decoder(code, data): + if code == 1: + return MyClass(data) + return f"no decoder for type {code}" + +buf = BytesIO() +pack(data, buf, default=encoder) +buf.seek(0) +decoded = unpack(buf, ext_hook=decoder) +print(f"decoded_type: {type(decoded).__name__}") +print(f"decoded_value: {decoded.value}") +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXTTYPE_CODE}) +def test_msgpack_exttype(circuitpython): + """ExtType with a custom encoder/decoder should round-trip.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "decoded_type: MyClass" in output + assert "decoded_value: b'my_value'" in output + assert "done" in output + + +EXTTYPE_PROPS_CODE = """\ +from msgpack import ExtType + +e = ExtType(5, b"hello") +print(f"code: {e.code}") +print(f"data: {e.data}") + +e.code = 10 +print(f"new_code: {e.code}") + +try: + ExtType(128, b"x") +except (ValueError, OverflowError) as ex: + print(f"range_error: {type(ex).__name__}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": EXTTYPE_PROPS_CODE}) +def test_msgpack_exttype_properties(circuitpython): + """ExtType exposes code/data as read/write properties and rejects out-of-range codes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "code: 5" in output + assert "data: b'hello'" in output + assert "new_code: 10" in output + assert "range_error:" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_nvm.py b/ports/zephyr-cp/tests/test_nvm.py new file mode 100644 index 0000000000000..5de304afc1bdc --- /dev/null +++ b/ports/zephyr-cp/tests/test_nvm.py @@ -0,0 +1,73 @@ +# SPDX-FileCopyrightText: 2025 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test NVM functionality on native_sim.""" + +import pytest + + +NVM_BASIC_CODE = """\ +import microcontroller + +nvm = microcontroller.nvm +print(f"nvm length: {len(nvm)}") + +# Write some bytes +nvm[0] = 42 +nvm[1] = 99 +print(f"nvm[0]: {nvm[0]}") +print(f"nvm[1]: {nvm[1]}") + +# Write a slice +nvm[2:5] = b"\\x01\\x02\\x03" +print(f"nvm[2:5]: {list(nvm[2:5])}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": NVM_BASIC_CODE}) +def test_nvm_read_write(circuitpython): + """Test basic NVM read and write operations.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "nvm length: 8192" in output + assert "nvm[0]: 42" in output + assert "nvm[1]: 99" in output + assert "nvm[2:5]: [1, 2, 3]" in output + assert "done" in output + + +NVM_PERSIST_CODE = """\ +import microcontroller + +nvm = microcontroller.nvm +value = nvm[0] +print(f"nvm[0]: {value}") + +if value == 255: + # First run: write a marker + nvm[0] = 123 + print("wrote marker") +else: + print(f"marker found: {value}") + +print("done") +""" + + +@pytest.mark.circuitpy_drive({"code.py": NVM_PERSIST_CODE}) +@pytest.mark.code_py_runs(2) +def test_nvm_persists_across_reload(circuitpython): + """Test that NVM data persists across soft reloads.""" + circuitpython.serial.wait_for("wrote marker") + # Trigger soft reload + circuitpython.serial.write("\x04") + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "nvm[0]: 255" in output + assert "wrote marker" in output + assert "marker found: 123" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_rotaryio.py b/ports/zephyr-cp/tests/test_rotaryio.py new file mode 100644 index 0000000000000..e9a5c1913cb20 --- /dev/null +++ b/ports/zephyr-cp/tests/test_rotaryio.py @@ -0,0 +1,132 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries LLC +# SPDX-License-Identifier: MIT + +"""Test rotaryio functionality on native_sim.""" + +import pytest + + +ROTARY_CODE_5S = """\ +import time +import microcontroller +import rotaryio + +encoder = rotaryio.IncrementalEncoder(microcontroller.pin.P_01, microcontroller.pin.P_02) + +time.sleep(5.0) # Sleep long enough for trace events to complete +print(f"position={encoder.position}") +print("done") +""" + + +ROTARY_CODE_7S = """\ +import time +import microcontroller +import rotaryio + +encoder = rotaryio.IncrementalEncoder(microcontroller.pin.P_01, microcontroller.pin.P_02) + +time.sleep(7.0) # Sleep long enough for trace events to complete +print(f"position={encoder.position}") +print("done") +""" + + +CLOCKWISE_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_100_000_000, 1), # 4.1s: A goes high (A leads) + (4_300_000_000, 0), # 4.3s: A goes low + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_200_000_000, 1), # 4.2s: B goes high (B follows) + (4_400_000_000, 0), # 4.4s: B goes low + ], +} + +COUNTERCLOCKWISE_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_200_000_000, 1), # 4.2s: A goes high (A follows) + (4_400_000_000, 0), # 4.4s: A goes low + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # 4.0s: initial state (low) + (4_100_000_000, 1), # 4.1s: B goes high (B leads) + (4_300_000_000, 0), # 4.3s: B goes low + ], +} + +BOTH_DIRECTIONS_TRACE = { + "gpio_emul.01": [ + (4_000_000_000, 0), # Initial state + # First clockwise detent + (4_100_000_000, 1), # A rises (leads) + (4_300_000_000, 0), # A falls + # Second clockwise detent + (4_500_000_000, 1), # A rises (leads) + (4_700_000_000, 0), # A falls + # First counter-clockwise detent + (5_000_000_000, 1), # A rises (follows) + (5_200_000_000, 0), # A falls + # Second counter-clockwise detent + (5_400_000_000, 1), # A rises (follows) + (5_600_000_000, 0), # A falls + # Third counter-clockwise detent + (5_800_000_000, 1), # A rises (follows) + (6_000_000_000, 0), # A falls + ], + "gpio_emul.02": [ + (4_000_000_000, 0), # Initial state + # First clockwise detent + (4_200_000_000, 1), # B rises (follows) + (4_400_000_000, 0), # B falls + # Second clockwise detent + (4_600_000_000, 1), # B rises (follows) + (4_800_000_000, 0), # B falls + # First counter-clockwise detent + (4_900_000_000, 1), # B rises (leads) + (5_100_000_000, 0), # B falls + # Second counter-clockwise detent + (5_300_000_000, 1), # B rises (leads) + (5_500_000_000, 0), # B falls + # Third counter-clockwise detent + (5_700_000_000, 1), # B rises (leads) + (5_900_000_000, 0), # B falls + ], +} + + +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_5S}) +@pytest.mark.input_trace(CLOCKWISE_TRACE) +def test_rotaryio_incrementalencoder_clockwise(circuitpython): + """Test clockwise rotation increments position.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=1" in output + assert "done" in output + + +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_5S}) +@pytest.mark.input_trace(COUNTERCLOCKWISE_TRACE) +def test_rotaryio_incrementalencoder_counterclockwise(circuitpython): + """Test counter-clockwise rotation decrements position.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=-1" in output + assert "done" in output + + +@pytest.mark.duration(12.0) +@pytest.mark.circuitpy_drive({"code.py": ROTARY_CODE_7S}) +@pytest.mark.input_trace(BOTH_DIRECTIONS_TRACE) +def test_rotaryio_incrementalencoder_both_directions(circuitpython): + """Test rotation in both directions: 2 clockwise, then 3 counter-clockwise.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "position=-1" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/test_web_workflow.py b/ports/zephyr-cp/tests/test_web_workflow.py new file mode 100644 index 0000000000000..d3a00782a333e --- /dev/null +++ b/ports/zephyr-cp/tests/test_web_workflow.py @@ -0,0 +1,142 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Tests for web workflow on native_sim.""" + +from __future__ import annotations + +import json +import re + +import pytest +import requests + + +pytestmark = pytest.mark.native_sim_rt + +WEB_WORKFLOW_PORT = 8090 +WEB_WORKFLOW_PASSWORD = "testpass" + +WEB_WORKFLOW_CODE = """\ +import time + +# Keep the VM alive while the web workflow starts. +time.sleep(3) +""" + +WEB_WORKFLOW_UPDATED_CODE = """\ +print("updated") +""" + +WEB_WORKFLOW_SETTINGS = f"""\ +CIRCUITPY_WEB_API_PASSWORD="{WEB_WORKFLOW_PASSWORD}" +CIRCUITPY_WEB_API_PORT={WEB_WORKFLOW_PORT} +""" + +WEB_WORKFLOW_SETTINGS_PORT_80 = f"""\ +CIRCUITPY_WEB_API_PASSWORD="{WEB_WORKFLOW_PASSWORD}" +CIRCUITPY_WEB_API_PORT=80 +""" + +WEB_WORKFLOW_BOOT = """\ +import storage + +storage.remount("/", readonly=False) +""" + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_hostnetwork(circuitpython): + """Ensure web workflow responds over hostnetwork.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + response = requests.get(f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/edit/", timeout=1.0) + + assert response.status_code == 401 + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_version_json_hostnetwork_ip_and_port(circuitpython): + """Ensure /cp/version.json reports hostnetwork endpoint with configured port.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + response = requests.get( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/cp/version.json", + auth=("", WEB_WORKFLOW_PASSWORD), + timeout=1.0, + ) + + assert response.status_code == 200 + + payload = json.loads(response.text) + assert payload["ip"] == "127.0.0.1" + assert payload["port"] == WEB_WORKFLOW_PORT + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_status_line_hostnetwork_non_default_port(circuitpython): + """Status line should include hostnetwork IP and non-default port.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + + # Remove ANSI control sequences before matching. + output = re.sub(r"\x1b\[[0-9;]*[A-Za-z]", "", output) + assert "127.0.0.1:8090" in output + + +@pytest.mark.circuitpy_drive( + { + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS_PORT_80, + } +) +def test_web_workflow_status_line_hostnetwork_default_port(circuitpython): + """Status line should show IP without :80 for default HTTP port.""" + circuitpython.wait_until_done() + output = circuitpython.serial.all_output + + output = re.sub(r"\x1b\[[0-9;]*[A-Za-z]", "", output) + assert "127.0.0.1" in output + assert "127.0.0.1:80" not in output + + +@pytest.mark.circuitpy_drive( + { + "boot.py": WEB_WORKFLOW_BOOT, + "code.py": WEB_WORKFLOW_CODE, + "settings.toml": WEB_WORKFLOW_SETTINGS, + } +) +def test_web_workflow_write_code_py_remount(circuitpython): + """Ensure web workflow can update code.py after remounting.""" + circuitpython.serial.wait_for(f"127.0.0.1:{WEB_WORKFLOW_PORT}") + body = WEB_WORKFLOW_UPDATED_CODE.encode("utf-8") + + response = requests.put( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/fs/code.py", + auth=("", WEB_WORKFLOW_PASSWORD), + data=body, + timeout=1.0, + ) + assert response.status_code in (201, 204) + + response = requests.get( + f"http://127.0.0.1:{WEB_WORKFLOW_PORT}/fs/code.py", + auth=("", WEB_WORKFLOW_PASSWORD), + timeout=1.0, + ) + assert response.status_code == 200 + assert WEB_WORKFLOW_UPDATED_CODE in response.text diff --git a/ports/zephyr-cp/tests/test_zlib.py b/ports/zephyr-cp/tests/test_zlib.py new file mode 100644 index 0000000000000..bd89d8e1c257a --- /dev/null +++ b/ports/zephyr-cp/tests/test_zlib.py @@ -0,0 +1,110 @@ +# SPDX-FileCopyrightText: 2026 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT + +"""Test the zlib module against CPython zlib. + +CircuitPython's zlib only implements ``decompress``; these tests compress data +with CPython and verify the zephyr-cp port decodes it back to the same bytes. +""" + +import zlib + +import pytest + + +PLAIN_TEXT = b"CircuitPython running on Zephyr says hello!" +REPEATED_TEXT = b"The quick brown fox jumps over the lazy dog. " * 32 +BINARY_BLOB = bytes(range(256)) * 4 + + +def _make_code(compressed: bytes, wbits: int, expected_len: int) -> str: + return ( + "import zlib\n" + f"compressed = {compressed!r}\n" + f"out = zlib.decompress(compressed, {wbits})\n" + f'print(f"out_len: {{len(out)}}")\n' + f'print(f"expected_len: {expected_len}")\n' + 'print(f"out_hex: {out.hex()}")\n' + 'print("done")\n' + ) + + +ZLIB_COMPRESSED = zlib.compress(PLAIN_TEXT) +ZLIB_CODE = _make_code(ZLIB_COMPRESSED, wbits=15, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": ZLIB_CODE}) +def test_zlib_decompress_zlib_format(circuitpython): + """Data produced by CPython zlib.compress() round-trips through CircuitPython zlib.decompress().""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output + + +REPEATED_COMPRESSED = zlib.compress(REPEATED_TEXT) +REPEATED_CODE = _make_code(REPEATED_COMPRESSED, wbits=15, expected_len=len(REPEATED_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": REPEATED_CODE}) +def test_zlib_decompress_repeated(circuitpython): + """Highly-compressible repeated input decompresses correctly (back-references).""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(REPEATED_TEXT)}" in output + # Repeated text has many back-references; shrinks a lot. + assert len(REPEATED_COMPRESSED) < len(REPEATED_TEXT) // 4 + assert f"out_hex: {REPEATED_TEXT.hex()}" in output + assert "done" in output + + +BINARY_COMPRESSED = zlib.compress(BINARY_BLOB) +BINARY_CODE = _make_code(BINARY_COMPRESSED, wbits=15, expected_len=len(BINARY_BLOB)) + + +@pytest.mark.circuitpy_drive({"code.py": BINARY_CODE}) +def test_zlib_decompress_binary_bytes(circuitpython): + """Decompression preserves every byte value (0x00-0xFF).""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(BINARY_BLOB)}" in output + assert f"out_hex: {BINARY_BLOB.hex()}" in output + assert "done" in output + + +# Raw DEFLATE stream (no zlib header/trailer). +_raw_compressor = zlib.compressobj(wbits=-15) +RAW_COMPRESSED = _raw_compressor.compress(PLAIN_TEXT) + _raw_compressor.flush() +RAW_CODE = _make_code(RAW_COMPRESSED, wbits=-15, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": RAW_CODE}) +def test_zlib_decompress_raw_deflate(circuitpython): + """Raw DEFLATE streams (wbits=-15) decompress to the original bytes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output + + +# Gzip wrapper (wbits=31). +_gzip_compressor = zlib.compressobj(wbits=31) +GZIP_COMPRESSED = _gzip_compressor.compress(PLAIN_TEXT) + _gzip_compressor.flush() +GZIP_CODE = _make_code(GZIP_COMPRESSED, wbits=31, expected_len=len(PLAIN_TEXT)) + + +@pytest.mark.circuitpy_drive({"code.py": GZIP_CODE}) +def test_zlib_decompress_gzip_format(circuitpython): + """Gzip-wrapped streams (wbits=31) decompress to the original bytes.""" + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert f"out_len: {len(PLAIN_TEXT)}" in output + assert f"out_hex: {PLAIN_TEXT.hex()}" in output + assert "done" in output diff --git a/ports/zephyr-cp/tests/zephyr_display/README.md b/ports/zephyr-cp/tests/zephyr_display/README.md new file mode 100644 index 0000000000000..6b50202154352 --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/README.md @@ -0,0 +1,45 @@ +# Zephyr Display Golden Tests + +This directory contains native_sim golden-image tests for the Zephyr-specific `zephyr_display` path. + +## What is tested + +- `board.DISPLAY` is present and usable. +- CircuitPython terminal/console tilegrids are attached to the default display root group. +- Deterministic console terminal output matches a checked-in golden image. +- `zephyr_display` pixel format constants are exposed. +- `displayio` rendering produces expected stripe colors at sampled pixel locations. + +## Files + +- `test_zephyr_display.py` – pytest tests. +- `golden/terminal_console_output_320x240.png` – console terminal output golden reference image. + +## How capture works + +These tests use trace-driven SDL display capture triggered by Perfetto instant events: + +- `--input-trace=` provides a Perfetto trace containing a `"display_capture"` track + with instant events at the desired capture timestamps. +- `--display_capture_png=` specifies the output PNG pattern (may contain `%d` for + a sequence number). +- `--display_headless` runs SDL in headless/hidden-window mode (always enabled for native_sim tests). + +The test harness sets these flags automatically when tests use +`@pytest.mark.display(capture_times_ns=[...])`. + +## Regenerating the console golden image + +```bash +rm -rf /tmp/zephyr-display-golden +pytest -q ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py::test_console_output_golden \ + --basetemp=/tmp/zephyr-display-golden +cp /tmp/zephyr-display-golden/test_console_output_golden0/frame_0.png \ + ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png +``` + +## Running the tests + +```bash +pytest -q ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py +``` diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png new file mode 100644 index 0000000000000..5739b8ee156eb Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png new file mode 100644 index 0000000000000..6bdb72b802c97 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_AL_88.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png new file mode 100644 index 0000000000000..90b422792db10 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_ARGB_8888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png new file mode 100644 index 0000000000000..5739b8ee156eb Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_BGR_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png new file mode 100644 index 0000000000000..6bdb72b802c97 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_L_8.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png new file mode 100644 index 0000000000000..b22de4417ab38 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO01.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png new file mode 100644 index 0000000000000..b22de4417ab38 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_MONO10.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png new file mode 100644 index 0000000000000..5739b8ee156eb Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png new file mode 100644 index 0000000000000..c4301da47c530 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/color_gradient_320x240_RGB_888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png new file mode 100644 index 0000000000000..3ebb967560f0a Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.mask.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png new file mode 100644 index 0000000000000..77577a65601ab Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png new file mode 100644 index 0000000000000..f9ceedebe4a20 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_AL_88.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png new file mode 100644 index 0000000000000..90b422792db10 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_ARGB_8888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png new file mode 100644 index 0000000000000..77577a65601ab Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_BGR_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png new file mode 100644 index 0000000000000..f9ceedebe4a20 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_L_8.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png new file mode 100644 index 0000000000000..59928bcd10704 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png new file mode 100644 index 0000000000000..59928bcd10704 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO01_no_vtiled.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png new file mode 100644 index 0000000000000..59928bcd10704 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png new file mode 100644 index 0000000000000..59928bcd10704 Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_MONO10_no_vtiled.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png new file mode 100644 index 0000000000000..77577a65601ab Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_565.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png new file mode 100644 index 0000000000000..28d51925caefe Binary files /dev/null and b/ports/zephyr-cp/tests/zephyr_display/golden/terminal_console_output_320x240_RGB_888.png differ diff --git a/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py b/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py new file mode 100644 index 0000000000000..6700c42ec4a94 --- /dev/null +++ b/ports/zephyr-cp/tests/zephyr_display/test_zephyr_display.py @@ -0,0 +1,365 @@ +# SPDX-FileCopyrightText: 2026 Scott Shawcroft for Adafruit Industries +# SPDX-License-Identifier: MIT + +import colorsys +import shutil +import struct +from pathlib import Path + +import pytest +from PIL import Image + + +def _read_image(path: Path) -> tuple[int, int, bytes]: + """Read an image file and return (width, height, RGB bytes).""" + with Image.open(path) as img: + rgb = img.convert("RGB") + return rgb.width, rgb.height, rgb.tobytes() + + +def _read_mask(golden_path: Path) -> bytes | None: + """Load the companion mask PNG for a golden image, if it exists. + + Non-zero pixels are masked (skipped during comparison). + """ + mask_path = golden_path.with_suffix(".mask.png") + if not mask_path.exists(): + return None + with Image.open(mask_path) as img: + return img.convert("L").tobytes() + + +def _assert_pixels_equal_masked( + golden_pixels: bytes, actual_pixels: bytes, mask: bytes | None = None +): + """Assert pixels match, skipping positions where the mask is non-zero.""" + assert len(golden_pixels) == len(actual_pixels) + for i in range(0, len(golden_pixels), 3): + if mask is not None and mask[i // 3] != 0: + continue + if golden_pixels[i : i + 3] != actual_pixels[i : i + 3]: + pixel = i // 3 + assert False, ( + f"Pixel {pixel} mismatch: " + f"golden={tuple(golden_pixels[i : i + 3])} " + f"actual={tuple(actual_pixels[i : i + 3])}" + ) + + +BOARD_DISPLAY_AVAILABLE_CODE = """\ +import board +print(hasattr(board, 'DISPLAY')) +print(type(board.DISPLAY).__name__) +print(board.DISPLAY.width, board.DISPLAY.height) +print('done') +""" + + +@pytest.mark.circuitpy_drive({"code.py": BOARD_DISPLAY_AVAILABLE_CODE}) +@pytest.mark.display +@pytest.mark.duration(8) +def test_board_display_available(circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "True" in output + assert "Display" in output + assert "320 240" in output + assert "done" in output + + +CONSOLE_TERMINAL_PRESENT_CODE = """\ +import board + +root = board.DISPLAY.root_group +has_terminal_tilegrids = ( + type(root).__name__ == 'Group' and + len(root) >= 2 and + type(root[0]).__name__ == 'TileGrid' and + type(root[-1]).__name__ == 'TileGrid' +) +print('has_terminal_tilegrids:', has_terminal_tilegrids) +print('done') +""" + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_TERMINAL_PRESENT_CODE}) +@pytest.mark.display +@pytest.mark.duration(8) +def test_console_terminal_present_by_default(circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "has_terminal_tilegrids: True" in output + assert "done" in output + + +CONSOLE_OUTPUT_GOLDEN_CODE = """\ +import time +time.sleep(0.25) +print('done') +while True: + time.sleep(1) +""" + + +def _golden_compare_or_update(request, captures, golden_path, mask_path=None): + """Compare captured PNG against golden, or update golden if --update-goldens. + + mask_path overrides the default companion mask lookup (golden.mask.png). + """ + if not captures or not captures[0].exists(): + pytest.skip("display capture was not produced") + + if request.config.getoption("--update-goldens"): + golden_path.parent.mkdir(parents=True, exist_ok=True) + shutil.copy2(captures[0], golden_path) + return + + gw, gh, gpx = _read_image(golden_path) + dw, dh, dpx = _read_image(captures[0]) + if mask_path is not None: + mask = _read_mask(mask_path) + else: + mask = _read_mask(golden_path) + + assert (dw, dh) == (gw, gh) + _assert_pixels_equal_masked(gpx, dpx, mask) + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.duration(8) +def test_console_output_golden(request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden = Path(__file__).parent / "golden" / "terminal_console_output_320x240.png" + _golden_compare_or_update(request, circuitpython.display_capture_paths(), golden) + + +PIXEL_FORMATS = ["ARGB_8888", "RGB_888", "RGB_565", "BGR_565", "L_8", "AL_88", "MONO01", "MONO10"] + +# Shared mask: the same screen regions vary regardless of pixel format. +_CONSOLE_GOLDEN_MASK = Path(__file__).parent / "golden" / "terminal_console_output_320x240.png" + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.duration(8) +@pytest.mark.parametrize( + "pixel_format", + PIXEL_FORMATS, + indirect=True, +) +def test_console_output_golden_pixel_format(pixel_format, request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden_name = f"terminal_console_output_320x240_{pixel_format}.png" + golden = Path(__file__).parent / "golden" / golden_name + _golden_compare_or_update( + request, circuitpython.display_capture_paths(), golden, _CONSOLE_GOLDEN_MASK + ) + + +MONO_NO_VTILED_FORMATS = ["MONO01", "MONO10"] + + +@pytest.mark.circuitpy_drive({"code.py": CONSOLE_OUTPUT_GOLDEN_CODE}) +@pytest.mark.display(capture_times_ns=[4_000_000_000]) +@pytest.mark.display_mono_vtiled(False) +@pytest.mark.duration(8) +@pytest.mark.parametrize( + "pixel_format", + MONO_NO_VTILED_FORMATS, + indirect=True, +) +def test_console_output_golden_mono_no_vtiled(pixel_format, request, circuitpython): + circuitpython.wait_until_done() + + output = circuitpython.serial.all_output + assert "done" in output + + golden_name = f"terminal_console_output_320x240_{pixel_format}_no_vtiled.png" + golden = Path(__file__).parent / "golden" / golden_name + _golden_compare_or_update( + request, circuitpython.display_capture_paths(), golden, _CONSOLE_GOLDEN_MASK + ) + + +def _generate_gradient_bmp(width, height): + """Generate a 24-bit BMP with HSL color gradient. + + Hue sweeps left to right, lightness goes from black (bottom) to white (top), + saturation is 1.0. + """ + row_size = width * 3 + row_padding = (4 - (row_size % 4)) % 4 + padded_row_size = row_size + row_padding + pixel_data_size = padded_row_size * height + file_size = 14 + 40 + pixel_data_size + + header = struct.pack( + "<2sIHHI", + b"BM", + file_size, + 0, + 0, + 14 + 40, + ) + info = struct.pack( + " + +extern int circuitpython_main(void); + +int main(void) { + // Use a unique name for CP main so that the linker needs to look in libcircuitpython.a + return circuitpython_main(); +} diff --git a/py/argcheck.c b/py/argcheck.c index 9302dec96c396..155e29bdc15bf 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -170,13 +170,13 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, } #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE -NORETURN void mp_arg_error_terse_mismatch(void) { +MP_NORETURN void mp_arg_error_terse_mismatch(void) { mp_raise_TypeError(MP_ERROR_TEXT("argument num/types mismatch")); } #endif #if MICROPY_CPYTHON_COMPAT -NORETURN void mp_arg_error_unimpl_kw(void) { +MP_NORETURN void mp_arg_error_unimpl_kw(void) { mp_raise_NotImplementedError(MP_ERROR_TEXT("keyword argument(s) not implemented - use normal args instead")); } #endif @@ -312,6 +312,6 @@ mp_int_t mp_arg_validate_type_int(mp_obj_t obj, qstr arg_name) { return an_int; } -NORETURN void mp_arg_error_invalid(qstr arg_name) { +MP_NORETURN void mp_arg_error_invalid(qstr arg_name) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), arg_name); } diff --git a/py/asmarm.c b/py/asmarm.c index 42724e4d4b37c..15bc73b61eca6 100644 --- a/py/asmarm.c +++ b/py/asmarm.c @@ -36,10 +36,10 @@ #include "py/asmarm.h" -#define SIGNED_FIT24(x) (((x) & 0xff800000) == 0) || (((x) & 0xff000000) == 0xff000000) +#define REG_TEMP ASM_ARM_REG_R8 // Insert word into instruction flow -STATIC void emit(asm_arm_t *as, uint op) { +static void emit(asm_arm_t *as, uint op) { uint8_t *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4); if (c != NULL) { *(uint32_t *)c = op; @@ -47,73 +47,83 @@ STATIC void emit(asm_arm_t *as, uint op) { } // Insert word into instruction flow, add "ALWAYS" condition code -STATIC void emit_al(asm_arm_t *as, uint op) { +static void emit_al(asm_arm_t *as, uint op) { emit(as, op | ASM_ARM_CC_AL); } // Basic instructions without condition code -STATIC uint asm_arm_op_push(uint reglist) { +static uint asm_arm_op_push(uint reglist) { // stmfd sp!, {reglist} return 0x92d0000 | (reglist & 0xFFFF); } -STATIC uint asm_arm_op_pop(uint reglist) { +static uint asm_arm_op_pop(uint reglist) { // ldmfd sp!, {reglist} return 0x8bd0000 | (reglist & 0xFFFF); } -STATIC uint asm_arm_op_mov_reg(uint rd, uint rn) { +static uint asm_arm_op_mov_reg(uint rd, uint rn) { // mov rd, rn return 0x1a00000 | (rd << 12) | rn; } -STATIC uint asm_arm_op_mov_imm(uint rd, uint imm) { +static uint asm_arm_op_mov_imm(uint rd, uint imm) { // mov rd, #imm return 0x3a00000 | (rd << 12) | imm; } -STATIC uint asm_arm_op_mvn_imm(uint rd, uint imm) { +static uint asm_arm_op_mvn_imm(uint rd, uint imm) { // mvn rd, #imm return 0x3e00000 | (rd << 12) | imm; } -STATIC uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) { +static uint asm_arm_op_mvn_reg(uint rd, uint rm) { + // mvn rd, rm + return 0x1e00000 | (rd << 12) | rm; +} + +static uint asm_arm_op_add_imm(uint rd, uint rn, uint imm) { // add rd, rn, #imm return 0x2800000 | (rn << 16) | (rd << 12) | (imm & 0xFF); } -STATIC uint asm_arm_op_add_reg(uint rd, uint rn, uint rm) { +static uint asm_arm_op_add_reg(uint rd, uint rn, uint rm) { // add rd, rn, rm return 0x0800000 | (rn << 16) | (rd << 12) | rm; } -STATIC uint asm_arm_op_sub_imm(uint rd, uint rn, uint imm) { +static uint asm_arm_op_sub_imm(uint rd, uint rn, uint imm) { // sub rd, rn, #imm return 0x2400000 | (rn << 16) | (rd << 12) | (imm & 0xFF); } -STATIC uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) { +static uint asm_arm_op_sub_reg(uint rd, uint rn, uint rm) { // sub rd, rn, rm return 0x0400000 | (rn << 16) | (rd << 12) | rm; } -STATIC uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) { +static uint asm_arm_op_rsb_imm(uint rd, uint rn, uint imm) { + // rsb rd, rn, #imm + return 0x2600000 | (rn << 16) | (rd << 12) | (imm & 0xFF); +} + +static uint asm_arm_op_mul_reg(uint rd, uint rm, uint rs) { // mul rd, rm, rs assert(rd != rm); return 0x0000090 | (rd << 16) | (rs << 8) | rm; } -STATIC uint asm_arm_op_and_reg(uint rd, uint rn, uint rm) { +static uint asm_arm_op_and_reg(uint rd, uint rn, uint rm) { // and rd, rn, rm return 0x0000000 | (rn << 16) | (rd << 12) | rm; } -STATIC uint asm_arm_op_eor_reg(uint rd, uint rn, uint rm) { +static uint asm_arm_op_eor_reg(uint rd, uint rn, uint rm) { // eor rd, rn, rm return 0x0200000 | (rn << 16) | (rd << 12) | rm; } -STATIC uint asm_arm_op_orr_reg(uint rd, uint rn, uint rm) { +static uint asm_arm_op_orr_reg(uint rd, uint rn, uint rm) { // orr rd, rn, rm return 0x1800000 | (rn << 16) | (rd << 12) | rm; } @@ -158,13 +168,23 @@ void asm_arm_entry(asm_arm_t *as, int num_locals) { emit_al(as, asm_arm_op_push(as->push_reglist | 1 << ASM_ARM_REG_LR)); if (as->stack_adjust > 0) { - emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); + if (as->stack_adjust < 0x100) { + emit_al(as, asm_arm_op_sub_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); + } else { + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, as->stack_adjust); + emit_al(as, asm_arm_op_sub_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, REG_TEMP)); + } } } void asm_arm_exit(asm_arm_t *as) { if (as->stack_adjust > 0) { - emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); + if (as->stack_adjust < 0x100) { + emit_al(as, asm_arm_op_add_imm(ASM_ARM_REG_SP, ASM_ARM_REG_SP, as->stack_adjust)); + } else { + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, as->stack_adjust); + emit_al(as, asm_arm_op_add_reg(ASM_ARM_REG_SP, ASM_ARM_REG_SP, REG_TEMP)); + } } emit_al(as, asm_arm_op_pop(as->push_reglist | (1 << ASM_ARM_REG_PC))); @@ -228,11 +248,23 @@ void asm_arm_setcc_reg(asm_arm_t *as, uint rd, uint cond) { emit(as, asm_arm_op_mov_imm(rd, 0) | (cond ^ (1 << 28))); // mov!COND rd, #0 } +void asm_arm_mvn_reg_reg(asm_arm_t *as, uint rd, uint rm) { + // mvn rd, rm + // computes: rd := ~rm + emit_al(as, asm_arm_op_mvn_reg(rd, rm)); +} + void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // add rd, rn, rm emit_al(as, asm_arm_op_add_reg(rd, rn, rm)); } +void asm_arm_rsb_reg_reg_imm(asm_arm_t *as, uint rd, uint rn, uint imm) { + // rsb rd, rn, #imm + // computes: rd := #imm - rn + emit_al(as, asm_arm_op_rsb_imm(rd, rn, imm)); +} + void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { // sub rd, rn, rm emit_al(as, asm_arm_op_sub_reg(rd, rn, rm)); @@ -260,8 +292,15 @@ void asm_arm_orr_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm) { } void asm_arm_mov_reg_local_addr(asm_arm_t *as, uint rd, int local_num) { - // add rd, sp, #local_num*4 - emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2)); + if (local_num >= 0x40) { + // mov temp, #local_num*4 + // add rd, sp, temp + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, local_num << 2); + emit_al(as, asm_arm_op_add_reg(rd, ASM_ARM_REG_SP, REG_TEMP)); + } else { + // add rd, sp, #local_num*4 + emit_al(as, asm_arm_op_add_imm(rd, ASM_ARM_REG_SP, local_num << 2)); + } } void asm_arm_mov_reg_pcrel(asm_arm_t *as, uint reg_dest, uint label) { @@ -294,39 +333,92 @@ void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs) { emit_al(as, 0x1a00050 | (rd << 12) | (rs << 8) | rd); } -void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { - // ldr rd, [rn, #off] - emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset); +void asm_arm_ldr_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x1000) { + // ldr rd, [rn, #off] + emit_al(as, 0x5900000 | (rn << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // ldr rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7900000 | (rn << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn) { - // ldrh rd, [rn] - emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12)); +void asm_arm_ldrh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldrh doesn't support scaled register index + emit_al(as, 0x1a00080 | (REG_TEMP << 12) | rn); // mov temp, rn, lsl #1 + emit_al(as, 0x19000b0 | (rm << 16) | (rd << 12) | REG_TEMP); // ldrh rd, [rm, temp]; } void asm_arm_ldrh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { - // ldrh rd, [rn, #off] - emit_al(as, 0x1f000b0 | (rn << 16) | (rd << 12) | ((byte_offset & 0xf0) << 4) | (byte_offset & 0xf)); + if (byte_offset < 0x100) { + // ldrh rd, [rn, #off] + emit_al(as, 0x1d000b0 | (rn << 16) | (rd << 12) | ((byte_offset & 0xf0) << 4) | (byte_offset & 0xf)); + } else { + // mov temp, #off + // ldrh rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x19000b0 | (rn << 16) | (rd << 12) | REG_TEMP); + } +} + +void asm_arm_ldrb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldrb rd, [rm, rn] + emit_al(as, 0x7d00000 | (rm << 16) | (rd << 12) | rn); +} + +void asm_arm_ldrb_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x1000) { + // ldrb rd, [rn, #off] + emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // ldrb rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7d00000 | (rn << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn) { - // ldrb rd, [rn] - emit_al(as, 0x5d00000 | (rn << 16) | (rd << 12)); +void asm_arm_ldr_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { + // ldr rd, [rm, rn, lsl #2] + emit_al(as, 0x7900100 | (rm << 16) | (rd << 12) | rn); } -void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { - // str rd, [rm, #off] - emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset); +void asm_arm_str_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { + if (byte_offset < 0x1000) { + // str rd, [rm, #off] + emit_al(as, 0x5800000 | (rm << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // str rd, [rm, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7800000 | (rm << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm) { - // strh rd, [rm] - emit_al(as, 0x1c000b0 | (rm << 16) | (rd << 12)); +void asm_arm_strh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset) { + if (byte_offset < 0x100) { + // strh rd, [rn, #off] + emit_al(as, 0x1c000b0 | (rn << 16) | (rd << 12) | ((byte_offset & 0xf0) << 4) | (byte_offset & 0xf)); + } else { + // mov temp, #off + // strh rd, [rn, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x18000b0 | (rn << 16) | (rd << 12) | REG_TEMP); + } } -void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm) { - // strb rd, [rm] - emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12)); +void asm_arm_strb_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset) { + if (byte_offset < 0x1000) { + // strb rd, [rm, #off] + emit_al(as, 0x5c00000 | (rm << 16) | (rd << 12) | byte_offset); + } else { + // mov temp, #off + // strb rd, [rm, temp] + asm_arm_mov_reg_i32_optimised(as, REG_TEMP, byte_offset); + emit_al(as, 0x7c00000 | (rm << 16) | (rd << 12) | REG_TEMP); + } } void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { @@ -336,8 +428,8 @@ void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { // strh doesn't support scaled register index - emit_al(as, 0x1a00080 | (ASM_ARM_REG_R8 << 12) | rn); // mov r8, rn, lsl #1 - emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | ASM_ARM_REG_R8); // strh rd, [rm, r8] + emit_al(as, 0x1a00080 | (REG_TEMP << 12) | rn); // mov temp, rn, lsl #1 + emit_al(as, 0x18000b0 | (rm << 16) | (rd << 12) | REG_TEMP); // strh rd, [rm, temp] } void asm_arm_strb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn) { @@ -352,7 +444,7 @@ void asm_arm_bcc_label(asm_arm_t *as, int cond, uint label) { rel -= 8; // account for instruction prefetch, PC is 8 bytes ahead of this instruction rel >>= 2; // in ARM mode the branch target is 32-bit aligned, so the 2 LSB are omitted - if (SIGNED_FIT24(rel)) { + if (MP_FIT_SIGNED(24, rel)) { emit(as, cond | 0xa000000 | (rel & 0xffffff)); } else { printf("asm_arm_bcc: branch does not fit in 24 bits\n"); diff --git a/py/asmarm.h b/py/asmarm.h index 0fc1efe5ecd87..f3fd586a37530 100644 --- a/py/asmarm.h +++ b/py/asmarm.h @@ -94,8 +94,10 @@ void asm_arm_cmp_reg_i8(asm_arm_t *as, uint rd, int imm); void asm_arm_cmp_reg_reg(asm_arm_t *as, uint rd, uint rn); // arithmetic +void asm_arm_mvn_reg_reg(asm_arm_t *as, uint rd, uint rm); void asm_arm_add_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_sub_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); +void asm_arm_rsb_reg_reg_imm(asm_arm_t *as, uint rd, uint rn, uint imm); void asm_arm_mul_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_and_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); void asm_arm_eor_reg_reg_reg(asm_arm_t *as, uint rd, uint rn, uint rm); @@ -107,13 +109,18 @@ void asm_arm_lsr_reg_reg(asm_arm_t *as, uint rd, uint rs); void asm_arm_asr_reg_reg(asm_arm_t *as, uint rd, uint rs); // memory -void asm_arm_ldr_reg_reg(asm_arm_t *as, uint rd, uint rn, uint byte_offset); -void asm_arm_ldrh_reg_reg(asm_arm_t *as, uint rd, uint rn); +void asm_arm_ldr_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); void asm_arm_ldrh_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); -void asm_arm_ldrb_reg_reg(asm_arm_t *as, uint rd, uint rn); -void asm_arm_str_reg_reg(asm_arm_t *as, uint rd, uint rm, uint byte_offset); -void asm_arm_strh_reg_reg(asm_arm_t *as, uint rd, uint rm); -void asm_arm_strb_reg_reg(asm_arm_t *as, uint rd, uint rm); +void asm_arm_ldrb_reg_reg_offset(asm_arm_t *as, uint rd, uint rn, uint byte_offset); +void asm_arm_str_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); +void asm_arm_strh_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); +void asm_arm_strb_reg_reg_offset(asm_arm_t *as, uint rd, uint rm, uint byte_offset); + +// load from array +void asm_arm_ldr_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_ldrh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); +void asm_arm_ldrb_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); + // store to array void asm_arm_str_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); void asm_arm_strh_reg_reg_reg(asm_arm_t *as, uint rd, uint rm, uint rn); @@ -158,12 +165,12 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_ARM_REG_FUN_TABLE -#define ASM_T asm_arm_t -#define ASM_END_PASS asm_arm_end_pass -#define ASM_ENTRY asm_arm_entry -#define ASM_EXIT asm_arm_exit +#define ASM_T asm_arm_t +#define ASM_END_PASS asm_arm_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_arm_entry((as), (num_locals)) +#define ASM_EXIT asm_arm_exit -#define ASM_JUMP asm_arm_b_label +#define ASM_JUMP asm_arm_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_arm_cmp_reg_i8(as, reg, 0); \ @@ -189,6 +196,8 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_arm_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_arm_mov_reg_pcrel((as), (reg_dest), (label)) +#define ASM_NOT_REG(as, reg_dest) asm_arm_mvn_reg_reg((as), (reg_dest), (reg_dest)) +#define ASM_NEG_REG(as, reg_dest) asm_arm_rsb_reg_reg_imm((as), (reg_dest), (reg_dest), 0) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_arm_lsl_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_LSR_REG_REG(as, reg_dest, reg_shift) asm_arm_lsr_reg_reg((as), (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_arm_asr_reg_reg((as), (reg_dest), (reg_shift)) @@ -199,18 +208,28 @@ void asm_arm_bx_reg(asm_arm_t *as, uint reg_src); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_arm_sub_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_arm_mul_reg_reg_reg((as), (reg_dest), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_arm_ldrb_reg_reg((as), (reg_dest), (reg_base)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_arm_ldrh_reg_reg((as), (reg_dest), (reg_base)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_arm_ldrh_reg_reg_offset((as), (reg_dest), (reg_base), 2 * (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_arm_ldr_reg_reg((as), (reg_dest), (reg_base), 0) - -#define ASM_STORE_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_str_reg_reg((as), (reg_dest), (reg_base), 4 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_value, reg_base) asm_arm_strb_reg_reg((as), (reg_value), (reg_base)) -#define ASM_STORE16_REG_REG(as, reg_value, reg_base) asm_arm_strh_reg_reg((as), (reg_value), (reg_base)) -#define ASM_STORE32_REG_REG(as, reg_value, reg_base) asm_arm_str_reg_reg((as), (reg_value), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_arm_ldrb_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_arm_ldrh_reg_reg_offset((as), (reg_dest), (reg_base), 2 * (halfword_offset)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_arm_ldr_reg_reg_offset((as), (reg_dest), (reg_base), 4 * (word_offset)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_value, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_value), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_value, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_value, reg_base, byte_offset) asm_arm_strb_reg_reg_offset((as), (reg_value), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_value, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_value, reg_base, halfword_offset) asm_arm_strh_reg_reg_offset((as), (reg_value), (reg_base), 2 * (halfword_offset)) +#define ASM_STORE32_REG_REG(as, reg_value, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_value), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_value, reg_base, word_offset) asm_arm_str_reg_reg_offset((as), (reg_value), (reg_base), 4 * (word_offset)) + +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldrb_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldrh_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_arm_ldr_reg_reg_reg((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_strb_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_strh_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_arm_str_reg_reg_reg((as), (reg_val), (reg_base), (reg_index)) #endif // GENERIC_ASM_API diff --git a/py/asmbase.c b/py/asmbase.c index cf64e3f3d054f..07dbf4430f9db 100644 --- a/py/asmbase.c +++ b/py/asmbase.c @@ -30,6 +30,7 @@ #include "py/obj.h" #include "py/misc.h" #include "py/asmbase.h" +#include "py/persistentcode.h" #if MICROPY_EMIT_MACHINE_CODE @@ -52,7 +53,7 @@ void mp_asm_base_start_pass(mp_asm_base_t *as, int pass) { } else { // allocating executable RAM is platform specific MP_PLAT_ALLOC_EXEC(as->code_offset, (void **)&as->code_base, &as->code_size); - assert(as->code_base != NULL); + assert(as->code_size == 0 || as->code_base != NULL); } as->pass = pass; as->suppress = false; @@ -91,12 +92,17 @@ void mp_asm_base_label_assign(mp_asm_base_t *as, size_t label) { } else { // ensure label offset has not changed from PASS_COMPUTE to PASS_EMIT assert(as->label_offsets[label] == as->code_offset); + #if MICROPY_DYNAMIC_COMPILER && MICROPY_EMIT_NATIVE_DEBUG + if (mp_dynamic_compiler.native_arch == MP_NATIVE_ARCH_DEBUG) { + mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, "label(label_%u)\n", (unsigned int)label); + } + #endif } } // align must be a multiple of 2 void mp_asm_base_align(mp_asm_base_t *as, unsigned int align) { - as->code_offset = (as->code_offset + align - 1) & (~(align - 1)); + as->code_offset = (as->code_offset + align - 1) & (~(size_t)(align - 1)); } // this function assumes a little endian machine diff --git a/py/asmbase.h b/py/asmbase.h index 352d2f54cc810..461393fe77fb7 100644 --- a/py/asmbase.h +++ b/py/asmbase.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_ASMBASE_H #include +#include #include #define MP_ASM_PASS_COMPUTE (1) diff --git a/py/asmrv32.c b/py/asmrv32.c new file mode 100644 index 0000000000000..1d0cea6c02616 --- /dev/null +++ b/py/asmrv32.c @@ -0,0 +1,614 @@ +/* + * This file is part of the MicroPython project, https://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include + +#include "py/emit.h" +#include "py/misc.h" +#include "py/mpconfig.h" + +// wrapper around everything in this file +#if MICROPY_EMIT_RV32 + +#include "py/asmrv32.h" +#include "py/mpstate.h" +#include "py/persistentcode.h" + +#if MICROPY_DEBUG_VERBOSE +#define DEBUG_PRINT (1) +#define DEBUG_printf DEBUG_printf +#else +#define DEBUG_printf(...) (void)0 +#endif + +#define INTERNAL_TEMPORARY ASM_RV32_REG_S0 + +#define FIT_UNSIGNED(value, bits) (((value) & ~((1U << (bits)) - 1)) == 0) +#define FIT_SIGNED(value, bits) \ + ((((value) & ~((1U << ((bits) - 1)) - 1)) == 0) || \ + (((value) & ~((1U << ((bits) - 1)) - 1)) == ~((1U << ((bits) - 1)) - 1))) + +/////////////////////////////////////////////////////////////////////////////// + +void asm_rv32_emit_word_opcode(asm_rv32_t *state, mp_uint_t word) { + uint8_t *cursor = mp_asm_base_get_cur_to_write_bytes(&state->base, sizeof(uint32_t)); + if (cursor == NULL) { + return; + } + + #if MP_ENDIANNESS_LITTLE + cursor[0] = word & 0xFF; + cursor[1] = (word >> 8) & 0xFF; + cursor[2] = (word >> 16) & 0xFF; + cursor[3] = (word >> 24) & 0xFF; + #else + cursor[0] = (word >> 24) & 0xFF; + cursor[1] = (word >> 16) & 0xFF; + cursor[2] = (word >> 8) & 0xFF; + cursor[3] = word & 0xFF; + #endif +} + +void asm_rv32_emit_halfword_opcode(asm_rv32_t *state, mp_uint_t word) { + uint8_t *cursor = mp_asm_base_get_cur_to_write_bytes(&state->base, sizeof(uint16_t)); + if (cursor == NULL) { + return; + } + + #if MP_ENDIANNESS_LITTLE + cursor[0] = word & 0xFF; + cursor[1] = (word >> 8) & 0xFF; + #else + cursor[0] = (word >> 8) & 0xFF; + cursor[1] = word & 0xFF; + #endif +} + +/////////////////////////////////////////////////////////////////////////////// + +static void split_immediate(mp_int_t immediate, mp_uint_t *upper, mp_uint_t *lower) { + assert(upper != NULL && "Upper pointer is NULL."); + assert(lower != NULL && "Lower pointer is NULL."); + + mp_uint_t unsigned_immediate = *((mp_uint_t *)&immediate); + *upper = unsigned_immediate & 0xFFFFF000; + *lower = unsigned_immediate & 0x00000FFF; + + // Turn the lower half from unsigned to signed. + if ((*lower & 0x800) != 0) { + *upper += 0x1000; + } +} + +static void load_upper_immediate(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate) { + // if immediate fits in 17 bits and is ≠ 0: + // c.lui rd, HI(immediate) + // else: + // lui rd, HI(immediate) + if (FIT_SIGNED(immediate, 17) && ((immediate >> 12) != 0)) { + asm_rv32_opcode_clui(state, rd, immediate); + } else { + asm_rv32_opcode_lui(state, rd, immediate); + } +} + +static void load_lower_immediate(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate) { + // WARNING: This must be executed on a register that has either been + // previously cleared or was the target of a LUI/C.LUI or + // AUIPC opcode. + + if (immediate == 0) { + return; + } + + // if LO(immediate) fits in 6 bits: + // c.addi rd, LO(immediate) + // else: + // addi rd, rd, LO(immediate) + if (FIT_SIGNED(immediate, 6)) { + asm_rv32_opcode_caddi(state, rd, immediate); + } else { + asm_rv32_opcode_addi(state, rd, rd, immediate); + } +} + +static void load_full_immediate(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(immediate, &upper, &lower); + + // if immediate fits in 17 bits: + // c.lui rd, HI(immediate) + // else: + // lui rd, HI(immediate) + // if LO(immediate) fits in 6 bits && LO(immediate) != 0: + // c.addi rd, LO(immediate) + // else: + // addi rd, rd, LO(immediate) + load_upper_immediate(state, rd, upper); + load_lower_immediate(state, rd, lower); +} + +void asm_rv32_emit_optimised_load_immediate(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + if (FIT_SIGNED(immediate, 6)) { + // c.li rd, immediate + asm_rv32_opcode_cli(state, rd, immediate); + return; + } + + if (FIT_SIGNED(immediate, 12)) { + // addi rd, zero, immediate + asm_rv32_opcode_addi(state, rd, ASM_RV32_REG_ZERO, immediate); + return; + } + + load_full_immediate(state, rd, immediate); +} + +// RV32 does not have dedicated push/pop opcodes, so series of loads and +// stores are generated in their place. + +static void emit_registers_store(asm_rv32_t *state, mp_uint_t registers_mask) { + mp_uint_t offset = 0; + for (mp_uint_t register_index = 0; register_index < RV32_AVAILABLE_REGISTERS_COUNT; register_index++) { + if (registers_mask & (1U << register_index)) { + assert(FIT_UNSIGNED(offset >> 2, 6) && "Registers save stack offset out of range."); + // c.swsp register, offset + asm_rv32_opcode_cswsp(state, register_index, offset); + offset += sizeof(uint32_t); + } + } +} + +static void emit_registers_load(asm_rv32_t *state, mp_uint_t registers_mask) { + mp_uint_t offset = 0; + for (mp_uint_t register_index = 0; register_index < RV32_AVAILABLE_REGISTERS_COUNT; register_index++) { + if (registers_mask & (1U << register_index)) { + assert(FIT_UNSIGNED(offset >> 2, 6) && "Registers load stack offset out of range."); + // c.lwsp register, offset + asm_rv32_opcode_clwsp(state, register_index, offset); + offset += sizeof(uint32_t); + } + } +} + +static void adjust_stack(asm_rv32_t *state, mp_int_t stack_size) { + if (stack_size == 0) { + return; + } + + if (FIT_SIGNED(stack_size, 6)) { + // c.addi sp, stack_size + asm_rv32_opcode_caddi(state, ASM_RV32_REG_SP, stack_size); + return; + } + + if (FIT_SIGNED(stack_size, 12)) { + // addi sp, sp, stack_size + asm_rv32_opcode_addi(state, ASM_RV32_REG_SP, ASM_RV32_REG_SP, stack_size); + return; + } + + // li temporary, stack_size + // c.add sp, temporary + load_full_immediate(state, REG_TEMP0, stack_size); + asm_rv32_opcode_cadd(state, ASM_RV32_REG_SP, REG_TEMP0); +} + +// Generate a generic function entry prologue code sequence, setting up the +// stack to hold all the tainted registers and an arbitrary amount of space +// for locals. +static void emit_function_prologue(asm_rv32_t *state, mp_uint_t registers) { + mp_uint_t registers_count = mp_popcount(registers); + state->stack_size = (registers_count + state->locals_count) * sizeof(uint32_t); + mp_uint_t old_saved_registers_mask = state->saved_registers_mask; + // Move stack pointer up. + adjust_stack(state, -state->stack_size); + // Store registers at the top of the saved stack area. + emit_registers_store(state, registers); + state->locals_stack_offset = registers_count * sizeof(uint32_t); + state->saved_registers_mask = old_saved_registers_mask; +} + +// Restore registers and reset the stack pointer to its initial value. +static void emit_function_epilogue(asm_rv32_t *state, mp_uint_t registers) { + mp_uint_t old_saved_registers_mask = state->saved_registers_mask; + // Restore registers from the top of the stack area. + emit_registers_load(state, registers); + // Move stack pointer down. + adjust_stack(state, state->stack_size); + state->saved_registers_mask = old_saved_registers_mask; +} + +static bool calculate_displacement_for_label(asm_rv32_t *state, mp_uint_t label, ptrdiff_t *displacement) { + assert(displacement != NULL && "Displacement pointer is NULL"); + + mp_uint_t label_offset = state->base.label_offsets[label]; + *displacement = (ptrdiff_t)(label_offset - state->base.code_offset); + return (label_offset != (mp_uint_t)-1) && (*displacement < 0); +} + +/////////////////////////////////////////////////////////////////////////////// + +void asm_rv32_entry(asm_rv32_t *state, mp_uint_t locals) { + state->saved_registers_mask |= (1U << REG_FUN_TABLE) | (1U << REG_LOCAL_1) | \ + (1U << REG_LOCAL_2) | (1U << REG_LOCAL_3); + state->locals_count = locals; + emit_function_prologue(state, state->saved_registers_mask); +} + +void asm_rv32_exit(asm_rv32_t *state) { + emit_function_epilogue(state, state->saved_registers_mask); + // c.jr ra + asm_rv32_opcode_cjr(state, ASM_RV32_REG_RA); +} + +void asm_rv32_end_pass(asm_rv32_t *state) { + (void)state; +} + +void asm_rv32_emit_call_ind(asm_rv32_t *state, mp_uint_t index) { + mp_uint_t offset = index * ASM_WORD_SIZE; + state->saved_registers_mask |= (1U << ASM_RV32_REG_RA); + + if (RV32_IS_IN_C_REGISTER_WINDOW(REG_FUN_TABLE) && RV32_IS_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY) && FIT_UNSIGNED(offset, 6)) { + state->saved_registers_mask |= (1U << INTERNAL_TEMPORARY); + // c.lw temporary, offset(fun_table) + // c.jalr temporary + asm_rv32_opcode_clw(state, RV32_MAP_IN_C_REGISTER_WINDOW(INTERNAL_TEMPORARY), RV32_MAP_IN_C_REGISTER_WINDOW(REG_FUN_TABLE), offset); + asm_rv32_opcode_cjalr(state, INTERNAL_TEMPORARY); + return; + } + + if (FIT_UNSIGNED(offset, 11)) { + // lw temporary, offset(fun_table) + // c.jalr temporary + asm_rv32_opcode_lw(state, REG_TEMP2, REG_FUN_TABLE, offset); + asm_rv32_opcode_cjalr(state, REG_TEMP2); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(offset, &upper, &lower); + + // lui temporary, HI(index) ; Or c.lui if possible + // c.add temporary, fun_table + // lw temporary, LO(index)(temporary) + // c.jalr temporary + load_upper_immediate(state, REG_TEMP2, upper); + asm_rv32_opcode_cadd(state, REG_TEMP2, REG_FUN_TABLE); + asm_rv32_opcode_lw(state, REG_TEMP2, REG_TEMP2, lower); + asm_rv32_opcode_cjalr(state, REG_TEMP2); +} + +void asm_rv32_emit_jump_if_reg_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t label) { + ptrdiff_t displacement = 0; + bool can_emit_short_jump = calculate_displacement_for_label(state, label, &displacement); + + if (can_emit_short_jump && FIT_SIGNED(displacement, 13)) { + // beq rs1, rs2, displacement + asm_rv32_opcode_beq(state, rs1, rs2, displacement); + return; + } + + // Compensate for the initial BNE opcode. + displacement -= ASM_WORD_SIZE; + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(displacement, &upper, &lower); + + // bne rs1, rs2, 12 ; PC + 0 + // auipc temporary, HI(displacement) ; PC + 4 + // jalr zero, temporary, LO(displacement) ; PC + 8 + // ... ; PC + 12 + asm_rv32_opcode_bne(state, rs1, rs2, 12); + asm_rv32_opcode_auipc(state, REG_TEMP2, upper); + asm_rv32_opcode_jalr(state, ASM_RV32_REG_ZERO, REG_TEMP2, lower); +} + +void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_t label) { + ptrdiff_t displacement = 0; + bool can_emit_short_jump = calculate_displacement_for_label(state, label, &displacement); + + if (can_emit_short_jump && FIT_SIGNED(displacement, 8) && RV32_IS_IN_C_REGISTER_WINDOW(rs)) { + // c.bnez rs', displacement + asm_rv32_opcode_cbnez(state, RV32_MAP_IN_C_REGISTER_WINDOW(rs), displacement); + return; + } + + if (can_emit_short_jump && FIT_SIGNED(displacement, 13)) { + // bne rs, zero, displacement + asm_rv32_opcode_bne(state, rs, ASM_RV32_REG_ZERO, displacement); + return; + } + + // if rs1 in C window and displacement is negative: + // c.beqz rs', 10 ; PC + 0 + // auipc temporary, HI(displacement) ; PC + 2 + // jalr zero, temporary, LO(displacement) ; PC + 6 + // ... ; PC + 10 + // else: + // beq rs, zero, 12 ; PC + 0 + // auipc temporary, HI(displacement) ; PC + 4 + // jalr zero, temporary, LO(displacement) ; PC + 8 + // ... ; PC + 12 + + if (can_emit_short_jump && RV32_IS_IN_C_REGISTER_WINDOW(rs)) { + asm_rv32_opcode_cbeqz(state, RV32_MAP_IN_C_REGISTER_WINDOW(rs), 10); + // Compensate for the C.BEQZ opcode. + displacement -= ASM_HALFWORD_SIZE; + } else { + asm_rv32_opcode_beq(state, rs, ASM_RV32_REG_ZERO, 12); + // Compensate for the BEQ opcode. + displacement -= ASM_WORD_SIZE; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(displacement, &upper, &lower); + asm_rv32_opcode_auipc(state, REG_TEMP2, upper); + asm_rv32_opcode_jalr(state, ASM_RV32_REG_ZERO, REG_TEMP2, lower); +} + +void asm_rv32_emit_mov_local_reg(asm_rv32_t *state, mp_uint_t local, mp_uint_t rs) { + mp_uint_t offset = state->locals_stack_offset + (local * ASM_WORD_SIZE); + + if (FIT_UNSIGNED(offset >> 2, 6)) { + // c.swsp rs, offset + asm_rv32_opcode_cswsp(state, rs, offset); + return; + } + + if (FIT_UNSIGNED(offset, 11)) { + // sw rs, offset(sp) + asm_rv32_opcode_sw(state, rs, ASM_RV32_REG_SP, offset); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(offset, &upper, &lower); + + // lui temporary, HI(offset) ; Or c.lui if possible + // c.add temporary, sp + // sw rs, LO(offset)(temporary) + load_upper_immediate(state, REG_TEMP2, upper); + asm_rv32_opcode_cadd(state, REG_TEMP2, ASM_RV32_REG_SP); + asm_rv32_opcode_sw(state, rs, REG_TEMP2, lower); +} + +void asm_rv32_emit_mov_reg_local(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local) { + mp_uint_t offset = state->locals_stack_offset + (local * ASM_WORD_SIZE); + + if (FIT_UNSIGNED(offset >> 2, 6)) { + // c.lwsp rd, offset + asm_rv32_opcode_clwsp(state, rd, offset); + return; + } + + if (FIT_UNSIGNED(offset, 11)) { + // lw rd, offset(sp) + asm_rv32_opcode_lw(state, rd, ASM_RV32_REG_SP, offset); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(offset, &upper, &lower); + + // lui rd, HI(offset) ; Or c.lui if possible + // c.add rd, sp + // lw rd, LO(offset)(rd) + load_upper_immediate(state, rd, upper); + asm_rv32_opcode_cadd(state, rd, ASM_RV32_REG_SP); + asm_rv32_opcode_lw(state, rd, rd, lower); +} + +void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local) { + mp_uint_t offset = state->locals_stack_offset + (local * ASM_WORD_SIZE); + + if (FIT_UNSIGNED(offset, 10) && offset != 0 && RV32_IS_IN_C_REGISTER_WINDOW(rd)) { + // c.addi4spn rd', offset + asm_rv32_opcode_caddi4spn(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), offset); + return; + } + + if (FIT_UNSIGNED(offset, 11)) { + // addi rd, sp, offset + asm_rv32_opcode_addi(state, rd, ASM_RV32_REG_SP, offset); + return; + } + + // li rd, offset + // c.add rd, sp + load_full_immediate(state, rd, offset); + asm_rv32_opcode_cadd(state, rd, ASM_RV32_REG_SP); +} + +static const uint8_t RV32_LOAD_OPCODE_TABLE[3] = { + 0x04, 0x05, 0x02 +}; + +void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + int32_t scaled_offset = offset << operation_size; + + if (scaled_offset >= 0 && operation_size == 2 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && MP_FIT_UNSIGNED(6, scaled_offset)) { + // c.lw rd', offset(rs') + asm_rv32_opcode_clw(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), RV32_MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset); + return; + } + + if (MP_FIT_SIGNED(12, scaled_offset)) { + // lbu|lhu|lw rd, offset(rs) + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, RV32_LOAD_OPCODE_TABLE[operation_size], rd, rs, scaled_offset)); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(scaled_offset, &upper, &lower); + + // lui rd, HI(offset) ; Or c.lui if possible + // c.add rd, rs + // lbu|lhu|lw rd, LO(offset)(rd) + load_upper_immediate(state, rd, upper); + asm_rv32_opcode_cadd(state, rd, rs); + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, RV32_LOAD_OPCODE_TABLE[operation_size], rd, rd, lower)); +} + +void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label) { + ptrdiff_t displacement = 0; + bool can_emit_short_jump = calculate_displacement_for_label(state, label, &displacement); + + if (can_emit_short_jump && FIT_SIGNED(displacement, 12)) { + // c.j displacement + asm_rv32_opcode_cj(state, displacement); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(displacement, &upper, &lower); + + // auipc temporary, HI(displacement) + // jalr zero, temporary, LO(displacement) + asm_rv32_opcode_auipc(state, REG_TEMP2, upper); + asm_rv32_opcode_jalr(state, ASM_RV32_REG_ZERO, REG_TEMP2, lower); +} + +void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + int32_t scaled_offset = offset << operation_size; + + if (scaled_offset >= 0 && operation_size == 2 && RV32_IS_IN_C_REGISTER_WINDOW(rd) && RV32_IS_IN_C_REGISTER_WINDOW(rs) && MP_FIT_UNSIGNED(6, scaled_offset)) { + // c.sw rd', offset(rs') + asm_rv32_opcode_csw(state, RV32_MAP_IN_C_REGISTER_WINDOW(rd), RV32_MAP_IN_C_REGISTER_WINDOW(rs), scaled_offset); + return; + } + + if (MP_FIT_SIGNED(12, scaled_offset)) { + // sb|sh|sw rd, offset(rs) + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, operation_size, rs, rd, scaled_offset)); + return; + } + + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(scaled_offset, &upper, &lower); + + // lui temporary, HI(offset) ; Or c.lui if possible + // c.add temporary, rs + // sb|sh|sw rd, LO(offset)(temporary) + load_upper_immediate(state, REG_TEMP2, upper); + asm_rv32_opcode_cadd(state, REG_TEMP2, rs); + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, operation_size, REG_TEMP2, rd, lower)); +} + +void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t label) { + ptrdiff_t displacement = (ptrdiff_t)(state->base.label_offsets[label] - state->base.code_offset); + mp_uint_t upper = 0; + mp_uint_t lower = 0; + split_immediate(displacement, &upper, &lower); + + // auipc rd, HI(relative) + // addi rd, rd, LO(relative) + asm_rv32_opcode_auipc(state, rd, upper); + asm_rv32_opcode_addi(state, rd, rd, lower); +} + +void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + if (rs == rd) { + // c.li rd, 0 + asm_rv32_opcode_cli(state, rd, 0); + return; + } + + // xor rd, rd, rs + asm_rv32_opcode_xor(state, rd, rd, rs); +} + +static bool asm_rv32_allow_zba_opcodes(void) { + return asm_rv32_allowed_extensions() & RV32_EXT_ZBA; +} + +static void asm_rv32_fix_up_scaled_reg_reg_reg(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size > 0 && asm_rv32_allow_zba_opcodes()) { + // sh{1,2}add rs1, rs2, rs1 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 1 << operation_size, 0x10, rs1, rs2, rs1)); + } else { + if (operation_size > 0) { + asm_rv32_opcode_cslli(state, rs2, operation_size); + } + asm_rv32_opcode_cadd(state, rs1, rs2); + } +} + +void asm_rv32_emit_load_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size); + asm_rv32_emit_load_reg_reg_offset(state, rd, rs1, 0, operation_size); +} + +void asm_rv32_emit_store_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size) { + asm_rv32_fix_up_scaled_reg_reg_reg(state, rs1, rs2, operation_size); + asm_rv32_emit_store_reg_reg_offset(state, rd, rs1, 0, operation_size); +} + +void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd) { + // sub rd, rs1, rs2 + // sltiu rd, rd, 1 + asm_rv32_opcode_sub(state, rd, rs1, rs2); + asm_rv32_opcode_sltiu(state, rd, rd, 1); +} + +void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd) { + // sub rd, rs1, rs2 + // sltu rd, zero, rd + asm_rv32_opcode_sub(state, rd, rs1, rs2); + asm_rv32_opcode_sltu(state, rd, ASM_RV32_REG_ZERO, rd); +} + +void asm_rv32_meta_comparison_lt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison) { + // slt|sltu rd, rs1, rs2 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, (0x02 | (unsigned_comparison ? 1 : 0)), 0x00, rd, rs1, rs2)); +} + +void asm_rv32_meta_comparison_le(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison) { + // slt[u] rd, rs2, rs1 + // xori rd, rd, 1 + asm_rv32_meta_comparison_lt(state, rs2, rs1, rd, unsigned_comparison); + asm_rv32_opcode_xori(state, rd, rd, 1); +} + +#endif // MICROPY_EMIT_RV32 diff --git a/py/asmrv32.h b/py/asmrv32.h new file mode 100644 index 0000000000000..6f709daa11bce --- /dev/null +++ b/py/asmrv32.h @@ -0,0 +1,817 @@ +/* + * This file is part of the MicroPython project, https://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_PY_ASMRV32_H +#define MICROPY_INCLUDED_PY_ASMRV32_H + +#include + +#include "py/asmbase.h" +#include "py/emit.h" +#include "py/misc.h" +#include "py/persistentcode.h" + +#define ASM_RV32_REG_X0 (0) // Zero +#define ASM_RV32_REG_X1 (1) // RA +#define ASM_RV32_REG_X2 (2) // SP +#define ASM_RV32_REG_X3 (3) // GP +#define ASM_RV32_REG_X4 (4) // TP +#define ASM_RV32_REG_X5 (5) // T0 +#define ASM_RV32_REG_X6 (6) // T1 +#define ASM_RV32_REG_X7 (7) // T2 +#define ASM_RV32_REG_X8 (8) // S0 +#define ASM_RV32_REG_X9 (9) // S1 +#define ASM_RV32_REG_X10 (10) // A0 +#define ASM_RV32_REG_X11 (11) // A1 +#define ASM_RV32_REG_X12 (12) // A2 +#define ASM_RV32_REG_X13 (13) // A3 +#define ASM_RV32_REG_X14 (14) // A4 +#define ASM_RV32_REG_X15 (15) // A5 +#define ASM_RV32_REG_X16 (16) // A6 +#define ASM_RV32_REG_X17 (17) // A7 +#define ASM_RV32_REG_X18 (18) // S2 +#define ASM_RV32_REG_X19 (19) // S3 +#define ASM_RV32_REG_X20 (20) // S4 +#define ASM_RV32_REG_X21 (21) // S5 +#define ASM_RV32_REG_X22 (22) // S6 +#define ASM_RV32_REG_X23 (23) // S7 +#define ASM_RV32_REG_X24 (24) // S8 +#define ASM_RV32_REG_X25 (25) // S9 +#define ASM_RV32_REG_X26 (26) // S10 +#define ASM_RV32_REG_X27 (27) // S11 +#define ASM_RV32_REG_X28 (28) // T3 +#define ASM_RV32_REG_X29 (29) // T4 +#define ASM_RV32_REG_X30 (30) // T5 +#define ASM_RV32_REG_X31 (31) // T6 + +// Alternate register names. + +#define ASM_RV32_REG_ZERO (ASM_RV32_REG_X0) +#define ASM_RV32_REG_RA (ASM_RV32_REG_X1) +#define ASM_RV32_REG_SP (ASM_RV32_REG_X2) +#define ASM_RV32_REG_GP (ASM_RV32_REG_X3) +#define ASM_RV32_REG_TP (ASM_RV32_REG_X4) +#define ASM_RV32_REG_A0 (ASM_RV32_REG_X10) +#define ASM_RV32_REG_A1 (ASM_RV32_REG_X11) +#define ASM_RV32_REG_A2 (ASM_RV32_REG_X12) +#define ASM_RV32_REG_A3 (ASM_RV32_REG_X13) +#define ASM_RV32_REG_A4 (ASM_RV32_REG_X14) +#define ASM_RV32_REG_A5 (ASM_RV32_REG_X15) +#define ASM_RV32_REG_A6 (ASM_RV32_REG_X16) +#define ASM_RV32_REG_A7 (ASM_RV32_REG_X17) +#define ASM_RV32_REG_T0 (ASM_RV32_REG_X5) +#define ASM_RV32_REG_T1 (ASM_RV32_REG_X6) +#define ASM_RV32_REG_T2 (ASM_RV32_REG_X7) +#define ASM_RV32_REG_T3 (ASM_RV32_REG_X28) +#define ASM_RV32_REG_T4 (ASM_RV32_REG_X29) +#define ASM_RV32_REG_T5 (ASM_RV32_REG_X30) +#define ASM_RV32_REG_T6 (ASM_RV32_REG_X31) +#define ASM_RV32_REG_FP (ASM_RV32_REG_X8) +#define ASM_RV32_REG_S0 (ASM_RV32_REG_X8) +#define ASM_RV32_REG_S1 (ASM_RV32_REG_X9) +#define ASM_RV32_REG_S2 (ASM_RV32_REG_X18) +#define ASM_RV32_REG_S3 (ASM_RV32_REG_X19) +#define ASM_RV32_REG_S4 (ASM_RV32_REG_X20) +#define ASM_RV32_REG_S5 (ASM_RV32_REG_X21) +#define ASM_RV32_REG_S6 (ASM_RV32_REG_X22) +#define ASM_RV32_REG_S7 (ASM_RV32_REG_X23) +#define ASM_RV32_REG_S8 (ASM_RV32_REG_X24) +#define ASM_RV32_REG_S9 (ASM_RV32_REG_X25) +#define ASM_RV32_REG_S10 (ASM_RV32_REG_X26) +#define ASM_RV32_REG_S11 (ASM_RV32_REG_X27) + +#define RV32_AVAILABLE_REGISTERS_COUNT 32 +#define RV32_MAP_IN_C_REGISTER_WINDOW(register_number) \ + ((register_number) - ASM_RV32_REG_X8) +#define RV32_IS_IN_C_REGISTER_WINDOW(register_number) \ + (((register_number) >= ASM_RV32_REG_X8) && ((register_number) <= ASM_RV32_REG_X15)) + +typedef struct _asm_rv32_t { + // Opaque emitter state. + mp_asm_base_t base; + // Which registers are tainted and need saving/restoring. + mp_uint_t saved_registers_mask; + // How many locals must be stored on the stack. + mp_uint_t locals_count; + // The computed function stack size. + mp_uint_t stack_size; + // The stack offset where stack-based locals start to be stored. + mp_uint_t locals_stack_offset; +} asm_rv32_t; + +enum { + RV32_EXT_NONE = 0, + RV32_EXT_ZBA = 1 << 0, + + RV32_EXT_ALL = RV32_EXT_ZBA +}; + +typedef struct _asm_rv32_backend_options_t { + // This is a bitmask holding a combination of RV32_EXT_* entries. + uint8_t allowed_extensions; +} asm_rv32_backend_options_t; + +void asm_rv32_entry(asm_rv32_t *state, mp_uint_t locals); +void asm_rv32_exit(asm_rv32_t *state); +void asm_rv32_end_pass(asm_rv32_t *state); + +//////////////////////////////////////////////////////////////////////////////// + +#define RV32_ENCODE_TYPE_B(op, ft3, rs1, rs2, imm) \ + ((op & 0x7F) | ((ft3 & 0x07) << 12) | ((imm & 0x800) >> 4) | \ + ((imm & 0x1E) << 7) | ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | \ + ((imm & 0x7E0) << 20) | ((imm & 0x1000) << 19)) + +#define RV32_ENCODE_TYPE_CSRI(op, ft3, rd, csr, imm) \ + ((op & 0x7F) | ((rd & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \ + ((csr & 0xFFF) << 20) | ((imm & 0x1F) << 15)) + +#define RV32_ENCODE_TYPE_I(op, ft3, rd, rs, imm) \ + ((op & 0x7F) | ((rd & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \ + ((rs & 0x1F) << 15) | ((imm & 0xFFF) << 20)) + +#define RV32_ENCODE_TYPE_J(op, rd, imm) \ + ((op & 0x7F) | ((rd & 0x1F) << 7) | (imm & 0xFF000) | \ + ((imm & 0x800) << 9) | ((imm & 0x7FE) << 20) | ((imm & 0x100000) << 11)) + +#define RV32_ENCODE_TYPE_R(op, ft3, ft7, rd, rs1, rs2) \ + ((op & 0x7F) | ((rd & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \ + ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | ((ft7 & 0x7F) << 25)) + +#define RV32_ENCODE_TYPE_S(op, ft3, rs1, rs2, imm) \ + ((op & 0x7F) | ((imm & 0x1F) << 7) | ((ft3 & 0x07) << 12) | \ + ((rs1 & 0x1F) << 15) | ((rs2 & 0x1F) << 20) | ((imm & 0xFE0) << 20)) + +#define RV32_ENCODE_TYPE_CA(op, ft6, ft2, rd, rs) \ + ((op & 0x03) | ((ft6 & 0x3F) << 10) | ((ft2 & 0x03) << 5) | \ + ((rd & 0x03) << 7) | ((rs & 0x03) << 2)) + +#define RV32_ENCODE_TYPE_U(op, rd, imm) \ + ((op & 0x7F) | ((rd & 0x1F) << 7) | (imm & 0xFFFFF000)) + +#define RV32_ENCODE_TYPE_CB(op, ft3, rs, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rs & 0x07) << 7) | \ + (((imm) & 0xE0) << 5) | (((imm) & 0x1F) << 2)) + +#define RV32_ENCODE_TYPE_CI(op, ft3, rd, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x1F) << 7) | \ + (((imm) & 0x20) << 7) | (((imm) & 0x1F) << 2)) + +#define RV32_ENCODE_TYPE_CIW(op, ft3, rd, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x07) << 2) | \ + ((imm & 0x3C0) << 1) | ((imm & 0x30) << 7) | \ + ((imm & 0x08) << 2) | ((imm & 0x04) << 4)) + +#define RV32_ENCODE_TYPE_CJ(op, ft3, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((imm & 0x0E) << 2) | \ + ((imm & 0x300) << 1) | ((imm & 0x800) << 1) | ((imm & 0x400) >> 2) | \ + ((imm & 0x80) >> 1) | ((imm & 0x40) << 1) | ((imm & 0x20) >> 3) | \ + ((imm & 0x10) << 7)) + +#define RV32_ENCODE_TYPE_CL(op, ft3, rd, rs, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x07) << 2) | \ + ((rs & 0x07) << 7) | ((imm & 0x40) >> 1) | ((imm & 0x38) << 7) | \ + ((imm & 0x04) << 4)) + +#define RV32_ENCODE_TYPE_CR(op, ft4, rs1, rs2) \ + ((op & 0x03) | ((rs2 & 0x1F) << 2) | ((rs1 & 0x1F) << 7) | ((ft4 & 0x0F) << 12)) + +#define RV32_ENCODE_TYPE_CS(op, ft3, rd, rs, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rd & 0x07) << 2) | \ + ((rs & 0x07) << 7) | ((imm & 0x40) >> 1) | ((imm & 0x38) << 7) | \ + ((imm & 0x04) << 4)) + +#define RV32_ENCODE_TYPE_CSS(op, ft3, rs, imm) \ + ((op & 0x03) | ((ft3 & 0x07) << 13) | ((rs & 0x1F) << 2) | ((imm) & 0x3F) << 7) + +void asm_rv32_emit_word_opcode(asm_rv32_t *state, mp_uint_t opcode); +void asm_rv32_emit_halfword_opcode(asm_rv32_t *state, mp_uint_t opcode); + +// ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 000 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x00, rd, rs1, rs2)); +} + +// ADDI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_addi(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 000 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x00, rd, rs, immediate)); +} + +// AND RD, RS1, RS2 +static inline void asm_rv32_opcode_and(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 111 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x07, 0x00, rd, rs1, rs2)); +} + +// ANDI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_andi(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 111 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x07, rd, rs, immediate)); +} + +// AUIPC RD, offset +static inline void asm_rv32_opcode_auipc(asm_rv32_t *state, mp_uint_t rd, mp_int_t offset) { + // U: .................... ..... 0010111 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_U(0x17, rd, offset)); +} + +// BEQ RS1, RS2, OFFSET +static inline void asm_rv32_opcode_beq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 000 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x00, rs1, rs2, offset)); +} + +// BGE RS1, RS2, OFFSET +static inline void asm_rv32_opcode_bge(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 101 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x05, rs1, rs2, offset)); +} + +// BGEU RS1, RS2, OFFSET +static inline void asm_rv32_opcode_bgeu(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 111 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x07, rs1, rs2, offset)); +} + +// BLT RS1, RS2, OFFSET +static inline void asm_rv32_opcode_blt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 100 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x04, rs1, rs2, offset)); +} + +// BLTU RS1, RS2, OFFSET +static inline void asm_rv32_opcode_bltu(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 110 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x06, rs1, rs2, offset)); +} + +// BNE RS1, RS2, OFFSET +static inline void asm_rv32_opcode_bne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // B: . ...... ..... ..... 001 .... . 1100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_B(0x63, 0x01, rs1, rs2, offset)); +} + +// C.ADD RD, RS +static inline void asm_rv32_opcode_cadd(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CR: 1001 ..... ..... 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x09, rd, rs)); +} + +// C.ADDI RD, IMMEDIATE +static inline void asm_rv32_opcode_caddi(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CI: 000 . ..... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x00, rd, immediate)); +} + +// C.ADDI4SPN RD', IMMEDIATE +static inline void asm_rv32_opcode_caddi4spn(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate) { + // CIW: 000 ........ ... 00 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CIW(0x00, 0x00, rd, immediate)); +} + +// C.AND RD', RS' +static inline void asm_rv32_opcode_cand(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CA: 100011 ... 11 ... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CA(0x01, 0x23, 0x03, rd, rs)); +} + +// C.ANDI RD', IMMEDIATE +static inline void asm_rv32_opcode_candi(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CB: 100 . 10 ... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x04, rd, + (((immediate & 0x20) << 2) | (immediate & 0x1F) | 0x40))); +} + +// C.BEQZ RS', IMMEDIATE +static inline void asm_rv32_opcode_cbeqz(asm_rv32_t *state, mp_uint_t rs, mp_int_t offset) { + // CB: 110 ... ... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x06, rs, + (((offset & 0x100) >> 1) | ((offset & 0xC0) >> 3) | ((offset & 0x20) >> 5) | + ((offset & 0x18) << 2) | (offset & 0x06)))); +} + +// C.BNEZ RS', IMMEDIATE +static inline void asm_rv32_opcode_cbnez(asm_rv32_t *state, mp_uint_t rs, mp_int_t offset) { + // CB: 111 ... ... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x07, rs, + (((offset & 0x100) >> 1) | ((offset & 0xC0) >> 3) | ((offset & 0x20) >> 5) | + ((offset & 0x18) << 2) | (offset & 0x06)))); +} + +// C.EBREAK +static inline void asm_rv32_opcode_cebreak(asm_rv32_t *state) { + // CA: 100 1 00000 00000 10 + asm_rv32_emit_halfword_opcode(state, 0x9002); +} + +// C.J OFFSET +static inline void asm_rv32_opcode_cj(asm_rv32_t *state, mp_int_t offset) { + // CJ: 101 ........... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CJ(0x01, 0x05, offset)); +} + +// C.JAL OFFSET +static inline void asm_rv32_opcode_cjal(asm_rv32_t *state, mp_int_t offset) { + // CJ: 001 ........... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CJ(0x01, 0x01, offset)); +} + +// C.JALR RS +static inline void asm_rv32_opcode_cjalr(asm_rv32_t *state, mp_uint_t rs) { + // CR: 1001 ..... 00000 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x09, rs, 0)); +} + +// C.JR RS +static inline void asm_rv32_opcode_cjr(asm_rv32_t *state, mp_uint_t rs) { + // CR: 1000 ..... 00000 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x08, rs, 0)); +} + +// C.LI RD, IMMEDIATE +static inline void asm_rv32_opcode_cli(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CI: 010 . ..... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x02, rd, immediate)); +} + +// C.LUI RD, IMMEDIATE +static inline void asm_rv32_opcode_clui(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CI: 011 . ..... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x01, 0x03, rd, immediate >> 12)); +} + +// C.LW RD', OFFSET(RS') +static inline void asm_rv32_opcode_clw(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // CL: 010 ... ... .. ... 00 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CL(0x00, 0x02, rd, rs, offset)); +} + +// C.LWSP RD, OFFSET +static inline void asm_rv32_opcode_clwsp(asm_rv32_t *state, mp_uint_t rd, mp_uint_t offset) { + // CI: 010 . ..... ..... 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x02, 0x02, rd, ((offset & 0xC0) >> 6) | (offset & 0x3C))); +} + +// C.MV RD, RS +static inline void asm_rv32_opcode_cmv(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CR: 1000 ..... ..... 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CR(0x02, 0x08, rd, rs)); +} + +// C.NOP +static inline void asm_rv32_opcode_cnop(asm_rv32_t *state) { + // CI: 000 . 00000 ..... 01 + asm_rv32_emit_halfword_opcode(state, 0x0001); +} + +// C.OR RD', RS' +static inline void asm_rv32_opcode_cor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CA: 100011 ... 10 ... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CA(0x01, 0x23, 0x02, rd, rs)); +} + +// C.SLLI RD, IMMEDIATE +static inline void asm_rv32_opcode_cslli(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CI: 000 . ..... ..... 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CI(0x02, 0x00, rd, immediate)); +} + +// C.SRAI RD, IMMEDIATE +static inline void asm_rv32_opcode_csrai(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CB: 100 . 01 ... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x04, rd, + (((immediate & 0x20) << 2) | (immediate & 0x1F) | 0x20))); +} + +// C.SRLI RD, IMMEDIATE +static inline void asm_rv32_opcode_csrli(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // CB: 100 . 00 ... ..... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CB(0x01, 0x04, rd, + (((immediate & 0x20) << 2) | (immediate & 0x1F)))); +} + +// C.SUB RD', RS' +static inline void asm_rv32_opcode_csub(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CA: 100011 ... 00 ... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CA(0x01, 0x23, 0x00, rd, rs)); +} + +// C.SW RS1', OFFSET(RS2') +static inline void asm_rv32_opcode_csw(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_int_t offset) { + // CS: 110 ... ... .. ... 00 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CL(0x00, 0x06, rs1, rs2, offset)); +} + +// C.SWSP RS, OFFSET +static inline void asm_rv32_opcode_cswsp(asm_rv32_t *state, mp_uint_t rs, mp_uint_t offset) { + // CSS: 010 ...... ..... 10 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CSS(0x02, 0x06, rs, ((offset & 0xC0) >> 6) | (offset & 0x3C))); +} + +// C.XOR RD', RS' +static inline void asm_rv32_opcode_cxor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs) { + // CA: 100011 ... 01 ... 01 + asm_rv32_emit_halfword_opcode(state, RV32_ENCODE_TYPE_CA(0x01, 0x23, 0x01, rd, rs)); +} + +// CSRRC RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_csrrc(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 011 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x73, 0x03, rd, rs, immediate)); +} + +// CSRRS RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_csrrs(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 010 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x73, 0x02, rd, rs, immediate)); +} + +// CSRRW RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_csrrw(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 001 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x73, 0x01, rd, rs, immediate)); +} + +// CSRRCI RD, CSR, IMMEDIATE +static inline void asm_rv32_opcode_csrrci(asm_rv32_t *state, mp_uint_t rd, mp_uint_t csr, mp_int_t immediate) { + // CSRI: ............ ..... 111 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_CSRI(0x73, 0x07, rd, csr, immediate)); +} + +// CSRRSI RD, CSR, IMMEDIATE +static inline void asm_rv32_opcode_csrrsi(asm_rv32_t *state, mp_uint_t rd, mp_uint_t csr, mp_int_t immediate) { + // CSRI: ............ ..... 110 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_CSRI(0x73, 0x06, rd, csr, immediate)); +} + +// CSRRWI RD, CSR, IMMEDIATE +static inline void asm_rv32_opcode_csrrwi(asm_rv32_t *state, mp_uint_t rd, mp_uint_t csr, mp_int_t immediate) { + // CSRI: ............ ..... 101 ..... 1110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_CSRI(0x73, 0x05, rd, csr, immediate)); +} + +// DIV RD, RS1, RS2 +static inline void asm_rv32_opcode_div(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 100 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x04, 0x01, rd, rs1, rs2)); +} + +// DIVU RD, RS1, RS2 +static inline void asm_rv32_opcode_divu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 101 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x05, 0x01, rd, rs1, rs2)); +} + +// EBREAK +static inline void asm_rv32_opcode_ebreak(asm_rv32_t *state) { + // I: 000000000001 00000 000 00000 1110011 + asm_rv32_emit_word_opcode(state, 0x100073); +} + +// ECALL +static inline void asm_rv32_opcode_ecall(asm_rv32_t *state) { + // I: 000000000000 00000 000 00000 1110011 + asm_rv32_emit_word_opcode(state, 0x73); +} + +// JAL RD, OFFSET +static inline void asm_rv32_opcode_jal(asm_rv32_t *state, mp_uint_t rd, mp_int_t offset) { + // J: ......................... 1101111 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_J(0x6F, rd, offset)); +} + +// JALR RD, RS, OFFSET +static inline void asm_rv32_opcode_jalr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 000 ..... 1100111 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x67, 0x00, rd, rs, offset)); +} + +// LB RD, OFFSET(RS) +static inline void asm_rv32_opcode_lb(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 000 ..... 0000011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x00, rd, rs, offset)); +} + +// LBU RD, OFFSET(RS) +static inline void asm_rv32_opcode_lbu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 100 ..... 0000011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x04, rd, rs, offset)); +} + +// LH RD, OFFSET(RS) +static inline void asm_rv32_opcode_lh(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 001 ..... 0000011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x01, rd, rs, offset)); +} + +// LHU RD, OFFSET(RS) +static inline void asm_rv32_opcode_lhu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 101 ..... 0000011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x05, rd, rs, offset)); +} + +// LUI RD, IMMEDIATE +static inline void asm_rv32_opcode_lui(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate) { + // U: .................... ..... 0110111 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_U(0x37, rd, immediate)); +} + +// LW RD, OFFSET(RS) +static inline void asm_rv32_opcode_lw(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t offset) { + // I: ............ ..... 010 ..... 0000011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x03, 0x02, rd, rs, offset)); +} + +// MUL RD, RS1, RS2 +static inline void asm_rv32_opcode_mul(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 000 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x01, rd, rs1, rs2)); +} + +// MULH RD, RS1, RS2 +static inline void asm_rv32_opcode_mulh(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 001 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x01, 0x01, rd, rs1, rs2)); +} + +// MULHSU RD, RS1, RS2 +static inline void asm_rv32_opcode_mulhsu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 010 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x02, 0x01, rd, rs1, rs2)); +} + +// MULHU RD, RS1, RS2 +static inline void asm_rv32_opcode_mulhu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 011 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x03, 0x01, rd, rs1, rs2)); +} + +// OR RD, RS1, RS2 +static inline void asm_rv32_opcode_or(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 110 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x06, 0x00, rd, rs1, rs2)); +} + +// ORI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_ori(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 110 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x06, rd, rs, immediate)); +} + +// REM RD, RS1, RS2 +static inline void asm_rv32_opcode_rem(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 110 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x06, 0x01, rd, rs1, rs2)); +} + +// REMU RD, RS1, RS2 +static inline void asm_rv32_opcode_remu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000001 ..... ..... 111 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x07, 0x01, rd, rs1, rs2)); +} + +// SH1ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh1add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 010 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x02, 0x10, rd, rs1, rs2)); +} + +// SH2ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh2add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 100 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x04, 0x10, rd, rs1, rs2)); +} + +// SH3ADD RD, RS1, RS2 +static inline void asm_rv32_opcode_sh3add(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0010000 ..... ..... 110 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x06, 0x10, rd, rs1, rs2)); +} + +// SLL RD, RS1, RS2 +static inline void asm_rv32_opcode_sll(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 001 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x01, 0x00, rd, rs1, rs2)); +} + +// SLLI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_slli(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: 0000000..... ..... 001 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x01, rd, rs, immediate & 0x1F)); +} + +// SLT RD, RS1, RS2 +static inline void asm_rv32_opcode_slt(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 010 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x02, 0x00, rd, rs1, rs2)); +} + +// SLTI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_slti(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 010 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x02, rd, rs, immediate)); +} + +// SLTIU RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_sltiu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 011 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x03, rd, rs, immediate)); +} + +// SLTU RD, RS1, RS2 +static inline void asm_rv32_opcode_sltu(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 011 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x03, 0x00, rd, rs1, rs2)); +} + +// SRA RD, RS1, RS2 +static inline void asm_rv32_opcode_sra(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0100000 ..... ..... 101 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x05, 0x20, rd, rs1, rs2)); +} + +// SRAI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_srai(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: 0100000..... ..... 101 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x05, rd, rs, ((immediate & 0x1F) | 0x400))); +} + +// SRL RD, RS1, RS2 +static inline void asm_rv32_opcode_srl(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 101 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x05, 0x00, rd, rs1, rs2)); +} + +// SRLI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_srli(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: 0000000..... ..... 101 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x05, rd, rs, immediate & 0x1F)); +} + +// SUB RD, RS1, RS2 +static inline void asm_rv32_opcode_sub(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0100000 ..... ..... 000 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x00, 0x20, rd, rs1, rs2)); +} + +// SB RS2, OFFSET(RS1) +static inline void asm_rv32_opcode_sb(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) { + // S: ....... ..... ..... 000 ..... 0100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x00, rs1, rs2, offset)); +} + +// SH RS2, OFFSET(RS1) +static inline void asm_rv32_opcode_sh(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) { + // S: ....... ..... ..... 001 ..... 0100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x01, rs1, rs2, offset)); +} + +// SW RS2, OFFSET(RS1) +static inline void asm_rv32_opcode_sw(asm_rv32_t *state, mp_uint_t rs2, mp_uint_t rs1, mp_int_t offset) { + // S: ....... ..... ..... 010 ..... 0100011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_S(0x23, 0x02, rs1, rs2, offset)); +} + +// XOR RD, RS1, RS2 +static inline void asm_rv32_opcode_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2) { + // R: 0000000 ..... ..... 100 ..... 0110011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_R(0x33, 0x04, 0x00, rd, rs1, rs2)); +} + +// XORI RD, RS, IMMEDIATE +static inline void asm_rv32_opcode_xori(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, mp_int_t immediate) { + // I: ............ ..... 100 ..... 0010011 + asm_rv32_emit_word_opcode(state, RV32_ENCODE_TYPE_I(0x13, 0x04, rd, rs, immediate)); +} + +#define MICROPY_RV32_EXTENSIONS \ + (MICROPY_EMIT_RV32_ZBA ? RV32_EXT_ZBA : 0) + +static inline uint8_t asm_rv32_allowed_extensions(void) { + uint8_t extensions = MICROPY_RV32_EXTENSIONS; + #if MICROPY_DYNAMIC_COMPILER + if (mp_dynamic_compiler.backend_options != NULL) { + extensions |= ((asm_rv32_backend_options_t *)mp_dynamic_compiler.backend_options)->allowed_extensions; + } + #endif + return extensions; +} + +#define ASM_WORD_SIZE (4) +#define ASM_HALFWORD_SIZE (2) + +#define REG_RET ASM_RV32_REG_A0 +#define REG_ARG_1 ASM_RV32_REG_A0 +#define REG_ARG_2 ASM_RV32_REG_A1 +#define REG_ARG_3 ASM_RV32_REG_A2 +#define REG_ARG_4 ASM_RV32_REG_A3 +#define REG_TEMP0 ASM_RV32_REG_T1 +#define REG_TEMP1 ASM_RV32_REG_T2 +#define REG_TEMP2 ASM_RV32_REG_T3 +#define REG_FUN_TABLE ASM_RV32_REG_S1 +#define REG_LOCAL_1 ASM_RV32_REG_S3 +#define REG_LOCAL_2 ASM_RV32_REG_S4 +#define REG_LOCAL_3 ASM_RV32_REG_S5 +#define REG_ZERO ASM_RV32_REG_ZERO + +void asm_rv32_meta_comparison_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd); +void asm_rv32_meta_comparison_ne(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd); +void asm_rv32_meta_comparison_lt(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison); +void asm_rv32_meta_comparison_le(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t rd, bool unsigned_comparison); + +void asm_rv32_emit_optimised_load_immediate(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate); +void asm_rv32_emit_load_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size); +void asm_rv32_emit_store_reg_reg_reg(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t operation_size); + +#ifdef GENERIC_ASM_API + +void asm_rv32_emit_call_ind(asm_rv32_t *state, mp_uint_t index); +void asm_rv32_emit_jump(asm_rv32_t *state, mp_uint_t label); +void asm_rv32_emit_jump_if_reg_eq(asm_rv32_t *state, mp_uint_t rs1, mp_uint_t rs2, mp_uint_t label); +void asm_rv32_emit_jump_if_reg_nonzero(asm_rv32_t *state, mp_uint_t rs, mp_uint_t label); +void asm_rv32_emit_load_reg_reg_offset(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs, int32_t offset, mp_uint_t operation_size); +void asm_rv32_emit_mov_local_reg(asm_rv32_t *state, mp_uint_t local, mp_uint_t rs); +void asm_rv32_emit_mov_reg_local_addr(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local); +void asm_rv32_emit_mov_reg_local(asm_rv32_t *state, mp_uint_t rd, mp_uint_t local); +void asm_rv32_emit_mov_reg_pcrel(asm_rv32_t *state, mp_uint_t rd, mp_uint_t label); +void asm_rv32_emit_optimised_xor(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs); +void asm_rv32_emit_store_reg_reg_offset(asm_rv32_t *state, mp_uint_t source, mp_uint_t base, int32_t offset, mp_uint_t operation_size); + +#define ASM_T asm_rv32_t +#define ASM_ENTRY(state, labels, name) asm_rv32_entry(state, labels) +#define ASM_EXIT(state) asm_rv32_exit(state) +#define ASM_END_PASS(state) asm_rv32_end_pass(state) + +#define ASM_ADD_REG_REG(state, rd, rs) asm_rv32_opcode_cadd(state, rd, rs) +#define ASM_AND_REG_REG(state, rd, rs) asm_rv32_opcode_and(state, rd, rs, rd) +#define ASM_ASR_REG_REG(state, rd, rs) asm_rv32_opcode_sra(state, rd, rd, rs) +#define ASM_CALL_IND(state, index) asm_rv32_emit_call_ind(state, index) +#define ASM_JUMP(state, label) asm_rv32_emit_jump(state, label) +#define ASM_JUMP_IF_REG_EQ(state, rs1, rs2, label) asm_rv32_emit_jump_if_reg_eq(state, rs1, rs2, label) +#define ASM_JUMP_IF_REG_NONZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_nonzero(state, rs, label) +#define ASM_JUMP_IF_REG_ZERO(state, rs, label, bool_test) asm_rv32_emit_jump_if_reg_eq(state, rs, ASM_RV32_REG_ZERO, label) +#define ASM_JUMP_REG(state, rs) asm_rv32_opcode_cjr(state, rs) +#define ASM_LOAD_REG_REG_OFFSET(state, rd, rs, offset) ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, offset) +#define ASM_LOAD8_REG_REG(state, rd, rs) ASM_LOAD8_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD16_REG_REG(state, rd, rs) ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD32_REG_REG(state, rd, rs) ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, 0) +#define ASM_LOAD8_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 0) +#define ASM_LOAD16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 1) +#define ASM_LOAD32_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_load_reg_reg_offset(state, rd, rs, offset, 2) +#define ASM_LSL_REG_REG(state, rd, rs) asm_rv32_opcode_sll(state, rd, rd, rs) +#define ASM_LSR_REG_REG(state, rd, rs) asm_rv32_opcode_srl(state, rd, rd, rs) +#define ASM_MOV_LOCAL_REG(state, local, rs) asm_rv32_emit_mov_local_reg(state, local, rs) +#define ASM_MOV_REG_IMM(state, rd, imm) asm_rv32_emit_optimised_load_immediate(state, rd, imm) +#define ASM_MOV_REG_LOCAL_ADDR(state, rd, local) asm_rv32_emit_mov_reg_local_addr(state, rd, local) +#define ASM_MOV_REG_LOCAL(state, rd, local) asm_rv32_emit_mov_reg_local(state, rd, local) +#define ASM_MOV_REG_PCREL(state, rd, label) asm_rv32_emit_mov_reg_pcrel(state, rd, label) +#define ASM_MOV_REG_REG(state, rd, rs) asm_rv32_opcode_cmv(state, rd, rs) +#define ASM_MUL_REG_REG(state, rd, rs) asm_rv32_opcode_mul(state, rd, rd, rs) +#define ASM_NEG_REG(state, rd) asm_rv32_opcode_sub(state, rd, ASM_RV32_REG_ZERO, rd) +#define ASM_NOT_REG(state, rd) asm_rv32_opcode_xori(state, rd, rd, -1) +#define ASM_OR_REG_REG(state, rd, rs) asm_rv32_opcode_or(state, rd, rd, rs) +#define ASM_STORE_REG_REG_OFFSET(state, rd, rs, offset) ASM_STORE32_REG_REG_OFFSET(state, rd, rs, offset) +#define ASM_STORE8_REG_REG(state, rs1, rs2) ASM_STORE8_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE16_REG_REG(state, rs1, rs2) ASM_STORE16_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE32_REG_REG(state, rs1, rs2) ASM_STORE32_REG_REG_OFFSET(state, rs1, rs2, 0) +#define ASM_STORE8_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 0) +#define ASM_STORE16_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 1) +#define ASM_STORE32_REG_REG_OFFSET(state, rd, rs, offset) asm_rv32_emit_store_reg_reg_offset(state, rd, rs, offset, 2) +#define ASM_SUB_REG_REG(state, rd, rs) asm_rv32_opcode_sub(state, rd, rd, rs) +#define ASM_XOR_REG_REG(state, rd, rs) asm_rv32_emit_optimised_xor(state, rd, rs) +#define ASM_CLR_REG(state, rd) +#define ASM_LOAD8_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 0) +#define ASM_LOAD16_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 1) +#define ASM_LOAD32_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_load_reg_reg_reg(state, rd, rs1, rs2, 2) +#define ASM_STORE8_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 0) +#define ASM_STORE16_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 1) +#define ASM_STORE32_REG_REG_REG(state, rd, rs1, rs2) asm_rv32_emit_store_reg_reg_reg(state, rd, rs1, rs2, 2) + +#endif + +#endif // MICROPY_INCLUDED_PY_ASMRV32_H diff --git a/py/asmthumb.c b/py/asmthumb.c index 395134028aaa9..58cc7aea88085 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -35,25 +35,8 @@ #include "py/mpstate.h" #include "py/asmthumb.h" +#include "py/misc.h" -#ifdef _MSC_VER -#include - -static uint32_t mp_clz(uint32_t x) { - unsigned long lz = 0; - return _BitScanReverse(&lz, x) ? (sizeof(x) * 8 - 1) - lz : 0; -} - -static uint32_t mp_ctz(uint32_t x) { - unsigned long tz = 0; - return _BitScanForward(&tz, x) ? tz : 0; -} -#else -#define mp_clz(x) __builtin_clz(x) -#define mp_ctz(x) __builtin_ctz(x) -#endif - -#define UNSIGNED_FIT5(x) ((uint32_t)(x) < 32) #define UNSIGNED_FIT7(x) ((uint32_t)(x) < 128) #define UNSIGNED_FIT8(x) (((x) & 0xffffff00) == 0) #define UNSIGNED_FIT16(x) (((x) & 0xffff0000) == 0) @@ -68,18 +51,12 @@ static uint32_t mp_ctz(uint32_t x) { #define OP_SUB_W_RRI_HI(reg_src) (0xf2a0 | (reg_src)) #define OP_SUB_W_RRI_LO(reg_dest, imm11) ((imm11 << 4 & 0x7000) | reg_dest << 8 | (imm11 & 0xff)) -#define OP_LDR_W_HI(reg_base) (0xf8d0 | (reg_base)) -#define OP_LDR_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) - -#define OP_LDRH_W_HI(reg_base) (0xf8b0 | (reg_base)) -#define OP_LDRH_W_LO(reg_dest, imm12) ((reg_dest) << 12 | (imm12)) - static inline byte *asm_thumb_get_cur_to_write_bytes(asm_thumb_t *as, int n) { return mp_asm_base_get_cur_to_write_bytes(&as->base, n); } /* -STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) { +static void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 1); c[0] = b1; } @@ -91,7 +68,7 @@ STATIC void asm_thumb_write_byte_1(asm_thumb_t *as, byte b1) { #define IMM32_L2(x) (((x) >> 16) & 0xff) #define IMM32_L3(x) (((x) >> 24) & 0xff) -STATIC void asm_thumb_write_word32(asm_thumb_t *as, int w32) { +static void asm_thumb_write_word32(asm_thumb_t *as, int w32) { byte *c = asm_thumb_get_cur_to_write_bytes(as, 4); c[0] = IMM32_L0(w32); c[1] = IMM32_L1(w32); @@ -216,7 +193,7 @@ void asm_thumb_exit(asm_thumb_t *as) { asm_thumb_op16(as, OP_POP_RLIST_PC(as->push_reglist)); } -STATIC mp_uint_t get_label_dest(asm_thumb_t *as, uint label) { +static mp_uint_t get_label_dest(asm_thumb_t *as, uint label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } @@ -290,9 +267,8 @@ bool asm_thumb_b_n_label(asm_thumb_t *as, uint label) { #define OP_BCC_N(cond, byte_offset) (0xd000 | ((cond) << 8) | (((byte_offset) >> 1) & 0x00ff)) -// all these bit-arithmetic operations need coverage testing! -#define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 14) & 0x003f)) -#define OP_BCC_W_LO(byte_offset) (0x8000 | ((byte_offset) & 0x2000) | (((byte_offset) >> 1) & 0x0fff)) +#define OP_BCC_W_HI(cond, byte_offset) (0xf000 | ((cond) << 6) | (((byte_offset) >> 10) & 0x0400) | (((byte_offset) >> 12) & 0x003f)) +#define OP_BCC_W_LO(byte_offset) (0x8000 | (((byte_offset) >> 5) & 0x2000) | (((byte_offset) >> 8) & 0x0800) | (((byte_offset) >> 1) & 0x07ff)) bool asm_thumb_bcc_nw_label(asm_thumb_t *as, int cond, uint label, bool wide) { mp_uint_t dest = get_label_dest(as, label); @@ -448,11 +424,6 @@ void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label) { asm_thumb_add_reg_reg(as, rlo_dest, ASM_THUMB_REG_R15); // 2 bytes } -// ARMv7-M only -static inline void asm_thumb_ldr_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { - asm_thumb_op32(as, OP_LDR_W_HI(reg_base), OP_LDR_W_LO(reg_dest, word_offset * 4)); -} - // emits code for: reg_dest = reg_base + offset << offset_shift static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint offset_shift) { if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8) { @@ -466,12 +437,12 @@ static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint re asm_thumb_lsl_rlo_rlo_i5(as, reg_dest, reg_dest, offset_shift); asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); } else if (reg_dest != reg_base) { - asm_thumb_mov_rlo_i16(as, reg_dest, offset << offset_shift); - asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_dest); + asm_thumb_mov_reg_i32_optimised(as, reg_dest, offset << offset_shift); + asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_base); } else { uint reg_other = reg_dest ^ 7; asm_thumb_op16(as, OP_PUSH_RLIST((1 << reg_other))); - asm_thumb_mov_rlo_i16(as, reg_other, offset << offset_shift); + asm_thumb_mov_reg_i32_optimised(as, reg_other, offset << offset_shift); asm_thumb_add_rlo_rlo_rlo(as, reg_dest, reg_dest, reg_other); asm_thumb_op16(as, OP_POP_RLIST((1 << reg_other))); } @@ -480,30 +451,50 @@ static void asm_thumb_add_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint re } } -void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset) { - if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(word_offset)) { - asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_base, word_offset); - } else if (asm_thumb_allow_armv7m(as)) { - asm_thumb_ldr_reg_reg_i12(as, reg_dest, reg_base, word_offset); +#define OP_LDR_STR_W_HI(operation_size, reg) ((0xf880 | (operation_size) << 5) | (reg)) +#define OP_LDR_STR_W_LO(reg, imm12) (((reg) << 12) | (imm12)) + +#define OP_LDR 0x01 +#define OP_STR 0x00 + +#define OP_LDR_W 0x10 +#define OP_STR_W 0x00 + +static const uint8_t OP_LDR_STR_TABLE[3] = { + 0x0E, 0x10, 0x0C +}; + +void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size out of range."); + + if (MP_FIT_UNSIGNED(5, offset) && (reg_dest < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) { + // Can use T1 encoding + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (offset << 6) | (reg_base << 3) | reg_dest); + } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) { + // Can use T3 encoding + asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_LDR_W), OP_LDR_STR_W_LO(reg_dest, (offset << operation_size))); } else { - asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, word_offset - 31, 2); - asm_thumb_ldr_rlo_rlo_i5(as, reg_dest, reg_dest, 31); + // Must use the generic sequence + asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, offset - 31, operation_size); + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_LDR) << 11) | (31 << 6) | (reg_dest << 3) | (reg_dest)); } } -// ARMv7-M only -static inline void asm_thumb_ldrh_reg_reg_i12(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { - asm_thumb_op32(as, OP_LDRH_W_HI(reg_base), OP_LDRH_W_LO(reg_dest, uint16_offset * 2)); -} +void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size out of range."); -void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset) { - if (reg_dest < ASM_THUMB_REG_R8 && reg_base < ASM_THUMB_REG_R8 && UNSIGNED_FIT5(uint16_offset)) { - asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_base, uint16_offset); - } else if (asm_thumb_allow_armv7m(as)) { - asm_thumb_ldrh_reg_reg_i12(as, reg_dest, reg_base, uint16_offset); + if (MP_FIT_UNSIGNED(5, offset) && (reg_src < ASM_THUMB_REG_R8) && (reg_base < ASM_THUMB_REG_R8)) { + // Can use T1 encoding + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (offset << 6) | (reg_base << 3) | reg_src); + } else if (asm_thumb_allow_armv7m(as) && MP_FIT_UNSIGNED(12, offset << operation_size)) { + // Can use T3 encoding + asm_thumb_op32(as, (OP_LDR_STR_W_HI(operation_size, reg_base) | OP_STR_W), OP_LDR_STR_W_LO(reg_src, (offset << operation_size))); } else { - asm_thumb_add_reg_reg_offset(as, reg_dest, reg_base, uint16_offset - 31, 1); - asm_thumb_ldrh_rlo_rlo_i5(as, reg_dest, reg_dest, 31); + // Must use the generic sequence + asm_thumb_op16(as, OP_PUSH_RLIST(1 << reg_base)); + asm_thumb_add_reg_reg_offset(as, reg_base, reg_base, offset - 31, operation_size); + asm_thumb_op16(as, ((OP_LDR_STR_TABLE[operation_size] | OP_STR) << 11) | (31 << 6) | (reg_base << 3) | reg_src); + asm_thumb_op16(as, OP_POP_RLIST(1 << reg_base)); } } @@ -511,6 +502,7 @@ void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint r #define OP_BW_HI(byte_offset) (0xf000 | (((byte_offset) >> 12) & 0x07ff)) #define OP_BW_LO(byte_offset) (0xb800 | (((byte_offset) >> 1) & 0x07ff)) +// In Thumb1 mode, this may clobber r1. void asm_thumb_b_label(asm_thumb_t *as, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; @@ -530,19 +522,40 @@ void asm_thumb_b_label(asm_thumb_t *as, uint label) { if (asm_thumb_allow_armv7m(as)) { asm_thumb_op32(as, OP_BW_HI(rel), OP_BW_LO(rel)); } else { + // this code path has to be the same instruction size irrespective of the value of rel + bool need_align = as->base.code_offset & 2u; if (SIGNED_FIT12(rel)) { - // this code path has to be the same number of instructions irrespective of rel asm_thumb_op16(as, OP_B_N(rel)); - } else { asm_thumb_op16(as, ASM_THUMB_OP_NOP); - if (dest != (mp_uint_t)-1) { - // we have an actual branch > 12 bits; this is not handled yet - mp_raise_NotImplementedError(MP_ERROR_TEXT("native method too big")); + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + if (need_align) { + asm_thumb_op16(as, ASM_THUMB_OP_NOP); } + } else { + // do a large jump using: + // (nop) + // ldr r1, [pc, _data] + // add pc, r1 + // _data: .word rel + // + // note: can't use r0 as a temporary because native code can have the return value + // in that register and use a large jump to get to the exit point of the function + + rel -= 2; // account for the "ldr r1, [pc, _data]" + if (need_align) { + asm_thumb_op16(as, ASM_THUMB_OP_NOP); + rel -= 2; // account for this nop + } + asm_thumb_ldr_rlo_pcrel_i8(as, ASM_THUMB_REG_R1, 0); + asm_thumb_add_reg_reg(as, ASM_THUMB_REG_R15, ASM_THUMB_REG_R1); + asm_thumb_op16(as, rel & 0xffff); + asm_thumb_op16(as, rel >> 16); } } } +// In Thumb1 mode, this may clobber r1. void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { mp_uint_t dest = get_label_dest(as, label); mp_int_t rel = dest - as->base.code_offset; @@ -563,8 +576,15 @@ void asm_thumb_bcc_label(asm_thumb_t *as, int cond, uint label) { asm_thumb_op32(as, OP_BCC_W_HI(cond, rel), OP_BCC_W_LO(rel)); } else { // reverse the sense of the branch to jump over a longer branch - asm_thumb_op16(as, OP_BCC_N(cond ^ 1, 0)); + size_t code_offset_start = as->base.code_offset; + byte *c = asm_thumb_get_cur_to_write_bytes(as, 2); asm_thumb_b_label(as, label); + size_t bytes_to_skip = as->base.code_offset - code_offset_start; + uint16_t op = OP_BCC_N(cond ^ 1, bytes_to_skip - 4); + if (c != NULL) { + c[0] = op; + c[1] = op >> 8; + } } } @@ -585,7 +605,7 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel) { void asm_thumb_bl_ind(asm_thumb_t *as, uint fun_id, uint reg_temp) { // Load ptr to function from table, indexed by fun_id, then call it - asm_thumb_ldr_reg_reg_i12_optimised(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id); + asm_thumb_load_reg_reg_offset(as, reg_temp, ASM_THUMB_REG_FUN_TABLE, fun_id, 2); asm_thumb_op16(as, OP_BLX(reg_temp)); } diff --git a/py/asmthumb.h b/py/asmthumb.h index 61b4928d8d9c2..cb786694f0b78 100644 --- a/py/asmthumb.h +++ b/py/asmthumb.h @@ -251,6 +251,50 @@ static inline void asm_thumb_bx_reg(asm_thumb_t *as, uint r_src) { asm_thumb_format_5(as, ASM_THUMB_FORMAT_5_BX, 0, r_src); } +// FORMAT 7: load/store with register offset +// FORMAT 8: load/store sign-extended byte/halfword + +#define ASM_THUMB_FORMAT_7_LDR (0x5800) +#define ASM_THUMB_FORMAT_7_STR (0x5000) +#define ASM_THUMB_FORMAT_7_WORD_TRANSFER (0x0000) +#define ASM_THUMB_FORMAT_7_BYTE_TRANSFER (0x0400) +#define ASM_THUMB_FORMAT_8_LDRH (0x5A00) +#define ASM_THUMB_FORMAT_8_STRH (0x5200) + +#define ASM_THUMB_FORMAT_7_8_ENCODE(op, rlo_dest, rlo_base, rlo_index) \ + ((op) | ((rlo_index) << 6) | ((rlo_base) << 3) | ((rlo_dest))) + +static inline void asm_thumb_format_7_8(asm_thumb_t *as, uint op, uint rlo_dest, uint rlo_base, uint rlo_index) { + assert(rlo_dest < ASM_THUMB_REG_R8); + assert(rlo_base < ASM_THUMB_REG_R8); + assert(rlo_index < ASM_THUMB_REG_R8); + asm_thumb_op16(as, ASM_THUMB_FORMAT_7_8_ENCODE(op, rlo_dest, rlo_base, rlo_index)); +} + +static inline void asm_thumb_ldrb_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_LDR | ASM_THUMB_FORMAT_7_BYTE_TRANSFER, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_ldrh_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_8_LDRH, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_ldr_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_LDR | ASM_THUMB_FORMAT_7_WORD_TRANSFER, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_strb_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_STR | ASM_THUMB_FORMAT_7_BYTE_TRANSFER, rlo_src, rlo_base, rlo_index); +} + +static inline void asm_thumb_strh_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_8_STRH, rlo_dest, rlo_base, rlo_index); +} + +static inline void asm_thumb_str_rlo_rlo_rlo(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint rlo_index) { + asm_thumb_format_7_8(as, ASM_THUMB_FORMAT_7_STR | ASM_THUMB_FORMAT_7_WORD_TRANSFER, rlo_src, rlo_base, rlo_index); +} + // FORMAT 9: load/store with immediate offset // For word transfers the offset must be aligned, and >>2 @@ -273,24 +317,6 @@ static inline void asm_thumb_format_9_10(asm_thumb_t *as, uint op, uint rlo_dest asm_thumb_op16(as, ASM_THUMB_FORMAT_9_10_ENCODE(op, rlo_dest, rlo_base, offset)); } -static inline void asm_thumb_str_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint word_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_src, rlo_base, word_offset); -} -static inline void asm_thumb_strb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint byte_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_STR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_src, rlo_base, byte_offset); -} -static inline void asm_thumb_strh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_src, uint rlo_base, uint uint16_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_STRH, rlo_src, rlo_base, uint16_offset); -} -static inline void asm_thumb_ldr_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint word_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER, rlo_dest, rlo_base, word_offset); -} -static inline void asm_thumb_ldrb_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint byte_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER, rlo_dest, rlo_base, byte_offset); -} -static inline void asm_thumb_ldrh_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_base, uint uint16_offset) { - asm_thumb_format_9_10(as, ASM_THUMB_FORMAT_10_LDRH, rlo_dest, rlo_base, uint16_offset); -} static inline void asm_thumb_lsl_rlo_rlo_i5(asm_thumb_t *as, uint rlo_dest, uint rlo_src, uint shift) { asm_thumb_format_1(as, ASM_THUMB_FORMAT_1_LSL, rlo_dest, rlo_src, shift); } @@ -338,8 +364,10 @@ void asm_thumb_mov_reg_local(asm_thumb_t *as, uint rlo_dest, int local_num); // void asm_thumb_mov_reg_local_addr(asm_thumb_t *as, uint rlo_dest, int local_num); // convenience void asm_thumb_mov_reg_pcrel(asm_thumb_t *as, uint rlo_dest, uint label); -void asm_thumb_ldr_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint word_offset); // convenience -void asm_thumb_ldrh_reg_reg_i12_optimised(asm_thumb_t *as, uint reg_dest, uint reg_base, uint uint16_offset); // convenience +// Generate optimised load dest, [src, #offset] sequence +void asm_thumb_load_reg_reg_offset(asm_thumb_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size); +// Generate optimised store src, [dest, #offset] sequence +void asm_thumb_store_reg_reg_offset(asm_thumb_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size); void asm_thumb_b_label(asm_thumb_t *as, uint label); // convenience: picks narrow or wide branch void asm_thumb_bcc_label(asm_thumb_t *as, int cc, uint label); // convenience: picks narrow or wide branch @@ -376,12 +404,12 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel); #define REG_FUN_TABLE ASM_THUMB_REG_FUN_TABLE -#define ASM_T asm_thumb_t -#define ASM_END_PASS asm_thumb_end_pass -#define ASM_ENTRY asm_thumb_entry -#define ASM_EXIT asm_thumb_exit +#define ASM_T asm_thumb_t +#define ASM_END_PASS asm_thumb_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_thumb_entry((as), (num_locals)) +#define ASM_EXIT asm_thumb_exit -#define ASM_JUMP asm_thumb_b_label +#define ASM_JUMP asm_thumb_b_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ asm_thumb_cmp_rlo_i8(as, reg, 0); \ @@ -407,6 +435,8 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel); #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_thumb_mov_reg_local_addr((as), (reg_dest), (local_num)) #define ASM_MOV_REG_PCREL(as, rlo_dest, label) asm_thumb_mov_reg_pcrel((as), (rlo_dest), (label)) +#define ASM_NOT_REG(as, reg_dest) asm_thumb_mvn_rlo_rlo((as), (reg_dest), (reg_dest)) +#define ASM_NEG_REG(as, reg_dest) asm_thumb_neg_rlo_rlo((as), (reg_dest), (reg_dest)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSL, (reg_dest), (reg_shift)) #define ASM_LSR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_LSR, (reg_dest), (reg_shift)) #define ASM_ASR_REG_REG(as, reg_dest, reg_shift) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_ASR, (reg_dest), (reg_shift)) @@ -417,18 +447,44 @@ void asm_thumb_b_rel12(asm_thumb_t *as, int rel); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_thumb_sub_rlo_rlo_rlo((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_thumb_format_4((as), ASM_THUMB_FORMAT_4_MUL, (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_ldr_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrb_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_thumb_ldrh_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_thumb_ldrh_reg_reg_i12_optimised((as), (reg_dest), (reg_base), (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_thumb_ldr_rlo_rlo_i5((as), (reg_dest), (reg_base), 0) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_thumb_strb_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_thumb_strh_rlo_rlo_i5((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_thumb_str_rlo_rlo_i5((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset), 0) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (halfword_offset), 1) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_thumb_load_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (byte_offset), 0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, halfword_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (halfword_offset), 1) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_thumb_store_reg_reg_offset((as), (reg_src), (reg_base), (word_offset), 2) + +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) asm_thumb_ldrb_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \ + asm_thumb_ldrh_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \ + } while (0) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \ + asm_thumb_ldr_rlo_rlo_rlo((as), (reg_dest), (reg_base), (reg_index)); \ + } while (0) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) asm_thumb_strb_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 1); \ + asm_thumb_strh_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \ + } while (0) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_thumb_lsl_rlo_rlo_i5((as), (reg_index), (reg_index), 2); \ + asm_thumb_str_rlo_rlo_rlo((as), (reg_val), (reg_base), (reg_index)); \ + } while (0) #endif // GENERIC_ASM_API diff --git a/py/asmx64.c b/py/asmx64.c index 5c923a523ca54..d9f33cfb2ad7e 100644 --- a/py/asmx64.c +++ b/py/asmx64.c @@ -54,6 +54,8 @@ #define OPCODE_MOVZX_RM8_TO_R64 (0xb6) /* 0x0f 0xb6/r */ #define OPCODE_MOVZX_RM16_TO_R64 (0xb7) /* 0x0f 0xb7/r */ #define OPCODE_LEA_MEM_TO_R64 (0x8d) /* /r */ +#define OPCODE_NOT_RM64 (0xf7) /* /2 */ +#define OPCODE_NEG_RM64 (0xf7) /* /3 */ #define OPCODE_AND_R64_TO_RM64 (0x21) /* /r */ #define OPCODE_OR_R64_TO_RM64 (0x09) /* /r */ #define OPCODE_XOR_R64_TO_RM64 (0x31) /* /r */ @@ -123,14 +125,14 @@ static inline byte *asm_x64_get_cur_to_write_bytes(asm_x64_t *as, int n) { return mp_asm_base_get_cur_to_write_bytes(&as->base, n); } -STATIC void asm_x64_write_byte_1(asm_x64_t *as, byte b1) { +static void asm_x64_write_byte_1(asm_x64_t *as, byte b1) { byte *c = asm_x64_get_cur_to_write_bytes(as, 1); if (c != NULL) { c[0] = b1; } } -STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) { +static void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) { byte *c = asm_x64_get_cur_to_write_bytes(as, 2); if (c != NULL) { c[0] = b1; @@ -138,7 +140,7 @@ STATIC void asm_x64_write_byte_2(asm_x64_t *as, byte b1, byte b2) { } } -STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) { +static void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) { byte *c = asm_x64_get_cur_to_write_bytes(as, 3); if (c != NULL) { c[0] = b1; @@ -147,7 +149,7 @@ STATIC void asm_x64_write_byte_3(asm_x64_t *as, byte b1, byte b2, byte b3) { } } -STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) { +static void asm_x64_write_word32(asm_x64_t *as, int w32) { byte *c = asm_x64_get_cur_to_write_bytes(as, 4); if (c != NULL) { c[0] = IMM32_L0(w32); @@ -157,7 +159,7 @@ STATIC void asm_x64_write_word32(asm_x64_t *as, int w32) { } } -STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) { +static void asm_x64_write_word64(asm_x64_t *as, int64_t w64) { byte *c = asm_x64_get_cur_to_write_bytes(as, 8); if (c != NULL) { c[0] = IMM32_L0(w64); @@ -172,7 +174,7 @@ STATIC void asm_x64_write_word64(asm_x64_t *as, int64_t w64) { } /* unused -STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) { +static void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) { byte* c; assert(offset + 4 <= as->code_size); c = as->code_base + offset; @@ -183,7 +185,7 @@ STATIC void asm_x64_write_word32_to(asm_x64_t *as, int offset, int w32) { } */ -STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) { +static void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int disp_offset) { uint8_t rm_disp; if (disp_offset == 0 && (disp_r64 & 7) != ASM_X64_REG_RBP) { rm_disp = MODRM_RM_DISP0; @@ -204,7 +206,7 @@ STATIC void asm_x64_write_r64_disp(asm_x64_t *as, int r64, int disp_r64, int dis } } -STATIC void asm_x64_generic_r64_r64(asm_x64_t *as, int dest_r64, int src_r64, int op) { +static void asm_x64_generic_r64_r64(asm_x64_t *as, int dest_r64, int src_r64, int op) { asm_x64_write_byte_3(as, REX_PREFIX | REX_W | REX_R_FROM_R64(src_r64) | REX_B_FROM_R64(dest_r64), op, MODRM_R64(src_r64) | MODRM_RM_REG | MODRM_RM_R64(dest_r64)); } @@ -243,7 +245,7 @@ void asm_x64_pop_r64(asm_x64_t *as, int dest_r64) { } } -STATIC void asm_x64_ret(asm_x64_t *as) { +static void asm_x64_ret(asm_x64_t *as) { asm_x64_write_byte_1(as, OPCODE_RET); } @@ -317,7 +319,7 @@ void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); } -STATIC void asm_x64_lea_disp_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { +static void asm_x64_lea_disp_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64) { // use REX prefix for 64 bit operation asm_x64_write_byte_2(as, REX_PREFIX | REX_W | REX_R_FROM_R64(dest_r64) | REX_B_FROM_R64(src_r64), OPCODE_LEA_MEM_TO_R64); asm_x64_write_r64_disp(as, dest_r64, src_r64, src_disp); @@ -362,6 +364,14 @@ void asm_x64_mov_i64_to_r64_optimised(asm_x64_t *as, int64_t src_i64, int dest_r } } +void asm_x64_not_r64(asm_x64_t *as, int dest_r64) { + asm_x64_generic_r64_r64(as, dest_r64, 2, OPCODE_NOT_RM64); +} + +void asm_x64_neg_r64(asm_x64_t *as, int dest_r64) { + asm_x64_generic_r64_r64(as, dest_r64, 3, OPCODE_NEG_RM64); +} + void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64) { asm_x64_generic_r64_r64(as, dest_r64, src_r64, OPCODE_AND_R64_TO_RM64); } @@ -414,7 +424,7 @@ void asm_x64_sub_i32_from_r32(asm_x64_t *as, int src_i32, int dest_r32) { } */ -STATIC void asm_x64_sub_r64_i32(asm_x64_t *as, int dest_r64, int src_i32) { +static void asm_x64_sub_r64_i32(asm_x64_t *as, int dest_r64, int src_i32) { assert(dest_r64 < 8); if (SIGNED_FIT8(src_i32)) { // use REX prefix for 64 bit operation @@ -480,7 +490,7 @@ void asm_x64_jmp_reg(asm_x64_t *as, int src_r64) { asm_x64_write_byte_2(as, OPCODE_JMP_RM64, MODRM_R64(4) | MODRM_RM_REG | MODRM_RM_R64(src_r64)); } -STATIC mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) { +static mp_uint_t get_label_dest(asm_x64_t *as, mp_uint_t label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } @@ -560,7 +570,7 @@ void asm_x64_exit(asm_x64_t *as) { // ^ ^ // | low address | high address in RAM // -STATIC int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) { +static int asm_x64_local_offset_from_rsp(asm_x64_t *as, int local_num) { (void)as; // Stack is full descending, RSP points to local0 return local_num * WORD_SIZE; diff --git a/py/asmx64.h b/py/asmx64.h index 2d4bf8d33ced9..1e8cb0c905f2b 100644 --- a/py/asmx64.h +++ b/py/asmx64.h @@ -97,6 +97,8 @@ void asm_x64_mov_mem8_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int des void asm_x64_mov_mem16_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_mov_mem32_to_r64zx(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); void asm_x64_mov_mem64_to_r64(asm_x64_t *as, int src_r64, int src_disp, int dest_r64); +void asm_x64_not_r64(asm_x64_t *as, int dest_r64); +void asm_x64_neg_r64(asm_x64_t *as, int dest_r64); void asm_x64_and_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); void asm_x64_or_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); void asm_x64_xor_r64_r64(asm_x64_t *as, int dest_r64, int src_r64); @@ -153,12 +155,12 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32); // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X64_REG_FUN_TABLE -#define ASM_T asm_x64_t -#define ASM_END_PASS asm_x64_end_pass -#define ASM_ENTRY asm_x64_entry -#define ASM_EXIT asm_x64_exit +#define ASM_T asm_x64_t +#define ASM_END_PASS asm_x64_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_x64_entry((as), (num_locals)) +#define ASM_EXIT asm_x64_exit -#define ASM_JUMP asm_x64_jmp_label +#define ASM_JUMP asm_x64_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ @@ -192,6 +194,8 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32); #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x64_mov_local_addr_to_r64((as), (local_num), (reg_dest)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x64_mov_reg_pcrel((as), (reg_dest), (label)) +#define ASM_NOT_REG(as, reg) asm_x64_not_r64((as), (reg)) +#define ASM_NEG_REG(as, reg) asm_x64_neg_r64((as), (reg)) #define ASM_LSL_REG(as, reg) asm_x64_shl_r64_cl((as), (reg)) #define ASM_LSR_REG(as, reg) asm_x64_shr_r64_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x64_sar_r64_cl((as), (reg)) @@ -202,18 +206,21 @@ void asm_x64_call_ind(asm_x64_t *as, size_t fun_id, int temp_r32); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x64_sub_r64_r64((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x64_mul_r64_r64((as), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem64_to_r64((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (word_offset), (reg_dest)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem8_to_r64zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 2 * (uint16_offset), (reg_dest)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 0, (reg_dest)) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, qword_offset) asm_x64_mov_mem64_to_r64((as), (reg_base), 8 * (qword_offset), (reg_dest)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_x64_mov_mem8_to_r64zx((as), (reg_base), (byte_offset), (reg_dest)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x64_mov_mem16_to_r64zx((as), (reg_base), 2 * (word_offset), (reg_dest)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) asm_x64_mov_mem32_to_r64zx((as), (reg_base), 4 * (dword_offset), (reg_dest)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, qword_offset) asm_x64_mov_r64_to_mem64((as), (reg_src), (reg_base), 8 * (qword_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_x64_mov_r8_to_mem8((as), (reg_src), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x64_mov_r16_to_mem16((as), (reg_src), (reg_base), 2 * (word_offset)) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) asm_x64_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (dword_offset)) #endif // GENERIC_ASM_API diff --git a/py/asmx86.c b/py/asmx86.c index 4b0f8047f6eb7..4acac1b46ac4f 100644 --- a/py/asmx86.c +++ b/py/asmx86.c @@ -54,6 +54,8 @@ #define OPCODE_MOVZX_RM8_TO_R32 (0xb6) /* 0x0f 0xb6/r */ #define OPCODE_MOVZX_RM16_TO_R32 (0xb7) /* 0x0f 0xb7/r */ #define OPCODE_LEA_MEM_TO_R32 (0x8d) /* /r */ +#define OPCODE_NOT_RM32 (0xf7) /* /2 */ +#define OPCODE_NEG_RM32 (0xf7) /* /3 */ #define OPCODE_AND_R32_TO_RM32 (0x21) /* /r */ #define OPCODE_OR_R32_TO_RM32 (0x09) /* /r */ #define OPCODE_XOR_R32_TO_RM32 (0x31) /* /r */ @@ -103,14 +105,14 @@ #define SIGNED_FIT8(x) (((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80) -STATIC void asm_x86_write_byte_1(asm_x86_t *as, byte b1) { +static void asm_x86_write_byte_1(asm_x86_t *as, byte b1) { byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 1); if (c != NULL) { c[0] = b1; } } -STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) { +static void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) { byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 2); if (c != NULL) { c[0] = b1; @@ -118,7 +120,7 @@ STATIC void asm_x86_write_byte_2(asm_x86_t *as, byte b1, byte b2) { } } -STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) { +static void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) { byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 3); if (c != NULL) { c[0] = b1; @@ -127,7 +129,7 @@ STATIC void asm_x86_write_byte_3(asm_x86_t *as, byte b1, byte b2, byte b3) { } } -STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) { +static void asm_x86_write_word32(asm_x86_t *as, int w32) { byte *c = mp_asm_base_get_cur_to_write_bytes(&as->base, 4); if (c != NULL) { c[0] = IMM32_L0(w32); @@ -137,7 +139,7 @@ STATIC void asm_x86_write_word32(asm_x86_t *as, int w32) { } } -STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) { +static void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int disp_offset) { uint8_t rm_disp; if (disp_offset == 0 && disp_r32 != ASM_X86_REG_EBP) { rm_disp = MODRM_RM_DISP0; @@ -158,17 +160,17 @@ STATIC void asm_x86_write_r32_disp(asm_x86_t *as, int r32, int disp_r32, int dis } } -STATIC void asm_x86_generic_r32_r32(asm_x86_t *as, int dest_r32, int src_r32, int op) { +static void asm_x86_generic_r32_r32(asm_x86_t *as, int dest_r32, int src_r32, int op) { asm_x86_write_byte_2(as, op, MODRM_R32(src_r32) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); } #if 0 -STATIC void asm_x86_nop(asm_x86_t *as) { +static void asm_x86_nop(asm_x86_t *as) { asm_x86_write_byte_1(as, OPCODE_NOP); } #endif -STATIC void asm_x86_push_r32(asm_x86_t *as, int src_r32) { +static void asm_x86_push_r32(asm_x86_t *as, int src_r32) { asm_x86_write_byte_1(as, OPCODE_PUSH_R32 | src_r32); } @@ -184,11 +186,11 @@ void asm_x86_push_disp(asm_x86_t *as, int src_r32, int src_offset) { } #endif -STATIC void asm_x86_pop_r32(asm_x86_t *as, int dest_r32) { +static void asm_x86_pop_r32(asm_x86_t *as, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_POP_R32 | dest_r32); } -STATIC void asm_x86_ret(asm_x86_t *as) { +static void asm_x86_ret(asm_x86_t *as) { asm_x86_write_byte_1(as, OPCODE_RET); } @@ -226,7 +228,7 @@ void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } -STATIC void asm_x86_lea_disp_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { +static void asm_x86_lea_disp_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32) { asm_x86_write_byte_1(as, OPCODE_LEA_MEM_TO_R32); asm_x86_write_r32_disp(as, dest_r32, src_r32, src_disp); } @@ -244,6 +246,14 @@ size_t asm_x86_mov_i32_to_r32(asm_x86_t *as, int32_t src_i32, int dest_r32) { return loc; } +void asm_x86_not_r32(asm_x86_t *as, int dest_r32) { + asm_x86_generic_r32_r32(as, dest_r32, 2, OPCODE_NOT_RM32); +} + +void asm_x86_neg_r32(asm_x86_t *as, int dest_r32) { + asm_x86_generic_r32_r32(as, dest_r32, 3, OPCODE_NEG_RM32); +} + void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_AND_R32_TO_RM32); } @@ -272,7 +282,7 @@ void asm_x86_add_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_ADD_R32_TO_RM32); } -STATIC void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) { +static void asm_x86_add_i32_to_r32(asm_x86_t *as, int src_i32, int dest_r32) { if (SIGNED_FIT8(src_i32)) { asm_x86_write_byte_2(as, OPCODE_ADD_I8_TO_RM32, MODRM_R32(0) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); asm_x86_write_byte_1(as, src_i32 & 0xff); @@ -286,7 +296,7 @@ void asm_x86_sub_r32_r32(asm_x86_t *as, int dest_r32, int src_r32) { asm_x86_generic_r32_r32(as, dest_r32, src_r32, OPCODE_SUB_R32_FROM_RM32); } -STATIC void asm_x86_sub_r32_i32(asm_x86_t *as, int dest_r32, int src_i32) { +static void asm_x86_sub_r32_i32(asm_x86_t *as, int dest_r32, int src_i32) { if (SIGNED_FIT8(src_i32)) { // defaults to 32 bit operation asm_x86_write_byte_2(as, OPCODE_SUB_I8_FROM_RM32, MODRM_R32(5) | MODRM_RM_REG | MODRM_RM_R32(dest_r32)); @@ -353,7 +363,7 @@ void asm_x86_jmp_reg(asm_x86_t *as, int src_r32) { asm_x86_write_byte_2(as, OPCODE_JMP_RM32, MODRM_R32(4) | MODRM_RM_REG | MODRM_RM_R32(src_r32)); } -STATIC mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) { +static mp_uint_t get_label_dest(asm_x86_t *as, mp_uint_t label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } @@ -422,7 +432,7 @@ void asm_x86_exit(asm_x86_t *as) { asm_x86_ret(as); } -STATIC int asm_x86_arg_offset_from_esp(asm_x86_t *as, size_t arg_num) { +static int asm_x86_arg_offset_from_esp(asm_x86_t *as, size_t arg_num) { // Above esp are: locals, 4 saved registers, return eip, arguments return (as->num_locals + 4 + 1 + arg_num) * WORD_SIZE; } @@ -454,7 +464,7 @@ void asm_x86_mov_r32_to_arg(asm_x86_t *as, int src_r32, int dest_arg_num) { // ^ ^ // | low address | high address in RAM // -STATIC int asm_x86_local_offset_from_esp(asm_x86_t *as, int local_num) { +static int asm_x86_local_offset_from_esp(asm_x86_t *as, int local_num) { (void)as; // Stack is full descending, ESP points to local0 return local_num * WORD_SIZE; diff --git a/py/asmx86.h b/py/asmx86.h index 10532265c28ef..f5d37228a2f04 100644 --- a/py/asmx86.h +++ b/py/asmx86.h @@ -92,6 +92,8 @@ void asm_x86_mov_r32_to_mem32(asm_x86_t *as, int src_r32, int dest_r32, int dest void asm_x86_mov_mem8_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); void asm_x86_mov_mem16_to_r32zx(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); void asm_x86_mov_mem32_to_r32(asm_x86_t *as, int src_r32, int src_disp, int dest_r32); +void asm_x86_not_r32(asm_x86_t *as, int dest_r32); +void asm_x86_neg_r32(asm_x86_t *as, int dest_r32); void asm_x86_and_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); void asm_x86_or_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); void asm_x86_xor_r32_r32(asm_x86_t *as, int dest_r32, int src_r32); @@ -148,12 +150,12 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r // Holds a pointer to mp_fun_table #define REG_FUN_TABLE ASM_X86_REG_FUN_TABLE -#define ASM_T asm_x86_t -#define ASM_END_PASS asm_x86_end_pass -#define ASM_ENTRY asm_x86_entry -#define ASM_EXIT asm_x86_exit +#define ASM_T asm_x86_t +#define ASM_END_PASS asm_x86_end_pass +#define ASM_ENTRY(as, num_locals, name) asm_x86_entry((as), (num_locals)) +#define ASM_EXIT asm_x86_exit -#define ASM_JUMP asm_x86_jmp_label +#define ASM_JUMP asm_x86_jmp_label #define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ do { \ if (bool_test) { \ @@ -187,6 +189,8 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_x86_mov_local_addr_to_r32((as), (local_num), (reg_dest)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_x86_mov_reg_pcrel((as), (reg_dest), (label)) +#define ASM_NOT_REG(as, reg) asm_x86_not_r32((as), (reg)) +#define ASM_NEG_REG(as, reg) asm_x86_neg_r32((as), (reg)) #define ASM_LSL_REG(as, reg) asm_x86_shl_r32_cl((as), (reg)) #define ASM_LSR_REG(as, reg) asm_x86_shr_r32_cl((as), (reg)) #define ASM_ASR_REG(as, reg) asm_x86_sar_r32_cl((as), (reg)) @@ -197,18 +201,21 @@ void asm_x86_call_ind(asm_x86_t *as, size_t fun_id, mp_uint_t n_args, int temp_r #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_x86_sub_r32_r32((as), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_x86_mul_r32_r32((as), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (word_offset), (reg_dest)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem8_to_r32zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 0, (reg_dest)) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 2 * (uint16_offset), (reg_dest)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_x86_mov_mem32_to_r32((as), (reg_base), 0, (reg_dest)) - -#define ASM_STORE_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (dword_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_x86_mov_mem8_to_r32zx((as), (reg_base), (byte_offset), (reg_dest)) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_x86_mov_mem16_to_r32zx((as), (reg_base), 2 * (word_offset), (reg_dest)) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, dword_offset) asm_x86_mov_mem32_to_r32((as), (reg_base), 4 * (dword_offset), (reg_dest)) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), (dword_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_x86_mov_r8_to_mem8((as), (reg_src), (reg_base), (byte_offset)) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) asm_x86_mov_r16_to_mem16((as), (reg_src), (reg_base), 2 * (word_offset)) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_src, reg_base, dword_offset) asm_x86_mov_r32_to_mem32((as), (reg_src), (reg_base), 4 * (dword_offset)) #endif // GENERIC_ASM_API diff --git a/py/asmxtensa.c b/py/asmxtensa.c index 8ac914ec412a4..bc3e717d9f3a0 100644 --- a/py/asmxtensa.c +++ b/py/asmxtensa.c @@ -34,9 +34,20 @@ #include "py/asmxtensa.h" +#if N_XTENSAWIN +#define REG_TEMP ASM_XTENSA_REG_TEMPORARY_WIN +#else +#define REG_TEMP ASM_XTENSA_REG_TEMPORARY +#endif + #define WORD_SIZE (4) +#define SIGNED_FIT6(x) ((((x) & 0xffffffe0) == 0) || (((x) & 0xffffffe0) == 0xffffffe0)) #define SIGNED_FIT8(x) ((((x) & 0xffffff80) == 0) || (((x) & 0xffffff80) == 0xffffff80)) #define SIGNED_FIT12(x) ((((x) & 0xfffff800) == 0) || (((x) & 0xfffff800) == 0xfffff800)) +#define SIGNED_FIT18(x) ((((x) & 0xfffe0000) == 0) || (((x) & 0xfffe0000) == 0xfffe0000)) + +#define ET_OUT_OF_RANGE MP_ERROR_TEXT("ERROR: xtensa %q out of range") +#define ET_NOT_ALIGNED MP_ERROR_TEXT("ERROR: %q %q not word-aligned") void asm_xtensa_end_pass(asm_xtensa_t *as) { as->num_const = as->cur_const; @@ -47,9 +58,9 @@ void asm_xtensa_end_pass(asm_xtensa_t *as) { if (as->base.pass == MP_ASM_PASS_EMIT) { uint8_t *d = as->base.code_base; printf("XTENSA ASM:"); - for (int i = 0; i < ((as->base.code_size + 15) & ~15); ++i) { + for (size_t i = 0; i < ((as->base.code_size + 15) & ~15); ++i) { if (i % 16 == 0) { - printf("\n%08x:", (uint32_t)&d[i]); + printf("\n%p:", &d[i]); } if (i % 2 == 0) { printf(" "); @@ -62,10 +73,12 @@ void asm_xtensa_end_pass(asm_xtensa_t *as) { } void asm_xtensa_entry(asm_xtensa_t *as, int num_locals) { - // jump over the constants - asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); - mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte - as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); + if (as->num_const > 0) { + // jump over the constants + asm_xtensa_op_j(as, as->num_const * WORD_SIZE + 4 - 4); + mp_asm_base_get_cur_to_write_bytes(&as->base, 1); // padding/alignment byte + as->const_table = (uint32_t *)mp_asm_base_get_cur_to_write_bytes(&as->base, as->num_const * 4); + } // adjust the stack-pointer to store a0, a12, a13, a14, a15 and locals, 16-byte aligned as->stack_adjust = (((ASM_XTENSA_NUM_REGS_SAVED + num_locals) * WORD_SIZE) + 15) & ~15; @@ -117,7 +130,7 @@ void asm_xtensa_exit_win(asm_xtensa_t *as) { asm_xtensa_op_retw_n(as); } -STATIC uint32_t get_label_dest(asm_xtensa_t *as, uint label) { +static uint32_t get_label_dest(asm_xtensa_t *as, uint label) { assert(label < as->base.max_num_labels); return as->base.label_offsets[label]; } @@ -146,22 +159,60 @@ void asm_xtensa_j_label(asm_xtensa_t *as, uint label) { asm_xtensa_op_j(as, rel); } +static bool calculate_branch_displacement(asm_xtensa_t *as, uint label, ptrdiff_t *displacement) { + assert(displacement != NULL && "Displacement pointer is NULL"); + + uint32_t label_offset = get_label_dest(as, label); + *displacement = (ptrdiff_t)(label_offset - as->base.code_offset - 4); + return (label_offset != (uint32_t)-1) && (*displacement < 0); +} + void asm_xtensa_bccz_reg_label(asm_xtensa_t *as, uint cond, uint reg, uint label) { - uint32_t dest = get_label_dest(as, label); - int32_t rel = dest - as->base.code_offset - 4; - if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT12(rel)) { - printf("ERROR: xtensa bccz out of range\n"); + ptrdiff_t rel = 0; + bool can_emit_short_jump = calculate_branch_displacement(as, label, &rel); + + if (can_emit_short_jump && SIGNED_FIT12(rel)) { + // Backwards BCCZ opcodes with an offset that fits in 12 bits can + // be emitted without any change. + asm_xtensa_op_bccz(as, cond, reg, rel); + return; } - asm_xtensa_op_bccz(as, cond, reg, rel); + + // Range is effectively extended to 18 bits, as a more complex jump code + // sequence is emitted. + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT18(rel - 6)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bccz); + } + + // ~BCCZ skip ; +0 <- Condition is flipped here (EQ -> NE, etc.) + // J addr ; +3 + // skip: ; +6 + asm_xtensa_op_bccz(as, cond ^ 1, reg, 6 - 4); + asm_xtensa_op_j(as, rel - 3); } void asm_xtensa_bcc_reg_reg_label(asm_xtensa_t *as, uint cond, uint reg1, uint reg2, uint label) { - uint32_t dest = get_label_dest(as, label); - int32_t rel = dest - as->base.code_offset - 4; - if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) { - printf("ERROR: xtensa bcc out of range\n"); + ptrdiff_t rel = 0; + bool can_emit_short_jump = calculate_branch_displacement(as, label, &rel); + + if (can_emit_short_jump && SIGNED_FIT8(rel)) { + // Backwards BCC opcodes with an offset that fits in 8 bits can + // be emitted without any change. + asm_xtensa_op_bcc(as, cond, reg1, reg2, rel); + return; + } + + // Range is effectively extended to 18 bits, as a more complex jump code + // sequence is emitted. + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT18(rel - 6)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bcc); } - asm_xtensa_op_bcc(as, cond, reg1, reg2, rel); + + // ~BCC skip ; +0 <- Condition is flipped here (EQ -> NE, etc.) + // J addr ; +3 + // skip: ; +6 + asm_xtensa_op_bcc(as, cond ^ 8, reg1, reg2, 6 - 4); + asm_xtensa_op_j(as, rel - 3); } // convenience function; reg_dest must be different from reg_src[12] @@ -179,13 +230,17 @@ size_t asm_xtensa_mov_reg_i32(asm_xtensa_t *as, uint reg_dest, uint32_t i32) { // store the constant in the table if (as->const_table != NULL) { as->const_table[as->cur_const] = i32; + } else { + assert((as->base.pass != MP_ASM_PASS_EMIT) && "Constants table was not built."); } ++as->cur_const; return loc; } void asm_xtensa_mov_reg_i32_optimised(asm_xtensa_t *as, uint reg_dest, uint32_t i32) { - if (SIGNED_FIT12(i32)) { + if (-32 <= (int)i32 && (int)i32 <= 95) { + asm_xtensa_op_movi_n(as, reg_dest, i32); + } else if (SIGNED_FIT12(i32)) { asm_xtensa_op_movi(as, reg_dest, i32); } else { asm_xtensa_mov_reg_i32(as, reg_dest, i32); @@ -238,17 +293,53 @@ void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, u } else if (word_offset < 256) { asm_xtensa_op_l32i(as, reg_dest, reg_base, word_offset); } else { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow")); + asm_xtensa_mov_reg_i32_optimised(as, reg_dest, word_offset * 4); + asm_xtensa_op_add_n(as, reg_dest, reg_base, reg_dest); + asm_xtensa_op_l32i_n(as, reg_dest, reg_dest, 0); } } -void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset) { - if (word_offset < 16) { - asm_xtensa_op_s32i_n(as, reg_src, reg_base, word_offset); - } else if (word_offset < 256) { - asm_xtensa_op_s32i(as, reg_src, reg_base, word_offset); +void asm_xtensa_load_reg_reg_offset(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size == 2 && MP_FIT_UNSIGNED(4, offset)) { + asm_xtensa_op_l32i_n(as, reg_dest, reg_base, offset); + return; + } + + if (MP_FIT_UNSIGNED(8, offset)) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, operation_size, reg_base, reg_dest, offset)); + return; + } + + asm_xtensa_mov_reg_i32_optimised(as, reg_dest, offset << operation_size); + asm_xtensa_op_add_n(as, reg_dest, reg_base, reg_dest); + if (operation_size == 2) { + asm_xtensa_op_l32i_n(as, reg_dest, reg_dest, 0); } else { - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("asm overflow")); + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, operation_size, reg_dest, reg_dest, 0)); + } +} + +void asm_xtensa_store_reg_reg_offset(asm_xtensa_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size) { + assert(operation_size <= 2 && "Operation size value out of range."); + + if (operation_size == 2 && MP_FIT_UNSIGNED(4, offset)) { + asm_xtensa_op_s32i_n(as, reg_src, reg_base, offset); + return; + } + + if (MP_FIT_UNSIGNED(8, offset)) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0x04 | operation_size, reg_base, reg_src, offset)); + return; + } + + asm_xtensa_mov_reg_i32_optimised(as, REG_TEMP, offset << operation_size); + asm_xtensa_op_add_n(as, REG_TEMP, reg_base, REG_TEMP); + if (operation_size == 2) { + asm_xtensa_op_s32i_n(as, reg_src, REG_TEMP, 0); + } else { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 0x04 | operation_size, REG_TEMP, reg_src, 0)); } } @@ -262,4 +353,47 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx) { asm_xtensa_op_callx8(as, ASM_XTENSA_REG_A8); } +void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset - 4; + if (as->base.pass == MP_ASM_PASS_EMIT && !SIGNED_FIT8(rel)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_bit_branch); + } + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(7, condition | ((bit >> 4) & 0x01), reg, bit & 0x0F, rel & 0xFF)); +} + +void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset - 3; + if (as->base.pass == MP_ASM_PASS_EMIT) { + if ((dest & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_target); + } + if ((rel & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_call0, MP_QSTR_location); + } + if (!SIGNED_FIT18(rel)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_call0); + } + } + asm_xtensa_op_call0(as, rel); +} + +void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label) { + uint32_t dest = get_label_dest(as, label); + int32_t rel = dest - as->base.code_offset; + if (as->base.pass == MP_ASM_PASS_EMIT) { + if ((dest & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_target); + } + if ((rel & 0x03) != 0) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_NOT_ALIGNED, MP_QSTR_l32r, MP_QSTR_location); + } + if (!SIGNED_FIT18(rel) || (rel >= 0)) { + mp_raise_msg_varg(&mp_type_RuntimeError, ET_OUT_OF_RANGE, MP_QSTR_l32r); + } + } + asm_xtensa_op_l32r(as, reg, as->base.code_offset, dest); +} + #endif // MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_XTENSAWIN diff --git a/py/asmxtensa.h b/py/asmxtensa.h index 62fdb5df89a81..ed98c9d730516 100644 --- a/py/asmxtensa.h +++ b/py/asmxtensa.h @@ -64,9 +64,11 @@ #define ASM_XTENSA_REG_A14 (14) #define ASM_XTENSA_REG_A15 (15) -// for bccz +// for bccz and bcci #define ASM_XTENSA_CCZ_EQ (0) #define ASM_XTENSA_CCZ_NE (1) +#define ASM_XTENSA_CCZ_LT (2) +#define ASM_XTENSA_CCZ_GE (3) // for bcc and setcc #define ASM_XTENSA_CC_NONE (0) @@ -143,6 +145,14 @@ static inline void asm_xtensa_op_addi(asm_xtensa_t *as, uint reg_dest, uint reg_ asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 12, reg_src, reg_dest, imm8 & 0xff)); } +static inline void asm_xtensa_op_addx2(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 9, reg_dest, reg_src_a, reg_src_b)); +} + +static inline void asm_xtensa_op_addx4(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 10, reg_dest, reg_src_a, reg_src_b)); +} + static inline void asm_xtensa_op_and(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 1, reg_dest, reg_src_a, reg_src_b)); } @@ -203,14 +213,19 @@ static inline void asm_xtensa_op_movi(asm_xtensa_t *as, uint reg_dest, int32_t i asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRI8(2, 10, (imm12 >> 8) & 0xf, reg_dest, imm12 & 0xff)); } -static inline void asm_xtensa_op_movi_n(asm_xtensa_t *as, uint reg_dest, int imm4) { - asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RI7(12, reg_dest, imm4)); +// Argument must be in the range (-32 .. 95) inclusive. +static inline void asm_xtensa_op_movi_n(asm_xtensa_t *as, uint reg_dest, int imm7) { + asm_xtensa_op16(as, ASM_XTENSA_ENCODE_RI7(12, reg_dest, imm7)); } static inline void asm_xtensa_op_mull(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 2, 8, reg_dest, reg_src_a, reg_src_b)); } +static inline void asm_xtensa_op_neg(asm_xtensa_t *as, uint reg_dest, uint reg_src) { + asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, reg_dest, 0, reg_src)); +} + static inline void asm_xtensa_op_or(asm_xtensa_t *as, uint reg_dest, uint reg_src_a, uint reg_src_b) { asm_xtensa_op24(as, ASM_XTENSA_ENCODE_RRR(0, 0, 2, reg_dest, reg_src_a, reg_src_b)); } @@ -278,15 +293,24 @@ void asm_xtensa_mov_local_reg(asm_xtensa_t *as, int local_num, uint reg_src); void asm_xtensa_mov_reg_local(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_local_addr(asm_xtensa_t *as, uint reg_dest, int local_num); void asm_xtensa_mov_reg_pcrel(asm_xtensa_t *as, uint reg_dest, uint label); -void asm_xtensa_l32i_optimised(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint word_offset); -void asm_xtensa_s32i_optimised(asm_xtensa_t *as, uint reg_src, uint reg_base, uint word_offset); +void asm_xtensa_load_reg_reg_offset(asm_xtensa_t *as, uint reg_dest, uint reg_base, uint offset, uint operation_size); +void asm_xtensa_store_reg_reg_offset(asm_xtensa_t *as, uint reg_src, uint reg_base, uint offset, uint operation_size); void asm_xtensa_call_ind(asm_xtensa_t *as, uint idx); void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); +void asm_xtensa_bit_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t bit, mp_uint_t label, mp_uint_t condition); +void asm_xtensa_immediate_branch(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t immediate, mp_uint_t label, mp_uint_t cond); +void asm_xtensa_call0(asm_xtensa_t *as, mp_uint_t label); +void asm_xtensa_l32r(asm_xtensa_t *as, mp_uint_t reg, mp_uint_t label); // Holds a pointer to mp_fun_table #define ASM_XTENSA_REG_FUN_TABLE ASM_XTENSA_REG_A15 #define ASM_XTENSA_REG_FUN_TABLE_WIN ASM_XTENSA_REG_A7 +// Internal temporary register (currently aliased to REG_ARG_5 for xtensa, +// and to REG_TEMP2 for xtensawin). +#define ASM_XTENSA_REG_TEMPORARY ASM_XTENSA_REG_A6 +#define ASM_XTENSA_REG_TEMPORARY_WIN ASM_XTENSA_REG_A12 + // CIRCUITPY-CHANGE: prevent #if warning #if defined(GENERIC_ASM_API) && GENERIC_ASM_API @@ -317,9 +341,9 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE -#define ASM_ENTRY(as, nlocal) asm_xtensa_entry((as), (nlocal)) -#define ASM_EXIT(as) asm_xtensa_exit((as)) -#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) +#define ASM_ENTRY(as, nlocal, name) asm_xtensa_entry((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind((as), (idx)) #else // Configuration for windowed calls with window size 8 @@ -347,9 +371,9 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_NUM_REGS_SAVED ASM_XTENSA_NUM_REGS_SAVED_WIN #define REG_FUN_TABLE ASM_XTENSA_REG_FUN_TABLE_WIN -#define ASM_ENTRY(as, nlocal) asm_xtensa_entry_win((as), (nlocal)) -#define ASM_EXIT(as) asm_xtensa_exit_win((as)) -#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) +#define ASM_ENTRY(as, nlocal, name) asm_xtensa_entry_win((as), (nlocal)) +#define ASM_EXIT(as) asm_xtensa_exit_win((as)) +#define ASM_CALL_IND(as, idx) asm_xtensa_call_ind_win((as), (idx)) #endif @@ -372,6 +396,7 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) asm_xtensa_mov_reg_local_addr((as), (reg_dest), ASM_NUM_REGS_SAVED + (local_num)) #define ASM_MOV_REG_PCREL(as, reg_dest, label) asm_xtensa_mov_reg_pcrel((as), (reg_dest), (label)) +#define ASM_NEG_REG(as, reg_dest) asm_xtensa_op_neg((as), (reg_dest), (reg_dest)) #define ASM_LSL_REG_REG(as, reg_dest, reg_shift) \ do { \ asm_xtensa_op_ssl((as), (reg_shift)); \ @@ -394,16 +419,51 @@ void asm_xtensa_call_ind_win(asm_xtensa_t *as, uint idx); #define ASM_SUB_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_sub((as), (reg_dest), (reg_dest), (reg_src)) #define ASM_MUL_REG_REG(as, reg_dest, reg_src) asm_xtensa_op_mull((as), (reg_dest), (reg_dest), (reg_src)) -#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_l32i_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0) -#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), (uint16_offset)) -#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) ASM_LOAD8_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD8_REG_REG_OFFSET(as, reg_dest, reg_base, byte_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (byte_offset), 0) +#define ASM_LOAD8_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_add_n((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l8ui((as), (reg_dest), (reg_base), 0); \ + } while (0) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) ASM_LOAD16_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, halfword_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (halfword_offset), 1) +#define ASM_LOAD16_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx2((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l16ui((as), (reg_dest), (reg_base), 0); \ + } while (0) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) ASM_LOAD32_REG_REG_OFFSET((as), (reg_dest), (reg_base), 0) +#define ASM_LOAD32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_load_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) +#define ASM_LOAD32_REG_REG_REG(as, reg_dest, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx4((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_l32i_n((as), (reg_dest), (reg_base), 0); \ + } while (0) -#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_s32i_optimised((as), (reg_dest), (reg_base), (word_offset)) -#define ASM_STORE8_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s8i((as), (reg_src), (reg_base), 0) -#define ASM_STORE16_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s16i((as), (reg_src), (reg_base), 0) -#define ASM_STORE32_REG_REG(as, reg_src, reg_base) asm_xtensa_op_s32i_n((as), (reg_src), (reg_base), 0) +#define ASM_STORE_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) ASM_STORE32_REG_REG_OFFSET((as), (reg_dest), (reg_base), (word_offset)) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) ASM_STORE8_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE8_REG_REG_OFFSET(as, reg_src, reg_base, byte_offset) asm_xtensa_store_reg_reg_offset((as), (reg_src), (reg_base), (byte_offset), 0) +#define ASM_STORE8_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_add_n((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s8i((as), (reg_val), (reg_base), 0); \ + } while (0) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) ASM_STORE16_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE16_REG_REG_OFFSET(as, reg_src, reg_base, halfword_offset) asm_xtensa_store_reg_reg_offset((as), (reg_src), (reg_base), (halfword_offset), 1) +#define ASM_STORE16_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx2((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s16i((as), (reg_val), (reg_base), 0); \ + } while (0) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) ASM_STORE32_REG_REG_OFFSET((as), (reg_src), (reg_base), 0) +#define ASM_STORE32_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) asm_xtensa_store_reg_reg_offset((as), (reg_dest), (reg_base), (word_offset), 2) +#define ASM_STORE32_REG_REG_REG(as, reg_val, reg_base, reg_index) \ + do { \ + asm_xtensa_op_addx4((as), (reg_base), (reg_index), (reg_base)); \ + asm_xtensa_op_s32i_n((as), (reg_val), (reg_base), 0); \ + } while (0) #endif // GENERIC_ASM_API diff --git a/py/bc.c b/py/bc.c index 752bd085372ae..4caa022e3d8b4 100644 --- a/py/bc.c +++ b/py/bc.c @@ -88,7 +88,7 @@ const byte *mp_decode_uint_skip(const byte *ptr) { return ptr; } -STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { +static MP_NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE // generic message, used also for other argument issues (void)f; @@ -109,7 +109,7 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, } #if DEBUG_PRINT -STATIC void dump_args(const mp_obj_t *a, size_t sz) { +static void dump_args(const mp_obj_t *a, size_t sz) { DEBUG_printf("%p: ", a); for (size_t i = 0; i < sz; i++) { DEBUG_printf("%p ", a[i]); @@ -126,7 +126,7 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { // - code_state->ip should contain a pointer to the beginning of the prelude // - code_state->sp should be: &code_state->state[0] - 1 // - code_state->n_state should be the number of objects in the local state -STATIC void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static void mp_setup_code_state_helper(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) { // This function is pretty complicated. It's main aim is to be efficient in speed and RAM // usage for the common case of positional only args. @@ -340,9 +340,9 @@ void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw // On entry code_state should be allocated somewhere (stack/heap) and // contain the following valid entries: // - code_state->fun_bc should contain a pointer to the function object -// - code_state->ip should contain a pointer to the beginning of the prelude // - code_state->n_state should be the number of objects in the local state void mp_setup_code_state_native(mp_code_state_native_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) { + code_state->ip = mp_obj_fun_native_get_prelude_ptr(code_state->fun_bc); code_state->sp = &code_state->state[0] - 1; mp_setup_code_state_helper((mp_code_state_t *)code_state, n_args, n_kw, args); } diff --git a/py/bc.h b/py/bc.h index f2d4c5ee67ce3..3b7a6fe1c960b 100644 --- a/py/bc.h +++ b/py/bc.h @@ -44,11 +44,11 @@ // prelude size : var uint // contains two values interleaved bit-wise as: xIIIIIIC repeated // x = extension another byte follows -// I = n_info number of bytes in source info section +// I = n_info number of bytes in source info section (always > 0) // C = n_cells number of bytes/cells in closure section // // source info section: -// simple_name : var qstr +// simple_name : var qstr always exists // argname0 : var qstr // ... : var qstr // argnameN : var qstr N = num_pos_args + num_kwonly_args - 1 @@ -226,13 +226,14 @@ typedef struct _mp_compiled_module_t { bool has_native; size_t n_qstr; size_t n_obj; + size_t arch_flags; #endif } mp_compiled_module_t; // Outer level struct defining a frozen module. typedef struct _mp_frozen_module_t { const mp_module_constants_t constants; - const struct _mp_raw_code_t *rc; + const void *proto_fun; } mp_frozen_module_t; // State for an executing function. @@ -287,7 +288,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); void mp_setup_code_state_native(mp_code_state_native_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args); -void mp_bytecode_print(const mp_print_t *print, const struct _mp_raw_code_t *rc, const mp_module_constants_t *cm); +void mp_bytecode_print(const mp_print_t *print, const struct _mp_raw_code_t *rc, size_t fun_data_len, const mp_module_constants_t *cm); void mp_bytecode_print2(const mp_print_t *print, const byte *ip, size_t len, struct _mp_raw_code_t *const *child_table, const mp_module_constants_t *cm); const byte *mp_bytecode_print_str(const mp_print_t *print, const byte *ip_start, const byte *ip, struct _mp_raw_code_t *const *child_table, const mp_module_constants_t *cm); #define mp_bytecode_print_inst(print, code, x_table) mp_bytecode_print2(print, code, 1, x_table) @@ -302,37 +303,49 @@ static inline void mp_module_context_alloc_tables(mp_module_context_t *context, #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE size_t nq = (n_qstr * sizeof(qstr_short_t) + sizeof(mp_uint_t) - 1) / sizeof(mp_uint_t); size_t no = n_obj; - mp_uint_t *mem = m_new(mp_uint_t, nq + no); + // CIRCUITPY-CHANGE + mp_uint_t *mem = (mp_uint_t *)m_malloc_items(nq + no); context->constants.qstr_table = (qstr_short_t *)mem; context->constants.obj_table = (mp_obj_t *)(mem + nq); #else if (n_obj == 0) { context->constants.obj_table = NULL; } else { - context->constants.obj_table = m_new(mp_obj_t, n_obj); + // CIRCUITPY-CHANGE + context->constants.obj_table = m_malloc_items(n_obj); } #endif } +typedef struct _mp_code_lineinfo_t { + size_t bc_increment; + size_t line_increment; +} mp_code_lineinfo_t; + +static inline mp_code_lineinfo_t mp_bytecode_decode_lineinfo(const byte **line_info) { + mp_code_lineinfo_t result; + size_t c = (*line_info)[0]; + if ((c & 0x80) == 0) { + // 0b0LLBBBBB encoding + result.bc_increment = c & 0x1f; + result.line_increment = c >> 5; + *line_info += 1; + } else { + // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) + result.bc_increment = c & 0xf; + result.line_increment = ((c << 4) & 0x700) | (*line_info)[1]; + *line_info += 2; + } + return result; +} + static inline size_t mp_bytecode_get_source_line(const byte *line_info, const byte *line_info_top, size_t bc_offset) { size_t source_line = 1; while (line_info < line_info_top) { - size_t c = *line_info; - size_t b, l; - if ((c & 0x80) == 0) { - // 0b0LLBBBBB encoding - b = c & 0x1f; - l = c >> 5; - line_info += 1; - } else { - // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) - b = c & 0xf; - l = ((c << 4) & 0x700) | line_info[1]; - line_info += 2; - } - if (bc_offset >= b) { - bc_offset -= b; - source_line += l; + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&line_info); + if (bc_offset >= decoded.bc_increment) { + bc_offset -= decoded.bc_increment; + source_line += decoded.line_increment; } else { // found source line corresponding to bytecode offset break; diff --git a/py/binary.c b/py/binary.c index d80d8e6e583aa..180a13beec7bf 100644 --- a/py/binary.c +++ b/py/binary.c @@ -71,18 +71,22 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { case 'Q': size = 8; break; - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': case 'O': case 'S': size = sizeof(void *); break; #endif + case 'e': + size = 2; + break; case 'f': + // CIRCUITPY-CHANGE: compiler determines size size = sizeof(float); break; case 'd': + // CIRCUITPY-CHANGE: compiler determines size size = sizeof(double); break; } @@ -123,8 +127,7 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { align = alignof(long long); size = sizeof(long long); break; - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': case 'O': case 'S': @@ -132,6 +135,10 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { size = sizeof(void *); break; #endif + case 'e': + align = 2; + size = 2; + break; case 'f': align = alignof(float); size = sizeof(float); @@ -154,6 +161,99 @@ size_t mp_binary_get_size(char struct_type, char val_type, size_t *palign) { return size; } +#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_USE_NATIVE_FLT16 + +static inline float mp_decode_half_float(uint16_t hf) { + union { + uint16_t i; + _Float16 f; + } fpu = { .i = hf }; + return fpu.f; +} + +static inline uint16_t mp_encode_half_float(float x) { + union { + uint16_t i; + _Float16 f; + } fp_sp = { .f = (_Float16)x }; + return fp_sp.i; +} + +#elif MICROPY_PY_BUILTINS_FLOAT + +static float mp_decode_half_float(uint16_t hf) { + union { + uint32_t i; + float f; + } fpu; + + uint16_t m = hf & 0x3ff; + int e = (hf >> 10) & 0x1f; + if (e == 0x1f) { + // Half-float is infinity. + e = 0xff; + } else if (e) { + // Half-float is normal. + e += 127 - 15; + } else if (m) { + // Half-float is subnormal, make it normal. + e = 127 - 15; + while (!(m & 0x400)) { + m <<= 1; + --e; + } + m -= 0x400; + ++e; + } + + fpu.i = ((hf & 0x8000u) << 16) | (e << 23) | (m << 13); + return fpu.f; +} + +static uint16_t mp_encode_half_float(float x) { + union { + uint32_t i; + float f; + } fpu = { .f = x }; + + uint16_t m = (fpu.i >> 13) & 0x3ff; + if (fpu.i & (1 << 12)) { + // Round up. + ++m; + } + int e = (fpu.i >> 23) & 0xff; + + if (e == 0xff) { + // Infinity. + e = 0x1f; + } else if (e != 0) { + e -= 127 - 15; + if (e < 0) { + // Underflow: denormalized, or zero. + if (e >= -11) { + m = (m | 0x400) >> -e; + if (m & 1) { + m = (m >> 1) + 1; + } else { + m >>= 1; + } + } else { + m = 0; + } + e = 0; + } else if (e > 0x3f) { + // Overflow: infinity. + e = 0x1f; + m = 0; + } + } + + uint16_t bits = ((fpu.i >> 16) & 0x8000) | (e << 10) | m; + return bits; +} + +#endif + mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) { mp_int_t val = 0; switch (typecode) { @@ -190,15 +290,14 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, size_t index) { case 'd': return mp_obj_new_float_from_d(((double *)p)[index]); #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES - // Extension to CPython: array of objects + // Extension to CPython: array of objects + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'O': return ((mp_obj_t *)p)[index]; // Extension to CPython: array of pointers case 'P': return mp_obj_new_int((mp_int_t)(uintptr_t)((void **)p)[index]); - #endif + #endif } return MP_OBJ_NEW_SMALL_INT(val); } @@ -248,15 +347,14 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte *p_base, byte * long long val = mp_binary_get_int(size, is_signed(val_type), (struct_type == '>'), p); - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - if (MICROPY_NONSTANDARD_TYPECODES && (val_type == 'O')) { + if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'O') { return (mp_obj_t)(mp_uint_t)val; - #if MICROPY_NONSTANDARD_TYPECODES - } else if (val_type == 'S') { + } else if (MICROPY_PY_STRUCT_UNSAFE_TYPECODES && val_type == 'S') { const char *s_val = (const char *)(uintptr_t)(mp_uint_t)val; - return mp_obj_new_str(s_val, strlen(s_val)); - #endif + return mp_obj_new_str_from_cstr(s_val); #if MICROPY_PY_BUILTINS_FLOAT + } else if (val_type == 'e') { + return mp_obj_new_float_from_f(mp_decode_half_float(val)); } else if (val_type == 'f') { union { uint32_t i; @@ -322,13 +420,15 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p mp_uint_t val; switch (val_type) { - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'O': val = (mp_uint_t)val_in; break; #endif #if MICROPY_PY_BUILTINS_FLOAT + case 'e': + val = mp_encode_half_float(mp_obj_get_float_to_f(val_in)); + break; case 'f': { union { uint32_t i; @@ -338,6 +438,8 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p val = fp_sp.i; break; } + // CIRCUITPY-CHANGE + #if MICROPY_PY_DOUBLE_TYPECODE case 'd': { union { uint64_t i64; @@ -356,6 +458,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p break; } #endif + #endif default: { // CIRCUITPY-CHANGE: add overflow checks bool signed_type = is_signed(val_type); @@ -367,6 +470,7 @@ void mp_binary_set_val(char struct_type, char val_type, mp_obj_t val_in, byte *p return; } #endif + // CIRCUITPY-CHANGE: add overflow checks { val = mp_obj_get_int(val_in); // Small int checking is separate, to be fast. @@ -397,8 +501,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_ ((double *)p)[index] = mp_obj_get_float_to_d(val_in); break; #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES // Extension to CPython: array of objects case 'O': ((mp_obj_t *)p)[index] = val_in; @@ -418,6 +521,7 @@ void mp_binary_set_val_array(char typecode, void *p, size_t index, mp_obj_t val_ return; } #endif + // CIRCUITPY-CHANGE: add overflow checks mp_int_t val = mp_obj_get_int(val_in); // Small int checking is separate, to be fast. mp_small_int_buffer_overflow_check(val, size, signed_type); @@ -469,12 +573,11 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, size_t index, mp_i ((double *)p)[index] = (double)val; break; #endif - // CIRCUITPY-CHANGE: non-standard typecodes can be turned off - #if MICROPY_NONSTANDARD_TYPECODES - // Extension to CPython: array of pointers + // Extension to CPython: array of pointers + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES case 'P': ((void **)p)[index] = (void *)(uintptr_t)val; break; - #endif + #endif } } diff --git a/py/builtin.h b/py/builtin.h index 81d0789802b9c..388bc8470053d 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -126,6 +126,8 @@ MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj); MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj); + // Modules needed by the runtime. extern const mp_obj_dict_t mp_module_builtins_globals; extern const mp_obj_module_t mp_module___main__; @@ -136,6 +138,7 @@ extern const mp_obj_module_t mp_module_sys; extern const mp_obj_module_t mp_module_errno; extern const mp_obj_module_t mp_module_uctypes; extern const mp_obj_module_t mp_module_machine; +extern const mp_obj_module_t mp_module_math; extern const char MICROPY_PY_BUILTINS_HELP_TEXT[]; diff --git a/py/builtinevex.c b/py/builtinevex.c index 73fca5d39bf52..74a4640492674 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -26,6 +26,7 @@ #include +#include "py/objcode.h" #include "py/objfun.h" #include "py/compile.h" #include "py/runtime.h" @@ -33,18 +34,7 @@ #if MICROPY_PY_BUILTINS_COMPILE -typedef struct _mp_obj_code_t { - mp_obj_base_t base; - mp_obj_t module_fun; -} mp_obj_code_t; - -STATIC MP_DEFINE_CONST_OBJ_TYPE( - mp_type_code, - MP_QSTR_code, - MP_TYPE_FLAG_NONE - ); - -STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { +static mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) { // save context nlr_jump_callback_node_globals_locals_t ctx; ctx.globals = mp_globals_get(); @@ -57,15 +47,28 @@ STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj // set exception handler to restore context if an exception is raised nlr_push_jump_callback(&ctx.callback, mp_globals_locals_set_from_nlr_jump_callback); - // a bit of a hack: fun_bc will re-set globals, so need to make sure it's - // the correct one - if (mp_obj_is_type(self->module_fun, &mp_type_fun_bc)) { - mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(self->module_fun); + #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_BASIC + mp_module_context_t *module_context = m_new_obj(mp_module_context_t); + module_context->module.base.type = &mp_type_module; + module_context->module.globals = globals; + module_context->constants = *mp_code_get_constants(self); + mp_obj_t module_fun = mp_make_function_from_proto_fun(mp_code_get_proto_fun(self), module_context, NULL); + #else + // The call to mp_parse_compile_execute() in mp_builtin_compile() below passes + // NULL for the globals, so repopulate that entry now with the correct globals. + mp_obj_t module_fun = self->module_fun; + if (mp_obj_is_type(self->module_fun, &mp_type_fun_bc) + #if MICROPY_EMIT_NATIVE + || mp_obj_is_type(self->module_fun, &mp_type_fun_native) + #endif + ) { + mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(module_fun); ((mp_module_context_t *)fun_bc->context)->module.globals = globals; } + #endif // execute code - mp_obj_t ret = mp_call_function_0(self->module_fun); + mp_obj_t ret = mp_call_function_0(module_fun); // deregister exception handler and restore context nlr_pop_jump_callback(true); @@ -74,7 +77,7 @@ STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj return ret; } -STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { (void)n_args; // get the source @@ -104,9 +107,29 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(MP_ERROR_TEXT("bad compile mode")); } - mp_obj_code_t *code = mp_obj_malloc(mp_obj_code_t, &mp_type_code); - code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL); - return MP_OBJ_FROM_PTR(code); + #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_BASIC + + mp_parse_tree_t parse_tree = mp_parse(lex, parse_input_kind); + mp_module_context_t ctx; + ctx.module.globals = NULL; + mp_compiled_module_t cm; + cm.context = &ctx; + mp_compile_to_raw_code(&parse_tree, lex->source_name, parse_input_kind == MP_PARSE_SINGLE_INPUT, &cm); + + #if MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_FULL + mp_module_context_t *ctx_ptr = m_new_obj(mp_module_context_t); + *ctx_ptr = ctx; + return mp_obj_new_code(ctx_ptr, cm.rc, true); + #else + return mp_obj_new_code(ctx.constants, cm.rc); + #endif + + #else + + mp_obj_t module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL); + return mp_obj_new_code(module_fun); + + #endif } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile); @@ -114,7 +137,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_com #if MICROPY_PY_BUILTINS_EVAL_EXEC -STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) { +static mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) { // work out the context mp_obj_dict_t *globals = mp_globals_get(); mp_obj_dict_t *locals = mp_locals_get(); @@ -154,12 +177,12 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i return mp_parse_compile_execute(lex, parse_input_kind, globals, locals); } -STATIC mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_eval(size_t n_args, const mp_obj_t *args) { return eval_exec_helper(n_args, args, MP_PARSE_EVAL_INPUT); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj, 1, 3, mp_builtin_eval); -STATIC mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_exec(size_t n_args, const mp_obj_t *args) { return eval_exec_helper(n_args, args, MP_PARSE_FILE_INPUT); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec); @@ -167,7 +190,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj, 1, 3, mp_builtin_exec); #endif // MICROPY_PY_BUILTINS_EVAL_EXEC #if MICROPY_PY_BUILTINS_EXECFILE -STATIC mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_execfile(size_t n_args, const mp_obj_t *args) { // MP_PARSE_SINGLE_INPUT is used to indicate a file input return eval_exec_helper(n_args, args, MP_PARSE_SINGLE_INPUT); } diff --git a/py/builtinhelp.c b/py/builtinhelp.c index 7f145a9ea5961..9ab2a12d21455 100644 --- a/py/builtinhelp.c +++ b/py/builtinhelp.c @@ -27,6 +27,7 @@ #include #include +// CIRCUITPY-CHANGE: more includes #include "genhdr/mpversion.h" #include "py/builtin.h" #include "py/mpconfig.h" @@ -49,7 +50,7 @@ const char mp_help_default_text[] = "For further help on a specific object, type help(obj)\n" ; -STATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) { +static void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) { mp_print_str(MP_PYTHON_PRINTER, " "); mp_obj_print(name_o, PRINT_STR); mp_print_str(MP_PYTHON_PRINTER, " -- "); @@ -58,7 +59,7 @@ STATIC void mp_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) { } #if MICROPY_PY_BUILTINS_HELP_MODULES -STATIC void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) { +static void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) { for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { mp_obj_list_append(list, map->table[i].key); @@ -67,7 +68,7 @@ STATIC void mp_help_add_from_map(mp_obj_t list, const mp_map_t *map) { } #if MICROPY_MODULE_FROZEN -STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) { +static void mp_help_add_from_names(mp_obj_t list, const char *name) { while (*name) { size_t len = strlen(name); // name should end in '.py' and we strip it off @@ -82,13 +83,14 @@ STATIC void mp_help_add_from_names(mp_obj_t list, const char *name) { extern const char mp_frozen_names[]; #endif -STATIC void mp_help_print_modules(void) { +static void mp_help_print_modules(void) { mp_obj_t list = mp_obj_new_list(0, NULL); mp_help_add_from_map(list, &mp_builtin_module_map); mp_help_add_from_map(list, &mp_builtin_extensible_module_map); #if MICROPY_MODULE_FROZEN + // CIRCUITPY-CHANGE: extern const char mp_frozen_names[] is at top level mp_help_add_from_names(list, mp_frozen_names); #endif @@ -129,7 +131,7 @@ STATIC void mp_help_print_modules(void) { } #endif -STATIC void mp_help_print_obj(const mp_obj_t obj) { +static void mp_help_print_obj(const mp_obj_t obj) { #if MICROPY_PY_BUILTINS_HELP_MODULES if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) { mp_help_print_modules(); @@ -160,15 +162,14 @@ STATIC void mp_help_print_obj(const mp_obj_t obj) { } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { - mp_obj_t key = map->table[i].key; - if (key != MP_OBJ_NULL) { - mp_help_print_info_about_object(key, map->table[i].value); + if (mp_map_slot_is_filled(map, i)) { + mp_help_print_info_about_object(map->table[i].key, map->table[i].value); } } } } -STATIC mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_help(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { // CIRCUITPY-CHANGE: make translatable // print a general help message. Translate only works on single strings on one line. diff --git a/py/builtinimport.c b/py/builtinimport.c index 2e25c390a2092..8fcac22ccb491 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -59,16 +59,17 @@ // uses mp_vfs_import_stat) to also search frozen modules. Given an exact // path to a file or directory (e.g. "foo/bar", foo/bar.py" or "foo/bar.mpy"), // will return whether the path is a file, directory, or doesn't exist. -STATIC mp_import_stat_t stat_path(const char *path) { +static mp_import_stat_t stat_path(vstr_t *path) { + const char *str = vstr_null_terminated_str(path); #if MICROPY_MODULE_FROZEN // Only try and load as a frozen module if it starts with .frozen/. const int frozen_path_prefix_len = strlen(MP_FROZEN_PATH_PREFIX); - if (strncmp(path, MP_FROZEN_PATH_PREFIX, frozen_path_prefix_len) == 0) { + if (strncmp(str, MP_FROZEN_PATH_PREFIX, frozen_path_prefix_len) == 0) { // Just stat (which is the return value), don't get the data. - return mp_find_frozen_module(path + frozen_path_prefix_len, NULL, NULL); + return mp_find_frozen_module(str + frozen_path_prefix_len, NULL, NULL); } #endif - return mp_import_stat(path); + return mp_import_stat(str); } // Stat a given filesystem path to a .py file. If the file does not exist, @@ -76,8 +77,8 @@ STATIC mp_import_stat_t stat_path(const char *path) { // argument. This is the logic that makes .py files take precedent over .mpy // files. This uses stat_path above, rather than mp_import_stat directly, so // that the .frozen path prefix is handled. -STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) { - mp_import_stat_t stat = stat_path(vstr_null_terminated_str(path)); +static mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) { + mp_import_stat_t stat = stat_path(path); if (stat == MP_IMPORT_STAT_FILE) { return stat; } @@ -87,7 +88,7 @@ STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) { // Note: There's no point doing this if it's a frozen path, but adding the check // would be extra code, and no harm letting mp_find_frozen_module fail instead. vstr_ins_byte(path, path->len - 2, 'm'); - stat = stat_path(vstr_null_terminated_str(path)); + stat = stat_path(path); if (stat == MP_IMPORT_STAT_FILE) { return stat; } @@ -100,8 +101,8 @@ STATIC mp_import_stat_t stat_file_py_or_mpy(vstr_t *path) { // or "foo/bar.(m)py" in either the filesystem or frozen modules. If the // result is a file, the path argument will be updated to include the file // extension. -STATIC mp_import_stat_t stat_module(vstr_t *path) { - mp_import_stat_t stat = stat_path(vstr_null_terminated_str(path)); +static mp_import_stat_t stat_module(vstr_t *path) { + mp_import_stat_t stat = stat_path(path); DEBUG_printf("stat %s: %d\n", vstr_str(path), stat); if (stat == MP_IMPORT_STAT_DIR) { return stat; @@ -115,9 +116,9 @@ STATIC mp_import_stat_t stat_module(vstr_t *path) { // Given a top-level module name, try and find it in each of the sys.path // entries. Note: On success, the dest argument will be updated to the matching // path (i.e. "/mod_name(.py)"). -STATIC mp_import_stat_t stat_top_level(qstr mod_name, vstr_t *dest) { +static mp_import_stat_t stat_top_level(qstr mod_name, vstr_t *dest) { DEBUG_printf("stat_top_level: '%s'\n", qstr_str(mod_name)); - #if MICROPY_PY_SYS + #if MICROPY_PY_SYS && MICROPY_PY_SYS_PATH size_t path_num; mp_obj_t *path_items; mp_obj_get_array(mp_sys_path, &path_num, &path_items); @@ -153,8 +154,8 @@ STATIC mp_import_stat_t stat_top_level(qstr mod_name, vstr_t *dest) { } #if MICROPY_MODULE_FROZEN_STR || MICROPY_ENABLE_COMPILER -STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { - #if MICROPY_PY___FILE__ +static void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { + #if MICROPY_MODULE___FILE__ qstr source_name = lex->source_name; mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #endif @@ -166,8 +167,8 @@ STATIC void do_load_from_lexer(mp_module_context_t *context, mp_lexer_t *lex) { #endif #if (MICROPY_HAS_FILE_READER && MICROPY_PERSISTENT_CODE_LOAD) || MICROPY_MODULE_FROZEN_MPY -STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw_code_t *rc, qstr source_name) { - #if MICROPY_PY___FILE__ +static void do_execute_proto_fun(const mp_module_context_t *context, mp_proto_fun_t proto_fun, qstr source_name) { + #if MICROPY_MODULE___FILE__ mp_store_attr(MP_OBJ_FROM_PTR(&context->module), MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); #else (void)source_name; @@ -189,7 +190,7 @@ STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw nlr_push_jump_callback(&ctx.callback, mp_globals_locals_set_from_nlr_jump_callback); // make and execute the function - mp_obj_t module_fun = mp_make_function_from_raw_code(rc, context, NULL); + mp_obj_t module_fun = mp_make_function_from_proto_fun(proto_fun, context, NULL); mp_call_function_0(module_fun); // deregister exception handler and restore context @@ -197,7 +198,7 @@ STATIC void do_execute_raw_code(const mp_module_context_t *context, const mp_raw } #endif -STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { +static void do_load(mp_module_context_t *module_obj, vstr_t *file) { #if MICROPY_MODULE_FROZEN || MICROPY_ENABLE_COMPILER || (MICROPY_PERSISTENT_CODE_LOAD && MICROPY_HAS_FILE_READER) const char *file_str = vstr_null_terminated_str(file); #endif @@ -226,12 +227,12 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { if (frozen_type == MP_FROZEN_MPY) { const mp_frozen_module_t *frozen = modref; module_obj->constants = frozen->constants; - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ qstr frozen_file_qstr = qstr_from_str(file_str + frozen_path_prefix_len); #else qstr frozen_file_qstr = MP_QSTRnull; #endif - do_execute_raw_code(module_obj, frozen->rc, frozen_file_qstr); + do_execute_proto_fun(module_obj, frozen->proto_fun, frozen_file_qstr); return; } #endif @@ -248,7 +249,7 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { mp_compiled_module_t cm; cm.context = module_obj; mp_raw_code_load_file(file_qstr, &cm); - do_execute_raw_code(cm.context, cm.rc, file_qstr); + do_execute_proto_fun(cm.context, cm.rc, file_qstr); return; } #endif @@ -269,7 +270,7 @@ STATIC void do_load(mp_module_context_t *module_obj, vstr_t *file) { // Convert a relative (to the current module) import, going up "level" levels, // into an absolute import. -STATIC void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len) { +static void evaluate_relative_import(mp_int_t level, const char **module_name, size_t *module_name_len, mp_obj_t globals) { // What we want to do here is to take the name of the current module, // remove trailing components, and concatenate the passed-in // module name. @@ -278,7 +279,7 @@ STATIC void evaluate_relative_import(mp_int_t level, const char **module_name, s // module's position in the package hierarchy." // http://legacy.python.org/dev/peps/pep-0328/#relative-imports-and-name - mp_obj_t current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__)); + mp_obj_t current_module_name_obj = mp_obj_dict_get(globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__)); assert(current_module_name_obj != MP_OBJ_NULL); #if MICROPY_MODULE_OVERRIDE_MAIN_IMPORT && MICROPY_CPYTHON_COMPAT @@ -286,12 +287,12 @@ STATIC void evaluate_relative_import(mp_int_t level, const char **module_name, s // This is a module loaded by -m command-line switch (e.g. unix port), // and so its __name__ has been set to "__main__". Get its real name // that we stored during import in the __main__ attribute. - current_module_name_obj = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__)); + current_module_name_obj = mp_obj_dict_get(globals, MP_OBJ_NEW_QSTR(MP_QSTR___main__)); } #endif // If we have a __path__ in the globals dict, then we're a package. - bool is_pkg = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); + bool is_pkg = mp_map_lookup(mp_obj_dict_get_map(globals), MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP); #if DEBUG_PRINT DEBUG_printf("Current module/package: "); @@ -352,7 +353,7 @@ typedef struct _nlr_jump_callback_node_unregister_module_t { qstr name; } nlr_jump_callback_node_unregister_module_t; -STATIC void unregister_module_from_nlr_jump_callback(void *ctx_in) { +static void unregister_module_from_nlr_jump_callback(void *ctx_in) { nlr_jump_callback_node_unregister_module_t *ctx = ctx_in; mp_map_t *mp_loaded_modules_map = &MP_STATE_VM(mp_loaded_modules_dict).map; mp_map_lookup(mp_loaded_modules_map, MP_OBJ_NEW_QSTR(ctx->name), MP_MAP_LOOKUP_REMOVE_IF_FOUND); @@ -365,11 +366,11 @@ STATIC void unregister_module_from_nlr_jump_callback(void *ctx_in) { // attribute on it) (or MP_OBJ_NULL for top-level). // override_main: Whether to set the __name__ to "__main__" (and use __main__ // for the actual path). -STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, mp_obj_t outer_module_obj, bool override_main) { +static mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, mp_obj_t outer_module_obj, bool override_main) { // Immediately return if the module at this level is already loaded. mp_map_elem_t *elem; - #if MICROPY_PY_SYS + #if MICROPY_PY_SYS && MICROPY_PY_SYS_PATH // If sys.path is empty, the intention is to force using a built-in. This // means we should also ignore any loaded modules with the same name // which may have come from the filesystem. @@ -405,6 +406,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, // all the locations in sys.path. stat = stat_top_level(level_mod_name, &path); + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES // If filesystem failed, now try and see if it matches an extensible // built-in module. if (stat == MP_IMPORT_STAT_NO_EXIST) { @@ -413,6 +415,7 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, return module_obj; } } + #endif } else { DEBUG_printf("Searching for sub-module\n"); @@ -450,7 +453,9 @@ STATIC mp_obj_t process_import_at_level(qstr full_mod_name, qstr level_mod_name, if (stat == MP_IMPORT_STAT_NO_EXIST) { // Not found -- fail. - #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE + // CIRCUITPY-CHANGE: always the use more verbose error message that names missing module. + // Otherwise `import a` where `a` imports `b`, but `b` is missing will give a confusing error. + #if 0 && (MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE) mp_raise_msg(&mp_type_ImportError, MP_ERROR_TEXT("module not found")); #else mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("no module named '%q'"), full_mod_name); @@ -574,10 +579,19 @@ mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { const char *module_name = mp_obj_str_get_data(module_name_obj, &module_name_len); if (level != 0) { + // This is the dict with all global symbols. + mp_obj_t globals = MP_OBJ_FROM_PTR(mp_globals_get()); + if (n_args >= 2 && args[1] != mp_const_none) { + globals = args[1]; + if (!mp_obj_is_type(globals, &mp_type_dict)) { + mp_raise_TypeError(NULL); + } + } + // Turn "foo.bar" with level=3 into ".foo.bar". // Current module name is extracted from globals().__name__. - evaluate_relative_import(level, &module_name, &module_name_len); // module_name is now an absolute module path. + evaluate_relative_import(level, &module_name, &module_name_len, globals); } if (module_name_len == 0) { @@ -653,11 +667,13 @@ mp_obj_t mp_builtin___import___default(size_t n_args, const mp_obj_t *args) { if (module_obj != MP_OBJ_NULL) { return module_obj; } + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES // Now try as an extensible built-in (e.g. `time`). module_obj = mp_module_get_builtin(module_name_qstr, true); if (module_obj != MP_OBJ_NULL) { return module_obj; } + #endif // Couldn't find the module, so fail #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index 6d7848997cac2..e0ad8fa81bc10 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -131,12 +131,24 @@ endif ifeq ($(CIRCUITPY_AUDIOCORE),1) SRC_PATTERNS += audiocore/% endif +ifeq ($(CIRCUITPY_AUDIODELAYS),1) +SRC_PATTERNS += audiodelays/% +endif +ifeq ($(CIRCUITPY_AUDIOFILTERS),1) +SRC_PATTERNS += audiofilters/% +endif +ifeq ($(CIRCUITPY_AUDIOFREEVERB),1) +SRC_PATTERNS += audiofreeverb/% +endif ifeq ($(CIRCUITPY_AUDIOMIXER),1) SRC_PATTERNS += audiomixer/% endif ifeq ($(CIRCUITPY_AUDIOMP3),1) SRC_PATTERNS += audiomp3/% endif +ifeq ($(CIRCUITPY_AUDIOSPEED),1) +SRC_PATTERNS += audiospeed/% +endif ifeq ($(CIRCUITPY_AURORA_EPAPER),1) SRC_PATTERNS += aurora_epaper/% endif @@ -156,7 +168,7 @@ endif ifeq ($(CIRCUITPY_BITOPS),1) SRC_PATTERNS += bitops/% endif -ifeq ($(CIRCUITPY_BLEIO),1) +ifeq ($(CIRCUITPY_BLEIO_NATIVE),1) SRC_PATTERNS += _bleio/% endif ifeq ($(CIRCUITPY_BOARD),1) @@ -192,6 +204,12 @@ endif ifeq ($(CIRCUITPY_DISPLAYIO),1) SRC_PATTERNS += displayio/% endif +ifeq ($(CIRCUITPY_DOTCLOCKFRAMEBUFFER),1) +SRC_PATTERNS += dotclockframebuffer/% +endif +ifeq ($(CIRCUITPY_DUALBANK),1) +SRC_PATTERNS += dualbank/% +endif ifeq ($(CIRCUITPY__EVE),1) SRC_PATTERNS += _eve/% endif @@ -243,6 +261,9 @@ endif ifeq ($(CIRCUITPY_I2CTARGET),1) SRC_PATTERNS += i2ctarget/% endif +ifeq ($(CIRCUITPY_I2CIOEXPANDER),1) +SRC_PATTERNS += i2cioexpander/% +endif ifeq ($(CIRCUITPY_IMAGECAPTURE),1) SRC_PATTERNS += imagecapture/% endif @@ -270,6 +291,12 @@ endif ifeq ($(CIRCUITPY_MAX3421E),1) SRC_PATTERNS += max3421e/% endif +ifeq ($(CIRCUITPY_MCP4822),1) +SRC_PATTERNS += mcp4822/% +endif +ifeq ($(CIRCUITPY_MDNS),1) +SRC_PATTERNS += mdns/% +endif ifeq ($(CIRCUITPY_MEMORYMAP),1) SRC_PATTERNS += memorymap/% endif @@ -279,8 +306,8 @@ endif ifeq ($(CIRCUITPY_MICROCONTROLLER),1) SRC_PATTERNS += microcontroller/% endif -ifeq ($(CIRCUITPY_MDNS),1) -SRC_PATTERNS += mdns/% +ifeq ($(CIRCUITPY_MIPIDSI),1) +SRC_PATTERNS += mipidsi/% endif ifeq ($(CIRCUITPY_MSGPACK),1) SRC_PATTERNS += msgpack/% @@ -297,9 +324,6 @@ endif ifeq ($(CIRCUITPY_OS),1) SRC_PATTERNS += os/% endif -ifeq ($(CIRCUITPY_DUALBANK),1) -SRC_PATTERNS += dualbank/% -endif ifeq ($(CIRCUITPY_PARALLELDISPLAYBUS),1) SRC_PATTERNS += paralleldisplaybus/% endif @@ -333,11 +357,14 @@ endif ifeq ($(CIRCUITPY_RANDOM),1) SRC_PATTERNS += random/% endif +ifeq ($(CIRCUITPY_RCLCPY),1) +SRC_PATTERNS += rclcpy/% +endif ifeq ($(CIRCUITPY_RGBMATRIX),1) SRC_PATTERNS += rgbmatrix/% endif -ifeq ($(CIRCUITPY_DOTCLOCKFRAMEBUFFER),1) -SRC_PATTERNS += dotclockframebuffer/% +ifeq ($(CIRCUITPY_QSPIBUS),1) +SRC_PATTERNS += qspibus/% endif ifeq ($(CIRCUITPY_RP2PIO),1) SRC_PATTERNS += rp2pio/% @@ -363,6 +390,9 @@ endif ifeq ($(CIRCUITPY_SOCKETPOOL),1) SRC_PATTERNS += socketpool/% endif +ifeq ($(CIRCUITPY_SPITARGET),1) +SRC_PATTERNS += spitarget/% +endif ifeq ($(CIRCUITPY_SSL),1) SRC_PATTERNS += ssl/% endif @@ -387,6 +417,12 @@ endif ifeq ($(CIRCUITPY_FONTIO),1) SRC_PATTERNS += fontio/% endif +ifeq ($(CIRCUITPY_LVFONTIO),1) +SRC_PATTERNS += lvfontio/% +endif +ifeq ($(CIRCUITPY_TILEPALETTEMAPPER),1) +SRC_PATTERNS += tilepalettemapper/% +endif ifeq ($(CIRCUITPY_TIME),1) SRC_PATTERNS += time/% endif @@ -502,6 +538,8 @@ SRC_COMMON_HAL_ALL = \ i2ctarget/I2CTarget.c \ i2ctarget/__init__.c \ max3421e/Max3421E.c \ + mcp4822/__init__.c \ + mcp4822/MCP4822.c \ memorymap/__init__.c \ memorymap/AddressRange.c \ microcontroller/__init__.c \ @@ -510,6 +548,9 @@ SRC_COMMON_HAL_ALL = \ mdns/__init__.c \ mdns/Server.c \ mdns/RemoteService.c \ + mipidsi/Bus.c \ + mipidsi/Display.c \ + mipidsi/__init__.c \ neopixel_write/__init__.c \ nvm/ByteArray.c \ nvm/__init__.c \ @@ -522,6 +563,11 @@ SRC_COMMON_HAL_ALL = \ pulseio/__init__.c \ pwmio/PWMOut.c \ pwmio/__init__.c \ + qspibus/QSPIBus.c \ + qspibus/__init__.c \ + rclcpy/__init__.c \ + rclcpy/Node.c \ + rclcpy/Publisher.c \ rgbmatrix/RGBMatrix.c \ rgbmatrix/__init__.c \ rotaryio/IncrementalEncoder.c \ @@ -533,6 +579,8 @@ SRC_COMMON_HAL_ALL = \ socketpool/__init__.c \ socketpool/SocketPool.c \ socketpool/Socket.c \ + spitarget/SPITarget.c \ + spitarget/__init__.c \ usb_host/__init__.c \ usb_host/Port.c \ watchdog/WatchDogMode.c \ @@ -544,16 +592,28 @@ SRC_COMMON_HAL_ALL = \ wifi/ScannedNetworks.c \ wifi/__init__.c \ -ifeq ($(CIRCUITPY_BLEIO_HCI),1) -# Helper code for _bleio HCI. -SRC_C += \ - common-hal/_bleio/att.c \ - common-hal/_bleio/hci.c \ +SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) +ifeq ($(CIRCUITPY_BLEIO_HCI),1) +# HCI device-specific HAL and helper sources. +SRC_DEVICES_HAL += \ + _bleio/att.c \ + _bleio/hci.c \ + _bleio/Adapter.c \ + _bleio/Attribute.c \ + _bleio/Characteristic.c \ + _bleio/CharacteristicBuffer.c \ + _bleio/Connection.c \ + _bleio/Descriptor.c \ + _bleio/PacketBuffer.c \ + _bleio/Service.c \ + _bleio/UUID.c \ + _bleio/__init__.c +# HCI device-specific bindings. +SRC_DEVICES_BINDINGS += \ + supervisor/bluetooth.c endif -SRC_COMMON_HAL = $(filter $(SRC_PATTERNS), $(SRC_COMMON_HAL_ALL)) - # These don't have corresponding files in each port but are still located in # shared-bindings to make it clear what the contents of the modules are. # All possible sources are listed here, and are filtered by SRC_PATTERNS. @@ -568,6 +628,7 @@ $(filter $(SRC_PATTERNS), \ canio/Match.c \ codeop/__init__.c \ countio/Edge.c \ + digitalio/DigitalInOutProtocol.c \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ @@ -588,8 +649,26 @@ $(filter $(SRC_PATTERNS), \ supervisor/StatusBar.c \ wifi/AuthMode.c \ wifi/Packet.c \ + wifi/PowerManagement.c \ ) +ifeq ($(CIRCUITPY_BLEIO_HCI),1) +# Common _bleio bindings used by HCI. +SRC_BINDINGS_ENUMS += \ + _bleio/Address.c \ + _bleio/Adapter.c \ + _bleio/Attribute.c \ + _bleio/Characteristic.c \ + _bleio/CharacteristicBuffer.c \ + _bleio/Connection.c \ + _bleio/Descriptor.c \ + _bleio/PacketBuffer.c \ + _bleio/ScanEntry.c \ + _bleio/Service.c \ + _bleio/UUID.c \ + _bleio/__init__.c +endif + ifeq ($(CIRCUITPY_SAFEMODE_PY),1) SRC_BINDINGS_ENUMS += \ supervisor/SafeModeReason.c @@ -617,6 +696,19 @@ SRC_SHARED_MODULE_ALL = \ audiocore/RawSample.c \ audiocore/WaveFile.c \ audiocore/__init__.c \ + audiospeed/SpeedChanger.c \ + audiospeed/__init__.c \ + audiodelays/Echo.c \ + audiodelays/Chorus.c \ + audiodelays/PitchShift.c \ + audiodelays/MultiTapDelay.c \ + audiodelays/__init__.c \ + audiofilters/Distortion.c \ + audiofilters/Filter.c \ + audiofilters/Phaser.c \ + audiofilters/__init__.c \ + audiofreeverb/__init__.c \ + audiofreeverb/Freeverb.c \ audioio/__init__.c \ audiomixer/Mixer.c \ audiomixer/MixerVoice.c \ @@ -652,9 +744,14 @@ SRC_SHARED_MODULE_ALL = \ dotclockframebuffer/__init__.c \ epaperdisplay/__init__.c \ epaperdisplay/EPaperDisplay.c \ + i2cioexpander/IOExpander.c \ + i2cioexpander/IOPin.c \ + i2cioexpander/__init__.c \ floppyio/__init__.c \ fontio/BuiltinFont.c \ fontio/__init__.c \ + lvfontio/OnDiskFont.c\ + lvfontio/__init__.c \ fourwire/__init__.c \ fourwire/FourWire.c \ framebufferio/FramebufferDisplay.c \ @@ -715,12 +812,15 @@ SRC_SHARED_MODULE_ALL = \ synthio/__init__.c \ terminalio/Terminal.c \ terminalio/__init__.c \ + tilepalettemapper/__init__.c \ + tilepalettemapper/TilePaletteMapper.c \ time/__init__.c \ traceback/__init__.c \ uheap/__init__.c \ usb/__init__.c \ usb/core/__init__.c \ usb/core/Device.c \ + usb/util/__init__.c \ ustack/__init__.c \ vectorio/Circle.c \ vectorio/Polygon.c \ @@ -734,6 +834,21 @@ SRC_SHARED_MODULE_ALL = \ # All possible sources are listed here, and are filtered by SRC_PATTERNS. SRC_SHARED_MODULE = $(filter $(SRC_PATTERNS), $(SRC_SHARED_MODULE_ALL)) +SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ + $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ + $(addprefix common-hal/, $(SRC_COMMON_HAL)) \ + $(addprefix devices/ble_hci/common-hal/, $(SRC_DEVICES_HAL)) \ + $(addprefix devices/ble_hci/, $(SRC_DEVICES_BINDINGS)) + +SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ + $(addprefix shared-module/, $(SRC_SHARED_MODULE)) \ + $(addprefix shared-module/, $(SRC_SHARED_MODULE_INTERNAL)) + +# There may be duplicates between SRC_COMMON_HAL_EXPANDED and SRC_SHARED_MODULE_EXPANDED, +# because a few modules have files both in common-hal/ and shared-module/. +# Doing a $(sort ...) removes duplicates as part of sorting. +SRC_COMMON_HAL_SHARED_MODULE_EXPANDED = $(sort $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)) + # Use the native touchio if requested. This flag is set conditionally in, say, mpconfigport.h. # The presence of common-hal/touchio/* does not imply it's available for all chips in a port, # so there is an explicit flag. For example, SAMD21 touchio is native, but SAMD51 is not. @@ -765,11 +880,15 @@ SRC_SHARED_MODULE_ALL += \ keypad_demux/DemuxKeyMatrix.c endif -# If supporting _bleio via HCI, make devices/ble_hci/common-hal/_bleio be includable, -# and use C source files in devices/ble_hci/common-hal. ifeq ($(CIRCUITPY_BLEIO_HCI),1) +# Add HCI device-specific includes to search path. INC += -I$(TOP)/devices/ble_hci -DEVICES_MODULES += $(TOP)/devices/ble_hci +# Add HCI shared modules to build. +SRC_SHARED_MODULE += \ + _bleio/Address.c \ + _bleio/Attribute.c \ + _bleio/ScanEntry.c \ + _bleio/ScanResults.c endif ifeq ($(CIRCUITPY_AUDIOMP3),1) @@ -855,15 +974,9 @@ SRC_SHARED_MODULE_INTERNAL = \ $(filter $(SRC_PATTERNS), \ displayio/bus_core.c \ displayio/display_core.c \ - os/getenv.c \ usb/utf16le.c \ ) -SRC_COMMON_HAL_INTERNAL = \ -$(filter $(SRC_PATTERNS), \ - _bleio/ \ -) - ifeq ($(INTERNAL_LIBM),1) SRC_LIBM = \ $(addprefix lib/,\ @@ -906,7 +1019,6 @@ endif # Sources used in all ports except unix. SRC_CIRCUITPY_COMMON = \ - shared/libc/string0.c \ shared/readline/readline.c \ lib/oofatfs/ff.c \ lib/oofatfs/ffunicode.c \ @@ -918,9 +1030,13 @@ SRC_CIRCUITPY_COMMON = \ shared/runtime/stdout_helpers.c \ shared/runtime/sys_stdio_mphal.c +ifeq ($(CIRCUITPY_LIBC_STRING0),1) +SRC_CIRCUITPY_COMMON += shared/libc/string0.c +endif + ifeq ($(CIRCUITPY_QRIO),1) SRC_CIRCUITPY_COMMON += lib/quirc/lib/decode.c lib/quirc/lib/identify.c lib/quirc/lib/quirc.c lib/quirc/lib/version_db.c -$(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h +$(BUILD)/lib/quirc/lib/%.o: CFLAGS += -Wno-type-limits -Wno-shadow -Wno-sign-compare -include shared-module/qrio/quirc_alloc.h endif ifdef LD_TEMPLATE_FILE diff --git a/py/circuitpy_mkenv.mk b/py/circuitpy_mkenv.mk index 7bdf943a14d04..6416d6bd19cfb 100644 --- a/py/circuitpy_mkenv.mk +++ b/py/circuitpy_mkenv.mk @@ -43,6 +43,10 @@ ifneq ($(VALID_BOARD),) include boards/$(BOARD)/mpconfigboard.mk endif +# user-specific settings that mpconfigport does not override +# (i.e. mpconfigport.mk uses "foo ?= bar") +-include user_pre_mpconfigport.mk + # Port-specific include mpconfigport.mk @@ -52,6 +56,10 @@ ifneq ($(VALID_BOARD),) include $(TOP)/py/circuitpy_mpconfig.mk endif +# user-specific overrides of hard-coded settings +# (i.e. xxx.mk uses "foo = bar") +-include user_post_mpconfigport.mk + # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h @@ -62,3 +70,6 @@ include $(TOP)/supervisor/supervisor.mk # Include make rules and variables common across CircuitPython builds. include $(TOP)/py/circuitpy_defns.mk + +# user specific +-include user_post_circuitpy_defns.mk diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h index 648853d2f45f3..4b23784c5416c 100644 --- a/py/circuitpy_mpconfig.h +++ b/py/circuitpy_mpconfig.h @@ -17,10 +17,8 @@ // Always 1: defined in circuitpy_mpconfig.mk // #define CIRCUITPY (1) -// Can be removed once CircuitPython 10 is released. -// Print warnings or not about deprecated names. See objmodule.c. -#ifndef CIRCUITPY_8_9_WARNINGS -#define CIRCUITPY_8_9_WARNINGS (0) +#ifndef MP_SSIZE_MAX +#define MP_SSIZE_MAX (0x7fffffff) #endif // REPR_C encodes qstrs, 31-bit ints, and 30-bit floats in a single 32-bit word. @@ -43,13 +41,23 @@ extern void common_hal_mcu_enable_interrupts(void); // MicroPython-only options not used by CircuitPython, but present in various files // inherited from MicroPython, especially in extmod/ #define MICROPY_ENABLE_DYNRUNTIME (0) +#define MICROPY_HW_ENABLE_USB (0) +#define MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE (0) #define MICROPY_PY_BLUETOOTH (0) #define MICROPY_PY_LWIP_SLIP (0) #define MICROPY_PY_OS_DUPTERM (0) +#define MICROPY_PYEXEC_COMPILE_ONLY (0) #define MICROPY_ROM_TEXT_COMPRESSION (0) #define MICROPY_VFS_LFS1 (0) #define MICROPY_VFS_LFS2 (0) +// Always turn on exit code handling +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (1) + +#ifndef MICROPY_GCREGS_SETJMP +#define MICROPY_GCREGS_SETJMP (0) +#endif + // Sorted alphabetically for easy finding. // // default is 128; consider raising to reduce fragmentation. @@ -67,6 +75,7 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_EMIT_X64 (0) #define MICROPY_ENABLE_DOC_STRING (0) #define MICROPY_ENABLE_FINALISER (1) +#define MICROPY_ENABLE_SELECTIVE_COLLECT (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_ENABLE_PYSTACK (1) #define MICROPY_TRACKED_ALLOC (CIRCUITPY_SSL_MBEDTLS) @@ -87,11 +96,11 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_MEM_STATS (0) #define MICROPY_MODULE_BUILTIN_INIT (1) #define MICROPY_MODULE_BUILTIN_SUBPACKAGES (1) -#define MICROPY_NONSTANDARD_TYPECODES (0) #define MICROPY_OPT_COMPUTED_GOTO (1) #define MICROPY_OPT_COMPUTED_GOTO_SAVE_SPACE (CIRCUITPY_COMPUTED_GOTO_SAVE_SPACE) #define MICROPY_OPT_LOAD_ATTR_FAST_PATH (CIRCUITPY_OPT_LOAD_ATTR_FAST_PATH) #define MICROPY_OPT_MAP_LOOKUP_CACHE (CIRCUITPY_OPT_MAP_LOOKUP_CACHE) +#define MICROPY_OPT_MPZ_BITWISE (0) #define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (CIRCUITPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE) #define MICROPY_PERSISTENT_CODE_LOAD (1) @@ -139,12 +148,20 @@ extern void common_hal_mcu_enable_interrupts(void); #define MICROPY_PY_RE (CIRCUITPY_RE) // Supplanted by shared-bindings/struct #define MICROPY_PY_STRUCT (0) +#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (0) #define MICROPY_PY_SYS (CIRCUITPY_SYS) #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_UCTYPES (0) #define MICROPY_PY___FILE__ (1) +#if CIRCUITPY_FULL_BUILD +#ifndef MICROPY_QSTR_BYTES_IN_HASH #define MICROPY_QSTR_BYTES_IN_HASH (1) +#endif +#else +#define MICROPY_QSTR_BYTES_IN_HASH (0) +#endif #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_STACK_CHECK (1) @@ -184,21 +201,6 @@ extern void common_hal_mcu_enable_interrupts(void); // Track stack usage. Expose results via ustack module. #define MICROPY_MAX_STACK_USAGE (0) -#define UINT_FMT "%u" -#define INT_FMT "%d" -#ifdef __LP64__ -typedef long mp_int_t; // must be pointer size -typedef unsigned long mp_uint_t; // must be pointer size -#else -// These are definitions for machines where sizeof(int) == sizeof(void*), -// regardless of actual size. -typedef int mp_int_t; // must be pointer size -typedef unsigned int mp_uint_t; // must be pointer size -#endif -#if __GNUC__ >= 10 // on recent gcc versions we can check that this is so -_Static_assert(sizeof(mp_int_t) == sizeof(void *)); -_Static_assert(sizeof(mp_uint_t) == sizeof(void *)); -#endif typedef long mp_off_t; #define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len) @@ -222,31 +224,56 @@ typedef long mp_off_t; // Turning off FULL_BUILD removes some functionality to reduce flash size on tiny SAMD21s #define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (CIRCUITPY_FULL_BUILD) + #ifndef MICROPY_CPYTHON_COMPAT #define MICROPY_CPYTHON_COMPAT (CIRCUITPY_FULL_BUILD) #endif + #ifndef MICROPY_CPYTHON_EXCEPTION_CHAIN #define MICROPY_CPYTHON_EXCEPTION_CHAIN (CIRCUITPY_FULL_BUILD) #endif + #define MICROPY_PY_BUILTINS_POW3 (CIRCUITPY_BUILTINS_POW3) #define MICROPY_PY_FSTRINGS (1) #define MICROPY_MODULE_WEAK_LINKS (0) #define MICROPY_PY_ALL_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD) + #ifndef MICROPY_PY_BUILTINS_COMPLEX #define MICROPY_PY_BUILTINS_COMPLEX (CIRCUITPY_FULL_BUILD) #endif + #define MICROPY_PY_BUILTINS_FROZENSET (CIRCUITPY_FULL_BUILD) + +#ifndef MICROPY_PY_BUILTINS_NOTIMPLEMENTED +#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (CIRCUITPY_FULL_BUILD) +#endif + #define MICROPY_PY_BUILTINS_STR_CENTER (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_STR_PARTITION (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (CIRCUITPY_FULL_BUILD) + #ifndef MICROPY_PY_COLLECTIONS_ORDEREDDICT #define MICROPY_PY_COLLECTIONS_ORDEREDDICT (CIRCUITPY_FULL_BUILD) #endif + #ifndef MICROPY_PY_COLLECTIONS_DEQUE #define MICROPY_PY_COLLECTIONS_DEQUE (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_COLLECTIONS_DEQUE_ITER (CIRCUITPY_FULL_BUILD) #define MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR (CIRCUITPY_FULL_BUILD) #endif + +#ifndef MICROPY_PY_DOUBLE_TYPECODE +#define MICROPY_PY_DOUBLE_TYPECODE (CIRCUITPY_FULL_BUILD ? 1 : 0) +#endif + +#ifndef MICROPY_PY_FUNCTION_ATTRS +#define MICROPY_PY_FUNCTION_ATTRS (CIRCUITPY_FULL_BUILD) +#endif + +#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS +#define MICROPY_PY_REVERSE_SPECIAL_METHODS (CIRCUITPY_FULL_BUILD) +#endif + #define MICROPY_PY_RE_MATCH_GROUPS (CIRCUITPY_RE) #define MICROPY_PY_RE_MATCH_SPAN_START_END (CIRCUITPY_RE) #define MICROPY_PY_RE_SUB (CIRCUITPY_RE) @@ -269,28 +296,33 @@ typedef long mp_off_t; #ifdef LONGINT_IMPL_MPZ #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) -#define MP_SSIZE_MAX (0x7fffffff) #endif #ifdef LONGINT_IMPL_LONGLONG #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) -#define MP_SSIZE_MAX (0x7fffffff) #endif #ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS #define MICROPY_PY_REVERSE_SPECIAL_METHODS (CIRCUITPY_ULAB || CIRCUITPY_FULL_BUILD) #endif -#if INTERNAL_FLASH_FILESYSTEM == 0 && QSPI_FLASH_FILESYSTEM == 0 && SPI_FLASH_FILESYSTEM == 0 && !DISABLE_FILESYSTEM +#if !defined(__ZEPHYR__) && INTERNAL_FLASH_FILESYSTEM == 0 && QSPI_FLASH_FILESYSTEM == 0 && SPI_FLASH_FILESYSTEM == 0 && !DISABLE_FILESYSTEM #error No *_FLASH_FILESYSTEM set! #endif // Default board buses. +#ifndef CIRCUITPY_MUTABLE_BOARD +#define CIRCUITPY_MUTABLE_BOARD (0) +#endif + #ifndef CIRCUITPY_BOARD_I2C #if defined(DEFAULT_I2C_BUS_SCL) && defined(DEFAULT_I2C_BUS_SDA) #define CIRCUITPY_BOARD_I2C (1) #define CIRCUITPY_BOARD_I2C_PIN {{.scl = DEFAULT_I2C_BUS_SCL, .sda = DEFAULT_I2C_BUS_SDA}} +#ifndef CIRCUITPY_BOARD_I2C_SPEED +#define CIRCUITPY_BOARD_I2C_SPEED (100000) +#endif #else #define CIRCUITPY_BOARD_I2C (0) #endif @@ -315,6 +347,9 @@ typedef long mp_off_t; #endif +// For easy debugging printf's. +#define PLAT_PRINTF(...) mp_printf(&mp_plat_print, __VA_ARGS__) + #if MICROPY_PY_ASYNC_AWAIT && !CIRCUITPY_TRACEBACK #error CIRCUITPY_ASYNCIO requires CIRCUITPY_TRACEBACK #endif @@ -327,8 +362,19 @@ typedef long mp_off_t; #ifndef CIRCUITPY_CONSOLE_UART_BAUDRATE #define CIRCUITPY_CONSOLE_UART_BAUDRATE (115200) #endif +#if !defined(CIRCUITPY_CONSOLE_UART_PRINTF) +#define CIRCUITPY_CONSOLE_UART_PRINTF(...) mp_printf(&console_uart_print, __VA_ARGS__) +#endif +#if !defined(CIRCUITPY_CONSOLE_UART_HEXDUMP) +#define CIRCUITPY_CONSOLE_UART_HEXDUMP(pfx, buf, len) print_hexdump(&console_uart_print, pfx, (const uint8_t *)buf, len) +#endif +#if !defined(CIRCUITPY_CONSOLE_UART_TIMESTAMP) +#define CIRCUITPY_CONSOLE_UART_TIMESTAMP (0) +#endif #else #define CIRCUITPY_CONSOLE_UART (0) +#define CIRCUITPY_CONSOLE_UART_PRINTF(...) (void)0 +#define CIRCUITPY_CONSOLE_UART_HEXDUMP(...) (void)0 #endif // These CIRCUITPY_xxx values should all be defined in the *.mk files as being on or off. @@ -339,9 +385,11 @@ typedef long mp_off_t; #define CIRCUITPY_DISPLAY_LIMIT (1) #endif -// Framebuffer area size in bytes. Rounded down to power of four for alignment. +// Display area buffer size in bytes for _refresh_area() VLA. +// Allocated on stack; boards with larger displays can override per-board. +// Default 512 bytes = 128 uint32_t words. #ifndef CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE -#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (128) +#define CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE (512) #endif #else @@ -358,6 +406,11 @@ extern const struct _mp_obj_module_t nvm_module; #define ULAB_SUPPORTS_COMPLEX (0) #endif +// The random module is fairly large. +#ifndef ULAB_NUMPY_HAS_RANDOM_MODULE +#define ULAB_NUMPY_HAS_RANDOM_MODULE (0) +#endif + #if CIRCUITPY_ULAB // ulab requires reverse special methods #if defined(MICROPY_PY_REVERSE_SPECIAL_METHODS) && !MICROPY_PY_REVERSE_SPECIAL_METHODS @@ -407,6 +460,7 @@ void background_callback_run_all(void); #define MICROPY_VM_HOOK_LOOP RUN_BACKGROUND_TASKS; #define MICROPY_VM_HOOK_RETURN RUN_BACKGROUND_TASKS; +#define MICROPY_INTERNAL_EVENT_HOOK (RUN_BACKGROUND_TASKS) // CIRCUITPY_AUTORELOAD_DELAY_MS = 0 will completely disable autoreload. #ifndef CIRCUITPY_AUTORELOAD_DELAY_MS @@ -418,7 +472,7 @@ void background_callback_run_all(void); #endif #ifndef CIRCUITPY_PYSTACK_SIZE -#define CIRCUITPY_PYSTACK_SIZE 1536 +#define CIRCUITPY_PYSTACK_SIZE 2048 #endif // The VM heap starts at this size and doubles in size as needed until it runs @@ -467,6 +521,18 @@ void background_callback_run_all(void); // USB settings +#ifndef CIRCUITPY_SDCARD_USB +#if CIRCUITPY_USB_DEVICE +#define CIRCUITPY_SDCARD_USB (CIRCUITPY_SDCARDIO && CIRCUITPY_USB_MSC) +#else +#define CIRCUITPY_SDCARD_USB (0) +#endif +#endif + +#if CIRCUITPY_SDCARD_USB && !(CIRCUITPY_SDCARDIO) +#error CIRCUITPY_SDCARD_USB requires CIRCUITPY_SDCARDIO +#endif + // Debug level for TinyUSB. Only outputs over debug UART so it doesn't cause // additional USB logging. #ifndef CIRCUITPY_DEBUG_TINYUSB @@ -477,10 +543,18 @@ void background_callback_run_all(void); #define CIRCUITPY_USB_DEVICE_INSTANCE 0 #endif +#ifndef CIRCUITPY_USB_DEVICE_HIGH_SPEED +#define CIRCUITPY_USB_DEVICE_HIGH_SPEED 0 +#endif + #ifndef CIRCUITPY_USB_HOST_INSTANCE #define CIRCUITPY_USB_HOST_INSTANCE -1 #endif +#ifndef CIRCUITPY_USB_HOST_HIGH_SPEED +#define CIRCUITPY_USB_HOST_HIGH_SPEED 0 +#endif + // If the port requires certain USB endpoint numbers, define these in mpconfigport.h. #ifndef USB_CDC_EP_NUM_NOTIFICATION @@ -580,7 +654,7 @@ void background_callback_run_all(void); // Align the internal sector buffer. Useful when it is passed into TinyUSB for // loads. #ifndef MICROPY_FATFS_WINDOW_ALIGNMENT -#define MICROPY_FATFS_WINDOW_ALIGNMENT CIRCUITPY_TUSB_MEM_ALIGN +#define MICROPY_FATFS_WINDOW_ALIGNMENT 64 // Espressif is strictest #endif #define FF_FS_CASE_INSENSITIVE_COMPARISON_ASCII_ONLY (1) @@ -592,3 +666,32 @@ void background_callback_run_all(void); // Enable compiler functionality. #define MICROPY_ENABLE_COMPILER (1) #define MICROPY_PY_BUILTINS_COMPILE (1) + +#ifndef CIRCUITPY_MIN_GCC_VERSION +#define CIRCUITPY_MIN_GCC_VERSION 14 +#endif + +#ifndef CIRCUITPY_SAVES_PARTITION_SIZE +#define CIRCUITPY_SAVES_PARTITION_SIZE 0 +#endif + +// Boards that have a boot button connected to a GPIO pin should set +// CIRCUITPY_BOOT_BUTTON_NO_GPIO to 1. +#ifndef CIRCUITPY_BOOT_BUTTON_NO_GPIO +#define CIRCUITPY_BOOT_BUTTON_NO_GPIO (0) +#endif +#if defined(CIRCUITPY_BOOT_BUTTON) && CIRCUITPY_BOOT_BUTTON_NO_GPIO +#error "CIRCUITPY_BOOT_BUTTON and CIRCUITPY_BOOT_BUTTON_NO_GPIO are mutually exclusive" +#endif + +#if defined(__GNUC__) && !defined(__ZEPHYR__) +#if __GNUC__ < CIRCUITPY_MIN_GCC_VERSION +// (the 3 level scheme here is required to get expansion & stringization +// correct) +#define DO_PRAGMA(x) _Pragma(#x) +#define DO_ERROR_HELPER(x) DO_PRAGMA(GCC error #x) +#define DO_ERROR(x) DO_ERROR_HELPER(Minimum GCC version x \ + -- older versions are known to miscompile CircuitPython) +DO_ERROR(CIRCUITPY_MIN_GCC_VERSION); +#endif +#endif diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index 81d46270f8f9c..170122903286b 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -62,6 +62,15 @@ CFLAGS += -DCIRCUITPY_FULL_BUILD=$(CIRCUITPY_FULL_BUILD) # increased build time CIRCUITPY_MESSAGE_COMPRESSION_LEVEL ?= 9 +# By default, use our copy of TLSF. Some vendor SDKs may provide their own +# implementation of TLSF, which can be used instead by setting CIRCUITPY_LIB_TLSF=0. +CIRCUITPY_LIB_TLSF ?= 1 + +# By default, use our copy of string0 (memcpy and friends) because it is optimized. Some vendor SDKs +# or ROMs may provide their own implementation of string0, which can be used instead by setting +# CIRCUITPY_LIBC_STRING0=0. +CIRCUITPY_LIBC_STRING0 ?= 1 + # Reduce the size of in-flash properties. Requires support in the .ld linker # file, so not enabled by default. CIRCUITPY_OPTIMIZE_PROPERTY_FLASH_SIZE ?= 0 @@ -98,6 +107,11 @@ CFLAGS += -DCIRCUITPY_ALARM=$(CIRCUITPY_ALARM) CIRCUITPY_ALARM_TOUCH ?= $(CIRCUITPY_ALARM) CFLAGS += -DCIRCUITPY_ALARM_TOUCH=$(CIRCUITPY_ALARM_TOUCH) +# Enable DMA buffer management for platforms where not all memory is DMA-capable +# Platforms with PSRAM or other non-DMA memory should set this to 0 +CIRCUITPY_ALL_MEMORY_DMA_CAPABLE ?= 1 +CFLAGS += -DCIRCUITPY_ALL_MEMORY_DMA_CAPABLE=$(CIRCUITPY_ALL_MEMORY_DMA_CAPABLE) + CIRCUITPY_ANALOGBUFIO ?= 0 CFLAGS += -DCIRCUITPY_ANALOGBUFIO=$(CIRCUITPY_ANALOGBUFIO) @@ -141,6 +155,14 @@ CFLAGS += -DCIRCUITPY_AUDIOCORE_DEBUG=$(CIRCUITPY_AUDIOCORE_DEBUG) CIRCUITPY_AUDIOMP3 ?= $(call enable-if-all,$(CIRCUITPY_FULL_BUILD) $(CIRCUITPY_AUDIOCORE)) CFLAGS += -DCIRCUITPY_AUDIOMP3=$(CIRCUITPY_AUDIOMP3) +CIRCUITPY_AUDIOEFFECTS ?= 0 +CIRCUITPY_AUDIODELAYS ?= $(CIRCUITPY_AUDIOEFFECTS) +CFLAGS += -DCIRCUITPY_AUDIODELAYS=$(CIRCUITPY_AUDIODELAYS) +CIRCUITPY_AUDIOFILTERS ?= $(CIRCUITPY_AUDIOEFFECTS) +CFLAGS += -DCIRCUITPY_AUDIOFILTERS=$(CIRCUITPY_AUDIOFILTERS) +CIRCUITPY_AUDIOFREEVERB ?= $(CIRCUITPY_AUDIOEFFECTS) +CFLAGS += -DCIRCUITPY_AUDIOFREEVERB=$(CIRCUITPY_AUDIOFREEVERB) + CIRCUITPY_AURORA_EPAPER ?= 0 CFLAGS += -DCIRCUITPY_AURORA_EPAPER=$(CIRCUITPY_AURORA_EPAPER) @@ -156,12 +178,19 @@ CFLAGS += -DCIRCUITPY_BITBANGIO=$(CIRCUITPY_BITBANGIO) CIRCUITPY_BITOPS ?= 0 CFLAGS += -DCIRCUITPY_BITOPS=$(CIRCUITPY_BITOPS) -# _bleio can be supported on most any board via HCI +# _bleio defaults to HCI serial for all full builds. CIRCUITPY_BLEIO_HCI ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_BLEIO_HCI=$(CIRCUITPY_BLEIO_HCI) -# Explicitly enabled for boards that support _bleio. -CIRCUITPY_BLEIO ?= $(CIRCUITPY_BLEIO_HCI) +# Native (i.e., on SoC or board) BLE support is off by default. +CIRCUITPY_BLEIO_NATIVE ?= 0 +CFLAGS += -DCIRCUITPY_BLEIO_NATIVE=$(CIRCUITPY_BLEIO_NATIVE) + +ifeq ($(CIRCUITPY_BLEIO_HCI)$(CIRCUITPY_BLEIO_NATIVE),11) +$(error "CIRCUITPY_BLEIO_HCI and CIRCUITPY_BLEIO_NATIVE cannot both be enabled") +endif + +CIRCUITPY_BLEIO ?= $(call enable-if-any,$(CIRCUITPY_BLEIO_HCI) $(CIRCUITPY_BLEIO_NATIVE)) CFLAGS += -DCIRCUITPY_BLEIO=$(CIRCUITPY_BLEIO) CIRCUITPY_BLE_FILE_SERVICE ?= 0 @@ -212,6 +241,12 @@ CFLAGS += -DCIRCUITPY_CYW43=$(CIRCUITPY_CYW43) CIRCUITPY_DIGITALIO ?= 1 CFLAGS += -DCIRCUITPY_DIGITALIO=$(CIRCUITPY_DIGITALIO) +# Enable the DigitalInOut protocol on the native DigitalInOut type. +# This allows other C code to use DigitalInOut objects polymorphically. +# Disable on small builds to save space. +CIRCUITPY_DIGITALINOUT_PROTOCOL ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DCIRCUITPY_DIGITALINOUT_PROTOCOL=$(CIRCUITPY_DIGITALINOUT_PROTOCOL) + CIRCUITPY_COPROC ?= 0 CFLAGS += -DCIRCUITPY_COPROC=$(CIRCUITPY_COPROC) @@ -227,6 +262,10 @@ CFLAGS += -DCIRCUITPY_BUSDISPLAY=$(CIRCUITPY_BUSDISPLAY) CIRCUITPY_FOURWIRE ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_FOURWIRE=$(CIRCUITPY_FOURWIRE) +# QSPI bus protocol for quad-SPI displays (like RM690B0) +CIRCUITPY_QSPIBUS ?= 0 +CFLAGS += -DCIRCUITPY_QSPIBUS=$(CIRCUITPY_QSPIBUS) + CIRCUITPY_EPAPERDISPLAY ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_EPAPERDISPLAY=$(CIRCUITPY_EPAPERDISPLAY) @@ -260,9 +299,6 @@ CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK) CIRCUITPY_ENABLE_MPY_NATIVE ?= 0 CFLAGS += -DCIRCUITPY_ENABLE_MPY_NATIVE=$(CIRCUITPY_ENABLE_MPY_NATIVE) -CIRCUITPY_OS_GETENV ?= $(CIRCUITPY_FULL_BUILD) -CFLAGS += -DCIRCUITPY_OS_GETENV=$(CIRCUITPY_OS_GETENV) - CIRCUITPY_ERRNO ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ERRNO=$(CIRCUITPY_ERRNO) @@ -314,9 +350,15 @@ CFLAGS += -DCIRCUITPY_HASHLIB_MBEDTLS=$(CIRCUITPY_HASHLIB_MBEDTLS) CIRCUITPY_HASHLIB_MBEDTLS_ONLY ?= $(call enable-if-all,$(CIRCUITPY_HASHLIB_MBEDTLS) $(call enable-if-not,$(CIRCUITPY_SSL))) CFLAGS += -DCIRCUITPY_HASHLIB_MBEDTLS_ONLY=$(CIRCUITPY_HASHLIB_MBEDTLS_ONLY) +# Always zero because it is for Zephyr only +CFLAGS += -DCIRCUITPY_HOSTNETWORK=0 + CIRCUITPY_I2CTARGET ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_I2CTARGET=$(CIRCUITPY_I2CTARGET) +CIRCUITPY_I2CIOEXPANDER ?= 0 +CFLAGS += -DCIRCUITPY_I2CIOEXPANDER=$(CIRCUITPY_I2CIOEXPANDER) + CIRCUITPY_IMAGECAPTURE ?= 0 CFLAGS += -DCIRCUITPY_IMAGECAPTURE=$(CIRCUITPY_IMAGECAPTURE) @@ -364,6 +406,9 @@ CFLAGS += -DCIRCUITPY_MATH=$(CIRCUITPY_MATH) CIRCUITPY_MAX3421E ?= 0 CFLAGS += -DCIRCUITPY_MAX3421E=$(CIRCUITPY_MAX3421E) +CIRCUITPY_MDNS ?= $(CIRCUITPY_WIFI) +CFLAGS += -DCIRCUITPY_MDNS=$(CIRCUITPY_MDNS) + CIRCUITPY_MEMORYMAP ?= 0 CFLAGS += -DCIRCUITPY_MEMORYMAP=$(CIRCUITPY_MEMORYMAP) @@ -373,8 +418,8 @@ CFLAGS += -DCIRCUITPY_MEMORYMONITOR=$(CIRCUITPY_MEMORYMONITOR) CIRCUITPY_MICROCONTROLLER ?= 1 CFLAGS += -DCIRCUITPY_MICROCONTROLLER=$(CIRCUITPY_MICROCONTROLLER) -CIRCUITPY_MDNS ?= $(CIRCUITPY_WIFI) -CFLAGS += -DCIRCUITPY_MDNS=$(CIRCUITPY_MDNS) +CIRCUITPY_MIPIDSI ?= 0 +CFLAGS += -DCIRCUITPY_MIPIDSI=$(CIRCUITPY_MIPIDSI) CIRCUITPY_MSGPACK ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_MSGPACK=$(CIRCUITPY_MSGPACK) @@ -411,6 +456,9 @@ CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF) CIRCUITPY_PIXELMAP ?= $(CIRCUITPY_PIXELBUF) CFLAGS += -DCIRCUITPY_PIXELMAP=$(CIRCUITPY_PIXELMAP) +CIRCUITPY_PORT_SERIAL ?= 0 +CFLAGS += -DCIRCUITPY_PORT_SERIAL=$(CIRCUITPY_PORT_SERIAL) + # Only for SAMD boards for the moment CIRCUITPY_PS2IO ?= 0 CFLAGS += -DCIRCUITPY_PS2IO=$(CIRCUITPY_PS2IO) @@ -436,6 +484,9 @@ CFLAGS += -DCIRCUITPY_RAINBOWIO=$(CIRCUITPY_RAINBOWIO) CIRCUITPY_RANDOM ?= 1 CFLAGS += -DCIRCUITPY_RANDOM=$(CIRCUITPY_RANDOM) +CIRCUITPY_RCLCPY ?= 0 +CFLAGS += -DCIRCUITPY_RCLCPY=$(CIRCUITPY_RCLCPY) + CIRCUITPY_RE ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_RE=$(CIRCUITPY_RE) @@ -488,6 +539,9 @@ CFLAGS += -DCIRCUITPY_SERIAL_BLE=$(CIRCUITPY_SERIAL_BLE) CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY?= 0 CFLAGS += -DCIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY=$(CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY) +CIRCUITPY_SETTINGS_TOML ?= $(CIRCUITPY_FULL_BUILD) +CFLAGS += -DCIRCUITPY_SETTINGS_TOML=$(CIRCUITPY_SETTINGS_TOML) + CIRCUITPY_SHARPDISPLAY ?= $(CIRCUITPY_FRAMEBUFFERIO) CFLAGS += -DCIRCUITPY_SHARPDISPLAY=$(CIRCUITPY_SHARPDISPLAY) @@ -499,6 +553,9 @@ CFLAGS += -DCIRCUITPY_SKIP_SAFE_MODE_WAIT=$(CIRCUITPY_SKIP_SAFE_MODE_WAIT) CIRCUITPY_SOCKETPOOL ?= $(CIRCUITPY_WIFI) CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL) +CIRCUITPY_SPITARGET ?= 0 +CFLAGS += -DCIRCUITPY_SPITARGET=$(CIRCUITPY_SPITARGET) + CIRCUITPY_SOCKETPOOL_IPV6 ?= 0 CFLAGS += -DCIRCUITPY_SOCKETPOOL_IPV6=$(CIRCUITPY_SOCKETPOOL_IPV6) @@ -540,9 +597,18 @@ CFLAGS += -DCIRCUITPY_SYS=$(CIRCUITPY_SYS) CIRCUITPY_TERMINALIO ?= $(CIRCUITPY_DISPLAYIO) CFLAGS += -DCIRCUITPY_TERMINALIO=$(CIRCUITPY_TERMINALIO) -CIRCUITPY_FONTIO ?= $(call enable-if-all,$(CIRCUITPY_DISPLAYIO) $(CIRCUITPY_TERMINALIO)) +CIRCUITPY_TERMINALIO_VT100 ?= $(CIRCUITPY_TERMINALIO) +CFLAGS += -DCIRCUITPY_TERMINALIO_VT100=$(CIRCUITPY_TERMINALIO_VT100) + +CIRCUITPY_FONTIO ?= $(CIRCUITPY_TERMINALIO) CFLAGS += -DCIRCUITPY_FONTIO=$(CIRCUITPY_FONTIO) +CIRCUITPY_LVFONTIO ?= $(CIRCUITPY_TERMINALIO) +CFLAGS += -DCIRCUITPY_LVFONTIO=$(CIRCUITPY_LVFONTIO) + +CIRCUITPY_TILEPALETTEMAPPER ?= $(CIRCUITPY_DISPLAYIO) +CFLAGS += -DCIRCUITPY_TILEPALETTEMAPPER=$(CIRCUITPY_TILEPALETTEMAPPER) + CIRCUITPY_TIME ?= 1 CFLAGS += -DCIRCUITPY_TIME=$(CIRCUITPY_TIME) @@ -644,6 +710,9 @@ CFLAGS += -DCIRCUITPY_USB_KEYBOARD_WORKFLOW=$(CIRCUITPY_USB_KEYBOARD_WORKFLOW) CIRCUITPY_USTACK ?= 0 CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK) +# Zephyr display integration is only built by ports/zephyr-cp. +CFLAGS += -DCIRCUITPY_ZEPHYR_DISPLAY=0 + # for decompressing utilities CIRCUITPY_ZLIB ?= $(CIRCUITPY_FULL_BUILD) CFLAGS += -DCIRCUITPY_ZLIB=$(CIRCUITPY_ZLIB) @@ -677,9 +746,6 @@ CFLAGS += -DCIRCUITPY_WEB_WORKFLOW=$(CIRCUITPY_WEB_WORKFLOW) CIRCUITPY_WIFI_RADIO_SETTABLE_MAC_ADDRESS?= 1 CFLAGS += -DCIRCUITPY_WIFI_RADIO_SETTABLE_MAC_ADDRESS=$(CIRCUITPY_WIFI_RADIO_SETTABLE_MAC_ADDRESS) -CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL?= 0 -CFLAGS += -DCIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL=$(CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL) - # tinyusb port tailored configuration CIRCUITPY_TUSB_MEM_ALIGN ?= 4 CFLAGS += -DCIRCUITPY_TUSB_MEM_ALIGN=$(CIRCUITPY_TUSB_MEM_ALIGN) @@ -691,6 +757,10 @@ CFLAGS += -DCIRCUITPY_TUSB_ATTR_USBRAM=$(CIRCUITPY_TUSB_ATTR_USBRAM) CIRCUITPY_SWO_TRACE ?= 0 CFLAGS += -DCIRCUITPY_SWO_TRACE=$(CIRCUITPY_SWO_TRACE) +# Check for a minimum GCC version during build (set to 0 to disable) +CIRCUITPY_MIN_GCC_VERSION ?= 14 +CFLAGS += -DCIRCUITPY_MIN_GCC_VERSION=$(CIRCUITPY_MIN_GCC_VERSION) + # Define an equivalent for MICROPY_LONGINT_IMPL, to pass to $(MPY-TOOL) in py/mkrules.mk # $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers. # This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h. diff --git a/py/compile.c b/py/compile.c index c73fa500469cc..c8704131234f1 100644 --- a/py/compile.c +++ b/py/compile.c @@ -41,8 +41,6 @@ #if MICROPY_ENABLE_COMPILER -// TODO need to mangle __attr names - #define INVALID_LABEL (0xffff) typedef enum { @@ -92,7 +90,7 @@ typedef enum { #define NATIVE_EMITTER(f) emit_native_table[mp_dynamic_compiler.native_arch]->emit_##f #define NATIVE_EMITTER_TABLE (emit_native_table[mp_dynamic_compiler.native_arch]) -STATIC const emit_method_table_t *emit_native_table[] = { +static const emit_method_table_t *emit_native_table[] = { NULL, &emit_native_x86_method_table, &emit_native_x64_method_table, @@ -104,6 +102,9 @@ STATIC const emit_method_table_t *emit_native_table[] = { &emit_native_thumb_method_table, &emit_native_xtensa_method_table, &emit_native_xtensawin_method_table, + &emit_native_rv32_method_table, + NULL, + &emit_native_debug_method_table, }; #elif MICROPY_EMIT_NATIVE @@ -120,6 +121,10 @@ STATIC const emit_method_table_t *emit_native_table[] = { #define NATIVE_EMITTER(f) emit_native_xtensa_##f #elif MICROPY_EMIT_XTENSAWIN #define NATIVE_EMITTER(f) emit_native_xtensawin_##f +#elif MICROPY_EMIT_RV32 +#define NATIVE_EMITTER(f) emit_native_rv32_##f +#elif MICROPY_EMIT_NATIVE_DEBUG +#define NATIVE_EMITTER(f) emit_native_debug_##f #else #error "unknown native emitter" #endif @@ -131,7 +136,7 @@ STATIC const emit_method_table_t *emit_native_table[] = { #define ASM_EMITTER(f) emit_asm_table[mp_dynamic_compiler.native_arch]->asm_##f #define ASM_EMITTER_TABLE emit_asm_table[mp_dynamic_compiler.native_arch] -STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { +static const emit_inline_asm_method_table_t *emit_asm_table[] = { NULL, NULL, NULL, @@ -143,6 +148,7 @@ STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { &emit_inline_thumb_method_table, &emit_inline_xtensa_method_table, NULL, + &emit_inline_rv32_method_table, }; #elif MICROPY_EMIT_INLINE_ASM @@ -153,6 +159,9 @@ STATIC const emit_inline_asm_method_table_t *emit_asm_table[] = { #elif MICROPY_EMIT_INLINE_XTENSA #define ASM_DECORATOR_QSTR MP_QSTR_asm_xtensa #define ASM_EMITTER(f) emit_inline_xtensa_##f +#elif MICROPY_EMIT_INLINE_RV32 +#define ASM_DECORATOR_QSTR MP_QSTR_asm_rv32 +#define ASM_EMITTER(f) emit_inline_rv32_##f #else #error "unknown asm emitter" #endif @@ -198,11 +207,15 @@ typedef struct _compiler_t { mp_emit_common_t emit_common; } compiler_t; +#if MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT +bool mp_compile_allow_top_level_await = false; +#endif + /******************************************************************************/ // mp_emit_common_t helper functions // These are defined here so they can be inlined, to reduce code size. -STATIC void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) { +static void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) { #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE mp_map_init(&emit->qstr_map, 1); @@ -213,7 +226,7 @@ STATIC void mp_emit_common_init(mp_emit_common_t *emit, qstr source_file) { mp_obj_list_init(&emit->const_obj_list, 0); } -STATIC void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) { +static void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) { emit->pass = pass; if (pass == MP_PASS_CODE_SIZE) { if (emit->ct_cur_child == 0) { @@ -225,7 +238,7 @@ STATIC void mp_emit_common_start_pass(mp_emit_common_t *emit, pass_kind_t pass) emit->ct_cur_child = 0; } -STATIC void mp_emit_common_populate_module_context(mp_emit_common_t *emit, qstr source_file, mp_module_context_t *context) { +static void mp_emit_common_populate_module_context(mp_emit_common_t *emit, qstr source_file, mp_module_context_t *context) { #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE size_t qstr_map_used = emit->qstr_map.used; mp_module_context_alloc_tables(context, qstr_map_used, emit->const_obj_list.len); @@ -248,14 +261,14 @@ STATIC void mp_emit_common_populate_module_context(mp_emit_common_t *emit, qstr /******************************************************************************/ -STATIC void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) { +static void compile_error_set_line(compiler_t *comp, mp_parse_node_t pn) { // if the line of the error is unknown then try to update it from the pn if (comp->compile_error_line == 0 && MP_PARSE_NODE_IS_STRUCT(pn)) { comp->compile_error_line = ((mp_parse_node_struct_t *)pn)->source_line; } } -STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, mp_rom_error_text_t msg) { +static void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, mp_rom_error_text_t msg) { // only register the error if there has been no other error if (comp->compile_error == MP_OBJ_NULL) { comp->compile_error = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); @@ -263,17 +276,17 @@ STATIC void compile_syntax_error(compiler_t *comp, mp_parse_node_t pn, mp_rom_er } } -STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra); -STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind); -STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map); -STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn); +static void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra); +static void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind); +static void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map); +static void compile_node(compiler_t *comp, mp_parse_node_t pn); -STATIC uint comp_next_label(compiler_t *comp) { +static uint comp_next_label(compiler_t *comp) { return comp->next_label++; } #if MICROPY_EMIT_NATIVE -STATIC void reserve_labels_for_native(compiler_t *comp, int n) { +static void reserve_labels_for_native(compiler_t *comp, int n) { if (comp->scope_cur->emit_options != MP_EMIT_OPT_BYTECODE) { comp->next_label += n; } @@ -282,7 +295,7 @@ STATIC void reserve_labels_for_native(compiler_t *comp, int n) { #define reserve_labels_for_native(comp, n) #endif -STATIC void compile_increase_except_level(compiler_t *comp, uint label, int kind) { +static void compile_increase_except_level(compiler_t *comp, uint label, int kind) { EMIT_ARG(setup_block, label, kind); comp->cur_except_level += 1; if (comp->cur_except_level > comp->scope_cur->exc_stack_size) { @@ -290,14 +303,14 @@ STATIC void compile_increase_except_level(compiler_t *comp, uint label, int kind } } -STATIC void compile_decrease_except_level(compiler_t *comp) { +static void compile_decrease_except_level(compiler_t *comp) { assert(comp->cur_except_level > 0); comp->cur_except_level -= 1; EMIT(end_finally); reserve_labels_for_native(comp, 1); } -STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { +static scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse_node_t pn, uint emit_options) { scope_t *scope = scope_new(kind, pn, emit_options); scope->parent = comp->scope_cur; scope->next = NULL; @@ -315,7 +328,7 @@ STATIC scope_t *scope_new_and_link(compiler_t *comp, scope_kind_t kind, mp_parse typedef void (*apply_list_fun_t)(compiler_t *comp, mp_parse_node_t pn); -STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) { +static void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_list_kind, apply_list_fun_t f) { if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, pn_list_kind)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn; int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); @@ -327,7 +340,7 @@ STATIC void apply_to_single_or_list(compiler_t *comp, mp_parse_node_t pn, pn_kin } } -STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (int i = 0; i < num_nodes; i++) { compile_node(comp, pns->nodes[i]); @@ -339,7 +352,7 @@ STATIC void compile_generic_all_nodes(compiler_t *comp, mp_parse_node_struct_t * } } -STATIC void compile_load_id(compiler_t *comp, qstr qst) { +static void compile_load_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_load(comp->scope_cur, qst); } else { @@ -351,7 +364,7 @@ STATIC void compile_load_id(compiler_t *comp, qstr qst) { } } -STATIC void compile_store_id(compiler_t *comp, qstr qst) { +static void compile_store_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_modification(comp->scope_cur, qst); } else { @@ -363,7 +376,7 @@ STATIC void compile_store_id(compiler_t *comp, qstr qst) { } } -STATIC void compile_delete_id(compiler_t *comp, qstr qst) { +static void compile_delete_id(compiler_t *comp, qstr qst) { if (comp->pass == MP_PASS_SCOPE) { mp_emit_common_get_id_for_modification(comp->scope_cur, qst); } else { @@ -375,7 +388,7 @@ STATIC void compile_delete_id(compiler_t *comp, qstr qst) { } } -STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) { // a simple tuple expression size_t num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); for (size_t i = 0; i < num_nodes; i++) { @@ -384,7 +397,7 @@ STATIC void compile_generic_tuple(compiler_t *comp, mp_parse_node_struct_t *pns) EMIT_ARG(build, num_nodes, MP_EMIT_BUILD_TUPLE); } -STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) { +static void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int label) { if (mp_parse_node_is_const_false(pn)) { if (jump_if == false) { EMIT_ARG(jump, label); @@ -432,9 +445,9 @@ STATIC void c_if_cond(compiler_t *comp, mp_parse_node_t pn, bool jump_if, int la } typedef enum { ASSIGN_STORE, ASSIGN_AUG_LOAD, ASSIGN_AUG_STORE } assign_kind_t; -STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind); +static void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t kind); -STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) { +static void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, assign_kind_t assign_kind) { if (assign_kind != ASSIGN_AUG_STORE) { compile_node(comp, pns->nodes[0]); } @@ -483,7 +496,7 @@ STATIC void c_assign_atom_expr(compiler_t *comp, mp_parse_node_struct_t *pns, as compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("can't assign to expression")); } -STATIC void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nodes_tail) { +static void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nodes_tail) { // look for star expression uint have_star_index = -1; for (uint i = 0; i < num_tail; i++) { @@ -510,7 +523,7 @@ STATIC void c_assign_tuple(compiler_t *comp, uint num_tail, mp_parse_node_t *nod } // assigns top of stack to pn -STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) { +static void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_kind) { assert(!MP_PARSE_NODE_IS_NULL(pn)); if (MP_PARSE_NODE_IS_LEAF(pn)) { if (MP_PARSE_NODE_IS_ID(pn)) { @@ -601,7 +614,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_ // if n_pos_defaults > 0 then there is a tuple on the stack with the positional defaults // if n_kw_defaults > 0 then there is a dictionary on the stack with the keyword defaults // if both exist, the tuple is above the dictionary (ie the first pop gets the tuple) -STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) { +static void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int n_pos_defaults, int n_kw_defaults) { assert(n_pos_defaults >= 0); assert(n_kw_defaults >= 0); @@ -643,7 +656,7 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int } } -STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) { +static void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) { // For efficiency of the code below we extract the parse-node kind here int pn_kind; if (MP_PARSE_NODE_IS_ID(pn)) { @@ -734,7 +747,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) } } -STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) { +static void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_node_t pn_params, pn_kind_t pn_list_kind) { // When we call compile_funcdef_lambdef_param below it can compile an arbitrary // expression for default arguments, which may contain a lambda. The lambda will // call here in a nested way, so we must save and restore the relevant state. @@ -770,7 +783,7 @@ STATIC void compile_funcdef_lambdef(compiler_t *comp, scope_t *scope, mp_parse_n // leaves function object on stack // returns function name -STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { +static qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this function scope_t *s = scope_new_and_link(comp, SCOPE_FUNCTION, (mp_parse_node_t)pns, emit_options); @@ -790,7 +803,7 @@ STATIC qstr compile_funcdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns // leaves class object on stack // returns class name -STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { +static qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pns, uint emit_options) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this class scope_t *s = scope_new_and_link(comp, SCOPE_CLASS, (mp_parse_node_t)pns, emit_options); @@ -822,7 +835,7 @@ STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pn } // returns true if it was a built-in decorator (even if the built-in had an error) -STATIC bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_parse_node_t *name_nodes, uint *emit_options) { +static bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_parse_node_t *name_nodes, uint *emit_options) { if (MP_PARSE_NODE_LEAF_ARG(name_nodes[0]) != MP_QSTR_micropython) { return false; } @@ -847,6 +860,8 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_par *emit_options = MP_EMIT_OPT_ASM; } else if (attr == MP_QSTR_asm_xtensa) { *emit_options = MP_EMIT_OPT_ASM; + } else if (attr == MP_QSTR_asm_rv32) { + *emit_options = MP_EMIT_OPT_ASM; #else } else if (attr == ASM_DECORATOR_QSTR) { *emit_options = MP_EMIT_OPT_ASM; @@ -871,7 +886,7 @@ STATIC bool compile_built_in_decorator(compiler_t *comp, size_t name_len, mp_par return true; } -STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the list of decorators mp_parse_node_t *nodes; size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_decorators, &nodes); @@ -940,13 +955,13 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_store_id(comp, body_name); } -STATIC void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_funcdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr fname = compile_funcdef_helper(comp, pns, comp->scope_cur->emit_options); // store function object into function name compile_store_id(comp, fname); } -STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { +static void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { compile_delete_id(comp, MP_PARSE_NODE_LEAF_ARG(pn)); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_expr_normal)) { @@ -1002,11 +1017,11 @@ STATIC void c_del_stmt(compiler_t *comp, mp_parse_node_t pn) { compile_syntax_error(comp, (mp_parse_node_t)pn, MP_ERROR_TEXT("can't delete expression")); } -STATIC void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_del_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_exprlist, c_del_stmt); } -STATIC void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint16_t label; if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_break_stmt) { label = comp->break_label; @@ -1020,7 +1035,7 @@ STATIC void compile_break_cont_stmt(compiler_t *comp, mp_parse_node_struct_t *pn EMIT_ARG(unwind_jump, label, comp->cur_except_level - comp->break_continue_except_level); } -STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { #if MICROPY_CPYTHON_COMPAT if (comp->scope_cur->kind != SCOPE_FUNCTION) { compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'return' outside function")); @@ -1048,12 +1063,12 @@ STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT(return_value); } -STATIC void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_yield_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT(pop_top); } -STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // raise EMIT_ARG(raise_varargs, 0); @@ -1073,7 +1088,7 @@ STATIC void compile_raise_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // q_base holds the base of the name // eg a -> q_base=a // a.b.c -> q_base=a -STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { +static void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { bool is_as = false; if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_dotted_as_name)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn; @@ -1134,7 +1149,7 @@ STATIC void do_import_name(compiler_t *comp, mp_parse_node_t pn, qstr *q_base) { } } -STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) { +static void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) { EMIT_ARG(load_const_small_int, 0); // level 0 import EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // not importing from anything qstr q_base; @@ -1142,11 +1157,11 @@ STATIC void compile_dotted_as_name(compiler_t *comp, mp_parse_node_t pn) { compile_store_id(comp, q_base); } -STATIC void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_import_name(compiler_t *comp, mp_parse_node_struct_t *pns) { apply_to_single_or_list(comp, pns->nodes[0], PN_dotted_as_names, compile_dotted_as_name); } -STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_t pn_import_source = pns->nodes[0]; // extract the preceding .'s (if any) for a relative import, to compute the import level @@ -1234,7 +1249,7 @@ STATIC void compile_import_from(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { +static void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { if (id_info->kind != ID_INFO_KIND_UNDECIDED && id_info->kind != ID_INFO_KIND_GLOBAL_EXPLICIT) { compile_syntax_error(comp, pn, MP_ERROR_TEXT("identifier redefined as global")); return; @@ -1248,7 +1263,7 @@ STATIC void compile_declare_global(compiler_t *comp, mp_parse_node_t pn, id_info } } -STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { +static void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info) { if (id_info->kind == ID_INFO_KIND_UNDECIDED) { id_info->kind = ID_INFO_KIND_GLOBAL_IMPLICIT; scope_check_to_close_over(comp->scope_cur, id_info); @@ -1260,7 +1275,7 @@ STATIC void compile_declare_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_in } } -STATIC void compile_declare_global_or_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info, bool is_global) { +static void compile_declare_global_or_nonlocal(compiler_t *comp, mp_parse_node_t pn, id_info_t *id_info, bool is_global) { if (is_global) { compile_declare_global(comp, pn, id_info); } else { @@ -1268,7 +1283,7 @@ STATIC void compile_declare_global_or_nonlocal(compiler_t *comp, mp_parse_node_t } } -STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == MP_PASS_SCOPE) { bool is_global = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_global_stmt; @@ -1287,7 +1302,7 @@ STATIC void compile_global_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_ } } -STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // with optimisations enabled we don't compile assertions if (MP_STATE_VM(mp_optimise_value) != 0) { return; @@ -1305,7 +1320,7 @@ STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(label_assign, l_end); } -STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { uint l_end = comp_next_label(comp); // optimisation: don't emit anything when "if False" @@ -1375,7 +1390,7 @@ STATIC void compile_if_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { comp->continue_label = old_continue_label; \ comp->break_continue_except_level = old_break_continue_except_level; -STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { START_BREAK_CONTINUE_BLOCK if (!mp_parse_node_is_const_false(pns->nodes[0])) { // optimisation: don't emit anything for "while False" @@ -1413,7 +1428,7 @@ STATIC void compile_while_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // If is a small-int, then the stack during the for-loop contains just // the current value of . Otherwise, the stack contains then the // current value of . -STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) { +static void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t pn_var, mp_parse_node_t pn_start, mp_parse_node_t pn_end, mp_parse_node_t pn_step, mp_parse_node_t pn_body, mp_parse_node_t pn_else) { START_BREAK_CONTINUE_BLOCK uint top_label = comp_next_label(comp); @@ -1495,7 +1510,7 @@ STATIC void compile_for_stmt_optimised_range(compiler_t *comp, mp_parse_node_t p } } -STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // this bit optimises: for in range(...), turning it into an explicitly incremented variable // this is actually slower, but uses no heap memory // for viper it will be much, much faster @@ -1575,7 +1590,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(label_assign, break_label); } -STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) { +static void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_excepts, mp_parse_node_t pn_else) { // setup code uint l1 = comp_next_label(comp); uint success_label = comp_next_label(comp); @@ -1672,7 +1687,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_ EMIT_ARG(label_assign, l2); } -STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) { +static void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n_except, mp_parse_node_t *pn_except, mp_parse_node_t pn_else, mp_parse_node_t pn_finally) { uint l_finally_block = comp_next_label(comp); compile_increase_except_level(comp, l_finally_block, MP_EMIT_SETUP_BLOCK_FINALLY); @@ -1701,7 +1716,7 @@ STATIC void compile_try_finally(compiler_t *comp, mp_parse_node_t pn_body, int n compile_decrease_except_level(comp); } -STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should be { mp_parse_node_struct_t *pns2 = (mp_parse_node_struct_t *)pns->nodes[1]; @@ -1728,7 +1743,7 @@ STATIC void compile_try_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) { +static void compile_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) { if (n == 0) { // no more pre-bits, compile the body of the with compile_node(comp, body); @@ -1755,7 +1770,7 @@ STATIC void compile_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t } } -STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit) mp_parse_node_t *nodes; size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes); @@ -1765,7 +1780,7 @@ STATIC void compile_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_with_stmt_helper(comp, n, nodes, pns->nodes[1]); } -STATIC void compile_yield_from(compiler_t *comp) { +static void compile_yield_from(compiler_t *comp) { EMIT_ARG(get_iter, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT_ARG(yield, MP_EMIT_YIELD_FROM); @@ -1773,13 +1788,13 @@ STATIC void compile_yield_from(compiler_t *comp) { } #if MICROPY_PY_ASYNC_AWAIT -STATIC void compile_await_object_method(compiler_t *comp, qstr method) { +static void compile_await_object_method(compiler_t *comp, qstr method) { EMIT_ARG(load_method, method, false); EMIT_ARG(call_method, 0, 0, 0); compile_yield_from(comp); } -STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // Allocate labels. uint while_else_label = comp_next_label(comp); uint try_exception_label = comp_next_label(comp); @@ -1846,7 +1861,7 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns // Stack: (...) } -STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) { +static void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_node_t *nodes, mp_parse_node_t body) { if (n == 0) { // no more pre-bits, compile the body of the with compile_node(comp, body); @@ -1892,19 +1907,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_ // Handle case 1: call __aexit__ // Stack: (..., ctx_mgr) - EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception - EMIT(rot_two); - EMIT_ARG(jump, l_aexit_no_exc); // jump to code below to call __aexit__ - - // Start of "finally" block - // At this point we have case 2 or 3, we detect which one by the TOS being an exception or not - EMIT_ARG(label_assign, l_finally_block); - - // Detect if TOS an exception or not - EMIT(dup_top); - EMIT_LOAD_GLOBAL(MP_QSTR_BaseException); - EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); - EMIT_ARG(pop_jump_if, false, l_ret_unwind_jump); // if not an exception then we have case 3 + EMIT_ARG(async_with_setup_finally, l_aexit_no_exc, l_finally_block, l_ret_unwind_jump); // Handle case 2: call __aexit__ and either swallow or re-raise the exception // Stack: (..., ctx_mgr, exc) @@ -1930,6 +1933,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_ EMIT_ARG(pop_jump_if, false, l_end); EMIT(pop_top); // pop exception EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // replace with None to swallow exception + // Stack: (..., None) EMIT_ARG(jump, l_end); EMIT_ARG(adjust_stack_size, 2); @@ -1939,6 +1943,8 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_ EMIT(rot_three); EMIT(rot_three); EMIT_ARG(label_assign, l_aexit_no_exc); + // We arrive here from either case 1 (a jump) or case 3 (fall through) + // Stack: case 1: (..., None, ctx_mgr) or case 3: (..., X, INT, ctx_mgr) EMIT_ARG(load_method, MP_QSTR___aexit__, false); EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); EMIT(dup_top); @@ -1946,6 +1952,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_ EMIT_ARG(call_method, 3, 0, 0); compile_yield_from(comp); EMIT(pop_top); + // Stack: case 1: (..., None) or case 3: (..., X, INT) EMIT_ARG(adjust_stack_size, -1); // End of "finally" block @@ -1958,7 +1965,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, size_t n, mp_parse_ } } -STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { // get the nodes for the pre-bit of the with (the a as b, c as d, ... bit) mp_parse_node_t *nodes; size_t n = mp_parse_node_extract_list(&pns->nodes[0], PN_with_stmt_list, &nodes); @@ -1968,7 +1975,7 @@ STATIC void compile_async_with_stmt(compiler_t *comp, mp_parse_node_struct_t *pn compile_async_with_stmt_helper(comp, n, nodes, pns->nodes[1]); } -STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[0])); mp_parse_node_struct_t *pns0 = (mp_parse_node_struct_t *)pns->nodes[0]; if (MP_PARSE_NODE_STRUCT_KIND(pns0) == PN_funcdef) { @@ -1998,7 +2005,7 @@ STATIC void compile_async_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } #endif -STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { mp_parse_node_t pn_rhs = pns->nodes[1]; if (MP_PARSE_NODE_IS_NULL(pn_rhs)) { if (comp->is_repl && comp->scope_cur->kind == SCOPE_MODULE) { @@ -2113,7 +2120,7 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_test_if_else)); mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t *)pns->nodes[1]; @@ -2128,7 +2135,7 @@ STATIC void compile_test_if_expr(compiler_t *comp, mp_parse_node_struct_t *pns) EMIT_ARG(label_assign, l_end); } -STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->pass == MP_PASS_SCOPE) { // create a new scope for this lambda scope_t *s = scope_new_and_link(comp, SCOPE_LAMBDA, (mp_parse_node_t)pns, comp->scope_cur->emit_options); @@ -2144,7 +2151,7 @@ STATIC void compile_lambdef(compiler_t *comp, mp_parse_node_struct_t *pns) { } #if MICROPY_PY_ASSIGN_EXPR -STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) { +static void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, mp_parse_node_t pn_expr) { if (!MP_PARSE_NODE_IS_ID(pn_name)) { compile_syntax_error(comp, (mp_parse_node_t)pn_name, MP_ERROR_TEXT("can't assign to expression")); } @@ -2176,12 +2183,12 @@ STATIC void compile_namedexpr_helper(compiler_t *comp, mp_parse_node_t pn_name, compile_store_id(comp, target); } -STATIC void compile_namedexpr(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_namedexpr(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_namedexpr_helper(comp, pns->nodes[0], pns->nodes[1]); } #endif -STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { bool cond = MP_PARSE_NODE_STRUCT_KIND(pns) == PN_or_test; uint l_end = comp_next_label(comp); int n = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); @@ -2194,12 +2201,12 @@ STATIC void compile_or_and_test(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(label_assign, l_end); } -STATIC void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_not_test_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[0]); EMIT_ARG(unary_op, MP_UNARY_OP_NOT); } -STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); bool multi = (num_nodes > 3); @@ -2252,11 +2259,11 @@ STATIC void compile_comparison(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_star_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("*x must be assignment target")); } -STATIC void compile_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns) { MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_xor_expr - PN_expr == MP_BINARY_OP_XOR); MP_STATIC_ASSERT(MP_BINARY_OP_OR + PN_and_expr - PN_expr == MP_BINARY_OP_AND); mp_binary_op_t binary_op = MP_BINARY_OP_OR + MP_PARSE_NODE_STRUCT_KIND(pns) - PN_expr; @@ -2268,7 +2275,7 @@ STATIC void compile_binary_op(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) { int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns); compile_node(comp, pns->nodes[0]); for (int i = 1; i + 1 < num_nodes; i += 2) { @@ -2279,7 +2286,7 @@ STATIC void compile_term(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_node(comp, pns->nodes[1]); mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]); mp_unary_op_t op; @@ -2292,7 +2299,7 @@ STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(unary_op, op); } -STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) { // compile the subject of the expression compile_node(comp, pns->nodes[0]); @@ -2388,12 +2395,12 @@ STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *p } } -STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power EMIT_ARG(binary_op, MP_BINARY_OP_POWER); } -STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) { +static void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) { // function to call is on top of stack // get the list of arguments @@ -2488,7 +2495,7 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar } // pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node -STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) { +static void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) { assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2); assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[1], PN_comp_for)); mp_parse_node_struct_t *pns_comp_for = (mp_parse_node_struct_t *)pns->nodes[1]; @@ -2513,7 +2520,7 @@ STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, EMIT_ARG(call_function, 1, 0, 0); } -STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // an empty tuple EMIT_ARG(build, 0, MP_EMIT_BUILD_TUPLE); @@ -2530,7 +2537,7 @@ STATIC void compile_atom_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { } } -STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) { // empty list EMIT_ARG(build, 0, MP_EMIT_BUILD_LIST); @@ -2551,7 +2558,7 @@ STATIC void compile_atom_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) } } -STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map) { +static void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t *pns, bool create_map) { mp_parse_node_t pn = pns->nodes[0]; if (MP_PARSE_NODE_IS_NULL(pn)) { // empty dict @@ -2653,27 +2660,27 @@ STATIC void compile_atom_brace_helper(compiler_t *comp, mp_parse_node_struct_t * } } -STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_atom_brace_helper(comp, pns, true); } -STATIC void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_trailer_paren(compiler_t *comp, mp_parse_node_struct_t *pns) { compile_trailer_paren_helper(comp, pns->nodes[0], false, 0); } -STATIC void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_trailer_bracket(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's index we want is on top of stack compile_node(comp, pns->nodes[0]); // the index EMIT_ARG(subscr, MP_EMIT_SUBSCR_LOAD); } -STATIC void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_trailer_period(compiler_t *comp, mp_parse_node_struct_t *pns) { // object who's attribute we want is on top of stack EMIT_ARG(attr, MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]), MP_EMIT_ATTR_LOAD); // attribute to get } #if MICROPY_PY_BUILTINS_SLICE -STATIC void compile_subscript(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_subscript(compiler_t *comp, mp_parse_node_struct_t *pns) { if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_subscript_2) { compile_node(comp, pns->nodes[0]); // start of slice assert(MP_PARSE_NODE_IS_STRUCT(pns->nodes[1])); // should always be @@ -2728,19 +2735,19 @@ STATIC void compile_subscript(compiler_t *comp, mp_parse_node_struct_t *pns) { } #endif // MICROPY_PY_BUILTINS_SLICE -STATIC void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_dictorsetmaker_item(compiler_t *comp, mp_parse_node_struct_t *pns) { // if this is called then we are compiling a dict key:value pair compile_node(comp, pns->nodes[1]); // value compile_node(comp, pns->nodes[0]); // key } -STATIC void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_classdef(compiler_t *comp, mp_parse_node_struct_t *pns) { qstr cname = compile_classdef_helper(comp, pns, comp->scope_cur->emit_options); // store class object into class name compile_store_id(comp, cname); } -STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) { compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'yield' outside function")); return; @@ -2751,6 +2758,7 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { reserve_labels_for_native(comp, 1); } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_yield_arg_from)) { pns = (mp_parse_node_struct_t *)pns->nodes[0]; + // CIRCUITPY-CHANGE: more error checking #if MICROPY_PY_ASYNC_AWAIT if (comp->scope_cur->scope_flags & MP_SCOPE_FLAG_ASYNC) { compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'yield from' inside async function")); @@ -2767,10 +2775,15 @@ STATIC void compile_yield_expr(compiler_t *comp, mp_parse_node_struct_t *pns) { } #if MICROPY_PY_ASYNC_AWAIT -STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pns) { if (comp->scope_cur->kind != SCOPE_FUNCTION && comp->scope_cur->kind != SCOPE_LAMBDA) { - compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'await' outside function")); - return; + #if MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT + if (!mp_compile_allow_top_level_await) + #endif + { + compile_syntax_error(comp, (mp_parse_node_t)pns, MP_ERROR_TEXT("'await' outside function")); + return; + } } compile_atom_expr_normal(comp, pns); @@ -2786,16 +2799,16 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn } #endif -STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) { +static mp_obj_t get_const_object(mp_parse_node_struct_t *pns) { return mp_parse_node_extract_const_object(pns); } -STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) { +static void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) { EMIT_ARG(load_const_obj, get_const_object(pns)); } typedef void (*compile_function_t)(compiler_t *, mp_parse_node_struct_t *); -STATIC const compile_function_t compile_function[] = { +static const compile_function_t compile_function[] = { // only define rules with a compile function #define c(f) compile_##f #define DEF_RULE(rule, comp, kind, ...) comp, @@ -2807,7 +2820,7 @@ STATIC const compile_function_t compile_function[] = { compile_const_object, }; -STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { +static void compile_node(compiler_t *comp, mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_NULL(pn)) { // pass } else if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { @@ -2843,7 +2856,7 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { } #if MICROPY_EMIT_NATIVE -STATIC int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_annotation) { +static int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_annotation) { int native_type = MP_NATIVE_TYPE_OBJ; if (MP_PARSE_NODE_IS_NULL(pn_annotation)) { // No annotation, type defaults to object @@ -2861,7 +2874,7 @@ STATIC int compile_viper_type_annotation(compiler_t *comp, mp_parse_node_t pn_an } #endif -STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) { +static void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn, pn_kind_t pn_name, pn_kind_t pn_star, pn_kind_t pn_dbl_star) { (void)pn_dbl_star; // check that **kw is last @@ -2948,15 +2961,15 @@ STATIC void compile_scope_func_lambda_param(compiler_t *comp, mp_parse_node_t pn } } -STATIC void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) { +static void compile_scope_func_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_typedargslist_name, PN_typedargslist_star, PN_typedargslist_dbl_star); } -STATIC void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) { +static void compile_scope_lambda_param(compiler_t *comp, mp_parse_node_t pn) { compile_scope_func_lambda_param(comp, pn, PN_varargslist_name, PN_varargslist_star, PN_varargslist_dbl_star); } -STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) { +static void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pns_comp_for, mp_parse_node_t pn_inner_expr, int for_depth) { uint l_top = comp_next_label(comp); uint l_end = comp_next_label(comp); EMIT_ARG(label_assign, l_top); @@ -2995,7 +3008,7 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn EMIT(for_iter_end); } -STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { +static void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { #if MICROPY_ENABLE_DOC_STRING // see http://www.python.org/dev/peps/pep-0257/ @@ -3040,7 +3053,7 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) { #endif } -STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { +static bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; comp->next_label = 0; @@ -3205,7 +3218,7 @@ STATIC bool compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) { #if MICROPY_EMIT_INLINE_ASM // requires 3 passes: SCOPE, CODE_SIZE, EMIT -STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { +static void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind_t pass) { comp->pass = pass; comp->scope_cur = scope; comp->next_label = 0; @@ -3283,7 +3296,9 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind } // check structure of parse node - assert(MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])); + if (!MP_PARSE_NODE_IS_STRUCT(pns2->nodes[0])) { + goto not_an_instruction; + } if (!MP_PARSE_NODE_IS_NULL(pns2->nodes[1])) { goto not_an_instruction; } @@ -3380,7 +3395,7 @@ STATIC void compile_scope_inline_asm(compiler_t *comp, scope_t *scope, pass_kind } #endif -STATIC void scope_compute_things(scope_t *scope) { +static void scope_compute_things(scope_t *scope) { // in MicroPython we put the *x parameter after all other parameters (except **y) if (scope->scope_flags & MP_SCOPE_FLAG_VARARGS) { id_info_t *id_param = NULL; @@ -3473,8 +3488,8 @@ STATIC void scope_compute_things(scope_t *scope) { } } -#if !MICROPY_PERSISTENT_CODE_SAVE -STATIC +#if !MICROPY_EXPOSE_MP_COMPILE_TO_RAW_CODE +static #endif void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_compiled_module_t *cm) { // put compiler state on the stack, it's relatively small @@ -3575,6 +3590,13 @@ void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool case MP_EMIT_OPT_NATIVE_PYTHON: case MP_EMIT_OPT_VIPER: if (emit_native == NULL) { + // The check looks like this to work around a false + // warning in GCC 13 (and possibly later), where it + // assumes that the check will always fail. + if ((uintptr_t)NATIVE_EMITTER_TABLE == (uintptr_t)NULL) { + comp->compile_error = mp_obj_new_exception_msg(&mp_type_NotImplementedError, MP_ERROR_TEXT("cannot emit native code for this architecture")); + goto emit_finished; + } emit_native = NATIVE_EMITTER(new)(&comp->emit_common, &comp->compile_error, &comp->next_label, max_num_labels); } comp->emit_method_table = NATIVE_EMITTER_TABLE; @@ -3607,6 +3629,10 @@ void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool } } + #if MICROPY_EMIT_NATIVE +emit_finished: + #endif + if (comp->compile_error != MP_OBJ_NULL) { // if there is no line number for the error then use the line // number for the start of this scope @@ -3642,7 +3668,7 @@ void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool for (scope_t *s = comp->scope_head; s != NULL; s = s->next) { mp_raw_code_t *rc = s->raw_code; if (rc->kind == MP_CODE_BYTECODE) { - mp_bytecode_print(&mp_plat_print, rc, &cm->context->constants); + mp_bytecode_print(&mp_plat_print, rc, s->raw_code_data_len, &cm->context->constants); } } } @@ -3684,7 +3710,7 @@ mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl) cm.context->module.globals = mp_globals_get(); mp_compile_to_raw_code(parse_tree, source_file, is_repl, &cm); // return function that executes the outer module - return mp_make_function_from_raw_code(cm.rc, cm.context, NULL); + return mp_make_function_from_proto_fun(cm.rc, cm.context, NULL); } #endif // MICROPY_ENABLE_COMPILER diff --git a/py/compile.h b/py/compile.h index 5e0fd8b31c4a8..64afc487d7c3d 100644 --- a/py/compile.h +++ b/py/compile.h @@ -30,12 +30,20 @@ #include "py/parse.h" #include "py/emitglue.h" +// Whether mp_compile_to_raw_code is exposed as a public function. +#define MICROPY_EXPOSE_MP_COMPILE_TO_RAW_CODE (MICROPY_PY_BUILTINS_CODE >= MICROPY_PY_BUILTINS_CODE_BASIC || MICROPY_PERSISTENT_CODE_SAVE) + +#if MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT +// set to `true` to allow top-level await expressions +extern bool mp_compile_allow_top_level_await; +#endif + // the compiler will raise an exception if an error occurred // the compiler will clear the parse tree before it returns // mp_globals_get() will be used for the context mp_obj_t mp_compile(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl); -#if MICROPY_PERSISTENT_CODE_SAVE +#if MICROPY_EXPOSE_MP_COMPILE_TO_RAW_CODE // this has the same semantics as mp_compile void mp_compile_to_raw_code(mp_parse_tree_t *parse_tree, qstr source_file, bool is_repl, mp_compiled_module_t *cm); #endif diff --git a/py/cstack.c b/py/cstack.c new file mode 100644 index 0000000000000..fe4b16d652a50 --- /dev/null +++ b/py/cstack.c @@ -0,0 +1,57 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Paul Sokolovsky + * Copryight (c) 2024 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/cstack.h" + +void mp_cstack_init_with_sp_here(size_t stack_size) { + #if __GNUC__ >= 13 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdangling-pointer" + #endif + volatile int stack_dummy; + mp_cstack_init_with_top((void *)&stack_dummy, stack_size); + #if __GNUC__ >= 13 + #pragma GCC diagnostic pop + #endif +} + +mp_uint_t mp_cstack_usage(void) { + // Assumes descending stack + volatile int stack_dummy; + return MP_STATE_THREAD(stack_top) - (char *)&stack_dummy; +} + +#if MICROPY_STACK_CHECK + +void mp_cstack_check(void) { + if (mp_cstack_usage() >= MP_STATE_THREAD(stack_limit)) { + mp_raise_recursion_depth(); + } +} + +#endif // MICROPY_STACK_CHECK diff --git a/py/cstack.h b/py/cstack.h new file mode 100644 index 0000000000000..bcd919d31f932 --- /dev/null +++ b/py/cstack.h @@ -0,0 +1,63 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Paul Sokolovsky + * Copyright (c) 2024 Angus Gratton + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_PY_CSTACK_H +#define MICROPY_INCLUDED_PY_CSTACK_H + +#include "py/mpstate.h" + +// Both init functions below accept the full stack size. Set the +// MICROPY_STACK_CHECK_MARGIN to the number of bytes subtracted to account +// for stack usage between checks. + +void mp_cstack_init_with_sp_here(size_t stack_size); + +static inline void mp_cstack_init_with_top(void *top, size_t stack_size) { + MP_STATE_THREAD(stack_top) = (char *)top; + + #if MICROPY_STACK_CHECK + assert(stack_size > MICROPY_STACK_CHECK_MARGIN); // Should be enforced by port + MP_STATE_THREAD(stack_limit) = stack_size - MICROPY_STACK_CHECK_MARGIN; + #else + (void)stack_size; + #endif +} + +mp_uint_t mp_cstack_usage(void); + +#if MICROPY_STACK_CHECK + +void mp_cstack_check(void); + +#else + +static inline void mp_cstack_check(void) { + // No-op when stack checking is disabled +} + +#endif + +#endif // MICROPY_INCLUDED_PY_CSTACK_H diff --git a/py/dynruntime.h b/py/dynruntime.h index d80ce10f577be..ab155a1387579 100644 --- a/py/dynruntime.h +++ b/py/dynruntime.h @@ -28,7 +28,16 @@ // This header file contains definitions to dynamically implement the static // MicroPython runtime API defined in py/obj.h and py/runtime.h. - +// +// All of the symbols made available in this header are overriding those defined +// in py/obj.h and py/runtime.h. This is done with macros. For macros that +// would be too complicated (usually more than a single expression), they call a +// static-inline function for the implementation. This function has the same +// name as the macro (hence the same name as a public API function) but with +// "_dyn" appended. For example, the m_malloc() macro calls the m_malloc_dyn() +// static-inline function. + +#include "py/binary.h" #include "py/nativeglue.h" #include "py/objfun.h" #include "py/objstr.h" @@ -38,6 +47,10 @@ #error "dynruntime.h included in non-dynamic-module build." #endif +#if MICROPY_MALLOC_USES_ALLOCATED_SIZE +#error "MICROPY_MALLOC_USES_ALLOCATED_SIZE must be disable in a dynamic-module build." +#endif + #undef MP_ROM_QSTR #undef MP_OBJ_QSTR_VALUE #undef MP_OBJ_NEW_QSTR @@ -51,13 +64,32 @@ /******************************************************************************/ // Memory allocation +#define m_malloc_fail(num_bytes) (m_malloc_fail_dyn((num_bytes))) #define m_malloc(n) (m_malloc_dyn((n))) #define m_free(ptr) (m_free_dyn((ptr))) #define m_realloc(ptr, new_num_bytes) (m_realloc_dyn((ptr), (new_num_bytes))) +#define m_realloc_maybe(ptr, new_num_bytes, allow_move) (m_realloc_maybe_dyn((ptr), (new_num_bytes), (allow_move))) + +static MP_NORETURN inline void m_malloc_fail_dyn(size_t num_bytes) { + mp_fun_table.raise_msg( + mp_fun_table.load_global(MP_QSTR_MemoryError), + "memory allocation failed"); +} + +static inline void *m_realloc_maybe_dyn(void *ptr, size_t new_num_bytes, bool allow_move) { + return mp_fun_table.realloc_(ptr, new_num_bytes, allow_move); +} + +static inline void *m_realloc_checked_dyn(void *ptr, size_t new_num_bytes, bool allow_move) { + ptr = m_realloc_maybe(ptr, new_num_bytes, allow_move); + if (ptr == NULL && new_num_bytes != 0) { + m_malloc_fail(new_num_bytes); + } + return ptr; +} static inline void *m_malloc_dyn(size_t n) { - // TODO won't raise on OOM - return mp_fun_table.realloc_(NULL, n, false); + return m_realloc_checked_dyn(NULL, n, false); } static inline void m_free_dyn(void *ptr) { @@ -65,8 +97,7 @@ static inline void m_free_dyn(void *ptr) { } static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { - // TODO won't raise on OOM - return mp_fun_table.realloc_(ptr, new_num_bytes, true); + return m_realloc_checked_dyn(ptr, new_num_bytes, true); } /******************************************************************************/ @@ -87,8 +118,10 @@ static inline void *m_realloc_dyn(void *ptr, size_t new_num_bytes) { #define mp_type_int (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_int))) #define mp_type_str (*mp_fun_table.type_str) #define mp_type_bytes (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_bytes))) +#define mp_type_bytearray (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_bytearray))) #define mp_type_tuple (*((mp_obj_base_t *)mp_const_empty_tuple)->type) #define mp_type_list (*mp_fun_table.type_list) +#define mp_type_Exception (*mp_fun_table.type_Exception) #define mp_type_EOFError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_EOFError))) #define mp_type_IndexError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_IndexError))) #define mp_type_KeyError (*(mp_obj_type_t *)(mp_load_global(MP_QSTR_KeyError))) @@ -187,10 +220,15 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type /******************************************************************************/ // General runtime functions +#define mp_binary_get_size(struct_type, val_type, palign) (mp_fun_table.binary_get_size((struct_type), (val_type), (palign))) +#define mp_binary_get_val_array(typecode, p, index) (mp_fun_table.binary_get_val_array((typecode), (p), (index))) +#define mp_binary_set_val_array(typecode, p, index, val_in) (mp_fun_table.binary_set_val_array((typecode), (p), (index), (val_in))) + #define mp_load_name(qst) (mp_fun_table.load_name((qst))) #define mp_load_global(qst) (mp_fun_table.load_global((qst))) #define mp_load_attr(base, attr) (mp_fun_table.load_attr((base), (attr))) #define mp_load_method(base, attr, dest) (mp_fun_table.load_method((base), (attr), (dest))) +#define mp_load_method_maybe(base, attr, dest) (mp_fun_table.load_method_maybe((base), (attr), (dest))) #define mp_load_super_method(attr, dest) (mp_fun_table.load_super_method((attr), (dest))) #define mp_store_name(qst, obj) (mp_fun_table.store_name((qst), (obj))) #define mp_store_global(qst, obj) (mp_fun_table.store_global((qst), (obj))) @@ -199,8 +237,8 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type #define mp_unary_op(op, obj) (mp_fun_table.unary_op((op), (obj))) #define mp_binary_op(op, lhs, rhs) (mp_fun_table.binary_op((op), (lhs), (rhs))) -#define mp_make_function_from_raw_code(rc, context, def_args) \ - (mp_fun_table.make_function_from_raw_code((rc), (context), (def_args))) +#define mp_make_function_from_proto_fun(rc, context, def_args) \ + (mp_fun_table.make_function_from_proto_fun((rc), (context), (def_args))) #define mp_call_function_n_kw(fun, n_args, n_kw, args) \ (mp_fun_table.call_function_n_kw((fun), (n_args) | ((n_kw) << 8), args)) @@ -208,11 +246,21 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type #define mp_arg_check_num(n_args, n_kw, n_args_min, n_args_max, takes_kw) \ (mp_fun_table.arg_check_num_sig((n_args), (n_kw), MP_OBJ_FUN_MAKE_SIG((n_args_min), (n_args_max), (takes_kw)))) +#define mp_arg_parse_all(n_pos, pos, kws, n_allowed, allowed, out_vals) \ + (mp_fun_table.arg_parse_all((n_pos), (pos), (kws), (n_allowed), (allowed), (out_vals))) + +#define mp_arg_parse_all_kw_array(n_pos, n_kw, args, n_allowed, allowed, out_vals) \ + (mp_fun_table.arg_parse_all_kw_array((n_pos), (n_kw), (args), (n_allowed), (allowed), (out_vals))) + +// CIRCUITPY-CHANGE: .is_async #define MP_DYNRUNTIME_INIT_ENTRY \ mp_obj_t old_globals = mp_fun_table.swap_globals(self->context->module.globals); \ - mp_raw_code_t rc; \ + mp_raw_code_truncated_t rc; \ + rc.proto_fun_indicator[0] = MP_PROTO_FUN_INDICATOR_RAW_CODE_0; \ + rc.proto_fun_indicator[1] = MP_PROTO_FUN_INDICATOR_RAW_CODE_1; \ rc.kind = MP_CODE_NATIVE_VIPER; \ - rc.scope_flags = 0; \ + rc.is_generator = 0; \ + rc.is_async = 0; \ (void)rc; #define MP_DYNRUNTIME_INIT_EXIT \ @@ -220,7 +268,7 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type return mp_const_none; #define MP_DYNRUNTIME_MAKE_FUNCTION(f) \ - (mp_make_function_from_raw_code((rc.fun_data = (f), &rc), MP_OBJ_NULL, MP_OBJ_NULL)) + (mp_make_function_from_proto_fun((rc.fun_data = (f), (const mp_raw_code_t *)&rc), self->context, NULL)) #define mp_import_name(name, fromlist, level) \ (mp_fun_table.import_name((name), (fromlist), (level))) @@ -232,12 +280,16 @@ static inline void *mp_obj_malloc_helper_dyn(size_t num_bytes, const mp_obj_type /******************************************************************************/ // Exceptions +#define mp_obj_exception_make_new (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, make_new)) +#define mp_obj_exception_print (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, print)) +#define mp_obj_exception_attr (MP_OBJ_TYPE_GET_SLOT(&mp_type_Exception, attr)) + #define mp_obj_new_exception(o) ((mp_obj_t)(o)) // Assumes returned object will be raised, will create instance then #define mp_obj_new_exception_arg1(e_type, arg) (mp_obj_new_exception_arg1_dyn((e_type), (arg))) #define nlr_raise(o) (mp_raise_dyn(o)) #define mp_raise_type_arg(type, arg) (mp_raise_dyn(mp_obj_new_exception_arg1_dyn((type), (arg)))) -// CIRCUITPY-CHANGE: use str +// CIRCUITPY-CHANGE: use mp_raise_msg_str #define mp_raise_msg(type, msg) (mp_fun_table.raise_msg_str((type), (msg))) #define mp_raise_OSError(er) (mp_raise_OSError_dyn(er)) #define mp_raise_NotImplementedError(msg) (mp_raise_msg(&mp_type_NotImplementedError, (msg))) @@ -249,14 +301,14 @@ static inline mp_obj_t mp_obj_new_exception_arg1_dyn(const mp_obj_type_t *exc_ty return mp_call_function_n_kw(MP_OBJ_FROM_PTR(exc_type), 1, 0, &args[0]); } -static NORETURN inline void mp_raise_dyn(mp_obj_t o) { +static MP_NORETURN inline void mp_raise_dyn(mp_obj_t o) { mp_fun_table.raise(o); for (;;) { } } // CIRCUITPY-CHANGE: new routine -static NORETURN inline void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { +static MP_NORETURN inline void mp_raise_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg) { mp_fun_table.raise(mp_obj_new_exception_arg1_dyn(exc_type, arg)); for (;;) { } @@ -268,6 +320,16 @@ static inline void mp_raise_OSError_dyn(int er) { nlr_raise(mp_call_function_n_kw(mp_load_global(MP_QSTR_OSError), 1, 0, &args[0])); } +static inline void mp_obj_exception_init(mp_obj_full_type_t *exc, qstr name, const mp_obj_type_t *base) { + exc->base.type = &mp_type_type; + exc->flags = MP_TYPE_FLAG_NONE; + exc->name = name; + MP_OBJ_TYPE_SET_SLOT(exc, make_new, mp_obj_exception_make_new, 0); + MP_OBJ_TYPE_SET_SLOT(exc, print, mp_obj_exception_print, 1); + MP_OBJ_TYPE_SET_SLOT(exc, attr, mp_obj_exception_attr, 2); + MP_OBJ_TYPE_SET_SLOT(exc, parent, base, 3); +} + /******************************************************************************/ // Floating point diff --git a/py/dynruntime.mk b/py/dynruntime.mk index 62db43ad149ca..030728cfc9adf 100644 --- a/py/dynruntime.mk +++ b/py/dynruntime.mk @@ -29,15 +29,18 @@ CFLAGS += -Wall -Werror -DNDEBUG CFLAGS += -DNO_QSTR CFLAGS += -DMICROPY_ENABLE_DYNRUNTIME CFLAGS += -DMP_CONFIGFILE='<$(CONFIG_H)>' -CFLAGS += -fpic -fno-common -CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions -#CFLAGS += -fdata-sections -ffunction-sections + +CFLAGS_ARCH += -fpic -fno-common +CFLAGS_ARCH += -U_FORTIFY_SOURCE # prevent use of __*_chk libc functions +#CFLAGS_ARCH += -fdata-sections -ffunction-sections MPY_CROSS_FLAGS += -march=$(ARCH) SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC))) $(patsubst %.S,%.o,$(filter %.S,$(SRC)))) SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC)))) +CLEAN_EXTRA += $(MOD).mpy .mpy_ld_cache + ################################################################################ # Architecture configuration @@ -45,66 +48,133 @@ ifeq ($(ARCH),x86) # x86 CROSS = -CFLAGS += -m32 -fno-stack-protector +CFLAGS_ARCH += -m32 -fno-stack-protector MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),x64) # x64 CROSS = -CFLAGS += -fno-stack-protector +CFLAGS_ARCH += -fno-stack-protector MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),armv6m) # thumb CROSS = arm-none-eabi- -CFLAGS += -mthumb -mcpu=cortex-m0 -MICROPY_FLOAT_IMPL ?= none +CFLAGS_ARCH += -mthumb -mcpu=cortex-m0 +MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7m) # thumb CROSS = arm-none-eabi- -CFLAGS += -mthumb -mcpu=cortex-m3 -MICROPY_FLOAT_IMPL ?= none +CFLAGS_ARCH += -mthumb -mcpu=cortex-m3 +MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7emsp) # thumb CROSS = arm-none-eabi- -CFLAGS += -mthumb -mcpu=cortex-m4 -CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard +CFLAGS_ARCH += -mthumb -mcpu=cortex-m4 +CFLAGS_ARCH += -mfpu=fpv4-sp-d16 -mfloat-abi=hard MICROPY_FLOAT_IMPL ?= float else ifeq ($(ARCH),armv7emdp) # thumb CROSS = arm-none-eabi- -CFLAGS += -mthumb -mcpu=cortex-m7 -CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard +CFLAGS_ARCH += -mthumb -mcpu=cortex-m7 +CFLAGS_ARCH += -mfpu=fpv5-d16 -mfloat-abi=hard MICROPY_FLOAT_IMPL ?= double else ifeq ($(ARCH),xtensa) # xtensa CROSS = xtensa-lx106-elf- -CFLAGS += -mforce-l32 +CFLAGS_ARCH += -mforce-l32 MICROPY_FLOAT_IMPL ?= none else ifeq ($(ARCH),xtensawin) # xtensawin CROSS = xtensa-esp32-elf- -CFLAGS += MICROPY_FLOAT_IMPL ?= float +else ifeq ($(ARCH),rv32imc) + +# rv32imc +CROSS = riscv64-unknown-elf- +CFLAGS_ARCH += -march=rv32imac -mabi=ilp32 -mno-relax +# If Picolibc is available then select it explicitly. Ubuntu 22.04 ships its +# bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default +# is "nosys" so a value must be provided. To avoid having per-distro +# workarounds, always select Picolibc if available. +PICOLIBC_SPECS := $(shell $(CROSS)gcc --print-file-name=picolibc.specs) +ifneq ($(PICOLIBC_SPECS),picolibc.specs) +CFLAGS_ARCH += -specs=$(PICOLIBC_SPECS) +USE_PICOLIBC := 1 +PICOLIBC_ARCH := rv32imac +PICOLIBC_ABI := ilp32 +endif + +MICROPY_FLOAT_IMPL ?= none + else $(error architecture '$(ARCH)' not supported) endif +ifneq ($(findstring -musl,$(shell $(CROSS)gcc -dumpmachine)),) +USE_MUSL := 1 +endif + MICROPY_FLOAT_IMPL_UPPER = $(shell echo $(MICROPY_FLOAT_IMPL) | tr '[:lower:]' '[:upper:]') -CFLAGS += -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_$(MICROPY_FLOAT_IMPL_UPPER) +CFLAGS += $(CFLAGS_ARCH) -DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_$(MICROPY_FLOAT_IMPL_UPPER) + +ifeq ($(LINK_RUNTIME),1) +# All of these picolibc-specific directives are here to work around a +# limitation of Ubuntu 22.04's RISC-V bare metal toolchain. In short, the +# specific version of GCC in use (10.2.0) does not seem to take into account +# extra paths provided by an explicitly passed specs file when performing name +# resolution via `--print-file-name`. +# +# If Picolibc is used and libc.a fails to resolve, then said file's path will +# be computed by searching the Picolibc libraries root for a libc.a file in a +# subdirectory whose path is built using the current `-march` and `-mabi` +# flags that are passed to GCC. The `PICOLIBC_ROOT` environment variable is +# checked to override the starting point for the library file search, and if +# it is not set then the default value is used, assuming that this is running +# on an Ubuntu 22.04 machine. +# +# This should be revised when the CI base image is updated to a newer Ubuntu +# version (that hopefully contains a newer RISC-V compiler) or to another Linux +# distribution. +ifeq ($(USE_PICOLIBC),1) +LIBM_NAME := libc.a +else ifeq ($(USE_MUSL),1) +LIBM_NAME := libc.a +else +LIBM_NAME := libm.a +endif +LIBGCC_PATH := $(realpath $(shell $(CROSS)gcc $(CFLAGS) --print-libgcc-file-name)) +LIBM_PATH := $(realpath $(shell $(CROSS)gcc $(CFLAGS) --print-file-name=$(LIBM_NAME))) +ifeq ($(USE_PICOLIBC),1) +ifeq ($(LIBM_PATH),) +# The CROSS toolchain prefix usually ends with a dash, but that may not be +# always the case. If the prefix ends with a dash it has to be taken out as +# Picolibc's architecture directory won't have it in its name. GNU Make does +# not have any facility to perform character-level text manipulation so we +# shell out to sed. +CROSS_PREFIX := $(shell echo $(CROSS) | sed -e 's/-$$//') +PICOLIBC_ROOT ?= /usr/lib/picolibc/$(CROSS_PREFIX)/lib +LIBM_PATH := $(PICOLIBC_ROOT)/$(PICOLIBC_ARCH)/$(PICOLIBC_ABI)/$(LIBM_NAME) +endif +endif +MPY_LD_FLAGS += $(addprefix -l, $(LIBGCC_PATH) $(LIBM_PATH)) +endif +ifneq ($(MPY_EXTERN_SYM_FILE),) +MPY_LD_FLAGS += --externs "$(realpath $(MPY_EXTERN_SYM_FILE))" +endif CFLAGS += $(CFLAGS_EXTRA) @@ -147,7 +217,7 @@ $(BUILD)/%.mpy: %.py # Build native .mpy from object files $(BUILD)/$(MOD).native.mpy: $(SRC_O) $(ECHO) "LINK $<" - $(Q)$(MPY_LD) --arch $(ARCH) --qstrs $(CONFIG_H) -o $@ $^ + $(Q)$(MPY_LD) --arch $(ARCH) --qstrs $(CONFIG_H) $(MPY_LD_FLAGS) -o $@ $^ # Build final .mpy from all intermediate .mpy files $(MOD).mpy: $(BUILD)/$(MOD).native.mpy $(SRC_MPY) diff --git a/py/emit.h b/py/emit.h index 26f978ba598ab..033ac9c763b07 100644 --- a/py/emit.h +++ b/py/emit.h @@ -144,6 +144,9 @@ typedef struct _emit_method_table_t { void (*unwind_jump)(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); void (*setup_block)(emit_t *emit, mp_uint_t label, int kind); void (*with_cleanup)(emit_t *emit, mp_uint_t label); + #if MICROPY_PY_ASYNC_AWAIT + void (*async_with_setup_finally)(emit_t *emit, mp_uint_t label_aexit_no_exc, mp_uint_t label_finally_block, mp_uint_t label_ret_unwind_jump); + #endif void (*end_finally)(emit_t *emit); void (*get_iter)(emit_t *emit, bool use_stack); void (*for_iter)(emit_t *emit, mp_uint_t label); @@ -201,6 +204,8 @@ extern const emit_method_table_t emit_native_thumb_method_table; extern const emit_method_table_t emit_native_arm_method_table; extern const emit_method_table_t emit_native_xtensa_method_table; extern const emit_method_table_t emit_native_xtensawin_method_table; +extern const emit_method_table_t emit_native_rv32_method_table; +extern const emit_method_table_t emit_native_debug_method_table; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_load_id_ops; extern const mp_emit_method_table_id_ops_t mp_emit_bc_method_table_store_id_ops; @@ -213,6 +218,8 @@ emit_t *emit_native_thumb_new(mp_emit_common_t *emit_common, mp_obj_t *error_slo emit_t *emit_native_arm_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_xtensa_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); emit_t *emit_native_xtensawin_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); +emit_t *emit_native_rv32_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); +emit_t *emit_native_debug_new(mp_emit_common_t *emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels); void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels); @@ -223,6 +230,8 @@ void emit_native_thumb_free(emit_t *emit); void emit_native_arm_free(emit_t *emit); void emit_native_xtensa_free(emit_t *emit); void emit_native_xtensawin_free(emit_t *emit); +void emit_native_rv32_free(emit_t *emit); +void emit_native_debug_free(emit_t *emit); void mp_emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope); bool mp_emit_bc_end_pass(emit_t *emit); @@ -258,6 +267,9 @@ void mp_emit_bc_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label); void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth); void mp_emit_bc_setup_block(emit_t *emit, mp_uint_t label, int kind); void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label); +#if MICROPY_PY_ASYNC_AWAIT +void mp_emit_bc_async_with_setup_finally(emit_t *emit, mp_uint_t label_aexit_no_exc, mp_uint_t label_finally_block, mp_uint_t label_ret_unwind_jump); +#endif void mp_emit_bc_end_finally(emit_t *emit); void mp_emit_bc_get_iter(emit_t *emit, bool use_stack); void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label); @@ -295,12 +307,15 @@ typedef struct _emit_inline_asm_method_table_t { void (*op)(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args); } emit_inline_asm_method_table_t; +extern const emit_inline_asm_method_table_t emit_inline_rv32_method_table; extern const emit_inline_asm_method_table_t emit_inline_thumb_method_table; extern const emit_inline_asm_method_table_t emit_inline_xtensa_method_table; +emit_inline_asm_t *emit_inline_rv32_new(mp_uint_t max_num_labels); emit_inline_asm_t *emit_inline_thumb_new(mp_uint_t max_num_labels); emit_inline_asm_t *emit_inline_xtensa_new(mp_uint_t max_num_labels); +void emit_inline_rv32_free(emit_inline_asm_t *emit); void emit_inline_thumb_free(emit_inline_asm_t *emit); void emit_inline_xtensa_free(emit_inline_asm_t *emit); diff --git a/py/emitbc.c b/py/emitbc.c index a07657408fabe..0bcac8a167627 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -83,7 +83,8 @@ emit_t *emit_bc_new(mp_emit_common_t *emit_common) { void emit_bc_set_max_num_labels(emit_t *emit, mp_uint_t max_num_labels) { emit->max_num_labels = max_num_labels; - emit->label_offsets = m_new(size_t, emit->max_num_labels); + // CIRCUITPY-CHANGE: Don't collect the label offsets + emit->label_offsets = m_malloc_without_collect(sizeof(size_t) * emit->max_num_labels); } void emit_bc_free(emit_t *emit) { @@ -92,7 +93,7 @@ void emit_bc_free(emit_t *emit) { } // all functions must go through this one to emit code info -STATIC uint8_t *emit_get_cur_to_write_code_info(void *emit_in, size_t num_bytes_to_write) { +static uint8_t *emit_get_cur_to_write_code_info(void *emit_in, size_t num_bytes_to_write) { emit_t *emit = emit_in; if (emit->pass < MP_PASS_EMIT) { emit->code_info_offset += num_bytes_to_write; @@ -105,16 +106,16 @@ STATIC uint8_t *emit_get_cur_to_write_code_info(void *emit_in, size_t num_bytes_ } } -STATIC void emit_write_code_info_byte(emit_t *emit, byte val) { +static void emit_write_code_info_byte(emit_t *emit, byte val) { *emit_get_cur_to_write_code_info(emit, 1) = val; } -STATIC void emit_write_code_info_qstr(emit_t *emit, qstr qst) { +static void emit_write_code_info_qstr(emit_t *emit, qstr qst) { mp_encode_uint(emit, emit_get_cur_to_write_code_info, mp_emit_common_use_qstr(emit->emit_common, qst)); } #if MICROPY_ENABLE_SOURCE_LINE -STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) { +static void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_skip, mp_uint_t lines_to_skip) { assert(bytes_to_skip > 0 || lines_to_skip > 0); while (bytes_to_skip > 0 || lines_to_skip > 0) { mp_uint_t b, l; @@ -143,7 +144,7 @@ STATIC void emit_write_code_info_bytes_lines(emit_t *emit, mp_uint_t bytes_to_sk #endif // all functions must go through this one to emit byte code -STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) { +static uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_to_write) { emit_t *emit = emit_in; if (emit->suppress) { return emit->dummy_data; @@ -159,19 +160,19 @@ STATIC uint8_t *emit_get_cur_to_write_bytecode(void *emit_in, size_t num_bytes_t } } -STATIC void emit_write_bytecode_raw_byte(emit_t *emit, byte b1) { +static void emit_write_bytecode_raw_byte(emit_t *emit, byte b1) { byte *c = emit_get_cur_to_write_bytecode(emit, 1); c[0] = b1; } -STATIC void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) { +static void emit_write_bytecode_byte(emit_t *emit, int stack_adj, byte b1) { mp_emit_bc_adjust_stack_size(emit, stack_adj); byte *c = emit_get_cur_to_write_bytecode(emit, 1); c[0] = b1; } // Similar to mp_encode_uint(), just some extra handling to encode sign -STATIC void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) { +static void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, mp_int_t num) { emit_write_bytecode_byte(emit, stack_adj, b1); // We store each 7 bits in a separate byte, and that's how many bytes needed @@ -197,24 +198,24 @@ STATIC void emit_write_bytecode_byte_int(emit_t *emit, int stack_adj, byte b1, m *c = *p; } -STATIC void emit_write_bytecode_byte_uint(emit_t *emit, int stack_adj, byte b, mp_uint_t val) { +static void emit_write_bytecode_byte_uint(emit_t *emit, int stack_adj, byte b, mp_uint_t val) { emit_write_bytecode_byte(emit, stack_adj, b); mp_encode_uint(emit, emit_get_cur_to_write_bytecode, val); } -STATIC void emit_write_bytecode_byte_const(emit_t *emit, int stack_adj, byte b, mp_uint_t n) { +static void emit_write_bytecode_byte_const(emit_t *emit, int stack_adj, byte b, mp_uint_t n) { emit_write_bytecode_byte_uint(emit, stack_adj, b, n); } -STATIC void emit_write_bytecode_byte_qstr(emit_t *emit, int stack_adj, byte b, qstr qst) { +static void emit_write_bytecode_byte_qstr(emit_t *emit, int stack_adj, byte b, qstr qst) { emit_write_bytecode_byte_uint(emit, stack_adj, b, mp_emit_common_use_qstr(emit->emit_common, qst)); } -STATIC void emit_write_bytecode_byte_obj(emit_t *emit, int stack_adj, byte b, mp_obj_t obj) { +static void emit_write_bytecode_byte_obj(emit_t *emit, int stack_adj, byte b, mp_obj_t obj) { emit_write_bytecode_byte_const(emit, stack_adj, b, mp_emit_common_use_const_obj(emit->emit_common, obj)); } -STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, mp_raw_code_t *rc) { +static void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, mp_raw_code_t *rc) { emit_write_bytecode_byte_const(emit, stack_adj, b, mp_emit_common_alloc_const_child(emit->emit_common, rc)); #if MICROPY_PY_SYS_SETTRACE @@ -227,7 +228,7 @@ STATIC void emit_write_bytecode_byte_child(emit_t *emit, int stack_adj, byte b, // The offset is encoded as either 1 or 2 bytes, depending on how big it is. // The encoding of this jump opcode can change size from one pass to the next, // but it must only ever decrease in size on successive passes. -STATIC void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { +static void emit_write_bytecode_byte_label(emit_t *emit, int stack_adj, byte b1, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, stack_adj); if (emit->suppress) { @@ -373,7 +374,8 @@ bool mp_emit_bc_end_pass(emit_t *emit) { // calculate size of total code-info + bytecode, in bytes emit->code_info_size = emit->code_info_offset; emit->bytecode_size = emit->bytecode_offset; - emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size); + // CIRCUITPY-CHANGE: Don't collect the bytecode or code info. + emit->code_base = m_malloc_without_collect(sizeof(byte) * (emit->code_info_size + emit->bytecode_size)); } else if (emit->pass == MP_PASS_EMIT) { // Code info and/or bytecode can shrink during this pass. @@ -393,13 +395,18 @@ bool mp_emit_bc_end_pass(emit_t *emit) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("bytecode overflow")); } + #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS + size_t bytecode_len = emit->code_info_size + emit->bytecode_size; + #if MICROPY_DEBUG_PRINTERS + emit->scope->raw_code_data_len = bytecode_len; + #endif + #endif + // Bytecode is finalised, assign it to the raw code object. mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base, - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - emit->code_info_size + emit->bytecode_size, - #endif emit->emit_common->children, #if MICROPY_PERSISTENT_CODE_SAVE + bytecode_len, emit->emit_common->ct_cur_child, #endif emit->scope->scope_flags); @@ -443,7 +450,6 @@ void mp_emit_bc_label_assign(emit_t *emit, mp_uint_t l) { // should be emitted (until another unconditional flow control). emit->suppress = false; - mp_emit_bc_adjust_stack_size(emit, 0); if (emit->pass == MP_PASS_SCOPE) { return; } @@ -662,6 +668,27 @@ void mp_emit_bc_with_cleanup(emit_t *emit, mp_uint_t label) { mp_emit_bc_adjust_stack_size(emit, -4); } +#if MICROPY_PY_ASYNC_AWAIT +void mp_emit_bc_async_with_setup_finally(emit_t *emit, mp_uint_t label_aexit_no_exc, mp_uint_t label_finally_block, mp_uint_t label_ret_unwind_jump) { + // The async-with body has executed and no exception was raised, the execution fell through to this point. + // Stack: (..., ctx_mgr) + + // Finish async-with body and prepare to enter "finally" block. + mp_emit_bc_load_const_tok(emit, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception + mp_emit_bc_rot_two(emit); + mp_emit_bc_jump(emit, label_aexit_no_exc); // jump to code to call __aexit__ + + // Start of "finally" block which is entered via one of: an exception propagating out, a return, an unwind jump. + mp_emit_bc_label_assign(emit, label_finally_block); + + // Detect which case we have by the TOS being an exception or not. + mp_emit_bc_dup_top(emit); + mp_emit_bc_load_global(emit, MP_QSTR_BaseException, MP_EMIT_IDOP_GLOBAL_GLOBAL); + mp_emit_bc_binary_op(emit, MP_BINARY_OP_EXCEPTION_MATCH); + mp_emit_bc_pop_jump_if(emit, false, label_ret_unwind_jump); // if not an exception then we have return or unwind jump. +} +#endif + void mp_emit_bc_end_finally(emit_t *emit) { emit_write_bytecode_byte(emit, -1, MP_BC_END_FINALLY); } @@ -764,15 +791,15 @@ void mp_emit_bc_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_ov } } -STATIC void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { +static void emit_bc_call_function_method_helper(emit_t *emit, int stack_adj, mp_uint_t bytecode_base, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { if (star_flags) { // each positional arg is one object, each kwarg is two objects, the key // and the value and one extra object for the star args bitmap. stack_adj -= (int)n_positional + 2 * (int)n_keyword + 1; - emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base + 1, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? + emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base + 1, (n_keyword << 8) | n_positional); } else { stack_adj -= (int)n_positional + 2 * (int)n_keyword; - emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base, (n_keyword << 8) | n_positional); // TODO make it 2 separate uints? + emit_write_bytecode_byte_uint(emit, stack_adj, bytecode_base, (n_keyword << 8) | n_positional); } } @@ -858,6 +885,9 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_unwind_jump, mp_emit_bc_setup_block, mp_emit_bc_with_cleanup, + #if MICROPY_PY_ASYNC_AWAIT + mp_emit_bc_async_with_setup_finally, + #endif mp_emit_bc_end_finally, mp_emit_bc_get_iter, mp_emit_bc_for_iter, diff --git a/py/emitcommon.c b/py/emitcommon.c index a9eb6e2021fc8..1369c544c54f5 100644 --- a/py/emitcommon.c +++ b/py/emitcommon.c @@ -25,6 +25,7 @@ */ #include +#include #include "py/emit.h" #include "py/nativeglue.h" @@ -72,7 +73,25 @@ static bool strictly_equal(mp_obj_t a, mp_obj_t b) { } return true; } else { - return mp_obj_equal(a, b); + if (!mp_obj_equal(a, b)) { + return false; + } + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_COMP_CONST_FLOAT + if (a_type == &mp_type_float) { + mp_float_t a_val = mp_obj_float_get(a); + // CIRCUITPY-CHANGE: ignore float equal warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + if (a_val == (mp_float_t)0.0) { + // Although 0.0 == -0.0, they are not strictly_equal and + // must be stored as two different constants in .mpy files + mp_float_t b_val = mp_obj_float_get(b); + return signbit(a_val) == signbit(b_val); + } + #pragma GCC diagnostic pop + } + #endif + return true; } } diff --git a/py/emitglue.c b/py/emitglue.c index d78ef48315967..c6ad3e3bc3845 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -32,6 +32,7 @@ #include #include "py/emitglue.h" +#include "py/mphal.h" #include "py/runtime0.h" #include "py/bc.h" #include "py/objfun.h" @@ -63,24 +64,23 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) { } void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - size_t len, - #endif mp_raw_code_t **children, #if MICROPY_PERSISTENT_CODE_SAVE - size_t n_children, + size_t len, + uint16_t n_children, #endif - mp_uint_t scope_flags) { + uint16_t scope_flags) { rc->kind = MP_CODE_BYTECODE; - rc->scope_flags = scope_flags; + rc->is_generator = (scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0; + // CIRCUITPY-CHANGE: async and generator are distinguished + // For async, BOTH is_generator and is_async will be set. + rc->is_async = (scope_flags & MP_SCOPE_FLAG_ASYNC) != 0; rc->fun_data = code; - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - rc->fun_data_len = len; - #endif rc->children = children; #if MICROPY_PERSISTENT_CODE_SAVE + rc->fun_data_len = len; rc->n_children = n_children; #endif @@ -91,7 +91,7 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, // CIRCUITPY-CHANGE: prevent warning #if defined(DEBUG_PRINT) && DEBUG_PRINT - #if !(MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS) + #if !MICROPY_PERSISTENT_CODE_SAVE const size_t len = 0; #endif DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags); @@ -99,13 +99,14 @@ void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, } #if MICROPY_EMIT_MACHINE_CODE -void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, +void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, const void *fun_data, mp_uint_t fun_len, mp_raw_code_t **children, #if MICROPY_PERSISTENT_CODE_SAVE - size_t n_children, + uint16_t n_children, uint16_t prelude_offset, #endif - mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t type_sig) { + uint16_t scope_flags, uint32_t asm_n_pos_args, uint32_t asm_type_sig + ) { assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM); @@ -122,7 +123,7 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void #endif #elif MICROPY_EMIT_ARM #if (defined(__linux__) && defined(__GNUC__)) || __ARM_ARCH == 7 - __builtin___clear_cache(fun_data, (uint8_t *)fun_data + fun_len); + __builtin___clear_cache((void *)fun_data, (char *)fun_data + fun_len); #elif defined(__arm__) // Flush I-cache and D-cache. asm volatile ( @@ -133,13 +134,19 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void "mcr p15, 0, r0, c7, c7, 0\n" // invalidate I-cache and D-cache : : : "r0", "cc"); #endif + #elif (MICROPY_EMIT_RV32 || MICROPY_EMIT_INLINE_RV32) && defined(MP_HAL_CLEAN_DCACHE) + // Flush the D-cache. + MP_HAL_CLEAN_DCACHE(fun_data, fun_len); #endif rc->kind = kind; - rc->scope_flags = scope_flags; + rc->is_generator = (scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0; + // CIRCUITPY-CHANGE: async and generator are distinguished + // For async, BOTH is_generator and is_async will be set. + rc->is_async = (scope_flags & MP_SCOPE_FLAG_ASYNC) != 0; rc->fun_data = fun_data; - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS + #if MICROPY_PERSISTENT_CODE_SAVE rc->fun_data_len = fun_len; #endif rc->children = children; @@ -149,21 +156,23 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void rc->prelude_offset = prelude_offset; #endif + #if MICROPY_EMIT_INLINE_ASM // These two entries are only needed for MP_CODE_NATIVE_ASM. - rc->n_pos_args = n_pos_args; - rc->type_sig = type_sig; + rc->asm_n_pos_args = asm_n_pos_args; + rc->asm_type_sig = asm_type_sig; + #endif #if DEBUG_PRINT - DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags); + DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, (uint)scope_flags); for (mp_uint_t i = 0; i < fun_len; i++) { if (i > 0 && i % 16 == 0) { DEBUG_printf("\n"); } - DEBUG_printf(" %02x", ((byte *)fun_data)[i]); + DEBUG_printf(" %02x", ((const byte *)fun_data)[i]); } DEBUG_printf("\n"); - #ifdef WRITE_CODE + #if WRITE_CODE FILE *fp_write_code = fopen("out-code", "wb"); fwrite(fun_data, fun_len, 1, fp_write_code); fclose(fp_write_code); @@ -174,9 +183,9 @@ void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void } #endif -mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, const mp_obj_t *def_args) { - DEBUG_OP_printf("make_function_from_raw_code %p\n", rc); - assert(rc != NULL); +mp_obj_t mp_make_function_from_proto_fun(mp_proto_fun_t proto_fun, const mp_module_context_t *context, const mp_obj_t *def_args) { + DEBUG_OP_printf("make_function_from_proto_fun %p\n", proto_fun); + assert(proto_fun != NULL); // def_args must be MP_OBJ_NULL or a tuple assert(def_args == NULL || def_args[0] == MP_OBJ_NULL || mp_obj_is_type(def_args[0], &mp_type_tuple)); @@ -184,25 +193,55 @@ mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module // def_kw_args must be MP_OBJ_NULL or a dict assert(def_args == NULL || def_args[1] == MP_OBJ_NULL || mp_obj_is_type(def_args[1], &mp_type_dict)); + #if MICROPY_MODULE_FROZEN_MPY + if (mp_proto_fun_is_bytecode(proto_fun)) { + const uint8_t *bc = proto_fun; + mp_obj_t fun = mp_obj_new_fun_bc(def_args, bc, context, NULL); + MP_BC_PRELUDE_SIG_DECODE(bc); + // CIRCUITPY-CHANGE: distinguish generators and async + // A coroutine is MP_SCOPE_FLAG_ASYNC | MP_SCOPE_FLAG_GENERATOR, + // so check for ASYNC first. + #if MICROPY_PY_ASYNC_AWAIT + if (scope_flags & MP_SCOPE_FLAG_ASYNC) { + ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_coro_wrap; + } else + #endif + if (scope_flags & MP_SCOPE_FLAG_GENERATOR) { + ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap; + } + return fun; + } + #endif + + // the proto-function is a mp_raw_code_t + const mp_raw_code_t *rc = proto_fun; + // make the function, depending on the raw code kind mp_obj_t fun; switch (rc->kind) { #if MICROPY_EMIT_NATIVE case MP_CODE_NATIVE_PY: - case MP_CODE_NATIVE_VIPER: fun = mp_obj_new_fun_native(def_args, rc->fun_data, context, rc->children); // Check for a generator function, and if so change the type of the object // CIRCUITPY-CHANGE: distinguish generators and async - if ((rc->scope_flags & MP_SCOPE_FLAG_ASYNC) != 0) { + #if MICROPY_PY_ASYNC_AWAIT + // For async, BOTH is_async and is_generator will be set, + // so check is_async first. + if ((rc->is_async) != 0) { ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_native_coro_wrap; - } else if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { + } else + #endif + if ((rc->is_generator) != 0) { ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_native_gen_wrap; } break; + case MP_CODE_NATIVE_VIPER: + fun = mp_obj_new_fun_viper(rc->fun_data, context, rc->children); + break; #endif #if MICROPY_EMIT_INLINE_ASM case MP_CODE_NATIVE_ASM: - fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->fun_data, rc->type_sig); + fun = mp_obj_new_fun_asm(rc->asm_n_pos_args, rc->fun_data, rc->asm_type_sig); break; #endif default: @@ -211,14 +250,14 @@ mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module fun = mp_obj_new_fun_bc(def_args, rc->fun_data, context, rc->children); // check for generator functions and if so change the type of the object // CIRCUITPY-CHANGE: distinguish generators and async - // A generator is MP_SCOPE_FLAG_ASYNC | MP_SCOPE_FLAG_GENERATOR, - // so check for ASYNC first. + // For async, BOTH is_async and is_generator will be set, + // so check is_async first. #if MICROPY_PY_ASYNC_AWAIT - if ((rc->scope_flags & MP_SCOPE_FLAG_ASYNC) != 0) { + if ((rc->is_async) != 0) { ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_coro_wrap; } else #endif - if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) { + if ((rc->is_generator) != 0) { ((mp_obj_base_t *)MP_OBJ_TO_PTR(fun))->type = &mp_type_gen_wrap; } @@ -233,16 +272,16 @@ mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module return fun; } -mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args) { - DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args); +mp_obj_t mp_make_closure_from_proto_fun(mp_proto_fun_t proto_fun, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args) { + DEBUG_OP_printf("make_closure_from_proto_fun %p " UINT_FMT " %p\n", proto_fun, n_closed_over, args); // make function object mp_obj_t ffun; if (n_closed_over & 0x100) { // default positional and keyword args given - ffun = mp_make_function_from_raw_code(rc, context, args); + ffun = mp_make_function_from_proto_fun(proto_fun, context, args); } else { // default positional and keyword args not given - ffun = mp_make_function_from_raw_code(rc, context, NULL); + ffun = mp_make_function_from_proto_fun(proto_fun, context, NULL); } // wrap function in closure object return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2)); diff --git a/py/emitglue.h b/py/emitglue.h index 4ddf74011fa70..d19503b823f4c 100644 --- a/py/emitglue.h +++ b/py/emitglue.h @@ -31,6 +31,11 @@ // These variables and functions glue the code emitters to the runtime. +// Used with mp_raw_code_t::proto_fun_indicator to detect if a mp_proto_fun_t is a +// mp_raw_code_t struct or a direct pointer to bytecode. +#define MP_PROTO_FUN_INDICATOR_RAW_CODE_0 (0) +#define MP_PROTO_FUN_INDICATOR_RAW_CODE_1 (0) + // These must fit in 8 bits; see scope.h enum { MP_EMIT_OPT_NONE, @@ -49,58 +54,97 @@ typedef enum { MP_CODE_NATIVE_ASM, } mp_raw_code_kind_t; +// An mp_proto_fun_t points to static information about a non-instantiated function. +// A function object is created from this information, and that object can then be executed. +// It points either to bytecode, or an mp_raw_code_t struct. +typedef const void *mp_proto_fun_t; + +// Bytecode is distinguished from an mp_raw_code_t struct by the first two bytes: bytecode +// is guaranteed to have either its first or second byte non-zero. So if both bytes are +// zero then the mp_proto_fun_t pointer must be an mp_raw_code_t. +static inline bool mp_proto_fun_is_bytecode(mp_proto_fun_t proto_fun) { + const uint8_t *header = (const uint8_t *)proto_fun; + return (header[0] | (header[1] << 8)) != (MP_PROTO_FUN_INDICATOR_RAW_CODE_0 | (MP_PROTO_FUN_INDICATOR_RAW_CODE_1 << 8)); +} + +// The mp_raw_code_t struct appears in the following places: // compiled bytecode: instance in RAM, referenced by outer scope, usually freed after first (and only) use // mpy file: instance in RAM, created when .mpy file is loaded (same comments as above) // frozen: instance in ROM typedef struct _mp_raw_code_t { - mp_uint_t kind : 3; // of type mp_raw_code_kind_t - mp_uint_t scope_flags : 7; - mp_uint_t n_pos_args : 11; + uint8_t proto_fun_indicator[2]; + uint8_t kind; // of type mp_raw_code_kind_t; only 3 bits used + // CIRCUITPY-CHANGE: distinguish generator and async + // For async, BOTH is_generator and is_async will be set. + bool is_generator : 1; + bool is_async : 1; const void *fun_data; - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - size_t fun_data_len; // so mp_raw_code_save and mp_bytecode_print work - #endif struct _mp_raw_code_t **children; #if MICROPY_PERSISTENT_CODE_SAVE - size_t n_children; + uint32_t fun_data_len; // for mp_raw_code_save + uint16_t n_children; + #if MICROPY_EMIT_MACHINE_CODE + uint16_t prelude_offset; + #endif #if MICROPY_PY_SYS_SETTRACE - mp_bytecode_prelude_t prelude; // line_of_definition is a Python source line where the raw_code was // created e.g. MP_BC_MAKE_FUNCTION. This is different from lineno info // stored in prelude, which provides line number for first statement of // a function. Required to properly implement "call" trace event. - mp_uint_t line_of_definition; + uint32_t line_of_definition; + mp_bytecode_prelude_t prelude; #endif + #endif + #if MICROPY_EMIT_INLINE_ASM + uint32_t asm_n_pos_args : 8; + uint32_t asm_type_sig : 24; // compressed as 2-bit types; ret is MSB, then arg0, arg1, etc + #endif +} mp_raw_code_t; + +// Version of mp_raw_code_t but without the asm_n_pos_args/asm_type_sig entries, which are +// only needed when the kind is MP_CODE_NATIVE_ASM. So this struct can be used when the +// kind is MP_CODE_BYTECODE, MP_CODE_NATIVE_PY or MP_CODE_NATIVE_VIPER, to reduce its size. +typedef struct _mp_raw_code_truncated_t { + uint8_t proto_fun_indicator[2]; + uint8_t kind; + // CIRCUITPY-CHANGE: distinguish generator and async + // For async, BOTH is_generator and is_async will be set. + bool is_generator : 1; + bool is_async : 1; + const void *fun_data; + struct _mp_raw_code_t **children; + #if MICROPY_PERSISTENT_CODE_SAVE + uint32_t fun_data_len; + uint16_t n_children; #if MICROPY_EMIT_MACHINE_CODE uint16_t prelude_offset; #endif + #if MICROPY_PY_SYS_SETTRACE + uint32_t line_of_definition; + mp_bytecode_prelude_t prelude; #endif - #if MICROPY_EMIT_MACHINE_CODE - mp_uint_t type_sig; // for viper, compressed as 2-bit types; ret is MSB, then arg0, arg1, etc #endif -} mp_raw_code_t; +} mp_raw_code_truncated_t; mp_raw_code_t *mp_emit_glue_new_raw_code(void); void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - size_t len, - #endif mp_raw_code_t **children, #if MICROPY_PERSISTENT_CODE_SAVE - size_t n_children, + size_t len, + uint16_t n_children, #endif - mp_uint_t scope_flags); + uint16_t scope_flags); -void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, +void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, const void *fun_data, mp_uint_t fun_len, mp_raw_code_t **children, #if MICROPY_PERSISTENT_CODE_SAVE - size_t n_children, + uint16_t n_children, uint16_t prelude_offset, #endif - mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t type_sig); + uint16_t scope_flags, uint32_t asm_n_pos_args, uint32_t asm_type_sig); -mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, const mp_obj_t *def_args); -mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args); +mp_obj_t mp_make_function_from_proto_fun(mp_proto_fun_t proto_fun, const mp_module_context_t *context, const mp_obj_t *def_args); +mp_obj_t mp_make_closure_from_proto_fun(mp_proto_fun_t proto_fun, const mp_module_context_t *context, mp_uint_t n_closed_over, const mp_obj_t *args); #endif // MICROPY_INCLUDED_PY_EMITGLUE_H diff --git a/py/emitinlinerv32.c b/py/emitinlinerv32.c new file mode 100644 index 0000000000000..e81b152087de3 --- /dev/null +++ b/py/emitinlinerv32.c @@ -0,0 +1,767 @@ +/* + * This file is part of the MicroPython project, https://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "py/emit.h" +#include "py/misc.h" + +#if MICROPY_EMIT_INLINE_RV32 + +#include "py/asmrv32.h" + +typedef enum { +// define rules with a compile function +#define DEF_RULE(rule, comp, kind, ...) PN_##rule, +#define DEF_RULE_NC(rule, kind, ...) + #include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC + PN_const_object, // special node for a constant, generic Python object +// define rules without a compile function +#define DEF_RULE(rule, comp, kind, ...) +#define DEF_RULE_NC(rule, kind, ...) PN_##rule, + #include "py/grammar.h" +#undef DEF_RULE +#undef DEF_RULE_NC +} pn_kind_t; + +struct _emit_inline_asm_t { + asm_rv32_t as; + uint16_t pass; + mp_obj_t *error_slot; + mp_uint_t max_num_labels; + qstr *label_lookup; +}; + +static const qstr_short_t REGISTERS_QSTR_TABLE[] = { + MP_QSTR_zero, MP_QSTR_ra, MP_QSTR_sp, MP_QSTR_gp, MP_QSTR_tp, MP_QSTR_t0, MP_QSTR_t1, MP_QSTR_t2, + MP_QSTR_s0, MP_QSTR_s1, MP_QSTR_a0, MP_QSTR_a1, MP_QSTR_a2, MP_QSTR_a3, MP_QSTR_a4, MP_QSTR_a5, + MP_QSTR_a6, MP_QSTR_a7, MP_QSTR_s2, MP_QSTR_s3, MP_QSTR_s4, MP_QSTR_s5, MP_QSTR_s6, MP_QSTR_s7, + MP_QSTR_s8, MP_QSTR_s9, MP_QSTR_s10, MP_QSTR_s11, MP_QSTR_t3, MP_QSTR_t4, MP_QSTR_t5, MP_QSTR_t6, + MP_QSTR_x0, MP_QSTR_x1, MP_QSTR_x2, MP_QSTR_x3, MP_QSTR_x4, MP_QSTR_x5, MP_QSTR_x6, MP_QSTR_x7, + MP_QSTR_x8, MP_QSTR_x9, MP_QSTR_x10, MP_QSTR_x11, MP_QSTR_x12, MP_QSTR_x13, MP_QSTR_x14, MP_QSTR_x15, + MP_QSTR_x16, MP_QSTR_x17, MP_QSTR_x18, MP_QSTR_x19, MP_QSTR_x20, MP_QSTR_x21, MP_QSTR_x22, MP_QSTR_x23, + MP_QSTR_x24, MP_QSTR_x25, MP_QSTR_x26, MP_QSTR_x27, MP_QSTR_x28, MP_QSTR_x29, MP_QSTR_x30, MP_QSTR_x31, +}; + +//////////////////////////////////////////////////////////////////////////////// + +static inline void emit_inline_rv32_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) { + *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); +} + +static inline void emit_inline_rv32_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { + *emit->error_slot = exc; +} + +emit_inline_asm_t *emit_inline_rv32_new(mp_uint_t max_num_labels) { + emit_inline_asm_t *emit = m_new_obj(emit_inline_asm_t); + memset(&emit->as, 0, sizeof(emit->as)); + mp_asm_base_init(&emit->as.base, max_num_labels); + emit->max_num_labels = max_num_labels; + emit->label_lookup = m_new(qstr, max_num_labels); + return emit; +} + +void emit_inline_rv32_free(emit_inline_asm_t *emit) { + m_del(qstr, emit->label_lookup, emit->max_num_labels); + mp_asm_base_deinit(&emit->as.base, false); + m_del_obj(emit_inline_asm_t, emit); +} + +static void emit_inline_rv32_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { + emit->pass = pass; + emit->error_slot = error_slot; + if (emit->pass == MP_PASS_CODE_SIZE) { + memset(emit->label_lookup, 0, emit->max_num_labels * sizeof(qstr)); + } + mp_asm_base_start_pass(&emit->as.base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); +} + +static void emit_inline_rv32_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { + // c.jr ra + asm_rv32_opcode_cjr(&emit->as, ASM_RV32_REG_RA); + asm_rv32_end_pass(&emit->as); +} + +static bool parse_register_node(mp_parse_node_t node, mp_uint_t *register_number, bool compressed) { + assert(register_number != NULL && "Register number pointer is NULL."); + + if (!MP_PARSE_NODE_IS_ID(node)) { + return false; + } + + qstr node_qstr = MP_PARSE_NODE_LEAF_ARG(node); + for (mp_uint_t index = 0; index < MP_ARRAY_SIZE(REGISTERS_QSTR_TABLE); index++) { + if (node_qstr == REGISTERS_QSTR_TABLE[index]) { + mp_uint_t number = index % RV32_AVAILABLE_REGISTERS_COUNT; + if (!compressed || (compressed && RV32_IS_IN_C_REGISTER_WINDOW(number))) { + *register_number = compressed ? RV32_MAP_IN_C_REGISTER_WINDOW(number) : number; + return true; + } + break; + } + } + + return false; +} + +static mp_uint_t lookup_label(emit_inline_asm_t *emit, mp_parse_node_t node, qstr *qstring) { + assert(qstring && "qstring pointer is NULL"); + + *qstring = MP_PARSE_NODE_LEAF_ARG(node); + for (mp_uint_t label = 0; label < emit->max_num_labels; label++) { + if (emit->label_lookup[label] == *qstring) { + return label; + } + } + + return emit->max_num_labels; +} + +static inline ptrdiff_t label_code_offset(emit_inline_asm_t *emit, mp_uint_t label_index) { + return emit->as.base.label_offsets[label_index] - emit->as.base.code_offset; +} + +static mp_uint_t emit_inline_rv32_count_params(emit_inline_asm_t *emit, mp_uint_t parameters_count, mp_parse_node_t *parameter_nodes) { + // TODO: Raise this up to 8? RV32I has 8 A-registers that are meant to + // be used for passing arguments. + + if (parameters_count > 4) { + emit_inline_rv32_error_msg(emit, MP_ERROR_TEXT("can only have up to 4 parameters for RV32 assembly")); + return 0; + } + + mp_uint_t register_index = 0; + for (mp_uint_t index = 0; index < parameters_count; index++) { + bool valid_register = parse_register_node(parameter_nodes[index], ®ister_index, false); + if (!valid_register || (register_index != (ASM_RV32_REG_A0 + index))) { + emit_inline_rv32_error_msg(emit, MP_ERROR_TEXT("parameters must be registers in sequence a0 to a3")); + return 0; + } + } + + return parameters_count; +} + +static bool emit_inline_rv32_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { + assert(label_num < emit->max_num_labels); + if (emit->pass == MP_PASS_CODE_SIZE) { + for (mp_uint_t index = 0; index < emit->max_num_labels; index++) { + if (emit->label_lookup[index] == label_id) { + return false; + } + } + } + emit->label_lookup[label_num] = label_id; + mp_asm_base_label_assign(&emit->as.base, label_num); + return true; +} + +typedef enum { + CALL_RRR, // Opcode Register, Register, Register + CALL_RR, // Opcode Register, Register + CALL_RRI, // Opcode Register, Register, Immediate + CALL_RRL, // Opcode Register, Register, Label + CALL_RI, // Opcode Register, Immediate + CALL_L, // Opcode Label + CALL_R, // Opcode Register + CALL_RL, // Opcode Register, Label + CALL_N, // Opcode + CALL_RII, // Opcode Register, Register, Immediate + CALL_RIR, // Opcode Register, Immediate(Register) + CALL_COUNT +} call_convention_t; + +#define N 0 // No argument +#define R 1 // Register +#define I 2 // Immediate +#define L 3 // Label +#define C (1 << 2) // Compressed register +#define U (1 << 2) // Unsigned immediate +#define Z (1 << 3) // Non-zero + +typedef void (*call_ri_t)(asm_rv32_t *state, mp_uint_t rd, mp_int_t immediate); +typedef void (*call_rri_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_int_t immediate); +typedef void (*call_rii_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t immediate1, mp_int_t immediate2); +typedef void (*call_rrr_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs1, mp_uint_t rs2); +typedef void (*call_rr_t)(asm_rv32_t *state, mp_uint_t rd, mp_uint_t rs); +typedef void (*call_i_t)(asm_rv32_t *state, mp_int_t immediate); +typedef void (*call_r_t)(asm_rv32_t *state, mp_uint_t rd); +typedef void (*call_n_t)(asm_rv32_t *state); + +typedef struct _opcode_t { + qstr_short_t qstring; + uint16_t argument1_mask : 4; + uint16_t argument2_mask : 4; + uint16_t argument3_mask : 4; + uint16_t parse_nodes : 2; + // 2 bits available here + uint32_t calling_convention : 4; + uint32_t argument1_kind : 4; + uint32_t argument1_shift : 4; + uint32_t argument2_kind : 4; + uint32_t argument2_shift : 4; + uint32_t argument3_kind : 4; + uint32_t argument3_shift : 4; + uint32_t required_extensions : 1; + // 3 bits available here + void *emitter; +} opcode_t; + +#define opcode_li asm_rv32_emit_optimised_load_immediate + +static void opcode_la(asm_rv32_t *state, mp_uint_t rd, mp_int_t displacement) { + // This cannot be optimised for size, otherwise label addresses would move around. + mp_uint_t upper = (mp_uint_t)displacement & 0xFFFFF000; + mp_uint_t lower = (mp_uint_t)displacement & 0x00000FFF; + if ((lower & 0x800) != 0) { + upper += 0x1000; + } + asm_rv32_opcode_auipc(state, rd, upper); + asm_rv32_opcode_addi(state, rd, rd, lower); +} + +#define RC (R | C) +#define IU (I | U) +#define IZ (I | Z) +#define IUZ (I | U | Z) + +#define MASK_NOT_USED 0 + +enum { + MASK_FFFFFFFF, + MASK_00000FFF, + MASK_FFFFF000, + MASK_00001FFE, + MASK_0000001F, + MASK_FFFFFFFE, + MASK_0000003F, + MASK_0000FF00, + MASK_000003FC, + MASK_000001FE, + MASK_00000FFE, + MASK_FFFFFFFA, + MASK_0001F800, + MASK_0000007C, + MASK_000000FC, + MASK_001FFFFE, +}; + +static const uint32_t OPCODE_MASKS[] = { + [MASK_FFFFFFFF] = 0xFFFFFFFF, + [MASK_00000FFF] = 0x00000FFF, + [MASK_FFFFF000] = 0xFFFFF000, + [MASK_00001FFE] = 0x00001FFE, + [MASK_0000001F] = 0x0000001F, + [MASK_FFFFFFFE] = 0xFFFFFFFE, + [MASK_0000003F] = 0x0000003F, + [MASK_0000FF00] = 0x0000FF00, + [MASK_000003FC] = 0x000003FC, + [MASK_000001FE] = 0x000001FE, + [MASK_00000FFE] = 0x00000FFE, + [MASK_FFFFFFFA] = 0xFFFFFFFA, + [MASK_0001F800] = 0x0001F800, + [MASK_0000007C] = 0x0000007C, + [MASK_000000FC] = 0x000000FC, + [MASK_001FFFFE] = 0x001FFFFE, +}; + +static const opcode_t OPCODES[] = { + { MP_QSTR_add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_add }, + { MP_QSTR_addi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_addi }, + { MP_QSTR_and_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_and }, + { MP_QSTR_andi, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_andi }, + { MP_QSTR_auipc, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_auipc }, + { MP_QSTR_beq, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_beq }, + { MP_QSTR_bge, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bge }, + { MP_QSTR_bgeu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bgeu }, + { MP_QSTR_blt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_blt }, + { MP_QSTR_bltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bltu }, + { MP_QSTR_bne, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00001FFE, 3, CALL_RRL, R, 0, R, 0, L, 0, RV32_EXT_NONE, asm_rv32_opcode_bne }, + { MP_QSTR_csrrc, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrc }, + { MP_QSTR_csrrs, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrs }, + { MP_QSTR_csrrw, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrw }, + { MP_QSTR_csrrci, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrci }, + { MP_QSTR_csrrsi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrsi }, + { MP_QSTR_csrrwi, MASK_FFFFFFFF, MASK_00000FFF, MASK_0000001F, 3, CALL_RII, R, 0, IU, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_csrrwi }, + { MP_QSTR_c_add, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cadd }, + { MP_QSTR_c_addi, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, IZ, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_caddi }, + { MP_QSTR_c_addi4spn, MASK_0000FF00, MASK_000003FC, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_caddi4spn }, + { MP_QSTR_c_and, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cand }, + { MP_QSTR_c_andi, MASK_0000FF00, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, RC, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_candi }, + { MP_QSTR_c_beqz, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cbeqz }, + { MP_QSTR_c_bnez, MASK_0000FF00, MASK_000001FE, MASK_NOT_USED, 2, CALL_RL, RC, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cbnez }, + { MP_QSTR_c_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cebreak }, + { MP_QSTR_c_j, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cj }, + { MP_QSTR_c_jal, MASK_00000FFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_L, L, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjal }, + { MP_QSTR_c_jalr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjalr }, + { MP_QSTR_c_jr, MASK_FFFFFFFE, MASK_NOT_USED, MASK_NOT_USED, 1, CALL_R, R, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cjr }, + { MP_QSTR_c_li, MASK_FFFFFFFE, MASK_0000003F, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cli }, + { MP_QSTR_c_lui, MASK_FFFFFFFA, MASK_0001F800, MASK_NOT_USED, 2, CALL_RI, R, 0, IUZ, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_clui }, + { MP_QSTR_c_lw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 2, CALL_RIR, RC, 0, I, 0, RC, 0, RV32_EXT_NONE, asm_rv32_opcode_clw }, + { MP_QSTR_c_lwsp, MASK_FFFFFFFE, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_clwsp }, + { MP_QSTR_c_mv, MASK_FFFFFFFE, MASK_FFFFFFFE, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cmv }, + { MP_QSTR_c_nop, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cnop }, + { MP_QSTR_c_or, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cor }, + { MP_QSTR_c_slli, MASK_FFFFFFFE, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, R, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cslli }, + { MP_QSTR_c_srai, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csrai }, + { MP_QSTR_c_srli, MASK_0000FF00, MASK_0000001F, MASK_NOT_USED, 2, CALL_RI, RC, 0, IU, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csrli }, + { MP_QSTR_c_sub, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_csub }, + { MP_QSTR_c_sw, MASK_0000FF00, MASK_0000007C, MASK_0000FF00, 2, CALL_RIR, RC, 0, I, 0, RC, 0, RV32_EXT_NONE, asm_rv32_opcode_csw }, + { MP_QSTR_c_swsp, MASK_FFFFFFFF, MASK_000000FC, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cswsp }, + { MP_QSTR_c_xor, MASK_0000FF00, MASK_0000FF00, MASK_NOT_USED, 2, CALL_RR, RC, 0, RC, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cxor }, + { MP_QSTR_div, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_div }, + { MP_QSTR_divu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_divu }, + { MP_QSTR_ebreak, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_ebreak }, + { MP_QSTR_ecall, MASK_NOT_USED, MASK_NOT_USED, MASK_NOT_USED, 0, CALL_N, N, 0, N, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_ecall }, + { MP_QSTR_jal, MASK_FFFFFFFF, MASK_001FFFFE, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_jal }, + { MP_QSTR_jalr, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_jalr }, + { MP_QSTR_la, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RL, R, 0, L, 0, N, 0, RV32_EXT_NONE, opcode_la }, + { MP_QSTR_lb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lb }, + { MP_QSTR_lbu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lbu }, + { MP_QSTR_lh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lh }, + { MP_QSTR_lhu, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lhu }, + { MP_QSTR_li, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 0, N, 0, RV32_EXT_NONE, opcode_li }, + { MP_QSTR_lui, MASK_FFFFFFFF, MASK_FFFFF000, MASK_NOT_USED, 2, CALL_RI, R, 0, I, 12, N, 0, RV32_EXT_NONE, asm_rv32_opcode_lui }, + { MP_QSTR_lw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_lw }, + { MP_QSTR_mv, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_NOT_USED, 2, CALL_RR, R, 0, R, 0, N, 0, RV32_EXT_NONE, asm_rv32_opcode_cmv }, + { MP_QSTR_mul, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mul }, + { MP_QSTR_mulh, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulh }, + { MP_QSTR_mulhsu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulhsu }, + { MP_QSTR_mulhu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_mulhu }, + { MP_QSTR_or_, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_or }, + { MP_QSTR_ori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_ori }, + { MP_QSTR_rem, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_rem }, + { MP_QSTR_remu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_remu }, + { MP_QSTR_sb, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sb }, + { MP_QSTR_sh, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sh }, + { MP_QSTR_sh1add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh1add }, + { MP_QSTR_sh2add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh2add }, + { MP_QSTR_sh3add, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_ZBA, asm_rv32_opcode_sh3add }, + { MP_QSTR_sll, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sll }, + { MP_QSTR_slli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_slli }, + { MP_QSTR_slt, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_slt }, + { MP_QSTR_slti, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_slti }, + { MP_QSTR_sltiu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_sltiu }, + { MP_QSTR_sltu, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sltu }, + { MP_QSTR_sra, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sra }, + { MP_QSTR_srai, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_srai }, + { MP_QSTR_srl, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_srl }, + { MP_QSTR_srli, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_0000001F, 3, CALL_RRI, R, 0, R, 0, IU, 0, RV32_EXT_NONE, asm_rv32_opcode_srli }, + { MP_QSTR_sub, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sub }, + { MP_QSTR_sw, MASK_FFFFFFFF, MASK_00000FFF, MASK_FFFFFFFF, 2, CALL_RIR, R, 0, I, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_sw }, + { MP_QSTR_xor, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_FFFFFFFF, 3, CALL_RRR, R, 0, R, 0, R, 0, RV32_EXT_NONE, asm_rv32_opcode_xor }, + { MP_QSTR_xori, MASK_FFFFFFFF, MASK_FFFFFFFF, MASK_00000FFF, 3, CALL_RRI, R, 0, R, 0, I, 0, RV32_EXT_NONE, asm_rv32_opcode_xori }, +}; + +#undef RC +#undef IU +#undef IZ +#undef IUZ + +// These two checks assume the bitmasks are contiguous. + +static bool is_in_signed_mask(uint32_t mask, mp_uint_t value) { + uint32_t leading_zeroes = mp_clz(mask); + if (leading_zeroes == 0) { + return true; + } + mp_uint_t positive_mask = ~(mask & ~(1U << (31 - leading_zeroes))); + if ((value & positive_mask) == 0) { + return true; + } + mp_uint_t negative_mask = ~(mask >> 1); + mp_uint_t trailing_zeroes = mp_ctz(mask); + if (trailing_zeroes > 0) { + mp_uint_t trailing_mask = (1U << trailing_zeroes) - 1; + if ((value & trailing_mask) != 0) { + return false; + } + negative_mask &= ~trailing_mask; + } + return (value & negative_mask) == negative_mask; +} + +static inline bool is_in_unsigned_mask(mp_uint_t mask, mp_uint_t value) { + return (value & ~mask) == 0; +} + +static bool validate_integer(mp_uint_t value, mp_uint_t mask, mp_uint_t flags) { + if (flags & U) { + if (!is_in_unsigned_mask(mask, value)) { + return false; + } + } else { + if (!is_in_signed_mask(mask, value)) { + return false; + } + } + + if ((flags & Z) && (value == 0)) { + return false; + } + + return true; +} + +#define ET_WRONG_ARGUMENT_KIND MP_ERROR_TEXT("opcode '%q' argument %d: expecting %q") +#define ET_WRONG_ARGUMENTS_COUNT MP_ERROR_TEXT("opcode '%q': expecting %d arguments") +#define ET_OUT_OF_RANGE MP_ERROR_TEXT("opcode '%q' argument %d: out of range") + +static bool serialise_argument(emit_inline_asm_t *emit, const opcode_t *opcode, mp_parse_node_t node, mp_uint_t node_index, mp_uint_t *serialised) { + assert((node_index < 3) && "Invalid argument node number."); + assert(serialised && "Serialised value pointer is NULL."); + + uint32_t kind = 0; + uint32_t shift = 0; + uint32_t mask = 0; + + switch (node_index) { + case 0: + kind = opcode->argument1_kind; + shift = opcode->argument1_shift; + mask = OPCODE_MASKS[opcode->argument1_mask]; + break; + + case 1: + kind = opcode->argument2_kind; + shift = opcode->argument2_shift; + mask = OPCODE_MASKS[opcode->argument2_mask]; + break; + + case 2: + kind = opcode->argument3_kind; + shift = opcode->argument3_shift; + mask = OPCODE_MASKS[opcode->argument3_mask]; + break; + + default: + break; + } + + mp_uint_t serialised_value = 0; + + switch (kind & 0x03) { + case N: + assert(mask == OPCODE_MASKS[MASK_NOT_USED] && "Invalid mask index for missing operand."); + break; + + case R: { + mp_uint_t register_index; + if (!parse_register_node(node, ®ister_index, false)) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_register)); + return false; + } + + if ((mask & (1U << register_index)) == 0) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + MP_ERROR_TEXT("opcode '%q' argument %d: unknown register"), + opcode->qstring, node_index + 1)); + return false; + } + + serialised_value = (kind & C) ? RV32_MAP_IN_C_REGISTER_WINDOW(register_index) : register_index; + } + break; + + case I: { + mp_obj_t object; + if (!mp_parse_node_get_int_maybe(node, &object)) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_integer)); + return false; + } + + mp_uint_t immediate = mp_obj_get_int_truncated(object) << shift; + if (kind & U) { + if (!is_in_unsigned_mask(mask, immediate)) { + goto out_of_range; + } + } else { + if (!is_in_signed_mask(mask, immediate)) { + goto out_of_range; + } + } + + if ((kind & Z) && (immediate == 0)) { + goto zero_immediate; + } + + serialised_value = immediate; + } + break; + + case L: { + if (!MP_PARSE_NODE_IS_ID(node)) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENT_KIND, opcode->qstring, node_index + 1, MP_QSTR_label)); + return false; + } + + qstr qstring; + mp_uint_t label_index = lookup_label(emit, node, &qstring); + if (label_index >= emit->max_num_labels && emit->pass == MP_PASS_EMIT) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + MP_ERROR_TEXT("opcode '%q' argument %d: undefined label '%q'"), + opcode->qstring, node_index + 1, qstring)); + return false; + } + + mp_uint_t displacement = (mp_uint_t)(label_code_offset(emit, label_index)); + if (kind & U) { + if (!is_in_unsigned_mask(mask, displacement)) { + goto out_of_range; + } + } else { + if (!is_in_signed_mask(mask, displacement)) { + goto out_of_range; + } + } + + serialised_value = displacement; + } + break; + + default: + assert(!"Unknown argument kind"); + MP_UNREACHABLE; + break; + } + + *serialised = serialised_value; + return true; + +out_of_range: + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode->qstring, node_index + 1)); + return false; + +zero_immediate: + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + MP_ERROR_TEXT("opcode '%q' argument %d: must not be zero"), + opcode->qstring, node_index + 1)); + return false; +} + +static bool serialise_register_offset_node(emit_inline_asm_t *emit, const opcode_t *opcode_data, mp_parse_node_t node, mp_uint_t node_index, mp_uint_t *offset, mp_uint_t *base) { + assert(offset && "Attempting to store the offset value into NULL."); + assert(base && "Attempting to store the base register into NULL."); + + if (!MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_atom_expr_normal) && !MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_factor_2)) { + goto invalid_structure; + } + mp_parse_node_struct_t *node_struct = (mp_parse_node_struct_t *)node; + bool negative = false; + if (MP_PARSE_NODE_IS_STRUCT_KIND(node, PN_factor_2)) { + if (MP_PARSE_NODE_IS_TOKEN_KIND(node_struct->nodes[0], MP_TOKEN_OP_MINUS)) { + negative = true; + } else { + if (!MP_PARSE_NODE_IS_TOKEN_KIND(node_struct->nodes[0], MP_TOKEN_OP_PLUS)) { + goto invalid_structure; + } + } + if (!MP_PARSE_NODE_IS_STRUCT_KIND(node_struct->nodes[1], PN_atom_expr_normal)) { + goto invalid_structure; + } + node_struct = (mp_parse_node_struct_t *)node_struct->nodes[1]; + } + + if (negative) { + // If the value is negative, RULE_atom_expr_normal's first token will be the + // offset stripped of its negative marker; range check will then fail if the + // default method is used, so a custom check is used instead. + mp_obj_t object; + if (!mp_parse_node_get_int_maybe(node_struct->nodes[0], &object)) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_WRONG_ARGUMENT_KIND, opcode_data->qstring, 2, MP_QSTR_integer)); + return false; + } + mp_uint_t value = mp_obj_get_int_truncated(object); + value = (~value + 1) & (mp_uint_t)-1; + if (!validate_integer(value << opcode_data->argument2_shift, OPCODE_MASKS[opcode_data->argument2_mask], opcode_data->argument2_kind)) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, ET_OUT_OF_RANGE, opcode_data->qstring, 2)); + return false; + } + *offset = value; + } else { + if (!serialise_argument(emit, opcode_data, node_struct->nodes[0], 1, offset)) { + return false; + } + } + + node_struct = (mp_parse_node_struct_t *)node_struct->nodes[1]; + if (!serialise_argument(emit, opcode_data, node_struct->nodes[0], 2, base)) { + return false; + } + return true; + +invalid_structure: + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENT_KIND, opcode_data->qstring, node_index + 1, MP_QSTR_offset)); + return false; +} + +static void handle_opcode(emit_inline_asm_t *emit, const opcode_t *opcode_data, mp_uint_t *arguments) { + switch (opcode_data->calling_convention) { + case CALL_RRR: + ((call_rrr_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); + break; + + case CALL_RR: + ((call_rr_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1]); + break; + + case CALL_RRI: + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); + break; + + case CALL_RI: + ((call_ri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1]); + break; + + case CALL_R: + ((call_r_t)opcode_data->emitter)(&emit->as, arguments[0]); + break; + + case CALL_RRL: + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], (ptrdiff_t)arguments[2]); + break; + + case CALL_RL: + ((call_ri_t)opcode_data->emitter)(&emit->as, arguments[0], (ptrdiff_t)arguments[1]); + break; + + case CALL_L: + ((call_i_t)opcode_data->emitter)(&emit->as, (ptrdiff_t)arguments[0]); + break; + + case CALL_N: + ((call_n_t)opcode_data->emitter)(&emit->as); + break; + + case CALL_RII: + ((call_rii_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[1], arguments[2]); + break; + + case CALL_RIR: + // The last two arguments indices are swapped on purpose. + ((call_rri_t)opcode_data->emitter)(&emit->as, arguments[0], arguments[2], arguments[1]); + break; + + default: + assert(!"Unhandled call convention."); + MP_UNREACHABLE; + break; + } +} + +static void emit_inline_rv32_opcode(emit_inline_asm_t *emit, qstr opcode, mp_uint_t arguments_count, mp_parse_node_t *argument_nodes) { + const opcode_t *opcode_data = NULL; + for (mp_uint_t index = 0; index < MP_ARRAY_SIZE(OPCODES); index++) { + if (OPCODES[index].qstring == opcode) { + opcode_data = &OPCODES[index]; + break; + } + } + + if (!opcode_data || (asm_rv32_allowed_extensions() & opcode_data->required_extensions) != opcode_data->required_extensions) { + emit_inline_rv32_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + MP_ERROR_TEXT("invalid RV32 instruction '%q'"), opcode)); + return; + } + + assert((opcode_data->argument1_mask < MP_ARRAY_SIZE(OPCODE_MASKS)) && "Argument #1 opcode mask index out of bounds."); + assert((opcode_data->argument2_mask < MP_ARRAY_SIZE(OPCODE_MASKS)) && "Argument #2 opcode mask index out of bounds."); + assert((opcode_data->argument3_mask < MP_ARRAY_SIZE(OPCODE_MASKS)) && "Argument #3 opcode mask index out of bounds."); + assert((opcode_data->calling_convention < CALL_COUNT) && "Calling convention index out of bounds."); + mp_uint_t serialised_arguments[3] = { 0 }; + if (arguments_count != opcode_data->parse_nodes) { + emit_inline_rv32_error_exc(emit, + mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, + ET_WRONG_ARGUMENTS_COUNT, opcode, opcode_data->parse_nodes)); + return; + } + + if (opcode_data->parse_nodes >= 1 && !serialise_argument(emit, opcode_data, argument_nodes[0], 0, &serialised_arguments[0])) { + return; + } + if (opcode_data->calling_convention == CALL_RIR) { + // "register, offset(base)" calls require some preprocessing to + // split the offset and base nodes - not to mention that if the offset + // is negative, the parser won't see the offset as a single node but as + // a sequence of the minus sign token followed by the number itself. + + if (!serialise_register_offset_node(emit, opcode_data, argument_nodes[1], 1, &serialised_arguments[1], &serialised_arguments[2])) { + return; + } + } else { + if (opcode_data->parse_nodes >= 2 && !serialise_argument(emit, opcode_data, argument_nodes[1], 1, &serialised_arguments[1])) { + return; + } + if (opcode_data->parse_nodes >= 3 && !serialise_argument(emit, opcode_data, argument_nodes[2], 2, &serialised_arguments[2])) { + return; + } + } + + handle_opcode(emit, opcode_data, serialised_arguments); +} + +#undef N +#undef R +#undef I +#undef L +#undef C +#undef U + +const emit_inline_asm_method_table_t emit_inline_rv32_method_table = { + #if MICROPY_DYNAMIC_COMPILER + emit_inline_rv32_new, + emit_inline_rv32_free, + #endif + + emit_inline_rv32_start_pass, + emit_inline_rv32_end_pass, + emit_inline_rv32_count_params, + emit_inline_rv32_label, + emit_inline_rv32_opcode, +}; + +#endif // MICROPY_EMIT_INLINE_RV32 diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c index 29487f10483f9..d6596337ae5a6 100644 --- a/py/emitinlinethumb.c +++ b/py/emitinlinethumb.c @@ -74,11 +74,11 @@ static inline bool emit_inline_thumb_allow_float(emit_inline_asm_t *emit) { #endif -STATIC void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) { +static void emit_inline_thumb_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) { *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); } -STATIC void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { +static void emit_inline_thumb_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { *emit->error_slot = exc; } @@ -97,7 +97,7 @@ void emit_inline_thumb_free(emit_inline_asm_t *emit) { m_del_obj(emit_inline_asm_t, emit); } -STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { +static void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { emit->pass = pass; emit->error_slot = error_slot; if (emit->pass == MP_PASS_CODE_SIZE) { @@ -107,12 +107,12 @@ STATIC void emit_inline_thumb_start_pass(emit_inline_asm_t *emit, pass_kind_t pa asm_thumb_entry(&emit->as, 0); } -STATIC void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { +static void emit_inline_thumb_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { asm_thumb_exit(&emit->as); asm_thumb_end_pass(&emit->as); } -STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { +static mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { emit_inline_thumb_error_msg(emit, MP_ERROR_TEXT("can only have up to 4 parameters to Thumb assembly")); return 0; @@ -131,7 +131,7 @@ STATIC mp_uint_t emit_inline_thumb_count_params(emit_inline_asm_t *emit, mp_uint return n_params; } -STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { +static bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { assert(label_num < emit->max_num_labels); if (emit->pass == MP_PASS_CODE_SIZE) { // check for duplicate label on first pass @@ -149,42 +149,42 @@ STATIC bool emit_inline_thumb_label(emit_inline_asm_t *emit, mp_uint_t label_num typedef struct _reg_name_t { byte reg; byte name[3]; } reg_name_t; -STATIC const reg_name_t reg_name_table[] = { - {0, "r0\0"}, - {1, "r1\0"}, - {2, "r2\0"}, - {3, "r3\0"}, - {4, "r4\0"}, - {5, "r5\0"}, - {6, "r6\0"}, - {7, "r7\0"}, - {8, "r8\0"}, - {9, "r9\0"}, - {10, "r10"}, - {11, "r11"}, - {12, "r12"}, - {13, "r13"}, - {14, "r14"}, - {15, "r15"}, - {10, "sl\0"}, - {11, "fp\0"}, - {13, "sp\0"}, - {14, "lr\0"}, - {15, "pc\0"}, +static const reg_name_t reg_name_table[] = { + {0, {'r', '0' }}, + {1, {'r', '1' }}, + {2, {'r', '2' }}, + {3, {'r', '3' }}, + {4, {'r', '4' }}, + {5, {'r', '5' }}, + {6, {'r', '6' }}, + {7, {'r', '7' }}, + {8, {'r', '8' }}, + {9, {'r', '9' }}, + {10, {'r', '1', '0' }}, + {11, {'r', '1', '1' }}, + {12, {'r', '1', '2' }}, + {13, {'r', '1', '3' }}, + {14, {'r', '1', '4' }}, + {15, {'r', '1', '5' }}, + {10, {'s', 'l' }}, + {11, {'f', 'p' }}, + {13, {'s', 'p' }}, + {14, {'l', 'r' }}, + {15, {'p', 'c' }}, }; #define MAX_SPECIAL_REGISTER_NAME_LENGTH 7 typedef struct _special_reg_name_t { byte reg; char name[MAX_SPECIAL_REGISTER_NAME_LENGTH + 1]; } special_reg_name_t; -STATIC const special_reg_name_t special_reg_name_table[] = { +static const special_reg_name_t special_reg_name_table[] = { {5, "IPSR"}, {17, "BASEPRI"}, }; // return empty string in case of error, so we can attempt to parse the string // without a special check if it was in fact a string -STATIC const char *get_arg_str(mp_parse_node_t pn) { +static const char *get_arg_str(mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { qstr qst = MP_PARSE_NODE_LEAF_ARG(pn); return qstr_str(qst); @@ -193,7 +193,7 @@ STATIC const char *get_arg_str(mp_parse_node_t pn) { } } -STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) { +static mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_uint_t max_reg) { const char *reg_str = get_arg_str(pn); for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) { const reg_name_t *r = ®_name_table[i]; @@ -217,7 +217,7 @@ STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_n return 0; } -STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { +static mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { const char *reg_str = get_arg_str(pn); for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(special_reg_name_table); i++) { const special_reg_name_t *r = &special_reg_name_table[i]; @@ -231,7 +231,7 @@ STATIC mp_uint_t get_arg_special_reg(emit_inline_asm_t *emit, const char *op, mp return 0; } -STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { +static mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { const char *reg_str = get_arg_str(pn); if (reg_str[0] == 's' && reg_str[1] != '\0') { mp_uint_t regno = 0; @@ -258,7 +258,7 @@ STATIC mp_uint_t get_arg_vfpreg(emit_inline_asm_t *emit, const char *op, mp_pars return 0; } -STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { +static mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { // a register list looks like {r0, r1, r2} and is parsed as a Python set if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_brace)) { @@ -310,7 +310,7 @@ STATIC mp_uint_t get_arg_reglist(emit_inline_asm_t *emit, const char *op, mp_par return 0; } -STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) { +static uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, uint32_t fit_mask) { mp_obj_t o; if (!mp_parse_node_get_int_maybe(pn, &o)) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("'%s' expects an integer"), op)); @@ -324,7 +324,7 @@ STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node return i; } -STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) { +static bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, mp_parse_node_t *pn_base, mp_parse_node_t *pn_offset) { if (!MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_atom_bracket)) { goto bad_arg; } @@ -346,7 +346,7 @@ STATIC bool get_arg_addr(emit_inline_asm_t *emit, const char *op, mp_parse_node_ return false; } -STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { +static int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (!MP_PARSE_NODE_IS_ID(pn)) { emit_inline_thumb_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("'%s' expects a label"), op)); return 0; @@ -367,43 +367,43 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_ typedef struct _cc_name_t { byte cc; byte name[2]; } cc_name_t; -STATIC const cc_name_t cc_name_table[] = { - { ASM_THUMB_CC_EQ, "eq" }, - { ASM_THUMB_CC_NE, "ne" }, - { ASM_THUMB_CC_CS, "cs" }, - { ASM_THUMB_CC_CC, "cc" }, - { ASM_THUMB_CC_MI, "mi" }, - { ASM_THUMB_CC_PL, "pl" }, - { ASM_THUMB_CC_VS, "vs" }, - { ASM_THUMB_CC_VC, "vc" }, - { ASM_THUMB_CC_HI, "hi" }, - { ASM_THUMB_CC_LS, "ls" }, - { ASM_THUMB_CC_GE, "ge" }, - { ASM_THUMB_CC_LT, "lt" }, - { ASM_THUMB_CC_GT, "gt" }, - { ASM_THUMB_CC_LE, "le" }, +static const cc_name_t cc_name_table[] = { + { ASM_THUMB_CC_EQ, { 'e', 'q' }}, + { ASM_THUMB_CC_NE, { 'n', 'e' }}, + { ASM_THUMB_CC_CS, { 'c', 's' }}, + { ASM_THUMB_CC_CC, { 'c', 'c' }}, + { ASM_THUMB_CC_MI, { 'm', 'i' }}, + { ASM_THUMB_CC_PL, { 'p', 'l' }}, + { ASM_THUMB_CC_VS, { 'v', 's' }}, + { ASM_THUMB_CC_VC, { 'v', 'c' }}, + { ASM_THUMB_CC_HI, { 'h', 'i' }}, + { ASM_THUMB_CC_LS, { 'l', 's' }}, + { ASM_THUMB_CC_GE, { 'g', 'e' }}, + { ASM_THUMB_CC_LT, { 'l', 't' }}, + { ASM_THUMB_CC_GT, { 'g', 't' }}, + { ASM_THUMB_CC_LE, { 'l', 'e' }}, }; typedef struct _format_4_op_t { byte op; char name[3]; } format_4_op_t; #define X(x) (((x) >> 4) & 0xff) // only need 1 byte to distinguish these ops -STATIC const format_4_op_t format_4_op_table[] = { - { X(ASM_THUMB_FORMAT_4_EOR), "eor" }, - { X(ASM_THUMB_FORMAT_4_LSL), "lsl" }, - { X(ASM_THUMB_FORMAT_4_LSR), "lsr" }, - { X(ASM_THUMB_FORMAT_4_ASR), "asr" }, - { X(ASM_THUMB_FORMAT_4_ADC), "adc" }, - { X(ASM_THUMB_FORMAT_4_SBC), "sbc" }, - { X(ASM_THUMB_FORMAT_4_ROR), "ror" }, - { X(ASM_THUMB_FORMAT_4_TST), "tst" }, - { X(ASM_THUMB_FORMAT_4_NEG), "neg" }, - { X(ASM_THUMB_FORMAT_4_CMP), "cmp" }, - { X(ASM_THUMB_FORMAT_4_CMN), "cmn" }, - { X(ASM_THUMB_FORMAT_4_ORR), "orr" }, - { X(ASM_THUMB_FORMAT_4_MUL), "mul" }, - { X(ASM_THUMB_FORMAT_4_BIC), "bic" }, - { X(ASM_THUMB_FORMAT_4_MVN), "mvn" }, +static const format_4_op_t format_4_op_table[] = { + { X(ASM_THUMB_FORMAT_4_EOR), {'e', 'o', 'r' }}, + { X(ASM_THUMB_FORMAT_4_LSL), {'l', 's', 'l' }}, + { X(ASM_THUMB_FORMAT_4_LSR), {'l', 's', 'r' }}, + { X(ASM_THUMB_FORMAT_4_ASR), {'a', 's', 'r' }}, + { X(ASM_THUMB_FORMAT_4_ADC), {'a', 'd', 'c' }}, + { X(ASM_THUMB_FORMAT_4_SBC), {'s', 'b', 'c' }}, + { X(ASM_THUMB_FORMAT_4_ROR), {'r', 'o', 'r' }}, + { X(ASM_THUMB_FORMAT_4_TST), {'t', 's', 't' }}, + { X(ASM_THUMB_FORMAT_4_NEG), {'n', 'e', 'g' }}, + { X(ASM_THUMB_FORMAT_4_CMP), {'c', 'm', 'p' }}, + { X(ASM_THUMB_FORMAT_4_CMN), {'c', 'm', 'n' }}, + { X(ASM_THUMB_FORMAT_4_ORR), {'o', 'r', 'r' }}, + { X(ASM_THUMB_FORMAT_4_MUL), {'m', 'u', 'l' }}, + { X(ASM_THUMB_FORMAT_4_BIC), {'b', 'i', 'c' }}, + { X(ASM_THUMB_FORMAT_4_MVN), {'m', 'v', 'n' }}, }; #undef X @@ -412,7 +412,7 @@ typedef struct _format_9_10_op_t { uint16_t op; uint16_t name; } format_9_10_op_t; #define X(x) (x) -STATIC const format_9_10_op_t format_9_10_op_table[] = { +static const format_9_10_op_t format_9_10_op_table[] = { { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_WORD_TRANSFER), MP_QSTR_ldr }, { X(ASM_THUMB_FORMAT_9_LDR | ASM_THUMB_FORMAT_9_BYTE_TRANSFER), MP_QSTR_ldrb }, { X(ASM_THUMB_FORMAT_10_LDRH), MP_QSTR_ldrh }, @@ -427,17 +427,17 @@ typedef struct _format_vfp_op_t { byte op; char name[3]; } format_vfp_op_t; -STATIC const format_vfp_op_t format_vfp_op_table[] = { - { 0x30, "add" }, - { 0x34, "sub" }, - { 0x20, "mul" }, - { 0x80, "div" }, +static const format_vfp_op_t format_vfp_op_table[] = { + { 0x30, {'a', 'd', 'd' }}, + { 0x34, {'s', 'u', 'b' }}, + { 0x20, {'m', 'u', 'l' }}, + { 0x80, {'d', 'i', 'v' }}, }; // shorthand alias for whether we allow ARMv7-M instructions #define ARMV7M asm_thumb_allow_armv7m(&emit->as) -STATIC void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { +static void emit_inline_thumb_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { // TODO perhaps make two tables: // one_args = // "b", LAB, asm_thumb_b_n, diff --git a/py/emitinlinextensa.c b/py/emitinlinextensa.c index 5dac2ae3907f1..d0eb3d566fce3 100644 --- a/py/emitinlinextensa.c +++ b/py/emitinlinextensa.c @@ -43,11 +43,11 @@ struct _emit_inline_asm_t { qstr *label_lookup; }; -STATIC void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) { +static void emit_inline_xtensa_error_msg(emit_inline_asm_t *emit, mp_rom_error_text_t msg) { *emit->error_slot = mp_obj_new_exception_msg(&mp_type_SyntaxError, msg); } -STATIC void emit_inline_xtensa_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { +static void emit_inline_xtensa_error_exc(emit_inline_asm_t *emit, mp_obj_t exc) { *emit->error_slot = exc; } @@ -66,7 +66,7 @@ void emit_inline_xtensa_free(emit_inline_asm_t *emit) { m_del_obj(emit_inline_asm_t, emit); } -STATIC void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { +static void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t pass, mp_obj_t *error_slot) { emit->pass = pass; emit->error_slot = error_slot; if (emit->pass == MP_PASS_CODE_SIZE) { @@ -76,12 +76,12 @@ STATIC void emit_inline_xtensa_start_pass(emit_inline_asm_t *emit, pass_kind_t p asm_xtensa_entry(&emit->as, 0); } -STATIC void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { +static void emit_inline_xtensa_end_pass(emit_inline_asm_t *emit, mp_uint_t type_sig) { asm_xtensa_exit(&emit->as); asm_xtensa_end_pass(&emit->as); } -STATIC mp_uint_t emit_inline_xtensa_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { +static mp_uint_t emit_inline_xtensa_count_params(emit_inline_asm_t *emit, mp_uint_t n_params, mp_parse_node_t *pn_params) { if (n_params > 4) { emit_inline_xtensa_error_msg(emit, MP_ERROR_TEXT("can only have up to 4 parameters to Xtensa assembly")); return 0; @@ -100,7 +100,7 @@ STATIC mp_uint_t emit_inline_xtensa_count_params(emit_inline_asm_t *emit, mp_uin return n_params; } -STATIC bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { +static bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_num, qstr label_id) { assert(label_num < emit->max_num_labels); if (emit->pass == MP_PASS_CODE_SIZE) { // check for duplicate label on first pass @@ -115,57 +115,28 @@ STATIC bool emit_inline_xtensa_label(emit_inline_asm_t *emit, mp_uint_t label_nu return true; } -typedef struct _reg_name_t { byte reg; - byte name[3]; -} reg_name_t; -STATIC const reg_name_t reg_name_table[] = { - {0, "a0\0"}, - {1, "a1\0"}, - {2, "a2\0"}, - {3, "a3\0"}, - {4, "a4\0"}, - {5, "a5\0"}, - {6, "a6\0"}, - {7, "a7\0"}, - {8, "a8\0"}, - {9, "a9\0"}, - {10, "a10"}, - {11, "a11"}, - {12, "a12"}, - {13, "a13"}, - {14, "a14"}, - {15, "a15"}, +static const qstr_short_t REGISTERS[16] = { + MP_QSTR_a0, MP_QSTR_a1, MP_QSTR_a2, MP_QSTR_a3, MP_QSTR_a4, MP_QSTR_a5, MP_QSTR_a6, MP_QSTR_a7, + MP_QSTR_a8, MP_QSTR_a9, MP_QSTR_a10, MP_QSTR_a11, MP_QSTR_a12, MP_QSTR_a13, MP_QSTR_a14, MP_QSTR_a15 }; -// return empty string in case of error, so we can attempt to parse the string -// without a special check if it was in fact a string -STATIC const char *get_arg_str(mp_parse_node_t pn) { +static mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_ID(pn)) { - qstr qst = MP_PARSE_NODE_LEAF_ARG(pn); - return qstr_str(qst); - } else { - return ""; - } -} - -STATIC mp_uint_t get_arg_reg(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { - const char *reg_str = get_arg_str(pn); - for (mp_uint_t i = 0; i < MP_ARRAY_SIZE(reg_name_table); i++) { - const reg_name_t *r = ®_name_table[i]; - if (reg_str[0] == r->name[0] - && reg_str[1] == r->name[1] - && reg_str[2] == r->name[2] - && (reg_str[2] == '\0' || reg_str[3] == '\0')) { - return r->reg; + qstr node_qstr = MP_PARSE_NODE_LEAF_ARG(pn); + for (size_t i = 0; i < MP_ARRAY_SIZE(REGISTERS); i++) { + if (node_qstr == REGISTERS[i]) { + return i; + } } } + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("'%s' expects a register"), op)); return 0; } -STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int min, int max) { +static uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn, int min, int max) { mp_obj_t o; if (!mp_parse_node_get_int_maybe(pn, &o)) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("'%s' expects an integer"), op)); @@ -179,7 +150,7 @@ STATIC uint32_t get_arg_i(emit_inline_asm_t *emit, const char *op, mp_parse_node return i; } -STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { +static int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_t pn) { if (!MP_PARSE_NODE_IS_ID(pn)) { emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("'%s' expects a label"), op)); return 0; @@ -202,13 +173,13 @@ STATIC int get_arg_label(emit_inline_asm_t *emit, const char *op, mp_parse_node_ #define RRI8_B (2) typedef struct _opcode_table_3arg_t { - uint16_t name; // actually a qstr, which should fit in 16 bits + qstr_short_t name; uint8_t type; uint8_t a0 : 4; uint8_t a1 : 4; } opcode_table_3arg_t; -STATIC const opcode_table_3arg_t opcode_table_3arg[] = { +static const opcode_table_3arg_t opcode_table_3arg[] = { // arithmetic opcodes: reg, reg, reg {MP_QSTR_and_, RRR, 0, 1}, {MP_QSTR_or_, RRR, 0, 2}, @@ -216,6 +187,13 @@ STATIC const opcode_table_3arg_t opcode_table_3arg[] = { {MP_QSTR_add, RRR, 0, 8}, {MP_QSTR_sub, RRR, 0, 12}, {MP_QSTR_mull, RRR, 2, 8}, + {MP_QSTR_addx2, RRR, 0, 9}, + {MP_QSTR_addx4, RRR, 0, 10}, + {MP_QSTR_addx8, RRR, 0, 11}, + {MP_QSTR_subx2, RRR, 0, 13}, + {MP_QSTR_subx4, RRR, 0, 14}, + {MP_QSTR_subx8, RRR, 0, 15}, + {MP_QSTR_src, RRR, 1, 8}, // load/store/addi opcodes: reg, reg, imm // upper nibble of type encodes the range of the immediate arg @@ -237,21 +215,62 @@ STATIC const opcode_table_3arg_t opcode_table_3arg[] = { {MP_QSTR_bge, RRI8_B, ASM_XTENSA_CC_GE, 0}, {MP_QSTR_bgeu, RRI8_B, ASM_XTENSA_CC_GEU, 0}, {MP_QSTR_blt, RRI8_B, ASM_XTENSA_CC_LT, 0}, + {MP_QSTR_bltu, RRI8_B, ASM_XTENSA_CC_LTU, 0}, {MP_QSTR_bnall, RRI8_B, ASM_XTENSA_CC_NALL, 0}, {MP_QSTR_bne, RRI8_B, ASM_XTENSA_CC_NE, 0}, {MP_QSTR_bnone, RRI8_B, ASM_XTENSA_CC_NONE, 0}, }; -STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { +// The index of the first four qstrs matches the CCZ condition value to be +// embedded into the opcode. +static const qstr_short_t BCCZ_OPCODES[] = { + MP_QSTR_beqz, MP_QSTR_bnez, MP_QSTR_bltz, MP_QSTR_bgez, + MP_QSTR_beqz_n, MP_QSTR_bnez_n +}; + +#if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES +typedef struct _single_opcode_t { + qstr_short_t name; + uint16_t value; +} single_opcode_t; + +static const single_opcode_t NOARGS_OPCODES[] = { + {MP_QSTR_dsync, 0x2030}, + {MP_QSTR_esync, 0x2020}, + {MP_QSTR_extw, 0x20D0}, + {MP_QSTR_ill, 0x0000}, + {MP_QSTR_isync, 0x2000}, + {MP_QSTR_memw, 0x20C0}, + {MP_QSTR_rsync, 0x2010}, +}; +#endif + +static void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_args, mp_parse_node_t *pn_args) { size_t op_len; const char *op_str = (const char *)qstr_data(op, &op_len); if (n_args == 0) { - if (op == MP_QSTR_ret_n) { + if (op == MP_QSTR_ret_n || op == MP_QSTR_ret) { asm_xtensa_op_ret_n(&emit->as); - } else { - goto unknown_op; + return; + } else if (op == MP_QSTR_nop) { + asm_xtensa_op24(&emit->as, 0x20F0); + return; + } else if (op == MP_QSTR_nop_n) { + asm_xtensa_op16(&emit->as, 0xF03D); + return; + } + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + for (size_t index = 0; index < MP_ARRAY_SIZE(NOARGS_OPCODES); index++) { + const single_opcode_t *opcode = &NOARGS_OPCODES[index]; + if (op == opcode->name) { + asm_xtensa_op24(&emit->as, opcode->value); + return; + } } + #endif + + goto unknown_op; } else if (n_args == 1) { if (op == MP_QSTR_callx0) { @@ -263,19 +282,45 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ } else if (op == MP_QSTR_jx) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); asm_xtensa_op_jx(&emit->as, r0); + } else if (op == MP_QSTR_ssl) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op_ssl(&emit->as, r0); + } else if (op == MP_QSTR_ssr) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op_ssr(&emit->as, r0); + } else if (op == MP_QSTR_ssai) { + mp_uint_t sa = get_arg_i(emit, op_str, pn_args[0], 0, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 4, sa & 0x0F, (sa >> 4) & 0x01)); + } else if (op == MP_QSTR_ssa8b) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 3, r0, 0)); + } else if (op == MP_QSTR_ssa8l) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 2, r0, 0)); + } else if (op == MP_QSTR_call0) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[0]); + asm_xtensa_call0(&emit->as, label); + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + } else if (op == MP_QSTR_fsync) { + mp_uint_t imm3 = get_arg_i(emit, op_str, pn_args[0], 0, 7); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 0, 2, 8 | imm3, 0)); + } else if (op == MP_QSTR_ill_n) { + asm_xtensa_op16(&emit->as, 0xF06D); + #endif } else { goto unknown_op; } } else if (n_args == 2) { uint r0 = get_arg_reg(emit, op_str, pn_args[0]); - if (op == MP_QSTR_beqz) { - int label = get_arg_label(emit, op_str, pn_args[1]); - asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_EQ, r0, label); - } else if (op == MP_QSTR_bnez) { - int label = get_arg_label(emit, op_str, pn_args[1]); - asm_xtensa_bccz_reg_label(&emit->as, ASM_XTENSA_CCZ_NE, r0, label); - } else if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) { + for (size_t index = 0; index < MP_ARRAY_SIZE(BCCZ_OPCODES); index++) { + if (op == BCCZ_OPCODES[index]) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]); + asm_xtensa_bccz_reg_label(&emit->as, index & 0x03, r0, label); + return; + } + } + if (op == MP_QSTR_mov || op == MP_QSTR_mov_n) { // we emit mov.n for both "mov" and "mov_n" opcodes uint r1 = get_arg_reg(emit, op_str, pn_args[1]); asm_xtensa_op_mov_n(&emit->as, r0, r1); @@ -283,7 +328,53 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ // for convenience we emit l32r if the integer doesn't fit in movi uint32_t imm = get_arg_i(emit, op_str, pn_args[1], 0, 0); asm_xtensa_mov_reg_i32(&emit->as, r0, imm); - } else { + } else if (op == MP_QSTR_abs_) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 1, r1)); + } else if (op == MP_QSTR_neg) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 6, r0, 0, r1)); + } else if (op == MP_QSTR_sll) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 10, r0, r1, 0)); + } else if (op == MP_QSTR_sra) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 11, r0, 0, r1)); + } else if (op == MP_QSTR_srl) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 9, r0, 0, r1)); + } else if (op == MP_QSTR_nsa) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 14, r1, r0)); + } else if (op == MP_QSTR_nsau) { + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 0, 4, 15, r1, r0)); + } else if (op == MP_QSTR_l32r) { + mp_uint_t label = get_arg_label(emit, op_str, pn_args[1]); + asm_xtensa_l32r(&emit->as, r0, label); + } else if (op == MP_QSTR_movi_n) { + mp_int_t imm = get_arg_i(emit, op_str, pn_args[1], -32, 95); + asm_xtensa_op_movi_n(&emit->as, r0, imm); + } else + #if MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES + if (op == MP_QSTR_rsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 0, sr, r0)); + } else if (op == MP_QSTR_rur) { + mp_uint_t imm8 = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 3, 14, r0, (imm8 >> 4) & 0x0F, imm8 & 0x0F)); + } else if (op == MP_QSTR_wsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 1, sr, r0)); + } else if (op == MP_QSTR_wur) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 3, 15, sr, r0)); + } else if (op == MP_QSTR_xsr) { + mp_uint_t sr = get_arg_i(emit, op_str, pn_args[1], 0, 255); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RSR(0, 1, 6, sr, r0)); + } else + #endif + { goto unknown_op; } @@ -317,7 +408,72 @@ STATIC void emit_inline_xtensa_op(emit_inline_asm_t *emit, qstr op, mp_uint_t n_ return; } } - goto unknown_op; + + if (op == MP_QSTR_add_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t r2 = get_arg_reg(emit, op_str, pn_args[2]); + asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(10, r0, r1, r2)); + } else if (op == MP_QSTR_addi_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_int_t imm4 = get_arg_i(emit, op_str, pn_args[2], -1, 15); + asm_xtensa_op16(&emit->as, ASM_XTENSA_ENCODE_RRRN(11, r0, r1, (imm4 != 0 ? imm4 : -1))); + } else if (op == MP_QSTR_addmi) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_int_t imm8 = get_arg_i(emit, op_str, pn_args[2], -128 * 256, 127 * 256); + if ((imm8 & 0xFF) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm8, 256)); + } else { + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRI8(2, 13, r1, r0, imm8 >> 8)); + } + } else if (op == MP_QSTR_bbci) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31); + mp_int_t label = get_arg_label(emit, op_str, pn_args[2]); + asm_xtensa_bit_branch(&emit->as, r0, bit, label, 6); + } else if (op == MP_QSTR_bbsi) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t bit = get_arg_i(emit, op_str, pn_args[1], 0, 31); + mp_uint_t label = get_arg_label(emit, op_str, pn_args[2]); + asm_xtensa_bit_branch(&emit->as, r0, bit, label, 14); + } else if (op == MP_QSTR_slli) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = 32 - get_arg_i(emit, op_str, pn_args[2], 1, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 0 | ((bits >> 4) & 0x01), r0, r1, bits & 0x0F)); + } else if (op == MP_QSTR_srai) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 31); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 2 | ((bits >> 4) & 0x01), r0, bits & 0x0F, r1)); + } else if (op == MP_QSTR_srli) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t bits = get_arg_i(emit, op_str, pn_args[2], 0, 15); + asm_xtensa_op24(&emit->as, ASM_XTENSA_ENCODE_RRR(0, 1, 4, r0, bits, r1)); + } else if (op == MP_QSTR_l32i_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60); + if ((imm & 0x03) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4)); + } else { + asm_xtensa_op_l32i_n(&emit->as, r0, r1, imm >> 2); + } + } else if (op == MP_QSTR_s32i_n) { + mp_uint_t r0 = get_arg_reg(emit, op_str, pn_args[0]); + mp_uint_t r1 = get_arg_reg(emit, op_str, pn_args[1]); + mp_uint_t imm = get_arg_i(emit, op_str, pn_args[2], 0, 60); + if ((imm & 0x03) != 0) { + emit_inline_xtensa_error_exc(emit, mp_obj_new_exception_msg_varg(&mp_type_SyntaxError, MP_ERROR_TEXT("%d is not a multiple of %d"), imm, 4)); + } else { + asm_xtensa_op_s32i_n(&emit->as, r0, r1, imm >> 2); + } + } else { + goto unknown_op; + } } else { goto unknown_op; diff --git a/py/emitnative.c b/py/emitnative.c index 8225f3ff33659..6f12200f7e171 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -60,28 +60,40 @@ #endif // CIRCUITPY-CHANGE: force definitions -#ifndef N_X64 -#define N_X64 (0) +#ifndef N_ARM +#define N_ARM (0) #endif -#ifndef N_X86 -#define N_X86 (0) +#ifndef N_DEBUG +#define N_DEBUG (0) +#endif + +#ifndef N_NLR_SETJMP +#define N_NLR_SETJMP (0) +#endif + +#ifndef N_RV32 +#define N_RV32 (0) #endif #ifndef N_THUMB #define N_THUMB (0) #endif -#ifndef N_ARM -#define N_ARM (0) +#ifndef N_X64 +#define N_X64 (0) +#endif + +#ifndef N_X86 +#define N_X86 (0) #endif #ifndef N_XTENSA #define N_XTENSA (0) #endif -#ifndef N_NLR_SETJMP -#define N_NLR_SETJMP (0) +#ifndef N_XTENSAWIN +#define N_XTENSAWIN (0) #endif #ifndef N_PRELUDE_AS_BYTES_OBJ @@ -89,7 +101,7 @@ #endif // wrapper around everything in this file -#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN +#if N_X64 || N_X86 || N_THUMB || N_ARM || N_XTENSA || N_XTENSAWIN || N_RV32 || N_DEBUG // C stack layout for native functions: // 0: nlr_buf_t [optional] @@ -159,6 +171,7 @@ // Whether a slot is needed to store LOCAL_IDX_EXC_HANDLER_UNWIND #define NEED_EXC_HANDLER_UNWIND(emit) ((emit)->scope->exc_stack_size > 0) +#define NEED_THROW_VAL(emit) ((emit)->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) // Whether registers can be used to store locals (only true if there are no // exception handlers, because otherwise an nlr_jump will restore registers to @@ -169,6 +182,7 @@ #define LOCAL_IDX_EXC_VAL(emit) (NLR_BUF_IDX_RET_VAL) #define LOCAL_IDX_EXC_HANDLER_PC(emit) (NLR_BUF_IDX_LOCAL_1) #define LOCAL_IDX_EXC_HANDLER_UNWIND(emit) (SIZEOF_NLR_BUF + 1) // this needs a dedicated variable outside nlr_buf_t +#define LOCAL_IDX_THROW_VAL(emit) (SIZEOF_NLR_BUF + 2) // needs a dedicated variable outside nlr_buf_t, following inject_exc in py/vm.c #define LOCAL_IDX_RET_VAL(emit) (SIZEOF_NLR_BUF) // needed when NEED_GLOBAL_EXC_HANDLER is true #define LOCAL_IDX_FUN_OBJ(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_FUN_BC) #define LOCAL_IDX_OLD_GLOBALS(emit) ((emit)->code_state_start + OFFSETOF_CODE_STATE_IP) @@ -186,7 +200,7 @@ #define REG_QSTR_TABLE (REG_LOCAL_3) #define MAX_REGS_FOR_LOCAL_VARS (2) -STATIC const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, REG_LOCAL_2}; +static const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, REG_LOCAL_2}; #else @@ -198,7 +212,7 @@ STATIC const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, RE #define REG_GENERATOR_STATE (REG_LOCAL_3) #define MAX_REGS_FOR_LOCAL_VARS (3) -STATIC const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, REG_LOCAL_2, REG_LOCAL_3}; +static const uint8_t reg_local_table[MAX_REGS_FOR_LOCAL_VARS] = {REG_LOCAL_1, REG_LOCAL_2, REG_LOCAL_3}; #endif @@ -232,7 +246,7 @@ typedef enum { VTYPE_BUILTIN_CAST = 0x70 | MP_NATIVE_TYPE_OBJ, } vtype_kind_t; -STATIC qstr vtype_to_qstr(vtype_kind_t vtype) { +static qstr vtype_to_qstr(vtype_kind_t vtype) { switch (vtype) { case VTYPE_PYOBJ: return MP_QSTR_object; @@ -283,7 +297,6 @@ struct _emit_t { int pass; bool do_viper_types; - bool prelude_offset_uses_u16_encoding; mp_uint_t local_vtype_alloc; vtype_kind_t *local_vtype; @@ -311,12 +324,32 @@ struct _emit_t { ASM_T *as; }; -STATIC void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj); -STATIC void emit_native_global_exc_entry(emit_t *emit); -STATIC void emit_native_global_exc_exit(emit_t *emit); -STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj); +#ifndef REG_ZERO +#define REG_ZERO REG_TEMP0 +#define ASM_CLR_REG(state, rd) ASM_XOR_REG_REG(state, rd, rd) +#endif + +#if N_RV32 +#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \ + ASM_MOV_LOCAL_REG(as, local_num, REG_ZERO) +#else +#define ASM_MOV_LOCAL_MP_OBJ_NULL(as, local_num, reg_temp) \ + ASM_MOV_REG_IMM(as, reg_temp, (mp_uint_t)MP_OBJ_NULL); \ + ASM_MOV_LOCAL_REG(as, local_num, reg_temp) +#endif + +static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj); +static void emit_native_global_exc_entry(emit_t *emit); +static void emit_native_global_exc_exit(emit_t *emit); +static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj); emit_t *EXPORT_FUN(new)(mp_emit_common_t * emit_common, mp_obj_t *error_slot, uint *label_slot, mp_uint_t max_num_labels) { + // Generated code performing exception handling assumes that MP_OBJ_NULL + // equals to 0 to simplify some checks, leveraging dedicated opcodes for + // comparisons against 0. If this assumption does not hold true anymore + // then generated code won't work correctly. + MP_STATIC_ASSERT(MP_OBJ_NULL == 0); + emit_t *emit = m_new0(emit_t, 1); emit->emit_common = emit_common; emit->error_slot = error_slot; @@ -339,13 +372,13 @@ void EXPORT_FUN(free)(emit_t * emit) { m_del_obj(emit_t, emit); } -STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg); +static void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg); -STATIC void emit_native_mov_reg_const(emit_t *emit, int reg_dest, int const_val) { +static void emit_native_mov_reg_const(emit_t *emit, int reg_dest, int const_val) { ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_FUN_TABLE, const_val); } -STATIC void emit_native_mov_state_reg(emit_t *emit, int local_num, int reg_src) { +static void emit_native_mov_state_reg(emit_t *emit, int local_num, int reg_src) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_STORE_REG_REG_OFFSET(emit->as, reg_src, REG_GENERATOR_STATE, local_num); } else { @@ -353,7 +386,7 @@ STATIC void emit_native_mov_state_reg(emit_t *emit, int local_num, int reg_src) } } -STATIC void emit_native_mov_reg_state(emit_t *emit, int reg_dest, int local_num) { +static void emit_native_mov_reg_state(emit_t *emit, int reg_dest, int local_num) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_LOAD_REG_REG_OFFSET(emit->as, reg_dest, REG_GENERATOR_STATE, local_num); } else { @@ -361,7 +394,7 @@ STATIC void emit_native_mov_reg_state(emit_t *emit, int reg_dest, int local_num) } } -STATIC void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local_num) { +static void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local_num) { if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { ASM_MOV_REG_IMM(emit->as, reg_dest, local_num * ASM_WORD_SIZE); ASM_ADD_REG_REG(emit->as, reg_dest, REG_GENERATOR_STATE); @@ -370,15 +403,18 @@ STATIC void emit_native_mov_reg_state_addr(emit_t *emit, int reg_dest, int local } } -STATIC void emit_native_mov_reg_qstr(emit_t *emit, int arg_reg, qstr qst) { +static void emit_native_mov_reg_qstr(emit_t *emit, int arg_reg, qstr qst) { #if MICROPY_PERSISTENT_CODE_SAVE ASM_LOAD16_REG_REG_OFFSET(emit->as, arg_reg, REG_QSTR_TABLE, mp_emit_common_use_qstr(emit->emit_common, qst)); + #elif defined(ASM_MOV_REG_QSTR) + ASM_MOV_REG_QSTR(emit->as, arg_reg, qst); #else ASM_MOV_REG_IMM(emit->as, arg_reg, qst); #endif } -STATIC void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) { +// This function may clobber REG_TEMP0 (and `reg_dest` can be REG_TEMP0). +static void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) { #if MICROPY_PERSISTENT_CODE_SAVE emit_load_reg_with_object(emit, reg_dest, MP_OBJ_NEW_QSTR(qst)); #else @@ -392,7 +428,7 @@ STATIC void emit_native_mov_reg_qstr_obj(emit_t *emit, int reg_dest, qstr qst) { emit_native_mov_state_reg((emit), (local_num), (reg_temp)); \ } while (false) -STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { +static void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) { DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope); emit->pass = pass; @@ -440,6 +476,30 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->stack_info[i].vtype = VTYPE_UNBOUND; } + char *qualified_name = NULL; + + #if N_DEBUG + scope_t *current_scope = scope; + vstr_t *qualified_name_vstr = vstr_new(qstr_len(current_scope->simple_name)); + size_t fragment_length = 0; + const byte *fragment_pointer; + for (;;) { + fragment_pointer = qstr_data(current_scope->simple_name, &fragment_length); + vstr_hint_size(qualified_name_vstr, fragment_length); + memmove(qualified_name_vstr->buf + fragment_length, qualified_name_vstr->buf, qualified_name_vstr->len); + memcpy(qualified_name_vstr->buf, fragment_pointer, fragment_length); + qualified_name_vstr->len += fragment_length; + if (current_scope->parent == NULL || current_scope->parent->simple_name == MP_QSTR__lt_module_gt_) { + break; + } + vstr_ins_char(qualified_name_vstr, 0, '.'); + current_scope = current_scope->parent; + } + qualified_name = vstr_null_terminated_str(qualified_name_vstr); + #else + (void)qualified_name; + #endif + mp_asm_base_start_pass(&emit->as->base, pass == MP_PASS_EMIT ? MP_ASM_PASS_EMIT : MP_ASM_PASS_COMPUTE); // generate code for entry to function @@ -449,7 +509,9 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop if (NEED_GLOBAL_EXC_HANDLER(emit)) { emit->code_state_start = SIZEOF_NLR_BUF; // for nlr_buf_t emit->code_state_start += 1; // for return_value - if (NEED_EXC_HANDLER_UNWIND(emit)) { + if (NEED_THROW_VAL(emit)) { + emit->code_state_start += 2; + } else if (NEED_EXC_HANDLER_UNWIND(emit)) { emit->code_state_start += 1; } } @@ -484,7 +546,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } // Entry to function - ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs); + ASM_ENTRY(emit->as, emit->stack_start + emit->n_state - num_locals_in_regs, qualified_name); #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 0, REG_PARENT_ARG_1); @@ -549,10 +611,13 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // work out size of state (locals plus stack) emit->n_state = scope->num_locals + scope->stack_size; + // Store in the first machine-word an index used to the function's prelude. + // This is used at runtime by mp_obj_fun_native_get_prelude_ptr(). + mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index); + if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { - mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->prelude_ptr_index); mp_asm_base_data(&emit->as->base, ASM_WORD_SIZE, (uintptr_t)emit->start_offset); - ASM_ENTRY(emit->as, emit->code_state_start); + ASM_ENTRY(emit->as, emit->code_state_start, qualified_name); // Reset the state size for the state pointed to by REG_GENERATOR_STATE emit->code_state_start = 0; @@ -565,11 +630,11 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop ASM_MOV_REG_REG(emit->as, REG_GENERATOR_STATE, REG_PARENT_ARG_1); #endif - // Put throw value into LOCAL_IDX_EXC_VAL slot, for yield/yield-from + // Put throw value into LOCAL_IDX_THROW_VAL slot, for yield/yield-from #if N_X86 asm_x86_mov_arg_to_r32(emit->as, 1, REG_PARENT_ARG_2); #endif - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_PARENT_ARG_2); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_PARENT_ARG_2); // Load REG_FUN_TABLE with a pointer to mp_fun_table, found in the const_table ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_GENERATOR_STATE, LOCAL_IDX_FUN_OBJ(emit)); @@ -584,7 +649,7 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop emit->stack_start = emit->code_state_start + SIZEOF_CODE_STATE; // Allocate space on C-stack for code_state structure, which includes state - ASM_ENTRY(emit->as, emit->stack_start + emit->n_state); + ASM_ENTRY(emit->as, emit->stack_start + emit->n_state, qualified_name); // Prepare incoming arguments for call to mp_setup_code_state @@ -606,15 +671,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop // Set code_state.fun_bc ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_FUN_OBJ(emit), REG_PARENT_ARG_1); - // Set code_state.ip, a pointer to the beginning of the prelude. This pointer is found - // either directly in mp_obj_fun_bc_t.child_table (if there are no children), or in - // mp_obj_fun_bc_t.child_table[num_children] (if num_children > 0). - ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, OFFSETOF_OBJ_FUN_BC_CHILD_TABLE); - if (emit->prelude_ptr_index != 0) { - ASM_LOAD_REG_REG_OFFSET(emit->as, REG_PARENT_ARG_1, REG_PARENT_ARG_1, emit->prelude_ptr_index); - } - emit_native_mov_state_reg(emit, emit->code_state_start + OFFSETOF_CODE_STATE_IP, REG_PARENT_ARG_1); - // Set code_state.n_state (only works on little endian targets due to n_state being uint16_t) emit_native_mov_state_imm_via(emit, emit->code_state_start + OFFSETOF_CODE_STATE_N_STATE, emit->n_state, REG_ARG_1); @@ -659,6 +715,10 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop } } } + + #if N_DEBUG + vstr_free(qualified_name_vstr); + #endif } static inline void emit_native_write_code_info_byte(emit_t *emit, byte val) { @@ -669,7 +729,7 @@ static inline void emit_native_write_code_info_qstr(emit_t *emit, qstr qst) { mp_encode_uint(&emit->as->base, mp_asm_base_get_cur_to_write_bytes, mp_emit_common_use_qstr(emit->emit_common, qst)); } -STATIC bool emit_native_end_pass(emit_t *emit) { +static bool emit_native_end_pass(emit_t *emit) { emit_native_global_exc_exit(emit); if (!emit->do_viper_types) { @@ -760,7 +820,7 @@ STATIC bool emit_native_end_pass(emit_t *emit) { return true; } -STATIC void ensure_extra_stack(emit_t *emit, size_t delta) { +static void ensure_extra_stack(emit_t *emit, size_t delta) { if (emit->stack_size + delta > emit->stack_info_alloc) { size_t new_alloc = (emit->stack_size + delta + 8) & ~3; emit->stack_info = m_renew(stack_info_t, emit->stack_info, emit->stack_info_alloc, new_alloc); @@ -768,7 +828,7 @@ STATIC void ensure_extra_stack(emit_t *emit, size_t delta) { } } -STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) { +static void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) { assert((mp_int_t)emit->stack_size + stack_size_delta >= 0); assert((mp_int_t)emit->stack_size + stack_size_delta <= (mp_int_t)emit->stack_info_alloc); emit->stack_size += stack_size_delta; @@ -785,7 +845,7 @@ STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) { #endif } -STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) { +static void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) { DEBUG_printf("adjust_stack_size(" INT_FMT ")\n", delta); if (delta > 0) { ensure_extra_stack(emit, delta); @@ -809,23 +869,23 @@ STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) { adjust_stack(emit, delta); } -STATIC void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) { +static void emit_native_set_source_line(emit_t *emit, mp_uint_t source_line) { (void)emit; (void)source_line; } // this must be called at start of emit functions -STATIC void emit_native_pre(emit_t *emit) { +static void emit_native_pre(emit_t *emit) { (void)emit; } // depth==0 is top, depth==1 is before top, etc -STATIC stack_info_t *peek_stack(emit_t *emit, mp_uint_t depth) { +static stack_info_t *peek_stack(emit_t *emit, mp_uint_t depth) { return &emit->stack_info[emit->stack_size - 1 - depth]; } // depth==0 is top, depth==1 is before top, etc -STATIC vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) { +static vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) { if (emit->do_viper_types) { return peek_stack(emit, depth)->vtype; } else { @@ -836,7 +896,7 @@ STATIC vtype_kind_t peek_vtype(emit_t *emit, mp_uint_t depth) { // pos=1 is TOS, pos=2 is next, etc // use pos=0 for no skipping -STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) { +static void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) { skip_stack_pos = emit->stack_size - skip_stack_pos; for (int i = 0; i < emit->stack_size; i++) { if (i != skip_stack_pos) { @@ -851,7 +911,7 @@ STATIC void need_reg_single(emit_t *emit, int reg_needed, int skip_stack_pos) { // Ensures all unsettled registers that hold Python values are copied to the // concrete Python stack. All registers are then free to use. -STATIC void need_reg_all(emit_t *emit) { +static void need_reg_all(emit_t *emit) { for (int i = 0; i < emit->stack_size; i++) { stack_info_t *si = &emit->stack_info[i]; if (si->kind == STACK_REG) { @@ -862,7 +922,7 @@ STATIC void need_reg_all(emit_t *emit) { } } -STATIC vtype_kind_t load_reg_stack_imm(emit_t *emit, int reg_dest, const stack_info_t *si, bool convert_to_pyobj) { +static vtype_kind_t load_reg_stack_imm(emit_t *emit, int reg_dest, const stack_info_t *si, bool convert_to_pyobj) { if (!convert_to_pyobj && emit->do_viper_types) { ASM_MOV_REG_IMM(emit->as, reg_dest, si->data.u_imm); return si->vtype; @@ -886,7 +946,7 @@ STATIC vtype_kind_t load_reg_stack_imm(emit_t *emit, int reg_dest, const stack_i // concrete Python stack. This ensures the concrete Python stack holds valid // values for the current stack_size. // This function may clobber REG_TEMP1. -STATIC void need_stack_settled(emit_t *emit) { +static void need_stack_settled(emit_t *emit) { DEBUG_printf(" need_stack_settled; stack_size=%d\n", emit->stack_size); need_reg_all(emit); for (int i = 0; i < emit->stack_size; i++) { @@ -902,7 +962,7 @@ STATIC void need_stack_settled(emit_t *emit) { } // pos=1 is TOS, pos=2 is next, etc -STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) { +static void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int reg_dest) { need_reg_single(emit, reg_dest, pos); stack_info_t *si = &emit->stack_info[emit->stack_size - pos]; *vtype = si->vtype; @@ -925,7 +985,7 @@ STATIC void emit_access_stack(emit_t *emit, int pos, vtype_kind_t *vtype, int re // does an efficient X=pop(); discard(); push(X) // needs a (non-temp) register in case the popped element was stored in the stack -STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { +static void emit_fold_stack_top(emit_t *emit, int reg_dest) { stack_info_t *si = &emit->stack_info[emit->stack_size - 2]; si[0] = si[1]; if (si->kind == STACK_VALUE) { @@ -939,7 +999,7 @@ STATIC void emit_fold_stack_top(emit_t *emit, int reg_dest) { // If stacked value is in a register and the register is not r1 or r2, then // *reg_dest is set to that register. Otherwise the value is put in *reg_dest. -STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { +static void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *reg_dest, int not_r1, int not_r2) { stack_info_t *si = peek_stack(emit, 0); if (si->kind == STACK_REG && si->data.u_reg != not_r1 && si->data.u_reg != not_r2) { *vtype = si->vtype; @@ -951,36 +1011,36 @@ STATIC void emit_pre_pop_reg_flexible(emit_t *emit, vtype_kind_t *vtype, int *re adjust_stack(emit, -1); } -STATIC void emit_pre_pop_discard(emit_t *emit) { +static void emit_pre_pop_discard(emit_t *emit) { adjust_stack(emit, -1); } -STATIC void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { +static void emit_pre_pop_reg(emit_t *emit, vtype_kind_t *vtype, int reg_dest) { emit_access_stack(emit, 1, vtype, reg_dest); adjust_stack(emit, -1); } -STATIC void emit_pre_pop_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb) { +static void emit_pre_pop_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb) { emit_pre_pop_reg(emit, vtypea, rega); emit_pre_pop_reg(emit, vtypeb, regb); } -STATIC void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb, vtype_kind_t *vtypec, int regc) { +static void emit_pre_pop_reg_reg_reg(emit_t *emit, vtype_kind_t *vtypea, int rega, vtype_kind_t *vtypeb, int regb, vtype_kind_t *vtypec, int regc) { emit_pre_pop_reg(emit, vtypea, rega); emit_pre_pop_reg(emit, vtypeb, regb); emit_pre_pop_reg(emit, vtypec, regc); } -STATIC void emit_post(emit_t *emit) { +static void emit_post(emit_t *emit) { (void)emit; } -STATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) { +static void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) { stack_info_t *si = &emit->stack_info[emit->stack_size - 1]; si->vtype = new_vtype; } -STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) { +static void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) { ensure_extra_stack(emit, 1); stack_info_t *si = &emit->stack_info[emit->stack_size]; si->vtype = vtype; @@ -989,7 +1049,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) { adjust_stack(emit, 1); } -STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) { +static void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) { ensure_extra_stack(emit, 1); stack_info_t *si = &emit->stack_info[emit->stack_size]; si->vtype = vtype; @@ -998,43 +1058,43 @@ STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) { adjust_stack(emit, 1); } -STATIC void emit_post_push_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb) { +static void emit_post_push_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); } -STATIC void emit_post_push_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc) { +static void emit_post_push_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); emit_post_push_reg(emit, vtypec, regc); } -STATIC void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc, vtype_kind_t vtyped, int regd) { +static void emit_post_push_reg_reg_reg_reg(emit_t *emit, vtype_kind_t vtypea, int rega, vtype_kind_t vtypeb, int regb, vtype_kind_t vtypec, int regc, vtype_kind_t vtyped, int regd) { emit_post_push_reg(emit, vtypea, rega); emit_post_push_reg(emit, vtypeb, regb); emit_post_push_reg(emit, vtypec, regc); emit_post_push_reg(emit, vtyped, regd); } -STATIC void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) { +static void emit_call(emit_t *emit, mp_fun_kind_t fun_kind) { need_reg_all(emit); ASM_CALL_IND(emit->as, fun_kind); } -STATIC void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) { +static void emit_call_with_imm_arg(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val, int arg_reg) { need_reg_all(emit); ASM_MOV_REG_IMM(emit->as, arg_reg, arg_val); ASM_CALL_IND(emit->as, fun_kind); } -STATIC void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) { +static void emit_call_with_2_imm_args(emit_t *emit, mp_fun_kind_t fun_kind, mp_int_t arg_val1, int arg_reg1, mp_int_t arg_val2, int arg_reg2) { need_reg_all(emit); ASM_MOV_REG_IMM(emit->as, arg_reg1, arg_val1); ASM_MOV_REG_IMM(emit->as, arg_reg2, arg_val2); ASM_CALL_IND(emit->as, fun_kind); } -STATIC void emit_call_with_qstr_arg(emit_t *emit, mp_fun_kind_t fun_kind, qstr qst, int arg_reg) { +static void emit_call_with_qstr_arg(emit_t *emit, mp_fun_kind_t fun_kind, qstr qst, int arg_reg) { need_reg_all(emit); emit_native_mov_reg_qstr(emit, arg_reg, qst); ASM_CALL_IND(emit->as, fun_kind); @@ -1044,7 +1104,7 @@ STATIC void emit_call_with_qstr_arg(emit_t *emit, mp_fun_kind_t fun_kind, qstr q // Will convert any items that are not VTYPE_PYOBJ to this type and put them back on the stack. // If any conversions of non-immediate values are needed, then it uses REG_ARG_1, REG_ARG_2 and REG_RET. // Otherwise, it does not use any temporary registers (but may use reg_dest before loading it with stack pointer). -STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) { +static void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_pop) { need_reg_all(emit); // First, store any immediate values to their respective place on the stack. @@ -1081,7 +1141,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de } // vtype of all n_push objects is VTYPE_PYOBJ -STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) { +static void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) { need_reg_all(emit); ensure_extra_stack(emit, n_push); for (mp_uint_t i = 0; i < n_push; i++) { @@ -1092,7 +1152,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_d adjust_stack(emit, n_push); } -STATIC void emit_native_push_exc_stack(emit_t *emit, uint label, bool is_finally) { +static void emit_native_push_exc_stack(emit_t *emit, uint label, bool is_finally) { if (emit->exc_stack_size + 1 > emit->exc_stack_alloc) { size_t new_alloc = emit->exc_stack_alloc + 4; emit->exc_stack = m_renew(exc_stack_entry_t, emit->exc_stack, emit->exc_stack_alloc, new_alloc); @@ -1109,7 +1169,7 @@ STATIC void emit_native_push_exc_stack(emit_t *emit, uint label, bool is_finally ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } -STATIC void emit_native_leave_exc_stack(emit_t *emit, bool start_of_handler) { +static void emit_native_leave_exc_stack(emit_t *emit, bool start_of_handler) { assert(emit->exc_stack_size > 0); // Get current exception handler and deactivate it @@ -1135,14 +1195,15 @@ STATIC void emit_native_leave_exc_stack(emit_t *emit, bool start_of_handler) { ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_RET); } -STATIC exc_stack_entry_t *emit_native_pop_exc_stack(emit_t *emit) { +static exc_stack_entry_t *emit_native_pop_exc_stack(emit_t *emit) { assert(emit->exc_stack_size > 0); exc_stack_entry_t *e = &emit->exc_stack[--emit->exc_stack_size]; assert(e->is_active == false); return e; } -STATIC void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj) { +// This function will clobber REG_TEMP0 (and `reg` can be REG_TEMP0). +static void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj) { emit->scope->scope_flags |= MP_SCOPE_FLAG_HASCONSTS; size_t table_off = mp_emit_common_use_const_obj(emit->emit_common, obj); emit_native_mov_reg_state(emit, REG_TEMP0, LOCAL_IDX_FUN_OBJ(emit)); @@ -1151,14 +1212,14 @@ STATIC void emit_load_reg_with_object(emit_t *emit, int reg, mp_obj_t obj) { ASM_LOAD_REG_REG_OFFSET(emit->as, reg, REG_TEMP0, table_off); } -STATIC void emit_load_reg_with_child(emit_t *emit, int reg, mp_raw_code_t *rc) { +static void emit_load_reg_with_child(emit_t *emit, int reg, mp_raw_code_t *rc) { size_t table_off = mp_emit_common_alloc_const_child(emit->emit_common, rc); emit_native_mov_reg_state(emit, REG_TEMP0, LOCAL_IDX_FUN_OBJ(emit)); ASM_LOAD_REG_REG_OFFSET(emit->as, REG_TEMP0, REG_TEMP0, OFFSETOF_OBJ_FUN_BC_CHILD_TABLE); ASM_LOAD_REG_REG_OFFSET(emit->as, reg, REG_TEMP0, table_off); } -STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) { +static void emit_native_label_assign(emit_t *emit, mp_uint_t l) { DEBUG_printf("label_assign(" UINT_FMT ")\n", l); bool is_finally = false; @@ -1170,7 +1231,7 @@ STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) { if (is_finally) { // Label is at start of finally handler: store TOS into exception slot vtype_kind_t vtype; - emit_pre_pop_reg(emit, &vtype, REG_TEMP0); + emit_access_stack(emit, 1, &vtype, REG_TEMP0); ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } @@ -1186,7 +1247,7 @@ STATIC void emit_native_label_assign(emit_t *emit, mp_uint_t l) { } } -STATIC void emit_native_global_exc_entry(emit_t *emit) { +static void emit_native_global_exc_entry(emit_t *emit) { // Note: 4 labels are reserved for this function, starting at *emit->label_slot emit->exit_label = *emit->label_slot; @@ -1223,8 +1284,12 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { ASM_JUMP_IF_REG_ZERO(emit->as, REG_RET, start_label, true); } else { // Clear the unwind state - ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_TEMP0); + ASM_CLR_REG(emit->as, REG_ZERO); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_UNWIND(emit), REG_ZERO); + + // clear nlr.ret_val, because it's passed to mp_native_raise regardless + // of whether there was an exception or not + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_ZERO); // Put PC of start code block into REG_LOCAL_1 ASM_MOV_REG_PCREL(emit->as, REG_LOCAL_1, start_label); @@ -1240,8 +1305,8 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { ASM_JUMP_IF_REG_NONZERO(emit->as, REG_RET, global_except_label, true); // Clear PC of current code block, and jump there to resume execution - ASM_XOR_REG_REG(emit->as, REG_TEMP0, REG_TEMP0); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_TEMP0); + ASM_CLR_REG(emit->as, REG_ZERO); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_HANDLER_PC(emit), REG_ZERO); ASM_JUMP_REG(emit->as, REG_LOCAL_1); // Global exception handler: check for valid exception handler @@ -1281,14 +1346,15 @@ STATIC void emit_native_global_exc_entry(emit_t *emit) { // This is the first entry of the generator - // Check LOCAL_IDX_EXC_VAL for any injected value - ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); + // Check LOCAL_IDX_THROW_VAL for any injected value + ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit)); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); emit_call(emit, MP_F_NATIVE_RAISE); } } } -STATIC void emit_native_global_exc_exit(emit_t *emit) { +static void emit_native_global_exc_exit(emit_t *emit) { // Label for end of function emit_native_label_assign(emit, emit->exit_label); @@ -1323,7 +1389,7 @@ STATIC void emit_native_global_exc_exit(emit_t *emit) { ASM_EXIT(emit->as); } -STATIC void emit_native_import_name(emit_t *emit, qstr qst) { +static void emit_native_import_name(emit_t *emit, qstr qst) { DEBUG_printf("import_name %s\n", qstr_str(qst)); // get arguments from stack: arg2 = fromlist, arg3 = level @@ -1342,7 +1408,7 @@ STATIC void emit_native_import_name(emit_t *emit, qstr qst) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_import_from(emit_t *emit, qstr qst) { +static void emit_native_import_from(emit_t *emit, qstr qst) { DEBUG_printf("import_from %s\n", qstr_str(qst)); emit_native_pre(emit); vtype_kind_t vtype_module; @@ -1352,7 +1418,7 @@ STATIC void emit_native_import_from(emit_t *emit, qstr qst) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_import_star(emit_t *emit) { +static void emit_native_import_star(emit_t *emit) { DEBUG_printf("import_star\n"); vtype_kind_t vtype_module; emit_pre_pop_reg(emit, &vtype_module, REG_ARG_1); // arg1 = module @@ -1361,7 +1427,7 @@ STATIC void emit_native_import_star(emit_t *emit) { emit_post(emit); } -STATIC void emit_native_import(emit_t *emit, qstr qst, int kind) { +static void emit_native_import(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_IMPORT_NAME) { emit_native_import_name(emit, qst); } else if (kind == MP_EMIT_IMPORT_FROM) { @@ -1371,7 +1437,7 @@ STATIC void emit_native_import(emit_t *emit, qstr qst, int kind) { } } -STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) { +static void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) { DEBUG_printf("load_const_tok(tok=%u)\n", tok); if (tok == MP_TOKEN_ELLIPSIS) { emit_native_load_const_obj(emit, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); @@ -1385,13 +1451,13 @@ STATIC void emit_native_load_const_tok(emit_t *emit, mp_token_kind_t tok) { } } -STATIC void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) { +static void emit_native_load_const_small_int(emit_t *emit, mp_int_t arg) { DEBUG_printf("load_const_small_int(int=" INT_FMT ")\n", arg); emit_native_pre(emit); emit_post_push_imm(emit, VTYPE_INT, arg); } -STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) { +static void emit_native_load_const_str(emit_t *emit, qstr qst) { emit_native_pre(emit); // TODO: Eventually we want to be able to work with raw pointers in viper to // do native array access. For now we just load them as any other object. @@ -1408,19 +1474,19 @@ STATIC void emit_native_load_const_str(emit_t *emit, qstr qst) { } } -STATIC void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) { +static void emit_native_load_const_obj(emit_t *emit, mp_obj_t obj) { emit_native_pre(emit); - need_reg_single(emit, REG_RET, 0); - emit_load_reg_with_object(emit, REG_RET, obj); - emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); + need_reg_single(emit, REG_TEMP0, 0); + emit_load_reg_with_object(emit, REG_TEMP0, obj); + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_TEMP0); } -STATIC void emit_native_load_null(emit_t *emit) { +static void emit_native_load_null(emit_t *emit) { emit_native_pre(emit); emit_post_push_imm(emit, VTYPE_PYOBJ, 0); } -STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { +static void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("load_fast(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); vtype_kind_t vtype = emit->local_vtype[local_num]; if (vtype == VTYPE_UNBOUND) { @@ -1436,7 +1502,7 @@ STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { } } -STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { +static void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("load_deref(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); need_reg_single(emit, REG_RET, 0); emit_native_load_fast(emit, qst, local_num); @@ -1448,7 +1514,7 @@ STATIC void emit_native_load_deref(emit_t *emit, qstr qst, mp_uint_t local_num) emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { +static void emit_native_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { emit_native_load_fast(emit, qst, local_num); } else { @@ -1456,7 +1522,7 @@ STATIC void emit_native_load_local(emit_t *emit, qstr qst, mp_uint_t local_num, } } -STATIC void emit_native_load_global(emit_t *emit, qstr qst, int kind) { +static void emit_native_load_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_LOAD_NAME); MP_STATIC_ASSERT(MP_F_LOAD_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_LOAD_GLOBAL); emit_native_pre(emit); @@ -1477,7 +1543,7 @@ STATIC void emit_native_load_global(emit_t *emit, qstr qst, int kind) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_load_attr(emit_t *emit, qstr qst) { +static void emit_native_load_attr(emit_t *emit, qstr qst) { // depends on type of subject: // - integer, function, pointer to integers: error // - pointer to structure: get member, quite easy @@ -1489,7 +1555,8 @@ STATIC void emit_native_load_attr(emit_t *emit, qstr qst) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) { +static void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) { + DEBUG_printf("load_method(%s, %d)\n", qstr_str(qst), is_super); if (is_super) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr @@ -1503,13 +1570,13 @@ STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) { } } -STATIC void emit_native_load_build_class(emit_t *emit) { +static void emit_native_load_build_class(emit_t *emit) { emit_native_pre(emit); emit_call(emit, MP_F_LOAD_BUILD_CLASS); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_load_subscr(emit_t *emit) { +static void emit_native_load_subscr(emit_t *emit) { DEBUG_printf("load_subscr\n"); // need to compile: base[index] @@ -1548,57 +1615,50 @@ STATIC void emit_native_load_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb ldrb r1, [r2, r3] + #ifdef ASM_LOAD8_REG_REG_OFFSET + ASM_LOAD8_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is non-zero - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldrb_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_LOAD8_REG_REG(emit->as, REG_RET, reg_base); // load from (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory + #ifdef ASM_LOAD16_REG_REG_OFFSET + ASM_LOAD16_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldrh_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_LOAD16_REG_REG(emit->as, REG_RET, reg_base); // load from (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory + #ifdef ASM_LOAD32_REG_REG_OFFSET + ASM_LOAD32_REG_REG_OFFSET(emit->as, REG_RET, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_ldr_rlo_rlo_i5(emit->as, REG_RET, reg_base, index_value); - break; - } - #endif need_reg_single(emit, reg_index, 0); ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_LOAD32_REG_REG(emit->as, REG_RET, reg_base); // load from (base+4*index) + #endif break; } default: @@ -1619,25 +1679,36 @@ STATIC void emit_native_load_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb ldrb r1, [r2, r3] + #ifdef ASM_LOAD8_REG_REG_REG + ASM_LOAD8_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD8_REG_REG(emit->as, REG_RET, REG_ARG_1); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory + #ifdef ASM_LOAD16_REG_REG_REG + ASM_LOAD16_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD16_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to word-size memory + #ifdef ASM_LOAD32_REG_REG_REG + ASM_LOAD32_REG_REG_REG(emit->as, REG_RET, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_LOAD32_REG_REG(emit->as, REG_RET, REG_ARG_1); // load from (base+4*index) + #endif break; } default: @@ -1649,7 +1720,7 @@ STATIC void emit_native_load_subscr(emit_t *emit) { } } -STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { +static void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) { vtype_kind_t vtype; if (local_num < MAX_REGS_FOR_LOCAL_VARS && CAN_USE_REGS_FOR_LOCALS(emit)) { emit_pre_pop_reg(emit, &vtype, reg_local_table[local_num]); @@ -1671,7 +1742,7 @@ STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) } } -STATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { +static void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) { DEBUG_printf("store_deref(%s, " UINT_FMT ")\n", qstr_str(qst), local_num); need_reg_single(emit, REG_TEMP0, 0); need_reg_single(emit, REG_TEMP1, 0); @@ -1685,7 +1756,7 @@ STATIC void emit_native_store_deref(emit_t *emit, qstr qst, mp_uint_t local_num) emit_post(emit); } -STATIC void emit_native_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { +static void emit_native_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { emit_native_store_fast(emit, qst, local_num); } else { @@ -1693,7 +1764,7 @@ STATIC void emit_native_store_local(emit_t *emit, qstr qst, mp_uint_t local_num, } } -STATIC void emit_native_store_global(emit_t *emit, qstr qst, int kind) { +static void emit_native_store_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_STORE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_STORE_NAME); MP_STATIC_ASSERT(MP_F_STORE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_STORE_GLOBAL); if (kind == MP_EMIT_IDOP_GLOBAL_NAME) { @@ -1715,7 +1786,7 @@ STATIC void emit_native_store_global(emit_t *emit, qstr qst, int kind) { emit_post(emit); } -STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { +static void emit_native_store_attr(emit_t *emit, qstr qst) { vtype_kind_t vtype_base; vtype_kind_t vtype_val = peek_vtype(emit, 1); if (vtype_val == VTYPE_PYOBJ) { @@ -1732,7 +1803,7 @@ STATIC void emit_native_store_attr(emit_t *emit, qstr qst) { emit_post(emit); } -STATIC void emit_native_store_subscr(emit_t *emit) { +static void emit_native_store_subscr(emit_t *emit) { DEBUG_printf("store_subscr\n"); // need to compile: base[index] = value @@ -1780,63 +1851,47 @@ STATIC void emit_native_store_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb strb r1, [r2, r3] + #ifdef ASM_STORE8_REG_REG_OFFSET + ASM_STORE8_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is non-zero - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_strb_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value); - #if N_ARM - asm_arm_strb_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); - return; - #endif ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add index to base reg_base = reg_index; } ASM_STORE8_REG_REG(emit->as, reg_value, reg_base); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory + #ifdef ASM_STORE16_REG_REG_OFFSET + ASM_STORE16_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_strh_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 1); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 2*index to base reg_base = reg_index; } ASM_STORE16_REG_REG(emit->as, reg_value, reg_base); // store value to (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory + #ifdef ASM_STORE32_REG_REG_OFFSET + ASM_STORE32_REG_REG_OFFSET(emit->as, reg_value, reg_base, index_value); + #else if (index_value != 0) { // index is a non-zero immediate - #if N_THUMB - if (index_value > 0 && index_value < 32) { - asm_thumb_str_rlo_rlo_i5(emit->as, reg_value, reg_base, index_value); - break; - } - #endif - #if N_ARM - ASM_MOV_REG_IMM(emit->as, reg_index, index_value); - asm_arm_str_reg_reg_reg(emit->as, reg_value, reg_base, reg_index); - return; - #endif ASM_MOV_REG_IMM(emit->as, reg_index, index_value << 2); ASM_ADD_REG_REG(emit->as, reg_index, reg_base); // add 4*index to base reg_base = reg_index; } ASM_STORE32_REG_REG(emit->as, reg_value, reg_base); // store value to (base+4*index) + #endif break; } default: @@ -1867,37 +1922,36 @@ STATIC void emit_native_store_subscr(emit_t *emit) { switch (vtype_base) { case VTYPE_PTR8: { // pointer to 8-bit memory - // TODO optimise to use thumb strb r1, [r2, r3] - #if N_ARM - asm_arm_strb_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #endif + #ifdef ASM_STORE8_REG_REG_REG + ASM_STORE8_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE8_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+index) + #endif break; } case VTYPE_PTR16: { // pointer to 16-bit memory - #if N_ARM - asm_arm_strh_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #endif + #ifdef ASM_STORE16_REG_REG_REG + ASM_STORE16_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE16_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+2*index) + #endif break; } case VTYPE_PTR32: { // pointer to 32-bit memory - #if N_ARM - asm_arm_str_reg_reg_reg(emit->as, reg_value, REG_ARG_1, reg_index); - break; - #endif + #ifdef ASM_STORE32_REG_REG_REG + ASM_STORE32_REG_REG_REG(emit->as, reg_value, REG_ARG_1, reg_index); + #else ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_ADD_REG_REG(emit->as, REG_ARG_1, reg_index); // add index to base ASM_STORE32_REG_REG(emit->as, reg_value, REG_ARG_1); // store value to (base+4*index) + #endif break; } default: @@ -1909,7 +1963,7 @@ STATIC void emit_native_store_subscr(emit_t *emit) { } } -STATIC void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { +static void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num, int kind) { if (kind == MP_EMIT_IDOP_LOCAL_FAST) { // TODO: This is not compliant implementation. We could use MP_OBJ_SENTINEL // to mark deleted vars but then every var would need to be checked on @@ -1921,7 +1975,7 @@ STATIC void emit_native_delete_local(emit_t *emit, qstr qst, mp_uint_t local_num } } -STATIC void emit_native_delete_global(emit_t *emit, qstr qst, int kind) { +static void emit_native_delete_global(emit_t *emit, qstr qst, int kind) { MP_STATIC_ASSERT(MP_F_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_NAME == MP_F_DELETE_NAME); MP_STATIC_ASSERT(MP_F_DELETE_NAME + MP_EMIT_IDOP_GLOBAL_GLOBAL == MP_F_DELETE_GLOBAL); emit_native_pre(emit); @@ -1929,7 +1983,7 @@ STATIC void emit_native_delete_global(emit_t *emit, qstr qst, int kind) { emit_post(emit); } -STATIC void emit_native_delete_attr(emit_t *emit, qstr qst) { +static void emit_native_delete_attr(emit_t *emit, qstr qst) { vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base assert(vtype_base == VTYPE_PYOBJ); @@ -1938,7 +1992,7 @@ STATIC void emit_native_delete_attr(emit_t *emit, qstr qst) { emit_post(emit); } -STATIC void emit_native_delete_subscr(emit_t *emit) { +static void emit_native_delete_subscr(emit_t *emit) { vtype_kind_t vtype_index, vtype_base; emit_pre_pop_reg_reg(emit, &vtype_index, REG_ARG_2, &vtype_base, REG_ARG_1); // index, base assert(vtype_index == VTYPE_PYOBJ); @@ -1946,7 +2000,7 @@ STATIC void emit_native_delete_subscr(emit_t *emit) { emit_call_with_imm_arg(emit, MP_F_OBJ_SUBSCR, (mp_uint_t)MP_OBJ_NULL, REG_ARG_3); } -STATIC void emit_native_subscr(emit_t *emit, int kind) { +static void emit_native_subscr(emit_t *emit, int kind) { if (kind == MP_EMIT_SUBSCR_LOAD) { emit_native_load_subscr(emit); } else if (kind == MP_EMIT_SUBSCR_STORE) { @@ -1956,7 +2010,7 @@ STATIC void emit_native_subscr(emit_t *emit, int kind) { } } -STATIC void emit_native_attr(emit_t *emit, qstr qst, int kind) { +static void emit_native_attr(emit_t *emit, qstr qst, int kind) { if (kind == MP_EMIT_ATTR_LOAD) { emit_native_load_attr(emit, qst); } else if (kind == MP_EMIT_ATTR_STORE) { @@ -1966,7 +2020,7 @@ STATIC void emit_native_attr(emit_t *emit, qstr qst, int kind) { } } -STATIC void emit_native_dup_top(emit_t *emit) { +static void emit_native_dup_top(emit_t *emit) { DEBUG_printf("dup_top\n"); vtype_kind_t vtype; int reg = REG_TEMP0; @@ -1974,33 +2028,33 @@ STATIC void emit_native_dup_top(emit_t *emit) { emit_post_push_reg_reg(emit, vtype, reg, vtype, reg); } -STATIC void emit_native_dup_top_two(emit_t *emit) { +static void emit_native_dup_top_two(emit_t *emit) { vtype_kind_t vtype0, vtype1; emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1); emit_post_push_reg_reg_reg_reg(emit, vtype1, REG_TEMP1, vtype0, REG_TEMP0, vtype1, REG_TEMP1, vtype0, REG_TEMP0); } -STATIC void emit_native_pop_top(emit_t *emit) { +static void emit_native_pop_top(emit_t *emit) { DEBUG_printf("pop_top\n"); emit_pre_pop_discard(emit); emit_post(emit); } -STATIC void emit_native_rot_two(emit_t *emit) { +static void emit_native_rot_two(emit_t *emit) { DEBUG_printf("rot_two\n"); vtype_kind_t vtype0, vtype1; emit_pre_pop_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1); emit_post_push_reg_reg(emit, vtype0, REG_TEMP0, vtype1, REG_TEMP1); } -STATIC void emit_native_rot_three(emit_t *emit) { +static void emit_native_rot_three(emit_t *emit) { DEBUG_printf("rot_three\n"); vtype_kind_t vtype0, vtype1, vtype2; emit_pre_pop_reg_reg_reg(emit, &vtype0, REG_TEMP0, &vtype1, REG_TEMP1, &vtype2, REG_TEMP2); emit_post_push_reg_reg_reg(emit, vtype0, REG_TEMP0, vtype2, REG_TEMP2, vtype1, REG_TEMP1); } -STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { +static void emit_native_jump(emit_t *emit, mp_uint_t label) { DEBUG_printf("jump(label=" UINT_FMT ")\n", label); emit_native_pre(emit); // need to commit stack because we are jumping elsewhere @@ -2010,7 +2064,7 @@ STATIC void emit_native_jump(emit_t *emit, mp_uint_t label) { mp_asm_base_suppress_code(&emit->as->base); } -STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { +static void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bool pop) { vtype_kind_t vtype = peek_vtype(emit, 0); if (vtype == VTYPE_PYOBJ) { emit_pre_pop_reg(emit, &vtype, REG_ARG_1); @@ -2047,17 +2101,17 @@ STATIC void emit_native_jump_helper(emit_t *emit, bool cond, mp_uint_t label, bo emit_post(emit); } -STATIC void emit_native_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { +static void emit_native_pop_jump_if(emit_t *emit, bool cond, mp_uint_t label) { DEBUG_printf("pop_jump_if(cond=%u, label=" UINT_FMT ")\n", cond, label); emit_native_jump_helper(emit, cond, label, true); } -STATIC void emit_native_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) { +static void emit_native_jump_if_or_pop(emit_t *emit, bool cond, mp_uint_t label) { DEBUG_printf("jump_if_or_pop(cond=%u, label=" UINT_FMT ")\n", cond, label); emit_native_jump_helper(emit, cond, label, false); } -STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) { +static void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_depth) { if (except_depth > 0) { exc_stack_entry_t *first_finally = NULL; exc_stack_entry_t *prev_finally = NULL; @@ -2100,7 +2154,7 @@ STATIC void emit_native_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t exc emit_native_jump(emit, label & ~MP_EMIT_BREAK_FROM_FOR); } -STATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) { +static void emit_native_setup_with(emit_t *emit, mp_uint_t label) { // the context manager is on the top of the stack // stack: (..., ctx_mgr) @@ -2139,7 +2193,8 @@ STATIC void emit_native_setup_with(emit_t *emit, mp_uint_t label) { // stack: (..., __exit__, self, as_value, as_value) } -STATIC void emit_native_setup_block(emit_t *emit, mp_uint_t label, int kind) { +static void emit_native_setup_block(emit_t *emit, mp_uint_t label, int kind) { + DEBUG_printf("setup_block(%d, %d)\n", (int)label, kind); if (kind == MP_EMIT_SETUP_BLOCK_WITH) { emit_native_setup_with(emit, label); } else { @@ -2151,7 +2206,7 @@ STATIC void emit_native_setup_block(emit_t *emit, mp_uint_t label, int kind) { } } -STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { +static void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { // Note: 3 labels are reserved for this function, starting at *emit->label_slot // stack: (..., __exit__, self, as_value) @@ -2209,22 +2264,49 @@ STATIC void emit_native_with_cleanup(emit_t *emit, mp_uint_t label) { // Replace exception with MP_OBJ_NULL. emit_native_label_assign(emit, *emit->label_slot); - ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); // end of with cleanup nlr_catch block emit_native_label_assign(emit, *emit->label_slot + 1); // Exception is in nlr_buf.ret_val slot + adjust_stack(emit, 1); } -STATIC void emit_native_end_finally(emit_t *emit) { +#if MICROPY_PY_ASYNC_AWAIT +static void emit_native_async_with_setup_finally(emit_t *emit, mp_uint_t label_aexit_no_exc, mp_uint_t label_finally_block, mp_uint_t label_ret_unwind_jump) { + // The async-with body has executed and no exception was raised, the execution fell through to this point. + // Stack: (..., ctx_mgr) + + // Insert a dummy value into the stack so the stack has the same layout to execute the code starting at label_aexit_no_exc + emit_native_adjust_stack_size(emit, 1); // push dummy value, it won't ever be used + emit_native_rot_two(emit); + emit_native_load_const_tok(emit, MP_TOKEN_KW_NONE); // to tell end_finally there's no exception + emit_native_rot_two(emit); + // Stack: (..., , None, ctx_mgr) + emit_native_jump(emit, label_aexit_no_exc); // jump to code to call __aexit__ + emit_native_adjust_stack_size(emit, -1); + + // Start of "finally" block which is entered via one of: an exception propagating out, a return, an unwind jump. + emit_native_label_assign(emit, label_finally_block); + + // Detect which case we have by the local exception slot holding an exception or not. + emit_pre_pop_discard(emit); + ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); // get exception + emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_1); + ASM_JUMP_IF_REG_ZERO(emit->as, REG_ARG_1, label_ret_unwind_jump, false); // if not an exception then we have return or unwind jump. +} +#endif + +static void emit_native_end_finally(emit_t *emit) { // logic: // exc = pop_stack // if exc == None: pass // else: raise exc // the check if exc is None is done in the MP_F_NATIVE_RAISE stub - emit_native_pre(emit); + DEBUG_printf("end_finally\n"); + + emit_pre_pop_discard(emit); ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); emit_call(emit, MP_F_NATIVE_RAISE); @@ -2244,10 +2326,12 @@ STATIC void emit_native_end_finally(emit_t *emit) { emit_post(emit); } -STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { +static void emit_native_get_iter(emit_t *emit, bool use_stack) { // perhaps the difficult one, as we want to rewrite for loops using native code // in cases where we iterate over a Python object, can we use normal runtime calls? + DEBUG_printf("get_iter(%d)\n", use_stack); + vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_1); assert(vtype == VTYPE_PYOBJ); @@ -2262,7 +2346,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) { } } -STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { +static void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_native_pre(emit); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS); adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS); @@ -2277,38 +2361,60 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_for_iter_end(emit_t *emit) { +static void emit_native_for_iter_end(emit_t *emit) { // adjust stack counter (we get here from for_iter ending, which popped the value for us) emit_native_pre(emit); adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS); emit_post(emit); } -STATIC void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { +static void emit_native_pop_except_jump(emit_t *emit, mp_uint_t label, bool within_exc_handler) { if (within_exc_handler) { // Cancel any active exception so subsequent handlers don't see it - ASM_MOV_REG_IMM(emit->as, REG_TEMP0, (mp_uint_t)MP_OBJ_NULL); - ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_EXC_VAL(emit), REG_TEMP0); } else { emit_native_leave_exc_stack(emit, false); } emit_native_jump(emit, label); } -STATIC void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) { - vtype_kind_t vtype; - emit_pre_pop_reg(emit, &vtype, REG_ARG_2); - if (vtype == VTYPE_PYOBJ) { +static void emit_native_unary_op(emit_t *emit, mp_unary_op_t op) { + vtype_kind_t vtype = peek_vtype(emit, 0); + if (vtype == VTYPE_INT || vtype == VTYPE_UINT) { + if (op == MP_UNARY_OP_POSITIVE) { + // No-operation, just leave the argument on the stack. + } else if (op == MP_UNARY_OP_NEGATIVE) { + int reg = REG_RET; + emit_pre_pop_reg_flexible(emit, &vtype, ®, reg, reg); + ASM_NEG_REG(emit->as, reg); + emit_post_push_reg(emit, vtype, reg); + } else if (op == MP_UNARY_OP_INVERT) { + #ifdef ASM_NOT_REG + int reg = REG_RET; + emit_pre_pop_reg_flexible(emit, &vtype, ®, reg, reg); + ASM_NOT_REG(emit->as, reg); + #else + int reg = REG_RET; + emit_pre_pop_reg_flexible(emit, &vtype, ®, REG_ARG_1, reg); + ASM_MOV_REG_IMM(emit->as, REG_ARG_1, -1); + ASM_XOR_REG_REG(emit->as, reg, REG_ARG_1); + #endif + emit_post_push_reg(emit, vtype, reg); + } else { + EMIT_NATIVE_VIPER_TYPE_ERROR(emit, + MP_ERROR_TEXT("'not' not implemented"), mp_binary_op_method_name[op]); + } + } else if (vtype == VTYPE_PYOBJ) { + emit_pre_pop_reg(emit, &vtype, REG_ARG_2); emit_call_with_imm_arg(emit, MP_F_UNARY_OP, op, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } else { - adjust_stack(emit, 1); EMIT_NATIVE_VIPER_TYPE_ERROR(emit, - MP_ERROR_TEXT("unary op %q not implemented"), mp_unary_op_method_name[op]); + MP_ERROR_TEXT("can't do unary op of '%q'"), vtype_to_qstr(vtype)); } } -STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { +static void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { DEBUG_printf("binary_op(" UINT_FMT ")\n", op); vtype_kind_t vtype_lhs = peek_vtype(emit, 1); vtype_kind_t vtype_rhs = peek_vtype(emit, 0); @@ -2413,7 +2519,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { #if N_X64 asm_x64_xor_r64_r64(emit->as, REG_RET, REG_RET); asm_x64_cmp_r64_with_r64(emit->as, reg_rhs, REG_ARG_2); - static byte ops[6 + 6] = { + static const byte ops[6 + 6] = { // unsigned ASM_X64_CC_JB, ASM_X64_CC_JA, @@ -2433,7 +2539,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { #elif N_X86 asm_x86_xor_r32_r32(emit->as, REG_RET, REG_RET); asm_x86_cmp_r32_with_r32(emit->as, reg_rhs, REG_ARG_2); - static byte ops[6 + 6] = { + static const byte ops[6 + 6] = { // unsigned ASM_X86_CC_JB, ASM_X86_CC_JA, @@ -2453,7 +2559,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { #elif N_THUMB asm_thumb_cmp_rlo_rlo(emit->as, REG_ARG_2, reg_rhs); if (asm_thumb_allow_armv7m(emit->as)) { - static uint16_t ops[6 + 6] = { + static const uint16_t ops[6 + 6] = { // unsigned ASM_THUMB_OP_ITE_CC, ASM_THUMB_OP_ITE_HI, @@ -2473,7 +2579,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { asm_thumb_mov_rlo_i8(emit->as, REG_RET, 1); asm_thumb_mov_rlo_i8(emit->as, REG_RET, 0); } else { - static uint16_t ops[6 + 6] = { + static const uint16_t ops[6 + 6] = { // unsigned ASM_THUMB_CC_CC, ASM_THUMB_CC_HI, @@ -2496,7 +2602,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } #elif N_ARM asm_arm_cmp_reg_reg(emit->as, REG_ARG_2, reg_rhs); - static uint ccs[6 + 6] = { + static const uint ccs[6 + 6] = { // unsigned ASM_ARM_CC_CC, ASM_ARM_CC_HI, @@ -2514,7 +2620,7 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { }; asm_arm_setcc_reg(emit->as, REG_RET, ccs[op_idx]); #elif N_XTENSA || N_XTENSAWIN - static uint8_t ccs[6 + 6] = { + static const uint8_t ccs[6 + 6] = { // unsigned ASM_XTENSA_CC_LTU, 0x80 | ASM_XTENSA_CC_LTU, // for GTU we'll swap args @@ -2536,6 +2642,38 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } else { asm_xtensa_setcc_reg_reg_reg(emit->as, cc & ~0x80, REG_RET, reg_rhs, REG_ARG_2); } + #elif N_RV32 + (void)op_idx; + switch (op) { + case MP_BINARY_OP_LESS: + asm_rv32_meta_comparison_lt(emit->as, REG_ARG_2, reg_rhs, REG_RET, vtype_lhs == VTYPE_UINT); + break; + + case MP_BINARY_OP_MORE: + asm_rv32_meta_comparison_lt(emit->as, reg_rhs, REG_ARG_2, REG_RET, vtype_lhs == VTYPE_UINT); + break; + + case MP_BINARY_OP_EQUAL: + asm_rv32_meta_comparison_eq(emit->as, REG_ARG_2, reg_rhs, REG_RET); + break; + + case MP_BINARY_OP_LESS_EQUAL: + asm_rv32_meta_comparison_le(emit->as, REG_ARG_2, reg_rhs, REG_RET, vtype_lhs == VTYPE_UINT); + break; + + case MP_BINARY_OP_MORE_EQUAL: + asm_rv32_meta_comparison_le(emit->as, reg_rhs, REG_ARG_2, REG_RET, vtype_lhs == VTYPE_UINT); + break; + + case MP_BINARY_OP_NOT_EQUAL: + asm_rv32_meta_comparison_ne(emit->as, reg_rhs, REG_ARG_2, REG_RET); + break; + + default: + break; + } + #elif N_DEBUG + asm_debug_setcc_reg_reg_reg(emit->as, op_idx, REG_RET, REG_ARG_2, reg_rhs); #else #error not implemented #endif @@ -2571,10 +2709,10 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) { } #if MICROPY_PY_BUILTINS_SLICE -STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args); +static void emit_native_build_slice(emit_t *emit, mp_uint_t n_args); #endif -STATIC void emit_native_build(emit_t *emit, mp_uint_t n_args, int kind) { +static void emit_native_build(emit_t *emit, mp_uint_t n_args, int kind) { // for viper: call runtime, with types of args // if wrapped in byte_array, or something, allocates memory and fills it MP_STATIC_ASSERT(MP_F_BUILD_TUPLE + MP_EMIT_BUILD_TUPLE == MP_F_BUILD_TUPLE); @@ -2595,7 +2733,7 @@ STATIC void emit_native_build(emit_t *emit, mp_uint_t n_args, int kind) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new tuple/list/map/set } -STATIC void emit_native_store_map(emit_t *emit) { +static void emit_native_store_map(emit_t *emit) { vtype_kind_t vtype_key, vtype_value, vtype_map; emit_pre_pop_reg_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3, &vtype_map, REG_ARG_1); // key, value, map assert(vtype_key == VTYPE_PYOBJ); @@ -2606,7 +2744,7 @@ STATIC void emit_native_store_map(emit_t *emit) { } #if MICROPY_PY_BUILTINS_SLICE -STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { +static void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("build_slice %d\n", n_args); if (n_args == 2) { vtype_kind_t vtype_start, vtype_stop; @@ -2627,7 +2765,7 @@ STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif -STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { +static void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { mp_fun_kind_t f; if (kind == SCOPE_LIST_COMP) { vtype_kind_t vtype_item; @@ -2656,7 +2794,7 @@ STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t co emit_post(emit); } -STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { +static void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("unpack_sequence %d\n", n_args); vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq @@ -2665,7 +2803,7 @@ STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { emit_call_with_imm_arg(emit, MP_F_UNPACK_SEQUENCE, n_args, REG_ARG_2); // arg2 = n_args } -STATIC void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) { +static void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right) { DEBUG_printf("unpack_ex %d %d\n", n_left, n_right); vtype_kind_t vtype_base; emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = seq @@ -2674,7 +2812,7 @@ STATIC void emit_native_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_ri emit_call_with_imm_arg(emit, MP_F_UNPACK_EX, n_left | (n_right << 8), REG_ARG_2); // arg2 = n_left + n_right } -STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { +static void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { // call runtime, with type info for args, or don't support dict/default params, or only support Python objects for them emit_native_pre(emit); emit_native_mov_reg_state(emit, REG_ARG_2, LOCAL_IDX_FUN_OBJ(emit)); @@ -2687,11 +2825,11 @@ STATIC void emit_native_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_ need_reg_all(emit); } emit_load_reg_with_child(emit, REG_ARG_1, scope->raw_code); - ASM_CALL_IND(emit->as, MP_F_MAKE_FUNCTION_FROM_RAW_CODE); + ASM_CALL_IND(emit->as, MP_F_MAKE_FUNCTION_FROM_PROTO_FUN); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { +static void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_closed_over, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults) { // make function emit_native_pre(emit); emit_native_mov_reg_state(emit, REG_ARG_2, LOCAL_IDX_FUN_OBJ(emit)); @@ -2705,7 +2843,7 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c need_reg_all(emit); } emit_load_reg_with_child(emit, REG_ARG_1, scope->raw_code); - ASM_CALL_IND(emit->as, MP_F_MAKE_FUNCTION_FROM_RAW_CODE); + ASM_CALL_IND(emit->as, MP_F_MAKE_FUNCTION_FROM_PROTO_FUN); // make closure #if REG_ARG_1 != REG_RET @@ -2720,7 +2858,7 @@ STATIC void emit_native_make_closure(emit_t *emit, scope_t *scope, mp_uint_t n_c emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); } -STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { +static void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { DEBUG_printf("call_function(n_pos=" UINT_FMT ", n_kw=" UINT_FMT ", star_flags=" UINT_FMT ")\n", n_positional, n_keyword, star_flags); // TODO: in viper mode, call special runtime routine with type info for args, @@ -2775,7 +2913,8 @@ STATIC void emit_native_call_function(emit_t *emit, mp_uint_t n_positional, mp_u } } -STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { +static void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uint_t n_keyword, mp_uint_t star_flags) { + DEBUG_printf("call_method(%d, %d, %d)\n", n_positional, n_keyword, star_flags); if (star_flags) { emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, n_positional + 2 * n_keyword + 3); // pointer to args emit_call_with_2_imm_args(emit, MP_F_CALL_METHOD_N_KW_VAR, 1, REG_ARG_1, n_positional | (n_keyword << 8), REG_ARG_2); @@ -2788,7 +2927,7 @@ STATIC void emit_native_call_method(emit_t *emit, mp_uint_t n_positional, mp_uin } } -STATIC void emit_native_return_value(emit_t *emit) { +static void emit_native_return_value(emit_t *emit) { DEBUG_printf("return_value\n"); if (emit->scope->scope_flags & MP_SCOPE_FLAG_GENERATOR) { @@ -2841,7 +2980,8 @@ STATIC void emit_native_return_value(emit_t *emit) { emit_native_unwind_jump(emit, emit->exit_label, emit->exc_stack_size); } -STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { +static void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { + DEBUG_printf("raise_varargs(%d)\n", n_args); (void)n_args; assert(n_args == 1); vtype_kind_t vtype_exc; @@ -2854,9 +2994,11 @@ STATIC void emit_native_raise_varargs(emit_t *emit, mp_uint_t n_args) { mp_asm_base_suppress_code(&emit->as->base); } -STATIC void emit_native_yield(emit_t *emit, int kind) { +static void emit_native_yield(emit_t *emit, int kind) { // Note: 1 (yield) or 3 (yield from) labels are reserved for this function, starting at *emit->label_slot + DEBUG_printf("yield(%d)\n", kind); + if (emit->do_viper_types) { mp_raise_NotImplementedError(MP_ERROR_TEXT("native yield")); } @@ -2912,18 +3054,21 @@ STATIC void emit_native_yield(emit_t *emit, int kind) { emit_native_adjust_stack_size(emit, 1); // send_value if (kind == MP_EMIT_YIELD_VALUE) { - // Check LOCAL_IDX_EXC_VAL for any injected value - ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_EXC_VAL(emit)); + // Check LOCAL_IDX_THROW_VAL for any injected value + ASM_MOV_REG_LOCAL(emit->as, REG_ARG_1, LOCAL_IDX_THROW_VAL(emit)); + ASM_MOV_LOCAL_MP_OBJ_NULL(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); emit_call(emit, MP_F_NATIVE_RAISE); } else { // Label loop entry emit_native_label_assign(emit, *emit->label_slot + 2); // Get the next item from the delegate generator + ASM_MOV_REG_LOCAL(emit->as, REG_ARG_3, LOCAL_IDX_THROW_VAL(emit)); // throw_value + ASM_MOV_REG_IMM(emit->as, REG_ARG_2, (mp_uint_t)MP_OBJ_NULL); + ASM_MOV_LOCAL_REG(emit->as, LOCAL_IDX_THROW_VAL(emit), REG_ARG_2); vtype_kind_t vtype; emit_pre_pop_reg(emit, &vtype, REG_ARG_2); // send_value emit_access_stack(emit, 1, &vtype, REG_ARG_1); // generator - ASM_MOV_REG_LOCAL(emit->as, REG_ARG_3, LOCAL_IDX_EXC_VAL(emit)); // throw_value emit_post_push_reg(emit, VTYPE_PYOBJ, REG_ARG_3); emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_3, 1); // ret_value emit_call(emit, MP_F_NATIVE_YIELD_FROM); @@ -2937,7 +3082,7 @@ STATIC void emit_native_yield(emit_t *emit, int kind) { } } -STATIC void emit_native_start_except_handler(emit_t *emit) { +static void emit_native_start_except_handler(emit_t *emit) { // Protected block has finished so leave the current exception handler emit_native_leave_exc_stack(emit, true); @@ -2946,8 +3091,7 @@ STATIC void emit_native_start_except_handler(emit_t *emit) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_TEMP0); } -STATIC void emit_native_end_except_handler(emit_t *emit) { - adjust_stack(emit, -1); // pop the exception (end_finally didn't use it) +static void emit_native_end_except_handler(emit_t *emit) { } const emit_method_table_t EXPORT_FUN(method_table) = { @@ -2996,6 +3140,9 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_unwind_jump, emit_native_setup_block, emit_native_with_cleanup, + #if MICROPY_PY_ASYNC_AWAIT + emit_native_async_with_setup_finally, + #endif emit_native_end_finally, emit_native_get_iter, emit_native_for_iter, diff --git a/py/emitndebug.c b/py/emitndebug.c new file mode 100644 index 0000000000000..e49c5cdbffa7b --- /dev/null +++ b/py/emitndebug.c @@ -0,0 +1,281 @@ +// native-debug specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_NATIVE_DEBUG + +#include "py/asmbase.h" +#include "py/nativeglue.h" + +#define asm_debug_printf(as, fmt, ...) \ + do { \ + if (as->base.pass == MP_ASM_PASS_EMIT) { \ + if (fmt[0] != 'E') { \ + mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, " "); \ + } \ + if (as->base.suppress) { \ + mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, "dead_code "); \ + } \ + mp_printf(MICROPY_EMIT_NATIVE_DEBUG_PRINTER, fmt, __VA_ARGS__); \ + } \ + } while (0) + +enum { + ASM_DEBUG_REG_R00, + ASM_DEBUG_REG_R01, + ASM_DEBUG_REG_R02, + ASM_DEBUG_REG_R03, + ASM_DEBUG_REG_R04, + ASM_DEBUG_REG_R05, + ASM_DEBUG_REG_R06, + ASM_DEBUG_REG_R07, + ASM_DEBUG_REG_R08, + ASM_DEBUG_REG_R09, + ASM_DEBUG_REG_R10, + ASM_DEBUG_REG_R11, +}; + +typedef struct _asm_debug_t { + mp_asm_base_t base; +} asm_debug_t; + +static const char *const reg_name_table[] = { + "r_ret", + "r_arg1", + "r_arg2", + "r_arg3", + "r_arg4", + "r_temp0", + "r_temp1", + "r_temp2", + "r_local1", + "r_local2", + "r_local3", + "r_fun_table", +}; + +static const char *const fun_name_table[MP_F_NUMBER_OF] = { + [MP_F_CONVERT_OBJ_TO_NATIVE] = "convert_obj_to_native", + [MP_F_CONVERT_NATIVE_TO_OBJ] = "convert_native_to_obj", + [MP_F_NATIVE_SWAP_GLOBALS] = "native_swap_globals", + [MP_F_LOAD_NAME] = "load_name", + [MP_F_LOAD_GLOBAL] = "load_global", + [MP_F_LOAD_BUILD_CLASS] = "load_build_class", + [MP_F_LOAD_ATTR] = "load_attr", + [MP_F_LOAD_METHOD] = "load_method", + [MP_F_LOAD_SUPER_METHOD] = "load_super_method", + [MP_F_STORE_NAME] = "store_name", + [MP_F_STORE_GLOBAL] = "store_global", + [MP_F_STORE_ATTR] = "store_attr", + [MP_F_OBJ_SUBSCR] = "obj_subscr", + [MP_F_OBJ_IS_TRUE] = "obj_is_true", + [MP_F_UNARY_OP] = "unary_op", + [MP_F_BINARY_OP] = "binary_op", + [MP_F_BUILD_TUPLE] = "build_tuple", + [MP_F_BUILD_LIST] = "build_list", + [MP_F_BUILD_MAP] = "build_map", + [MP_F_BUILD_SET] = "build_set", + [MP_F_STORE_SET] = "store_set", + [MP_F_LIST_APPEND] = "list_append", + [MP_F_STORE_MAP] = "store_map", + [MP_F_MAKE_FUNCTION_FROM_PROTO_FUN] = "make_function_from_proto_fun", + [MP_F_NATIVE_CALL_FUNCTION_N_KW] = "native_call_function_n_kw", + [MP_F_CALL_METHOD_N_KW] = "call_method_n_kw", + [MP_F_CALL_METHOD_N_KW_VAR] = "call_method_n_kw_var", + [MP_F_NATIVE_GETITER] = "native_getiter", + [MP_F_NATIVE_ITERNEXT] = "native_iternext", + [MP_F_NLR_PUSH] = "nlr_push", + [MP_F_NLR_POP] = "nlr_pop", + [MP_F_NATIVE_RAISE] = "native_raise", + [MP_F_IMPORT_NAME] = "import_name", + [MP_F_IMPORT_FROM] = "import_from", + [MP_F_IMPORT_ALL] = "import_all", + [MP_F_NEW_SLICE] = "new_slice", + [MP_F_UNPACK_SEQUENCE] = "unpack_sequence", + [MP_F_UNPACK_EX] = "unpack_ex", + [MP_F_DELETE_NAME] = "delete_name", + [MP_F_DELETE_GLOBAL] = "delete_global", + [MP_F_NEW_CLOSURE] = "new_closure", + [MP_F_ARG_CHECK_NUM_SIG] = "arg_check_num_sig", + [MP_F_SETUP_CODE_STATE] = "setup_code_state", + [MP_F_SMALL_INT_FLOOR_DIVIDE] = "small_int_floor_divide", + [MP_F_SMALL_INT_MODULO] = "small_int_modulo", + [MP_F_NATIVE_YIELD_FROM] = "native_yield_from", + [MP_F_SETJMP] = "setjmp", +}; + +static void asm_debug_end_pass(asm_debug_t *as) { + (void)as; +} + +static void asm_debug_entry(asm_debug_t *as, int num_locals, char *name) { + asm_debug_printf(as, "ENTRY(%s, num_locals=%d)\n", name != NULL ? name : "?", num_locals); +} + +static void asm_debug_exit(asm_debug_t *as) { + asm_debug_printf(as, "EXIT(%u)\n", 0); +} + +static void asm_debug_fun(asm_debug_t *as, const char *op, int fun_idx) { + asm_debug_printf(as, "%s(%s)\n", op, fun_name_table[fun_idx]); +} + +static void asm_debug_reg(asm_debug_t *as, const char *op, int reg) { + asm_debug_printf(as, "%s(%s)\n", op, reg_name_table[reg]); +} + +static void asm_debug_label(asm_debug_t *as, const char *op, unsigned int label) { + asm_debug_printf(as, "%s(label_%u)\n", op, label); +} + +static void asm_debug_reg_imm(asm_debug_t *as, const char *op, int reg, int imm) { + asm_debug_printf(as, "%s(%s, %d=0x%x)\n", op, reg_name_table[reg], imm, imm); +} + +#if !MICROPY_PERSISTENT_CODE_SAVE +static void asm_debug_reg_qstr(asm_debug_t *as, const char *op, int reg, int qst) { + asm_debug_printf(as, "%s(%s, %s)\n", op, reg_name_table[reg], qstr_str(qst)); +} +#endif + +static void asm_debug_reg_reg(asm_debug_t *as, const char *op, int reg1, int reg2) { + asm_debug_printf(as, "%s(%s, %s)\n", op, reg_name_table[reg1], reg_name_table[reg2]); +} + +static void asm_debug_reg_local(asm_debug_t *as, const char *op, int reg, unsigned int local) { + asm_debug_printf(as, "%s(%s, local_%u)\n", op, reg_name_table[reg], local); +} + +static void asm_debug_reg_label(asm_debug_t *as, const char *op, int reg, unsigned int label) { + asm_debug_printf(as, "%s(%s, label_%u)\n", op, reg_name_table[reg], label); +} + +static void asm_debug_local_reg(asm_debug_t *as, const char *op, int local, int reg) { + asm_debug_printf(as, "%s(local_%d, %s)\n", op, local, reg_name_table[reg]); +} + +static void asm_debug_reg_label_bool(asm_debug_t *as, const char *op, int reg, unsigned int label, bool b) { + asm_debug_printf(as, "%s(%s, label_%u, %s)\n", op, reg_name_table[reg], label, b ? "true" : "false"); +} + +static void asm_debug_reg_reg_offset(asm_debug_t *as, const char *op, int reg1, int reg2, int offset) { + asm_debug_printf(as, "%s(%s, %s, %d)\n", op, reg_name_table[reg1], reg_name_table[reg2], offset); +} + +static void asm_debug_reg_reg_label(asm_debug_t *as, const char *op, int reg1, int reg2, unsigned int label) { + asm_debug_printf(as, "%s(%s, %s, label_%u)\n", op, reg_name_table[reg1], reg_name_table[reg2], label); +} + +static void asm_debug_setcc_reg_reg_reg(asm_debug_t *as, int op, int reg1, int reg2, int reg3) { + asm_debug_printf(as, "setcc(%d, %s, %s, %s)\n", op, reg_name_table[reg1], reg_name_table[reg2], reg_name_table[reg3]); +} + +// The following macros provide a (mostly) arch-independent API to +// generate native code, and are used by the native emitter. + +#define ASM_WORD_SIZE (8) + +#define REG_RET ASM_DEBUG_REG_R00 +#define REG_ARG_1 ASM_DEBUG_REG_R01 +#define REG_ARG_2 ASM_DEBUG_REG_R02 +#define REG_ARG_3 ASM_DEBUG_REG_R03 +#define REG_ARG_4 ASM_DEBUG_REG_R04 + +#define REG_TEMP0 ASM_DEBUG_REG_R05 +#define REG_TEMP1 ASM_DEBUG_REG_R06 +#define REG_TEMP2 ASM_DEBUG_REG_R07 + +#define REG_LOCAL_1 ASM_DEBUG_REG_R08 +#define REG_LOCAL_2 ASM_DEBUG_REG_R09 +#define REG_LOCAL_3 ASM_DEBUG_REG_R10 +#define REG_LOCAL_NUM (3) + +// Holds a pointer to mp_fun_table +#define REG_FUN_TABLE ASM_DEBUG_REG_R11 + +#define ASM_T asm_debug_t +#define ASM_END_PASS asm_debug_end_pass +#define ASM_ENTRY(as, num_locals, name) \ + asm_debug_entry(as, num_locals, name) +#define ASM_EXIT(as) \ + asm_debug_exit(as) + +#define ASM_JUMP(as, label) \ + asm_debug_label(as, "jump", label) +#define ASM_JUMP_IF_REG_ZERO(as, reg, label, bool_test) \ + asm_debug_reg_label_bool(as, "jump_if_reg_zero", reg, label, bool_test) +#define ASM_JUMP_IF_REG_NONZERO(as, reg, label, bool_test) \ + asm_debug_reg_label_bool(as, "jump_if_reg_nonzero", reg, label, bool_test) +#define ASM_JUMP_IF_REG_EQ(as, reg1, reg2, label) \ + asm_debug_reg_reg_label(as, "jump_if_reg_eq", reg1, reg2, label) +#define ASM_JUMP_REG(as, reg) \ + asm_debug_reg(as, "jump_reg", reg) +#define ASM_CALL_IND(as, idx) \ + asm_debug_fun(as, "call_ind", idx) + +#define ASM_MOV_LOCAL_REG(as, local_num, reg_src) \ + asm_debug_local_reg(as, "mov_local_reg", local_num, reg_src) +#define ASM_MOV_REG_IMM(as, reg_dest, imm) \ + asm_debug_reg_imm(as, "mov_reg_imm", reg_dest, imm) +#define ASM_MOV_REG_QSTR(as, reg_dest, qst) \ + asm_debug_reg_qstr(as, "mov_reg_qstr", reg_dest, qst) +#define ASM_MOV_REG_LOCAL(as, reg_dest, local_num) \ + asm_debug_reg_local(as, "mov_reg_local", reg_dest, local_num) +#define ASM_MOV_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "mov_reg_reg", reg_dest, reg_src) +#define ASM_MOV_REG_LOCAL_ADDR(as, reg_dest, local_num) \ + asm_debug_reg_local(as, "mov_reg_local_addr", reg_dest, local_num) +#define ASM_MOV_REG_PCREL(as, reg_dest, label) \ + asm_debug_reg_label(as, "mov_reg_pcrel", reg_dest, label) + +#define ASM_NOT_REG(as, reg_dest) \ + asm_debug_reg(as, "not", reg_dest) +#define ASM_NEG_REG(as, reg_dest) \ + asm_debug_reg(as, "neg", reg_dest) +#define ASM_LSL_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "lsl", reg_dest, reg_src) +#define ASM_LSR_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "lsr", reg_dest, reg_src) +#define ASM_ASR_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "asr", reg_dest, reg_src) +#define ASM_OR_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "or", reg_dest, reg_src) +#define ASM_XOR_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "xor", reg_dest, reg_src) +#define ASM_AND_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "and", reg_dest, reg_src) +#define ASM_ADD_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "add", reg_dest, reg_src) +#define ASM_SUB_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "sub", reg_dest, reg_src) +#define ASM_MUL_REG_REG(as, reg_dest, reg_src) \ + asm_debug_reg_reg(as, "mul", reg_dest, reg_src) + +#define ASM_LOAD_REG_REG_OFFSET(as, reg_dest, reg_base, word_offset) \ + asm_debug_reg_reg_offset(as, "load", reg_dest, reg_base, word_offset) +#define ASM_LOAD8_REG_REG(as, reg_dest, reg_base) \ + asm_debug_reg_reg(as, "load8", reg_dest, reg_base) +#define ASM_LOAD16_REG_REG(as, reg_dest, reg_base) \ + asm_debug_reg_reg(as, "load16", reg_dest, reg_base) +#define ASM_LOAD16_REG_REG_OFFSET(as, reg_dest, reg_base, uint16_offset) \ + asm_debug_reg_reg_offset(as, "load16", reg_dest, reg_base, uint16_offset) +#define ASM_LOAD32_REG_REG(as, reg_dest, reg_base) \ + asm_debug_reg_reg(as, "load32", reg_dest, reg_base) + +#define ASM_STORE_REG_REG_OFFSET(as, reg_src, reg_base, word_offset) \ + asm_debug_reg_reg_offset(as, "store", reg_src, reg_base, word_offset) +#define ASM_STORE8_REG_REG(as, reg_src, reg_base) \ + asm_debug_reg_reg(as, "store8", reg_src, reg_base) +#define ASM_STORE16_REG_REG(as, reg_src, reg_base) \ + asm_debug_reg_reg(as, "store16", reg_src, reg_base) +#define ASM_STORE32_REG_REG(as, reg_src, reg_base) \ + asm_debug_reg_reg(as, "store32", reg_src, reg_base) + +// Word indices of REG_LOCAL_x in nlr_buf_t +#define NLR_BUF_IDX_LOCAL_1 (5) // rbx + +#define N_DEBUG (1) +#define EXPORT_FUN(name) emit_native_debug_##name +#include "py/emitnative.c" + +#endif diff --git a/py/emitnrv32.c b/py/emitnrv32.c new file mode 100644 index 0000000000000..4a44100093141 --- /dev/null +++ b/py/emitnrv32.c @@ -0,0 +1,44 @@ +/* + * This file is part of the MicroPython project, https://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// RISC-V RV32 specific stuff + +#include "py/mpconfig.h" + +#if MICROPY_EMIT_RV32 + +// this is defined so that the assembler exports generic assembler API macros +#define GENERIC_ASM_API (1) +#include "py/asmrv32.h" + +// Word indices of REG_LOCAL_x in nlr_buf_t +#define NLR_BUF_IDX_LOCAL_1 (6) // S3 + +#define N_RV32 (1) +#define EXPORT_FUN(name) emit_native_rv32_##name +#include "py/emitnative.c" + +#endif diff --git a/py/emitnx86.c b/py/emitnx86.c index a9050c65d4036..1d2aefa7920bc 100644 --- a/py/emitnx86.c +++ b/py/emitnx86.c @@ -13,7 +13,7 @@ #define NLR_BUF_IDX_LOCAL_1 (5) // ebx // x86 needs a table to know how many args a given function has -STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { +static byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_CONVERT_OBJ_TO_NATIVE] = 2, [MP_F_CONVERT_NATIVE_TO_OBJ] = 2, [MP_F_NATIVE_SWAP_GLOBALS] = 1, @@ -37,7 +37,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = { [MP_F_STORE_SET] = 2, [MP_F_LIST_APPEND] = 2, [MP_F_STORE_MAP] = 3, - [MP_F_MAKE_FUNCTION_FROM_RAW_CODE] = 3, + [MP_F_MAKE_FUNCTION_FROM_PROTO_FUN] = 3, [MP_F_NATIVE_CALL_FUNCTION_N_KW] = 3, [MP_F_CALL_METHOD_N_KW] = 3, [MP_F_CALL_METHOD_N_KW_VAR] = 3, diff --git a/py/formatfloat.c b/py/formatfloat.c index b4348122ff428..1ea34f84bf7fb 100644 --- a/py/formatfloat.c +++ b/py/formatfloat.c @@ -33,394 +33,537 @@ #include #include #include "py/formatfloat.h" +#include "py/parsenum.h" /*********************************************************************** Routine for converting a arbitrary floating point number into a string. - The code in this function was inspired from Fred Bayer's pdouble.c. - Since pdouble.c was released as Public Domain, I'm releasing this - code as public domain as well. + The code in this function was inspired from Dave Hylands's previous + version, which was itself inspired from Fred Bayer's pdouble.c. The original code can be found in https://github.com/dhylands/format-float - Dave Hylands - ***********************************************************************/ -#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -// 1 sign bit, 8 exponent bits, and 23 mantissa bits. -// exponent values 0 and 255 are reserved, exponent can be 1 to 254. -// exponent is stored with a bias of 127. -// The min and max floats are on the order of 1x10^37 and 1x10^-37 - -#define FPTYPE float -#define FPCONST(x) x##F -#define FPROUND_TO_ONE 0.9999995F -#define FPDECEXP 32 -#define FPMIN_BUF_SIZE 6 // +9e+99 +// Float formatting debug code is intended for use in ports/unix only, +// as it uses the libc float printing function as a reference. +#define DEBUG_FLOAT_FORMATTING 0 + +#if DEBUG_FLOAT_FORMATTING +#define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +#if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT || MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define MP_FFUINT_FMT "%lu" +#else +#define MP_FFUINT_FMT "%u" +#endif + +static inline int fp_expval(mp_float_t x) { + mp_float_union_t fb = { x }; + return (int)fb.p.exp - MP_FLOAT_EXP_OFFSET; +} -#define FLT_SIGN_MASK 0x80000000 +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -static inline int fp_signbit(float x) { - mp_float_union_t fb = {x}; - return fb.i & FLT_SIGN_MASK; +static inline int fp_isless1(mp_float_t x) { + return x < 1.0; } -#define fp_isnan(x) isnan(x) -#define fp_isinf(x) isinf(x) -static inline int fp_iszero(float x) { - mp_float_union_t fb = {x}; - return fb.i == 0; + +static inline int fp_iszero(mp_float_t x) { + return x == 0.0; } -static inline int fp_isless1(float x) { - mp_float_union_t fb = {x}; + +#if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX +static inline int fp_equal(mp_float_t x, mp_float_t y) { + return x == y; +} +#else +static inline mp_float_t fp_diff(mp_float_t x, mp_float_t y) { + return x - y; +} +#endif + +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT + +// The functions below are roughly equivalent to the ones above, +// but they are optimized to reduce code footprint by skipping +// handling for special values such as nan, inf, +/-0.0 +// for ports where FP support is done in software. +// +// They also take into account lost bits of REPR_C as needed. + +static inline int fp_isless1(mp_float_t x) { + mp_float_union_t fb = { x }; return fb.i < 0x3f800000; } -#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +static inline int fp_iszero(mp_float_t x) { + mp_float_union_t x_check = { x }; + return !x_check.i; // this is valid for REPR_C as well +} -// CIRCUITPY-CHANGE: prevent warnings -#pragma GCC diagnostic ignored "-Wfloat-equal" -#define FPTYPE double -#define FPCONST(x) x -#define FPROUND_TO_ONE 0.999999999995 -#define FPDECEXP 256 -#define FPMIN_BUF_SIZE 7 // +9e+199 -#define fp_signbit(x) signbit(x) -#define fp_isnan(x) isnan(x) -#define fp_isinf(x) isinf(x) -#define fp_iszero(x) (x == 0) -#define fp_isless1(x) (x < 1.0) +#if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX +static inline int fp_equal(mp_float_t x, mp_float_t y) { + mp_float_union_t x_check = { x }; + mp_float_union_t y_check = { y }; + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + return (x_check.i & ~3) == (y_check.i & ~3); + #else + return x_check.i == y_check.i; + #endif +} +#else +static inline mp_float_t fp_diff(mp_float_t x, mp_float_t y) { + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C + mp_float_union_t x_check = { x }; + mp_float_union_t y_check = { y }; + x_check.i &= ~3; + y_check.i &= ~3; + return x_check.f - y_check.f; + #else + return x - y; + #endif +} +#endif -#endif // MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT/DOUBLE +#endif -static inline int fp_expval(FPTYPE x) { - mp_float_union_t fb = {x}; - return (int)((fb.i >> MP_FLOAT_FRAC_BITS) & (~(0xFFFFFFFF << MP_FLOAT_EXP_BITS))) - MP_FLOAT_EXP_OFFSET; +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define FPMIN_BUF_SIZE 6 // +9e+99 +#define MAX_MANTISSA_DIGITS (9) +#define SAFE_MANTISSA_DIGITS (6) +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#define FPMIN_BUF_SIZE 7 // +9e+199 +#define MAX_MANTISSA_DIGITS (19) +#define SAFE_MANTISSA_DIGITS (16) +#endif + +// Internal formatting flags +#define FMT_MODE_E 0x01 // render using scientific notation (%e) +#define FMT_MODE_G 0x02 // render using general format (%g) +#define FMT_MODE_F 0x04 // render using using expanded fixed-point format (%f) +#define FMT_E_CASE 0x20 // don't change this value (used for case conversion!) + +static char *mp_prepend_zeros(char *s, int cnt) { + *s++ = '0'; + *s++ = '.'; + while (cnt > 0) { + *s++ = '0'; + cnt--; + } + return s; } -int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, char sign) { +// Helper to convert a decimal mantissa (provided as an mp_large_float_uint_t) to string +static int mp_format_mantissa(mp_large_float_uint_t mantissa, mp_large_float_uint_t mantissa_cap, char *buf, char *s, + int num_digits, int max_exp_zeros, int trailing_zeros, int dec, int e, int fmt_flags) { - char *s = buf; + DEBUG_PRINTF("mantissa=" MP_FFUINT_FMT " exp=%d (cap=" MP_FFUINT_FMT "):\n", mantissa, e, mantissa_cap); - if (buf_size <= FPMIN_BUF_SIZE) { - // FPMIN_BUF_SIZE is the minimum size needed to store any FP number. - // If the buffer does not have enough room for this (plus null terminator) - // then don't try to format the float. + if (mantissa) { + // If rounding/searching created an extra digit or removed too many, fix mantissa first + if (mantissa >= mantissa_cap) { + if (fmt_flags & FMT_MODE_F) { + assert(e >= 0); + num_digits++; + dec++; + } else { + mantissa /= 10; + e++; + } + } + } - if (buf_size >= 2) { - *s++ = '?'; + // When 'g' format is used, replace small exponents by explicit zeros + if ((fmt_flags & FMT_MODE_G) && e != 0) { + if (e >= 0) { + // If 0 < e < max_exp_zeros, expand positive exponent into trailing zeros + if (e < max_exp_zeros) { + dec += e; + if (dec >= num_digits) { + trailing_zeros = dec - (num_digits - 1); + } + e = 0; + } + } else { + // If -4 <= e < 0, expand negative exponent without losing significant digits + if (e >= -4) { + int cnt = 0; + while (e < 0 && !(mantissa % 10)) { + mantissa /= 10; + cnt++; + e++; + } + num_digits -= cnt; + s = mp_prepend_zeros(s, cnt - e - 1); + dec = 255; + e = 0; + } } - if (buf_size >= 1) { - *s = '\0'; + } + + // Convert the integer mantissa to string + for (int digit = num_digits - 1; digit >= 0; digit--) { + int digit_ofs = (digit > dec ? digit + 1 : digit); + s[digit_ofs] = '0' + (int)(mantissa % 10); + mantissa /= 10; + } + int dot = (dec >= 255); + if (dec + 1 < num_digits) { + dot = 1; + s++; + s[dec] = '.'; + } + s += num_digits; + #if DEBUG_FLOAT_FORMATTING + *s = 0; + DEBUG_PRINTF(" = %s exp=%d num_digits=%d zeros=%d dec=%d\n", buf, e, num_digits, trailing_zeros, dec); + #endif + + // Append or remove trailing zeros, as required by format + if (trailing_zeros) { + dec -= num_digits - 1; + while (trailing_zeros--) { + if (!dec--) { + *s++ = '.'; + dot = 1; + } + *s++ = '0'; } - return buf_size >= 2; } - if (fp_signbit(f) && !fp_isnan(f)) { - *s++ = '-'; - f = -f; - } else { - if (sign) { - *s++ = sign; + if (fmt_flags & FMT_MODE_G) { + // 'g' format requires to remove trailing zeros after decimal point + if (dot) { + while (s[-1] == '0') { + s--; + } + if (s[-1] == '.') { + s--; + } + } + } + + // Append the exponent if needed + if (((e != 0) || (fmt_flags & FMT_MODE_E)) && !(fmt_flags & FMT_MODE_F)) { + *s++ = 'E' | (fmt_flags & FMT_E_CASE); + if (e >= 0) { + *s++ = '+'; + } else { + *s++ = '-'; + e = -e; } + if (e >= 100) { + *s++ = '0' + (e / 100); + } + *s++ = '0' + ((e / 10) % 10); + *s++ = '0' + (e % 10); } + *s = '\0'; + DEBUG_PRINTF(" ===> %s\n", buf); - // buf_remaining contains bytes available for digits and exponent. - // It is buf_size minus room for the sign and null byte. - int buf_remaining = buf_size - 1 - (s - buf); + return s - buf; +} +// minimal value expected for buf_size, to avoid checking everywhere for overflow +#define MIN_BUF_SIZE (MAX_MANTISSA_DIGITS + 10) + +int mp_format_float(mp_float_t f_entry, char *buf_entry, size_t buf_size, char fmt, int prec, char sign) { + assert(buf_size >= MIN_BUF_SIZE); + + // Handle sign + mp_float_t f = f_entry; + char *buf = buf_entry; + if (signbit(f_entry) && !isnan(f_entry)) { + f = -f; + sign = '-'; + } + if (sign) { + *buf++ = sign; + buf_size--; + } + + // Handle inf/nan + char uc = fmt & 0x20; { - char uc = fmt & 0x20; - if (fp_isinf(f)) { + char *s = buf; + if (isinf(f)) { *s++ = 'I' ^ uc; *s++ = 'N' ^ uc; *s++ = 'F' ^ uc; goto ret; - } else if (fp_isnan(f)) { + } else if (isnan(f)) { *s++ = 'N' ^ uc; *s++ = 'A' ^ uc; *s++ = 'N' ^ uc; ret: *s = '\0'; - return s - buf; + return s - buf_entry; } } + // Decode format character + int fmt_flags = (unsigned char)uc; // setup FMT_E_CASE, clear all other bits + char lofmt = (char)(fmt | 0x20); // fmt in lowercase + if (lofmt == 'f') { + fmt_flags |= FMT_MODE_F; + } else if (lofmt == 'g') { + fmt_flags |= FMT_MODE_G; + } else { + fmt_flags |= FMT_MODE_E; + } + + // When precision is unspecified, default to 6 if (prec < 0) { prec = 6; } - char e_char = 'E' | (fmt & 0x20); // e_char will match case of fmt - fmt |= 0x20; // Force fmt to be lowercase - char org_fmt = fmt; - if (fmt == 'g' && prec == 0) { - prec = 1; + // Use high precision for `repr`, but switch to exponent mode + // after 16 digits in any case to match CPython behaviour + int max_exp_zeros = (prec < (int)buf_size - 3 ? prec : (int)buf_size - 3); + if (prec == MP_FLOAT_REPR_PREC) { + prec = MAX_MANTISSA_DIGITS; + max_exp_zeros = 16; } - int e; - int dec = 0; - char e_sign = '\0'; - int num_digits = 0; - int signed_e = 0; - // Approximate power of 10 exponent from binary exponent. - // abs(e_guess) is lower bound on abs(power of 10 exponent). - int e_guess = (int)(fp_expval(f) * FPCONST(0.3010299956639812)); // 1/log2(10). - if (fp_iszero(f)) { - e = 0; - if (fmt == 'f') { - // Truncate precision to prevent buffer overflow - if (prec + 2 > buf_remaining) { - prec = buf_remaining - 2; - } - num_digits = prec + 1; - } else { - // Truncate precision to prevent buffer overflow - if (prec + 6 > buf_remaining) { - prec = buf_remaining - 6; - } - if (fmt == 'e') { - e_sign = '+'; - } + // Precompute the exact decimal exponent of f, such that + // abs(e) is lower bound on abs(power of 10 exponent). + int e = 0; + if (!fp_iszero(f)) { + // Approximate power of 10 exponent from binary exponent. + e = (int)(fp_expval(f) * MICROPY_FLOAT_CONST(0.3010299956639812)); // 1/log2(10). + int positive_exp = !fp_isless1(f); + mp_float_t u_base = (mp_float_t)mp_decimal_exp((mp_large_float_t)1.0, e + positive_exp); + while ((f >= u_base) == positive_exp) { + e += (positive_exp ? 1 : -1); + u_base = (mp_float_t)mp_decimal_exp((mp_large_float_t)1.0, e + positive_exp); } - } else if (fp_isless1(f)) { - FPTYPE f_entry = f; // Save f in case we go to 'f' format. - // Build negative exponent - e = -e_guess; - FPTYPE u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); - while (u_base > f) { - ++e; - u_base = MICROPY_FLOAT_C_FUN(pow)(10, -e); - } - // Normalize out the inferred unit. Use divide because - // pow(10, e) * pow(10, -e) is slightly < 1 for some e in float32 - // (e.g. print("%.12f" % ((1e13) * (1e-13)))) - f /= u_base; - - // If the user specified 'g' format, and e is <= 4, then we'll switch - // to the fixed format ('f') - - if (fmt == 'f' || (fmt == 'g' && e <= 4)) { - fmt = 'f'; - dec = 0; + } - if (org_fmt == 'g') { - prec += (e - 1); - } + // For 'e' format, prec is # digits after the decimal + // For 'f' format, prec is # digits after the decimal + // For 'g' format, prec is the max number of significant digits + // + // For 'e' & 'g' format, there will be a single digit before the decimal + // For 'f' format, zeros must be expanded instead of using an exponent. + // Make sure there is enough room in the buffer for them, or switch to format 'g'. + if ((fmt_flags & FMT_MODE_F) && e > 0) { + int req_size = e + prec + 2; + if (req_size > (int)buf_size) { + fmt_flags ^= FMT_MODE_F; + fmt_flags |= FMT_MODE_G; + prec++; + } + } - // truncate precision to prevent buffer overflow - if (prec + 2 > buf_remaining) { - prec = buf_remaining - 2; + // To work independently of the format, we precompute: + // - the max number of significant digits to produce + // - the number of leading zeros to prepend (mode f only) + // - the number of trailing zeros to append + int max_digits = prec; + int lead_zeros = 0; + int trail_zeros = 0; + if (fmt_flags & FMT_MODE_F) { + if (max_digits > (int)buf_size - 3) { + // cannot satisfy requested number of decimals given buf_size, sorry + max_digits = (int)buf_size - 3; + } + if (e < 0) { + if (max_digits > 2 && e < -2) { + // Insert explicit leading zeros + lead_zeros = (-e < max_digits ? -e : max_digits) - 2; + max_digits -= lead_zeros; + } else { + max_digits++; } - - num_digits = prec; - signed_e = 0; - f = f_entry; - ++num_digits; } else { - // For e & g formats, we'll be printing the exponent, so set the - // sign. - e_sign = '-'; - dec = 0; - - if (prec > (buf_remaining - FPMIN_BUF_SIZE)) { - prec = buf_remaining - FPMIN_BUF_SIZE; - if (fmt == 'g') { - prec++; - } - } - signed_e = -e; + max_digits += e + 1; } } else { - // Build positive exponent. - // We don't modify f at this point to avoid inaccuracies from - // scaling it. Instead, we find the product of powers of 10 - // that is not greater than it, and use that to start the - // mantissa. - e = e_guess; - FPTYPE next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); - while (f >= next_u) { - ++e; - next_u = MICROPY_FLOAT_C_FUN(pow)(10, e + 1); + if (!(fmt_flags & FMT_MODE_G) || max_digits == 0) { + max_digits++; } + } + if (max_digits > MAX_MANTISSA_DIGITS) { + // use trailing zeros to avoid overflowing the mantissa + trail_zeros = max_digits - MAX_MANTISSA_DIGITS; + max_digits = MAX_MANTISSA_DIGITS; + } + int overhead = (fmt_flags & FMT_MODE_F ? 3 : FPMIN_BUF_SIZE + 1); + if (trail_zeros > (int)buf_size - max_digits - overhead) { + // cannot satisfy requested number of decimals given buf_size, sorry + trail_zeros = (int)buf_size - max_digits - overhead; + } - // If the user specified fixed format (fmt == 'f') and e makes the - // number too big to fit into the available buffer, then we'll - // switch to the 'e' format. - - if (fmt == 'f') { - if (e >= buf_remaining) { - fmt = 'e'; - } else if ((e + prec + 2) > buf_remaining) { - prec = buf_remaining - e - 2; - if (prec < 0) { - // This means no decimal point, so we can add one back - // for the decimal. - prec++; - } - } - } - if (fmt == 'e' && prec > (buf_remaining - FPMIN_BUF_SIZE)) { - prec = buf_remaining - FPMIN_BUF_SIZE; - } - if (fmt == 'g') { - // Truncate precision to prevent buffer overflow - if (prec + (FPMIN_BUF_SIZE - 1) > buf_remaining) { - prec = buf_remaining - (FPMIN_BUF_SIZE - 1); - } - } - // If the user specified 'g' format, and e is < prec, then we'll switch - // to the fixed format. + // When the caller asks for more precision than available for sure, + // Look for a shorter (rounded) representation first, and only dig + // into more digits if there is no short representation. + int num_digits = (SAFE_MANTISSA_DIGITS < max_digits ? SAFE_MANTISSA_DIGITS : max_digits); +try_again: + ; - if (fmt == 'g' && e < prec) { - fmt = 'f'; - prec -= (e + 1); - } - if (fmt == 'f') { - dec = e; - num_digits = prec + e + 1; + char *s = buf; + int extra_zeros = trail_zeros + (max_digits - num_digits); + int decexp; + int dec = 0; + + if (fp_iszero(f)) { + // no need for scaling 0.0 + decexp = 0; + } else if (fmt_flags & FMT_MODE_F) { + decexp = num_digits - 1; + if (e < 0) { + // Negative exponent: we keep a single leading zero in the mantissa, + // as using more would waste precious digits needed for accuracy. + if (lead_zeros > 0) { + // We are using leading zeros + s = mp_prepend_zeros(s, lead_zeros); + decexp += lead_zeros + 1; + dec = 255; // no decimal dot + } else { + // Small negative exponent, work directly on the mantissa + dec = 0; + } } else { - e_sign = '+'; + // Positive exponent: we will add trailing zeros separately + decexp -= e; + dec = e; } - signed_e = e; + } else { + decexp = num_digits - e - 1; } - if (prec < 0) { - // This can happen when the prec is trimmed to prevent buffer overflow - prec = 0; + DEBUG_PRINTF("input=%.19g e=%d fmt=%c max_d=%d num_d=%d decexp=%d dec=%d l0=%d r0=%d\n", + (double)f, e, lofmt, max_digits, num_digits, decexp, dec, lead_zeros, extra_zeros); + + // At this point, + // - buf points to beginning of output buffer for the unsigned representation + // - num_digits == the number of mantissa digits to add + // - (dec + 1) == the number of digits to print before adding a decimal point + // - decexp == the power of 10 exponent to apply to f to get the decimal mantissa + // - e == the power of 10 exponent to append ('e' or 'g' format) + mp_large_float_uint_t mantissa_cap = 10; + for (int n = 1; n < num_digits; n++) { + mantissa_cap *= 10; } - // At this point e contains the absolute value of the power of 10 exponent. - // (dec + 1) == the number of dgits before the decimal. - - // For e, prec is # digits after the decimal - // For f, prec is # digits after the decimal - // For g, prec is the max number of significant digits - // - // For e & g there will be a single digit before the decimal - // for f there will be e digits before the decimal - - if (fmt == 'e') { - num_digits = prec + 1; - } else if (fmt == 'g') { - if (prec == 0) { - prec = 1; + // Build the decimal mantissa into a large uint + mp_large_float_uint_t mantissa = 1; + if (sizeof(mp_large_float_t) == sizeof(mp_float_t) && num_digits > SAFE_MANTISSA_DIGITS && decexp > 1) { + // if we don't have large floats, use integer multiply to produce the last digits + if (num_digits > SAFE_MANTISSA_DIGITS + 1 && decexp > 2) { + mantissa = 100; + decexp -= 2; + } else { + mantissa = 10; + decexp -= 1; } - num_digits = prec; } - - int d = 0; - for (int digit_index = signed_e; num_digits >= 0; --digit_index) { - FPTYPE u_base = FPCONST(1.0); - if (digit_index > 0) { - // Generate 10^digit_index for positive digit_index. - u_base = MICROPY_FLOAT_C_FUN(pow)(10, digit_index); - } - for (d = 0; d < 9; ++d) { - if (f < u_base) { - break; - } - f -= u_base; - } - // We calculate one more digit than we display, to use in rounding - // below. So only emit the digit if it's one that we display. - if (num_digits > 0) { - // Emit this number (the leading digit). - *s++ = '0' + d; - if (dec == 0 && prec > 0) { - *s++ = '.'; - } - } - --dec; - --num_digits; - if (digit_index <= 0) { - // Once we get below 1.0, we scale up f instead of calculating - // negative powers of 10 in u_base. This provides better - // renditions of exact decimals like 1/16 etc. - f *= FPCONST(10.0); + mp_large_float_t mantissa_f = mp_decimal_exp((mp_large_float_t)f, decexp); + mantissa *= (mp_large_float_uint_t)(mantissa_f + (mp_large_float_t)0.5); + DEBUG_PRINTF("input=%.19g fmt=%c num_digits=%d dec=%d mantissa=" MP_FFUINT_FMT " r0=%d\n", (double)f, lofmt, num_digits, dec, mantissa, extra_zeros); + + // Finally convert the decimal mantissa to a floating-point string, according to formatting rules + int reprlen = mp_format_mantissa(mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + assert(reprlen + 1 <= (int)buf_size); + + #if MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_APPROX + + if (num_digits < max_digits) { + // The initial precision might not be sufficient for an exact representation + // for all numbers. If the result is not exact, restart using next precision. + // parse the resulting number and compare against the original + mp_float_t check; + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + if (!fp_equal(check, f)) { + num_digits++; + DEBUG_PRINTF("Not perfect, retry using more digits (%d)\n", num_digits); + goto try_again; } } - // Rounding. If the next digit to print is >= 5, round up. - if (d >= 5) { - char *rs = s; - rs--; - while (1) { - if (*rs == '.') { - rs--; - continue; - } - if (*rs < '0' || *rs > '9') { - // + or - - rs++; // So we sit on the digit to the right of the sign - break; + + #else + + // The initial decimal mantissa might not have been be completely accurate due + // to the previous loating point operations. The best way to verify this is to + // parse the resulting number and compare against the original + mp_float_t check; + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + mp_float_t diff = fp_diff(check, f); + mp_float_t best_diff = diff; + mp_large_float_uint_t best_mantissa = mantissa; + + if (fp_iszero(diff)) { + // we have a perfect match + DEBUG_PRINTF(MP_FFUINT_FMT ": perfect match (direct)\n", mantissa); + } else { + // In order to get the best possible representation, we will perform a + // dichotomic search for a reversible representation. + // This will also provide optimal rounding on the fly. + unsigned err_range = 1; + if (num_digits > SAFE_MANTISSA_DIGITS) { + err_range <<= 3 * (num_digits - SAFE_MANTISSA_DIGITS); + } + int maxruns = 3 + 3 * (MAX_MANTISSA_DIGITS - SAFE_MANTISSA_DIGITS); + while (maxruns-- > 0) { + // update mantissa according to dichotomic search + if (signbit(diff)) { + mantissa += err_range; + } else { + // mantissa is expected to always have more significant digits than err_range + assert(mantissa >= err_range); + mantissa -= err_range; } - if (*rs < '9') { - (*rs)++; + // retry conversion + reprlen = mp_format_mantissa(mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + assert(reprlen + 1 <= (int)buf_size); + DEBUG_PRINTF("input=%.19g, compare to float('%s')\n", (double)f, buf); + mp_parse_float_internal(buf, reprlen, &check); + DEBUG_PRINTF("check=%.19g num_digits=%d e=%d mantissa=" MP_FFUINT_FMT "\n", (double)check, num_digits, e, mantissa); + diff = fp_diff(check, f); + if (fp_iszero(diff)) { + // we have a perfect match + DEBUG_PRINTF(MP_FFUINT_FMT ": perfect match\n", mantissa); break; } - *rs = '0'; - if (rs == buf) { - break; + // keep track of our best estimate + mp_float_t delta = MICROPY_FLOAT_C_FUN(fabs)(diff) - MICROPY_FLOAT_C_FUN(fabs)(best_diff); + if (signbit(delta) || (fp_iszero(delta) && !(mantissa % 10u))) { + best_diff = diff; + best_mantissa = mantissa; } - rs--; - } - if (*rs == '0') { - // We need to insert a 1 - if (rs[1] == '.' && fmt != 'f') { - // We're going to round 9.99 to 10.00 - // Move the decimal point - rs[0] = '.'; - rs[1] = '0'; - if (e_sign == '-') { - e--; - if (e == 0) { - e_sign = '+'; - } - } else { - e++; - } + // string repr is not perfect: continue a dichotomic improvement + DEBUG_PRINTF(MP_FFUINT_FMT ": %.19g, err_range=%d\n", mantissa, (double)check, err_range); + if (err_range > 1) { + err_range >>= 1; } else { - // Need at extra digit at the end to make room for the leading '1' - // but if we're at the buffer size limit, just drop the final digit. - if ((size_t)(s + 1 - buf) < buf_size) { - s++; + // We have tried all possible mantissa, without finding a reversible repr. + // Check if we have an alternate precision to try. + if (num_digits < max_digits) { + num_digits++; + DEBUG_PRINTF("Failed to find a perfect match, try with more digits (%d)\n", num_digits); + goto try_again; } + // Otherwise, keep the closest one, which is either the first one or the last one. + if (mantissa == best_mantissa) { + // Last guess is the best one + DEBUG_PRINTF(MP_FFUINT_FMT ": last guess was the best one\n", mantissa); + } else { + // We had a better guess earlier + DEBUG_PRINTF(MP_FFUINT_FMT ": use best guess\n", mantissa); + reprlen = mp_format_mantissa(best_mantissa, mantissa_cap, buf, s, num_digits, max_exp_zeros, extra_zeros, dec, e, fmt_flags); + } + break; } - char *ss = s; - while (ss > rs) { - *ss = ss[-1]; - ss--; - } - *rs = '1'; } } + #endif - // verify that we did not overrun the input buffer so far - assert((size_t)(s + 1 - buf) <= buf_size); - - if (org_fmt == 'g' && prec > 0) { - // Remove trailing zeros and a trailing decimal point - while (s[-1] == '0') { - s--; - } - if (s[-1] == '.') { - s--; - } - } - // Append the exponent - if (e_sign) { - *s++ = e_char; - *s++ = e_sign; - if (FPMIN_BUF_SIZE == 7 && e >= 100) { - *s++ = '0' + (e / 100); - } - *s++ = '0' + ((e / 10) % 10); - *s++ = '0' + (e % 10); - } - *s = '\0'; - - // verify that we did not overrun the input buffer - assert((size_t)(s + 1 - buf) <= buf_size); - - return s - buf; + return buf + reprlen - buf_entry; } #endif // MICROPY_FLOAT_IMPL != MICROPY_FLOAT_IMPL_NONE diff --git a/py/formatfloat.h b/py/formatfloat.h index 9a1643b4ddff5..7b1414672b77b 100644 --- a/py/formatfloat.h +++ b/py/formatfloat.h @@ -29,6 +29,7 @@ #include "py/mpconfig.h" #if MICROPY_PY_BUILTINS_FLOAT +#define MP_FLOAT_REPR_PREC (99) // magic `prec` value for optimal `repr` behaviour int mp_format_float(mp_float_t f, char *buf, size_t bufSize, char fmt, int prec, char sign); #endif diff --git a/py/gc.c b/py/gc.c index 7c60ab79627e3..757c27e3de696 100644 --- a/py/gc.c +++ b/py/gc.c @@ -32,6 +32,12 @@ #include "py/gc.h" #include "py/runtime.h" +#if defined(__ZEPHYR__) +#include +#include +#include +#endif + #if MICROPY_DEBUG_VALGRIND #include #endif @@ -39,10 +45,18 @@ // CIRCUITPY-CHANGE #include "supervisor/shared/safe_mode.h" +#include "supervisor/shared/serial.h" + #if CIRCUITPY_MEMORYMONITOR #include "shared-module/memorymonitor/__init__.h" #endif +#if defined(__ZEPHYR__) && defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +#include "perfetto_encoder.h" +#define CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID 0x3001ULL +#define CIRCUITPY_PERFETTO_VM_HEAP_MAX_FREE_UUID 0x3002ULL +#endif + #if MICROPY_ENABLE_GC #if MICROPY_DEBUG_VERBOSE // print debugging info @@ -123,10 +137,23 @@ #define FTB_CLEAR(area, block) do { area->gc_finaliser_table_start[(block) / BLOCKS_PER_FTB] &= (~(1 << ((block) & 7))); } while (0) #endif +// CIRCUITPY-CHANGE: Add selective collect table to skip scanning large buffers without pointers +// CTB = collect table byte +// if set, then the corresponding block should be collected during GC + +#define BLOCKS_PER_CTB (8) + +#define CTB_GET(area, block) ((area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] >> ((block) & 7)) & 1) +#define CTB_SET(area, block) do { area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] |= (1 << ((block) & 7)); } while (0) +#define CTB_CLEAR(area, block) do { area->gc_collect_table_start[(block) / BLOCKS_PER_CTB] &= (~(1 << ((block) & 7))); } while (0) + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL -#define GC_ENTER() mp_thread_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) -#define GC_EXIT() mp_thread_mutex_unlock(&MP_STATE_MEM(gc_mutex)) +#define GC_MUTEX_INIT() mp_thread_recursive_mutex_init(&MP_STATE_MEM(gc_mutex)) +#define GC_ENTER() mp_thread_recursive_mutex_lock(&MP_STATE_MEM(gc_mutex), 1) +#define GC_EXIT() mp_thread_recursive_mutex_unlock(&MP_STATE_MEM(gc_mutex)) #else +// Either no threading, or assume callers to gc_collect() hold the GIL +#define GC_MUTEX_INIT() #define GC_ENTER() #define GC_EXIT() #endif @@ -143,48 +170,103 @@ void __attribute__ ((noinline)) gc_log_change(uint32_t start_block, uint32_t len #pragma GCC pop_options #endif +#if defined(__ZEPHYR__) && defined(CONFIG_TRACING_PERFETTO) && defined(CONFIG_BOARD_NATIVE_SIM) +static void gc_perfetto_emit_heap_stats(void) { + if (!perfetto_start()) { + return; + } + gc_info_t info; + gc_info(&info); + perfetto_emit_counter(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, (int64_t)info.used); + Z_SPIN_DELAY(1); +} + +static void gc_perfetto_emit_heap_stopped(void) { + if (!perfetto_start()) { + return; + } + perfetto_emit_counter(CIRCUITPY_PERFETTO_VM_HEAP_USED_UUID, 0); + Z_SPIN_DELAY(1); +} +#else +static inline void gc_perfetto_emit_heap_stats(void) { +} + +static inline void gc_perfetto_emit_heap_stopped(void) { +} +#endif + +// Static functions for individual steps of the GC mark/sweep sequence +static void gc_collect_start_common(void); +static void *gc_get_ptr(void **ptrs, int i); +#if MICROPY_GC_SPLIT_HEAP +static void gc_mark_subtree(mp_state_mem_area_t *area, size_t block); +#else +static void gc_mark_subtree(size_t block); +#endif +static void gc_deal_with_stack_overflow(void); +static void gc_sweep_run_finalisers(void); +static void gc_sweep_free_blocks(void); + // TODO waste less memory; currently requires that all entries in alloc_table have a corresponding block in pool -STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { - // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, P=pool; all in bytes): - // T = A + F + P +static void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { + // CIRCUITPY-CHANGE: Updated calculation to include selective collect table + // calculate parameters for GC (T=total, A=alloc table, F=finaliser table, C=collect table, P=pool; all in bytes): + // T = A + F + C + P // F = A * BLOCKS_PER_ATB / BLOCKS_PER_FTB + // C = A * BLOCKS_PER_ATB / BLOCKS_PER_CTB // P = A * BLOCKS_PER_ATB * BYTES_PER_BLOCK - // => T = A * (1 + BLOCKS_PER_ATB / BLOCKS_PER_FTB + BLOCKS_PER_ATB * BYTES_PER_BLOCK) + size_t total_byte_len = (byte *)end - (byte *)start; + + // Calculate the denominator for the alloc table size calculation + size_t bits_per_block = MP_BITS_PER_BYTE / BLOCKS_PER_ATB; // Start with bits for ATB + #if MICROPY_ENABLE_FINALISER - area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) - * MP_BITS_PER_BYTE - / ( - MP_BITS_PER_BYTE - + MP_BITS_PER_BYTE * BLOCKS_PER_ATB / BLOCKS_PER_FTB - + MP_BITS_PER_BYTE * BLOCKS_PER_ATB * BYTES_PER_BLOCK - ); - #else - area->gc_alloc_table_byte_len = (total_byte_len - ALLOC_TABLE_GAP_BYTE) / (1 + MP_BITS_PER_BYTE / 2 * BYTES_PER_BLOCK); + bits_per_block += MP_BITS_PER_BYTE / BLOCKS_PER_FTB; // Add bits for FTB + #endif + + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bits_per_block += MP_BITS_PER_BYTE / BLOCKS_PER_CTB; // Add bits for CTB #endif + bits_per_block += MP_BITS_PER_BYTE * BYTES_PER_BLOCK; // Add bits for the block itself + + // Calculate the allocation table size + size_t available_bits = (total_byte_len - ALLOC_TABLE_GAP_BYTE) * MP_BITS_PER_BYTE; + size_t blocks = available_bits / bits_per_block; + area->gc_alloc_table_byte_len = blocks / BLOCKS_PER_ATB; + + // Set up all the table pointers area->gc_alloc_table_start = (byte *)start; + byte *next_table = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE; + // Total number of blocks in the pool + size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + + // Calculate table sizes and set start pointers #if MICROPY_ENABLE_FINALISER - size_t gc_finaliser_table_byte_len = (area->gc_alloc_table_byte_len * BLOCKS_PER_ATB + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; - area->gc_finaliser_table_start = area->gc_alloc_table_start + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE; + size_t gc_finaliser_table_byte_len = (gc_pool_block_len + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + area->gc_finaliser_table_start = next_table; + next_table += gc_finaliser_table_byte_len; #endif - size_t gc_pool_block_len = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; + #if MICROPY_ENABLE_SELECTIVE_COLLECT + size_t gc_collect_table_byte_len = (gc_pool_block_len + BLOCKS_PER_CTB - 1) / BLOCKS_PER_CTB; + area->gc_collect_table_start = next_table; + next_table += gc_collect_table_byte_len; + #endif + + // Set pool pointers area->gc_pool_start = (byte *)end - gc_pool_block_len * BYTES_PER_BLOCK; area->gc_pool_end = end; - #if MICROPY_ENABLE_FINALISER - assert(area->gc_pool_start >= area->gc_finaliser_table_start + gc_finaliser_table_byte_len); - #endif + // Verify enough space between last table and start of pool + assert(area->gc_pool_start >= next_table); - #if MICROPY_ENABLE_FINALISER - // clear ATB's and FTB's - memset(area->gc_alloc_table_start, 0, gc_finaliser_table_byte_len + area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); - #else - // clear ATB's - memset(area->gc_alloc_table_start, 0, area->gc_alloc_table_byte_len + ALLOC_TABLE_GAP_BYTE); - #endif + // Clear all tables + size_t tables_size = next_table - area->gc_alloc_table_start; + memset(area->gc_alloc_table_start, 0, tables_size); area->gc_last_free_atb_index = 0; area->gc_last_used_block = 0; @@ -204,6 +286,12 @@ STATIC void gc_setup_area(mp_state_mem_area_t *area, void *start, void *end) { gc_finaliser_table_byte_len, gc_finaliser_table_byte_len * BLOCKS_PER_FTB); #endif + #if MICROPY_ENABLE_SELECTIVE_COLLECT + DEBUG_printf(" collect table at %p, length " UINT_FMT " bytes, " + UINT_FMT " blocks\n", area->gc_collect_table_start, + gc_collect_table_byte_len, + gc_collect_table_byte_len * BLOCKS_PER_CTB); + #endif DEBUG_printf(" pool at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", area->gc_pool_start, gc_pool_block_len * BYTES_PER_BLOCK, gc_pool_block_len); @@ -233,9 +321,8 @@ void gc_init(void *start, void *end) { MP_STATE_MEM(gc_alloc_amount) = 0; #endif - #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL - mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex)); - #endif + GC_MUTEX_INIT(); + gc_perfetto_emit_heap_stats(); } #if MICROPY_GC_SPLIT_HEAP @@ -261,16 +348,46 @@ void gc_add(void *start, void *end) { } #if MICROPY_GC_SPLIT_HEAP_AUTO +// CIRCUITPY-CHANGE: Added function to compute heap size with selective collect table +static size_t compute_heap_size(size_t total_blocks) { + // Round up to the nearest multiple of BLOCKS_PER_ATB. Partial ATB blocks aren't supported and + // will result in a heap that is too small. + total_blocks = ((total_blocks + BLOCKS_PER_ATB - 1) / BLOCKS_PER_ATB) * BLOCKS_PER_ATB; + size_t atb_bytes = (total_blocks + BLOCKS_PER_ATB - 1) / BLOCKS_PER_ATB; + size_t ftb_bytes = 0; + size_t ctb_bytes = 0; + #if MICROPY_ENABLE_FINALISER + ftb_bytes = (total_blocks + BLOCKS_PER_FTB - 1) / BLOCKS_PER_FTB; + #endif + #if MICROPY_ENABLE_SELECTIVE_COLLECT + ctb_bytes = (total_blocks + BLOCKS_PER_CTB - 1) / BLOCKS_PER_CTB; + #endif + size_t pool_bytes = total_blocks * BYTES_PER_BLOCK; + + // Compute bytes needed to build a heap with total_blocks blocks. + size_t total_heap = + sizeof(mp_state_mem_area_t) + + atb_bytes + + ALLOC_TABLE_GAP_BYTE + + ftb_bytes + + ctb_bytes + + pool_bytes + + BYTES_PER_BLOCK; // Extra block of bytes to account for end pointer alignment + + // Round up size to the nearest multiple of BYTES_PER_BLOCK. + total_heap = (total_heap + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; + total_heap *= BYTES_PER_BLOCK; + return total_heap; +} + // Try to automatically add a heap area large enough to fulfill 'failed_alloc'. -STATIC bool gc_try_add_heap(size_t failed_alloc) { +static bool gc_try_add_heap(size_t failed_alloc) { // 'needed' is the size of a heap large enough to hold failed_alloc, with // the additional metadata overheads as calculated in gc_setup_area(). - // - // Rather than reproduce all of that logic here, we approximate that adding - // (13/512) is enough overhead for sufficiently large heap areas (the - // overhead converges to 3/128, but there's some fixed overhead and some - // rounding up of partial block sizes). - size_t needed = failed_alloc + MAX(2048, failed_alloc * 13 / 512); + // CIRCUITPY-CHANGE: calculation of how much to grow the heap + size_t total_new_blocks = (failed_alloc + BYTES_PER_BLOCK - 1) / BYTES_PER_BLOCK; + // CIRCUITPY-CHANGE + size_t needed = compute_heap_size(total_new_blocks); size_t avail = gc_get_max_new_split(); @@ -314,18 +431,8 @@ STATIC bool gc_try_add_heap(size_t failed_alloc) { total_blocks += area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; } - // Compute bytes needed to build a heap with total_blocks blocks. - size_t total_heap = - total_blocks / BLOCKS_PER_ATB - #if MICROPY_ENABLE_FINALISER - + total_blocks / BLOCKS_PER_FTB - #endif - + total_blocks * BYTES_PER_BLOCK - + ALLOC_TABLE_GAP_BYTE - + sizeof(mp_state_mem_area_t); - - // Round up size to the nearest multiple of BYTES_PER_BLOCK. - total_heap = (total_heap + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1)); + // CIRCUITPY-CHANGE + size_t total_heap = compute_heap_size(total_blocks); DEBUG_printf("total_heap " UINT_FMT " bytes\n", total_heap); @@ -352,11 +459,12 @@ STATIC bool gc_try_add_heap(size_t failed_alloc) { #endif -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: additional function void gc_deinit(void) { // Run any finalisers before we stop using the heap. This will also free // any additional heap areas (but not the first.) gc_sweep_all(); + gc_perfetto_emit_heap_stopped(); memset(&MP_STATE_MEM(area), 0, sizeof(MP_STATE_MEM(area))); } @@ -365,20 +473,20 @@ void gc_lock(void) { // - each thread has its own gc_lock_depth so there are no races between threads; // - a hard interrupt will only change gc_lock_depth during its execution, and // upon return will restore the value of gc_lock_depth. - MP_STATE_THREAD(gc_lock_depth)++; + MP_STATE_THREAD(gc_lock_depth) += (1 << GC_LOCK_DEPTH_SHIFT); } void gc_unlock(void) { // This does not need to be atomic, See comment above in gc_lock. - MP_STATE_THREAD(gc_lock_depth)--; + MP_STATE_THREAD(gc_lock_depth) -= (1 << GC_LOCK_DEPTH_SHIFT); } bool gc_is_locked(void) { return MP_STATE_THREAD(gc_lock_depth) != 0; } -// CIRCUITPY-CHANGE -bool gc_ptr_on_heap(void *ptr) { +// CIRCUITPY-CHANGE: additional function +bool gc_ptr_on_heap(const void *ptr) { for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { if (ptr >= (void *)area->gc_pool_start // must be above start of pool && ptr < (void *)area->gc_pool_end) { // must be below end of pool @@ -391,7 +499,7 @@ bool gc_ptr_on_heap(void *ptr) { #if MICROPY_GC_SPLIT_HEAP // Returns the area to which this pointer belongs, or NULL if it isn't // allocated on the GC-managed heap. -STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { +static inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { if (((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) != 0) { // must be aligned on a block return NULL; } @@ -420,15 +528,74 @@ STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) { #endif #endif +void gc_collect_start(void) { + gc_collect_start_common(); + #if MICROPY_GC_ALLOC_THRESHOLD + MP_STATE_MEM(gc_alloc_amount) = 0; + #endif + + // Trace root pointers. This relies on the root pointers being organised + // correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals, + // dict_globals, then the root pointer section of mp_state_vm. + void **ptrs = (void **)(void *)&mp_state_ctx; + size_t root_start = offsetof(mp_state_ctx_t, thread.dict_locals); + size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk); + gc_collect_root(ptrs + root_start / sizeof(void *), (root_end - root_start) / sizeof(void *)); + + #if MICROPY_ENABLE_PYSTACK + // Trace root pointers from the Python stack. + ptrs = (void **)(void *)MP_STATE_THREAD(pystack_start); + gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void *)); + #endif +} + +static void gc_collect_start_common(void) { + GC_ENTER(); + assert((MP_STATE_THREAD(gc_lock_depth) & GC_COLLECT_FLAG) == 0); + MP_STATE_THREAD(gc_lock_depth) |= GC_COLLECT_FLAG; + MP_STATE_MEM(gc_stack_overflow) = 0; +} + +void gc_collect_root(void **ptrs, size_t len) { + #if !MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = &MP_STATE_MEM(area); + #endif + for (size_t i = 0; i < len; i++) { + MICROPY_GC_HOOK_LOOP(i); + void *ptr = gc_get_ptr(ptrs, i); + #if MICROPY_GC_SPLIT_HEAP + mp_state_mem_area_t *area = gc_get_ptr_area(ptr); + if (!area) { + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + #endif + size_t block = BLOCK_FROM_PTR(area, ptr); + if (ATB_GET_KIND(area, block) == AT_HEAD) { + // An unmarked head: mark it, and mark all its children + ATB_HEAD_TO_MARK(area, block); + #if MICROPY_GC_SPLIT_HEAP + gc_mark_subtree(area, block); + #else + gc_mark_subtree(block); + #endif + } + } +} + // Take the given block as the topmost block on the stack. Check all it's // children: mark the unmarked child blocks and put those newly marked // blocks on the stack. When all children have been checked, pop off the // topmost block on the stack and repeat with that one. // CIRCUITPY-CHANGE: We don't instrument these functions because they occur a lot during GC and +// fill up the output buffer quickly. #if MICROPY_GC_SPLIT_HEAP -STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(mp_state_mem_area_t * area, size_t block) +static void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(mp_state_mem_area_t * area, size_t block) #else -STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) +static void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) #endif { // Start with the block passed in the argument. @@ -447,41 +614,52 @@ STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) // check that the consecutive blocks didn't overflow past the end of the area assert(area->gc_pool_start + (block + n_blocks) * BYTES_PER_BLOCK <= area->gc_pool_end); - // check this block's children - void **ptrs = (void **)PTR_FROM_BLOCK(area, block); - for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { - MICROPY_GC_HOOK_LOOP(i); - void *ptr = *ptrs; - // If this is a heap pointer that hasn't been marked, mark it and push - // it's children to the stack. - #if MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); - if (!ptr_area) { - // Not a heap-allocated pointer (might even be random data). - continue; - } - #else - if (!VERIFY_PTR(ptr)) { - continue; - } - mp_state_mem_area_t *ptr_area = area; - #endif - size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); - if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { - // This block is already marked. - continue; - } - // An unmarked head. Mark it, and push it on gc stack. - TRACE_MARK(ptr_block, ptr); - ATB_HEAD_TO_MARK(ptr_area, ptr_block); - if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { - MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; + // CIRCUITPY-CHANGE + // check if this block should be collected + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bool should_scan = CTB_GET(area, block); + #else + bool should_scan = true; + #endif + + // Only scan the block's children if it's not a leaf + if (should_scan) { + // check this block's children + void **ptrs = (void **)PTR_FROM_BLOCK(area, block); + for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) { + MICROPY_GC_HOOK_LOOP(i); + void *ptr = *ptrs; + // If this is a heap pointer that hasn't been marked, mark it and push + // it's children to the stack. #if MICROPY_GC_SPLIT_HEAP - MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; + mp_state_mem_area_t *ptr_area = gc_get_ptr_area(ptr); + if (!ptr_area) { + // Not a heap-allocated pointer (might even be random data). + continue; + } + #else + if (!VERIFY_PTR(ptr)) { + continue; + } + mp_state_mem_area_t *ptr_area = area; #endif - sp += 1; - } else { - MP_STATE_MEM(gc_stack_overflow) = 1; + size_t ptr_block = BLOCK_FROM_PTR(ptr_area, ptr); + if (ATB_GET_KIND(ptr_area, ptr_block) != AT_HEAD) { + // This block is already marked. + continue; + } + // An unmarked head. Mark it, and push it on gc stack. + TRACE_MARK(ptr_block, ptr); + ATB_HEAD_TO_MARK(ptr_area, ptr_block); + if (sp < MICROPY_ALLOC_GC_STACK_SIZE) { + MP_STATE_MEM(gc_block_stack)[sp] = ptr_block; + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_area_stack)[sp] = ptr_area; + #endif + sp += 1; + } else { + MP_STATE_MEM(gc_stack_overflow) = 1; + } } } @@ -499,7 +677,27 @@ STATIC void MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_mark_subtree)(size_t block) } } -STATIC void gc_deal_with_stack_overflow(void) { +void gc_sweep_all(void) { + gc_collect_start_common(); + gc_collect_end(); +} + +void gc_collect_end(void) { + gc_deal_with_stack_overflow(); + gc_sweep_run_finalisers(); + gc_sweep_free_blocks(); + #if MICROPY_GC_SPLIT_HEAP + MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); + #endif + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + area->gc_last_free_atb_index = 0; + } + MP_STATE_THREAD(gc_lock_depth) &= ~GC_COLLECT_FLAG; + GC_EXIT(); + gc_perfetto_emit_heap_stats(); +} + +static void gc_deal_with_stack_overflow(void) { while (MP_STATE_MEM(gc_stack_overflow)) { MP_STATE_MEM(gc_stack_overflow) = 0; @@ -520,29 +718,20 @@ STATIC void gc_deal_with_stack_overflow(void) { } } -STATIC void gc_sweep(void) { - #if MICROPY_PY_GC_COLLECT_RETVAL - MP_STATE_MEM(gc_collected) = 0; - #endif - // free unmarked heads and their tails - int free_tail = 0; - #if MICROPY_GC_SPLIT_HEAP_AUTO - mp_state_mem_area_t *prev_area = NULL; - #endif - for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { - size_t end_block = area->gc_alloc_table_byte_len * BLOCKS_PER_ATB; - if (area->gc_last_used_block < end_block) { - end_block = area->gc_last_used_block + 1; - } - - size_t last_used_block = 0; - - for (size_t block = 0; block < end_block; block++) { - MICROPY_GC_HOOK_LOOP(block); - switch (ATB_GET_KIND(area, block)) { - case AT_HEAD: - #if MICROPY_ENABLE_FINALISER - if (FTB_GET(area, block)) { +// Run finalisers for all to-be-freed blocks +static void gc_sweep_run_finalisers(void) { + #if MICROPY_ENABLE_FINALISER + for (const mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + assert(area->gc_last_used_block <= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB); + // Small speed optimisation: skip over empty FTB blocks + size_t ftb_end = area->gc_last_used_block / BLOCKS_PER_FTB; // index is inclusive + for (size_t ftb_idx = 0; ftb_idx <= ftb_end; ftb_idx++) { + byte ftb = area->gc_finaliser_table_start[ftb_idx]; + size_t block = ftb_idx * BLOCKS_PER_FTB; + while (ftb) { + MICROPY_GC_HOOK_LOOP(block); + if (ftb & 1) { // FTB_GET(area, block) shortcut + if (ATB_GET_KIND(area, block) == AT_HEAD) { mp_obj_base_t *obj = (mp_obj_base_t *)PTR_FROM_BLOCK(area, block); if (obj->type != NULL) { // if the object has a type then see if it has a __del__ method @@ -562,9 +751,35 @@ STATIC void gc_sweep(void) { // clear finaliser flag FTB_CLEAR(area, block); } - #endif + } + ftb >>= 1; + block++; + } + } + } + #endif // MICROPY_ENABLE_FINALISER +} + +// Free unmarked heads and their tails +static void gc_sweep_free_blocks(void) { + #if MICROPY_PY_GC_COLLECT_RETVAL + MP_STATE_MEM(gc_collected) = 0; + #endif + int free_tail = 0; + #if MICROPY_GC_SPLIT_HEAP_AUTO + mp_state_mem_area_t *prev_area = NULL; + #endif + + for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { + size_t last_used_block = 0; + assert(area->gc_last_used_block <= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB); + + for (size_t block = 0; block <= area->gc_last_used_block; block++) { + MICROPY_GC_HOOK_LOOP(block); + switch (ATB_GET_KIND(area, block)) { + case AT_HEAD: free_tail = 1; - DEBUG_printf("gc_sweep(%p)\n", (void *)PTR_FROM_BLOCK(area, block)); + DEBUG_printf("gc_sweep_free_blocks(%p)\n", (void *)PTR_FROM_BLOCK(area, block)); #if MICROPY_PY_GC_COLLECT_RETVAL MP_STATE_MEM(gc_collected)++; #endif @@ -595,7 +810,7 @@ STATIC void gc_sweep(void) { #if MICROPY_GC_SPLIT_HEAP_AUTO // Free any empty area, aside from the first one if (last_used_block == 0 && prev_area != NULL) { - DEBUG_printf("gc_sweep free empty area %p\n", area); + DEBUG_printf("gc_sweep_free_blocks free empty area %p\n", area); NEXT_AREA(prev_area) = NEXT_AREA(area); MP_PLAT_FREE_HEAP(area); area = prev_area; @@ -605,30 +820,7 @@ STATIC void gc_sweep(void) { } } -void gc_collect_start(void) { - GC_ENTER(); - MP_STATE_THREAD(gc_lock_depth)++; - #if MICROPY_GC_ALLOC_THRESHOLD - MP_STATE_MEM(gc_alloc_amount) = 0; - #endif - MP_STATE_MEM(gc_stack_overflow) = 0; - - // Trace root pointers. This relies on the root pointers being organised - // correctly in the mp_state_ctx structure. We scan nlr_top, dict_locals, - // dict_globals, then the root pointer section of mp_state_vm. - void **ptrs = (void **)(void *)&mp_state_ctx; - size_t root_start = offsetof(mp_state_ctx_t, thread.dict_locals); - size_t root_end = offsetof(mp_state_ctx_t, vm.qstr_last_chunk); - gc_collect_root(ptrs + root_start / sizeof(void *), (root_end - root_start) / sizeof(void *)); - - #if MICROPY_ENABLE_PYSTACK - // Trace root pointers from the Python stack. - ptrs = (void **)(void *)MP_STATE_THREAD(pystack_start); - gc_collect_root(ptrs, (MP_STATE_THREAD(pystack_cur) - MP_STATE_THREAD(pystack_start)) / sizeof(void *)); - #endif -} - -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add function void gc_collect_ptr(void *ptr) { void *ptrs[1] = { ptr }; gc_collect_root(ptrs, 1); @@ -650,56 +842,6 @@ static void *MP_NO_INSTRUMENT PLACE_IN_ITCM(gc_get_ptr)(void **ptrs, int i) { return ptrs[i]; } -void gc_collect_root(void **ptrs, size_t len) { - #if !MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *area = &MP_STATE_MEM(area); - #endif - for (size_t i = 0; i < len; i++) { - MICROPY_GC_HOOK_LOOP(i); - void *ptr = gc_get_ptr(ptrs, i); - #if MICROPY_GC_SPLIT_HEAP - mp_state_mem_area_t *area = gc_get_ptr_area(ptr); - if (!area) { - continue; - } - #else - if (!VERIFY_PTR(ptr)) { - continue; - } - #endif - size_t block = BLOCK_FROM_PTR(area, ptr); - if (ATB_GET_KIND(area, block) == AT_HEAD) { - // An unmarked head: mark it, and mark all its children - ATB_HEAD_TO_MARK(area, block); - #if MICROPY_GC_SPLIT_HEAP - gc_mark_subtree(area, block); - #else - gc_mark_subtree(block); - #endif - } - } -} - -void gc_collect_end(void) { - gc_deal_with_stack_overflow(); - gc_sweep(); - #if MICROPY_GC_SPLIT_HEAP - MP_STATE_MEM(gc_last_free_area) = &MP_STATE_MEM(area); - #endif - for (mp_state_mem_area_t *area = &MP_STATE_MEM(area); area != NULL; area = NEXT_AREA(area)) { - area->gc_last_free_atb_index = 0; - } - MP_STATE_THREAD(gc_lock_depth)--; - GC_EXIT(); -} - -void gc_sweep_all(void) { - GC_ENTER(); - MP_STATE_THREAD(gc_lock_depth)++; - MP_STATE_MEM(gc_stack_overflow) = 0; - gc_collect_end(); -} - void gc_info(gc_info_t *info) { GC_ENTER(); info->total = 0; @@ -773,13 +915,11 @@ void gc_info(gc_info_t *info) { GC_EXIT(); } -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: New function. +// C code may be used when the VM heap isn't active. This function +// allows that code to test if it is. It can use the outer pool if needed. bool gc_alloc_possible(void) { - #if MICROPY_GC_SPLIT_HEAP - return MP_STATE_MEM(gc_last_free_area) != 0; - #else return MP_STATE_MEM(area).gc_pool_start != 0; - #endif } void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { @@ -947,6 +1087,20 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { (void)has_finaliser; #endif + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + bool do_not_collect = (alloc_flags & GC_ALLOC_FLAG_DO_NOT_COLLECT) != 0; + GC_ENTER(); + if (do_not_collect) { + // Mark as not to be collected + CTB_CLEAR(area, start_block); + } else { + // By default, all blocks should be collected + CTB_SET(area, start_block); + } + GC_EXIT(); + #endif + #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(&mp_plat_print); #endif @@ -956,26 +1110,21 @@ void *gc_alloc(size_t n_bytes, unsigned int alloc_flags) { memorymonitor_track_allocation(end_block - start_block + 1); #endif - return ret_ptr; -} - -/* -void *gc_alloc(mp_uint_t n_bytes) { - return _gc_alloc(n_bytes, false); -} + gc_perfetto_emit_heap_stats(); -void *gc_alloc_with_finaliser(mp_uint_t n_bytes) { - return _gc_alloc(n_bytes, true); + return ret_ptr; } -*/ // force the freeing of a piece of memory // TODO: freeing here does not call finaliser void gc_free(void *ptr) { - if (MP_STATE_THREAD(gc_lock_depth) > 0) { - // Cannot free while the GC is locked. However free is an optimisation - // to reclaim the memory immediately, this means it will now be left - // until the next collection. + // Cannot free while the GC is locked, unless we're only doing a gc sweep. + // However free is an optimisation to reclaim the memory immediately, this + // means it will now be left until the next collection. + // + // (We have the optimisation to free immediately from inside a gc sweep so + // that finalisers can free more memory when trying to avoid MemoryError.) + if (MP_STATE_THREAD(gc_lock_depth) & ~GC_COLLECT_FLAG) { return; } @@ -993,6 +1142,7 @@ void gc_free(void *ptr) { mp_state_mem_area_t *area; #if MICROPY_GC_SPLIT_HEAP area = gc_get_ptr_area(ptr); + // CIRCUITPY-CHANGE: don't just assert. // assert(area); #else // CIRCUITPY-CHANGE: extra checking @@ -1004,7 +1154,8 @@ void gc_free(void *ptr) { #endif size_t block = BLOCK_FROM_PTR(area, ptr); - assert(ATB_GET_KIND(area, block) == AT_HEAD); + assert(ATB_GET_KIND(area, block) == AT_HEAD + || (ATB_GET_KIND(area, block) == AT_MARK && (MP_STATE_THREAD(gc_lock_depth) & GC_COLLECT_FLAG))); #if MICROPY_ENABLE_FINALISER FTB_CLEAR(area, block); @@ -1042,6 +1193,7 @@ void gc_free(void *ptr) { } while (ATB_GET_KIND(area, block) == AT_TAIL); GC_EXIT(); + gc_perfetto_emit_heap_stats(); #if EXTENSIVE_HEAP_PROFILING gc_dump_alloc_table(&mp_plat_print); @@ -1080,39 +1232,11 @@ size_t gc_nbytes(const void *ptr) { return 0; } -#if 0 -// old, simple realloc that didn't expand memory in place -void *gc_realloc(void *ptr, mp_uint_t n_bytes) { - mp_uint_t n_existing = gc_nbytes(ptr); - if (n_bytes <= n_existing) { - return ptr; - } else { - bool has_finaliser; - if (ptr == NULL) { - has_finaliser = false; - } else { - #if MICROPY_ENABLE_FINALISER - has_finaliser = FTB_GET(BLOCK_FROM_PTR((mp_uint_t)ptr)); - #else - has_finaliser = false; - #endif - } - void *ptr2 = gc_alloc(n_bytes, has_finaliser); - if (ptr2 == NULL) { - return ptr2; - } - memcpy(ptr2, ptr, n_existing); - gc_free(ptr); - return ptr2; - } -} - -#else // Alternative gc_realloc impl - void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { // check for pure allocation if (ptr_in == NULL) { - return gc_alloc(n_bytes, false); + // CIRCUITPY-CHANGE + return gc_alloc(n_bytes, 0); } // check for pure free @@ -1210,6 +1334,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { memorymonitor_track_allocation(new_blocks); #endif + gc_perfetto_emit_heap_stats(); + return ptr_in; } @@ -1247,13 +1373,24 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { memorymonitor_track_allocation(new_blocks); #endif + gc_perfetto_emit_heap_stats(); + return ptr_in; } + uint8_t alloc_flags = 0; #if MICROPY_ENABLE_FINALISER - bool ftb_state = FTB_GET(area, block); - #else - bool ftb_state = false; + // CIRCUITPY-CHANGE for selective collect + if (FTB_GET(area, block)) { + alloc_flags |= GC_ALLOC_FLAG_HAS_FINALISER; + } + #endif + + // CIRCUITPY-CHANGE for selective collect + #if MICROPY_ENABLE_SELECTIVE_COLLECT + if (!CTB_GET(area, block)) { + alloc_flags |= GC_ALLOC_FLAG_DO_NOT_COLLECT; + } #endif GC_EXIT(); @@ -1264,7 +1401,8 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { } // can't resize inplace; try to find a new contiguous chain - void *ptr_out = gc_alloc(n_bytes, ftb_state); + // CIRCUITPY-CHANGE + void *ptr_out = gc_alloc(n_bytes, alloc_flags); // check that the alloc succeeded if (ptr_out == NULL) { @@ -1276,7 +1414,6 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) { gc_free(ptr_in); return ptr_out; } -#endif // Alternative gc_realloc impl void gc_dump_info(const mp_print_t *print) { gc_info_t info; @@ -1310,7 +1447,7 @@ void gc_dump_alloc_table(const mp_print_t *print) { } if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) { // there are at least 2 lines containing only free blocks, so abbreviate their printing - mp_printf(print, "\n (%u lines all free)", (uint)(bl2 - bl) / DUMP_BYTES_PER_LINE); + mp_printf(print, "\n (%u lines all free)", (uint)((bl2 - bl) / DUMP_BYTES_PER_LINE)); bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1)); if (bl >= area->gc_alloc_table_byte_len * BLOCKS_PER_ATB) { // got to end of heap @@ -1353,7 +1490,7 @@ void gc_dump_alloc_table(const mp_print_t *print) { break; } */ - /* this prints the uPy object type of the head block */ + /* this prints the MicroPython object type of the head block */ case AT_HEAD: { // CIRCUITPY-CHANGE: compiler warning avoidance #pragma GCC diagnostic push @@ -1424,41 +1561,4 @@ void gc_dump_alloc_table(const mp_print_t *print) { GC_EXIT(); } -#if 0 -// For testing the GC functions -void gc_test(void) { - mp_uint_t len = 500; - mp_uint_t *heap = malloc(len); - gc_init(heap, heap + len / sizeof(mp_uint_t)); - void *ptrs[100]; - { - mp_uint_t **p = gc_alloc(16, false); - p[0] = gc_alloc(64, false); - p[1] = gc_alloc(1, false); - p[2] = gc_alloc(1, false); - p[3] = gc_alloc(1, false); - mp_uint_t ***p2 = gc_alloc(16, false); - p2[0] = p; - p2[1] = p; - ptrs[0] = p2; - } - for (int i = 0; i < 25; i += 2) { - mp_uint_t *p = gc_alloc(i, false); - printf("p=%p\n", p); - if (i & 3) { - // ptrs[i] = p; - } - } - - printf("Before GC:\n"); - gc_dump_alloc_table(&mp_plat_print); - printf("Starting GC...\n"); - gc_collect_start(); - gc_collect_root(ptrs, sizeof(ptrs) / sizeof(void *)); - gc_collect_end(); - printf("After GC:\n"); - gc_dump_alloc_table(&mp_plat_print); -} -#endif - #endif // MICROPY_ENABLE_GC diff --git a/py/gc.h b/py/gc.h index 5f4b18f7e64bb..f9028d637c5c6 100644 --- a/py/gc.h +++ b/py/gc.h @@ -71,8 +71,17 @@ bool gc_alloc_possible(void); // Use this function to sweep the whole heap and run all finalisers void gc_sweep_all(void); +// These functions are used to manage weakrefs. +void gc_weakref_mark(void *ptr); +void gc_weakref_about_to_be_freed(void *ptr); +void gc_weakref_sweep(void); + enum { GC_ALLOC_FLAG_HAS_FINALISER = 1, + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + GC_ALLOC_FLAG_DO_NOT_COLLECT = 2, + #endif }; void *gc_alloc(size_t n_bytes, unsigned int alloc_flags); @@ -83,7 +92,7 @@ void *gc_realloc(void *ptr, size_t n_bytes, bool allow_move); // CIRCUITPY-CHANGE // True if the pointer is on the MP heap. Doesn't require that it is the start // of a block. -bool gc_ptr_on_heap(void *ptr); +bool gc_ptr_on_heap(const void *ptr); typedef struct _gc_info_t { size_t total; diff --git a/py/lexer.c b/py/lexer.c index 5e911a1a23337..98a10c87b2e5a 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -42,74 +42,74 @@ #define MP_LEXER_EOF ((unichar)MP_READER_EOF) #define CUR_CHAR(lex) ((lex)->chr0) -STATIC bool is_end(mp_lexer_t *lex) { +static bool is_end(mp_lexer_t *lex) { return lex->chr0 == MP_LEXER_EOF; } -STATIC bool is_physical_newline(mp_lexer_t *lex) { +static bool is_physical_newline(mp_lexer_t *lex) { return lex->chr0 == '\n'; } -STATIC bool is_char(mp_lexer_t *lex, byte c) { +static bool is_char(mp_lexer_t *lex, byte c) { return lex->chr0 == c; } -STATIC bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) { +static bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr0 == c1 || lex->chr0 == c2; } -STATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) { +static bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) { return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3; } #if MICROPY_PY_FSTRINGS -STATIC bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) { +static bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) { return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3 || lex->chr0 == c4; } #endif -STATIC bool is_char_following(mp_lexer_t *lex, byte c) { +static bool is_char_following(mp_lexer_t *lex, byte c) { return lex->chr1 == c; } -STATIC bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) { +static bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr1 == c1 || lex->chr1 == c2; } -STATIC bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) { +static bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr2 == c1 || lex->chr2 == c2; } -STATIC bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) { +static bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) { return lex->chr0 == c1 && lex->chr1 == c2; } -STATIC bool is_whitespace(mp_lexer_t *lex) { +static bool is_whitespace(mp_lexer_t *lex) { return unichar_isspace(lex->chr0); } -STATIC bool is_letter(mp_lexer_t *lex) { +static bool is_letter(mp_lexer_t *lex) { return unichar_isalpha(lex->chr0); } -STATIC bool is_digit(mp_lexer_t *lex) { +static bool is_digit(mp_lexer_t *lex) { return unichar_isdigit(lex->chr0); } -STATIC bool is_following_digit(mp_lexer_t *lex) { +static bool is_following_digit(mp_lexer_t *lex) { return unichar_isdigit(lex->chr1); } -STATIC bool is_following_base_char(mp_lexer_t *lex) { +static bool is_following_base_char(mp_lexer_t *lex) { const unichar chr1 = lex->chr1 | 0x20; return chr1 == 'b' || chr1 == 'o' || chr1 == 'x'; } -STATIC bool is_following_odigit(mp_lexer_t *lex) { +static bool is_following_odigit(mp_lexer_t *lex) { return lex->chr1 >= '0' && lex->chr1 <= '7'; } -STATIC bool is_string_or_bytes(mp_lexer_t *lex) { +static bool is_string_or_bytes(mp_lexer_t *lex) { return is_char_or(lex, '\'', '\"') #if MICROPY_PY_FSTRINGS || (is_char_or4(lex, 'r', 'u', 'b', 'f') && is_char_following_or(lex, '\'', '\"')) @@ -123,15 +123,15 @@ STATIC bool is_string_or_bytes(mp_lexer_t *lex) { } // to easily parse utf-8 identifiers we allow any raw byte with high bit set -STATIC bool is_head_of_identifier(mp_lexer_t *lex) { +static bool is_head_of_identifier(mp_lexer_t *lex) { return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80; } -STATIC bool is_tail_of_identifier(mp_lexer_t *lex) { +static bool is_tail_of_identifier(mp_lexer_t *lex) { return is_head_of_identifier(lex) || is_digit(lex); } -STATIC void next_char(mp_lexer_t *lex) { +static void next_char(mp_lexer_t *lex) { if (lex->chr0 == '\n') { // a new line ++lex->line; @@ -189,7 +189,7 @@ STATIC void next_char(mp_lexer_t *lex) { } } -STATIC void indent_push(mp_lexer_t *lex, size_t indent) { +static void indent_push(mp_lexer_t *lex, size_t indent) { if (lex->num_indent_level >= lex->alloc_indent_level) { lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC); lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC; @@ -197,11 +197,11 @@ STATIC void indent_push(mp_lexer_t *lex, size_t indent) { lex->indent_level[lex->num_indent_level++] = indent; } -STATIC size_t indent_top(mp_lexer_t *lex) { +static size_t indent_top(mp_lexer_t *lex) { return lex->indent_level[lex->num_indent_level - 1]; } -STATIC void indent_pop(mp_lexer_t *lex) { +static void indent_pop(mp_lexer_t *lex) { lex->num_indent_level -= 1; } @@ -211,7 +211,7 @@ STATIC void indent_pop(mp_lexer_t *lex) { // c = continue with , if this opchar matches then continue matching // this means if the start of two ops are the same then they are equal til the last char -STATIC const char *const tok_enc = +static const char *const tok_enc = "()[]{},;~" // singles ":e=" // : := "0 means we're extracting the args. // only when fstring_args_idx>0 will we consume the arg data - // note: lex->fstring_args will be empty already (it's reset when finished) - vstr_add_str(&lex->fstring_args, ".format("); + // lex->fstring_args is reset when finished, so at this point there are two cases: + // - lex->fstring_args is empty: start of a new f-string + // - lex->fstring_args is non-empty: concatenation of adjacent f-strings + if (vstr_len(&lex->fstring_args) == 0) { + vstr_add_str(&lex->fstring_args, ".format("); + } } #endif @@ -529,7 +532,7 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) // This function returns whether it has crossed a newline or not. // It therefore always return true if stop_at_newline is true -STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) { +static bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) { while (!is_end(lex)) { if (is_physical_newline(lex)) { if (stop_at_newline && lex->nested_bracket_level == 0) { @@ -657,21 +660,19 @@ void mp_lexer_to_next(mp_lexer_t *lex) { } #if MICROPY_PY_FSTRINGS if (is_char_following(lex, 'f')) { - // raw-f-strings unsupported, immediately return (invalid) token. - lex->tok_kind = MP_TOKEN_FSTRING_RAW; - break; + is_fstring = true; + n_char = 2; } #endif } #if MICROPY_PY_FSTRINGS else if (is_char(lex, 'f')) { + is_fstring = true; + n_char = 1; if (is_char_following(lex, 'r')) { - // raw-f-strings unsupported, immediately return (invalid) token. - lex->tok_kind = MP_TOKEN_FSTRING_RAW; - break; + is_raw = true; + n_char = 2; } - n_char = 1; - is_fstring = true; } #endif @@ -772,6 +773,9 @@ void mp_lexer_to_next(mp_lexer_t *lex) { } else { // search for encoded delimiter or operator + // assert that the token enum value fits in a byte, so they all fit in tok_enc_kind + MP_STATIC_ASSERT(MP_TOKEN_NUMBER_OF <= 256); + const char *t = tok_enc; size_t tok_enc_index = 0; for (; *t != 0 && !is_char(lex, *t); t += 1) { diff --git a/py/lexer.h b/py/lexer.h index 2d9d0447b8ba3..6e6c3e8f23e06 100644 --- a/py/lexer.h +++ b/py/lexer.h @@ -46,7 +46,6 @@ typedef enum _mp_token_kind_t { MP_TOKEN_LONELY_STRING_OPEN, #if MICROPY_PY_FSTRINGS MP_TOKEN_MALFORMED_FSTRING, - MP_TOKEN_FSTRING_RAW, #endif MP_TOKEN_NEWLINE, @@ -153,6 +152,8 @@ typedef enum _mp_token_kind_t { MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_DEL_EQUAL, MP_TOKEN_DEL_MINUS_MORE, + + MP_TOKEN_NUMBER_OF, } mp_token_kind_t; // this data structure is exposed for efficiency diff --git a/py/make_root_pointers.py b/py/make_root_pointers.py index efe398b8227ca..5da343c1270ec 100644 --- a/py/make_root_pointers.py +++ b/py/make_root_pointers.py @@ -6,8 +6,6 @@ "struct _mp_state_vm_t" in py/mpstate.h """ -from __future__ import print_function - import argparse import io import re diff --git a/py/makecompresseddata.py b/py/makecompresseddata.py index 1bce3e8e8374a..a6fa7db00b280 100644 --- a/py/makecompresseddata.py +++ b/py/makecompresseddata.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import collections import re import sys diff --git a/py/makemoduledefs.py b/py/makemoduledefs.py index 29162ab387c8b..c8fdc21f6fbe2 100644 --- a/py/makemoduledefs.py +++ b/py/makemoduledefs.py @@ -14,8 +14,6 @@ the built-in version. """ -from __future__ import print_function - import sys import re import io @@ -87,19 +85,25 @@ def generate_module_table_header(modules): ) ) + # There should always be at least one module (__main__ in runtime.c) + assert mod_defs + print("\n#define MICROPY_REGISTERED_MODULES \\") for mod_def in sorted(mod_defs): print(" {mod_def} \\".format(mod_def=mod_def)) - print("// MICROPY_REGISTERED_MODULES") - print("\n#define MICROPY_REGISTERED_EXTENSIBLE_MODULES \\") + # There are not necessarily any extensible modules (e.g., bare-arm or minimal x86) + print("\n#define MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES ", len(extensible_mod_defs)) - for mod_def in sorted(extensible_mod_defs): - print(" {mod_def} \\".format(mod_def=mod_def)) + if extensible_mod_defs: + print("\n#define MICROPY_REGISTERED_EXTENSIBLE_MODULES \\") + + for mod_def in sorted(extensible_mod_defs): + print(" {mod_def} \\".format(mod_def=mod_def)) - print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES") + print("// MICROPY_REGISTERED_EXTENSIBLE_MODULES") def generate_module_delegations(delegations): diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 9e84330a347c2..3fdb2d5476b8a 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -1,36 +1,54 @@ """ Process raw qstr file and output qstr data with length, hash and data bytes. -This script works with Python 2.7, 3.3 and 3.4. - -CIRCUITPY-CHANGE: -For documentation about the format of compressed translated strings, see -supervisor/shared/translate/translate.h +This script works with Python 3.3+. """ -from __future__ import print_function - - import re import sys -# CIRCUITPY-CHANGE -if hasattr(sys.stdout, "reconfigure"): - sys.stdout.reconfigure(encoding="utf-8") - sys.stderr.reconfigure(errors="backslashreplace") - -# Python 2/3 compatibility: -# - iterating through bytes is different -# - codepoint2name lives in a different module -import platform - -if platform.python_version_tuple()[0] == "2": - bytes_cons = lambda val, enc=None: bytearray(val) - from htmlentitydefs import codepoint2name -elif platform.python_version_tuple()[0] == "3": - bytes_cons = bytes - from html.entities import codepoint2name -# end compatibility code +bytes_cons = bytes + +# fmt: off +codepoint2name = { + 198: "AElig", 193: "Aacute", 194: "Acirc", 192: "Agrave", 913: "Alpha", 197: "Aring", 195: "Atilde", + 196: "Auml", 914: "Beta", 199: "Ccedil", 935: "Chi", 8225: "Dagger", 916: "Delta", 208: "ETH", + 201: "Eacute", 202: "Ecirc", 200: "Egrave", 917: "Epsilon", 919: "Eta", 203: "Euml", 915: "Gamma", + 205: "Iacute", 206: "Icirc", 204: "Igrave", 921: "Iota", 207: "Iuml", 922: "Kappa", 923: "Lambda", + 924: "Mu", 209: "Ntilde", 925: "Nu", 338: "OElig", 211: "Oacute", 212: "Ocirc", 210: "Ograve", + 937: "Omega", 927: "Omicron", 216: "Oslash", 213: "Otilde", 214: "Ouml", 934: "Phi", 928: "Pi", + 8243: "Prime", 936: "Psi", 929: "Rho", 352: "Scaron", 931: "Sigma", 222: "THORN", 932: "Tau", + 920: "Theta", 218: "Uacute", 219: "Ucirc", 217: "Ugrave", 933: "Upsilon", 220: "Uuml", 926: "Xi", + 221: "Yacute", 376: "Yuml", 918: "Zeta", 225: "aacute", 226: "acirc", 180: "acute", 230: "aelig", + 224: "agrave", 8501: "alefsym", 945: "alpha", 38: "amp", 8743: "and", 8736: "ang", 229: "aring", + 8776: "asymp", 227: "atilde", 228: "auml", 8222: "bdquo", 946: "beta", 166: "brvbar", 8226: "bull", + 8745: "cap", 231: "ccedil", 184: "cedil", 162: "cent", 967: "chi", 710: "circ", 9827: "clubs", + 8773: "cong", 169: "copy", 8629: "crarr", 8746: "cup", 164: "curren", 8659: "dArr", 8224: "dagger", + 8595: "darr", 176: "deg", 948: "delta", 9830: "diams", 247: "divide", 233: "eacute", 234: "ecirc", + 232: "egrave", 8709: "empty", 8195: "emsp", 8194: "ensp", 949: "epsilon", 8801: "equiv", 951: "eta", + 240: "eth", 235: "euml", 8364: "euro", 8707: "exist", 402: "fnof", 8704: "forall", 189: "frac12", + 188: "frac14", 190: "frac34", 8260: "frasl", 947: "gamma", 8805: "ge", 62: "gt", 8660: "hArr", + 8596: "harr", 9829: "hearts", 8230: "hellip", 237: "iacute", 238: "icirc", 161: "iexcl", 236: "igrave", + 8465: "image", 8734: "infin", 8747: "int", 953: "iota", 191: "iquest", 8712: "isin", 239: "iuml", + 954: "kappa", 8656: "lArr", 955: "lambda", 9001: "lang", 171: "laquo", 8592: "larr", 8968: "lceil", + 8220: "ldquo", 8804: "le", 8970: "lfloor", 8727: "lowast", 9674: "loz", 8206: "lrm", 8249: "lsaquo", + 8216: "lsquo", 60: "lt", 175: "macr", 8212: "mdash", 181: "micro", 183: "middot", 8722: "minus", + 956: "mu", 8711: "nabla", 160: "nbsp", 8211: "ndash", 8800: "ne", 8715: "ni", 172: "not", 8713: "notin", # codespell:ignore notin + 8836: "nsub", 241: "ntilde", 957: "nu", 243: "oacute", 244: "ocirc", 339: "oelig", 242: "ograve", + 8254: "oline", 969: "omega", 959: "omicron", 8853: "oplus", 8744: "or", 170: "ordf", 186: "ordm", + 248: "oslash", 245: "otilde", 8855: "otimes", 246: "ouml", 182: "para", 8706: "part", 8240: "permil", + 8869: "perp", 966: "phi", 960: "pi", 982: "piv", 177: "plusmn", 163: "pound", 8242: "prime", + 8719: "prod", 8733: "prop", 968: "psi", 34: "quot", 8658: "rArr", 8730: "radic", 9002: "rang", + 187: "raquo", 8594: "rarr", 8969: "rceil", 8221: "rdquo", 8476: "real", 174: "reg", 8971: "rfloor", + 961: "rho", 8207: "rlm", 8250: "rsaquo", 8217: "rsquo", 8218: "sbquo", 353: "scaron", 8901: "sdot", + 167: "sect", 173: "shy", 963: "sigma", 962: "sigmaf", 8764: "sim", 9824: "spades", 8834: "sub", + 8838: "sube", 8721: "sum", 8835: "sup", 185: "sup1", 178: "sup2", 179: "sup3", 8839: "supe", + 223: "szlig", 964: "tau", 8756: "there4", 952: "theta", 977: "thetasym", 8201: "thinsp", 254: "thorn", + 732: "tilde", 215: "times", 8482: "trade", 8657: "uArr", 250: "uacute", 8593: "uarr", 251: "ucirc", + 249: "ugrave", 168: "uml", 978: "upsih", 965: "upsilon", 252: "uuml", 8472: "weierp", 958: "xi", + 253: "yacute", 165: "yen", 255: "yuml", 950: "zeta", 8205: "zwj", 8204: "zwnj" +} +# fmt: on codepoint2name[ord("-")] = "hyphen" @@ -233,11 +251,11 @@ "zip", ] -# Additional QSTRs that must have index <255 because they are stored in -# `mp_binary_op_method_name` and `mp_unary_op_method_name` (see py/objtype.c). +# Additional QSTRs that must have index <255 because they are stored as `byte` values. # These are not part of the .mpy compatibility list, but we place them in the # fixed unsorted pool (i.e. QDEF0) to ensure their indices are small. -operator_qstr_list = { +unsorted_qstr_list = { + # From py/objtype.c: used in the `mp_binary_op_method_name` and `mp_unary_op_method_name` tables. "__bool__", "__pos__", "__neg__", @@ -296,8 +314,18 @@ "__get__", "__set__", "__delete__", + # From py/scope.c: used in `scope_simple_name_table` table. + # Note: "" is already in `static_qstr_list`. + "", + "", + "", + "", + "", } +# Matches any string that needs no escaping (alphanum + _ only) +RE_NO_ESCAPE = re.compile(r"^[a-zA-Z0-9_]$") + # this must match the equivalent function in qstr.c def compute_hash(qstr, bytes_hash): @@ -305,19 +333,22 @@ def compute_hash(qstr, bytes_hash): for b in qstr: hash = (hash * 33) ^ b # Make sure that valid hash is never zero, zero means "hash not computed" - return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1 + # if bytes_hash is zero, assume a 16-bit mask (to match qstr.c) + return (hash & ((1 << (8 * (bytes_hash or 2))) - 1)) or 1 def qstr_escape(qst): - def esc_char(m): - c = ord(m.group(0)) + def esc_char(c): + if RE_NO_ESCAPE.match(c): + return c + c = ord(c) try: name = codepoint2name[c] except KeyError: name = "0x%02x" % c return "_" + name + "_" - return re.sub(r"[^A-Za-z0-9_]", esc_char, qst) + return "".join(map(esc_char, qst)) static_qstr_list_ident = list(map(qstr_escape, static_qstr_list)) @@ -378,8 +409,11 @@ def parse_input_headers_with_translations(infiles): qstrs[ident] = (ident, qstr) if not qcfgs: - sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n") - sys.exit(1) + # CIRCUITPY-CHANGE: These values are hardcoded for CircuitPython so + # don't error if they are missing. + qcfgs = {} + qcfgs["BYTES_IN_LEN"] = 1 + qcfgs["BYTES_IN_HASH"] = 1 # CIRCUITPY-CHANGE return qcfgs, qstrs, translations @@ -433,10 +467,10 @@ def print_qstr_data(qcfgs, qstrs, translations): total_qstr_size = 0 # add remaining qstrs to the sorted (by value) pool (unless they're in - # operator_qstr_list, in which case add them to the unsorted pool) + # unsorted_qstr_list, in which case add them to the unsorted pool) for ident, qstr in sorted(qstrs.values(), key=lambda x: x[1]): qbytes = make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr) - pool = 0 if qstr in operator_qstr_list else 1 + pool = 0 if qstr in unsorted_qstr_list else 1 print("QDEF%d(MP_QSTR_%s, %s)" % (pool, ident, qbytes)) # CIRCUITPY-CHANGE: track total qstr size diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index 21300efb2c8a5..8c07899baf843 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -2,11 +2,9 @@ This script processes the output from the C preprocessor and extracts all qstr. Each qstr is transformed into a qstr definition of the form 'Q(...)'. -This script works with Python 3.x (CIRCUITPY-CHANGE: not 2.x) +This script works with Python 3.3+. """ -from __future__ import print_function - import io import os import re @@ -139,7 +137,8 @@ def qstr_unescape(qstr): return qstr -def process_file(f): +# CIRCUITPY-CHANGE: output_filename as an arg +def process_file(f, output_filename=None): # match gcc-like output (# n "file") and msvc-like output (#line n "file") re_line = re.compile(r"^#(?:line)?\s+\d+\s\"([^\"]+)\"") if args.mode == _MODE_QSTR: @@ -164,7 +163,7 @@ def process_file(f): fname = m.group(1) if not is_c_source(fname) and not is_cxx_source(fname): continue - if fname != last_fname: + if fname != last_fname and output_filename is None: write_out(last_fname, output) output = [] last_fname = fname @@ -181,7 +180,10 @@ def process_file(f): for match in re_translate.findall(line): output.append('TRANSLATE("' + match[0] + '")') - if last_fname: + if output_filename is not None: + with open(output_filename, "w") as f: + f.write("\n".join(output) + "\n") + elif last_fname: write_out(last_fname, output) return "" @@ -198,6 +200,11 @@ def cat_together(): with open(fname, "rb") as f: lines = f.readlines() all_lines += lines + # CIRCUITPY-CHANGE: Check for subdirectories as well. + for fname in glob.glob(args.output_dir + "/**/*." + args.mode): + with open(fname, "rb") as f: + lines = f.readlines() + all_lines += lines all_lines.sort() all_lines = b"\n".join(all_lines) # CIRCUITPY-CHANGE: added @@ -284,6 +291,9 @@ class Args: args.input_filename = sys.argv[3] # Unused for command=cat args.output_dir = sys.argv[4] args.output_file = None if len(sys.argv) == 5 else sys.argv[5] # Unused for command=split + # CIRCUITPY-CHANGE + if args.output_file == "_": + args.output_file = None if args.mode not in (_MODE_QSTR, _MODE_COMPRESS, _MODE_MODULE, _MODE_ROOT_POINTER): print("error: mode %s unrecognised" % sys.argv[2]) @@ -296,7 +306,8 @@ class Args: if args.command == "split": with io.open(args.input_filename, encoding="utf-8") as infile: - process_file(infile) + # CIRCUITPY-CHANGE: pass output_file + process_file(infile, args.output_file) if args.command == "cat": cat_together() diff --git a/py/maketranslationdata.py b/py/maketranslationdata.py index 0c264f31d68f0..3933387b645db 100644 --- a/py/maketranslationdata.py +++ b/py/maketranslationdata.py @@ -90,8 +90,8 @@ def translate(translation_file, i18ns): translations = [] for original in i18ns: unescaped = original - for s in C_ESCAPES: - unescaped = unescaped.replace(C_ESCAPES[s], s) + for s, replacement in C_ESCAPES.items(): + unescaped = unescaped.replace(replacement, s) if original == "en_US": translation = table.info()["language"] else: @@ -543,10 +543,9 @@ def parse_input_headers(infiles): with open(infile, "rt") as f: for line in f: line = line.strip() - - match = re.match(r'^TRANSLATE\("(.*)"\)$', line) + match = re.match(r'^TRANSLAT(E|ION)\("(.*)"(, \d+)?\)$', line) if match: - i18ns.add(match.group(1)) + i18ns.add(match.group(2)) continue return i18ns @@ -594,12 +593,15 @@ def output_translation_data(encoding_table, i18ns, out): total_text_compressed_size += len(compressed) decompressed = decompress(encoding_table, compressed, encoded_length_bits) assert decompressed == translation, (decompressed, translation) - for c in C_ESCAPES: - decompressed = decompressed.replace(c, C_ESCAPES[c]) + for c, replacement in C_ESCAPES.items(): + decompressed = decompressed.replace(c, replacement) formatted = ["{:d}".format(x) for x in compressed] out.write( "const struct compressed_string translation{} = {{ .data = {}, .tail = {{ {} }} }}; // {}\n".format( - i, formatted[0], ", ".join(formatted[1:]), original, decompressed + i, + formatted[0], + ", ".join(formatted[1:]), + original, ) ) total_text_size += len(translation.encode("utf-8")) diff --git a/py/makeversionhdr.py b/py/makeversionhdr.py index 72d6f3237876e..94321ef0bad4d 100644 --- a/py/makeversionhdr.py +++ b/py/makeversionhdr.py @@ -5,8 +5,6 @@ This script works with Python 3.7 and newer """ -from __future__ import print_function - import argparse import sys import os @@ -14,72 +12,11 @@ import datetime import subprocess -# CIRCUITPY-CHANGE: use external script that can override git describe output with an -# environment variable. -tools_describe = str(pathlib.Path(__file__).resolve().parent.parent / "tools/describe") - - -def get_version_info_from_git(repo_path): - # Python 2.6 doesn't have check_output, so check for that - try: - subprocess.check_output - subprocess.check_call - except AttributeError: - return None - - # Note: git describe doesn't work if no tag is available - try: - git_tag = subprocess.check_output( - [tools_describe], - cwd=repo_path, - shell=True, - stderr=subprocess.STDOUT, - universal_newlines=True, - ).strip() - except subprocess.CalledProcessError as er: - if er.returncode == 128: - # git exit code of 128 means no repository found - return None - git_tag = "" - except OSError: - return None - try: - git_hash = subprocess.check_output( - ["git", "rev-parse", "--short", "HEAD"], - cwd=repo_path, - stderr=subprocess.STDOUT, - universal_newlines=True, - ).strip() - except subprocess.CalledProcessError: - git_hash = "unknown" - except OSError: - return None - - try: - # Check if there are any modified files. - subprocess.check_call( - ["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"], - cwd=repo_path, - stderr=subprocess.STDOUT, - ) - # Check if there are any staged files. - subprocess.check_call( - ["git", "diff-index", "--cached", "--quiet", "HEAD", "--"], - cwd=repo_path, - stderr=subprocess.STDOUT, - ) - except subprocess.CalledProcessError: - git_hash += "-dirty" - except OSError: - return None - - # CIRCUITPY-CHANGE - # Try to extract MicroPython version from git tag - ver = git_tag.split("-")[0].split(".") - - return git_tag, git_hash, ver +# CIRCUITPY-CHANGE: Factor out version computation to py/version.py +import version +# CIRCUITPY-CHANGE def cannot_determine_version(): raise SystemExit( """Cannot determine version. @@ -93,7 +30,7 @@ def cannot_determine_version(): def make_version_header(repo_path, filename): # Get version info using git (required) - info = get_version_info_from_git(repo_path) + info = version.get_version_info_from_git(repo_path) if info is None: cannot_determine_version() git_tag, git_hash, ver = info @@ -104,11 +41,12 @@ def make_version_header(repo_path, filename): build_date = datetime.date.today() if "SOURCE_DATE_EPOCH" in os.environ: - build_date = datetime.datetime.utcfromtimestamp( - int(os.environ["SOURCE_DATE_EPOCH"]) + build_date = datetime.datetime.fromtimestamp( + int(os.environ["SOURCE_DATE_EPOCH"]), datetime.timezone.utc ).date() # Generate the file with the git and version info + # CIRCUITPY-CHANGE: different contents file_data = """\ // This file was generated by py/makeversionhdr.py #define MICROPY_GIT_TAG "%s" @@ -125,7 +63,7 @@ def make_version_header(repo_path, filename): """ % ( git_tag, git_hash, - datetime.date.today().strftime("%Y-%m-%d"), + build_date.strftime("%Y-%m-%d"), ver[0].replace("v", ""), ver[1], ver[2], diff --git a/py/malloc.c b/py/malloc.c index 0dbe66ea55851..fc9795043a879 100644 --- a/py/malloc.c +++ b/py/malloc.c @@ -24,6 +24,7 @@ * THE SOFTWARE. */ +#include #include #include #include @@ -69,7 +70,12 @@ #error MICROPY_ENABLE_FINALISER requires MICROPY_ENABLE_GC #endif -STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { +// CIRCUITPY-CHANGE: Add selective collect support to malloc to optimize GC for large buffers +#if MICROPY_ENABLE_SELECTIVE_COLLECT +#error MICROPY_ENABLE_SELECTIVE_COLLECT requires MICROPY_ENABLE_GC +#endif + +static void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { if (allow_move) { return realloc(ptr, n_bytes); } else { @@ -82,9 +88,26 @@ STATIC void *realloc_ext(void *ptr, size_t n_bytes, bool allow_move) { #endif // MICROPY_ENABLE_GC -void *m_malloc(size_t num_bytes) { - void *ptr = malloc(num_bytes); - if (ptr == NULL && num_bytes != 0) { +// CIRCUITPY-CHANGE: Add malloc helper to factor out flag handling and allow combinations. +void *m_malloc_helper(size_t num_bytes, uint8_t flags) { + void *ptr; + #if MICROPY_ENABLE_GC + uint8_t gc_flags = 0; + #if MICROPY_ENABLE_SELECTIVE_COLLECT + if ((flags & M_MALLOC_COLLECT) == 0) { + gc_flags |= GC_ALLOC_FLAG_DO_NOT_COLLECT; + } + #endif + #if MICROPY_ENABLE_FINALISER + if ((flags & M_MALLOC_WITH_FINALISER) != 0) { + gc_flags |= GC_ALLOC_FLAG_HAS_FINALISER; + } + #endif + ptr = gc_alloc(num_bytes, gc_flags); + #else + ptr = malloc(num_bytes); + #endif + if (ptr == NULL && num_bytes != 0 && (flags & M_MALLOC_RAISE_ERROR)) { m_malloc_fail(num_bytes); } #if MICROPY_MEM_STATS @@ -92,44 +115,49 @@ void *m_malloc(size_t num_bytes) { MP_STATE_MEM(current_bytes_allocated) += num_bytes; UPDATE_PEAK(); #endif + // If this config is set then the GC clears all memory, so we don't need to. + #if !MICROPY_GC_CONSERVATIVE_CLEAR + if (flags & M_MALLOC_ENSURE_ZEROED) { + memset(ptr, 0, num_bytes); + } + #endif DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); return ptr; } +void *m_malloc(size_t num_bytes) { + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); +} + void *m_malloc_maybe(size_t num_bytes) { - void *ptr = malloc(num_bytes); - #if MICROPY_MEM_STATS - MP_STATE_MEM(total_bytes_allocated) += num_bytes; - MP_STATE_MEM(current_bytes_allocated) += num_bytes; - UPDATE_PEAK(); - #endif - DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); - return ptr; + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, M_MALLOC_COLLECT); } #if MICROPY_ENABLE_FINALISER void *m_malloc_with_finaliser(size_t num_bytes) { - void *ptr = malloc_with_finaliser(num_bytes); - if (ptr == NULL && num_bytes != 0) { - m_malloc_fail(num_bytes); - } - #if MICROPY_MEM_STATS - MP_STATE_MEM(total_bytes_allocated) += num_bytes; - MP_STATE_MEM(current_bytes_allocated) += num_bytes; - UPDATE_PEAK(); - #endif - DEBUG_printf("malloc %d : %p\n", num_bytes, ptr); - return ptr; + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, M_MALLOC_COLLECT | M_MALLOC_WITH_FINALISER); } #endif void *m_malloc0(size_t num_bytes) { - void *ptr = m_malloc(num_bytes); - // If this config is set then the GC clears all memory, so we don't need to. - #if !MICROPY_GC_CONSERVATIVE_CLEAR - memset(ptr, 0, num_bytes); - #endif - return ptr; + // CIRCUITPY-CHANGE: use helper + return m_malloc_helper(num_bytes, + (MICROPY_GC_CONSERVATIVE_CLEAR ? 0 : M_MALLOC_ENSURE_ZEROED) + | M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); +} + +// CIRCUITPY-CHANGE: add selective collect +void *m_malloc_without_collect(size_t num_bytes) { + return m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR); +} + +// CIRCUITPY-CHANGE: add selective collect +void *m_malloc_maybe_without_collect(size_t num_bytes) { + + return m_malloc_helper(num_bytes, 0); } #if MICROPY_MALLOC_USES_ALLOCATED_SIZE @@ -209,6 +237,31 @@ void m_free(void *ptr) #if MICROPY_TRACKED_ALLOC +#if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL +// If there's no GIL, use the GC recursive mutex to protect the tracked node linked list +// under m_tracked_head. +// +// (For ports with GIL, the expectation is to only call tracked alloc functions +// while holding the GIL.) + +static inline void m_tracked_node_lock(void) { + mp_thread_recursive_mutex_lock(&MP_STATE_MEM(gc_mutex), 1); +} + +static inline void m_tracked_node_unlock(void) { + mp_thread_recursive_mutex_unlock(&MP_STATE_MEM(gc_mutex)); +} + +#else + +static inline void m_tracked_node_lock(void) { +} + +static inline void m_tracked_node_unlock(void) { +} + +#endif + #define MICROPY_TRACKED_ALLOC_STORE_SIZE (!MICROPY_ENABLE_GC) typedef struct _m_tracked_node_t { @@ -221,7 +274,8 @@ typedef struct _m_tracked_node_t { } m_tracked_node_t; #if MICROPY_DEBUG_VERBOSE -STATIC size_t m_tracked_count_links(size_t *nb) { +static size_t m_tracked_count_links(size_t *nb) { + m_tracked_node_lock(); m_tracked_node_t *node = MP_STATE_VM(m_tracked_head); size_t n = 0; *nb = 0; @@ -234,6 +288,7 @@ STATIC size_t m_tracked_count_links(size_t *nb) { #endif node = node->next; } + m_tracked_node_unlock(); return n; } #endif @@ -248,12 +303,14 @@ void *m_tracked_calloc(size_t nmemb, size_t size) { size_t n = m_tracked_count_links(&nb); DEBUG_printf("m_tracked_calloc(%u, %u) -> (%u;%u) %p\n", (int)nmemb, (int)size, (int)n, (int)nb, node); #endif + m_tracked_node_lock(); if (MP_STATE_VM(m_tracked_head) != NULL) { MP_STATE_VM(m_tracked_head)->prev = node; } node->prev = NULL; node->next = MP_STATE_VM(m_tracked_head); MP_STATE_VM(m_tracked_head) = node; + m_tracked_node_unlock(); #if MICROPY_TRACKED_ALLOC_STORE_SIZE node->size = nmemb * size; #endif @@ -279,7 +336,8 @@ void m_tracked_free(void *ptr_in) { size_t nb; size_t n = m_tracked_count_links(&nb); DEBUG_printf("m_tracked_free(%p, [%p, %p], nbytes=%u, links=%u;%u)\n", node, node->prev, node->next, (int)data_bytes, (int)n, (int)nb); - #endif + #endif // MICROPY_DEBUG_VERBOSE + m_tracked_node_lock(); if (node->next != NULL) { node->next->prev = node->prev; } @@ -288,6 +346,7 @@ void m_tracked_free(void *ptr_in) { } else { MP_STATE_VM(m_tracked_head) = node->next; } + m_tracked_node_unlock(); m_free(node #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #if MICROPY_TRACKED_ALLOC_STORE_SIZE diff --git a/py/map.c b/py/map.c index c18df5a9f333c..c434e0d0cddcc 100644 --- a/py/map.c +++ b/py/map.c @@ -65,14 +65,14 @@ // The first set of sizes are chosen so the allocation fits exactly in a // 4-word GC block, and it's not so important for these small values to be // prime. The latter sizes are prime and increase at an increasing rate. -STATIC const uint16_t hash_allocation_sizes[] = { +static const uint16_t hash_allocation_sizes[] = { 0, 2, 4, 6, 8, 10, 12, // +2 17, 23, 29, 37, 47, 59, 73, // *1.25 97, 127, 167, 223, 293, 389, 521, 691, 919, 1223, 1627, 2161, // *1.33 3229, 4831, 7243, 10861, 16273, 24407, 36607, 54907, // *1.5 }; -STATIC size_t get_hash_alloc_greater_or_equal_to(size_t x) { +static size_t get_hash_alloc_greater_or_equal_to(size_t x) { for (size_t i = 0; i < MP_ARRAY_SIZE(hash_allocation_sizes); i++) { if (hash_allocation_sizes[i] >= x) { return hash_allocation_sizes[i]; @@ -86,13 +86,17 @@ STATIC size_t get_hash_alloc_greater_or_equal_to(size_t x) { /******************************************************************************/ /* map */ +// CIRCUITPY-CHANGE: Helper for allocating tables of elements +#define malloc_table(num) m_new0(mp_map_elem_t, num) + void mp_map_init(mp_map_t *map, size_t n) { if (n == 0) { map->alloc = 0; map->table = NULL; } else { map->alloc = n; - map->table = m_new0(mp_map_elem_t, map->alloc); + // CIRCUITPY-CHANGE + map->table = malloc_table(map->alloc); } map->used = 0; map->all_keys_are_qstrs = 1; @@ -128,12 +132,13 @@ void mp_map_clear(mp_map_t *map) { map->table = NULL; } -STATIC void mp_map_rehash(mp_map_t *map) { +static void mp_map_rehash(mp_map_t *map) { size_t old_alloc = map->alloc; size_t new_alloc = get_hash_alloc_greater_or_equal_to(map->alloc + 1); DEBUG_printf("mp_map_rehash(%p): " UINT_FMT " -> " UINT_FMT "\n", map, old_alloc, new_alloc); mp_map_elem_t *old_table = map->table; - mp_map_elem_t *new_table = m_new0(mp_map_elem_t, new_alloc); + // CIRCUITPY-CHANGE + mp_map_elem_t *new_table = malloc_table(new_alloc); // If we reach this point, table resizing succeeded, now we can edit the old map. map->alloc = new_alloc; map->used = 0; @@ -329,15 +334,17 @@ mp_map_elem_t *MICROPY_WRAP_MP_MAP_LOOKUP(mp_map_lookup)(mp_map_t * map, mp_obj_ void mp_set_init(mp_set_t *set, size_t n) { set->alloc = n; set->used = 0; - set->table = m_new0(mp_obj_t, set->alloc); + // CIRCUITPY-CHANGE + set->table = m_malloc_items0(set->alloc); } -STATIC void mp_set_rehash(mp_set_t *set) { +static void mp_set_rehash(mp_set_t *set) { size_t old_alloc = set->alloc; mp_obj_t *old_table = set->table; set->alloc = get_hash_alloc_greater_or_equal_to(set->alloc + 1); set->used = 0; - set->table = m_new0(mp_obj_t, set->alloc); + // CIRCUITPY-CHANGE + set->table = m_malloc_items0(set->alloc); for (size_t i = 0; i < old_alloc; i++) { if (old_table[i] != MP_OBJ_NULL && old_table[i] != MP_OBJ_SENTINEL) { mp_set_lookup(set, old_table[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); diff --git a/py/misc.h b/py/misc.h index dc43e613155f0..d5d7950574f90 100644 --- a/py/misc.h +++ b/py/misc.h @@ -26,6 +26,8 @@ #ifndef MICROPY_INCLUDED_PY_MISC_H #define MICROPY_INCLUDED_PY_MISC_H +#include "py/mpconfig.h" + // a mini library of useful types and functions /** types *******************************************************/ @@ -33,13 +35,25 @@ #include #include #include - -// CIRCUITPY-CHANGE: include directly instead of depending on previous includes -#include "mpconfig.h" +// CIRCUITPY-CHANGE: #ifdef instead of #if +#ifdef __cplusplus // Required on at least one compiler to get ULLONG_MAX +#include +#else +#include +#endif typedef unsigned char byte; typedef unsigned int uint; +#ifndef __has_builtin +#define __has_builtin(x) (0) +#endif +#ifndef __has_feature +// This macro is supported by Clang and gcc>=14 +#define __has_feature(x) (0) +#endif + + /** generic ops *************************************************/ #ifndef MIN @@ -54,7 +68,15 @@ typedef unsigned int uint; #define MP_STRINGIFY(x) MP_STRINGIFY_HELPER(x) // Static assertion macro +// CIRCUITPY-CHANGE: defined() +#if defined(__cplusplus) +#define MP_STATIC_ASSERT(cond) static_assert((cond), #cond) +#elif __GNUC__ >= 5 || __STDC_VERSION__ >= 201112L +#define MP_STATIC_ASSERT(cond) _Static_assert((cond), #cond) +#else #define MP_STATIC_ASSERT(cond) ((void)sizeof(char[1 - 2 * !(cond)])) +#endif + // In C++ things like comparing extern const pointers are not constant-expressions so cannot be used // in MP_STATIC_ASSERT. Note that not all possible compiler versions will reject this. Some gcc versions // do, others only with -Werror=vla, msvc always does. @@ -63,7 +85,11 @@ typedef unsigned int uint; #if defined(_MSC_VER) || defined(__cplusplus) #define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)1) #else -#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) MP_STATIC_ASSERT(cond) +// CIRCUITPY-CHANGE: defined() +#if defined(__clang__) +#pragma GCC diagnostic ignored "-Wgnu-folding-constant" +#endif +#define MP_STATIC_ASSERT_NONCONSTEXPR(cond) ((void)sizeof(char[1 - 2 * !(cond)])) #endif // Round-up integer division @@ -74,6 +100,15 @@ typedef unsigned int uint; // TODO make a lazy m_renew that can increase by a smaller amount than requested (but by at least 1 more element) +// CIRCUITPY-CHANGE: new wrappers for selective collect, and use of m_malloc_helper() +// The following are convenience wrappers for m_malloc_helper and can save space at the call sites. +// m_malloc and m_new allocate space that is collected and does not have a finaliser. Use +// m_malloc_without_collect() if the space will not contain pointers to other heap allocations. It +// will still be marked and swept but not scanned for other pointers. +// Use m_malloc_items() to allocate space for mp_obj_ts that will be collected. +// Use mp_obj_malloc*() to allocate space for objects (aka structs with a type pointer) that will be +// collected. + #define m_new(type, num) ((type *)(m_malloc(sizeof(type) * (num)))) #define m_new_maybe(type, num) ((type *)(m_malloc_maybe(sizeof(type) * (num)))) #define m_new0(type, num) ((type *)(m_malloc0(sizeof(type) * (num)))) @@ -82,13 +117,6 @@ typedef unsigned int uint; #define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) #define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) #define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) -#if MICROPY_ENABLE_FINALISER -#define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type)))) -#define m_new_obj_var_with_finaliser(type, var_field, var_type, var_num) ((type *)m_malloc_with_finaliser(offsetof(type, var_field) + sizeof(var_type) * (var_num))) -#else -#define m_new_obj_with_finaliser(type) m_new_obj(type) -#define m_new_obj_var_with_finaliser(type, var_field, var_type, var_num) m_new_obj_var(type, var_field, var_type, var_num) -#endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move)))) @@ -102,10 +130,25 @@ typedef unsigned int uint; #endif #define m_del_obj(type, ptr) (m_del(type, ptr, 1)) +#define m_malloc_items(num) m_malloc(sizeof(mp_obj_t) * (num)) +#define m_malloc_items0(num) m_malloc0(sizeof(mp_obj_t) * (num)) + +// Flags for m_malloc_helper +#define M_MALLOC_ENSURE_ZEROED (1 << 0) +#define M_MALLOC_RAISE_ERROR (1 << 1) +#define M_MALLOC_COLLECT (1 << 2) +#define M_MALLOC_WITH_FINALISER (1 << 3) + +void *m_malloc_helper(size_t num_bytes, uint8_t flags); void *m_malloc(size_t num_bytes); void *m_malloc_maybe(size_t num_bytes); void *m_malloc_with_finaliser(size_t num_bytes); void *m_malloc0(size_t num_bytes); + +// CIRCUITPY-CHANGE: _without_collect +void *m_malloc_without_collect(size_t num_bytes); +void *m_malloc_maybe_without_collect(size_t num_bytes); + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes, bool allow_move); @@ -115,7 +158,7 @@ void *m_realloc(void *ptr, size_t new_num_bytes); void *m_realloc_maybe(void *ptr, size_t new_num_bytes, bool allow_move); void m_free(void *ptr); #endif -NORETURN void m_malloc_fail(size_t num_bytes); +MP_NORETURN void m_malloc_fail(size_t num_bytes); #if MICROPY_TRACKED_ALLOC // These alloc/free functions track the pointers in a linked list so the GC does not reclaim @@ -138,7 +181,7 @@ size_t m_get_peak_bytes_allocated(void); // align ptr to the nearest multiple of "alignment" #define MP_ALIGN(ptr, alignment) (void *)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1)) -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: addition #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) /** unichar / UTF-8 *********************************************/ @@ -285,6 +328,25 @@ typedef union _mp_float_union_t { mp_float_uint_t i; } mp_float_union_t; +#if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT + +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +// Exact float conversion requires using internally a bigger sort of floating point +typedef double mp_large_float_t; +#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +typedef long double mp_large_float_t; +#endif +// Always use a 64 bit mantissa for formatting and parsing +typedef uint64_t mp_large_float_uint_t; + +#else // MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_EXACT + +// No bigger floating points +typedef mp_float_t mp_large_float_t; +typedef mp_float_uint_t mp_large_float_uint_t; + +#endif + #endif // MICROPY_PY_BUILTINS_FLOAT /** ROM string compression *************/ @@ -350,4 +412,184 @@ typedef const char *mp_rom_error_text_t; // For now, forward directly to MP_COMPRESSED_ROM_TEXT. #define MP_ERROR_TEXT(x) (mp_rom_error_text_t)MP_COMPRESSED_ROM_TEXT(x) +// Portable implementations of CLZ and CTZ intrinsics +#ifdef _MSC_VER +#include + +static inline uint32_t mp_clz(uint32_t x) { + unsigned long lz = 0; + return _BitScanReverse(&lz, x) ? (sizeof(x) * 8 - 1) - lz : 0; +} + +static inline uint32_t mp_clzl(unsigned long x) { + unsigned long lz = 0; + return _BitScanReverse(&lz, x) ? (sizeof(x) * 8 - 1) - lz : 0; +} + +#ifdef _WIN64 +static inline uint32_t mp_clzll(unsigned long long x) { + unsigned long lz = 0; + return _BitScanReverse64(&lz, x) ? (sizeof(x) * 8 - 1) - lz : 0; +} +#else +// Microsoft don't ship _BitScanReverse64 on Win32, so emulate it +static inline uint32_t mp_clzll(unsigned long long x) { + unsigned long h = x >> 32; + return h ? mp_clzl(h) : (mp_clzl((unsigned long)x) + 32); +} +#endif + +static inline uint32_t mp_ctz(uint32_t x) { + unsigned long tz = 0; + return _BitScanForward(&tz, x) ? tz : 0; +} + +// Workaround for 'warning C4127: conditional expression is constant'. +static inline bool mp_check(bool value) { + return value; +} + +static inline uint32_t mp_popcount(uint32_t x) { + return __popcnt(x); +} +#else // _MSC_VER +#define mp_clz(x) __builtin_clz(x) +#define mp_clzl(x) __builtin_clzl(x) +#define mp_clzll(x) __builtin_clzll(x) +#define mp_ctz(x) __builtin_ctz(x) +#define mp_check(x) (x) +#if __has_builtin(__builtin_popcount) +#define mp_popcount(x) __builtin_popcount(x) +#else +static inline uint32_t mp_popcount(uint32_t x) { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + return (x * 0x01010101) >> 24; +} +#endif // __has_builtin(__builtin_popcount) +#endif // _MSC_VER + +#define MP_FIT_UNSIGNED(bits, value) (((value) & (~0U << (bits))) == 0) +#define MP_FIT_SIGNED(bits, value) \ + (MP_FIT_UNSIGNED(((bits) - 1), (value)) || \ + (((value) & (~0U << ((bits) - 1))) == (~0U << ((bits) - 1)))) + +// mp_int_t can be larger than long, i.e. Windows 64-bit, nan-box variants +static inline uint32_t mp_clz_mpi(mp_int_t x) { + #ifdef __XC16__ + mp_uint_t mask = MP_OBJ_WORD_MSBIT_HIGH; + mp_uint_t zeroes = 0; + while (mask != 0) { + if (mask & (mp_uint_t)x) { + break; + } + zeroes++; + mask >>= 1; + } + return zeroes; + #else + #if MP_INT_MAX == INT_MAX + return mp_clz((unsigned)x); + #elif MP_INT_MAX == LONG_MAX + return mp_clzl((unsigned long)x); + #elif MP_INT_MAX == LLONG_MAX + return mp_clzll((unsigned long long)x); + #else + #error Unexpected MP_INT_MAX value + #endif + #endif +} + +// Overflow-checked operations + +// Integer overflow builtins were added to GCC 5, but __has_builtin only in GCC 10 +// +// Note that the builtins has a defined result when overflow occurs, whereas the custom +// functions below don't update the result if an overflow would occur (to avoid UB). +#define MP_GCC_HAS_BUILTIN_OVERFLOW (__GNUC__ >= 5) + +#if MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC + +#define mp_mul_ull_overflow __builtin_umulll_overflow +#define mp_mul_ll_overflow __builtin_smulll_overflow +static inline bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { + // __builtin_mul_overflow is a type-generic function, this inline ensures the argument + // types are checked to match mp_int_t. + return __builtin_mul_overflow(x, y, res); +} + +#else + +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res); +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res); +static inline bool mp_mul_ull_overflow(unsigned long long int x, unsigned long long int y, unsigned long long int *res) { + if (y > 0 && x > (ULLONG_MAX / y)) { + return true; // overflow + } + *res = x * y; + return false; +} + +#endif + +#if __has_builtin(__builtin_saddll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW +#define mp_add_ll_overflow __builtin_saddll_overflow +#else +static inline bool mp_add_ll_overflow(long long int lhs, long long int rhs, long long int *res) { + bool overflow; + + if (rhs > 0) { + overflow = (lhs > LLONG_MAX - rhs); + } else { + overflow = (lhs < LLONG_MIN - rhs); + } + + if (!overflow) { + *res = lhs + rhs; + } + + return overflow; +} +#endif + +#if __has_builtin(__builtin_ssubll_overflow) || MP_GCC_HAS_BUILTIN_OVERFLOW +#define mp_sub_ll_overflow __builtin_ssubll_overflow +#else +static inline bool mp_sub_ll_overflow(long long int lhs, long long int rhs, long long int *res) { + bool overflow; + + if (rhs > 0) { + overflow = (lhs < LLONG_MIN + rhs); + } else { + overflow = (lhs > LLONG_MAX + rhs); + } + + if (!overflow) { + *res = lhs - rhs; + } + + return overflow; +} +#endif + + +// Helper macros for detecting if sanitizers are enabled +// +// Use sparingly, not for masking issues reported by sanitizers! +// +// Can be detected automatically in Clang and gcc>=14, need to be +// set manually otherwise. +#ifndef MP_UBSAN +#define MP_UBSAN __has_feature(undefined_behavior_sanitizer) +#endif + +#ifndef MP_ASAN +#define MP_ASAN __has_feature(address_sanitizer) +#endif + +#ifndef MP_SANITIZER_BUILD +#define MP_SANITIZER_BUILD (MP_UBSAN || MP_ASAN) +#endif + #endif // MICROPY_INCLUDED_PY_MISC_H diff --git a/py/mkrules.cmake b/py/mkrules.cmake index bfc56abfe80b7..e3d769cc59b5c 100644 --- a/py/mkrules.cmake +++ b/py/mkrules.cmake @@ -14,11 +14,34 @@ set(MICROPY_MODULEDEFS "${MICROPY_GENHDR_DIR}/moduledefs.h") set(MICROPY_ROOT_POINTERS_SPLIT "${MICROPY_GENHDR_DIR}/root_pointers.split") set(MICROPY_ROOT_POINTERS_COLLECTED "${MICROPY_GENHDR_DIR}/root_pointers.collected") set(MICROPY_ROOT_POINTERS "${MICROPY_GENHDR_DIR}/root_pointers.h") +set(MICROPY_COMPRESSED_SPLIT "${MICROPY_GENHDR_DIR}/compressed.split") +set(MICROPY_COMPRESSED_COLLECTED "${MICROPY_GENHDR_DIR}/compressed.collected") +set(MICROPY_COMPRESSED_DATA "${MICROPY_GENHDR_DIR}/compressed.data.h") if(NOT MICROPY_PREVIEW_VERSION_2) set(MICROPY_PREVIEW_VERSION_2 0) endif() +# Set the board name. +if(MICROPY_BOARD) + if(MICROPY_BOARD_VARIANT) + set(MICROPY_BOARD_BUILD_NAME ${MICROPY_BOARD}-${MICROPY_BOARD_VARIANT}) + else() + set(MICROPY_BOARD_BUILD_NAME ${MICROPY_BOARD}) + endif() + + target_compile_definitions(${MICROPY_TARGET} PRIVATE + MICROPY_BOARD_BUILD_NAME="${MICROPY_BOARD_BUILD_NAME}" + ) +endif() + +# Need to do this before extracting MICROPY_CPP_DEF below. +if(MICROPY_ROM_TEXT_COMPRESSION) + target_compile_definitions(${MICROPY_TARGET} PUBLIC + MICROPY_ROM_TEXT_COMPRESSION=\(1\) + ) +endif() + # Need to do this before extracting MICROPY_CPP_DEF below. Rest of frozen # manifest handling is at the end of this file. if(MICROPY_FROZEN_MANIFEST) @@ -53,6 +76,15 @@ foreach(_arg ${MICROPY_CPP_DEF}) endforeach() list(APPEND MICROPY_CPP_FLAGS ${MICROPY_CPP_FLAGS_EXTRA}) +# Include anything passed in via CFLAGS_EXTRA +# in both MICROPY_CPP_FLAGS and CMAKE_C_FLAGS +if(DEFINED ENV{CFLAGS_EXTRA}) + set(CFLAGS_EXTRA $ENV{CFLAGS_EXTRA}) + string(APPEND CMAKE_C_FLAGS " ${CFLAGS_EXTRA}") # ... not a list + separate_arguments(CFLAGS_EXTRA) + list(APPEND MICROPY_CPP_FLAGS ${CFLAGS_EXTRA}) # ... a list +endif() + find_package(Python3 REQUIRED COMPONENTS Interpreter) target_sources(${MICROPY_TARGET} PRIVATE @@ -62,6 +94,18 @@ target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_ROOT_POINTERS} ) +if(MICROPY_ROM_TEXT_COMPRESSION) + target_sources(${MICROPY_TARGET} PRIVATE + ${MICROPY_COMPRESSED_DATA} + ) +endif() + +# Ensure genhdr directory is removed on clean + +set_property(TARGET ${MICROPY_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${MICROPY_GENHDR_DIR}" +) + # Command to force the build of another command # Generate mpversion.h @@ -175,11 +219,41 @@ add_custom_command( DEPENDS ${MICROPY_ROOT_POINTERS_COLLECTED} ${MICROPY_PY_DIR}/make_root_pointers.py ) +# Generate compressed.data.h + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_SPLIT} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py split compress ${MICROPY_QSTRDEFS_LAST} ${MICROPY_GENHDR_DIR}/compress _ + COMMAND touch ${MICROPY_COMPRESSED_SPLIT} + DEPENDS ${MICROPY_QSTRDEFS_LAST} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_COLLECTED} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py cat compress _ ${MICROPY_GENHDR_DIR}/compress ${MICROPY_COMPRESSED_COLLECTED} + BYPRODUCTS "${MICROPY_COMPRESSED_COLLECTED}.hash" + DEPENDS ${MICROPY_COMPRESSED_SPLIT} + VERBATIM + COMMAND_EXPAND_LISTS +) + +add_custom_command( + OUTPUT ${MICROPY_COMPRESSED_DATA} + COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makecompresseddata.py ${MICROPY_COMPRESSED_COLLECTED} > ${MICROPY_COMPRESSED_DATA} + DEPENDS ${MICROPY_COMPRESSED_COLLECTED} ${MICROPY_PY_DIR}/makecompresseddata.py +) + # Build frozen code if enabled if(MICROPY_FROZEN_MANIFEST) set(MICROPY_FROZEN_CONTENT "${CMAKE_BINARY_DIR}/frozen_content.c") + set_property(TARGET ${MICROPY_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES + "${CMAKE_BINARY_DIR}/frozen_mpy" + ) + target_sources(${MICROPY_TARGET} PRIVATE ${MICROPY_FROZEN_CONTENT} ) @@ -187,16 +261,11 @@ if(MICROPY_FROZEN_MANIFEST) # Note: target_compile_definitions already added earlier. if(NOT MICROPY_LIB_DIR) - string(CONCAT GIT_SUBMODULES "${GIT_SUBMODULES} " lib/micropython-lib) + list(APPEND GIT_SUBMODULES lib/micropython-lib) set(MICROPY_LIB_DIR ${MICROPY_DIR}/lib/micropython-lib) endif() - if(ECHO_SUBMODULES) - # No-op, we're just doing submodule/variant discovery. - # Note: All the following rules are safe to run in discovery mode even - # though the submodule might not be available as they do not directly depend - # on anything from the submodule. - elseif(NOT EXISTS ${MICROPY_LIB_DIR}/README.md) + if(NOT UPDATE_SUBMODULES AND NOT EXISTS ${MICROPY_LIB_DIR}/README.md) message(FATAL_ERROR " micropython-lib not initialized.\n Run 'make BOARD=${MICROPY_BOARD} submodules'") endif() @@ -211,7 +280,7 @@ if(MICROPY_FROZEN_MANIFEST) endif() add_custom_command( OUTPUT ${MICROPY_MPYCROSS_DEPENDENCY} - COMMAND ${MICROPY_MAKE_EXECUTABLE} -C ${MICROPY_DIR}/mpy-cross + COMMAND ${MICROPY_MAKE_EXECUTABLE} -C ${MICROPY_DIR}/mpy-cross USER_C_MODULES= ) endif() @@ -250,12 +319,29 @@ if(MICROPY_FROZEN_MANIFEST) ) endif() -# Update submodules -if(ECHO_SUBMODULES) - # If cmake is run with GIT_SUBMODULES defined on command line, process the port / board - # settings then print the final GIT_SUBMODULES variable and exit. - # Note: the GIT_SUBMODULES is done via echo rather than message, as message splits - # the output onto multiple lines - execute_process(COMMAND ${CMAKE_COMMAND} -E echo "GIT_SUBMODULES=${GIT_SUBMODULES}") - message(FATAL_ERROR "Done") +# Update submodules, this is invoked on some ports via 'make submodules'. +# +# Note: This logic has a Makefile equivalent in py/mkrules.mk +if(UPDATE_SUBMODULES AND GIT_SUBMODULES) + macro(run_git) + execute_process(COMMAND git ${ARGV} WORKING_DIRECTORY ${MICROPY_DIR} + RESULT_VARIABLE RES) + endmacro() + + list(JOIN GIT_SUBMODULES " " GIT_SUBMODULES_MSG) + message("Updating submodules: ${GIT_SUBMODULES_MSG}") + run_git(submodule sync ${GIT_SUBMODULES}) + if(RES EQUAL 0) + # If available, do blobless partial clones of submodules to save time and space. + # A blobless partial clone lazily fetches data as needed, but has all the metadata available (tags, etc.). + run_git(submodule update --init --filter=blob:none ${GIT_SUBMODULES}) + # Fallback to standard submodule update if blobless isn't available (earlier than git 2.36.0) + if (NOT RES EQUAL 0) + run_git(submodule update --init ${GIT_SUBMODULES}) + endif() + endif() + + if (NOT RES EQUAL 0) + message(FATAL_ERROR "Submodule update failed") + endif() endif() diff --git a/py/mkrules.mk b/py/mkrules.mk index 4a72ced536031..03988996c71ce 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -11,7 +11,8 @@ ifeq ($(MICROPY_PREVIEW_VERSION_2),1) CFLAGS += -DMICROPY_PREVIEW_VERSION_2=1 endif -HELP_BUILD_ERROR ?= "See \033[1;31mhttps://github.com/micropython/micropython/wiki/Build-Troubleshooting\033[0m" +# CIRCUITPY-CHANGE: point to CircuitPython documentation +HELP_BUILD_ERROR ?= "See \033[1;31mhttps://learn.adafruit.com/building-circuitpython; Adafruit Discord \#circuitpython-dev\033[0m" HELP_MPY_LIB_SUBMODULE ?= "\033[1;31mError: micropython-lib submodule is not initialized.\033[0m Run 'make submodules'" # Extra deps that need to happen before object compilation. @@ -27,6 +28,17 @@ OBJ_EXTRA_ORDER_DEPS += $(HEADER_BUILD)/compressed.data.h CFLAGS += -DMICROPY_ROM_TEXT_COMPRESSION=1 endif +# Set the variant or board name. +ifneq ($(VARIANT),) +CFLAGS += -DMICROPY_BOARD_BUILD_NAME=\"$(VARIANT)\" +else ifneq ($(BOARD),) +ifeq ($(BOARD_VARIANT),) +CFLAGS += -DMICROPY_BOARD_BUILD_NAME=\"$(BOARD)\" +else +CFLAGS += -DMICROPY_BOARD_BUILD_NAME=\"$(BOARD)-$(BOARD_VARIANT)\" +endif +endif + # QSTR generation uses the same CFLAGS, with these modifications. QSTR_GEN_FLAGS = -DNO_QSTR # Note: := to force evaluation immediately. @@ -87,8 +99,8 @@ $(Q)$(CXX) $(CXXFLAGS) -c -MD -MF $(@:.o=.d) -o $@ $< || (echo -e $(HELP_BUILD_E $(RM) -f $(@:.o=.d) endef -# CIRCUITPY-CHANGE: add $(DEVICES_MODULES) and $(BUILD) -vpath %.c . $(TOP) $(USER_C_MODULES) $(DEVICES_MODULES) $(BUILD) +# CIRCUITPY-CHANGE: add $(BUILD) +vpath %.c . $(TOP) $(USER_C_MODULES) $(BUILD) $(BUILD)/%.o: %.c $(call compile_c) @@ -101,6 +113,14 @@ $(BUILD)/%.pp: %.c $(STEPECHO) "PreProcess $<" $(Q)$(CPP) $(CFLAGS) -Wp,-C,-dD,-dI -o $@ $< +.PHONY: $(BUILD)/%.sz +$(BUILD)/%.sz: $(BUILD)/%.o + $(Q)$(SIZE) $< + +# Special case for compiling auto-generated source files. +$(BUILD)/%.o: $(BUILD)/%.c + $(call compile_c) + # The following rule uses | to create an order only prerequisite. Order only # prerequisites only get built if they don't exist. They don't cause timestamp # checking to be performed. @@ -168,7 +188,7 @@ $(HEADER_BUILD)/compressed.collected: $(HEADER_BUILD)/compressed.split # will be created if they don't exist. OBJ_DIRS = $(sort $(dir $(OBJ))) $(OBJ): | $(OBJ_DIRS) -// CIRCUITPY-CHANGE: use $(Q) +# CIRCUITPY-CHANGE: use $(Q) $(OBJ_DIRS): $(Q)$(MKDIR) -p $@ @@ -178,7 +198,7 @@ $(HEADER_BUILD): ifneq ($(MICROPY_MPYCROSS_DEPENDENCY),) # to automatically build mpy-cross, if needed $(MICROPY_MPYCROSS_DEPENDENCY): - $(MAKE) -C $(abspath $(dir $@)..) + $(MAKE) -C "$(abspath $(dir $@)..)" USER_C_MODULES= endif ifneq ($(FROZEN_DIR),) @@ -240,11 +260,17 @@ clean-prog: .PHONY: clean-prog endif +# If available, do blobless partial clones of submodules to save time and space. +# A blobless partial clone lazily fetches data as needed, but has all the metadata available (tags, etc.). +# Fallback to standard submodule update if blobless isn't available (earlier than 2.36.0) +# +# Note: This target has a CMake equivalent in py/mkrules.cmake submodules: $(ECHO) "Updating submodules: $(GIT_SUBMODULES)" ifneq ($(GIT_SUBMODULES),) - $(Q)git submodule sync $(addprefix $(TOP)/,$(GIT_SUBMODULES)) - $(Q)git submodule update --init $(addprefix $(TOP)/,$(GIT_SUBMODULES)) + $(Q)cd $(TOP) && git submodule sync $(GIT_SUBMODULES) + $(Q)cd $(TOP) && git submodule update --init --filter=blob:none $(GIT_SUBMODULES) 2>/dev/null || \ + git submodule update --init $(GIT_SUBMODULES) endif .PHONY: submodules diff --git a/py/modarray.c b/py/modarray.c index ac2e56ed38b40..116c844e8eb1c 100644 --- a/py/modarray.c +++ b/py/modarray.c @@ -28,12 +28,12 @@ #if MICROPY_PY_ARRAY -STATIC const mp_rom_map_elem_t mp_module_array_globals_table[] = { +static const mp_rom_map_elem_t mp_module_array_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_array) }, { MP_ROM_QSTR(MP_QSTR_array), MP_ROM_PTR(&mp_type_array) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_array_globals, mp_module_array_globals_table); const mp_obj_module_t mp_module_array = { .base = { &mp_type_module }, diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 8aacafb796a3e..cdeacc25f7116 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -46,7 +46,7 @@ extern struct _mp_dummy_t mp_sys_stdout_obj; // type is irrelevant, just need po // args[0] is function from class body // args[1] is class name // args[2:] are base objects -STATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) { assert(2 <= n_args); // set the new classes __locals__ object @@ -88,12 +88,12 @@ STATIC mp_obj_t mp_builtin___build_class__(size_t n_args, const mp_obj_t *args) } MP_DEFINE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj, 2, mp_builtin___build_class__); -STATIC mp_obj_t mp_builtin_abs(mp_obj_t o_in) { +static mp_obj_t mp_builtin_abs(mp_obj_t o_in) { return mp_unary_op(MP_UNARY_OP_ABS, o_in); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_abs_obj, mp_builtin_abs); -STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) { +static mp_obj_t mp_builtin_all(mp_obj_t o_in) { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(o_in, &iter_buf); mp_obj_t item; @@ -106,7 +106,7 @@ STATIC mp_obj_t mp_builtin_all(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_all_obj, mp_builtin_all); -STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) { +static mp_obj_t mp_builtin_any(mp_obj_t o_in) { mp_obj_iter_buf_t iter_buf; mp_obj_t iterable = mp_getiter(o_in, &iter_buf); mp_obj_t item; @@ -119,13 +119,13 @@ STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any); -STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) { +static mp_obj_t mp_builtin_bin(mp_obj_t o_in) { mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in }; return mp_obj_str_format(MP_ARRAY_SIZE(args), args, NULL); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin); -STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) { +static mp_obj_t mp_builtin_callable(mp_obj_t o_in) { if (mp_obj_is_callable(o_in)) { return mp_const_true; } else { @@ -134,7 +134,7 @@ STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_callable_obj, mp_builtin_callable); -STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { +static mp_obj_t mp_builtin_chr(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_UNICODE mp_uint_t c = mp_obj_get_int(o_in); if (c >= 0x110000) { @@ -155,7 +155,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_chr_obj, mp_builtin_chr); -STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { mp_obj_t dir = mp_obj_new_list(0, NULL); if (n_args == 0) { // Make a list of names in the local namespace @@ -170,7 +170,7 @@ STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { // Implemented by probing all possible qstrs with mp_load_method_maybe size_t nqstr = QSTR_TOTAL(); for (size_t i = MP_QSTR_ + 1; i < nqstr; ++i) { - // CIRCUITPY-CHANGE: changes PR #6539: catch dir() exceptions + // CIRCUITPY-CHANGE: PR #6539: catch dir() exceptions mp_obj_t dest[2] = {}; mp_load_method_protected(args[0], i, dest, true); if (dest[0] != MP_OBJ_NULL) { @@ -189,18 +189,18 @@ STATIC mp_obj_t mp_builtin_dir(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj, 0, 1, mp_builtin_dir); -STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { +static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { return mp_binary_op(MP_BINARY_OP_DIVMOD, o1_in, o2_in); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod); -STATIC mp_obj_t mp_builtin_hash(mp_obj_t o_in) { +static mp_obj_t mp_builtin_hash(mp_obj_t o_in) { // result is guaranteed to be a (small) int return mp_unary_op(MP_UNARY_OP_HASH, o_in); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hash_obj, mp_builtin_hash); -STATIC mp_obj_t mp_builtin_hex(mp_obj_t o_in) { +static mp_obj_t mp_builtin_hex(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_OP_MODULO return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_x), o_in); #else @@ -220,7 +220,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_hex_obj, mp_builtin_hex); #define mp_hal_readline readline #endif -STATIC mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_input(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { mp_obj_print(args[0], PRINT_STR); } @@ -239,14 +239,14 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj, 0, 1, mp_builtin_input #endif -STATIC mp_obj_t mp_builtin_iter(mp_obj_t o_in) { +static mp_obj_t mp_builtin_iter(mp_obj_t o_in) { return mp_getiter(o_in, NULL); } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_iter_obj, mp_builtin_iter); #if MICROPY_PY_BUILTINS_MIN_MAX -STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs, mp_uint_t op) { +static mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs, mp_uint_t op) { mp_map_elem_t *key_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_key), MP_MAP_LOOKUP); mp_map_elem_t *default_elem; mp_obj_t key_fn = key_elem == NULL ? MP_OBJ_NULL : key_elem->value; @@ -288,12 +288,12 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t } } -STATIC mp_obj_t mp_builtin_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { +static mp_obj_t mp_builtin_max(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_MORE); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_max_obj, 1, mp_builtin_max); -STATIC mp_obj_t mp_builtin_min(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { +static mp_obj_t mp_builtin_min(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { return mp_builtin_min_max(n_args, args, kwargs, MP_BINARY_OP_LESS); } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_min_obj, 1, mp_builtin_min); @@ -301,7 +301,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_min_obj, 1, mp_builtin_min); #endif #if MICROPY_PY_BUILTINS_NEXT2 -STATIC mp_obj_t mp_builtin_next(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_next(size_t n_args, const mp_obj_t *args) { if (n_args == 1) { mp_obj_t ret = mp_iternext_allow_raise(args[0]); if (ret == MP_OBJ_STOP_ITERATION) { @@ -316,7 +316,7 @@ STATIC mp_obj_t mp_builtin_next(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_next_obj, 1, 2, mp_builtin_next); #else -STATIC mp_obj_t mp_builtin_next(mp_obj_t o) { +static mp_obj_t mp_builtin_next(mp_obj_t o) { mp_obj_t ret = mp_iternext_allow_raise(o); if (ret == MP_OBJ_STOP_ITERATION) { mp_raise_StopIteration(MP_STATE_THREAD(stop_iteration_arg)); @@ -327,7 +327,7 @@ STATIC mp_obj_t mp_builtin_next(mp_obj_t o) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next); #endif -STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) { +static mp_obj_t mp_builtin_oct(mp_obj_t o_in) { #if MICROPY_PY_BUILTINS_STR_OP_MODULO return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_o), o_in); #else @@ -337,7 +337,7 @@ STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); -STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { +static mp_obj_t mp_builtin_ord(mp_obj_t o_in) { size_t len; const byte *str = (const byte *)mp_obj_str_get_data(o_in, &len); #if MICROPY_PY_BUILTINS_STR_UNICODE @@ -358,13 +358,14 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("ord expects a character")); #else + // CIRCUITPY-CHANGE: more specific mp_raise mp_raise_TypeError_varg( MP_ERROR_TEXT("ord() expected a character, but string of length %d found"), (int)len); #endif } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord); -STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { switch (n_args) { case 2: return mp_binary_op(MP_BINARY_OP_POWER, args[0], args[1]); @@ -381,7 +382,7 @@ STATIC mp_obj_t mp_builtin_pow(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj, 2, 3, mp_builtin_pow); // CIRCUITPY-CHANGE: adds flush() -STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sep, ARG_end, ARG_flush, ARG_file }; static const mp_arg_t allowed_args[] = { { MP_QSTR_sep, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_QSTR(MP_QSTR__space_)} }, @@ -426,6 +427,7 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map } #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES mp_stream_write_adaptor(print.data, end_data, u.len[1]); + // CIRCUITPY-CHANGE: add flush() if (u.args[ARG_flush].u_bool) { mp_stream_flush(MP_OBJ_FROM_PTR(print.data)); } @@ -436,7 +438,7 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *pos_args, mp_map } MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print); -STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { +static mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { if (o != mp_const_none) { mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR); mp_print_str(MP_PYTHON_PRINTER, "\n"); @@ -450,7 +452,7 @@ STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj, mp_builtin___repl_print__); -STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { +static mp_obj_t mp_builtin_repr(mp_obj_t o_in) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); @@ -459,7 +461,7 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr); -STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { mp_obj_t o_in = args[0]; if (mp_obj_is_int(o_in)) { if (n_args <= 1) { @@ -511,7 +513,7 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round); -STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { mp_obj_t value; switch (n_args) { case 1: @@ -531,7 +533,7 @@ STATIC mp_obj_t mp_builtin_sum(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); -STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { +static mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args > 1) { mp_raise_TypeError(MP_ERROR_TEXT("must use keyword argument for key function")); } @@ -562,7 +564,7 @@ static inline mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t d } } -STATIC mp_obj_t mp_builtin_getattr(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_builtin_getattr(size_t n_args, const mp_obj_t *args) { mp_obj_t defval = MP_OBJ_NULL; if (n_args > 2) { defval = args[2]; @@ -571,20 +573,20 @@ STATIC mp_obj_t mp_builtin_getattr(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr); -STATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value) { +static mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value) { mp_store_attr(base, mp_obj_str_get_qstr(attr), value); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr); #if MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) { +static mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) { return mp_builtin_setattr(base, attr, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr); #endif -STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { +static mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { qstr attr = mp_obj_str_get_qstr(attr_in); mp_obj_t dest[2]; mp_load_method_protected(object_in, attr, dest, false); @@ -592,12 +594,12 @@ STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) { } MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj, mp_builtin_hasattr); -STATIC mp_obj_t mp_builtin_globals(void) { +static mp_obj_t mp_builtin_globals(void) { return MP_OBJ_FROM_PTR(mp_globals_get()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_globals_obj, mp_builtin_globals); -STATIC mp_obj_t mp_builtin_locals(void) { +static mp_obj_t mp_builtin_locals(void) { return MP_OBJ_FROM_PTR(mp_locals_get()); } MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_builtin_locals); @@ -606,7 +608,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(mp_builtin_locals_obj, mp_builtin_locals); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_obj_id); MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_len_obj, mp_obj_len); -STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { +static const mp_rom_map_elem_t mp_module_builtins_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_builtins) }, // built-in core functions diff --git a/py/modcmath.c b/py/modcmath.c index 1418362ad9b1e..33cb00cbe7e69 100644 --- a/py/modcmath.c +++ b/py/modcmath.c @@ -31,15 +31,15 @@ #include // phase(z): returns the phase of the number z in the range (-pi, +pi] -STATIC mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_phase(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_float(MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_phase_obj, mp_cmath_phase); // polar(z): returns the polar form of z as a tuple -STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_obj_t tuple[2] = { @@ -48,71 +48,71 @@ STATIC mp_obj_t mp_cmath_polar(mp_obj_t z_obj) { }; return mp_obj_new_tuple(2, tuple); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_polar_obj, mp_cmath_polar); // rect(r, phi): returns the complex number with modulus r and phase phi -STATIC mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) { +static mp_obj_t mp_cmath_rect(mp_obj_t r_obj, mp_obj_t phi_obj) { mp_float_t r = mp_obj_get_float(r_obj); mp_float_t phi = mp_obj_get_float(phi_obj); return mp_obj_new_complex(r * MICROPY_FLOAT_C_FUN(cos)(phi), r * MICROPY_FLOAT_C_FUN(sin)(phi)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect); +static MP_DEFINE_CONST_FUN_OBJ_2(mp_cmath_rect_obj, mp_cmath_rect); // exp(z): return the exponential of z -STATIC mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_exp(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_float_t exp_real = MICROPY_FLOAT_C_FUN(exp)(real); return mp_obj_new_complex(exp_real * MICROPY_FLOAT_C_FUN(cos)(imag), exp_real * MICROPY_FLOAT_C_FUN(sin)(imag)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_exp_obj, mp_cmath_exp); // log(z): return the natural logarithm of z, with branch cut along the negative real axis // TODO can take second argument, being the base -STATIC mp_obj_t mp_cmath_log(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_log(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(log)(real * real + imag * imag), MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log_obj, mp_cmath_log); #if MICROPY_PY_MATH_SPECIAL_FUNCTIONS // log10(z): return the base-10 logarithm of z, with branch cut along the negative real axis -STATIC mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_log10(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(log10)(real * real + imag * imag), MICROPY_FLOAT_CONST(0.4342944819032518) * MICROPY_FLOAT_C_FUN(atan2)(imag, real)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_log10_obj, mp_cmath_log10); #endif // sqrt(z): return the square-root of z -STATIC mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_sqrt(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); mp_float_t sqrt_abs = MICROPY_FLOAT_C_FUN(pow)(real * real + imag * imag, MICROPY_FLOAT_CONST(0.25)); mp_float_t theta = MICROPY_FLOAT_CONST(0.5) * MICROPY_FLOAT_C_FUN(atan2)(imag, real); return mp_obj_new_complex(sqrt_abs * MICROPY_FLOAT_C_FUN(cos)(theta), sqrt_abs * MICROPY_FLOAT_C_FUN(sin)(theta)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sqrt_obj, mp_cmath_sqrt); // cos(z): return the cosine of z -STATIC mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_cos(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), -MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_cos_obj, mp_cmath_cos); // sin(z): return the sine of z -STATIC mp_obj_t mp_cmath_sin(mp_obj_t z_obj) { +static mp_obj_t mp_cmath_sin(mp_obj_t z_obj) { mp_float_t real, imag; mp_obj_get_complex(z_obj, &real, &imag); return mp_obj_new_complex(MICROPY_FLOAT_C_FUN(sin)(real) * MICROPY_FLOAT_C_FUN(cosh)(imag), MICROPY_FLOAT_C_FUN(cos)(real) * MICROPY_FLOAT_C_FUN(sinh)(imag)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_cmath_sin_obj, mp_cmath_sin); -STATIC const mp_rom_map_elem_t mp_module_cmath_globals_table[] = { +static const mp_rom_map_elem_t mp_module_cmath_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cmath) }, { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e }, { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi }, @@ -142,7 +142,7 @@ STATIC const mp_rom_map_elem_t mp_module_cmath_globals_table[] = { // { MP_ROM_QSTR(MP_QSTR_isnan), MP_ROM_PTR(&mp_cmath_isnan_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_cmath_globals, mp_module_cmath_globals_table); const mp_obj_module_t mp_module_cmath = { .base = { &mp_type_module }, diff --git a/py/modcollections.c b/py/modcollections.c index 30a5881bc2c3a..46326d13eef5a 100644 --- a/py/modcollections.c +++ b/py/modcollections.c @@ -28,7 +28,7 @@ #if MICROPY_PY_COLLECTIONS -STATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = { +static const mp_rom_map_elem_t mp_module_collections_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_collections) }, #if MICROPY_PY_COLLECTIONS_DEQUE { MP_ROM_QSTR(MP_QSTR_deque), MP_ROM_PTR(&mp_type_deque) }, @@ -39,7 +39,7 @@ STATIC const mp_rom_map_elem_t mp_module_collections_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_collections_globals, mp_module_collections_globals_table); const mp_obj_module_t mp_module_collections = { .base = { &mp_type_module }, diff --git a/py/moderrno.c b/py/moderrno.c index b1002f177da5d..140ae1cc0a640 100644 --- a/py/moderrno.c +++ b/py/moderrno.c @@ -35,6 +35,7 @@ // This list can be defined per port in mpconfigport.h to tailor it to a // specific port's needs. If it's not defined then we provide a default. #ifndef MICROPY_PY_ERRNO_LIST +// CIRCUITPY-CHANGE: add ENOSPC and EROFS, because they are in mp_common_errno_to_str(). #define MICROPY_PY_ERRNO_LIST \ X(EPERM) \ X(ENOENT) \ @@ -47,6 +48,8 @@ X(ENODEV) \ X(EISDIR) \ X(EINVAL) \ + X(ENOSPC) \ + X(EROFS) \ X(EOPNOTSUPP) \ X(EADDRINUSE) \ X(ECONNABORTED) \ @@ -62,13 +65,13 @@ #endif #if MICROPY_PY_ERRNO_ERRORCODE -STATIC const mp_rom_map_elem_t errorcode_table[] = { +static const mp_rom_map_elem_t errorcode_table[] = { #define X(e) { MP_ROM_INT(MP_##e), MP_ROM_QSTR(MP_QSTR_##e) }, MICROPY_PY_ERRNO_LIST #undef X }; -STATIC const mp_obj_dict_t errorcode_dict = { +static const mp_obj_dict_t errorcode_dict = { .base = {&mp_type_dict}, .map = { .all_keys_are_qstrs = 0, // keys are integers @@ -81,7 +84,7 @@ STATIC const mp_obj_dict_t errorcode_dict = { }; #endif -STATIC const mp_rom_map_elem_t mp_module_errno_globals_table[] = { +static const mp_rom_map_elem_t mp_module_errno_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_errno) }, #if MICROPY_PY_ERRNO_ERRORCODE { MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) }, @@ -92,7 +95,7 @@ STATIC const mp_rom_map_elem_t mp_module_errno_globals_table[] = { #undef X }; -STATIC MP_DEFINE_CONST_DICT(mp_module_errno_globals, mp_module_errno_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_errno_globals, mp_module_errno_globals_table); const mp_obj_module_t mp_module_errno = { .base = { &mp_type_module }, diff --git a/py/modgc.c b/py/modgc.c index 7b18045b083a3..47902d8c95bce 100644 --- a/py/modgc.c +++ b/py/modgc.c @@ -31,7 +31,7 @@ #if MICROPY_PY_GC && MICROPY_ENABLE_GC // collect(): run a garbage collection -STATIC mp_obj_t py_gc_collect(void) { +static mp_obj_t py_gc_collect(void) { gc_collect(); #if MICROPY_PY_GC_COLLECT_RETVAL return MP_OBJ_NEW_SMALL_INT(MP_STATE_MEM(gc_collected)); @@ -42,26 +42,26 @@ STATIC mp_obj_t py_gc_collect(void) { MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect); // disable(): disable the garbage collector -STATIC mp_obj_t gc_disable(void) { +static mp_obj_t gc_disable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 0; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable); // enable(): enable the garbage collector -STATIC mp_obj_t gc_enable(void) { +static mp_obj_t gc_enable(void) { MP_STATE_MEM(gc_auto_collect_enabled) = 1; return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable); -STATIC mp_obj_t gc_isenabled(void) { +static mp_obj_t gc_isenabled(void) { return mp_obj_new_bool(MP_STATE_MEM(gc_auto_collect_enabled)); } MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled); // mem_free(): return the number of bytes of available heap RAM -STATIC mp_obj_t gc_mem_free(void) { +static mp_obj_t gc_mem_free(void) { gc_info_t info; gc_info(&info); #if MICROPY_GC_SPLIT_HEAP_AUTO @@ -74,7 +74,7 @@ STATIC mp_obj_t gc_mem_free(void) { MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_free_obj, gc_mem_free); // mem_alloc(): return the number of bytes of heap RAM that are allocated -STATIC mp_obj_t gc_mem_alloc(void) { +static mp_obj_t gc_mem_alloc(void) { gc_info_t info; gc_info(&info); return MP_OBJ_NEW_SMALL_INT(info.used); @@ -82,7 +82,7 @@ STATIC mp_obj_t gc_mem_alloc(void) { MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc); #if MICROPY_GC_ALLOC_THRESHOLD -STATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) { +static mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { if (MP_STATE_MEM(gc_alloc_threshold) == (size_t)-1) { return MP_OBJ_NEW_SMALL_INT(-1); @@ -100,7 +100,7 @@ STATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 1, gc_threshold); #endif -STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = { +static const mp_rom_map_elem_t mp_module_gc_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) }, { MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) }, { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&gc_disable_obj) }, @@ -113,7 +113,7 @@ STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table); const mp_obj_module_t mp_module_gc = { .base = { &mp_type_module }, diff --git a/py/modio.c b/py/modio.c index 39317c52d545f..9aeb42d30aa13 100644 --- a/py/modio.c +++ b/py/modio.c @@ -39,11 +39,11 @@ #if MICROPY_PY_IO_IOBASE -STATIC const mp_obj_type_t mp_type_iobase; +static const mp_obj_type_t mp_type_iobase; -STATIC const mp_obj_base_t iobase_singleton = {&mp_type_iobase}; +static const mp_obj_base_t iobase_singleton = {&mp_type_iobase}; -STATIC mp_obj_t iobase_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t iobase_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type; (void)n_args; (void)n_kw; @@ -51,7 +51,7 @@ STATIC mp_obj_t iobase_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(&iobase_singleton); } -STATIC mp_uint_t iobase_read_write(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode, qstr qst) { +static mp_uint_t iobase_read_write(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode, qstr qst) { mp_obj_t dest[3]; mp_load_method(obj, qst, dest); mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, size, buf}; @@ -69,15 +69,15 @@ STATIC mp_uint_t iobase_read_write(mp_obj_t obj, void *buf, mp_uint_t size, int return MP_STREAM_ERROR; } } -STATIC mp_uint_t iobase_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t iobase_read(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode) { return iobase_read_write(obj, buf, size, errcode, MP_QSTR_readinto); } -STATIC mp_uint_t iobase_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t iobase_write(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode) { return iobase_read_write(obj, (void *)buf, size, errcode, MP_QSTR_write); } -STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode) { mp_obj_t dest[4]; mp_load_method(obj, MP_QSTR_ioctl, dest); dest[2] = mp_obj_new_int_from_uint(request); @@ -91,13 +91,13 @@ STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, in } } -STATIC const mp_stream_p_t iobase_p = { +static const mp_stream_p_t iobase_p = { .read = iobase_read, .write = iobase_write, .ioctl = iobase_ioctl, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_iobase, MP_QSTR_IOBase, MP_TYPE_FLAG_NONE, @@ -116,17 +116,17 @@ typedef struct _mp_obj_bufwriter_t { byte buf[0]; } mp_obj_bufwriter_t; -STATIC mp_obj_t bufwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t bufwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 2, false); size_t alloc = mp_obj_get_int(args[1]); - mp_obj_bufwriter_t *o = mp_obj_malloc_var(mp_obj_bufwriter_t, byte, alloc, type); + mp_obj_bufwriter_t *o = mp_obj_malloc_var(mp_obj_bufwriter_t, buf, byte, alloc, type); o->stream = args[0]; o->alloc = alloc; o->len = 0; return o; } -STATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t org_size = size; @@ -162,37 +162,38 @@ STATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t si return org_size; } -STATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) { +static mp_obj_t bufwriter_flush(mp_obj_t self_in) { mp_obj_bufwriter_t *self = MP_OBJ_TO_PTR(self_in); if (self->len != 0) { int err; mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err); (void)out_sz; - // TODO: try to recover from a case of non-blocking stream, e.g. move - // remaining chunk to the beginning of buffer. - assert(out_sz == self->len); - self->len = 0; if (err != 0) { mp_raise_OSError(err); + } else { + // TODO: try to recover from a case of non-blocking stream, e.g. move + // remaining chunk to the beginning of buffer. + assert(out_sz == self->len); + self->len = 0; } } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bufwriter_flush_obj, bufwriter_flush); +static MP_DEFINE_CONST_FUN_OBJ_1(bufwriter_flush_obj, bufwriter_flush); -STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { +static const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&bufwriter_flush_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); +static MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); -STATIC const mp_stream_p_t bufwriter_stream_p = { +static const mp_stream_p_t bufwriter_stream_p = { .write = bufwriter_write, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_bufwriter, MP_QSTR_BufferedWriter, MP_TYPE_FLAG_NONE, @@ -202,7 +203,7 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( ); #endif // MICROPY_PY_IO_BUFFEREDWRITER -STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { +static const mp_rom_map_elem_t mp_module_io_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_io) }, // Note: mp_builtin_open_obj should be defined by port, it's not // part of the core. @@ -219,7 +220,7 @@ STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_io_globals, mp_module_io_globals_table); const mp_obj_module_t mp_module_io = { .base = { &mp_type_module }, diff --git a/py/modmath.c b/py/modmath.c index e20a38850f4f3..2a9ed1b7f2291 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -37,11 +37,11 @@ #define MP_PI_4 MICROPY_FLOAT_CONST(0.78539816339744830962) #define MP_3_PI_4 MICROPY_FLOAT_CONST(2.35619449019234492885) -STATIC NORETURN void math_error(void) { +static MP_NORETURN void math_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("math domain error")); } -STATIC mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) { +static mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) { mp_float_t x = mp_obj_get_float(x_obj); mp_float_t ans = f(x); if ((isnan(ans) && !isnan(x)) || (isinf(ans) && !isinf(x))) { @@ -50,7 +50,7 @@ STATIC mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) { return mp_obj_new_float(ans); } -STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(mp_float_t, mp_float_t)) { +static mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(mp_float_t, mp_float_t)) { mp_float_t x = mp_obj_get_float(x_obj); mp_float_t y = mp_obj_get_float(y_obj); mp_float_t ans = f(x, y); @@ -61,30 +61,30 @@ STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(m } #define MATH_FUN_1(py_name, c_name) \ - STATIC mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { \ + static mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { \ return math_generic_1(x_obj, MICROPY_FLOAT_C_FUN(c_name)); \ } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); + static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); #define MATH_FUN_1_TO_BOOL(py_name, c_name) \ - STATIC mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); + static mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \ + static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); #define MATH_FUN_1_TO_INT(py_name, c_name) \ - STATIC mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); + static mp_obj_t mp_math_##py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \ + static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_##py_name##_obj, mp_math_##py_name); #define MATH_FUN_2(py_name, c_name) \ - STATIC mp_obj_t mp_math_##py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ + static mp_obj_t mp_math_##py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ return math_generic_2(x_obj, y_obj, MICROPY_FLOAT_C_FUN(c_name)); \ } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_##py_name##_obj, mp_math_##py_name); + static MP_DEFINE_CONST_FUN_OBJ_2(mp_math_##py_name##_obj, mp_math_##py_name); #define MATH_FUN_2_FLT_INT(py_name, c_name) \ - STATIC mp_obj_t mp_math_##py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ + static mp_obj_t mp_math_##py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_int(y_obj))); \ } \ - STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_##py_name##_obj, mp_math_##py_name); + static MP_DEFINE_CONST_FUN_OBJ_2(mp_math_##py_name##_obj, mp_math_##py_name); #if MP_NEED_LOG2 #undef log2 @@ -99,12 +99,16 @@ mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) { MATH_FUN_1(sqrt, sqrt) // pow(x, y): returns x to the power of y #if MICROPY_PY_MATH_POW_FIX_NAN -mp_float_t pow_func(mp_float_t x, mp_float_t y) { +mp_float_t MICROPY_FLOAT_C_FUN(pow_func)(mp_float_t x, mp_float_t y) { // pow(base, 0) returns 1 for any base, even when base is NaN // pow(+1, exponent) returns 1 for any exponent, even when exponent is NaN if (x == MICROPY_FLOAT_CONST(1.0) || y == MICROPY_FLOAT_CONST(0.0)) { return MICROPY_FLOAT_CONST(1.0); } + // pow(base, NaN) returns NaN for any other value of base + if (isnan(y)) { + return y; + } return MICROPY_FLOAT_C_FUN(pow)(x, y); } MATH_FUN_2(pow, pow_func) @@ -160,12 +164,17 @@ MATH_FUN_2(atan2, atan2) // ceil(x) MATH_FUN_1_TO_INT(ceil, ceil) // copysign(x, y) -STATIC mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) { +static mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) { + #if MICROPY_PY_MATH_COPYSIGN_FIX_NAN + if (isnan(y)) { + y = 0.0; + } + #endif return MICROPY_FLOAT_C_FUN(copysign)(x, y); } MATH_FUN_2(copysign, copysign_func) // fabs(x) -STATIC mp_float_t MICROPY_FLOAT_C_FUN(fabs_func)(mp_float_t x) { +static mp_float_t MICROPY_FLOAT_C_FUN(fabs_func)(mp_float_t x) { return MICROPY_FLOAT_C_FUN(fabs)(x); } MATH_FUN_1(fabs, fabs_func) @@ -196,14 +205,24 @@ MATH_FUN_1(erf, erf) // erfc(x): return the complementary error function of x MATH_FUN_1(erfc, erfc) // gamma(x): return the gamma function of x +#if MICROPY_PY_MATH_GAMMA_FIX_NEGINF +static mp_float_t MICROPY_FLOAT_C_FUN(tgamma_func)(mp_float_t x) { + if (isinf(x) && x < 0) { + math_error(); + } + return MICROPY_FLOAT_C_FUN(tgamma)(x); +} +MATH_FUN_1(gamma, tgamma_func) +#else MATH_FUN_1(gamma, tgamma) +#endif // lgamma(x): return the natural logarithm of the gamma function of x MATH_FUN_1(lgamma, lgamma) #endif // TODO: fsum #if MICROPY_PY_MATH_ISCLOSE -STATIC mp_obj_t mp_math_isclose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t mp_math_isclose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_rel_tol, ARG_abs_tol }; static const mp_arg_t allowed_args[] = { {MP_QSTR_rel_tol, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, @@ -239,7 +258,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_math_isclose_obj, 2, mp_math_isclose); // Function that takes a variable number of arguments // log(x[, base]) -STATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { mp_float_t x = mp_obj_get_float(args[0]); if (x <= (mp_float_t)0.0) { math_error(); @@ -258,12 +277,12 @@ STATIC mp_obj_t mp_math_log(size_t n_args, const mp_obj_t *args) { return mp_obj_new_float(l / MICROPY_FLOAT_C_FUN(log)(base)); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_math_log_obj, 1, 2, mp_math_log); // Functions that return a tuple // frexp(x): converts a floating-point number to fractional and integral components -STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) { +static mp_obj_t mp_math_frexp(mp_obj_t x_obj) { int int_exponent = 0; mp_float_t significand = MICROPY_FLOAT_C_FUN(frexp)(mp_obj_get_float(x_obj), &int_exponent); mp_obj_t tuple[2]; @@ -271,10 +290,10 @@ STATIC mp_obj_t mp_math_frexp(mp_obj_t x_obj) { tuple[1] = mp_obj_new_int(int_exponent); return mp_obj_new_tuple(2, tuple); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_frexp_obj, mp_math_frexp); // modf(x) -STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) { +static mp_obj_t mp_math_modf(mp_obj_t x_obj) { mp_float_t int_part = 0.0; mp_float_t x = mp_obj_get_float(x_obj); mp_float_t fractional_part = MICROPY_FLOAT_C_FUN(modf)(x, &int_part); @@ -288,28 +307,28 @@ STATIC mp_obj_t mp_math_modf(mp_obj_t x_obj) { tuple[1] = mp_obj_new_float(int_part); return mp_obj_new_tuple(2, tuple); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf); // Angular conversions // radians(x) -STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) { +static mp_obj_t mp_math_radians(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0))); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians); // degrees(x) -STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) { +static mp_obj_t mp_math_degrees(mp_obj_t x_obj) { return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees); #if MICROPY_PY_MATH_FACTORIAL #if MICROPY_OPT_MATH_FACTORIAL // factorial(x): slightly efficient recursive implementation -STATIC mp_obj_t mp_math_factorial_inner(mp_uint_t start, mp_uint_t end) { +static mp_obj_t mp_math_factorial_inner(mp_uint_t start, mp_uint_t end) { if (start == end) { return mp_obj_new_int(start); } else if (end - start == 1) { @@ -327,7 +346,7 @@ STATIC mp_obj_t mp_math_factorial_inner(mp_uint_t start, mp_uint_t end) { return mp_binary_op(MP_BINARY_OP_MULTIPLY, left, right); } } -STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { +static mp_obj_t mp_math_factorial(mp_obj_t x_obj) { mp_int_t max = mp_obj_get_int(x_obj); if (max < 0) { mp_raise_ValueError(MP_ERROR_TEXT("negative factorial")); @@ -341,7 +360,7 @@ STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { // factorial(x): squared difference implementation // based on http://www.luschny.de/math/factorial/index.html -STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { +static mp_obj_t mp_math_factorial(mp_obj_t x_obj) { mp_int_t max = mp_obj_get_int(x_obj); if (max < 0) { mp_raise_ValueError(MP_ERROR_TEXT("negative factorial")); @@ -364,11 +383,11 @@ STATIC mp_obj_t mp_math_factorial(mp_obj_t x_obj) { #endif -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_factorial_obj, mp_math_factorial); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_math_factorial_obj, mp_math_factorial); #endif -STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { +static const mp_rom_map_elem_t mp_module_math_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_math) }, { MP_ROM_QSTR(MP_QSTR_e), mp_const_float_e }, { MP_ROM_QSTR(MP_QSTR_pi), mp_const_float_pi }, @@ -429,7 +448,7 @@ STATIC const mp_rom_map_elem_t mp_module_math_globals_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_math_globals, mp_module_math_globals_table); const mp_obj_module_t mp_module_math = { .base = { &mp_type_module }, diff --git a/py/modmicropython.c b/py/modmicropython.c index 17985b3e2b946..67bb32626c3fa 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -27,7 +27,7 @@ #include #include "py/builtin.h" -#include "py/stackctrl.h" +#include "py/cstack.h" #include "py/runtime.h" #include "py/gc.h" #include "py/mphal.h" @@ -39,7 +39,7 @@ // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_ENABLE_COMPILER -STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value)); } else { @@ -47,27 +47,27 @@ STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { return mp_const_none; } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); #endif // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS -STATIC mp_obj_t mp_micropython_mem_total(void) { +static mp_obj_t mp_micropython_mem_total(void) { return MP_OBJ_NEW_SMALL_INT(m_get_total_bytes_allocated()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_total_obj, mp_micropython_mem_total); -STATIC mp_obj_t mp_micropython_mem_current(void) { +static mp_obj_t mp_micropython_mem_current(void) { return MP_OBJ_NEW_SMALL_INT(m_get_current_bytes_allocated()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_current_obj, mp_micropython_mem_current); -STATIC mp_obj_t mp_micropython_mem_peak(void) { +static mp_obj_t mp_micropython_mem_peak(void) { return MP_OBJ_NEW_SMALL_INT(m_get_peak_bytes_allocated()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_mem_peak_obj, mp_micropython_mem_peak); #endif mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) { @@ -78,9 +78,9 @@ mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) { #endif #if MICROPY_STACK_CHECK mp_printf(&mp_plat_print, "stack: " UINT_FMT " out of " UINT_FMT "\n", - mp_stack_usage(), (mp_uint_t)MP_STATE_THREAD(stack_limit)); + mp_cstack_usage(), (mp_uint_t)MP_STATE_THREAD(stack_limit)); #else - mp_printf(&mp_plat_print, "stack: " UINT_FMT "\n", mp_stack_usage()); + mp_printf(&mp_plat_print, "stack: " UINT_FMT "\n", mp_cstack_usage()); #endif #if MICROPY_ENABLE_GC gc_dump_info(&mp_plat_print); @@ -93,87 +93,86 @@ mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args) { #endif return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_mem_info_obj, 0, 1, mp_micropython_mem_info); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_mem_info_obj, 0, 1, mp_micropython_mem_info); -STATIC mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_micropython_qstr_info(size_t n_args, const mp_obj_t *args) { (void)args; size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); mp_printf(&mp_plat_print, "qstr pool: n_pool=%u, n_qstr=%u, n_str_data_bytes=%u, n_total_bytes=%u\n", - n_pool, n_qstr, n_str_data_bytes, n_total_bytes); + (uint)n_pool, (uint)n_qstr, (uint)n_str_data_bytes, (uint)n_total_bytes); if (n_args == 1) { // arg given means dump qstr data qstr_dump_data(); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_qstr_info_obj, 0, 1, mp_micropython_qstr_info); #endif // MICROPY_PY_MICROPYTHON_MEM_INFO -// CIRCUITPY-CHANGE: avoid warning -#if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_PY_MICROPYTHON_STACK_USE -STATIC mp_obj_t mp_micropython_stack_use(void) { - return MP_OBJ_NEW_SMALL_INT(mp_stack_usage()); +#if MICROPY_PY_MICROPYTHON_STACK_USE +static mp_obj_t mp_micropython_stack_use(void) { + return MP_OBJ_NEW_SMALL_INT(mp_cstack_usage()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_stack_use_obj, mp_micropython_stack_use); #endif // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_ENABLE_PYSTACK -STATIC mp_obj_t mp_micropython_pystack_use(void) { +static mp_obj_t mp_micropython_pystack_use(void) { return MP_OBJ_NEW_SMALL_INT(mp_pystack_usage()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_pystack_use_obj, mp_micropython_pystack_use); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_pystack_use_obj, mp_micropython_pystack_use); #endif // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_ENABLE_GC -STATIC mp_obj_t mp_micropython_heap_lock(void) { +static mp_obj_t mp_micropython_heap_lock(void) { gc_lock(); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_lock_obj, mp_micropython_heap_lock); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_lock_obj, mp_micropython_heap_lock); -STATIC mp_obj_t mp_micropython_heap_unlock(void) { +static mp_obj_t mp_micropython_heap_unlock(void) { gc_unlock(); - return MP_OBJ_NEW_SMALL_INT(MP_STATE_THREAD(gc_lock_depth)); + return MP_OBJ_NEW_SMALL_INT(MP_STATE_THREAD(gc_lock_depth) >> GC_LOCK_DEPTH_SHIFT); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_heap_unlock); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_heap_unlock); #if MICROPY_PY_MICROPYTHON_HEAP_LOCKED -STATIC mp_obj_t mp_micropython_heap_locked(void) { - return MP_OBJ_NEW_SMALL_INT(MP_STATE_THREAD(gc_lock_depth)); +static mp_obj_t mp_micropython_heap_locked(void) { + return MP_OBJ_NEW_SMALL_INT(MP_STATE_THREAD(gc_lock_depth) >> GC_LOCK_DEPTH_SHIFT); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_locked_obj, mp_micropython_heap_locked); +static MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_locked_obj, mp_micropython_heap_locked); #endif #endif // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF && (MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE == 0) -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf); #endif // CIRCUITPY-CHANGE: avoid warning #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_KBD_EXCEPTION -STATIC mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) { +static mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) { mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in)); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr); #endif #if MICROPY_ENABLE_SCHEDULER -STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) { +static mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) { if (!mp_sched_schedule(function, arg)) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("schedule queue full")); } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule); +static MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule); #endif -STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { +static const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) }, { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) }, // CIRCUITPY-CHANGE: avoid warning @@ -214,12 +213,15 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { #if CIRCUITPY_MICROPYTHON_ADVANCED && MICROPY_KBD_EXCEPTION { MP_ROM_QSTR(MP_QSTR_kbd_intr), MP_ROM_PTR(&mp_micropython_kbd_intr_obj) }, #endif + #if MICROPY_PY_MICROPYTHON_RINGIO + { MP_ROM_QSTR(MP_QSTR_RingIO), MP_ROM_PTR(&mp_type_ringio) }, + #endif #if MICROPY_ENABLE_SCHEDULER { MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) }, #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table); const mp_obj_module_t mp_module_micropython = { .base = { &mp_type_module }, diff --git a/py/modstruct.c b/py/modstruct.c index b2124ac677d3e..5e405bb0d9311 100644 --- a/py/modstruct.c +++ b/py/modstruct.c @@ -52,7 +52,7 @@ character data". */ -STATIC char get_fmt_type(const char **fmt) { +static char get_fmt_type(const char **fmt) { char t = **fmt; switch (t) { case '!': @@ -71,7 +71,7 @@ STATIC char get_fmt_type(const char **fmt) { return t; } -STATIC mp_uint_t get_fmt_num(const char **p) { +static mp_uint_t get_fmt_num(const char **p) { const char *num = *p; uint len = 1; while (unichar_isdigit(*++num)) { @@ -82,7 +82,7 @@ STATIC mp_uint_t get_fmt_num(const char **p) { return val; } -STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { +static size_t calc_size_items(const char *fmt, size_t *total_sz) { char fmt_type = get_fmt_type(&fmt); size_t total_cnt = 0; size_t size; @@ -112,7 +112,7 @@ STATIC size_t calc_size_items(const char *fmt, size_t *total_sz) { return total_cnt; } -STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { +static mp_obj_t struct_calcsize(mp_obj_t fmt_in) { const char *fmt = mp_obj_str_get_str(fmt_in); size_t size; calc_size_items(fmt, &size); @@ -120,7 +120,7 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) { } MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize); -STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { +static mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { // unpack requires that the buffer be exactly the right size. // unpack_from requires that the buffer be "big enough". // Since we implement unpack and unpack_from using the same function @@ -180,7 +180,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_from_obj, 2, 3, struct_unpack_from); // This function assumes there is enough room in p to store all the values -STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, const mp_obj_t *args) { +static void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, const mp_obj_t *args) { // CIRCUITPY-CHANGE: additional error checking size_t size; size_t count = calc_size_items(mp_obj_str_get_str(fmt_in), &size); @@ -229,7 +229,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, size_t n_args, c } } -STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { +static mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { // TODO: "The arguments must match the values required by the format exactly." mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); vstr_t vstr; @@ -241,7 +241,7 @@ STATIC mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, struct_pack); -STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { +static mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); mp_int_t offset = mp_obj_get_int(args[2]); @@ -267,7 +267,7 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX, struct_pack_into); -STATIC const mp_rom_map_elem_t mp_module_struct_globals_table[] = { +static const mp_rom_map_elem_t mp_module_struct_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_struct) }, { MP_ROM_QSTR(MP_QSTR_calcsize), MP_ROM_PTR(&struct_calcsize_obj) }, { MP_ROM_QSTR(MP_QSTR_pack), MP_ROM_PTR(&struct_pack_obj) }, @@ -276,7 +276,7 @@ STATIC const mp_rom_map_elem_t mp_module_struct_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_unpack_from), MP_ROM_PTR(&struct_unpack_from_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_struct_globals, mp_module_struct_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_struct_globals, mp_module_struct_globals_table); const mp_obj_module_t mp_module_struct = { .base = { &mp_type_module }, diff --git a/py/modsys.c b/py/modsys.c index 6397467c2282d..bbae93d0c3f78 100644 --- a/py/modsys.c +++ b/py/modsys.c @@ -26,6 +26,7 @@ */ #include "py/builtin.h" +#include "py/objexcept.h" #include "py/objlist.h" #include "py/objmodule.h" #include "py/objtuple.h" @@ -64,15 +65,15 @@ const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adap #endif // version - Python language version that this implementation conforms to, as a string -STATIC const MP_DEFINE_STR_OBJ(mp_sys_version_obj, "3.4.0; " MICROPY_BANNER_NAME_AND_VERSION); +static const MP_DEFINE_STR_OBJ(mp_sys_version_obj, "3.4.0; " MICROPY_BANNER_NAME_AND_VERSION); // version_info - Python language version that this implementation conforms to, as a tuple of ints // TODO: CPython is now at 5-element array (major, minor, micro, releaselevel, serial), but save 2 els so far... -STATIC const mp_rom_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {MP_ROM_INT(3), MP_ROM_INT(4), MP_ROM_INT(0)}}; +static const mp_rom_obj_tuple_t mp_sys_version_info_obj = {{&mp_type_tuple}, 3, {MP_ROM_INT(3), MP_ROM_INT(4), MP_ROM_INT(0)}}; // sys.implementation object // this holds the MicroPython version -STATIC const mp_rom_obj_tuple_t mp_sys_implementation_version_info_obj = { +static const mp_rom_obj_tuple_t mp_sys_implementation_version_info_obj = { {&mp_type_tuple}, 4, { @@ -86,7 +87,7 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_version_info_obj = { #endif } }; -STATIC const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER_MACHINE); +static const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER_MACHINE); // CIRCUITPY-CHANGE: MP_QSTR_circuitpython #define SYS_IMPLEMENTATION_ELEMS_BASE \ MP_ROM_QSTR(MP_QSTR_circuitpython), \ @@ -94,13 +95,44 @@ STATIC const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER MP_ROM_PTR(&mp_sys_implementation_machine_obj) #if MICROPY_PERSISTENT_CODE_LOAD +// Note: Adding architecture flags to _mpy will break if the flags information +// takes up more bits than what is available in a small-int value. +#if MICROPY_EMIT_RV32 +#include "py/asmrv32.h" +#define MPY_FILE_ARCH_FLAGS (MICROPY_RV32_EXTENSIONS << 16) +#else +#define MPY_FILE_ARCH_FLAGS (0) +#endif #define SYS_IMPLEMENTATION_ELEMS__MPY \ - , MP_ROM_INT(MPY_FILE_HEADER_INT) + , MP_ROM_INT(MPY_FILE_HEADER_INT | MPY_FILE_ARCH_FLAGS) #else #define SYS_IMPLEMENTATION_ELEMS__MPY #endif #if MICROPY_PY_ATTRTUPLE + +#if defined(MICROPY_BOARD_BUILD_NAME) +static const MP_DEFINE_STR_OBJ(mp_sys_implementation__build_obj, MICROPY_BOARD_BUILD_NAME); +#define MICROPY_BOARD_BUILD (1) +#define SYS_IMPLEMENTATION_ELEMS__BUILD \ + , MP_ROM_PTR(&mp_sys_implementation__build_obj) +#else +#define MICROPY_BOARD_BUILD (0) +#define SYS_IMPLEMENTATION_ELEMS__BUILD +#endif + +#if MICROPY_PY_THREAD +#if MICROPY_PY_THREAD_GIL +#define SYS_IMPLEMENTATION_ELEMS__THREAD \ + , MP_ROM_QSTR(MP_QSTR_GIL) +#else +#define SYS_IMPLEMENTATION_ELEMS__THREAD \ + , MP_ROM_QSTR(MP_QSTR_unsafe) +#endif +#else +#define SYS_IMPLEMENTATION_ELEMS__THREAD +#endif + #if MICROPY_PREVIEW_VERSION_2 #define SYS_IMPLEMENTATION_ELEMS__V2 \ , MP_ROM_TRUE @@ -108,33 +140,41 @@ STATIC const MP_DEFINE_STR_OBJ(mp_sys_implementation_machine_obj, MICROPY_BANNER #define SYS_IMPLEMENTATION_ELEMS__V2 #endif -STATIC const qstr impl_fields[] = { +static const qstr impl_fields[] = { MP_QSTR_name, MP_QSTR_version, MP_QSTR__machine, #if MICROPY_PERSISTENT_CODE_LOAD MP_QSTR__mpy, #endif + #if defined(MICROPY_BOARD_BUILD_NAME) + MP_QSTR__build, + #endif + #if MICROPY_PY_THREAD + MP_QSTR__thread, + #endif #if MICROPY_PREVIEW_VERSION_2 MP_QSTR__v2, #endif }; -STATIC MP_DEFINE_ATTRTUPLE( +static MP_DEFINE_ATTRTUPLE( mp_sys_implementation_obj, impl_fields, - 3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_PREVIEW_VERSION_2, + 3 + MICROPY_PERSISTENT_CODE_LOAD + MICROPY_BOARD_BUILD + MICROPY_PY_THREAD + MICROPY_PREVIEW_VERSION_2, SYS_IMPLEMENTATION_ELEMS_BASE SYS_IMPLEMENTATION_ELEMS__MPY + SYS_IMPLEMENTATION_ELEMS__BUILD + SYS_IMPLEMENTATION_ELEMS__THREAD SYS_IMPLEMENTATION_ELEMS__V2 ); #else -STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { +static const mp_rom_obj_tuple_t mp_sys_implementation_obj = { {&mp_type_tuple}, 3 + MICROPY_PERSISTENT_CODE_LOAD, - // Do not include SYS_IMPLEMENTATION_ELEMS__V2 because - // SYS_IMPLEMENTATION_ELEMS__MPY may be empty if + // Do not include SYS_IMPLEMENTATION_ELEMS__BUILD, SYS_IMPLEMENTATION_ELEMS__THREAD + // or SYS_IMPLEMENTATION_ELEMS__V2 because SYS_IMPLEMENTATION_ELEMS__MPY may be empty if // MICROPY_PERSISTENT_CODE_LOAD is disabled, which means they'll share - // the same index. Cannot query _v2 if MICROPY_PY_ATTRTUPLE is + // the same index. Cannot query _build, _thread or _v2 if MICROPY_PY_ATTRTUPLE is // disabled. { SYS_IMPLEMENTATION_ELEMS_BASE @@ -147,7 +187,7 @@ STATIC const mp_rom_obj_tuple_t mp_sys_implementation_obj = { #ifdef MICROPY_PY_SYS_PLATFORM // platform - the platform that MicroPython is running on -STATIC const MP_DEFINE_STR_OBJ(mp_sys_platform_obj, MICROPY_PY_SYS_PLATFORM); +static const MP_DEFINE_STR_OBJ(mp_sys_platform_obj, MICROPY_PY_SYS_PLATFORM); #endif #ifdef MICROPY_PY_SYS_EXECUTABLE @@ -161,7 +201,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_intern_obj, mp_obj_str_intern_checked); #endif // exit([retval]): raise SystemExit, with optional argument given to the exception -STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { mp_raise_type(&mp_type_SystemExit); } else { @@ -170,32 +210,10 @@ STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit); -STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) { - // CIRCUITPY-CHANGE - #if CIRCUITPY_WARNINGS - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_print_exception, MP_QSTR_sys, MP_QSTR_traceback); - #endif - - #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES - void *stream_obj = &mp_sys_stdout_obj; - if (n_args > 1) { - mp_get_stream_raise(args[1], MP_STREAM_OP_WRITE); - stream_obj = MP_OBJ_TO_PTR(args[1]); - } - - mp_print_t print = {stream_obj, mp_stream_write_adaptor}; - mp_obj_print_exception(&print, args[0]); - #else - (void)n_args; - mp_obj_print_exception(&mp_plat_print, args[0]); - #endif - - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_print_exception); +// CIRCUITPY-CHANGE: Removed print_exception because it isn't in CPython. #if MICROPY_PY_SYS_EXC_INFO -STATIC mp_obj_t mp_sys_exc_info(void) { +static mp_obj_t mp_sys_exc_info(void) { mp_obj_t cur_exc = MP_OBJ_FROM_PTR(MP_STATE_VM(cur_exception)); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL)); @@ -209,32 +227,33 @@ STATIC mp_obj_t mp_sys_exc_info(void) { t->items[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(cur_exc)); t->items[1] = cur_exc; // CIRCUITPY-CHANGE: has traceback obj - t->items[2] = mp_obj_exception_get_traceback_obj(cur_exc); + mp_obj_exception_t *native_exc = mp_obj_exception_get_native(cur_exc); + t->items[2] = native_exc->traceback; return MP_OBJ_FROM_PTR(t); } MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info); #endif #if MICROPY_PY_SYS_GETSIZEOF -STATIC mp_obj_t mp_sys_getsizeof(mp_obj_t obj) { +static mp_obj_t mp_sys_getsizeof(mp_obj_t obj) { return mp_unary_op(MP_UNARY_OP_SIZEOF, obj); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_getsizeof_obj, mp_sys_getsizeof); #endif #if MICROPY_PY_SYS_ATEXIT // atexit(callback): Callback is called when sys.exit is called. -STATIC mp_obj_t mp_sys_atexit(mp_obj_t obj) { +static mp_obj_t mp_sys_atexit(mp_obj_t obj) { mp_obj_t old = MP_STATE_VM(sys_exitfunc); MP_STATE_VM(sys_exitfunc) = obj; return old; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_atexit_obj, mp_sys_atexit); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_atexit_obj, mp_sys_atexit); #endif #if MICROPY_PY_SYS_SETTRACE // settrace(tracefunc): Set the system's trace function. -STATIC mp_obj_t mp_sys_settrace(mp_obj_t obj) { +static mp_obj_t mp_sys_settrace(mp_obj_t obj) { return mp_prof_settrace(obj); } MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace); @@ -258,7 +277,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_sys_settrace_obj, mp_sys_settrace); #if MICROPY_PY_SYS_ATTR_DELEGATION // Must be kept in sync with the enum at the top of mpstate.h. -STATIC const uint16_t sys_mutable_keys[] = { +static const uint16_t sys_mutable_keys[] = { #if MICROPY_PY_SYS_PATH // Code should access this (as an mp_obj_t) for use with e.g. // mp_obj_list_append by using the `mp_sys_path` macro defined in runtime.h. @@ -281,7 +300,7 @@ void mp_module_sys_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } #endif -STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { +static const mp_rom_map_elem_t mp_module_sys_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys) }, #if MICROPY_PY_SYS_ARGV @@ -347,14 +366,12 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = { /* * Extensions to CPython */ - - { MP_ROM_QSTR(MP_QSTR_print_exception), MP_ROM_PTR(&mp_sys_print_exception_obj) }, #if MICROPY_PY_SYS_ATEXIT { MP_ROM_QSTR(MP_QSTR_atexit), MP_ROM_PTR(&mp_sys_atexit_obj) }, #endif }; -STATIC MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_sys_globals, mp_module_sys_globals_table); const mp_obj_module_t mp_module_sys = { .base = { &mp_type_module }, diff --git a/py/modthread.c b/py/modthread.c index aac58076f3026..1b792eaeb774b 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -28,7 +28,6 @@ #include #include "py/runtime.h" -#include "py/stackctrl.h" #if MICROPY_PY_THREAD @@ -45,7 +44,7 @@ /****************************************************************/ // Lock object -STATIC const mp_obj_type_t mp_type_thread_lock; +static const mp_obj_type_t mp_type_thread_lock; typedef struct _mp_obj_thread_lock_t { mp_obj_base_t base; @@ -53,14 +52,14 @@ typedef struct _mp_obj_thread_lock_t { volatile bool locked; } mp_obj_thread_lock_t; -STATIC mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) { +static mp_obj_thread_lock_t *mp_obj_new_thread_lock(void) { mp_obj_thread_lock_t *self = mp_obj_malloc(mp_obj_thread_lock_t, &mp_type_thread_lock); mp_thread_mutex_init(&self->mutex); self->locked = false; return self; } -STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { +static mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(args[0]); bool wait = true; if (n_args > 1) { @@ -79,9 +78,9 @@ STATIC mp_obj_t thread_lock_acquire(size_t n_args, const mp_obj_t *args) { mp_raise_OSError(-ret); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock_acquire_obj, 1, 3, thread_lock_acquire); -STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { +static mp_obj_t thread_lock_release(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); if (!self->locked) { mp_raise_msg(&mp_type_RuntimeError, NULL); @@ -92,21 +91,21 @@ STATIC mp_obj_t thread_lock_release(mp_obj_t self_in) { MP_THREAD_GIL_ENTER(); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release); +static MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_release_obj, thread_lock_release); -STATIC mp_obj_t thread_lock_locked(mp_obj_t self_in) { +static mp_obj_t thread_lock_locked(mp_obj_t self_in) { mp_obj_thread_lock_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(self->locked); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_locked_obj, thread_lock_locked); +static MP_DEFINE_CONST_FUN_OBJ_1(thread_lock_locked_obj, thread_lock_locked); -STATIC mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) { +static mp_obj_t thread_lock___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; // unused return thread_lock_release(args[0]); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(thread_lock___exit___obj, 4, 4, thread_lock___exit__); -STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { +static const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_acquire), MP_ROM_PTR(&thread_lock_acquire_obj) }, { MP_ROM_QSTR(MP_QSTR_release), MP_ROM_PTR(&thread_lock_release_obj) }, { MP_ROM_QSTR(MP_QSTR_locked), MP_ROM_PTR(&thread_lock_locked_obj) }, @@ -114,9 +113,9 @@ STATIC const mp_rom_map_elem_t thread_lock_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&thread_lock___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table); +static MP_DEFINE_CONST_DICT(thread_lock_locals_dict, thread_lock_locals_dict_table); -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_thread_lock, MP_QSTR_lock, MP_TYPE_FLAG_NONE, @@ -126,15 +125,14 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( /****************************************************************/ // _thread module -STATIC size_t thread_stack_size = 0; +static size_t thread_stack_size = 0; -STATIC mp_obj_t mod_thread_get_ident(void) { - // CIRCUITPY-CHANGE: uintptr_t cast to avoid warning - return mp_obj_new_int_from_uint((uintptr_t)mp_thread_get_state()); +static mp_obj_t mod_thread_get_ident(void) { + return mp_obj_new_int_from_uint(mp_thread_get_id()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_get_ident_obj, mod_thread_get_ident); -STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { mp_obj_t ret = mp_obj_new_int_from_uint(thread_stack_size); if (n_args == 0) { thread_stack_size = 0; @@ -143,7 +141,7 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) { } return ret; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size); typedef struct _thread_entry_args_t { mp_obj_dict_t *dict_locals; @@ -155,16 +153,13 @@ typedef struct _thread_entry_args_t { mp_obj_t args[]; } thread_entry_args_t; -STATIC void *thread_entry(void *args_in) { +static void *thread_entry(void *args_in) { // Execution begins here for a new thread. We do not have the GIL. thread_entry_args_t *args = (thread_entry_args_t *)args_in; mp_state_thread_t ts; - mp_thread_set_state(&ts); - - mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan - mp_stack_set_limit(args->stack_size); + mp_thread_init_state(&ts, args->stack_size, args->dict_locals, args->dict_globals); #if MICROPY_ENABLE_PYSTACK // TODO threading and pystack is not fully supported, for now just make a small stack @@ -172,6 +167,7 @@ STATIC void *thread_entry(void *args_in) { mp_pystack_init(mini_pystack, &mini_pystack[128]); #endif + // CIRCUITPY-CHANGE // The GC starts off unlocked on this thread. ts.gc_lock_depth = 0; @@ -221,7 +217,7 @@ STATIC void *thread_entry(void *args_in) { return NULL; } -STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) { // This structure holds the Python function and arguments for thread entry. // We copy all arguments into this structure to keep ownership of them. // We must be very careful about root pointers because this pointer may @@ -272,19 +268,19 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) // spawn the thread! return mp_obj_new_int_from_uint(mp_thread_create(thread_entry, th_args, &th_args->stack_size)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_start_new_thread_obj, 2, 3, mod_thread_start_new_thread); -STATIC mp_obj_t mod_thread_exit(void) { +static mp_obj_t mod_thread_exit(void) { mp_raise_type(&mp_type_SystemExit); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_exit_obj, mod_thread_exit); -STATIC mp_obj_t mod_thread_allocate_lock(void) { +static mp_obj_t mod_thread_allocate_lock(void) { return MP_OBJ_FROM_PTR(mp_obj_new_thread_lock()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock); +static MP_DEFINE_CONST_FUN_OBJ_0(mod_thread_allocate_lock_obj, mod_thread_allocate_lock); -STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { +static const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__thread) }, { MP_ROM_QSTR(MP_QSTR_LockType), MP_ROM_PTR(&mp_type_thread_lock) }, { MP_ROM_QSTR(MP_QSTR_get_ident), MP_ROM_PTR(&mod_thread_get_ident_obj) }, @@ -294,7 +290,7 @@ STATIC const mp_rom_map_elem_t mp_module_thread_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_allocate_lock), MP_ROM_PTR(&mod_thread_allocate_lock_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_table); +static MP_DEFINE_CONST_DICT(mp_module_thread_globals, mp_module_thread_globals_table); const mp_obj_module_t mp_module_thread = { .base = { &mp_type_module }, diff --git a/py/mpconfig.h b/py/mpconfig.h index 0a846bcd7cb33..69a338d746a2f 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -26,6 +26,14 @@ #ifndef MICROPY_INCLUDED_PY_MPCONFIG_H #define MICROPY_INCLUDED_PY_MPCONFIG_H +#include + +#if defined(__cplusplus) // Required on at least one compiler to get ULLONG_MAX +#include +#else +#include +#endif + // CIRCUITPY-CHANGE // Is this a CircuitPython build? #ifndef CIRCUITPY @@ -36,10 +44,12 @@ #if CIRCUITPY #include "genhdr/mpversion.h" #else -// Current version of MicroPython +// Current version of MicroPython. This is used by sys.implementation.version +// as well as a fallback to generate MICROPY_GIT_TAG if the git repo or tags +// are unavailable. #define MICROPY_VERSION_MAJOR 1 -#define MICROPY_VERSION_MINOR 22 -#define MICROPY_VERSION_MICRO 2 +#define MICROPY_VERSION_MINOR 27 +#define MICROPY_VERSION_MICRO 0 #define MICROPY_VERSION_PRERELEASE 0 // Combined version as a 32-bit number for convenience to allow version @@ -171,6 +181,78 @@ #define MICROPY_OBJ_IMMEDIATE_OBJS (MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D) #endif +// Definition of the `mp_int_t` and `mp_uint_t` types and associated macros. +// Normally, it suffices for the platform to do nothing: A type as wide +// as a pointer is chosen, unless nanboxing (REPR_D) is selected, in +// which case a 64-bit type is chosen to match the assumed size of +// double-precision floats. +// +// In the case of exceptions, the port, board, or variant must define +// MP_INT_TYPE as MP_INT_TYPE_OTHER and provide all the typedefs and +// defines. +#define MP_INT_TYPE_INTPTR (0) +#define MP_INT_TYPE_INT64 (1) +#define MP_INT_TYPE_OTHER (2) + +#if !defined(MP_INT_TYPE) +#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D +#define MP_INT_TYPE (MP_INT_TYPE_INT64) +#else +#define MP_INT_TYPE (MP_INT_TYPE_INTPTR) +#endif +#endif + +#if MP_INT_TYPE == MP_INT_TYPE_INTPTR +typedef intptr_t mp_int_t; +typedef uintptr_t mp_uint_t; +#define MP_INT_MAX INTPTR_MAX +#define MP_INT_MIN INTPTR_MIN +#define MP_UINT_MAX INTPTR_UMAX +#elif MP_INT_TYPE == MP_INT_TYPE_INT64 +typedef int64_t mp_int_t; +typedef uint64_t mp_uint_t; +#define MP_INT_MAX INT64_MAX +#define MP_INT_MIN INT64_MIN +#define MP_UINT_MAX INT64_UMAX +#endif + +// mp_printf format support for mp_int_t. In the unusual case that MP_INT_MAX doesn't +// match any of the standard C types (int/long/long long), provide all 3 +// macros. Otherwise, rely on these automatic definitions. +#if !defined(INT_FMT) +#if MP_INT_MAX == INT_MAX +#define INT_FMT "%d" +#define UINT_FMT "%u" +#define HEX_FMT "%x" +#elif MP_INT_MAX == LONG_MAX +#define INT_FMT "%ld" +#define UINT_FMT "%lu" +#define HEX_FMT "%lx" +#elif MP_INT_MAX == LLONG_MAX +#define INT_FMT "%lld" +#define UINT_FMT "%llu" +#define HEX_FMT "%llx" +#else +#error Unexpected MP_INT_MAX value +#endif +#endif + +// mp_printf format support for size_t. In the unusual case that SIZE_MAX doesn't +// match any of the standard C types (int/long/long long), provide a +// macro. Otherwise, rely on these automatic definitions. +#if !defined(SIZE_FMT) +#if SIZE_MAX == UINT_MAX +#define SIZE_FMT "%u" +#elif SIZE_MAX == ULONG_MAX +#define SIZE_FMT "%lu" +#elif SIZE_MAX == ULLONG_MAX +#define SIZE_FMT "%llu" +#else +#error Unexpected SIZE_MAX value +#endif +#endif + + /*****************************************************************************/ /* Memory allocation policy */ @@ -300,10 +382,12 @@ // Number of bytes used to store qstr hash #ifndef MICROPY_QSTR_BYTES_IN_HASH -#if MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES +#if MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES #define MICROPY_QSTR_BYTES_IN_HASH (2) -#else +#elif MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES #define MICROPY_QSTR_BYTES_IN_HASH (1) +#else +#define MICROPY_QSTR_BYTES_IN_HASH (0) #endif #endif @@ -350,6 +434,11 @@ #define MICROPY_PERSISTENT_CODE_SAVE_FILE (0) #endif +// Whether to support converting functions to persistent code (bytes) +#ifndef MICROPY_PERSISTENT_CODE_SAVE_FUN +#define MICROPY_PERSISTENT_CODE_SAVE_FUN (MICROPY_PY_MARSHAL) +#endif + // Whether generated code can persist independently of the VM/runtime instance // This is enabled automatically when needed by other features #ifndef MICROPY_PERSISTENT_CODE @@ -409,13 +498,38 @@ #define MICROPY_EMIT_INLINE_XTENSA (0) #endif +// Whether to support uncommon Xtensa inline assembler opcodes +#ifndef MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES +#define MICROPY_EMIT_INLINE_XTENSA_UNCOMMON_OPCODES (0) +#endif + // Whether to emit Xtensa-Windowed native code #ifndef MICROPY_EMIT_XTENSAWIN #define MICROPY_EMIT_XTENSAWIN (0) #endif +// Whether to emit RISC-V RV32 native code +#ifndef MICROPY_EMIT_RV32 +#define MICROPY_EMIT_RV32 (0) +#endif + +// Whether to emit RISC-V RV32 Zba opcodes in native code +#ifndef MICROPY_EMIT_RV32_ZBA +#define MICROPY_EMIT_RV32_ZBA (0) +#endif + +// Whether to enable the RISC-V RV32 inline assembler +#ifndef MICROPY_EMIT_INLINE_RV32 +#define MICROPY_EMIT_INLINE_RV32 (0) +#endif + +// Whether to enable the human-readable native instructions emitter +#ifndef MICROPY_EMIT_NATIVE_DEBUG +#define MICROPY_EMIT_NATIVE_DEBUG (0) +#endif + // Convenience definition for whether any native emitter is enabled -#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN) +#define MICROPY_EMIT_NATIVE (MICROPY_EMIT_X64 || MICROPY_EMIT_X86 || MICROPY_EMIT_THUMB || MICROPY_EMIT_ARM || MICROPY_EMIT_XTENSA || MICROPY_EMIT_XTENSAWIN || MICROPY_EMIT_RV32 || MICROPY_EMIT_NATIVE_DEBUG) // Some architectures cannot read byte-wise from executable memory. In this case // the prelude for a native function (which usually sits after the machine code) @@ -423,23 +537,11 @@ #define MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE (MICROPY_EMIT_XTENSAWIN) // Convenience definition for whether any inline assembler emitter is enabled -#define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA) +#define MICROPY_EMIT_INLINE_ASM (MICROPY_EMIT_INLINE_THUMB || MICROPY_EMIT_INLINE_XTENSA || MICROPY_EMIT_INLINE_RV32) // Convenience definition for whether any native or inline assembler emitter is enabled #define MICROPY_EMIT_MACHINE_CODE (MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_ASM) -// Whether native relocatable code loaded from .mpy files is explicitly tracked -// so that the GC cannot reclaim it. Needed on architectures that allocate -// executable memory on the MicroPython heap and don't explicitly track this -// data some other way. -#ifndef MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE -#if !MICROPY_EMIT_MACHINE_CODE || defined(MP_PLAT_ALLOC_EXEC) || defined(MP_PLAT_COMMIT_EXEC) -#define MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE (0) -#else -#define MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE (1) -#endif -#endif - /*****************************************************************************/ /* Compiler configuration */ @@ -454,6 +556,11 @@ #define MICROPY_DYNAMIC_COMPILER (0) #endif +// Whether the compiler allows compiling top-level await expressions +#ifndef MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT +#define MICROPY_COMP_ALLOW_TOP_LEVEL_AWAIT (0) +#endif + // Whether to enable constant folding; eg 1+2 rewritten as 3 #ifndef MICROPY_COMP_CONST_FOLDING #define MICROPY_COMP_CONST_FOLDING (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) @@ -480,6 +587,13 @@ #define MICROPY_COMP_CONST (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Whether to enable float constant folding like 1.2+3.4 (when MICROPY_COMP_CONST_FOLDING is also enabled) +// and constant optimisation like id = const(1.2) (when MICROPY_COMP_CONST is also enabled) +// and constant lookup like math.inf (when MICROPY_COMP_MODULE_CONST is also enabled) +#ifndef MICROPY_COMP_CONST_FLOAT +#define MICROPY_COMP_CONST_FLOAT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#endif + // Whether to enable optimisation of: a, b = c, d // Costs 124 bytes (Thumb2) #ifndef MICROPY_COMP_DOUBLE_TUPLE_ASSIGN @@ -599,6 +713,12 @@ /*****************************************************************************/ /* Python internal features */ +// Use a special long jump in nlrthumb.c, which may be necessary if nlr.o and +// nlrthumb.o are linked far apart from each other. +#ifndef MICROPY_NLR_THUMB_USE_LONG_JUMP +#define MICROPY_NLR_THUMB_USE_LONG_JUMP (0) +#endif + // Whether to enable import of external modules // When disabled, only importing of built-in modules is supported // When enabled, a port must implement mp_import_stat (among other things) @@ -697,6 +817,20 @@ #define MICROPY_STACK_CHECK (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif +// Additional margin between the places in the runtime where Python stack is +// checked and the actual end of the C stack. Needs to be large enough to avoid +// overflows from function calls made between checks. +#ifndef MICROPY_STACK_CHECK_MARGIN +#define MICROPY_STACK_CHECK_MARGIN (0) +#endif + +// The size of a separate stack used for hard IRQ handlers, which should be +// checked instead of the main stack when running a hard callback. 0 implies +// there is no separate ISR stack to check. +#ifndef MICROPY_STACK_SIZE_HARD_IRQ +#define MICROPY_STACK_SIZE_HARD_IRQ (0) +#endif + // Whether to have an emergency exception buffer #ifndef MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF #define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0) @@ -866,6 +1000,36 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT) #endif +// Float to string conversion implementations +// +// Note that the EXACT method is only available if the compiler supports +// floating points larger than mp_float_t: +// - with MICROPY_FLOAT_IMPL_FLOAT, the compiler needs to support `double` +// - with MICROPY_FLOAT_IMPL_DOUBLE, the compiler needs to support `long double` +// +#define MICROPY_FLOAT_FORMAT_IMPL_BASIC (0) // smallest code, but inexact +#define MICROPY_FLOAT_FORMAT_IMPL_APPROX (1) // slightly bigger, almost perfect +#define MICROPY_FLOAT_FORMAT_IMPL_EXACT (2) // bigger code, and 100% exact repr + +#ifndef MICROPY_FLOAT_FORMAT_IMPL +#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_APPROX) +#elif defined(__SIZEOF_LONG_DOUBLE__) && __SIZEOF_LONG_DOUBLE__ > __SIZEOF_DOUBLE__ +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_EXACT) +#else +#define MICROPY_FLOAT_FORMAT_IMPL (MICROPY_FLOAT_FORMAT_IMPL_APPROX) +#endif +#endif + +// Whether to use the native _Float16 for 16-bit float support +#ifndef MICROPY_FLOAT_USE_NATIVE_FLT16 +#ifdef __FLT16_MAX__ +#define MICROPY_FLOAT_USE_NATIVE_FLT16 (1) +#else +#define MICROPY_FLOAT_USE_NATIVE_FLT16 (0) +#endif +#endif + // Whether to provide a high-quality hash for float and complex numbers. // Otherwise the default is a very simple but correct hashing function. #ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH @@ -889,6 +1053,64 @@ typedef double mp_float_t; #define MICROPY_FULL_CHECKS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Ports can choose to use timestamps based on 2000-01-01 or 1970-01-01 +// Default is timestamps based on 2000-01-01 +#if !defined(MICROPY_EPOCH_IS_2000) && !defined(MICROPY_EPOCH_IS_1970) +#define MICROPY_EPOCH_IS_2000 (1) +#define MICROPY_EPOCH_IS_1970 (0) +#elif !defined(MICROPY_EPOCH_IS_1970) +#define MICROPY_EPOCH_IS_1970 (1 - (MICROPY_EPOCH_IS_2000)) +#elif !defined(MICROPY_EPOCH_IS_2000) +#define MICROPY_EPOCH_IS_2000 (1 - (MICROPY_EPOCH_IS_1970)) +#endif + +// To maintain reasonable compatibility with CPython on embedded systems, +// and avoid breaking anytime soon, time functions are defined to work +// at least between 1970 and 2099 (included) on any machine. +// +// Specific ports can enable extended date support +// - after 2099 using MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND +// - before 1970 using MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +// The largest possible range is year 1600 to year 3000 +// +// By default, extended date support is only enabled for machines using 64 bit pointers, +// but it can be enabled by specific ports +#ifndef MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +#if MP_SSIZE_MAX > 2147483647 +#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (1) +#else +#define MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE (0) +#endif +#endif + +// When support for dates <1970 is enabled, supporting >=2100 does not cost anything +#ifndef MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND +#define MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND (MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE) +#endif + +// The type to be used to represent platform-specific timestamps depends on the choices above +#define MICROPY_TIMESTAMP_IMPL_LONG_LONG (0) +#define MICROPY_TIMESTAMP_IMPL_UINT (1) +#define MICROPY_TIMESTAMP_IMPL_TIME_T (2) + +#ifndef MICROPY_TIMESTAMP_IMPL +#if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE || MICROPY_EPOCH_IS_2000 +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_LONG_LONG) +#else +#define MICROPY_TIMESTAMP_IMPL (MICROPY_TIMESTAMP_IMPL_UINT) +#endif +#endif + +// `mp_timestamp_t` is the type that should be used by the port +// to represent timestamps, and is referenced to the platform epoch +#if MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_LONG_LONG +typedef long long mp_timestamp_t; +#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT +typedef mp_uint_t mp_timestamp_t; +#elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_TIME_T +typedef time_t mp_timestamp_t; +#endif + // Whether POSIX-semantics non-blocking streams are supported #ifndef MICROPY_STREAMS_NON_BLOCK #define MICROPY_STREAMS_NON_BLOCK (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -900,6 +1122,16 @@ typedef double mp_float_t; #define MICROPY_STREAMS_POSIX_API (0) #endif +// Whether to process __all__ when importing all public symbols from a module. +#ifndef MICROPY_MODULE___ALL__ +#define MICROPY_MODULE___ALL__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES) +#endif + +// Whether to set __file__ on imported modules. +#ifndef MICROPY_MODULE___FILE__ +#define MICROPY_MODULE___FILE__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#endif + // Whether modules can use MP_REGISTER_MODULE_DELEGATION() to delegate failed // attribute lookups to a custom handler function. #ifndef MICROPY_MODULE_ATTR_DELEGATION @@ -987,6 +1219,16 @@ typedef double mp_float_t; #define MICROPY_ENABLE_VM_ABORT (0) #endif +// Whether to handle abort behavior in pyexec code +#ifndef MICROPY_PYEXEC_ENABLE_VM_ABORT +#define MICROPY_PYEXEC_ENABLE_VM_ABORT (0) +#endif + +// Whether to set exit codes according to the exit reason (keyboard interrupt, crash, normal exit, ...) +#ifndef MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING (0) +#endif + // Support for internal scheduler #ifndef MICROPY_ENABLE_SCHEDULER #define MICROPY_ENABLE_SCHEDULER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1007,11 +1249,26 @@ typedef double mp_float_t; #define MICROPY_VFS (0) #endif +// Whether to include support for writable filesystems. +#ifndef MICROPY_VFS_WRITABLE +#define MICROPY_VFS_WRITABLE (1) +#endif + +// Whether to enable the mp_vfs_rom_ioctl C function, and vfs.rom_ioctl Python function +#ifndef MICROPY_VFS_ROM_IOCTL +#define MICROPY_VFS_ROM_IOCTL (MICROPY_VFS_ROM) +#endif + // Support for VFS POSIX component, to mount a POSIX filesystem within VFS #ifndef MICROPY_VFS_POSIX #define MICROPY_VFS_POSIX (0) #endif +// Whether to include support for writable POSIX filesystems. +#ifndef MICROPY_VFS_POSIX_WRITABLE +#define MICROPY_VFS_POSIX_WRITABLE (1) +#endif + // Support for VFS FAT component, to mount a FAT filesystem within VFS #ifndef MICROPY_VFS_FAT #define MICROPY_VFS_FAT (0) @@ -1027,6 +1284,11 @@ typedef double mp_float_t; #define MICROPY_VFS_LFS2 (0) #endif +// Support for ROMFS. +#ifndef MICROPY_VFS_ROM +#define MICROPY_VFS_ROM (0) +#endif + /*****************************************************************************/ /* Fine control over Python builtins, classes, modules, etc */ @@ -1042,7 +1304,20 @@ typedef double mp_float_t; #define MICROPY_PY_FUNCTION_ATTRS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to support the descriptors __get__, __set__, __delete__ +// Whether to implement the __code__ attribute on functions, and function constructor +#ifndef MICROPY_PY_FUNCTION_ATTRS_CODE +#define MICROPY_PY_FUNCTION_ATTRS_CODE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_FULL_FEATURES) +#endif + +// Whether bound_method can just use == (feature disabled), or requires a call to +// mp_obj_equal (feature enabled), to test equality of the self and meth entities. +// This is only needed if objects and functions can be identical without being the +// same thing, eg when using an object proxy. +#ifndef MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK +#define MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK (0) +#endif + +// Whether to support the descriptors __get__, __set__, __delete__, __set_name__ // This costs some code size and makes load/store/delete of instance // attributes slower for the classes that use this feature #ifndef MICROPY_PY_DESCRIPTORS @@ -1130,6 +1405,15 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_BYTEARRAY (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif +// Whether to support code objects, and how many features they have +#define MICROPY_PY_BUILTINS_CODE_NONE (0) +#define MICROPY_PY_BUILTINS_CODE_MINIMUM (1) +#define MICROPY_PY_BUILTINS_CODE_BASIC (2) +#define MICROPY_PY_BUILTINS_CODE_FULL (3) +#ifndef MICROPY_PY_BUILTINS_CODE +#define MICROPY_PY_BUILTINS_CODE (MICROPY_PY_SYS_SETTRACE ? MICROPY_PY_BUILTINS_CODE_FULL : (MICROPY_PY_FUNCTION_ATTRS_CODE ? MICROPY_PY_BUILTINS_CODE_BASIC : (MICROPY_PY_BUILTINS_COMPILE ? MICROPY_PY_BUILTINS_CODE_MINIMUM : MICROPY_PY_BUILTINS_CODE_NONE))) +#endif + // Whether to support dict.fromkeys() class method #ifndef MICROPY_PY_BUILTINS_DICT_FROMKEYS #define MICROPY_PY_BUILTINS_DICT_FROMKEYS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) @@ -1192,7 +1476,7 @@ typedef double mp_float_t; // Support for calling next() with second argument #ifndef MICROPY_PY_BUILTINS_NEXT2 -#define MICROPY_PY_BUILTINS_NEXT2 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) +#define MICROPY_PY_BUILTINS_NEXT2 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES) #endif // Whether to support rounding of integers (incl bignum); eg round(123,-1)=120 @@ -1290,11 +1574,6 @@ typedef double mp_float_t; #define MICROPY_PY_BUILTINS_HELP_MODULES (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// Whether to set __file__ for imported modules -#ifndef MICROPY_PY___FILE__ -#define MICROPY_PY___FILE__ (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) -#endif - // Whether to provide mem-info related functions in micropython module #ifndef MICROPY_PY_MICROPYTHON_MEM_INFO #define MICROPY_PY_MICROPYTHON_MEM_INFO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1310,6 +1589,11 @@ typedef double mp_float_t; #define MICROPY_PY_MICROPYTHON_HEAP_LOCKED (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif +// Support for micropython.RingIO() +#ifndef MICROPY_PY_MICROPYTHON_RINGIO +#define MICROPY_PY_MICROPYTHON_RINGIO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + // Whether to provide "array" module. Note that large chunk of the // underlying code is shared with "bytearray" builtin type, so to // get real savings, it should be disabled too. @@ -1339,13 +1623,11 @@ typedef double mp_float_t; #define MICROPY_PY_COLLECTIONS_DEQUE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// CIRCUITPY-CHANGE // Whether "collections.deque" supports iteration #ifndef MICROPY_PY_COLLECTIONS_DEQUE_ITER #define MICROPY_PY_COLLECTIONS_DEQUE_ITER (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif -// CIRCUITPY-CHANGE // Whether "collections.deque" supports subscription #ifndef MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR #define MICROPY_PY_COLLECTIONS_DEQUE_SUBSCR (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1361,6 +1643,11 @@ typedef double mp_float_t; #define MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) #endif +// Whether to provide "marshal" module +#ifndef MICROPY_PY_MARSHAL +#define MICROPY_PY_MARSHAL (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EVERYTHING) +#endif + // Whether to provide "math" module #ifndef MICROPY_PY_MATH #define MICROPY_PY_MATH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) @@ -1402,10 +1689,16 @@ typedef double mp_float_t; #endif // Whether to provide fix for pow(1, NaN) and pow(NaN, 0), which both should be 1 not NaN. +// Also fixes pow(base, NaN) to return NaN for other values of base. #ifndef MICROPY_PY_MATH_POW_FIX_NAN #define MICROPY_PY_MATH_POW_FIX_NAN (0) #endif +// Whether to provide fix for gamma(-inf) to raise ValueError +#ifndef MICROPY_PY_MATH_GAMMA_FIX_NEGINF +#define MICROPY_PY_MATH_GAMMA_FIX_NEGINF (0) +#endif + // Whether to provide "cmath" module #ifndef MICROPY_PY_CMATH #define MICROPY_PY_CMATH (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) @@ -1433,7 +1726,7 @@ typedef double mp_float_t; // Whether to provide "io.IOBase" class to support user streams #ifndef MICROPY_PY_IO_IOBASE -#define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#define MICROPY_PY_IO_IOBASE (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif // Whether to provide "io.BytesIO" class @@ -1451,15 +1744,16 @@ typedef double mp_float_t; #define MICROPY_PY_STRUCT (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) #endif -// CIRCUITPY-CHANGE -// Whether to provide non-standard typecodes in "struct" module -#ifndef MICROPY_NONSTANDARD_TYPECODES -#define MICROPY_NONSTANDARD_TYPECODES (1) +// Whether struct module provides unsafe and non-standard typecodes O, P, S. +// These typecodes are not in CPython and can cause crashes by accessing arbitrary +// memory. +#ifndef MICROPY_PY_STRUCT_UNSAFE_TYPECODES +#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (1) #endif // Whether to provide "sys" module #ifndef MICROPY_PY_SYS -#define MICROPY_PY_SYS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES) +#define MICROPY_PY_SYS (1) #endif // Whether to initialise "sys.path" and "sys.argv" to their defaults in mp_init() @@ -1628,12 +1922,21 @@ typedef double mp_float_t; #define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32) #endif +// Is a recursive mutex type in use? +#ifndef MICROPY_PY_THREAD_RECURSIVE_MUTEX +#define MICROPY_PY_THREAD_RECURSIVE_MUTEX (MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL) +#endif + // Extended modules #ifndef MICROPY_PY_ASYNCIO #define MICROPY_PY_ASYNCIO (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif +#ifndef MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK +#define MICROPY_PY_ASYNCIO_TASK_QUEUE_PUSH_CALLBACK (0) +#endif + #ifndef MICROPY_PY_UCTYPES #define MICROPY_PY_UCTYPES (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif @@ -1706,11 +2009,11 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_HASHLIB_MD5 -#define MICROPY_PY_HASHLIB_MD5 (0) +#define MICROPY_PY_HASHLIB_MD5 (MICROPY_PY_SSL) #endif #ifndef MICROPY_PY_HASHLIB_SHA1 -#define MICROPY_PY_HASHLIB_SHA1 (0) +#define MICROPY_PY_HASHLIB_SHA1 (MICROPY_PY_SSL) #endif #ifndef MICROPY_PY_HASHLIB_SHA256 @@ -1718,7 +2021,7 @@ typedef double mp_float_t; #endif #ifndef MICROPY_PY_CRYPTOLIB -#define MICROPY_PY_CRYPTOLIB (0) +#define MICROPY_PY_CRYPTOLIB (MICROPY_PY_SSL) #endif // Depends on MICROPY_PY_CRYPTOLIB @@ -1735,6 +2038,7 @@ typedef double mp_float_t; #endif // CIRCUITPY-CHANGE: does not depend on MICROPY_PY_DEFLATE +// Depends on MICROPY_PY_DEFLATE #ifndef MICROPY_PY_BINASCII_CRC32 #define MICROPY_PY_BINASCII_CRC32 (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) #endif @@ -1752,6 +2056,16 @@ typedef double mp_float_t; #define MICROPY_PY_MACHINE (0) #endif +// Whether to include: reset, reset_cause +#ifndef MICROPY_PY_MACHINE_RESET +#define MICROPY_PY_MACHINE_RESET (0) +#endif + +// Maximum number of arguments for machine.freq() +#ifndef MICROPY_PY_MACHINE_FREQ_NUM_ARGS_MAX +#define MICROPY_PY_MACHINE_FREQ_NUM_ARGS_MAX (1) +#endif + // Whether to include: bitstream #ifndef MICROPY_PY_MACHINE_BITSTREAM #define MICROPY_PY_MACHINE_BITSTREAM (0) @@ -1762,6 +2076,16 @@ typedef double mp_float_t; #define MICROPY_PY_MACHINE_PULSE (0) #endif +// Whether to provide the "machine.mem8/16/32" objects +#ifndef MICROPY_PY_MACHINE_MEMX +#define MICROPY_PY_MACHINE_MEMX (MICROPY_PY_MACHINE) +#endif + +// Whether to provide the "machine.Signal" class +#ifndef MICROPY_PY_MACHINE_SIGNAL +#define MICROPY_PY_MACHINE_SIGNAL (MICROPY_PY_MACHINE) +#endif + #ifndef MICROPY_PY_MACHINE_I2C #define MICROPY_PY_MACHINE_I2C (0) #endif @@ -1785,6 +2109,12 @@ typedef double mp_float_t; #define MICROPY_PY_MACHINE_SOFTSPI (0) #endif +// Values of SPI.MSB and SPI.LSB constants +#ifndef MICROPY_PY_MACHINE_SPI_MSB +#define MICROPY_PY_MACHINE_SPI_MSB (0) +#define MICROPY_PY_MACHINE_SPI_LSB (1) +#endif + // Whether to provide the "machine.Timer" class #ifndef MICROPY_PY_MACHINE_TIMER #define MICROPY_PY_MACHINE_TIMER (0) @@ -1799,11 +2129,31 @@ typedef double mp_float_t; #define MICROPY_PY_SSL (0) #endif +// CIRCUITPY-CHANGE: avoid undefined warnings +#ifndef MICROPY_PY_SSL_ECDSA_SIGN_ALT +#define MICROPY_PY_SSL_ECDSA_SIGN_ALT (0) +#endif + // Whether to add finaliser code to ssl objects #ifndef MICROPY_PY_SSL_FINALISER #define MICROPY_PY_SSL_FINALISER (MICROPY_ENABLE_FINALISER) #endif +// Whether to add a root pointer for the current ssl object +#ifndef MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT +#define MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT (MICROPY_PY_SSL_ECDSA_SIGN_ALT) +#endif + +// Whether to support DTLS protocol (non-CPython feature) +#ifndef MICROPY_PY_SSL_DTLS +#define MICROPY_PY_SSL_DTLS (MICROPY_SSL_MBEDTLS && MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_EXTRA_FEATURES) +#endif + +// Whether to provide the "vfs" module +#ifndef MICROPY_PY_VFS +#define MICROPY_PY_VFS (MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_CORE_FEATURES && MICROPY_VFS) +#endif + #ifndef MICROPY_PY_WEBSOCKET #define MICROPY_PY_WEBSOCKET (0) #endif @@ -1891,7 +2241,7 @@ typedef double mp_float_t; /*****************************************************************************/ /* Miscellaneous settings */ -// All uPy objects in ROM must be aligned on at least a 4 byte boundary +// All MicroPython objects in ROM must be aligned on at least a 4 byte boundary // so that the small-int/qstr/pointer distinction can be made. For machines // that don't do this (eg 16-bit CPU), define the following macro to something // like __attribute__((aligned(4))). @@ -1904,6 +2254,7 @@ typedef double mp_float_t; #if MICROPY_PREVIEW_VERSION_2 #define MICROPY_BANNER_NAME_AND_VERSION "MicroPython (with v2.0 preview) " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE #else +// CIRCUITPY-CHANGE: "CircuitPython" #define MICROPY_BANNER_NAME_AND_VERSION "CircuitPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE #endif #endif @@ -1917,12 +2268,6 @@ typedef double mp_float_t; #endif #endif -// Allow to override static modifier for global objects, e.g. to use with -// object code analysis tools which don't support static symbols. -#ifndef STATIC -#define STATIC static -#endif - // Number of bytes in an object word: mp_obj_t, mp_uint_t, mp_uint_t #ifndef MP_BYTES_PER_OBJ_WORD #define MP_BYTES_PER_OBJ_WORD (sizeof(mp_uint_t)) @@ -1971,14 +2316,48 @@ typedef double mp_float_t; #define MICROPY_MAKE_POINTER_CALLABLE(p) (p) #endif -// If these MP_PLAT_*_EXEC macros are overridden then the memory allocated by them -// must be somehow reachable for marking by the GC, since the native code -// generators store pointers to GC managed memory in the code. +// Whether native text/BSS/rodata memory loaded from .mpy files is explicitly tracked +// so that the GC cannot reclaim it. +// +// In general a port should let these options have their defaults, but the defaults here +// can be overridden if needed by defining both MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA +// and MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA. +#ifndef MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA +#if MICROPY_EMIT_MACHINE_CODE && MICROPY_PERSISTENT_CODE_LOAD +// Pointer tracking is required when loading native code is enabled. +#if defined(MP_PLAT_ALLOC_EXEC) || defined(MP_PLAT_COMMIT_EXEC) +// If a port defined a custom allocator or commit function for native text, then the +// text does not need to be tracked (its allocation is managed by the port). But the +// BSS/rodata must be tracked (if there is any) because if there are any pointers to it +// in the function data, they aren't traced by the GC. +#define MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA (0) +#define MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA (1) +#else +// If a port uses the default allocator (the GC heap) then all native text is allocated +// on the GC heap. But it's not guaranteed that a pointer to the head of the block of +// native text (which may contain multiple native functions) will be retained for the GC +// to trace. This is because native functions can start inside the big block of text +// and so it's possible that the only GC-reachable pointers are pointers inside. +// Therefore the big block is explicitly tracked. If there is any BSS/rodata memory, +// then it does not need to be explicitly tracked because a pointer to it is stored into +// the function text via `mp_native_relocate()`. +#define MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA (1) +#define MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA (0) +#endif +#else // MICROPY_EMIT_MACHINE_CODE && MICROPY_PERSISTENT_CODE_LOAD +// Pointer tracking not needed when loading native code is disabled. +#define MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA (0) +#define MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA (0) +#endif +#endif + +// If these macros are defined then the memory allocated by them does not need to be +// traced by the GC. But if they are left undefined then the GC heap will be used as +// the allocator and the memory must be traced by the GC. See also above logic for +// enabling MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA and +// MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA. #ifndef MP_PLAT_ALLOC_EXEC #define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) do { *ptr = m_new(byte, min_size); *size = min_size; } while (0) -#endif - -#ifndef MP_PLAT_FREE_EXEC #define MP_PLAT_FREE_EXEC(ptr, size) m_del(byte, ptr, size) #endif @@ -2001,25 +2380,13 @@ typedef double mp_float_t; #define MP_SSIZE_MAX SSIZE_MAX #endif -// printf format spec to use for mp_int_t and friends -#ifndef INT_FMT -#if defined(__LP64__) -// Archs where mp_int_t == long, long != int -#define UINT_FMT "%lu" -#define INT_FMT "%ld" -#elif defined(_WIN64) -#define UINT_FMT "%llu" -#define INT_FMT "%lld" -#else -// Archs where mp_int_t == int -#define UINT_FMT "%u" -#define INT_FMT "%d" +// Modifier for function which doesn't return +#ifndef MP_NORETURN +#define MP_NORETURN __attribute__((noreturn)) #endif -#endif // INT_FMT -// Modifier for function which doesn't return -#ifndef NORETURN -#define NORETURN __attribute__((noreturn)) +#if !MICROPY_PREVIEW_VERSION_2 +#define NORETURN MP_NORETURN #endif // Modifier for weak functions @@ -2040,6 +2407,12 @@ typedef double mp_float_t; #define MP_INLINE inline MP_NO_INSTRUMENT #endif +// CIRCUITPY-CHANGE +// Modifier for functions whose return value should not be ignored +#ifndef MP_WARN_UNUSED_RESULT +#define MP_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#endif + // Modifier for functions which should be never inlined #ifndef MP_NOINLINE #define MP_NOINLINE __attribute__((noinline)) @@ -2114,4 +2487,23 @@ typedef double mp_float_t; #define MP_WARN_CAT(x) (NULL) #endif +// If true, use __builtin_mul_overflow (a gcc intrinsic supported by clang) for +// overflow checking when multiplying two small ints. Otherwise, use a portable +// algorithm. +// +// Most MCUs have a 32x32->64 bit multiply instruction, in which case the +// intrinsic is likely to be faster and generate smaller code. The main exception is +// cortex-m0 with __ARM_ARCH_ISA_THUMB == 1. +// +// The intrinsic is in GCC starting with version 5. +#ifndef MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC +#if defined(__ARM_ARCH_ISA_THUMB) && (__GNUC__ >= 5) +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (__ARM_ARCH_ISA_THUMB >= 2) +#elif (__GNUC__ >= 5) +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (1) +#else +#define MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC (0) +#endif +#endif + #endif // MICROPY_INCLUDED_PY_MPCONFIG_H diff --git a/py/mperrno.h b/py/mperrno.h index 9e4ecd9419c66..6c675125f4e08 100644 --- a/py/mperrno.h +++ b/py/mperrno.h @@ -143,6 +143,9 @@ #endif +// Type for return values where 0 indicates success and negative values are negated MP_E* error codes. +typedef int mp_negative_errno_t; + #if MICROPY_PY_ERRNO #include "py/obj.h" diff --git a/py/mphal.h b/py/mphal.h index a4f222d0b1e11..3907641be838a 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_MPHAL_H #include +#include #include "py/mpconfig.h" #ifdef MICROPY_MPHALPORT_H @@ -88,6 +89,8 @@ mp_uint_t mp_hal_ticks_cpu(void); uint64_t mp_hal_time_ns(void); #endif +// CIRCUITPY-CHANGE: extmod/virtpin.* not used by CircuitPython +#if 0 // If port HAL didn't define its own pin API, use generic // "virtual pin" API from the core. #ifndef mp_hal_pin_obj_t @@ -97,6 +100,7 @@ uint64_t mp_hal_time_ns(void); #define mp_hal_pin_write(pin, v) mp_virtual_pin_write(pin, v) #include "extmod/virtpin.h" #endif +#endif // Event handling and wait-for-event functions. diff --git a/py/mpprint.c b/py/mpprint.c index 18bc1e5b9b79a..62e80d1e8e85c 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -40,10 +40,22 @@ #include "py/formatfloat.h" #endif -static const char pad_spaces[] = " "; -static const char pad_zeroes[] = "0000000000000000"; - -STATIC void plat_print_strn(void *env, const char *str, size_t len) { +static const char pad_spaces[16] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '}; +#define pad_spaces_size (sizeof(pad_spaces)) +static const char pad_common[23] = {'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '_', '0', '0', '0', ',', '0', '0'}; +// The contents of pad_common is arranged to provide the following padding +// strings with minimal flash size: +// 0000000000000000 <- pad_zeroes +// 0000_000 <- pad_zeroes_underscore (offset: 12, size 5) +// 000,00 <- pad_zeroes_comma (offset: 17, size 4) +#define pad_zeroes (pad_common + 0) +#define pad_zeroes_size (16) +#define pad_zeroes_underscore (pad_common + 12) +#define pad_zeroes_underscore_size (5) +#define pad_zeroes_comma (pad_common + 17) +#define pad_zeroes_comma_size (4) + +static void plat_print_strn(void *env, const char *str, size_t len) { (void)env; MP_PLAT_PRINT_STRN(str, len); } @@ -58,20 +70,37 @@ int mp_print_str(const mp_print_t *print, const char *str) { return len; } -int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width) { +int mp_print_strn(const mp_print_t *print, const char *str, size_t len, unsigned int flags, char fill, int width) { int left_pad = 0; int right_pad = 0; int pad = width - len; int pad_size; int total_chars_printed = 0; const char *pad_chars; + char grouping = flags >> PF_FLAG_SEP_POS; if (!fill || fill == ' ') { pad_chars = pad_spaces; - pad_size = sizeof(pad_spaces) - 1; - } else if (fill == '0') { + pad_size = pad_spaces_size; + } else if (fill == '0' && !grouping) { pad_chars = pad_zeroes; - pad_size = sizeof(pad_zeroes) - 1; + pad_size = pad_zeroes_size; + } else if (fill == '0') { + if (grouping == '_') { + pad_chars = pad_zeroes_underscore; + pad_size = pad_zeroes_underscore_size; + } else { + pad_chars = pad_zeroes_comma; + pad_size = pad_zeroes_comma_size; + } + // The result will never start with a grouping character. An extra leading zero is added. + // width is dead after this so we can use it in calculation + if (width % pad_size == 0) { + pad++; + width++; + } + // position the grouping character correctly within the pad repetition + pad_chars += pad_size - 1 - width % pad_size; } else { // Other pad characters are fairly unusual, so we'll take the hit // and output them 1 at a time. @@ -127,7 +156,7 @@ int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flag // This function is used exclusively by mp_vprintf to format ints. // It needs to be a separate function to mp_print_mp_int, since converting to a mp_int looses the MSB. -STATIC int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) { +static int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, int base_char, int flags, char fill, int width) { char sign = 0; if (sgn) { if ((mp_int_t)x < 0) { @@ -201,7 +230,7 @@ STATIC int mp_print_int(const mp_print_t *print, mp_uint_t x, int sgn, int base, return len; } -int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec) { +int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, unsigned int base, int base_char, int flags, char fill, int width, int prec) { // These are the only values for "base" that are required to be supported by this // function, since Python only allows the user to format integers in these bases. // If needed this function could be generalised to handle other values. @@ -248,10 +277,7 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char int prefix_len = prefix - prefix_buf; prefix = prefix_buf; - char comma = '\0'; - if (flags & PF_FLAG_SHOW_COMMA) { - comma = ','; - } + char comma = flags >> PF_FLAG_SEP_POS; // The size of this buffer is rather arbitrary. If it's not large // enough, a dynamic one will be allocated. @@ -340,8 +366,8 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char } #if MICROPY_PY_BUILTINS_FLOAT -int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec) { - char buf[32]; +int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, unsigned int flags, char fill, int width, int prec) { + char buf[36]; char sign = '\0'; int chrs = 0; @@ -352,11 +378,17 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c sign = ' '; } - int len = mp_format_float(f, buf, sizeof(buf), fmt, prec, sign); + int len = mp_format_float(f, buf, sizeof(buf) - 3, fmt, prec, sign); char *s = buf; - if ((flags & PF_FLAG_ADD_PERCENT) && (size_t)(len + 1) < sizeof(buf)) { + if ((flags & PF_FLAG_ALWAYS_DECIMAL) && strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { + buf[len++] = '.'; + buf[len++] = '0'; + buf[len] = '\0'; + } + + if (flags & PF_FLAG_ADD_PERCENT) { buf[len++] = '%'; buf[len] = '\0'; } @@ -376,14 +408,6 @@ int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, c } #endif -// CIRCUITPY-CHANGE -static int print_str_common(const mp_print_t *print, const char *str, int prec, size_t len, int flags, int fill, int width) { - if (prec >= 0 && (size_t)prec < len) { - len = prec; - } - return mp_print_strn(print, str, len, flags, fill, width); -} - int mp_printf(const mp_print_t *print, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -424,8 +448,6 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { flags |= PF_FLAG_SHOW_SIGN; } else if (*fmt == ' ') { flags |= PF_FLAG_SPACE_SIGN; - } else if (*fmt == '!') { - flags |= PF_FLAG_NO_TRAILZ; } else if (*fmt == '0') { flags |= PF_FLAG_PAD_AFTER_SIGN; fill = '0'; @@ -459,16 +481,36 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { } } - // parse long specifiers (only for LP64 model where they make a difference) - #ifndef __LP64__ - const + // parse long and long long specifiers (only where they make a difference) + #if (MP_INT_MAX > INT_MAX && MP_INT_MAX == LONG_MAX) || defined(MICROPY_UNIX_COVERAGE) + #define SUPPORT_L_FORMAT (1) + #else + #define SUPPORT_L_FORMAT (0) #endif + #if SUPPORT_L_FORMAT bool long_arg = false; + #endif + + #if (MP_INT_MAX > LONG_MAX) || defined(MICROPY_UNIX_COVERAGE) + #define SUPPORT_LL_FORMAT (1) + #else + #define SUPPORT_LL_FORMAT (0) + #endif + #if SUPPORT_LL_FORMAT + bool long_long_arg = false; + #endif + if (*fmt == 'l') { ++fmt; - #ifdef __LP64__ + #if SUPPORT_L_FORMAT long_arg = true; #endif + #if SUPPORT_LL_FORMAT + if (*fmt == 'l') { + ++fmt; + long_long_arg = true; + } + #endif } if (*fmt == '\0') { @@ -492,27 +534,19 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { qstr qst = va_arg(args, qstr); size_t len; const char *str = (const char *)qstr_data(qst, &len); - // CIRCUITPY-CHANGE - chrs += print_str_common(print, str, prec, len, flags, fill, width); - break; - } - // CIRCUITPY-CHANGE: new code to print compressed strings - case 'S': { - mp_rom_error_text_t arg = va_arg(args, mp_rom_error_text_t); - size_t len_with_nul = decompress_length(arg); - size_t len = len_with_nul - 1; - char str[len_with_nul]; - decompress(arg, str); - chrs += print_str_common(print, str, prec, len, flags, fill, width); + if (prec >= 0 && (size_t)prec < len) { + len = prec; + } + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } case 's': { const char *str = va_arg(args, const char *); #ifndef NDEBUG // With debugging enabled, catch printing of null string pointers - if (str == NULL) { - // CIRCUITPY-CHANGE - str = "(null)"; + if (prec != 0 && str == NULL) { + chrs += mp_print_strn(print, "(null)", 6, flags, fill, width); + break; } #endif size_t len = strlen(str); @@ -522,41 +556,58 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { chrs += mp_print_strn(print, str, len, flags, fill, width); break; } - case 'd': { - mp_int_t val; - if (long_arg) { - val = va_arg(args, long int); - } else { - val = va_arg(args, int); - } - chrs += mp_print_int(print, val, 1, 10, 'a', flags, fill, width); - break; - } + case 'd': + case 'p': + case 'P': case 'u': case 'x': case 'X': { - int base = 16 - ((*fmt + 1) & 6); // maps char u/x/X to base 10/16/16 - char fmt_c = (*fmt & 0xf0) - 'P' + 'A'; // maps char u/x/X to char a/a/A + char fmt_chr = *fmt; mp_uint_t val; - if (long_arg) { - val = va_arg(args, unsigned long int); + if (fmt_chr == 'p' || fmt_chr == 'P') { + val = va_arg(args, uintptr_t); + } + #if SUPPORT_LL_FORMAT + else if (long_long_arg) { + val = va_arg(args, unsigned long long); + } + #endif + #if SUPPORT_L_FORMAT + else if (long_arg) { + if (sizeof(long) != sizeof(mp_uint_t) && fmt_chr == 'd') { + val = va_arg(args, long); + } else { + val = va_arg(args, unsigned long); + } + } + #endif + else { + if (sizeof(int) != sizeof(mp_uint_t) && fmt_chr == 'd') { + val = va_arg(args, int); + } else { + val = va_arg(args, unsigned); + } + } + int base; + // Map format char x/p/X/P to a/a/A/A for hex letters. + // It doesn't matter what d/u map to. + char fmt_c = (fmt_chr & 0xf0) - 'P' + 'A'; + if (fmt_chr == 'd' || fmt_chr == 'u') { + base = 10; } else { - val = va_arg(args, unsigned int); + base = 16; } - chrs += mp_print_int(print, val, 0, base, fmt_c, flags, fill, width); + // CIRCUITPY-CHANGE: include "0x" for 'p' and 'P'. + if (fmt_chr == 'p' || fmt_chr == 'P') { + #if SUPPORT_INT_BASE_PREFIX + chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags | PF_FLAG_SHOW_PREFIX, fill, width); + #else + chrs += mp_print_strn(print, "0x", 2, flags, fill, width); + #endif + } + chrs += mp_print_int(print, val, fmt_chr == 'd', base, fmt_c, flags, fill, width); break; } - case 'p': - case 'P': // don't bother to handle upcase for 'P' - // Use unsigned long int to work on both ILP32 and LP64 systems - // CIRCUITPY-CHANGE: print 0x prefix - #if SUPPORT_INT_BASE_PREFIX - chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags | PF_FLAG_SHOW_PREFIX, fill, width); - #else - print->print_strn(print->data, "0x", 2); - chrs += mp_print_int(print, va_arg(args, unsigned long int), 0, 16, 'a', flags, fill, width) + 2; - #endif - break; #if MICROPY_PY_BUILTINS_FLOAT case 'e': case 'E': @@ -573,18 +624,21 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) { break; } #endif - // Because 'l' is eaten above, another 'l' means %ll. We need to support - // this length specifier for OBJ_REPR_D (64-bit NaN boxing). - // TODO Either enable this unconditionally, or provide a specific config var. - #if (MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D) || defined(_WIN64) - case 'l': { - unsigned long long int arg_value = va_arg(args, unsigned long long int); - ++fmt; - assert(*fmt == 'u' || *fmt == 'd' || !"unsupported fmt char"); - chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width); + + // CIRCUITPY-CHANGE: new format code to print compressed strings + case 'S': { + mp_rom_error_text_t arg = va_arg(args, mp_rom_error_text_t); + size_t len_with_nul = decompress_length(arg); + size_t len = len_with_nul - 1; + char str[len_with_nul]; + decompress(arg, str); + if (prec >= 0 && (size_t)prec < len) { + len = prec; + } + chrs += mp_print_strn(print, str, len, flags, fill, width); break; } - #endif + default: // if it's not %% then it's an unsupported format character assert(*fmt == '%' || !"unsupported fmt char"); diff --git a/py/mpprint.h b/py/mpprint.h index e883cc27047f1..614c61ea41537 100644 --- a/py/mpprint.h +++ b/py/mpprint.h @@ -31,13 +31,13 @@ #define PF_FLAG_LEFT_ADJUST (0x001) #define PF_FLAG_SHOW_SIGN (0x002) #define PF_FLAG_SPACE_SIGN (0x004) -#define PF_FLAG_NO_TRAILZ (0x008) -#define PF_FLAG_SHOW_PREFIX (0x010) -#define PF_FLAG_SHOW_COMMA (0x020) -#define PF_FLAG_PAD_AFTER_SIGN (0x040) -#define PF_FLAG_CENTER_ADJUST (0x080) -#define PF_FLAG_ADD_PERCENT (0x100) -#define PF_FLAG_SHOW_OCTAL_LETTER (0x200) +#define PF_FLAG_SHOW_PREFIX (0x008) +#define PF_FLAG_PAD_AFTER_SIGN (0x010) +#define PF_FLAG_CENTER_ADJUST (0x020) +#define PF_FLAG_ADD_PERCENT (0x040) +#define PF_FLAG_SHOW_OCTAL_LETTER (0x080) +#define PF_FLAG_ALWAYS_DECIMAL (0x100) +#define PF_FLAG_SEP_POS (9) // must be above all the above PF_FLAGs #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES #define MP_PYTHON_PRINTER &mp_sys_stdout_print @@ -69,9 +69,9 @@ extern const mp_print_t mp_sys_stdout_print; #endif int mp_print_str(const mp_print_t *print, const char *str); -int mp_print_strn(const mp_print_t *print, const char *str, size_t len, int flags, char fill, int width); +int mp_print_strn(const mp_print_t *print, const char *str, size_t len, unsigned int flags, char fill, int width); #if MICROPY_PY_BUILTINS_FLOAT -int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, int flags, char fill, int width, int prec); +int mp_print_float(const mp_print_t *print, mp_float_t f, char fmt, unsigned int flags, char fill, int width, int prec); #endif int mp_printf(const mp_print_t *print, const char *fmt, ...); diff --git a/py/mpstate.h b/py/mpstate.h index 1898982e1c1eb..7934e843f0651 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George + * Copyright (c) 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -71,6 +71,12 @@ enum { // This structure contains dynamic configuration for the compiler. #if MICROPY_DYNAMIC_COMPILER typedef struct mp_dynamic_compiler_t { + // This is used to let mpy-cross pass options to the emitter chosen with + // `native_arch`. The main use case for the time being is to give the + // RV32 emitter extended information about which extensions can be + // optionally used, in order to generate code that's better suited for the + // hardware platform the code will run on. + void *backend_options; uint8_t small_int_bits; // must be <= host small_int_bits uint8_t native_arch; uint8_t nlr_buf_num_regs; @@ -88,6 +94,18 @@ typedef struct _mp_sched_item_t { mp_obj_t arg; } mp_sched_item_t; +// gc_lock_depth field is a combination of the GC_COLLECT_FLAG +// bit and a lock depth shifted GC_LOCK_DEPTH_SHIFT bits left. +#if MICROPY_ENABLE_FINALISER +#define GC_COLLECT_FLAG 1 +#define GC_LOCK_DEPTH_SHIFT 1 +#else +// If finalisers are disabled then this check doesn't matter, as gc_lock() +// is called anywhere else that heap can't be changed. So save some code size. +#define GC_COLLECT_FLAG 0 +#define GC_LOCK_DEPTH_SHIFT 0 +#endif + // This structure holds information about a single contiguous area of // memory reserved for the memory manager. typedef struct _mp_state_mem_area_t { @@ -100,6 +118,10 @@ typedef struct _mp_state_mem_area_t { #if MICROPY_ENABLE_FINALISER byte *gc_finaliser_table_start; #endif + // CIRCUITPY-CHANGE + #if MICROPY_ENABLE_SELECTIVE_COLLECT + byte *gc_collect_table_start; + #endif byte *gc_pool_start; byte *gc_pool_end; @@ -144,11 +166,8 @@ typedef struct _mp_state_mem_t { #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL // This is a global mutex used to make the GC thread-safe. - mp_thread_mutex_t gc_mutex; + mp_thread_recursive_mutex_t gc_mutex; #endif - - // CIRCUITPY-CHANGE - void **permanent_pointers; } mp_state_mem_t; // This structure hold runtime and VM information. It includes a section @@ -295,6 +314,7 @@ typedef struct _mp_state_thread_t { #endif // Locking of the GC is done per thread. + // See GC_LOCK_DEPTH_SHIFT for an explanation of this field. uint16_t gc_lock_depth; //////////////////////////////////////////////////////////// @@ -321,6 +341,10 @@ typedef struct _mp_state_thread_t { struct _mp_code_state_t *current_code_state; #endif + #if MICROPY_PY_SSL_MBEDTLS_NEED_ACTIVE_CONTEXT + struct _mp_obj_ssl_context_t *tls_ssl_context; + #endif + // CIRCUITPY-CHANGE #if CIRCUITPY_WARNINGS warnings_action_t warnings_action; @@ -342,6 +366,7 @@ extern mp_state_ctx_t mp_state_ctx; #define MP_STATE_MAIN_THREAD(x) (mp_state_ctx.thread.x) #if MICROPY_PY_THREAD +// CIRCUITPY-CHANGE: explicit declaration extern mp_state_thread_t *mp_thread_get_state(void); #define MP_STATE_THREAD(x) (mp_thread_get_state()->x) #define mp_thread_is_main_thread() (mp_thread_get_state() == &mp_state_ctx.thread) @@ -350,4 +375,7 @@ extern mp_state_thread_t *mp_thread_get_state(void); #define mp_thread_is_main_thread() (true) #endif +// CIRCUITPY-CHANGE: defined in main.c +bool vm_is_running(void); + #endif // MICROPY_INCLUDED_PY_MPSTATE_H diff --git a/py/mpthread.h b/py/mpthread.h index f335cc02911fc..795f230bb4a0c 100644 --- a/py/mpthread.h +++ b/py/mpthread.h @@ -48,6 +48,12 @@ void mp_thread_mutex_init(mp_thread_mutex_t *mutex); int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait); void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex); +#if MICROPY_PY_THREAD_RECURSIVE_MUTEX +void mp_thread_recursive_mutex_init(mp_thread_recursive_mutex_t *mutex); +int mp_thread_recursive_mutex_lock(mp_thread_recursive_mutex_t *mutex, int wait); +void mp_thread_recursive_mutex_unlock(mp_thread_recursive_mutex_t *mutex); +#endif + #endif // MICROPY_PY_THREAD #if MICROPY_PY_THREAD && MICROPY_PY_THREAD_GIL diff --git a/py/mpz.c b/py/mpz.c index 6317d93d4cb26..74fd175463600 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -49,7 +49,7 @@ Definition of normalise: ? */ -STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) { +static size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) { for (--idig; idig >= oidig && *idig == 0; --idig) { } return idig + 1 - oidig; @@ -59,7 +59,7 @@ STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) { returns sign(i - j) assumes i, j are normalised */ -STATIC int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, size_t jlen) { +static int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, size_t jlen) { if (ilen < jlen) { return -1; } @@ -85,7 +85,7 @@ STATIC int mpn_cmp(const mpz_dig_t *idig, size_t ilen, const mpz_dig_t *jdig, si assumes enough memory in i; assumes normalised j; assumes n > 0 can have i, j pointing to same memory */ -STATIC size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { +static size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { mp_uint_t n_whole = (n + DIG_SIZE - 1) / DIG_SIZE; mp_uint_t n_part = n % DIG_SIZE; if (n_part == 0) { @@ -124,7 +124,7 @@ STATIC size_t mpn_shl(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n assumes enough memory in i; assumes normalised j; assumes n > 0 can have i, j pointing to same memory */ -STATIC size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { +static size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n) { mp_uint_t n_whole = n / DIG_SIZE; mp_uint_t n_part = n % DIG_SIZE; @@ -156,7 +156,7 @@ STATIC size_t mpn_shr(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mp_uint_t n assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ -STATIC size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { +static size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carry = 0; @@ -186,7 +186,7 @@ STATIC size_t mpn_add(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const assumes enough memory in i; assumes normalised j, k; assumes j >= k can have i, j, k pointing to same memory */ -STATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { +static size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; mpz_dbl_dig_signed_t borrow = 0; @@ -214,7 +214,7 @@ STATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen (jlen argument not needed) can have i, j, k pointing to same memory */ -STATIC size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, size_t klen) { +static size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; for (; klen > 0; --klen, ++idig, ++jdig, ++kdig) { @@ -235,7 +235,7 @@ STATIC size_t mpn_and(mpz_dig_t *idig, const mpz_dig_t *jdig, const mpz_dig_t *k assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ -STATIC size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, +static size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; @@ -266,7 +266,7 @@ STATIC size_t mpn_and_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, c assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ -STATIC size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { +static size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; jlen -= klen; @@ -296,7 +296,7 @@ STATIC size_t mpn_or(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const #if MICROPY_OPT_MPZ_BITWISE -STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, +static size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carryi = 1; @@ -326,7 +326,7 @@ STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, co #else -STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, +static size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; mpz_dig_t imask = (0 == carryi) ? 0 : DIG_MASK; @@ -358,7 +358,7 @@ STATIC size_t mpn_or_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, co assumes enough memory in i; assumes normalised j, k; assumes jlen >= klen can have i, j, k pointing to same memory */ -STATIC size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { +static size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; jlen -= klen; @@ -385,7 +385,7 @@ STATIC size_t mpn_xor(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const assumes enough memory in i; assumes normalised j, k; assumes length j >= length k can have i, j, k pointing to same memory */ -STATIC size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, +static size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const mpz_dig_t *kdig, size_t klen, mpz_dbl_dig_t carryi, mpz_dbl_dig_t carryj, mpz_dbl_dig_t carryk) { mpz_dig_t *oidig = idig; @@ -410,7 +410,7 @@ STATIC size_t mpn_xor_neg(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, c returns number of digits in i assumes enough memory in i; assumes normalised i; assumes dmul != 0 */ -STATIC size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) { +static size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, mpz_dig_t dadd) { mpz_dig_t *oidig = idig; mpz_dbl_dig_t carry = dadd; @@ -432,7 +432,7 @@ STATIC size_t mpn_mul_dig_add_dig(mpz_dig_t *idig, size_t ilen, mpz_dig_t dmul, assumes enough memory in i; assumes i is zeroed; assumes normalised j, k can have j, k point to same memory */ -STATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t *kdig, size_t klen) { +static size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t *kdig, size_t klen) { mpz_dig_t *oidig = idig; size_t ilen = 0; @@ -452,7 +452,7 @@ STATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t * } ilen = id - oidig; - // CIRCUITPY-CHANGE: check to prevent usb starvation + // CIRCUITPY-CHANGE: prevent usb and other background task starvation #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; #endif @@ -467,7 +467,7 @@ STATIC size_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, size_t jlen, mpz_dig_t * assumes quo_dig has enough memory (as many digits as num) assumes quo_dig is filled with zeros */ -STATIC void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_dig, size_t den_len, mpz_dig_t *quo_dig, size_t *quo_len) { +static void mpn_div(mpz_dig_t *num_dig, size_t *num_len, const mpz_dig_t *den_dig, size_t den_len, mpz_dig_t *quo_dig, size_t *quo_len) { mpz_dig_t *orig_num_dig = num_dig; mpz_dig_t *orig_quo_dig = quo_dig; mpz_dig_t norm_shift = 0; @@ -672,14 +672,14 @@ mpz_t *mpz_from_str(const char *str, size_t len, bool neg, unsigned int base) { } #endif -STATIC void mpz_free(mpz_t *z) { +static void mpz_free(mpz_t *z) { if (z != NULL) { m_del(mpz_dig_t, z->dig, z->alloc); m_del_obj(mpz_t, z); } } -STATIC void mpz_need_dig(mpz_t *z, size_t need) { +static void mpz_need_dig(mpz_t *z, size_t need) { if (need < MIN_ALLOC) { need = MIN_ALLOC; } @@ -693,7 +693,7 @@ STATIC void mpz_need_dig(mpz_t *z, size_t need) { } } -STATIC mpz_t *mpz_clone(const mpz_t *src) { +static mpz_t *mpz_clone(const mpz_t *src) { assert(src->alloc != 0); mpz_t *z = m_new_obj(mpz_t); z->neg = src->neg; @@ -1541,7 +1541,8 @@ mp_int_t mpz_hash(const mpz_t *z) { mp_uint_t val = 0; mpz_dig_t *d = z->dig + z->len; - while (d-- > z->dig) { + while (d > z->dig) { + d--; val = (val << DIG_SIZE) | *d; } @@ -1556,11 +1557,12 @@ bool mpz_as_int_checked(const mpz_t *i, mp_int_t *value) { mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { if (val > (~(MP_OBJ_WORD_MSBIT_HIGH) >> DIG_SIZE)) { // will overflow return false; } + d--; val = (val << DIG_SIZE) | *d; } @@ -1581,11 +1583,12 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { mp_uint_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { if (val > (~(MP_OBJ_WORD_MSBIT_HIGH) >> (DIG_SIZE - 1))) { // will overflow return false; } + d--; val = (val << DIG_SIZE) | *d; } @@ -1593,7 +1596,7 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) { return true; } -void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) { +bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf) { byte *b = buf; if (big_endian) { b += len; @@ -1602,6 +1605,8 @@ void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) { int bits = 0; mpz_dbl_dig_t d = 0; mpz_dbl_dig_t carry = 1; + size_t olen = len; // bytes in output buffer + bool ok = true; for (size_t zlen = z->len; zlen > 0; --zlen) { bits += DIG_SIZE; d = (d << DIG_SIZE) | *zdig++; @@ -1611,28 +1616,32 @@ void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) { val = (~val & 0xff) + carry; carry = val >> 8; } + + if (!olen) { + // Buffer is full, only OK if all remaining bytes are zeroes + ok = ok && ((byte)val == 0); + continue; + } + if (big_endian) { *--b = val; - if (b == buf) { - return; - } } else { *b++ = val; - if (b == buf + len) { - return; - } } + olen--; } } - // fill remainder of buf with zero/sign extension of the integer - if (big_endian) { - len = b - buf; + if (as_signed && olen == 0 && len > 0) { + // If output exhausted then ensure there was enough space for the sign bit + byte most_sig = big_endian ? buf[0] : buf[len - 1]; + ok = ok && (bool)(most_sig & 0x80) == (bool)z->neg; } else { - len = buf + len - b; - buf = b; + // fill remainder of buf with zero/sign extension of the integer + memset(big_endian ? buf : b, z->neg ? 0xff : 0x00, olen); } - memset(buf, z->neg ? 0xff : 0x00, len); + + return ok; } #if MICROPY_PY_BUILTINS_FLOAT @@ -1640,7 +1649,8 @@ mp_float_t mpz_as_float(const mpz_t *i) { mp_float_t val = 0; mpz_dig_t *d = i->dig + i->len; - while (d-- > i->dig) { + while (d > i->dig) { + d--; val = val * DIG_BASE + *d; } @@ -1670,6 +1680,8 @@ size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, ch size_t ilen = i->len; + int n_comma = (base == 10) ? 3 : 4; + char *s = str; if (ilen == 0) { if (prefix) { @@ -1715,7 +1727,7 @@ size_t mpz_as_str_inpl(const mpz_t *i, unsigned int base, const char *prefix, ch break; } } - if (comma && (s - last_comma) == 3) { + if (!done && comma && (s - last_comma) == n_comma) { *s++ = comma; last_comma = s; } diff --git a/py/mpz.h b/py/mpz.h index f205e3cd158a1..0422b014a3350 100644 --- a/py/mpz.h +++ b/py/mpz.h @@ -93,9 +93,9 @@ typedef int8_t mpz_dbl_dig_signed_t; typedef struct _mpz_t { // Zero has neg=0, len=0. Negative zero is not allowed. size_t neg : 1; - size_t fixed_dig : 1; - size_t alloc : (8 * sizeof(size_t) - 2); - size_t len; + size_t fixed_dig : 1; // flag, 'dig' buffer cannot be reallocated + size_t alloc : (8 * sizeof(size_t) - 2); // number of entries allocated in 'dig' + size_t len; // number of entries used in 'dig' mpz_dig_t *dig; } mpz_t; @@ -153,7 +153,8 @@ static inline size_t mpz_num_bits(const mpz_t *z) { mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); -void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf); +// Returns true if 'z' fit into 'len' bytes of 'buf' without overflowing, 'buf' is truncated otherwise. +bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf); #if MICROPY_PY_BUILTINS_FLOAT mp_float_t mpz_as_float(const mpz_t *z); #endif diff --git a/py/nativeglue.c b/py/nativeglue.c index 4df7fbcd0729d..3b072ba8c38d5 100644 --- a/py/nativeglue.c +++ b/py/nativeglue.c @@ -29,6 +29,7 @@ #include #include +#include "py/binary.h" #include "py/runtime.h" #include "py/smallint.h" #include "py/nativeglue.h" @@ -141,7 +142,7 @@ mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) { } #endif -STATIC mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { +static mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { if (new_globals == NULL) { // Globals were the originally the same so don't restore them return NULL; @@ -157,20 +158,20 @@ STATIC mp_obj_dict_t *mp_native_swap_globals(mp_obj_dict_t *new_globals) { // wrapper that accepts n_args and n_kw in one argument // (native emitter can only pass at most 3 arguments to a function) -STATIC mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { +static mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args) { return mp_call_function_n_kw(fun_in, n_args_kw & 0xff, (n_args_kw >> 8) & 0xff, args); } // wrapper that makes raise obj and raises it // END_FINALLY opcode requires that we don't raise if o==None -STATIC void mp_native_raise(mp_obj_t o) { +static void mp_native_raise(mp_obj_t o) { if (o != MP_OBJ_NULL && o != mp_const_none) { nlr_raise(mp_make_raise_obj(o)); } } // wrapper that handles iterator buffer -STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) { +static mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) { if (iter == NULL) { return mp_getiter(obj, NULL); } else { @@ -185,7 +186,7 @@ STATIC mp_obj_t mp_native_getiter(mp_obj_t obj, mp_obj_iter_buf_t *iter) { } // wrapper that handles iterator buffer -STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { +static mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { mp_obj_t obj; if (iter->base.type == MP_OBJ_NULL) { obj = iter->buf[0]; @@ -195,7 +196,7 @@ STATIC mp_obj_t mp_native_iternext(mp_obj_iter_buf_t *iter) { return mp_iternext(obj); } -STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) { +static bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *ret_value) { mp_vm_return_kind_t ret_kind; nlr_buf_t nlr_buf; mp_obj_t throw_value = *ret_value; @@ -233,22 +234,22 @@ STATIC bool mp_native_yield_from(mp_obj_t gen, mp_obj_t send_value, mp_obj_t *re #if !MICROPY_PY_BUILTINS_FLOAT -STATIC mp_obj_t mp_obj_new_float_from_f(float f) { +static mp_obj_t mp_obj_new_float_from_f(float f) { (void)f; mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported")); } -STATIC mp_obj_t mp_obj_new_float_from_d(double d) { +static mp_obj_t mp_obj_new_float_from_d(double d) { (void)d; mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported")); } -STATIC float mp_obj_get_float_to_f(mp_obj_t o) { +static float mp_obj_get_float_to_f(mp_obj_t o) { (void)o; mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported")); } -STATIC double mp_obj_get_float_to_d(mp_obj_t o) { +static double mp_obj_get_float_to_d(mp_obj_t o) { (void)o; mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("float unsupported")); } @@ -283,7 +284,7 @@ const mp_fun_table_t mp_fun_table = { mp_obj_set_store, mp_obj_list_append, mp_obj_dict_store, - mp_make_function_from_raw_code, + mp_make_function_from_proto_fun, mp_native_call_function_n_kw, mp_call_method_n_kw, mp_call_method_n_kw_var, @@ -321,7 +322,7 @@ const mp_fun_table_t mp_fun_table = { gc_realloc, mp_printf, mp_vprintf, - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: mp_raise_msg_str instead of mp_raise_msg mp_raise_msg_str, mp_obj_get_type, mp_obj_new_str, @@ -331,10 +332,16 @@ const mp_fun_table_t mp_fun_table = { mp_obj_new_float_from_d, mp_obj_get_float_to_f, mp_obj_get_float_to_d, + mp_load_method_maybe, mp_get_buffer, mp_get_stream_raise, - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: add mp_obj_assert_native_inited mp_obj_assert_native_inited, + mp_arg_parse_all, + mp_arg_parse_all_kw_array, + mp_binary_get_size, + mp_binary_get_val_array, + mp_binary_set_val_array, &mp_plat_print, &mp_type_type, &mp_type_str, @@ -345,6 +352,7 @@ const mp_fun_table_t mp_fun_table = { &mp_type_fun_builtin_2, &mp_type_fun_builtin_3, &mp_type_fun_builtin_var, + &mp_type_Exception, &mp_stream_read_obj, &mp_stream_readinto_obj, &mp_stream_unbuffered_readline_obj, diff --git a/py/nativeglue.h b/py/nativeglue.h index 407fd4c637ae2..01825ac60edb4 100644 --- a/py/nativeglue.h +++ b/py/nativeglue.h @@ -58,7 +58,7 @@ typedef enum { MP_F_STORE_SET, MP_F_LIST_APPEND, MP_F_STORE_MAP, - MP_F_MAKE_FUNCTION_FROM_RAW_CODE, + MP_F_MAKE_FUNCTION_FROM_PROTO_FUN, MP_F_NATIVE_CALL_FUNCTION_N_KW, MP_F_CALL_METHOD_N_KW, MP_F_CALL_METHOD_N_KW_VAR, @@ -112,7 +112,7 @@ typedef struct _mp_fun_table_t { void (*set_store)(mp_obj_t self_in, mp_obj_t item); mp_obj_t (*list_append)(mp_obj_t self_in, mp_obj_t arg); mp_obj_t (*dict_store)(mp_obj_t self_in, mp_obj_t key, mp_obj_t value); - mp_obj_t (*make_function_from_raw_code)(const mp_raw_code_t *rc, const mp_module_context_t *cm, const mp_obj_t *def_args); + mp_obj_t (*make_function_from_proto_fun)(mp_proto_fun_t proto_fun, const mp_module_context_t *cm, const mp_obj_t *def_args); mp_obj_t (*call_function_n_kw)(mp_obj_t fun_in, size_t n_args_kw, const mp_obj_t *args); mp_obj_t (*call_method_n_kw)(size_t n_args, size_t n_kw, const mp_obj_t *args); mp_obj_t (*call_method_n_kw_var)(bool have_self, size_t n_args_n_kw, const mp_obj_t *args); @@ -143,9 +143,9 @@ typedef struct _mp_fun_table_t { int (*printf_)(const mp_print_t *print, const char *fmt, ...); int (*vprintf_)(const mp_print_t *print, const char *fmt, va_list args); #if defined(__GNUC__) - NORETURN // Only certain compilers support no-return attributes in function pointer declarations + MP_NORETURN // Only certain compilers support no-return attributes in function pointer declarations #endif - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: raise_msg_str instead of raise_msg void (*raise_msg_str)(const mp_obj_type_t *exc_type, const char *msg); const mp_obj_type_t *(*obj_get_type)(mp_const_obj_t o_in); mp_obj_t (*obj_new_str)(const char *data, size_t len); @@ -155,11 +155,19 @@ typedef struct _mp_fun_table_t { mp_obj_t (*obj_new_float_from_d)(double d); float (*obj_get_float_to_f)(mp_obj_t o); double (*obj_get_float_to_d)(mp_obj_t o); + void (*load_method_maybe)(mp_obj_t base, qstr attr, mp_obj_t *dest); bool (*get_buffer)(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags); const mp_stream_p_t *(*get_stream_raise)(mp_obj_t self_in, int flags); // CIRCUITPY-CHANGE void (*assert_native_inited)(mp_obj_t native_object); + void (*arg_parse_all)(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); + void (*arg_parse_all_kw_array)(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); + size_t (*binary_get_size)(char struct_type, char val_type, size_t *palign); + mp_obj_t (*binary_get_val_array)(char typecode, void *p, size_t index); + void (*binary_set_val_array)(char typecode, void *p, size_t index, mp_obj_t val_in); const mp_print_t *plat_print; + // The following entries start at index 73 and are referenced by tools-mpy_ld.py, + // see constant MP_FUN_TABLE_MP_TYPE_TYPE_OFFSET. const mp_obj_type_t *type_type; const mp_obj_type_t *type_str; const mp_obj_type_t *type_list; @@ -169,6 +177,7 @@ typedef struct _mp_fun_table_t { const mp_obj_type_t *type_fun_builtin_2; const mp_obj_type_t *type_fun_builtin_3; const mp_obj_type_t *type_fun_builtin_var; + const mp_obj_type_t *type_Exception; const mp_obj_fun_builtin_var_t *stream_read_obj; const mp_obj_fun_builtin_var_t *stream_readinto_obj; const mp_obj_fun_builtin_var_t *stream_unbuffered_readline_obj; diff --git a/py/nlr.c b/py/nlr.c index 516b8b86276b2..de2a38ceff3e9 100644 --- a/py/nlr.c +++ b/py/nlr.c @@ -28,8 +28,7 @@ #if !MICROPY_NLR_SETJMP // When not using setjmp, nlr_push_tail is called from inline asm so needs special care -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_X86) && MICROPY_NLR_X86 && defined(MICROPY_NLR_OS_WINDOWS) && MICROPY_NLR_OS_WINDOWS +#if MICROPY_NLR_X86 && MICROPY_NLR_OS_WINDOWS // On these 32-bit platforms make sure nlr_push_tail doesn't have a leading underscore unsigned int nlr_push_tail(nlr_buf_t *nlr) asm ("nlr_push_tail"); #else @@ -82,7 +81,7 @@ void nlr_call_jump_callbacks(nlr_buf_t *nlr) { } #if MICROPY_ENABLE_VM_ABORT -NORETURN void nlr_jump_abort(void) { +MP_NORETURN void nlr_jump_abort(void) { MP_STATE_THREAD(nlr_top) = MP_STATE_VM(nlr_abort); nlr_jump(NULL); } diff --git a/py/nlr.h b/py/nlr.h index 15f883422f5fc..446e78c7ebbf7 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -44,6 +44,8 @@ #define MICROPY_NLR_NUM_REGS_MIPS (13) #define MICROPY_NLR_NUM_REGS_XTENSA (10) #define MICROPY_NLR_NUM_REGS_XTENSAWIN (17) +#define MICROPY_NLR_NUM_REGS_RV32I (14) +#define MICROPY_NLR_NUM_REGS_RV64I (14) // *FORMAT-OFF* @@ -99,16 +101,65 @@ #elif defined(__mips__) #define MICROPY_NLR_MIPS (1) #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_MIPS) +#elif defined(__riscv) + #if __riscv_xlen == 32 + #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_RV32I) + #define MICROPY_NLR_RV32I (1) + #elif __riscv_xlen == 64 + #define MICROPY_NLR_NUM_REGS (MICROPY_NLR_NUM_REGS_RV64I) + #define MICROPY_NLR_RV64I (1) + #else + #error Unsupported RISC-V variant. + #endif #else #define MICROPY_NLR_SETJMP (1) //#warning "No native NLR support for this arch, using setjmp implementation" #endif #endif -// CIRCUITPY-CHANGE -// If MICROPY_NLR_SETJMP is not defined above - define/disable it here -#if !defined(MICROPY_NLR_SETJMP) - #define MICROPY_NLR_SETJMP (0) +// CIRCUITPY-CHANGE: Avoid warnings by defining all these MICROPY_PY_NLR_* macros +#ifndef MICROPY_NLR_AARCH64 +#define MICROPY_NLR_AARCH64 (0) +#endif + +#ifndef MICROPY_NLR_MIPS +#define MICROPY_NLR_MIPS (0) +#endif + +#ifndef MICROPY_NLR_OS_WINDOWS +#define MICROPY_NLR_OS_WINDOWS (0) +#endif + +#ifndef MICROPY_NLR_POWERPC +#define MICROPY_NLR_POWERPC (0) +#endif + +#ifndef MICROPY_NLR_RV32I +#define MICROPY_NLR_RV32I (0) +#endif + +#ifndef MICROPY_NLR_RV64I +#define MICROPY_NLR_RV64I (0) +#endif + +#ifndef MICROPY_NLR_SETJMP +#define MICROPY_NLR_SETJMP (0) +#endif + +#ifndef MICROPY_NLR_THUMB +#define MICROPY_NLR_THUMB (0) +#endif + +#ifndef MICROPY_NLR_X64 +#define MICROPY_NLR_X64 (0) +#endif + +#ifndef MICROPY_NLR_X86 +#define MICROPY_NLR_X86 (0) +#endif + +#ifndef MICROPY_NLR_XTENSA +#define MICROPY_NLR_XTENSA (0) #endif // *FORMAT-ON* @@ -182,18 +233,18 @@ unsigned int nlr_push(nlr_buf_t *); unsigned int nlr_push_tail(nlr_buf_t *top); void nlr_pop(void); -NORETURN void nlr_jump(void *val); +MP_NORETURN void nlr_jump(void *val); #if MICROPY_ENABLE_VM_ABORT #define nlr_set_abort(buf) MP_STATE_VM(nlr_abort) = buf #define nlr_get_abort() MP_STATE_VM(nlr_abort) -NORETURN void nlr_jump_abort(void); +MP_NORETURN void nlr_jump_abort(void); #endif // This must be implemented by a port. It's called by nlr_jump // if no nlr buf has been pushed. It must not return, but rather // should bail out with a fatal error. -NORETURN void nlr_jump_fail(void *val); +MP_NORETURN void nlr_jump_fail(void *val); // use nlr_raise instead of nlr_jump so that debugging is easier #ifndef MICROPY_DEBUG_NLR diff --git a/py/nlraarch64.c b/py/nlraarch64.c index f6fee5b63abd9..3318004b5e037 100644 --- a/py/nlraarch64.c +++ b/py/nlraarch64.c @@ -26,8 +26,7 @@ #include "py/mpstate.h" // needed for NLR defs -// CIRCUITPY-CHANGE: avoid warnings -#if defined(MICROPY_NLR_AARCH64) && MICROPY_NLR_AARCH64 +#if MICROPY_NLR_AARCH64 // AArch64 callee-saved registers are x19-x29. // https://en.wikipedia.org/wiki/Calling_convention#ARM_(A64) @@ -57,7 +56,7 @@ __asm( #endif ); -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) MP_STATIC_ASSERT(offsetof(nlr_buf_t, regs) == 16); // asm assumes it @@ -76,7 +75,6 @@ NORETURN void nlr_jump(void *val) { "ret \n" : : "r" (top) - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" ); diff --git a/py/nlrmips.c b/py/nlrmips.c index 22690d19dc802..5c55db7e268ec 100644 --- a/py/nlrmips.c +++ b/py/nlrmips.c @@ -26,7 +26,7 @@ #include "py/mpstate.h" -#if defined(MICROPY_NLR_MIPS) && MICROPY_NLR_MIPS +#if MICROPY_NLR_MIPS __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); @@ -57,7 +57,7 @@ __asm( ".end nlr_push \n" ); -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm( "move $4, %0 \n" @@ -78,7 +78,6 @@ NORETURN void nlr_jump(void *val) { "nop \n" : : "r" (top) - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" ); MP_UNREACHABLE diff --git a/py/nlrpowerpc.c b/py/nlrpowerpc.c index f516383f776ea..cf140400e68f5 100644 --- a/py/nlrpowerpc.c +++ b/py/nlrpowerpc.c @@ -26,7 +26,7 @@ #include "py/mpstate.h" -#if defined(MICROPY_NLR_POWERPC) && MICROPY_NLR_POWERPC +#if MICROPY_NLR_POWERPC #undef nlr_push @@ -78,7 +78,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm__ volatile ( @@ -114,7 +114,6 @@ NORETURN void nlr_jump(void *val) { "blr ;" : : "r" (&top->regs) - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" ); @@ -168,7 +167,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm__ volatile ( diff --git a/py/nlrrv32.c b/py/nlrrv32.c new file mode 100644 index 0000000000000..565a8629db5f0 --- /dev/null +++ b/py/nlrrv32.c @@ -0,0 +1,81 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpstate.h" + +#if MICROPY_NLR_RV32I + +#undef nlr_push + +__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { + __asm volatile ( + "sw x1, 8(x10) \n" // Store RA. + "sw x8, 12(x10) \n" // Store S0. + "sw x9, 16(x10) \n" // Store S1. + "sw x18, 20(x10) \n" // Store S2. + "sw x19, 24(x10) \n" // Store S3. + "sw x20, 28(x10) \n" // Store S4. + "sw x21, 32(x10) \n" // Store S5. + "sw x22, 36(x10) \n" // Store S6. + "sw x23, 40(x10) \n" // Store S7. + "sw x24, 44(x10) \n" // Store S8. + "sw x25, 48(x10) \n" // Store S9. + "sw x26, 52(x10) \n" // Store S10. + "sw x27, 56(x10) \n" // Store S11. + "sw x2, 60(x10) \n" // Store SP. + "jal x0, nlr_push_tail \n" // Jump to the C part. + ); +} + +MP_NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + __asm volatile ( + "add x10, x0, %0 \n" // Load nlr_buf address. + "lw x1, 8(x10) \n" // Retrieve RA. + "lw x8, 12(x10) \n" // Retrieve S0. + "lw x9, 16(x10) \n" // Retrieve S1. + "lw x18, 20(x10) \n" // Retrieve S2. + "lw x19, 24(x10) \n" // Retrieve S3. + "lw x20, 28(x10) \n" // Retrieve S4. + "lw x21, 32(x10) \n" // Retrieve S5. + "lw x22, 36(x10) \n" // Retrieve S6. + "lw x23, 40(x10) \n" // Retrieve S7. + "lw x24, 44(x10) \n" // Retrieve S8. + "lw x25, 48(x10) \n" // Retrieve S9. + "lw x26, 52(x10) \n" // Retrieve S10. + "lw x27, 56(x10) \n" // Retrieve S11. + "lw x2, 60(x10) \n" // Retrieve SP. + "addi x10, x0, 1 \n" // Return 1 for a non-local return. + "jalr x0, x1, 0 \n" // Return. + : // Outputs. + : "r" (top) // Inputs. + : "memory" // Clobbered. + ); + + MP_UNREACHABLE +} + +#endif // MICROPY_NLR_RV32I diff --git a/py/nlrrv64.c b/py/nlrrv64.c new file mode 100644 index 0000000000000..b7d1467b8f6f6 --- /dev/null +++ b/py/nlrrv64.c @@ -0,0 +1,81 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mpstate.h" + +#if MICROPY_NLR_RV64I + +#undef nlr_push + +__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { + __asm volatile ( + "sd x1, 16(x10) \n" // Store RA. + "sd x8, 24(x10) \n" // Store S0. + "sd x9, 32(x10) \n" // Store S1. + "sd x18, 40(x10) \n" // Store S2. + "sd x19, 48(x10) \n" // Store S3. + "sd x20, 56(x10) \n" // Store S4. + "sd x21, 64(x10) \n" // Store S5. + "sd x22, 72(x10) \n" // Store S6. + "sd x23, 80(x10) \n" // Store S7. + "sd x24, 88(x10) \n" // Store S8. + "sd x25, 96(x10) \n" // Store S9. + "sd x26, 104(x10) \n" // Store S10. + "sd x27, 112(x10) \n" // Store S11. + "sd x2, 120(x10) \n" // Store SP. + "jal x0, nlr_push_tail \n" // Jump to the C part. + ); +} + +MP_NORETURN void nlr_jump(void *val) { + MP_NLR_JUMP_HEAD(val, top) + __asm volatile ( + "add x10, x0, %0 \n" // Load nlr_buf address. + "ld x1, 16(x10) \n" // Retrieve RA. + "ld x8, 24(x10) \n" // Retrieve S0. + "ld x9, 32(x10) \n" // Retrieve S1. + "ld x18, 40(x10) \n" // Retrieve S2. + "ld x19, 48(x10) \n" // Retrieve S3. + "ld x20, 56(x10) \n" // Retrieve S4. + "ld x21, 64(x10) \n" // Retrieve S5. + "ld x22, 72(x10) \n" // Retrieve S6. + "ld x23, 80(x10) \n" // Retrieve S7. + "ld x24, 88(x10) \n" // Retrieve S8. + "ld x25, 96(x10) \n" // Retrieve S9. + "ld x26, 104(x10) \n" // Retrieve S10. + "ld x27, 112(x10) \n" // Retrieve S11. + "ld x2, 120(x10) \n" // Retrieve SP. + "addi x10, x0, 1 \n" // Return 1 for a non-local return. + "jalr x0, x1, 0 \n" // Return. + : // Outputs. + : "r" (top) // Inputs. + : "memory" // Clobbered. + ); + + MP_UNREACHABLE +} + +#endif // MICROPY_NLR_RV64I diff --git a/py/nlrthumb.c b/py/nlrthumb.c index 06a713a213b35..1791d8b49294e 100644 --- a/py/nlrthumb.c +++ b/py/nlrthumb.c @@ -26,8 +26,7 @@ #include "py/mpstate.h" -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_THUMB) && MICROPY_NLR_THUMB +#if MICROPY_NLR_THUMB #undef nlr_push @@ -37,9 +36,16 @@ // For reference, arm/thumb callee save regs are: // r4-r11, r13=sp -// CIRCUITPY-CHANGE: added returns_twice -__attribute__((naked, returns_twice)) unsigned int nlr_push(nlr_buf_t *nlr) { +__attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) { + // If you get a linker error here, indicating that a relocation doesn't + // fit, try the following (in that order): + // + // 1. Ensure that nlr.o nlrthumb.o are linked closely together, i.e. + // there aren't too many other files between them in the linker list + // (PY_CORE_O_BASENAME in py/py.mk) + // 2. Set -DMICROPY_NLR_THUMB_USE_LONG_JUMP=1 during the build + // __asm volatile ( "str r4, [r0, #12] \n" // store r4 into nlr_buf "str r5, [r0, #16] \n" // store r5 into nlr_buf @@ -73,7 +79,7 @@ __attribute__((naked, returns_twice)) unsigned int nlr_push(nlr_buf_t *nlr) { "str lr, [r0, #8] \n" // store lr into nlr_buf #endif - #if !defined(__thumb2__) + #if MICROPY_NLR_THUMB_USE_LONG_JUMP "ldr r1, nlr_push_tail_var \n" "bx r1 \n" // do the rest in C ".align 2 \n" @@ -85,6 +91,10 @@ __attribute__((naked, returns_twice)) unsigned int nlr_push(nlr_buf_t *nlr) { "b nlr_push_tail \n" // do the rest in C #endif #endif + // CIRCUITPY-CHANGE: add input and clobbers to prevent smashing registers. + : // output operands + : "r" (nlr) // input operands + : "r1", "r2", "r3" // clobbers ); #if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) @@ -94,7 +104,7 @@ __attribute__((naked, returns_twice)) unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( @@ -134,8 +144,8 @@ NORETURN void nlr_jump(void *val) { "bx lr \n" // return : // output operands : "r" (top) // input operands - // CIRCUITPY-CHANGE: MicroPython makes this change in https://github.com/micropython/micropython/pull/14126 (later than v1.22) - : "memory" // clobbered registers + // CIRCUITPY-CHANGE: better comment + : "memory" // clobbers ); MP_UNREACHABLE diff --git a/py/nlrx64.c b/py/nlrx64.c index 4db637cbe8fb7..51224729fc90d 100644 --- a/py/nlrx64.c +++ b/py/nlrx64.c @@ -26,8 +26,7 @@ #include "py/mpstate.h" -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_X64) && MICROPY_NLR_X64 +#if MICROPY_NLR_X64 #undef nlr_push @@ -101,7 +100,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( @@ -124,7 +123,6 @@ NORETURN void nlr_jump(void *val) { "ret \n" // return : // output operands : "r" (top) // input operands - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" // clobbered registers ); diff --git a/py/nlrx86.c b/py/nlrx86.c index 83b2f0f3ae03e..26bf0dc6ccb85 100644 --- a/py/nlrx86.c +++ b/py/nlrx86.c @@ -26,16 +26,14 @@ #include "py/mpstate.h" -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_X86) && MICROPY_NLR_X86 +#if MICROPY_NLR_X86 #undef nlr_push // For reference, x86 callee save regs are: // ebx, esi, edi, ebp, esp, eip -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_OS_WINDOWS) && MICROPY_NLR_OS_WINDOWS +#if MICROPY_NLR_OS_WINDOWS unsigned int nlr_push_tail(nlr_buf_t *nlr) asm ("nlr_push_tail"); #else __attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr); @@ -80,7 +78,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { #endif } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( @@ -97,7 +95,6 @@ NORETURN void nlr_jump(void *val) { "ret \n" // return : // output operands : "r" (top) // input operands - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" // clobbered registers ); diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c index 01828ae5f46c8..2d1bf35e381a3 100644 --- a/py/nlrxtensa.c +++ b/py/nlrxtensa.c @@ -26,8 +26,7 @@ #include "py/mpstate.h" -// CIRCUITPY-CHANGE: avoid warning -#if defined(MICROPY_NLR_XTENSA) && MICROPY_NLR_XTENSA +#if MICROPY_NLR_XTENSA #undef nlr_push @@ -56,7 +55,7 @@ unsigned int nlr_push(nlr_buf_t *nlr) { return 0; // needed to silence compiler warning } -NORETURN void nlr_jump(void *val) { +MP_NORETURN void nlr_jump(void *val) { MP_NLR_JUMP_HEAD(val, top) __asm volatile ( @@ -75,7 +74,6 @@ NORETURN void nlr_jump(void *val) { "ret.n \n" // return : // output operands : "r" (top) // input operands - // CIRCUITPY-CHANGE: MicroPython caught up with this change in https://github.com/micropython/micropython/pull/14126 : "memory" // clobbered registers ); diff --git a/py/obj.c b/py/obj.c index 94544cc2ea2c4..ba3e6a9a9964d 100644 --- a/py/obj.c +++ b/py/obj.c @@ -31,6 +31,7 @@ // CIRCUITPY-CHANGE #include "shared/runtime/interrupt_char.h" +#include "py/misc.h" #include "py/obj.h" #include "py/objtype.h" #include "py/objint.h" @@ -38,7 +39,7 @@ // CIRCUITPY-CHANGE #include "py/qstr.h" #include "py/runtime.h" -#include "py/stackctrl.h" +#include "py/cstack.h" #include "py/stream.h" // for mp_obj_print // CIRCUITPY-CHANGE @@ -46,11 +47,22 @@ // Allocates an object and also sets type, for mp_obj_malloc{,_var} macros. MP_NOINLINE void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { - mp_obj_base_t *base = (mp_obj_base_t *)m_malloc(num_bytes); + // CIRCUITPY-CHANGE + mp_obj_base_t *base = (mp_obj_base_t *)m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT); base->type = type; return base; } +#if MICROPY_ENABLE_FINALISER +// Allocates an object and also sets type, for mp_obj_malloc{,_var}_with_finaliser macros. +MP_NOINLINE void *mp_obj_malloc_with_finaliser_helper(size_t num_bytes, const mp_obj_type_t *type) { + // CIRCUITPY-CHANGE + mp_obj_base_t *base = (mp_obj_base_t *)m_malloc_helper(num_bytes, M_MALLOC_RAISE_ERROR | M_MALLOC_COLLECT | M_MALLOC_WITH_FINALISER); + base->type = type; + return base; +} +#endif + const mp_obj_type_t *MICROPY_WRAP_MP_OBJ_GET_TYPE(mp_obj_get_type)(mp_const_obj_t o_in) { #if MICROPY_OBJ_IMMEDIATE_OBJS && MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A @@ -116,7 +128,7 @@ const char *mp_obj_get_type_str(mp_const_obj_t o_in) { void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { // There can be data structures nested too deep, or just recursive - MP_STACK_CHECK(); + mp_cstack_check(); // CIRCUITPY-CHANGE #ifdef RUN_BACKGROUND_TASKS RUN_BACKGROUND_TASKS; @@ -135,10 +147,17 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t } #endif const mp_obj_type_t *type = mp_obj_get_type(o_in); + // CIRCUITPY-CHANGE: Diagnose json.dump on invalid types + #if MICROPY_PY_JSON + if (kind == PRINT_JSON && !(type->flags & MP_TYPE_FLAG_PRINT_JSON)) { + mp_raise_msg_varg(&mp_type_TypeError, + MP_ERROR_TEXT("can't convert %q to %q"), type->name, MP_QSTR_json); + } + #endif if (MP_OBJ_TYPE_HAS_SLOT(type, print)) { MP_OBJ_TYPE_GET_SLOT(type, print)((mp_print_t *)print, o_in, kind); } else { - mp_printf(print, "<%q>", type->name); + mp_printf(print, "<%q>", (qstr)type->name); } } @@ -398,6 +417,36 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return val; } +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE +mp_uint_t mp_obj_get_uint(mp_const_obj_t arg) { + if (!mp_obj_is_exact_type(arg, &mp_type_int)) { + mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg); + if (as_int == MP_OBJ_NULL) { + mp_raise_TypeError_int_conversion(arg); + } + arg = as_int; + } + return mp_obj_int_get_uint_checked(arg); +} + +long long mp_obj_get_ll(mp_const_obj_t arg) { + if (!mp_obj_is_exact_type(arg, &mp_type_int)) { + mp_obj_t as_int = mp_unary_op(MP_UNARY_OP_INT_MAYBE, (mp_obj_t)arg); + if (as_int == MP_OBJ_NULL) { + mp_raise_TypeError_int_conversion(arg); + } + arg = as_int; + } + if (mp_obj_is_small_int(arg)) { + return MP_OBJ_SMALL_INT_VALUE(arg); + } else { + long long res; + mp_obj_int_to_bytes_impl((mp_obj_t)arg, MP_ENDIANNESS_BIG, sizeof(res), (byte *)&res); + return res; + } +} +#endif + mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg) { if (mp_obj_is_int(arg)) { return mp_obj_int_get_truncated(arg); @@ -677,7 +726,7 @@ typedef struct { mp_int_t cur; } mp_obj_generic_subscript_it_t; -STATIC mp_obj_t generic_subscript_it_iternext(mp_obj_t self_in) { +static mp_obj_t generic_subscript_it_iternext(mp_obj_t self_in) { mp_obj_generic_subscript_it_t *self = MP_OBJ_TO_PTR(self_in); const mp_obj_type_t *type = mp_obj_get_type(self->obj); mp_obj_t current_length = MP_OBJ_TYPE_GET_SLOT(type, unary_op)(MP_UNARY_OP_LEN, self->obj); diff --git a/py/obj.h b/py/obj.h index 2d1637dafa29b..eb7143bd43f62 100644 --- a/py/obj.h +++ b/py/obj.h @@ -184,12 +184,15 @@ static inline bool mp_obj_is_small_int(mp_const_obj_t o) { #define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)((((mp_uint_t)(small_int)) << 1) | 1)) #if MICROPY_PY_BUILTINS_FLOAT -#define mp_const_float_e MP_ROM_PTR((mp_obj_t)(((0x402df854 & ~3) | 2) + 0x80800000)) -#define mp_const_float_pi MP_ROM_PTR((mp_obj_t)(((0x40490fdb & ~3) | 2) + 0x80800000)) +#include +// note: MP_OBJ_NEW_CONST_FLOAT should be a MP_ROM_PTR but that macro isn't available yet +#define MP_OBJ_NEW_CONST_FLOAT(f) ((mp_obj_t)((((((uint64_t)f) & ~3) | 2) + 0x80800000) & 0xffffffff)) +#define mp_const_float_e MP_OBJ_NEW_CONST_FLOAT(0x402df854) +#define mp_const_float_pi MP_OBJ_NEW_CONST_FLOAT(0x40490fdb) +#define mp_const_float_nan MP_OBJ_NEW_CONST_FLOAT(0x7fc00000) #if MICROPY_PY_MATH_CONSTANTS -#define mp_const_float_tau MP_ROM_PTR((mp_obj_t)(((0x40c90fdb & ~3) | 2) + 0x80800000)) -#define mp_const_float_inf MP_ROM_PTR((mp_obj_t)(((0x7f800000 & ~3) | 2) + 0x80800000)) -#define mp_const_float_nan MP_ROM_PTR((mp_obj_t)(((0xffc00000 & ~3) | 2) + 0x80800000)) +#define mp_const_float_tau MP_OBJ_NEW_CONST_FLOAT(0x40c90fdb) +#define mp_const_float_inf MP_OBJ_NEW_CONST_FLOAT(0x7f800000) #endif static inline bool mp_obj_is_float(mp_const_obj_t o) { @@ -202,15 +205,23 @@ static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { union { mp_float_t f; mp_uint_t u; - } num = {.u = ((mp_uint_t)o - 0x80800000) & ~3}; + } num = {.u = ((mp_uint_t)o - 0x80800000u) & ~3u}; + // Rather than always truncating toward zero, which creates a strong + // bias, copy the two previous bits to fill in the two missing bits. + // This appears to be a pretty good heuristic. + num.u |= (num.u >> 2) & 3u; return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { + if (isnan(f)) { + // prevent creation of bad nanboxed pointers via array.array or struct + return mp_const_float_nan; + } union { mp_float_t f; mp_uint_t u; } num = {.f = f}; - return (mp_obj_t)(((num.u & ~0x3) | 2) + 0x80800000); + return (mp_obj_t)(((num.u & ~0x3u) | 2u) + 0x80800000u); } #endif @@ -256,8 +267,10 @@ static inline bool mp_obj_is_immediate_obj(mp_const_obj_t o) { #error MICROPY_OBJ_REPR_D requires MICROPY_FLOAT_IMPL_DOUBLE #endif +#include #define mp_const_float_e {((mp_obj_t)((uint64_t)0x4005bf0a8b145769 + 0x8004000000000000))} #define mp_const_float_pi {((mp_obj_t)((uint64_t)0x400921fb54442d18 + 0x8004000000000000))} +#define mp_const_float_nan {((mp_obj_t)((uint64_t)0x7ff8000000000000 + 0x8004000000000000))} #if MICROPY_PY_MATH_CONSTANTS #define mp_const_float_tau {((mp_obj_t)((uint64_t)0x401921fb54442d18 + 0x8004000000000000))} #define mp_const_float_inf {((mp_obj_t)((uint64_t)0x7ff0000000000000 + 0x8004000000000000))} @@ -275,6 +288,13 @@ static inline mp_float_t mp_obj_float_get(mp_const_obj_t o) { return num.f; } static inline mp_obj_t mp_obj_new_float(mp_float_t f) { + if (isnan(f)) { + // prevent creation of bad nanboxed pointers via array.array or struct + struct { + uint64_t r; + } num = mp_const_float_nan; + return num.r; + } union { mp_float_t f; uint64_t r; @@ -370,25 +390,25 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t; #define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_0}, .fun._0 = fun_name} + {.base = {.type = &mp_type_fun_builtin_0}, .fun = {._0 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_1}, .fun._1 = fun_name} + {.base = {.type = &mp_type_fun_builtin_1}, .fun = {._1 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_2}, .fun._2 = fun_name} + {.base = {.type = &mp_type_fun_builtin_2}, .fun = {._2 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \ const mp_obj_fun_builtin_fixed_t obj_name = \ - {{&mp_type_fun_builtin_3}, .fun._3 = fun_name} + {.base = {.type = &mp_type_fun_builtin_3}, .fun = {._3 = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, false), .fun.var = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, false), .fun = {.var = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, false), .fun.var = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, n_args_max, false), .fun = {.var = fun_name}} #define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \ const mp_obj_fun_builtin_var_t obj_name = \ - {{&mp_type_fun_builtin_var}, MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, true), .fun.kw = fun_name} + {.base = {.type = &mp_type_fun_builtin_var}, .sig = MP_OBJ_FUN_MAKE_SIG(n_args_min, MP_OBJ_FUN_ARGS_MAX, true), .fun = {.kw = fun_name}} // CIRCUITPY-CHANGE #define MP_DEFINE_CONST_PROP_GET(obj_name, fun_name) \ @@ -515,9 +535,7 @@ static inline bool mp_map_slot_is_filled(const mp_map_t *map, size_t pos) { void mp_map_init(mp_map_t *map, size_t n); void mp_map_init_fixed_table(mp_map_t *map, size_t n, const mp_obj_t *table); -mp_map_t *mp_map_new(size_t n); void mp_map_deinit(mp_map_t *map); -void mp_map_free(mp_map_t *map); mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind); void mp_map_clear(mp_map_t *map); void mp_map_dump(mp_map_t *map); @@ -548,9 +566,16 @@ typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t); typedef mp_obj_t (*mp_fun_var_t)(size_t n, const mp_obj_t *); // mp_fun_kw_t takes mp_map_t* (and not const mp_map_t*) to ease passing // this arg to mp_map_lookup(). +// Note that the mp_obj_t* array will contain all arguments, positional and keyword, with the keyword +// ones starting at offset n, like: arg0 arg1 ... arg key0 value0 key1 value1 ..., and the mp_map_t* +// gets those same keyword arguments but as a map for convenience; see fun_builtin_var_call. typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // Flags for type behaviour (mp_obj_type_t.flags) +// If MP_TYPE_FLAG_IS_SUBCLASSED is set, then subclasses of this class have been created. +// Mutations to this class that would require updating all subclasses must be rejected. +// If MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS is set, then attribute lookups involving this +// class need to additionally check for special accessor methods, such as from descriptors. // If MP_TYPE_FLAG_EQ_NOT_REFLEXIVE is clear then __eq__ is reflexive (A==A returns True). // If MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE is clear then the type can't be equal to an // instance of any different class that also clears this flag. If this flag is set @@ -568,6 +593,8 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); // If MP_TYPE_FLAG_ITER_IS_STREAM is set then the type implicitly gets a "return self" // getiter, and mp_stream_unbuffered_iter for iternext. // If MP_TYPE_FLAG_INSTANCE_TYPE is set then this is an instance type (i.e. defined in Python). +// If MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE is set then the "subscr" slot allows a stack +// allocated slice to be passed in (no references to it will be retained after the call). #define MP_TYPE_FLAG_NONE (0x0000) #define MP_TYPE_FLAG_IS_SUBCLASSED (0x0001) #define MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS (0x0002) @@ -581,6 +608,9 @@ typedef mp_obj_t (*mp_fun_kw_t)(size_t n, const mp_obj_t *, mp_map_t *); #define MP_TYPE_FLAG_ITER_IS_CUSTOM (0x0100) #define MP_TYPE_FLAG_ITER_IS_STREAM (MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_ITER_IS_CUSTOM) #define MP_TYPE_FLAG_INSTANCE_TYPE (0x0200) +#define MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE (0x0400) +// CIRCUITPY-CHANGE: check for valid types in json dumps +#define MP_TYPE_FLAG_PRINT_JSON (0x0800) typedef enum { PRINT_STR = 0, @@ -785,20 +815,20 @@ typedef struct _mp_obj_full_type_t { // Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE. // Generated with: // for i in range(13): -// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slots = { v1, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } -#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } +// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .flags = _flags, .name = _name{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}") +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slots = { v1, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } } +#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } } // Because the mp_obj_type_t instances are in (zero-initialised) ROM, we take // slot_index_foo=0 to mean that the slot is unset. This also simplifies checking @@ -821,7 +851,7 @@ typedef struct _mp_obj_full_type_t { #define MP_DEFINE_CONST_OBJ_TYPE_NARGS(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, N, ...) MP_DEFINE_CONST_OBJ_TYPE_NARGS_##N // This macros is used to define a object type in ROM. -// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, _make_new [, slot, func]*) +// Invoke as MP_DEFINE_CONST_OBJ_TYPE(_typename, _name, _flags, [, slot, func]*) // It uses the number of arguments to select which MP_DEFINE_CONST_OBJ_TYPE_* // macro to use based on the number of arguments. It works by shifting the // numeric values 12, 11, ... 0 by the number of arguments, such that the @@ -841,7 +871,7 @@ extern const mp_obj_type_t mp_type_bytearray; extern const mp_obj_type_t mp_type_memoryview; extern const mp_obj_type_t mp_type_float; extern const mp_obj_type_t mp_type_complex; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add traceback support extern const mp_obj_type_t mp_type_traceback; extern const mp_obj_type_t mp_type_tuple; extern const mp_obj_type_t mp_type_list; @@ -873,6 +903,10 @@ extern const mp_obj_type_t mp_type_fun_builtin_2; extern const mp_obj_type_t mp_type_fun_builtin_3; extern const mp_obj_type_t mp_type_fun_builtin_var; extern const mp_obj_type_t mp_type_fun_bc; +extern const mp_obj_type_t mp_type_fun_native; +extern const mp_obj_type_t mp_type_fun_viper; +extern const mp_obj_type_t mp_type_fun_asm; +extern const mp_obj_type_t mp_type_code; extern const mp_obj_type_t mp_type_module; extern const mp_obj_type_t mp_type_staticmethod; extern const mp_obj_type_t mp_type_classmethod; @@ -880,6 +914,7 @@ extern const mp_obj_type_t mp_type_bound_meth; extern const mp_obj_type_t mp_type_property; extern const mp_obj_type_t mp_type_stringio; extern const mp_obj_type_t mp_type_bytesio; +extern const mp_obj_type_t mp_type_ringio; extern const mp_obj_type_t mp_type_reversed; extern const mp_obj_type_t mp_type_polymorph_iter; #if MICROPY_ENABLE_FINALISER @@ -898,7 +933,7 @@ extern const mp_obj_type_t mp_type_ImportError; extern const mp_obj_type_t mp_type_IndentationError; extern const mp_obj_type_t mp_type_IndexError; extern const mp_obj_type_t mp_type_KeyboardInterrupt; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add ReloadException extern const mp_obj_type_t mp_type_ReloadException; extern const mp_obj_type_t mp_type_KeyError; extern const mp_obj_type_t mp_type_LookupError; @@ -906,9 +941,9 @@ extern const mp_obj_type_t mp_type_MemoryError; extern const mp_obj_type_t mp_type_NameError; extern const mp_obj_type_t mp_type_NotImplementedError; extern const mp_obj_type_t mp_type_OSError; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add ConnectionError extern const mp_obj_type_t mp_type_ConnectionError; -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: add BrokenPipeError extern const mp_obj_type_t mp_type_BrokenPipeError; extern const mp_obj_type_t mp_type_OverflowError; extern const mp_obj_type_t mp_type_RuntimeError; @@ -916,6 +951,7 @@ extern const mp_obj_type_t mp_type_StopAsyncIteration; extern const mp_obj_type_t mp_type_StopIteration; extern const mp_obj_type_t mp_type_SyntaxError; extern const mp_obj_type_t mp_type_SystemExit; +// CIRCUITPY-CHANGE: add TimeoutError extern const mp_obj_type_t mp_type_TimeoutError; extern const mp_obj_type_t mp_type_TypeError; extern const mp_obj_type_t mp_type_UnicodeError; @@ -974,9 +1010,19 @@ extern const struct _mp_obj_exception_t mp_const_GeneratorExit_obj; // Helper versions of m_new_obj when you need to immediately set base.type. // Implementing this as a call rather than inline saves 8 bytes per usage. #define mp_obj_malloc(struct_type, obj_type) ((struct_type *)mp_obj_malloc_helper(sizeof(struct_type), obj_type)) -#define mp_obj_malloc_var(struct_type, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_helper(sizeof(struct_type) + sizeof(var_type) * (var_num), obj_type)) +#define mp_obj_malloc_var(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type)) void *mp_obj_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); +// Object allocation macros for allocating objects that have a finaliser. +#if MICROPY_ENABLE_FINALISER +#define mp_obj_malloc_with_finaliser(struct_type, obj_type) ((struct_type *)mp_obj_malloc_with_finaliser_helper(sizeof(struct_type), obj_type)) +#define mp_obj_malloc_var_with_finaliser(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_malloc_with_finaliser_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type)) +void *mp_obj_malloc_with_finaliser_helper(size_t num_bytes, const mp_obj_type_t *type); +#else +#define mp_obj_malloc_with_finaliser(struct_type, obj_type) mp_obj_malloc(struct_type, obj_type) +#define mp_obj_malloc_var_with_finaliser(struct_type, var_field, var_type, var_num, obj_type) mp_obj_malloc_var(struct_type, var_field, var_type, var_num, obj_type) +#endif + // These macros are derived from more primitive ones and are used to // check for more specific object types. // Note: these are kept as macros because inline functions sometimes use much @@ -1011,7 +1057,6 @@ bool mp_obj_is_dict_or_ordereddict(mp_obj_t o); // type check is done on iter method to allow tuple, namedtuple, attrtuple #define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) -mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); static inline mp_obj_t mp_obj_new_bool(mp_int_t x) { return x ? mp_const_true : mp_const_false; } @@ -1022,6 +1067,7 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, uns mp_obj_t mp_obj_new_int_from_ll(long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val); // this must return a multi-precision integer object (or raise an overflow exception) mp_obj_t mp_obj_new_str(const char *data, size_t len); // will check utf-8 (raises UnicodeError) +mp_obj_t mp_obj_new_str_from_cstr(const char *str); // // accepts null-terminated string, will check utf-8 (raises UnicodeError) mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len); // input data must be valid utf-8 mp_obj_t mp_obj_new_str_from_vstr(vstr_t *vstr); // will check utf-8 (raises UnicodeError) #if MICROPY_PY_BUILTINS_STR_UNICODE && MICROPY_PY_BUILTINS_STR_UNICODE_CHECK @@ -1031,10 +1077,10 @@ mp_obj_t mp_obj_new_str_from_utf8_vstr(vstr_t *vstr); // input data must be vali #endif mp_obj_t mp_obj_new_bytes_from_vstr(vstr_t *vstr); mp_obj_t mp_obj_new_bytes(const byte *data, size_t len); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_new_bytes_of_zeros(size_t len); mp_obj_t mp_obj_new_bytearray(size_t n, const void *items); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_new_bytearray_of_zeros(size_t n); mp_obj_t mp_obj_new_bytearray_by_ref(size_t n, void *items); #if MICROPY_PY_BUILTINS_FLOAT @@ -1070,7 +1116,7 @@ mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items); const mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in); const char *mp_obj_get_type_str(mp_const_obj_t o_in); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine #define mp_obj_get_type_qstr(o_in) (mp_obj_get_type((o_in))->name) bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo); // arguments should be type objects mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type); @@ -1078,7 +1124,7 @@ mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind); void mp_obj_print(mp_obj_t o, mp_print_kind_t kind); void mp_obj_print_exception(const mp_print_t *print, mp_obj_t exc); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine void mp_obj_print_exception_with_limit(const mp_print_t *print, mp_obj_t exc, mp_int_t limit); bool mp_obj_is_true(mp_obj_t arg); @@ -1092,6 +1138,8 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) { } mp_int_t mp_obj_get_int(mp_const_obj_t arg); +mp_uint_t mp_obj_get_uint(mp_const_obj_t arg); +long long mp_obj_get_ll(mp_const_obj_t arg); mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg); bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value); #if MICROPY_PY_BUILTINS_FLOAT @@ -1141,7 +1189,7 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type); void mp_obj_exception_clear_traceback(mp_obj_t self_in); void mp_obj_exception_add_traceback(mp_obj_t self_in, qstr file, size_t line, qstr block); void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values); -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: new routine mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in); mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in); mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -1218,7 +1266,7 @@ void mp_obj_tuple_del(mp_obj_t self_in); mp_int_t mp_obj_tuple_hash(mp_obj_t self_in); // list -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: public routine mp_obj_t mp_obj_list_clear(mp_obj_t self_in); mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value); @@ -1314,7 +1362,7 @@ typedef struct _mp_rom_obj_static_class_method_t { } mp_rom_obj_static_class_method_t; // property -// CIRCUITPY-CHANGE +// CIRCUITPY-CHANGE: extra args const mp_obj_t *mp_obj_property_get(mp_obj_t self_in, size_t *n_proxy); // sequence helpers @@ -1332,7 +1380,7 @@ bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte * bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2); mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args); mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value); -mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes); +mp_obj_t mp_seq_extract_slice(const mp_obj_t *seq, mp_bound_slice_t *indexes); // Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems #define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte *)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz)) @@ -1347,6 +1395,8 @@ mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t memmove(((char *)dest) + (beg + slice_len) * (item_sz), ((char *)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \ memmove(((char *)dest) + (beg) * (item_sz), slice, slice_len * (item_sz)); +#if !MICROPY_PREVIEW_VERSION_2 + // Provide translation for legacy API #define MP_OBJ_IS_SMALL_INT mp_obj_is_small_int #define MP_OBJ_IS_QSTR mp_obj_is_qstr @@ -1359,4 +1409,6 @@ mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t #define MP_MAP_SLOT_IS_FILLED mp_map_slot_is_filled #define MP_SET_SLOT_IS_FILLED mp_set_slot_is_filled +#endif + #endif // MICROPY_INCLUDED_PY_OBJ_H diff --git a/py/objarray.c b/py/objarray.c index bf12b7e5ef6f5..1e259a20ac8cb 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -61,13 +61,13 @@ // so not defined to catch errors #endif -STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf); -STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg); -STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in); -STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); +static mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf); +static mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg); +static mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in); +static mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); // CIRCUITPY-CHANGE #if MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t array_decode(size_t n_args, const mp_obj_t *args); +static mp_obj_t array_decode(size_t n_args, const mp_obj_t *args); #endif @@ -75,7 +75,7 @@ STATIC mp_obj_t array_decode(size_t n_args, const mp_obj_t *args); // array #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); if (o->typecode == BYTEARRAY_TYPECODE) { @@ -99,30 +99,47 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC mp_obj_array_t *array_new(char typecode, size_t n) { +static mp_obj_array_t *array_new(char typecode, size_t n) { // CIRCUITPY-CHANGE if (typecode == 'x') { mp_raise_ValueError(MP_ERROR_TEXT("bad typecode")); } int typecode_size = mp_binary_get_size('@', typecode, NULL); - mp_obj_array_t *o = m_new_obj(mp_obj_array_t); + + // CIRCUITPY-CHANGE: refactor to use m_obj_malloc() + const mp_obj_type_t *type; #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY - o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array; + type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array; #elif MICROPY_PY_BUILTINS_BYTEARRAY - o->base.type = &mp_type_bytearray; + type = &mp_type_bytearray; #else - o->base.type = &mp_type_array; + type = &mp_type_array; #endif + mp_obj_array_t *o = mp_obj_malloc(mp_obj_array_t, type); o->typecode = typecode; o->free = 0; o->len = n; - o->items = m_new(byte, typecode_size * o->len); + // CIRCUITPY-CHANGE + o->items = m_malloc_without_collect(typecode_size * o->len); return o; } #endif #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { +static void array_extend_impl(mp_obj_array_t *array, mp_obj_t arg, char typecode, size_t len) { + mp_obj_t iterable = mp_getiter(arg, NULL); + mp_obj_t item; + size_t i = 0; + while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (len == 0) { + array_append(MP_OBJ_FROM_PTR(array), item); + } else { + mp_binary_set_val_array(typecode, array->items, i++, item); + } + } +} + +static mp_obj_t array_construct(char typecode, mp_obj_t initializer) { // bytearrays can be raw-initialised from anything with the buffer protocol // other arrays can only be raw-initialised from bytes and bytearray objects mp_buffer_info_t bufinfo; @@ -154,24 +171,13 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) { } mp_obj_array_t *array = array_new(typecode, len); - - mp_obj_t iterable = mp_getiter(initializer, NULL); - mp_obj_t item; - size_t i = 0; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (len == 0) { - array_append(MP_OBJ_FROM_PTR(array), item); - } else { - mp_binary_set_val_array(typecode, array->items, i++, item); - } - } - + array_extend_impl(array, initializer, typecode, len); return MP_OBJ_FROM_PTR(array); } #endif #if MICROPY_PY_ARRAY -STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 1, 2, false); @@ -189,7 +195,7 @@ STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size #endif #if MICROPY_PY_BUILTINS_BYTEARRAY -STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // Can take 2nd/3rd arg if constructs from str mp_arg_check_num(n_args, n_kw, 0, 3, false); @@ -198,7 +204,7 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, // no args: construct an empty bytearray return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0)); } else if (mp_obj_is_int(args[0])) { - // CIRCUITPY-CHANGE: error checks this + // CIRCUITPY-CHANGE: error check this if (n_args > 1) { mp_raise_TypeError(MP_ERROR_TEXT("wrong number of arguments")); } @@ -225,12 +231,13 @@ STATIC mp_obj_t bytearray_make_new(const mp_obj_type_t *type_in, size_t n_args, #if MICROPY_PY_BUILTINS_MEMORYVIEW mp_obj_t mp_obj_new_memoryview(byte typecode, size_t nitems, void *items) { - mp_obj_array_t *self = m_new_obj(mp_obj_array_t); + // CIRCUITPY-CHANGE + mp_obj_array_t *self = mp_obj_malloc(mp_obj_array_t, &mp_type_memoryview); mp_obj_memoryview_init(self, typecode, 0, nitems, items); return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // TODO possibly allow memoryview constructor to take start/stop so that one @@ -263,7 +270,7 @@ STATIC mp_obj_t memoryview_make_new(const mp_obj_type_t *type_in, size_t n_args, // CIRCUITPY-CHANGE: adds cast #if MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_in) { +static mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_in) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); const char *typecode = mp_obj_str_get_str(typecode_in); size_t new_element_size = mp_binary_get_size('@', typecode[0], NULL); @@ -281,11 +288,11 @@ STATIC mp_obj_t memoryview_cast(const mp_obj_t self_in, const mp_obj_t typecode_ } return MP_OBJ_FROM_PTR(result); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(memoryview_cast_obj, memoryview_cast); +static MP_DEFINE_CONST_FUN_OBJ_2(memoryview_cast_obj, memoryview_cast); #endif #if MICROPY_PY_BUILTINS_MEMORYVIEW_ITEMSIZE -STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { return; } @@ -293,7 +300,7 @@ STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_NEW_SMALL_INT(mp_binary_get_size('@', self->typecode & TYPECODE_MASK, NULL)); } - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: add MICROPY_CPYTHON_COMPAT #if MICROPY_PY_BUILTINS_BYTES_HEX || MICROPY_CPYTHON_COMPAT else { // Need to forward to locals dict. @@ -305,7 +312,7 @@ STATIC void memoryview_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { #endif -STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: @@ -317,7 +324,7 @@ STATIC mp_obj_t array_unary_op(mp_unary_op_t op, mp_obj_t o_in) { } } -STATIC int typecode_for_comparison(int typecode, bool *is_unsigned) { +static int typecode_for_comparison(int typecode, bool *is_unsigned) { if (typecode == BYTEARRAY_TYPECODE) { typecode = 'B'; } @@ -328,7 +335,7 @@ STATIC int typecode_for_comparison(int typecode, bool *is_unsigned) { return typecode; } -STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in); switch (op) { // CIRCUITPY-CHANGE: does multiply @@ -458,7 +465,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs } #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY -STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array))); @@ -467,8 +474,9 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { if (self->free == 0) { size_t item_sz = mp_binary_get_size('@', self->typecode, NULL); // TODO: alloc policy - self->free = 8; - self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + self->free)); + size_t add_cnt = 8; + self->items = m_renew(byte, self->items, item_sz * self->len, item_sz * (self->len + add_cnt)); + self->free = add_cnt; mp_seq_clear(self->items, self->len + 1, self->len + self->free, item_sz); } mp_binary_set_val_array(self->typecode, self->items, self->len, arg); @@ -479,7 +487,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) { } MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_append_obj, array_append); -STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { +static mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // self is not a memoryview, so we don't need to use (& TYPECODE_MASK) assert((MICROPY_PY_BUILTINS_BYTEARRAY && mp_obj_is_type(self_in, &mp_type_bytearray)) || (MICROPY_PY_ARRAY && mp_obj_is_type(self_in, &mp_type_array))); @@ -487,41 +495,44 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) { // allow to extend by anything that has the buffer protocol (extension to CPython) mp_buffer_info_t arg_bufinfo; - // CIRCUITPY-CHANGE: allow appending an iterable - if (mp_get_buffer(arg_in, &arg_bufinfo, MP_BUFFER_READ)) { - size_t sz = mp_binary_get_size('@', self->typecode, NULL); - - // convert byte count to element count - size_t len = arg_bufinfo.len / sz; - - // make sure we have enough room to extend - // TODO: alloc policy; at the moment we go conservative - if (self->free < len) { - self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); - self->free = 0; - } else { - self->free -= len; - } + if (!mp_get_buffer(arg_in, &arg_bufinfo, MP_BUFFER_READ)) { + array_extend_impl(self, arg_in, 0, 0); + return mp_const_none; + } - // extend - mp_seq_copy((byte *)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); - self->len += len; - } else { - // Otherwise argument must be an iterable of items to append - mp_obj_t iterable = mp_getiter(arg_in, NULL); - mp_obj_t item; - while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - array_append(self_in, item); + size_t sz = mp_binary_get_size('@', self->typecode, NULL); + + // convert byte count to element count + size_t len = arg_bufinfo.len / sz; + + // make sure we have enough room to extend + // TODO: alloc policy; at the moment we go conservative + if (self->free < len) { + self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz); + self->free = 0; + + if (self_in == arg_in) { + // Get arg_bufinfo again in case self->items has moved + // + // (Note not possible to handle case that arg_in is a memoryview into self) + mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ); } + } else { + self->free -= len; } + + // extend + mp_seq_copy((byte *)self->items + self->len * sz, arg_bufinfo.buf, len * sz, byte); + self->len += len; + return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_array_extend_obj, array_extend); #endif -// CIRCUITPY-CHANGE: buffer_finder used belo +// CIRCUITPY-CHANGE: buffer_finder used below #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { +static mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { mp_check_self(mp_obj_is_type(args[0], &mp_type_bytearray)); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); @@ -558,30 +569,29 @@ STATIC mp_obj_t buffer_finder(size_t n_args, const mp_obj_t *args, int direction } return MP_OBJ_NEW_SMALL_INT(p - (const byte *)haystack_bufinfo.buf); } - // CIRCUITPY-CHANGE: provides find, rfind, index -STATIC mp_obj_t buffer_find(size_t n_args, const mp_obj_t *args) { +static mp_obj_t buffer_find(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, 1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(buffer_find_obj, 2, 4, buffer_find); -STATIC mp_obj_t buffer_rfind(size_t n_args, const mp_obj_t *args) { +static mp_obj_t buffer_rfind(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, -1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(buffer_rfind_obj, 2, 4, buffer_rfind); -STATIC mp_obj_t buffer_index(size_t n_args, const mp_obj_t *args) { +static mp_obj_t buffer_index(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, 1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(buffer_index_obj, 2, 4, buffer_index); -STATIC mp_obj_t buffer_rindex(size_t n_args, const mp_obj_t *args) { +static mp_obj_t buffer_rindex(size_t n_args, const mp_obj_t *args) { return buffer_finder(n_args, args, -1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(buffer_rindex_obj, 2, 4, buffer_rindex); #endif -STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { +static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item // TODO implement @@ -600,7 +610,8 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value #if MICROPY_PY_ARRAY_SLICE_ASSIGN // Assign size_t src_len; - void *src_items; + uint8_t *src_items; + size_t src_offs = 0; size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); if (mp_obj_is_obj(value) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type, subscr) == array_subscr) { // value is array, bytearray or memoryview @@ -613,7 +624,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value src_items = src_slice->items; #if MICROPY_PY_BUILTINS_MEMORYVIEW if (mp_obj_is_type(value, &mp_type_memoryview)) { - src_items = (uint8_t *)src_items + (src_slice->memview_offset * item_sz); + src_offs = src_slice->memview_offset * item_sz; } #endif } else if (mp_obj_is_type(value, &mp_type_bytes)) { @@ -648,15 +659,19 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value // TODO: alloc policy; at the moment we go conservative o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz); o->free = len_adj; + // m_renew may have moved o->items + if (src_items == dest_items) { + src_items = o->items; + } dest_items = o->items; } mp_seq_replace_slice_grow_inplace(dest_items, o->len, - slice.start, slice.stop, src_items, src_len, len_adj, item_sz); + slice.start, slice.stop, src_items + src_offs, src_len, len_adj, item_sz); } else { mp_seq_replace_slice_no_grow(dest_items, o->len, - slice.start, slice.stop, src_items, src_len, item_sz); + slice.start, slice.stop, src_items + src_offs, src_len, item_sz); // CIRCUITPY-CHANGE - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES // Clear "freed" elements at the end of list // TODO: This is actually only needed for typecode=='O' mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz); @@ -679,7 +694,8 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value if (slice.start > memview_offset_max) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("memoryview offset too large")); } - res = m_new_obj(mp_obj_array_t); + // CIRCUITPY-CHANGE + res = mp_obj_malloc(mp_obj_array_t, &mp_type_memoryview); *res = *o; res->memview_offset += slice.start; res->len = slice.stop - slice.start; @@ -715,7 +731,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value } } -STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { +static mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in); size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL); bufinfo->buf = o->items; @@ -738,7 +754,7 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui // CIRCUITPY-CHANGE #if MICROPY_CPYTHON_COMPAT && MICROPY_PY_BUILTINS_BYTEARRAY // Directly lifted from objstr.c -STATIC mp_obj_t array_decode(size_t n_args, const mp_obj_t *args) { +static mp_obj_t array_decode(size_t n_args, const mp_obj_t *args) { mp_obj_t new_args[2]; if (n_args == 1) { new_args[0] = args[0]; @@ -753,7 +769,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(array_decode_obj, 1, 3, array_decode); #if MICROPY_PY_BUILTINS_BYTEARRAY -STATIC const mp_rom_map_elem_t bytearray_locals_dict_table[] = { +static const mp_rom_map_elem_t bytearray_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, @@ -791,7 +807,7 @@ MP_DEFINE_CONST_OBJ_TYPE( MP_DEFINE_CONST_OBJ_TYPE( mp_type_bytearray, MP_QSTR_bytearray, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE, make_new, bytearray_make_new, print, array_print, iter, array_iterator_new, @@ -813,7 +829,7 @@ MP_DEFINE_CONST_OBJ_TYPE( // CIRCUITPY-CHANGE: provides cast #if MICROPY_CPYTHON_COMPAT // CIRCUITPY-CHANGE: provides cast -STATIC const mp_rom_map_elem_t memoryview_locals_dict_table[] = { +static const mp_rom_map_elem_t memoryview_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_cast), MP_ROM_PTR(&memoryview_cast_obj) }, #if MICROPY_PY_BUILTINS_BYTES_HEX { MP_ROM_QSTR(MP_QSTR_hex), MP_ROM_PTR(&mp_obj_bytes_hex_as_str_obj) }, @@ -830,7 +846,7 @@ MP_DEFINE_CONST_DICT(memoryview_locals_dict, memoryview_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_memoryview, MP_QSTR_memoryview, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE, make_new, memoryview_make_new, iter, array_iterator_new, unary_op, array_unary_op, @@ -883,7 +899,7 @@ typedef struct _mp_obj_array_it_t { size_t cur; } mp_obj_array_it_t; -STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { +static mp_obj_t array_it_iternext(mp_obj_t self_in) { mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->cur < self->array->len) { return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++); @@ -892,14 +908,14 @@ STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) { } } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_array_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, iter, array_it_iternext ); -STATIC mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t array_iterator_new(mp_obj_t array_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_array_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in); mp_obj_array_it_t *o = (mp_obj_array_it_t *)iter_buf; diff --git a/py/objarray.h b/py/objarray.h index 4a0e8a983fe77..bb7a514b97913 100644 --- a/py/objarray.h +++ b/py/objarray.h @@ -53,6 +53,10 @@ typedef struct _mp_obj_array_t { } mp_obj_array_t; #if MICROPY_PY_BUILTINS_MEMORYVIEW + +#define MP_DEFINE_MEMORYVIEW_OBJ(obj_name, typecode, offset, len, ptr) \ + mp_obj_array_t obj_name = {{&mp_type_memoryview}, (typecode), (offset), (len), (ptr)} + static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, size_t offset, size_t len, void *items) { self->base.type = &mp_type_memoryview; self->typecode = typecode; @@ -60,6 +64,7 @@ static inline void mp_obj_memoryview_init(mp_obj_array_t *self, size_t typecode, self->len = len; self->items = items; } + #endif #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY diff --git a/py/objattrtuple.c b/py/objattrtuple.c index fbe04bedb877a..1280e3308938e 100644 --- a/py/objattrtuple.c +++ b/py/objattrtuple.c @@ -30,7 +30,7 @@ // this helper function is used by collections.namedtuple #if !MICROPY_PY_COLLECTIONS -STATIC +static #endif void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_tuple_t *o) { mp_print_str(print, "("); @@ -48,14 +48,14 @@ void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, #if MICROPY_PY_ATTRTUPLE -STATIC void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in); const qstr *fields = (const qstr *)MP_OBJ_TO_PTR(o->items[o->len]); mp_obj_attrtuple_print_helper(print, fields, o); } -STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // load attribute mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); @@ -71,7 +71,7 @@ STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items) { - mp_obj_tuple_t *o = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, n + 1, &mp_type_attrtuple); + mp_obj_tuple_t *o = mp_obj_malloc_var(mp_obj_tuple_t, items, mp_obj_t, n + 1, &mp_type_attrtuple); o->len = n; for (size_t i = 0; i < n; i++) { o->items[i] = items[i]; diff --git a/py/objbool.c b/py/objbool.c index 96f0e60dd1765..990f52bb26fe4 100644 --- a/py/objbool.c +++ b/py/objbool.c @@ -43,7 +43,7 @@ typedef struct _mp_obj_bool_t { #endif -STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bool value = BOOL_VALUE(self_in); if (MICROPY_PY_JSON && kind == PRINT_JSON) { if (value) { @@ -60,7 +60,7 @@ STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); @@ -71,7 +71,7 @@ STATIC mp_obj_t bool_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ } } -STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { if (op == MP_UNARY_OP_LEN) { return MP_OBJ_NULL; } @@ -79,16 +79,17 @@ STATIC mp_obj_t bool_unary_op(mp_unary_op_t op, mp_obj_t o_in) { return mp_unary_op(op, MP_OBJ_NEW_SMALL_INT(value)); } -STATIC mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t bool_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { bool value = BOOL_VALUE(lhs_in); return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(value), rhs_in); } +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( // can match all numeric types mp_type_bool, MP_QSTR_bool, - MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_PRINT_JSON, make_new, bool_make_new, print, bool_print, unary_op, bool_unary_op, diff --git a/py/objboundmeth.c b/py/objboundmeth.c index b0be810c5c15e..6df67f7bf9e0c 100644 --- a/py/objboundmeth.c +++ b/py/objboundmeth.c @@ -36,7 +36,7 @@ typedef struct _mp_obj_bound_meth_t { } mp_obj_bound_meth_t; #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED -STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "meth, self->self, n_args, n_kw, args); } -STATIC mp_obj_t bound_meth_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t bound_meth_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_HASH: @@ -93,7 +93,7 @@ STATIC mp_obj_t bound_meth_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // The MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE flag is clear for this type, so if this // function is called with MP_BINARY_OP_EQUAL then lhs_in and rhs_in must have the // same type, which is mp_type_bound_meth. @@ -102,11 +102,15 @@ STATIC mp_obj_t bound_meth_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_ } mp_obj_bound_meth_t *lhs = MP_OBJ_TO_PTR(lhs_in); mp_obj_bound_meth_t *rhs = MP_OBJ_TO_PTR(rhs_in); + #if MICROPY_PY_BOUND_METHOD_FULL_EQUALITY_CHECK + return mp_obj_new_bool(mp_obj_equal(lhs->self, rhs->self) && mp_obj_equal(lhs->meth, rhs->meth)); + #else return mp_obj_new_bool(lhs->self == rhs->self && lhs->meth == rhs->meth); + #endif } #if MICROPY_PY_FUNCTION_ATTRS -STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; diff --git a/py/objcell.c b/py/objcell.c index 0a74e29d2064a..5c030c7405a80 100644 --- a/py/objcell.c +++ b/py/objcell.c @@ -27,10 +27,10 @@ #include "py/obj.h" #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED -STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_cell_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "obj); + mp_printf(print, "obj); if (o->obj == MP_OBJ_NULL) { mp_print_str(print, "(nil)"); } else { @@ -46,7 +46,7 @@ STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k #define CELL_TYPE_PRINT #endif -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( // cell representation is just value in < > mp_type_cell, MP_QSTR_, MP_TYPE_FLAG_NONE CELL_TYPE_PRINT diff --git a/py/objclosure.c b/py/objclosure.c index 6059d18100e03..5235312b519bf 100644 --- a/py/objclosure.c +++ b/py/objclosure.c @@ -36,7 +36,7 @@ typedef struct _mp_obj_closure_t { mp_obj_t closed[]; } mp_obj_closure_t; -STATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_closure_t *self = MP_OBJ_TO_PTR(self_in); // need to concatenate closed-over-vars and args @@ -50,7 +50,8 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const return mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); } else { // use heap to allocate temporary args array - mp_obj_t *args2 = m_new(mp_obj_t, n_total); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(n_total); memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t)); memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); mp_obj_t res = mp_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2); @@ -60,7 +61,7 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const } #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED -STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_closure_t *o = MP_OBJ_TO_PTR(o_in); mp_print_str(print, "fun mp_obj_closure_t *o = MP_OBJ_TO_PTR(self_in); mp_load_method_maybe(o->fun, attr, dest); @@ -105,7 +106,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed_over, const mp_obj_t *closed) { - mp_obj_closure_t *o = mp_obj_malloc_var(mp_obj_closure_t, mp_obj_t, n_closed_over, &mp_type_closure); + mp_obj_closure_t *o = mp_obj_malloc_var(mp_obj_closure_t, closed, mp_obj_t, n_closed_over, &mp_type_closure); o->fun = fun; o->n_closed = n_closed_over; memcpy(o->closed, closed, n_closed_over * sizeof(mp_obj_t)); diff --git a/py/objcode.c b/py/objcode.c new file mode 100644 index 0000000000000..09904f10f3683 --- /dev/null +++ b/py/objcode.c @@ -0,0 +1,246 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/objcode.h" + +#if MICROPY_PY_BUILTINS_CODE == MICROPY_PY_BUILTINS_CODE_NONE + +// Code object not implemented at this configuration level. + +#elif MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_code, + MP_QSTR_code, + MP_TYPE_FLAG_NONE + ); + +#elif MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_FULL + +#include "py/profile.h" + +static void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { + (void)kind; + mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in); + const mp_raw_code_t *rc = o->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + mp_printf(print, + "", + MP_CODE_QSTR_MAP(o->context, prelude->qstr_block_name_idx), + o, + MP_CODE_QSTR_MAP(o->context, 0), + rc->line_of_definition + ); +} + +static mp_obj_tuple_t *code_consts(const mp_module_context_t *context, const mp_raw_code_t *rc) { + mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(rc->n_children + 1, NULL)); + + size_t const_no = 0; + for (size_t i = 0; i < rc->n_children; ++i) { + mp_obj_t code = mp_obj_new_code(context, rc->children[i], true); + consts->items[const_no++] = code; + } + consts->items[const_no++] = mp_const_none; + + return consts; +} + +#if !MICROPY_PREVIEW_VERSION_2 +static mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { + // const mp_bytecode_prelude_t *prelude = &rc->prelude; + uint start = 0; + uint stop = rc->fun_data_len - start; + + uint last_lineno = mp_prof_bytecode_lineno(rc, start); + uint lasti = 0; + + const uint buffer_chunk_size = (stop - start) >> 2; // heuristic magic + uint buffer_size = buffer_chunk_size; + byte *buffer = m_new(byte, buffer_size); + uint buffer_index = 0; + + for (uint i = start; i < stop; ++i) { + uint lineno = mp_prof_bytecode_lineno(rc, i); + size_t line_diff = lineno - last_lineno; + if (line_diff > 0) { + uint instr_diff = (i - start) - lasti; + + assert(instr_diff < 256); + assert(line_diff < 256); + + if (buffer_index + 2 > buffer_size) { + buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size); + buffer_size = buffer_size + buffer_chunk_size; + } + last_lineno = lineno; + lasti = i - start; + buffer[buffer_index++] = instr_diff; + buffer[buffer_index++] = line_diff; + } + } + + mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index); + m_del(byte, buffer, buffer_size); + return o; +} +#endif + +static mp_obj_t code_colines_iter(mp_obj_t); +static mp_obj_t code_colines_next(mp_obj_t); +typedef struct _mp_obj_colines_iter_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + const mp_raw_code_t *rc; + mp_uint_t bc; + mp_uint_t source_line; + const byte *ci; +} mp_obj_colines_iter_t; + +static mp_obj_t code_colines_iter(mp_obj_t self_in) { + mp_obj_code_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_colines_iter_t *iter = mp_obj_malloc(mp_obj_colines_iter_t, &mp_type_polymorph_iter); + iter->iternext = code_colines_next; + iter->rc = self->rc; + iter->bc = 0; + iter->source_line = 1; + iter->ci = self->rc->prelude.line_info; + return MP_OBJ_FROM_PTR(iter); +} +static MP_DEFINE_CONST_FUN_OBJ_1(code_colines_obj, code_colines_iter); + +static mp_obj_t code_colines_next(mp_obj_t iter_in) { + mp_obj_colines_iter_t *iter = MP_OBJ_TO_PTR(iter_in); + const byte *ci_end = iter->rc->prelude.line_info_top; + + mp_uint_t start = iter->bc; + mp_uint_t line_no = iter->source_line; + bool another = true; + + while (another && iter->ci < ci_end) { + another = false; + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&iter->ci); + iter->bc += decoded.bc_increment; + iter->source_line += decoded.line_increment; + + if (decoded.bc_increment == 0) { + line_no = iter->source_line; + another = true; + } else if (decoded.line_increment == 0) { + another = true; + } + } + + if (another) { + mp_uint_t prelude_size = (iter->rc->prelude.opcodes - (const byte *)iter->rc->fun_data); + mp_uint_t bc_end = iter->rc->fun_data_len - prelude_size; + if (iter->bc >= bc_end) { + return MP_OBJ_STOP_ITERATION; + } else { + iter->bc = bc_end; + } + } + + mp_uint_t end = iter->bc; + mp_obj_t next[3] = {MP_OBJ_NEW_SMALL_INT(start), MP_OBJ_NEW_SMALL_INT(end), MP_OBJ_NEW_SMALL_INT(line_no)}; + + return mp_obj_new_tuple(MP_ARRAY_SIZE(next), next); +} + +static void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { + if (dest[0] != MP_OBJ_NULL) { + // not load attribute + return; + } + mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in); + const mp_raw_code_t *rc = o->rc; + const mp_bytecode_prelude_t *prelude = &rc->prelude; + switch (attr) { + case MP_QSTR_co_code: + dest[0] = mp_obj_new_bytes( + (void *)prelude->opcodes, + rc->fun_data_len - (prelude->opcodes - (const byte *)rc->fun_data) + ); + break; + case MP_QSTR_co_consts: + dest[0] = MP_OBJ_FROM_PTR(code_consts(o->context, rc)); + break; + case MP_QSTR_co_filename: + dest[0] = MP_OBJ_NEW_QSTR(MP_CODE_QSTR_MAP(o->context, 0)); + break; + case MP_QSTR_co_firstlineno: + dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0)); + break; + case MP_QSTR_co_name: + dest[0] = MP_OBJ_NEW_QSTR(MP_CODE_QSTR_MAP(o->context, prelude->qstr_block_name_idx)); + break; + case MP_QSTR_co_names: + dest[0] = MP_OBJ_FROM_PTR(o->dict_locals); + break; + #if !MICROPY_PREVIEW_VERSION_2 + case MP_QSTR_co_lnotab: + if (!o->lnotab) { + o->lnotab = raw_code_lnotab(rc); + } + dest[0] = o->lnotab; + break; + #endif + case MP_QSTR_co_lines: + dest[0] = MP_OBJ_FROM_PTR(&code_colines_obj); + dest[1] = self_in; + break; + } +} + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_code, + MP_QSTR_code, + MP_TYPE_FLAG_NONE, + print, code_print, + attr, code_attr + ); + +mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc, bool result_required) { + mp_obj_code_t *o; + if (result_required) { + o = m_new_obj(mp_obj_code_t); + } else { + o = m_new_obj_maybe(mp_obj_code_t); + if (o == NULL) { + return MP_OBJ_NULL; + } + } + o->base.type = &mp_type_code; + o->context = context; + o->rc = rc; + o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly? + #if !MICROPY_PREVIEW_VERSION_2 + o->lnotab = MP_OBJ_NULL; + #endif + return MP_OBJ_FROM_PTR(o); +} + +#endif diff --git a/py/objcode.h b/py/objcode.h new file mode 100644 index 0000000000000..7be15e23f5271 --- /dev/null +++ b/py/objcode.h @@ -0,0 +1,100 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2025 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_PY_OBJCODE_H +#define MICROPY_INCLUDED_PY_OBJCODE_H + +#include "py/bc.h" + +#if MICROPY_PY_BUILTINS_CODE == MICROPY_PY_BUILTINS_CODE_NONE + +// Code object not implemented at this configuration level. + +#elif MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_MINIMUM + +typedef struct _mp_obj_code_t { + mp_obj_base_t base; + mp_obj_t module_fun; +} mp_obj_code_t; + +static inline mp_obj_t mp_obj_new_code(mp_obj_t module_fun) { + mp_obj_code_t *code = mp_obj_malloc(mp_obj_code_t, &mp_type_code); + code->module_fun = module_fun; + return MP_OBJ_FROM_PTR(code); +} + +#elif MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC + +typedef struct _mp_obj_code_t { + mp_obj_base_t base; + mp_module_constants_t constants; + const void *proto_fun; +} mp_obj_code_t; + +static inline mp_obj_t mp_obj_new_code(const mp_module_constants_t constants, const void *proto_fun) { + mp_obj_code_t *code = mp_obj_malloc(mp_obj_code_t, &mp_type_code); + code->constants = constants; + code->proto_fun = proto_fun; + return MP_OBJ_FROM_PTR(code); +} + +static inline const mp_module_constants_t *mp_code_get_constants(mp_obj_code_t *self) { + return &self->constants; +} + +static inline const void *mp_code_get_proto_fun(mp_obj_code_t *self) { + return self->proto_fun; +} + +#elif MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_FULL + +#include "py/emitglue.h" + +#define MP_CODE_QSTR_MAP(context, idx) ((qstr)(context->constants.qstr_table[idx])) + +typedef struct _mp_obj_code_t { + mp_obj_base_t base; + const mp_module_context_t *context; + const mp_raw_code_t *rc; + mp_obj_dict_t *dict_locals; + #if !MICROPY_PREVIEW_VERSION_2 + mp_obj_t lnotab; + #endif +} mp_obj_code_t; + +mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc, bool result_required); + +static inline const mp_module_constants_t *mp_code_get_constants(mp_obj_code_t *self) { + return &self->context->constants; +} + +static inline const void *mp_code_get_proto_fun(mp_obj_code_t *self) { + // A mp_raw_code_t is always a proto_fun (but not the other way around). + return self->rc; +} + +#endif + +#endif // MICROPY_INCLUDED_PY_OBJCODE_H diff --git a/py/objcomplex.c b/py/objcomplex.c index c69339c6ccac2..88f4444f09e4d 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -46,35 +46,24 @@ typedef struct _mp_obj_complex_t { mp_float_t imag; } mp_obj_complex_t; -STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT - char buf[16]; - #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C - const int precision = 6; - #else - const int precision = 7; - #endif - #else - char buf[32]; - const int precision = 16; - #endif - if (o->real == 0) { - mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "%sj", buf); + const char *suffix; + int flags = 0; + if (o->real != 0) { + mp_print_str(print, "("); + mp_print_float(print, o->real, 'g', 0, '\0', -1, MP_FLOAT_REPR_PREC); + flags = PF_FLAG_SHOW_SIGN; + suffix = "j)"; } else { - mp_format_float(o->real, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "(%s", buf); - if (o->imag >= 0 || isnan(o->imag)) { - mp_print_str(print, "+"); - } - mp_format_float(o->imag, buf, sizeof(buf), 'g', precision, '\0'); - mp_printf(print, "%sj)", buf); + suffix = "j"; } + mp_print_float(print, o->imag, 'g', flags, '\0', -1, MP_FLOAT_REPR_PREC); + mp_print_str(print, suffix); } -STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 2, false); @@ -119,7 +108,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si } } -STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in); switch (op) { case MP_UNARY_OP_BOOL: @@ -137,12 +126,12 @@ STATIC mp_obj_t complex_unary_op(mp_unary_op_t op, mp_obj_t o_in) { } } -STATIC mp_obj_t complex_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t complex_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in); return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in); } -STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; diff --git a/py/objdeque.c b/py/objdeque.c index 5f22bb33f96e4..4e1ee82e9d4de 100644 --- a/py/objdeque.c +++ b/py/objdeque.c @@ -30,9 +30,6 @@ #if MICROPY_PY_COLLECTIONS_DEQUE -// CIRCUITPY-CHANGE: Upcoming https://github.com/micropython/micropython/pull/10724 -// will incporate some or all of the changes here. - typedef struct _mp_obj_deque_t { mp_obj_base_t base; size_t alloc; @@ -43,13 +40,17 @@ typedef struct _mp_obj_deque_t { #define FLAG_CHECK_OVERFLOW 1 } mp_obj_deque_t; -// CIRCUITPY-CHANGE: add operations static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg); static mp_obj_t mp_obj_deque_extend(mp_obj_t self_in, mp_obj_t arg_in); #if MICROPY_PY_COLLECTIONS_DEQUE_ITER static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque, mp_obj_iter_buf_t *iter_buf); #endif +// CIRCUITPY-CHANGE +static mp_obj_deque_t *native_deque(mp_obj_t self_in) { + return MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_deque))); +} + static mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 3, false); @@ -62,13 +63,13 @@ static mp_obj_t deque_make_new(const mp_obj_type_t *type, size_t n_args, size_t mp_obj_deque_t *o = mp_obj_malloc(mp_obj_deque_t, type); o->alloc = maxlen + 1; o->i_get = o->i_put = 0; - o->items = m_new0(mp_obj_t, o->alloc); + // CIRCUITPY-CHANGE + o->items = m_malloc_items(o->alloc); if (n_args > 2) { o->flags = mp_obj_get_int(args[2]); } - // CIRCUITPY-CHANGE: allow non-empty initialization mp_obj_deque_extend(MP_OBJ_FROM_PTR(o), args[0]); return MP_OBJ_FROM_PTR(o); @@ -83,7 +84,8 @@ static size_t deque_len(mp_obj_deque_t *self) { } static mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->i_get != self->i_put); @@ -102,7 +104,8 @@ static mp_obj_t deque_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t new_i_put = self->i_put + 1; if (new_i_put == self->alloc) { @@ -127,7 +130,8 @@ static mp_obj_t mp_obj_deque_append(mp_obj_t self_in, mp_obj_t arg) { static MP_DEFINE_CONST_FUN_OBJ_2(deque_append_obj, mp_obj_deque_append); static mp_obj_t mp_obj_deque_appendleft(mp_obj_t self_in, mp_obj_t arg) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t new_i_get = self->i_get - 1; if (self->i_get == 0) { @@ -166,7 +170,8 @@ static mp_obj_t mp_obj_deque_extend(mp_obj_t self_in, mp_obj_t arg_in) { static MP_DEFINE_CONST_FUN_OBJ_2(deque_extend_obj, mp_obj_deque_extend); static mp_obj_t deque_popleft(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); if (self->i_get == self->i_put) { mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty")); @@ -184,7 +189,8 @@ static mp_obj_t deque_popleft(mp_obj_t self_in) { static MP_DEFINE_CONST_FUN_OBJ_1(deque_popleft_obj, deque_popleft); static mp_obj_t deque_pop(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); if (self->i_get == self->i_put) { mp_raise_msg(&mp_type_IndexError, MP_ERROR_TEXT("empty")); @@ -209,11 +215,12 @@ static mp_obj_t deque_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { // delete not supported, fall back to mp_obj_subscr() error message return MP_OBJ_NULL; } - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); size_t offset = mp_get_index(self->base.type, deque_len(self), index, false); size_t index_val = self->i_get + offset; - if (index_val > self->alloc) { + if (index_val >= self->alloc) { index_val -= self->alloc; } @@ -230,7 +237,8 @@ static mp_obj_t deque_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if 0 static mp_obj_t deque_clear(mp_obj_t self_in) { - mp_obj_deque_t *self = MP_OBJ_TO_PTR(self_in); + // CIRCUITPY-CHANGE + mp_obj_deque_t *self = native_deque(self_in); self->i_get = self->i_put = 0; mp_seq_clear(self->items, 0, self->alloc, sizeof(*self->items)); return mp_const_none; @@ -268,7 +276,7 @@ static MP_DEFINE_CONST_DICT(deque_locals_dict, deque_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_deque, MP_QSTR_deque, - MP_TYPE_FLAG_ITER_IS_GETITER, + DEQUE_TYPE_FLAGS, make_new, deque_make_new, unary_op, deque_unary_op, DEQUE_TYPE_SUBSCR @@ -290,7 +298,8 @@ typedef struct _mp_obj_deque_it_t { static mp_obj_t deque_it_iternext(mp_obj_t self_in) { mp_obj_deque_it_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_deque_t *deque = MP_OBJ_TO_PTR(self->deque); + // CIRCUITPY-CHANGE + mp_obj_deque_t *deque = native_deque(self->deque); if (self->cur != deque->i_put) { mp_obj_t o_out = deque->items[self->cur]; if (++self->cur == deque->alloc) { @@ -302,9 +311,10 @@ static mp_obj_t deque_it_iternext(mp_obj_t self_in) { } } -static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque, mp_obj_iter_buf_t *iter_buf) { - mp_obj_deque_t *deque_ = MP_OBJ_TO_PTR(deque); - size_t i_get = deque_->i_get; +static mp_obj_t mp_obj_new_deque_it(mp_obj_t deque_in, mp_obj_iter_buf_t *iter_buf) { + // CIRCUITPY-CHANGE + mp_obj_deque_t *deque = native_deque(deque_in); + size_t i_get = deque->i_get; assert(sizeof(mp_obj_deque_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_deque_it_t *o = (mp_obj_deque_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; diff --git a/py/objdict.c b/py/objdict.c index 18862decb7f6e..d459d1ae48647 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -52,7 +52,7 @@ const mp_obj_dict_t mp_const_empty_dict_obj = { // CIRCUITPY-CHANGE: Native methods are passed the subclass instance so they can // refer to subclass members. Dict only cares about the native struct so this // function gets it. -STATIC mp_obj_dict_t *native_dict(mp_obj_t self_in) { +static mp_obj_dict_t *native_dict(mp_obj_t self_in) { // Check for OrderedDict first because it is marked as a subclass of dict. However, it doesn't // store its state in subobj like python types to native types do. mp_obj_t native_instance = MP_OBJ_NULL; @@ -65,12 +65,12 @@ STATIC mp_obj_dict_t *native_dict(mp_obj_t self_in) { return MP_OBJ_TO_PTR(native_instance); } -STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); +static mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs); // This is a helper function to iterate through a dictionary. The state of // the iteration is held in *cur and should be initialised with zero for the // first call. Will return NULL when no more elements are available. -STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) { +static mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) { size_t max = dict->map.alloc; mp_map_t *map = &dict->map; @@ -86,7 +86,7 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, size_t *cur) { return NULL; } -STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(self_in); bool first = true; @@ -101,7 +101,7 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ #endif } if (MICROPY_PY_COLLECTIONS_ORDEREDDICT && self->base.type != &mp_type_dict && kind != PRINT_JSON) { - mp_printf(print, "%q(", self->base.type->name); + mp_printf(print, "%q(", (qstr)self->base.type->name); } mp_print_str(print, "{"); size_t cur = 0; @@ -131,7 +131,7 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ // CIRCUITPY-CHANGE // This is a helper function to initialize an empty, but typed dictionary with // a given number of slots. -STATIC mp_obj_t dict_new_typed(const mp_obj_type_t *type, const size_t n) { +static mp_obj_t dict_new_typed(const mp_obj_type_t *type, const size_t n) { mp_obj_t dict_out = mp_obj_new_dict(n); mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out); dict->base.type = type; @@ -161,7 +161,7 @@ mp_obj_t mp_obj_dict_make_new(const mp_obj_type_t *type, size_t n_args, size_t n return dict_out; } -STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(self_in); switch (op) { @@ -180,7 +180,7 @@ STATIC mp_obj_t dict_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t dict_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // CIRCUITPY-CHANGE mp_obj_dict_t *o = native_dict(lhs_in); switch (op) { @@ -253,7 +253,7 @@ mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { } } -STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete mp_obj_dict_delete(self_in, index); @@ -278,14 +278,14 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { /******************************************************************************/ /* dict methods */ -// CIRCUITPY-CHANGE -STATIC void PLACE_IN_ITCM(mp_ensure_not_fixed)(const mp_obj_dict_t * dict) { +// CIRCUITPY-CHANGE: PLACE_IN_ITCM +static void PLACE_IN_ITCM(mp_ensure_not_fixed)(const mp_obj_dict_t * dict) { if (dict->map.is_fixed) { mp_raise_TypeError(NULL); } } -STATIC mp_obj_t dict_clear(mp_obj_t self_in) { +static mp_obj_t dict_clear(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(self_in); @@ -295,7 +295,7 @@ STATIC mp_obj_t dict_clear(mp_obj_t self_in) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear); mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); @@ -312,11 +312,11 @@ mp_obj_t mp_obj_dict_copy(mp_obj_t self_in) { memcpy(other->map.table, self->map.table, self->map.alloc * sizeof(mp_map_elem_t)); return other_out; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, mp_obj_dict_copy); #if MICROPY_PY_BUILTINS_DICT_FROMKEYS // this is a classmethod -STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { +static mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { // CIRCUITPY-CHANGE mp_obj_type_t *type = MP_OBJ_TO_PTR(args[0]); mp_obj_t iter = mp_getiter(args[1], NULL); @@ -345,11 +345,11 @@ STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { return self_out; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys); -STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromkeys_fun_obj)); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_fromkeys_fun_obj, 2, 3, dict_fromkeys); +static MP_DEFINE_CONST_CLASSMETHOD_OBJ(dict_fromkeys_obj, MP_ROM_PTR(&dict_fromkeys_fun_obj)); #endif -STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { +static mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_lookup_kind_t lookup_kind) { mp_check_self(mp_obj_is_dict_or_ordereddict(args[0])); // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(args[0]); @@ -380,28 +380,28 @@ STATIC mp_obj_t dict_get_helper(size_t n_args, const mp_obj_t *args, mp_map_look return value; } -STATIC mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) { +static mp_obj_t dict_get(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get); -STATIC mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) { +static mp_obj_t dict_pop(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP_REMOVE_IF_FOUND); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop); -STATIC mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) { +static mp_obj_t dict_setdefault(size_t n_args, const mp_obj_t *args) { return dict_get_helper(n_args, args, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault); -STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { +static mp_obj_t dict_popitem(mp_obj_t self_in) { mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(self_in); mp_ensure_not_fixed(self); if (self->map.used == 0) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: different message mp_raise_msg_varg(&mp_type_KeyError, MP_ERROR_TEXT("pop from empty %q"), MP_QSTR_dict); } size_t cur = 0; @@ -420,9 +420,9 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { return tuple; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem); -STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { +static mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { mp_check_self(mp_obj_is_dict_or_ordereddict(args[0])); // CIRCUITPY-CHANGE mp_obj_dict_t *self = native_dict(args[0]); @@ -471,11 +471,11 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dict_update_obj, 1, dict_update); +static MP_DEFINE_CONST_FUN_OBJ_KW(dict_update_obj, 1, dict_update); // CIRCUITPY-CHANGE #if MICROPY_PY_COLLECTIONS_ORDEREDDICT -STATIC mp_obj_t dict_move_to_end(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t dict_move_to_end(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_validate_type(self, &mp_type_ordereddict, MP_QSTR_self); @@ -518,14 +518,14 @@ STATIC mp_obj_t dict_move_to_end(size_t n_args, const mp_obj_t *pos_args, mp_map return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(dict_move_to_end_obj, 1, dict_move_to_end); +static MP_DEFINE_CONST_FUN_OBJ_KW(dict_move_to_end_obj, 1, dict_move_to_end); #endif /******************************************************************************/ /* dict views */ -STATIC const mp_obj_type_t mp_type_dict_view; -STATIC const mp_obj_type_t mp_type_dict_view_it; +static const mp_obj_type_t mp_type_dict_view; +static const mp_obj_type_t mp_type_dict_view_it; typedef enum _mp_dict_view_kind_t { MP_DICT_VIEW_ITEMS, @@ -533,7 +533,7 @@ typedef enum _mp_dict_view_kind_t { MP_DICT_VIEW_VALUES, } mp_dict_view_kind_t; -STATIC const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"}; +static const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"}; typedef struct _mp_obj_dict_view_it_t { mp_obj_base_t base; @@ -548,7 +548,7 @@ typedef struct _mp_obj_dict_view_t { mp_dict_view_kind_t kind; } mp_obj_dict_view_t; -STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { +static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view_it)); mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in); // CIRCUITPY-CHANGE @@ -571,14 +571,14 @@ STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) { } } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, iter, dict_view_it_iternext ); -STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_check_self(mp_obj_is_type(view_in, &mp_type_dict_view)); mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in); @@ -590,7 +590,7 @@ STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in, mp_obj_iter_buf_t *iter_buf) return MP_OBJ_FROM_PTR(o); } -STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_check_self(mp_obj_is_type(self_in, &mp_type_dict_view)); mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in); @@ -610,16 +610,17 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ mp_print_str(print, "])"); } -STATIC mp_obj_t dict_view_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t dict_view_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(o_in); // only dict.values() supports __hash__. if (op == MP_UNARY_OP_HASH && o->kind == MP_DICT_VIEW_VALUES) { return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); } - return MP_OBJ_NULL; + // delegate all other ops to dict unary op handler + return dict_unary_op(op, o->dict); } -STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // only supported for the 'keys' kind until sets and dicts are refactored mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in); if (o->kind != MP_DICT_VIEW_KEYS) { @@ -631,7 +632,7 @@ STATIC mp_obj_t dict_view_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t return dict_binary_op(op, o->dict, rhs_in); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict_view, MP_QSTR_dict_view, MP_TYPE_FLAG_ITER_IS_GETITER, @@ -641,37 +642,37 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( iter, dict_view_getiter ); -STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { +static mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) { mp_obj_dict_view_t *o = mp_obj_malloc(mp_obj_dict_view_t, &mp_type_dict_view); o->dict = dict; o->kind = kind; return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) { +static mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) { mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); return mp_obj_new_dict_view(self_in, kind); } -STATIC mp_obj_t dict_items(mp_obj_t self_in) { +static mp_obj_t dict_items(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_ITEMS); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_items_obj, dict_items); -STATIC mp_obj_t dict_keys(mp_obj_t self_in) { +static mp_obj_t dict_keys(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_KEYS); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_keys_obj, dict_keys); -STATIC mp_obj_t dict_values(mp_obj_t self_in) { +static mp_obj_t dict_values(mp_obj_t self_in) { return dict_view(self_in, MP_DICT_VIEW_VALUES); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values); +static MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values); /******************************************************************************/ /* dict iterator */ -STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_dict_view_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_check_self(mp_obj_is_dict_or_ordereddict(self_in)); mp_obj_dict_view_it_t *o = (mp_obj_dict_view_it_t *)iter_buf; @@ -685,7 +686,7 @@ STATIC mp_obj_t dict_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) { /******************************************************************************/ /* dict constructors & public C API */ -STATIC const mp_rom_map_elem_t dict_locals_dict_table[] = { +static const mp_rom_map_elem_t dict_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&dict_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&dict_copy_obj) }, #if MICROPY_PY_BUILTINS_DICT_FROMKEYS @@ -708,12 +709,13 @@ STATIC const mp_rom_map_elem_t dict_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___delitem__), MP_ROM_PTR(&mp_op_delitem_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); +static MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table); +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_dict, MP_QSTR_dict, - MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, @@ -724,10 +726,11 @@ MP_DEFINE_CONST_OBJ_TYPE( ); #if MICROPY_PY_COLLECTIONS_ORDEREDDICT +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_ordereddict, MP_QSTR_OrderedDict, - MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_dict_make_new, print, dict_print, unary_op, dict_unary_op, @@ -745,7 +748,8 @@ void mp_obj_dict_init(mp_obj_dict_t *dict, size_t n_args) { } mp_obj_t mp_obj_new_dict(size_t n_args) { - mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t); + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_dict_t *o = mp_obj_malloc(mp_obj_dict_t, &mp_type_dict); mp_obj_dict_init(o, n_args); return MP_OBJ_FROM_PTR(o); } diff --git a/py/objenumerate.c b/py/objenumerate.c index 40bed919ed750..8217a0d4f9927 100644 --- a/py/objenumerate.c +++ b/py/objenumerate.c @@ -37,9 +37,9 @@ typedef struct _mp_obj_enumerate_t { mp_int_t cur; } mp_obj_enumerate_t; -STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in); +static mp_obj_t enumerate_iternext(mp_obj_t self_in); -STATIC mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t enumerate_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT static const mp_arg_t allowed_args[] = { { MP_QSTR_iterable, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, @@ -75,7 +75,7 @@ MP_DEFINE_CONST_OBJ_TYPE( iter, enumerate_iternext ); -STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) { +static mp_obj_t enumerate_iternext(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_enumerate)); mp_obj_enumerate_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t next = mp_iternext(self->iter); diff --git a/py/objexcept.c b/py/objexcept.c index 03dbff334e4b0..6a6b1e4d4a7a5 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -31,8 +31,6 @@ #include #include "py/objlist.h" -// CIRCUITPY-CHANGE -#include "py/objnamedtuple.h" #include "py/objstr.h" #include "py/objtuple.h" #include "py/objtype.h" @@ -129,7 +127,7 @@ mp_obj_exception_t *mp_obj_exception_get_native(mp_obj_t self_in) { } } -STATIC void decompress_error_text_maybe(mp_obj_exception_t *o) { +static void decompress_error_text_maybe(mp_obj_exception_t *o) { #if MICROPY_ROM_TEXT_COMPRESSION if (o->args->len == 1 && mp_obj_is_exact_type(o->args->items[0], &mp_type_str)) { mp_obj_str_t *o_str = MP_OBJ_TO_PTR(o->args->items[0]); @@ -485,8 +483,9 @@ mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, size_t n_args, } #if MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_NONE + mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { - // CIRCUITPY-CHANGE: is different here and for many lines below. + // CIRCUITPY-CHANGE return mp_obj_new_exception_msg_varg(exc_type, msg); } @@ -501,7 +500,7 @@ struct _exc_printer_t { byte *buf; }; -STATIC void exc_add_strn(void *data, const char *str, size_t len) { +static void exc_add_strn(void *data, const char *str, size_t len) { struct _exc_printer_t *pr = data; if (pr->len + len >= pr->alloc) { // Not enough room for data plus a null byte so try to grow the buffer @@ -538,10 +537,14 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_er assert(MP_OBJ_TYPE_GET_SLOT_OR_NULL(exc_type, make_new) == mp_obj_exception_make_new); // Try to allocate memory for the message - mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); + mp_obj_str_t *o_str = NULL; + byte *o_str_buf = NULL; // CIRCUITPY-CHANGE: here and more below size_t o_str_alloc = decompress_length(fmt); - byte *o_str_buf = m_new_maybe(byte, o_str_alloc); + if (gc_alloc_possible()) { + o_str = m_new_obj_maybe(mp_obj_str_t); + o_str_buf = m_new_maybe(byte, o_str_alloc); + } bool used_emg_buf = false; #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF @@ -566,6 +569,7 @@ mp_obj_t mp_obj_new_exception_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_er } if (o_str_buf == NULL) { + // CIRCUITPY-CHANGE: different way of building message // No memory for the string buffer: the string is compressed so don't add it. o_str->len = 0; o_str->data = NULL; @@ -723,126 +727,3 @@ void mp_obj_exception_get_traceback(mp_obj_t self_in, size_t *n, size_t **values *values = self->traceback->data; } } - -// CIRCUITPY-CHANGE: here until end -#if MICROPY_PY_SYS_EXC_INFO -STATIC const mp_obj_namedtuple_type_t code_type_obj = { - NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_code), - .n_fields = 15, - .fields = { - MP_QSTR_co_argcount, - MP_QSTR_co_kwonlyargcount, - MP_QSTR_co_nlocals, - MP_QSTR_co_stacksize, - MP_QSTR_co_flags, - MP_QSTR_co_code, - MP_QSTR_co_consts, - MP_QSTR_co_names, - MP_QSTR_co_varnames, - MP_QSTR_co_freevars, - MP_QSTR_co_cellvars, - MP_QSTR_co_filename, - MP_QSTR_co_name, - MP_QSTR_co_firstlineno, - MP_QSTR_co_lnotab, - }, -}; - -STATIC mp_obj_t code_make_new(qstr file, qstr block) { - mp_obj_t elems[15] = { - mp_obj_new_int(0), // co_argcount - mp_obj_new_int(0), // co_kwonlyargcount - mp_obj_new_int(0), // co_nlocals - mp_obj_new_int(0), // co_stacksize - mp_obj_new_int(0), // co_flags - mp_obj_new_bytearray(0, NULL), // co_code - mp_obj_new_tuple(0, NULL), // co_consts - mp_obj_new_tuple(0, NULL), // co_names - mp_obj_new_tuple(0, NULL), // co_varnames - mp_obj_new_tuple(0, NULL), // co_freevars - mp_obj_new_tuple(0, NULL), // co_cellvars - MP_OBJ_NEW_QSTR(file), // co_filename - MP_OBJ_NEW_QSTR(block), // co_name - mp_obj_new_int(1), // co_firstlineno - mp_obj_new_bytearray(0, NULL), // co_lnotab - }; - - return namedtuple_make_new((const mp_obj_type_t *)&code_type_obj, 15, 0, elems); -} - -STATIC const mp_obj_namedtuple_type_t frame_type_obj = { - NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_frame), - .n_fields = 8, - .fields = { - MP_QSTR_f_back, - MP_QSTR_f_builtins, - MP_QSTR_f_code, - MP_QSTR_f_globals, - MP_QSTR_f_lasti, - MP_QSTR_f_lineno, - MP_QSTR_f_locals, - MP_QSTR_f_trace, - }, -}; - -STATIC mp_obj_t frame_make_new(mp_obj_t f_code, int f_lineno) { - mp_obj_t elems[8] = { - mp_const_none, // f_back - mp_obj_new_dict(0), // f_builtins - f_code, // f_code - mp_obj_new_dict(0), // f_globals - mp_obj_new_int(0), // f_lasti - mp_obj_new_int(f_lineno), // f_lineno - mp_obj_new_dict(0), // f_locals - mp_const_none, // f_trace - }; - - return namedtuple_make_new((const mp_obj_type_t *)&frame_type_obj, 8, 0, elems); -} - -STATIC const mp_obj_namedtuple_type_t traceback_type_obj = { - NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_traceback), - .n_fields = 4, - .fields = { - MP_QSTR_tb_frame, - MP_QSTR_tb_lasti, - MP_QSTR_tb_lineno, - MP_QSTR_tb_next, - }, -}; - -STATIC mp_obj_t traceback_from_values(size_t *values, mp_obj_t tb_next) { - int lineno = values[1]; - - mp_obj_t elems[4] = { - frame_make_new(code_make_new(values[0], values[2]), lineno), - mp_obj_new_int(0), - mp_obj_new_int(lineno), - tb_next, - }; - - return namedtuple_make_new((const mp_obj_type_t *)&traceback_type_obj, 4, 0, elems); -}; - -mp_obj_t mp_obj_exception_get_traceback_obj(mp_obj_t self_in) { - mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in); - - if (!mp_obj_is_exception_instance(self)) { - return mp_const_none; - } - - size_t n, *values; - mp_obj_exception_get_traceback(self, &n, &values); - if (n == 0) { - return mp_const_none; - } - - mp_obj_t tb_next = mp_const_none; - - for (size_t i = 0; i < n; i += 3) { - tb_next = traceback_from_values(&values[i], tb_next); - } - - return tb_next; -} -#endif diff --git a/py/objfilter.c b/py/objfilter.c index 2a657fde4b71b..7f1f700f6a607 100644 --- a/py/objfilter.c +++ b/py/objfilter.c @@ -34,7 +34,7 @@ typedef struct _mp_obj_filter_t { mp_obj_t iter; } mp_obj_filter_t; -STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, 2, false); mp_obj_filter_t *o = mp_obj_malloc(mp_obj_filter_t, type); o->fun = args[0]; @@ -42,7 +42,7 @@ STATIC mp_obj_t filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t filter_iternext(mp_obj_t self_in) { +static mp_obj_t filter_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_filter)); mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t next; diff --git a/py/objfloat.c b/py/objfloat.c index 9129c364032d0..ecc0f61a6abc9 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -34,6 +34,11 @@ #if MICROPY_PY_BUILTINS_FLOAT +// Workaround a bug in Windows SDK version 10.0.26100.0, where NAN is no longer constant. +#if defined(_MSC_VER) && !defined(_UCRT_NOISY_NAN) +#define _UCRT_NOISY_NAN +#endif + #include #include "py/formatfloat.h" @@ -106,29 +111,13 @@ mp_int_t mp_float_hash(mp_float_t src) { } #endif -STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_float_t o_val = mp_obj_float_get(o_in); - #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT - char buf[16]; - #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C - const int precision = 6; - #else - const int precision = 7; - #endif - #else - char buf[32]; - const int precision = 16; - #endif - mp_format_float(o_val, buf, sizeof(buf), 'g', precision, '\0'); - mp_print_str(print, buf); - if (strchr(buf, '.') == NULL && strchr(buf, 'e') == NULL && strchr(buf, 'n') == NULL) { - // Python floats always have decimal point (unless inf or nan) - mp_print_str(print, ".0"); - } + mp_print_float(print, o_val, 'g', PF_FLAG_ALWAYS_DECIMAL, '\0', -1, MP_FLOAT_REPR_PREC); } -STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); @@ -153,7 +142,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size } } -STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_float_t val = mp_obj_float_get(o_in); switch (op) { case MP_UNARY_OP_BOOL: @@ -176,7 +165,7 @@ STATIC mp_obj_t float_unary_op(mp_unary_op_t op, mp_obj_t o_in) { } } -STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { mp_float_t lhs_val = mp_obj_float_get(lhs_in); #if MICROPY_PY_BUILTINS_COMPLEX if (mp_obj_is_type(rhs_in, &mp_type_complex)) { @@ -186,8 +175,9 @@ STATIC mp_obj_t float_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs return mp_obj_float_binary_op(op, lhs_val, rhs_in); } +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( - mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE, + mp_type_float, MP_QSTR_float, MP_TYPE_FLAG_EQ_NOT_REFLEXIVE | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_PRINT_JSON, make_new, float_make_new, print, float_print, unary_op, float_unary_op, @@ -197,9 +187,8 @@ MP_DEFINE_CONST_OBJ_TYPE( #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D mp_obj_t mp_obj_new_float(mp_float_t value) { - // Don't use mp_obj_malloc here to avoid extra function call overhead. - mp_obj_float_t *o = m_new_obj(mp_obj_float_t); - o->base.type = &mp_type_float; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_float_t *o = mp_obj_malloc(mp_obj_float_t, &mp_type_float); o->value = value; return MP_OBJ_FROM_PTR(o); } @@ -212,7 +201,7 @@ mp_float_t mp_obj_float_get(mp_obj_t self_in) { #endif -STATIC void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { +static void mp_obj_float_divmod(mp_float_t *x, mp_float_t *y) { // logic here follows that of CPython // https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations // x == (x//y)*y + (x%y) @@ -317,6 +306,10 @@ mp_obj_t mp_obj_float_binary_op(mp_binary_op_t op, mp_float_t lhs_val, mp_obj_t lhs_val = MICROPY_FLOAT_CONST(1.0); break; } + if (isnan(rhs_val)) { + lhs_val = rhs_val; + break; + } #endif lhs_val = MICROPY_FLOAT_C_FUN(pow)(lhs_val, rhs_val); break; diff --git a/py/objfun.c b/py/objfun.c index 46145129eb4ec..34565cf633632 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -28,11 +28,13 @@ #include #include +#include "py/emitglue.h" +#include "py/objcode.h" #include "py/objtuple.h" #include "py/objfun.h" #include "py/runtime.h" #include "py/bc.h" -#include "py/stackctrl.h" +#include "py/cstack.h" #if MICROPY_DEBUG_VERBOSE // print debugging info #define DEBUG_PRINT (1) @@ -49,7 +51,7 @@ /* builtin functions */ // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_0_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t PLACE_IN_ITCM(fun_builtin_0_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)args; assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_0)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); @@ -63,7 +65,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_1_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t PLACE_IN_ITCM(fun_builtin_1_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_1)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 1, 1, false); @@ -75,7 +77,7 @@ MP_DEFINE_CONST_OBJ_TYPE( call, fun_builtin_1_call ); -STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_2)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 2, 2, false); @@ -88,7 +90,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_builtin_3_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t PLACE_IN_ITCM(fun_builtin_3_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_3)); mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); mp_arg_check_num(n_args, n_kw, 3, 3, false); @@ -100,7 +102,7 @@ MP_DEFINE_CONST_OBJ_TYPE( call, fun_builtin_3_call ); -STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_type(self_in, &mp_type_fun_builtin_var)); mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in); @@ -110,7 +112,9 @@ STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_k if (self->sig & 1) { // function allows keywords - // we create a map directly from the given args array + // we create a map directly from the given args array; self->fun.kw does still + // expect args to have both positional and keyword arguments, ordered as: + // arg0 arg1 ... arg key0 value0 key1 value1 ... key value mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); @@ -131,43 +135,62 @@ MP_DEFINE_CONST_OBJ_TYPE( /******************************************************************************/ /* byte code functions */ -STATIC qstr mp_obj_code_get_name(const mp_obj_fun_bc_t *fun, const byte *code_info) { - MP_BC_PRELUDE_SIZE_DECODE(code_info); - mp_uint_t name = mp_decode_uint_value(code_info); +qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { + const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in); + const byte *bc = fun->bytecode; + + #if MICROPY_EMIT_NATIVE + if (fun->base.type == &mp_type_fun_native || fun->base.type == &mp_type_native_gen_wrap) { + bc = mp_obj_fun_native_get_prelude_ptr(fun); + } + #endif + + MP_BC_PRELUDE_SIG_DECODE(bc); + MP_BC_PRELUDE_SIZE_DECODE(bc); + + mp_uint_t name = mp_decode_uint_value(bc); #if MICROPY_EMIT_BYTECODE_USES_QSTR_TABLE name = fun->context->constants.qstr_table[name]; #endif + return name; } -#if MICROPY_EMIT_NATIVE -STATIC const mp_obj_type_t mp_type_fun_native; -#endif +#if MICROPY_PY_FUNCTION_ATTRS_CODE +static mp_obj_t fun_bc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + (void)type; + mp_arg_check_num(n_args, n_kw, 2, 2, false); -qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) { - const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in); - #if MICROPY_EMIT_NATIVE - if (fun->base.type == &mp_type_fun_native || fun->base.type == &mp_type_native_gen_wrap) { - // TODO native functions don't have name stored - return MP_QSTR_; + if (!mp_obj_is_type(args[0], &mp_type_code)) { + mp_raise_TypeError(NULL); + } + if (!mp_obj_is_type(args[1], &mp_type_dict)) { + mp_raise_TypeError(NULL); } - #endif - const byte *bc = fun->bytecode; - MP_BC_PRELUDE_SIG_DECODE(bc); - return mp_obj_code_get_name(fun, bc); + mp_obj_code_t *code = MP_OBJ_TO_PTR(args[0]); + mp_obj_t globals = args[1]; + + mp_module_context_t *module_context = m_new_obj(mp_module_context_t); + module_context->module.base.type = &mp_type_module; + module_context->module.globals = MP_OBJ_TO_PTR(globals); + module_context->constants = *mp_code_get_constants(code); + + return mp_make_function_from_proto_fun(mp_code_get_proto_fun(code), module_context, NULL); } +#endif #if MICROPY_CPYTHON_COMPAT -STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "", mp_obj_fun_get_name(o_in), o); + // CIRCUITPY-CHANGE: %p already prints "0x", so don't include it explicitly. + mp_printf(print, "", mp_obj_fun_get_name(o_in), o); } #endif #if DEBUG_PRINT -STATIC void dump_args(const mp_obj_t *a, size_t sz) { +static void dump_args(const mp_obj_t *a, size_t sz) { DEBUG_printf("%p: ", a); for (size_t i = 0; i < sz; i++) { DEBUG_printf("%p ", a[i]); @@ -203,7 +226,7 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) { #if MICROPY_STACKLESS mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - MP_STACK_CHECK(); + mp_cstack_check(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); size_t n_state, state_size; @@ -234,8 +257,8 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args #endif // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_bc_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - MP_STACK_CHECK(); +static mp_obj_t PLACE_IN_ITCM(fun_bc_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_cstack_check(); DEBUG_printf("Input n_args: " UINT_FMT ", n_kw: " UINT_FMT "\n", n_args, n_kw); DEBUG_printf("Input pos args: "); @@ -348,9 +371,29 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); dest[0] = MP_OBJ_FROM_PTR(self->context->module.globals); } + #if MICROPY_PY_FUNCTION_ATTRS_CODE + if (attr == MP_QSTR___code__) { + const mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); + if ((self->base.type == &mp_type_fun_bc + || self->base.type == &mp_type_gen_wrap) + && self->child_table == NULL) { + #if MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC + dest[0] = mp_obj_new_code(self->context->constants, self->bytecode); + #else + dest[0] = mp_obj_new_code(self->context, self->rc, true); + #endif + } + } + #endif } #endif +#if MICROPY_PY_FUNCTION_ATTRS_CODE +#define FUN_BC_MAKE_NEW make_new, fun_bc_make_new, +#else +#define FUN_BC_MAKE_NEW +#endif + #if MICROPY_CPYTHON_COMPAT #define FUN_BC_TYPE_PRINT print, fun_bc_print, #else @@ -367,6 +410,7 @@ MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_bc, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, + FUN_BC_MAKE_NEW FUN_BC_TYPE_PRINT FUN_BC_TYPE_ATTR call, fun_bc_call @@ -388,7 +432,7 @@ mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_ def_kw_args = def_args[1]; n_extra_args += 1; } - mp_obj_fun_bc_t *o = mp_obj_malloc_var(mp_obj_fun_bc_t, mp_obj_t, n_extra_args, &mp_type_fun_bc); + mp_obj_fun_bc_t *o = mp_obj_malloc_var(mp_obj_fun_bc_t, extra_args, mp_obj_t, n_extra_args, &mp_type_fun_bc); o->bytecode = code; o->context = context; o->child_table = child_table; @@ -407,10 +451,10 @@ mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_ #if MICROPY_EMIT_NATIVE // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_native_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - MP_STACK_CHECK(); +static mp_obj_t PLACE_IN_ITCM(fun_native_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_cstack_check(); mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); - mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void *)self->bytecode); + mp_call_fun_t fun = mp_obj_fun_native_get_function_start(self); return fun(self_in, n_args, n_kw, args); } @@ -425,7 +469,7 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_native_call)(mp_obj_t self_in, size_t n_args, #define FUN_BC_TYPE_ATTR #endif -STATIC MP_DEFINE_CONST_OBJ_TYPE( +MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_native, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, @@ -434,12 +478,27 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( call, fun_native_call ); -mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { - mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table)); - o->base.type = &mp_type_fun_native; - return MP_OBJ_FROM_PTR(o); +#endif // MICROPY_EMIT_NATIVE + +/******************************************************************************/ +/* viper functions */ + +#if MICROPY_EMIT_NATIVE + +static mp_obj_t fun_viper_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_cstack_check(); + mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in); + mp_call_fun_t fun = MICROPY_MAKE_POINTER_CALLABLE((void *)self->bytecode); + return fun(self_in, n_args, n_kw, args); } +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_fun_viper, + MP_QSTR_function, + MP_TYPE_FLAG_BINDS_SELF, + call, fun_viper_call + ); + #endif // MICROPY_EMIT_NATIVE /******************************************************************************/ @@ -447,13 +506,6 @@ mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, c #if MICROPY_EMIT_INLINE_ASM -typedef struct _mp_obj_fun_asm_t { - mp_obj_base_t base; - size_t n_args; - const void *fun_data; // GC must be able to trace this pointer - mp_uint_t type_sig; -} mp_obj_fun_asm_t; - typedef mp_uint_t (*inline_asm_fun_0_t)(void); typedef mp_uint_t (*inline_asm_fun_1_t)(mp_uint_t); typedef mp_uint_t (*inline_asm_fun_2_t)(mp_uint_t, mp_uint_t); @@ -461,7 +513,7 @@ typedef mp_uint_t (*inline_asm_fun_3_t)(mp_uint_t, mp_uint_t, mp_uint_t); typedef mp_uint_t (*inline_asm_fun_4_t)(mp_uint_t, mp_uint_t, mp_uint_t, mp_uint_t); // convert a MicroPython object to a sensible value for inline asm -STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { +static mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { // TODO for byte_array, pass pointer to the array if (mp_obj_is_small_int(obj)) { return MP_OBJ_SMALL_INT_VALUE(obj); @@ -505,7 +557,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) { } // CIRCUITPY-CHANGE: PLACE_IN_ITCM -STATIC mp_obj_t PLACE_IN_ITCM(fun_asm_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t PLACE_IN_ITCM(fun_asm_call)(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_fun_asm_t *self = self_in; mp_arg_check_num(n_args, n_kw, self->n_args, self->n_args, false); @@ -535,19 +587,11 @@ STATIC mp_obj_t PLACE_IN_ITCM(fun_asm_call)(mp_obj_t self_in, size_t n_args, siz return mp_native_to_obj(ret, self->type_sig); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +MP_DEFINE_CONST_OBJ_TYPE( mp_type_fun_asm, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, call, fun_asm_call ); -mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) { - mp_obj_fun_asm_t *o = mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm); - o->n_args = n_args; - o->fun_data = fun_data; - o->type_sig = type_sig; - return MP_OBJ_FROM_PTR(o); -} - #endif // MICROPY_EMIT_INLINE_ASM diff --git a/py/objfun.h b/py/objfun.h index 9de15b8841553..4059343983c2b 100644 --- a/py/objfun.h +++ b/py/objfun.h @@ -43,9 +43,82 @@ typedef struct _mp_obj_fun_bc_t { mp_obj_t extra_args[]; } mp_obj_fun_bc_t; +typedef struct _mp_obj_fun_asm_t { + mp_obj_base_t base; + size_t n_args; + const void *fun_data; // GC must be able to trace this pointer + mp_uint_t type_sig; +} mp_obj_fun_asm_t; + mp_obj_t mp_obj_new_fun_bc(const mp_obj_t *def_args, const byte *code, const mp_module_context_t *cm, struct _mp_raw_code_t *const *raw_code_table); -mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *cm, struct _mp_raw_code_t *const *raw_code_table); -mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig); void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest); +#if MICROPY_EMIT_NATIVE + +static inline mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { + mp_obj_fun_bc_t *o = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table)); + o->base.type = &mp_type_fun_native; + return MP_OBJ_FROM_PTR(o); +} + +static inline mp_obj_t mp_obj_new_fun_viper(const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) { + mp_obj_fun_bc_t *o = mp_obj_malloc(mp_obj_fun_bc_t, &mp_type_fun_viper); + o->bytecode = (const byte *)fun_data; + o->context = mc; + o->child_table = child_table; + return MP_OBJ_FROM_PTR(o); +} + +static inline const uint8_t *mp_obj_fun_native_get_prelude_ptr(const mp_obj_fun_bc_t *fun_native) { + // Obtain a pointer to the start of the function prelude, based on prelude_ptr_index. + // CIRCUITPY-CHANGE: prevent warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + uintptr_t prelude_ptr_index = ((uintptr_t *)fun_native->bytecode)[0]; + #pragma GCC diagnostic pop + const uint8_t *prelude_ptr; + if (prelude_ptr_index == 0) { + prelude_ptr = (const uint8_t *)fun_native->child_table; + } else { + prelude_ptr = (const uint8_t *)fun_native->child_table[prelude_ptr_index]; + } + return prelude_ptr; +} + +static inline void *mp_obj_fun_native_get_function_start(const mp_obj_fun_bc_t *fun_native) { + // Obtain a pointer to the start of the function executable machine code. + return MICROPY_MAKE_POINTER_CALLABLE((void *)(fun_native->bytecode + sizeof(uintptr_t))); +} + +static inline void *mp_obj_fun_native_get_generator_start(const mp_obj_fun_bc_t *fun_native) { + // Obtain a pointer to the start of the generator executable machine code. + // CIRCUITPY-CHANGE: prevent warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + uintptr_t start_offset = ((uintptr_t *)fun_native->bytecode)[1]; + #pragma GCC diagnostic pop + return MICROPY_MAKE_POINTER_CALLABLE((void *)(fun_native->bytecode + start_offset)); +} + +static inline void *mp_obj_fun_native_get_generator_resume(const mp_obj_fun_bc_t *fun_native) { + // Obtain a pointer to the resume location of the generator executable machine code. + // CIRCUITPY-CHANGE: prevent warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wcast-align" + return MICROPY_MAKE_POINTER_CALLABLE((void *)&((uintptr_t *)fun_native->bytecode)[2]); + #pragma GCC diagnostic pop +} + +#endif + +#if MICROPY_EMIT_INLINE_ASM +static inline mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) { + mp_obj_fun_asm_t *o = (mp_obj_fun_asm_t *)mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm); + o->n_args = n_args; + o->fun_data = (const byte *)fun_data; + o->type_sig = type_sig; + return MP_OBJ_FROM_PTR(o); +} +#endif + #endif // MICROPY_INCLUDED_PY_OBJFUN_H diff --git a/py/objgenerator.c b/py/objgenerator.c index 6dc1f17aa8034..de063d384587d 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -33,7 +33,7 @@ #include "py/objstr.h" #include "py/objgenerator.h" #include "py/objfun.h" -#include "py/stackctrl.h" +#include "py/cstack.h" // Instance of GeneratorExit exception - needed by generator.close() // CIRCUITPY-CHANGE: https://github.com/adafruit/circuitpython/pull/7069 fix @@ -57,7 +57,7 @@ typedef struct _mp_obj_gen_instance_t { mp_code_state_t code_state; } mp_obj_gen_instance_t; -STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // CIRCUITPY-CHANGE // A generating or coroutine function is just a bytecode function // with type mp_type_gen_wrap or mp_type_coro_wrap. @@ -69,7 +69,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons // CIRCUITPY-CHANGE // allocate the generator or coroutine object, with room for local stack and exception stack - mp_obj_gen_instance_t *o = mp_obj_malloc_var(mp_obj_gen_instance_t, byte, + mp_obj_gen_instance_t *o = mp_obj_malloc_var(mp_obj_gen_instance_t, code_state.state, byte, n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t), // CIRCUITPY-CHANGE #if MICROPY_PY_ASYNC_AWAIT @@ -123,29 +123,19 @@ typedef struct _mp_obj_gen_instance_native_t { mp_code_state_native_t code_state; } mp_obj_gen_instance_native_t; -STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // The state for a native generating function is held in the same struct as a bytecode function mp_obj_fun_bc_t *self_fun = MP_OBJ_TO_PTR(self_in); // Determine start of prelude. - // CIRCUITPY-CHANGE: prevent compiler warning - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - uintptr_t prelude_ptr_index = ((uintptr_t *)self_fun->bytecode)[0]; - #pragma GCC diagnostic pop - const uint8_t *prelude_ptr; - if (prelude_ptr_index == 0) { - prelude_ptr = (void *)self_fun->child_table; - } else { - prelude_ptr = (void *)self_fun->child_table[prelude_ptr_index]; - } + const uint8_t *prelude_ptr = mp_obj_fun_native_get_prelude_ptr(self_fun); // Extract n_state from the prelude. const uint8_t *ip = prelude_ptr; MP_BC_PRELUDE_SIG_DECODE(ip); // Allocate the generator object, with room for local stack (exception stack not needed). - mp_obj_gen_instance_native_t *o = mp_obj_malloc_var(mp_obj_gen_instance_native_t, byte, n_state * sizeof(mp_obj_t), + mp_obj_gen_instance_native_t *o = mp_obj_malloc_var(mp_obj_gen_instance_native_t, code_state.state, byte, n_state * sizeof(mp_obj_t), // CIRCUITPY-CHANGE #if MICROPY_PY_ASYNC_AWAIT (self_fun->base.type == &mp_type_native_gen_wrap) ? &mp_type_gen_instance : &mp_type_coro_instance @@ -157,21 +147,14 @@ STATIC mp_obj_t native_gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_k // Parse the input arguments and set up the code state o->pend_exc = mp_const_none; o->code_state.fun_bc = self_fun; - o->code_state.ip = prelude_ptr; o->code_state.n_state = n_state; - o->code_state.sp = &o->code_state.state[0] - 1; mp_setup_code_state_native(&o->code_state, n_args, n_kw, args); // Indicate we are a native function, which doesn't use this variable o->code_state.exc_sp_idx = MP_CODE_STATE_EXC_SP_IDX_SENTINEL; // Prepare the generator instance for execution - // CIRCUITPY-CHANGE: prevent compiler warning - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wcast-align" - uintptr_t start_offset = ((uintptr_t *)self_fun->bytecode)[1]; - #pragma GCC diagnostic pop - o->code_state.ip = MICROPY_MAKE_POINTER_CALLABLE((void *)(self_fun->bytecode + start_offset)); + o->code_state.ip = mp_obj_fun_native_get_generator_start(self_fun); return MP_OBJ_FROM_PTR(o); } @@ -206,7 +189,7 @@ MP_DEFINE_CONST_OBJ_TYPE( /******************************************************************************/ /* generator instance */ -STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); @@ -214,7 +197,7 @@ STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pri // CIRCUITPY-CHANGE #if MICROPY_PY_ASYNC_AWAIT -STATIC void coro_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void coro_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self); @@ -222,7 +205,7 @@ STATIC void coro_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_pr #endif mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) { - MP_STACK_CHECK(); + mp_cstack_check(); // CIRCUITPY-CHANGE // note that self may have as its type either gen or coro, // both of which are stored as an mp_obj_gen_instance_t . @@ -278,9 +261,9 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ #if MICROPY_EMIT_NATIVE if (self->code_state.exc_sp_idx == MP_CODE_STATE_EXC_SP_IDX_SENTINEL) { - // A native generator, with entry point 2 words into the "bytecode" pointer + // A native generator. typedef uintptr_t (*mp_fun_native_gen_t)(void *, mp_obj_t); - mp_fun_native_gen_t fun = MICROPY_MAKE_POINTER_CALLABLE((const void *)(self->code_state.fun_bc->bytecode + 2 * sizeof(uintptr_t))); + mp_fun_native_gen_t fun = mp_obj_fun_native_get_generator_resume(self->code_state.fun_bc); ret_kind = fun((void *)&self->code_state, throw_value); } else #endif @@ -333,7 +316,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ return ret_kind; } -STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, bool raise_stop_iteration) { +static mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, bool raise_stop_iteration) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) { case MP_VM_RETURN_NORMAL: @@ -357,24 +340,24 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o } } -STATIC mp_obj_t gen_instance_iternext(mp_obj_t self_in) { +static mp_obj_t gen_instance_iternext(mp_obj_t self_in) { return gen_resume_and_raise(self_in, mp_const_none, MP_OBJ_NULL, false); } -STATIC mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { +static mp_obj_t gen_instance_send(mp_obj_t self_in, mp_obj_t send_value) { return gen_resume_and_raise(self_in, send_value, MP_OBJ_NULL, true); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); +static MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_send_obj, gen_instance_send); // CIRCUITPY-CHANGE #if MICROPY_PY_ASYNC_AWAIT -STATIC mp_obj_t coro_instance_await(mp_obj_t self_in) { +static mp_obj_t coro_instance_await(mp_obj_t self_in) { return self_in; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(coro_instance_await_obj, coro_instance_await); +static MP_DEFINE_CONST_FUN_OBJ_1(coro_instance_await_obj, coro_instance_await); #endif -STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { +static mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { // The signature of this function is: throw(type[, value[, traceback]]) // CPython will pass all given arguments through the call chain and process them // at the point they are used (native generators will handle them differently to @@ -394,7 +377,7 @@ STATIC mp_obj_t gen_instance_throw(size_t n_args, const mp_obj_t *args) { return gen_resume_and_raise(args[0], mp_const_none, exc, true); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_instance_throw); // CIRCUITPY-CHANGE static mp_obj_t generatorexit(void) { @@ -407,7 +390,7 @@ static mp_obj_t generatorexit(void) { #endif } -STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { +static mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; // CIRCUITPY-CHANGE switch (mp_obj_gen_resume(self_in, mp_const_none, generatorexit(), &ret)) { @@ -427,10 +410,10 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { return mp_const_none; } } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); +static MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close); #if MICROPY_PY_GENERATOR_PEND_THROW -STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { +static mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in); if (self->pend_exc == MP_OBJ_NULL) { mp_raise_ValueError(MP_ERROR_TEXT("generator already executing")); @@ -439,10 +422,10 @@ STATIC mp_obj_t gen_instance_pend_throw(mp_obj_t self_in, mp_obj_t exc_in) { self->pend_exc = exc_in; return prev; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); +static MP_DEFINE_CONST_FUN_OBJ_2(gen_instance_pend_throw_obj, gen_instance_pend_throw); #endif -STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { +static const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) }, { MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) }, @@ -451,7 +434,7 @@ STATIC const mp_rom_map_elem_t gen_instance_locals_dict_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); +static MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_gen_instance, @@ -466,7 +449,7 @@ MP_DEFINE_CONST_OBJ_TYPE( #if MICROPY_PY_ASYNC_AWAIT // coroutine instance locals dict and type // same as generator, but with addition of __await()__. -STATIC const mp_rom_map_elem_t coro_instance_locals_dict_table[] = { +static const mp_rom_map_elem_t coro_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&gen_instance_close_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&gen_instance_send_obj) }, { MP_ROM_QSTR(MP_QSTR_throw), MP_ROM_PTR(&gen_instance_throw_obj) }, @@ -476,7 +459,7 @@ STATIC const mp_rom_map_elem_t coro_instance_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___await__), MP_ROM_PTR(&coro_instance_await_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(coro_instance_locals_dict, coro_instance_locals_dict_table); +static MP_DEFINE_CONST_DICT(coro_instance_locals_dict, coro_instance_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_coro_instance, diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c index c598d1daaca9a..c735c65b652d6 100644 --- a/py/objgetitemiter.c +++ b/py/objgetitemiter.c @@ -35,7 +35,7 @@ typedef struct _mp_obj_getitem_iter_t { mp_obj_t args[3]; } mp_obj_getitem_iter_t; -STATIC mp_obj_t it_iternext(mp_obj_t self_in) { +static mp_obj_t it_iternext(mp_obj_t self_in) { mp_obj_getitem_iter_t *self = MP_OBJ_TO_PTR(self_in); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { @@ -56,7 +56,7 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) { } } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, diff --git a/py/objint.c b/py/objint.c index f8fb9b5113754..cabbd7b8f0e12 100644 --- a/py/objint.c +++ b/py/objint.c @@ -40,7 +40,7 @@ #endif // This dispatcher function is expected to be independent of the implementation of long int -STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 2, false); @@ -55,7 +55,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args, return o; } else if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) { // a textual representation, parse it - return mp_parse_num_integer(bufinfo.buf, bufinfo.len, 0, NULL); + return mp_parse_num_integer(bufinfo.buf, bufinfo.len, 10, NULL); #if MICROPY_PY_BUILTINS_FLOAT } else if (mp_obj_is_float(args[0])) { return mp_obj_new_int_from_float(mp_obj_float_get(args[0])); @@ -83,7 +83,7 @@ typedef enum { MP_FP_CLASS_OVERFLOW } mp_fp_as_int_class_t; -STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { +static mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { union { mp_float_t f; #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT @@ -117,9 +117,15 @@ STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) { } // 8 * sizeof(uintptr_t) counts the number of bits for a small int // TODO provide a way to configure this properly + #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B + if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 4) << MP_FLOAT_EXP_SHIFT_I32)) { + return MP_FP_CLASS_FIT_SMALLINT; + } + #else if (e <= ((8 * sizeof(uintptr_t) + MP_FLOAT_EXP_BIAS - 3) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_SMALLINT; } + #endif #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG if (e <= (((sizeof(long long) * MP_BITS_PER_BYTE) + MP_FLOAT_EXP_BIAS - 2) << MP_FLOAT_EXP_SHIFT_I32)) { return MP_FP_CLASS_FIT_LONGINT; @@ -195,7 +201,7 @@ void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } } -STATIC const uint8_t log_base2_floor[] = { +static const uint8_t log_base2_floor[] = { 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, @@ -211,7 +217,7 @@ STATIC const uint8_t log_base2_floor[] = { size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) { assert(2 <= base && base <= 16); size_t num_digits = num_bits / log_base2_floor[base - 1] + 1; - size_t num_commas = comma ? num_digits / 3 : 0; + size_t num_commas = comma ? (base == 10 ? num_digits / 3 : num_digits / 4): 0; size_t prefix_len = prefix ? strlen(prefix) : 0; return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte } @@ -249,10 +255,11 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co char sign = '\0'; if (num < 0) { - num = -num; + num = -(fmt_uint_t)num; sign = '-'; } + int n_comma = (base == 10) ? 3 : 4; size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); @@ -277,7 +284,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co c += '0'; } *(--b) = c; - if (comma && num != 0 && b > str && (last_comma - b) == 3) { + if (comma && num != 0 && b > str && (last_comma - b) == n_comma) { *(--b) = comma; last_comma = b; } @@ -308,7 +315,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co void mp_obj_int_buffer_overflow_check(mp_obj_t self_in, size_t nbytes, bool is_signed) { if (is_signed) { // self must be < 2**(bits - 1) - mp_obj_t edge = mp_binary_op(MP_BINARY_OP_INPLACE_LSHIFT, + mp_obj_t edge = mp_binary_op(MP_BINARY_OP_LSHIFT, mp_obj_new_int(1), mp_obj_new_int(nbytes * 8 - 1)); @@ -323,7 +330,7 @@ void mp_obj_int_buffer_overflow_check(mp_obj_t self_in, size_t nbytes, bool is_s // self must be >= 0 if (mp_obj_int_sign(self_in) >= 0) { // and < 2**(bits) - mp_obj_t edge = mp_binary_op(MP_BINARY_OP_INPLACE_LSHIFT, + mp_obj_t edge = mp_binary_op(MP_BINARY_OP_LSHIFT, mp_obj_new_int(1), mp_obj_new_int(nbytes * 8)); @@ -462,7 +469,7 @@ mp_obj_t mp_obj_int_binary_op_extra_cases(mp_binary_op_t op, mp_obj_t lhs_in, mp // CIRCUITPY-CHANGE #if MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t int_bit_length(mp_obj_t self_in) { +static mp_obj_t int_bit_length(mp_obj_t self_in) { #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE if (!mp_obj_is_small_int(self_in)) { return mp_obj_int_bit_length_impl(self_in); @@ -484,13 +491,14 @@ MP_DEFINE_CONST_FUN_OBJ_1(int_bit_length_obj, int_bit_length); // CIRCUITPY-CHANGE: more functionality // this is a classmethod -STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // TODO: Support signed param (assumes signed=False at the moment) enum { ARG_bytes, ARG_byteorder, ARG_signed }; static const mp_arg_t allowed_args[] = { { MP_QSTR_bytes, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = NULL} }, - { MP_QSTR_byteorder, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = NULL} }, + // CIRCUITPY-CHANGE: not required and given a default value. + { MP_QSTR_byteorder, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_big)} }, { MP_QSTR_signed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -527,15 +535,17 @@ STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t return mp_obj_new_int_from_uint(value); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_from_bytes_fun_obj, 3, int_from_bytes); -STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj)); +// CIRCUITPY-CHANGE: only two required args. +static MP_DEFINE_CONST_FUN_OBJ_KW(int_from_bytes_fun_obj, 2, int_from_bytes); +static MP_DEFINE_CONST_CLASSMETHOD_OBJ(int_from_bytes_obj, MP_ROM_PTR(&int_from_bytes_fun_obj)); // CIRCUITPY-CHANGE: supports signed -STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_length, ARG_byteorder, ARG_signed }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_length, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_byteorder, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_length, MP_ARG_INT, {.u_int = 1} }, + // CIRCUITPY-CHANGE: not required and given a default value. + { MP_QSTR_byteorder, MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_QSTR(MP_QSTR_big)} }, { MP_QSTR_signed, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -575,9 +585,9 @@ STATIC mp_obj_t int_to_bytes(size_t n_args, const mp_obj_t *pos_args, mp_map_t * return mp_obj_new_bytes_from_vstr(&vstr); } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 3, int_to_bytes); +static MP_DEFINE_CONST_FUN_OBJ_KW(int_to_bytes_obj, 1, int_to_bytes); -STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { +static const mp_rom_map_elem_t int_locals_dict_table[] = { // CIRCUITPY-CHANGE #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR_bit_length), MP_ROM_PTR(&int_bit_length_obj) }, @@ -586,12 +596,13 @@ STATIC const mp_rom_map_elem_t int_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_to_bytes), MP_ROM_PTR(&int_to_bytes_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); +static MP_DEFINE_CONST_DICT(int_locals_dict, int_locals_dict_table); +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_int, MP_QSTR_int, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_int_make_new, print, mp_obj_int_print, unary_op, mp_obj_int_unary_op, diff --git a/py/objint.h b/py/objint.h index b081d6590517a..92466bae4e26e 100644 --- a/py/objint.h +++ b/py/objint.h @@ -64,7 +64,8 @@ mp_int_t mp_obj_int_hash(mp_obj_t self_in); // CIRCUITPY-CHANGE mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in); mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf); -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); +// Returns true if 'self_in' fit into 'len' bytes of 'buf' without overflowing, 'buf' is truncated otherwise. +bool mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in); mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index 70d7e2873c55f..f24aa0cc18664 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -43,6 +43,10 @@ const mp_obj_int_t mp_sys_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif +static void raise_long_long_overflow(void) { + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("result overflows long long storage")); +} + // CIRCUITPY-CHANGE: bit_length mp_obj_t mp_obj_int_bit_length_impl(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_int)); @@ -69,10 +73,27 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf return mp_obj_new_int_from_ll(value); } -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { +bool mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; + size_t slen; // Number of bytes to represent val + + // This logic has a twin in objint.c + if (val > 0) { + slen = (sizeof(long long) * 8 - mp_clzll(val) + 7) / 8; + } else if (val < -1) { + slen = (sizeof(long long) * 8 - mp_clzll(~val) + 8) / 8; + } else { + // clz of 0 is defined, so 0 and -1 map to 0 and 1 + slen = -val; + } + + if (slen > len) { + return false; // Would overflow + // TODO: Determine whether to copy and truncate, as some callers probably expect this...? + } + if (big_endian) { byte *b = buf + len; while (b > buf) { @@ -85,6 +106,7 @@ void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byt val >>= 8; } } + return true; } int mp_obj_int_sign(mp_obj_t self_in) { @@ -114,7 +136,6 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { // small int if the value fits without truncation case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_int_t)o->val); - case MP_UNARY_OP_POSITIVE: return o_in; case MP_UNARY_OP_NEGATIVE: @@ -141,6 +162,8 @@ mp_obj_t mp_obj_int_unary_op(mp_unary_op_t op, mp_obj_t o_in) { mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { long long lhs_val; long long rhs_val; + bool overflow = false; + long long result; if (mp_obj_is_small_int(lhs_in)) { lhs_val = MP_OBJ_SMALL_INT_VALUE(lhs_in); @@ -153,21 +176,41 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i rhs_val = MP_OBJ_SMALL_INT_VALUE(rhs_in); } else if (mp_obj_is_exact_type(rhs_in, &mp_type_int)) { rhs_val = ((mp_obj_int_t *)rhs_in)->val; + #if MICROPY_PY_BUILTINS_FLOAT + } else if (mp_obj_is_float(rhs_in)) { + return mp_obj_float_binary_op(op, (mp_float_t)lhs_val, rhs_in); + #endif + #if MICROPY_PY_BUILTINS_COMPLEX + } else if (mp_obj_is_type(rhs_in, &mp_type_complex)) { + return mp_obj_complex_binary_op(op, (mp_float_t)lhs_val, 0, rhs_in); + #endif } else { // delegate to generic function to check for extra cases return mp_obj_int_binary_op_extra_cases(op, lhs_in, rhs_in); } + #if MICROPY_PY_BUILTINS_FLOAT + if (op == MP_BINARY_OP_TRUE_DIVIDE || op == MP_BINARY_OP_INPLACE_TRUE_DIVIDE) { + if (rhs_val == 0) { + goto zero_division; + } + return mp_obj_new_float((mp_float_t)lhs_val / (mp_float_t)rhs_val); + } + #endif + switch (op) { case MP_BINARY_OP_ADD: case MP_BINARY_OP_INPLACE_ADD: - return mp_obj_new_int_from_ll(lhs_val + rhs_val); + overflow = mp_add_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_SUBTRACT: case MP_BINARY_OP_INPLACE_SUBTRACT: - return mp_obj_new_int_from_ll(lhs_val - rhs_val); + overflow = mp_sub_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: - return mp_obj_new_int_from_ll(lhs_val * rhs_val); + overflow = mp_mul_ll_overflow(lhs_val, rhs_val, &result); + break; case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { @@ -193,9 +236,21 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i case MP_BINARY_OP_LSHIFT: case MP_BINARY_OP_INPLACE_LSHIFT: - return mp_obj_new_int_from_ll(lhs_val << (int)rhs_val); + if (rhs_val < 0) { + // negative shift not allowed + mp_raise_ValueError(MP_ERROR_TEXT("negative shift count")); + } + overflow = rhs_val >= (sizeof(long long) * MP_BITS_PER_BYTE) + || lhs_val > (LLONG_MAX >> rhs_val) + || lhs_val < (LLONG_MIN >> rhs_val); + result = (unsigned long long)lhs_val << rhs_val; + break; case MP_BINARY_OP_RSHIFT: case MP_BINARY_OP_INPLACE_RSHIFT: + if ((int)rhs_val < 0) { + // negative shift not allowed + mp_raise_ValueError(MP_ERROR_TEXT("negative shift count")); + } return mp_obj_new_int_from_ll(lhs_val >> (int)rhs_val); case MP_BINARY_OP_POWER: @@ -207,18 +262,18 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_raise_ValueError(MP_ERROR_TEXT("negative power with no float support")); #endif } - long long ans = 1; - while (rhs_val > 0) { + result = 1; + while (rhs_val > 0 && !overflow) { if (rhs_val & 1) { - ans *= lhs_val; + overflow = mp_mul_ll_overflow(result, lhs_val, &result); } - if (rhs_val == 1) { + if (rhs_val == 1 || overflow) { break; } rhs_val /= 2; - lhs_val *= lhs_val; + overflow = mp_mul_ll_overflow(lhs_val, lhs_val, &lhs_val); } - return mp_obj_new_int_from_ll(ans); + break; } case MP_BINARY_OP_LESS: @@ -236,50 +291,39 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return MP_OBJ_NULL; // op not supported } + if (overflow) { + raise_long_long_overflow(); + } + + return mp_obj_new_int_from_ll(result); + zero_division: - mp_raise_ZeroDivisionError(); + mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("divide by zero")); } mp_obj_t mp_obj_new_int(mp_int_t value) { - if (MP_SMALL_INT_FITS(value)) { - return MP_OBJ_NEW_SMALL_INT(value); - } return mp_obj_new_int_from_ll(value); } mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { - // SMALL_INT accepts only signed numbers, so make sure the input - // value fits completely in the small-int positive range. - if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { - return MP_OBJ_NEW_SMALL_INT(value); - } return mp_obj_new_int_from_ll(value); } mp_obj_t mp_obj_new_int_from_ll(long long val) { + if ((long long)(mp_int_t)val == val && MP_SMALL_INT_FITS(val)) { + return MP_OBJ_NEW_SMALL_INT(val); + } + mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int); o->val = val; - return o; + return MP_OBJ_FROM_PTR(o); } mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { - // TODO raise an exception if the unsigned long long won't fit if (val >> (sizeof(unsigned long long) * 8 - 1) != 0) { - mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("ulonglong too large")); + raise_long_long_overflow(); } - mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int); - o->val = val; - return o; -} - -mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) { - // TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated - // TODO check overflow - mp_obj_int_t *o = mp_obj_malloc(mp_obj_int_t, &mp_type_int); - char *endptr; - o->val = strtoll(*str, &endptr, base); - *str = endptr; - return o; + return mp_obj_new_int_from_ll(val); } mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { @@ -292,8 +336,33 @@ mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) { } mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { - // TODO: Check overflow - return mp_obj_int_get_truncated(self_in); + if (mp_obj_is_small_int(self_in)) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } else { + const mp_obj_int_t *self = self_in; + long long value = self->val; + mp_int_t truncated = (mp_int_t)value; + if ((long long)truncated == value) { + return truncated; + } + } + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word")); +} + +mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) { + if (mp_obj_is_small_int(self_in)) { + if (MP_OBJ_SMALL_INT_VALUE(self_in) >= 0) { + return MP_OBJ_SMALL_INT_VALUE(self_in); + } + } else { + const mp_obj_int_t *self = self_in; + long long value = self->val; + mp_uint_t truncated = (mp_uint_t)value; + if (value >= 0 && (long long)truncated == value) { + return truncated; + } + } + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("overflow converting long int to machine word")); } #if MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 71e6d51f3a419..1bede811a4aaa 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -43,7 +43,7 @@ // Export value for sys.maxsize // *FORMAT-OFF* #define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1) -STATIC const mpz_dig_t maxsize_dig[] = { +static const mpz_dig_t maxsize_dig[] = { #define NUM_DIG 1 (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK, #if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK @@ -119,10 +119,10 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf return MP_OBJ_FROM_PTR(o); } -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { +bool mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(mp_obj_is_exact_type(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); - mpz_as_bytes(&self->mpz, big_endian, len, buf); + return mpz_as_bytes(&self->mpz, big_endian, self->mpz.neg, len, buf); } int mp_obj_int_sign(mp_obj_t self_in) { @@ -320,6 +320,14 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i return MP_OBJ_NULL; // op not supported } + // Check if the result fits in a small-int, and if so just return that. + mp_int_t res_small; + if (mpz_as_int_checked(&res->mpz, &res_small)) { + if (MP_SMALL_INT_FITS(res_small)) { + return MP_OBJ_NEW_SMALL_INT(res_small); + } + } + return MP_OBJ_FROM_PTR(res); } else { @@ -343,7 +351,7 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i } #if MICROPY_PY_BUILTINS_POW3 -STATIC mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) { +static mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) { if (mp_obj_is_small_int(arg)) { mpz_init_from_int(temp, MP_OBJ_SMALL_INT_VALUE(arg)); return temp; @@ -356,9 +364,10 @@ STATIC mpz_t *mp_mpz_for_int(mp_obj_t arg, mpz_t *temp) { mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { if (!mp_obj_is_int(base) || !mp_obj_is_int(exponent) || !mp_obj_is_int(modulus)) { mp_raise_TypeError(MP_ERROR_TEXT("pow() with 3 arguments requires integers")); + } else if (modulus == MP_OBJ_NEW_SMALL_INT(0)) { + mp_raise_ValueError(MP_ERROR_TEXT("divide by zero")); } else { - mp_obj_t result = mp_obj_new_int_from_ull(0); // Use the _from_ull version as this forces an mpz int - mp_obj_int_t *res_p = (mp_obj_int_t *)MP_OBJ_TO_PTR(result); + mp_obj_int_t *res_p = mp_obj_int_new_mpz(); mpz_t l_temp, r_temp, m_temp; mpz_t *lhs = mp_mpz_for_int(base, &l_temp); @@ -381,7 +390,7 @@ mp_obj_t mp_obj_int_pow3(mp_obj_t base, mp_obj_t exponent, mp_obj_t modulus) { if (mod == &m_temp) { mpz_deinit(mod); } - return result; + return MP_OBJ_FROM_PTR(res_p); } } #endif @@ -438,6 +447,10 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t value; if (mpz_as_int_checked(&self->mpz, &value)) { + // mp_obj_int_t objects should always contain a value that is a large + // integer (if the value fits in a small-int then it should have been + // converted to a small-int object), and so this code-path should never + // be taken in normal circumstances. return value; } else { // overflow diff --git a/py/objlist.c b/py/objlist.c index d2de15fb642f4..a29fc51b10472 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -29,12 +29,12 @@ #include "py/objlist.h" #include "py/runtime.h" -#include "py/stackctrl.h" +#include "py/cstack.h" -STATIC mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf); -STATIC mp_obj_list_t *list_new(size_t n); -STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); -STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args); +static mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, size_t cur, mp_obj_iter_buf_t *iter_buf); +static mp_obj_list_t *list_new(size_t n); +static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in); +static mp_obj_t list_pop(size_t n_args, const mp_obj_t *args); // TODO: Move to mpconfig.h #define LIST_MIN_ALLOC 4 @@ -45,7 +45,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args); /******************************************************************************/ /* list */ -STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_list_t *o = MP_OBJ_TO_PTR(o_in); const char *item_separator = ", "; if (!(MICROPY_PY_JSON && kind == PRINT_JSON)) { @@ -65,7 +65,7 @@ STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t k mp_print_str(print, "]"); } -STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { +static mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { mp_obj_t iter = mp_getiter(iterable, NULL); mp_obj_t item; while ((item = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { @@ -94,11 +94,11 @@ mp_obj_t mp_obj_list_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ } // CIRCUITPY-CHANGE -STATIC mp_obj_list_t *native_list(mp_obj_t self_in) { +static mp_obj_list_t *native_list(mp_obj_t self_in) { return MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(self_in, MP_OBJ_FROM_PTR(&mp_type_list))); } -STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // CIRCUITPY-CHANGE mp_obj_list_t *self = native_list(self_in); switch (op) { @@ -117,8 +117,8 @@ STATIC mp_obj_t list_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { - // CIRCUITPY-CHANGE +static mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { + // CIRCUITPY-CHANGE: allow subclassing mp_obj_list_t *o = native_list(lhs); switch (op) { case MP_BINARY_OP_ADD: { @@ -142,7 +142,7 @@ STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { if (n < 0) { n = 0; } - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: overflow check (PR#1279) size_t new_len = mp_seq_multiply_len(o->len, n); mp_obj_list_t *s = list_new(new_len); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); @@ -170,89 +170,79 @@ STATIC mp_obj_t list_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { } } -STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { - // CIRCUITPY-CHANGE - mp_obj_list_t *self = native_list(self_in); - if (value == MP_OBJ_NULL) { - // delete - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { - mp_raise_NotImplementedError(NULL); +static mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { + #if MICROPY_PY_BUILTINS_SLICE + if (mp_obj_is_type(index, &mp_type_slice)) { + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_list_t *self = native_list(self_in); + mp_bound_slice_t slice; + bool fast = mp_seq_get_fast_slice_indexes(self->len, index, &slice); + if (value == MP_OBJ_SENTINEL) { + // load + if (!fast) { + return mp_seq_extract_slice(self->items, &slice); } - - mp_int_t len_adj = slice.start - slice.stop; - assert(len_adj <= 0); - mp_seq_replace_slice_no_grow(self->items, self->len, slice.start, slice.stop, self->items /*NULL*/, 0, sizeof(*self->items)); + mp_obj_list_t *res = list_new(slice.stop - slice.start); + mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); + return MP_OBJ_FROM_PTR(res); + } + // assign/delete + if (value == MP_OBJ_NULL) { + // delete is equivalent to slice assignment of an empty sequence + value = mp_const_empty_tuple; + } + if (!fast) { + mp_raise_NotImplementedError(NULL); + } + size_t value_len; + mp_obj_t *value_items; + mp_obj_get_array(value, &value_len, &value_items); + mp_int_t len_adj = value_len - (slice.stop - slice.start); + if (len_adj > 0) { + if (self->len + len_adj > self->alloc) { + // TODO: Might optimize memory copies here by checking if block can + // be grown inplace or not + self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); + self->alloc = self->len + len_adj; + } + mp_seq_replace_slice_grow_inplace(self->items, self->len, + slice.start, slice.stop, value_items, value_len, len_adj, sizeof(*self->items)); + } else { + mp_seq_replace_slice_no_grow(self->items, self->len, + slice.start, slice.stop, value_items, value_len, sizeof(*self->items)); // Clear "freed" elements at the end of list mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); - self->len += len_adj; - return mp_const_none; + // TODO: apply allocation policy re: alloc_size } - #endif - // CIRCUITPY-CHANGE - mp_obj_t args[2] = {MP_OBJ_FROM_PTR(self), index}; + self->len += len_adj; + return mp_const_none; + } + #endif + if (value == MP_OBJ_NULL) { + // delete + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_t args[2] = {MP_OBJ_FROM_PTR(self_in), index}; list_pop(2, args); return mp_const_none; } else if (value == MP_OBJ_SENTINEL) { // load - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - mp_bound_slice_t slice; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) { - return mp_seq_extract_slice(self->len, self->items, &slice); - } - mp_obj_list_t *res = list_new(slice.stop - slice.start); - mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t); - return MP_OBJ_FROM_PTR(res); - } - #endif + // CIRCUITPY-CHANGE: handle subclassing + mp_obj_list_t *self = native_list(self_in); size_t index_val = mp_get_index(self->base.type, self->len, index, false); return self->items[index_val]; } else { - #if MICROPY_PY_BUILTINS_SLICE - if (mp_obj_is_type(index, &mp_type_slice)) { - size_t value_len; - mp_obj_t *value_items; - mp_obj_get_array(value, &value_len, &value_items); - mp_bound_slice_t slice_out; - if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) { - mp_raise_NotImplementedError(NULL); - } - mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start); - if (len_adj > 0) { - if (self->len + len_adj > self->alloc) { - // TODO: Might optimize memory copies here by checking if block can - // be grown inplace or not - self->items = m_renew(mp_obj_t, self->items, self->alloc, self->len + len_adj); - self->alloc = self->len + len_adj; - } - mp_seq_replace_slice_grow_inplace(self->items, self->len, - slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items)); - } else { - mp_seq_replace_slice_no_grow(self->items, self->len, - slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items)); - // Clear "freed" elements at the end of list - mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items)); - // TODO: apply allocation policy re: alloc_size - } - self->len += len_adj; - return mp_const_none; - } - #endif mp_obj_list_store(self_in, index, value); return mp_const_none; } } -STATIC mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t list_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { return mp_obj_new_list_iterator(o_in, 0, iter_buf); } mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); if (self->len >= self->alloc) { self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2); @@ -263,10 +253,10 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) { return mp_const_none; // return None, as per CPython } -STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { +static mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); if (mp_obj_is_type(arg_in, &mp_type_list)) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); mp_obj_list_t *arg = native_list(arg_in); @@ -285,9 +275,10 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) { return mp_const_none; // return None, as per CPython } -// CIRCUITPY-CHANGE: used elsewhere so not static +// CIRCUITPY-CHANGE: provide version for C use outside this file inline mp_obj_t mp_obj_list_pop(mp_obj_list_t *self, size_t index) { if (self->len == 0) { + // CIRCUITPY-CHANGE: more specific mp_raise mp_raise_IndexError_varg(MP_ERROR_TEXT("pop from empty %q"), MP_QSTR_list); } mp_obj_t ret = self->items[index]; @@ -302,18 +293,28 @@ inline mp_obj_t mp_obj_list_pop(mp_obj_list_t *self, size_t index) { return ret; } -// CIRCUITPY-CHANGE -STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { +static mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); mp_obj_list_t *self = native_list(args[0]); size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); + // CIRCUITPY-CHANGE: use factored-out pop code return mp_obj_list_pop(self, index); } -STATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) { - MP_STACK_CHECK(); - while (head < tail) { - mp_obj_t *h = head - 1; +// "head" is actually the *exclusive lower bound* of the range to sort. That is, +// the first element to be sorted is `head[1]`, not `head[0]`. Similarly `tail` +// is an *inclusive upper bound* of the range to sort. That is, the final +// element to sort is `tail[0]`, not `tail[-1]`. +// +// The pivot element is always chosen as `tail[0]`. +// +// These unusual choices allows structuring the partitioning +// process as a do/while loop, which generates smaller code than the equivalent +// code with usual C bounds & a while or for loop. +static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj_t binop_less_result) { + mp_cstack_check(); + while (tail - head > 1) { // So long as at least 2 elements remain + mp_obj_t *h = head; mp_obj_t *t = tail; mp_obj_t v = key_fn == MP_OBJ_NULL ? tail[0] : mp_call_function_1(key_fn, tail[0]); // get pivot using key_fn for (;;) { @@ -324,19 +325,21 @@ STATIC void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, mp_obj if (h >= t) { break; } + // A pair of objects must be swapped to the other side of the partition mp_obj_t x = h[0]; h[0] = t[0]; t[0] = x; } + // Place the pivot element in the proper position mp_obj_t x = h[0]; h[0] = tail[0]; tail[0] = x; // do the smaller recursive call first, to keep stack within O(log(N)) - if (t - head < tail - h - 1) { + if (t - head < tail - h) { mp_quicksort(head, t, key_fn, binop_less_result); - head = h + 1; + head = h; } else { - mp_quicksort(h + 1, tail, key_fn, binop_less_result); + mp_quicksort(h, tail, key_fn, binop_less_result); tail = t; } } @@ -361,7 +364,7 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ mp_obj_list_t *self = native_list(pos_args[0]); if (self->len > 1) { - mp_quicksort(self->items, self->items + self->len - 1, + mp_quicksort(self->items - 1, self->items + self->len - 1, args.key.u_obj == mp_const_none ? MP_OBJ_NULL : args.key.u_obj, args.reverse.u_bool ? mp_const_false : mp_const_true); } @@ -369,10 +372,10 @@ mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_ return mp_const_none; } -// CIRCUITPY-CHANGE: used elsewhere so not static +// CIRCUITPY-CHANGE: rename and make not static for use elsewhere mp_obj_t mp_obj_list_clear(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); self->len = 0; self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC); @@ -381,29 +384,30 @@ mp_obj_t mp_obj_list_clear(mp_obj_t self_in) { return mp_const_none; } -STATIC mp_obj_t list_copy(mp_obj_t self_in) { +static mp_obj_t list_copy(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); return mp_obj_new_list(self->len, self->items); } -STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { +static mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(self_in); return mp_seq_count_obj(self->items, self->len, value); } -STATIC mp_obj_t list_index(size_t n_args, const mp_obj_t *args) { +static mp_obj_t list_index(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_list)); - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: handle subclassing mp_obj_list_t *self = native_list(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } -// CIRCUITPY-CHANGE: used elsewhere so not static -inline void mp_obj_list_insert(mp_obj_list_t *self, size_t index, mp_obj_t obj) { +// CIRCUITPY-CHANGE: factor out for C use elsewhere; not meant to emulate Python API +inline void mp_obj_list_insert(mp_obj_list_t *self_in, size_t index, mp_obj_t obj) { + mp_obj_list_t *self = native_list(self_in); mp_obj_list_append(MP_OBJ_FROM_PTR(self), mp_const_none); for (size_t i = self->len - 1; i > index; --i) { @@ -412,7 +416,7 @@ inline void mp_obj_list_insert(mp_obj_list_t *self, size_t index, mp_obj_t obj) self->items[index] = obj; } -STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { +static mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); // CIRCUITPY-CHANGE mp_obj_list_t *self = native_list(self_in); @@ -427,7 +431,7 @@ STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) { if ((size_t)index > self->len) { index = self->len; } - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: use factored-out insert code mp_obj_list_insert(self, index, obj); return mp_const_none; } @@ -441,10 +445,9 @@ mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) { return mp_const_none; } -STATIC mp_obj_t list_reverse(mp_obj_t self_in) { +static mp_obj_t list_reverse(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_list)); - // CIRCUITPY-CHANGE - mp_obj_list_t *self = native_list(self_in); + mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = self->len; for (mp_int_t i = 0; i < len / 2; i++) { @@ -456,20 +459,20 @@ STATIC mp_obj_t list_reverse(mp_obj_t self_in) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend); +static MP_DEFINE_CONST_FUN_OBJ_2(list_append_obj, mp_obj_list_append); +static MP_DEFINE_CONST_FUN_OBJ_2(list_extend_obj, list_extend); // CIRCUITPY-CHANGE: use renamed public function -STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, mp_obj_list_clear); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_index_obj, 2, 4, list_index); -STATIC MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, mp_obj_list_remove); -STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse); -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 1, mp_obj_list_sort); - -STATIC const mp_rom_map_elem_t list_locals_dict_table[] = { +static MP_DEFINE_CONST_FUN_OBJ_1(list_clear_obj, mp_obj_list_clear); +static MP_DEFINE_CONST_FUN_OBJ_1(list_copy_obj, list_copy); +static MP_DEFINE_CONST_FUN_OBJ_2(list_count_obj, list_count); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_index_obj, 2, 4, list_index); +static MP_DEFINE_CONST_FUN_OBJ_3(list_insert_obj, list_insert); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(list_pop_obj, 1, 2, list_pop); +static MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, mp_obj_list_remove); +static MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse); +static MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 1, mp_obj_list_sort); + +static const mp_rom_map_elem_t list_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&list_append_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&list_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&list_copy_obj) }, @@ -483,12 +486,13 @@ STATIC const mp_rom_map_elem_t list_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_sort), MP_ROM_PTR(&list_sort_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); +static MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table); +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_list, MP_QSTR_list, - MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_list_make_new, print, list_print, unary_op, list_unary_op, @@ -503,12 +507,14 @@ void mp_obj_list_init(mp_obj_list_t *o, size_t n) { o->base.type = &mp_type_list; o->alloc = n < LIST_MIN_ALLOC ? LIST_MIN_ALLOC : n; o->len = n; - o->items = m_new(mp_obj_t, o->alloc); + // CIRCUITPY-CHANGE: Use m_malloc_items because these are mp_obj_t + o->items = m_malloc_items(o->alloc); mp_seq_clear(o->items, n, o->alloc, sizeof(*o->items)); } -STATIC mp_obj_list_t *list_new(size_t n) { - mp_obj_list_t *o = m_new_obj(mp_obj_list_t); +static mp_obj_list_t *list_new(size_t n) { + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_list_t *o = mp_obj_malloc(mp_obj_list_t, &mp_type_list); mp_obj_list_init(o, n); return o; } @@ -554,7 +560,7 @@ typedef struct _mp_obj_list_it_t { size_t cur; } mp_obj_list_it_t; -STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) { +static mp_obj_t list_it_iternext(mp_obj_t self_in) { mp_obj_list_it_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list); if (self->cur < list->len) { diff --git a/py/objmap.c b/py/objmap.c index e7e594cd2c54b..d8042f867c73b 100644 --- a/py/objmap.c +++ b/py/objmap.c @@ -36,9 +36,9 @@ typedef struct _mp_obj_map_t { mp_obj_t iters[]; } mp_obj_map_t; -STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, false); - mp_obj_map_t *o = mp_obj_malloc_var(mp_obj_map_t, mp_obj_t, n_args - 1, type); + mp_obj_map_t *o = mp_obj_malloc_var(mp_obj_map_t, iters, mp_obj_t, n_args - 1, type); o->n_iters = n_args - 1; o->fun = args[0]; for (size_t i = 0; i < n_args - 1; i++) { @@ -47,10 +47,11 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t map_iternext(mp_obj_t self_in) { +static mp_obj_t map_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_map)); mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters); + // CIRCUITPY-CHANGE: Use m_malloc_items because it is an array of objects + mp_obj_t *nextses = m_malloc_items(self->n_iters); for (size_t i = 0; i < self->n_iters; i++) { mp_obj_t next = mp_iternext(self->iters[i]); diff --git a/py/objmodule.c b/py/objmodule.c index d211ccc78d4f4..84b6a10f9abd4 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -34,12 +34,7 @@ #include "py/runtime.h" #include "py/builtin.h" -// CIRCUITPY-CHANGE -#if CIRCUITPY_WARNINGS -#include "shared-module/warnings/__init__.h" -#endif - -STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); @@ -49,7 +44,7 @@ STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin module_name = mp_obj_str_get_str(elem->value); } - #if MICROPY_PY___FILE__ + #if MICROPY_MODULE___FILE__ // If we store __file__ to imported modules then try to lookup this // symbol to give more information about the module. elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(MP_QSTR___file__), MP_MAP_LOOKUP); @@ -62,38 +57,11 @@ STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin mp_printf(print, "", module_name); } -STATIC void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *dest); +static void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *dest); -STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in); if (dest[0] == MP_OBJ_NULL) { - // CIRCUITPY-CHANGE - #if CIRCUITPY_8_9_WARNINGS && CIRCUITPY_DISPLAYIO && CIRCUITPY_WARNINGS - if (self == &displayio_module) { - #if CIRCUITPY_BUSDISPLAY - if (attr == MP_QSTR_Display) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_Display, MP_QSTR_displayio, MP_QSTR_busdisplay); - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_Display, MP_QSTR_BusDisplay); - } - #endif - #if CIRCUITPY_EPAPERDISPLAY - if (attr == MP_QSTR_EPaperDisplay) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_EPaperDisplay, MP_QSTR_displayio, MP_QSTR_epaperdisplay); - } - #endif - #if CIRCUITPY_FOURWIRE - if (attr == MP_QSTR_FourWire) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_FourWire, MP_QSTR_displayio, MP_QSTR_fourwire); - } - #endif - #if CIRCUITPY_I2CDISPLAYBUS - if (attr == MP_QSTR_I2CDisplay) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_I2CDisplay, MP_QSTR_displayio, MP_QSTR_i2cdisplaybus); - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_I2CDisplay, MP_QSTR_I2CDisplayBus); - } - #endif - } - #endif // load attribute mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); if (elem != NULL) { @@ -161,8 +129,8 @@ mp_obj_t mp_obj_new_module(qstr module_name) { } // create new module object - mp_module_context_t *o = m_new_obj(mp_module_context_t); - o->module.base.type = &mp_type_module; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_module_context_t *o = mp_obj_malloc(mp_module_context_t, &mp_type_module); o->module.globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE)); // store __name__ entry in the module @@ -178,17 +146,19 @@ mp_obj_t mp_obj_new_module(qstr module_name) { /******************************************************************************/ // Global module table and related functions -STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { +static const mp_rom_map_elem_t mp_builtin_module_table[] = { // built-in modules declared with MP_REGISTER_MODULE() MICROPY_REGISTERED_MODULES }; MP_DEFINE_CONST_MAP(mp_builtin_module_map, mp_builtin_module_table); -STATIC const mp_rom_map_elem_t mp_builtin_extensible_module_table[] = { +#if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES +static const mp_rom_map_elem_t mp_builtin_extensible_module_table[] = { // built-in modules declared with MP_REGISTER_EXTENSIBLE_MODULE() MICROPY_REGISTERED_EXTENSIBLE_MODULES }; MP_DEFINE_CONST_MAP(mp_builtin_extensible_module_map, mp_builtin_extensible_module_table); +#endif #if MICROPY_MODULE_ATTR_DELEGATION && defined(MICROPY_MODULE_DELEGATIONS) typedef struct _mp_module_delegation_entry_t { @@ -196,7 +166,7 @@ typedef struct _mp_module_delegation_entry_t { mp_attr_fun_t fun; } mp_module_delegation_entry_t; -STATIC const mp_module_delegation_entry_t mp_builtin_module_delegation_table[] = { +static const mp_module_delegation_entry_t mp_builtin_module_delegation_table[] = { // delegation entries declared with MP_REGISTER_MODULE_DELEGATION() MICROPY_MODULE_DELEGATIONS }; @@ -205,13 +175,13 @@ STATIC const mp_module_delegation_entry_t mp_builtin_module_delegation_table[] = // Attempts to find (and initialise) a built-in, otherwise returns // MP_OBJ_NULL. mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { - // CIRCUITPY-CHANGE - #if CIRCUITPY_PARALLELDISPLAYBUS && CIRCUITPY_WARNINGS - if (module_name == MP_QSTR_paralleldisplay) { - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_paralleldisplay, MP_QSTR_paralleldisplaybus); - } + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES + const mp_map_t *map = extensible ? &mp_builtin_extensible_module_map : &mp_builtin_module_map; + #else + const mp_map_t *map = &mp_builtin_module_map; #endif - mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)(extensible ? &mp_builtin_extensible_module_map : &mp_builtin_module_map), MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup((mp_map_t *)map, MP_OBJ_NEW_QSTR(module_name), MP_MAP_LOOKUP); + if (!elem) { #if MICROPY_PY_SYS // Special case for sys, which isn't extensible but can always be @@ -221,6 +191,7 @@ mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { } #endif + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES if (extensible) { // At this point we've already tried non-extensible built-ins, the // filesystem, and now extensible built-ins. No match, so fail @@ -237,6 +208,7 @@ mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { // the old behaviour of the u-prefix being used to force a built-in // import. // CIRCUITPY-CHANGE: Don't look for `ufoo`. + #endif return MP_OBJ_NULL; } @@ -254,7 +226,7 @@ mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible) { return elem->value; } -STATIC void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void module_attr_try_delegation(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { #if MICROPY_MODULE_ATTR_DELEGATION && defined(MICROPY_MODULE_DELEGATIONS) // Delegate lookup to a module's custom attr method. size_t n = MP_ARRAY_SIZE(mp_builtin_module_delegation_table); diff --git a/py/objmodule.h b/py/objmodule.h index 8b14cd9fc3d30..221392ccce431 100644 --- a/py/objmodule.h +++ b/py/objmodule.h @@ -32,10 +32,16 @@ // Only include module definitions when not doing qstr extraction, because the // qstr extraction stage also generates this module definition header file. #include "genhdr/moduledefs.h" +// CIRCUITPY-CHANGE: avoid undef warning +#else +#define MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES (0) #endif extern const mp_map_t mp_builtin_module_map; + +#if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES extern const mp_map_t mp_builtin_extensible_module_map; +#endif mp_obj_t mp_module_get_builtin(qstr module_name, bool extensible); diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index bcf7ac7c3c818..d687dbfda59d6 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -45,9 +45,9 @@ size_t mp_obj_namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr n return (size_t)-1; } -// CIRCUITPY-CHANGE: differences +// CIRCUITPY-CHANGE: multiple differences #if MICROPY_PY_COLLECTIONS_NAMEDTUPLE__ASDICT -STATIC mp_obj_t namedtuple_asdict(mp_obj_t self_in) { +static mp_obj_t namedtuple_asdict(mp_obj_t self_in) { mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in); const qstr *fields = ((mp_obj_namedtuple_type_t *)self->tuple.base.type)->fields; mp_obj_t dict = mp_obj_new_dict(self->tuple.len); @@ -73,7 +73,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(namedtuple_asdict_obj, namedtuple_asdict); void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in); - mp_printf(print, "%q", o->tuple.base.type->name); + mp_printf(print, "%q", (qstr)o->tuple.base.type->name); const qstr *fields = ((mp_obj_namedtuple_type_t *)o->tuple.base.type)->fields; mp_obj_attrtuple_print_helper(print, fields, &o->tuple); } @@ -125,7 +125,7 @@ mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t // Create a namedtuple with explicit malloc. Calling mp_obj_new_tuple // with num_fields=0 returns a read-only object. - mp_obj_tuple_t *tuple = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, num_fields, type_in); + mp_obj_tuple_t *tuple = mp_obj_malloc_var(mp_obj_tuple_t, items, mp_obj_t, num_fields, type_in); tuple->len = num_fields; // Copy the positional args into the first slots of the namedtuple @@ -166,7 +166,7 @@ mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t * return o; } -STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { +static mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) { mp_obj_namedtuple_type_t *o = mp_obj_new_namedtuple_base(n_fields, fields); mp_obj_type_t *type = (mp_obj_type_t *)&o->base; type->base.type = &mp_type_type; @@ -183,7 +183,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) { +static mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) { qstr name = mp_obj_str_get_qstr(name_in); size_t n_fields; mp_obj_t *fields; diff --git a/py/objnone.c b/py/objnone.c index 5b25cd38c46d5..1e2016abd9fb7 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -34,7 +34,7 @@ typedef struct _mp_obj_none_t { } mp_obj_none_t; #endif -STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)self_in; if (MICROPY_PY_JSON && kind == PRINT_JSON) { mp_print_str(print, "null"); @@ -43,10 +43,11 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_NoneType, MP_QSTR_NoneType, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_PRINT_JSON, print, none_print ); diff --git a/py/objobject.c b/py/objobject.c index 4806c2522d993..ee7a00ee9a790 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -33,7 +33,7 @@ typedef struct _mp_obj_object_t { mp_obj_base_t base; } mp_obj_object_t; -STATIC mp_obj_t object_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t object_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)args; mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_obj_object_t *o = mp_obj_malloc(mp_obj_object_t, type); @@ -41,13 +41,13 @@ STATIC mp_obj_t object_make_new(const mp_obj_type_t *type, size_t n_args, size_t } #if MICROPY_CPYTHON_COMPAT -STATIC mp_obj_t object___init__(mp_obj_t self) { +static mp_obj_t object___init__(mp_obj_t self) { (void)self; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); +static MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); -STATIC mp_obj_t object___new__(mp_obj_t cls) { +static mp_obj_t object___new__(mp_obj_t cls) { if (!mp_obj_is_type(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t *)MP_OBJ_TO_PTR(cls))) { // CIRCUITPY-CHANGE: better error mp_raise_TypeError(MP_ERROR_TEXT("__new__ arg must be a user-type")); @@ -59,11 +59,11 @@ STATIC mp_obj_t object___new__(mp_obj_t cls) { const mp_obj_type_t *native_base; return MP_OBJ_FROM_PTR(mp_obj_new_instance(MP_OBJ_TO_PTR(cls), &native_base)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__); -STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj)); +static MP_DEFINE_CONST_FUN_OBJ_1(object___new___fun_obj, object___new__); +static MP_DEFINE_CONST_STATICMETHOD_OBJ(object___new___obj, MP_ROM_PTR(&object___new___fun_obj)); #if MICROPY_PY_DELATTR_SETATTR -STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t value) { +static mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t value) { if (!mp_obj_is_instance_type(mp_obj_get_type(self_in))) { mp_raise_TypeError(MP_ERROR_TEXT("arg must be user-type")); } @@ -76,9 +76,9 @@ STATIC mp_obj_t object___setattr__(mp_obj_t self_in, mp_obj_t attr, mp_obj_t val mp_map_lookup(&self->members, attr, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__); +static MP_DEFINE_CONST_FUN_OBJ_3(object___setattr___obj, object___setattr__); -STATIC mp_obj_t object___delattr__(mp_obj_t self_in, mp_obj_t attr) { +static mp_obj_t object___delattr__(mp_obj_t self_in, mp_obj_t attr) { if (!mp_obj_is_instance_type(mp_obj_get_type(self_in))) { mp_raise_TypeError(MP_ERROR_TEXT("arg must be user-type")); } @@ -93,10 +93,10 @@ STATIC mp_obj_t object___delattr__(mp_obj_t self_in, mp_obj_t attr) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(object___delattr___obj, object___delattr__); +static MP_DEFINE_CONST_FUN_OBJ_2(object___delattr___obj, object___delattr__); #endif -STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { +static const mp_rom_map_elem_t object_locals_dict_table[] = { #if MICROPY_CPYTHON_COMPAT { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&object___init___obj) }, #endif @@ -109,7 +109,7 @@ STATIC const mp_rom_map_elem_t object_locals_dict_table[] = { #endif }; -STATIC MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); +static MP_DEFINE_CONST_DICT(object_locals_dict, object_locals_dict_table); #endif #if MICROPY_CPYTHON_COMPAT diff --git a/py/objpolyiter.c b/py/objpolyiter.c index 78b600abacdcd..65c1f182ec8ec 100644 --- a/py/objpolyiter.c +++ b/py/objpolyiter.c @@ -39,7 +39,7 @@ typedef struct _mp_obj_polymorph_iter_t { mp_fun_1_t iternext; } mp_obj_polymorph_iter_t; -STATIC mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { +static mp_obj_t polymorph_it_iternext(mp_obj_t self_in) { mp_obj_polymorph_iter_t *self = MP_OBJ_TO_PTR(self_in); // Redirect call to object instance's iternext method return self->iternext(self_in); @@ -64,17 +64,17 @@ typedef struct _mp_obj_polymorph_iter_with_finaliser_t { mp_fun_1_t finaliser; } mp_obj_polymorph_with_finaliser_iter_t; -STATIC mp_obj_t mp_obj_polymorph_iter_del(mp_obj_t self_in) { +static mp_obj_t mp_obj_polymorph_iter_del(mp_obj_t self_in) { mp_obj_polymorph_with_finaliser_iter_t *self = MP_OBJ_TO_PTR(self_in); // Redirect call to object instance's finaliser method return self->finaliser(self_in); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_polymorph_iter_del_obj, mp_obj_polymorph_iter_del); +static MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_polymorph_iter_del_obj, mp_obj_polymorph_iter_del); -STATIC const mp_rom_map_elem_t mp_obj_polymorph_iter_locals_dict_table[] = { +static const mp_rom_map_elem_t mp_obj_polymorph_iter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_obj_polymorph_iter_del_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_iter_locals_dict_table); +static MP_DEFINE_CONST_DICT(mp_obj_polymorph_iter_locals_dict, mp_obj_polymorph_iter_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_polymorph_iter_with_finaliser, diff --git a/py/objproperty.c b/py/objproperty.c index 824f82ea802e6..96563f6dba389 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -37,7 +37,7 @@ #if MICROPY_PY_BUILTINS_PROPERTY -STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, @@ -56,40 +56,43 @@ STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); +static mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) { + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[0] = getter; return MP_OBJ_FROM_PTR(p2); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter); +static MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter); -STATIC mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); +static mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) { + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[1] = setter; return MP_OBJ_FROM_PTR(p2); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter); +static MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter); -STATIC mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) { - mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t); +static mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) { + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_property_t *p2 = mp_obj_malloc(mp_obj_property_t, &mp_type_property); *p2 = *(mp_obj_property_t *)MP_OBJ_TO_PTR(self_in); p2->proxy[2] = deleter; return MP_OBJ_FROM_PTR(p2); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_deleter_obj, property_deleter); +static MP_DEFINE_CONST_FUN_OBJ_2(property_deleter_obj, property_deleter); -STATIC const mp_rom_map_elem_t property_locals_dict_table[] = { +static const mp_rom_map_elem_t property_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_getter), MP_ROM_PTR(&property_getter_obj) }, { MP_ROM_QSTR(MP_QSTR_setter), MP_ROM_PTR(&property_setter_obj) }, { MP_ROM_QSTR(MP_QSTR_deleter), MP_ROM_PTR(&property_deleter_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table); +static MP_DEFINE_CONST_DICT(property_locals_dict, property_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_property, diff --git a/py/objproperty.h b/py/objproperty.h index 0098bfd0b1118..eb0f65d3dbebf 100644 --- a/py/objproperty.h +++ b/py/objproperty.h @@ -1,30 +1,10 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_PY_OBJPROPERTY_H -#define MICROPY_INCLUDED_PY_OBJPROPERTY_H +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2016 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once #include "py/obj.h" @@ -64,5 +44,3 @@ typedef struct _mp_obj_property_t mp_obj_property_getset_t; #endif #endif // MICROPY_PY_BUILTINS_PROPERTY - -#endif // MICROPY_INCLUDED_PY_OBJPROPERTY_H diff --git a/py/objrange.c b/py/objrange.c index c5a6d1ff6e820..dea9fe5f2963a 100644 --- a/py/objrange.c +++ b/py/objrange.c @@ -33,31 +33,30 @@ typedef struct _mp_obj_range_it_t { mp_obj_base_t base; - // TODO make these values generic objects or something mp_int_t cur; mp_int_t stop; mp_int_t step; } mp_obj_range_it_t; -STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) { +static mp_obj_t range_it_iternext(mp_obj_t o_in) { mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in); if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) { - mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur); + mp_int_t cur = o->cur; o->cur += o->step; - return o_out; + return mp_obj_new_int(cur); } else { return MP_OBJ_STOP_ITERATION; } } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_range_it, MP_QSTR_iterator, MP_TYPE_FLAG_ITER_IS_ITERNEXT, iter, range_it_iternext ); -STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t step, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_range_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_range_it_t *o = (mp_obj_range_it_t *)iter_buf; o->base.type = &mp_type_range_it; @@ -72,13 +71,12 @@ STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t typedef struct _mp_obj_range_t { mp_obj_base_t base; - // TODO make these values generic objects or something mp_int_t start; mp_int_t stop; mp_int_t step; } mp_obj_range_t; -STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "range(" INT_FMT ", " INT_FMT "", self->start, self->stop); @@ -89,7 +87,7 @@ STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind } } -STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 3, false); mp_obj_range_t *o = mp_obj_malloc(mp_obj_range_t, type); @@ -113,7 +111,7 @@ STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t return MP_OBJ_FROM_PTR(o); } -STATIC mp_int_t range_len(mp_obj_range_t *self) { +static mp_int_t range_len(mp_obj_range_t *self) { // When computing length, need to take into account step!=1 and step<0. mp_int_t len = self->stop - self->start + self->step; if (self->step > 0) { @@ -128,21 +126,21 @@ STATIC mp_int_t range_len(mp_obj_range_t *self) { return len; } -STATIC mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t range_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t len = range_len(self); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0); case MP_UNARY_OP_LEN: - return MP_OBJ_NEW_SMALL_INT(len); + return mp_obj_new_int(len); default: return MP_OBJ_NULL; // op not supported } } #if MICROPY_PY_BUILTINS_RANGE_BINOP -STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { if (!mp_obj_is_type(rhs_in, &mp_type_range) || op != MP_BINARY_OP_EQUAL) { return MP_OBJ_NULL; // op not supported } @@ -159,7 +157,7 @@ STATIC mp_obj_t range_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs } #endif -STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { if (value == MP_OBJ_SENTINEL) { // load mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in); @@ -167,33 +165,29 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { #if MICROPY_PY_BUILTINS_SLICE if (mp_obj_is_type(index, &mp_type_slice)) { mp_bound_slice_t slice; - mp_seq_get_fast_slice_indexes(len, index, &slice); + mp_obj_slice_indices(index, len, &slice); mp_obj_range_t *o = mp_obj_malloc(mp_obj_range_t, &mp_type_range); o->start = self->start + slice.start * self->step; o->stop = self->start + slice.stop * self->step; o->step = slice.step * self->step; - if (slice.step < 0) { - // Negative slice steps have inclusive stop, so adjust for exclusive - o->stop -= self->step; - } return MP_OBJ_FROM_PTR(o); } #endif size_t index_val = mp_get_index(self->base.type, len, index, false); - return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step); + return mp_obj_new_int(self->start + index_val * self->step); } else { return MP_OBJ_NULL; // op not supported } } -STATIC mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t range_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in); return mp_obj_new_range_iterator(o->start, o->stop, o->step, iter_buf); } #if MICROPY_PY_BUILTINS_RANGE_ATTRS -STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { +static void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; diff --git a/py/objreversed.c b/py/objreversed.c index c66698f028adf..c580ee286b76d 100644 --- a/py/objreversed.c +++ b/py/objreversed.c @@ -37,7 +37,7 @@ typedef struct _mp_obj_reversed_t { mp_uint_t cur_index; // current index, plus 1; 0=no more, 1=last one (index 0) } mp_obj_reversed_t; -STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); // check if __reversed__ exists, and if so delegate to it @@ -54,7 +54,7 @@ STATIC mp_obj_t reversed_make_new(const mp_obj_type_t *type, size_t n_args, size return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) { +static mp_obj_t reversed_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_reversed)); mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/py/objringio.c b/py/objringio.c new file mode 100644 index 0000000000000..0025b26be3b07 --- /dev/null +++ b/py/objringio.c @@ -0,0 +1,127 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Andrew Leech + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "ringbuf.h" +#include "py/mpconfig.h" + +#if MICROPY_PY_MICROPYTHON_RINGIO + +#include "py/runtime.h" +#include "py/stream.h" + +typedef struct _micropython_ringio_obj_t { + mp_obj_base_t base; + ringbuf_t ringbuffer; +} micropython_ringio_obj_t; + +static mp_obj_t micropython_ringio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, 1, false); + mp_buffer_info_t bufinfo = {NULL, 0, 0}; + + if (!mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) { + bufinfo.len = mp_obj_get_int(args[0]) + 1; + bufinfo.buf = m_new(uint8_t, bufinfo.len); + } + if (bufinfo.len < 2 || bufinfo.len > UINT16_MAX) { + mp_raise_ValueError(NULL); + } + micropython_ringio_obj_t *self = mp_obj_malloc(micropython_ringio_obj_t, type); + self->ringbuffer.buf = bufinfo.buf; + self->ringbuffer.size = bufinfo.len; + self->ringbuffer.iget = self->ringbuffer.iput = 0; + return MP_OBJ_FROM_PTR(self); +} + +static mp_uint_t micropython_ringio_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { + micropython_ringio_obj_t *self = MP_OBJ_TO_PTR(self_in); + size = MIN(size, ringbuf_avail(&self->ringbuffer)); + ringbuf_memcpy_get_internal(&(self->ringbuffer), buf_in, size); + *errcode = 0; + return size; +} + +static mp_uint_t micropython_ringio_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { + micropython_ringio_obj_t *self = MP_OBJ_TO_PTR(self_in); + size = MIN(size, ringbuf_free(&self->ringbuffer)); + ringbuf_memcpy_put_internal(&(self->ringbuffer), buf_in, size); + *errcode = 0; + return size; +} + +static mp_uint_t micropython_ringio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { + micropython_ringio_obj_t *self = MP_OBJ_TO_PTR(self_in); + switch (request) { + case MP_STREAM_POLL: { + mp_uint_t ret = 0; + if ((arg & MP_STREAM_POLL_RD) && ringbuf_avail(&self->ringbuffer) > 0) { + ret |= MP_STREAM_POLL_RD; + } + if ((arg & MP_STREAM_POLL_WR) && ringbuf_free(&self->ringbuffer) > 0) { + ret |= MP_STREAM_POLL_WR; + } + return ret; + } + case MP_STREAM_CLOSE: + return 0; + } + *errcode = MP_EINVAL; + return MP_STREAM_ERROR; +} + +static mp_obj_t micropython_ringio_any(mp_obj_t self_in) { + micropython_ringio_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->ringbuffer)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(micropython_ringio_any_obj, micropython_ringio_any); + +static const mp_rom_map_elem_t micropython_ringio_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(µpython_ringio_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) }, + +}; +static MP_DEFINE_CONST_DICT(micropython_ringio_locals_dict, micropython_ringio_locals_dict_table); + +static const mp_stream_p_t ringio_stream_p = { + .read = micropython_ringio_read, + .write = micropython_ringio_write, + .ioctl = micropython_ringio_ioctl, + .is_text = false, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + mp_type_ringio, + MP_QSTR_RingIO, + MP_TYPE_FLAG_NONE, + make_new, micropython_ringio_make_new, + protocol, &ringio_stream_p, + locals_dict, µpython_ringio_locals_dict + ); + +#endif // MICROPY_PY_MICROPYTHON_RINGIO diff --git a/py/objset.c b/py/objset.c index 1906163e2d17a..49e6beec11ec3 100644 --- a/py/objset.c +++ b/py/objset.c @@ -45,7 +45,7 @@ typedef struct _mp_obj_set_it_t { size_t cur; } mp_obj_set_it_t; -STATIC bool is_set_or_frozenset(mp_obj_t o) { +static bool is_set_or_frozenset(mp_obj_t o) { return mp_obj_is_type(o, &mp_type_set) #if MICROPY_PY_BUILTINS_FROZENSET || mp_obj_is_type(o, &mp_type_frozenset) @@ -60,7 +60,7 @@ STATIC bool is_set_or_frozenset(mp_obj_t o) { // set or frozenset for methods that operate on both of these types. #define check_set_or_frozenset(o) mp_check_self(is_set_or_frozenset(o)) -STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_BUILTINS_FROZENSET @@ -99,7 +99,7 @@ STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t #endif } -STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, 1, false); switch (n_args) { @@ -127,7 +127,7 @@ STATIC mp_obj_t set_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } } -STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) { +static mp_obj_t set_it_iternext(mp_obj_t self_in) { mp_obj_set_it_t *self = MP_OBJ_TO_PTR(self_in); size_t max = self->set->set.alloc; mp_set_t *set = &self->set->set; @@ -142,7 +142,7 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) { return MP_OBJ_STOP_ITERATION; } -STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_set_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_set_it_t *o = (mp_obj_set_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; @@ -155,23 +155,23 @@ STATIC mp_obj_t set_getiter(mp_obj_t set_in, mp_obj_iter_buf_t *iter_buf) { /******************************************************************************/ /* set methods */ -STATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) { +static mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add); +static MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add); -STATIC mp_obj_t set_clear(mp_obj_t self_in) { +static mp_obj_t set_clear(mp_obj_t self_in) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_clear(&self->set); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); +static MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear); -STATIC mp_obj_t set_copy(mp_obj_t self_in) { +static mp_obj_t set_copy(mp_obj_t self_in) { check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_set_t *other = mp_obj_malloc(mp_obj_set_t, self->base.type); @@ -180,17 +180,17 @@ STATIC mp_obj_t set_copy(mp_obj_t self_in) { memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t)); return MP_OBJ_FROM_PTR(other); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy); +static MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy); -STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { +static mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard); +static MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard); -STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { +static mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { mp_obj_t self; if (update) { check_set(args[0]); @@ -216,18 +216,18 @@ STATIC mp_obj_t set_diff_int(size_t n_args, const mp_obj_t *args, bool update) { return self; } -STATIC mp_obj_t set_diff(size_t n_args, const mp_obj_t *args) { +static mp_obj_t set_diff(size_t n_args, const mp_obj_t *args) { return set_diff_int(n_args, args, false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff); +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_obj, 1, set_diff); -STATIC mp_obj_t set_diff_update(size_t n_args, const mp_obj_t *args) { +static mp_obj_t set_diff_update(size_t n_args, const mp_obj_t *args) { set_diff_int(n_args, args, true); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update); +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_diff_update_obj, 1, set_diff_update); -STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { +static mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) { if (update) { check_set(self_in); } else { @@ -259,17 +259,17 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update) return update ? mp_const_none : MP_OBJ_FROM_PTR(out); } -STATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) { +static mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) { return set_intersect_int(self_in, other, false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect); +static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_obj, set_intersect); -STATIC mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) { +static mp_obj_t set_intersect_update(mp_obj_t self_in, mp_obj_t other) { return set_intersect_int(self_in, other, true); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update); +static MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update); -STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { +static mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); @@ -283,9 +283,9 @@ STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) { } return mp_const_true; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint); +static MP_DEFINE_CONST_FUN_OBJ_2(set_isdisjoint_obj, set_isdisjoint); -STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) { +static mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool proper) { mp_obj_set_t *self; bool cleanup_self = false; if (is_set_or_frozenset(self_in)) { @@ -327,25 +327,25 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool return out; } -STATIC mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_issubset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset); +static MP_DEFINE_CONST_FUN_OBJ_2(set_issubset_obj, set_issubset); -STATIC mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_issubset_proper(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(self_in, other_in, true); } -STATIC mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_issuperset(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(other_in, self_in, false); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset); +static MP_DEFINE_CONST_FUN_OBJ_2(set_issuperset_obj, set_issuperset); -STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset_internal(other_in, self_in, true); } -STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { assert(is_set_or_frozenset(other_in)); check_set_or_frozenset(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); @@ -356,7 +356,7 @@ STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) { return set_issubset(self_in, other_in); } -STATIC mp_obj_t set_pop(mp_obj_t self_in) { +static mp_obj_t set_pop(mp_obj_t self_in) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); @@ -366,9 +366,9 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { } return obj; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop); +static MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop); -STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { +static mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { check_set(self_in); mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) { @@ -376,9 +376,9 @@ STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) { } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove); +static MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove); -STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) { check_set_or_frozenset(self_in); // can be frozenset due to call from set_symmetric_difference mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t iter = mp_getiter(other_in, NULL); @@ -388,16 +388,16 @@ STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other } return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update); +static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmetric_difference_update); -STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) { mp_obj_t self_out = set_copy(self_in); set_symmetric_difference_update(self_out, other_in); return self_out; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference); +static MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference); -STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { +static void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { mp_obj_t iter = mp_getiter(other_in, NULL); mp_obj_t next; while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) { @@ -405,7 +405,7 @@ STATIC void set_update_int(mp_obj_set_t *self, mp_obj_t other_in) { } } -STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { +static mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { check_set(args[0]); for (size_t i = 1; i < n_args; i++) { set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]); @@ -413,17 +413,17 @@ STATIC mp_obj_t set_update(size_t n_args, const mp_obj_t *args) { return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update); +static MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update); -STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) { +static mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) { check_set_or_frozenset(self_in); mp_obj_t self = set_copy(self_in); set_update_int(MP_OBJ_TO_PTR(self), other_in); return self; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union); +static MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union); -STATIC mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { case MP_UNARY_OP_BOOL: @@ -454,7 +454,7 @@ STATIC mp_obj_t set_unary_op(mp_unary_op_t op, mp_obj_t self_in) { } } -STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { +static mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_t args[] = {lhs, rhs}; #if MICROPY_PY_BUILTINS_FROZENSET bool update = mp_obj_is_type(lhs, &mp_type_set); @@ -520,7 +520,7 @@ STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { /******************************************************************************/ /* set constructors & public C API */ -STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { +static const mp_rom_map_elem_t set_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_add), MP_ROM_PTR(&set_add_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&set_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) }, @@ -540,7 +540,7 @@ STATIC const mp_rom_map_elem_t set_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&set_update_obj) }, { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); +static MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_set, @@ -555,7 +555,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); #if MICROPY_PY_BUILTINS_FROZENSET -STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { +static const mp_rom_map_elem_t frozenset_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_copy), MP_ROM_PTR(&set_copy_obj) }, { MP_ROM_QSTR(MP_QSTR_difference), MP_ROM_PTR(&set_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_intersection), MP_ROM_PTR(&set_intersect_obj) }, @@ -566,7 +566,7 @@ STATIC const mp_rom_map_elem_t frozenset_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_union), MP_ROM_PTR(&set_union_obj) }, { MP_ROM_QSTR(MP_QSTR___contains__), MP_ROM_PTR(&mp_op_contains_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); +static MP_DEFINE_CONST_DICT(frozenset_locals_dict, frozenset_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( mp_type_frozenset, diff --git a/py/objsingleton.c b/py/objsingleton.c index 6537676c52329..c1f102c94c014 100644 --- a/py/objsingleton.c +++ b/py/objsingleton.c @@ -37,7 +37,7 @@ typedef struct _mp_obj_singleton_t { qstr name; } mp_obj_singleton_t; -STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_singleton_t *self = MP_OBJ_TO_PTR(self_in); mp_printf(print, "%q", self->name); diff --git a/py/objslice.c b/py/objslice.c index abc1e87549955..5b21162d7487c 100644 --- a/py/objslice.c +++ b/py/objslice.c @@ -35,7 +35,7 @@ #if MICROPY_PY_BUILTINS_SLICE -STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_slice_t *o = MP_OBJ_TO_PTR(o_in); mp_print_str(print, "slice("); @@ -47,14 +47,14 @@ STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t mp_print_str(print, ")"); } -STATIC mp_obj_t slice_unary_op(mp_unary_op_t op, mp_obj_t o_in) { +static mp_obj_t slice_unary_op(mp_unary_op_t op, mp_obj_t o_in) { // Needed to explicitly opt out of default __hash__. // REVISIT: CPython implements comparison operators for slice. return MP_OBJ_NULL; } #if MICROPY_PY_BUILTINS_SLICE_INDICES -STATIC mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) { +static mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) { mp_int_t length = mp_obj_get_int(length_obj); mp_bound_slice_t bound_indices; mp_obj_slice_indices(self_in, length, &bound_indices); @@ -66,11 +66,11 @@ STATIC mp_obj_t slice_indices(mp_obj_t self_in, mp_obj_t length_obj) { }; return mp_obj_new_tuple(3, results); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(slice_indices_obj, slice_indices); +static MP_DEFINE_CONST_FUN_OBJ_2(slice_indices_obj, slice_indices); #endif #if MICROPY_PY_BUILTINS_SLICE_ATTRS -STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; @@ -94,7 +94,7 @@ STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // CIRCUITPY-CHANGE #if MICROPY_PY_BUILTINS_SLICE_ATTRS -STATIC mp_obj_t slice_make_new(const mp_obj_type_t *type, +static mp_obj_t slice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { if (type != &mp_type_slice) { mp_raise_NotImplementedError(MP_ERROR_TEXT("Cannot subclass slice")); @@ -121,10 +121,10 @@ STATIC mp_obj_t slice_make_new(const mp_obj_type_t *type, #endif #if MICROPY_PY_BUILTINS_SLICE_INDICES && !MICROPY_PY_BUILTINS_SLICE_ATTRS -STATIC const mp_rom_map_elem_t slice_locals_dict_table[] = { +static const mp_rom_map_elem_t slice_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_indices), MP_ROM_PTR(&slice_indices_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); +static MP_DEFINE_CONST_DICT(slice_locals_dict, slice_locals_dict_table); #endif #if MICROPY_PY_BUILTINS_SLICE_ATTRS diff --git a/py/objstr.c b/py/objstr.c index 5794765e7daca..bd650bbe18ad6 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -32,7 +32,8 @@ #include "py/objstr.h" #include "py/objlist.h" #include "py/runtime.h" -#include "py/stackctrl.h" +#include "py/cstack.h" +#include "py/objtuple.h" // CIRCUITPY-CHANGE const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', @@ -42,15 +43,15 @@ const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8 'a', 'b', 'c', 'd', 'e', 'f'}; #if MICROPY_PY_BUILTINS_STR_OP_MODULO -STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict); +static mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict); #endif -STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); -STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); +static mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); +static MP_NORETURN void bad_implicit_conversion(mp_obj_t self_in); -STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); +static mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr); -STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t arg) { +static void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t arg) { // String operations generally need the args type to match the object they're called on, // e.g. str.find(str), byte.startswith(byte) // with the exception that bytes may be used for bytearray and vice versa. @@ -70,10 +71,30 @@ STATIC void str_check_arg_type(const mp_obj_type_t *self_type, const mp_obj_t ar } } -STATIC void check_is_str_or_bytes(mp_obj_t self_in) { +static void check_is_str_or_bytes(mp_obj_t self_in) { mp_check_self(mp_obj_is_str_or_bytes(self_in)); } +static const byte *get_substring_data(const mp_obj_t obj, size_t n_args, const mp_obj_t *args, size_t *len) { + // Get substring data from obj, using args[0,1] to specify start and end indices. + GET_STR_DATA_LEN(obj, str, str_len); + if (n_args > 0) { + const mp_obj_type_t *self_type = mp_obj_get_type(obj); + const byte *end = str + str_len; + if (n_args > 1 && args[1] != mp_const_none) { + end = str_index_to_ptr(self_type, str, str_len, args[1], true); + } + if (args[0] != mp_const_none) { + str = str_index_to_ptr(self_type, str, str_len, args[0], true); + } + str_len = MAX(end - str, 0); + } + if (len) { + *len = str_len; + } + return str; +} + /******************************************************************************/ /* str */ @@ -142,7 +163,7 @@ void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str } #endif -STATIC void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void str_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { GET_STR_DATA_LEN(self_in, str_data, str_len); #if MICROPY_PY_JSON if (kind == PRINT_JSON) { @@ -219,7 +240,7 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ } } -STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; #if MICROPY_CPYTHON_COMPAT @@ -352,8 +373,7 @@ mp_obj_t mp_obj_str_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i mp_obj_t *args = &rhs_in; size_t n_args = 1; mp_obj_t dict = MP_OBJ_NULL; - if (mp_obj_is_type(rhs_in, &mp_type_tuple)) { - // TODO: Support tuple subclasses? + if (mp_obj_is_tuple_compatible(rhs_in)) { mp_obj_tuple_get(rhs_in, &n_args, &args); } else if (mp_obj_is_type(rhs_in, &mp_type_dict)) { dict = rhs_in; @@ -475,7 +495,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s #endif // This is used for both bytes and 8-bit strings. This is not used for unicode strings. -STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { const mp_obj_type_t *type = mp_obj_get_type(self_in); GET_STR_DATA_LEN(self_in, self_data, self_len); if (value == MP_OBJ_SENTINEL) { @@ -501,7 +521,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) { check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); const mp_obj_type_t *ret_type = self_type; @@ -645,7 +665,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, mp_obj_str_split); #if MICROPY_PY_BUILTINS_STR_SPLITLINES -STATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_keepends }; static const mp_arg_t allowed_args[] = { { MP_QSTR_keepends, MP_ARG_BOOL, {.u_bool = false} }, @@ -691,7 +711,7 @@ STATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t MP_DEFINE_CONST_FUN_OBJ_KW(str_splitlines_obj, 1, str_splitlines); #endif -STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { if (n_args < 3) { // If we don't have split limit, it doesn't matter from which side // we split. @@ -756,7 +776,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) { } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit); -STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { +static mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, bool is_index) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); check_is_str_or_bytes(args[0]); @@ -799,61 +819,58 @@ STATIC mp_obj_t str_finder(size_t n_args, const mp_obj_t *args, int direction, b } } -STATIC mp_obj_t str_find(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_find(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, 1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj, 2, 4, str_find); -STATIC mp_obj_t str_rfind(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_rfind(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, -1, false); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj, 2, 4, str_rfind); -STATIC mp_obj_t str_index(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_index(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, 1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_index_obj, 2, 4, str_index); -STATIC mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_rindex(size_t n_args, const mp_obj_t *args) { return str_finder(n_args, args, -1, true); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rindex_obj, 2, 4, str_rindex); -// TODO: (Much) more variety in args -STATIC mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { - const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); - GET_STR_DATA_LEN(args[0], str, str_len); - size_t prefix_len; - const char *prefix = mp_obj_str_get_data(args[1], &prefix_len); - const byte *start = str; - if (n_args > 2) { - start = str_index_to_ptr(self_type, str, str_len, args[2], true); +static mp_obj_t str_startendswith(size_t n_args, const mp_obj_t *args, bool ends_with) { + size_t str_len; + const byte *str = get_substring_data(args[0], n_args - 2, args + 2, &str_len); + mp_obj_t *prefixes = (mp_obj_t *)&args[1]; + size_t n_prefixes = 1; + if (mp_obj_is_type(args[1], &mp_type_tuple)) { + mp_obj_tuple_get(args[1], &n_prefixes, &prefixes); } - if (prefix_len + (start - str) > str_len) { - return mp_const_false; + size_t prefix_len; + for (size_t i = 0; i < n_prefixes; i++) { + const char *prefix = mp_obj_str_get_data(prefixes[i], &prefix_len); + const byte *s = str + (ends_with ? str_len - prefix_len : 0); + if (prefix_len <= str_len && memcmp(s, prefix, prefix_len) == 0) { + return mp_const_true; + } } - return mp_obj_new_bool(memcmp(start, prefix, prefix_len) == 0); + return mp_const_false; } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith); -STATIC mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { - GET_STR_DATA_LEN(args[0], str, str_len); - size_t suffix_len; - const char *suffix = mp_obj_str_get_data(args[1], &suffix_len); - if (n_args > 2) { - mp_raise_NotImplementedError(MP_ERROR_TEXT("start/end indices")); - } +static mp_obj_t str_startswith(size_t n_args, const mp_obj_t *args) { + return str_startendswith(n_args, args, false); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 4, str_startswith); - if (suffix_len > str_len) { - return mp_const_false; - } - return mp_obj_new_bool(memcmp(str + (str_len - suffix_len), suffix, suffix_len) == 0); +static mp_obj_t str_endswith(size_t n_args, const mp_obj_t *args) { + return str_startendswith(n_args, args, true); } -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 4, str_endswith); enum { LSTRIP, RSTRIP, STRIP }; -STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { check_is_str_or_bytes(args[0]); const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); @@ -922,23 +939,23 @@ STATIC mp_obj_t str_uni_strip(int type, size_t n_args, const mp_obj_t *args) { return mp_obj_new_str_of_type(self_type, orig_str + first_good_char_pos, stripped_len); } -STATIC mp_obj_t str_strip(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_strip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(STRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); -STATIC mp_obj_t str_lstrip(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_lstrip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(LSTRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_lstrip_obj, 1, 2, str_lstrip); -STATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) { return str_uni_strip(RSTRIP, n_args, args); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rstrip_obj, 1, 2, str_rstrip); #if MICROPY_PY_BUILTINS_STR_CENTER -STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) { +static mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) { GET_STR_DATA_LEN(str_in, str, str_len); mp_uint_t width = mp_obj_get_int(width_in); if (str_len >= width) { @@ -957,7 +974,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center); // Takes an int arg, but only parses unsigned numbers, and only changes // *num if at least one digit was parsed. -STATIC const char *str_to_int(const char *str, const char *top, int *num) { +static const char *str_to_int(const char *str, const char *top, int *num) { if (str < top && '0' <= *str && *str <= '9') { *num = 0; do { @@ -969,19 +986,19 @@ STATIC const char *str_to_int(const char *str, const char *top, int *num) { return str; } -STATIC bool isalignment(char ch) { +static bool isalignment(char ch) { return ch && strchr("<>=^", ch) != NULL; } -STATIC bool istype(char ch) { +static bool istype(char ch) { return ch && strchr("bcdeEfFgGnosxX%", ch) != NULL; } -STATIC bool arg_looks_integer(mp_obj_t arg) { +static bool arg_looks_integer(mp_obj_t arg) { return mp_obj_is_bool(arg) || mp_obj_is_int(arg); } -STATIC bool arg_looks_numeric(mp_obj_t arg) { +static bool arg_looks_numeric(mp_obj_t arg) { return arg_looks_integer(arg) #if MICROPY_PY_BUILTINS_FLOAT || mp_obj_is_float(arg) @@ -990,7 +1007,7 @@ STATIC bool arg_looks_numeric(mp_obj_t arg) { } #if MICROPY_PY_BUILTINS_STR_OP_MODULO -STATIC mp_obj_t arg_as_int(mp_obj_t arg) { +static mp_obj_t arg_as_int(mp_obj_t arg) { #if MICROPY_PY_BUILTINS_FLOAT if (mp_obj_is_float(arg)) { return mp_obj_new_int_from_float(mp_obj_float_get(arg)); @@ -1001,7 +1018,7 @@ STATIC mp_obj_t arg_as_int(mp_obj_t arg) { #endif #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE -STATIC NORETURN void terse_str_format_value_error(void) { +static MP_NORETURN void terse_str_format_value_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("bad format string")); } #else @@ -1009,7 +1026,7 @@ STATIC NORETURN void terse_str_format_value_error(void) { #define terse_str_format_value_error() #endif -STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { +static vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *arg_i, size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 16, &print); @@ -1102,7 +1119,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE terse_str_format_value_error(); #else - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: consolidated message mp_raise_ValueError_varg(MP_ERROR_TEXT("unmatched '%c' in format"), '{'); #endif } @@ -1129,7 +1146,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } field_name = str_to_int(field_name, field_name_top, &index); if ((uint)index >= n_args - 1) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE:consolidated message mp_raise_IndexError_varg(MP_ERROR_TEXT("%q index out of range"), MP_QSTR_tuple); } arg = args[index + 1]; @@ -1188,7 +1205,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar int width = -1; int precision = -1; char type = '\0'; - int flags = 0; + unsigned int flags = 0; if (format_spec) { // The format specifier (from http://docs.python.org/2/library/string.html#formatspec) @@ -1202,7 +1219,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar // type ::= "b" | "c" | "d" | "e" | "E" | "f" | "F" | "g" | "G" | "n" | "o" | "s" | "x" | "X" | "%" // recursively call the formatter to format any nested specifiers - MP_STACK_CHECK(); + mp_cstack_check(); vstr_t format_spec_vstr = mp_obj_str_format_helper(format_spec, str, arg_i, n_args, args, kwargs); const char *s = vstr_null_terminated_str(&format_spec_vstr); const char *stop = s + format_spec_vstr.len; @@ -1233,8 +1250,9 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } } s = str_to_int(s, stop, &width); - if (*s == ',') { - flags |= PF_FLAG_SHOW_COMMA; + if (*s == ',' || *s == '_') { + MP_STATIC_ASSERT((unsigned)'_' << PF_FLAG_SEP_POS >> PF_FLAG_SEP_POS == '_'); + flags |= (unsigned)*s << PF_FLAG_SEP_POS; s++; } if (*s == '.') { @@ -1307,7 +1325,7 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar } case '\0': // No explicit format type implies 'd' - case 'n': // I don't think we support locales in uPy so use 'd' + case 'n': // I don't think we support locales in MicroPython so use 'd' case 'd': mp_print_mp_int(&print, arg, 10, 'a', flags, fill, width, 0); continue; @@ -1473,7 +1491,7 @@ mp_obj_t mp_obj_str_format(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs MP_DEFINE_CONST_FUN_OBJ_KW(str_format_obj, 1, mp_obj_str_format); #if MICROPY_PY_BUILTINS_STR_OP_MODULO -STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) { +static mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_t *args, mp_obj_t dict) { check_is_str_or_bytes(pattern); GET_STR_DATA_LEN(pattern, str, len); @@ -1503,8 +1521,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ // Dictionary value lookup if (*str == '(') { if (dict == MP_OBJ_NULL) { - // CIRCUITPY-CHANGE: clearer message - mp_raise_TypeError(MP_ERROR_TEXT("format requires a dict")); + mp_raise_TypeError(MP_ERROR_TEXT("format needs a dict")); } arg_i = 1; // we used up the single dict argument const byte *key = ++str; @@ -1585,8 +1602,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ if (arg == MP_OBJ_NULL) { if (arg_i >= n_args) { not_enough_args: - // CIRCUITPY-CHANGE: clearer message - mp_raise_TypeError(MP_ERROR_TEXT("not enough arguments for format string")); + mp_raise_TypeError(MP_ERROR_TEXT("format string needs more arguments")); } arg = args[arg_i++]; } @@ -1596,16 +1612,14 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ size_t slen; const char *s = mp_obj_str_get_data(arg, &slen); if (slen != 1) { - // CIRCUITPY-CHANGE: clearer message - mp_raise_TypeError(MP_ERROR_TEXT("%%c requires int or char")); + mp_raise_TypeError(MP_ERROR_TEXT("%%c needs int or char")); } mp_print_strn(&print, s, 1, flags, ' ', width); } else if (arg_looks_integer(arg)) { char ch = mp_obj_get_int(arg); mp_print_strn(&print, &ch, 1, flags, ' ', width); } else { - // CIRCUITPY-CHANGE: clearer message - mp_raise_TypeError(MP_ERROR_TEXT("%%c requires int or char")); + mp_raise_TypeError(MP_ERROR_TEXT("%%c needs int or char")); } break; @@ -1677,8 +1691,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ if (dict == MP_OBJ_NULL && arg_i != n_args) { // NOTE: if `dict` exists, then `n_args` is 1 and the dict is always consumed; either // positionally, or as a map of named args, even if none were actually referenced. - // CIRCUITPY-CHANGE: clearer message - mp_raise_TypeError(MP_ERROR_TEXT("not all arguments converted during string formatting")); + mp_raise_TypeError(MP_ERROR_TEXT("format string didn't convert all arguments")); } return mp_obj_new_str_type_from_vstr(is_bytes ? &mp_type_bytes : &mp_type_str, &vstr); @@ -1687,7 +1700,7 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ // The implementation is optimized, returning the original string if there's // nothing to replace. -STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { check_is_str_or_bytes(args[0]); mp_int_t max_rep = -1; @@ -1789,7 +1802,7 @@ STATIC mp_obj_t str_replace(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); #if MICROPY_PY_BUILTINS_STR_COUNT -STATIC mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_count(size_t n_args, const mp_obj_t *args) { const mp_obj_type_t *self_type = mp_obj_get_type(args[0]); check_is_str_or_bytes(args[0]); @@ -1832,7 +1845,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); #endif #if MICROPY_PY_BUILTINS_STR_PARTITION -STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { +static mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { check_is_str_or_bytes(self_in); const mp_obj_type_t *self_type = mp_obj_get_type(self_in); str_check_arg_type(self_type, arg); @@ -1878,19 +1891,19 @@ STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, int direction) { return mp_obj_new_tuple(3, result); } -STATIC mp_obj_t str_partition(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t str_partition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, 1); } MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition); -STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { +static mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { return str_partitioner(self_in, arg, -1); } MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition); #endif // Supposedly not too critical operations, so optimize for code size -STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { +static mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); vstr_t vstr; vstr_init_len(&vstr, self_len); @@ -1901,17 +1914,17 @@ STATIC mp_obj_t str_caseconv(unichar (*op)(unichar), mp_obj_t self_in) { return mp_obj_new_str_type_from_vstr(mp_obj_get_type(self_in), &vstr); } -STATIC mp_obj_t str_lower(mp_obj_t self_in) { +static mp_obj_t str_lower(mp_obj_t self_in) { return str_caseconv(unichar_tolower, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_lower_obj, str_lower); -STATIC mp_obj_t str_upper(mp_obj_t self_in) { +static mp_obj_t str_upper(mp_obj_t self_in) { return str_caseconv(unichar_toupper, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_upper_obj, str_upper); -STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) { +static mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, self_data, self_len); if (self_len == 0) { @@ -1944,27 +1957,27 @@ STATIC mp_obj_t str_uni_istype(bool (*f)(unichar), mp_obj_t self_in) { return mp_const_true; } -STATIC mp_obj_t str_isspace(mp_obj_t self_in) { +static mp_obj_t str_isspace(mp_obj_t self_in) { return str_uni_istype(unichar_isspace, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isspace_obj, str_isspace); -STATIC mp_obj_t str_isalpha(mp_obj_t self_in) { +static mp_obj_t str_isalpha(mp_obj_t self_in) { return str_uni_istype(unichar_isalpha, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isalpha_obj, str_isalpha); -STATIC mp_obj_t str_isdigit(mp_obj_t self_in) { +static mp_obj_t str_isdigit(mp_obj_t self_in) { return str_uni_istype(unichar_isdigit, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isdigit_obj, str_isdigit); -STATIC mp_obj_t str_isupper(mp_obj_t self_in) { +static mp_obj_t str_isupper(mp_obj_t self_in) { return str_uni_istype(unichar_isupper, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_isupper_obj, str_isupper); -STATIC mp_obj_t str_islower(mp_obj_t self_in) { +static mp_obj_t str_islower(mp_obj_t self_in) { return str_uni_istype(unichar_islower, self_in); } MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower); @@ -1973,7 +1986,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(str_islower_obj, str_islower); // These methods are superfluous in the presence of str() and bytes() // constructors. // TODO: should accept kwargs too -STATIC mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) { +static mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) { mp_obj_t new_args[2]; if (n_args == 1) { new_args[0] = args[0]; @@ -1986,7 +1999,7 @@ STATIC mp_obj_t bytes_decode(size_t n_args, const mp_obj_t *args) { MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bytes_decode_obj, 1, 3, bytes_decode); // TODO: should accept kwargs too -STATIC mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) { +static mp_obj_t str_encode(size_t n_args, const mp_obj_t *args) { mp_obj_t new_args[2]; if (n_args == 1) { new_args[0] = args[0]; @@ -2044,38 +2057,32 @@ mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); - if ((bufinfo.len & 1) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("odd-length string")); - } vstr_t vstr; vstr_init_len(&vstr, bufinfo.len / 2); byte *in = bufinfo.buf, *out = (byte *)vstr.buf; - byte hex_byte = 0; - for (mp_uint_t i = bufinfo.len; i--;) { - byte hex_ch = *in++; - if (unichar_isxdigit(hex_ch)) { - hex_byte += unichar_xdigit_value(hex_ch); - } else { - mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit found")); + byte *in_end = in + bufinfo.len; + mp_uint_t ch1, ch2; + while (in < in_end) { + if (unichar_isspace(ch1 = *in++)) { + continue; // Skip whitespace between hex digit pairs } - if (i & 1) { - hex_byte <<= 4; - } else { - *out++ = hex_byte; - hex_byte = 0; + if (in == in_end || !unichar_isxdigit(ch1) || !unichar_isxdigit(ch2 = *in++)) { + mp_raise_ValueError(MP_ERROR_TEXT("non-hex digit")); } + *out++ = (byte)((unichar_xdigit_value(ch1) << 4) | unichar_xdigit_value(ch2)); } + vstr.len = out - (byte *)vstr.buf; // Length may be shorter due to whitespace in input return mp_obj_new_str_type_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr); } -STATIC mp_obj_t bytes_hex_as_str(size_t n_args, const mp_obj_t *args) { +static mp_obj_t bytes_hex_as_str(size_t n_args, const mp_obj_t *args) { return mp_obj_bytes_hex(n_args, args, &mp_type_str); } // CIRCUITPY-CHANGE: make public MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_obj_bytes_hex_as_str_obj, 1, 2, bytes_hex_as_str); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bytes_fromhex_obj, mp_obj_bytes_fromhex); -STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR(&bytes_fromhex_obj)); +static MP_DEFINE_CONST_FUN_OBJ_2(bytes_fromhex_obj, mp_obj_bytes_fromhex); +static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bytes_fromhex_classmethod_obj, MP_ROM_PTR(&bytes_fromhex_obj)); #endif // MICROPY_PY_BUILTINS_BYTES_HEX mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { @@ -2099,7 +2106,7 @@ void mp_obj_str_set_data(mp_obj_str_t *str, const byte *data, size_t len) { // This locals table is used for the following types: str, bytes, bytearray, array.array. // Each type takes a different section (start to end offset) of this table. -STATIC const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { +static const mp_rom_map_elem_t array_bytearray_str_bytes_locals_table[] = { #if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY { MP_ROM_QSTR(MP_QSTR_append), MP_ROM_PTR(&mp_obj_array_append_obj) }, { MP_ROM_QSTR(MP_QSTR_extend), MP_ROM_PTR(&mp_obj_array_extend_obj) }, @@ -2201,12 +2208,13 @@ MP_DEFINE_CONST_DICT_WITH_SIZE(mp_obj_memoryview_locals_dict, #endif #if !MICROPY_PY_BUILTINS_STR_UNICODE -STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); +static mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_str, MP_QSTR_str, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_str_make_new, print, str_print, binary_op, mp_obj_str_binary_op, @@ -2273,7 +2281,7 @@ mp_obj_t mp_obj_new_str_via_qstr(const char *data, size_t len) { // Create a str/bytes object from the given vstr. The vstr buffer is resized to // the exact length required and then reused for the str/bytes object. The vstr // is cleared and can safely be passed to vstr_free if it was heap allocated. -STATIC mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { +static mp_obj_t mp_obj_new_str_type_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) { // if not a bytes object, look if a qstr with this data already exists if (type == &mp_type_str) { qstr q = qstr_find_strn(vstr->buf, vstr->len); @@ -2341,6 +2349,10 @@ mp_obj_t mp_obj_new_str(const char *data, size_t len) { } } +mp_obj_t mp_obj_new_str_from_cstr(const char *str) { + return mp_obj_new_str(str, strlen(str)); +} + mp_obj_t mp_obj_str_intern(mp_obj_t str) { GET_STR_DATA_LEN(str, data, len); return mp_obj_new_str_via_qstr((const char *)data, len); @@ -2384,7 +2396,7 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) { } } -STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in) { +static MP_NORETURN void bad_implicit_conversion(mp_obj_t self_in) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("can't convert to str implicitly")); #else @@ -2454,7 +2466,7 @@ typedef struct _mp_obj_str8_it_t { } mp_obj_str8_it_t; #if !MICROPY_PY_BUILTINS_STR_UNICODE -STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { +static mp_obj_t str_it_iternext(mp_obj_t self_in) { mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { @@ -2466,7 +2478,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { } } -STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_str8_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_str8_it_t *o = (mp_obj_str8_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; @@ -2477,7 +2489,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_bu } #endif -STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) { +static mp_obj_t bytes_it_iternext(mp_obj_t self_in) { mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { diff --git a/py/objstr.h b/py/objstr.h index bc3a36b5f8fcb..c241d6e1cd1b2 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -104,6 +104,8 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); +#define MP_DEFINE_BYTES_OBJ(obj_name, target, len) mp_obj_str_t obj_name = {{&mp_type_bytes}, 0, (len), (const byte *)(target)} + mp_obj_t mp_obj_bytes_hex(size_t n_args, const mp_obj_t *args, const mp_obj_type_t *type); mp_obj_t mp_obj_bytes_fromhex(mp_obj_t type_in, mp_obj_t data); diff --git a/py/objstringio.c b/py/objstringio.c index d191974a1fc03..25e04cb4c696c 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -36,7 +36,7 @@ #if MICROPY_PY_IO #if MICROPY_CPYTHON_COMPAT -STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { +static void check_stringio_is_open(const mp_obj_stringio_t *o) { if (o->vstr == NULL) { mp_raise_ValueError(MP_ERROR_TEXT("I/O operation on closed file")); } @@ -46,7 +46,7 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { #endif // CIRCUITPY-CHANGE: handling subclassing -STATIC mp_obj_stringio_t *native_obj(mp_obj_t o_in) { +static mp_obj_stringio_t *native_obj(mp_obj_t o_in) { mp_obj_stringio_t *native = mp_obj_cast_to_native_base(o_in, &mp_type_stringio); #if MICROPY_PY_IO_BYTESIO @@ -57,14 +57,14 @@ STATIC mp_obj_stringio_t *native_obj(mp_obj_t o_in) { return native; } -STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; // CIRCUITPY-CHANGE mp_obj_stringio_t *self = native_obj(self_in); mp_printf(print, self->base.type == &mp_type_stringio ? "" : "", self); } -STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) { (void)errcode; // CIRCUITPY-CHANGE mp_obj_stringio_t *o = native_obj(o_in); @@ -81,7 +81,7 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er return size; } -STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) { +static void stringio_copy_on_write(mp_obj_stringio_t *o) { const void *buf = o->vstr->buf; o->vstr->buf = m_new(char, o->vstr->len); o->vstr->fixed_buf = false; @@ -89,7 +89,7 @@ STATIC void stringio_copy_on_write(mp_obj_stringio_t *o) { memcpy(o->vstr->buf, buf, o->vstr->len); } -STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) { (void)errcode; // CIRCUITPY-CHANGE mp_obj_stringio_t *o = native_obj(o_in); @@ -124,7 +124,7 @@ STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, return size; } -STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)errcode; // CIRCUITPY-CHANGE mp_obj_stringio_t *o = native_obj(o_in); @@ -178,23 +178,23 @@ STATIC mp_uint_t stringio_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, #define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes) -STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) { +static mp_obj_t stringio_getvalue(mp_obj_t self_in) { // CIRCUITPY-CHANGE mp_obj_stringio_t *self = native_obj(self_in); check_stringio_is_open(self); // TODO: Try to avoid copying string return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte *)self->vstr->buf, self->vstr->len); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); +static MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue); -STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { +static mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { mp_obj_stringio_t *o = mp_obj_malloc(mp_obj_stringio_t, type); o->pos = 0; o->ref_obj = MP_OBJ_NULL; return o; } -STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)n_kw; // TODO check n_kw==0 mp_uint_t sz = 16; @@ -232,7 +232,7 @@ STATIC mp_obj_t stringio_make_new(const mp_obj_type_t *type_in, size_t n_args, s return MP_OBJ_FROM_PTR(o); } -STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { +static const mp_rom_map_elem_t stringio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, @@ -246,9 +246,9 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); +static MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); -STATIC const mp_stream_p_t stringio_stream_p = { +static const mp_stream_p_t stringio_stream_p = { .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, @@ -266,7 +266,7 @@ MP_DEFINE_CONST_OBJ_TYPE( ); #if MICROPY_PY_IO_BYTESIO -STATIC const mp_stream_p_t bytesio_stream_p = { +static const mp_stream_p_t bytesio_stream_p = { .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, diff --git a/py/objstrunicode.c b/py/objstrunicode.c index b1c1185d2d6a9..a158b91236588 100644 --- a/py/objstrunicode.c +++ b/py/objstrunicode.c @@ -34,12 +34,12 @@ #if MICROPY_PY_BUILTINS_STR_UNICODE -STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); +static mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); /******************************************************************************/ /* str */ -STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) { +static void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint str_len) { // this escapes characters, but it will be very slow to print (calling print many times) bool has_single_quote = false; bool has_double_quote = false; @@ -90,7 +90,7 @@ STATIC void uni_print_quoted(const mp_print_t *print, const byte *str_data, uint mp_printf(print, "%c", quote_char); } -STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { GET_STR_DATA_LEN(self_in, str_data, str_len); #if MICROPY_PY_JSON if (kind == PRINT_JSON) { @@ -105,7 +105,7 @@ STATIC void uni_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t } } -STATIC mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t uni_unary_op(mp_unary_op_t op, mp_obj_t self_in) { GET_STR_DATA_LEN(self_in, str_data, str_len); switch (op) { case MP_UNARY_OP_BOOL: @@ -185,7 +185,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s return s; } -STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { const mp_obj_type_t *type = mp_obj_get_type(self_in); assert(type == &mp_type_str); GET_STR_DATA_LEN(self_in, self_data, self_len); @@ -236,10 +236,11 @@ STATIC mp_obj_t str_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_str, MP_QSTR_str, - MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_str_make_new, print, uni_print, unary_op, uni_unary_op, @@ -260,7 +261,7 @@ typedef struct _mp_obj_str_it_t { size_t cur; } mp_obj_str_it_t; -STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { +static mp_obj_t str_it_iternext(mp_obj_t self_in) { mp_obj_str_it_t *self = MP_OBJ_TO_PTR(self_in); GET_STR_DATA_LEN(self->str, str, len); if (self->cur < len) { @@ -274,7 +275,7 @@ STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) { } } -STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { +static mp_obj_t mp_obj_new_str_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_str_it_t) <= sizeof(mp_obj_iter_buf_t)); mp_obj_str_it_t *o = (mp_obj_str_it_t *)iter_buf; o->base.type = &mp_type_polymorph_iter; diff --git a/py/objtraceback.c b/py/objtraceback.c index 7fcec9383d05d..7299427b15941 100644 --- a/py/objtraceback.c +++ b/py/objtraceback.c @@ -1,35 +1,15 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 microDev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT #include "py/runtime.h" #include "py/objtraceback.h" const mp_obj_traceback_t mp_const_empty_traceback_obj = {{&mp_type_traceback}, 0, 0, NULL}; -STATIC void mp_obj_traceback_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void mp_obj_traceback_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_traceback_t *o = MP_OBJ_TO_PTR(o_in); mp_printf(print, "<%q object at %p>", MP_QSTR_traceback, o); diff --git a/py/objtraceback.h b/py/objtraceback.h index 992fe89b01f83..e6be254a5db6c 100644 --- a/py/objtraceback.h +++ b/py/objtraceback.h @@ -1,31 +1,10 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 microDev - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2021 microDev +// +// SPDX-License-Identifier: MIT -#ifndef MICROPY_INCLUDED_PY_OBJTRACEBACK_H -#define MICROPY_INCLUDED_PY_OBJTRACEBACK_H +#pragma once #include "py/obj.h" @@ -35,5 +14,3 @@ typedef struct _mp_obj_traceback_t { size_t len : (8 * sizeof(size_t) / 2); size_t *data; } mp_obj_traceback_t; - -#endif // MICROPY_INCLUDED_PY_OBJTRACEBACK_H diff --git a/py/objtuple.c b/py/objtuple.c index 79703d68c83d6..b2ccbbb299082 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -31,9 +31,6 @@ #include "py/objtuple.h" #include "py/runtime.h" -// type check is done on getiter method to allow tuple, namedtuple, attrtuple -#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) - /******************************************************************************/ /* tuple */ @@ -65,7 +62,7 @@ void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t } } -STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 0, 1, false); @@ -86,7 +83,8 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg size_t alloc = 4; size_t len = 0; - mp_obj_t *items = m_new(mp_obj_t, alloc); + // CIRCUITPY-CHANGE + mp_obj_t *items = m_malloc_items(alloc); mp_obj_t iterable = mp_getiter(args[0], NULL); mp_obj_t item; @@ -107,7 +105,7 @@ STATIC mp_obj_t mp_obj_tuple_make_new(const mp_obj_type_t *type_in, size_t n_arg } // Don't pass MP_BINARY_OP_NOT_EQUAL here -STATIC mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { +static mp_obj_t tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { mp_check_self(mp_obj_is_tuple_compatible(self_in)); const mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); @@ -211,31 +209,32 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { } } -STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) { +static mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) { mp_check_self(mp_obj_is_type(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); return mp_seq_count_obj(self->items, self->len, value); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count); +static MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count); -STATIC mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) { +static mp_obj_t tuple_index(size_t n_args, const mp_obj_t *args) { mp_check_self(mp_obj_is_type(args[0], &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]); return mp_seq_index_obj(self->items, self->len, n_args, args); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index); -STATIC const mp_rom_map_elem_t tuple_locals_dict_table[] = { +static const mp_rom_map_elem_t tuple_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&tuple_count_obj) }, { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&tuple_index_obj) }, }; -STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); +static MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table); +// CIRCUITPY-CHANGE: Diagnose json.dump on invalid types MP_DEFINE_CONST_OBJ_TYPE( mp_type_tuple, MP_QSTR_tuple, - MP_TYPE_FLAG_ITER_IS_GETITER, + MP_TYPE_FLAG_ITER_IS_GETITER | MP_TYPE_FLAG_PRINT_JSON, make_new, mp_obj_tuple_make_new, print, mp_obj_tuple_print, unary_op, mp_obj_tuple_unary_op, @@ -248,11 +247,14 @@ MP_DEFINE_CONST_OBJ_TYPE( // the zero-length tuple const mp_obj_tuple_t mp_const_empty_tuple_obj = {{&mp_type_tuple}, 0}; +// CIRCUITPY-CHANGE: No change here, but implementation was copied for +// mp_obj_new_port_tuple in supervisor/shared/port.c, which allocates using port_malloc(). +// Change that to match if this changes. mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) { if (n == 0) { return mp_const_empty_tuple; } - mp_obj_tuple_t *o = mp_obj_malloc_var(mp_obj_tuple_t, mp_obj_t, n, &mp_type_tuple); + mp_obj_tuple_t *o = mp_obj_malloc_var(mp_obj_tuple_t, items, mp_obj_t, n, &mp_type_tuple); o->len = n; if (items) { for (size_t i = 0; i < n; i++) { @@ -285,7 +287,7 @@ typedef struct _mp_obj_tuple_it_t { size_t cur; } mp_obj_tuple_it_t; -STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) { +static mp_obj_t tuple_it_iternext(mp_obj_t self_in) { mp_obj_tuple_it_t *self = MP_OBJ_TO_PTR(self_in); if (self->cur < self->tuple->len) { mp_obj_t o_out = self->tuple->items[self->cur]; diff --git a/py/objtuple.h b/py/objtuple.h index e2d010e6c5a3d..783522a6222b5 100644 --- a/py/objtuple.h +++ b/py/objtuple.h @@ -57,7 +57,7 @@ extern const mp_obj_type_t mp_type_attrtuple; #define MP_DEFINE_ATTRTUPLE(tuple_obj_name, fields, nitems, ...) \ const mp_rom_obj_tuple_t tuple_obj_name = { \ - .base = {&mp_type_attrtuple}, \ + .base = {.type = &mp_type_attrtuple}, \ .len = nitems, \ .items = { __VA_ARGS__, MP_ROM_PTR((void *)fields) } \ } @@ -68,4 +68,7 @@ void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields, mp_obj_t mp_obj_new_attrtuple(const qstr *fields, size_t n, const mp_obj_t *items); +// type check is done on getiter method to allow tuple, namedtuple, attrtuple +#define mp_obj_is_tuple_compatible(o) (MP_OBJ_TYPE_GET_SLOT_OR_NULL(mp_obj_get_type(o), iter) == mp_obj_tuple_getiter) + #endif // MICROPY_INCLUDED_PY_OBJTUPLE_H diff --git a/py/objtype.c b/py/objtype.c index 504806d807d6a..b1a984b50e057 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -44,12 +44,14 @@ #define ENABLE_SPECIAL_ACCESSORS \ (MICROPY_PY_DESCRIPTORS || MICROPY_PY_DELATTR_SETATTR || MICROPY_PY_BUILTINS_PROPERTY) -STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); +static mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict); +static mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo); +static mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_t n_args, size_t n_kw, const mp_obj_t *args); /******************************************************************************/ // instance object -STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) { +static int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) { int count = 0; for (;;) { if (type == &mp_type_object) { @@ -83,9 +85,9 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t } // CIRCUITPY-CHANGE: support superclass constructors that take kw args -// This wrapper function is allows a subclass of a native type to call the +// This wrapper function allows a subclass of a native type to call the // __init__() method (corresponding to type->make_new) of the native type. -STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +static mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(pos_args[0]); const mp_obj_type_t *native_base = NULL; instance_count_native_bases(self->base.type, &native_base); @@ -96,7 +98,8 @@ STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args pos_args++; n_args--; - mp_obj_t *args2 = m_new(mp_obj_t, n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(n_args + 2 * n_kw); // copy in args memcpy(args2, pos_args, n_args * sizeof(mp_obj_t)); // copy in kwargs @@ -109,15 +112,15 @@ STATIC mp_obj_t native_base_init_wrapper(size_t n_args, const mp_obj_t *pos_args return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(native_base_init_wrapper_obj, 1, native_base_init_wrapper); +static MP_DEFINE_CONST_FUN_OBJ_KW(native_base_init_wrapper_obj, 1, native_base_init_wrapper); #if !MICROPY_CPYTHON_COMPAT -STATIC +static #endif mp_obj_instance_t *mp_obj_new_instance(const mp_obj_type_t *class, const mp_obj_type_t **native_base) { size_t num_native_bases = instance_count_native_bases(class, native_base); assert(num_native_bases < 2); - mp_obj_instance_t *o = mp_obj_malloc_var(mp_obj_instance_t, mp_obj_t, num_native_bases, class); + mp_obj_instance_t *o = mp_obj_malloc_var(mp_obj_instance_t, subobj, mp_obj_t, num_native_bases, class); mp_map_init(&o->members, 0); // Initialise the native base-class slot (should be 1 at most) with a valid // object. It doesn't matter which object, so long as it can be uniquely @@ -161,7 +164,7 @@ struct class_lookup_data { bool is_type; }; -STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) { +static void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_type_t *type) { assert(lookup->dest[0] == MP_OBJ_NULL); assert(lookup->dest[1] == MP_OBJ_NULL); for (;;) { @@ -263,7 +266,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_t } } -STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__; mp_obj_t member[2] = {MP_OBJ_NULL}; @@ -306,7 +309,7 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k mp_printf(print, "<%q object at %p>", mp_obj_get_type_qstr(self_in), self); } -STATIC mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { assert(mp_obj_is_instance_type(self)); // look for __new__ function @@ -340,7 +343,8 @@ STATIC mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_arg mp_obj_t args2[1] = {MP_OBJ_FROM_PTR(self)}; new_ret = mp_call_function_n_kw(init_fn[0], 1, 0, args2); } else { - mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(1 + n_args + 2 * n_kw); args2[0] = MP_OBJ_FROM_PTR(self); memcpy(args2 + 1, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); new_ret = mp_call_function_n_kw(init_fn[0], n_args + 1, n_kw, args2); @@ -371,7 +375,8 @@ STATIC mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_arg if (n_args == 0 && n_kw == 0) { init_ret = mp_call_method_n_kw(0, 0, init_fn); } else { - mp_obj_t *args2 = m_new(mp_obj_t, 2 + n_args + 2 * n_kw); + // CIRCUITPY-CHANGE + mp_obj_t *args2 = m_malloc_items(2 + n_args + 2 * n_kw); args2[0] = init_fn[0]; args2[1] = init_fn[1]; memcpy(args2 + 2, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t)); @@ -399,6 +404,8 @@ STATIC mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_arg // Qstrs for special methods are guaranteed to have a small value, so we use byte // type to represent them. +// The (unescaped) names appear in `unsorted_str_list` in the QSTR +// generator script py/makeqstrdata.py to ensure they are assigned low numbers. const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { [MP_UNARY_OP_BOOL] = MP_QSTR___bool__, [MP_UNARY_OP_LEN] = MP_QSTR___len__, @@ -421,7 +428,7 @@ const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = { #endif }; -STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { +static mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_PY_SYS_GETSIZEOF @@ -497,6 +504,8 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) { // fail). They can be added at the expense of code size for the qstr. // Qstrs for special methods are guaranteed to have a small value, so we use byte // type to represent them. +// The (unescaped) names appear in `unsorted_str_list` in the QSTR +// generator script py/makeqstrdata.py to ensure they are assigned low numbers. const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { [MP_BINARY_OP_LESS] = MP_QSTR___lt__, [MP_BINARY_OP_MORE] = MP_QSTR___gt__, @@ -559,7 +568,7 @@ const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = { #endif }; -STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // Note: For ducktyping, CPython does not look in the instance members or use // __getattr__ or __getattribute__. It only looks in the class dictionary. mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in); @@ -601,7 +610,7 @@ STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t return res; } -STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { // logic: look in instance members then class locals assert(mp_obj_is_instance_type(mp_obj_get_type(self_in))); mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); @@ -681,6 +690,13 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des // try __getattr__ if (attr != MP_QSTR___getattr__) { + #if MICROPY_PY_DESCRIPTORS + // With descriptors enabled, don't delegate lookups of __get__/__set__/__delete__/__set_name__. + if (attr == MP_QSTR___get__ || attr == MP_QSTR___set__ || attr == MP_QSTR___delete__ || attr == MP_QSTR___set_name__) { + return; + } + #endif + #if MICROPY_PY_DELATTR_SETATTR // If the requested attr is __setattr__/__delattr__ then don't delegate the lookup // to __getattr__. If we followed CPython's behaviour then __setattr__/__delattr__ @@ -701,7 +717,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des } } -STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { +static bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); if (!(self->base.type->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { @@ -826,7 +842,7 @@ STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val } } -STATIC void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { mp_obj_instance_load_attr(self_in, attr, dest); } else { @@ -836,7 +852,7 @@ STATIC void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } } -STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { +static mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[4] = {MP_OBJ_NULL, MP_OBJ_NULL, index, value}; struct class_lookup_data lookup = { @@ -875,7 +891,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value } } -STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) { +static mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in, mp_obj_t *member) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); struct class_lookup_data lookup = { .obj = self, @@ -900,7 +916,8 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("object not callable")); #else - mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object is not callable"), + // CIRCUITPY-CHANGE: use more specific raise + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object isn't callable"), mp_obj_get_type_qstr(self_in)); #endif } @@ -941,7 +958,7 @@ mp_obj_t mp_obj_instance_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) } } -STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { +static mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t member[2] = {MP_OBJ_NULL}; struct class_lookup_data lookup = { @@ -967,7 +984,7 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, // - creating a new class (a new type) creates a new mp_obj_type_t #if ENABLE_SPECIAL_ACCESSORS -STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { +static bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #if MICROPY_PY_DELATTR_SETATTR if (key == MP_OBJ_NEW_QSTR(MP_QSTR___setattr__) || key == MP_OBJ_NEW_QSTR(MP_QSTR___delattr__)) { return true; @@ -980,7 +997,7 @@ STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { #endif #if MICROPY_PY_DESCRIPTORS static const uint8_t to_check[] = { - MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__, + MP_QSTR___get__, MP_QSTR___set__, MP_QSTR___delete__, // not needed for MP_QSTR___set_name__ though }; for (size_t i = 0; i < MP_ARRAY_SIZE(to_check); ++i) { mp_obj_t dest_temp[2]; @@ -994,13 +1011,55 @@ STATIC bool check_for_special_accessors(mp_obj_t key, mp_obj_t value) { } #endif -STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +#if MICROPY_PY_DESCRIPTORS +// Shared data layout for the __set_name__ call and a linked list of calls to be made. +typedef union _setname_list_t setname_list_t; +union _setname_list_t { + mp_obj_t call[4]; + struct { + mp_obj_t _meth; + mp_obj_t _self; + setname_list_t *next; // can use the "owner" argument position temporarily for the linked list + mp_obj_t _name; + }; +}; + +// Append any `__set_name__` method on `value` to the setname list, with its per-attr args +static setname_list_t *setname_maybe_bind_append(setname_list_t *tail, mp_obj_t name, mp_obj_t value) { + // make certain our type-punning is safe: + MP_STATIC_ASSERT_NONCONSTEXPR(offsetof(setname_list_t, next) == offsetof(setname_list_t, call[2])); + + // tail is a blank list entry + mp_load_method_maybe(value, MP_QSTR___set_name__, tail->call); + if (tail->call[1] != MP_OBJ_NULL) { + // Each time a __set_name__ is found, leave it in-place in the former tail and allocate a new tail + tail->next = m_new_obj(setname_list_t); + tail->next->next = NULL; + tail->call[3] = name; + return tail->next; + } else { + return tail; + } +} + +// Execute the captured `__set_name__` calls, destroying the setname list in the process. +static inline void setname_consume_call_all(setname_list_t *head, mp_obj_t owner) { + setname_list_t *next; + while ((next = head->next) != NULL) { + head->call[2] = owner; + mp_call_method_n_kw(2, 0, head->call); + head = next; + } +} +#endif + +static void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", self->name); + mp_printf(print, "", (qstr)self->name); } -STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; mp_arg_check_num(n_args, n_kw, 1, 3, false); @@ -1020,18 +1079,17 @@ STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ } } -STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { // instantiate an instance of a class mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); if (!MP_OBJ_TYPE_HAS_SLOT(self, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE - // CIRCUITPY-CHANGE: error message change - mp_raise_TypeError(MP_ERROR_TEXT("cannot create instance")); + mp_raise_TypeError(MP_ERROR_TEXT("can't create instance")); #else - // CIRCUITPY-CHANGE: error message change - mp_raise_TypeError_varg(MP_ERROR_TEXT("cannot create '%q' instances"), self->name); + // CIRCUITPY-CHANGE: more specific mp_raise + mp_raise_TypeError_varg(MP_ERROR_TEXT("can't create '%q' instances"), self->name); #endif } @@ -1042,7 +1100,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp return o; } -STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { assert(mp_obj_is_type(self_in, &mp_type_type)); mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in); @@ -1144,7 +1202,7 @@ MP_DEFINE_CONST_OBJ_TYPE( attr, type_attr ); -mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { +static mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) { // Verify input objects have expected type if (!mp_obj_is_type(bases_tuple, &mp_type_tuple)) { mp_raise_TypeError(NULL); @@ -1172,12 +1230,11 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO: Verify with CPy, tested on function type if (!MP_OBJ_TYPE_HAS_SLOT(t, make_new)) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE - // CIRCUITPY-CHANGE: error message change - mp_raise_TypeError(MP_ERROR_TEXT("type is not an acceptable base type")); + mp_raise_TypeError(MP_ERROR_TEXT("type isn't an acceptable base type")); #else - // CIRCUITPY-CHANGE: error message change + // CIRCUITPY-CHANGE: more specific mp_raise mp_raise_TypeError_varg( - MP_ERROR_TEXT("type '%q' is not an acceptable base type"), t->name); + MP_ERROR_TEXT("type '%q' isn't an acceptable base type"), t->name); #endif } #if ENABLE_SPECIAL_ACCESSORS @@ -1187,6 +1244,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) base_flags |= t->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; if (mp_obj_is_instance_type(t)) { t->flags |= MP_TYPE_FLAG_IS_SUBCLASSED; + base_flags |= t->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } #endif } @@ -1237,20 +1295,38 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } } + #if MICROPY_PY_DESCRIPTORS + // To avoid any dynamic allocations when no __set_name__ exists, + // the head of this list is kept on the stack (marked blank with `next = NULL`). + setname_list_t setname_list = { .next = NULL }; + setname_list_t *setname_tail = &setname_list; + #endif + #if ENABLE_SPECIAL_ACCESSORS - // Check if the class has any special accessor methods - if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS)) { - for (size_t i = 0; i < locals_ptr->map.alloc; i++) { - if (mp_map_slot_is_filled(&locals_ptr->map, i)) { - const mp_map_elem_t *elem = &locals_ptr->map.table[i]; - if (check_for_special_accessors(elem->key, elem->value)) { - o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; - break; - } + // Check if the class has any special accessor methods, + // and accumulate bound __set_name__ methods that need to be called + for (size_t i = 0; i < locals_ptr->map.alloc; i++) { + #if !MICROPY_PY_DESCRIPTORS + // __set_name__ needs to scan the entire locals map, can't early-terminate + if (o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS) { + break; + } + #endif + + if (mp_map_slot_is_filled(&locals_ptr->map, i)) { + const mp_map_elem_t *elem = &locals_ptr->map.table[i]; + + if (!(o->flags & MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS) // elidable when the early-termination check is enabled + && check_for_special_accessors(elem->key, elem->value)) { + o->flags |= MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS; } + + #if MICROPY_PY_DESCRIPTORS + setname_tail = setname_maybe_bind_append(setname_tail, elem->key, elem->value); + #endif } } - #endif + #endif // ENABLE_SPECIAL_ACCESSORS const mp_obj_type_t *native_base; size_t num_native_bases = instance_count_native_bases(o, &native_base); @@ -1258,8 +1334,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) mp_raise_TypeError(MP_ERROR_TEXT("multiple bases have instance lay-out conflict")); } - mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(o, locals_dict)->map; - mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); + mp_map_elem_t *elem = mp_map_lookup(&locals_ptr->map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP); if (elem != NULL) { // __new__ slot exists; check if it is a function if (mp_obj_is_fun(elem->value)) { @@ -1268,6 +1343,10 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) } } + #if MICROPY_PY_DESCRIPTORS + setname_consume_call_all(&setname_list, MP_OBJ_FROM_PTR(o)); + #endif + return MP_OBJ_FROM_PTR(o); } @@ -1280,7 +1359,7 @@ typedef struct _mp_obj_super_t { mp_obj_t obj; } mp_obj_super_t; -STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in); mp_print_str(print, ""); } -STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void)type_in; // 0 arguments are turned into 2 in the compiler // 1 argument is not yet implemented mp_arg_check_num(n_args, n_kw, 2, 2, false); + + // CIRCUITPY-CHANGE: check type of first arg if (!mp_obj_is_type(args[0], &mp_type_type)) { - // CIRCUITPY-CHANGE: error message mp_raise_TypeError(MP_ERROR_TEXT("first argument to super() must be type")); } + + // Per CPython: "If the second argument is an object, isinstance(obj, type) must be true. + // If the second argument is a type, issubclass(type2, type) must be true (this is useful for classmethods)." + const mp_obj_type_t *second_arg_type = mp_obj_get_type(args[1]); + mp_obj_t second_arg_obj = second_arg_type == &mp_type_type ? args[1] : MP_OBJ_FROM_PTR(second_arg_type); + if (mp_obj_is_subclass(second_arg_obj, args[0]) == mp_const_false) { + mp_raise_TypeError(NULL); + } + mp_obj_super_t *o = m_new_obj(mp_obj_super_t); *o = (mp_obj_super_t) {{type_in}, args[0], args[1]}; return MP_OBJ_FROM_PTR(o); } -STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; @@ -1457,7 +1546,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) { } } -STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { +static mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { size_t len; mp_obj_t *items; if (mp_obj_is_type(classinfo, &mp_type_type)) { @@ -1478,7 +1567,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { return mp_const_false; } -STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { +static mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { if (!mp_obj_is_type(object, &mp_type_type)) { mp_raise_TypeError(MP_ERROR_TEXT("issubclass() arg 1 must be a class")); } @@ -1487,7 +1576,7 @@ STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass); -STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { +static mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) { return mp_obj_is_subclass(MP_OBJ_FROM_PTR(mp_obj_get_type(object)), classinfo); } @@ -1509,13 +1598,15 @@ mp_obj_t mp_obj_cast_to_native_base(mp_obj_t self_in, mp_const_obj_t native_type /******************************************************************************/ // staticmethod and classmethod types (probably should go in a different file) -STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) { - assert(self == &mp_type_staticmethod || self == &mp_type_classmethod); +// CIRCUITPY-CHANGE: better arg name +static mp_obj_t static_class_method_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(type == &mp_type_staticmethod || type == &mp_type_classmethod); mp_arg_check_num(n_args, n_kw, 1, 1, false); - mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t); - *o = (mp_obj_static_class_method_t) {{self}, args[0]}; + // CIRCUITPY-CHANGE: Use mp_obj_malloc because it is a Python object + mp_obj_static_class_method_t *o = mp_obj_malloc(mp_obj_static_class_method_t, type); + o->fun = args[0]; return MP_OBJ_FROM_PTR(o); } diff --git a/py/objzip.c b/py/objzip.c index 3c3138180a28f..dd2b39ee07110 100644 --- a/py/objzip.c +++ b/py/objzip.c @@ -36,10 +36,10 @@ typedef struct _mp_obj_zip_t { mp_obj_t iters[]; } mp_obj_zip_t; -STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false); - mp_obj_zip_t *o = mp_obj_malloc_var(mp_obj_zip_t, mp_obj_t, n_args, type); + mp_obj_zip_t *o = mp_obj_malloc_var(mp_obj_zip_t, iters, mp_obj_t, n_args, type); o->n_iters = n_args; for (size_t i = 0; i < n_args; i++) { o->iters[i] = mp_getiter(args[i], NULL); @@ -47,7 +47,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_ return MP_OBJ_FROM_PTR(o); } -STATIC mp_obj_t zip_iternext(mp_obj_t self_in) { +static mp_obj_t zip_iternext(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &mp_type_zip)); mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in); if (self->n_iters == 0) { diff --git a/py/opmethods.c b/py/opmethods.c index 68a0ce8031273..841dd981544b4 100644 --- a/py/opmethods.c +++ b/py/opmethods.c @@ -31,28 +31,28 @@ // code the type to dict so that subclassed types still use the native dict // subscr. MP doesn't have this problem because it passes the native instance // in. CP passes the subclass instance. -STATIC mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { +static mp_obj_t op_getitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = &mp_type_dict; // Note: assumes type must have subscr (only used by dict). return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_SENTINEL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_getitem_obj, op_getitem); -STATIC mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { +static mp_obj_t op_setitem(mp_obj_t self_in, mp_obj_t key_in, mp_obj_t value_in) { const mp_obj_type_t *type = &mp_type_dict; // Note: assumes type must have subscr (only used by dict). return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, value_in); } MP_DEFINE_CONST_FUN_OBJ_3(mp_op_setitem_obj, op_setitem); -STATIC mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { +static mp_obj_t op_delitem(mp_obj_t self_in, mp_obj_t key_in) { const mp_obj_type_t *type = &mp_type_dict; // Note: assumes type must have subscr (only used by dict). return MP_OBJ_TYPE_GET_SLOT(type, subscr)(self_in, key_in, MP_OBJ_NULL); } MP_DEFINE_CONST_FUN_OBJ_2(mp_op_delitem_obj, op_delitem); -STATIC mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { +static mp_obj_t op_contains(mp_obj_t lhs_in, mp_obj_t rhs_in) { const mp_obj_type_t *type = mp_obj_get_type(lhs_in); // Note: assumes type must have binary_op (only used by set/frozenset). return MP_OBJ_TYPE_GET_SLOT(type, binary_op)(MP_BINARY_OP_CONTAINS, lhs_in, rhs_in); diff --git a/py/parse.c b/py/parse.c index fae55d0e42ac1..36150ef468bdf 100644 --- a/py/parse.c +++ b/py/parse.c @@ -75,7 +75,7 @@ enum { }; // Define an array of actions corresponding to each rule -STATIC const uint8_t rule_act_table[] = { +static const uint8_t rule_act_table[] = { #define or(n) (RULE_ACT_OR | n) #define and(n) (RULE_ACT_AND | n) #define and_ident(n) (RULE_ACT_AND | n | RULE_ACT_ALLOW_IDENT) @@ -108,7 +108,7 @@ STATIC const uint8_t rule_act_table[] = { }; // Define the argument data for each rule, as a combined array -STATIC const uint16_t rule_arg_combined_table[] = { +static const uint16_t rule_arg_combined_table[] = { #define tok(t) (RULE_ARG_TOK | MP_TOKEN_##t) #define rule(r) (RULE_ARG_RULE | RULE_##r) #define opt_rule(r) (RULE_ARG_OPT_RULE | RULE_##r) @@ -161,7 +161,7 @@ enum { // data, which indexes rule_arg_combined_table. The offsets require 9 bits of // storage but only the lower 8 bits are stored here. The 9th bit is computed // in get_rule_arg using the FIRST_RULE_WITH_OFFSET_ABOVE_255 constant. -STATIC const uint8_t rule_arg_offset_table[] = { +static const uint8_t rule_arg_offset_table[] = { #define DEF_RULE(rule, comp, kind, ...) RULE_ARG_OFFSET(rule, __VA_ARGS__) & 0xff, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" @@ -191,7 +191,7 @@ static const size_t FIRST_RULE_WITH_OFFSET_ABOVE_255 = #if MICROPY_DEBUG_PARSE_RULE_NAME // Define an array of rule names corresponding to each rule -STATIC const char *const rule_name_table[] = { +static const char *const rule_name_table[] = { #define DEF_RULE(rule, comp, kind, ...) #rule, #define DEF_RULE_NC(rule, kind, ...) #include "py/grammar.h" @@ -242,9 +242,9 @@ typedef struct _parser_t { #endif } parser_t; -STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args); +static void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args); -STATIC const uint16_t *get_rule_arg(uint8_t r_id) { +static const uint16_t *get_rule_arg(uint8_t r_id) { size_t off = rule_arg_offset_table[r_id]; if (r_id >= FIRST_RULE_WITH_OFFSET_ABOVE_255) { off |= 0x100; @@ -256,7 +256,7 @@ STATIC const uint16_t *get_rule_arg(uint8_t r_id) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" -STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { +static void *parser_alloc(parser_t *parser, size_t num_bytes) { // use a custom memory allocator to store parse nodes sequentially in large chunks mp_parse_chunk_t *chunk = parser->cur_chunk; @@ -299,7 +299,7 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { #pragma GCC diagnostic pop #if MICROPY_COMP_CONST_TUPLE -STATIC void parser_free_parse_node_struct(parser_t *parser, mp_parse_node_struct_t *pns) { +static void parser_free_parse_node_struct(parser_t *parser, mp_parse_node_struct_t *pns) { mp_parse_chunk_t *chunk = parser->cur_chunk; if (chunk->data <= (byte *)pns && (byte *)pns < chunk->data + chunk->union_.used) { size_t num_bytes = sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * MP_PARSE_NODE_STRUCT_NUM_NODES(pns); @@ -308,7 +308,7 @@ STATIC void parser_free_parse_node_struct(parser_t *parser, mp_parse_node_struct } #endif -STATIC void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t arg_i) { +static void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t arg_i) { if (parser->rule_stack_top >= parser->rule_stack_alloc) { rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC); parser->rule_stack = rs; @@ -320,13 +320,13 @@ STATIC void push_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t rs->arg_i = arg_i; } -STATIC void push_rule_from_arg(parser_t *parser, size_t arg) { +static void push_rule_from_arg(parser_t *parser, size_t arg) { assert((arg & RULE_ARG_KIND_MASK) == RULE_ARG_RULE || (arg & RULE_ARG_KIND_MASK) == RULE_ARG_OPT_RULE); size_t rule_id = arg & RULE_ARG_ARG_MASK; push_rule(parser, parser->lexer->tok_line, rule_id, 0); } -STATIC uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) { +static uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) { parser->rule_stack_top -= 1; uint8_t rule_id = parser->rule_stack[parser->rule_stack_top].rule_id; *arg_i = parser->rule_stack[parser->rule_stack_top].arg_i; @@ -335,27 +335,43 @@ STATIC uint8_t pop_rule(parser_t *parser, size_t *arg_i, size_t *src_line) { } #if MICROPY_COMP_CONST_TUPLE -STATIC uint8_t peek_rule(parser_t *parser, size_t n) { +static uint8_t peek_rule(parser_t *parser, size_t n) { assert(parser->rule_stack_top > n); return parser->rule_stack[parser->rule_stack_top - 1 - n].rule_id; } #endif -bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { +#if MICROPY_COMP_CONST_FOLDING || MICROPY_EMIT_INLINE_ASM +static bool mp_parse_node_get_number_maybe(mp_parse_node_t pn, mp_obj_t *o) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { *o = MP_OBJ_NEW_SMALL_INT(MP_PARSE_NODE_LEAF_SMALL_INT(pn)); return true; } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, RULE_const_object)) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn; *o = mp_parse_node_extract_const_object(pns); - return mp_obj_is_int(*o); + return mp_obj_is_int(*o) + #if MICROPY_COMP_CONST_FLOAT + || mp_obj_is_float(*o) + #endif + ; } else { return false; } } +#endif + +#if MICROPY_EMIT_INLINE_ASM +bool mp_parse_node_get_int_maybe(mp_parse_node_t pn, mp_obj_t *o) { + return mp_parse_node_get_number_maybe(pn, o) + #if MICROPY_COMP_CONST_FLOAT + && mp_obj_is_int(*o) + #endif + ; +} +#endif #if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST -STATIC bool mp_parse_node_is_const(mp_parse_node_t pn) { +static bool mp_parse_node_is_const(mp_parse_node_t pn) { if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { // Small integer. return true; @@ -382,7 +398,7 @@ STATIC bool mp_parse_node_is_const(mp_parse_node_t pn) { return false; } -STATIC mp_obj_t mp_parse_node_convert_to_obj(mp_parse_node_t pn) { +static mp_obj_t mp_parse_node_convert_to_obj(mp_parse_node_t pn) { assert(mp_parse_node_is_const(pn)); if (MP_PARSE_NODE_IS_SMALL_INT(pn)) { mp_int_t arg = MP_PARSE_NODE_LEAF_SMALL_INT(pn); @@ -424,7 +440,7 @@ STATIC mp_obj_t mp_parse_node_convert_to_obj(mp_parse_node_t pn) { } #endif -STATIC bool parse_node_is_const_bool(mp_parse_node_t pn, bool value) { +static bool parse_node_is_const_bool(mp_parse_node_t pn, bool value) { // Returns true if 'pn' is a constant whose boolean value is equivalent to 'value' #if MICROPY_COMP_CONST_TUPLE || MICROPY_COMP_CONST return mp_parse_node_is_const(pn) && mp_obj_is_true(mp_parse_node_convert_to_obj(pn)) == value; @@ -518,7 +534,7 @@ void mp_parse_node_print(const mp_print_t *print, mp_parse_node_t pn, size_t ind #endif // MICROPY_DEBUG_PRINTERS /* -STATIC void result_stack_show(const mp_print_t *print, parser_t *parser) { +static void result_stack_show(const mp_print_t *print, parser_t *parser) { mp_printf(print, "result stack, most recent first\n"); for (ssize_t i = parser->result_stack_top - 1; i >= 0; i--) { mp_parse_node_print(print, parser->result_stack[i], 0); @@ -526,17 +542,17 @@ STATIC void result_stack_show(const mp_print_t *print, parser_t *parser) { } */ -STATIC mp_parse_node_t pop_result(parser_t *parser) { +static mp_parse_node_t pop_result(parser_t *parser) { assert(parser->result_stack_top > 0); return parser->result_stack[--parser->result_stack_top]; } -STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) { +static mp_parse_node_t peek_result(parser_t *parser, size_t pos) { assert(parser->result_stack_top > pos); return parser->result_stack[parser->result_stack_top - 1 - pos]; } -STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) { +static void push_result_node(parser_t *parser, mp_parse_node_t pn) { if (parser->result_stack_top >= parser->result_stack_alloc) { mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC); parser->result_stack = stack; @@ -545,7 +561,7 @@ STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) { parser->result_stack[parser->result_stack_top++] = pn; } -STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) { +static mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) { mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t)); pn->source_line = src_line; #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D @@ -562,7 +578,7 @@ STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, // Create a parse node representing a constant object, possibly optimising the case of // an integer, by putting the (small) integer value directly in the parse node itself. -STATIC mp_parse_node_t make_node_const_object_optimised(parser_t *parser, size_t src_line, mp_obj_t obj) { +static mp_parse_node_t make_node_const_object_optimised(parser_t *parser, size_t src_line, mp_obj_t obj) { if (mp_obj_is_small_int(obj)) { mp_int_t val = MP_OBJ_SMALL_INT_VALUE(obj); #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D @@ -584,7 +600,7 @@ STATIC mp_parse_node_t make_node_const_object_optimised(parser_t *parser, size_t } } -STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { +static void push_result_token(parser_t *parser, uint8_t rule_id) { mp_parse_node_t pn; mp_lexer_t *lex = parser->lexer; if (lex->tok_kind == MP_TOKEN_NAME) { @@ -640,26 +656,40 @@ STATIC void push_result_token(parser_t *parser, uint8_t rule_id) { #if MICROPY_COMP_CONST_FOLDING #if MICROPY_COMP_MODULE_CONST -STATIC const mp_rom_map_elem_t mp_constants_table[] = { +static const mp_rom_map_elem_t mp_constants_table[] = { #if MICROPY_PY_ERRNO { MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_module_errno) }, #endif #if MICROPY_PY_UCTYPES { MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) }, #endif + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_PY_MATH && MICROPY_COMP_CONST_FLOAT + { MP_ROM_QSTR(MP_QSTR_math), MP_ROM_PTR(&mp_module_math) }, + #endif // Extra constants as defined by a port MICROPY_PORT_CONSTANTS }; -STATIC MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table); +static MP_DEFINE_CONST_MAP(mp_constants_map, mp_constants_table); #endif -// CIRCUITPY-CHANGE: avoid compiler warning -#if defined(MICROPY_COMP_CONST_FOLDING_COMPILER_WORKAROUND) && MICROPY_COMP_CONST_FOLDING_COMPILER_WORKAROUND -// Some versions of the xtensa-esp32-elf-gcc compiler generate wrong code if this -// function is static, so provide a hook for them to work around this problem. -MP_NOINLINE -#endif -STATIC bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) { +static bool binary_op_maybe(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs, mp_obj_t *res) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t tmp = mp_binary_op(op, lhs, rhs); + nlr_pop(); + #if MICROPY_PY_BUILTINS_COMPLEX + if (mp_obj_is_type(tmp, &mp_type_complex)) { + return false; + } + #endif + *res = tmp; + return true; + } else { + return false; + } +} + +static bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *num_args) { if (rule_id == RULE_or_test || rule_id == RULE_and_test) { // folding for binary logical ops: or and @@ -716,8 +746,8 @@ STATIC bool fold_logical_constants(parser_t *parser, uint8_t rule_id, size_t *nu return false; } -STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { - // this code does folding of arbitrary integer expressions, eg 1 + 2 * 3 + 4 +static bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { + // this code does folding of arbitrary numeric expressions, eg 1 + 2 * 3 + 4 // it does not do partial folding, eg 1 + 2 + x -> 3 + x mp_obj_t arg0; @@ -727,7 +757,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { || rule_id == RULE_power) { // folding for binary ops: | ^ & ** mp_parse_node_t pn = peek_result(parser, num_args - 1); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } mp_binary_op_t op; @@ -743,58 +773,45 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { for (ssize_t i = num_args - 2; i >= 0; --i) { pn = peek_result(parser, i); mp_obj_t arg1; - if (!mp_parse_node_get_int_maybe(pn, &arg1)) { + if (!mp_parse_node_get_number_maybe(pn, &arg1)) { return false; } - if (op == MP_BINARY_OP_POWER && mp_obj_int_sign(arg1) < 0) { - // ** can't have negative rhs + if (!binary_op_maybe(op, arg0, arg1, &arg0)) { return false; } - arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_shift_expr || rule_id == RULE_arith_expr || rule_id == RULE_term) { // folding for binary ops: << >> + - * @ / % // mp_parse_node_t pn = peek_result(parser, num_args - 1); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } for (ssize_t i = num_args - 2; i >= 1; i -= 2) { pn = peek_result(parser, i - 1); mp_obj_t arg1; - if (!mp_parse_node_get_int_maybe(pn, &arg1)) { + if (!mp_parse_node_get_number_maybe(pn, &arg1)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, i)); - if (tok == MP_TOKEN_OP_AT || tok == MP_TOKEN_OP_SLASH) { - // Can't fold @ or / - return false; - } mp_binary_op_t op = MP_BINARY_OP_LSHIFT + (tok - MP_TOKEN_OP_DBL_LESS); - int rhs_sign = mp_obj_int_sign(arg1); - if (op <= MP_BINARY_OP_RSHIFT) { - // << and >> can't have negative rhs - if (rhs_sign < 0) { - return false; - } - } else if (op >= MP_BINARY_OP_FLOOR_DIVIDE) { - // % and // can't have zero rhs - if (rhs_sign == 0) { - return false; - } + if (!binary_op_maybe(op, arg0, arg1, &arg0)) { + return false; } - arg0 = mp_binary_op(op, arg0, arg1); } } else if (rule_id == RULE_factor_2) { // folding for unary ops: + - ~ mp_parse_node_t pn = peek_result(parser, 0); - if (!mp_parse_node_get_int_maybe(pn, &arg0)) { + if (!mp_parse_node_get_number_maybe(pn, &arg0)) { return false; } mp_token_kind_t tok = MP_PARSE_NODE_LEAF_ARG(peek_result(parser, 1)); mp_unary_op_t op; if (tok == MP_TOKEN_OP_TILDE) { + if (!mp_obj_is_int(arg0)) { + return false; + } op = MP_UNARY_OP_INVERT; } else { assert(tok == MP_TOKEN_OP_PLUS || tok == MP_TOKEN_OP_MINUS); // should be @@ -866,7 +883,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { return false; } // id1.id2 - // look it up in constant table, see if it can be replaced with an integer + // look it up in constant table, see if it can be replaced with an integer or a float mp_parse_node_struct_t *pns1 = (mp_parse_node_struct_t *)pn1; assert(MP_PARSE_NODE_IS_ID(pns1->nodes[0])); qstr q_base = MP_PARSE_NODE_LEAF_ARG(pn0); @@ -877,7 +894,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { } mp_obj_t dest[2]; mp_load_method_maybe(elem->value, q_attr, dest); - if (!(dest[0] != MP_OBJ_NULL && mp_obj_is_int(dest[0]) && dest[1] == MP_OBJ_NULL)) { + if (!(dest[0] != MP_OBJ_NULL && (mp_obj_is_int(dest[0]) || mp_obj_is_float(dest[0])) && dest[1] == MP_OBJ_NULL)) { return false; } arg0 = dest[0]; @@ -900,7 +917,7 @@ STATIC bool fold_constants(parser_t *parser, uint8_t rule_id, size_t num_args) { #endif // MICROPY_COMP_CONST_FOLDING #if MICROPY_COMP_CONST_TUPLE -STATIC bool build_tuple_from_stack(parser_t *parser, size_t src_line, size_t num_args) { +static bool build_tuple_from_stack(parser_t *parser, size_t src_line, size_t num_args) { for (size_t i = num_args; i > 0;) { mp_parse_node_t pn = peek_result(parser, --i); if (!mp_parse_node_is_const(pn)) { @@ -919,7 +936,7 @@ STATIC bool build_tuple_from_stack(parser_t *parser, size_t src_line, size_t num return true; } -STATIC bool build_tuple(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { +static bool build_tuple(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { if (rule_id == RULE_testlist_comp) { if (peek_rule(parser, 0) == RULE_atom_paren) { // Tuple of the form "(a,)". @@ -952,7 +969,7 @@ STATIC bool build_tuple(parser_t *parser, size_t src_line, uint8_t rule_id, size } #endif -STATIC void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { +static void push_result_rule(parser_t *parser, size_t src_line, uint8_t rule_id, size_t num_args) { // Simplify and optimise certain rules, to reduce memory usage and simplify the compiler. if (rule_id == RULE_atom_paren) { // Remove parenthesis around a single expression if possible. @@ -1378,9 +1395,6 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) { } else if (lex->tok_kind == MP_TOKEN_MALFORMED_FSTRING) { exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, MP_ERROR_TEXT("malformed f-string")); - } else if (lex->tok_kind == MP_TOKEN_FSTRING_RAW) { - exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, - MP_ERROR_TEXT("raw f-strings are not supported")); #endif } else { exc = mp_obj_new_exception_msg(&mp_type_SyntaxError, @@ -1413,6 +1427,7 @@ void mp_parse_tree_clear(mp_parse_tree_t *tree) { m_del(byte, chunk, sizeof(mp_parse_chunk_t) + chunk->alloc); chunk = next; } + tree->chunk = NULL; // Avoid dangling pointer that may live on stack } #endif // MICROPY_ENABLE_COMPILER diff --git a/py/parsenum.c b/py/parsenum.c index 68f7417c0bd63..c52f040e1a210 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -28,6 +28,7 @@ #include #include "py/runtime.h" +#include "py/misc.h" #include "py/parsenumbase.h" #include "py/parsenum.h" #include "py/smallint.h" @@ -36,7 +37,7 @@ #include #endif -STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { +static MP_NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { // if lex!=NULL then the parser called us and we need to convert the // exception's type from ValueError to SyntaxError and add traceback info if (lex != NULL) { @@ -46,6 +47,27 @@ STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) { nlr_raise(exc); } +#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG +// For the common small integer parsing case, we parse directly to mp_int_t and +// check that the value doesn't overflow a smallint (in which case we fail over +// to bigint parsing if supported) +typedef mp_int_t parsed_int_t; + +#define PARSED_INT_MUL_OVERFLOW mp_mul_mp_int_t_overflow +#define PARSED_INT_FITS MP_SMALL_INT_FITS +#else +// In the special case where bigint support is long long, we save code size by +// parsing directly to long long and then return either a bigint or smallint +// from the same result. +// +// To avoid pulling in (slow) signed 64-bit math routines we do the initial +// parsing to an unsigned long long and only convert to signed at the end. +typedef unsigned long long parsed_int_t; + +#define PARSED_INT_MUL_OVERFLOW mp_mul_ull_overflow +#define PARSED_INT_FITS(I) ((I) <= (unsigned long long)LLONG_MAX + 1) +#endif + mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, mp_lexer_t *lex) { const byte *restrict str = (const byte *)str_; const byte *restrict top = str + len; @@ -77,7 +99,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m str += mp_parse_num_base((const char *)str, top - str, &base); // string should be an integer number - mp_int_t int_val = 0; + parsed_int_t parsed_val = 0; const byte *restrict str_val_start = str; for (; str < top; str++) { // get next digit as a value @@ -99,25 +121,32 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m break; } - // add next digi and check for overflow - if (mp_small_int_mul_overflow(int_val, base)) { + // add next digit and check for overflow + if (PARSED_INT_MUL_OVERFLOW(parsed_val, base, &parsed_val)) { goto overflow; } - int_val = int_val * base + dig; - if (!MP_SMALL_INT_FITS(int_val)) { + parsed_val += dig; + if (!PARSED_INT_FITS(parsed_val)) { goto overflow; } } - // negate value if needed - if (neg) { - int_val = -int_val; + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG + // The PARSED_INT_FITS check above ensures parsed_val fits in small int representation + ret_val = MP_OBJ_NEW_SMALL_INT(neg ? (-parsed_val) : parsed_val); +have_ret_val: + #else + // The PARSED_INT_FITS check above ensures parsed_val won't overflow signed long long + long long signed_val = -parsed_val; + if (!neg) { + if (signed_val == LLONG_MIN) { + goto overflow; + } + signed_val = -signed_val; } + ret_val = mp_obj_new_int_from_ll(signed_val); // Could be large or small int + #endif - // create the small int - ret_val = MP_OBJ_NEW_SMALL_INT(int_val); - -have_ret_val: // check we parsed something if (str == str_val_start) { goto value_error; @@ -136,6 +165,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m return ret_val; overflow: + #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_LONGLONG // reparse using long int { const char *s2 = (const char *)str_val_start; @@ -143,6 +173,9 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m str = (const byte *)s2; goto have_ret_val; } + #else + mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("result overflows long long storage")); + #endif value_error: { @@ -152,13 +185,13 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m raise_exc(exc, lex); #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL mp_obj_t exc = mp_obj_new_exception_msg_varg(&mp_type_ValueError, - MP_ERROR_TEXT("invalid syntax for integer with base %d"), base); + MP_ERROR_TEXT("invalid syntax for integer with base %d"), base == 1 ? 0 : base); raise_exc(exc, lex); #else vstr_t vstr; mp_print_t print; vstr_init_print(&vstr, 50, &print); - mp_printf(&print, "invalid syntax for integer with base %d: ", base); + mp_printf(&print, "invalid syntax for integer with base %d: ", base == 1 ? 0 : base); mp_str_print_quoted(&print, str_val_start, top - str_val_start, true); mp_obj_t exc = mp_obj_new_exception_arg1(&mp_type_ValueError, mp_obj_new_str_from_utf8_vstr(&vstr)); @@ -167,6 +200,8 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m } } +#if MICROPY_PY_BUILTINS_FLOAT + enum { REAL_IMAG_STATE_START = 0, REAL_IMAG_STATE_HAVE_REAL = 1, @@ -179,41 +214,175 @@ typedef enum { PARSE_DEC_IN_EXP, } parse_dec_in_t; -#if MICROPY_PY_BUILTINS_FLOAT -// DEC_VAL_MAX only needs to be rough and is used to retain precision while not overflowing -// SMALL_NORMAL_VAL is the smallest power of 10 that is still a normal float -// EXACT_POWER_OF_10 is the largest value of x so that 10^x can be stored exactly in a float -// Note: EXACT_POWER_OF_10 is at least floor(log_5(2^mantissa_length)). Indeed, 10^n = 2^n * 5^n -// so we only have to store the 5^n part in the mantissa (the 2^n part will go into the float's -// exponent). +// MANTISSA_MAX is used to retain precision while not overflowing mantissa +#define MANTISSA_MAX (sizeof(mp_large_float_uint_t) == 8 ? 0x1999999999999998ULL : 0x19999998U) + +// MAX_EXACT_POWER_OF_5 is the largest value of x so that 5^x can be stored exactly in a float #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT -#define DEC_VAL_MAX 1e20F -#define SMALL_NORMAL_VAL (1e-37F) -#define SMALL_NORMAL_EXP (-37) -#define EXACT_POWER_OF_10 (9) +#define MAX_EXACT_POWER_OF_5 (10) #elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE -#define DEC_VAL_MAX 1e200 -#define SMALL_NORMAL_VAL (1e-307) -#define SMALL_NORMAL_EXP (-307) -#define EXACT_POWER_OF_10 (22) +#define MAX_EXACT_POWER_OF_5 (22) #endif +// Helper to compute `num * (10.0 ** dec_exp)` +mp_large_float_t mp_decimal_exp(mp_large_float_t num, int dec_exp) { + // CIRCUITPY-CHANGE: ignore float equal warning + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + if (dec_exp == 0 || num == (mp_large_float_t)(0.0)) { + return num; + } + #pragma GCC diagnostic pop + + #if MICROPY_FLOAT_FORMAT_IMPL == MICROPY_FLOAT_FORMAT_IMPL_EXACT + + // If the assert below fails, it means you have chosen MICROPY_FLOAT_FORMAT_IMPL_EXACT + // manually on a platform where `larger floats` are not supported, which would + // result in inexact conversions. To fix this issue, change your `mpconfigport.h` + // and select MICROPY_FLOAT_FORMAT_IMPL_APPROX instead + assert(sizeof(mp_large_float_t) > sizeof(mp_float_t)); + + // Perform power using simple multiplications, to avoid + // dependency to higher-precision pow() function + int neg_exp = (dec_exp < 0); + if (neg_exp) { + dec_exp = -dec_exp; + } + mp_large_float_t res = num; + mp_large_float_t expo = (mp_large_float_t)10.0; + while (dec_exp) { + if (dec_exp & 1) { + if (neg_exp) { + res /= expo; + } else { + res *= expo; + } + } + dec_exp >>= 1; + if (dec_exp) { + expo *= expo; + } + } + return res; + + #else + // MICROPY_FLOAT_FORMAT_IMPL != MICROPY_FLOAT_FORMAT_IMPL_EXACT + + mp_float_union_t res = {num}; + // Multiply first by (2.0 ** dec_exp) via the exponent + // - this will ensure that the result of `pow()` is always in mp_float_t range + // when the result is expected to be in mp_float_t range (e.g. during format) + // - we don't need to care about p.exp overflow, as (5.0 ** dec_exp) will anyway + // force the final result toward the proper edge if needed (0.0 or inf) + res.p.exp += dec_exp; + // Use positive exponents when they are more precise then negative + if (dec_exp < 0 && dec_exp >= -MAX_EXACT_POWER_OF_5) { + res.f /= MICROPY_FLOAT_C_FUN(pow)(5, -dec_exp); + } else { + res.f *= MICROPY_FLOAT_C_FUN(pow)(5, dec_exp); + } + return (mp_large_float_t)res.f; + + #endif +} + + // Break out inner digit accumulation routine to ease trailing zero deferral. -static void accept_digit(mp_float_t *p_dec_val, int dig, int *p_exp_extra, int in) { +static mp_large_float_uint_t accept_digit(mp_large_float_uint_t p_mantissa, unsigned int dig, int *p_exp_extra, int in) { // Core routine to ingest an additional digit. - if (*p_dec_val < DEC_VAL_MAX) { + if (p_mantissa < MANTISSA_MAX) { // dec_val won't overflow so keep accumulating - *p_dec_val = 10 * *p_dec_val + dig; if (in == PARSE_DEC_IN_FRAC) { --(*p_exp_extra); } + return 10u * p_mantissa + dig; } else { // dec_val might overflow and we anyway can't represent more digits // of precision, so ignore the digit and just adjust the exponent if (in == PARSE_DEC_IN_INTG) { ++(*p_exp_extra); } + return p_mantissa; + } +} + +// Helper to parse an unsigned decimal number into a mp_float_t +const char *mp_parse_float_internal(const char *str, size_t len, mp_float_t *res) { + const char *top = str + len; + + parse_dec_in_t in = PARSE_DEC_IN_INTG; + bool exp_neg = false; + mp_large_float_uint_t mantissa = 0; + int exp_val = 0; + int exp_extra = 0; + int trailing_zeros_intg = 0, trailing_zeros_frac = 0; + while (str < top) { + unsigned int dig = *str++; + if ('0' <= dig && dig <= '9') { + dig -= '0'; + if (in == PARSE_DEC_IN_EXP) { + // don't overflow exp_val when adding next digit, instead just truncate + // it and the resulting float will still be correct, either inf or 0.0 + // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) + if (exp_val < (INT_MAX / 2 - 9) / 10) { + exp_val = 10 * exp_val + dig; + } + } else { + if (dig == 0 || mantissa >= MANTISSA_MAX) { + // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. + // Also, once we reach MANTISSA_MAX, treat every additional digit as a trailing zero. + if (in == PARSE_DEC_IN_INTG) { + ++trailing_zeros_intg; + } else { + ++trailing_zeros_frac; + } + } else { + // Time to un-defer any trailing zeros. Intg zeros first. + while (trailing_zeros_intg) { + mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_INTG); + --trailing_zeros_intg; + } + while (trailing_zeros_frac) { + mantissa = accept_digit(mantissa, 0, &exp_extra, PARSE_DEC_IN_FRAC); + --trailing_zeros_frac; + } + mantissa = accept_digit(mantissa, dig, &exp_extra, in); + } + } + } else if (in == PARSE_DEC_IN_INTG && dig == '.') { + in = PARSE_DEC_IN_FRAC; + } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { + in = PARSE_DEC_IN_EXP; + if (str < top) { + if (str[0] == '+') { + str++; + } else if (str[0] == '-') { + str++; + exp_neg = true; + } + } + if (str == top) { + return NULL; + } + } else if (dig == '_') { + continue; + } else { + // unknown character + str--; + break; + } } + + // work out the exponent + if (exp_neg) { + exp_val = -exp_val; + } + exp_val += exp_extra + trailing_zeros_intg; + + // At this point, we just need to multiply the mantissa by its base 10 exponent. + *res = (mp_float_t)mp_decimal_exp(mantissa, exp_val); + + return str; } #endif // MICROPY_PY_BUILTINS_FLOAT @@ -227,13 +396,13 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex const char *top = str + len; mp_float_t dec_val = 0; - bool dec_neg = false; #if MICROPY_PY_BUILTINS_COMPLEX unsigned int real_imag_state = REAL_IMAG_STATE_START; mp_float_t dec_real = 0; -parse_start: +parse_start:; #endif + bool dec_neg = false; // skip leading space for (; str < top && unichar_isspace(*str); str++) { @@ -252,109 +421,23 @@ mp_obj_t mp_parse_num_float(const char *str, size_t len, bool allow_imag, mp_lex const char *str_val_start = str; // determine what the string is - if (str < top && (str[0] | 0x20) == 'i') { - // string starts with 'i', should be 'inf' or 'infinity' (case insensitive) - if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { - // inf - str += 3; - dec_val = (mp_float_t)INFINITY; - if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { - // infinity - str += 5; - } - } - } else if (str < top && (str[0] | 0x20) == 'n') { - // string starts with 'n', should be 'nan' (case insensitive) - if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { - // NaN - str += 3; - dec_val = MICROPY_FLOAT_C_FUN(nan)(""); + if (str + 2 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { + // 'inf' or 'infinity' (case insensitive) + str += 3; + dec_val = (mp_float_t)INFINITY; + if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { + // infinity + str += 5; } + } else if (str + 2 < top && (str[0] | 0x20) == 'n' && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { + // 'nan' (case insensitive) + str += 3; + dec_val = MICROPY_FLOAT_C_FUN(nan)(""); } else { // string should be a decimal number - parse_dec_in_t in = PARSE_DEC_IN_INTG; - bool exp_neg = false; - int exp_val = 0; - int exp_extra = 0; - int trailing_zeros_intg = 0, trailing_zeros_frac = 0; - while (str < top) { - unsigned int dig = *str++; - if ('0' <= dig && dig <= '9') { - dig -= '0'; - if (in == PARSE_DEC_IN_EXP) { - // don't overflow exp_val when adding next digit, instead just truncate - // it and the resulting float will still be correct, either inf or 0.0 - // (use INT_MAX/2 to allow adding exp_extra at the end without overflow) - if (exp_val < (INT_MAX / 2 - 9) / 10) { - exp_val = 10 * exp_val + dig; - } - } else { - if (dig == 0 || dec_val >= DEC_VAL_MAX) { - // Defer treatment of zeros in fractional part. If nothing comes afterwards, ignore them. - // Also, once we reach DEC_VAL_MAX, treat every additional digit as a trailing zero. - if (in == PARSE_DEC_IN_INTG) { - ++trailing_zeros_intg; - } else { - ++trailing_zeros_frac; - } - } else { - // Time to un-defer any trailing zeros. Intg zeros first. - while (trailing_zeros_intg) { - accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_INTG); - --trailing_zeros_intg; - } - while (trailing_zeros_frac) { - accept_digit(&dec_val, 0, &exp_extra, PARSE_DEC_IN_FRAC); - --trailing_zeros_frac; - } - accept_digit(&dec_val, dig, &exp_extra, in); - } - } - } else if (in == PARSE_DEC_IN_INTG && dig == '.') { - in = PARSE_DEC_IN_FRAC; - } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { - in = PARSE_DEC_IN_EXP; - if (str < top) { - if (str[0] == '+') { - str++; - } else if (str[0] == '-') { - str++; - exp_neg = true; - } - } - if (str == top) { - goto value_error; - } - } else if (dig == '_') { - continue; - } else { - // unknown character - str--; - break; - } - } - - // work out the exponent - if (exp_neg) { - exp_val = -exp_val; - } - - // apply the exponent, making sure it's not a subnormal value - exp_val += exp_extra + trailing_zeros_intg; - if (exp_val < SMALL_NORMAL_EXP) { - exp_val -= SMALL_NORMAL_EXP; - dec_val *= SMALL_NORMAL_VAL; - } - - // At this point, we need to multiply the mantissa by its base 10 exponent. If possible, - // we would rather manipulate numbers that have an exact representation in IEEE754. It - // turns out small positive powers of 10 do, whereas small negative powers of 10 don't. - // So in that case, we'll yield a division of exact values rather than a multiplication - // of slightly erroneous values. - if (exp_val < 0 && exp_val >= -EXACT_POWER_OF_10) { - dec_val /= MICROPY_FLOAT_C_FUN(pow)(10, -exp_val); - } else { - dec_val *= MICROPY_FLOAT_C_FUN(pow)(10, exp_val); + str = mp_parse_float_internal(str, top - str, &dec_val); + if (!str) { + goto value_error; } } diff --git a/py/parsenum.h b/py/parsenum.h index f444632d23021..d532cb194a5d8 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -34,6 +34,11 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, size_t len, int base, mp_lexer_t *lex); +#if MICROPY_PY_BUILTINS_FLOAT +mp_large_float_t mp_decimal_exp(mp_large_float_t num, int dec_exp); +const char *mp_parse_float_internal(const char *str, size_t len, mp_float_t *res); +#endif + #if MICROPY_PY_BUILTINS_COMPLEX mp_obj_t mp_parse_num_decimal(const char *str, size_t len, bool allow_imag, bool force_complex, mp_lexer_t *lex); diff --git a/py/parsenumbase.c b/py/parsenumbase.c index 94523a666d325..fbf07a119584f 100644 --- a/py/parsenumbase.c +++ b/py/parsenumbase.c @@ -30,35 +30,28 @@ // find real radix base, and strip preceding '0x', '0o' and '0b' // puts base in *base, and returns number of bytes to skip the prefix +// in base-0, puts 1 in *base to indicate a number that starts with 0, to provoke a +// ValueError if it's not all-digits-zero. size_t mp_parse_num_base(const char *str, size_t len, int *base) { const byte *p = (const byte *)str; if (len <= 1) { goto no_prefix; } unichar c = *(p++); - if ((*base == 0 || *base == 16) && c == '0') { - c = *(p++); - if ((c | 32) == 'x') { + if (c == '0') { + c = *(p++) | 32; + int b = *base; + if (c == 'x' && (b == 0 || b == 16)) { *base = 16; - } else if (*base == 0 && (c | 32) == 'o') { + } else if (c == 'o' && (b == 0 || b == 8)) { *base = 8; - } else if (*base == 0 && (c | 32) == 'b') { + } else if (c == 'b' && (b == 0 || b == 2)) { *base = 2; } else { - if (*base == 0) { - *base = 10; - } - p -= 2; - } - } else if (*base == 8 && c == '0') { - c = *(p++); - if ((c | 32) != 'o') { - p -= 2; - } - } else if (*base == 2 && c == '0') { - c = *(p++); - if ((c | 32) != 'b') { p -= 2; + if (b == 0) { + *base = 1; + } } } else { p--; diff --git a/py/persistentcode.c b/py/persistentcode.c index 9c78c93b23bb4..5c3de3174bcd0 100644 --- a/py/persistentcode.c +++ b/py/persistentcode.c @@ -63,17 +63,35 @@ typedef struct _bytecode_prelude_t { uint code_info_size; } bytecode_prelude_t; +#if MICROPY_EMIT_RV32 +#include "py/asmrv32.h" +#endif + #endif // MICROPY_PERSISTENT_CODE_LOAD || MICROPY_PERSISTENT_CODE_SAVE #if MICROPY_PERSISTENT_CODE_LOAD #include "py/parsenum.h" -STATIC int read_byte(mp_reader_t *reader); -STATIC size_t read_uint(mp_reader_t *reader); +static int read_byte(mp_reader_t *reader); +static size_t read_uint(mp_reader_t *reader); #if MICROPY_EMIT_MACHINE_CODE +#if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA + +// An mp_obj_list_t that tracks native text/BSS/rodata to prevent the GC from reclaiming them. +MP_REGISTER_ROOT_POINTER(mp_obj_t persistent_code_root_pointers); + +static void track_root_pointer(void *ptr) { + if (MP_STATE_PORT(persistent_code_root_pointers) == MP_OBJ_NULL) { + MP_STATE_PORT(persistent_code_root_pointers) = mp_obj_new_list(0, NULL); + } + mp_obj_list_append(MP_STATE_PORT(persistent_code_root_pointers), MP_OBJ_FROM_PTR(ptr)); +} + +#endif + typedef struct _reloc_info_t { mp_reader_t *reader; mp_module_context_t *context; @@ -145,17 +163,17 @@ void mp_native_relocate(void *ri_in, uint8_t *text, uintptr_t reloc_text) { #endif -STATIC int read_byte(mp_reader_t *reader) { +static int read_byte(mp_reader_t *reader) { return reader->readbyte(reader->data); } -STATIC void read_bytes(mp_reader_t *reader, byte *buf, size_t len) { +static void read_bytes(mp_reader_t *reader, byte *buf, size_t len) { while (len-- > 0) { *buf++ = reader->readbyte(reader->data); } } -STATIC size_t read_uint(mp_reader_t *reader) { +static size_t read_uint(mp_reader_t *reader) { size_t unum = 0; for (;;) { byte b = reader->readbyte(reader->data); @@ -167,13 +185,22 @@ STATIC size_t read_uint(mp_reader_t *reader) { return unum; } -STATIC qstr load_qstr(mp_reader_t *reader) { +static qstr load_qstr(mp_reader_t *reader) { size_t len = read_uint(reader); if (len & 1) { // static qstr return len >> 1; } len >>= 1; + + #if MICROPY_VFS_ROM + // If possible, create the qstr from the memory-mapped string data. + const uint8_t *memmap = mp_reader_try_read_rom(reader, len + 1); + if (memmap != NULL) { + return qstr_from_strn_static((const char *)memmap, len); + } + #endif + char *str = m_new(char, len); read_bytes(reader, (byte *)str, len); read_byte(reader); // read and discard null terminator @@ -182,7 +209,25 @@ STATIC qstr load_qstr(mp_reader_t *reader) { return qst; } -STATIC mp_obj_t load_obj(mp_reader_t *reader) { +#if MICROPY_VFS_ROM +// Create a str/bytes object that can forever reference the given data. +static mp_obj_t mp_obj_new_str_static(const mp_obj_type_t *type, const byte *data, size_t len) { + if (type == &mp_type_str) { + qstr q = qstr_find_strn((const char *)data, len); + if (q != MP_QSTRnull) { + return MP_OBJ_NEW_QSTR(q); + } + } + assert(data[len] == '\0'); + mp_obj_str_t *o = mp_obj_malloc(mp_obj_str_t, type); + o->len = len; + o->hash = qstr_compute_hash(data, len); + o->data = data; + return MP_OBJ_FROM_PTR(o); +} +#endif + +static mp_obj_t load_obj(mp_reader_t *reader) { byte obj_type = read_byte(reader); #if MICROPY_EMIT_MACHINE_CODE if (obj_type == MP_PERSISTENT_OBJ_FUN_TABLE) { @@ -199,6 +244,8 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj); } else { size_t len = read_uint(reader); + + // Handle empty bytes object, and tuple objects. if (len == 0 && obj_type == MP_PERSISTENT_OBJ_BYTES) { read_byte(reader); // skip null terminator return mp_const_empty_bytes; @@ -209,11 +256,31 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { } return MP_OBJ_FROM_PTR(tuple); } + + // Read in the object's data, either from ROM or into RAM. + const uint8_t *memmap = NULL; vstr_t vstr; - vstr_init_len(&vstr, len); - read_bytes(reader, (byte *)vstr.buf, len); + #if MICROPY_VFS_ROM + memmap = mp_reader_try_read_rom(reader, len); + vstr.buf = (void *)memmap; + vstr.len = len; + #endif + if (memmap == NULL) { + // Data could not be memory-mapped, so allocate it in RAM and read it in. + vstr_init_len(&vstr, len); + read_bytes(reader, (byte *)vstr.buf, len); + } + + // Create and return the object. if (obj_type == MP_PERSISTENT_OBJ_STR || obj_type == MP_PERSISTENT_OBJ_BYTES) { - read_byte(reader); // skip null terminator + read_byte(reader); // skip null terminator (it needs to be there for ROM str objects) + #if MICROPY_VFS_ROM + if (memmap != NULL) { + // Create a str/bytes that references the memory-mapped data. + const mp_obj_type_t *t = obj_type == MP_PERSISTENT_OBJ_STR ? &mp_type_str : &mp_type_bytes; + return mp_obj_new_str_static(t, memmap, len); + } + #endif if (obj_type == MP_PERSISTENT_OBJ_STR) { return mp_obj_new_str_from_utf8_vstr(&vstr); } else { @@ -228,7 +295,7 @@ STATIC mp_obj_t load_obj(mp_reader_t *reader) { } } -STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *context) { +static mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *context) { // Load function kind and data length size_t kind_len = read_uint(reader); int kind = (kind_len & 3) + MP_CODE_BYTECODE; @@ -250,10 +317,17 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co #endif if (kind == MP_CODE_BYTECODE) { - // Allocate memory for the bytecode - fun_data = m_new(uint8_t, fun_data_len); - // Load bytecode - read_bytes(reader, fun_data, fun_data_len); + #if MICROPY_VFS_ROM + // Try to reference memory-mapped data for the bytecode. + fun_data = (uint8_t *)mp_reader_try_read_rom(reader, fun_data_len); + #endif + + if (fun_data == NULL) { + // Allocate memory for the bytecode. + fun_data = m_new(uint8_t, fun_data_len); + // Load bytecode. + read_bytes(reader, fun_data, fun_data_len); + } #if MICROPY_EMIT_MACHINE_CODE } else { @@ -306,11 +380,10 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co read_bytes(reader, rodata, rodata_size); } - // Viper code with BSS/rodata should not have any children. - // Reuse the children pointer to reference the BSS/rodata - // memory so that it is not reclaimed by the GC. - assert(!has_children); - children = (void *)data; + #if MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA + // Track the BSS/rodata memory so it's not reclaimed by the GC. + track_root_pointer(data); + #endif } } #endif @@ -331,18 +404,16 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co MP_BC_PRELUDE_SIG_DECODE(ip); // Assign bytecode to raw code object mp_emit_glue_assign_bytecode(rc, fun_data, - #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS - fun_data_len, - #endif children, #if MICROPY_PERSISTENT_CODE_SAVE + fun_data_len, n_children, #endif scope_flags); #if MICROPY_EMIT_MACHINE_CODE } else { - const uint8_t *prelude_ptr; + const uint8_t *prelude_ptr = NULL; #if MICROPY_EMIT_NATIVE_PRELUDE_SEPARATE_FROM_MACHINE_CODE if (kind == MP_CODE_NATIVE_PY) { // Executable code cannot be accessed byte-wise on this architecture, so copy @@ -355,22 +426,17 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader, mp_module_context_t *co // Relocate and commit code to executable address space reloc_info_t ri = {reader, context, rodata, bss}; + #if MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA + if (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { + // Track the function data memory so it's not reclaimed by the GC. + track_root_pointer(fun_data); + } + #endif #if defined(MP_PLAT_COMMIT_EXEC) void *opt_ri = (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) ? &ri : NULL; fun_data = MP_PLAT_COMMIT_EXEC(fun_data, fun_data_len, opt_ri); #else if (native_scope_flags & MP_SCOPE_FLAG_VIPERRELOC) { - #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE - // If native code needs relocations then it's not guaranteed that a pointer to - // the head of `buf` (containing the machine code) will be retained for the GC - // to trace. This is because native functions can start inside `buf` and so - // it's possible that the only GC-reachable pointers are pointers inside `buf`. - // So put this `buf` on a list of reachable root pointers. - if (MP_STATE_PORT(track_reloc_code_list) == MP_OBJ_NULL) { - MP_STATE_PORT(track_reloc_code_list) = mp_obj_new_list(0, NULL); - } - mp_obj_list_append(MP_STATE_PORT(track_reloc_code_list), MP_OBJ_FROM_PTR(fun_data)); - #endif // Do the relocations. mp_native_relocate(&ri, fun_data, (uintptr_t)fun_data); } @@ -411,13 +477,16 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { read_bytes(reader, header, sizeof(header)); byte arch = MPY_FEATURE_DECODE_ARCH(header[2]); // CIRCUITPY-CHANGE: 'C', not 'M' + if (header[0] == 'M') { + mp_raise_ValueError(MP_ERROR_TEXT("MicroPython .mpy file; use CircuitPython mpy-cross")); + } if (header[0] != 'C' || header[1] != MPY_VERSION || (arch != MP_NATIVE_ARCH_NONE && MPY_FEATURE_DECODE_SUB_VERSION(header[2]) != MPY_SUB_VERSION) || header[3] > MP_SMALL_INT_BITS) { mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); } - if (MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE) { + if (arch != MP_NATIVE_ARCH_NONE) { if (!MPY_FEATURE_ARCH_TEST(arch)) { if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_NONE)) { // On supported ports this can be resolved by enabling feature, eg @@ -429,6 +498,23 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { } } + size_t arch_flags = 0; + if (MPY_FEATURE_ARCH_FLAGS_TEST(header[2])) { + #if MICROPY_EMIT_RV32 + arch_flags = read_uint(reader); + + if (MPY_FEATURE_ARCH_TEST(MP_NATIVE_ARCH_RV32IMC)) { + if ((arch_flags & (size_t)asm_rv32_allowed_extensions()) != arch_flags) { + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); + } + } else + #endif + { + (void)arch_flags; + mp_raise_ValueError(MP_ERROR_TEXT("incompatible .mpy file")); + } + } + size_t n_qstr = read_uint(reader); size_t n_obj = read_uint(reader); mp_module_context_alloc_tables(cm->context, n_qstr, n_obj); @@ -450,6 +536,7 @@ void mp_raw_code_load(mp_reader_t *reader, mp_compiled_module_t *cm) { cm->has_native = MPY_FEATURE_DECODE_ARCH(header[2]) != MP_NATIVE_ARCH_NONE; cm->n_qstr = n_qstr; cm->n_obj = n_obj; + cm->arch_flags = arch_flags; #endif // Deregister exception handler and close the reader. @@ -474,16 +561,16 @@ void mp_raw_code_load_file(qstr filename, mp_compiled_module_t *context) { #endif // MICROPY_PERSISTENT_CODE_LOAD -#if MICROPY_PERSISTENT_CODE_SAVE +#if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_PERSISTENT_CODE_SAVE_FUN #include "py/objstr.h" -STATIC void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) { +static void mp_print_bytes(mp_print_t *print, const byte *data, size_t len) { print->print_strn(print->data, (const char *)data, len); } #define BYTES_FOR_INT ((MP_BYTES_PER_OBJ_WORD * 8 + 6) / 7) -STATIC void mp_print_uint(mp_print_t *print, size_t n) { +static void mp_print_uint(mp_print_t *print, size_t n) { byte buf[BYTES_FOR_INT]; byte *p = buf + sizeof(buf); *--p = n & 0x7f; @@ -494,7 +581,7 @@ STATIC void mp_print_uint(mp_print_t *print, size_t n) { print->print_strn(print->data, (char *)p, buf + sizeof(buf) - p); } -STATIC void save_qstr(mp_print_t *print, qstr qst) { +static void save_qstr(mp_print_t *print, qstr qst) { if (qst <= QSTR_LAST_STATIC) { // encode static qstr mp_print_uint(print, qst << 1 | 1); @@ -506,7 +593,7 @@ STATIC void save_qstr(mp_print_t *print, qstr qst) { mp_print_bytes(print, str, len + 1); // +1 to store null terminator } -STATIC void save_obj(mp_print_t *print, mp_obj_t o) { +static void save_obj(mp_print_t *print, mp_obj_t o) { #if MICROPY_EMIT_MACHINE_CODE if (o == MP_OBJ_FROM_PTR(&mp_fun_table)) { byte obj_type = MP_PERSISTENT_OBJ_FUN_TABLE; @@ -572,7 +659,11 @@ STATIC void save_obj(mp_print_t *print, mp_obj_t o) { } } -STATIC void save_raw_code(mp_print_t *print, const mp_raw_code_t *rc) { +#endif // MICROPY_PERSISTENT_CODE_SAVE || MICROPY_PERSISTENT_CODE_SAVE_FUN + +#if MICROPY_PERSISTENT_CODE_SAVE + +static void save_raw_code(mp_print_t *print, const mp_raw_code_t *rc) { // Save function kind and data length mp_print_uint(print, (rc->fun_data_len << 3) | ((rc->n_children != 0) << 2) | (rc->kind - MP_CODE_BYTECODE)); @@ -585,11 +676,15 @@ STATIC void save_raw_code(mp_print_t *print, const mp_raw_code_t *rc) { mp_print_uint(print, rc->prelude_offset); } else if (rc->kind == MP_CODE_NATIVE_VIPER || rc->kind == MP_CODE_NATIVE_ASM) { // Save basic scope info for viper and asm - mp_print_uint(print, rc->scope_flags & MP_SCOPE_FLAG_ALL_SIG); + // Viper/asm functions don't support generator, variable args, or default keyword args + // so (scope_flags & MP_SCOPE_FLAG_ALL_SIG) for these functions is always 0. + mp_print_uint(print, 0); + #if MICROPY_EMIT_INLINE_ASM if (rc->kind == MP_CODE_NATIVE_ASM) { - mp_print_uint(print, rc->n_pos_args); - mp_print_uint(print, rc->type_sig); + mp_print_uint(print, rc->asm_n_pos_args); + mp_print_uint(print, rc->asm_type_sig); } + #endif } #endif @@ -611,7 +706,7 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { byte header[4] = { 'C', MPY_VERSION, - cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0, + (cm->arch_flags != 0 ? MPY_FEATURE_ARCH_FLAGS : 0) | (cm->has_native ? MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH_DYNAMIC) : 0), #if MICROPY_DYNAMIC_COMPILER mp_dynamic_compiler.small_int_bits, #else @@ -620,6 +715,10 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { }; mp_print_bytes(print, header, sizeof(header)); + if (cm->arch_flags) { + mp_print_uint(print, cm->arch_flags); + } + // Number of entries in constant table. mp_print_uint(print, cm->n_qstr); mp_print_uint(print, cm->n_obj); @@ -638,13 +737,15 @@ void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print) { save_raw_code(print, cm->rc); } +#endif // MICROPY_PERSISTENT_CODE_SAVE + #if MICROPY_PERSISTENT_CODE_SAVE_FILE #include #include #include -STATIC void fd_print_strn(void *env, const char *str, size_t len) { +static void fd_print_strn(void *env, const char *str, size_t len) { int fd = (intptr_t)env; MP_THREAD_GIL_EXIT(); ssize_t ret = write(fd, str, len); @@ -668,7 +769,182 @@ void mp_raw_code_save_file(mp_compiled_module_t *cm, qstr filename) { #endif // MICROPY_PERSISTENT_CODE_SAVE_FILE -#endif // MICROPY_PERSISTENT_CODE_SAVE +#if MICROPY_PERSISTENT_CODE_SAVE_FUN + +#include "py/bc0.h" +#include "py/objfun.h" +#include "py/smallint.h" +#include "py/gc.h" + +#define MP_BC_OPCODE_HAS_SIGNED_OFFSET(opcode) (MP_BC_UNWIND_JUMP <= (opcode) && (opcode) <= MP_BC_POP_JUMP_IF_FALSE) + +typedef struct _bit_vector_t { + size_t max_bit_set; + size_t alloc; + uintptr_t *bits; +} bit_vector_t; + +static void bit_vector_init(bit_vector_t *self) { + self->max_bit_set = 0; + self->alloc = 1; + self->bits = m_new(uintptr_t, self->alloc); +} + +static void bit_vector_clear(bit_vector_t *self) { + m_del(uintptr_t, self->bits, self->alloc); +} + +static bool bit_vector_is_set(bit_vector_t *self, size_t index) { + const size_t bits_size = sizeof(*self->bits) * MP_BITS_PER_BYTE; + return index / bits_size < self->alloc + && (self->bits[index / bits_size] & ((uintptr_t)1 << (index % bits_size))) != 0; +} + +static void bit_vector_set(bit_vector_t *self, size_t index) { + const size_t bits_size = sizeof(*self->bits) * MP_BITS_PER_BYTE; + self->max_bit_set = MAX(self->max_bit_set, index); + if (index / bits_size >= self->alloc) { + size_t new_alloc = self->alloc * 2; + self->bits = m_renew(uintptr_t, self->bits, self->alloc, new_alloc); + self->alloc = new_alloc; + } + self->bits[index / bits_size] |= (uintptr_t)1 << (index % bits_size); +} + +typedef struct _mp_opcode_t { + uint8_t opcode; + uint8_t format; + uint8_t size; + mp_int_t arg; + uint8_t extra_arg; +} mp_opcode_t; + +static mp_opcode_t mp_opcode_decode(const uint8_t *ip) { + const uint8_t *ip_start = ip; + uint8_t opcode = *ip++; + uint8_t opcode_format = MP_BC_FORMAT(opcode); + mp_uint_t arg = 0; + uint8_t extra_arg = 0; + if (opcode_format == MP_BC_FORMAT_QSTR || opcode_format == MP_BC_FORMAT_VAR_UINT) { + arg = *ip & 0x7f; + if (opcode == MP_BC_LOAD_CONST_SMALL_INT && (arg & 0x40) != 0) { + arg |= (mp_uint_t)(-1) << 7; + } + while ((*ip & 0x80) != 0) { + arg = (arg << 7) | (*++ip & 0x7f); + } + ++ip; + } else if (opcode_format == MP_BC_FORMAT_OFFSET) { + if ((*ip & 0x80) == 0) { + arg = *ip++; + if (MP_BC_OPCODE_HAS_SIGNED_OFFSET(opcode)) { + arg -= 0x40; + } + } else { + arg = (ip[0] & 0x7f) | (ip[1] << 7); + ip += 2; + if (MP_BC_OPCODE_HAS_SIGNED_OFFSET(opcode)) { + arg -= 0x4000; + } + } + } + if ((opcode & MP_BC_MASK_EXTRA_BYTE) == 0) { + extra_arg = *ip++; + } + + mp_opcode_t op = { opcode, opcode_format, ip - ip_start, arg, extra_arg }; + return op; +} + +mp_obj_t mp_raw_code_save_fun_to_bytes(const mp_module_constants_t *consts, const uint8_t *bytecode) { + const uint8_t *fun_data = bytecode; + const uint8_t *fun_data_top = fun_data + gc_nbytes(fun_data); + + // Extract function information. + const byte *ip = fun_data; + MP_BC_PRELUDE_SIG_DECODE(ip); + MP_BC_PRELUDE_SIZE_DECODE(ip); + + // Track the qstrs used by the function. + bit_vector_t qstr_table_used; + bit_vector_init(&qstr_table_used); + + // Track the objects used by the function. + bit_vector_t obj_table_used; + bit_vector_init(&obj_table_used); + + const byte *ip_names = ip; + mp_uint_t simple_name = mp_decode_uint(&ip_names); + bit_vector_set(&qstr_table_used, simple_name); + for (size_t i = 0; i < n_pos_args + n_kwonly_args; ++i) { + mp_uint_t arg_name = mp_decode_uint(&ip_names); + bit_vector_set(&qstr_table_used, arg_name); + } + + // Skip pass source code info and cell info. + // Then ip points to the start of the opcodes. + ip += n_info + n_cell; + + // Decode bytecode. + while (ip < fun_data_top) { + mp_opcode_t op = mp_opcode_decode(ip); + if (op.opcode == MP_BC_BASE_RESERVED) { + // End of opcodes. + fun_data_top = ip; + } else if (op.opcode == MP_BC_LOAD_CONST_OBJ) { + bit_vector_set(&obj_table_used, op.arg); + } else if (op.format == MP_BC_FORMAT_QSTR) { + bit_vector_set(&qstr_table_used, op.arg); + } + ip += op.size; + } + + mp_uint_t fun_data_len = fun_data_top - fun_data; + + mp_print_t print; + vstr_t vstr; + vstr_init_print(&vstr, 64, &print); + + // Start with .mpy header. + const uint8_t header[4] = { 'M', MPY_VERSION, 0, MP_SMALL_INT_BITS }; + mp_print_bytes(&print, header, sizeof(header)); + + // Number of entries in constant table. + mp_print_uint(&print, qstr_table_used.max_bit_set + 1); + mp_print_uint(&print, obj_table_used.max_bit_set + 1); + + // Save qstrs. + for (size_t i = 0; i <= qstr_table_used.max_bit_set; ++i) { + if (bit_vector_is_set(&qstr_table_used, i)) { + save_qstr(&print, consts->qstr_table[i]); + } else { + save_qstr(&print, MP_QSTR_); + } + } + + // Save constant objects. + for (size_t i = 0; i <= obj_table_used.max_bit_set; ++i) { + if (bit_vector_is_set(&obj_table_used, i)) { + save_obj(&print, consts->obj_table[i]); + } else { + save_obj(&print, mp_const_none); + } + } + + bit_vector_clear(&qstr_table_used); + bit_vector_clear(&obj_table_used); + + // Save function kind and data length. + mp_print_uint(&print, fun_data_len << 3); + + // Save function code. + mp_print_bytes(&print, fun_data, fun_data_len); + + // Create and return bytes representing the .mpy data. + return mp_obj_new_bytes_from_vstr(&vstr); +} + +#endif // MICROPY_PERSISTENT_CODE_SAVE_FUN #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE // An mp_obj_list_t that tracks relocated native code to prevent the GC from reclaiming them. diff --git a/py/persistentcode.h b/py/persistentcode.h index 45a268d63fb91..85668e608c85b 100644 --- a/py/persistentcode.h +++ b/py/persistentcode.h @@ -30,12 +30,17 @@ #include "py/reader.h" #include "py/emitglue.h" +// CIRCUITPY-CHANGE: Avoid undefined warnings +#ifndef MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE +#define MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE (0) +#endif + // The current version of .mpy files. A bytecode-only .mpy file can be loaded // as long as MPY_VERSION matches, but a native .mpy (i.e. one with an arch // set) must also match MPY_SUB_VERSION. This allows 3 additional updates to // the native ABI per bytecode revision. #define MPY_VERSION 6 -#define MPY_SUB_VERSION 2 +#define MPY_SUB_VERSION 3 // Macros to encode/decode sub-version to/from the feature byte. This replaces // the bits previously used to encode the flags (map caching and unicode) @@ -45,7 +50,7 @@ // Macros to encode/decode native architecture to/from the feature byte #define MPY_FEATURE_ENCODE_ARCH(arch) ((arch) << 2) -#define MPY_FEATURE_DECODE_ARCH(feat) ((feat) >> 2) +#define MPY_FEATURE_DECODE_ARCH(feat) (((feat) >> 2) & 0x2F) // Define the host architecture #if MICROPY_EMIT_X86 @@ -71,6 +76,8 @@ #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSA) #elif MICROPY_EMIT_XTENSAWIN #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_XTENSAWIN) +#elif MICROPY_EMIT_RV32 + #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_RV32IMC) #else #define MPY_FEATURE_ARCH (MP_NATIVE_ARCH_NONE) #endif @@ -83,6 +90,10 @@ #define MPY_FILE_HEADER_INT (MPY_VERSION \ | (MPY_FEATURE_ENCODE_SUB_VERSION(MPY_SUB_VERSION) | MPY_FEATURE_ENCODE_ARCH(MPY_FEATURE_ARCH)) << 8) +// Architecture-specific flags are present in the .mpy file +#define MPY_FEATURE_ARCH_FLAGS (0x40) +#define MPY_FEATURE_ARCH_FLAGS_TEST(x) (((x) & MPY_FEATURE_ARCH_FLAGS) == MPY_FEATURE_ARCH_FLAGS) + enum { MP_NATIVE_ARCH_NONE = 0, MP_NATIVE_ARCH_X86, @@ -95,6 +106,9 @@ enum { MP_NATIVE_ARCH_ARMV7EMDP, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN, + MP_NATIVE_ARCH_RV32IMC, + MP_NATIVE_ARCH_RV64IMC, + MP_NATIVE_ARCH_DEBUG, // this entry should always be last }; enum { @@ -117,6 +131,7 @@ void mp_raw_code_load_file(qstr filename, mp_compiled_module_t *ctx); void mp_raw_code_save(mp_compiled_module_t *cm, mp_print_t *print); void mp_raw_code_save_file(mp_compiled_module_t *cm, qstr filename); +mp_obj_t mp_raw_code_save_fun_to_bytes(const mp_module_constants_t *consts, const uint8_t *bytecode); void mp_native_relocate(void *reloc, uint8_t *text, uintptr_t reloc_text); diff --git a/py/profile.c b/py/profile.c index 274089d7022f1..b5a0c54728c97 100644 --- a/py/profile.c +++ b/py/profile.c @@ -38,9 +38,8 @@ #endif #define prof_trace_cb MP_STATE_THREAD(prof_trace_callback) -#define QSTR_MAP(context, idx) (context->constants.qstr_table[idx]) -STATIC uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { +uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc) { const mp_bytecode_prelude_t *prelude = &rc->prelude; return mp_bytecode_get_source_line(prelude->line_info, prelude->line_info_top, bc); } @@ -68,141 +67,10 @@ void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelud prelude->line_info = ip; } -/******************************************************************************/ -// code object - -STATIC void code_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { - (void)kind; - mp_obj_code_t *o = MP_OBJ_TO_PTR(o_in); - const mp_raw_code_t *rc = o->rc; - const mp_bytecode_prelude_t *prelude = &rc->prelude; - mp_printf(print, - "", - QSTR_MAP(o->context, prelude->qstr_block_name_idx), - o, - QSTR_MAP(o->context, 0), - rc->line_of_definition - ); -} - -STATIC mp_obj_tuple_t *code_consts(const mp_module_context_t *context, const mp_raw_code_t *rc) { - mp_obj_tuple_t *consts = MP_OBJ_TO_PTR(mp_obj_new_tuple(rc->n_children + 1, NULL)); - - size_t const_no = 0; - for (size_t i = 0; i < rc->n_children; ++i) { - mp_obj_t code = mp_obj_new_code(context, rc->children[i]); - if (code == MP_OBJ_NULL) { - m_malloc_fail(sizeof(mp_obj_code_t)); - } - consts->items[const_no++] = code; - } - consts->items[const_no++] = mp_const_none; - - return consts; -} - -STATIC mp_obj_t raw_code_lnotab(const mp_raw_code_t *rc) { - // const mp_bytecode_prelude_t *prelude = &rc->prelude; - uint start = 0; - uint stop = rc->fun_data_len - start; - - uint last_lineno = mp_prof_bytecode_lineno(rc, start); - uint lasti = 0; - - const uint buffer_chunk_size = (stop - start) >> 2; // heuristic magic - uint buffer_size = buffer_chunk_size; - byte *buffer = m_new(byte, buffer_size); - uint buffer_index = 0; - - for (uint i = start; i < stop; ++i) { - uint lineno = mp_prof_bytecode_lineno(rc, i); - size_t line_diff = lineno - last_lineno; - if (line_diff > 0) { - uint instr_diff = (i - start) - lasti; - - assert(instr_diff < 256); - assert(line_diff < 256); - - if (buffer_index + 2 > buffer_size) { - buffer = m_renew(byte, buffer, buffer_size, buffer_size + buffer_chunk_size); - buffer_size = buffer_size + buffer_chunk_size; - } - last_lineno = lineno; - lasti = i - start; - buffer[buffer_index++] = instr_diff; - buffer[buffer_index++] = line_diff; - } - } - - mp_obj_t o = mp_obj_new_bytes(buffer, buffer_index); - m_del(byte, buffer, buffer_size); - return o; -} - -STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { - if (dest[0] != MP_OBJ_NULL) { - // not load attribute - return; - } - mp_obj_code_t *o = MP_OBJ_TO_PTR(self_in); - const mp_raw_code_t *rc = o->rc; - const mp_bytecode_prelude_t *prelude = &rc->prelude; - switch (attr) { - case MP_QSTR_co_code: - dest[0] = mp_obj_new_bytes( - (void *)prelude->opcodes, - rc->fun_data_len - (prelude->opcodes - (const byte *)rc->fun_data) - ); - break; - case MP_QSTR_co_consts: - dest[0] = MP_OBJ_FROM_PTR(code_consts(o->context, rc)); - break; - case MP_QSTR_co_filename: - dest[0] = MP_OBJ_NEW_QSTR(QSTR_MAP(o->context, 0)); - break; - case MP_QSTR_co_firstlineno: - dest[0] = MP_OBJ_NEW_SMALL_INT(mp_prof_bytecode_lineno(rc, 0)); - break; - case MP_QSTR_co_name: - dest[0] = MP_OBJ_NEW_QSTR(QSTR_MAP(o->context, prelude->qstr_block_name_idx)); - break; - case MP_QSTR_co_names: - dest[0] = MP_OBJ_FROM_PTR(o->dict_locals); - break; - case MP_QSTR_co_lnotab: - if (!o->lnotab) { - o->lnotab = raw_code_lnotab(rc); - } - dest[0] = o->lnotab; - break; - } -} - -MP_DEFINE_CONST_OBJ_TYPE( - mp_type_settrace_codeobj, - MP_QSTR_code, - MP_TYPE_FLAG_NONE, - print, code_print, - attr, code_attr - ); - -mp_obj_t mp_obj_new_code(const mp_module_context_t *context, const mp_raw_code_t *rc) { - mp_obj_code_t *o = m_new_obj_maybe(mp_obj_code_t); - if (o == NULL) { - return MP_OBJ_NULL; - } - o->base.type = &mp_type_settrace_codeobj; - o->context = context; - o->rc = rc; - o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly? - o->lnotab = MP_OBJ_NULL; - return MP_OBJ_FROM_PTR(o); -} - /******************************************************************************/ // frame object -STATIC void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { +static void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) { (void)kind; mp_obj_frame_t *frame = MP_OBJ_TO_PTR(o_in); mp_obj_code_t *code = frame->code; @@ -211,13 +79,13 @@ STATIC void frame_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t mp_printf(print, "", frame, - QSTR_MAP(code->context, 0), - frame->lineno, - QSTR_MAP(code->context, prelude->qstr_block_name_idx) + MP_CODE_QSTR_MAP(code->context, 0), + (int)frame->lineno, + MP_CODE_QSTR_MAP(code->context, prelude->qstr_block_name_idx) ); } -STATIC void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { +static void frame_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { // not load attribute return; @@ -265,7 +133,7 @@ mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state) { return MP_OBJ_NULL; } - mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->context, code_state->fun_bc->rc)); + mp_obj_code_t *code = o->code = MP_OBJ_TO_PTR(mp_obj_new_code(code_state->fun_bc->context, code_state->fun_bc->rc, false)); if (code == NULL) { return MP_OBJ_NULL; } @@ -294,7 +162,7 @@ typedef struct { mp_obj_t arg; } prof_callback_args_t; -STATIC mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) { +static mp_obj_t mp_prof_callback_invoke(mp_obj_t callback, prof_callback_args_t *args) { assert(mp_obj_is_callable(callback)); mp_prof_is_executing = true; @@ -474,7 +342,7 @@ typedef struct _mp_dis_instruction_t { mp_obj_t argobjex_cache; } mp_dis_instruction_t; -STATIC const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) { +static const byte *mp_prof_opcode_decode(const byte *ip, const mp_uint_t *const_table, mp_dis_instruction_t *instruction) { mp_uint_t unum; const byte *ptr; mp_obj_t obj; diff --git a/py/profile.h b/py/profile.h index 7f3f914034623..db72b9f076818 100644 --- a/py/profile.h +++ b/py/profile.h @@ -28,20 +28,12 @@ #define MICROPY_INCLUDED_PY_PROFILING_H #include "py/emitglue.h" +#include "py/objcode.h" #if MICROPY_PY_SYS_SETTRACE #define mp_prof_is_executing MP_STATE_THREAD(prof_callback_is_executing) -typedef struct _mp_obj_code_t { - // TODO this was 4 words - mp_obj_base_t base; - const mp_module_context_t *context; - const mp_raw_code_t *rc; - mp_obj_dict_t *dict_locals; - mp_obj_t lnotab; -} mp_obj_code_t; - typedef struct _mp_obj_frame_t { mp_obj_base_t base; const mp_code_state_t *code_state; @@ -53,9 +45,9 @@ typedef struct _mp_obj_frame_t { bool trace_opcodes; } mp_obj_frame_t; +uint mp_prof_bytecode_lineno(const mp_raw_code_t *rc, size_t bc); void mp_prof_extract_prelude(const byte *bytecode, mp_bytecode_prelude_t *prelude); -mp_obj_t mp_obj_new_code(const mp_module_context_t *mc, const mp_raw_code_t *rc); mp_obj_t mp_obj_new_frame(const mp_code_state_t *code_state); // This is the implementation for the sys.settrace diff --git a/py/py.cmake b/py/py.cmake index 1cbbe08f0136f..b99d2d24b5db3 100644 --- a/py/py.cmake +++ b/py/py.cmake @@ -9,6 +9,7 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/argcheck.c ${MICROPY_PY_DIR}/asmarm.c ${MICROPY_PY_DIR}/asmbase.c + ${MICROPY_PY_DIR}/asmrv32.c ${MICROPY_PY_DIR}/asmthumb.c ${MICROPY_PY_DIR}/asmx64.c ${MICROPY_PY_DIR}/asmx86.c @@ -19,12 +20,16 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/builtinhelp.c ${MICROPY_PY_DIR}/builtinimport.c ${MICROPY_PY_DIR}/compile.c + ${MICROPY_PY_DIR}/cstack.c ${MICROPY_PY_DIR}/emitbc.c ${MICROPY_PY_DIR}/emitcommon.c ${MICROPY_PY_DIR}/emitglue.c + ${MICROPY_PY_DIR}/emitinlinerv32.c ${MICROPY_PY_DIR}/emitinlinethumb.c ${MICROPY_PY_DIR}/emitinlinextensa.c ${MICROPY_PY_DIR}/emitnarm.c + ${MICROPY_PY_DIR}/emitndebug.c + ${MICROPY_PY_DIR}/emitnrv32.c ${MICROPY_PY_DIR}/emitnthumb.c ${MICROPY_PY_DIR}/emitnx64.c ${MICROPY_PY_DIR}/emitnx86.c @@ -53,8 +58,11 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/mpz.c ${MICROPY_PY_DIR}/nativeglue.c ${MICROPY_PY_DIR}/nlr.c + ${MICROPY_PY_DIR}/nlraarch64.c ${MICROPY_PY_DIR}/nlrmips.c ${MICROPY_PY_DIR}/nlrpowerpc.c + ${MICROPY_PY_DIR}/nlrrv32.c + ${MICROPY_PY_DIR}/nlrrv64.c ${MICROPY_PY_DIR}/nlrsetjmp.c ${MICROPY_PY_DIR}/nlrthumb.c ${MICROPY_PY_DIR}/nlrx64.c @@ -65,6 +73,7 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/objattrtuple.c ${MICROPY_PY_DIR}/objbool.c ${MICROPY_PY_DIR}/objboundmeth.c + ${MICROPY_PY_DIR}/objcode.c ${MICROPY_PY_DIR}/objcell.c ${MICROPY_PY_DIR}/objclosure.c ${MICROPY_PY_DIR}/objcomplex.c @@ -90,6 +99,7 @@ set(MICROPY_SOURCE_PY ${MICROPY_PY_DIR}/objproperty.c ${MICROPY_PY_DIR}/objrange.c ${MICROPY_PY_DIR}/objreversed.c + ${MICROPY_PY_DIR}/objringio.c ${MICROPY_PY_DIR}/objset.c ${MICROPY_PY_DIR}/objsingleton.c ${MICROPY_PY_DIR}/objslice.c diff --git a/py/py.mk b/py/py.mk index e45ed89b8c635..21be07c794fb1 100644 --- a/py/py.mk +++ b/py/py.mk @@ -36,12 +36,16 @@ ifneq ($(USER_C_MODULES),) # pre-define USERMOD variables as expanded so that variables are immediate # expanded as they're added to them +# Confirm the provided path exists, show abspath if not to make it clearer to fix. +$(if $(wildcard $(USER_C_MODULES)/.),,$(error USER_C_MODULES doesn't exist: $(abspath $(USER_C_MODULES)))) + # C/C++ files that are included in the QSTR/module build SRC_USERMOD_C := SRC_USERMOD_CXX := -# Other C/C++ files (e.g. libraries or helpers) +# Other C/C++/Assembly files (e.g. libraries or helpers) SRC_USERMOD_LIB_C := SRC_USERMOD_LIB_CXX := +SRC_USERMOD_LIB_ASM := # Optionally set flags CFLAGS_USERMOD := CXXFLAGS_USERMOD := @@ -63,6 +67,7 @@ SRC_USERMOD_PATHFIX_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_C)) SRC_USERMOD_PATHFIX_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_CXX)) SRC_USERMOD_PATHFIX_LIB_C += $(patsubst $(USER_C_MODULES)/%.c,%.c,$(SRC_USERMOD_LIB_C)) SRC_USERMOD_PATHFIX_LIB_CXX += $(patsubst $(USER_C_MODULES)/%.cpp,%.cpp,$(SRC_USERMOD_LIB_CXX)) +SRC_USERMOD_PATHFIX_LIB_ASM += $(patsubst $(USER_C_MODULES)/%.S,%.S,$(SRC_USERMOD_LIB_ASM)) CFLAGS += $(CFLAGS_USERMOD) CXXFLAGS += $(CXXFLAGS_USERMOD) @@ -100,6 +105,8 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ nlrmips.o \ nlrpowerpc.o \ nlrxtensa.o \ + nlrrv32.o \ + nlrrv64.o \ nlrsetjmp.o \ malloc.o \ gc.o \ @@ -131,6 +138,10 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ emitnxtensa.o \ emitinlinextensa.o \ emitnxtensawin.o \ + asmrv32.o \ + emitnrv32.o \ + emitinlinerv32.o \ + emitndebug.o \ formatfloat.o \ parsenumbase.o \ parsenum.o \ @@ -143,6 +154,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ nativeglue.o \ pairheap.o \ ringbuf.o \ + cstack.o \ stackctrl.o \ argcheck.o \ warning.o \ @@ -155,6 +167,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objboundmeth.o \ objcell.o \ objclosure.o \ + objcode.o \ objcomplex.o \ objdeque.o \ objdict.o \ @@ -178,6 +191,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objnamedtuple.o \ objrange.o \ objreversed.o \ + objringio.o \ objset.o \ objsingleton.o \ objslice.o \ @@ -223,7 +237,7 @@ PY_O += $(PY_CORE_O) # object file for frozen code specified via a manifest ifneq ($(FROZEN_MANIFEST),) -PY_O += $(BUILD)/$(BUILD)/frozen_content.o +PY_O += $(BUILD)/frozen_content.o endif # Sources that may contain qstrings @@ -276,7 +290,7 @@ $(HEADER_BUILD)/compressed_translations.generated.h: $(PY_SRC)/maketranslationda PY_CORE_O += $(PY_BUILD)/translations-$(TRANSLATION).o # build a list of registered modules for py/objmodule.c. -$(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected +$(HEADER_BUILD)/moduledefs.h: $(HEADER_BUILD)/moduledefs.collected $(PY_SRC)/makemoduledefs.py @$(ECHO) "GEN $@" $(Q)$(PYTHON) $(PY_SRC)/makemoduledefs.py $< > $@ diff --git a/py/qstr.c b/py/qstr.c index 41a031d101439..ab9ff4dd67db1 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -42,7 +42,11 @@ // A qstr is an index into the qstr pool. // The data for a qstr is \0 terminated (so they can be printed using printf) +#if MICROPY_QSTR_BYTES_IN_HASH #define Q_HASH_MASK ((1 << (8 * MICROPY_QSTR_BYTES_IN_HASH)) - 1) +#else +#define Q_HASH_MASK (0xffff) +#endif #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL #define QSTR_ENTER() mp_thread_mutex_lock(&MP_STATE_VM(qstr_mutex), 1) @@ -75,8 +79,9 @@ size_t qstr_compute_hash(const byte *data, size_t len) { // it is part of the .mpy ABI. See the top of py/persistentcode.c and // static_qstr_list in makeqstrdata.py. This pool is unsorted (although in a // future .mpy version we could re-order them and make it sorted). It also -// contains additional qstrs that must have IDs <256, see operator_qstr_list +// contains additional qstrs that must have IDs <256, see unsorted_qstr_list // in makeqstrdata.py. +#if MICROPY_QSTR_BYTES_IN_HASH const qstr_hash_t mp_qstr_const_hashes_static[] = { #ifndef NO_QSTR #define QDEF0(id, hash, len, str) hash, @@ -90,6 +95,7 @@ const qstr_hash_t mp_qstr_const_hashes_static[] = { #undef TRANSLATION #endif }; +#endif const qstr_len_t mp_qstr_const_lengths_static[] = { #ifndef NO_QSTR @@ -111,7 +117,9 @@ const qstr_pool_t mp_qstr_const_pool_static = { false, // is_sorted MICROPY_ALLOC_QSTR_ENTRIES_INIT, MP_QSTRnumber_of_static, // corresponds to number of strings in array just below + #if MICROPY_QSTR_BYTES_IN_HASH (qstr_hash_t *)mp_qstr_const_hashes_static, + #endif (qstr_len_t *)mp_qstr_const_lengths_static, { #ifndef NO_QSTR @@ -130,6 +138,7 @@ const qstr_pool_t mp_qstr_const_pool_static = { // The next pool is the remainder of the qstrs defined in the firmware. This // is sorted. +#if MICROPY_QSTR_BYTES_IN_HASH const qstr_hash_t mp_qstr_const_hashes[] = { #ifndef NO_QSTR #define QDEF0(id, hash, len, str) @@ -143,6 +152,7 @@ const qstr_hash_t mp_qstr_const_hashes[] = { #undef TRANSLATION #endif }; +#endif const qstr_len_t mp_qstr_const_lengths[] = { #ifndef NO_QSTR @@ -164,7 +174,9 @@ const qstr_pool_t mp_qstr_const_pool = { true, // is_sorted MICROPY_ALLOC_QSTR_ENTRIES_INIT, MP_QSTRnumber_of - MP_QSTRnumber_of_static, // corresponds to number of strings in array just below + #if MICROPY_QSTR_BYTES_IN_HASH (qstr_hash_t *)mp_qstr_const_hashes, + #endif (qstr_len_t *)mp_qstr_const_lengths, { #ifndef NO_QSTR @@ -181,6 +193,8 @@ const qstr_pool_t mp_qstr_const_pool = { }, }; +// If frozen code is enabled, then there is an additional, sorted, ROM pool +// containing additional qstrs required by the frozen code. #ifdef MICROPY_QSTR_EXTRA_POOL extern const qstr_pool_t MICROPY_QSTR_EXTRA_POOL; #define CONST_POOL MICROPY_QSTR_EXTRA_POOL @@ -202,7 +216,7 @@ void qstr_init(void) { #endif } -STATIC const qstr_pool_t *find_qstr(qstr *q) { +static const qstr_pool_t *find_qstr(qstr *q) { // search pool for this qstr // total_prev_len==0 in the final pool, so the loop will always terminate const qstr_pool_t *pool = MP_STATE_VM(last_pool); @@ -215,8 +229,13 @@ STATIC const qstr_pool_t *find_qstr(qstr *q) { } // qstr_mutex must be taken while in this function -STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { +static qstr qstr_add(mp_uint_t len, const char *q_ptr) { + #if MICROPY_QSTR_BYTES_IN_HASH + mp_uint_t hash = qstr_compute_hash((const byte *)q_ptr, len); DEBUG_printf("QSTR: add hash=%d len=%d data=%.*s\n", hash, len, len, q_ptr); + #else + DEBUG_printf("QSTR: add len=%d data=%.*s\n", len, len, q_ptr); + #endif // make sure we have room in the pool for a new qstr if (MP_STATE_VM(last_pool)->len >= MP_STATE_VM(last_pool)->alloc) { @@ -226,7 +245,11 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { new_alloc = MAX(MICROPY_ALLOC_QSTR_ENTRIES_INIT, new_alloc); #endif mp_uint_t pool_size = sizeof(qstr_pool_t) - + (sizeof(const char *) + sizeof(qstr_hash_t) + sizeof(qstr_len_t)) * new_alloc; + + (sizeof(const char *) + #if MICROPY_QSTR_BYTES_IN_HASH + + sizeof(qstr_hash_t) + #endif + + sizeof(qstr_len_t)) * new_alloc; qstr_pool_t *pool = (qstr_pool_t *)m_malloc_maybe(pool_size); if (pool == NULL) { // Keep qstr_last_chunk consistent with qstr_pool_t: qstr_last_chunk is not scanned @@ -238,8 +261,12 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { QSTR_EXIT(); m_malloc_fail(new_alloc); } + #if MICROPY_QSTR_BYTES_IN_HASH pool->hashes = (qstr_hash_t *)(pool->qstrs + new_alloc); pool->lengths = (qstr_len_t *)(pool->hashes + new_alloc); + #else + pool->lengths = (qstr_len_t *)(pool->qstrs + new_alloc); + #endif pool->prev = MP_STATE_VM(last_pool); pool->total_prev_len = MP_STATE_VM(last_pool)->total_prev_len + MP_STATE_VM(last_pool)->len; pool->alloc = new_alloc; @@ -250,7 +277,9 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { // add the new qstr mp_uint_t at = MP_STATE_VM(last_pool)->len; + #if MICROPY_QSTR_BYTES_IN_HASH MP_STATE_VM(last_pool)->hashes[at] = hash; + #endif MP_STATE_VM(last_pool)->lengths[at] = len; MP_STATE_VM(last_pool)->qstrs[at] = q_ptr; MP_STATE_VM(last_pool)->len++; @@ -265,8 +294,10 @@ qstr qstr_find_strn(const char *str, size_t str_len) { return MP_QSTR_; } + #if MICROPY_QSTR_BYTES_IN_HASH // work out hash of str size_t str_hash = qstr_compute_hash((const byte *)str, str_len); + #endif // search pools for the data for (const qstr_pool_t *pool = MP_STATE_VM(last_pool); pool != NULL; pool = pool->prev) { @@ -288,7 +319,11 @@ qstr qstr_find_strn(const char *str, size_t str_len) { // sequential search for the remaining strings for (mp_uint_t at = low; at < high + 1; at++) { - if (pool->hashes[at] == str_hash && pool->lengths[at] == str_len + if ( + #if MICROPY_QSTR_BYTES_IN_HASH + pool->hashes[at] == str_hash && + #endif + pool->lengths[at] == str_len && memcmp(pool->qstrs[at], str, str_len) == 0) { return pool->total_prev_len + at; } @@ -303,7 +338,7 @@ qstr qstr_from_str(const char *str) { return qstr_from_strn(str, strlen(str)); } -qstr qstr_from_strn(const char *str, size_t len) { +static qstr qstr_from_strn_helper(const char *str, size_t len, bool data_is_static) { QSTR_ENTER(); qstr q = qstr_find_strn(str, len); if (q == 0) { @@ -315,6 +350,12 @@ qstr qstr_from_strn(const char *str, size_t len) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("name too long")); } + if (data_is_static) { + // Given string data will be forever available so use it directly. + assert(str[len] == '\0'); + goto add; + } + // compute number of bytes needed to intern this string size_t n_bytes = len + 1; @@ -337,10 +378,11 @@ qstr qstr_from_strn(const char *str, size_t len) { if (al < MICROPY_ALLOC_QSTR_CHUNK_INIT) { al = MICROPY_ALLOC_QSTR_CHUNK_INIT; } - MP_STATE_VM(qstr_last_chunk) = m_new_maybe(char, al); + // CIRCUITPY-CHANGE: Don't collect the QSTR blocks that only contain a chunk of a string + MP_STATE_VM(qstr_last_chunk) = m_malloc_maybe_without_collect(sizeof(char) * al); if (MP_STATE_VM(qstr_last_chunk) == NULL) { // failed to allocate a large chunk so try with exact size - MP_STATE_VM(qstr_last_chunk) = m_new_maybe(char, n_bytes); + MP_STATE_VM(qstr_last_chunk) = m_malloc_maybe_without_collect(sizeof(char) * n_bytes); if (MP_STATE_VM(qstr_last_chunk) == NULL) { QSTR_EXIT(); m_malloc_fail(n_bytes); @@ -356,18 +398,35 @@ qstr qstr_from_strn(const char *str, size_t len) { MP_STATE_VM(qstr_last_used) += n_bytes; // store the interned strings' data - size_t hash = qstr_compute_hash((const byte *)str, len); memcpy(q_ptr, str, len); q_ptr[len] = '\0'; - q = qstr_add(hash, len, q_ptr); + str = q_ptr; + + add: + q = qstr_add(len, str); } QSTR_EXIT(); return q; } +qstr qstr_from_strn(const char *str, size_t len) { + return qstr_from_strn_helper(str, len, false); +} + +#if MICROPY_VFS_ROM +// Create a new qstr that can forever reference the given string data. +qstr qstr_from_strn_static(const char *str, size_t len) { + return qstr_from_strn_helper(str, len, true); +} +#endif + mp_uint_t qstr_hash(qstr q) { const qstr_pool_t *pool = find_qstr(&q); + #if MICROPY_QSTR_BYTES_IN_HASH return pool->hashes[q]; + #else + return qstr_compute_hash((byte *)pool->qstrs[q], pool->lengths[q]); + #endif } size_t qstr_len(qstr q) { @@ -402,7 +461,11 @@ void qstr_pool_info(size_t *n_pool, size_t *n_qstr, size_t *n_str_data_bytes, si *n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap #else *n_total_bytes += sizeof(qstr_pool_t) - + (sizeof(const char *) + sizeof(qstr_hash_t) + sizeof(qstr_len_t)) * pool->alloc; + + (sizeof(const char *) + #if MICROPY_QSTR_BYTES_IN_HASH + + sizeof(qstr_hash_t) + #endif + + sizeof(qstr_len_t)) * pool->alloc; #endif } *n_total_bytes += *n_str_data_bytes; @@ -431,7 +494,7 @@ void qstr_dump_data(void) { #else // Emit the compressed_string_data string. -#define MP_COMPRESSED_DATA(x) STATIC const char *compressed_string_data = x; +#define MP_COMPRESSED_DATA(x) static const char *compressed_string_data = x; #define MP_MATCH_COMPRESSED(a, b) #include "genhdr/compressed.data.h" #undef MP_COMPRESSED_DATA @@ -445,7 +508,7 @@ void qstr_dump_data(void) { // The compressed string data is delimited by setting high bit in the final char of each word. // e.g. aaaa<0x80|a>bbbbbb<0x80|b>.... // This method finds the n'th string. -STATIC const byte *find_uncompressed_string(uint8_t n) { +static const byte *find_uncompressed_string(uint8_t n) { const byte *c = (byte *)compressed_string_data; while (n > 0) { while ((*c & 0x80) == 0) { diff --git a/py/qstr.h b/py/qstr.h index 426726fe556b9..7dc04a8accb39 100644 --- a/py/qstr.h +++ b/py/qstr.h @@ -64,7 +64,9 @@ enum { typedef size_t qstr; typedef uint16_t qstr_short_t; -#if MICROPY_QSTR_BYTES_IN_HASH == 1 +#if MICROPY_QSTR_BYTES_IN_HASH == 0 +// No qstr_hash_t type needed. +#elif MICROPY_QSTR_BYTES_IN_HASH == 1 typedef uint8_t qstr_hash_t; #elif MICROPY_QSTR_BYTES_IN_HASH == 2 typedef uint16_t qstr_hash_t; @@ -86,7 +88,9 @@ typedef struct _qstr_pool_t { size_t is_sorted : 1; size_t alloc; size_t len; + #if MICROPY_QSTR_BYTES_IN_HASH qstr_hash_t *hashes; + #endif qstr_len_t *lengths; const char *qstrs[]; } qstr_pool_t; @@ -98,10 +102,14 @@ void qstr_reset(void); void qstr_init(void); size_t qstr_compute_hash(const byte *data, size_t len); + qstr qstr_find_strn(const char *str, size_t str_len); // returns MP_QSTRnull if not found qstr qstr_from_str(const char *str); qstr qstr_from_strn(const char *str, size_t len); +#if MICROPY_VFS_ROM +qstr qstr_from_strn_static(const char *str, size_t len); +#endif mp_uint_t qstr_hash(qstr q); const char *qstr_str(qstr q); diff --git a/py/reader.c b/py/reader.c index d2af62cfb344d..8feb6d75275f1 100644 --- a/py/reader.c +++ b/py/reader.c @@ -39,7 +39,7 @@ typedef struct _mp_reader_mem_t { const byte *end; } mp_reader_mem_t; -STATIC mp_uint_t mp_reader_mem_readbyte(void *data) { +static mp_uint_t mp_reader_mem_readbyte(void *data) { mp_reader_mem_t *reader = (mp_reader_mem_t *)data; if (reader->cur < reader->end) { return *reader->cur++; @@ -48,9 +48,9 @@ STATIC mp_uint_t mp_reader_mem_readbyte(void *data) { } } -STATIC void mp_reader_mem_close(void *data) { +static void mp_reader_mem_close(void *data) { mp_reader_mem_t *reader = (mp_reader_mem_t *)data; - if (reader->free_len > 0) { + if (reader->free_len > 0 && reader->free_len != MP_READER_IS_ROM) { m_del(char, (char *)reader->beg, reader->free_len); } m_del_obj(mp_reader_mem_t, reader); @@ -67,6 +67,19 @@ void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t reader->close = mp_reader_mem_close; } +const uint8_t *mp_reader_try_read_rom(mp_reader_t *reader, size_t len) { + if (reader->readbyte != mp_reader_mem_readbyte) { + return NULL; + } + mp_reader_mem_t *m = reader->data; + if (m->free_len != MP_READER_IS_ROM) { + return NULL; + } + const uint8_t *data = m->cur; + m->cur += len; + return data; +} + #if MICROPY_READER_POSIX #include @@ -81,7 +94,7 @@ typedef struct _mp_reader_posix_t { byte buf[20]; } mp_reader_posix_t; -STATIC mp_uint_t mp_reader_posix_readbyte(void *data) { +static mp_uint_t mp_reader_posix_readbyte(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t *)data; if (reader->pos >= reader->len) { if (reader->len == 0) { @@ -101,7 +114,7 @@ STATIC mp_uint_t mp_reader_posix_readbyte(void *data) { return reader->buf[reader->pos++]; } -STATIC void mp_reader_posix_close(void *data) { +static void mp_reader_posix_close(void *data) { mp_reader_posix_t *reader = (mp_reader_posix_t *)data; if (reader->close_fd) { MP_THREAD_GIL_EXIT(); diff --git a/py/reader.h b/py/reader.h index 5cb1e67966c61..6378457007cb3 100644 --- a/py/reader.h +++ b/py/reader.h @@ -28,6 +28,10 @@ #include "py/obj.h" +// Pass to the `free_len` argument to `mp_reader_new_mem` to indicate that the data is in ROM. +// This means that the data is addressable and will remain valid at least until a soft reset. +#define MP_READER_IS_ROM ((size_t)-1) + // the readbyte function must return the next byte in the input stream // it must return MP_READER_EOF if end of stream // it can be called again after returning MP_READER_EOF, and in that case must return MP_READER_EOF @@ -43,4 +47,9 @@ void mp_reader_new_mem(mp_reader_t *reader, const byte *buf, size_t len, size_t void mp_reader_new_file(mp_reader_t *reader, qstr filename); void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd); +// Try to efficiently read the given number of bytes from a ROM-based reader. +// Returns a valid, non-NULL pointer to the requested data if the reader points to ROM. +// Returns NULL if the reader does not point to ROM. +const uint8_t *mp_reader_try_read_rom(mp_reader_t *reader, size_t len); + #endif // MICROPY_INCLUDED_PY_READER_H diff --git a/py/repl.c b/py/repl.c index a40aa5b85a49b..bbfdd2ea6a6e2 100644 --- a/py/repl.c +++ b/py/repl.c @@ -48,7 +48,7 @@ const char *mp_repl_get_psx(unsigned int entry) { } #endif -STATIC bool str_startswith_word(const char *str, const char *head) { +static bool str_startswith_word(const char *str, const char *head) { size_t i; for (i = 0; str[i] && head[i]; i++) { if (str[i] != head[i]) { @@ -159,7 +159,7 @@ bool mp_repl_continue_with_input(const char *input) { return false; } -STATIC bool test_qstr(mp_obj_t obj, qstr name) { +static bool test_qstr(mp_obj_t obj, qstr name) { if (obj) { // try object member mp_obj_t dest[2]; @@ -181,12 +181,15 @@ STATIC bool test_qstr(mp_obj_t obj, qstr name) { return dest[0] != MP_OBJ_NULL; } else { // try builtin module - return mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) || - mp_map_lookup((mp_map_t *)&mp_builtin_extensible_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP); + return mp_map_lookup((mp_map_t *)&mp_builtin_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) + #if MICROPY_HAVE_REGISTERED_EXTENSIBLE_MODULES + || mp_map_lookup((mp_map_t *)&mp_builtin_extensible_module_map, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP) + #endif + ; } } -STATIC const char *find_completions(const char *s_start, size_t s_len, +static const char *find_completions(const char *s_start, size_t s_len, mp_obj_t obj, size_t *match_len, qstr *q_first, qstr *q_last) { const char *match_str = NULL; @@ -226,7 +229,7 @@ STATIC const char *find_completions(const char *s_start, size_t s_len, return match_str; } -STATIC void print_completions(const mp_print_t *print, +static void print_completions(const mp_print_t *print, const char *s_start, size_t s_len, mp_obj_t obj, qstr q_first, qstr q_last) { @@ -237,6 +240,10 @@ STATIC void print_completions(const mp_print_t *print, for (qstr q = q_first; q <= q_last; ++q) { size_t d_len; const char *d_str = (const char *)qstr_data(q, &d_len); + // filter out words that begin with underscore unless there's already a partial match + if (s_len == 0 && d_str[0] == '_') { + continue; + } if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) { if (test_qstr(obj, q)) { int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len; @@ -244,7 +251,6 @@ STATIC void print_completions(const mp_print_t *print, gap += WORD_SLOT_LEN; } if (line_len + gap + d_len <= MAX_LINE_LEN) { - // TODO optimise printing of gap? for (int j = 0; j < gap; ++j) { mp_print_str(print, " "); } diff --git a/py/runtime.c b/py/runtime.c index 24caceaaac8b7..81abc3de87570 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -45,9 +45,13 @@ #include "py/stream.h" #include "py/runtime.h" #include "py/builtin.h" -#include "py/stackctrl.h" +#include "py/cstack.h" #include "py/gc.h" +#if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL +#include "extmod/vfs.h" +#endif + // CIRCUITPY-CHANGE #if CIRCUITPY_WARNINGS #include "shared-module/warnings/__init__.h" @@ -130,8 +134,8 @@ void mp_init(void) { MP_STATE_VM(mp_module_builtins_override_dict) = NULL; #endif - #if MICROPY_PERSISTENT_CODE_TRACK_RELOC_CODE - MP_STATE_VM(track_reloc_code_list) = MP_OBJ_NULL; + #if MICROPY_EMIT_MACHINE_CODE && (MICROPY_PERSISTENT_CODE_TRACK_FUN_DATA || MICROPY_PERSISTENT_CODE_TRACK_BSS_RODATA) + MP_STATE_VM(persistent_code_root_pointers) = MP_OBJ_NULL; #endif #if MICROPY_PY_OS_DUPTERM @@ -183,6 +187,10 @@ void mp_init(void) { MP_STATE_VM(bluetooth) = MP_OBJ_NULL; #endif + #if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE + MP_STATE_VM(usbd) = MP_OBJ_NULL; + #endif + #if MICROPY_PY_THREAD_GIL mp_thread_mutex_init(&MP_STATE_VM(gil_mutex)); #endif @@ -193,6 +201,11 @@ void mp_init(void) { #endif MP_THREAD_GIL_ENTER(); + + #if MICROPY_VFS_ROM && MICROPY_VFS_ROM_IOCTL + // Mount ROMFS if it exists. + mp_vfs_mount_romfs_protected(); + #endif } void mp_deinit(void) { @@ -247,8 +260,7 @@ mp_obj_t MICROPY_WRAP_MP_LOAD_GLOBAL(mp_load_global)(qstr qst) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_msg(&mp_type_NameError, MP_ERROR_TEXT("name not defined")); #else - // CIRCUITPY-CHANGE: slight message change - mp_raise_msg_varg(&mp_type_NameError, MP_ERROR_TEXT("name '%q' is not defined"), qst); + mp_raise_msg_varg(&mp_type_NameError, MP_ERROR_TEXT("name '%q' isn't defined"), qst); #endif } } @@ -434,7 +446,7 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs // Operations that can overflow: // + result always fits in mp_int_t, then handled by SMALL_INT check // - result always fits in mp_int_t, then handled by SMALL_INT check - // * checked explicitly + // * checked explicitly for fit in mp_int_t, then handled by SMALL_INT check // / if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // % if lhs=MIN and rhs=-1; result always fits in mp_int_t, then handled by SMALL_INT check // << checked explicitly @@ -493,30 +505,16 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs break; case MP_BINARY_OP_MULTIPLY: case MP_BINARY_OP_INPLACE_MULTIPLY: { - - // If long long type exists and is larger than mp_int_t, then - // we can use the following code to perform overflow-checked multiplication. - // Otherwise (eg in x64 case) we must use mp_small_int_mul_overflow. - #if 0 - // compute result using long long precision - long long res = (long long)lhs_val * (long long)rhs_val; - if (res > MP_SMALL_INT_MAX || res < MP_SMALL_INT_MIN) { - // result overflowed SMALL_INT, so return higher precision integer - return mp_obj_new_int_from_ll(res); - } else { - // use standard precision - lhs_val = (mp_int_t)res; - } - #endif - - if (mp_small_int_mul_overflow(lhs_val, rhs_val)) { + mp_int_t int_res; + if (mp_mul_mp_int_t_overflow(lhs_val, rhs_val, &int_res)) { // use higher precision lhs = mp_obj_new_int_from_ll(lhs_val); goto generic_binary_op; } else { // use standard precision - return MP_OBJ_NEW_SMALL_INT(lhs_val * rhs_val); + lhs_val = int_res; } + break; } case MP_BINARY_OP_FLOOR_DIVIDE: case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: @@ -556,19 +554,19 @@ mp_obj_t MICROPY_WRAP_MP_BINARY_OP(mp_binary_op)(mp_binary_op_t op, mp_obj_t lhs mp_int_t ans = 1; while (rhs_val > 0) { if (rhs_val & 1) { - if (mp_small_int_mul_overflow(ans, lhs_val)) { + if (mp_mul_mp_int_t_overflow(ans, lhs_val, &ans)) { goto power_overflow; } - ans *= lhs_val; } if (rhs_val == 1) { break; } rhs_val /= 2; - if (mp_small_int_mul_overflow(lhs_val, lhs_val)) { + mp_int_t int_res; + if (mp_mul_mp_int_t_overflow(lhs_val, lhs_val, &int_res)) { goto power_overflow; } - lhs_val *= lhs_val; + lhs_val = int_res; } lhs_val = ans; } @@ -735,8 +733,8 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("object not callable")); #else - // CIRCUITPY-CHANGE: use new raise function and different message - mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object is not callable"), mp_obj_get_type_qstr(fun_in)); + // CIRCUITPY-CHANGE: more specific mp_raise + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object isn't callable"), mp_obj_get_type_qstr(fun_in)); #endif } @@ -750,7 +748,7 @@ mp_obj_t mp_call_method_n_kw(size_t n_args, size_t n_kw, const mp_obj_t *args) { // This function only needs to be exposed externally when in stackless mode. #if !MICROPY_STACKLESS -STATIC +static #endif // CIRCUITPY-CHANGE: PLACE_IN_ITCM void PLACE_IN_ITCM(mp_call_prepare_args_n_kw_var)(bool have_self, size_t n_args_n_kw, const mp_obj_t *args, mp_call_args_t *out_args) { @@ -964,7 +962,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob // unpacked items are stored in reverse order into the array pointed to by items // CIRCUITPY-CHANGE: noline -void __attribute__((noinline, )) mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { +MP_NOINLINE void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) { size_t seq_len; if (mp_obj_is_type(seq_in, &mp_type_tuple) || mp_obj_is_type(seq_in, &mp_type_list)) { mp_obj_t *seq_items; @@ -1102,7 +1100,7 @@ typedef struct _mp_obj_checked_fun_t { mp_obj_t fun; } mp_obj_checked_fun_t; -STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { +static mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in); if (n_args > 0) { const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]); @@ -1114,14 +1112,14 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c return mp_call_function_n_kw(self->fun, n_args, n_kw, args); } -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( mp_type_checked_fun, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF, call, checked_fun_call ); -STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) { +static mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun) { mp_obj_checked_fun_t *o = mp_obj_malloc(mp_obj_checked_fun_t, &mp_type_checked_fun); o->type = type; o->fun = fun; @@ -1173,6 +1171,10 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t // base type (which is what is passed in the `type` argument to this function). if (self != MP_OBJ_NULL) { type = mp_obj_get_type(self); + if (type == &mp_type_type) { + // `self` is already a type, so use `self` directly. + type = MP_OBJ_TO_PTR(self); + } } dest[0] = ((mp_obj_static_class_method_t *)MP_OBJ_TO_PTR(member))->fun; dest[1] = MP_OBJ_FROM_PTR(type); @@ -1285,6 +1287,19 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("type object '%q' has no attribute '%q'"), ((mp_obj_type_t *)MP_OBJ_TO_PTR(base))->name, attr); + #if MICROPY_MODULE___ALL__ && MICROPY_ERROR_REPORTING >= MICROPY_ERROR_REPORTING_DETAILED + } else if (mp_obj_is_type(base, &mp_type_module)) { + // report errors in __all__ as done by CPython + mp_obj_t dest_name[2]; + qstr module_name = MP_QSTR_; + mp_load_method_maybe(base, MP_QSTR___name__, dest_name); + if (mp_obj_is_qstr(dest_name[0])) { + module_name = mp_obj_str_get_qstr(dest_name[0]); + } + mp_raise_msg_varg(&mp_type_AttributeError, + MP_ERROR_TEXT("module '%q' has no attribute '%q'"), + module_name, attr); + #endif } else { mp_raise_msg_varg(&mp_type_AttributeError, MP_ERROR_TEXT("'%s' object has no attribute '%q'"), @@ -1409,14 +1424,14 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("object not iterable")); #else - // CIRCUITPY-CHANGE: raise function + // CIRCUITPY-CHANGE: more specific mp_raise mp_raise_TypeError_varg( - MP_ERROR_TEXT("'%q' object is not iterable"), mp_obj_get_type_qstr(o_in)); + MP_ERROR_TEXT("'%q' object isn't iterable"), mp_obj_get_type_qstr(o_in)); #endif } -STATIC mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) { +static mp_fun_1_t type_get_iternext(const mp_obj_type_t *type) { if ((type->flags & MP_TYPE_FLAG_ITER_IS_STREAM) == MP_TYPE_FLAG_ITER_IS_STREAM) { return mp_stream_unbuffered_iter; } else if (type->flags & MP_TYPE_FLAG_ITER_IS_ITERNEXT) { @@ -1446,8 +1461,8 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("object not an iterator")); #else - // CIRCUITPY-CHANGE: raise function - mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object is not an iterator"), + // CIRCUITPY-CHANGE: more specific mp_raise + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object isn't an iterator"), mp_obj_get_type_qstr(o_in)); #endif } @@ -1457,7 +1472,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { // will always return MP_OBJ_STOP_ITERATION instead of raising StopIteration() (or any subclass thereof) // may raise other exceptions mp_obj_t mp_iternext(mp_obj_t o_in) { - MP_STACK_CHECK(); // enumerate, filter, map and zip can recursively call mp_iternext + mp_cstack_check(); // enumerate, filter, map and zip can recursively call mp_iternext const mp_obj_type_t *type = mp_obj_get_type(o_in); if (TYPE_HAS_ITERNEXT(type)) { MP_STATE_THREAD(stop_iteration_arg) = MP_OBJ_NULL; @@ -1484,8 +1499,8 @@ mp_obj_t mp_iternext(mp_obj_t o_in) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE mp_raise_TypeError(MP_ERROR_TEXT("object not an iterator")); #else - // CIRCUITPY-CHANGE: raise function - mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object is not an iterator"), + // CIRCUITPY-CHANGE: more specific mp_raise + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object isn't an iterator"), mp_obj_get_type_qstr(o_in)); #endif } @@ -1603,7 +1618,7 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { // build args array mp_obj_t args[5]; args[0] = MP_OBJ_NEW_QSTR(name); - args[1] = mp_const_none; // TODO should be globals + args[1] = MP_OBJ_FROM_PTR(mp_globals_get()); // globals of the current context args[2] = mp_const_none; // TODO should be locals args[3] = fromlist; args[4] = level; @@ -1623,20 +1638,17 @@ mp_obj_t mp_import_name(qstr name, mp_obj_t fromlist, mp_obj_t level) { } // CIRCUITPY-CHANGE: noinline -mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) { +MP_NOINLINE mp_obj_t mp_import_from(mp_obj_t module, qstr name) { DEBUG_printf("import from %p %s\n", module, qstr_str(name)); mp_obj_t dest[2]; mp_load_method_maybe(module, name, dest); - if (dest[1] != MP_OBJ_NULL) { - // Hopefully we can't import bound method from an object - import_error: - mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name); - } - - if (dest[0] != MP_OBJ_NULL) { + // Importing a bound method from a class instance. + return mp_obj_new_bound_meth(dest[0], dest[1]); + } else if (dest[0] != MP_OBJ_NULL) { + // Importing a function or attribute. return dest[0]; } @@ -1669,33 +1681,36 @@ mp_obj_t __attribute__((noinline, )) mp_import_from(mp_obj_t module, qstr name) goto import_error; #endif + +import_error: + mp_raise_msg_varg(&mp_type_ImportError, MP_ERROR_TEXT("can't import name %q"), name); } void mp_import_all(mp_obj_t module) { DEBUG_printf("import all %p\n", module); - // CIRCUITPY-CHANGE: displayio name changes; remove in 10.0 - #if CIRCUITPY_DISPLAYIO && CIRCUITPY_WARNINGS - if (module == &displayio_module) { - #if CIRCUITPY_BUSDISPLAY - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_Display, MP_QSTR_displayio, MP_QSTR_busdisplay); - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_Display, MP_QSTR_BusDisplay); - #endif - #if CIRCUITPY_EPAPERDISPLAY - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_EPaperDisplay, MP_QSTR_displayio, MP_QSTR_epaperdisplay); - #endif - #if CIRCUITPY_FOURWIRE - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_FourWire, MP_QSTR_displayio, MP_QSTR_fourwire); - #endif - #if CIRCUITPY_I2CDISPLAYBUS - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q moved from %q to %q"), MP_QSTR_I2CDisplay, MP_QSTR_displayio, MP_QSTR_i2cdisplaybus); - warnings_warn(&mp_type_FutureWarning, MP_ERROR_TEXT("%q renamed %q"), MP_QSTR_I2CDisplay, MP_QSTR_I2CDisplayBus); - #endif + mp_map_t *map = &mp_obj_module_get_globals(module)->map; + + #if MICROPY_MODULE___ALL__ + mp_map_elem_t *elem = mp_map_lookup(map, MP_OBJ_NEW_QSTR(MP_QSTR___all__), MP_MAP_LOOKUP); + if (elem != NULL) { + // When __all__ is defined, we must explicitly load all specified + // symbols, possibly invoking the module __getattr__ function + size_t len; + mp_obj_t *items; + mp_obj_get_array(elem->value, &len, &items); + for (size_t i = 0; i < len; i++) { + qstr qname = mp_obj_str_get_qstr(items[i]); + mp_obj_t dest[2]; + mp_load_method(module, qname, dest); + mp_store_name(qname, dest[0]); + } + return; } #endif - // TODO: Support __all__ - mp_map_t *map = &mp_obj_module_get_globals(module)->map; + // By default, the set of public names includes all names found in the module's + // namespace which do not begin with an underscore character ('_') for (size_t i = 0; i < map->alloc; i++) { if (mp_map_slot_is_filled(map, i)) { // Entry in module global scope may be generated programmatically @@ -1730,10 +1745,13 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i mp_obj_t module_fun = mp_compile(&parse_tree, source_name, parse_input_kind == MP_PARSE_SINGLE_INPUT); mp_obj_t ret; - if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) { + #if MICROPY_PY_BUILTINS_COMPILE && MICROPY_PY_BUILTINS_CODE == MICROPY_PY_BUILTINS_CODE_MINIMUM + if (globals == NULL) { // for compile only, return value is the module function ret = module_fun; - } else { + } else + #endif + { // execute module function and get return value ret = mp_call_function_0(module_fun); } @@ -1748,7 +1766,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i #endif // MICROPY_ENABLE_COMPILER // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void m_malloc_fail(size_t num_bytes) { +MP_COLD MP_NORETURN void m_malloc_fail(size_t num_bytes) { DEBUG_printf("memory allocation failed, allocating %u bytes\n", (uint)num_bytes); #if MICROPY_ENABLE_GC if (gc_is_locked()) { @@ -1762,29 +1780,29 @@ NORETURN MP_COLD void m_malloc_fail(size_t num_bytes) { #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_type(const mp_obj_type_t *exc_type) { +MP_COLD MP_NORETURN void mp_raise_type(const mp_obj_type_t *exc_type) { nlr_raise(mp_obj_new_exception(exc_type)); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_ValueError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_ValueError_no_msg(void) { mp_raise_type(&mp_type_ValueError); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_TypeError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_TypeError_no_msg(void) { mp_raise_type(&mp_type_TypeError); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_NotImplementedError_no_msg(void) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError_no_msg(void) { mp_raise_type(&mp_type_NotImplementedError); } #else // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg) { if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { @@ -1793,24 +1811,24 @@ NORETURN MP_COLD void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_t } // CIRCUITPY-CHANGE: new function for use below. -NORETURN MP_COLD void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr) { +MP_COLD MP_NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr) { mp_obj_t exception = mp_obj_new_exception_msg_vlist(exc_type, fmt, argptr); nlr_raise(exception); } // CIRCUITPY-CHANGE: MP_COLD and use mp_raise_msg_vlist() -NORETURN MP_COLD void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(exc_type, fmt, argptr); va_end(argptr); } -NORETURN MP_COLD void mp_raise_ValueError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ValueError, msg); } -NORETURN MP_COLD void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg) { +MP_COLD MP_NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg) { if (msg == NULL) { nlr_raise(mp_obj_new_exception(exc_type)); } else { @@ -1819,17 +1837,17 @@ NORETURN MP_COLD void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_AttributeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_AttributeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_RuntimeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_RuntimeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_RuntimeError, fmt, argptr); @@ -1837,17 +1855,17 @@ NORETURN MP_COLD void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ImportError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ImportError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_IndexError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_IndexError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_IndexError, fmt, argptr); @@ -1855,7 +1873,7 @@ NORETURN MP_COLD void mp_raise_IndexError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_ValueError, fmt, argptr); @@ -1863,12 +1881,12 @@ NORETURN MP_COLD void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_TypeError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_TypeError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_TypeError, fmt, argptr); @@ -1876,12 +1894,12 @@ NORETURN MP_COLD void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_msg(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_OSError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { +MP_COLD MP_NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { mp_obj_t args[2] = { MP_OBJ_NEW_SMALL_INT(errno_), str, @@ -1890,7 +1908,7 @@ NORETURN MP_COLD void mp_raise_OSError_errno_str(int errno_, mp_obj_t str) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_OSError, fmt, argptr); @@ -1898,21 +1916,23 @@ NORETURN MP_COLD void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...) { } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ConnectionError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_ConnectionError, msg); } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_BrokenPipeError(void) { +MP_COLD MP_NORETURN void mp_raise_BrokenPipeError(void) { mp_raise_type_arg(&mp_type_BrokenPipeError, MP_OBJ_NEW_SMALL_INT(MP_EPIPE)); } -NORETURN MP_COLD void mp_raise_NotImplementedError(mp_rom_error_text_t msg) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_NotImplementedError, msg); } +#endif + // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_NotImplementedError, fmt, argptr); @@ -1920,7 +1940,7 @@ NORETURN MP_COLD void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) { +MP_COLD MP_NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_raise_msg_vlist(&mp_type_OverflowError, fmt, argptr); @@ -1928,12 +1948,11 @@ NORETURN MP_COLD void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...) } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg) { +MP_COLD MP_NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg) { nlr_raise(mp_obj_new_exception_arg1(exc_type, arg)); } -// CIRCUITPY-CHANGE: MP_COLD -NORETURN void mp_raise_StopIteration(mp_obj_t arg) { +MP_NORETURN void mp_raise_StopIteration(mp_obj_t arg) { if (arg == MP_OBJ_NULL) { mp_raise_type(&mp_type_StopIteration); } else { @@ -1941,7 +1960,7 @@ NORETURN void mp_raise_StopIteration(mp_obj_t arg) { } } -NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { +MP_NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { #if MICROPY_ERROR_REPORTING <= MICROPY_ERROR_REPORTING_TERSE (void)arg; mp_raise_TypeError(MP_ERROR_TEXT("can't convert to int")); @@ -1952,12 +1971,12 @@ NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg) { } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_OSError(int errno_) { +MP_COLD MP_NORETURN void mp_raise_OSError(int errno_) { mp_raise_type_arg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno_)); } // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_OSError_with_filename(int errno_, const char *filename) { +MP_COLD MP_NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename) { vstr_t vstr; vstr_init(&vstr, 32); vstr_printf(&vstr, "can't open %s", filename); @@ -1967,13 +1986,12 @@ NORETURN MP_COLD void mp_raise_OSError_with_filename(int errno_, const char *fil } // CIRCUITPY-CHANGE: added -NORETURN MP_COLD void mp_raise_ZeroDivisionError(void) { +MP_COLD MP_NORETURN void mp_raise_ZeroDivisionError(void) { mp_raise_msg(&mp_type_ZeroDivisionError, MP_ERROR_TEXT("division by zero")); } #if MICROPY_STACK_CHECK || MICROPY_ENABLE_PYSTACK // CIRCUITPY-CHANGE: MP_COLD -NORETURN MP_COLD void mp_raise_recursion_depth(void) { +MP_COLD MP_NORETURN void mp_raise_recursion_depth(void) { mp_raise_RuntimeError(MP_ERROR_TEXT("maximum recursion depth exceeded")); } #endif -#endif diff --git a/py/runtime.h b/py/runtime.h index 379dd65c81e36..22ed9c3eaf9b8 100644 --- a/py/runtime.h +++ b/py/runtime.h @@ -30,17 +30,19 @@ #include "py/mpstate.h" #include "py/pystack.h" +#include "py/cstack.h" // CIRCUITPY-CHANGE #include "supervisor/linker.h" #include "supervisor/shared/translate/translate.h" // For use with mp_call_function_1_from_nlr_jump_callback. +// Initialize an nlr_jump_callback_node_call_function_1_t struct for use with +// nlr_push_jump_callback(&ctx.callback, mp_call_function_1_from_nlr_jump_callback); #define MP_DEFINE_NLR_JUMP_CALLBACK_FUNCTION_1(ctx, f, a) \ - nlr_jump_callback_node_call_function_1_t ctx = { \ - .func = (void (*)(void *))(f), \ - .arg = (a), \ - } + nlr_jump_callback_node_call_function_1_t ctx; \ + ctx.func = (void (*)(void *))(f); \ + ctx.arg = (a) typedef enum { MP_VM_RETURN_NORMAL, @@ -57,6 +59,12 @@ typedef enum { MP_ARG_KW_ONLY = 0x200, } mp_arg_flag_t; +typedef enum { + MP_HANDLE_PENDING_CALLBACKS_ONLY, + MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS, + MP_HANDLE_PENDING_CALLBACKS_AND_CLEAR_EXCEPTIONS, +} mp_handle_pending_behaviour_t; + typedef union _mp_arg_val_t { bool u_bool; mp_int_t u_int; @@ -105,7 +113,14 @@ void mp_sched_keyboard_interrupt(void); #if MICROPY_ENABLE_VM_ABORT void mp_sched_vm_abort(void); #endif -void mp_handle_pending(bool raise_exc); + +void mp_handle_pending_internal(mp_handle_pending_behaviour_t behavior); + +static inline void mp_handle_pending(bool raise_exc) { + mp_handle_pending_internal(raise_exc ? + MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS : + MP_HANDLE_PENDING_CALLBACKS_AND_CLEAR_EXCEPTIONS); +} #if MICROPY_ENABLE_SCHEDULER void mp_sched_lock(void); @@ -133,7 +148,7 @@ void mp_event_wait_indefinite(void); void mp_event_wait_ms(mp_uint_t timeout_ms); // extra printing method specifically for mp_obj_t's which are integral type -int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec); +int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, unsigned base, int base_char, int flags, char fill, int width, int prec); void mp_arg_check_num_sig(size_t n_args, size_t n_kw, uint32_t sig); static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_args_max, bool takes_kw) { @@ -141,11 +156,11 @@ static inline void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_mi } void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, size_t n_allowed, const mp_arg_t *allowed, mp_arg_val_t *out_vals); -NORETURN void mp_arg_error_terse_mismatch(void); -NORETURN void mp_arg_error_unimpl_kw(void); +MP_NORETURN void mp_arg_error_terse_mismatch(void); +MP_NORETURN void mp_arg_error_unimpl_kw(void); // CIRCUITPY-CHANGE: arg validation routines -NORETURN void mp_arg_error_invalid(qstr arg_name); +MP_NORETURN void mp_arg_error_invalid(qstr arg_name); mp_int_t mp_arg_validate_int(mp_int_t i, mp_int_t required_i, qstr arg_name); mp_int_t mp_arg_validate_int_min(mp_int_t i, mp_int_t min, qstr arg_name); mp_int_t mp_arg_validate_int_max(mp_int_t i, mp_int_t j, qstr arg_name); @@ -183,6 +198,38 @@ static inline void mp_globals_set(mp_obj_dict_t *d) { void mp_globals_locals_set_from_nlr_jump_callback(void *ctx_in); void mp_call_function_1_from_nlr_jump_callback(void *ctx_in); +#if MICROPY_PY_THREAD +static inline void mp_thread_init_state(mp_state_thread_t *ts, size_t stack_size, mp_obj_dict_t *locals, mp_obj_dict_t *globals) { + mp_thread_set_state(ts); + + mp_cstack_init_with_top(ts + 1, stack_size); // need to include ts in root-pointer scan + + // GC starts off unlocked + ts->gc_lock_depth = 0; + + // There are no pending jump callbacks or exceptions yet + ts->nlr_top = NULL; + ts->nlr_jump_callback_top = NULL; + ts->mp_pending_exception = MP_OBJ_NULL; + + #if MICROPY_PY_SYS_SETTRACE + ts->prof_trace_callback = MP_OBJ_NULL; + ts->prof_callback_is_executing = false; + ts->current_code_state = NULL; + #endif + + // If locals/globals are not given, inherit from main thread + if (locals == NULL) { + locals = mp_state_ctx.thread.dict_locals; + } + if (globals == NULL) { + globals = mp_state_ctx.thread.dict_globals; + } + mp_locals_set(locals); + mp_globals_set(globals); +} +#endif + mp_obj_t mp_load_name(qstr qst); mp_obj_t mp_load_global(qstr qst); mp_obj_t mp_load_build_class(void); @@ -248,10 +295,10 @@ mp_obj_t mp_import_from(mp_obj_t module, qstr name); void mp_import_all(mp_obj_t module); #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NONE -NORETURN void mp_raise_type(const mp_obj_type_t *exc_type); -NORETURN void mp_raise_ValueError_no_msg(void); -NORETURN void mp_raise_TypeError_no_msg(void); -NORETURN void mp_raise_NotImplementedError_no_msg(void); +MP_NORETURN void mp_raise_type(const mp_obj_type_t *exc_type); +MP_NORETURN void mp_raise_ValueError_no_msg(void); +MP_NORETURN void mp_raise_TypeError_no_msg(void); +MP_NORETURN void mp_raise_NotImplementedError_no_msg(void); #define mp_raise_msg(exc_type, msg) mp_raise_type(exc_type) #define mp_raise_msg_varg(exc_type, ...) mp_raise_type(exc_type) #define mp_raise_ValueError(msg) mp_raise_ValueError_no_msg() @@ -259,46 +306,46 @@ NORETURN void mp_raise_NotImplementedError_no_msg(void); #define mp_raise_NotImplementedError(msg) mp_raise_NotImplementedError_no_msg() #else #define mp_raise_type(exc_type) mp_raise_msg(exc_type, NULL) -NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); -NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); -NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); #endif // CIRCUITPY-CHANGE: new mp_raise routines -NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); -NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); -NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt +MP_NORETURN void mp_raise_type_arg(const mp_obj_type_t *exc_type, mp_obj_t arg); +MP_NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_msg_varg(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt , ...); -NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr); +MP_NORETURN void mp_raise_msg_vlist(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, va_list argptr); // Only use this string version in native mpy files. Otherwise, use the compressed string version. -NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg); - -NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_BrokenPipeError(void); -NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg); -NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg); -NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg); -NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t msg, ...); -NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); -NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); -NORETURN void mp_raise_OSError(int errno_); -NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg); -NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); -NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_recursion_depth(void); -NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_StopIteration(mp_obj_t arg); -NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); -NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg); -NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); -NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_ZeroDivisionError(void); +MP_NORETURN void mp_raise_msg_str(const mp_obj_type_t *exc_type, const char *msg); + +MP_NORETURN void mp_raise_AttributeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_BrokenPipeError(void); +MP_NORETURN void mp_raise_ConnectionError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_ImportError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_IndexError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_IndexError_varg(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_NotImplementedError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_NotImplementedError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_OSError_errno_str(int errno_, mp_obj_t str); +MP_NORETURN void mp_raise_OSError(int errno_); +MP_NORETURN void mp_raise_OSError_msg(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_OSError_msg_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_OSError_with_filename(int errno_, const char *filename); +MP_NORETURN void mp_raise_OverflowError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_recursion_depth(void); +MP_NORETURN void mp_raise_RuntimeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_RuntimeError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_StopIteration(mp_obj_t arg); +MP_NORETURN void mp_raise_TypeError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_TypeError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_TypeError_int_conversion(mp_const_obj_t arg); +MP_NORETURN void mp_raise_ValueError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_ValueError_varg(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_ZeroDivisionError(void); #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG #undef mp_check_self diff --git a/py/runtime0.h b/py/runtime0.h index 87a7c6fd1579d..86c48a6eaa7d6 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -26,12 +26,13 @@ #ifndef MICROPY_INCLUDED_PY_RUNTIME0_H #define MICROPY_INCLUDED_PY_RUNTIME0_H -// CIRCUITPY-CHANGE -#include "mpconfig.h" - -// The first four must fit in 8 bits, see emitbc.c -// The remaining must fit in 16 bits, see scope.h -// and must match definitions in mpy-tool.py and mpy_ld.py +// These constants are used by: +// - mp_raw_code_t::is_generator (only MP_SCOPE_FLAG_GENERATOR) +// CIRCUITPY-CHANGE: distinguish generator and async +// - mp_raw_code_t::is_generator (only MP_SCOPE_FLAG_ASYNC) +// - scope_t::scope_flags (16 bits) +// - MP_BC_PRELUDE_SIG_ENCODE macro, masked by MP_SCOPE_FLAG_ALL_SIG (4 bits) +// - tools/mpy_ld.py, when generating mpy files (maximum 7 bits) #define MP_SCOPE_FLAG_ALL_SIG (0x1f) #define MP_SCOPE_FLAG_GENERATOR (0x01) #define MP_SCOPE_FLAG_VARKEYWORDS (0x02) diff --git a/py/runtime_utils.c b/py/runtime_utils.c index 98252c3122048..33da558e30f08 100644 --- a/py/runtime_utils.c +++ b/py/runtime_utils.c @@ -53,3 +53,59 @@ mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2 return MP_OBJ_NULL; } } + +#if !MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res) { + bool overflow; + + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + overflow = (x > (LLONG_MAX / y)); + } else { // x positive, y nonpositive + overflow = (y < (LLONG_MIN / x)); + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + overflow = (x < (LLONG_MIN / y)); + } else { // x and y are nonpositive + overflow = (x != 0 && y < (LLONG_MAX / x)); + } // End if x and y are nonpositive + } // End if x is nonpositive + + if (!overflow) { + *res = x * y; + } + + return overflow; +} + +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + if (x > (MP_INT_MAX / y)) { + return true; + } + } else { // x positive, y nonpositive + if (y < (MP_INT_MIN / x)) { + return true; + } + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + if (x < (MP_INT_MIN / y)) { + return true; + } + } else { // x and y are nonpositive + if (x != 0 && y < (MP_INT_MAX / x)) { + return true; + } + } // End if x and y are nonpositive + } // End if x is nonpositive + + // Result doesn't overflow + *res = x * y; + return false; +} +#endif diff --git a/py/scheduler.c b/py/scheduler.c index cb5f1043cc4cd..ee9cd96b331a6 100644 --- a/py/scheduler.c +++ b/py/scheduler.c @@ -29,6 +29,10 @@ #include "py/mphal.h" #include "py/runtime.h" +#ifdef __ZEPHYR__ +#include +#endif + // Schedules an exception on the main thread (for exceptions "thrown" by async // sources such as interrupts and UNIX signal handlers). void MICROPY_WRAP_MP_SCHED_EXCEPTION(mp_sched_exception)(mp_obj_t exc) { @@ -50,6 +54,10 @@ void MICROPY_WRAP_MP_SCHED_KEYBOARD_INTERRUPT(mp_sched_keyboard_interrupt)(void) // CIRCUITPY-CHANGE: traceback differences MP_STATE_VM(mp_kbd_exception).traceback = (mp_obj_traceback_t *)&mp_const_empty_traceback_obj; mp_sched_exception(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))); + + #ifdef __ZEPHYR__ + k_sem_give(&mp_interrupt_sem); + #endif } #endif @@ -89,17 +97,21 @@ static inline void mp_sched_run_pending(void) { #if MICROPY_SCHEDULER_STATIC_NODES // Run all pending C callbacks. - while (MP_STATE_VM(sched_head) != NULL) { - mp_sched_node_t *node = MP_STATE_VM(sched_head); - MP_STATE_VM(sched_head) = node->next; - if (MP_STATE_VM(sched_head) == NULL) { - MP_STATE_VM(sched_tail) = NULL; - } - mp_sched_callback_t callback = node->callback; - node->callback = NULL; - MICROPY_END_ATOMIC_SECTION(atomic_state); - callback(node); - atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + mp_sched_node_t *original_tail = MP_STATE_VM(sched_tail); + if (original_tail != NULL) { + mp_sched_node_t *node; + do { + node = MP_STATE_VM(sched_head); + MP_STATE_VM(sched_head) = node->next; + if (MP_STATE_VM(sched_head) == NULL) { + MP_STATE_VM(sched_tail) = NULL; + } + mp_sched_callback_t callback = node->callback; + node->callback = NULL; + MICROPY_END_ATOMIC_SECTION(atomic_state); + callback(node); + atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); + } while (node != original_tail); // Don't execute any callbacks scheduled during this run } #endif @@ -210,24 +222,27 @@ MP_REGISTER_ROOT_POINTER(mp_sched_item_t sched_queue[MICROPY_SCHEDULER_DEPTH]); // Called periodically from the VM or from "waiting" code (e.g. sleep) to // process background tasks and pending exceptions (e.g. KeyboardInterrupt). -void mp_handle_pending(bool raise_exc) { +void mp_handle_pending_internal(mp_handle_pending_behaviour_t behavior) { + bool handle_exceptions = (behavior != MP_HANDLE_PENDING_CALLBACKS_ONLY); + bool raise_exceptions = (behavior == MP_HANDLE_PENDING_CALLBACKS_AND_EXCEPTIONS); + // Handle pending VM abort. #if MICROPY_ENABLE_VM_ABORT - if (MP_STATE_VM(vm_abort) && mp_thread_is_main_thread()) { + if (handle_exceptions && MP_STATE_VM(vm_abort) && mp_thread_is_main_thread()) { MP_STATE_VM(vm_abort) = false; - if (raise_exc && nlr_get_abort() != NULL) { + if (raise_exceptions && nlr_get_abort() != NULL) { nlr_jump_abort(); } } #endif // Handle any pending exception. - if (MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { + if (handle_exceptions && MP_STATE_THREAD(mp_pending_exception) != MP_OBJ_NULL) { mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_obj_t obj = MP_STATE_THREAD(mp_pending_exception); if (obj != MP_OBJ_NULL) { MP_STATE_THREAD(mp_pending_exception) = MP_OBJ_NULL; - if (raise_exc) { + if (raise_exceptions) { MICROPY_END_ATOMIC_SECTION(atomic_state); nlr_raise(obj); } @@ -237,7 +252,13 @@ void mp_handle_pending(bool raise_exc) { // Handle any pending callbacks. #if MICROPY_ENABLE_SCHEDULER - if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) { + bool run_scheduler = (MP_STATE_VM(sched_state) == MP_SCHED_PENDING); + #if MICROPY_PY_THREAD && !MICROPY_PY_THREAD_GIL + // Avoid races by running the scheduler on the main thread, only. + // (Not needed if GIL enabled, as GIL ensures thread safety here.) + run_scheduler = run_scheduler && mp_thread_is_main_thread(); + #endif + if (run_scheduler) { mp_sched_run_pending(); } #endif @@ -263,10 +284,6 @@ void mp_event_wait_indefinite(void) { MICROPY_EVENT_POLL_HOOK #else mp_event_handle_nowait(); - - // CIRCUITPY-CHANGE: don't starve CircuitPython background tasks - RUN_BACKGROUND_TASKS; - MICROPY_INTERNAL_WFE(-1); #endif } @@ -279,10 +296,6 @@ void mp_event_wait_ms(mp_uint_t timeout_ms) { MICROPY_EVENT_POLL_HOOK #else mp_event_handle_nowait(); - - // CIRCUITPY-CHANGE: don't starve CircuitPython background tasks - RUN_BACKGROUND_TASKS; - MICROPY_INTERNAL_WFE(timeout_ms); #endif } diff --git a/py/scope.c b/py/scope.c index 8fc0943289b4f..4893e7cc4e5e1 100644 --- a/py/scope.c +++ b/py/scope.c @@ -31,7 +31,9 @@ #if MICROPY_ENABLE_COMPILER // These low numbered qstrs should fit in 8 bits. See assertions below. -STATIC const uint8_t scope_simple_name_table[] = { +// The (unescaped) names appear in `unsorted_str_list` in the QSTR +// generator script py/makeqstrdata.py to ensure they are assigned low numbers. +static const uint8_t scope_simple_name_table[] = { [SCOPE_MODULE] = MP_QSTR__lt_module_gt_, [SCOPE_LAMBDA] = MP_QSTR__lt_lambda_gt_, [SCOPE_LIST_COMP] = MP_QSTR__lt_listcomp_gt_, @@ -111,7 +113,7 @@ id_info_t *scope_find_global(scope_t *scope, qstr qst) { return scope_find(scope, qst); } -STATIC void scope_close_over_in_parents(scope_t *scope, qstr qst) { +static void scope_close_over_in_parents(scope_t *scope, qstr qst) { assert(scope->parent != NULL); // we should have at least 1 parent for (scope_t *s = scope->parent;; s = s->parent) { assert(s->parent != NULL); // we should not get to the outer scope diff --git a/py/scope.h b/py/scope.h index e7d2a304f79f3..927c4a7b93e2b 100644 --- a/py/scope.h +++ b/py/scope.h @@ -76,6 +76,9 @@ typedef struct _scope_t { struct _scope_t *next; mp_parse_node_t pn; mp_raw_code_t *raw_code; + #if MICROPY_DEBUG_PRINTERS + size_t raw_code_data_len; // for mp_bytecode_print + #endif uint16_t simple_name; // a qstr uint16_t scope_flags; // see runtime0.h uint16_t emit_options; // see emitglue.h diff --git a/py/sequence.c b/py/sequence.c index cc89d1b0b05a0..6bbc62f0f7fb1 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -34,18 +34,13 @@ #define SWAP(type, var1, var2) { type t = var2; var2 = var1; var1 = t; } // CIRCUITPY-CHANGE: detect sequence overflow -#if __GNUC__ < 5 -// n.b. does not actually detect overflow! -#define __builtin_mul_overflow(a, b, x) (*(x) = (a) * (b), false) -#endif - // Detect when a multiply causes an overflow. size_t mp_seq_multiply_len(size_t item_sz, size_t len) { - size_t new_len; - if (__builtin_mul_overflow(item_sz, len, &new_len)) { + mp_int_t new_len; + if (mp_mul_mp_int_t_overflow(item_sz, len, &new_len)) { mp_raise_msg(&mp_type_OverflowError, MP_ERROR_TEXT("small int overflow")); } - return new_len; + return (size_t)new_len; } // Implements backend of sequence * integer operation. Assumes elements are @@ -78,11 +73,7 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice return indexes->step == 1; } -#endif - -mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) { - (void)len; // TODO can we remove len from the arg list? - +mp_obj_t mp_seq_extract_slice(const mp_obj_t *seq, mp_bound_slice_t *indexes) { mp_int_t start = indexes->start, stop = indexes->stop; mp_int_t step = indexes->step; @@ -102,6 +93,8 @@ mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t return res; } +#endif + // Special-case comparison function for sequences of bytes // Don't pass MP_BINARY_OP_NOT_EQUAL here bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2) { diff --git a/py/showbc.c b/py/showbc.c index f9c334b93bbbb..792fccd013383 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -83,7 +83,7 @@ DECODE_UINT; \ unum = (mp_uint_t)obj_table[unum] -void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, const mp_module_constants_t *cm) { +void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, size_t fun_data_len, const mp_module_constants_t *cm) { const byte *ip_start = rc->fun_data; const byte *ip = rc->fun_data; @@ -100,13 +100,13 @@ void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, const m qstr source_file = cm->source_file; #endif mp_printf(print, "File %s, code block '%s' (descriptor: %p, bytecode @%p %u bytes)\n", - qstr_str(source_file), qstr_str(block_name), rc, ip_start, (unsigned)rc->fun_data_len); + qstr_str(source_file), qstr_str(block_name), rc, ip_start, (unsigned)fun_data_len); // raw bytecode dump size_t prelude_size = ip - ip_start + n_info + n_cell; mp_printf(print, "Raw bytecode (code_info_size=%u, bytecode_size=%u):\n", - (unsigned)prelude_size, (unsigned)(rc->fun_data_len - prelude_size)); - for (size_t i = 0; i < rc->fun_data_len; i++) { + (unsigned)prelude_size, (unsigned)(fun_data_len - prelude_size)); + for (size_t i = 0; i < fun_data_len; i++) { if (i > 0 && i % 16 == 0) { mp_printf(print, "\n"); } @@ -144,21 +144,13 @@ void mp_bytecode_print(const mp_print_t *print, const mp_raw_code_t *rc, const m mp_uint_t source_line = 1; mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); for (const byte *ci = code_info; ci < line_info_top;) { - if ((ci[0] & 0x80) == 0) { - // 0b0LLBBBBB encoding - bc += ci[0] & 0x1f; - source_line += ci[0] >> 5; - ci += 1; - } else { - // 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) - bc += ci[0] & 0xf; - source_line += ((ci[0] << 4) & 0x700) | ci[1]; - ci += 2; - } + mp_code_lineinfo_t decoded = mp_bytecode_decode_lineinfo(&ci); + bc += decoded.bc_increment; + source_line += decoded.line_increment; mp_printf(print, " bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line); } } - mp_bytecode_print2(print, ip, rc->fun_data_len - prelude_size, rc->children, cm); + mp_bytecode_print2(print, ip, fun_data_len - prelude_size, rc->children, cm); } const byte *mp_bytecode_print_str(const mp_print_t *print, const byte *ip_start, const byte *ip, mp_raw_code_t *const *child_table, const mp_module_constants_t *cm) { diff --git a/py/smallint.c b/py/smallint.c index aa542ca7bf29a..eb99b58667a07 100644 --- a/py/smallint.c +++ b/py/smallint.c @@ -26,32 +26,6 @@ #include "py/smallint.h" -bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) { - // Check for multiply overflow; see CERT INT32-C - if (x > 0) { // x is positive - if (y > 0) { // x and y are positive - if (x > (MP_SMALL_INT_MAX / y)) { - return true; - } - } else { // x positive, y nonpositive - if (y < (MP_SMALL_INT_MIN / x)) { - return true; - } - } // x positive, y nonpositive - } else { // x is nonpositive - if (y > 0) { // x is nonpositive, y is positive - if (x < (MP_SMALL_INT_MIN / y)) { - return true; - } - } else { // x and y are nonpositive - if (x != 0 && y < (MP_SMALL_INT_MAX / x)) { - return true; - } - } // End if x and y are nonpositive - } // End if x is nonpositive - return false; -} - mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) { // Python specs require that mod has same sign as second operand dividend %= divisor; diff --git a/py/smallint.h b/py/smallint.h index 584e0018d1ba3..ec5b0af3b2867 100644 --- a/py/smallint.h +++ b/py/smallint.h @@ -68,7 +68,6 @@ // The number of bits in a MP_SMALL_INT including the sign bit. #define MP_SMALL_INT_BITS (MP_IMAX_BITS(MP_SMALL_INT_MAX) + 1) -bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y); mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor); mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom); diff --git a/py/stackctrl.c b/py/stackctrl.c index f192fad0534de..0372a1db35007 100644 --- a/py/stackctrl.c +++ b/py/stackctrl.c @@ -24,7 +24,12 @@ * THE SOFTWARE. */ +// This API is deprecated, please use py/cstack.h instead + #include "py/runtime.h" + +#if !MICROPY_PREVIEW_VERSION_2 + #include "py/stackctrl.h" void mp_stack_ctrl_init(void) { @@ -68,3 +73,5 @@ void PLACE_IN_ITCM(mp_stack_check)(void) { } #endif // MICROPY_STACK_CHECK + +#endif // !MICROPY_PREVIEW_VERSION_2 diff --git a/py/stackctrl.h b/py/stackctrl.h index 63667f8a5512a..5ff24798103b0 100644 --- a/py/stackctrl.h +++ b/py/stackctrl.h @@ -26,8 +26,12 @@ #ifndef MICROPY_INCLUDED_PY_STACKCTRL_H #define MICROPY_INCLUDED_PY_STACKCTRL_H +// This API is deprecated, please use py/cstack.h instead + #include "py/mpconfig.h" +#if !MICROPY_PREVIEW_VERSION_2 + void mp_stack_ctrl_init(void); void mp_stack_set_top(void *top); mp_uint_t mp_stack_usage(void); @@ -43,7 +47,9 @@ void mp_stack_check(void); #define mp_stack_set_limit(limit) (void)(limit) #define MP_STACK_CHECK() -#endif +#endif // MICROPY_STACK_CHECK + +#endif // !MICROPY_PREVIEW_VERSION_2 // CIRCUITPY-CHANGE: provide max stack usage #if MICROPY_MAX_STACK_USAGE diff --git a/py/stream.c b/py/stream.c index 7f62b3be9d617..520422cc92fcf 100644 --- a/py/stream.c +++ b/py/stream.c @@ -38,7 +38,7 @@ // TODO: should be in mpconfig.h #define DEFAULT_BUFFER_SIZE 256 -STATIC mp_obj_t stream_readall(mp_obj_t self_in); +static mp_obj_t stream_readall(mp_obj_t self_in); // Returns error condition in *errcode, if non-zero, return value is number of bytes written // before error condition occurred. If *errcode == 0, returns total bytes written (which will @@ -82,6 +82,18 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode return done; } +mp_off_t mp_stream_seek(mp_obj_t stream, mp_off_t offset, int whence, int *errcode) { + struct mp_stream_seek_t seek_s; + seek_s.offset = offset; + seek_s.whence = whence; + const mp_stream_p_t *stream_p = mp_get_stream(stream); + mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, errcode); + if (res == MP_STREAM_ERROR) { + return (mp_off_t)-1; + } + return seek_s.offset; +} + const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { // CIRCUITPY-CHANGE: using type-safe protocol accessor const mp_stream_p_t *stream_p = mp_get_stream(self_in); @@ -95,7 +107,7 @@ const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("stream operation not supported")); } -STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { +static mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte flags) { // What to do if sz < -1? Python docs don't specify this case. // CPython does a readall, but here we silently let negatives through, // and they will cause a MemoryError. @@ -217,12 +229,12 @@ STATIC mp_obj_t stream_read_generic(size_t n_args, const mp_obj_t *args, byte fl } } -STATIC mp_obj_t stream_read(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_read(size_t n_args, const mp_obj_t *args) { return stream_read_generic(n_args, args, MP_STREAM_RW_READ); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read); -STATIC mp_obj_t stream_read1(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_read1(size_t n_args, const mp_obj_t *args) { return stream_read_generic(n_args, args, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj, 1, 2, stream_read1); @@ -248,9 +260,14 @@ void mp_stream_write_adaptor(void *self, const char *buf, size_t len) { mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len, MP_STREAM_RW_WRITE); } -STATIC mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_readinto_write_generic(size_t n_args, const mp_obj_t *args, byte flags) { mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(args[1], &bufinfo, (flags & MP_STREAM_RW_WRITE) ? MP_BUFFER_READ : MP_BUFFER_WRITE); + + // CPython extension, allow optional maximum length and offset: + // - stream.operation(buf, max_len) + // - stream.operation(buf, off, max_len) + // Similar to https://docs.python.org/3/library/socket.html#socket.socket.recv_into size_t max_len = (size_t)-1; size_t off = 0; if (n_args == 3) { @@ -263,46 +280,32 @@ STATIC mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { } } bufinfo.len -= off; - return mp_stream_write(args[0], (byte *)bufinfo.buf + off, MIN(bufinfo.len, max_len), MP_STREAM_RW_WRITE); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj, 2, 4, stream_write_method); -STATIC mp_obj_t stream_write1_method(mp_obj_t self_in, mp_obj_t arg) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ); - return mp_stream_write(self_in, bufinfo.buf, bufinfo.len, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE); + // Perform the readinto or write operation. + return mp_stream_write(args[0], (byte *)bufinfo.buf + off, MIN(bufinfo.len, max_len), flags); } -MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write1_obj, stream_write1_method); -STATIC mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); +static mp_obj_t stream_write_method(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_WRITE); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj, 2, 4, stream_write_method); - // CPython extension: if 2nd arg is provided, that's max len to read, - // instead of full buffer. Similar to - // https://docs.python.org/3/library/socket.html#socket.socket.recv_into - mp_uint_t len = bufinfo.len; - if (n_args > 2) { - len = mp_obj_get_int(args[2]); - if (len > bufinfo.len) { - len = bufinfo.len; - } - } +static mp_obj_t stream_write1_method(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_WRITE | MP_STREAM_RW_ONCE); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write1_obj, 2, 4, stream_write1_method); - int error; - mp_uint_t out_sz = mp_stream_read_exactly(args[0], bufinfo.buf, len, &error); - if (error != 0) { - if (mp_is_nonblocking_error(error)) { - return mp_const_none; - } - mp_raise_OSError(error); - } else { - return MP_OBJ_NEW_SMALL_INT(out_sz); - } +static mp_obj_t stream_readinto(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_READ); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto); -STATIC mp_obj_t stream_readall(mp_obj_t self_in) { +static mp_obj_t stream_readinto1(size_t n_args, const mp_obj_t *args) { + return stream_readinto_write_generic(n_args, args, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto1_obj, 2, 3, stream_readinto1); + +static mp_obj_t stream_readall(mp_obj_t self_in) { const mp_stream_p_t *stream_p = mp_get_stream(self_in); mp_uint_t total_size = 0; @@ -347,7 +350,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) { } // Unbuffered, inefficient implementation of readline() for raw I/O files. -STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) { const mp_stream_p_t *stream_p = mp_get_stream(args[0]); mp_int_t max_size = -1; @@ -405,7 +408,7 @@ STATIC mp_obj_t stream_unbuffered_readline(size_t n_args, const mp_obj_t *args) MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline); // TODO take an optional extra argument (what does it do exactly?) -STATIC mp_obj_t stream_unbuffered_readlines(mp_obj_t self) { +static mp_obj_t stream_unbuffered_readlines(mp_obj_t self) { mp_obj_t lines = mp_obj_new_list(0, NULL); for (;;) { mp_obj_t line = stream_unbuffered_readline(1, &self); @@ -437,39 +440,37 @@ mp_obj_t mp_stream_close(mp_obj_t stream) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_close_obj, mp_stream_close); -STATIC mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) { +static mp_obj_t mp_stream___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; return mp_stream_close(args[0]); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream___exit___obj, 4, 4, mp_stream___exit__); -STATIC mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) { - struct mp_stream_seek_t seek_s; +static mp_obj_t stream_seek(size_t n_args, const mp_obj_t *args) { // TODO: Could be uint64 - seek_s.offset = mp_obj_get_int(args[1]); - seek_s.whence = SEEK_SET; + mp_off_t offset = mp_obj_get_int(args[1]); + int whence = SEEK_SET; if (n_args == 3) { - seek_s.whence = mp_obj_get_int(args[2]); + whence = mp_obj_get_int(args[2]); } // In POSIX, it's error to seek before end of stream, we enforce it here. - if (seek_s.whence == SEEK_SET && seek_s.offset < 0) { + if (whence == SEEK_SET && offset < 0) { mp_raise_OSError(MP_EINVAL); } - const mp_stream_p_t *stream_p = mp_get_stream(args[0]); int error; - mp_uint_t res = stream_p->ioctl(args[0], MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error); - if (res == MP_STREAM_ERROR) { + mp_off_t res = mp_stream_seek(args[0], offset, whence, &error); + if (res == (mp_off_t)-1) { mp_raise_OSError(error); } // TODO: Could be uint64 - return mp_obj_new_int_from_uint(seek_s.offset); + return mp_obj_new_int_from_uint(res); } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj, 2, 3, stream_seek); -STATIC mp_obj_t stream_tell(mp_obj_t self) { +static mp_obj_t stream_tell(mp_obj_t self) { mp_obj_t offset = MP_OBJ_NEW_SMALL_INT(0); mp_obj_t whence = MP_OBJ_NEW_SMALL_INT(SEEK_CUR); const mp_obj_t args[3] = {self, offset, whence}; @@ -489,7 +490,7 @@ mp_obj_t mp_stream_flush(mp_obj_t self) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_flush_obj, mp_stream_flush); -STATIC mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { +static mp_obj_t stream_ioctl(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; uintptr_t val = 0; if (n_args > 2) { @@ -545,16 +546,11 @@ ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) { } off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) { - const mp_obj_base_t *o = stream; - const mp_stream_p_t *stream_p = MP_OBJ_TYPE_GET_SLOT(o->type, protocol); - struct mp_stream_seek_t seek_s; - seek_s.offset = offset; - seek_s.whence = whence; - mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &errno); - if (res == MP_STREAM_ERROR) { + mp_off_t res = mp_stream_seek(MP_OBJ_FROM_PTR(stream), offset, whence, &errno); + if (res == (mp_off_t)-1) { return -1; } - return seek_s.offset; + return res; } int mp_stream_posix_fsync(void *stream) { diff --git a/py/stream.h b/py/stream.h index 8ee4fe055b3fc..6e60e849b5f48 100644 --- a/py/stream.h +++ b/py/stream.h @@ -87,10 +87,11 @@ typedef struct _mp_stream_p_t { MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read1_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto1_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_unbuffered_readlines_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write_obj); -MP_DECLARE_CONST_FUN_OBJ_2(mp_stream_write1_obj); +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_write1_obj); MP_DECLARE_CONST_FUN_OBJ_1(mp_stream_close_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream___exit___obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_seek_obj); @@ -124,6 +125,7 @@ mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len, byte fla mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf, mp_uint_t size, int *errcode, byte flags); #define mp_stream_write_exactly(stream, buf, size, err) mp_stream_rw(stream, (byte *)buf, size, err, MP_STREAM_RW_WRITE) #define mp_stream_read_exactly(stream, buf, size, err) mp_stream_rw(stream, buf, size, err, MP_STREAM_RW_READ) +mp_off_t mp_stream_seek(mp_obj_t stream, mp_off_t offset, int whence, int *errcode); void mp_stream_write_adaptor(void *self, const char *buf, size_t len); // CIRCUITPY-CHANGE: make public diff --git a/py/unicode.c b/py/unicode.c index 5acaad378843c..81a37880f3c72 100644 --- a/py/unicode.c +++ b/py/unicode.c @@ -48,7 +48,7 @@ #define AT_LX (FL_LOWER | FL_ALPHA | FL_PRINT | FL_XDIGIT) // table of attributes for ascii characters -STATIC const uint8_t attr[] = { +static const uint8_t attr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, AT_SP, AT_SP, AT_SP, AT_SP, AT_SP, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/py/usermod.cmake b/py/usermod.cmake index 853276283746d..4a8b99ff31b46 100644 --- a/py/usermod.cmake +++ b/py/usermod.cmake @@ -5,6 +5,10 @@ function(usermod_gather_sources SOURCES_VARNAME INCLUDE_DIRECTORIES_VARNAME INCL if (NOT ${LIB} IN_LIST ${INCLUDED_VARNAME}) list(APPEND ${INCLUDED_VARNAME} ${LIB}) + if (NOT TARGET ${LIB}) + return() + endif() + # Gather library sources get_target_property(lib_sources ${LIB} INTERFACE_SOURCES) if (lib_sources) @@ -38,6 +42,16 @@ endfunction() # Include CMake files for user modules. if (USER_C_MODULES) foreach(USER_C_MODULE_PATH ${USER_C_MODULES}) + # If a directory is given, append the micropython.cmake to it. + if (IS_DIRECTORY ${USER_C_MODULE_PATH}) + set(USER_C_MODULE_PATH "${USER_C_MODULE_PATH}/micropython.cmake") + endif() + # Confirm the provided path exists, show abspath if not to make it clearer to fix. + if (NOT EXISTS ${USER_C_MODULE_PATH}) + get_filename_component(USER_C_MODULES_ABS "${USER_C_MODULE_PATH}" ABSOLUTE) + message(FATAL_ERROR "USER_C_MODULES doesn't exist: ${USER_C_MODULES_ABS}") + endif() + message("Including User C Module(s) from ${USER_C_MODULE_PATH}") include(${USER_C_MODULE_PATH}) endforeach() diff --git a/py/verbose.mk b/py/verbose.mk new file mode 100644 index 0000000000000..734623a21e80f --- /dev/null +++ b/py/verbose.mk @@ -0,0 +1,16 @@ +# Turn on increased build verbosity by defining BUILD_VERBOSE in your main +# Makefile or in your environment. You can also use V=1 on the make command +# line. + +ifeq ("$(origin V)", "command line") +BUILD_VERBOSE=$(V) +endif +ifndef BUILD_VERBOSE +$(info Use make V=1 or set BUILD_VERBOSE in your environment to increase build verbosity.) +BUILD_VERBOSE = 0 +endif +ifeq ($(BUILD_VERBOSE),0) +Q = @ +else +Q = +endif diff --git a/py/version.py b/py/version.py new file mode 100755 index 0000000000000..b9e889b86b6ed --- /dev/null +++ b/py/version.py @@ -0,0 +1,84 @@ +import os +import subprocess + + +def get_version_info_from_git(repo_path, extra_args=[]): + if "CP_VERSION" in os.environ: + git_tag = os.environ["CP_VERSION"] + else: + # Note: git describe doesn't work if no tag is available + try: + git_tag = subprocess.check_output( + # CIRCUITPY-CHANGE: Ignore MicroPython tags that start with v. + # Also ignore tags that are on merged in branches. + [ + "git", + "describe", + "--dirty", + "--tags", + "--always", + "--first-parent", + "--match", + "[!v]*", # This is a glob, not a regex + *extra_args, + ], + cwd=repo_path, + stderr=subprocess.STDOUT, + universal_newlines=True, + ).strip() + # CIRCUITPY-CHANGE + except subprocess.CalledProcessError as er: + if er.returncode == 128: + # git exit code of 128 means no repository found + return None + git_tag = "" + except OSError: + return None + try: + # CIRCUITPY-CHANGE + git_hash = subprocess.check_output( + ["git", "rev-parse", "--short", "HEAD"], + cwd=repo_path, + stderr=subprocess.STDOUT, + universal_newlines=True, + ).strip() + except subprocess.CalledProcessError: + # CIRCUITPY-CHANGE + git_hash = "unknown" + except OSError: + return None + + # CIRCUITPY-CHANGE + try: + # Check if there are any modified files. + subprocess.check_call( + ["git", "diff", "--no-ext-diff", "--quiet", "--exit-code"], + cwd=repo_path, + stderr=subprocess.STDOUT, + ) + # Check if there are any staged files. + subprocess.check_call( + ["git", "diff-index", "--cached", "--quiet", "HEAD", "--"], + cwd=repo_path, + stderr=subprocess.STDOUT, + ) + except subprocess.CalledProcessError: + git_hash += "-dirty" + except OSError: + return None + + # CIRCUITPY-CHANGE + # Try to extract MicroPython version from git tag + ver = git_tag.split("-")[0].split(".") + + return git_tag, git_hash, ver + + +if __name__ == "__main__": + import pathlib + import sys + + git_tag, _, _ = get_version_info_from_git(pathlib.Path("."), sys.argv[1:]) + if git_tag is None: + sys.exit(-1) + print(git_tag) diff --git a/py/vm.c b/py/vm.c index d58efa08309a1..860aa36e39792 100644 --- a/py/vm.c +++ b/py/vm.c @@ -196,7 +196,7 @@ #endif // MICROPY_PY_SYS_SETTRACE // CIRCUITPY-CHANGE -STATIC mp_obj_t get_active_exception(mp_exc_stack_t *exc_sp, mp_exc_stack_t *exc_stack) { +static mp_obj_t get_active_exception(mp_exc_stack_t *exc_sp, mp_exc_stack_t *exc_stack) { for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; --e) { if (e->prev_exc != NULL) { return MP_OBJ_FROM_PTR(e->prev_exc); @@ -205,6 +205,22 @@ STATIC mp_obj_t get_active_exception(mp_exc_stack_t *exc_sp, mp_exc_stack_t *exc return MP_OBJ_NULL; } +#if MICROPY_PY_BUILTINS_SLICE +// This function is marked "no inline" so it doesn't increase the C stack usage of the main VM function. +MP_NOINLINE static mp_obj_t *build_slice_stack_allocated(byte op, mp_obj_t *sp, mp_obj_t step) { + mp_obj_t stop = sp[2]; + mp_obj_t start = sp[1]; + mp_obj_slice_t slice = { .base = { .type = &mp_type_slice }, .start = start, .stop = stop, .step = step }; + if (op == MP_BC_LOAD_SUBSCR) { + SET_TOP(mp_obj_subscr(TOP(), MP_OBJ_FROM_PTR(&slice), MP_OBJ_SENTINEL)); + } else { // MP_BC_STORE_SUBSCR + mp_obj_subscr(TOP(), MP_OBJ_FROM_PTR(&slice), sp[-1]); + sp -= 2; + } + return sp; +} +#endif + // fastn has items in reverse order (fastn[0] is local[0], fastn[-1] is local[1], etc) // sp points to bottom of stack which grows up // returns: @@ -871,9 +887,20 @@ unwind_jump:; // 3-argument slice includes step step = POP(); } - mp_obj_t stop = POP(); - mp_obj_t start = TOP(); - SET_TOP(mp_obj_new_slice(start, stop, step)); + if ((*ip == MP_BC_LOAD_SUBSCR || *ip == MP_BC_STORE_SUBSCR) + && (mp_obj_get_type(sp[-2])->flags & MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE)) { + // Fast path optimisation for when the BUILD_SLICE is immediately followed + // by a LOAD/STORE_SUBSCR for an accepting type, to avoid needing to allocate + // the slice on the heap. In some cases (e.g. a[1:3] = x) this can result + // in no allocations at all. We can't do this for instance types because + // the get/set/delattr implementation may keep a reference to the slice. + byte op = *ip++; + sp = build_slice_stack_allocated(op, sp - 2, step); + } else { + mp_obj_t stop = POP(); + mp_obj_t start = TOP(); + SET_TOP(mp_obj_new_slice(start, stop, step)); + } DISPATCH(); } #endif @@ -915,7 +942,7 @@ unwind_jump:; ENTRY(MP_BC_MAKE_FUNCTION): { DECODE_PTR; - PUSH(mp_make_function_from_raw_code(ptr, code_state->fun_bc->context, NULL)); + PUSH(mp_make_function_from_proto_fun(ptr, code_state->fun_bc->context, NULL)); DISPATCH(); } @@ -923,7 +950,7 @@ unwind_jump:; DECODE_PTR; // Stack layout: def_tuple def_dict <- TOS sp -= 1; - SET_TOP(mp_make_function_from_raw_code(ptr, code_state->fun_bc->context, sp)); + SET_TOP(mp_make_function_from_proto_fun(ptr, code_state->fun_bc->context, sp)); DISPATCH(); } @@ -932,7 +959,7 @@ unwind_jump:; size_t n_closed_over = *ip++; // Stack layout: closed_overs <- TOS sp -= n_closed_over - 1; - SET_TOP(mp_make_closure_from_raw_code(ptr, code_state->fun_bc->context, n_closed_over, sp)); + SET_TOP(mp_make_closure_from_proto_fun(ptr, code_state->fun_bc->context, n_closed_over, sp)); DISPATCH(); } @@ -941,7 +968,7 @@ unwind_jump:; size_t n_closed_over = *ip++; // Stack layout: def_tuple def_dict closed_overs <- TOS sp -= 2 + n_closed_over - 1; - SET_TOP(mp_make_closure_from_raw_code(ptr, code_state->fun_bc->context, 0x100 | n_closed_over, sp)); + SET_TOP(mp_make_closure_from_proto_fun(ptr, code_state->fun_bc->context, 0x100 | n_closed_over, sp)); DISPATCH(); } diff --git a/py/vstr.c b/py/vstr.c index 46d1a0b9e8e46..522509d0d05cf 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -51,7 +51,7 @@ void vstr_init(vstr_t *vstr, size_t alloc) { // Init the vstr so it allocs exactly enough ram to hold a null-terminated // string of the given length, and set the length. void vstr_init_len(vstr_t *vstr, size_t len) { - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: check for invalid length if (len == SIZE_MAX) { m_malloc_fail(len); } @@ -108,7 +108,7 @@ char *vstr_extend(vstr_t *vstr, size_t size) { return p; } -STATIC void vstr_ensure_extra(vstr_t *vstr, size_t size) { +static void vstr_ensure_extra(vstr_t *vstr, size_t size) { if (vstr->len + size > vstr->alloc) { if (vstr->fixed_buf) { // We can't reallocate, and the caller is expecting the space to @@ -187,7 +187,7 @@ void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) { vstr->len += len; } -STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { +static char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { size_t l = vstr->len; if (byte_pos > l) { byte_pos = l; diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000..5f84ca104ac47 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,91 @@ +# can be empty if no extra settings are needed, presence enables setuptools-scm +[tool.ruff] +target-version = "py312" +line-length = 99 +# Include Python source files that don't end with .py +extend-include = [ "tools/cc1" ] +# Exclude third-party code from linting and formatting +extend-exclude = [ + # CIRCUITPY-CHANGES + "extmod/ulab", + "frozen", + "lib", + "ports/analog/msdk", + "ports/atmel-samd/asf4", + "ports/broadcom/peripherals", + "ports/espress/tools", + "ports/espressif/esp-idf", + "ports/espressif/esp-protocols", + "ports/raspberrypi/sdk", + "ports/silabs/gecko_sdk", + "ports/silabs/tools/slc_cli_linux", + "ports/stm/st_driver", + "tests/cpydiff/syntax_assign_expr.py", # intentionally incorrect CPython code + "tools/adabot", + "tools/bitmap_font", + "tools/cc1", + "tools/huffman", + "tools/msgfmt.py", + "tools/python-semver", + "tools/uf2", +] +# Exclude third-party code, and exclude the following tests: +# basics: needs careful attention before applying automatic formatting +# repl_: not real python files +# viper_args: uses f(*) +format.exclude = [ + "tests/*/repl_*.py", + "tests/basics/*.py", + "tests/cmdline/cmd_compile_only_error.py", + "tests/micropython/test_normalize_newlines.py", + "tests/micropython/viper_args.py", +] +lint.extend-select = [ "C9", "PLC" ] +lint.exclude = [ + # Ruff finds Python SyntaxError in these files + "tests/cmdline/cmd_compile_only_error.py", + "tests/cmdline/repl_autocomplete.py", + "tests/cmdline/repl_autocomplete_underscore.py", + "tests/cmdline/repl_autoindent.py", + "tests/cmdline/repl_basic.py", + "tests/cmdline/repl_cont.py", + "tests/cmdline/repl_emacs_keys.py", + "tests/cmdline/repl_paste.py", + "tests/cmdline/repl_words_move.py", + "tests/feature_check/repl_emacs_check.py", + "tests/feature_check/repl_words_move_check.py", + "tests/micropython/viper_args.py", +] +lint.extend-ignore = [ + "E401", + "E402", + "E722", + "E731", + "E741", + "F401", + "F403", + "F405", + "PLC0206", + "PLC0415", # conditional imports are common in MicroPython +] +# manifest.py files are evaluated with some global names pre-defined +lint.per-file-ignores."**/manifest.py" = [ "F821" ] +lint.per-file-ignores."ports/**/boards/**/manifest_*.py" = [ "F821" ] +lint.per-file-ignores."ports/cc3200/tools/uniflash.py" = [ "E711" ] +# Exclude all tests from linting. +lint.per-file-ignores."tests/**/*.py" = [ "ALL" ] +# Uses assignment expressions. +lint.per-file-ignores."tests/cpydiff/syntax_assign_expr.py" = [ "F821" ] +lint.mccabe.max-complexity = 40 + +[tool.codespell] +count = "" +ignore-regex = "\\b[A-Z]{3}\\b" +# CIRCUITPY-CHANGE: aranges +ignore-words-list = "ans,aranges,asend,deques,dout,emac,extint,hsi,iput,mis,notin,numer,ser,shft,synopsys,technic,ure,curren" +quiet-level = 3 +skip = """\ + */build*,./.git,./drivers/cc3100,./lib,./ports/cc3200/FreeRTOS,./ports/cc3200/bootmgr/sl,./ports/cc3200/hal,./ports/c\ + c3200/simplelink,./ports/cc3200/telnet,./ports/esp32/managed_components,./ports/nrf/drivers/bluetooth/s1*,./ports/stm\ + 32/usbhost,./tests,ACKNOWLEDGEMENTS,\ + """ diff --git a/requirements-dev.txt b/requirements-dev.txt index 050b612241192..6a33c49daecb2 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,7 +4,7 @@ jinja2 typer sh -click +click<8.2.0 cpp-coveralls requests @@ -14,7 +14,7 @@ requests-cache polib # For pre-commit -black +ruff==0.9.4 # ruff version must exactly match pre-commit-config.yaml pyyaml pre-commit micropython-uncrustify @@ -25,9 +25,7 @@ intelhex # for building & testing natmods pyelftools -# for mbedtls certificate store -# version limit due to espressif -cryptography<36.1,>=2.1.4 +cryptography # for web workflow minify minify_html @@ -39,3 +37,9 @@ colorama # for silabs builds setuptools + +# For zephyr port +tomlkit +pytest +pytest-rerunfailures +perfetto diff --git a/requirements-doc.txt b/requirements-doc.txt index 15df3b13780d1..c0ff03ac7707d 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -10,7 +10,7 @@ setuptools>=45 setuptools_scm # For sphinx -sphinx!=5.2.0.post0 +sphinx!=5.2.0.post0,<8.1.0 sphinx-autoapi sphinx-rtd-theme sphinxcontrib-svg2pdfconverter diff --git a/runtime.py b/runtime.py index 28bf98962edc3..28193ce590ed0 100644 --- a/runtime.py +++ b/runtime.py @@ -1,10 +1,11 @@ import pathlib + paths = pathlib.Path(".").glob("**/*.c") -translate_h = "#include \"supervisor/shared/translate/translate.h\"" +translate_h = '#include "supervisor/shared/translate/translate.h"' for p in paths: if "esp-idf" in p: continue lines = p.read_text().split("\n") - if "#include \"py/runtime.h\"" in lines and translate_h in lines: + if '#include "py/runtime.h"' in lines and translate_h in lines: lines.remove(translate_h) p.write_text("\n".join(lines)) diff --git a/setup.py-stubs b/setup.py-stubs index 9cea5f7eeffd3..68412fd18929f 100644 --- a/setup.py-stubs +++ b/setup.py-stubs @@ -45,12 +45,7 @@ setup( packages=list(package_data.keys()), package_data=package_data, package_dir = package_dir, - setup_requires=["setuptools_scm", "setuptools>=38.6.0"], - use_scm_version = { - "root": "..", - "relative_to": __file__, - "local_scheme": local_scheme, - "git_describe_command": "tools/describe --long", - }, + setup_requires=["setuptools>=38.6.0"], + version="__version__", zip_safe=False, ) diff --git a/shared-bindings/_bleio/Adapter.c b/shared-bindings/_bleio/Adapter.c index 7190594c10a73..a1f81a063fdaa 100644 --- a/shared-bindings/_bleio/Adapter.c +++ b/shared-bindings/_bleio/Adapter.c @@ -62,6 +62,7 @@ //| Use `_bleio.adapter` to access the sole instance already available. //| """ //| ... +//| static mp_obj_t bleio_adapter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_BLEIO_HCI bleio_adapter_obj_t *self = common_hal_bleio_allocate_adapter_or_raise(); @@ -135,6 +136,7 @@ MP_PROPERTY_GETSET(bleio_adapter_address_obj, //| """name of the BLE adapter used once connected. //| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, //| to make it easy to distinguish multiple CircuitPython boards.""" +//| static mp_obj_t _bleio_adapter_get_name(mp_obj_t self) { return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_name(self)); } @@ -161,7 +163,7 @@ MP_PROPERTY_GETSET(bleio_adapter_name_obj, //| timeout: int = 0, //| interval: float = 0.1, //| tx_power: int = 0, -//| directed_to: Optional[Address] = None +//| directed_to: Optional[Address] = None, //| ) -> None: //| """Starts advertising until `stop_advertising` is called or if connectable, another device //| connects to us. @@ -181,6 +183,7 @@ MP_PROPERTY_GETSET(bleio_adapter_name_obj, //| :param int tx_power: transmitter power while advertising in dBm //| :param Address directed_to: peer to advertise directly to""" //| ... +//| static mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -212,7 +215,7 @@ static mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t args[ARG_interval].u_obj = mp_obj_new_float(ADV_INTERVAL_DEFAULT); } - const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); + const mp_float_t interval = mp_arg_validate_type_float(args[ARG_interval].u_obj, MP_QSTR_interval); if (interval < ADV_INTERVAL_MIN || interval > ADV_INTERVAL_MAX) { mp_raise_ValueError_varg(MP_ERROR_TEXT("interval must be in range %s-%s"), ADV_INTERVAL_MIN_STRING, ADV_INTERVAL_MAX_STRING); @@ -220,7 +223,7 @@ static mp_obj_t bleio_adapter_start_advertising(mp_uint_t n_args, const mp_obj_t bool connectable = args[ARG_connectable].u_bool; bool anonymous = args[ARG_anonymous].u_bool; - uint32_t timeout = args[ARG_timeout].u_int; + const uint32_t timeout = (uint32_t)mp_arg_validate_int_min(args[ARG_timeout].u_int, 0, MP_QSTR_timeout); if (data_bufinfo.len > 31 && connectable && scan_response_bufinfo.len > 0) { mp_raise_bleio_BluetoothError(MP_ERROR_TEXT("Cannot have scan responses for extended, connectable advertisements.")); } @@ -243,6 +246,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_advertising_obj, 1, bleio_ //| def stop_advertising(self) -> None: //| """Stop sending advertising packets.""" //| ... +//| static mp_obj_t bleio_adapter_stop_advertising(mp_obj_t self_in) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -262,7 +266,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapt //| interval: float = 0.1, //| window: float = 0.1, //| minimum_rssi: int = -80, -//| active: bool = True +//| active: bool = True, //| ) -> Iterable[ScanEntry]: //| """Starts a BLE scan and returns an iterator of results. Advertisements and scan responses are //| filtered and returned separately. @@ -282,6 +286,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_stop_advertising_obj, bleio_adapt //| :returns: an iterable of `_bleio.ScanEntry` objects //| :rtype: iterable""" //| ... +//| static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_prefixes, ARG_buffer_size, ARG_extended, ARG_timeout, ARG_interval, ARG_window, ARG_minimum_rssi, ARG_active }; static const mp_arg_t allowed_args[] = { @@ -301,7 +306,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args mp_float_t timeout = 0.0f; if (args[ARG_timeout].u_obj != mp_const_none) { - timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + timeout = mp_arg_validate_obj_float_non_negative(args[ARG_timeout].u_obj, 0.0f, MP_QSTR_timeout); } if (args[ARG_interval].u_obj == MP_OBJ_NULL) { @@ -312,7 +317,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args args[ARG_window].u_obj = mp_obj_new_float(WINDOW_DEFAULT); } - const mp_float_t interval = mp_obj_get_float(args[ARG_interval].u_obj); + const mp_float_t interval = mp_arg_validate_type_float(args[ARG_interval].u_obj, MP_QSTR_interval); if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { mp_raise_ValueError_varg(MP_ERROR_TEXT("interval must be in range %s-%s"), INTERVAL_MIN_STRING, INTERVAL_MAX_STRING); } @@ -324,7 +329,7 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args } #pragma GCC diagnostic pop - const mp_float_t window = mp_obj_get_float(args[ARG_window].u_obj); + const mp_float_t window = mp_arg_validate_type_float(args[ARG_window].u_obj, MP_QSTR_window); if (window > interval) { mp_raise_ValueError(MP_ERROR_TEXT("window must be <= interval")); } @@ -334,18 +339,21 @@ static mp_obj_t bleio_adapter_start_scan(size_t n_args, const mp_obj_t *pos_args if (args[ARG_prefixes].u_obj != MP_OBJ_NULL) { mp_get_buffer_raise(args[ARG_prefixes].u_obj, &prefix_bufinfo, MP_BUFFER_READ); // An empty buffer may not be on the heap, but that doesn't matter. - if (prefix_bufinfo.len > 0 && gc_nbytes(prefix_bufinfo.buf) == 0) { + if (prefix_bufinfo.len > 0 && !gc_ptr_on_heap(prefix_bufinfo.buf)) { mp_raise_ValueError(MP_ERROR_TEXT("Prefix buffer must be on the heap")); } } - return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, args[ARG_buffer_size].u_int, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); + const mp_int_t buffer_size = mp_arg_validate_int_min(args[ARG_buffer_size].u_int, 1, MP_QSTR_buffer_size); + + return common_hal_bleio_adapter_start_scan(self, prefix_bufinfo.buf, prefix_bufinfo.len, args[ARG_extended].u_bool, buffer_size, timeout, interval, window, args[ARG_minimum_rssi].u_int, args[ARG_active].u_bool); } static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_start_scan_obj, 1, bleio_adapter_start_scan); //| def stop_scan(self) -> None: //| """Stop the current scan.""" //| ... +//| static mp_obj_t bleio_adapter_stop_scan(mp_obj_t self_in) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -381,6 +389,7 @@ MP_PROPERTY_GETTER(bleio_adapter_connected_obj, //| connections: Tuple[Connection] //| """Tuple of active connections including those initiated through //| :py:meth:`_bleio.Adapter.connect`. (read-only)""" +//| static mp_obj_t bleio_adapter_get_connections(mp_obj_t self) { return common_hal_bleio_adapter_get_connections(self); } @@ -395,6 +404,7 @@ MP_PROPERTY_GETTER(bleio_adapter_connections_obj, //| :param Address address: The address of the peripheral to connect to //| :param float/int timeout: Try to connect for timeout seconds.""" //| ... +//| static mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -408,7 +418,8 @@ static mp_obj_t bleio_adapter_connect(mp_uint_t n_args, const mp_obj_t *pos_args mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); bleio_address_obj_t *address = mp_arg_validate_type(args[ARG_address].u_obj, &bleio_address_type, MP_QSTR_address); - mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); + const mp_float_t timeout = + mp_arg_validate_obj_float_non_negative(args[ARG_timeout].u_obj, 0.0f, MP_QSTR_timeout); return common_hal_bleio_adapter_connect(self, address, timeout); } @@ -418,6 +429,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_adapter_connect_obj, 1, bleio_adapter_co //| """Erase all bonding information stored in flash memory.""" //| ... //| +//| static mp_obj_t bleio_adapter_erase_bonding(mp_obj_t self_in) { bleio_adapter_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_bleio/Address.c b/shared-bindings/_bleio/Address.c index 5cedd2b4663b4..10500bec9cb1d 100644 --- a/shared-bindings/_bleio/Address.c +++ b/shared-bindings/_bleio/Address.c @@ -26,6 +26,7 @@ //| :param int address_type: one of the integer values: `PUBLIC`, `RANDOM_STATIC`, //| `RANDOM_PRIVATE_RESOLVABLE`, or `RANDOM_PRIVATE_NON_RESOLVABLE`.""" //| ... +//| static mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_address, ARG_address_type }; static const mp_arg_t allowed_args[] = { @@ -36,20 +37,18 @@ static mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - bleio_address_obj_t *self = mp_obj_malloc(bleio_address_obj_t, &bleio_address_type); - const mp_obj_t address = args[ARG_address].u_obj; mp_buffer_info_t buf_info; mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); - if (buf_info.len != NUM_BLEIO_ADDRESS_BYTES) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Address must be %d bytes long"), NUM_BLEIO_ADDRESS_BYTES); - } + mp_arg_validate_length(buf_info.len, NUM_BLEIO_ADDRESS_BYTES, MP_QSTR_address); - const mp_int_t address_type = args[ARG_address_type].u_int; - if (address_type < BLEIO_ADDRESS_TYPE_MIN || address_type > BLEIO_ADDRESS_TYPE_MAX) { - mp_arg_error_invalid(MP_QSTR_address_type); - } + const mp_int_t address_type = + mp_arg_validate_int_range(args[ARG_address_type].u_int, + BLEIO_ADDRESS_TYPE_MIN, + BLEIO_ADDRESS_TYPE_MAX, + MP_QSTR_address_type); + bleio_address_obj_t *self = mp_obj_malloc(bleio_address_obj_t, &bleio_address_type); common_hal_bleio_address_construct(self, buf_info.buf, address_type); return MP_OBJ_FROM_PTR(self); @@ -86,6 +85,7 @@ MP_PROPERTY_GETTER(bleio_address_address_bytes_obj, //| //| One of the integer values: `PUBLIC`, `RANDOM_STATIC`, `RANDOM_PRIVATE_RESOLVABLE`, //| or `RANDOM_PRIVATE_NON_RESOLVABLE`.""" +//| static mp_obj_t bleio_address_get_type(mp_obj_t self_in) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -99,6 +99,7 @@ MP_PROPERTY_GETTER(bleio_address_type_obj, //| def __eq__(self, other: object) -> bool: //| """Two Address objects are equal if their addresses and address types are equal.""" //| ... +//| static mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { // Two Addresses are equal if their address bytes and address_type are equal @@ -124,6 +125,7 @@ static mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o //| def __hash__(self) -> int: //| """Returns a hash for the Address data.""" //| ... +//| static mp_obj_t bleio_address_unary_op(mp_unary_op_t op, mp_obj_t self_in) { switch (op) { // Two Addresses are equal if their address bytes and address_type are equal @@ -166,6 +168,7 @@ static void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_pr //| RANDOM_PRIVATE_NON_RESOLVABLE: int //| """A randomly generated address that changes on every connection.""" //| +//| static const mp_rom_map_elem_t bleio_address_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) }, { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) }, diff --git a/shared-bindings/_bleio/Attribute.c b/shared-bindings/_bleio/Attribute.c index fe890d875e51c..f91fa22568054 100644 --- a/shared-bindings/_bleio/Attribute.c +++ b/shared-bindings/_bleio/Attribute.c @@ -19,6 +19,7 @@ //| def __init__(self) -> None: //| """You cannot create an instance of :py:class:`~_bleio.Attribute`.""" //| ... +//| static const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { @@ -42,6 +43,7 @@ static const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { //| //| SIGNED_WITH_MITM: int //| """security_mode: authenticated data signing, without man-in-the-middle protection""" +//| //| { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SECURITY_MODE_NO_ACCESS) }, { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SECURITY_MODE_OPEN) }, diff --git a/shared-bindings/_bleio/Characteristic.c b/shared-bindings/_bleio/Characteristic.c index ddb6627df24cb..0ed4c2b7eaa97 100644 --- a/shared-bindings/_bleio/Characteristic.c +++ b/shared-bindings/_bleio/Characteristic.c @@ -12,6 +12,8 @@ #include "shared-bindings/_bleio/Characteristic.h" #include "shared-bindings/_bleio/Service.h" #include "shared-bindings/_bleio/UUID.h" +#include "shared-bindings/util.h" + //| class Characteristic: //| """Stores information about a BLE service characteristic and allows reading @@ -23,6 +25,7 @@ //| Remote Characteristic objects are created by `Connection.discover_remote_services()` //| as part of remote Services.""" //| ... +//| //| @classmethod //| def add_to_service( @@ -36,7 +39,7 @@ //| max_length: int = 20, //| fixed_length: bool = False, //| initial_value: Optional[ReadableBuffer] = None, -//| user_description: Optional[str] = None +//| user_description: Optional[str] = None, //| ) -> Characteristic: //| """Create a new Characteristic object, and add it to this Service. //| @@ -61,6 +64,7 @@ //| //| :return: the new Characteristic.""" //| ... +//| static mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // class is arg[0], which we can ignore. @@ -112,9 +116,10 @@ static mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ } mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); - if (initial_value_bufinfo.len > max_length || - (fixed_length && initial_value_bufinfo.len != max_length)) { - mp_raise_ValueError(MP_ERROR_TEXT("initial_value length is wrong")); + if (fixed_length) { + mp_arg_validate_length(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); + } else { + mp_arg_validate_length_max(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); } const char *user_description = NULL; @@ -138,7 +143,22 @@ static mp_obj_t bleio_characteristic_add_to_service(size_t n_args, const mp_obj_ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_add_to_service_fun_obj, 1, bleio_characteristic_add_to_service); static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, MP_ROM_PTR(&bleio_characteristic_add_to_service_fun_obj)); +//| def deinit(self) -> None: +//| """Deinitialises the Characteristic and releases any hardware resources for reuse.""" +//| ... +//| +static mp_obj_t bleio_characteristic_deinit(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_bleio_characteristic_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_deinit_obj, bleio_characteristic_deinit); +static void check_for_deinit(bleio_characteristic_obj_t *self) { + if (common_hal_bleio_characteristic_deinited(self)) { + raise_deinited_error(); + } +} //| properties: int //| """An int bitmask representing which properties are set, specified as bitwise or'ing of @@ -146,6 +166,7 @@ static MP_DEFINE_CONST_CLASSMETHOD_OBJ(bleio_characteristic_add_to_service_obj, //| `BROADCAST`, `INDICATE`, `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE`.""" static mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_properties(self)); } @@ -160,6 +181,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_properties_obj, //| Will be ``None`` if the 128-bit UUID for this characteristic is not known.""" static mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); bleio_uuid_obj_t *uuid = common_hal_bleio_characteristic_get_uuid(self); return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none; @@ -173,6 +195,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_uuid_obj, //| """The value of this characteristic.""" static mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); uint8_t temp[512]; size_t actual_len = common_hal_bleio_characteristic_get_value(self, temp, sizeof(temp)); @@ -182,6 +205,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_value_obj, bleio_chara static mp_obj_t bleio_characteristic_set_value(mp_obj_t self_in, mp_obj_t value_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); mp_buffer_info_t bufinfo; mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ); @@ -200,6 +224,7 @@ MP_PROPERTY_GETSET(bleio_characteristic_value_obj, //| """The max length of this characteristic.""" static mp_obj_t bleio_characteristic_get_max_length(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_max_length(self)); } @@ -212,6 +237,8 @@ MP_PROPERTY_GETTER(bleio_characteristic_max_length_obj, //| """A tuple of :py:class:`Descriptor` objects related to this characteristic. (read-only)""" static mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + // Return list as a tuple so user won't be able to change it. return MP_OBJ_FROM_PTR(common_hal_bleio_characteristic_get_descriptors(self)); } @@ -223,8 +250,10 @@ MP_PROPERTY_GETTER(bleio_characteristic_descriptors_obj, //| service: Service //| """The Service this Characteristic is a part of.""" +//| static mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return common_hal_bleio_characteristic_get_service(self); } @@ -240,8 +269,10 @@ MP_PROPERTY_GETTER(bleio_characteristic_service_obj, //| :param float indicate: True if Characteristic should receive indications of remote writes //| """ //| ... +//| static mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); enum { ARG_notify, ARG_indicate }; static const mp_arg_t allowed_args[] = { @@ -259,6 +290,9 @@ static mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t * static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd); static const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_characteristic_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&bleio_characteristic_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_add_to_service), MP_ROM_PTR(&bleio_characteristic_add_to_service_obj) }, { MP_ROM_QSTR(MP_QSTR_descriptors), MP_ROM_PTR(&bleio_characteristic_descriptors_obj) }, { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_properties_obj) }, @@ -284,6 +318,7 @@ static const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { //| //| WRITE_NO_RESPONSE: int //| """property: clients may write this characteristic; no response will be sent back""" +//| //| { MP_ROM_QSTR(MP_QSTR_BROADCAST), MP_ROM_INT(CHAR_PROP_BROADCAST) }, { MP_ROM_QSTR(MP_QSTR_INDICATE), MP_ROM_INT(CHAR_PROP_INDICATE) }, diff --git a/shared-bindings/_bleio/Characteristic.h b/shared-bindings/_bleio/Characteristic.h index 2d343b8b07f9e..67b1062691da2 100644 --- a/shared-bindings/_bleio/Characteristic.h +++ b/shared-bindings/_bleio/Characteristic.h @@ -24,5 +24,7 @@ extern size_t common_hal_bleio_characteristic_get_max_length(bleio_characteristi extern size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self, uint8_t *buf, size_t len); extern void common_hal_bleio_characteristic_add_descriptor(bleio_characteristic_obj_t *self, bleio_descriptor_obj_t *descriptor); extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_service_obj_t *service, uint16_t handle, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_buffer_info_t *initial_value_bufinfo, const char *user_description); +extern bool common_hal_bleio_characteristic_deinited(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_deinit(bleio_characteristic_obj_t *self); extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index a8ae04fd12081..5ffff0dcba757 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -37,6 +37,7 @@ static void raise_error_if_not_connected(bleio_characteristic_buffer_obj_t *self //| :param int buffer_size: Size of ring buffer that stores incoming data coming from client. //| Must be >= 1.""" //| ... +//| static mp_obj_t bleio_characteristic_buffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_characteristic, ARG_timeout, ARG_buffer_size, }; static const mp_arg_t allowed_args[] = { @@ -80,9 +81,11 @@ static void check_for_deinit(bleio_characteristic_buffer_obj_t *self) { //| :rtype: bytes or None""" //| ... //| -//| def readinto(self, buf: WriteableBuffer) -> Optional[int]: +//| def readinto(self, buf: WriteableBuffer, nbytes: Optional[int] = None) -> Optional[int]: //| """Read bytes into the ``buf``. Read at most ``len(buf)`` bytes. //| +//| You may reduce this maximum read using the ``nbytes`` argument. +//| //| :return: number of bytes read and stored into ``buf`` //| :rtype: int or None (on a non-blocking error)""" //| ... @@ -93,6 +96,7 @@ static void check_for_deinit(bleio_characteristic_buffer_obj_t *self) { //| :return: the line read //| :rtype: int or None""" //| ... +//| // These three methods are used by the shared stream methods. static mp_uint_t bleio_characteristic_buffer_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { @@ -138,6 +142,7 @@ static mp_uint_t bleio_characteristic_buffer_ioctl(mp_obj_t self_in, mp_uint_t r //| in_waiting: int //| """The number of bytes in the input buffer, available to be read""" +//| static mp_obj_t bleio_characteristic_buffer_obj_get_in_waiting(mp_obj_t self_in) { bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -156,6 +161,7 @@ MP_PROPERTY_GETTER(bleio_characteristic_buffer_in_waiting_obj, //| def reset_input_buffer(self) -> None: //| """Discard any unread characters in the input buffer.""" //| ... +//| static mp_obj_t bleio_characteristic_buffer_obj_reset_input_buffer(mp_obj_t self_in) { bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -168,6 +174,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_buffer_reset_input_buffer_ //| """Disable permanently.""" //| ... //| +//| static mp_obj_t bleio_characteristic_buffer_deinit(mp_obj_t self_in) { bleio_characteristic_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_bleio_characteristic_buffer_deinit(self); @@ -179,13 +186,13 @@ static const mp_rom_map_elem_t bleio_characteristic_buffer_locals_dict_table[] = { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_characteristic_buffer_deinit_obj) }, // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, // CharacteristicBuffer is currently read-only. - // { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + // { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&bleio_characteristic_buffer_reset_input_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&bleio_characteristic_buffer_reset_input_buffer_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&bleio_characteristic_buffer_in_waiting_obj) }, diff --git a/shared-bindings/_bleio/Connection.c b/shared-bindings/_bleio/Connection.c index becd275f761fb..4a81d753433b3 100644 --- a/shared-bindings/_bleio/Connection.c +++ b/shared-bindings/_bleio/Connection.c @@ -56,6 +56,7 @@ void bleio_connection_ensure_connected(bleio_connection_obj_t *self) { //| def disconnect(self) -> None: //| """Disconnects from the remote peripheral. Does nothing if already disconnected.""" //| ... +//| static mp_obj_t bleio_connection_disconnect(mp_obj_t self_in) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); // common_hal_bleio_connection_disconnect() does nothing if already disconnected. @@ -66,8 +67,12 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_disconnect_obj, bleio_connecti //| def pair(self, *, bond: bool = True) -> None: -//| """Pair to the peer to improve security.""" +//| """Pair to the peer to improve security. +//| +//| **Limitation**: Currently ``bond``must be ``True``: bonding always occurs. +//| """ //| ... +//| static mp_obj_t bleio_connection_pair(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -79,6 +84,9 @@ static mp_obj_t bleio_connection_pair(mp_uint_t n_args, const mp_obj_t *pos_args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + if (args[ARG_bond].u_bool == false) { + mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q=%q"), MP_QSTR_bond, MP_QSTR_False); + } bleio_connection_ensure_connected(self); common_hal_bleio_connection_pair(self->connection, args[ARG_bond].u_bool); @@ -111,6 +119,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_connection_pair_obj, 1, bleio_connection //| //| :return: A tuple of `_bleio.Service` objects provided by the remote peripheral.""" //| ... +//| static mp_obj_t bleio_connection_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -182,6 +191,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(bleio_connection_get_connection_interval_obj, b //| But for a regular characteristic read or write, may be sent in multiple packets, //| so this limit does not apply.""" //| +//| static mp_obj_t bleio_connection_get_max_packet_length(mp_obj_t self_in) { bleio_connection_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_bleio/Descriptor.c b/shared-bindings/_bleio/Descriptor.c index f8615fd28abb5..9e29f57d8dd2b 100644 --- a/shared-bindings/_bleio/Descriptor.c +++ b/shared-bindings/_bleio/Descriptor.c @@ -35,7 +35,7 @@ //| write_perm: int = Attribute.OPEN, //| max_length: int = 20, //| fixed_length: bool = False, -//| initial_value: ReadableBuffer = b"" +//| initial_value: ReadableBuffer = b"", //| ) -> Descriptor: //| """Create a new Descriptor object, and add it to this Service. //| @@ -55,6 +55,7 @@ //| //| :return: the new Descriptor.""" //| ... +//| static mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { // class is arg[0], which we can ignore. @@ -98,9 +99,10 @@ static mp_obj_t bleio_descriptor_add_to_characteristic(size_t n_args, const mp_o } } mp_get_buffer_raise(initial_value, &initial_value_bufinfo, MP_BUFFER_READ); - if (initial_value_bufinfo.len > max_length || - (fixed_length && initial_value_bufinfo.len != max_length)) { - mp_raise_ValueError(MP_ERROR_TEXT("initial_value length is wrong")); + if (fixed_length) { + mp_arg_validate_length(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); + } else { + mp_arg_validate_length_max(initial_value_bufinfo.len, max_length, MP_QSTR_initial_value); } bleio_descriptor_obj_t *descriptor = mp_obj_malloc(bleio_descriptor_obj_t, &bleio_descriptor_type); @@ -147,6 +149,7 @@ MP_PROPERTY_GETTER(bleio_descriptor_characteristic_obj, //| value: bytearray //| """The value of this descriptor.""" //| +//| static mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) { bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_bleio/PacketBuffer.c b/shared-bindings/_bleio/PacketBuffer.c index dc89d9b33d1d6..aa1e6e8645a61 100644 --- a/shared-bindings/_bleio/PacketBuffer.c +++ b/shared-bindings/_bleio/PacketBuffer.c @@ -21,7 +21,7 @@ //| characteristic: Characteristic, //| *, //| buffer_size: int, -//| max_packet_size: Optional[int] = None +//| max_packet_size: Optional[int] = None, //| ) -> None: //| """Accumulates a Characteristic's incoming packets in a FIFO buffer and facilitates packet aware //| outgoing writes. A packet's size is either the characteristic length or the maximum transmission @@ -39,6 +39,7 @@ //| :param int max_packet_size: Maximum size of packets. Overrides value from the characteristic. //| (Remote characteristics may not have the correct length.)""" //| ... +//| static mp_obj_t bleio_packet_buffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_characteristic, ARG_buffer_size, ARG_max_packet_size }; static const mp_arg_t allowed_args[] = { @@ -56,7 +57,10 @@ static mp_obj_t bleio_packet_buffer_make_new(const mp_obj_type_t *type, size_t n size_t max_packet_size = common_hal_bleio_characteristic_get_max_length(characteristic); if (args[ARG_max_packet_size].u_obj != mp_const_none) { - max_packet_size = mp_obj_get_int(args[ARG_max_packet_size].u_obj); + const mp_int_t max_packet_size_int = + mp_arg_validate_type_int(args[ARG_max_packet_size].u_obj, MP_QSTR_max_packet_size); + max_packet_size = + (size_t)mp_arg_validate_int_min(max_packet_size_int, 1, MP_QSTR_max_packet_size); } bleio_packet_buffer_obj_t *self = mp_obj_malloc(bleio_packet_buffer_obj_t, &bleio_packet_buffer_type); @@ -79,6 +83,7 @@ static void check_for_deinit(bleio_packet_buffer_obj_t *self) { //| :return: number of bytes read and stored into ``buf`` //| :rtype: int""" //| ... +//| static mp_obj_t bleio_packet_buffer_readinto(mp_obj_t self_in, mp_obj_t buffer_obj) { bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -104,6 +109,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(bleio_packet_buffer_readinto_obj, bleio_packet_ //| :return: number of bytes written. May include header bytes when packet is empty. //| :rtype: int""" //| ... +//| // TODO: Add a kwarg `merge=False` to dictate whether subsequent writes are merged into a pending // one. static mp_obj_t bleio_packet_buffer_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -149,6 +155,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_packet_buffer_write_obj, 1, bleio_packet //| def deinit(self) -> None: //| """Disable permanently.""" //| ... +//| static mp_obj_t bleio_packet_buffer_deinit(mp_obj_t self_in) { bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_bleio_packet_buffer_deinit(self); @@ -175,6 +182,7 @@ MP_PROPERTY_GETTER(bleio_packet_buffer_incoming_packet_length_obj, //| outgoing_packet_length: int //| """Maximum length in bytes of a packet we are writing.""" //| +//| static mp_obj_t bleio_packet_buffer_get_outgoing_packet_length(mp_obj_t self_in) { bleio_packet_buffer_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -193,11 +201,11 @@ static const mp_rom_map_elem_t bleio_packet_buffer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bleio_packet_buffer_deinit_obj) }, // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bleio_packet_buffer_readinto_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_packet_buffer_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&bleio_packet_buffer_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_packet_buffer_write_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_incoming_packet_length), MP_ROM_PTR(&bleio_packet_buffer_incoming_packet_length_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_outgoing_packet_length), MP_ROM_PTR(&bleio_packet_buffer_outgoing_packet_length_obj) }, + { MP_ROM_QSTR(MP_QSTR_incoming_packet_length), MP_ROM_PTR(&bleio_packet_buffer_incoming_packet_length_obj) }, + { MP_ROM_QSTR(MP_QSTR_outgoing_packet_length), MP_ROM_PTR(&bleio_packet_buffer_outgoing_packet_length_obj) }, }; static MP_DEFINE_CONST_DICT(bleio_packet_buffer_locals_dict, bleio_packet_buffer_locals_dict_table); diff --git a/shared-bindings/_bleio/PacketBuffer.h b/shared-bindings/_bleio/PacketBuffer.h index e9e642e2677e8..24fb24bce78d3 100644 --- a/shared-bindings/_bleio/PacketBuffer.h +++ b/shared-bindings/_bleio/PacketBuffer.h @@ -6,6 +6,7 @@ #pragma once +#include "shared-bindings/_bleio/Characteristic.h" #include "common-hal/_bleio/PacketBuffer.h" extern const mp_obj_type_t bleio_packet_buffer_type; @@ -21,13 +22,11 @@ void common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, size_t buffer_size, size_t max_packet_size); // Allocation free version for BLE workflow use. -#if CIRCUITPY_SERIAL_BLE || CIRCUITPY_BLE_FILE_SERVICE void _common_hal_bleio_packet_buffer_construct( bleio_packet_buffer_obj_t *self, bleio_characteristic_obj_t *characteristic, uint32_t *incoming_buffer, size_t incoming_buffer_size, - uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t outgoing_buffer_size, + uint32_t *outgoing_buffer1, uint32_t *outgoing_buffer2, size_t max_packet_size, ble_event_handler_t *static_handler_entry); -#endif mp_int_t common_hal_bleio_packet_buffer_write(bleio_packet_buffer_obj_t *self, const uint8_t *data, size_t len, uint8_t *header, size_t header_len); mp_int_t common_hal_bleio_packet_buffer_readinto(bleio_packet_buffer_obj_t *self, uint8_t *data, size_t len); mp_int_t common_hal_bleio_packet_buffer_get_incoming_packet_length(bleio_packet_buffer_obj_t *self); @@ -35,3 +34,4 @@ mp_int_t common_hal_bleio_packet_buffer_get_outgoing_packet_length(bleio_packet_ void common_hal_bleio_packet_buffer_flush(bleio_packet_buffer_obj_t *self); bool common_hal_bleio_packet_buffer_deinited(bleio_packet_buffer_obj_t *self); void common_hal_bleio_packet_buffer_deinit(bleio_packet_buffer_obj_t *self); +bool common_hal_bleio_packet_buffer_connected(bleio_packet_buffer_obj_t *self); diff --git a/shared-bindings/_bleio/ScanEntry.c b/shared-bindings/_bleio/ScanEntry.c index 9e66b70e8e956..6b1591093ae5d 100644 --- a/shared-bindings/_bleio/ScanEntry.c +++ b/shared-bindings/_bleio/ScanEntry.c @@ -25,11 +25,12 @@ //| """Cannot be instantiated directly. Use `_bleio.Adapter.start_scan`.""" //| ... //| -//| def matches(self, prefixes: ScanEntry, *, match_all: bool = True) -> bool: +//| def matches(self, prefixes: ReadableBuffer, *, match_all: bool = True) -> bool: //| """Returns True if the ScanEntry matches all prefixes when ``match_all`` is True. This is stricter //| than the scan filtering which accepts any advertisements that match any of the prefixes //| where ``match_all`` is False.""" //| ... +//| static mp_obj_t bleio_scanentry_matches(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -97,6 +98,7 @@ MP_PROPERTY_GETTER(bleio_scanentry_connectable_obj, //| scan_response: bool //| """True if the entry was a scan response. (read-only)""" //| +//| static mp_obj_t scanentry_get_scan_response(mp_obj_t self_in) { bleio_scanentry_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(common_hal_bleio_scanentry_get_scan_response(self)); diff --git a/shared-bindings/_bleio/ScanResults.c b/shared-bindings/_bleio/ScanResults.c index 81680902e4da9..2b52615f81627 100644 --- a/shared-bindings/_bleio/ScanResults.c +++ b/shared-bindings/_bleio/ScanResults.c @@ -40,6 +40,7 @@ static mp_obj_t scanresults_iternext(mp_obj_t self_in) { //| """ //| ... //| +//| MP_DEFINE_CONST_OBJ_TYPE( bleio_scanresults_type, diff --git a/shared-bindings/_bleio/Service.c b/shared-bindings/_bleio/Service.c index 00da34c8bce2d..cea9a68e69416 100644 --- a/shared-bindings/_bleio/Service.c +++ b/shared-bindings/_bleio/Service.c @@ -27,6 +27,7 @@ //| //| :return: the new Service""" //| ... +//| static mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_uuid, ARG_secondary }; static const mp_arg_t allowed_args[] = { @@ -41,8 +42,7 @@ static mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const bool is_secondary = args[ARG_secondary].u_bool; - bleio_service_obj_t *service = m_new_obj_with_finaliser(bleio_service_obj_t); - service->base.type = &bleio_service_type; + bleio_service_obj_t *service = mp_obj_malloc_with_finaliser(bleio_service_obj_t, &bleio_service_type); common_hal_bleio_service_construct(service, uuid, is_secondary); @@ -52,6 +52,7 @@ static mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, //| def deinit(self) -> None: //| """Disable and deinitialise the Service.""" //| ... +//| static mp_obj_t bleio_service_deinit(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_bleio_service_deinit(self); @@ -100,6 +101,7 @@ MP_PROPERTY_GETTER(bleio_service_secondary_obj, //| //| Will be ``None`` if the 128-bit UUID for this service is not known.""" //| +//| static mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_bleio/UUID.c b/shared-bindings/_bleio/UUID.c index 5dac1b3ecfdea..eef8546e2535c 100644 --- a/shared-bindings/_bleio/UUID.c +++ b/shared-bindings/_bleio/UUID.c @@ -30,23 +30,22 @@ //| :param value: The uuid value to encapsulate //| :type value: int, ~circuitpython_typing.ReadableBuffer or str""" //| ... +//| static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); - const mp_obj_t value = all_args[0]; uint8_t uuid128[16]; if (mp_obj_is_int(value)) { - mp_int_t uuid16 = mp_obj_get_int(value); - if (uuid16 < 0 || uuid16 > 0xffff) { - mp_raise_ValueError(MP_ERROR_TEXT("UUID integer value must be 0-0xffff")); - } + const mp_int_t uuid16 = + mp_arg_validate_int_range(mp_obj_get_int(value), 0, 0xffff, MP_QSTR_value); // NULL means no 128-bit value. + bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); common_hal_bleio_uuid_construct(self, uuid16, NULL); + return MP_OBJ_FROM_PTR(self); } else { if (mp_obj_is_str(value)) { // 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' @@ -81,9 +80,7 @@ static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, si mp_raise_ValueError(MP_ERROR_TEXT("UUID value is not str, int or byte buffer")); } - if (bufinfo.len != 16) { - mp_raise_ValueError(MP_ERROR_TEXT("Byte buffer must be 16 bytes.")); - } + mp_arg_validate_length(bufinfo.len, 16, MP_QSTR_value); memcpy(uuid128, bufinfo.buf, 16); } @@ -92,10 +89,12 @@ static mp_obj_t bleio_uuid_make_new(const mp_obj_type_t *type, size_t n_args, si uint32_t uuid16 = (uuid128[13] << 8) | uuid128[12]; uuid128[12] = 0; uuid128[13] = 0; + + bleio_uuid_obj_t *self = mp_obj_malloc(bleio_uuid_obj_t, &bleio_uuid_type); common_hal_bleio_uuid_construct(self, uuid16, uuid128); - } - return MP_OBJ_FROM_PTR(self); + return MP_OBJ_FROM_PTR(self); + } } //| uuid16: int @@ -138,6 +137,7 @@ MP_PROPERTY_GETTER(bleio_uuid_uuid128_obj, //| 16-bit Bluetooth SIG assigned UUID. (read-only) 32-bit UUIDs are not currently supported. //| //| :type: int""" +//| static mp_obj_t bleio_uuid_get_size(mp_obj_t self_in) { bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_uuid_get_size(self)); @@ -152,6 +152,7 @@ MP_PROPERTY_GETTER(bleio_uuid_size_obj, //| def pack_into(self, buffer: WriteableBuffer, offset: int = 0) -> None: //| """Packs the UUID into the given buffer at the given offset.""" //| ... +//| static mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_uuid_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -168,12 +169,12 @@ static mp_obj_t bleio_uuid_pack_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); - size_t offset = args[ARG_offset].u_int; - if (offset + common_hal_bleio_uuid_get_size(self) / 8 > bufinfo.len) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer + offset too small %d %d %d")); - } + const mp_int_t offset = + mp_arg_validate_int_range(args[ARG_offset].u_int, 0, (mp_int_t)bufinfo.len, MP_QSTR_offset); + const size_t packed_len = common_hal_bleio_uuid_get_size(self) / 8; + mp_arg_validate_length_min(bufinfo.len - (size_t)offset, packed_len, MP_QSTR_buffer); - common_hal_bleio_uuid_pack_into(self, bufinfo.buf + offset); + common_hal_bleio_uuid_pack_into(self, (uint8_t *)bufinfo.buf + (size_t)offset); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_KW(bleio_uuid_pack_into_obj, 1, bleio_uuid_pack_into); @@ -214,6 +215,7 @@ static mp_obj_t bleio_uuid_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| """Two UUID objects are equal if their values match and they are both 128-bit or both 16-bit.""" //| ... //| +//| static mp_obj_t bleio_uuid_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { // Two UUID's are equal if their uuid16 values match or their uuid128 values match. diff --git a/shared-bindings/_bleio/__init__.c b/shared-bindings/_bleio/__init__.c index c0cd439f7d924..1ec9fd96e766b 100644 --- a/shared-bindings/_bleio/__init__.c +++ b/shared-bindings/_bleio/__init__.c @@ -33,20 +33,30 @@ //| `adafruit_ble `_ //| CircuitPython library instead, which builds on `_bleio`, and //| provides higher-level convenience functionality, including predefined beacons, clients, -//| servers.""" +//| servers. +//| +//| .. note:: `_bleio` uses native BLE capability on boards that support it, including Nordic nRF, +//| Espressif (except ESP32-S2 and ESP32-P4), and SiLabs. +//| On other boards, `_bleio`, if present, supports BLE using an AirLift co-processor. +//| Pico W boards do *not* support BLE using the on-board CYW43 co-processor, +//| but do support using an external AirLift. +//| """ +//| //| adapter: Adapter //| """BLE Adapter used to manage device discovery and connections. //| This object is the sole instance of `_bleio.Adapter`.""" //| +//| //| class BluetoothError(Exception): //| """Catchall exception for Bluetooth related errors.""" //| //| ... //| +//| MP_DEFINE_BLEIO_EXCEPTION(BluetoothError, Exception) -NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_BluetoothError, fmt, argptr); @@ -60,8 +70,9 @@ NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t fmt, ...) { //| //| ... //| +//| MP_DEFINE_BLEIO_EXCEPTION(RoleError, bleio_BluetoothError) -NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { +MP_NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { mp_raise_msg(&mp_type_bleio_RoleError, msg); } @@ -70,8 +81,9 @@ NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg) { //| //| ... //| +//| MP_DEFINE_BLEIO_EXCEPTION(SecurityError, bleio_BluetoothError) -NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_bleio_SecurityError, fmt, argptr); @@ -101,6 +113,7 @@ static mp_obj_dict_t bleio_module_globals; //| Raises `NotImplementedError` when the adapter is a singleton and cannot be set.""" //| ... //| +//| mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj) { #if CIRCUITPY_BLEIO_HCI (void)mp_arg_validate_type_or_none(adapter_obj, &bleio_adapter_type, MP_QSTR_adapter); diff --git a/shared-bindings/_bleio/__init__.h b/shared-bindings/_bleio/__init__.h index faf11ea1d0637..0c5a5fec06b29 100644 --- a/shared-bindings/_bleio/__init__.h +++ b/shared-bindings/_bleio/__init__.h @@ -45,19 +45,11 @@ void common_hal_bleio_init(void); extern mp_obj_t bleio_set_adapter(mp_obj_t adapter_obj); -NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); -NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg); -NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_bleio_BluetoothError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_bleio_RoleError(mp_rom_error_text_t msg); +MP_NORETURN void mp_raise_bleio_SecurityError(mp_rom_error_text_t msg, ...); bleio_adapter_obj_t *common_hal_bleio_allocate_adapter_or_raise(void); -void common_hal_bleio_check_connected(uint16_t conn_handle); - -uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); -size_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); -void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); -size_t common_hal_bleio_gattc_read(uint16_t handle, uint16_t conn_handle, uint8_t *buf, size_t len); -void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); - void common_hal_bleio_gc_collect(void); diff --git a/shared-bindings/_eve/__init__.c b/shared-bindings/_eve/__init__.c index bbcb329203166..a3914d07f324f 100644 --- a/shared-bindings/_eve/__init__.c +++ b/shared-bindings/_eve/__init__.c @@ -11,6 +11,11 @@ #include "py/runtime.h" #include "py/binary.h" +#if CIRCUITPY_ULAB +#include "extmod/ulab/code/ulab.h" +#include "extmod/ulab/code/ndarray.h" +#endif + #include "shared-module/_eve/__init__.h" #include "shared-bindings/_eve/__init__.h" @@ -20,9 +25,11 @@ //| contains methods for constructing EVE command //| buffers and appending basic graphics commands.""" //| +//| //| class _EVE: //| def __init__(self) -> None: //| """Create an _EVE object""" +//| typedef struct _mp_obj__EVE_t { mp_obj_base_t base; common_hal__eve_t _eve; @@ -33,7 +40,10 @@ static const mp_obj_type_t _EVE_type; #define EVEHAL(s) \ (&((mp_obj__EVE_t *)mp_obj_cast_to_native_base((s), &_EVE_type))->_eve) -//| def register(self, o: object) -> None: ... +//| def register(self, o: object) -> None: +//| """Register an object's ``write()`` function""" +//| ... +//| static mp_obj_t _register(mp_obj_t self, mp_obj_t o) { common_hal__eve_t *eve = EVEHAL(self); mp_load_method(o, MP_QSTR_write, eve->dest); @@ -41,11 +51,25 @@ static mp_obj_t _register(mp_obj_t self, mp_obj_t o) { } static MP_DEFINE_CONST_FUN_OBJ_2(register_obj, _register); +//| +//| def setmodel(self, m: int) -> None: +//| """Set the model number of the EVE chip""" +//| ... +//| +static mp_obj_t _setmodel(mp_obj_t self, mp_obj_t m) { + common_hal__eve_t *eve = EVEHAL(self); + eve->model = mp_obj_get_int_truncated(m); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(setmodel_obj, _setmodel); + +//| //| def flush(self) -> None: //| """Send any queued drawing commands directly to the hardware. //| //| :param int width: The width of the grid in tiles, or 1 for sprites.""" //| ... +//| static mp_obj_t _flush(mp_obj_t self) { common_hal__eve_flush(EVEHAL(self)); return mp_const_none; @@ -57,6 +81,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(flush_obj, _flush); //| //| :param ~circuitpython_typing.ReadableBuffer b: The bytes to add""" //| ... +//| static mp_obj_t _cc(mp_obj_t self, mp_obj_t b) { mp_buffer_info_t buffer_info; mp_get_buffer_raise(b, &buffer_info, MP_BUFFER_READ); @@ -76,6 +101,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(cc_obj, _cc); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _alphafunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t func = mp_obj_get_int_truncated(a0); @@ -93,6 +119,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(alphafunc_obj, _alphafunc); //| Valid primitives are ``BITMAPS``, ``POINTS``, ``LINES``, ``LINE_STRIP``, ``EDGE_STRIP_R``, ``EDGE_STRIP_L``, ``EDGE_STRIP_A``, ``EDGE_STRIP_B`` and ``RECTS``. //| """ //| ... +//| static mp_obj_t _begin(mp_obj_t self, mp_obj_t a0) { uint32_t prim = mp_obj_get_int_truncated(a0); @@ -106,6 +133,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(begin_obj, _begin); //| //| :param int format: bitmap pixel format.""" //| ... +//| static mp_obj_t _bitmapextformat(mp_obj_t self, mp_obj_t a0) { uint32_t fmt = mp_obj_get_int_truncated(a0); @@ -122,6 +150,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(bitmapextformat_obj, _bitmapextformat); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _bitmaphandle(mp_obj_t self, mp_obj_t a0) { uint32_t handle = mp_obj_get_int_truncated(a0); @@ -136,6 +165,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(bitmaphandle_obj, _bitmaphandle); //| :param int linestride: high part of bitmap line stride, in bytes. Range 0-7 //| :param int height: high part of bitmap height, in lines. Range 0-3""" //| ... +//| static mp_obj_t _bitmaplayouth(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t linestride = mp_obj_get_int_truncated(a0); @@ -152,6 +182,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(bitmaplayouth_obj, _bitmaplayouth); //| :param int linestride: bitmap line stride, in bytes. Range 0-1023 //| :param int height: bitmap height, in lines. Range 0-511""" //| ... +//| static mp_obj_t _bitmaplayout(size_t n_args, const mp_obj_t *args) { uint32_t format = mp_obj_get_int_truncated(args[1]); @@ -168,6 +199,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaplayout_obj, 4, 4, _bitmaplayout //| :param int width: high part of drawn bitmap width, in pixels. Range 0-3 //| :param int height: high part of drawn bitmap height, in pixels. Range 0-3""" //| ... +//| static mp_obj_t _bitmapsizeh(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t width = mp_obj_get_int_truncated(a0); @@ -186,6 +218,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(bitmapsizeh_obj, _bitmapsizeh); //| :param int width: drawn bitmap width, in pixels. Range 0-511 //| :param int height: drawn bitmap height, in pixels. Range 0-511""" //| ... +//| static mp_obj_t _bitmapsize(size_t n_args, const mp_obj_t *args) { uint32_t filter = mp_obj_get_int_truncated(args[1]); @@ -201,9 +234,10 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapsize_obj, 6, 6, _bitmapsize); //| def BitmapSource(self, addr: int) -> None: //| """Set the source address for bitmap graphics //| -//| :param int addr: Bitmap start address, pixel-aligned. May be in SRAM or flash. Range 0-16777215 +//| :param int addr: Bitmap start address, pixel-aligned, low part. //| """ //| ... +//| static mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) { uint32_t addr = mp_obj_get_int_truncated(a0); @@ -212,6 +246,21 @@ static mp_obj_t _bitmapsource(mp_obj_t self, mp_obj_t a0) { } static MP_DEFINE_CONST_FUN_OBJ_2(bitmapsource_obj, _bitmapsource); +//| def BitmapSourceH(self, addr: int) -> None: +//| """Set the high source address for bitmap graphics +//| +//| :param int addr: Bitmap start address, pixel-aligned, high part. +//| """ +//| ... +//| + +static mp_obj_t _bitmapsourceh(mp_obj_t self, mp_obj_t a0) { + uint32_t addr = mp_obj_get_int_truncated(a0); + common_hal__eve_BitmapSourceH(EVEHAL(self), addr); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(bitmapsourceh_obj, _bitmapsourceh); + //| def BitmapSwizzle(self, r: int, g: int, b: int, a: int) -> None: //| """Set the source for the r,g,b and a channels of a bitmap //| @@ -220,6 +269,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(bitmapsource_obj, _bitmapsource); //| :param int b: blue component source channel. Range 0-7 //| :param int a: alpha component source channel. Range 0-7""" //| ... +//| static mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) { uint32_t r = mp_obj_get_int_truncated(args[1]); @@ -231,113 +281,159 @@ static mp_obj_t _bitmapswizzle(size_t n_args, const mp_obj_t *args) { } static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmapswizzle_obj, 5, 5, _bitmapswizzle); -//| def BitmapTransformA(self, p: int, v: int) -> None: +//| def BitmapTransformA(self, v: float) -> None: //| """Set the :math:`a` component of the bitmap transform matrix //| -//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 -//| :param int v: The :math:`a` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256 +//| :param float v: The :math:`a` component of the bitmap transform matrix //| -//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0. +//| The initial value 1.0. //| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| + +static void _transform1(uint32_t *p, uint32_t *v, size_t n_args, const mp_obj_t *args) { + common_hal__eve_t *eve = EVEHAL(args[0]); + mp_float_t a; -static mp_obj_t _bitmaptransforma(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t p = mp_obj_get_int_truncated(a0); - uint32_t v = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformA(EVEHAL(self), p, v); + if (eve->model == 0) { + // Backwards-compatible case for legacy code + if (n_args != 3) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), 2, n_args - 1); + } + *p = mp_obj_get_int_truncated(args[1]); + *v = mp_obj_get_int_truncated(args[2]); + } else { + if (n_args != 2) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("function takes %d positional arguments but %d were given"), 1, n_args - 1); + } + a = mp_obj_get_float(args[1]); + if ((eve->model > 810) && (-2.0 <= a) && (a < 2.0)) { + *p = 1; + *v = (int)(32768.0 * a); + } else { + *p = 0; + *v = (int)(256.0 * a); + } + } +} + +static mp_obj_t _bitmaptransforma(size_t n_args, const mp_obj_t *args) { + uint32_t p, v; + _transform1(&p, &v, n_args, args); + common_hal__eve_BitmapTransformA(EVEHAL(args[0]), p, v); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforma_obj, _bitmaptransforma); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaptransforma_obj, 2, 3, _bitmaptransforma); -//| def BitmapTransformB(self, p: int, v: int) -> None: +//| def BitmapTransformB(self, v: float) -> None: //| """Set the :math:`b` component of the bitmap transform matrix //| -//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 -//| :param int v: The :math:`b` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0 +//| :param float v: The :math:`b` component of the bitmap transform matrix //| -//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0. +//| The initial value 0.0. //| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| -static mp_obj_t _bitmaptransformb(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t p = mp_obj_get_int_truncated(a0); - uint32_t v = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformB(EVEHAL(self), p, v); +static mp_obj_t _bitmaptransformb(size_t n_args, const mp_obj_t *args) { + uint32_t p, v; + _transform1(&p, &v, n_args, args); + common_hal__eve_BitmapTransformB(EVEHAL(args[0]), p, v); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformb_obj, _bitmaptransformb); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaptransformb_obj, 2, 3, _bitmaptransformb); -//| def BitmapTransformC(self, v: int) -> None: +//| def BitmapTransformC(self, v: float) -> None: //| """Set the :math:`c` component of the bitmap transform matrix //| -//| :param int v: The :math:`c` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 +//| :param int v: The :math:`c` component of the bitmap transform matrix +//| +//| The initial value 0.0. //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _bitmaptransformc(mp_obj_t self, mp_obj_t a0) { - uint32_t v = mp_obj_get_int_truncated(a0); + common_hal__eve_t *eve = EVEHAL(self); + int v; + + if (eve->model == 0) { + v = mp_obj_get_int_truncated(a0); + } else { + v = (int)(256.0 * mp_obj_get_float(a0)); + } common_hal__eve_BitmapTransformC(EVEHAL(self), v); return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformc_obj, _bitmaptransformc); -//| def BitmapTransformD(self, p: int, v: int) -> None: +//| def BitmapTransformD(self, v: float) -> None: //| """Set the :math:`d` component of the bitmap transform matrix //| -//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 -//| :param int v: The :math:`d` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 0 +//| :param float v: The :math:`d` component of the bitmap transform matrix //| -//| The initial value is **p** = 0, **v** = 0. This represents the value 0.0. +//| The initial value 0.0. //| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| -static mp_obj_t _bitmaptransformd(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t p = mp_obj_get_int_truncated(a0); - uint32_t v = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformD(EVEHAL(self), p, v); +static mp_obj_t _bitmaptransformd(size_t n_args, const mp_obj_t *args) { + uint32_t p, v; + _transform1(&p, &v, n_args, args); + common_hal__eve_BitmapTransformD(EVEHAL(args[0]), p, v); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransformd_obj, _bitmaptransformd); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaptransformd_obj, 2, 3, _bitmaptransformd); -//| def BitmapTransformE(self, p: int, v: int) -> None: +//| def BitmapTransformE(self, v: float) -> None: //| """Set the :math:`e` component of the bitmap transform matrix //| -//| :param int p: precision control: 0 is 8.8, 1 is 1.15. Range 0-1. The initial value is 0 -//| :param int v: The :math:`e` component of the bitmap transform matrix, in signed 8.8 or 1.15 bit fixed-point form. Range 0-131071. The initial value is 256 +//| :param float v: The :math:`e` component of the bitmap transform matrix //| -//| The initial value is **p** = 0, **v** = 256. This represents the value 1.0. +//| The initial value 1.0. //| //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| -static mp_obj_t _bitmaptransforme(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { - uint32_t p = mp_obj_get_int_truncated(a0); - uint32_t v = mp_obj_get_int_truncated(a1); - common_hal__eve_BitmapTransformE(EVEHAL(self), p, v); +static mp_obj_t _bitmaptransforme(size_t n_args, const mp_obj_t *args) { + uint32_t p, v; + _transform1(&p, &v, n_args, args); + common_hal__eve_BitmapTransformE(EVEHAL(args[0]), p, v); return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_3(bitmaptransforme_obj, _bitmaptransforme); +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitmaptransforme_obj, 2, 3, _bitmaptransforme); //| def BitmapTransformF(self, v: int) -> None: //| """Set the :math:`f` component of the bitmap transform matrix //| -//| :param int v: The :math:`f` component of the bitmap transform matrix, in signed 15.8 bit fixed-point form. Range 0-16777215. The initial value is 0 +//| :param int v: The :math:`f` component of the bitmap transform matrix +//| +//| The initial value 0.0. //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _bitmaptransformf(mp_obj_t self, mp_obj_t a0) { - uint32_t v = mp_obj_get_int_truncated(a0); + common_hal__eve_t *eve = EVEHAL(self); + int v; + + if (eve->model == 0) { + v = mp_obj_get_int_truncated(a0); + } else { + v = (int)(256.0 * mp_obj_get_float(a0)); + } common_hal__eve_BitmapTransformF(EVEHAL(self), v); return mp_const_none; } @@ -352,6 +448,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(bitmaptransformf_obj, _bitmaptransformf); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _blendfunc(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t src = mp_obj_get_int_truncated(a0); @@ -366,6 +463,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(blendfunc_obj, _blendfunc); //| //| :param int dest: display list address. Range 0-65535""" //| ... +//| static mp_obj_t _call(mp_obj_t self, mp_obj_t a0) { uint32_t dest = mp_obj_get_int_truncated(a0); @@ -382,6 +480,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(call_obj, _call); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _cell(mp_obj_t self, mp_obj_t a0) { uint32_t cell = mp_obj_get_int_truncated(a0); @@ -398,6 +497,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(cell_obj, _cell); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _clearcolora(mp_obj_t self, mp_obj_t a0) { uint32_t alpha = mp_obj_get_int_truncated(a0); @@ -416,6 +516,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(clearcolora_obj, _clearcolora); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _clearcolorrgb(size_t n_args, const mp_obj_t *args) { uint32_t red = mp_obj_get_int_truncated(args[1]); @@ -433,6 +534,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clearcolorrgb_obj, 4, 4, _clearcolorr //| :param int s: clear stencil buffer. Range 0-1 //| :param int t: clear tag buffer. Range 0-1""" //| ... +//| static mp_obj_t _clear(size_t n_args, const mp_obj_t *args) { uint32_t c = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 1; @@ -451,6 +553,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(clear_obj, 1, 4, _clear); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _clearstencil(mp_obj_t self, mp_obj_t a0) { uint32_t s = mp_obj_get_int_truncated(a0); @@ -466,6 +569,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(clearstencil_obj, _clearstencil); //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ +//| static mp_obj_t _cleartag(mp_obj_t self, mp_obj_t a0) { uint32_t s = mp_obj_get_int_truncated(a0); @@ -482,6 +586,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(cleartag_obj, _cleartag); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _colora(mp_obj_t self, mp_obj_t a0) { uint32_t alpha = mp_obj_get_int_truncated(a0); @@ -501,6 +606,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(colora_obj, _colora); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _colormask(size_t n_args, const mp_obj_t *args) { uint32_t r = mp_obj_get_int_truncated(args[1]); @@ -522,6 +628,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colormask_obj, 5, 5, _colormask); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _colorrgb(size_t n_args, const mp_obj_t *args) { uint32_t red = mp_obj_get_int_truncated(args[1]); @@ -535,6 +642,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(colorrgb_obj, 4, 4, _colorrgb); //| def Display(self) -> None: //| """End the display list""" //| ... +//| static mp_obj_t _display(mp_obj_t self) { @@ -549,6 +657,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(display_obj, _display); //| :meth:`Vertex2ii` and :meth:`Vertex2f` calls are ignored until the next :meth:`Begin`. //| """ //| ... +//| static mp_obj_t _end(mp_obj_t self) { @@ -562,6 +671,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(end_obj, _end); //| //| :param int dest: display list address. Range 0-65535""" //| ... +//| static mp_obj_t _jump(mp_obj_t self, mp_obj_t a0) { uint32_t dest = mp_obj_get_int_truncated(a0); @@ -575,6 +685,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(jump_obj, _jump); //| //| :param int m: macro register to read. Range 0-1""" //| ... +//| static mp_obj_t _macro(mp_obj_t self, mp_obj_t a0) { uint32_t m = mp_obj_get_int_truncated(a0); @@ -586,6 +697,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(macro_obj, _macro); //| def Nop(self) -> None: //| """No operation""" //| ... +//| static mp_obj_t _nop(mp_obj_t self) { @@ -597,11 +709,12 @@ static MP_DEFINE_CONST_FUN_OBJ_1(nop_obj, _nop); //| def PaletteSource(self, addr: int) -> None: //| """Set the base address of the palette //| -//| :param int addr: Address in graphics SRAM, 2-byte aligned. Range 0-4194303. The initial value is 0 +//| :param int addr: Address in graphics RAM, 2-byte aligned, low part. //| //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) { uint32_t addr = mp_obj_get_int_truncated(a0); @@ -610,9 +723,27 @@ static mp_obj_t _palettesource(mp_obj_t self, mp_obj_t a0) { } static MP_DEFINE_CONST_FUN_OBJ_2(palettesource_obj, _palettesource); +//| def PaletteSourceH(self, addr: int) -> None: +//| """Set the base address of the palette +//| +//| :param int addr: Address in graphics RAM, 2-byte aligned, high part. +//| +//| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. +//| """ +//| ... +//| + +static mp_obj_t _palettesourceh(mp_obj_t self, mp_obj_t a0) { + uint32_t addr = mp_obj_get_int_truncated(a0); + common_hal__eve_PaletteSourceH(EVEHAL(self), addr); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(palettesourceh_obj, _palettesourceh); + //| def RestoreContext(self) -> None: //| """Restore the current graphics context from the context stack""" //| ... +//| static mp_obj_t _restorecontext(mp_obj_t self) { @@ -624,6 +755,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(restorecontext_obj, _restorecontext); //| def Return(self) -> None: //| """Return from a previous call command""" //| ... +//| static mp_obj_t _return(mp_obj_t self) { @@ -635,6 +767,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(return_obj, _return); //| def SaveContext(self) -> None: //| """Push the current graphics context on the context stack""" //| ... +//| static mp_obj_t _savecontext(mp_obj_t self) { @@ -652,6 +785,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(savecontext_obj, _savecontext); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _scissorsize(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t width = mp_obj_get_int_truncated(a0); @@ -670,6 +804,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(scissorsize_obj, _scissorsize); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _scissorxy(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t x = mp_obj_get_int_truncated(a0); @@ -689,6 +824,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(scissorxy_obj, _scissorxy); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _stencilfunc(size_t n_args, const mp_obj_t *args) { uint32_t func = mp_obj_get_int_truncated(args[1]); @@ -707,6 +843,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stencilfunc_obj, 4, 4, _stencilfunc); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _stencilmask(mp_obj_t self, mp_obj_t a0) { uint32_t mask = mp_obj_get_int_truncated(a0); @@ -724,6 +861,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(stencilmask_obj, _stencilmask); //| These values are part of the graphics context and are saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _stencilop(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { uint32_t sfail = mp_obj_get_int_truncated(a0); @@ -741,6 +879,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(stencilop_obj, _stencilop); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _tagmask(mp_obj_t self, mp_obj_t a0) { uint32_t mask = mp_obj_get_int_truncated(a0); @@ -757,6 +896,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(tagmask_obj, _tagmask); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _tag(mp_obj_t self, mp_obj_t a0) { uint32_t s = mp_obj_get_int_truncated(a0); @@ -780,6 +920,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(vertexformat_obj, _vertexformat); //| //| This method is an alternative to :meth:`Vertex2f`.""" //| ... +//| static mp_obj_t _vertex2ii(size_t n_args, const mp_obj_t *args) { uint32_t x = mp_obj_get_int_truncated(args[1]); @@ -801,6 +942,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii); { MP_ROM_QSTR(MP_QSTR_BitmapSizeH), MP_ROM_PTR(&bitmapsizeh_obj) }, \ { MP_ROM_QSTR(MP_QSTR_BitmapSize), MP_ROM_PTR(&bitmapsize_obj) }, \ { MP_ROM_QSTR(MP_QSTR_BitmapSource), MP_ROM_PTR(&bitmapsource_obj) }, \ + { MP_ROM_QSTR(MP_QSTR_BitmapSourceH), MP_ROM_PTR(&bitmapsourceh_obj) }, \ { MP_ROM_QSTR(MP_QSTR_BitmapSwizzle), MP_ROM_PTR(&bitmapswizzle_obj) }, \ { MP_ROM_QSTR(MP_QSTR_BitmapTransformA), MP_ROM_PTR(&bitmaptransforma_obj) }, \ { MP_ROM_QSTR(MP_QSTR_BitmapTransformB), MP_ROM_PTR(&bitmaptransformb_obj) }, \ @@ -826,7 +968,9 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii); { MP_ROM_QSTR(MP_QSTR_Macro), MP_ROM_PTR(¯o_obj) }, \ { MP_ROM_QSTR(MP_QSTR_Nop), MP_ROM_PTR(&nop_obj) }, \ { MP_ROM_QSTR(MP_QSTR_PaletteSource), MP_ROM_PTR(&palettesource_obj) }, \ + { MP_ROM_QSTR(MP_QSTR_PaletteSourceH), MP_ROM_PTR(&palettesourceh_obj) }, \ { MP_ROM_QSTR(MP_QSTR_PointSize), MP_ROM_PTR(&pointsize_obj) }, \ + { MP_ROM_QSTR(MP_QSTR_Region), MP_ROM_PTR(®ion_obj) }, \ { MP_ROM_QSTR(MP_QSTR_RestoreContext), MP_ROM_PTR(&restorecontext_obj) }, \ { MP_ROM_QSTR(MP_QSTR_Return), MP_ROM_PTR(&return_obj) }, \ { MP_ROM_QSTR(MP_QSTR_SaveContext), MP_ROM_PTR(&savecontext_obj) }, \ @@ -844,6 +988,19 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii); // } +#if CIRCUITPY_ULAB +static bool is_vector(mp_obj_t a) { + if (!mp_obj_is_type(a, &ulab_ndarray_type)) { + return false; + } + ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(a); + if (!ndarray_is_dense(ndarray)) { + mp_raise_TypeError(MP_ERROR_TEXT("input must be an ndarray")); + } + return true; +} +#endif + // Hand-written functions { //| def Vertex2f(self, b: float) -> None: @@ -852,7 +1009,20 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vertex2ii_obj, 3, 5, _vertex2ii); //| :param float x: pixel x-coordinate //| :param float y: pixel y-coordinate""" //| ... +//| static mp_obj_t _vertex2f(mp_obj_t self, mp_obj_t a0, mp_obj_t a1) { + #if CIRCUITPY_ULAB + if (is_vector(a0) && is_vector(a1)) { + ndarray_obj_t *v0 = MP_OBJ_TO_PTR(a0); + ndarray_obj_t *v1 = MP_OBJ_TO_PTR(a1); + mp_float_t *p0 = (mp_float_t *)v0->array; + mp_float_t *p1 = (mp_float_t *)v1->array; + for (size_t i = 0; i < v0->len; i++, p0++, p1++) { + common_hal__eve_Vertex2f(EVEHAL(self), *p0, *p1); + } + return mp_const_none; + } + #endif mp_float_t x = mp_obj_get_float(a0); mp_float_t y = mp_obj_get_float(a1); common_hal__eve_Vertex2f(EVEHAL(self), x, y); @@ -868,6 +1038,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(vertex2f_obj, _vertex2f); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _linewidth(mp_obj_t self, mp_obj_t a0) { mp_float_t width = mp_obj_get_float(a0); @@ -884,14 +1055,36 @@ static MP_DEFINE_CONST_FUN_OBJ_2(linewidth_obj, _linewidth); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _pointsize(mp_obj_t self, mp_obj_t a0) { mp_float_t size = mp_obj_get_float(a0); common_hal__eve_PointSize(EVEHAL(self), size); return mp_const_none; } + static MP_DEFINE_CONST_FUN_OBJ_2(pointsize_obj, _pointsize); +//| def Region(self, y: int, h: int, dest: int) -> None: +//| """Specify a cull region in the display list +//| +//| :param int y: Starting Y band in the render buffer. Range 0-63 +//| :param int h: Y height in the render buffer. Range 0-63 +//| :param int dest: destination address in the display list if the raster is outside the region +//| +//| """ +//| ... +//| + +static mp_obj_t _region(size_t n_args, const mp_obj_t *args) { + uint32_t y = mp_obj_get_int_truncated(args[1]); + uint32_t h = mp_obj_get_int_truncated(args[2]); + uint32_t dest = mp_obj_get_int_truncated(args[3]); + common_hal__eve_Region(EVEHAL(args[0]), y, h, dest); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(region_obj, 4, 4, _region); + //| def VertexTranslateX(self, x: float) -> None: //| """Set the vertex transformation's x translation component //| @@ -900,6 +1093,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(pointsize_obj, _pointsize); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _vertextranslatex(mp_obj_t self, mp_obj_t a0) { mp_float_t x = mp_obj_get_float(a0); @@ -916,6 +1110,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatex_obj, _vertextranslatex); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| static mp_obj_t _vertextranslatey(mp_obj_t self, mp_obj_t a0) { @@ -933,6 +1128,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatey_obj, _vertextranslatey); //| This value is part of the graphics context and is saved and restored by :meth:`SaveContext` and :meth:`RestoreContext`. //| """ //| ... +//| // } @@ -948,6 +1144,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(vertextranslatey_obj, _vertextranslatey); //| This method is used by the ``eve`` module to efficiently add //| commands to the FIFO.""" //| ... +//| static mp_obj_t _cmd0(mp_obj_t self, mp_obj_t n) { uint32_t code = 0xffffff00 | mp_obj_get_int_truncated(n); @@ -970,6 +1167,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(cmd0_obj, _cmd0); //| commands to the FIFO.""" //| ... //| +//| static mp_obj_t _cmd(size_t n_args, const mp_obj_t *args) { mp_obj_t self = args[0]; mp_obj_t num = args[1]; @@ -1027,6 +1225,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(cmd_obj, 4, 4, _cmd); static const mp_rom_map_elem_t _EVE_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(®ister_obj) }, + { MP_ROM_QSTR(MP_QSTR_setmodel), MP_ROM_PTR(&setmodel_obj) }, { MP_ROM_QSTR(MP_QSTR_cc), MP_ROM_PTR(&cc_obj) }, { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&flush_obj) }, { MP_ROM_QSTR(MP_QSTR_Vertex2f), MP_ROM_PTR(&vertex2f_obj) }, @@ -1041,6 +1240,7 @@ static mp_obj_t _EVE_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_obj__EVE_t *o = mp_obj_malloc(mp_obj__EVE_t, &_EVE_type); o->_eve.n = 0; o->_eve.vscale = 16; + o->_eve.model = 0; // default is legacy behavior return MP_OBJ_FROM_PTR(o); } diff --git a/shared-bindings/_eve/__init__.h b/shared-bindings/_eve/__init__.h index ea743cbf07fef..13ae1b8a6cb50 100644 --- a/shared-bindings/_eve/__init__.h +++ b/shared-bindings/_eve/__init__.h @@ -21,6 +21,7 @@ void common_hal__eve_BitmapLayout(common_hal__eve_t *eve, uint32_t format, uint3 void common_hal__eve_BitmapSizeH(common_hal__eve_t *eve, uint32_t width, uint32_t height); void common_hal__eve_BitmapSize(common_hal__eve_t *eve, uint32_t filter, uint32_t wrapx, uint32_t wrapy, uint32_t width, uint32_t height); void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_BitmapSourceH(common_hal__eve_t *eve, uint32_t addr); void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a); void common_hal__eve_BitmapTransformA(common_hal__eve_t *eve, uint32_t p, uint32_t v); void common_hal__eve_BitmapTransformB(common_hal__eve_t *eve, uint32_t p, uint32_t v); @@ -46,7 +47,9 @@ void common_hal__eve_LineWidth(common_hal__eve_t *eve, mp_float_t width); void common_hal__eve_Macro(common_hal__eve_t *eve, uint32_t m); void common_hal__eve_Nop(common_hal__eve_t *eve); void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr); +void common_hal__eve_PaletteSourceH(common_hal__eve_t *eve, uint32_t addr); void common_hal__eve_PointSize(common_hal__eve_t *eve, mp_float_t size); +void common_hal__eve_Region(common_hal__eve_t *eve, uint32_t y, uint32_t h, uint32_t dest); void common_hal__eve_RestoreContext(common_hal__eve_t *eve); void common_hal__eve_Return(common_hal__eve_t *eve); void common_hal__eve_SaveContext(common_hal__eve_t *eve); diff --git a/shared-bindings/_pew/PewPew.c b/shared-bindings/_pew/PewPew.c index af10b47ca6777..42e7f4d372b6b 100644 --- a/shared-bindings/_pew/PewPew.c +++ b/shared-bindings/_pew/PewPew.c @@ -41,6 +41,7 @@ //| buttons are connected to rows of the matrix).""" //| ... //| +//| static mp_obj_t pewpew_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer, ARG_rows, ARG_cols, ARG_buttons }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/_pew/__init__.c b/shared-bindings/_pew/__init__.c index 002255f1154b2..cfcf627bbcf28 100644 --- a/shared-bindings/_pew/__init__.c +++ b/shared-bindings/_pew/__init__.c @@ -31,9 +31,9 @@ static MP_DEFINE_CONST_FUN_OBJ_0(get_ticks_obj, get_ticks); //| """LED matrix driver""" static const mp_rom_map_elem_t pew_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__pew) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_PewPew), MP_ROM_PTR(&pewpew_type)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&get_pressed_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_ticks), MP_ROM_PTR(&get_ticks_obj)}, + { MP_ROM_QSTR(MP_QSTR_PewPew), MP_ROM_PTR(&pewpew_type)}, + { MP_ROM_QSTR(MP_QSTR_get_pressed), MP_ROM_PTR(&get_pressed_obj)}, + { MP_ROM_QSTR(MP_QSTR_get_ticks), MP_ROM_PTR(&get_ticks_obj)}, }; static MP_DEFINE_CONST_DICT(pew_module_globals, pew_module_globals_table); diff --git a/shared-bindings/_pixelmap/PixelMap.c b/shared-bindings/_pixelmap/PixelMap.c index 6bddeaac9c3f5..9e3b9bb0a8da3 100644 --- a/shared-bindings/_pixelmap/PixelMap.c +++ b/shared-bindings/_pixelmap/PixelMap.c @@ -15,9 +15,11 @@ //| from adafruit_pixelbuf import PixelBuf, PixelReturnType, PixelSequence, PixelType //| +//| //| class PixelMap: //| def __init__(self, pixelbuf: PixelBuf, indices: Tuple[Union[int, Tuple[int]]]) -> None: //| """Construct a PixelMap object that uses the given indices of the underlying pixelbuf""" +//| static mp_obj_t pixelmap_pixelmap_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pixelbuf, ARG_indices }; @@ -116,6 +118,7 @@ MP_PROPERTY_GETTER(pixelmap_pixelmap_byteorder_obj, //| //| def fill(self, color: PixelType) -> None: //| """Fill all the pixels in the map with the given color""" +//| static mp_obj_t pixelmap_pixelmap_fill(const mp_obj_t self_in, const mp_obj_t color) { pixelmap_pixelmap_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -127,6 +130,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(pixelmap_pixelmap_fill_obj, pixelmap_pixelmap_fill); //| //| def indices(self, index: int) -> Tuple[int]: //| """Return the PixelBuf indices for a PixelMap index""" +//| static mp_obj_t pixelmap_pixelmap_indices(const mp_obj_t self_in, const mp_obj_t index) { pixelmap_pixelmap_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -148,6 +152,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(pixelmap_pixelmap_indices_obj, pixelmap_pixelmap_indic //| //| @overload //| def __setitem__(self, index: slice, value: PixelSequence) -> None: ... +//| //| @overload //| def __setitem__(self, index: int, value: PixelType) -> None: //| """Sets the pixel value at the given index. Value can either be a tuple or integer. Tuples are @@ -156,6 +161,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(pixelmap_pixelmap_indices_obj, pixelmap_pixelmap_indic //| For RGBW byteorders, if given only RGB values either as an int or as a tuple, the white value //| is used instead when the red, green, and blue values are the same.""" //| ... +//| static mp_obj_t pixelmap_pixelmap_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { pixelmap_pixelmap_obj_t *self = MP_OBJ_TO_PTR(self_in); if (value == MP_OBJ_NULL) { @@ -200,6 +206,7 @@ static mp_obj_t pixelmap_pixelmap_subscr(mp_obj_t self_in, mp_obj_t index_in, mp //| def __len__(self) -> int: //| """Length of the map""" +//| static mp_obj_t pixelmap_pixelmap_unary_op(mp_unary_op_t op, mp_obj_t self_in) { pixelmap_pixelmap_obj_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { @@ -217,6 +224,7 @@ static mp_obj_t pixelmap_pixelmap_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| when `auto_write` is True.""" //| ... //| +//| static mp_obj_t pixelmap_pixelmap_show(mp_obj_t self_in) { pixelmap_pixelmap_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_stage/Layer.c b/shared-bindings/_stage/Layer.c index 3958b4c7f1c19..0d7a1bfbd5efc 100644 --- a/shared-bindings/_stage/Layer.c +++ b/shared-bindings/_stage/Layer.c @@ -33,48 +33,50 @@ //| This class is intended for internal use in the ``stage`` library and //| it shouldn't be used on its own.""" //| ... +//| static mp_obj_t layer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 4, 5, false); - layer_obj_t *self = mp_obj_malloc(layer_obj_t, type); + mp_uint_t width = mp_arg_validate_int_min(mp_obj_get_int(args[0]), 0, MP_QSTR_width); + mp_uint_t height = mp_arg_validate_int_min(mp_obj_get_int(args[1]), 0, MP_QSTR_height); - self->width = mp_obj_get_int(args[0]); - self->height = mp_obj_get_int(args[1]); - self->x = 0; - self->y = 0; - self->frame = 0; - self->rotation = false; - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - self->graphic = bufinfo.buf; - if (bufinfo.len != 2048) { - mp_raise_ValueError(MP_ERROR_TEXT("graphic must be 2048 bytes long")); - } + mp_buffer_info_t graphic_bufinfo; + mp_get_buffer_raise(args[2], &graphic_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(graphic_bufinfo.len, 2048, MP_QSTR_graphic); - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - self->palette = bufinfo.buf; - if (bufinfo.len != 32) { - mp_raise_ValueError(MP_ERROR_TEXT("palette must be 32 bytes long")); - } + mp_buffer_info_t palette_bufinfo; + mp_get_buffer_raise(args[3], &palette_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(palette_bufinfo.len, 32, MP_QSTR_palette); + mp_buffer_info_t map_bufinfo = { .buf = NULL }; if (n_args > 4) { - mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); - self->map = bufinfo.buf; - if (bufinfo.len < (self->width * self->height) / 2) { + mp_get_buffer_raise(args[4], &map_bufinfo, MP_BUFFER_READ); + if (map_bufinfo.len < (width * height) / 2) { mp_raise_ValueError(MP_ERROR_TEXT("map buffer too small")); } - } else { - self->map = NULL; } + // Only allocate after validation is finished. + layer_obj_t *self = mp_obj_malloc(layer_obj_t, type); + + self->width = width; + self->height = height; + self->x = 0; + self->y = 0; + self->frame = 0; + self->rotation = false; + self->graphic = graphic_bufinfo.buf; + self->palette = palette_bufinfo.buf; + self->map = map_bufinfo.buf; + return MP_OBJ_FROM_PTR(self); } //| def move(self, x: int, y: int) -> None: //| """Set the offset of the layer to the specified values.""" //| ... +//| static mp_obj_t layer_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { layer_obj_t *self = MP_OBJ_TO_PTR(self_in); self->x = mp_obj_get_int(x_in); @@ -88,6 +90,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(layer_move_obj, layer_move); //| graphic.""" //| ... //| +//| static mp_obj_t layer_frame(mp_obj_t self_in, mp_obj_t frame_in, mp_obj_t rotation_in) { layer_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/_stage/Text.c b/shared-bindings/_stage/Text.c index 53abf03b77365..0013ffb669797 100644 --- a/shared-bindings/_stage/Text.c +++ b/shared-bindings/_stage/Text.c @@ -33,36 +33,37 @@ //| This class is intended for internal use in the ``stage`` library and //| it shouldn't be used on its own.""" //| ... +//| static mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 5, 5, false); - text_obj_t *self = mp_obj_malloc(text_obj_t, type); - - self->width = mp_obj_get_int(args[0]); - self->height = mp_obj_get_int(args[1]); - self->x = 0; - self->y = 0; + mp_uint_t width = mp_arg_validate_int_min(mp_obj_get_int(args[0]), 0, MP_QSTR_width); + mp_uint_t height = mp_arg_validate_int_min(mp_obj_get_int(args[1]), 0, MP_QSTR_height); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); - self->font = bufinfo.buf; - if (bufinfo.len != 2048) { - mp_raise_ValueError(MP_ERROR_TEXT("font must be 2048 bytes long")); - } + mp_buffer_info_t font_bufinfo; + mp_get_buffer_raise(args[2], &font_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(font_bufinfo.len, 2048, MP_QSTR_font); - mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); - self->palette = bufinfo.buf; - if (bufinfo.len != 32) { - mp_raise_ValueError(MP_ERROR_TEXT("palette must be 32 bytes long")); - } + mp_buffer_info_t palette_bufinfo; + mp_get_buffer_raise(args[3], &palette_bufinfo, MP_BUFFER_READ); + mp_arg_validate_length(palette_bufinfo.len, 32, MP_QSTR_palette); - mp_get_buffer_raise(args[4], &bufinfo, MP_BUFFER_READ); - self->chars = bufinfo.buf; - if (bufinfo.len < self->width * self->height) { + mp_buffer_info_t chars_bufinfo; + mp_get_buffer_raise(args[4], &chars_bufinfo, MP_BUFFER_READ); + if (chars_bufinfo.len < width * height) { mp_raise_ValueError(MP_ERROR_TEXT("chars buffer too small")); } + text_obj_t *self = mp_obj_malloc(text_obj_t, type); + self->width = width; + self->height = height; + self->x = 0; + self->y = 0; + self->font = font_bufinfo.buf; + self->palette = palette_bufinfo.buf; + self->chars = chars_bufinfo.buf; + return MP_OBJ_FROM_PTR(self); } @@ -70,6 +71,7 @@ static mp_obj_t text_make_new(const mp_obj_type_t *type, size_t n_args, //| """Set the offset of the text to the specified values.""" //| ... //| +//| static mp_obj_t text_move(mp_obj_t self_in, mp_obj_t x_in, mp_obj_t y_in) { text_obj_t *self = MP_OBJ_TO_PTR(self_in); self->x = mp_obj_get_int(x_in); diff --git a/shared-bindings/_stage/__init__.c b/shared-bindings/_stage/__init__.c index 06e103e2441b6..bd5e89b5a67ab 100644 --- a/shared-bindings/_stage/__init__.c +++ b/shared-bindings/_stage/__init__.c @@ -16,8 +16,9 @@ //| """C-level helpers for animation of sprites on a stage //| -//| The `_stage` module contains native code to speed-up the ```stage`` Library -//| `_.""" +//| The `_stage` module contains native code to speed-up the ``stage`` +//| `library `_.""" +//| //| //| def render( //| x0: int, @@ -50,6 +51,7 @@ //| This function is intended for internal use in the ``stage`` library //| and all the necessary checks are performed there.""" //| +//| static mp_obj_t stage_render(size_t n_args, const mp_obj_t *args) { uint16_t x0 = mp_obj_get_int(args[0]); uint16_t y0 = mp_obj_get_int(args[1]); diff --git a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c index 737ff419ddaa1..5fb821ceade80 100644 --- a/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c +++ b/shared-bindings/adafruit_bus_device/i2c_device/I2CDevice.c @@ -43,10 +43,10 @@ //| with device: //| device.write(bytes_read) //| """ +//| //| ... +//| static mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - adafruit_bus_device_i2cdevice_obj_t *self = - mp_obj_malloc(adafruit_bus_device_i2cdevice_obj_t, &adafruit_bus_device_i2cdevice_type); enum { ARG_i2c, ARG_device_address, ARG_probe }; static const mp_arg_t allowed_args[] = { { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -58,17 +58,20 @@ static mp_obj_t adafruit_bus_device_i2cdevice_make_new(const mp_obj_type_t *type mp_obj_t *i2c = args[ARG_i2c].u_obj; + adafruit_bus_device_i2cdevice_obj_t *self = + mp_obj_malloc(adafruit_bus_device_i2cdevice_obj_t, &adafruit_bus_device_i2cdevice_type); common_hal_adafruit_bus_device_i2cdevice_construct(MP_OBJ_TO_PTR(self), i2c, args[ARG_device_address].u_int); if (args[ARG_probe].u_bool == true) { common_hal_adafruit_bus_device_i2cdevice_probe_for_device(self); } - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def __enter__(self) -> I2CDevice: //| """Context manager entry to lock bus.""" //| ... +//| static mp_obj_t adafruit_bus_device_i2cdevice_obj___enter__(mp_obj_t self_in) { adafruit_bus_device_i2cdevice_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_adafruit_bus_device_i2cdevice_lock(self); @@ -79,6 +82,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(adafruit_bus_device_i2cdevice___enter___obj, ad //| def __exit__(self) -> None: //| """Automatically unlocks the bus on exit.""" //| ... +//| static mp_obj_t adafruit_bus_device_i2cdevice_obj___exit__(size_t n_args, const mp_obj_t *args) { common_hal_adafruit_bus_device_i2cdevice_unlock(MP_OBJ_TO_PTR(args[0])); return mp_const_none; @@ -86,6 +90,7 @@ static mp_obj_t adafruit_bus_device_i2cdevice_obj___exit__(size_t n_args, const static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit___obj, 4, 4, adafruit_bus_device_i2cdevice_obj___exit__); //| import sys +//| //| def readinto( //| self, buffer: WriteableBuffer, *, start: int = 0, end: int = sys.maxsize //| ) -> None: @@ -100,6 +105,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(adafruit_bus_device_i2cdevice___exit_ //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| static mp_obj_t adafruit_bus_device_i2cdevice_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { @@ -134,6 +140,7 @@ static mp_obj_t adafruit_bus_device_i2cdevice_readinto(size_t n_args, const mp_o static MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 1, adafruit_bus_device_i2cdevice_readinto); //| import sys +//| //| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize) -> None: //| """Write the bytes from ``buffer`` to the device, then transmit a stop bit. //| @@ -146,6 +153,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_readinto_obj, 1, //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| static mp_obj_t adafruit_bus_device_i2cdevice_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { @@ -180,6 +188,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 1, adafruit_ //| import sys +//| //| def write_then_readinto( //| self, //| out_buffer: ReadableBuffer, @@ -188,7 +197,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 1, adafruit_ //| out_start: int = 0, //| out_end: int = sys.maxsize, //| in_start: int = 0, -//| in_end: int = sys.maxsize +//| in_end: int = sys.maxsize, //| ) -> None: //| """Write the bytes from ``out_buffer`` to the device, then immediately //| reads into ``in_buffer`` from the device. @@ -210,6 +219,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(adafruit_bus_device_i2cdevice_write_obj, 1, adafruit_ //| """ //| ... //| +//| static mp_obj_t adafruit_bus_device_i2cdevice_write_then_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c index 6336b0cd12276..2f4895e38ce92 100644 --- a/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c +++ b/shared-bindings/adafruit_bus_device/spi_device/SPIDevice.c @@ -27,7 +27,7 @@ //| baudrate: int = 100000, //| polarity: int = 0, //| phase: int = 0, -//| extra_clocks: int = 0 +//| extra_clocks: int = 0, //| ) -> None: //| """ //| Represents a single SPI device and manages locking the bus and the device address. @@ -55,10 +55,10 @@ //| # A second transaction //| with device as spi: //| spi.write(bytes_read)""" +//| //| ... +//| static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - adafruit_bus_device_spidevice_obj_t *self = - mp_obj_malloc(adafruit_bus_device_spidevice_obj_t, &adafruit_bus_device_spidevice_type); enum { ARG_spi, ARG_chip_select, ARG_cs_active_value, ARG_baudrate, ARG_polarity, ARG_phase, ARG_extra_clocks }; static const mp_arg_t allowed_args[] = { { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -76,12 +76,11 @@ static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type mp_arg_validate_type_or_none(args[ARG_chip_select].u_obj, &digitalio_digitalinout_type, MP_QSTR_chip_select); - common_hal_adafruit_bus_device_spidevice_construct(MP_OBJ_TO_PTR(self), spi, args[ARG_chip_select].u_obj, args[ARG_cs_active_value].u_bool, args[ARG_baudrate].u_int, args[ARG_polarity].u_int, - args[ARG_phase].u_int, args[ARG_extra_clocks].u_int); - if (args[ARG_chip_select].u_obj != mp_const_none) { - digitalinout_result_t result = common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), - true, DRIVE_MODE_PUSH_PULL); + digitalinout_result_t result = + common_hal_digitalio_digitalinout_switch_to_output(MP_OBJ_TO_PTR(args[ARG_chip_select].u_obj), + true, + DRIVE_MODE_PUSH_PULL); #if CIRCUITPY_DIGITALIO_HAVE_INPUT_ONLY if (result == DIGITALINOUT_INPUT_ONLY) { mp_raise_NotImplementedError(MP_ERROR_TEXT("Pin is input only")); @@ -91,12 +90,25 @@ static mp_obj_t adafruit_bus_device_spidevice_make_new(const mp_obj_type_t *type #endif } - return (mp_obj_t)self; + adafruit_bus_device_spidevice_obj_t *self = + mp_obj_malloc(adafruit_bus_device_spidevice_obj_t, &adafruit_bus_device_spidevice_type); + common_hal_adafruit_bus_device_spidevice_construct(MP_OBJ_TO_PTR(self), + spi, + args[ARG_chip_select].u_obj, + args[ARG_cs_active_value].u_bool, + args[ARG_baudrate].u_int, + args[ARG_polarity].u_int, + args[ARG_phase].u_int, + args[ARG_extra_clocks].u_int); + + + return MP_OBJ_FROM_PTR(self); } //| def __enter__(self) -> busio.SPI: //| """Starts a SPI transaction by configuring the SPI and asserting chip select.""" //| ... +//| static mp_obj_t adafruit_bus_device_spidevice_obj___enter__(mp_obj_t self_in) { adafruit_bus_device_spidevice_obj_t *self = MP_OBJ_TO_PTR(self_in); return common_hal_adafruit_bus_device_spidevice_enter(self); @@ -109,6 +121,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(adafruit_bus_device_spidevice___enter___obj, ad //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... //| +//| static mp_obj_t adafruit_bus_device_spidevice_obj___exit__(size_t n_args, const mp_obj_t *args) { common_hal_adafruit_bus_device_spidevice_exit(MP_OBJ_TO_PTR(args[0])); return mp_const_none; diff --git a/shared-bindings/adafruit_pixelbuf/PixelBuf.c b/shared-bindings/adafruit_pixelbuf/PixelBuf.c index 95b353611f734..4144f086b98d6 100644 --- a/shared-bindings/adafruit_pixelbuf/PixelBuf.c +++ b/shared-bindings/adafruit_pixelbuf/PixelBuf.c @@ -24,7 +24,7 @@ #include "extmod/ulab/code/ndarray.h" #endif -static NORETURN void invalid_byteorder(void) { +static MP_NORETURN void invalid_byteorder(void) { mp_arg_error_invalid(MP_QSTR_byteorder); } @@ -41,7 +41,7 @@ static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t //| brightness: float = 0, //| auto_write: bool = False, //| header: ReadableBuffer = b"", -//| trailer: ReadableBuffer = b"" +//| trailer: ReadableBuffer = b"", //| ) -> None: //| """Create a PixelBuf object of the specified size, byteorder, and bits per pixel. //| @@ -61,6 +61,7 @@ static void parse_byteorder(mp_obj_t byteorder_obj, pixelbuf_byteorder_details_t //| :param ~circuitpython_typing.ReadableBuffer trailer: Sequence of bytes to always send after pixel values. //| """ //| ... +//| static mp_obj_t pixelbuf_pixelbuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_size, ARG_byteorder, ARG_brightness, ARG_auto_write, ARG_header, ARG_trailer }; static const mp_arg_t allowed_args[] = { @@ -201,6 +202,7 @@ MP_PROPERTY_GETSET(pixelbuf_pixelbuf_auto_write_obj, //| byteorder: str //| """byteorder string for the buffer (read-only)""" +//| static mp_obj_t pixelbuf_pixelbuf_obj_get_byteorder(mp_obj_t self_in) { return common_hal_adafruit_pixelbuf_pixelbuf_get_byteorder_string(self_in); } @@ -224,6 +226,7 @@ static mp_obj_t pixelbuf_pixelbuf_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| """Transmits the color data to the pixels so that they are shown. This is done automatically //| when `auto_write` is True.""" //| ... +//| static mp_obj_t pixelbuf_pixelbuf_show(mp_obj_t self_in) { common_hal_adafruit_pixelbuf_pixelbuf_show(self_in); @@ -234,6 +237,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(pixelbuf_pixelbuf_show_obj, pixelbuf_pixelbuf_s //| def fill(self, color: PixelType) -> None: //| """Fills the given pixelbuf with the given color.""" //| ... +//| static mp_obj_t pixelbuf_pixelbuf_fill(mp_obj_t self_in, mp_obj_t value) { common_hal_adafruit_pixelbuf_pixelbuf_fill(self_in, value); @@ -258,6 +262,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_f //| //| @overload //| def __setitem__(self, index: slice, value: PixelSequence) -> None: ... +//| //| @overload //| def __setitem__(self, index: int, value: PixelType) -> None: //| """Sets the pixel value at the given index. Value can either be a tuple or integer. Tuples are @@ -267,6 +272,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(pixelbuf_pixelbuf_fill_obj, pixelbuf_pixelbuf_f //| is used instead when the red, green, and blue values are the same.""" //| ... //| +//| static mp_obj_t pixelbuf_pixelbuf_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item diff --git a/shared-bindings/aesio/aes.c b/shared-bindings/aesio/aes.c index 33f2a3356329c..75f2850a7ef96 100644 --- a/shared-bindings/aesio/aes.c +++ b/shared-bindings/aesio/aes.c @@ -19,6 +19,7 @@ //| MODE_CBC: int //| MODE_CTR: int //| +//| //| class AES: //| """Encrypt and decrypt AES streams""" //| @@ -50,11 +51,10 @@ //| cipher.encrypt_into(inp, outp) //| hexlify(outp)""" //| ... +//| static mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - aesio_aes_obj_t *self = mp_obj_malloc(aesio_aes_obj_t, &aesio_aes_type); - enum { ARG_key, ARG_mode, ARG_IV, ARG_counter, ARG_segment_size }; static const mp_arg_t allowed_args[] = { {MP_QSTR_key, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL} }, @@ -98,8 +98,10 @@ static mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, iv = bufinfo.buf; } + aesio_aes_obj_t *self = mp_obj_malloc(aesio_aes_obj_t, &aesio_aes_type); common_hal_aesio_aes_construct(self, key, key_length, iv, mode, args[ARG_counter].u_int); + return MP_OBJ_FROM_PTR(self); } @@ -114,6 +116,7 @@ static mp_obj_t aesio_aes_make_new(const mp_obj_type_t *type, size_t n_args, //| :param ~circuitpython_typing.ReadableBuffer IV: Initialization vector to use //| for CBC or CTR mode""" //| ... +//| static mp_obj_t aesio_aes_rekey(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { aesio_aes_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); enum { ARG_key, ARG_IV }; @@ -174,9 +177,12 @@ static void validate_length(aesio_aes_obj_t *self, size_t src_length, //| """Encrypt the buffer from ``src`` into ``dest``. //| //| For ECB mode, the buffers must be 16 bytes long. For CBC mode, the -//| buffers must be a multiple of 16 bytes, and must be equal length. For -//| CTR mode, there are no restrictions.""" +//| buffers must be a multiple of 16 bytes, and must be equal length. +//| Any included padding must conform to the required padding style for the given mode. +//| For CTR mode, there are no restrictions. +//| """ //| ... +//| static mp_obj_t aesio_aes_encrypt_into(mp_obj_t self_in, mp_obj_t src, mp_obj_t dest) { aesio_aes_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -200,6 +206,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(aesio_aes_encrypt_into_obj, aesio_aes_encrypt_i //| CTR mode, there are no restrictions.""" //| ... //| +//| static mp_obj_t aesio_aes_decrypt_into(mp_obj_t self_in, mp_obj_t src, mp_obj_t dest) { aesio_aes_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -247,7 +254,7 @@ MP_PROPERTY_GETSET(aesio_aes_mode_obj, static const mp_rom_map_elem_t aesio_locals_dict_table[] = { // Methods - {MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_AES)}, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_AES)}, {MP_ROM_QSTR(MP_QSTR_encrypt_into), (mp_obj_t)&aesio_aes_encrypt_into_obj}, {MP_ROM_QSTR(MP_QSTR_decrypt_into), (mp_obj_t)&aesio_aes_decrypt_into_obj}, {MP_ROM_QSTR(MP_QSTR_rekey), (mp_obj_t)&aesio_aes_rekey_obj}, diff --git a/shared-bindings/alarm/SleepMemory.c b/shared-bindings/alarm/SleepMemory.c index cf1b211c6853f..e6d65de45551d 100644 --- a/shared-bindings/alarm/SleepMemory.c +++ b/shared-bindings/alarm/SleepMemory.c @@ -20,8 +20,6 @@ //| instance of :class:`SleepMemory` is available at //| :attr:`alarm.sleep_memory`. //| -//| **Limitations:** Not supported on RP2040. -//| //| Usage:: //| //| import alarm @@ -43,6 +41,7 @@ //| def __len__(self) -> int: //| """Return the length. This is used by (`len`)""" //| ... +//| static mp_obj_t alarm_sleep_memory_unary_op(mp_unary_op_t op, mp_obj_t self_in) { alarm_sleep_memory_obj_t *self = MP_OBJ_TO_PTR(self_in); uint16_t len = common_hal_alarm_sleep_memory_get_length(self); @@ -75,6 +74,7 @@ static MP_DEFINE_CONST_DICT(alarm_sleep_memory_locals_dict, alarm_sleep_memory_l //| """Set the value at the given index.""" //| ... //| +//| static mp_obj_t alarm_sleep_memory_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item diff --git a/shared-bindings/alarm/__init__.c b/shared-bindings/alarm/__init__.c index 7cdc2f7750e57..e9f2db324d58d 100644 --- a/shared-bindings/alarm/__init__.c +++ b/shared-bindings/alarm/__init__.c @@ -44,6 +44,7 @@ //| For more information about working with alarms and light/deep sleep in CircuitPython, //| see `this Learn guide `_. //| """ +//| //| sleep_memory: SleepMemory //| """Memory that persists during deep sleep. @@ -54,6 +55,7 @@ //| If no alarm occurred since the last hard reset or soft restart, value is ``None``. //| """ //| +//| // wake_alarm is implemented as a dictionary entry, so there's no code here. @@ -90,6 +92,7 @@ static void validate_objs_are_alarms(size_t n_args, const mp_obj_t *objs) { //| """ //| ... //| +//| static mp_obj_t alarm_light_sleep_until_alarms(size_t n_args, const mp_obj_t *args) { if (n_args == 0) { return mp_const_none; @@ -172,6 +175,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(alarm_light_sleep_until_alarms_obj, 1, MP_OB //| """ //| ... //| +//| static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_preserve_dios }; static const mp_arg_t allowed_args[] = { @@ -196,7 +200,7 @@ static mp_obj_t alarm_exit_and_deep_sleep_until_alarms(size_t n_args, const mp_o common_hal_alarm_set_deep_sleep_alarms(n_args, pos_args, num_dios, dios_array); // Raise an exception, which will be processed in main.c. - mp_raise_type_arg(&mp_type_DeepSleepRequest, NULL); + mp_raise_type(&mp_type_DeepSleepRequest); // Doesn't get here. return mp_const_none; diff --git a/shared-bindings/alarm/__init__.h b/shared-bindings/alarm/__init__.h index af92b381137c8..37bfd9c51b7cd 100644 --- a/shared-bindings/alarm/__init__.h +++ b/shared-bindings/alarm/__init__.h @@ -24,7 +24,7 @@ extern mp_obj_t common_hal_alarm_light_sleep_until_alarms(size_t n_alarms, const // it will exit idle as if deep sleep was exited extern void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *alarms, size_t n_dios, digitalio_digitalinout_obj_t **preserve_dios); -extern NORETURN void common_hal_alarm_enter_deep_sleep(void); +extern MP_NORETURN void common_hal_alarm_enter_deep_sleep(void); // May be used to re-initialize peripherals like GPIO, if the VM reset returned // them to a default state diff --git a/shared-bindings/alarm/pin/PinAlarm.c b/shared-bindings/alarm/pin/PinAlarm.c index 9c786766f6ca5..4633fdb233c8d 100644 --- a/shared-bindings/alarm/pin/PinAlarm.c +++ b/shared-bindings/alarm/pin/PinAlarm.c @@ -40,8 +40,8 @@ //| pulls it high. //| """ //| ... +//| static mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_pin_pinalarm_obj_t *self = mp_obj_malloc(alarm_pin_pinalarm_obj_t, &alarm_pin_pinalarm_type); enum { ARG_pin, ARG_value, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -54,6 +54,7 @@ static mp_obj_t alarm_pin_pinalarm_make_new(const mp_obj_type_t *type, mp_uint_t const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + alarm_pin_pinalarm_obj_t *self = mp_obj_malloc(alarm_pin_pinalarm_obj_t, &alarm_pin_pinalarm_type); common_hal_alarm_pin_pinalarm_construct(self, pin, args[ARG_value].u_bool, @@ -81,6 +82,7 @@ MP_PROPERTY_GETTER(alarm_pin_pinalarm_pin_obj, //| value: bool //| """The value on which to trigger.""" //| +//| static mp_obj_t alarm_pin_pinalarm_obj_get_value(mp_obj_t self_in) { alarm_pin_pinalarm_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(common_hal_alarm_pin_pinalarm_get_value(self)); diff --git a/shared-bindings/alarm/time/TimeAlarm.c b/shared-bindings/alarm/time/TimeAlarm.c index 012ca602a11bf..a3df6ddf7fd2e 100644 --- a/shared-bindings/alarm/time/TimeAlarm.c +++ b/shared-bindings/alarm/time/TimeAlarm.c @@ -35,12 +35,17 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { //| If the given time is already in the past, then an exception is raised. //| If the sleep happens after the given time, then it will wake immediately //| due to this time alarm. +//| +//| Example:: +//| +//| # Deep sleep for 30 seconds. +//| time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 30) +//| alarm.exit_and_deep_sleep_until_alarms(time_alarm) //| """ //| ... +//| static mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_time_timealarm_obj_t *self = mp_obj_malloc(alarm_time_timealarm_obj_t, &alarm_time_timealarm_type); - enum { ARG_monotonic_time, ARG_epoch_time }; static const mp_arg_t allowed_args[] = { { MP_QSTR_monotonic_time, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -85,6 +90,7 @@ static mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, mp_raise_ValueError(MP_ERROR_TEXT("Time is in the past.")); } + alarm_time_timealarm_obj_t *self = mp_obj_malloc(alarm_time_timealarm_obj_t, &alarm_time_timealarm_type); common_hal_alarm_time_timealarm_construct(self, monotonic_time); return MP_OBJ_FROM_PTR(self); @@ -96,6 +102,7 @@ static mp_obj_t alarm_time_timealarm_make_new(const mp_obj_type_t *type, //| by this property only as a `time.monotonic()` time. //| """ //| +//| static mp_obj_t alarm_time_timealarm_obj_get_monotonic_time(mp_obj_t self_in) { alarm_time_timealarm_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_float(common_hal_alarm_time_timealarm_get_monotonic_time(self)); diff --git a/shared-bindings/alarm/touch/TouchAlarm.c b/shared-bindings/alarm/touch/TouchAlarm.c index c4fd595efea32..42b149c9eeea7 100644 --- a/shared-bindings/alarm/touch/TouchAlarm.c +++ b/shared-bindings/alarm/touch/TouchAlarm.c @@ -23,10 +23,9 @@ //| **Limitations:** Not available on SAMD, Nordic, or RP2040. //| """ //| ... +//| static mp_obj_t alarm_touch_touchalarm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - alarm_touch_touchalarm_obj_t *self = mp_obj_malloc(alarm_touch_touchalarm_obj_t, &alarm_touch_touchalarm_type); - enum { ARG_pin }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -37,6 +36,7 @@ static mp_obj_t alarm_touch_touchalarm_make_new(const mp_obj_type_t *type, const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + alarm_touch_touchalarm_obj_t *self = mp_obj_malloc(alarm_touch_touchalarm_obj_t, &alarm_touch_touchalarm_type); common_hal_alarm_touch_touchalarm_construct(self, pin); return MP_OBJ_FROM_PTR(self); @@ -45,6 +45,7 @@ static mp_obj_t alarm_touch_touchalarm_make_new(const mp_obj_type_t *type, //| pin: microcontroller.Pin //| """The trigger pin.""" //| +//| static mp_obj_t alarm_touch_touchalarm_obj_get_pin(mp_obj_t self_in) { alarm_touch_touchalarm_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_FROM_PTR(self->pin); diff --git a/shared-bindings/analogbufio/BufferedIn.c b/shared-bindings/analogbufio/BufferedIn.c index 6627715ae3972..2c42ee1f32571 100644 --- a/shared-bindings/analogbufio/BufferedIn.c +++ b/shared-bindings/analogbufio/BufferedIn.c @@ -40,8 +40,14 @@ //| """Create a `BufferedIn` on the given pin and given sample rate. //| //| :param ~microcontroller.Pin pin: the pin to read from -//| :param ~int sample_rate: rate: sampling frequency, in samples per second""" +//| :param ~int sample_rate: rate: sampling frequency, in samples per second +//| +//| **Limitations**: On many boards with a CYW43 radio module, such as Pico W, +//| GPIO29 (often ``board.A3``) is also used to control the CYW43, +//| and is therefore not available to use as the `BufferedIn` pin. +//| """ //| ... +//| static mp_obj_t analogbufio_bufferedin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pin, ARG_sample_rate }; static const mp_arg_t allowed_args[] = { @@ -54,11 +60,8 @@ static mp_obj_t analogbufio_bufferedin_make_new(const mp_obj_type_t *type, size_ // Validate Pin const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); - // Create local object - analogbufio_bufferedin_obj_t *self = m_new_obj_with_finaliser(analogbufio_bufferedin_obj_t); - self->base.type = &analogbufio_bufferedin_type; - - // Call local interface in ports/common-hal/analogbufio + analogbufio_bufferedin_obj_t *self = + mp_obj_malloc_with_finaliser(analogbufio_bufferedin_obj_t, &analogbufio_bufferedin_type); common_hal_analogbufio_bufferedin_construct(self, pin, args[ARG_sample_rate].u_int); return MP_OBJ_FROM_PTR(self); @@ -67,6 +70,7 @@ static mp_obj_t analogbufio_bufferedin_make_new(const mp_obj_type_t *type, size_ //| def deinit(self) -> None: //| """Shut down the `BufferedIn` and release the pin for other use.""" //| ... +//| static mp_obj_t analogbufio_bufferedin_deinit(mp_obj_t self_in) { analogbufio_bufferedin_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_analogbufio_bufferedin_deinit(self); @@ -82,18 +86,15 @@ static void check_for_deinit(analogbufio_bufferedin_obj_t *self) { //| def __enter__(self) -> BufferedIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t analogbufio_bufferedin___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_analogbufio_bufferedin_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogbufio_bufferedin___exit___obj, 4, 4, analogbufio_bufferedin___exit__); +//| +// Provided by context manager helper. //| def readinto(self, buffer: WriteableBuffer, loop: bool = False) -> int: //| """Fills the provided buffer with ADC voltage values. @@ -111,6 +112,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogbufio_bufferedin___exit___obj, //| """ //| ... //| +//| static mp_obj_t analogbufio_bufferedin_obj_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -140,7 +142,7 @@ static const mp_rom_map_elem_t analogbufio_bufferedin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&analogbufio_bufferedin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&analogbufio_bufferedin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&analogbufio_bufferedin___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&analogbufio_bufferedin_readinto_obj)}, }; diff --git a/shared-bindings/analogio/AnalogIn.c b/shared-bindings/analogio/AnalogIn.c index f56ce600c2479..b68b044ab5238 100644 --- a/shared-bindings/analogio/AnalogIn.c +++ b/shared-bindings/analogio/AnalogIn.c @@ -46,6 +46,7 @@ MP_WEAK const mcu_pin_obj_t *common_hal_analogio_analogin_validate_pin(mp_obj_t //| when you read a value. You can retry the read. //| """ //| ... +//| static mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, size_t n_kw, const mp_obj_t *args) { // check number of arguments @@ -62,6 +63,7 @@ static mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type, //| def deinit(self) -> None: //| """Turn off the AnalogIn and release the pin for other use.""" //| ... +//| static mp_obj_t analogio_analogin_deinit(mp_obj_t self_in) { analogio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_analogio_analogin_deinit(self); @@ -77,18 +79,15 @@ static void check_for_deinit(analogio_analogin_obj_t *self) { //| def __enter__(self) -> AnalogIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t analogio_analogin___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_analogio_analogin_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogin___exit___obj, 4, 4, analogio_analogin___exit__); +//| +// Provided by context manager helper. //| value: int //| """The value on the analog pin between 0 and 65535 inclusive (16-bit). (read-only) @@ -110,6 +109,7 @@ MP_PROPERTY_GETTER(analogio_analogin_value_obj, //| ``float`` in Volts. Note the ADC value may not scale to the actual voltage linearly //| at ends of the analog range.""" //| +//| static mp_obj_t analogio_analogin_obj_get_reference_voltage(mp_obj_t self_in) { analogio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -130,7 +130,7 @@ MP_PROPERTY_GETTER(analogio_analogin_reference_voltage_obj, static const mp_rom_map_elem_t analogio_analogin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&analogio_analogin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&analogio_analogin___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&analogio_analogin_value_obj)}, { MP_ROM_QSTR(MP_QSTR_reference_voltage), MP_ROM_PTR(&analogio_analogin_reference_voltage_obj)}, }; diff --git a/shared-bindings/analogio/AnalogOut.c b/shared-bindings/analogio/AnalogOut.c index ab0b018a23755..b9e5824f978b7 100644 --- a/shared-bindings/analogio/AnalogOut.c +++ b/shared-bindings/analogio/AnalogOut.c @@ -20,6 +20,9 @@ //| //| **Limitations:** Not available on Nordic, RP2040, Spresense, as there is no on-chip DAC. //| On Espressif, available only on ESP32 and ESP32-S2; other chips do not have a DAC. +//| On ESP32-S2 boards, GPIO18 (DAC2) is often connected to a pull-up resistor, which causes +//| `unexpected output values in the lower part of the output range +//| `_. //| //| Example usage:: //| @@ -36,6 +39,7 @@ //| //| """ //| ... +//| static mp_obj_t analogio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t n_args, size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, 1, false); @@ -51,6 +55,7 @@ static mp_obj_t analogio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t //| def deinit(self) -> None: //| """Turn off the AnalogOut and release the pin for other use.""" //| ... +//| static mp_obj_t analogio_analogout_deinit(mp_obj_t self_in) { analogio_analogout_obj_t *self = self_in; @@ -63,18 +68,15 @@ static MP_DEFINE_CONST_FUN_OBJ_1(analogio_analogout_deinit_obj, analogio_analogo //| def __enter__(self) -> AnalogOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t analogio_analogout___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_analogio_analogout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogout___exit___obj, 4, 4, analogio_analogout___exit__); +//| +// Provided by context manager helper. //| value: int //| """The value on the analog pin between 0 and 65535 inclusive (16-bit). (write-only) @@ -82,6 +84,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(analogio_analogout___exit___obj, 4, 4 //| Even if the underlying digital to analog converter (DAC) is lower //| resolution, the value is 16-bit.""" //| +//| static mp_obj_t analogio_analogout_obj_set_value(mp_obj_t self_in, mp_obj_t value) { analogio_analogout_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_analogio_analogout_deinited(self)) { @@ -100,12 +103,12 @@ MP_PROPERTY_GETSET(analogio_analogout_value_obj, static const mp_rom_map_elem_t analogio_analogout_locals_dict_table[] = { // instance methods - { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&analogio_analogout_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&analogio_analogout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&analogio_analogout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties - { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&analogio_analogout_value_obj }, + { MP_ROM_QSTR(MP_QSTR_value), (mp_obj_t)&analogio_analogout_value_obj }, }; static MP_DEFINE_CONST_DICT(analogio_analogout_locals_dict, analogio_analogout_locals_dict_table); diff --git a/shared-bindings/atexit/__init__.c b/shared-bindings/atexit/__init__.c index b18e26f2476e2..11d142bbf35e1 100644 --- a/shared-bindings/atexit/__init__.c +++ b/shared-bindings/atexit/__init__.c @@ -16,8 +16,10 @@ //| //| |see_cpython_module| :mod:`cpython:atexit`. //| """ +//| //| ... //| +//| //| def register( //| func: Callable[..., Any], *args: Optional[Any], **kwargs: Optional[Any] @@ -38,6 +40,7 @@ //| """ //| ... //| +//| static mp_obj_t atexit_register(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { shared_module_atexit_register(pos_args[0], (n_args - 1), ((n_args > 1) ? &pos_args[1] : NULL), kw_args); return pos_args[0]; @@ -53,6 +56,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(atexit_register_obj, 1, atexit_register); //| """ //| ... //| +//| static mp_obj_t atexit_unregister(const mp_obj_t self_in) { shared_module_atexit_unregister(&self_in); return mp_const_none; diff --git a/shared-bindings/audiobusio/I2SOut.c b/shared-bindings/audiobusio/I2SOut.c index 4b6d57ba18d4d..952a00e2903ee 100644 --- a/shared-bindings/audiobusio/I2SOut.c +++ b/shared-bindings/audiobusio/I2SOut.c @@ -24,7 +24,7 @@ //| data: microcontroller.Pin, //| *, //| main_clock: Optional[microcontroller.Pin] = None, -//| left_justified: bool = False +//| left_justified: bool = False, //| ) -> None: //| """Create a I2SOut object associated with the given pins. //| @@ -76,6 +76,7 @@ //| pass //| print("stopped")""" //| ... +//| static mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if !CIRCUITPY_AUDIOBUSIO_I2SOUT mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_I2SOut); @@ -97,8 +98,7 @@ static mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a const mcu_pin_obj_t *data = validate_obj_is_free_pin(args[ARG_data].u_obj, MP_QSTR_data); const mcu_pin_obj_t *main_clock = validate_obj_is_free_pin_or_none(args[ARG_main_clock].u_obj, MP_QSTR_main_clock); - audiobusio_i2sout_obj_t *self = m_new_obj_with_finaliser(audiobusio_i2sout_obj_t); - self->base.type = &audiobusio_i2sout_type; + audiobusio_i2sout_obj_t *self = mp_obj_malloc_with_finaliser(audiobusio_i2sout_obj_t, &audiobusio_i2sout_type); common_hal_audiobusio_i2sout_construct(self, bit_clock, word_select, data, main_clock, args[ARG_left_justified].u_bool); return MP_OBJ_FROM_PTR(self); @@ -110,6 +110,7 @@ static mp_obj_t audiobusio_i2sout_make_new(const mp_obj_type_t *type, size_t n_a //| def deinit(self) -> None: //| """Deinitialises the I2SOut and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audiobusio_i2sout_deinit(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audiobusio_i2sout_deinit(self); @@ -126,18 +127,15 @@ static void check_for_deinit(audiobusio_i2sout_obj_t *self) { //| def __enter__(self) -> I2SOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audiobusio_i2sout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audiobusio_i2sout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4, audiobusio_i2sout_obj___exit__); +//| +// Provided by context manager helper. //| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: @@ -146,8 +144,11 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_i2sout___exit___obj, 4, 4, //| //| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. //| +//| Mono samples will be converted to stereo by copying value to both the left channel and the right channel. +//| //| The sample itself should consist of 8 bit or 16 bit samples.""" //| ... +//| static mp_obj_t audiobusio_i2sout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -169,6 +170,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audiobusio_i2sout_play_obj, 1, audiobusio_i2sout_obj_ //| def stop(self) -> None: //| """Stops playback.""" //| ... +//| static mp_obj_t audiobusio_i2sout_obj_stop(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -179,6 +181,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_stop_obj, audiobusio_i2sout_obj_stop //| playing: bool //| """True when the audio sample is being output. (read-only)""" +//| static mp_obj_t audiobusio_i2sout_obj_get_playing(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -192,6 +195,7 @@ MP_PROPERTY_GETTER(audiobusio_i2sout_playing_obj, //| def pause(self) -> None: //| """Stops playback temporarily while remembering the position. Use `resume` to resume playback.""" //| ... +//| static mp_obj_t audiobusio_i2sout_obj_pause(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -207,6 +211,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_pause_obj, audiobusio_i2sout_obj_pau //| def resume(self) -> None: //| """Resumes sample playback after :py:func:`pause`.""" //| ... +//| static mp_obj_t audiobusio_i2sout_obj_resume(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -222,6 +227,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiobusio_i2sout_resume_obj, audiobusio_i2sout_obj_re //| paused: bool //| """True when playback is paused. (read-only)""" //| +//| static mp_obj_t audiobusio_i2sout_obj_get_paused(mp_obj_t self_in) { audiobusio_i2sout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -239,7 +245,7 @@ static const mp_rom_map_elem_t audiobusio_i2sout_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audiobusio_i2sout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiobusio_i2sout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiobusio_i2sout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiobusio_i2sout_play_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiobusio_i2sout_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audiobusio_i2sout_pause_obj) }, diff --git a/shared-bindings/audiobusio/PDMIn.c b/shared-bindings/audiobusio/PDMIn.c index 12428e20034c9..092897a15cff3 100644 --- a/shared-bindings/audiobusio/PDMIn.c +++ b/shared-bindings/audiobusio/PDMIn.c @@ -27,7 +27,7 @@ //| bit_depth: int = 8, //| mono: bool = True, //| oversample: int = 64, -//| startup_delay: float = 0.11 +//| startup_delay: float = 0.11, //| ) -> None: //| """Create a PDMIn object associated with the given pins. This allows you to //| record audio signals from the given pins. Individual ports may put further @@ -70,7 +70,9 @@ //| with audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA, sample_rate=16000, bit_depth=16) as mic: //| mic.record(b, len(b)) //| """ +//| //| ... +//| static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if !CIRCUITPY_AUDIOBUSIO_PDMIN mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_PDMIn); @@ -94,9 +96,6 @@ static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar const mcu_pin_obj_t *clock_pin = validate_obj_is_free_pin(args[ARG_clock_pin].u_obj, MP_QSTR_clock_pin); const mcu_pin_obj_t *data_pin = validate_obj_is_free_pin(args[ARG_data_pin].u_obj, MP_QSTR_data_pin); - // create PDMIn object from the given pin - audiobusio_pdmin_obj_t *self = mp_obj_malloc(audiobusio_pdmin_obj_t, &audiobusio_pdmin_type); - uint32_t sample_rate = args[ARG_sample_rate].u_int; uint8_t bit_depth = args[ARG_bit_depth].u_int; if (bit_depth % 8 != 0) { @@ -113,6 +112,7 @@ static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar : mp_obj_get_float(args[ARG_startup_delay].u_obj); mp_arg_validate_float_range(startup_delay, 0.0f, 1.0f, MP_QSTR_startup_delay); + audiobusio_pdmin_obj_t *self = mp_obj_malloc_with_finaliser(audiobusio_pdmin_obj_t, &audiobusio_pdmin_type); common_hal_audiobusio_pdmin_construct(self, clock_pin, data_pin, sample_rate, bit_depth, mono, oversample); @@ -127,6 +127,7 @@ static mp_obj_t audiobusio_pdmin_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the PDMIn and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audiobusio_pdmin_deinit(mp_obj_t self_in) { audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audiobusio_pdmin_deinit(self); @@ -142,30 +143,28 @@ static void check_for_deinit(audiobusio_pdmin_obj_t *self) { //| def __enter__(self) -> PDMIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context.""" //| ... -static mp_obj_t audiobusio_pdmin_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audiobusio_pdmin_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiobusio_pdmin___exit___obj, 4, 4, audiobusio_pdmin_obj___exit__); +//| +// Provided by context manager helper. -//| def record(self, destination: WriteableBuffer, destination_length: int) -> None: +//| def record(self, destination: WriteableBuffer, destination_length: int) -> int: //| """Records destination_length bytes of samples to destination. This is //| blocking. //| -//| An IOError may be raised when the destination is too slow to record the +//| An OSError may be raised when the destination is too slow to record the //| audio at the given rate. For internal flash, writing all 1s to the file //| before recording is recommended to speed up writes. //| //| :return: The number of samples recorded. If this is less than ``destination_length``, //| some samples were missed due to processing time.""" //| ... +//| static mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destination, mp_obj_t destination_length) { audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_obj); check_for_deinit(self); @@ -175,22 +174,22 @@ static mp_obj_t audiobusio_pdmin_obj_record(mp_obj_t self_obj, mp_obj_t destinat mp_buffer_info_t bufinfo; if (mp_obj_is_type(destination, &mp_type_fileio)) { mp_raise_NotImplementedError(MP_ERROR_TEXT("Cannot record to a file")); - } else if (mp_get_buffer(destination, &bufinfo, MP_BUFFER_WRITE)) { - if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) { - mp_raise_ValueError(MP_ERROR_TEXT("Destination capacity is smaller than destination_length.")); - } - uint8_t bit_depth = common_hal_audiobusio_pdmin_get_bit_depth(self); - if (bufinfo.typecode != 'H' && bit_depth == 16) { - mp_raise_ValueError(MP_ERROR_TEXT("destination buffer must be an array of type 'H' for bit_depth = 16")); - } else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE && bit_depth == 8) { - mp_raise_ValueError(MP_ERROR_TEXT("destination buffer must be a bytearray or array of type 'B' for bit_depth = 8")); - } - // length is the buffer length in slots, not bytes. - uint32_t length_written = - common_hal_audiobusio_pdmin_record_to_buffer(self, bufinfo.buf, length); - return MP_OBJ_NEW_SMALL_INT(length_written); } - return mp_const_none; + + mp_get_buffer_raise(destination, &bufinfo, MP_BUFFER_WRITE); + if (bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL) < length) { + mp_raise_ValueError(MP_ERROR_TEXT("Destination capacity is smaller than destination_length.")); + } + uint8_t bit_depth = common_hal_audiobusio_pdmin_get_bit_depth(self); + if (bufinfo.typecode != 'H' && bit_depth == 16) { + mp_raise_ValueError(MP_ERROR_TEXT("destination buffer must be an array of type 'H' for bit_depth = 16")); + } else if (bufinfo.typecode != 'B' && bufinfo.typecode != BYTEARRAY_TYPECODE && bit_depth == 8) { + mp_raise_ValueError(MP_ERROR_TEXT("destination buffer must be a bytearray or array of type 'B' for bit_depth = 8")); + } + // length is the buffer length in slots, not bytes. + uint32_t length_written = + common_hal_audiobusio_pdmin_record_to_buffer(self, bufinfo.buf, length); + return MP_OBJ_NEW_SMALL_INT(length_written); } MP_DEFINE_CONST_FUN_OBJ_3(audiobusio_pdmin_record_obj, audiobusio_pdmin_obj_record); @@ -198,6 +197,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(audiobusio_pdmin_record_obj, audiobusio_pdmin_obj_reco //| """The actual sample_rate of the recording. This may not match the constructed //| sample rate due to internal clock limitations.""" //| +//| static mp_obj_t audiobusio_pdmin_obj_get_sample_rate(mp_obj_t self_in) { audiobusio_pdmin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -210,9 +210,10 @@ MP_PROPERTY_GETTER(audiobusio_pdmin_sample_rate_obj, static const mp_rom_map_elem_t audiobusio_pdmin_locals_dict_table[] = { // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audiobusio_pdmin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiobusio_pdmin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiobusio_pdmin___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_record), MP_ROM_PTR(&audiobusio_pdmin_record_obj) }, { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiobusio_pdmin_sample_rate_obj) } }; diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 8da693b7c5997..8dc57903286d3 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -12,6 +12,7 @@ #include "py/runtime.h" #include "shared-bindings/util.h" #include "shared-bindings/audiocore/RawSample.h" +#include "shared-bindings/audiocore/__init__.h" //| class RawSample: //| """A raw audio sample buffer in memory""" @@ -22,7 +23,7 @@ //| *, //| channel_count: int = 1, //| sample_rate: int = 8000, -//| single_buffer: bool = True +//| single_buffer: bool = True, //| ) -> None: //| """Create a RawSample based on the given buffer of values. If channel_count is more than //| 1 then each channel's samples should alternate. In other words, for a two channel buffer, the @@ -77,6 +78,7 @@ //| pwm.stop() //| pwm.deinit()""" //| ... +//| static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer, ARG_channel_count, ARG_sample_rate, ARG_single_buffer }; static const mp_arg_t allowed_args[] = { @@ -88,7 +90,6 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - audioio_rawsample_obj_t *self = mp_obj_malloc(audioio_rawsample_obj_t, &audioio_rawsample_type); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); uint8_t bytes_per_sample = 1; @@ -101,9 +102,16 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a if (!args[ARG_single_buffer].u_bool && bufinfo.len % (bytes_per_sample * args[ARG_channel_count].u_int * 2) != 0) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Length of %q must be an even multiple of channel_count * type_size"), MP_QSTR_buffer); } - common_hal_audioio_rawsample_construct(self, ((uint8_t *)bufinfo.buf), bufinfo.len, - bytes_per_sample, signed_samples, args[ARG_channel_count].u_int, - args[ARG_sample_rate].u_int, args[ARG_single_buffer].u_bool); + + audioio_rawsample_obj_t *self = mp_obj_malloc(audioio_rawsample_obj_t, &audioio_rawsample_type); + common_hal_audioio_rawsample_construct(self, + ((uint8_t *)bufinfo.buf), + bufinfo.len, + bytes_per_sample, + signed_samples, + args[ARG_channel_count].u_int, + args[ARG_sample_rate].u_int, + args[ARG_single_buffer].u_bool); return MP_OBJ_FROM_PTR(self); } @@ -111,6 +119,7 @@ static mp_obj_t audioio_rawsample_make_new(const mp_obj_type_t *type, size_t n_a //| def deinit(self) -> None: //| """Deinitialises the RawSample and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audioio_rawsample_deinit(mp_obj_t self_in) { audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audioio_rawsample_deinit(self); @@ -118,27 +127,18 @@ static mp_obj_t audioio_rawsample_deinit(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_deinit_obj, audioio_rawsample_deinit); -static void check_for_deinit(audioio_rawsample_obj_t *self) { - if (common_hal_audioio_rawsample_deinited(self)) { - raise_deinited_error(); - } -} - //| def __enter__(self) -> RawSample: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audioio_rawsample_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audioio_rawsample_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_rawsample___exit___obj, 4, 4, audioio_rawsample_obj___exit__); +//| +// Provided by context manager helper. //| sample_rate: Optional[int] //| """32 bit value that dictates how quickly samples are played in Hertz (cycles per second). @@ -146,44 +146,23 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_rawsample___exit___obj, 4, 4, //| sample. This will not change the sample rate of any active playback. Call ``play`` again to //| change it.""" //| -static mp_obj_t audioio_rawsample_obj_get_sample_rate(mp_obj_t self_in) { - audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_rawsample_get_sample_rate(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audioio_rawsample_get_sample_rate_obj, audioio_rawsample_obj_get_sample_rate); - -static mp_obj_t audioio_rawsample_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) { - audioio_rawsample_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - common_hal_audioio_rawsample_set_sample_rate(self, mp_obj_get_int(sample_rate)); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(audioio_rawsample_set_sample_rate_obj, audioio_rawsample_obj_set_sample_rate); - -MP_PROPERTY_GETSET(audioio_rawsample_sample_rate_obj, - (mp_obj_t)&audioio_rawsample_get_sample_rate_obj, - (mp_obj_t)&audioio_rawsample_set_sample_rate_obj); +//| static const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_rawsample_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_rawsample___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_rawsample_sample_rate_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(audioio_rawsample_locals_dict, audioio_rawsample_locals_dict_table); static const audiosample_p_t audioio_rawsample_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_rawsample_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_rawsample_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_audioio_rawsample_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)audioio_rawsample_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)audioio_rawsample_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure, }; MP_DEFINE_CONST_OBJ_TYPE( diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h index 1f4ca7f8ec52b..a5b9b06e79700 100644 --- a/shared-bindings/audiocore/RawSample.h +++ b/shared-bindings/audiocore/RawSample.h @@ -15,8 +15,3 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self, uint8_t channel_count, uint32_t sample_rate, bool single_buffer); void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self); -bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self); -uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t *self); -uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t *self); -uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t *self); -void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t *self, uint32_t sample_rate); diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 372330577f960..c93bedd4213ea 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -10,6 +10,7 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/audiocore/WaveFile.h" +#include "shared-bindings/audiocore/__init__.h" #include "shared-bindings/util.h" #include "extmod/vfs_posix.h" @@ -50,6 +51,7 @@ //| print("stopped") //| """ //| ... +//| static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_obj_t arg = args[0]; @@ -58,7 +60,6 @@ static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar arg = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), arg, MP_ROM_QSTR(MP_QSTR_rb)); } - audioio_wavefile_obj_t *self = mp_obj_malloc(audioio_wavefile_obj_t, &audioio_wavefile_type); if (!mp_obj_is_type(arg, &mp_type_vfs_fat_fileio)) { mp_raise_TypeError(MP_ERROR_TEXT("file must be a file opened in byte mode")); } @@ -70,6 +71,8 @@ static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar buffer = bufinfo.buf; buffer_size = mp_arg_validate_length_range(bufinfo.len, 8, 1024, MP_QSTR_buffer); } + + audioio_wavefile_obj_t *self = mp_obj_malloc(audioio_wavefile_obj_t, &audioio_wavefile_type); common_hal_audioio_wavefile_construct(self, MP_OBJ_TO_PTR(arg), buffer, buffer_size); @@ -79,6 +82,7 @@ static mp_obj_t audioio_wavefile_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the WaveFile and releases all memory resources for reuse.""" //| ... +//| static mp_obj_t audioio_wavefile_deinit(mp_obj_t self_in) { audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audioio_wavefile_deinit(self); @@ -86,97 +90,47 @@ static mp_obj_t audioio_wavefile_deinit(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_deinit_obj, audioio_wavefile_deinit); -static void check_for_deinit(audioio_wavefile_obj_t *self) { - if (common_hal_audioio_wavefile_deinited(self)) { - raise_deinited_error(); - } -} - //| def __enter__(self) -> WaveFile: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audioio_wavefile_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audioio_wavefile_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_wavefile___exit___obj, 4, 4, audioio_wavefile_obj___exit__); +//| +// Provided by context manager helper. //| sample_rate: int //| """32 bit value that dictates how quickly samples are loaded into the DAC //| in Hertz (cycles per second). When the sample is looped, this can change //| the pitch output without changing the underlying sample.""" -static mp_obj_t audioio_wavefile_obj_get_sample_rate(mp_obj_t self_in) { - audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_sample_rate(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_sample_rate_obj, audioio_wavefile_obj_get_sample_rate); - -static mp_obj_t audioio_wavefile_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) { - audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - common_hal_audioio_wavefile_set_sample_rate(self, mp_obj_get_int(sample_rate)); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(audioio_wavefile_set_sample_rate_obj, audioio_wavefile_obj_set_sample_rate); - -MP_PROPERTY_GETSET(audioio_wavefile_sample_rate_obj, - (mp_obj_t)&audioio_wavefile_get_sample_rate_obj, - (mp_obj_t)&audioio_wavefile_set_sample_rate_obj); //| bits_per_sample: int //| """Bits per sample. (read only)""" -static mp_obj_t audioio_wavefile_obj_get_bits_per_sample(mp_obj_t self_in) { - audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_bits_per_sample(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_bits_per_sample_obj, audioio_wavefile_obj_get_bits_per_sample); - -MP_PROPERTY_GETTER(audioio_wavefile_bits_per_sample_obj, - (mp_obj_t)&audioio_wavefile_get_bits_per_sample_obj); +// //| channel_count: int //| """Number of audio channels. (read only)""" //| -static mp_obj_t audioio_wavefile_obj_get_channel_count(mp_obj_t self_in) { - audioio_wavefile_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audioio_wavefile_get_channel_count(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audioio_wavefile_get_channel_count_obj, audioio_wavefile_obj_get_channel_count); - -MP_PROPERTY_GETTER(audioio_wavefile_channel_count_obj, - (mp_obj_t)&audioio_wavefile_get_channel_count_obj); - +//| static const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_wavefile_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_wavefile___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audioio_wavefile_sample_rate_obj) }, - { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audioio_wavefile_bits_per_sample_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audioio_wavefile_channel_count_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table); static const audiosample_p_t audioio_wavefile_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_wavefile_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_wavefile_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_audioio_wavefile_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)audioio_wavefile_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)audioio_wavefile_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_wavefile_get_buffer_structure, }; diff --git a/shared-bindings/audiocore/WaveFile.h b/shared-bindings/audiocore/WaveFile.h index 7c847bbced7fb..5249959a1cc50 100644 --- a/shared-bindings/audiocore/WaveFile.h +++ b/shared-bindings/audiocore/WaveFile.h @@ -17,8 +17,3 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, pyb_file_obj_t *file, uint8_t *buffer, size_t buffer_size); void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t *self); -bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t *self); -uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t *self); -void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t *self, uint32_t sample_rate); -uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t *self); -uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t *self); diff --git a/shared-bindings/audiocore/__init__.c b/shared-bindings/audiocore/__init__.c index 4eff83bcfdbfc..b2b6c4da0f314 100644 --- a/shared-bindings/audiocore/__init__.c +++ b/shared-bindings/audiocore/__init__.c @@ -7,12 +7,14 @@ #include #include "py/obj.h" +#include "py/objproperty.h" #include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/audiocore/__init__.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/audiocore/WaveFile.h" +#include "shared-bindings/util.h" // #include "shared-bindings/audiomixer/Mixer.h" //| """Support for audio samples""" @@ -24,6 +26,9 @@ static mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) { uint32_t buffer_length = 0; audioio_get_buffer_result_t gbr = audiosample_get_buffer(sample_in, false, 0, &buffer, &buffer_length); + // audiosample_get_buffer checked that we're a sample so this is a safe cast + audiosample_base_t *sample = MP_OBJ_TO_PTR(sample_in); + mp_obj_t result[2] = {mp_obj_new_int_from_uint(gbr), mp_const_none}; if (gbr != GET_BUFFER_ERROR) { @@ -31,10 +36,10 @@ static mp_obj_t audiocore_get_buffer(mp_obj_t sample_in) { uint32_t max_buffer_length; uint8_t spacing; - uint8_t bits_per_sample = audiosample_bits_per_sample(sample_in); - audiosample_get_buffer_structure(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); + uint8_t bits_per_sample = audiosample_get_bits_per_sample(sample); + audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); // copies the data because the gc semantics of get_buffer are unclear - void *result_buf = m_malloc(buffer_length); + void *result_buf = m_malloc_without_collect(buffer_length); memcpy(result_buf, buffer, buffer_length); char typecode = (bits_per_sample == 8 && samples_signed) ? 'b' : @@ -55,7 +60,7 @@ static mp_obj_t audiocore_get_structure(mp_obj_t sample_in) { uint32_t max_buffer_length; uint8_t spacing; - audiosample_get_buffer_structure(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); + audiosample_get_buffer_structure_checked(sample_in, false, &single_buffer, &samples_signed, &max_buffer_length, &spacing); mp_obj_t result[4] = { mp_obj_new_int_from_uint(single_buffer), mp_obj_new_int_from_uint(samples_signed), @@ -92,4 +97,61 @@ const mp_obj_module_t audiocore_module = { .globals = (mp_obj_dict_t *)&audiocore_module_globals, }; +bool audiosample_deinited(const audiosample_base_t *self) { + return self->channel_count == 0; +} + +void audiosample_check_for_deinit(const audiosample_base_t *self) { + if (audiosample_deinited(self)) { + raise_deinited_error(); + } +} + +void audiosample_mark_deinit(audiosample_base_t *self) { + self->channel_count = 0; +} + +// common implementation of channel_count property for audio samples +static mp_obj_t audiosample_obj_get_channel_count(mp_obj_t self_in) { + audiosample_base_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(audiosample_get_channel_count(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_channel_count_obj, audiosample_obj_get_channel_count); + +MP_PROPERTY_GETTER(audiosample_channel_count_obj, + (mp_obj_t)&audiosample_get_channel_count_obj); + + +// common implementation of bits_per_sample property for audio samples +static mp_obj_t audiosample_obj_get_bits_per_sample(mp_obj_t self_in) { + audiosample_base_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(audiosample_get_bits_per_sample(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_bits_per_sample_obj, audiosample_obj_get_bits_per_sample); + +MP_PROPERTY_GETTER(audiosample_bits_per_sample_obj, + (mp_obj_t)&audiosample_get_bits_per_sample_obj); + +// common implementation of sample_rate property for audio samples +static mp_obj_t audiosample_obj_get_sample_rate(mp_obj_t self_in) { + audiosample_base_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(audiosample_get_sample_rate(audiosample_check(self_in))); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiosample_get_sample_rate_obj, audiosample_obj_get_sample_rate); + +static mp_obj_t audiosample_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) { + audiosample_base_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(self); + audiosample_set_sample_rate(audiosample_check(self_in), mp_obj_get_int(sample_rate)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiosample_set_sample_rate_obj, audiosample_obj_set_sample_rate); + +MP_PROPERTY_GETSET(audiosample_sample_rate_obj, + (mp_obj_t)&audiosample_get_sample_rate_obj, + (mp_obj_t)&audiosample_set_sample_rate_obj); + MP_REGISTER_MODULE(MP_QSTR_audiocore, audiocore_module); diff --git a/shared-bindings/audiocore/__init__.h b/shared-bindings/audiocore/__init__.h index 2c669f638b6b5..defa3d6c8dcb8 100644 --- a/shared-bindings/audiocore/__init__.h +++ b/shared-bindings/audiocore/__init__.h @@ -5,3 +5,18 @@ // SPDX-License-Identifier: MIT #pragma once + +#include "py/objproperty.h" + +#define AUDIOSAMPLE_FIELDS \ + { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiosample_sample_rate_obj) }, \ + { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiosample_bits_per_sample_obj) }, \ + { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiosample_channel_count_obj) } + +typedef struct audiosample_base audiosample_base_t; +extern const mp_obj_property_getset_t audiosample_sample_rate_obj; +extern const mp_obj_property_getter_t audiosample_bits_per_sample_obj; +extern const mp_obj_property_getter_t audiosample_channel_count_obj; +void audiosample_check_for_deinit(const audiosample_base_t *self); +bool audiosample_deinited(const audiosample_base_t *self); +void audiosample_mark_deinit(audiosample_base_t *self); diff --git a/shared-bindings/audiodelays/Chorus.c b/shared-bindings/audiodelays/Chorus.c new file mode 100644 index 0000000000000..87922ff110b1b --- /dev/null +++ b/shared-bindings/audiodelays/Chorus.c @@ -0,0 +1,282 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiodelays/Chorus.h" +#include "shared-module/audiodelays/Chorus.h" +#include "shared-bindings/audiocore/__init__.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class Chorus: +//| """An Chorus effect""" +//| +//| def __init__( +//| self, +//| max_delay_ms: int = 50, +//| delay_ms: synthio.BlockInput = 50.0, +//| voices: synthio.BlockInput = 1.0, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Chorus effect by playing the current sample along with one or more samples +//| (the voices) from the delay buffer. The voices played are evenly spaced across the delay +//| buffer. So for 2 voices you would hear the current sample and the one delay milliseconds back. +//| The delay timing of the chorus can be changed at runtime with the delay_ms parameter but the delay +//| can never exceed the max_delay_ms parameter. The maximum delay you can set is limited by available +//| memory. +//| +//| :param int max_delay_ms: The maximum time the chorus can be in milliseconds +//| :param synthio.BlockInput delay_ms: The current time of the chorus delay in milliseconds. Must be less the max_delay_ms. +//| :param synthio.BlockInput voices: The number of voices playing split evenly over the delay buffer. +//| :param synthio.BlockInput mix: How much of the wet audio to include along with the original signal. +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Playing adding an chorus to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiodelays +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| chorus = audiodelays.Chorus(max_delay_ms=50, delay_ms=5, buffer_size=1024, channel_count=1, sample_rate=44100) +//| chorus.play(synth) +//| audio.play(chorus) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.25) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| +static mp_obj_t audiodelays_chorus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_max_delay_ms, ARG_delay_ms, ARG_voices, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_max_delay_ms, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 50 } }, + { MP_QSTR_delay_ms, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_voices, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t max_delay_ms = mp_arg_validate_int_range(args[ARG_max_delay_ms].u_int, 1, 4000, MP_QSTR_max_delay_ms); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiodelays_chorus_obj_t *self = mp_obj_malloc(audiodelays_chorus_obj_t, &audiodelays_chorus_type); + common_hal_audiodelays_chorus_construct(self, max_delay_ms, args[ARG_delay_ms].u_obj, args[ARG_voices].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Chorus.""" +//| ... +//| +static mp_obj_t audiodelays_chorus_deinit(mp_obj_t self_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_chorus_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_deinit_obj, audiodelays_chorus_deinit); + +static void check_for_deinit(audiodelays_chorus_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Chorus: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +static mp_obj_t audiodelays_chorus_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_audiodelays_chorus_deinit(args[0]); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiodelays_chorus___exit___obj, 4, 4, audiodelays_chorus_obj___exit__); + + +//| delay_ms: synthio.BlockInput +//| """The current time of the chorus delay in milliseconds. Must be less the max_delay_ms.""" +//| +static mp_obj_t audiodelays_chorus_obj_get_delay_ms(mp_obj_t self_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_audiodelays_chorus_get_delay_ms(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_get_delay_ms_obj, audiodelays_chorus_obj_get_delay_ms); + +static mp_obj_t audiodelays_chorus_obj_set_delay_ms(mp_obj_t self_in, mp_obj_t delay_ms_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_chorus_set_delay_ms(self, delay_ms_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_chorus_set_delay_ms_obj, audiodelays_chorus_obj_set_delay_ms); + +MP_PROPERTY_GETSET(audiodelays_chorus_delay_ms_obj, + (mp_obj_t)&audiodelays_chorus_get_delay_ms_obj, + (mp_obj_t)&audiodelays_chorus_set_delay_ms_obj); + +//| voices: synthio.BlockInput +//| """The number of voices playing split evenly over the delay buffer.""" +static mp_obj_t audiodelays_chorus_obj_get_voices(mp_obj_t self_in) { + return common_hal_audiodelays_chorus_get_voices(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_get_voices_obj, audiodelays_chorus_obj_get_voices); + +static mp_obj_t audiodelays_chorus_obj_set_voices(mp_obj_t self_in, mp_obj_t voices_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_chorus_set_voices(self, voices_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_chorus_set_voices_obj, audiodelays_chorus_obj_set_voices); + +MP_PROPERTY_GETSET(audiodelays_chorus_voices_obj, + (mp_obj_t)&audiodelays_chorus_get_voices_obj, + (mp_obj_t)&audiodelays_chorus_set_voices_obj); + +//| mix: synthio.BlockInput +//| """The rate the echo mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiodelays_chorus_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiodelays_chorus_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_get_mix_obj, audiodelays_chorus_obj_get_mix); + +static mp_obj_t audiodelays_chorus_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_chorus_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_chorus_set_mix_obj, audiodelays_chorus_obj_set_mix); + +MP_PROPERTY_GETSET(audiodelays_chorus_mix_obj, + (mp_obj_t)&audiodelays_chorus_get_mix_obj, + (mp_obj_t)&audiodelays_chorus_set_mix_obj); + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiodelays_chorus_obj_get_playing(mp_obj_t self_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiodelays_chorus_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_get_playing_obj, audiodelays_chorus_obj_get_playing); + +MP_PROPERTY_GETTER(audiodelays_chorus_playing_obj, + (mp_obj_t)&audiodelays_chorus_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Chorus: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Chorus""" +//| ... +//| +static mp_obj_t audiodelays_chorus_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiodelays_chorus_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_chorus_play_obj, 1, audiodelays_chorus_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiodelays_chorus_obj_stop(mp_obj_t self_in) { + audiodelays_chorus_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiodelays_chorus_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_chorus_stop_obj, audiodelays_chorus_obj_stop); + +static const mp_rom_map_elem_t audiodelays_chorus_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_chorus_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiodelays_chorus___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_chorus_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_chorus_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_chorus_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_delay_ms), MP_ROM_PTR(&audiodelays_chorus_delay_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_voices), MP_ROM_PTR(&audiodelays_chorus_voices_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_chorus_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiodelays_chorus_locals_dict, audiodelays_chorus_locals_dict_table); + +static const audiosample_p_t audiodelays_chorus_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiodelays_chorus_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiodelays_chorus_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiodelays_chorus_type, + MP_QSTR_Chorus, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiodelays_chorus_make_new, + locals_dict, &audiodelays_chorus_locals_dict, + protocol, &audiodelays_chorus_proto + ); diff --git a/shared-bindings/audiodelays/Chorus.h b/shared-bindings/audiodelays/Chorus.h new file mode 100644 index 0000000000000..63e9ba9c28d2c --- /dev/null +++ b/shared-bindings/audiodelays/Chorus.h @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiodelays/Chorus.h" + +extern const mp_obj_type_t audiodelays_chorus_type; + +void common_hal_audiodelays_chorus_construct(audiodelays_chorus_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t voices, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiodelays_chorus_deinit(audiodelays_chorus_obj_t *self); +bool common_hal_audiodelays_chorus_deinited(audiodelays_chorus_obj_t *self); + +mp_obj_t common_hal_audiodelays_chorus_get_delay_ms(audiodelays_chorus_obj_t *self); +void common_hal_audiodelays_chorus_set_delay_ms(audiodelays_chorus_obj_t *self, mp_obj_t delay_ms); + +mp_obj_t common_hal_audiodelays_chorus_get_voices(audiodelays_chorus_obj_t *self); +void common_hal_audiodelays_chorus_set_voices(audiodelays_chorus_obj_t *self, mp_obj_t voices); + +mp_obj_t common_hal_audiodelays_chorus_get_mix(audiodelays_chorus_obj_t *self); +void common_hal_audiodelays_chorus_set_mix(audiodelays_chorus_obj_t *self, mp_obj_t arg); + +bool common_hal_audiodelays_chorus_get_playing(audiodelays_chorus_obj_t *self); +void common_hal_audiodelays_chorus_play(audiodelays_chorus_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiodelays_chorus_stop(audiodelays_chorus_obj_t *self); diff --git a/shared-bindings/audiodelays/Echo.c b/shared-bindings/audiodelays/Echo.c new file mode 100644 index 0000000000000..dbb496c61b975 --- /dev/null +++ b/shared-bindings/audiodelays/Echo.c @@ -0,0 +1,307 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiodelays/Echo.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiodelays/Echo.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class Echo: +//| """An Echo effect""" +//| +//| def __init__( +//| self, +//| max_delay_ms: int = 500, +//| delay_ms: synthio.BlockInput = 250.0, +//| decay: synthio.BlockInput = 0.7, +//| mix: synthio.BlockInput = 0.25, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Echo effect where you hear the original sample play back, at a lesser volume after +//| a set number of millisecond delay. The delay timing of the echo can be changed at runtime +//| with the delay_ms parameter but the delay can never exceed the max_delay_ms parameter. The +//| maximum delay you can set is limited by available memory. +//| +//| Each time the echo plays back the volume is reduced by the decay setting (echo * decay). +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param int max_delay_ms: The maximum time the echo can be in milliseconds +//| :param synthio.BlockInput delay_ms: The current time of the echo delay in milliseconds. Must be less the max_delay_ms +//| :param synthio.BlockInput decay: The rate the echo fades. 0.0 = instant; 1.0 = never. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| :param bool freq_shift: Do echos change frequency as the echo delay changes +//| +//| Playing adding an echo to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiodelays +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| echo = audiodelays.Echo(max_delay_ms=1000, delay_ms=850, decay=0.65, buffer_size=1024, channel_count=1, sample_rate=44100, mix=0.7, freq_shift=False) +//| echo.play(synth) +//| audio.play(echo) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.25) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| +static mp_obj_t audiodelays_echo_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_max_delay_ms, ARG_delay_ms, ARG_decay, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, ARG_freq_shift, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_max_delay_ms, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 500 } }, + { MP_QSTR_delay_ms, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_decay, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + { MP_QSTR_freq_shift, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t max_delay_ms = mp_arg_validate_int_range(args[ARG_max_delay_ms].u_int, 1, 4000, MP_QSTR_max_delay_ms); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiodelays_echo_obj_t *self = mp_obj_malloc(audiodelays_echo_obj_t, &audiodelays_echo_type); + common_hal_audiodelays_echo_construct(self, max_delay_ms, args[ARG_delay_ms].u_obj, args[ARG_decay].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate, args[ARG_freq_shift].u_bool); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Echo.""" +//| ... +//| +static mp_obj_t audiodelays_echo_deinit(mp_obj_t self_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_echo_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_deinit_obj, audiodelays_echo_deinit); + +static void check_for_deinit(audiodelays_echo_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Echo: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + + +//| delay_ms: synthio.BlockInput +//| """Delay of the echo in milliseconds. (read-only)""" +//| +static mp_obj_t audiodelays_echo_obj_get_delay_ms(mp_obj_t self_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_audiodelays_echo_get_delay_ms(self); + +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_delay_ms_obj, audiodelays_echo_obj_get_delay_ms); + +static mp_obj_t audiodelays_echo_obj_set_delay_ms(mp_obj_t self_in, mp_obj_t delay_ms_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_echo_set_delay_ms(self, delay_ms_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_echo_set_delay_ms_obj, audiodelays_echo_obj_set_delay_ms); + +MP_PROPERTY_GETSET(audiodelays_echo_delay_ms_obj, + (mp_obj_t)&audiodelays_echo_get_delay_ms_obj, + (mp_obj_t)&audiodelays_echo_set_delay_ms_obj); + +//| decay: synthio.BlockInput +//| """The rate the echo fades between 0 and 1 where 0 is instant and 1 is never.""" +static mp_obj_t audiodelays_echo_obj_get_decay(mp_obj_t self_in) { + return common_hal_audiodelays_echo_get_decay(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_decay_obj, audiodelays_echo_obj_get_decay); + +static mp_obj_t audiodelays_echo_obj_set_decay(mp_obj_t self_in, mp_obj_t decay_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_echo_set_decay(self, decay_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_echo_set_decay_obj, audiodelays_echo_obj_set_decay); + +MP_PROPERTY_GETSET(audiodelays_echo_decay_obj, + (mp_obj_t)&audiodelays_echo_get_decay_obj, + (mp_obj_t)&audiodelays_echo_set_decay_obj); + +//| mix: synthio.BlockInput +//| """The rate the echo mix between 0 and 1 where 0 is only sample, 0.5 is an equal mix of the sample and the effect and 1 is all effect.""" +static mp_obj_t audiodelays_echo_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiodelays_echo_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_mix_obj, audiodelays_echo_obj_get_mix); + +static mp_obj_t audiodelays_echo_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_echo_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_echo_set_mix_obj, audiodelays_echo_obj_set_mix); + +MP_PROPERTY_GETSET(audiodelays_echo_mix_obj, + (mp_obj_t)&audiodelays_echo_get_mix_obj, + (mp_obj_t)&audiodelays_echo_set_mix_obj); + + + +//| freq_shift: bool +//| """Does the echo change frequencies as the delay changes.""" +static mp_obj_t audiodelays_echo_obj_get_freq_shift(mp_obj_t self_in) { + return mp_obj_new_bool(common_hal_audiodelays_echo_get_freq_shift(self_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_freq_shift_obj, audiodelays_echo_obj_get_freq_shift); + +static mp_obj_t audiodelays_echo_obj_set_freq_shift(mp_obj_t self_in, mp_obj_t freq_shift_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_echo_set_freq_shift(self, mp_obj_is_true(freq_shift_in)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_echo_set_freq_shift_obj, audiodelays_echo_obj_set_freq_shift); + +MP_PROPERTY_GETSET(audiodelays_echo_freq_shift_obj, + (mp_obj_t)&audiodelays_echo_get_freq_shift_obj, + (mp_obj_t)&audiodelays_echo_set_freq_shift_obj); + + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiodelays_echo_obj_get_playing(mp_obj_t self_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiodelays_echo_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_get_playing_obj, audiodelays_echo_obj_get_playing); + +MP_PROPERTY_GETTER(audiodelays_echo_playing_obj, + (mp_obj_t)&audiodelays_echo_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Echo: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Echo""" +//| ... +//| +static mp_obj_t audiodelays_echo_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiodelays_echo_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_echo_play_obj, 1, audiodelays_echo_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample. The echo continues playing.""" +//| ... +//| +//| +static mp_obj_t audiodelays_echo_obj_stop(mp_obj_t self_in) { + audiodelays_echo_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiodelays_echo_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_echo_stop_obj, audiodelays_echo_obj_stop); + +static const mp_rom_map_elem_t audiodelays_echo_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_echo_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_echo_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_echo_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_echo_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_delay_ms), MP_ROM_PTR(&audiodelays_echo_delay_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_decay), MP_ROM_PTR(&audiodelays_echo_decay_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_echo_mix_obj) }, + { MP_ROM_QSTR(MP_QSTR_freq_shift), MP_ROM_PTR(&audiodelays_echo_freq_shift_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiodelays_echo_locals_dict, audiodelays_echo_locals_dict_table); + +static const audiosample_p_t audiodelays_echo_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiodelays_echo_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiodelays_echo_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiodelays_echo_type, + MP_QSTR_Echo, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiodelays_echo_make_new, + locals_dict, &audiodelays_echo_locals_dict, + protocol, &audiodelays_echo_proto + ); diff --git a/shared-bindings/audiodelays/Echo.h b/shared-bindings/audiodelays/Echo.h new file mode 100644 index 0000000000000..83d454ed05c57 --- /dev/null +++ b/shared-bindings/audiodelays/Echo.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiodelays/Echo.h" + +extern const mp_obj_type_t audiodelays_echo_type; + +void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t decay, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate, bool freq_shift); + +void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self); + +mp_obj_t common_hal_audiodelays_echo_get_delay_ms(audiodelays_echo_obj_t *self); +void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, mp_obj_t delay_ms); + +bool common_hal_audiodelays_echo_get_freq_shift(audiodelays_echo_obj_t *self); +void common_hal_audiodelays_echo_set_freq_shift(audiodelays_echo_obj_t *self, bool freq_shift); + +mp_obj_t common_hal_audiodelays_echo_get_decay(audiodelays_echo_obj_t *self); +void common_hal_audiodelays_echo_set_decay(audiodelays_echo_obj_t *self, mp_obj_t decay); + +mp_obj_t common_hal_audiodelays_echo_get_mix(audiodelays_echo_obj_t *self); +void common_hal_audiodelays_echo_set_mix(audiodelays_echo_obj_t *self, mp_obj_t arg); + +bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self); +void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiodelays_echo_stop(audiodelays_echo_obj_t *self); diff --git a/shared-bindings/audiodelays/MultiTapDelay.c b/shared-bindings/audiodelays/MultiTapDelay.c new file mode 100644 index 0000000000000..2126dbf990435 --- /dev/null +++ b/shared-bindings/audiodelays/MultiTapDelay.c @@ -0,0 +1,310 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiodelays/MultiTapDelay.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiodelays/MultiTapDelay.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class MultiTapDelay: +//| """A delay with multiple buffer positions to create a rhythmic effect.""" +//| +//| def __init__( +//| self, +//| max_delay_ms: int = 500, +//| delay_ms: synthio.BlockInput = 250.0, +//| decay: synthio.BlockInput = 0.7, +//| mix: synthio.BlockInput = 0.25, +//| taps: Optional[Tuple[float|Tuple[float, float], ...]] = None, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a delay effect where you hear the original sample play back at varying times, or "taps". +//| These tap positions and levels can be used to create rhythmic effects. +//| The timing of the delay can be changed at runtime with the delay_ms parameter but the delay can +//| never exceed the max_delay_ms parameter. The maximum delay you can set is limited by available +//| memory. +//| +//| Each time the delay plays back the volume is reduced by the decay setting (delay * decay). +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param int max_delay_ms: The maximum time the delay can be in milliseconds. +//| :param float delay_ms: The current time of the delay in milliseconds. Must be less than max_delay_ms. +//| :param synthio.BlockInput decay: The rate the delay fades. 0.0 = instant; 1.0 = never. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param tuple taps: The positions and levels to tap into the delay buffer. +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use. +//| :param int sample_rate: The sample rate to be used. +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect. +//| :param bool samples_signed: Effect is signed (True) or unsigned (False). +//| +//| Playing adding a multi-tap delay to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiodelays +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| effect = audiodelays.MultiTapDelay(max_delay_ms=500, delay_ms=500, decay=0.65, mix=0.5, taps=((2/3, 0.7), 1), buffer_size=1024, channel_count=1, sample_rate=44100) +//| effect.play(synth) +//| audio.play(effect) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.05) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| +static mp_obj_t audiodelays_multi_tap_delay_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_max_delay_ms, ARG_delay_ms, ARG_decay, ARG_mix, ARG_taps, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_max_delay_ms, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 500 } }, + { MP_QSTR_delay_ms, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(250) } }, + { MP_QSTR_decay, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_taps, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t max_delay_ms = mp_arg_validate_int_range(args[ARG_max_delay_ms].u_int, 1, 4000, MP_QSTR_max_delay_ms); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiodelays_multi_tap_delay_obj_t *self = mp_obj_malloc(audiodelays_multi_tap_delay_obj_t, &audiodelays_multi_tap_delay_type); + common_hal_audiodelays_multi_tap_delay_construct(self, max_delay_ms, args[ARG_delay_ms].u_obj, args[ARG_decay].u_obj, args[ARG_mix].u_obj, args[ARG_taps].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the MultiTapDelay.""" +//| ... +//| +static mp_obj_t audiodelays_multi_tap_delay_deinit(mp_obj_t self_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_multi_tap_delay_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_deinit_obj, audiodelays_multi_tap_delay_deinit); + +static void check_for_deinit(audiodelays_multi_tap_delay_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> MultiTapDelay: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + + +//| delay_ms: float +//| """Time to delay the incoming signal in milliseconds. Must be less than max_delay_ms.""" +//| +static mp_obj_t audiodelays_multi_tap_delay_obj_get_delay_ms(mp_obj_t self_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + return mp_obj_new_float(common_hal_audiodelays_multi_tap_delay_get_delay_ms(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_delay_ms_obj, audiodelays_multi_tap_delay_obj_get_delay_ms); + +static mp_obj_t audiodelays_multi_tap_delay_obj_set_delay_ms(mp_obj_t self_in, mp_obj_t delay_ms_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_multi_tap_delay_set_delay_ms(self, delay_ms_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_multi_tap_delay_set_delay_ms_obj, audiodelays_multi_tap_delay_obj_set_delay_ms); + +MP_PROPERTY_GETSET(audiodelays_multi_tap_delay_delay_ms_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_get_delay_ms_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_set_delay_ms_obj); + +//| decay: synthio.BlockInput +//| """The rate the echo fades between 0 and 1 where 0 is instant and 1 is never.""" +static mp_obj_t audiodelays_multi_tap_delay_obj_get_decay(mp_obj_t self_in) { + return common_hal_audiodelays_multi_tap_delay_get_decay(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_decay_obj, audiodelays_multi_tap_delay_obj_get_decay); + +static mp_obj_t audiodelays_multi_tap_delay_obj_set_decay(mp_obj_t self_in, mp_obj_t decay_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_multi_tap_delay_set_decay(self, decay_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_multi_tap_delay_set_decay_obj, audiodelays_multi_tap_delay_obj_set_decay); + +MP_PROPERTY_GETSET(audiodelays_multi_tap_delay_decay_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_get_decay_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_set_decay_obj); + +//| mix: synthio.BlockInput +//| """The mix of the effect between 0 and 1 where 0 is only sample, 0.5 is an equal mix of the sample and the effect and 1 is all effect.""" +static mp_obj_t audiodelays_multi_tap_delay_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiodelays_multi_tap_delay_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_mix_obj, audiodelays_multi_tap_delay_obj_get_mix); + +static mp_obj_t audiodelays_multi_tap_delay_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_multi_tap_delay_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_multi_tap_delay_set_mix_obj, audiodelays_multi_tap_delay_obj_set_mix); + +MP_PROPERTY_GETSET(audiodelays_multi_tap_delay_mix_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_get_mix_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_set_mix_obj); + +//| taps: Tuple[float|int|Tuple[float|int, float|int], ...] +//| """The position or position and level of delay taps. +//| The position is a number from 0 (start) to 1 (end) as a relative position in the delay buffer. +//| The level is a number from 0 (silence) to 1 (full volume). +//| If only a float or integer is provided as an element of the tuple, the level is assumed to be 1. +//| When retrieving the value of this property, the level will always be included.""" +//| +static mp_obj_t audiodelays_multi_tap_delay_obj_get_taps(mp_obj_t self_in) { + return common_hal_audiodelays_multi_tap_delay_get_taps(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_taps_obj, audiodelays_multi_tap_delay_obj_get_taps); + +static mp_obj_t audiodelays_multi_tap_delay_obj_set_taps(mp_obj_t self_in, mp_obj_t taps_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_multi_tap_delay_set_taps(self, taps_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_multi_tap_delay_set_taps_obj, audiodelays_multi_tap_delay_obj_set_taps); + +MP_PROPERTY_GETSET(audiodelays_multi_tap_delay_taps_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_get_taps_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_set_taps_obj); + + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiodelays_multi_tap_delay_obj_get_playing(mp_obj_t self_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiodelays_multi_tap_delay_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_get_playing_obj, audiodelays_multi_tap_delay_obj_get_playing); + +MP_PROPERTY_GETTER(audiodelays_multi_tap_delay_playing_obj, + (mp_obj_t)&audiodelays_multi_tap_delay_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> MultiTapDelay: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: MultiTapDelay""" +//| ... +//| +static mp_obj_t audiodelays_multi_tap_delay_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiodelays_multi_tap_delay_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_multi_tap_delay_play_obj, 1, audiodelays_multi_tap_delay_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample. The echo continues playing.""" +//| ... +//| +//| +static mp_obj_t audiodelays_multi_tap_delay_obj_stop(mp_obj_t self_in) { + audiodelays_multi_tap_delay_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiodelays_multi_tap_delay_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_multi_tap_delay_stop_obj, audiodelays_multi_tap_delay_obj_stop); + +static const mp_rom_map_elem_t audiodelays_multi_tap_delay_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_multi_tap_delay_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_multi_tap_delay_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_multi_tap_delay_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_multi_tap_delay_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_delay_ms), MP_ROM_PTR(&audiodelays_multi_tap_delay_delay_ms_obj) }, + { MP_ROM_QSTR(MP_QSTR_decay), MP_ROM_PTR(&audiodelays_multi_tap_delay_decay_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_multi_tap_delay_mix_obj) }, + { MP_ROM_QSTR(MP_QSTR_taps), MP_ROM_PTR(&audiodelays_multi_tap_delay_taps_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiodelays_multi_tap_delay_locals_dict, audiodelays_multi_tap_delay_locals_dict_table); + +static const audiosample_p_t audiodelays_multi_tap_delay_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiodelays_multi_tap_delay_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiodelays_multi_tap_delay_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiodelays_multi_tap_delay_type, + MP_QSTR_MultiTapDelay, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiodelays_multi_tap_delay_make_new, + locals_dict, &audiodelays_multi_tap_delay_locals_dict, + protocol, &audiodelays_multi_tap_delay_proto + ); diff --git a/shared-bindings/audiodelays/MultiTapDelay.h b/shared-bindings/audiodelays/MultiTapDelay.h new file mode 100644 index 0000000000000..6684c16b63f46 --- /dev/null +++ b/shared-bindings/audiodelays/MultiTapDelay.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiodelays/MultiTapDelay.h" + +extern const mp_obj_type_t audiodelays_multi_tap_delay_type; + +void common_hal_audiodelays_multi_tap_delay_construct(audiodelays_multi_tap_delay_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t decay, mp_obj_t mix, mp_obj_t taps, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiodelays_multi_tap_delay_deinit(audiodelays_multi_tap_delay_obj_t *self); + +mp_float_t common_hal_audiodelays_multi_tap_delay_get_delay_ms(audiodelays_multi_tap_delay_obj_t *self); +void common_hal_audiodelays_multi_tap_delay_set_delay_ms(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t delay_ms); + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_decay(audiodelays_multi_tap_delay_obj_t *self); +void common_hal_audiodelays_multi_tap_delay_set_decay(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t decay); + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_mix(audiodelays_multi_tap_delay_obj_t *self); +void common_hal_audiodelays_multi_tap_delay_set_mix(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t mix); + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_taps(audiodelays_multi_tap_delay_obj_t *self); +void common_hal_audiodelays_multi_tap_delay_set_taps(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t taps); + +bool common_hal_audiodelays_multi_tap_delay_get_playing(audiodelays_multi_tap_delay_obj_t *self); +void common_hal_audiodelays_multi_tap_delay_play(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiodelays_multi_tap_delay_stop(audiodelays_multi_tap_delay_obj_t *self); diff --git a/shared-bindings/audiodelays/PitchShift.c b/shared-bindings/audiodelays/PitchShift.c new file mode 100644 index 0000000000000..ee3bf5afdd7bd --- /dev/null +++ b/shared-bindings/audiodelays/PitchShift.c @@ -0,0 +1,275 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiodelays/PitchShift.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiodelays/PitchShift.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class PitchShift: +//| """A pitch shift effect""" +//| +//| def __init__( +//| self, +//| semitones: synthio.BlockInput = 0.0, +//| mix: synthio.BlockInput = 1.0, +//| window: int = 1024, +//| overlap: int = 128, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a pitch shift effect where the original sample play back is altered to change the +//| the perceived pitch by a factor of semi-tones (1/12th of an octave). This effect will cause +//| a slight delay in the output depending on the size of the window and overlap buffers. +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param synthio.BlockInput semitones: The amount of pitch shifting in semitones (1/12th of an octave) +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0) +//| :param int window: The total size in bytes of the window buffer used alter the playback pitch +//| :param int overlap: The total size in bytes of the overlap buffer used to prevent popping in the output. If set as 0, no overlap will be used. +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Shifting the pitch of a synth by 5 semitones:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiodelays +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP0, word_select=board.GP1, data=board.GP2) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| pitch_shift = audiodelays.PitchShift(semitones=5.0, mix=0.5, window=2048, overlap=256, buffer_size=1024, channel_count=1, sample_rate=44100) +//| pitch_shift.play(synth) +//| audio.play(pitch_shift) +//| +//| while True: +//| for notenum in (60, 64, 67, 71): +//| synth.press(notenum) +//| time.sleep(0.25) +//| synth.release_all()""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_semitones, ARG_mix, ARG_window, ARG_overlap, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_semitones, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0)} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1)} }, + { MP_QSTR_window, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1024} }, + { MP_QSTR_overlap, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 128} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiodelays_pitch_shift_obj_t *self = + mp_obj_malloc(audiodelays_pitch_shift_obj_t, &audiodelays_pitch_shift_type); + common_hal_audiodelays_pitch_shift_construct(self, + args[ARG_semitones].u_obj, + args[ARG_mix].u_obj, + args[ARG_window].u_int, + args[ARG_overlap].u_int, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + + +//| def deinit(self) -> None: +//| """Deinitialises the PitchShift.""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_deinit(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_deinit_obj, audiodelays_pitch_shift_deinit); + +static void check_for_deinit(audiodelays_pitch_shift_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + + +//| def __enter__(self) -> PitchShift: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_audiodelays_pitch_shift_deinit(args[0]); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiodelays_pitch_shift___exit___obj, 4, 4, audiodelays_pitch_shift_obj___exit__); + + +//| semitones: synthio.BlockInput +//| """The amount of pitch shifting in semitones (1/12th of an octave).""" +//| +static mp_obj_t audiodelays_pitch_shift_obj_get_semitones(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_audiodelays_pitch_shift_get_semitones(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_semitones_obj, audiodelays_pitch_shift_obj_get_semitones); + +static mp_obj_t audiodelays_pitch_shift_obj_set_semitones(mp_obj_t self_in, mp_obj_t semitones_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_set_semitones(self, semitones_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_pitch_shift_set_semitones_obj, audiodelays_pitch_shift_obj_set_semitones); + +MP_PROPERTY_GETSET(audiodelays_pitch_shift_semitones_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_semitones_obj, + (mp_obj_t)&audiodelays_pitch_shift_set_semitones_obj); + + +//| mix: synthio.BlockInput +//| """The output mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiodelays_pitch_shift_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiodelays_pitch_shift_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_mix_obj, audiodelays_pitch_shift_obj_get_mix); + +static mp_obj_t audiodelays_pitch_shift_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiodelays_pitch_shift_set_mix_obj, audiodelays_pitch_shift_obj_set_mix); + +MP_PROPERTY_GETSET(audiodelays_pitch_shift_mix_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_mix_obj, + (mp_obj_t)&audiodelays_pitch_shift_set_mix_obj); + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiodelays_pitch_shift_obj_get_playing(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiodelays_pitch_shift_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_get_playing_obj, audiodelays_pitch_shift_obj_get_playing); + +MP_PROPERTY_GETTER(audiodelays_pitch_shift_playing_obj, + (mp_obj_t)&audiodelays_pitch_shift_get_playing_obj); + + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> PitchShift: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: PitchShift""" +//| ... +//| +static mp_obj_t audiodelays_pitch_shift_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiodelays_pitch_shift_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiodelays_pitch_shift_play_obj, 1, audiodelays_pitch_shift_obj_play); + + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiodelays_pitch_shift_obj_stop(mp_obj_t self_in) { + audiodelays_pitch_shift_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiodelays_pitch_shift_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiodelays_pitch_shift_stop_obj, audiodelays_pitch_shift_obj_stop); + + +static const mp_rom_map_elem_t audiodelays_pitch_shift_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiodelays_pitch_shift_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiodelays_pitch_shift___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiodelays_pitch_shift_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiodelays_pitch_shift_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiodelays_pitch_shift_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_semitones), MP_ROM_PTR(&audiodelays_pitch_shift_semitones_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiodelays_pitch_shift_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiodelays_pitch_shift_locals_dict, audiodelays_pitch_shift_locals_dict_table); + +static const audiosample_p_t audiodelays_pitch_shift_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiodelays_pitch_shift_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiodelays_pitch_shift_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiodelays_pitch_shift_type, + MP_QSTR_PitchShift, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiodelays_pitch_shift_make_new, + locals_dict, &audiodelays_pitch_shift_locals_dict, + protocol, &audiodelays_pitch_shift_proto + ); diff --git a/shared-bindings/audiodelays/PitchShift.h b/shared-bindings/audiodelays/PitchShift.h new file mode 100644 index 0000000000000..78c78b5ea828e --- /dev/null +++ b/shared-bindings/audiodelays/PitchShift.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiodelays/PitchShift.h" + +extern const mp_obj_type_t audiodelays_pitch_shift_type; + +void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t *self, + mp_obj_t semitones, mp_obj_t mix, uint32_t window, uint32_t overlap, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self); + +mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t semitones); + +mp_obj_t common_hal_audiodelays_pitch_shift_get_mix(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_set_mix(audiodelays_pitch_shift_obj_t *self, mp_obj_t arg); + +bool common_hal_audiodelays_pitch_shift_get_playing(audiodelays_pitch_shift_obj_t *self); +void common_hal_audiodelays_pitch_shift_play(audiodelays_pitch_shift_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiodelays_pitch_shift_stop(audiodelays_pitch_shift_obj_t *self); diff --git a/shared-bindings/audiodelays/__init__.c b/shared-bindings/audiodelays/__init__.c new file mode 100644 index 0000000000000..e93052eabfd4a --- /dev/null +++ b/shared-bindings/audiodelays/__init__.c @@ -0,0 +1,39 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/audiodelays/__init__.h" +#include "shared-bindings/audiodelays/Echo.h" +#include "shared-bindings/audiodelays/Chorus.h" +#include "shared-bindings/audiodelays/PitchShift.h" +#include "shared-bindings/audiodelays/MultiTapDelay.h" + +//| """Support for audio delay effects +//| +//| The `audiodelays` module contains classes to provide access to audio delay effects. +//| +//| """ + +static const mp_rom_map_elem_t audiodelays_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiodelays) }, + { MP_ROM_QSTR(MP_QSTR_Echo), MP_ROM_PTR(&audiodelays_echo_type) }, + { MP_ROM_QSTR(MP_QSTR_Chorus), MP_ROM_PTR(&audiodelays_chorus_type) }, + { MP_ROM_QSTR(MP_QSTR_PitchShift), MP_ROM_PTR(&audiodelays_pitch_shift_type) }, + { MP_ROM_QSTR(MP_QSTR_MultiTapDelay), MP_ROM_PTR(&audiodelays_multi_tap_delay_type) }, +}; + +static MP_DEFINE_CONST_DICT(audiodelays_module_globals, audiodelays_module_globals_table); + +const mp_obj_module_t audiodelays_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audiodelays_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audiodelays, audiodelays_module); diff --git a/shared-bindings/audiodelays/__init__.h b/shared-bindings/audiodelays/__init__.h new file mode 100644 index 0000000000000..3bc9246e5bbf0 --- /dev/null +++ b/shared-bindings/audiodelays/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/audiofilters/Distortion.c b/shared-bindings/audiofilters/Distortion.c new file mode 100644 index 0000000000000..bed28f5ed4973 --- /dev/null +++ b/shared-bindings/audiofilters/Distortion.c @@ -0,0 +1,401 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiofilters/Distortion.h" +#include "shared-bindings/audiocore/__init__.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/enum.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class DistortionMode: +//| """The method of distortion used by the `audiofilters.Distortion` effect.""" +//| +//| CLIP: DistortionMode +//| """Digital distortion effect which cuts off peaks at the top and bottom of the waveform.""" +//| +//| LOFI: DistortionMode +//| """Low-resolution digital distortion effect (bit depth reduction). You can use it to emulate the sound of early digital audio devices.""" +//| +//| OVERDRIVE: DistortionMode +//| """Emulates the warm distortion produced by a field effect transistor, which is commonly used in solid-state musical instrument amplifiers. The `audiofilters.Distortion.drive` property has no effect in this mode.""" +//| +//| WAVESHAPE: DistortionMode +//| """Waveshaper distortions are used mainly by electronic musicians to achieve an extra-abrasive sound.""" +//| +//| + +MAKE_ENUM_VALUE(audiofilters_distortion_mode_type, distortion_mode, CLIP, DISTORTION_MODE_CLIP); +MAKE_ENUM_VALUE(audiofilters_distortion_mode_type, distortion_mode, LOFI, DISTORTION_MODE_LOFI); +MAKE_ENUM_VALUE(audiofilters_distortion_mode_type, distortion_mode, OVERDRIVE, DISTORTION_MODE_OVERDRIVE); +MAKE_ENUM_VALUE(audiofilters_distortion_mode_type, distortion_mode, WAVESHAPE, DISTORTION_MODE_WAVESHAPE); + +MAKE_ENUM_MAP(audiofilters_distortion_mode) { + MAKE_ENUM_MAP_ENTRY(distortion_mode, CLIP), + MAKE_ENUM_MAP_ENTRY(distortion_mode, LOFI), + MAKE_ENUM_MAP_ENTRY(distortion_mode, OVERDRIVE), + MAKE_ENUM_MAP_ENTRY(distortion_mode, WAVESHAPE), +}; + +static MP_DEFINE_CONST_DICT(audiofilters_distortion_mode_locals_dict, audiofilters_distortion_mode_locals_table); + +MAKE_PRINTER(audiofilters, audiofilters_distortion_mode); + +MAKE_ENUM_TYPE(audiofilters, DistortionMode, audiofilters_distortion_mode); + +static audiofilters_distortion_mode validate_distortion_mode(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&audiofilters_distortion_mode_type, obj, arg_name); +} + +//| class Distortion: +//| """A Distortion effect""" +//| +//| def __init__( +//| self, +//| drive: synthio.BlockInput = 0.0, +//| pre_gain: synthio.BlockInput = 0.0, +//| post_gain: synthio.BlockInput = 0.0, +//| mode: DistortionMode = DistortionMode.CLIP, +//| soft_clip: bool = False, +//| mix: synthio.BlockInput = 1.0, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Distortion effect where the original sample is manipulated to create a distorted +//| sound according to the DistortionMode. +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param synthio.BlockInput drive: Distortion power. Value can range from 0.0 to 1.0. +//| :param synthio.BlockInput pre_gain: Increases or decreases the volume before the effect, in decibels. Value can range from -60 to 60. +//| :param synthio.BlockInput post_gain: Increases or decreases the volume after the effect, in decibels. Value can range from -80 to 24. +//| :param DistortionMode mode: Distortion type. +//| :param bool soft_clip: Whether or not to soft clip (True) or hard clip (False) the output. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Playing adding a distortion to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiofilters +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| effect = audiofilters.Distortion(drive=0.5, mix=1.0, buffer_size=1024, channel_count=1, sample_rate=44100) +//| effect.play(synth) +//| audio.play(effect) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.25) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| + +static mp_obj_t audiofilters_distortion_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_drive, ARG_pre_gain, ARG_post_gain, ARG_mode, ARG_soft_clip, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_drive, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0)} }, + { MP_QSTR_pre_gain, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0)} }, + { MP_QSTR_post_gain, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0)} }, + { MP_QSTR_mode, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_soft_clip, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1)} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiofilters_distortion_mode mode = DISTORTION_MODE_CLIP; + if (args[ARG_mode].u_obj != MP_OBJ_NULL) { + mode = validate_distortion_mode(args[ARG_mode].u_obj, MP_QSTR_mode); + } + + audiofilters_distortion_obj_t *self = + mp_obj_malloc(audiofilters_distortion_obj_t, &audiofilters_distortion_type); + common_hal_audiofilters_distortion_construct(self, + args[ARG_drive].u_obj, + args[ARG_pre_gain].u_obj, + args[ARG_post_gain].u_obj, + mode, + args[ARG_soft_clip].u_obj, + args[ARG_mix].u_obj, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Distortion.""" +//| ... +//| +static mp_obj_t audiofilters_distortion_deinit(mp_obj_t self_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_deinit_obj, audiofilters_distortion_deinit); + +static void check_for_deinit(audiofilters_distortion_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Distortion: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + + +//| drive: synthio.BlockInput +//| """Distortion power. Value can range from 0.0 to 1.0.""" +static mp_obj_t audiofilters_distortion_obj_get_drive(mp_obj_t self_in) { + return common_hal_audiofilters_distortion_get_drive(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_drive_obj, audiofilters_distortion_obj_get_drive); + +static mp_obj_t audiofilters_distortion_obj_set_drive(mp_obj_t self_in, mp_obj_t drive_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_set_drive(self, drive_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_drive_obj, audiofilters_distortion_obj_set_drive); + +MP_PROPERTY_GETSET(audiofilters_distortion_drive_obj, + (mp_obj_t)&audiofilters_distortion_get_drive_obj, + (mp_obj_t)&audiofilters_distortion_set_drive_obj); + + +//| pre_gain: synthio.BlockInput +//| """Increases or decreases the volume before the effect, in decibels. Value can range from -60 to 60.""" +static mp_obj_t audiofilters_distortion_obj_get_pre_gain(mp_obj_t self_in) { + return common_hal_audiofilters_distortion_get_pre_gain(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_pre_gain_obj, audiofilters_distortion_obj_get_pre_gain); + +static mp_obj_t audiofilters_distortion_obj_set_pre_gain(mp_obj_t self_in, mp_obj_t pre_gain_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_set_pre_gain(self, pre_gain_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_pre_gain_obj, audiofilters_distortion_obj_set_pre_gain); + +MP_PROPERTY_GETSET(audiofilters_distortion_pre_gain_obj, + (mp_obj_t)&audiofilters_distortion_get_pre_gain_obj, + (mp_obj_t)&audiofilters_distortion_set_pre_gain_obj); + + +//| post_gain: synthio.BlockInput +//| """Increases or decreases the volume after the effect, in decibels. Value can range from -80 to 24.""" +static mp_obj_t audiofilters_distortion_obj_get_post_gain(mp_obj_t self_in) { + return common_hal_audiofilters_distortion_get_post_gain(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_post_gain_obj, audiofilters_distortion_obj_get_post_gain); + +static mp_obj_t audiofilters_distortion_obj_set_post_gain(mp_obj_t self_in, mp_obj_t post_gain_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_set_post_gain(self, post_gain_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_post_gain_obj, audiofilters_distortion_obj_set_post_gain); + +MP_PROPERTY_GETSET(audiofilters_distortion_post_gain_obj, + (mp_obj_t)&audiofilters_distortion_get_post_gain_obj, + (mp_obj_t)&audiofilters_distortion_set_post_gain_obj); + + +//| mode: DistortionMode +//| """Distortion type.""" +static mp_obj_t audiofilters_distortion_obj_get_mode(mp_obj_t self_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return cp_enum_find(&audiofilters_distortion_mode_type, common_hal_audiofilters_distortion_get_mode(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_mode_obj, audiofilters_distortion_obj_get_mode); + +static mp_obj_t audiofilters_distortion_obj_set_mode(mp_obj_t self_in, mp_obj_t mode_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiofilters_distortion_mode mode = validate_distortion_mode(mode_in, MP_QSTR_mode); + common_hal_audiofilters_distortion_set_mode(self, mode); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_mode_obj, audiofilters_distortion_obj_set_mode); + +MP_PROPERTY_GETSET(audiofilters_distortion_mode_obj, + (mp_obj_t)&audiofilters_distortion_get_mode_obj, + (mp_obj_t)&audiofilters_distortion_set_mode_obj); + + +//| soft_clip: bool +//| """Whether or not to soft clip (True) or hard clip (False) the output.""" +static mp_obj_t audiofilters_distortion_obj_get_soft_clip(mp_obj_t self_in) { + return mp_obj_new_bool(common_hal_audiofilters_distortion_get_soft_clip(self_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_soft_clip_obj, audiofilters_distortion_obj_get_soft_clip); + +static mp_obj_t audiofilters_distortion_obj_set_soft_clip(mp_obj_t self_in, mp_obj_t soft_clip_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_set_soft_clip(self, mp_obj_is_true(soft_clip_in)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_soft_clip_obj, audiofilters_distortion_obj_set_soft_clip); + +MP_PROPERTY_GETSET(audiofilters_distortion_soft_clip_obj, + (mp_obj_t)&audiofilters_distortion_get_soft_clip_obj, + (mp_obj_t)&audiofilters_distortion_set_soft_clip_obj); + + +//| mix: synthio.BlockInput +//| """The rate the filtered signal mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiofilters_distortion_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiofilters_distortion_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_mix_obj, audiofilters_distortion_obj_get_mix); + +static mp_obj_t audiofilters_distortion_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_distortion_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_distortion_set_mix_obj, audiofilters_distortion_obj_set_mix); + +MP_PROPERTY_GETSET(audiofilters_distortion_mix_obj, + (mp_obj_t)&audiofilters_distortion_get_mix_obj, + (mp_obj_t)&audiofilters_distortion_set_mix_obj); + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiofilters_distortion_obj_get_playing(mp_obj_t self_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiofilters_distortion_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_get_playing_obj, audiofilters_distortion_obj_get_playing); + +MP_PROPERTY_GETTER(audiofilters_distortion_playing_obj, + (mp_obj_t)&audiofilters_distortion_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Distortion: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Distortion""" +//| ... +//| +static mp_obj_t audiofilters_distortion_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiofilters_distortion_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_distortion_play_obj, 1, audiofilters_distortion_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiofilters_distortion_obj_stop(mp_obj_t self_in) { + audiofilters_distortion_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiofilters_distortion_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_distortion_stop_obj, audiofilters_distortion_obj_stop); + +static const mp_rom_map_elem_t audiofilters_distortion_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiofilters_distortion_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiofilters_distortion_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiofilters_distortion_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofilters_distortion_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_drive), MP_ROM_PTR(&audiofilters_distortion_drive_obj) }, + { MP_ROM_QSTR(MP_QSTR_pre_gain), MP_ROM_PTR(&audiofilters_distortion_pre_gain_obj) }, + { MP_ROM_QSTR(MP_QSTR_post_gain), MP_ROM_PTR(&audiofilters_distortion_post_gain_obj) }, + { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&audiofilters_distortion_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_soft_clip), MP_ROM_PTR(&audiofilters_distortion_soft_clip_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofilters_distortion_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiofilters_distortion_locals_dict, audiofilters_distortion_locals_dict_table); + +static const audiosample_p_t audiofilters_distortion_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiofilters_distortion_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiofilters_distortion_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiofilters_distortion_type, + MP_QSTR_Distortion, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiofilters_distortion_make_new, + locals_dict, &audiofilters_distortion_locals_dict, + protocol, &audiofilters_distortion_proto + ); diff --git a/shared-bindings/audiofilters/Distortion.h b/shared-bindings/audiofilters/Distortion.h new file mode 100644 index 0000000000000..ded32eada303a --- /dev/null +++ b/shared-bindings/audiofilters/Distortion.h @@ -0,0 +1,42 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiofilters/Distortion.h" + +extern const mp_obj_type_t audiofilters_distortion_type; +extern const mp_obj_type_t audiofilters_distortion_mode_type; + +void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t *self, + mp_obj_t drive, mp_obj_t pre_gain, mp_obj_t post_gain, + audiofilters_distortion_mode mode, bool soft_clip, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self); + +mp_obj_t common_hal_audiofilters_distortion_get_drive(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_drive(audiofilters_distortion_obj_t *self, mp_obj_t arg); + +mp_obj_t common_hal_audiofilters_distortion_get_pre_gain(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_pre_gain(audiofilters_distortion_obj_t *self, mp_obj_t arg); + +mp_obj_t common_hal_audiofilters_distortion_get_post_gain(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_post_gain(audiofilters_distortion_obj_t *self, mp_obj_t arg); + +audiofilters_distortion_mode common_hal_audiofilters_distortion_get_mode(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_mode(audiofilters_distortion_obj_t *self, audiofilters_distortion_mode mode); + +bool common_hal_audiofilters_distortion_get_soft_clip(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_soft_clip(audiofilters_distortion_obj_t *self, bool soft_clip); + +mp_obj_t common_hal_audiofilters_distortion_get_mix(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_set_mix(audiofilters_distortion_obj_t *self, mp_obj_t arg); + +bool common_hal_audiofilters_distortion_get_playing(audiofilters_distortion_obj_t *self); +void common_hal_audiofilters_distortion_play(audiofilters_distortion_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiofilters_distortion_stop(audiofilters_distortion_obj_t *self); diff --git a/shared-bindings/audiofilters/Filter.c b/shared-bindings/audiofilters/Filter.c new file mode 100644 index 0000000000000..2d0d12b226abe --- /dev/null +++ b/shared-bindings/audiofilters/Filter.c @@ -0,0 +1,261 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiofilters/Filter.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiofilters/Filter.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class Filter: +//| """A Filter effect""" +//| +//| def __init__( +//| self, +//| filter: Optional[synthio.Biquad | Tuple[synthio.Biquad]] = None, +//| mix: synthio.BlockInput = 1.0, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Filter effect where the original sample is processed through a biquad filter +//| created by a synthio.Synthesizer object. This can be used to generate a low-pass, +//| high-pass, or band-pass filter. +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param Optional[synthio.Biquad|Tuple[synthio.Biquad]] filter: A normalized biquad filter object or tuple of normalized biquad filter objects. The sample is processed sequentially by each filter to produce the output samples. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Playing adding a filter to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiofilters +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| effect = audiofilters.Filter(buffer_size=1024, channel_count=1, sample_rate=44100, mix=1.0) +//| effect.filter = synth.low_pass_filter(frequency=2000, Q=1.25) +//| effect.play(synth) +//| audio.play(effect) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.25) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| +static mp_obj_t audiofilters_filter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_filter, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_filter, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1)} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiofilters_filter_obj_t *self = mp_obj_malloc(audiofilters_filter_obj_t, &audiofilters_filter_type); + common_hal_audiofilters_filter_construct(self, + args[ARG_filter].u_obj, + args[ARG_mix].u_obj, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Filter.""" +//| ... +//| +static mp_obj_t audiofilters_filter_deinit(mp_obj_t self_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_filter_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_deinit_obj, audiofilters_filter_deinit); + +static void check_for_deinit(audiofilters_filter_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Filter: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + + +//| filter: synthio.Biquad | Tuple[synthio.Biquad] | None +//| """A normalized biquad filter object or tuple of normalized biquad filter objects. The sample is processed sequentially by each filter to produce the output samples.""" +//| +static mp_obj_t audiofilters_filter_obj_get_filter(mp_obj_t self_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return common_hal_audiofilters_filter_get_filter(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_get_filter_obj, audiofilters_filter_obj_get_filter); + +static mp_obj_t audiofilters_filter_obj_set_filter(mp_obj_t self_in, mp_obj_t filter_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_filter_set_filter(self, filter_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_filter_set_filter_obj, audiofilters_filter_obj_set_filter); + +MP_PROPERTY_GETSET(audiofilters_filter_filter_obj, + (mp_obj_t)&audiofilters_filter_get_filter_obj, + (mp_obj_t)&audiofilters_filter_set_filter_obj); + + +//| mix: synthio.BlockInput +//| """The rate the filtered signal mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiofilters_filter_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiofilters_filter_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_get_mix_obj, audiofilters_filter_obj_get_mix); + +static mp_obj_t audiofilters_filter_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_filter_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_filter_set_mix_obj, audiofilters_filter_obj_set_mix); + +MP_PROPERTY_GETSET(audiofilters_filter_mix_obj, + (mp_obj_t)&audiofilters_filter_get_mix_obj, + (mp_obj_t)&audiofilters_filter_set_mix_obj); + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiofilters_filter_obj_get_playing(mp_obj_t self_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiofilters_filter_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_get_playing_obj, audiofilters_filter_obj_get_playing); + +MP_PROPERTY_GETTER(audiofilters_filter_playing_obj, + (mp_obj_t)&audiofilters_filter_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Filter: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Filter""" +//| ... +//| +static mp_obj_t audiofilters_filter_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiofilters_filter_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_filter_play_obj, 1, audiofilters_filter_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiofilters_filter_obj_stop(mp_obj_t self_in) { + audiofilters_filter_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiofilters_filter_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_filter_stop_obj, audiofilters_filter_obj_stop); + +static const mp_rom_map_elem_t audiofilters_filter_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiofilters_filter_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiofilters_filter_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiofilters_filter_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofilters_filter_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_filter), MP_ROM_PTR(&audiofilters_filter_filter_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofilters_filter_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiofilters_filter_locals_dict, audiofilters_filter_locals_dict_table); + +static const audiosample_p_t audiofilters_filter_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiofilters_filter_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiofilters_filter_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiofilters_filter_type, + MP_QSTR_Filter, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiofilters_filter_make_new, + locals_dict, &audiofilters_filter_locals_dict, + protocol, &audiofilters_filter_proto + ); diff --git a/shared-bindings/audiofilters/Filter.h b/shared-bindings/audiofilters/Filter.h new file mode 100644 index 0000000000000..e8dac00ba9ffd --- /dev/null +++ b/shared-bindings/audiofilters/Filter.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiofilters/Filter.h" + +extern const mp_obj_type_t audiofilters_filter_type; + +void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, + mp_obj_t filter, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self); + +mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self); +void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t arg); + +mp_obj_t common_hal_audiofilters_filter_get_mix(audiofilters_filter_obj_t *self); +void common_hal_audiofilters_filter_set_mix(audiofilters_filter_obj_t *self, mp_obj_t arg); + +bool common_hal_audiofilters_filter_get_playing(audiofilters_filter_obj_t *self); +void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiofilters_filter_stop(audiofilters_filter_obj_t *self); diff --git a/shared-bindings/audiofilters/Phaser.c b/shared-bindings/audiofilters/Phaser.c new file mode 100644 index 0000000000000..2aed9623b7219 --- /dev/null +++ b/shared-bindings/audiofilters/Phaser.c @@ -0,0 +1,300 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiofilters/Phaser.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiofilters/Phaser.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class Phaser: +//| """A Phaser effect""" +//| +//| def __init__( +//| self, +//| frequency: synthio.BlockInput = 1000.0, +//| feedback: synthio.BlockInput = 0.7, +//| mix: synthio.BlockInput = 1.0, +//| stages: int = 6, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Phaser effect where the original sample is processed through a variable +//| number of all-pass filter stages. This slightly delays the signal so that it is out +//| of phase with the original signal. When the amount of phase is modulated and mixed +//| back into the original signal with the mix parameter, it creates a distinctive +//| phasing sound. +//| +//| :param synthio.BlockInput frequency: The target frequency which is affected by the effect in hz. +//| :param int stages: The number of all-pass filters which will be applied to the signal. +//| :param synthio.BlockInput feedback: The amount that the previous output of the filters is mixed back into their input along with the unprocessed signal. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect +//| :param bool samples_signed: Effect is signed (True) or unsigned (False) +//| +//| Playing adding a phaser to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import audiofilters +//| import synthio +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| effect = audiofilters.Phaser(channel_count=1, sample_rate=44100) +//| effect.frequency = synthio.LFO(offset=1000.0, scale=600.0, rate=0.5) +//| effect.play(synth) +//| audio.play(effect) +//| +//| synth.press(48)""" +//| ... +//| +static mp_obj_t audiofilters_phaser_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_frequency, ARG_feedback, ARG_mix, ARG_stages, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_frequency, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1000) } }, + { MP_QSTR_feedback, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1)} }, + { MP_QSTR_stages, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 6 } }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 8 && bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); + } + + audiofilters_phaser_obj_t *self = mp_obj_malloc(audiofilters_phaser_obj_t, &audiofilters_phaser_type); + common_hal_audiofilters_phaser_construct(self, + args[ARG_frequency].u_obj, + args[ARG_feedback].u_obj, + args[ARG_mix].u_obj, + args[ARG_stages].u_int, + args[ARG_buffer_size].u_int, + bits_per_sample, + args[ARG_samples_signed].u_bool, + channel_count, + sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Phaser.""" +//| ... +//| +static mp_obj_t audiofilters_phaser_deinit(mp_obj_t self_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_phaser_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_deinit_obj, audiofilters_phaser_deinit); + +static void check_for_deinit(audiofilters_phaser_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Phaser: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + + +//| frequency: synthio.BlockInput +//| """The target frequency in hertz at which the phaser is delaying the signal.""" +static mp_obj_t audiofilters_phaser_obj_get_frequency(mp_obj_t self_in) { + return common_hal_audiofilters_phaser_get_frequency(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_frequency_obj, audiofilters_phaser_obj_get_frequency); + +static mp_obj_t audiofilters_phaser_obj_set_frequency(mp_obj_t self_in, mp_obj_t frequency_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_phaser_set_frequency(self, frequency_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_phaser_set_frequency_obj, audiofilters_phaser_obj_set_frequency); + +MP_PROPERTY_GETSET(audiofilters_phaser_frequency_obj, + (mp_obj_t)&audiofilters_phaser_get_frequency_obj, + (mp_obj_t)&audiofilters_phaser_set_frequency_obj); + + +//| feedback: synthio.BlockInput +//| """The amount of which the incoming signal is fed back into the phasing filters from 0.1 to 0.9.""" +static mp_obj_t audiofilters_phaser_obj_get_feedback(mp_obj_t self_in) { + return common_hal_audiofilters_phaser_get_feedback(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_feedback_obj, audiofilters_phaser_obj_get_feedback); + +static mp_obj_t audiofilters_phaser_obj_set_feedback(mp_obj_t self_in, mp_obj_t feedback_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_phaser_set_feedback(self, feedback_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_phaser_set_feedback_obj, audiofilters_phaser_obj_set_feedback); + +MP_PROPERTY_GETSET(audiofilters_phaser_feedback_obj, + (mp_obj_t)&audiofilters_phaser_get_feedback_obj, + (mp_obj_t)&audiofilters_phaser_set_feedback_obj); + + +//| mix: synthio.BlockInput +//| """The amount that the effect signal is mixed into the output between 0 and 1 where 0 is only the original sample and 1 is all effect.""" +static mp_obj_t audiofilters_phaser_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiofilters_phaser_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_mix_obj, audiofilters_phaser_obj_get_mix); + +static mp_obj_t audiofilters_phaser_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_phaser_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_phaser_set_mix_obj, audiofilters_phaser_obj_set_mix); + +MP_PROPERTY_GETSET(audiofilters_phaser_mix_obj, + (mp_obj_t)&audiofilters_phaser_get_mix_obj, + (mp_obj_t)&audiofilters_phaser_set_mix_obj); + + +//| stages: int +//| """The number of allpass filters to pass the signal through. More stages requires more processing but produces a more pronounced effect. Requires a minimum value of 1.""" +static mp_obj_t audiofilters_phaser_obj_get_stages(mp_obj_t self_in) { + return MP_OBJ_NEW_SMALL_INT(common_hal_audiofilters_phaser_get_stages(self_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_stages_obj, audiofilters_phaser_obj_get_stages); + +static mp_obj_t audiofilters_phaser_obj_set_stages(mp_obj_t self_in, mp_obj_t stages_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofilters_phaser_set_stages(self, mp_obj_get_int(stages_in)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofilters_phaser_set_stages_obj, audiofilters_phaser_obj_set_stages); + +MP_PROPERTY_GETSET(audiofilters_phaser_stages_obj, + (mp_obj_t)&audiofilters_phaser_get_stages_obj, + (mp_obj_t)&audiofilters_phaser_set_stages_obj); + + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiofilters_phaser_obj_get_playing(mp_obj_t self_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiofilters_phaser_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_get_playing_obj, audiofilters_phaser_obj_get_playing); + +MP_PROPERTY_GETTER(audiofilters_phaser_playing_obj, + (mp_obj_t)&audiofilters_phaser_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Phaser: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Phaser""" +//| ... +//| +static mp_obj_t audiofilters_phaser_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiofilters_phaser_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiofilters_phaser_play_obj, 1, audiofilters_phaser_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample.""" +//| ... +//| +//| +static mp_obj_t audiofilters_phaser_obj_stop(mp_obj_t self_in) { + audiofilters_phaser_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiofilters_phaser_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofilters_phaser_stop_obj, audiofilters_phaser_obj_stop); + +static const mp_rom_map_elem_t audiofilters_phaser_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiofilters_phaser_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiofilters_phaser_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiofilters_phaser_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofilters_phaser_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&audiofilters_phaser_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_feedback), MP_ROM_PTR(&audiofilters_phaser_feedback_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofilters_phaser_mix_obj) }, + { MP_ROM_QSTR(MP_QSTR_stages), MP_ROM_PTR(&audiofilters_phaser_stages_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiofilters_phaser_locals_dict, audiofilters_phaser_locals_dict_table); + +static const audiosample_p_t audiofilters_phaser_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiofilters_phaser_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiofilters_phaser_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiofilters_phaser_type, + MP_QSTR_Phaser, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiofilters_phaser_make_new, + locals_dict, &audiofilters_phaser_locals_dict, + protocol, &audiofilters_phaser_proto + ); diff --git a/shared-bindings/audiofilters/Phaser.h b/shared-bindings/audiofilters/Phaser.h new file mode 100644 index 0000000000000..dbab22f571025 --- /dev/null +++ b/shared-bindings/audiofilters/Phaser.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiofilters/Phaser.h" + +extern const mp_obj_type_t audiofilters_phaser_type; + +void common_hal_audiofilters_phaser_construct(audiofilters_phaser_obj_t *self, + mp_obj_t frequency, mp_obj_t feedback, mp_obj_t mix, uint8_t stages, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiofilters_phaser_deinit(audiofilters_phaser_obj_t *self); + +mp_obj_t common_hal_audiofilters_phaser_get_frequency(audiofilters_phaser_obj_t *self); +void common_hal_audiofilters_phaser_set_frequency(audiofilters_phaser_obj_t *self, mp_obj_t arg); + +mp_obj_t common_hal_audiofilters_phaser_get_feedback(audiofilters_phaser_obj_t *self); +void common_hal_audiofilters_phaser_set_feedback(audiofilters_phaser_obj_t *self, mp_obj_t arg); + +mp_obj_t common_hal_audiofilters_phaser_get_mix(audiofilters_phaser_obj_t *self); +void common_hal_audiofilters_phaser_set_mix(audiofilters_phaser_obj_t *self, mp_obj_t arg); + +uint8_t common_hal_audiofilters_phaser_get_stages(audiofilters_phaser_obj_t *self); +void common_hal_audiofilters_phaser_set_stages(audiofilters_phaser_obj_t *self, uint8_t arg); + +bool common_hal_audiofilters_phaser_get_playing(audiofilters_phaser_obj_t *self); +void common_hal_audiofilters_phaser_play(audiofilters_phaser_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiofilters_phaser_stop(audiofilters_phaser_obj_t *self); diff --git a/shared-bindings/audiofilters/__init__.c b/shared-bindings/audiofilters/__init__.c new file mode 100644 index 0000000000000..ae43af9bfef83 --- /dev/null +++ b/shared-bindings/audiofilters/__init__.c @@ -0,0 +1,40 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/audiofilters/__init__.h" +#include "shared-bindings/audiofilters/Distortion.h" +#include "shared-bindings/audiofilters/Filter.h" +#include "shared-bindings/audiofilters/Phaser.h" + +//| """Support for audio filter effects +//| +//| The `audiofilters` module contains classes to provide access to audio filter effects. +//| +//| """ + +static const mp_rom_map_elem_t audiofilters_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiofilters) }, + { MP_ROM_QSTR(MP_QSTR_Filter), MP_ROM_PTR(&audiofilters_filter_type) }, + { MP_ROM_QSTR(MP_QSTR_Distortion), MP_ROM_PTR(&audiofilters_distortion_type) }, + { MP_ROM_QSTR(MP_QSTR_Phaser), MP_ROM_PTR(&audiofilters_phaser_type) }, + + // Enum-like Classes. + { MP_ROM_QSTR(MP_QSTR_DistortionMode), MP_ROM_PTR(&audiofilters_distortion_mode_type) }, +}; + +static MP_DEFINE_CONST_DICT(audiofilters_module_globals, audiofilters_module_globals_table); + +const mp_obj_module_t audiofilters_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audiofilters_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audiofilters, audiofilters_module); diff --git a/shared-bindings/audiofilters/__init__.h b/shared-bindings/audiofilters/__init__.h new file mode 100644 index 0000000000000..29d2f6726559b --- /dev/null +++ b/shared-bindings/audiofilters/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/audiofreeverb/Freeverb.c b/shared-bindings/audiofreeverb/Freeverb.c new file mode 100644 index 0000000000000..12eb7ef70ab79 --- /dev/null +++ b/shared-bindings/audiofreeverb/Freeverb.c @@ -0,0 +1,272 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/audiofreeverb/Freeverb.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/audiofreeverb/Freeverb.h" + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-module/synthio/block.h" + +//| class Freeverb: +//| """An Freeverb effect""" +//| +//| def __init__( +//| self, +//| roomsize: synthio.BlockInput = 0.5, +//| damp: synthio.BlockInput = 0.5, +//| mix: synthio.BlockInput = 0.5, +//| buffer_size: int = 512, +//| sample_rate: int = 8000, +//| bits_per_sample: int = 16, +//| samples_signed: bool = True, +//| channel_count: int = 1, +//| ) -> None: +//| """Create a Reverb effect simulating the audio taking place in a large room where you get echos +//| off of various surfaces at various times. The size of the room can be adjusted as well as how +//| much the higher frequencies get absorbed by the walls. +//| +//| The mix parameter allows you to change how much of the unchanged sample passes through to +//| the output to how much of the effect audio you hear as the output. +//| +//| :param synthio.BlockInput roomsize: The size of the room. 0.0 = smallest; 1.0 = largest. +//| :param synthio.BlockInput damp: How much the walls absorb. 0.0 = least; 1.0 = most. +//| :param synthio.BlockInput mix: The mix as a ratio of the sample (0.0) to the effect (1.0). +//| :param int buffer_size: The total size in bytes of each of the two playback buffers to use +//| :param int sample_rate: The sample rate to be used +//| :param int channel_count: The number of channels the source samples contain. 1 = mono; 2 = stereo. +//| :param int bits_per_sample: The bits per sample of the effect. Freeverb requires 16 bits. +//| :param bool samples_signed: Effect is signed (True) or unsigned (False). Freeverb requires signed (True). +//| +//| Playing adding reverb to a synth:: +//| +//| import time +//| import board +//| import audiobusio +//| import synthio +//| import audiofreeverb +//| +//| audio = audiobusio.I2SOut(bit_clock=board.GP20, word_select=board.GP21, data=board.GP22) +//| synth = synthio.Synthesizer(channel_count=1, sample_rate=44100) +//| reverb = audiofreeverb.Freeverb(roomsize=0.7, damp=0.3, buffer_size=1024, channel_count=1, sample_rate=44100, mix=0.7) +//| reverb.play(synth) +//| audio.play(reverb) +//| +//| note = synthio.Note(261) +//| while True: +//| synth.press(note) +//| time.sleep(0.55) +//| synth.release(note) +//| time.sleep(5)""" +//| ... +//| +static mp_obj_t audiofreeverb_freeverb_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_roomsize, ARG_damp, ARG_mix, ARG_buffer_size, ARG_sample_rate, ARG_bits_per_sample, ARG_samples_signed, ARG_channel_count, }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_roomsize, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_damp, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_mix, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_buffer_size, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 512} }, + { MP_QSTR_sample_rate, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 8000} }, + { MP_QSTR_bits_per_sample, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16} }, + { MP_QSTR_samples_signed, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + { MP_QSTR_channel_count, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1 } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t channel_count = mp_arg_validate_int_range(args[ARG_channel_count].u_int, 1, 2, MP_QSTR_channel_count); + mp_int_t sample_rate = mp_arg_validate_int_min(args[ARG_sample_rate].u_int, 1, MP_QSTR_sample_rate); + if (args[ARG_samples_signed].u_bool != true) { + mp_raise_ValueError(MP_ERROR_TEXT("samples_signed must be true")); + } + mp_int_t bits_per_sample = args[ARG_bits_per_sample].u_int; + if (bits_per_sample != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 16")); + } + + audiofreeverb_freeverb_obj_t *self = mp_obj_malloc(audiofreeverb_freeverb_obj_t, &audiofreeverb_freeverb_type); + common_hal_audiofreeverb_freeverb_construct(self, args[ARG_roomsize].u_obj, args[ARG_damp].u_obj, args[ARG_mix].u_obj, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the Freeverb.""" +//| ... +//| +static mp_obj_t audiofreeverb_freeverb_deinit(mp_obj_t self_in) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofreeverb_freeverb_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_deinit_obj, audiofreeverb_freeverb_deinit); + +static void check_for_deinit(audiofreeverb_freeverb_obj_t *self) { + audiosample_check_for_deinit(&self->base); +} + +//| def __enter__(self) -> Freeverb: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| roomsize: synthio.BlockInput +//| """Apparent size of the room 0.0-1.0""" +static mp_obj_t audiofreeverb_freeverb_obj_get_roomsize(mp_obj_t self_in) { + return common_hal_audiofreeverb_freeverb_get_roomsize(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_roomsize_obj, audiofreeverb_freeverb_obj_get_roomsize); + +static mp_obj_t audiofreeverb_freeverb_obj_set_roomsize(mp_obj_t self_in, mp_obj_t roomsize) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofreeverb_freeverb_set_roomsize(self, roomsize); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_roomsize_obj, audiofreeverb_freeverb_obj_set_roomsize); + +MP_PROPERTY_GETSET(audiofreeverb_freeverb_roomsize_obj, + (mp_obj_t)&audiofreeverb_freeverb_get_roomsize_obj, + (mp_obj_t)&audiofreeverb_freeverb_set_roomsize_obj); + +//| damp: synthio.BlockInput +//| """How much the high frequencies are dampened in the area. 0.0-1.0""" +static mp_obj_t audiofreeverb_freeverb_obj_get_damp(mp_obj_t self_in) { + return common_hal_audiofreeverb_freeverb_get_damp(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_damp_obj, audiofreeverb_freeverb_obj_get_damp); + +static mp_obj_t audiofreeverb_freeverb_obj_set_damp(mp_obj_t self_in, mp_obj_t damp) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofreeverb_freeverb_set_damp(self, damp); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_damp_obj, audiofreeverb_freeverb_obj_set_damp); + +MP_PROPERTY_GETSET(audiofreeverb_freeverb_damp_obj, + (mp_obj_t)&audiofreeverb_freeverb_get_damp_obj, + (mp_obj_t)&audiofreeverb_freeverb_set_damp_obj); + +//| mix: synthio.BlockInput +//| """The rate the reverb mix between 0 and 1 where 0 is only sample and 1 is all effect.""" +static mp_obj_t audiofreeverb_freeverb_obj_get_mix(mp_obj_t self_in) { + return common_hal_audiofreeverb_freeverb_get_mix(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_mix_obj, audiofreeverb_freeverb_obj_get_mix); + +static mp_obj_t audiofreeverb_freeverb_obj_set_mix(mp_obj_t self_in, mp_obj_t mix_in) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiofreeverb_freeverb_set_mix(self, mix_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiofreeverb_freeverb_set_mix_obj, audiofreeverb_freeverb_obj_set_mix); + +MP_PROPERTY_GETSET(audiofreeverb_freeverb_mix_obj, + (mp_obj_t)&audiofreeverb_freeverb_get_mix_obj, + (mp_obj_t)&audiofreeverb_freeverb_set_mix_obj); + +//| playing: bool +//| """True when the effect is playing a sample. (read-only)""" +//| +static mp_obj_t audiofreeverb_freeverb_obj_get_playing(mp_obj_t self_in) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_audiofreeverb_freeverb_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_get_playing_obj, audiofreeverb_freeverb_obj_get_playing); + +MP_PROPERTY_GETTER(audiofreeverb_freeverb_playing_obj, + (mp_obj_t)&audiofreeverb_freeverb_get_playing_obj); + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> Freeverb: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| The sample must match the encoding settings given in the constructor. +//| +//| :return: The effect object itself. Can be used for chaining, ie: +//| ``audio.play(effect.play(sample))``. +//| :rtype: Freeverb""" +//| ... +//| +static mp_obj_t audiofreeverb_freeverb_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_audiofreeverb_freeverb_play(self, sample, args[ARG_loop].u_bool); + + return MP_OBJ_FROM_PTR(self); +} +MP_DEFINE_CONST_FUN_OBJ_KW(audiofreeverb_freeverb_play_obj, 1, audiofreeverb_freeverb_obj_play); + +//| def stop(self) -> None: +//| """Stops playback of the sample. The reverb continues playing.""" +//| ... +//| +//| +static mp_obj_t audiofreeverb_freeverb_obj_stop(mp_obj_t self_in) { + audiofreeverb_freeverb_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_audiofreeverb_freeverb_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiofreeverb_freeverb_stop_obj, audiofreeverb_freeverb_obj_stop); + +static const mp_rom_map_elem_t audiofreeverb_freeverb_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiofreeverb_freeverb_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiofreeverb_freeverb_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiofreeverb_freeverb_stop_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiofreeverb_freeverb_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_roomsize), MP_ROM_PTR(&audiofreeverb_freeverb_roomsize_obj) }, + { MP_ROM_QSTR(MP_QSTR_damp), MP_ROM_PTR(&audiofreeverb_freeverb_damp_obj) }, + { MP_ROM_QSTR(MP_QSTR_mix), MP_ROM_PTR(&audiofreeverb_freeverb_mix_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiofreeverb_freeverb_locals_dict, audiofreeverb_freeverb_locals_dict_table); + +static const audiosample_p_t audiofreeverb_freeverb_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiofreeverb_freeverb_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiofreeverb_freeverb_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiofreeverb_freeverb_type, + MP_QSTR_freeverb, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiofreeverb_freeverb_make_new, + locals_dict, &audiofreeverb_freeverb_locals_dict, + protocol, &audiofreeverb_freeverb_proto + ); diff --git a/shared-bindings/audiofreeverb/Freeverb.h b/shared-bindings/audiofreeverb/Freeverb.h new file mode 100644 index 0000000000000..bde6cfffda7d2 --- /dev/null +++ b/shared-bindings/audiofreeverb/Freeverb.h @@ -0,0 +1,32 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiofreeverb/Freeverb.h" + +extern const mp_obj_type_t audiofreeverb_freeverb_type; + +void common_hal_audiofreeverb_freeverb_construct(audiofreeverb_freeverb_obj_t *self, + mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate); + +void common_hal_audiofreeverb_freeverb_deinit(audiofreeverb_freeverb_obj_t *self); +bool common_hal_audiofreeverb_freeverb_deinited(audiofreeverb_freeverb_obj_t *self); + +mp_obj_t common_hal_audiofreeverb_freeverb_get_roomsize(audiofreeverb_freeverb_obj_t *self); +void common_hal_audiofreeverb_freeverb_set_roomsize(audiofreeverb_freeverb_obj_t *self, mp_obj_t feedback); + +mp_obj_t common_hal_audiofreeverb_freeverb_get_damp(audiofreeverb_freeverb_obj_t *self); +void common_hal_audiofreeverb_freeverb_set_damp(audiofreeverb_freeverb_obj_t *self, mp_obj_t damp); + +mp_obj_t common_hal_audiofreeverb_freeverb_get_mix(audiofreeverb_freeverb_obj_t *self); +void common_hal_audiofreeverb_freeverb_set_mix(audiofreeverb_freeverb_obj_t *self, mp_obj_t mix); + +bool common_hal_audiofreeverb_freeverb_get_playing(audiofreeverb_freeverb_obj_t *self); +void common_hal_audiofreeverb_freeverb_play(audiofreeverb_freeverb_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_audiofreeverb_freeverb_stop(audiofreeverb_freeverb_obj_t *self); diff --git a/shared-bindings/audiofreeverb/__init__.c b/shared-bindings/audiofreeverb/__init__.c new file mode 100644 index 0000000000000..cb8c979c8cfec --- /dev/null +++ b/shared-bindings/audiofreeverb/__init__.c @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/audiofreeverb/__init__.h" +#include "shared-bindings/audiofreeverb/Freeverb.h" + + +//| """Support for audio freeverb effect +//| +//| The `audiofreeverb` module contains classes to provide access to audio freeverb effects. +//| +//| """ + +static const mp_rom_map_elem_t audiofreeverb_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiofreeverb) }, + { MP_ROM_QSTR(MP_QSTR_Freeverb), MP_ROM_PTR(&audiofreeverb_freeverb_type) }, +}; + +static MP_DEFINE_CONST_DICT(audiofreeverb_module_globals, audiofreeverb_module_globals_table); + +const mp_obj_module_t audiofreeverb_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audiofreeverb_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audiofreeverb, audiofreeverb_module); diff --git a/shared-bindings/audiofreeverb/__init__.h b/shared-bindings/audiofreeverb/__init__.h new file mode 100644 index 0000000000000..66463561f5443 --- /dev/null +++ b/shared-bindings/audiofreeverb/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/audioio/AudioOut.c b/shared-bindings/audioio/AudioOut.c index ceeaf1f399077..8ea068ceb8f3a 100644 --- a/shared-bindings/audioio/AudioOut.c +++ b/shared-bindings/audioio/AudioOut.c @@ -23,16 +23,21 @@ //| left_channel: microcontroller.Pin, //| *, //| right_channel: Optional[microcontroller.Pin] = None, -//| quiescent_value: int = 0x8000 +//| quiescent_value: int = 0x8000, //| ) -> None: //| """Create a AudioOut object associated with the given pin(s). This allows you to //| play audio signals out on the given pin(s). //| -//| :param ~microcontroller.Pin left_channel: The pin to output the left channel to -//| :param ~microcontroller.Pin right_channel: The pin to output the right channel to +//| :param ~microcontroller.Pin left_channel: Output left channel data to this pin +//| :param ~microcontroller.Pin right_channel: Output right channel data to this pin. May be ``None``. //| :param int quiescent_value: The output value when no signal is present. Samples should start //| and end with this value to prevent audible popping. //| +//| .. note:: On ESP32 and ESP32-S2, the DAC channels are usually designated +//| as ``DAC_1`` (right stereo channel) and DAC_2 (left stereo channel). +//| These pins are sometimes labelled as ``A0`` and ``A1``, but they may be assigned +//| in either order. Check your board's pinout to verify which pin is which channel. +//| //| Simple 8ksps 440 Hz sin wave:: //| //| import audiocore @@ -74,6 +79,7 @@ //| pass //| print("stopped")""" //| ... +//| static mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value }; static const mp_arg_t allowed_args[] = { @@ -89,10 +95,18 @@ static mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar const mcu_pin_obj_t *right_channel_pin = validate_obj_is_free_pin_or_none(args[ARG_right_channel].u_obj, MP_QSTR_right_channel); + // Can't use the same pin for both left and right channels. + if (left_channel_pin == right_channel_pin) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q and %q must be different"), + MP_QSTR_left_channel, MP_QSTR_right_channel); + } + // create AudioOut object from the given pin - audioio_audioout_obj_t *self = m_new_obj_with_finaliser(audioio_audioout_obj_t); - self->base.type = &audioio_audioout_type; - common_hal_audioio_audioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); + audioio_audioout_obj_t *self = mp_obj_malloc_with_finaliser(audioio_audioout_obj_t, &audioio_audioout_type); + common_hal_audioio_audioout_construct(self, + left_channel_pin, + right_channel_pin, + args[ARG_quiescent_value].u_int); return MP_OBJ_FROM_PTR(self); } @@ -100,6 +114,7 @@ static mp_obj_t audioio_audioout_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the AudioOut and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audioio_audioout_deinit(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audioio_audioout_deinit(self); @@ -115,19 +130,15 @@ static void check_for_deinit(audioio_audioout_obj_t *self) { //| def __enter__(self) -> AudioOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audioio_audioout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audioio_audioout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4, audioio_audioout_obj___exit__); - +//| +// Provided by context manager helper. //| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: //| """Plays the sample once when loop=False and continuously when loop=True. @@ -139,6 +150,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audioio_audioout___exit___obj, 4, 4, //| resolution will use the highest order bits to output. For example, the SAMD21 has a 10 bit //| DAC that ignores the lowest 6 bits when playing 16 bit samples.""" //| ... +//| static mp_obj_t audioio_audioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -160,6 +172,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audioio_audioout_play_obj, 1, audioio_audioout_obj_pl //| def stop(self) -> None: //| """Stops playback and resets to the start of the sample.""" //| ... +//| static mp_obj_t audioio_audioout_obj_stop(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -170,6 +183,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_stop_obj, audioio_audioout_obj_stop); //| playing: bool //| """True when an audio sample is being output even if `paused`. (read-only)""" +//| static mp_obj_t audioio_audioout_obj_get_playing(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -183,6 +197,7 @@ MP_PROPERTY_GETTER(audioio_audioout_playing_obj, //| def pause(self) -> None: //| """Stops playback temporarily while remembering the position. Use `resume` to resume playback.""" //| ... +//| static mp_obj_t audioio_audioout_obj_pause(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -198,6 +213,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_pause_obj, audioio_audioout_obj_pause //| def resume(self) -> None: //| """Resumes sample playback after :py:func:`pause`.""" //| ... +//| static mp_obj_t audioio_audioout_obj_resume(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -213,6 +229,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audioio_audioout_resume_obj, audioio_audioout_obj_resu //| paused: bool //| """True when playback is paused. (read-only)""" //| +//| static mp_obj_t audioio_audioout_obj_get_paused(mp_obj_t self_in) { audioio_audioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -228,7 +245,7 @@ static const mp_rom_map_elem_t audioio_audioout_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audioio_audioout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audioio_audioout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audioio_audioout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audioio_audioout_play_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audioio_audioout_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audioio_audioout_pause_obj) }, diff --git a/shared-bindings/audioio/__init__.c b/shared-bindings/audioio/__init__.c index ac8a85f1d65ac..88109d5d52125 100644 --- a/shared-bindings/audioio/__init__.c +++ b/shared-bindings/audioio/__init__.c @@ -27,11 +27,7 @@ //| `_. //| //| Since CircuitPython 5, `RawSample` and `WaveFile` are moved -//| to :mod:`audiocore`, and `Mixer` is moved to :mod:`audiomixer`. -//| -//| For compatibility with CircuitPython 4.x, some builds allow the items in -//| `audiocore` to be imported from `audioio`. This will be removed for all -//| boards in a future build of CircuitPython.""" +//| to :mod:`audiocore`, and `Mixer` is moved to :mod:`audiomixer`.""" static const mp_rom_map_elem_t audioio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audioio) }, diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c index 149e98584db2c..516d079cd2a09 100644 --- a/shared-bindings/audiomixer/Mixer.c +++ b/shared-bindings/audiomixer/Mixer.c @@ -5,6 +5,7 @@ // SPDX-License-Identifier: MIT #include "shared-bindings/audiomixer/Mixer.h" #include "shared-bindings/audiomixer/MixerVoice.h" +#include "shared-bindings/audiocore/__init__.h" #include "shared-module/audiomixer/MixerVoice.h" #include @@ -62,6 +63,7 @@ //| time.sleep(1) //| print("stopped")""" //| ... +//| static mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_voice_count, ARG_buffer_size, ARG_channel_count, ARG_bits_per_sample, ARG_samples_signed, ARG_sample_rate }; static const mp_arg_t allowed_args[] = { @@ -83,7 +85,7 @@ static mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_ar mp_raise_ValueError(MP_ERROR_TEXT("bits_per_sample must be 8 or 16")); } audiomixer_mixer_obj_t *self = - mp_obj_malloc_var(audiomixer_mixer_obj_t, mp_obj_t, voice_count, &audiomixer_mixer_type); + mp_obj_malloc_var(audiomixer_mixer_obj_t, voice, mp_obj_t, voice_count, &audiomixer_mixer_type); common_hal_audiomixer_mixer_construct(self, voice_count, args[ARG_buffer_size].u_int, bits_per_sample, args[ARG_samples_signed].u_bool, channel_count, sample_rate); for (int v = 0; v < voice_count; v++) { @@ -98,6 +100,7 @@ static mp_obj_t audiomixer_mixer_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the Mixer and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audiomixer_mixer_deinit(mp_obj_t self_in) { audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audiomixer_mixer_deinit(self); @@ -106,26 +109,21 @@ static mp_obj_t audiomixer_mixer_deinit(mp_obj_t self_in) { static MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_deinit_obj, audiomixer_mixer_deinit); static void check_for_deinit(audiomixer_mixer_obj_t *self) { - if (common_hal_audiomixer_mixer_deinited(self)) { - raise_deinited_error(); - } + audiosample_check_for_deinit(&self->base); } //| def __enter__(self) -> Mixer: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audiomixer_mixer_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audiomixer_mixer_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomixer_mixer___exit___obj, 4, 4, audiomixer_mixer_obj___exit__); +//| +// Provided by context manager helper. //| playing: bool //| """True when any voice is being output. (read-only)""" @@ -141,15 +139,6 @@ MP_PROPERTY_GETTER(audiomixer_mixer_playing_obj, //| sample_rate: int //| """32 bit value that dictates how quickly samples are played in Hertz (cycles per second).""" -static mp_obj_t audiomixer_mixer_obj_get_sample_rate(mp_obj_t self_in) { - audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audiomixer_mixer_get_sample_rate(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixer_get_sample_rate_obj, audiomixer_mixer_obj_get_sample_rate); - -MP_PROPERTY_GETTER(audiomixer_mixer_sample_rate_obj, - (mp_obj_t)&audiomixer_mixer_get_sample_rate_obj); //| voice: Tuple[MixerVoice, ...] //| """A tuple of the mixer's `audiomixer.MixerVoice` object(s). @@ -158,6 +147,7 @@ MP_PROPERTY_GETTER(audiomixer_mixer_sample_rate_obj, //| //| >>> mixer.voice //| (,)""" +//| static mp_obj_t audiomixer_mixer_obj_get_voice(mp_obj_t self_in) { audiomixer_mixer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -170,14 +160,19 @@ MP_PROPERTY_GETTER(audiomixer_mixer_voice_obj, //| def play( //| self, sample: circuitpython_typing.AudioSample, *, voice: int = 0, loop: bool = False -//| ) -> None: +//| ) -> Mixer: //| """Plays the sample once when loop=False and continuously when loop=True. //| Does not block. Use `playing` to block. //| //| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. //| -//| The sample must match the Mixer's encoding settings given in the constructor.""" +//| The sample must match the Mixer's encoding settings given in the constructor. +//| +//| :return: The mixer object itself. Can be used for chaining, ie: +//| ``audio.play(mixer.play(sample))``. +//| :rtype: Chorus""" //| ... +//| static mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_voice, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -198,7 +193,7 @@ static mp_obj_t audiomixer_mixer_obj_play(size_t n_args, const mp_obj_t *pos_arg mp_obj_t sample = args[ARG_sample].u_obj; common_hal_audiomixer_mixervoice_play(voice, sample, args[ARG_loop].u_bool); - return mp_const_none; + return MP_OBJ_FROM_PTR(self); } MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_play_obj, 1, audiomixer_mixer_obj_play); @@ -206,6 +201,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixer_play_obj, 1, audiomixer_mixer_obj_pl //| """Stops playback of the sample on the given voice.""" //| ... //| +//| static mp_obj_t audiomixer_mixer_obj_stop_voice(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_voice }; static const mp_arg_t allowed_args[] = { @@ -231,25 +227,21 @@ static const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiomixer_mixer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiomixer_mixer___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiomixer_mixer_play_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_voice), MP_ROM_PTR(&audiomixer_mixer_stop_voice_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixer_playing_obj) }, - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomixer_mixer_sample_rate_obj) }, - { MP_ROM_QSTR(MP_QSTR_voice), MP_ROM_PTR(&audiomixer_mixer_voice_obj) } + { MP_ROM_QSTR(MP_QSTR_voice), MP_ROM_PTR(&audiomixer_mixer_voice_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table); static const audiosample_p_t audiomixer_mixer_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomixer_mixer_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomixer_mixer_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_audiomixer_mixer_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)audiomixer_mixer_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)audiomixer_mixer_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure, }; MP_DEFINE_CONST_OBJ_TYPE( diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h index 29577b0a61b86..3e6e5890f44e0 100644 --- a/shared-bindings/audiomixer/Mixer.h +++ b/shared-bindings/audiomixer/Mixer.h @@ -20,9 +20,5 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self, uint32_t sample_rate); void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self); -bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self); bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self); -uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t *self); -uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t *self); -uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t *self); diff --git a/shared-bindings/audiomixer/MixerVoice.c b/shared-bindings/audiomixer/MixerVoice.c index eed877bc789b5..4957fab388460 100644 --- a/shared-bindings/audiomixer/MixerVoice.c +++ b/shared-bindings/audiomixer/MixerVoice.c @@ -13,6 +13,9 @@ #include "py/objproperty.h" #include "py/runtime.h" #include "shared-bindings/util.h" +#if CIRCUITPY_SYNTHIO +#include "shared-module/synthio/block.h" +#endif //| class MixerVoice: //| """Voice objects used with Mixer @@ -22,11 +25,12 @@ //| def __init__(self) -> None: //| """MixerVoice instance object(s) created by `audiomixer.Mixer`.""" //| ... +//| // TODO: support mono or stereo voices static mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 0, 0, false); - audiomixer_mixervoice_obj_t *self = mp_obj_malloc(audiomixer_mixervoice_obj_t, &audiomixer_mixervoice_type); + audiomixer_mixervoice_obj_t *self = mp_obj_malloc(audiomixer_mixervoice_obj_t, &audiomixer_mixervoice_type); common_hal_audiomixer_mixervoice_construct(self); return MP_OBJ_FROM_PTR(self); @@ -41,6 +45,7 @@ static mp_obj_t audiomixer_mixervoice_make_new(const mp_obj_type_t *type, size_t //| The sample must match the `audiomixer.Mixer`'s encoding settings given in the constructor. //| """ //| ... +//| static mp_obj_t audiomixer_mixervoice_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -60,6 +65,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_play_obj, 1, audiomixer_mixervo //| def stop(self) -> None: //| """Stops playback of the sample on this voice.""" //| ... +//| static mp_obj_t audiomixer_mixervoice_obj_stop(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_voice }; static const mp_arg_t allowed_args[] = { @@ -75,41 +81,87 @@ static mp_obj_t audiomixer_mixervoice_obj_stop(size_t n_args, const mp_obj_t *po } MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_stop_obj, 1, audiomixer_mixervoice_obj_stop); -//| level: float -//| """The volume level of a voice, as a floating point number between 0 and 1.""" +//| def end(self) -> None: +//| """ Sets looping to False if sample is playing. This allows the looped +//| sample to complete its current playback and end further looping """ +//| ... +//| +static mp_obj_t audiomixer_mixervoice_obj_end(mp_obj_t self_in) { + audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiomixer_mixervoice_end(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_end_obj, audiomixer_mixervoice_obj_end); + + +//| level: synthio.BlockInput +//| """The volume level of a voice, as a floating point number between 0 and 1. If your board +//| does not support synthio, this property will only accept a float value. +//| """ static mp_obj_t audiomixer_mixervoice_obj_get_level(mp_obj_t self_in) { - return mp_obj_new_float(common_hal_audiomixer_mixervoice_get_level(self_in)); + return common_hal_audiomixer_mixervoice_get_level(self_in); } MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_level_obj, audiomixer_mixervoice_obj_get_level); -static mp_obj_t audiomixer_mixervoice_obj_set_level(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_level }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_level, MP_ARG_OBJ | MP_ARG_REQUIRED, {} }, - }; - audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); +static mp_obj_t audiomixer_mixervoice_obj_set_level(mp_obj_t self_in, mp_obj_t level_in) { + audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiomixer_mixervoice_set_level(self, level_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiomixer_mixervoice_set_level_obj, audiomixer_mixervoice_obj_set_level); + +MP_PROPERTY_GETSET(audiomixer_mixervoice_level_obj, + (mp_obj_t)&audiomixer_mixervoice_get_level_obj, + (mp_obj_t)&audiomixer_mixervoice_set_level_obj); + +//| panning: synthio.BlockInput +//| """Defines the channel(s) in which the voice appears, as a floating point number between +//| -1 and 1. If your board does not support synthio, this property will only accept a float +//| value. This property is ignored if ``audiomixer.Mixer.channel_count=1``. +//| +//| -1 is left channel only, 0 is both channels, and 1 is right channel. For fractional values, +//| the note plays at full amplitude in one channel and partial amplitude in the other channel. +//| For instance -.5 plays at full amplitude in the left channel and 1/2 amplitude in the right +//| channel.""" +static mp_obj_t audiomixer_mixervoice_obj_get_panning(mp_obj_t self_in) { + return common_hal_audiomixer_mixervoice_get_panning(self_in); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_panning_obj, audiomixer_mixervoice_obj_get_panning); - mp_float_t level = mp_obj_get_float(args[ARG_level].u_obj); +static mp_obj_t audiomixer_mixervoice_obj_set_panning(mp_obj_t self_in, mp_obj_t panning_in) { + audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiomixer_mixervoice_set_panning(self, panning_in); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiomixer_mixervoice_set_panning_obj, audiomixer_mixervoice_obj_set_panning); - if (level > 1 || level < 0) { - mp_raise_ValueError(MP_ERROR_TEXT("level must be between 0 and 1")); - } +MP_PROPERTY_GETSET(audiomixer_mixervoice_panning_obj, + (mp_obj_t)&audiomixer_mixervoice_get_panning_obj, + (mp_obj_t)&audiomixer_mixervoice_set_panning_obj); - common_hal_audiomixer_mixervoice_set_level(self, level); +//| loop: bool +//| """Get or set the loop status of the currently playing sample.""" +static mp_obj_t audiomixer_mixervoice_obj_get_loop(mp_obj_t self_in) { + return mp_obj_new_bool(common_hal_audiomixer_mixervoice_get_loop(self_in)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiomixer_mixervoice_get_loop_obj, audiomixer_mixervoice_obj_get_loop); +static mp_obj_t audiomixer_mixervoice_obj_set_loop(mp_obj_t self_in, mp_obj_t loop_in) { + audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool loop = mp_obj_is_true(loop_in); + common_hal_audiomixer_mixervoice_set_loop(self, loop); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_KW(audiomixer_mixervoice_set_level_obj, 1, audiomixer_mixervoice_obj_set_level); +MP_DEFINE_CONST_FUN_OBJ_2(audiomixer_mixervoice_set_loop_obj, audiomixer_mixervoice_obj_set_loop); -MP_PROPERTY_GETSET(audiomixer_mixervoice_level_obj, - (mp_obj_t)&audiomixer_mixervoice_get_level_obj, - (mp_obj_t)&audiomixer_mixervoice_set_level_obj); +MP_PROPERTY_GETSET(audiomixer_mixervoice_loop_obj, + (mp_obj_t)&audiomixer_mixervoice_get_loop_obj, + (mp_obj_t)&audiomixer_mixervoice_set_loop_obj); //| playing: bool //| """True when this voice is being output. (read-only)""" //| +//| static mp_obj_t audiomixer_mixervoice_obj_get_playing(mp_obj_t self_in) { audiomixer_mixervoice_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -126,10 +178,13 @@ static const mp_rom_map_elem_t audiomixer_mixervoice_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiomixer_mixervoice_play_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiomixer_mixervoice_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_end), MP_ROM_PTR(&audiomixer_mixervoice_end_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&audiomixer_mixervoice_playing_obj) }, { MP_ROM_QSTR(MP_QSTR_level), MP_ROM_PTR(&audiomixer_mixervoice_level_obj) }, + { MP_ROM_QSTR(MP_QSTR_panning), MP_ROM_PTR(&audiomixer_mixervoice_panning_obj) }, + { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&audiomixer_mixervoice_loop_obj) }, }; static MP_DEFINE_CONST_DICT(audiomixer_mixervoice_locals_dict, audiomixer_mixervoice_locals_dict_table); diff --git a/shared-bindings/audiomixer/MixerVoice.h b/shared-bindings/audiomixer/MixerVoice.h index 1f5311edf41e2..d60820f7f5734 100644 --- a/shared-bindings/audiomixer/MixerVoice.h +++ b/shared-bindings/audiomixer/MixerVoice.h @@ -15,7 +15,13 @@ void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *sel void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t *self, audiomixer_mixer_obj_t *parent); void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample, bool loop); void common_hal_audiomixer_mixervoice_stop(audiomixer_mixervoice_obj_t *self); -mp_float_t common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t *self); -void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *self, mp_float_t gain); +void common_hal_audiomixer_mixervoice_end(audiomixer_mixervoice_obj_t *self); +mp_obj_t common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t *self); +void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *self, mp_obj_t gain); +mp_obj_t common_hal_audiomixer_mixervoice_get_panning(audiomixer_mixervoice_obj_t *self); +void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *self, mp_obj_t value); bool common_hal_audiomixer_mixervoice_get_playing(audiomixer_mixervoice_obj_t *self); + +void common_hal_audiomixer_mixervoice_set_loop(audiomixer_mixervoice_obj_t *self, bool loop); +bool common_hal_audiomixer_mixervoice_get_loop(audiomixer_mixervoice_obj_t *self); diff --git a/shared-bindings/audiomp3/MP3Decoder.c b/shared-bindings/audiomp3/MP3Decoder.c index ff715720d0282..433b308c156c8 100644 --- a/shared-bindings/audiomp3/MP3Decoder.c +++ b/shared-bindings/audiomp3/MP3Decoder.c @@ -8,6 +8,7 @@ #include #include "shared/runtime/context_manager_helpers.h" +#include "shared-bindings/audiocore/__init__.h" #include "py/objproperty.h" #include "py/runtime.h" #include "py/stream.h" @@ -80,6 +81,7 @@ //| that the socket closes when the stream ends. //| """ //| ... +//| static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 2, false); @@ -89,9 +91,6 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar stream = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), stream, MP_ROM_QSTR(MP_QSTR_rb)); } - audiomp3_mp3file_obj_t *self = m_new_obj_with_finaliser(audiomp3_mp3file_obj_t); - self->base.type = &audiomp3_mp3file_type; - const mp_stream_p_t *stream_p = mp_get_stream_raise(stream, MP_STREAM_OP_READ); if (stream_p->is_text) { @@ -105,6 +104,8 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar buffer = bufinfo.buf; buffer_size = bufinfo.len; } + + audiomp3_mp3file_obj_t *self = mp_obj_malloc_with_finaliser(audiomp3_mp3file_obj_t, &audiomp3_mp3file_type); common_hal_audiomp3_mp3file_construct(self, stream, buffer, buffer_size); return MP_OBJ_FROM_PTR(self); @@ -113,6 +114,7 @@ static mp_obj_t audiomp3_mp3file_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the MP3 and releases all memory resources for reuse.""" //| ... +//| static mp_obj_t audiomp3_mp3file_deinit(mp_obj_t self_in) { audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audiomp3_mp3file_deinit(self); @@ -121,29 +123,25 @@ static mp_obj_t audiomp3_mp3file_deinit(mp_obj_t self_in) { static MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_deinit_obj, audiomp3_mp3file_deinit); static void check_for_deinit(audiomp3_mp3file_obj_t *self) { - if (common_hal_audiomp3_mp3file_deinited(self)) { - raise_deinited_error(); - } + audiosample_check_for_deinit(&self->base); } //| def __enter__(self) -> MP3Decoder: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audiomp3_mp3file_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audiomp3_mp3file_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiomp3_mp3file___exit___obj, 4, 4, audiomp3_mp3file_obj___exit__); +//| +// Provided by context manager helper. //| file: typing.BinaryIO //| """File to play back.""" +//| static mp_obj_t audiomp3_mp3file_obj_get_file(mp_obj_t self_in) { audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -167,6 +165,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_file_obj, audiomp3_mp3file_obj_se //| def open(self, filepath: str) -> None: //| """Takes in the name of a mp3 file, opens it, and replaces the old playback file.""" //| ... +//| static mp_obj_t audiomp3_mp3file_obj_open(mp_obj_t self_in, mp_obj_t path) { audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -188,48 +187,12 @@ MP_PROPERTY_GETSET(audiomp3_mp3file_file_obj, //| """32 bit value that dictates how quickly samples are loaded into the DAC //| in Hertz (cycles per second). When the sample is looped, this can change //| the pitch output without changing the underlying sample.""" -static mp_obj_t audiomp3_mp3file_obj_get_sample_rate(mp_obj_t self_in) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_sample_rate(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_sample_rate_obj, audiomp3_mp3file_obj_get_sample_rate); - -static mp_obj_t audiomp3_mp3file_obj_set_sample_rate(mp_obj_t self_in, mp_obj_t sample_rate) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - common_hal_audiomp3_mp3file_set_sample_rate(self, mp_obj_get_int(sample_rate)); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(audiomp3_mp3file_set_sample_rate_obj, audiomp3_mp3file_obj_set_sample_rate); - -MP_PROPERTY_GETSET(audiomp3_mp3file_sample_rate_obj, - (mp_obj_t)&audiomp3_mp3file_get_sample_rate_obj, - (mp_obj_t)&audiomp3_mp3file_set_sample_rate_obj); //| bits_per_sample: int //| """Bits per sample. (read only)""" -static mp_obj_t audiomp3_mp3file_obj_get_bits_per_sample(mp_obj_t self_in) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_bits_per_sample(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_bits_per_sample_obj, audiomp3_mp3file_obj_get_bits_per_sample); - -MP_PROPERTY_GETTER(audiomp3_mp3file_bits_per_sample_obj, - (mp_obj_t)&audiomp3_mp3file_get_bits_per_sample_obj); //| channel_count: int //| """Number of audio channels. (read only)""" -static mp_obj_t audiomp3_mp3file_obj_get_channel_count(mp_obj_t self_in) { - audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_audiomp3_mp3file_get_channel_count(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(audiomp3_mp3file_get_channel_count_obj, audiomp3_mp3file_obj_get_channel_count); - -MP_PROPERTY_GETTER(audiomp3_mp3file_channel_count_obj, - (mp_obj_t)&audiomp3_mp3file_get_channel_count_obj); //| rms_level: float //| """The RMS audio level of a recently played moment of audio. (read only)""" @@ -246,6 +209,7 @@ MP_PROPERTY_GETTER(audiomp3_mp3file_rms_level_obj, //| samples_decoded: int //| """The number of audio samples decoded from the current file. (read only)""" //| +//| static mp_obj_t audiomp3_mp3file_obj_get_samples_decoded(mp_obj_t self_in) { audiomp3_mp3file_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -262,26 +226,20 @@ static const mp_rom_map_elem_t audiomp3_mp3file_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiomp3_mp3file_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audiomp3_mp3file_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiomp3_mp3file___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_file), MP_ROM_PTR(&audiomp3_mp3file_file_obj) }, - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&audiomp3_mp3file_sample_rate_obj) }, - { MP_ROM_QSTR(MP_QSTR_bits_per_sample), MP_ROM_PTR(&audiomp3_mp3file_bits_per_sample_obj) }, - { MP_ROM_QSTR(MP_QSTR_channel_count), MP_ROM_PTR(&audiomp3_mp3file_channel_count_obj) }, { MP_ROM_QSTR(MP_QSTR_rms_level), MP_ROM_PTR(&audiomp3_mp3file_rms_level_obj) }, { MP_ROM_QSTR(MP_QSTR_samples_decoded), MP_ROM_PTR(&audiomp3_mp3file_samples_decoded_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(audiomp3_mp3file_locals_dict, audiomp3_mp3file_locals_dict_table); static const audiosample_p_t audiomp3_mp3file_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomp3_mp3file_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomp3_mp3file_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_audiomp3_mp3file_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)audiomp3_mp3file_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)audiomp3_mp3file_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomp3_mp3file_get_buffer_structure, }; MP_DEFINE_CONST_OBJ_TYPE( diff --git a/shared-bindings/audiomp3/MP3Decoder.h b/shared-bindings/audiomp3/MP3Decoder.h index 4381430c228a1..0b485b4bca17e 100644 --- a/shared-bindings/audiomp3/MP3Decoder.h +++ b/shared-bindings/audiomp3/MP3Decoder.h @@ -19,10 +19,5 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t stream); void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self); -bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self); -uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self); -void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, uint32_t sample_rate); -uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self); -uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self); float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self); uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self); diff --git a/shared-bindings/audiopwmio/PWMAudioOut.c b/shared-bindings/audiopwmio/PWMAudioOut.c index 3b75df16ec457..5b8d071924b83 100644 --- a/shared-bindings/audiopwmio/PWMAudioOut.c +++ b/shared-bindings/audiopwmio/PWMAudioOut.c @@ -23,7 +23,7 @@ //| left_channel: microcontroller.Pin, //| *, //| right_channel: Optional[microcontroller.Pin] = None, -//| quiescent_value: int = 0x8000 +//| quiescent_value: int = 0x8000, //| ) -> None: //| """Create a PWMAudioOut object associated with the given pin(s). This allows you to //| play audio signals out on the given pin(s). In contrast to mod:`audioio`, @@ -81,6 +81,7 @@ //| pass //| print("stopped")""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_left_channel, ARG_right_channel, ARG_quiescent_value }; static const mp_arg_t allowed_args[] = { @@ -99,9 +100,10 @@ static mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_ // create AudioOut object from the given pin // The object is created with a finaliser as some ports use these (rather than 'reset' functions) // to ensure resources are collected at interpreter shutdown. - audiopwmio_pwmaudioout_obj_t *self = m_new_obj_with_finaliser(audiopwmio_pwmaudioout_obj_t); - self->base.type = &audiopwmio_pwmaudioout_type; - common_hal_audiopwmio_pwmaudioout_construct(self, left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); + audiopwmio_pwmaudioout_obj_t *self = + mp_obj_malloc_with_finaliser(audiopwmio_pwmaudioout_obj_t, &audiopwmio_pwmaudioout_type); + common_hal_audiopwmio_pwmaudioout_construct(self, + left_channel_pin, right_channel_pin, args[ARG_quiescent_value].u_int); return MP_OBJ_FROM_PTR(self); } @@ -109,6 +111,7 @@ static mp_obj_t audiopwmio_pwmaudioout_make_new(const mp_obj_type_t *type, size_ //| def deinit(self) -> None: //| """Deinitialises the PWMAudioOut and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_deinit(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_audiopwmio_pwmaudioout_deinit(self); @@ -124,18 +127,15 @@ static void check_for_deinit(audiopwmio_pwmaudioout_obj_t *self) { //| def __enter__(self) -> PWMAudioOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t audiopwmio_pwmaudioout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_audiopwmio_pwmaudioout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, 4, 4, audiopwmio_pwmaudioout_obj___exit__); +//| +// Provided by context manager helper. //| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: @@ -147,6 +147,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiopwmio_pwmaudioout___exit___obj, //| The sample itself should consist of 16 bit samples. Microcontrollers with a lower output //| resolution will use the highest order bits to output.""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sample, ARG_loop }; static const mp_arg_t allowed_args[] = { @@ -168,6 +169,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(audiopwmio_pwmaudioout_play_obj, 1, audiopwmio_pwmaud //| def stop(self) -> None: //| """Stops playback and resets to the start of the sample.""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_obj_stop(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -178,6 +180,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_stop_obj, audiopwmio_pwmaudioou //| playing: bool //| """True when an audio sample is being output even if `paused`. (read-only)""" +//| static mp_obj_t audiopwmio_pwmaudioout_obj_get_playing(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -191,6 +194,7 @@ MP_PROPERTY_GETTER(audiopwmio_pwmaudioout_playing_obj, //| def pause(self) -> None: //| """Stops playback temporarily while remembering the position. Use `resume` to resume playback.""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_obj_pause(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -206,6 +210,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_pause_obj, audiopwmio_pwmaudioo //| def resume(self) -> None: //| """Resumes sample playback after :py:func:`pause`.""" //| ... +//| static mp_obj_t audiopwmio_pwmaudioout_obj_resume(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -221,6 +226,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(audiopwmio_pwmaudioout_resume_obj, audiopwmio_pwmaudio //| paused: bool //| """True when playback is paused. (read-only)""" //| +//| static mp_obj_t audiopwmio_pwmaudioout_obj_get_paused(mp_obj_t self_in) { audiopwmio_pwmaudioout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -236,7 +242,7 @@ static const mp_rom_map_elem_t audiopwmio_pwmaudioout_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiopwmio_pwmaudioout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&audiopwmio_pwmaudioout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&audiopwmio_pwmaudioout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&audiopwmio_pwmaudioout_play_obj) }, { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&audiopwmio_pwmaudioout_stop_obj) }, { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&audiopwmio_pwmaudioout_pause_obj) }, diff --git a/shared-bindings/audiospeed/SpeedChanger.c b/shared-bindings/audiospeed/SpeedChanger.c new file mode 100644 index 0000000000000..34efa1516b035 --- /dev/null +++ b/shared-bindings/audiospeed/SpeedChanger.c @@ -0,0 +1,138 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/audiospeed/SpeedChanger.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-bindings/util.h" +#include "shared-module/audiospeed/SpeedChanger.h" + +// Convert a Python float to 16.16 fixed-point rate +static uint32_t rate_to_fp(mp_obj_t rate_obj) { + mp_float_t rate = mp_arg_validate_obj_float_range(rate_obj, 0.001, 1000.0, MP_QSTR_rate); + return (uint32_t)(rate * (1 << 16)); +} + +// Convert 16.16 fixed-point rate to Python float +static mp_obj_t fp_to_rate(uint32_t rate_fp) { + return mp_obj_new_float((mp_float_t)rate_fp / (1 << 16)); +} + +//| class SpeedChanger: +//| """Wraps an audio sample to play it back at a different speed. +//| +//| Uses nearest-neighbor resampling with a fixed-point phase accumulator +//| for CPU-efficient variable-speed playback.""" +//| +//| def __init__(self, source: circuitpython_typing.AudioSample, rate: float = 1.0) -> None: +//| """Create a SpeedChanger that wraps ``source``. +//| +//| :param audiosample source: The audio source to resample. +//| :param float rate: Playback speed multiplier. 1.0 = normal, 2.0 = double speed, +//| 0.5 = half speed. Must be positive. +//| +//| Playing a wave file at 1.5x speed:: +//| +//| import board +//| import audiocore +//| import audiospeed +//| import audioio +//| +//| wav = audiocore.WaveFile("drum.wav") +//| fast = audiospeed.SpeedChanger(wav, rate=1.5) +//| audio = audioio.AudioOut(board.A0) +//| audio.play(fast) +//| +//| # Change speed during playback: +//| fast.rate = 2.0 # double speed +//| fast.rate = 0.5 # half speed +//| """ +//| ... +//| +static mp_obj_t audiospeed_speedchanger_make_new(const mp_obj_type_t *type, + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_source, ARG_rate }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_source, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rate, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Validate source implements audiosample protocol + mp_obj_t source = args[ARG_source].u_obj; + audiosample_check(source); + + uint32_t rate_fp = 1 << 16; // default 1.0 + if (args[ARG_rate].u_obj != mp_const_none) { + rate_fp = rate_to_fp(args[ARG_rate].u_obj); + } + + audiospeed_speedchanger_obj_t *self = mp_obj_malloc(audiospeed_speedchanger_obj_t, &audiospeed_speedchanger_type); + common_hal_audiospeed_speedchanger_construct(self, source, rate_fp); + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialises the SpeedChanger and releases all memory resources for reuse.""" +//| ... +//| +static mp_obj_t audiospeed_speedchanger_deinit(mp_obj_t self_in) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_audiospeed_speedchanger_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_speedchanger_deinit_obj, audiospeed_speedchanger_deinit); + +//| rate: float +//| """Playback speed multiplier. Can be changed during playback.""" +//| +static mp_obj_t audiospeed_speedchanger_obj_get_rate(mp_obj_t self_in) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(&self->base); + return fp_to_rate(common_hal_audiospeed_speedchanger_get_rate(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(audiospeed_speedchanger_get_rate_obj, audiospeed_speedchanger_obj_get_rate); + +static mp_obj_t audiospeed_speedchanger_obj_set_rate(mp_obj_t self_in, mp_obj_t rate_obj) { + audiospeed_speedchanger_obj_t *self = MP_OBJ_TO_PTR(self_in); + audiosample_check_for_deinit(&self->base); + common_hal_audiospeed_speedchanger_set_rate(self, rate_to_fp(rate_obj)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(audiospeed_speedchanger_set_rate_obj, audiospeed_speedchanger_obj_set_rate); + +MP_PROPERTY_GETSET(audiospeed_speedchanger_rate_obj, + (mp_obj_t)&audiospeed_speedchanger_get_rate_obj, + (mp_obj_t)&audiospeed_speedchanger_set_rate_obj); + +static const mp_rom_map_elem_t audiospeed_speedchanger_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiospeed_speedchanger_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_rate), MP_ROM_PTR(&audiospeed_speedchanger_rate_obj) }, + AUDIOSAMPLE_FIELDS, +}; +static MP_DEFINE_CONST_DICT(audiospeed_speedchanger_locals_dict, audiospeed_speedchanger_locals_dict_table); + +static const audiosample_p_t audiospeed_speedchanger_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .reset_buffer = (audiosample_reset_buffer_fun)audiospeed_speedchanger_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiospeed_speedchanger_get_buffer, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + audiospeed_speedchanger_type, + MP_QSTR_SpeedChanger, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, audiospeed_speedchanger_make_new, + locals_dict, &audiospeed_speedchanger_locals_dict, + protocol, &audiospeed_speedchanger_proto + ); diff --git a/shared-bindings/audiospeed/SpeedChanger.h b/shared-bindings/audiospeed/SpeedChanger.h new file mode 100644 index 0000000000000..64a126a7a61fb --- /dev/null +++ b/shared-bindings/audiospeed/SpeedChanger.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/audiospeed/SpeedChanger.h" + +extern const mp_obj_type_t audiospeed_speedchanger_type; + +void common_hal_audiospeed_speedchanger_construct(audiospeed_speedchanger_obj_t *self, + mp_obj_t source, uint32_t rate_fp); +void common_hal_audiospeed_speedchanger_deinit(audiospeed_speedchanger_obj_t *self); +void common_hal_audiospeed_speedchanger_set_rate(audiospeed_speedchanger_obj_t *self, uint32_t rate_fp); +uint32_t common_hal_audiospeed_speedchanger_get_rate(audiospeed_speedchanger_obj_t *self); diff --git a/shared-bindings/audiospeed/__init__.c b/shared-bindings/audiospeed/__init__.c new file mode 100644 index 0000000000000..b12e6db7e6bc7 --- /dev/null +++ b/shared-bindings/audiospeed/__init__.c @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/audiospeed/SpeedChanger.h" + +//| """Audio processing tools""" + +static const mp_rom_map_elem_t audiospeed_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_audiospeed) }, + { MP_ROM_QSTR(MP_QSTR_SpeedChanger), MP_ROM_PTR(&audiospeed_speedchanger_type) }, +}; + +static MP_DEFINE_CONST_DICT(audiospeed_module_globals, audiospeed_module_globals_table); + +const mp_obj_module_t audiospeed_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&audiospeed_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_audiospeed, audiospeed_module); diff --git a/shared-bindings/audiospeed/__init__.h b/shared-bindings/audiospeed/__init__.h new file mode 100644 index 0000000000000..c4a52e5819d12 --- /dev/null +++ b/shared-bindings/audiospeed/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/aurora_epaper/__init__.c b/shared-bindings/aurora_epaper/__init__.c index dedd9995e316c..a17e8319af7ae 100644 --- a/shared-bindings/aurora_epaper/__init__.c +++ b/shared-bindings/aurora_epaper/__init__.c @@ -5,7 +5,7 @@ #include "shared-bindings/aurora_epaper/aurora_framebuffer.h" -STATIC const mp_rom_map_elem_t aurora_epaper_module_globals_table[] = { +static const mp_rom_map_elem_t aurora_epaper_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_aurora_epaper) }, { MP_ROM_QSTR(MP_QSTR_AuroraMemoryFramebuffer), MP_ROM_PTR(&aurora_framebuffer_type) }, }; diff --git a/shared-bindings/aurora_epaper/aurora_framebuffer.c b/shared-bindings/aurora_epaper/aurora_framebuffer.c index 0b15d45e7da8c..49e0b34a85616 100644 --- a/shared-bindings/aurora_epaper/aurora_framebuffer.c +++ b/shared-bindings/aurora_epaper/aurora_framebuffer.c @@ -64,7 +64,7 @@ //| ) -> None: //| """Create a framebuffer for the Aurora CoG display. //| -//| .. note:: Displays of size 1.9" and 2.6" are not tested, and may exibit unexpected behavior. +//| .. note:: Displays of size 1.9" and 2.6" are not tested, and may exhibit unexpected behavior. //| //| :param busio.SPI spi_bus: The SPI bus that the display is connected to //| :param microcontroller.Pin chip_select: The pin connected to the displays chip select input @@ -77,6 +77,7 @@ //| :param bool free_bus: Determines whether the SPI bus passed in will be freed when the frame buffer is freed (optional). //| """ //| ... +//| static mp_obj_t aurora_epaper_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_spi_bus, ARG_chip_select, ARG_reset, ARG_busy, ARG_discharge, ARG_width, ARG_height, ARG_power, ARG_free_bus, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -124,6 +125,7 @@ static mp_int_t aurora_epaper_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer //| AuroraMemoryFramebuffer instance. After deinitialization, no further operations //| may be performed.""" //| ... +//| static mp_obj_t aurora_epaper_framebuffer_deinit(mp_obj_t self_in) { aurora_epaper_framebuffer_obj_t *self = (aurora_epaper_framebuffer_obj_t *)self_in; common_hal_aurora_epaper_framebuffer_deinit(self); @@ -137,6 +139,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(aurora_epaper_framebuffer_deinit_obj, aurora_ep //| Higher temperature means faster update speed. //| """ //| ... +//| static mp_obj_t aurora_epaper_frambuffer_set_temperature(mp_obj_t self_in, mp_obj_t temperature) { aurora_epaper_framebuffer_obj_t *self = (aurora_epaper_framebuffer_obj_t *)self_in; @@ -151,6 +154,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(aurora_epaper_frambuffer_set_temperature_obj, a //| If you have multiple displays this could be used to keep the other active on soft reset.""" //| ... //| +//| static mp_obj_t aurora_epaper_framebuffer_get_free_bus(mp_obj_t self_in) { aurora_epaper_framebuffer_obj_t *self = (aurora_epaper_framebuffer_obj_t *)self_in; return mp_obj_new_bool(self->free_bus); diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c index 491833c27d45f..e14133926994a 100644 --- a/shared-bindings/bitbangio/I2C.c +++ b/shared-bindings/bitbangio/I2C.c @@ -22,11 +22,11 @@ //| //| def __init__( //| self, -//| scl: microcontroller.Pin, -//| sda: microcontroller.Pin, +//| scl: Union[microcontroller.Pin, digitalio.DigitalInOutProtocol], +//| sda: Union[microcontroller.Pin, digitalio.DigitalInOutProtocol], //| *, //| frequency: int = 400000, -//| timeout: int = 255 +//| timeout: int = 255, //| ) -> None: //| """I2C is a two-wire protocol for communicating between devices. At the //| physical level it consists of 2 wires: SCL and SDA, the clock and data @@ -40,11 +40,12 @@ //| bit unpacking. Instead, use an existing driver or make one with //| :ref:`Register ` data descriptors. //| -//| :param ~microcontroller.Pin scl: The clock pin -//| :param ~microcontroller.Pin sda: The data pin +//| :param ~microcontroller.Pin scl: The clock pin or DigitalInOut object +//| :param ~microcontroller.Pin sda: The data pin or DigitalInOut object //| :param int frequency: The clock frequency of the bus //| :param int timeout: The maximum clock stretching timeout in microseconds""" //| ... +//| static mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -56,17 +57,16 @@ static mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const mcu_pin_obj_t *scl = validate_obj_is_free_pin(args[ARG_scl].u_obj, MP_QSTR_scl); - const mcu_pin_obj_t *sda = validate_obj_is_free_pin(args[ARG_sda].u_obj, MP_QSTR_sda); + bitbangio_i2c_obj_t *self = mp_obj_malloc_with_finaliser(bitbangio_i2c_obj_t, &bitbangio_i2c_type); + shared_module_bitbangio_i2c_construct(self, args[ARG_scl].u_obj, args[ARG_sda].u_obj, args[ARG_frequency].u_int, args[ARG_timeout].u_int); - bitbangio_i2c_obj_t *self = mp_obj_malloc(bitbangio_i2c_obj_t, &bitbangio_i2c_type); - shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Releases control of the underlying hardware so other classes can use it.""" //| ... +//| static mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) { bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); shared_module_bitbangio_i2c_deinit(self); @@ -83,18 +83,15 @@ static void check_for_deinit(bitbangio_i2c_obj_t *self) { //| def __enter__(self) -> I2C: //| """No-op used in Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware on context exit. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t bitbangio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - shared_module_bitbangio_i2c_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_i2c_obj___exit___obj, 4, 4, bitbangio_i2c_obj___exit__); +//| +// Provided by context manager helper. static void check_lock(bitbangio_i2c_obj_t *self) { if (!shared_module_bitbangio_i2c_has_lock(self)) { @@ -102,11 +99,30 @@ static void check_lock(bitbangio_i2c_obj_t *self) { } } +//| def probe(self, address: int) -> List[int]: +//| """Check if a device at the specified address responds. +//| +//| :param int address: 7-bit device address +//| :return: ``True`` if a device at ``address`` responds; ``False`` otherwise +//| :rtype: bool""" +//| ... +//| +static mp_obj_t bitbangio_i2c_probe(mp_obj_t self_in, mp_obj_t address_obj) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + check_lock(self); + + const uint16_t addr = mp_obj_get_int(address_obj); + return mp_obj_new_bool(shared_module_bitbangio_i2c_probe(self, addr)); +} +MP_DEFINE_CONST_FUN_OBJ_2(bitbangio_i2c_probe_obj, bitbangio_i2c_probe); + //| def scan(self) -> List[int]: //| """Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of //| those that respond. A device responds if it pulls the SDA line low after //| its address (including a read bit) is sent on the bus.""" //| ... +//| static mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) { bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -126,6 +142,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_scan_obj, bitbangio_i2c_scan); //| def try_lock(self) -> bool: //| """Attempts to grab the I2C lock. Returns True on success.""" //| ... +//| static mp_obj_t bitbangio_i2c_obj_try_lock(mp_obj_t self_in) { bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -136,6 +153,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_try_lock_obj, bitbangio_i2c_obj_try_lock //| def unlock(self) -> None: //| """Releases the I2C lock.""" //| ... +//| static mp_obj_t bitbangio_i2c_obj_unlock(mp_obj_t self_in) { bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -145,6 +163,7 @@ static mp_obj_t bitbangio_i2c_obj_unlock(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock); //| import sys +//| //| def readfrom_into( //| self, address: int, buffer: WriteableBuffer, *, start: int = 0, end: int = sys.maxsize //| ) -> None: @@ -161,6 +180,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock); //| :param int start: Index to start writing at //| :param int end: Index to write up to but not include""" //| ... +//| // Shared arg parsing for readfrom_into and writeto_then_readfrom. static void readfrom(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) { mp_buffer_info_t bufinfo; @@ -202,6 +222,7 @@ static mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 1, bitbangio_i2c_readfrom_into); //| import sys +//| //| def writeto( //| self, address: int, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize //| ) -> None: @@ -222,6 +243,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 1, bitbangio_i2c_rea //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| // Shared arg parsing for writeto and writeto_then_readfrom. static void writeto(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) { // get the buffer to write the data from @@ -267,6 +289,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_wr //| import sys +//| //| def writeto_then_readfrom( //| self, //| address: int, @@ -276,7 +299,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_wr //| out_start: int = 0, //| out_end: int = sys.maxsize, //| in_start: int = 0, -//| in_end: int = sys.maxsize +//| in_end: int = sys.maxsize, //| ) -> None: //| """Write the bytes from ``out_buffer`` to the device selected by ``address``, generate no stop //| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and @@ -300,6 +323,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_wr //| """ //| ... //| +//| static mp_obj_t bitbangio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { @@ -329,7 +353,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_then_readfrom_obj, 1, bitbangio static const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_i2c_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_i2c_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_probe), MP_ROM_PTR(&bitbangio_i2c_probe_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bitbangio_i2c_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&bitbangio_i2c_try_lock_obj) }, diff --git a/shared-bindings/bitbangio/I2C.h b/shared-bindings/bitbangio/I2C.h index 022be3692a6cf..cc9cd21b6012a 100644 --- a/shared-bindings/bitbangio/I2C.h +++ b/shared-bindings/bitbangio/I2C.h @@ -16,8 +16,8 @@ extern const mp_obj_type_t bitbangio_i2c_type; // Initializes the hardware peripheral. extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, - const mcu_pin_obj_t *scl, - const mcu_pin_obj_t *sda, + mp_obj_t scl, + mp_obj_t sda, uint32_t frequency, uint32_t us_timeout); diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c index 62fb1e5a2b363..de021867f3ca9 100644 --- a/shared-bindings/bitbangio/SPI.c +++ b/shared-bindings/bitbangio/SPI.c @@ -33,9 +33,9 @@ //| //| def __init__( //| self, -//| clock: microcontroller.Pin, -//| MOSI: Optional[microcontroller.Pin] = None, -//| MISO: Optional[microcontroller.Pin] = None, +//| clock: Union[microcontroller.Pin, digitalio.DigitalInOutProtocol], +//| MOSI: Optional[Union[microcontroller.Pin, digitalio.DigitalInOutProtocol]] = None, +//| MISO: Optional[Union[microcontroller.Pin, digitalio.DigitalInOutProtocol]] = None, //| ) -> None: //| """Construct an SPI object on the given pins. //| @@ -48,10 +48,11 @@ //| :ref:`Register ` data descriptors. //| //| -//| :param ~microcontroller.Pin clock: the pin to use for the clock. -//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin. -//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin.""" +//| :param ~microcontroller.Pin clock: the pin to use for the clock or DigitalInOut object +//| :param ~microcontroller.Pin MOSI: the Main Out Selected In pin or DigitalInOut object +//| :param ~microcontroller.Pin MISO: the Main In Selected Out pin or DigitalInOut object""" //| ... +//| // TODO(tannewt): Support LSB SPI. static mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { @@ -64,18 +65,15 @@ static mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); - const mcu_pin_obj_t *mosi = validate_obj_is_free_pin_or_none(args[ARG_MOSI].u_obj, MP_QSTR_mosi); - const mcu_pin_obj_t *miso = validate_obj_is_free_pin_or_none(args[ARG_MISO].u_obj, MP_QSTR_miso); - bitbangio_spi_obj_t *self = mp_obj_malloc(bitbangio_spi_obj_t, &bitbangio_spi_type); - shared_module_bitbangio_spi_construct(self, clock, mosi, miso); - return (mp_obj_t)self; + shared_module_bitbangio_spi_construct(self, args[ARG_clock].u_obj, args[ARG_MOSI].u_obj, args[ARG_MISO].u_obj); + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Turn off the SPI bus.""" //| ... +//| static mp_obj_t bitbangio_spi_obj_deinit(mp_obj_t self_in) { bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); shared_module_bitbangio_spi_deinit(self); @@ -92,18 +90,15 @@ static void check_for_deinit(bitbangio_spi_obj_t *self) { //| def __enter__(self) -> SPI: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t bitbangio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - shared_module_bitbangio_spi_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_obj___exit___obj, 4, 4, bitbangio_spi_obj___exit__); +//| +// Provided by context manager helper. static void check_lock(bitbangio_spi_obj_t *self) { @@ -123,6 +118,7 @@ static void check_lock(bitbangio_spi_obj_t *self) { //| or second (1). Rising or falling depends on clock polarity. //| :param int bits: the number of bits per word""" //| ... +//| static mp_obj_t bitbangio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; static const mp_arg_t allowed_args[] = { @@ -153,6 +149,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_configure_obj, 1, bitbangio_spi_configu //| :return: True when lock has been grabbed //| :rtype: bool""" //| ... +//| static mp_obj_t bitbangio_spi_obj_try_lock(mp_obj_t self_in) { bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -163,6 +160,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_try_lock_obj, bitbangio_spi_obj_try_lock //| def unlock(self) -> None: //| """Releases the SPI lock.""" //| ... +//| static mp_obj_t bitbangio_spi_obj_unlock(mp_obj_t self_in) { bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -172,6 +170,7 @@ static mp_obj_t bitbangio_spi_obj_unlock(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock); //| import sys +//| //| def write(self, buf: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize) -> None: //| """Write the data contained in ``buf``. Requires the SPI being locked. //| If the buffer is empty, nothing happens. @@ -185,6 +184,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_unlock_obj, bitbangio_spi_obj_unlock); //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| static mp_obj_t bitbangio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { @@ -224,13 +224,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_write_obj, 1, bitbangio_spi_write); //| import sys +//| //| def readinto( //| self, //| buffer: WriteableBuffer, //| *, //| start: int = 0, //| end: int = sys.maxsize, -//| write_value: int = 0 +//| write_value: int = 0, //| ) -> None: //| """Read into ``buffer`` while writing ``write_value`` for each byte read. //| The SPI object must be locked. @@ -246,6 +247,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_write_obj, 1, bitbangio_spi_write); //| :param int write_value: value to write while reading //| """ //| ... +//| static mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; static const mp_arg_t allowed_args[] = { @@ -285,6 +287,7 @@ static mp_obj_t bitbangio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_readinto_obj, 1, bitbangio_spi_readinto); //| import sys +//| //| def write_readinto( //| self, //| out_buffer: ReadableBuffer, @@ -293,7 +296,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_readinto_obj, 1, bitbangio_spi_readinto //| out_start: int = 0, //| out_end: int = sys.maxsize, //| in_start: int = 0, -//| in_end: int = sys.maxsize +//| in_end: int = sys.maxsize, //| ) -> None: //| """Write out the data in ``out_buffer`` while simultaneously reading data into ``in_buffer``. //| The SPI object must be locked. @@ -319,6 +322,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_readinto_obj, 1, bitbangio_spi_readinto //| """ //| ... //| +//| static mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { @@ -378,7 +382,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_write_readinto_obj, 1, bitbangio_spi_wr static const mp_rom_map_elem_t bitbangio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_spi_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&bitbangio_spi_configure_obj) }, { MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&bitbangio_spi_try_lock_obj) }, diff --git a/shared-bindings/bitbangio/SPI.h b/shared-bindings/bitbangio/SPI.h index dbe821683b0a2..19ec05152ad37 100644 --- a/shared-bindings/bitbangio/SPI.h +++ b/shared-bindings/bitbangio/SPI.h @@ -16,8 +16,7 @@ extern const mp_obj_type_t bitbangio_spi_type; // Construct an underlying SPI object. extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, - const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, - const mcu_pin_obj_t *miso); + mp_obj_t clock, mp_obj_t mosi, mp_obj_t miso); extern void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self); extern bool shared_module_bitbangio_spi_deinited(bitbangio_spi_obj_t *self); diff --git a/shared-bindings/bitmapfilter/__init__.c b/shared-bindings/bitmapfilter/__init__.c index 0bd63c20ab923..7c5344dde1140 100644 --- a/shared-bindings/bitmapfilter/__init__.c +++ b/shared-bindings/bitmapfilter/__init__.c @@ -12,6 +12,7 @@ #include "shared-bindings/displayio/Palette.h" #include "shared-bindings/bitmapfilter/__init__.h" +//| //| //| def morph( //| bitmap: displayio.Bitmap, @@ -19,7 +20,7 @@ //| mul: float | None = None, //| add: float = 0, //| mask: displayio.Bitmap | None = None, -//| threshold=False, +//| threshold: bool = False, //| offset: int = 0, //| invert: bool = False, //| ) -> displayio.Bitmap: @@ -79,6 +80,7 @@ //| bitmapfilter.morph(bitmap, kernel_gauss_3, 1/sum(kernel_gauss_3)) //| """ //| +//| static mp_float_t get_m(mp_obj_t mul_obj, int sum) { @@ -165,6 +167,7 @@ static mp_float_t float_subscr(mp_obj_t o, int i) { //| The ``r`` parameter gives the scale factor for the red channel of //| pixels, and so forth.""" //| +//| static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_type = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ChannelScale), .n_fields = 3, @@ -198,6 +201,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_type = { //| ) -> None: //| """Construct a ChannelScaleOffset object""" //| +//| static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_offset_type = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ChannelScaleOffset), .n_fields = 6, @@ -253,6 +257,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_scale_offset_type = { //| ) -> None: //| """Construct a ChannelMixer object""" //| +//| static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_type = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ChannelMixer), .n_fields = 9, @@ -305,6 +310,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_type = { //| ) -> None: //| """Construct a ChannelMixerOffset object""" //| +//| static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_offset_type = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_ChannelMixerOffset), .n_fields = 12, @@ -351,6 +357,7 @@ static const mp_obj_namedtuple_type_t bitmapfilter_channel_mixer_offset_type = { //| Only pixels set to a non-zero value in the mask are modified. //| """ //| +//| static mp_obj_t bitmapfilter_mix(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_weights, ARG_mask }; static const mp_arg_t allowed_args[] = { @@ -406,7 +413,11 @@ static mp_obj_t bitmapfilter_mix(size_t n_args, const mp_obj_t *pos_args, mp_map } MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_mix_obj, 0, bitmapfilter_mix); -//| def solarize(bitmap, threshold: float = 0.5, mask: displayio.Bitmap | None = None): +//| def solarize( +//| bitmap: displayio.Bitmap, +//| threshold: float = 0.5, +//| mask: displayio.Bitmap | None = None, +//| ) -> displayio.Bitmap: //| """Create a "solarization" effect on an image //| //| This filter inverts pixels with brightness values above ``threshold``, while leaving @@ -420,6 +431,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_mix_obj, 0, bitmapfilter_mix); //| PIL and ImageMagic both call this "solarize". //| """ //| +//| static mp_obj_t bitmapfilter_solarize(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_threshold, ARG_mask }; static const mp_arg_t allowed_args[] = { @@ -454,6 +466,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_solarize_obj, 0, bitmapfilter_solarize); //| ThreeLookupFunctions = Tuple[LookupFunction, LookupFunction, LookupFunction] //| """Any sequenceof three `LookupFunction` objects""" //| +//| //| def lookup( //| bitmap: displayio.Bitmap, //| lookup: LookupFunction | ThreeLookupFunctions, @@ -483,6 +496,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_solarize_obj, 0, bitmapfilter_solarize); //| Only pixels set to a non-zero value in the mask are modified. //| """ //| +//| static int scaled_lut(int maxval, mp_obj_t func, int i) { mp_obj_t obj = mp_call_function_1(func, mp_obj_new_float(i / (mp_float_t)maxval)); @@ -562,6 +576,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_lookup_obj, 0, bitmapfilter_lookup); //| Only pixels set to a non-zero value in the mask are modified. //| """ //| +//| static mp_obj_t bitmapfilter_false_color(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_palette, ARG_mask }; static const mp_arg_t allowed_args[] = { @@ -608,6 +623,7 @@ static uint8_t *get_blend_table(mp_obj_t lookup, int mode) { //| There is not actually a BlendTable type. The real type is actually any //| buffer 4096 bytes in length.""" //| +//| //| def blend_precompute(lookup: BlendFunction, table: BlendTable | None = None) -> BlendTable: //| """Precompute a BlendTable from a BlendFunction //| @@ -624,6 +640,7 @@ static uint8_t *get_blend_table(mp_obj_t lookup, int mode) { //| return a * .33 + b * .67 //| """ //| +//| static mp_obj_t blend_precompute(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_lookup, ARG_table }; static const mp_arg_t allowed_args[] = { @@ -648,6 +665,7 @@ static mp_obj_t blend_precompute(size_t n_args, const mp_obj_t *pos_args, mp_map } MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_precompute_obj, 0, blend_precompute); +//| //| //| def blend( //| dest: displayio.Bitmap, @@ -669,6 +687,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmapfilter_blend_precompute_obj, 0, blend_precomput //| The destination bitmap is returned. //| """ //| +//| static mp_obj_t bitmapfilter_blend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_dest, ARG_src1, ARG_src2, ARG_lookup, ARG_mask }; diff --git a/shared-bindings/bitmaptools/__init__.c b/shared-bindings/bitmaptools/__init__.c index de44b5164bb6e..4d56f393189e4 100644 --- a/shared-bindings/bitmaptools/__init__.c +++ b/shared-bindings/bitmaptools/__init__.c @@ -52,6 +52,7 @@ bitmaptools_rect_t bitmaptools_validate_coord_range_pair(const mp_arg_val_t in[4 //| for information about using the :py:mod:`displayio` module. //| """ //| +//| static int16_t validate_point(mp_obj_t point, int16_t default_value) { // Checks if point is None and returns default_value, otherwise decodes integer value @@ -141,7 +142,7 @@ static void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tupl //| source_clip1: Tuple[int, int], //| angle: float, //| scale: float, -//| skip_index: int +//| skip_index: int, //| ) -> None: //| """Inserts the source bitmap region into the destination bitmap with rotation //| (angle), scale and clipping (both on source and destination bitmaps). @@ -176,6 +177,7 @@ static void validate_clip_region(displayio_bitmap_t *bitmap, mp_obj_t clip0_tupl //| set to None to copy all pixels""" //| ... //| +//| static mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_source_bitmap, ARG_ox, ARG_oy, ARG_dest_clip0, ARG_dest_clip1, @@ -183,8 +185,8 @@ static mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args ARG_angle, ARG_scale, ARG_skip_index}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, {MP_QSTR_ox, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to destination->width / 2 {MP_QSTR_oy, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, // None convert to destination->height / 2 @@ -204,9 +206,9 @@ static mp_obj_t bitmaptools_obj_rotozoom(size_t n_args, const mp_obj_t *pos_args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap - displayio_bitmap_t *source = MP_OBJ_TO_PTR(args[ARG_source_bitmap].u_obj); // the source bitmap + displayio_bitmap_t *source = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_source_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_source_bitmap)); // the source bitmap // ensure that the destination bitmap has at least as many `bits_per_value` as the source if (destination->bits_per_value < source->bits_per_value) { @@ -284,6 +286,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_rotozoom_obj, 0, bitmaptools_obj_rotozoom //| Screen: BlendMode //| """Blend based on the value in each color channel. The result keeps the lighter colors and discards darker colors.""" //| +//| MAKE_ENUM_VALUE(bitmaptools_blendmode_type, bitmaptools_blendmode, Normal, BITMAPTOOLS_BLENDMODE_NORMAL); MAKE_ENUM_VALUE(bitmaptools_blendmode_type, bitmaptools_blendmode, Screen, BITMAPTOOLS_BLENDMODE_SCREEN); @@ -327,6 +330,7 @@ MAKE_ENUM_TYPE(bitmaptools, BlendMode, bitmaptools_blendmode); //| For the L8 colorspace, the bitmaps must have a bits-per-value of 8. //| For the RGB colorspaces, they must have a bits-per-value of 16.""" //| +//| static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_source_bitmap_1, ARG_source_bitmap_2, ARG_colorspace, ARG_factor_1, ARG_factor_2, ARG_blendmode, ARG_skip_source1_index, ARG_skip_source2_index}; @@ -414,6 +418,46 @@ static mp_obj_t bitmaptools_alphablend(size_t n_args, const mp_obj_t *pos_args, } MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_alphablend_obj, 0, bitmaptools_alphablend); +//| def replace_color( +//| dest_bitmap: displayio.Bitmap, old_color: int, new_color: int +//| ) -> None: +//| """Replace any pixels of ``old_color`` with ``new_color`` in the ``bitmap`` +//| +//| :param displayio.Bitmap bitmap: Bitmap that will be changed +//| :param int old_color: Bitmap palette index that will overwritten +//| :param int new_color: Bitmap palette index that will get put in the bitmap""" +//| ... +//| +//| +static mp_obj_t bitmaptools_obj_replace_color(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum {ARG_bitmap, ARG_old_color, ARG_new_color}; + + static const mp_arg_t allowed_args[] = { + {MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_old_color, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_new_color, MP_ARG_REQUIRED | MP_ARG_INT}, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_bitmap)); + + uint32_t old_color, new_color, color_depth; + old_color = args[ARG_old_color].u_int; + new_color = args[ARG_new_color].u_int; + + color_depth = (1 << destination->bits_per_value); + if (color_depth <= old_color || color_depth <= new_color) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q out of range"), MP_QSTR_color); + } + + common_hal_bitmaptools_replace_color(destination, old_color, new_color); + + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_replace_color_obj, 0, bitmaptools_obj_replace_color); + //| def fill_region( //| dest_bitmap: displayio.Bitmap, x1: int, y1: int, x2: int, y2: int, value: int //| ) -> None: @@ -429,18 +473,19 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_alphablend_obj, 0, bitmaptools_alphablend //| fill region in the destination bitmap""" //| ... //| +//| static mp_obj_t bitmaptools_obj_fill_region(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARGS_X1_Y1_X2_Y2, ARG_value}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, ALLOWED_ARGS_X1_Y1_X2_Y2(MP_ARG_REQUIRED, MP_ARG_REQUIRED), - {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; @@ -477,14 +522,15 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_fill_region_obj, 0, bitmaptools_obj_fill_ //| value color in the enclosed area in the destination bitmap""" //| ... //| +//| static mp_obj_t bitmaptools_obj_boundary_fill(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_fill_color_value, ARG_replaced_color_value}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_fill_color_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_fill_color_value, MP_ARG_REQUIRED | MP_ARG_INT}, {MP_QSTR_replaced_color_value, MP_ARG_INT, {.u_int = INT_MAX} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -537,21 +583,22 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_boundary_fill_obj, 0, bitmaptools_obj_bou //| line in the destination bitmap""" //| ... //| +//| static mp_obj_t bitmaptools_obj_draw_line(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_value}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_y2, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_x1, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_y1, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_x2, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_y2, MP_ARG_REQUIRED | MP_ARG_INT}, + {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; @@ -623,20 +670,21 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_line_obj, 0, bitmaptools_obj_draw_li //| """ //| ... //| +//| static mp_obj_t bitmaptools_obj_draw_polygon(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_xs, ARG_ys, ARG_value, ARG_close}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_xs, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_ys, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_xs, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_ys, MP_ARG_REQUIRED | MP_ARG_OBJ}, + {MP_QSTR_value, MP_ARG_REQUIRED | MP_ARG_INT}, {MP_QSTR_close, MP_ARG_BOOL, {.u_bool = true}}, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap mp_buffer_info_t xs_buf, ys_buf; mp_get_buffer_raise(args[ARG_xs].u_obj, &xs_buf, MP_BUFFER_READ); @@ -683,7 +731,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw //| available in the destination bitmap. //| //| If x1 or y1 are not specified, they are taken as 0. If x2 or y2 -//| are not specified, or are given as -1, they are taken as the width +//| are not specified, or are given as None, they are taken as the width //| and height of the image. //| //| The coordinates affected by the blit are ``x1 <= x < x2`` and ``y1 <= y < y2``. @@ -705,12 +753,13 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_polygon_obj, 0, bitmaptools_obj_draw //| """ //| ... //| +//| static mp_obj_t bitmaptools_arrayblit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_data, ARGS_X1_Y1_X2_Y2, ARG_skip_index }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - ALLOWED_ARGS_X1_Y1_X2_Y2(0, MP_ARG_REQUIRED), + { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ }, + ALLOWED_ARGS_X1_Y1_X2_Y2(0, 0), { MP_QSTR_skip_index, MP_ARG_OBJ, {.u_obj = mp_const_none } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -768,13 +817,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_arrayblit_obj, 0, bitmaptools_arrayblit); //| """ //| ... //| +//| static mp_obj_t bitmaptools_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_file, ARG_bits_per_pixel, ARG_element_size, ARG_reverse_pixels_in_element, ARG_swap_bytes_in_element, ARG_reverse_rows }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_bits_per_pixel, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_file, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bits_per_pixel, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_element_size, MP_ARG_INT, { .u_int = 1 } }, { MP_QSTR_reverse_pixels_in_element, MP_ARG_BOOL, { .u_bool = false } }, { MP_QSTR_swap_bytes_in_element, MP_ARG_BOOL, { .u_bool = false } }, @@ -830,6 +880,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_readinto_obj, 0, bitmaptools_readinto); //| FloydStenberg: "DitherAlgorithm" //| """The Floyd-Stenberg dither""" //| +//| MAKE_ENUM_VALUE(bitmaptools_dither_algorithm_type, dither_algorithm, Atkinson, DITHER_ALGORITHM_ATKINSON); MAKE_ENUM_VALUE(bitmaptools_dither_algorithm_type, dither_algorithm, FloydStenberg, DITHER_ALGORITHM_FLOYD_STENBERG); @@ -858,12 +909,13 @@ MAKE_ENUM_TYPE(bitmaptools, DitherAlgorithm, bitmaptools_dither_algorithm); //| """ //| ... //| +//| static mp_obj_t bitmaptools_dither(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_dest_bitmap, ARG_source_bitmap, ARG_source_colorspace, ARG_algorithm }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_source_colorspace, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_source_colorspace, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_algorithm, MP_ARG_OBJ, { .u_obj = MP_ROM_PTR((void *)&dither_algorithm_Atkinson_obj) } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -951,6 +1003,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_dither_obj, 0, bitmaptools_dither); //| //| ... //| +//| static mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_dest_bitmap, ARG_x, ARG_y, ARG_radius, ARG_value}; @@ -964,7 +1017,7 @@ static mp_obj_t bitmaptools_obj_draw_circle(size_t n_args, const mp_obj_t *pos_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - displayio_bitmap_t *destination = MP_OBJ_TO_PTR(args[ARG_dest_bitmap].u_obj); // the destination bitmap + displayio_bitmap_t *destination = MP_OBJ_TO_PTR(mp_arg_validate_type(args[ARG_dest_bitmap].u_obj, &displayio_bitmap_type, MP_QSTR_dest_bitmap)); // the destination bitmap uint32_t value, color_depth; value = args[ARG_value].u_int; @@ -1000,7 +1053,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_circle_obj, 0, bitmaptools_obj_draw_ //| x2: int | None = None, //| y2: int | None = None, //| skip_source_index: int | None = None, -//| skip_dest_index: int | None = None +//| skip_dest_index: int | None = None, //| ) -> None: //| """Inserts the source_bitmap region defined by rectangular boundaries //| (x1,y1) and (x2,y2) into the bitmap at the specified (x,y) location. @@ -1021,13 +1074,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitmaptools_draw_circle_obj, 0, bitmaptools_obj_draw_ //| by the pixels from the source""" //| ... //| +//| static mp_obj_t bitmaptools_obj_blit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum {ARG_destination, ARG_source, ARG_x, ARG_y, ARG_x1, ARG_y1, ARG_x2, ARG_y2, ARG_skip_source_index, ARG_skip_dest_index}; static const mp_arg_t allowed_args[] = { - {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} }, - {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT, {.u_obj = MP_OBJ_NULL} }, + {MP_QSTR_dest_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + {MP_QSTR_source_bitmap, MP_ARG_REQUIRED | MP_ARG_OBJ }, + {MP_QSTR_x, MP_ARG_REQUIRED | MP_ARG_INT }, + {MP_QSTR_y, MP_ARG_REQUIRED | MP_ARG_INT }, ALLOWED_ARGS_X1_Y1_X2_Y2(0, 0), {MP_QSTR_skip_source_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, {MP_QSTR_skip_dest_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, @@ -1089,6 +1143,7 @@ static const mp_rom_map_elem_t bitmaptools_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_rotozoom), MP_ROM_PTR(&bitmaptools_rotozoom_obj) }, { MP_ROM_QSTR(MP_QSTR_arrayblit), MP_ROM_PTR(&bitmaptools_arrayblit_obj) }, { MP_ROM_QSTR(MP_QSTR_alphablend), MP_ROM_PTR(&bitmaptools_alphablend_obj) }, + { MP_ROM_QSTR(MP_QSTR_replace_color), MP_ROM_PTR(&bitmaptools_replace_color_obj) }, { MP_ROM_QSTR(MP_QSTR_fill_region), MP_ROM_PTR(&bitmaptools_fill_region_obj) }, { MP_ROM_QSTR(MP_QSTR_boundary_fill), MP_ROM_PTR(&bitmaptools_boundary_fill_obj) }, { MP_ROM_QSTR(MP_QSTR_draw_line), MP_ROM_PTR(&bitmaptools_draw_line_obj) }, diff --git a/shared-bindings/bitmaptools/__init__.h b/shared-bindings/bitmaptools/__init__.h index 2d9b22e216e5f..f193ef6d95282 100644 --- a/shared-bindings/bitmaptools/__init__.h +++ b/shared-bindings/bitmaptools/__init__.h @@ -42,6 +42,9 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, int16_t x2, int16_t y2, uint32_t value); +void common_hal_bitmaptools_replace_color(displayio_bitmap_t *destination, + uint32_t old_color, uint32_t new_color); + void common_hal_bitmaptools_boundary_fill(displayio_bitmap_t *destination, int16_t x, int16_t y, uint32_t fill_color_value, uint32_t replaced_color_value); @@ -80,8 +83,8 @@ typedef struct { #define ARGS_X1_Y1_X2_Y2 ARG_x1, ARG_y1, ARG_x2, ARG_y2 #define ALLOWED_ARGS_X1_Y1_X2_Y2(if_required1, if_required2) \ {MP_QSTR_x1, if_required1 | MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0)}}, \ - {MP_QSTR_y1, if_required2 | MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0)}}, \ - {MP_QSTR_x2, if_required1 | MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}}, \ + {MP_QSTR_y1, if_required1 | MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0)}}, \ + {MP_QSTR_x2, if_required2 | MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}}, \ {MP_QSTR_y2, if_required2 | MP_ARG_OBJ, {.u_obj = MP_ROM_NONE}} bitmaptools_rect_t bitmaptools_validate_coord_range_pair(const mp_arg_val_t in[4], int width, int height); diff --git a/shared-bindings/bitops/__init__.c b/shared-bindings/bitops/__init__.c index dc07436866a30..088aa260e9790 100644 --- a/shared-bindings/bitops/__init__.c +++ b/shared-bindings/bitops/__init__.c @@ -11,6 +11,7 @@ //| """Routines for low-level manipulation of binary data""" //| +//| //| def bit_transpose( //| input: ReadableBuffer, output: WriteableBuffer, width: int = 8 @@ -35,6 +36,7 @@ //| Returns the output buffer.""" //| ... //| +//| static mp_obj_t bit_transpose(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_input, ARG_output, ARG_width }; diff --git a/shared-bindings/board/__init__.c b/shared-bindings/board/__init__.c index 1a2721a91c4f5..c985d85217530 100644 --- a/shared-bindings/board/__init__.c +++ b/shared-bindings/board/__init__.c @@ -33,12 +33,14 @@ //| //| .. warning:: The board module varies by board. The APIs documented here may or may not be //| available on a specific board.""" +//| //| board_id: str //| """Board ID string. The unique identifier for the board model in //| circuitpython, as well as on circuitpython.org. //| Example: "hallowing_m0_express".""" //| +//| //| def I2C() -> busio.I2C: //| """Returns the `busio.I2C` object for the board's designated I2C bus(es). @@ -46,6 +48,7 @@ //| """ //| ... //| +//| #if CIRCUITPY_BOARD_I2C static mp_obj_t board_i2c_0(void) { return common_hal_board_create_i2c(0); @@ -64,6 +67,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_i2c_obj, board_i2c_0); //| """ //| ... //| +//| #if CIRCUITPY_BOARD_SPI static mp_obj_t board_spi_0(void) { return common_hal_board_create_spi(0); @@ -82,6 +86,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(board_spi_obj, board_spi_0); //| """ //| ... //| +//| #if CIRCUITPY_BOARD_UART static mp_obj_t board_uart_0(void) { return common_hal_board_create_uart(0); diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h index 7c9a59d2dbd0d..4334309973005 100644 --- a/shared-bindings/board/__init__.h +++ b/shared-bindings/board/__init__.h @@ -11,22 +11,23 @@ #include "shared-bindings/microcontroller/Pin.h" // for the pin definitions +#if CIRCUITPY_MUTABLE_BOARD +extern mp_obj_dict_t board_module_globals; +#else extern const mp_obj_dict_t board_module_globals; +#endif static const MP_DEFINE_STR_OBJ(board_module_id_obj, CIRCUITPY_BOARD_ID); -bool common_hal_board_is_i2c(mp_obj_t obj); mp_obj_t common_hal_board_get_i2c(const mp_int_t instance); mp_obj_t common_hal_board_create_i2c(const mp_int_t instance); mp_obj_t board_i2c(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_0(board_i2c_obj); -bool common_hal_board_is_spi(mp_obj_t obj); mp_obj_t common_hal_board_get_spi(const mp_int_t instance); mp_obj_t common_hal_board_create_spi(const mp_int_t instance); mp_obj_t board_spi(size_t n_args, const mp_obj_t *args); MP_DECLARE_CONST_FUN_OBJ_0(board_spi_obj); -bool common_hal_board_is_uart(mp_obj_t obj); mp_obj_t common_hal_board_get_uart(const mp_int_t instance); mp_obj_t common_hal_board_create_uart(const mp_int_t instance); mp_obj_t board_uart(size_t n_args, const mp_obj_t *args); @@ -41,3 +42,7 @@ MP_DECLARE_CONST_FUN_OBJ_0(board_uart_obj); #define CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS \ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, \ { MP_ROM_QSTR(MP_QSTR_board_id), MP_ROM_PTR(&board_module_id_obj) }, + +#define CIRCUITPYTHON_MUTABLE_BOARD_DICT_STANDARD_ITEMS \ + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_board) }, \ + { MP_ROM_QSTR(MP_QSTR_board_id), MP_OBJ_FROM_PTR(&board_module_id_obj) }, diff --git a/shared-bindings/busdisplay/BusDisplay.c b/shared-bindings/busdisplay/BusDisplay.c index 1b9a1a70c7e92..0bf171a5d089c 100644 --- a/shared-bindings/busdisplay/BusDisplay.c +++ b/shared-bindings/busdisplay/BusDisplay.c @@ -28,6 +28,7 @@ //| ] //| """:py:class:`fourwire.FourWire`, :py:class:`paralleldisplaybus.ParallelBus` or :py:class:`i2cdisplaybus.I2CDisplayBus`""" //| +//| //| class BusDisplay: //| """Manage updating a display over a display bus @@ -65,7 +66,7 @@ //| auto_refresh: bool = True, //| native_frames_per_second: int = 60, //| backlight_on_high: bool = True, -//| SH1107_addressing: bool = False +//| SH1107_addressing: bool = False, //| ) -> None: //| r"""Create a Display object on the given display bus (`FourWire`, `paralleldisplaybus.ParallelBus` or `I2CDisplayBus`). //| @@ -99,8 +100,8 @@ //| :param ~circuitpython_typing.ReadableBuffer init_sequence: Byte-packed initialization sequence. //| :param int width: Width in pixels //| :param int height: Height in pixels -//| :param int colstart: The index if the first visible column -//| :param int rowstart: The index if the first visible row +//| :param int colstart: The index of the first visible column +//| :param int rowstart: The index of the first visible row //| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270) //| :param int color_depth: The number of bits of color per pixel transmitted. (Some displays //| support 18 bit but 16 is easier to transmit. The last bit is extrapolated.) @@ -121,17 +122,17 @@ //| :param int native_frames_per_second: Number of display refreshes per second that occur with the given init_sequence. //| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on. //| :param bool SH1107_addressing: Special quirk for SH1107, use upper/lower column set and page set -//| :param int set_vertical_scroll: This parameter is accepted but ignored for backwards compatibility. It will be removed in a future release. //| :param int backlight_pwm_frequency: The frequency to use to drive the PWM for backlight brightness control. Default is 50000. //| """ //| ... +//| static mp_obj_t busdisplay_busdisplay_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_display_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_color_depth, ARG_grayscale, ARG_pixels_in_byte_share_row, ARG_bytes_per_cell, ARG_reverse_pixels_in_byte, ARG_reverse_bytes_in_word, ARG_set_column_command, ARG_set_row_command, ARG_write_ram_command, - ARG_set_vertical_scroll, ARG_backlight_pin, ARG_brightness_command, + ARG_backlight_pin, ARG_brightness_command, ARG_brightness, ARG_single_byte_bounds, ARG_data_as_commands, ARG_auto_refresh, ARG_native_frames_per_second, ARG_backlight_on_high, ARG_SH1107_addressing, ARG_backlight_pwm_frequency }; @@ -152,7 +153,6 @@ static mp_obj_t busdisplay_busdisplay_make_new(const mp_obj_type_t *type, size_t { MP_QSTR_set_column_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2a} }, { MP_QSTR_set_row_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2b} }, { MP_QSTR_write_ram_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x2c} }, - { MP_QSTR_set_vertical_scroll, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x0} }, { MP_QSTR_backlight_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, { MP_QSTR_brightness_command, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = NO_BRIGHTNESS_COMMAND} }, { MP_QSTR_brightness, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} }, @@ -236,7 +236,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(busdisplay_busdisplay_show_obj, busdisplay_busdisplay_ //| self, //| *, //| target_frames_per_second: Optional[int] = None, -//| minimum_frames_per_second: int = 0 +//| minimum_frames_per_second: int = 0, //| ) -> bool: //| """When auto_refresh is off, and :py:attr:`target_frames_per_second` is not `None` this waits //| for the target frame rate and then refreshes the display, @@ -258,6 +258,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(busdisplay_busdisplay_show_obj, busdisplay_busdisplay_ //| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second. //| """ //| ... +//| static mp_obj_t busdisplay_busdisplay_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second }; static const mp_arg_t allowed_args[] = { @@ -395,6 +396,7 @@ MP_PROPERTY_GETTER(busdisplay_busdisplay_bus_obj, //| If the root group is set to `displayio.CIRCUITPYTHON_TERMINAL`, the default CircuitPython terminal will be shown. //| If the root group is set to ``None``, no output will be shown. //| """ +//| static mp_obj_t busdisplay_busdisplay_obj_get_root_group(mp_obj_t self_in) { busdisplay_busdisplay_obj_t *self = native_display(self_in); return common_hal_busdisplay_busdisplay_get_root_group(self); @@ -426,6 +428,7 @@ MP_PROPERTY_GETSET(busdisplay_busdisplay_root_group_obj, //| """ //| ... //| +//| static mp_obj_t busdisplay_busdisplay_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_y, ARG_buffer }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/busio/I2C.c b/shared-bindings/busio/I2C.c index 8a1b832a7a8d8..5fa62f9df3859 100644 --- a/shared-bindings/busio/I2C.c +++ b/shared-bindings/busio/I2C.c @@ -25,7 +25,7 @@ //| sda: microcontroller.Pin, //| *, //| frequency: int = 100000, -//| timeout: int = 255 +//| timeout: int = 255, //| ) -> None: //| """I2C is a two-wire protocol for communicating between devices. At the //| physical level it consists of 2 wires: SCL and SDA, the clock and data @@ -39,16 +39,19 @@ //| bit unpacking. Instead, use an existing driver or make one with //| :ref:`Register ` data descriptors. //| +//| .. seealso:: This class provides an I2C controller, which controls I2C targets (peripherals). +//| To act as an I2C target, use `i2ctarget.I2CTarget`. +//| //| :param ~microcontroller.Pin scl: The clock pin //| :param ~microcontroller.Pin sda: The data pin //| :param int frequency: The clock frequency in Hertz -//| :param int timeout: The maximum clock stretching timeut - (used only for +//| :param int timeout: The maximum clock stretching timeout - (used only for //| :class:`bitbangio.I2C`; ignored for :class:`busio.I2C`) //| """ //| ... +//| static mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_BUSIO_I2C - busio_i2c_obj_t *self = mp_obj_malloc(busio_i2c_obj_t, &busio_i2c_type); enum { ARG_scl, ARG_sda, ARG_frequency, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -62,8 +65,9 @@ static mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz const mcu_pin_obj_t *scl = validate_obj_is_free_pin(args[ARG_scl].u_obj, MP_QSTR_scl); const mcu_pin_obj_t *sda = validate_obj_is_free_pin(args[ARG_sda].u_obj, MP_QSTR_sda); + busio_i2c_obj_t *self = mp_obj_malloc_with_finaliser(busio_i2c_obj_t, &busio_i2c_type); common_hal_busio_i2c_construct(self, scl, sda, args[ARG_frequency].u_int, args[ARG_timeout].u_int); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); #endif // CIRCUITPY_BUSIO_I2C @@ -74,6 +78,7 @@ static mp_obj_t busio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, siz //| def deinit(self) -> None: //| """Releases control of the underlying hardware so other classes can use it.""" //| ... +//| static mp_obj_t busio_i2c_obj_deinit(mp_obj_t self_in) { busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_busio_i2c_deinit(self); @@ -90,26 +95,41 @@ static void check_for_deinit(busio_i2c_obj_t *self) { //| def __enter__(self) -> I2C: //| """No-op used in Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware on context exit. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t busio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_busio_i2c_deinit(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_i2c___exit___obj, 4, 4, busio_i2c_obj___exit__); +//| +// Provided by context manager helper. static void check_lock(busio_i2c_obj_t *self) { - asm (""); + __asm__ (""); if (!common_hal_busio_i2c_has_lock(self)) { mp_raise_RuntimeError(MP_ERROR_TEXT("Function requires lock")); } } +//| def probe(self, address: int) -> bool: +//| """Check if a device at the specified address responds. +//| +//| :param int address: 7-bit device address +//| :return: ``True`` if a device at ``address`` responds; ``False`` otherwise +//| :rtype: bool""" +//| ... +//| +static mp_obj_t busio_i2c_probe(mp_obj_t self_in, mp_obj_t address_obj) { + busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + check_lock(self); + + const uint16_t addr = mp_obj_get_int(address_obj); + return mp_obj_new_bool(common_hal_busio_i2c_probe(self, addr)); +} +MP_DEFINE_CONST_FUN_OBJ_2(busio_i2c_probe_obj, busio_i2c_probe); + //| def scan(self) -> List[int]: //| """Scan all I2C addresses between 0x08 and 0x77 inclusive and return a //| list of those that respond. @@ -117,6 +137,7 @@ static void check_lock(busio_i2c_obj_t *self) { //| :return: List of device ids on the I2C bus //| :rtype: list""" //| ... +//| static mp_obj_t busio_i2c_scan(mp_obj_t self_in) { busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -139,6 +160,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_scan_obj, busio_i2c_scan); //| :return: True when lock has been grabbed //| :rtype: bool""" //| ... +//| static mp_obj_t busio_i2c_obj_try_lock(mp_obj_t self_in) { busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -149,6 +171,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_try_lock_obj, busio_i2c_obj_try_lock); //| def unlock(self) -> None: //| """Releases the I2C lock.""" //| ... +//| static mp_obj_t busio_i2c_obj_unlock(mp_obj_t self_in) { busio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -158,6 +181,7 @@ static mp_obj_t busio_i2c_obj_unlock(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock); //| import sys +//| //| def readfrom_into( //| self, address: int, buffer: WriteableBuffer, *, start: int = 0, end: int = sys.maxsize //| ) -> None: @@ -173,6 +197,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_i2c_unlock_obj, busio_i2c_obj_unlock); //| :param int start: beginning of buffer slice //| :param int end: end of buffer slice; if not specified, use ``len(buffer)``""" //| ... +//| static mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_address, ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { @@ -203,10 +228,10 @@ static mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, start *= stride_in_bytes; length *= stride_in_bytes; - uint8_t status = + mp_negative_errno_t status = common_hal_busio_i2c_read(self, args[ARG_address].u_int, ((uint8_t *)bufinfo.buf) + start, length); if (status != 0) { - mp_raise_OSError(status); + mp_raise_OSError(-status); } return mp_const_none; @@ -214,6 +239,7 @@ static mp_obj_t busio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 1, busio_i2c_readfrom_into); //| import sys +//| //| def writeto( //| self, address: int, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize //| ) -> None: @@ -233,6 +259,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_readfrom_into_obj, 1, busio_i2c_readfrom_in //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| static mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_address, ARG_buffer, ARG_start, ARG_end }; static const mp_arg_t allowed_args[] = { @@ -263,11 +290,11 @@ static mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma length *= stride_in_bytes; // do the transfer - uint8_t status = + mp_negative_errno_t status = common_hal_busio_i2c_write(self, args[ARG_address].u_int, ((uint8_t *)bufinfo.buf) + start, length); if (status != 0) { - mp_raise_OSError(status); + mp_raise_OSError(-status); } return mp_const_none; @@ -275,6 +302,7 @@ static mp_obj_t busio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_ma static MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto); //| import sys +//| //| def writeto_then_readfrom( //| self, //| address: int, @@ -284,7 +312,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto); //| out_start: int = 0, //| out_end: int = sys.maxsize, //| in_start: int = 0, -//| in_end: int = sys.maxsize +//| in_end: int = sys.maxsize, //| ) -> None: //| """Write the bytes from ``out_buffer`` to the device selected by ``address``, generate no stop //| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and @@ -308,6 +336,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_obj, 1, busio_i2c_writeto); //| """ //| ... //| +//| static mp_obj_t busio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; static const mp_arg_t allowed_args[] = { @@ -348,10 +377,10 @@ static mp_obj_t busio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *p in_start *= in_stride_in_bytes; in_length *= in_stride_in_bytes; - uint8_t status = common_hal_busio_i2c_write_read(self, args[ARG_address].u_int, + mp_negative_errno_t status = common_hal_busio_i2c_write_read(self, args[ARG_address].u_int, ((uint8_t *)out_bufinfo.buf) + out_start, out_length, ((uint8_t *)in_bufinfo.buf) + in_start, in_length); if (status != 0) { - mp_raise_OSError(status); + mp_raise_OSError(-status); } return mp_const_none; @@ -362,8 +391,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_i2c_writeto_then_readfrom_obj, 1, busio_i2c_wri static const mp_rom_map_elem_t busio_i2c_locals_dict_table[] = { #if CIRCUITPY_BUSIO_I2C { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_i2c_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&busio_i2c_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busio_i2c___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_probe), MP_ROM_PTR(&busio_i2c_probe_obj) }, { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&busio_i2c_scan_obj) }, { MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&busio_i2c_try_lock_obj) }, diff --git a/shared-bindings/busio/I2C.h b/shared-bindings/busio/I2C.h index da505436b0868..2978a90754490 100644 --- a/shared-bindings/busio/I2C.h +++ b/shared-bindings/busio/I2C.h @@ -7,6 +7,7 @@ #pragma once #include "py/obj.h" +#include "py/mperrno.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/busio/I2C.h" @@ -19,11 +20,15 @@ extern void common_hal_busio_i2c_construct(busio_i2c_obj_t *self, const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda, uint32_t frequency, - uint32_t timeout); + uint32_t timeout_ms); extern void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self); extern bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self); +// Mark as deinit without deiniting. This is used by displayio after copying the +// object elsewhere and prevents the heap from deiniting the object. +extern void common_hal_busio_i2c_mark_deinit(busio_i2c_obj_t *self); + extern bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self); extern bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self); extern void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self); @@ -31,17 +36,17 @@ extern void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self); // Probe the bus to see if a device acknowledges the given address. extern bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr); -// Write to the device and return 0 on success or an appropriate error code from mperrno.h -extern uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t address, +// Write to the device and return 0 on success or a negative error code from mperrno.h +extern mp_negative_errno_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t address, const uint8_t *data, size_t len); // Reads memory of the i2c device picking up where it left off and return 0 on -// success or an appropriate error code from mperrno.h -extern uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address, +// success or a negative error code from mperrno.h +extern mp_negative_errno_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t address, uint8_t *data, size_t len); // Do a write and then a read in the same I2C transaction. -uint8_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t address, +mp_negative_errno_t common_hal_busio_i2c_write_read(busio_i2c_obj_t *self, uint16_t address, uint8_t *out_data, size_t out_len, uint8_t *in_data, size_t in_len); // This is used by the supervisor to claim I2C devices indefinitely. diff --git a/shared-bindings/busio/SPI.c b/shared-bindings/busio/SPI.c index 2e52486cabe86..962080648ce4d 100644 --- a/shared-bindings/busio/SPI.c +++ b/shared-bindings/busio/SPI.c @@ -9,17 +9,17 @@ #include +#include "py/binary.h" +#include "py/mperrno.h" +#include "py/objproperty.h" +#include "py/runtime.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/util.h" - #include "shared/runtime/buffer_helper.h" #include "shared/runtime/context_manager_helpers.h" -#include "py/binary.h" -#include "py/mperrno.h" -#include "py/objproperty.h" -#include "py/runtime.h" - +#include "shared/runtime/interrupt_char.h" +#include "supervisor/shared/tick.h" //| class SPI: //| """A 3-4 wire serial protocol @@ -28,7 +28,7 @@ //| main device. It is typically faster than :py:class:`~bitbangio.I2C` because a //| separate pin is used to select a device rather than a transmitted //| address. This class only manages three of the four SPI lines: `!clock`, -//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate +//| `!MOSI`, `!MISO`. It is up to the client to manage the appropriate //| select line, often abbreviated `!CS` or `!SS`. (This is common because //| multiple secondaries can share the `!clock`, `!MOSI` and `!MISO` lines //| and therefore the hardware.) @@ -46,6 +46,8 @@ //| //|

//| +//| .. seealso:: This class acts as an SPI main (controller). +//| To act as an SPI secondary (target), use `spitarget.SPITarget`. //| """ //| //| def __init__( @@ -80,18 +82,18 @@ //| **Limitations:** ``half_duplex`` is available only on STM; other chips do not have the hardware support. //| """ //| ... +//| // TODO(tannewt): Support LSB SPI. static mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_BUSIO_SPI - busio_spi_obj_t *self = mp_obj_malloc(busio_spi_obj_t, &busio_spi_type); enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_half_duplex }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_MOSI, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_MISO, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_half_duplex, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_bool = false} }, + { MP_QSTR_half_duplex, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -104,6 +106,7 @@ static mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz mp_raise_ValueError(MP_ERROR_TEXT("Must provide MISO or MOSI pin")); } + busio_spi_obj_t *self = mp_obj_malloc_with_finaliser(busio_spi_obj_t, &busio_spi_type); common_hal_busio_spi_construct(self, clock, mosi, miso, args[ARG_half_duplex].u_bool); return MP_OBJ_FROM_PTR(self); #else @@ -115,6 +118,7 @@ static mp_obj_t busio_spi_make_new(const mp_obj_type_t *type, size_t n_args, siz //| def deinit(self) -> None: //| """Turn off the SPI bus.""" //| ... +//| static mp_obj_t busio_spi_obj_deinit(mp_obj_t self_in) { busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_busio_spi_deinit(self); @@ -126,20 +130,17 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_deinit_obj, busio_spi_obj_deinit); //| """No-op used by Context Managers. //| Provided by context manager helper.""" //| ... +//| //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t busio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_busio_spi_deinit(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_spi_obj___exit___obj, 4, 4, busio_spi_obj___exit__); +//| +// Provided by context manager helper. static void check_lock(busio_spi_obj_t *self) { - asm (""); + __asm__ (""); if (!common_hal_busio_spi_has_lock(self)) { mp_raise_RuntimeError(MP_ERROR_TEXT("Function requires lock")); } @@ -175,6 +176,7 @@ static void check_for_deinit(busio_spi_obj_t *self) { //| Two SPI objects may be created, except on the Circuit Playground Bluefruit, //| which allows only one (to allow for an additional I2C object).""" //| ... +//| static mp_obj_t busio_spi_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits }; @@ -208,6 +210,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_configure_obj, 1, busio_spi_configure); //| :return: True when lock has been grabbed //| :rtype: bool""" //| ... +//| static mp_obj_t busio_spi_obj_try_lock(mp_obj_t self_in) { busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -218,6 +221,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_try_lock_obj, busio_spi_obj_try_lock); //| def unlock(self) -> None: //| """Releases the SPI lock.""" //| ... +//| static mp_obj_t busio_spi_obj_unlock(mp_obj_t self_in) { busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -228,6 +232,7 @@ static mp_obj_t busio_spi_obj_unlock(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| import sys +//| //| def write(self, buffer: ReadableBuffer, *, start: int = 0, end: int = sys.maxsize) -> None: //| """Write the data contained in ``buffer``. The SPI object must be locked. //| If the buffer is empty, nothing happens. @@ -241,6 +246,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_unlock_obj, busio_spi_obj_unlock); //| :param int end: end of buffer slice; if not specified, use ``len(buffer)`` //| """ //| ... +//| static mp_obj_t busio_spi_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end }; @@ -281,13 +287,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 1, busio_spi_write); //| import sys +//| //| def readinto( //| self, //| buffer: WriteableBuffer, //| *, //| start: int = 0, //| end: int = sys.maxsize, -//| write_value: int = 0 +//| write_value: int = 0, //| ) -> None: //| """Read into ``buffer`` while writing ``write_value`` for each byte read. //| The SPI object must be locked. @@ -305,6 +312,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_obj, 1, busio_spi_write); //| :param int write_value: value to write while reading //| """ //| ... +//| static mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_start, ARG_end, ARG_write_value }; @@ -345,6 +353,7 @@ static mp_obj_t busio_spi_readinto(size_t n_args, const mp_obj_t *pos_args, mp_m MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 1, busio_spi_readinto); //| import sys +//| //| def write_readinto( //| self, //| out_buffer: ReadableBuffer, @@ -353,7 +362,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 1, busio_spi_readinto); //| out_start: int = 0, //| out_end: int = sys.maxsize, //| in_start: int = 0, -//| in_end: int = sys.maxsize +//| in_end: int = sys.maxsize, //| ) -> None: //| """Write out the data in ``out_buffer`` while simultaneously reading data into ``in_buffer``. //| The SPI object must be locked. @@ -378,6 +387,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_readinto_obj, 1, busio_spi_readinto); //| :param int in_end: end of ``in_buffer slice``; if not specified, use ``len(in_buffer)`` //| """ //| ... +//| static mp_obj_t busio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end }; @@ -438,6 +448,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(busio_spi_write_readinto_obj, 1, busio_spi_write_read //| """The actual SPI bus frequency. This may not match the frequency requested //| due to internal limitations.""" //| +//| static mp_obj_t busio_spi_obj_get_frequency(mp_obj_t self_in) { busio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -448,14 +459,16 @@ MP_DEFINE_CONST_FUN_OBJ_1(busio_spi_get_frequency_obj, busio_spi_obj_get_frequen MP_PROPERTY_GETTER(busio_spi_frequency_obj, (mp_obj_t)&busio_spi_get_frequency_obj); + #endif // CIRCUITPY_BUSIO_SPI static const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { #if CIRCUITPY_BUSIO_SPI { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&busio_spi_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busio_spi_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&busio_spi_configure_obj) }, { MP_ROM_QSTR(MP_QSTR_try_lock), MP_ROM_PTR(&busio_spi_try_lock_obj) }, @@ -465,6 +478,7 @@ static const mp_rom_map_elem_t busio_spi_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&busio_spi_write_obj) }, { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&busio_spi_write_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&busio_spi_frequency_obj) } + #endif // CIRCUITPY_BUSIO_SPI }; static MP_DEFINE_CONST_DICT(busio_spi_locals_dict, busio_spi_locals_dict_table); @@ -480,3 +494,17 @@ MP_DEFINE_CONST_OBJ_TYPE( busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj, qstr arg_name) { return mp_arg_validate_type(obj, &busio_spi_type, arg_name); } + +// Wait as long as needed for the lock. This is used by SD card access from USB. +// The default implementation is to busy-wait while running the background tasks. espressif is different. +bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms) { + uint64_t deadline = supervisor_ticks_ms64() + timeout_ms; + while (supervisor_ticks_ms64() < deadline && + !mp_hal_is_interrupted()) { + if (common_hal_busio_spi_try_lock(self)) { + return true; + } + RUN_BACKGROUND_TASKS; + } + return false; +} diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index 69e582411a169..76ed697d66531 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -22,6 +22,10 @@ extern void common_hal_busio_spi_construct(busio_spi_obj_t *self, extern void common_hal_busio_spi_deinit(busio_spi_obj_t *self); extern bool common_hal_busio_spi_deinited(busio_spi_obj_t *self); +// Mark as deinit without deiniting. This is used by displayio after copying the +// object elsewhere and prevents the heap from deiniting the object. +extern void common_hal_busio_spi_mark_deinit(busio_spi_obj_t *self); + extern bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits); extern bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self); @@ -50,3 +54,7 @@ uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t *self); extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self); extern busio_spi_obj_t *validate_obj_is_spi_bus(mp_obj_t obj_in, qstr arg_name); + +// Wait as long as needed for the lock. This is used by SD card access from USB. +// For most ports, busy-wait while running the background tasks. +MP_WEAK bool common_hal_busio_spi_wait_for_lock(busio_spi_obj_t *self, uint32_t timeout_ms); diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 3a7a602848573..017b983778115 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -54,7 +54,7 @@ //| parity: Optional[Parity] = None, //| stop: int = 1, //| timeout: float = 1, -//| receiver_buffer_size: int = 64 +//| receiver_buffer_size: int = 64, //| ) -> None: //| """A common bidirectional serial protocol that uses an an agreed upon speed //| rather than a shared clock line. @@ -83,6 +83,7 @@ //| RS485 specifications intermittently. //| """ //| ... +//| typedef struct { mp_obj_base_t base; } busio_uart_parity_obj_t; @@ -151,13 +152,12 @@ static mp_obj_t busio_uart_make_new(const mp_obj_type_t *type, size_t n_args, si const bool rs485_invert = args[ARG_rs485_invert].u_bool; - busio_uart_obj_t *self = m_new_obj_with_finaliser(busio_uart_obj_t); - self->base.type = &busio_uart_type; + busio_uart_obj_t *self = mp_obj_malloc_with_finaliser(busio_uart_obj_t, &busio_uart_type); common_hal_busio_uart_construct(self, tx, rx, rts, cts, rs485_dir, rs485_invert, args[ARG_baudrate].u_int, bits, parity, stop, timeout, buffer_size, NULL, false); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); #endif // CIRCUITPY_BUSIO_UART @@ -179,6 +179,7 @@ static busio_uart_obj_t *native_uart(mp_obj_t uart_obj) { //| def deinit(self) -> None: //| """Deinitialises the UART and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t busio_uart_obj_deinit(mp_obj_t self_in) { busio_uart_obj_t *self = native_uart(self_in); common_hal_busio_uart_deinit(self); @@ -195,18 +196,15 @@ static void check_for_deinit(busio_uart_obj_t *self) { //| def __enter__(self) -> UART: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t busio_uart_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_busio_uart_deinit(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_uart_obj___exit__); +//| +// Provided by context manager helper. // These are standard stream methods. Code is in py/stream.c. // @@ -223,6 +221,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_ //| :return: Data read //| :rtype: bytes or None""" //| ... +//| //| def readinto(self, buf: WriteableBuffer) -> Optional[int]: //| """Read bytes into the ``buf``. Read at most ``len(buf)`` bytes. @@ -232,6 +231,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_ //| //| *New in CircuitPython 4.0:* No length parameter is permitted.""" //| ... +//| //| def readline(self) -> bytes: //| """Read a line, ending in a newline character, or @@ -242,6 +242,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_ //| :return: the line read //| :rtype: bytes or None""" //| ... +//| //| def write(self, buf: ReadableBuffer) -> Optional[int]: //| """Write the buffer of bytes to the bus. @@ -251,6 +252,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(busio_uart___exit___obj, 4, 4, busio_ //| :return: the number of bytes written //| :rtype: int or None""" //| ... +//| // These three methods are used by the shared stream methods. static mp_uint_t busio_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { @@ -331,6 +333,7 @@ MP_PROPERTY_GETTER(busio_uart_in_waiting_obj, //| timeout: float //| """The current timeout, in seconds (float).""" +//| static mp_obj_t busio_uart_obj_get_timeout(mp_obj_t self_in) { busio_uart_obj_t *self = native_uart(self_in); check_for_deinit(self); @@ -357,6 +360,7 @@ MP_PROPERTY_GETSET(busio_uart_timeout_obj, //| """Discard any unread characters in the input buffer.""" //| ... //| +//| static mp_obj_t busio_uart_obj_reset_input_buffer(mp_obj_t self_in) { busio_uart_obj_t *self = native_uart(self_in); check_for_deinit(self); @@ -364,14 +368,15 @@ static mp_obj_t busio_uart_obj_reset_input_buffer(mp_obj_t self_in) { return mp_const_none; } static MP_DEFINE_CONST_FUN_OBJ_1(busio_uart_reset_input_buffer_obj, busio_uart_obj_reset_input_buffer); -//| class Parity: -//| """Enum-like class to define the parity used to verify correct data transfer.""" +//| class Parity: +//| """Enum-like class to define the parity used to verify correct data transfer.""" +//| +//| ODD: int +//| """Total number of ones should be odd.""" //| -//| ODD: int -//| """Total number of ones should be odd.""" +//| EVEN: int +//| """Total number of ones should be even.""" //| -//| EVEN: int -//| """Total number of ones should be even.""" //| const mp_obj_type_t busio_uart_parity_type; @@ -412,15 +417,15 @@ static const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&busio_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&busio_uart_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&busio_uart___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&busio_uart_reset_input_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&busio_uart_reset_input_buffer_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_baudrate), MP_ROM_PTR(&busio_uart_baudrate_obj) }, diff --git a/shared-bindings/camera/Camera.c b/shared-bindings/camera/Camera.c index a0be953222b06..f0991082e5039 100644 --- a/shared-bindings/camera/Camera.c +++ b/shared-bindings/camera/Camera.c @@ -39,11 +39,12 @@ //| def __init__(self) -> None: //| """Initialize camera.""" //| ... +//| static mp_obj_t camera_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - camera_obj_t *self = mp_obj_malloc(camera_obj_t, &camera_type); // No arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); + camera_obj_t *self = mp_obj_malloc(camera_obj_t, &camera_type); common_hal_camera_construct(self); return MP_OBJ_FROM_PTR(self); } @@ -51,6 +52,7 @@ static mp_obj_t camera_make_new(const mp_obj_type_t *type, size_t n_args, size_t //| def deinit(self) -> None: //| """De-initialize camera.""" //| ... +//| static mp_obj_t camera_obj_deinit(mp_obj_t self_in) { camera_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_camera_deinit(self); @@ -72,6 +74,7 @@ static void check_for_deinit(camera_obj_t *self) { //| :rtype: int""" //| ... //| +//| static mp_obj_t camera_obj_take_picture(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_width, ARG_height, ARG_format }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/camera/ImageFormat.c b/shared-bindings/camera/ImageFormat.c index ad436b4b39e32..86ea2741243c2 100644 --- a/shared-bindings/camera/ImageFormat.c +++ b/shared-bindings/camera/ImageFormat.c @@ -11,12 +11,14 @@ //| //| def __init__(self) -> None: //| """Enum-like class to define the image format.""" +//| //| JPG: ImageFormat //| """JPG format.""" //| //| RGB565: ImageFormat //| """RGB565 format.""" //| +//| const camera_imageformat_obj_t camera_imageformat_jpg_obj = { { &camera_imageformat_type }, diff --git a/shared-bindings/canio/CAN.c b/shared-bindings/canio/CAN.c index 82bf86dd97b2d..ff46eb26da228 100644 --- a/shared-bindings/canio/CAN.c +++ b/shared-bindings/canio/CAN.c @@ -42,6 +42,7 @@ //| :param bool auto_restart: If True, will restart communications after entering bus-off state //| """ //| ... +//| static mp_obj_t canio_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_loopback, ARG_silent, ARG_auto_restart, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -132,6 +133,7 @@ MP_PROPERTY_GETTER(canio_can_receive_error_count_obj, //| state: BusState //| """The current state of the bus. (read-only)""" +//| static mp_obj_t canio_can_state_get(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -147,6 +149,7 @@ MP_PROPERTY_GETTER(canio_can_state_obj, //| def restart(self) -> None: //| """If the device is in the bus off state, restart it.""" //| ... +//| static mp_obj_t canio_can_restart(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -187,8 +190,13 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_can_restart_obj, canio_can_restart); //| //| ESP32S2 supports one Listener. There is a single filter block, which can either match a //| standard address with mask or an extended address with mask. +//| +//| i.MX RT10xx supports one Listener and 8 filter blocks per CAN interface. +//| Each interface is fully independent from the other. A filter block can match +//| either a single address or a mask of addresses, both standard or extended. //| """ //| ... +//| static mp_obj_t canio_can_listen(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { canio_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); common_hal_canio_can_check_for_deinit(self); @@ -226,6 +234,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(canio_can_listen_obj, 1, canio_can_listen); //| loopback: bool //| """True if the device was created in loopback mode, False //| otherwise (read-only)""" +//| static mp_obj_t canio_can_loopback_get(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -242,6 +251,7 @@ MP_PROPERTY_GETTER(canio_can_loopback_obj, //| If the message could not be sent due to a full fifo or a bus error condition, RuntimeError is raised. //| """ //| ... +//| static mp_obj_t canio_can_send(mp_obj_t self_in, mp_obj_t message_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -259,6 +269,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(canio_can_send_obj, canio_can_send); //| silent: bool //| """True if the device was created in silent mode, False //| otherwise (read-only)""" +//| static mp_obj_t canio_can_silent_get(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -273,6 +284,7 @@ MP_PROPERTY_GETTER(canio_can_silent_obj, //| def deinit(self) -> None: //| """Deinitialize this object, freeing its hardware resources""" //| ... +//| static mp_obj_t canio_can_deinit(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_deinit(self); @@ -283,6 +295,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_can_deinit_obj, canio_can_deinit); //| def __enter__(self) -> CAN: //| """Returns self, to allow the object to be used in a `with` statement for resource control""" //| ... +//| static mp_obj_t canio_can_enter(mp_obj_t self_in) { canio_can_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_can_check_for_deinit(self); @@ -299,6 +312,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_can_enter_obj, canio_can_enter); //| """Calls deinit()""" //| ... //| +//| static mp_obj_t canio_can_exit(size_t num_args, const mp_obj_t args[]) { canio_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); common_hal_canio_can_deinit(self); diff --git a/shared-bindings/canio/Listener.c b/shared-bindings/canio/Listener.c index 26b5fb2cbb2ac..0fd53eecbef69 100644 --- a/shared-bindings/canio/Listener.c +++ b/shared-bindings/canio/Listener.c @@ -29,6 +29,7 @@ //| If no message is received in time, `None` is returned. Otherwise, //| a `Message` or `RemoteTransmissionRequest` is returned.""" //| ... +//| static mp_obj_t canio_listener_receive(mp_obj_t self_in) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_listener_check_for_deinit(self); @@ -47,6 +48,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_receive_obj, canio_listener_rece //| """Returns the number of messages (including remote //| transmission requests) waiting""" //| ... +//| static mp_obj_t canio_listener_in_waiting(mp_obj_t self_in) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_listener_check_for_deinit(self); @@ -70,6 +72,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_in_waiting_obj, canio_listener_i //| This method enables the `Listener` to be used as an //| iterable, for instance in a for-loop.""" //| ... +//| static mp_obj_t canio_iternext(mp_obj_t self_in) { mp_obj_t result = canio_listener_receive(self_in); if (result == mp_const_none) { @@ -81,6 +84,7 @@ static mp_obj_t canio_iternext(mp_obj_t self_in) { //| def deinit(self) -> None: //| """Deinitialize this object, freeing its hardware resources""" //| ... +//| static mp_obj_t canio_listener_deinit(mp_obj_t self_in) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_listener_deinit(self); @@ -91,6 +95,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_deinit_obj, canio_listener_deini //| def __enter__(self) -> CAN: //| """Returns self, to allow the object to be used in a `with` statement for resource control""" //| ... +//| static mp_obj_t canio_listener_enter(mp_obj_t self_in) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_listener_check_for_deinit(self); @@ -106,6 +111,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(canio_listener_enter_obj, canio_listener_enter) //| ) -> None: //| """Calls deinit()""" //| ... +//| static mp_obj_t canio_listener_exit(size_t num_args, const mp_obj_t args[]) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(args[0]); common_hal_canio_listener_deinit(self); @@ -116,6 +122,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(canio_listener_exit_obj, 4, 4, canio_ //| timeout: float //| +//| static mp_obj_t canio_listener_timeout_get(mp_obj_t self_in) { canio_listener_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_canio_listener_check_for_deinit(self); diff --git a/shared-bindings/canio/Match.c b/shared-bindings/canio/Match.c index 7594b03ee933e..e7c3dba42aab8 100644 --- a/shared-bindings/canio/Match.c +++ b/shared-bindings/canio/Match.c @@ -19,6 +19,7 @@ //| the nonzero bits in mask. Otherwise, it matches exactly the given id. //| If extended is true then only extended ids are matched, otherwise //| only standard ids are matched.""" +//| static mp_obj_t canio_match_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_mask, ARG_extended, NUM_ARGS }; @@ -46,7 +47,8 @@ static mp_obj_t canio_match_make_new(const mp_obj_type_t *type, size_t n_args, s canio_match_obj_t *self = mp_obj_malloc(canio_match_obj_t, &canio_match_type); common_hal_canio_match_construct(self, id, mask, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } //| id: int @@ -76,6 +78,7 @@ MP_PROPERTY_GETTER(canio_match_mask_obj, //| extended: bool //| """True to match extended ids, False to match standard ides""" //| +//| static mp_obj_t canio_match_extended_get(mp_obj_t self_in) { canio_match_obj_t *self = self_in; diff --git a/shared-bindings/canio/Message.c b/shared-bindings/canio/Message.c index 78665f91d2ac5..848b5b15e43cb 100644 --- a/shared-bindings/canio/Message.c +++ b/shared-bindings/canio/Message.c @@ -21,6 +21,7 @@ //| In CAN, messages can have a length from 0 to 8 bytes. //| """ //| ... +//| static mp_obj_t canio_message_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_data, ARG_extended, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -40,7 +41,8 @@ static mp_obj_t canio_message_make_new(const mp_obj_type_t *type, size_t n_args, canio_message_obj_t *self = mp_obj_malloc(canio_message_obj_t, &canio_message_type); common_hal_canio_message_construct(self, args[ARG_id].u_int, data.buf, data.len, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } //| id: int @@ -91,6 +93,7 @@ MP_PROPERTY_GETSET(canio_message_data_obj, //| extended: bool //| """True if the message's id is an extended id""" //| +//| static mp_obj_t canio_message_extended_get(const mp_obj_t self_in) { canio_message_obj_t *self = self_in; return mp_obj_new_bool(common_hal_canio_message_get_extended(self)); diff --git a/shared-bindings/canio/RemoteTransmissionRequest.c b/shared-bindings/canio/RemoteTransmissionRequest.c index ba936b9a94946..bdc91c494a4a3 100644 --- a/shared-bindings/canio/RemoteTransmissionRequest.c +++ b/shared-bindings/canio/RemoteTransmissionRequest.c @@ -21,6 +21,7 @@ //| In CAN, messages can have a length from 0 to 8 bytes. //| """ //| ... +//| static mp_obj_t canio_remote_transmission_request_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_id, ARG_length, ARG_extended, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -41,7 +42,8 @@ static mp_obj_t canio_remote_transmission_request_make_new(const mp_obj_type_t * canio_remote_transmission_request_obj_t *self = mp_obj_malloc(canio_remote_transmission_request_obj_t, &canio_remote_transmission_request_type); common_hal_canio_remote_transmission_request_construct(self, args[ARG_id].u_int, length, args[ARG_extended].u_bool); - return self; + + return MP_OBJ_FROM_PTR(self); } @@ -87,6 +89,7 @@ MP_PROPERTY_GETSET(canio_remote_transmission_request_extended_obj, //| length: int //| """The length of the requested message.""" //| +//| static mp_obj_t canio_remote_transmission_request_length_get(const mp_obj_t self_in) { canio_remote_transmission_request_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT(common_hal_canio_remote_transmission_request_get_length(self)); diff --git a/shared-bindings/canio/__init__.c b/shared-bindings/canio/__init__.c index 991d37c8d2566..2300a6652dd6b 100644 --- a/shared-bindings/canio/__init__.c +++ b/shared-bindings/canio/__init__.c @@ -36,12 +36,13 @@ //| //| Other implementations of the CAN device may exist (for instance, attached //| via an SPI bus). If so their constructor arguments may differ, but -//| otherwise we encourage implementors to follow the API that the core uses. +//| otherwise we encourage implementers to follow the API that the core uses. //| //| For more information on working with this module, refer to //| `this Learn Guide on using it `_. //| """ //| +//| #include "py/obj.h" #include "py/enum.h" @@ -81,6 +82,7 @@ MAKE_ENUM_VALUE(canio_bus_state_type, bus_state, BUS_OFF, BUS_STATE_OFF); //| occurred recently. It must be restarted before it will send or receive //| packets. This device will neither send or acknowledge packets on the bus.""" //| +//| MAKE_ENUM_MAP(canio_bus_state) { MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_ACTIVE), MAKE_ENUM_MAP_ENTRY(bus_state, ERROR_PASSIVE), diff --git a/shared-bindings/codeop/__init__.c b/shared-bindings/codeop/__init__.c index 4ddd792be6637..dd675f551edb2 100644 --- a/shared-bindings/codeop/__init__.c +++ b/shared-bindings/codeop/__init__.c @@ -16,8 +16,13 @@ static const char *get_arg_str(mp_obj_t arg, qstr name) { //| """Utilities to compile possibly incomplete Python source code.""" //| +//| from types import CodeType +//| +//| -//| def compile_command(source: str, filename: str = "", symbol: str = "single"): +//| def compile_command( +//| source: str, filename: str = "", symbol: str = "single" +//| ) -> CodeType: //| """Compile a command and determine whether it is incomplete //| //| The 'completeness' determination is slightly different than in standard Python @@ -25,6 +30,7 @@ static const char *get_arg_str(mp_obj_t arg, qstr name) { //| In particular, it's important that the code not end with a newline character //| or it is likely to be treated as a complete command.""" //| +//| static mp_obj_t compile_command(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_source, ARG_filename, ARG_symbol }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/countio/Counter.c b/shared-bindings/countio/Counter.c index 5fa2a7a30fa22..9f8bd00645ce5 100644 --- a/shared-bindings/countio/Counter.c +++ b/shared-bindings/countio/Counter.c @@ -23,7 +23,7 @@ //| pin: microcontroller.Pin, //| *, //| edge: Edge = Edge.FALL, -//| pull: Optional[digitalio.Pull] = None +//| pull: Optional[digitalio.Pull] = None, //| ) -> None: //| """Create a Counter object associated with the given pin that counts //| rising- and/or falling-edge transitions. At least one of ``rise`` and ``fall`` must be True. @@ -52,6 +52,7 @@ //| See the pin assignments for your board to see which pins can be used. //| """ //| ... +//| static mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pin, ARG_edge, ARG_pull }; static const mp_arg_t allowed_args[] = { @@ -65,9 +66,8 @@ static mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_arg const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); const countio_edge_t edge = validate_edge(args[ARG_edge].u_obj, MP_QSTR_edge); const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); - countio_counter_obj_t *self = m_new_obj_with_finaliser(countio_counter_obj_t); - self->base.type = &countio_counter_type; + countio_counter_obj_t *self = mp_obj_malloc_with_finaliser(countio_counter_obj_t, &countio_counter_type); common_hal_countio_counter_construct(self, pin, edge, pull); return MP_OBJ_FROM_PTR(self); @@ -75,6 +75,7 @@ static mp_obj_t countio_counter_make_new(const mp_obj_type_t *type, size_t n_arg //| def deinit(self) -> None: //| """Deinitializes the Counter and releases any hardware resources for reuse.""" +//| static mp_obj_t countio_counter_deinit(mp_obj_t self_in) { countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_countio_counter_deinit(self); @@ -90,21 +91,19 @@ static void check_for_deinit(countio_counter_obj_t *self) { //| def __enter__(self) -> Counter: //| """No-op used by Context Managers.""" +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" -static mp_obj_t countio_counter_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_countio_counter_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(countio_counter___exit___obj, 4, 4, countio_counter_obj___exit__); +//| +// Provided by context manager helper. //| count: int //| """The current count in terms of pulses.""" +//| static mp_obj_t countio_counter_obj_get_count(mp_obj_t self_in) { countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -129,6 +128,7 @@ MP_PROPERTY_GETSET(countio_counter_count_obj, //| def reset(self) -> None: //| """Resets the count back to 0.""" //| +//| static mp_obj_t countio_counter_reset(mp_obj_t self_in) { countio_counter_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -144,7 +144,7 @@ static const mp_rom_map_elem_t countio_counter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&countio_counter_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&countio_counter_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&countio_counter___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&countio_counter_count_obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&countio_counter_reset_obj) }, }; diff --git a/shared-bindings/countio/Edge.c b/shared-bindings/countio/Edge.c index b7ec25078aeee..9ace6a923ffbb 100644 --- a/shared-bindings/countio/Edge.c +++ b/shared-bindings/countio/Edge.c @@ -20,6 +20,7 @@ MAKE_ENUM_VALUE(countio_edge_type, edge, RISE_AND_FALL, EDGE_RISE_AND_FALL); //| def __init__(self) -> None: //| """Enum-like class to define which signal transitions to count.""" //| ... +//| //| RISE: Edge //| """Count the rising edges.""" //| @@ -32,6 +33,7 @@ MAKE_ENUM_VALUE(countio_edge_type, edge, RISE_AND_FALL, EDGE_RISE_AND_FALL); //| **Limitations:** ``RISE_AND_FALL`` is not available to RP2040 due to hardware limitations. //| """ //| +//| MAKE_ENUM_MAP(countio_edge) { MAKE_ENUM_MAP_ENTRY(edge, RISE), MAKE_ENUM_MAP_ENTRY(edge, FALL), diff --git a/shared-bindings/digitalio/DigitalInOut.c b/shared-bindings/digitalio/DigitalInOut.c index 6bbdc68be5233..58f90b0b1419f 100644 --- a/shared-bindings/digitalio/DigitalInOut.c +++ b/shared-bindings/digitalio/DigitalInOut.c @@ -17,6 +17,7 @@ #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" #include "shared-bindings/digitalio/Direction.h" #include "shared-bindings/digitalio/DriveMode.h" #include "shared-bindings/digitalio/Pull.h" @@ -65,13 +66,14 @@ MP_WEAK const mcu_pin_obj_t *common_hal_digitalio_validate_pin(mp_obj_t obj) { //| //| :param ~microcontroller.Pin pin: The pin to control""" //| ... +//| static mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - digitalio_digitalinout_obj_t *self = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); - const mcu_pin_obj_t *pin = common_hal_digitalio_validate_pin(args[0]); + + digitalio_digitalinout_obj_t *self = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(self, pin); return MP_OBJ_FROM_PTR(self); @@ -80,6 +82,7 @@ static mp_obj_t digitalio_digitalinout_make_new(const mp_obj_type_t *type, //| def deinit(self) -> None: //| """Turn off the DigitalInOut and release the pin for other use.""" //| ... +//| static mp_obj_t digitalio_digitalinout_obj_deinit(mp_obj_t self_in) { digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_digitalio_digitalinout_deinit(self); @@ -90,18 +93,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_deinit_obj, digitalio_digitalin //| def __enter__(self) -> DigitalInOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t digitalio_digitalinout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_digitalio_digitalinout_deinit(MP_OBJ_TO_PTR(args[0])); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(digitalio_digitalinout_obj___exit___obj, 4, 4, digitalio_digitalinout_obj___exit__); +//| +// Provided by context manager helper. static inline void check_for_deinit(digitalio_digitalinout_obj_t *self) { if (common_hal_digitalio_digitalinout_deinited(self)) { @@ -119,6 +119,7 @@ static inline void check_for_deinit(digitalio_digitalinout_obj_t *self) { //| :param ~digitalio.DriveMode drive_mode: drive mode for the output //| """ //| ... +//| static mp_obj_t digitalio_digitalinout_switch_to_output(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_value, ARG_drive_mode }; static const mp_arg_t allowed_args[] = { @@ -156,6 +157,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(digitalio_digitalinout_switch_to_output_obj, 1, digit //| switch.pull = digitalio.Pull.UP //| print(switch.value)""" //| ... +//| static mp_obj_t digitalio_digitalinout_switch_to_input(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_pull }; static const mp_arg_t allowed_args[] = { @@ -189,9 +191,9 @@ static mp_obj_t digitalio_digitalinout_obj_get_direction(mp_obj_t self_in) { check_for_deinit(self); digitalio_direction_t direction = common_hal_digitalio_digitalinout_get_direction(self); if (direction == DIRECTION_INPUT) { - return (mp_obj_t)&digitalio_direction_input_obj; + return MP_OBJ_FROM_PTR(&digitalio_direction_input_obj); } - return (mp_obj_t)&digitalio_direction_output_obj; + return MP_OBJ_FROM_PTR(&digitalio_direction_output_obj); } MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_direction_obj, digitalio_digitalinout_obj_get_direction); @@ -253,9 +255,9 @@ static mp_obj_t digitalio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) { } digitalio_drive_mode_t drive_mode = common_hal_digitalio_digitalinout_get_drive_mode(self); if (drive_mode == DRIVE_MODE_PUSH_PULL) { - return (mp_obj_t)&digitalio_drive_mode_push_pull_obj; + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_push_pull_obj); } - return (mp_obj_t)&digitalio_drive_mode_open_drain_obj; + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_open_drain_obj); } MP_DEFINE_CONST_FUN_OBJ_1(digitalio_digitalinout_get_drive_mode_obj, digitalio_digitalinout_obj_get_drive_mode); @@ -288,6 +290,7 @@ MP_PROPERTY_GETSET(digitalio_digitalio_drive_mode_obj, //| //| :raises AttributeError: if `direction` is :py:data:`~digitalio.Direction.OUTPUT`.""" //| +//| static mp_obj_t digitalio_digitalinout_obj_get_pull(mp_obj_t self_in) { digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -326,7 +329,7 @@ static const mp_rom_map_elem_t digitalio_digitalinout_locals_dict_table[] = { // instance methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&digitalio_digitalinout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&digitalio_digitalinout_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_switch_to_output), MP_ROM_PTR(&digitalio_digitalinout_switch_to_output_obj) }, { MP_ROM_QSTR(MP_QSTR_switch_to_input), MP_ROM_PTR(&digitalio_digitalinout_switch_to_input_obj) }, @@ -339,12 +342,91 @@ static const mp_rom_map_elem_t digitalio_digitalinout_locals_dict_table[] = { static MP_DEFINE_CONST_DICT(digitalio_digitalinout_locals_dict, digitalio_digitalinout_locals_dict_table); +// Protocol implementation - thin wrappers to match protocol signature +void digitalinout_deinit(mp_obj_t self_in) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_digitalio_digitalinout_deinit(self); +} + +bool digitalinout_deinited(mp_obj_t self_in) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_deinited(self); +} + +digitalinout_result_t digitalinout_switch_to_input(mp_obj_t self_in, digitalio_pull_t pull) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_switch_to_input(self, pull); +} + +digitalinout_result_t digitalinout_switch_to_output(mp_obj_t self_in, bool value, digitalio_drive_mode_t drive_mode) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_switch_to_output(self, value, drive_mode); +} + +digitalio_direction_t digitalinout_get_direction(mp_obj_t self_in) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_get_direction(self); +} + +mp_negative_errno_t digitalinout_set_value(mp_obj_t self_in, bool value) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_digitalio_digitalinout_set_value(self, value); + return 0; +} + +mp_negative_errno_t digitalinout_get_value(mp_obj_t self_in, bool *value) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + *value = common_hal_digitalio_digitalinout_get_value(self); + return 0; +} + +digitalinout_result_t digitalinout_set_drive_mode(mp_obj_t self_in, digitalio_drive_mode_t drive_mode) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_set_drive_mode(self, drive_mode); +} + +digitalio_drive_mode_t digitalinout_get_drive_mode(mp_obj_t self_in) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_get_drive_mode(self); +} + +digitalinout_result_t digitalinout_set_pull(mp_obj_t self_in, digitalio_pull_t pull) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_set_pull(self, pull); +} + +digitalio_pull_t digitalinout_get_pull(mp_obj_t self_in) { + digitalio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_digitalio_digitalinout_get_pull(self); +} + +#if CIRCUITPY_DIGITALINOUT_PROTOCOL +static const digitalinout_p_t digitalinout_digitalinout_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_DigitalInOut) + .deinit = digitalinout_deinit, + .deinited = digitalinout_deinited, + .switch_to_input = digitalinout_switch_to_input, + .switch_to_output = digitalinout_switch_to_output, + .get_direction = digitalinout_get_direction, + .get_value = digitalinout_get_value, + .set_value = digitalinout_set_value, + .get_drive_mode = digitalinout_get_drive_mode, + .set_drive_mode = digitalinout_set_drive_mode, + .get_pull = digitalinout_get_pull, + .set_pull = digitalinout_set_pull, +}; +#endif + MP_DEFINE_CONST_OBJ_TYPE( digitalio_digitalinout_type, MP_QSTR_DigitalInOut, MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, make_new, digitalio_digitalinout_make_new, locals_dict, &digitalio_digitalinout_locals_dict + #if CIRCUITPY_DIGITALINOUT_PROTOCOL + , + protocol, &digitalinout_digitalinout_proto + #endif ); // Helper for validating digitalio.DigitalInOut arguments diff --git a/shared-bindings/digitalio/DigitalInOut.h b/shared-bindings/digitalio/DigitalInOut.h index f030e27a60b98..8d3fe8c00a2c5 100644 --- a/shared-bindings/digitalio/DigitalInOut.h +++ b/shared-bindings/digitalio/DigitalInOut.h @@ -28,6 +28,9 @@ typedef enum { #endif } digitalinout_result_t; +// Include protocol after types are defined +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" + typedef enum { DIGITALINOUT_REG_READ, DIGITALINOUT_REG_WRITE, @@ -54,3 +57,16 @@ digitalio_digitalinout_obj_t *assert_digitalinout(mp_obj_t obj); volatile uint32_t *common_hal_digitalio_digitalinout_get_reg(digitalio_digitalinout_obj_t *self, digitalinout_reg_op_t op, uint32_t *mask); bool common_hal_digitalio_has_reg_op(digitalinout_reg_op_t op); + +// Protocol wrapper functions - always available for direct calls +void digitalinout_deinit(mp_obj_t self_in); +bool digitalinout_deinited(mp_obj_t self_in); +digitalinout_result_t digitalinout_switch_to_input(mp_obj_t self_in, digitalio_pull_t pull); +digitalinout_result_t digitalinout_switch_to_output(mp_obj_t self_in, bool value, digitalio_drive_mode_t drive_mode); +digitalio_direction_t digitalinout_get_direction(mp_obj_t self_in); +mp_negative_errno_t digitalinout_set_value(mp_obj_t self_in, bool value); +mp_negative_errno_t digitalinout_get_value(mp_obj_t self_in, bool *value); +digitalinout_result_t digitalinout_set_drive_mode(mp_obj_t self_in, digitalio_drive_mode_t drive_mode); +digitalio_drive_mode_t digitalinout_get_drive_mode(mp_obj_t self_in); +digitalinout_result_t digitalinout_set_pull(mp_obj_t self_in, digitalio_pull_t pull); +digitalio_pull_t digitalinout_get_pull(mp_obj_t self_in); diff --git a/shared-bindings/digitalio/DigitalInOutProtocol.c b/shared-bindings/digitalio/DigitalInOutProtocol.c new file mode 100644 index 0000000000000..48b428ad46336 --- /dev/null +++ b/shared-bindings/digitalio/DigitalInOutProtocol.c @@ -0,0 +1,397 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" + +#include "py/obj.h" +#include "py/objtype.h" +#include "py/proto.h" +#include "py/runtime.h" +#include "py/nlr.h" +#include "py/gc.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/digitalio/Pull.h" +#include "shared-bindings/util.h" +#include "supervisor/port_heap.h" + +//| from typing import Protocol, Optional +//| +//| class DigitalInOutProtocol(Protocol): +//| """Protocol for digital input/output pin control. +//| +//| Any object that implements this protocol can be used as a digital pin, +//| providing compatibility with code expecting a `digitalio.DigitalInOut`. +//| """ +//| +//| def deinit(self) -> None: +//| """Deinitialize the pin and release hardware resources.""" +//| ... +//| +//| def deinited(self) -> bool: +//| """Check whether the pin has been deinitialized. +//| +//| :return: True if deinitialized, False otherwise +//| """ +//| ... +//| +//| def switch_to_input(self, pull: Optional[digitalio.Pull] = None) -> None: +//| """Configure the pin as a digital input. +//| +//| :param pull: Pull resistor configuration (UP, DOWN, or None) +//| """ +//| ... +//| +//| def switch_to_output( +//| self, +//| value: bool = False, +//| drive_mode: digitalio.DriveMode = digitalio.DriveMode.PUSH_PULL +//| ) -> None: +//| """Configure the pin as a digital output. +//| +//| :param value: Initial output value (default False) +//| :param drive_mode: Output drive mode (PUSH_PULL or OPEN_DRAIN) +//| """ +//| ... +//| +//| @property +//| def direction(self) -> digitalio.Direction: +//| """The pin direction (INPUT or OUTPUT).""" +//| ... +//| +//| @direction.setter +//| def direction(self, value: digitalio.Direction) -> None: +//| ... +//| +//| @property +//| def value(self) -> bool: +//| """The digital logic level of the pin.""" +//| ... +//| +//| @value.setter +//| def value(self, val: bool) -> None: +//| ... +//| +//| @property +//| def pull(self) -> Optional[digitalio.Pull]: +//| """The pull resistor configuration for inputs (UP, DOWN, or None).""" +//| ... +//| +//| @pull.setter +//| def pull(self, pul: Optional[digitalio.Pull]) -> None: +//| ... +//| +//| @property +//| def drive_mode(self) -> digitalio.DriveMode: +//| """The drive mode for outputs (PUSH_PULL or OPEN_DRAIN).""" +//| ... +//| +//| @drive_mode.setter +//| def drive_mode(self, mode: digitalio.DriveMode) -> None: +//| ... +//| +// C Implementation Notes: +// ----------------------- +// For C implementations, define a digitalinout_p_t protocol structure and assign it +// to your type's protocol field in MP_DEFINE_CONST_OBJ_TYPE. +// +// Example: +// static const digitalinout_p_t my_type_proto = { +// MP_PROTO_IMPLEMENT(MP_QSTR_DigitalInOut) +// .construct = my_construct_func, +// .deinit = my_deinit_func, +// .deinited = my_deinited_func, +// .switch_to_input = my_switch_to_input_func, +// .switch_to_output = my_switch_to_output_func, +// .get_direction = my_get_direction_func, +// .get_value = my_get_value_func, +// .set_value = my_set_value_func, +// .get_drive_mode = my_get_drive_mode_func, +// .set_drive_mode = my_set_drive_mode_func, +// .get_pull = my_get_pull_func, +// .set_pull = my_set_pull_func, +// }; +// +// MP_DEFINE_CONST_OBJ_TYPE( +// my_type, +// MP_QSTR_MyType, +// MP_TYPE_FLAG_NONE, +// make_new, my_make_new, +// protocol, &my_type_proto +// ); +// +// See shared-bindings/digitalio/DigitalInOut.c for a complete example. +// + +#if CIRCUITPY_DIGITALINOUT_PROTOCOL +static void check_object_has_method(mp_obj_t obj, qstr method_name) { + mp_obj_t dest[2]; + mp_load_method_protected(obj, method_name, dest, true); + if (dest[0] == MP_OBJ_NULL) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("%q object missing '%q' method"), MP_OBJ_TO_PTR(obj), method_name); + } +} + +static void check_object_has_attr(mp_obj_t obj, qstr attr_name) { + mp_obj_t dest[2]; + mp_load_method_protected(obj, attr_name, dest, true); + if (dest[0] == MP_OBJ_NULL) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("%q object missing '%q' attribute"), MP_OBJ_TO_PTR(obj), attr_name); + } +} +#endif + +mp_obj_t digitalinout_protocol_from_pin( + mp_obj_t pin_or_dio, + qstr arg_name, + bool allow_none, + bool use_port_allocation, + bool *out_owns_pin) { + + *out_owns_pin = false; + + // Handle None case + if (allow_none && pin_or_dio == mp_const_none) { + return mp_const_none; + } + + // Check if it's a Pin + if (mp_obj_is_type(pin_or_dio, &mcu_pin_type)) { + // Validate the pin is free + const mcu_pin_obj_t *pin; + if (allow_none) { + pin = validate_obj_is_free_pin_or_none(pin_or_dio, arg_name); + if (pin == NULL) { + return mp_const_none; + } + } else { + pin = validate_obj_is_free_pin(pin_or_dio, arg_name); + } + + // Allocate and construct a DigitalInOut object + // Use port_malloc if GC is not available or if forced + digitalio_digitalinout_obj_t *dio; + if (use_port_allocation) { + dio = port_malloc(sizeof(digitalio_digitalinout_obj_t), false); + } else { + dio = m_malloc(sizeof(digitalio_digitalinout_obj_t)); + } + dio->base.type = &digitalio_digitalinout_type; + mp_obj_t dio_obj = MP_OBJ_FROM_PTR(dio); + *out_owns_pin = true; + + digitalinout_result_t result = common_hal_digitalio_digitalinout_construct(dio_obj, pin); + if (result != DIGITALINOUT_OK) { + // Free the allocation on error + if (use_port_allocation) { + port_free(dio); + } + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q init failed"), arg_name); + } + return dio_obj; + } + + #if CIRCUITPY_DIGITALINOUT_PROTOCOL + // Check if it natively implements the DigitalInOutProtocol + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, pin_or_dio); + if (proto != NULL) { + // Native protocol support - use it directly + return pin_or_dio; + } + + // Verify the object has the required methods/attributes + check_object_has_method(pin_or_dio, MP_QSTR_deinit); + check_object_has_method(pin_or_dio, MP_QSTR_switch_to_input); + check_object_has_method(pin_or_dio, MP_QSTR_switch_to_output); + check_object_has_attr(pin_or_dio, MP_QSTR_deinited); + check_object_has_attr(pin_or_dio, MP_QSTR_direction); + check_object_has_attr(pin_or_dio, MP_QSTR_value); + check_object_has_attr(pin_or_dio, MP_QSTR_drive_mode); + check_object_has_attr(pin_or_dio, MP_QSTR_pull); + + // Object has all required attributes - use it as DigitalInOutProtocol + return pin_or_dio; + #else + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object does not support '%q'"), + mp_obj_get_type_qstr(pin_or_dio), MP_QSTR_DigitalInOut); + #endif +} + +// These functions are only used when CIRCUITPY_DIGITALINOUT_PROTOCOL is enabled. +// Otherwise, the digitalinout_* functions are called directly. +#if CIRCUITPY_DIGITALINOUT_PROTOCOL +void digitalinout_protocol_deinit(mp_obj_t self) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_protocol_digitalinout, self); + if (proto && proto->deinit) { + proto->deinit(self); + return; + } + + // Fallback to Python method call + mp_obj_t dest[2]; + mp_load_method_maybe(self, MP_QSTR_deinit, dest); + if (dest[0] != MP_OBJ_NULL) { + mp_call_method_n_kw(0, 0, dest); + return; + } +} + +bool digitalinout_protocol_deinited(mp_obj_t self) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->deinited) { + return proto->deinited(self); + } + + // Try as attribute + mp_obj_t attr = mp_load_attr(self, MP_QSTR_deinited); + return mp_obj_is_true(attr); +} + +digitalinout_result_t digitalinout_protocol_switch_to_input(mp_obj_t self, digitalio_pull_t pull) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->switch_to_input) { + return proto->switch_to_input(self, pull); + } + + // Fallback to Python method call + mp_obj_t dest[3]; + mp_load_method_maybe(self, MP_QSTR_switch_to_input, dest); + if (dest[0] != MP_OBJ_NULL) { + mp_obj_t pull_obj = mp_const_none; + if (pull == PULL_UP) { + pull_obj = MP_OBJ_FROM_PTR(&digitalio_pull_up_obj); + } else if (pull == PULL_DOWN) { + pull_obj = MP_OBJ_FROM_PTR(&digitalio_pull_down_obj); + } + dest[2] = pull_obj; + mp_call_method_n_kw(1, 0, dest); + return DIGITALINOUT_OK; + } + + return DIGITALINOUT_PIN_BUSY; +} + +digitalinout_result_t digitalinout_protocol_switch_to_output(mp_obj_t self, bool value, digitalio_drive_mode_t drive_mode) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->switch_to_output) { + return proto->switch_to_output(self, value, drive_mode); + } + + // Fallback to Python method call + mp_obj_t dest[4]; + mp_load_method_maybe(self, MP_QSTR_switch_to_output, dest); + if (dest[0] != MP_OBJ_NULL) { + dest[2] = mp_obj_new_bool(value); + dest[3] = (drive_mode == DRIVE_MODE_PUSH_PULL) ? + MP_OBJ_FROM_PTR(&digitalio_drive_mode_push_pull_obj) : + MP_OBJ_FROM_PTR(&digitalio_drive_mode_open_drain_obj); + mp_call_method_n_kw(2, 0, dest); + return DIGITALINOUT_OK; + } + + mp_raise_TypeError(MP_ERROR_TEXT("object does not support DigitalInOut protocol")); +} + +digitalio_direction_t digitalinout_protocol_get_direction(mp_obj_t self) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->get_direction) { + return proto->get_direction(self); + } + + // Fallback to Python attribute access + mp_obj_t direction = mp_load_attr(self, MP_QSTR_direction); + if (direction == MP_ROM_PTR(&digitalio_direction_input_obj)) { + return DIRECTION_INPUT; + } + return DIRECTION_OUTPUT; +} + +mp_negative_errno_t digitalinout_protocol_set_value(mp_obj_t self, bool value) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->set_value) { + return proto->set_value(self, value); + } + + // Fallback to Python attribute assignment + mp_store_attr(self, MP_QSTR_value, mp_obj_new_bool(value)); + return 0; +} + +mp_negative_errno_t digitalinout_protocol_get_value(mp_obj_t self, bool *value) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->get_value) { + return proto->get_value(self, value); + } + + // Fallback to Python attribute access + *value = mp_obj_is_true(mp_load_attr(self, MP_QSTR_value)); + return 0; +} + +digitalinout_result_t digitalinout_protocol_set_drive_mode(mp_obj_t self, digitalio_drive_mode_t drive_mode) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->set_drive_mode) { + return proto->set_drive_mode(self, drive_mode); + } + + // Fallback to Python attribute assignment + mp_obj_t drive_mode_obj = (drive_mode == DRIVE_MODE_PUSH_PULL) ? + MP_OBJ_FROM_PTR(&digitalio_drive_mode_push_pull_obj) : + MP_OBJ_FROM_PTR(&digitalio_drive_mode_open_drain_obj); + mp_store_attr(self, MP_QSTR_drive_mode, drive_mode_obj); + return DIGITALINOUT_OK; +} + +digitalio_drive_mode_t digitalinout_protocol_get_drive_mode(mp_obj_t self) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->get_drive_mode) { + return proto->get_drive_mode(self); + } + + // Fallback to Python attribute access + mp_obj_t drive_mode = mp_load_attr(self, MP_QSTR_drive_mode); + if (drive_mode == MP_ROM_PTR(&digitalio_drive_mode_open_drain_obj)) { + return DRIVE_MODE_OPEN_DRAIN; + } + return DRIVE_MODE_PUSH_PULL; +} + +digitalinout_result_t digitalinout_protocol_set_pull(mp_obj_t self, digitalio_pull_t pull) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->set_pull) { + return proto->set_pull(self, pull); + } + + // Fallback to Python attribute assignment + mp_obj_t pull_obj = mp_const_none; + if (pull == PULL_UP) { + pull_obj = MP_OBJ_FROM_PTR(&digitalio_pull_up_obj); + } else if (pull == PULL_DOWN) { + pull_obj = MP_OBJ_FROM_PTR(&digitalio_pull_down_obj); + } + mp_store_attr(self, MP_QSTR_pull, pull_obj); + return DIGITALINOUT_OK; +} + +digitalio_pull_t digitalinout_protocol_get_pull(mp_obj_t self) { + const digitalinout_p_t *proto = mp_proto_get(MP_QSTR_DigitalInOut, self); + if (proto && proto->get_pull) { + return proto->get_pull(self); + } + + // Fallback to Python attribute access + mp_obj_t pull = mp_load_attr(self, MP_QSTR_pull); + if (pull == MP_OBJ_FROM_PTR(&digitalio_pull_up_obj)) { + return PULL_UP; + } else if (pull == MP_OBJ_FROM_PTR(&digitalio_pull_down_obj)) { + return PULL_DOWN; + } + return PULL_NONE; +} + +#endif // CIRCUITPY_DIGITALINOUT_PROTOCOL diff --git a/shared-bindings/digitalio/DigitalInOutProtocol.h b/shared-bindings/digitalio/DigitalInOutProtocol.h new file mode 100644 index 0000000000000..6cb92a3735f33 --- /dev/null +++ b/shared-bindings/digitalio/DigitalInOutProtocol.h @@ -0,0 +1,83 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "py/proto.h" +#include "py/mperrno.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/digitalio/Pull.h" + +// Protocol structure for DigitalInOut implementations +// Note: mcu_pin_obj_t and digitalinout_result_t are defined by files that include this header +typedef struct _digitalinout_p_t { + MP_PROTOCOL_HEAD // MP_QSTR_DigitalInOut + void (*deinit)(mp_obj_t self); + bool (*deinited)(mp_obj_t self); + digitalinout_result_t (*switch_to_input)(mp_obj_t self, digitalio_pull_t pull); + digitalinout_result_t (*switch_to_output)(mp_obj_t self, bool value, digitalio_drive_mode_t drive_mode); + digitalio_direction_t (*get_direction)(mp_obj_t self); + mp_negative_errno_t (*set_value)(mp_obj_t self, bool value); // Return 0 if ok + mp_negative_errno_t (*get_value)(mp_obj_t self, bool *value); // Return 0 if ok + digitalinout_result_t (*set_drive_mode)(mp_obj_t self, digitalio_drive_mode_t drive_mode); + digitalio_drive_mode_t (*get_drive_mode)(mp_obj_t self); + digitalinout_result_t (*set_pull)(mp_obj_t self, digitalio_pull_t pull); + digitalio_pull_t (*get_pull)(mp_obj_t self); +} digitalinout_p_t; + +// Protocol helper functions +// These functions work with any object that implements the DigitalInOut protocol, +// either through native C protocol or Python attributes/methods. + +// Converts a Pin or DigitalInOutProtocol to a DigitalInOutProtocol object. +// If pin_or_dio is a Pin, allocates and initializes a DigitalInOut object. +// If pin_or_dio is already a DigitalInOutProtocol, returns it directly. +// If allow_none is true and pin_or_dio is None, returns None. +// If force_port_allocation is true, uses port_malloc instead of GC allocation. +// Sets *out_owns_pin to true if a new DigitalInOut was allocated (caller must deinit and free). +// Returns the DigitalInOutProtocol object to use. +// Raises an exception on error. +// Note: To free allocated objects, deinit first, then use gc_ptr_on_heap() to determine +// if port_free() should be called (if not on heap) or let GC handle it (if on heap). +mp_obj_t digitalinout_protocol_from_pin( + mp_obj_t pin_or_dio, + qstr arg_name, + bool allow_none, + bool force_port_allocation, + bool *out_owns_pin); + +#if CIRCUITPY_DIGITALINOUT_PROTOCOL +// Protocol helper functions that do protocol lookup or Python fallback +void digitalinout_protocol_deinit(mp_obj_t self); +bool digitalinout_protocol_deinited(mp_obj_t self); +digitalinout_result_t digitalinout_protocol_switch_to_input(mp_obj_t self, digitalio_pull_t pull); +digitalinout_result_t digitalinout_protocol_switch_to_output(mp_obj_t self, bool value, digitalio_drive_mode_t drive_mode); +digitalio_direction_t digitalinout_protocol_get_direction(mp_obj_t self); +mp_negative_errno_t digitalinout_protocol_set_value(mp_obj_t self, bool value); +mp_negative_errno_t digitalinout_protocol_get_value(mp_obj_t self, bool *value); +digitalinout_result_t digitalinout_protocol_set_drive_mode(mp_obj_t self, digitalio_drive_mode_t drive_mode); +digitalio_drive_mode_t digitalinout_protocol_get_drive_mode(mp_obj_t self); +digitalinout_result_t digitalinout_protocol_set_pull(mp_obj_t self, digitalio_pull_t pull); +digitalio_pull_t digitalinout_protocol_get_pull(mp_obj_t self); +#else +// When protocol is disabled, map directly to native DigitalInOut functions +#define digitalinout_protocol_deinit digitalinout_deinit +#define digitalinout_protocol_deinited digitalinout_deinited +#define digitalinout_protocol_switch_to_input digitalinout_switch_to_input +#define digitalinout_protocol_switch_to_output digitalinout_switch_to_output +#define digitalinout_protocol_get_direction digitalinout_get_direction +#define digitalinout_protocol_set_value digitalinout_set_value +#define digitalinout_protocol_get_value digitalinout_get_value +#define digitalinout_protocol_set_drive_mode digitalinout_set_drive_mode +#define digitalinout_protocol_get_drive_mode digitalinout_get_drive_mode +#define digitalinout_protocol_set_pull digitalinout_set_pull +#define digitalinout_protocol_get_pull digitalinout_get_pull +#endif diff --git a/shared-bindings/digitalio/Direction.c b/shared-bindings/digitalio/Direction.c index 442d2dcd35992..35c3660035473 100644 --- a/shared-bindings/digitalio/Direction.c +++ b/shared-bindings/digitalio/Direction.c @@ -25,12 +25,14 @@ //| """Enum-like class to define which direction the digital values are //| going.""" //| ... +//| //| INPUT: Direction //| """Read digital data in""" //| //| OUTPUT: Direction //| """Write digital data out""" //| +//| const mp_obj_type_t digitalio_direction_type; const digitalio_direction_obj_t digitalio_direction_input_obj = { diff --git a/shared-bindings/digitalio/DriveMode.c b/shared-bindings/digitalio/DriveMode.c index 78ced01df2510..5fbee20526c74 100644 --- a/shared-bindings/digitalio/DriveMode.c +++ b/shared-bindings/digitalio/DriveMode.c @@ -13,6 +13,7 @@ //| """Enum-like class to define the drive mode used when outputting //| digital values.""" //| ... +//| //| PUSH_PULL: DriveMode //| """Output both high and low digital values""" //| @@ -20,6 +21,7 @@ //| """Output low digital values but go into high z for digital high. This is //| useful for i2c and other protocols that share a digital line.""" //| +//| const mp_obj_type_t digitalio_drive_mode_type; const digitalio_drive_mode_obj_t digitalio_drive_mode_push_pull_obj = { diff --git a/shared-bindings/digitalio/Pull.c b/shared-bindings/digitalio/Pull.c index 7a02564354a10..6886699d12794 100644 --- a/shared-bindings/digitalio/Pull.c +++ b/shared-bindings/digitalio/Pull.c @@ -14,6 +14,7 @@ //| """Enum-like class to define the pull value, if any, used while reading //| digital values in.""" //| ... +//| //| UP: Pull //| """When the input line isn't being driven the pull up can pull the state //| of the line high so it reads as true.""" @@ -22,6 +23,7 @@ //| """When the input line isn't being driven the pull down can pull the //| state of the line low so it reads as false.""" //| +//| const mp_obj_type_t digitalio_pull_type; const digitalio_pull_obj_t digitalio_pull_up_obj = { diff --git a/shared-bindings/digitalio/__init__.c b/shared-bindings/digitalio/__init__.c index d241bbe0ebbe6..0d3b6365f1f34 100644 --- a/shared-bindings/digitalio/__init__.c +++ b/shared-bindings/digitalio/__init__.c @@ -58,6 +58,27 @@ //| //| For more information on using `digitalio`, see `this additional Learn guide //| `_ +//| +//| .. warning:: `digitalio.DigitalInOut` on Raspberry Pi RP2350 A2 stepping has some limitations +//| due to a GPIO hardware issue that causes excessive leakage current (~120uA). +//| A pin can read as high even when driven or pulled low, if the input signal is high +//| impedance or if an attached pull-down resistor is too weak (has too high a value). +//| +//| To prevent this problem, drive the the input pin with a strong signal that can overcome +//| the leakage current. If you need to use a pull-down, +//| connect a strong external pull-down resistor that is 8.2k ohms or less. +//| +//| The internal pull-down resistor (``digitalio.DigitalInOut.pull = digitalio.Pull.DOWN``) +//| is not strong enough, and is not useful. +//| +//| Typical push-pull outputs from attached peripherals or other microcontrollers will drive +//| input pins adequately, with no resistor needed. +//| +//| There is no problem when pull-ups are used, even weak ones. Using the internal pull-up resistor +//| (``digitalioDigitalInOut.pull = digitalio.Pull.UP``) will work fine. +//| +//| For more information, see the RP2350-E9 erratum in the +//| `RP2350 datasheet `_ //| """ static const mp_rom_map_elem_t digitalio_module_globals_table[] = { diff --git a/shared-bindings/displayio/Bitmap.c b/shared-bindings/displayio/Bitmap.c index 4c8fc97345cf4..e543687901a78 100644 --- a/shared-bindings/displayio/Bitmap.c +++ b/shared-bindings/displayio/Bitmap.c @@ -39,6 +39,7 @@ //| :param int height: The number of values high //| :param int value_count: The number of possible pixel values.""" //| ... +//| static mp_obj_t displayio_bitmap_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 3, 3, false); uint32_t width = mp_arg_validate_int_range(mp_obj_get_int(all_args[0]), 0, 32767, MP_QSTR_width); @@ -96,6 +97,7 @@ MP_PROPERTY_GETTER(displayio_bitmap_height_obj, //| bits_per_value: int //| """Bits per Pixel of the bitmap. (read only)""" +//| static mp_obj_t displayio_bitmap_obj_get_bits_per_value(mp_obj_t self_in) { displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in); @@ -126,6 +128,7 @@ MP_PROPERTY_GETTER(displayio_bitmap_bits_per_value_obj, //| //| bitmap[0,1] = 3""" //| ... +//| static mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) { if (value_obj == mp_const_none) { // delete item @@ -183,6 +186,7 @@ static mp_obj_t bitmap_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t val //| def fill(self, value: int) -> None: //| """Fills the bitmap with the supplied palette index value.""" //| ... +//| static mp_obj_t displayio_bitmap_obj_fill(mp_obj_t self_in, mp_obj_t value_obj) { displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -213,6 +217,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_bitmap_fill_obj, displayio_bitmap_obj_fill); //| notified of the "dirty rectangle" that encloses all modified //| pixels.""" //| ... +//| static mp_obj_t displayio_bitmap_obj_dirty(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { displayio_bitmap_t *self = MP_OBJ_TO_PTR(pos_args[0]); check_for_deinit(self); @@ -244,6 +249,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(displayio_bitmap_dirty_obj, 0, displayio_bitmap_obj_d //| """Release resources allocated by Bitmap.""" //| ... //| +//| static mp_obj_t displayio_bitmap_obj_deinit(mp_obj_t self_in) { displayio_bitmap_t *self = MP_OBJ_TO_PTR(self_in); common_hal_displayio_bitmap_deinit(self); diff --git a/shared-bindings/displayio/ColorConverter.c b/shared-bindings/displayio/ColorConverter.c index 1f973b5a42ab9..bfd037016d41f 100644 --- a/shared-bindings/displayio/ColorConverter.c +++ b/shared-bindings/displayio/ColorConverter.c @@ -26,6 +26,7 @@ //| :param Colorspace colorspace: The source colorspace, one of the Colorspace constants //| :param bool dither: Adds random noise to dither the output image""" //| ... +//| static mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_dither, ARG_input_colorspace }; @@ -38,7 +39,6 @@ static mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); displayio_colorconverter_t *self = mp_obj_malloc(displayio_colorconverter_t, &displayio_colorconverter_type); - common_hal_displayio_colorconverter_construct(self, args[ARG_dither].u_bool, (displayio_colorspace_t)cp_enum_value(&displayio_colorspace_type, args[ARG_input_colorspace].u_obj, MP_QSTR_input_colorspace)); return MP_OBJ_FROM_PTR(self); @@ -47,6 +47,7 @@ static mp_obj_t displayio_colorconverter_make_new(const mp_obj_type_t *type, siz //| def convert(self, color: int) -> int: //| """Converts the given color to RGB565 according to the Colorspace""" //| ... +//| static mp_obj_t displayio_colorconverter_obj_convert(mp_obj_t self_in, mp_obj_t color_obj) { displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in); @@ -60,6 +61,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_convert_obj, displayio_colorc //| dither: bool //| """When `True` the ColorConverter dithers the output by adding random noise when //| truncating to display bitdepth""" +//| static mp_obj_t displayio_colorconverter_obj_get_dither(mp_obj_t self_in) { displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(common_hal_displayio_colorconverter_get_dither(self)); @@ -84,6 +86,7 @@ MP_PROPERTY_GETSET(displayio_colorconverter_dither_obj, //| raise an Exception if there is already a selected transparent index. //| //| :param int color: The color to be transparent""" +//| static mp_obj_t displayio_colorconverter_make_transparent(mp_obj_t self_in, mp_obj_t transparent_color_obj) { displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in); @@ -98,6 +101,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_colorconverter_make_transparent_obj, display //| //| :param int color: [IGNORED] Use any value""" //| +//| static mp_obj_t displayio_colorconverter_make_opaque(mp_obj_t self_in, mp_obj_t transparent_color_obj) { displayio_colorconverter_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/displayio/Colorspace.c b/shared-bindings/displayio/Colorspace.c index f4677b25a9086..f6592024fa3be 100644 --- a/shared-bindings/displayio/Colorspace.c +++ b/shared-bindings/displayio/Colorspace.c @@ -39,6 +39,7 @@ MAKE_ENUM_VALUE(displayio_colorspace_type, displayio_colorspace, L8, DISPLAYIO_C //| RGB555_SWAPPED: Colorspace //| """The swapped 15-bit colorspace. First, the high and low 8 bits of the number are swapped, then they are interpreted as for RGB555""" //| +//| MAKE_ENUM_MAP(displayio_colorspace) { MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB888), MAKE_ENUM_MAP_ENTRY(displayio_colorspace, RGB565), diff --git a/shared-bindings/displayio/Group.c b/shared-bindings/displayio/Group.c index 73c3d06988c8d..94ee2e58de15c 100644 --- a/shared-bindings/displayio/Group.c +++ b/shared-bindings/displayio/Group.c @@ -25,6 +25,7 @@ //| :param int x: Initial x position within the parent. //| :param int y: Initial y position within the parent.""" //| ... +//| static mp_obj_t displayio_group_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_scale, ARG_x, ARG_y }; static const mp_arg_t allowed_args[] = { @@ -120,6 +121,7 @@ MP_PROPERTY_GETSET(displayio_group_x_obj, //| y: int //| """Y position of the Group in the parent.""" +//| static mp_obj_t displayio_group_obj_get_y(mp_obj_t self_in) { displayio_group_t *self = native_group(self_in); return MP_OBJ_NEW_SMALL_INT(common_hal_displayio_group_get_y(self)); @@ -145,6 +147,7 @@ MP_PROPERTY_GETSET(displayio_group_y_obj, //| ) -> None: //| """Append a layer to the group. It will be drawn above other layers.""" //| ... +//| static mp_obj_t displayio_group_obj_append(mp_obj_t self_in, mp_obj_t layer) { displayio_group_t *self = native_group(self_in); common_hal_displayio_group_insert(self, common_hal_displayio_group_get_len(self), layer); @@ -159,6 +162,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_append_obj, displayio_group_obj_append //| ) -> None: //| """Insert a layer into the group.""" //| ... +//| static mp_obj_t displayio_group_obj_insert(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t layer) { displayio_group_t *self = native_group(self_in); if ((size_t)MP_OBJ_SMALL_INT_VALUE(index_obj) == common_hal_displayio_group_get_len(self)) { @@ -177,6 +181,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(displayio_group_insert_obj, displayio_group_obj_insert //| ) -> int: //| """Returns the index of the first copy of layer. Raises ValueError if not found.""" //| ... +//| static mp_obj_t displayio_group_obj_index(mp_obj_t self_in, mp_obj_t layer) { displayio_group_t *self = native_group(self_in); mp_int_t index = common_hal_displayio_group_index(self, layer); @@ -192,6 +197,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_index_obj, displayio_group_obj_index); //| ) -> Union[vectorio.Circle, vectorio.Rectangle, vectorio.Polygon, Group, TileGrid]: //| """Remove the ith item and return it.""" //| ... +//| static mp_obj_t displayio_group_obj_pop(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_i }; static const mp_arg_t allowed_args[] = { @@ -217,6 +223,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(displayio_group_pop_obj, 1, displayio_group_obj_pop); //| ) -> None: //| """Remove the first copy of layer. Raises ValueError if it is not present.""" //| ... +//| static mp_obj_t displayio_group_obj_remove(mp_obj_t self_in, mp_obj_t layer) { mp_obj_t index = displayio_group_obj_index(self_in, layer); displayio_group_t *self = native_group(self_in); @@ -239,6 +246,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(displayio_group_remove_obj, displayio_group_obj_remove //| def __len__(self) -> int: //| """Returns the number of layers in a Group""" //| ... +//| static mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { displayio_group_t *self = native_group(self_in); uint16_t len = common_hal_displayio_group_get_len(self); @@ -281,6 +289,7 @@ static mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| //| del group[0]""" //| ... +//| static mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { displayio_group_t *self = native_group(self_in); @@ -305,14 +314,17 @@ static mp_obj_t group_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t valu //| """Sort the members of the group.""" //| ... //| +//| static mp_obj_t displayio_group_obj_sort(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { displayio_group_t *self = native_group(pos_args[0]); - mp_obj_t *args = m_new(mp_obj_t, n_args); + mp_obj_t *args = m_malloc_items(n_args); for (size_t i = 1; i < n_args; ++i) { args[i] = pos_args[i]; } args[0] = MP_OBJ_FROM_PTR(self->members); - return mp_obj_list_sort(n_args, args, kw_args); + mp_obj_t res = mp_obj_list_sort(n_args, args, kw_args); + m_del(mp_obj_t, args, n_args); + return res; } MP_DEFINE_CONST_FUN_OBJ_KW(displayio_group_sort_obj, 1, displayio_group_obj_sort); diff --git a/shared-bindings/displayio/OnDiskBitmap.c b/shared-bindings/displayio/OnDiskBitmap.c index fea3763657e86..cd2161fd3b081 100644 --- a/shared-bindings/displayio/OnDiskBitmap.c +++ b/shared-bindings/displayio/OnDiskBitmap.c @@ -58,6 +58,7 @@ //| of CircuitPython will remove the ability to pass in an opened file. //| """ //| ... +//| static mp_obj_t displayio_ondiskbitmap_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_obj_t arg = all_args[0]; @@ -106,6 +107,7 @@ MP_PROPERTY_GETTER(displayio_ondiskbitmap_height_obj, //| bitmap's structure. The pixel shader can be modified (e.g., to set the //| transparent pixel or, for palette shaded images, to update the palette.)""" //| +//| static mp_obj_t displayio_ondiskbitmap_obj_get_pixel_shader(mp_obj_t self_in) { displayio_ondiskbitmap_t *self = MP_OBJ_TO_PTR(self_in); return common_hal_displayio_ondiskbitmap_get_pixel_shader(self); @@ -113,13 +115,8 @@ static mp_obj_t displayio_ondiskbitmap_obj_get_pixel_shader(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(displayio_ondiskbitmap_get_pixel_shader_obj, displayio_ondiskbitmap_obj_get_pixel_shader); -const mp_obj_property_t displayio_ondiskbitmap_pixel_shader_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&displayio_ondiskbitmap_get_pixel_shader_obj, - (mp_obj_t)MP_ROM_NONE, - (mp_obj_t)MP_ROM_NONE}, -}; - +MP_PROPERTY_GETTER(displayio_ondiskbitmap_pixel_shader_obj, + (mp_obj_t)&displayio_ondiskbitmap_get_pixel_shader_obj); static const mp_rom_map_elem_t displayio_ondiskbitmap_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&displayio_ondiskbitmap_height_obj) }, diff --git a/shared-bindings/displayio/Palette.c b/shared-bindings/displayio/Palette.c index 528df88ec4e7e..c69c8d11f250a 100644 --- a/shared-bindings/displayio/Palette.c +++ b/shared-bindings/displayio/Palette.c @@ -25,6 +25,7 @@ //| :param bool dither: When true, dither the RGB color before converting to the display's color space //| """ //| ... +//| // TODO(tannewt): Add support for other color formats. // TODO(tannewt): Add support for 8-bit alpha blending. //| @@ -46,6 +47,7 @@ static mp_obj_t displayio_palette_make_new(const mp_obj_type_t *type, size_t n_a //| dither: bool //| """When `True` the Palette dithers the output color by adding random //| noise when truncating to display bitdepth""" +//| static mp_obj_t displayio_palette_obj_get_dither(mp_obj_t self_in) { displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(common_hal_displayio_palette_get_dither(self)); @@ -69,6 +71,7 @@ MP_PROPERTY_GETSET(displayio_palette_dither_obj, //| def __len__(self) -> int: //| """Returns the number of colors in a Palette""" //| ... +//| static mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { @@ -102,6 +105,7 @@ static mp_obj_t group_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| palette[3] = bytearray(b'\x00\x00\xFF') # set using a bytearay of 3 or 4 bytes //| palette[4] = (10, 20, 30) # set using a tuple of 3 integers""" //| ... +//| static mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item @@ -149,7 +153,10 @@ static mp_obj_t palette_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t val return mp_const_none; } -//| def make_transparent(self, palette_index: int) -> None: ... +//| def make_transparent(self, palette_index: int) -> None: +//| """Makes the palette index transparent. The color is ignored.""" +//| ... +//| static mp_obj_t displayio_palette_obj_make_transparent(mp_obj_t self_in, mp_obj_t palette_index_obj) { displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); @@ -161,7 +168,11 @@ static mp_obj_t displayio_palette_obj_make_transparent(mp_obj_t self_in, mp_obj_ } MP_DEFINE_CONST_FUN_OBJ_2(displayio_palette_make_transparent_obj, displayio_palette_obj_make_transparent); -//| def make_opaque(self, palette_index: int) -> None: ... +//| +//| def make_opaque(self, palette_index: int) -> None: +//| """Mark the given palette index as opaque.""" +//| ... +//| static mp_obj_t displayio_palette_obj_make_opaque(mp_obj_t self_in, mp_obj_t palette_index_obj) { displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); @@ -173,10 +184,12 @@ static mp_obj_t displayio_palette_obj_make_opaque(mp_obj_t self_in, mp_obj_t pal } MP_DEFINE_CONST_FUN_OBJ_2(displayio_palette_make_opaque_obj, displayio_palette_obj_make_opaque); +//| //| def is_transparent(self, palette_index: int) -> bool: //| """Returns `True` if the palette index is transparent. Returns `False` if opaque.""" //| ... //| +//| static mp_obj_t displayio_palette_obj_is_transparent(mp_obj_t self_in, mp_obj_t palette_index_obj) { displayio_palette_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/displayio/TileGrid.c b/shared-bindings/displayio/TileGrid.c index 9800480b22a45..5d54c1e3e306b 100644 --- a/shared-bindings/displayio/TileGrid.c +++ b/shared-bindings/displayio/TileGrid.c @@ -17,6 +17,25 @@ #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/OnDiskBitmap.h" #include "shared-bindings/displayio/Palette.h" +#ifdef CIRCUITPY_TILEPALETTEMAPPER +#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" +#endif + + +void displayio_tilegrid_validate_pixel_shader(mp_obj_t pixel_shader) { + bool valid_type = true; + if (!mp_obj_is_type(pixel_shader, &displayio_palette_type) && !mp_obj_is_type(pixel_shader, &displayio_colorconverter_type)) { + valid_type = false; + } + #if CIRCUITPY_TILEPALETTEMAPPER + if (mp_obj_is_type(pixel_shader, &tilepalettemapper_tilepalettemapper_type)) { + valid_type = true; + } + #endif + if (!valid_type) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader); + } +} //| class TileGrid: //| """A grid of tiles sourced out of one bitmap @@ -30,25 +49,26 @@ //| self, //| bitmap: Union[Bitmap, OnDiskBitmap], //| *, -//| pixel_shader: Union[ColorConverter, Palette], +//| pixel_shader: Union[ColorConverter, Palette, tilepalettemapper.TilePaletteMapper], //| width: int = 1, //| height: int = 1, //| tile_width: Optional[int] = None, //| tile_height: Optional[int] = None, //| default_tile: int = 0, //| x: int = 0, -//| y: int = 0 +//| y: int = 0, //| ) -> None: //| """Create a TileGrid object. The bitmap is source for 2d pixels. The pixel_shader is used to //| convert the value and its location to a display native pixel color. This may be a simple color //| palette lookup, a gradient, a pattern or a color transformer. //| -//| To save RAM usage, tile values are only allowed in the range from 0 to 255 inclusive (single byte values). +//| When the total number of tiles is 256 or less, tile values are stored as single bytes (uint8_t). +//| When the total number of tiles is more than 256, tile values are stored as double bytes (uint16_t). //| //| tile_width and tile_height match the height of the bitmap by default. //| //| :param Bitmap,OnDiskBitmap bitmap: The bitmap storing one or more tiles. -//| :param ColorConverter,Palette pixel_shader: The pixel shader that produces colors from values +//| :param ColorConverter,Palette,tilepalettemapper.TilePaletteMapper pixel_shader: The pixel shader that produces colors from values //| :param int width: Width of the grid in tiles. //| :param int height: Height of the grid in tiles. //| :param int tile_width: Width of a single tile in pixels. Defaults to the full Bitmap and must evenly divide into the Bitmap's dimensions. @@ -56,6 +76,7 @@ //| :param int default_tile: Default tile index to show. //| :param int x: Initial x position of the left edge within the parent. //| :param int y: Initial y position of the top edge within the parent.""" +//| static mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_bitmap, ARG_pixel_shader, ARG_width, ARG_height, ARG_tile_width, ARG_tile_height, ARG_default_tile, ARG_x, ARG_y }; static const mp_arg_t allowed_args[] = { @@ -88,10 +109,7 @@ static mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_ mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_bitmap); } mp_obj_t pixel_shader = args[ARG_pixel_shader].u_obj; - if (!mp_obj_is_type(pixel_shader, &displayio_colorconverter_type) && - !mp_obj_is_type(pixel_shader, &displayio_palette_type)) { - mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader); - } + displayio_tilegrid_validate_pixel_shader(pixel_shader); uint16_t tile_width = args[ARG_tile_width].u_int; if (tile_width == 0) { tile_width = bitmap_width; @@ -115,6 +133,7 @@ static mp_obj_t displayio_tilegrid_make_new(const mp_obj_type_t *type, size_t n_ bitmap_width / tile_width, bitmap_height / tile_height, pixel_shader, args[ARG_width].u_int, args[ARG_height].u_int, tile_width, tile_height, x, y, args[ARG_default_tile].u_int); + return MP_OBJ_FROM_PTR(self); } @@ -275,6 +294,7 @@ MP_PROPERTY_GETSET(displayio_tilegrid_flip_y_obj, //| transpose_xy: bool //| """If true, the TileGrid's axis will be swapped. When combined with mirroring, any 90 degree //| rotation can be achieved along with the corresponding mirrored version.""" +//| static mp_obj_t displayio_tilegrid_obj_get_transpose_xy(mp_obj_t self_in) { displayio_tilegrid_t *self = native_tilegrid(self_in); return mp_obj_new_bool(common_hal_displayio_tilegrid_get_transpose_xy(self)); @@ -296,8 +316,9 @@ MP_PROPERTY_GETSET(displayio_tilegrid_transpose_xy_obj, //| def contains(self, touch_tuple: tuple) -> bool: //| """Returns True if the first two values in ``touch_tuple`` represent an x,y coordinate //| inside the tilegrid rectangle bounds.""" +//| static mp_obj_t displayio_tilegrid_obj_contains(mp_obj_t self_in, mp_obj_t touch_tuple) { - displayio_tilegrid_t *self = MP_OBJ_TO_PTR(self_in); + displayio_tilegrid_t *self = native_tilegrid(self_in); mp_obj_t *touch_tuple_items; mp_obj_get_array_fixed_n(touch_tuple, 3, &touch_tuple_items); @@ -310,7 +331,7 @@ static mp_obj_t displayio_tilegrid_obj_contains(mp_obj_t self_in, mp_obj_t touch } MP_DEFINE_CONST_FUN_OBJ_2(displayio_tilegrid_contains_obj, displayio_tilegrid_obj_contains); -//| pixel_shader: Union[ColorConverter, Palette] +//| pixel_shader: Union[ColorConverter, Palette, tilepalettemapper.TilePaletteMapper] //| """The pixel shader of the tilegrid.""" static mp_obj_t displayio_tilegrid_obj_get_pixel_shader(mp_obj_t self_in) { displayio_tilegrid_t *self = native_tilegrid(self_in); @@ -320,10 +341,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(displayio_tilegrid_get_pixel_shader_obj, displayio_til static mp_obj_t displayio_tilegrid_obj_set_pixel_shader(mp_obj_t self_in, mp_obj_t pixel_shader) { displayio_tilegrid_t *self = native_tilegrid(self_in); - if (!mp_obj_is_type(pixel_shader, &displayio_palette_type) && !mp_obj_is_type(pixel_shader, &displayio_colorconverter_type)) { - mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader); - } - + displayio_tilegrid_validate_pixel_shader(pixel_shader); common_hal_displayio_tilegrid_set_pixel_shader(self, pixel_shader); return mp_const_none; @@ -336,6 +354,7 @@ MP_PROPERTY_GETSET(displayio_tilegrid_pixel_shader_obj, //| bitmap: Union[Bitmap, OnDiskBitmap] //| """The bitmap of the tilegrid.""" +//| static mp_obj_t displayio_tilegrid_obj_get_bitmap(mp_obj_t self_in) { displayio_tilegrid_t *self = native_tilegrid(self_in); return common_hal_displayio_tilegrid_get_bitmap(self); @@ -403,6 +422,7 @@ MP_PROPERTY_GETSET(displayio_tilegrid_bitmap_obj, //| grid[0,0] = 10""" //| ... //| +//| static mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) { displayio_tilegrid_t *self = native_tilegrid(self_in); @@ -435,7 +455,7 @@ static mp_obj_t tilegrid_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t v return MP_OBJ_NULL; // op not supported } else { mp_int_t value = mp_obj_get_int(value_obj); - mp_arg_validate_int_range(value, 0, 255, MP_QSTR_tile); + mp_arg_validate_int_range(value, 0, self->tiles_in_bitmap - 1, MP_QSTR_tile); common_hal_displayio_tilegrid_set_tile(self, x, y, value); } diff --git a/shared-bindings/displayio/TileGrid.h b/shared-bindings/displayio/TileGrid.h index 19af39fadeb37..35b2b2fd00c9e 100644 --- a/shared-bindings/displayio/TileGrid.h +++ b/shared-bindings/displayio/TileGrid.h @@ -13,7 +13,7 @@ extern const mp_obj_type_t displayio_tilegrid_type; void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap, uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height, - uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile); + uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint16_t default_tile); bool common_hal_displayio_tilegrid_get_hidden(displayio_tilegrid_t *self); void common_hal_displayio_tilegrid_set_hidden(displayio_tilegrid_t *self, bool hidden); @@ -43,9 +43,9 @@ uint16_t common_hal_displayio_tilegrid_get_height(displayio_tilegrid_t *self); uint16_t common_hal_displayio_tilegrid_get_tile_width(displayio_tilegrid_t *self); uint16_t common_hal_displayio_tilegrid_get_tile_height(displayio_tilegrid_t *self); -uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y); -void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index); +uint16_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y); +void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint16_t tile_index); // Private API for scrolling the TileGrid. void common_hal_displayio_tilegrid_set_top_left(displayio_tilegrid_t *self, uint16_t x, uint16_t y); -void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint8_t tile_index); +void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint16_t tile_index); diff --git a/shared-bindings/displayio/__init__.c b/shared-bindings/displayio/__init__.c index acd48f5ea3cac..e0c35d3bce47d 100644 --- a/shared-bindings/displayio/__init__.c +++ b/shared-bindings/displayio/__init__.c @@ -43,7 +43,25 @@ //| refer to `this Learn guide //| `_. //| """ +//| +//| AnyDisplayBus = fourwire.FourWire | i2cdisplaybus.I2CDisplayBus | is31fl3741.IS31FL3741 +//| """Type-checking shorthand for any kind of display bus. Not actually defined in CircuitPython.""" +//| +//| AnyFramebuffer = ( +//| rgbmatrix.RGBMatrix +//| | is31fl3741.IS31FL3741_FrameBuffer +//| | sharpdisplay.SharpMemoryFramebuffer +//| | videocore.Framebuffer +//| | picodvi.Framebuffer +//| | aurora_epaper.AuroraMemoryFramebuffer +//| ) +//| """Type-checking shorthand for any kind of framebuffer. Not actually defined in CircuitPython.""" +//| +//| AnyDisplay = ( +//| busdisplay.BusDisplay | epaperdisplay.EPaperDisplay | framebufferio.FramebufferDisplay +//| ) +//| """Type-checking shorthand for any kind of display. Not actually defined in CircuitPython.""" //| CIRCUITPYTHON_TERMINAL: Group //| """The `displayio.Group` that is the displayed serial terminal (REPL).""" //| @@ -53,6 +71,7 @@ //| from fourwire import FourWire //| from i2cdisplaybus import I2CDisplayBus as I2CDisplay //| +//| //| def release_displays() -> None: //| """Releases any actively used displays so their buses and pins can be used again. This will also @@ -63,6 +82,7 @@ //| initialization so the display is active as long as possible.""" //| ... //| +//| static mp_obj_t displayio_release_displays(void) { common_hal_displayio_release_displays(); return mp_const_none; @@ -80,21 +100,8 @@ static const mp_rom_map_elem_t displayio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Palette), MP_ROM_PTR(&displayio_palette_type) }, { MP_ROM_QSTR(MP_QSTR_TileGrid), MP_ROM_PTR(&displayio_tilegrid_type) }, - // Remove these in CircuitPython 10 - #if CIRCUITPY_BUSDISPLAY - { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&busdisplay_busdisplay_type) }, - #endif - #if CIRCUITPY_EPAPERDISPLAY - { MP_ROM_QSTR(MP_QSTR_EPaperDisplay), MP_ROM_PTR(&epaperdisplay_epaperdisplay_type) }, - #endif - #if CIRCUITPY_FOURWIRE - { MP_ROM_QSTR(MP_QSTR_FourWire), MP_ROM_PTR(&fourwire_fourwire_type) }, - #endif - #if CIRCUITPY_I2CDISPLAYBUS - { MP_ROM_QSTR(MP_QSTR_I2CDisplay), MP_ROM_PTR(&i2cdisplaybus_i2cdisplaybus_type) }, - #endif - { MP_ROM_QSTR(MP_QSTR_release_displays), MP_ROM_PTR(&displayio_release_displays_obj) }, + { MP_ROM_QSTR(MP_QSTR_CIRCUITPYTHON_TERMINAL), MP_ROM_PTR(&circuitpython_splash) }, }; static MP_DEFINE_CONST_DICT(displayio_module_globals, displayio_module_globals_table); diff --git a/shared-bindings/displayio/__init__.h b/shared-bindings/displayio/__init__.h index 33987ebe38ae5..583f6b217fa9f 100644 --- a/shared-bindings/displayio/__init__.h +++ b/shared-bindings/displayio/__init__.h @@ -23,6 +23,9 @@ typedef enum displayio_colorspace { } displayio_colorspace_t; void common_hal_displayio_release_displays(void); +mp_obj_t common_hal_displayio_get_primary_display(void); +void common_hal_displayio_set_primary_display(mp_obj_t o); +void common_hal_displayio_auto_primary_display(void); extern const mp_obj_type_t displayio_colorspace_type; extern const cp_enum_obj_t displayio_colorspace_RGB888_obj; @@ -46,4 +49,5 @@ typedef bool (*display_bus_begin_transaction)(mp_obj_t bus); typedef void (*display_bus_send)(mp_obj_t bus, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length); typedef void (*display_bus_end_transaction)(mp_obj_t bus); +typedef void (*display_bus_flush)(mp_obj_t bus); typedef void (*display_bus_collect_ptrs)(mp_obj_t bus); diff --git a/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c b/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c index 6b7aeefcfb789..faa0c21b0978b 100644 --- a/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c +++ b/shared-bindings/dotclockframebuffer/DotClockFramebuffer.c @@ -93,6 +93,7 @@ //| #:param int overscan_right: Allocate additional non-visible columns right of the last display column //| #:param int overscan_bottom: Allocate additional non-visible rows below the last display row //| ... +//| static mp_obj_t dotclockframebuffer_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_de, ARG_vsync, ARG_hsync, ARG_dclk, ARG_red, ARG_green, ARG_blue, ARG_frequency, ARG_width, ARG_height, @@ -176,6 +177,7 @@ static void check_for_deinit(dotclockframebuffer_framebuffer_obj_t *self) { //| If this function is not called, the results are unpredictable; updates may be partially shown. //| """ //| ... +//| static mp_obj_t dotclockframebuffer_framebuffer_refresh(mp_obj_t self_in) { dotclockframebuffer_framebuffer_obj_t *self = (dotclockframebuffer_framebuffer_obj_t *)self_in; check_for_deinit(self); @@ -257,6 +259,7 @@ MP_PROPERTY_GETTER(dotclockframebuffer_framebuffer_row_stride_obj, //| //| On Espressif this value is **guaranteed** to be a multiple of the 2 (i.e., it is a whole number of pixels)""" //| +//| static mp_obj_t dotclockframebuffer_framebuffer_get_first_pixel_offset(mp_obj_t self_in) { dotclockframebuffer_framebuffer_obj_t *self = (dotclockframebuffer_framebuffer_obj_t *)self_in; check_for_deinit(self); diff --git a/shared-bindings/dotclockframebuffer/__init__.c b/shared-bindings/dotclockframebuffer/__init__.c index d05c57cddf590..b8dbf8c1897b8 100644 --- a/shared-bindings/dotclockframebuffer/__init__.c +++ b/shared-bindings/dotclockframebuffer/__init__.c @@ -17,6 +17,7 @@ //| //| Length = typing.Literal[1, 2] //| +//| //| def ioexpander_send_init_sequence( //| bus: busio.I2C, //| init_sequence: ReadableBuffer, @@ -30,7 +31,7 @@ //| mosi_bit: int, //| clk_bit: int, //| reset_bit: Optional[int], -//| ): +//| ) -> None: //| """Send a displayio-style initialization sequence over an I2C I/O expander //| //| This function is highly generic in order to support various I/O expanders. @@ -61,6 +62,7 @@ //| :param Optional[ReadableBuffer] i2c_init_sequence: An initialization sequence to send to the I2C expander //| """ //| +//| static mp_obj_t ioexpander_send_init_sequence(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bus, ARG_init_sequence, ARG_i2c_address, ARG_gpio_address, ARG_gpio_data_len, ARG_gpio_data, ARG_cs_bit, ARG_mosi_bit, ARG_clk_bit, ARG_reset_bit, ARG_i2c_init_sequence, NUM_ARGS }; diff --git a/shared-bindings/dualbank/__init__.c b/shared-bindings/dualbank/__init__.c index 2f7f5776d6835..2c00a5b01002b 100644 --- a/shared-bindings/dualbank/__init__.c +++ b/shared-bindings/dualbank/__init__.c @@ -44,8 +44,10 @@ //| dualbank.flash(buffer, offset) //| dualbank.switch() //| """ +//| //| ... //| +//| #if CIRCUITPY_STORAGE_EXTEND static void raise_error_if_storage_extended(void) { @@ -65,6 +67,7 @@ static void raise_error_if_storage_extended(void) { //| """ //| ... //| +//| static mp_obj_t dualbank_flash(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_offset }; static const mp_arg_t allowed_args[] = { @@ -98,6 +101,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(dualbank_flash_obj, 0, dualbank_flash); //| """ //| ... //| +//| static mp_obj_t dualbank_switch(void) { #if CIRCUITPY_STORAGE_EXTEND raise_error_if_storage_extended(); diff --git a/shared-bindings/epaperdisplay/EPaperDisplay.c b/shared-bindings/epaperdisplay/EPaperDisplay.c index ea7296920e2ab..cd9c18e27d526 100644 --- a/shared-bindings/epaperdisplay/EPaperDisplay.c +++ b/shared-bindings/epaperdisplay/EPaperDisplay.c @@ -20,6 +20,7 @@ //| from busdisplay import _DisplayBus //| +//| //| class EPaperDisplay: //| """Manage updating an epaper display over a display bus //| @@ -28,7 +29,8 @@ //| is called. This is done so that CircuitPython can use the display itself. //| //| Most people should not use this class directly. Use a specific display driver instead that will -//| contain the startup and shutdown sequences at minimum.""" +//| contain the startup and shutdown sequences at minimum. +//| """ //| //| def __init__( //| self, @@ -52,6 +54,7 @@ //| write_color_ram_command: Optional[int] = None, //| color_bits_inverted: bool = False, //| highlight_color: int = 0x000000, +//| highlight_color2: int = 0x000000, //| refresh_display_command: Union[int, circuitpython_typing.ReadableBuffer], //| refresh_time: float = 40, //| busy_pin: Optional[microcontroller.Pin] = None, @@ -60,9 +63,10 @@ //| always_toggle_chip_select: bool = False, //| grayscale: bool = False, //| advanced_color_epaper: bool = False, +//| spectra6: bool = False, //| two_byte_sequence_length: bool = False, //| start_up_time: float = 0, -//| address_little_endian: bool = False +//| address_little_endian: bool = False, //| ) -> None: //| """Create a EPaperDisplay object on the given display bus (`fourwire.FourWire` or `paralleldisplaybus.ParallelBus`). //| @@ -94,6 +98,7 @@ //| :param int write_color_ram_command: Command used to write pixels values into the update region //| :param bool color_bits_inverted: True if 0 bits are used to show the color. Otherwise, 1 means to show color. //| :param int highlight_color: RGB888 of source color to highlight with third ePaper color. +//| :param int highlight_color2: RGB888 of source color to highlight with fourth ePaper color. //| :param int refresh_display_command: Command used to start a display refresh. Single int or byte-packed command sequence //| :param float refresh_time: Time it takes to refresh the display before the stop_sequence should be sent. Ignored when busy_pin is provided. //| :param microcontroller.Pin busy_pin: Pin used to signify the display is busy @@ -102,19 +107,21 @@ //| :param bool always_toggle_chip_select: When True, chip select is toggled every byte //| :param bool grayscale: When true, the color ram is the low bit of 2-bit grayscale //| :param bool advanced_color_epaper: When true, the display is a 7-color advanced color epaper (ACeP) +//| :param bool spectra6: When true, the display is a 6-color spectra6 epaper //| :param bool two_byte_sequence_length: When true, use two bytes to define sequence length //| :param float start_up_time: Time to wait after reset before sending commands //| :param bool address_little_endian: Send the least significant byte (not bit) of multi-byte addresses first. Ignored when ram is addressed with one byte //| """ //| ... +//| static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_display_bus, ARG_start_sequence, ARG_stop_sequence, ARG_width, ARG_height, ARG_ram_width, ARG_ram_height, ARG_colstart, ARG_rowstart, ARG_rotation, ARG_set_column_window_command, ARG_set_row_window_command, ARG_set_current_column_command, ARG_set_current_row_command, ARG_write_black_ram_command, ARG_black_bits_inverted, - ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, + ARG_write_color_ram_command, ARG_color_bits_inverted, ARG_highlight_color, ARG_highlight_color2, ARG_refresh_display_command, ARG_refresh_time, ARG_busy_pin, ARG_busy_state, - ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale, ARG_advanced_color_epaper, + ARG_seconds_per_frame, ARG_always_toggle_chip_select, ARG_grayscale, ARG_advanced_color_epaper, ARG_spectra6, ARG_two_byte_sequence_length, ARG_start_up_time, ARG_address_little_endian }; static const mp_arg_t allowed_args[] = { { MP_QSTR_display_bus, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -136,6 +143,7 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, { MP_QSTR_write_color_ram_command, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, { MP_QSTR_color_bits_inverted, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, { MP_QSTR_highlight_color, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x000000} }, + { MP_QSTR_highlight_color2, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0x000000} }, { MP_QSTR_refresh_display_command, MP_ARG_OBJ | MP_ARG_REQUIRED }, { MP_QSTR_refresh_time, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(40)} }, { MP_QSTR_busy_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, @@ -144,6 +152,7 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, { MP_QSTR_always_toggle_chip_select, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, { MP_QSTR_grayscale, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, { MP_QSTR_advanced_color_epaper, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + { MP_QSTR_spectra6, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, { MP_QSTR_two_byte_sequence_length, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, { MP_QSTR_start_up_time, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(0)} }, { MP_QSTR_address_little_endian, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, @@ -175,6 +184,7 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, mp_int_t write_color_ram_command = NO_COMMAND; mp_int_t highlight_color = args[ARG_highlight_color].u_int; + mp_int_t highlight_color2 = args[ARG_highlight_color2].u_int; if (args[ARG_write_color_ram_command].u_obj != mp_const_none) { write_color_ram_command = mp_obj_get_int(args[ARG_write_color_ram_command].u_obj); } @@ -187,7 +197,7 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, size_t refresh_buf_len = 0; mp_int_t refresh_command; if (mp_obj_get_int_maybe(refresh_obj, &refresh_command)) { - uint8_t *command_buf = m_malloc(3); + uint8_t *command_buf = m_malloc_without_collect(3); command_buf[0] = refresh_command; command_buf[1] = 0; command_buf[2] = 0; @@ -201,20 +211,43 @@ static mp_obj_t epaperdisplay_epaperdisplay_make_new(const mp_obj_type_t *type, } self->base.type = &epaperdisplay_epaperdisplay_type; - common_hal_epaperdisplay_epaperdisplay_construct( - self, - display_bus, - start_bufinfo.buf, start_bufinfo.len, start_up_time, stop_bufinfo.buf, stop_bufinfo.len, - args[ARG_width].u_int, args[ARG_height].u_int, args[ARG_ram_width].u_int, args[ARG_ram_height].u_int, - args[ARG_colstart].u_int, args[ARG_rowstart].u_int, rotation, - args[ARG_set_column_window_command].u_int, args[ARG_set_row_window_command].u_int, - args[ARG_set_current_column_command].u_int, args[ARG_set_current_row_command].u_int, - args[ARG_write_black_ram_command].u_int, args[ARG_black_bits_inverted].u_bool, write_color_ram_command, - args[ARG_color_bits_inverted].u_bool, highlight_color, refresh_buf, refresh_buf_len, refresh_time, - busy_pin, args[ARG_busy_state].u_bool, seconds_per_frame, - args[ARG_always_toggle_chip_select].u_bool, args[ARG_grayscale].u_bool, args[ARG_advanced_color_epaper].u_bool, - two_byte_sequence_length, args[ARG_address_little_endian].u_bool - ); + epaperdisplay_construct_args_t construct_args = EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS; + construct_args.bus = display_bus; + construct_args.start_sequence = start_bufinfo.buf; + construct_args.start_sequence_len = start_bufinfo.len; + construct_args.start_up_time = start_up_time; + construct_args.stop_sequence = stop_bufinfo.buf; + construct_args.stop_sequence_len = stop_bufinfo.len; + construct_args.width = args[ARG_width].u_int; + construct_args.height = args[ARG_height].u_int; + construct_args.ram_width = args[ARG_ram_width].u_int; + construct_args.ram_height = args[ARG_ram_height].u_int; + construct_args.colstart = args[ARG_colstart].u_int; + construct_args.rowstart = args[ARG_rowstart].u_int; + construct_args.rotation = rotation; + construct_args.set_column_window_command = args[ARG_set_column_window_command].u_int; + construct_args.set_row_window_command = args[ARG_set_row_window_command].u_int; + construct_args.set_current_column_command = args[ARG_set_current_column_command].u_int; + construct_args.set_current_row_command = args[ARG_set_current_row_command].u_int; + construct_args.write_black_ram_command = args[ARG_write_black_ram_command].u_int; + construct_args.black_bits_inverted = args[ARG_black_bits_inverted].u_bool; + construct_args.write_color_ram_command = write_color_ram_command; + construct_args.color_bits_inverted = args[ARG_color_bits_inverted].u_bool; + construct_args.highlight_color = highlight_color; + construct_args.highlight_color2 = highlight_color2; + construct_args.refresh_sequence = refresh_buf; + construct_args.refresh_sequence_len = refresh_buf_len; + construct_args.refresh_time = refresh_time; + construct_args.busy_pin = busy_pin; + construct_args.busy_state = args[ARG_busy_state].u_bool; + construct_args.seconds_per_frame = seconds_per_frame; + construct_args.always_toggle_chip_select = args[ARG_always_toggle_chip_select].u_bool; + construct_args.grayscale = args[ARG_grayscale].u_bool; + construct_args.acep = args[ARG_advanced_color_epaper].u_bool; + construct_args.spectra6 = args[ARG_spectra6].u_bool; + construct_args.two_byte_sequence_length = two_byte_sequence_length; + construct_args.address_little_endian = args[ARG_address_little_endian].u_bool; + common_hal_epaperdisplay_epaperdisplay_construct(self, &construct_args); return self; } @@ -238,6 +271,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(epaperdisplay_epaperdisplay_show_obj, epaperdisplay_ep //| ) -> None: //| """Updates the ``start_sequence`` and ``seconds_per_frame`` parameters to enable //| varying the refresh mode of the display.""" +//| static mp_obj_t epaperdisplay_epaperdisplay_update_refresh_mode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_start_sequence, ARG_seconds_per_frame }; static const mp_arg_t allowed_args[] = { @@ -263,6 +297,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(epaperdisplay_epaperdisplay_update_refresh_mode_obj, //| """Refreshes the display immediately or raises an exception if too soon. Use //| ``time.sleep(display.time_to_refresh)`` to sleep until a refresh can occur.""" //| ... +//| static mp_obj_t epaperdisplay_epaperdisplay_obj_refresh(mp_obj_t self_in) { epaperdisplay_epaperdisplay_obj_t *self = native_display(self_in); bool ok = common_hal_epaperdisplay_epaperdisplay_refresh(self); @@ -360,6 +395,7 @@ MP_PROPERTY_GETTER(epaperdisplay_epaperdisplay_bus_obj, //| If the root group is set to ``None``, no output will be shown. //| """ //| +//| static mp_obj_t epaperdisplay_epaperdisplay_obj_get_root_group(mp_obj_t self_in) { epaperdisplay_epaperdisplay_obj_t *self = native_display(self_in); return common_hal_epaperdisplay_epaperdisplay_get_root_group(self); diff --git a/shared-bindings/epaperdisplay/EPaperDisplay.h b/shared-bindings/epaperdisplay/EPaperDisplay.h index d4475e0a6aa43..83f0b0377fe6c 100644 --- a/shared-bindings/epaperdisplay/EPaperDisplay.h +++ b/shared-bindings/epaperdisplay/EPaperDisplay.h @@ -15,19 +15,84 @@ extern const mp_obj_type_t epaperdisplay_epaperdisplay_type; #define NO_COMMAND 0x100 +typedef struct { + mp_obj_t bus; + const uint8_t *start_sequence; + uint16_t start_sequence_len; + mp_float_t start_up_time; + const uint8_t *stop_sequence; + uint16_t stop_sequence_len; + uint16_t width; + uint16_t height; + uint16_t ram_width; + uint16_t ram_height; + int16_t colstart; + int16_t rowstart; + uint16_t rotation; + uint16_t set_column_window_command; + uint16_t set_row_window_command; + uint16_t set_current_column_command; + uint16_t set_current_row_command; + uint16_t write_black_ram_command; + bool black_bits_inverted; + uint16_t write_color_ram_command; + bool color_bits_inverted; + uint32_t highlight_color; + uint32_t highlight_color2; + const uint8_t *refresh_sequence; + uint16_t refresh_sequence_len; + mp_float_t refresh_time; + const mcu_pin_obj_t *busy_pin; + bool busy_state; + mp_float_t seconds_per_frame; + bool always_toggle_chip_select; + bool grayscale; + bool acep; + bool spectra6; + bool two_byte_sequence_length; + bool address_little_endian; +} epaperdisplay_construct_args_t; + +#define EPAPERDISPLAY_CONSTRUCT_ARGS_DEFAULTS { \ + .bus = mp_const_none, \ + .start_sequence = NULL, \ + .start_sequence_len = 0, \ + .start_up_time = 0.0, \ + .stop_sequence = NULL, \ + .stop_sequence_len = 0, \ + .width = 0, \ + .height = 0, \ + .ram_width = 0, \ + .ram_height = 0, \ + .colstart = 0, \ + .rowstart = 0, \ + .rotation = 0, \ + .set_column_window_command = NO_COMMAND, \ + .set_row_window_command = NO_COMMAND, \ + .set_current_column_command = NO_COMMAND, \ + .set_current_row_command = NO_COMMAND, \ + .write_black_ram_command = NO_COMMAND, \ + .black_bits_inverted = false, \ + .write_color_ram_command = NO_COMMAND, \ + .color_bits_inverted = false, \ + .highlight_color = 0x000000, \ + .highlight_color2 = 0x000000, \ + .refresh_sequence = NULL, \ + .refresh_sequence_len = 0, \ + .refresh_time = 0.0, \ + .busy_pin = NULL, \ + .busy_state = false, \ + .seconds_per_frame = 0.0, \ + .always_toggle_chip_select = false, \ + .grayscale = false, \ + .acep = false, \ + .spectra6 = false, \ + .two_byte_sequence_length = false, \ + .address_little_endian = false \ +} + void common_hal_epaperdisplay_epaperdisplay_construct(epaperdisplay_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, mp_float_t start_up_time, - const uint8_t *stop_sequence, uint16_t stop_sequence_len, - uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, - int16_t colstart, int16_t rowstart, uint16_t rotation, - uint16_t set_column_window_command, uint16_t set_row_window_command, - uint16_t set_current_column_command, uint16_t set_current_row_command, - uint16_t write_black_ram_command, bool black_bits_inverted, - uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, - const uint8_t *refresh_sequence, uint16_t refresh_sequence_len, mp_float_t refresh_time, - const mcu_pin_obj_t *busy_pin, bool busy_state, mp_float_t seconds_per_frame, - bool always_toggle_chip_select, bool grayscale, bool acep, bool two_byte_sequence_length, - bool address_little_endian); + const epaperdisplay_construct_args_t *args); bool common_hal_epaperdisplay_epaperdisplay_refresh(epaperdisplay_epaperdisplay_obj_t *self); diff --git a/shared-bindings/epaperdisplay/__init__.c b/shared-bindings/epaperdisplay/__init__.c index 1b18212a35a39..eff31cb01b309 100644 --- a/shared-bindings/epaperdisplay/__init__.c +++ b/shared-bindings/epaperdisplay/__init__.c @@ -13,9 +13,7 @@ #include "shared-bindings/epaperdisplay/__init__.h" #include "shared-bindings/epaperdisplay/EPaperDisplay.h" -//| """Displays a `displayio` object tree on an e-paper display -//| -//| """ +//| """Displays a `displayio` object tree on an e-paper display""" static const mp_rom_map_elem_t epaperdisplay_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_displayio) }, diff --git a/shared-bindings/floppyio/__init__.c b/shared-bindings/floppyio/__init__.c index ab166f1354e89..09034b4675d2a 100644 --- a/shared-bindings/floppyio/__init__.c +++ b/shared-bindings/floppyio/__init__.c @@ -23,7 +23,7 @@ //| buffer: WriteableBuffer, //| data: digitalio.DigitalInOut, //| index: digitalio.DigitalInOut, -//| index_wait=0.220, +//| index_wait: float = 0.220, //| ) -> int: //| """Read flux transition information into the buffer. //| @@ -40,6 +40,7 @@ //| """ //| ... //| +//| static mp_obj_t floppyio_flux_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { #if CIRCUITPY_DIGITALIO enum { ARG_buffer, ARG_data, ARG_index, ARG_index_wait }; @@ -102,7 +103,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(floppyio_flux_readinto_obj, 0, floppyio_flux_readinto //| def ns_to_count(ns, samplerate): //| return round(ns * samplerate * 1e-9) //| -//| This means the following typical values are a good starting place for a 1.44MB floppy: +//| This means the following typical values are a good starting place for a 1.44MB floppy: //| //| .. code-block:: py //| @@ -119,6 +120,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(floppyio_flux_readinto_obj, 0, floppyio_flux_readinto //| """ //| ... //| +//| static mp_obj_t floppyio_mfm_readinto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_flux, ARG_t2_max, ARG_t3_max, ARG_validity, ARG_clear_validity }; static const mp_arg_t allowed_args[] = { @@ -135,7 +137,7 @@ static mp_obj_t floppyio_mfm_readinto(size_t n_args, const mp_obj_t *pos_args, m mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE); if (bufinfo.len % 512 != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer must be a multiple of 512 bytes")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } size_t n_sectors = bufinfo.len / 512; diff --git a/shared-bindings/fontio/BuiltinFont.c b/shared-bindings/fontio/BuiltinFont.c index 9d3f30675b9ea..4969aed637d83 100644 --- a/shared-bindings/fontio/BuiltinFont.c +++ b/shared-bindings/fontio/BuiltinFont.c @@ -17,6 +17,7 @@ //| from typing_extensions import Protocol # for compat with python < 3.8 //| +//| //| class FontProtocol(Protocol): //| """A protocol shared by `BuiltinFont` and classes in ``adafruit_bitmap_font``""" //| @@ -34,6 +35,7 @@ //| If the code point is not present in the font, `None` is returned.""" //| pass //| +//| //| class BuiltinFont: //| """A font built into CircuitPython""" @@ -43,11 +45,13 @@ //| `Adafruit_CircuitPython_Bitmap_Font `_ //| library for dynamically loaded fonts.""" //| ... +//| //| bitmap: displayio.Bitmap //| """Bitmap containing all font glyphs starting with ASCII and followed by unicode. Use //| `get_glyph` in most cases. This is useful for use with `displayio.TileGrid` and //| `terminalio.Terminal`.""" +//| static mp_obj_t fontio_builtinfont_obj_get_bitmap(mp_obj_t self_in) { fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in); return common_hal_fontio_builtinfont_get_bitmap(self); @@ -60,6 +64,7 @@ MP_PROPERTY_GETTER(fontio_builtinfont_bitmap_obj, //| def get_bounding_box(self) -> Tuple[int, int]: //| """Returns the maximum bounds of all glyphs in the font in a tuple of two values: width, height.""" //| ... +//| static mp_obj_t fontio_builtinfont_obj_get_bounding_box(mp_obj_t self_in) { fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in); @@ -72,6 +77,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(fontio_builtinfont_get_bounding_box_obj, fontio_builti //| """Returns a `fontio.Glyph` for the given codepoint or None if no glyph is available.""" //| ... //| +//| static mp_obj_t fontio_builtinfont_obj_get_glyph(mp_obj_t self_in, mp_obj_t codepoint_obj) { fontio_builtinfont_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/fontio/Glyph.c b/shared-bindings/fontio/Glyph.c index 009fcb0606037..5651cb3d0f231 100644 --- a/shared-bindings/fontio/Glyph.c +++ b/shared-bindings/fontio/Glyph.c @@ -34,6 +34,7 @@ //| :param shift_y: the y difference to the next glyph""" //| ... //| +//| const mp_obj_namedtuple_type_t fontio_glyph_type = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_Glyph), .n_fields = 8, diff --git a/shared-bindings/fourwire/FourWire.c b/shared-bindings/fourwire/FourWire.c index bddd772c2e6e1..608645aaebf0b 100644 --- a/shared-bindings/fourwire/FourWire.c +++ b/shared-bindings/fourwire/FourWire.c @@ -20,18 +20,22 @@ //| class FourWire: //| """Manage updating a display over SPI four wire protocol in the background while Python code runs. -//| It doesn't handle display initialization.""" +//| It doesn't handle display initialization. +//| +//| .. seealso:: See `busdisplay.BusDisplay` and `epaperdisplay.EPaperDisplay` +//| for how to initialize a display, given a `FourWire` bus. +//| """ //| //| def __init__( //| self, //| spi_bus: busio.SPI, //| *, -//| command: Optional[microcontroller.Pin], -//| chip_select: Optional[microcontroller.Pin], -//| reset: Optional[microcontroller.Pin] = None, +//| command: Optional[Union[microcontroller.Pin, digitalio.DigitalInOutProtocol]] = None, +//| chip_select: Optional[Union[microcontroller.Pin, digitalio.DigitalInOutProtocol]] = None, +//| reset: Optional[Union[microcontroller.Pin, digitalio.DigitalInOutProtocol]] = None, //| baudrate: int = 24000000, //| polarity: int = 0, -//| phase: int = 0 +//| phase: int = 0, //| ) -> None: //| """Create a FourWire object associated with the given pins. //| @@ -54,6 +58,7 @@ //| :param int phase: the edge of the clock that data is captured. First (0) //| or second (1). Rising or falling depends on clock polarity.""" //| ... +//| static mp_obj_t fourwire_fourwire_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_spi_bus, ARG_command, ARG_chip_select, ARG_reset, ARG_baudrate, ARG_polarity, ARG_phase }; static const mp_arg_t allowed_args[] = { @@ -68,10 +73,6 @@ static mp_obj_t fourwire_fourwire_make_new(const mp_obj_type_t *type, size_t n_a mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - const mcu_pin_obj_t *command = validate_obj_is_free_pin_or_none(args[ARG_command].u_obj, MP_QSTR_command); - const mcu_pin_obj_t *chip_select = validate_obj_is_free_pin_or_none(args[ARG_chip_select].u_obj, MP_QSTR_chip_select); - const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset); - mp_obj_t spi = mp_arg_validate_type(args[ARG_spi_bus].u_obj, &busio_spi_type, MP_QSTR_spi_bus); fourwire_fourwire_obj_t *self = &allocate_display_bus_or_raise()->fourwire_bus; @@ -81,7 +82,7 @@ static mp_obj_t fourwire_fourwire_make_new(const mp_obj_type_t *type, size_t n_a uint8_t phase = (uint8_t)mp_arg_validate_int_range(args[ARG_phase].u_int, 0, 1, MP_QSTR_phase); common_hal_fourwire_fourwire_construct(self, - MP_OBJ_TO_PTR(spi), command, chip_select, reset, args[ARG_baudrate].u_int, polarity, phase); + MP_OBJ_TO_PTR(spi), args[ARG_command].u_obj, args[ARG_chip_select].u_obj, args[ARG_reset].u_obj, args[ARG_baudrate].u_int, polarity, phase); return self; } @@ -89,6 +90,7 @@ static mp_obj_t fourwire_fourwire_make_new(const mp_obj_type_t *type, size_t n_a //| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin //| is available.""" //| ... +//| static mp_obj_t fourwire_fourwire_obj_reset(mp_obj_t self_in) { fourwire_fourwire_obj_t *self = self_in; @@ -106,6 +108,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(fourwire_fourwire_reset_obj, fourwire_fourwire_obj_res //| vertical scroll, set via ``send`` may or may not be reset once the code is done.""" //| ... //| +//| static mp_obj_t fourwire_fourwire_obj_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_command, ARG_data, ARG_toggle_every_byte }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/fourwire/FourWire.h b/shared-bindings/fourwire/FourWire.h index 515a466b4b98c..3e77c25434d64 100644 --- a/shared-bindings/fourwire/FourWire.h +++ b/shared-bindings/fourwire/FourWire.h @@ -16,8 +16,8 @@ extern const mp_obj_type_t fourwire_fourwire_type; void common_hal_fourwire_fourwire_construct(fourwire_fourwire_obj_t *self, - busio_spi_obj_t *spi, const mcu_pin_obj_t *command, - const mcu_pin_obj_t *chip_select, const mcu_pin_obj_t *reset, uint32_t baudrate, + busio_spi_obj_t *spi, mp_obj_t command, + mp_obj_t chip_select, mp_obj_t reset, uint32_t baudrate, uint8_t polarity, uint8_t phase); void common_hal_fourwire_fourwire_deinit(fourwire_fourwire_obj_t *self); diff --git a/shared-bindings/fourwire/__init__.c b/shared-bindings/fourwire/__init__.c index 34542db97a7e1..659d9482cb57b 100644 --- a/shared-bindings/fourwire/__init__.c +++ b/shared-bindings/fourwire/__init__.c @@ -13,9 +13,7 @@ #include "shared-bindings/fourwire/__init__.h" #include "shared-bindings/fourwire/FourWire.h" -//| """Connects to a BusDisplay over a four wire bus -//| -//| """ +//| """Connects to a BusDisplay over a four wire bus""" static const mp_rom_map_elem_t fourwire_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_fourwire) }, diff --git a/shared-bindings/framebufferio/FramebufferDisplay.c b/shared-bindings/framebufferio/FramebufferDisplay.c index 29242d3a632b0..71ce18a1b4bdc 100644 --- a/shared-bindings/framebufferio/FramebufferDisplay.c +++ b/shared-bindings/framebufferio/FramebufferDisplay.c @@ -31,7 +31,7 @@ //| framebuffer: circuitpython_typing.FrameBuffer, //| *, //| rotation: int = 0, -//| auto_refresh: bool = True +//| auto_refresh: bool = True, //| ) -> None: //| """Create a Display object with the given framebuffer (a buffer, array, ulab.array, etc) //| @@ -40,6 +40,7 @@ //| :param int rotation: The rotation of the display in degrees clockwise. Must be in 90 degree increments (0, 90, 180, 270) //| """ //| ... +//| static mp_obj_t framebufferio_framebufferdisplay_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_framebuffer, ARG_rotation, ARG_auto_refresh, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -89,7 +90,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_show_obj, framebuffer //| self, //| *, //| target_frames_per_second: Optional[int] = None, -//| minimum_frames_per_second: int = 0 +//| minimum_frames_per_second: int = 0, //| ) -> bool: //| """When auto_refresh is off, and :py:attr:`target_frames_per_second` is not `None` this waits //| for the target frame rate and then refreshes the display, @@ -111,6 +112,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(framebufferio_framebufferdisplay_show_obj, framebuffer //| :param int minimum_frames_per_second: The minimum number of times the screen should be updated per second. //| """ //| ... +//| static mp_obj_t framebufferio_framebufferdisplay_obj_refresh(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_target_frames_per_second, ARG_minimum_frames_per_second }; static const mp_arg_t allowed_args[] = { @@ -232,6 +234,7 @@ MP_PROPERTY_GETSET(framebufferio_framebufferdisplay_rotation_obj, //| framebuffer: circuitpython_typing.FrameBuffer //| """The framebuffer being used by the display""" +//| static mp_obj_t framebufferio_framebufferdisplay_obj_get_framebuffer(mp_obj_t self_in) { framebufferio_framebufferdisplay_obj_t *self = native_display(self_in); return common_hal_framebufferio_framebufferdisplay_get_framebuffer(self); @@ -249,6 +252,7 @@ MP_PROPERTY_GETTER(framebufferio_framebufferframebuffer_obj, //| :param ~circuitpython_typing.WriteableBuffer buffer: The buffer in which to place the pixel data //| """ //| ... +//| static mp_obj_t framebufferio_framebufferdisplay_obj_fill_row(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_y, ARG_buffer }; static const mp_arg_t allowed_args[] = { @@ -309,6 +313,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(framebufferio_framebufferdisplay_fill_row_obj, 1, fra //| If the root group is set to ``None``, no output will be shown. //| """ //| +//| static mp_obj_t framebufferio_framebufferdisplay_obj_get_root_group(mp_obj_t self_in) { framebufferio_framebufferdisplay_obj_t *self = native_display(self_in); return common_hal_framebufferio_framebufferdisplay_get_root_group(self); diff --git a/shared-bindings/frequencyio/FrequencyIn.c b/shared-bindings/frequencyio/FrequencyIn.c index 5bd18658d70b8..d742655b11d3c 100644 --- a/shared-bindings/frequencyio/FrequencyIn.c +++ b/shared-bindings/frequencyio/FrequencyIn.c @@ -49,6 +49,7 @@ //| # as the value. //| frequency.clear()""" //| ... +//| static mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_check_num(n_args, n_kw, 1, 1, true); @@ -64,8 +65,7 @@ static mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size const uint16_t capture_period = args[ARG_capture_period].u_int; - frequencyio_frequencyin_obj_t *self = m_new_obj_with_finaliser(frequencyio_frequencyin_obj_t); - self->base.type = &frequencyio_frequencyin_type; + frequencyio_frequencyin_obj_t *self = mp_obj_malloc_with_finaliser(frequencyio_frequencyin_obj_t, &frequencyio_frequencyin_type); common_hal_frequencyio_frequencyin_construct(self, pin, capture_period); return MP_OBJ_FROM_PTR(self); @@ -74,6 +74,7 @@ static mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size //| def deinit(self) -> None: //| """Deinitialises the FrequencyIn and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t frequencyio_frequencyin_deinit(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_frequencyio_frequencyin_deinit(self); @@ -90,22 +91,20 @@ static void check_for_deinit(frequencyio_frequencyin_obj_t *self) { //| def __enter__(self) -> FrequencyIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t frequencyio_frequencyin_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_frequencyio_frequencyin_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(frequencyio_frequencyin___exit___obj, 4, 4, frequencyio_frequencyin_obj___exit__); +//| +// Provided by context manager helper. //| def pause(self) -> None: //| """Pause frequency capture.""" //| ... +//| static mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -118,6 +117,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_pause_obj, frequencyio_frequen //| def resume(self) -> None: //| """Resumes frequency capture.""" //| ... +//| static mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -130,6 +130,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_resume_obj, frequencyio_freque //| def clear(self) -> None: //| """Clears the last detected frequency capture value.""" //| ... +//| static mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -147,6 +148,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_clear_obj, frequencyio_frequen //| //| .. note:: When setting a new ``capture_period``, all previous capture information is //| cleared with a call to ``clear()``.""" +//| static mp_obj_t frequencyio_frequencyin_obj_get_capture_period(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -172,6 +174,7 @@ MP_PROPERTY_GETSET(frequencyio_frequencyin_capture_period_obj, //| """Returns the value of the last frequency captured.""" //| ... //| +//| static mp_obj_t frequencyio_frequencyin_obj_get_value(mp_obj_t self_in) { frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -189,7 +192,7 @@ static const mp_rom_map_elem_t frequencyio_frequencyin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&frequencyio_frequencyin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&frequencyio_frequencyin_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&frequencyio_frequencyin___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&frequencyio_frequencyin_value_obj) }, { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&frequencyio_frequencyin_pause_obj) }, { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&frequencyio_frequencyin_resume_obj) }, diff --git a/shared-bindings/getpass/__init__.c b/shared-bindings/getpass/__init__.c index b779311f5fc36..54a860aa569e6 100644 --- a/shared-bindings/getpass/__init__.c +++ b/shared-bindings/getpass/__init__.c @@ -12,8 +12,10 @@ //| This module provides a way to get input from user without echoing it. //| //| """ +//| //| ... //| +//| //| def getpass(prompt: Optional[str] = "Password: ", stream: Optional[io.FileIO] = None) -> str: //| """Prompt the user without echoing. @@ -24,6 +26,7 @@ //| """ //| ... //| +//| static mp_obj_t getpass_getpass(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_prompt, ARG_stream }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/gifio/GifWriter.c b/shared-bindings/gifio/GifWriter.c index c1a2c69c59926..f649a9299c0a8 100644 --- a/shared-bindings/gifio/GifWriter.c +++ b/shared-bindings/gifio/GifWriter.c @@ -33,6 +33,7 @@ //| :param dither: If True, and the image is in color, a simple ordered dither is applied. //| """ //| ... +//| static mp_obj_t gifio_gifwriter_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_file, ARG_width, ARG_height, ARG_colorspace, ARG_loop, ARG_dither }; static const mp_arg_t allowed_args[] = { @@ -71,12 +72,14 @@ static mp_obj_t gifio_gifwriter_make_new(const mp_obj_type_t *type, size_t n_arg //| def __enter__(self) -> GifWriter: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... +//| static mp_obj_t gifio_gifwriter___exit__(size_t n_args, const mp_obj_t *args) { gifio_gifwriter_t *self = MP_OBJ_TO_PTR(args[0]); shared_module_gifio_gifwriter_deinit(self); @@ -87,6 +90,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gifio_gifwriter___exit___obj, 4, 4, gifio_gi //| def deinit(self) -> None: //| """Close the underlying file.""" //| ... +//| static mp_obj_t gifio_gifwriter_deinit(mp_obj_t self_in) { gifio_gifwriter_t *self = MP_OBJ_TO_PTR(self_in); shared_module_gifio_gifwriter_deinit(self); @@ -102,6 +106,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(gifio_gifwriter_deinit_obj, gifio_gifwriter_deinit); //| """ //| ... //| +//| static mp_obj_t gifio_gifwriter_add_frame(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bitmap, ARG_delay }; static const mp_arg_t allowed_args[] = { @@ -131,7 +136,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(gifio_gifwriter_add_frame_obj, 1, gifio_gifwriter_add static const mp_rom_map_elem_t gifio_gifwriter_locals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_GifWriter) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&gifio_gifwriter___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gifio_gifwriter_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_add_frame), MP_ROM_PTR(&gifio_gifwriter_add_frame_obj) }, }; diff --git a/shared-bindings/gifio/OnDiskGif.c b/shared-bindings/gifio/OnDiskGif.c index 10913233f871d..092d9dd19cf7d 100644 --- a/shared-bindings/gifio/OnDiskGif.c +++ b/shared-bindings/gifio/OnDiskGif.c @@ -101,6 +101,7 @@ //| is not limited but images that are too large will cause a memory exception. //| """ //| ... +//| static mp_obj_t gifio_ondiskgif_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_filename, ARG_use_palette, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -135,18 +136,15 @@ static void check_for_deinit(gifio_ondiskgif_t *self) { //| def __enter__(self) -> OnDiskGif: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the GIF when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t gifio_ondiskgif_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_gifio_ondiskgif_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gifio_ondiskgif___exit___obj, 4, 4, gifio_ondiskgif_obj___exit__); +//| +// Provided by context manager helper. //| width: int //| """Width of the gif. (read only)""" @@ -192,6 +190,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_bitmap_obj, //| palette: Optional[displayio.Palette] //| """The palette for the current frame if it exists.""" +//| static mp_obj_t gifio_ondiskgif_obj_get_palette(mp_obj_t self_in) { gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); @@ -206,6 +205,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_palette_obj, //| def next_frame(self) -> float: //| """Loads the next frame. Returns expected delay before the next frame in seconds.""" +//| static mp_obj_t gifio_ondiskgif_obj_next_frame(mp_obj_t self_in) { gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); @@ -277,6 +277,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_max_delay_obj, //| """Release resources allocated by OnDiskGif.""" //| ... //| +//| static mp_obj_t gifio_ondiskgif_obj_deinit(mp_obj_t self_in) { gifio_ondiskgif_t *self = MP_OBJ_TO_PTR(self_in); common_hal_gifio_ondiskgif_deinit(self); @@ -287,7 +288,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_deinit_obj, gifio_ondiskgif_obj_deinit static const mp_rom_map_elem_t gifio_ondiskgif_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gifio_ondiskgif_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&gifio_ondiskgif___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&gifio_ondiskgif_height_obj) }, { MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&gifio_ondiskgif_bitmap_obj) }, { MP_ROM_QSTR(MP_QSTR_palette), MP_ROM_PTR(&gifio_ondiskgif_palette_obj) }, diff --git a/shared-bindings/gifio/__init__.c b/shared-bindings/gifio/__init__.c index 057d18ce82d47..2c1d5c8924626 100644 --- a/shared-bindings/gifio/__init__.c +++ b/shared-bindings/gifio/__init__.c @@ -10,11 +10,10 @@ #include "shared-bindings/gifio/OnDiskGif.h" #include "shared-bindings/util.h" -//| """Access GIF-format images -//| """ +//| """Access GIF-format images""" static const mp_rom_map_elem_t gifio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gifio) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_GifWriter), MP_ROM_PTR(&gifio_gifwriter_type)}, + { MP_ROM_QSTR(MP_QSTR_GifWriter), MP_ROM_PTR(&gifio_gifwriter_type)}, { MP_ROM_QSTR(MP_QSTR_OnDiskGif), MP_ROM_PTR(&gifio_ondiskgif_type) }, }; diff --git a/shared-bindings/gnss/GNSS.c b/shared-bindings/gnss/GNSS.c index 75093e7b55b49..3df23979c9ee1 100644 --- a/shared-bindings/gnss/GNSS.c +++ b/shared-bindings/gnss/GNSS.c @@ -36,8 +36,8 @@ //| //| :param system: satellite system to use""" //| ... -STATIC mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - gnss_obj_t *self = mp_obj_malloc(gnss_obj_t, &gnss_type); +//| +static mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_system }; static const mp_arg_t allowed_args[] = { { MP_QSTR_system, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -62,21 +62,24 @@ STATIC mp_obj_t gnss_make_new(const mp_obj_type_t *type, size_t n_args, size_t n mp_raise_TypeError(MP_ERROR_TEXT("System entry must be gnss.SatelliteSystem")); } + gnss_obj_t *self = mp_obj_malloc(gnss_obj_t, &gnss_type); common_hal_gnss_construct(self, selection); + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Turn off the GNSS.""" //| ... -STATIC mp_obj_t gnss_obj_deinit(mp_obj_t self_in) { +//| +static mp_obj_t gnss_obj_deinit(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_gnss_deinit(self); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(gnss_deinit_obj, gnss_obj_deinit); -STATIC void check_for_deinit(gnss_obj_t *self) { +static void check_for_deinit(gnss_obj_t *self) { if (common_hal_gnss_deinited(self)) { raise_deinited_error(); } @@ -85,7 +88,8 @@ STATIC void check_for_deinit(gnss_obj_t *self) { //| def update(self) -> None: //| """Update GNSS positioning information.""" //| ... -STATIC mp_obj_t gnss_obj_update(mp_obj_t self_in) { +//| +static mp_obj_t gnss_obj_update(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -96,7 +100,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(gnss_update_obj, gnss_obj_update); //| latitude: float //| """Latitude of current position in degrees (float).""" -STATIC mp_obj_t gnss_obj_get_latitude(mp_obj_t self_in) { +static mp_obj_t gnss_obj_get_latitude(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); return mp_obj_new_float(common_hal_gnss_get_latitude(self)); @@ -108,7 +112,7 @@ MP_PROPERTY_GETTER(gnss_latitude_obj, //| longitude: float //| """Longitude of current position in degrees (float).""" -STATIC mp_obj_t gnss_obj_get_longitude(mp_obj_t self_in) { +static mp_obj_t gnss_obj_get_longitude(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); return mp_obj_new_float(common_hal_gnss_get_longitude(self)); @@ -120,7 +124,7 @@ MP_PROPERTY_GETTER(gnss_longitude_obj, //| altitude: float //| """Altitude of current position in meters (float).""" -STATIC mp_obj_t gnss_obj_get_altitude(mp_obj_t self_in) { +static mp_obj_t gnss_obj_get_altitude(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); return mp_obj_new_float(common_hal_gnss_get_altitude(self)); @@ -132,7 +136,7 @@ MP_PROPERTY_GETTER(gnss_altitude_obj, //| timestamp: time.struct_time //| """Time when the position data was updated.""" -STATIC mp_obj_t gnss_obj_get_timestamp(mp_obj_t self_in) { +static mp_obj_t gnss_obj_get_timestamp(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); timeutils_struct_time_t tm; @@ -147,7 +151,8 @@ MP_PROPERTY_GETTER(gnss_timestamp_obj, //| fix: PositionFix //| """Fix mode.""" //| -STATIC mp_obj_t gnss_obj_get_fix(mp_obj_t self_in) { +//| +static mp_obj_t gnss_obj_get_fix(mp_obj_t self_in) { gnss_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); return gnss_positionfix_type_to_obj(common_hal_gnss_get_fix(self)); @@ -157,7 +162,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(gnss_get_fix_obj, gnss_obj_get_fix); MP_PROPERTY_GETTER(gnss_fix_obj, (mp_obj_t)&gnss_get_fix_obj); -STATIC const mp_rom_map_elem_t gnss_locals_dict_table[] = { +static const mp_rom_map_elem_t gnss_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&gnss_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&gnss_update_obj) }, @@ -167,7 +172,7 @@ STATIC const mp_rom_map_elem_t gnss_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_timestamp), MP_ROM_PTR(&gnss_timestamp_obj) }, { MP_ROM_QSTR(MP_QSTR_fix), MP_ROM_PTR(&gnss_fix_obj) } }; -STATIC MP_DEFINE_CONST_DICT(gnss_locals_dict, gnss_locals_dict_table); +static MP_DEFINE_CONST_DICT(gnss_locals_dict, gnss_locals_dict_table); MP_DEFINE_CONST_OBJ_TYPE( gnss_type, diff --git a/shared-bindings/gnss/PositionFix.c b/shared-bindings/gnss/PositionFix.c index d63623eb6a2f2..1b85befd89b23 100644 --- a/shared-bindings/gnss/PositionFix.c +++ b/shared-bindings/gnss/PositionFix.c @@ -9,6 +9,7 @@ //| //| def __init__(self) -> None: //| """Enum-like class to define the position fix mode.""" +//| //| INVALID: PositionFix //| """No measurement.""" //| @@ -18,6 +19,7 @@ //| FIX_3D: PositionFix //| """3D fix.""" //| +//| const mp_obj_type_t gnss_positionfix_type; const gnss_positionfix_obj_t gnss_positionfix_invalid_obj = { @@ -54,14 +56,14 @@ mp_obj_t gnss_positionfix_type_to_obj(gnss_positionfix_t posfix) { } } -STATIC const mp_rom_map_elem_t gnss_positionfix_locals_dict_table[] = { +static const mp_rom_map_elem_t gnss_positionfix_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_INVALID), MP_ROM_PTR(&gnss_positionfix_invalid_obj)}, {MP_ROM_QSTR(MP_QSTR_FIX_2D), MP_ROM_PTR(&gnss_positionfix_fix2d_obj)}, {MP_ROM_QSTR(MP_QSTR_FIX_3D), MP_ROM_PTR(&gnss_positionfix_fix3d_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(gnss_positionfix_locals_dict, gnss_positionfix_locals_dict_table); +static MP_DEFINE_CONST_DICT(gnss_positionfix_locals_dict, gnss_positionfix_locals_dict_table); -STATIC void gnss_positionfix_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void gnss_positionfix_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { qstr posfix = MP_QSTR_INVALID; if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_positionfix_fix2d_obj)) { posfix = MP_QSTR_FIX_2D; diff --git a/shared-bindings/gnss/SatelliteSystem.c b/shared-bindings/gnss/SatelliteSystem.c index c9e71f2c8f502..1d6168f61f906 100644 --- a/shared-bindings/gnss/SatelliteSystem.c +++ b/shared-bindings/gnss/SatelliteSystem.c @@ -9,6 +9,7 @@ //| //| def __init__(self) -> None: //| """Enum-like class to define the satellite system type.""" +//| //| GPS: SatelliteSystem //| """Global Positioning System.""" //| @@ -24,6 +25,7 @@ //| QZSS_L1S: SatelliteSystem //| """Quasi-Zenith Satellite System L1S.""" //| +//| const mp_obj_type_t gnss_satellitesystem_type; const gnss_satellitesystem_obj_t gnss_satellitesystem_gps_obj = { @@ -79,16 +81,16 @@ mp_obj_t gnss_satellitesystem_type_to_obj(gnss_satellitesystem_t system) { } } -STATIC const mp_rom_map_elem_t gnss_satellitesystem_locals_dict_table[] = { +static const mp_rom_map_elem_t gnss_satellitesystem_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_GPS), MP_ROM_PTR(&gnss_satellitesystem_gps_obj)}, {MP_ROM_QSTR(MP_QSTR_GLONASS), MP_ROM_PTR(&gnss_satellitesystem_glonass_obj)}, {MP_ROM_QSTR(MP_QSTR_SBAS), MP_ROM_PTR(&gnss_satellitesystem_sbas_obj)}, {MP_ROM_QSTR(MP_QSTR_QZSS_L1CA), MP_ROM_PTR(&gnss_satellitesystem_qzss_l1ca_obj)}, {MP_ROM_QSTR(MP_QSTR_QZSS_L1S), MP_ROM_PTR(&gnss_satellitesystem_qzss_l1s_obj)}, }; -STATIC MP_DEFINE_CONST_DICT(gnss_satellitesystem_locals_dict, gnss_satellitesystem_locals_dict_table); +static MP_DEFINE_CONST_DICT(gnss_satellitesystem_locals_dict, gnss_satellitesystem_locals_dict_table); -STATIC void gnss_satellitesystem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void gnss_satellitesystem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { qstr system = MP_QSTR_None; if (MP_OBJ_TO_PTR(self_in) == MP_ROM_PTR(&gnss_satellitesystem_gps_obj)) { system = MP_QSTR_GPS; diff --git a/shared-bindings/gnss/__init__.c b/shared-bindings/gnss/__init__.c index 4409b0be1b360..beaeb117c19ba 100644 --- a/shared-bindings/gnss/__init__.c +++ b/shared-bindings/gnss/__init__.c @@ -13,7 +13,7 @@ //| """Global Navigation Satellite System //| //| The `gnss` module contains classes to control the GNSS and acquire positioning information.""" -STATIC const mp_rom_map_elem_t gnss_module_globals_table[] = { +static const mp_rom_map_elem_t gnss_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gnss) }, { MP_ROM_QSTR(MP_QSTR_GNSS), MP_ROM_PTR(&gnss_type) }, @@ -22,7 +22,7 @@ STATIC const mp_rom_map_elem_t gnss_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_PositionFix), MP_ROM_PTR(&gnss_positionfix_type) }, }; -STATIC MP_DEFINE_CONST_DICT(gnss_module_globals, gnss_module_globals_table); +static MP_DEFINE_CONST_DICT(gnss_module_globals, gnss_module_globals_table); const mp_obj_module_t gnss_module = { .base = { &mp_type_module }, diff --git a/shared-bindings/hashlib/Hash.c b/shared-bindings/hashlib/Hash.c index 68930b137e4ea..a82698432aec9 100644 --- a/shared-bindings/hashlib/Hash.c +++ b/shared-bindings/hashlib/Hash.c @@ -18,6 +18,7 @@ //| digest_size: int //| """Digest size in bytes""" +//| static mp_obj_t hashlib_hash_digest_size_get(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &hashlib_hash_type)); hashlib_hash_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -32,6 +33,7 @@ MP_PROPERTY_GETTER(hashlib_hash_digest_size_obj, (mp_obj_t)&hashlib_hash_digest_ //| :param ~circuitpython_typing.ReadableBuffer data: Update the hash from data in this buffer //| """ //| ... +//| mp_obj_t hashlib_hash_update(mp_obj_t self_in, mp_obj_t buf_in) { mp_check_self(mp_obj_is_type(self_in, &hashlib_hash_type)); hashlib_hash_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -48,6 +50,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(hashlib_hash_update_obj, hashlib_hash_update); //| """Returns the current digest as bytes() with a length of `hashlib.Hash.digest_size`.""" //| ... //| +//| static mp_obj_t hashlib_hash_digest(mp_obj_t self_in) { mp_check_self(mp_obj_is_type(self_in, &hashlib_hash_type)); hashlib_hash_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/hashlib/__init__.c b/shared-bindings/hashlib/__init__.c index fa3b1b1872527..354529cfa77cd 100644 --- a/shared-bindings/hashlib/__init__.c +++ b/shared-bindings/hashlib/__init__.c @@ -17,14 +17,16 @@ //| |see_cpython_module| :mod:`cpython:hashlib`. //| """ //| +//| //| def new(name: str, data: bytes = b"") -> hashlib.Hash: //| """Returns a Hash object setup for the named algorithm. Raises ValueError when the named -//| algorithm is unsupported. +//| algorithm is unsupported. Supported algorithms for ``name`` are ``'sha1'`` and ``'sha256'``. //| //| :return: a hash object for the given algorithm //| :rtype: hashlib.Hash""" //| ... //| +//| static mp_obj_t hashlib_new(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_name, ARG_data }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/i2cdisplaybus/I2CDisplayBus.c b/shared-bindings/i2cdisplaybus/I2CDisplayBus.c index 065baa782fcc9..8633f166805d2 100644 --- a/shared-bindings/i2cdisplaybus/I2CDisplayBus.c +++ b/shared-bindings/i2cdisplaybus/I2CDisplayBus.c @@ -19,14 +19,18 @@ //| class I2CDisplayBus: //| """Manage updating a display over I2C in the background while Python code runs. -//| It doesn't handle display initialization.""" +//| It doesn't handle display initialization. +//| +//| .. seealso:: See `busdisplay.BusDisplay` and `epaperdisplay.EPaperDisplay` +//| for how to initialize a display, given an `I2CDisplayBus`. +//| """ //| //| def __init__( //| self, //| i2c_bus: busio.I2C, //| *, //| device_address: int, -//| reset: Optional[microcontroller.Pin] = None +//| reset: Optional[microcontroller.Pin] = None, //| ) -> None: //| """Create a I2CDisplayBus object associated with the given I2C bus and reset pin. //| @@ -40,6 +44,7 @@ //| :param microcontroller.Pin reset: Reset pin. When None only software reset can be used //| """ //| ... +//| static mp_obj_t i2cdisplaybus_i2cdisplaybus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_i2c_bus, ARG_device_address, ARG_reset }; static const mp_arg_t allowed_args[] = { @@ -65,6 +70,7 @@ static mp_obj_t i2cdisplaybus_i2cdisplaybus_make_new(const mp_obj_type_t *type, //| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin //| is available.""" //| ... +//| static mp_obj_t i2cdisplaybus_i2cdisplaybus_obj_reset(mp_obj_t self_in) { i2cdisplaybus_i2cdisplaybus_obj_t *self = self_in; @@ -80,6 +86,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(i2cdisplaybus_i2cdisplaybus_reset_obj, i2cdisplaybus_i //| vertical scroll, set via ``send`` may or may not be reset once the code is done.""" //| ... //| +//| static mp_obj_t i2cdisplaybus_i2cdisplaybus_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) { mp_int_t command_int = mp_obj_get_int(command_obj); mp_arg_validate_int_range(command_int, 0, 255, MP_QSTR_command); diff --git a/shared-bindings/i2cdisplaybus/__init__.c b/shared-bindings/i2cdisplaybus/__init__.c index 45be89668f028..dc25571758307 100644 --- a/shared-bindings/i2cdisplaybus/__init__.c +++ b/shared-bindings/i2cdisplaybus/__init__.c @@ -13,9 +13,7 @@ #include "shared-bindings/i2cdisplaybus/__init__.h" #include "shared-bindings/i2cdisplaybus/I2CDisplayBus.h" -//| """Communicates to a display IC over I2C -//| -//| """ +//| """Communicates to a display IC over I2C""" static const mp_rom_map_elem_t i2cdisplaybus_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2cdisplaybus) }, diff --git a/shared-bindings/i2cioexpander/IOExpander.c b/shared-bindings/i2cioexpander/IOExpander.c new file mode 100644 index 0000000000000..3efa0fd18685f --- /dev/null +++ b/shared-bindings/i2cioexpander/IOExpander.c @@ -0,0 +1,247 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "shared-bindings/i2cioexpander/IOExpander.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/util.h" +#include "shared/runtime/context_manager_helpers.h" + +//| class IOExpander: +//| """Control a generic I2C-based GPIO expander +//| +//| IOExpander provides a simple interface to I2C-based GPIO expanders that +//| use basic register reads and writes for control. The expander provides +//| individual pins through the `pins` attribute that implement the +//| DigitalInOutProtocol. +//| """ +//| +//| def __init__( +//| self, +//| i2c: busio.I2C, +//| address: int, +//| num_pins: int, +//| set_value_reg: Optional[int] = None, +//| get_value_reg: Optional[int] = None, +//| set_direction_reg: Optional[int] = None, +//| ) -> None: +//| """Initialize an I2C GPIO expander +//| +//| :param busio.I2C i2c: The I2C bus the expander is connected to +//| :param int address: The I2C device address +//| :param int num_pins: The number of GPIO pins (8 or 16) +//| :param int set_value_reg: Register address to write pin values (optional) +//| :param int get_value_reg: Register address to read pin values (optional) +//| :param int set_direction_reg: Register address to set pin directions (optional) +//| """ +//| ... + +static mp_obj_t i2cioexpander_ioexpander_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_i2c, ARG_address, ARG_num_pins, ARG_set_value_reg, ARG_get_value_reg, ARG_set_direction_reg }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_i2c, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_num_pins, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_set_value_reg, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_get_value_reg, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_set_direction_reg, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Validate I2C object + mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c); + + // Validate address + int address = args[ARG_address].u_int; + if (address < 0 || address > 0x7F) { + mp_raise_ValueError(MP_ERROR_TEXT("address out of range")); + } + + // Validate num_pins + int num_pins = args[ARG_num_pins].u_int; + if (num_pins != 8 && num_pins != 16) { + mp_raise_ValueError(MP_ERROR_TEXT("num_pins must be 8 or 16")); + } + + // Convert and validate register parameters + uint16_t set_value_reg = NO_REGISTER; + if (args[ARG_set_value_reg].u_obj != mp_const_none) { + mp_int_t reg = mp_obj_get_int(args[ARG_set_value_reg].u_obj); + mp_arg_validate_int_range(reg, 0, 255, MP_QSTR_set_value_reg); + set_value_reg = reg; + } + + uint16_t get_value_reg = NO_REGISTER; + if (args[ARG_get_value_reg].u_obj != mp_const_none) { + mp_int_t reg = mp_obj_get_int(args[ARG_get_value_reg].u_obj); + mp_arg_validate_int_range(reg, 0, 255, MP_QSTR_get_value_reg); + get_value_reg = reg; + } + + uint16_t set_direction_reg = NO_REGISTER; + if (args[ARG_set_direction_reg].u_obj != mp_const_none) { + mp_int_t reg = mp_obj_get_int(args[ARG_set_direction_reg].u_obj); + mp_arg_validate_int_range(reg, 0, 255, MP_QSTR_set_direction_reg); + set_direction_reg = reg; + } + + i2cioexpander_ioexpander_obj_t *self = + mp_obj_malloc(i2cioexpander_ioexpander_obj_t, &i2cioexpander_ioexpander_type); + common_hal_i2cioexpander_ioexpander_construct( + self, + i2c, + address, + num_pins, + set_value_reg, + get_value_reg, + set_direction_reg); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitialize the expander. No further operations are possible.""" +//| ... +static mp_obj_t i2cioexpander_ioexpander_deinit(mp_obj_t self_in) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_i2cioexpander_ioexpander_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_ioexpander_deinit_obj, i2cioexpander_ioexpander_deinit); + +//| def __enter__(self) -> IOExpander: +//| """No-op used by Context Managers.""" +//| ... +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +static mp_obj_t i2cioexpander_ioexpander___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_i2cioexpander_ioexpander_deinit(MP_OBJ_TO_PTR(args[0])); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2cioexpander_ioexpander___exit___obj, 4, 4, i2cioexpander_ioexpander___exit__); + +//| @property +//| def input_value(self) -> int: +//| """Read the live value of all pins at once. Returns an integer where each +//| bit represents a pin's current state.""" +//| ... +static mp_obj_t i2cioexpander_ioexpander_obj_get_input_value(mp_obj_t self_in) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t value; + if (!common_hal_i2cioexpander_ioexpander_get_input_value(self, &value)) { + mp_raise_OSError(MP_EIO); + } + return MP_OBJ_NEW_SMALL_INT(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_ioexpander_get_input_value_obj, i2cioexpander_ioexpander_obj_get_input_value); + +MP_PROPERTY_GETTER(i2cioexpander_ioexpander_input_value_obj, + (mp_obj_t)&i2cioexpander_ioexpander_get_input_value_obj); + +//| @property +//| def output_value(self) -> int: +//| """Get or set the cached output value. Reading returns the last value written, +//| not the live pin state. Writing updates the output pins.""" +//| ... +//| @output_value.setter +//| def output_value(self, val: int) -> None: ... +static mp_obj_t i2cioexpander_ioexpander_obj_get_output_value(mp_obj_t self_in) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t value; + common_hal_i2cioexpander_ioexpander_get_output_value(self, &value); + return mp_obj_new_int(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_ioexpander_get_output_value_obj, i2cioexpander_ioexpander_obj_get_output_value); + +static mp_obj_t i2cioexpander_ioexpander_obj_set_output_value(mp_obj_t self_in, mp_obj_t value) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_negative_errno_t result = common_hal_i2cioexpander_ioexpander_set_output_value(self, mp_obj_get_int(value)); + if (result != 0) { + mp_raise_OSError(result); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_ioexpander_set_output_value_obj, i2cioexpander_ioexpander_obj_set_output_value); + +MP_PROPERTY_GETSET(i2cioexpander_ioexpander_output_value_obj, + (mp_obj_t)&i2cioexpander_ioexpander_get_output_value_obj, + (mp_obj_t)&i2cioexpander_ioexpander_set_output_value_obj); + +//| @property +//| def output_mask(self) -> int: +//| """Get or set which pins are configured as outputs. Each bit in the mask +//| represents a pin: 1 for output, 0 for input.""" +//| ... +//| @output_mask.setter +//| def output_mask(self, val: int) -> None: ... +static mp_obj_t i2cioexpander_ioexpander_obj_get_output_mask(mp_obj_t self_in) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + size_t output_mask; + common_hal_i2cioexpander_ioexpander_get_output_mask(self, &output_mask); + return mp_obj_new_int(output_mask); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_ioexpander_get_output_mask_obj, i2cioexpander_ioexpander_obj_get_output_mask); + +static mp_obj_t i2cioexpander_ioexpander_obj_set_output_mask(mp_obj_t self_in, mp_obj_t value) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_negative_errno_t result = common_hal_i2cioexpander_ioexpander_set_output_mask(self, mp_obj_get_int(value)); + if (result != 0) { + mp_raise_OSError(result); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_ioexpander_set_output_mask_obj, i2cioexpander_ioexpander_obj_set_output_mask); + +MP_PROPERTY_GETSET(i2cioexpander_ioexpander_output_mask_obj, + (mp_obj_t)&i2cioexpander_ioexpander_get_output_mask_obj, + (mp_obj_t)&i2cioexpander_ioexpander_set_output_mask_obj); + +//| @property +//| def pins(self) -> Tuple[IOPin, ...]: +//| """A tuple of `IOPin` objects that implement the DigitalInOutProtocol. +//| Each pin can be used like a digitalio.DigitalInOut object.""" +//| ... +static mp_obj_t i2cioexpander_ioexpander_obj_get_pins(mp_obj_t self_in) { + i2cioexpander_ioexpander_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_ioexpander_get_pins(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_ioexpander_get_pins_obj, i2cioexpander_ioexpander_obj_get_pins); + +MP_PROPERTY_GETTER(i2cioexpander_ioexpander_pins_obj, + (mp_obj_t)&i2cioexpander_ioexpander_get_pins_obj); + +static const mp_rom_map_elem_t i2cioexpander_ioexpander_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&i2cioexpander_ioexpander_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2cioexpander_ioexpander___exit___obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_input_value), MP_ROM_PTR(&i2cioexpander_ioexpander_input_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_output_value), MP_ROM_PTR(&i2cioexpander_ioexpander_output_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_output_mask), MP_ROM_PTR(&i2cioexpander_ioexpander_output_mask_obj) }, + { MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&i2cioexpander_ioexpander_pins_obj) }, +}; +static MP_DEFINE_CONST_DICT(i2cioexpander_ioexpander_locals_dict, i2cioexpander_ioexpander_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + i2cioexpander_ioexpander_type, + MP_QSTR_IOExpander, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, i2cioexpander_ioexpander_make_new, + locals_dict, &i2cioexpander_ioexpander_locals_dict + ); diff --git a/shared-bindings/i2cioexpander/IOExpander.h b/shared-bindings/i2cioexpander/IOExpander.h new file mode 100644 index 0000000000000..5c93c6250cc7d --- /dev/null +++ b/shared-bindings/i2cioexpander/IOExpander.h @@ -0,0 +1,34 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/i2cioexpander/IOExpander.h" + +extern const mp_obj_type_t i2cioexpander_ioexpander_type; + +void common_hal_i2cioexpander_ioexpander_construct( + i2cioexpander_ioexpander_obj_t *self, + mp_obj_t i2c, + uint8_t address, + uint8_t num_pins, + uint16_t set_value_reg, + uint16_t get_value_reg, + uint16_t set_direction_reg); + +void common_hal_i2cioexpander_ioexpander_deinit(i2cioexpander_ioexpander_obj_t *self); +bool common_hal_i2cioexpander_ioexpander_deinited(i2cioexpander_ioexpander_obj_t *self); + +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_get_input_value(i2cioexpander_ioexpander_obj_t *self, size_t *value); +// No error return because this returns a cached value. +void common_hal_i2cioexpander_ioexpander_get_output_value(i2cioexpander_ioexpander_obj_t *self, size_t *value); +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_set_output_value(i2cioexpander_ioexpander_obj_t *self, size_t value); + +void common_hal_i2cioexpander_ioexpander_get_output_mask(i2cioexpander_ioexpander_obj_t *self, size_t *mask); +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_set_output_mask(i2cioexpander_ioexpander_obj_t *self, size_t mask); + +mp_obj_t common_hal_i2cioexpander_ioexpander_get_pins(i2cioexpander_ioexpander_obj_t *self); diff --git a/shared-bindings/i2cioexpander/IOPin.c b/shared-bindings/i2cioexpander/IOPin.c new file mode 100644 index 0000000000000..bba229bd31e22 --- /dev/null +++ b/shared-bindings/i2cioexpander/IOPin.c @@ -0,0 +1,326 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/i2cioexpander/IOPin.h" +#include "shared-module/i2cioexpander/IOPin.h" + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/digitalio/Pull.h" +#include "shared-bindings/util.h" + +static void check_result(digitalinout_result_t result) { + switch (result) { + case DIGITALINOUT_OK: + return; + case DIGITALINOUT_PIN_BUSY: + mp_raise_ValueError_varg(MP_ERROR_TEXT("%q in use"), MP_QSTR_Pin); + #if CIRCUITPY_DIGITALIO_HAVE_INPUT_ONLY + case DIGITALINOUT_INPUT_ONLY: + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_direction); + #endif + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL + case DIGITALINOUT_INVALID_PULL: + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_pull); + #endif + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE + case DIGITALINOUT_INVALID_DRIVE_MODE: + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_drive_mode); + #endif + } +} + +static inline void check_for_deinit(i2cioexpander_iopin_obj_t *self) { + if (common_hal_i2cioexpander_iopin_deinited(self)) { + raise_deinited_error(); + } +} +//| class IOPin: +//| """Control a single pin on an `IOExpander` in the same way as `DigitalInOut`. +//| +//| Not constructed directly. Get from `IOExpander.pins` instead. +//| """ +//| + +//| def switch_to_output( +//| self, value: bool = False, drive_mode: digitalio.DriveMode = digitalio.DriveMode.PUSH_PULL +//| ) -> None: +//| """Set the drive mode and value and then switch to writing out digital values. +//| +//| :param bool value: default value to set upon switching +//| :param digitalio.DriveMode drive_mode: drive mode for the output""" +//| ... +static mp_obj_t i2cioexpander_iopin_switch_to_output(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_value, ARG_drive_mode }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_drive_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&digitalio_drive_mode_push_pull_obj)} }, + }; + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + digitalio_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL; + if (args[ARG_drive_mode].u_rom_obj == MP_ROM_PTR(&digitalio_drive_mode_open_drain_obj)) { + drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + check_result(common_hal_i2cioexpander_iopin_switch_to_output(self, args[ARG_value].u_bool, drive_mode)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(i2cioexpander_iopin_switch_to_output_obj, 1, i2cioexpander_iopin_switch_to_output); + +//| def switch_to_input(self, pull: Optional[digitalio.Pull] = None) -> None: +//| """Set the pull and then switch to read in digital values. +//| +//| :param digitalio.Pull pull: pull configuration for the input""" +//| ... +static mp_obj_t i2cioexpander_iopin_switch_to_input(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_pull }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, + }; + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + check_result(common_hal_i2cioexpander_iopin_switch_to_input(self, validate_pull(args[ARG_pull].u_rom_obj, MP_QSTR_pull))); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(i2cioexpander_iopin_switch_to_input_obj, 1, i2cioexpander_iopin_switch_to_input); + +//| direction: digitalio.Direction +//| """The direction of the pin.""" +static mp_obj_t i2cioexpander_iopin_obj_get_direction(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + digitalio_direction_t direction = common_hal_i2cioexpander_iopin_get_direction(self); + if (direction == DIRECTION_INPUT) { + return MP_OBJ_FROM_PTR(&digitalio_direction_input_obj); + } + return MP_OBJ_FROM_PTR(&digitalio_direction_output_obj); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_iopin_get_direction_obj, i2cioexpander_iopin_obj_get_direction); + +static mp_obj_t i2cioexpander_iopin_obj_set_direction(mp_obj_t self_in, mp_obj_t value) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (value == MP_ROM_PTR(&digitalio_direction_input_obj)) { + check_result(common_hal_i2cioexpander_iopin_switch_to_input(self, PULL_NONE)); + } else if (value == MP_ROM_PTR(&digitalio_direction_output_obj)) { + check_result(common_hal_i2cioexpander_iopin_switch_to_output(self, false, DRIVE_MODE_PUSH_PULL)); + } else { + mp_arg_error_invalid(MP_QSTR_direction); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_iopin_set_direction_obj, i2cioexpander_iopin_obj_set_direction); + +MP_PROPERTY_GETSET(i2cioexpander_iopin_direction_obj, + (mp_obj_t)&i2cioexpander_iopin_get_direction_obj, + (mp_obj_t)&i2cioexpander_iopin_set_direction_obj); + +//| value: bool +//| """The digital logic level of the pin.""" +static mp_obj_t i2cioexpander_iopin_obj_get_value(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + bool value; + mp_negative_errno_t res = common_hal_i2cioexpander_iopin_get_value(self, &value); + if (res != 0) { + mp_raise_OSError(-res); + } + return mp_obj_new_bool(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_iopin_get_value_obj, i2cioexpander_iopin_obj_get_value); + +static mp_obj_t i2cioexpander_iopin_obj_set_value(mp_obj_t self_in, mp_obj_t value) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (common_hal_i2cioexpander_iopin_get_direction(self) == DIRECTION_INPUT) { + mp_raise_AttributeError(MP_ERROR_TEXT("Cannot set value when direction is input.")); + return mp_const_none; + } + mp_negative_errno_t res = common_hal_i2cioexpander_iopin_set_value(self, mp_obj_is_true(value)); + if (res != 0) { + mp_raise_OSError(-res); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_iopin_set_value_obj, i2cioexpander_iopin_obj_set_value); + +MP_PROPERTY_GETSET(i2cioexpander_iopin_value_obj, + (mp_obj_t)&i2cioexpander_iopin_get_value_obj, + (mp_obj_t)&i2cioexpander_iopin_set_value_obj); + +//| drive_mode: digitalio.DriveMode +//| """The pin drive mode.""" +static mp_obj_t i2cioexpander_iopin_obj_get_drive_mode(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (common_hal_i2cioexpander_iopin_get_direction(self) == DIRECTION_INPUT) { + mp_raise_AttributeError(MP_ERROR_TEXT("Drive mode not used when direction is input.")); + return mp_const_none; + } + digitalio_drive_mode_t drive_mode = common_hal_i2cioexpander_iopin_get_drive_mode(self); + if (drive_mode == DRIVE_MODE_PUSH_PULL) { + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_push_pull_obj); + } + return MP_OBJ_FROM_PTR(&digitalio_drive_mode_open_drain_obj); +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_iopin_get_drive_mode_obj, i2cioexpander_iopin_obj_get_drive_mode); + +static mp_obj_t i2cioexpander_iopin_obj_set_drive_mode(mp_obj_t self_in, mp_obj_t drive_mode) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (common_hal_i2cioexpander_iopin_get_direction(self) == DIRECTION_INPUT) { + mp_raise_AttributeError(MP_ERROR_TEXT("Drive mode not used when direction is input.")); + return mp_const_none; + } + digitalio_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL; + if (drive_mode == MP_ROM_PTR(&digitalio_drive_mode_open_drain_obj)) { + c_drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + check_result(common_hal_i2cioexpander_iopin_set_drive_mode(self, c_drive_mode)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_iopin_set_drive_mode_obj, i2cioexpander_iopin_obj_set_drive_mode); + +MP_PROPERTY_GETSET(i2cioexpander_iopin_drive_mode_obj, + (mp_obj_t)&i2cioexpander_iopin_get_drive_mode_obj, + (mp_obj_t)&i2cioexpander_iopin_set_drive_mode_obj); + +//| pull: Optional[digitalio.Pull] +//| """The pin pull direction.""" +static mp_obj_t i2cioexpander_iopin_obj_get_pull(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (common_hal_i2cioexpander_iopin_get_direction(self) == DIRECTION_OUTPUT) { + mp_raise_AttributeError(MP_ERROR_TEXT("Pull not used when direction is output.")); + return mp_const_none; + } + digitalio_pull_t pull = common_hal_i2cioexpander_iopin_get_pull(self); + if (pull == PULL_UP) { + return MP_OBJ_FROM_PTR(&digitalio_pull_up_obj); + } else if (pull == PULL_DOWN) { + return MP_OBJ_FROM_PTR(&digitalio_pull_down_obj); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(i2cioexpander_iopin_get_pull_obj, i2cioexpander_iopin_obj_get_pull); + +static mp_obj_t i2cioexpander_iopin_obj_set_pull(mp_obj_t self_in, mp_obj_t pull_obj) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (common_hal_i2cioexpander_iopin_get_direction(self) == DIRECTION_OUTPUT) { + mp_raise_AttributeError(MP_ERROR_TEXT("Pull not used when direction is output.")); + return mp_const_none; + } + check_result(common_hal_i2cioexpander_iopin_set_pull(self, validate_pull(pull_obj, MP_QSTR_pull))); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(i2cioexpander_iopin_set_pull_obj, i2cioexpander_iopin_obj_set_pull); + +MP_PROPERTY_GETSET(i2cioexpander_iopin_pull_obj, + (mp_obj_t)&i2cioexpander_iopin_get_pull_obj, + (mp_obj_t)&i2cioexpander_iopin_set_pull_obj); + +// Protocol implementation for DigitalInOutProtocol +static void iopin_protocol_deinit(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_i2cioexpander_iopin_deinit(self); +} + +static bool iopin_protocol_deinited(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_deinited(self); +} + +static digitalinout_result_t iopin_protocol_switch_to_input(mp_obj_t self_in, digitalio_pull_t pull) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_switch_to_input(self, pull); +} + +static digitalinout_result_t iopin_protocol_switch_to_output(mp_obj_t self_in, bool value, digitalio_drive_mode_t drive_mode) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_switch_to_output(self, value, drive_mode); +} + +static digitalio_direction_t iopin_protocol_get_direction(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_get_direction(self); +} + +static mp_negative_errno_t iopin_protocol_get_value(mp_obj_t self_in, bool *value) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_get_value(self, value); +} + +static mp_negative_errno_t iopin_protocol_set_value(mp_obj_t self_in, bool value) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_set_value(self, value); +} + +static digitalio_drive_mode_t iopin_protocol_get_drive_mode(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_get_drive_mode(self); +} + +static digitalinout_result_t iopin_protocol_set_drive_mode(mp_obj_t self_in, digitalio_drive_mode_t drive_mode) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_set_drive_mode(self, drive_mode); +} + +static digitalio_pull_t iopin_protocol_get_pull(mp_obj_t self_in) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_get_pull(self); +} + +static digitalinout_result_t iopin_protocol_set_pull(mp_obj_t self_in, digitalio_pull_t pull) { + i2cioexpander_iopin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_i2cioexpander_iopin_set_pull(self, pull); +} + +static const digitalinout_p_t iopin_digitalinout_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_DigitalInOut) + .deinit = iopin_protocol_deinit, + .deinited = iopin_protocol_deinited, + .switch_to_input = iopin_protocol_switch_to_input, + .switch_to_output = iopin_protocol_switch_to_output, + .get_direction = iopin_protocol_get_direction, + .get_value = iopin_protocol_get_value, + .set_value = iopin_protocol_set_value, + .get_drive_mode = iopin_protocol_get_drive_mode, + .set_drive_mode = iopin_protocol_set_drive_mode, + .get_pull = iopin_protocol_get_pull, + .set_pull = iopin_protocol_set_pull, +}; + +static const mp_rom_map_elem_t i2cioexpander_iopin_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_switch_to_input), MP_ROM_PTR(&i2cioexpander_iopin_switch_to_input_obj) }, + { MP_ROM_QSTR(MP_QSTR_switch_to_output), MP_ROM_PTR(&i2cioexpander_iopin_switch_to_output_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&i2cioexpander_iopin_direction_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&i2cioexpander_iopin_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_drive_mode), MP_ROM_PTR(&i2cioexpander_iopin_drive_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&i2cioexpander_iopin_pull_obj) }, +}; +static MP_DEFINE_CONST_DICT(i2cioexpander_iopin_locals_dict, i2cioexpander_iopin_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + i2cioexpander_iopin_type, + MP_QSTR_IOPin, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + protocol, &iopin_digitalinout_p, + locals_dict, &i2cioexpander_iopin_locals_dict + ); diff --git a/shared-bindings/i2cioexpander/IOPin.h b/shared-bindings/i2cioexpander/IOPin.h new file mode 100644 index 0000000000000..c8155c71aa1f3 --- /dev/null +++ b/shared-bindings/i2cioexpander/IOPin.h @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/i2cioexpander/IOPin.h" + +extern const mp_obj_type_t i2cioexpander_iopin_type; + +mp_negative_errno_t i2cioexpander_iopin_construct( + i2cioexpander_iopin_obj_t *self, + i2cioexpander_ioexpander_obj_t *expander, + uint8_t pin_number); + +void common_hal_i2cioexpander_iopin_deinit(i2cioexpander_iopin_obj_t *self); +bool common_hal_i2cioexpander_iopin_deinited(i2cioexpander_iopin_obj_t *self); + +digitalinout_result_t common_hal_i2cioexpander_iopin_switch_to_input( + i2cioexpander_iopin_obj_t *self, + digitalio_pull_t pull); + +digitalinout_result_t common_hal_i2cioexpander_iopin_switch_to_output( + i2cioexpander_iopin_obj_t *self, + bool value, + digitalio_drive_mode_t drive_mode); + +digitalio_direction_t common_hal_i2cioexpander_iopin_get_direction(i2cioexpander_iopin_obj_t *self); + +mp_negative_errno_t common_hal_i2cioexpander_iopin_set_value(i2cioexpander_iopin_obj_t *self, bool value); +mp_negative_errno_t common_hal_i2cioexpander_iopin_get_value(i2cioexpander_iopin_obj_t *self, bool *value); + +digitalinout_result_t common_hal_i2cioexpander_iopin_set_drive_mode( + i2cioexpander_iopin_obj_t *self, + digitalio_drive_mode_t drive_mode); + +digitalio_drive_mode_t common_hal_i2cioexpander_iopin_get_drive_mode(i2cioexpander_iopin_obj_t *self); + +digitalinout_result_t common_hal_i2cioexpander_iopin_set_pull( + i2cioexpander_iopin_obj_t *self, + digitalio_pull_t pull); + +digitalio_pull_t common_hal_i2cioexpander_iopin_get_pull(i2cioexpander_iopin_obj_t *self); diff --git a/shared-bindings/i2cioexpander/__init__.c b/shared-bindings/i2cioexpander/__init__.c new file mode 100644 index 0000000000000..106c45c3768bf --- /dev/null +++ b/shared-bindings/i2cioexpander/__init__.c @@ -0,0 +1,49 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/i2cioexpander/__init__.h" +#include "shared-bindings/i2cioexpander/IOExpander.h" + +//| """Support for I2C-based GPIO expanders +//| +//| The `i2cioexpander` module contains classes to support I2C-based GPIO expanders +//| that can be controlled via simple register reads and writes. +//| +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed if the program continues after use. To do so, either +//| call :py:meth:`!deinit` or use a context manager. See +//| :ref:`lifetime-and-contextmanagers` for more info. +//| +//| Example:: +//| +//| import board +//| import busio +//| import i2cioexpander +//| +//| i2c = busio.I2C(board.SCL, board.SDA) +//| expander = i2cioexpander.IOExpander(i2c, 0x20, 8, 0x01, 0x00, 0x03) +//| pin0 = expander.pins[0] +//| pin0.switch_to_output(value=True) +//| """ + +static const mp_rom_map_elem_t i2cioexpander_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_i2cioexpander) }, + { MP_ROM_QSTR(MP_QSTR_IOExpander), MP_ROM_PTR(&i2cioexpander_ioexpander_type) }, +}; + +static MP_DEFINE_CONST_DICT(i2cioexpander_module_globals, i2cioexpander_module_globals_table); + +const mp_obj_module_t i2cioexpander_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&i2cioexpander_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_i2cioexpander, i2cioexpander_module); diff --git a/shared-bindings/i2cioexpander/__init__.h b/shared-bindings/i2cioexpander/__init__.h new file mode 100644 index 0000000000000..e0d0668686859 --- /dev/null +++ b/shared-bindings/i2cioexpander/__init__.h @@ -0,0 +1,9 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +// Nothing now. diff --git a/shared-bindings/i2ctarget/I2CTarget.c b/shared-bindings/i2ctarget/I2CTarget.c index 2a3749fdb286b..94dbf4e8be4f6 100644 --- a/shared-bindings/i2ctarget/I2CTarget.c +++ b/shared-bindings/i2ctarget/I2CTarget.c @@ -21,12 +21,13 @@ static mp_obj_t mp_obj_new_i2ctarget_i2c_target_request(i2ctarget_i2c_target_obj_t *target, uint8_t address, bool is_read, bool is_restart) { i2ctarget_i2c_target_request_obj_t *self = - mp_obj_malloc(i2ctarget_i2c_target_request_obj_t, &i2ctarget_i2c_target_request_type); + mp_obj_malloc_with_finaliser(i2ctarget_i2c_target_request_obj_t, &i2ctarget_i2c_target_request_type); self->target = target; self->address = address; self->is_read = is_read; self->is_restart = is_restart; - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| class I2CTarget: @@ -48,8 +49,8 @@ static mp_obj_t mp_obj_new_i2ctarget_i2c_target_request(i2ctarget_i2c_target_obj //| :type addresses: list[int] //| :param bool smbus: Use SMBUS timings if the hardware supports it""" //| ... +//| static mp_obj_t i2ctarget_i2c_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - i2ctarget_i2c_target_obj_t *self = mp_obj_malloc(i2ctarget_i2c_target_obj_t, &i2ctarget_i2c_target_type); enum { ARG_scl, ARG_sda, ARG_addresses, ARG_smbus }; static const mp_arg_t allowed_args[] = { { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -77,37 +78,41 @@ static mp_obj_t i2ctarget_i2c_target_make_new(const mp_obj_type_t *type, size_t mp_raise_ValueError(MP_ERROR_TEXT("addresses is empty")); } + i2ctarget_i2c_target_obj_t *self = mp_obj_malloc_with_finaliser(i2ctarget_i2c_target_obj_t, &i2ctarget_i2c_target_type); common_hal_i2ctarget_i2c_target_construct(self, scl, sda, addresses, i, args[ARG_smbus].u_bool); - return (mp_obj_t)self; + + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Releases control of the underlying hardware so other classes can use it.""" //| ... +//| static mp_obj_t i2ctarget_i2c_target_obj_deinit(mp_obj_t self_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_type)); i2ctarget_i2c_target_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_i2ctarget_i2c_target_deinit(self); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(i2ctarget_i2c_target_deinit_obj, i2ctarget_i2c_target_obj_deinit); +static void check_for_deinit(i2ctarget_i2c_target_obj_t *self) { + if (common_hal_i2ctarget_i2c_target_deinited(self)) { + raise_deinited_error(); + } +} + //| def __enter__(self) -> I2CTarget: //| """No-op used in Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware on context exit. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t i2ctarget_i2c_target_obj___exit__(size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_type(args[0], &i2ctarget_i2c_target_type)); - i2ctarget_i2c_target_obj_t *self = MP_OBJ_TO_PTR(args[0]); - common_hal_i2ctarget_i2c_target_deinit(self); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2ctarget_i2c_target___exit___obj, 4, 4, i2ctarget_i2c_target_obj___exit__); +//| +// Provided by context manager helper. //| def request(self, *, timeout: float = -1) -> I2CTargetRequest: //| """Wait for an I2C request. @@ -116,12 +121,11 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2ctarget_i2c_target___exit___obj, 4, //| :return: I2CTargetRequest or None if timeout=-1 and there's no request //| :rtype: ~i2ctarget.I2CTargetRequest""" //| +//| static mp_obj_t i2ctarget_i2c_target_request(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_check_self(mp_obj_is_type(pos_args[0], &i2ctarget_i2c_target_type)); i2ctarget_i2c_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - if (common_hal_i2ctarget_i2c_target_deinited(self)) { - raise_deinited_error(); - } + check_for_deinit(self); + enum { ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, @@ -186,8 +190,9 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(i2ctarget_i2c_target_request_obj, 1, i2ctarget static const mp_rom_map_elem_t i2ctarget_i2c_target_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&i2ctarget_i2c_target_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&i2ctarget_i2c_target_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2ctarget_i2c_target___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_request), MP_ROM_PTR(&i2ctarget_i2c_target_request_obj) }, }; @@ -197,7 +202,7 @@ static MP_DEFINE_CONST_DICT(i2ctarget_i2c_target_locals_dict, i2ctarget_i2c_targ MP_DEFINE_CONST_OBJ_TYPE( i2ctarget_i2c_target_type, MP_QSTR_I2CTarget, - MP_TYPE_FLAG_NONE, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, make_new, i2ctarget_i2c_target_make_new, locals_dict, &i2ctarget_i2c_target_locals_dict ); @@ -213,32 +218,45 @@ MP_DEFINE_CONST_OBJ_TYPE( //| :param address: I2C address //| :param is_read: True if the main target is requesting data //| :param is_restart: Repeated Start Condition""" +//| static mp_obj_t i2ctarget_i2c_target_request_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 4, 4, false); return mp_obj_new_i2ctarget_i2c_target_request(args[0], mp_obj_get_int(args[1]), mp_obj_is_true(args[2]), mp_obj_is_true(args[3])); } -//| def __enter__(self) -> I2CTargetRequest: -//| """No-op used in Context Managers.""" -//| ... -// Provided by context manager helper. +static void target_request_check_for_deinit(i2ctarget_i2c_target_request_obj_t *self) { + if (self->target == NULL) { + raise_deinited_error(); + } + check_for_deinit(self->target); +} -//| def __exit__(self) -> None: -//| """Close the request.""" +//| def deinit(self) -> None: +//| """Disconnects from parent `I2CTarget`. +//| Called by `__exit__()` to indicate the `I2CTargetRequest` is no longer useful.""" //| ... -static mp_obj_t i2ctarget_i2c_target_request_obj___exit__(size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_type(args[0], &i2ctarget_i2c_target_request_type)); - i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(args[0]); - common_hal_i2ctarget_i2c_target_close(self->target); +//| +static mp_obj_t i2ctarget_i2c_target_request_deinit(mp_obj_t self_in) { + i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); + target_request_check_for_deinit(self); + + i2ctarget_i2c_target_obj_t *target = self->target; + + // Deinit I2CTargetRequest first in case _close() fails. + self->target = NULL; + + common_hal_i2ctarget_i2c_target_close(target); + return mp_const_none; } -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2ctarget_i2c_target_request___exit___obj, 4, 4, i2ctarget_i2c_target_request_obj___exit__); +MP_DEFINE_CONST_FUN_OBJ_1(i2ctarget_i2c_target_request_deinit_obj, i2ctarget_i2c_target_request_deinit); //| address: int //| """The I2C address of the request.""" static mp_obj_t i2ctarget_i2c_target_request_get_address(mp_obj_t self_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); + target_request_check_for_deinit(self); + return mp_obj_new_int(self->address); } MP_DEFINE_CONST_PROP_GET(i2ctarget_i2c_target_request_address_obj, i2ctarget_i2c_target_request_get_address); @@ -246,17 +264,20 @@ MP_DEFINE_CONST_PROP_GET(i2ctarget_i2c_target_request_address_obj, i2ctarget_i2c //| is_read: bool //| """The I2C main controller is reading from this target.""" static mp_obj_t i2ctarget_i2c_target_request_get_is_read(mp_obj_t self_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); + target_request_check_for_deinit(self); + return mp_obj_new_bool(self->is_read); } MP_DEFINE_CONST_PROP_GET(i2ctarget_i2c_target_request_is_read_obj, i2ctarget_i2c_target_request_get_is_read); //| is_restart: bool //| """Is Repeated Start Condition.""" +//| static mp_obj_t i2ctarget_i2c_target_request_get_is_restart(mp_obj_t self_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); + target_request_check_for_deinit(self); + return mp_obj_new_bool(self->is_restart); } MP_DEFINE_CONST_PROP_GET(i2ctarget_i2c_target_request_is_restart_obj, i2ctarget_i2c_target_request_get_is_restart); @@ -269,9 +290,11 @@ MP_DEFINE_CONST_PROP_GET(i2ctarget_i2c_target_request_is_restart_obj, i2ctarget_ //| :param ack: Whether or not to send an ACK after the n'th byte //| :return: Bytes read""" //| ... +//| static mp_obj_t i2ctarget_i2c_target_request_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_check_self(mp_obj_is_type(pos_args[0], &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + target_request_check_for_deinit(self); + enum { ARG_n, ARG_ack }; static const mp_arg_t allowed_args[] = { { MP_QSTR_n, MP_ARG_INT, {.u_int = -1} }, @@ -326,9 +349,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(i2ctarget_i2c_target_request_read_obj, 1, i2ctarget_i //| :param ~circuitpython_typing.ReadableBuffer buffer: Write out the data in this buffer //| :return: Number of bytes written""" //| ... +//| static mp_obj_t i2ctarget_i2c_target_request_write(mp_obj_t self_in, mp_obj_t buf_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); + target_request_check_for_deinit(self); if (!self->is_read) { mp_raise_OSError(MP_EACCES); @@ -360,9 +384,11 @@ static MP_DEFINE_CONST_FUN_OBJ_2(i2ctarget_i2c_target_request_write_obj, i2ctarg //| :param ack: Whether to send an ACK or NACK""" //| ... //| +//| static mp_obj_t i2ctarget_i2c_target_request_ack(uint n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_type(args[0], &i2ctarget_i2c_target_request_type)); i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(args[0]); + target_request_check_for_deinit(self); + bool ack = (n_args == 1) ? true : mp_obj_is_true(args[1]); if (self->is_read) { @@ -374,25 +400,29 @@ static mp_obj_t i2ctarget_i2c_target_request_ack(uint n_args, const mp_obj_t *ar } MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(i2ctarget_i2c_target_request_ack_obj, 1, 2, i2ctarget_i2c_target_request_ack); -static mp_obj_t i2ctarget_i2c_target_request_close(mp_obj_t self_in) { - mp_check_self(mp_obj_is_type(self_in, &i2ctarget_i2c_target_request_type)); - i2ctarget_i2c_target_request_obj_t *self = MP_OBJ_TO_PTR(self_in); +//| def __enter__(self) -> I2CTargetRequest: +//| """No-op used in Context Managers.""" +//| ... +//| +// Provided by context manager helper. - common_hal_i2ctarget_i2c_target_close(self->target); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(i2ctarget_i2c_target_request_close_obj, i2ctarget_i2c_target_request_close); +//| def __exit__(self) -> None: +//| """Close and deinit the request.""" +//| ... +//| +// Provided by context manager helper. static const mp_rom_map_elem_t i2ctarget_i2c_target_request_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&i2ctarget_i2c_target_request___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&i2ctarget_i2c_target_request_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR__del__), MP_ROM_PTR(&i2ctarget_i2c_target_request_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&i2ctarget_i2c_target_request_address_obj) }, { MP_ROM_QSTR(MP_QSTR_is_read), MP_ROM_PTR(&i2ctarget_i2c_target_request_is_read_obj) }, { MP_ROM_QSTR(MP_QSTR_is_restart), MP_ROM_PTR(&i2ctarget_i2c_target_request_is_restart_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&i2ctarget_i2c_target_request_read_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&i2ctarget_i2c_target_request_write_obj) }, { MP_ROM_QSTR(MP_QSTR_ack), MP_ROM_PTR(&i2ctarget_i2c_target_request_ack_obj) }, - { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&i2ctarget_i2c_target_request_close_obj) }, }; static MP_DEFINE_CONST_DICT(i2ctarget_i2c_target_request_locals_dict, i2ctarget_i2c_target_request_locals_dict_table); diff --git a/shared-bindings/imagecapture/ParallelImageCapture.c b/shared-bindings/imagecapture/ParallelImageCapture.c index d1964c7175330..427eaeb379373 100644 --- a/shared-bindings/imagecapture/ParallelImageCapture.c +++ b/shared-bindings/imagecapture/ParallelImageCapture.c @@ -34,6 +34,7 @@ //| :param microcontroller.Pin href: The horizontal reference input, which is high whenever the camera is transmitting valid pixel information. //| """ //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_data_pins, ARG_clock, ARG_vsync, ARG_href, NUM_ARGS }; @@ -57,7 +58,6 @@ static mp_obj_t imagecapture_parallelimagecapture_make_new(const mp_obj_type_t * imagecapture_parallelimagecapture_obj_t *self = mp_obj_malloc(imagecapture_parallelimagecapture_obj_t, &imagecapture_parallelimagecapture_type); - common_hal_imagecapture_parallelimagecapture_construct(self, pins, pin_count, clock, vsync, href); return self; @@ -68,6 +68,7 @@ static mp_obj_t imagecapture_parallelimagecapture_make_new(const mp_obj_type_t * //| //| This will stop a continuous-mode capture, if one is in progress.""" //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_capture(mp_obj_t self_in, mp_obj_t buffer) { imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; common_hal_imagecapture_parallelimagecapture_singleshot_capture(self, buffer); @@ -88,6 +89,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(imagecapture_parallelimagecapture_capture_obj, //| `ParallelImageCapture` object keeps references to ``buffer1`` and //| ``buffer2``, so the objects will not be garbage collected.""" //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_continuous_capture_start(mp_obj_t self_in, mp_obj_t buffer1, mp_obj_t buffer2) { imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; common_hal_imagecapture_parallelimagecapture_continuous_capture_start(self, buffer1, buffer2); @@ -99,6 +101,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(imagecapture_parallelimagecapture_continuous_ca //| def continuous_capture_get_frame(self) -> WriteableBuffer: //| """Return the next available frame, one of the two buffers passed to `continuous_capture_start`""" //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_continuous_capture_get_frame(mp_obj_t self_in) { imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; return common_hal_imagecapture_parallelimagecapture_continuous_capture_get_frame(self); @@ -114,6 +117,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(imagecapture_parallelimagecapture_continuous_ca //| references to the buffers passed to `continuous_capture_start`, //| potentially allowing the objects to be garbage collected.""" //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_continuous_capture_stop(mp_obj_t self_in) { imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; common_hal_imagecapture_parallelimagecapture_continuous_capture_stop(self); @@ -128,6 +132,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(imagecapture_parallelimagecapture_continuous_ca //| def deinit(self) -> None: //| """Deinitialize this instance""" //| ... +//| static mp_obj_t imagecapture_parallelimagecapture_deinit(mp_obj_t self_in) { imagecapture_parallelimagecapture_obj_t *self = (imagecapture_parallelimagecapture_obj_t *)self_in; common_hal_imagecapture_parallelimagecapture_deinit(self); @@ -139,6 +144,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(imagecapture_parallelimagecapture_deinit_obj, i //| def __enter__(self) -> ParallelImageCapture: //| """No-op used in Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: @@ -146,19 +152,14 @@ static MP_DEFINE_CONST_FUN_OBJ_1(imagecapture_parallelimagecapture_deinit_obj, i //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... //| -static mp_obj_t imagecapture_parallelimagecapture___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_imagecapture_parallelimagecapture_deinit(args[0]); - return mp_const_none; -} - -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(imagecapture_parallelimagecapture___exit___obj, 4, 4, imagecapture_parallelimagecapture___exit__); +//| +// Provided by context manager helper. static const mp_rom_map_elem_t imagecapture_parallelimagecapture_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&imagecapture_parallelimagecapture_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&imagecapture_parallelimagecapture___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&imagecapture_parallelimagecapture_capture_obj) }, { MP_ROM_QSTR(MP_QSTR_continuous_capture_start), MP_ROM_PTR(&imagecapture_parallelimagecapture_continuous_capture_start_obj) }, diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index bf04ae18b1338..6d3e4d6884209 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -15,6 +15,12 @@ a list of modules supported on each board. Modules --------- +.. note:: Some modules are documented in :doc:`/docs/library/index`, not here: + `builtins`, `heapq`, `array`, `binascii`, `collections`, `errno`, `gc`, + `io`, `json`, `re`, `sys`, `select`. + + The documentation for :func:`help` is at the end of this page. + .. toctree:: :glob: :maxdepth: 2 diff --git a/shared-bindings/ipaddress/IPv4Address.c b/shared-bindings/ipaddress/IPv4Address.c index bf18eda0f790a..7705e500e7e6a 100644 --- a/shared-bindings/ipaddress/IPv4Address.c +++ b/shared-bindings/ipaddress/IPv4Address.c @@ -24,6 +24,7 @@ //| //| The value itself can either be bytes or a string formatted address.""" //| ... +//| static mp_obj_t ipaddress_ipv4address_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_address }; static const mp_arg_t allowed_args[] = { @@ -58,7 +59,6 @@ static mp_obj_t ipaddress_ipv4address_make_new(const mp_obj_type_t *type, size_t ipaddress_ipv4address_obj_t *self = mp_obj_malloc(ipaddress_ipv4address_obj_t, &ipaddress_ipv4address_type); - common_hal_ipaddress_ipv4address_construct(self, buf, 4); return MP_OBJ_FROM_PTR(self); @@ -78,6 +78,7 @@ MP_PROPERTY_GETTER(ipaddress_ipv4address_packed_obj, //| version: int //| """4 for IPv4, 6 for IPv6""" +//| static mp_obj_t ipaddress_ipv4address_get_version(mp_obj_t self_in) { ipaddress_ipv4address_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t buf_info; @@ -98,6 +99,7 @@ MP_PROPERTY_GETTER(ipaddress_ipv4address_version_obj, //| def __eq__(self, other: object) -> bool: //| """Two Address objects are equal if their addresses and address types are equal.""" //| ... +//| static mp_obj_t ipaddress_ipv4address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { // Two Addresses are equal if their address bytes and address_type are equal @@ -122,6 +124,7 @@ static mp_obj_t ipaddress_ipv4address_binary_op(mp_binary_op_t op, mp_obj_t lhs_ //| """Returns a hash for the IPv4Address data.""" //| ... //| +//| static mp_obj_t ipaddress_ipv4address_unary_op(mp_unary_op_t op, mp_obj_t self_in) { switch (op) { // Two Addresses are equal if their address bytes and address_type are equal diff --git a/shared-bindings/ipaddress/__init__.c b/shared-bindings/ipaddress/__init__.c index 75892f6f2ea04..60bc6226ba1b6 100644 --- a/shared-bindings/ipaddress/__init__.c +++ b/shared-bindings/ipaddress/__init__.c @@ -16,6 +16,7 @@ //| module. //| """ //| +//| bool ipaddress_parse_ipv4address(const char *str_data, size_t str_len, uint32_t *ip_out) { @@ -60,6 +61,7 @@ bool ipaddress_parse_ipv4address(const char *str_data, size_t str_len, uint32_t //| """Return a corresponding IP address object or raise ValueError if not possible.""" //| ... //| +//| static mp_obj_t ipaddress_ip_address(mp_obj_t ip_in) { uint32_t value; diff --git a/shared-bindings/is31fl3741/FrameBuffer.c b/shared-bindings/is31fl3741/FrameBuffer.c index b197f4447cb62..b59c7360f8b0b 100644 --- a/shared-bindings/is31fl3741/FrameBuffer.c +++ b/shared-bindings/is31fl3741/FrameBuffer.c @@ -29,7 +29,7 @@ //| *, //| framebuffer: Optional[WriteableBuffer] = None, //| scale: bool = False, -//| gamma: bool = False +//| gamma: bool = False, //| ) -> None: //| """Create a IS31FL3741_FrameBuffer object with the given attributes. //| @@ -51,6 +51,7 @@ //| :param bool scale: if True display is scaled down by 3 when displayed //| :param bool gamma: if True apply gamma correction to all LEDs""" //| ... +//| static mp_obj_t is31fl3741_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_is31, ARG_width, ARG_height, ARG_mapping, ARG_framebuffer, ARG_scale, ARG_gamma }; static const mp_arg_t allowed_args[] = { @@ -111,6 +112,7 @@ static mp_obj_t is31fl3741_framebuffer_make_new(const mp_obj_type_t *type, size_ //| IS31FL3741 instance. After deinitialization, no further operations //| may be performed.""" //| ... +//| static mp_obj_t is31fl3741_framebuffer_deinit(mp_obj_t self_in) { is31fl3741_framebuffer_obj_t *self = (is31fl3741_framebuffer_obj_t *)self_in; common_hal_is31fl3741_framebuffer_deinit(self); @@ -127,6 +129,7 @@ static void check_for_deinit(is31fl3741_framebuffer_obj_t *self) { //| brightness: float //| """In the current implementation, 0.0 turns the display off entirely //| and any other value up to 1.0 turns the display on fully.""" +//| static mp_obj_t is31fl3741_framebuffer_get_brightness(mp_obj_t self_in) { is31fl3741_framebuffer_obj_t *self = (is31fl3741_framebuffer_obj_t *)self_in; check_for_deinit(self); @@ -160,6 +163,7 @@ MP_PROPERTY_GETSET(is31fl3741_framebuffer_brightness_obj, //| """Transmits the color data in the buffer to the pixels so that //| they are shown.""" //| ... +//| static mp_obj_t is31fl3741_framebuffer_refresh(mp_obj_t self_in) { is31fl3741_framebuffer_obj_t *self = (is31fl3741_framebuffer_obj_t *)self_in; check_for_deinit(self); @@ -182,6 +186,7 @@ MP_PROPERTY_GETTER(is31fl3741_framebuffer_width_obj, //| height: int //| """The height of the display, in pixels""" //| +//| static mp_obj_t is31fl3741_framebuffer_get_height(mp_obj_t self_in) { is31fl3741_framebuffer_obj_t *self = (is31fl3741_framebuffer_obj_t *)self_in; check_for_deinit(self); diff --git a/shared-bindings/is31fl3741/IS31FL3741.c b/shared-bindings/is31fl3741/IS31FL3741.c index 7815a2ac809de..71c4437a1d23f 100644 --- a/shared-bindings/is31fl3741/IS31FL3741.c +++ b/shared-bindings/is31fl3741/IS31FL3741.c @@ -25,6 +25,7 @@ //| :param ~busio.I2C i2c: I2C bus the IS31FL3741 is on //| :param int addr: device address""" //| ... +//| static mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_i2c, ARG_addr }; static const mp_arg_t allowed_args[] = { @@ -37,7 +38,6 @@ static mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t mp_obj_t i2c = mp_arg_validate_type(args[ARG_i2c].u_obj, &busio_i2c_type, MP_QSTR_i2c_bus); is31fl3741_IS31FL3741_obj_t *self = mp_obj_malloc(is31fl3741_IS31FL3741_obj_t, &is31fl3741_IS31FL3741_type); - common_hal_is31fl3741_IS31FL3741_construct(self, MP_OBJ_TO_PTR(i2c), args[ARG_addr].u_int @@ -52,6 +52,7 @@ static mp_obj_t is31fl3741_IS31FL3741_make_new(const mp_obj_type_t *type, size_t //| may be performed.""" //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_deinit(mp_obj_t self_in) { is31fl3741_IS31FL3741_obj_t *self = (is31fl3741_IS31FL3741_obj_t *)self_in; common_hal_is31fl3741_IS31FL3741_deinit(self); @@ -63,6 +64,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_deinit_obj, is31fl3741_IS //| """Resets the IS31FL3741 chip.""" //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_reset(mp_obj_t self_in) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_is31fl3741_send_reset(self); @@ -74,6 +76,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_reset_obj, is31fl3741_IS31FL3741 //| """Enables the IS31FL3741 chip.""" //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_enable(mp_obj_t self_in) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_is31fl3741_send_enable(self); @@ -87,6 +90,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(is31fl3741_IS31FL3741_enable_obj, is31fl3741_IS31FL374 //| :param int current: global current value 0x00 to 0xFF""" //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_set_global_current(mp_obj_t self_in, mp_obj_t value) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_int_t current = mp_obj_get_int(value); @@ -105,6 +109,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(is31fl3741_IS31FL3741_set_global_current_obj, is31fl37 //| of 0 or 2)""" //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_set_led(size_t n_args, const mp_obj_t *args) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t led = mp_obj_get_int(args[1]); @@ -123,6 +128,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(is31fl3741_IS31FL3741_set_led_obj, 4, 4, is3 //| """ //| ... //| +//| static mp_obj_t is31fl3741_IS31FL3741_write(mp_obj_t self_in, mp_obj_t mapping, mp_obj_t buffer) { is31fl3741_IS31FL3741_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!mp_obj_is_tuple_compatible(mapping)) { @@ -143,11 +149,11 @@ MP_DEFINE_CONST_FUN_OBJ_3(is31fl3741_IS31FL3741_write_obj, is31fl3741_IS31FL3741 static const mp_rom_map_elem_t is31fl3741_IS31FL3741_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&is31fl3741_IS31FL3741_deinit_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&is31fl3741_IS31FL3741_write_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&is31fl3741_IS31FL3741_reset_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&is31fl3741_IS31FL3741_enable_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_set_global_current), (mp_obj_t)&is31fl3741_IS31FL3741_set_global_current_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_set_led), (mp_obj_t)&is31fl3741_IS31FL3741_set_led_obj }, + { MP_ROM_QSTR(MP_QSTR_write), (mp_obj_t)&is31fl3741_IS31FL3741_write_obj }, + { MP_ROM_QSTR(MP_QSTR_reset), (mp_obj_t)&is31fl3741_IS31FL3741_reset_obj }, + { MP_ROM_QSTR(MP_QSTR_enable), (mp_obj_t)&is31fl3741_IS31FL3741_enable_obj }, + { MP_ROM_QSTR(MP_QSTR_set_global_current), (mp_obj_t)&is31fl3741_IS31FL3741_set_global_current_obj }, + { MP_ROM_QSTR(MP_QSTR_set_led), (mp_obj_t)&is31fl3741_IS31FL3741_set_led_obj }, }; static MP_DEFINE_CONST_DICT(is31fl3741_IS31FL3741_locals_dict, is31fl3741_IS31FL3741_locals_dict_table); diff --git a/shared-bindings/jpegio/JpegDecoder.c b/shared-bindings/jpegio/JpegDecoder.c index d045e178bddc2..ad2a0622e7a61 100644 --- a/shared-bindings/jpegio/JpegDecoder.c +++ b/shared-bindings/jpegio/JpegDecoder.c @@ -32,7 +32,9 @@ //| # .. do something with bitmap //| """ //| -//| def __init__(self) -> None: ... +//| def __init__(self) -> None: +//| """Create a JpegDecoder""" +//| ... //| static mp_obj_t jpegio_jpegdecoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = { @@ -41,12 +43,12 @@ static mp_obj_t jpegio_jpegdecoder_make_new(const mp_obj_type_t *type, size_t n_ mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); jpegio_jpegdecoder_obj_t *self = mp_obj_malloc(jpegio_jpegdecoder_obj_t, &jpegio_jpegdecoder_type); - self->base.type = &jpegio_jpegdecoder_type; common_hal_jpegio_jpegdecoder_construct(self); return MP_OBJ_FROM_PTR(self); } +//| //| @overload //| def open(self, filename: str) -> Tuple[int, int]: ... //| @overload @@ -62,6 +64,7 @@ static mp_obj_t jpegio_jpegdecoder_make_new(const mp_obj_type_t *type, size_t n_ //| not shown in the function signature in the documentation. //| //| Returns the image size as the tuple ``(width, height)``.""" +//| static mp_obj_t jpegio_jpegdecoder_open(mp_obj_t self_in, mp_obj_t arg) { jpegio_jpegdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in); if (mp_obj_is_str(arg)) { @@ -132,6 +135,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(jpegio_jpegdecoder_open_obj, jpegio_jpegdecoder_open); //| by the pixels from the source //| """ //| +//| static mp_obj_t jpegio_jpegdecoder_decode(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { jpegio_jpegdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); diff --git a/shared-bindings/keypad/Event.c b/shared-bindings/keypad/Event.c index 53c36a76dfb37..f83e01e785e6a 100644 --- a/shared-bindings/keypad/Event.c +++ b/shared-bindings/keypad/Event.c @@ -24,8 +24,8 @@ //| :param int timestamp: The time in milliseconds that the keypress occurred in the `supervisor.ticks_ms` time system. If specified as None, the current value of `supervisor.ticks_ms` is used. //| """ //| ... +//| static mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - keypad_event_obj_t *self = mp_obj_malloc(keypad_event_obj_t, &keypad_event_type); enum { ARG_key_number, ARG_pressed, ARG_timestamp }; static const mp_arg_t allowed_args[] = { { MP_QSTR_key_number, MP_ARG_INT, {.u_int = 0} }, @@ -44,7 +44,9 @@ static mp_obj_t keypad_event_make_new(const mp_obj_type_t *type, size_t n_args, } (void)mp_obj_get_int_truncated(timestamp); // ensure that timestamp is an integer + keypad_event_obj_t *self = mp_obj_malloc(keypad_event_obj_t, &keypad_event_type); common_hal_keypad_event_construct(self, key_number, args[ARG_pressed].u_bool, timestamp); + return MP_OBJ_FROM_PTR(self); } @@ -87,6 +89,7 @@ MP_PROPERTY_GETTER(keypad_event_released_obj, //| timestamp: int //| """The timestamp.""" +//| static mp_obj_t keypad_event_get_timestamp(mp_obj_t self_in) { keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in); return common_hal_keypad_event_get_timestamp(self); @@ -103,6 +106,7 @@ MP_PROPERTY_GETTER(keypad_event_timestamp_obj, //| Note that this does not compare the event timestamps. //| """ //| ... +//| static mp_obj_t keypad_event_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { switch (op) { case MP_BINARY_OP_EQUAL: @@ -131,6 +135,7 @@ static mp_obj_t keypad_event_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_ob //| """ //| ... //| +//| static mp_obj_t keypad_event_unary_op(mp_unary_op_t op, mp_obj_t self_in) { keypad_event_obj_t *self = MP_OBJ_TO_PTR(self_in); switch (op) { diff --git a/shared-bindings/keypad/EventQueue.c b/shared-bindings/keypad/EventQueue.c index e15b19df3b8f8..a899c652bc546 100644 --- a/shared-bindings/keypad/EventQueue.c +++ b/shared-bindings/keypad/EventQueue.c @@ -20,9 +20,11 @@ //| """ //| //| ... +//| //| def get(self) -> Optional[Event]: -//| """Return the next key transition event. Return ``None`` if no events are pending. +//| """Remove the next key transition event from the `EventQueue` and return it. +//| Return ``None`` if no events are pending. //| //| Note that the queue size is limited; see ``max_events`` in the constructor of //| a scanner such as `Keys` or `KeyMatrix`. @@ -33,6 +35,7 @@ //| :rtype: Optional[Event] //| """ //| ... +//| static mp_obj_t keypad_eventqueue_get(mp_obj_t self_in) { keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -41,7 +44,7 @@ static mp_obj_t keypad_eventqueue_get(mp_obj_t self_in) { MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_get_obj, keypad_eventqueue_get); //| def get_into(self, event: Event) -> bool: -//| """Store the next key transition event in the supplied event, if available, +//| """Remove the next key transition event from the ``EventQueue`, store it in ``event``, //| and return ``True``. //| If there are no queued events, do not touch ``event`` and return ``False``. //| @@ -55,6 +58,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_get_obj, keypad_eventqueue_get); //| :rtype: bool //| """ //| ... +//| static mp_obj_t keypad_eventqueue_get_into(mp_obj_t self_in, mp_obj_t event_in) { keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -67,6 +71,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(keypad_eventqueue_get_into_obj, keypad_eventqueue_get_ //| def clear(self) -> None: //| """Clear any queued key transition events. Also sets `overflowed` to ``False``.""" //| ... +//| static mp_obj_t keypad_eventqueue_clear(mp_obj_t self_in) { keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -84,6 +89,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_eventqueue_clear_obj, keypad_eventqueue_clear); //| def __len__(self) -> int: //| """Return the number of events currently in the queue. Used to implement ``len()``.""" //| ... +//| static mp_obj_t keypad_eventqueue_unary_op(mp_unary_op_t op, mp_obj_t self_in) { keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); uint16_t len = common_hal_keypad_eventqueue_get_length(self); @@ -102,6 +108,7 @@ static mp_obj_t keypad_eventqueue_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| Set to ``False`` by `clear()`. //| """ //| +//| static mp_obj_t keypad_eventqueue_get_overflowed(mp_obj_t self_in) { keypad_eventqueue_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_bool(common_hal_keypad_eventqueue_get_overflowed(self)); diff --git a/shared-bindings/keypad/EventQueue.h b/shared-bindings/keypad/EventQueue.h index 893165e3220f1..02c3414b0764c 100644 --- a/shared-bindings/keypad/EventQueue.h +++ b/shared-bindings/keypad/EventQueue.h @@ -11,7 +11,7 @@ extern const mp_obj_type_t keypad_eventqueue_type; -void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events); +void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events, bool use_gc_allocator); void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self); size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self); diff --git a/shared-bindings/keypad/KeyMatrix.c b/shared-bindings/keypad/KeyMatrix.c index 7a8bb97247a5a..01416a2f8a190 100644 --- a/shared-bindings/keypad/KeyMatrix.c +++ b/shared-bindings/keypad/KeyMatrix.c @@ -67,12 +67,20 @@ //| in the respective state for ``debounce_threshold`` times on average. //| Successive measurements are spaced apart by ``interval`` seconds. //| The default is 1, which resolves immediately. The maximum is 127. +//| +//| .. warning:: On Raspberry Pi RP2350, using ``columns_to_anodes=False`` +//| normally depends on the internal pull-down resistors. +//| This will not work, due to an RP2350 issue. +//| The easiest fix is simply to swap the ``row_pins`` and ```column_pins`` and to set +//| ``columns_to_anodes=True``. This requires no external components. +//| An alternative is to add external pull-downs of 8.2 kohms or less, but that will draw more current. +//| See the Warning in `digitalio` for more information. //| """ //| ... +//| static mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_KEYMATRIX - keypad_keymatrix_obj_t *self = mp_obj_malloc(keypad_keymatrix_obj_t, &keypad_keymatrix_type); enum { ARG_row_pins, ARG_column_pins, ARG_columns_to_anodes, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_row_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -114,7 +122,9 @@ static mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_ar column_pins_array[column] = pin; } + keypad_keymatrix_obj_t *self = mp_obj_malloc(keypad_keymatrix_obj_t, &keypad_keymatrix_type); common_hal_keypad_keymatrix_construct(self, num_row_pins, row_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, interval, max_events, debounce_threshold); + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError_varg(MP_ERROR_TEXT("%q"), MP_QSTR_KeyMatrix); @@ -126,6 +136,7 @@ static mp_obj_t keypad_keymatrix_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Stop scanning and release the pins.""" //| ... +//| static mp_obj_t keypad_keymatrix_deinit(mp_obj_t self_in) { keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_keypad_keymatrix_deinit(self); @@ -136,18 +147,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_keymatrix_deinit_obj, keypad_keymatrix_deinit); //| def __enter__(self) -> KeyMatrix: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t keypad_keymatrix___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_keypad_keymatrix_deinit(args[0]); - return MP_ROM_NONE; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_keymatrix___exit___obj, 4, 4, keypad_keymatrix___exit__); +//| +// Provided by context manager helper. static void check_for_deinit(keypad_keymatrix_obj_t *self) { if (common_hal_keypad_deinited(self)) { @@ -159,12 +167,17 @@ static void check_for_deinit(keypad_keymatrix_obj_t *self) { //| """Reset the internal state of the scanner to assume that all keys are now released. //| Any key that is already pressed at the time of this call will therefore immediately cause //| a new key-pressed event to occur. +//| For instance, if you call `reset()` immediately after creating a `KeyMatrix` object +//| at the beginning of your program, the events it generates will let you determine which keys +//| were being held down at program start. //| """ //| ... +//| //| key_count: int //| """The number of keys that are being scanned. (read-only) //| """ +//| //| def key_number_to_row_column(self, key_number: int) -> Tuple[int]: //| """Return the row and column for the given key number. @@ -175,6 +188,7 @@ static void check_for_deinit(keypad_keymatrix_obj_t *self) { //| :rtype: Tuple[int] //| """ //| ... +//| static mp_obj_t keypad_keymatrix_key_number_to_row_column(mp_obj_t self_in, mp_obj_t key_number_in) { keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -201,6 +215,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(keypad_keymatrix_key_number_to_row_column_obj, keypad_ //| The key number is ``row * len(column_pins) + column``. //| """ //| ... +//| static mp_obj_t keypad_keymatrix_row_column_to_key_number(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t column_in) { keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -220,11 +235,12 @@ MP_DEFINE_CONST_FUN_OBJ_3(keypad_keymatrix_row_column_to_key_number_obj, keypad_ //| """The `EventQueue` associated with this `Keys` object. (read-only) //| """ //| +//| static const mp_rom_map_elem_t keypad_keymatrix_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keymatrix_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keymatrix___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_generic_events_obj) }, { MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_generic_key_count_obj) }, diff --git a/shared-bindings/keypad/Keys.c b/shared-bindings/keypad/Keys.c index 208bc0a62d497..5fd065fc6271c 100644 --- a/shared-bindings/keypad/Keys.c +++ b/shared-bindings/keypad/Keys.c @@ -69,12 +69,18 @@ //| in the respective state for ``debounce_threshold`` times on average. //| Successive measurements are spaced apart by ``interval`` seconds. //| The default is 1, which resolves immediately. The maximum is 127. +//| +//| .. warning:: On Raspberry Pi RP2350, using ``value_when_pressed=True`` and ``pull=True``, +//| to enable using the internal pull-down resistor, will not work, due to an RP2350 +//| hardware issue. Instead, wire the switch to be ``value_when_pressed=False``, or add +//| an external pull-down resistor of 8.2 kohms or less. +//| See the Warning in `digitalio` for more information. //| """ //| ... +//| static mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_KEYS - keypad_keys_obj_t *self = mp_obj_malloc(keypad_keys_obj_t, &keypad_keys_type); enum { ARG_pins, ARG_value_when_pressed, ARG_pull, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -105,6 +111,7 @@ static mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, s validate_obj_is_free_pin(mp_obj_subscr(pins, MP_OBJ_NEW_SMALL_INT(i), MP_OBJ_SENTINEL), MP_QSTR_pin); } + keypad_keys_obj_t *self = mp_obj_malloc(keypad_keys_obj_t, &keypad_keys_type); common_hal_keypad_keys_construct(self, num_pins, pins_array, value_when_pressed, args[ARG_pull].u_bool, interval, max_events, debounce_threshold); return MP_OBJ_FROM_PTR(self); @@ -118,6 +125,7 @@ static mp_obj_t keypad_keys_make_new(const mp_obj_type_t *type, size_t n_args, s //| def deinit(self) -> None: //| """Stop scanning and release the pins.""" //| ... +//| static mp_obj_t keypad_keys_deinit(mp_obj_t self_in) { keypad_keys_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -129,26 +137,27 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_keys_deinit_obj, keypad_keys_deinit); //| def __enter__(self) -> Keys: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t keypad_keys___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_keypad_keys_deinit(args[0]); - return MP_ROM_NONE; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_keys___exit___obj, 4, 4, keypad_keys___exit__); +//| +// Provided by context manager helper. //| def reset(self) -> None: //| """Reset the internal state of the scanner to assume that all keys are now released. //| Any key that is already pressed at the time of this call will therefore immediately cause //| a new key-pressed event to occur. +//| For instance, if you call `reset()` immediately after creating a `Keys` object +//| at the beginning of your program, the events it generates will let you determine which keys +//| were being held down at program start. //| """ //| ... +//| //| key_count: int //| """The number of keys that are being scanned. (read-only) @@ -158,10 +167,11 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_keys___exit___obj, 4, 4, keypa //| """The `EventQueue` associated with this `Keys` object. (read-only) //| """ //| +//| static const mp_rom_map_elem_t keypad_keys_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_keys_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_keys___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_generic_events_obj) }, { MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_generic_key_count_obj) }, diff --git a/shared-bindings/keypad/ShiftRegisterKeys.c b/shared-bindings/keypad/ShiftRegisterKeys.c index a0bcde96e94cf..7f89a11ecf169 100644 --- a/shared-bindings/keypad/ShiftRegisterKeys.c +++ b/shared-bindings/keypad/ShiftRegisterKeys.c @@ -53,13 +53,14 @@ //| //| Key number 0 is the first (or more properly, the zero-th) bit read. In the //| 74HC165, this bit is labeled ``Q7``. Key number 1 will be the value of ``Q6``, etc. -//| With multiple data pins, key numbers of the next pin are sequentially to the current pin. +//| Key numbers are sequenced such that there are ``key_count[0]`` values read from ``data[0]``, followed by ``key_count[1]`` values read from ``data[1]``, etc. //| //| An `EventQueue` is created when this object is created and is available in the `events` attribute. //| //| :param microcontroller.Pin clock: The shift register clock pin. //| The shift register should clock on a low-to-high transition. -//| :param Union[microcontroller.Pin, Sequence[microcontroller.Pin]] data: the incoming shift register data pin(s) +//| :param Union[microcontroller.Pin, Sequence[microcontroller.Pin]] data: the incoming shift register data pin(s). +//| When a ``microcontroller.Pin`` argument is given, it is logically equivalent to a one-element sequence. //| :param microcontroller.Pin latch: //| Pin used to latch parallel data going into the shift register. //| :param bool value_to_latch: Pin state to latch data being read. @@ -68,6 +69,7 @@ //| The default is ``True``, which is how the 74HC165 operates. The CD4021 latch is the opposite. //| Once the data is latched, it will be shifted out by toggling the clock pin. //| :param Union[int, Sequence[int]] key_count: number of data lines to clock in (per data pin) +//| When an ``int`` argument is given, it is logically equivalent to a one-element sequence. //| :param bool value_when_pressed: ``True`` if the pin reads high when the key is pressed. //| ``False`` if the pin reads low (is grounded) when the key is pressed. //| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing. @@ -82,11 +84,10 @@ //| The default is 1, which resolves immediately. The maximum is 127. //| """ //| ... +//| static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_KEYPAD_SHIFTREGISTERKEYS - keypad_shiftregisterkeys_obj_t *self = - mp_obj_malloc(keypad_shiftregisterkeys_obj_t, &keypad_shiftregisterkeys_type); enum { ARG_clock, ARG_data, ARG_latch, ARG_value_to_latch, ARG_key_count, ARG_value_when_pressed, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -136,7 +137,8 @@ static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz size_t key_count_array[num_key_counts]; if (mp_obj_is_int(args[ARG_key_count].u_obj)) { - const size_t key_count = (size_t)mp_arg_validate_int_min(args[ARG_key_count].u_int, 1, MP_QSTR_key_count); + const size_t key_count = + (size_t)mp_arg_validate_int_min(mp_obj_get_int(args[ARG_key_count].u_obj), 1, MP_QSTR_key_count); key_count_array[0] = key_count; } else { for (size_t kc = 0; kc < num_key_counts; kc++) { @@ -156,6 +158,8 @@ static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz const size_t max_events = (size_t)mp_arg_validate_int_min(args[ARG_max_events].u_int, 1, MP_QSTR_max_events); const uint8_t debounce_threshold = (uint8_t)mp_arg_validate_int_range(args[ARG_debounce_threshold].u_int, 1, 127, MP_QSTR_debounce_threshold); + keypad_shiftregisterkeys_obj_t *self = + mp_obj_malloc(keypad_shiftregisterkeys_obj_t, &keypad_shiftregisterkeys_type); common_hal_keypad_shiftregisterkeys_construct( self, clock, num_data_pins, data_pins_array, latch, value_to_latch, num_key_counts, key_count_array, value_when_pressed, interval, max_events, debounce_threshold); @@ -170,6 +174,7 @@ static mp_obj_t keypad_shiftregisterkeys_make_new(const mp_obj_type_t *type, siz //| def deinit(self) -> None: //| """Stop scanning and release the pins.""" //| ... +//| static mp_obj_t keypad_shiftregisterkeys_deinit(mp_obj_t self_in) { keypad_shiftregisterkeys_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -181,25 +186,26 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_shiftregisterkeys_deinit_obj, keypad_shiftregis //| def __enter__(self) -> Keys: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t keypad_shiftregisterkeys___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_keypad_shiftregisterkeys_deinit(args[0]); - return MP_ROM_NONE; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_shiftregisterkeys___exit___obj, 4, 4, keypad_shiftregisterkeys___exit__); +//| +// Provided by context manager helper. //| def reset(self) -> None: //| """Reset the internal state of the scanner to assume that all keys are now released. //| Any key that is already pressed at the time of this call will therefore immediately cause //| a new key-pressed event to occur. +//| For instance, if you call `reset()` immediately after creating a `ShiftRegisterKeys` object +//| at the beginning of your program, the events it generates will let you determine which keys +//| were being held down at program start. //| """ //| ... +//| //| key_count: int //| """The total number of keys that are being scanned. (read-only) @@ -209,11 +215,12 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_shiftregisterkeys___exit___obj //| """The `EventQueue` associated with this `Keys` object. (read-only) //| """ //| +//| static const mp_rom_map_elem_t keypad_shiftregisterkeys_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_shiftregisterkeys_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_shiftregisterkeys___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_generic_events_obj) }, { MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_generic_key_count_obj) }, diff --git a/shared-bindings/keypad/__init__.c b/shared-bindings/keypad/__init__.c index 4c65d98a085ca..b182e977829d1 100644 --- a/shared-bindings/keypad/__init__.c +++ b/shared-bindings/keypad/__init__.c @@ -37,12 +37,8 @@ static mp_obj_t keypad_generic_get_key_count(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(keypad_generic_get_key_count_obj, keypad_generic_get_key_count); -const mp_obj_property_t keypad_generic_key_count_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&keypad_generic_get_key_count_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; +MP_PROPERTY_GETTER(keypad_generic_key_count_obj, + (mp_obj_t)&keypad_generic_get_key_count_obj); static mp_obj_t keypad_generic_get_events(mp_obj_t self_in) { keypad_keymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -52,13 +48,8 @@ static mp_obj_t keypad_generic_get_events(mp_obj_t self_in) { } MP_DEFINE_CONST_FUN_OBJ_1(keypad_generic_get_events_obj, keypad_generic_get_events); -const mp_obj_property_t keypad_generic_events_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&keypad_generic_get_events_obj, - MP_ROM_NONE, - MP_ROM_NONE}, -}; - +MP_PROPERTY_GETTER(keypad_generic_events_obj, + (mp_obj_t)&keypad_generic_get_events_obj); //| """Support for scanning keys and key matrices //| @@ -70,6 +61,12 @@ const mp_obj_property_t keypad_generic_events_obj = { //| For more information about working with the `keypad` module in CircuitPython, //| see `this Learn guide `_. //| +//| .. warning:: Using pull-downs with `keypad` on Raspberry Pi RP2350 A2 stepping has some limitations +//| due to a GPIO hardware issue that causes excessive leakage current (~120uA). +//| A pin can read as high even when driven or pulled low, if the input signal is high +//| impedance or if an attached pull-down resistor is too weak (has too high a value). +//| See the warnings in `keypad.Keys`, `keypad.KeyMatrix`, and `digitalio` for workarounds and more information. +//| //| .. jinja //| """ diff --git a/shared-bindings/keypad/__init__.h b/shared-bindings/keypad/__init__.h index 7f8079ecdc921..fd193cee217c8 100644 --- a/shared-bindings/keypad/__init__.h +++ b/shared-bindings/keypad/__init__.h @@ -17,5 +17,5 @@ mp_obj_t common_hal_keypad_generic_get_events(void *self); MP_DECLARE_CONST_FUN_OBJ_1(keypad_generic_reset_obj); -extern const mp_obj_property_t keypad_generic_events_obj; -extern const mp_obj_property_t keypad_generic_key_count_obj; +extern const mp_obj_property_getter_t keypad_generic_events_obj; +extern const mp_obj_property_getter_t keypad_generic_key_count_obj; diff --git a/shared-bindings/keypad_demux/DemuxKeyMatrix.c b/shared-bindings/keypad_demux/DemuxKeyMatrix.c index 9f6d65c3dd335..554e461c2289b 100644 --- a/shared-bindings/keypad_demux/DemuxKeyMatrix.c +++ b/shared-bindings/keypad_demux/DemuxKeyMatrix.c @@ -36,6 +36,8 @@ //| self, //| row_addr_pins: Sequence[microcontroller.Pin], //| column_pins: Sequence[microcontroller.Pin], +//| columns_to_anodes: bool = True, +//| transpose: bool = False, //| interval: float = 0.020, //| max_events: int = 64, //| debounce_threshold: int = 1, @@ -51,7 +53,18 @@ //| An `keypad.EventQueue` is created when this object is created and is available in the `events` attribute. //| //| :param Sequence[microcontroller.Pin] row_addr_pins: The pins attached to the rows demultiplexer. +//| If your columns are multiplexed, set ``transpose`` to ``True``. //| :param Sequence[microcontroller.Pin] column_pins: The pins attached to the columns. +//| :param bool columns_to_anodes: Default ``True``. +//| If the matrix uses diodes, the diode anodes are typically connected to the column pins +//| with the cathodes connected to the row pins. This implies an inverting multiplexer that drives +//| the selected row pin low. If your diodes are reversed, with a non-inverting multiplexer +//| that drives the selected row high, set ``columns_to_anodes`` to ``False``. +//| If ``transpose`` is ``True`` the sense of columns and rows are reversed here. +//| :param bool transpose: Default ``False``. +//| If your matrix is multiplexed on columns rather than rows, set ``transpose`` to ``True``. +//| This swaps the meaning of ``row_addr_pins`` to ``column_addr_pins``; +//| ``column_pins`` to ``row_pins``; and ``columns_to_anodes`` to ``rows_to_anodes``. //| :param float interval: Scan keys no more often than ``interval`` to allow for debouncing. //| ``interval`` is in float seconds. The default is 0.020 (20 msecs). //| :param int max_events: maximum size of `events` `keypad.EventQueue`: @@ -64,13 +77,15 @@ //| The default is 1, which resolves immediately. The maximum is 127. //| """ //| ... +//| static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type); - enum { ARG_row_addr_pins, ARG_column_pins, ARG_interval, ARG_max_events, ARG_debounce_threshold }; + enum { ARG_row_addr_pins, ARG_column_pins, ARG_columns_to_anodes, ARG_transpose, ARG_interval, ARG_max_events, ARG_debounce_threshold }; static const mp_arg_t allowed_args[] = { { MP_QSTR_row_addr_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_column_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_columns_to_anodes, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_transpose, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_interval, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_max_events, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 64} }, { MP_QSTR_debounce_threshold, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, @@ -107,13 +122,17 @@ static mp_obj_t keypad_demux_demuxkeymatrix_make_new(const mp_obj_type_t *type, column_pins_array[column] = pin; } - common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, interval, max_events, debounce_threshold); + keypad_demux_demuxkeymatrix_obj_t *self = mp_obj_malloc(keypad_demux_demuxkeymatrix_obj_t, &keypad_demux_demuxkeymatrix_type); + // Last arg is use_gc_allocator, true during VM use. + common_hal_keypad_demux_demuxkeymatrix_construct(self, num_row_addr_pins, row_addr_pins_array, num_column_pins, column_pins_array, args[ARG_columns_to_anodes].u_bool, args[ARG_transpose].u_bool, interval, max_events, debounce_threshold, true); + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Stop scanning and release the pins.""" //| ... +//| static mp_obj_t keypad_demux_demuxkeymatrix_deinit(mp_obj_t self_in) { keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_keypad_demux_demuxkeymatrix_deinit(self); @@ -124,18 +143,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(keypad_demux_demuxkeymatrix_deinit_obj, keypad_demux_d //| def __enter__(self) -> DemuxKeyMatrix: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t keypad_demux_demuxkeymatrix___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_keypad_demux_demuxkeymatrix_deinit(args[0]); - return MP_ROM_NONE; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(keypad_demux_demuxkeymatrix___exit___obj, 4, 4, keypad_demux_demuxkeymatrix___exit__); +//| +// Provided by context manager helper. static void check_for_deinit(keypad_demux_demuxkeymatrix_obj_t *self) { if (common_hal_keypad_deinited(self)) { @@ -147,12 +163,17 @@ static void check_for_deinit(keypad_demux_demuxkeymatrix_obj_t *self) { //| """Reset the internal state of the scanner to assume that all keys are now released. //| Any key that is already pressed at the time of this call will therefore immediately cause //| a new key-pressed event to occur. +//| For instance, if you call `reset()` immediately after creating a `DemuxKeyMatrix` object +//| at the beginning of your program, the events it generates will let you determine which keys +//| were being held down at program start. //| """ //| ... +//| //| key_count: int //| """The number of keys that are being scanned. (read-only) //| """ +//| //| def key_number_to_row_column(self, key_number: int) -> Tuple[int]: //| """Return the row and column for the given key number. @@ -163,6 +184,7 @@ static void check_for_deinit(keypad_demux_demuxkeymatrix_obj_t *self) { //| :rtype: Tuple[int] //| """ //| ... +//| static mp_obj_t keypad_demux_demuxkeymatrix_key_number_to_row_column(mp_obj_t self_in, mp_obj_t key_number_in) { keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -189,6 +211,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(keypad_demux_demuxkeymatrix_key_number_to_row_column_o //| The key number is ``row * len(column_pins) + column``. //| """ //| ... +//| static mp_obj_t keypad_demux_demuxkeymatrix_row_column_to_key_number(mp_obj_t self_in, mp_obj_t row_in, mp_obj_t column_in) { keypad_demux_demuxkeymatrix_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -208,11 +231,12 @@ MP_DEFINE_CONST_FUN_OBJ_3(keypad_demux_demuxkeymatrix_row_column_to_key_number_o //| """The `keypad.EventQueue` associated with this `keypad.Keys` object. (read-only) //| """ //| +//| static const mp_rom_map_elem_t keypad_demux_demuxkeymatrix_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&keypad_demux_demuxkeymatrix_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&keypad_demux_demuxkeymatrix___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_events), MP_ROM_PTR(&keypad_generic_events_obj) }, { MP_ROM_QSTR(MP_QSTR_key_count), MP_ROM_PTR(&keypad_generic_key_count_obj) }, diff --git a/shared-bindings/keypad_demux/DemuxKeyMatrix.h b/shared-bindings/keypad_demux/DemuxKeyMatrix.h index fc7a11a0d37f3..25d36283e90fc 100644 --- a/shared-bindings/keypad_demux/DemuxKeyMatrix.h +++ b/shared-bindings/keypad_demux/DemuxKeyMatrix.h @@ -11,7 +11,7 @@ extern const mp_obj_type_t keypad_demux_demuxkeymatrix_type; -void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], mp_float_t interval, size_t max_events, uint8_t debounce_threshold); +void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator); void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self); diff --git a/shared-bindings/keypad_demux/__init__.c b/shared-bindings/keypad_demux/__init__.c index c1359b2515926..30ef1234823eb 100644 --- a/shared-bindings/keypad_demux/__init__.c +++ b/shared-bindings/keypad_demux/__init__.c @@ -11,8 +11,14 @@ //| """Support for scanning key matrices that use a demultiplexer //| -//| The `keypad_demux` module provides native support to scan sets of keys or buttons, -//| connected in a row-and-column matrix. +//| The `keypad_demux` module provides native support to scan a matrix of keys or buttons +//| where either the row or column axis is controlled by a demultiplexer or decoder IC +//| such as the 74LS138 or 74LS238. In this arrangement a binary input value +//| determines which column (or row) to select, thereby reducing the number of input pins. +//| For example the input 101 would select line 5 in the matrix. +//| Set ``columns_to_anodes`` to ``False`` with a non-inverting demultiplexer +//| which drives the selected line high. +//| Set ``transpose`` to ``True`` if columns are multiplexed rather than rows. //| //| .. jinja //| """ diff --git a/shared-bindings/locale/__init__.c b/shared-bindings/locale/__init__.c index e3201c13a1978..66b9e9762a1a6 100644 --- a/shared-bindings/locale/__init__.c +++ b/shared-bindings/locale/__init__.c @@ -9,6 +9,7 @@ //| """Locale support module""" //| +//| //| def getlocale() -> None: //| """Returns the current locale setting as a tuple ``(language code, "utf-8")`` //| @@ -18,6 +19,7 @@ //| Differences from CPython: No ``LC_*`` argument is permitted. //| """ //| +//| static mp_obj_t getlocale(void) { mp_rom_error_text_t locale_msg = MP_ERROR_TEXT("en_US"); diff --git a/shared-bindings/lvfontio/OnDiskFont.c b/shared-bindings/lvfontio/OnDiskFont.c new file mode 100644 index 0000000000000..3a50ea9aedf5c --- /dev/null +++ b/shared-bindings/lvfontio/OnDiskFont.c @@ -0,0 +1,98 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/lvfontio/OnDiskFont.h" + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" + +//| class OnDiskFont: +//| """A font built into CircuitPython for use with LVGL. +//| +//| There is an in-browser converter here: https://lvgl.io/tools/fontconverter +//| +//| The format is documented here: https://github.com/lvgl/lv_font_conv/tree/master/doc""" +//| +//| def __init__(self, file_path: str, max_glyphs: int = 100) -> None: +//| """Create a OnDiskFont by loading an LVGL font file from the filesystem. +//| +//| :param str file_path: The path to the font file +//| :param int max_glyphs: Maximum number of glyphs to cache at once +//| """ +//| ... +//| + +//| bitmap: displayio.Bitmap +//| """Bitmap containing all font glyphs starting with ASCII and followed by unicode. This is useful for use with LVGL.""" +//| +static mp_obj_t lvfontio_ondiskfont_obj_get_bitmap(mp_obj_t self_in) { + lvfontio_ondiskfont_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_lvfontio_ondiskfont_get_bitmap(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(lvfontio_ondiskfont_get_bitmap_obj, lvfontio_ondiskfont_obj_get_bitmap); + +MP_PROPERTY_GETTER(lvfontio_ondiskfont_bitmap_obj, + (mp_obj_t)&lvfontio_ondiskfont_get_bitmap_obj); + +//| def get_bounding_box(self) -> Tuple[int, int]: +//| """Returns the maximum bounds of all glyphs in the font in a tuple of two values: width, height.""" +//| ... +//| +//| +static mp_obj_t lvfontio_ondiskfont_obj_get_bounding_box(mp_obj_t self_in) { + lvfontio_ondiskfont_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_lvfontio_ondiskfont_get_bounding_box(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(lvfontio_ondiskfont_get_bounding_box_obj, lvfontio_ondiskfont_obj_get_bounding_box); + +static const mp_rom_map_elem_t lvfontio_ondiskfont_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_bitmap), MP_ROM_PTR(&lvfontio_ondiskfont_bitmap_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_bounding_box), MP_ROM_PTR(&lvfontio_ondiskfont_get_bounding_box_obj) }, +}; +static MP_DEFINE_CONST_DICT(lvfontio_ondiskfont_locals_dict, lvfontio_ondiskfont_locals_dict_table); + +static mp_obj_t lvfontio_ondiskfont_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_file_path, ARG_max_glyphs }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_file_path, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_max_glyphs, MP_ARG_INT, {.u_int = 100} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Allocate the BuiltinFont object + lvfontio_ondiskfont_t *self = m_new_obj(lvfontio_ondiskfont_t); + self->base.type = &lvfontio_ondiskfont_type; + + // Extract arguments + mp_obj_t file_path_obj = args[ARG_file_path].u_obj; + mp_uint_t max_glyphs = args[ARG_max_glyphs].u_int; + + // Get the C string from the Python string + const char *file_path = mp_obj_str_get_str(file_path_obj); + + // Always use GC allocator for Python-created objects + common_hal_lvfontio_ondiskfont_construct(self, file_path, max_glyphs, true); + + return MP_OBJ_FROM_PTR(self); +} + +MP_DEFINE_CONST_OBJ_TYPE( + lvfontio_ondiskfont_type, + MP_QSTR_OnDiskFont, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, lvfontio_ondiskfont_make_new, + locals_dict, &lvfontio_ondiskfont_locals_dict + ); diff --git a/shared-bindings/lvfontio/OnDiskFont.h b/shared-bindings/lvfontio/OnDiskFont.h new file mode 100644 index 0000000000000..d7dac6ac6787a --- /dev/null +++ b/shared-bindings/lvfontio/OnDiskFont.h @@ -0,0 +1,22 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "shared-module/lvfontio/OnDiskFont.h" + +extern const mp_obj_type_t lvfontio_ondiskfont_type; + +mp_obj_t common_hal_lvfontio_ondiskfont_get_bitmap(const lvfontio_ondiskfont_t *self); +mp_obj_t common_hal_lvfontio_ondiskfont_get_bounding_box(const lvfontio_ondiskfont_t *self); +void common_hal_lvfontio_ondiskfont_get_dimensions(const lvfontio_ondiskfont_t *self, uint16_t *width, uint16_t *height); + +// Function prototypes +void common_hal_lvfontio_ondiskfont_construct(lvfontio_ondiskfont_t *self, const char *file_path, uint16_t max_glyphs, bool use_gc_allocator); +void common_hal_lvfontio_ondiskfont_deinit(lvfontio_ondiskfont_t *self); +bool common_hal_lvfontio_ondiskfont_deinited(lvfontio_ondiskfont_t *self); +int16_t common_hal_lvfontio_ondiskfont_cache_glyph(lvfontio_ondiskfont_t *self, uint32_t codepoint, bool *is_full_width); +void common_hal_lvfontio_ondiskfont_release_glyph(lvfontio_ondiskfont_t *self, uint32_t slot); diff --git a/shared-bindings/lvfontio/__init__.c b/shared-bindings/lvfontio/__init__.c new file mode 100644 index 0000000000000..ec5f352279952 --- /dev/null +++ b/shared-bindings/lvfontio/__init__.c @@ -0,0 +1,33 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/lvfontio/__init__.h" +#include "shared-bindings/lvfontio/OnDiskFont.h" + +//| """Core font related data structures for LVGL +//| +//| .. note:: This module is intended only for low-level usage with LVGL. +//| +//| """ + +static const mp_rom_map_elem_t lvfontio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_lvfontio) }, + { MP_ROM_QSTR(MP_QSTR_OnDiskFont), MP_ROM_PTR(&lvfontio_ondiskfont_type) }, +}; + +static MP_DEFINE_CONST_DICT(lvfontio_module_globals, lvfontio_module_globals_table); + +const mp_obj_module_t lvfontio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&lvfontio_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_lvfontio, lvfontio_module); diff --git a/shared-bindings/lvfontio/__init__.h b/shared-bindings/lvfontio/__init__.h new file mode 100644 index 0000000000000..b56388fa8ae3a --- /dev/null +++ b/shared-bindings/lvfontio/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/math/__init__.c b/shared-bindings/math/__init__.c index 6a2dd1b3e1638..49ca2958d8c96 100644 --- a/shared-bindings/math/__init__.c +++ b/shared-bindings/math/__init__.c @@ -24,8 +24,9 @@ //| //| |see_cpython_module| :mod:`cpython:math`. //| """ +//| -static NORETURN void math_error(void) { +static MP_NORETURN void math_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("math domain error")); } @@ -66,55 +67,68 @@ static NORETURN void math_error(void) { //| pi: float //| """the ratio of a circle's circumference to its diameter""" //| +//| //| def acos(x: float) -> float: //| """Return the inverse cosine of ``x``.""" //| ... //| +//| //| def asin(x: float) -> float: //| """Return the inverse sine of ``x``.""" //| ... //| +//| //| def atan(x: float) -> float: //| """Return the inverse tangent of ``x``.""" //| ... //| +//| //| def atan2(y: float, x: float) -> float: //| """Return the principal value of the inverse tangent of ``y/x``.""" //| ... //| +//| //| def ceil(x: float) -> int: //| """Return an integer, being ``x`` rounded towards positive infinity.""" //| ... //| +//| //| def copysign(x: float, y: float) -> float: //| """Return ``x`` with the sign of ``y``.""" //| ... //| +//| //| def cos(x: float) -> float: //| """Return the cosine of ``x``.""" //| ... //| +//| //| def degrees(x: float) -> float: //| """Return radians ``x`` converted to degrees.""" //| ... //| +//| //| def exp(x: float) -> float: //| """Return the exponential of ``x``.""" //| ... //| +//| //| def fabs(x: float) -> float: //| """Return the absolute value of ``x``.""" //| ... //| +//| //| def floor(x: float) -> int: //| """Return an integer, being ``x`` rounded towards negative infinity.""" //| ... //| +//| //| def fmod(x: float, y: float) -> int: //| """Return the remainder of ``x/y``.""" //| ... //| +//| //| def frexp(x: float) -> Tuple[int, int]: //| """Decomposes a floating-point number into its mantissa and exponent. //| The returned value is the tuple ``(m, e)`` such that ``x == m * 2**e`` @@ -122,54 +136,67 @@ static NORETURN void math_error(void) { //| the relation ``0.5 <= abs(m) < 1`` holds.""" //| ... //| +//| //| def isfinite(x: float) -> bool: //| """Return ``True`` if ``x`` is finite.""" //| ... //| +//| //| def isinf(x: float) -> bool: //| """Return ``True`` if ``x`` is infinite.""" //| ... //| +//| //| def isnan(x: float) -> bool: //| """Return ``True`` if ``x`` is not-a-number""" //| ... //| +//| //| def ldexp(x: float, exp: float) -> float: //| """Return ``x * (2**exp)``.""" //| ... //| +//| //| def log(x: float, base: float = e) -> float: //| """Return the logarithm of x to the given base. If base is not specified, //| returns the natural logarithm (base e) of x""" //| ... //| +//| //| def modf(x: float) -> Tuple[float, float]: //| """Return a tuple of two floats, being the fractional and integral parts of //| ``x``. Both return values have the same sign as ``x``.""" //| ... //| +//| //| def pow(x: float, y: float) -> float: //| """Returns ``x`` to the power of ``y``.""" //| +//| //| def radians(x: float) -> float: //| """Return degrees ``x`` converted to radians.""" //| +//| //| def sin(x: float) -> float: //| """Return the sine of ``x``.""" //| ... //| +//| //| def sqrt(x: float) -> float: //| """Returns the square root of ``x``.""" //| ... //| +//| //| def tan(x: float) -> float: //| """Return the tangent of ``x``.""" //| ... //| +//| //| def trunc(x: float) -> int: //| """Return an integer, being ``x`` rounded towards 0.""" //| ... //| +//| MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0)) MATH_FUN_2(pow, pow) @@ -183,6 +210,7 @@ MATH_FUN_1(exp, exp) //| """ //| ... //| +//| MATH_FUN_1(expm1, expm1) //| def log2(x: float) -> float: @@ -192,6 +220,7 @@ MATH_FUN_1(expm1, expm1) //| """ //| ... //| +//| MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0)) //| def log10(x: float) -> float: @@ -201,6 +230,7 @@ MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0)) //| """ //| ... //| +//| MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0)) //| def cosh(x: float) -> float: @@ -210,6 +240,7 @@ MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0)) //| """ //| ... //| +//| MATH_FUN_1(cosh, cosh) //| def sinh(x: float) -> float: @@ -219,6 +250,7 @@ MATH_FUN_1(cosh, cosh) //| """ //| ... //| +//| MATH_FUN_1(sinh, sinh) //| def tanh(x: float) -> float: @@ -228,6 +260,7 @@ MATH_FUN_1(sinh, sinh) //| """ //| ... //| +//| MATH_FUN_1(tanh, tanh) //| def acosh(x: float) -> float: @@ -237,6 +270,7 @@ MATH_FUN_1(tanh, tanh) //| """ //| ... //| +//| MATH_FUN_1(acosh, acosh) //| def asinh(x: float) -> float: @@ -246,6 +280,7 @@ MATH_FUN_1(acosh, acosh) //| """ //| ... //| +//| MATH_FUN_1(asinh, asinh) //| def atanh(x: float) -> float: @@ -255,6 +290,7 @@ MATH_FUN_1(asinh, asinh) //| """ //| ... //| +//| MATH_FUN_1(atanh, atanh) #endif @@ -300,6 +336,7 @@ MATH_FUN_2(ldexp, ldexp) //| """ //| ... //| +//| MATH_FUN_1(erf, erf) //| def erfc(x: float) -> float: @@ -309,6 +346,7 @@ MATH_FUN_1(erf, erf) //| """ //| ... //| +//| MATH_FUN_1(erfc, erfc) //| def gamma(x: float) -> float: @@ -318,6 +356,7 @@ MATH_FUN_1(erfc, erfc) //| """ //| ... //| +//| MATH_FUN_1(gamma, tgamma) //| def lgamma(x: float) -> float: @@ -327,6 +366,7 @@ MATH_FUN_1(gamma, tgamma) //| """ //| ... //| +//| MATH_FUN_1(lgamma, lgamma) //| def dist(p: tuple, q: tuple) -> float: @@ -336,6 +376,7 @@ MATH_FUN_1(lgamma, lgamma) //| """ //| ... //| +//| static mp_obj_t mp_math_dist(mp_obj_t p_obj, mp_obj_t q_obj) { mp_obj_t *p_items; mp_obj_get_array_fixed_n(p_obj, 2, &p_items); diff --git a/shared-bindings/max3421e/Max3421E.c b/shared-bindings/max3421e/Max3421E.c index e7de988a67819..ed3453efeb329 100644 --- a/shared-bindings/max3421e/Max3421E.c +++ b/shared-bindings/max3421e/Max3421E.c @@ -19,7 +19,7 @@ //| *, //| chip_select: microcontroller.Pin, //| irq: microcontroller.Pin, -//| baudrate: int = 26000000 +//| baudrate: int = 26000000, //| ) -> None: //| """Create a Max3421E object associated with the given pins. //| @@ -31,6 +31,7 @@ //| :param microcontroller.Pin irq: Interrupt pin //| :param int baudrate: Maximum baudrate to talk to the Max chip in Hz""" //| ... +//| static mp_obj_t max3421e_max3421e_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_spi_bus, ARG_chip_select, ARG_irq, ARG_baudrate }; static const mp_arg_t allowed_args[] = { @@ -47,8 +48,7 @@ static mp_obj_t max3421e_max3421e_make_new(const mp_obj_type_t *type, size_t n_a mp_obj_t spi = mp_arg_validate_type(args[ARG_spi_bus].u_obj, &busio_spi_type, MP_QSTR_spi_bus); - max3421e_max3421e_obj_t *self = m_new_obj_with_finaliser(max3421e_max3421e_obj_t); - self->base.type = &max3421e_max3421e_type; + max3421e_max3421e_obj_t *self = mp_obj_malloc_with_finaliser(max3421e_max3421e_obj_t, &max3421e_max3421e_type); common_hal_max3421e_max3421e_construct(self, MP_OBJ_TO_PTR(spi), chip_select, irq, args[ARG_baudrate].u_int); return self; @@ -58,6 +58,7 @@ static mp_obj_t max3421e_max3421e_make_new(const mp_obj_type_t *type, size_t n_a //| """Shuts down USB host functionality and releases chip_select and irq pins.""" //| ... //| +//| static mp_obj_t max3421e_max3421e_obj_deinit(mp_obj_t self_in) { max3421e_max3421e_obj_t *self = self_in; if (common_hal_max3421e_max3421e_deinited(self)) { diff --git a/shared-bindings/mcp4822/MCP4822.c b/shared-bindings/mcp4822/MCP4822.c new file mode 100644 index 0000000000000..f192caf4052a6 --- /dev/null +++ b/shared-bindings/mcp4822/MCP4822.c @@ -0,0 +1,243 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/mcp4822/MCP4822.h" +#include "shared-bindings/util.h" + +//| class MCP4822: +//| """Output audio to an MCP4822 dual-channel 12-bit SPI DAC.""" +//| +//| def __init__( +//| self, +//| clock: microcontroller.Pin, +//| mosi: microcontroller.Pin, +//| cs: microcontroller.Pin, +//| *, +//| gain: int = 1, +//| ) -> None: +//| """Create an MCP4822 object associated with the given SPI pins. +//| +//| :param ~microcontroller.Pin clock: The SPI clock (SCK) pin +//| :param ~microcontroller.Pin mosi: The SPI data (SDI/MOSI) pin +//| :param ~microcontroller.Pin cs: The chip select (CS) pin +//| :param int gain: DAC output gain, 1 for 1x (0-2.048V) or 2 for 2x (0-4.096V). Default 1. +//| +//| Simple 8ksps 440 Hz sine wave:: +//| +//| import mcp4822 +//| import audiocore +//| import board +//| import array +//| import time +//| import math +//| +//| length = 8000 // 440 +//| sine_wave = array.array("H", [0] * length) +//| for i in range(length): +//| sine_wave[i] = int(math.sin(math.pi * 2 * i / length) * (2 ** 15) + 2 ** 15) +//| +//| sine_wave = audiocore.RawSample(sine_wave, sample_rate=8000) +//| dac = mcp4822.MCP4822(clock=board.GP18, mosi=board.GP19, cs=board.GP21) +//| dac.play(sine_wave, loop=True) +//| time.sleep(1) +//| dac.stop() +//| +//| Playing a wave file from flash:: +//| +//| import board +//| import audiocore +//| import mcp4822 +//| +//| f = open("sound.wav", "rb") +//| wav = audiocore.WaveFile(f) +//| +//| dac = mcp4822.MCP4822(clock=board.GP18, mosi=board.GP19, cs=board.GP21) +//| dac.play(wav) +//| while dac.playing: +//| pass""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_clock, ARG_mosi, ARG_cs, ARG_gain }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_mosi, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_cs, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_gain, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 1} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *mosi = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mp_int_t gain = mp_arg_validate_int_range(args[ARG_gain].u_int, 1, 2, MP_QSTR_gain); + + mcp4822_mcp4822_obj_t *self = mp_obj_malloc_with_finaliser(mcp4822_mcp4822_obj_t, &mcp4822_mcp4822_type); + common_hal_mcp4822_mcp4822_construct(self, clock, mosi, cs, (uint8_t)gain); + + return MP_OBJ_FROM_PTR(self); +} + +static void check_for_deinit(mcp4822_mcp4822_obj_t *self) { + if (common_hal_mcp4822_mcp4822_deinited(self)) { + raise_deinited_error(); + } +} + +//| def deinit(self) -> None: +//| """Deinitialises the MCP4822 and releases any hardware resources for reuse.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_deinit(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_mcp4822_mcp4822_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_deinit_obj, mcp4822_mcp4822_deinit); + +//| def __enter__(self) -> MCP4822: +//| """No-op used by Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware when exiting a context. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +// Provided by context manager helper. + +//| def play(self, sample: circuitpython_typing.AudioSample, *, loop: bool = False) -> None: +//| """Plays the sample once when loop=False and continuously when loop=True. +//| Does not block. Use `playing` to block. +//| +//| Sample must be an `audiocore.WaveFile`, `audiocore.RawSample`, `audiomixer.Mixer` or `audiomp3.MP3Decoder`. +//| +//| The sample itself should consist of 8 bit or 16 bit samples.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_play(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_sample, ARG_loop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sample, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_loop, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = false} }, + }; + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_obj_t sample = args[ARG_sample].u_obj; + common_hal_mcp4822_mcp4822_play(self, sample, args[ARG_loop].u_bool); + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mcp4822_mcp4822_play_obj, 1, mcp4822_mcp4822_obj_play); + +//| def stop(self) -> None: +//| """Stops playback.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_stop(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_mcp4822_mcp4822_stop(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_stop_obj, mcp4822_mcp4822_obj_stop); + +//| playing: bool +//| """True when the audio sample is being output. (read-only)""" +//| +static mp_obj_t mcp4822_mcp4822_obj_get_playing(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_mcp4822_mcp4822_get_playing(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_get_playing_obj, mcp4822_mcp4822_obj_get_playing); + +MP_PROPERTY_GETTER(mcp4822_mcp4822_playing_obj, + (mp_obj_t)&mcp4822_mcp4822_get_playing_obj); + +//| def pause(self) -> None: +//| """Stops playback temporarily while remembering the position. Use `resume` to resume playback.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_pause(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (!common_hal_mcp4822_mcp4822_get_playing(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Not playing")); + } + common_hal_mcp4822_mcp4822_pause(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_pause_obj, mcp4822_mcp4822_obj_pause); + +//| def resume(self) -> None: +//| """Resumes sample playback after :py:func:`pause`.""" +//| ... +//| +static mp_obj_t mcp4822_mcp4822_obj_resume(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + if (common_hal_mcp4822_mcp4822_get_paused(self)) { + common_hal_mcp4822_mcp4822_resume(self); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_resume_obj, mcp4822_mcp4822_obj_resume); + +//| paused: bool +//| """True when playback is paused. (read-only)""" +//| +//| +static mp_obj_t mcp4822_mcp4822_obj_get_paused(mp_obj_t self_in) { + mcp4822_mcp4822_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(common_hal_mcp4822_mcp4822_get_paused(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mcp4822_mcp4822_get_paused_obj, mcp4822_mcp4822_obj_get_paused); + +MP_PROPERTY_GETTER(mcp4822_mcp4822_paused_obj, + (mp_obj_t)&mcp4822_mcp4822_get_paused_obj); + +static const mp_rom_map_elem_t mcp4822_mcp4822_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mcp4822_mcp4822_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mcp4822_mcp4822_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_play), MP_ROM_PTR(&mcp4822_mcp4822_play_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mcp4822_mcp4822_stop_obj) }, + { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&mcp4822_mcp4822_pause_obj) }, + { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&mcp4822_mcp4822_resume_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_playing), MP_ROM_PTR(&mcp4822_mcp4822_playing_obj) }, + { MP_ROM_QSTR(MP_QSTR_paused), MP_ROM_PTR(&mcp4822_mcp4822_paused_obj) }, +}; +static MP_DEFINE_CONST_DICT(mcp4822_mcp4822_locals_dict, mcp4822_mcp4822_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mcp4822_mcp4822_type, + MP_QSTR_MCP4822, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, mcp4822_mcp4822_make_new, + locals_dict, &mcp4822_mcp4822_locals_dict + ); diff --git a/shared-bindings/mcp4822/MCP4822.h b/shared-bindings/mcp4822/MCP4822.h new file mode 100644 index 0000000000000..b129aec306124 --- /dev/null +++ b/shared-bindings/mcp4822/MCP4822.h @@ -0,0 +1,25 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/mcp4822/MCP4822.h" +#include "common-hal/microcontroller/Pin.h" + +extern const mp_obj_type_t mcp4822_mcp4822_type; + +void common_hal_mcp4822_mcp4822_construct(mcp4822_mcp4822_obj_t *self, + const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, + const mcu_pin_obj_t *cs, uint8_t gain); + +void common_hal_mcp4822_mcp4822_deinit(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_deinited(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_play(mcp4822_mcp4822_obj_t *self, mp_obj_t sample, bool loop); +void common_hal_mcp4822_mcp4822_stop(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_get_playing(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_pause(mcp4822_mcp4822_obj_t *self); +void common_hal_mcp4822_mcp4822_resume(mcp4822_mcp4822_obj_t *self); +bool common_hal_mcp4822_mcp4822_get_paused(mcp4822_mcp4822_obj_t *self); diff --git a/shared-bindings/mcp4822/__init__.c b/shared-bindings/mcp4822/__init__.c new file mode 100644 index 0000000000000..bac2136d9e7c0 --- /dev/null +++ b/shared-bindings/mcp4822/__init__.c @@ -0,0 +1,36 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/mcp4822/__init__.h" +#include "shared-bindings/mcp4822/MCP4822.h" + +//| """Audio output via MCP4822 dual-channel 12-bit SPI DAC. +//| +//| The `mcp4822` module provides the `MCP4822` class for non-blocking +//| audio playback through the Microchip MCP4822 SPI DAC using PIO and DMA. +//| +//| All classes change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager.""" + +static const mp_rom_map_elem_t mcp4822_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mcp4822) }, + { MP_ROM_QSTR(MP_QSTR_MCP4822), MP_ROM_PTR(&mcp4822_mcp4822_type) }, +}; + +static MP_DEFINE_CONST_DICT(mcp4822_module_globals, mcp4822_module_globals_table); + +const mp_obj_module_t mcp4822_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mcp4822_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_mcp4822, mcp4822_module); diff --git a/shared-bindings/mcp4822/__init__.h b/shared-bindings/mcp4822/__init__.h new file mode 100644 index 0000000000000..c4a52e5819d12 --- /dev/null +++ b/shared-bindings/mcp4822/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/mdns/RemoteService.c b/shared-bindings/mdns/RemoteService.c index d1eddc6961118..b3ee3d7f7b74f 100644 --- a/shared-bindings/mdns/RemoteService.c +++ b/shared-bindings/mdns/RemoteService.c @@ -20,6 +20,7 @@ //| def __init__(self) -> None: //| """Cannot be instantiated directly. Use `mdns.Server.find`.""" //| ... +//| //| hostname: str //| """The hostname of the device (read-only),.""" @@ -82,6 +83,7 @@ MP_PROPERTY_GETTER(mdns_remoteservice_port_obj, //| ipv4_address: Optional[ipaddress.IPv4Address] //| """IP v4 Address of the remote service. None if no A records are found.""" +//| static mp_obj_t _mdns_remoteservice_get_ipv4_address(mp_obj_t self) { return common_hal_mdns_remoteservice_get_ipv4_address(self); @@ -95,6 +97,7 @@ MP_PROPERTY_GETTER(mdns_remoteservice_ipv4_address_obj, //| """Deletes the RemoteService object.""" //| ... //| +//| static mp_obj_t mdns_remoteservice_obj_deinit(mp_obj_t self_in) { mdns_remoteservice_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_mdns_remoteservice_deinit(self); diff --git a/shared-bindings/mdns/Server.c b/shared-bindings/mdns/Server.c index 247c96254fbb7..86fb2eb6d7aaa 100644 --- a/shared-bindings/mdns/Server.c +++ b/shared-bindings/mdns/Server.c @@ -30,6 +30,7 @@ //| may already be using it.) Only native interfaces are currently supported. //| """ //| ... +//| static mp_obj_t mdns_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_network_interface }; static const mp_arg_t allowed_args[] = { @@ -46,8 +47,7 @@ static mp_obj_t mdns_server_make_new(const mp_obj_type_t *type, size_t n_args, s } #endif - mdns_server_obj_t *self = m_new_obj_with_finaliser(mdns_server_obj_t); - self->base.type = &mdns_server_type; + mdns_server_obj_t *self = mp_obj_malloc_with_finaliser(mdns_server_obj_t, &mdns_server_type); common_hal_mdns_server_construct(self, args[ARG_network_interface].u_obj); return MP_OBJ_FROM_PTR(self); @@ -56,6 +56,7 @@ static mp_obj_t mdns_server_make_new(const mp_obj_type_t *type, size_t n_args, s //| def deinit(self) -> None: //| """Stops the server""" //| ... +//| static mp_obj_t mdns_server_obj_deinit(mp_obj_t self_in) { mdns_server_obj_t *self = (mdns_server_obj_t *)self_in; common_hal_mdns_server_deinit(self); @@ -94,6 +95,7 @@ MP_PROPERTY_GETSET(mdns_server_hostname_obj, //| instance_name: str //| """Human readable name to describe the device.""" +//| static mp_obj_t mdns_server_get_instance_name(mp_obj_t self) { check_for_deinit(self); const char *instance_name = common_hal_mdns_server_get_instance_name(self); @@ -125,6 +127,7 @@ MP_PROPERTY_GETSET(mdns_server_instance_name_obj, //| :param str protocol: The service protocol such as "_tcp" //| :param float/int timeout: Time to wait for responses""" //| ... +//| static mp_obj_t _mdns_server_find(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mdns_server_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); check_for_deinit(self); @@ -165,6 +168,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(mdns_server_find_obj, 1, _mdns_server_find); //| """ //| ... //| +//| static mp_obj_t mdns_server_advertise_service(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mdns_server_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); check_for_deinit(self); diff --git a/shared-bindings/memorymap/AddressRange.c b/shared-bindings/memorymap/AddressRange.c index 3b742ce463bed..5f7ee0deb9554 100644 --- a/shared-bindings/memorymap/AddressRange.c +++ b/shared-bindings/memorymap/AddressRange.c @@ -39,7 +39,7 @@ //| # Pad control register is updated using an MP-safe atomic XOR //| pad_ctrl ^= (d << 4) //| pad_ctrl &= 0x00000030 -//| pads_bank0[p*4+0x3004:p*4+0x3008] = pad_ctrl.to_bytes(4, "little") +//| pads_bank0[p*4+0x1004:p*4+0x1008] = pad_ctrl.to_bytes(4, "little") //| //| def rp2040_get_pad_drive(p): //| pads_bank0 = memorymap.AddressRange(start=0x4001C000, length=0x4000) @@ -51,14 +51,19 @@ //| //| # print GPIO16 pad drive strength //| print(rp2040_get_pad_drive(16)) +//| +//| Note that the above example does **not** work on RP2350 because base +//| address and organization of the "pads0" registers changed compared +//| to the RP2040. //| """ //| -//| def __init__(self, *, start, length) -> None: +//| def __init__(self, *, start: int, length: int) -> None: //| """Constructs an address range starting at ``start`` and ending at //| ``start + length``. An exception will be raised if any of the //| addresses are invalid or protected.""" //| ... +//| static mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_start, ARG_length }; static const mp_arg_t allowed_args[] = { @@ -87,7 +92,6 @@ static mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_ } memorymap_addressrange_obj_t *self = mp_obj_malloc(memorymap_addressrange_obj_t, &memorymap_addressrange_type); - common_hal_memorymap_addressrange_construct(self, (uint8_t *)start, length); return MP_OBJ_FROM_PTR(self); @@ -97,6 +101,7 @@ static mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_ //| def __len__(self) -> int: //| """Return the length. This is used by (`len`)""" //| ... +//| static mp_obj_t memorymap_addressrange_unary_op(mp_unary_op_t op, mp_obj_t self_in) { memorymap_addressrange_obj_t *self = MP_OBJ_TO_PTR(self_in); uint16_t len = common_hal_memorymap_addressrange_get_length(self); @@ -128,6 +133,7 @@ static MP_DEFINE_CONST_DICT(memorymap_addressrange_locals_dict, memorymap_addres //| //| @overload //| def __setitem__(self, index: slice, value: ReadableBuffer) -> None: ... +//| //| @overload //| def __setitem__(self, index: int, value: int) -> None: //| """Set the value(s) at the given index. @@ -137,6 +143,7 @@ static MP_DEFINE_CONST_DICT(memorymap_addressrange_locals_dict, memorymap_addres //| All others may use multiple transactions.""" //| ... //| +//| static mp_obj_t memorymap_addressrange_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item diff --git a/shared-bindings/memorymonitor/AllocationAlarm.c b/shared-bindings/memorymonitor/AllocationAlarm.c index 9fa07376b2c4f..00cfbbd9fe194 100644 --- a/shared-bindings/memorymonitor/AllocationAlarm.c +++ b/shared-bindings/memorymonitor/AllocationAlarm.c @@ -33,6 +33,7 @@ //| //| """ //| ... +//| static mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) { enum { ARG_minimum_block_count }; static const mp_arg_t allowed_args[] = { @@ -47,7 +48,6 @@ static mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type memorymonitor_allocationalarm_obj_t *self = mp_obj_malloc(memorymonitor_allocationalarm_obj_t, &memorymonitor_allocationalarm_type); - common_hal_memorymonitor_allocationalarm_construct(self, minimum_block_count); return MP_OBJ_FROM_PTR(self); @@ -64,6 +64,7 @@ static mp_obj_t memorymonitor_allocationalarm_make_new(const mp_obj_type_t *type //| x = bytearray(20) //| """ //| ... +//| static mp_obj_t memorymonitor_allocationalarm_obj_ignore(mp_obj_t self_in, mp_obj_t count_obj) { mp_int_t count = mp_obj_get_int(count_obj); mp_arg_validate_int_min(count, 0, MP_QSTR_count); @@ -76,6 +77,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(memorymonitor_allocationalarm_ignore_obj, memorymonito //| def __enter__(self) -> AllocationAlarm: //| """Enables the alarm.""" //| ... +//| static mp_obj_t memorymonitor_allocationalarm_obj___enter__(mp_obj_t self_in) { common_hal_memorymonitor_allocationalarm_resume(self_in); return self_in; @@ -87,6 +89,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(memorymonitor_allocationalarm___enter___obj, memorymon //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... //| +//| static mp_obj_t memorymonitor_allocationalarm_obj___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; common_hal_memorymonitor_allocationalarm_set_ignore(args[0], 0); diff --git a/shared-bindings/memorymonitor/AllocationSize.c b/shared-bindings/memorymonitor/AllocationSize.c index 34f1d3e3f3b94..3113d6ed191ad 100644 --- a/shared-bindings/memorymonitor/AllocationSize.c +++ b/shared-bindings/memorymonitor/AllocationSize.c @@ -40,6 +40,7 @@ //| //| """ //| ... +//| static mp_obj_t memorymonitor_allocationsize_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *all_args, mp_map_t *kw_args) { memorymonitor_allocationsize_obj_t *self = m_new_obj(memorymonitor_allocationsize_obj_t, &memorymonitor_allocationsize_type); @@ -52,6 +53,7 @@ static mp_obj_t memorymonitor_allocationsize_make_new(const mp_obj_type_t *type, //| def __enter__(self) -> AllocationSize: //| """Clears counts and resumes tracking.""" //| ... +//| static mp_obj_t memorymonitor_allocationsize_obj___enter__(mp_obj_t self_in) { common_hal_memorymonitor_allocationsize_clear(self_in); common_hal_memorymonitor_allocationsize_resume(self_in); @@ -63,6 +65,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(memorymonitor_allocationsize___enter___obj, memorymoni //| """Automatically pauses allocation tracking when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... +//| static mp_obj_t memorymonitor_allocationsize_obj___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; common_hal_memorymonitor_allocationsize_pause(args[0]); @@ -72,6 +75,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(memorymonitor_allocationsize___exit__ //| bytes_per_block: int //| """Number of bytes per block""" +//| static mp_obj_t memorymonitor_allocationsize_obj_get_bytes_per_block(mp_obj_t self_in) { memorymonitor_allocationsize_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -90,6 +94,7 @@ MP_PROPERTY_GETTER(memorymonitor_allocationsize_bytes_per_block_obj, //| mm = memorymonitor.AllocationSize() //| print(len(mm))""" //| ... +//| static mp_obj_t memorymonitor_allocationsize_unary_op(mp_unary_op_t op, mp_obj_t self_in) { memorymonitor_allocationsize_obj_t *self = MP_OBJ_TO_PTR(self_in); uint16_t len = common_hal_memorymonitor_allocationsize_get_len(self); @@ -112,6 +117,7 @@ static mp_obj_t memorymonitor_allocationsize_unary_op(mp_unary_op_t op, mp_obj_t //| print(mm[0])""" //| ... //| +//| static mp_obj_t memorymonitor_allocationsize_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { if (value == mp_const_none) { // delete item diff --git a/shared-bindings/memorymonitor/__init__.c b/shared-bindings/memorymonitor/__init__.c index e925eb54e7466..e364344b363bd 100644 --- a/shared-bindings/memorymonitor/__init__.c +++ b/shared-bindings/memorymonitor/__init__.c @@ -15,15 +15,17 @@ //| """Memory monitoring helpers""" //| +//| //| class AllocationError(Exception): //| """Catchall exception for allocation related errors.""" //| //| ... //| +//| MP_DEFINE_MEMORYMONITOR_EXCEPTION(AllocationError, Exception) -NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t fmt, ...) { va_list argptr; va_start(argptr, fmt); mp_obj_t exception = mp_obj_new_exception_msg_vlist(&mp_type_memorymonitor_AllocationError, fmt, argptr); diff --git a/shared-bindings/memorymonitor/__init__.h b/shared-bindings/memorymonitor/__init__.h index 28480bea7b52b..5f141b924d09d 100644 --- a/shared-bindings/memorymonitor/__init__.h +++ b/shared-bindings/memorymonitor/__init__.h @@ -23,4 +23,4 @@ void memorymonitor_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr extern const mp_obj_type_t mp_type_memorymonitor_AllocationError; -NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t msg, ...); +MP_NORETURN void mp_raise_memorymonitor_AllocationError(mp_rom_error_text_t msg, ...); diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c index b0260a2295478..1fcde50e060b6 100644 --- a/shared-bindings/microcontroller/Pin.c +++ b/shared-bindings/microcontroller/Pin.c @@ -20,11 +20,13 @@ //| hardware so they cannot be constructed on demand. Instead, use //| :mod:`board` or :mod:`microcontroller.pin` to reference the desired pin.""" //| ... +//| //| def __hash__(self) -> int: //| """Returns a hash for the Pin.""" //| ... //| +//| // Provided inherently. // See https://github.com/micropython/micropython/pull/10348. @@ -173,14 +175,14 @@ void validate_pins(qstr what, uint8_t *pin_nos, mp_int_t max_pins, mp_obj_t seq, } } -NORETURN void raise_ValueError_invalid_pin(void) { +MP_NORETURN void raise_ValueError_invalid_pin(void) { mp_arg_error_invalid(MP_QSTR_pin); } -NORETURN void raise_ValueError_invalid_pins(void) { +MP_NORETURN void raise_ValueError_invalid_pins(void) { mp_arg_error_invalid(MP_QSTR_pins); } -NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name) { +MP_NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name) { mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q pin"), pin_name); } diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h index 1245b5f23e4a7..8ddca71bfbbe3 100644 --- a/shared-bindings/microcontroller/Pin.h +++ b/shared-bindings/microcontroller/Pin.h @@ -21,9 +21,9 @@ void validate_no_duplicate_pins(mp_obj_t seq, qstr arg_name); void validate_no_duplicate_pins_2(mp_obj_t seq1, mp_obj_t seq2, qstr arg_name1, qstr arg_name2); void validate_list_is_free_pins(qstr what, const mcu_pin_obj_t **pins_out, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out); void validate_pins(qstr what, uint8_t *pin_nos, mp_int_t max_pins, mp_obj_t seq, uint8_t *count_out); -NORETURN void raise_ValueError_invalid_pin(void); -NORETURN void raise_ValueError_invalid_pins(void); -NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name); +MP_NORETURN void raise_ValueError_invalid_pin(void); +MP_NORETURN void raise_ValueError_invalid_pins(void); +MP_NORETURN void raise_ValueError_invalid_pin_name(qstr pin_name); void assert_pin_free(const mcu_pin_obj_t *pin); diff --git a/shared-bindings/microcontroller/Processor.c b/shared-bindings/microcontroller/Processor.c index 0a14059783288..a3518ab754f50 100644 --- a/shared-bindings/microcontroller/Processor.c +++ b/shared-bindings/microcontroller/Processor.c @@ -42,6 +42,7 @@ //| """You cannot create an instance of `microcontroller.Processor`. //| Use `microcontroller.cpu` to access the sole instance available.""" //| ... +//| //| frequency: int //| """The CPU operating frequency in Hertz. @@ -130,6 +131,7 @@ MP_PROPERTY_GETTER(mcu_processor_uid_obj, //| //| Is `None` if the voltage is not available.""" //| +//| static mp_obj_t mcu_processor_get_voltage(mp_obj_t self) { float voltage = common_hal_mcu_processor_get_voltage(); return isnan(voltage) ? mp_const_none : mp_obj_new_float(voltage); diff --git a/shared-bindings/microcontroller/ResetReason.c b/shared-bindings/microcontroller/ResetReason.c index 301205d84f369..e16e8a056fbf2 100644 --- a/shared-bindings/microcontroller/ResetReason.c +++ b/shared-bindings/microcontroller/ResetReason.c @@ -45,6 +45,7 @@ MAKE_ENUM_VALUE(mcu_reset_reason_type, reset_reason, RESCUE_DEBUG, RESET_REASON_ //| RESCUE_DEBUG: object //| """The microcontroller was reset by the rescue debug port.""" //| +//| MAKE_ENUM_MAP(mcu_reset_reason) { MAKE_ENUM_MAP_ENTRY(reset_reason, POWER_ON), MAKE_ENUM_MAP_ENTRY(reset_reason, BROWNOUT), diff --git a/shared-bindings/microcontroller/RunMode.c b/shared-bindings/microcontroller/RunMode.c index 95979e5533c5a..ac5ffd62136c2 100644 --- a/shared-bindings/microcontroller/RunMode.c +++ b/shared-bindings/microcontroller/RunMode.c @@ -12,6 +12,7 @@ //| def __init__(self) -> None: //| """Enum-like class to define the run mode of the microcontroller and //| CircuitPython.""" +//| //| NORMAL: RunMode //| """Run CircuitPython as normal. //| @@ -33,6 +34,7 @@ //| //| :type microcontroller.RunMode:""" //| +//| const mp_obj_type_t mcu_runmode_type; const mcu_runmode_obj_t mcu_runmode_uf2_obj = { diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c index eb2fc79ec33ee..55e36356a537e 100644 --- a/shared-bindings/microcontroller/__init__.c +++ b/shared-bindings/microcontroller/__init__.c @@ -39,6 +39,7 @@ //| (clock frequency) on chips with more than 1 cpu. The index selects which cpu. //| This object is an instance of `microcontroller.Processor`.""" //| +//| //| def delay_us(delay: int) -> None: //| """Dedicated delay method used for very short delays. **Do not** do long delays @@ -49,6 +50,7 @@ //| `time.sleep()`.""" //| ... //| +//| static mp_obj_t mcu_delay_us(mp_obj_t delay_obj) { uint32_t delay = mp_obj_get_int(delay_obj); @@ -62,6 +64,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(mcu_delay_us_obj, mcu_delay_us); //| """Disable all interrupts. Be very careful, this can stall everything.""" //| ... //| +//| static mp_obj_t mcu_disable_interrupts(void) { common_hal_mcu_disable_interrupts(); return mp_const_none; @@ -72,6 +75,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(mcu_disable_interrupts_obj, mcu_disable_interru //| """Enable the interrupts that were enabled at the last disable.""" //| ... //| +//| static mp_obj_t mcu_enable_interrupts(void) { common_hal_mcu_enable_interrupts(); return mp_const_none; @@ -85,6 +89,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(mcu_enable_interrupts_obj, mcu_enable_interrupt //| :param ~microcontroller.RunMode run_mode: The next run mode""" //| ... //| +//| static mp_obj_t mcu_on_next_reset(mp_obj_t run_mode_obj) { mcu_runmode_t run_mode; if (run_mode_obj == MP_OBJ_FROM_PTR(&mcu_runmode_uf2_obj)) { @@ -112,6 +117,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(mcu_on_next_reset_obj, mcu_on_next_reset); //| "Safely removed" on Windows or "ejected" on Mac OSX and Linux.""" //| ... //| +//| static mp_obj_t mcu_reset(void) { common_hal_mcu_reset(); // We won't actually get here because we're resetting. diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h index a94cca7b69726..5c5902ff965f5 100644 --- a/shared-bindings/microcontroller/__init__.h +++ b/shared-bindings/microcontroller/__init__.h @@ -20,7 +20,7 @@ extern void common_hal_mcu_disable_interrupts(void); extern void common_hal_mcu_enable_interrupts(void); extern void common_hal_mcu_on_next_reset(mcu_runmode_t runmode); -extern void common_hal_mcu_reset(void); +MP_NORETURN extern void common_hal_mcu_reset(void); extern const mp_obj_dict_t mcu_pin_globals; diff --git a/shared-bindings/mipidsi/Bus.c b/shared-bindings/mipidsi/Bus.c new file mode 100644 index 0000000000000..bac3cd3c75e1b --- /dev/null +++ b/shared-bindings/mipidsi/Bus.c @@ -0,0 +1,84 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +#include "shared-bindings/mipidsi/Bus.h" +#include "shared-bindings/util.h" +#include "shared/runtime/context_manager_helpers.h" + +//| class Bus: +//| def __init__( +//| self, +//| *, +//| frequency: int = 500_000_000, +//| num_lanes: int = 2, +//| ) -> None: +//| """Create a MIPI DSI Bus object. +//| +//| This creates a DSI bus interface. The specific pins used are determined by the board. +//| DSI supports 1-4 data lanes. +//| +//| :param int frequency: the high speed clock frequency in Hz (default 500 MHz) +//| :param int num_lanes: the number of data lanes to use (default 2, range 1-4) +//| """ +//| +// +// +// All MCUs we support only have one DSI bus but it can be shared between multiple displays. One +// display may live longer than the VM, so we need to allocate the bus outside the VM. To simplify +// memory tracking, we use a global object for the bus. +// +static mipidsi_bus_obj_t _mipidsi_bus_obj; + +static mp_obj_t mipidsi_bus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_frequency, ARG_num_lanes }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000000} }, + { MP_QSTR_num_lanes, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 2} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + _mipidsi_bus_obj.base.type = &mipidsi_bus_type; + mipidsi_bus_obj_t *self = &_mipidsi_bus_obj; + + mp_uint_t frequency = (mp_uint_t)mp_arg_validate_int_min(args[ARG_frequency].u_int, 1, MP_QSTR_frequency); + uint8_t num_lanes = (uint8_t)mp_arg_validate_int_range(args[ARG_num_lanes].u_int, 1, 4, MP_QSTR_num_lanes); + + common_hal_mipidsi_bus_construct(self, frequency, num_lanes); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Free the resources (pins, timers, etc.) associated with this +//| `mipidsi.Bus` instance. After deinitialization, no further operations +//| may be performed.""" +//| ... +//| +static mp_obj_t mipidsi_bus_deinit(mp_obj_t self_in) { + mipidsi_bus_obj_t *self = (mipidsi_bus_obj_t *)self_in; + common_hal_mipidsi_bus_deinit(self); + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_1(mipidsi_bus_deinit_obj, mipidsi_bus_deinit); + +static const mp_rom_map_elem_t mipidsi_bus_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mipidsi_bus_deinit_obj) }, +}; +static MP_DEFINE_CONST_DICT(mipidsi_bus_locals_dict, mipidsi_bus_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + mipidsi_bus_type, + MP_QSTR_Bus, + MP_TYPE_FLAG_NONE, + make_new, mipidsi_bus_make_new, + locals_dict, &mipidsi_bus_locals_dict + ); diff --git a/shared-bindings/mipidsi/Bus.h b/shared-bindings/mipidsi/Bus.h new file mode 100644 index 0000000000000..f2fd13f7fc165 --- /dev/null +++ b/shared-bindings/mipidsi/Bus.h @@ -0,0 +1,15 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/mipidsi/Bus.h" + +extern const mp_obj_type_t mipidsi_bus_type; + +void common_hal_mipidsi_bus_construct(mipidsi_bus_obj_t *self, mp_uint_t frequency, uint8_t num_lanes); +void common_hal_mipidsi_bus_deinit(mipidsi_bus_obj_t *self); +bool common_hal_mipidsi_bus_deinited(mipidsi_bus_obj_t *self); diff --git a/shared-bindings/mipidsi/Display.c b/shared-bindings/mipidsi/Display.c new file mode 100644 index 0000000000000..149d31e52a93f --- /dev/null +++ b/shared-bindings/mipidsi/Display.c @@ -0,0 +1,300 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/objtype.h" + +#include "shared-bindings/mipidsi/Display.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "shared-module/displayio/__init__.h" +#include "shared-module/framebufferio/FramebufferDisplay.h" + +//| class Display: +//| def __init__( +//| self, +//| bus: Bus, +//| init_sequence: ReadableBuffer, +//| *, +//| width: int, +//| height: int, +//| hsync_pulse_width: int, +//| hsync_back_porch: int, +//| hsync_front_porch: int, +//| vsync_pulse_width: int, +//| vsync_back_porch: int, +//| vsync_front_porch: int, +//| pixel_clock_frequency: int, +//| virtual_channel: int = 0, +//| rotation: int = 0, +//| color_depth: int = 16, +//| backlight_pin: Optional[microcontroller.Pin] = None, +//| brightness: float = 1.0, +//| native_frames_per_second: int = 60, +//| backlight_on_high: bool = True, +//| ) -> None: +//| """Create a MIPI DSI Display object connected to the given bus. +//| +//| This allocates a framebuffer and configures the DSI display to use the +//| specified virtual channel for communication. +//| +//| The framebuffer pixel format varies depending on color_depth: +//| +//| * 16 - Each two bytes is a pixel in RGB565 format. +//| * 24 - Each three bytes is a pixel in RGB888 format. +//| +//| A Display is often used in conjunction with a +//| `framebufferio.FramebufferDisplay`. +//| +//| :param Bus bus: the DSI bus to use +//| :param ~circuitpython_typing.ReadableBuffer init_sequence: Byte-packed initialization sequence for the display +//| :param int width: the width of the framebuffer in pixels +//| :param int height: the height of the framebuffer in pixels +//| :param int hsync_pulse_width: horizontal sync pulse width in pixel clocks +//| :param int hsync_back_porch: horizontal back porch in pixel clocks +//| :param int hsync_front_porch: horizontal front porch in pixel clocks +//| :param int vsync_pulse_width: vertical sync pulse width in lines +//| :param int vsync_back_porch: vertical back porch in lines +//| :param int vsync_front_porch: vertical front porch in lines +//| :param int pixel_clock_frequency: pixel clock frequency in Hz +//| :param int virtual_channel: the DSI virtual channel (0-3) +//| :param int rotation: the rotation of the display in degrees clockwise (0, 90, 180, 270) +//| :param int color_depth: the color depth of the framebuffer in bits (16 or 24) +//| :param microcontroller.Pin backlight_pin: Pin connected to the display's backlight +//| :param float brightness: Initial display brightness (0.0 to 1.0) +//| :param int native_frames_per_second: Number of display refreshes per second +//| :param bool backlight_on_high: If True, pulling the backlight pin high turns the backlight on +//| """ +//| + +static mp_obj_t mipidsi_display_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_bus, ARG_init_sequence, ARG_width, ARG_height, ARG_hsync_pulse_width, ARG_hsync_back_porch, + ARG_hsync_front_porch, ARG_vsync_pulse_width, ARG_vsync_back_porch, ARG_vsync_front_porch, + ARG_pixel_clock_frequency, ARG_virtual_channel, ARG_rotation, + ARG_color_depth, ARG_backlight_pin, ARG_brightness, ARG_native_frames_per_second, + ARG_backlight_on_high }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bus, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_init_sequence, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_height, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_hsync_pulse_width, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_hsync_back_porch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_hsync_front_porch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_vsync_pulse_width, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_vsync_back_porch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_vsync_front_porch, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_pixel_clock_frequency, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_virtual_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rotation, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_color_depth, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} }, + { MP_QSTR_backlight_pin, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = mp_const_none} }, + { MP_QSTR_brightness, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_OBJ_NEW_SMALL_INT(1)} }, + { MP_QSTR_native_frames_per_second, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 60} }, + { MP_QSTR_backlight_on_high, MP_ARG_BOOL | MP_ARG_KW_ONLY, {.u_bool = true} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mipidsi_display_obj_t *self = &allocate_display_bus_or_raise()->mipidsi; + self->base.type = &mipidsi_display_type; + + mipidsi_bus_obj_t *bus = mp_arg_validate_type(args[ARG_bus].u_obj, &mipidsi_bus_type, MP_QSTR_bus); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_init_sequence].u_obj, &bufinfo, MP_BUFFER_READ); + + const mcu_pin_obj_t *backlight_pin = + validate_obj_is_free_pin_or_none(args[ARG_backlight_pin].u_obj, MP_QSTR_backlight_pin); + + mp_float_t brightness = mp_obj_get_float(args[ARG_brightness].u_obj); + + mp_int_t rotation = args[ARG_rotation].u_int; + if (rotation % 90 != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("Display rotation must be in 90 degree increments")); + } + + mp_uint_t virtual_channel = (mp_uint_t)mp_arg_validate_int_range(args[ARG_virtual_channel].u_int, 0, 3, MP_QSTR_virtual_channel); + mp_uint_t width = (mp_uint_t)mp_arg_validate_int_min(args[ARG_width].u_int, 0, MP_QSTR_width); + mp_uint_t height = (mp_uint_t)mp_arg_validate_int_min(args[ARG_height].u_int, 0, MP_QSTR_height); + mp_uint_t color_depth = args[ARG_color_depth].u_int; + + if (color_depth != 16 && color_depth != 24) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_color_depth); + } + + common_hal_mipidsi_display_construct(self, bus, bufinfo.buf, bufinfo.len, virtual_channel, width, height, + rotation, color_depth, MP_OBJ_TO_PTR(backlight_pin), brightness, + args[ARG_native_frames_per_second].u_int, + args[ARG_backlight_on_high].u_bool, + args[ARG_hsync_pulse_width].u_int, + args[ARG_hsync_back_porch].u_int, + args[ARG_hsync_front_porch].u_int, + args[ARG_vsync_pulse_width].u_int, + args[ARG_vsync_back_porch].u_int, + args[ARG_vsync_front_porch].u_int, + args[ARG_pixel_clock_frequency].u_int); + + return MP_OBJ_FROM_PTR(self); +} + +// Helper to ensure we have the native super class instead of a subclass. +static mipidsi_display_obj_t *native_display(mp_obj_t display_obj) { + mp_obj_t native_display = mp_obj_cast_to_native_base(display_obj, &mipidsi_display_type); + mp_obj_assert_native_inited(native_display); + return MP_OBJ_TO_PTR(native_display); +} + +//| def deinit(self) -> None: +//| """Free the resources (pins, timers, etc.) associated with this +//| `mipidsi.Display` instance. After deinitialization, no further operations +//| may be performed.""" +//| ... +//| +static mp_obj_t mipidsi_display_deinit(mp_obj_t self_in) { + mipidsi_display_obj_t *self = native_display(self_in); + common_hal_mipidsi_display_deinit(self); + return mp_const_none; +} + +static MP_DEFINE_CONST_FUN_OBJ_1(mipidsi_display_deinit_obj, mipidsi_display_deinit); + +static void check_for_deinit(mipidsi_display_obj_t *self) { + if (common_hal_mipidsi_display_deinited(self)) { + raise_deinited_error(); + } +} + +//| width: int +//| """The width of the framebuffer, in pixels.""" +static mp_obj_t mipidsi_display_get_width(mp_obj_t self_in) { + mipidsi_display_obj_t *self = native_display(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_mipidsi_display_get_width(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mipidsi_display_get_width_obj, mipidsi_display_get_width); +MP_PROPERTY_GETTER(mipidsi_display_width_obj, + (mp_obj_t)&mipidsi_display_get_width_obj); + +//| height: int +//| """The height of the framebuffer, in pixels.""" +//| +//| +static mp_obj_t mipidsi_display_get_height(mp_obj_t self_in) { + mipidsi_display_obj_t *self = native_display(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_mipidsi_display_get_height(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mipidsi_display_get_height_obj, mipidsi_display_get_height); + +MP_PROPERTY_GETTER(mipidsi_display_height_obj, + (mp_obj_t)&mipidsi_display_get_height_obj); + +//| color_depth: int +//| """The color depth of the framebuffer.""" +static mp_obj_t mipidsi_display_get_color_depth(mp_obj_t self_in) { + mipidsi_display_obj_t *self = native_display(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_mipidsi_display_get_color_depth(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(mipidsi_display_get_color_depth_obj, mipidsi_display_get_color_depth); +MP_PROPERTY_GETTER(mipidsi_display_color_depth_obj, + (mp_obj_t)&mipidsi_display_get_color_depth_obj); + + +static const mp_rom_map_elem_t mipidsi_display_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&mipidsi_display_deinit_obj) }, + + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&mipidsi_display_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&mipidsi_display_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_color_depth), MP_ROM_PTR(&mipidsi_display_color_depth_obj) }, +}; +static MP_DEFINE_CONST_DICT(mipidsi_display_locals_dict, mipidsi_display_locals_dict_table); + +static void mipidsi_display_get_bufinfo(mp_obj_t self_in, mp_buffer_info_t *bufinfo) { + common_hal_mipidsi_display_get_buffer(self_in, bufinfo, 0); +} + +static float mipidsi_display_get_brightness_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_brightness(self_in); +} + +static bool mipidsi_display_set_brightness_proto(mp_obj_t self_in, mp_float_t value) { + common_hal_mipidsi_display_set_brightness(self_in, value); + return true; +} + +// These versions exist so that the prototype matches the protocol, +// avoiding a type cast that can hide errors +static void mipidsi_display_swapbuffers(mp_obj_t self_in, uint8_t *dirty_row_bitmap) { + (void)dirty_row_bitmap; + common_hal_mipidsi_display_refresh(self_in); +} + +static void mipidsi_display_deinit_proto(mp_obj_t self_in) { + common_hal_mipidsi_display_deinit(self_in); +} + +static int mipidsi_display_get_width_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_width(self_in); +} + +static int mipidsi_display_get_height_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_height(self_in); +} + +static int mipidsi_display_get_color_depth_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_color_depth(self_in); +} + +static bool mipidsi_display_get_grayscale_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_grayscale(self_in); +} + +static int mipidsi_display_get_bytes_per_cell_proto(mp_obj_t self_in) { + return 1; +} + +static int mipidsi_display_get_native_frames_per_second_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_native_frames_per_second(self_in); +} + +static bool mipidsi_display_get_pixels_in_byte_share_row_proto(mp_obj_t self_in) { + return true; +} + +static int mipidsi_display_get_row_stride_proto(mp_obj_t self_in) { + return common_hal_mipidsi_display_get_row_stride(self_in); +} + +static const framebuffer_p_t mipidsi_display_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuffer) + .get_bufinfo = mipidsi_display_get_bufinfo, + .set_brightness = mipidsi_display_set_brightness_proto, + .get_brightness = mipidsi_display_get_brightness_proto, + .get_width = mipidsi_display_get_width_proto, + .get_height = mipidsi_display_get_height_proto, + .get_color_depth = mipidsi_display_get_color_depth_proto, + .get_grayscale = mipidsi_display_get_grayscale_proto, + .get_row_stride = mipidsi_display_get_row_stride_proto, + .get_bytes_per_cell = mipidsi_display_get_bytes_per_cell_proto, + .get_native_frames_per_second = mipidsi_display_get_native_frames_per_second_proto, + .get_pixels_in_byte_share_row = mipidsi_display_get_pixels_in_byte_share_row_proto, + .swapbuffers = mipidsi_display_swapbuffers, + .deinit = mipidsi_display_deinit_proto, +}; + +MP_DEFINE_CONST_OBJ_TYPE( + mipidsi_display_type, + MP_QSTR_Display, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + locals_dict, &mipidsi_display_locals_dict, + make_new, mipidsi_display_make_new, + buffer, common_hal_mipidsi_display_get_buffer, + protocol, &mipidsi_display_proto + ); diff --git a/shared-bindings/mipidsi/Display.h b/shared-bindings/mipidsi/Display.h new file mode 100644 index 0000000000000..09cf130bf4a28 --- /dev/null +++ b/shared-bindings/mipidsi/Display.h @@ -0,0 +1,46 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "common-hal/mipidsi/Display.h" +#include "shared-bindings/mipidsi/Bus.h" +#include "common-hal/microcontroller/Pin.h" + +extern const mp_obj_type_t mipidsi_display_type; + +void common_hal_mipidsi_display_construct(mipidsi_display_obj_t *self, + mipidsi_bus_obj_t *bus, + const uint8_t *init_sequence, + size_t init_sequence_len, + mp_uint_t virtual_channel, + mp_uint_t width, + mp_uint_t height, + mp_int_t rotation, + mp_uint_t color_depth, + const mcu_pin_obj_t *backlight_pin, + mp_float_t brightness, + mp_uint_t native_frames_per_second, + bool backlight_on_high, + mp_uint_t hsync_pulse_width, + mp_uint_t hsync_back_porch, + mp_uint_t hsync_front_porch, + mp_uint_t vsync_pulse_width, + mp_uint_t vsync_back_porch, + mp_uint_t vsync_front_porch, + mp_uint_t pixel_clock_frequency); +void common_hal_mipidsi_display_deinit(mipidsi_display_obj_t *self); +bool common_hal_mipidsi_display_deinited(mipidsi_display_obj_t *self); +void common_hal_mipidsi_display_refresh(mipidsi_display_obj_t *self); +mp_float_t common_hal_mipidsi_display_get_brightness(mipidsi_display_obj_t *self); +bool common_hal_mipidsi_display_set_brightness(mipidsi_display_obj_t *self, mp_float_t brightness); +int common_hal_mipidsi_display_get_width(mipidsi_display_obj_t *self); +int common_hal_mipidsi_display_get_height(mipidsi_display_obj_t *self); +int common_hal_mipidsi_display_get_row_stride(mipidsi_display_obj_t *self); +int common_hal_mipidsi_display_get_color_depth(mipidsi_display_obj_t *self); +int common_hal_mipidsi_display_get_native_frames_per_second(mipidsi_display_obj_t *self); +bool common_hal_mipidsi_display_get_grayscale(mipidsi_display_obj_t *self); +mp_int_t common_hal_mipidsi_display_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags); diff --git a/shared-bindings/mipidsi/__init__.c b/shared-bindings/mipidsi/__init__.c new file mode 100644 index 0000000000000..0b6b856592918 --- /dev/null +++ b/shared-bindings/mipidsi/__init__.c @@ -0,0 +1,30 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/mipidsi/Bus.h" +#include "shared-bindings/mipidsi/Display.h" + +//| """Low-level routines for interacting with MIPI DSI""" + +static const mp_rom_map_elem_t mipidsi_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_mipidsi) }, + { MP_ROM_QSTR(MP_QSTR_Bus), MP_ROM_PTR(&mipidsi_bus_type) }, + { MP_ROM_QSTR(MP_QSTR_Display), MP_ROM_PTR(&mipidsi_display_type) }, +}; + +static MP_DEFINE_CONST_DICT(mipidsi_module_globals, mipidsi_module_globals_table); + +const mp_obj_module_t mipidsi_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&mipidsi_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_mipidsi, mipidsi_module); diff --git a/shared-bindings/mipidsi/__init__.h b/shared-bindings/mipidsi/__init__.h new file mode 100644 index 0000000000000..972a7c082fd7b --- /dev/null +++ b/shared-bindings/mipidsi/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-bindings/msgpack/ExtType.c b/shared-bindings/msgpack/ExtType.c index 7cee4b9b0d3f9..c69416f9773e7 100644 --- a/shared-bindings/msgpack/ExtType.c +++ b/shared-bindings/msgpack/ExtType.c @@ -16,8 +16,8 @@ //| """Constructor //| :param int code: type code in range 0~127. //| :param bytes data: representation.""" +//| static mp_obj_t mod_msgpack_exttype_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - mod_msgpack_extype_obj_t *self = mp_obj_malloc(mod_msgpack_extype_obj_t, &mod_msgpack_exttype_type); enum { ARG_code, ARG_data }; static const mp_arg_t allowed_args[] = { { MP_QSTR_code, MP_ARG_INT | MP_ARG_REQUIRED }, @@ -27,11 +27,12 @@ static mp_obj_t mod_msgpack_exttype_make_new(const mp_obj_type_t *type, size_t n mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); int code = mp_arg_validate_int_range(args[ARG_code].u_int, 0, 127, MP_QSTR_code); + mp_obj_t data = args[ARG_data].u_obj; + mod_msgpack_extype_obj_t *self = mp_obj_malloc(mod_msgpack_extype_obj_t, &mod_msgpack_exttype_type); self->code = code; - - mp_obj_t data = args[ARG_data].u_obj; self->data = data; + return MP_OBJ_FROM_PTR(self); } @@ -64,6 +65,7 @@ MP_PROPERTY_GETSET(mod_msgpack_exttype_code_obj, //| """Data.""" //| ... //| +//| static mp_obj_t mod_msgpack_exttype_get_data(mp_obj_t self_in) { mod_msgpack_extype_obj_t *self = MP_OBJ_TO_PTR(self_in); return self->data; diff --git a/shared-bindings/msgpack/__init__.c b/shared-bindings/msgpack/__init__.c index eaa1cfb98ba6c..a3e31f23ca6e8 100644 --- a/shared-bindings/msgpack/__init__.c +++ b/shared-bindings/msgpack/__init__.c @@ -65,12 +65,13 @@ //| //| """ //| +//| //| def pack( //| obj: object, //| stream: circuitpython_typing.ByteStream, //| *, -//| default: Union[Callable[[object], None], None] = None +//| default: Union[Callable[[object], None], None] = None, //| ) -> None: //| """Output object to stream in msgpack format. //| @@ -82,6 +83,7 @@ //| """ //| ... //| +//| static mp_obj_t mod_msgpack_pack(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_obj, ARG_buffer, ARG_default }; static const mp_arg_t allowed_args[] = { @@ -107,7 +109,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mod_msgpack_pack_obj, 0, mod_msgpack_pack); //| stream: circuitpython_typing.ByteStream, //| *, //| ext_hook: Union[Callable[[int, bytes], object], None] = None, -//| use_list: bool = True +//| use_list: bool = True, //| ) -> object: //| """Unpack and return one object from stream. //| @@ -120,6 +122,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mod_msgpack_pack_obj, 0, mod_msgpack_pack); //| """ //| ... //| +//| static mp_obj_t mod_msgpack_unpack(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_buffer, ARG_ext_hook, ARG_use_list }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c index 9f221ddd5ac11..3768b70c772eb 100644 --- a/shared-bindings/neopixel_write/__init__.c +++ b/shared-bindings/neopixel_write/__init__.c @@ -84,6 +84,7 @@ static void check_for_deinit(digitalio_digitalinout_obj_t *self) { //| //| """ //| +//| //| def neopixel_write(digitalinout: digitalio.DigitalInOut, buf: ReadableBuffer) -> None: //| """Write buf out on the given DigitalInOut. //| @@ -92,6 +93,7 @@ static void check_for_deinit(digitalio_digitalinout_obj_t *self) { //| """ //| ... //| +//| static mp_obj_t neopixel_write_neopixel_write_(mp_obj_t digitalinout_obj, mp_obj_t buf) { const digitalio_digitalinout_obj_t *digitalinout = mp_arg_validate_type(digitalinout_obj, &digitalio_digitalinout_type, MP_QSTR_digitalinout); @@ -108,8 +110,8 @@ static mp_obj_t neopixel_write_neopixel_write_(mp_obj_t digitalinout_obj, mp_obj static MP_DEFINE_CONST_FUN_OBJ_2(neopixel_write_neopixel_write_obj, neopixel_write_neopixel_write_); static const mp_rom_map_elem_t neopixel_write_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&neopixel_write_neopixel_write_obj }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write) }, + { MP_ROM_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&neopixel_write_neopixel_write_obj }, }; static MP_DEFINE_CONST_DICT(neopixel_write_module_globals, neopixel_write_module_globals_table); diff --git a/shared-bindings/nvm/ByteArray.c b/shared-bindings/nvm/ByteArray.c index 7549023247eca..b278300626737 100644 --- a/shared-bindings/nvm/ByteArray.c +++ b/shared-bindings/nvm/ByteArray.c @@ -26,14 +26,16 @@ //| def __init__(self) -> None: //| """Not currently dynamically supported. Access the sole instance through `microcontroller.nvm`.""" //| ... +//| //| def __bool__(self) -> bool: ... //| def __len__(self) -> int: //| """Return the length. This is used by (`len`)""" //| ... +//| static mp_obj_t nvm_bytearray_unary_op(mp_unary_op_t op, mp_obj_t self_in) { nvm_bytearray_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint16_t len = common_hal_nvm_bytearray_get_length(self); + uint32_t len = common_hal_nvm_bytearray_get_length(self); switch (op) { case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0); @@ -63,6 +65,7 @@ static MP_DEFINE_CONST_DICT(nvm_bytearray_locals_dict, nvm_bytearray_locals_dict //| """Set the value at the given index.""" //| ... //| +//| static mp_obj_t nvm_bytearray_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) { if (value == MP_OBJ_NULL) { // delete item diff --git a/shared-bindings/onewireio/OneWire.c b/shared-bindings/onewireio/OneWire.c index d2cb379ab4f84..2f69424cc234b 100644 --- a/shared-bindings/onewireio/OneWire.c +++ b/shared-bindings/onewireio/OneWire.c @@ -32,6 +32,7 @@ //| onewire.write_bit(False) //| print(onewire.read_bit())""" //| ... +//| static mp_obj_t onewireio_onewire_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pin }; static const mp_arg_t allowed_args[] = { @@ -42,14 +43,15 @@ static mp_obj_t onewireio_onewire_make_new(const mp_obj_type_t *type, size_t n_a const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); onewireio_onewire_obj_t *self = mp_obj_malloc(onewireio_onewire_obj_t, &onewireio_onewire_type); - common_hal_onewireio_onewire_construct(self, pin); + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Deinitialize the OneWire bus and release any hardware resources for reuse.""" //| ... +//| static mp_obj_t onewireio_onewire_deinit(mp_obj_t self_in) { onewireio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_onewireio_onewire_deinit(self); @@ -66,18 +68,15 @@ static void check_for_deinit(onewireio_onewire_obj_t *self) { //| def __enter__(self) -> OneWire: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t onewireio_onewire_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_onewireio_onewire_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(onewireio_onewire___exit___obj, 4, 4, onewireio_onewire_obj___exit__); +//| +// Provided by context manager helper. //| def reset(self) -> bool: //| """Reset the OneWire bus and read presence @@ -85,6 +84,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(onewireio_onewire___exit___obj, 4, 4, //| :returns: False when at least one device is present //| :rtype: bool""" //| ... +//| static mp_obj_t onewireio_onewire_obj_reset(mp_obj_t self_in) { onewireio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -99,6 +99,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(onewireio_onewire_reset_obj, onewireio_onewire_obj_res //| :returns: bit state read //| :rtype: bool""" //| ... +//| static mp_obj_t onewireio_onewire_obj_read_bit(mp_obj_t self_in) { onewireio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -111,6 +112,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(onewireio_onewire_read_bit_obj, onewireio_onewire_obj_ //| """Write out a bit based on value.""" //| ... //| +//| static mp_obj_t onewireio_onewire_obj_write_bit(mp_obj_t self_in, mp_obj_t bool_obj) { onewireio_onewire_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -124,7 +126,7 @@ static const mp_rom_map_elem_t onewireio_onewire_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&onewireio_onewire_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&onewireio_onewire___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&onewireio_onewire_reset_obj) }, { MP_ROM_QSTR(MP_QSTR_read_bit), MP_ROM_PTR(&onewireio_onewire_read_bit_obj) }, { MP_ROM_QSTR(MP_QSTR_write_bit), MP_ROM_PTR(&onewireio_onewire_write_bit_obj) }, diff --git a/shared-bindings/onewireio/__init__.c b/shared-bindings/onewireio/__init__.c index bce56326b1ad9..9af86ae821175 100644 --- a/shared-bindings/onewireio/__init__.c +++ b/shared-bindings/onewireio/__init__.c @@ -17,7 +17,7 @@ //| """Low-level bit primitives for Maxim (formerly Dallas Semi) one-wire protocol. //| -//| Protocol definition is here: https://www.analog.com/en/technical-articles/1wire-communication-through-software.html""" +//| Protocol definition is here: https://www.analog.com/en/technical-articles/1wire-communication-through-software.html""" static const mp_rom_map_elem_t onewireio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewireio) }, diff --git a/shared-bindings/os/__init__.c b/shared-bindings/os/__init__.c index 37dea4290759e..bbf5a5025c1bf 100644 --- a/shared-bindings/os/__init__.c +++ b/shared-bindings/os/__init__.c @@ -26,12 +26,14 @@ //| //| import typing //| +//| //| def uname() -> _Uname: //| """Returns a named tuple of operating specific and CircuitPython port //| specific information.""" //| ... //| +//| //| class _Uname(typing.NamedTuple): //| """The type of values that :py:func:`.uname()` returns""" //| @@ -41,8 +43,31 @@ //| version: str //| machine: str //| +//| +static const qstr os_uname_info_fields[] = { + MP_QSTR_sysname, MP_QSTR_nodename, + MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine +}; +static const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_HW_MCU_NAME); +static const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_HW_MCU_NAME); +static const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING); +static const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE); +static const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME); + + +static MP_DEFINE_ATTRTUPLE( + os_uname_info_obj, + os_uname_info_fields, + 5, + (mp_obj_t)&os_uname_info_sysname_obj, + (mp_obj_t)&os_uname_info_nodename_obj, + (mp_obj_t)&os_uname_info_release_obj, + (mp_obj_t)&os_uname_info_version_obj, + (mp_obj_t)&os_uname_info_machine_obj + ); + static mp_obj_t os_uname(void) { - return common_hal_os_uname(); + return MP_OBJ_FROM_PTR(&os_uname_info_obj); } static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); @@ -50,6 +75,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname); //| """Change current directory.""" //| ... //| +//| static mp_obj_t os_chdir(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); common_hal_os_chdir(path); @@ -61,17 +87,27 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir); //| """Get the current directory.""" //| ... //| +//| static mp_obj_t os_getcwd(void) { return common_hal_os_getcwd(); } MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); //| def getenv(key: str, default: Optional[str] = None) -> Optional[str]: -//| """Get the environment variable value for the given key or return ``default``. +//| """Get the environment variable value for the given ``key`` from the +//| ``/settings.toml`` file. +//| If ``key`` is not present or the value is ill-formed, return the ``default`` value. +//| The value is returned as a string even if it can be parsed as an integer or boolean. +//| No errors are raised if the value is not a valid TOML value; instead the original +//| string is returned, or ``default`` if no value can be retrieved at all. //| -//| This may load values from disk so cache the result instead of calling this often. +//| If you want to retrieve the value as a ``str``, ``bool``, or ``int``, use `supervisor.get_setting()`. //| -//| On boards that do not support ``settings.toml`` reading in the core, this function will raise NotImplementedError. +//| The ``settings.toml`` file is re-scanned on every call, +//| so cache the result instead of calling `getenv()` frequently. +//| +//| On boards that do not support ``settings.toml`` reading in the core, +//| this function will raise NotImplementedError. //| //| .. raw:: html //| @@ -89,8 +125,9 @@ MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd); //| """ //| ... //| +//| static mp_obj_t os_getenv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - #if CIRCUITPY_OS_GETENV + #if CIRCUITPY_SETTINGS_TOML enum { ARG_key, ARG_default }; static const mp_arg_t allowed_args[] = { { MP_QSTR_key, MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -110,6 +147,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(os_getenv_obj, 1, os_getenv); //| """With no argument, list the current directory. Otherwise list the given directory.""" //| ... //| +//| static mp_obj_t os_listdir(size_t n_args, const mp_obj_t *args) { const char *path; if (n_args == 1) { @@ -125,6 +163,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir); //| """Create a new directory.""" //| ... //| +//| static mp_obj_t os_mkdir(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); common_hal_os_mkdir(path); @@ -136,6 +175,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir); //| """Remove a file.""" //| ... //| +//| static mp_obj_t os_remove(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); common_hal_os_remove(path); @@ -147,6 +187,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove); //| """Remove a directory.""" //| ... //| +//| static mp_obj_t os_rename(mp_obj_t old_path_in, mp_obj_t new_path_in) { const char *old_path = mp_obj_str_get_str(old_path_in); const char *new_path = mp_obj_str_get_str(new_path_in); @@ -159,6 +200,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename); //| """Rename a file.""" //| ... //| +//| static mp_obj_t os_rmdir(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); common_hal_os_rmdir(path); @@ -189,6 +231,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir); //| which is the number of seconds corresponding to 1999-12-31.""" //| ... //| +//| static mp_obj_t os_stat(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); return common_hal_os_stat(path); @@ -216,6 +259,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat); //| in a port-specific implementation.""" //| ... //| +//| static mp_obj_t os_statvfs(mp_obj_t path_in) { const char *path = mp_obj_str_get_str(path_in); return common_hal_os_statvfs(path); @@ -226,6 +270,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_statvfs_obj, os_statvfs); //| """Sync all filesystems.""" //| ... //| +//| static mp_obj_t os_sync(void) { for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { // this assumes that vfs->obj is fs_user_mount_t with block device functions @@ -243,6 +288,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync); //| """ //| ... //| +//| static mp_obj_t os_urandom(mp_obj_t size_in) { mp_int_t size = mp_obj_get_int(size_in); mp_obj_str_t *result = MP_OBJ_TO_PTR(mp_obj_new_bytes_of_zeros(size)); @@ -257,6 +303,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); //| """Change the timestamp of a file.""" //| ... //| +//| static mp_obj_t os_utime(mp_obj_t path_in, mp_obj_t times_in) { const char *path = mp_obj_str_get_str(path_in); common_hal_os_utime(path, times_in); diff --git a/shared-bindings/os/__init__.h b/shared-bindings/os/__init__.h index f273708cf4ed9..3729f43d5b6b1 100644 --- a/shared-bindings/os/__init__.h +++ b/shared-bindings/os/__init__.h @@ -10,10 +10,8 @@ #include #include "py/objtuple.h" +#include "shared-module/os/__init__.h" -extern const mp_rom_obj_tuple_t common_hal_os_uname_info_obj; - -mp_obj_t common_hal_os_uname(void); void common_hal_os_chdir(const char *path); mp_obj_t common_hal_os_getcwd(void); mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_); diff --git a/shared-bindings/paralleldisplaybus/ParallelBus.c b/shared-bindings/paralleldisplaybus/ParallelBus.c index 0a674920a0c38..dfe363bdcb797 100644 --- a/shared-bindings/paralleldisplaybus/ParallelBus.c +++ b/shared-bindings/paralleldisplaybus/ParallelBus.c @@ -18,7 +18,11 @@ //| class ParallelBus: //| """Manage updating a display over 8-bit parallel bus in the background while Python code runs. This //| protocol may be referred to as 8080-I Series Parallel Interface in datasheets. It doesn't handle -//| display initialization.""" +//| display initialization. +//| +//| .. seealso:: See `busdisplay.BusDisplay` and `epaperdisplay.EPaperDisplay` +//| for how to initialize a display, given a `ParallelBus`. +//| """ //| //| def __init__( //| self, @@ -49,6 +53,7 @@ //| :param microcontroller.Pin reset: Reset pin, optional //| :param int frequency: The communication frequency in Hz for the display on the bus""" //| ... +//| static mp_obj_t paralleldisplaybus_parallelbus_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_data0, ARG_data_pins, ARG_command, ARG_chip_select, ARG_write, ARG_read, ARG_reset, ARG_frequency }; static const mp_arg_t allowed_args[] = { @@ -96,6 +101,7 @@ static mp_obj_t paralleldisplaybus_parallelbus_make_new(const mp_obj_type_t *typ //| """Performs a hardware reset via the reset pin. Raises an exception if called when no reset pin //| is available.""" //| ... +//| static mp_obj_t paralleldisplaybus_parallelbus_obj_reset(mp_obj_t self_in) { paralleldisplaybus_parallelbus_obj_t *self = self_in; @@ -112,6 +118,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(paralleldisplaybus_parallelbus_reset_obj, paralleldisp //| vertical scroll, set via ``send`` may or may not be reset once the code is done.""" //| ... //| +//| static mp_obj_t paralleldisplaybus_parallelbus_obj_send(mp_obj_t self, mp_obj_t command_obj, mp_obj_t data_obj) { mp_int_t command_int = mp_arg_validate_int_range(mp_obj_get_int(command_obj), 0, 255, MP_QSTR_command); diff --git a/shared-bindings/paralleldisplaybus/__init__.c b/shared-bindings/paralleldisplaybus/__init__.c index 24d968c9e3111..19a381570bada 100644 --- a/shared-bindings/paralleldisplaybus/__init__.c +++ b/shared-bindings/paralleldisplaybus/__init__.c @@ -29,6 +29,3 @@ const mp_obj_module_t paralleldisplaybus_module = { }; MP_REGISTER_MODULE(MP_QSTR_paralleldisplaybus, paralleldisplaybus_module); - -// Remove in CircuitPython 10 -MP_REGISTER_MODULE(MP_QSTR_paralleldisplay, paralleldisplaybus_module); diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c index f92d5f0dd88cf..90e6b0b604561 100644 --- a/shared-bindings/ps2io/Ps2.c +++ b/shared-bindings/ps2io/Ps2.c @@ -44,6 +44,7 @@ //| print(kbd.sendcmd(0xed)) //| print(kbd.sendcmd(0x01))""" //| ... +//| static mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_data_pin, ARG_clock_pin }; static const mp_arg_t allowed_args[] = { @@ -57,7 +58,6 @@ static mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, siz const mcu_pin_obj_t *data_pin = validate_obj_is_free_pin(args[ARG_data_pin].u_obj, MP_QSTR_data_pin); ps2io_ps2_obj_t *self = mp_obj_malloc(ps2io_ps2_obj_t, &ps2io_ps2_type); - common_hal_ps2io_ps2_construct(self, data_pin, clock_pin); return MP_OBJ_FROM_PTR(self); @@ -66,6 +66,7 @@ static mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, siz //| def deinit(self) -> None: //| """Deinitialises the Ps2 and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t ps2io_ps2_deinit(mp_obj_t self_in) { ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_ps2io_ps2_deinit(self); @@ -82,24 +83,21 @@ static void check_for_deinit(ps2io_ps2_obj_t *self) { //| def __enter__(self) -> Ps2: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t ps2io_ps2_obj___exit__(size_t n_args, const mp_obj_t *args) { - mp_check_self(mp_obj_is_type(args[0], &ps2io_ps2_type)); - ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(args[0]); - common_hal_ps2io_ps2_deinit(self); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ps2io_ps2___exit___obj, 4, 4, ps2io_ps2_obj___exit__); +//| +// Provided by context manager helper. //| def popleft(self) -> int: //| """Removes and returns the oldest received byte. When buffer //| is empty, raises an IndexError exception.""" //| ... +//| static mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) { ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -124,6 +122,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_popleft_obj, ps2io_ps2_obj_popleft); //| //| :param int byte: byte value of the command""" //| ... +//| static mp_obj_t ps2io_ps2_obj_sendcmd(mp_obj_t self_in, mp_obj_t ob) { ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -165,6 +164,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(ps2io_ps2_sendcmd_obj, ps2io_ps2_obj_sendcmd); //| //| 0x2000: device didn't send a response byte in time""" //| ... +//| static mp_obj_t ps2io_ps2_obj_clear_errors(mp_obj_t self_in) { ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -179,6 +179,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_clear_errors_obj, ps2io_ps2_obj_clear_errors //| to :py:func:`popleft()`.""" //| ... //| +//| static mp_obj_t ps2_unary_op(mp_unary_op_t op, mp_obj_t self_in) { ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -197,7 +198,7 @@ static const mp_rom_map_elem_t ps2io_ps2_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&ps2io_ps2_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&ps2io_ps2___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&ps2io_ps2_popleft_obj) }, { MP_ROM_QSTR(MP_QSTR_sendcmd), MP_ROM_PTR(&ps2io_ps2_sendcmd_obj) }, { MP_ROM_QSTR(MP_QSTR_clear_errors), MP_ROM_PTR(&ps2io_ps2_clear_errors_obj) }, diff --git a/shared-bindings/pulseio/PulseIn.c b/shared-bindings/pulseio/PulseIn.c index 38b63873c70ff..830f7b7c62ce3 100644 --- a/shared-bindings/pulseio/PulseIn.c +++ b/shared-bindings/pulseio/PulseIn.c @@ -56,6 +56,7 @@ //| # Resume with an 80 microsecond active pulse //| pulses.resume(80)""" //| ... +//| static mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pin, ARG_maxlen, ARG_idle_state }; static const mp_arg_t allowed_args[] = { @@ -67,9 +68,7 @@ static mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_arg mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); - pulseio_pulsein_obj_t *self = m_new_obj_with_finaliser(pulseio_pulsein_obj_t); - self->base.type = &pulseio_pulsein_type; - + pulseio_pulsein_obj_t *self = mp_obj_malloc_with_finaliser(pulseio_pulsein_obj_t, &pulseio_pulsein_type); common_hal_pulseio_pulsein_construct(self, pin, args[ARG_maxlen].u_int, args[ARG_idle_state].u_bool); @@ -79,6 +78,7 @@ static mp_obj_t pulseio_pulsein_make_new(const mp_obj_type_t *type, size_t n_arg //| def deinit(self) -> None: //| """Deinitialises the PulseIn and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t pulseio_pulsein_deinit(mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_pulseio_pulsein_deinit(self); @@ -95,22 +95,20 @@ static void check_for_deinit(pulseio_pulsein_obj_t *self) { //| def __enter__(self) -> PulseIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t pulseio_pulsein_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_pulseio_pulsein_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulsein___exit___obj, 4, 4, pulseio_pulsein_obj___exit__); +//| +// Provided by context manager helper. //| def pause(self) -> None: //| """Pause pulse capture""" //| ... +//| static mp_obj_t pulseio_pulsein_obj_pause(mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -130,6 +128,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_pause_obj, pulseio_pulsein_obj_pause); //| //| :param int trigger_duration: trigger pulse duration in microseconds""" //| ... +//| static mp_obj_t pulseio_pulsein_obj_resume(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_trigger_duration }; static const mp_arg_t allowed_args[] = { @@ -149,6 +148,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pulseio_pulsein_resume_obj, 1, pulseio_pulsein_obj_re //| def clear(self) -> None: //| """Clears all captured pulses""" //| ... +//| static mp_obj_t pulseio_pulsein_obj_clear(mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -161,6 +161,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulsein_clear_obj, pulseio_pulsein_obj_clear); //| def popleft(self) -> int: //| """Removes and returns the oldest read pulse duration in microseconds.""" //| ... +//| static mp_obj_t pulseio_pulsein_obj_popleft(mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -186,6 +187,7 @@ MP_PROPERTY_GETTER(pulseio_pulsein_maxlen_obj, //| paused: bool //| """True when pulse capture is paused as a result of :py:func:`pause` or an error during capture //| such as a signal that is too fast.""" +//| static mp_obj_t pulseio_pulsein_obj_get_paused(mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -206,6 +208,7 @@ MP_PROPERTY_GETTER(pulseio_pulsein_paused_obj, //| pulses = pulseio.PulseIn(pin) //| print(len(pulses))""" //| ... +//| static mp_obj_t pulsein_unary_op(mp_unary_op_t op, mp_obj_t self_in) { pulseio_pulsein_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -229,6 +232,7 @@ static mp_obj_t pulsein_unary_op(mp_unary_op_t op, mp_obj_t self_in) { //| print(pulses[0])""" //| ... //| +//| static mp_obj_t pulsein_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value) { if (value == mp_const_none) { // delete item @@ -257,7 +261,7 @@ static const mp_rom_map_elem_t pulseio_pulsein_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pulseio_pulsein_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pulseio_pulsein_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pulseio_pulsein___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&pulseio_pulsein_pause_obj) }, { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&pulseio_pulsein_resume_obj) }, { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&pulseio_pulsein_clear_obj) }, diff --git a/shared-bindings/pulseio/PulseOut.c b/shared-bindings/pulseio/PulseOut.c index 663eb1dfafe5b..58c98b8e2cce8 100644 --- a/shared-bindings/pulseio/PulseOut.c +++ b/shared-bindings/pulseio/PulseOut.c @@ -44,6 +44,7 @@ //| pulses[0] = 200 //| pulse.send(pulses)""" //| ... +//| static mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { #if CIRCUITPY_PULSEIO_PULSEOUT enum { ARG_pin, ARG_frequency, ARG_duty_cycle}; @@ -59,9 +60,9 @@ static mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_ar mp_int_t frequency = args[ARG_frequency].u_int; mp_int_t duty_cycle = args[ARG_duty_cycle].u_int; - pulseio_pulseout_obj_t *self = m_new_obj_with_finaliser(pulseio_pulseout_obj_t); - self->base.type = &pulseio_pulseout_type; + pulseio_pulseout_obj_t *self = mp_obj_malloc_with_finaliser(pulseio_pulseout_obj_t, &pulseio_pulseout_type); common_hal_pulseio_pulseout_construct(self, pin, frequency, duty_cycle); + return MP_OBJ_FROM_PTR(self); #else mp_raise_NotImplementedError(NULL); @@ -72,6 +73,7 @@ static mp_obj_t pulseio_pulseout_make_new(const mp_obj_type_t *type, size_t n_ar //| def deinit(self) -> None: //| """Deinitialises the PulseOut and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t pulseio_pulseout_deinit(mp_obj_t self_in) { pulseio_pulseout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_pulseio_pulseout_deinit(self); @@ -82,18 +84,15 @@ static MP_DEFINE_CONST_FUN_OBJ_1(pulseio_pulseout_deinit_obj, pulseio_pulseout_d //| def __enter__(self) -> PulseOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t pulseio_pulseout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_pulseio_pulseout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulseout___exit___obj, 4, 4, pulseio_pulseout_obj___exit__); +//| +// Provided by context manager helper. //| def send(self, pulses: ReadableBuffer) -> None: //| """Pulse alternating on and off durations in microseconds starting with on. @@ -106,6 +105,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pulseio_pulseout___exit___obj, 4, 4, //| :param array.array pulses: pulse durations in microseconds""" //| ... //| +//| static mp_obj_t pulseio_pulseout_obj_send(mp_obj_t self_in, mp_obj_t pulses) { pulseio_pulseout_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_pulseio_pulseout_deinited(self)) { @@ -129,7 +129,7 @@ static const mp_rom_map_elem_t pulseio_pulseout_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pulseio_pulseout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pulseio_pulseout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pulseio_pulseout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pulseio_pulseout_send_obj) }, #endif // CIRCUITPY_PULSEIO_PULSEOUT }; diff --git a/shared-bindings/pwmio/PWMOut.c b/shared-bindings/pwmio/PWMOut.c index e312d4d8facdb..97dbd2079f72b 100644 --- a/shared-bindings/pwmio/PWMOut.c +++ b/shared-bindings/pwmio/PWMOut.c @@ -70,7 +70,7 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { //| *, //| duty_cycle: int = 0, //| frequency: int = 500, -//| variable_frequency: bool = False +//| variable_frequency: bool = False, //| ) -> None: //| """Create a PWM object associated with the given pin. This allows you to //| write PWM signals out on the given pin. Frequency is fixed after init @@ -131,6 +131,7 @@ void common_hal_pwmio_pwmout_raise_error(pwmout_result_t result) { //| //| """ //| ... +//| static mp_obj_t pwmio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { enum { ARG_pin, ARG_duty_cycle, ARG_frequency, ARG_variable_frequency }; static const mp_arg_t allowed_args[] = { @@ -149,8 +150,7 @@ static mp_obj_t pwmio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, bool variable_frequency = parsed_args[ARG_variable_frequency].u_bool; // create PWM object from the given pin - pwmio_pwmout_obj_t *self = m_new_obj_with_finaliser(pwmio_pwmout_obj_t); - self->base.type = &pwmio_pwmout_type; + pwmio_pwmout_obj_t *self = mp_obj_malloc_with_finaliser(pwmio_pwmout_obj_t, &pwmio_pwmout_type); pwmout_result_t result = common_hal_pwmio_pwmout_construct(self, pin, duty_cycle, frequency, variable_frequency); common_hal_pwmio_pwmout_raise_error(result); @@ -160,6 +160,7 @@ static mp_obj_t pwmio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, //| def deinit(self) -> None: //| """Deinitialises the PWMOut and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t pwmio_pwmout_deinit(mp_obj_t self_in) { pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_pwmio_pwmout_deinit(self); @@ -176,18 +177,15 @@ static void check_for_deinit(pwmio_pwmout_obj_t *self) { //| def __enter__(self) -> PWMOut: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t pwmio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_pwmio_pwmout_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pwmio_pwmout___exit___obj, 4, 4, pwmio_pwmout_obj___exit__); +//| +// Provided by context manager helper. //| duty_cycle: int //| """16 bit value that dictates how much of one cycle is high (1) versus low @@ -232,6 +230,7 @@ MP_PROPERTY_GETSET(pwmio_pwmout_duty_cycle_obj, //| to manually re-set the duty cycle. However, an output glitch may occur during the adjustment. //| """ //| +//| static mp_obj_t pwmio_pwmout_obj_get_frequency(mp_obj_t self_in) { pwmio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -263,7 +262,7 @@ static const mp_rom_map_elem_t pwmio_pwmout_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pwmio_pwmout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pwmio_pwmout_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pwmio_pwmout___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pwmio_pwmout_duty_cycle_obj) }, diff --git a/shared-bindings/qrio/PixelPolicy.c b/shared-bindings/qrio/PixelPolicy.c index b8a422c40fda3..6acce4984a12c 100644 --- a/shared-bindings/qrio/PixelPolicy.c +++ b/shared-bindings/qrio/PixelPolicy.c @@ -25,6 +25,7 @@ //| RGB565: PixelPolicy //| """The input buffer to `QRDecoder.decode` consists of RGB565 values in native order. The green component is used.""" //| +//| MAKE_ENUM_VALUE(qrio_pixel_policy_type, qrio_pixel_policy, EVERY_BYTE, QRIO_EVERY_BYTE); MAKE_ENUM_VALUE(qrio_pixel_policy_type, qrio_pixel_policy, RGB565, QRIO_RGB565); diff --git a/shared-bindings/qrio/QRDecoder.c b/shared-bindings/qrio/QRDecoder.c index d9a7b31708dd9..e8977bc1efee3 100644 --- a/shared-bindings/qrio/QRDecoder.c +++ b/shared-bindings/qrio/QRDecoder.c @@ -20,6 +20,7 @@ //| :param int height: The pixel height of the image to decode //| """ //| ... +//| static mp_obj_t qrio_qrdecoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args_in) { enum { ARG_width, ARG_height }; @@ -33,7 +34,7 @@ static mp_obj_t qrio_qrdecoder_make_new(const mp_obj_type_t *type, size_t n_args qrio_qrdecoder_obj_t *self = mp_obj_malloc(qrio_qrdecoder_obj_t, &qrio_qrdecoder_type_obj); shared_module_qrio_qrdecoder_construct(self, args[ARG_width].u_int, args[ARG_height].u_int); - return self; + return MP_OBJ_FROM_PTR(self); } @@ -53,6 +54,7 @@ static void verify_buffer_size(qrio_qrdecoder_obj_t *self, mp_obj_t *buffer, siz //| self, buffer: ReadableBuffer, pixel_policy: PixelPolicy = PixelPolicy.EVERY_BYTE //| ) -> List[QRInfo]: //| """Decode zero or more QR codes from the given image. The size of the buffer must be at least ``length``×``width`` bytes for `EVERY_BYTE`, and 2×``length``×``width`` bytes for `EVEN_BYTES` or `ODD_BYTES`.""" +//| static mp_obj_t qrio_qrdecoder_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -78,6 +80,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(qrio_qrdecoder_decode_obj, 1, qrio_qrdecoder_decode); //| self, buffer: ReadableBuffer, pixel_policy: PixelPolicy = PixelPolicy.EVERY_BYTE //| ) -> List[QRPosition]: //| """Find all visible QR codes from the given image. The size of the buffer must be at least ``length``×``width`` bytes for `EVERY_BYTE`, and 2×``length``×``width`` bytes for `EVEN_BYTES` or `ODD_BYTES`.""" +//| static mp_obj_t qrio_qrdecoder_find(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -122,6 +125,7 @@ MP_PROPERTY_GETSET(qrio_qrdecoder_width_obj, //| height: int //| """The height of image the decoder expects""" //| +//| static mp_obj_t qrio_qrdecoder_get_height(mp_obj_t self_in) { qrio_qrdecoder_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(shared_module_qrio_qrdecoder_get_height(self)); diff --git a/shared-bindings/qrio/QRInfo.c b/shared-bindings/qrio/QRInfo.c index 3f63c21e3cee5..351ee32210583 100644 --- a/shared-bindings/qrio/QRInfo.c +++ b/shared-bindings/qrio/QRInfo.c @@ -18,6 +18,7 @@ //| data_type: Union[str, int] //| """The encoding of the payload as a string (if a standard encoding) or int (if not standard)""" //| +//| const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_QRInfo), @@ -58,6 +59,7 @@ const mp_obj_namedtuple_type_t qrio_qrinfo_type_obj = { //| size: int //| """The number of bits the code contains""" //| +//| const mp_obj_namedtuple_type_t qrio_qrposition_type_obj = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS(MP_QSTR_QRPosition), diff --git a/shared-bindings/qspibus/QSPIBus.c b/shared-bindings/qspibus/QSPIBus.c new file mode 100644 index 0000000000000..24c3089213fec --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.c @@ -0,0 +1,199 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/qspibus/QSPIBus.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "shared-module/displayio/__init__.h" + +#include "py/binary.h" +#include "py/obj.h" +#include "py/runtime.h" + +static void check_for_deinit(qspibus_qspibus_obj_t *self) { + if (common_hal_qspibus_qspibus_deinited(self)) { + raise_deinited_error(); + } +} + +//| class QSPIBus: +//| """QSPI bus for quad-SPI displays.""" +//| +//| def __init__( +//| self, +//| *, +//| clock: microcontroller.Pin, +//| data0: microcontroller.Pin, +//| data1: microcontroller.Pin, +//| data2: microcontroller.Pin, +//| data3: microcontroller.Pin, +//| cs: microcontroller.Pin, +//| dcx: Optional[microcontroller.Pin] = None, +//| reset: Optional[microcontroller.Pin] = None, +//| frequency: int = 80_000_000, +//| ) -> None: +//| """Create a QSPIBus object for quad-SPI display communication. +//| +//| :param ~microcontroller.Pin clock: QSPI clock pin +//| :param ~microcontroller.Pin data0: QSPI data line 0 +//| :param ~microcontroller.Pin data1: QSPI data line 1 +//| :param ~microcontroller.Pin data2: QSPI data line 2 +//| :param ~microcontroller.Pin data3: QSPI data line 3 +//| :param ~microcontroller.Pin cs: Chip select pin +//| :param ~microcontroller.Pin dcx: Optional data/command select pin. +//| Reserved for future hardware paths. Current ESP32-S3 implementation +//| uses encoded QSPI command words and does not require explicit DCX. +//| :param ~microcontroller.Pin reset: Optional reset pin +//| :param int frequency: Bus frequency in Hz (1-80MHz) +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) { + + enum { ARG_clock, ARG_data0, ARG_data1, ARG_data2, ARG_data3, ARG_cs, ARG_dcx, ARG_reset, ARG_frequency }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data0, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data1, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data2, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_data3, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_dcx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_reset, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_frequency, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 80000000} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *clock = validate_obj_is_free_pin(args[ARG_clock].u_obj, MP_QSTR_clock); + const mcu_pin_obj_t *data0 = validate_obj_is_free_pin(args[ARG_data0].u_obj, MP_QSTR_data0); + const mcu_pin_obj_t *data1 = validate_obj_is_free_pin(args[ARG_data1].u_obj, MP_QSTR_data1); + const mcu_pin_obj_t *data2 = validate_obj_is_free_pin(args[ARG_data2].u_obj, MP_QSTR_data2); + const mcu_pin_obj_t *data3 = validate_obj_is_free_pin(args[ARG_data3].u_obj, MP_QSTR_data3); + const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); + const mcu_pin_obj_t *dcx = validate_obj_is_free_pin_or_none(args[ARG_dcx].u_obj, MP_QSTR_dcx); + const mcu_pin_obj_t *reset = validate_obj_is_free_pin_or_none(args[ARG_reset].u_obj, MP_QSTR_reset); + + uint32_t frequency = (uint32_t)mp_arg_validate_int_range(args[ARG_frequency].u_int, 1, 80000000, MP_QSTR_frequency); + + qspibus_qspibus_obj_t *self = &allocate_display_bus_or_raise()->qspi_bus; + self->base.type = &qspibus_qspibus_type; + common_hal_qspibus_qspibus_construct(self, clock, data0, data1, data2, data3, cs, dcx, reset, frequency); + + return MP_OBJ_FROM_PTR(self); +} + +//| def reset(self) -> None: +//| """Perform a hardware reset using the reset pin. +//| +//| :raises RuntimeError: if no reset pin was provided at construction. +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_obj_reset(mp_obj_t self_in) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + if (!common_hal_qspibus_qspibus_reset(MP_OBJ_FROM_PTR(self))) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("No %q pin"), MP_QSTR_reset); + } + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(qspibus_qspibus_reset_obj, qspibus_qspibus_obj_reset); + +//| def send( +//| self, command: int, data: ReadableBuffer, *, toggle_every_byte: bool = False +//| ) -> None: +//| """Sends the given command value followed by the full set of data. Display state, such as +//| vertical scroll, set via ``send`` may or may not be reset once the code is done.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_command, ARG_data }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_command, MP_ARG_INT | MP_ARG_REQUIRED }, + { MP_QSTR_data, MP_ARG_OBJ | MP_ARG_REQUIRED }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(args[ARG_command].u_int, 0, 255, MP_QSTR_command); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_data].u_obj, &bufinfo, MP_BUFFER_READ); + + // Flush any pending command from a prior write_command() call. + // begin_transaction() returns false while has_pending_command is set, + // so entering the wait loop without flushing would spin forever. + if (self->has_pending_command) { + common_hal_qspibus_qspibus_write_data(self, NULL, 0); + } + + // Wait for display bus to be available, then acquire transaction. + while (!common_hal_qspibus_qspibus_begin_transaction(MP_OBJ_FROM_PTR(self))) { + RUN_BACKGROUND_TASKS; + } + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_COMMAND, CHIP_SELECT_UNTOUCHED, &command, 1); + common_hal_qspibus_qspibus_send(MP_OBJ_FROM_PTR(self), DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, ((uint8_t *)bufinfo.buf), bufinfo.len); + common_hal_qspibus_qspibus_end_transaction(MP_OBJ_FROM_PTR(self)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(qspibus_qspibus_send_obj, 1, qspibus_qspibus_send); + +//| def write_command(self, command: int) -> None: +//| """Stage a command byte for subsequent :py:meth:`write_data`. +//| +//| If a previously staged command had no data, it is sent as +//| a command-only transaction before staging the new one. +//| """ +//| ... +//| +static mp_obj_t qspibus_qspibus_write_command(mp_obj_t self_in, mp_obj_t command_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + uint8_t command = (uint8_t)mp_arg_validate_int_range(mp_obj_get_int(command_obj), 0, 255, MP_QSTR_command); + common_hal_qspibus_qspibus_write_command(self, command); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_command_obj, qspibus_qspibus_write_command); + +//| def write_data(self, data: ReadableBuffer) -> None: +//| """Send payload bytes for the most recently staged command.""" +//| ... +//| +static mp_obj_t qspibus_qspibus_write_data(mp_obj_t self_in, mp_obj_t data_obj) { + qspibus_qspibus_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); + common_hal_qspibus_qspibus_write_data(self, (const uint8_t *)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(qspibus_qspibus_write_data_obj, qspibus_qspibus_write_data); + +static const mp_rom_map_elem_t qspibus_qspibus_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&qspibus_qspibus_reset_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&qspibus_qspibus_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_command), MP_ROM_PTR(&qspibus_qspibus_write_command_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_data), MP_ROM_PTR(&qspibus_qspibus_write_data_obj) }, +}; +static MP_DEFINE_CONST_DICT(qspibus_qspibus_locals_dict, qspibus_qspibus_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + qspibus_qspibus_type, + MP_QSTR_QSPIBus, + MP_TYPE_FLAG_NONE, + make_new, qspibus_qspibus_make_new, + locals_dict, &qspibus_qspibus_locals_dict + ); diff --git a/shared-bindings/qspibus/QSPIBus.h b/shared-bindings/qspibus/QSPIBus.h new file mode 100644 index 0000000000000..140b639279dc0 --- /dev/null +++ b/shared-bindings/qspibus/QSPIBus.h @@ -0,0 +1,53 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" + +#include "shared-bindings/displayio/__init__.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/qspibus/QSPIBus.h" + +extern const mp_obj_type_t qspibus_qspibus_type; + +void common_hal_qspibus_qspibus_construct( + qspibus_qspibus_obj_t *self, + const mcu_pin_obj_t *clock, + const mcu_pin_obj_t *data0, + const mcu_pin_obj_t *data1, + const mcu_pin_obj_t *data2, + const mcu_pin_obj_t *data3, + const mcu_pin_obj_t *cs, + const mcu_pin_obj_t *dcx, + const mcu_pin_obj_t *reset, + uint32_t frequency); + +void common_hal_qspibus_qspibus_deinit(qspibus_qspibus_obj_t *self); +bool common_hal_qspibus_qspibus_deinited(qspibus_qspibus_obj_t *self); + +void common_hal_qspibus_qspibus_write_command( + qspibus_qspibus_obj_t *self, + uint8_t command); +void common_hal_qspibus_qspibus_write_data( + qspibus_qspibus_obj_t *self, + const uint8_t *data, + size_t len); + +bool common_hal_qspibus_qspibus_reset(mp_obj_t obj); +bool common_hal_qspibus_qspibus_bus_free(mp_obj_t obj); +bool common_hal_qspibus_qspibus_begin_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_send( + mp_obj_t obj, + display_byte_type_t data_type, + display_chip_select_behavior_t chip_select, + const uint8_t *data, + uint32_t data_length); +void common_hal_qspibus_qspibus_end_transaction(mp_obj_t obj); +void common_hal_qspibus_qspibus_flush(mp_obj_t obj); +void common_hal_qspibus_qspibus_collect_ptrs(mp_obj_t obj); diff --git a/shared-bindings/qspibus/__init__.c b/shared-bindings/qspibus/__init__.c new file mode 100644 index 0000000000000..0281c41c80420 --- /dev/null +++ b/shared-bindings/qspibus/__init__.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/qspibus/__init__.h" +#include "shared-bindings/qspibus/QSPIBus.h" + +//| """QSPI bus protocol for quad-SPI displays +//| +//| The `qspibus` module provides a low-level QSPI bus interface for displays +//| that use four data lines. It is analogous to `fourwire` for standard SPI. +//| +//| Use :class:`qspibus.QSPIBus` to create a bus instance. +//| +//| Example usage:: +//| +//| import board +//| import qspibus +//| import displayio +//| +//| displayio.release_displays() +//| +//| bus = qspibus.QSPIBus( +//| clock=board.LCD_CLK, +//| data0=board.LCD_D0, +//| data1=board.LCD_D1, +//| data2=board.LCD_D2, +//| data3=board.LCD_D3, +//| cs=board.LCD_CS, +//| reset=board.LCD_RESET, +//| frequency=80_000_000, +//| ) +//| """ + +static const mp_rom_map_elem_t qspibus_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_qspibus) }, + { MP_ROM_QSTR(MP_QSTR_QSPIBus), MP_ROM_PTR(&qspibus_qspibus_type) }, +}; + +static MP_DEFINE_CONST_DICT(qspibus_module_globals, qspibus_module_globals_table); + +const mp_obj_module_t qspibus_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&qspibus_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_qspibus, qspibus_module); diff --git a/shared-bindings/qspibus/__init__.h b/shared-bindings/qspibus/__init__.h new file mode 100644 index 0000000000000..9b4ca24332703 --- /dev/null +++ b/shared-bindings/qspibus/__init__.h @@ -0,0 +1,8 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-bindings/qspibus/QSPIBus.h" diff --git a/shared-bindings/rainbowio/__init__.c b/shared-bindings/rainbowio/__init__.c index a5a941e2a7819..e02df713eeba2 100644 --- a/shared-bindings/rainbowio/__init__.c +++ b/shared-bindings/rainbowio/__init__.c @@ -13,12 +13,15 @@ //| //| Provides the `colorwheel()` function.""" //| +//| //| def colorwheel(n: float) -> int: //| """C implementation of the common colorwheel() function found in many examples. -//| Returns the colorwheel RGB value as an integer value for n (usable in neopixel and dotstar). +//| Takes a hue, a value between 0-255, and returns an RGB tuple encoded as an +//| integer value (usable in neopixel and dotstar). //| """ //| ... //| +//| static mp_obj_t rainbowio_colorwheel(mp_obj_t n) { mp_float_t f = mp_obj_get_float(n); return MP_OBJ_NEW_SMALL_INT(colorwheel(f)); diff --git a/shared-bindings/random/__init__.c b/shared-bindings/random/__init__.c index e255174fc1b6c..81201e6f8abbc 100644 --- a/shared-bindings/random/__init__.c +++ b/shared-bindings/random/__init__.c @@ -27,12 +27,14 @@ //| //| _T = TypeVar("_T") //| +//| //| def seed(seed: int) -> None: //| """Sets the starting seed of the random number generation. Further calls to //| `random` will return deterministic results afterwards.""" //| ... //| +//| static mp_obj_t random_seed(mp_obj_t seed_in) { mp_uint_t seed = mp_obj_get_int_truncated(seed_in); shared_modules_random_seed(seed); @@ -44,6 +46,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(random_seed_obj, random_seed); //| """Returns an integer with *k* random bits.""" //| ... //| +//| static mp_obj_t random_getrandbits(mp_obj_t num_in) { mp_int_t n = mp_obj_get_int(num_in); if (n > 32 || n < 0) { @@ -62,6 +65,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(random_getrandbits_obj, random_getrandbits); //| """Returns a randomly selected integer from ``range(start[, stop[, step]])``.""" //| ... //| +//| static mp_obj_t random_randrange(size_t n_args, const mp_obj_t *args) { mp_int_t start = 0; mp_int_t stop = mp_obj_get_int(args[0]); @@ -105,6 +109,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(random_randrange_obj, 1, 3, random_ra //| to ``randrange(a, b + 1, 1)``""" //| ... //| +//| static mp_obj_t random_randint(mp_obj_t a_in, mp_obj_t b_in) { mp_int_t a = mp_obj_get_int(a_in); mp_int_t b = mp_obj_get_int(b_in); @@ -120,6 +125,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(random_randint_obj, random_randint); //| IndexError when the sequence is empty.""" //| ... //| +//| static mp_obj_t random_choice(mp_obj_t seq) { mp_int_t len = mp_obj_get_int(mp_obj_len(seq)); if (len == 0) { @@ -133,6 +139,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(random_choice_obj, random_choice); //| """Returns a random float between 0 and 1.0.""" //| ... //| +//| static mp_obj_t random_random(void) { return mp_obj_new_float(shared_modules_random_random()); } @@ -143,6 +150,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(random_random_obj, random_random); //| depending on float rounding.""" //| ... //| +//| static mp_obj_t random_uniform(mp_obj_t a_in, mp_obj_t b_in) { mp_float_t a = mp_obj_get_float(a_in); mp_float_t b = mp_obj_get_float(b_in); diff --git a/shared-bindings/rclcpy/Node.c b/shared-bindings/rclcpy/Node.c new file mode 100644 index 0000000000000..4097fbc1515f4 --- /dev/null +++ b/shared-bindings/rclcpy/Node.c @@ -0,0 +1,146 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include +#include "shared-bindings/rclcpy/Node.h" +#include "shared-bindings/rclcpy/Publisher.h" +#include "shared-bindings/util.h" +#include "py/objproperty.h" +#include "py/objtype.h" +#include "py/runtime.h" + + +//| class Node: +//| """A ROS2 Node""" +//| +//| def __init__( +//| self, +//| node_name: str, +//| *, +//| namespace: str | None = None, +//| ) -> None: +//| """Create a Node. +//| +//| Creates an instance of a ROS2 Node. Nodes can be used to create other ROS +//| entities like publishers or subscribers. Nodes must have a unique name, and +//| may also be constructed from their class. +//| +//| :param str node_name: The name of the node. Must be a valid ROS 2 node name +//| :param str namespace: The namespace for the node. If None, the node will be +//| created in the root namespace +//| """ +//| ... +//| +static mp_obj_t rclcpy_node_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_node_name, ARG_namespace }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_node_name, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_namespace, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + const char *node_name = mp_obj_str_get_str(args[ARG_node_name].u_obj); + const char *namespace = ""; + if (args[ARG_namespace].u_obj != mp_const_none) { + namespace = mp_obj_str_get_str(args[ARG_namespace].u_obj); + } + + rclcpy_node_obj_t *self = mp_obj_malloc_with_finaliser(rclcpy_node_obj_t, &rclcpy_node_type); + common_hal_rclcpy_node_construct(self, node_name, namespace); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Deinitializes the node and frees any hardware or remote agent resources +//| used by it. Deinitialized nodes cannot be used again. +//| """ +//| ... +//| +static mp_obj_t rclcpy_node_obj_deinit(mp_obj_t self_in) { + rclcpy_node_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_rclcpy_node_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(rclcpy_node_deinit_obj, rclcpy_node_obj_deinit); + +static void check_for_deinit(rclcpy_node_obj_t *self) { + if (common_hal_rclcpy_node_deinited(self)) { + raise_deinited_error(); + } +} + +//| def create_publisher(self, topic: str) -> Publisher: +//| """Create a publisher for a given topic string. +//| +//| Creates an instance of a ROS2 Publisher. +//| +//| :param str topic: The name of the topic +//| :return: A new Publisher object for the specified topic +//| :rtype: Publisher +//| """ +//| ... +//| +static mp_obj_t rclcpy_node_create_publisher(mp_obj_t self_in, mp_obj_t topic) { + rclcpy_node_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + const char *topic_name = mp_obj_str_get_str(topic); + + rclcpy_publisher_obj_t *publisher = mp_obj_malloc_with_finaliser(rclcpy_publisher_obj_t, &rclcpy_publisher_type); + common_hal_rclcpy_publisher_construct(publisher, self, topic_name); + return MP_OBJ_FROM_PTR(publisher); +} +static MP_DEFINE_CONST_FUN_OBJ_2(rclcpy_node_create_publisher_obj, rclcpy_node_create_publisher); + +//| def get_name(self) -> str: +//| """Get the name of the node. +//| +//| :return: The node's name +//| :rtype: str +//| """ +//| ... +//| +static mp_obj_t rclcpy_node_get_name(mp_obj_t self_in) { + rclcpy_node_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + const char *name_str = common_hal_rclcpy_node_get_name(self); + return mp_obj_new_str(name_str, strlen(name_str)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(rclcpy_node_get_name_obj, rclcpy_node_get_name); + +//| def get_namespace(self) -> str: +//| """Get the namespace of the node. +//| +//| :return: The node's namespace +//| :rtype: str +//| """ +//| ... +//| +static mp_obj_t rclcpy_node_get_namespace(mp_obj_t self_in) { + rclcpy_node_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + const char *namespace_str = common_hal_rclcpy_node_get_namespace(self); + return mp_obj_new_str(namespace_str, strlen(namespace_str)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(rclcpy_node_get_namespace_obj, rclcpy_node_get_namespace); + +static const mp_rom_map_elem_t rclcpy_node_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rclcpy_node_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&rclcpy_node_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_create_publisher), MP_ROM_PTR(&rclcpy_node_create_publisher_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_name), MP_ROM_PTR(&rclcpy_node_get_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_namespace), MP_ROM_PTR(&rclcpy_node_get_namespace_obj) }, +}; +static MP_DEFINE_CONST_DICT(rclcpy_node_locals_dict, rclcpy_node_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + rclcpy_node_type, + MP_QSTR_Node, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, rclcpy_node_make_new, + locals_dict, &rclcpy_node_locals_dict + ); diff --git a/shared-bindings/rclcpy/Node.h b/shared-bindings/rclcpy/Node.h new file mode 100644 index 0000000000000..be0230846f6bd --- /dev/null +++ b/shared-bindings/rclcpy/Node.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once +#include "common-hal/rclcpy/Node.h" + + +extern const mp_obj_type_t rclcpy_node_type; + +void common_hal_rclcpy_node_construct(rclcpy_node_obj_t *self, + const char *node_name, const char *namespace); +bool common_hal_rclcpy_node_deinited(rclcpy_node_obj_t *self); +void common_hal_rclcpy_node_deinit(rclcpy_node_obj_t *self); +const char *common_hal_rclcpy_node_get_name(rclcpy_node_obj_t *self); +const char *common_hal_rclcpy_node_get_namespace(rclcpy_node_obj_t *self); diff --git a/shared-bindings/rclcpy/Publisher.c b/shared-bindings/rclcpy/Publisher.c new file mode 100644 index 0000000000000..be1e229cce4f8 --- /dev/null +++ b/shared-bindings/rclcpy/Publisher.c @@ -0,0 +1,99 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include +#include "shared-bindings/rclcpy/Publisher.h" +#include "shared-bindings/util.h" +#include "py/objproperty.h" +#include "py/objtype.h" +#include "py/runtime.h" + + +//| class Publisher: +//| """A ROS2 publisher""" +//| +//| def __init__(self) -> None: +//| """Publishers cannot be created directly. +//| +//| Use :meth:`Node.create_publisher` to create a publisher from a node. +//| +//| :raises NotImplementedError: Always, as direct instantiation is not supported +//| """ +//| ... +//| +static mp_obj_t rclcpy_publisher_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("Publishers can only be created from a parent node")); +} + +//| def deinit(self) -> None: +//| """Deinitializes the publisher and frees any hardware or remote agent resources +//| used by it. Deinitialized publishers cannot be used again. +//| """ +//| ... +//| +static mp_obj_t rclcpy_publisher_obj_deinit(mp_obj_t self_in) { + rclcpy_publisher_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_rclcpy_publisher_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(rclcpy_publisher_deinit_obj, rclcpy_publisher_obj_deinit); + +static void check_for_deinit(rclcpy_publisher_obj_t *self) { + if (common_hal_rclcpy_publisher_deinited(self)) { + raise_deinited_error(); + } +} + +//| def publish_int32(self, message: int) -> None: +//| """Publish a 32-bit signed integer message to the topic. +//| +//| :param int message: The integer value to publish. Must be within the range +//| of a 32-bit signed integer (-2,147,483,648 to 2,147,483,647) +//| """ +//| ... +//| +static mp_obj_t rclcpy_publisher_publish_int32(mp_obj_t self_in, mp_obj_t in_msg) { + rclcpy_publisher_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + int32_t msg = mp_obj_get_int(in_msg); + common_hal_rclcpy_publisher_publish_int32(self, msg); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_2(rclcpy_publisher_publish_int32_obj, rclcpy_publisher_publish_int32); + +//| def get_topic_name(self) -> str: +//| """Get the name of the topic this publisher publishes to. +//| +//| :return: The topic name as specified when the publisher was created +//| :rtype: str +//| """ +//| ... +//| +static mp_obj_t rclcpy_publisher_get_topic_name(mp_obj_t self_in) { + rclcpy_publisher_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + const char *topic_str = common_hal_rclcpy_publisher_get_topic_name(self); + return mp_obj_new_str(topic_str, strlen(topic_str)); +} +static MP_DEFINE_CONST_FUN_OBJ_1(rclcpy_publisher_get_topic_name_obj, rclcpy_publisher_get_topic_name); + + +static const mp_rom_map_elem_t rclcpy_publisher_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rclcpy_publisher_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&rclcpy_publisher_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_publish_int32), MP_ROM_PTR(&rclcpy_publisher_publish_int32_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_topic_name), MP_ROM_PTR(&rclcpy_publisher_get_topic_name_obj) }, +}; +static MP_DEFINE_CONST_DICT(rclcpy_publisher_locals_dict, rclcpy_publisher_locals_dict_table); + + +MP_DEFINE_CONST_OBJ_TYPE( + rclcpy_publisher_type, + MP_QSTR_Publisher, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, rclcpy_publisher_make_new, + locals_dict, &rclcpy_publisher_locals_dict + ); diff --git a/shared-bindings/rclcpy/Publisher.h b/shared-bindings/rclcpy/Publisher.h new file mode 100644 index 0000000000000..21909fe12bed9 --- /dev/null +++ b/shared-bindings/rclcpy/Publisher.h @@ -0,0 +1,18 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once +#include "common-hal/rclcpy/Publisher.h" + + +extern const mp_obj_type_t rclcpy_publisher_type; + +void common_hal_rclcpy_publisher_construct(rclcpy_publisher_obj_t *self, rclcpy_node_obj_t *node, + const char *topic_name); +bool common_hal_rclcpy_publisher_deinited(rclcpy_publisher_obj_t *self); +void common_hal_rclcpy_publisher_deinit(rclcpy_publisher_obj_t *self); +void common_hal_rclcpy_publisher_publish_int32(rclcpy_publisher_obj_t *self, int32_t data); +const char *common_hal_rclcpy_publisher_get_topic_name(rclcpy_publisher_obj_t *self); diff --git a/shared-bindings/rclcpy/__init__.c b/shared-bindings/rclcpy/__init__.c new file mode 100644 index 0000000000000..e195294cde61b --- /dev/null +++ b/shared-bindings/rclcpy/__init__.c @@ -0,0 +1,135 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/rclcpy/__init__.h" +#include "shared-bindings/rclcpy/Node.h" +#include "shared-bindings/rclcpy/Publisher.h" + +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" + +//| """Robot Operating System (ROS2) connectivity through micro-ROS +//| +//| The `rclcpy` module contains basic classes and connectivity options for +//| communicating with a ROS network running on a linux machine, using the +//| eProsima's `micro-ROS client API `_. +//| +//| The underlying micro-ROS system uses a resource-constrained middleware layer +//| (XRCE-DDS) that must be connected to an agent running within ROS2 on a host +//| Linux computer. The API exposed by Circuitpython aims to be close to the +//| standard Python API for ROS2, ``rclpy`` with minor additions to support +//| connecting to this agent. +//| +//| Wifi must be connected before calling any `rclcpy` functions. As with +//| ``rclpy``, the `rclcpy.init()` function must be run before creating any ROS +//| objects. Child objects, such as publishers, must be created by their parent +//| objects. For example:: +//| +//| import os, wifi, time +//| import rclcpy +//| wifi.radio.connect(ssid=os.getenv('CIRCUITPY_WIFI_SSID'), +//| password=os.getenv('CIRCUITPY_WIFI_PASSWORD')) +//| rclcpy.init("192.168.10.111","8888") +//| mynode = rclcpy.Node("foo") +//| mypub = mynode.create_publisher("bar") +//| mypub.publish_int32(42) +//| """ + +//| def init( +//| agent_ip: str, +//| agent_port: str, +//| *, +//| domain_id: int = 0, +//| ) -> None: +//| """Initialize micro-ROS and connect to a micro-ROS agent. +//| +//| This function starts ROS communications and connects to the micro-ROS agent +//| on a linux computer. It must be called before creating ROS objects. +//| +//| :param str agent_ip: The IP address of the micro-ROS agent +//| :param str agent_port: The port number of the micro-ROS agent as a string +//| :param int domain_id: The ROS 2 domain ID for network isolation and organization. +//| Devices with the same domain ID can communicate with each other. +//| """ +//| ... +//| +static mp_obj_t rclcpy_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_agent_ip, ARG_agent_port, ARG_domain_id}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_agent_ip, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_agent_port, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_domain_id, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + const char *agent_ip = mp_obj_str_get_str(args[ARG_agent_ip].u_obj); + const char *agent_port = mp_obj_str_get_str(args[ARG_agent_port].u_obj); + int16_t domain_id = args[ARG_domain_id].u_int; + + common_hal_rclcpy_init(agent_ip, agent_port, domain_id); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(rclcpy_init_obj, 2, rclcpy_init); + + +//| def create_node( +//| node_name: str, +//| *, +//| namespace: str | None = None +//| ) -> Node: +//| """Create a Node. +//| +//| Creates an instance of a ROS2 Node. Nodes can be used to create other ROS +//| entities like publishers or subscribers. Nodes must have a unique name, and +//| may also be constructed from their class. +//| +//| :param str node_name: The name of the node. Must be a valid ROS 2 node name. +//| :param str namespace: The namespace for the node. If None, the node will be +//| created in the root namespace. +//| :return: A new Node object +//| :rtype: Node +//| """ +//| ... +//| +static mp_obj_t rclcpy_create_node(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_node_name, ARG_namespace }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_node_name, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_namespace, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + const char *node_name = mp_obj_str_get_str(args[ARG_node_name].u_obj); + const char *namespace = ""; + if (args[ARG_namespace].u_obj != mp_const_none) { + namespace = mp_obj_str_get_str(args[ARG_namespace].u_obj); + } + + rclcpy_node_obj_t *self = mp_obj_malloc_with_finaliser(rclcpy_node_obj_t, &rclcpy_node_type); + common_hal_rclcpy_node_construct(self, node_name, namespace); + + return MP_OBJ_FROM_PTR(self); +} +static MP_DEFINE_CONST_FUN_OBJ_KW(rclcpy_create_node_obj, 2, rclcpy_create_node); + +static const mp_rom_map_elem_t rclcpy_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rclcpy) }, + { MP_ROM_QSTR(MP_QSTR_Node), MP_ROM_PTR(&rclcpy_node_type) }, + { MP_ROM_QSTR(MP_QSTR_Publisher), MP_ROM_PTR(&rclcpy_publisher_type) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&rclcpy_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_create_node), MP_ROM_PTR(&rclcpy_create_node_obj) }, +}; + +static MP_DEFINE_CONST_DICT(rclcpy_module_globals, rclcpy_module_globals_table); + +const mp_obj_module_t rclcpy_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&rclcpy_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_rclcpy, rclcpy_module); diff --git a/shared-bindings/rclcpy/__init__.h b/shared-bindings/rclcpy/__init__.h new file mode 100644 index 0000000000000..1b4734216889c --- /dev/null +++ b/shared-bindings/rclcpy/__init__.h @@ -0,0 +1,12 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Lucian Copeland +// +// SPDX-License-Identifier: MIT + +#pragma once +#include "common-hal/rclcpy/__init__.h" + +void common_hal_rclcpy_init(const char *agent_ip, const char *agent_port, int16_t domain_id); +rclcpy_context_t *common_hal_rclcpy_get_default_context(void); +bool common_hal_rclcpy_default_context_is_initialized(void); diff --git a/shared-bindings/rgbmatrix/RGBMatrix.c b/shared-bindings/rgbmatrix/RGBMatrix.c index bb4b5093330ef..6242f981fdfe9 100644 --- a/shared-bindings/rgbmatrix/RGBMatrix.c +++ b/shared-bindings/rgbmatrix/RGBMatrix.c @@ -130,7 +130,7 @@ static void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_ //| framebuffer: Optional[WriteableBuffer] = None, //| height: int = 0, //| tile: int = 1, -//| serpentine: bool = True +//| serpentine: bool = True, //| ) -> None: //| """Create a RGBMatrix object with the given attributes. The height of //| the display is determined by the number of rgb and address pins and the number of tiles: @@ -193,6 +193,7 @@ static void preflight_pins_or_throw(uint8_t clock_pin, uint8_t *rgb_pins, uint8_ //| :param Optional[WriteableBuffer] framebuffer: A pre-allocated framebuffer to use. If unspecified, a framebuffer is allocated //| :param int height: The optional overall height of the whole matrix in pixels. This value is not required because it can be calculated as described above. //| """ +//| static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_width, ARG_bit_depth, ARG_rgb_list, ARG_addr_list, @@ -269,6 +270,7 @@ static mp_obj_t rgbmatrix_rgbmatrix_make_new(const mp_obj_type_t *type, size_t n //| rgbmatrix instance. After deinitialization, no further operations //| may be performed.""" //| ... +//| static mp_obj_t rgbmatrix_rgbmatrix_deinit(mp_obj_t self_in) { rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t *)self_in; common_hal_rgbmatrix_rgbmatrix_deinit(self); @@ -286,6 +288,7 @@ static void check_for_deinit(rgbmatrix_rgbmatrix_obj_t *self) { //| brightness: float //| """In the current implementation, 0.0 turns the display off entirely //| and any other value up to 1.0 turns the display on fully.""" +//| static mp_obj_t rgbmatrix_rgbmatrix_get_brightness(mp_obj_t self_in) { rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t *)self_in; check_for_deinit(self); @@ -314,6 +317,7 @@ MP_PROPERTY_GETSET(rgbmatrix_rgbmatrix_brightness_obj, //| """Transmits the color data in the buffer to the pixels so that //| they are shown.""" //| ... +//| static mp_obj_t rgbmatrix_rgbmatrix_refresh(mp_obj_t self_in) { rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t *)self_in; check_for_deinit(self); @@ -336,6 +340,7 @@ MP_PROPERTY_GETTER(rgbmatrix_rgbmatrix_width_obj, //| height: int //| """The height of the display, in pixels""" //| +//| static mp_obj_t rgbmatrix_rgbmatrix_get_height(mp_obj_t self_in) { rgbmatrix_rgbmatrix_obj_t *self = (rgbmatrix_rgbmatrix_obj_t *)self_in; check_for_deinit(self); diff --git a/shared-bindings/rotaryio/IncrementalEncoder.c b/shared-bindings/rotaryio/IncrementalEncoder.c index 9b92daf13a05d..0cd94c0756214 100644 --- a/shared-bindings/rotaryio/IncrementalEncoder.c +++ b/shared-bindings/rotaryio/IncrementalEncoder.c @@ -16,8 +16,8 @@ //| class IncrementalEncoder: //| """IncrementalEncoder determines the relative rotational position based on two series of pulses. -//| It assumes that the encoder's common pin(s) are connected to ground,and enables pull-ups on -//| pin_a and pin_b.""" +//| It assumes that the encoder's common pin(s) are connected to ground,and enables pull-ups on +//| pin_a and pin_b.""" //| //| def __init__( //| self, pin_a: microcontroller.Pin, pin_b: microcontroller.Pin, divisor: int = 4 @@ -42,8 +42,15 @@ //| position = enc.position //| if last_position == None or position != last_position: //| print(position) -//| last_position = position""" +//| last_position = position +//| +//| .. warning:: On RP2350 boards, any pulldowns used must be 8.2 kohms or less, +//| to overcome a hardware issue. +//| See the RP2350 warning in `digitalio` for more information. +//| """ +//| //| ... +//| static mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pin_a, ARG_pin_b, ARG_divisor }; static const mp_arg_t allowed_args[] = { @@ -57,8 +64,7 @@ static mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type, const mcu_pin_obj_t *pin_a = validate_obj_is_free_pin(args[ARG_pin_a].u_obj, MP_QSTR_pin_a); const mcu_pin_obj_t *pin_b = validate_obj_is_free_pin(args[ARG_pin_b].u_obj, MP_QSTR_pin_b); - rotaryio_incrementalencoder_obj_t *self = m_new_obj_with_finaliser(rotaryio_incrementalencoder_obj_t); - self->base.type = &rotaryio_incrementalencoder_type; + rotaryio_incrementalencoder_obj_t *self = mp_obj_malloc_with_finaliser(rotaryio_incrementalencoder_obj_t, &rotaryio_incrementalencoder_type); common_hal_rotaryio_incrementalencoder_construct(self, pin_a, pin_b); common_hal_rotaryio_incrementalencoder_set_divisor(self, args[ARG_divisor].u_int); @@ -69,6 +75,7 @@ static mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type, //| def deinit(self) -> None: //| """Deinitializes the IncrementalEncoder and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t rotaryio_incrementalencoder_deinit(mp_obj_t self_in) { rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_rotaryio_incrementalencoder_deinit(self); @@ -85,18 +92,15 @@ static void check_for_deinit(rotaryio_incrementalencoder_obj_t *self) { //| def __enter__(self) -> IncrementalEncoder: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t rotaryio_incrementalencoder_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_rotaryio_incrementalencoder_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rotaryio_incrementalencoder___exit___obj, 4, 4, rotaryio_incrementalencoder_obj___exit__); +//| +// Provided by context manager helper. //| divisor: int @@ -128,6 +132,7 @@ MP_PROPERTY_GETSET(rotaryio_incrementalencoder_divisor_obj, //| """The current position in terms of pulses. The number of pulses per rotation is defined by the //| specific hardware and by the divisor.""" //| +//| static mp_obj_t rotaryio_incrementalencoder_obj_get_position(mp_obj_t self_in) { rotaryio_incrementalencoder_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -154,7 +159,7 @@ static const mp_rom_map_elem_t rotaryio_incrementalencoder_locals_dict_table[] = { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rotaryio_incrementalencoder_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&rotaryio_incrementalencoder_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&rotaryio_incrementalencoder___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_position), MP_ROM_PTR(&rotaryio_incrementalencoder_position_obj) }, { MP_ROM_QSTR(MP_QSTR_divisor), MP_ROM_PTR(&rotaryio_incrementalencoder_divisor_obj) }, }; diff --git a/shared-bindings/rotaryio/IncrementalEncoder.h b/shared-bindings/rotaryio/IncrementalEncoder.h index 1c60dd69a1937..b3ceb3eeb1513 100644 --- a/shared-bindings/rotaryio/IncrementalEncoder.h +++ b/shared-bindings/rotaryio/IncrementalEncoder.h @@ -13,11 +13,15 @@ extern const mp_obj_type_t rotaryio_incrementalencoder_type; extern void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self, const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b); + extern void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_obj_t *self); extern bool common_hal_rotaryio_incrementalencoder_deinited(rotaryio_incrementalencoder_obj_t *self); +extern void common_hal_rotaryio_incrementalencoder_mark_deinit(rotaryio_incrementalencoder_obj_t *self); + extern mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self); extern void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self, mp_int_t new_position); + extern mp_int_t common_hal_rotaryio_incrementalencoder_get_divisor(rotaryio_incrementalencoder_obj_t *self); extern void common_hal_rotaryio_incrementalencoder_set_divisor(rotaryio_incrementalencoder_obj_t *self, mp_int_t new_divisor); diff --git a/shared-bindings/rtc/RTC.c b/shared-bindings/rtc/RTC.c index 01686a75d9fd3..d732ee94d7e0a 100644 --- a/shared-bindings/rtc/RTC.c +++ b/shared-bindings/rtc/RTC.c @@ -23,6 +23,7 @@ const rtc_rtc_obj_t rtc_rtc_obj = {{&rtc_rtc_type}}; //| def __init__(self) -> None: //| """This class represents the onboard Real Time Clock. It is a singleton and will always return the same instance.""" //| ... +//| static mp_obj_t rtc_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // No arguments mp_arg_check_num(n_args, n_kw, 0, 0, false); @@ -73,7 +74,7 @@ MP_PROPERTY_GETSET(rtc_rtc_datetime_obj, //| //| A positive value speeds up the clock and a negative value slows it down. //| -//| **Limitations:** Calibration not supported on SAMD, Nordic, RP240, Spresense, and STM. +//| **Limitations:** Calibration not supported on SAMD, Nordic, RP2040, Spresense, and STM. //| //| Range and value is hardware specific, but one step is often approximately 1 ppm:: //| @@ -83,6 +84,7 @@ MP_PROPERTY_GETSET(rtc_rtc_datetime_obj, //| r = rtc.RTC() //| r.calibration = 1""" //| +//| static mp_obj_t rtc_rtc_obj_get_calibration(mp_obj_t self_in) { int calibration = common_hal_rtc_get_calibration(); return mp_obj_new_int(calibration); diff --git a/shared-bindings/rtc/__init__.c b/shared-bindings/rtc/__init__.c index 16158413d1875..d719ec8441ddc 100644 --- a/shared-bindings/rtc/__init__.c +++ b/shared-bindings/rtc/__init__.c @@ -17,6 +17,7 @@ //| RTC using :class:`rtc.RTC`. It also backs the :func:`time.time` and :func:`time.localtime` //| functions using the onboard RTC if present.""" //| +//| void rtc_reset(void) { MP_STATE_VM(rtc_time_source) = (mp_obj_t)&rtc_rtc_obj; @@ -47,6 +48,7 @@ mp_obj_t rtc_get_time_source_time(void) { //| rtc.set_time_source(r)""" //| ... //| +//| static mp_obj_t rtc_set_time_source(mp_obj_t time_source) { MP_STATE_VM(rtc_time_source) = time_source; diff --git a/shared-bindings/sdcardio/SDCard.c b/shared-bindings/sdcardio/SDCard.c index 97bd51c001932..9a04cea57e594 100644 --- a/shared-bindings/sdcardio/SDCard.c +++ b/shared-bindings/sdcardio/SDCard.c @@ -9,7 +9,8 @@ #include "py/objarray.h" #include "shared-bindings/sdcardio/SDCard.h" -#include "shared-module/sdcardio/SDCard.h" +#include "shared-bindings/util.h" + #include "common-hal/busio/SPI.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/microcontroller/Pin.h" @@ -42,6 +43,13 @@ //| Failure to do so can prevent the SD card from being recognized until it is //| powered off or re-inserted. //| +//| Exception: on boards where another SPI peripheral has a floating CS +//| pin with no hardware pull-up (such as the Feather RP2040 RFM), that +//| peripheral's CS must be driven HIGH before SD card initialization. +//| Failure to do so will corrupt the SPI bus during SD card init. In +//| these cases, initialize and drive the other peripheral's CS high +//| first, then initialize the SD card. +//| //| Example usage: //| //| .. code-block:: python @@ -52,10 +60,19 @@ //| import sdcardio //| import storage //| +//| # Make sure to make an "sd" folder on CIRCUITPY +//| //| sd = sdcardio.SDCard(board.SPI(), board.SD_CS) //| vfs = storage.VfsFat(sd) //| storage.mount(vfs, '/sd') -//| os.listdir('/sd')""" +//| print(os.listdir('/sd'))""" +//| + +static void check_for_deinit(sdcardio_sdcard_obj_t *self) { + if (common_hal_sdcardio_sdcard_deinited(self)) { + raise_deinited_error(); + } +} static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_spi, ARG_cs, ARG_baudrate, NUM_ARGS }; @@ -71,11 +88,10 @@ static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_arg busio_spi_obj_t *spi = validate_obj_is_spi_bus(args[ARG_spi].u_obj, MP_QSTR_spi); const mcu_pin_obj_t *cs = validate_obj_is_free_pin(args[ARG_cs].u_obj, MP_QSTR_cs); - sdcardio_sdcard_obj_t *self = mp_obj_malloc(sdcardio_sdcard_obj_t, &sdcardio_SDCard_type); - + sdcardio_sdcard_obj_t *self = mp_obj_malloc_with_finaliser(sdcardio_sdcard_obj_t, &sdcardio_SDCard_type); common_hal_sdcardio_sdcard_construct(self, spi, cs, args[ARG_baudrate].u_int); - return self; + return MP_OBJ_FROM_PTR(self); } @@ -85,8 +101,10 @@ static mp_obj_t sdcardio_sdcard_make_new(const mp_obj_type_t *type, size_t n_arg //| Due to technical limitations, this is a function and not a property. //| //| :return: The number of 512-byte blocks, as a number""" +//| static mp_obj_t sdcardio_sdcard_count(mp_obj_t self_in) { sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + check_for_deinit(self); return mp_obj_new_int_from_ull(common_hal_sdcardio_sdcard_get_blockcount(self)); } MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count); @@ -95,6 +113,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_count_obj, sdcardio_sdcard_count); //| """Disable permanently. //| //| :return: None""" +//| static mp_obj_t sdcardio_sdcard_deinit(mp_obj_t self_in) { sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; common_hal_sdcardio_sdcard_deinit(self); @@ -110,12 +129,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_deinit_obj, sdcardio_sdcard_deinit); //| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512. //| //| :return: None""" +//| static mp_obj_t _sdcardio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + check_for_deinit(self); + uint32_t start_block = mp_obj_get_int(start_block_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; int result = common_hal_sdcardio_sdcard_readblocks(self, start_block, &bufinfo); if (result < 0) { mp_raise_OSError(-result); @@ -130,8 +152,10 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_readblocks_obj, _sdcardio_sdcard_readb //| //| :return: None""" //| ... +//| static mp_obj_t sdcardio_sdcard_sync(mp_obj_t self_in) { sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + check_for_deinit(self); int result = common_hal_sdcardio_sdcard_sync(self); if (result < 0) { mp_raise_OSError(-result); @@ -150,12 +174,15 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdcardio_sdcard_sync_obj, sdcardio_sdcard_sync); //| //| :return: None""" //| +//| static mp_obj_t _sdcardio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { + sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; + check_for_deinit(self); + uint32_t start_block = mp_obj_get_int(start_block_in); mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - sdcardio_sdcard_obj_t *self = (sdcardio_sdcard_obj_t *)self_in; int result = common_hal_sdcardio_sdcard_writeblocks(self, start_block, &bufinfo); if (result < 0) { mp_raise_OSError(-result); @@ -167,6 +194,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdcardio_sdcard_writeblocks_obj, _sdcardio_sdcard_writ static const mp_rom_map_elem_t sdcardio_sdcard_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&sdcardio_sdcard_count_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&sdcardio_sdcard_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&sdcardio_sdcard_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&sdcardio_sdcard_sync_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&sdcardio_sdcard_writeblocks_obj) }, diff --git a/shared-bindings/sdcardio/SDCard.h b/shared-bindings/sdcardio/SDCard.h index ac27b47aa4d21..d0cb8206c349d 100644 --- a/shared-bindings/sdcardio/SDCard.h +++ b/shared-bindings/sdcardio/SDCard.h @@ -7,17 +7,20 @@ #pragma once +#include "py/mperrno.h" #include "shared-module/sdcardio/SDCard.h" extern const mp_obj_type_t sdcardio_SDCard_type; void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *spi, const mcu_pin_obj_t *cs, int baudrate); void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self); +bool common_hal_sdcardio_sdcard_deinited(sdcardio_sdcard_obj_t *self); void common_hal_sdcardio_sdcard_check_for_deinit(sdcardio_sdcard_obj_t *self); +void common_hal_sdcardio_sdcard_mark_deinit(sdcardio_sdcard_obj_t *self); int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self); -int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self); -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); +mp_negative_errno_t common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); +mp_negative_errno_t common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self); +mp_negative_errno_t common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf); // Used by native vfs blockdev. mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); diff --git a/shared-bindings/sdioio/SDCard.c b/shared-bindings/sdioio/SDCard.c index 98a9ef6c8588a..baf1e1660e845 100644 --- a/shared-bindings/sdioio/SDCard.c +++ b/shared-bindings/sdioio/SDCard.c @@ -55,15 +55,18 @@ //| sd = sdioio.SDCard( //| clock=board.SDIO_CLOCK, //| command=board.SDIO_COMMAND, -//| data=[board.SDIO_DATA], +//| # Note that board.SDIO_DATA is a tuple of four pins, not an individual pin. +//| data=board.SDIO_DATA, +//| # On some boards, the data pins are named individually. Use this line instead. +//| #data=(board.SDIO_DATA0, board.SDIO_DATA1, board.SDIO_DATA2, board.SDIO_DATA3), //| frequency=25000000) //| vfs = storage.VfsFat(sd) //| storage.mount(vfs, '/sd') //| os.listdir('/sd')""" //| ... +//| static mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - sdioio_sdcard_obj_t *self = mp_obj_malloc(sdioio_sdcard_obj_t, &sdioio_SDCard_type); enum { ARG_clock, ARG_command, ARG_data, ARG_frequency, NUM_ARGS }; static const mp_arg_t allowed_args[] = { { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ }, @@ -82,6 +85,7 @@ static mp_obj_t sdioio_sdcard_make_new(const mp_obj_type_t *type, size_t n_args, uint8_t num_data; validate_list_is_free_pins(MP_QSTR_data, data_pins, MP_ARRAY_SIZE(data_pins), args[ARG_data].u_obj, &num_data); + sdioio_sdcard_obj_t *self = mp_obj_malloc(sdioio_sdcard_obj_t, &sdioio_SDCard_type); common_hal_sdioio_sdcard_construct(self, clock, command, num_data, data_pins, args[ARG_frequency].u_int); return MP_OBJ_FROM_PTR(self); } @@ -99,6 +103,7 @@ static void check_for_deinit(sdioio_sdcard_obj_t *self) { //| :param int width: the number of data lines to use. Must be 1 or 4 and must also not exceed the number of data lines at construction //| //| .. note:: Leaving a value unspecified or 0 means the current setting is kept""" +//| static mp_obj_t sdioio_sdcard_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_frequency, ARG_width, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -130,6 +135,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(sdioio_sdcard_configure_obj, 1, sdioio_sdcard_configu //| Due to technical limitations, this is a function and not a property. //| //| :return: The number of 512-byte blocks, as a number""" +//| static mp_obj_t sdioio_sdcard_count(mp_obj_t self_in) { sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -144,6 +150,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_count_obj, sdioio_sdcard_count); //| :param ~circuitpython_typing.WriteableBuffer buf: The buffer to write into. Length must be multiple of 512. //| //| :return: None""" +//| static mp_obj_t _sdioio_sdcard_readblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { uint32_t start_block = mp_obj_get_int(start_block_in); mp_buffer_info_t bufinfo; @@ -165,6 +172,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(sdioio_sdcard_readblocks_obj, _sdioio_sdcard_readblock //| :param ~circuitpython_typing.ReadableBuffer buf: The buffer to read from. Length must be multiple of 512. //| //| :return: None""" +//| static mp_obj_t _sdioio_sdcard_writeblocks(mp_obj_t self_in, mp_obj_t start_block_in, mp_obj_t buf_in) { uint32_t start_block = mp_obj_get_int(start_block_in); mp_buffer_info_t bufinfo; @@ -194,6 +202,7 @@ MP_PROPERTY_GETTER(sdioio_sdcard_frequency_obj, //| width: int //| """The actual SDIO bus width, in bits""" +//| static mp_obj_t sdioio_sdcard_obj_get_width(mp_obj_t self_in) { sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -208,6 +217,7 @@ MP_PROPERTY_GETTER(sdioio_sdcard_width_obj, //| """Disable permanently. //| //| :return: None""" +//| static mp_obj_t sdioio_sdcard_obj_deinit(mp_obj_t self_in) { sdioio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_sdioio_sdcard_deinit(self); @@ -219,23 +229,20 @@ MP_DEFINE_CONST_FUN_OBJ_1(sdioio_sdcard_deinit_obj, sdioio_sdcard_obj_deinit); //| """No-op used by Context Managers. //| Provided by context manager helper.""" //| ... +//| //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... //| -static mp_obj_t sdioio_sdcard_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_sdioio_sdcard_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(sdioio_sdcard_obj___exit___obj, 4, 4, sdioio_sdcard_obj___exit__); +//| +// Provided by context manager helper. static const mp_rom_map_elem_t sdioio_sdcard_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&sdioio_sdcard_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&sdioio_sdcard_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&sdioio_sdcard_configure_obj) }, { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&sdioio_sdcard_frequency_obj) }, diff --git a/shared-bindings/sdioio/SDCard.h b/shared-bindings/sdioio/SDCard.h index dfeaf8fca8962..042521aea50dd 100644 --- a/shared-bindings/sdioio/SDCard.h +++ b/shared-bindings/sdioio/SDCard.h @@ -7,6 +7,7 @@ #pragma once #include "py/obj.h" +#include "py/mperrno.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/sdioio/SDCard.h" @@ -35,9 +36,14 @@ uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self); // Return number of device blocks uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self); -// Read or write blocks -int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo); -int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo); +// Read or write blocks - returns 0 on success or negative error code from mperrno.h +mp_negative_errno_t common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo); +mp_negative_errno_t common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo); + +// Used by native vfs blockdev. +mp_negative_errno_t sdioio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); +mp_negative_errno_t sdioio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t buflen); +bool sdioio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value); // This is used by the supervisor to claim SDIO devices indefinitely. extern void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self); diff --git a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c index 3dd4e2717e2d5..e1e2469e36154 100644 --- a/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-bindings/sharpdisplay/SharpMemoryFramebuffer.c @@ -40,6 +40,7 @@ //| :param bool jdi_display: When True, work with an 8-color JDI display. Otherwise, a monochrome Sharp display. //| """ //| ... +//| static mp_obj_t sharpdisplay_framebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_spi_bus, ARG_chip_select, ARG_width, ARG_height, ARG_baudrate, ARG_jdi_display, NUM_ARGS }; static const mp_arg_t allowed_args[] = { @@ -83,6 +84,7 @@ static mp_int_t sharpdisplay_framebuffer_get_buffer(mp_obj_t self_in, mp_buffer_ //| may be performed.""" //| ... //| +//| static mp_obj_t sharpdisplay_framebuffer_deinit(mp_obj_t self_in) { sharpdisplay_framebuffer_obj_t *self = (sharpdisplay_framebuffer_obj_t *)self_in; common_hal_sharpdisplay_framebuffer_deinit(self); diff --git a/shared-bindings/socketpool/Socket.c b/shared-bindings/socketpool/Socket.c index 25d10c294827a..5dac9d150e8ff 100644 --- a/shared-bindings/socketpool/Socket.c +++ b/shared-bindings/socketpool/Socket.c @@ -32,18 +32,21 @@ //| def __hash__(self) -> int: //| """Returns a hash for the Socket.""" //| ... +//| // Provided inherently. // See https://github.com/micropython/micropython/pull/10348. //| def __enter__(self) -> Socket: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically closes the Socket when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... +//| static mp_obj_t socketpool_socket___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; common_hal_socketpool_socket_close(args[0]); @@ -55,6 +58,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket___exit___obj, 4, 4, //| """Accept a connection on a listening socket of type SOCK_STREAM, //| creating a new socket of type SOCK_STREAM. //| Returns a tuple of (new_socket, remote_address)""" +//| static mp_obj_t _socketpool_socket_accept(mp_obj_t self_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -70,6 +74,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_accept_obj, _socketpool_socke //| //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... +//| static mp_obj_t socketpool_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -94,6 +99,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_bind_obj, socketpool_socket_b //| def close(self) -> None: //| """Closes this Socket and makes its resources available to its SocketPool.""" +//| static mp_obj_t _socketpool_socket_close(mp_obj_t self_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_socketpool_socket_close(self); @@ -106,6 +112,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(socketpool_socket_close_obj, _socketpool_socket //| //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... +//| static mp_obj_t socketpool_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -130,6 +137,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_connect_obj, socketpool_socke //| //| :param ~int backlog: length of backlog queue for waiting connections""" //| ... +//| static mp_obj_t socketpool_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -149,6 +157,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_listen_obj, socketpool_socket //| //| :param object buffer: buffer to read into""" //| ... +//| static mp_obj_t socketpool_socket_recvfrom_into(mp_obj_t self_in, mp_obj_t data_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_buffer_info_t bufinfo; @@ -174,6 +183,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_recvfrom_into_obj, socketpool //| :param bytearray buffer: buffer to receive into //| :param int bufsize: optionally, a maximum number of bytes to read.""" //| ... +//| static mp_obj_t _socketpool_socket_recv_into(size_t n_args, const mp_obj_t *args) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (common_hal_socketpool_socket_get_closed(self)) { @@ -212,6 +222,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket_recv_into_obj, 2, 3 //| //| :param ~bytes bytes: some bytes to send""" //| ... +//| static mp_obj_t _socketpool_socket_send(mp_obj_t self_in, mp_obj_t buf_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_socketpool_socket_get_closed(self)) { @@ -241,6 +252,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_send_obj, _socketpool_socket_ //| //| :param ~bytes bytes: some bytes to send""" //| ... +//| static mp_obj_t _socketpool_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_socketpool_socket_get_closed(self)) { @@ -278,6 +290,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_sendall_obj, _socketpool_sock //| :param ~bytes bytes: some bytes to send //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... +//| static mp_obj_t socketpool_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -306,6 +319,7 @@ static MP_DEFINE_CONST_FUN_OBJ_3(socketpool_socket_sendto_obj, socketpool_socket //| //| :param ~bool flag: False means non-blocking, True means block indefinitely.""" //| ... +//| // method socket.setblocking(flag) static mp_obj_t socketpool_socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -321,6 +335,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_setblocking_obj, socketpool_s //| def setsockopt(self, level: int, optname: int, value: int) -> None: //| """Sets socket options""" //| ... +//| static mp_obj_t socketpool_socket_setsockopt(size_t n_args, const mp_obj_t *args) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t level = mp_obj_get_int(args[1]); @@ -356,6 +371,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socketpool_socket_setsockopt_obj, 4, //| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely. //| """ //| ... +//| static mp_obj_t socketpool_socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t timeout_ms; @@ -376,6 +392,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(socketpool_socket_settimeout_obj, socketpool_so //| type: int //| """Read-only access to the socket type""" //| +//| static mp_obj_t socketpool_socket_obj_get_type(mp_obj_t self_in) { socketpool_socket_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(common_hal_socketpool_socket_get_type(self)); diff --git a/shared-bindings/socketpool/Socket.h b/shared-bindings/socketpool/Socket.h index a883ebd505463..295f86e737169 100644 --- a/shared-bindings/socketpool/Socket.h +++ b/shared-bindings/socketpool/Socket.h @@ -6,6 +6,7 @@ #pragma once +#include "py/mperrno.h" #include "common-hal/socketpool/Socket.h" extern const mp_obj_type_t socketpool_socket_type; diff --git a/shared-bindings/socketpool/SocketPool.c b/shared-bindings/socketpool/SocketPool.c index ada850ad17d4d..1fc9e2c3335ca 100644 --- a/shared-bindings/socketpool/SocketPool.c +++ b/shared-bindings/socketpool/SocketPool.c @@ -24,22 +24,20 @@ //| a pool of sockets provided by the underlying OS. //| """ //| -//| def __init__(self, radio: wifi.Radio) -> None: +//| def __init__(self, radio: Union[wifi.Radio, hostnetwork.HostNetwork]) -> None: //| """Create a new SocketPool object for the provided radio //| -//| :param wifi.Radio radio: The (connected) network hardware to associate -//| with this SocketPool; currently, this will always be the object -//| returned by :py:attr:`wifi.radio` +//| :param radio: The (connected) network interface to associate with this +//| SocketPool, such as :py:attr:`wifi.radio` or :py:attr:`board.NETWORK`. //| """ //| ... //| static mp_obj_t socketpool_socketpool_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 1, false); - socketpool_socketpool_obj_t *s = m_new_obj_with_finaliser(socketpool_socketpool_obj_t); - s->base.type = &socketpool_socketpool_type; mp_obj_t radio = args[0]; + socketpool_socketpool_obj_t *s = mp_obj_malloc_with_finaliser(socketpool_socketpool_obj_t, &socketpool_socketpool_type); common_hal_socketpool_socketpool_construct(s, radio); return MP_OBJ_FROM_PTR(s); @@ -87,6 +85,7 @@ MP_DEFINE_EXCEPTION(gaierror, OSError) //| in CPython is not supported. //| """ //| ... +//| static mp_obj_t socketpool_socketpool_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_family, ARG_type, ARG_proto }; static const mp_arg_t allowed_args[] = { @@ -103,10 +102,6 @@ static mp_obj_t socketpool_socketpool_socket(size_t n_args, const mp_obj_t *pos_ socketpool_socketpool_sock_t type = args[ARG_type].u_int; socketpool_socketpool_ipproto_t proto = args[ARG_proto].u_int; - if (proto < 0) { - proto = 0; - } - return common_hal_socketpool_socket(self, family, type, proto); } MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_socket_obj, 1, socketpool_socketpool_socket); @@ -127,6 +122,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(socketpool_socketpool_socket_obj, 1, socketpool_socke //| as a tuple.""" //| ... //| +//| static mp_obj_t socketpool_socketpool_getaddrinfo(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_host, ARG_port, ARG_family, ARG_type, ARG_proto, ARG_flags }; static const mp_arg_t allowed_args[] = { @@ -193,7 +189,7 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &socketpool_socketpool_locals_dict ); -MP_WEAK NORETURN +MP_WEAK MP_NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void) { vstr_t vstr; mp_print_t print; diff --git a/shared-bindings/socketpool/SocketPool.h b/shared-bindings/socketpool/SocketPool.h index 36035ed00e11a..60d58372b9131 100644 --- a/shared-bindings/socketpool/SocketPool.h +++ b/shared-bindings/socketpool/SocketPool.h @@ -25,6 +25,6 @@ bool socketpool_socket(socketpool_socketpool_obj_t *self, socketpool_socketpool_addressfamily_t family, socketpool_socketpool_sock_t type, int proto, socketpool_socket_obj_t *sock); -NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); +MP_NORETURN void common_hal_socketpool_socketpool_raise_gaierror_noname(void); mp_obj_t common_hal_socketpool_getaddrinfo_raise(socketpool_socketpool_obj_t *self, const char *host, int port, int family, int type, int proto, int flags); diff --git a/shared-bindings/spitarget/SPITarget.c b/shared-bindings/spitarget/SPITarget.c new file mode 100644 index 0000000000000..08f6d554f3a45 --- /dev/null +++ b/shared-bindings/spitarget/SPITarget.c @@ -0,0 +1,190 @@ +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/spitarget/SPITarget.h" +#include "shared-bindings/time/__init__.h" +#include "shared-bindings/util.h" + +#include "shared/runtime/buffer_helper.h" +#include "shared/runtime/context_manager_helpers.h" +#include "shared/runtime/interrupt_char.h" + +#include "py/mperrno.h" +#include "py/mphal.h" +#include "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" + +//| class SPITarget: +//| """Serial Peripheral Interface protocol target""" +//| +//| def __init__( +//| self, +//| sck: microcontroller.Pin, +//| mosi: microcontroller.Pin, +//| miso: microcontroller.Pin, +//| ss: microcontroller.Pin, +//| ) -> None: +//| """SPI is a four-wire protocol for communicating between devices. +//| This implements the secondary (aka target or peripheral) side. +//| +//| :param ~microcontroller.Pin sck: The SPI clock pin +//| :param ~microcontroller.Pin mosi: The pin transferring data from the main to the secondary +//| :param ~microcontroller.Pin miso: The pin transferring data from the secondary to the main +//| :param ~microcontroller.Pin ss: The secondary selection pin""" +//| ... +//| +static mp_obj_t spitarget_spi_target_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_sck, ARG_mosi, ARG_miso, ARG_ss }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_sck, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_mosi, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_miso, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_ss, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mcu_pin_obj_t *sck = validate_obj_is_free_pin(args[ARG_sck].u_obj, MP_QSTR_sck); + const mcu_pin_obj_t *mosi = validate_obj_is_free_pin(args[ARG_mosi].u_obj, MP_QSTR_mosi); + const mcu_pin_obj_t *miso = validate_obj_is_free_pin(args[ARG_miso].u_obj, MP_QSTR_miso); + const mcu_pin_obj_t *ss = validate_obj_is_free_pin(args[ARG_ss].u_obj, MP_QSTR_ss); + + spitarget_spi_target_obj_t *self = mp_obj_malloc(spitarget_spi_target_obj_t, &spitarget_spi_target_type); + common_hal_spitarget_spi_target_construct(self, sck, mosi, miso, ss); + + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Releases control of the underlying hardware so other classes can use it.""" +//| ... +//| +static mp_obj_t spitarget_spi_target_obj_deinit(mp_obj_t self_in) { + mp_check_self(mp_obj_is_type(self_in, &spitarget_spi_target_type)); + spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_spitarget_spi_target_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(spitarget_spi_target_deinit_obj, spitarget_spi_target_obj_deinit); + +//| def __enter__(self) -> SPITarget: +//| """No-op used in Context Managers.""" +//| ... +//| +// Provided by context manager helper. + +//| def __exit__(self) -> None: +//| """Automatically deinitializes the hardware on context exit. See +//| :ref:`lifetime-and-contextmanagers` for more info.""" +//| ... +//| +static mp_obj_t spitarget_spi_target_obj___exit__(size_t n_args, const mp_obj_t *args) { + mp_check_self(mp_obj_is_type(args[0], &spitarget_spi_target_target_type)); + spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(args[0]); + common_hal_spitarget_spi_target_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(spitarget_spi_target___exit___obj, 4, 4, spitarget_spi_target_obj___exit__); + +//| def load_packet(self, mosi_packet: bytearray, miso_packet: bytearray) -> None: +//| """Queue data for the next SPI transfer from the main device. +//| If a packet has already been queued for this SPI bus but has not yet been transferred, an error will be raised. +//| +//| :param bytearray miso_packet: Packet data to be sent from secondary to main on next request. +//| :param bytearray mosi_packet: Packet to be filled with data from main on next request. +//| """ +//| +static mp_obj_t spitarget_spi_target_load_packet(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_check_self(mp_obj_is_type(pos_args[0], &spitarget_spi_target_type)); + spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (common_hal_spitarget_spi_target_deinited(self)) { + raise_deinited_error(); + } + enum { ARG_mosi_packet, ARG_miso_packet }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mosi_packet, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_miso_packet, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_buffer_info_t mosi_bufinfo; + mp_get_buffer_raise(args[ARG_mosi_packet].u_obj, &mosi_bufinfo, MP_BUFFER_WRITE); + + mp_buffer_info_t miso_bufinfo; + mp_get_buffer_raise(args[ARG_miso_packet].u_obj, &miso_bufinfo, MP_BUFFER_READ); + + if (miso_bufinfo.len != mosi_bufinfo.len) { + mp_raise_ValueError(MP_ERROR_TEXT("Packet buffers for an SPI transfer must have the same length.")); + } + + common_hal_spitarget_spi_target_transfer_start(self, ((uint8_t *)mosi_bufinfo.buf), ((uint8_t *)miso_bufinfo.buf), mosi_bufinfo.len); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(spitarget_spi_target_load_packet_obj, 1, spitarget_spi_target_load_packet); + +//| def wait_transfer(self, *, timeout: float = -1) -> bool: +//| """Wait for an SPI transfer from the main device. +//| +//| :param float timeout: Timeout in seconds. Zero means wait forever, a negative value means check once +//| :return: True if the transfer is complete, or False if no response received before the timeout +//| """ +//| +//| +static mp_obj_t spitarget_spi_target_wait_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + mp_check_self(mp_obj_is_type(pos_args[0], &spitarget_spi_target_type)); + spitarget_spi_target_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + if (common_hal_spitarget_spi_target_deinited(self)) { + raise_deinited_error(); + } + enum { ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NEW_SMALL_INT(-1)} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + #if MICROPY_PY_BUILTINS_FLOAT + float f = mp_obj_get_float(args[ARG_timeout].u_obj) * 1000; + int timeout_ms = (int)f; + #else + int timeout_ms = mp_obj_get_int(args[ARG_timeout].u_obj) * 1000; + #endif + + bool forever = false; + uint64_t timeout_end = 0; + if (timeout_ms == 0) { + forever = true; + } else if (timeout_ms > 0) { + timeout_end = common_hal_time_monotonic_ms() + timeout_ms; + } + + do { + if (common_hal_spitarget_spi_target_transfer_is_finished(self)) { + common_hal_spitarget_spi_target_transfer_close(self); // implicitly discards error indicator code + return mp_const_true; + } + mp_hal_delay_us(10); + } while (forever || common_hal_time_monotonic_ms() < timeout_end); + + return mp_const_false; +} +static MP_DEFINE_CONST_FUN_OBJ_KW(spitarget_spi_target_wait_transfer_obj, 1, spitarget_spi_target_wait_transfer); + +static const mp_rom_map_elem_t spitarget_spi_target_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&spitarget_spi_target_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&spitarget_spi_target___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_load_packet), MP_ROM_PTR(&spitarget_spi_target_load_packet_obj) }, + { MP_ROM_QSTR(MP_QSTR_wait_transfer), MP_ROM_PTR(&spitarget_spi_target_wait_transfer_obj) }, + +}; + +static MP_DEFINE_CONST_DICT(spitarget_spi_target_locals_dict, spitarget_spi_target_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + spitarget_spi_target_type, + MP_QSTR_SPITarget, + MP_TYPE_FLAG_NONE, + make_new, spitarget_spi_target_make_new, + locals_dict, &spitarget_spi_target_locals_dict + ); diff --git a/shared-bindings/spitarget/SPITarget.h b/shared-bindings/spitarget/SPITarget.h new file mode 100644 index 0000000000000..a8501976a7f9a --- /dev/null +++ b/shared-bindings/spitarget/SPITarget.h @@ -0,0 +1,21 @@ +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H + +#include "py/obj.h" + +#include "common-hal/microcontroller/Pin.h" +#include "common-hal/spitarget/SPITarget.h" + +extern const mp_obj_type_t spitarget_spi_target_type; + +extern void common_hal_spitarget_spi_target_construct(spitarget_spi_target_obj_t *self, + const mcu_pin_obj_t *sck, const mcu_pin_obj_t *mosi, const mcu_pin_obj_t *miso, const mcu_pin_obj_t *ss); +extern void common_hal_spitarget_spi_target_deinit(spitarget_spi_target_obj_t *self); +extern bool common_hal_spitarget_spi_target_deinited(spitarget_spi_target_obj_t *self); + +extern void common_hal_spitarget_spi_target_transfer_start(spitarget_spi_target_obj_t *self, + uint8_t *mosi_packet, const uint8_t *miso_packet, size_t len); +extern bool common_hal_spitarget_spi_target_transfer_is_finished(spitarget_spi_target_obj_t *self); +extern int common_hal_spitarget_spi_target_transfer_close(spitarget_spi_target_obj_t *self); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_TARGET_H diff --git a/shared-bindings/spitarget/__init__.c b/shared-bindings/spitarget/__init__.c new file mode 100644 index 0000000000000..0fcf90ea34be6 --- /dev/null +++ b/shared-bindings/spitarget/__init__.c @@ -0,0 +1,89 @@ +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/spitarget/SPITarget.h" + +#include "py/runtime.h" + +//| """Serial Peripheral Interface protocol target +//| +//| The `spitarget` module contains classes to support an SPI target. +//| +//| Example that emulates an SPI analog-to-digital converter:: +//| +//| import board +//| import analogio +//| from spitarget import SPITarget +//| +//| ain0 = analogio.AnalogIn(board.A0) +//| ain1 = analogio.AnalogIn(board.A1) +//| selected_channel = ain0 +//| +//| def map_adc_channel(index): +//| return ain0 if (index == 0) else ain1 +//| +//| mosi_buffer = bytearray(2) +//| miso_buffer = bytearray(2) +//| with SPITarget(sck=board.D12, mosi=board.D13, miso=board.D11, ss=board.D10) as device: +//| while True: +//| # Convert analog signal to array of bytes +//| reading = selected_channel.value +//| miso_buffer[0] = (reading >> 8) & 0xFF +//| miso_buffer[1] = (reading) & 0xFF +//| # Send array of bytes over SPI to main +//| device.load_packet(mosi_buffer, miso_buffer) +//| while not device.wait_transfer(timeout=-1): +//| pass +//| # Handle command from main, which sets the ADC channel +//| selected_channel = map_adc_channel((mosi_buffer[0] << 8) | mosi_buffer[1]) +//| +//| Communicating with the ADC emulator from the REPL of an attached CircuitPython board might look like :: +//| +//| >>> import board +//| >>> import digitalio +//| >>> import busio +//| >>> import time +//| >>> +//| >>> ## setup +//| >>> spi = busio.SPI(board.SCK, board.MOSI, board.MISO) +//| >>> cs = digitalio.DigitalInOut(board.CS) +//| >>> cs.direction = digitalio.Direction.OUTPUT +//| >>> cs.value = True +//| >>> spi.try_lock() +//| True +//| >>> +//| >>> ## ADC command: read from A0 +//| >>> cs.value = False +//| >>> spi.write(bytearray([0, 0])) +//| >>> cs.value = True +//| >>> +//| >>> # wait for ADC to read a value +//| >>> +//| >>> ## get two-byte output from ADC +//| >>> adc_result = bytearray(2) +//| >>> cs.value = False +//| >>> spi.readinto(adc_result, write_value=1) +//| >>> cs.value = True +//| >>> list(adc_result) +//| [0, 255] +//| +//| """ + + + +static const mp_rom_map_elem_t spitarget_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_spitarget) }, + { MP_ROM_QSTR(MP_QSTR_SPITarget), MP_ROM_PTR(&spitarget_spi_target_type) }, +}; + +static MP_DEFINE_CONST_DICT(spitarget_module_globals, spitarget_module_globals_table); + +const mp_obj_module_t spitarget_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&spitarget_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_spitarget, spitarget_module); diff --git a/shared-bindings/ssl/SSLContext.c b/shared-bindings/ssl/SSLContext.c index 9c7f098cc4ac7..9546c50ed7c41 100644 --- a/shared-bindings/ssl/SSLContext.c +++ b/shared-bindings/ssl/SSLContext.c @@ -26,7 +26,6 @@ static mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args mp_arg_check_num(n_args, n_kw, 0, 1, false); ssl_sslcontext_obj_t *s = mp_obj_malloc(ssl_sslcontext_obj_t, &ssl_sslcontext_type); - common_hal_ssl_sslcontext_construct(s); return MP_OBJ_FROM_PTR(s); @@ -40,6 +39,7 @@ static mp_obj_t ssl_sslcontext_make_new(const mp_obj_type_t *type, size_t n_args //| needed to establish the certificate's authenticity. The keyfile string //| must point to a file containing the private key. //| """ +//| static void get_file_contents(mp_obj_t name_obj, mp_buffer_info_t *bufinfo) { mp_obj_t file = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), name_obj, MP_OBJ_NEW_QSTR(MP_QSTR_rb)); @@ -88,6 +88,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_load_cert_chain_obj, 1, ssl_ssl //| :param str cadata: A single CA certificate in PEM format. **Limitation**: CPython allows one //| or more certificates, but this implementation is limited to one. //| """ +//| static mp_obj_t ssl_sslcontext_load_verify_locations(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_cafile, ARG_capath, ARG_cadata }; static const mp_arg_t allowed_args[] = { @@ -117,6 +118,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_load_verify_locations_obj, 1, s //| def set_default_verify_paths(self) -> None: //| """Load a set of default certification authority (CA) certificates.""" +//| static mp_obj_t ssl_sslcontext_set_default_verify_paths(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -128,6 +130,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(ssl_sslcontext_set_default_verify_paths_obj, 1 //| check_hostname: bool //| """Whether to match the peer certificate's hostname.""" +//| static mp_obj_t ssl_sslcontext_get_check_hostname(mp_obj_t self_in) { ssl_sslcontext_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -153,11 +156,12 @@ MP_PROPERTY_GETSET(ssl_sslcontext_check_hostname_obj, //| sock: socketpool.Socket, //| *, //| server_side: bool = False, -//| server_hostname: Optional[str] = None +//| server_hostname: Optional[str] = None, //| ) -> ssl.SSLSocket: //| """Wraps the socket into a socket-compatible class that handles SSL negotiation. //| The socket must be of type SOCK_STREAM.""" //| +//| static mp_obj_t ssl_sslcontext_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_sock, ARG_server_side, ARG_server_hostname }; diff --git a/shared-bindings/ssl/SSLSocket.c b/shared-bindings/ssl/SSLSocket.c index 3ed4fa3662433..4418a8e48d9c9 100644 --- a/shared-bindings/ssl/SSLSocket.c +++ b/shared-bindings/ssl/SSLSocket.c @@ -29,18 +29,21 @@ //| def __hash__(self) -> int: //| """Returns a hash for the Socket.""" //| ... +//| // Provided by automatic inclusion of hash() // https://github.com/micropython/micropython/pull/10348 //| def __enter__(self) -> SSLSocket: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically closes the Socket when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... +//| static mp_obj_t ssl_sslsocket___exit__(size_t n_args, const mp_obj_t *args) { (void)n_args; common_hal_ssl_sslsocket_close(args[0]); @@ -52,6 +55,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ssl_sslsocket___exit___obj, 4, 4, ssl //| """Accept a connection on a listening socket of type SOCK_STREAM, //| creating a new socket of type SOCK_STREAM. //| Returns a tuple of (new_socket, remote_address)""" +//| static mp_obj_t ssl_sslsocket_accept(mp_obj_t self_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); return common_hal_ssl_sslsocket_accept(self); @@ -63,6 +67,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(ssl_sslsocket_accept_obj, ssl_sslsocket_accept) //| //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... +//| static mp_obj_t ssl_sslsocket_bind(mp_obj_t self_in, mp_obj_t addr_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -76,6 +81,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_sslsocket_bind_obj, ssl_sslsocket_bind); //| def close(self) -> None: //| """Closes this Socket""" +//| static mp_obj_t ssl_sslsocket_close(mp_obj_t self_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_ssl_sslsocket_close(self); @@ -88,6 +94,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(ssl_sslsocket_close_obj, ssl_sslsocket_close); //| //| :param ~tuple address: tuple of (remote_address, remote_port)""" //| ... +//| static mp_obj_t ssl_sslsocket_connect(mp_obj_t self_in, mp_obj_t addr_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_ssl_sslsocket_connect(self, addr_in); @@ -99,8 +106,9 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_sslsocket_connect_obj, ssl_sslsocket_connec //| def listen(self, backlog: int) -> None: //| """Set socket to listen for incoming connections //| -//| :param ~int backlog: length of backlog queue for waiting connetions""" +//| :param ~int backlog: length of backlog queue for waiting connections""" //| ... +//| static mp_obj_t ssl_sslsocket_listen(mp_obj_t self_in, mp_obj_t backlog_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -124,6 +132,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_sslsocket_listen_obj, ssl_sslsocket_listen) //| :param bytearray buffer: buffer to receive into //| :param int bufsize: optionally, a maximum number of bytes to read.""" //| ... +//| static mp_obj_t ssl_sslsocket_recv_into(size_t n_args, const mp_obj_t *args) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (common_hal_ssl_sslsocket_get_closed(self)) { @@ -162,6 +171,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ssl_sslsocket_recv_into_obj, 2, 3, ss //| //| :param ~bytes bytes: some bytes to send""" //| ... +//| static mp_obj_t ssl_sslsocket_send(mp_obj_t self_in, mp_obj_t buf_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_ssl_sslsocket_get_closed(self)) { @@ -204,6 +214,7 @@ static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ssl_sslsocket_setsockopt_obj, 4, 4, s //| :param ~int value: timeout in seconds. 0 means non-blocking. None means block indefinitely. //| """ //| ... +//| static mp_obj_t ssl_sslsocket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_ssl_sslsocket_settimeout(self, timeout_in); @@ -217,6 +228,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(ssl_sslsocket_settimeout_obj, ssl_sslsocket_set //| :param ~bool flag: False means non-blocking, True means block indefinitely.""" //| ... //| +//| // method socket.setblocking(flag) static mp_obj_t ssl_sslsocket_setblocking(mp_obj_t self_in, mp_obj_t blocking) { ssl_sslsocket_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/ssl/__init__.c b/shared-bindings/ssl/__init__.c index 9a5f94636a8df..51a3ad3cfc42a 100644 --- a/shared-bindings/ssl/__init__.c +++ b/shared-bindings/ssl/__init__.c @@ -17,17 +17,19 @@ //| |see_cpython_module| :mod:`cpython:ssl`. //| """ //| +//| //| def create_default_context() -> ssl.SSLContext: //| """Return the default SSLContext.""" //| ... //| +//| static mp_obj_t ssl_create_default_context(void) { ssl_sslcontext_obj_t *s = mp_obj_malloc(ssl_sslcontext_obj_t, &ssl_sslcontext_type); - common_hal_ssl_create_default_context(s); - return s; + + return MP_OBJ_FROM_PTR(s); } MP_DEFINE_CONST_FUN_OBJ_0(ssl_create_default_context_obj, ssl_create_default_context); diff --git a/shared-bindings/storage/__init__.c b/shared-bindings/storage/__init__.c index e046c11879744..14ec16f3096c7 100644 --- a/shared-bindings/storage/__init__.c +++ b/shared-bindings/storage/__init__.c @@ -27,6 +27,7 @@ //| `_. //| """ //| +//| //| def mount(filesystem: VfsFat, mount_path: str, *, readonly: bool = False) -> None: //| """Mounts the given filesystem object at the given path. //| @@ -38,6 +39,7 @@ //| """ //| ... //| +//| static mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_filesystem, ARG_mount_path, ARG_readonly }; static const mp_arg_t allowed_args[] = { @@ -52,15 +54,11 @@ static mp_obj_t storage_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t // get the mount point const char *mnt_str = mp_obj_str_get_str(args[ARG_mount_path].u_obj); - // Make sure we're given an object we can mount. - // TODO(tannewt): Make sure we have all the methods we need to operating it - // as a file system. + mp_obj_t vfs_obj = args[ARG_filesystem].u_obj; - mp_obj_t dest[2]; - mp_load_method_maybe(vfs_obj, MP_QSTR_mount, dest); - if (dest[0] == MP_OBJ_NULL) { - mp_raise_ValueError(MP_ERROR_TEXT("filesystem must provide mount method")); - } + + // Currently, the only supported filesystem is VfsFat. + mp_arg_validate_type(vfs_obj, &mp_fat_vfs_type, MP_QSTR_filesystem); common_hal_storage_mount(vfs_obj, mnt_str, args[ARG_readonly].u_bool); @@ -75,6 +73,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(storage_mount_obj, 0, storage_mount); //| This is the CircuitPython analog to the UNIX ``umount`` command.""" //| ... //| +//| static mp_obj_t storage_umount(mp_obj_t mnt_in) { if (mp_obj_is_str(mnt_in)) { common_hal_storage_umount_path(mp_obj_str_get_str(mnt_in)); @@ -90,10 +89,18 @@ MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount); //| mount_path: str, //| readonly: bool = False, //| *, -//| disable_concurrent_write_protection: bool = False +//| disable_concurrent_write_protection: bool = False, //| ) -> None: //| """Remounts the given path with new parameters. //| +//| This can always be done from boot.py. After boot, it can only be done when the host computer +//| doesn't have write access and CircuitPython isn't currently writing to the filesystem. An +//| exception will be raised if this is the case. Some host OSes allow you to eject a drive which +//| will allow for remounting. +//| +//| Remounting after USB is active may take a little time because it "ejects" the drive for one +//| query from the host. These queries happen every second or so. +//| //| :param str mount_path: The path to remount. //| :param bool readonly: True when the filesystem should be readonly to CircuitPython. //| :param bool disable_concurrent_write_protection: When True, the check that makes sure the @@ -102,6 +109,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(storage_umount_obj, storage_umount); //| filesystem will be corrupted.""" //| ... //| +//| static mp_obj_t storage_remount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mount_path, ARG_readonly, ARG_disable_concurrent_write_protection }; static const mp_arg_t allowed_args[] = { @@ -125,6 +133,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(storage_remount_obj, 0, storage_remount); //| """Retrieves the mount object associated with the mount path""" //| ... //| +//| static mp_obj_t storage_getmount(const mp_obj_t mnt_in) { return common_hal_storage_getmount(mp_obj_str_get_str(mnt_in)); } @@ -152,6 +161,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(storage_getmount_obj, storage_getmount); //| CircuitPython will restart on certain boards.""" //| ... //| +//| static mp_obj_t storage_erase_filesystem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_extended }; @@ -182,6 +192,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(storage_erase_filesystem_obj, 0, storage_erase_filesy //| Can be called in ``boot.py``, before USB is connected.""" //| ... //| +//| static mp_obj_t storage_disable_usb_drive(void) { #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC if (!common_hal_storage_disable_usb_drive()) { @@ -207,6 +218,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(storage_disable_usb_drive_obj, storage_disable_usb_dri //| """ //| ... //| +//| static mp_obj_t storage_enable_usb_drive(void) { #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC if (!common_hal_storage_enable_usb_drive()) { @@ -235,6 +247,7 @@ static const mp_rom_map_elem_t storage_module_globals_table[] = { //| """Create a new VfsFat filesystem around the given block device. //| //| :param block_device: Block device the the filesystem lives on""" +//| //| label: str //| """The filesystem label, up to 11 case-insensitive bytes. Note that //| this property can only be set when the device is writable by the @@ -290,6 +303,7 @@ static const mp_rom_map_elem_t storage_module_globals_table[] = { //| def umount(self) -> None: //| """Don't call this directly, call `storage.umount`.""" //| ... +//| //| { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) }, }; diff --git a/shared-bindings/storage/__init__.h b/shared-bindings/storage/__init__.h index 7ab5fc97bd7e4..6df604262956a 100644 --- a/shared-bindings/storage/__init__.h +++ b/shared-bindings/storage/__init__.h @@ -16,7 +16,7 @@ void common_hal_storage_umount_path(const char *path); void common_hal_storage_umount_object(mp_obj_t vfs_obj); void common_hal_storage_remount(const char *path, bool readonly, bool disable_concurrent_write_protection); mp_obj_t common_hal_storage_getmount(const char *path); -void common_hal_storage_erase_filesystem(bool extended); +MP_NORETURN void common_hal_storage_erase_filesystem(bool extended); bool common_hal_storage_disable_usb_drive(void); bool common_hal_storage_enable_usb_drive(void); diff --git a/shared-bindings/struct/__init__.c b/shared-bindings/struct/__init__.c index eded8b1a3daba..3f9fd40895ef0 100644 --- a/shared-bindings/struct/__init__.c +++ b/shared-bindings/struct/__init__.c @@ -26,12 +26,14 @@ //| Supported format codes: *b*, *B*, *x*, *h*, *H*, *i*, *I*, *l*, *L*, *q*, *Q*, //| *s*, *P*, *f*, *d* (the latter 2 depending on the floating-point support).""" //| +//| //| def calcsize(fmt: str) -> int: //| """Return the number of bytes needed to store the given fmt.""" //| ... //| +//| static mp_obj_t struct_calcsize(mp_obj_t fmt_in) { @@ -44,6 +46,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(struct_calcsize_obj, struct_calcsize); //| The return value is a bytes object encoding the values.""" //| ... //| +//| static mp_obj_t struct_pack(size_t n_args, const mp_obj_t *args) { mp_int_t size = MP_OBJ_SMALL_INT_VALUE(struct_calcsize(args[0])); @@ -62,6 +65,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_obj, 1, MP_OBJ_FUN_ARGS_MAX, str //| starting at offset. offset may be negative to count from the end of buffer.""" //| ... //| +//| static mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; @@ -89,6 +93,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_pack_into_obj, 3, MP_OBJ_FUN_ARGS_MAX //| required by the format.""" //| ... //| +//| static mp_obj_t struct_unpack(size_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; @@ -108,6 +113,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(struct_unpack_obj, 2, 3, struct_unpack); //| as the size required by the form.""" //| ... //| +//| static mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_format, ARG_buffer, ARG_offset }; diff --git a/shared-bindings/supervisor/RunReason.c b/shared-bindings/supervisor/RunReason.c index 5fc29fa27b6aa..3a0005a3dd3ac 100644 --- a/shared-bindings/supervisor/RunReason.c +++ b/shared-bindings/supervisor/RunReason.c @@ -29,6 +29,7 @@ MAKE_ENUM_VALUE(supervisor_run_reason_type, run_reason, REPL_RELOAD, RUN_REASON_ //| REPL_RELOAD: object //| """CircuitPython started due to the user typing CTRL-D in the REPL.""" //| +//| MAKE_ENUM_MAP(supervisor_run_reason) { MAKE_ENUM_MAP_ENTRY(run_reason, STARTUP), MAKE_ENUM_MAP_ENTRY(run_reason, AUTO_RELOAD), diff --git a/shared-bindings/supervisor/Runtime.c b/shared-bindings/supervisor/Runtime.c index 5c4754b85f2e4..20cfd2e82007a 100644 --- a/shared-bindings/supervisor/Runtime.c +++ b/shared-bindings/supervisor/Runtime.c @@ -20,8 +20,12 @@ #include "supervisor/shared/status_leds.h" #include "supervisor/shared/bluetooth/bluetooth.h" -#if CIRCUITPY_TINYUSB -#include "tusb.h" +#if CIRCUITPY_USB_DEVICE +#include "supervisor/usb.h" +#endif + +#if CIRCUITPY_DISPLAYIO +#include "shared-bindings/displayio/__init__.h" #endif static supervisor_run_reason_t _run_reason; @@ -42,12 +46,13 @@ static supervisor_run_reason_t _run_reason; //| """You cannot create an instance of `supervisor.Runtime`. //| Use `supervisor.runtime` to access the sole instance available.""" //| ... +//| //| usb_connected: bool //| """Returns the USB enumeration status (read-only).""" static mp_obj_t supervisor_runtime_get_usb_connected(mp_obj_t self) { #if CIRCUITPY_USB_DEVICE - return mp_obj_new_bool(tud_ready()); + return mp_obj_new_bool(usb_connected()); #else return mp_const_false; #endif @@ -202,6 +207,39 @@ MP_PROPERTY_GETSET(supervisor_runtime_rgb_status_brightness_obj, (mp_obj_t)&supervisor_runtime_get_rgb_status_brightness_obj, (mp_obj_t)&supervisor_runtime_set_rgb_status_brightness_obj); +#if CIRCUITPY_DISPLAYIO +//| display: displayio.AnyDisplay | None +//| """The primary configured displayio display, if any. +//| +//| If the board has a display that is hard coded, or that was explicitly set +//| in boot.py or code.py (including a previous run of code.py), it is +//| available here until it is released with ``displayio.release_displays()``. +//| +//| The display can be of any supported display type, such as `busdisplay.BusDisplay`. +//| +//| If no display is configured, this property is `None`. +//| +//| In a future release of CircuitPython, any display that is not the primary display +//| will be automatically released at the end of running a code file. +//| +//| On boards without displayio, this property is present but the value is always `None`.""" +//| +//| +static mp_obj_t supervisor_runtime_get_display(mp_obj_t self) { + return common_hal_displayio_get_primary_display(); +} +MP_DEFINE_CONST_FUN_OBJ_1(supervisor_runtime_get_display_obj, supervisor_runtime_get_display); +static mp_obj_t supervisor_runtime_set_display(mp_obj_t self, mp_obj_t new_primary_display) { + common_hal_displayio_set_primary_display(new_primary_display); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(supervisor_runtime_set_display_obj, supervisor_runtime_set_display); + +MP_PROPERTY_GETSET(supervisor_runtime_display_obj, + (mp_obj_t)&supervisor_runtime_get_display_obj, + (mp_obj_t)&supervisor_runtime_set_display_obj); +#endif + static const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_usb_connected), MP_ROM_PTR(&supervisor_runtime_usb_connected_obj) }, { MP_ROM_QSTR(MP_QSTR_serial_connected), MP_ROM_PTR(&supervisor_runtime_serial_connected_obj) }, @@ -211,6 +249,11 @@ static const mp_rom_map_elem_t supervisor_runtime_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_autoreload), MP_ROM_PTR(&supervisor_runtime_autoreload_obj) }, { MP_ROM_QSTR(MP_QSTR_ble_workflow), MP_ROM_PTR(&supervisor_runtime_ble_workflow_obj) }, { MP_ROM_QSTR(MP_QSTR_rgb_status_brightness), MP_ROM_PTR(&supervisor_runtime_rgb_status_brightness_obj) }, + #if CIRCUITPY_DISPLAYIO + { MP_ROM_QSTR(MP_QSTR_display), MP_ROM_PTR(&supervisor_runtime_display_obj) }, + #else + { MP_ROM_QSTR(MP_QSTR_display), MP_ROM_NONE }, + #endif }; static MP_DEFINE_CONST_DICT(supervisor_runtime_locals_dict, supervisor_runtime_locals_dict_table); diff --git a/shared-bindings/supervisor/SafeModeReason.c b/shared-bindings/supervisor/SafeModeReason.c index e2cbac3b9a7d5..ff85d8a3d5ceb 100644 --- a/shared-bindings/supervisor/SafeModeReason.c +++ b/shared-bindings/supervisor/SafeModeReason.c @@ -127,6 +127,7 @@ MAKE_ENUM_MAP(supervisor_safe_mode_reason) { //| WATCHDOG: object //| """An internal watchdog timer expired.""" +//| //| MAKE_ENUM_MAP_ENTRY(safe_mode_reason, WATCHDOG), }; diff --git a/shared-bindings/supervisor/StatusBar.c b/shared-bindings/supervisor/StatusBar.c index 46e7962cf0571..be109a6e2211b 100644 --- a/shared-bindings/supervisor/StatusBar.c +++ b/shared-bindings/supervisor/StatusBar.c @@ -26,6 +26,7 @@ //| """You cannot create an instance of `supervisor.StatusBar`. //| Use `supervisor.status_bar` to access the sole instance available.""" //| ... +//| //| console: bool //| """Whether status bar information is sent over the console (REPL) serial connection, @@ -65,6 +66,7 @@ MP_PROPERTY_GETSET(supervisor_status_bar_console_obj, //| Not available if `terminalio` is not available. //| """ //| +//| static mp_obj_t supervisor_status_bar_get_display(mp_obj_t self_in) { #if CIRCUITPY_STATUS_BAR && CIRCUITPY_TERMINALIO supervisor_status_bar_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/supervisor/__init__.c b/shared-bindings/supervisor/__init__.c index e09094ff88e72..a0a01f124f786 100644 --- a/shared-bindings/supervisor/__init__.c +++ b/shared-bindings/supervisor/__init__.c @@ -3,6 +3,7 @@ // SPDX-FileCopyrightText: Copyright (c) 2016-2017 Scott Shawcroft for Adafruit Industries // // SPDX-License-Identifier: MIT +#include #include #include "py/obj.h" @@ -20,13 +21,19 @@ #include "supervisor/usb.h" #endif +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/time/__init__.h" #include "shared-bindings/supervisor/Runtime.h" #include "shared-bindings/supervisor/StatusBar.h" +#include "shared-bindings/util.h" //| """Supervisor settings""" +//| //| runtime: Runtime //| """Runtime information, such as ``runtime.serial_connected`` @@ -40,11 +47,13 @@ //| the last exception name and location, and firmware version information. //| This object is the sole instance of `supervisor.StatusBar`.""" //| +//| //| def reload() -> None: //| """Reload the main Python code and run it (equivalent to hitting Ctrl-D at the REPL).""" //| ... //| +//| static mp_obj_t supervisor_reload(void) { reload_initiate(RUN_REASON_SUPERVISOR_RELOAD); return mp_const_none; @@ -54,11 +63,12 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload); //| def set_next_code_file( //| filename: Optional[str], //| *, +//| working_directory: Optional[str] = None, //| reload_on_success: bool = False, //| reload_on_error: bool = False, //| sticky_on_success: bool = False, //| sticky_on_error: bool = False, -//| sticky_on_reload: bool = False +//| sticky_on_reload: bool = False, //| ) -> None: //| """Set what file to run on the next vm run. //| @@ -92,9 +102,11 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_reload_obj, supervisor_reload); //| reset to the standard search sequence.""" //| ... //| +//| static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_filename, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, + { MP_QSTR_working_directory, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, { MP_QSTR_reload_on_success, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_reload_on_error, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_sticky_on_success, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, @@ -103,6 +115,7 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos }; struct { mp_arg_val_t filename; + mp_arg_val_t working_directory; mp_arg_val_t reload_on_success; mp_arg_val_t reload_on_error; mp_arg_val_t sticky_on_success; @@ -114,6 +127,11 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos if (!mp_obj_is_str_or_bytes(filename_obj) && filename_obj != mp_const_none) { mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_filename, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(filename_obj)->name); } + + mp_obj_t working_directory_obj = args.working_directory.u_obj; + if (!mp_obj_is_str_or_bytes(working_directory_obj) && working_directory_obj != mp_const_none) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_working_directory, MP_QSTR_str, MP_QSTR_None, mp_obj_get_type(working_directory_obj)->name); + } if (filename_obj == mp_const_none) { filename_obj = mp_const_empty_bytes; } @@ -135,18 +153,50 @@ static mp_obj_t supervisor_set_next_code_file(size_t n_args, const mp_obj_t *pos } size_t len; const char *filename = mp_obj_str_get_data(filename_obj, &len); + if (!path_exists(filename)) { + mp_raise_ValueError(MP_ERROR_TEXT("File not found")); + } + + size_t working_directory_len = 0; + const char *working_directory = NULL; + if (working_directory_obj != mp_const_none) { + working_directory = mp_obj_str_get_data(working_directory_obj, &working_directory_len); + if (!path_exists(working_directory)) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_working_directory); + } + } if (next_code_configuration != NULL) { port_free(next_code_configuration); next_code_configuration = NULL; } if (options != 0 || len != 0) { - next_code_configuration = port_malloc(sizeof(supervisor_next_code_info_t) + len + 1, false); + + size_t next_code_size = sizeof(supervisor_next_code_info_t) + len + 1; + if (working_directory_len > 0) { + next_code_size += working_directory_len + 1; + } + next_code_configuration = port_malloc(next_code_size, false); if (next_code_configuration == NULL) { - m_malloc_fail(sizeof(supervisor_next_code_info_t) + len + 1); + m_malloc_fail(next_code_size); + } + char *filename_ptr = (char *)next_code_configuration + sizeof(supervisor_next_code_info_t); + + // Copy filename + memcpy(filename_ptr, filename, len); + filename_ptr[len] = '\0'; + + char *working_directory_ptr = NULL; + // Copy working directory after filename if present + if (working_directory_len > 0) { + working_directory_ptr = filename_ptr + len + 1; + memcpy(working_directory_ptr, working_directory, working_directory_len); + working_directory_ptr[working_directory_len] = '\0'; } + // Set everything up last. We may have raised an exception early and we + // don't want to free the memory if we failed. + next_code_configuration->filename = filename_ptr; + next_code_configuration->working_directory = working_directory_ptr; next_code_configuration->options = options | SUPERVISOR_NEXT_CODE_OPT_NEWLY_SET; - memcpy(&next_code_configuration->filename, filename, len); - next_code_configuration->filename[len] = '\0'; } return mp_const_none; } @@ -194,6 +244,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_next_code_file_obj, 0, supervisor_set_ //| """ //| ... //| +//| mp_obj_t supervisor_ticks_ms(void) { uint64_t ticks_ms = common_hal_time_monotonic_ms(); return mp_obj_new_int((ticks_ms + 0x1fff0000) % (1 << 29)); @@ -210,6 +261,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_ticks_ms_obj, supervisor_ticks_ms); //| Only code (main or boot) runs are considered, not REPL runs.""" //| ... //| +//| static mp_obj_t supervisor_get_previous_traceback(void) { if (prev_traceback_string) { size_t len = strlen(prev_traceback_string); @@ -230,6 +282,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(supervisor_get_previous_traceback_obj, supervisor_get_ //| """Reset the CircuitPython serial terminal with new dimensions.""" //| ... //| +//| static mp_obj_t supervisor_reset_terminal(mp_obj_t x_pixels, mp_obj_t y_pixels) { #if CIRCUITPY_DISPLAYIO supervisor_stop_terminal(); @@ -258,6 +311,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(supervisor_reset_terminal_obj, supervisor_reset_termin //| """ //| ... //| +//| static mp_obj_t supervisor_set_usb_identification(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_IDENTIFICATION static const mp_arg_t allowed_args[] = { @@ -310,6 +364,68 @@ static mp_obj_t supervisor_set_usb_identification(size_t n_args, const mp_obj_t } MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_set_usb_identification_obj, 0, supervisor_set_usb_identification); +//| def get_setting(key: str, default: object=None) -> int | str | bool: +//| """ +//| Get and parse the value for the given ``key`` from the ``/settings.toml`` file. +//| If ``key`` is not found or ``settings.toml`` is not present, return the ``default`` value. +//| +//| :param str key: The setting key to retrieve +//| :return: The setting value as an ``int``, ``str``, or ``bool`` depending on the value in the file +//| +//| :raises ValueError: If the value cannot be parsed as a valid TOML value. +//| +//| The value must be parseable as one of these types: +//| +//| - ``str``: Double-quoted string. +//| The string may include Unicode characters, and ``\\u`` Unicode escapes. Backslash-escaped characters +//| ``\\b``, ``\\r``, ``\\n``, ``\\t``, ``\\v``, ``\\v`` are also allowed. +//| - ``int``: signed or unsigned integer +//| - lower-case boolean words ``true`` and ``false``. +//| The values are returned as Python ``True`` or ``False`` values. +//| +//| Example:: +//| +//| # settings.toml: +//| WIDTH = 42 +//| color = "red" +//| DEBUG = true +//| +//| import supervisor +//| print(supervisor.get_setting("WIDTH")) # prints 42 +//| print(supervisor.get_setting("color")) # prints 'red' +//| print(supervisor.get_setting("DEBUG")) # prints True +//| """ +//| ... +//| +static mp_obj_t supervisor_get_setting(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + #if CIRCUITPY_SETTINGS_TOML + enum { ARG_key, ARG_default }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_key, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_default, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args); + + const char *key = mp_obj_str_get_str(args[ARG_key].u_obj); + mp_obj_t value; + settings_err_t result = settings_get_obj(key, &value); + + switch (result) { + case SETTINGS_OK: + return value; + case SETTINGS_ERR_NOT_FOUND: + case SETTINGS_ERR_OPEN: + return args[ARG_default].u_obj; + default: + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_value); + } + #else + mp_raise_NotImplementedError(NULL); + #endif +} +MP_DEFINE_CONST_FUN_OBJ_KW(supervisor_get_setting_obj, 1, supervisor_get_setting); + static const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_supervisor) }, { MP_ROM_QSTR(MP_QSTR_runtime), MP_ROM_PTR(&common_hal_supervisor_runtime_obj) }, @@ -323,6 +439,7 @@ static const mp_rom_map_elem_t supervisor_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_set_next_code_file), MP_ROM_PTR(&supervisor_set_next_code_file_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&supervisor_ticks_ms_obj) }, { MP_ROM_QSTR(MP_QSTR_get_previous_traceback), MP_ROM_PTR(&supervisor_get_previous_traceback_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_setting), MP_ROM_PTR(&supervisor_get_setting_obj) }, { MP_ROM_QSTR(MP_QSTR_reset_terminal), MP_ROM_PTR(&supervisor_reset_terminal_obj) }, { MP_ROM_QSTR(MP_QSTR_set_usb_identification), MP_ROM_PTR(&supervisor_set_usb_identification_obj) }, { MP_ROM_QSTR(MP_QSTR_status_bar), MP_ROM_PTR(&shared_module_supervisor_status_bar_obj) }, diff --git a/shared-bindings/supervisor/__init__.h b/shared-bindings/supervisor/__init__.h index c442534072ae7..4be9667ef563a 100644 --- a/shared-bindings/supervisor/__init__.h +++ b/shared-bindings/supervisor/__init__.h @@ -6,6 +6,8 @@ #pragma once +#include +#include // #include "py/mpconfig.h" #include "py/obj.h" @@ -18,7 +20,8 @@ typedef struct { uint8_t options; - char filename[]; + const char *working_directory; + const char *filename; } supervisor_next_code_info_t; extern const super_runtime_obj_t common_hal_supervisor_runtime_obj; diff --git a/shared-bindings/synthio/Biquad.c b/shared-bindings/synthio/Biquad.c index 79a9fa4593f4d..55465fae02486 100644 --- a/shared-bindings/synthio/Biquad.c +++ b/shared-bindings/synthio/Biquad.c @@ -1,74 +1,210 @@ // This file is part of the CircuitPython project: https://circuitpython.org // -// SPDX-FileCopyrightText: Copyright (c) 2021 Artyom Skrobov +// SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries // // SPDX-License-Identifier: MIT -#include -#include - #include "py/enum.h" -#include "py/mperrno.h" -#include "py/obj.h" -#include "py/objnamedtuple.h" +#include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/synthio/Biquad.h" +#include "shared-bindings/util.h" -#include "shared-bindings/synthio/__init__.h" -#include "shared-bindings/synthio/LFO.h" -#include "shared-bindings/synthio/Math.h" -#include "shared-bindings/synthio/MidiTrack.h" -#include "shared-bindings/synthio/Note.h" -#include "shared-bindings/synthio/Synthesizer.h" - -#include "shared-module/synthio/LFO.h" +//| class FilterMode: +//| """The type of filter""" +//| +//| LOW_PASS: FilterMode +//| """A low-pass filter""" +//| HIGH_PASS: FilterMode +//| """A high-pass filter""" +//| BAND_PASS: FilterMode +//| """A band-pass filter""" +//| NOTCH: FilterMode +//| """A notch filter""" +//| LOW_SHELF: FilterMode +//| """A low shelf filter""" +//| HIGH_SHELF: FilterMode +//| """A high shelf filter""" +//| PEAKING_EQ: FilterMode +//| """A peaking equalizer filter""" +//| +//| -#define default_attack_time (MICROPY_FLOAT_CONST(0.1)) -#define default_decay_time (MICROPY_FLOAT_CONST(0.05)) -#define default_release_time (MICROPY_FLOAT_CONST(0.2)) -#define default_attack_level (MICROPY_FLOAT_CONST(1.)) -#define default_sustain_level (MICROPY_FLOAT_CONST(0.8)) +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, LOW_PASS, SYNTHIO_LOW_PASS); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, HIGH_PASS, SYNTHIO_HIGH_PASS); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, BAND_PASS, SYNTHIO_BAND_PASS); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, NOTCH, SYNTHIO_NOTCH); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, LOW_SHELF, SYNTHIO_LOW_SHELF); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, HIGH_SHELF, SYNTHIO_HIGH_SHELF); +MAKE_ENUM_VALUE(synthio_filter_mode_type, mode, PEAKING_EQ, SYNTHIO_PEAKING_EQ); -static const mp_arg_t biquad_properties[] = { - { MP_QSTR_a1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_a2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_b0, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_b1, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_b2, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, +MAKE_ENUM_MAP(synthio_filter_mode) { + MAKE_ENUM_MAP_ENTRY(mode, LOW_PASS), + MAKE_ENUM_MAP_ENTRY(mode, HIGH_PASS), + MAKE_ENUM_MAP_ENTRY(mode, BAND_PASS), + MAKE_ENUM_MAP_ENTRY(mode, NOTCH), + MAKE_ENUM_MAP_ENTRY(mode, LOW_SHELF), + MAKE_ENUM_MAP_ENTRY(mode, HIGH_SHELF), + MAKE_ENUM_MAP_ENTRY(mode, PEAKING_EQ), }; +static MP_DEFINE_CONST_DICT(synthio_filter_mode_locals_dict, synthio_filter_mode_locals_table); + +MAKE_PRINTER(synthio, synthio_filter_mode); + +MAKE_ENUM_TYPE(synthio, FilterMode, synthio_filter_mode); + +static synthio_filter_mode validate_synthio_filter_mode(mp_obj_t obj, qstr arg_name) { + return cp_enum_value(&synthio_filter_mode_type, obj, arg_name); +} + //| class Biquad: -//| def __init__(self, b0: float, b1: float, b2: float, a1: float, a2: float) -> None: -//| """Construct a normalized biquad filter object. +//| def __init__( +//| self, +//| mode: FilterMode, +//| frequency: BlockInput, +//| Q: BlockInput = 0.7071067811865475, +//| A: BlockInput = None, +//| ) -> None: +//| """Construct a biquad filter object with given settings. +//| +//| ``frequency`` gives the center frequency or corner frequency of the filter, +//| depending on the mode. //| -//| This implements the "direct form 1" biquad filter, where each coefficient -//| has been pre-divided by a0. +//| ``Q`` gives the gain or sharpness of the filter. //| -//| Biquad objects are usually constructed via one of the related methods on a `Synthesizer` object -//| rather than directly from coefficients. +//| ``A`` controls the gain of peaking and shelving filters according to the +//| formula ``A = 10^(dBgain/40)``. For other filter types it is ignored. //| -//| https://github.com/WebAudio/Audio-EQ-Cookbook/blob/main/Audio-EQ-Cookbook.txt -//| """ +//| Since ``frequency`` and ``Q`` are `BlockInput` objects, they can +//| be varied dynamically. Internally, this is evaluated as "direct form 1" +//| biquad filter. //| +//| The internal filter state x[] and y[] is not updated when the filter +//| coefficients change, and there is no theoretical justification for why +//| this should result in a stable filter output. However, in practice, +//| slowly varying the filter's characteristic frequency and sharpness +//| appears to work as you'd expect.""" +//| + +static const mp_arg_t biquad_properties[] = { + { MP_QSTR_mode, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_frequency, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_Q, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_A, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE } }, +}; + static mp_obj_t synthio_biquad_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_mode, ARG_frequency, ARG_Q }; + mp_arg_val_t args[MP_ARRAY_SIZE(biquad_properties)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(biquad_properties), biquad_properties, args); - for (size_t i = 0; i < MP_ARRAY_SIZE(biquad_properties); i++) { - args[i].u_obj = mp_obj_new_float(mp_arg_validate_type_float(args[i].u_obj, biquad_properties[i].qst)); + if (args[ARG_Q].u_obj == MP_OBJ_NULL) { + args[ARG_Q].u_obj = mp_obj_new_float(MICROPY_FLOAT_CONST(0.7071067811865475)); } - MP_STATIC_ASSERT(sizeof(mp_arg_val_t) == sizeof(mp_obj_t)); - return namedtuple_make_new(type_in, MP_ARRAY_SIZE(args), 0, &args[0].u_obj); + synthio_filter_mode mode = validate_synthio_filter_mode(args[ARG_mode].u_obj, MP_QSTR_mode); + mp_obj_t result = common_hal_synthio_biquad_new(mode); + properties_construct_helper(result, biquad_properties + 1, args + 1, MP_ARRAY_SIZE(biquad_properties) - 1); + return result; } -const mp_obj_namedtuple_type_t synthio_biquad_type_obj = { - NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_Biquad, synthio_biquad_make_new), - .n_fields = 5, - .fields = { - MP_QSTR_a1, - MP_QSTR_a2, - MP_QSTR_b0, - MP_QSTR_b1, - MP_QSTR_b2, - }, +//| +//| mode: FilterMode +//| """The mode of filter (read-only)""" +static mp_obj_t synthio_biquad_get_mode(mp_obj_t self_in) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + return cp_enum_find(&synthio_filter_mode_type, common_hal_synthio_biquad_get_mode(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_mode_obj, synthio_biquad_get_mode); + +MP_PROPERTY_GETTER(synthio_biquad_mode_obj, + (mp_obj_t)&synthio_biquad_get_mode_obj); + +//| +//| frequency: BlockInput +//| """The central frequency (in Hz) of the filter""" +static mp_obj_t synthio_biquad_get_frequency(mp_obj_t self_in) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_synthio_biquad_get_frequency(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_frequency_obj, synthio_biquad_get_frequency); + +static mp_obj_t synthio_biquad_set_frequency(mp_obj_t self_in, mp_obj_t arg) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_synthio_biquad_set_frequency(self, arg); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_frequency_obj, synthio_biquad_set_frequency); +MP_PROPERTY_GETSET(synthio_biquad_frequency_obj, + (mp_obj_t)&synthio_biquad_get_frequency_obj, + (mp_obj_t)&synthio_biquad_set_frequency_obj); + + +//| +//| Q: BlockInput +//| """The sharpness (Q) of the filter""" +//| +static mp_obj_t synthio_biquad_get_Q(mp_obj_t self_in) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_synthio_biquad_get_Q(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_Q_obj, synthio_biquad_get_Q); + +static mp_obj_t synthio_biquad_set_Q(mp_obj_t self_in, mp_obj_t arg) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_synthio_biquad_set_Q(self, arg); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_Q_obj, synthio_biquad_set_Q); +MP_PROPERTY_GETSET(synthio_biquad_Q_obj, + (mp_obj_t)&synthio_biquad_get_Q_obj, + (mp_obj_t)&synthio_biquad_set_Q_obj); + +//| +//| A: BlockInput +//| """The gain (A) of the filter +//| +//| This setting only has an effect for peaking and shelving EQ filters. It is related +//| to the filter gain according to the formula ``A = 10^(dBgain/40)``. +//| """ +//| +//| +static mp_obj_t synthio_biquad_get_A(mp_obj_t self_in) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_synthio_biquad_get_A(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(synthio_biquad_get_A_obj, synthio_biquad_get_A); + +static mp_obj_t synthio_biquad_set_A(mp_obj_t self_in, mp_obj_t arg) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_synthio_biquad_set_A(self, arg); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_biquad_set_A_obj, synthio_biquad_set_A); +MP_PROPERTY_GETSET(synthio_biquad_A_obj, + (mp_obj_t)&synthio_biquad_get_A_obj, + (mp_obj_t)&synthio_biquad_set_A_obj); + +static const mp_rom_map_elem_t synthio_biquad_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&synthio_biquad_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&synthio_biquad_frequency_obj) }, + { MP_ROM_QSTR(MP_QSTR_Q), MP_ROM_PTR(&synthio_biquad_Q_obj) }, + { MP_ROM_QSTR(MP_QSTR_A), MP_ROM_PTR(&synthio_biquad_A_obj) }, }; +static MP_DEFINE_CONST_DICT(synthio_biquad_locals_dict, synthio_biquad_locals_dict_table); + +static void biquad_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + (void)kind; + properties_print_helper(print, self_in, biquad_properties, MP_ARRAY_SIZE(biquad_properties)); +} + +MP_DEFINE_CONST_OBJ_TYPE( + synthio_biquad_type_obj, + MP_QSTR_Biquad, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, synthio_biquad_make_new, + locals_dict, &synthio_biquad_locals_dict, + print, biquad_print + ); diff --git a/shared-bindings/synthio/Biquad.h b/shared-bindings/synthio/Biquad.h index 2b40960fc5d3e..616488525f2de 100644 --- a/shared-bindings/synthio/Biquad.h +++ b/shared-bindings/synthio/Biquad.h @@ -7,9 +7,27 @@ #pragma once #include "py/obj.h" -#include "py/objnamedtuple.h" -extern const mp_obj_namedtuple_type_t synthio_biquad_type_obj; -mp_obj_t common_hal_synthio_new_lpf(mp_float_t w0, mp_float_t Q); -mp_obj_t common_hal_synthio_new_hpf(mp_float_t w0, mp_float_t Q); -mp_obj_t common_hal_synthio_new_bpf(mp_float_t w0, mp_float_t Q); +extern const mp_obj_type_t synthio_biquad_type_obj; +extern const mp_obj_type_t synthio_filter_mode_type; +typedef struct synthio_biquad synthio_biquad_t; + +typedef enum { + SYNTHIO_LOW_PASS, SYNTHIO_HIGH_PASS, SYNTHIO_BAND_PASS, SYNTHIO_NOTCH, + // filters beyond this line use the "A" parameter (in addition to f0 and Q) + SYNTHIO_PEAKING_EQ, SYNTHIO_LOW_SHELF, SYNTHIO_HIGH_SHELF +} synthio_filter_mode; + + +mp_obj_t common_hal_synthio_biquad_get_A(synthio_biquad_t *self); +void common_hal_synthio_biquad_set_A(synthio_biquad_t *self, mp_obj_t A); + +mp_obj_t common_hal_synthio_biquad_get_Q(synthio_biquad_t *self); +void common_hal_synthio_biquad_set_Q(synthio_biquad_t *self, mp_obj_t Q); + +mp_obj_t common_hal_synthio_biquad_get_frequency(synthio_biquad_t *self); +void common_hal_synthio_biquad_set_frequency(synthio_biquad_t *self, mp_obj_t frequency); + +synthio_filter_mode common_hal_synthio_biquad_get_mode(synthio_biquad_t *self); + +mp_obj_t common_hal_synthio_biquad_new(synthio_filter_mode mode); diff --git a/shared-bindings/synthio/LFO.c b/shared-bindings/synthio/LFO.c index 328050e783f51..2dfae22a57774 100644 --- a/shared-bindings/synthio/LFO.c +++ b/shared-bindings/synthio/LFO.c @@ -34,7 +34,7 @@ static const uint16_t triangle[] = {0, 32767, 0, -32767}; //| including indirectly via a `Note` or another intermediate LFO. //| //| Using the same LFO as an input to multiple other LFOs or Notes is OK, but -//| the result if an LFO is tied to multiple Synthtesizer objects is undefined. +//| the result if an LFO is tied to multiple `Synthesizer` objects is undefined. //| //| In the current implementation, LFOs are updated every 256 samples. This //| should be considered an implementation detail, though it affects how LFOs @@ -43,7 +43,7 @@ static const uint16_t triangle[] = {0, 32767, 0, -32767}; //| An LFO's ``value`` property is computed once when it is constructed, and then //| when its associated synthesizer updates it. //| -//| This means that for instance an LFO **created** with ``offset=1`` has ```value==1`` +//| This means that for instance an LFO **created** with ``offset=1`` has ``value==1`` //| immediately, but **updating** the ``offset`` property alone does not //| change ``value``; it only updates through an association with an active synthesizer. //| @@ -74,10 +74,11 @@ static const uint16_t triangle[] = {0, 32767, 0, -32767}; //| scale: BlockInput = 1.0, //| offset: BlockInput = 0.0, //| phase_offset: BlockInput = 0.0, -//| once=False, -//| interpolate=True -//| ): +//| once: bool = False, +//| interpolate: bool = True, +//| ) -> None: //| pass +//| static const mp_arg_t lfo_properties[] = { { MP_QSTR_waveform, MP_ARG_OBJ, {.u_obj = MP_ROM_NONE } }, { MP_QSTR_rate, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1) } }, @@ -102,17 +103,17 @@ static mp_obj_t synthio_lfo_make_new(const mp_obj_type_t *type_in, size_t n_args } self->waveform_obj = args[ARG_waveform].u_obj; - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, lfo_properties + 1, args + 1, MP_ARRAY_SIZE(lfo_properties) - 1); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); + properties_construct_helper(self_obj, lfo_properties + 1, args + 1, MP_ARRAY_SIZE(lfo_properties) - 1); // Force computation of the LFO's initial output synthio_global_rate_scale = 0; self->base.last_tick = synthio_global_tick - 1; synthio_block_slot_t slot; - synthio_block_assign_slot(MP_OBJ_FROM_PTR(result), &slot, MP_QSTR_self); + synthio_block_assign_slot(self_obj, &slot, MP_QSTR_self); (void)synthio_block_slot_get(&slot); - return result; + return self_obj; }; //| waveform: Optional[ReadableBuffer] @@ -268,9 +269,10 @@ MP_PROPERTY_GETTER(synthio_lfo_value_obj, //| -//| def retrigger(self): +//| def retrigger(self) -> None: //| """Reset the LFO's internal index to the start of the waveform. Most useful when it its `once` property is `True`.""" //| +//| static mp_obj_t synthio_lfo_retrigger(mp_obj_t self_in) { synthio_lfo_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_synthio_lfo_retrigger(self); diff --git a/shared-bindings/synthio/Math.c b/shared-bindings/synthio/Math.c index e2c7e40900a00..96857fb351373 100644 --- a/shared-bindings/synthio/Math.c +++ b/shared-bindings/synthio/Math.c @@ -36,6 +36,7 @@ MAKE_ENUM_VALUE(synthio_math_operation_type, math_op, ABS, OP_ABS); //| //| def __call__(self, a: BlockInput, b: BlockInput = 0.0, c: BlockInput = 1.0) -> Math: //| """A MathOperation enumeration value can be called to construct a Math block that performs that operation""" +//| //| SUM: "MathOperation" //| """Computes ``a+b+c``. For 2-input sum, set one argument to ``0.0``. To hold a control value for multiple subscribers, set two arguments to ``0.0``.""" //| @@ -78,6 +79,7 @@ MAKE_ENUM_VALUE(synthio_math_operation_type, math_op, ABS, OP_ABS); //| ABS: "MathOperation" //| """Returns the absolute value of ``a``.""" //| +//| MAKE_ENUM_MAP(synthio_math_operation) { MAKE_ENUM_MAP_ENTRY(math_op, SUM), MAKE_ENUM_MAP_ENTRY(math_op, ADD_SUB), @@ -121,7 +123,7 @@ MAKE_ENUM_TYPE(synthio, MathOperation, synthio_math_operation, //| including indirectly via a `Note` or another intermediate Math. //| //| Using the same Math as an input to multiple other Maths or Notes is OK, but -//| the result if an Math is tied to multiple Synthtesizer objects is undefined. +//| the result if an Math is tied to multiple `Synthesizer` objects is undefined. //| //| In the current implementation, Maths are updated every 256 samples. This //| should be considered an implementation detail. @@ -133,8 +135,9 @@ MAKE_ENUM_TYPE(synthio, MathOperation, synthio_math_operation, //| a: BlockInput, //| b: BlockInput = 0.0, //| c: BlockInput = 1.0, -//| ): +//| ) -> None: //| pass +//| static const mp_arg_t math_properties[] = { { MP_QSTR_operation, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = NULL } }, { MP_QSTR_a, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = NULL } }, @@ -154,10 +157,10 @@ static mp_obj_t synthio_math_make_new_common(mp_arg_val_t args[MP_ARRAY_SIZE(mat self->base.last_tick = synthio_global_tick; - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, math_properties, args, MP_ARRAY_SIZE(math_properties)); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); + properties_construct_helper(self_obj, math_properties, args, MP_ARRAY_SIZE(math_properties)); - return result; + return self_obj; }; //| a: BlockInput @@ -241,6 +244,7 @@ MP_PROPERTY_GETSET(synthio_math_operation_obj, //| value: float //| """The value of the oscillator (read-only)""" //| +//| static mp_obj_t synthio_math_get_value(mp_obj_t self_in) { synthio_math_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_float(common_hal_synthio_math_get_value(self)); diff --git a/shared-bindings/synthio/MidiTrack.c b/shared-bindings/synthio/MidiTrack.c index dee42770630f2..0304df12a8191 100644 --- a/shared-bindings/synthio/MidiTrack.c +++ b/shared-bindings/synthio/MidiTrack.c @@ -13,6 +13,7 @@ #include "shared-bindings/util.h" #include "shared-bindings/synthio/MidiTrack.h" #include "shared-bindings/synthio/__init__.h" +#include "shared-bindings/audiocore/__init__.h" //| class MidiTrack: //| """Simple MIDI synth""" @@ -52,6 +53,7 @@ //| pass //| print("stopped")""" //| ... +//| static mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_buffer, ARG_tempo, ARG_sample_rate, ARG_waveform, ARG_envelope }; static const mp_arg_t allowed_args[] = { @@ -68,7 +70,6 @@ static mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_a mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); synthio_miditrack_obj_t *self = mp_obj_malloc(synthio_miditrack_obj_t, &synthio_miditrack_type); - common_hal_synthio_miditrack_construct(self, (uint8_t *)bufinfo.buf, bufinfo.len, args[ARG_tempo].u_int, @@ -84,6 +85,7 @@ static mp_obj_t synthio_miditrack_make_new(const mp_obj_type_t *type, size_t n_a //| def deinit(self) -> None: //| """Deinitialises the MidiTrack and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t synthio_miditrack_deinit(mp_obj_t self_in) { synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_synthio_miditrack_deinit(self); @@ -92,43 +94,51 @@ static mp_obj_t synthio_miditrack_deinit(mp_obj_t self_in) { static MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_deinit_obj, synthio_miditrack_deinit); static void check_for_deinit(synthio_miditrack_obj_t *self) { - if (common_hal_synthio_miditrack_deinited(self)) { - raise_deinited_error(); - } + audiosample_check_for_deinit(&self->synth.base); } //| def __enter__(self) -> MidiTrack: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t synthio_miditrack_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_synthio_miditrack_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(synthio_miditrack___exit___obj, 4, 4, synthio_miditrack_obj___exit__); +//| +// Provided by context manager helper. //| sample_rate: int //| """32 bit value that tells how quickly samples are played in Hertz (cycles per second).""" //| -static mp_obj_t synthio_miditrack_obj_get_sample_rate(mp_obj_t self_in) { + +//| tempo: int +//| """Tempo of the streamed events, in MIDI ticks per second.""" +//| +static mp_obj_t synthio_miditrack_obj_get_tempo(mp_obj_t self_in) { synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_synthio_miditrack_get_sample_rate(self)); + return mp_obj_new_int(common_hal_synthio_miditrack_get_tempo(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_sample_rate_obj, synthio_miditrack_obj_get_sample_rate); +MP_DEFINE_CONST_FUN_OBJ_1(synthio_miditrack_get_tempo_obj, synthio_miditrack_obj_get_tempo); -MP_PROPERTY_GETTER(synthio_miditrack_sample_rate_obj, - (mp_obj_t)&synthio_miditrack_get_sample_rate_obj); +static mp_obj_t synthio_miditrack_obj_set_tempo(mp_obj_t self_in, mp_obj_t arg) { + synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + common_hal_synthio_miditrack_set_tempo(self, mp_obj_get_int(arg)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(synthio_miditrack_set_tempo_obj, synthio_miditrack_obj_set_tempo); +MP_PROPERTY_GETSET(synthio_miditrack_tempo_obj, + (mp_obj_t)&synthio_miditrack_get_tempo_obj, + (mp_obj_t)&synthio_miditrack_set_tempo_obj); //| error_location: Optional[int] //| """Offset, in bytes within the midi data, of a decoding error""" //| +//| static mp_obj_t synthio_miditrack_obj_get_error_location(mp_obj_t self_in) { synthio_miditrack_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -147,22 +157,19 @@ static const mp_rom_map_elem_t synthio_miditrack_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&synthio_miditrack_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&synthio_miditrack___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_miditrack_sample_rate_obj) }, { MP_ROM_QSTR(MP_QSTR_error_location), MP_ROM_PTR(&synthio_miditrack_error_location_obj) }, + { MP_ROM_QSTR(MP_QSTR_tempo), MP_ROM_PTR(&synthio_miditrack_tempo_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(synthio_miditrack_locals_dict, synthio_miditrack_locals_dict_table); static const audiosample_p_t synthio_miditrack_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_synthio_miditrack_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_synthio_miditrack_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_synthio_miditrack_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)synthio_miditrack_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)synthio_miditrack_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_miditrack_get_buffer_structure, }; MP_DEFINE_CONST_OBJ_TYPE( diff --git a/shared-bindings/synthio/MidiTrack.h b/shared-bindings/synthio/MidiTrack.h index 50a6c921cb659..cb154d3996b1a 100644 --- a/shared-bindings/synthio/MidiTrack.h +++ b/shared-bindings/synthio/MidiTrack.h @@ -14,8 +14,7 @@ extern const mp_obj_type_t synthio_miditrack_type; void common_hal_synthio_miditrack_construct(synthio_miditrack_obj_t *self, const uint8_t *buffer, uint32_t len, uint32_t tempo, uint32_t sample_rate, mp_obj_t waveform_obj, mp_obj_t filter_obj, mp_obj_t envelope_obj); void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self); -bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self); -uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self); -uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self); -uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self); mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self); + +mp_int_t common_hal_synthio_miditrack_get_tempo(synthio_miditrack_obj_t *self); +void common_hal_synthio_miditrack_set_tempo(synthio_miditrack_obj_t *self, mp_int_t value); diff --git a/shared-bindings/synthio/Note.c b/shared-bindings/synthio/Note.c index c886f106a4cfd..183c59d5fbd32 100644 --- a/shared-bindings/synthio/Note.c +++ b/shared-bindings/synthio/Note.c @@ -20,15 +20,15 @@ static const mp_arg_t note_properties[] = { { MP_QSTR_amplitude, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(1) } }, { MP_QSTR_bend, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, { MP_QSTR_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, - { MP_QSTR_waveform_loop_start, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, - { MP_QSTR_waveform_loop_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, + { MP_QSTR_waveform_loop_start, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_waveform_loop_end, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, { MP_QSTR_envelope, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, { MP_QSTR_filter, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, - { MP_QSTR_ring_frequency, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, - { MP_QSTR_ring_bend, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_ring_frequency, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_ring_bend, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, { MP_QSTR_ring_waveform, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_NONE } }, - { MP_QSTR_ring_waveform_loop_start, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(0) } }, - { MP_QSTR_ring_waveform_loop_end, MP_ARG_OBJ, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, + { MP_QSTR_ring_waveform_loop_start, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(0) } }, + { MP_QSTR_ring_waveform_loop_end, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_obj = MP_ROM_INT(SYNTHIO_WAVEFORM_SIZE) } }, }; //| class Note: //| def __init__( @@ -37,17 +37,17 @@ static const mp_arg_t note_properties[] = { //| frequency: float, //| panning: BlockInput = 0.0, //| waveform: Optional[ReadableBuffer] = None, -//| waveform_loop_start: int = 0, -//| waveform_loop_end: int = waveform_max_length, +//| waveform_loop_start: BlockInput = 0, +//| waveform_loop_end: BlockInput = waveform_max_length, //| envelope: Optional[Envelope] = None, -//| amplitude: BlockInput = 0.0, +//| amplitude: BlockInput = 1.0, //| bend: BlockInput = 0.0, //| filter: Optional[Biquad] = None, //| ring_frequency: float = 0.0, //| ring_bend: float = 0.0, //| ring_waveform: Optional[ReadableBuffer] = None, -//| ring_waveform_loop_start: int = 0, -//| ring_waveform_loop_end: int = waveform_max_length, +//| ring_waveform_loop_start: BlockInput = 0, +//| ring_waveform_loop_end: BlockInput = waveform_max_length, //| ) -> None: //| """Construct a Note object, with a frequency in Hz, and optional panning, waveform, envelope, tremolo (volume change) and bend (frequency change). //| @@ -55,16 +55,17 @@ static const mp_arg_t note_properties[] = { //| //| If the same Note object is played on multiple Synthesizer objects, the result is undefined. //| """ +//| static mp_obj_t synthio_note_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_val_t args[MP_ARRAY_SIZE(note_properties)]; mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(note_properties), note_properties, args); synthio_note_obj_t *self = mp_obj_malloc(synthio_note_obj_t, &synthio_note_type); + mp_obj_t self_obj = MP_OBJ_FROM_PTR(self); - mp_obj_t result = MP_OBJ_FROM_PTR(self); - properties_construct_helper(result, note_properties, args, MP_ARRAY_SIZE(note_properties)); + properties_construct_helper(self_obj, note_properties, args, MP_ARRAY_SIZE(note_properties)); - return result; + return self_obj; }; //| frequency: float @@ -198,21 +199,21 @@ MP_PROPERTY_GETSET(synthio_note_waveform_obj, (mp_obj_t)&synthio_note_get_waveform_obj, (mp_obj_t)&synthio_note_set_waveform_obj); -//| waveform_loop_start: int + + +//| waveform_loop_start: BlockInput //| """The sample index of where to begin looping waveform data. //| -//| Values outside the range ``0`` to ``waveform_max_length-1`` (inclusive) are rejected with a `ValueError`. -//| -//| Values greater than or equal to the actual waveform length are treated as 0.""" +//| The value is limited to the range ``0`` to ``len(waveform)-1`` (inclusive).""" static mp_obj_t synthio_note_get_waveform_loop_start(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_waveform_loop_start(self)); + return common_hal_synthio_note_get_waveform_loop_start(self); } MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_waveform_loop_start_obj, synthio_note_get_waveform_loop_start); static mp_obj_t synthio_note_set_waveform_loop_start(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_waveform_loop_start(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_waveform_loop_start(self, arg); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_waveform_loop_start_obj, synthio_note_set_waveform_loop_start); @@ -220,24 +221,22 @@ MP_PROPERTY_GETSET(synthio_note_waveform_loop_start_obj, (mp_obj_t)&synthio_note_get_waveform_loop_start_obj, (mp_obj_t)&synthio_note_set_waveform_loop_start_obj); -//| waveform_loop_end: int +//| waveform_loop_end: BlockInput //| """The sample index of where to end looping waveform data. //| -//| Values outside the range ``1`` to ``waveform_max_length`` (inclusive) are rejected with a `ValueError`. -//| -//| If the value is greater than the actual waveform length, or less than or equal to the loop start, the loop will occur at the end of the waveform. +//| The value is limited to the range ``waveform_loop_start+1`` to ``len(waveform)`` (inclusive). //| //| Use the `synthio.waveform_max_length` constant to set the loop point at the end of the wave form, no matter its length.""" //| static mp_obj_t synthio_note_get_waveform_loop_end(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_waveform_loop_end(self)); + return common_hal_synthio_note_get_waveform_loop_end(self); } MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_waveform_loop_end_obj, synthio_note_get_waveform_loop_end); static mp_obj_t synthio_note_set_waveform_loop_end(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_waveform_loop_end(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_waveform_loop_end(self, arg); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_waveform_loop_end_obj, synthio_note_set_waveform_loop_end); @@ -331,21 +330,19 @@ MP_PROPERTY_GETSET(synthio_note_ring_waveform_obj, (mp_obj_t)&synthio_note_get_ring_waveform_obj, (mp_obj_t)&synthio_note_set_ring_waveform_obj); -//| ring_waveform_loop_start: int +//| ring_waveform_loop_start: BlockInput //| """The sample index of where to begin looping waveform data. //| -//| Values outside the range ``0`` to ``waveform_max_length-1`` (inclusive) are rejected with a `ValueError`. -//| -//| Values greater than or equal to the actual waveform length are treated as 0.""" +//| The value is limited to the range ``0`` to ``len(ring_waveform)-1`` (inclusive).""" static mp_obj_t synthio_note_get_ring_waveform_loop_start(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_ring_waveform_loop_start(self)); + return common_hal_synthio_note_get_ring_waveform_loop_start(self); } MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_ring_waveform_loop_start_obj, synthio_note_get_ring_waveform_loop_start); static mp_obj_t synthio_note_set_ring_waveform_loop_start(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_ring_waveform_loop_start(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_ring_waveform_loop_start(self, arg); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_ring_waveform_loop_start_obj, synthio_note_set_ring_waveform_loop_start); @@ -353,24 +350,23 @@ MP_PROPERTY_GETSET(synthio_note_ring_waveform_loop_start_obj, (mp_obj_t)&synthio_note_get_ring_waveform_loop_start_obj, (mp_obj_t)&synthio_note_set_ring_waveform_loop_start_obj); -//| ring_waveform_loop_end: int +//| ring_waveform_loop_end: BlockInput //| """The sample index of where to end looping waveform data. //| -//| Values outside the range ``1`` to ``waveform_max_length`` (inclusive) are rejected with a `ValueError`. -//| -//| If the value is greater than the actual waveform length, or less than or equal to the loop start, the loop will occur at the end of the waveform. +//| The value is limited to the range ``ring_waveform_loop_start+1`` to ``len(ring_waveform)`` (inclusive). //| //| Use the `synthio.waveform_max_length` constant to set the loop point at the end of the wave form, no matter its length.""" //| +//| static mp_obj_t synthio_note_get_ring_waveform_loop_end(mp_obj_t self_in) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_synthio_note_get_ring_waveform_loop_end(self)); + return common_hal_synthio_note_get_ring_waveform_loop_end(self); } MP_DEFINE_CONST_FUN_OBJ_1(synthio_note_get_ring_waveform_loop_end_obj, synthio_note_get_ring_waveform_loop_end); static mp_obj_t synthio_note_set_ring_waveform_loop_end(mp_obj_t self_in, mp_obj_t arg) { synthio_note_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_synthio_note_set_ring_waveform_loop_end(self, mp_obj_get_int(arg)); + common_hal_synthio_note_set_ring_waveform_loop_end(self, arg); return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_2(synthio_note_set_ring_waveform_loop_end_obj, synthio_note_set_ring_waveform_loop_end); diff --git a/shared-bindings/synthio/Note.h b/shared-bindings/synthio/Note.h index 0ee450acfe467..707b9f2e10463 100644 --- a/shared-bindings/synthio/Note.h +++ b/shared-bindings/synthio/Note.h @@ -31,11 +31,11 @@ void common_hal_synthio_note_set_bend(synthio_note_obj_t *self, mp_obj_t value); mp_obj_t common_hal_synthio_note_get_waveform_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_waveform(synthio_note_obj_t *self, mp_obj_t value); -mp_int_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self); -void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in); +mp_obj_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self); +void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_obj_t value); -mp_int_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self); -void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in); +mp_obj_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self); +void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_obj_t value); mp_float_t common_hal_synthio_note_get_ring_frequency(synthio_note_obj_t *self); void common_hal_synthio_note_set_ring_frequency(synthio_note_obj_t *self, mp_float_t value); @@ -46,11 +46,11 @@ void common_hal_synthio_note_set_ring_bend(synthio_note_obj_t *self, mp_obj_t va mp_obj_t common_hal_synthio_note_get_ring_waveform_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_ring_waveform(synthio_note_obj_t *self, mp_obj_t value); -mp_int_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self); -void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in); +mp_obj_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self); +void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_obj_t value); -mp_int_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self); -void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in); +mp_obj_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self); +void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_obj_t value); mp_obj_t common_hal_synthio_note_get_envelope_obj(synthio_note_obj_t *self); void common_hal_synthio_note_set_envelope(synthio_note_obj_t *self, mp_obj_t value); diff --git a/shared-bindings/synthio/Synthesizer.c b/shared-bindings/synthio/Synthesizer.c index cd5c3847e64bf..35cc42a20371f 100644 --- a/shared-bindings/synthio/Synthesizer.c +++ b/shared-bindings/synthio/Synthesizer.c @@ -17,6 +17,7 @@ #include "shared-bindings/synthio/Synthesizer.h" #include "shared-bindings/synthio/LFO.h" #include "shared-bindings/synthio/__init__.h" +#include "shared-bindings/audiocore/__init__.h" //| NoteSequence = Sequence[Union[int, Note]] //| """A sequence of notes, which can each be integer MIDI note numbers or `Note` objects""" @@ -25,6 +26,7 @@ //| LFOOrLFOSequence = Union["LFO", Sequence["LFO"]] //| """An LFO or a sequence of LFOs""" //| +//| //| class Synthesizer: //| def __init__( //| self, @@ -47,6 +49,7 @@ //| :param ReadableBuffer waveform: A single-cycle waveform. Default is a 50% duty cycle square wave. If specified, must be a ReadableBuffer of type 'h' (signed 16 bit) //| :param Optional[Envelope] envelope: An object that defines the loudness of a note over time. The default envelope, `None` provides no ramping, voices turn instantly on and off. //| """ +//| static mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_sample_rate, ARG_channel_count, ARG_waveform, ARG_envelope }; static const mp_arg_t allowed_args[] = { @@ -59,7 +62,6 @@ static mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); synthio_synthesizer_obj_t *self = mp_obj_malloc(synthio_synthesizer_obj_t, &synthio_synthesizer_type); - common_hal_synthio_synthesizer_construct(self, args[ARG_sample_rate].u_int, args[ARG_channel_count].u_int, @@ -70,9 +72,7 @@ static mp_obj_t synthio_synthesizer_make_new(const mp_obj_type_t *type, size_t n } static void check_for_deinit(synthio_synthesizer_obj_t *self) { - if (common_hal_synthio_synthesizer_deinited(self)) { - raise_deinited_error(); - } + audiosample_check_for_deinit(&self->synth.base); } //| def press(self, /, press: NoteOrNoteSequence = ()) -> None: @@ -81,6 +81,7 @@ static void check_for_deinit(synthio_synthesizer_obj_t *self) { //| Pressing a note that was already pressed has no effect. //| //| :param NoteOrNoteSequence press: Any sequence of notes.""" +//| static mp_obj_t synthio_synthesizer_press(mp_obj_t self_in, mp_obj_t press) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -94,6 +95,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_press_obj, synthio_synthesi //| Releasing a note that was already released has no effect. //| //| :param NoteOrNoteSequence release: Any sequence of notes.""" +//| static mp_obj_t synthio_synthesizer_release(mp_obj_t self_in, mp_obj_t release) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -106,7 +108,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_release_obj, synthio_synthe //| self, //| release: NoteOrNoteSequence = (), //| press: NoteOrNoteSequence = (), -//| retrigger=LFOOrLFOSequence, +//| retrigger: LFOOrLFOSequence = (), //| ) -> None: //| """Start notes, stop them, and/or re-trigger some LFOs. //| @@ -127,6 +129,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_release_obj, synthio_synthe //| //| Note: for compatibility, ``release_then_press`` may be used as an alias //| for this function. This compatibility name will be removed in 9.0.""" +//| static mp_obj_t synthio_synthesizer_change(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_release, ARG_press, ARG_retrigger }; static const mp_arg_t allowed_args[] = { @@ -155,6 +158,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(synthio_synthesizer_change_obj, 1, synthio_syn //| attack phase with an initial amplitude of 0. //| //| :param NoteOrNoteSequence press: Any sequence of notes.""" +//| static mp_obj_t synthio_synthesizer_release_all_then_press(mp_obj_t self_in, mp_obj_t press) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -167,6 +171,7 @@ static MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_release_all_then_press_obj, // //| def release_all(self) -> None: //| """Turn any currently-playing notes off""" +//| static mp_obj_t synthio_synthesizer_release_all(mp_obj_t self_in) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -178,6 +183,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_release_all_obj, synthio_sy //| def deinit(self) -> None: //| """Deinitialises the object and releases any memory resources for reuse.""" //| ... +//| static mp_obj_t synthio_synthesizer_deinit(mp_obj_t self_in) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_synthio_synthesizer_deinit(self); @@ -188,18 +194,15 @@ static MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_deinit_obj, synthio_synthes //| def __enter__(self) -> Synthesizer: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t synthio_synthesizer_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_synthio_synthesizer_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(synthio_synthesizer___exit___obj, 4, 4, synthio_synthesizer_obj___exit__); +//| +// Provided by context manager helper. //| envelope: Optional[Envelope] //| """The envelope to apply to all notes. `None`, the default envelope, instantly turns notes on and off. The envelope may be changed dynamically, but it affects all notes (even currently playing notes)""" @@ -224,15 +227,6 @@ MP_PROPERTY_GETSET(synthio_synthesizer_envelope_obj, //| sample_rate: int //| """32 bit value that tells how quickly samples are played in Hertz (cycles per second).""" -static mp_obj_t synthio_synthesizer_obj_get_sample_rate(mp_obj_t self_in) { - synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); - check_for_deinit(self); - return MP_OBJ_NEW_SMALL_INT(common_hal_synthio_synthesizer_get_sample_rate(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_get_sample_rate_obj, synthio_synthesizer_obj_get_sample_rate); - -MP_PROPERTY_GETTER(synthio_synthesizer_sample_rate_obj, - (mp_obj_t)&synthio_synthesizer_get_sample_rate_obj); //| pressed: NoteSequence //| """A sequence of the currently pressed notes (read-only property). @@ -255,6 +249,7 @@ MP_PROPERTY_GETTER(synthio_synthesizer_pressed_obj, //| If the note is currently playing (including in the release phase), the returned value gives the current envelope state and the current envelope value. //| //| If the note is not playing on this synthesizer, returns the tuple ``(None, 0.0)``.""" +//| static mp_obj_t synthio_synthesizer_obj_note_info(mp_obj_t self_in, mp_obj_t note) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -273,6 +268,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(synthio_synthesizer_note_info_obj, synthio_synthesizer //| //| This property is read-only but its contents may be modified by e.g., calling ``synth.blocks.append()`` or ``synth.blocks.remove()``. It is initially an empty list.""" //| +//| static mp_obj_t synthio_synthesizer_obj_get_blocks(mp_obj_t self_in) { synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -283,118 +279,6 @@ MP_DEFINE_CONST_FUN_OBJ_1(synthio_synthesizer_get_blocks_obj, synthio_synthesize MP_PROPERTY_GETTER(synthio_synthesizer_blocks_obj, (mp_obj_t)&synthio_synthesizer_get_blocks_obj); -//| max_polyphony: int -//| """Maximum polyphony of the synthesizer (read-only class property)""" -//| - -//| def low_pass_filter(cls, frequency: float, q_factor: float = 0.7071067811865475) -> Biquad: -//| """Construct a low-pass filter with the given parameters. -//| -//| ``frequency``, called f0 in the cookbook, is the corner frequency in Hz -//| of the filter. -//| -//| ``q_factor``, called ``Q`` in the cookbook. Controls how peaked the response will be at the cutoff frequency. A large value makes the response more peaked. -//| """ - -enum passfilter_arg_e { ARG_f0, ARG_Q }; - -// M_PI is not part of the math.h standard and may not be defined -// And by defining our own we can ensure it uses the correct const format. -#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846) - -static const mp_arg_t passfilter_properties[] = { - { MP_QSTR_frequency, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_obj = MP_ROM_NONE} }, - { MP_QSTR_Q, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, -}; - -static mp_obj_t synthio_synthesizer_lpf(size_t n_pos, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[MP_ARRAY_SIZE(passfilter_properties)]; - - mp_obj_t self_in = pos_args[0]; - synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - mp_arg_parse_all(n_pos - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(passfilter_properties), passfilter_properties, args); - - mp_float_t f0 = mp_arg_validate_type_float(args[ARG_f0].u_obj, MP_QSTR_f0); - mp_float_t Q = - args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) : - mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q); - - mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI; - - return common_hal_synthio_new_lpf(w0, Q); - -} - -MP_DEFINE_CONST_FUN_OBJ_KW(synthio_synthesizer_lpf_fun_obj, 1, synthio_synthesizer_lpf); - -//| def high_pass_filter( -//| cls, frequency: float, q_factor: float = 0.7071067811865475 -//| ) -> Biquad: -//| """Construct a high-pass filter with the given parameters. -//| -//| ``frequency``, called f0 in the cookbook, is the corner frequency in Hz -//| of the filter. -//| -//| ``q_factor``, called ``Q`` in the cookbook. Controls how peaked the response will be at the cutoff frequency. A large value makes the response more peaked. -//| """ - -static mp_obj_t synthio_synthesizer_hpf(size_t n_pos, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[MP_ARRAY_SIZE(passfilter_properties)]; - - mp_obj_t self_in = pos_args[0]; - synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - mp_arg_parse_all(n_pos - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(passfilter_properties), passfilter_properties, args); - - mp_float_t f0 = mp_arg_validate_type_float(args[ARG_f0].u_obj, MP_QSTR_f0); - mp_float_t Q = - args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) : - mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q); - - mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI; - - return common_hal_synthio_new_hpf(w0, Q); - -} - -//| def band_pass_filter( -//| cls, frequency: float, q_factor: float = 0.7071067811865475 -//| ) -> Biquad: -//| """Construct a band-pass filter with the given parameters. -//| -//| ``frequency``, called f0 in the cookbook, is the center frequency in Hz -//| of the filter. -//| -//| ``q_factor``, called ``Q`` in the cookbook. Controls how peaked the response will be at the cutoff frequency. A large value makes the response more peaked. -//| -//| The coefficients are scaled such that the filter has a 0dB peak gain. -//| """ -//| - -MP_DEFINE_CONST_FUN_OBJ_KW(synthio_synthesizer_hpf_fun_obj, 1, synthio_synthesizer_hpf); - -static mp_obj_t synthio_synthesizer_bpf(size_t n_pos, const mp_obj_t *pos_args, mp_map_t *kw_args) { - mp_arg_val_t args[MP_ARRAY_SIZE(passfilter_properties)]; - - mp_obj_t self_in = pos_args[0]; - synthio_synthesizer_obj_t *self = MP_OBJ_TO_PTR(self_in); - - mp_arg_parse_all(n_pos - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(passfilter_properties), passfilter_properties, args); - - mp_float_t f0 = mp_arg_validate_type_float(args[ARG_f0].u_obj, MP_QSTR_f0); - mp_float_t Q = - args[ARG_Q].u_obj == MP_OBJ_NULL ? MICROPY_FLOAT_CONST(0.7071067811865475) : - mp_arg_validate_type_float(args[ARG_Q].u_obj, MP_QSTR_Q); - - mp_float_t w0 = f0 / self->synth.sample_rate * 2 * MP_PI; - - return common_hal_synthio_new_bpf(w0, Q); - -} - -MP_DEFINE_CONST_FUN_OBJ_KW(synthio_synthesizer_bpf_fun_obj, 1, synthio_synthesizer_bpf); - static const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_press), MP_ROM_PTR(&synthio_synthesizer_press_obj) }, @@ -405,29 +289,22 @@ static const mp_rom_map_elem_t synthio_synthesizer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_release_all_then_press), MP_ROM_PTR(&synthio_synthesizer_release_all_then_press_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&synthio_synthesizer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&synthio_synthesizer___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, - { MP_ROM_QSTR(MP_QSTR_low_pass_filter), MP_ROM_PTR(&synthio_synthesizer_lpf_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_high_pass_filter), MP_ROM_PTR(&synthio_synthesizer_hpf_fun_obj) }, - { MP_ROM_QSTR(MP_QSTR_band_pass_filter), MP_ROM_PTR(&synthio_synthesizer_bpf_fun_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_envelope), MP_ROM_PTR(&synthio_synthesizer_envelope_obj) }, - { MP_ROM_QSTR(MP_QSTR_sample_rate), MP_ROM_PTR(&synthio_synthesizer_sample_rate_obj) }, { MP_ROM_QSTR(MP_QSTR_max_polyphony), MP_ROM_INT(CIRCUITPY_SYNTHIO_MAX_CHANNELS) }, { MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&synthio_synthesizer_pressed_obj) }, { MP_ROM_QSTR(MP_QSTR_note_info), MP_ROM_PTR(&synthio_synthesizer_note_info_obj) }, { MP_ROM_QSTR(MP_QSTR_blocks), MP_ROM_PTR(&synthio_synthesizer_blocks_obj) }, + AUDIOSAMPLE_FIELDS, }; static MP_DEFINE_CONST_DICT(synthio_synthesizer_locals_dict, synthio_synthesizer_locals_dict_table); static const audiosample_p_t synthio_synthesizer_proto = { MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) - .sample_rate = (audiosample_sample_rate_fun)common_hal_synthio_synthesizer_get_sample_rate, - .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_synthio_synthesizer_get_bits_per_sample, - .channel_count = (audiosample_channel_count_fun)common_hal_synthio_synthesizer_get_channel_count, .reset_buffer = (audiosample_reset_buffer_fun)synthio_synthesizer_reset_buffer, .get_buffer = (audiosample_get_buffer_fun)synthio_synthesizer_get_buffer, - .get_buffer_structure = (audiosample_get_buffer_structure_fun)synthio_synthesizer_get_buffer_structure, }; MP_DEFINE_CONST_OBJ_TYPE( diff --git a/shared-bindings/synthio/Synthesizer.h b/shared-bindings/synthio/Synthesizer.h index 65e15ae88ad5b..ffadb433047fb 100644 --- a/shared-bindings/synthio/Synthesizer.h +++ b/shared-bindings/synthio/Synthesizer.h @@ -15,10 +15,6 @@ void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t envelope_obj); void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self); -bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self); -uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self); -uint8_t common_hal_synthio_synthesizer_get_bits_per_sample(synthio_synthesizer_obj_t *self); -uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj_t *self); void common_hal_synthio_synthesizer_release(synthio_synthesizer_obj_t *self, mp_obj_t to_release); void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_obj_t to_press); void common_hal_synthio_synthesizer_retrigger(synthio_synthesizer_obj_t *self, mp_obj_t to_retrigger); diff --git a/shared-bindings/synthio/__init__.c b/shared-bindings/synthio/__init__.c index fbc5cd559afb5..6a21834751b63 100644 --- a/shared-bindings/synthio/__init__.c +++ b/shared-bindings/synthio/__init__.c @@ -32,6 +32,8 @@ //| """ //| +//| +//| //| class EnvelopeState: //| ATTACK: EnvelopeState //| """The note is in its attack phase""" @@ -42,6 +44,7 @@ //| RELEASE: EnvelopeState //| """The note is in its release phase""" //| +//| MAKE_ENUM_VALUE(synthio_note_state_type, note_state, ATTACK, SYNTHIO_ENVELOPE_STATE_ATTACK); MAKE_ENUM_VALUE(synthio_note_state_type, note_state, DECAY, SYNTHIO_ENVELOPE_STATE_DECAY); MAKE_ENUM_VALUE(synthio_note_state_type, note_state, SUSTAIN, SYNTHIO_ENVELOPE_STATE_SUSTAIN); @@ -78,6 +81,7 @@ static const mp_arg_t envelope_properties[] = { //| A BlockInput can be any of the following types: `Math`, `LFO`, `builtins.float`, `None` (treated same as 0). //| """ //| +//| //| class Envelope: //| def __init__( //| self, @@ -102,6 +106,7 @@ static const mp_arg_t envelope_properties[] = { //| :param float attack_level: The level, in the range ``0.0`` to ``1.0`` of the peak volume of the attack phase //| :param float sustain_level: The level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase relative to the attack level //| """ +//| //| attack_time: float //| """The time in seconds it takes to ramp from 0 volume to attack_volume""" //| @@ -117,6 +122,7 @@ static const mp_arg_t envelope_properties[] = { //| sustain_level: float //| """The level, in the range ``0.0`` to ``1.0`` of the volume of the sustain phase relative to the attack level""" //| +//| static mp_obj_t synthio_envelope_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { mp_arg_val_t args[MP_ARRAY_SIZE(envelope_properties)]; @@ -194,6 +200,7 @@ const mp_obj_namedtuple_type_t synthio_envelope_type_obj = { //| print("stopped")""" //| ... //| +//| static mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_file, ARG_sample_rate, ARG_waveform, ARG_envelope }; static const mp_arg_t allowed_args[] = { @@ -236,7 +243,7 @@ static mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma } uint32_t track_size = (chunk_header[4] << 24) | (chunk_header[5] << 16) | (chunk_header[6] << 8) | chunk_header[7]; - uint8_t *buffer = m_malloc(track_size); + uint8_t *buffer = m_malloc_without_collect(track_size); if (f_read(&file->fp, buffer, track_size, &bytes_read) != FR_OK) { mp_raise_OSError(MP_EIO); } @@ -245,7 +252,6 @@ static mp_obj_t synthio_from_file(size_t n_args, const mp_obj_t *pos_args, mp_ma } synthio_miditrack_obj_t *result = mp_obj_malloc(synthio_miditrack_obj_t, &synthio_miditrack_type); - common_hal_synthio_miditrack_construct(result, buffer, track_size, tempo, args[ARG_sample_rate].u_int, args[ARG_waveform].u_obj, mp_const_none, @@ -265,6 +271,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(synthio_from_file_obj, 1, synthio_from_file); //| def midi_to_hz(midi_note: float) -> float: //| """Converts the given midi note (60 = middle C, 69 = concert A) to Hz""" //| +//| static mp_obj_t midi_to_hz(mp_obj_t arg) { mp_float_t note = mp_arg_validate_type_float(arg, MP_QSTR_note); @@ -277,6 +284,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(synthio_midi_to_hz_obj, midi_to_hz); //| //| 24/12 (2.0) corresponds to middle C, 33/12 (2.75) is concert A.""" //| +//| static mp_obj_t voct_to_hz(mp_obj_t arg) { mp_float_t note = mp_arg_validate_obj_float_range(arg, -11, 11, MP_QSTR_ctrl); @@ -291,7 +299,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(synthio_voct_to_hz_obj, voct_to_hz); #if CIRCUITPY_AUDIOCORE_DEBUG static mp_obj_t synthio_lfo_tick(size_t n, const mp_obj_t *args) { - shared_bindings_synthio_lfo_tick(48000); + shared_bindings_synthio_lfo_tick(48000, SYNTHIO_MAX_DUR); mp_obj_t result[n]; for (size_t i = 0; i < n; i++) { synthio_block_slot_t slot; @@ -307,6 +315,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR(synthio_lfo_tick_obj, 1, synthio_lfo_tick); static const mp_rom_map_elem_t synthio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_synthio) }, { MP_ROM_QSTR(MP_QSTR_Biquad), MP_ROM_PTR(&synthio_biquad_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_FilterMode), MP_ROM_PTR(&synthio_filter_mode_type) }, { MP_ROM_QSTR(MP_QSTR_Math), MP_ROM_PTR(&synthio_math_type) }, { MP_ROM_QSTR(MP_QSTR_MathOperation), MP_ROM_PTR(&synthio_math_operation_type) }, { MP_ROM_QSTR(MP_QSTR_MidiTrack), MP_ROM_PTR(&synthio_miditrack_type) }, diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index 1173cbbe244d8..72c43ba2dc152 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -16,23 +16,114 @@ #include "py/stream.h" #include "shared-bindings/fontio/BuiltinFont.h" +#if CIRCUITPY_LVFONTIO +#include "shared-bindings/lvfontio/OnDiskFont.h" +#endif + //| class Terminal: -//| """Display a character stream with a TileGrid +//| """Terminal manages tile indices and cursor position based on VT100 commands. The ``font`` should be +//| a `fontio.BuiltinFont` and the ``scroll_area`` TileGrid's bitmap should match the font's bitmap. +//| +//| Display a character stream with a TileGrid //| //| ASCII control: +//| //| * ``\\r`` - Move cursor to column 1 //| * ``\\n`` - Move cursor down a row //| * ``\\b`` - Move cursor left one if possible //| //| OSC control sequences: +//| //| * ``ESC ] 0; ESC \\`` - Set title bar to //| * ``ESC ] ####; ESC \\`` - Ignored //| //| VT100 control sequences: +//| //| * ``ESC [ K`` - Clear the remainder of the line +//| * ``ESC [ 0 K`` - Clear the remainder of the line +//| * ``ESC [ 1 K`` - Clear start of the line to cursor +//| * ``ESC [ 2 K`` - Clear the entire line //| * ``ESC [ #### D`` - Move the cursor to the left by #### //| * ``ESC [ 2 J`` - Erase the entire display //| * ``ESC [ nnnn ; mmmm H`` - Move the cursor to mmmm, nnnn. +//| * ``ESC [ H`` - Move the cursor to 0,0. +//| * ``ESC M`` - Move the cursor up one line, scrolling if necessary. +//| * ``ESC D`` - Move the cursor down one line, scrolling if necessary. +//| * ``ESC [ r`` - Disable scrolling range (set to fullscreen). +//| * ``ESC [ nnnn ; mmmm r`` - Set scrolling range between rows nnnn and mmmm. +//| * ``ESC [ ## m`` - Set the terminal display attributes. +//| * ``ESC [ ## ; ## m`` - Set the terminal display attributes. +//| * ``ESC [ ## ; ## ; ## m`` - Set the terminal display attributes. +//| +//| Supported Display attributes: +//| +//| +--------+------------+------------+ +//| | Color | Foreground | Background | +//| +========+============+============+ +//| | Reset | 0 | 0 | +//| +--------+------------+------------+ +//| | Black | 30 | 40 | +//| +--------+------------+------------+ +//| | Red | 31 | 41 | +//| +--------+------------+------------+ +//| | Green | 32 | 42 | +//| +--------+------------+------------+ +//| | Yellow | 33 | 43 | +//| +--------+------------+------------+ +//| | Blue | 34 | 44 | +//| +--------+------------+------------+ +//| | Magenta| 35 | 45 | +//| +--------+------------+------------+ +//| | Cyan | 36 | 46 | +//| +--------+------------+------------+ +//| | White | 37 | 47 | +//| +--------+------------+------------+ +//| +//| Example Usage: +//| +//| .. code-block:: python +//| +//| import time +//| import displayio +//| import supervisor +//| from displayio import Group, TileGrid +//| from terminalio import FONT, Terminal +//| +//| main_group = Group() +//| display = supervisor.runtime.display +//| font_bb = FONT.get_bounding_box() +//| screen_size = (display.width // font_bb[0], display.height // font_bb[1]) +//| char_size = FONT.get_bounding_box() +//| +//| palette = displayio.Palette(2) +//| palette[0] = 0x000000 +//| palette[1] = 0xffffff +//| +//| tilegrid = TileGrid( +//| bitmap=FONT.bitmap, width=screen_size[0], height=screen_size[1], +//| tile_width=char_size[0], tile_height=char_size[1], pixel_shader=palette) +//| +//| terminal = Terminal(tilegrid, FONT) +//| +//| main_group.append(tilegrid) +//| display.root_group = main_group +//| +//| message = "Hello World\\n" +//| terminal.write(message) +//| +//| print(terminal.cursor_x, terminal.cursor_y) +//| move_cursor = chr(27) + "[10;10H" +//| terminal.write(f"Moving the cursor\\n{move_cursor} To here") +//| +//| cursor_home = chr(27) + f"[{screen_size[1]};0H" +//| terminal.write(cursor_home) +//| i = 1 +//| while True: +//| terminal.write(f"Writing again {i}\\n") +//| i = i + 1 +//| time.sleep(1) +//| +//| //| """ //| //| def __init__( @@ -40,11 +131,10 @@ //| scroll_area: displayio.TileGrid, //| font: fontio.BuiltinFont, //| *, -//| status_bar: Optional[displayio.TileGrid] = None +//| status_bar: Optional[displayio.TileGrid] = None, //| ) -> None: -//| """Terminal manages tile indices and cursor position based on VT100 commands. The font should be -//| a `fontio.BuiltinFont` and the TileGrid's bitmap should match the font's bitmap.""" //| ... +//| static mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_scroll_area, ARG_font, ARG_status_bar }; @@ -62,14 +152,32 @@ static mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n status_bar = mp_arg_validate_type(args[ARG_status_bar].u_obj, &displayio_tilegrid_type, MP_QSTR_status_bar); } - fontio_builtinfont_t *font = mp_arg_validate_type(args[ARG_font].u_obj, &fontio_builtinfont_type, MP_QSTR_font); + mp_obj_t font = args[ARG_font].u_obj; - mp_arg_validate_int_min(scroll_area->width_in_tiles, 2, MP_QSTR_scroll_area_width); - mp_arg_validate_int_min(scroll_area->height_in_tiles, 2, MP_QSTR_scroll_area_height); + // Ensure the font is one of the supported types + bool valid_font = false; - terminalio_terminal_obj_t *self = mp_obj_malloc(terminalio_terminal_obj_t, &terminalio_terminal_type); + #if CIRCUITPY_FONTIO + if (mp_obj_is_type(font, &fontio_builtinfont_type)) { + valid_font = true; + } + #endif + + #if CIRCUITPY_LVFONTIO + if (mp_obj_is_type(font, &lvfontio_ondiskfont_type)) { + valid_font = true; + } + #endif + + if (!valid_font) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_font); + } + + mp_arg_validate_int_min(scroll_area->width_in_tiles * scroll_area->height_in_tiles, 2, MP_QSTR_scroll_area_area); + terminalio_terminal_obj_t *self = mp_obj_malloc(terminalio_terminal_obj_t, &terminalio_terminal_type); common_hal_terminalio_terminal_construct(self, scroll_area, font, status_bar); + return MP_OBJ_FROM_PTR(self); } @@ -82,6 +190,7 @@ static mp_obj_t terminalio_terminal_make_new(const mp_obj_type_t *type, size_t n //| :rtype: int or None""" //| ... //| +//| static mp_uint_t terminalio_terminal_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); const byte *buf = buf_in; @@ -89,6 +198,30 @@ static mp_uint_t terminalio_terminal_write(mp_obj_t self_in, const void *buf_in, return common_hal_terminalio_terminal_write(self, buf, size, errcode); } +//| cursor_x: int +//| """The x position of the cursor.""" +//| +static mp_obj_t terminalio_terminal_obj_get_cursor_x(mp_obj_t self_in) { + terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_terminalio_terminal_get_cursor_x(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(terminalio_terminal_get_cursor_x_obj, terminalio_terminal_obj_get_cursor_x); + +MP_PROPERTY_GETTER(terminalio_terminal_cursor_x_obj, + (mp_obj_t)&terminalio_terminal_get_cursor_x_obj); + +//| cursor_y: int +//| """The y position of the cursor.""" +//| +static mp_obj_t terminalio_terminal_obj_get_cursor_y(mp_obj_t self_in) { + terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_terminalio_terminal_get_cursor_y(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(terminalio_terminal_get_cursor_y_obj, terminalio_terminal_obj_get_cursor_y); + +MP_PROPERTY_GETTER(terminalio_terminal_cursor_y_obj, + (mp_obj_t)&terminalio_terminal_get_cursor_y_obj); + static mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) { terminalio_terminal_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_uint_t ret; @@ -107,7 +240,9 @@ static mp_uint_t terminalio_terminal_ioctl(mp_obj_t self_in, mp_uint_t request, static const mp_rom_map_elem_t terminalio_terminal_locals_dict_table[] = { // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_cursor_x), MP_ROM_PTR(&terminalio_terminal_cursor_x_obj) }, + { MP_ROM_QSTR(MP_QSTR_cursor_y), MP_ROM_PTR(&terminalio_terminal_cursor_y_obj) }, }; static MP_DEFINE_CONST_DICT(terminalio_terminal_locals_dict, terminalio_terminal_locals_dict_table); @@ -121,7 +256,7 @@ static const mp_stream_p_t terminalio_terminal_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( terminalio_terminal_type, MP_QSTR_Terminal, - MP_TYPE_FLAG_ITER_IS_ITERNEXT, + MP_TYPE_FLAG_ITER_IS_ITERNEXT | MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, make_new, terminalio_terminal_make_new, locals_dict, (mp_obj_dict_t *)&terminalio_terminal_locals_dict, iter, mp_stream_unbuffered_iter, diff --git a/shared-bindings/terminalio/Terminal.h b/shared-bindings/terminalio/Terminal.h index 893db4d131128..6613500ac2ecb 100644 --- a/shared-bindings/terminalio/Terminal.h +++ b/shared-bindings/terminalio/Terminal.h @@ -13,10 +13,13 @@ extern const mp_obj_type_t terminalio_terminal_type; extern void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, - displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, displayio_tilegrid_t *status_bar); + displayio_tilegrid_t *scroll_area, mp_obj_t font, displayio_tilegrid_t *status_bar); // Write characters. len is in characters NOT bytes! extern size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const uint8_t *data, size_t len, int *errcode); +extern uint16_t common_hal_terminalio_terminal_get_cursor_x(terminalio_terminal_obj_t *self); +extern uint16_t common_hal_terminalio_terminal_get_cursor_y(terminalio_terminal_obj_t *self); + extern bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self); diff --git a/shared-bindings/tilepalettemapper/TilePaletteMapper.c b/shared-bindings/tilepalettemapper/TilePaletteMapper.c new file mode 100644 index 0000000000000..c22ea47bf2652 --- /dev/null +++ b/shared-bindings/tilepalettemapper/TilePaletteMapper.c @@ -0,0 +1,180 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT +#include +#include +#include "shared/runtime/context_manager_helpers.h" +#include "py/binary.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/util.h" +#include "shared-bindings/displayio/Palette.h" +#include "shared-bindings/displayio/ColorConverter.h" +#include "shared-bindings/displayio/TileGrid.h" +#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" + +//| class TilePaletteMapper: +//| """Remaps color indices from the source bitmap to alternate indices on a +//| per-tile basis. This allows for altering coloring of tiles based on +//| their tilegrid location. It also allows for using a limited color +//| bitmap with a wider array of colors.""" +//| +//| def __init__( +//| self, palette: displayio.Palette, input_color_count: int +//| ) -> None: +//| """Create a TilePaletteMApper object to store a set of color mappings for tiles. +//| +//| :param Union[displayio.Palette, displayio.ColorConverter] pixel_shader: +//| The palette or ColorConverter to get mapped colors from. +//| :param int input_color_count: The number of colors in in the input bitmap.""" +//| + +static mp_obj_t tilepalettemapper_tilepalettemapper_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_pixel_shader, ARG_input_color_count }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_input_color_count, MP_ARG_INT | MP_ARG_REQUIRED }, + + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + mp_obj_t pixel_shader = args[ARG_pixel_shader].u_obj; + if (!mp_obj_is_type(pixel_shader, &displayio_palette_type) && !mp_obj_is_type(pixel_shader, &displayio_colorconverter_type)) { + mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_pixel_shader); + } + + tilepalettemapper_tilepalettemapper_t *self = mp_obj_malloc(tilepalettemapper_tilepalettemapper_t, &tilepalettemapper_tilepalettemapper_type); + common_hal_tilepalettemapper_tilepalettemapper_construct(self, pixel_shader, args[ARG_input_color_count].u_int); + + return MP_OBJ_FROM_PTR(self); +} + +//| width: int +//| """Width of the tile palette mapper in tiles.""" +static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_width(mp_obj_t self_in) { + tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_tilepalettemapper_tilepalettemapper_get_width(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_width_obj, tilepalettemapper_tilepalettemapper_obj_get_width); + +MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_width_obj, + (mp_obj_t)&tilepalettemapper_tilepalettemapper_get_width_obj); + +//| height: int +//| """Height of the tile palette mapper in tiles.""" +static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_height(mp_obj_t self_in) { + tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_tilepalettemapper_tilepalettemapper_get_height(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_height_obj, tilepalettemapper_tilepalettemapper_obj_get_height); + +MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_height_obj, + (mp_obj_t)&tilepalettemapper_tilepalettemapper_get_height_obj); + + +//| pixel_shader: Union[displayio.Palette, displayio.ColorConverter] +//| """The palette or ColorConverter that the mapper uses.""" +//| +static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_pixel_shader(mp_obj_t self_in) { + tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_pixel_shader_obj, tilepalettemapper_tilepalettemapper_obj_get_pixel_shader); + +MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_pixel_shader_obj, + (mp_obj_t)&tilepalettemapper_tilepalettemapper_get_pixel_shader_obj); + +//| tilegrid: displayio.TileGrid +//| """The TileGrid that the TilePaletteMapper is used with.""" +//| +static mp_obj_t tilepalettemapper_tilepalettemapper_obj_get_tilegrid(mp_obj_t self_in) { + tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in); + return common_hal_tilepalettemapper_tilepalettemapper_get_tilegrid(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(tilepalettemapper_tilepalettemapper_get_tilegrid_obj, tilepalettemapper_tilepalettemapper_obj_get_tilegrid); + +MP_PROPERTY_GETTER(tilepalettemapper_tilepalettemapper_tilegrid_obj, + (mp_obj_t)&tilepalettemapper_tilepalettemapper_get_tilegrid_obj); + +//| def __getitem__(self, index: Union[Tuple[int, int], int]) -> Tuple[int]: +//| """Returns the mapping for the given index. The index can either be an x,y tuple or an int equal +//| to ``y * width + x``. +//| +//| This allows you to:: +//| +//| print(tpm[0])""" +//| ... +//| +//| def __setitem__(self, index: Union[Tuple[int, int], int], value: List[int]) -> None: +//| """Sets the mapping at the given tile index. The index can either be an x,y tuple or an int equal +//| to ``y * width + x``. +//| +//| This allows you to:: +//| +//| tpm[0] = [1,0] +//| +//| or:: +//| +//| tpm[0,0] = [1,0]""" +//| ... +//| +//| +static mp_obj_t tilepalettemapper_subscr(mp_obj_t self_in, mp_obj_t index_obj, mp_obj_t value_obj) { + tilepalettemapper_tilepalettemapper_t *self = MP_OBJ_TO_PTR(self_in); + if (mp_obj_is_type(index_obj, &mp_type_slice)) { + mp_raise_NotImplementedError(MP_ERROR_TEXT("Slices not supported")); + } else { + uint16_t x = 0; + uint16_t y = 0; + if (mp_obj_is_small_int(index_obj)) { + mp_int_t i = MP_OBJ_SMALL_INT_VALUE(index_obj); + uint16_t width = common_hal_tilepalettemapper_tilepalettemapper_get_width(self); + x = i % width; + y = i / width; + } else { + mp_obj_t *items; + mp_obj_get_array_fixed_n(index_obj, 2, &items); + x = mp_obj_get_int(items[0]); + y = mp_obj_get_int(items[1]); + } + if (x >= common_hal_tilepalettemapper_tilepalettemapper_get_width(self) || + y >= common_hal_tilepalettemapper_tilepalettemapper_get_height(self)) { + mp_raise_IndexError(MP_ERROR_TEXT("Tile index out of bounds")); + } + + if (value_obj == MP_OBJ_SENTINEL) { + // load + return common_hal_tilepalettemapper_tilepalettemapper_get_mapping(self, x, y); + } else if (value_obj == mp_const_none) { + return MP_OBJ_NULL; // op not supported + } else { + size_t len = 0; + mp_obj_t *items; + mp_obj_list_get(value_obj, &len, &items); + mp_arg_validate_int_range(len, 0, self->input_color_count, MP_QSTR_mapping_length); + common_hal_tilepalettemapper_tilepalettemapper_set_mapping(self, x, y, len, items); + } + } + return mp_const_none; +} + + +static const mp_rom_map_elem_t tilepalettemapper_tilepalettemapper_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_width_obj) }, + { MP_ROM_QSTR(MP_QSTR_height), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_height_obj) }, + { MP_ROM_QSTR(MP_QSTR_pixel_shader), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_pixel_shader_obj) }, + { MP_ROM_QSTR(MP_QSTR_tilegrid), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_tilegrid_obj) }, +}; +static MP_DEFINE_CONST_DICT(tilepalettemapper_tilepalettemapper_locals_dict, tilepalettemapper_tilepalettemapper_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + tilepalettemapper_tilepalettemapper_type, + MP_QSTR_TilePaletteMapper, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, tilepalettemapper_tilepalettemapper_make_new, + locals_dict, &tilepalettemapper_tilepalettemapper_locals_dict, + subscr, tilepalettemapper_subscr, + iter, mp_obj_generic_subscript_getiter + ); diff --git a/shared-bindings/tilepalettemapper/TilePaletteMapper.h b/shared-bindings/tilepalettemapper/TilePaletteMapper.h new file mode 100644 index 0000000000000..ef0d949591722 --- /dev/null +++ b/shared-bindings/tilepalettemapper/TilePaletteMapper.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT +#include "shared-module/tilepalettemapper/TilePaletteMapper.h" + +extern const mp_obj_type_t tilepalettemapper_tilepalettemapper_type; + +void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_tilepalettemapper_t *self, + mp_obj_t paltte, uint16_t input_color_count); + + +uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_width(tilepalettemapper_tilepalettemapper_t *self); +uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettemapper_tilepalettemapper_t *self); +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(tilepalettemapper_tilepalettemapper_t *self); +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_tilegrid(tilepalettemapper_tilepalettemapper_t *self); +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y); +void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items); diff --git a/shared-bindings/tilepalettemapper/__init__.c b/shared-bindings/tilepalettemapper/__init__.c new file mode 100644 index 0000000000000..966de95076659 --- /dev/null +++ b/shared-bindings/tilepalettemapper/__init__.c @@ -0,0 +1,21 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks +// +// SPDX-License-Identifier: MIT +#include "py/obj.h" +#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" + + +static const mp_rom_map_elem_t tilepalettemapper_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_tilepalettemapper) }, + { MP_ROM_QSTR(MP_QSTR_TilePaletteMapper), MP_ROM_PTR(&tilepalettemapper_tilepalettemapper_type) }, +}; +static MP_DEFINE_CONST_DICT(tilepalettemapper_module_globals, tilepalettemapper_module_globals_table); + +const mp_obj_module_t tilepalettemapper_module = { + .base = {&mp_type_module }, + .globals = (mp_obj_dict_t *)&tilepalettemapper_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_tilepalettemapper, tilepalettemapper_module); diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index dbf626180358c..e19d97251bcb8 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -20,13 +20,14 @@ //| |see_cpython_module| :mod:`cpython:time`. //| """ //| +//| //| def monotonic() -> float: -//| """Returns an always increasing value of time with an unknown reference +//| """Returns an always increasing value of time, in fractional seconds, with an unknown reference //| point. Only use it to compare against other values from `time.monotonic()` //| during the same code run. //| //| On most boards, `time.monotonic()` converts a 64-bit millisecond tick counter -//| to a float. Floats on most boards are encoded in 30 bits internally, with +//| to seconds, as a float. Floats on most boards are encoded in 30 bits internally, with //| effectively 22 bits of precision. The float returned by `time.monotonic()` will //| accurately represent time to millisecond precision only up to 2**22 milliseconds //| (about 1.165 hours). @@ -43,6 +44,7 @@ //| :rtype: float""" //| ... //| +//| static mp_obj_t time_monotonic(void) { uint64_t ticks_ms = common_hal_time_monotonic_ms(); return mp_obj_new_float(uint64_to_float(ticks_ms) / MICROPY_FLOAT_CONST(1000.0)); @@ -55,6 +57,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic); //| :param float seconds: the time to sleep in fractional seconds""" //| ... //| +//| static mp_obj_t time_sleep(mp_obj_t seconds_o) { #if MICROPY_PY_BUILTINS_FLOAT mp_float_t seconds = mp_obj_get_float(seconds_o); @@ -80,6 +83,16 @@ static mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, s } //| class struct_time: +//| tm_year: int +//| tm_mon: int +//| tm_mday: int +//| tm_hour: int +//| tm_min: int +//| tm_sec: int +//| tm_wday: int +//| tm_yday: int +//| tm_isdst: int +//| //| def __init__(self, time_tuple: Sequence[int]) -> None: //| """Structure used to capture a date and time. Can be constructed from a `struct_time`, `tuple`, `list`, or `namedtuple` with 9 elements. //| @@ -96,6 +109,7 @@ static mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, s //| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown.""" //| ... //| +//| const mp_obj_namedtuple_type_t struct_time_type_obj = { NAMEDTUPLE_TYPE_BASE_AND_SLOTS_MAKE_NEW(MP_QSTR_struct_time, struct_time_make_new), .n_fields = 9, @@ -179,6 +193,7 @@ mp_obj_t MP_WEAK rtc_get_time_source_time(void) { //| :rtype: int""" //| ... //| +//| static mp_obj_t time_time(void) { timeutils_struct_time_t tm; struct_time_to_tm(rtc_get_time_source_time(), &tm); @@ -198,13 +213,14 @@ MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); //| :rtype: int""" //| ... //| +//| static mp_obj_t time_monotonic_ns(void) { uint64_t time64 = common_hal_time_monotonic_ns(); return mp_obj_new_int_from_ll((long long)time64); } MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns); -//| def localtime(secs: int) -> struct_time: +//| def localtime(secs: Optional[int] = None) -> struct_time: //| """Convert a time expressed in seconds since Jan 1, 1970 to a struct_time in //| local time. If secs is not provided or None, the current time as returned //| by time() is used. @@ -214,6 +230,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_ns_obj, time_monotonic_ns); //| :rtype: time.struct_time""" //| ... //| +//| static mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) { if (n_args == 0 || args[0] == mp_const_none) { return rtc_get_time_source_time(); @@ -251,6 +268,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime); //| :rtype: int""" //| ... //| +//| static mp_obj_t time_mktime(mp_obj_t t) { mp_obj_t *elem; size_t len; diff --git a/shared-bindings/touchio/TouchIn.c b/shared-bindings/touchio/TouchIn.c index d435ae250c800..2250e88f599f1 100644 --- a/shared-bindings/touchio/TouchIn.c +++ b/shared-bindings/touchio/TouchIn.c @@ -31,28 +31,38 @@ //| print("touched!")""" //| -//| def __init__(self, pin: microcontroller.Pin) -> None: +//| def __init__(self, pin: microcontroller.Pin, pull: Optional[digitalio.Pull] = None) -> None: //| """Use the TouchIn on the given pin. //| -//| :param ~microcontroller.Pin pin: the pin to read from""" +//| :param ~microcontroller.Pin pin: the pin to read from +//| :param Optional[digitalio.Pull] pull: specify external pull resistor type. If None, assume pull-down or chip-specific implementation that does not require a pull. +//| """ //| ... +//| static mp_obj_t touchio_touchin_make_new(const mp_obj_type_t *type, - size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check number of arguments - mp_arg_check_num(n_args, n_kw, 1, 1, false); + size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + + enum { ARG_pin, ARG_pull }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_OBJ | MP_ARG_REQUIRED }, + { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // 1st argument is the pin - const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0], MP_QSTR_pin); + const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[ARG_pin].u_obj, MP_QSTR_pin); + const digitalio_pull_t pull = validate_pull(args[ARG_pull].u_obj, MP_QSTR_pull); touchio_touchin_obj_t *self = mp_obj_malloc(touchio_touchin_obj_t, &touchio_touchin_type); - common_hal_touchio_touchin_construct(self, pin); + common_hal_touchio_touchin_construct(self, pin, pull); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } //| def deinit(self) -> None: //| """Deinitialises the TouchIn and releases any hardware resources for reuse.""" //| ... +//| static mp_obj_t touchio_touchin_deinit(mp_obj_t self_in) { touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_touchio_touchin_deinit(self); @@ -69,18 +79,15 @@ static void check_for_deinit(touchio_touchin_obj_t *self) { //| def __enter__(self) -> TouchIn: //| """No-op used by Context Managers.""" //| ... +//| // Provided by context manager helper. //| def __exit__(self) -> None: //| """Automatically deinitializes the hardware when exiting a context. See //| :ref:`lifetime-and-contextmanagers` for more info.""" //| ... -static mp_obj_t touchio_touchin_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - common_hal_touchio_touchin_deinit(args[0]); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(touchio_touchin___exit___obj, 4, 4, touchio_touchin_obj___exit__); +//| +// Provided by context manager helper. //| value: bool //| """Whether the touch pad is being touched or not. (read-only) @@ -125,6 +132,7 @@ MP_PROPERTY_GETTER(touchio_touchin_raw_value_obj, //| touch = touchio.TouchIn(board.A1) //| touch.threshold = 7300""" //| +//| static mp_obj_t touchio_touchin_obj_get_threshold(mp_obj_t self_in) { touchio_touchin_obj_t *self = MP_OBJ_TO_PTR(self_in); check_for_deinit(self); @@ -151,12 +159,12 @@ MP_PROPERTY_GETSET(touchio_touchin_threshold_obj, static const mp_rom_map_elem_t touchio_touchin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&touchio_touchin___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&default___exit___obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&touchio_touchin_deinit_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_value), MP_ROM_PTR(&touchio_touchin_value_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_raw_value), MP_ROM_PTR(&touchio_touchin_raw_value_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&touchio_touchin_threshold_obj)}, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&touchio_touchin_value_obj)}, + { MP_ROM_QSTR(MP_QSTR_raw_value), MP_ROM_PTR(&touchio_touchin_raw_value_obj)}, + { MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&touchio_touchin_threshold_obj)}, }; static MP_DEFINE_CONST_DICT(touchio_touchin_locals_dict, touchio_touchin_locals_dict_table); diff --git a/shared-bindings/touchio/TouchIn.h b/shared-bindings/touchio/TouchIn.h index 0ab510394792f..d9b34aa74e51e 100644 --- a/shared-bindings/touchio/TouchIn.h +++ b/shared-bindings/touchio/TouchIn.h @@ -7,6 +7,7 @@ #pragma once #include "common-hal/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" #if CIRCUITPY_TOUCHIO_USE_NATIVE #include "common-hal/touchio/TouchIn.h" @@ -16,7 +17,7 @@ extern const mp_obj_type_t touchio_touchin_type; -void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin); +void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin, digitalio_pull_t pull); void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self); bool common_hal_touchio_touchin_deinited(touchio_touchin_obj_t *self); bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self); diff --git a/shared-bindings/touchio/__init__.c b/shared-bindings/touchio/__init__.c index 804e55b4117d6..8f9e56d4bdb58 100644 --- a/shared-bindings/touchio/__init__.c +++ b/shared-bindings/touchio/__init__.c @@ -28,6 +28,10 @@ //| For more information about working with the `touchio` module in CircuitPython, //| see `this Learn guide page `_. //| +//| **Limitations**: `touchio` on RP2350 must have a pull-up resistor to 3.3V +//| instead of ground and set the ``pull=Pull.UP`` parameter when constructing +//| a `TouchIn` object, due to GPIO hardware limitations. +//| //| Example:: //| //| import touchio @@ -37,7 +41,8 @@ //| print(touch_pin.value) //| //| This example will initialize the the device, and print the -//| :py:data:`~touchio.TouchIn.value`.""" +//| :py:data:`~touchio.TouchIn.value`. +//| """ static const mp_rom_map_elem_t touchio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_touchio) }, diff --git a/shared-bindings/traceback/__init__.c b/shared-bindings/traceback/__init__.c index d1cf33070502a..ca1e6fe976a4f 100644 --- a/shared-bindings/traceback/__init__.c +++ b/shared-bindings/traceback/__init__.c @@ -16,8 +16,10 @@ //| //| |see_cpython_module| :mod:`cpython:traceback`. //| """ +//| //| ... //| +//| static void traceback_exception_common(bool is_print_exception, mp_print_t *print, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_exc, ARG_value, ARG_tb, ARG_limit, ARG_file, ARG_chain }; @@ -133,6 +135,7 @@ static void traceback_exception_common(bool is_print_exception, mp_print_t *prin //| :param bool chain: If `True` then chained exceptions will be printed. //| """ //| +//| static mp_obj_t traceback_format_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_print_t print; vstr_t vstr; @@ -176,6 +179,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(traceback_format_exception_obj, 0, traceback_f //| """ //| ... //| +//| static mp_obj_t traceback_print_exception(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { mp_print_t print = mp_plat_print; diff --git a/shared-bindings/uheap/__init__.c b/shared-bindings/uheap/__init__.c index 0170c56c04b58..a46ff7625973e 100644 --- a/shared-bindings/uheap/__init__.c +++ b/shared-bindings/uheap/__init__.c @@ -13,12 +13,14 @@ //| """Heap size analysis""" //| +//| //| def info(object: object) -> int: //| """Prints memory debugging info for the given object and returns the //| estimated size.""" //| ... //| +//| static mp_obj_t uheap_info(mp_obj_t obj) { uint32_t size = shared_module_uheap_info(obj); diff --git a/shared-bindings/usb/__init__.c b/shared-bindings/usb/__init__.c index d1a61be7bc4fd..ea05229984c97 100644 --- a/shared-bindings/usb/__init__.c +++ b/shared-bindings/usb/__init__.c @@ -10,6 +10,7 @@ #include "shared-bindings/usb/__init__.h" #include "shared-bindings/usb/core/__init__.h" +#include "shared-bindings/usb/util/__init__.h" #include "supervisor/usb.h" //| """PyUSB-compatible USB host API @@ -21,6 +22,7 @@ static mp_rom_map_elem_t usb_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usb) }, { MP_ROM_QSTR(MP_QSTR_core), MP_OBJ_FROM_PTR(&usb_core_module) }, + { MP_ROM_QSTR(MP_QSTR_util), MP_OBJ_FROM_PTR(&usb_util_module) }, }; static MP_DEFINE_CONST_DICT(usb_module_globals, usb_module_globals_table); diff --git a/shared-bindings/usb/core/Device.c b/shared-bindings/usb/core/Device.c index 813b89a896c59..683115a842102 100644 --- a/shared-bindings/usb/core/Device.c +++ b/shared-bindings/usb/core/Device.c @@ -39,6 +39,7 @@ #include "py/objproperty.h" #include "shared-bindings/usb/core/Device.h" +#include "shared-bindings/util.h" #include "py/runtime.h" //| class Device: @@ -47,11 +48,30 @@ //| `usb.core.find`. //| """ //| ... +//| + +static void check_for_deinit(usb_core_device_obj_t *self) { + if (common_hal_usb_core_device_deinited(self)) { + raise_deinited_error(); + } +} + +//| def __del__(self) -> None: +//| """Closes any resources used for this device.""" +//| ... +//| +static mp_obj_t usb_core_device_deinit(mp_obj_t self_in) { + usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_usb_core_device_deinit(self); + return mp_const_none; +} +static MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_deinit_obj, usb_core_device_deinit); //| idVendor: int //| """The USB vendor ID of the device""" static mp_obj_t usb_core_device_obj_get_idVendor(mp_obj_t self_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_usb_core_device_get_idVendor(self)); } MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_idVendor_obj, usb_core_device_obj_get_idVendor); @@ -63,6 +83,7 @@ MP_PROPERTY_GETTER(usb_core_device_idVendor_obj, //| """The USB product ID of the device""" static mp_obj_t usb_core_device_obj_get_idProduct(mp_obj_t self_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return MP_OBJ_NEW_SMALL_INT(common_hal_usb_core_device_get_idProduct(self)); } MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_idProduct_obj, usb_core_device_obj_get_idProduct); @@ -74,6 +95,7 @@ MP_PROPERTY_GETTER(usb_core_device_idProduct_obj, //| """The USB device's serial number string.""" static mp_obj_t usb_core_device_obj_get_serial_number(mp_obj_t self_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return common_hal_usb_core_device_get_serial_number(self); } MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_serial_number_obj, usb_core_device_obj_get_serial_number); @@ -85,6 +107,7 @@ MP_PROPERTY_GETTER(usb_core_device_serial_number_obj, //| """The USB device's product string.""" static mp_obj_t usb_core_device_obj_get_product(mp_obj_t self_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return common_hal_usb_core_device_get_product(self); } MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_product_obj, usb_core_device_obj_get_product); @@ -94,8 +117,10 @@ MP_PROPERTY_GETTER(usb_core_device_product_obj, //| manufacturer: str //| """The USB device's manufacturer string.""" +//| static mp_obj_t usb_core_device_obj_get_manufacturer(mp_obj_t self_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); return common_hal_usb_core_device_get_manufacturer(self); } MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_manufacturer_obj, usb_core_device_obj_get_manufacturer); @@ -103,7 +128,48 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_manufacturer_obj, usb_core_device_ MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj, (mp_obj_t)&usb_core_device_get_manufacturer_obj); -//| def set_configuration(self, configuration=1): +//| bus: int +//| """The bus number of the root hub this device is connected to.""" +//| +static mp_obj_t usb_core_device_obj_get_bus(mp_obj_t self_in) { + usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_usb_core_device_get_bus(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_bus_obj, usb_core_device_obj_get_bus); + +MP_PROPERTY_GETTER(usb_core_device_bus_obj, + (mp_obj_t)&usb_core_device_get_bus_obj); + +//| port_numbers: tuple[int] | None +//| """The port topology of the devices location. None when connected to the +//| root port (aka bus).""" +//| +static mp_obj_t usb_core_device_obj_get_port_numbers(mp_obj_t self_in) { + usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return common_hal_usb_core_device_get_port_numbers(self); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_port_numbers_obj, usb_core_device_obj_get_port_numbers); + +MP_PROPERTY_GETTER(usb_core_device_port_numbers_obj, + (mp_obj_t)&usb_core_device_get_port_numbers_obj); + + +//| speed: int +//| """The speed of the device. One of `usb.util.SPEED_LOW`, `usb.util.SPEED_FULL`, `usb.util.SPEED_HIGH` or 0 for unknown.""" +//| +static mp_obj_t usb_core_device_obj_get_speed(mp_obj_t self_in) { + usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return MP_OBJ_NEW_SMALL_INT(common_hal_usb_core_device_get_speed(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(usb_core_device_get_speed_obj, usb_core_device_obj_get_speed); + +MP_PROPERTY_GETTER(usb_core_device_speed_obj, + (mp_obj_t)&usb_core_device_get_speed_obj); + +//| def set_configuration(self, configuration: int = 1) -> None: //| """Set the active configuration. //| //| The configuration parameter is the bConfigurationValue field of the @@ -113,12 +179,14 @@ MP_PROPERTY_GETTER(usb_core_device_manufacturer_obj, //| without arguments is enough to get the device ready. //| """ //| ... +//| static mp_obj_t usb_core_device_set_configuration(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_configuration }; static const mp_arg_t allowed_args[] = { { MP_QSTR_configuration, MP_ARG_INT, {.u_int = 1} }, }; usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -136,6 +204,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_device_set_configuration_obj, 1, usb_core_de //| :returns: the number of bytes written //| """ //| ... +//| static mp_obj_t usb_core_device_write(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_endpoint, ARG_data, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -144,6 +213,7 @@ static mp_obj_t usb_core_device_write(size_t n_args, const mp_obj_t *pos_args, m { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 0} }, }; usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -166,6 +236,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_device_write_obj, 2, usb_core_device_write); //| :returns: the number of bytes read //| """ //| ... +//| static mp_obj_t usb_core_device_read(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_endpoint, ARG_size_or_buffer, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -174,6 +245,7 @@ static mp_obj_t usb_core_device_read(size_t n_args, const mp_obj_t *pos_args, mp { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 0} }, }; usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -211,6 +283,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_device_read_obj, 2, usb_core_device_read); //| number of bytes read. //| """ //| ... +//| static mp_obj_t usb_core_device_ctrl_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bmRequestType, ARG_bRequest, ARG_wValue, ARG_wIndex, ARG_data_or_wLength, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -222,6 +295,7 @@ static mp_obj_t usb_core_device_ctrl_transfer(size_t n_args, const mp_obj_t *pos { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 0} }, }; usb_core_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -252,8 +326,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_core_device_ctrl_transfer_obj, 2, usb_core_device //| :param int interface: the device interface number to check //| """ //| ... +//| static mp_obj_t usb_core_device_is_kernel_driver_active(mp_obj_t self_in, mp_obj_t interface_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); mp_int_t interface = mp_obj_get_int(interface_in); bool active = common_hal_usb_core_device_is_kernel_driver_active(self, interface); return mp_obj_new_bool(active); @@ -268,8 +344,10 @@ MP_DEFINE_CONST_FUN_OBJ_2(usb_core_device_is_kernel_driver_active_obj, usb_core_ //| :param int interface: the device interface number to stop CircuitPython on //| """ //| ... +//| static mp_obj_t usb_core_device_detach_kernel_driver(mp_obj_t self_in, mp_obj_t interface_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); mp_int_t interface = mp_obj_get_int(interface_in); common_hal_usb_core_device_detach_kernel_driver(self, interface); return mp_const_none; @@ -283,8 +361,10 @@ MP_DEFINE_CONST_FUN_OBJ_2(usb_core_device_detach_kernel_driver_obj, usb_core_dev //| """ //| ... //| +//| static mp_obj_t usb_core_device_attach_kernel_driver(mp_obj_t self_in, mp_obj_t interface_in) { usb_core_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); mp_int_t interface = mp_obj_get_int(interface_in); common_hal_usb_core_device_attach_kernel_driver(self, interface); return mp_const_none; @@ -293,11 +373,16 @@ MP_DEFINE_CONST_FUN_OBJ_2(usb_core_device_attach_kernel_driver_obj, usb_core_dev static const mp_rom_map_elem_t usb_core_device_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&usb_core_device_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&usb_core_device_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_idVendor), MP_ROM_PTR(&usb_core_device_idVendor_obj) }, { MP_ROM_QSTR(MP_QSTR_idProduct), MP_ROM_PTR(&usb_core_device_idProduct_obj) }, { MP_ROM_QSTR(MP_QSTR_serial_number), MP_ROM_PTR(&usb_core_device_serial_number_obj) }, { MP_ROM_QSTR(MP_QSTR_product), MP_ROM_PTR(&usb_core_device_product_obj) }, { MP_ROM_QSTR(MP_QSTR_manufacturer), MP_ROM_PTR(&usb_core_device_manufacturer_obj) }, + { MP_ROM_QSTR(MP_QSTR_bus), MP_ROM_PTR(&usb_core_device_bus_obj) }, + { MP_ROM_QSTR(MP_QSTR_port_numbers), MP_ROM_PTR(&usb_core_device_port_numbers_obj) }, + { MP_ROM_QSTR(MP_QSTR_speed), MP_ROM_PTR(&usb_core_device_speed_obj) }, { MP_ROM_QSTR(MP_QSTR_set_configuration), MP_ROM_PTR(&usb_core_device_set_configuration_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&usb_core_device_write_obj) }, diff --git a/shared-bindings/usb/core/Device.h b/shared-bindings/usb/core/Device.h index 232d16bdabf3c..28c2cfbe19860 100644 --- a/shared-bindings/usb/core/Device.h +++ b/shared-bindings/usb/core/Device.h @@ -13,11 +13,17 @@ extern const mp_obj_type_t usb_core_device_type; bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t device_number); +bool common_hal_usb_core_device_deinited(usb_core_device_obj_t *self); +void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self); uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self); uint16_t common_hal_usb_core_device_get_idProduct(usb_core_device_obj_t *self); mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *self); mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self); mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self); +mp_int_t common_hal_usb_core_device_get_bus(usb_core_device_obj_t *self); +mp_obj_t common_hal_usb_core_device_get_port_numbers(usb_core_device_obj_t *self); +mp_int_t common_hal_usb_core_device_get_speed(usb_core_device_obj_t *self); + void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, mp_int_t configuration); mp_int_t common_hal_usb_core_device_write(usb_core_device_obj_t *self, mp_int_t endpoint, const uint8_t *buffer, mp_int_t len, mp_int_t timeout); mp_int_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t endpoint, uint8_t *buffer, mp_int_t len, mp_int_t timeout); diff --git a/shared-bindings/usb/core/__init__.c b/shared-bindings/usb/core/__init__.c index 99be3888bf877..29dab285084ef 100644 --- a/shared-bindings/usb/core/__init__.c +++ b/shared-bindings/usb/core/__init__.c @@ -21,14 +21,16 @@ //| This is a subset of the PyUSB core module. //| """ //| +//| //| class USBError(OSError): //| """Catchall exception for USB related errors.""" //| //| ... //| +//| MP_DEFINE_USB_CORE_EXCEPTION(USBError, OSError) -NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { +MP_NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { mp_obj_t exception; if (fmt == NULL) { exception = mp_obj_new_exception(&mp_type_usb_core_USBError); @@ -46,8 +48,9 @@ NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...) { //| //| ... //| +//| MP_DEFINE_USB_CORE_EXCEPTION(USBTimeoutError, usb_core_USBError) -NORETURN void mp_raise_usb_core_USBTimeoutError(void) { +MP_NORETURN void mp_raise_usb_core_USBTimeoutError(void) { mp_raise_type(&mp_type_usb_core_USBTimeoutError); } @@ -61,6 +64,7 @@ NORETURN void mp_raise_usb_core_USBTimeoutError(void) { //| Returns None if no device matches. //| """ //| +//| typedef struct { mp_obj_base_t base; mp_int_t vid; @@ -86,9 +90,10 @@ static mp_obj_t _next_device(usb_core_devices_obj_t *iter) { // We passed the filters. Now make a properly allocated object to // return to the user. usb_core_device_obj_t *self = mp_obj_malloc(usb_core_device_obj_t, &usb_core_device_type); - common_hal_usb_core_device_construct(self, i); + iter->next_index = i + 1; + return MP_OBJ_FROM_PTR(self); } // Iter is done. diff --git a/shared-bindings/usb/core/__init__.h b/shared-bindings/usb/core/__init__.h index 0dc08fae53257..adb8430a6c382 100644 --- a/shared-bindings/usb/core/__init__.h +++ b/shared-bindings/usb/core/__init__.h @@ -25,8 +25,8 @@ void usb_core_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_k extern const mp_obj_type_t mp_type_usb_core_USBError; extern const mp_obj_type_t mp_type_usb_core_USBTimeoutError; -NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...); -NORETURN void mp_raise_usb_core_USBTimeoutError(void); +MP_NORETURN void mp_raise_usb_core_USBError(mp_rom_error_text_t fmt, ...); +MP_NORETURN void mp_raise_usb_core_USBTimeoutError(void); // Find is all Python object oriented so we don't need a separate common-hal API // for it. It uses the device common-hal instead. diff --git a/shared-bindings/usb/util/__init__.c b/shared-bindings/usb/util/__init__.c new file mode 100644 index 0000000000000..20405827abee7 --- /dev/null +++ b/shared-bindings/usb/util/__init__.c @@ -0,0 +1,48 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include + +#include "py/obj.h" +#include "py/objexcept.h" +#include "py/misc.h" +#include "py/mphal.h" +#include "py/runtime.h" + +#include "shared-bindings/usb/util/__init__.h" + +//| """USB Util +//| +//| This is a subset of the PyUSB util module. +//| """ +//| +//| SPEED_LOW: int = ... +//| """A low speed, 1.5 Mbit/s device.""" +//| +//| SPEED_FULL: int = ... +//| """A full speed, 12 Mbit/s device.""" +//| +//| SPEED_HIGH: int = ... +//| """A high speed, 480 Mbit/s device.""" +//| + +static mp_rom_map_elem_t usb_util_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usb_dot_util) }, + // Speed constants + { MP_ROM_QSTR(MP_QSTR_SPEED_LOW), MP_OBJ_NEW_SMALL_INT(PYUSB_SPEED_LOW) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_FULL), MP_OBJ_NEW_SMALL_INT(PYUSB_SPEED_FULL) }, + { MP_ROM_QSTR(MP_QSTR_SPEED_HIGH), MP_OBJ_NEW_SMALL_INT(PYUSB_SPEED_HIGH) }, +}; + +static MP_DEFINE_CONST_DICT(usb_util_module_globals, usb_util_module_globals_table); + +const mp_obj_module_t usb_util_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&usb_util_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_usb_dot_util, usb_util_module); diff --git a/shared-bindings/usb/util/__init__.h b/shared-bindings/usb/util/__init__.h new file mode 100644 index 0000000000000..446bdf41e8aff --- /dev/null +++ b/shared-bindings/usb/util/__init__.h @@ -0,0 +1,17 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +#include "py/obj.h" + +extern const mp_obj_module_t usb_util_module; + +#define PYUSB_SPEED_LOW 1 +#define PYUSB_SPEED_FULL 2 +#define PYUSB_SPEED_HIGH 3 diff --git a/shared-bindings/usb_cdc/Serial.c b/shared-bindings/usb_cdc/Serial.c index 9fc5de21bcda1..eb526615927bd 100644 --- a/shared-bindings/usb_cdc/Serial.c +++ b/shared-bindings/usb_cdc/Serial.c @@ -22,11 +22,15 @@ //| The available instances are in the ``usb_cdc.serials`` tuple.""" //| ... //| -//| def read(self, size: int = 1) -> bytes: -//| """Read at most ``size`` bytes. If ``size`` exceeds the internal buffer size -//| only the bytes in the buffer will be read. If `timeout` is > 0 or ``None``, -//| and fewer than ``size`` bytes are available, keep waiting until the timeout -//| expires or ``size`` bytes are available. +//| def read(self, size: int = -1) -> bytes: +//| """Read at most ``size`` bytes. If ``size`` exceeds the internal buffer size, +//| only the bytes in the buffer will be read. If ``size`` is not specified or is ``-1``, +//| read as many bytes as possible, until the timeout expires. +//| If `timeout` is > 0 or ``None``, and fewer than ``size`` bytes are available, +//| keep waiting until the timeout expires or ``size`` bytes are available. +//| +//| If no bytes are read, return ``b''``. This is unlike, say, `busio.UART.read()`, which +//| would return ``None``. //| //| :return: Data read //| :rtype: bytes""" @@ -74,6 +78,7 @@ //| def flush(self) -> None: //| """Force out any unwritten bytes, waiting until they are written.""" //| ... +//| // These three methods are used by the shared stream methods. static mp_uint_t usb_cdc_serial_read_stream(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { @@ -151,6 +156,7 @@ MP_PROPERTY_GETTER(usb_cdc_serial_in_waiting_obj, //| out_waiting: int //| """Returns the number of bytes waiting to be written on the USB serial output. (read-only)""" +//| static mp_obj_t usb_cdc_serial_get_out_waiting(mp_obj_t self_in) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); return mp_obj_new_int(common_hal_usb_cdc_serial_get_out_waiting(self)); @@ -163,6 +169,7 @@ MP_PROPERTY_GETTER(usb_cdc_serial_out_waiting_obj, //| def reset_input_buffer(self) -> None: //| """Clears any unread bytes.""" //| ... +//| static mp_obj_t usb_cdc_serial_reset_input_buffer(mp_obj_t self_in) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_usb_cdc_serial_reset_input_buffer(self); @@ -173,6 +180,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_reset_input_buffer_obj, usb_cdc_serial_ //| def reset_output_buffer(self) -> None: //| """Clears any unwritten bytes.""" //| ... +//| static mp_obj_t usb_cdc_serial_reset_output_buffer(mp_obj_t self_in) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); common_hal_usb_cdc_serial_reset_output_buffer(self); @@ -186,7 +194,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_reset_output_buffer_obj, usb_cdc_serial static mp_obj_t usb_cdc_serial_get_timeout(mp_obj_t self_in) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_float_t timeout = common_hal_usb_cdc_serial_get_timeout(self); - return (timeout < 0.0f) ? mp_const_none : mp_obj_new_float(self->timeout); + return (timeout < 0.0f) ? mp_const_none : mp_obj_new_float(timeout); } MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_timeout_obj, usb_cdc_serial_get_timeout); @@ -207,10 +215,11 @@ MP_PROPERTY_GETSET(usb_cdc_serial_timeout_obj, //| writing all the bytes passed to ``write()``.If 0, do not wait. //| If > 0, wait only ``write_timeout`` seconds.""" //| +//| static mp_obj_t usb_cdc_serial_get_write_timeout(mp_obj_t self_in) { usb_cdc_serial_obj_t *self = MP_OBJ_TO_PTR(self_in); mp_float_t write_timeout = common_hal_usb_cdc_serial_get_write_timeout(self); - return (write_timeout < 0.0f) ? mp_const_none : mp_obj_new_float(self->write_timeout); + return (write_timeout < 0.0f) ? mp_const_none : mp_obj_new_float(write_timeout); } MP_DEFINE_CONST_FUN_OBJ_1(usb_cdc_serial_get_write_timeout_obj, usb_cdc_serial_get_write_timeout); @@ -230,22 +239,22 @@ MP_PROPERTY_GETSET(usb_cdc_serial_write_timeout_obj, static const mp_rom_map_elem_t usb_cdc_serial_locals_dict_table[] = { // Standard stream methods. { MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&mp_stream_flush_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)}, { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, // Other pyserial-inspired attributes. - { MP_OBJ_NEW_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&usb_cdc_serial_in_waiting_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_out_waiting), MP_ROM_PTR(&usb_cdc_serial_out_waiting_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_input_buffer_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_reset_output_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_output_buffer_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&usb_cdc_serial_timeout_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write_timeout), MP_ROM_PTR(&usb_cdc_serial_write_timeout_obj) }, + { MP_ROM_QSTR(MP_QSTR_in_waiting), MP_ROM_PTR(&usb_cdc_serial_in_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_out_waiting), MP_ROM_PTR(&usb_cdc_serial_out_waiting_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_input_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_input_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_output_buffer), MP_ROM_PTR(&usb_cdc_serial_reset_output_buffer_obj) }, + { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&usb_cdc_serial_timeout_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_timeout), MP_ROM_PTR(&usb_cdc_serial_write_timeout_obj) }, // Not in pyserial protocol. - { MP_OBJ_NEW_QSTR(MP_QSTR_connected), MP_ROM_PTR(&usb_cdc_serial_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&usb_cdc_serial_connected_obj) }, diff --git a/shared-bindings/usb_cdc/Serial.h b/shared-bindings/usb_cdc/Serial.h index 30249cef389c1..091f7514a4fb7 100644 --- a/shared-bindings/usb_cdc/Serial.h +++ b/shared-bindings/usb_cdc/Serial.h @@ -6,7 +6,11 @@ #pragma once +#if defined(__ZEPHYR__) && __ZEPHYR__ == 1 +#include "common-hal/usb_cdc/Serial.h" +#else #include "shared-module/usb_cdc/Serial.h" +#endif extern const mp_obj_type_t usb_cdc_serial_type; diff --git a/shared-bindings/usb_cdc/__init__.c b/shared-bindings/usb_cdc/__init__.c index 3a2c43c3e922a..65d343b03510e 100644 --- a/shared-bindings/usb_cdc/__init__.c +++ b/shared-bindings/usb_cdc/__init__.c @@ -40,6 +40,7 @@ //| the host. //| Note that `data` is *disabled* by default. ``data`` is ``None`` if disabled.""" //| +//| //| def disable() -> None: //| """Do not present any USB CDC device to the host. @@ -47,6 +48,7 @@ //| Equivalent to ``usb_cdc.enable(console=False, data=False)``.""" //| ... //| +//| static mp_obj_t usb_cdc_disable(void) { if (!common_hal_usb_cdc_disable()) { mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now")); @@ -70,6 +72,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_cdc_disable_obj, usb_cdc_disable); //| """ //| ... //| +//| static mp_obj_t usb_cdc_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_console, ARG_data }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/usb_cdc/__init__.h b/shared-bindings/usb_cdc/__init__.h index 34099f7e8fd61..154f259f4101d 100644 --- a/shared-bindings/usb_cdc/__init__.h +++ b/shared-bindings/usb_cdc/__init__.h @@ -6,7 +6,11 @@ #pragma once +#if defined(__ZEPHYR__) && __ZEPHYR__ == 1 +#include "common-hal/usb_cdc/__init__.h" +#else #include "shared-module/usb_cdc/__init__.h" +#endif // Set the module dict entries. void usb_cdc_set_console(mp_obj_t serial_obj); diff --git a/shared-bindings/usb_hid/Device.c b/shared-bindings/usb_hid/Device.c index 1afdda509f41e..66c9c01ad6e43 100644 --- a/shared-bindings/usb_hid/Device.c +++ b/shared-bindings/usb_hid/Device.c @@ -19,7 +19,7 @@ //| usage: int, //| report_ids: Sequence[int], //| in_report_lengths: Sequence[int], -//| out_report_lengths: Sequence[int] +//| out_report_lengths: Sequence[int], //| ) -> None: //| """Create a description of a USB HID device. The actual device is created when you //| pass a `Device` to `usb_hid.enable()`. @@ -57,6 +57,7 @@ //| See `send_report()` for details. //| """ //| ... +//| //| KEYBOARD: Device //| """Standard keyboard device supporting keycodes 0x00-0xDD, modifiers 0xE-0xE7, and five LED indicators. //| Uses Report ID 1 for its IN and OUT reports. @@ -71,9 +72,9 @@ //| CONSUMER_CONTROL: Device //| """Consumer Control device supporting sent values from 1-652, with no rollover. //| Uses Report ID 3 for its IN report.""" +//| static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - usb_hid_device_obj_t *self = mp_obj_malloc(usb_hid_device_obj_t, &usb_hid_device_type); enum { ARG_report_descriptor, ARG_usage_page, ARG_usage, ARG_report_ids, ARG_in_report_lengths, ARG_out_report_lengths }; static const mp_arg_t allowed_args[] = { { MP_QSTR_report_descriptor, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, @@ -96,7 +97,7 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args const uint16_t usage_page = usage_page_arg; const mp_int_t usage_arg = args[ARG_usage].u_int; - mp_arg_validate_int_range(usage_arg, 1, 0xFFFF, MP_QSTR_usage); + mp_arg_validate_int_range(usage_arg, 0, 0xFFFF, MP_QSTR_usage); const uint16_t usage = usage_arg; mp_obj_t report_ids = args[ARG_report_ids].u_obj; @@ -139,9 +140,10 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args mp_raise_ValueError_varg(MP_ERROR_TEXT("%q length must be %d"), MP_QSTR_report_id_space_0, 1); } + usb_hid_device_obj_t *self = mp_obj_malloc(usb_hid_device_obj_t, &usb_hid_device_type); common_hal_usb_hid_device_construct( self, descriptor, usage_page, usage, report_ids_count, report_ids_array, in_report_lengths_array, out_report_lengths_array); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } @@ -161,6 +163,7 @@ static mp_obj_t usb_hid_device_make_new(const mp_obj_type_t *type, size_t n_args //| In addition, there may be USB wakeup settings in the host computer BIOS/UEFI. //| """ //| ... +//| static mp_obj_t usb_hid_device_send_report(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -195,6 +198,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_hid_device_send_report_obj, 1, usb_hid_device_sen //| will return `None` until next report is received. //| """ //| ... +//| static mp_obj_t usb_hid_device_get_last_received_report(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -233,6 +237,7 @@ MP_PROPERTY_GETTER(usb_hid_device_usage_page_obj, //| For example, Keyboard is 0x06 within the generic desktop usage page 0x01. //| Mouse is 0x02 within the same usage page.""" //| +//| static mp_obj_t usb_hid_device_obj_get_usage(mp_obj_t self_in) { usb_hid_device_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_NEW_SMALL_INT(common_hal_usb_hid_device_get_usage(self)); diff --git a/shared-bindings/usb_hid/__init__.c b/shared-bindings/usb_hid/__init__.c index 49a9662c95628..47f7f03c493ec 100644 --- a/shared-bindings/usb_hid/__init__.c +++ b/shared-bindings/usb_hid/__init__.c @@ -14,6 +14,7 @@ //| """USB Human Interface Device //| //| The `usb_hid` module allows you to output data as a HID device.""" +//| //| devices: Tuple[Device, ...] //| """Tuple of all active HID device interfaces. @@ -26,6 +27,7 @@ //| The request for a boot device overrides any other HID devices. //| """ //| +//| //| def disable() -> None: //| """Do not present any USB HID devices to the host computer. @@ -36,6 +38,7 @@ //| as `usb_cdc` or `storage` to free up endpoints for use by `usb_hid`. //| """ //| +//| static mp_obj_t usb_hid_disable(void) { if (!common_hal_usb_hid_disable()) { mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now")); @@ -65,15 +68,16 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_hid_disable_obj, usb_hid_disable); //| //| **Boot Devices** //| -//| Boot devices implement a fixed, predefined report descriptor, defined in -//| https://www.usb.org/sites/default/files/hid1_12.pdf, Appendix B. A USB host -//| can request to use the boot device if the USB device says it is available. -//| Usually only a BIOS or other kind of limited-functionality -//| host needs boot keyboard support. +//| A USB HID boot device implements a fixed, predefined report descriptor, +//| as defined in https://www.usb.org/sites/default/files/hid1_12.pdf, Appendix B. +//| Currently the only HID boot devices defined in the USB specification are a keyboard and a mouse. +//| A USB host can ask a USB device to use a boot device if the USB device says it is available. +//| Usually only a limited-functionality host like a BIOS or other boot-time software +//| needs boot device support. //| //| For example, to make a boot keyboard available, you can use this code:: //| -//| usb_hid.enable((Device.KEYBOARD), boot_device=1) # 1 for a keyboard +//| usb_hid.enable((Device.KEYBOARD,), boot_device=1) # 1 for a keyboard, 2 for a mouse //| //| If the host requests the boot keyboard, the report descriptor provided by `Device.KEYBOARD` //| will be ignored, and the predefined report descriptor will be used. @@ -88,6 +92,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_hid_disable_obj, usb_hid_disable); //| """ //| ... //| +//| static mp_obj_t usb_hid_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_devices, ARG_boot_device }; static const mp_arg_t allowed_args[] = { @@ -130,6 +135,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(usb_hid_enable_obj, 1, usb_hid_enable); //| :rtype int: //| """ //| +//| static mp_obj_t usb_hid_get_boot_device(void) { return MP_OBJ_NEW_SMALL_INT(common_hal_usb_hid_get_boot_device()); } @@ -147,6 +153,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_hid_get_boot_device_obj, usb_hid_get_boot_device); //| """ //| ... //| +//| static mp_obj_t usb_hid_set_interface_name(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_interface_name, MP_ARG_OBJ | MP_ARG_REQUIRED, {.u_rom_obj = mp_const_none} } diff --git a/shared-bindings/usb_host/Port.c b/shared-bindings/usb_host/Port.c index 10e38c8f3a670..2c61e641a05be 100644 --- a/shared-bindings/usb_host/Port.c +++ b/shared-bindings/usb_host/Port.c @@ -28,6 +28,7 @@ //| """ //| ... //| +//| static mp_obj_t usb_host_port_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { // check number of arguments @@ -41,7 +42,7 @@ static mp_obj_t usb_host_port_make_new(const mp_obj_type_t *type, usb_host_port_obj_t *self = common_hal_usb_host_port_construct(dp, dm); - return (mp_obj_t)self; + return MP_OBJ_FROM_PTR(self); } static const mp_rom_map_elem_t usb_host_port_locals_dict_table[] = { diff --git a/shared-bindings/usb_host/__init__.c b/shared-bindings/usb_host/__init__.c index d71231aef15dc..a42c688b6af75 100644 --- a/shared-bindings/usb_host/__init__.c +++ b/shared-bindings/usb_host/__init__.c @@ -18,6 +18,7 @@ //| with devices use the `usb` module that is a subset of PyUSB's API. //| """ //| +//| //| def set_user_keymap(keymap: ReadableBuffer, /) -> None: //| """Set the keymap used by a USB HID keyboard in kernel mode //| @@ -40,6 +41,7 @@ //| This function is a CircuitPython extension not present in PyUSB //| """ //| +//| static mp_obj_t usb_set_user_keymap(mp_obj_t buf_in) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index 38662a4468cd2..d62d0b53af1d4 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -23,6 +23,7 @@ //| PortIn objects are constructed for every corresponding entry in the USB //| descriptor and added to the ``usb_midi.ports`` tuple.""" //| ... +//| // These are standard stream methods. Code is in py/stream.c. // @@ -44,6 +45,7 @@ //| :rtype: bytes or None""" //| ... //| +//| // These three methods are used by the shared stream methods. static mp_uint_t usb_midi_portin_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { @@ -76,8 +78,8 @@ static mp_uint_t usb_midi_portin_ioctl(mp_obj_t self_in, mp_uint_t request, mp_u static const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = { // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, }; static MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table); diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index c39683c3f09de..89c838101887b 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -22,6 +22,7 @@ //| //| PortOut objects are constructed for every corresponding entry in the USB //| descriptor and added to the ``usb_midi.ports`` tuple.""" +//| // These are standard stream methods. Code is in py/stream.c. // @@ -32,6 +33,7 @@ //| :rtype: int or None""" //| ... //| +//| static mp_uint_t usb_midi_portout_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { usb_midi_portout_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -58,7 +60,7 @@ static mp_uint_t usb_midi_portout_ioctl(mp_obj_t self_in, mp_uint_t request, mp_ static const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = { // Standard stream methods. - { MP_OBJ_NEW_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, }; static MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table); diff --git a/shared-bindings/usb_midi/__init__.c b/shared-bindings/usb_midi/__init__.c index c29cb3b4414f4..fc10f89c31fdb 100644 --- a/shared-bindings/usb_midi/__init__.c +++ b/shared-bindings/usb_midi/__init__.c @@ -22,6 +22,7 @@ //| ports: Tuple[Union[PortIn, PortOut], ...] //| """Tuple of all MIDI ports. Each item is ether `PortIn` or `PortOut`.""" //| +//| //| def disable() -> None: //| """Disable presenting a USB MIDI device to the host. @@ -30,6 +31,7 @@ //| Can be called in ``boot.py``, before USB is connected.""" //| ... //| +//| static mp_obj_t usb_midi_disable(void) { if (!common_hal_usb_midi_disable()) { mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now")); @@ -50,6 +52,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(usb_midi_disable_obj, usb_midi_disable); //| """ //| ... //| +//| static mp_obj_t usb_midi_enable(void) { if (!common_hal_usb_midi_enable()) { mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot change USB devices now")); @@ -81,7 +84,7 @@ static void set_name(mp_obj_t name_obj, qstr arg_name_qstr, char **custom_name_p //| streaming_interface_name: Optional[str] = None, //| audio_control_interface_name: Optional[str] = None, //| in_jack_name: Optional[str] = None, -//| out_jack_name: Optional[str] = None +//| out_jack_name: Optional[str] = None, //| ) -> None: //| """Override the MIDI interface names in the USB Interface Descriptor. //| @@ -93,9 +96,13 @@ static void set_name(mp_obj_t name_obj, qstr arg_name_qstr, char **custom_name_p //| This method must be called in boot.py to have any effect. //| //| Not available on boards without native USB support. +//| +//| .. warning:: On Windows, if ``audio_control_interface_name`` is more than 31 characters long, Windows +//| will not recognize the device. This issue is not present on macOS or Linux. //| """ //| ... //| +//| static mp_obj_t usb_midi_set_names(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_streaming_interface_name, ARG_audio_control_interface_name, ARG_in_jack_name, ARG_out_jack_name }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/usb_video/USBFramebuffer.c b/shared-bindings/usb_video/USBFramebuffer.c index f89424fa88c79..25151809df561 100644 --- a/shared-bindings/usb_video/USBFramebuffer.c +++ b/shared-bindings/usb_video/USBFramebuffer.c @@ -31,8 +31,9 @@ static void check_for_deinit(usb_video_uvcframebuffer_obj_t *self) { //| it also supports the ``WritableBuffer`` protocol and can be accessed //| as an array of ``H`` (unsigned 16-bit values).""" //| -//| def __new__(self): +//| def __init__(self) -> None: //| """Returns the singleton framebuffer object, if USB video is enabled""" +//| static mp_obj_t usb_video_uvcframebuffer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { static const mp_arg_t allowed_args[] = {}; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -45,6 +46,7 @@ static mp_obj_t usb_video_uvcframebuffer_make_new(const mp_obj_type_t *type, siz //| """Transmits the color data in the buffer to the pixels so that //| they are shown.""" //| ... +//| static mp_obj_t usb_video_uvcframebuffer_refresh(mp_obj_t self_in) { usb_video_uvcframebuffer_obj_t *self = (usb_video_uvcframebuffer_obj_t *)self_in; check_for_deinit(self); @@ -67,6 +69,7 @@ MP_PROPERTY_GETTER(usb_video_uvcframebuffer_width_obj, //| height: int //| """The height of the display, in pixels""" //| +//| static mp_obj_t usb_video_uvcframebuffer_get_height(mp_obj_t self_in) { usb_video_uvcframebuffer_obj_t *self = (usb_video_uvcframebuffer_obj_t *)self_in; check_for_deinit(self); diff --git a/shared-bindings/usb_video/__init__.c b/shared-bindings/usb_video/__init__.c index 189acd9109c6f..06050188d6663 100644 --- a/shared-bindings/usb_video/__init__.c +++ b/shared-bindings/usb_video/__init__.c @@ -46,6 +46,7 @@ //| This interface is experimental and may change without notice even in stable //| versions of CircuitPython.""" //| +//| //| def enable_framebuffer(width: int, height: int) -> None: //| """Enable a USB video framebuffer, setting the given width & height @@ -59,6 +60,7 @@ //| for Python objects. If the allocation fails, a MemoryError is raised. //| This message can be seen in ``boot_out.txt``.""" //| +//| static mp_obj_t usb_video_enable_framebuffer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_width, ARG_height }; diff --git a/shared-bindings/ustack/__init__.c b/shared-bindings/ustack/__init__.c index 3002254db2584..9676c517a629c 100644 --- a/shared-bindings/ustack/__init__.c +++ b/shared-bindings/ustack/__init__.c @@ -16,12 +16,14 @@ //| """Stack information and analysis""" //| +//| #if MICROPY_MAX_STACK_USAGE //| def max_stack_usage() -> int: //| """Return the maximum excursion of the stack so far.""" //| ... //| +//| static mp_obj_t max_stack_usage(void) { return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_max_stack_usage()); } @@ -35,6 +37,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(max_stack_usage_obj, max_stack_usage); //| of just printing it.""" //| ... //| +//| static mp_obj_t stack_size(void) { return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_stack_size()); } @@ -45,6 +48,7 @@ static MP_DEFINE_CONST_FUN_OBJ_0(stack_size_obj, stack_size); //| Same as micropython.stack_use(); duplicated here for convenience.""" //| ... //| +//| static mp_obj_t stack_usage(void) { return MP_OBJ_NEW_SMALL_INT(shared_module_ustack_stack_usage()); } diff --git a/shared-bindings/util.c b/shared-bindings/util.c index 0711428b4de03..0bcaa2eef41e9 100644 --- a/shared-bindings/util.c +++ b/shared-bindings/util.c @@ -8,6 +8,8 @@ #include "shared-bindings/util.h" +#include "shared-bindings/os/__init__.h" + // If so, deinit() has already been called on the object, so complain. void raise_deinited_error(void) { mp_raise_ValueError(MP_ERROR_TEXT("Object has been deinitialized and can no longer be used. Create a new object.")); @@ -33,3 +35,16 @@ void properties_construct_helper(mp_obj_t self_in, const mp_arg_t *args, const m } } } + +bool path_exists(const char *path) { + // Use common_hal_os_stat to check if path exists + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + common_hal_os_stat(path); + nlr_pop(); + return true; + } else { + // Path doesn't exist + return false; + } +} diff --git a/shared-bindings/util.h b/shared-bindings/util.h index f1e4dca13aa43..11f0a00db71ea 100644 --- a/shared-bindings/util.h +++ b/shared-bindings/util.h @@ -9,6 +9,7 @@ #include "py/mpprint.h" #include "py/runtime.h" -void raise_deinited_error(void); +MP_NORETURN void raise_deinited_error(void); void properties_print_helper(const mp_print_t *print, mp_obj_t self_in, const mp_arg_t *properties, size_t n_properties); void properties_construct_helper(mp_obj_t self_in, const mp_arg_t *args, const mp_arg_val_t *vals, size_t n_properties); +bool path_exists(const char *path); diff --git a/shared-bindings/vectorio/Circle.c b/shared-bindings/vectorio/Circle.c index d2f31d6b86d82..7fb20b59b4d9f 100644 --- a/shared-bindings/vectorio/Circle.c +++ b/shared-bindings/vectorio/Circle.c @@ -31,11 +31,12 @@ //| :param int y: Initial y position of the axis. //| :param int color_index: Initial color_index to use when selecting color from the palette. //| """ +//| static mp_obj_t vectorio_circle_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pixel_shader, ARG_radius, ARG_x, ARG_y, ARG_color_index }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, - { MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, { .u_obj = NULL } }, + { MP_QSTR_radius, MP_ARG_REQUIRED | MP_ARG_INT, { .u_obj = NULL } }, { MP_QSTR_x, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_y, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_color_index, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, @@ -123,6 +124,7 @@ MP_PROPERTY_GETSET(vectorio_circle_color_index_obj, //| pixel_shader: Union[displayio.ColorConverter, displayio.Palette] //| """The pixel shader of the circle.""" //| +//| static const mp_rom_map_elem_t vectorio_circle_locals_dict_table[] = { // Functions diff --git a/shared-bindings/vectorio/Polygon.c b/shared-bindings/vectorio/Polygon.c index 05228465f6c16..0f45da21e6123 100644 --- a/shared-bindings/vectorio/Polygon.c +++ b/shared-bindings/vectorio/Polygon.c @@ -39,10 +39,11 @@ //| :param int y: Initial screen y position of the 0,0 origin in the points list. //| :param int color_index: Initial color_index to use when selecting color from the palette. //| """ +//| static mp_obj_t vectorio_polygon_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pixel_shader, ARG_points_list, ARG_x, ARG_y, ARG_color_index }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, + { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, { .u_obj = NULL } }, { MP_QSTR_points, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_x, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_y, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, @@ -132,6 +133,7 @@ MP_PROPERTY_GETSET(vectorio_polygon_color_index_obj, //| pixel_shader: Union[displayio.ColorConverter, displayio.Palette] //| """The pixel shader of the polygon.""" //| +//| static const mp_rom_map_elem_t vectorio_polygon_locals_dict_table[] = { // Functions diff --git a/shared-bindings/vectorio/Rectangle.c b/shared-bindings/vectorio/Rectangle.c index d1f2e6193ce3e..3582b01014912 100644 --- a/shared-bindings/vectorio/Rectangle.c +++ b/shared-bindings/vectorio/Rectangle.c @@ -32,12 +32,13 @@ //| :param int y: Initial y position of the top left corner. //| :param int color_index: Initial color_index to use when selecting color from the palette. //| """ +//| static mp_obj_t vectorio_rectangle_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_pixel_shader, ARG_width, ARG_height, ARG_x, ARG_y, ARG_color_index }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED }, - { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_pixel_shader, MP_ARG_OBJ | MP_ARG_KW_ONLY | MP_ARG_REQUIRED, {.u_obj = NULL } }, + { MP_QSTR_width, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0 } }, + { MP_QSTR_height, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0 } }, { MP_QSTR_x, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_y, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, { MP_QSTR_color_index, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 0} }, @@ -85,12 +86,9 @@ static mp_obj_t vectorio_rectangle_obj_set_width(mp_obj_t self_in, mp_obj_t widt } MP_DEFINE_CONST_FUN_OBJ_2(vectorio_rectangle_set_width_obj, vectorio_rectangle_obj_set_width); -const mp_obj_property_t vectorio_rectangle_width_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&vectorio_rectangle_get_width_obj, - (mp_obj_t)&vectorio_rectangle_set_width_obj, - MP_ROM_NONE}, -}; +MP_PROPERTY_GETSET(vectorio_rectangle_width_obj, + (mp_obj_t)&vectorio_rectangle_get_width_obj, + (mp_obj_t)&vectorio_rectangle_set_width_obj); //| height: int //| """The height of the rectangle in pixels.""" @@ -107,12 +105,9 @@ static mp_obj_t vectorio_rectangle_obj_set_height(mp_obj_t self_in, mp_obj_t hei } MP_DEFINE_CONST_FUN_OBJ_2(vectorio_rectangle_set_height_obj, vectorio_rectangle_obj_set_height); -const mp_obj_property_t vectorio_rectangle_height_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&vectorio_rectangle_get_height_obj, - (mp_obj_t)&vectorio_rectangle_set_height_obj, - MP_ROM_NONE}, -}; +MP_PROPERTY_GETSET(vectorio_rectangle_height_obj, + (mp_obj_t)&vectorio_rectangle_get_height_obj, + (mp_obj_t)&vectorio_rectangle_set_height_obj); //| color_index: int //| """The color_index of the rectangle in 1 based index of the palette.""" @@ -129,12 +124,9 @@ static mp_obj_t vectorio_rectangle_obj_set_color_index(mp_obj_t self_in, mp_obj_ } MP_DEFINE_CONST_FUN_OBJ_2(vectorio_rectangle_set_color_index_obj, vectorio_rectangle_obj_set_color_index); -const mp_obj_property_t vectorio_rectangle_color_index_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&vectorio_rectangle_get_color_index_obj, - (mp_obj_t)&vectorio_rectangle_set_color_index_obj, - MP_ROM_NONE}, -}; +MP_PROPERTY_GETSET(vectorio_rectangle_color_index_obj, + (mp_obj_t)&vectorio_rectangle_get_color_index_obj, + (mp_obj_t)&vectorio_rectangle_set_color_index_obj); // Documentation for properties inherited from VectorShape. @@ -153,6 +145,7 @@ const mp_obj_property_t vectorio_rectangle_color_index_obj = { //| pixel_shader: Union[displayio.ColorConverter, displayio.Palette] //| """The pixel shader of the rectangle.""" //| +//| static const mp_rom_map_elem_t vectorio_rectangle_locals_dict_table[] = { // Functions diff --git a/shared-bindings/vectorio/VectorShape.c b/shared-bindings/vectorio/VectorShape.c index 041600bff4e49..834f1fbff5083 100644 --- a/shared-bindings/vectorio/VectorShape.c +++ b/shared-bindings/vectorio/VectorShape.c @@ -69,7 +69,7 @@ mp_obj_t vectorio_vector_shape_make_new(const mp_obj_t shape, const mp_obj_t pix } else if (mp_obj_is_type(shape, &vectorio_circle_type)) { common_hal_vectorio_circle_set_on_dirty(self->ishape.shape, on_dirty); } else { - mp_raise_TypeError_varg(MP_ERROR_TEXT("unsupported %q type"), MP_QSTR_shape); + // Already excluded due to previous else-if chain. } return MP_OBJ_FROM_PTR(self); @@ -82,6 +82,7 @@ vectorio_draw_protocol_impl_t vectorio_vector_shape_draw_protocol_impl = { .draw_finish_refresh = (draw_finish_refresh_fun)vectorio_vector_shape_finish_refresh, .draw_get_refresh_areas = (draw_get_refresh_areas_fun)vectorio_vector_shape_get_refresh_areas, .draw_set_dirty = (draw_set_dirty_fun)common_hal_vectorio_vector_shape_set_dirty, + .draw_set_in_group = (draw_set_in_group_fun)vectorio_vector_shape_set_in_group, }; // Stub checker does not approve of these shared properties. diff --git a/shared-bindings/vectorio/VectorShape.h b/shared-bindings/vectorio/VectorShape.h index 9e06a0c146e8d..7924eb07ba287 100644 --- a/shared-bindings/vectorio/VectorShape.h +++ b/shared-bindings/vectorio/VectorShape.h @@ -43,6 +43,7 @@ mp_obj_t common_hal_vectorio_vector_shape_get_pixel_shader(vectorio_vector_shape void common_hal_vectorio_vector_shape_set_pixel_shader(vectorio_vector_shape_t *self, mp_obj_t pixel_shader); void vectorio_vector_shape_update_transform(vectorio_vector_shape_t *self, displayio_buffer_transform_t *group_transform); +bool vectorio_vector_shape_set_in_group(vectorio_vector_shape_t *self, bool in_group); // Composable property definition for shapes that use VectorShape extern vectorio_draw_protocol_impl_t vectorio_vector_shape_draw_protocol_impl; diff --git a/shared-bindings/vectorio/__init__.h b/shared-bindings/vectorio/__init__.h index c982f63815b4d..c5dcc02656738 100644 --- a/shared-bindings/vectorio/__init__.h +++ b/shared-bindings/vectorio/__init__.h @@ -23,6 +23,7 @@ typedef bool (*draw_get_dirty_area_fun)(mp_obj_t draw_protocol_self, displayio_a typedef void (*draw_update_transform_fun)(mp_obj_t draw_protocol_self, displayio_buffer_transform_t *group_transform); typedef void (*draw_finish_refresh_fun)(mp_obj_t draw_protocol_self); typedef void (*draw_set_dirty_fun)(mp_obj_t draw_protocol_self); +typedef bool (*draw_set_in_group_fun)(mp_obj_t draw_protocol_self, bool in_group); typedef displayio_area_t *(*draw_get_refresh_areas_fun)(mp_obj_t draw_protocol_self, displayio_area_t *tail); typedef struct _vectorio_draw_protocol_impl_t { @@ -32,6 +33,7 @@ typedef struct _vectorio_draw_protocol_impl_t { draw_finish_refresh_fun draw_finish_refresh; draw_get_refresh_areas_fun draw_get_refresh_areas; draw_set_dirty_fun draw_set_dirty; + draw_set_in_group_fun draw_set_in_group; } vectorio_draw_protocol_impl_t; // Draw protocol diff --git a/shared-bindings/warnings/__init__.c b/shared-bindings/warnings/__init__.c index 1d726bc61a8a8..3984bb31758f4 100644 --- a/shared-bindings/warnings/__init__.c +++ b/shared-bindings/warnings/__init__.c @@ -25,6 +25,7 @@ //| //| import typing //| +//| //| def warn(message: str, category: type = Warning) -> None: //| """Issue a warning with an optional category. Use `simplefilter()` to @@ -33,6 +34,7 @@ //| """ //| ... //| +//| static mp_obj_t warnings_warn(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_message, ARG_category }; static const mp_arg_t allowed_args[] = { @@ -58,6 +60,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(warnings_warn_obj, 1, warnings_warn); //| behavior because it allows for per-category changes.""" //| ... //| +//| static mp_obj_t warnings_simplefilter(mp_obj_t action_in) { const char *action_str = mp_obj_str_get_str(action_in); warnings_action_t action; diff --git a/shared-bindings/watchdog/WatchDogMode.c b/shared-bindings/watchdog/WatchDogMode.c index 3aee1203d38fb..c049c0517097e 100644 --- a/shared-bindings/watchdog/WatchDogMode.c +++ b/shared-bindings/watchdog/WatchDogMode.c @@ -20,6 +20,7 @@ MAKE_ENUM_VALUE(watchdog_watchdogmode_type, watchdogmode, RESET, WATCHDOGMODE_RE //| RESET: WatchDogMode //| """Reset the system when the `WatchDogTimer` expires.""" //| +//| MAKE_ENUM_MAP(watchdog_watchdogmode) { MAKE_ENUM_MAP_ENTRY(watchdogmode, RAISE), MAKE_ENUM_MAP_ENTRY(watchdogmode, RESET), diff --git a/shared-bindings/watchdog/WatchDogTimer.c b/shared-bindings/watchdog/WatchDogTimer.c index 8ff8ba2f9c282..dbb91311345f2 100644 --- a/shared-bindings/watchdog/WatchDogTimer.c +++ b/shared-bindings/watchdog/WatchDogTimer.c @@ -32,11 +32,13 @@ //| def __init__(self) -> None: //| """Access the sole instance through `microcontroller.watchdog`.""" //| ... +//| //| def feed(self) -> None: //| """Feed the watchdog timer. This must be called regularly, otherwise //| the timer will expire. Silently does nothing if the watchdog isn't active.""" //| ... +//| static mp_obj_t watchdog_watchdogtimer_feed(mp_obj_t self_in) { watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in); if (common_hal_watchdog_get_mode(self) != WATCHDOGMODE_NONE) { @@ -46,23 +48,6 @@ static mp_obj_t watchdog_watchdogtimer_feed(mp_obj_t self_in) { } static MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_feed_obj, watchdog_watchdogtimer_feed); -//| def deinit(self) -> None: -//| """Stop the watchdog timer. -//| -//| :raises RuntimeError: if the watchdog timer cannot be disabled on this platform. -//| -//| .. note:: This is deprecated in ``9.0.0`` and will be removed in ``10.0.0``. -//| Set watchdog `mode` to `None` instead. -//| -//| """ -//| ... -static mp_obj_t watchdog_watchdogtimer_deinit(mp_obj_t self_in) { - watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_watchdog_deinit(self); - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_1(watchdog_watchdogtimer_deinit_obj, watchdog_watchdogtimer_deinit); - //| timeout: float //| """The maximum number of seconds that can elapse between calls //| to `feed()`. Setting the timeout will also feed the watchdog.""" @@ -102,6 +87,7 @@ MP_PROPERTY_GETSET(watchdog_watchdogtimer_timeout_obj, //| //| Once set, the `WatchDogTimer` will perform the specified action if the timer expires.""" //| +//| static mp_obj_t watchdog_watchdogtimer_obj_get_mode(mp_obj_t self_in) { watchdog_watchdogtimer_obj_t *self = MP_OBJ_TO_PTR(self_in); return cp_enum_find(&watchdog_watchdogmode_type, common_hal_watchdog_get_mode(self)); @@ -122,7 +108,6 @@ MP_PROPERTY_GETSET(watchdog_watchdogtimer_mode_obj, static const mp_rom_map_elem_t watchdog_watchdogtimer_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&watchdog_watchdogtimer_feed_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&watchdog_watchdogtimer_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_timeout), MP_ROM_PTR(&watchdog_watchdogtimer_timeout_obj) }, { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&watchdog_watchdogtimer_mode_obj) }, }; diff --git a/shared-bindings/watchdog/__init__.c b/shared-bindings/watchdog/__init__.c index 4e338844a0a18..8ae7633f1f35c 100644 --- a/shared-bindings/watchdog/__init__.c +++ b/shared-bindings/watchdog/__init__.c @@ -30,6 +30,7 @@ //| w.mode = WatchDogMode.RAISE //| w.feed()""" //| +//| //| class WatchDogTimeout(Exception): //| """Exception raised when the watchdog timer is set to @@ -58,6 +59,7 @@ //| print("Exited loop") //| """ //| +//| MP_DEFINE_CONST_OBJ_TYPE( mp_type_WatchDogTimeout, diff --git a/shared-bindings/wifi/AuthMode.c b/shared-bindings/wifi/AuthMode.c index c2c653727d6f5..d7f3af80befcb 100644 --- a/shared-bindings/wifi/AuthMode.c +++ b/shared-bindings/wifi/AuthMode.c @@ -40,6 +40,7 @@ MAKE_ENUM_VALUE(wifi_authmode_type, authmode, ENTERPRISE, AUTHMODE_ENTERPRISE); //| ENTERPRISE: object //| """Each user has a unique credential.""" //| +//| MAKE_ENUM_MAP(wifi_authmode) { MAKE_ENUM_MAP_ENTRY(authmode, OPEN), MAKE_ENUM_MAP_ENTRY(authmode, WEP), diff --git a/shared-bindings/wifi/Monitor.c b/shared-bindings/wifi/Monitor.c index a2e91dca4b4ac..fb09c4b4f771b 100644 --- a/shared-bindings/wifi/Monitor.c +++ b/shared-bindings/wifi/Monitor.c @@ -24,6 +24,7 @@ //| //| """ //| ... +//| static mp_obj_t wifi_monitor_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { enum { ARG_channel, ARG_queue }; static const mp_arg_t allowed_args[] = { @@ -70,6 +71,7 @@ MP_PROPERTY_GETSET(wifi_monitor_channel_obj, //| queue: int //| """The queue size for buffering the packet.""" +//| static mp_obj_t wifi_monitor_obj_get_queue(mp_obj_t self_in) { return common_hal_wifi_monitor_get_queue(self_in); } @@ -81,6 +83,7 @@ MP_PROPERTY_GETTER(wifi_monitor_queue_obj, //| def deinit(self) -> None: //| """De-initialize `wifi.Monitor` singleton.""" //| ... +//| static mp_obj_t wifi_monitor_obj_deinit(mp_obj_t self_in) { common_hal_wifi_monitor_deinit(self_in); return mp_const_none; @@ -90,6 +93,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(wifi_monitor_deinit_obj, wifi_monitor_obj_deini //| def lost(self) -> int: //| """Returns the packet loss count. The counter resets after each poll.""" //| ... +//| static mp_obj_t wifi_monitor_obj_get_lost(mp_obj_t self_in) { return common_hal_wifi_monitor_get_lost(self_in); } @@ -98,6 +102,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_monitor_lost_obj, wifi_monitor_obj_get_lost); //| def queued(self) -> int: //| """Returns the packet queued count.""" //| ... +//| static mp_obj_t wifi_monitor_obj_get_queued(mp_obj_t self_in) { if (common_hal_wifi_monitor_deinited()) { return mp_obj_new_int_from_uint(0); @@ -110,6 +115,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_monitor_queued_obj, wifi_monitor_obj_get_queued); //| """Returns the monitor packet.""" //| ... //| +//| static mp_obj_t wifi_monitor_obj_get_packet(mp_obj_t self_in) { if (common_hal_wifi_monitor_deinited()) { raise_deinited_error(); diff --git a/shared-bindings/wifi/Network.c b/shared-bindings/wifi/Network.c index 3b9c0b6116c1b..93a483930e8d2 100644 --- a/shared-bindings/wifi/Network.c +++ b/shared-bindings/wifi/Network.c @@ -17,6 +17,7 @@ //| def __init__(self) -> None: //| """You cannot create an instance of `wifi.Network`. They are returned by `wifi.Radio.start_scanning_networks`.""" //| ... +//| //| ssid: str //| """String id of the network""" @@ -76,8 +77,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_network_get_country_obj, wifi_network_get_country MP_PROPERTY_GETTER(wifi_network_country_obj, (mp_obj_t)&wifi_network_get_country_obj); -//| authmode: str -//| """String id of the authmode""" +//| authmode: Sequence[wifi.AuthMode] +//| """List of authmodes (wifi.AuthMode) used by the network """ +//| //| static mp_obj_t wifi_network_get_authmode(mp_obj_t self) { return common_hal_wifi_network_get_authmode(self); diff --git a/shared-bindings/wifi/Packet.c b/shared-bindings/wifi/Packet.c index 9d7befa7a8aaf..85dd8cc25b103 100644 --- a/shared-bindings/wifi/Packet.c +++ b/shared-bindings/wifi/Packet.c @@ -28,6 +28,7 @@ MAKE_ENUM_VALUE(wifi_packet_type, packet, RSSI, PACKET_RSSI); //| RSSI: object //| """The packet's rssi.""" //| +//| MAKE_ENUM_MAP(wifi_packet) { MAKE_ENUM_MAP_ENTRY(packet, CH), MAKE_ENUM_MAP_ENTRY(packet, LEN), diff --git a/shared-bindings/wifi/PowerManagement.c b/shared-bindings/wifi/PowerManagement.c new file mode 100644 index 0000000000000..659144b024db8 --- /dev/null +++ b/shared-bindings/wifi/PowerManagement.c @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "py/enum.h" + +#include "shared-bindings/wifi/PowerManagement.h" + +//| class PowerManagement: +//| """Power-saving options for wifi +//| +//| .. note:: On boards using the CYW43 radio module, the choices below correspond to the +//| power management values defined in the `cyw43` module: +//| `PowerManagement.MIN` is the same as `cyw43.PM_PERFORMANCE`, `PowerManagement.MAX` +//| is the same as `cyw43.PM_AGGRESSIVE`, and `PowerManagement.NONE` is the same as +//| `cyw43.PM_DISABLED`. If a custom value was set with `cyw43.set_power_management()` +//| not corresponding to one of these three values, then `PowerManagement.UNKNOWN` will be returned. +//| """ +//| +//| MIN: PowerManagement +//| """Minimum power management (default). The WiFi station wakes up to receive a beacon every DTIM period. +//| The DTIM period is set by the access point.""" +//| MAX: PowerManagement +//| """Maximum power management, at the expense of some performance. The WiFi station wakes up less often than `MIN`.""" +//| NONE: PowerManagement +//| """No power management: the WiFi station does not sleep.""" +//| UNKNOWN: PowerManagement +//| """Power management setting cannot be determined.""" +//| + +// In order of the enum type. +MAKE_ENUM_VALUE(wifi_power_management_type, power_management, NONE, POWER_MANAGEMENT_NONE); +MAKE_ENUM_VALUE(wifi_power_management_type, power_management, MIN, POWER_MANAGEMENT_MIN); +MAKE_ENUM_VALUE(wifi_power_management_type, power_management, MAX, POWER_MANAGEMENT_MAX); +MAKE_ENUM_VALUE(wifi_power_management_type, power_management, UNKNOWN, POWER_MANAGEMENT_UNKNOWN); + +MAKE_ENUM_MAP(wifi_power_management) { + MAKE_ENUM_MAP_ENTRY(power_management, NONE), + MAKE_ENUM_MAP_ENTRY(power_management, MIN), + MAKE_ENUM_MAP_ENTRY(power_management, MAX), + MAKE_ENUM_MAP_ENTRY(power_management, UNKNOWN), +}; + +static MP_DEFINE_CONST_DICT(wifi_power_management_locals_dict, wifi_power_management_locals_table); + +MAKE_PRINTER(wifi, wifi_power_management); + +MAKE_ENUM_TYPE(wifi, PowerManagement, wifi_power_management); diff --git a/shared-bindings/wifi/PowerManagement.h b/shared-bindings/wifi/PowerManagement.h new file mode 100644 index 0000000000000..c933e36df154d --- /dev/null +++ b/shared-bindings/wifi/PowerManagement.h @@ -0,0 +1,19 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/enum.h" + +typedef enum { + POWER_MANAGEMENT_NONE = 0, + POWER_MANAGEMENT_MIN = 1, + POWER_MANAGEMENT_MAX = 2, + // Value can't be determined. + POWER_MANAGEMENT_UNKNOWN = 3, +} wifi_power_management_t; + +extern const mp_obj_type_t wifi_power_management_type; diff --git a/shared-bindings/wifi/Radio.c b/shared-bindings/wifi/Radio.c index 34e48925d3e75..9a7d445fd0473 100644 --- a/shared-bindings/wifi/Radio.c +++ b/shared-bindings/wifi/Radio.c @@ -6,9 +6,11 @@ #include "shared-bindings/wifi/__init__.h" #include "shared-bindings/wifi/AuthMode.h" +#include "shared-bindings/wifi/PowerManagement.h" #include +#include "py/enum.h" #include "py/unicode.h" #include "py/runtime.h" #include "py/objproperty.h" @@ -73,6 +75,7 @@ static void validate_hex_password(const uint8_t *buf, size_t len) { //| """You cannot create an instance of `wifi.Radio`. //| Use `wifi.radio` to access the sole instance available.""" //| ... +//| //| enabled: bool //| """``True`` when the wifi radio is enabled. @@ -96,7 +99,7 @@ MP_PROPERTY_GETSET(wifi_radio_enabled_obj, (mp_obj_t)&wifi_radio_get_enabled_obj, (mp_obj_t)&wifi_radio_set_enabled_obj); -//| hostname: Union[str | ReadableBuffer] +//| hostname: Union[str, ReadableBuffer] //| """Hostname for wifi interface. When the hostname is altered after interface started/connected //| the changes would only be reflected once the interface restarts/reconnects.""" static mp_obj_t wifi_radio_get_hostname(mp_obj_t self_in) { @@ -186,33 +189,30 @@ MP_PROPERTY_GETSET(wifi_radio_tx_power_obj, (mp_obj_t)&wifi_radio_get_tx_power_obj, (mp_obj_t)&wifi_radio_set_tx_power_obj); -//| listen_interval: int -//| """Wifi power save listen interval, in DTIM periods, or 100ms intervals if TWT is supported.""" -static mp_obj_t wifi_radio_get_listen_interval(mp_obj_t self_in) { - #if CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL +//| power_management: PowerManagement +//| """Wifi power management setting. See `wifi.PowerManagement`. The default is `wifi.PowerManagement.MIN`. +//| """ +static mp_obj_t wifi_radio_get_power_management(mp_obj_t self_in) { wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(common_hal_wifi_radio_get_listen_interval(self)); - #else - return mp_obj_new_int(0); - #endif + return cp_enum_find(&wifi_power_management_type, common_hal_wifi_radio_get_power_management(self)); } -MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_listen_interval_obj, wifi_radio_get_listen_interval); +MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_power_management_obj, wifi_radio_get_power_management); -static mp_obj_t wifi_radio_set_listen_interval(mp_obj_t self_in, mp_obj_t listen_interval_in) { - #if CIRCUITPY_WIFI_RADIO_SETTABLE_LISTEN_INTERVAL - mp_int_t listen_interval = mp_obj_get_int(listen_interval_in); +static mp_obj_t wifi_radio_set_power_management(mp_obj_t self_in, mp_obj_t power_management_in) { wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in); - common_hal_wifi_radio_set_listen_interval(self, listen_interval); - #else - mp_raise_NotImplementedError(NULL); - #endif + wifi_power_management_t power_management = + cp_enum_value(&wifi_power_management_type, power_management_in, MP_QSTR_power_management); + if (power_management == POWER_MANAGEMENT_UNKNOWN) { + mp_arg_error_invalid(MP_QSTR_power_management); + } + common_hal_wifi_radio_set_power_management(self, power_management); return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_2(wifi_radio_set_listen_interval_obj, wifi_radio_set_listen_interval); +MP_DEFINE_CONST_FUN_OBJ_2(wifi_radio_set_power_management_obj, wifi_radio_set_power_management); -MP_PROPERTY_GETSET(wifi_radio_listen_interval_obj, - (mp_obj_t)&wifi_radio_get_listen_interval_obj, - (mp_obj_t)&wifi_radio_set_listen_interval_obj); +MP_PROPERTY_GETSET(wifi_radio_power_management_obj, + (mp_obj_t)&wifi_radio_get_power_management_obj, + (mp_obj_t)&wifi_radio_set_power_management_obj); //| mac_address_ap: ReadableBuffer //| """MAC address for the AP. When the address is altered after interface is started @@ -220,6 +220,7 @@ MP_PROPERTY_GETSET(wifi_radio_listen_interval_obj, //| //| **Limitations:** Not settable on RP2040 CYW43 boards, such as Pi Pico W. //| """ +//| static mp_obj_t wifi_radio_get_mac_address_ap(mp_obj_t self_in) { wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in); return MP_OBJ_FROM_PTR(common_hal_wifi_radio_get_mac_address_ap(self)); @@ -262,6 +263,7 @@ MP_PROPERTY_GETTER(wifi_radio_mac_address_ap_obj, //| In the raspberrypi port (RP2040 CYW43), ``start_channel`` and ``stop_channel`` are ignored. //| """ //| ... +//| static mp_obj_t wifi_radio_start_scanning_networks(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_start_channel, ARG_stop_channel }; static const mp_arg_t allowed_args[] = { @@ -291,6 +293,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_scanning_networks_obj, 1, wif //| def stop_scanning_networks(self) -> None: //| """Stop scanning for Wifi networks and free any resources used to do it.""" //| ... +//| static mp_obj_t wifi_radio_stop_scanning_networks(mp_obj_t self_in) { wifi_radio_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -303,6 +306,7 @@ static MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_scanning_networks_obj, wifi_rad //| def start_station(self) -> None: //| """Starts a Station.""" //| ... +//| static mp_obj_t wifi_radio_start_station(mp_obj_t self) { common_hal_wifi_radio_start_station(self); return mp_const_none; @@ -312,6 +316,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_station_obj, wifi_radio_start_station //| def stop_station(self) -> None: //| """Stops the Station.""" //| ... +//| static mp_obj_t wifi_radio_stop_station(mp_obj_t self) { common_hal_wifi_radio_stop_station(self); return mp_const_none; @@ -320,8 +325,8 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_station_obj, wifi_radio_stop_station); //| def start_ap( //| self, -//| ssid: Union[str | ReadableBuffer], -//| password: Union[str | ReadableBuffer] = b"", +//| ssid: Union[str, ReadableBuffer], +//| password: Union[str, ReadableBuffer] = b"", //| *, //| channel: int = 1, //| authmode: Iterable[AuthMode] = (), @@ -355,6 +360,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_station_obj, wifi_radio_stop_station); //| In the raspberrypi port (RP2040 CYW43), ``max_connections`` is ignored. //| """ //| ... +//| static mp_obj_t wifi_radio_start_ap(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ssid, ARG_password, ARG_channel, ARG_authmode, ARG_max_connections }; static const mp_arg_t allowed_args[] = { @@ -412,6 +418,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_ap_obj, 1, wifi_radio_start_a //| def stop_ap(self) -> None: //| """Stops the access point.""" //| ... +//| static mp_obj_t wifi_radio_stop_ap(mp_obj_t self) { common_hal_wifi_radio_stop_ap(self); return mp_const_none; @@ -420,6 +427,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_ap_obj, wifi_radio_stop_ap); //| ap_active: bool //| """True if running as an access point. (read-only)""" +//| static mp_obj_t wifi_radio_get_ap_active(mp_obj_t self) { return mp_obj_new_bool(common_hal_wifi_radio_get_ap_active(self)); } @@ -430,11 +438,11 @@ MP_PROPERTY_GETTER(wifi_radio_ap_active_obj, //| def connect( //| self, -//| ssid: Union[str | ReadableBuffer], -//| password: Union[str | ReadableBuffer] = b"", +//| ssid: Union[str, ReadableBuffer], +//| password: Union[str, ReadableBuffer] = b"", //| *, //| channel: int = 0, -//| bssid: Optional[Union[str | ReadableBuffer]] = None, +//| bssid: Optional[Union[str, ReadableBuffer]] = None, //| timeout: Optional[float] = None, //| ) -> None: //| """Connects to the given ssid and waits for an ip address. Reconnections are handled @@ -453,6 +461,7 @@ MP_PROPERTY_GETTER(wifi_radio_ap_active_obj, //| If ``bssid`` is given and not None, the scan will start at the first channel or the one given and //| connect to the AP with the given ``bssid`` and ``ssid``.""" //| ... +//| static mp_obj_t wifi_radio_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ssid, ARG_password, ARG_channel, ARG_bssid, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -556,6 +565,7 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_subnet_obj, //| ipv4_subnet_ap: Optional[ipaddress.IPv4Address] //| """IP v4 Address of the access point subnet, when enabled. None otherwise. (read-only)""" +//| static mp_obj_t wifi_radio_get_ipv4_subnet_ap(mp_obj_t self) { return common_hal_wifi_radio_get_ipv4_subnet_ap(self); } @@ -580,6 +590,7 @@ MP_PROPERTY_GETTER(wifi_radio_ipv4_subnet_ap_obj, //| In the raspberrypi port (RP2040 CYW43), the access point needs to be started before the IP v4 address can be set. //| """ //| ... +//| static mp_obj_t wifi_radio_set_ipv4_address(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ipv4, ARG_netmask, ARG_gateway, ARG_ipv4_dns }; static const mp_arg_t allowed_args[] = { @@ -607,6 +618,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_set_ipv4_address_obj, 1, wifi_radio //| ) -> None: //| """Sets the IP v4 address of the access point. Must include the netmask and gateway.""" //| ... +//| static mp_obj_t wifi_radio_set_ipv4_address_ap(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ipv4, ARG_netmask, ARG_gateway }; static const mp_arg_t allowed_args[] = { @@ -712,6 +724,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_get_ap_info_obj, wifi_radio_get_ap_info); //| mac: bytearray (read-only) //| rssi: int (read-only, None on Raspberry Pi Pico W) //| ipv4_address: ipv4_address (read-only, None if station connected but no address assigned yet or self-assigned address)""" +//| static mp_obj_t wifi_radio_get_stations_ap(mp_obj_t self) { return common_hal_wifi_radio_get_stations_ap(self); } @@ -729,11 +742,12 @@ MP_PROPERTY_GETTER(wifi_radio_stations_ap_obj, //| then the corresponding DHCP client is stopped if it was active. //| """ //| ... +//| static mp_obj_t wifi_radio_start_dhcp_client(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ipv4, ARG_ipv6 }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_ipv4, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_TRUE } }, - { MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = MP_ROM_FALSE } }, + { MP_QSTR_ipv4, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = true } }, + { MP_QSTR_ipv6, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = false } }, }; wifi_radio_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -748,6 +762,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(wifi_radio_start_dhcp_client_obj, 1, wifi_radi //| def stop_dhcp(self) -> None: //| """Stops the station DHCP client. Needed to assign a static IP address.""" //| ... +//| static mp_obj_t wifi_radio_stop_dhcp_client(mp_obj_t self) { common_hal_wifi_radio_stop_dhcp_client(self); return mp_const_none; @@ -757,6 +772,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_stop_dhcp_client_obj, wifi_radio_stop_dhcp_ //| def start_dhcp_ap(self) -> None: //| """Starts the access point DHCP server.""" //| ... +//| static mp_obj_t wifi_radio_start_dhcp_server(mp_obj_t self) { common_hal_wifi_radio_start_dhcp_server(self); return mp_const_none; @@ -766,6 +782,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(wifi_radio_start_dhcp_server_obj, wifi_radio_start_dhc //| def stop_dhcp_ap(self) -> None: //| """Stops the access point DHCP server. Needed to assign a static IP address.""" //| ... +//| static mp_obj_t wifi_radio_stop_dhcp_server(mp_obj_t self) { common_hal_wifi_radio_stop_dhcp_server(self); return mp_const_none; @@ -787,6 +804,7 @@ MP_PROPERTY_GETTER(wifi_radio_ap_info_obj, //| """ //| ... //| +//| static mp_obj_t wifi_radio_ping(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_ip, ARG_timeout }; static const mp_arg_t allowed_args[] = { @@ -849,6 +867,7 @@ static const mp_rom_map_elem_t wifi_radio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ipv4_subnet_ap), MP_ROM_PTR(&wifi_radio_ipv4_subnet_ap_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address), MP_ROM_PTR(&wifi_radio_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_ipv4_address_ap_obj) }, + { MP_ROM_QSTR(MP_QSTR_power_management), MP_ROM_PTR(&wifi_radio_power_management_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address), MP_ROM_PTR(&wifi_radio_set_ipv4_address_obj) }, { MP_ROM_QSTR(MP_QSTR_set_ipv4_address_ap), MP_ROM_PTR(&wifi_radio_set_ipv4_address_ap_obj) }, diff --git a/shared-bindings/wifi/Radio.h b/shared-bindings/wifi/Radio.h index ac352626dccba..d3c12344b8706 100644 --- a/shared-bindings/wifi/Radio.h +++ b/shared-bindings/wifi/Radio.h @@ -8,6 +8,8 @@ #include +#include "shared-bindings/wifi/PowerManagement.h" + #include "common-hal/wifi/Radio.h" #include "py/objstr.h" @@ -75,8 +77,8 @@ extern void common_hal_wifi_radio_set_mac_address_ap(wifi_radio_obj_t *self, con extern mp_float_t common_hal_wifi_radio_get_tx_power(wifi_radio_obj_t *self); extern void common_hal_wifi_radio_set_tx_power(wifi_radio_obj_t *self, const mp_float_t power); -extern void common_hal_wifi_radio_set_listen_interval(wifi_radio_obj_t *self, const mp_int_t listen_interval); -extern mp_int_t common_hal_wifi_radio_get_listen_interval(wifi_radio_obj_t *self); +extern wifi_power_management_t common_hal_wifi_radio_get_power_management(wifi_radio_obj_t *self); +extern void common_hal_wifi_radio_set_power_management(wifi_radio_obj_t *self, wifi_power_management_t power_management); extern mp_obj_t common_hal_wifi_radio_start_scanning_networks(wifi_radio_obj_t *self, uint8_t start_channel, uint8_t stop_channel); extern void common_hal_wifi_radio_stop_scanning_networks(wifi_radio_obj_t *self); diff --git a/shared-bindings/wifi/ScannedNetworks.c b/shared-bindings/wifi/ScannedNetworks.c index dea3474d423e1..2fb5c2a578769 100644 --- a/shared-bindings/wifi/ScannedNetworks.c +++ b/shared-bindings/wifi/ScannedNetworks.c @@ -40,6 +40,7 @@ static mp_obj_t scannednetworks_iternext(mp_obj_t self_in) { //| Raises `StopIteration` if scanning is finished and no other results are available.""" //| ... //| +//| MP_DEFINE_CONST_OBJ_TYPE( wifi_scannednetworks_type, diff --git a/shared-bindings/wifi/__init__.c b/shared-bindings/wifi/__init__.c index 3b09255052e02..2a1c0097080db 100644 --- a/shared-bindings/wifi/__init__.c +++ b/shared-bindings/wifi/__init__.c @@ -15,6 +15,7 @@ //| The `wifi` module provides necessary low-level functionality for managing //| wifi connections. Use `socketpool` for communicating over the network. //| """ +//| //| radio: Radio //| """Wifi radio used to manage both station and AP modes. @@ -29,21 +30,22 @@ static MP_DEFINE_CONST_FUN_OBJ_0(wifi___init___obj, wifi___init__); static const mp_rom_map_elem_t wifi_module_globals_table[] = { // Name - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wifi) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_wifi) }, // Initialization - { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&wifi___init___obj) }, + { MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&wifi___init___obj) }, // Classes - { MP_ROM_QSTR(MP_QSTR_AuthMode), MP_ROM_PTR(&wifi_authmode_type) }, - { MP_ROM_QSTR(MP_QSTR_Monitor), MP_ROM_PTR(&wifi_monitor_type) }, - { MP_ROM_QSTR(MP_QSTR_Network), MP_ROM_PTR(&wifi_network_type) }, - { MP_ROM_QSTR(MP_QSTR_Packet), MP_ROM_PTR(&wifi_packet_type) }, - { MP_ROM_QSTR(MP_QSTR_Radio), MP_ROM_PTR(&wifi_radio_type) }, - { MP_ROM_QSTR(MP_QSTR_Station), MP_ROM_PTR(&wifi_radio_station_type) }, + { MP_ROM_QSTR(MP_QSTR_AuthMode), MP_ROM_PTR(&wifi_authmode_type) }, + { MP_ROM_QSTR(MP_QSTR_Monitor), MP_ROM_PTR(&wifi_monitor_type) }, + { MP_ROM_QSTR(MP_QSTR_Network), MP_ROM_PTR(&wifi_network_type) }, + { MP_ROM_QSTR(MP_QSTR_Packet), MP_ROM_PTR(&wifi_packet_type) }, + { MP_ROM_QSTR(MP_QSTR_PowerManagement), MP_ROM_PTR(&wifi_power_management_type) }, + { MP_ROM_QSTR(MP_QSTR_Radio), MP_ROM_PTR(&wifi_radio_type) }, + { MP_ROM_QSTR(MP_QSTR_Station), MP_ROM_PTR(&wifi_radio_station_type) }, // Properties - { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) }, + { MP_ROM_QSTR(MP_QSTR_radio), MP_ROM_PTR(&common_hal_wifi_radio_obj) }, }; static MP_DEFINE_CONST_DICT(wifi_module_globals, wifi_module_globals_table); diff --git a/shared-bindings/zlib/__init__.c b/shared-bindings/zlib/__init__.c index f9db723c4fc3c..a17694d8a2e81 100644 --- a/shared-bindings/zlib/__init__.c +++ b/shared-bindings/zlib/__init__.c @@ -25,6 +25,7 @@ //| This module allows to decompress binary data compressed with DEFLATE algorithm //| (commonly used in zlib library and gzip archiver). Compression is not yet implemented.""" //| +//| //| def decompress(data: bytes, wbits: Optional[int] = 0, bufsize: Optional[int] = 0) -> bytes: //| """Return decompressed *data* as bytes. *wbits* is DEFLATE dictionary window @@ -48,6 +49,7 @@ //| """ //| ... //| +//| static mp_obj_t zlib_decompress(size_t n_args, const mp_obj_t *args) { mp_int_t wbits = 0; if (n_args > 1) { diff --git a/shared-module/_eve/__init__.c b/shared-module/_eve/__init__.c index 881528ca0da0e..ca084d9b43b36 100644 --- a/shared-module/_eve/__init__.c +++ b/shared-module/_eve/__init__.c @@ -75,7 +75,7 @@ void common_hal__eve_BitmapExtFormat(common_hal__eve_t *eve, uint32_t fmt) { void common_hal__eve_BitmapHandle(common_hal__eve_t *eve, uint32_t handle) { - C4(eve, ((5 << 24) | ((handle & 31)))); + C4(eve, ((5 << 24) | ((handle & 63)))); } @@ -104,6 +104,11 @@ void common_hal__eve_BitmapSource(common_hal__eve_t *eve, uint32_t addr) { } +void common_hal__eve_BitmapSourceH(common_hal__eve_t *eve, uint32_t addr) { + C4(eve, ((49 << 24) | ((addr & 0xff)))); +} + + void common_hal__eve_BitmapSwizzle(common_hal__eve_t *eve, uint32_t r, uint32_t g, uint32_t b, uint32_t a) { C4(eve, ((47 << 24) | ((r & 7) << 9) | ((g & 7) << 6) | ((b & 7) << 3) | ((a & 7)))); } @@ -175,7 +180,7 @@ void common_hal__eve_ClearStencil(common_hal__eve_t *eve, uint32_t s) { void common_hal__eve_ClearTag(common_hal__eve_t *eve, uint32_t s) { - C4(eve, ((18 << 24) | ((s & 255)))); + C4(eve, ((18 << 24) | ((s & 0xffffff)))); } @@ -226,7 +231,12 @@ void common_hal__eve_Nop(common_hal__eve_t *eve) { void common_hal__eve_PaletteSource(common_hal__eve_t *eve, uint32_t addr) { - C4(eve, ((42 << 24) | (((addr) & 4194303)))); + C4(eve, ((42 << 24) | (((addr) & 0xffffff)))); +} + + +void common_hal__eve_PaletteSourceH(common_hal__eve_t *eve, uint32_t addr) { + C4(eve, ((50 << 24) | (((addr) & 0xff)))); } @@ -236,6 +246,11 @@ void common_hal__eve_PointSize(common_hal__eve_t *eve, mp_float_t size) { } +void common_hal__eve_Region(common_hal__eve_t *eve, uint32_t y, uint32_t h, uint32_t dest) { + C4(eve, ((52 << 24) | ((y & 0x3f) << 18) | ((h & 0x3f) << 12) | (dest & 0xfff))); +} + + void common_hal__eve_RestoreContext(common_hal__eve_t *eve) { C4(eve, ((35 << 24))); } @@ -282,7 +297,7 @@ void common_hal__eve_TagMask(common_hal__eve_t *eve, uint32_t mask) { void common_hal__eve_Tag(common_hal__eve_t *eve, uint32_t s) { - C4(eve, ((3 << 24) | ((s & 255)))); + C4(eve, ((3 << 24) | ((s & 0xffffff)))); } diff --git a/shared-module/_eve/__init__.h b/shared-module/_eve/__init__.h index 227fe8fc935e9..b25d9bf662031 100644 --- a/shared-module/_eve/__init__.h +++ b/shared-module/_eve/__init__.h @@ -8,6 +8,7 @@ typedef struct _common_hal__eve_t { mp_obj_t dest[3]; // Own 'write' method, plus argument + int model; // 0 for unknown, or 810, 815, 817 for the three EVE generations int vscale; // fixed-point scaling used for Vertex2f size_t n; // Current size of command buffer uint8_t buf[512]; // Command buffer diff --git a/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c b/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c index 0795e29f38294..e01875452b119 100644 --- a/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c +++ b/shared-module/adafruit_bus_device/i2c_device/I2CDevice.c @@ -41,30 +41,14 @@ void common_hal_adafruit_bus_device_i2cdevice_unlock(adafruit_bus_device_i2cdevi void common_hal_adafruit_bus_device_i2cdevice_probe_for_device(adafruit_bus_device_i2cdevice_obj_t *self) { common_hal_adafruit_bus_device_i2cdevice_lock(self); - mp_buffer_info_t write_bufinfo; - mp_obj_t write_buffer = mp_obj_new_bytearray_of_zeros(0); - mp_get_buffer_raise(write_buffer, &write_bufinfo, MP_BUFFER_READ); + mp_obj_t dest[3]; + mp_load_method(self->i2c, MP_QSTR_probe, dest); + dest[2] = MP_OBJ_NEW_SMALL_INT(self->device_address); + const bool found = mp_obj_is_true(mp_call_method_n_kw(1, 0, dest)); - mp_obj_t dest[4]; - - /* catch exceptions that may be thrown while probing for the device */ - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_load_method(self->i2c, MP_QSTR_writeto, dest); - dest[2] = MP_OBJ_NEW_SMALL_INT(self->device_address); - dest[3] = write_buffer; - mp_call_method_n_kw(2, 0, dest); - nlr_pop(); - } else { - common_hal_adafruit_bus_device_i2cdevice_unlock(self); + common_hal_adafruit_bus_device_i2cdevice_unlock(self); - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_OSError))) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("No I2C device at address: 0x%x"), self->device_address); - } else { - /* In case we receive an unrelated exception pass it up */ - nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val)); - } + if (!found) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("No I2C device at address: 0x%x"), self->device_address); } - - common_hal_adafruit_bus_device_i2cdevice_unlock(self); } diff --git a/shared-module/adafruit_pixelbuf/PixelBuf.c b/shared-module/adafruit_pixelbuf/PixelBuf.c index 0eb1afe9adb1c..155862f17a361 100644 --- a/shared-module/adafruit_pixelbuf/PixelBuf.c +++ b/shared-module/adafruit_pixelbuf/PixelBuf.c @@ -30,13 +30,10 @@ void common_hal_adafruit_pixelbuf_pixelbuf_construct(pixelbuf_pixelbuf_obj_t *se self->auto_write = false; size_t pixel_len = self->pixel_count * self->bytes_per_pixel; - self->transmit_buffer_obj = mp_obj_new_bytes_of_zeros(header_len + pixel_len + trailer_len); - mp_obj_str_t *o = MP_OBJ_TO_PTR(self->transmit_buffer_obj); + self->transmit_buffer_obj = mp_obj_new_bytearray_of_zeros(header_len + pixel_len + trailer_len); + mp_obj_array_t *o = MP_OBJ_TO_PTR(self->transmit_buffer_obj); - // Abuse the bytes object a bit by mutating it's data by dropping the const. If the user's - // Python code holds onto it, they'll find out that it changes. At least this way it isn't - // mutable by the code itself. - uint8_t *transmit_buffer = (uint8_t *)o->data; + uint8_t *transmit_buffer = o->items; memcpy(transmit_buffer, header, header_len); memcpy(transmit_buffer + header_len + pixel_len, trailer, trailer_len); self->post_brightness_buffer = transmit_buffer + header_len; @@ -103,7 +100,7 @@ void common_hal_adafruit_pixelbuf_pixelbuf_set_brightness(mp_obj_t self_in, mp_f return; } else { if (self->pre_brightness_buffer == NULL) { - self->pre_brightness_buffer = m_malloc(pixel_len); + self->pre_brightness_buffer = m_malloc_without_collect(pixel_len); memcpy(self->pre_brightness_buffer, self->post_brightness_buffer, pixel_len); } for (size_t i = 0; i < pixel_len; i++) { diff --git a/shared-module/atexit/__init__.c b/shared-module/atexit/__init__.c index ff369e83c77c1..537a2a9d969a1 100644 --- a/shared-module/atexit/__init__.c +++ b/shared-module/atexit/__init__.c @@ -12,8 +12,13 @@ static size_t callback_len = 0; static atexit_callback_t *callback = NULL; void atexit_reset(void) { - callback_len = 0; + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(callback, callback_len * sizeof(atexit_callback_t)); + #else m_free(callback); + #endif + + callback_len = 0; callback = NULL; } @@ -23,14 +28,14 @@ void atexit_gc_collect(void) { void shared_module_atexit_register(mp_obj_t *func, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { if (!mp_obj_is_callable(func)) { - mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object is not callable"), mp_obj_get_type_qstr(func)); + mp_raise_TypeError_varg(MP_ERROR_TEXT("'%q' object isn't callable"), mp_obj_get_type_qstr(func)); } size_t n_kw_args = (kw_args) ? kw_args->used : 0; atexit_callback_t cb = { .n_pos = 0, .n_kw = 0, .func = func, - .args = (n_args + n_kw_args) ? m_malloc((n_args + (n_kw_args * 2)) * sizeof(mp_obj_t)) : NULL + .args = (n_args + n_kw_args) ? m_malloc_items(n_args + (n_kw_args * 2)) : NULL }; for (; cb.n_pos < n_args; cb.n_pos++) { cb.args[cb.n_pos] = pos_args[cb.n_pos]; @@ -39,7 +44,13 @@ void shared_module_atexit_register(mp_obj_t *func, size_t n_args, const mp_obj_t cb.args[i] = kw_args->table[cb.n_kw].key; cb.args[i += 1] = kw_args->table[cb.n_kw].value; } - callback = (atexit_callback_t *)m_realloc(callback, (callback_len + 1) * sizeof(cb)); + + callback = (atexit_callback_t *)m_realloc(callback, + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + callback_len *sizeof(cb), // Old size + #endif + (callback_len + 1) * sizeof(cb)); + callback[callback_len++] = cb; } diff --git a/shared-module/audiocore/RawSample.c b/shared-module/audiocore/RawSample.c index 9944597d08f1c..900b42c3c3e7d 100644 --- a/shared-module/audiocore/RawSample.c +++ b/shared-module/audiocore/RawSample.c @@ -7,6 +7,7 @@ // SPDX-License-Identifier: MIT #include "shared-bindings/audiocore/RawSample.h" +#include "shared-bindings/audiocore/__init__.h" #include @@ -22,34 +23,18 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t *self, bool single_buffer) { self->buffer = buffer; - self->bits_per_sample = bytes_per_sample * 8; - self->samples_signed = samples_signed; - self->len = len; - self->channel_count = channel_count; - self->sample_rate = sample_rate; - self->single_buffer = single_buffer; + self->base.bits_per_sample = bytes_per_sample * 8; + self->base.samples_signed = samples_signed; + self->base.max_buffer_length = len; + self->base.channel_count = channel_count; + self->base.sample_rate = sample_rate; + self->base.single_buffer = single_buffer; self->buffer_index = 0; } void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t *self) { self->buffer = NULL; -} -bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t *self) { - return self->buffer == NULL; -} - -uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t *self) { - return self->sample_rate; -} -void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t *self, - uint32_t sample_rate) { - self->sample_rate = sample_rate; -} -uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t *self) { - return self->bits_per_sample; -} -uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t *self) { - return self->channel_count; + audiosample_mark_deinit(&self->base); } void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t *self, @@ -63,37 +48,23 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t uint8_t **buffer, uint32_t *buffer_length) { - if (self->single_buffer) { - *buffer_length = self->len; + if (self->base.single_buffer) { + *buffer_length = self->base.max_buffer_length; if (single_channel_output) { - *buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8); + *buffer = self->buffer + (channel % self->base.channel_count) * (self->base.bits_per_sample / 8); } else { *buffer = self->buffer; } return GET_BUFFER_DONE; } else { - *buffer_length = self->len / 2; + *buffer_length = self->base.max_buffer_length / 2; if (single_channel_output) { - *buffer = self->buffer + (channel % self->channel_count) * (self->bits_per_sample / 8) + \ - self->len / 2 * self->buffer_index; + *buffer = self->buffer + (channel % self->base.channel_count) * (self->base.bits_per_sample / 8) + \ + self->base.max_buffer_length / 2 * self->buffer_index; } else { - *buffer = self->buffer + self->len / 2 * self->buffer_index; + *buffer = self->buffer + self->base.max_buffer_length / 2 * self->buffer_index; } self->buffer_index = 1 - self->buffer_index; return GET_BUFFER_DONE; } } - -void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing) { - - *single_buffer = self->single_buffer; - *samples_signed = self->samples_signed; - *max_buffer_length = self->len; - if (single_channel_output) { - *spacing = self->channel_count; - } else { - *spacing = 1; - } -} diff --git a/shared-module/audiocore/RawSample.h b/shared-module/audiocore/RawSample.h index 3fa94404f1c4a..1489bc3f504d0 100644 --- a/shared-module/audiocore/RawSample.h +++ b/shared-module/audiocore/RawSample.h @@ -11,14 +11,8 @@ #include "shared-module/audiocore/__init__.h" typedef struct { - mp_obj_base_t base; + audiosample_base_t base; uint8_t *buffer; - uint32_t len; - uint8_t bits_per_sample; - bool samples_signed; - uint8_t channel_count; - uint32_t sample_rate; - bool single_buffer; uint8_t buffer_index; } audioio_rawsample_obj_t; @@ -32,6 +26,3 @@ audioio_get_buffer_result_t audioio_rawsample_get_buffer(audioio_rawsample_obj_t uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audioio_rawsample_get_buffer_structure(audioio_rawsample_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiocore/WaveFile.c b/shared-module/audiocore/WaveFile.c index 50f56303e9503..77ca2445edbf3 100644 --- a/shared-module/audiocore/WaveFile.c +++ b/shared-module/audiocore/WaveFile.c @@ -13,6 +13,7 @@ #include "py/runtime.h" #include "shared-module/audiocore/WaveFile.h" +#include "shared-bindings/audiocore/__init__.h" struct wave_format_chunk { uint16_t audio_format; @@ -21,7 +22,11 @@ struct wave_format_chunk { uint32_t byte_rate; uint16_t block_align; uint16_t bits_per_sample; - uint16_t extra_params; // Assumed to be zero below. + uint16_t extra_params; + uint16_t valid_bits_per_sample; + uint32_t channel_mask; + uint16_t extended_audio_format; + uint8_t extended_guid[14]; }; void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, @@ -56,37 +61,54 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, if (bytes_read != format_size) { } - if (format.audio_format != 1 || + if ((format_size != 40 && format.audio_format != 1) || format.num_channels > 2 || format.bits_per_sample > 16 || - (format_size == 18 && - format.extra_params != 0)) { - mp_raise_ValueError(MP_ERROR_TEXT("Unsupported format")); + (format_size == 18 && format.extra_params != 0) || + (format_size == 40 && + (format.audio_format != 0xfffe || + format.extended_audio_format != 1 || + format.valid_bits_per_sample != format.bits_per_sample))) { + mp_raise_ValueError(MP_ERROR_TEXT("Format not supported")); } // Get the sample_rate - self->sample_rate = format.sample_rate; - self->channel_count = format.num_channels; - self->bits_per_sample = format.bits_per_sample; + self->base.sample_rate = format.sample_rate; + self->base.channel_count = format.num_channels; + self->base.bits_per_sample = format.bits_per_sample; + self->base.samples_signed = format.bits_per_sample > 8; + self->base.max_buffer_length = 512; + self->base.single_buffer = false; + + uint8_t chunk_tag[4]; + uint32_t chunk_length; + bool found_data_chunk = false; + + while (!found_data_chunk) { + if (f_read(&self->file->fp, &chunk_tag, 4, &bytes_read) != FR_OK) { + mp_raise_OSError(MP_EIO); + } + if (bytes_read != 4) { + mp_raise_OSError(MP_EIO); + } + if (memcmp((uint8_t *)chunk_tag, "data", 4) == 0) { + found_data_chunk = true; + } - // TODO(tannewt): Skip any extra chunks that occur before the data section. + if (f_read(&self->file->fp, &chunk_length, 4, &bytes_read) != FR_OK) { + mp_raise_OSError(MP_EIO); + } + if (bytes_read != 4) { + mp_raise_OSError(MP_EIO); + } - uint8_t data_tag[4]; - if (f_read(&self->file->fp, &data_tag, 4, &bytes_read) != FR_OK) { - mp_raise_OSError(MP_EIO); - } - if (bytes_read != 4 || - memcmp((uint8_t *)data_tag, "data", 4) != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Data chunk must follow fmt chunk")); + if (!found_data_chunk) { + if (f_lseek(&self->file->fp, f_tell(&self->file->fp) + chunk_length) != FR_OK) { + mp_raise_OSError(MP_EIO); + } + } } - uint32_t data_length; - if (f_read(&self->file->fp, &data_length, 4, &bytes_read) != FR_OK) { - mp_raise_OSError(MP_EIO); - } - if (bytes_read != 4) { - mp_arg_error_invalid(MP_QSTR_file); - } - self->file_length = data_length; + self->file_length = chunk_length; self->data_start = self->file->fp.fptr; // Try to allocate two buffers, one will be loaded from file and the other @@ -97,13 +119,13 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, self->second_buffer = buffer + self->len; } else { self->len = 256; - self->buffer = m_malloc(self->len); + self->buffer = m_malloc_without_collect(self->len); if (self->buffer == NULL) { common_hal_audioio_wavefile_deinit(self); m_malloc_fail(self->len); } - self->second_buffer = m_malloc(self->len); + self->second_buffer = m_malloc_without_collect(self->len); if (self->second_buffer == NULL) { common_hal_audioio_wavefile_deinit(self); m_malloc_fail(self->len); @@ -114,27 +136,7 @@ void common_hal_audioio_wavefile_construct(audioio_wavefile_obj_t *self, void common_hal_audioio_wavefile_deinit(audioio_wavefile_obj_t *self) { self->buffer = NULL; self->second_buffer = NULL; -} - -bool common_hal_audioio_wavefile_deinited(audioio_wavefile_obj_t *self) { - return self->buffer == NULL; -} - -uint32_t common_hal_audioio_wavefile_get_sample_rate(audioio_wavefile_obj_t *self) { - return self->sample_rate; -} - -void common_hal_audioio_wavefile_set_sample_rate(audioio_wavefile_obj_t *self, - uint32_t sample_rate) { - self->sample_rate = sample_rate; -} - -uint8_t common_hal_audioio_wavefile_get_bits_per_sample(audioio_wavefile_obj_t *self) { - return self->bits_per_sample; -} - -uint8_t common_hal_audioio_wavefile_get_channel_count(audioio_wavefile_obj_t *self) { - return self->channel_count; + audiosample_mark_deinit(&self->base); } void audioio_wavefile_reset_buffer(audioio_wavefile_obj_t *self, @@ -193,11 +195,11 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t * if (self->bytes_remaining == 0 && length_read % sizeof(uint32_t) != 0) { uint32_t pad = length_read % sizeof(uint32_t); length_read += pad; - if (self->bits_per_sample == 8) { + if (self->base.bits_per_sample == 8) { for (uint32_t i = 0; i < pad; i++) { ((uint8_t *)(*buffer))[length_read / sizeof(uint8_t) - i - 1] = 0x80; } - } else if (self->bits_per_sample == 16) { + } else if (self->base.bits_per_sample == 16) { // We know the buffer is aligned because we allocated it onto the heap ourselves. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" @@ -228,22 +230,8 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t * self->left_read_count += 1; } else if (channel == 1) { self->right_read_count += 1; - *buffer = *buffer + self->bits_per_sample / 8; + *buffer = *buffer + self->base.bits_per_sample / 8; } return self->bytes_remaining == 0 ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA; } - -void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing) { - *single_buffer = false; - // In WAV files, 8-bit samples are always unsigned, and larger samples are always signed. - *samples_signed = self->bits_per_sample > 8; - *max_buffer_length = 512; - if (single_channel_output) { - *spacing = self->channel_count; - } else { - *spacing = 1; - } -} diff --git a/shared-module/audiocore/WaveFile.h b/shared-module/audiocore/WaveFile.h index a86c1409abc9a..74e25ffebfec0 100644 --- a/shared-module/audiocore/WaveFile.h +++ b/shared-module/audiocore/WaveFile.h @@ -12,20 +12,16 @@ #include "shared-module/audiocore/__init__.h" typedef struct { - mp_obj_base_t base; + audiosample_base_t base; uint8_t *buffer; uint32_t buffer_length; uint8_t *second_buffer; uint32_t second_buffer_length; uint32_t file_length; // In bytes uint16_t data_start; // Where the data values start - uint8_t bits_per_sample; uint16_t buffer_index; uint32_t bytes_remaining; - uint8_t channel_count; - uint32_t sample_rate; - uint32_t len; pyb_file_obj_t *file; @@ -43,6 +39,3 @@ audioio_get_buffer_result_t audioio_wavefile_get_buffer(audioio_wavefile_obj_t * uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audioio_wavefile_get_buffer_structure(audioio_wavefile_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index ff3c9652807c0..2ee683d75e1cd 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -7,6 +7,7 @@ #include "shared-module/audioio/__init__.h" #include "py/obj.h" +#include "py/runtime.h" #include "shared-bindings/audiocore/RawSample.h" #include "shared-bindings/audiocore/WaveFile.h" #include "shared-module/audiocore/RawSample.h" @@ -15,21 +16,6 @@ #include "shared-bindings/audiomixer/Mixer.h" #include "shared-module/audiomixer/Mixer.h" -uint32_t audiosample_sample_rate(mp_obj_t sample_obj) { - const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - return proto->sample_rate(MP_OBJ_TO_PTR(sample_obj)); -} - -uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) { - const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - return proto->bits_per_sample(MP_OBJ_TO_PTR(sample_obj)); -} - -uint8_t audiosample_channel_count(mp_obj_t sample_obj) { - const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - return proto->channel_count(MP_OBJ_TO_PTR(sample_obj)); -} - void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel) { const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, audio_channel); @@ -43,14 +29,6 @@ audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel_output, channel, buffer, buffer_length); } -void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing) { - const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); - proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel_output, single_buffer, - samples_signed, max_buffer_length, spacing); -} - void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes) { for (; nframes--;) { int16_t sample = (*buffer_in++ - 0x80) << 8; @@ -59,7 +37,6 @@ void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, } } - void audiosample_convert_u8s_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes) { size_t nsamples = 2 * nframes; for (; nsamples--;) { @@ -76,7 +53,6 @@ void audiosample_convert_s8m_s16s(int16_t *buffer_out, const int8_t *buffer_in, } } - void audiosample_convert_s8s_s16s(int16_t *buffer_out, const int8_t *buffer_in, size_t nframes) { size_t nsamples = 2 * nframes; for (; nsamples--;) { @@ -85,7 +61,6 @@ void audiosample_convert_s8s_s16s(int16_t *buffer_out, const int8_t *buffer_in, } } - void audiosample_convert_u16m_s16s(int16_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { for (; nframes--;) { int16_t sample = *buffer_in++ - 0x8000; @@ -94,7 +69,6 @@ void audiosample_convert_u16m_s16s(int16_t *buffer_out, const uint16_t *buffer_i } } - void audiosample_convert_u16s_s16s(int16_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { size_t nsamples = 2 * nframes; for (; nsamples--;) { @@ -110,3 +84,130 @@ void audiosample_convert_s16m_s16s(int16_t *buffer_out, const int16_t *buffer_in *buffer_out++ = sample; } } + + +void audiosample_convert_u8s_u8m(uint8_t *buffer_out, const uint8_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = *buffer_in++ + 0x80; + *buffer_out++ = sample; + buffer_in++; + } +} + +void audiosample_convert_s8m_u8m(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = *buffer_in++ + 0x80; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s8s_u8m(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = *buffer_in++ + 0x80; + *buffer_out++ = sample; + buffer_in++; + } +} + +void audiosample_convert_u16m_u8m(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++) >> 8; + *buffer_out++ = sample; + } +} + +void audiosample_convert_u16s_u8m(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++) >> 8; + *buffer_out++ = sample; + buffer_in++; + } +} + +void audiosample_convert_s16m_u8m(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++ + 0x8000) >> 8; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s16s_u8m(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++ + 0x8000) >> 8; + *buffer_out++ = sample; + buffer_in++; + } +} + + +void audiosample_convert_u8m_u8s(uint8_t *buffer_out, const uint8_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = *buffer_in++; + *buffer_out++ = sample; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s8m_u8s(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = *buffer_in++ + 0x80; + *buffer_out++ = sample; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s8s_u8s(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes) { + size_t nsamples = 2 * nframes; + for (; nsamples--;) { + uint8_t sample = *buffer_in++ + 0x80; + *buffer_out++ = sample; + } +} + +void audiosample_convert_u16m_u8s(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++) >> 8; + *buffer_out++ = sample; + *buffer_out++ = sample; + } +} + +void audiosample_convert_u16s_u8s(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes) { + size_t nsamples = 2 * nframes; + for (; nsamples--;) { + uint8_t sample = (*buffer_in++) >> 8; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s16m_u8s(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes) { + for (; nframes--;) { + uint8_t sample = (*buffer_in++ + 0x8000) >> 8; + *buffer_out++ = sample; + *buffer_out++ = sample; + } +} + +void audiosample_convert_s16s_u8s(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes) { + size_t nsamples = 2 * nframes; + for (; nsamples--;) { + uint8_t sample = (*buffer_in++ + 0x8000) >> 8; + *buffer_out++ = sample; + } +} + +void audiosample_must_match(audiosample_base_t *self, mp_obj_t other_in, bool allow_mono_to_stereo) { + const audiosample_base_t *other = audiosample_check(other_in); + if (other->sample_rate != self->sample_rate) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_sample_rate); + } + if ((!allow_mono_to_stereo || (allow_mono_to_stereo && self->channel_count != 2)) && other->channel_count != self->channel_count) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_channel_count); + } + if (other->bits_per_sample != self->bits_per_sample) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_bits_per_sample); + } + if (other->samples_signed != self->samples_signed) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("The sample's %q does not match"), MP_QSTR_signedness); + } +} diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 0e5b38d7b1445..920fe752c3822 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -18,40 +18,78 @@ typedef enum { GET_BUFFER_ERROR, // Error while reading data. } audioio_get_buffer_result_t; -typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t); -typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t); -typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t); +typedef struct audiosample_base { + mp_obj_base_t self; + uint32_t sample_rate; + uint32_t max_buffer_length; + uint8_t bits_per_sample; + uint8_t channel_count; + uint8_t samples_signed; + bool single_buffer; +} audiosample_base_t; + typedef void (*audiosample_reset_buffer_fun)(mp_obj_t, bool single_channel_output, uint8_t audio_channel); typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t, bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); -typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t, - bool single_channel_output, bool *single_buffer, - bool *samples_signed, uint32_t *max_buffer_length, - uint8_t *spacing); typedef struct _audiosample_p_t { MP_PROTOCOL_HEAD // MP_QSTR_protocol_audiosample - audiosample_sample_rate_fun sample_rate; - audiosample_bits_per_sample_fun bits_per_sample; - audiosample_channel_count_fun channel_count; audiosample_reset_buffer_fun reset_buffer; audiosample_get_buffer_fun get_buffer; - audiosample_get_buffer_structure_fun get_buffer_structure; } audiosample_p_t; -uint32_t audiosample_sample_rate(mp_obj_t sample_obj); -uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); -uint8_t audiosample_channel_count(mp_obj_t sample_obj); +static inline uint32_t audiosample_get_bits_per_sample(audiosample_base_t *self) { + return self->bits_per_sample; +} + +static inline uint32_t audiosample_get_sample_rate(audiosample_base_t *self) { + return self->sample_rate; +} + +static inline void audiosample_set_sample_rate(audiosample_base_t *self, uint32_t sample_rate) { + self->sample_rate = sample_rate; +} + +static inline uint8_t audiosample_get_channel_count(audiosample_base_t *self) { + return self->channel_count; +} + void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t audio_channel); audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); -void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel_output, + +static inline void audiosample_get_buffer_structure(audiosample_base_t *self, bool single_channel_output, + bool *single_buffer, bool *samples_signed, + uint32_t *max_buffer_length, uint8_t *spacing) { + + *single_buffer = self->single_buffer; + *samples_signed = self->samples_signed; + *max_buffer_length = self->max_buffer_length; + + if (single_channel_output) { + *spacing = self->channel_count; + } else { + *spacing = 1; + } +} + +static inline audiosample_base_t *audiosample_check(mp_obj_t self_in) { + // called for side effect + (void)mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, self_in); + return MP_OBJ_TO_PTR(self_in); +} + +static inline void audiosample_get_buffer_structure_checked(mp_obj_t self_in, bool single_channel_output, bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); + uint32_t *max_buffer_length, uint8_t *spacing) { + audiosample_get_buffer_structure(audiosample_check(self_in), single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing); +} + +void audiosample_must_match(audiosample_base_t *self, mp_obj_t other, bool allow_mono_to_stereo); void audiosample_convert_u8m_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes); void audiosample_convert_u8s_s16s(int16_t *buffer_out, const uint8_t *buffer_in, size_t nframes); @@ -60,3 +98,19 @@ void audiosample_convert_s8s_s16s(int16_t *buffer_out, const int8_t *buffer_in, void audiosample_convert_u16m_s16s(int16_t *buffer_out, const uint16_t *buffer_in, size_t nframes); void audiosample_convert_u16s_s16s(int16_t *buffer_out, const uint16_t *buffer_in, size_t nframes); void audiosample_convert_s16m_s16s(int16_t *buffer_out, const int16_t *buffer_in, size_t nframes); + +void audiosample_convert_u8s_u8m(uint8_t *buffer_out, const uint8_t *buffer_in, size_t nframes); +void audiosample_convert_s8m_u8m(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes); +void audiosample_convert_s8s_u8m(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes); +void audiosample_convert_u16m_u8m(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes); +void audiosample_convert_u16s_u8m(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes); +void audiosample_convert_s16m_u8m(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes); +void audiosample_convert_s16s_u8m(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes); + +void audiosample_convert_u8m_u8s(uint8_t *buffer_out, const uint8_t *buffer_in, size_t nframes); +void audiosample_convert_s8m_u8s(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes); +void audiosample_convert_s8s_u8s(uint8_t *buffer_out, const int8_t *buffer_in, size_t nframes); +void audiosample_convert_u16m_u8s(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes); +void audiosample_convert_u16s_u8s(uint8_t *buffer_out, const uint16_t *buffer_in, size_t nframes); +void audiosample_convert_s16m_u8s(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes); +void audiosample_convert_s16s_u8s(uint8_t *buffer_out, const int16_t *buffer_in, size_t nframes); diff --git a/shared-module/audiodelays/Chorus.c b/shared-module/audiodelays/Chorus.c new file mode 100644 index 0000000000000..3c35b902189cd --- /dev/null +++ b/shared-module/audiodelays/Chorus.c @@ -0,0 +1,340 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiodelays/Chorus.h" +#include "shared-bindings/audiocore/__init__.h" + +#include +#include +#include "py/runtime.h" + +void common_hal_audiodelays_chorus_construct(audiodelays_chorus_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t voices, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiodelays_chorus_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiodelays_chorus_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the chorus effect's starting values. For a different effect this section will change + + // If we did not receive a BlockInput we need to create a default float value + if (voices == MP_OBJ_NULL) { + voices = mp_obj_new_float(MICROPY_FLOAT_CONST(1.0)); + } + synthio_block_assign_slot(voices, &self->voices, MP_QSTR_voices); + + if (delay_ms == MP_OBJ_NULL) { + delay_ms = mp_obj_new_float(MICROPY_FLOAT_CONST(50.0)); + } + synthio_block_assign_slot(delay_ms, &self->delay_ms, MP_QSTR_delay_ms); + + if (mix == MP_OBJ_NULL) { + mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5)); + } + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + // Many effects may need buffers of what was played this shows how it was done for the chorus + // A maximum length buffer was created and then the current chorus length can be dynamically changes + // without having to reallocate a large chunk of memory. + + // Allocate the chorus buffer for the max possible delay, chorus is always 16-bit + self->max_delay_ms = max_delay_ms; + self->max_chorus_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms * (self->base.channel_count * sizeof(uint16_t))); // bytes + self->chorus_buffer = m_malloc_without_collect(self->max_chorus_buffer_len); + if (self->chorus_buffer == NULL) { + common_hal_audiodelays_chorus_deinit(self); + m_malloc_fail(self->max_chorus_buffer_len); + } + memset(self->chorus_buffer, 0, self->max_chorus_buffer_len); + + // calculate the length of a single sample in milliseconds + self->sample_ms = MICROPY_FLOAT_CONST(1000.0) / self->base.sample_rate; + + // calculate everything needed for the current delay + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + chorus_recalculate_delay(self, f_delay_ms); + + // where we are storing the next chorus sample + self->chorus_buffer_pos = 0; +} + +bool common_hal_audiodelays_chorus_deinited(audiodelays_chorus_obj_t *self) { + if (self->chorus_buffer == NULL) { + return true; + } + return false; +} + +void common_hal_audiodelays_chorus_deinit(audiodelays_chorus_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->chorus_buffer = NULL; + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiodelays_chorus_get_delay_ms(audiodelays_chorus_obj_t *self) { + return self->delay_ms.obj; +} + +void common_hal_audiodelays_chorus_set_delay_ms(audiodelays_chorus_obj_t *self, mp_obj_t delay_ms) { + synthio_block_assign_slot(delay_ms, &self->delay_ms, MP_QSTR_delay_ms); + + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + + chorus_recalculate_delay(self, f_delay_ms); +} + +void chorus_recalculate_delay(audiodelays_chorus_obj_t *self, mp_float_t f_delay_ms) { + // Require that delay is at least 1 sample long + f_delay_ms = MAX(f_delay_ms, self->sample_ms); + + // Calculate the current chorus buffer length in bytes + uint32_t new_chorus_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * (self->base.channel_count * sizeof(uint16_t)); + + self->chorus_buffer_len = new_chorus_buffer_len; + + self->current_delay_ms = f_delay_ms; +} + +mp_obj_t common_hal_audiodelays_chorus_get_voices(audiodelays_chorus_obj_t *self) { + return self->voices.obj; +} + +void common_hal_audiodelays_chorus_set_voices(audiodelays_chorus_obj_t *self, mp_obj_t voices) { + synthio_block_assign_slot(voices, &self->voices, MP_QSTR_voices); +} + +void audiodelays_chorus_reset_buffer(audiodelays_chorus_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->chorus_buffer, 0, self->chorus_buffer_len); +} + +mp_obj_t common_hal_audiodelays_chorus_get_mix(audiodelays_chorus_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiodelays_chorus_set_mix(audiodelays_chorus_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +bool common_hal_audiodelays_chorus_get_playing(audiodelays_chorus_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiodelays_chorus_play(audiodelays_chorus_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiodelays_chorus_stop(audiodelays_chorus_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + // For chorus we clear the sample but the chorus continues until the object reading our effect stops + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiodelays_chorus_get_buffer(audiodelays_chorus_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // The chorus buffer is always stored as a 16-bit value internally + int16_t *chorus_buffer = (int16_t *)self->chorus_buffer; + uint32_t chorus_buf_len = self->chorus_buffer_len / sizeof(uint16_t); + uint32_t max_chorus_buf_len = self->max_chorus_buffer_len / sizeof(uint16_t); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it but we still need to play the chorus + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n; + if (self->sample == NULL) { + n = MIN(length, SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + + int32_t voices = (int32_t)MAX(synthio_block_slot_get(&self->voices), 1.0); + int32_t mix_down_scale = SYNTHIO_MIX_DOWN_SCALE(voices); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + if (MICROPY_FLOAT_C_FUN(fabs)(self->current_delay_ms - f_delay_ms) >= self->sample_ms) { + chorus_recalculate_delay(self, f_delay_ms); + } + + if (self->sample == NULL) { + if (self->base.samples_signed) { + memset(word_buffer, 0, n * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + uint16_t *uword_buffer = (uint16_t *)word_buffer; + for (uint32_t i = 0; i < n; i++) { + *uword_buffer++ = 32768; + } + } else { + memset(hword_buffer, 128, n * (self->base.bits_per_sample / 8)); + } + } + } else { + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + for (uint32_t i = 0; i < n; i++) { + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + chorus_buffer[self->chorus_buffer_pos++] = (int16_t)sample_word; + + int32_t word = 0; + if (voices == 1) { + word = sample_word; + } else { + int32_t step = chorus_buf_len / (voices - 1) - 1; + int32_t c_pos = self->chorus_buffer_pos - 1; + + for (int32_t v = 0; v < voices; v++) { + if (c_pos < 0) { + c_pos += max_chorus_buf_len; + } + word += chorus_buffer[c_pos]; + + c_pos -= step; + } + + // Dividing would get an average but does not sound as good + // Leaving this here in case someone wants to try an average instead + // word = word / voices; + + word = synthio_mix_down_sample(word, mix_down_scale); + } + + // Add original sample + effect + word = sample_word + (int32_t)(word * mix); + word = synthio_mix_down_sample(word, 2); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t out = word; + if (self->base.samples_signed) { + hword_buffer[i] = out; + } else { + hword_buffer[i] = (uint8_t)out ^ 0x80; + } + } + + if (self->chorus_buffer_pos >= max_chorus_buf_len) { + self->chorus_buffer_pos = 0; + } + } + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Chorus always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiodelays/Chorus.h b/shared-module/audiodelays/Chorus.h new file mode 100644 index 0000000000000..c2602866ef7c5 --- /dev/null +++ b/shared-module/audiodelays/Chorus.h @@ -0,0 +1,53 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/block.h" + +extern const mp_obj_type_t audiodelays_chorus_type; + +typedef struct { + audiosample_base_t base; + uint32_t max_delay_ms; + synthio_block_slot_t delay_ms; + mp_float_t current_delay_ms; + mp_float_t sample_ms; + synthio_block_slot_t voices; + synthio_block_slot_t mix; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int8_t *chorus_buffer; + uint32_t chorus_buffer_len; // bytes + uint32_t max_chorus_buffer_len; // bytes + + uint32_t chorus_buffer_pos; // words + + mp_obj_t sample; +} audiodelays_chorus_obj_t; + +void chorus_recalculate_delay(audiodelays_chorus_obj_t *self, mp_float_t f_delay_ms); + +void audiodelays_chorus_reset_buffer(audiodelays_chorus_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiodelays_chorus_get_buffer(audiodelays_chorus_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiodelays/Echo.c b/shared-module/audiodelays/Echo.c new file mode 100644 index 0000000000000..0ca5fc8a7502e --- /dev/null +++ b/shared-module/audiodelays/Echo.c @@ -0,0 +1,475 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus, Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiodelays/Echo.h" +#include "shared-bindings/audiocore/__init__.h" + +#include +#include "py/runtime.h" +#include + +void common_hal_audiodelays_echo_construct(audiodelays_echo_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t decay, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate, bool freq_shift) { + + // Set whether the echo shifts frequencies as the delay changes like a doppler effect + self->freq_shift = freq_shift; + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiodelays_echo_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiodelays_echo_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the echo effect's starting values. For a different effect this section will change + + // If we did not receive a BlockInput we need to create a default float value + if (decay == MP_OBJ_NULL) { + decay = mp_obj_new_float(MICROPY_FLOAT_CONST(0.7)); + } + synthio_block_assign_slot(decay, &self->decay, MP_QSTR_decay); + + if (delay_ms == MP_OBJ_NULL) { + delay_ms = mp_obj_new_float(MICROPY_FLOAT_CONST(250.0)); + } + synthio_block_assign_slot(delay_ms, &self->delay_ms, MP_QSTR_delay_ms); + + if (mix == MP_OBJ_NULL) { + mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.25)); + } + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + // Many effects may need buffers of what was played this shows how it was done for the echo + // A maximum length buffer was created and then the current echo length can be dynamically changes + // without having to reallocate a large chunk of memory. + + // Allocate the echo buffer for the max possible delay, echo is always 16-bit + self->max_delay_ms = max_delay_ms; + self->max_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms) * (self->base.channel_count * sizeof(uint16_t)); // bytes + self->echo_buffer = m_malloc_without_collect(self->max_echo_buffer_len); + if (self->echo_buffer == NULL) { + common_hal_audiodelays_echo_deinit(self); + m_malloc_fail(self->max_echo_buffer_len); + } + memset(self->echo_buffer, 0, self->max_echo_buffer_len); + + // calculate the length of a single sample in milliseconds + self->sample_ms = MICROPY_FLOAT_CONST(1000.0) / self->base.sample_rate; + + // calculate everything needed for the current delay + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + recalculate_delay(self, f_delay_ms); + + // read is where we read previous echo from delay_ms ago to play back now + // write is where the store the latest playing sample to echo back later + self->echo_buffer_left_pos = 0; + + // use a separate buffer position for the right channel + self->echo_buffer_right_pos = 0; +} + +void common_hal_audiodelays_echo_deinit(audiodelays_echo_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->echo_buffer = NULL; + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiodelays_echo_get_delay_ms(audiodelays_echo_obj_t *self) { + return self->delay_ms.obj; +} + +void common_hal_audiodelays_echo_set_delay_ms(audiodelays_echo_obj_t *self, mp_obj_t delay_ms) { + synthio_block_assign_slot(delay_ms, &self->delay_ms, MP_QSTR_delay_ms); + + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + + recalculate_delay(self, f_delay_ms); +} + +void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms) { + // Require that delay is at least 1 sample long + f_delay_ms = MAX(f_delay_ms, self->sample_ms); + + // Calculate the maximum buffer size per channel in bytes + uint32_t max_echo_buffer_len = self->max_echo_buffer_len >> (self->base.channel_count - 1); + + if (self->freq_shift) { + // Calculate the rate of iteration over the echo buffer with 8 sub-bits + self->echo_buffer_rate = (uint32_t)MAX(self->max_delay_ms / f_delay_ms * MICROPY_FLOAT_CONST(256.0), MICROPY_FLOAT_CONST(1.0)); + // Only use half of the buffer per channel if stereo + self->echo_buffer_len = max_echo_buffer_len; + } else { + // Calculate the current echo buffer length in bytes + uint32_t new_echo_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * f_delay_ms) * sizeof(uint16_t); + + // Limit to valid range + if (new_echo_buffer_len > max_echo_buffer_len) { + new_echo_buffer_len = max_echo_buffer_len; + } else if (new_echo_buffer_len < self->buffer_len) { + // If the echo buffer is smaller than our audio buffer, weird things happen + new_echo_buffer_len = self->buffer_len; + } + + self->echo_buffer_len = new_echo_buffer_len; + + // Clear the now unused part of the buffer or some weird artifacts appear + for (uint32_t i = 0; i < self->base.channel_count; i++) { + memset(self->echo_buffer + (i * max_echo_buffer_len) + self->echo_buffer_len, 0, max_echo_buffer_len - self->echo_buffer_len); + } + } + + self->current_delay_ms = f_delay_ms; +} + +mp_obj_t common_hal_audiodelays_echo_get_decay(audiodelays_echo_obj_t *self) { + return self->decay.obj; +} + +void common_hal_audiodelays_echo_set_decay(audiodelays_echo_obj_t *self, mp_obj_t decay) { + synthio_block_assign_slot(decay, &self->decay, MP_QSTR_decay); +} + +mp_obj_t common_hal_audiodelays_echo_get_mix(audiodelays_echo_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiodelays_echo_set_mix(audiodelays_echo_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +bool common_hal_audiodelays_echo_get_freq_shift(audiodelays_echo_obj_t *self) { + return self->freq_shift; +} + +void common_hal_audiodelays_echo_set_freq_shift(audiodelays_echo_obj_t *self, bool freq_shift) { + // Clear the echo buffer and reset buffer position if changing freq_shift modes + if (self->freq_shift != freq_shift) { + memset(self->echo_buffer, 0, self->max_echo_buffer_len); + self->echo_buffer_left_pos = 0; + self->echo_buffer_right_pos = 0; + } + self->freq_shift = freq_shift; + uint32_t delay_ms = (uint32_t)synthio_block_slot_get(&self->delay_ms); + recalculate_delay(self, delay_ms); +} + +void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->echo_buffer, 0, self->max_echo_buffer_len); +} + +bool common_hal_audiodelays_echo_get_playing(audiodelays_echo_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiodelays_echo_play(audiodelays_echo_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiodelays_echo_stop(audiodelays_echo_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + // For echo we clear the sample but the echo continues until the object reading our effect stops + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // The echo buffer is always stored as a 16-bit value internally + int16_t *echo_buffer = (int16_t *)self->echo_buffer; + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it but we still need to play the echo + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n; + if (self->sample == NULL) { + n = MIN(length, SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); + mp_float_t decay = synthio_block_slot_get_limited(&self->decay, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + mp_float_t f_delay_ms = synthio_block_slot_get(&self->delay_ms); + if (MICROPY_FLOAT_C_FUN(fabs)(self->current_delay_ms - f_delay_ms) >= self->sample_ms) { + recalculate_delay(self, f_delay_ms); + } + + uint32_t echo_buf_len = self->echo_buffer_len / sizeof(uint16_t); + uint32_t max_echo_buf_len = (self->max_echo_buffer_len >> (self->base.channel_count - 1)) / sizeof(uint16_t); + + // If we have no sample keep the echo echoing + if (self->sample == NULL) { + if (mix <= MICROPY_FLOAT_CONST(0.01)) { // Mix of 0 is pure sample sound. We have no sample so no sound + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + uint16_t *uword_buffer = (uint16_t *)word_buffer; + while (length--) { + *uword_buffer++ = 32768; + } + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + } else { + // Since we have no sample we can just iterate over the our entire remaining buffer and finish + for (uint32_t i = 0; i < length; i++) { + int16_t echo, word = 0; + uint32_t next_buffer_pos = 0; + + // Get our echo buffer position and offset depending on current channel + uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1)); + uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos; + + if (self->freq_shift) { + echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset]; + next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate; + + for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { + word = (int16_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay); + echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = word; + } + } else { + echo = echo_buffer[echo_buffer_pos + echo_buffer_offset]; + word = (int16_t)(echo * decay); + echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = word; + } + + word = (int16_t)(echo * MIN(mix, MICROPY_FLOAT_CONST(1.0))); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + hword_buffer[i] = (int8_t)word; + if (!self->base.samples_signed) { + hword_buffer[i] ^= 0x80; + } + } + + if (self->freq_shift) { + echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8); + } else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) { + echo_buffer_pos = 0; + } + + // Update buffer position + if (echo_buffer_offset) { + self->echo_buffer_right_pos = echo_buffer_pos; + } else { + self->echo_buffer_left_pos = echo_buffer_pos; + } + } + } + + length = 0; + } else { + // we have a sample to play and echo + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + if (mix <= MICROPY_FLOAT_CONST(0.01)) { // if mix is zero pure sample only + for (uint32_t i = 0; i < n; i++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = sample_src[i]; + } else { + hword_buffer[i] = sample_hsrc[i]; + } + } + } else { + for (uint32_t i = 0; i < n; i++) { + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + int32_t echo, word = 0; + uint32_t next_buffer_pos = 0; + + // Get our echo buffer position and offset depending on current channel + uint32_t echo_buffer_offset = max_echo_buf_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1)); + uint32_t echo_buffer_pos = echo_buffer_offset ? self->echo_buffer_right_pos : self->echo_buffer_left_pos; + + if (self->freq_shift) { + echo = echo_buffer[(echo_buffer_pos >> 8) + echo_buffer_offset]; + next_buffer_pos = echo_buffer_pos + self->echo_buffer_rate; + } else { + echo = echo_buffer[echo_buffer_pos + echo_buffer_offset]; + word = (int32_t)(echo * decay + sample_word); + } + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + if (self->freq_shift) { + for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { + word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int16_t)word; + } + } else { + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int16_t)word; + } + } else { + if (self->freq_shift) { + for (uint32_t j = echo_buffer_pos >> 8; j < next_buffer_pos >> 8; j++) { + word = (int32_t)(echo_buffer[(j % echo_buf_len) + echo_buffer_offset] * decay + sample_word); + // Do not have mix_down for 8 bit so just hard cap samples into 1 byte + word = MIN(MAX(word, -128), 127); + echo_buffer[(j % echo_buf_len) + echo_buffer_offset] = (int8_t)word; + } + } else { + // Do not have mix_down for 8 bit so just hard cap samples into 1 byte + word = MIN(MAX(word, -128), 127); + echo_buffer[echo_buffer_pos++ + echo_buffer_offset] = (int8_t)word; + } + } + + word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) + + (echo * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = (int16_t)word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t mixed = (int16_t)word; + if (self->base.samples_signed) { + hword_buffer[i] = mixed; + } else { + hword_buffer[i] = (uint8_t)mixed ^ 0x80; + } + } + + if (self->freq_shift) { + echo_buffer_pos = next_buffer_pos % (echo_buf_len << 8); + } else if (!self->freq_shift && echo_buffer_pos >= echo_buf_len) { + echo_buffer_pos = 0; + } + + // Update buffer position + if (echo_buffer_offset) { + self->echo_buffer_right_pos = echo_buffer_pos; + } else { + self->echo_buffer_left_pos = echo_buffer_pos; + } + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Echo always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiodelays/Echo.h b/shared-module/audiodelays/Echo.h new file mode 100644 index 0000000000000..cc37f7030be0e --- /dev/null +++ b/shared-module/audiodelays/Echo.h @@ -0,0 +1,57 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus, Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +extern const mp_obj_type_t audiodelays_echo_type; + +typedef struct { + audiosample_base_t base; + uint32_t max_delay_ms; + synthio_block_slot_t delay_ms; + mp_float_t current_delay_ms; + mp_float_t sample_ms; + synthio_block_slot_t decay; + synthio_block_slot_t mix; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + bool freq_shift; // does the echo shift frequencies if delay changes + + int8_t *echo_buffer; + uint32_t echo_buffer_len; // bytes + uint32_t max_echo_buffer_len; // bytes + + uint32_t echo_buffer_left_pos; // words (<< 8 when freq_shift=True) + uint32_t echo_buffer_right_pos; // words (<< 8 when freq_shift=True) + uint32_t echo_buffer_rate; // words << 8 + + mp_obj_t sample; +} audiodelays_echo_obj_t; + +void recalculate_delay(audiodelays_echo_obj_t *self, mp_float_t f_delay_ms); + +void audiodelays_echo_reset_buffer(audiodelays_echo_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiodelays_echo_get_buffer(audiodelays_echo_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiodelays/MultiTapDelay.c b/shared-module/audiodelays/MultiTapDelay.c new file mode 100644 index 0000000000000..9c33a5eaee750 --- /dev/null +++ b/shared-module/audiodelays/MultiTapDelay.c @@ -0,0 +1,478 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiodelays/MultiTapDelay.h" +#include "shared-bindings/audiocore/__init__.h" + +#include +#include "py/runtime.h" +#include + +void common_hal_audiodelays_multi_tap_delay_construct(audiodelays_multi_tap_delay_obj_t *self, uint32_t max_delay_ms, + mp_obj_t delay_ms, mp_obj_t decay, mp_obj_t mix, mp_obj_t taps, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_maybe(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiodelays_multi_tap_delay_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_maybe(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiodelays_multi_tap_delay_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the multi-tap delay effect's starting values. For a different effect this section will change + + // If we did not receive a BlockInput we need to create a default float value + if (decay == MP_OBJ_NULL) { + decay = mp_obj_new_float(MICROPY_FLOAT_CONST(0.7)); + } + synthio_block_assign_slot(decay, &self->decay, MP_QSTR_decay); + + if (mix == MP_OBJ_NULL) { + mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.25)); + } + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + // Allocate the delay buffer for the max possible delay, delay is always 16-bit + self->max_delay_ms = max_delay_ms; + self->max_delay_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * max_delay_ms) * (self->base.channel_count * sizeof(uint16_t)); // bytes + self->delay_buffer = m_malloc_maybe(self->max_delay_buffer_len); + if (self->delay_buffer == NULL) { + common_hal_audiodelays_multi_tap_delay_deinit(self); + m_malloc_fail(self->max_delay_buffer_len); + } + memset(self->delay_buffer, 0, self->max_delay_buffer_len); + + // calculate the length of a single sample in milliseconds + self->sample_ms = MICROPY_FLOAT_CONST(1000.0) / self->base.sample_rate; + + // calculate everything needed for the current delay + common_hal_audiodelays_multi_tap_delay_set_delay_ms(self, delay_ms); + self->delay_buffer_pos = 0; + self->delay_buffer_right_pos = 0; + + // Initialize our tap values + self->tap_positions = NULL; + self->tap_levels = NULL; + self->tap_offsets = NULL; + self->tap_len = 0; + common_hal_audiodelays_multi_tap_delay_set_taps(self, taps); +} + +void common_hal_audiodelays_multi_tap_delay_deinit(audiodelays_multi_tap_delay_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->delay_buffer = NULL; + self->buffer[0] = NULL; + self->buffer[1] = NULL; + + self->tap_positions = NULL; + self->tap_levels = NULL; + self->tap_offsets = NULL; +} + +mp_float_t common_hal_audiodelays_multi_tap_delay_get_delay_ms(audiodelays_multi_tap_delay_obj_t *self) { + return self->delay_ms; +} + +void common_hal_audiodelays_multi_tap_delay_set_delay_ms(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t delay_ms) { + self->delay_ms = mp_obj_get_float(delay_ms); + + // Require that delay is at least 1 sample long + self->delay_ms = MAX(self->delay_ms, self->sample_ms); + + // Calculate the current delay buffer length in bytes + self->delay_buffer_len = (uint32_t)(self->base.sample_rate / MICROPY_FLOAT_CONST(1000.0) * self->delay_ms) * (self->base.channel_count * sizeof(uint16_t)); + + // Limit to valid range + if (self->delay_buffer_len > self->max_delay_buffer_len) { + self->delay_buffer_len = self->max_delay_buffer_len; + } else if (self->delay_buffer_len < self->buffer_len) { + // If the delay buffer is smaller than our audio buffer, weird things happen + self->delay_buffer_len = self->buffer_len; + } + + // Clear the now unused part of the buffer or some weird artifacts appear + memset(self->delay_buffer + self->delay_buffer_len, 0, self->max_delay_buffer_len - self->delay_buffer_len); + + // Update tap offsets if we have any + recalculate_tap_offsets(self); +} + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_decay(audiodelays_multi_tap_delay_obj_t *self) { + return self->decay.obj; +} + +void common_hal_audiodelays_multi_tap_delay_set_decay(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t decay) { + synthio_block_assign_slot(decay, &self->decay, MP_QSTR_decay); +} + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_mix(audiodelays_multi_tap_delay_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiodelays_multi_tap_delay_set_mix(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t mix) { + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); +} + +mp_obj_t common_hal_audiodelays_multi_tap_delay_get_taps(audiodelays_multi_tap_delay_obj_t *self) { + if (!self->tap_len) { + return mp_const_none; + } else { + mp_obj_tuple_t *taps = mp_obj_new_tuple(self->tap_len, NULL); + for (size_t i = 0; i < self->tap_len; i++) { + mp_obj_tuple_t *pair = mp_obj_new_tuple(2, NULL); + pair->items[0] = mp_obj_new_float(self->tap_positions[i]); + pair->items[1] = mp_obj_new_float(self->tap_levels[i]); + taps->items[i] = pair; + } + return taps; + } +} + +void validate_tap_value(mp_obj_t item, qstr arg_name) { + if (mp_obj_is_small_int(item)) { + mp_arg_validate_int_range(mp_obj_get_int(item), 0, 1, arg_name); + } else { + mp_arg_validate_obj_float_range(item, 0, 1, arg_name); + } +} + +mp_float_t get_tap_value(mp_obj_t item) { + mp_float_t value; + if (mp_obj_is_small_int(item)) { + value = (mp_float_t)mp_obj_get_int(item); + } else { + value = mp_obj_float_get(item); + } + return value; +} + +void common_hal_audiodelays_multi_tap_delay_set_taps(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t taps_in) { + if (taps_in != mp_const_none && !MP_OBJ_TYPE_HAS_SLOT(mp_obj_get_type(taps_in), iter)) { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("%q must be of type %q, not %q"), + MP_QSTR_taps, MP_QSTR_iterable, mp_obj_get_type(taps_in)->name); + } + + size_t len, i; + mp_obj_t *items; + + if (taps_in == mp_const_none) { + len = 0; + items = NULL; + } else { + // convert object to tuple if it wasn't before + taps_in = MP_OBJ_TYPE_GET_SLOT(&mp_type_tuple, make_new)( + &mp_type_tuple, 1, 0, &taps_in); + + mp_obj_tuple_get(taps_in, &len, &items); + mp_arg_validate_length_min(len, 1, MP_QSTR_items); + + for (i = 0; i < len; i++) { + mp_obj_t item = items[i]; + if (mp_obj_is_tuple_compatible(item)) { + size_t len1; + mp_obj_t *items1; + mp_obj_tuple_get(item, &len1, &items1); + mp_arg_validate_length(len1, 2, MP_QSTR_items); + + for (size_t j = 0; j < len1; j++) { + validate_tap_value(items1[j], j ? MP_QSTR_level : MP_QSTR_position); + } + } else if (mp_obj_is_float(item) || mp_obj_is_small_int(item)) { + validate_tap_value(item, MP_QSTR_position); + } else { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("%q in %q must be of type %q or %q, not %q"), + MP_QSTR_object, + MP_QSTR_taps, + MP_QSTR_iterable, + MP_QSTR_float, + mp_obj_get_type(item)->name); + } + + } + } + + self->tap_positions = m_renew(mp_float_t, + self->tap_positions, + self->tap_len, + len); + self->tap_levels = m_renew(mp_float_t, + self->tap_levels, + self->tap_len, + len); + self->tap_offsets = m_renew(uint32_t, + self->tap_offsets, + self->tap_len, + len); + self->tap_len = len; + + for (i = 0; i < len; i++) { + mp_obj_t item = items[i]; + if (mp_obj_is_tuple_compatible(item)) { + size_t len1; + mp_obj_t *items1; + mp_obj_tuple_get(item, &len1, &items1); + + self->tap_positions[i] = get_tap_value(items1[0]); + self->tap_levels[i] = get_tap_value(items1[1]); + } else { + self->tap_positions[i] = get_tap_value(item); + self->tap_levels[i] = MICROPY_FLOAT_CONST(1.0); + } + } + + recalculate_tap_offsets(self); +} + +void recalculate_tap_offsets(audiodelays_multi_tap_delay_obj_t *self) { + if (!self->tap_len) { + return; + } + + uint32_t delay_buffer_len = self->delay_buffer_len / self->base.channel_count / sizeof(uint16_t); + for (size_t i = 0; i < self->tap_len; i++) { + self->tap_offsets[i] = (uint32_t)(delay_buffer_len * self->tap_positions[i]); + } +} + +void audiodelays_multi_tap_delay_reset_buffer(audiodelays_multi_tap_delay_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->delay_buffer, 0, self->max_delay_buffer_len); +} + +bool common_hal_audiodelays_multi_tap_delay_get_playing(audiodelays_multi_tap_delay_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiodelays_multi_tap_delay_play(audiodelays_multi_tap_delay_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiodelays_multi_tap_delay_stop(audiodelays_multi_tap_delay_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + // For delay we clear the sample but the delay continues until the object reading our effect stops + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiodelays_multi_tap_delay_get_buffer(audiodelays_multi_tap_delay_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // The delay buffer is always stored as a 16-bit value internally + int16_t *delay_buffer = (int16_t *)self->delay_buffer; + uint32_t delay_buffer_len = self->delay_buffer_len / self->base.channel_count / sizeof(uint16_t); + + uint32_t delay_buffer_pos = self->delay_buffer_pos; + if (single_channel_output && channel == 1) { + delay_buffer_pos = self->delay_buffer_right_pos; + } + + int32_t mix_down_scale = SYNTHIO_MIX_DOWN_SCALE(self->tap_len); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it but we still need to play the delay + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n; + if (self->sample == NULL) { + n = MIN(length, SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); + mp_float_t decay = synthio_block_slot_get_limited(&self->decay, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + int16_t *sample_src = NULL; + int8_t *sample_hsrc = NULL; + if (self->sample != NULL) { + // we have a sample to play and delay + sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + } + + for (uint32_t i = 0; i < n; i++) { + uint32_t delay_buffer_offset = delay_buffer_len * ((single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1)); + + int32_t sample_word = 0; + if (self->sample != NULL) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + } + + // Pull words from delay buffer at tap positions, apply level and mix down + int32_t word = 0; + int32_t delay_word; + if (self->tap_len) { + size_t tap_pos; + for (size_t j = 0; j < self->tap_len; j++) { + tap_pos = (delay_buffer_pos + delay_buffer_len - self->tap_offsets[j]) % delay_buffer_len; + delay_word = delay_buffer[tap_pos + delay_buffer_offset]; + word += (int32_t)(delay_word * self->tap_levels[j]); + } + + if (self->tap_len > 1) { + word = synthio_mix_down_sample(word, mix_down_scale); + } + } + + // Update delay buffer with sample and decay + delay_word = delay_buffer[delay_buffer_pos + delay_buffer_offset]; + + // If no taps are provided, use as standard delay + if (!self->tap_len) { + word = delay_word; + } + + // Apply decay and add sample + delay_word = (int32_t)(delay_word * decay) + sample_word; + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + delay_word = synthio_mix_down_sample(delay_word, SYNTHIO_MIX_DOWN_SCALE(2)); + delay_buffer[delay_buffer_pos + delay_buffer_offset] = (int16_t)delay_word; + } else { + // Do not have mix_down for 8 bit so just hard cap samples into 1 byte + delay_word = MIN(MAX(delay_word, -128), 127); + delay_buffer[delay_buffer_pos + delay_buffer_offset] = (int8_t)delay_word; + } + + // Mix sample with tap output + word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) + + (word * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = (int16_t)word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t mixed = (int16_t)word; + if (self->base.samples_signed) { + hword_buffer[i] = mixed; + } else { + hword_buffer[i] = (uint8_t)mixed ^ 0x80; + } + } + + if ((self->base.channel_count == 1 || single_channel_output || (!single_channel_output && (i % self->base.channel_count) == 1)) + && ++delay_buffer_pos >= delay_buffer_len) { + delay_buffer_pos = 0; + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + if (self->sample != NULL) { + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + if (single_channel_output && channel == 1) { + self->delay_buffer_right_pos = delay_buffer_pos; + } else { + self->delay_buffer_pos = delay_buffer_pos; + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // MultiTapDelay always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiodelays/MultiTapDelay.h b/shared-module/audiodelays/MultiTapDelay.h new file mode 100644 index 0000000000000..ebe310b05f71d --- /dev/null +++ b/shared-module/audiodelays/MultiTapDelay.h @@ -0,0 +1,60 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +extern const mp_obj_type_t audiodelays_multi_tap_delay_type; + +typedef struct { + audiosample_base_t base; + uint32_t max_delay_ms; + mp_float_t delay_ms; + mp_float_t sample_ms; + synthio_block_slot_t decay; + synthio_block_slot_t mix; + + mp_float_t *tap_positions; + mp_float_t *tap_levels; + uint32_t *tap_offsets; + size_t tap_len; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int8_t *delay_buffer; + uint32_t delay_buffer_len; // bytes + uint32_t max_delay_buffer_len; // bytes + uint32_t delay_buffer_pos; + uint32_t delay_buffer_right_pos; + + mp_obj_t sample; +} audiodelays_multi_tap_delay_obj_t; + +void validate_tap_value(mp_obj_t item, qstr arg_name); +mp_float_t get_tap_value(mp_obj_t item); +void recalculate_tap_offsets(audiodelays_multi_tap_delay_obj_t *self); + +void audiodelays_multi_tap_delay_reset_buffer(audiodelays_multi_tap_delay_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiodelays_multi_tap_delay_get_buffer(audiodelays_multi_tap_delay_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiodelays/PitchShift.c b/shared-module/audiodelays/PitchShift.c new file mode 100644 index 0000000000000..3b8c1a07c7b16 --- /dev/null +++ b/shared-module/audiodelays/PitchShift.c @@ -0,0 +1,350 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiodelays/PitchShift.h" +#include "shared-bindings/audiocore/__init__.h" + +#include +#include "py/runtime.h" +#include + +void common_hal_audiodelays_pitch_shift_construct(audiodelays_pitch_shift_obj_t *self, + mp_obj_t semitones, mp_obj_t mix, uint32_t window, uint32_t overlap, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the effect's starting values. + + synthio_block_assign_slot(semitones, &self->semitones, MP_QSTR_semitones); + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + // Allocate the window buffer + self->window_len = window; // bytes + self->window_buffer = m_malloc_without_collect(self->window_len); + if (self->window_buffer == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->window_len); + } + memset(self->window_buffer, 0, self->window_len); + + // Allocate the overlap buffer + self->overlap_len = overlap; // bytes + if (self->overlap_len) { + self->overlap_buffer = m_malloc_without_collect(self->overlap_len); + if (self->overlap_buffer == NULL) { + common_hal_audiodelays_pitch_shift_deinit(self); + m_malloc_fail(self->overlap_len); + } + memset(self->overlap_buffer, 0, self->overlap_len); + } else { + self->overlap_buffer = NULL; + } + + // The current position that the end of the overlap buffer will be written to the window buffer + self->window_index = 0; + + // The position that the current sample will be written to the overlap buffer + self->overlap_index = 0; + + // The position that the window buffer will be read from and written to the output + self->read_index = 0; + + // Calculate the rate to increment the read index + mp_float_t f_semitones = synthio_block_slot_get(&self->semitones); + recalculate_rate(self, f_semitones); +} + +void common_hal_audiodelays_pitch_shift_deinit(audiodelays_pitch_shift_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->window_buffer = NULL; + self->overlap_buffer = NULL; + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiodelays_pitch_shift_get_semitones(audiodelays_pitch_shift_obj_t *self) { + return self->semitones.obj; +} + +void common_hal_audiodelays_pitch_shift_set_semitones(audiodelays_pitch_shift_obj_t *self, mp_obj_t delay_ms) { + synthio_block_assign_slot(delay_ms, &self->semitones, MP_QSTR_semitones); + mp_float_t semitones = synthio_block_slot_get(&self->semitones); + recalculate_rate(self, semitones); +} + +void recalculate_rate(audiodelays_pitch_shift_obj_t *self, mp_float_t semitones) { + self->read_rate = (uint32_t)(MICROPY_FLOAT_C_FUN(pow)(2.0, semitones / MICROPY_FLOAT_CONST(12.0)) * (1 << PITCH_READ_SHIFT)); + self->current_semitones = semitones; +} + +mp_obj_t common_hal_audiodelays_pitch_shift_get_mix(audiodelays_pitch_shift_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiodelays_pitch_shift_set_mix(audiodelays_pitch_shift_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +void audiodelays_pitch_shift_reset_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->window_buffer, 0, self->window_len); + if (self->overlap_len) { + memset(self->overlap_buffer, 0, self->overlap_len); + } +} + +bool common_hal_audiodelays_pitch_shift_get_playing(audiodelays_pitch_shift_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiodelays_pitch_shift_play(audiodelays_pitch_shift_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiodelays_pitch_shift_stop(audiodelays_pitch_shift_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch_shift_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // The window and overlap buffers are always stored as a 16-bit value internally + int16_t *window_buffer = (int16_t *)self->window_buffer; + uint32_t window_size = self->window_len / sizeof(uint16_t) / self->base.channel_count; + + int16_t *overlap_buffer = NULL; + uint32_t overlap_size = 0; + if (self->overlap_len) { + overlap_buffer = (int16_t *)self->overlap_buffer; + overlap_size = self->overlap_len / sizeof(uint16_t) / self->base.channel_count; + } + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + if (self->sample == NULL) { + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + memset(word_buffer, 32768, length * (self->base.bits_per_sample / 8)); + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + + // tick all block inputs + shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count); + (void)synthio_block_slot_get(&self->semitones); + (void)synthio_block_slot_get(&self->mix); + + length = 0; + } else { + // we have a sample to play and apply effect + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t semitones = synthio_block_slot_get(&self->semitones); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * MICROPY_FLOAT_CONST(2.0); + + // Only recalculate rate if semitones has changes + if (memcmp(&semitones, &self->current_semitones, sizeof(mp_float_t))) { + recalculate_rate(self, semitones); + } + + for (uint32_t i = 0; i < n; i++) { + bool buf_offset = (channel == 1 || i % self->base.channel_count == 1); + + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + if (overlap_size) { + // Copy last sample from overlap and store in buffer + window_buffer[self->window_index + window_size * buf_offset] = overlap_buffer[self->overlap_index + overlap_size * buf_offset]; + + // Save current sample in overlap + overlap_buffer[self->overlap_index + overlap_size * buf_offset] = (int16_t)sample_word; + } else { + // Write sample to buffer + window_buffer[self->window_index + window_size * buf_offset] = (int16_t)sample_word; + } + + // Determine how far we are into the overlap + uint32_t read_index = self->read_index >> PITCH_READ_SHIFT; + uint32_t read_overlap_offset = read_index + window_size * (read_index < self->window_index) - self->window_index; + + // Read sample from buffer + int32_t word = (int32_t)window_buffer[read_index + window_size * buf_offset]; + + // Check if we're within the overlap range and mix buffer sample with overlap sample + if (overlap_size && read_overlap_offset > 0 && read_overlap_offset <= overlap_size) { + // Apply volume based on overlap position to buffer sample + word *= (int32_t)read_overlap_offset; + + // Add overlap with volume based on overlap position + word += (int32_t)overlap_buffer[((self->overlap_index + read_overlap_offset) % overlap_size) + overlap_size * buf_offset] * (int32_t)(overlap_size - read_overlap_offset); + + // Scale down + word /= (int32_t)overlap_size; + } + + word = (int32_t)((sample_word * MIN(MICROPY_FLOAT_CONST(2.0) - mix, MICROPY_FLOAT_CONST(1.0))) + (word * MIN(mix, MICROPY_FLOAT_CONST(1.0)))); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = (int16_t)word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t mixed = (int8_t)word; + if (self->base.samples_signed) { + hword_buffer[i] = mixed; + } else { + hword_buffer[i] = (uint8_t)mixed ^ 0x80; + } + } + + if (self->base.channel_count == 1 || buf_offset) { + // Increment window buffer write pointer + self->window_index++; + if (self->window_index >= window_size) { + self->window_index = 0; + } + + // Increment overlap buffer pointer + if (overlap_size) { + self->overlap_index++; + if (self->overlap_index >= overlap_size) { + self->overlap_index = 0; + } + } + + // Increment window buffer read pointer by rate + self->read_index += self->read_rate; + if (self->read_index >= window_size << PITCH_READ_SHIFT) { + self->read_index -= window_size << PITCH_READ_SHIFT; + } + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // PitchShift always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiodelays/PitchShift.h b/shared-module/audiodelays/PitchShift.h new file mode 100644 index 0000000000000..dddcfa4efc019 --- /dev/null +++ b/shared-module/audiodelays/PitchShift.h @@ -0,0 +1,58 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +#define PITCH_READ_SHIFT (8) + +extern const mp_obj_type_t audiodelays_pitch_shift_type; + +typedef struct { + audiosample_base_t base; + synthio_block_slot_t semitones; + mp_float_t current_semitones; + synthio_block_slot_t mix; + uint32_t window_len; + uint32_t overlap_len; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int8_t *window_buffer; + uint32_t window_index; // words + + int8_t *overlap_buffer; + uint32_t overlap_index; // words + + uint32_t read_index; // words << PITCH_READ_SHIFT + uint32_t read_rate; // words << PITCH_READ_SHIFT + + mp_obj_t sample; +} audiodelays_pitch_shift_obj_t; + +void recalculate_rate(audiodelays_pitch_shift_obj_t *self, mp_float_t semitones); + +void audiodelays_pitch_shift_reset_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiodelays_pitch_shift_get_buffer(audiodelays_pitch_shift_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiodelays/__init__.c b/shared-module/audiodelays/__init__.c new file mode 100644 index 0000000000000..7b5abdb4ff317 --- /dev/null +++ b/shared-module/audiodelays/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT diff --git a/shared-module/audiodelays/__init__.h b/shared-module/audiodelays/__init__.h new file mode 100644 index 0000000000000..3bc9246e5bbf0 --- /dev/null +++ b/shared-module/audiodelays/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/audiofilters/Distortion.c b/shared-module/audiofilters/Distortion.c new file mode 100644 index 0000000000000..c4b6b7566ad0d --- /dev/null +++ b/shared-module/audiofilters/Distortion.c @@ -0,0 +1,356 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#include +#include "py/obj.h" +#include "py/runtime.h" +#include +#include "shared-bindings/audiofilters/Distortion.h" +#include "shared-module/audiofilters/Distortion.h" +#include "shared-bindings/audiocore/__init__.h" + +/** + * Based on Godot's AudioEffectDistortion + * - https://docs.godotengine.org/en/stable/classes/class_audioeffectdistortion.html + * - https://github.com/godotengine/godot/blob/master/servers/audio/effects/audio_effect_distortion.cpp + */ + +void common_hal_audiofilters_distortion_construct(audiofilters_distortion_obj_t *self, + mp_obj_t drive, mp_obj_t pre_gain, mp_obj_t post_gain, + audiofilters_distortion_mode mode, bool soft_clip, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, bool samples_signed, + uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiofilters_distortion_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiofilters_distortion_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the effect's starting values. + + synthio_block_assign_slot(drive, &self->drive, MP_QSTR_drive); + synthio_block_assign_slot(pre_gain, &self->pre_gain, MP_QSTR_pre_gain); + synthio_block_assign_slot(post_gain, &self->post_gain, MP_QSTR_post_gain); + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + self->mode = mode; + self->soft_clip = soft_clip; +} + +void common_hal_audiofilters_distortion_deinit(audiofilters_distortion_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiofilters_distortion_get_drive(audiofilters_distortion_obj_t *self) { + return self->drive.obj; +} + +void common_hal_audiofilters_distortion_set_drive(audiofilters_distortion_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->drive, MP_QSTR_drive); +} + +mp_obj_t common_hal_audiofilters_distortion_get_pre_gain(audiofilters_distortion_obj_t *self) { + return self->pre_gain.obj; +} + +void common_hal_audiofilters_distortion_set_pre_gain(audiofilters_distortion_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->pre_gain, MP_QSTR_pre_gain); +} + +mp_obj_t common_hal_audiofilters_distortion_get_post_gain(audiofilters_distortion_obj_t *self) { + return self->post_gain.obj; +} + +void common_hal_audiofilters_distortion_set_post_gain(audiofilters_distortion_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->post_gain, MP_QSTR_post_gain); +} + +audiofilters_distortion_mode common_hal_audiofilters_distortion_get_mode(audiofilters_distortion_obj_t *self) { + return self->mode; +} + +void common_hal_audiofilters_distortion_set_mode(audiofilters_distortion_obj_t *self, audiofilters_distortion_mode arg) { + self->mode = arg; +} + +bool common_hal_audiofilters_distortion_get_soft_clip(audiofilters_distortion_obj_t *self) { + return self->soft_clip; +} + +void common_hal_audiofilters_distortion_set_soft_clip(audiofilters_distortion_obj_t *self, bool soft_clip) { + self->soft_clip = soft_clip; +} + +mp_obj_t common_hal_audiofilters_distortion_get_mix(audiofilters_distortion_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiofilters_distortion_set_mix(audiofilters_distortion_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +void audiofilters_distortion_reset_buffer(audiofilters_distortion_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); +} + +bool common_hal_audiofilters_distortion_get_playing(audiofilters_distortion_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiofilters_distortion_play(audiofilters_distortion_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiofilters_distortion_stop(audiofilters_distortion_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + self->sample = NULL; + return; +} + +static mp_float_t db_to_linear(mp_float_t value) { + return MICROPY_FLOAT_C_FUN(exp)(value * MICROPY_FLOAT_CONST(0.11512925464970228420089957273422)); +} + +audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_distortion_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + if (self->sample == NULL) { + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + memset(word_buffer, 32768, length * (self->base.bits_per_sample / 8)); + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + + // tick all block inputs + shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count); + (void)synthio_block_slot_get(&self->drive); + (void)synthio_block_slot_get(&self->pre_gain); + (void)synthio_block_slot_get(&self->post_gain); + (void)synthio_block_slot_get(&self->mix); + + length = 0; + } else { + // we have a sample to play and apply effect + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t drive = synthio_block_slot_get_limited(&self->drive, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + mp_float_t pre_gain = db_to_linear(synthio_block_slot_get_limited(&self->pre_gain, MICROPY_FLOAT_CONST(-60.0), MICROPY_FLOAT_CONST(60.0))); + mp_float_t post_gain = db_to_linear(synthio_block_slot_get_limited(&self->post_gain, MICROPY_FLOAT_CONST(-80.0), MICROPY_FLOAT_CONST(24.0))); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + // Modify drive value depending on mode + uint32_t word_mask = 0; + if (self->mode == DISTORTION_MODE_CLIP) { + drive = MICROPY_FLOAT_CONST(1.0001) - drive; + } else if (self->mode == DISTORTION_MODE_WAVESHAPE) { + drive = MICROPY_FLOAT_CONST(2.0) * drive / (MICROPY_FLOAT_CONST(1.0001) - drive); + } else if (self->mode == DISTORTION_MODE_LOFI) { + word_mask = 0xFFFFFFFF ^ ((1 << (uint32_t)MICROPY_FLOAT_C_FUN(round)(drive * MICROPY_FLOAT_CONST(14.0))) - 1); + } + + if (mix <= MICROPY_FLOAT_CONST(0.01)) { // if mix is zero pure sample only + for (uint32_t i = 0; i < n; i++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = sample_src[i]; + } else { + hword_buffer[i] = sample_hsrc[i]; + } + } + } else { + for (uint32_t i = 0; i < n; i++) { + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + // Apply pre-gain + int32_t word = (int32_t)(sample_word * pre_gain); + + // Apply bit mask before converting to float + if (self->mode == DISTORTION_MODE_LOFI) { + word = word & word_mask; + } + + if (self->mode != DISTORTION_MODE_LOFI || self->soft_clip) { + // Convert sample to float + mp_float_t wordf = word / MICROPY_FLOAT_CONST(32768.0); + + switch (self->mode) { + case DISTORTION_MODE_CLIP: { + wordf = MICROPY_FLOAT_C_FUN(pow)(MICROPY_FLOAT_C_FUN(fabs)(wordf), drive); + if (word < 0) { + wordf *= MICROPY_FLOAT_CONST(-1.0); + } + } break; + case DISTORTION_MODE_LOFI: + break; + case DISTORTION_MODE_OVERDRIVE: { + wordf *= MICROPY_FLOAT_CONST(0.686306); + mp_float_t z = MICROPY_FLOAT_CONST(1.0) + MICROPY_FLOAT_C_FUN(exp)(MICROPY_FLOAT_C_FUN(sqrt)(MICROPY_FLOAT_C_FUN(fabs)(wordf)) * MICROPY_FLOAT_CONST(-0.75)); + mp_float_t word_exp = MICROPY_FLOAT_C_FUN(exp)(wordf); + wordf *= MICROPY_FLOAT_CONST(-1.0); + wordf = (word_exp - MICROPY_FLOAT_C_FUN(exp)(wordf * z)) / (word_exp + MICROPY_FLOAT_C_FUN(exp)(wordf)); + } break; + case DISTORTION_MODE_WAVESHAPE: { + wordf = (MICROPY_FLOAT_CONST(1.0) + drive) * wordf / (MICROPY_FLOAT_CONST(1.0) + drive * MICROPY_FLOAT_C_FUN(fabs)(wordf)); + } break; + } + + // Apply post-gain + wordf = wordf * post_gain; + + // Soft clip + if (self->soft_clip) { + if (wordf > 0) { + wordf = MICROPY_FLOAT_CONST(1.0) - MICROPY_FLOAT_C_FUN(exp)(-wordf); + } else { + wordf = MICROPY_FLOAT_CONST(-1.0) + MICROPY_FLOAT_C_FUN(exp)(wordf); + } + } + + // Convert sample back to signed integer + word = (int32_t)(wordf * MICROPY_FLOAT_CONST(32767.0)); + } else { + // Apply post-gain + word = (int32_t)(word * post_gain); + } + + // Hard clip + if (!self->soft_clip) { + word = MIN(MAX(word, -32767), 32768); + } + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = (int16_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t mixed = (int8_t)((sample_word * (MICROPY_FLOAT_CONST(1.0) - mix)) + (word * mix)); + if (self->base.samples_signed) { + hword_buffer[i] = mixed; + } else { + hword_buffer[i] = (uint8_t)mixed ^ 0x80; + } + } + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Distortion always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiofilters/Distortion.h b/shared-module/audiofilters/Distortion.h new file mode 100644 index 0000000000000..ddfa1231e645e --- /dev/null +++ b/shared-module/audiofilters/Distortion.h @@ -0,0 +1,51 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-bindings/audiofilters/Distortion.h" +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/block.h" + +typedef enum { + DISTORTION_MODE_CLIP, + DISTORTION_MODE_LOFI, + DISTORTION_MODE_OVERDRIVE, + DISTORTION_MODE_WAVESHAPE, +} audiofilters_distortion_mode; + +extern const mp_obj_type_t audiofilters_distortion_type; + +typedef struct { + audiosample_base_t base; + synthio_block_slot_t drive; + synthio_block_slot_t pre_gain; + synthio_block_slot_t post_gain; + audiofilters_distortion_mode mode; + bool soft_clip; + synthio_block_slot_t mix; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + mp_obj_t sample; +} audiofilters_distortion_obj_t; + +void audiofilters_distortion_reset_buffer(audiofilters_distortion_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiofilters_distortion_get_buffer(audiofilters_distortion_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); diff --git a/shared-module/audiofilters/Filter.c b/shared-module/audiofilters/Filter.c new file mode 100644 index 0000000000000..4cedc810abad6 --- /dev/null +++ b/shared-module/audiofilters/Filter.c @@ -0,0 +1,309 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiofilters/Filter.h" +#include "shared-bindings/audiocore/__init__.h" + +#include "shared-module/synthio/Biquad.h" +#include +#include "py/runtime.h" + +void common_hal_audiofilters_filter_construct(audiofilters_filter_obj_t *self, + mp_obj_t filter, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // This buffer will be used to process samples through the biquad filter + self->filter_buffer = m_malloc_without_collect(SYNTHIO_MAX_DUR * sizeof(int32_t)); + memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * sizeof(int32_t)); + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the effect's starting values. + + common_hal_audiofilters_filter_set_filter(self, filter); + + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); +} + +void common_hal_audiofilters_filter_deinit(audiofilters_filter_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->buffer[0] = NULL; + self->buffer[1] = NULL; + self->filter = mp_const_none; + self->filter_buffer = NULL; + self->filter_states = NULL; +} + +void common_hal_audiofilters_filter_set_filter(audiofilters_filter_obj_t *self, mp_obj_t filter_in) { + size_t n_items; + mp_obj_t *items; + mp_obj_t *filter_objs; + + if (filter_in == mp_const_none) { + n_items = 0; + filter_objs = NULL; + } else if (MP_OBJ_TYPE_HAS_SLOT(mp_obj_get_type(filter_in), iter)) { + // convert object to tuple if it wasn't before + filter_in = MP_OBJ_TYPE_GET_SLOT(&mp_type_tuple, make_new)( + &mp_type_tuple, 1, 0, &filter_in); + mp_obj_tuple_get(filter_in, &n_items, &items); + for (size_t i = 0; i < n_items; i++) { + if (!mp_obj_is_type(items[i], &synthio_biquad_type_obj)) { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("%q in %q must be of type %q, not %q"), + MP_QSTR_object, + MP_QSTR_filter, + MP_QSTR_Biquad, + mp_obj_get_type(items[i])->name); + } + } + filter_objs = items; + } else { + n_items = 1; + if (!mp_obj_is_type(filter_in, &synthio_biquad_type_obj)) { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), + MP_QSTR_filter, MP_QSTR_Biquad, MP_QSTR_iterable, mp_obj_get_type(filter_in)->name); + } + filter_objs = &self->filter; + } + + // everything has been checked, so we can do the following without fear + + self->filter = filter_in; + self->filter_objs = filter_objs; + self->filter_states = m_renew(biquad_filter_state, + self->filter_states, + self->filter_states_len, + n_items); + self->filter_states_len = n_items; +} + +mp_obj_t common_hal_audiofilters_filter_get_filter(audiofilters_filter_obj_t *self) { + return self->filter; +} + +mp_obj_t common_hal_audiofilters_filter_get_mix(audiofilters_filter_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiofilters_filter_set_mix(audiofilters_filter_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->filter_buffer, 0, SYNTHIO_MAX_DUR * sizeof(int32_t)); + + if (self->filter_states) { + for (uint8_t i = 0; i < self->filter_states_len; i++) { + synthio_biquad_filter_reset(&self->filter_states[i]); + } + } +} + +bool common_hal_audiofilters_filter_get_playing(audiofilters_filter_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiofilters_filter_play(audiofilters_filter_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiofilters_filter_stop(audiofilters_filter_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + (void)channel; + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + if (self->sample == NULL) { + // tick all block inputs + shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count); + (void)synthio_block_slot_get(&self->mix); + + // Tick biquad filters + for (uint8_t j = 0; j < self->filter_states_len; j++) { + common_hal_synthio_biquad_tick(self->filter_objs[j]); + } + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + uint16_t *uword_buffer = (uint16_t *)word_buffer; + while (length--) { + *uword_buffer++ = 32768; + } + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + + length = 0; + } else { + // we have a sample to play and filter + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + + if (mix <= MICROPY_FLOAT_CONST(0.01) || !self->filter_states) { // if mix is zero pure sample only or no biquad filter objects are provided + for (uint32_t i = 0; i < n; i++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = sample_src[i]; + } else { + hword_buffer[i] = sample_hsrc[i]; + } + } + } else { + uint32_t i = 0; + while (i < n) { + uint32_t n_samples = MIN(SYNTHIO_MAX_DUR, n - i); + + // Fill filter buffer with samples + for (uint32_t j = 0; j < n_samples; j++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + self->filter_buffer[j] = sample_src[i + j]; + } else { + if (self->base.samples_signed) { + self->filter_buffer[j] = sample_hsrc[i + j]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + self->filter_buffer[j] = (int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80); + } + } + } + + // Process biquad filters + for (uint8_t j = 0; j < self->filter_states_len; j++) { + mp_obj_t filter_obj = self->filter_objs[j]; + common_hal_synthio_biquad_tick(filter_obj); + synthio_biquad_filter_samples(filter_obj, &self->filter_states[j], self->filter_buffer, n_samples); + } + + // Mix processed signal with original sample and transfer to output buffer + for (uint32_t j = 0; j < n_samples; j++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i + j] = synthio_mix_down_sample((int32_t)((sample_src[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)), SYNTHIO_MIX_DOWN_SCALE(2)); + if (!self->base.samples_signed) { + word_buffer[i + j] ^= 0x8000; + } + } else { + if (self->base.samples_signed) { + hword_buffer[i + j] = (int8_t)((sample_hsrc[i + j] * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)); + } else { + hword_buffer[i + j] = (uint8_t)(((int8_t)(((uint8_t)sample_hsrc[i + j]) ^ 0x80) * (MICROPY_FLOAT_CONST(1.0) - mix)) + (self->filter_buffer[j] * mix)) ^ 0x80; + } + } + } + + i += n_samples; + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Filter always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiofilters/Filter.h b/shared-module/audiofilters/Filter.h new file mode 100644 index 0000000000000..4447f8a29887f --- /dev/null +++ b/shared-module/audiofilters/Filter.h @@ -0,0 +1,50 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-bindings/synthio/Biquad.h" +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" +#include "shared-module/synthio/Biquad.h" + +extern const mp_obj_type_t audiofilters_filter_type; + +typedef struct { + audiosample_base_t base; + mp_obj_t filter; + synthio_block_slot_t mix; + + mp_obj_t *filter_objs; + size_t filter_states_len; + biquad_filter_state *filter_states; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + int32_t *filter_buffer; + + bool loop; + bool more_data; + + mp_obj_t sample; +} audiofilters_filter_obj_t; + +void audiofilters_filter_reset_buffer(audiofilters_filter_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiofilters_filter_get_buffer(audiofilters_filter_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiofilters/Phaser.c b/shared-module/audiofilters/Phaser.c new file mode 100644 index 0000000000000..01b938c3a0027 --- /dev/null +++ b/shared-module/audiofilters/Phaser.c @@ -0,0 +1,302 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#include "shared-bindings/audiofilters/Phaser.h" +#include "shared-bindings/audiocore/__init__.h" + +#include +#include "py/runtime.h" + +void common_hal_audiofilters_phaser_construct(audiofilters_phaser_obj_t *self, + mp_obj_t frequency, mp_obj_t feedback, mp_obj_t mix, uint8_t stages, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_without_collect(self->buffer_len); + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_without_collect(self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the effect's starting values. + + // Create buffer to hold the last processed word + self->word_buffer = m_malloc_without_collect(self->base.channel_count * sizeof(int16_t)); + memset(self->word_buffer, 0, self->base.channel_count * sizeof(int16_t)); + + self->nyquist = (mp_float_t)self->base.sample_rate / 2; + + if (feedback == mp_const_none) { + feedback = mp_obj_new_float(MICROPY_FLOAT_CONST(0.7)); + } + + synthio_block_assign_slot(frequency, &self->frequency, MP_QSTR_frequency); + synthio_block_assign_slot(feedback, &self->feedback, MP_QSTR_feedback); + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + + common_hal_audiofilters_phaser_set_stages(self, stages); +} + +void common_hal_audiofilters_phaser_deinit(audiofilters_phaser_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->buffer[0] = NULL; + self->buffer[1] = NULL; + self->word_buffer = NULL; + self->allpass_buffer = NULL; +} + +mp_obj_t common_hal_audiofilters_phaser_get_frequency(audiofilters_phaser_obj_t *self) { + return self->frequency.obj; +} + +void common_hal_audiofilters_phaser_set_frequency(audiofilters_phaser_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->frequency, MP_QSTR_frequency); +} + +mp_obj_t common_hal_audiofilters_phaser_get_feedback(audiofilters_phaser_obj_t *self) { + return self->feedback.obj; +} + +void common_hal_audiofilters_phaser_set_feedback(audiofilters_phaser_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->feedback, MP_QSTR_feedback); +} + +mp_obj_t common_hal_audiofilters_phaser_get_mix(audiofilters_phaser_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiofilters_phaser_set_mix(audiofilters_phaser_obj_t *self, mp_obj_t arg) { + synthio_block_assign_slot(arg, &self->mix, MP_QSTR_mix); +} + +uint8_t common_hal_audiofilters_phaser_get_stages(audiofilters_phaser_obj_t *self) { + return self->stages; +} + +void common_hal_audiofilters_phaser_set_stages(audiofilters_phaser_obj_t *self, uint8_t arg) { + if (!arg) { + arg = 1; + } + + self->allpass_buffer = (int16_t *)m_realloc(self->allpass_buffer, + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + self->base.channel_count * self->stages * sizeof(int16_t), // Old size + #endif + self->base.channel_count * arg * sizeof(int16_t)); + self->stages = arg; + + memset(self->allpass_buffer, 0, self->base.channel_count * self->stages * sizeof(int16_t)); +} + +void audiofilters_phaser_reset_buffer(audiofilters_phaser_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); + memset(self->word_buffer, 0, self->base.channel_count * sizeof(int16_t)); + memset(self->allpass_buffer, 0, self->base.channel_count * self->stages * sizeof(int16_t)); +} + +bool common_hal_audiofilters_phaser_get_playing(audiofilters_phaser_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiofilters_phaser_play(audiofilters_phaser_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiofilters_phaser_stop(audiofilters_phaser_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiofilters_phaser_get_buffer(audiofilters_phaser_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + (void)channel; + + if (!single_channel_output) { + channel = 0; + } + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // If we are using 16 bit samples we need a 16 bit pointer, 8 bit needs an 8 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + int8_t *hword_buffer = self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + if (self->sample == NULL) { + // tick all block inputs + shared_bindings_synthio_lfo_tick(self->base.sample_rate, length / self->base.channel_count); + (void)synthio_block_slot_get(&self->frequency); + (void)synthio_block_slot_get(&self->feedback); + (void)synthio_block_slot_get(&self->mix); + + if (self->base.samples_signed) { + memset(word_buffer, 0, length * (self->base.bits_per_sample / 8)); + } else { + // For unsigned samples set to the middle which is "quiet" + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + uint16_t *uword_buffer = (uint16_t *)word_buffer; + while (length--) { + *uword_buffer++ = 32768; + } + } else { + memset(hword_buffer, 128, length * (self->base.bits_per_sample / 8)); + } + } + + length = 0; + } else { + // we have a sample to play and filter + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; // for 16-bit samples + int8_t *sample_hsrc = (int8_t *)self->sample_remaining_buffer; // for 8-bit samples + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t frequency = synthio_block_slot_get_limited(&self->frequency, MICROPY_FLOAT_CONST(0.0), self->nyquist); + int16_t feedback = (int16_t)(synthio_block_slot_get_limited(&self->feedback, MICROPY_FLOAT_CONST(0.1), MICROPY_FLOAT_CONST(0.9)) * 32767); + int16_t mix = (int16_t)(synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * 32767); + + if (mix <= 328) { // if mix is zero (0.01 in fixed point), pure sample only + for (uint32_t i = 0; i < n; i++) { + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = sample_src[i]; + } else { + hword_buffer[i] = sample_hsrc[i]; + } + } + } else { + // Update all-pass filter coefficient + frequency /= self->nyquist; // scale relative to frequency range + int16_t allpasscoef = (int16_t)((MICROPY_FLOAT_CONST(1.0) - frequency) / (MICROPY_FLOAT_CONST(1.0) + frequency) * 32767); + + for (uint32_t i = 0; i < n; i++) { + bool right_channel = (single_channel_output && channel == 1) || (!single_channel_output && (i % self->base.channel_count) == 1); + uint32_t allpass_buffer_offset = self->stages * right_channel; + + int32_t sample_word = 0; + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + sample_word = sample_src[i]; + } else { + if (self->base.samples_signed) { + sample_word = sample_hsrc[i]; + } else { + // Be careful here changing from an 8 bit unsigned to signed into a 32-bit signed + sample_word = (int8_t)(((uint8_t)sample_hsrc[i]) ^ 0x80); + } + } + + int32_t word = synthio_sat16(sample_word + synthio_sat16((int32_t)self->word_buffer[right_channel] * feedback, 15), 0); + int32_t allpass_word = 0; + + // Update all-pass filters + for (uint32_t j = 0; j < self->stages; j++) { + allpass_word = synthio_sat16(synthio_sat16(word * -allpasscoef, 15) + self->allpass_buffer[j + allpass_buffer_offset], 0); + self->allpass_buffer[j + allpass_buffer_offset] = synthio_sat16(synthio_sat16(allpass_word * allpasscoef, 15) + word, 0); + word = allpass_word; + } + self->word_buffer[(bool)allpass_buffer_offset] = (int16_t)word; + + // Add original sample + effect + word = sample_word + (int32_t)(synthio_sat16(word * mix, 15)); + word = synthio_mix_down_sample(word, 2); + + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + word_buffer[i] = word; + if (!self->base.samples_signed) { + word_buffer[i] ^= 0x8000; + } + } else { + int8_t out = word; + if (self->base.samples_signed) { + hword_buffer[i] = out; + } else { + hword_buffer[i] = (uint8_t)out ^ 0x80; + } + } + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + hword_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Phaser always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiofilters/Phaser.h b/shared-module/audiofilters/Phaser.h new file mode 100644 index 0000000000000..f627b147014a0 --- /dev/null +++ b/shared-module/audiofilters/Phaser.h @@ -0,0 +1,49 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +extern const mp_obj_type_t audiofilters_phaser_type; + +typedef struct { + audiosample_base_t base; + synthio_block_slot_t frequency; + synthio_block_slot_t feedback; + synthio_block_slot_t mix; + uint8_t stages; + + mp_float_t nyquist; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int16_t *allpass_buffer; + int16_t *word_buffer; + + mp_obj_t sample; +} audiofilters_phaser_obj_t; + +void audiofilters_phaser_reset_buffer(audiofilters_phaser_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiofilters_phaser_get_buffer(audiofilters_phaser_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes diff --git a/shared-module/audiofilters/__init__.c b/shared-module/audiofilters/__init__.c new file mode 100644 index 0000000000000..83929b4c4fb82 --- /dev/null +++ b/shared-module/audiofilters/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT diff --git a/shared-module/audiofilters/__init__.h b/shared-module/audiofilters/__init__.h new file mode 100644 index 0000000000000..29d2f6726559b --- /dev/null +++ b/shared-module/audiofilters/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Cooper Dalrymple +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/audiofreeverb/Freeverb.c b/shared-module/audiofreeverb/Freeverb.c new file mode 100644 index 0000000000000..b57e82cdca2e5 --- /dev/null +++ b/shared-module/audiofreeverb/Freeverb.c @@ -0,0 +1,337 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT +// +// Based on FreeVerb - https://github.com/sinshu/freeverb/tree/main +// Fixed point ideas from - Paul Stoffregen in the Teensy audio library https://github.com/PaulStoffregen/Audio/blob/master/effect_freeverb.cpp +// +#include "shared-bindings/audiofreeverb/Freeverb.h" +#include "shared-bindings/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" + +#include +#include "py/runtime.h" +#include + +void common_hal_audiofreeverb_freeverb_construct(audiofreeverb_freeverb_obj_t *self, mp_obj_t roomsize, mp_obj_t damp, mp_obj_t mix, + uint32_t buffer_size, uint8_t bits_per_sample, + bool samples_signed, uint8_t channel_count, uint32_t sample_rate) { + + // Basic settings every effect and audio sample has + // These are the effects values, not the source sample(s) + self->base.bits_per_sample = bits_per_sample; // Most common is 16, but 8 is also supported in many places + self->base.samples_signed = samples_signed; // Are the samples we provide signed (common is true) + self->base.channel_count = channel_count; // Channels can be 1 for mono or 2 for stereo + self->base.sample_rate = sample_rate; // Sample rate for the effect, this generally needs to match all audio objects + self->base.single_buffer = false; + self->base.max_buffer_length = buffer_size; + + // To smooth things out as CircuitPython is doing other tasks most audio objects have a buffer + // A double buffer is set up here so the audio output can use DMA on buffer 1 while we + // write to and create buffer 2. + // This buffer is what is passed to the audio component that plays the effect. + // Samples are set sequentially. For stereo audio they are passed L/R/L/R/... + self->buffer_len = buffer_size; // in bytes + + self->buffer[0] = m_malloc_maybe(self->buffer_len); + if (self->buffer[0] == NULL) { + common_hal_audiofreeverb_freeverb_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[0], 0, self->buffer_len); + + self->buffer[1] = m_malloc_maybe(self->buffer_len); + if (self->buffer[1] == NULL) { + common_hal_audiofreeverb_freeverb_deinit(self); + m_malloc_fail(self->buffer_len); + } + memset(self->buffer[1], 0, self->buffer_len); + + self->last_buf_idx = 1; // Which buffer to use first, toggle between 0 and 1 + + // Initialize other values most effects will need. + self->sample = NULL; // The current playing sample + self->sample_remaining_buffer = NULL; // Pointer to the start of the sample buffer we have not played + self->sample_buffer_length = 0; // How many samples do we have left to play (these may be 16 bit!) + self->loop = false; // When the sample is done do we loop to the start again or stop (e.g. in a wav file) + self->more_data = false; // Is there still more data to read from the sample or did we finish + + // The below section sets up the reverb effect's starting values. For a different effect this section will change + if (roomsize == MP_OBJ_NULL) { + roomsize = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5)); + } + synthio_block_assign_slot(roomsize, &self->roomsize, MP_QSTR_roomsize); + common_hal_audiofreeverb_freeverb_set_roomsize(self, roomsize); + + if (damp == MP_OBJ_NULL) { + damp = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5)); + } + synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp); + common_hal_audiofreeverb_freeverb_set_damp(self, damp); + + if (mix == MP_OBJ_NULL) { + mix = mp_obj_new_float(MICROPY_FLOAT_CONST(0.5)); + } + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); + common_hal_audiofreeverb_freeverb_set_mix(self, mix); + + // Set up the comb filters + // These values come from FreeVerb and are selected for the best reverb sound + self->combbuffersizes[0] = self->combbuffersizes[8] = 1116; + self->combbuffersizes[1] = self->combbuffersizes[9] = 1188; + self->combbuffersizes[2] = self->combbuffersizes[10] = 1277; + self->combbuffersizes[3] = self->combbuffersizes[11] = 1356; + self->combbuffersizes[4] = self->combbuffersizes[12] = 1422; + self->combbuffersizes[5] = self->combbuffersizes[13] = 1491; + self->combbuffersizes[6] = self->combbuffersizes[14] = 1557; + self->combbuffersizes[7] = self->combbuffersizes[15] = 1617; + for (uint32_t i = 0; i < 8 * channel_count; i++) { + self->combbuffers[i] = m_malloc_maybe(self->combbuffersizes[i] * sizeof(uint16_t)); + if (self->combbuffers[i] == NULL) { + common_hal_audiofreeverb_freeverb_deinit(self); + m_malloc_fail(self->combbuffersizes[i]); + } + memset(self->combbuffers[i], 0, self->combbuffersizes[i]); + + self->combbufferindex[i] = 0; + self->combfitlers[i] = 0; + } + + // Set up the allpass filters + // These values come from FreeVerb and are selected for the best reverb sound + self->allpassbuffersizes[0] = self->allpassbuffersizes[4] = 556; + self->allpassbuffersizes[1] = self->allpassbuffersizes[5] = 441; + self->allpassbuffersizes[2] = self->allpassbuffersizes[6] = 341; + self->allpassbuffersizes[3] = self->allpassbuffersizes[7] = 225; + for (uint32_t i = 0; i < 4 * channel_count; i++) { + self->allpassbuffers[i] = m_malloc_maybe(self->allpassbuffersizes[i] * sizeof(uint16_t)); + if (self->allpassbuffers[i] == NULL) { + common_hal_audiofreeverb_freeverb_deinit(self); + m_malloc_fail(self->allpassbuffersizes[i]); + } + memset(self->allpassbuffers[i], 0, self->allpassbuffersizes[i]); + + self->allpassbufferindex[i] = 0; + } +} + +bool common_hal_audiofreeverb_freeverb_deinited(audiofreeverb_freeverb_obj_t *self) { + if (self->buffer[0] == NULL) { + return true; + } + return false; +} + +void common_hal_audiofreeverb_freeverb_deinit(audiofreeverb_freeverb_obj_t *self) { + audiosample_mark_deinit(&self->base); + self->buffer[0] = NULL; + self->buffer[1] = NULL; +} + +mp_obj_t common_hal_audiofreeverb_freeverb_get_roomsize(audiofreeverb_freeverb_obj_t *self) { + return self->roomsize.obj; +} + +void common_hal_audiofreeverb_freeverb_set_roomsize(audiofreeverb_freeverb_obj_t *self, mp_obj_t roomsize_obj) { + synthio_block_assign_slot(roomsize_obj, &self->roomsize, MP_QSTR_roomsize); +} + +int16_t audiofreeverb_freeverb_get_roomsize_fixedpoint(mp_float_t n) { + if (n > (mp_float_t)MICROPY_FLOAT_CONST(1.0)) { + n = MICROPY_FLOAT_CONST(1.0); + } else if (n < (mp_float_t)MICROPY_FLOAT_CONST(0.0)) { + n = MICROPY_FLOAT_CONST(0.0); + } + + return (int16_t)(n * (mp_float_t)MICROPY_FLOAT_CONST(9175.04)) + 22937; // 9175.04 = 0.28f in fixed point 22937 = 0.7f +} + +mp_obj_t common_hal_audiofreeverb_freeverb_get_damp(audiofreeverb_freeverb_obj_t *self) { + return self->damp.obj; +} + +void common_hal_audiofreeverb_freeverb_set_damp(audiofreeverb_freeverb_obj_t *self, mp_obj_t damp) { + synthio_block_assign_slot(damp, &self->damp, MP_QSTR_damp); +} + +void audiofreeverb_freeverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2) { + if (n > (mp_float_t)MICROPY_FLOAT_CONST(1.0)) { + n = MICROPY_FLOAT_CONST(1.0); + } else if (n < (mp_float_t)MICROPY_FLOAT_CONST(0.0)) { + n = MICROPY_FLOAT_CONST(0.0); + } + + *damp1 = (int16_t)(n * (mp_float_t)MICROPY_FLOAT_CONST(13107.2)); // 13107.2 = 0.4f scaling factor + *damp2 = (int16_t)(32768 - *damp1); // inverse of x1 damp2 = 1.0 - damp1 +} + +mp_obj_t common_hal_audiofreeverb_freeverb_get_mix(audiofreeverb_freeverb_obj_t *self) { + return self->mix.obj; +} + +void common_hal_audiofreeverb_freeverb_set_mix(audiofreeverb_freeverb_obj_t *self, mp_obj_t mix) { + synthio_block_assign_slot(mix, &self->mix, MP_QSTR_mix); +} + +void audiofreeverb_freeverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect) { + mix = mix * (mp_float_t)MICROPY_FLOAT_CONST(2.0); + *mix_sample = (int16_t)(MIN((mp_float_t)MICROPY_FLOAT_CONST(2.0) - mix, (mp_float_t)MICROPY_FLOAT_CONST(1.0)) * 32767); + *mix_effect = (int16_t)(MIN(mix, (mp_float_t)MICROPY_FLOAT_CONST(1.0)) * 32767); +} + +void audiofreeverb_freeverb_reset_buffer(audiofreeverb_freeverb_obj_t *self, + bool single_channel_output, + uint8_t channel) { + + memset(self->buffer[0], 0, self->buffer_len); + memset(self->buffer[1], 0, self->buffer_len); +} + +bool common_hal_audiofreeverb_freeverb_get_playing(audiofreeverb_freeverb_obj_t *self) { + return self->sample != NULL; +} + +void common_hal_audiofreeverb_freeverb_play(audiofreeverb_freeverb_obj_t *self, mp_obj_t sample, bool loop) { + audiosample_must_match(&self->base, sample, false); + + self->sample = sample; + self->loop = loop; + + audiosample_reset_buffer(self->sample, false, 0); + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + + // Track remaining sample length in terms of bytes per sample + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + // Store if we have more data in the sample to retrieve + self->more_data = result == GET_BUFFER_MORE_DATA; + + return; +} + +void common_hal_audiofreeverb_freeverb_stop(audiofreeverb_freeverb_obj_t *self) { + // When the sample is set to stop playing do any cleanup here + // For reverb we clear the sample but the reverb continues until the object reading our effect stops + self->sample = NULL; + return; +} + +audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_freeverb_obj_t *self, bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + // Switch our buffers to the other buffer + self->last_buf_idx = !self->last_buf_idx; + + // 16 bit samples we need a 16 bit pointer + int16_t *word_buffer = (int16_t *)self->buffer[self->last_buf_idx]; + uint32_t length = self->buffer_len / (self->base.bits_per_sample / 8); + + // Loop over the entire length of our buffer to fill it, this may require several calls to get data from the sample + while (length != 0) { + // Check if there is no more sample to play, we will either load more data, reset the sample if loop is on or clear the sample + if (self->sample_buffer_length == 0) { + if (!self->more_data) { // The sample has indicated it has no more data to play + if (self->loop && self->sample) { // If we are supposed to loop reset the sample to the start + audiosample_reset_buffer(self->sample, false, 0); + } else { // If we were not supposed to loop the sample, stop playing it but we still need to play the reverb + self->sample = NULL; + } + } + if (self->sample) { + // Load another sample buffer to play + audioio_get_buffer_result_t result = audiosample_get_buffer(self->sample, false, 0, (uint8_t **)&self->sample_remaining_buffer, &self->sample_buffer_length); + // Track length in terms of words. + self->sample_buffer_length /= (self->base.bits_per_sample / 8); + self->more_data = result == GET_BUFFER_MORE_DATA; + } + } + + // Determine how many bytes we can process to our buffer, the less of the sample we have left and our buffer remaining + uint32_t n; + if (self->sample == NULL) { + n = MIN(length, SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(self->sample_buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } + + // get the effect values we need from the BlockInput. These may change at run time so you need to do bounds checking if required + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + mp_float_t damp = synthio_block_slot_get_limited(&self->damp, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int16_t damp1, damp2; + audiofreeverb_freeverb_get_damp_fixedpoint(damp, &damp1, &damp2); + + mp_float_t mix = synthio_block_slot_get_limited(&self->mix, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int16_t mix_sample, mix_effect; + audiofreeverb_freeverb_get_mix_fixedpoint(mix, &mix_sample, &mix_effect); + + mp_float_t roomsize = synthio_block_slot_get_limited(&self->roomsize, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)); + int16_t feedback = audiofreeverb_freeverb_get_roomsize_fixedpoint(roomsize); + + int16_t *sample_src = (int16_t *)self->sample_remaining_buffer; + + for (uint32_t i = 0; i < n; i++) { + int32_t sample_word = 0; + if (self->sample != NULL) { + sample_word = sample_src[i]; + } + + int32_t word, sum; + int16_t input, bufout, output; + uint32_t channel_comb_offset = 0, channel_allpass_offset = 0; + + input = synthio_sat16(sample_word * 8738, 17); // Initial input scaled down so we can add reverb + sum = 0; + + // Calculate each of the 8 comb buffers + for (uint32_t j = 0 + channel_comb_offset; j < 8 + channel_comb_offset; j++) { + bufout = self->combbuffers[j][self->combbufferindex[j]]; + sum += bufout; + self->combfitlers[j] = synthio_sat16(bufout * damp2 + self->combfitlers[j] * damp1, 15); + self->combbuffers[j][self->combbufferindex[j]] = synthio_sat16(input + synthio_sat16(self->combfitlers[j] * feedback, 15), 0); + if (++self->combbufferindex[j] >= self->combbuffersizes[j]) { + self->combbufferindex[j] = 0; + } + } + + output = synthio_sat16(sum * 31457, 17); // 31457 = 0.24f with shift of 17 + + // Calculate each of the 4 all pass buffers + for (uint32_t j = 0 + channel_allpass_offset; j < 4 + channel_allpass_offset; j++) { + bufout = self->allpassbuffers[j][self->allpassbufferindex[j]]; + self->allpassbuffers[j][self->allpassbufferindex[j]] = output + (bufout >> 1); // bufout >> 1 same as bufout*0.5f + output = synthio_sat16(bufout - output, 1); + if (++self->allpassbufferindex[j] >= self->allpassbuffersizes[j]) { + self->allpassbufferindex[j] = 0; + } + } + + word = output * 30; // Add some volume back don't have to saturate as next step will + + word = synthio_sat16(sample_word * mix_sample, 15) + synthio_sat16(word * mix_effect, 15); + word = synthio_mix_down_sample(word, SYNTHIO_MIX_DOWN_SCALE(2)); + word_buffer[i] = (int16_t)word; + + if ((self->base.channel_count == 2) && (channel_comb_offset == 0)) { + channel_comb_offset = 8; + channel_allpass_offset = 4; + } else { + channel_comb_offset = 0; + channel_allpass_offset = 0; + } + } + + // Update the remaining length and the buffer positions based on how much we wrote into our buffer + length -= n; + word_buffer += n; + self->sample_remaining_buffer += (n * (self->base.bits_per_sample / 8)); + self->sample_buffer_length -= n; + } + + // Finally pass our buffer and length to the calling audio function + *buffer = (uint8_t *)self->buffer[self->last_buf_idx]; + *buffer_length = self->buffer_len; + + // Reverb always returns more data but some effects may return GET_BUFFER_DONE or GET_BUFFER_ERROR (see audiocore/__init__.h) + return GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiofreeverb/Freeverb.h b/shared-module/audiofreeverb/Freeverb.h new file mode 100644 index 0000000000000..44747f0fc951d --- /dev/null +++ b/shared-module/audiofreeverb/Freeverb.h @@ -0,0 +1,56 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "py/obj.h" + +#include "shared-module/audiocore/__init__.h" +#include "shared-module/synthio/__init__.h" +#include "shared-module/synthio/block.h" + +extern const mp_obj_type_t audiofreeverb_freeverb_type; + +typedef struct { + audiosample_base_t base; + synthio_block_slot_t roomsize; + synthio_block_slot_t damp; + synthio_block_slot_t mix; + + int8_t *buffer[2]; + uint8_t last_buf_idx; + uint32_t buffer_len; // max buffer in bytes + + uint8_t *sample_remaining_buffer; + uint32_t sample_buffer_length; + + bool loop; + bool more_data; + + int16_t combbuffersizes[16]; + int16_t *combbuffers[16]; + int16_t combbufferindex[16]; + int16_t combfitlers[16]; + + int16_t allpassbuffersizes[8]; + int16_t *allpassbuffers[8]; + int16_t allpassbufferindex[8]; + + mp_obj_t sample; +} audiofreeverb_freeverb_obj_t; + +void audiofreeverb_freeverb_reset_buffer(audiofreeverb_freeverb_obj_t *self, + bool single_channel_output, + uint8_t channel); + +audioio_get_buffer_result_t audiofreeverb_freeverb_get_buffer(audiofreeverb_freeverb_obj_t *self, + bool single_channel_output, + uint8_t channel, + uint8_t **buffer, + uint32_t *buffer_length); // length in bytes + +int16_t audiofreeverb_freeverb_get_roomsize_fixedpoint(mp_float_t n); +void audiofreeverb_freeverb_get_damp_fixedpoint(mp_float_t n, int16_t *damp1, int16_t *damp2); +void audiofreeverb_freeverb_get_mix_fixedpoint(mp_float_t mix, int16_t *mix_sample, int16_t *mix_effect); diff --git a/shared-module/audiofreeverb/__init__.c b/shared-module/audiofreeverb/__init__.c new file mode 100644 index 0000000000000..94cd4caa3bd1b --- /dev/null +++ b/shared-module/audiofreeverb/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT diff --git a/shared-module/audiofreeverb/__init__.h b/shared-module/audiofreeverb/__init__.h new file mode 100644 index 0000000000000..66463561f5443 --- /dev/null +++ b/shared-module/audiofreeverb/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Mark Komus +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index f086e78323be2..212686a092ee9 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -11,6 +11,7 @@ #include "py/runtime.h" #include "shared-module/audiocore/__init__.h" +#include "shared-bindings/audiocore/__init__.h" #if defined(__arm__) && __arm__ #include "cmsis_compiler.h" @@ -25,46 +26,33 @@ void common_hal_audiomixer_mixer_construct(audiomixer_mixer_obj_t *self, uint32_t sample_rate) { self->len = buffer_size / 2 / sizeof(uint32_t) * sizeof(uint32_t); - self->first_buffer = m_malloc(self->len); + self->first_buffer = m_malloc_without_collect(self->len); if (self->first_buffer == NULL) { common_hal_audiomixer_mixer_deinit(self); m_malloc_fail(self->len); } - self->second_buffer = m_malloc(self->len); + self->second_buffer = m_malloc_without_collect(self->len); if (self->second_buffer == NULL) { common_hal_audiomixer_mixer_deinit(self); m_malloc_fail(self->len); } - self->bits_per_sample = bits_per_sample; - self->samples_signed = samples_signed; - self->channel_count = channel_count; - self->sample_rate = sample_rate; + self->base.bits_per_sample = bits_per_sample; + self->base.samples_signed = samples_signed; + self->base.channel_count = channel_count; + self->base.sample_rate = sample_rate; + self->base.single_buffer = false; self->voice_count = voice_count; + self->base.max_buffer_length = buffer_size; } void common_hal_audiomixer_mixer_deinit(audiomixer_mixer_obj_t *self) { + audiosample_mark_deinit(&self->base); self->first_buffer = NULL; self->second_buffer = NULL; } -bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t *self) { - return self->first_buffer == NULL; -} - -uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t *self) { - return self->sample_rate; -} - -uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t *self) { - return self->channel_count; -} - -uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t *self) { - return self->bits_per_sample; -} - bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t *self) { for (uint8_t v = 0; v < self->voice_count; v++) { if (common_hal_audiomixer_mixervoice_get_playing(MP_OBJ_TO_PTR(self->voice[v]))) { @@ -104,22 +92,23 @@ static inline uint32_t add16signed(uint32_t a, uint32_t b) { } __attribute__((always_inline)) -static inline uint32_t mult16signed(uint32_t val, int32_t mul) { +static inline uint32_t mult16signed(uint32_t val, int32_t mul[2]) { #if (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) - mul <<= 16; + mul[0] <<= 16; + mul[1] <<= 16; int32_t hi, lo; enum { bits = 16 }; // saturate to 16 bits enum { shift = 15 }; // shift is done automatically - asm volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul), "r" (val)); - asm volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul), "r" (val)); - asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); - asm volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); - asm volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack + __asm__ volatile ("smulwb %0, %1, %2" : "=r" (lo) : "r" (mul[0]), "r" (val)); + __asm__ volatile ("smulwt %0, %1, %2" : "=r" (hi) : "r" (mul[1]), "r" (val)); + __asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (lo) : "I" (bits), "r" (lo), "I" (shift)); + __asm__ volatile ("ssat %0, %1, %2, asr %3" : "=r" (hi) : "I" (bits), "r" (hi), "I" (shift)); + __asm__ volatile ("pkhbt %0, %1, %2, lsl #16" : "=r" (val) : "r" (lo), "r" (hi)); // pack return val; #else uint32_t result = 0; - float mod_mul = (float)mul / (float)((1 << 15) - 1); for (int8_t i = 0; i < 2; i++) { + float mod_mul = (float)mul[i] / (float)((1 << 15) - 1); int16_t ai = (val >> (sizeof(uint16_t) * 8 * i)); int32_t intermediate = (int32_t)(ai * mod_mul); if (intermediate > SHRT_MAX) { @@ -166,9 +155,32 @@ static inline uint32_t pack8(uint32_t val) { return ((val & 0xff000000) >> 16) | ((val & 0xff00) >> 8); } +static inline uint32_t copy16lsb(uint32_t val) { + val &= 0x0000ffff; + return val | (val << 16); +} + +static inline uint32_t copy16msb(uint32_t val) { + val &= 0xffff0000; + return val | (val >> 16); +} + +static inline uint32_t copy8lsb(uint32_t val) { + val &= 0x00ff; + return val | (val << 8); +} + +static inline uint32_t copy8msb(uint32_t val) { + val &= 0xff00; + return val | (val >> 8); +} + +#define ALMOST_ONE (MICROPY_FLOAT_CONST(32767.) / 32768) + static void mix_down_one_voice(audiomixer_mixer_obj_t *self, audiomixer_mixervoice_obj_t *voice, bool voices_active, uint32_t *word_buffer, uint32_t length) { + audiosample_base_t *sample = MP_OBJ_TO_PTR(voice->sample); while (length != 0) { if (voice->buffer_length == 0) { if (!voice->more_data) { @@ -188,69 +200,166 @@ static void mix_down_one_voice(audiomixer_mixer_obj_t *self, } } - uint32_t n = MIN(voice->buffer_length, length); uint32_t *src = voice->remaining_buffer; + + #if CIRCUITPY_SYNTHIO + uint32_t n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + n = MIN(MIN(voice->buffer_length, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } else { + n = MIN(MIN(voice->buffer_length << 1, length), SYNTHIO_MAX_DUR * self->base.channel_count); + } + + // Get the current level from the BlockInput. These may change at run time so you need to do bounds checking if required. + shared_bindings_synthio_lfo_tick(self->base.sample_rate, n / self->base.channel_count); + uint16_t level = (uint16_t)(synthio_block_slot_get_limited(&voice->level, MICROPY_FLOAT_CONST(0.0), MICROPY_FLOAT_CONST(1.0)) * (1 << 15)); + int16_t panning = synthio_block_slot_get_scaled(&voice->panning, -ALMOST_ONE, ALMOST_ONE); + #else + uint32_t n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + n = MIN(voice->buffer_length, length); + } else { + n = MIN(voice->buffer_length << 1, length); + } uint16_t level = voice->level; + int16_t panning = voice->panning; + #endif + + uint16_t left_panning_scaled = 32768, right_panning_scaled = 32768; + if (MP_LIKELY(self->base.channel_count == 2)) { + if (panning >= 0) { + right_panning_scaled = 32767 - panning; + } else { + left_panning_scaled = 32767 + panning; + } + } + + int32_t loudness[2] = { level, level }; + if (MP_LIKELY(self->base.channel_count == 2)) { + loudness[0] = (left_panning_scaled * loudness[0]) >> 15; + loudness[1] = (right_panning_scaled * loudness[1]) >> 15; + } // First active voice gets copied over verbatim. if (!voices_active) { - if (MP_LIKELY(self->bits_per_sample == 16)) { - if (MP_LIKELY(self->samples_signed)) { - for (uint32_t i = 0; i < n; i++) { - uint32_t v = src[i]; - word_buffer[i] = mult16signed(v, level); + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + if (MP_LIKELY(self->base.samples_signed)) { + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t v = src[i]; + word_buffer[i] = mult16signed(v, loudness); + } + } else { + for (uint32_t i = 0; i < n; i += 2) { + uint32_t v = src[i >> 1]; + word_buffer[i] = mult16signed(copy16lsb(v), loudness); + word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + } } } else { - for (uint32_t i = 0; i < n; i++) { - uint32_t v = src[i]; - v = tosigned16(v); - word_buffer[i] = mult16signed(v, level); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t v = src[i]; + v = tosigned16(v); + word_buffer[i] = mult16signed(v, loudness); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t v = src[i >> 1]; + v = tosigned16(v); + word_buffer[i] = mult16signed(copy16lsb(v), loudness); + word_buffer[i + 1] = mult16signed(copy16msb(v), loudness); + } } } } else { uint16_t *hword_buffer = (uint16_t *)word_buffer; uint16_t *hsrc = (uint16_t *)src; - for (uint32_t i = 0; i < n * 2; i++) { - uint32_t word = unpack8(hsrc[i]); - if (MP_LIKELY(!self->samples_signed)) { - word = tosigned16(word); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n * 2; i++) { + uint32_t word = unpack8(hsrc[i]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, loudness); + hword_buffer[i] = pack8(word); + } + } else { + for (uint32_t i = 0; i + 1 < n * 2; i += 2) { + uint32_t word = unpack8(hsrc[i >> 1]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + hword_buffer[i] = pack8(mult16signed(copy16lsb(word), loudness)); + hword_buffer[i + 1] = pack8(mult16signed(copy16msb(word), loudness)); } - word = mult16signed(word, level); - hword_buffer[i] = pack8(word); } } } else { - if (MP_LIKELY(self->bits_per_sample == 16)) { - if (MP_LIKELY(self->samples_signed)) { - for (uint32_t i = 0; i < n; i++) { - uint32_t word = src[i]; - word_buffer[i] = add16signed(mult16signed(word, level), word_buffer[i]); + if (MP_LIKELY(self->base.bits_per_sample == 16)) { + if (MP_LIKELY(self->base.samples_signed)) { + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t word = src[i]; + word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t word = src[i >> 1]; + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + } } } else { - for (uint32_t i = 0; i < n; i++) { - uint32_t word = src[i]; - word = tosigned16(word); - word_buffer[i] = add16signed(mult16signed(word, level), word_buffer[i]); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n; i++) { + uint32_t word = src[i]; + word = tosigned16(word); + word_buffer[i] = add16signed(mult16signed(word, loudness), word_buffer[i]); + } + } else { + for (uint32_t i = 0; i + 1 < n; i += 2) { + uint32_t word = src[i >> 1]; + word = tosigned16(word); + word_buffer[i] = add16signed(mult16signed(copy16lsb(word), loudness), word_buffer[i]); + word_buffer[i + 1] = add16signed(mult16signed(copy16msb(word), loudness), word_buffer[i + 1]); + } } } } else { uint16_t *hword_buffer = (uint16_t *)word_buffer; uint16_t *hsrc = (uint16_t *)src; - for (uint32_t i = 0; i < n * 2; i++) { - uint32_t word = unpack8(hsrc[i]); - if (MP_LIKELY(!self->samples_signed)) { - word = tosigned16(word); + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + for (uint32_t i = 0; i < n * 2; i++) { + uint32_t word = unpack8(hsrc[i]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + word = mult16signed(word, loudness); + word = add16signed(word, unpack8(hword_buffer[i])); + hword_buffer[i] = pack8(word); + } + } else { + for (uint32_t i = 0; i + 1 < n * 2; i += 2) { + uint32_t word = unpack8(hsrc[i >> 1]); + if (MP_LIKELY(!self->base.samples_signed)) { + word = tosigned16(word); + } + hword_buffer[i] = pack8(add16signed(mult16signed(copy16lsb(word), loudness), unpack8(hword_buffer[i]))); + hword_buffer[i + 1] = pack8(add16signed(mult16signed(copy16msb(word), loudness), unpack8(hword_buffer[i + 1]))); } - word = mult16signed(word, level); - word = add16signed(word, unpack8(hword_buffer[i])); - hword_buffer[i] = pack8(word); } } } length -= n; word_buffer += n; - voice->remaining_buffer += n; - voice->buffer_length -= n; + if (MP_LIKELY(self->base.channel_count == sample->channel_count)) { + voice->remaining_buffer += n; + voice->buffer_length -= n; + } else { + voice->remaining_buffer += n >> 1; + voice->buffer_length -= n >> 1; + } } if (length && !voices_active) { @@ -303,8 +412,8 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t * } } - if (!self->samples_signed) { - if (self->bits_per_sample == 16) { + if (!self->base.samples_signed) { + if (self->base.bits_per_sample == 16) { for (uint32_t i = 0; i < length; i++) { word_buffer[i] = tounsigned16(word_buffer[i]); } @@ -327,20 +436,7 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t * self->left_read_count += 1; } else if (channel == 1) { self->right_read_count += 1; - *buffer = *buffer + self->bits_per_sample / 8; + *buffer = *buffer + self->base.bits_per_sample / 8; } return GET_BUFFER_MORE_DATA; } - -void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing) { - *single_buffer = false; - *samples_signed = self->samples_signed; - *max_buffer_length = self->len; - if (single_channel_output) { - *spacing = self->channel_count; - } else { - *spacing = 1; - } -} diff --git a/shared-module/audiomixer/Mixer.h b/shared-module/audiomixer/Mixer.h index 771b3969719c9..b793fa12a2d49 100644 --- a/shared-module/audiomixer/Mixer.h +++ b/shared-module/audiomixer/Mixer.h @@ -12,15 +12,11 @@ #include "shared-module/audiocore/__init__.h" typedef struct { - mp_obj_base_t base; + audiosample_base_t base; uint32_t *first_buffer; uint32_t *second_buffer; uint32_t len; // in words - uint8_t bits_per_sample; bool use_first_buffer; - bool samples_signed; - uint8_t channel_count; - uint32_t sample_rate; uint32_t read_count; uint32_t left_read_count; @@ -41,6 +37,3 @@ audioio_get_buffer_result_t audiomixer_mixer_get_buffer(audiomixer_mixer_obj_t * uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audiomixer_mixer_get_buffer_structure(audiomixer_mixer_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/audiomixer/MixerVoice.c b/shared-module/audiomixer/MixerVoice.c index c32d37cdec288..6c23a39215cbc 100644 --- a/shared-module/audiomixer/MixerVoice.c +++ b/shared-module/audiomixer/MixerVoice.c @@ -15,40 +15,58 @@ void common_hal_audiomixer_mixervoice_construct(audiomixer_mixervoice_obj_t *self) { self->sample = NULL; - self->level = 1 << 15; + common_hal_audiomixer_mixervoice_set_level(self, mp_obj_new_float(1.0)); + common_hal_audiomixer_mixervoice_set_panning(self, mp_obj_new_float(0.0)); } void common_hal_audiomixer_mixervoice_set_parent(audiomixer_mixervoice_obj_t *self, audiomixer_mixer_obj_t *parent) { self->parent = parent; } -mp_float_t common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t *self) { - return (mp_float_t)self->level / (1 << 15); +mp_obj_t common_hal_audiomixer_mixervoice_get_level(audiomixer_mixervoice_obj_t *self) { + #if CIRCUITPY_SYNTHIO + return self->level.obj; + #else + return mp_obj_new_float((mp_float_t)self->level / (1 << 15)); + #endif } -void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *self, mp_float_t level) { - self->level = (uint16_t)(level * (1 << 15)); +void common_hal_audiomixer_mixervoice_set_level(audiomixer_mixervoice_obj_t *self, mp_obj_t arg) { + #if CIRCUITPY_SYNTHIO + synthio_block_assign_slot(arg, &self->level, MP_QSTR_level); + #else + self->level = (uint16_t)(mp_arg_validate_obj_float_range(arg, 0, 1, MP_QSTR_level) * (1 << 15)); + #endif } -void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample, bool loop) { - if (audiosample_sample_rate(sample) != self->parent->sample_rate) { - mp_raise_ValueError(MP_ERROR_TEXT("The sample's sample rate does not match the mixer's")); - } - if (audiosample_channel_count(sample) != self->parent->channel_count) { - mp_raise_ValueError(MP_ERROR_TEXT("The sample's channel count does not match the mixer's")); - } - if (audiosample_bits_per_sample(sample) != self->parent->bits_per_sample) { - mp_raise_ValueError(MP_ERROR_TEXT("The sample's bits_per_sample does not match the mixer's")); - } - bool single_buffer; - bool samples_signed; - uint32_t max_buffer_length; - uint8_t spacing; - audiosample_get_buffer_structure(sample, false, &single_buffer, &samples_signed, - &max_buffer_length, &spacing); - if (samples_signed != self->parent->samples_signed) { - mp_raise_ValueError(MP_ERROR_TEXT("The sample's signedness does not match the mixer's")); - } +mp_obj_t common_hal_audiomixer_mixervoice_get_panning(audiomixer_mixervoice_obj_t *self) { + #if CIRCUITPY_SYNTHIO + return self->panning.obj; + #else + return mp_obj_new_float((mp_float_t)self->panning / ((1 << 15) - 1)); + #endif +} + +void common_hal_audiomixer_mixervoice_set_panning(audiomixer_mixervoice_obj_t *self, mp_obj_t arg) { + #if CIRCUITPY_SYNTHIO + synthio_block_assign_slot(arg, &self->panning, MP_QSTR_panning); + #else + self->panning = (uint16_t)(mp_arg_validate_obj_float_range(arg, -1, 1, MP_QSTR_panning) * ((1 << 15) - 1)); + #endif +} + +bool common_hal_audiomixer_mixervoice_get_loop(audiomixer_mixervoice_obj_t *self) { + return self->loop; +} + +void common_hal_audiomixer_mixervoice_set_loop(audiomixer_mixervoice_obj_t *self, bool loop) { + self->loop = loop; +} + +void common_hal_audiomixer_mixervoice_play(audiomixer_mixervoice_obj_t *self, mp_obj_t sample_in, bool loop) { + audiosample_must_match(&self->parent->base, sample_in, true); + // cast is safe, checked by must_match + audiosample_base_t *sample = MP_OBJ_TO_PTR(sample_in); self->sample = sample; self->loop = loop; @@ -66,3 +84,9 @@ bool common_hal_audiomixer_mixervoice_get_playing(audiomixer_mixervoice_obj_t *s void common_hal_audiomixer_mixervoice_stop(audiomixer_mixervoice_obj_t *self) { self->sample = NULL; } + +void common_hal_audiomixer_mixervoice_end(audiomixer_mixervoice_obj_t *self) { + if (self->sample != NULL) { + self->loop = false; + } +} diff --git a/shared-module/audiomixer/MixerVoice.h b/shared-module/audiomixer/MixerVoice.h index ad70f64b6e16f..75e7d47faa33d 100644 --- a/shared-module/audiomixer/MixerVoice.h +++ b/shared-module/audiomixer/MixerVoice.h @@ -9,6 +9,9 @@ #include "shared-module/audiomixer/__init__.h" #include "shared-module/audiomixer/Mixer.h" +#if CIRCUITPY_SYNTHIO +#include "shared-module/synthio/block.h" +#endif typedef struct { mp_obj_base_t base; @@ -18,5 +21,11 @@ typedef struct { bool more_data; uint32_t *remaining_buffer; uint32_t buffer_length; + #if CIRCUITPY_SYNTHIO + synthio_block_slot_t level; + synthio_block_slot_t panning; + #else uint16_t level; + int16_t panning; + #endif } audiomixer_mixervoice_obj_t; diff --git a/shared-module/audiomp3/MP3Decoder.c b/shared-module/audiomp3/MP3Decoder.c index f59f4a4510b66..dc22c0be2454c 100644 --- a/shared-module/audiomp3/MP3Decoder.c +++ b/shared-module/audiomp3/MP3Decoder.c @@ -6,6 +6,7 @@ // SPDX-License-Identifier: MIT #include "shared-bindings/audiomp3/MP3Decoder.h" +#include "shared-bindings/audiocore/__init__.h" #include #include @@ -20,6 +21,7 @@ #include "shared-module/audiomp3/MP3Decoder.h" #include "supervisor/background_callback.h" #include "lib/mp3/src/mp3common.h" +#include "lib/mp3/src/coder.h" #define MAX_BUFFER_LEN (MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t)) @@ -167,7 +169,7 @@ static bool mp3file_update_inbuf_always(audiomp3_mp3file_obj_t *self, bool block */ static void mp3file_update_inbuf_cb(void *self_in) { audiomp3_mp3file_obj_t *self = self_in; - if (common_hal_audiomp3_mp3file_deinited(self_in)) { + if (audiosample_deinited(&self->base)) { return; } if (!self->eof && stream_readable(self->stream)) { @@ -303,7 +305,7 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, self->inbuf.size = buffer_size - 2 * MAX_BUFFER_LEN; } else { self->inbuf.size = DEFAULT_INPUT_BUFFER_SIZE; - self->inbuf.buf = m_malloc(DEFAULT_INPUT_BUFFER_SIZE); + self->inbuf.buf = m_malloc_without_collect(DEFAULT_INPUT_BUFFER_SIZE); if (self->inbuf.buf == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(DEFAULT_INPUT_BUFFER_SIZE); @@ -313,13 +315,13 @@ void common_hal_audiomp3_mp3file_construct(audiomp3_mp3file_obj_t *self, self->pcm_buffer[0] = (int16_t *)(void *)buffer; self->pcm_buffer[1] = (int16_t *)(void *)(buffer + MAX_BUFFER_LEN); } else { - self->pcm_buffer[0] = m_malloc(MAX_BUFFER_LEN); + self->pcm_buffer[0] = m_malloc_without_collect(MAX_BUFFER_LEN); if (self->pcm_buffer[0] == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(MAX_BUFFER_LEN); } - self->pcm_buffer[1] = m_malloc(MAX_BUFFER_LEN); + self->pcm_buffer[1] = m_malloc_without_collect(MAX_BUFFER_LEN); if (self->pcm_buffer[1] == NULL) { common_hal_audiomp3_mp3file_deinit(self); m_malloc_fail(MAX_BUFFER_LEN); @@ -360,6 +362,17 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t // get_buffer() that I didn't understand. memset(self->pcm_buffer[0], 0, MAX_BUFFER_LEN); memset(self->pcm_buffer[1], 0, MAX_BUFFER_LEN); + + /* important to do this - DSP primitives assume a bunch of state variables are 0 on first use */ + struct _MP3DecInfo *decoder = self->decoder; + memset(decoder->FrameHeaderPS, 0, sizeof(FrameHeader)); + memset(decoder->SideInfoPS, 0, sizeof(SideInfo)); + memset(decoder->ScaleFactorInfoPS, 0, sizeof(ScaleFactorInfo)); + memset(decoder->HuffmanInfoPS, 0, sizeof(HuffmanInfo)); + memset(decoder->DequantInfoPS, 0, sizeof(DequantInfo)); + memset(decoder->IMDCTInfoPS, 0, sizeof(IMDCTInfo)); + memset(decoder->SubbandInfoPS, 0, sizeof(SubbandInfo)); + MP3FrameInfo fi; bool result = mp3file_get_next_frame_info(self, &fi, true); background_callback_allow(); @@ -368,14 +381,18 @@ void common_hal_audiomp3_mp3file_set_file(audiomp3_mp3file_obj_t *self, mp_obj_t MP_ERROR_TEXT("Failed to parse MP3 file")); } - self->sample_rate = fi.samprate; - self->channel_count = fi.nChans; - self->frame_buffer_size = fi.outputSamps * sizeof(int16_t); - self->len = 2 * self->frame_buffer_size; + self->base.sample_rate = fi.samprate; + self->base.channel_count = fi.nChans; + self->base.single_buffer = false; + self->base.bits_per_sample = 16; + self->base.samples_signed = true; + self->base.max_buffer_length = fi.outputSamps * sizeof(int16_t); + self->len = 2 * self->base.max_buffer_length; self->samples_decoded = 0; } void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) { + audiosample_mark_deinit(&self->base); if (self->decoder) { MP3FreeDecoder(self->decoder); } @@ -388,27 +405,6 @@ void common_hal_audiomp3_mp3file_deinit(audiomp3_mp3file_obj_t *self) { self->samples_decoded = 0; } -bool common_hal_audiomp3_mp3file_deinited(audiomp3_mp3file_obj_t *self) { - return self->pcm_buffer[0] == NULL; -} - -uint32_t common_hal_audiomp3_mp3file_get_sample_rate(audiomp3_mp3file_obj_t *self) { - return self->sample_rate; -} - -void common_hal_audiomp3_mp3file_set_sample_rate(audiomp3_mp3file_obj_t *self, - uint32_t sample_rate) { - self->sample_rate = sample_rate; -} - -uint8_t common_hal_audiomp3_mp3file_get_bits_per_sample(audiomp3_mp3file_obj_t *self) { - return 16; -} - -uint8_t common_hal_audiomp3_mp3file_get_channel_count(audiomp3_mp3file_obj_t *self) { - return self->channel_count; -} - void audiomp3_mp3file_reset_buffer(audiomp3_mp3file_obj_t *self, bool single_channel_output, uint8_t channel) { @@ -445,7 +441,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * channel = 0; } - size_t frame_buffer_size_bytes = self->frame_buffer_size; + size_t frame_buffer_size_bytes = self->base.max_buffer_length; *buffer_length = frame_buffer_size_bytes; if (channel == self->other_channel) { @@ -467,7 +463,7 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * mp3file_skip_id3v2(self, false); if (!mp3file_find_sync_word(self, false)) { - memset(buffer, 0, self->frame_buffer_size); + memset(buffer, 0, self->base.max_buffer_length); *buffer_length = 0; return self->eof ? GET_BUFFER_DONE : GET_BUFFER_ERROR; } @@ -482,8 +478,8 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * if (DO_DEBUG) { mp_printf(&mp_plat_print, "%s:%d err=%d\n", __FILE__, __LINE__, err); } - if (err != ERR_MP3_INDATA_UNDERFLOW && err != ERR_MP3_MAINDATA_UNDERFLOW) { - memset(buffer, 0, self->frame_buffer_size); + if (self->eof || (err != ERR_MP3_INDATA_UNDERFLOW && err != ERR_MP3_MAINDATA_UNDERFLOW)) { + memset(buffer, 0, self->base.max_buffer_length); *buffer_length = 0; self->eof = true; return GET_BUFFER_ERROR; @@ -511,27 +507,14 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * return result; } -void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing) { - *single_buffer = false; - *samples_signed = true; - *max_buffer_length = self->frame_buffer_size; - if (single_channel_output) { - *spacing = self->channel_count; - } else { - *spacing = 1; - } -} - float common_hal_audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self) { float sumsq = 0.f; // Assumes no DC component to the audio. Is that a safe assumption? int16_t *buffer = (int16_t *)(void *)self->pcm_buffer[self->buffer_index]; - for (size_t i = 0; i < self->frame_buffer_size / sizeof(int16_t); i++) { + for (size_t i = 0; i < self->base.max_buffer_length / sizeof(int16_t); i++) { sumsq += (float)buffer[i] * buffer[i]; } - return sqrtf(sumsq) / (self->frame_buffer_size / sizeof(int16_t)); + return sqrtf(sumsq) / (self->base.max_buffer_length / sizeof(int16_t)); } uint32_t common_hal_audiomp3_mp3file_get_samples_decoded(audiomp3_mp3file_obj_t *self) { diff --git a/shared-module/audiomp3/MP3Decoder.h b/shared-module/audiomp3/MP3Decoder.h index 9f1b97a5a516d..9af3300047b26 100644 --- a/shared-module/audiomp3/MP3Decoder.h +++ b/shared-module/audiomp3/MP3Decoder.h @@ -21,19 +21,16 @@ typedef struct { } mp3_input_buffer_t; typedef struct { - mp_obj_base_t base; + audiosample_base_t base; struct _MP3DecInfo *decoder; background_callback_t inbuf_fill_cb; mp3_input_buffer_t inbuf; int16_t *pcm_buffer[2]; uint32_t len; - uint32_t frame_buffer_size; - uint32_t sample_rate; mp_obj_t stream; uint8_t buffer_index; - uint8_t channel_count; bool eof; bool block_ok; mp_obj_t settimeout_args[3]; @@ -53,9 +50,6 @@ audioio_get_buffer_result_t audiomp3_mp3file_get_buffer(audiomp3_mp3file_obj_t * uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes -void audiomp3_mp3file_get_buffer_structure(audiomp3_mp3file_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); float audiomp3_mp3file_get_rms_level(audiomp3_mp3file_obj_t *self); diff --git a/shared-module/audiospeed/SpeedChanger.c b/shared-module/audiospeed/SpeedChanger.c new file mode 100644 index 0000000000000..e76bed1f17c39 --- /dev/null +++ b/shared-module/audiospeed/SpeedChanger.c @@ -0,0 +1,175 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/audiospeed/SpeedChanger.h" + +#include +#include "py/runtime.h" +#include "py/gc.h" + +#include "shared-module/audiocore/WaveFile.h" +#include "shared-bindings/audiocore/__init__.h" + +#define OUTPUT_BUFFER_FRAMES 128 + +void common_hal_audiospeed_speedchanger_construct(audiospeed_speedchanger_obj_t *self, + mp_obj_t source, uint32_t rate_fp) { + audiosample_base_t *src_base = audiosample_check(source); + + self->source = source; + self->rate_fp = rate_fp; + self->phase = 0; + self->src_buffer = NULL; + self->src_buffer_length = 0; + self->src_sample_count = 0; + self->source_done = false; + self->source_exhausted = false; + + // Copy format from source + self->base.sample_rate = src_base->sample_rate; + self->base.channel_count = src_base->channel_count; + self->base.bits_per_sample = src_base->bits_per_sample; + self->base.samples_signed = src_base->samples_signed; + self->base.single_buffer = true; + + uint8_t bytes_per_frame = (src_base->bits_per_sample / 8) * src_base->channel_count; + self->output_buffer_length = OUTPUT_BUFFER_FRAMES * bytes_per_frame; + self->base.max_buffer_length = self->output_buffer_length; + + self->output_buffer = m_malloc_without_collect(self->output_buffer_length); + if (self->output_buffer == NULL) { + m_malloc_fail(self->output_buffer_length); + } +} + +void common_hal_audiospeed_speedchanger_deinit(audiospeed_speedchanger_obj_t *self) { + self->output_buffer = NULL; + self->source = MP_OBJ_NULL; + audiosample_mark_deinit(&self->base); +} + +void common_hal_audiospeed_speedchanger_set_rate(audiospeed_speedchanger_obj_t *self, uint32_t rate_fp) { + self->rate_fp = rate_fp; +} + +uint32_t common_hal_audiospeed_speedchanger_get_rate(audiospeed_speedchanger_obj_t *self) { + return self->rate_fp; +} + +// Fetch the next buffer from the source. Returns false if no data available. +static bool fetch_source_buffer(audiospeed_speedchanger_obj_t *self) { + if (self->source_exhausted) { + return false; + } + uint8_t *buf = NULL; + uint32_t len = 0; + audioio_get_buffer_result_t result = audiosample_get_buffer(self->source, false, 0, &buf, &len); + if (result == GET_BUFFER_ERROR) { + self->source_exhausted = true; + return false; + } + if (len == 0) { + self->source_exhausted = true; + return false; + } + self->src_buffer = buf; + self->src_buffer_length = len; + uint8_t bytes_per_frame = (self->base.bits_per_sample / 8) * self->base.channel_count; + self->src_sample_count = len / bytes_per_frame; + self->source_done = (result == GET_BUFFER_DONE); + // Reset phase to index within this new buffer + self->phase = 0; + return true; +} + +void audiospeed_speedchanger_reset_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel) { + if (single_channel_output && channel == 1) { + return; + } + audiosample_reset_buffer(self->source, false, 0); + self->phase = 0; + self->src_buffer = NULL; + self->src_buffer_length = 0; + self->src_sample_count = 0; + self->source_done = false; + self->source_exhausted = false; +} + +audioio_get_buffer_result_t audiospeed_speedchanger_get_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length) { + + // Ensure we have a source buffer + if (self->src_buffer == NULL) { + if (!fetch_source_buffer(self)) { + *buffer = NULL; + *buffer_length = 0; + return GET_BUFFER_DONE; + } + } + + uint8_t bytes_per_sample = self->base.bits_per_sample / 8; + uint8_t channels = self->base.channel_count; + uint8_t bytes_per_frame = bytes_per_sample * channels; + uint32_t out_frames = 0; + uint32_t max_out_frames = self->output_buffer_length / bytes_per_frame; + + if (bytes_per_sample == 1) { + // 8-bit samples + uint8_t *out = self->output_buffer; + while (out_frames < max_out_frames) { + uint32_t src_index = self->phase >> SPEED_SHIFT; + // Advance to next source buffer if needed + if (src_index >= self->src_sample_count) { + if (self->source_done) { + self->source_exhausted = true; + break; + } + if (!fetch_source_buffer(self)) { + break; + } + src_index = 0; // phase was reset by fetch + } + uint8_t *src = self->src_buffer + src_index * bytes_per_frame; + for (uint8_t c = 0; c < channels; c++) { + *out++ = src[c]; + } + out_frames++; + self->phase += self->rate_fp; + } + } else { + // 16-bit samples + int16_t *out = (int16_t *)self->output_buffer; + while (out_frames < max_out_frames) { + uint32_t src_index = self->phase >> SPEED_SHIFT; + if (src_index >= self->src_sample_count) { + if (self->source_done) { + self->source_exhausted = true; + break; + } + if (!fetch_source_buffer(self)) { + break; + } + src_index = 0; + } + int16_t *src = (int16_t *)(self->src_buffer + src_index * bytes_per_frame); + for (uint8_t c = 0; c < channels; c++) { + *out++ = src[c]; + } + out_frames++; + self->phase += self->rate_fp; + } + } + + *buffer = self->output_buffer; + *buffer_length = out_frames * bytes_per_frame; + + if (out_frames == 0) { + return GET_BUFFER_DONE; + } + return self->source_exhausted ? GET_BUFFER_DONE : GET_BUFFER_MORE_DATA; +} diff --git a/shared-module/audiospeed/SpeedChanger.h b/shared-module/audiospeed/SpeedChanger.h new file mode 100644 index 0000000000000..e920c72caf461 --- /dev/null +++ b/shared-module/audiospeed/SpeedChanger.h @@ -0,0 +1,35 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/audiocore/__init__.h" + +// Fixed-point 16.16 format +#define SPEED_SHIFT 16 + +typedef struct { + audiosample_base_t base; + mp_obj_t source; + uint8_t *output_buffer; + uint32_t output_buffer_length; // in bytes, allocated size + // Source buffer cache + uint8_t *src_buffer; + uint32_t src_buffer_length; // in bytes + uint32_t src_sample_count; // in frames + // Phase accumulator and rate in 16.16 fixed-point (units: source frames) + uint32_t phase; + uint32_t rate_fp; // 16.16 fixed-point rate + bool source_done; // source returned DONE on last get_buffer + bool source_exhausted; // source DONE and we consumed all of it +} audiospeed_speedchanger_obj_t; + +void audiospeed_speedchanger_reset_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel); +audioio_get_buffer_result_t audiospeed_speedchanger_get_buffer(audiospeed_speedchanger_obj_t *self, + bool single_channel_output, uint8_t channel, + uint8_t **buffer, uint32_t *buffer_length); diff --git a/shared-module/audiospeed/__init__.c b/shared-module/audiospeed/__init__.c new file mode 100644 index 0000000000000..7c9b271a4b501 --- /dev/null +++ b/shared-module/audiospeed/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT diff --git a/shared-module/audiospeed/__init__.h b/shared-module/audiospeed/__init__.h new file mode 100644 index 0000000000000..c4a52e5819d12 --- /dev/null +++ b/shared-module/audiospeed/__init__.h @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Tod Kurt +// +// SPDX-License-Identifier: MIT + +#pragma once diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c index 0089bdc1e1e1e..d88455729e28b 100644 --- a/shared-module/bitbangio/I2C.c +++ b/shared-module/bitbangio/I2C.c @@ -8,10 +8,15 @@ #include "py/mperrno.h" #include "py/obj.h" #include "py/runtime.h" +#include "py/gc.h" #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" +#include "shared-bindings/util.h" +#include "supervisor/port.h" static void delay(bitbangio_i2c_obj_t *self) { // We need to use an accurate delay to get acceptable I2C @@ -19,61 +24,81 @@ static void delay(bitbangio_i2c_obj_t *self) { common_hal_mcu_delay_us(self->us_delay); } -static void scl_low(bitbangio_i2c_obj_t *self) { - common_hal_digitalio_digitalinout_set_value(&self->scl, false); +static bool scl_low(bitbangio_i2c_obj_t *self) { + return digitalinout_protocol_set_value(self->scl, false) == 0; } -static void scl_release(bitbangio_i2c_obj_t *self) { - common_hal_digitalio_digitalinout_set_value(&self->scl, true); +static bool scl_release(bitbangio_i2c_obj_t *self) { + if (digitalinout_protocol_set_value(self->scl, true) != 0) { + return false; + } uint32_t count = self->us_timeout; delay(self); // For clock stretching, wait for the SCL pin to be released, with timeout. - common_hal_digitalio_digitalinout_switch_to_input(&self->scl, PULL_UP); - for (; !common_hal_digitalio_digitalinout_get_value(&self->scl) && count; --count) { + digitalinout_protocol_switch_to_input(self->scl, PULL_UP); + bool value; + for (; count; --count) { + if (digitalinout_protocol_get_value(self->scl, &value) != 0) { + return false; + } + if (value) { + break; + } common_hal_mcu_delay_us(1); } - common_hal_digitalio_digitalinout_switch_to_output(&self->scl, true, DRIVE_MODE_OPEN_DRAIN); + digitalinout_protocol_switch_to_output(self->scl, true, DRIVE_MODE_OPEN_DRAIN); // raise exception on timeout if (count == 0) { mp_raise_msg_varg(&mp_type_TimeoutError, MP_ERROR_TEXT("%q too long"), MP_QSTR_timeout); } + return true; } -static void sda_low(bitbangio_i2c_obj_t *self) { - common_hal_digitalio_digitalinout_set_value(&self->sda, false); +static bool sda_low(bitbangio_i2c_obj_t *self) { + return digitalinout_protocol_set_value(self->sda, false) == 0; } -static void sda_release(bitbangio_i2c_obj_t *self) { - common_hal_digitalio_digitalinout_set_value(&self->sda, true); +static bool sda_release(bitbangio_i2c_obj_t *self) { + return digitalinout_protocol_set_value(self->sda, true) == 0; } -static bool sda_read(bitbangio_i2c_obj_t *self) { - common_hal_digitalio_digitalinout_switch_to_input(&self->sda, PULL_UP); - bool value = common_hal_digitalio_digitalinout_get_value(&self->sda); - common_hal_digitalio_digitalinout_switch_to_output(&self->sda, true, DRIVE_MODE_OPEN_DRAIN); - return value; +static bool sda_read(bitbangio_i2c_obj_t *self, bool *value) { + digitalinout_protocol_switch_to_input(self->sda, PULL_UP); + if (digitalinout_protocol_get_value(self->sda, value) != 0) { + return false; + } + digitalinout_protocol_switch_to_output(self->sda, true, DRIVE_MODE_OPEN_DRAIN); + return true; } -static void start(bitbangio_i2c_obj_t *self) { - sda_release(self); +static bool start(bitbangio_i2c_obj_t *self) { + if (!sda_release(self)) { + return false; + } delay(self); scl_release(self); sda_low(self); delay(self); + return true; } -static void stop(bitbangio_i2c_obj_t *self) { +static bool stop(bitbangio_i2c_obj_t *self) { delay(self); - sda_low(self); + if (!sda_low(self)) { + return false; + } delay(self); scl_release(self); sda_release(self); delay(self); + return true; } static int write_byte(bitbangio_i2c_obj_t *self, uint8_t val) { delay(self); - scl_low(self); + if (!scl_low(self)) { + return -1; + } for (int i = 7; i >= 0; i--) { if ((val >> i) & 1) { @@ -90,7 +115,10 @@ static int write_byte(bitbangio_i2c_obj_t *self, uint8_t val) { delay(self); scl_release(self); - int ret = sda_read(self); + bool ret; + if (!sda_read(self, &ret)) { + return -1; + } delay(self); scl_low(self); @@ -99,13 +127,17 @@ static int write_byte(bitbangio_i2c_obj_t *self, uint8_t val) { static bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) { delay(self); - scl_low(self); + if (!scl_low(self)) { + return false; + } delay(self); uint8_t data = 0; for (int i = 7; i >= 0; i--) { scl_release(self); - data = (data << 1) | sda_read(self); + bool bit; + sda_read(self, &bit); + data = (data << 1) | bit; scl_low(self); delay(self); } @@ -124,8 +156,8 @@ static bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) { } void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, - const mcu_pin_obj_t *scl, - const mcu_pin_obj_t *sda, + mp_obj_t scl, + mp_obj_t sda, uint32_t frequency, uint32_t us_timeout) { @@ -134,32 +166,42 @@ void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, if (self->us_delay == 0) { self->us_delay = 1; } - digitalinout_result_t result = common_hal_digitalio_digitalinout_construct(&self->scl, scl); - if (result != DIGITALINOUT_OK) { - return; - } - result = common_hal_digitalio_digitalinout_construct(&self->sda, sda); - if (result != DIGITALINOUT_OK) { - common_hal_digitalio_digitalinout_deinit(&self->scl); - return; - } - common_hal_digitalio_digitalinout_switch_to_output(&self->scl, true, DRIVE_MODE_OPEN_DRAIN); - common_hal_digitalio_digitalinout_switch_to_output(&self->sda, true, DRIVE_MODE_OPEN_DRAIN); - stop(self); + // Allocate the pins in the same place as self. + bool use_port_allocation = !gc_alloc_possible() || !gc_ptr_on_heap(self); + + // Convert scl from Pin to DigitalInOutProtocol + self->scl = digitalinout_protocol_from_pin(scl, MP_QSTR_scl, false, use_port_allocation, &self->own_scl); + + // Convert sda from Pin to DigitalInOutProtocol + self->sda = digitalinout_protocol_from_pin(sda, MP_QSTR_sda, false, use_port_allocation, &self->own_sda); + + digitalinout_protocol_switch_to_output(self->scl, true, DRIVE_MODE_OPEN_DRAIN); + digitalinout_protocol_switch_to_output(self->sda, true, DRIVE_MODE_OPEN_DRAIN); + + if (!stop(self)) { + mp_raise_OSError(MP_EIO); + } } bool shared_module_bitbangio_i2c_deinited(bitbangio_i2c_obj_t *self) { // If one is deinited, both will be. - return common_hal_digitalio_digitalinout_deinited(&self->scl); + return digitalinout_protocol_deinited(self->scl); } void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self) { if (shared_module_bitbangio_i2c_deinited(self)) { return; } - common_hal_digitalio_digitalinout_deinit(&self->scl); - common_hal_digitalio_digitalinout_deinit(&self->sda); + // Only deinit and free the pins if we own them + if (self->own_scl) { + digitalinout_protocol_deinit(self->scl); + circuitpy_free_obj(self->scl); + } + if (self->own_sda) { + digitalinout_protocol_deinit(self->sda); + circuitpy_free_obj(self->sda); + } } bool shared_module_bitbangio_i2c_try_lock(bitbangio_i2c_obj_t *self) { @@ -182,18 +224,28 @@ void shared_module_bitbangio_i2c_unlock(bitbangio_i2c_obj_t *self) { } bool shared_module_bitbangio_i2c_probe(bitbangio_i2c_obj_t *self, uint8_t addr) { - start(self); - bool ok = write_byte(self, addr << 1); + if (!start(self)) { + mp_raise_OSError(MP_EIO); + } + int result = write_byte(self, addr << 1); stop(self); - return ok; + if (result < 0) { + mp_raise_OSError(MP_EIO); + } + return result; } uint8_t shared_module_bitbangio_i2c_write(bitbangio_i2c_obj_t *self, uint16_t addr, const uint8_t *data, size_t len, bool transmit_stop_bit) { // start the I2C transaction - start(self); + if (!start(self)) { + return MP_EIO; + } uint8_t status = 0; - if (!write_byte(self, addr << 1)) { + int result = write_byte(self, addr << 1); + if (result < 0) { + status = MP_EIO; + } else if (!result) { status = MP_ENODEV; } @@ -215,7 +267,9 @@ uint8_t shared_module_bitbangio_i2c_write(bitbangio_i2c_obj_t *self, uint16_t ad uint8_t shared_module_bitbangio_i2c_read(bitbangio_i2c_obj_t *self, uint16_t addr, uint8_t *data, size_t len) { // start the I2C transaction - start(self); + if (!start(self)) { + return MP_EIO; + } uint8_t status = 0; if (!write_byte(self, (addr << 1) | 1)) { status = MP_ENODEV; diff --git a/shared-module/bitbangio/I2C.h b/shared-module/bitbangio/I2C.h index 3908a3dd3740e..0cec9186e9b9d 100644 --- a/shared-module/bitbangio/I2C.h +++ b/shared-module/bitbangio/I2C.h @@ -12,9 +12,11 @@ typedef struct { mp_obj_base_t base; - digitalio_digitalinout_obj_t scl; - digitalio_digitalinout_obj_t sda; + mp_obj_t scl; + mp_obj_t sda; uint32_t us_delay; uint32_t us_timeout; volatile bool locked; + bool own_scl; + bool own_sda; } bitbangio_i2c_obj_t; diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 56e978985edcc..9b89d1d4a1b05 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -7,64 +7,66 @@ #include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" +#include "py/gc.h" #include "common-hal/microcontroller/Pin.h" #include "shared-bindings/bitbangio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" #include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/util.h" +#include "supervisor/port.h" #define MAX_BAUDRATE (common_hal_mcu_get_clock_frequency() / 48) void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, - const mcu_pin_obj_t *clock, const mcu_pin_obj_t *mosi, - const mcu_pin_obj_t *miso) { - digitalinout_result_t result = common_hal_digitalio_digitalinout_construct(&self->clock, clock); - if (result != DIGITALINOUT_OK) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_clock); - } - common_hal_digitalio_digitalinout_switch_to_output(&self->clock, self->polarity == 1, DRIVE_MODE_PUSH_PULL); + mp_obj_t clock, mp_obj_t mosi, mp_obj_t miso) { - if (mosi != NULL) { - result = common_hal_digitalio_digitalinout_construct(&self->mosi, mosi); - if (result != DIGITALINOUT_OK) { - common_hal_digitalio_digitalinout_deinit(&self->clock); - mp_raise_ValueError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_mosi); - } - self->has_mosi = true; - common_hal_digitalio_digitalinout_switch_to_output(&self->mosi, false, DRIVE_MODE_PUSH_PULL); - } + // Allocate the pins in the same place as self. + bool use_port_allocation = !gc_alloc_possible() || !gc_ptr_on_heap(self); - if (miso != NULL) { - // Starts out as input by default, no need to change. - result = common_hal_digitalio_digitalinout_construct(&self->miso, miso); - if (result != DIGITALINOUT_OK) { - common_hal_digitalio_digitalinout_deinit(&self->clock); - if (mosi != NULL) { - common_hal_digitalio_digitalinout_deinit(&self->mosi); - } - mp_raise_ValueError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_miso); - } - self->has_miso = true; + // Convert clock from Pin to DigitalInOutProtocol + self->clock = digitalinout_protocol_from_pin(clock, MP_QSTR_clock, false, use_port_allocation, &self->own_clock); + digitalinout_protocol_switch_to_output(self->clock, self->polarity == 1, DRIVE_MODE_PUSH_PULL); + + // Convert mosi from Pin to DigitalInOutProtocol (optional) + self->mosi = digitalinout_protocol_from_pin(mosi, MP_QSTR_mosi, true, use_port_allocation, &self->own_mosi); + self->has_mosi = (self->mosi != mp_const_none); + if (self->has_mosi) { + digitalinout_protocol_switch_to_output(self->mosi, false, DRIVE_MODE_PUSH_PULL); } + + // Convert miso from Pin to DigitalInOutProtocol (optional) + self->miso = digitalinout_protocol_from_pin(miso, MP_QSTR_miso, true, use_port_allocation, &self->own_miso); + self->has_miso = (self->miso != mp_const_none); + // MISO starts out as input by default, no need to change + self->delay_half = 5; self->polarity = 0; self->phase = 0; } bool shared_module_bitbangio_spi_deinited(bitbangio_spi_obj_t *self) { - return common_hal_digitalio_digitalinout_deinited(&self->clock); + return digitalinout_protocol_deinited(self->clock); } void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self) { if (shared_module_bitbangio_spi_deinited(self)) { return; } - common_hal_digitalio_digitalinout_deinit(&self->clock); - if (self->has_mosi) { - common_hal_digitalio_digitalinout_deinit(&self->mosi); + // Only deinit and free the pins if we own them + if (self->own_clock) { + digitalinout_protocol_deinit(self->clock); + circuitpy_free_obj(self->clock); + } + if (self->has_mosi && self->own_mosi) { + digitalinout_protocol_deinit(self->mosi); + circuitpy_free_obj(self->mosi); } - if (self->has_miso) { - common_hal_digitalio_digitalinout_deinit(&self->miso); + if (self->has_miso && self->own_miso) { + digitalinout_protocol_deinit(self->miso); + circuitpy_free_obj(self->miso); } } @@ -80,7 +82,7 @@ void shared_module_bitbangio_spi_configure(bitbangio_spi_obj_t *self, // If the polarity has changed, make sure we re-initialize the idle state // of the clock as well. self->polarity = polarity; - common_hal_digitalio_digitalinout_switch_to_output(&self->clock, polarity == 1, DRIVE_MODE_PUSH_PULL); + digitalinout_protocol_switch_to_output(self->clock, polarity == 1, DRIVE_MODE_PUSH_PULL); } self->phase = phase; } @@ -121,9 +123,15 @@ bool shared_module_bitbangio_spi_write(bitbangio_spi_obj_t *self, const uint8_t for (size_t i = 0; i < len; ++i) { uint8_t data_out = data[i]; for (int j = 0; j < 8; ++j, data_out <<= 1) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + if (i == 0 && j == 0) { + if (digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1) != 0) { + return false; + } + } else { + digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1); + } + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); } if (dest != NULL) { dest[i] = data_in; @@ -136,16 +144,22 @@ bool shared_module_bitbangio_spi_write(bitbangio_spi_obj_t *self, const uint8_t for (size_t i = 0; i < len; ++i) { uint8_t data_out = data[i]; for (int j = 0; j < 8; ++j, data_out <<= 1) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); + if (i == 0 && j == 0) { + if (!digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1)) { + return false; + } + } else { + digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1); + } if (self->phase == 0) { common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); } else { - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); common_hal_mcu_delay_us(delay_half); } } @@ -176,14 +190,18 @@ bool shared_module_bitbangio_spi_read(bitbangio_spi_obj_t *self, uint8_t *data, if (delay_half <= MICROPY_PY_MACHINE_SPI_MIN_DELAY) { // Clock out zeroes while we read. if (self->has_mosi) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, false); + if (digitalinout_protocol_set_value(self->mosi, false) != 0) { + return false; + } } for (size_t i = 0; i < len; ++i) { uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); - data_in = (data_in << 1) | common_hal_digitalio_digitalinout_get_value(&self->miso); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); + bool bit; + digitalinout_protocol_get_value(self->miso, &bit); + data_in = (data_in << 1) | bit; + digitalinout_protocol_set_value(self->clock, self->polarity); } data[i] = data_in; } @@ -191,28 +209,32 @@ bool shared_module_bitbangio_spi_read(bitbangio_spi_obj_t *self, uint8_t *data, } #endif if (self->has_mosi) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, false); + if (!digitalinout_protocol_set_value(self->mosi, false)) { + return false; + } } for (size_t i = 0; i < len; ++i) { uint8_t data_out = write_data; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { if (self->has_mosi) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); + digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1); } if (self->phase == 0) { common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); } else { - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); common_hal_mcu_delay_us(delay_half); } - data_in = (data_in << 1) | common_hal_digitalio_digitalinout_get_value(&self->miso); + bool bit; + digitalinout_protocol_get_value(self->miso, &bit); + data_in = (data_in << 1) | bit; if (self->phase == 0) { common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); } else { - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); common_hal_mcu_delay_us(delay_half); } } @@ -248,10 +270,18 @@ bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, const uint8 uint8_t data_out = dout[i]; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); - data_in = (data_in << 1) | common_hal_digitalio_digitalinout_get_value(&self->miso); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + if (i == 0 && j == 0) { + if (digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1) != 0) { + return false; + } + } else { + digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1); + } + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); + bool bit; + digitalinout_protocol_get_value(self->miso, &bit); + data_in = (data_in << 1) | bit; + digitalinout_protocol_set_value(self->clock, self->polarity); } din[i] = data_in; @@ -267,20 +297,28 @@ bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, const uint8 uint8_t data_out = dout[i]; uint8_t data_in = 0; for (int j = 0; j < 8; ++j, data_out <<= 1) { - common_hal_digitalio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); + if (i == 0 && j == 0) { + if (!digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1)) { + return false; + } + } else { + digitalinout_protocol_set_value(self->mosi, (data_out >> 7) & 1); + } if (self->phase == 0) { common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); } else { - common_hal_digitalio_digitalinout_set_value(&self->clock, 1 - self->polarity); + digitalinout_protocol_set_value(self->clock, 1 - self->polarity); common_hal_mcu_delay_us(delay_half); } - data_in = (data_in << 1) | common_hal_digitalio_digitalinout_get_value(&self->miso); + bool bit; + digitalinout_protocol_get_value(self->miso, &bit); + data_in = (data_in << 1) | bit; if (self->phase == 0) { common_hal_mcu_delay_us(delay_half); - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); } else { - common_hal_digitalio_digitalinout_set_value(&self->clock, self->polarity); + digitalinout_protocol_set_value(self->clock, self->polarity); common_hal_mcu_delay_us(delay_half); } } diff --git a/shared-module/bitbangio/SPI.h b/shared-module/bitbangio/SPI.h index c19170af7c46f..5f3c109b7f685 100644 --- a/shared-module/bitbangio/SPI.h +++ b/shared-module/bitbangio/SPI.h @@ -12,13 +12,16 @@ typedef struct { mp_obj_base_t base; - digitalio_digitalinout_obj_t clock; - digitalio_digitalinout_obj_t mosi; - digitalio_digitalinout_obj_t miso; + mp_obj_t clock; + mp_obj_t mosi; + mp_obj_t miso; uint32_t delay_half; bool has_miso : 1; bool has_mosi : 1; uint8_t polarity : 1; uint8_t phase : 1; volatile bool locked : 1; + bool own_clock; + bool own_mosi; + bool own_miso; } bitbangio_spi_obj_t; diff --git a/shared-module/bitmapfilter/__init__.c b/shared-module/bitmapfilter/__init__.c index cdce674628cd5..2a54ab7443b6c 100644 --- a/shared-module/bitmapfilter/__init__.c +++ b/shared-module/bitmapfilter/__init__.c @@ -21,7 +21,7 @@ #include #define port_free free #define port_malloc(sz, hint) (malloc(sz)) -#define port_realloc realloc +#define port_realloc(ptr, size, dma_capable) realloc(ptr, size) #else #include "supervisor/port_heap.h" #endif @@ -48,7 +48,7 @@ static void *scratchpad_alloc(size_t sz) { } else { if (scratchpad) { if (sz > scratchpad_size) { - void *tmp = port_realloc(scratchpad, sz); + void *tmp = port_realloc(scratchpad, sz, false); if (!tmp) { port_free(scratchpad); scratchpad = NULL; diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 8a41e387e513a..2f2b7aaf47583 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -204,6 +204,21 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 } } +void common_hal_bitmaptools_replace_color(displayio_bitmap_t *destination, + uint32_t old_color, + uint32_t new_color) { + + int16_t x, y; + for (x = 0; x < destination->width; x++) { + for (y = 0; y < destination->height; y++) { + uint32_t pixel_val = common_hal_displayio_bitmap_get_pixel(destination, x, y); + if (pixel_val == old_color) { + displayio_bitmap_write_pixel(destination, x, y, new_color); + } + } + } +} + void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, int16_t x1, int16_t y1, int16_t x2, int16_t y2, diff --git a/shared-module/board/__init__.c b/shared-module/board/__init__.c index 96735c8dbaa40..6bfc0bbf0f1d9 100644 --- a/shared-module/board/__init__.c +++ b/shared-module/board/__init__.c @@ -43,15 +43,6 @@ static const board_i2c_pin_t i2c_pin[CIRCUITPY_BOARD_I2C] = CIRCUITPY_BOARD_I2C_ static busio_i2c_obj_t i2c_obj[CIRCUITPY_BOARD_I2C]; static bool i2c_obj_created[CIRCUITPY_BOARD_I2C]; -bool common_hal_board_is_i2c(mp_obj_t obj) { - for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_I2C; instance++) { - if (obj == &i2c_obj[instance]) { - return true; - } - } - return false; -} - mp_obj_t common_hal_board_get_i2c(const mp_int_t instance) { return i2c_obj_created[instance] ? &i2c_obj[instance] : NULL; } @@ -89,15 +80,6 @@ static const board_spi_pin_t spi_pin[CIRCUITPY_BOARD_SPI] = CIRCUITPY_BOARD_SPI_ static busio_spi_obj_t spi_obj[CIRCUITPY_BOARD_SPI]; static bool spi_obj_created[CIRCUITPY_BOARD_SPI]; -bool common_hal_board_is_spi(mp_obj_t obj) { - for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_SPI; instance++) { - if (obj == &spi_obj[instance]) { - return true; - } - } - return false; -} - mp_obj_t common_hal_board_get_spi(const mp_int_t instance) { return spi_obj_created[instance] ? &spi_obj[instance] : NULL; } @@ -136,15 +118,6 @@ static const board_uart_pin_t uart_pin[CIRCUITPY_BOARD_UART] = CIRCUITPY_BOARD_U static busio_uart_obj_t uart_obj[CIRCUITPY_BOARD_UART]; static bool uart_obj_created[CIRCUITPY_BOARD_UART]; -bool common_hal_board_is_uart(mp_obj_t obj) { - for (uint8_t instance = 0; instance < CIRCUITPY_BOARD_UART; instance++) { - if (obj == &uart_obj[instance]) { - return true; - } - } - return false; -} - mp_obj_t common_hal_board_get_uart(const mp_int_t instance) { return uart_obj_created[instance] ? &uart_obj[instance] : NULL; } @@ -183,6 +156,10 @@ void reset_board_buses(void) { } } #endif + #if CIRCUITPY_I2CIOEXPANDER + // Assume the native I2C bus is used for IO Expander pins. + display_using_i2c = true; + #endif if (i2c_obj_created[instance]) { // make sure I2C lock is not held over a soft reset common_hal_busio_i2c_unlock(&i2c_obj[instance]); diff --git a/shared-module/busdisplay/BusDisplay.c b/shared-module/busdisplay/BusDisplay.c index 001f2f20c03e3..01e0f7a7896f0 100644 --- a/shared-module/busdisplay/BusDisplay.c +++ b/shared-module/busdisplay/BusDisplay.c @@ -6,6 +6,7 @@ #include "shared-bindings/busdisplay/BusDisplay.h" +#include "py/mphal.h" #include "py/runtime.h" #if CIRCUITPY_FOURWIRE #include "shared-bindings/fourwire/FourWire.h" @@ -16,6 +17,7 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#include "shared/runtime/interrupt_char.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -73,6 +75,9 @@ void common_hal_busdisplay_busdisplay_construct(busdisplay_busdisplay_obj_t *sel uint8_t *data = cmd + 2; while (!displayio_display_bus_begin_transaction(&self->bus)) { RUN_BACKGROUND_TASKS; + if (mp_hal_is_interrupted()) { + mp_raise_RuntimeError_varg(MP_ERROR_TEXT("%q init failed"), MP_QSTR_display); + } } if (self->bus.data_as_commands) { uint8_t full_command[data_size + 1]; @@ -80,7 +85,7 @@ void common_hal_busdisplay_busdisplay_construct(busdisplay_busdisplay_obj_t *sel memcpy(full_command + 1, data, data_size); self->bus.send(self->bus.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, full_command, data_size + 1); } else { - self->bus.send(self->bus.bus, DISPLAY_COMMAND, CHIP_SELECT_TOGGLE_EVERY_BYTE, cmd, 1); + self->bus.send(self->bus.bus, DISPLAY_COMMAND, data_size > 0 ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED, cmd, 1); self->bus.send(self->bus.bus, DISPLAY_DATA, CHIP_SELECT_UNTOUCHED, data, data_size); } displayio_display_bus_end_transaction(&self->bus); @@ -214,7 +219,7 @@ static void _send_pixels(busdisplay_busdisplay_obj_t *self, uint8_t *pixels, uin } static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_area_t *area) { - uint16_t buffer_size = 128; // In uint32_ts + uint16_t buffer_size = CIRCUITPY_DISPLAY_AREA_BUFFER_SIZE / sizeof(uint32_t); // In uint32_ts displayio_area_t clipped; // Clip the area to the display by overlapping the areas. If there is no overlap then we're done. @@ -256,9 +261,10 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are // Allocated and shared as a uint32_t array so the compiler knows the // alignment everywhere. - uint32_t buffer[buffer_size]; uint32_t mask_length = (pixels_per_buffer / 32) + 1; + uint32_t buffer[buffer_size]; uint32_t mask[mask_length]; + uint16_t remaining_rows = displayio_area_height(&clipped); for (uint16_t j = 0; j < subrectangles; j++) { @@ -273,8 +279,6 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are } remaining_rows -= rows_per_buffer; - displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle); - uint16_t subrectangle_size_bytes; if (self->core.colorspace.depth >= 8) { subrectangle_size_bytes = displayio_area_size(&subrectangle) * (self->core.colorspace.depth / 8); @@ -287,21 +291,28 @@ static bool _refresh_area(busdisplay_busdisplay_obj_t *self, const displayio_are displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); + displayio_display_bus_set_region_to_update(&self->bus, &self->core, &subrectangle); + // Can't acquire display bus; skip the rest of the data. - if (!displayio_display_bus_is_free(&self->bus)) { + if (!displayio_display_bus_begin_transaction(&self->bus)) { return false; } - - displayio_display_bus_begin_transaction(&self->bus); _send_pixels(self, (uint8_t *)buffer, subrectangle_size_bytes); displayio_display_bus_end_transaction(&self->bus); - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; + + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif } + + // Drain any remaining asynchronous transfers. + displayio_display_bus_flush(&self->bus); + return true; } @@ -310,7 +321,11 @@ static void _refresh_display(busdisplay_busdisplay_obj_t *self) { // A refresh on this bus is already in progress. Try next display. return; } - displayio_display_core_start_refresh(&self->core); + if (!displayio_display_core_start_refresh(&self->core)) { + // Refresh for this display already in progress. + return; + } + const displayio_area_t *current_area = _get_refresh_areas(self); while (current_area != NULL) { _refresh_area(self, current_area); diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index d5236f6b4f610..acc41b9eef642 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -31,7 +31,7 @@ void common_hal_displayio_bitmap_construct_from_buffer(displayio_bitmap_t *self, self->stride = stride(width, bits_per_value); self->data_alloc = false; if (!data) { - data = m_malloc(self->stride * height * sizeof(uint32_t)); + data = m_malloc_without_collect(self->stride * height * sizeof(uint32_t)); self->data_alloc = true; } self->data = data; diff --git a/shared-module/displayio/ColorConverter.c b/shared-module/displayio/ColorConverter.c index 512d45108ebe6..d4e64ee286eb8 100644 --- a/shared-module/displayio/ColorConverter.c +++ b/shared-module/displayio/ColorConverter.c @@ -91,6 +91,40 @@ uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888) { return hue; } +uint8_t displayio_colorconverter_compute_sixcolor(uint32_t color_rgb888) { + // This is DDX=1, the default for the displays. + uint8_t chroma = displayio_colorconverter_compute_chroma(color_rgb888); + if (chroma >= 64) { + uint8_t hue = displayio_colorconverter_compute_hue(color_rgb888); + // Red 0 + if (hue < 10) { + return 0x3; + } + // Yellow 42 + if (hue < 42 + 21) { + return 0x2; + } + // Green 85 + if (hue < 85 + 42) { + return 0x6; + } + // Blue 170 + if (hue < 170 + 42) { + return 0x5; + } + + // The rest is red to 255 + return 0x3; + } else { + uint8_t luma = displayio_colorconverter_compute_luma(color_rgb888); + if (luma >= 128) { + return 0x1; // White + } else { + return 0x0; // Black + } + } +} + uint8_t displayio_colorconverter_compute_sevencolor(uint32_t color_rgb888) { // This is DDX=1, the default for the displays. uint8_t chroma = displayio_colorconverter_compute_chroma(color_rgb888); @@ -129,8 +163,13 @@ uint8_t displayio_colorconverter_compute_sevencolor(uint32_t color_rgb888) { } } -void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_hue, uint32_t *color) { - +void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_chroma, uint8_t pixel_hue, uint32_t *color) { + if (pixel_chroma <= 16) { + if (!colorspace->grayscale) { + *color = 0; + } + return; + } int16_t hue_diff = colorspace->tricolor_hue - pixel_hue; if ((-10 <= hue_diff && hue_diff <= 10) || hue_diff <= -220 || hue_diff >= 220) { if (colorspace->grayscale) { @@ -143,6 +182,21 @@ void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *co } } +void displayio_colorconverter_compute_fourcolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_chroma, uint8_t pixel_hue, uint32_t *color) { + *color >>= 1; + if (pixel_chroma <= 16) { + return; + } + int16_t hue_diff = colorspace->tricolor_hue - pixel_hue; + if ((-10 <= hue_diff && hue_diff <= 10) || hue_diff <= -220 || hue_diff >= 220) { + *color = 2; + } + int16_t hue_diff2 = colorspace->fourcolor_hue - pixel_hue; + if ((-10 <= hue_diff2 && hue_diff2 <= 10) || hue_diff2 <= -220 || hue_diff2 >= 220) { + *color = 3; + } +} + void common_hal_displayio_colorconverter_convert(displayio_colorconverter_t *self, const _displayio_colorspace_t *colorspace, uint32_t input_color, uint32_t *output_color) { displayio_input_pixel_t input_pixel; input_pixel.pixel = input_color; @@ -197,9 +251,12 @@ uint32_t displayio_colorconverter_convert_pixel(displayio_colorspace_t colorspac pixel = __builtin_bswap16(pixel); MP_FALLTHROUGH; case DISPLAYIO_COLORSPACE_RGB555: { - uint32_t r8 = (pixel >> 10) << 3; - uint32_t g8 = ((pixel >> 5) << 3) & 0xff; - uint32_t b8 = (pixel << 3) & 0xff; + uint32_t r8 = (pixel >> 10) & 0x1f; + uint32_t g8 = (pixel >> 5) & 0x1f; + uint32_t b8 = pixel & 0x1f; + r8 = (r8 << 3) | ((r8 >> 2) & 0b111); + g8 = (g8 << 3) | ((g8 >> 2) & 0b111); + b8 = (b8 << 3) | ((b8 >> 2) & 0b111); pixel = (r8 << 16) | (g8 << 8) | b8; } break; @@ -219,9 +276,12 @@ uint32_t displayio_colorconverter_convert_pixel(displayio_colorspace_t colorspac pixel = __builtin_bswap16(pixel); MP_FALLTHROUGH; case DISPLAYIO_COLORSPACE_BGR555: { - uint32_t b8 = (pixel >> 10) << 3; - uint32_t g8 = ((pixel >> 5) << 3) & 0xff; - uint32_t r8 = (pixel << 3) & 0xff; + uint32_t b8 = (pixel >> 10) & 0x1f; + uint32_t g8 = (pixel >> 5) & 0x1f; + uint32_t r8 = pixel & 0x1f; + r8 = (r8 << 3) | ((r8 >> 2) & 0b111); + g8 = (g8 << 3) | ((g8 >> 2) & 0b111); + b8 = (b8 << 3) | ((b8 >> 2) & 0b111); pixel = (r8 << 16) | (g8 << 8) | b8; } break; @@ -273,18 +333,17 @@ void displayio_convert_color(const _displayio_colorspace_t *colorspace, bool dit output_color->pixel = packed; output_color->opaque = true; return; - } else if (colorspace->tricolor) { + } else if (colorspace->tricolor || colorspace->fourcolor) { uint8_t luma = displayio_colorconverter_compute_luma(pixel); + uint8_t pixel_chroma = displayio_colorconverter_compute_chroma(pixel); output_color->pixel = luma >> (8 - colorspace->depth); - if (displayio_colorconverter_compute_chroma(pixel) <= 16) { - if (!colorspace->grayscale) { - output_color->pixel = 0; - } - output_color->opaque = true; - return; - } uint8_t pixel_hue = displayio_colorconverter_compute_hue(pixel); - displayio_colorconverter_compute_tricolor(colorspace, pixel_hue, &output_color->pixel); + if (colorspace->tricolor) { + displayio_colorconverter_compute_tricolor(colorspace, pixel_chroma, pixel_hue, &output_color->pixel); + } else if (colorspace->fourcolor) { + displayio_colorconverter_compute_fourcolor(colorspace, pixel_chroma, pixel_hue, &output_color->pixel); + } + output_color->opaque = true; return; } else if (colorspace->grayscale && colorspace->depth <= 8) { uint8_t luma = displayio_colorconverter_compute_luma(pixel); @@ -292,7 +351,7 @@ void displayio_convert_color(const _displayio_colorspace_t *colorspace, bool dit output_color->pixel = (luma >> colorspace->grayscale_bit) & bitmask; output_color->opaque = true; return; - } else if (colorspace->depth == 32) { + } else if (colorspace->depth == 32 || colorspace->depth == 24) { output_color->pixel = pixel; output_color->opaque = true; return; @@ -303,7 +362,9 @@ void displayio_convert_color(const _displayio_colorspace_t *colorspace, bool dit return; } else if (colorspace->depth == 4) { uint8_t packed; - if (colorspace->sevencolor) { + if (colorspace->sixcolor) { + packed = displayio_colorconverter_compute_sixcolor(pixel); + } else if (colorspace->sevencolor) { packed = displayio_colorconverter_compute_sevencolor(pixel); } else { packed = displayio_colorconverter_compute_rgbd(pixel); diff --git a/shared-module/displayio/ColorConverter.h b/shared-module/displayio/ColorConverter.h index 60efc132f9ae5..304004d566a95 100644 --- a/shared-module/displayio/ColorConverter.h +++ b/shared-module/displayio/ColorConverter.h @@ -41,5 +41,7 @@ uint8_t displayio_colorconverter_compute_rgbd(uint32_t color_rgb888); uint8_t displayio_colorconverter_compute_luma(uint32_t color_rgb888); uint8_t displayio_colorconverter_compute_chroma(uint32_t color_rgb888); uint8_t displayio_colorconverter_compute_hue(uint32_t color_rgb888); +uint8_t displayio_colorconverter_compute_sixcolor(uint32_t color_rgb888); uint8_t displayio_colorconverter_compute_sevencolor(uint32_t color_rgb888); -void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_hue, uint32_t *color); +void displayio_colorconverter_compute_tricolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_chroma, uint8_t pixel_hue, uint32_t *color); +void displayio_colorconverter_compute_fourcolor(const _displayio_colorspace_t *colorspace, uint8_t pixel_chroma, uint8_t pixel_hue, uint32_t *color); diff --git a/shared-module/displayio/Group.c b/shared-module/displayio/Group.c index e2a1a527062b8..a2bf685d0f7c4 100644 --- a/shared-module/displayio/Group.c +++ b/shared-module/displayio/Group.c @@ -251,7 +251,11 @@ static void _add_layer(displayio_group_t *self, mp_obj_t layer) { #if CIRCUITPY_VECTORIO const vectorio_draw_protocol_t *draw_protocol = mp_proto_get(MP_QSTR_protocol_draw, layer); if (draw_protocol != NULL) { - draw_protocol->draw_protocol_impl->draw_update_transform(draw_protocol->draw_get_protocol_self(layer), &self->absolute_transform); + mp_obj_t protocol_self = draw_protocol->draw_get_protocol_self(layer); + if (draw_protocol->draw_protocol_impl->draw_set_in_group(protocol_self, true)) { + mp_raise_ValueError(MP_ERROR_TEXT("Layer already in a group")); + } + draw_protocol->draw_protocol_impl->draw_update_transform(protocol_self, &self->absolute_transform); return; } #endif @@ -296,6 +300,7 @@ static void _remove_layer(displayio_group_t *self, size_t index) { bool has_dirty_area = draw_protocol->draw_protocol_impl->draw_get_dirty_area(layer, &layer_area); rendered_last_frame = has_dirty_area; draw_protocol->draw_protocol_impl->draw_update_transform(layer, NULL); + draw_protocol->draw_protocol_impl->draw_set_in_group(layer, false); } #endif layer = mp_obj_cast_to_native_base( diff --git a/shared-module/displayio/OnDiskBitmap.c b/shared-module/displayio/OnDiskBitmap.c index 6777bd738a9e4..9abe8cf4fe1ed 100644 --- a/shared-module/displayio/OnDiskBitmap.c +++ b/shared-module/displayio/OnDiskBitmap.c @@ -1,6 +1,7 @@ // This file is part of the CircuitPython project: https://circuitpython.org // // SPDX-FileCopyrightText: Copyright (c) 2018 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 SamantazFox // // SPDX-License-Identifier: MIT @@ -15,6 +16,11 @@ #include "py/mperrno.h" #include "py/runtime.h" + +#define DISPLAYIO_ODBMP_DEBUG(...) (void)0 +// #define DISPLAYIO_ODBMP_DEBUG(...) mp_printf(&mp_plat_print __VA_OPT__(,) __VA_ARGS__) + + static uint32_t read_word(uint16_t *bmp_header, uint16_t index) { return bmp_header[index] | bmp_header[index + 1] << 16; } @@ -25,39 +31,63 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, uint16_t bmp_header[69]; f_rewind(&self->file->fp); UINT bytes_read; - if (f_read(&self->file->fp, bmp_header, 138, &bytes_read) != FR_OK) { + + // Read the minimum amount of bytes required to parse a BITMAPCOREHEADER. + // If needed, we will read more bytes down below. + if (f_read(&self->file->fp, bmp_header, 26, &bytes_read) != FR_OK) { mp_raise_OSError(MP_EIO); } - if (bytes_read != 138 || - memcmp(bmp_header, "BM", 2) != 0) { + DISPLAYIO_ODBMP_DEBUG("bytes_read: %d\n", bytes_read); + if (bytes_read != 26 || memcmp(bmp_header, "BM", 2) != 0) { mp_arg_error_invalid(MP_QSTR_file); } - // We can't cast because we're not aligned. - self->data_offset = read_word(bmp_header, 5); - + // Read header size to determine if more header bytes needs to be read. uint32_t header_size = read_word(bmp_header, 7); - uint16_t bits_per_pixel = bmp_header[14]; + DISPLAYIO_ODBMP_DEBUG("header_size: %d\n", header_size); + + if (header_size == 40 || header_size == 108 || header_size == 124) { + // Read the remaining header bytes + if (f_read(&self->file->fp, bmp_header + 13, header_size - 12, &bytes_read) != FR_OK) { + mp_raise_OSError(MP_EIO); + } + DISPLAYIO_ODBMP_DEBUG("bytes_read: %d\n", bytes_read); + if (bytes_read != (header_size - 12)) { + mp_arg_error_invalid(MP_QSTR_file); + } + } else if (header_size != 12) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Only Windows format, uncompressed BMP supported: given header size is %d"), header_size); + } + + uint32_t compression = read_word(bmp_header, 15); - uint32_t number_of_colors = read_word(bmp_header, 23); + DISPLAYIO_ODBMP_DEBUG("compression: %d\n", compression); // 0 is uncompressed; 3 is bitfield compressed. 1 and 2 are RLE compression. if (compression != 0 && compression != 3) { mp_raise_ValueError(MP_ERROR_TEXT("RLE-compressed BMP not supported")); } - bool indexed = bits_per_pixel <= 8; + // We can't cast because we're not aligned. + self->data_offset = read_word(bmp_header, 5); + self->bitfield_compressed = (compression == 3); - self->bits_per_pixel = bits_per_pixel; + self->bits_per_pixel = bmp_header[14]; self->width = read_word(bmp_header, 9); self->height = read_word(bmp_header, 11); + DISPLAYIO_ODBMP_DEBUG("data offset: %d\n", self->data_offset); + DISPLAYIO_ODBMP_DEBUG("width: %d\n", self->width); + DISPLAYIO_ODBMP_DEBUG("height: %d\n", self->height); + DISPLAYIO_ODBMP_DEBUG("bpp: %d\n", self->bits_per_pixel); + + displayio_colorconverter_t *colorconverter = mp_obj_malloc(displayio_colorconverter_t, &displayio_colorconverter_type); common_hal_displayio_colorconverter_construct(colorconverter, false, DISPLAYIO_COLORSPACE_RGB888); self->colorconverter = colorconverter; - if (bits_per_pixel == 16) { + if (self->bits_per_pixel == 16) { if (((header_size >= 56)) || (self->bitfield_compressed)) { self->r_bitmask = read_word(bmp_header, 27); self->g_bitmask = read_word(bmp_header, 29); @@ -68,9 +98,13 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, self->g_bitmask = 0x3e0; self->b_bitmask = 0x1f; } - } else if (indexed) { + } else if (self->bits_per_pixel <= 8) { // indexed + uint32_t number_of_colors = 0; + if (header_size >= 40) { + number_of_colors = read_word(bmp_header, 23); + } if (number_of_colors == 0) { - number_of_colors = 1 << bits_per_pixel; + number_of_colors = 1 << self->bits_per_pixel; } displayio_palette_t *palette = mp_obj_malloc(displayio_palette_t, &displayio_palette_type); @@ -80,7 +114,7 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, uint16_t palette_size = number_of_colors * sizeof(uint32_t); uint16_t palette_offset = 0xe + header_size; - uint32_t *palette_data = m_malloc(palette_size); + uint32_t *palette_data = m_malloc_without_collect(palette_size); f_rewind(&self->file->fp); f_lseek(&self->file->fp, palette_offset); @@ -95,19 +129,17 @@ void common_hal_displayio_ondiskbitmap_construct(displayio_ondiskbitmap_t *self, for (uint16_t i = 0; i < number_of_colors; i++) { common_hal_displayio_palette_set_color(palette, i, palette_data[i]); } + + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(palette_data, palette_size); + #else m_free(palette_data); + #endif } else { common_hal_displayio_palette_set_color(palette, 0, 0x0); common_hal_displayio_palette_set_color(palette, 1, 0xffffff); } self->palette = palette; - - } else if (!(header_size == 12 || header_size == 40 || header_size == 108 || header_size == 124)) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Only Windows format, uncompressed BMP supported: given header size is %d"), header_size); - } - - if (bits_per_pixel == 8 && number_of_colors == 0) { - mp_raise_ValueError_varg(MP_ERROR_TEXT("Only monochrome, indexed 4bpp or 8bpp, and 16bpp or greater BMPs supported: %d bpp given"), bits_per_pixel); } uint8_t bytes_per_pixel = (self->bits_per_pixel / 8) ? (self->bits_per_pixel / 8) : 1; diff --git a/shared-module/displayio/Palette.c b/shared-module/displayio/Palette.c index d80f1c47da171..968296c69f1d0 100644 --- a/shared-module/displayio/Palette.c +++ b/shared-module/displayio/Palette.c @@ -10,7 +10,7 @@ void common_hal_displayio_palette_construct(displayio_palette_t *self, uint16_t color_count, bool dither) { self->color_count = color_count; - self->colors = (_displayio_color_t *)m_malloc(color_count * sizeof(_displayio_color_t)); + self->colors = (_displayio_color_t *)m_malloc_without_collect(color_count * sizeof(_displayio_color_t)); self->dither = dither; } diff --git a/shared-module/displayio/Palette.h b/shared-module/displayio/Palette.h index 092b934b66a24..24ae5c4b7a525 100644 --- a/shared-module/displayio/Palette.h +++ b/shared-module/displayio/Palette.h @@ -15,10 +15,12 @@ typedef struct { uint8_t depth; uint8_t bytes_per_cell; uint8_t tricolor_hue; - uint8_t tricolor_luma; + uint8_t fourcolor_hue; uint8_t grayscale_bit; // The lowest grayscale bit. Normally 8 - depth. bool grayscale; bool tricolor; + bool fourcolor; + bool sixcolor; // Spectra6 e-ink screens. bool sevencolor; // Acep e-ink screens. bool pixels_in_byte_share_row; bool reverse_pixels_in_byte; diff --git a/shared-module/displayio/Shape.c b/shared-module/displayio/Shape.c deleted file mode 100644 index f36e9e32ac17d..0000000000000 --- a/shared-module/displayio/Shape.c +++ /dev/null @@ -1,126 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#include "shared-bindings/displayio/Shape.h" - -#include - -#include "py/runtime.h" -#include "py/misc.h" - -void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t width, - uint32_t height, bool mirror_x, bool mirror_y) { - self->mirror_x = mirror_x; - self->mirror_y = mirror_y; - self->width = width; - if (self->mirror_x) { - width /= 2; - width += self->width % 2; - } - self->half_width = width; - - self->height = height; - if (self->mirror_y) { - height /= 2; - height += self->height % 2; - } - self->half_height = height; - - self->data = m_malloc(height * sizeof(uint32_t)); - - for (uint16_t i = 0; i < height; i++) { - self->data[2 * i] = 0; - self->data[2 * i + 1] = width; - } - - self->dirty_area.x1 = 0; - self->dirty_area.x2 = width; - self->dirty_area.y1 = 0; - self->dirty_area.y2 = height; -} - -void common_hal_displayio_shape_set_boundary(displayio_shape_t *self, uint16_t y, uint16_t start_x, uint16_t end_x) { - uint16_t max_y = self->height - 1; - if (self->mirror_y) { - max_y = self->half_height - 1; - } - mp_arg_validate_int_range(y, 0, max_y, MP_QSTR_y); - uint16_t max_x = self->width - 1; - if (self->mirror_x) { - max_x = self->half_width - 1; - } - mp_arg_validate_int_range(start_x, 0, max_x, MP_QSTR_start_x); - mp_arg_validate_int_range(end_x, 0, max_x, MP_QSTR_end_x); - - uint16_t lower_x, upper_x, lower_y, upper_y; - - // find x-boundaries for updating based on current data and start_x, end_x, and mirror_x - lower_x = MIN(start_x, self->data[2 * y]); - - if (self->mirror_x) { - upper_x = self->width - lower_x + 1; // dirty rectangles are treated with max value exclusive - } else { - upper_x = MAX(end_x, self->data[2 * y + 1]) + 1; // dirty rectangles are treated with max value exclusive - } - - // find y-boundaries based on y and mirror_y - lower_y = y; - - if (self->mirror_y) { - upper_y = self->height - lower_y + 1; // dirty rectangles are treated with max value exclusive - } else { - upper_y = y + 1; // dirty rectangles are treated with max value exclusive - } - - self->data[2 * y] = start_x; // update the data array with the new boundaries - self->data[2 * y + 1] = end_x; - - if (self->dirty_area.x1 == self->dirty_area.x2) { // Dirty region is empty - self->dirty_area.x1 = lower_x; - self->dirty_area.x2 = upper_x; - self->dirty_area.y1 = lower_y; - self->dirty_area.y2 = upper_y; - - } else { // Dirty region is not empty - self->dirty_area.x1 = MIN(lower_x, self->dirty_area.x1); - self->dirty_area.x2 = MAX(upper_x, self->dirty_area.x2); - - self->dirty_area.y1 = MIN(lower_y, self->dirty_area.y1); - self->dirty_area.y2 = MAX(upper_y, self->dirty_area.y2); - } -} - -uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) { - displayio_shape_t *self = obj; - if (x >= self->width || x < 0 || y >= self->height || y < 0) { - return 0; - } - if (self->mirror_x && x >= self->half_width) { - x = self->width - x - 1; - } - if (self->mirror_y && y >= self->half_height) { - y = self->height - y - 1; - } - uint16_t start_x = self->data[2 * y]; - uint16_t end_x = self->data[2 * y + 1]; - if (x < start_x || x > end_x) { - return 0; - } - return 1; -} - -displayio_area_t *displayio_shape_get_refresh_areas(displayio_shape_t *self, displayio_area_t *tail) { - if (self->dirty_area.x1 == self->dirty_area.x2) { - return tail; - } - self->dirty_area.next = tail; - return &self->dirty_area; -} - -void displayio_shape_finish_refresh(displayio_shape_t *self) { - self->dirty_area.x1 = 0; - self->dirty_area.x2 = 0; -} diff --git a/shared-module/displayio/Shape.h b/shared-module/displayio/Shape.h deleted file mode 100644 index 20ee182023fe9..0000000000000 --- a/shared-module/displayio/Shape.h +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -#pragma once - -#include -#include - -#include "py/obj.h" -#include "shared-module/displayio/area.h" - -typedef struct { - mp_obj_base_t base; - uint16_t width; - uint16_t height; - uint16_t half_width; - uint16_t half_height; - uint16_t *data; - bool mirror_x; - bool mirror_y; - displayio_area_t dirty_area; -} displayio_shape_t; - -void displayio_shape_finish_refresh(displayio_shape_t *self); -displayio_area_t *displayio_shape_get_refresh_areas(displayio_shape_t *self, displayio_area_t *tail); diff --git a/shared-module/displayio/TileGrid.c b/shared-module/displayio/TileGrid.c index 137dc02250e03..b5c691ccbd6ce 100644 --- a/shared-module/displayio/TileGrid.c +++ b/shared-module/displayio/TileGrid.c @@ -11,30 +11,57 @@ #include "shared-bindings/displayio/ColorConverter.h" #include "shared-bindings/displayio/OnDiskBitmap.h" #include "shared-bindings/displayio/Palette.h" +#if CIRCUITPY_TILEPALETTEMAPPER +#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" +#endif + +#include "supervisor/shared/serial.h" void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_t bitmap, uint16_t bitmap_width_in_tiles, uint16_t bitmap_height_in_tiles, mp_obj_t pixel_shader, uint16_t width, uint16_t height, - uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint8_t default_tile) { + uint16_t tile_width, uint16_t tile_height, uint16_t x, uint16_t y, uint16_t default_tile) { + uint32_t total_tiles = width * height; + self->bitmap_width_in_tiles = bitmap_width_in_tiles; + self->tiles_in_bitmap = bitmap_width_in_tiles * bitmap_height_in_tiles; + + // Determine if we need uint16_t or uint8_t for tile indices + bool use_uint16 = self->tiles_in_bitmap > 255; + // Sprites will only have one tile so save a little memory by inlining values in the pointer. - uint8_t inline_tiles = sizeof(uint8_t *); + uint8_t inline_tiles = sizeof(void *) / (use_uint16 ? sizeof(uint16_t) : sizeof(uint8_t)); + if (total_tiles <= inline_tiles) { self->tiles = 0; // Pack values into the pointer since there are only a few. - for (uint32_t i = 0; i < inline_tiles; i++) { - ((uint8_t *)&self->tiles)[i] = default_tile; + if (use_uint16) { + for (uint32_t i = 0; i < inline_tiles && i < total_tiles; i++) { + ((uint16_t *)&self->tiles)[i] = default_tile; + } + } else { + for (uint32_t i = 0; i < inline_tiles && i < total_tiles; i++) { + ((uint8_t *)&self->tiles)[i] = (uint8_t)default_tile; + } } self->inline_tiles = true; } else { - self->tiles = (uint8_t *)m_malloc(total_tiles); - for (uint32_t i = 0; i < total_tiles; i++) { - self->tiles[i] = default_tile; + if (use_uint16) { + uint16_t *tiles16 = (uint16_t *)m_malloc_without_collect(total_tiles * sizeof(uint16_t)); + for (uint32_t i = 0; i < total_tiles; i++) { + tiles16[i] = default_tile; + } + self->tiles = tiles16; + } else { + uint8_t *tiles8 = (uint8_t *)m_malloc_without_collect(total_tiles); + for (uint32_t i = 0; i < total_tiles; i++) { + tiles8[i] = (uint8_t)default_tile; + } + self->tiles = tiles8; } self->inline_tiles = false; } - self->bitmap_width_in_tiles = bitmap_width_in_tiles; - self->tiles_in_bitmap = bitmap_width_in_tiles * bitmap_height_in_tiles; + self->width_in_tiles = width; self->height_in_tiles = height; self->x = x; @@ -54,6 +81,11 @@ void common_hal_displayio_tilegrid_construct(displayio_tilegrid_t *self, mp_obj_ self->flip_y = false; self->transpose_xy = false; self->absolute_transform = NULL; + #if CIRCUITPY_TILEPALETTEMAPPER + if (mp_obj_is_type(self->pixel_shader, &tilepalettemapper_tilepalettemapper_type)) { + tilepalettemapper_tilepalettemapper_bind(self->pixel_shader, self); + } + #endif } @@ -204,6 +236,11 @@ mp_obj_t common_hal_displayio_tilegrid_get_pixel_shader(displayio_tilegrid_t *se void common_hal_displayio_tilegrid_set_pixel_shader(displayio_tilegrid_t *self, mp_obj_t pixel_shader) { self->pixel_shader = pixel_shader; self->full_change = true; + #if CIRCUITPY_TILEPALETTEMAPPER + if (mp_obj_is_type(self->pixel_shader, &tilepalettemapper_tilepalettemapper_type)) { + tilepalettemapper_tilepalettemapper_bind(self->pixel_shader, self); + } + #endif } mp_obj_t common_hal_displayio_tilegrid_get_bitmap(displayio_tilegrid_t *self) { @@ -231,29 +268,24 @@ uint16_t common_hal_displayio_tilegrid_get_tile_height(displayio_tilegrid_t *sel return self->tile_height; } -uint8_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { - uint8_t *tiles = self->tiles; +uint16_t common_hal_displayio_tilegrid_get_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { + void *tiles = self->tiles; if (self->inline_tiles) { - tiles = (uint8_t *)&self->tiles; + tiles = &self->tiles; } if (tiles == NULL) { return 0; } - return tiles[y * self->width_in_tiles + x]; -} -void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint8_t tile_index) { - if (tile_index >= self->tiles_in_bitmap) { - mp_raise_ValueError(MP_ERROR_TEXT("Tile index out of bounds")); - } - uint8_t *tiles = self->tiles; - if (self->inline_tiles) { - tiles = (uint8_t *)&self->tiles; - } - if (tiles == NULL) { - return; + uint32_t index = y * self->width_in_tiles + x; + if (self->tiles_in_bitmap > 255) { + return ((uint16_t *)tiles)[index]; + } else { + return ((uint8_t *)tiles)[index]; } - tiles[y * self->width_in_tiles + x] = tile_index; +} + +void displayio_tilegrid_mark_tile_dirty(displayio_tilegrid_t *self, uint16_t x, uint16_t y) { displayio_area_t temp_area; displayio_area_t *tile_area; if (!self->partial_change) { @@ -277,25 +309,57 @@ void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t if (self->partial_change) { displayio_area_union(&self->dirty_area, &temp_area, &self->dirty_area); } - self->partial_change = true; } -void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint8_t tile_index) { +void common_hal_displayio_tilegrid_set_tile(displayio_tilegrid_t *self, uint16_t x, uint16_t y, uint16_t tile_index) { + if (tile_index >= self->tiles_in_bitmap) { + mp_raise_ValueError(MP_ERROR_TEXT("Tile index out of bounds")); + } + + void *tiles = self->tiles; + if (self->inline_tiles) { + tiles = &self->tiles; + } + if (tiles == NULL) { + return; + } + + uint32_t index = y * self->width_in_tiles + x; + if (self->tiles_in_bitmap > 255) { + ((uint16_t *)tiles)[index] = tile_index; + } else { + ((uint8_t *)tiles)[index] = (uint8_t)tile_index; + } + displayio_tilegrid_mark_tile_dirty(self, x, y); +} + +void common_hal_displayio_tilegrid_set_all_tiles(displayio_tilegrid_t *self, uint16_t tile_index) { if (tile_index >= self->tiles_in_bitmap) { mp_raise_ValueError(MP_ERROR_TEXT("Tile index out of bounds")); } - uint8_t *tiles = self->tiles; + + void *tiles = self->tiles; if (self->inline_tiles) { - tiles = (uint8_t *)&self->tiles; + tiles = &self->tiles; } if (tiles == NULL) { return; } - for (uint16_t x = 0; x < self->width_in_tiles; x++) { + if (self->tiles_in_bitmap > 255) { + uint16_t *tiles16 = (uint16_t *)tiles; for (uint16_t y = 0; y < self->height_in_tiles; y++) { - tiles[y * self->width_in_tiles + x] = tile_index; + for (uint16_t x = 0; x < self->width_in_tiles; x++) { + tiles16[y * self->width_in_tiles + x] = tile_index; + } + } + } else { + uint8_t *tiles8 = (uint8_t *)tiles; + for (uint16_t y = 0; y < self->height_in_tiles; y++) { + for (uint16_t x = 0; x < self->width_in_tiles; x++) { + tiles8[y * self->width_in_tiles + x] = (uint8_t)tile_index; + } } } @@ -365,9 +429,9 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, const _displayio_colorspace_t *colorspace, const displayio_area_t *area, uint32_t *mask, uint32_t *buffer) { // If no tiles are present we have no impact. - uint8_t *tiles = self->tiles; + void *tiles = self->tiles; if (self->inline_tiles) { - tiles = (uint8_t *)&self->tiles; + tiles = &self->tiles; } if (tiles == NULL) { return false; @@ -448,8 +512,6 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, y_shift = temp_shift; } - uint8_t pixels_per_byte = 8 / colorspace->depth; - displayio_input_pixel_t input_pixel; displayio_output_pixel_t output_pixel; @@ -470,8 +532,15 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, continue; } int16_t local_x = input_pixel.x / self->absolute_transform->scale; - uint16_t tile_location = ((local_y / self->tile_height + self->top_left_y) % self->height_in_tiles) * self->width_in_tiles + (local_x / self->tile_width + self->top_left_x) % self->width_in_tiles; - input_pixel.tile = tiles[tile_location]; + uint16_t x_tile_index = (local_x / self->tile_width + self->top_left_x) % self->width_in_tiles; + uint16_t y_tile_index = (local_y / self->tile_height + self->top_left_y) % self->height_in_tiles; + uint16_t tile_location = y_tile_index * self->width_in_tiles + x_tile_index; + + if (self->tiles_in_bitmap > 255) { + input_pixel.tile = ((uint16_t *)tiles)[tile_location]; + } else { + input_pixel.tile = ((uint8_t *)tiles)[tile_location]; + } input_pixel.tile_x = (input_pixel.tile % self->bitmap_width_in_tiles) * self->tile_width + local_x % self->tile_width; input_pixel.tile_y = (input_pixel.tile / self->bitmap_width_in_tiles) * self->tile_height + local_y % self->tile_height; @@ -487,6 +556,11 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, } output_pixel.opaque = true; + #if CIRCUITPY_TILEPALETTEMAPPER + if (mp_obj_is_type(self->pixel_shader, &tilepalettemapper_tilepalettemapper_type)) { + tilepalettemapper_tilepalettemapper_get_color(self->pixel_shader, colorspace, &input_pixel, &output_pixel, x_tile_index, y_tile_index); + } + #endif if (self->pixel_shader == mp_const_none) { output_pixel.pixel = input_pixel.pixel; } else if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { @@ -503,9 +577,13 @@ bool displayio_tilegrid_fill_area(displayio_tilegrid_t *self, *(((uint16_t *)buffer) + offset) = output_pixel.pixel; } else if (colorspace->depth == 32) { *(((uint32_t *)buffer) + offset) = output_pixel.pixel; + } else if (colorspace->depth == 24) { + memcpy(((uint8_t *)buffer) + offset * 3, &output_pixel.pixel, 3); } else if (colorspace->depth == 8) { *(((uint8_t *)buffer) + offset) = output_pixel.pixel; } else if (colorspace->depth < 8) { + uint8_t pixels_per_byte = 8 / colorspace->depth; + // Reorder the offsets to pack multiple rows into a byte (meaning they share a column). if (!colorspace->pixels_in_byte_share_row) { uint16_t width = displayio_area_width(area); @@ -601,6 +679,7 @@ displayio_area_t *displayio_tilegrid_get_refresh_areas(displayio_tilegrid_t *sel displayio_palette_needs_refresh(self->pixel_shader)) || (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type) && displayio_colorconverter_needs_refresh(self->pixel_shader)); + if (self->full_change || first_draw) { self->current_area.next = tail; return &self->current_area; diff --git a/shared-module/displayio/TileGrid.h b/shared-module/displayio/TileGrid.h index c9c31696bf8f2..0051cc0ebf19d 100644 --- a/shared-module/displayio/TileGrid.h +++ b/shared-module/displayio/TileGrid.h @@ -30,7 +30,7 @@ typedef struct { uint16_t tile_height; uint16_t top_left_x; uint16_t top_left_y; - uint8_t *tiles; + void *tiles; // Can be either uint8_t* or uint16_t* depending on tiles_in_bitmap const displayio_buffer_transform_t *absolute_transform; displayio_area_t dirty_area; // Stored as a relative area until the refresh area is fetched. displayio_area_t previous_area; // Stored as an absolute area. @@ -67,3 +67,6 @@ bool displayio_tilegrid_get_previous_area(displayio_tilegrid_t *self, displayio_ void displayio_tilegrid_finish_refresh(displayio_tilegrid_t *self); bool displayio_tilegrid_get_rendered_hidden(displayio_tilegrid_t *self); +void displayio_tilegrid_validate_pixel_shader(mp_obj_t pixel_shader); + +void displayio_tilegrid_mark_tile_dirty(displayio_tilegrid_t *self, uint16_t x, uint16_t y); diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 8b3c9556f4886..c1309ee09723d 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -10,8 +10,11 @@ #include "shared-bindings/displayio/__init__.h" #include "shared/runtime/interrupt_char.h" +#include "py/gc.h" #include "py/runtime.h" #include "shared-bindings/board/__init__.h" +#include "shared-bindings/busio/I2C.h" +#include "shared-bindings/busio/SPI.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/Palette.h" @@ -39,10 +42,20 @@ #include "shared-module/aurora_epaper/aurora_framebuffer.h" #endif +#if CIRCUITPY_MIPIDSI +#include "shared-bindings/mipidsi/Display.h" +#endif +#if CIRCUITPY_ZEPHYR_DISPLAY +#include "bindings/zephyr_display/Display.h" +#endif + #ifdef BOARD_USE_INTERNAL_SPI #include "supervisor/spi_flash_api.h" #endif +// The default indicates no primary display +static int primary_display_number = -1; + primary_display_bus_t display_buses[CIRCUITPY_DISPLAY_LIMIT]; primary_display_t displays[CIRCUITPY_DISPLAY_LIMIT]; @@ -59,7 +72,7 @@ displayio_buffer_transform_t null_transform = { .transpose_xy = false }; -#if CIRCUITPY_RGBMATRIX || CIRCUITPY_IS31FL3741 || CIRCUITPY_VIDEOCORE || CIRCUITPY_PICODVI +#if CIRCUITPY_RGBMATRIX || CIRCUITPY_IS31FL3741 || CIRCUITPY_VIDEOCORE || CIRCUITPY_PICODVI || CIRCUITPY_MIPIDSI static bool any_display_uses_this_framebuffer(mp_obj_base_t *obj) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { if (displays[i].display_base.type == &framebufferio_framebufferdisplay_type) { @@ -102,15 +115,25 @@ void displayio_background(void) { } else if (display_type == &epaperdisplay_epaperdisplay_type) { epaperdisplay_epaperdisplay_background(&displays[i].epaper_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_background(&displays[i].zephyr_display); + #endif } } } -void common_hal_displayio_release_displays(void) { +static void common_hal_displayio_release_displays_impl(bool keep_primary) { // Release displays before busses so that they can send any final commands to turn the display // off properly. + if (!keep_primary) { + primary_display_number = -1; + } for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + if (i == primary_display_number) { + continue; + } mp_const_obj_t display_type = displays[i].display_base.type; if (display_type == NULL || display_type == &mp_type_NoneType) { continue; @@ -126,10 +149,17 @@ void common_hal_displayio_release_displays(void) { } else if (display_type == &framebufferio_framebufferdisplay_type) { release_framebufferdisplay(&displays[i].framebuffer_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + release_zephyr_display(&displays[i].zephyr_display); + #endif } displays[i].display_base.type = &mp_type_NoneType; } for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + if (i == primary_display_number) { + continue; + } mp_const_obj_t bus_type = display_buses[i].bus_base.type; if (bus_type == NULL || bus_type == &mp_type_NoneType) { continue; @@ -169,18 +199,37 @@ void common_hal_displayio_release_displays(void) { } else if (bus_type == &picodvi_framebuffer_type) { common_hal_picodvi_framebuffer_deinit(&display_buses[i].picodvi); #endif + #if CIRCUITPY_MIPIDSI + } else if (bus_type == &mipidsi_display_type) { + common_hal_mipidsi_display_deinit(&display_buses[i].mipidsi); + #endif + #if CIRCUITPY_QSPIBUS + } else if (bus_type == &qspibus_qspibus_type) { + common_hal_qspibus_qspibus_deinit(&display_buses[i].qspi_bus); + #endif } display_buses[i].bus_base.type = &mp_type_NoneType; } - supervisor_stop_terminal(); + if (!keep_primary) { + supervisor_stop_terminal(); + } +} + +void common_hal_displayio_release_displays(void) { + common_hal_displayio_release_displays_impl(false); } void reset_displays(void) { + // TODO: In CircuitPython 11, uncomment the call. + // Release secondary displays. + // common_hal_displayio_release_displays_impl(/*keep_primary*/ true); + // The SPI buses used by FourWires may be allocated on the heap so we need to move them inline. for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { mp_const_obj_t display_bus_type = display_buses[i].bus_base.type; if (display_bus_type == NULL || display_bus_type == &mp_type_NoneType) { + display_buses[i].bus_base.type = &mp_type_NoneType; continue; #if CIRCUITPY_FOURWIRE } else if (display_bus_type == &fourwire_fourwire_type) { @@ -188,21 +237,12 @@ void reset_displays(void) { if (((size_t)fourwire->bus) < ((size_t)&display_buses) || ((size_t)fourwire->bus) > ((size_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT * sizeof(primary_display_bus_t))) { busio_spi_obj_t *original_spi = fourwire->bus; - #if CIRCUITPY_BOARD_SPI - // We don't need to move original_spi if it is a board.SPI object because it is - // statically allocated already. (Doing so would also make it impossible to reference in - // a subsequent VM run.) - if (common_hal_board_is_spi(original_spi)) { + if (!gc_ptr_on_heap(original_spi)) { continue; } - #endif - #ifdef BOARD_USE_INTERNAL_SPI - if (original_spi == (mp_obj_t)(&supervisor_flash_spi_bus)) { - continue; - } - #endif memcpy(&fourwire->inline_bus, original_spi, sizeof(busio_spi_obj_t)); fourwire->bus = &fourwire->inline_bus; + // Check for other display buses that use the same spi bus and swap them too. for (uint8_t j = i + 1; j < CIRCUITPY_DISPLAY_LIMIT; j++) { if (display_buses[j].fourwire_bus.base.type == &fourwire_fourwire_type && @@ -210,6 +250,8 @@ void reset_displays(void) { display_buses[j].fourwire_bus.bus = &fourwire->inline_bus; } } + // Mark the old SPI object so it is considered deinit. + common_hal_busio_spi_mark_deinit(original_spi); } #endif #if CIRCUITPY_I2CDISPLAYBUS @@ -219,14 +261,9 @@ void reset_displays(void) { if (((size_t)i2c->bus) < ((size_t)&display_buses) || ((size_t)i2c->bus) > ((size_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT * sizeof(primary_display_bus_t))) { busio_i2c_obj_t *original_i2c = i2c->bus; - #if CIRCUITPY_BOARD_I2C - // We don't need to move original_i2c if it is a board.I2C object because it is - // statically allocated already. (Doing so would also make it impossible to reference in - // a subsequent VM run.) - if (common_hal_board_is_i2c(original_i2c)) { + if (!gc_ptr_on_heap(original_i2c)) { continue; } - #endif memcpy(&i2c->inline_bus, original_i2c, sizeof(busio_i2c_obj_t)); i2c->bus = &i2c->inline_bus; // Check for other displays that use the same i2c bus and swap them too. @@ -236,6 +273,8 @@ void reset_displays(void) { display_buses[j].i2cdisplay_bus.bus = &i2c->inline_bus; } } + // Mark the old i2c object so it is considered deinit. + common_hal_busio_i2c_mark_deinit(original_i2c); } #endif #if CIRCUITPY_RGBMATRIX @@ -253,22 +292,17 @@ void reset_displays(void) { if (((uint32_t)is31fb->is31fl3741->i2c) < ((uint32_t)&display_buses) || ((uint32_t)is31fb->is31fl3741->i2c) > ((uint32_t)&display_buses + CIRCUITPY_DISPLAY_LIMIT)) { - #if CIRCUITPY_BOARD_I2C - // We don't need to move original_i2c if it is the board.I2C object because it is - // statically allocated already. (Doing so would also make it impossible to reference in - // a subsequent VM run.) - if (common_hal_board_is_i2c(is31fb->is31fl3741->i2c)) { - continue; - } - #endif - is31fl3741_IS31FL3741_obj_t *original_is31 = is31fb->is31fl3741; - memcpy(&is31fb->inline_is31fl3741, original_is31, sizeof(is31fl3741_IS31FL3741_obj_t)); - is31fb->is31fl3741 = &is31fb->inline_is31fl3741; + if (gc_ptr_on_heap(original_is31)) { + memcpy(&is31fb->inline_is31fl3741, original_is31, sizeof(is31fl3741_IS31FL3741_obj_t)); + is31fb->is31fl3741 = &is31fb->inline_is31fl3741; + } busio_i2c_obj_t *original_i2c = is31fb->is31fl3741->i2c; - memcpy(&is31fb->is31fl3741->inline_i2c, original_i2c, sizeof(busio_i2c_obj_t)); - is31fb->is31fl3741->i2c = &is31fb->is31fl3741->inline_i2c; + if (gc_ptr_on_heap(original_i2c)) { + memcpy(&is31fb->is31fl3741->inline_i2c, original_i2c, sizeof(busio_i2c_obj_t)); + is31fb->is31fl3741->i2c = &is31fb->is31fl3741->inline_i2c; + } } if (!any_display_uses_this_framebuffer(&is31fb->base)) { @@ -300,15 +334,20 @@ void reset_displays(void) { #endif #if CIRCUITPY_AURORA_EPAPER } else if (display_bus_type == &aurora_framebuffer_type) { - #if CIRCUITPY_BOARD_SPI aurora_epaper_framebuffer_obj_t *aurora = &display_buses[i].aurora_epaper; - if (common_hal_board_is_spi(aurora->bus)) { + if (gc_ptr_on_heap(aurora->bus)) { common_hal_aurora_epaper_framebuffer_set_free_bus(false); } - #endif // Set to None, gets deinit'd up by display_base display_buses[i].bus_base.type = &mp_type_NoneType; #endif + #if CIRCUITPY_MIPIDSI + } else if (display_bus_type == &mipidsi_display_type) { + mipidsi_display_obj_t *display = &display_buses[i].mipidsi; + if (!any_display_uses_this_framebuffer(&display->base)) { + common_hal_mipidsi_display_deinit(display); + } + #endif } else { // Not an active display bus. continue; @@ -334,6 +373,10 @@ void reset_displays(void) { } else if (display_type == &framebufferio_framebufferdisplay_type) { framebufferio_framebufferdisplay_reset(&displays[i].framebuffer_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_reset(&displays[i].zephyr_display); + #endif } } } @@ -385,14 +428,21 @@ void displayio_gc_collect(void) { } else if (display_type == &epaperdisplay_epaperdisplay_type) { epaperdisplay_epaperdisplay_collect_ptrs(&displays[i].epaper_display); #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + } else if (display_type == &zephyr_display_display_type) { + zephyr_display_display_collect_ptrs(&displays[i].zephyr_display); + #endif } } } +static bool is_display_active(mp_obj_base_t *display_maybe) { + return display_maybe->type != &mp_type_NoneType && display_maybe->type != NULL; +} + primary_display_t *allocate_display(void) { for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { - mp_const_obj_t display_type = displays[i].display_base.type; - if (display_type == NULL || display_type == &mp_type_NoneType) { + if (!is_display_active(&displays[i].display_base)) { // Clear this memory so it is in a known state before init. memset(&displays[i], 0, sizeof(displays[i])); // Default to None so that it works as board.DISPLAY. @@ -431,3 +481,42 @@ primary_display_bus_t *allocate_display_bus_or_raise(void) { } mp_raise_RuntimeError(MP_ERROR_TEXT("Too many display busses; forgot displayio.release_displays() ?")); } + +mp_obj_t common_hal_displayio_get_primary_display(void) { + if (primary_display_number == -1 || primary_display_number >= CIRCUITPY_DISPLAY_LIMIT) { + return mp_const_none; + } + mp_obj_base_t *primary_display = &displays[primary_display_number].display_base; + if (is_display_active(primary_display)) { + return MP_OBJ_FROM_PTR(primary_display); + } + return mp_const_none; +} + +void common_hal_displayio_set_primary_display(mp_obj_t new_primary_display) { + if (new_primary_display == mp_const_none) { + primary_display_number = -1; + return; + } + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + mp_obj_t display = MP_OBJ_FROM_PTR(&displays[i]); + if (new_primary_display == display && is_display_active(display)) { + primary_display_number = i; + return; + } + } + // object was not a display after all... + mp_raise_TypeError_varg(MP_ERROR_TEXT("%q must be of type %q or %q, not %q"), MP_QSTR_Display, MP_QSTR_AnyDisplay, MP_QSTR_None, mp_obj_get_type(new_primary_display)->name); +} + +void common_hal_displayio_auto_primary_display(void) { + if (primary_display_number != -1) { + return; + } + for (uint8_t i = 0; i < CIRCUITPY_DISPLAY_LIMIT; i++) { + if (is_display_active(&displays[i].display_base)) { + primary_display_number = i; + return; + } + } +} diff --git a/shared-module/displayio/__init__.h b/shared-module/displayio/__init__.h index 29b8c64c97240..eabff662782af 100644 --- a/shared-module/displayio/__init__.h +++ b/shared-module/displayio/__init__.h @@ -38,6 +38,15 @@ #if CIRCUITPY_DOTCLOCKFRAMEBUFFER #include "common-hal/dotclockframebuffer/DotClockFramebuffer.h" #endif +#if CIRCUITPY_MIPIDSI +#include "shared-bindings/mipidsi/Display.h" +#endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif +#if CIRCUITPY_ZEPHYR_DISPLAY +#include "bindings/zephyr_display/Display.h" +#endif // Port unique frame buffers. #if CIRCUITPY_VIDEOCORE #include "bindings/videocore/Framebuffer.h" @@ -81,6 +90,12 @@ typedef struct { #if CIRCUITPY_AURORA_EPAPER aurora_epaper_framebuffer_obj_t aurora_epaper; #endif + #if CIRCUITPY_MIPIDSI + mipidsi_display_obj_t mipidsi; + #endif + #if CIRCUITPY_QSPIBUS + qspibus_qspibus_obj_t qspi_bus; + #endif }; } primary_display_bus_t; @@ -96,6 +111,9 @@ typedef struct { #if CIRCUITPY_FRAMEBUFFERIO framebufferio_framebufferdisplay_obj_t framebuffer_display; #endif + #if CIRCUITPY_ZEPHYR_DISPLAY + zephyr_display_display_obj_t zephyr_display; + #endif }; } primary_display_t; diff --git a/shared-module/displayio/bus_core.c b/shared-module/displayio/bus_core.c index c945a342cf89a..9b3fb426217e1 100644 --- a/shared-module/displayio/bus_core.c +++ b/shared-module/displayio/bus_core.c @@ -17,6 +17,9 @@ #if CIRCUITPY_PARALLELDISPLAYBUS #include "shared-bindings/paralleldisplaybus/ParallelBus.h" #endif +#if CIRCUITPY_QSPIBUS +#include "shared-bindings/qspibus/QSPIBus.h" +#endif #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/time/__init__.h" #include "shared-module/displayio/__init__.h" @@ -49,6 +52,8 @@ void displayio_display_bus_construct(displayio_display_bus_t *self, self->SH1107_addressing = SH1107_addressing; self->address_little_endian = address_little_endian; + self->flush = NULL; + #if CIRCUITPY_PARALLELDISPLAYBUS if (mp_obj_is_type(bus, ¶lleldisplaybus_parallelbus_type)) { self->bus_reset = common_hal_paralleldisplaybus_parallelbus_reset; @@ -79,17 +84,37 @@ void displayio_display_bus_construct(displayio_display_bus_t *self, self->collect_ptrs = common_hal_i2cdisplaybus_i2cdisplaybus_collect_ptrs; } else #endif + #if CIRCUITPY_QSPIBUS + if (mp_obj_is_type(bus, &qspibus_qspibus_type)) { + self->bus_reset = common_hal_qspibus_qspibus_reset; + self->bus_free = common_hal_qspibus_qspibus_bus_free; + self->begin_transaction = common_hal_qspibus_qspibus_begin_transaction; + self->send = common_hal_qspibus_qspibus_send; + self->end_transaction = common_hal_qspibus_qspibus_end_transaction; + self->flush = common_hal_qspibus_qspibus_flush; + self->collect_ptrs = common_hal_qspibus_qspibus_collect_ptrs; + } else + #endif { mp_raise_ValueError(MP_ERROR_TEXT("Unsupported display bus type")); } self->bus = bus; } +// This is just a hint, and is not a reliable result, since the bus could be grabbed in between this called +// and the attempt to use the bus. Use displayio_display_bus_begin_transaction(), which is atomic. bool displayio_display_bus_is_free(displayio_display_bus_t *self) { return !self->bus || self->bus_free(self->bus); } -bool displayio_display_bus_begin_transaction(displayio_display_bus_t *self) { +MP_WARN_UNUSED_RESULT bool displayio_display_bus_begin_transaction(displayio_display_bus_t *self) { + if (!self->bus) { + return false; + } + mp_obj_base_t *bus_base = MP_OBJ_TO_PTR(self->bus); + if (bus_base->type == &mp_type_NoneType) { + return false; + } return self->begin_transaction(self->bus); } @@ -124,7 +149,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d } // Set column. - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } uint8_t data[5]; data[0] = self->column_command; uint8_t data_length = 1; @@ -163,7 +190,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d if (self->set_current_column_command != NO_COMMAND) { uint8_t command = self->set_current_column_command; - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); // Only send the first half of data because it is the first coordinate. self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); @@ -172,7 +201,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d // Set row. - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } data[0] = self->row_command; data_length = 1; if (!self->data_as_commands) { @@ -207,7 +238,9 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d if (self->set_current_row_command != NO_COMMAND) { uint8_t command = self->set_current_row_command; - displayio_display_bus_begin_transaction(self); + if (!displayio_display_bus_begin_transaction(self)) { + return; + } self->send(self->bus, DISPLAY_COMMAND, chip_select, &command, 1); // Only send the first half of data because it is the first coordinate. self->send(self->bus, DISPLAY_DATA, chip_select, data, data_length / 2); @@ -215,6 +248,12 @@ void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, d } } +void displayio_display_bus_flush(displayio_display_bus_t *self) { + if (self->flush != NULL) { + self->flush(self->bus); + } +} + void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self) { self->collect_ptrs(self->bus); } diff --git a/shared-module/displayio/bus_core.h b/shared-module/displayio/bus_core.h index 838454c92e6d8..75d03d7f28430 100644 --- a/shared-module/displayio/bus_core.h +++ b/shared-module/displayio/bus_core.h @@ -21,6 +21,7 @@ typedef struct { display_bus_begin_transaction begin_transaction; display_bus_send send; display_bus_end_transaction end_transaction; + display_bus_flush flush; display_bus_collect_ptrs collect_ptrs; uint16_t ram_width; uint16_t ram_height; @@ -49,6 +50,10 @@ void displayio_display_bus_end_transaction(displayio_display_bus_t *self); void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area); +// Drain any pending asynchronous transfers on the bus. +// No-op for synchronous buses (FourWire, I2C, ParallelBus). +void displayio_display_bus_flush(displayio_display_bus_t *self); + void release_display_bus(displayio_display_bus_t *self); void displayio_display_bus_collect_ptrs(displayio_display_bus_t *self); diff --git a/shared-module/epaperdisplay/EPaperDisplay.c b/shared-module/epaperdisplay/EPaperDisplay.c index 9f43195b8cf53..d34be9d5c7c0a 100644 --- a/shared-module/epaperdisplay/EPaperDisplay.c +++ b/shared-module/epaperdisplay/EPaperDisplay.c @@ -26,70 +26,73 @@ #define DELAY 0x80 void common_hal_epaperdisplay_epaperdisplay_construct(epaperdisplay_epaperdisplay_obj_t *self, - mp_obj_t bus, const uint8_t *start_sequence, uint16_t start_sequence_len, mp_float_t start_up_time, - const uint8_t *stop_sequence, uint16_t stop_sequence_len, - uint16_t width, uint16_t height, uint16_t ram_width, uint16_t ram_height, - int16_t colstart, int16_t rowstart, uint16_t rotation, - uint16_t set_column_window_command, uint16_t set_row_window_command, - uint16_t set_current_column_command, uint16_t set_current_row_command, - uint16_t write_black_ram_command, bool black_bits_inverted, - uint16_t write_color_ram_command, bool color_bits_inverted, uint32_t highlight_color, - const uint8_t *refresh_sequence, uint16_t refresh_sequence_len, mp_float_t refresh_time, - const mcu_pin_obj_t *busy_pin, bool busy_state, mp_float_t seconds_per_frame, - bool chip_select, bool grayscale, bool acep, bool two_byte_sequence_length, bool address_little_endian) { + const epaperdisplay_construct_args_t *args) { uint16_t color_depth = 1; bool core_grayscale = true; - if (highlight_color != 0x000000) { + if (args->highlight_color != 0x000000) { self->core.colorspace.tricolor = true; - self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(highlight_color); - self->core.colorspace.tricolor_luma = displayio_colorconverter_compute_luma(highlight_color); + self->core.colorspace.tricolor_hue = displayio_colorconverter_compute_hue(args->highlight_color); } else { self->core.colorspace.tricolor = false; } - self->acep = acep; - self->core.colorspace.sevencolor = acep; - if (acep) { + if (args->highlight_color != 0x000000 && args->highlight_color2 != 0x000000) { + self->core.colorspace.tricolor = false; + self->core.colorspace.fourcolor = true; + self->core.colorspace.fourcolor_hue = displayio_colorconverter_compute_hue(args->highlight_color2); + } else { + self->core.colorspace.fourcolor = false; + } + self->acep = args->acep || args->spectra6; + self->core.colorspace.sixcolor = args->spectra6; + self->core.colorspace.sevencolor = args->acep; + bool grayscale = args->grayscale; + if (self->acep) { color_depth = 4; // bits. 7 colors + clean grayscale = false; core_grayscale = false; } + if ((args->highlight_color != 0x000000 || args->highlight_color2 != 0x000000) && args->write_color_ram_command == NO_COMMAND) { + color_depth = 2; + core_grayscale = false; + grayscale = false; + } - displayio_display_core_construct(&self->core, width, height, rotation, color_depth, core_grayscale, true, 1, true, true); - displayio_display_bus_construct(&self->bus, bus, ram_width, ram_height, - colstart, rowstart, - set_column_window_command, set_row_window_command, set_current_column_command, set_current_row_command, - false /* data_as_commands */, chip_select, - false /* SH1107_addressing */, address_little_endian); + displayio_display_core_construct(&self->core, args->width, args->height, args->rotation, color_depth, core_grayscale, true, 1, true, true); + displayio_display_bus_construct(&self->bus, args->bus, args->ram_width, args->ram_height, + args->colstart, args->rowstart, + args->set_column_window_command, args->set_row_window_command, args->set_current_column_command, args->set_current_row_command, + false /* data_as_commands */, args->always_toggle_chip_select, + false /* SH1107_addressing */, args->address_little_endian); - self->write_black_ram_command = write_black_ram_command; - self->black_bits_inverted = black_bits_inverted; - self->write_color_ram_command = write_color_ram_command; - self->color_bits_inverted = color_bits_inverted; - self->refresh_time = refresh_time * 1000; - self->busy_state = busy_state; + self->write_black_ram_command = args->write_black_ram_command; + self->black_bits_inverted = args->black_bits_inverted; + self->write_color_ram_command = args->write_color_ram_command; + self->color_bits_inverted = args->color_bits_inverted; + self->refresh_time = args->refresh_time * 1000; + self->busy_state = args->busy_state; self->refreshing = false; - self->milliseconds_per_frame = seconds_per_frame * 1000; - self->chip_select = chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; + self->milliseconds_per_frame = args->seconds_per_frame * 1000; + self->chip_select = args->always_toggle_chip_select ? CHIP_SELECT_TOGGLE_EVERY_BYTE : CHIP_SELECT_UNTOUCHED; self->grayscale = grayscale; - self->start_sequence = start_sequence; - self->start_sequence_len = start_sequence_len; - self->start_up_time_ms = start_up_time * 1000; - self->stop_sequence = stop_sequence; - self->stop_sequence_len = stop_sequence_len; - self->refresh_sequence = refresh_sequence; - self->refresh_sequence_len = refresh_sequence_len; + self->start_sequence = args->start_sequence; + self->start_sequence_len = args->start_sequence_len; + self->start_up_time_ms = args->start_up_time * 1000; + self->stop_sequence = args->stop_sequence; + self->stop_sequence_len = args->stop_sequence_len; + self->refresh_sequence = args->refresh_sequence; + self->refresh_sequence_len = args->refresh_sequence_len; self->busy.base.type = &mp_type_NoneType; - self->two_byte_sequence_length = two_byte_sequence_length; - if (busy_pin != NULL) { + self->two_byte_sequence_length = args->two_byte_sequence_length; + if (args->busy_pin != NULL) { self->busy.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->busy, busy_pin); - common_hal_never_reset_pin(busy_pin); + common_hal_digitalio_digitalinout_construct(&self->busy, args->busy_pin); + common_hal_never_reset_pin(args->busy_pin); } // Clear the color memory if it isn't in use. - if (highlight_color == 0x00 && write_color_ram_command != NO_COMMAND) { + if (args->highlight_color == 0x00 && args->highlight_color2 == 0x00 && args->write_color_ram_command != NO_COMMAND) { // TODO: Clear } @@ -150,14 +153,17 @@ static void send_command_sequence(epaperdisplay_epaperdisplay_obj_t *self, data_size = ((data_size & ~DELAY) << 8) + *(cmd + 2); data = cmd + 3; } - displayio_display_bus_begin_transaction(&self->bus); + while (!displayio_display_bus_begin_transaction(&self->bus) && + !mp_hal_is_interrupted()) { + RUN_BACKGROUND_TASKS; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, cmd, 1); self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, data, data_size); displayio_display_bus_end_transaction(&self->bus); uint16_t delay_length_ms = 0; if (delay) { data_size++; - delay_length_ms = *(cmd + 1 + data_size); + delay_length_ms = *(cmd + 1 + data_size + self->two_byte_sequence_length); if (delay_length_ms == 255) { delay_length_ms = 500; } @@ -188,6 +194,10 @@ static void epaperdisplay_epaperdisplay_start_refresh(epaperdisplay_epaperdispla // Can't acquire display bus; skip updating this display. Try next display. return; } + if (!displayio_display_core_start_refresh(&self->core)) { + // Refresh on this display already in progress. + return; + } // run start sequence self->bus.bus_reset(self->bus.bus); @@ -198,7 +208,6 @@ static void epaperdisplay_epaperdisplay_start_refresh(epaperdisplay_epaperdispla if (mp_hal_is_interrupted()) { return; } - displayio_display_core_start_refresh(&self->core); } uint32_t common_hal_epaperdisplay_epaperdisplay_get_time_to_refresh(epaperdisplay_epaperdisplay_obj_t *self) { @@ -305,7 +314,10 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay if (pass == 1) { write_command = self->write_color_ram_command; } - displayio_display_bus_begin_transaction(&self->bus); + if (!displayio_display_bus_begin_transaction(&self->bus)) { + // Display bus not available now. + return false; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1); displayio_display_bus_end_transaction(&self->bus); @@ -338,7 +350,7 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay } else if (self->core.colorspace.tricolor) { self->core.colorspace.grayscale = false; displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); - } else if (self->core.colorspace.sevencolor) { + } else if (self->core.colorspace.sixcolor || self->core.colorspace.sevencolor) { displayio_display_core_fill_area(&self->core, &subrectangle, mask, buffer); } } else { @@ -360,8 +372,11 @@ static bool epaperdisplay_epaperdisplay_refresh_area(epaperdisplay_epaperdisplay self->bus.send(self->bus.bus, DISPLAY_DATA, self->chip_select, (uint8_t *)buffer, subrectangle_size_bytes); displayio_display_bus_end_transaction(&self->bus); - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; + + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif @@ -379,7 +394,9 @@ static bool _clean_area(epaperdisplay_epaperdisplay_obj_t *self) { memset(buffer, 0x77, width / 2); uint8_t write_command = self->write_black_ram_command; - displayio_display_bus_begin_transaction(&self->bus); + if (displayio_display_bus_begin_transaction(&self->bus)) { + return false; + } self->bus.send(self->bus.bus, DISPLAY_COMMAND, self->chip_select, &write_command, 1); displayio_display_bus_end_transaction(&self->bus); diff --git a/shared-module/fontio/BuiltinFont.c b/shared-module/fontio/BuiltinFont.c index e24fe9c7f3733..03ef933c55c2f 100644 --- a/shared-module/fontio/BuiltinFont.c +++ b/shared-module/fontio/BuiltinFont.c @@ -16,7 +16,8 @@ mp_obj_t common_hal_fontio_builtinfont_get_bitmap(const fontio_builtinfont_t *se } mp_obj_t common_hal_fontio_builtinfont_get_bounding_box(const fontio_builtinfont_t *self) { - mp_obj_t *items = m_new(mp_obj_t, 2); + // Stack allocation is ok because tuple copies the values out. + mp_obj_t items[2]; items[0] = MP_OBJ_NEW_SMALL_INT(self->width); items[1] = MP_OBJ_NEW_SMALL_INT(self->height); return mp_obj_new_tuple(2, items); diff --git a/shared-module/fourwire/FourWire.c b/shared-module/fourwire/FourWire.c index 0a168fa1563fc..d87cb0cec0f95 100644 --- a/shared-module/fourwire/FourWire.c +++ b/shared-module/fourwire/FourWire.c @@ -11,13 +11,15 @@ #include "py/gc.h" #include "shared-bindings/busio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOutProtocol.h" #include "shared-bindings/microcontroller/Pin.h" #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/time/__init__.h" +#include "supervisor/port.h" void common_hal_fourwire_fourwire_construct(fourwire_fourwire_obj_t *self, - busio_spi_obj_t *spi, const mcu_pin_obj_t *command, - const mcu_pin_obj_t *chip_select, const mcu_pin_obj_t *reset, uint32_t baudrate, + busio_spi_obj_t *spi, mp_obj_t command, + mp_obj_t chip_select, mp_obj_t reset, uint32_t baudrate, uint8_t polarity, uint8_t phase) { self->bus = spi; @@ -27,31 +29,27 @@ void common_hal_fourwire_fourwire_construct(fourwire_fourwire_obj_t *self, self->polarity = polarity; self->phase = phase; + // Allocate the pins in the same place as self. + bool use_port_allocation = !gc_alloc_possible() || !gc_ptr_on_heap(self); - self->command.base.type = &mp_type_NoneType; - if (command != NULL) { - self->command.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->command, command); - common_hal_digitalio_digitalinout_switch_to_output(&self->command, true, DRIVE_MODE_PUSH_PULL); + self->command = digitalinout_protocol_from_pin(command, MP_QSTR_command, true, use_port_allocation, &self->own_command); + if (self->command != mp_const_none) { + digitalinout_protocol_switch_to_output(self->command, true, DRIVE_MODE_PUSH_PULL); common_hal_never_reset_pin(command); } - self->reset.base.type = &mp_type_NoneType; - if (reset != NULL) { - self->reset.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->reset, reset); - common_hal_digitalio_digitalinout_switch_to_output(&self->reset, true, DRIVE_MODE_PUSH_PULL); + + self->reset = digitalinout_protocol_from_pin(reset, MP_QSTR_reset, true, use_port_allocation, &self->own_reset); + if (self->reset != mp_const_none) { + digitalinout_protocol_switch_to_output(self->reset, true, DRIVE_MODE_PUSH_PULL); common_hal_never_reset_pin(reset); common_hal_fourwire_fourwire_reset(self); } - self->chip_select.base.type = &mp_type_NoneType; - if (chip_select != NULL) { - self->chip_select.base.type = &digitalio_digitalinout_type; - common_hal_digitalio_digitalinout_construct(&self->chip_select, chip_select); - common_hal_digitalio_digitalinout_switch_to_output(&self->chip_select, true, DRIVE_MODE_PUSH_PULL); + self->chip_select = digitalinout_protocol_from_pin(chip_select, MP_QSTR_chip_select, true, use_port_allocation, &self->own_chip_select); + if (self->chip_select != mp_const_none) { + digitalinout_protocol_switch_to_output(self->chip_select, true, DRIVE_MODE_PUSH_PULL); common_hal_never_reset_pin(chip_select); } - } void common_hal_fourwire_fourwire_deinit(fourwire_fourwire_obj_t *self) { @@ -59,19 +57,33 @@ void common_hal_fourwire_fourwire_deinit(fourwire_fourwire_obj_t *self) { common_hal_busio_spi_deinit(self->bus); } - common_hal_reset_pin(self->command.pin); - common_hal_reset_pin(self->chip_select.pin); - common_hal_reset_pin(self->reset.pin); + // Only deinit and free the pins if we own them + if (self->command != mp_const_none && self->own_command) { + digitalinout_protocol_deinit(self->command); + circuitpy_free_obj(self->command); + } + if (self->chip_select != mp_const_none && self->own_chip_select) { + digitalinout_protocol_deinit(self->chip_select); + circuitpy_free_obj(self->chip_select); + } + if (self->reset != mp_const_none && self->own_reset) { + digitalinout_protocol_deinit(self->reset); + circuitpy_free_obj(self->reset); + } } bool common_hal_fourwire_fourwire_reset(mp_obj_t obj) { fourwire_fourwire_obj_t *self = MP_OBJ_TO_PTR(obj); - if (self->reset.base.type == &mp_type_NoneType) { + if (self->reset == mp_const_none) { + return false; + } + if (digitalinout_protocol_set_value(self->reset, false) != 0) { return false; } - common_hal_digitalio_digitalinout_set_value(&self->reset, false); common_hal_mcu_delay_us(1000); - common_hal_digitalio_digitalinout_set_value(&self->reset, true); + if (digitalinout_protocol_set_value(self->reset, true) != 0) { + return false; + } common_hal_mcu_delay_us(1000); return true; } @@ -92,16 +104,23 @@ bool common_hal_fourwire_fourwire_begin_transaction(mp_obj_t obj) { } common_hal_busio_spi_configure(self->bus, self->frequency, self->polarity, self->phase, 8); - if (self->chip_select.base.type != &mp_type_NoneType) { - common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); + if (self->chip_select != mp_const_none) { + // IO Expander CS can fail due to an I2C lock. + if (digitalinout_protocol_set_value(self->chip_select, false) != 0) { + common_hal_busio_spi_unlock(self->bus); + return false; + } } return true; } void common_hal_fourwire_fourwire_send(mp_obj_t obj, display_byte_type_t data_type, display_chip_select_behavior_t chip_select, const uint8_t *data, uint32_t data_length) { + if (data_length == 0) { + return; + } fourwire_fourwire_obj_t *self = MP_OBJ_TO_PTR(obj); - if (self->command.base.type == &mp_type_NoneType) { + if (self->command == mp_const_none) { // When the data/command pin is not specified, we simulate a 9-bit SPI mode, by // adding a data/command bit to every byte, and then splitting the resulting data back // into 8-bit chunks for transmission. If the length of the data being transmitted @@ -133,24 +152,24 @@ void common_hal_fourwire_fourwire_send(mp_obj_t obj, display_byte_type_t data_ty if (bits > 0) { buffer = buffer << (8 - bits); common_hal_busio_spi_write(self->bus, &buffer, 1); - if (self->chip_select.base.type != &mp_type_NoneType) { + if (self->chip_select != mp_const_none) { // toggle CS to discard superfluous bits - common_hal_digitalio_digitalinout_set_value(&self->chip_select, true); + digitalinout_protocol_set_value(self->chip_select, true); common_hal_mcu_delay_us(1); - common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); + digitalinout_protocol_set_value(self->chip_select, false); } } } else { - common_hal_digitalio_digitalinout_set_value(&self->command, data_type == DISPLAY_DATA); + digitalinout_protocol_set_value(self->command, data_type == DISPLAY_DATA); if (chip_select == CHIP_SELECT_TOGGLE_EVERY_BYTE) { // Toggle chip select after each command byte in case the display driver // IC latches commands based on it. for (size_t i = 0; i < data_length; i++) { common_hal_busio_spi_write(self->bus, &data[i], 1); - if (self->chip_select.base.type != &mp_type_NoneType) { - common_hal_digitalio_digitalinout_set_value(&self->chip_select, true); + if (self->chip_select != mp_const_none) { + digitalinout_protocol_set_value(self->chip_select, true); common_hal_mcu_delay_us(1); - common_hal_digitalio_digitalinout_set_value(&self->chip_select, false); + digitalinout_protocol_set_value(self->chip_select, false); } } } else { @@ -161,8 +180,8 @@ void common_hal_fourwire_fourwire_send(mp_obj_t obj, display_byte_type_t data_ty void common_hal_fourwire_fourwire_end_transaction(mp_obj_t obj) { fourwire_fourwire_obj_t *self = MP_OBJ_TO_PTR(obj); - if (self->chip_select.base.type != &mp_type_NoneType) { - common_hal_digitalio_digitalinout_set_value(&self->chip_select, true); + if (self->chip_select != mp_const_none) { + digitalinout_protocol_set_value(self->chip_select, true); } common_hal_busio_spi_unlock(self->bus); } diff --git a/shared-module/fourwire/FourWire.h b/shared-module/fourwire/FourWire.h index 629a426b3b035..c239a3dfde374 100644 --- a/shared-module/fourwire/FourWire.h +++ b/shared-module/fourwire/FourWire.h @@ -6,6 +6,8 @@ #pragma once +#include + #include "common-hal/busio/SPI.h" #include "common-hal/digitalio/DigitalInOut.h" #include "shared-module/displayio/Group.h" @@ -14,10 +16,13 @@ typedef struct { mp_obj_base_t base; busio_spi_obj_t *bus; busio_spi_obj_t inline_bus; - digitalio_digitalinout_obj_t command; - digitalio_digitalinout_obj_t chip_select; - digitalio_digitalinout_obj_t reset; + mp_obj_t command; + mp_obj_t chip_select; + mp_obj_t reset; uint32_t frequency; uint8_t polarity; uint8_t phase; + bool own_command; + bool own_chip_select; + bool own_reset; } fourwire_fourwire_obj_t; diff --git a/shared-module/framebufferio/FramebufferDisplay.c b/shared-module/framebufferio/FramebufferDisplay.c index c9fe52e0e40b1..8116f4b0347cb 100644 --- a/shared-module/framebufferio/FramebufferDisplay.c +++ b/shared-module/framebufferio/FramebufferDisplay.c @@ -200,9 +200,11 @@ static bool _refresh_area(framebufferio_framebufferdisplay_obj_t *self, const di dest += rowstride; src += rowsize; } + // Run background tasks so they can run during an explicit refresh. + // Auto-refresh won't run background tasks here because it is a background task itself. + RUN_BACKGROUND_TASKS; - // TODO(tannewt): Make refresh displays faster so we don't starve other - // background tasks. + // Run USB background tasks so they can run during an implicit refresh. #if CIRCUITPY_TINYUSB usb_background(); #endif @@ -215,7 +217,10 @@ static void _refresh_display(framebufferio_framebufferdisplay_obj_t *self) { if (!self->bufinfo.buf) { return; } - displayio_display_core_start_refresh(&self->core); + if (!displayio_display_core_start_refresh(&self->core)) { + // Refresh on this display already in progress. + return; + } const displayio_area_t *current_area = _get_refresh_areas(self); if (current_area) { bool transposed = (self->core.rotation == 90 || self->core.rotation == 270); diff --git a/shared-module/gifio/GifWriter.c b/shared-module/gifio/GifWriter.c index 8747f4a486ca1..bf0b33836cfd3 100644 --- a/shared-module/gifio/GifWriter.c +++ b/shared-module/gifio/GifWriter.c @@ -70,7 +70,7 @@ void shared_module_gifio_gifwriter_construct(gifio_gifwriter_t *self, mp_obj_t * size_t nblocks = (width * height + 125) / 126; self->size = nblocks * 128 + 4; - self->data = m_malloc(self->size); + self->data = m_malloc_without_collect(self->size); self->cur = 0; self->error = 0; diff --git a/shared-module/hashlib/Hash.c b/shared-module/hashlib/Hash.c index a454966d99361..b7e966e951b5c 100644 --- a/shared-module/hashlib/Hash.c +++ b/shared-module/hashlib/Hash.c @@ -13,6 +13,9 @@ void common_hal_hashlib_hash_update(hashlib_hash_obj_t *self, const uint8_t *dat if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { mbedtls_sha1_update_ret(&self->sha1, data, datalen); return; + } else if (self->hash_type == MBEDTLS_SSL_HASH_SHA256) { + mbedtls_sha256_update_ret(&self->sha256, data, datalen); + return; } } @@ -27,12 +30,19 @@ void common_hal_hashlib_hash_digest(hashlib_hash_obj_t *self, uint8_t *data, siz mbedtls_sha1_clone(©, &self->sha1); mbedtls_sha1_finish_ret(&self->sha1, data); mbedtls_sha1_clone(&self->sha1, ©); + } else if (self->hash_type == MBEDTLS_SSL_HASH_SHA256) { + mbedtls_sha256_context copy; + mbedtls_sha256_clone(©, &self->sha256); + mbedtls_sha256_finish_ret(&self->sha256, data); + mbedtls_sha256_clone(&self->sha256, ©); } } size_t common_hal_hashlib_hash_get_digest_size(hashlib_hash_obj_t *self) { if (self->hash_type == MBEDTLS_SSL_HASH_SHA1) { return 20; + } else if (self->hash_type == MBEDTLS_SSL_HASH_SHA256) { + return 32; } return 0; } diff --git a/shared-module/hashlib/Hash.h b/shared-module/hashlib/Hash.h index ccc82037cb7aa..f3c2979e59c85 100644 --- a/shared-module/hashlib/Hash.h +++ b/shared-module/hashlib/Hash.h @@ -7,11 +7,13 @@ #pragma once #include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" typedef struct { mp_obj_base_t base; union { mbedtls_sha1_context sha1; + mbedtls_sha256_context sha256; }; // Of MBEDTLS_SSL_HASH_* uint8_t hash_type; diff --git a/shared-module/hashlib/__init__.c b/shared-module/hashlib/__init__.c index be3a9f1895964..f9bc787d49f16 100644 --- a/shared-module/hashlib/__init__.c +++ b/shared-module/hashlib/__init__.c @@ -16,6 +16,11 @@ bool common_hal_hashlib_new(hashlib_hash_obj_t *self, const char *algorithm) { mbedtls_sha1_init(&self->sha1); mbedtls_sha1_starts_ret(&self->sha1); return true; + } else if (strcmp(algorithm, "sha256") == 0) { + self->hash_type = MBEDTLS_SSL_HASH_SHA256; + mbedtls_sha256_init(&self->sha256); + mbedtls_sha256_starts_ret(&self->sha256, 0); + return true; } return false; } diff --git a/shared-module/hashlib/__init__.h b/shared-module/hashlib/__init__.h index f72882a1c03b3..847bd8a834728 100644 --- a/shared-module/hashlib/__init__.h +++ b/shared-module/hashlib/__init__.h @@ -13,4 +13,9 @@ #define mbedtls_sha1_starts_ret mbedtls_sha1_starts #define mbedtls_sha1_update_ret mbedtls_sha1_update #define mbedtls_sha1_finish_ret mbedtls_sha1_finish + +#define mbedtls_sha256_starts_ret mbedtls_sha256_starts +#define mbedtls_sha256_update_ret mbedtls_sha256_update +#define mbedtls_sha256_finish_ret mbedtls_sha256_finish + #endif diff --git a/shared-module/i2cioexpander/IOExpander.c b/shared-module/i2cioexpander/IOExpander.c new file mode 100644 index 0000000000000..f4aac5c053245 --- /dev/null +++ b/shared-module/i2cioexpander/IOExpander.c @@ -0,0 +1,196 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/i2cioexpander/IOExpander.h" +#include "shared-bindings/i2cioexpander/IOPin.h" + +#include + +#include "py/gc.h" +#include "py/runtime.h" +#include "shared-bindings/busio/I2C.h" +#include "supervisor/port.h" + +void common_hal_i2cioexpander_ioexpander_construct( + i2cioexpander_ioexpander_obj_t *self, + mp_obj_t i2c, + uint8_t address, + uint8_t num_pins, + uint16_t set_value_reg, + uint16_t get_value_reg, + uint16_t set_direction_reg) { + + // Store the I2C bus + self->i2c = (busio_i2c_obj_t *)i2c; + self->address = address; + self->num_pins = num_pins; + self->output_value = 0; + self->output_mask = 0; + + // Parse optional register addresses + self->has_set_value = (set_value_reg != NO_REGISTER); + if (self->has_set_value) { + self->set_value_reg = set_value_reg; + } + + self->has_get_value = (get_value_reg != NO_REGISTER); + if (self->has_get_value) { + self->get_value_reg = get_value_reg; + } + + self->has_set_direction = (set_direction_reg != NO_REGISTER); + if (self->has_set_direction) { + self->set_direction_reg = set_direction_reg; + } + + bool allocate_in_port_heap = !gc_alloc_possible() || !gc_ptr_on_heap(self); + + // Allocate tuple with space for pin objects in items[] + size_t tuple_size = offsetof(mp_obj_tuple_t, items) + sizeof(mp_obj_t) * num_pins; + mp_obj_tuple_t *pins_tuple = allocate_in_port_heap ? port_malloc(tuple_size, false) : m_malloc(tuple_size); + pins_tuple->base.type = &mp_type_tuple; + pins_tuple->len = num_pins; + + // Create IOPin objects for each pin + size_t pin_size = sizeof(i2cioexpander_iopin_obj_t); + for (uint8_t i = 0; i < num_pins; i++) { + i2cioexpander_iopin_obj_t *pin = allocate_in_port_heap ? port_malloc(pin_size, false) : m_malloc(pin_size); + pin->base.type = &i2cioexpander_iopin_type; + i2cioexpander_iopin_construct(pin, self, i); + pins_tuple->items[i] = MP_OBJ_FROM_PTR(pin); + } + + self->pins = pins_tuple; +} + +void common_hal_i2cioexpander_ioexpander_deinit(i2cioexpander_ioexpander_obj_t *self) { + if (gc_alloc_possible() && !gc_ptr_on_heap(self)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot deinitialize board IOExpander")); + } + for (uint8_t i = 0; i < self->num_pins; i++) { + circuitpy_free_obj(self->pins->items[i]); + } + circuitpy_free_obj(self->pins); + self->i2c = NULL; +} + +bool common_hal_i2cioexpander_ioexpander_deinited(i2cioexpander_ioexpander_obj_t *self) { + return self->i2c == NULL; +} + +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_get_input_value(i2cioexpander_ioexpander_obj_t *self, size_t *value) { + uint8_t buffer[2]; + uint8_t num_bytes = (self->num_pins > 8) ? 2 : 1; + + while (!common_hal_busio_i2c_try_lock(self->i2c)) { + RUN_BACKGROUND_TASKS; + } + + mp_negative_errno_t result; + if (self->has_get_value) { + // Send register address then read + result = common_hal_busio_i2c_write_read( + self->i2c, self->address, &self->get_value_reg, 1, buffer, num_bytes); + } else { + // Read directly without register address + result = common_hal_busio_i2c_read(self->i2c, self->address, buffer, num_bytes); + } + common_hal_busio_i2c_unlock(self->i2c); + + if (result != 0) { + return result; + } + + if (num_bytes == 2) { + *value = buffer[0] | (buffer[1] << 8); + } else { + *value = buffer[0]; + } + return 0; +} + +void common_hal_i2cioexpander_ioexpander_get_output_value(i2cioexpander_ioexpander_obj_t *self, size_t *value) { + *value = self->output_value; +} + +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_set_output_value(i2cioexpander_ioexpander_obj_t *self, size_t value) { + uint8_t buffer[5]; + uint8_t num_bytes = 0; + + // Add register address if provided + if (self->has_set_value) { + buffer[num_bytes++] = self->set_value_reg; + } + + size_t current_value = self->output_value; + if (current_value == value) { + return 0; + } + size_t diff = current_value ^ value; + + // Add value byte(s) but only if a high bit is changed + buffer[num_bytes++] = value & 0xFF; + if (self->num_pins > 8 && (diff >> 8) != 0) { + buffer[num_bytes++] = (value >> 8) & 0xFF; + } + if (self->num_pins > 16 && (diff >> 16) != 0) { + buffer[num_bytes++] = (value >> 16) & 0xFF; + } + if (self->num_pins > 24 && (diff >> 24) != 0) { + buffer[num_bytes++] = (value >> 24) & 0xFF; + } + + if (!common_hal_busio_i2c_try_lock(self->i2c)) { + return -MP_EBUSY; + } + + mp_negative_errno_t result = common_hal_busio_i2c_write(self->i2c, self->address, buffer, num_bytes); + common_hal_busio_i2c_unlock(self->i2c); + if (result == 0) { + self->output_value = value; + } + return result; +} + +void common_hal_i2cioexpander_ioexpander_get_output_mask(i2cioexpander_ioexpander_obj_t *self, size_t *mask) { + *mask = self->output_mask; +} + +mp_negative_errno_t common_hal_i2cioexpander_ioexpander_set_output_mask(i2cioexpander_ioexpander_obj_t *self, size_t mask) { + self->output_mask = mask; + + // Only write to device if direction register is provided + if (!self->has_set_direction) { + return 0; + } + + uint8_t buffer[3]; + uint8_t num_bytes = 0; + + // Add register address + buffer[num_bytes++] = self->set_direction_reg; + + // Invert the mask so 0 indicates output. We taken 1 for output to match output enable. + size_t inverted_mask = ~mask; + + // Add mask byte(s) + buffer[num_bytes++] = inverted_mask & 0xFF; + if (self->num_pins > 8) { + buffer[num_bytes++] = (inverted_mask >> 8) & 0xFF; + } + + if (!common_hal_busio_i2c_try_lock(self->i2c)) { + return -MP_EBUSY; + } + + mp_negative_errno_t result = common_hal_busio_i2c_write(self->i2c, self->address, buffer, num_bytes); + common_hal_busio_i2c_unlock(self->i2c); + return result; +} + +mp_obj_t common_hal_i2cioexpander_ioexpander_get_pins(i2cioexpander_ioexpander_obj_t *self) { + return MP_OBJ_FROM_PTR(self->pins); +} diff --git a/shared-module/i2cioexpander/IOExpander.h b/shared-module/i2cioexpander/IOExpander.h new file mode 100644 index 0000000000000..e225bfc75c778 --- /dev/null +++ b/shared-module/i2cioexpander/IOExpander.h @@ -0,0 +1,41 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "py/objtuple.h" +#include "shared-bindings/busio/I2C.h" + +#define NO_REGISTER (0x100) + +typedef struct { + mp_obj_base_t base; + busio_i2c_obj_t *i2c; + uint8_t address; + uint8_t num_pins; + uint8_t set_value_reg; + uint8_t get_value_reg; + uint8_t set_direction_reg; + size_t output_value; + size_t output_mask; + bool has_set_value; + bool has_get_value; + bool has_set_direction; + mp_obj_tuple_t *pins; +} i2cioexpander_ioexpander_obj_t; + +void common_hal_i2cioexpander_ioexpander_construct( + i2cioexpander_ioexpander_obj_t *self, + mp_obj_t i2c, + uint8_t address, + uint8_t num_pins, + uint16_t set_value_reg, + uint16_t get_value_reg, + uint16_t set_direction_reg); diff --git a/shared-module/i2cioexpander/IOPin.c b/shared-module/i2cioexpander/IOPin.c new file mode 100644 index 0000000000000..04642623b3dc0 --- /dev/null +++ b/shared-module/i2cioexpander/IOPin.c @@ -0,0 +1,148 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "shared-bindings/i2cioexpander/IOPin.h" +#include "shared-bindings/i2cioexpander/IOExpander.h" + +#include "py/runtime.h" + +mp_negative_errno_t i2cioexpander_iopin_construct( + i2cioexpander_iopin_obj_t *self, + i2cioexpander_ioexpander_obj_t *expander, + uint8_t pin_number) { + + if (pin_number >= expander->num_pins) { + return MP_EINVAL; // Reusing this for "invalid pin" + } + + self->expander = expander; + self->pin_number = pin_number; + self->direction = DIRECTION_INPUT; + + return 0; +} + +void common_hal_i2cioexpander_iopin_deinit(i2cioexpander_iopin_obj_t *self) { + // Switch to input on deinit. + common_hal_i2cioexpander_iopin_switch_to_input(self, PULL_NONE); +} + +bool common_hal_i2cioexpander_iopin_deinited(i2cioexpander_iopin_obj_t *self) { + return self->expander == NULL || common_hal_i2cioexpander_ioexpander_deinited(self->expander); +} + +digitalinout_result_t common_hal_i2cioexpander_iopin_switch_to_input( + i2cioexpander_iopin_obj_t *self, + digitalio_pull_t pull) { + + if (pull != PULL_NONE) { + // IO expanders typically don't support pull resistors + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL + return DIGITALINOUT_INVALID_PULL; + #endif + } + + self->direction = DIRECTION_INPUT; + + // Clear the output mask bit for this pin + size_t new_mask = self->expander->output_mask & ~(1 << self->pin_number); + common_hal_i2cioexpander_ioexpander_set_output_mask(self->expander, new_mask); + + return DIGITALINOUT_OK; +} + +digitalinout_result_t common_hal_i2cioexpander_iopin_switch_to_output( + i2cioexpander_iopin_obj_t *self, + bool value, + digitalio_drive_mode_t drive_mode) { + + if (drive_mode != DRIVE_MODE_PUSH_PULL) { + // IO expanders typically only support push-pull + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE + return DIGITALINOUT_INVALID_DRIVE_MODE; + #endif + } + + self->direction = DIRECTION_OUTPUT; + + // Set the value first + size_t new_value = self->expander->output_value; + if (value) { + new_value |= (1 << self->pin_number); + } else { + new_value &= ~(1 << self->pin_number); + } + common_hal_i2cioexpander_ioexpander_set_output_value(self->expander, new_value); + + // Set the output mask bit for this pin + size_t new_mask = self->expander->output_mask | (1 << self->pin_number); + common_hal_i2cioexpander_ioexpander_set_output_mask(self->expander, new_mask); + + return DIGITALINOUT_OK; +} + +digitalio_direction_t common_hal_i2cioexpander_iopin_get_direction(i2cioexpander_iopin_obj_t *self) { + return self->direction; +} + +mp_negative_errno_t common_hal_i2cioexpander_iopin_set_value(i2cioexpander_iopin_obj_t *self, bool value) { + size_t current_value; + common_hal_i2cioexpander_ioexpander_get_output_value(self->expander, ¤t_value); + size_t new_value; + if (value) { + new_value = current_value | (1 << self->pin_number); + } else { + new_value = current_value & ~(1 << self->pin_number); + } + if (new_value != current_value) { + return common_hal_i2cioexpander_ioexpander_set_output_value(self->expander, new_value); + } + return 0; +} + +mp_negative_errno_t common_hal_i2cioexpander_iopin_get_value(i2cioexpander_iopin_obj_t *self, bool *value) { + size_t full_value; + mp_negative_errno_t result = common_hal_i2cioexpander_ioexpander_get_input_value(self->expander, &full_value); + if (result != 0) { + return result; + } + *value = (full_value & (1 << self->pin_number)) != 0; + return 0; +} + +digitalinout_result_t common_hal_i2cioexpander_iopin_set_drive_mode( + i2cioexpander_iopin_obj_t *self, + digitalio_drive_mode_t drive_mode) { + + if (drive_mode != DRIVE_MODE_PUSH_PULL) { + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_DRIVE_MODE + return DIGITALINOUT_INVALID_DRIVE_MODE; + #endif + } + + return DIGITALINOUT_OK; +} + +digitalio_drive_mode_t common_hal_i2cioexpander_iopin_get_drive_mode(i2cioexpander_iopin_obj_t *self) { + return DRIVE_MODE_PUSH_PULL; +} + +digitalinout_result_t common_hal_i2cioexpander_iopin_set_pull( + i2cioexpander_iopin_obj_t *self, + digitalio_pull_t pull) { + + if (pull != PULL_NONE) { + #if CIRCUITPY_DIGITALIO_HAVE_INVALID_PULL + return DIGITALINOUT_INVALID_PULL; + #endif + } + + return DIGITALINOUT_OK; +} + +digitalio_pull_t common_hal_i2cioexpander_iopin_get_pull(i2cioexpander_iopin_obj_t *self) { + return PULL_NONE; +} diff --git a/shared-module/i2cioexpander/IOPin.h b/shared-module/i2cioexpander/IOPin.h new file mode 100644 index 0000000000000..0c4da8a0213fc --- /dev/null +++ b/shared-module/i2cioexpander/IOPin.h @@ -0,0 +1,26 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "shared-bindings/digitalio/Direction.h" +#include "shared-bindings/digitalio/DriveMode.h" +#include "shared-bindings/digitalio/Pull.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-module/i2cioexpander/IOExpander.h" + +typedef struct { + mp_obj_base_t base; + i2cioexpander_ioexpander_obj_t *expander; + uint8_t pin_number; + digitalio_direction_t direction; +} i2cioexpander_iopin_obj_t; + +extern const mp_obj_type_t i2cioexpander_iopin_type; diff --git a/shared-module/i2cioexpander/__init__.c b/shared-module/i2cioexpander/__init__.c new file mode 100644 index 0000000000000..43e652db897e0 --- /dev/null +++ b/shared-module/i2cioexpander/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2026 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Nothing now. diff --git a/shared-module/jpegio/JpegDecoder.c b/shared-module/jpegio/JpegDecoder.c index 484ba8e7ccd09..89cb624a8d03f 100644 --- a/shared-module/jpegio/JpegDecoder.c +++ b/shared-module/jpegio/JpegDecoder.c @@ -46,7 +46,7 @@ static void check_jresult(JRESULT j) { msg = MP_ERROR_TEXT("Right format but not supported"); break; case JDR_FMT3: - msg = MP_ERROR_TEXT("Not supported JPEG standard"); + msg = MP_ERROR_TEXT("Unsupported JPEG (may be progressive)"); break; } mp_raise_RuntimeError(msg); diff --git a/shared-module/keypad/EventQueue.c b/shared-module/keypad/EventQueue.c index 8d831d7a38e65..3130d8b59a1d7 100644 --- a/shared-module/keypad/EventQueue.c +++ b/shared-module/keypad/EventQueue.c @@ -13,9 +13,16 @@ #define EVENT_PRESSED (1 << 15) #define EVENT_KEY_NUM_MASK ((1 << 15) - 1) -void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events) { +#define EVENT_SIZE_BYTES (sizeof(uint16_t) + sizeof(mp_obj_t)) + +void common_hal_keypad_eventqueue_construct(keypad_eventqueue_obj_t *self, size_t max_events, bool use_gc_allocator) { // Event queue is 16-bit values. - ringbuf_alloc(&self->encoded_events, max_events * (sizeof(uint16_t) + sizeof(mp_obj_t))); + const size_t size = max_events * EVENT_SIZE_BYTES; + if (use_gc_allocator) { + ringbuf_alloc(&self->encoded_events, size); + } else { + ringbuf_init(&self->encoded_events, port_malloc(size, false), size); + } self->overflowed = false; self->event_handler = NULL; } @@ -39,7 +46,13 @@ mp_obj_t common_hal_keypad_eventqueue_get(keypad_eventqueue_obj_t *self) { if (result) { return event; } + + #if MICROPY_MALLOC_USES_ALLOCATED_SIZE + m_free(event, sizeof(keypad_event_obj_t)); + #else m_free(event); + #endif + return MP_ROM_NONE; } @@ -57,7 +70,7 @@ void common_hal_keypad_eventqueue_clear(keypad_eventqueue_obj_t *self) { } size_t common_hal_keypad_eventqueue_get_length(keypad_eventqueue_obj_t *self) { - return ringbuf_num_filled(&self->encoded_events); + return ringbuf_num_filled(&self->encoded_events) / EVENT_SIZE_BYTES; } void common_hal_keypad_eventqueue_set_event_handler(keypad_eventqueue_obj_t *self, void (*event_handler)(keypad_eventqueue_obj_t *)) { diff --git a/shared-module/keypad/KeyMatrix.c b/shared-module/keypad/KeyMatrix.c index 7706e335af82f..28830f591b129 100644 --- a/shared-module/keypad/KeyMatrix.c +++ b/shared-module/keypad/KeyMatrix.c @@ -7,6 +7,7 @@ #include #include "py/gc.h" +#include "py/mphal.h" #include "py/runtime.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/keypad/EventQueue.h" @@ -55,7 +56,7 @@ void common_hal_keypad_keymatrix_construct(keypad_keymatrix_obj_t *self, mp_uint self->columns_to_anodes = columns_to_anodes; self->funcs = &keymatrix_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } void common_hal_keypad_keymatrix_deinit(keypad_keymatrix_obj_t *self) { @@ -133,6 +134,10 @@ static void keymatrix_scan_now(void *self_in, mp_obj_t timestamp) { // to switch values. Just switching to an input with a (relatively weak) pullup/pulldown // causes a slight delay in the output changing, which can cause false readings. common_hal_digitalio_digitalinout_set_value(row_dio, self->columns_to_anodes); + + // Wait a moment to let the columns settle. + mp_hal_delay_us(1); + // Switch the row back to an input, pulled appropriately common_hal_digitalio_digitalinout_switch_to_input( row_dio, self->columns_to_anodes ? PULL_UP : PULL_DOWN); diff --git a/shared-module/keypad/Keys.c b/shared-module/keypad/Keys.c index 39d50f95e3238..80dcf36e163ad 100644 --- a/shared-module/keypad/Keys.c +++ b/shared-module/keypad/Keys.c @@ -41,7 +41,7 @@ void common_hal_keypad_keys_construct(keypad_keys_obj_t *self, mp_uint_t num_pin self->value_when_pressed = value_when_pressed; self->funcs = &keys_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } diff --git a/shared-module/keypad/ShiftRegisterKeys.c b/shared-module/keypad/ShiftRegisterKeys.c index f65c9a0532fc5..aa0c14dd36b50 100644 --- a/shared-module/keypad/ShiftRegisterKeys.c +++ b/shared-module/keypad/ShiftRegisterKeys.c @@ -32,9 +32,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ common_hal_digitalio_digitalinout_switch_to_output(clock, false, DRIVE_MODE_PUSH_PULL); self->clock = clock; - digitalio_digitalinout_obj_t *latch = m_new_obj(digitalio_digitalinout_obj_t); - latch->base.type = &digitalio_digitalinout_type; - + digitalio_digitalinout_obj_t *latch = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(latch, latch_pin); common_hal_digitalio_digitalinout_switch_to_output(latch, true, DRIVE_MODE_PUSH_PULL); self->latch = latch; @@ -42,8 +40,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ mp_obj_t dios[num_data_pins]; for (size_t i = 0; i < num_data_pins; i++) { - digitalio_digitalinout_obj_t *dio = m_new_obj(digitalio_digitalinout_obj_t); - dio->base.type = &digitalio_digitalinout_type; + digitalio_digitalinout_obj_t *dio = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, data_pins[i]); common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_NONE); dios[i] = dio; @@ -52,7 +49,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ // Allocate a tuple object with the data pins self->data_pins = mp_obj_new_tuple(num_data_pins, dios); - self->key_counts = (mp_uint_t *)m_malloc(sizeof(mp_uint_t) * num_key_counts); + self->key_counts = (mp_uint_t *)m_malloc_without_collect(sizeof(mp_uint_t) * num_key_counts); self->num_key_counts = num_key_counts; // copy to an m_malloc() and on the fly record pin with largest Shift register @@ -74,7 +71,7 @@ void common_hal_keypad_shiftregisterkeys_construct(keypad_shiftregisterkeys_obj_ self->value_when_pressed = value_when_pressed; self->funcs = &shiftregisterkeys_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, true); } void common_hal_keypad_shiftregisterkeys_deinit(keypad_shiftregisterkeys_obj_t *self) { diff --git a/shared-module/keypad/__init__.c b/shared-module/keypad/__init__.c index e43c7bce4fb09..f1d5d395df789 100644 --- a/shared-module/keypad/__init__.c +++ b/shared-module/keypad/__init__.c @@ -85,14 +85,20 @@ void keypad_deregister_scanner(keypad_scanner_obj_t *scanner) { supervisor_release_lock(&keypad_scanners_linked_list_lock); } -void keypad_construct_common(keypad_scanner_obj_t *self, mp_float_t interval, size_t max_events, uint8_t debounce_threshold) { +void keypad_construct_common(keypad_scanner_obj_t *self, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator) { size_t key_count = common_hal_keypad_generic_get_key_count(self); - self->debounce_counter = (int8_t *)m_malloc(sizeof(int8_t) * key_count); + self->debounce_counter = + use_gc_allocator + ? (int8_t *)m_malloc_without_collect(sizeof(int8_t) * key_count) + : (int8_t *)port_malloc_zero(sizeof(int8_t) * key_count, false); self->interval_ticks = (mp_uint_t)(interval * 1024); // interval * 1000 * (1024/1000) - keypad_eventqueue_obj_t *events = mp_obj_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type); - common_hal_keypad_eventqueue_construct(events, max_events); + keypad_eventqueue_obj_t *events = + use_gc_allocator + ? mp_obj_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type) + : mp_obj_port_malloc(keypad_eventqueue_obj_t, &keypad_eventqueue_type); + common_hal_keypad_eventqueue_construct(events, max_events, use_gc_allocator); self->events = events; self->debounce_threshold = debounce_threshold; @@ -140,7 +146,7 @@ void keypad_never_reset(keypad_scanner_obj_t *self) { void common_hal_keypad_generic_reset(void *self_in) { keypad_scanner_obj_t *self = self_in; size_t key_count = common_hal_keypad_generic_get_key_count(self); - memset(self->debounce_counter, self->debounce_threshold, key_count); + memset(self->debounce_counter, -self->debounce_threshold, key_count); keypad_scan_now(self, port_get_raw_ticks(NULL)); } diff --git a/shared-module/keypad/__init__.h b/shared-module/keypad/__init__.h index a7d21753f6625..66fea4878543b 100644 --- a/shared-module/keypad/__init__.h +++ b/shared-module/keypad/__init__.h @@ -39,7 +39,7 @@ void keypad_reset(void); void keypad_register_scanner(keypad_scanner_obj_t *scanner); void keypad_deregister_scanner(keypad_scanner_obj_t *scanner); -void keypad_construct_common(keypad_scanner_obj_t *scanner, mp_float_t interval, size_t max_events, uint8_t debounce_cycles); +void keypad_construct_common(keypad_scanner_obj_t *scanner, mp_float_t interval, size_t max_events, uint8_t debounce_cycles, bool use_gc_allocator); bool keypad_debounce(keypad_scanner_obj_t *self, mp_uint_t key_number, bool current); void keypad_never_reset(keypad_scanner_obj_t *self); diff --git a/shared-module/keypad_demux/DemuxKeyMatrix.c b/shared-module/keypad_demux/DemuxKeyMatrix.c index 42a0a0e68cc17..329f7679d3f76 100644 --- a/shared-module/keypad_demux/DemuxKeyMatrix.c +++ b/shared-module/keypad_demux/DemuxKeyMatrix.c @@ -7,6 +7,7 @@ #include #include "py/gc.h" +#include "py/mphal.h" #include "py/runtime.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/keypad/EventQueue.h" @@ -26,35 +27,49 @@ static keypad_scanner_funcs_t keymatrix_funcs = { }; static mp_uint_t row_column_to_key_number(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) { - return row * self->column_digitalinouts->len + column; + // return the key index in the user's coordinate system + return row * common_hal_keypad_demux_demuxkeymatrix_get_column_count(self) + column; } -void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], mp_float_t interval, size_t max_events, uint8_t debounce_threshold) { - +void common_hal_keypad_demux_demuxkeymatrix_construct(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t num_row_addr_pins, const mcu_pin_obj_t *row_addr_pins[], mp_uint_t num_column_pins, const mcu_pin_obj_t *column_pins[], bool columns_to_anodes, bool transpose, mp_float_t interval, size_t max_events, uint8_t debounce_threshold, bool use_gc_allocator) { + // the multiplexed pins are outputs so we can set the address for the target row + // the sense of the address pins themselves doesn't change with columns_to_anodes + // but the value output on the selected row line will be !columns_to_anodes mp_obj_t row_addr_dios[num_row_addr_pins]; for (size_t row = 0; row < num_row_addr_pins; row++) { digitalio_digitalinout_obj_t *dio = - mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); + use_gc_allocator + ? mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type) + : mp_obj_port_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, row_addr_pins[row]); common_hal_digitalio_digitalinout_switch_to_output(dio, false, DRIVE_MODE_PUSH_PULL); row_addr_dios[row] = dio; } - self->row_addr_digitalinouts = mp_obj_new_tuple(num_row_addr_pins, row_addr_dios); + self->row_addr_digitalinouts = + use_gc_allocator + ? mp_obj_new_tuple(num_row_addr_pins, row_addr_dios) + : mp_obj_new_port_tuple(num_row_addr_pins, row_addr_dios); + // the column pins are always inputs, with default state based on columns_to_anodes mp_obj_t column_dios[num_column_pins]; for (size_t column = 0; column < num_column_pins; column++) { digitalio_digitalinout_obj_t *dio = - mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); - dio->base.type = &digitalio_digitalinout_type; + use_gc_allocator + ? mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type) + : mp_obj_port_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(dio, column_pins[column]); - common_hal_digitalio_digitalinout_switch_to_input(dio, PULL_UP); + common_hal_digitalio_digitalinout_switch_to_input(dio, columns_to_anodes ? PULL_UP : PULL_DOWN); column_dios[column] = dio; } - self->column_digitalinouts = mp_obj_new_tuple(num_column_pins, column_dios); - + self->column_digitalinouts = + use_gc_allocator + ? mp_obj_new_tuple(num_column_pins, column_dios) + : mp_obj_new_port_tuple(num_column_pins, column_dios); + self->columns_to_anodes = columns_to_anodes; + self->transpose = transpose; self->funcs = &keymatrix_funcs; - keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold); + keypad_construct_common((keypad_scanner_obj_t *)self, interval, max_events, debounce_threshold, use_gc_allocator); } void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_obj_t *self) { @@ -78,11 +93,15 @@ void common_hal_keypad_demux_demuxkeymatrix_deinit(keypad_demux_demuxkeymatrix_o } size_t common_hal_keypad_demux_demuxkeymatrix_get_row_count(keypad_demux_demuxkeymatrix_obj_t *self) { - return 1 << self->row_addr_digitalinouts->len; + return self->transpose + ? self->column_digitalinouts->len + : (size_t)(1 << self->row_addr_digitalinouts->len); } size_t common_hal_keypad_demux_demuxkeymatrix_get_column_count(keypad_demux_demuxkeymatrix_obj_t *self) { - return self->column_digitalinouts->len; + return self->transpose + ? (size_t)(1 << self->row_addr_digitalinouts->len) + : self->column_digitalinouts->len; } mp_uint_t common_hal_keypad_demux_demuxkeymatrix_row_column_to_key_number(keypad_demux_demuxkeymatrix_obj_t *self, mp_uint_t row, mp_uint_t column) { @@ -102,9 +121,13 @@ static size_t demuxkeymatrix_get_key_count(void *self_in) { static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp) { keypad_demux_demuxkeymatrix_obj_t *self = self_in; - - for (size_t row = 0; row < common_hal_keypad_demux_demuxkeymatrix_get_row_count(self); row++) { - // Set the row address on demultiplexer + // We always scan through the multiplexed lines using the array sizes directly + // and apply transposition only when translating to key number. + for (int row = 0; row < (1 << self->row_addr_digitalinouts->len); row++) { + // Set the row address on the demultiplexer. + // When columns_to_anodes is True (default) we've got an inverting demux + // so the selected line is pulled low, and we look for rows that get pulled low. + // When columns_to_anodes is False we do the reverse. size_t mask = 0b00000001; for (size_t row_addr_pin = 0; row_addr_pin < self->row_addr_digitalinouts->len; row_addr_pin++) { digitalio_digitalinout_obj_t *dio = self->row_addr_digitalinouts->items[row_addr_pin]; @@ -112,12 +135,24 @@ static void demuxkeymatrix_scan_now(void *self_in, mp_obj_t timestamp) { mask = mask << 1; } - for (size_t column = 0; column < common_hal_keypad_demux_demuxkeymatrix_get_column_count(self); column++) { - mp_uint_t key_number = row_column_to_key_number(self, row, column); - - // Get the current state, by reading whether the column got pulled to the row value or not. - // If low, the key is pressed. - const bool current = !common_hal_digitalio_digitalinout_get_value(self->column_digitalinouts->items[column]); + // Wait a moment to let the columns settle. + // The normal KeyMatrix uses a 1us delay but that still gave echoes on my + // nullbitsco nibble 65% (16 x 5 matrix). For example when key (row, col) is pressed + // both (row, col) and (row+1, col) (and sometimes row+2) are registered, + // especially when row+1 is a power of 2 (all mux bits change) and col is 0. + // The QMK implementation for this keyboard uses a 5us delay which works here too + mp_hal_delay_us(5); + + for (size_t column = 0; column < self->column_digitalinouts->len; column++) { + mp_uint_t key_number = self->transpose + ? row_column_to_key_number(self, column, row) + : row_column_to_key_number(self, row, column); + + // Get the current state, by reading whether the column got pulled to the row value or not, + // which is the opposite of columns_to_anodes. + const bool current = + common_hal_digitalio_digitalinout_get_value(self->column_digitalinouts->items[column]) != + self->columns_to_anodes; // Record any transitions. if (keypad_debounce((keypad_scanner_obj_t *)self, key_number, current)) { diff --git a/shared-module/keypad_demux/DemuxKeyMatrix.h b/shared-module/keypad_demux/DemuxKeyMatrix.h index 45afa93a8442b..fe315775dd211 100644 --- a/shared-module/keypad_demux/DemuxKeyMatrix.h +++ b/shared-module/keypad_demux/DemuxKeyMatrix.h @@ -17,6 +17,8 @@ typedef struct { KEYPAD_SCANNER_COMMON_FIELDS; mp_obj_tuple_t *row_addr_digitalinouts; mp_obj_tuple_t *column_digitalinouts; + bool columns_to_anodes; + bool transpose; } keypad_demux_demuxkeymatrix_obj_t; void keypad_demux_demuxkeymatrix_scan(keypad_demux_demuxkeymatrix_obj_t *self); diff --git a/shared-module/lvfontio/OnDiskFont.c b/shared-module/lvfontio/OnDiskFont.c new file mode 100644 index 0000000000000..efffed6307443 --- /dev/null +++ b/shared-module/lvfontio/OnDiskFont.c @@ -0,0 +1,885 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include + +#include "shared-bindings/lvfontio/OnDiskFont.h" +#include "py/runtime.h" +#include "py/mperrno.h" +#include "py/stream.h" +#include "py/objstr.h" +#include "py/gc.h" +#include "shared-bindings/displayio/Bitmap.h" +#include "extmod/vfs_fat.h" +#include "lib/oofatfs/ff.h" +#include "supervisor/shared/translate/translate.h" +#include "supervisor/port.h" +#include "supervisor/shared/serial.h" +#include "supervisor/filesystem.h" + +// Helper functions for memory allocation +static inline void *allocate_memory(lvfontio_ondiskfont_t *self, size_t size) { + void *ptr; + if (self->use_gc_allocator) { + ptr = m_malloc_maybe(size); + } else { + ptr = port_malloc(size, false); + } + if (ptr != NULL) { + return ptr; + } + common_hal_lvfontio_ondiskfont_deinit(self); + if (self->use_gc_allocator) { + m_malloc_fail(size); + } + return NULL; +} + +static inline void free_memory(lvfontio_ondiskfont_t *self, void *ptr) { + if (self->use_gc_allocator) { + m_free(ptr); + } else { + port_free(ptr); + } +} + +// Forward declarations for helper functions +static int16_t find_codepoint_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint); +static bool slot_has_active_full_width_partner(lvfontio_ondiskfont_t *self, uint16_t slot); +static uint16_t find_free_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint); +static FRESULT read_bits(FIL *file, size_t num_bits, uint8_t *byte_val, uint8_t *remaining_bits, uint32_t *result); +static FRESULT read_glyph_dimensions(FIL *file, lvfontio_ondiskfont_t *self, uint32_t *advance_width, int32_t *bbox_x, int32_t *bbox_y, uint32_t *bbox_w, uint32_t *bbox_h, uint8_t *byte_val, uint8_t *remaining_bits); + +// Load font header data from file +static bool load_font_header(lvfontio_ondiskfont_t *self, FIL *file, size_t *max_slots) { + UINT bytes_read; + FRESULT res; + + // Start at the beginning of the file + res = f_lseek(file, 0); + if (res != FR_OK) { + return false; + } + + uint8_t buffer[8]; + bool found_head = false; + bool found_cmap = false; + bool found_loca = false; + bool found_glyf = false; + + + size_t current_position = 0; + + // Read sections until we find all the sections we need or reach end of file + while (true) { + // Read section size (4 bytes) + res = f_read(file, buffer, 4, &bytes_read); + if (res != FR_OK || bytes_read < 4) { + break; // Read error or end of file + } + + uint32_t section_size = buffer[0] | (buffer[1] << 8) | + (buffer[2] << 16) | (buffer[3] << 24); + + if (section_size == 0) { + break; // End of sections marker + } + + // Read section marker (4 bytes) + res = f_read(file, buffer, 4, &bytes_read); + if (res != FR_OK || bytes_read < 4) { + break; // Read error or unexpected end of file + } + + + // Make a null-terminated copy of the section marker for debug printing + char section_marker[5] = {0}; + memcpy(section_marker, buffer, 4); + + // Process different section types + if (memcmp(buffer, "head", 4) == 0) { + // Read head section data (35 bytes) + uint8_t head_buf[35]; + res = f_read(file, head_buf, 35, &bytes_read); + if (res != FR_OK || bytes_read < 35) { + break; + } + + // Skip version (4 bytes) and padding (1 byte) + // Parse font metrics at offset 6 + self->header.font_size = head_buf[6] | (head_buf[7] << 8); + self->header.ascent = head_buf[8] | (head_buf[9] << 8); + self->header.default_advance_width = head_buf[22] | (head_buf[23] << 8); + + // Parse format information + self->header.index_to_loc_format = head_buf[26]; + self->header.bits_per_pixel = head_buf[29]; + self->header.glyph_bbox_xy_bits = head_buf[30]; + self->header.glyph_bbox_wh_bits = head_buf[31]; + self->header.glyph_advance_bits = head_buf[32]; + + // Calculate derived values + self->header.glyph_header_bits = self->header.glyph_advance_bits + + 2 * self->header.glyph_bbox_xy_bits + + 2 * self->header.glyph_bbox_wh_bits; + self->header.glyph_header_bytes = (self->header.glyph_header_bits + 7) / 8; + + found_head = true; + } else if (memcmp(buffer, "cmap", 4) == 0) { + // Read subtable count + uint8_t cmap_header[4]; + res = f_read(file, cmap_header, 4, &bytes_read); + if (res != FR_OK || bytes_read < 4) { + break; + } + + uint32_t subtable_count = cmap_header[0] | (cmap_header[1] << 8) | + (cmap_header[2] << 16) | (cmap_header[3] << 24); + + // Allocate memory for cmap ranges + self->cmap_range_count = subtable_count; + self->cmap_ranges = allocate_memory(self, sizeof(lvfontio_cmap_range_t) * subtable_count); + if (self->cmap_ranges == NULL) { + return false; + } + + // Read each subtable + for (uint16_t i = 0; i < subtable_count; i++) { + uint8_t subtable_buf[16]; + res = f_read(file, subtable_buf, 16, &bytes_read); + if (res != FR_OK || bytes_read < 16) { + break; + } + + // Read data_offset (4 bytes) + uint32_t data_offset = subtable_buf[0] | (subtable_buf[1] << 8) | + (subtable_buf[2] << 16) | (subtable_buf[3] << 24); + + // Read range_start, range_length, glyph_offset + uint32_t range_start = subtable_buf[4] | (subtable_buf[5] << 8) | + (subtable_buf[6] << 16) | (subtable_buf[7] << 24); + uint16_t range_length = subtable_buf[8] | (subtable_buf[9] << 8); + uint16_t glyph_offset = subtable_buf[10] | (subtable_buf[11] << 8); + uint16_t entries_count = subtable_buf[12] | (subtable_buf[13] << 8); + + // Get format type (0=sparse mapping, 1=range mapping, 2=range to range, 3=direct mapping) + uint8_t format_type = subtable_buf[14]; + // Check for supported format types (0, 2, and 3) + if (format_type != 0 && format_type != 2 && format_type != 3) { + continue; + } + + // Store the range information + self->cmap_ranges[i].range_start = range_start; + self->cmap_ranges[i].range_end = range_start + range_length; + self->cmap_ranges[i].glyph_offset = glyph_offset; + self->cmap_ranges[i].format_type = format_type; + self->cmap_ranges[i].data_offset = current_position + data_offset; + self->cmap_ranges[i].entries_count = entries_count; + } + + found_cmap = true; + } else if (memcmp(buffer, "loca", 4) == 0) { + // Read max_cid + uint8_t loca_header[4]; + res = f_read(file, loca_header, 4, &bytes_read); + if (res != FR_OK || bytes_read < 4) { + break; + } + + // Store max_cid value + self->max_cid = loca_header[0] | (loca_header[1] << 8) | + (loca_header[2] << 16) | (loca_header[3] << 24); + + // Store location of the loca table offset data + self->loca_table_offset = current_position + 12; + + found_loca = true; + } else if (memcmp(buffer, "glyf", 4) == 0) { + // Store start of glyf table + self->glyf_table_offset = current_position; + size_t advances[2] = {0, 0}; + size_t advance_count[2] = {0, 0}; + + if (self->header.default_advance_width != 0) { + advances[0] = self->header.default_advance_width; + } + + // Set the default advance width based on the first character in the + // file. + size_t cid = 0; + while (cid < self->max_cid - 1) { + // Read glyph header fields + uint32_t glyph_advance; + int32_t bbox_x, bbox_y; + uint32_t bbox_w, bbox_h; + + uint8_t byte_val = 0; + uint8_t remaining_bits = 0; + + // Use the helper function to read glyph dimensions + read_glyph_dimensions(file, self, &glyph_advance, &bbox_x, &bbox_y, &bbox_w, &bbox_h, &byte_val, &remaining_bits); + + // Throw away the bitmap bits. + read_bits(file, self->header.bits_per_pixel * bbox_w * bbox_h, &byte_val, &remaining_bits, NULL); + + if (glyph_advance == 0) { + // Ignore zero-advance glyphs when inferring the terminal cell width. + // Some fonts include placeholders/control glyphs with zero advance, + // which would otherwise skew default_advance_width too small. + } else if (advances[0] == glyph_advance) { + advance_count[0]++; + } else if (advances[1] == glyph_advance) { + advance_count[1]++; + } else if (advance_count[0] == 0) { + advances[0] = glyph_advance; + advance_count[0] = 1; + } else if (advance_count[1] == 0) { + advances[1] = glyph_advance; + advance_count[1] = 1; + } else { + break; + } + cid++; + } + + if (self->header.default_advance_width == 0) { + if (advance_count[1] == 0) { + self->header.default_advance_width = advances[0]; + *max_slots = advance_count[0]; + } else { + if (advances[0] > advances[1]) { + self->header.default_advance_width = advances[0] / 2; + *max_slots = advance_count[0] * 2 + advance_count[1]; + } else { + self->header.default_advance_width = advances[1] / 2; + *max_slots = advance_count[1] * 2 + advance_count[0]; + } + } + } else { + *max_slots = advance_count[0] + advance_count[1]; + } + + if (self->header.default_advance_width == 0) { + self->header.default_advance_width = 1; + } + if (*max_slots == 0) { + *max_slots = 1; + } + found_glyf = true; + } + + current_position += section_size; + + // Skip to the end of the section + res = f_lseek(file, current_position); + if (res != FR_OK) { + break; + } + + // If we found all needed sections, we can stop + if (found_head && found_cmap && found_loca && found_glyf) { + break; + } + } + + // Check if we found all required sections + if (!found_head || !found_cmap || !found_loca || !found_glyf) { + return false; + } + + return true; +} + +// Get character ID (glyph index) for a codepoint +static int32_t get_char_id(lvfontio_ondiskfont_t *self, uint32_t codepoint) { + // Find codepoint in cmap ranges + for (uint16_t i = 0; i < self->cmap_range_count; i++) { + // Check if codepoint is in range for this subtable + if (codepoint >= self->cmap_ranges[i].range_start && + codepoint < self->cmap_ranges[i].range_end) { + + // Handle according to format type + switch (self->cmap_ranges[i].format_type) { + case 0: { // Sparse mapping - need to look up in a sparse table + if (!self->file_is_open) { + return -1; + } + + // Calculate the relative position within the range + uint32_t idx = codepoint - self->cmap_ranges[i].range_start; + + if (idx >= self->cmap_ranges[i].entries_count) { + return -1; + } + + // Calculate the absolute data position in the file + uint32_t data_pos = self->cmap_ranges[i].data_offset + idx; // 1 byte per entry + FRESULT res = f_lseek(&self->file, data_pos); + if (res != FR_OK) { + return -1; + } + + // Read the glyph ID (1 byte) + uint8_t glyph_id; + UINT bytes_read; + res = f_read(&self->file, &glyph_id, 1, &bytes_read); + + if (res != FR_OK || bytes_read < 1) { + return -1; + } + + + return self->cmap_ranges[i].glyph_offset + glyph_id; + } + + case 2: // Range to range - calculate based on offset within range + uint16_t idx = codepoint - self->cmap_ranges[i].range_start; + uint16_t glyph_id = self->cmap_ranges[i].glyph_offset + idx; + return glyph_id; + + case 3: { // Direct mapping - need to look up in the table + if (!self->file_is_open) { + return -1; + } + + FRESULT res; + res = f_lseek(&self->file, self->cmap_ranges[i].data_offset); + if (res != FR_OK) { + return -1; + } + uint16_t codepoint_delta = codepoint - self->cmap_ranges[i].range_start; + + for (size_t j = 0; j < self->cmap_ranges[i].entries_count; j++) { + // Read code point at the index + uint16_t candidate_codepoint_delta; + UINT bytes_read; + res = f_read(&self->file, &candidate_codepoint_delta, 2, &bytes_read); + if (res != FR_OK || bytes_read < 2) { + return -1; + } + + if (candidate_codepoint_delta == codepoint_delta) { + return self->cmap_ranges[i].glyph_offset + j; + } + } + return -1; + } + + default: + return -1; + } + } + } + + return -1; // Not found +} + +// Load glyph bitmap data into a slot +// This function assumes the file is already open and positioned after reading the glyph dimensions +static bool load_glyph_bitmap(FIL *file, lvfontio_ondiskfont_t *self, uint32_t codepoint, uint16_t slot, + uint32_t glyph_advance, int32_t bbox_x, int32_t bbox_y, uint32_t bbox_w, uint32_t bbox_h, + uint8_t *byte_val, uint8_t *remaining_bits) { + // Store codepoint at slot + self->codepoints[slot] = codepoint; + self->reference_counts[slot] = 1; + + // Read bitmap data pixel by pixel + uint16_t x_offset = slot * self->header.default_advance_width; + uint16_t y_offset = self->header.ascent - bbox_y - bbox_h; + for (uint16_t y = 0; y < bbox_h; y++) { + for (uint16_t x = 0; x < bbox_w; x++) { + uint32_t pixel_value; + FRESULT res = read_bits(file, self->header.bits_per_pixel, byte_val, remaining_bits, &pixel_value); + if (res != FR_OK) { + return false; + } + + // Adjust for bbox position within the glyph bounding box + int16_t bitmap_x = x_offset + x + bbox_x; + int16_t bitmap_y = y_offset + y; + + // Make sure we're in bounds + if (bitmap_x >= 0 && + bitmap_x < self->header.default_advance_width * self->max_glyphs && + bitmap_y >= 0 && + bitmap_y < self->header.font_size) { + common_hal_displayio_bitmap_set_pixel( + self->bitmap, + bitmap_x, + bitmap_y, + pixel_value + ); + } + } + } + + return true; +} + +// Constructor +void common_hal_lvfontio_ondiskfont_construct(lvfontio_ondiskfont_t *self, + const char *file_path, + uint16_t max_glyphs, + bool use_gc_allocator) { + + // Store the allocation mode + self->use_gc_allocator = use_gc_allocator; + // Store parameters + self->file_path = file_path; // Store the provided path string directly + self->max_glyphs = max_glyphs; + self->cmap_ranges = NULL; + self->file_is_open = false; + + // Determine which filesystem to use based on the path + const char *path_under_mount; + fs_user_mount_t *vfs = filesystem_for_path(file_path, &path_under_mount); + + if (vfs == NULL) { + if (self->use_gc_allocator) { + mp_raise_ValueError(MP_ERROR_TEXT("File not found")); + } + return; + } + + // Open the file and keep it open for the lifetime of the object + FRESULT res = f_open(&vfs->fatfs, &self->file, path_under_mount, FA_READ); + + if (res != FR_OK) { + if (self->use_gc_allocator) { + mp_raise_ValueError(MP_ERROR_TEXT("File not found")); + } + return; + } + + self->file_is_open = true; + + // Load font headers + size_t max_slots; + if (!load_font_header(self, &self->file, &max_slots)) { + f_close(&self->file); + self->file_is_open = false; + if (self->use_gc_allocator) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid %q"), MP_QSTR_file); + } + return; + } + // Cap the number of slots to the number of slots needed by the font. That way + // small font files don't need a bunch of extra cache space. + max_glyphs = MIN(max_glyphs, max_slots); + + // Allocate codepoints array. allocate_memory will raise an exception if + // allocation fails and the VM is active. + self->codepoints = allocate_memory(self, sizeof(uint32_t) * max_glyphs); + if (self->codepoints == NULL) { + return; + } + + // Initialize codepoints to invalid + for (uint16_t i = 0; i < max_glyphs; i++) { + self->codepoints[i] = LVFONTIO_INVALID_CODEPOINT; + } + + // Allocate reference counts + self->reference_counts = allocate_memory(self, sizeof(uint16_t) * max_glyphs); + if (self->reference_counts == NULL) { + return; + } + + // Initialize reference counts to 0 + memset(self->reference_counts, 0, sizeof(uint16_t) * max_glyphs); + + self->half_width_px = self->header.default_advance_width; + + // Create bitmap for glyph cache + displayio_bitmap_t *bitmap = allocate_memory(self, sizeof(displayio_bitmap_t)); + bitmap->base.type = &displayio_bitmap_type; + if (bitmap == NULL) { + return; + } + + // Calculate bitmap stride + uint32_t bits_per_pixel = 1 << self->header.bits_per_pixel; + uint32_t width = self->header.default_advance_width * max_glyphs; + uint32_t row_width = width * bits_per_pixel; + uint16_t stride = (row_width + 31) / 32; // Align to uint32_t (32 bits) + + // Allocate buffer for bitmap data + uint32_t buffer_size = stride * self->header.font_size * sizeof(uint32_t); + uint32_t *bitmap_buffer = allocate_memory(self, buffer_size); + if (bitmap_buffer == NULL) { + return; + } + + // Zero out bitmap buffer + memset(bitmap_buffer, 0, buffer_size); + + // Construct bitmap with allocated buffer + common_hal_displayio_bitmap_construct_from_buffer(bitmap, + self->header.default_advance_width * max_glyphs, + self->header.font_size, + 1 << self->header.bits_per_pixel, + bitmap_buffer, + false); + self->bitmap = bitmap; +} + +void common_hal_lvfontio_ondiskfont_deinit(lvfontio_ondiskfont_t *self) { + if (!self->file_is_open) { + return; + } + + if (self->bitmap != NULL) { + common_hal_displayio_bitmap_deinit(self->bitmap); + self->bitmap = NULL; + } + + if (self->codepoints != NULL) { + free_memory(self, self->codepoints); + self->codepoints = NULL; + } + + if (self->reference_counts != NULL) { + free_memory(self, self->reference_counts); + self->reference_counts = NULL; + } + + + + if (self->cmap_ranges != NULL) { + free_memory(self, self->cmap_ranges); + self->cmap_ranges = NULL; + } + + f_close(&self->file); + self->file_is_open = false; +} + +bool common_hal_lvfontio_ondiskfont_deinited(lvfontio_ondiskfont_t *self) { + return !self->file_is_open; +} + +mp_obj_t common_hal_lvfontio_ondiskfont_get_bitmap(const lvfontio_ondiskfont_t *self) { + return MP_OBJ_FROM_PTR(self->bitmap); +} + +mp_obj_t common_hal_lvfontio_ondiskfont_get_bounding_box(const lvfontio_ondiskfont_t *self) { + mp_obj_t bbox[2]; + bbox[0] = MP_OBJ_NEW_SMALL_INT(self->header.default_advance_width); + bbox[1] = MP_OBJ_NEW_SMALL_INT(self->header.font_size); + return mp_obj_new_tuple(2, bbox); +} + +void common_hal_lvfontio_ondiskfont_get_dimensions(const lvfontio_ondiskfont_t *self, + uint16_t *width, uint16_t *height) { + if (width != NULL) { + *width = self->header.default_advance_width; + } + if (height != NULL) { + *height = self->header.font_size; + } +} + +int16_t common_hal_lvfontio_ondiskfont_cache_glyph(lvfontio_ondiskfont_t *self, uint32_t codepoint, bool *is_full_width) { + // Check if already cached + int16_t existing_slot = find_codepoint_slot(self, codepoint); + if (existing_slot >= 0) { + // Glyph is already cached, increment reference count(s). + self->reference_counts[existing_slot]++; + + // Check if this is a full-width character by looking for a second slot + // with the same codepoint right after this one, wrapping at the end. + uint16_t next_slot = (existing_slot + 1) % self->max_glyphs; + bool cached_is_full_width = self->codepoints[next_slot] == codepoint; + + if (cached_is_full_width) { + self->reference_counts[next_slot]++; + } + + if (is_full_width != NULL) { + *is_full_width = cached_is_full_width; + } + + return existing_slot; + } + + // First check if the glyph is full-width before allocating slots + // This way we know if we need one or two slots before committing + bool is_full_width_glyph = false; + + // Check if file is already open + if (!self->file_is_open) { + + return -1; + } + + // Find character ID from codepoint + int32_t char_id = get_char_id(self, codepoint); + if (char_id < 0 || (uint32_t)char_id >= self->max_cid) { + return -1; // Invalid character + } + + // Get glyph offset from location table + uint32_t glyph_offset = 0; + uint32_t loca_offset = self->loca_table_offset + char_id * + (self->header.index_to_loc_format == 1 ? 4 : 2); + + FRESULT res = f_lseek(&self->file, loca_offset); + if (res != FR_OK) { + return -1; + } + + UINT bytes_read; + if (self->header.index_to_loc_format == 1) { + // 4-byte offset + uint8_t offset_buf[4]; + res = f_read(&self->file, offset_buf, 4, &bytes_read); + if (res != FR_OK || bytes_read < 4) { + return -1; + } + glyph_offset = offset_buf[0] | (offset_buf[1] << 8) | + (offset_buf[2] << 16) | (offset_buf[3] << 24); + } else { + // 2-byte offset + uint8_t offset_buf[2]; + res = f_read(&self->file, offset_buf, 2, &bytes_read); + if (res != FR_OK || bytes_read < 2) { + return -1; + } + glyph_offset = offset_buf[0] | (offset_buf[1] << 8); + } + // Seek to glyph data + res = f_lseek(&self->file, self->glyf_table_offset + glyph_offset); + if (res != FR_OK) { + return -1; + } + + // Read glyph header fields to determine width + uint32_t glyph_advance; + int32_t bbox_x, bbox_y; + uint32_t bbox_w, bbox_h; + + // Initialize bit reading state + uint8_t byte_val = 0; + uint8_t remaining_bits = 0; + + // Use the helper function to read glyph dimensions + res = read_glyph_dimensions(&self->file, self, &glyph_advance, &bbox_x, &bbox_y, &bbox_w, &bbox_h, &byte_val, &remaining_bits); + if (res != FR_OK) { + return -1; + } + + // Check if the glyph is full-width based on its advance width + // Full-width characters typically have an advance width close to or greater than the font height + is_full_width_glyph = glyph_advance > self->half_width_px; + + // Now we know if we need one or two slots + uint16_t slots_needed = is_full_width_glyph ? 2 : 1; + + // Find an appropriate slot (or consecutive slots for full-width) + uint16_t slot = UINT16_MAX; + + if (slots_needed == 1) { + // For regular width, find a free slot starting at codepoint's position + slot = find_free_slot(self, codepoint); + } else { + // For full-width, find two consecutive free slots + for (uint16_t i = 0; i < self->max_glyphs - 1; i++) { + if (self->codepoints[i] == LVFONTIO_INVALID_CODEPOINT && + self->reference_counts[i] == 0 && + self->codepoints[i + 1] == LVFONTIO_INVALID_CODEPOINT && + self->reference_counts[i + 1] == 0) { + slot = i; + break; + } + } + } + + // Check if we found appropriate slot(s) + if (slot == UINT16_MAX) { + return -1; // No slots available + } + + // Load glyph into the slot + if (!load_glyph_bitmap(&self->file, self, codepoint, slot, glyph_advance, + bbox_x, bbox_y, bbox_w, bbox_h, &byte_val, &remaining_bits)) { + return -1; // Failed to load glyph + } + + // For full-width characters, mark both slots with the same codepoint + if (is_full_width_glyph && slot + 1 < self->max_glyphs) { + self->codepoints[slot + 1] = codepoint; + self->reference_counts[slot + 1] = 1; + } + + if (is_full_width != NULL) { + *is_full_width = is_full_width_glyph; + } + + return slot; +} + +void common_hal_lvfontio_ondiskfont_release_glyph(lvfontio_ondiskfont_t *self, uint32_t slot) { + if (slot >= self->max_glyphs) { + return; + } + + if (self->reference_counts[slot] > 0) { + self->reference_counts[slot]--; + } +} + +static int16_t find_codepoint_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint) { + size_t offset = codepoint % self->max_glyphs; + for (uint16_t i = 0; i < self->max_glyphs; i++) { + int16_t slot = (i + offset) % self->max_glyphs; + if (self->codepoints[slot] == codepoint) { + // If this is the second slot of a full-width glyph pair, return the + // first slot so callers always get a canonical index. + if (slot > 0 && self->codepoints[slot - 1] == codepoint) { + return slot - 1; + } + return slot; + } + } + return -1; +} + +static bool slot_has_active_full_width_partner(lvfontio_ondiskfont_t *self, uint16_t slot) { + uint32_t codepoint = self->codepoints[slot]; + if (codepoint == LVFONTIO_INVALID_CODEPOINT) { + return false; + } + + // Don't evict one half of a full-width pair while the other half is still in use. + uint16_t prev_slot = (slot + self->max_glyphs - 1) % self->max_glyphs; + uint16_t next_slot = (slot + 1) % self->max_glyphs; + + if (self->codepoints[prev_slot] == codepoint && self->reference_counts[prev_slot] > 0) { + return true; + } + if (self->codepoints[next_slot] == codepoint && self->reference_counts[next_slot] > 0) { + return true; + } + + return false; +} + +static uint16_t find_free_slot(lvfontio_ondiskfont_t *self, uint32_t codepoint) { + size_t offset = codepoint % self->max_glyphs; + + // First look for completely unused slots, starting at the offset + for (uint16_t i = 0; i < self->max_glyphs; i++) { + int16_t slot = (i + offset) % self->max_glyphs; + if (self->codepoints[slot] == LVFONTIO_INVALID_CODEPOINT && self->reference_counts[slot] == 0) { + return slot; + } + } + + // If none found, look for slots with zero reference count, starting at the offset. + // Avoid reusing one half of an active full-width glyph pair. + for (uint16_t i = 0; i < self->max_glyphs; i++) { + int16_t slot = (i + offset) % self->max_glyphs; + if (self->reference_counts[slot] == 0 && !slot_has_active_full_width_partner(self, slot)) { + return slot; + } + } + + // No slots available + return UINT16_MAX; +} + +static FRESULT read_glyph_dimensions(FIL *file, lvfontio_ondiskfont_t *self, + uint32_t *advance_width, int32_t *bbox_x, int32_t *bbox_y, + uint32_t *bbox_w, uint32_t *bbox_h, + uint8_t *byte_val, uint8_t *remaining_bits) { + FRESULT res; + uint32_t temp_value; + + // Read glyph_advance + res = read_bits(file, self->header.glyph_advance_bits, byte_val, remaining_bits, &temp_value); + if (res != FR_OK) { + return res; + } + *advance_width = temp_value; + + // Read bbox_x (signed) + res = read_bits(file, self->header.glyph_bbox_xy_bits, byte_val, remaining_bits, &temp_value); + if (res != FR_OK) { + return res; + } + // Convert to signed value if needed + if (temp_value & (1 << (self->header.glyph_bbox_xy_bits - 1))) { + *bbox_x = temp_value - (1 << self->header.glyph_bbox_xy_bits); + } else { + *bbox_x = temp_value; + } + + // Read bbox_y (signed) + res = read_bits(file, self->header.glyph_bbox_xy_bits, byte_val, remaining_bits, &temp_value); + if (res != FR_OK) { + return res; + } + // Convert to signed value if needed + if (temp_value & (1 << (self->header.glyph_bbox_xy_bits - 1))) { + *bbox_y = temp_value - (1 << self->header.glyph_bbox_xy_bits); + } else { + *bbox_y = temp_value; + } + + // Read bbox_w + res = read_bits(file, self->header.glyph_bbox_wh_bits, byte_val, remaining_bits, &temp_value); + if (res != FR_OK) { + return res; + } + *bbox_w = temp_value; + + // Read bbox_h + res = read_bits(file, self->header.glyph_bbox_wh_bits, byte_val, remaining_bits, &temp_value); + if (res != FR_OK) { + return res; + } + *bbox_h = temp_value; + + return FR_OK; +} + +static FRESULT read_bits(FIL *file, size_t num_bits, uint8_t *byte_val, uint8_t *remaining_bits, uint32_t *result) { + FRESULT res = FR_OK; + UINT bytes_read; + + uint32_t value = 0; + // Bits will be lost when num_bits > 32. However, this is good for skipping bits. + size_t bits_needed = num_bits; + + while (bits_needed > 0) { + // If no bits remaining, read a new byte + if (*remaining_bits == 0) { + res = f_read(file, byte_val, 1, &bytes_read); + if (res != FR_OK || bytes_read < 1) { + return FR_DISK_ERR; + } + *remaining_bits = 8; + } + + // Calculate how many bits to take from current byte + uint8_t bits_to_take = (*remaining_bits < bits_needed) ? *remaining_bits : bits_needed; + value = (value << bits_to_take) | (*byte_val >> (8 - bits_to_take)); + + // Update state + *remaining_bits -= bits_to_take; + bits_needed -= bits_to_take; + + // Shift byte for next read + *byte_val <<= bits_to_take; + *byte_val &= 0xFF; + } + + if (result != NULL) { + *result = value; + } + return FR_OK; +} diff --git a/shared-module/lvfontio/OnDiskFont.h b/shared-module/lvfontio/OnDiskFont.h new file mode 100644 index 0000000000000..db68126e9f459 --- /dev/null +++ b/shared-module/lvfontio/OnDiskFont.h @@ -0,0 +1,75 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" +#include "shared-module/displayio/Bitmap.h" + +#include "lib/oofatfs/ff.h" + +#define LVFONTIO_INVALID_CODEPOINT 0xFFFFFFFF + +// LV Font header information +typedef struct { + // Font size and metrics + uint16_t font_size; + uint16_t ascent; + uint16_t default_advance_width; + + // Encoding formats + uint8_t index_to_loc_format; + uint8_t bits_per_pixel; + uint8_t glyph_bbox_xy_bits; + uint8_t glyph_bbox_wh_bits; + uint8_t glyph_advance_bits; + + // Calculated values + uint8_t glyph_header_bits; + uint8_t glyph_header_bytes; +} lvfontio_header_t; + +// Mapping of codepoint ranges to glyph IDs +typedef struct { + uint32_t range_start; // Start of codepoint range + uint32_t range_end; // End of codepoint range (exclusive) + uint16_t glyph_offset; // Offset to apply to codepoint + uint8_t format_type; // Format type: 0=sparse mapping, 2=range to range, 3=direct mapping + uint16_t entries_count; // Number of entries in sparse data + uint32_t data_offset; // File offset to the cmap data +} lvfontio_cmap_range_t; + +typedef struct { + mp_obj_base_t base; + // Bitmap containing cached glyphs + displayio_bitmap_t *bitmap; + // Source of font file path (either a const char* or a copied string) + const char *file_path; + // Array mapping glyph indices to codepoints + uint32_t *codepoints; + // Array of reference counts for each glyph slot + uint16_t *reference_counts; // Use uint16_t to handle higher reference counts + // Maximum number of glyphs to cache at once + uint16_t max_glyphs; + // Flag indicating whether to use m_malloc (true) or port_malloc (false) + bool use_gc_allocator; + uint8_t half_width_px; + + FIL file; + bool file_is_open; + + // Font metrics information loaded from file + lvfontio_header_t header; + + // CMAP information + lvfontio_cmap_range_t *cmap_ranges; + uint16_t cmap_range_count; + + // Offsets for tables in the file + uint32_t loca_table_offset; + uint32_t glyf_table_offset; + uint32_t max_cid; +} lvfontio_ondiskfont_t; diff --git a/shared-module/lvfontio/__init__.c b/shared-module/lvfontio/__init__.c new file mode 100644 index 0000000000000..d0eee6d0a521a --- /dev/null +++ b/shared-module/lvfontio/__init__.c @@ -0,0 +1,5 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2024 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT diff --git a/shared-module/max3421e/Max3421E.c b/shared-module/max3421e/Max3421E.c index 4946e4e7d8dfa..3448cdd4c7596 100644 --- a/shared-module/max3421e/Max3421E.c +++ b/shared-module/max3421e/Max3421E.c @@ -83,7 +83,7 @@ void common_hal_max3421e_max3421e_deinit(max3421e_max3421e_obj_t *self) { // anyway. Don't run background tasks because this function is used by // tuh_task() which is run as a background task. #if CFG_TUSB_OS == OPT_OS_NONE -void osal_task_delay(uint32_t msec) { +void tusb_time_delay_ms_api(uint32_t msec) { uint32_t end_time = common_hal_time_monotonic_ms() + msec; while (common_hal_time_monotonic_ms() < end_time) { if (tuh_callback.prev != NULL) { diff --git a/shared-module/msgpack/__init__.c b/shared-module/msgpack/__init__.c index a98fb02de39dd..7c3e664bb6c1e 100644 --- a/shared-module/msgpack/__init__.c +++ b/shared-module/msgpack/__init__.c @@ -394,7 +394,9 @@ static mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { size_t len = code & 0b1111; mp_obj_dict_t *d = MP_OBJ_TO_PTR(mp_obj_new_dict(len)); for (size_t i = 0; i < len; i++) { - mp_obj_dict_store(d, unpack(s, ext_hook, use_list), unpack(s, ext_hook, use_list)); + mp_obj_t key = unpack(s, ext_hook, use_list); + mp_obj_t value = unpack(s, ext_hook, use_list); + mp_obj_dict_store(d, key, value); } return MP_OBJ_FROM_PTR(d); } @@ -462,7 +464,9 @@ static mp_obj_t unpack(msgpack_stream_t *s, mp_obj_t ext_hook, bool use_list) { size_t len = read_size(s, code - 0xde + 1); mp_obj_dict_t *d = MP_OBJ_TO_PTR(mp_obj_new_dict(len)); for (size_t i = 0; i < len; i++) { - mp_obj_dict_store(d, unpack(s, ext_hook, use_list), unpack(s, ext_hook, use_list)); + mp_obj_t key = unpack(s, ext_hook, use_list); + mp_obj_t value = unpack(s, ext_hook, use_list); + mp_obj_dict_store(d, key, value); } return MP_OBJ_FROM_PTR(d); } diff --git a/shared-module/os/__init__.c b/shared-module/os/__init__.c index 81296db854cd3..3a9c0e31f8edf 100644 --- a/shared-module/os/__init__.c +++ b/shared-module/os/__init__.c @@ -6,6 +6,7 @@ // // SPDX-License-Identifier: MIT +#include #include #include "extmod/vfs.h" @@ -16,8 +17,12 @@ #include "py/runtime.h" #include "shared-bindings/os/__init__.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + // This provides all VFS related OS functions so that ports can share the code -// as needed. It does not provide uname. +// as needed. // Version of mp_vfs_lookup_path that takes and returns uPy string objects. static mp_vfs_mount_t *lookup_path(const char *path, mp_obj_t *path_out) { @@ -63,9 +68,80 @@ static mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_ return mp_call_method_n_kw(n_args, 0, meth); } +const char *common_hal_os_path_abspath(const char *path) { + const char *cwd; + if (path[0] == '/') { + cwd = ""; + } else { + cwd = MP_STATE_VM(cwd_path); + if (cwd == NULL) { + char *new_cwd = m_malloc_without_collect(2); + strcpy(new_cwd, "/"); + MP_STATE_VM(cwd_path) = new_cwd; + cwd = new_cwd; + } + } + + // Store the current output length for previous components so we can rewind to before them. + char *full_path = m_malloc_without_collect(strlen(cwd) + strlen(path) + 2); + size_t full_path_len = 0; + memcpy(full_path, cwd, strlen(cwd)); + full_path_len += strlen(cwd); + if (full_path_len > 0 && full_path[full_path_len - 1] != '/') { + full_path[full_path_len++] = '/'; + } + memcpy(full_path + full_path_len, path, strlen(path) + 1); + + // Scan to see if the path has any `..` in it and return the same string if it doesn't + bool found_dot_dot = false; + size_t slash_count = 0; + for (size_t i = 0; i < strlen(full_path); i++) { + if (full_path[i] == '/') { + slash_count++; + } + if (i + 2 < strlen(full_path) && full_path[i] == '/' && full_path[i + 1] == '.' && full_path[i + 2] == '.' && (i + 3 == strlen(full_path) || full_path[i + 3] == '/')) { + found_dot_dot = true; + } + } + if (!found_dot_dot) { + return full_path; + } + + size_t slashes[slash_count]; + size_t output_len = 0; + size_t component_len = 0; + slash_count = 0; + + // Remove `..` and `.` + size_t original_len = strlen(full_path); + for (size_t i = 0; i <= original_len; i++) { + full_path[output_len++] = full_path[i]; + // Treat the final nul character as a slash. + if (full_path[i] == '/' || full_path[i] == '\0') { + if (component_len == 1 && full_path[i - 1] == '.') { + // Remove the dot + output_len = slashes[slash_count - 1]; + } else if (component_len == 2 && full_path[i - 1] == '.' && full_path[i - 2] == '.') { + // Remove the double dot and the previous component if it exists + slash_count--; + output_len = slashes[slash_count - 1]; + } else { + slashes[slash_count] = output_len; + slash_count++; + } + component_len = 0; + } else { + component_len++; + } + } + full_path[output_len] = '\0'; + return full_path; +} + void common_hal_os_chdir(const char *path) { + MP_STATE_VM(cwd_path) = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(MP_STATE_VM(cwd_path), &path_out); MP_STATE_VM(vfs_cur) = vfs; if (vfs == MP_VFS_ROOT) { // If we change to the root dir and a VFS is mounted at the root then @@ -84,27 +160,30 @@ void common_hal_os_chdir(const char *path) { } mp_obj_t common_hal_os_getcwd(void) { - return mp_vfs_getcwd(); + const char *cwd = MP_STATE_VM(cwd_path); + if (cwd == NULL) { + return MP_OBJ_NEW_QSTR(MP_QSTR__slash_); + } + return mp_obj_new_str_of_type(&mp_type_str, (const byte *)cwd, strlen(cwd)); } mp_obj_t common_hal_os_listdir(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); - - mp_vfs_ilistdir_it_t iter; - mp_obj_t iter_obj = MP_OBJ_FROM_PTR(&iter); - + mp_vfs_mount_t *vfs = lookup_dir_path(abspath, &path_out); if (vfs == MP_VFS_ROOT) { - // list the root directory - iter.base.type = &mp_type_polymorph_iter; - iter.iternext = mp_vfs_ilistdir_it_iternext; - iter.cur.vfs = MP_STATE_VM(vfs_mount_table); - iter.is_str = true; - iter.is_iter = false; - } else { - iter_obj = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out); + vfs = MP_STATE_VM(vfs_mount_table); + while (vfs != NULL) { + if (vfs->len == 1) { + break; + } + vfs = vfs->next; + } + path_out = MP_OBJ_NEW_QSTR(MP_QSTR__slash_); } + mp_obj_t iter_obj = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out); + mp_obj_t dir_list = mp_obj_new_list(0, NULL); mp_obj_t next; while ((next = mp_iternext(iter_obj)) != MP_OBJ_STOP_ITERATION) { @@ -116,8 +195,9 @@ mp_obj_t common_hal_os_listdir(const char *path) { } void common_hal_os_mkdir(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(abspath, &path_out); if (vfs == MP_VFS_ROOT || (vfs != MP_VFS_NONE && !strcmp(mp_obj_str_get_str(path_out), "/"))) { mp_raise_OSError(MP_EEXIST); } @@ -125,8 +205,9 @@ void common_hal_os_mkdir(const char *path) { } void common_hal_os_remove(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_path(abspath, &path_out); mp_vfs_proxy_call(vfs, MP_QSTR_remove, 1, &path_out); } @@ -142,14 +223,16 @@ void common_hal_os_rename(const char *old_path, const char *new_path) { } void common_hal_os_rmdir(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_dir_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_dir_path(abspath, &path_out); mp_vfs_proxy_call(vfs, MP_QSTR_rmdir, 1, &path_out); } mp_obj_t common_hal_os_stat(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_path(abspath, &path_out); if (vfs == MP_VFS_ROOT) { mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL)); t->items[0] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); // st_mode @@ -162,8 +245,9 @@ mp_obj_t common_hal_os_stat(const char *path) { } mp_obj_t common_hal_os_statvfs(const char *path) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t path_out; - mp_vfs_mount_t *vfs = lookup_path(path, &path_out); + mp_vfs_mount_t *vfs = lookup_path(abspath, &path_out); if (vfs == MP_VFS_ROOT) { // statvfs called on the root directory, see if there's anything mounted there for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) { @@ -194,8 +278,24 @@ mp_obj_t common_hal_os_statvfs(const char *path) { } void common_hal_os_utime(const char *path, mp_obj_t times) { + const char *abspath = common_hal_os_path_abspath(path); mp_obj_t args[2]; - mp_vfs_mount_t *vfs = lookup_path(path, &args[0]); + mp_vfs_mount_t *vfs = lookup_path(abspath, &args[0]); args[1] = times; mp_vfs_proxy_call(vfs, MP_QSTR_utime, 2, args); } + +#if CIRCUITPY_SETTINGS_TOML +mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { + vstr_t vstr; + vstr_init(&vstr, 64); + + settings_err_t result = settings_get_raw_vstr(key, &vstr); + if (result == SETTINGS_OK) { + return mp_obj_new_str_from_vstr(&vstr); + } + return default_; +} +#endif + +MP_REGISTER_ROOT_POINTER(const char *cwd_path); diff --git a/shared-module/os/__init__.h b/shared-module/os/__init__.h index be9c077b2006f..830f762950975 100644 --- a/shared-module/os/__init__.h +++ b/shared-module/os/__init__.h @@ -6,23 +6,5 @@ #pragma once -typedef enum { - GETENV_OK = 0, - GETENV_ERR_OPEN, - GETENV_ERR_UNICODE, - GETENV_ERR_LENGTH, - GETENV_ERR_NOT_FOUND, - GETENV_ERR_UNEXPECTED = 0xff00, // logical or'd with the byte value -} os_getenv_err_t; - -// Allocation free version that returns the full length of the value. -// If it fits, the return value is 0-terminated. The passed in buffer -// may be modified even if an error is returned. Allocation free. -// An error that is not 'open' or 'not found' is printed on the repl. -os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len); - -// Returns GETENV_OK and sets value to the read value. Returns -// GETENV_ERR_... if the value was not numeric. allocation-free. -// If any error code is returned, value is guaranteed not modified -// An error that is not 'open' or 'not found' is printed on the repl. -os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value); +// Not made available to the VM but used by other modules to normalize paths. +const char *common_hal_os_path_abspath(const char *path); diff --git a/shared-module/os/getenv.c b/shared-module/os/getenv.c deleted file mode 100644 index 39c3b4cee4ac7..0000000000000 --- a/shared-module/os/getenv.c +++ /dev/null @@ -1,414 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries -// -// SPDX-License-Identifier: MIT - -// These functions are separate from __init__.c so that os.getenv() can be -// tested in the unix "coverage" build, without bringing in "our" os module - -#include -#include -#include - -#include "shared-bindings/os/__init__.h" -#include "shared-module/os/__init__.h" - -#include "py/gc.h" -#include "py/misc.h" -#include "py/mpstate.h" -#include "py/mpprint.h" -#include "py/objstr.h" -#include "py/parsenum.h" -#include "py/runtime.h" -#include "supervisor/filesystem.h" - -#define GETENV_PATH "/settings.toml" - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -typedef FIL file_arg; -static bool open_file(const char *name, file_arg *active_file) { - #if defined(UNIX) - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_obj_t file_obj = mp_call_function_2(MP_OBJ_FROM_PTR(&mp_builtin_open_obj), mp_obj_new_str(name, strlen(name)), MP_ROM_QSTR(MP_QSTR_rb)); - mp_arg_validate_type(file_obj, &mp_type_vfs_fat_fileio, MP_QSTR_file); - pyb_file_obj_t *file = MP_OBJ_TO_PTR(file_obj); - *active_file = file->fp; - nlr_pop(); - return true; - } else { - return false; - } - #else - fs_user_mount_t *fs_mount = filesystem_circuitpy(); - if (fs_mount == NULL) { - return false; - } - FATFS *fatfs = &fs_mount->fatfs; - FRESULT result = f_open(fatfs, active_file, name, FA_READ); - return result == FR_OK; - #endif -} -static void close_file(file_arg *active_file) { - // nothing -} -static bool is_eof(file_arg *active_file) { - return f_eof(active_file) || f_error(active_file); -} - -// Return 0 if there is no next character (EOF). -static uint8_t get_next_byte(FIL *active_file) { - uint8_t character = 0; - UINT quantity_read; - // If there's an error or quantity_read is 0, character will remain 0. - f_read(active_file, &character, 1, &quantity_read); - return character; -} -static void seek_eof(file_arg *active_file) { - f_lseek(active_file, f_size(active_file)); -} - -// For a fixed buffer, record the required size rather than throwing -static void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { - if (!vstr->fixed_buf || vstr->alloc > vstr->len) { - vstr_add_byte(vstr, b); - } else { - vstr->len++; - } -} - -// For a fixed buffer, record the required size rather than throwing -static void vstr_add_char_nonstd(vstr_t *vstr, unichar c) { - size_t ulen = - (c < 0x80) ? 1 : - (c < 0x800) ? 2 : - (c < 0x10000) ? 3 : 4; - if (!vstr->fixed_buf || vstr->alloc > vstr->len + ulen) { - vstr_add_char(vstr, c); - } else { - vstr->len += ulen; - } -} - -static void next_line(file_arg *active_file) { - uint8_t character; - do { - character = get_next_byte(active_file); - } while (character != 0 && character != '\n'); -} - -// Discard whitespace, except for newlines, returning the next character after the whitespace. -// Return 0 if there is no next character (EOF). -static uint8_t consume_whitespace(file_arg *active_file) { - uint8_t character; - do { - character = get_next_byte(active_file); - } while (character != '\n' && character != 0 && unichar_isspace(character)); - return character; -} - -// Starting at the start of a new line, determines if the key matches the given -// key. -// -// If result is true, the key matches and file pointer is pointing just after the "=". -// If the result is false, the key does NOT match and the file pointer is -// pointing at the start of the next line, if any -static bool key_matches(file_arg *active_file, const char *key) { - uint8_t character; - character = consume_whitespace(active_file); - if (character == '[' || character == 0) { - seek_eof(active_file); - return false; - } - while (*key) { - if (character != *key++) { - // A character didn't match the key, so it's not a match - // If the non-matching char was not the end of the line, - // then consume the rest of the line - if (character != '\n') { - next_line(active_file); - } - return false; - } - character = get_next_byte(active_file); - } - // the next character could be whitespace; consume if necessary - if (unichar_isspace(character)) { - character = consume_whitespace(active_file); - } - // If we're not looking at the "=" then the key didn't match - if (character != '=') { - // A character didn't match the key, so it's not a match - // If the non-matching char was not the end of the line, - // then consume the rest of the line - if (character != '\n') { - next_line(active_file); - } - return false; - } - return true; -} - -static os_getenv_err_t read_unicode_escape(file_arg *active_file, int sz, vstr_t *buf) { - char hex_buf[sz + 1]; - for (int i = 0; i < sz; i++) { - hex_buf[i] = get_next_byte(active_file); - } - hex_buf[sz] = 0; - char *end; - unsigned long c = strtoul(hex_buf, &end, 16); - if (end != &hex_buf[sz]) { - return GETENV_ERR_UNEXPECTED | *end; - } - if (c >= 0x110000) { - return GETENV_ERR_UNICODE; - } - vstr_add_char_nonstd(buf, c); - return GETENV_OK; -} - -// Read a quoted string -static os_getenv_err_t read_string_value(file_arg *active_file, vstr_t *buf) { - while (true) { - int character = get_next_byte(active_file); - switch (character) { - case 0: - case '\n': - return GETENV_ERR_UNEXPECTED | character; - - case '"': - character = consume_whitespace(active_file); - switch (character) { - case '#': - next_line(active_file); - MP_FALLTHROUGH; - case 0: - case '\n': - return GETENV_OK; - default: - return GETENV_ERR_UNEXPECTED | character; - } - - case '\\': - character = get_next_byte(active_file); - switch (character) { - case 0: - case '\n': - return GETENV_ERR_UNEXPECTED | character; - case 'b': - character = '\b'; - break; - case 'r': - character = '\r'; - break; - case 'n': - character = '\n'; - break; - case 't': - character = '\t'; - break; - case 'v': - character = '\v'; - break; - case 'f': - character = '\f'; - break; - case 'U': - case 'u': { - int sz = (character == 'u') ? 4 : 8; - os_getenv_err_t res; - res = read_unicode_escape(active_file, sz, buf); - if (res != GETENV_OK) { - return res; - } - continue; - } - // default falls through, other escaped characters - // represent themselves - } - MP_FALLTHROUGH; - default: - vstr_add_byte_nonstd(buf, character); - } - } -} - -// Read a numeric value (non-quoted value) as a string -static os_getenv_err_t read_bare_value(file_arg *active_file, vstr_t *buf, int first_character) { - int character = first_character; - while (true) { - switch (character) { - case 0: - case '\n': - return GETENV_OK; - case '#': - next_line(active_file); - return GETENV_OK; - default: - vstr_add_byte_nonstd(buf, character); - } - character = get_next_byte(active_file); - } -} - -static mp_int_t read_value(file_arg *active_file, vstr_t *buf, bool *quoted) { - uint8_t character; - character = consume_whitespace(active_file); - *quoted = (character == '"'); - - if (*quoted) { - return read_string_value(active_file, buf); - } else { - return read_bare_value(active_file, buf, character); - } -} - -static os_getenv_err_t os_getenv_vstr(const char *path, const char *key, vstr_t *buf, bool *quoted) { - file_arg active_file; - if (!open_file(path, &active_file)) { - return GETENV_ERR_OPEN; - } - - os_getenv_err_t result = GETENV_ERR_NOT_FOUND; - while (!is_eof(&active_file)) { - if (key_matches(&active_file, key)) { - result = read_value(&active_file, buf, quoted); - break; - } - } - close_file(&active_file); - return result; -} - -static os_getenv_err_t os_getenv_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { - vstr_t buf; - vstr_init_fixed_buf(&buf, value_len, value); - os_getenv_err_t result = os_getenv_vstr(GETENV_PATH, key, &buf, quoted); - - if (result == GETENV_OK) { - vstr_add_byte_nonstd(&buf, 0); - memcpy(value, buf.buf, MIN(buf.len, value_len)); - if (buf.len > value_len) { // this length includes trailing NUL - result = GETENV_ERR_LENGTH; - } - } - return result; -} - -static void print_dont_raise(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...) { - va_list argptr; - va_start(argptr, fmt); - mp_vcprintf(&mp_plat_print, fmt, argptr); - mp_printf(&mp_plat_print, "\n"); - va_end(argptr); -} - -static void handle_getenv_error(os_getenv_err_t error, void (*handle)(const mp_obj_type_t *exc_type, mp_rom_error_text_t fmt, ...)) { - if (error == GETENV_OK) { - return; - } - if (error & GETENV_ERR_UNEXPECTED) { - byte character = (error & 0xff); - char buf[8]; - vstr_t vstr; - vstr_init_fixed_buf(&vstr, sizeof(buf), buf); - mp_print_t print = { .data = &vstr, .print_strn = (mp_print_strn_t)vstr_add_strn }; - - if (character) { - mp_str_print_quoted(&print, &character, 1, true); - } else { - mp_str_print_quoted(&print, (byte *)"EOF", 3, true); - } - handle(&mp_type_ValueError, MP_ERROR_TEXT("Invalid byte %.*s"), vstr.len, vstr.buf); - } else { - switch (error) { - case GETENV_ERR_OPEN: - handle(&mp_type_ValueError, MP_ERROR_TEXT("%S"), MP_ERROR_TEXT("File not found")); - break; - case GETENV_ERR_UNICODE: - handle(&mp_type_ValueError, MP_ERROR_TEXT("%S"), MP_ERROR_TEXT("Invalid unicode escape")); - break; - case GETENV_ERR_NOT_FOUND: - handle(&mp_type_ValueError, MP_ERROR_TEXT("%S"), MP_ERROR_TEXT("Key not found")); - break; - default: - handle(&mp_type_RuntimeError, MP_ERROR_TEXT("%S"), MP_ERROR_TEXT("Internal error")); - break; - } - } -} - -static void common_hal_os_getenv_showerr(const char *key, os_getenv_err_t result) { - if (result != GETENV_OK && result != GETENV_ERR_OPEN && result != GETENV_ERR_NOT_FOUND) { - mp_cprintf(&mp_plat_print, MP_ERROR_TEXT("An error occurred while retrieving '%s':\n"), key); - handle_getenv_error(result, print_dont_raise); - } -} - -static -os_getenv_err_t common_hal_os_getenv_str_inner(const char *key, char *value, size_t value_len) { - bool quoted; - os_getenv_err_t result = os_getenv_buf_terminated(key, value, value_len, "ed); - if (result == GETENV_OK && !quoted) { - result = GETENV_ERR_UNEXPECTED | value[0]; - } - return result; -} - -os_getenv_err_t common_hal_os_getenv_str(const char *key, char *value, size_t value_len) { - os_getenv_err_t result = common_hal_os_getenv_str_inner(key, value, value_len); - common_hal_os_getenv_showerr(key, result); - return result; -} - -mp_obj_t common_hal_os_getenv_path(const char *path, const char *key, mp_obj_t default_) { - vstr_t buf; - bool quoted; - - vstr_init(&buf, 64); - os_getenv_err_t result = os_getenv_vstr(path, key, &buf, "ed); - if (result == GETENV_ERR_NOT_FOUND || result == GETENV_ERR_OPEN) { - return default_; - } - handle_getenv_error(result, mp_raise_msg_varg); - - if (quoted) { - return mp_obj_new_str_from_vstr(&buf); - } else { - return mp_parse_num_integer(buf.buf, buf.len, 0, NULL); - } -} - -mp_obj_t common_hal_os_getenv(const char *key, mp_obj_t default_) { - return common_hal_os_getenv_path(GETENV_PATH, key, default_); -} - -static os_getenv_err_t common_hal_os_getenv_int_inner(const char *key, mp_int_t *value) { - char buf[16]; - bool quoted; - os_getenv_err_t result = os_getenv_buf_terminated(key, buf, sizeof(buf), "ed); - if (result != GETENV_OK) { - return result; - } - if (quoted) { - return GETENV_ERR_UNEXPECTED | '"'; - } - char *end; - long num = strtol(buf, &end, 0); - while (unichar_isspace(*end)) { - end++; - } - if (end == buf || *end) { // If the whole buffer was not consumed it's an error - return GETENV_ERR_UNEXPECTED | *end; - } - *value = (mp_int_t)num; - return GETENV_OK; -} - -os_getenv_err_t common_hal_os_getenv_int(const char *key, mp_int_t *value) { - os_getenv_err_t result = common_hal_os_getenv_int_inner(key, value); - common_hal_os_getenv_showerr(key, result); - return result; -} diff --git a/shared-module/sdcardio/SDCard.c b/shared-module/sdcardio/SDCard.c index 86a4f587b8eba..5d3c021f27ed4 100644 --- a/shared-module/sdcardio/SDCard.c +++ b/shared-module/sdcardio/SDCard.c @@ -7,15 +7,16 @@ // This implementation largely follows the structure of adafruit_sdcard.py #include "extmod/vfs.h" - #include "shared-bindings/busio/SPI.h" #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/sdcardio/SDCard.h" #include "shared-bindings/time/__init__.h" #include "shared-bindings/util.h" #include "shared-module/sdcardio/SDCard.h" +#include "supervisor/shared/tick.h" #include "py/mperrno.h" +#include "py/mphal.h" #if 0 #define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print,##__VA_ARGS__)) @@ -23,7 +24,15 @@ #define DEBUG_PRINT(...) ((void)0) #endif -#define CMD_TIMEOUT (200) +// https://nodeloop.org/guides/sd-card-spi-init-guide/ is an excellent source of info for SPI card use. + +// https://www.taterli.com/wp-content/uploads/2017/05/Physical-Layer-Simplified-SpecificationV6.0.pdf +// specifies timeouts for read (100 ms), write (250 ms), erase (depends on size), and other operations. +#define CMD_TIMEOUT_MS (250) +#define SPI_TIMEOUT_MS (250) +// Init ready timeout. +#define READY_TIMEOUT_MS (300) + #define R1_IDLE_STATE (1 << 0) #define R1_ILLEGAL_COMMAND (1 << 2) @@ -32,18 +41,40 @@ #define TOKEN_STOP_TRAN (0xFD) #define TOKEN_DATA (0xFE) +bool common_hal_sdcardio_sdcard_deinited(sdcardio_sdcard_obj_t *self) { + // Also check SPI bus was deinited out from under us. + if (!self->bus || common_hal_busio_spi_deinited(self->bus)) { + return true; + } + return false; +} + +void common_hal_sdcardio_sdcard_mark_deinit(sdcardio_sdcard_obj_t *self) { + self->bus = NULL; +} + static void common_hal_sdcardio_check_for_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->bus) { + if (common_hal_sdcardio_sdcard_deinited(self)) { raise_deinited_error(); } } static bool lock_and_configure_bus(sdcardio_sdcard_obj_t *self) { - common_hal_sdcardio_check_for_deinit(self); + if (common_hal_sdcardio_sdcard_deinited(self)) { + return false; + } + + if (!common_hal_busio_spi_wait_for_lock(self->bus, SPI_TIMEOUT_MS)) { + return false; + } - if (!common_hal_busio_spi_try_lock(self->bus)) { + // Make sure we can still use the SPI bus after grabbing the lock. + // The VM might be in the process of shutting down, and there could be a race. + if (!vm_is_running() && !self->persistent_mount) { + common_hal_busio_spi_unlock(self->bus); return false; } + common_hal_busio_spi_configure(self->bus, self->baudrate, 0, 0, 8); common_hal_digitalio_digitalinout_set_value(&self->cs, false); return true; @@ -56,11 +87,10 @@ static void lock_bus_or_throw(sdcardio_sdcard_obj_t *self) { } static void clock_card(sdcardio_sdcard_obj_t *self, int bytes) { - uint8_t buf[] = {0xff}; + uint8_t buf[bytes]; + memset(buf, 0xff, bytes); common_hal_digitalio_digitalinout_set_value(&self->cs, true); - for (int i = 0; i < bytes; i++) { - common_hal_busio_spi_write(self->bus, buf, 1); - } + common_hal_busio_spi_write(self->bus, buf, bytes); } static void extraclock_and_unlock_bus(sdcardio_sdcard_obj_t *self) { @@ -83,21 +113,35 @@ static uint8_t CRC7(const uint8_t *data, uint8_t n) { return (crc << 1) | 1; } -#define READY_TIMEOUT_NS (300 * 1000 * 1000) // 300ms -static int wait_for_ready(sdcardio_sdcard_obj_t *self) { - uint64_t deadline = common_hal_time_monotonic_ns() + READY_TIMEOUT_NS; - while (common_hal_time_monotonic_ns() < deadline) { +// Assumes that the spi lock has been acquired. +// +// Mask the incoming value with mask. Use 0xff to not mask. +// if not_match is true, wait for something NOT matching the value. +// Return the response as an int32_t (which is always >= 0), or -1 if timed out. +static int32_t wait_for_masked_response(sdcardio_sdcard_obj_t *self, uint8_t mask, uint8_t response, bool not_match, uint32_t timeout_ms) { + uint64_t deadline = supervisor_ticks_ms64() + timeout_ms; + while (supervisor_ticks_ms64() < deadline) { uint8_t b; common_hal_busio_spi_read(self->bus, &b, 1, 0xff); - if (b == 0xff) { - return 0; + if (((b & mask) == response) ^ not_match) { + return b; } } - return -ETIMEDOUT; + return -1; +} + +// Wait for the given response byte. +static bool wait_for_response(sdcardio_sdcard_obj_t *self, uint8_t response) { + return wait_for_masked_response(self, 0xff, response, false, CMD_TIMEOUT_MS) != -1; +} + +// Wait for 0xff, with a specific timeout. +static bool wait_for_ready(sdcardio_sdcard_obj_t *self) { + return wait_for_masked_response(self, 0xff, 0xff, false, READY_TIMEOUT_MS) != -1; } // Note: this is never called while "in cmd25" (in fact, it's only used by `exit_cmd25`) -static bool cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { +static mp_negative_errno_t cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { uint8_t cmdbuf[2] = {cmd, 0xff}; assert(!self->in_cmd25); @@ -105,17 +149,14 @@ static bool cmd_nodata(sdcardio_sdcard_obj_t *self, int cmd, int response) { common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); // Wait for the response (response[7] == response) - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if (cmdbuf[0] == response) { - return 0; - } + if (wait_for_response(self, response)) { + return 0; } - return -EIO; + return -MP_EIO; } -static int exit_cmd25(sdcardio_sdcard_obj_t *self) { +static mp_negative_errno_t exit_cmd25(sdcardio_sdcard_obj_t *self) { if (self->in_cmd25) { DEBUG_PRINT("exit cmd25\n"); self->in_cmd25 = false; @@ -126,7 +167,7 @@ static int exit_cmd25(sdcardio_sdcard_obj_t *self) { // In Python API, defaults are response=None, data_block=True, wait=True static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf, size_t response_len, bool data_block, bool wait) { - int r = exit_cmd25(self); + mp_negative_errno_t r = exit_cmd25(self); if (r < 0) { return r; } @@ -141,48 +182,43 @@ static int cmd(sdcardio_sdcard_obj_t *self, int cmd, int arg, void *response_buf cmdbuf[5] = CRC7(cmdbuf, 5); if (wait) { - r = wait_for_ready(self); - if (r < 0) { - return r; + if (!wait_for_ready(self)) { + return -MP_ETIMEDOUT; } } common_hal_busio_spi_write(self->bus, cmdbuf, sizeof(cmdbuf)); // Wait for the response (response[7] == 0) - bool response_received = false; - for (int i = 0; i < CMD_TIMEOUT; i++) { - common_hal_busio_spi_read(self->bus, cmdbuf, 1, 0xff); - if ((cmdbuf[0] & 0x80) == 0) { - response_received = true; - break; - } - } - - if (!response_received) { - return -EIO; + // Now wait for cmd response, which is the high bit being 0. + int32_t response = wait_for_masked_response(self, 0x80, 0, false, CMD_TIMEOUT_MS); + if (response == -1) { + return -MP_EIO; } if (response_buf) { if (data_block) { cmdbuf[1] = 0xff; - do { - // Wait for the start block byte - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 1, 0xff); - } while (cmdbuf[1] != 0xfe); + if (!wait_for_response(self, 0xfe)) { + return -MP_EIO; + } } - common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff); + if (!common_hal_busio_spi_read(self->bus, response_buf, response_len, 0xff)) { + return -MP_EIO; + } if (data_block) { // Read and discard the CRC-CCITT checksum - common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff); + if (!common_hal_busio_spi_read(self->bus, cmdbuf + 1, 2, 0xff)) { + return -MP_EIO; + } } } - return cmdbuf[0]; + return response; } static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *response_buf, size_t response_len, bool data_block, bool wait) { @@ -190,7 +226,8 @@ static int block_cmd(sdcardio_sdcard_obj_t *self, int cmd_, int block, void *res } static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { if (cmd(self, 41, 0, NULL, 0, true, true) == 0) { return NULL; } @@ -199,7 +236,8 @@ static mp_rom_error_text_t init_card_v1(sdcardio_sdcard_obj_t *self) { } static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { uint8_t ocr[4]; common_hal_time_delay_ms(50); cmd(self, 58, 0, ocr, sizeof(ocr), false, true); @@ -216,6 +254,8 @@ static mp_rom_error_text_t init_card_v2(sdcardio_sdcard_obj_t *self) { } static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { + // https://nodeloop.org/guides/sd-card-spi-init-guide/ recommends at least 74 bit clocks + // and says 80 bit clocks(10*8) is common. Value below is bytes, not bits. clock_card(self, 10); common_hal_digitalio_digitalinout_set_value(&self->cs, false); @@ -294,13 +334,16 @@ static mp_rom_error_text_t init_card(sdcardio_sdcard_obj_t *self) { return NULL; } -void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate, bool persistent_mount) { self->bus = bus; + self->persistent_mount = persistent_mount; common_hal_digitalio_digitalinout_construct(&self->cs, cs); common_hal_digitalio_digitalinout_switch_to_output(&self->cs, true, DRIVE_MODE_PUSH_PULL); self->cdv = 512; self->sectors = 0; + + // During initialization, talk to the SPI card between 100 khZ and 400 kHz. After that, can use full speed. self->baudrate = 250000; lock_bus_or_throw(self); @@ -309,18 +352,28 @@ void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi if (result != NULL) { common_hal_digitalio_digitalinout_deinit(&self->cs); - mp_raise_OSError_msg(result); + return result; } self->baudrate = baudrate; + return NULL; +} + + +void common_hal_sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate) { + // User mounted, so persistent_mount=false. + mp_rom_error_text_t result = sdcardio_sdcard_construct(self, bus, cs, baudrate, false); + if (result != NULL) { + mp_raise_OSError_msg(result); + } } void common_hal_sdcardio_sdcard_deinit(sdcardio_sdcard_obj_t *self) { - if (!self->bus) { + if (common_hal_sdcardio_sdcard_deinited(self)) { return; } common_hal_sdcardio_sdcard_sync(self); - self->bus = 0; + common_hal_sdcardio_sdcard_mark_deinit(self); common_hal_digitalio_digitalinout_deinit(&self->cs); } @@ -330,23 +383,25 @@ int common_hal_sdcardio_sdcard_get_blockcount(sdcardio_sdcard_obj_t *self) { } static int readinto(sdcardio_sdcard_obj_t *self, void *buf, size_t size) { - uint8_t aux[2] = {0, 0}; - while (aux[0] != 0xfe) { - common_hal_busio_spi_read(self->bus, aux, 1, 0xff); + + if (!wait_for_response(self, 0xfe)) { + return -MP_EIO; } common_hal_busio_spi_read(self->bus, buf, size, 0xff); // Read checksum and throw it away - common_hal_busio_spi_read(self->bus, aux, sizeof(aux), 0xff); + uint8_t checksum[2]; + common_hal_busio_spi_read(self->bus, checksum, sizeof(checksum), 0xff); return 0; } +// The mp_uint_t is misleading; negative errors can be returned. mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t start_block, uint32_t nblocks) { // deinit check is in lock_and_configure_bus() sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; + return -MP_ETIMEDOUT; } int r = 0; size_t buflen = 512 * nblocks; @@ -379,19 +434,22 @@ mp_uint_t sdcardio_sdcard_readblocks(mp_obj_t self_in, uint8_t *buf, uint32_t st } } extraclock_and_unlock_bus(self); + // No caller actually uses this value. return r; } int common_hal_sdcardio_sdcard_readblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { if (buf->len % 512 != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } return sdcardio_sdcard_readblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); } static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t size) { - wait_for_ready(self); + if (!wait_for_ready(self)) { + return -MP_ETIMEDOUT; + } uint8_t cmd[2]; cmd[0] = token; @@ -414,12 +472,12 @@ static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t // with STATUS 010 indicating "data accepted", and other status bit // combinations indicating failure. // In practice, I was seeing cmd[0] as 0xe5, indicating success - for (int i = 0; i < CMD_TIMEOUT; i++) { + uint64_t deadline = supervisor_ticks_ms64() + CMD_TIMEOUT_MS; + while (supervisor_ticks_ms64() < deadline) { common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - DEBUG_PRINT("i=%02d cmd[0] = 0x%02x\n", i, cmd[0]); if ((cmd[0] & 0b00010001) == 0b00000001) { if ((cmd[0] & 0x1f) != 0x5) { - return -EIO; + return -MP_EIO; } else { break; } @@ -427,9 +485,11 @@ static int _write(sdcardio_sdcard_obj_t *self, uint8_t token, void *buf, size_t } // Wait for the write to finish - do { - common_hal_busio_spi_read(self->bus, cmd, 1, 0xff); - } while (cmd[0] == 0); + + // Wait for a non-zero value. + if (wait_for_masked_response(self, 0xff /*mask*/, 0, true /*not_match*/, CMD_TIMEOUT_MS) == -1) { + return -MP_EIO; + } // Success return 0; @@ -439,7 +499,7 @@ mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t s // deinit check is in lock_and_configure_bus() sdcardio_sdcard_obj_t *self = MP_OBJ_TO_PTR(self_in); if (!lock_and_configure_bus(self)) { - return MP_EAGAIN; + return -MP_ETIMEDOUT; } if (!self->in_cmd25 || start_block != self->next_block) { @@ -471,23 +531,21 @@ mp_uint_t sdcardio_sdcard_writeblocks(mp_obj_t self_in, uint8_t *buf, uint32_t s return 0; } -int common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { +mp_negative_errno_t common_hal_sdcardio_sdcard_sync(sdcardio_sdcard_obj_t *self) { // deinit check is in lock_and_configure_bus() - lock_and_configure_bus(self); + if (!lock_and_configure_bus(self)) { + return -MP_ETIMEDOUT; + } int r = exit_cmd25(self); extraclock_and_unlock_bus(self); return r; } -int common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { - // deinit check is in lock_and_configure_bus() +mp_negative_errno_t common_hal_sdcardio_sdcard_writeblocks(sdcardio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *buf) { if (buf->len % 512 != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("Buffer length must be a multiple of 512")); + mp_raise_ValueError_varg(MP_ERROR_TEXT("Buffer must be a multiple of %d bytes"), 512); } - lock_and_configure_bus(self); - int r = sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); - extraclock_and_unlock_bus(self); - return r; + return sdcardio_sdcard_writeblocks(MP_OBJ_FROM_PTR(self), buf->buf, start_block, buf->len / 512); } bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { @@ -495,11 +553,8 @@ bool sdcardio_sdcard_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *o *out_value = 0; switch (cmd) { case MP_BLOCKDEV_IOCTL_DEINIT: - common_hal_sdcardio_sdcard_sync(self); - break; // TODO properly case MP_BLOCKDEV_IOCTL_SYNC: - common_hal_sdcardio_sdcard_sync(self); - break; + return common_hal_sdcardio_sdcard_sync(self) == 0; case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: *out_value = common_hal_sdcardio_sdcard_get_blockcount(self); break; diff --git a/shared-module/sdcardio/SDCard.h b/shared-module/sdcardio/SDCard.h index 0b315395aadf0..35a9ed1bf3c12 100644 --- a/shared-module/sdcardio/SDCard.h +++ b/shared-module/sdcardio/SDCard.h @@ -23,4 +23,9 @@ typedef struct { uint32_t sectors; uint32_t next_block; bool in_cmd25; + // Automounted SD cards are usually persistent across VM's. Note this as needed to allow access + // when the VM is not running. + bool persistent_mount; } sdcardio_sdcard_obj_t; + +mp_rom_error_text_t sdcardio_sdcard_construct(sdcardio_sdcard_obj_t *self, busio_spi_obj_t *bus, const mcu_pin_obj_t *cs, int baudrate, bool persistent_mount); diff --git a/shared-module/sdcardio/__init__.c b/shared-module/sdcardio/__init__.c index 72d32ef2b2c5d..4a7a4d500cc3f 100644 --- a/shared-module/sdcardio/__init__.c +++ b/shared-module/sdcardio/__init__.c @@ -3,3 +3,125 @@ // SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC // // SPDX-License-Identifier: MIT + +#include "shared-module/sdcardio/__init__.h" + +#include "extmod/vfs_fat.h" + +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/sdcardio/SDCard.h" + +#include "supervisor/filesystem.h" + +#ifdef DEFAULT_SD_CARD_DETECT +static digitalio_digitalinout_obj_t sd_card_detect_pin; +static sdcardio_sdcard_obj_t sdcard; + +static mp_vfs_mount_t _sdcard_vfs; +fs_user_mount_t _sdcard_usermount; + +static bool _init_error = false; +static bool _automounted = false; + +#ifdef DEFAULT_SD_MOSI +static busio_spi_obj_t busio_spi_obj; +#else +#include "shared-bindings/board/__init__.h" +#endif +#endif + +void sdcardio_init(void) { + #ifdef DEFAULT_SD_CARD_DETECT + sd_card_detect_pin.base.type = &digitalio_digitalinout_type; + common_hal_digitalio_digitalinout_construct(&sd_card_detect_pin, DEFAULT_SD_CARD_DETECT); + common_hal_digitalio_digitalinout_switch_to_input(&sd_card_detect_pin, PULL_UP); + common_hal_digitalio_digitalinout_never_reset(&sd_card_detect_pin); + #endif +} + +void automount_sd_card(void) { + #ifdef DEFAULT_SD_CARD_DETECT + if (common_hal_digitalio_digitalinout_get_value(&sd_card_detect_pin) != DEFAULT_SD_CARD_INSERTED) { + // No card. + _init_error = false; + if (_automounted) { + // Unmount the card. + mp_vfs_mount_t *cur = MP_STATE_VM(vfs_mount_table); + if (cur == &_sdcard_vfs) { + MP_STATE_VM(vfs_mount_table) = cur->next; + } else { + while (cur->next != &_sdcard_vfs && cur != NULL) { + cur = cur->next; + } + if (cur != NULL) { + cur->next = _sdcard_vfs.next; + } + } + _sdcard_vfs.next = NULL; + + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(&busio_spi_obj); + #endif + _automounted = false; + } + return; + } else if (_init_error || _automounted) { + // We've already tried and failed to init the card, or it's still mounted. Don't try again. + return; + } + + busio_spi_obj_t *spi_obj; + #ifndef DEFAULT_SD_MOSI + spi_obj = MP_OBJ_TO_PTR(common_hal_board_create_spi(0)); + #else + spi_obj = &busio_spi_obj; + spi_obj->base.type = &busio_spi_type; + common_hal_busio_spi_construct(spi_obj, DEFAULT_SD_SCK, DEFAULT_SD_MOSI, DEFAULT_SD_MISO, false); + common_hal_busio_spi_never_reset(spi_obj); + #endif + sdcard.base.type = &sdcardio_SDCard_type; + mp_rom_error_text_t error = sdcardio_sdcard_construct(&sdcard, spi_obj, DEFAULT_SD_CS, 25000000, true); + if (error != NULL) { + // Failed to communicate with the card. + _automounted = false; + _init_error = true; + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(spi_obj); + #endif + return; + } + common_hal_digitalio_digitalinout_never_reset(&sdcard.cs); + + fs_user_mount_t *vfs = &_sdcard_usermount; + vfs->base.type = &mp_fat_vfs_type; + vfs->fatfs.drv = vfs; + + // Initialise underlying block device + vfs->blockdev.block_size = FF_MIN_SS; // default, will be populated by call to MP_BLOCKDEV_IOCTL_BLOCK_SIZE + mp_vfs_blockdev_init(&vfs->blockdev, &sdcard); + + // mount the block device so the VFS methods can be used + FRESULT res = f_mount(&vfs->fatfs); + if (res != FR_OK) { + _automounted = false; + _init_error = true; + common_hal_sdcardio_sdcard_deinit(&sdcard); + #ifdef DEFAULT_SD_MOSI + common_hal_busio_spi_deinit(spi_obj); + #endif + return; + } + + filesystem_set_concurrent_write_protection(vfs, true); + filesystem_set_writable_by_usb(vfs, false); + + mp_vfs_mount_t *sdcard_vfs = &_sdcard_vfs; + sdcard_vfs->str = "/sd"; + sdcard_vfs->len = 3; + sdcard_vfs->obj = MP_OBJ_FROM_PTR(&_sdcard_usermount); + sdcard_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = sdcard_vfs; + _automounted = true; + #endif // DEFAULT_SD_CARD_DETECT +} diff --git a/shared-module/sdcardio/__init__.h b/shared-module/sdcardio/__init__.h index c9069db9fd7d5..59b4cf892f29b 100644 --- a/shared-module/sdcardio/__init__.h +++ b/shared-module/sdcardio/__init__.h @@ -5,3 +5,6 @@ // SPDX-License-Identifier: MIT #pragma once + +void sdcardio_init(void); +void automount_sd_card(void); diff --git a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c index 3c6eaf065df72..8b9629b002f45 100644 --- a/shared-module/sharpdisplay/SharpMemoryFramebuffer.c +++ b/shared-module/sharpdisplay/SharpMemoryFramebuffer.c @@ -54,11 +54,7 @@ static bool common_hal_sharpdisplay_framebuffer_get_pixels_in_byte_share_row(sha } void common_hal_sharpdisplay_framebuffer_reset(sharpdisplay_framebuffer_obj_t *self) { - if (self->bus != &self->inline_bus - #if CIRCUITPY_BOARD_SPI - && !common_hal_board_is_spi(self->bus) - #endif - ) { + if (self->bus != &self->inline_bus && gc_ptr_on_heap(self->bus)) { memcpy(&self->inline_bus, self->bus, sizeof(busio_spi_obj_t)); self->bus = &self->inline_bus; } diff --git a/shared-module/ssl/SSLSocket.c b/shared-module/ssl/SSLSocket.c index 0b40bd663c7d2..fa1de8bb484aa 100644 --- a/shared-module/ssl/SSLSocket.c +++ b/shared-module/ssl/SSLSocket.c @@ -37,14 +37,14 @@ static void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) { (void)ctx; (void)level; - mp_printf(&mp_plat_print, "DBG:%s:%04d: %s\n", file, line, str); + mp_printf(&mp_plat_print, "DBG:%s:%04d: %s", file, line, str); } #define DEBUG_PRINT(fmt, ...) mp_printf(&mp_plat_print, "DBG:%s:%04d: " fmt "\n", __FILE__, __LINE__,##__VA_ARGS__) #else #define DEBUG_PRINT(...) do {} while (0) #endif -static NORETURN void mbedtls_raise_error(int err) { +static MP_NORETURN void mbedtls_raise_error(int err) { // _mbedtls_ssl_send and _mbedtls_ssl_recv (below) turn positive error codes from the // underlying socket into negative codes to pass them through mbedtls. Here we turn them // positive again so they get interpreted as the OSError they really are. The @@ -65,7 +65,7 @@ static NORETURN void mbedtls_raise_error(int err) { // Try to allocate memory for the message #define ERR_STR_MAX 80 // mbedtls_strerror truncates if it doesn't fit mp_obj_str_t *o_str = m_new_obj_maybe(mp_obj_str_t); - byte *o_str_buf = m_new_maybe(byte, ERR_STR_MAX); + byte *o_str_buf = m_malloc_without_collect(ERR_STR_MAX); if (o_str == NULL || o_str_buf == NULL) { mp_raise_OSError(err); } @@ -218,8 +218,7 @@ ssl_sslsocket_obj_t *common_hal_ssl_sslcontext_wrap_socket(ssl_sslcontext_obj_t mp_raise_RuntimeError(MP_ERROR_TEXT("Invalid socket for TLS")); } - ssl_sslsocket_obj_t *o = m_new_obj_with_finaliser(ssl_sslsocket_obj_t); - o->base.type = &ssl_sslsocket_type; + ssl_sslsocket_obj_t *o = mp_obj_malloc_with_finaliser(ssl_sslsocket_obj_t, &ssl_sslsocket_type); o->ssl_context = self; o->sock_obj = socket; o->poll_mask = 0; diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index 12486aff752f3..dedcee1ff23f5 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -26,47 +26,6 @@ #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC #include "tusb.h" -static const uint8_t usb_msc_descriptor_template[] = { - // MSC Interface Descriptor - 0x09, // 0 bLength - 0x04, // 1 bDescriptorType (Interface) - 0xFF, // 2 bInterfaceNumber [SET AT RUNTIME] -#define MSC_INTERFACE_INDEX (2) - 0x00, // 3 bAlternateSetting - 0x02, // 4 bNumEndpoints 2 - 0x08, // 5 bInterfaceClass: MSC - 0x06, // 6 bInterfaceSubClass: TRANSPARENT - 0x50, // 7 bInterfaceProtocol: BULK - 0xFF, // 8 iInterface (String Index) [SET AT RUNTIME] -#define MSC_INTERFACE_STRING_INDEX (8) - - // MSC Endpoint IN Descriptor - 0x07, // 9 bLength - 0x05, // 10 bDescriptorType (Endpoint) - 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number] -#define MSC_IN_ENDPOINT_INDEX (11) - 0x02, // 12 bmAttributes (Bulk) - #if USB_HIGHSPEED - 0x00, 0x02, // 13,14 wMaxPacketSize 512 - #else - 0x40, 0x00, // 13,14 wMaxPacketSize 64 - #endif - 0x00, // 15 bInterval 0 (unit depends on device speed) - - // MSC Endpoint OUT Descriptor - 0x07, // 16 bLength - 0x05, // 17 bDescriptorType (Endpoint) - 0xFF, // 18 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] -#define MSC_OUT_ENDPOINT_INDEX (18) - 0x02, // 19 bmAttributes (Bulk) - #if USB_HIGHSPEED - 0x00, 0x02, // 20,21 wMaxPacketSize 512 - #else - 0x40, 0x00, // 20,21 wMaxPacketSize 64 - #endif - 0x00, // 22 bInterval 0 (unit depends on device speed) -}; - // Is the MSC device enabled? bool storage_usb_is_enabled; @@ -78,32 +37,6 @@ bool storage_usb_enabled(void) { return storage_usb_is_enabled; } -size_t storage_usb_descriptor_length(void) { - return sizeof(usb_msc_descriptor_template); -} - -static const char storage_interface_name[] = USB_INTERFACE_NAME " Mass Storage"; - -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) { - memcpy(descriptor_buf, usb_msc_descriptor_template, sizeof(usb_msc_descriptor_template)); - descriptor_buf[MSC_INTERFACE_INDEX] = descriptor_counts->current_interface; - descriptor_counts->current_interface++; - - descriptor_buf[MSC_IN_ENDPOINT_INDEX] = - 0x80 | (USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : descriptor_counts->current_endpoint); - descriptor_counts->num_in_endpoints++; - descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = - USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : descriptor_counts->current_endpoint; - descriptor_counts->num_out_endpoints++; - descriptor_counts->current_endpoint++; - - usb_add_interface_string(*current_interface_string, storage_interface_name); - descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string; - (*current_interface_string)++; - - return sizeof(usb_msc_descriptor_template); -} - static bool usb_drive_set_enabled(bool enabled) { // We can't change the descriptors once we're connected. if (tud_connected()) { @@ -149,10 +82,11 @@ static mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_ } void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool readonly) { + const char *abs_mount_path = common_hal_os_path_abspath(mount_path); // create new object mp_vfs_mount_t *vfs = m_new_obj(mp_vfs_mount_t); - vfs->str = mount_path; - vfs->len = strlen(mount_path); + vfs->str = abs_mount_path; + vfs->len = strlen(abs_mount_path); vfs->obj = vfs_obj; vfs->next = NULL; @@ -165,7 +99,7 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea if (strcmp(vfs->str, "/") != 0) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - mp_obj_t mount_point_stat = common_hal_os_stat(mount_path); + mp_obj_t mount_point_stat = common_hal_os_stat(abs_mount_path); nlr_pop(); mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mount_point_stat); if ((MP_OBJ_SMALL_INT_VALUE(t->items[0]) & MP_S_IFDIR) == 0) { @@ -179,7 +113,7 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea // check that the destination mount point is unused const char *path_out; - mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(mount_path, &path_out); + mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(abs_mount_path, &path_out); if (existing_mount != MP_VFS_NONE && existing_mount != MP_VFS_ROOT) { if (vfs->len != 1 && existing_mount->len == 1) { // if root dir is mounted, still allow to mount something within a subdir of root @@ -192,6 +126,11 @@ void common_hal_storage_mount(mp_obj_t vfs_obj, const char *mount_path, bool rea // call the underlying object to do any mounting operation mp_vfs_proxy_call(vfs, MP_QSTR_mount, 2, (mp_obj_t *)&args); + fs_user_mount_t *vfs_fat = MP_OBJ_TO_PTR(vfs_obj); + // Filesystem is read-only to USB if writable by CircuitPython, and vice versa. + filesystem_set_writable_by_usb(vfs_fat, readonly); + filesystem_set_concurrent_write_protection(vfs_fat, true); + // Insert the vfs into the mount table by pushing it onto the front of the // mount table. mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); @@ -224,8 +163,9 @@ void common_hal_storage_umount_object(mp_obj_t vfs_obj) { } static mp_obj_t storage_object_from_path(const char *mount_path) { + const char *abs_mount_path = common_hal_os_path_abspath(mount_path); for (mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table); *vfsp != NULL; vfsp = &(*vfsp)->next) { - if (strcmp(mount_path, (*vfsp)->str) == 0) { + if (strcmp(abs_mount_path, (*vfsp)->str) == 0) { return (*vfsp)->obj; } } @@ -241,18 +181,26 @@ mp_obj_t common_hal_storage_getmount(const char *mount_path) { } void common_hal_storage_remount(const char *mount_path, bool readonly, bool disable_concurrent_write_protection) { - if (strcmp(mount_path, "/") != 0) { + const char *path_under_mount; + const char *abs_mount_path = common_hal_os_path_abspath(mount_path); + fs_user_mount_t *fs_usermount = filesystem_for_path(abs_mount_path, &path_under_mount); + if (path_under_mount[0] != 0 && strcmp(abs_mount_path, "/") != 0) { mp_raise_OSError(MP_EINVAL); } #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC - if (!usb_msc_ejected() && storage_usb_is_enabled) { - mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot remount '/' when visible via USB.")); + if (!blockdev_lock(fs_usermount)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("Cannot remount path when visible via USB.")); } #endif - filesystem_set_internal_writable_by_usb(readonly); - filesystem_set_internal_concurrent_write_protection(!disable_concurrent_write_protection); + filesystem_set_writable_by_usb(fs_usermount, readonly); + filesystem_set_concurrent_write_protection(fs_usermount, !disable_concurrent_write_protection); + blockdev_unlock(fs_usermount); + + #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC + usb_msc_remount(fs_usermount); + #endif } void common_hal_storage_erase_filesystem(bool extended) { @@ -264,6 +212,7 @@ void common_hal_storage_erase_filesystem(bool extended) { supervisor_flash_set_extended(extended); #endif (void)filesystem_init(false, true); // Force a re-format. Ignore failure. + common_hal_mcu_on_next_reset(RUNMODE_NORMAL); common_hal_mcu_reset(); // We won't actually get here, since we're resetting. } diff --git a/shared-module/storage/__init__.h b/shared-module/storage/__init__.h index 3adda2c2f7131..03503f4e80246 100644 --- a/shared-module/storage/__init__.h +++ b/shared-module/storage/__init__.h @@ -11,6 +11,4 @@ bool storage_usb_enabled(void); void storage_usb_set_defaults(void); -size_t storage_usb_descriptor_length(void); -size_t storage_usb_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string); #endif diff --git a/shared-module/struct/__init__.c b/shared-module/struct/__init__.c index 715b504302115..4b6b2b589efc8 100644 --- a/shared-module/struct/__init__.c +++ b/shared-module/struct/__init__.c @@ -14,7 +14,8 @@ #include "shared-bindings/struct/__init__.h" static void struct_validate_format(char fmt) { - #if MICROPY_NONSTANDARD_TYPECODES + #if MICROPY_PY_STRUCT_UNSAFE_TYPECODES + if (fmt == 'S' || fmt == 'O') { mp_raise_RuntimeError(MP_ERROR_TEXT("'S' and 'O' are not supported format types")); } diff --git a/shared-module/synthio/Biquad.c b/shared-module/synthio/Biquad.c index 366d516455224..08aab81a7bfa5 100644 --- a/shared-module/synthio/Biquad.c +++ b/shared-module/synthio/Biquad.c @@ -1,3 +1,4 @@ + // This file is part of the CircuitPython project: https://circuitpython.org // // SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries @@ -7,99 +8,203 @@ #include #include "shared-bindings/synthio/Biquad.h" #include "shared-module/synthio/Biquad.h" +#include "shared-module/synthio/block.h" +#include "shared-bindings/synthio/__init__.h" + +typedef struct { + mp_float_t s, c; +} sincos_result_t; + +#include // uint32_t + +// The famous Quake approximate square root function +static mp_float_t Q_rsqrt(mp_float_t number_in) { + float number = (float)number_in; + union { + float f; + uint32_t i; + } conv = { .f = (float)number }; + conv.i = 0x5f3759df - (conv.i >> 1); + conv.f *= 1.5F - (number * 0.5F * conv.f * conv.f); + return (mp_float_t)conv.f; +} -mp_obj_t common_hal_synthio_new_lpf(mp_float_t w0, mp_float_t Q) { - mp_float_t s = MICROPY_FLOAT_C_FUN(sin)(w0); - mp_float_t c = MICROPY_FLOAT_C_FUN(cos)(w0); - mp_float_t alpha = s / (2 * Q); - mp_float_t a0 = 1 + alpha; - mp_float_t a1 = -2 * c; - mp_float_t a2 = 1 - alpha; - mp_float_t b0 = (1 - c) / 2; - mp_float_t b1 = 1 - c; - mp_float_t b2 = (1 - c) / 2; - - mp_obj_t out_args[] = { - mp_obj_new_float(a1 / a0), - mp_obj_new_float(a2 / a0), - mp_obj_new_float(b0 / a0), - mp_obj_new_float(b1 / a0), - mp_obj_new_float(b2 / a0), - }; - - return namedtuple_make_new((const mp_obj_type_t *)&synthio_biquad_type_obj, MP_ARRAY_SIZE(out_args), 0, out_args); -} - -mp_obj_t common_hal_synthio_new_hpf(mp_float_t w0, mp_float_t Q) { - mp_float_t s = MICROPY_FLOAT_C_FUN(sin)(w0); - mp_float_t c = MICROPY_FLOAT_C_FUN(cos)(w0); - mp_float_t alpha = s / (2 * Q); - mp_float_t a0 = 1 + alpha; - mp_float_t a1 = -2 * c; - mp_float_t a2 = 1 - alpha; - mp_float_t b0 = (1 + c) / 2; - mp_float_t b1 = -(1 + c); - mp_float_t b2 = (1 + c) / 2; - - mp_obj_t out_args[] = { - mp_obj_new_float(a1 / a0), - mp_obj_new_float(a2 / a0), - mp_obj_new_float(b0 / a0), - mp_obj_new_float(b1 / a0), - mp_obj_new_float(b2 / a0), - }; - - return namedtuple_make_new((const mp_obj_type_t *)&synthio_biquad_type_obj, MP_ARRAY_SIZE(out_args), 0, out_args); -} - -mp_obj_t common_hal_synthio_new_bpf(mp_float_t w0, mp_float_t Q) { - mp_float_t s = MICROPY_FLOAT_C_FUN(sin)(w0); - mp_float_t c = MICROPY_FLOAT_C_FUN(cos)(w0); - mp_float_t alpha = s / (2 * Q); - mp_float_t a0 = 1 + alpha; - mp_float_t a1 = -2 * c; - mp_float_t a2 = 1 - alpha; - mp_float_t b0 = alpha; - mp_float_t b1 = 0; - mp_float_t b2 = -alpha; - - mp_obj_t out_args[] = { - mp_obj_new_float(a1 / a0), - mp_obj_new_float(a2 / a0), - mp_obj_new_float(b0 / a0), - mp_obj_new_float(b1 / a0), - mp_obj_new_float(b2 / a0), - }; - - return namedtuple_make_new((const mp_obj_type_t *)&synthio_biquad_type_obj, MP_ARRAY_SIZE(out_args), 0, out_args); -} - -#define BIQUAD_SHIFT (15) -static int32_t biquad_scale_arg_obj(mp_obj_t arg) { - return (int32_t)MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(ldexp)(mp_obj_get_float(arg), BIQUAD_SHIFT)); -} -void synthio_biquad_filter_assign(biquad_filter_state *st, mp_obj_t biquad_obj) { - if (biquad_obj != mp_const_none) { - mp_arg_validate_type(biquad_obj, (const mp_obj_type_t *)&synthio_biquad_type_obj, MP_QSTR_filter); - mp_obj_tuple_t *biquad = (mp_obj_tuple_t *)MP_OBJ_TO_PTR(biquad_obj); - st->a1 = biquad_scale_arg_obj(biquad->items[0]); - st->a2 = biquad_scale_arg_obj(biquad->items[1]); - st->b0 = biquad_scale_arg_obj(biquad->items[2]); - st->b1 = biquad_scale_arg_obj(biquad->items[3]); - st->b2 = biquad_scale_arg_obj(biquad->items[4]); +static mp_float_t fast_sqrt(mp_float_t number) { + return number * Q_rsqrt(number); +} + +#define FOUR_OVER_PI (4 / M_PI) +static void fast_sincos(mp_float_t theta, sincos_result_t *result) { + mp_float_t x = (theta * FOUR_OVER_PI) - 1; + mp_float_t x2 = x * x, x3 = x2 * x, x4 = x2 * x2, x5 = x2 * x3; + mp_float_t c0 = 0.70708592, + c1x = -0.55535724 * x, + c2x2 = -0.21798592 * x2, + c3x3 = 0.05707685 * x3, + c4x4 = 0.0109 * x4, + c5x5 = -0.00171961 * x5; + + mp_float_t evens = c4x4 + c2x2 + c0, odds = c5x5 + c3x3 + c1x; + result->c = evens + odds; + result->s = evens - odds; +} + +mp_obj_t common_hal_synthio_biquad_new(synthio_filter_mode mode) { + synthio_biquad_t *self = mp_obj_malloc(synthio_biquad_t, &synthio_biquad_type_obj); + self->mode = mode; + return MP_OBJ_FROM_PTR(self); +} + +synthio_filter_mode common_hal_synthio_biquad_get_mode(synthio_biquad_t *self) { + return self->mode; +} + +mp_obj_t common_hal_synthio_biquad_get_Q(synthio_biquad_t *self) { + return self->Q.obj; +} + +void common_hal_synthio_biquad_set_Q(synthio_biquad_t *self, mp_obj_t Q) { + synthio_block_assign_slot(Q, &self->Q, MP_QSTR_Q); +} + +mp_obj_t common_hal_synthio_biquad_get_A(synthio_biquad_t *self) { + return self->A.obj; +} + +void common_hal_synthio_biquad_set_A(synthio_biquad_t *self, mp_obj_t A) { + synthio_block_assign_slot(A, &self->A, MP_QSTR_A); +} + +mp_obj_t common_hal_synthio_biquad_get_frequency(synthio_biquad_t *self) { + return self->f0.obj; +} + +void common_hal_synthio_biquad_set_frequency(synthio_biquad_t *self, mp_obj_t frequency) { + synthio_block_assign_slot(frequency, &self->f0, MP_QSTR_frequency); +} + +static int32_t biquad_scale_arg_float(mp_float_t arg) { + return (int32_t)MICROPY_FLOAT_C_FUN(round)(MICROPY_FLOAT_C_FUN(ldexp)(arg, BIQUAD_SHIFT)); +} + +static int float_equal_or_update( + mp_float_t *cached, + mp_float_t new) { + // uses memcmp to avoid error about equality float comparison + if (memcmp(cached, &new, sizeof(mp_float_t))) { + *cached = new; + return false; + } + return true; +} + +void common_hal_synthio_biquad_tick(mp_obj_t self_in) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + + mp_float_t W0 = synthio_block_slot_get(&self->f0) * synthio_global_W_scale; + mp_float_t Q = synthio_block_slot_get(&self->Q); + mp_float_t A = + (self->mode >= SYNTHIO_PEAKING_EQ) ? synthio_block_slot_get(&self->A) : 0; + + // n.b., assumes that the `mode` field is read-only + // n.b., use of `&` is deliberate, avoids short-circuiting behavior + if (float_equal_or_update(&self->cached_W0, W0) + & float_equal_or_update(&self->cached_Q, Q) + & float_equal_or_update(&self->cached_A, A)) { + return; } + + sincos_result_t sc; + fast_sincos(W0, &sc); + + mp_float_t alpha = sc.s / (2 * Q); + + mp_float_t a0, a1, a2, b0, b1, b2; + + switch (self->mode) { + default: + a0 = 1 + alpha; + a1 = -2 * sc.c; + a2 = 1 - alpha; + + switch (self->mode) { + default: + case SYNTHIO_LOW_PASS: + b2 = b0 = (1 - sc.c) * .5; + b1 = 1 - sc.c; + break; + + case SYNTHIO_HIGH_PASS: + b2 = b0 = (1 + sc.c) * .5; + b1 = -(1 + sc.c); + break; + + case SYNTHIO_BAND_PASS: + b0 = alpha; + b1 = 0; + b2 = -b0; + break; + + case SYNTHIO_NOTCH: + b0 = 1; + b1 = -2 * sc.c; + b2 = 1; + } + + break; + + case SYNTHIO_PEAKING_EQ: + b0 = 1 + alpha * A; + b1 = -2 * sc.c; + b2 = 1 + alpha * A; + a0 = 1 + alpha / A; + a1 = -2 * sc.c; + a2 = 1 - alpha / A; + break; + + case SYNTHIO_LOW_SHELF: { + mp_float_t sqrt_A = fast_sqrt(A); + b0 = A * ((A + 1) - (A - 1) * sc.c + 2 * sqrt_A * alpha); + b1 = 2 * A * ((A - 1) - (A + 1) * sc.c); + b2 = A * ((A + 1) - (A - 1) * sc.c - 2 * sqrt_A * alpha); + a0 = (A + 1) + (A - 1) * sc.c + 2 * sqrt_A * alpha; + a1 = -2 * ((A - 1) + (A + 1) * sc.c); + a2 = (A + 1) + (A - 1) * sc.c - 2 * sqrt_A * alpha; + } + break; + + case SYNTHIO_HIGH_SHELF: { + mp_float_t sqrt_A = fast_sqrt(A); + b0 = A * ((A + 1) + (A - 1) * sc.c + 2 * sqrt_A * alpha); + b1 = -2 * A * ((A - 1) + (A + 1) * sc.c); + b2 = A * ((A + 1) + (A - 1) * sc.c - 2 * sqrt_A * alpha); + a0 = (A + 1) - (A - 1) * sc.c + 2 * sqrt_A * alpha; + a1 = 2 * ((A - 1) - (A + 1) * sc.c); + a2 = (A + 1) - (A - 1) * sc.c - 2 * sqrt_A * alpha; + } + break; + } + mp_float_t recip_a0 = 1 / a0; + + self->a1 = biquad_scale_arg_float(a1 * recip_a0); + self->a2 = biquad_scale_arg_float(a2 * recip_a0); + self->b0 = biquad_scale_arg_float(b0 * recip_a0); + self->b1 = biquad_scale_arg_float(b1 * recip_a0); + self->b2 = biquad_scale_arg_float(b2 * recip_a0); } void synthio_biquad_filter_reset(biquad_filter_state *st) { memset(&st->x, 0, 4 * sizeof(int16_t)); } -void synthio_biquad_filter_samples(biquad_filter_state *st, int32_t *buffer, size_t n_samples) { - int32_t a1 = st->a1; - int32_t a2 = st->a2; - int32_t b0 = st->b0; - int32_t b1 = st->b1; - int32_t b2 = st->b2; +void synthio_biquad_filter_samples(mp_obj_t self_in, biquad_filter_state *st, int32_t *buffer, size_t n_samples) { + synthio_biquad_t *self = MP_OBJ_TO_PTR(self_in); + + int32_t a1 = self->a1; + int32_t a2 = self->a2; + int32_t b0 = self->b0; + int32_t b1 = self->b1; + int32_t b2 = self->b2; int32_t x0 = st->x[0]; int32_t x1 = st->x[1]; @@ -108,7 +213,7 @@ void synthio_biquad_filter_samples(biquad_filter_state *st, int32_t *buffer, siz for (size_t n = n_samples; n; --n, ++buffer) { int32_t input = *buffer; - int32_t output = (b0 * input + b1 * x0 + b2 * x1 - a1 * y0 - a2 * y1 + (1 << (BIQUAD_SHIFT - 1))) >> BIQUAD_SHIFT; + int32_t output = synthio_sat16((b0 * input + b1 * x0 + b2 * x1 - a1 * y0 - a2 * y1 + (1 << (BIQUAD_SHIFT - 1))), BIQUAD_SHIFT); x1 = x0; x0 = input; diff --git a/shared-module/synthio/Biquad.h b/shared-module/synthio/Biquad.h index b33a6230caf86..3b9920ed92f58 100644 --- a/shared-module/synthio/Biquad.h +++ b/shared-module/synthio/Biquad.h @@ -1,3 +1,4 @@ + // This file is part of the CircuitPython project: https://circuitpython.org // // SPDX-FileCopyrightText: Copyright (c) 2023 Jeff Epler for Adafruit Industries @@ -6,13 +7,23 @@ #pragma once -#include "py/obj.h" +#include "shared-bindings/synthio/Biquad.h" +#include "shared-module/synthio/block.h" -typedef struct { +#define BIQUAD_SHIFT (15) + +typedef struct synthio_biquad { + mp_obj_base_t base; + synthio_filter_mode mode; + synthio_block_slot_t f0, Q, A; + mp_float_t cached_W0, cached_Q, cached_A; int32_t a1, a2, b0, b1, b2; +} synthio_biquad_t; + +typedef struct { int32_t x[2], y[2]; } biquad_filter_state; -void synthio_biquad_filter_assign(biquad_filter_state *st, mp_obj_t biquad_obj); +void common_hal_synthio_biquad_tick(mp_obj_t self_in); void synthio_biquad_filter_reset(biquad_filter_state *st); -void synthio_biquad_filter_samples(biquad_filter_state *st, int32_t *buffer, size_t n_samples); +void synthio_biquad_filter_samples(mp_obj_t self_in, biquad_filter_state *st, int32_t *buffer, size_t n_samples); diff --git a/shared-module/synthio/MidiTrack.c b/shared-module/synthio/MidiTrack.c index 2391a8bb7c7cd..1cccd440fad9e 100644 --- a/shared-module/synthio/MidiTrack.c +++ b/shared-module/synthio/MidiTrack.c @@ -6,6 +6,7 @@ #include "py/runtime.h" #include "shared-bindings/synthio/MidiTrack.h" +#include "shared-bindings/audiocore/__init__.h" static void record_midi_stream_error(synthio_miditrack_obj_t *self) { @@ -42,7 +43,7 @@ static int decode_duration(synthio_miditrack_obj_t *self) { self->pos = self->track.len; record_midi_stream_error(self); } - return delta * self->synth.sample_rate / self->tempo; + return delta * self->synth.base.sample_rate / self->tempo; } // invariant: pointing at a MIDI message @@ -111,22 +112,18 @@ void common_hal_synthio_miditrack_deinit(synthio_miditrack_obj_t *self) { synthio_synth_deinit(&self->synth); } -bool common_hal_synthio_miditrack_deinited(synthio_miditrack_obj_t *self) { - return synthio_synth_deinited(&self->synth); -} - mp_int_t common_hal_synthio_miditrack_get_error_location(synthio_miditrack_obj_t *self) { return self->error_location; } -uint32_t common_hal_synthio_miditrack_get_sample_rate(synthio_miditrack_obj_t *self) { - return self->synth.sample_rate; -} -uint8_t common_hal_synthio_miditrack_get_bits_per_sample(synthio_miditrack_obj_t *self) { - return SYNTHIO_BITS_PER_SAMPLE; +mp_int_t common_hal_synthio_miditrack_get_tempo(synthio_miditrack_obj_t *self) { + return self->tempo; } -uint8_t common_hal_synthio_miditrack_get_channel_count(synthio_miditrack_obj_t *self) { - return 1; + +void common_hal_synthio_miditrack_set_tempo(synthio_miditrack_obj_t *self, mp_int_t value) { + mp_int_t val = mp_arg_validate_int_min(value, 1, MP_QSTR_tempo); + self->synth.span.dur = (uint32_t)self->synth.span.dur * self->tempo / val; + self->tempo = val; } void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self, @@ -137,7 +134,7 @@ void synthio_miditrack_reset_buffer(synthio_miditrack_obj_t *self, audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t *self, bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { - if (common_hal_synthio_miditrack_deinited(self)) { + if (audiosample_deinited(&self->synth.base)) { *buffer_length = 0; return GET_BUFFER_ERROR; } @@ -152,8 +149,3 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t } return GET_BUFFER_MORE_DATA; } - -void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { - return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing); -} diff --git a/shared-module/synthio/MidiTrack.h b/shared-module/synthio/MidiTrack.h index 816c0be695886..1e4d5cba2daf8 100644 --- a/shared-module/synthio/MidiTrack.h +++ b/shared-module/synthio/MidiTrack.h @@ -11,7 +11,6 @@ #include "shared-module/synthio/__init__.h" typedef struct { - mp_obj_base_t base; synthio_synth_t synth; mp_buffer_info_t track; // invariant: after initial startup, pos always points just after an encoded duration, i.e., at a midi message (or at EOF) @@ -31,7 +30,3 @@ audioio_get_buffer_result_t synthio_miditrack_get_buffer(synthio_miditrack_obj_t uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes - -void synthio_miditrack_get_buffer_structure(synthio_miditrack_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/synthio/Note.c b/shared-module/synthio/Note.c index 49dfbb7f429d3..c8c307bb415df 100644 --- a/shared-module/synthio/Note.c +++ b/shared-module/synthio/Note.c @@ -25,7 +25,11 @@ mp_obj_t common_hal_synthio_note_get_filter_obj(synthio_note_obj_t *self) { } void common_hal_synthio_note_set_filter(synthio_note_obj_t *self, mp_obj_t filter_in) { - synthio_biquad_filter_assign(&self->filter_state, filter_in); + if (filter_in != mp_const_none && !mp_obj_is_type(filter_in, &synthio_biquad_type_obj)) { + mp_raise_TypeError_varg( + MP_ERROR_TEXT("%q must be of type %q, not %q"), + MP_QSTR_filter, MP_QSTR_Biquad, mp_obj_get_type(filter_in)->name); + } self->filter_obj = filter_in; } @@ -100,22 +104,20 @@ void common_hal_synthio_note_set_waveform(synthio_note_obj_t *self, mp_obj_t wav self->waveform_obj = waveform_in; } -mp_int_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self) { - return self->waveform_loop_start; +mp_obj_t common_hal_synthio_note_get_waveform_loop_start(synthio_note_obj_t *self) { + return self->waveform_loop_start.obj; } -void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 0, SYNTHIO_WAVEFORM_SIZE - 1, MP_QSTR_waveform_loop_start); - self->waveform_loop_start = val; +void common_hal_synthio_note_set_waveform_loop_start(synthio_note_obj_t *self, mp_obj_t value_in) { + synthio_block_assign_slot(value_in, &self->waveform_loop_start, MP_QSTR_waveform_loop_start); } -mp_int_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self) { - return self->waveform_loop_end; +mp_obj_t common_hal_synthio_note_get_waveform_loop_end(synthio_note_obj_t *self) { + return self->waveform_loop_end.obj; } -void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 1, SYNTHIO_WAVEFORM_SIZE, MP_QSTR_waveform_loop_end); - self->waveform_loop_end = val; +void common_hal_synthio_note_set_waveform_loop_end(synthio_note_obj_t *self, mp_obj_t value_in) { + synthio_block_assign_slot(value_in, &self->waveform_loop_end, MP_QSTR_waveform_loop_end); } mp_obj_t common_hal_synthio_note_get_ring_waveform_obj(synthio_note_obj_t *self) { @@ -133,22 +135,20 @@ void common_hal_synthio_note_set_ring_waveform(synthio_note_obj_t *self, mp_obj_ self->ring_waveform_obj = ring_waveform_in; } -mp_int_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self) { - return self->ring_waveform_loop_start; +mp_obj_t common_hal_synthio_note_get_ring_waveform_loop_start(synthio_note_obj_t *self) { + return self->ring_waveform_loop_start.obj; } -void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 0, SYNTHIO_WAVEFORM_SIZE - 1, MP_QSTR_ring_waveform_loop_start); - self->ring_waveform_loop_start = val; +void common_hal_synthio_note_set_ring_waveform_loop_start(synthio_note_obj_t *self, mp_obj_t value_in) { + synthio_block_assign_slot(value_in, &self->ring_waveform_loop_start, MP_QSTR_ring_waveform_loop_start); } -mp_int_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self) { - return self->ring_waveform_loop_end; +mp_obj_t common_hal_synthio_note_get_ring_waveform_loop_end(synthio_note_obj_t *self) { + return self->ring_waveform_loop_end.obj; } -void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_int_t value_in) { - mp_int_t val = mp_arg_validate_int_range(value_in, 1, SYNTHIO_WAVEFORM_SIZE, MP_QSTR_ring_waveform_loop_end); - self->ring_waveform_loop_end = val; +void common_hal_synthio_note_set_ring_waveform_loop_end(synthio_note_obj_t *self, mp_obj_t value_in) { + synthio_block_assign_slot(value_in, &self->ring_waveform_loop_end, MP_QSTR_ring_waveform_loop_end); } void synthio_note_recalculate(synthio_note_obj_t *self, int32_t sample_rate) { diff --git a/shared-module/synthio/Note.h b/shared-module/synthio/Note.h index dc4e5557fd3c9..9d9deb42ac8f3 100644 --- a/shared-module/synthio/Note.h +++ b/shared-module/synthio/Note.h @@ -28,9 +28,9 @@ typedef struct synthio_note_obj { int32_t ring_frequency_scaled, ring_frequency_bent; mp_buffer_info_t waveform_buf; - uint32_t waveform_loop_start, waveform_loop_end; + synthio_block_slot_t waveform_loop_start, waveform_loop_end; mp_buffer_info_t ring_waveform_buf; - uint32_t ring_waveform_loop_start, ring_waveform_loop_end; + synthio_block_slot_t ring_waveform_loop_start, ring_waveform_loop_end; synthio_envelope_definition_t envelope_def; } synthio_note_obj_t; diff --git a/shared-module/synthio/Synthesizer.c b/shared-module/synthio/Synthesizer.c index e4b343f6ba215..39eb4a02e6a36 100644 --- a/shared-module/synthio/Synthesizer.c +++ b/shared-module/synthio/Synthesizer.c @@ -7,6 +7,7 @@ #include "py/runtime.h" #include "shared-bindings/synthio/LFO.h" #include "shared-bindings/synthio/Note.h" +#include "shared-bindings/audiocore/__init__.h" #include "shared-bindings/synthio/Synthesizer.h" #include "shared-module/synthio/Note.h" @@ -23,19 +24,6 @@ void common_hal_synthio_synthesizer_construct(synthio_synthesizer_obj_t *self, void common_hal_synthio_synthesizer_deinit(synthio_synthesizer_obj_t *self) { synthio_synth_deinit(&self->synth); } -bool common_hal_synthio_synthesizer_deinited(synthio_synthesizer_obj_t *self) { - return synthio_synth_deinited(&self->synth); -} - -uint32_t common_hal_synthio_synthesizer_get_sample_rate(synthio_synthesizer_obj_t *self) { - return self->synth.sample_rate; -} -uint8_t common_hal_synthio_synthesizer_get_bits_per_sample(synthio_synthesizer_obj_t *self) { - return SYNTHIO_BITS_PER_SAMPLE; -} -uint8_t common_hal_synthio_synthesizer_get_channel_count(synthio_synthesizer_obj_t *self) { - return self->synth.channel_count; -} void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self, bool single_channel_output, uint8_t channel) { @@ -44,7 +32,7 @@ void synthio_synthesizer_reset_buffer(synthio_synthesizer_obj_t *self, audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_obj_t *self, bool single_channel_output, uint8_t channel, uint8_t **buffer, uint32_t *buffer_length) { - if (common_hal_synthio_synthesizer_deinited(self)) { + if (audiosample_deinited(&self->synth.base)) { *buffer_length = 0; return GET_BUFFER_ERROR; } @@ -67,11 +55,6 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o return GET_BUFFER_MORE_DATA; } -void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { - return synthio_synth_get_buffer_structure(&self->synth, single_channel_output, single_buffer, samples_signed, max_buffer_length, spacing); -} - void common_hal_synthio_synthesizer_release_all(synthio_synthesizer_obj_t *self) { for (size_t i = 0; i < CIRCUITPY_SYNTHIO_MAX_CHANNELS; i++) { if (self->synth.span.note_obj[i] != SYNTHIO_SILENCE) { @@ -114,7 +97,7 @@ void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_ob if (is_note(to_press)) { if (!mp_obj_is_small_int(to_press)) { synthio_note_obj_t *note = MP_OBJ_TO_PTR(to_press); - synthio_note_start(note, self->synth.sample_rate); + synthio_note_start(note, self->synth.base.sample_rate); } synthio_span_change_note(&self->synth, SYNTHIO_SILENCE, validate_note(to_press)); return; @@ -127,7 +110,7 @@ void common_hal_synthio_synthesizer_press(synthio_synthesizer_obj_t *self, mp_ob note_obj = validate_note(note_obj); if (!mp_obj_is_small_int(note_obj)) { synthio_note_obj_t *note = MP_OBJ_TO_PTR(note_obj); - synthio_note_start(note, self->synth.sample_rate); + synthio_note_start(note, self->synth.base.sample_rate); } synthio_span_change_note(&self->synth, SYNTHIO_SILENCE, note_obj); } diff --git a/shared-module/synthio/Synthesizer.h b/shared-module/synthio/Synthesizer.h index 4fd5012cdcd94..a4dac7c25c6da 100644 --- a/shared-module/synthio/Synthesizer.h +++ b/shared-module/synthio/Synthesizer.h @@ -12,7 +12,6 @@ #include "shared-module/synthio/__init__.h" typedef struct { - mp_obj_base_t base; synthio_synth_t synth; mp_obj_t blocks; } synthio_synthesizer_obj_t; @@ -28,7 +27,3 @@ audioio_get_buffer_result_t synthio_synthesizer_get_buffer(synthio_synthesizer_o uint8_t channel, uint8_t **buffer, uint32_t *buffer_length); // length in bytes - -void synthio_synthesizer_get_buffer_structure(synthio_synthesizer_obj_t *self, bool single_channel_output, - bool *single_buffer, bool *samples_signed, - uint32_t *max_buffer_length, uint8_t *spacing); diff --git a/shared-module/synthio/__init__.c b/shared-module/synthio/__init__.c index 630c3de86988c..db0c449bfab69 100644 --- a/shared-module/synthio/__init__.c +++ b/shared-module/synthio/__init__.c @@ -6,6 +6,7 @@ // SPDX-License-Identifier: MIT #include "shared-module/synthio/__init__.h" +#include "shared-bindings/audiocore/__init__.h" #include "shared-bindings/synthio/__init__.h" #include "shared-module/synthio/Biquad.h" #include "shared-module/synthio/Note.h" @@ -13,7 +14,9 @@ #include #include -mp_float_t synthio_global_rate_scale; +#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846) + +mp_float_t synthio_global_rate_scale, synthio_global_W_scale; uint8_t synthio_global_tick; static const int16_t square_wave[] = {-32768, 32767}; @@ -21,6 +24,26 @@ static const int16_t square_wave[] = {-32768, 32767}; static const uint16_t notes[] = {8372, 8870, 9397, 9956, 10548, 11175, 11840, 12544, 13290, 14080, 14917, 15804}; // 9th octave +// cleaner sat16 by http://www.moseleyinstruments.com/ +int16_t synthio_sat16(int32_t n, int rshift) { + // we should always round towards 0 + // to avoid recirculating round-off noise + // + // a 2s complement positive number is always + // rounded down, so we only need to take + // care of negative numbers + if (n < 0) { + n = n + (~(0xFFFFFFFFUL << rshift)); + } + n = n >> rshift; + if (n > 32767) { + return 32767; + } + if (n < -32768) { + return -32768; + } + return n; +} static int64_t round_float_to_int64(mp_float_t f) { return (int64_t)(f + MICROPY_FLOAT_CONST(0.5)); @@ -126,28 +149,24 @@ static synthio_envelope_definition_t *synthio_synth_get_note_envelope(synthio_sy } -#define RANGE_LOW (-28000) -#define RANGE_HIGH (28000) #define RANGE_SHIFT (16) -#define RANGE_SCALE (0xfffffff / (32768 * CIRCUITPY_SYNTHIO_MAX_CHANNELS - RANGE_HIGH)) // dynamic range compression via a downward compressor with hard knee // // When the output value is within the range +-28000 (about 85% of full scale), // it is unchanged. Otherwise, it undergoes a gain reduction so that the -// largest possible values, (+32768,-32767) * CIRCUITPY_SYNTHIO_MAX_CHANNELS, +// largest possible values, (+32768,-32767) * count, // still fit within the output range // // This produces a much louder overall volume with multiple voices, without // much additional processing. // // https://en.wikipedia.org/wiki/Dynamic_range_compression -static -int16_t mix_down_sample(int32_t sample) { - if (sample < RANGE_LOW) { - sample = (((sample - RANGE_LOW) * RANGE_SCALE) >> RANGE_SHIFT) + RANGE_LOW; - } else if (sample > RANGE_HIGH) { - sample = (((sample - RANGE_HIGH) * RANGE_SCALE) >> RANGE_SHIFT) + RANGE_HIGH; +int16_t synthio_mix_down_sample(int32_t sample, int32_t scale) { + if (sample < SYNTHIO_MIX_DOWN_RANGE_LOW) { + sample = (((sample - SYNTHIO_MIX_DOWN_RANGE_LOW) * scale) >> RANGE_SHIFT) + SYNTHIO_MIX_DOWN_RANGE_LOW; + } else if (sample > SYNTHIO_MIX_DOWN_RANGE_HIGH) { + sample = (((sample - SYNTHIO_MIX_DOWN_RANGE_HIGH) * scale) >> RANGE_SHIFT) + SYNTHIO_MIX_DOWN_RANGE_HIGH; } return sample; } @@ -155,7 +174,7 @@ int16_t mix_down_sample(int32_t sample) { static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *out_buffer32, int16_t dur, int16_t loudness[2]) { mp_obj_t note_obj = synth->span.note_obj[chan]; - int32_t sample_rate = synth->sample_rate; + int32_t sample_rate = synth->base.sample_rate; uint32_t dds_rate; @@ -184,23 +203,15 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou if (note->waveform_buf.buf) { waveform = note->waveform_buf.buf; waveform_length = note->waveform_buf.len; - if (note->waveform_loop_start > 0 && note->waveform_loop_start < waveform_length) { - waveform_start = note->waveform_loop_start; - } - if (note->waveform_loop_end > waveform_start && note->waveform_loop_end < waveform_length) { - waveform_length = note->waveform_loop_end; - } + waveform_start = (uint32_t)synthio_block_slot_get_limited(¬e->waveform_loop_start, 0, waveform_length - 1); + waveform_length = (uint32_t)synthio_block_slot_get_limited(¬e->waveform_loop_end, waveform_start + 1, waveform_length); } dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)frequency_scaled * (waveform_length - waveform_start), sample_rate); if (note->ring_frequency_scaled != 0 && note->ring_waveform_buf.buf) { ring_waveform = note->ring_waveform_buf.buf; ring_waveform_length = note->ring_waveform_buf.len; - if (note->ring_waveform_loop_start > 0 && note->ring_waveform_loop_start < ring_waveform_length) { - ring_waveform_start = note->waveform_loop_start; - } - if (note->ring_waveform_loop_end > ring_waveform_start && note->ring_waveform_loop_end < ring_waveform_length) { - ring_waveform_length = note->ring_waveform_loop_end; - } + ring_waveform_start = (uint32_t)synthio_block_slot_get_limited(¬e->ring_waveform_loop_start, 0, ring_waveform_length - 1); + ring_waveform_length = (uint32_t)synthio_block_slot_get_limited(¬e->ring_waveform_loop_end, ring_waveform_start + 1, ring_waveform_length); ring_dds_rate = synthio_frequency_convert_scaled_to_dds((uint64_t)note->ring_frequency_bent * (ring_waveform_length - ring_waveform_start), sample_rate); uint32_t lim = ring_waveform_length << SYNTHIO_FREQUENCY_SHIFT; if (ring_dds_rate > lim / sizeof(int16_t)) { @@ -259,7 +270,7 @@ static bool synth_note_into_buffer(synthio_synth_t *synth, int chan, int32_t *ou accum = accum - lim + offset; } int16_t idx = accum >> SYNTHIO_FREQUENCY_SHIFT; - int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768; + int16_t wi = (ring_waveform[idx] * out_buffer32[i]) / 32768; // consider for synthio_sat16 but had a weird artificat out_buffer32[i] = wi; } synth->ring_accum[chan] = accum; @@ -281,12 +292,12 @@ static mp_obj_t synthio_synth_get_note_filter(mp_obj_t note_obj) { static void sum_with_loudness(int32_t *out_buffer32, int32_t *tmp_buffer32, int16_t loudness[2], size_t dur, int synth_chan) { if (synth_chan == 1) { for (size_t i = 0; i < dur; i++) { - *out_buffer32++ += (*tmp_buffer32++ *loudness[0]) >> 16; + *out_buffer32++ += synthio_sat16((*tmp_buffer32++ *loudness[0]), 16); } } else { for (size_t i = 0; i < dur; i++) { - *out_buffer32++ += (*tmp_buffer32 * loudness[0]) >> 16; - *out_buffer32++ += (*tmp_buffer32++ *loudness[1]) >> 16; + *out_buffer32++ += synthio_sat16((*tmp_buffer32 * loudness[0]), 16); + *out_buffer32++ += synthio_sat16((*tmp_buffer32++ *loudness[1]), 16); } } } @@ -299,7 +310,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t return; } - shared_bindings_synthio_lfo_tick(synth->sample_rate); + shared_bindings_synthio_lfo_tick(synth->base.sample_rate, SYNTHIO_MAX_DUR); synth->buffer_index = !synth->buffer_index; synth->other_channel = 1 - channel; @@ -308,9 +319,9 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t uint16_t dur = MIN(SYNTHIO_MAX_DUR, synth->span.dur); synth->span.dur -= dur; - int32_t out_buffer32[SYNTHIO_MAX_DUR * synth->channel_count]; + int32_t out_buffer32[SYNTHIO_MAX_DUR * synth->base.channel_count]; int32_t tmp_buffer32[SYNTHIO_MAX_DUR]; - memset(out_buffer32, 0, synth->channel_count * dur * sizeof(int32_t)); + memset(out_buffer32, 0, synth->base.channel_count * dur * sizeof(int32_t)); for (int chan = 0; chan < CIRCUITPY_SYNTHIO_MAX_CHANNELS; chan++) { mp_obj_t note_obj = synth->span.note_obj[chan]; @@ -335,19 +346,20 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t mp_obj_t filter_obj = synthio_synth_get_note_filter(note_obj); if (filter_obj != mp_const_none) { synthio_note_obj_t *note = MP_OBJ_TO_PTR(note_obj); - synthio_biquad_filter_samples(¬e->filter_state, tmp_buffer32, dur); + common_hal_synthio_biquad_tick(filter_obj); + synthio_biquad_filter_samples(filter_obj, ¬e->filter_state, tmp_buffer32, dur); } // adjust loudness by envelope - sum_with_loudness(out_buffer32, tmp_buffer32, loudness, dur, synth->channel_count); + sum_with_loudness(out_buffer32, tmp_buffer32, loudness, dur, synth->base.channel_count); } int16_t *out_buffer16 = (int16_t *)(void *)synth->buffers[synth->buffer_index]; // mix down audio - for (size_t i = 0; i < dur * synth->channel_count; i++) { + for (size_t i = 0; i < dur * synth->base.channel_count; i++) { int32_t sample = out_buffer32[i]; - out_buffer16[i] = mix_down_sample(sample); + out_buffer16[i] = synthio_mix_down_sample(sample, SYNTHIO_MIX_DOWN_SCALE(CIRCUITPY_SYNTHIO_MAX_CHANNELS)); } // advance envelope states @@ -359,7 +371,7 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **bufptr, uint32_t synthio_envelope_state_step(&synth->envelope_state[chan], synthio_synth_get_note_envelope(synth, note_obj), dur); } - *buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE * synth->channel_count; + *buffer_length = synth->last_buffer_length = dur * SYNTHIO_BYTES_PER_SAMPLE * synth->base.channel_count; *bufptr = (uint8_t *)out_buffer16; } @@ -370,17 +382,14 @@ void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_outp synth->other_channel = -1; } -bool synthio_synth_deinited(synthio_synth_t *synth) { - return synth->buffers[0] == NULL; -} - void synthio_synth_deinit(synthio_synth_t *synth) { synth->buffers[0] = NULL; synth->buffers[1] = NULL; + audiosample_mark_deinit(&synth->base); } void synthio_synth_envelope_set(synthio_synth_t *synth, mp_obj_t envelope_obj) { - synthio_envelope_definition_set(&synth->global_envelope_definition, envelope_obj, synth->sample_rate); + synthio_envelope_definition_set(&synth->global_envelope_definition, envelope_obj, synth->base.sample_rate); synth->envelope_obj = envelope_obj; } @@ -392,12 +401,16 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe synthio_synth_parse_waveform(&synth->waveform_bufinfo, waveform_obj); mp_arg_validate_int_range(channel_count, 1, 2, MP_QSTR_channel_count); synth->buffer_length = SYNTHIO_MAX_DUR * SYNTHIO_BYTES_PER_SAMPLE * channel_count; - synth->buffers[0] = m_malloc(synth->buffer_length); - synth->buffers[1] = m_malloc(synth->buffer_length); - synth->channel_count = channel_count; + synth->buffers[0] = m_malloc_without_collect(synth->buffer_length); + synth->buffers[1] = m_malloc_without_collect(synth->buffer_length); + synth->base.channel_count = channel_count; + synth->base.single_buffer = false; synth->other_channel = -1; synth->waveform_obj = waveform_obj; - synth->sample_rate = sample_rate; + synth->base.sample_rate = sample_rate; + synth->base.bits_per_sample = 16; + synth->base.samples_signed = true; + synth->base.max_buffer_length = synth->buffer_length; synthio_synth_envelope_set(synth, envelope_obj); for (size_t i = 0; i < CIRCUITPY_SYNTHIO_MAX_CHANNELS; i++) { @@ -405,18 +418,6 @@ void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channe } } -void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output, - bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing) { - *single_buffer = false; - *samples_signed = true; - *max_buffer_length = synth->buffer_length; - if (single_channel_output) { - *spacing = synth->channel_count; - } else { - *spacing = 1; - } -} - static void parse_common(mp_buffer_info_t *bufinfo, mp_obj_t o, int16_t what, mp_int_t max_len) { if (o != mp_const_none) { mp_get_buffer_raise(o, bufinfo, MP_BUFFER_READ); @@ -489,8 +490,10 @@ uint32_t synthio_frequency_convert_scaled_to_dds(uint64_t frequency_scaled, int3 return (sample_rate / 2 + frequency_scaled) / sample_rate; } -void shared_bindings_synthio_lfo_tick(uint32_t sample_rate) { - synthio_global_rate_scale = (mp_float_t)SYNTHIO_MAX_DUR / sample_rate; +void shared_bindings_synthio_lfo_tick(uint32_t sample_rate, uint16_t num_samples) { + mp_float_t recip_sample_rate = MICROPY_FLOAT_CONST(1.) / sample_rate; + synthio_global_rate_scale = num_samples * recip_sample_rate; + synthio_global_W_scale = (2 * MP_PI) * recip_sample_rate; synthio_global_tick++; } diff --git a/shared-module/synthio/__init__.h b/shared-module/synthio/__init__.h index b0bca1efcffe4..5162b49fd552e 100644 --- a/shared-module/synthio/__init__.h +++ b/shared-module/synthio/__init__.h @@ -14,8 +14,13 @@ #define SYNTHIO_NOTE_IS_PLAYING(synth, i) ((synth)->envelope_state[(i)].state != SYNTHIO_ENVELOPE_STATE_RELEASE) #define SYNTHIO_FREQUENCY_SHIFT (16) +#define SYNTHIO_MIX_DOWN_RANGE_LOW (-28000) +#define SYNTHIO_MIX_DOWN_RANGE_HIGH (28000) +#define SYNTHIO_MIX_DOWN_SCALE(x) (0xfffffff / (32768 * x - SYNTHIO_MIX_DOWN_RANGE_HIGH)) + #include "shared-module/audiocore/__init__.h" #include "shared-bindings/synthio/__init__.h" +#include "shared-bindings/synthio/Biquad.h" typedef struct { uint16_t dur; @@ -37,10 +42,9 @@ typedef struct { } synthio_envelope_state_t; typedef struct synthio_synth { - uint32_t sample_rate; + audiosample_base_t base; uint32_t total_envelope; int16_t *buffers[2]; - uint8_t channel_count; uint16_t buffer_length; uint16_t last_buffer_length; uint8_t other_channel, buffer_index, other_buffer_index; @@ -67,8 +71,6 @@ void synthio_synth_synthesize(synthio_synth_t *synth, uint8_t **buffer, uint32_t void synthio_synth_deinit(synthio_synth_t *synth); bool synthio_synth_deinited(synthio_synth_t *synth); void synthio_synth_init(synthio_synth_t *synth, uint32_t sample_rate, int channel_count, mp_obj_t waveform_obj, mp_obj_t envelope); -void synthio_synth_get_buffer_structure(synthio_synth_t *synth, bool single_channel_output, - bool *single_buffer, bool *samples_signed, uint32_t *max_buffer_length, uint8_t *spacing); void synthio_synth_reset_buffer(synthio_synth_t *synth, bool single_channel_output, uint8_t channel); void synthio_synth_parse_waveform(mp_buffer_info_t *bufinfo_waveform, mp_obj_t waveform_obj); void synthio_synth_parse_filter(mp_buffer_info_t *bufinfo_filter, mp_obj_t filter_obj); @@ -79,6 +81,8 @@ bool synthio_span_change_note(synthio_synth_t *synth, mp_obj_t old_note, mp_obj_ void synthio_envelope_step(synthio_envelope_definition_t *definition, synthio_envelope_state_t *state, int n_samples); void synthio_envelope_definition_set(synthio_envelope_definition_t *envelope, mp_obj_t obj, uint32_t sample_rate); +int16_t synthio_mix_down_sample(int32_t sample, int32_t scale); + uint64_t synthio_frequency_convert_float_to_scaled(mp_float_t frequency_hz); uint32_t synthio_frequency_convert_float_to_dds(mp_float_t frequency_hz, int32_t sample_rate); uint32_t synthio_frequency_convert_scaled_to_dds(uint64_t frequency_scaled, int32_t sample_rate); @@ -88,6 +92,8 @@ int synthio_lfo_step(synthio_lfo_state_t *state, uint16_t dur); int synthio_sweep_step(synthio_lfo_state_t *state, uint16_t dur); int synthio_sweep_in_step(synthio_lfo_state_t *state, uint16_t dur); -extern mp_float_t synthio_global_rate_scale; +extern mp_float_t synthio_global_rate_scale, synthio_global_W_scale; extern uint8_t synthio_global_tick; -void shared_bindings_synthio_lfo_tick(uint32_t sample_rate); +void shared_bindings_synthio_lfo_tick(uint32_t sample_rate, uint16_t num_samples); + +int16_t synthio_sat16(int32_t n, int rshift); diff --git a/shared-module/terminalio/Terminal.c b/shared-module/terminalio/Terminal.c index e6f1cb23111ff..6e73804ea3adf 100644 --- a/shared-module/terminalio/Terminal.c +++ b/shared-module/terminalio/Terminal.c @@ -8,21 +8,152 @@ #include "shared-module/fontio/BuiltinFont.h" #include "shared-bindings/displayio/TileGrid.h" +#include "shared-bindings/displayio/Palette.h" #include "shared-bindings/terminalio/Terminal.h" +#include "shared-bindings/fontio/BuiltinFont.h" +#if CIRCUITPY_LVFONTIO +#include "shared-bindings/lvfontio/OnDiskFont.h" +#endif #if CIRCUITPY_STATUS_BAR #include "shared-bindings/supervisor/__init__.h" #include "shared-bindings/supervisor/StatusBar.h" #endif +#include "supervisor/shared/serial.h" + +uint16_t terminalio_terminal_get_glyph_index(mp_obj_t font, mp_uint_t codepoint, bool *is_full_width) { + if (is_full_width != NULL) { + *is_full_width = false; // Default to not full width + } + + #if CIRCUITPY_LVFONTIO + if (mp_obj_is_type(font, &lvfontio_ondiskfont_type)) { + // For LV fonts, we need to cache the glyph first + lvfontio_ondiskfont_t *lv_font = MP_OBJ_TO_PTR(font); + bool full_width = false; + int16_t slot = common_hal_lvfontio_ondiskfont_cache_glyph(lv_font, codepoint, &full_width); + + if (is_full_width != NULL) { + *is_full_width = full_width; + } + + if (slot == -1) { + // Not found or couldn't cache + return 0xffff; + } + return (uint16_t)slot; + } + #endif + + #if CIRCUITPY_FONTIO + if (mp_obj_is_type(font, &fontio_builtinfont_type)) { + // Use the standard fontio function + fontio_builtinfont_t *fontio_font = MP_OBJ_TO_PTR(font); + uint8_t index = fontio_builtinfont_get_glyph_index(fontio_font, codepoint); + if (index == 0xff) { + return 0xffff; + } + return index; + } + #endif + + // Unsupported font type + return 0xffff; +} + +static void wrap_cursor(uint16_t width, uint16_t height, uint16_t *cursor_x, uint16_t *cursor_y) { + if (*cursor_x >= width) { + *cursor_y = *cursor_y + 1; + *cursor_x %= width; + } + if (*cursor_y >= height) { + *cursor_y %= height; + } +} + +static void release_current_glyph(displayio_tilegrid_t *tilegrid, mp_obj_t font, uint16_t x, uint16_t y) { + #if CIRCUITPY_LVFONTIO + if (!mp_obj_is_type(font, &lvfontio_ondiskfont_type)) { + return; + } + uint16_t current_tile = common_hal_displayio_tilegrid_get_tile(tilegrid, x, y); + if (current_tile == 0) { + } + common_hal_lvfontio_ondiskfont_release_glyph(MP_OBJ_TO_PTR(font), current_tile); + #endif +} + +static void terminalio_terminal_set_tile(terminalio_terminal_obj_t *self, bool status_bar, mp_uint_t character, bool release_glyphs) { + displayio_tilegrid_t *tilegrid = self->scroll_area; + uint16_t *x = &self->cursor_x; + uint16_t *y = &self->cursor_y; + uint16_t w = self->scroll_area->width_in_tiles; + uint16_t h = self->scroll_area->height_in_tiles; + if (status_bar) { + tilegrid = self->status_bar; + x = &self->status_x; + y = &self->status_y; + w = self->status_bar->width_in_tiles; + h = self->status_bar->height_in_tiles; + } + if (release_glyphs) { + release_current_glyph(tilegrid, self->font, *x, *y); + } + bool is_full_width; + uint16_t new_tile = terminalio_terminal_get_glyph_index(self->font, character, &is_full_width); + if (new_tile == 0xffff) { + // Missing glyph. + return; + } + // If there is only half width left, then fill it with a space and wrap to the next line. + if (is_full_width && *x == w - 1) { + uint16_t space = terminalio_terminal_get_glyph_index(self->font, ' ', NULL); + common_hal_displayio_tilegrid_set_tile(tilegrid, *x, *y, space); + *x = *x + 1; + wrap_cursor(w, h, x, y); + if (release_glyphs) { + release_current_glyph(tilegrid, self->font, *x, *y); + } + } + common_hal_displayio_tilegrid_set_tile(tilegrid, *x, *y, new_tile); + *x = *x + 1; + wrap_cursor(w, h, x, y); + if (is_full_width) { + if (release_glyphs) { + release_current_glyph(tilegrid, self->font, *x, *y); + } + common_hal_displayio_tilegrid_set_tile(tilegrid, *x, *y, new_tile + 1); + *x = *x + 1; + wrap_cursor(w, h, x, y); + } +} + +// Helper function to set all tiles in a tilegrid with optional glyph release +static void terminalio_terminal_set_all_tiles(terminalio_terminal_obj_t *self, bool status_bar, mp_uint_t character, bool release_glyphs) { + uint16_t *x = &self->cursor_x; + uint16_t *y = &self->cursor_y; + if (status_bar) { + x = &self->status_x; + y = &self->status_y; + } + *x = 0; + *y = 0; + terminalio_terminal_set_tile(self, status_bar, character, release_glyphs); + while (*x != 0 || *y != 0) { + terminalio_terminal_set_tile(self, status_bar, character, release_glyphs); + } +} + void terminalio_terminal_clear_status_bar(terminalio_terminal_obj_t *self) { if (self->status_bar) { - common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0); + terminalio_terminal_set_all_tiles(self, true, ' ', true); } } + void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, - displayio_tilegrid_t *scroll_area, const fontio_builtinfont_t *font, + displayio_tilegrid_t *scroll_area, mp_obj_t font, displayio_tilegrid_t *status_bar) { self->cursor_x = 0; self->cursor_y = 0; @@ -32,20 +163,43 @@ void common_hal_terminalio_terminal_construct(terminalio_terminal_obj_t *self, self->status_x = 0; self->status_y = 0; self->first_row = 0; - common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0); + self->vt_scroll_top = 0; + self->vt_scroll_end = self->scroll_area->height_in_tiles - 1; + terminalio_terminal_set_all_tiles(self, false, ' ', false); if (self->status_bar) { - common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0); + terminalio_terminal_set_all_tiles(self, true, ' ', false); } common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 1); } size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, const byte *data, size_t len, int *errcode) { + #define SCRNMOD(x) (((x) + (self->scroll_area->top_left_y)) % (self->scroll_area->height_in_tiles)) + // Make sure the terminal is initialized before we do anything with it. if (self->scroll_area == NULL) { return len; } + #if CIRCUITPY_TERMINALIO_VT100 + uint32_t _select_color(uint16_t ascii_color) { + uint32_t color_value = 0; + if ((ascii_color & 1) > 0) { + color_value += 0xff0000; + } + if ((ascii_color & 2) > 0) { + color_value += 0x00ff00; + } + if ((ascii_color & 4) > 0) { + color_value += 0x0000ff; + } + + return color_value; + } + + displayio_palette_t *terminal_palette = self->scroll_area->pixel_shader; + #endif + const byte *i = data; uint16_t start_y = self->cursor_y; while (i < data + len) { @@ -61,30 +215,21 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con self->osc_command == 0 && self->status_bar != NULL && self->status_y < self->status_bar->height_in_tiles) { - uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c); - if (tile_index != 0xff) { - // Clear the tile grid before we start putting new info. - if (self->status_x == 0 && self->status_y == 0) { - common_hal_displayio_tilegrid_set_all_tiles(self->status_bar, 0); - } - common_hal_displayio_tilegrid_set_tile(self->status_bar, self->status_x, self->status_y, tile_index); - self->status_x++; - if (self->status_x >= self->status_bar->width_in_tiles) { - self->status_y++; - self->status_x %= self->status_bar->width_in_tiles; - } + // Clear the tile grid before we start putting new info. + if (self->status_x == 0 && self->status_y == 0) { + terminalio_terminal_set_all_tiles(self, true, ' ', true); } + terminalio_terminal_set_tile(self, true, c, true); } continue; } - // Always handle ASCII. - if (c < 128) { - if (c >= 0x20 && c <= 0x7e) { - uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c); - common_hal_displayio_tilegrid_set_tile(self->scroll_area, self->cursor_x, self->cursor_y, tile_index); - self->cursor_x++; - } else if (c == '\r') { + if (c < 0x20) { + if (c == '\r') { self->cursor_x = 0; + } else if (c == '\t') { + for (uint8_t space_i = 0; space_i < 4; space_i++) { + terminalio_terminal_set_tile(self, false, ' ', true); + } } else if (c == '\n') { self->cursor_y++; // Commands below are used by MicroPython in the REPL @@ -94,84 +239,179 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con } } else if (c == 0x1b) { // Handle commands of the form [ESC]. where . is not yet known. - uint16_t n = 0; + int16_t vt_args[3] = {0, 0, 0}; uint8_t j = 1; + #if CIRCUITPY_TERMINALIO_VT100 + uint8_t n_args = 1; + #endif for (; j < 6; j++) { if ('0' <= i[j] && i[j] <= '9') { - n = n * 10 + (i[j] - '0'); + vt_args[0] = vt_args[0] * 10 + (i[j] - '0'); } else { c = i[j]; break; } } if (i[0] == '[') { - if (i[1] == 'K') { - // Clear the rest of the line. - for (uint16_t k = self->cursor_x; k < self->scroll_area->width_in_tiles; k++) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, k, self->cursor_y, 0); + for (uint8_t i_args = 1; i_args < 3 && c == ';'; i_args++) { + vt_args[i_args] = 0; + for (++j; j < 12; j++) { + if ('0' <= i[j] && i[j] <= '9') { + vt_args[i_args] = vt_args[i_args] * 10 + (i[j] - '0'); + #if CIRCUITPY_TERMINALIO_VT100 + n_args = i_args + 1; + #endif + } else { + c = i[j]; + break; + } } - i += 2; + } + if (c == '?') { + #if CIRCUITPY_TERMINALIO_VT100 + if (i[2] == '2' && i[3] == '5') { + // cursor visibility commands + if (i[4] == 'h') { + // make cursor visible + // not implemented yet + } else if (i[4] == 'l') { + // make cursor invisible + // not implemented yet + } + } + i += 5; + #endif } else { - if (c == 'D') { - if (n > self->cursor_x) { + if (c == 'K') { + int16_t original_cursor_x = self->cursor_x; + int16_t original_cursor_y = self->cursor_y; + int16_t clr_start = self->cursor_x; + int16_t clr_end = self->scroll_area->width_in_tiles; + #if CIRCUITPY_TERMINALIO_VT100 + if (vt_args[0] == 1) { + clr_start = 0; + clr_end = self->cursor_x; + } else if (vt_args[0] == 2) { + clr_start = 0; + } + self->cursor_x = clr_start; + #endif + // Clear the (start/rest/all) of the line. + for (uint16_t k = clr_start; k < clr_end; k++) { + terminalio_terminal_set_tile(self, false, ' ', true); + } + self->cursor_x = original_cursor_x; + self->cursor_y = original_cursor_y; + } else if (c == 'D') { + if (vt_args[0] > self->cursor_x) { self->cursor_x = 0; } else { - self->cursor_x -= n; + self->cursor_x -= vt_args[0]; } - } - if (c == 'J') { - if (n == 2) { + } else if (c == 'J') { + if (vt_args[0] == 2) { common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, 0); self->cursor_x = self->cursor_y = start_y = 0; - n = 0; - common_hal_displayio_tilegrid_set_all_tiles(self->scroll_area, 0); + terminalio_terminal_set_all_tiles(self, false, ' ', true); } - } - if (c == ';') { - uint16_t m = 0; - for (++j; j < 9; j++) { - if ('0' <= i[j] && i[j] <= '9') { - m = m * 10 + (i[j] - '0'); - } else { - c = i[j]; - break; - } + } else if (c == 'H') { + if (vt_args[0] > 0) { + vt_args[0]--; } - if (c == 'H') { - if (n > 0) { - n--; - } - if (m > 0) { - m--; - } - if (n >= self->scroll_area->height_in_tiles) { - n = self->scroll_area->height_in_tiles - 1; + if (vt_args[1] > 0) { + vt_args[1]--; + } + if (vt_args[0] >= self->scroll_area->height_in_tiles) { + vt_args[0] = self->scroll_area->height_in_tiles - 1; + } + if (vt_args[1] >= self->scroll_area->width_in_tiles) { + vt_args[1] = self->scroll_area->width_in_tiles - 1; + } + vt_args[0] = SCRNMOD(vt_args[0]); + self->cursor_x = vt_args[1]; + self->cursor_y = vt_args[0]; + start_y = self->cursor_y; + #if CIRCUITPY_TERMINALIO_VT100 + } else if (c == 'm') { + for (uint8_t i_args = 0; i_args < n_args; i_args++) { + if ((vt_args[i_args] >= 40 && vt_args[i_args] <= 47) || (vt_args[i_args] >= 30 && vt_args[i_args] <= 37)) { + common_hal_displayio_palette_set_color(terminal_palette, 1 - (vt_args[i_args] / 40), _select_color(vt_args[i_args] % 10)); } - if (m >= self->scroll_area->width_in_tiles) { - m = self->scroll_area->width_in_tiles - 1; + if (vt_args[i_args] == 0) { + common_hal_displayio_palette_set_color(terminal_palette, 0, 0x000000); + common_hal_displayio_palette_set_color(terminal_palette, 1, 0xffffff); } - n = (n + self->scroll_area->top_left_y) % self->scroll_area->height_in_tiles; - self->cursor_x = m; - self->cursor_y = n; - start_y = self->cursor_y; } + } else if (c == 'r') { + if (vt_args[0] < vt_args[1] && vt_args[0] >= 1 && vt_args[1] <= self->scroll_area->height_in_tiles) { + self->vt_scroll_top = vt_args[0] - 1; + self->vt_scroll_end = vt_args[1] - 1; + } else { + self->vt_scroll_top = 0; + self->vt_scroll_end = self->scroll_area->height_in_tiles - 1; + } + self->cursor_x = 0; + self->cursor_y = self->scroll_area->top_left_y % self->scroll_area->height_in_tiles; + start_y = self->cursor_y; + #endif } i += j + 1; - continue; } + #if CIRCUITPY_TERMINALIO_VT100 + } else if (i[0] == 'M') { + if (self->cursor_y != SCRNMOD(self->vt_scroll_top)) { + if (self->cursor_y > 0) { + self->cursor_y = self->cursor_y - 1; + } else { + self->cursor_y = self->scroll_area->height_in_tiles - 1; + } + } else { + if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles - 1) { + // Scroll range defined, manually move tiles to perform scroll + for (int16_t irow = self->vt_scroll_end - 1; irow >= self->vt_scroll_top; irow--) { + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, SCRNMOD(irow + 1), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, SCRNMOD(irow))); + } + } + self->cursor_x = 0; + int16_t old_y = self->cursor_y; + // Fill the row with spaces. + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + terminalio_terminal_set_tile(self, false, ' ', true); + } + self->cursor_y = old_y; + } else { + // Full screen scroll, just set new top_y pointer and clear row + if (self->cursor_y > 0) { + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->cursor_y - 1); + } else { + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, self->scroll_area->height_in_tiles - 1); + } + + self->cursor_x = 0; + self->cursor_y = self->scroll_area->top_left_y; + // Fill the row with spaces. + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + terminalio_terminal_set_tile(self, false, ' ', true); + } + self->cursor_y = self->scroll_area->top_left_y; + } + self->cursor_x = 0; + } + start_y = self->cursor_y; + i++; + } else if (i[0] == 'D') { + self->cursor_y++; + i++; + #endif } else if (i[0] == ']' && c == ';') { self->in_osc_command = true; - self->osc_command = n; + self->osc_command = vt_args[0]; i += j + 1; } } } else { - uint8_t tile_index = fontio_builtinfont_get_glyph_index(self->font, c); - if (tile_index != 0xff) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, self->cursor_x, self->cursor_y, tile_index); - self->cursor_x++; - - } + terminalio_terminal_set_tile(self, false, c, true); } if (self->cursor_x >= self->scroll_area->width_in_tiles) { self->cursor_y++; @@ -181,12 +421,31 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con self->cursor_y %= self->scroll_area->height_in_tiles; } if (self->cursor_y != start_y) { - // clear the new row in case of scroll up - if (self->cursor_y == self->scroll_area->top_left_y) { - for (uint16_t j = 0; j < self->scroll_area->width_in_tiles; j++) { - common_hal_displayio_tilegrid_set_tile(self->scroll_area, j, self->cursor_y, 0); + if (((self->cursor_y + self->scroll_area->height_in_tiles) - 1) % self->scroll_area->height_in_tiles == SCRNMOD(self->vt_scroll_end)) { + #if CIRCUITPY_TERMINALIO_VT100 + if (self->vt_scroll_top != 0 || self->vt_scroll_end != self->scroll_area->height_in_tiles - 1) { + // Scroll range defined, manually move tiles to perform scroll + self->cursor_y = SCRNMOD(self->vt_scroll_end); + + for (int16_t irow = self->vt_scroll_top; irow < self->vt_scroll_end; irow++) { + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + common_hal_displayio_tilegrid_set_tile(self->scroll_area, icol, SCRNMOD(irow), common_hal_displayio_tilegrid_get_tile(self->scroll_area, icol, SCRNMOD(irow + 1))); + } + } + } + #endif + if (self->vt_scroll_top == 0 && self->vt_scroll_end == self->scroll_area->height_in_tiles - 1) { + // Full screen scroll, just set new top_y pointer + common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles); } - common_hal_displayio_tilegrid_set_top_left(self->scroll_area, 0, (self->cursor_y + self->scroll_area->height_in_tiles + 1) % self->scroll_area->height_in_tiles); + // clear the new row in case of scroll up + self->cursor_x = 0; + int16_t old_y = self->cursor_y; + for (int16_t icol = 0; icol < self->scroll_area->width_in_tiles; icol++) { + terminalio_terminal_set_tile(self, false, ' ', true); + } + self->cursor_x = 0; + self->cursor_y = old_y; } start_y = self->cursor_y; } @@ -194,6 +453,13 @@ size_t common_hal_terminalio_terminal_write(terminalio_terminal_obj_t *self, con return i - data; } +uint16_t common_hal_terminalio_terminal_get_cursor_x(terminalio_terminal_obj_t *self) { + return self->cursor_x; +} +uint16_t common_hal_terminalio_terminal_get_cursor_y(terminalio_terminal_obj_t *self) { + return self->cursor_y; +} + bool common_hal_terminalio_terminal_ready_to_tx(terminalio_terminal_obj_t *self) { return self->scroll_area != NULL; } diff --git a/shared-module/terminalio/Terminal.h b/shared-module/terminalio/Terminal.h index 17230a74066c1..8bf294cb27ff7 100644 --- a/shared-module/terminalio/Terminal.h +++ b/shared-module/terminalio/Terminal.h @@ -15,7 +15,7 @@ typedef struct { mp_obj_base_t base; - const fontio_builtinfont_t *font; + mp_obj_t font; // Can be fontio_builtinfont_t or lvfontio_ondiskfont_t uint16_t cursor_x; uint16_t cursor_y; displayio_tilegrid_t *scroll_area; @@ -23,8 +23,11 @@ typedef struct { uint16_t status_x; uint16_t status_y; uint16_t first_row; + uint16_t vt_scroll_top; + uint16_t vt_scroll_end; uint16_t osc_command; bool in_osc_command; } terminalio_terminal_obj_t; extern void terminalio_terminal_clear_status_bar(terminalio_terminal_obj_t *self); +uint16_t terminalio_terminal_get_glyph_index(mp_obj_t font, mp_uint_t codepoint, bool *is_full_width); diff --git a/shared-module/tilepalettemapper/TilePaletteMapper.c b/shared-module/tilepalettemapper/TilePaletteMapper.c new file mode 100644 index 0000000000000..13711b2c2537d --- /dev/null +++ b/shared-module/tilepalettemapper/TilePaletteMapper.c @@ -0,0 +1,104 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT +#include +#include "py/runtime.h" +#include "shared-bindings/tilepalettemapper/TilePaletteMapper.h" +#include "shared-bindings/displayio/Palette.h" +#include "shared-bindings/displayio/ColorConverter.h" +#include "shared-bindings/displayio/TileGrid.h" + +void common_hal_tilepalettemapper_tilepalettemapper_construct(tilepalettemapper_tilepalettemapper_t *self, + mp_obj_t pixel_shader, uint16_t input_color_count) { + self->pixel_shader = pixel_shader; + self->input_color_count = input_color_count; + self->tilegrid = mp_const_none; +} + +uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_width(tilepalettemapper_tilepalettemapper_t *self) { + return self->width_in_tiles; +} + +uint16_t common_hal_tilepalettemapper_tilepalettemapper_get_height(tilepalettemapper_tilepalettemapper_t *self) { + return self->height_in_tiles; +} + +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_pixel_shader(tilepalettemapper_tilepalettemapper_t *self) { + return self->pixel_shader; +} + +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_tilegrid(tilepalettemapper_tilepalettemapper_t *self) { + return self->tilegrid; +} + +mp_obj_t common_hal_tilepalettemapper_tilepalettemapper_get_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y) { + int index = x + y * self->width_in_tiles; + mp_obj_t result[self->input_color_count]; + for (uint32_t i = 0; i < self->input_color_count; i++) { + result[i] = mp_obj_new_int(self->tile_mappings[index][i]); + } + return mp_obj_new_tuple(self->input_color_count, result); +} + +void common_hal_tilepalettemapper_tilepalettemapper_set_mapping(tilepalettemapper_tilepalettemapper_t *self, uint16_t x, uint16_t y, size_t len, mp_obj_t *items) { + uint32_t palette_max; + if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { + palette_max = common_hal_displayio_palette_get_len(self->pixel_shader) - 1; + } else { // colorconverter type + palette_max = 0xFFFFFF; + } + + for (uint16_t i = 0; i < MIN(len, self->input_color_count); i++) { + int mapping_val = mp_arg_validate_type_int(items[i], MP_QSTR_mapping_value); + mp_arg_validate_int_range(mapping_val, 0, palette_max, MP_QSTR_mapping_value); + self->tile_mappings[y * self->width_in_tiles + x][i] = mapping_val; + } + displayio_tilegrid_mark_tile_dirty(self->tilegrid, x, y); +} + +void tilepalettemapper_tilepalettemapper_get_color(tilepalettemapper_tilepalettemapper_t *self, const _displayio_colorspace_t *colorspace, displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color, uint16_t x_tile_index, uint16_t y_tile_index) { + if (x_tile_index >= self->width_in_tiles || y_tile_index >= self->height_in_tiles) { + if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { + displayio_palette_get_color(self->pixel_shader, colorspace, input_pixel, output_color); + } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { + displayio_colorconverter_convert(self->pixel_shader, colorspace, input_pixel, output_color); + } + return; + } + uint16_t tile_index = y_tile_index * self->width_in_tiles + x_tile_index; + uint32_t mapped_index = self->tile_mappings[tile_index][input_pixel->pixel]; + displayio_input_pixel_t tmp_pixel; + tmp_pixel.pixel = mapped_index; + if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { + displayio_palette_get_color(self->pixel_shader, colorspace, &tmp_pixel, output_color); + } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { + displayio_colorconverter_convert(self->pixel_shader, colorspace, &tmp_pixel, output_color); + } + +} + +void tilepalettemapper_tilepalettemapper_bind(tilepalettemapper_tilepalettemapper_t *self, displayio_tilegrid_t *tilegrid) { + if (self->tilegrid != mp_const_none) { + mp_raise_RuntimeError(MP_ERROR_TEXT("TilePaletteMapper may only be bound to a TileGrid once")); + } + self->tilegrid = tilegrid; + self->width_in_tiles = common_hal_displayio_tilegrid_get_width(tilegrid); + self->height_in_tiles = common_hal_displayio_tilegrid_get_height(tilegrid); + + int mappings_len = self->width_in_tiles * self->height_in_tiles; + self->tile_mappings = (uint32_t **)m_malloc(mappings_len * sizeof(uint32_t *)); + for (int i = 0; i < mappings_len; i++) { + self->tile_mappings[i] = (uint32_t *)m_malloc_without_collect(self->input_color_count * sizeof(uint32_t)); + if (mp_obj_is_type(self->pixel_shader, &displayio_palette_type)) { + for (uint16_t j = 0; j < self->input_color_count; j++) { + self->tile_mappings[i][j] = j; + } + } else if (mp_obj_is_type(self->pixel_shader, &displayio_colorconverter_type)) { + for (uint16_t j = 0; j < self->input_color_count; j++) { + self->tile_mappings[i][j] = 0; + } + } + } +} diff --git a/shared-module/tilepalettemapper/TilePaletteMapper.h b/shared-module/tilepalettemapper/TilePaletteMapper.h new file mode 100644 index 0000000000000..d1f535eda11bb --- /dev/null +++ b/shared-module/tilepalettemapper/TilePaletteMapper.h @@ -0,0 +1,28 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries +// +// SPDX-License-Identifier: MIT + + +#pragma once + +#include +#include + +#include "py/obj.h" +#include "shared-module/displayio/Palette.h" +#include "shared-module/displayio/TileGrid.h" + +typedef struct { + mp_obj_base_t base; + mp_obj_t pixel_shader; + mp_obj_t tilegrid; + uint16_t width_in_tiles; + uint16_t height_in_tiles; + uint16_t input_color_count; + uint32_t **tile_mappings; +} tilepalettemapper_tilepalettemapper_t; + +void tilepalettemapper_tilepalettemapper_get_color(tilepalettemapper_tilepalettemapper_t *self, const _displayio_colorspace_t *colorspace, displayio_input_pixel_t *input_pixel, displayio_output_pixel_t *output_color, uint16_t x_tile_index, uint16_t y_tile_index); +void tilepalettemapper_tilepalettemapper_bind(tilepalettemapper_tilepalettemapper_t *self, displayio_tilegrid_t *tilegrid); diff --git a/shared-module/tilepalettemapper/__init__.c b/shared-module/tilepalettemapper/__init__.c new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/shared-module/touchio/TouchIn.c b/shared-module/touchio/TouchIn.c index 9334b369f6579..268055d14bf53 100644 --- a/shared-module/touchio/TouchIn.c +++ b/shared-module/touchio/TouchIn.c @@ -12,15 +12,18 @@ #include "py/mphal.h" #include "shared-bindings/touchio/TouchIn.h" #include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/digitalio/Pull.h" -// This is a capacitive touch sensing routine using a single digital -// pin. The pin should be connected to the sensing pad, and to ground +// This is a capacitive touch sensing routine using a single digital pin. +// For pull==PULL_DOWN, the pin should be connected to the sensing pad and to ground // via a 1Mohm or thereabout drain resistor. When a reading is taken, // the pin's capacitance is charged by setting it to a digital output // 'high' for a few microseconds, and then it is changed to a high // impedance input. We measure how long it takes to discharge through // the resistor (around 50us), using a busy-waiting loop, and average // over N_SAMPLES cycles to reduce the effects of noise. +// For the pull=PULL_UP case, the 1M resistor is connected to 3v3, the pin is +// driven 'low' then measure how long it takes to go 'high'. #define N_SAMPLES 10 #define TIMEOUT_TICKS 10000 @@ -28,18 +31,19 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { uint16_t ticks = 0; - + // state to charge pin to: if pull-down or None, pull HIGH, if pull-up, pull LOW + bool pincharge = !(self->pull == PULL_UP); for (uint16_t i = 0; i < N_SAMPLES; i++) { - // set pad to digital output high for 10us to charge it + // set pad to digital output 'pincharge' for 10us to charge it - common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, true, DRIVE_MODE_PUSH_PULL); + common_hal_digitalio_digitalinout_switch_to_output(self->digitalinout, pincharge, DRIVE_MODE_PUSH_PULL); mp_hal_delay_us(10); // set pad back to an input and take some samples common_hal_digitalio_digitalinout_switch_to_input(self->digitalinout, PULL_NONE); - while (common_hal_digitalio_digitalinout_get_value(self->digitalinout)) { + while (common_hal_digitalio_digitalinout_get_value(self->digitalinout) == pincharge) { if (ticks >= TIMEOUT_TICKS) { return TIMEOUT_TICKS; } @@ -49,16 +53,22 @@ static uint16_t get_raw_reading(touchio_touchin_obj_t *self) { return ticks; } -void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin) { +void common_hal_touchio_touchin_construct(touchio_touchin_obj_t *self, const mcu_pin_obj_t *pin, const digitalio_pull_t pull) { common_hal_mcu_pin_claim(pin); self->digitalinout = mp_obj_malloc(digitalio_digitalinout_obj_t, &digitalio_digitalinout_type); common_hal_digitalio_digitalinout_construct(self->digitalinout, pin); + self->pull = pull; + uint16_t raw_reading = get_raw_reading(self); if (raw_reading == TIMEOUT_TICKS) { common_hal_touchio_touchin_deinit(self); - mp_raise_ValueError(MP_ERROR_TEXT("No pulldown on pin; 1Mohm recommended")); + if (self->pull == PULL_UP) { + mp_raise_ValueError(MP_ERROR_TEXT("No pullup on pin; 1Mohm recommended")); + } else { + mp_raise_ValueError(MP_ERROR_TEXT("No pulldown on pin; 1Mohm recommended")); + } } self->threshold = raw_reading * 1.05 + 100; } @@ -76,7 +86,7 @@ void common_hal_touchio_touchin_deinit(touchio_touchin_obj_t *self) { self->digitalinout = MP_OBJ_NULL; } -void touchin_reset() { +void touchin_reset(void) { } bool common_hal_touchio_touchin_get_value(touchio_touchin_obj_t *self) { diff --git a/shared-module/touchio/TouchIn.h b/shared-module/touchio/TouchIn.h index a03811a1823d4..1d35b904f35d8 100644 --- a/shared-module/touchio/TouchIn.h +++ b/shared-module/touchio/TouchIn.h @@ -15,6 +15,7 @@ typedef struct { mp_obj_base_t base; digitalio_digitalinout_obj_t *digitalinout; + digitalio_pull_t pull; uint16_t threshold; } touchio_touchin_obj_t; diff --git a/shared-module/usb/core/Device.c b/shared-module/usb/core/Device.c index 4ed0d410523e4..83def37de914e 100644 --- a/shared-module/usb/core/Device.c +++ b/shared-module/usb/core/Device.c @@ -1,17 +1,22 @@ // This file is part of the CircuitPython project: https://circuitpython.org // // SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2025 Sam Blenny // // SPDX-License-Identifier: MIT #include "shared-bindings/usb/core/Device.h" #include "tusb_config.h" +#include "supervisor/port.h" +#include "supervisor/port_heap.h" +#include "lib/tinyusb/src/host/hcd.h" #include "lib/tinyusb/src/host/usbh.h" #include "py/runtime.h" #include "shared/runtime/interrupt_char.h" #include "shared-bindings/usb/core/__init__.h" +#include "shared-bindings/usb/util/__init__.h" #include "shared-module/usb/utf16le.h" #include "supervisor/shared/tick.h" #include "supervisor/usb.h" @@ -30,34 +35,78 @@ void tuh_umount_cb(uint8_t dev_addr) { static xfer_result_t _xfer_result; static size_t _actual_len; -bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t device_number) { + +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +// Helper to ensure buffer is DMA-capable for transfer operations +static uint8_t *_ensure_dma_buffer(usb_core_device_obj_t *self, const uint8_t *buffer, size_t len, bool for_write) { + if (port_buffer_is_dma_capable(buffer)) { + return (uint8_t *)buffer; // Already DMA-capable, use directly + } + + uint8_t *dma_buffer = port_malloc(len, true); // true = DMA capable + if (dma_buffer == NULL) { + return NULL; // Allocation failed + } + + // Copy data to DMA buffer if writing + if (for_write && buffer != NULL) { + memcpy(dma_buffer, buffer, len); + } + + return dma_buffer; +} + +#endif +bool common_hal_usb_core_device_construct(usb_core_device_obj_t *self, uint8_t device_address) { if (!tuh_inited()) { mp_raise_RuntimeError(MP_ERROR_TEXT("No usb host port initialized")); } - if (device_number == 0 || device_number > CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) { + if (device_address == 0 || device_address > CFG_TUH_DEVICE_MAX + CFG_TUH_HUB) { return false; } - if ((_mounted_devices & (1 << device_number)) == 0) { + if ((_mounted_devices & (1 << device_address)) == 0) { return false; } - self->device_number = device_number; + self->device_address = device_address; self->first_langid = 0; - _xfer_result = 0xff; + _xfer_result = XFER_RESULT_INVALID; return true; } +bool common_hal_usb_core_device_deinited(usb_core_device_obj_t *self) { + return self->device_address == 0; +} + +void common_hal_usb_core_device_deinit(usb_core_device_obj_t *self) { + if (common_hal_usb_core_device_deinited(self)) { + return; + } + size_t open_size = sizeof(self->open_endpoints); + for (size_t i = 0; i < open_size; i++) { + if (self->open_endpoints[i] != 0) { + tuh_edpt_close(self->device_address, self->open_endpoints[i]); + self->open_endpoints[i] = 0; + } + } + self->device_address = 0; +} + uint16_t common_hal_usb_core_device_get_idVendor(usb_core_device_obj_t *self) { uint16_t vid; uint16_t pid; - tuh_vid_pid_get(self->device_number, &vid, &pid); + if (!tuh_vid_pid_get(self->device_address, &vid, &pid)) { + mp_raise_usb_core_USBError(NULL); + } return vid; } uint16_t common_hal_usb_core_device_get_idProduct(usb_core_device_obj_t *self) { uint16_t vid; uint16_t pid; - tuh_vid_pid_get(self->device_number, &vid, &pid); + if (!tuh_vid_pid_get(self->device_address, &vid, &pid)) { + mp_raise_usb_core_USBError(NULL); + } return pid; } @@ -71,14 +120,109 @@ static void _transfer_done_cb(tuh_xfer_t *xfer) { static bool _wait_for_callback(void) { while (!mp_hal_is_interrupted() && - _xfer_result == 0xff) { + _xfer_result == XFER_RESULT_INVALID) { // The background tasks include TinyUSB which will call the function // we provided above. In other words, the callback isn't in an interrupt. RUN_BACKGROUND_TASKS; } + if (mp_hal_is_interrupted()) { + // Handle case of VM being interrupted by Ctrl-C or autoreload + return false; + } + // Handle callback result code from TinyUSB xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - return result == XFER_RESULT_SUCCESS; + _xfer_result = XFER_RESULT_INVALID; + switch (result) { + case XFER_RESULT_SUCCESS: + return true; + case XFER_RESULT_FAILED: + mp_raise_usb_core_USBError(NULL); + break; + case XFER_RESULT_STALLED: + mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); + break; + case XFER_RESULT_TIMEOUT: + case XFER_RESULT_INVALID: + mp_raise_usb_core_USBTimeoutError(); + break; + } + return false; +} + +static void _prepare_for_transfer(void) { + // Prepare for transfer. Unless there is a timeout, these static globals will + // get modified by the _transfer_done_cb() callback when tinyusb finishes the + // transfer or encounters an error condition. + _xfer_result = XFER_RESULT_INVALID; + _actual_len = 0; +} + +static void _abort_transfer(tuh_xfer_t *xfer) { + bool aborted = tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); + if (aborted) { + // If the transfer was aborted, then we can continue. + return; + } + uint32_t start_time = supervisor_ticks_ms32(); + // If not, we need to wait for it to finish, otherwise we may free memory out from under it. + // Limit the wait time to 10 milliseconds to avoid blocking indefinitely. + while (_xfer_result == XFER_RESULT_INVALID && (supervisor_ticks_ms32() - start_time < 10)) { + // The background tasks include TinyUSB which will call the function + // we provided above. In other words, the callback isn't in an interrupt. + RUN_BACKGROUND_TASKS; + } +} + +// Only frees the transfer buffer on error. +static size_t _handle_timed_transfer_callback(tuh_xfer_t *xfer, mp_int_t timeout, bool our_buffer) { + if (xfer == NULL) { + mp_raise_usb_core_USBError(NULL); + return 0; + } + uint32_t start_time = supervisor_ticks_ms32(); + while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && + !mp_hal_is_interrupted() && + _xfer_result == XFER_RESULT_INVALID) { + // The background tasks include TinyUSB which will call the function + // we provided above. In other words, the callback isn't in an interrupt. + RUN_BACKGROUND_TASKS; + } + if (mp_hal_is_interrupted()) { + // Handle case of VM being interrupted by Ctrl-C or autoreload + _abort_transfer(xfer); + return 0; + } + // Handle transfer result code from TinyUSB + xfer_result_t result = _xfer_result; + _xfer_result = XFER_RESULT_INVALID; + if (our_buffer && result != XFER_RESULT_SUCCESS && result != XFER_RESULT_INVALID) { + port_free(xfer->buffer); + } + switch (result) { + case XFER_RESULT_SUCCESS: + return _actual_len; + case XFER_RESULT_FAILED: + mp_raise_usb_core_USBError(NULL); + break; + case XFER_RESULT_STALLED: + mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); + break; + case XFER_RESULT_TIMEOUT: + // This timeout comes from TinyUSB, so assume that it has stopped the + // transfer (note: timeout logic may be unimplemented on TinyUSB side) + mp_raise_usb_core_USBTimeoutError(); + break; + case XFER_RESULT_INVALID: + // This timeout comes from CircuitPython, not TinyUSB, so tell TinyUSB + // to stop the transfer and then wait to free the buffer. + _abort_transfer(xfer); + if (our_buffer) { + port_free(xfer->buffer); + } + mp_raise_usb_core_USBTimeoutError(); + break; + } + return 0; } static mp_obj_t _get_string(const uint16_t *temp_buf) { @@ -95,41 +239,124 @@ static void _get_langid(usb_core_device_obj_t *self) { } // Two control bytes and one uint16_t language code. uint16_t temp_buf[2]; - if (!tuh_descriptor_get_string(self->device_number, 0, 0, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { - return; + _prepare_for_transfer(); + if (!tuh_descriptor_get_string(self->device_address, 0, 0, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + self->first_langid = temp_buf[1]; } - self->first_langid = temp_buf[1]; } mp_obj_t common_hal_usb_core_device_get_serial_number(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; - _get_langid(self); - if (!tuh_descriptor_get_serial_string(self->device_number, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { return mp_const_none; } - return _get_string(temp_buf); + if (descriptor.iSerialNumber == 0) { + return mp_const_none; + } + // Device does provide this string, so continue + _get_langid(self); + _prepare_for_transfer(); + if (!tuh_descriptor_get_serial_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; } mp_obj_t common_hal_usb_core_device_get_product(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; - _get_langid(self); - if (!tuh_descriptor_get_product_string(self->device_number, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { return mp_const_none; } - return _get_string(temp_buf); + if (descriptor.iProduct == 0) { + return mp_const_none; + } + // Device does provide this string, so continue + _get_langid(self); + _prepare_for_transfer(); + if (!tuh_descriptor_get_product_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; } mp_obj_t common_hal_usb_core_device_get_manufacturer(usb_core_device_obj_t *self) { uint16_t temp_buf[127]; + tusb_desc_device_t descriptor; + // First, be sure not to ask TinyUSB for a non-existent string (avoid error) + if (!tuh_descriptor_get_device_local(self->device_address, &descriptor)) { + return mp_const_none; + } + if (descriptor.iManufacturer == 0) { + return mp_const_none; + } + // Device does provide this string, so continue _get_langid(self); - if (!tuh_descriptor_get_manufacturer_string(self->device_number, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0) || - !_wait_for_callback()) { + _prepare_for_transfer(); + if (!tuh_descriptor_get_manufacturer_string(self->device_address, self->first_langid, temp_buf, sizeof(temp_buf), _transfer_done_cb, 0)) { + mp_raise_usb_core_USBError(NULL); + } else if (_wait_for_callback()) { + return _get_string(temp_buf); + } + return mp_const_none; +} + + +mp_int_t common_hal_usb_core_device_get_bus(usb_core_device_obj_t *self) { + tuh_bus_info_t bus_info; + if (!tuh_bus_info_get(self->device_address, &bus_info)) { + return 0; + } + return bus_info.rhport; +} + +mp_obj_t common_hal_usb_core_device_get_port_numbers(usb_core_device_obj_t *self) { + tuh_bus_info_t bus_info; + if (!tuh_bus_info_get(self->device_address, &bus_info)) { return mp_const_none; } - return _get_string(temp_buf); + if (bus_info.hub_addr == 0) { + return mp_const_none; + } + // USB allows for 5 hubs deep chaining. So we're at most 5 ports deep. + mp_obj_t ports[5]; + size_t port_count = 0; + tuh_bus_info_t current_bus_info = bus_info; + while (current_bus_info.hub_addr != 0 && port_count < MP_ARRAY_SIZE(ports)) { + // Reverse the order of the ports so most downstream comes last. + ports[MP_ARRAY_SIZE(ports) - 1 - port_count] = MP_OBJ_NEW_SMALL_INT(current_bus_info.hub_port); + port_count++; + if (!tuh_bus_info_get(current_bus_info.hub_addr, ¤t_bus_info)) { + break; + } + } + return mp_obj_new_tuple(port_count, ports + (MP_ARRAY_SIZE(ports) - port_count)); +} + +mp_int_t common_hal_usb_core_device_get_speed(usb_core_device_obj_t *self) { + tuh_bus_info_t bus_info; + if (!tuh_bus_info_get(self->device_address, &bus_info)) { + return 0; + } + switch (bus_info.speed) { + case TUSB_SPEED_HIGH: + return PYUSB_SPEED_HIGH; + case TUSB_SPEED_FULL: + return PYUSB_SPEED_FULL; + case TUSB_SPEED_LOW: + return PYUSB_SPEED_LOW; + default: + return 0; + } } void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, mp_int_t configuration) { @@ -140,53 +367,33 @@ void common_hal_usb_core_device_set_configuration(usb_core_device_obj_t *self, m // Get only the config descriptor first. tusb_desc_configuration_t desc; - if (!tuh_descriptor_get_configuration(self->device_number, config_index, &desc, sizeof(desc), _transfer_done_cb, 0) || + if (!tuh_descriptor_get_configuration(self->device_address, config_index, &desc, sizeof(desc), _transfer_done_cb, 0) || !_wait_for_callback()) { return; } // Get the config descriptor plus interfaces and endpoints. self->configuration_descriptor = m_realloc(self->configuration_descriptor, desc.wTotalLength); - if (!tuh_descriptor_get_configuration(self->device_number, config_index, self->configuration_descriptor, desc.wTotalLength, _transfer_done_cb, 0) || + if (!tuh_descriptor_get_configuration(self->device_address, config_index, self->configuration_descriptor, desc.wTotalLength, _transfer_done_cb, 0) || !_wait_for_callback()) { return; } - tuh_configuration_set(self->device_number, configuration, _transfer_done_cb, 0); + tuh_configuration_set(self->device_address, configuration, _transfer_done_cb, 0); _wait_for_callback(); } -static size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout) { - _xfer_result = 0xff; +// Raises an exception on failure. Returns the number of bytes transferred (maybe zero) on success. +static size_t _xfer(tuh_xfer_t *xfer, mp_int_t timeout, bool our_buffer) { + _prepare_for_transfer(); xfer->complete_cb = _transfer_done_cb; if (!tuh_edpt_xfer(xfer)) { + if (our_buffer) { + port_free(xfer->buffer); + } mp_raise_usb_core_USBError(NULL); - } - uint32_t start_time = supervisor_ticks_ms32(); - while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && - !mp_hal_is_interrupted() && - _xfer_result == 0xff) { - // The background tasks include TinyUSB which will call the function - // we provided above. In other words, the callback isn't in an interrupt. - RUN_BACKGROUND_TASKS; - } - if (mp_hal_is_interrupted()) { - tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); return 0; } - xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - if (result == XFER_RESULT_STALLED) { - mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); - } - if (result == 0xff) { - tuh_edpt_abort_xfer(xfer->daddr, xfer->ep_addr); - mp_raise_usb_core_USBTimeoutError(); - } - if (result == XFER_RESULT_SUCCESS) { - return _actual_len; - } - - return 0; + return _handle_timed_transfer_callback(xfer, timeout, our_buffer); } static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) { @@ -206,6 +413,7 @@ static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) { if (self->configuration_descriptor == NULL) { mp_raise_usb_core_USBError(MP_ERROR_TEXT("No configuration set")); + return false; } tusb_desc_configuration_t *desc_cfg = (tusb_desc_configuration_t *)self->configuration_descriptor; @@ -230,7 +438,7 @@ static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) { } tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; - bool open = tuh_edpt_open(self->device_number, desc_ep); + bool open = tuh_edpt_open(self->device_address, desc_ep); if (open) { self->open_endpoints[first_free] = endpoint; } @@ -240,25 +448,67 @@ static bool _open_endpoint(usb_core_device_obj_t *self, mp_int_t endpoint) { mp_int_t common_hal_usb_core_device_write(usb_core_device_obj_t *self, mp_int_t endpoint, const uint8_t *buffer, mp_int_t len, mp_int_t timeout) { if (!_open_endpoint(self, endpoint)) { mp_raise_usb_core_USBError(NULL); + return 0; } + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = _ensure_dma_buffer(self, buffer, len, true); // true = for write + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + #else + uint8_t *dma_buffer = (uint8_t *)buffer; // All memory is DMA-capable + #endif + tuh_xfer_t xfer; - xfer.daddr = self->device_number; + xfer.daddr = self->device_address; xfer.ep_addr = endpoint; - xfer.buffer = (uint8_t *)buffer; + xfer.buffer = dma_buffer; xfer.buflen = len; - return _xfer(&xfer, timeout); + size_t result = _xfer(&xfer, timeout, dma_buffer != buffer); + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + if (dma_buffer != buffer) { + port_free(dma_buffer); + } + #endif + return result; } mp_int_t common_hal_usb_core_device_read(usb_core_device_obj_t *self, mp_int_t endpoint, uint8_t *buffer, mp_int_t len, mp_int_t timeout) { if (!_open_endpoint(self, endpoint)) { mp_raise_usb_core_USBError(NULL); + return 0; } + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = _ensure_dma_buffer(self, buffer, len, false); // false = for read + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + #else + uint8_t *dma_buffer = buffer; // All memory is DMA-capable + #endif + tuh_xfer_t xfer; - xfer.daddr = self->device_number; + xfer.daddr = self->device_address; xfer.ep_addr = endpoint; - xfer.buffer = buffer; + xfer.buffer = dma_buffer; xfer.buflen = len; - return _xfer(&xfer, timeout); + mp_int_t result = _xfer(&xfer, timeout, dma_buffer != buffer); + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Copy data back to original buffer if needed + if (dma_buffer != buffer) { + memcpy(buffer, dma_buffer, result); + port_free(dma_buffer); + } + #endif + + return result; } mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, @@ -267,6 +517,23 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, uint8_t *buffer, mp_int_t len, mp_int_t timeout) { // Timeout is in ms. + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + // Determine if this is a write (host-to-device) or read (device-to-host) transfer + bool is_write = (bmRequestType & 0x80) == 0; // Bit 7: 0=host-to-device, 1=device-to-host + + // Ensure buffer is in DMA-capable memory + uint8_t *dma_buffer = NULL; + if (len > 0 && buffer != NULL) { + dma_buffer = _ensure_dma_buffer(self, buffer, len, is_write); + if (dma_buffer == NULL) { + mp_raise_msg(&mp_type_MemoryError, MP_ERROR_TEXT("Could not allocate DMA capable buffer")); + return 0; + } + } + #else + uint8_t *dma_buffer = buffer; // All memory is DMA-capable + #endif + tusb_control_request_t request = { .bmRequestType = bmRequestType, .bRequest = bRequest, @@ -275,49 +542,36 @@ mp_int_t common_hal_usb_core_device_ctrl_transfer(usb_core_device_obj_t *self, .wLength = len }; tuh_xfer_t xfer = { - .daddr = self->device_number, + .daddr = self->device_address, .ep_addr = 0, .setup = &request, - .buffer = buffer, + .buffer = dma_buffer, .complete_cb = _transfer_done_cb, }; - _xfer_result = 0xff; - + _prepare_for_transfer(); if (!tuh_control_xfer(&xfer)) { mp_raise_usb_core_USBError(NULL); - } - uint32_t start_time = supervisor_ticks_ms32(); - while ((timeout == 0 || supervisor_ticks_ms32() - start_time < (uint32_t)timeout) && - !mp_hal_is_interrupted() && - _xfer_result == 0xff) { - // The background tasks include TinyUSB which will call the function - // we provided above. In other words, the callback isn't in an interrupt. - RUN_BACKGROUND_TASKS; - } - if (mp_hal_is_interrupted()) { - tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr); return 0; } - xfer_result_t result = _xfer_result; - _xfer_result = 0xff; - if (result == XFER_RESULT_STALLED) { - mp_raise_usb_core_USBError(MP_ERROR_TEXT("Pipe error")); - } - if (result == 0xff) { - tuh_edpt_abort_xfer(xfer.daddr, xfer.ep_addr); - mp_raise_usb_core_USBTimeoutError(); - } - if (result == XFER_RESULT_SUCCESS) { - return len; + mp_int_t result = (mp_int_t)_handle_timed_transfer_callback(&xfer, timeout, dma_buffer != buffer); + + #if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE + if (dma_buffer != buffer) { + // Copy data back to original buffer if this was a read transfer + if (buffer != NULL && !is_write) { + memcpy(buffer, dma_buffer, result); + } + port_free(dma_buffer); } + #endif - return 0; + return result; } bool common_hal_usb_core_device_is_kernel_driver_active(usb_core_device_obj_t *self, mp_int_t interface) { #if CIRCUITPY_USB_KEYBOARD_WORKFLOW - if (usb_keyboard_in_use(self->device_number, interface)) { + if (usb_keyboard_in_use(self->device_address, interface)) { return true; } #endif @@ -326,12 +580,12 @@ bool common_hal_usb_core_device_is_kernel_driver_active(usb_core_device_obj_t *s void common_hal_usb_core_device_detach_kernel_driver(usb_core_device_obj_t *self, mp_int_t interface) { #if CIRCUITPY_USB_KEYBOARD_WORKFLOW - usb_keyboard_detach(self->device_number, interface); + usb_keyboard_detach(self->device_address, interface); #endif } void common_hal_usb_core_device_attach_kernel_driver(usb_core_device_obj_t *self, mp_int_t interface) { #if CIRCUITPY_USB_KEYBOARD_WORKFLOW - usb_keyboard_attach(self->device_number, interface); + usb_keyboard_attach(self->device_address, interface); #endif } diff --git a/shared-module/usb/core/Device.h b/shared-module/usb/core/Device.h index 2b628e05cf641..c7392a04ba7bc 100644 --- a/shared-module/usb/core/Device.h +++ b/shared-module/usb/core/Device.h @@ -10,7 +10,7 @@ typedef struct { mp_obj_base_t base; - uint8_t device_number; + uint8_t device_address; uint8_t configuration_index; // not bConfigurationValue uint8_t *configuration_descriptor; // Contains the length of the all descriptors. uint8_t open_endpoints[8]; diff --git a/shared-module/usb/util/__init__.c b/shared-module/usb/util/__init__.c new file mode 100644 index 0000000000000..d3f12eb42bb8e --- /dev/null +++ b/shared-module/usb/util/__init__.c @@ -0,0 +1,7 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +// Nothing implementation specific. diff --git a/shared-module/usb_cdc/Serial.c b/shared-module/usb_cdc/Serial.c index 3c67103afcee9..348729365c2fc 100644 --- a/shared-module/usb_cdc/Serial.c +++ b/shared-module/usb_cdc/Serial.c @@ -19,9 +19,7 @@ size_t common_hal_usb_cdc_serial_read(usb_cdc_serial_obj_t *self, uint8_t *data, // Read up to len bytes immediately. // The number of bytes read will not be larger than what is already in the TinyUSB FIFO. uint32_t total_num_read = 0; - if (tud_cdc_n_connected(self->idx)) { - total_num_read = tud_cdc_n_read(self->idx, data, len); - } + total_num_read = tud_cdc_n_read(self->idx, data, len); if (wait_forever || wait_for_timeout) { // Continue filling the buffer past what we already read. @@ -48,9 +46,7 @@ size_t common_hal_usb_cdc_serial_read(usb_cdc_serial_obj_t *self, uint8_t *data, data += num_read; // Try to read another batch of bytes. - if (tud_cdc_n_connected(self->idx)) { - num_read = tud_cdc_n_read(self->idx, data, len); - } + num_read = tud_cdc_n_read(self->idx, data, len); total_num_read += num_read; } } diff --git a/shared-module/usb_cdc/__init__.c b/shared-module/usb_cdc/__init__.c index 502d8fa620e07..644c4ccae792b 100644 --- a/shared-module/usb_cdc/__init__.c +++ b/shared-module/usb_cdc/__init__.c @@ -105,7 +105,7 @@ static const uint8_t usb_cdc_descriptor_template[] = { 0xFF, // 54 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] #define CDC_DATA_OUT_ENDPOINT_INDEX 54 0x02, // 55 bmAttributes (Bulk) - #if USB_HIGHSPEED + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 0x00, 0x02, // 56,57 wMaxPacketSize 512 #else 0x40, 0x00, // 56,57 wMaxPacketSize 64 @@ -118,7 +118,7 @@ static const uint8_t usb_cdc_descriptor_template[] = { 0xFF, // 61 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number] #define CDC_DATA_IN_ENDPOINT_INDEX 61 0x02, // 62 bmAttributes (Bulk) - #if USB_HIGHSPEED + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 0x00, 0x02, // 63,64 wMaxPacketSize 512 #else 0x40, 0x00, // 63,64 wMaxPacketSize 64 @@ -192,6 +192,11 @@ size_t usb_cdc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *desc ? (USB_CDC_EP_NUM_DATA_IN ? USB_CDC_EP_NUM_DATA_IN : descriptor_counts->current_endpoint) : (USB_CDC2_EP_NUM_DATA_IN ? USB_CDC2_EP_NUM_DATA_IN : descriptor_counts->current_endpoint)); descriptor_counts->num_in_endpoints++; + // Some TinyUSB devices have issues with bi-directional endpoints + #ifdef TUD_ENDPOINT_ONE_DIRECTION_ONLY + descriptor_counts->current_endpoint++; + #endif + descriptor_buf[CDC_DATA_OUT_ENDPOINT_INDEX] = console ? (USB_CDC_EP_NUM_DATA_OUT ? USB_CDC_EP_NUM_DATA_OUT : descriptor_counts->current_endpoint) @@ -321,7 +326,7 @@ static const uint8_t usb_vendor_descriptor_template[] = { 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: number] #define VENDOR_OUT_ENDPOINT_INDEX 11 0x02, // 12 bmAttributes (Bulk) - #if USB_HIGHSPEED + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 0x00, 0x02, // 13,14 wMaxPacketSize 512 #else 0x40, 0x00, // 13,14 wMaxPacketSize 64 @@ -351,10 +356,10 @@ size_t usb_vendor_descriptor_length(void) { static uint8_t *ms_os_20_descriptor = NULL; -size_t vendor_ms_os_20_descriptor_length() { +size_t vendor_ms_os_20_descriptor_length(void) { return ms_os_20_descriptor != NULL ? sizeof(ms_os_20_descriptor_template) : 0; } -uint8_t const *vendor_ms_os_20_descriptor() { +uint8_t const *vendor_ms_os_20_descriptor(void) { return ms_os_20_descriptor; } diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index b007bc3ac2d4d..4d0d5fc2e3d5b 100644 --- a/shared-module/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -172,6 +172,12 @@ size_t usb_hid_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *desc descriptor_buf[HID_IN_ENDPOINT_INDEX] = 0x80 | (USB_HID_EP_NUM_IN ? USB_HID_EP_NUM_IN : descriptor_counts->current_endpoint); descriptor_counts->num_in_endpoints++; + + // Some TinyUSB devices have issues with bi-directional endpoints + #ifdef TUD_ENDPOINT_ONE_DIRECTION_ONLY + descriptor_counts->current_endpoint++; + #endif + descriptor_buf[HID_OUT_ENDPOINT_INDEX] = USB_HID_EP_NUM_OUT ? USB_HID_EP_NUM_OUT : descriptor_counts->current_endpoint; descriptor_counts->num_out_endpoints++; diff --git a/shared-module/usb_midi/__init__.c b/shared-module/usb_midi/__init__.c index e0853e4e2a7a5..1722911536fc2 100644 --- a/shared-module/usb_midi/__init__.c +++ b/shared-module/usb_midi/__init__.c @@ -106,7 +106,7 @@ static const uint8_t usb_midi_descriptor_template[] = { 0xFF, // 66 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] #define MIDI_STREAMING_OUT_ENDPOINT_INDEX (66) 0x02, // 67 bmAttributes (Bulk) - #if USB_HIGHSPEED + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 0x00, 0x02, // 68,69 wMaxPacketSize (512) #else 0x40, 0x00, // 68,69 wMaxPacketSize (64) @@ -126,7 +126,7 @@ static const uint8_t usb_midi_descriptor_template[] = { 0xFF, // 78 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number] #define MIDI_STREAMING_IN_ENDPOINT_INDEX (78) 0x02, // 79 bmAttributes (Bulk) - #if USB_HIGHSPEED + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 0x00, 0x02, // 80, 81 wMaxPacketSize (512) #else 0x40, 0x00, // 80, 81 wMaxPacketSize (64) @@ -176,6 +176,12 @@ size_t usb_midi_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *des descriptor_buf[MIDI_STREAMING_IN_ENDPOINT_INDEX] = 0x80 | (USB_MIDI_EP_NUM_IN ? USB_MIDI_EP_NUM_IN : descriptor_counts->current_endpoint); descriptor_counts->num_in_endpoints++; + + // Some TinyUSB devices have issues with bi-directional endpoints + #ifdef TUD_ENDPOINT_ONE_DIRECTION_ONLY + descriptor_counts->current_endpoint++; + #endif + descriptor_buf[MIDI_STREAMING_OUT_ENDPOINT_INDEX] = USB_MIDI_EP_NUM_OUT ? USB_MIDI_EP_NUM_OUT : descriptor_counts->current_endpoint; descriptor_counts->num_out_endpoints++; diff --git a/shared-module/vectorio/VectorShape.c b/shared-module/vectorio/VectorShape.c index ca6a68adb6da6..3ac752f327ce3 100644 --- a/shared-module/vectorio/VectorShape.c +++ b/shared-module/vectorio/VectorShape.c @@ -96,10 +96,12 @@ static void _get_screen_area(vectorio_vector_shape_t *self, displayio_area_t *ou x = self->absolute_transform->x + self->absolute_transform->dx * self->y; y = self->absolute_transform->y + self->absolute_transform->dy * self->x; if (self->absolute_transform->dx < 1) { + x -= 1; out_area->y1 = out_area->y1 * -1 + 1; out_area->y2 = out_area->y2 * -1 + 1; } if (self->absolute_transform->dy < 1) { + y -= 1; out_area->x1 = out_area->x1 * -1 + 1; out_area->x2 = out_area->x2 * -1 + 1; } @@ -109,10 +111,12 @@ static void _get_screen_area(vectorio_vector_shape_t *self, displayio_area_t *ou y = self->absolute_transform->y + self->absolute_transform->dy * self->y; if (self->absolute_transform->dx < 1) { + x -= 1; out_area->x1 = out_area->x1 * -1 + 1; out_area->x2 = out_area->x2 * -1 + 1; } if (self->absolute_transform->dy < 1) { + y -= 1; out_area->y1 = out_area->y1 * -1 + 1; out_area->y2 = out_area->y2 * -1 + 1; } @@ -132,11 +136,12 @@ static void screen_to_shape_coordinates(vectorio_vector_shape_t *self, uint16_t VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", *out_shape_x, *out_shape_y); if (self->absolute_transform->dx < 1) { *out_shape_y *= -1; + *out_shape_y -= 1; } if (self->absolute_transform->dy < 1) { *out_shape_x *= -1; + *out_shape_x -= 1; } - VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", *out_shape_x, *out_shape_y); } else { *out_shape_x = x - self->absolute_transform->x - self->absolute_transform->dx * self->x; *out_shape_y = y - self->absolute_transform->y - self->absolute_transform->dy * self->y; @@ -144,12 +149,12 @@ static void screen_to_shape_coordinates(vectorio_vector_shape_t *self, uint16_t VECTORIO_SHAPE_PIXEL_DEBUG(" a(%3d, %3d)", *out_shape_x, *out_shape_y); if (self->absolute_transform->dx < 1) { *out_shape_x *= -1; + *out_shape_x -= 1; } if (self->absolute_transform->dy < 1) { *out_shape_y *= -1; + *out_shape_y -= 1; } - VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", *out_shape_x, *out_shape_y); - // It's mirrored via dx. Maybe we need to add support for also separately mirroring? // if (self->absolute_transform->mirror_x) { // pixel_to_get_x = (shape_area.x2 - shape_area.x1) - (pixel_to_get_x - shape_area.x1) + shape_area.x1 - 1; @@ -158,6 +163,7 @@ static void screen_to_shape_coordinates(vectorio_vector_shape_t *self, uint16_t // pixel_to_get_y = (shape_area.y2 - shape_area.y1) - (pixel_to_get_y - shape_area.y1) + +shape_area.y1 - 1; // } } + VECTORIO_SHAPE_PIXEL_DEBUG(" b(%3d, %3d)", *out_shape_x, *out_shape_y); } static void check_bounds_and_set_x(vectorio_vector_shape_t *self, mp_int_t x) { @@ -533,6 +539,7 @@ displayio_area_t *vectorio_vector_shape_get_refresh_areas(vectorio_vector_shape_ self->ephemeral_dirty_area.next = tail; tail = &self->ephemeral_dirty_area; } else { + self->current_area_dirty = true; self->current_area.next = tail; tail = &self->current_area; VECTORIO_SHAPE_DEBUG("%p get_refresh_area: redrawing current: {(%3d,%3d), (%3d,%3d)}\n", self, self->current_area.x1, self->current_area.y1, self->current_area.x2, self->current_area.y2); @@ -549,3 +556,9 @@ void vectorio_vector_shape_update_transform(vectorio_vector_shape_t *self, displ self->absolute_transform = group_transform == NULL ? &null_transform : group_transform; common_hal_vectorio_vector_shape_set_dirty(self); } + +bool vectorio_vector_shape_set_in_group(vectorio_vector_shape_t *self, bool in_group) { + bool was_in_group = self->in_group; + self->in_group = in_group; + return was_in_group; +} diff --git a/shared-module/vectorio/VectorShape.h b/shared-module/vectorio/VectorShape.h index db77fc0acb940..f66569f97d492 100644 --- a/shared-module/vectorio/VectorShape.h +++ b/shared-module/vectorio/VectorShape.h @@ -43,6 +43,7 @@ typedef struct { displayio_area_t current_area; bool current_area_dirty; bool hidden; + bool in_group; } vectorio_vector_shape_t; displayio_area_t *vectorio_vector_shape_get_refresh_areas(vectorio_vector_shape_t *self, displayio_area_t *tail); diff --git a/shared-module/zlib/__init__.c b/shared-module/zlib/__init__.c index 031432a215fee..7becb6faf73c8 100644 --- a/shared-module/zlib/__init__.c +++ b/shared-module/zlib/__init__.c @@ -37,7 +37,7 @@ mp_obj_t common_hal_zlib_decompress(mp_obj_t data, mp_int_t wbits) { DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp)); uzlib_uncompress_init(decomp, NULL, 0); mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15; - byte *dest_buf = m_new(byte, dest_buf_size); + byte *dest_buf = m_malloc_without_collect(dest_buf_size); decomp->dest = dest_buf; decomp->dest_limit = dest_buf + dest_buf_size; diff --git a/shared/libc/abort_.c b/shared/libc/abort_.c index 3051eae81e0ce..54eab67d3fb49 100644 --- a/shared/libc/abort_.c +++ b/shared/libc/abort_.c @@ -1,7 +1,7 @@ #include -NORETURN void abort_(void); +MP_NORETURN void abort_(void); -NORETURN void abort_(void) { +MP_NORETURN void abort_(void) { mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("abort() called")); } diff --git a/shared/libc/printf.c b/shared/libc/printf.c index 715181229e4fc..50b04ce9be082 100644 --- a/shared/libc/printf.c +++ b/shared/libc/printf.c @@ -87,7 +87,7 @@ typedef struct _strn_print_env_t { size_t remain; } strn_print_env_t; -STATIC void strn_print_strn(void *data, const char *str, size_t len) { +static void strn_print_strn(void *data, const char *str, size_t len) { strn_print_env_t *strn_print_env = data; if (len > strn_print_env->remain) { len = strn_print_env->remain; diff --git a/shared/libc/string0.c b/shared/libc/string0.c index 8d513e933c282..5a9e0ff853a52 100644 --- a/shared/libc/string0.c +++ b/shared/libc/string0.c @@ -26,10 +26,12 @@ #include #include -#include +// CIRCUITPY-CHANGE: additional includes +#include #include "py/mpconfig.h" +// CIRCUITPY-CHANGE: ifndef #ifndef likely #define likely(x) __builtin_expect((x), 1) #endif @@ -38,6 +40,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-align" void *memcpy(void *dst, const void *src, size_t n) { +// CIRCUITPY-CHANGE: fancier copy only for full build #if CIRCUITPY_FULL_BUILD if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) { // pointers aligned @@ -100,6 +103,7 @@ void *memmove(void *dest, const void *src, size_t n) { } void *memset(void *s, int c, size_t n) { +// CIRCUITPY-CHANGE: fancier copy only for full build #if CIRCUITPY_FULL_BUILD if (c == 0 && ((uintptr_t)s & 3) == 0) { // aligned store of 0 @@ -125,6 +129,7 @@ void *memset(void *s, int c, size_t n) { return s; } +// CIRCUITPY-CHANGE #pragma GCC diagnostic pop int memcmp(const void *s1, const void *s2, size_t n) { diff --git a/shared/memzip/make-memzip.py b/shared/memzip/make-memzip.py index 92a5d6168bb1d..e406c55a43ca7 100755 --- a/shared/memzip/make-memzip.py +++ b/shared/memzip/make-memzip.py @@ -7,8 +7,6 @@ # This is somewhat like frozen modules in python, but allows arbitrary files # to be used. -from __future__ import print_function - import argparse import os import subprocess diff --git a/shared/netutils/dhcpserver.c b/shared/netutils/dhcpserver.c index 41bc4ffdcb871..6d9cdb97d1fc6 100644 --- a/shared/netutils/dhcpserver.c +++ b/shared/netutils/dhcpserver.c @@ -117,7 +117,7 @@ static void dhcp_socket_free(struct udp_pcb **udp) { static int dhcp_socket_bind(struct udp_pcb **udp, uint32_t ip, uint16_t port) { ip_addr_t addr; - IP4_ADDR(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); + IP_ADDR4(&addr, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); // TODO convert lwIP errors to errno return udp_bind(*udp, &addr, port); } @@ -135,7 +135,7 @@ static int dhcp_socket_sendto(struct udp_pcb **udp, struct netif *netif, const v memcpy(p->payload, buf, len); ip_addr_t dest; - IP4_ADDR(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); + IP_ADDR4(&dest, ip >> 24 & 0xff, ip >> 16 & 0xff, ip >> 8 & 0xff, ip & 0xff); err_t err; if (netif != NULL) { err = udp_sendto_if(*udp, p, &dest, port, netif); @@ -209,7 +209,7 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, } dhcp_msg.op = DHCPOFFER; - memcpy(&dhcp_msg.yiaddr, &d->ip.addr, 4); + memcpy(&dhcp_msg.yiaddr, &ip_2_ip4(&d->ip)->addr, 4); uint8_t *opt = (uint8_t *)&dhcp_msg.options; opt += 4; // assume magic cookie: 99, 130, 83, 99 @@ -252,7 +252,7 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, // Should be NACK goto ignore_request; } - if (memcmp(o + 2, &d->ip.addr, 3) != 0) { + if (memcmp(o + 2, &ip_2_ip4(&d->ip)->addr, 3) != 0) { // Should be NACK goto ignore_request; } @@ -285,9 +285,9 @@ static void dhcp_server_process(void *arg, struct udp_pcb *upcb, struct pbuf *p, goto ignore_request; } - opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &d->ip.addr); - opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &d->nm.addr); - opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &d->ip.addr); // aka gateway; can have multiple addresses + opt_write_n(&opt, DHCP_OPT_SERVER_ID, 4, &ip_2_ip4(&d->ip)->addr); + opt_write_n(&opt, DHCP_OPT_SUBNET_MASK, 4, &ip_2_ip4(&d->nm)->addr); + opt_write_n(&opt, DHCP_OPT_ROUTER, 4, &ip_2_ip4(&d->ip)->addr); // aka gateway; can have multiple addresses opt_write_u32(&opt, DHCP_OPT_DNS, DEFAULT_DNS); // can have multiple addresses opt_write_u32(&opt, DHCP_OPT_IP_LEASE_TIME, DEFAULT_LEASE_TIME_S); *opt++ = DHCP_OPT_END; diff --git a/shared/netutils/netutils.c b/shared/netutils/netutils.c index 84b4405c41d38..cd1422f7c8058 100644 --- a/shared/netutils/netutils.c +++ b/shared/netutils/netutils.c @@ -63,7 +63,13 @@ void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian return; } const char *s = addr_str; - const char *s_top = addr_str + addr_len; + const char *s_top; + // Scan for the end of valid address characters + for (s_top = addr_str; s_top < addr_str + addr_len; s_top++) { + if (!(*s_top == '.' || (*s_top >= '0' && *s_top <= '9'))) { + break; + } + } for (mp_uint_t i = 3; ; i--) { mp_uint_t val = 0; for (; s < s_top && *s != '.'; s++) { diff --git a/shared/netutils/trace.c b/shared/netutils/trace.c index a6dfb42c28f00..24af4d5ca315f 100644 --- a/shared/netutils/trace.c +++ b/shared/netutils/trace.c @@ -56,7 +56,7 @@ static const char *ethertype_str(uint16_t type) { } void netutils_ethernet_trace(const mp_print_t *print, size_t len, const uint8_t *buf, unsigned int flags) { - mp_printf(print, "[% 8d] ETH%cX len=%u", mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len); + mp_printf(print, "[% 8u] ETH%cX len=%u", (unsigned)mp_hal_ticks_ms(), flags & NETUTILS_TRACE_IS_TX ? 'T' : 'R', len); mp_printf(print, " dst=%02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); mp_printf(print, " src=%02x:%02x:%02x:%02x:%02x:%02x", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]); diff --git a/shared/readline/readline.c b/shared/readline/readline.c index 4906f51af3c14..12acf1589781c 100644 --- a/shared/readline/readline.c +++ b/shared/readline/readline.c @@ -55,7 +55,7 @@ void readline_init0(void) { memset(MP_STATE_PORT(readline_hist), 0, MICROPY_READLINE_HISTORY_SIZE * sizeof(const char*)); } -STATIC char *str_dup_maybe(const char *str) { +static char *str_dup_maybe(const char *str) { uint32_t len = strlen(str); char *s2 = m_new_maybe(char, len + 1); if (s2 == NULL) { @@ -66,7 +66,7 @@ STATIC char *str_dup_maybe(const char *str) { } // CIRCUITPY-CHANGE -STATIC size_t count_cont_bytes(char *start, char *end) { +static size_t count_cont_bytes(char *start, char *end) { int count = 0; for (char *pos = start; pos < end; pos++) { if(UTF8_IS_CONT(*pos)) { @@ -83,7 +83,7 @@ STATIC size_t count_cont_bytes(char *start, char *end) { // ...and provide the implementation using them #if MICROPY_HAL_HAS_VT100 -STATIC void mp_hal_move_cursor_back(uint pos) { +static void mp_hal_move_cursor_back(uint pos) { if (pos <= 4) { // fast path for most common case of 1 step back mp_hal_stdout_tx_strn("\b\b\b\b", pos); @@ -99,7 +99,7 @@ STATIC void mp_hal_move_cursor_back(uint pos) { } } -STATIC void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) { +static void mp_hal_erase_line_from_cursor(uint n_chars_to_erase) { (void)n_chars_to_erase; mp_hal_stdout_tx_strn("\x1b[K", 3); } @@ -120,10 +120,10 @@ typedef struct _readline_t { const char *prompt; } readline_t; -STATIC readline_t rl; +static readline_t rl; #if MICROPY_REPL_EMACS_WORDS_MOVE -STATIC size_t cursor_count_word(int forward) { +static size_t cursor_count_word(int forward) { const char *line_buf = vstr_str(rl.line); size_t pos = rl.cursor_pos; bool in_word = false; @@ -553,7 +553,7 @@ int readline_process_char(int c) { } #if MICROPY_REPL_AUTO_INDENT -STATIC void readline_auto_indent(void) { +static void readline_auto_indent(void) { if (!(rl.auto_indent_state & AUTO_INDENT_ENABLED)) { return; } diff --git a/shared/runtime/context_manager_helpers.c b/shared/runtime/context_manager_helpers.c index 56955da089c32..5b025209ff7f2 100644 --- a/shared/runtime/context_manager_helpers.c +++ b/shared/runtime/context_manager_helpers.c @@ -7,8 +7,12 @@ #include "shared/runtime/context_manager_helpers.h" #include "py/obj.h" +#include "py/runtime.h" -static mp_obj_t default___enter__(mp_obj_t self_in) { - return self_in; +static mp_obj_t default___exit__(size_t n_args, const mp_obj_t *args) { + mp_obj_t dest[2]; + mp_load_method(args[0], MP_QSTR_deinit, dest); + mp_call_method_n_kw(0, 0, dest); + return mp_const_none; } -MP_DEFINE_CONST_FUN_OBJ_1(default___enter___obj, default___enter__); +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(default___exit___obj, 4, 4, default___exit__); diff --git a/shared/runtime/context_manager_helpers.h b/shared/runtime/context_manager_helpers.h index d8ec102ac5a54..10970ce1a1a92 100644 --- a/shared/runtime/context_manager_helpers.h +++ b/shared/runtime/context_manager_helpers.h @@ -8,4 +8,13 @@ #include "py/obj.h" -MP_DECLARE_CONST_FUN_OBJ_1(default___enter___obj); +// An object that has a `deinit` method can use `default___enter___obj` and +// `default___exit___obj` to define the `__enter__` and `__exit__` members in +// its object table. +// +// `__enter__` returns the object itself, and `__exit__` calls its `deinit`. +// +// If enter/exit do anything else, such as taking & releasing a lock, these are +// not suitable. +#define default___enter___obj (mp_identity_obj) +MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(default___exit___obj); diff --git a/shared/runtime/gchelper.h b/shared/runtime/gchelper.h index 645ee837f5146..1e85e06f46ef9 100644 --- a/shared/runtime/gchelper.h +++ b/shared/runtime/gchelper.h @@ -41,6 +41,8 @@ typedef uintptr_t gc_helper_regs_t[4]; typedef uintptr_t gc_helper_regs_t[10]; #elif defined(__aarch64__) typedef uintptr_t gc_helper_regs_t[11]; // x19-x29 +#elif defined(__riscv) && (__riscv_xlen <= 64) +typedef uintptr_t gc_helper_regs_t[12]; // S0-S11 #endif #endif diff --git a/shared/runtime/gchelper_generic.c b/shared/runtime/gchelper_generic.c index 272e37056aaa8..230a24440050f 100644 --- a/shared/runtime/gchelper_generic.c +++ b/shared/runtime/gchelper_generic.c @@ -42,13 +42,14 @@ // stack already by the caller. #if defined(__x86_64__) -STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { - register long rbx asm ("rbx"); - register long rbp asm ("rbp"); - register long r12 asm ("r12"); - register long r13 asm ("r13"); - register long r14 asm ("r14"); - register long r15 asm ("r15"); +// CIRCUITPY-CHANGE: use __asm__ instead of asm +static void gc_helper_get_regs(gc_helper_regs_t arr) { + register long rbx __asm__ ("rbx"); + register long rbp __asm__ ("rbp"); + register long r12 __asm__ ("r12"); + register long r13 __asm__ ("r13"); + register long r14 __asm__ ("r14"); + register long r15 __asm__ ("r15"); #ifdef __clang__ // TODO: // This is dirty workaround for Clang. It tries to get around @@ -56,12 +57,12 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { // Application of this patch here is random, and done only to unbreak // MacOS build. Better, cross-arch ways to deal with Clang issues should // be found. - asm ("" : "=r" (rbx)); - asm ("" : "=r" (rbp)); - asm ("" : "=r" (r12)); - asm ("" : "=r" (r13)); - asm ("" : "=r" (r14)); - asm ("" : "=r" (r15)); + __asm__ ("" : "=r" (rbx)); + __asm__ ("" : "=r" (rbp)); + __asm__ ("" : "=r" (r12)); + __asm__ ("" : "=r" (r13)); + __asm__ ("" : "=r" (r14)); + __asm__ ("" : "=r" (r15)); #endif arr[0] = rbx; arr[1] = rbp; @@ -73,11 +74,11 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { #elif defined(__i386__) -STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { - register long ebx asm ("ebx"); - register long esi asm ("esi"); - register long edi asm ("edi"); - register long ebp asm ("ebp"); +static void gc_helper_get_regs(gc_helper_regs_t arr) { + register long ebx __asm__ ("ebx"); + register long esi __asm__ ("esi"); + register long edi __asm__ ("edi"); + register long ebp __asm__ ("ebp"); #ifdef __clang__ // TODO: // This is dirty workaround for Clang. It tries to get around @@ -85,10 +86,10 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { // Application of this patch here is random, and done only to unbreak // MacOS build. Better, cross-arch ways to deal with Clang issues should // be found. - asm ("" : "=r" (ebx)); - asm ("" : "=r" (esi)); - asm ("" : "=r" (edi)); - asm ("" : "=r" (ebp)); + __asm__ ("" : "=r" (ebx)); + __asm__ ("" : "=r" (esi)); + __asm__ ("" : "=r" (edi)); + __asm__ ("" : "=r" (ebp)); #endif arr[0] = ebx; arr[1] = esi; @@ -100,17 +101,21 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { // Fallback implementation, prefer gchelper_thumb1.s or gchelper_thumb2.s -STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { - register long r4 asm ("r4"); - register long r5 asm ("r5"); - register long r6 asm ("r6"); - register long r7 asm ("r7"); - register long r8 asm ("r8"); - register long r9 asm ("r9"); - register long r10 asm ("r10"); - register long r11 asm ("r11"); - register long r12 asm ("r12"); - register long r13 asm ("r13"); +static void gc_helper_get_regs(gc_helper_regs_t arr) { + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wuninitialized" + #endif + register long r4 __asm__ ("r4"); + register long r5 __asm__ ("r5"); + register long r6 __asm__ ("r6"); + register long r7 __asm__ ("r7"); + register long r8 __asm__ ("r8"); + register long r9 __asm__ ("r9"); + register long r10 __asm__ ("r10"); + register long r11 __asm__ ("r11"); + register long r12 __asm__ ("r12"); + register long r13 __asm__ ("r13"); arr[0] = r4; arr[1] = r5; arr[2] = r6; @@ -121,22 +126,25 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { arr[7] = r11; arr[8] = r12; arr[9] = r13; + #ifdef __clang__ + #pragma clang diagnostic pop + #endif } #elif defined(__aarch64__) -STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { - const register long x19 asm ("x19"); - const register long x20 asm ("x20"); - const register long x21 asm ("x21"); - const register long x22 asm ("x22"); - const register long x23 asm ("x23"); - const register long x24 asm ("x24"); - const register long x25 asm ("x25"); - const register long x26 asm ("x26"); - const register long x27 asm ("x27"); - const register long x28 asm ("x28"); - const register long x29 asm ("x29"); +static void gc_helper_get_regs(gc_helper_regs_t arr) { + const register long x19 __asm__ ("x19"); + const register long x20 __asm__ ("x20"); + const register long x21 __asm__ ("x21"); + const register long x22 __asm__ ("x22"); + const register long x23 __asm__ ("x23"); + const register long x24 __asm__ ("x24"); + const register long x25 __asm__ ("x25"); + const register long x26 __asm__ ("x26"); + const register long x27 __asm__ ("x27"); + const register long x28 __asm__ ("x28"); + const register long x29 __asm__ ("x29"); arr[0] = x19; arr[1] = x20; arr[2] = x21; @@ -150,6 +158,38 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { arr[10] = x29; } +#elif defined(__riscv) && (__riscv_xlen <= 64) + +// Fallback implementation for RV32I and RV64I, prefer gchelper_rv32i.s +// for RV32I targets or gchelper_rv64i.s for RV64I targets. + +static void gc_helper_get_regs(gc_helper_regs_t arr) { + register uintptr_t s0 __asm__ ("x8"); + register uintptr_t s1 __asm__ ("x9"); + register uintptr_t s2 __asm__ ("x18"); + register uintptr_t s3 __asm__ ("x19"); + register uintptr_t s4 __asm__ ("x20"); + register uintptr_t s5 __asm__ ("x21"); + register uintptr_t s6 __asm__ ("x22"); + register uintptr_t s7 __asm__ ("x23"); + register uintptr_t s8 __asm__ ("x24"); + register uintptr_t s9 __asm__ ("x25"); + register uintptr_t s10 __asm__ ("x26"); + register uintptr_t s11 __asm__ ("x27"); + arr[0] = s0; + arr[1] = s1; + arr[2] = s2; + arr[3] = s3; + arr[4] = s4; + arr[5] = s5; + arr[6] = s6; + arr[7] = s7; + arr[8] = s8; + arr[9] = s9; + arr[10] = s10; + arr[11] = s11; +} + #else #error "Architecture not supported for gc_helper_get_regs. Set MICROPY_GCREGS_SETJMP to use the fallback implementation." @@ -161,7 +201,7 @@ STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { // Even if we have specific support for an architecture, it is // possible to force use of setjmp-based implementation. -STATIC void gc_helper_get_regs(gc_helper_regs_t arr) { +static void gc_helper_get_regs(gc_helper_regs_t arr) { setjmp(arr); } diff --git a/shared/runtime/gchelper_rv32i.s b/shared/runtime/gchelper_rv32i.s new file mode 100644 index 0000000000000..64248e771a861 --- /dev/null +++ b/shared/runtime/gchelper_rv32i.s @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + .global gc_helper_get_regs_and_sp + .type gc_helper_get_regs_and_sp, @function + +gc_helper_get_regs_and_sp: + + /* Store registers into the given array. */ + + sw x8, 0(x10) /* Save S0. */ + sw x9, 4(x10) /* Save S1. */ + sw x18, 8(x10) /* Save S2. */ + sw x19, 12(x10) /* Save S3. */ + sw x20, 16(x10) /* Save S4. */ + sw x21, 20(x10) /* Save S5. */ + sw x22, 24(x10) /* Save S6. */ + sw x23, 28(x10) /* Save S7. */ + sw x24, 32(x10) /* Save S8. */ + sw x25, 36(x10) /* Save S9. */ + sw x26, 40(x10) /* Save S10. */ + sw x27, 44(x10) /* Save S11. */ + + /* Return the stack pointer. */ + + add x10, x0, x2 + jalr x0, x1, 0 + + .size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp diff --git a/shared/runtime/gchelper_rv64i.s b/shared/runtime/gchelper_rv64i.s new file mode 100644 index 0000000000000..147a0e2bf5b5d --- /dev/null +++ b/shared/runtime/gchelper_rv64i.s @@ -0,0 +1,52 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + .global gc_helper_get_regs_and_sp + .type gc_helper_get_regs_and_sp, @function + +gc_helper_get_regs_and_sp: + + /* Store registers into the given array. */ + + sd x8, 0(x10) /* Save S0. */ + sd x9, 8(x10) /* Save S1. */ + sd x18, 16(x10) /* Save S2. */ + sd x19, 24(x10) /* Save S3. */ + sd x20, 32(x10) /* Save S4. */ + sd x21, 40(x10) /* Save S5. */ + sd x22, 48(x10) /* Save S6. */ + sd x23, 56(x10) /* Save S7. */ + sd x24, 64(x10) /* Save S8. */ + sd x25, 72(x10) /* Save S9. */ + sd x26, 80(x10) /* Save S10. */ + sd x27, 88(x10) /* Save S11. */ + + /* Return the stack pointer. */ + + add x10, x0, x2 + jalr x0, x1, 0 + + .size gc_helper_get_regs_and_sp, .-gc_helper_get_regs_and_sp diff --git a/shared/runtime/interrupt_char.c b/shared/runtime/interrupt_char.c index 1dfccc4b5c8e2..1f2702017190f 100644 --- a/shared/runtime/interrupt_char.c +++ b/shared/runtime/interrupt_char.c @@ -31,6 +31,16 @@ #if MICROPY_KBD_EXCEPTION +// CIRCUITPY-CHANGE +#ifdef __ZEPHYR__ +#include + +// This semaphore is released when an interrupt character is seen. Core CP code +// can wait for this release but shouldn't take it. They should return instead +// after cancelling what they were doing. +K_SEM_DEFINE(mp_interrupt_sem, 0, 1); +#endif + int mp_interrupt_char = -1; void mp_hal_set_interrupt_char(int c) { diff --git a/shared/runtime/interrupt_char.h b/shared/runtime/interrupt_char.h index f15036545c173..44fd4b45a6121 100644 --- a/shared/runtime/interrupt_char.h +++ b/shared/runtime/interrupt_char.h @@ -29,6 +29,17 @@ // CIRCUITPY-CHANGE #include +// CIRCUITPY-CHANGE +#ifdef __ZEPHYR__ +#include + +// This semaphore is released when an interrupt character is seen. Core CP code +// can wait for this release but shouldn't take it. They should return instead +// after cancelling what they were doing. +extern struct k_sem mp_interrupt_sem; +#endif + + extern int mp_interrupt_char; void mp_hal_set_interrupt_char(int c); // CIRCUITPY-CHANGE diff --git a/shared/runtime/mpirq.c b/shared/runtime/mpirq.c deleted file mode 100644 index acd727403b558..0000000000000 --- a/shared/runtime/mpirq.c +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * 2018 Tobias Badertscher - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "py/runtime.h" -#include "py/gc.h" -#include "shared/runtime/mpirq.h" - -#if MICROPY_ENABLE_SCHEDULER - -/****************************************************************************** - DECLARE PUBLIC DATA - ******************************************************************************/ - -const mp_arg_t mp_irq_init_args[] = { - { MP_QSTR_handler, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, - { MP_QSTR_trigger, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} }, -}; - -/****************************************************************************** - DECLARE PRIVATE DATA - ******************************************************************************/ - -/****************************************************************************** - DEFINE PUBLIC FUNCTIONS - ******************************************************************************/ - -mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent) { - mp_irq_obj_t *self = m_new0(mp_irq_obj_t, 1); - mp_irq_init(self, methods, parent); - return self; -} - -void mp_irq_init(mp_irq_obj_t *self, const mp_irq_methods_t *methods, mp_obj_t parent) { - self->base.type = &mp_irq_type; - self->methods = (mp_irq_methods_t *)methods; - self->parent = parent; - self->handler = mp_const_none; - self->ishard = false; -} - -void mp_irq_handler(mp_irq_obj_t *self) { - if (self->handler != mp_const_none) { - if (self->ishard) { - // When executing code within a handler we must lock the scheduler to - // prevent any scheduled callbacks from running, and lock the GC to - // prevent any memory allocations. - mp_sched_lock(); - gc_lock(); - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_call_function_1(self->handler, self->parent); - nlr_pop(); - } else { - // Uncaught exception; disable the callback so that it doesn't run again - self->methods->trigger(self->parent, 0); - self->handler = mp_const_none; - mp_printf(MICROPY_ERROR_PRINTER, "Uncaught exception in IRQ callback handler\n"); - mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(nlr.ret_val)); - } - gc_unlock(); - mp_sched_unlock(); - } else { - // Schedule call to user function - mp_sched_schedule(self->handler, self->parent); - } - } -} - -/******************************************************************************/ -// MicroPython bindings - -STATIC mp_obj_t mp_irq_flags(mp_obj_t self_in) { - mp_irq_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_FLAGS)); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags); - -STATIC mp_obj_t mp_irq_trigger(size_t n_args, const mp_obj_t *args) { - mp_irq_obj_t *self = MP_OBJ_TO_PTR(args[0]); - mp_obj_t ret_obj = mp_obj_new_int(self->methods->info(self->parent, MP_IRQ_INFO_TRIGGERS)); - if (n_args == 2) { - // Set trigger - self->methods->trigger(self->parent, mp_obj_get_int(args[1])); - } - return ret_obj; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_irq_trigger_obj, 1, 2, mp_irq_trigger); - -STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 0, 0, false); - mp_irq_handler(MP_OBJ_TO_PTR(self_in)); - return mp_const_none; -} - -STATIC const mp_rom_map_elem_t mp_irq_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_flags), MP_ROM_PTR(&mp_irq_flags_obj) }, - { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&mp_irq_trigger_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - mp_irq_type, - MP_QSTR_irq, - MP_TYPE_FLAG_NONE, - call, mp_irq_call, - locals_dict, &mp_irq_locals_dict - ); - -#endif // MICROPY_ENABLE_SCHEDULER diff --git a/shared/runtime/mpirq.h b/shared/runtime/mpirq.h deleted file mode 100644 index dd423c0101137..0000000000000 --- a/shared/runtime/mpirq.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Daniel Campora - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H -#define MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H - -#include "py/runtime.h" - -/****************************************************************************** - DEFINE CONSTANTS - ******************************************************************************/ - -enum { - MP_IRQ_ARG_INIT_handler = 0, - MP_IRQ_ARG_INIT_trigger, - MP_IRQ_ARG_INIT_hard, - MP_IRQ_ARG_INIT_NUM_ARGS, -}; - -/****************************************************************************** - DEFINE TYPES - ******************************************************************************/ - -typedef mp_uint_t (*mp_irq_trigger_fun_t)(mp_obj_t self, mp_uint_t trigger); -typedef mp_uint_t (*mp_irq_info_fun_t)(mp_obj_t self, mp_uint_t info_type); - -enum { - MP_IRQ_INFO_FLAGS, - MP_IRQ_INFO_TRIGGERS, -}; - -typedef struct _mp_irq_methods_t { - mp_irq_trigger_fun_t trigger; - mp_irq_info_fun_t info; -} mp_irq_methods_t; - -typedef struct _mp_irq_obj_t { - mp_obj_base_t base; - mp_irq_methods_t *methods; - mp_obj_t parent; - mp_obj_t handler; - bool ishard; -} mp_irq_obj_t; - -/****************************************************************************** - DECLARE EXPORTED DATA - ******************************************************************************/ - -extern const mp_arg_t mp_irq_init_args[]; -extern const mp_obj_type_t mp_irq_type; - -/****************************************************************************** - DECLARE PUBLIC FUNCTIONS - ******************************************************************************/ - -mp_irq_obj_t *mp_irq_new(const mp_irq_methods_t *methods, mp_obj_t parent); -void mp_irq_init(mp_irq_obj_t *self, const mp_irq_methods_t *methods, mp_obj_t parent); -void mp_irq_handler(mp_irq_obj_t *self); - -#endif // MICROPY_INCLUDED_LIB_UTILS_MPIRQ_H diff --git a/shared/runtime/pyexec.c b/shared/runtime/pyexec.c index 94c506502c305..bc5f89bdc81ad 100644 --- a/shared/runtime/pyexec.c +++ b/shared/runtime/pyexec.c @@ -31,31 +31,27 @@ // CIRCUITPY-CHANGE: add #include "py/mphal.h" + #include "py/compile.h" #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" #include "py/frozenmod.h" #include "py/mphal.h" -// CIRCUITPY-CHANGE: prevent undefined warning -#if defined(MICROPY_HW_ENABLE_USB) && MICROPY_HW_ENABLE_USB -#include "irq.h" -#include "usb.h" -#endif #include "shared/readline/readline.h" #include "shared/runtime/pyexec.h" +#include "extmod/modplatform.h" #include "genhdr/mpversion.h" -// CIRCUITPY-CHANGE: atexit support +// CIRCUITPY-CHANGE: add atexit support #if CIRCUITPY_ATEXIT #include "shared-module/atexit/__init__.h" #endif pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; -int pyexec_system_exit = 0; #if MICROPY_REPL_INFO -STATIC bool repl_display_debugging_info = 0; +static bool repl_display_debugging_info = 0; #endif #define EXEC_FLAG_PRINT_EOF (1 << 0) @@ -75,7 +71,7 @@ STATIC bool repl_display_debugging_info = 0; // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) // CIRCUITPY-CHANGE: add result support -STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, mp_uint_t exec_flags, pyexec_result_t *result) { +static int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, mp_uint_t exec_flags, pyexec_result_t *result) { int ret = 0; #if MICROPY_REPL_INFO uint32_t start = 0; @@ -85,62 +81,74 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input MICROPY_BOARD_BEFORE_PYTHON_EXEC(input_kind, exec_flags); #endif - // by default a SystemExit exception returns 0 - pyexec_system_exit = 0; - nlr_buf_t nlr; nlr.ret_val = NULL; if (nlr_push(&nlr) == 0) { - mp_obj_t module_fun; - // CIRCUITPY-CHANGE + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(&nlr); + #endif + + // CIRCUITPY-CHANGE: move declaration for easier handling of atexit #if. + // Also make it possible to determine if module_fun was set. + mp_obj_t module_fun = NULL; + + // CIRCUITPY-CHANGE: add atexit support #if CIRCUITPY_ATEXIT - if (!(exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT)) + if (exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT) { + atexit_callback_t *callback = (atexit_callback_t *)source; + mp_call_function_n_kw(callback->func, callback->n_pos, callback->n_kw, callback->args); + } else #endif - // CIRCUITPY-CHANGE: multiple code changes - { - #if MICROPY_MODULE_FROZEN_MPY - if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { - // source is a raw_code object, create the function - const mp_frozen_module_t *frozen = source; - mp_module_context_t *ctx = m_new_obj(mp_module_context_t); - ctx->module.globals = mp_globals_get(); - ctx->constants = frozen->constants; - module_fun = mp_make_function_from_raw_code(frozen->rc, ctx, NULL); - } else - #endif - { - #if MICROPY_ENABLE_COMPILER - mp_lexer_t *lex; - if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { - const vstr_t *vstr = source; - lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); - } else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) { - lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source); - } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { - lex = mp_lexer_new_from_file(qstr_from_str(source)); - } else { - lex = (mp_lexer_t *)source; - } - // source is a lexer, parse and compile the script - qstr source_name = lex->source_name; - // CIRCUITPY-CHANGE - #if MICROPY_PY___FILE__ - if (input_kind == MP_PARSE_FILE_INPUT) { - mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); - } - #endif - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); - #else - mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported")); - #endif + #if MICROPY_MODULE_FROZEN_MPY + if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { + // source is a raw_code object, create the function + const mp_frozen_module_t *frozen = source; + mp_module_context_t *ctx = m_new_obj(mp_module_context_t); + ctx->module.globals = mp_globals_get(); + ctx->constants = frozen->constants; + module_fun = mp_make_function_from_proto_fun(frozen->proto_fun, ctx, NULL); + } else + #endif + { + #if MICROPY_ENABLE_COMPILER + mp_lexer_t *lex; + if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { + const vstr_t *vstr = source; + lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); + } else if (exec_flags & EXEC_FLAG_SOURCE_IS_READER) { + lex = mp_lexer_new(MP_QSTR__lt_stdin_gt_, *(mp_reader_t *)source); + } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { + lex = mp_lexer_new_from_file(qstr_from_str(source)); + } else { + lex = (mp_lexer_t *)source; } - - // If the code was loaded from a file, collect any garbage before running. + // source is a lexer, parse and compile the script + qstr source_name = lex->source_name; + #if MICROPY_MODULE___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { - gc_collect(); + mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } + #endif + mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); + #if defined(MICROPY_UNIX_COVERAGE) + // allow to print the parse tree in the coverage build + if (mp_verbose_flag >= 3) { + printf("----------------\n"); + mp_parse_node_print(&mp_plat_print, parse_tree.root, 0); + printf("----------------\n"); + } + #endif + module_fun = mp_compile(&parse_tree, source_name, exec_flags & EXEC_FLAG_IS_REPL); + #else + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("script compilation not supported")); + #endif + } + + // CIRCUITPY-CHANGE: garbage collect after loading + // If the code was loaded from a file, collect any garbage before running. + if (input_kind == MP_PARSE_FILE_INPUT) { + gc_collect(); } // execute code @@ -150,21 +158,19 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input #if MICROPY_REPL_INFO start = mp_hal_ticks_ms(); #endif - // CIRCUITPY-CHANGE - #if CIRCUITPY_ATEXIT - if (exec_flags & EXEC_FLAG_SOURCE_IS_ATEXIT) { - atexit_callback_t *callback = (atexit_callback_t *)source; - mp_call_function_n_kw(callback->func, callback->n_pos, callback->n_kw, callback->args); - } else + #if MICROPY_PYEXEC_COMPILE_ONLY + if (!mp_compile_only) #endif { - mp_call_function_0(module_fun); + // CIRCUITPY-CHANGE: if atexit function was called, there is nothing to call. + if (module_fun != NULL) { + mp_call_function_0(module_fun); + } } mp_hal_set_interrupt_char(-1); // disable interrupt mp_handle_pending(true); // handle any pending exceptions (and any callbacks) nlr_pop(); - // CIRCUITPY-CHANGE - ret = 0; + ret = PYEXEC_NORMAL_EXIT; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } @@ -183,36 +189,65 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input mp_hal_stdout_tx_strn("\x04", 1); } - // check for SystemExit - - // CIRCUITPY-CHANGE + // CIRCUITPY-CHANGE: Name and use some values. // nlr.ret_val is an exception object. mp_obj_t exception_obj = (mp_obj_t)nlr.ret_val; + const mp_obj_type_t *exception_obj_type = mp_obj_get_type(exception_obj); + + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + if (nlr.ret_val == NULL) { // abort + ret = PYEXEC_ABORT; + } else + #endif - if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { - // at the moment, the value of SystemExit is unused - ret = pyexec_system_exit; - // CIRCUITPY-CHANGE + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exception_obj_type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // system exit + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + // None is an exit value of 0; an int is its value; anything else is 1 + mp_obj_t val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val)); + if (val != mp_const_none) { + if (mp_obj_is_int(val)) { + ret = (int)mp_obj_int_get_truncated(val); + } else { + mp_obj_print_helper(MICROPY_ERROR_PRINTER, val, PRINT_STR); + mp_print_str(MICROPY_ERROR_PRINTER, "\n"); + ret = PYEXEC_UNHANDLED_EXCEPTION; + } + } else { + ret = PYEXEC_NORMAL_EXIT; + } + // Set PYEXEC_FORCED_EXIT flag so REPL knows to exit + ret |= PYEXEC_FORCED_EXIT; + #else + ret = PYEXEC_FORCED_EXIT; + #endif + // CIRCUITPY-CHANGE: support DeepSleepRequest #if CIRCUITPY_ALARM - } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(exception_obj)), MP_OBJ_FROM_PTR(&mp_type_DeepSleepRequest))) { + } else if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exception_obj_type), MP_OBJ_FROM_PTR(&mp_type_DeepSleepRequest))) { ret = PYEXEC_DEEP_SLEEP; #endif + // CIRCUITPY-CHANGE: support ReloadException } else if (exception_obj == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) { ret = PYEXEC_RELOAD; - } else { - mp_obj_print_exception(&mp_plat_print, exception_obj); - ret = PYEXEC_EXCEPTION; + } else { // other exception + mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); + ret = PYEXEC_UNHANDLED_EXCEPTION; + #if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING + if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t *)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_KeyboardInterrupt))) { // keyboard interrupt + ret = PYEXEC_KEYBOARD_INTERRUPT; + } + #endif } - } + + // CIRCUITPY_CHANGE: Fill in result out argument. if (result != NULL) { result->return_code = ret; - #if CIRCUITPY_ALARM // Don't set the exception object if we exited for deep sleep. - if (ret != 0 && ret != PYEXEC_DEEP_SLEEP) { - #else - if (ret != 0) { + if (ret != 0 + #if CIRCUITPY_ALARM + && ret != PYEXEC_DEEP_SLEEP #endif + ) { mp_obj_t return_value = (mp_obj_t)nlr.ret_val; result->exception = return_value; result->exception_line = -1; @@ -229,6 +264,10 @@ STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input } } + #if MICROPY_PYEXEC_ENABLE_VM_ABORT + nlr_set_abort(NULL); + #endif + #if MICROPY_REPL_INFO // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { @@ -277,7 +316,7 @@ typedef struct _mp_reader_stdin_t { uint16_t window_remain; } mp_reader_stdin_t; -STATIC mp_uint_t mp_reader_stdin_readbyte(void *data) { +static mp_uint_t mp_reader_stdin_readbyte(void *data) { mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data; if (reader->eof) { @@ -310,7 +349,7 @@ STATIC mp_uint_t mp_reader_stdin_readbyte(void *data) { return c; } -STATIC void mp_reader_stdin_close(void *data) { +static void mp_reader_stdin_close(void *data) { mp_reader_stdin_t *reader = (mp_reader_stdin_t *)data; if (!reader->eof) { reader->eof = true; @@ -324,7 +363,7 @@ STATIC void mp_reader_stdin_close(void *data) { } } -STATIC void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_stdin, uint16_t buf_max) { +static void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_stdin, uint16_t buf_max) { // Make flow-control window half the buffer size, and indicate to the host that 2x windows are // free (sending the window size implicitly indicates that a window is free, and then the 0x01 // indicates that another window is free). @@ -340,7 +379,7 @@ STATIC void mp_reader_new_stdin(mp_reader_t *reader, mp_reader_stdin_t *reader_s reader->close = mp_reader_stdin_close; } -STATIC int do_reader_stdin(int c) { +static int do_reader_stdin(int c) { if (c != 'A') { // Unsupported command. mp_hal_stdout_tx_strn("R\x00", 2); @@ -372,8 +411,8 @@ typedef struct _repl_t { repl_t repl; -STATIC int pyexec_raw_repl_process_char(int c); -STATIC int pyexec_friendly_repl_process_char(int c); +static int pyexec_raw_repl_process_char(int c); +static int pyexec_friendly_repl_process_char(int c); void pyexec_event_repl_init(void) { MP_STATE_VM(repl_line) = vstr_new(32); @@ -388,7 +427,7 @@ void pyexec_event_repl_init(void) { } } -STATIC int pyexec_raw_repl_process_char(int c) { +static int pyexec_raw_repl_process_char(int c) { if (c == CHAR_CTRL_A) { // reset raw REPL if (vstr_len(MP_STATE_VM(repl_line)) == 2 && vstr_str(MP_STATE_VM(repl_line))[0] == CHAR_CTRL_E) { @@ -443,7 +482,7 @@ STATIC int pyexec_raw_repl_process_char(int c) { return 0; } -STATIC int pyexec_friendly_repl_process_char(int c) { +static int pyexec_friendly_repl_process_char(int c) { if (repl.paste_mode) { if (c == CHAR_CTRL_C) { // cancel everything @@ -486,7 +525,10 @@ STATIC int pyexec_friendly_repl_process_char(int c) { // CIRCUITPY-CHANGE: print CircuitPython-style banner. mp_hal_stdout_tx_str(MICROPY_FULL_VERSION_INFO); mp_hal_stdout_tx_str("\r\n"); + #if MICROPY_PY_BUILTINS_HELP + // CIRCUITPY-CHANGE: don't print help info // mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n"); + #endif goto input_restart; } else if (ret == CHAR_CTRL_C) { // break @@ -572,10 +614,21 @@ MP_REGISTER_ROOT_POINTER(vstr_t * repl_line); #else // MICROPY_REPL_EVENT_DRIVEN +// CIRCUITPY-CHANGE: avoid warnings +#if !defined(MICROPY_HAL_HAS_STDIO_MODE_SWITCH) || !MICROPY_HAL_HAS_STDIO_MODE_SWITCH +// If the port doesn't need any stdio mode switching calls then provide trivial ones. +static inline void mp_hal_stdio_mode_raw(void) { +} +static inline void mp_hal_stdio_mode_orig(void) { +} +#endif + int pyexec_raw_repl(void) { vstr_t line; vstr_init(&line, 32); + mp_hal_stdio_mode_raw(); + raw_repl_reset: mp_hal_stdout_tx_str("raw REPL; CTRL-B to exit\r\n"); @@ -589,6 +642,7 @@ int pyexec_raw_repl(void) { if (vstr_len(&line) == 2 && vstr_str(&line)[0] == CHAR_CTRL_E) { int ret = do_reader_stdin(vstr_str(&line)[1]); if (ret & PYEXEC_FORCED_EXIT) { + mp_hal_stdio_mode_orig(); return ret; } vstr_reset(&line); @@ -601,6 +655,7 @@ int pyexec_raw_repl(void) { mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; + mp_hal_stdio_mode_orig(); return 0; } else if (c == CHAR_CTRL_C) { // clear line @@ -621,14 +676,18 @@ int pyexec_raw_repl(void) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); + mp_hal_stdio_mode_orig(); return PYEXEC_FORCED_EXIT; } + // Switch to original terminal mode to execute code, eg to support keyboard interrupt (SIGINT). + mp_hal_stdio_mode_orig(); // CIRCUITPY-CHANGE: add last arg, handle reload int ret = parse_compile_execute(&line, MP_PARSE_FILE_INPUT, EXEC_FLAG_PRINT_EOF | EXEC_FLAG_SOURCE_IS_VSTR, NULL); if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) { return ret; } + mp_hal_stdio_mode_raw(); } } @@ -636,6 +695,8 @@ int pyexec_friendly_repl(void) { vstr_t line; vstr_init(&line, 32); + mp_hal_stdio_mode_raw(); + friendly_repl_reset: // CIRCUITPY-CHANGE: CircuitPython-style banner. mp_hal_stdout_tx_str("\r\n"); @@ -663,21 +724,6 @@ int pyexec_friendly_repl(void) { for (;;) { input_restart: - - // CIRCUITPY-CHANGE: prevent undef warning - #if defined(MICROPY_HW_ENABLE_USB) && MICROPY_HW_ENABLE_USB - if (usb_vcp_is_enabled()) { - // If the user gets to here and interrupts are disabled then - // they'll never see the prompt, traceback etc. The USB REPL needs - // interrupts to be enabled or no transfers occur. So we try to - // do the user a favor and re-enable interrupts. - if (query_irq() == IRQ_STATE_DISABLED) { - enable_irq(IRQ_STATE_ENABLED); - mp_hal_stdout_tx_str("MPY: enabling IRQs\r\n"); - } - } - #endif - // If the GC is locked at this point there is no way out except a reset, // so force the GC to be unlocked to help the user debug what went wrong. if (MP_STATE_THREAD(gc_lock_depth) != 0) { @@ -708,6 +754,7 @@ int pyexec_friendly_repl(void) { mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); pyexec_mode_kind = PYEXEC_MODE_RAW_REPL; + mp_hal_stdio_mode_orig(); return 0; } else if (ret == CHAR_CTRL_B) { // reset friendly REPL @@ -721,6 +768,7 @@ int pyexec_friendly_repl(void) { // exit for a soft reset mp_hal_stdout_tx_str("\r\n"); vstr_clear(&line); + mp_hal_stdio_mode_orig(); return PYEXEC_FORCED_EXIT; } else if (ret == CHAR_CTRL_E) { // paste mode @@ -765,11 +813,14 @@ int pyexec_friendly_repl(void) { } } + // Switch to original terminal mode to execute code, eg to support keyboard interrupt (SIGINT). + mp_hal_stdio_mode_orig(); // CIRCUITPY-CHANGE: add last arg ret = parse_compile_execute(&line, parse_input_kind, EXEC_FLAG_ALLOW_DEBUGGING | EXEC_FLAG_IS_REPL | EXEC_FLAG_SOURCE_IS_VSTR, NULL); if (ret & (PYEXEC_FORCED_EXIT | PYEXEC_RELOAD)) { return ret; } + mp_hal_stdio_mode_raw(); } } @@ -832,6 +883,11 @@ int pyexec_exit_handler(const void *source, pyexec_result_t *result) { } #endif +int pyexec_vstr(vstr_t *str, bool allow_keyboard_interrupt, pyexec_result_t *result) { + mp_uint_t exec_flags = allow_keyboard_interrupt ? 0 : EXEC_FLAG_NO_INTERRUPT; + return parse_compile_execute(str, MP_PARSE_FILE_INPUT, exec_flags | EXEC_FLAG_SOURCE_IS_VSTR, result); +} + #if MICROPY_REPL_INFO mp_obj_t pyb_set_repl_info(mp_obj_t o_value) { repl_display_debugging_info = mp_obj_get_int(o_value); diff --git a/shared/runtime/pyexec.h b/shared/runtime/pyexec.h index 762b926c9c388..9d1ef2a3cb029 100644 --- a/shared/runtime/pyexec.h +++ b/shared/runtime/pyexec.h @@ -45,23 +45,30 @@ typedef struct { extern pyexec_mode_kind_t pyexec_mode_kind; -// Set this to the value (eg PYEXEC_FORCED_EXIT) that will be propagated through -// the pyexec functions if a SystemExit exception is raised by the running code. -// It will reset to 0 at the start of each execution (eg each REPL entry). -extern int pyexec_system_exit; - #define PYEXEC_FORCED_EXIT (0x100) // CIRCUITPY-CHANGE: additional flags #define PYEXEC_EXCEPTION (0x200) #define PYEXEC_DEEP_SLEEP (0x400) #define PYEXEC_RELOAD (0x800) +#if MICROPY_PYEXEC_ENABLE_EXIT_CODE_HANDLING +#define PYEXEC_NORMAL_EXIT (0) +#define PYEXEC_UNHANDLED_EXCEPTION (1) +#define PYEXEC_KEYBOARD_INTERRUPT (128 + 2) // same as SIG INT exit code +#define PYEXEC_ABORT (128 + 9) // same as SIG KILL exit code +#else +#define PYEXEC_NORMAL_EXIT (1) +#define PYEXEC_UNHANDLED_EXCEPTION (0) +#define PYEXEC_ABORT PYEXEC_FORCED_EXIT +#endif + int pyexec_raw_repl(void); int pyexec_friendly_repl(void); // CIRCUITPY-CHANGE: result out argument int pyexec_file(const char *filename, pyexec_result_t *result); int pyexec_file_if_exists(const char *filename, pyexec_result_t *result); int pyexec_frozen_module(const char *name, bool allow_keyboard_interrupt, pyexec_result_t *result); +int pyexec_vstr(vstr_t *str, bool allow_keyboard_interrupt, pyexec_result_t *result); void pyexec_event_repl_init(void); int pyexec_event_repl_process_char(int c); extern uint8_t pyexec_repl_active; diff --git a/shared/runtime/semihosting.c b/shared/runtime/semihosting.c deleted file mode 100644 index 18c7f5d57a3f3..0000000000000 --- a/shared/runtime/semihosting.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Ayke van Laethem - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "semihosting.h" - -// Resources: -// http://embed.rs/articles/2016/semi-hosting-rust/ -// https://wiki.dlang.org/Minimal_semihosted_ARM_Cortex-M_%22Hello_World%22 -// https://github.com/arduino/OpenOCD/blob/master/src/target/arm_semihosting.c - -#define SYS_OPEN 0x01 -#define SYS_WRITEC 0x03 -#define SYS_WRITE 0x05 -#define SYS_READC 0x07 - -// Constants: -#define OPEN_MODE_READ (0) // mode "r" -#define OPEN_MODE_WRITE (4) // mode "w" - -#ifndef __thumb__ -#error Semihosting is only implemented for ARM microcontrollers. -#endif - -static int mp_semihosting_stdout; - -static uint32_t mp_semihosting_call(uint32_t num, const void *arg) { - // A semihosting call works as follows, similar to a SVCall: - // * the call is invoked by a special breakpoint: 0xAB - // * the command is placed in r0 - // * a pointer to the arguments is placed in r1 - // * the return value is placed in r0 - // Note that because it uses the breakpoint instruction, applications - // will hang if they're not connected to a debugger. And they'll be - // stuck in a breakpoint if semihosting is not specifically enabled in - // the debugger. - // Also note that semihosting is extremely slow (sometimes >100ms per - // call). - register uint32_t num_reg __asm__ ("r0") = num; - register const void *args_reg __asm__ ("r1") = arg; - __asm__ __volatile__ ( - "bkpt 0xAB\n" // invoke semihosting call - : "+r" (num_reg) // call number and result - : "r" (args_reg) // arguments - : "memory"); // make sure args aren't optimized away - return num_reg; // r0, which became the result -} - -static int mp_semihosting_open_console(uint32_t mode) { - struct { - char *name; - uint32_t mode; - uint32_t name_len; - } args = { - .name = ":tt", // magic path to console - .mode = mode, // e.g. "r", "w" (see OPEN_MODE_* constants) - .name_len = 3, // strlen(":tt") - }; - return mp_semihosting_call(SYS_OPEN, &args); -} - -void mp_semihosting_init() { - mp_semihosting_stdout = mp_semihosting_open_console(OPEN_MODE_WRITE); -} - -int mp_semihosting_rx_char() { - return mp_semihosting_call(SYS_READC, NULL); -} - -static void mp_semihosting_tx_char(char c) { - mp_semihosting_call(SYS_WRITEC, &c); -} - -uint32_t mp_semihosting_tx_strn(const char *str, size_t len) { - if (len == 0) { - return 0; // nothing to do - } - if (len == 1) { - mp_semihosting_tx_char(*str); // maybe faster? - return 0; - } - - struct { - uint32_t fd; - const char *str; - uint32_t len; - } args = { - .fd = mp_semihosting_stdout, - .str = str, - .len = len, - }; - return mp_semihosting_call(SYS_WRITE, &args); -} - -uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len) { - // Write chunks of data until (excluding) the first '\n' character, - // insert a '\r' character, and then continue with the next chunk - // (starting with '\n'). - // Doing byte-by-byte writes would be easier to implement but is far - // too slow. - size_t start = 0; - for (size_t i = 0; i < len; i++) { - if (str[i] == '\n') { - mp_semihosting_tx_strn(str + start, i - start); - mp_semihosting_tx_char('\r'); - start = i; - } - } - return mp_semihosting_tx_strn(str + start, len - start); -} diff --git a/shared/runtime/semihosting.h b/shared/runtime/semihosting.h deleted file mode 100644 index d053a03edaae9..0000000000000 --- a/shared/runtime/semihosting.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 Ayke van Laethem - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H -#define MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H - -/* - -To use semi-hosting for a replacement UART: -- Add lib/semihosting/semihosting.c to the Makefile sources. -- Call mp_semihosting_init() in main(), around the time UART is initialized. -- Replace mp_hal_stdin_rx_chr and similar in mphalport.c with the semihosting equivalent. -- Include lib/semihosting/semihosting.h in the relevant files. - -Then make sure the debugger is attached and enables semihosting. In OpenOCD this is -done with ARM semihosting enable followed by reset. The terminal will need further -configuration to work with MicroPython (bash: stty raw -echo). - -*/ - -#include -#include - -void mp_semihosting_init(); -int mp_semihosting_rx_char(); -uint32_t mp_semihosting_tx_strn(const char *str, size_t len); -uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len); - -#endif // MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H diff --git a/shared/runtime/semihosting_arm.c b/shared/runtime/semihosting_arm.c new file mode 100644 index 0000000000000..f4d168f79bc81 --- /dev/null +++ b/shared/runtime/semihosting_arm.c @@ -0,0 +1,157 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Ayke van Laethem + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "semihosting_arm.h" + +// Resources: +// http://embed.rs/articles/2016/semi-hosting-rust/ +// https://wiki.dlang.org/Minimal_semihosted_ARM_Cortex-M_%22Hello_World%22 +// https://github.com/arduino/OpenOCD/blob/master/src/target/arm_semihosting.c + +#define SYS_OPEN 0x01 +#define SYS_WRITEC 0x03 +#define SYS_WRITE 0x05 +#define SYS_READ 0x06 +#define SYS_READC 0x07 +#define SYS_EXIT 0x18 + +// Constants: +#define OPEN_MODE_READ (0) // mode "r" +#define OPEN_MODE_WRITE (4) // mode "w" + +static int mp_semihosting_stdout; + +static uint32_t mp_semihosting_call(uint32_t num, const void *arg) { + // A semihosting call works as follows, similar to a SVCall: + // * the call is invoked by a special breakpoint: 0xAB + // * the command is placed in r0 + // * a pointer to the arguments is placed in r1 + // * the return value is placed in r0 + // Note that because it uses the breakpoint instruction, applications + // will hang if they're not connected to a debugger. And they'll be + // stuck in a breakpoint if semihosting is not specifically enabled in + // the debugger. + // Also note that semihosting is extremely slow (sometimes >100ms per + // call). + register uint32_t num_reg __asm__ ("r0") = num; + register const void *args_reg __asm__ ("r1") = arg; + __asm__ __volatile__ ( + #if defined(__ARM_ARCH_ISA_ARM) + "svc 0x00123456\n" // invoke semihosting call + #elif defined(__ARM_ARCH_ISA_THUMB) + "bkpt 0xAB\n" // invoke semihosting call + #else + #error Unknown architecture + #endif + : "+r" (num_reg) // call number and result + : "r" (args_reg) // arguments + : "memory"); // make sure args aren't optimized away + return num_reg; // r0, which became the result +} + +static int mp_semihosting_open_console(uint32_t mode) { + struct { + char *name; + uint32_t mode; + uint32_t name_len; + } args = { + .name = ":tt", // magic path to console + .mode = mode, // e.g. "r", "w" (see OPEN_MODE_* constants) + .name_len = 3, // strlen(":tt") + }; + return mp_semihosting_call(SYS_OPEN, &args); +} + +void mp_semihosting_init() { + mp_semihosting_stdout = mp_semihosting_open_console(OPEN_MODE_WRITE); +} + +void mp_semihosting_exit(int status) { + if (status == 0) { + status = 0x20026; + } + mp_semihosting_call(SYS_EXIT, (void *)(uintptr_t)status); +} + +int mp_semihosting_rx_char() { + return mp_semihosting_call(SYS_READC, NULL); +} + +// Returns 0 on success. +int mp_semihosting_rx_chars(char *str, size_t len) { + struct { + uint32_t fd; + const char *str; + uint32_t len; + } args = { + .fd = mp_semihosting_stdout, + .str = str, + .len = len, + }; + return mp_semihosting_call(SYS_READ, &args); +} + +static void mp_semihosting_tx_char(char c) { + mp_semihosting_call(SYS_WRITEC, &c); +} + +uint32_t mp_semihosting_tx_strn(const char *str, size_t len) { + if (len == 0) { + return 0; // nothing to do + } + if (len == 1) { + mp_semihosting_tx_char(*str); // maybe faster? + return 0; + } + + struct { + uint32_t fd; + const char *str; + uint32_t len; + } args = { + .fd = mp_semihosting_stdout, + .str = str, + .len = len, + }; + return mp_semihosting_call(SYS_WRITE, &args); +} + +uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len) { + // Write chunks of data until (excluding) the first '\n' character, + // insert a '\r' character, and then continue with the next chunk + // (starting with '\n'). + // Doing byte-by-byte writes would be easier to implement but is far + // too slow. + size_t start = 0; + for (size_t i = 0; i < len; i++) { + if (str[i] == '\n') { + mp_semihosting_tx_strn(str + start, i - start); + mp_semihosting_tx_char('\r'); + start = i; + } + } + return mp_semihosting_tx_strn(str + start, len - start); +} diff --git a/shared/runtime/semihosting_arm.h b/shared/runtime/semihosting_arm.h new file mode 100644 index 0000000000000..08fb66578ac14 --- /dev/null +++ b/shared/runtime/semihosting_arm.h @@ -0,0 +1,55 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Ayke van Laethem + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_ARM_H +#define MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_ARM_H + +/* + +To use semi-hosting for a replacement UART: +- Add shared/runtime/semihosting_arm.c to the Makefile sources. +- Call mp_semihosting_init() in main(), around the time UART is initialized. +- Replace mp_hal_stdin_rx_chr and similar in mphalport.c with the semihosting equivalent. +- Include shared/runtime/semihosting_arm.h in the relevant files. + +Then make sure the debugger is attached and enables semihosting. In OpenOCD this is +done with ARM semihosting enable followed by reset. The terminal will need further +configuration to work with MicroPython (bash: stty raw -echo). + +If mp_semihosting_rx_char() doesn't work then try mp_semihosting_rx_chars(str, 1). + +*/ + +#include +#include + +void mp_semihosting_init(); +void mp_semihosting_exit(int status); +int mp_semihosting_rx_char(); +int mp_semihosting_rx_chars(char *str, size_t len); +uint32_t mp_semihosting_tx_strn(const char *str, size_t len); +uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len); + +#endif // MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_ARM_H diff --git a/shared/runtime/semihosting_rv32.c b/shared/runtime/semihosting_rv32.c new file mode 100644 index 0000000000000..1d02b69b23ea8 --- /dev/null +++ b/shared/runtime/semihosting_rv32.c @@ -0,0 +1,481 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "semihosting_rv32.h" + +#if !defined(__riscv) || !defined(__riscv_xlen) || (__riscv_xlen != 32) +#error "This semihosting support code is only available for RV32 targets." +#endif + +// Features file magic header. +#define MAGIC_SIZE 4 +#define MAGIC_0 0x53 // 'S' +#define MAGIC_1 0x48 // 'H' +#define MAGIC_2 0x46 // 'B' +#define MAGIC_3 0x42 // 'F' + +#define CMDLINE_MIN_BUFFER_SIZE 80 + +#define SYS_OPEN 0x01 +#define SYS_CLOSE 0x02 +#define SYS_WRITEC 0x03 +#define SYS_WRITE0 0x04 +#define SYS_WRITE 0x05 +#define SYS_READ 0x06 +#define SYS_READC 0x07 +#define SYS_ISERROR 0x08 +#define SYS_ISTTY 0x09 +#define SYS_SEEK 0x0A +#define SYS_FLEN 0x0C +#define SYS_TMPNAM 0x0D +#define SYS_REMOVE 0x0E +#define SYS_RENAME 0x0F +#define SYS_CLOCK 0x10 +#define SYS_TIME 0x11 +#define SYS_SYSTEM 0x12 +#define SYS_ERRNO 0x13 +#define SYS_GET_CMDLINE 0x15 +#define SYS_HEAPINFO 0x16 +#define SYS_EXIT 0x18 +#define SYS_EXIT_EXTENDED 0x20 +#define SYS_ELAPSED 0x30 +#define SYS_TICKFREQ 0x31 + +// Extended features availability flags. +static bool exit_extended_available = false; +static bool split_stdout_stderr = false; + +// Perform a semihosting call with the given call number and using the given +// parameters block. +int mp_semihosting_call(uint32_t num, void *arg); + +// Convert the given fopen(3) open mode string into the appropriate integer +// value required by SYS_OPEN. If the mode is invalid, it will return -1. +static int mp_lookup_open_mode(const char *mode); + +// Computes the length of the given string. If it gets passed a NULL pointer +// it will return -1. +static int mp_strlen(const char *string); + +// Check which extended features are advertised by the host system. +static void mp_check_extended_features_availability(void); + +// Write the given string to the host system's debug console. +static int mp_write_to_debug_console(const char *string, size_t length); + +// The host system's STDOUT file handle. +int mp_semihosting_stdout = -1; + +// The host system's STDERR file handle. +int mp_semihosting_stderr = -1; + +int mp_semihosting_open(const char *file_name, const char *file_mode) { + if (file_name == NULL || file_mode == NULL) { + return -1; + } + + int file_name_length = mp_strlen(file_name); + if (file_name_length <= 0) { + return -1; + } + int file_open_mode = mp_lookup_open_mode(file_mode); + if (file_open_mode < 0) { + return -1; + } + + uint32_t arguments[3] = { (uintptr_t)file_name, file_open_mode, file_name_length }; + return mp_semihosting_call(SYS_OPEN, arguments); +} + +int mp_semihosting_close(int handle) { + uint32_t arguments[] = { handle }; + return mp_semihosting_call(SYS_CLOSE, arguments); +} + +void mp_semihosting_writec(char character) { + uint32_t arguments[] = { character }; + mp_semihosting_call(SYS_WRITEC, arguments); +} + +void mp_semihosting_write0(const char *string) { + if (string == NULL) { + return; + } + uint32_t arguments[] = { (uintptr_t)string }; + mp_semihosting_call(SYS_WRITE0, arguments); +} + +int mp_semihosting_write(int handle, const void *data, size_t length) { + if (data == NULL) { + return length; + } + if (length == 0) { + return 0; + } + + uint32_t arguments[] = { handle, (uintptr_t)data, length }; + return mp_semihosting_call(SYS_WRITE, arguments); +} + +int mp_semihosting_read(int handle, void *data, size_t length) { + if (data == NULL) { + return -1; + } + if (length == 0) { + return 0; + } + + uint32_t arguments[] = { handle, (uintptr_t)data, length }; + return mp_semihosting_call(SYS_READ, arguments); +} + +inline int mp_semihosting_readc(void) { + return mp_semihosting_call(SYS_READC, NULL); +} + +int mp_semihosting_iserror(int code) { + uint32_t arguments[] = { code }; + return mp_semihosting_call(SYS_ISERROR, arguments); +} + +int mp_semihosting_istty(int handle) { + uint32_t arguments[] = { handle }; + return mp_semihosting_call(SYS_ISTTY, arguments); +} + +int mp_semihosting_seek(int handle, uint32_t offset) { + uint32_t arguments[] = { handle, offset }; + return mp_semihosting_call(SYS_SEEK, arguments); +} + +int mp_semihosting_flen(int handle) { + uint32_t arguments[] = { handle }; + return mp_semihosting_call(SYS_FLEN, arguments); +} + +int mp_semihosting_tmpnam(uint8_t identifier, void *buffer, size_t buffer_length) { + if (buffer == NULL || buffer_length == 0) { + return -1; + } + + uint32_t arguments[] = { (uintptr_t)buffer, identifier, buffer_length }; + return mp_semihosting_call(SYS_TMPNAM, arguments); +} + +int mp_semihosting_remove(const char *file_name) { + if (file_name == NULL) { + return -1; + } + + int file_name_length = mp_strlen(file_name); + if (file_name_length <= 0) { + return -1; + } + + uint32_t arguments[] = { (uintptr_t)file_name, file_name_length }; + return mp_semihosting_call(SYS_REMOVE, arguments); +} + +int mp_semihosting_rename(const char *old_name, const char *new_name) { + if (old_name == NULL || new_name == NULL) { + return -1; + } + + int old_name_length = mp_strlen(old_name); + if (old_name_length <= 0) { + return -1; + } + + int new_name_length = mp_strlen(new_name); + if (new_name_length <= 0) { + return -1; + } + + uint32_t arguments[] = { + (uintptr_t)old_name, old_name_length, (uintptr_t)new_name, new_name_length + }; + return mp_semihosting_call(SYS_RENAME, arguments); +} + +inline int mp_semihosting_clock(void) { + return mp_semihosting_call(SYS_CLOCK, NULL); +} + +inline int mp_semihosting_time(void) { + return mp_semihosting_call(SYS_TIME, NULL); +} + +int mp_semihosting_system(const char *command) { + if (command == NULL) { + return -1; + } + + int command_length = mp_strlen(command); + if (command_length <= 0) { + return -1; + } + + uint32_t arguments[] = { (uintptr_t)command, command_length }; + return mp_semihosting_call(SYS_SYSTEM, arguments); +} + +inline int mp_semihosting_errno(void) { + return mp_semihosting_call(SYS_ERRNO, NULL); +} + +int mp_semihosting_get_cmdline(void *buffer, size_t buffer_length) { + if (buffer == NULL || buffer_length < CMDLINE_MIN_BUFFER_SIZE) { + return -1; + } + + uint32_t arguments[] = { (uintptr_t)buffer, buffer_length }; + return mp_semihosting_call(SYS_GET_CMDLINE, arguments); +} + +void mp_semihosting_heapinfo(mp_semihosting_heap_info_t *block) { + if (block == NULL) { + return; + } + + uint32_t arguments[] = { (uintptr_t)block }; + mp_semihosting_call(SYS_HEAPINFO, arguments); +} + +void mp_semihosting_exit(uint32_t code, uint32_t subcode) { + uint32_t arguments[] = { code, subcode }; + mp_semihosting_call(SYS_EXIT, arguments); + for (;;) {} +} + +void mp_semihosting_exit_extended(uint32_t code, uint32_t subcode) { + uint32_t arguments[] = { code, subcode }; + mp_semihosting_call(SYS_EXIT_EXTENDED, arguments); + for (;;) {} +} + +int mp_semihosting_elapsed(mp_semihosting_elapsed_ticks_t *ticks) { + if (ticks == NULL) { + return -1; + } + + uint32_t arguments[] = { (uintptr_t)ticks }; + return mp_semihosting_call(SYS_ELAPSED, arguments); +} + +inline int mp_semihosting_tickfreq(void) { + return mp_semihosting_call(SYS_TICKFREQ, NULL); +} + +void mp_semihosting_init() { + mp_check_extended_features_availability(); + mp_semihosting_stdout = mp_semihosting_open(":tt", "w"); + if (split_stdout_stderr) { + mp_semihosting_stderr = mp_semihosting_open(":tt", "a"); + } else { + mp_semihosting_stderr = mp_semihosting_stdout; + } +} + +void mp_check_extended_features_availability(void) { + int features_handle = mp_semihosting_open(":semihosting-features", "r"); + if (features_handle < 0) { + return; + } + + uint8_t magic_buffer[MAGIC_SIZE]; + if (mp_semihosting_flen(features_handle) < sizeof(magic_buffer)) { + mp_semihosting_close(features_handle); + return; + } + + if (mp_semihosting_read(features_handle, magic_buffer, sizeof(magic_buffer)) != 0) { + mp_semihosting_close(features_handle); + return; + } + + if (magic_buffer[0] != MAGIC_0 || + magic_buffer[1] != MAGIC_1 || + magic_buffer[2] != MAGIC_2 || + magic_buffer[3] != MAGIC_3) { + mp_semihosting_close(features_handle); + return; + } + + uint8_t features_byte = 0; + if (mp_semihosting_read(features_handle, &features_byte, sizeof(features_byte)) != 0) { + mp_semihosting_close(features_handle); + return; + } + + mp_semihosting_close(features_handle); + + exit_extended_available = (features_byte & 0x01) != 0; + split_stdout_stderr = (features_byte & 0x02) != 0; +} + +int mp_strlen(const char *string) { + int length = 0; + while (*string++ != 0) { + length += 1; + } + return length; +} + +int mp_lookup_open_mode(const char *mode) { + if (mode == NULL) { + return -1; + } + + int mode_found; + + switch (mode[0]) { + case 'r': + mode_found = 0x00; + break; + case 'w': + mode_found = 0x04; + break; + case 'a': + mode_found = 0x08; + break; + default: + return -1; + } + + switch (mode[1]) { + case 'b': + mode_found |= 0x01; + break; + case '+': + mode_found |= 0x02; + break; + case '\0': + return mode_found; + default: + return -1; + } + + switch (mode[2]) { + case 'b': + if (mode_found & 0x01) { + // 'b' was already seen. + return -1; + } + mode_found |= 1; + break; + case '+': + if (mode_found & 0x02) { + // '+' was already seen. + return -1; + } + mode_found |= 2; + break; + case '\0': + return mode_found; + default: + return -1; + } + + return mode[3] == '\0' ? mode_found : -1; +} + +int mp_semihosting_call(uint32_t num, void *arg) { + register uint32_t call_number_register __asm__ ("x10") = num; + register void *arguments_register __asm__ ("x11") = arg; + + __asm volatile ( + ".option push \n" // Transient options + ".option norvc \n" // Do not emit compressed instructions + ".align 4 \n" // 16 bytes alignment + "slli zero, zero, 0x1F \n" // Entry NOP + "ebreak \n" // Give control to the debugger + "srai zero, zero, 7 \n" // Semihosting call + ".option pop \n" // Restore previous options set + : "+r" (call_number_register) + : "r" (arguments_register) + : "memory" + ); + + return call_number_register; +} + +inline int mp_semihosting_rx_char() { + return mp_semihosting_call(SYS_READC, NULL); +} + +int mp_write_to_debug_console(const char *string, size_t length) { + if (length == 0) { + return 0; + } + + if (length == 1) { + mp_semihosting_writec(*string); + return 0; + } + + return mp_semihosting_write(mp_semihosting_stdout, string, length); +} + +void mp_semihosting_terminate(uint32_t code, uint32_t subcode) { + if (exit_extended_available) { + mp_semihosting_exit_extended(code, subcode); + } else { + mp_semihosting_exit(code, subcode); + } +} + +int mp_semihosting_tx_strn(const char *string, size_t length) { + if (string == NULL) { + return -1; + } + + return mp_write_to_debug_console(string, length); +} + +int mp_semihosting_tx_strn_cooked(const char *string, size_t length) { + if (string == NULL) { + return -1; + } + + if (length == 0) { + return 0; + } + + size_t current_offset = 0; + for (size_t index = 0; index < length; index++) { + if (string[index] != '\n') { + continue; + } + + mp_write_to_debug_console(string + current_offset, index - current_offset); + mp_semihosting_writec('\r'); + current_offset = index; + } + + return mp_write_to_debug_console(string + current_offset, length - current_offset); +} diff --git a/shared/runtime/semihosting_rv32.h b/shared/runtime/semihosting_rv32.h new file mode 100644 index 0000000000000..7cabd1692c1cf --- /dev/null +++ b/shared/runtime/semihosting_rv32.h @@ -0,0 +1,247 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Alessandro Gatti + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_RV32_H +#define MICROPY_INCLUDED_SHARED_RUNTIME_SEMIHOSTING_RV32_H + +/* + * To integrate semihosting, make sure to call mp_semihosting_init() first. + * Then, if the host system's STDOUT should be used instead of a UART, replace + * mp_hal_stdin_rx_chr and similar calls in mphalport.c with the semihosting + * equivalents. + * + * At runtime, make sure that the debugger is attached and semihosting is + * enabled on its end. The terminal must be configured in raw mode with local + * echo disabled, on Linux this can be done with "stty raw -echo" on the + * command line. + */ + +/* + * This follows the RISC-V Semihosting specification version 0.3. + * + * That document can be downloaded from + * https://github.com/riscv-non-isa/riscv-semihosting/releases/ + * + * Version 0.3 claims that the current RISC-V Semihosting implementation + * should follow Arm's, and more precisely the "Semihosting for AArch32 + * and AArch64" document, revision 2023Q3. + */ + +#include +#include +#include + +// A container for heap and stack pointers as returned by SYS_HEAPINFO. +typedef struct { + void *heap_base; + void *heap_limit; + void *stack_base; + void *stack_limit; +} mp_semihosting_heap_info_t; + +// A 64-bits value indicating how many ticks were counted since the target +// image's execution started. +typedef struct { + uint32_t low; + uint32_t high; +} mp_semihosting_elapsed_ticks_t; + +// The host system's STDOUT file handle. +extern int mp_semihosting_stdout; + +// The host system's STDERR file handle. If the host system does not support +// explicit STDOUT and STDERR handles, this handle will be aliased to STDOUT +// instead. +extern int mp_semihosting_stderr; + +/* + * Even though exit codes from 0x20000 to 0x20007 are part of the original Arm + * specification document, they are omitted due to them being tied to hardware + * events. Whilst some of them may still have a meaning on the RISC-V + * platform, it is not yet clear which ones are available and which ones are + * not. Thus, only "soft" error codes are provided here although the SYS_EXIT + * and SYS_EXIT_EXTENDED semihosting calls accept any 32-bits integer as an + * exit code. + */ + +enum { + MP_SEMIHOSTING_EXIT_BREAKPOINT = 0x20020, + MP_SEMIHOSTING_EXIT_WATCHPOINT, + MP_SEMIHOSTING_EXIT_STEP_COMPLETE, + MP_SEMIHOSTING_EXIT_RUNTIME_ERROR_UNKNOWN, + MP_SEMIHOSTING_EXIT_INTERNAL_ERROR, + MP_SEMIHOSTING_EXIT_USER_INTERRUPTION, + MP_SEMIHOSTING_EXIT_APPLICATION_EXIT, + MP_SEMIHOSTING_EXIT_STACK_OVERFLOW, + MP_SEMIHOSTING_EXIT_DIVISION_BY_ZERO, + MP_SEMIHOSTING_EXIT_OS_SPECIFIC +}; + +// Initialises semihosting support. +void mp_semihosting_init(); + +// Read a character from the host system's STDIN stream. +int mp_semihosting_rx_char(); + +// Write the given string to the host system's STDOUT stream. +int mp_semihosting_tx_strn(const char *string, size_t length); + +// Write the given string to the host system's STDOUT stream, writing a CR byte +// before each LF byte to be written. +int mp_semihosting_tx_strn_cooked(const char *string, size_t length); + +// Terminates execution with the given code and an optional subcode. This +// will choose the appropriate semihosting call (either SYS_EXIT or +// SYS_EXIT_EXTENDED) depending on the host system's reported capabilities. +noreturn void mp_semihosting_terminate(uint32_t code, uint32_t subcode); + +// Direct semihosting calls access. + +// Open a file on the host system with the given name and file mode. +// The file mode follows fopen(3)'s syntax. The function will return -1 if it +// failed to open the required file, or a file handle number if the operation +// succeeded. To see why the operation failed, call mp_semihosting_errno. +int mp_semihosting_open(const char *file_name, const char *file_mode); + +// Close a file previously opened with mp_semihosting_open. If the file cannot +// be closed, the function will return -1, otherwise it will return 0. To see +// why the operation failed, call mp_semihosting_errno. +int mp_semihosting_close(int handle); + +// Write the given character to the host system's STDOUT file handle. +void mp_semihosting_writec(char character); + +// Write the given NULL-terminated string to the host system's STDOUT file +// handle. +void mp_semihosting_write0(const char *string); + +// Write the given buffer to the given host system file handle. The function +// will return how many characters were left to be written (0 if the operation +// wrote the whole buffer), or -1 if the input buffer pointer is NULL. +int mp_semihosting_write(int handle, const void *data, size_t length); + +// Read from the given host system file handle into the given buffer. The +// function will return how many characters were left to be read (0 if the +// operation read whole buffer), or -1 if the input buffer pointer is NULL. +int mp_semihosting_read(int handle, void *data, size_t length); + +// Read a single character from the host system's STDIN file handle. +int mp_semihosting_readc(void); + +// Check whether the given result code represents an error. The function will +// return a non-zero value if the code is indeed an error, or zero otherwise. +int mp_semihosting_iserror(int code); + +// Check whether the given host system file handle is mapped to an interactive +// device. The function will return 1 if the handle is mapped to an +// interactive device, 0 if it is mapped to a regular file, and anything else +// if an error occurred. +int mp_semihosting_istty(int handle); + +// Move the file pointer on the given host system's file handle to the given +// absolute offset (in bytes). The function will return 0 if the file pointer +// was moved to the requested position, or a negative value if it was not +// possible to do so. To see why the operation failed, call +// mp_semihosting_errno. +int mp_semihosting_seek(int handle, uint32_t offset); + +// Get the length (in bytes) of the host system's file mapped to the given +// handle. The function will return a negative value if an error occurred, or +// the requested file's length (in bytes). +int mp_semihosting_flen(int handle); + +// Create a temporary file on the host system. The function requires a file +// identifier between 0 and 255 (inclusive) that will be bound to the requested +// temporary file. Subsequent calls to mp_semihosting_tmpnam with the same +// identifier will always return the same host system file name. On success, +// the function will fill the given buffer with the host system's file name, +// and will return 0. If the buffer pointer is NULL, the buffer name area is +// too small, or the operation failed on the host system's end, the function +// will return -1 instead. Make sure that the buffer is big enough to contain +// a host system's full path name. +int mp_semihosting_tmpnam(uint8_t identifier, void *buffer, size_t buffer_length); + +// Delete a file on the host system's matching the given file name. The +// function will return 0 if the deletion operation succeeded, or a host system +// dependent error code instead. +int mp_semihosting_remove(const char *file_name); + +// Rename a file on the host system's name matching the given file name to the +// new chosen name. The function will return 0 if the rename operation +// succeeded, or a host system dependent error code instead. +int mp_semihosting_rename(const char *old_name, const char *new_name); + +// Get how many hundredths of a second passed since execution started. If an +// error occurred whilst retrieving clock value, the function will return -1. +int mp_semihosting_clock(void); + +// Get the host system's clock in seconds since midnight of January 1st, 1970 +// at UTC. +int mp_semihosting_time(void); + +// Execute the given command on the host system. The function will return the +// command's result code retrieved on the host system. +int mp_semihosting_system(const char *command); + +// Get the last operation's status code. The function will return the host +// system's errno variable contents, and can be used to see the exact result +// code for failed I/O operations. +int mp_semihosting_errno(void); + +// Get the host system's command line that started execution of the target +// image. The function will fill the given buffer with the command line +// arguments passed to the target executable. The function will return 0 on +// success, or -1 if it failed. Make sure that the buffer can contain at +// least 80 bytes, as it is the minimum supported size defined by the +// specifications document. +int mp_semihosting_get_cmdline(void *buffer, size_t buffer_length); + +// Fill the given heap info structure with the system's stack and heap +// start/end addresses. +void mp_semihosting_heapinfo(mp_semihosting_heap_info_t *block); + +// Terminate the execution with the given reason code and optional subcode. +// This should be preferred over mp_semihosting_exit_extended if the host +// system does not support the SYS_EXIT_EXTENDED semihosting call. In doubt +// use mp_semihosting_terminate instead. +noreturn void mp_semihosting_exit(uint32_t code, uint32_t subcode); + +// Terminate the execution with the given reason code and optional subcode. +// This should be preferred over mp_semihosting_exit if the host system +// supports this semihosting call. In doubt use mp_semihosting_terminate +// instead. +noreturn void mp_semihosting_exit_extended(uint32_t code, uint32_t subcode); + +// Fill the given structure with how many ticks were counted since execution +// started. On success, the function will return 0, or -1 if it was not +// possible to compute the ticks count. +int mp_semihosting_elapsed(mp_semihosting_elapsed_ticks_t *ticks); + +// Get the system's tick frequency. If this value is not known, the function +// will return -1 instead. +int mp_semihosting_tickfreq(void); + +#endif // MICROPY_INCLUDED_SHARED_SEMIHOSTING_RUNTIME_RV32_H diff --git a/shared/runtime/sys_stdio_mphal.c b/shared/runtime/sys_stdio_mphal.c index e8e39799d9229..b82725bfa7bf8 100644 --- a/shared/runtime/sys_stdio_mphal.c +++ b/shared/runtime/sys_stdio_mphal.c @@ -49,15 +49,15 @@ typedef struct _sys_stdio_obj_t { } sys_stdio_obj_t; #if MICROPY_PY_SYS_STDIO_BUFFER -STATIC const sys_stdio_obj_t stdio_buffer_obj; +static const sys_stdio_obj_t stdio_buffer_obj; #endif -STATIC void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +static void stdio_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "", self->fd); + mp_printf(print, "", mp_obj_get_type_str(self_in), self->fd); } -STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->fd == STDIO_FD_IN) { for (uint i = 0; i < size; i++) { @@ -74,7 +74,7 @@ STATIC mp_uint_t stdio_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *er } } -STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { sys_stdio_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->fd == STDIO_FD_OUT || self->fd == STDIO_FD_ERR) { mp_hal_stdout_tx_strn_cooked(buf, size); @@ -85,7 +85,7 @@ STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, } } -STATIC mp_uint_t stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { +static mp_uint_t stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) { (void)self_in; if (request == MP_STREAM_POLL) { return mp_hal_stdio_poll(arg); @@ -97,7 +97,7 @@ STATIC mp_uint_t stdio_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, } } -STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { +static const mp_rom_map_elem_t stdio_locals_dict_table[] = { #if MICROPY_PY_SYS_STDIO_BUFFER { MP_ROM_QSTR(MP_QSTR_buffer), MP_ROM_PTR(&stdio_buffer_obj) }, #endif @@ -111,9 +111,9 @@ STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&mp_stream___exit___obj) }, }; -STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); +static MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); -STATIC const mp_stream_p_t stdio_obj_stream_p = { +static const mp_stream_p_t stdio_obj_stream_p = { .read = stdio_read, .write = stdio_write, .ioctl = stdio_ioctl, @@ -122,7 +122,7 @@ STATIC const mp_stream_p_t stdio_obj_stream_p = { MP_DEFINE_CONST_OBJ_TYPE( stdio_obj_type, - MP_QSTR_StringIO, + MP_QSTR_TextIOWrapper, MP_TYPE_FLAG_ITER_IS_STREAM, print, stdio_obj_print, protocol, &stdio_obj_stream_p, @@ -134,25 +134,25 @@ const sys_stdio_obj_t mp_sys_stdout_obj = {{&stdio_obj_type}, .fd = STDIO_FD_OUT const sys_stdio_obj_t mp_sys_stderr_obj = {{&stdio_obj_type}, .fd = STDIO_FD_ERR}; #if MICROPY_PY_SYS_STDIO_BUFFER -STATIC mp_uint_t stdio_buffer_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stdio_buffer_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) { for (uint i = 0; i < size; i++) { ((byte *)buf)[i] = mp_hal_stdin_rx_chr(); } return size; } -STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { +static mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) { return mp_hal_stdout_tx_strn(buf, size); } -STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { +static const mp_stream_p_t stdio_buffer_obj_stream_p = { .read = stdio_buffer_read, .write = stdio_buffer_write, .ioctl = stdio_ioctl, .is_text = false, }; -STATIC MP_DEFINE_CONST_OBJ_TYPE( +static MP_DEFINE_CONST_OBJ_TYPE( stdio_buffer_obj_type, MP_QSTR_FileIO, MP_TYPE_FLAG_ITER_IS_STREAM, @@ -161,5 +161,5 @@ STATIC MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &stdio_locals_dict ); -STATIC const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused +static const sys_stdio_obj_t stdio_buffer_obj = {{&stdio_buffer_obj_type}, .fd = 0}; // fd unused #endif diff --git a/shared/timeutils/timeutils.c b/shared/timeutils/timeutils.c index 6bf3eca84a82b..0c6916e06ddd6 100644 --- a/shared/timeutils/timeutils.c +++ b/shared/timeutils/timeutils.c @@ -29,21 +29,48 @@ #include "shared/timeutils/timeutils.h" -// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately -// after Feb 29. We calculate seconds as a signed integer relative to that. +// To maintain reasonable compatibility with CPython on embedded systems, +// and avoid breaking anytime soon, timeutils functions are required to +// work properly between 1970 and 2099 on all ports. // -// Our timebase is relative to 2000-01-01. - -#define LEAPOCH ((31 + 29) * 86400) +// During that period of time, leap years occur every 4 years without +// exception, so we can keep the code short for 32 bit machines. + +// The last leap day before the required period is Feb 29, 1968. +// This is the number of days to add to get to that date. +#define PREV_LEAP_DAY ((mp_uint_t)(365 + 366 - (31 + 29))) +#define PREV_LEAP_YEAR 1968 + +// On ports where either MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND or +// MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE is enabled, we include extra +// code to support leap years outside of the 'easy' period. +// Computation is then made based on 1600 (a mod-400 year). +// This is the number of days between 1600 and 1968. +#define QC_BASE_DAY 134409 +#define QC_LEAP_YEAR 1600 +// This is the number of leap days between 1600 and 1970 +#define QC_LEAP_DAYS 89 #define DAYS_PER_400Y (365 * 400 + 97) #define DAYS_PER_100Y (365 * 100 + 24) #define DAYS_PER_4Y (365 * 4 + 1) -STATIC const uint16_t days_since_jan1[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; +static const uint16_t days_since_jan1[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + +// type used internally to count small integers relative to epoch +// (using uint when possible produces smaller code on some platforms) +#if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +typedef mp_int_t relint_t; +#else +typedef mp_uint_t relint_t; +#endif bool timeutils_is_leap_year(mp_uint_t year) { + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; + #else + return year % 4 == 0; + #endif } // month is one based @@ -65,67 +92,67 @@ mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) { return yday; } -void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_time_t *tm) { - // The following algorithm was adapted from musl's __secs_to_tm and adapted - // for differences in MicroPython's timebase. - - mp_int_t seconds = t - LEAPOCH; +void timeutils_seconds_since_1970_to_struct_time(timeutils_timestamp_t seconds, timeutils_struct_time_t *tm) { + // The following algorithm was inspired from musl's __secs_to_tm + // and simplified to reduce code footprint in the simple case - mp_int_t days = seconds / 86400; + relint_t days = seconds / 86400; seconds %= 86400; + #if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (seconds < 0) { seconds += 86400; days -= 1; } + #endif tm->tm_hour = seconds / 3600; tm->tm_min = seconds / 60 % 60; tm->tm_sec = seconds % 60; - mp_int_t wday = (days + 2) % 7; // Mar 1, 2000 was a Wednesday (2) + relint_t wday = (days + 3) % 7; // Jan 1, 1970 was a Thursday (3) + #if MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (wday < 0) { wday += 7; } + #endif tm->tm_wday = wday; - mp_int_t qc_cycles = days / DAYS_PER_400Y; + days += PREV_LEAP_DAY; + + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + // rebase day to the oldest supported date (=> always positive) + mp_uint_t base_year = QC_LEAP_YEAR; + days += QC_BASE_DAY; + mp_uint_t qc_cycles = days / DAYS_PER_400Y; days %= DAYS_PER_400Y; - if (days < 0) { - days += DAYS_PER_400Y; - qc_cycles--; - } - mp_int_t c_cycles = days / DAYS_PER_100Y; + mp_uint_t c_cycles = days / DAYS_PER_100Y; if (c_cycles == 4) { c_cycles--; } days -= (c_cycles * DAYS_PER_100Y); - - mp_int_t q_cycles = days / DAYS_PER_4Y; + #else + mp_uint_t base_year = PREV_LEAP_YEAR; + mp_uint_t qc_cycles = 0; + mp_uint_t c_cycles = 0; + #endif + + mp_uint_t q_cycles = days / DAYS_PER_4Y; + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE if (q_cycles == 25) { q_cycles--; } + #endif days -= q_cycles * DAYS_PER_4Y; - mp_int_t years = days / 365; + relint_t years = days / 365; if (years == 4) { years--; } days -= (years * 365); - /* We will compute tm_yday at the very end - mp_int_t leap = !years && (q_cycles || !c_cycles); - - tm->tm_yday = days + 31 + 28 + leap; - if (tm->tm_yday >= 365 + leap) { - tm->tm_yday -= 365 + leap; - } - - tm->tm_yday++; // Make one based - */ - - tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles; + tm->tm_year = base_year + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles; // Note: days_in_month[0] corresponds to March - STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29}; + static const uint8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29}; mp_int_t month; for (month = 0; days_in_month[month] <= days; month++) { @@ -144,21 +171,28 @@ void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, timeutils_struct_t } // returns the number of seconds, as an integer, since 2000-01-01 -mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, +timeutils_timestamp_t timeutils_seconds_since_1970(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { - return - second - + minute * 60 - + hour * 3600 - + (timeutils_year_day(year, month, date) - 1 - + ((year - 2000 + 3) / 4) // add a day each 4 years starting with 2001 - - ((year - 2000 + 99) / 100) // subtract a day each 100 years starting with 2001 - + ((year - 2000 + 399) / 400) // add a day each 400 years starting with 2001 - ) * 86400 - + (year - 2000) * 31536000; + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + mp_uint_t ref_year = QC_LEAP_YEAR; + #else + mp_uint_t ref_year = PREV_LEAP_YEAR; + #endif + timeutils_timestamp_t res; + res = ((relint_t)year - 1970) * 365; + res += (year - (ref_year + 1)) / 4; // add a day each 4 years + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + res -= (year - (ref_year + 1)) / 100; // subtract a day each 100 years + res += (year - (ref_year + 1)) / 400; // add a day each 400 years + res -= QC_LEAP_DAYS; + #endif + res += timeutils_year_day(year, month, date) - 1; + res *= 86400; + res += hour * 3600 + minute * 60 + second; + return res; } -mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, +timeutils_timestamp_t timeutils_mktime_1970(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { // Normalize the tuple. This allows things like: @@ -211,12 +245,16 @@ mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, year++; } } - return timeutils_seconds_since_2000(year, month, mday, hours, minutes, seconds); + return timeutils_seconds_since_1970(year, month, mday, hours, minutes, seconds); } // Calculate the weekday from the date. // The result is zero based with 0 = Monday. // by Michael Keith and Tom Craver, 1990. int timeutils_calc_weekday(int y, int m, int d) { - return ((d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) + 6) % 7; + return ((d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 + #if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE + - y / 100 + y / 400 + #endif + ) + 6) % 7; } diff --git a/shared/timeutils/timeutils.h b/shared/timeutils/timeutils.h index ebebfa8980167..35356b462aafc 100644 --- a/shared/timeutils/timeutils.h +++ b/shared/timeutils/timeutils.h @@ -27,12 +27,23 @@ #ifndef MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H #define MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H -// CIRCUITPY-CHANGE: MICROPY_EPOCH_IS_1970 -#include "mpconfigport.h" +#include "py/obj.h" +#if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE +#include // required for trunc() +#endif + +// `timeutils_timestamp_t` is the type used internally by timeutils to +// represent timestamps, and is always referenced to 1970. +// It may not match the platform-specific `mp_timestamp_t`. +#if MICROPY_TIME_SUPPORT_Y2100_AND_BEYOND || MICROPY_TIME_SUPPORT_Y1969_AND_BEFORE +typedef long long timeutils_timestamp_t; +#else +typedef mp_uint_t timeutils_timestamp_t; +#endif // The number of seconds between 1970/1/1 and 2000/1/1 is calculated using: // time.mktime((2000,1,1,0,0,0,0,0,0)) - time.mktime((1970,1,1,0,0,0,0,0,0)) -#define TIMEUTILS_SECONDS_1970_TO_2000 (946684800ULL) +#define TIMEUTILS_SECONDS_1970_TO_2000 (946684800LL) typedef struct _timeutils_struct_time_t { uint16_t tm_year; // i.e. 2014 @@ -48,62 +59,116 @@ typedef struct _timeutils_struct_time_t { bool timeutils_is_leap_year(mp_uint_t year); mp_uint_t timeutils_days_in_month(mp_uint_t year, mp_uint_t month); mp_uint_t timeutils_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date); +int timeutils_calc_weekday(int y, int m, int d); -void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t, +void timeutils_seconds_since_1970_to_struct_time(timeutils_timestamp_t t, timeutils_struct_time_t *tm); -mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +timeutils_timestamp_t timeutils_seconds_since_1970(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second); -mp_uint_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +timeutils_timestamp_t timeutils_mktime_1970(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds); +static inline mp_timestamp_t timeutils_obj_get_timestamp(mp_obj_t o_in) { + #if MICROPY_PY_BUILTINS_FLOAT && MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE + mp_float_t val = mp_obj_get_float(o_in); + return (mp_timestamp_t)MICROPY_FLOAT_C_FUN(trunc)(val); + #elif MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT + return mp_obj_get_uint(o_in); + #else + return mp_obj_get_ll(o_in); + #endif +} + +static inline mp_obj_t timeutils_obj_from_timestamp(mp_timestamp_t t) { + #if MICROPY_TIMESTAMP_IMPL == MICROPY_TIMESTAMP_IMPL_UINT + return mp_obj_new_int_from_uint(t); + #else + return mp_obj_new_int_from_ll(t); + #endif +} + +static inline void timeutils_seconds_since_2000_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_1970_to_struct_time((timeutils_timestamp_t)(t + TIMEUTILS_SECONDS_1970_TO_2000), tm); +} + +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return (mp_timestamp_t)timeutils_seconds_since_1970(year, month, date, hour, minute, second) - TIMEUTILS_SECONDS_1970_TO_2000; +} + +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +static inline mp_timestamp_t timeutils_mktime_2000(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return (mp_timestamp_t)timeutils_mktime_1970(year, month, mday, hours, minutes, seconds) - TIMEUTILS_SECONDS_1970_TO_2000; +} + + // Select the Epoch used by the port. #if MICROPY_EPOCH_IS_1970 -static inline void timeutils_seconds_since_epoch_to_struct_time(uint64_t t, timeutils_struct_time_t *tm) { - // TODO this will give incorrect results for dates before 2000/1/1 - return timeutils_seconds_since_2000_to_struct_time(t - TIMEUTILS_SECONDS_1970_TO_2000, tm); +static inline void timeutils_seconds_since_epoch_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_1970_to_struct_time(t, tm); +} + +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return timeutils_seconds_since_1970(year, month, date, hour, minute, second); } -static inline uint64_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { - return timeutils_mktime_2000(year, month, mday, hours, minutes, seconds) + TIMEUTILS_SECONDS_1970_TO_2000; +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +static inline mp_timestamp_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return timeutils_mktime_1970(year, month, mday, hours, minutes, seconds); } -static inline uint64_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, - mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { - // TODO this will give incorrect results for dates before 2000/1/1 - return timeutils_seconds_since_2000(year, month, date, hour, minute, second) + TIMEUTILS_SECONDS_1970_TO_2000; +static inline mp_timestamp_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(int64_t ns) { + return (mp_timestamp_t)(ns / 1000000000LL); } -static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) { - return ns / 1000000000ULL; +static inline int64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_timestamp_t s) { + return (int64_t)s * 1000000000LL; } -static inline uint64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(uint64_t ns) { +static inline int64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(int64_t ns) { return ns; } #else // Epoch is 2000 -#define timeutils_seconds_since_epoch_to_struct_time timeutils_seconds_since_2000_to_struct_time -#define timeutils_seconds_since_epoch timeutils_seconds_since_2000 -#define timeutils_mktime timeutils_mktime_2000 +static inline void timeutils_seconds_since_epoch_to_struct_time(mp_timestamp_t t, timeutils_struct_time_t *tm) { + timeutils_seconds_since_2000_to_struct_time(t, tm); +} + +// Year is absolute, month/date are 1-based, hour/minute/second are 0-based. +static inline mp_timestamp_t timeutils_seconds_since_epoch(mp_uint_t year, mp_uint_t month, mp_uint_t date, + mp_uint_t hour, mp_uint_t minute, mp_uint_t second) { + return timeutils_seconds_since_2000(year, month, date, hour, minute, second); +} + +// Year is absolute, month/mday are 1-based, hours/minutes/seconds are 0-based. +static inline mp_timestamp_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday, + mp_int_t hours, mp_int_t minutes, mp_int_t seconds) { + return timeutils_mktime_2000(year, month, mday, hours, minutes, seconds); +} -static inline uint64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_uint_t s) { - return ((uint64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000ULL; +static inline mp_timestamp_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(int64_t ns) { + return (mp_timestamp_t)(ns / 1000000000LL - TIMEUTILS_SECONDS_1970_TO_2000); } -static inline mp_uint_t timeutils_seconds_since_epoch_from_nanoseconds_since_1970(uint64_t ns) { - return ns / 1000000000ULL - TIMEUTILS_SECONDS_1970_TO_2000; +static inline int64_t timeutils_seconds_since_epoch_to_nanoseconds_since_1970(mp_timestamp_t s) { + return ((int64_t)s + TIMEUTILS_SECONDS_1970_TO_2000) * 1000000000LL; } static inline int64_t timeutils_nanoseconds_since_epoch_to_nanoseconds_since_1970(int64_t ns) { - return ns + TIMEUTILS_SECONDS_1970_TO_2000 * 1000000000ULL; + return ns + TIMEUTILS_SECONDS_1970_TO_2000 * 1000000000LL; } #endif -int timeutils_calc_weekday(int y, int m, int d); - #endif // MICROPY_INCLUDED_LIB_TIMEUTILS_TIMEUTILS_H diff --git a/shared/upytesthelper/upytesthelper.c b/shared/upytesthelper/upytesthelper.c deleted file mode 100644 index ba20037f7ac04..0000000000000 --- a/shared/upytesthelper/upytesthelper.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Linaro Limited - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include - -#include "py/mphal.h" -#include "py/gc.h" -#include "py/runtime.h" -#include "py/compile.h" -#include "upytesthelper.h" - -#if !MICROPY_PY_SYS_PATH -#error "upytesthelper requires MICROPY_PY_SYS_PATH=1" -#endif - -#if !MICROPY_PY_SYS_ARGV -#error "upytesthelper requires MICROPY_PY_SYS_ARGV=1" -#endif - -static const char *test_exp_output; -static int test_exp_output_len, test_rem_output_len; -static int test_failed; -static void *heap_start, *heap_end; - -void upytest_set_heap(void *start, void *end) { - heap_start = start; - heap_end = end; -} - -void upytest_set_expected_output(const char *output, unsigned len) { - test_exp_output = output; - test_exp_output_len = test_rem_output_len = len; - test_failed = false; -} - -bool upytest_is_failed(void) { - if (test_failed) { - return true; - } - #if 0 - if (test_rem_output_len != 0) { - printf("remaining len: %d\n", test_rem_output_len); - } - #endif - return test_rem_output_len != 0; -} - -// MP_PLAT_PRINT_STRN() should be redirected to this function. -// It will pass-through any content to mp_hal_stdout_tx_strn_cooked() -// (the default value of MP_PLAT_PRINT_STRN), but will also match -// it to the expected output as set by upytest_set_expected_output(). -// If mismatch happens, upytest_is_failed() returns true. -void upytest_output(const char *str, mp_uint_t len) { - if (!test_failed) { - if (len > test_rem_output_len) { - test_failed = true; - } else { - test_failed = memcmp(test_exp_output, str, len); - #if 0 - if (test_failed) { - printf("failed after char %u, within %d chars, res: %d\n", - test_exp_output_len - test_rem_output_len, (int)len, test_failed); - for (int i = 0; i < len; i++) { - if (str[i] != test_exp_output[i]) { - printf("%d %02x %02x\n", i, str[i], test_exp_output[i]); - } - } - } - #endif - test_exp_output += len; - test_rem_output_len -= len; - } - } - mp_hal_stdout_tx_strn_cooked(str, len); -} - -void upytest_execute_test(const char *src) { - // To provide clean room for each test, interpreter and heap are - // reinitialized before running each. - gc_init(heap_start, heap_end); - mp_init(); - mp_sys_path = mp_obj_new_list(0, NULL); - #if MICROPY_MODULE_FROZEN - mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__dot_frozen)); - #endif - mp_obj_list_init(mp_sys_argv, 0); - - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); - qstr source_name = lex->source_name; - mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, false); - mp_call_function_0(module_fun); - nlr_pop(); - } else { - mp_obj_t exc = (mp_obj_t)nlr.ret_val; - if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { - // Assume that sys.exit() is called to skip the test. - // TODO: That can be always true, we should set up convention to - // use specific exit code as skip indicator. - tinytest_set_test_skipped_(); - goto end; - } - mp_obj_print_exception(&mp_plat_print, exc); - tt_abort_msg("Uncaught exception\n"); - } - - if (upytest_is_failed()) { - tinytest_set_test_failed_(); - } - -end: - mp_deinit(); -} diff --git a/shared/upytesthelper/upytesthelper.h b/shared/upytesthelper/upytesthelper.h deleted file mode 100644 index 3a292befd7757..0000000000000 --- a/shared/upytesthelper/upytesthelper.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Linaro Limited - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include "py/mpconfig.h" -#include "lib/tinytest/tinytest.h" -#include "lib/tinytest/tinytest_macros.h" - -void upytest_set_heap(void *start, void *end); -void upytest_set_expected_output(const char *output, unsigned len); -void upytest_execute_test(const char *src); -void upytest_output(const char *str, mp_uint_t len); -bool upytest_is_failed(void); diff --git a/stubs/micropython/__init__.pyi b/stubs/micropython/__init__.pyi new file mode 100644 index 0000000000000..1bcde6ae81354 --- /dev/null +++ b/stubs/micropython/__init__.pyi @@ -0,0 +1,20 @@ +"""Access and control MicroPython internals""" + +def const[T](expr: T) -> T: + """Used to declare that the expression is a constant so that the compiler + can optimise it. The use of this function should be as follows:: + + from micropython import const + + CONST_X = const(123) + CONST_Y = const(2 * CONST_X + 1) + + Constants declared this way are still accessible as global variables from + outside the module they are declared in. On the other hand, if a constant + begins with an underscore then it is hidden, it is not available as a global + variable, and does not take up any memory during execution. + + This `const` function is recognised directly by the MicroPython parser and is + provided as part of the :mod:`micropython` module mainly so that scripts can be + written which run under both CPython and MicroPython, by following the above + pattern.""" diff --git a/supervisor/filesystem.h b/supervisor/filesystem.h index a0445b0510da9..30cd83d443815 100644 --- a/supervisor/filesystem.h +++ b/supervisor/filesystem.h @@ -21,6 +21,7 @@ void filesystem_set_internal_writable_by_usb(bool usb_writable); void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection); void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable); void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection); +void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection); // Whether user code can modify the filesystem. It doesn't depend on the state // of USB. Don't use this for a workflow. In workflows, grab the shared file diff --git a/supervisor/linker.h b/supervisor/linker.h index 5b6895d5b492c..6f05d93bb69d6 100644 --- a/supervisor/linker.h +++ b/supervisor/linker.h @@ -8,11 +8,16 @@ #pragma once -#if defined(IMXRT1XXX) || defined(FOMU) || defined(STM32H7) || defined(RASPBERRYPI) +#if !defined(__ZEPHYR__) && (defined(IMXRT1XXX) || defined(FOMU) || defined(RASPBERRYPI)) #define PLACE_IN_DTCM_DATA(name) name __attribute__((section(".dtcm_data." #name))) #define PLACE_IN_DTCM_BSS(name) name __attribute__((section(".dtcm_bss." #name))) // Don't inline ITCM functions because that may pull them out of ITCM into other sections. #define PLACE_IN_ITCM(name) __attribute__((section(".itcm." #name), noinline, aligned(4))) name +#elif !defined(__ZEPHYR__) && defined(STM32H7) +#define PLACE_IN_DTCM_DATA(name) name __attribute__((section(".dtcm_data." #name))) +#define PLACE_IN_DTCM_BSS(name) name __attribute__((section(".dtcm_bss." #name))) +// using ITCM on the H7 generates hard fault exception +#define PLACE_IN_ITCM(name) name #else #define PLACE_IN_DTCM_DATA(name) name #define PLACE_IN_DTCM_BSS(name) name diff --git a/supervisor/port.h b/supervisor/port.h index 29c071515c133..f0e13e167cce1 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -9,6 +9,7 @@ #include #include +#include "py/obj.h" #include "supervisor/shared/safe_mode.h" // Provided by the linker; @@ -23,13 +24,13 @@ extern uint32_t _ebss; safe_mode_t port_init(void); // Reset the microcontroller completely. -void reset_cpu(void) NORETURN; +void reset_cpu(void) MP_NORETURN; // Reset the microcontroller state. void reset_port(void); // Reset to the bootloader -void reset_to_bootloader(void) NORETURN; +void reset_to_bootloader(void) MP_NORETURN; // Get stack limit address uint32_t *port_stack_get_limit(void); @@ -91,15 +92,17 @@ void port_wake_main_task(void); void port_wake_main_task_from_isr(void); // Some ports may use real RTOS tasks besides the background task framework of -// CircuitPython. Calling this will yield to other tasks and then return to the -// CircuitPython task when others are done. -void port_yield(void); - -// Some ports need special handling just after completing boot.py execution. -// This function is called once while boot.py's VM is still valid, and -// then a second time after the VM is finalized. -// A default weak implementation is provided that does nothing. -void port_post_boot_py(bool heap_valid); +// CircuitPython. Calling this will yield to other tasks at the same priority level +// (or higher priority level if pre-emption is not immediate in the RTOS) +// and then return to the CircuitPython task when others are done. +// Note that this does NOT yield to lower priority tasks. Use port_task_sleep_ms() instead. +void port_task_yield(void); + +// On ports using real RTOS tasks, yield to other tasks for at least msecs. +// This will allow lower priority tasks to run. +// On non-RTOS implementations, this just sleeps for msecs and will run CircuitPython +// background tasks. +void port_task_sleep_ms(uint32_t msecs); // Some ports want to add information to boot_out.txt. // A default weak implementation is provided that does nothing. @@ -108,3 +111,20 @@ void port_boot_info(void); // Some ports want to mark additional pointers as gc roots. // A default weak implementation is provided that does nothing. void port_gc_collect(void); + +// Most ports that implement CIRCUITPY_BOOT_BUTTON use a generic version of +// this function to sense the button. Ports that need to can override this +// function to provide their own implementation. +bool port_boot_button_pressed(void); + +// Allocating objects on the port heap, not the VM heap. +#define mp_obj_port_malloc(struct_type, obj_type) ((struct_type *)mp_obj_port_malloc_helper(sizeof(struct_type), obj_type)) +#define mp_obj_port_malloc_var(struct_type, var_field, var_type, var_num, obj_type) ((struct_type *)mp_obj_port_malloc_helper(offsetof(struct_type, var_field) + sizeof(var_type) * (var_num), obj_type)) + +void *mp_obj_port_malloc_helper(size_t num_bytes, const mp_obj_type_t *type); +mp_obj_t mp_obj_new_port_tuple(size_t n, const mp_obj_t *items); + +// Safely free an object that may have been allocated from either the GC heap or port heap. +// If the pointer is on the GC heap, it will be freed by the GC automatically. +// If the pointer is not on the GC heap, it will be freed with port_free. +void circuitpy_free_obj(mp_obj_t obj); diff --git a/supervisor/port_heap.h b/supervisor/port_heap.h index f035cc2409e70..3e6b5a660fa79 100644 --- a/supervisor/port_heap.h +++ b/supervisor/port_heap.h @@ -21,9 +21,16 @@ void port_heap_init(void); void *port_malloc(size_t size, bool dma_capable); +void *port_malloc_zero(size_t size, bool dma_capable); void port_free(void *ptr); -void *port_realloc(void *ptr, size_t size); +void *port_realloc(void *ptr, size_t size, bool dma_capable); + +#if !CIRCUITPY_ALL_MEMORY_DMA_CAPABLE +// Check if a buffer pointer is in DMA-capable memory. DMA-capable memory is also accessible during +// flash operations. +bool port_buffer_is_dma_capable(const void *ptr); +#endif size_t port_heap_get_largest_free_size(void); diff --git a/supervisor/shared/background_callback.c b/supervisor/shared/background_callback.c index 309210b7a12ae..ffeb78bbb8371 100644 --- a/supervisor/shared/background_callback.c +++ b/supervisor/shared/background_callback.c @@ -58,7 +58,7 @@ inline bool background_callback_pending(void) { static int background_prevention_count; -void PLACE_IN_ITCM(background_callback_run_all)() { +void PLACE_IN_ITCM(background_callback_run_all)(void) { port_background_task(); if (!background_callback_pending()) { return; @@ -89,13 +89,13 @@ void PLACE_IN_ITCM(background_callback_run_all)() { CALLBACK_CRITICAL_END; } -void background_callback_prevent() { +void background_callback_prevent(void) { CALLBACK_CRITICAL_BEGIN; ++background_prevention_count; CALLBACK_CRITICAL_END; } -void background_callback_allow() { +void background_callback_allow(void) { CALLBACK_CRITICAL_BEGIN; --background_prevention_count; CALLBACK_CRITICAL_END; @@ -103,7 +103,7 @@ void background_callback_allow() { // Filter out queued callbacks if they are allocated on the heap. -void background_callback_reset() { +void background_callback_reset(void) { background_callback_t *new_head = NULL; background_callback_t **previous_next = &new_head; background_callback_t *new_tail = NULL; diff --git a/supervisor/shared/bluetooth/bluetooth.c b/supervisor/shared/bluetooth/bluetooth.c index 68b43871ce161..cccb371fc4dd2 100644 --- a/supervisor/shared/bluetooth/bluetooth.c +++ b/supervisor/shared/bluetooth/bluetooth.c @@ -10,16 +10,13 @@ #include "shared-bindings/_bleio/__init__.h" #include "shared-bindings/_bleio/Adapter.h" -#if defined(CIRCUITPY_BOOT_BUTTON) -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/time/__init__.h" -#endif #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" #include "shared-module/storage/__init__.h" #include "common-hal/_bleio/__init__.h" +#include "supervisor/port.h" #include "supervisor/shared/serial.h" #include "supervisor/shared/status_leds.h" #include "supervisor/shared/tick.h" @@ -39,8 +36,8 @@ #include "supervisor/shared/status_bar.h" #endif -#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV -#include "shared-module/os/__init__.h" +#if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" #endif @@ -192,6 +189,7 @@ void supervisor_bluetooth_init(void) { boot_in_discovery_mode = false; if (reset_reason != RESET_REASON_POWER_ON && reset_reason != RESET_REASON_RESET_PIN && + reset_reason != RESET_REASON_DEEP_SLEEP_ALARM && reset_reason != RESET_REASON_UNKNOWN && reset_reason != RESET_REASON_SOFTWARE) { return; @@ -218,18 +216,18 @@ void supervisor_bluetooth_init(void) { // Checking here allows us to have the status LED solidly on even if no button was // pressed. bool wifi_workflow_active = false; - #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_SETTINGS_TOML char _api_password[64]; const size_t api_password_len = sizeof(_api_password) - 1; - os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); - wifi_workflow_active = result == GETENV_OK; + settings_err_t result = settings_get_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + wifi_workflow_active = result == SETTINGS_OK; #endif if (!bonded && !wifi_workflow_active) { boot_in_discovery_mode = true; } #endif while (diff < 1000) { - #ifdef CIRCUITPY_STATUS_LED + #if CIRCUITPY_STATUS_LED // Blink on for 50 and off for 100 bool led_on = boot_in_discovery_mode || (diff % 150) <= 50; if (led_on) { @@ -238,18 +236,10 @@ void supervisor_bluetooth_init(void) { new_status_color(BLACK); } #endif - // Init the boot button every time in case it is used for LEDs. - #ifdef CIRCUITPY_BOOT_BUTTON - digitalio_digitalinout_obj_t boot_button; - common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); - common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); - common_hal_time_delay_ms(1); - bool button_pressed = !common_hal_digitalio_digitalinout_get_value(&boot_button); - common_hal_digitalio_digitalinout_deinit(&boot_button); - if (button_pressed) { + if (port_boot_button_pressed()) { boot_in_discovery_mode = true; + break; } - #endif diff = supervisor_ticks_ms64() - start_ticks; } if (boot_in_discovery_mode) { @@ -339,6 +329,10 @@ void supervisor_stop_bluetooth(void) { ble_started = false; + #if CIRCUITPY_BLE_FILE_SERVICE + supervisor_stop_bluetooth_file_transfer(); + #endif + #if CIRCUITPY_SERIAL_BLE supervisor_stop_bluetooth_serial(); #endif diff --git a/supervisor/shared/bluetooth/file_transfer.c b/supervisor/shared/bluetooth/file_transfer.c index aa49c0a899a80..66eccf8cbf2c8 100644 --- a/supervisor/shared/bluetooth/file_transfer.c +++ b/supervisor/shared/bluetooth/file_transfer.c @@ -101,6 +101,13 @@ void supervisor_start_bluetooth_file_transfer(void) { &static_handler_entry); } +void supervisor_stop_bluetooth_file_transfer(void) { + common_hal_bleio_packet_buffer_deinit(&_transfer_packet_buffer); + common_hal_bleio_characteristic_deinit(&supervisor_ble_transfer_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_version_characteristic); + common_hal_bleio_service_deinit(&supervisor_ble_service); +} + #define COMMAND_SIZE 1024 #define ANY_COMMAND 0x00 diff --git a/supervisor/shared/bluetooth/file_transfer.h b/supervisor/shared/bluetooth/file_transfer.h index 12c75e1f548c7..8d4fc9c66848e 100644 --- a/supervisor/shared/bluetooth/file_transfer.h +++ b/supervisor/shared/bluetooth/file_transfer.h @@ -8,6 +8,8 @@ #include -void supervisor_bluetooth_file_transfer_background(void); void supervisor_start_bluetooth_file_transfer(void); +void supervisor_stop_bluetooth_file_transfer(void); + +void supervisor_bluetooth_file_transfer_background(void); void supervisor_bluetooth_file_transfer_disconnected(void); diff --git a/supervisor/shared/bluetooth/serial.c b/supervisor/shared/bluetooth/serial.c index 3c8ae71eb4828..86ff1738a2a85 100644 --- a/supervisor/shared/bluetooth/serial.c +++ b/supervisor/shared/bluetooth/serial.c @@ -148,10 +148,15 @@ void supervisor_stop_bluetooth_serial(void) { return; } common_hal_bleio_packet_buffer_flush(&_tx_packet_buffer); + common_hal_bleio_packet_buffer_deinit(&_tx_packet_buffer); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_rx_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_tx_characteristic); + common_hal_bleio_characteristic_deinit(&supervisor_ble_circuitpython_version_characteristic); + common_hal_bleio_service_deinit(&supervisor_ble_circuitpython_service); } bool ble_serial_connected(void) { - return _tx_packet_buffer.conn_handle != BLEIO_HANDLE_INVALID; + return common_hal_bleio_packet_buffer_connected(&_tx_packet_buffer); } uint32_t ble_serial_available(void) { diff --git a/supervisor/shared/display.c b/supervisor/shared/display.c index f6788af0a8db4..1352c76b0066a 100644 --- a/supervisor/shared/display.c +++ b/supervisor/shared/display.c @@ -7,8 +7,10 @@ #include "supervisor/shared/display.h" #include +#include "supervisor/port.h" #include "py/mpstate.h" +#include "py/gc.h" #include "shared-bindings/displayio/Bitmap.h" #include "shared-bindings/displayio/Group.h" #include "shared-bindings/displayio/Palette.h" @@ -36,6 +38,82 @@ #if CIRCUITPY_TERMINALIO #include "supervisor/port.h" + +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" +#endif + +#if CIRCUITPY_LVFONTIO +#include "shared-bindings/lvfontio/OnDiskFont.h" +#include "supervisor/filesystem.h" +#include "extmod/vfs_fat.h" +#include "lib/oofatfs/ff.h" + +#include "supervisor/shared/serial.h" + +// Check if a custom font file exists and return its path if found +// Returns true if font file exists, false otherwise +static bool check_for_custom_font(const char **font_path_out) { + if (!filesystem_present()) { + return false; + } + + fs_user_mount_t *vfs = filesystem_circuitpy(); + if (vfs == NULL) { + return false; + } + + // Use FATFS directly to check if file exists + FILINFO file_info; + const char *default_font_path = "/fonts/terminal.lvfontbin"; + const char *font_path = default_font_path; + + #if CIRCUITPY_SETTINGS_TOML + // Buffer for storing custom font path + static char custom_font_path[128]; + if (settings_get_str("CIRCUITPY_TERMINAL_FONT", custom_font_path, sizeof(custom_font_path)) == SETTINGS_OK) { + // Use custom font path from environment variable + font_path = custom_font_path; + } + #endif + + FRESULT result = f_stat(&vfs->fatfs, font_path, &file_info); + if (result == FR_OK) { + if (font_path_out != NULL) { + *font_path_out = font_path; + } + return true; + } + + // If custom font path doesn't exist, use default font + font_path = default_font_path; + result = f_stat(&vfs->fatfs, font_path, &file_info); + + if (result == FR_OK) { + if (font_path_out != NULL) { + *font_path_out = font_path; + } + return true; + } + + return false; +} + +// Initialize a BuiltinFont object with the specified font file and max_slots +// Returns true on success, false on failure +static bool init_lvfont(lvfontio_ondiskfont_t *font, const char *font_path, uint16_t max_slots) { + if (font == NULL) { + return false; + } + + font->base.type = &lvfontio_ondiskfont_type; + + // Pass false for use_gc_allocator during startup when garbage collector isn't fully initialized + common_hal_lvfontio_ondiskfont_construct(font, font_path, max_slots, false); + + return !common_hal_lvfontio_ondiskfont_deinited(font); +} +#endif #endif #if CIRCUITPY_REPL_LOGO @@ -49,26 +127,66 @@ static uint8_t *tilegrid_tiles = NULL; static size_t tilegrid_tiles_size = 0; #endif +#if CIRCUITPY_LVFONTIO && CIRCUITPY_TERMINALIO +static lvfontio_ondiskfont_t *lvfont = NULL; +#endif + void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { if (supervisor_terminal_started()) { return; } + + #if CIRCUITPY_TERMINALIO // Default the scale to 2 because we may show blinka without the terminal for // languages that don't have font support. - uint8_t scale = 2; + mp_int_t scale = 2; - #if CIRCUITPY_TERMINALIO displayio_tilegrid_t *scroll_area = &supervisor_terminal_scroll_area_text_grid; displayio_tilegrid_t *status_bar = &supervisor_terminal_status_bar_text_grid; - bool reset_tiles = false; - uint16_t width_in_tiles = width_px / scroll_area->tile_width; + bool reset_tiles = tilegrid_tiles == NULL; + + uint16_t glyph_width = 0; + uint16_t glyph_height = 0; + + #if CIRCUITPY_LVFONTIO + // Check if we have a custom terminal font in the filesystem + bool use_lv_font = false; + const char *font_path = NULL; + + if (check_for_custom_font(&font_path)) { + // Initialize a temporary font just to get dimensions + lvfontio_ondiskfont_t temp_font; + if (init_lvfont(&temp_font, font_path, 1)) { + // Get the font dimensions + common_hal_lvfontio_ondiskfont_get_dimensions(&temp_font, &glyph_width, &glyph_height); + + // Clean up the temp font - we'll create a proper one later + common_hal_lvfontio_ondiskfont_deinit(&temp_font); + use_lv_font = true; + reset_tiles = true; + // TODO: We may want to detect when the files modified time hasn't changed. + } + } + #endif + #if CIRCUITPY_FONTIO + if (glyph_width == 0) { + glyph_width = supervisor_terminal_font.width; + glyph_height = supervisor_terminal_font.height; + } + #endif + + uint16_t width_in_tiles = width_px / glyph_width; + // determine scale based on width - if (width_in_tiles <= 80) { + if (width_in_tiles <= 120) { scale = 1; } + #if CIRCUITPY_SETTINGS_TOML + (void)settings_get_int("CIRCUITPY_TERMINAL_SCALE", &scale); + #endif - width_in_tiles = MAX(1, width_px / (scroll_area->tile_width * scale)); - uint16_t height_in_tiles = MAX(2, height_px / (scroll_area->tile_height * scale)); + width_in_tiles = MAX(1, width_px / (glyph_width * scale)); + uint16_t height_in_tiles = MAX(2, height_px / (glyph_height * scale)); uint16_t total_tiles = width_in_tiles * height_in_tiles; @@ -77,69 +195,121 @@ void supervisor_start_terminal(uint16_t width_px, uint16_t height_px) { (scroll_area->height_in_tiles != height_in_tiles - 1)) { reset_tiles = true; } - // Reuse the previous allocation if possible - if (tilegrid_tiles) { - if (tilegrid_tiles_size != total_tiles) { + + circuitpython_splash.scale = scale; + if (!reset_tiles) { + return; + } + + // Adjust the display dimensions to account for scale of the outer group. + width_px /= scale; + height_px /= scale; + + // Number of tiles from the left edge to inset the status bar. + size_t min_left_padding = 0; + status_bar->tile_width = glyph_width; + status_bar->tile_height = glyph_height; + #if CIRCUITPY_REPL_LOGO + // Blinka + 1 px padding minimum + min_left_padding = supervisor_blinka_sprite.pixel_width + 1; + // Align the status bar to the bottom of the logo. + status_bar->y = supervisor_blinka_sprite.pixel_height - status_bar->tile_height; + #else + status_bar->y = 0; + #endif + status_bar->width_in_tiles = (width_px - min_left_padding) / status_bar->tile_width; + status_bar->height_in_tiles = 1; + status_bar->pixel_width = status_bar->width_in_tiles * status_bar->tile_width; + status_bar->pixel_height = status_bar->tile_height; + // Right align the status bar. + status_bar->x = width_px - status_bar->pixel_width; + status_bar->top_left_y = 0; + status_bar->full_change = true; + + scroll_area->tile_width = glyph_width; + scroll_area->tile_height = glyph_height; + scroll_area->width_in_tiles = width_in_tiles; + // Leave space for the status bar, no matter if we have logo or not. + scroll_area->height_in_tiles = height_in_tiles - 1; + scroll_area->pixel_width = scroll_area->width_in_tiles * scroll_area->tile_width; + scroll_area->pixel_height = scroll_area->height_in_tiles * scroll_area->tile_height; + // Right align the scroll area to give margin to the start of each line. + scroll_area->x = width_px - scroll_area->pixel_width; + scroll_area->top_left_y = 0; + // Align the scroll area to the bottom so that the newest line isn't cutoff. The top line + // may be clipped by the status bar and that's ok. + scroll_area->y = height_px - scroll_area->pixel_height; + scroll_area->full_change = true; + + mp_obj_t new_bitmap = mp_const_none; + mp_obj_t new_font = mp_const_none; + + #if CIRCUITPY_LVFONTIO + if (lvfont != NULL) { + common_hal_lvfontio_ondiskfont_deinit(lvfont); + // This will also free internal buffers that may change size. + port_free(lvfont); + lvfont = NULL; + } + + if (use_lv_font) { + // We found a custom terminal font file, use it instead of the built-in font + + lvfont = port_malloc(sizeof(lvfontio_ondiskfont_t), false); + if (lvfont != NULL) { + // Use the number of tiles in the terminal and status bar for the number of slots + // This ensures we have enough slots to display all characters that could appear on screen + uint16_t num_slots = width_in_tiles * height_in_tiles; + + // Initialize the font with our helper function + if (init_lvfont(lvfont, font_path, num_slots)) { + // Get the bitmap from the font + new_bitmap = common_hal_lvfontio_ondiskfont_get_bitmap(lvfont); + new_font = MP_OBJ_FROM_PTR(lvfont); + } else { + // If font initialization failed, free the memory and fall back to built-in font + port_free(lvfont); + lvfont = NULL; + use_lv_font = false; + } + } + } + #endif + #if CIRCUITPY_FONTIO + if (new_font == mp_const_none) { + new_bitmap = MP_OBJ_FROM_PTR(supervisor_terminal_font.bitmap); + new_font = MP_OBJ_FROM_PTR(&supervisor_terminal_font); + } + #endif + + if (new_font != mp_const_none) { + size_t total_values = common_hal_displayio_bitmap_get_width(new_bitmap) / glyph_width; + if (tilegrid_tiles) { port_free(tilegrid_tiles); tilegrid_tiles = NULL; - tilegrid_tiles_size = 0; - reset_tiles = true; } - } - if (!tilegrid_tiles) { - tilegrid_tiles = port_malloc(total_tiles, false); - reset_tiles = true; + size_t bytes_per_tile = 1; + if (total_tiles > 255) { + // Two bytes per tile. + bytes_per_tile = 2; + } + tilegrid_tiles = port_malloc(total_tiles * bytes_per_tile, false); if (!tilegrid_tiles) { return; } - } - - if (reset_tiles) { - // Adjust the display dimensions to account for scale of the outer group. - width_px /= scale; - height_px /= scale; - - // Number of tiles from the left edge to inset the status bar. - size_t min_left_padding = 0; - #if CIRCUITPY_REPL_LOGO - // Blinka + 1 px padding minimum - min_left_padding = supervisor_blinka_sprite.pixel_width + 1; - // Align the status bar to the bottom of the logo. - status_bar->y = supervisor_blinka_sprite.pixel_height - status_bar->tile_height; - #else - status_bar->y = 0; - #endif - status_bar->width_in_tiles = (width_px - min_left_padding) / status_bar->tile_width; - status_bar->height_in_tiles = 1; - status_bar->pixel_width = status_bar->width_in_tiles * status_bar->tile_width; - status_bar->pixel_height = status_bar->tile_height; - // Right align the status bar. - status_bar->x = width_px - status_bar->pixel_width; - status_bar->top_left_y = 0; status_bar->tiles = tilegrid_tiles; - status_bar->full_change = true; - - scroll_area->width_in_tiles = width_in_tiles; - // Leave space for the status bar, no matter if we have logo or not. - scroll_area->height_in_tiles = height_in_tiles - 1; - scroll_area->pixel_width = scroll_area->width_in_tiles * scroll_area->tile_width; - scroll_area->pixel_height = scroll_area->height_in_tiles * scroll_area->tile_height; - // Right align the scroll area to give margin to the start of each line. - scroll_area->x = width_px - scroll_area->pixel_width; - scroll_area->top_left_y = 0; - // Align the scroll area to the bottom so that the newest line isn't cutoff. The top line - // may be clipped by the status bar and that's ok. - scroll_area->y = height_px - scroll_area->pixel_height; - scroll_area->tiles = tilegrid_tiles + width_in_tiles; - scroll_area->full_change = true; - - common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, &supervisor_terminal_font, status_bar); - - // Do not update status bar until after boot.py has run, in case it is disabled. + status_bar->tiles_in_bitmap = total_values; + status_bar->bitmap_width_in_tiles = total_values; + scroll_area->tiles = tilegrid_tiles + width_in_tiles * bytes_per_tile; + scroll_area->tiles_in_bitmap = total_values; + scroll_area->bitmap_width_in_tiles = total_values; + + common_hal_displayio_tilegrid_set_bitmap(scroll_area, new_bitmap); + common_hal_displayio_tilegrid_set_bitmap(status_bar, new_bitmap); + common_hal_terminalio_terminal_construct(&supervisor_terminal, scroll_area, + new_font, status_bar); } #endif - - circuitpython_splash.scale = scale; } void supervisor_stop_terminal(void) { diff --git a/supervisor/shared/external_flash/common_commands.h b/supervisor/shared/external_flash/common_commands.h index 539f679d766e4..f2853e6b509b6 100644 --- a/supervisor/shared/external_flash/common_commands.h +++ b/supervisor/shared/external_flash/common_commands.h @@ -23,3 +23,4 @@ #define CMD_ENABLE_RESET 0x66 #define CMD_RESET 0x99 #define CMD_WAKE 0xab +#define CMD_GLOBAL_BLOCK_PROTECTION_UNLOCK 0x98 diff --git a/supervisor/shared/external_flash/device.h b/supervisor/shared/external_flash/device.h index 869f7b7a24439..d35a84d9c325c 100644 --- a/supervisor/shared/external_flash/device.h +++ b/supervisor/shared/external_flash/device.h @@ -24,8 +24,12 @@ typedef struct { // status register. uint8_t quad_enable_bit_mask; + // Device has sector-level write protection bool has_sector_protection : 1; + // Device uses global block protection lock instead of status register bits to enable sector writes + bool use_global_block_protection_lock : 1; + // Supports the 0x0b fast read command with 8 dummy cycles. bool supports_fast_read : 1; diff --git a/supervisor/shared/external_flash/devices.h.jinja b/supervisor/shared/external_flash/devices.h.jinja index 3859559d2b35d..3d24b674fed1e 100644 --- a/supervisor/shared/external_flash/devices.h.jinja +++ b/supervisor/shared/external_flash/devices.h.jinja @@ -17,6 +17,7 @@ .max_clock_speed_mhz = {{ device.max_clock_speed_mhz }}, \ .quad_enable_bit_mask = {{ device.quad_enable_bit_mask }}, \ .has_sector_protection = {{ device.has_sector_protection | lower() }}, \ + .use_global_block_protection_lock = {{ device.use_global_block_protection_lock | lower() }}, \ .supports_fast_read = {{ device.supports_fast_read | lower() }}, \ .supports_qspi = {{ device["6b_quad_read"] | lower() }}, \ .supports_qspi_writes = {{ device["32_qspi_write"] | lower() }}, \ diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index b029286fa418e..abf232c0d18c6 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -268,8 +268,12 @@ void supervisor_flash_init(void) { write_enable(); // Turn off sector protection - uint8_t data[1] = {0x00}; - spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, data, 1); + if (flash_device->use_global_block_protection_lock) { + spi_flash_command(CMD_GLOBAL_BLOCK_PROTECTION_UNLOCK); + } else { + uint8_t data[1] = {0x00}; + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, data, 1); + } } // Turn off writes in case this is a microcontroller only reset. diff --git a/supervisor/shared/filesystem.c b/supervisor/shared/filesystem.c index e5edb148e4145..eb4b6548d11ff 100644 --- a/supervisor/shared/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -15,8 +15,17 @@ #include "supervisor/flash.h" #include "supervisor/linker.h" -static mp_vfs_mount_t _mp_vfs; -static fs_user_mount_t _internal_vfs; +#if CIRCUITPY_SDCARDIO +#include "shared-module/sdcardio/__init__.h" +#endif + +static mp_vfs_mount_t _circuitpy_vfs; +static fs_user_mount_t _circuitpy_usermount; + +#if CIRCUITPY_SAVES_PARTITION_SIZE > 0 +static mp_vfs_mount_t _saves_vfs; +static fs_user_mount_t _saves_usermount; +#endif static volatile uint32_t filesystem_flush_interval_ms = CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS; volatile bool filesystem_flush_requested = false; @@ -73,15 +82,29 @@ static void make_file_with_contents(FATFS *fatfs, const char *filename, const by // want it to be executed without using stack within main() function bool filesystem_init(bool create_allowed, bool force_create) { // init the vfs object - fs_user_mount_t *vfs_fat = &_internal_vfs; - vfs_fat->blockdev.flags = 0; - supervisor_flash_init_vfs(vfs_fat); + fs_user_mount_t *circuitpy = &_circuitpy_usermount; + circuitpy->blockdev.flags = 0; + supervisor_flash_init_vfs(circuitpy); + + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + // SAVES is placed before CIRCUITPY so that CIRCUITPY takes up the remaining space. + circuitpy->blockdev.offset = CIRCUITPY_SAVES_PARTITION_SIZE; + circuitpy->blockdev.size = -1; + + fs_user_mount_t *saves = &_saves_usermount; + saves->blockdev.flags = 0; + saves->blockdev.offset = 0; + saves->blockdev.size = CIRCUITPY_SAVES_PARTITION_SIZE; + supervisor_flash_init_vfs(saves); + filesystem_set_concurrent_write_protection(saves, true); + filesystem_set_writable_by_usb(saves, false); + #endif - mp_vfs_mount_t *vfs = &_mp_vfs; - vfs->len = 0; + mp_vfs_mount_t *circuitpy_vfs = &_circuitpy_vfs; + circuitpy_vfs->len = 0; // try to mount the flash - FRESULT res = f_mount(&vfs_fat->fatfs); + FRESULT res = f_mount(&circuitpy->fatfs); if ((res == FR_NO_FILESYSTEM && create_allowed) || force_create) { // No filesystem so create a fresh one, or reformat has been requested. uint8_t working_buf[FF_MAX_SS]; @@ -89,7 +112,7 @@ bool filesystem_init(bool create_allowed, bool force_create) { #if FF_FS_EXFAT formats |= FM_EXFAT | FM_FAT32; #endif - res = f_mkfs(&vfs_fat->fatfs, formats, 0, working_buf, sizeof(working_buf)); + res = f_mkfs(&circuitpy->fatfs, formats, 0, working_buf, sizeof(working_buf)); if (res != FR_OK) { return false; } @@ -98,9 +121,9 @@ bool filesystem_init(bool create_allowed, bool force_create) { // set label #ifdef CIRCUITPY_DRIVE_LABEL - res = f_setlabel(&vfs_fat->fatfs, CIRCUITPY_DRIVE_LABEL); + res = f_setlabel(&circuitpy->fatfs, CIRCUITPY_DRIVE_LABEL); #else - res = f_setlabel(&vfs_fat->fatfs, "CIRCUITPY"); + res = f_setlabel(&circuitpy->fatfs, "CIRCUITPY"); #endif if (res != FR_OK) { return false; @@ -108,36 +131,55 @@ bool filesystem_init(bool create_allowed, bool force_create) { #if CIRCUITPY_USB_DEVICE // inhibit file indexing on MacOS - res = f_mkdir(&vfs_fat->fatfs, "/.fseventsd"); + res = f_mkdir(&circuitpy->fatfs, "/.fseventsd"); if (res != FR_OK) { return false; } - make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); - make_empty_file(&vfs_fat->fatfs, "/.metadata_never_index"); + make_empty_file(&circuitpy->fatfs, "/.fseventsd/no_log"); + make_empty_file(&circuitpy->fatfs, "/.metadata_never_index"); // Prevent storing trash on all OSes. - make_empty_file(&vfs_fat->fatfs, "/.Trashes"); // MacOS - make_empty_file(&vfs_fat->fatfs, "/.Trash-1000"); // Linux, XDG trash spec: + make_empty_file(&circuitpy->fatfs, "/.Trashes"); // MacOS + make_empty_file(&circuitpy->fatfs, "/.Trash-1000"); // Linux, XDG trash spec: // https://specifications.freedesktop.org/trash-spec/trashspec-latest.html #endif #if CIRCUITPY_SDCARDIO || CIRCUITPY_SDIOIO - res = f_mkdir(&vfs_fat->fatfs, "/sd"); + res = f_mkdir(&circuitpy->fatfs, "/sd"); + #if CIRCUITPY_FULL_BUILD + MAKE_FILE_WITH_OPTIONAL_CONTENTS(&circuitpy->fatfs, "/sd/placeholder.txt", + "SD cards mounted at /sd will hide this file from Python.\n"); + #endif + #endif + + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + res = f_mkfs(&saves->fatfs, formats, 0, working_buf, sizeof(working_buf)); + if (res == FR_OK) { + // Flush the new file system to make sure it's repaired immediately. + supervisor_flash_flush(); + res = f_setlabel(&saves->fatfs, "CPSAVES"); + } + + if (res == FR_OK) { + res = f_mkdir(&circuitpy->fatfs, "/saves"); + } #if CIRCUITPY_FULL_BUILD - MAKE_FILE_WITH_OPTIONAL_CONTENTS(&vfs_fat->fatfs, "/sd/placeholder.txt", - "SD cards mounted at /sd will hide this file from Python." - " SD cards are not visible via USB CIRCUITPY.\n"); + if (res == FR_OK) { + MAKE_FILE_WITH_OPTIONAL_CONTENTS(&circuitpy->fatfs, "/saves/placeholder.txt", + "A separate filesystem mounted at /saves will hide this file from Python." + " Saves are visible via USB CPSAVES.\n"); + } #endif #endif - #if CIRCUITPY_OS_GETENV - make_empty_file(&vfs_fat->fatfs, "/settings.toml"); + #if CIRCUITPY_SETTINGS_TOML + make_empty_file(&circuitpy->fatfs, "/settings.toml"); #endif // make a sample code.py file - MAKE_FILE_WITH_OPTIONAL_CONTENTS(&vfs_fat->fatfs, "/code.py", "print(\"Hello World!\")\n"); + MAKE_FILE_WITH_OPTIONAL_CONTENTS(&circuitpy->fatfs, "/code.py", "print(\"Hello World!\")\n"); // create empty lib directory - res = f_mkdir(&vfs_fat->fatfs, "/lib"); + res = f_mkdir(&circuitpy->fatfs, "/lib"); if (res != FR_OK) { return false; } @@ -148,21 +190,37 @@ bool filesystem_init(bool create_allowed, bool force_create) { return false; } - vfs->str = "/"; - vfs->len = 1; - vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); - vfs->next = NULL; - - MP_STATE_VM(vfs_mount_table) = vfs; + circuitpy_vfs->str = "/"; + circuitpy_vfs->len = 1; + circuitpy_vfs->obj = MP_OBJ_FROM_PTR(circuitpy); + circuitpy_vfs->next = NULL; + + MP_STATE_VM(vfs_mount_table) = circuitpy_vfs; + + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + res = f_mount(&saves->fatfs); + if (res == FR_OK) { + mp_vfs_mount_t *saves_vfs = &_saves_vfs; + saves_vfs->str = "/saves"; + saves_vfs->len = 6; + saves_vfs->obj = MP_OBJ_FROM_PTR(&_saves_usermount); + saves_vfs->next = MP_STATE_VM(vfs_mount_table); + MP_STATE_VM(vfs_mount_table) = saves_vfs; + } + #endif // The current directory is used as the boot up directory. // It is set to the internal flash filesystem by default. - MP_STATE_PORT(vfs_cur) = vfs; + MP_STATE_PORT(vfs_cur) = circuitpy_vfs; #if CIRCUITPY_STORAGE_EXTEND supervisor_flash_update_extended(); #endif + #if CIRCUITPY_SDCARDIO + sdcardio_init(); + #endif + return true; } @@ -175,7 +233,7 @@ void PLACE_IN_ITCM(filesystem_flush)(void) { } void filesystem_set_internal_writable_by_usb(bool writable) { - fs_user_mount_t *vfs = &_internal_vfs; + fs_user_mount_t *vfs = &_circuitpy_usermount; filesystem_set_writable_by_usb(vfs, writable); } @@ -189,17 +247,19 @@ void filesystem_set_writable_by_usb(fs_user_mount_t *vfs, bool usb_writable) { } bool filesystem_is_writable_by_python(fs_user_mount_t *vfs) { - return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || - (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0; + return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0); } bool filesystem_is_writable_by_usb(fs_user_mount_t *vfs) { - return (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0 || - (vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0; + return ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED) == 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_USB_WRITABLE) != 0) || + ((vfs->blockdev.flags & MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION) != 0); } void filesystem_set_internal_concurrent_write_protection(bool concurrent_write_protection) { - filesystem_set_concurrent_write_protection(&_internal_vfs, concurrent_write_protection); + filesystem_set_concurrent_write_protection(&_circuitpy_usermount, concurrent_write_protection); } void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concurrent_write_protection) { @@ -210,15 +270,23 @@ void filesystem_set_concurrent_write_protection(fs_user_mount_t *vfs, bool concu } } +void filesystem_set_ignore_write_protection(fs_user_mount_t *vfs, bool ignore_write_protection) { + if (ignore_write_protection) { + vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; + } else { + vfs->blockdev.flags &= ~MP_BLOCKDEV_FLAG_IGNORE_WRITE_PROTECTION; + } +} + bool filesystem_present(void) { - return _mp_vfs.len > 0; + return _circuitpy_vfs.len > 0; } fs_user_mount_t *filesystem_circuitpy(void) { if (!filesystem_present()) { return NULL; } - return &_internal_vfs; + return &_circuitpy_usermount; } fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_under_mount) { @@ -237,7 +305,7 @@ fs_user_mount_t *filesystem_for_path(const char *path_in, const char **path_unde // because otherwise the path will be adjusted by os.getcwd() when it's looked up. if (strlen(vfs->str) != 1) { // Remove the mount point directory name, such as "/sd". - path_under_mount += strlen(vfs->str); + *path_under_mount += strlen(vfs->str); } } return fs_mount; diff --git a/supervisor/shared/flash.c b/supervisor/shared/flash.c index 37fba60ae8b34..ccb60efe32192 100644 --- a/supervisor/shared/flash.c +++ b/supervisor/shared/flash.c @@ -7,6 +7,7 @@ #include "extmod/vfs_fat.h" #include "py/runtime.h" +#include "lib/oofatfs/diskio.h" #include "lib/oofatfs/ff.h" #include "supervisor/flash.h" #include "supervisor/shared/tick.h" @@ -27,9 +28,54 @@ static mp_obj_t supervisor_flash_obj_make_new(const mp_obj_type_t *type, size_t return (mp_obj_t)&supervisor_flash_obj; } -static uint32_t flash_get_block_count(void) { - return PART1_START_BLOCK + supervisor_flash_get_block_count(); + +static bool flash_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { + if (out_value != NULL) { + *out_value = 0; + } + + mp_vfs_blockdev_t *self = (mp_vfs_blockdev_t *)self_in; + switch (cmd) { + case MP_BLOCKDEV_IOCTL_INIT: + supervisor_flash_init(); + break; + case MP_BLOCKDEV_IOCTL_DEINIT: + supervisor_flash_flush(); + break; // TODO properly + case MP_BLOCKDEV_IOCTL_SYNC: + supervisor_flash_flush(); + break; + case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: + *out_value = PART1_START_BLOCK; + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + if (self->size > 0) { + *out_value += self->size / self->block_size; + } else { + *out_value += supervisor_flash_get_block_count() - (self->offset / self->block_size); + } + #else + *out_value += supervisor_flash_get_block_count(); + #endif + break; + case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: + *out_value = self->block_size; + break; + default: + return false; + } + return true; +} + +static mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { + mp_int_t cmd = mp_obj_get_int(cmd_in); + mp_int_t arg = mp_obj_get_int(arg_in); + mp_int_t out_value; + if (flash_ioctl(self, cmd, arg, &out_value)) { + return MP_OBJ_NEW_SMALL_INT(out_value); + } + return mp_const_none; } +static MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_ioctl_obj, supervisor_flash_obj_ioctl); static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { buf[0] = boot; @@ -67,7 +113,7 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo buf[15] = num_blocks >> 24; } -static mp_uint_t flash_read_blocks(mp_obj_t self, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { +static mp_uint_t flash_read_blocks(mp_obj_t self_in, uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { if (block_num == 0) { // fake the MBR so we can decide on our own partition table @@ -75,8 +121,11 @@ static mp_uint_t flash_read_blocks(mp_obj_t self, uint8_t *dest, uint32_t block_ dest[i] = 0; } + mp_int_t block_count; + flash_ioctl(self_in, MP_BLOCKDEV_IOCTL_BLOCK_COUNT, 0, &block_count); + // Specifying "Big FAT12/16 CHS" allows mounting by Android - build_partition(dest + 446, 0, 0x06 /* Big FAT12/16 CHS */, PART1_START_BLOCK, supervisor_flash_get_block_count()); + build_partition(dest + 446, 0, 0x06 /* Big FAT12/16 CHS */, PART1_START_BLOCK, block_count - PART1_START_BLOCK); build_partition(dest + 462, 0, 0, 0, 0); build_partition(dest + 478, 0, 0, 0, 0); build_partition(dest + 494, 0, 0, 0, 0); @@ -92,12 +141,17 @@ static mp_uint_t flash_read_blocks(mp_obj_t self, uint8_t *dest, uint32_t block_ return 0; // Done and ok. } } - return supervisor_flash_read_blocks(dest, block_num - PART1_START_BLOCK, num_blocks); + block_num -= PART1_START_BLOCK; + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + mp_vfs_blockdev_t *self = (mp_vfs_blockdev_t *)self_in; + block_num += self->offset / self->block_size; + #endif + return supervisor_flash_read_blocks(dest, block_num, num_blocks); } static volatile bool filesystem_dirty = false; -static mp_uint_t flash_write_blocks(mp_obj_t self, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { +static mp_uint_t flash_write_blocks(mp_obj_t self_in, const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { if (block_num == 0) { if (num_blocks > 1) { return 1; // error @@ -110,7 +164,12 @@ static mp_uint_t flash_write_blocks(mp_obj_t self, const uint8_t *src, uint32_t supervisor_enable_tick(); filesystem_dirty = true; } - return supervisor_flash_write_blocks(src, block_num - PART1_START_BLOCK, num_blocks); + block_num -= PART1_START_BLOCK; + #if CIRCUITPY_SAVES_PARTITION_SIZE > 0 + mp_vfs_blockdev_t *self = (mp_vfs_blockdev_t *)self_in; + block_num += self->offset / self->block_size; + #endif + return supervisor_flash_write_blocks(src, block_num, num_blocks); } } @@ -143,43 +202,6 @@ static mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_n } static MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks); -static bool flash_ioctl(mp_obj_t self_in, size_t cmd, size_t arg, mp_int_t *out_value) { - if (out_value != NULL) { - *out_value = 0; - } - switch (cmd) { - case MP_BLOCKDEV_IOCTL_INIT: - supervisor_flash_init(); - break; - case MP_BLOCKDEV_IOCTL_DEINIT: - supervisor_flash_flush(); - break; // TODO properly - case MP_BLOCKDEV_IOCTL_SYNC: - supervisor_flash_flush(); - break; - case MP_BLOCKDEV_IOCTL_BLOCK_COUNT: - *out_value = flash_get_block_count(); - break; - case MP_BLOCKDEV_IOCTL_BLOCK_SIZE: - *out_value = supervisor_flash_get_block_size(); - break; - default: - return false; - } - return true; -} - -static mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - mp_int_t arg = mp_obj_get_int(arg_in); - mp_int_t out_value; - if (flash_ioctl(self, cmd, arg, &out_value)) { - return MP_OBJ_NEW_SMALL_INT(out_value); - } - return mp_const_none; -} -static MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_ioctl_obj, supervisor_flash_obj_ioctl); - static const mp_rom_map_elem_t supervisor_flash_obj_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&supervisor_flash_obj_readblocks_obj) }, { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&supervisor_flash_obj_writeblocks_obj) }, @@ -199,15 +221,16 @@ MP_DEFINE_CONST_OBJ_TYPE( void supervisor_flash_init_vfs(fs_user_mount_t *vfs) { vfs->base.type = &mp_fat_vfs_type; vfs->blockdev.flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL; + vfs->blockdev.block_size = supervisor_flash_get_block_size(); vfs->fatfs.drv = vfs; vfs->fatfs.part = 1; // flash filesystem lives on first fake partition - vfs->blockdev.readblocks[0] = (mp_obj_t)&supervisor_flash_obj_readblocks_obj; - vfs->blockdev.readblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->blockdev.readblocks[0] = mp_const_none; + vfs->blockdev.readblocks[1] = (mp_obj_t)&vfs->blockdev; vfs->blockdev.readblocks[2] = (mp_obj_t)flash_read_blocks; // native version - vfs->blockdev.writeblocks[0] = (mp_obj_t)&supervisor_flash_obj_writeblocks_obj; - vfs->blockdev.writeblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->blockdev.writeblocks[0] = mp_const_none; + vfs->blockdev.writeblocks[1] = (mp_obj_t)&vfs->blockdev; vfs->blockdev.writeblocks[2] = (mp_obj_t)flash_write_blocks; // native version - vfs->blockdev.u.ioctl[0] = (mp_obj_t)&supervisor_flash_obj_ioctl_obj; - vfs->blockdev.u.ioctl[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->blockdev.u.ioctl[0] = mp_const_none; + vfs->blockdev.u.ioctl[1] = (mp_obj_t)&vfs->blockdev; vfs->blockdev.u.ioctl[2] = (mp_obj_t)flash_ioctl; // native version } diff --git a/supervisor/shared/port.c b/supervisor/shared/port.c index 72bb45b8a270c..3c95f2b740931 100644 --- a/supervisor/shared/port.c +++ b/supervisor/shared/port.c @@ -8,10 +8,17 @@ #include +#include "py/mphal.h" #include "py/runtime.h" +#include "py/gc.h" #include "lib/tlsf/tlsf.h" +#ifdef CIRCUITPY_BOOT_BUTTON +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/time/__init__.h" +#endif + static tlsf_t heap; MP_WEAK void port_wake_main_task(void) { @@ -20,7 +27,11 @@ MP_WEAK void port_wake_main_task(void) { MP_WEAK void port_wake_main_task_from_isr(void) { } -MP_WEAK void port_yield(void) { +MP_WEAK void port_task_yield(void) { +} + +MP_WEAK void port_task_sleep_ms(uint32_t msecs) { + mp_hal_delay_ms(msecs); } MP_WEAK void port_boot_info(void) { @@ -38,11 +49,36 @@ MP_WEAK void *port_malloc(size_t size, bool dma_capable) { return block; } +// Ensure allocated memory is zero. +MP_WEAK void *port_malloc_zero(size_t size, bool dma_capable) { + void *ptr = port_malloc(size, dma_capable); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + MP_WEAK void port_free(void *ptr) { tlsf_free(heap, ptr); } -MP_WEAK void *port_realloc(void *ptr, size_t size) { +// Safely free an object that may have been allocated from either the GC heap or port heap. +// If the pointer is on the GC heap, it will be freed by the GC automatically, so we do nothing. +// If the pointer is not on the GC heap (i.e., allocated with port_malloc), we free it with port_free. +// This is safe to call during shutdown when GC may not be available. +void circuitpy_free_obj(mp_obj_t obj) { + if (obj == mp_const_none) { + return; + } + void *ptr = MP_OBJ_TO_PTR(obj); + if (gc_alloc_possible() && gc_ptr_on_heap(ptr)) { + gc_free(ptr); + } else { + port_free(ptr); + } +} + +MP_WEAK void *port_realloc(void *ptr, size_t size, bool dma_capable) { return tlsf_realloc(heap, ptr, size); } @@ -60,3 +96,45 @@ MP_WEAK size_t port_heap_get_largest_free_size(void) { // IDF does this. Not sure why. return tlsf_fit_size(heap, max_size); } + +MP_WEAK bool port_boot_button_pressed(void) { + #if defined(CIRCUITPY_BOOT_BUTTON) + // Init/deinit the boot button every time in case it is used for LEDs. + digitalio_digitalinout_obj_t boot_button; + common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); + common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); + common_hal_time_delay_ms(1); + bool button_pressed = !common_hal_digitalio_digitalinout_get_value(&boot_button); + common_hal_digitalio_digitalinout_deinit(&boot_button); + return button_pressed; + #else + return false; + #endif +} + +// Ports may provide an implementation of this function if it is needed +MP_WEAK void port_gc_collect(void) { +} + +// Allocates an object in the port heap, not the VM heap, and also sets type, for mp_obj_malloc{,_var} macros. +MP_NOINLINE void *mp_obj_port_malloc_helper(size_t num_bytes, const mp_obj_type_t *type) { + mp_obj_base_t *base = (mp_obj_base_t *)port_malloc_zero(num_bytes, false); + base->type = type; + return base; +} + +// Creates a tuple on the port heap, not the VM heap. +// Implementation copied from py/objtuple.c. +mp_obj_t mp_obj_new_port_tuple(size_t n, const mp_obj_t *items) { + if (n == 0) { + return mp_const_empty_tuple; + } + mp_obj_tuple_t *o = mp_obj_port_malloc_var(mp_obj_tuple_t, items, mp_obj_t, n, &mp_type_tuple); + o->len = n; + if (items) { + for (size_t i = 0; i < n; i++) { + o->items[i] = items[i]; + } + } + return MP_OBJ_FROM_PTR(o); +} diff --git a/supervisor/shared/reload.c b/supervisor/shared/reload.c index fb7ff0403c259..862c4ccebc7aa 100644 --- a/supervisor/shared/reload.c +++ b/supervisor/shared/reload.c @@ -35,16 +35,16 @@ void reload_initiate(supervisor_run_reason_t run_reason) { port_wake_main_task(); } -void autoreload_reset() { +void autoreload_reset(void) { last_autoreload_trigger = 0; } -void autoreload_enable() { +void autoreload_enable(void) { autoreload_enabled = true; last_autoreload_trigger = 0; } -void autoreload_disable() { +void autoreload_disable(void) { autoreload_enabled = false; } @@ -56,11 +56,11 @@ void autoreload_resume(uint32_t suspend_reason_mask) { autoreload_suspended &= ~suspend_reason_mask; } -inline bool autoreload_is_enabled() { +inline bool autoreload_is_enabled(void) { return autoreload_enabled; } -void autoreload_trigger() { +void autoreload_trigger(void) { if (!autoreload_enabled || autoreload_suspended != 0) { return; } @@ -78,7 +78,7 @@ void autoreload_trigger() { } } -bool autoreload_ready() { +bool autoreload_ready(void) { if (last_autoreload_trigger == 0 || autoreload_suspended != 0) { return false; } diff --git a/supervisor/shared/safe_mode.c b/supervisor/shared/safe_mode.c index 30e5a23729bad..3860de6621f71 100644 --- a/supervisor/shared/safe_mode.c +++ b/supervisor/shared/safe_mode.c @@ -8,10 +8,6 @@ #include "mphalport.h" -#if defined(CIRCUITPY_BOOT_BUTTON) -#include "shared-bindings/digitalio/DigitalInOut.h" -#include "shared-bindings/time/__init__.h" -#endif #include "shared-bindings/microcontroller/Processor.h" #include "shared-bindings/microcontroller/ResetReason.h" @@ -22,6 +18,10 @@ #include "supervisor/shared/translate/translate.h" #include "supervisor/shared/tick.h" +#ifdef __ZEPHYR__ +#include +#endif + #define SAFE_MODE_DATA_GUARD 0xad0000af #define SAFE_MODE_DATA_GUARD_MASK 0xff0000ff @@ -69,7 +69,7 @@ safe_mode_t wait_for_safe_mode_reset(void) { uint64_t diff = 0; bool boot_in_safe_mode = false; while (diff < 1000) { - #ifdef CIRCUITPY_STATUS_LED + #if CIRCUITPY_STATUS_LED // Blink on for 100, off for 100 bool led_on = (diff % 250) < 125; if (led_on) { @@ -78,19 +78,10 @@ safe_mode_t wait_for_safe_mode_reset(void) { new_status_color(BLACK); } #endif - // Init the boot button every time in case it is used for LEDs. - #ifdef CIRCUITPY_BOOT_BUTTON - digitalio_digitalinout_obj_t boot_button; - common_hal_digitalio_digitalinout_construct(&boot_button, CIRCUITPY_BOOT_BUTTON); - common_hal_digitalio_digitalinout_switch_to_input(&boot_button, PULL_UP); - common_hal_time_delay_ms(1); - bool button_pressed = !common_hal_digitalio_digitalinout_get_value(&boot_button); - common_hal_digitalio_digitalinout_deinit(&boot_button); - if (button_pressed) { + if (port_boot_button_pressed()) { boot_in_safe_mode = true; break; } - #endif diff = supervisor_ticks_ms64() - start_ticks; } #if CIRCUITPY_STATUS_LED @@ -112,10 +103,19 @@ void PLACE_IN_ITCM(safe_mode_on_next_reset)(safe_mode_t reason) { // Don't inline this so it's easy to break on it from GDB. void __attribute__((noinline, )) PLACE_IN_ITCM(reset_into_safe_mode)(safe_mode_t reason) { if (_safe_mode > SAFE_MODE_BROWNOUT && reason > SAFE_MODE_BROWNOUT) { + #ifdef __ZEPHYR__ + printk("Already in safe mode\n"); + printk("Reason: %d\n", reason); + printk("Current safe mode: %d\n", _safe_mode); + while (true) { + k_cpu_idle(); + } + #else while (true) { // This very bad because it means running in safe mode didn't save us. Only ignore brownout // because it may be due to a switch bouncing. } + #endif } safe_mode_on_next_reset(reason); @@ -142,7 +142,7 @@ void print_safe_mode_message(safe_mode_t reason) { case SAFE_MODE_USER: #if defined(BOARD_USER_SAFE_MODE_ACTION) message = BOARD_USER_SAFE_MODE_ACTION; - #elif defined(CIRCUITPY_BOOT_BUTTON) + #elif defined(CIRCUITPY_BOOT_BUTTON) || CIRCUITPY_BOOT_BUTTON_NO_GPIO message = MP_ERROR_TEXT("You pressed the BOOT button at start up"); #else message = MP_ERROR_TEXT("You pressed the reset button during boot."); diff --git a/supervisor/shared/safe_mode.h b/supervisor/shared/safe_mode.h index 8f4037cbe20c3..87f65d867ea62 100644 --- a/supervisor/shared/safe_mode.h +++ b/supervisor/shared/safe_mode.h @@ -38,6 +38,6 @@ void set_safe_mode(safe_mode_t safe_mode); safe_mode_t wait_for_safe_mode_reset(void); void safe_mode_on_next_reset(safe_mode_t reason); -void reset_into_safe_mode(safe_mode_t reason) NORETURN; +void reset_into_safe_mode(safe_mode_t reason) MP_NORETURN; void print_safe_mode_message(safe_mode_t reason); diff --git a/supervisor/shared/serial.c b/supervisor/shared/serial.c index fce066f70de7f..5728a95e08f4c 100644 --- a/supervisor/shared/serial.c +++ b/supervisor/shared/serial.c @@ -9,6 +9,7 @@ #include "py/mpconfig.h" #include "py/mphal.h" +#include "py/mpprint.h" #include "supervisor/shared/cpu.h" #include "supervisor/shared/display.h" @@ -34,7 +35,6 @@ #endif #if CIRCUITPY_CONSOLE_UART -#include "py/mpprint.h" #include "shared-bindings/busio/UART.h" busio_uart_obj_t console_uart; @@ -63,33 +63,94 @@ static bool _serial_console_write_disabled; // Set to true to temporarily discard writes to the display terminal only. static bool _serial_display_write_disabled; +// Indicates that serial console has been early initialized. +static bool _serial_console_early_inited = false; + #if CIRCUITPY_CONSOLE_UART -static void console_uart_print_strn(void *env, const char *str, size_t len) { + +// All output to the console uart comes through this inner write function. It ensures that all +// lines are terminated with a "cooked" '\r\n' sequence. Lines that are already cooked are sent +// on unchanged. +static void inner_console_uart_write_cb(void *env, const char *str, size_t len) { (void)env; int uart_errcode; - common_hal_busio_uart_write(&console_uart, (const uint8_t *)str, len, &uart_errcode); + bool last_cr = false; + while (len > 0) { + size_t i = 0; + if (str[0] == '\n' && !last_cr) { + common_hal_busio_uart_write(&console_uart, (const uint8_t *)"\r", 1, &uart_errcode); + i = 1; + } + // Lump all characters on the next line together. + while ((last_cr || str[i] != '\n') && i < len) { + last_cr = str[i] == '\r'; + i++; + } + common_hal_busio_uart_write(&console_uart, (const uint8_t *)str, i, &uart_errcode); + str = &str[i]; + len -= i; + } } -const mp_print_t console_uart_print = {NULL, console_uart_print_strn}; +#if CIRCUITPY_CONSOLE_UART_TIMESTAMP +static const mp_print_t inner_console_uart_write = {NULL, inner_console_uart_write_cb}; +static uint32_t console_uart_write_prev_time = 0; +static bool console_uart_write_prev_nl = true; + +static inline void console_uart_write_timestamp(void) { + uint32_t now = supervisor_ticks_ms32(); + uint32_t delta = now - console_uart_write_prev_time; + console_uart_write_prev_time = now; + mp_printf(&inner_console_uart_write, + "%01lu.%03lu(%01lu.%03lu): ", + now / 1000, now % 1000, delta / 1000, delta % 1000); +} #endif -int console_uart_printf(const char *fmt, ...) { - #if CIRCUITPY_CONSOLE_UART - // Skip prints that occur before console serial is started. It's better than - // crashing. - if (common_hal_busio_uart_deinited(&console_uart)) { - return 0; +static size_t console_uart_write(const char *str, size_t len) { + // Ignore writes if console uart is not yet initialized. + if (!_serial_console_early_inited) { + return len; } - va_list ap; - va_start(ap, fmt); - int ret = mp_vprintf(&console_uart_print, fmt, ap); - va_end(ap); - return ret; - #else - return 0; - #endif + + if (!_first_write_done) { + mp_hal_delay_ms(50); + _first_write_done = true; + } + + // There may be multiple newlines in the string, split at newlines. + int remaining_len = len; + while (remaining_len > 0) { + #if CIRCUITPY_CONSOLE_UART_TIMESTAMP + if (console_uart_write_prev_nl) { + console_uart_write_timestamp(); + console_uart_write_prev_nl = false; + } + #endif + int print_len = 0; + while (print_len < remaining_len) { + if (str[print_len++] == '\n') { + #if CIRCUITPY_CONSOLE_UART_TIMESTAMP + console_uart_write_prev_nl = true; + #endif + break; + } + } + inner_console_uart_write_cb(NULL, str, print_len); + str += print_len; + remaining_len -= print_len; + } + return len; +} + +static void console_uart_write_cb(void *env, const char *str, size_t len) { + (void)env; + console_uart_write(str, len); } +const mp_print_t console_uart_print = {NULL, console_uart_write_cb}; +#endif + MP_WEAK void board_serial_early_init(void) { } @@ -113,33 +174,15 @@ MP_WEAK void board_serial_write_substring(const char *text, uint32_t length) { (void)length; } -MP_WEAK void port_serial_early_init(void) { -} - -MP_WEAK void port_serial_init(void) { -} - -MP_WEAK bool port_serial_connected(void) { - return false; -} - -MP_WEAK char port_serial_read(void) { - return -1; -} - -MP_WEAK uint32_t port_serial_bytes_available(void) { - return 0; -} - -MP_WEAK void port_serial_write_substring(const char *text, uint32_t length) { - (void)text; - (void)length; -} - void serial_early_init(void) { - // Set up console UART, if enabled. + // Ignore duplicate calls to initialize allowing port-specific code to + // call this function early. + if (_serial_console_early_inited) { + return; + } #if CIRCUITPY_CONSOLE_UART + // Set up console UART, if enabled. console_uart.base.type = &busio_uart_type; const mcu_pin_obj_t *console_rx = MP_OBJ_TO_PTR(CIRCUITPY_CONSOLE_UART_RX); @@ -149,13 +192,18 @@ void serial_early_init(void) { false, CIRCUITPY_CONSOLE_UART_BAUDRATE, 8, BUSIO_UART_PARITY_NONE, 1, 1.0f, sizeof(console_uart_rx_buf), console_uart_rx_buf, true); common_hal_busio_uart_never_reset(&console_uart); - - // Do an initial print so that we can confirm the serial output is working. - console_uart_printf("Serial console setup\r\n"); #endif board_serial_early_init(); + + #if CIRCUITPY_PORT_SERIAL port_serial_early_init(); + #endif + + _serial_console_early_inited = true; + + // Do an initial print so that we can confirm the serial output is working. + CIRCUITPY_CONSOLE_UART_PRINTF("Serial console setup\n"); } void serial_init(void) { @@ -164,11 +212,14 @@ void serial_init(void) { #endif board_serial_init(); + + #if CIRCUITPY_PORT_SERIAL port_serial_init(); + #endif } bool serial_connected(void) { - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR if (tud_vendor_connected()) { return true; } @@ -184,11 +235,11 @@ bool serial_connected(void) { } #endif - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC if (usb_cdc_console_enabled() && tud_cdc_connected()) { return true; } - #elif CIRCUITPY_USB_DEVICE + #elif CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE if (tud_cdc_connected()) { return true; } @@ -211,15 +262,18 @@ bool serial_connected(void) { return true; } + + #if CIRCUITPY_PORT_SERIAL if (port_serial_connected()) { return true; } + #endif return false; } char serial_read(void) { - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR if (tud_vendor_connected() && tud_vendor_available() > 0) { char tiny_buffer; tud_vendor_read(&tiny_buffer, 1); @@ -244,7 +298,7 @@ char serial_read(void) { #if CIRCUITPY_WEB_WORKFLOW if (websocket_available()) { - char c = websocket_read_char(); + int c = websocket_read_char(); if (c != -1) { return c; } @@ -261,16 +315,19 @@ char serial_read(void) { return board_serial_read(); } + + #if CIRCUITPY_PORT_SERIAL if (port_serial_bytes_available() > 0) { return port_serial_read(); } + #endif #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC if (!usb_cdc_console_enabled()) { return -1; } #endif - #if CIRCUITPY_USB_DEVICE + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE return (char)tud_cdc_read_char(); #endif @@ -281,7 +338,7 @@ uint32_t serial_bytes_available(void) { // There may be multiple serial input channels, so sum the count from all. uint32_t count = 0; - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR if (tud_vendor_connected()) { count += tud_vendor_available(); } @@ -303,7 +360,7 @@ uint32_t serial_bytes_available(void) { count += usb_keyboard_chars_available(); #endif - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC if (usb_cdc_console_enabled()) { count += tud_cdc_available(); } @@ -312,8 +369,10 @@ uint32_t serial_bytes_available(void) { // Board-specific serial input. count += board_serial_bytes_available(); + #if CIRCUITPY_PORT_SERIAL // Port-specific serial input. count += port_serial_bytes_available(); + #endif return count; } @@ -340,19 +399,14 @@ uint32_t serial_write_substring(const char *text, uint32_t length) { return length_sent; } - #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_VENDOR if (tud_vendor_connected()) { length_sent = tud_vendor_write(text, length); } #endif #if CIRCUITPY_CONSOLE_UART - if (!_first_write_done) { - mp_hal_delay_ms(50); - _first_write_done = true; - } - int uart_errcode; - length_sent = common_hal_busio_uart_write(&console_uart, (const uint8_t *)text, length, &uart_errcode); + length_sent = console_uart_write(text, length); #endif #if CIRCUITPY_SERIAL_BLE @@ -369,7 +423,7 @@ uint32_t serial_write_substring(const char *text, uint32_t length) { } #endif - #if CIRCUITPY_USB_DEVICE + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE // Delay the very first write if (tud_cdc_connected() && !_first_write_done) { mp_hal_delay_ms(50); @@ -389,7 +443,10 @@ uint32_t serial_write_substring(const char *text, uint32_t length) { #endif board_serial_write_substring(text, length); + + #if CIRCUITPY_PORT_SERIAL port_serial_write_substring(text, length); + #endif return length_sent; } @@ -409,3 +466,73 @@ bool serial_display_write_disable(bool disabled) { _serial_display_write_disabled = disabled; return now; } + +// A general purpose hex/ascii dump function for arbitrary area of memory. +void print_hexdump(const mp_print_t *printer, const char *prefix, const uint8_t *buf, size_t len) { + size_t i; + for (i = 0; i < len; ++i) { + // print hex digit + if (i % 32 == 0) { + mp_printf(printer, "%s0x%04x:", prefix, i); + } + if (i % 32 == 16) { + mp_printf(printer, " : "); + } else if (i % 4 == 0) { + mp_printf(printer, " "); + } + mp_printf(printer, "%02x", buf[i]); + // print ascii chars for this line + if (i % 32 == 31) { + size_t k = i - 31; + mp_printf(printer, " : "); + for (size_t j = 0; j < 32; ++j) { + if (j == 16) { + mp_printf(printer, " "); + } + if (buf[k + j] >= 32 && buf[k + j] < 127) { + mp_printf(printer, "%c", buf[k + j]); + } else { + mp_printf(printer, "."); + } + } + mp_printf(printer, "\n"); + } + } + if (i % 32 != 0) { + // For a final line of less than 32 bytes, pad with spaces + i -= i % 32; + for (size_t j = len % 32; j < 32; ++j) { + if (j % 32 == 16) { + mp_printf(printer, " "); + } else if (j % 4 == 0) { + mp_printf(printer, " "); + } + mp_printf(printer, " "); + } + // Print ascii chars for the last line fragment + mp_printf(printer, " : "); + for (size_t j = 0; j < len % 32; ++j) { + if (j == 16) { + mp_printf(printer, " "); + } + if (buf[i + j] >= 32 && buf[i + j] < 127) { + mp_printf(printer, "%c", buf[i + j]); + } else { + mp_printf(printer, "."); + } + } + mp_printf(printer, "\n"); + } +} + +int console_uart_printf(const char *fmt, ...) { + #if CIRCUITPY_CONSOLE_UART + va_list args; + va_start(args, fmt); + int ret = mp_vprintf(&console_uart_print, fmt, args); + va_end(args); + return ret; + #else + return 0; + #endif +} diff --git a/supervisor/shared/serial.h b/supervisor/shared/serial.h index ea0f147cc49ee..d64a316ff3271 100644 --- a/supervisor/shared/serial.h +++ b/supervisor/shared/serial.h @@ -11,6 +11,7 @@ #include #include "py/mpconfig.h" +#include "py/mpprint.h" #ifdef CIRCUITPY_BOOT_OUTPUT_FILE #include "py/misc.h" @@ -47,4 +48,8 @@ char board_serial_read(void); uint32_t board_serial_bytes_available(void); void board_serial_write_substring(const char *text, uint32_t length); -int console_uart_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); +extern const mp_print_t console_uart_print; + +int console_uart_printf(const char *fmt, ...); + +void print_hexdump(const mp_print_t *printer, const char *prefix, const uint8_t *buf, size_t len); diff --git a/supervisor/shared/settings.c b/supervisor/shared/settings.c new file mode 100644 index 0000000000000..d1b05a5da9db5 --- /dev/null +++ b/supervisor/shared/settings.c @@ -0,0 +1,463 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// SPDX-FileCopyrightText: Copyright (c) 2026 Dan Halbert for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include +#include +#include + +#include "py/gc.h" +#include "py/misc.h" +#include "py/mpstate.h" +#include "py/mpprint.h" +#include "py/objstr.h" +#include "py/parsenum.h" +#include "py/runtime.h" +#include "supervisor/filesystem.h" +#include "supervisor/shared/settings.h" + +#define SETTINGS_PATH "/settings.toml" + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" + +#if CIRCUITPY_SETTINGS_TOML +typedef FIL file_arg; +static bool open_file(const char *name, file_arg *file_handle) { + #if defined(UNIX) + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_obj_t file_obj = mp_call_function_2( + MP_OBJ_FROM_PTR(&mp_builtin_open_obj), mp_obj_new_str(name, strlen(name)), MP_ROM_QSTR(MP_QSTR_rb)); + mp_arg_validate_type(file_obj, &mp_type_vfs_fat_fileio, MP_QSTR_file); + pyb_file_obj_t *file = MP_OBJ_TO_PTR(file_obj); + *file_handle = file->fp; + nlr_pop(); + return true; + } else { + return false; + } + #else + fs_user_mount_t *fs_mount = filesystem_circuitpy(); + if (fs_mount == NULL) { + return false; + } + FATFS *fatfs = &fs_mount->fatfs; + FRESULT result = f_open(fatfs, file_handle, name, FA_READ); + return result == FR_OK; + #endif +} + +static void close_file(file_arg *file_handle) { + f_close(file_handle); +} + +static bool is_eof(file_arg *file_handle) { + return f_eof(file_handle) || f_error(file_handle); +} + +// Return 0 if there is no next character (EOF). +static uint8_t get_next_byte(FIL *file_handle) { + uint8_t character = 0; + UINT quantity_read; + // If there's an error or quantity_read is 0, character will remain 0. + f_read(file_handle, &character, 1, &quantity_read); + return character; +} + +static void seek_eof(file_arg *file_handle) { + f_lseek(file_handle, f_size(file_handle)); +} + +// For a fixed buffer, record the required size rather than throwing +static void vstr_add_byte_nonstd(vstr_t *vstr, byte b) { + if (!vstr->fixed_buf || vstr->alloc > vstr->len) { + vstr_add_byte(vstr, b); + } else { + vstr->len++; + } +} + +// For a fixed buffer, record the required size rather than throwing +static void vstr_add_char_nonstd(vstr_t *vstr, unichar c) { + size_t ulen = + (c < 0x80) ? 1 : + (c < 0x800) ? 2 : + (c < 0x10000) ? 3 : 4; + if (!vstr->fixed_buf || vstr->alloc > vstr->len + ulen) { + vstr_add_char(vstr, c); + } else { + vstr->len += ulen; + } +} + +static void next_line(file_arg *file_handle) { + uint8_t character; + do { + character = get_next_byte(file_handle); + } while (character != 0 && character != '\n'); +} + +// Discard whitespace, except for newlines, returning the next character after the whitespace. +// Return 0 if there is no next character (EOF). +static uint8_t consume_whitespace(file_arg *file_handle) { + uint8_t character; + do { + character = get_next_byte(file_handle); + } while (character != '\n' && character != 0 && unichar_isspace(character)); + return character; +} + +// Starting at the start of a new line, determines if the key matches the given key. +// +// If result is true, the key matches and file pointer is pointing just after the "=". +// If the result is false, the key does NOT match and the file pointer is +// pointing at the start of the next line, if any +static bool key_matches(file_arg *file_handle, const char *key) { + uint8_t character; + character = consume_whitespace(file_handle); + // [section] isn't implemented, so skip to end of file. + if (character == '[' || character == 0) { + seek_eof(file_handle); + return false; + } + while (*key) { + if (character != *key++) { + // A character didn't match the key, so it's not a match + // If the non-matching char was not the end of the line, + // then consume the rest of the line + if (character != '\n') { + next_line(file_handle); + } + return false; + } + character = get_next_byte(file_handle); + } + // the next character could be whitespace; consume if necessary + if (unichar_isspace(character)) { + character = consume_whitespace(file_handle); + } + // If we're not looking at the "=" then the key didn't match + if (character != '=') { + // A character didn't match the key, so it's not a match + // If the non-matching char was not the end of the line, + // then consume the rest of the line + if (character != '\n') { + next_line(file_handle); + } + return false; + } + return true; +} + +static settings_err_t read_unicode_escape(file_arg *file_handle, int sz, vstr_t *vstr) { + char hex_buf[sz + 1]; + for (int i = 0; i < sz; i++) { + hex_buf[i] = get_next_byte(file_handle); + } + hex_buf[sz] = 0; + char *end; + unsigned long c = strtoul(hex_buf, &end, 16); + if (end != &hex_buf[sz]) { + return SETTINGS_ERR_BAD_VALUE; + } + if (c >= 0x110000) { + return SETTINGS_ERR_UNICODE; + } + vstr_add_char_nonstd(vstr, c); + return SETTINGS_OK; +} + +// Read a quoted string +static settings_err_t read_string_value(file_arg *file_handle, vstr_t *vstr) { + while (true) { + int character = get_next_byte(file_handle); + switch (character) { + case 0: + case '\n': + return SETTINGS_ERR_BAD_VALUE; + + case '"': + character = consume_whitespace(file_handle); + switch (character) { + case '#': + next_line(file_handle); + MP_FALLTHROUGH; + case 0: + case '\n': + return SETTINGS_OK; + default: + return SETTINGS_ERR_BAD_VALUE; + } + + case '\\': + character = get_next_byte(file_handle); + switch (character) { + case 0: + case '\n': + return SETTINGS_ERR_BAD_VALUE; + case 'b': + character = '\b'; + break; + case 'r': + character = '\r'; + break; + case 'n': + character = '\n'; + break; + case 't': + character = '\t'; + break; + case 'v': + character = '\v'; + break; + case 'f': + character = '\f'; + break; + case 'U': + case 'u': { + int sz = (character == 'u') ? 4 : 8; + settings_err_t res; + res = read_unicode_escape(file_handle, sz, vstr); + if (res != SETTINGS_OK) { + return res; + } + continue; + } + // default falls through, other escaped characters + // represent themselves + } + MP_FALLTHROUGH; + default: + vstr_add_byte_nonstd(vstr, character); + } + } +} + +// Read a bare value (non-quoted value) as a string +// Trims leading and trailing spaces/tabs, stops at # comment or newline +static settings_err_t read_bare_value(file_arg *file_handle, vstr_t *vstr, int first_character) { + int character = first_character; + size_t trailing_space_count = 0; + + while (true) { + switch (character) { + case 0: + case '\n': + // Remove trailing spaces/tabs and \r + vstr->len -= trailing_space_count; + return SETTINGS_OK; + case '#': + // Remove trailing spaces/tabs and \r before comment + vstr->len -= trailing_space_count; + next_line(file_handle); + return SETTINGS_OK; + case ' ': + case '\t': + case '\r': + // Track potential trailing whitespace + vstr_add_byte_nonstd(vstr, character); + trailing_space_count++; + break; + default: + // Non-whitespace character resets trailing space count + vstr_add_byte_nonstd(vstr, character); + trailing_space_count = 0; + } + character = get_next_byte(file_handle); + } +} + +static mp_int_t read_value(file_arg *file_handle, vstr_t *vstr, bool *quoted) { + uint8_t character; + character = consume_whitespace(file_handle); + *quoted = (character == '"'); + + if (*quoted) { + return read_string_value(file_handle, vstr); + } else if (character == '\n' || character == 0) { + // Empty value is an error + return SETTINGS_ERR_BAD_VALUE; + } else { + return read_bare_value(file_handle, vstr, character); + } +} + +static settings_err_t settings_get_vstr(const char *key, vstr_t *vstr, bool *quoted) { + file_arg file_handle; + if (!open_file(SETTINGS_PATH, &file_handle)) { + return SETTINGS_ERR_OPEN; + } + + settings_err_t result = SETTINGS_ERR_NOT_FOUND; + while (!is_eof(&file_handle)) { + if (key_matches(&file_handle, key)) { + result = read_value(&file_handle, vstr, quoted); + break; + } + } + close_file(&file_handle); + return result; +} + +static settings_err_t settings_get_buf_terminated(const char *key, char *value, size_t value_len, bool *quoted) { + vstr_t vstr; + vstr_init_fixed_buf(&vstr, value_len, value); + settings_err_t result = settings_get_vstr(key, &vstr, quoted); + + if (result == SETTINGS_OK) { + vstr_add_byte_nonstd(&vstr, 0); + memcpy(value, vstr.buf, MIN(vstr.len, value_len)); + if (vstr.len > value_len) { // this length includes trailing NUL + result = SETTINGS_ERR_LENGTH; + } + } + return result; +} + +static void print_error(const char *key, settings_err_t result) { + switch (result) { + case SETTINGS_OK: + case SETTINGS_ERR_OPEN: + case SETTINGS_ERR_NOT_FOUND: + // These errors need not be printed. + // The code asking for the value is not necessarily expecting to find one. + return; + default: + mp_cprintf(&mp_plat_print, MP_ERROR_TEXT("An error occurred while retrieving '%s':\n"), key); + break; + } + + switch (result) { + case SETTINGS_ERR_UNICODE: + mp_cprintf(&mp_plat_print, MP_ERROR_TEXT("Invalid unicode escape")); + break; + case SETTINGS_ERR_BAD_VALUE: + mp_cprintf(&mp_plat_print, MP_ERROR_TEXT("Invalid format")); + break; + default: + mp_cprintf(&mp_plat_print, MP_ERROR_TEXT("Internal error")); + break; + } + mp_printf(&mp_plat_print, "\n"); +} + + +static settings_err_t get_str(const char *key, char *value, size_t value_len) { + bool quoted; + settings_err_t result = settings_get_buf_terminated(key, value, value_len, "ed); + if (result == SETTINGS_OK && !quoted) { + result = SETTINGS_ERR_BAD_VALUE; + } + return result; +} + +settings_err_t settings_get_str(const char *key, char *value, size_t value_len) { + settings_err_t result = get_str(key, value, value_len); + print_error(key, result); + return result; +} + +static settings_err_t get_int(const char *key, mp_int_t *value) { + char buf[16]; + bool quoted; + settings_err_t result = settings_get_buf_terminated(key, buf, sizeof(buf), "ed); + if (result != SETTINGS_OK) { + return result; + } + if (quoted) { + return SETTINGS_ERR_BAD_VALUE; + } + char *end; + long num = strtol(buf, &end, 0); + while (unichar_isspace(*end)) { + end++; + } + if (end == buf || *end) { // If the whole buffer was not consumed it's an error + return SETTINGS_ERR_BAD_VALUE; + } + *value = (mp_int_t)num; + return SETTINGS_OK; +} + +settings_err_t settings_get_int(const char *key, mp_int_t *value) { + settings_err_t result = get_int(key, value); + print_error(key, result); + return result; +} + +static settings_err_t get_bool(const char *key, bool *value) { + char buf[16]; + bool quoted; + settings_err_t result = settings_get_buf_terminated(key, buf, sizeof(buf), "ed); + if (result != SETTINGS_OK) { + return result; + } + if (quoted) { + return SETTINGS_ERR_BAD_VALUE; + } + + // Check for "true" or "false" (case-sensitive) + if (strcmp(buf, "true") == 0) { + *value = true; + return SETTINGS_OK; + } else if (strcmp(buf, "false") == 0) { + *value = false; + return SETTINGS_OK; + } + + // Not a valid boolean value + return SETTINGS_ERR_BAD_VALUE; +} + +settings_err_t settings_get_bool(const char *key, bool *value) { + settings_err_t result = get_bool(key, value); + print_error(key, result); + return result; +} + +// Get the raw value as a vstr, whether quoted or bare. Value may be an invalid TOML value. +settings_err_t settings_get_raw_vstr(const char *key, vstr_t *vstr) { + bool quoted; + return settings_get_vstr(key, vstr, "ed); +} + +settings_err_t settings_get_obj(const char *key, mp_obj_t *value) { + vstr_t vstr; + vstr_init(&vstr, 32); + bool quoted; + + settings_err_t result = settings_get_vstr(key, &vstr, "ed); + if (result != SETTINGS_OK) { + return result; + } + + if (quoted) { + // Successfully parsed a quoted string + *value = mp_obj_new_str_from_vstr(&vstr); + return SETTINGS_OK; + } + + // Not a quoted string, try boolean + bool bool_val; + result = get_bool(key, &bool_val); + if (result == SETTINGS_OK) { + *value = mp_obj_new_bool(bool_val); + return SETTINGS_OK; + } + + // Not a boolean, try integer + mp_int_t int_val; + result = get_int(key, &int_val); + if (result == SETTINGS_OK) { + *value = mp_obj_new_int(int_val); + return SETTINGS_OK; + } + + return SETTINGS_ERR_BAD_VALUE; +} + +#endif diff --git a/supervisor/shared/settings.h b/supervisor/shared/settings.h new file mode 100644 index 0000000000000..eafa9962e9527 --- /dev/null +++ b/supervisor/shared/settings.h @@ -0,0 +1,53 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2022 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#pragma once + +#include "py/obj.h" + +typedef enum { + SETTINGS_OK = 0, + SETTINGS_ERR_OPEN, + SETTINGS_ERR_UNICODE, + SETTINGS_ERR_LENGTH, + SETTINGS_ERR_NOT_FOUND, + SETTINGS_ERR_BAD_VALUE, +} settings_err_t; + +// Read a string value from the settings file. +// If it fits, the return value is 0-terminated. The passed-in buffer +// may be modified even if an error is returned. Allocation free. +// An error that is not 'open' or 'not found' is printed on the repl. +// Returns an error if the value is not a quoted string. +settings_err_t settings_get_str(const char *key, char *value, size_t value_len); + +// Read an integer value from the settings file. +// Returns SETTINGS_OK and sets value to the read value. Returns +// SETTINGS_ERR_... if the value was not numeric. allocation-free. +// If any error code is returned, value is guaranteed not modified +// An error that is not 'open' or 'not found' is printed on the repl. +settings_err_t settings_get_int(const char *key, mp_int_t *value); + +// Read a boolean value from the settings file. +// Returns SETTINGS_OK and sets value to the read value. Returns +// SETTINGS_ERR_... if the value was not a boolean (true or false). allocation-free. +// If any error code is returned, value is guaranteed not modified +// An error that is not 'open' or 'not found' is printed on the repl. +settings_err_t settings_get_bool(const char *key, bool *value); + +// Read a value from the settings file and return as parsed Python object. +// Returns SETTINGS_OK and sets value to a parsed Python object from the RHS value: +// - Quoted strings return as str +// - Bare "true" or "false" return as bool +// - Valid integers return as int +// Returns SETTINGS_ERR_... if the value is not parseable as one of these types. +// An error that is not 'open' or 'not found' is printed on the repl. +settings_err_t settings_get_obj(const char *key, mp_obj_t *value); + +// Read the raw value as a string, whether quoted or bare. +// This is used by os.getenv() to always return strings. +// Does not print errors. +settings_err_t settings_get_raw_vstr(const char *key, vstr_t *vstr); diff --git a/supervisor/shared/stack.c b/supervisor/shared/stack.c index ebf99f425cc19..e7984f10d9fb0 100644 --- a/supervisor/shared/stack.c +++ b/supervisor/shared/stack.c @@ -13,17 +13,24 @@ #include "supervisor/shared/safe_mode.h" void stack_init(void) { + // Zephyr has a stack canary of its own. + #ifndef __ZEPHYR__ uint32_t *stack_limit = port_stack_get_limit(); *stack_limit = STACK_CANARY_VALUE; + #endif } inline bool stack_ok(void) { + #ifndef __ZEPHYR__ uint32_t *stack_limit = port_stack_get_limit(); return *stack_limit == STACK_CANARY_VALUE; + #endif } inline void assert_heap_ok(void) { + #ifndef __ZEPHYR__ if (!stack_ok()) { reset_into_safe_mode(SAFE_MODE_STACK_OVERFLOW); } + #endif } diff --git a/supervisor/shared/status_bar.c b/supervisor/shared/status_bar.c index 2a8f88d1a3f89..8e32eee033e86 100644 --- a/supervisor/shared/status_bar.c +++ b/supervisor/shared/status_bar.c @@ -25,6 +25,10 @@ #include "supervisor/shared/bluetooth/bluetooth.h" #endif +#if CIRCUITPY_USB_KEYBOARD_WORKFLOW +#include "supervisor/usb.h" +#endif + static background_callback_t status_bar_background_cb; static bool _forced_dirty = false; @@ -75,6 +79,10 @@ void supervisor_status_bar_update(void) { serial_write("\x1b" "]0;"); serial_write("🐍"); + #if CIRCUITPY_USB_KEYBOARD_WORKFLOW + usb_keyboard_status(); + #endif + #if CIRCUITPY_WEB_WORKFLOW supervisor_web_workflow_status(); serial_write(" | "); diff --git a/supervisor/shared/status_leds.c b/supervisor/shared/status_leds.c index e7b3d4b6e46d5..ca29fd79212cf 100644 --- a/supervisor/shared/status_leds.c +++ b/supervisor/shared/status_leds.c @@ -112,7 +112,7 @@ static uint32_t current_status_color = 0; #endif static bool status_led_init_in_progress = false; -void status_led_init() { +void status_led_init(void) { if (status_led_init_in_progress) { // Avoid recursion. return; @@ -133,9 +133,9 @@ void status_led_init() { memset(status_apa102_color + 4, 0xff, APA102_BUFFER_LENGTH - 4); #if CIRCUITPY_BITBANG_APA102 shared_module_bitbangio_spi_construct(&status_apa102, - MICROPY_HW_APA102_SCK, - MICROPY_HW_APA102_MOSI, - NULL); + MP_OBJ_FROM_PTR(MICROPY_HW_APA102_SCK), + MP_OBJ_FROM_PTR(MICROPY_HW_APA102_MOSI), + mp_const_none); #else if (!common_hal_busio_spi_deinited(&status_apa102)) { common_hal_busio_spi_deinit(&status_apa102); @@ -170,7 +170,7 @@ void status_led_init() { common_hal_pwmio_pwmout_construct(&rgb_status_b, CIRCUITPY_RGB_STATUS_B, 0, 50000, false); } - #elif defined(MICROPY_HW_LED_STATUS) + #elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS) common_hal_digitalio_digitalinout_construct(&single_color_led, MICROPY_HW_LED_STATUS); common_hal_digitalio_digitalinout_switch_to_output( &single_color_led, MICROPY_HW_LED_STATUS_INVERTED == 0, DRIVE_MODE_PUSH_PULL); @@ -186,7 +186,7 @@ void status_led_init() { status_led_init_in_progress = false; } -void status_led_deinit() { +void status_led_deinit(void) { #ifdef MICROPY_HW_NEOPIXEL // Make sure the pin stays low for the reset period. The pin reset may pull // it up and stop the reset period. @@ -216,7 +216,7 @@ void status_led_deinit() { common_hal_pwmio_pwmout_deinit(&rgb_status_b); } - #elif defined(MICROPY_HW_LED_STATUS) + #elif CIRCUITPY_DIGITALIO && defined(MICROPY_HW_LED_STATUS) common_hal_digitalio_digitalinout_deinit(&single_color_led); #endif diff --git a/supervisor/shared/tick.c b/supervisor/shared/tick.c index 24a06e622a181..346ef9a93c4c5 100644 --- a/supervisor/shared/tick.c +++ b/supervisor/shared/tick.c @@ -85,38 +85,49 @@ void supervisor_tick(void) { background_callback_add(&tick_callback, supervisor_background_tick, NULL); } -uint64_t supervisor_ticks_ms64() { +static uint64_t _get_raw_subticks(void) { + uint64_t ticks; + uint8_t subticks; + ticks = port_get_raw_ticks(&subticks); + return (ticks << 5) | subticks; +} + +uint64_t supervisor_ticks_ms64(void) { uint64_t result; result = port_get_raw_ticks(NULL); result = result * 1000 / 1024; return result; } -uint32_t supervisor_ticks_ms32() { +uint32_t supervisor_ticks_ms32(void) { return supervisor_ticks_ms64(); } void mp_hal_delay_ms(mp_uint_t delay_ms) { - uint64_t start_tick = port_get_raw_ticks(NULL); - // Adjust the delay to ticks vs ms. - uint64_t delay_ticks = (delay_ms * (uint64_t)1024) / 1000; - uint64_t end_tick = start_tick + delay_ticks; - int64_t remaining = delay_ticks; + uint64_t start_subtick = _get_raw_subticks(); + // Convert delay from ms to subticks + uint64_t delay_subticks = (delay_ms * (uint64_t)32768) / 1000; + uint64_t end_subtick = start_subtick + delay_subticks; + int64_t remaining = delay_subticks; // Loop until we've waited long enough or we've been CTRL-Ced by autoreload // or the user. while (remaining > 0 && !mp_hal_is_interrupted()) { RUN_BACKGROUND_TASKS; - remaining = end_tick - port_get_raw_ticks(NULL); - // We break a bit early so we don't risk setting the alarm before the time when we call - // sleep. - if (remaining < 1) { + // Exit if interrupted while running background tasks + if (mp_hal_is_interrupted()) { break; } - port_interrupt_after_ticks(remaining); - // Idle until an interrupt happens. - port_idle_until_interrupt(); - remaining = end_tick - port_get_raw_ticks(NULL); + // Recalculate remaining delay after running background tasks + remaining = end_subtick - _get_raw_subticks(); + // If remaining delay is less than 1 tick, idle loop until end of delay + int64_t remaining_ticks = remaining / 32; + if (remaining_ticks > 0) { + port_interrupt_after_ticks(remaining_ticks); + // Idle until an interrupt happens. + port_idle_until_interrupt(); + } + remaining = end_subtick - _get_raw_subticks(); } } diff --git a/supervisor/shared/usb.c b/supervisor/shared/usb.c new file mode 100644 index 0000000000000..ff0dd1f84672f --- /dev/null +++ b/supervisor/shared/usb.c @@ -0,0 +1,65 @@ +// This file is part of the CircuitPython project: https://circuitpython.org +// +// SPDX-FileCopyrightText: Copyright (c) 2025 Scott Shawcroft for Adafruit Industries +// +// SPDX-License-Identifier: MIT + +#include "supervisor/usb.h" + +#if CIRCUITPY_STORAGE +#include "shared-module/storage/__init__.h" +#endif + +#if CIRCUITPY_USB_DEVICE +#include "shared-bindings/supervisor/__init__.h" + +#if CIRCUITPY_USB_CDC +#include "shared-module/usb_cdc/__init__.h" +#endif + +#if CIRCUITPY_USB_HID +#include "shared-module/usb_hid/__init__.h" +#endif + +#if CIRCUITPY_USB_MIDI +#include "shared-module/usb_midi/__init__.h" +#endif + +#if CIRCUITPY_USB_VIDEO +#include "shared-module/usb_video/__init__.h" +#endif +#endif + +// Set up USB defaults before any USB changes are made in boot.py +void usb_set_defaults(void) { + #if CIRCUITPY_USB_DEVICE + #if CIRCUITPY_STORAGE && CIRCUITPY_USB_MSC + storage_usb_set_defaults(); + #endif + + #if CIRCUITPY_USB_CDC + usb_cdc_set_defaults(); + #endif + + #if CIRCUITPY_USB_HID + usb_hid_set_defaults(); + #endif + + #if CIRCUITPY_USB_MIDI + usb_midi_set_defaults(); + #endif + #endif +}; + +// Call this when ready to run code.py or a REPL, and a VM has been started. +void usb_setup_with_vm(void) { + #if CIRCUITPY_USB_DEVICE + #if CIRCUITPY_USB_HID + usb_hid_setup_devices(); + #endif + + #if CIRCUITPY_USB_MIDI + usb_midi_setup_ports(); + #endif + #endif +} diff --git a/supervisor/shared/usb/host_keyboard.c b/supervisor/shared/usb/host_keyboard.c index 78c3f3673ba02..f99b1e5c42a3a 100644 --- a/supervisor/shared/usb/host_keyboard.c +++ b/supervisor/shared/usb/host_keyboard.c @@ -12,6 +12,8 @@ #include "shared/runtime/interrupt_char.h" #include "supervisor/usb.h" #include "supervisor/background_callback.h" +#include "supervisor/shared/serial.h" +#include "supervisor/shared/status_bar.h" #include "supervisor/shared/tick.h" #ifndef DEBUG @@ -155,8 +157,9 @@ static void send_bufn_core(const char *buf, size_t n) { for (; n--; buf++) { int code = *buf; if (code == mp_interrupt_char) { + ringbuf_clear(&_incoming_ringbuf); mp_sched_keyboard_interrupt(); - return; + continue; } if (ringbuf_num_empty(&_incoming_ringbuf) == 0) { // Drop on the floor @@ -315,6 +318,7 @@ void usb_keyboard_detach(uint8_t dev_addr, uint8_t interface) { tuh_hid_receive_abort(dev_addr, interface); _dev_addr = 0; _interface = 0; + supervisor_status_bar_request_update(false); } void usb_keyboard_attach(uint8_t dev_addr, uint8_t interface) { @@ -327,6 +331,7 @@ void usb_keyboard_attach(uint8_t dev_addr, uint8_t interface) { _interface = interface; tuh_hid_receive_report(dev_addr, interface); } + supervisor_status_bar_request_update(false); } void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t interface, uint8_t const *desc_report, uint16_t desc_len) { @@ -361,3 +366,9 @@ char usb_keyboard_read_char(void) { } return -1; } + +void usb_keyboard_status(void) { + if (_dev_addr != 0 && _interface != 0) { + serial_write("🖮"); + } +} diff --git a/supervisor/shared/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h index a3ac3e3237d09..f2d800b99127e 100644 --- a/supervisor/shared/usb/tusb_config.h +++ b/supervisor/shared/usb/tusb_config.h @@ -55,7 +55,11 @@ extern "C" { // When debugging TinyUSB, only output to the console UART link. #if CIRCUITPY_DEBUG_TINYUSB > 0 && defined(CIRCUITPY_CONSOLE_UART) #define CFG_TUSB_DEBUG CIRCUITPY_DEBUG_TINYUSB +#ifdef __ZEPHYR__ +#define CFG_TUSB_DEBUG_PRINTF zephyr_printk +#else #define CFG_TUSB_DEBUG_PRINTF console_uart_printf +#endif // Raise the device log level to 3 so we can debug host-only at level 2. #define CFG_TUD_LOG_LEVEL 3 @@ -75,18 +79,22 @@ extern "C" { #if CIRCUITPY_USB_DEVICE -#if CIRCUITPY_USB_DEVICE_INSTANCE == 0 -#if USB_HIGHSPEED -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 +#define _DEVICE_SPEED OPT_MODE_HIGH_SPEED #else -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE) +#define _DEVICE_SPEED 0 #endif + +#if CIRCUITPY_USB_DEVICE_INSTANCE == 0 +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | _DEVICE_SPEED) #elif CIRCUITPY_USB_DEVICE_INSTANCE == 1 -#if USB_HIGHSPEED -#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) -#else -#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE) +#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | _DEVICE_SPEED) #endif + +// Use DMA with the USB peripheral. +#if defined(CONFIG_IDF_TARGET_ESP32P4) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) +#define CFG_TUD_DWC2_DMA_ENABLE (1) +#define CFG_TUH_DWC2_DMA_ENABLE (1) #endif // Vendor name included in Inquiry response, max 8 bytes @@ -147,27 +155,28 @@ extern "C" { #define CFG_TUH_RPI_PIO_USB 1 #endif -#if CIRCUITPY_USB_HOST_INSTANCE == 0 -#if USB_HIGHSPEED -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 +#define _HOST_SPEED OPT_MODE_HIGH_SPEED #else -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST) +#define _HOST_SPEED 0 #endif + +#if CIRCUITPY_USB_HOST_INSTANCE == 0 +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | _HOST_SPEED) #elif CIRCUITPY_USB_HOST_INSTANCE == 1 -#if USB_HIGHSPEED -#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) -#else -#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_HOST) -#endif +#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_HOST | _HOST_SPEED) #endif // Size of buffer to hold descriptors and other data used for enumeration +// CircuitPython itself is 284 bytes of configuration descriptor when both CDC endpoints are +// enabled, plus 4 bytes for alignment. #ifndef CFG_TUH_ENUMERATION_BUFSIZE -#define CFG_TUH_ENUMERATION_BUFSIZE 256 +#define CFG_TUH_ENUMERATION_BUFSIZE (284 + 4) #endif #if CIRCUITPY_USB_KEYBOARD_WORKFLOW -#define CFG_TUH_HID 2 +// One keyboard, one mouse and two other HID like gamepad. +#define CFG_TUH_HID 4 #else #define CFG_TUH_HID 0 #endif @@ -190,6 +199,11 @@ extern "C" { #endif +// Hack to work with older nrfx than what TinyUSB is designed for. +#define nrf52_errata_187 errata_187 +#define nrf52_errata_171 errata_171 +#define nrf52_errata_166 errata_166 + #ifdef __cplusplus } #endif diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index b87cf78e903d8..5061fee00633e 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -7,6 +7,8 @@ #include "py/objstr.h" #include "supervisor/background_callback.h" #include "supervisor/linker.h" +#include "supervisor/port.h" +#include "supervisor/shared/tick.h" #include "supervisor/usb.h" #include "shared/readline/readline.h" @@ -41,10 +43,59 @@ #include "tusb.h" +#if CFG_TUSB_OS == OPT_OS_ZEPHYR +#include +int CFG_TUSB_DEBUG_PRINTF(const char *format, ...) { + va_list args; + va_start(args, format); + printk(format, args); + va_end(args); + return 0; +} + +#ifdef CFG_TUSB_DEBUG + #define USBD_STACK_SIZE (5 * CONFIG_IDLE_STACK_SIZE) +#else + #define USBD_STACK_SIZE (5 * CONFIG_IDLE_STACK_SIZE / 2) +#endif + +struct k_thread tinyusb_thread_data; +K_THREAD_STACK_DEFINE(tinyusb_thread_stack, USBD_STACK_SIZE); +k_tid_t _tinyusb_tid; + +// USB Device Driver task +// This top level thread process all usb events and invoke callbacks +static void tinyusb_thread(void *unused0, void *unused1, void *unused2) { + (void)unused0; + (void)unused1; + (void)unused2; + + // RTOS forever loop + while (1) { + // tinyusb device task + if (tusb_inited()) { + tud_task(); + tud_cdc_write_flush(); + } else { + k_sleep(K_MSEC(1000)); + } + } +} + +#endif + bool usb_enabled(void) { return tusb_inited(); } +bool usb_connected(void) { + #if CIRCUITPY_TINYUSB && CIRCUITPY_USB_DEVICE + return tud_ready(); + #else + return false; + #endif +} + MP_WEAK void post_usb_init(void) { } @@ -91,39 +142,14 @@ void usb_init(void) { tud_cdc_set_wanted_char(CHAR_CTRL_C); } #endif -} -// Set up USB defaults before any USB changes are made in boot.py -void usb_set_defaults(void) { - #if CIRCUITPY_USB_DEVICE - #if CIRCUITPY_STORAGE && CIRCUITPY_USB_MSC - storage_usb_set_defaults(); - #endif - - #if CIRCUITPY_USB_CDC - usb_cdc_set_defaults(); - #endif - - #if CIRCUITPY_USB_HID - usb_hid_set_defaults(); - #endif - - #if CIRCUITPY_USB_MIDI - usb_midi_set_defaults(); - #endif - #endif -}; - -// Call this when ready to run code.py or a REPL, and a VM has been started. -void usb_setup_with_vm(void) { - #if CIRCUITPY_USB_DEVICE - #if CIRCUITPY_USB_HID - usb_hid_setup_devices(); - #endif - - #if CIRCUITPY_USB_MIDI - usb_midi_setup_ports(); - #endif + #if CFG_TUSB_OS == OPT_OS_ZEPHYR + _tinyusb_tid = k_thread_create(&tinyusb_thread_data, tinyusb_thread_stack, + K_THREAD_STACK_SIZEOF(tinyusb_thread_stack), + tinyusb_thread, + NULL, NULL, NULL, + CONFIG_MAIN_THREAD_PRIORITY - 1, 0, K_NO_WAIT); + k_thread_name_set(_tinyusb_tid, "tinyusb"); #endif } @@ -135,9 +161,8 @@ void usb_background(void) { tuh_task(); #endif #elif CFG_TUSB_OS == OPT_OS_FREERTOS - // Yield to FreeRTOS in case TinyUSB runs in a separate task. Don't use - // port_yield() because it has a longer delay. - vTaskDelay(0); + // TinyUSB may run in a separate task, at the same priority as CircuitPython. + port_task_yield(); #endif // No need to flush if there's no REPL. #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_CDC @@ -152,6 +177,10 @@ void usb_background(void) { } } +uint32_t tusb_time_millis_api(void) { + return supervisor_ticks_ms32(); +} + static background_callback_t usb_callback; static void usb_background_do(void *unused) { usb_background(); diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c index c4e182ff1e5d9..9427171fe9b98 100644 --- a/supervisor/shared/usb/usb_desc.c +++ b/supervisor/shared/usb/usb_desc.c @@ -137,9 +137,13 @@ static bool usb_build_configuration_descriptor(void) { #endif #if CIRCUITPY_USB_MSC + #if CIRCUITPY_STORAGE if (storage_usb_enabled()) { - total_descriptor_length += storage_usb_descriptor_length(); - } + #endif + total_descriptor_length += usb_msc_descriptor_length(); + #if CIRCUITPY_STORAGE +} + #endif #endif #if CIRCUITPY_USB_HID @@ -210,11 +214,15 @@ static bool usb_build_configuration_descriptor(void) { #endif #if CIRCUITPY_USB_MSC + #if CIRCUITPY_STORAGE if (storage_usb_enabled()) { - // Concatenate and fix up the MSC descriptor. - descriptor_buf_remaining += storage_usb_add_descriptor( - descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); - } + #endif + // Concatenate and fix up the MSC descriptor. + descriptor_buf_remaining += usb_msc_add_descriptor( + descriptor_buf_remaining, &descriptor_counts, ¤t_interface_string); + #if CIRCUITPY_STORAGE +} + #endif #endif #if CIRCUITPY_USB_HID diff --git a/supervisor/shared/usb/usb_device.c b/supervisor/shared/usb/usb_device.c index ec08b8bf4d7e2..16ae137eddefb 100644 --- a/supervisor/shared/usb/usb_device.c +++ b/supervisor/shared/usb/usb_device.c @@ -166,6 +166,9 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ * @param wanted_char The wanted char (set previously) */ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { + // CircuitPython's VM is run in a separate FreeRTOS task from TinyUSB on ESP. + // So, we must notify the other task when a CTRL-C is received. + port_wake_main_task(); // Workaround for using shared/runtime/interrupt_char.c // Compare mp_interrupt_char with wanted_char and ignore if not matched if (mp_interrupt_char == wanted_char) { @@ -177,7 +180,14 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) { void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms) { if (usb_cdc_console_enabled() && mp_interrupt_char != -1 && itf == 0 && duration_ms > 0) { mp_sched_keyboard_interrupt(); + port_wake_main_task(); } } +void tud_cdc_rx_cb(uint8_t itf) { + (void)itf; + // Workaround for "press any key to enter REPL" response being delayed on espressif. + // Wake main task when any key is pressed. + port_wake_main_task(); +} #endif diff --git a/supervisor/shared/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index 201a818c0bf71..5ea457ef328cc 100644 --- a/supervisor/shared/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -5,14 +5,15 @@ // SPDX-License-Identifier: MIT #include "tusb.h" -// // #include "supervisor/flash.h" // For updating fatfs's cache #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "lib/oofatfs/diskio.h" #include "lib/oofatfs/ff.h" +#include "py/gc.h" #include "py/mpstate.h" +#include "py/runtime.h" #include "shared-module/storage/__init__.h" #include "supervisor/filesystem.h" @@ -20,28 +21,154 @@ #define MSC_FLASH_BLOCK_SIZE 512 -static bool ejected[1] = {true}; -static bool locked[1] = {false}; +#if CIRCUITPY_SAVES_PARTITION_SIZE > 0 +#define SAVES_COUNT 1 +#define SAVES_LUN (1) +#else +#define SAVES_COUNT 0 +#endif -// The root FS is always at the end of the list. +#if CIRCUITPY_SDCARD_USB +#include "shared-module/sdcardio/__init__.h" + +#define SDCARD_COUNT 1 +#define SDCARD_LUN (1 + SAVES_COUNT) +#else +#define SDCARD_COUNT 0 +#endif + +#define LUN_COUNT (1 + SAVES_COUNT + SDCARD_COUNT) + +// The ellipsis range in the designated initializer of `ejected` is not standard C, +// but it works in both gcc and clang. +static bool ejected[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = true}; +static bool eject_once[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; +static bool locked[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; + +// Set to true if a write was in a file data or metadata area, +// as opposed to in the filesystem metadata area (e.g., dirty bit). +// Used to determine if an auto-reload is warranted. +static bool content_write[LUN_COUNT] = { [0 ... (LUN_COUNT - 1)] = false}; + +#include "tusb.h" + +static const uint8_t usb_msc_descriptor_template[] = { + // MSC Interface Descriptor + 0x09, // 0 bLength + 0x04, // 1 bDescriptorType (Interface) + 0xFF, // 2 bInterfaceNumber [SET AT RUNTIME] +#define MSC_INTERFACE_INDEX (2) + 0x00, // 3 bAlternateSetting + 0x02, // 4 bNumEndpoints 2 + 0x08, // 5 bInterfaceClass: MSC + 0x06, // 6 bInterfaceSubClass: TRANSPARENT + 0x50, // 7 bInterfaceProtocol: BULK + 0xFF, // 8 iInterface (String Index) [SET AT RUNTIME] +#define MSC_INTERFACE_STRING_INDEX (8) + + // MSC Endpoint IN Descriptor + 0x07, // 9 bLength + 0x05, // 10 bDescriptorType (Endpoint) + 0xFF, // 11 bEndpointAddress (IN/D2H) [SET AT RUNTIME: 0x80 | number] +#define MSC_IN_ENDPOINT_INDEX (11) + 0x02, // 12 bmAttributes (Bulk) + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 + 0x00, 0x02, // 13,14 wMaxPacketSize 512 + #else + 0x40, 0x00, // 13,14 wMaxPacketSize 64 + #endif + 0x00, // 15 bInterval 0 (unit depends on device speed) + + // MSC Endpoint OUT Descriptor + 0x07, // 16 bLength + 0x05, // 17 bDescriptorType (Endpoint) + 0xFF, // 18 bEndpointAddress (OUT/H2D) [SET AT RUNTIME] +#define MSC_OUT_ENDPOINT_INDEX (18) + 0x02, // 19 bmAttributes (Bulk) + #if CIRCUITPY_USB_DEVICE_HIGH_SPEED == 1 + 0x00, 0x02, // 20,21 wMaxPacketSize 512 + #else + 0x40, 0x00, // 20,21 wMaxPacketSize 64 + #endif + 0x00, // 22 bInterval 0 (unit depends on device speed) +}; + +size_t usb_msc_descriptor_length(void) { + return sizeof(usb_msc_descriptor_template); +} + +static const char storage_interface_name[] = USB_INTERFACE_NAME " Mass Storage"; + +size_t usb_msc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string) { + memcpy(descriptor_buf, usb_msc_descriptor_template, sizeof(usb_msc_descriptor_template)); + descriptor_buf[MSC_INTERFACE_INDEX] = descriptor_counts->current_interface; + descriptor_counts->current_interface++; + + descriptor_buf[MSC_IN_ENDPOINT_INDEX] = + 0x80 | (USB_MSC_EP_NUM_IN ? USB_MSC_EP_NUM_IN : descriptor_counts->current_endpoint); + descriptor_counts->num_in_endpoints++; + // Some TinyUSB devices have issues with bi-directional endpoints + #ifdef TUD_ENDPOINT_ONE_DIRECTION_ONLY + descriptor_counts->current_endpoint++; + #endif + + descriptor_buf[MSC_OUT_ENDPOINT_INDEX] = + USB_MSC_EP_NUM_OUT ? USB_MSC_EP_NUM_OUT : descriptor_counts->current_endpoint; + descriptor_counts->num_out_endpoints++; + descriptor_counts->current_endpoint++; + + usb_add_interface_string(*current_interface_string, storage_interface_name); + descriptor_buf[MSC_INTERFACE_STRING_INDEX] = *current_interface_string; + (*current_interface_string)++; + + return sizeof(usb_msc_descriptor_template); +} + +// We hardcode LUN -> mount mapping so that it doesn't changes with saves and +// SD card appearing and disappearing. static fs_user_mount_t *get_vfs(int lun) { - // TODO(tannewt): Return the mount which matches the lun where 0 is the end - // and is counted in reverse. - if (lun > 0) { - return NULL; + fs_user_mount_t *root = filesystem_circuitpy(); + if (lun == 0) { + return root; } - mp_vfs_mount_t *current_mount = MP_STATE_VM(vfs_mount_table); - if (current_mount == NULL) { - return NULL; + // Other filesystems must be native because we don't guard against exceptions. + // They must also be off the VM heap so they don't disappear on autoreload. + #ifdef SAVES_LUN + if (lun == SAVES_LUN) { + const char *path_under_mount; + fs_user_mount_t *saves = filesystem_for_path("/saves", &path_under_mount); + if (saves != root && + (saves->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0 && !gc_ptr_on_heap(saves)) { + return saves; + } } - while (current_mount->next != NULL) { - current_mount = current_mount->next; + #endif + #ifdef SDCARD_LUN + if (lun == SDCARD_LUN) { + const char *path_under_mount; + fs_user_mount_t *sdcard = filesystem_for_path("/sd", &path_under_mount); + // If sdcard ("/sd") is on the root filesystem, nothing has been mounted there, so don't + // return it as a separate filesystem. + // If the SD card was automounted at startup, then it persists across VMs and its fs_user_mount_t is + // not on the heap. + // If the SD card filesystem was mounted by the user using heap objects, + // it should not be used when the VM has stopped running. + if ((sdcard != root) && + ((sdcard->blockdev.flags & MP_BLOCKDEV_FLAG_NATIVE) != 0) && + (vm_is_running() || !gc_ptr_on_heap(sdcard))) { + return sdcard; + } else { + // Clear any ejected state so that a re-insert causes it to reappear. + ejected[SDCARD_LUN] = false; + locked[SDCARD_LUN] = false; + } } - return current_mount->obj; + #endif + return NULL; } static void _usb_msc_uneject(void) { - for (uint8_t i = 0; i < sizeof(ejected); i++) { + for (uint8_t i = 0; i < LUN_COUNT; i++) { ejected[i] = false; locked[i] = false; } @@ -52,8 +179,8 @@ void usb_msc_mount(void) { } void usb_msc_umount(void) { - for (uint8_t i = 0; i < sizeof(ejected); i++) { - fs_user_mount_t *vfs = get_vfs(i + 1); + for (uint8_t i = 0; i < LUN_COUNT; i++) { + fs_user_mount_t *vfs = get_vfs(i); if (vfs == NULL) { continue; } @@ -62,18 +189,26 @@ void usb_msc_umount(void) { } } -bool usb_msc_ejected(void) { - bool all_ejected = true; - for (uint8_t i = 0; i < sizeof(ejected); i++) { - all_ejected &= ejected[i]; +void usb_msc_remount(fs_user_mount_t *fs_mount) { + for (uint8_t i = 0; i < LUN_COUNT; i++) { + fs_user_mount_t *vfs = get_vfs(i); + if (vfs == NULL || vfs != fs_mount) { + continue; + } + ejected[i] = false; + eject_once[i] = true; } - return all_ejected; +} + +uint8_t tud_msc_get_maxlun_cb(void) { + return LUN_COUNT; } // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 have their own callbacks int32_t tud_msc_scsi_cb(uint8_t lun, const uint8_t scsi_cmd[16], void *buffer, uint16_t bufsize) { + // Note that no command uses a response right now. const void *response = NULL; int32_t resplen = 0; @@ -107,12 +242,14 @@ int32_t tud_msc_scsi_cb(uint8_t lun, const uint8_t scsi_cmd[16], void *buffer, u void tud_msc_capacity_cb(uint8_t lun, uint32_t *block_count, uint16_t *block_size) { fs_user_mount_t *vfs = get_vfs(lun); - disk_ioctl(vfs, GET_SECTOR_COUNT, block_count); - disk_ioctl(vfs, GET_SECTOR_SIZE, block_size); + if (vfs != NULL) { + disk_ioctl(vfs, GET_SECTOR_COUNT, block_count); + disk_ioctl(vfs, GET_SECTOR_SIZE, block_size); + } } bool tud_msc_is_writable_cb(uint8_t lun) { - if (lun > 1) { + if (lun >= LUN_COUNT) { return false; } @@ -120,7 +257,7 @@ bool tud_msc_is_writable_cb(uint8_t lun) { if (vfs == NULL) { return false; } - if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL || !filesystem_is_writable_by_usb(vfs)) { + if (!filesystem_is_writable_by_usb(vfs)) { return false; } // Lock the blockdev once we say we're writable. @@ -139,6 +276,9 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void *buff const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; fs_user_mount_t *vfs = get_vfs(lun); + if (vfs == NULL) { + return -1; + } uint32_t disk_block_count; disk_ioctl(vfs, GET_SECTOR_COUNT, &disk_block_count); @@ -161,16 +301,22 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; fs_user_mount_t *vfs = get_vfs(lun); + if (vfs == NULL) { + return -1; + } + disk_write(vfs, buffer, lba, block_count); // Since by getting here we assume the mount is read-only to - // MicroPython let's update the cached FatFs sector if it's the one + // CircuitPython let's update the cached FatFs sector if it's the one // we just wrote. + if #if FF_MAX_SS != FF_MIN_SS - if (vfs->fatfs.ssize == MSC_FLASH_BLOCK_SIZE) { + (vfs->fatfs.ssize == MSC_FLASH_BLOCK_SIZE) #else // The compiler can optimize this away. - if (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE) { - #endif + (FF_MAX_SS == FILESYSTEM_BLOCK_SIZE) + #endif + { if (lba == vfs->fatfs.winsect && lba > 0) { memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), @@ -178,17 +324,30 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t * } } + // A write to an lba below fatbase is in the filesystem metadata (BPB) area or the "Reserved Region", + // and is probably setting or clearing the dirty bit. This should not trigger auto-reload. + // All other writes will trigger auto-reload. + if (lba >= vfs->fatfs.fatbase) { + content_write[lun] = true; + } + return block_count * MSC_FLASH_BLOCK_SIZE; } // Callback invoked when WRITE10 command is completed (status received and accepted by host). // used to flush any pending cache. void tud_msc_write10_complete_cb(uint8_t lun) { - (void)lun; - - // This write is complete; initiate an autoreload. autoreload_resume(AUTORELOAD_SUSPEND_USB); - autoreload_trigger(); + + // This write is complete; initiate an autoreload if this was a file data or metadata write, + // not just a dirty-bit write. + if (content_write[lun] && + // Fast path: lun == 0 is CIRCUITPY, which can always trigger auto-reload if enabled. + // Don't autoreload if this lun was mounted by the user: that will cause a VM stop and an unmount. + (lun == 0 || !gc_ptr_on_heap(get_vfs(lun)))) { + autoreload_trigger(); + content_write[lun] = false; + } } // Invoked when received SCSI_CMD_INQUIRY @@ -204,15 +363,22 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 // Invoked when received Test Unit Ready command. // return true allowing host to read/write this LUN e.g SD card inserted bool tud_msc_test_unit_ready_cb(uint8_t lun) { - if (lun > 1) { + if (lun >= LUN_COUNT) { return false; } + #ifdef SDCARD_LUN + if (lun == SDCARD_LUN) { + automount_sd_card(); + } + #endif + fs_user_mount_t *current_mount = get_vfs(lun); if (current_mount == NULL) { return false; } - if (ejected[lun]) { + if (ejected[lun] || eject_once[lun]) { + eject_once[lun] = false; // Set 0x3a for media not present. tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3A, 0x00); return false; @@ -225,7 +391,7 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) { // - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage // - Start = 1 : active mode, if load_eject = 1 : load disk storage bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) { - if (lun > 1) { + if (lun >= LUN_COUNT) { return false; } fs_user_mount_t *current_mount = get_vfs(lun); diff --git a/supervisor/shared/web_workflow/static/directory.js b/supervisor/shared/web_workflow/static/directory.js index 91c4c110b4618..1841993714281 100644 --- a/supervisor/shared/web_workflow/static/directory.js +++ b/supervisor/shared/web_workflow/static/directory.js @@ -191,7 +191,17 @@ async function mkdir(e) { } } +const beforeUnloadHandler = function(event){ + // Recommended + event.preventDefault(); + + // Included for legacy support, e.g. Chrome/Edge < 119 + event.returnValue = true; +} + async function upload(e) { + const upload_path = current_path; + window.addEventListener("beforeunload", beforeUnloadHandler); set_upload_enabled(false); let progress = document.querySelector("#progress"); let made_dirs = new Set(); @@ -213,7 +223,7 @@ async function upload(e) { made_dirs.add(parent_dir); } } - let file_path = new URL("/fs" + current_path + file_name, url_base); + let file_path = new URL("/fs" + upload_path + file_name, url_base); const response = await fetch(file_path, { method: "PUT", @@ -242,6 +252,7 @@ async function upload(e) { files.value = ""; dirs.value = ""; set_upload_enabled(true); + window.removeEventListener("beforeunload", beforeUnloadHandler); } async function del(e) { diff --git a/supervisor/shared/web_workflow/static/serial.js b/supervisor/shared/web_workflow/static/serial.js index 52cde953961cf..c8ee2537bae7d 100644 --- a/supervisor/shared/web_workflow/static/serial.js +++ b/supervisor/shared/web_workflow/static/serial.js @@ -43,6 +43,8 @@ ws.onmessage = function(e) { } else if (e.data == "\x1b[K") { // Clear line log.textContent = log.textContent.slice(0, -left_count); left_count = 0; + } else if (e.data == "\x1b[2K\x1b[0G") { + // ignore } else { log.textContent += e.data; } diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index 45d3c21163ace..a14f79a5bb47f 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -8,6 +8,8 @@ #define _GNU_SOURCE #include +#include +#include #include #include "extmod/vfs.h" @@ -42,12 +44,16 @@ #include "shared-bindings/socketpool/Socket.h" #include "shared-bindings/socketpool/SocketPool.h" +#if CIRCUITPY_HOSTNETWORK +#include "bindings/hostnetwork/__init__.h" +#endif + #if CIRCUITPY_WIFI #include "shared-bindings/wifi/__init__.h" #endif -#if CIRCUITPY_OS_GETENV -#include "shared-module/os/__init__.h" +#if CIRCUITPY_SETTINGS_TOML +#include "supervisor/shared/settings.h" #endif enum request_state { @@ -84,12 +90,18 @@ typedef struct { char websocket_key[24 + 1]; } _request; +#if CIRCUITPY_WIFI static wifi_radio_error_t _wifi_status = WIFI_RADIO_ERROR_NONE; +#endif -#if CIRCUITPY_STATUS_BAR +#if CIRCUITPY_STATUS_BAR && (CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK) // Store various last states to compute if status bar needs an update. static bool _last_enabled = false; static uint32_t _last_ip = 0; +static mp_int_t _last_web_api_port = 80; +#endif + +#if CIRCUITPY_STATUS_BAR && CIRCUITPY_WIFI static wifi_radio_error_t _last_wifi_status = WIFI_RADIO_ERROR_NONE; #endif @@ -171,11 +183,7 @@ static bool _base64_in_place(char *buf, size_t in_len, size_t out_len) { return true; } -static void _update_encoded_ip(void) { - uint32_t ipv4_address = 0; - if (common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { - ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); - } +static void _update_encoded_ip(uint32_t ipv4_address) { if (_encoded_ip != ipv4_address) { uint8_t *octets = (uint8_t *)&ipv4_address; snprintf(_our_ip_encoded, sizeof(_our_ip_encoded), "%d.%d.%d.%d", octets[0], octets[1], octets[2], octets[3]); @@ -183,75 +191,127 @@ static void _update_encoded_ip(void) { } } +static bool _get_web_workflow_ip(uint32_t *ipv4_address) { + *ipv4_address = 0; + #if CIRCUITPY_WIFI + if (!common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj)) { + return false; + } + *ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); + return true; + #elif CIRCUITPY_HOSTNETWORK + // hostnetwork uses the host network namespace and is reachable via localhost. + *ipv4_address = 0x0100007f; // 127.0.0.1 + return true; + #else + return false; + #endif +} + +#if CIRCUITPY_STATUS_BAR +static void _print_web_workflow_endpoint(void) { + mp_printf(&mp_plat_print, "%s", _our_ip_encoded); + if (web_api_port != 80) { + mp_printf(&mp_plat_print, ":%d", web_api_port); + } +} +#endif + mdns_server_obj_t *supervisor_web_workflow_mdns(mp_obj_t network_interface) { - #if CIRCUITPY_MDNS + #if CIRCUITPY_MDNS && CIRCUITPY_WIFI if (network_interface == &common_hal_wifi_radio_obj && mdns.base.type == &mdns_server_type) { return &mdns; } #endif + (void)network_interface; return NULL; } #if CIRCUITPY_STATUS_BAR bool supervisor_web_workflow_status_dirty(void) { - return common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj) != _last_enabled || - _encoded_ip != _last_ip || - _last_wifi_status != _wifi_status; + #if CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK + uint32_t ipv4_address = 0; + bool enabled = _get_web_workflow_ip(&ipv4_address); + if (enabled != _last_enabled || ipv4_address != _last_ip || web_api_port != _last_web_api_port) { + return true; + } + #if CIRCUITPY_WIFI + if (_last_wifi_status != _wifi_status) { + return true; + } + #endif + return false; + #else + return false; + #endif } #endif #if CIRCUITPY_STATUS_BAR void supervisor_web_workflow_status(void) { - _last_enabled = common_hal_wifi_radio_get_enabled(&common_hal_wifi_radio_obj); + #if CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK + uint32_t ipv4_address = 0; + _last_enabled = _get_web_workflow_ip(&ipv4_address); + _last_web_api_port = web_api_port; + if (_last_enabled) { - uint32_t ipv4_address = wifi_radio_get_ipv4_address(&common_hal_wifi_radio_obj); + _update_encoded_ip(ipv4_address); + _last_ip = _encoded_ip; + if (ipv4_address != 0) { - _update_encoded_ip(); - _last_ip = _encoded_ip; - mp_printf(&mp_plat_print, "%s", _our_ip_encoded); - if (web_api_port != 80) { - mp_printf(&mp_plat_print, ":%d", web_api_port); - } + _print_web_workflow_endpoint(); // TODO: Use these unicode to show signal strength: ▂▄▆█ return; } - serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); - _last_wifi_status = _wifi_status; - if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE || - _wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) { - serial_write_compressed(MP_ERROR_TEXT("Authentication failure")); - } else if (_wifi_status != WIFI_RADIO_ERROR_NONE) { - mp_printf(&mp_plat_print, "%d", _wifi_status); - } else if (ipv4_address == 0) { - _last_ip = 0; - serial_write_compressed(MP_ERROR_TEXT("No IP")); - } else { - } - } else { - // Keep Wi-Fi print separate so its data can be matched with the one above. - serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); + } + + #if CIRCUITPY_WIFI + serial_write_compressed(MP_ERROR_TEXT("Wi-Fi: ")); + _last_wifi_status = _wifi_status; + if (!_last_enabled) { serial_write_compressed(MP_ERROR_TEXT("off")); + } else if (_wifi_status == WIFI_RADIO_ERROR_AUTH_EXPIRE || + _wifi_status == WIFI_RADIO_ERROR_AUTH_FAIL) { + serial_write_compressed(MP_ERROR_TEXT("Authentication failure")); + } else if (_wifi_status != WIFI_RADIO_ERROR_NONE) { + mp_printf(&mp_plat_print, "%d", _wifi_status); + } else { + _last_ip = 0; + serial_write_compressed(MP_ERROR_TEXT("No IP")); } + #endif + #else + return; + #endif } #endif bool supervisor_start_web_workflow(void) { - #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_WIFI && CIRCUITPY_OS_GETENV + #if CIRCUITPY_WEB_WORKFLOW && CIRCUITPY_SETTINGS_TOML && (CIRCUITPY_WIFI || CIRCUITPY_HOSTNETWORK) + #if CIRCUITPY_WIFI + mp_obj_t socketpool_radio = MP_OBJ_FROM_PTR(&common_hal_wifi_radio_obj); + #else + mp_obj_t socketpool_radio = MP_OBJ_FROM_PTR(&common_hal_hostnetwork_obj); + #endif + + settings_err_t result; + + #if CIRCUITPY_WIFI char ssid[33]; char password[64]; - os_getenv_err_t result = common_hal_os_getenv_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); - if (result != GETENV_OK) { + result = settings_get_str("CIRCUITPY_WIFI_SSID", ssid, sizeof(ssid)); + if (result != SETTINGS_OK || strlen(ssid) < 1) { return false; } - result = common_hal_os_getenv_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); - if (result == GETENV_ERR_NOT_FOUND) { + result = settings_get_str("CIRCUITPY_WIFI_PASSWORD", password, sizeof(password)); + if (result == SETTINGS_ERR_NOT_FOUND) { // if password is unspecified, assume an open network password[0] = '\0'; - } else if (result != GETENV_OK) { + } else if (result != SETTINGS_OK) { return false; } @@ -275,6 +335,7 @@ bool supervisor_start_web_workflow(void) { common_hal_wifi_radio_set_enabled(&common_hal_wifi_radio_obj, false); return false; } + #endif // Skip starting the workflow if we're not starting from power on or reset. const mcu_reset_reason_t reset_reason = common_hal_mcu_processor_get_reset_reason(); @@ -289,17 +350,17 @@ bool supervisor_start_web_workflow(void) { bool initialized = pool.base.type == &socketpool_socketpool_type; if (!initialized) { - result = common_hal_os_getenv_str("CIRCUITPY_WEB_INSTANCE_NAME", web_instance_name, sizeof(web_instance_name)); - if (result != GETENV_OK || web_instance_name[0] == '\0') { + result = settings_get_str("CIRCUITPY_WEB_INSTANCE_NAME", web_instance_name, sizeof(web_instance_name)); + if (result != SETTINGS_OK || web_instance_name[0] == '\0') { strcpy(web_instance_name, MICROPY_HW_BOARD_NAME); } // (leaves new_port unchanged on any failure) - (void)common_hal_os_getenv_int("CIRCUITPY_WEB_API_PORT", &web_api_port); + (void)settings_get_int("CIRCUITPY_WEB_API_PORT", &web_api_port); const size_t api_password_len = sizeof(_api_password) - 1; - result = common_hal_os_getenv_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); - if (result == GETENV_OK) { + result = settings_get_str("CIRCUITPY_WEB_API_PASSWORD", _api_password + 1, api_password_len); + if (result == SETTINGS_OK) { _api_password[0] = ':'; _base64_in_place(_api_password, strlen(_api_password), sizeof(_api_password) - 1); } else { // Skip starting web-workflow when no password is passed. @@ -307,7 +368,7 @@ bool supervisor_start_web_workflow(void) { } pool.base.type = &socketpool_socketpool_type; - common_hal_socketpool_socketpool_construct(&pool, &common_hal_wifi_radio_obj); + common_hal_socketpool_socketpool_construct(&pool, socketpool_radio); socketpool_socket_reset(&listening); socketpool_socket_reset(&active); @@ -373,7 +434,7 @@ void web_workflow_send_raw(socketpool_socket_obj_t *socket, bool flush, const ui total_sent += sent; if (total_sent < len) { // Yield so that network code can run. - port_yield(); + port_task_sleep_ms(4); } } } @@ -847,7 +908,9 @@ static void _reply_with_version_json(socketpool_socket_obj_t *socket, _request * instance_name = common_hal_mdns_server_get_instance_name(&mdns); } #endif - _update_encoded_ip(); + uint32_t ipv4_address = 0; + (void)_get_web_workflow_ip(&ipv4_address); + _update_encoded_ip(ipv4_address); // Note: this leverages the fact that C concats consecutive string literals together. mp_printf(&_socket_print, "{\"web_api_version\": 4, " @@ -1085,6 +1148,10 @@ static void _reply_static(socketpool_socket_obj_t *socket, _request *request, co "Content-Encoding: gzip\r\n", "Content-Length: ", encoded_len, "\r\n", "Content-Type: ", content_type, "\r\n", + #if CIRCUITPY_DEBUG == 0 + "Cache-Control: max-age=31536000\r\n", // Cache for a year. + "Vary: Accept\r\n", + #endif "\r\n", NULL); web_workflow_send_raw(socket, true, response, response_len); } diff --git a/supervisor/shared/web_workflow/web_workflow.h b/supervisor/shared/web_workflow/web_workflow.h index 439964dd333ac..9ec15a14ddc48 100644 --- a/supervisor/shared/web_workflow/web_workflow.h +++ b/supervisor/shared/web_workflow/web_workflow.h @@ -8,7 +8,12 @@ #include +#if CIRCUITPY_MDNS #include "shared-bindings/mdns/Server.h" +#else +typedef struct mdns_server_obj mdns_server_obj_t; +#endif + #include "shared-bindings/socketpool/Socket.h" // This background function should be called repeatedly. It cannot be done based diff --git a/supervisor/shared/web_workflow/websocket.c b/supervisor/shared/web_workflow/websocket.c index accd2398e1e59..67b003b18a4f6 100644 --- a/supervisor/shared/web_workflow/websocket.c +++ b/supervisor/shared/web_workflow/websocket.c @@ -227,6 +227,7 @@ void websocket_background(void) { while (ringbuf_num_empty(&_incoming_ringbuf) > 0 && _read_next_payload_byte(&c)) { if (c == mp_interrupt_char) { + ringbuf_clear(&_incoming_ringbuf); mp_sched_keyboard_interrupt(); continue; } diff --git a/supervisor/shared/workflow.c b/supervisor/shared/workflow.c index df2055580fc5d..7370e34e86007 100644 --- a/supervisor/shared/workflow.c +++ b/supervisor/shared/workflow.c @@ -43,10 +43,12 @@ void supervisor_workflow_reset(void) { #if CIRCUITPY_WEB_WORKFLOW bool result = supervisor_start_web_workflow(); - if (workflow_background_cb.fun) { - if (result) { - supervisor_workflow_request_background(); + if (result) { + if (!workflow_background_cb.fun) { + memset(&workflow_background_cb, 0, sizeof(workflow_background_cb)); + workflow_background_cb.fun = supervisor_web_workflow_background; } + supervisor_workflow_request_background(); } #endif } @@ -89,7 +91,7 @@ bool supervisor_workflow_active(void) { void supervisor_workflow_start(void) { // Start USB after giving boot.py a chance to tweak behavior. - #if CIRCUITPY_TINYUSB + #if CIRCUITPY_USB_DEVICE // Setup USB connection after heap is available. // It needs the heap to build descriptors. usb_init(); @@ -105,9 +107,11 @@ void supervisor_workflow_start(void) { #if CIRCUITPY_WEB_WORKFLOW if (supervisor_start_web_workflow()) { - // Enable background callbacks if web_workflow startup successful + // Enable background callbacks if web_workflow startup successful. memset(&workflow_background_cb, 0, sizeof(workflow_background_cb)); workflow_background_cb.fun = supervisor_web_workflow_background; + // Kick the first background run now that the callback is installed. + supervisor_workflow_request_background(); } #endif diff --git a/supervisor/stub/misc.c b/supervisor/stub/misc.c deleted file mode 100644 index c0a2a87f9fecd..0000000000000 --- a/supervisor/stub/misc.c +++ /dev/null @@ -1,13 +0,0 @@ -// This file is part of the CircuitPython project: https://circuitpython.org -// -// SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries -// -// SPDX-License-Identifier: MIT -#include "stdbool.h" - -#include "supervisor/port.h" -#include "py/mpconfig.h" - - -MP_WEAK void port_post_boot_py(bool heap_valid) { -} diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index 50ce3f4c18168..bce47353f578f 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -1,6 +1,5 @@ SRC_SUPERVISOR = \ main.c \ - lib/tlsf/tlsf.c \ supervisor/port.c \ supervisor/shared/background_callback.c \ supervisor/shared/board.c \ @@ -19,7 +18,14 @@ SRC_SUPERVISOR = \ supervisor/shared/traceback.c \ supervisor/shared/translate/translate.c \ supervisor/shared/workflow.c \ - supervisor/stub/misc.c \ + +ifeq ($(CIRCUITPY_SETTINGS_TOML),1) +SRC_SUPERVISOR += supervisor/shared/settings.c +endif + +ifeq ($(CIRCUITPY_LIB_TLSF),1) +SRC_SUPERVISOR += lib/tlsf/tlsf.c +endif # For tlsf CFLAGS += -D_DEBUG=0 @@ -114,6 +120,7 @@ ifeq ($(CIRCUITPY_TINYUSB),1) lib/tinyusb/src/common/tusb_fifo.c \ lib/tinyusb/src/tusb.c \ supervisor/usb.c \ + supervisor/shared/usb.c \ supervisor/shared/usb/usb.c \ ifeq ($(CIRCUITPY_USB_DEVICE),1) @@ -257,12 +264,10 @@ ifeq ($(CIRCUITPY_USB_CDC),1) CFLAGS += -DCFG_TUD_CDC=2 endif -USB_HIGHSPEED ?= 0 -CFLAGS += -DUSB_HIGHSPEED=$(USB_HIGHSPEED) - $(BUILD)/supervisor/shared/translate/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h $(HEADER_BUILD)/compressed_translations.generated.h CIRCUITPY_DISPLAY_FONT ?= "../../tools/fonts/ter-u12n.bdf" +CIRCUITPY_FONT_EXTRA_CHARACTERS ?= "" $(BUILD)/autogen_display_resources-$(TRANSLATION).c: ../../tools/gen_display_resources.py $(TOP)/locale/$(TRANSLATION).po Makefile | $(HEADER_BUILD) $(STEPECHO) "GEN $@" @@ -270,4 +275,5 @@ $(BUILD)/autogen_display_resources-$(TRANSLATION).c: ../../tools/gen_display_res $(Q)$(PYTHON) ../../tools/gen_display_resources.py \ --font $(CIRCUITPY_DISPLAY_FONT) \ --sample_file $(TOP)/locale/$(TRANSLATION).po \ + --extra_characters $(CIRCUITPY_FONT_EXTRA_CHARACTERS) \ --output_c_file $@ diff --git a/supervisor/usb.h b/supervisor/usb.h index 0b0fabb5d6069..d6e4236c9b48d 100644 --- a/supervisor/usb.h +++ b/supervisor/usb.h @@ -48,6 +48,7 @@ typedef struct { bool usb_enabled(void); void usb_add_interface_string(uint8_t interface_string_index, const char str[]); bool usb_build_descriptors(const usb_identification_t *identification); +bool usb_connected(void); void usb_disconnect(void); void usb_init(void); void usb_set_defaults(void); @@ -61,9 +62,13 @@ void usb_setup_with_vm(void); // Propagate plug/unplug events to the MSC logic. #if CIRCUITPY_USB_DEVICE && CIRCUITPY_USB_MSC +size_t usb_msc_descriptor_length(void); +size_t usb_msc_add_descriptor(uint8_t *descriptor_buf, descriptor_counts_t *descriptor_counts, uint8_t *current_interface_string); void usb_msc_mount(void); void usb_msc_umount(void); -bool usb_msc_ejected(void); + +#include "extmod/vfs_fat.h" +void usb_msc_remount(fs_user_mount_t *fs_mount); #endif #if CIRCUITPY_USB_KEYBOARD_WORKFLOW @@ -71,6 +76,8 @@ void usb_keyboard_init(void); uint32_t usb_keyboard_chars_available(void); char usb_keyboard_read_char(void); +void usb_keyboard_status(void); + bool usb_keyboard_in_use(uint8_t dev_addr, uint8_t interface); void usb_keyboard_detach(uint8_t dev_addr, uint8_t interface); void usb_keyboard_attach(uint8_t dev_addr, uint8_t interface); diff --git a/tests/README.md b/tests/README.md index 9a93c69b29cc0..534e7e0a05972 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,7 +1,46 @@ # MicroPython Test Suite -This directory contains tests for various functionality areas of MicroPython. -To run all stable tests, run "run-tests.py" script in this directory. +This directory contains tests for most parts of MicroPython. To run it you will need +CPython 3.8.2 or newer, which is used to validate MicroPython's behaviour. + +To run all stable tests, run the "run-tests.py" script in this directory. By default +that will run the test suite against the unix port of MicroPython. + +To run the test suite against a bare-metal target (a board running MicroPython firmware) +use the `-t` option to specify the serial port. This will automatically detect the +target platform and run the appropriate set of tests for that platform. For example: + + $ ./run-tests.py -t /dev/ttyACM0 + +That will run tests on the `/dev/ttyACM0` serial port. You can also use shortcut +device names like `a` for `/dev/ttyACM` and `c` for `COM`. Use +`./run-tests.py --help` to see all of the device possibilities, and other options. + +There are three kinds of tests: + +* Tests that use `unittest`: these tests require `unittest` to be installed on the + target (eg via `mpremote mip install unittest`), and are used to test things that are + MicroPython-specific, such as behaviour that is different to CPython, modules that + aren't available in CPython, and hardware tests. These tests are run only under + MicroPython and the test passes if the `unittest` runner prints "OK" at the end of the + run. Other output may be printed, eg for use as diagnostics, and this output does not + affect the result of the test. + +* Tests with a corresponding `.exp` file: similar to the `unittest` tests, these tests + are for features that generally cannot be run under CPython. In this case the test is + run under MicroPython only and the output from MicroPython is compared against the + provided `.exp` file. The test passes if the output matches exactly. + +* Tests without a corresponding `.exp` file (and don't use `unittest`): these tests are + used to test MicroPython behaviour that should precisely match CPython. These tests + are first run under CPython and the output captured, and then run under MicroPython + and the output compared to the CPython output. The test passes if the output matches + exactly. If the output differs then the test fails and the outputs are saved in a + `.exp` and a `.out` file respectively. + +In all three cases above, the test can usually be run directly on the target MicroPython +instance, either using the unix port with `micropython `, or on a board with +`mpremote run `. This is useful for creating and debugging tests. Tests of capabilities not supported on all platforms should be written to check for the capability being present. If it is not, the test @@ -15,15 +54,6 @@ condition a test. The run-tests.py script uses small scripts in the feature_check directory to check whether each such feature is present, and skips the relevant tests if not. -Tests are generally verified by running the test both in MicroPython and -in CPython and comparing the outputs. If the output differs the test fails -and the outputs are saved in a .out and a .exp file respectively. -For tests that cannot be run in CPython, for example because they use -the machine module, a .exp file can be provided next to the test's .py -file. A convenient way to generate that is to run the test, let it fail -(because CPython cannot run it) and then copy the .out file (but not -before checking it manually!) - When creating new tests, anything that relies on float support should go in the float/ subdirectory. Anything that relies on import x, where x is not a built-in module, should go in the import/ subdirectory. @@ -38,16 +68,14 @@ for a full list of command line options. ### Benchmarking a target -To run tests on a firmware target using `pyboard.py`, run the command line like +To run tests on a firmware target using a serial port, run the command line like this: ``` -./run-perfbench.py -p -d /dev/ttyACM0 168 100 +./run-perfbench.py -t /dev/ttyACM0 168 100 ``` -* `-p` indicates running on a remote target via pyboard.py, not the host. -* `-d PORTNAME` is the serial port, `/dev/ttyACM0` is the default if not - provided. +* `-t PORTNAME` is the serial port to use (and it supports shorthand like `a0`). * `168` is value `N`, the approximate CPU frequency in MHz (in this case Pyboard V1.1 is 168MHz). It's possible to choose other values as well: lower values like `10` will run much the tests much quicker, higher values like `1000` will @@ -107,11 +135,11 @@ Usually you want to know if something is faster or slower than a reference. To do this, copy the output of each `run-perfbench.py` run to a text file. This can be done multiple ways, but one way on Linux/macOS is with the `tee` -utility: `./run-perfbench.py -p 168 100 | tee pyb-run1.txt` +utility: `./run-perfbench.py -t a0 168 100 | tee pyb-run1.txt` Once you have two files with output from two different runs (maybe with different code or configuration), compare the runtimes with `./run-perfbench.py --t pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s +-m pybv-run1.txt pybv-run2.txt` or compare scores with `./run-perfbench.py -s pybv-run1.txt pybv-run2.txt`: ``` @@ -175,20 +203,49 @@ internal_bench/bytebuf: 1 tests performed (3 individual testcases) ``` +## Serial reliability and performance test + +Serial port reliability and performance can be tested using the `serial_test.py` script. +Pass the name of the port to test against, for example: + + $ ./serial_test.py -t /dev/ttyACM0 + +If no port is specified then `/dev/ttyACM0` is used as the default. + +The test will send data out to the target, and receive data from the target, in various +chunk sizes. The throughput of the serial connection will be reported for each sub-test. + ## Test key/certificates -SSL/TLS tests in `multi_net` and `net_inet` use a -self-signed key/cert pair that is randomly generated and to be used for -testing/demonstration only. You should always generate your own key/cert. +SSL/TLS tests in `multi_net` and `net_inet` use self-signed key/cert pairs +that are randomly generated to be used for testing/demonstration only. -To generate a new self-signed key/cert pair with openssl do: +To run tests on-device the `.der` files should be copied and the current time +set to ensure certs validity. This can be done with: ``` -$ openssl req -x509 -newkey rsa:4096 -keyout rsa_key.pem -out rsa_cert.pem -days 365 -nodes +$ mpremote rtc --set cp multi_net/*.der net_inet/*.der : +``` + +### Generating new test key/certificates + +The keys used for the unit tests are included in the tests folders so don't generally +need to be re-created by end users. This section is included here for reference only. + +A new self-signed RSA key/cert pair can be created with openssl: +``` +$ openssl req -x509 -newkey rsa:2048 -keyout rsa_key.pem -out rsa_cert.pem -days 3650 -nodes -subj '/CN=micropython.local/O=MicroPython/C=AU' ``` In this case CN is: micropython.local Convert them to DER format: ``` -$ openssl rsa -in rsa_key.pem -out rsa_key.der -outform DER +$ openssl pkey -in rsa_key.pem -out rsa_key.der -outform DER $ openssl x509 -in rsa_cert.pem -out rsa_cert.der -outform DER ``` + +For elliptic curve tests using key/cert pairs, create a key then a certificate using: +``` +$ openssl ecparam -name prime256v1 -genkey -noout -out ec_key.pem +$ openssl pkey -in ec_key.pem -out ec_key.der -outform DER +$ openssl req -new -x509 -key ec_key.pem -out ec_cert.der -outform DER -days 3650 -nodes -subj '/CN=micropython.local/O=MicroPython/C=AU' +``` diff --git a/tests/basics/annotate_var.py.exp b/tests/basics/annotate_var.py.exp deleted file mode 100644 index 9b6536e966b0e..0000000000000 --- a/tests/basics/annotate_var.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -False -1 -(1, 2) -NameError -1 diff --git a/tests/basics/array_add.py b/tests/basics/array_add.py index 76ce59f761e06..e78615541c3cb 100644 --- a/tests/basics/array_add.py +++ b/tests/basics/array_add.py @@ -14,3 +14,9 @@ a1.extend(array.array('I', [5])) print(a1) + +a1.extend([6, 7]) +print(a1) + +a1.extend(i for i in (8, 9)) +print(a1) diff --git a/tests/basics/assign_expr.py.exp b/tests/basics/assign_expr.py.exp deleted file mode 100644 index 47da56b80d47b..0000000000000 --- a/tests/basics/assign_expr.py.exp +++ /dev/null @@ -1,16 +0,0 @@ -4 -True -2 -4 5 -5 -1 5 5 -5 -2 1 -1 0 -any True -8 -123 -any True -8 -[(1, 0), (2, 2), (3, 6), (4, 12)] -4 diff --git a/tests/basics/assign_expr_scope.py.exp b/tests/basics/assign_expr_scope.py.exp deleted file mode 100644 index 5c780b382215f..0000000000000 --- a/tests/basics/assign_expr_scope.py.exp +++ /dev/null @@ -1,23 +0,0 @@ -scope0 -1 -None -scope1 -[1] -1 -None -scope2 -[0, 1] -1 -1 -scope3 -[0, 1] -None -None -scope4 -[0, 1] -1 -1 -scope5 -[0, 1] -1 -None diff --git a/tests/basics/async_await.py.exp b/tests/basics/async_await.py.exp deleted file mode 100644 index b51c388a9339e..0000000000000 --- a/tests/basics/async_await.py.exp +++ /dev/null @@ -1,32 +0,0 @@ -4 -3 -2 -1 -0 -0 -1 -0 -0 -2 -1 -0 -0 -1 -0 -0 -3 -2 -1 -0 -0 -1 -0 -0 -2 -1 -0 -0 -1 -0 -0 -finished diff --git a/tests/basics/async_await2.py.exp b/tests/basics/async_await2.py.exp deleted file mode 100644 index fc9ff0aa535fc..0000000000000 --- a/tests/basics/async_await2.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -wait value: 1 -return from send: message from wait(1) -wait got back: message from main -x = 100 -got StopIteration diff --git a/tests/basics/async_def.py.exp b/tests/basics/async_def.py.exp deleted file mode 100644 index f555ace99ab20..0000000000000 --- a/tests/basics/async_def.py.exp +++ /dev/null @@ -1,3 +0,0 @@ -decorator -foo -StopIteration diff --git a/tests/basics/async_for.py.exp b/tests/basics/async_for.py.exp deleted file mode 100644 index 6f59979c065de..0000000000000 --- a/tests/basics/async_for.py.exp +++ /dev/null @@ -1,51 +0,0 @@ -== start == -init -aiter -init -anext -a -anext -b -anext -c -anext -== finish == -== start == -init -aiter -init -anext -d -anext -e -anext -f -anext -AsyncIteratorWrapper-def -== finish == -init -== start == -aiter -init -anext -g -anext -h -anext -i -anext -AsyncIteratorWrapper-ghi -== finish == -init -== start == -aiter -init -anext -j -anext -k -anext -l -anext -AsyncIteratorWrapper-jkl -== finish == diff --git a/tests/basics/async_for2.py b/tests/basics/async_for2.py index bbdb02c49b209..82232d52fc2a1 100644 --- a/tests/basics/async_for2.py +++ b/tests/basics/async_for2.py @@ -1,7 +1,7 @@ # test waiting within "async for" __anext__ function # CIRCUITPY-CHANGE -# uPy allows normal generators to be awaitables. +# MicroPython allows normal generators to be awaitables. # CircuitPython does not. # In CircuitPython you need to have an __await__ method on an awaitable like in CPython; # and like in CPython, generators do not have __await__. diff --git a/tests/basics/async_for2.py.exp b/tests/basics/async_for2.py.exp deleted file mode 100644 index 52bbe90c85376..0000000000000 --- a/tests/basics/async_for2.py.exp +++ /dev/null @@ -1,32 +0,0 @@ -init -aiter -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 0 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 1 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 2 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -x 3 -anext -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -finished diff --git a/tests/basics/async_syntaxerror.py.exp b/tests/basics/async_syntaxerror.py.exp deleted file mode 100644 index 5275689b41383..0000000000000 --- a/tests/basics/async_syntaxerror.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -SyntaxError -SyntaxError diff --git a/tests/basics/async_with.py.exp b/tests/basics/async_with.py.exp deleted file mode 100644 index 6bbf84cb4b52c..0000000000000 --- a/tests/basics/async_with.py.exp +++ /dev/null @@ -1,11 +0,0 @@ -enter -body -exit None None -finished -enter -1 -exit error -ValueError -enter -exit -BaseException diff --git a/tests/basics/async_with2.py b/tests/basics/async_with2.py index 5bac38236fe4a..b18fa6bdee106 100644 --- a/tests/basics/async_with2.py +++ b/tests/basics/async_with2.py @@ -1,7 +1,7 @@ # test waiting within async with enter/exit functions # CIRCUITPY-CHANGE -# uPy allows normal generators to be awaitables. +# MicroPython allows normal generators to be awaitables. # CircuitPython does not. # In CircuitPython you need to have an __await__ method on an awaitable like in CPython; # and like in CPython, generators do not have __await__. diff --git a/tests/basics/async_with2.py.exp b/tests/basics/async_with2.py.exp deleted file mode 100644 index 76b173b4c24a7..0000000000000 --- a/tests/basics/async_with2.py.exp +++ /dev/null @@ -1,17 +0,0 @@ -enter -f start: 10 -coro yielded: 11 -coro yielded: 12 -f returned: 13 -body start -f start: 30 -coro yielded: 31 -coro yielded: 32 -body f returned: 33 -body end -exit None None -f start: 20 -coro yielded: 21 -coro yielded: 22 -f returned: 23 -finished diff --git a/tests/basics/async_with_break.py.exp b/tests/basics/async_with_break.py.exp deleted file mode 100644 index d077a88fad0e4..0000000000000 --- a/tests/basics/async_with_break.py.exp +++ /dev/null @@ -1,15 +0,0 @@ -enter -body -exit None None -finished -enter -body -exit None None -finally -finished -enter -body -exit None None -finally inner -finally outer -finished diff --git a/tests/basics/async_with_return.py.exp b/tests/basics/async_with_return.py.exp deleted file mode 100644 index d077a88fad0e4..0000000000000 --- a/tests/basics/async_with_return.py.exp +++ /dev/null @@ -1,15 +0,0 @@ -enter -body -exit None None -finished -enter -body -exit None None -finally -finished -enter -body -exit None None -finally inner -finally outer -finished diff --git a/tests/basics/attrtuple2.py b/tests/basics/attrtuple2.py new file mode 100644 index 0000000000000..081d24b6ae92c --- /dev/null +++ b/tests/basics/attrtuple2.py @@ -0,0 +1,25 @@ +# test os.uname() attrtuple, if available +try: + import os +except ImportError: + print("SKIP") + raise SystemExit + +try: + u = os.uname() +except AttributeError: + print("SKIP") + raise SystemExit + +# test printing of attrtuple +print(str(u).find("machine=") > 0) + +# test read attr +print(isinstance(u.machine, str)) + +# test str modulo operator for attrtuple +impl_str = ("%s " * len(u)) % u +test_str = "" +for val in u: + test_str += val + " " +print(impl_str == test_str) diff --git a/tests/basics/boundmeth1.py b/tests/basics/boundmeth1.py index fe1b454688d64..9f08d9bbb259b 100644 --- a/tests/basics/boundmeth1.py +++ b/tests/basics/boundmeth1.py @@ -1,6 +1,6 @@ # tests basics of bound methods -# uPy and CPython differ when printing a bound method, so just print the type +# MicroPython and CPython differ when printing a bound method, so just print the type print(type(repr([].append))) diff --git a/tests/basics/builtin_compile.py b/tests/basics/builtin_compile.py index 41dc746ad163c..361d7ec53a729 100644 --- a/tests/basics/builtin_compile.py +++ b/tests/basics/builtin_compile.py @@ -29,6 +29,9 @@ def test(): exec(compile("print(10 + 2)", "file", "single")) print(eval(compile("10 + 3", "file", "eval"))) + # test accessing a function's globals from within a compile + exec(compile("def func():pass\nprint('x', func.__globals__['x'])", "file", "exec")) + # bad mode try: compile('1', 'file', '') diff --git a/tests/basics/builtin_help.py b/tests/basics/builtin_help.py index 6ec39653fe993..3d4e4f26bd2bb 100644 --- a/tests/basics/builtin_help.py +++ b/tests/basics/builtin_help.py @@ -14,4 +14,10 @@ help(micropython) # help for a module help('modules') # list available modules +class A: + x = 1 + y = 2 + del x +help(A) + print('done') # so last bit of output is predictable diff --git a/tests/basics/builtin_pow3_intbig.py b/tests/basics/builtin_pow3_intbig.py index bedc8b36b7edd..41d2acbc0cc75 100644 --- a/tests/basics/builtin_pow3_intbig.py +++ b/tests/basics/builtin_pow3_intbig.py @@ -20,3 +20,8 @@ print(hex(pow(y, x-1, x))) # Should be 1, since x is prime print(hex(pow(y, y-1, x))) # Should be a 'big value' print(hex(pow(y, y-1, y))) # Should be a 'big value' + +try: + print(pow(1, 2, 0)) +except ValueError: + print("ValueError") diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py index 66226bad16a6d..9608a8163107e 100644 --- a/tests/basics/builtin_range.py +++ b/tests/basics/builtin_range.py @@ -32,13 +32,29 @@ print(range(1, 4)[0:]) print(range(1, 4)[1:]) print(range(1, 4)[:-1]) +print(range(4, 1)[:]) +print(range(4, 1)[0:]) +print(range(4, 1)[1:]) +print(range(4, 1)[:-1]) print(range(7, -2, -4)[:]) print(range(1, 100, 5)[5:15:3]) print(range(1, 100, 5)[15:5:-3]) print(range(100, 1, -5)[5:15:3]) print(range(100, 1, -5)[15:5:-3]) +print(range(1, 100, 5)[5:15:-3]) +print(range(1, 100, 5)[15:5:3]) +print(range(100, 1, -5)[5:15:-3]) +print(range(100, 1, -5)[15:5:3]) +print(range(1, 100, 5)[5:15:3]) +print(range(1, 100, 5)[15:5:-3]) +print(range(1, 100, -5)[5:15:3]) +print(range(1, 100, -5)[15:5:-3]) +print(range(1, 100, 5)[5:15:-3]) +print(range(1, 100, 5)[15:5:3]) +print(range(1, 100, -5)[5:15:-3]) +print(range(1, 100, -5)[15:5:3]) -# for this case uPy gives a different stop value but the listed elements are still correct +# for this case MicroPython gives a different stop value but the listed elements are still correct print(list(range(7, -2, -4)[2:-2:])) # zero step diff --git a/tests/basics/builtin_range_maxsize.py b/tests/basics/builtin_range_maxsize.py new file mode 100644 index 0000000000000..b0f3a5e5129f1 --- /dev/null +++ b/tests/basics/builtin_range_maxsize.py @@ -0,0 +1,38 @@ +try: + from sys import maxsize +except ImportError: + print("SKIP") + raise SystemExit + +# Test the range builtin at extreme values. (https://github.com/micropython/micropython/issues/17684) +# +# This is written using asserts instead of prints because the value of `maxsize` differs. +# +# Numbers & counts right up against the max of mp_int_t also cause overflows, such as +# objrange.c:115:14: runtime error: signed integer overflow: 9223372036854775807 + 1 cannot be represented in type 'long int' +# so just avoid them for the purposes of this test. + +r = range(-maxsize + 1, -1) +assert r.start == -maxsize + 1 +assert r.stop == -1 +assert r[0] == -maxsize + 1 +assert r[1] == -maxsize + 2 +assert r[-1] == -2 +assert r[-2] == -3 + +ir = iter(r) +assert next(ir) == -maxsize + 1 +assert next(ir) == -maxsize + 2 + +r = range(0, maxsize - 1) +assert len(r) == maxsize - 1 +assert r.stop == maxsize - 1 + +r = range(maxsize, 0, -1) +assert len(r) == maxsize +assert r.start == maxsize +assert r[0] == maxsize +assert r[1] == maxsize - 1 +ir = iter(r) +assert next(ir) == maxsize +assert next(ir) == maxsize - 1 diff --git a/tests/basics/builtin_setattr.py b/tests/basics/builtin_setattr.py index e4acb14cac354..2c9a452c32774 100644 --- a/tests/basics/builtin_setattr.py +++ b/tests/basics/builtin_setattr.py @@ -21,5 +21,5 @@ def __init__(self): try: setattr(int, 'to_bytes', 1) except (AttributeError, TypeError): - # uPy raises AttributeError, CPython raises TypeError + # MicroPython raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') diff --git a/tests/basics/builtin_slice.py b/tests/basics/builtin_slice.py index 3ff3c3dd04d43..cbce3d14ed699 100644 --- a/tests/basics/builtin_slice.py +++ b/tests/basics/builtin_slice.py @@ -1,11 +1,44 @@ # test builtin slice +# ensures that slices passed to user types are heap-allocated and can be +# safely stored as well as not overridden by subsequent slices. + # print slice class A: def __getitem__(self, idx): - print(idx) + print("get", idx) + print("abc"[1:]) + print("get", idx) + return idx + + def __setitem__(self, idx, value): + print("set", idx) + print("abc"[1:]) + print("set", idx) + self.saved_idx = idx + return idx + + def __delitem__(self, idx): + print("del", idx) + print("abc"[1:]) + print("del", idx) return idx -s = A()[1:2:3] + + +a = A() +s = a[1:2:3] +a[4:5:6] = s +del a[7:8:9] + +print(a.saved_idx) + +# nested slicing +print(A()[1 : A()[A()[2:3:4] : 5]]) + +# tuple slicing +a[1:2, 4:5, 7:8] +a[1, 4:5, 7:8, 2] +a[1:2, a[3:4], 5:6] # check type print(type(s) is slice) diff --git a/tests/basics/builtin_str_hex.py b/tests/basics/builtin_str_hex.py index 7390c8eaee17c..9455883012c0d 100644 --- a/tests/basics/builtin_str_hex.py +++ b/tests/basics/builtin_str_hex.py @@ -20,5 +20,20 @@ "08090a0b0c0d0e0f", "7f80ff", "313233344142434461626364", + "ab\tcd\n ef ", + "ab cd ef", + "ab cd ef ", + " ab cd ef ", + # Invalid hex strings: + "abcde", # Odd number of hex digits + "ab cd e", + "a b cd ef", # Spaces between hex pairs + "ab cd e f ", + "abga", # Invalid hex digits + "ab_cd", + "ab:cd", ): - print(bytes.fromhex(x)) + try: + print(bytes.fromhex(x)) + except ValueError as e: + print("ValueError:", e) diff --git a/tests/basics/builtin_str_hex.py.exp b/tests/basics/builtin_str_hex.py.exp index 990dd8570767e..0309cad02d1a6 100644 --- a/tests/basics/builtin_str_hex.py.exp +++ b/tests/basics/builtin_str_hex.py.exp @@ -26,3 +26,14 @@ b'\x00\x01\x02\x03\x04\x05\x06\x07' b'\x08\t\n\x0b\x0c\r\x0e\x0f' b'\x7f\x80\xff' b'1234ABCDabcd' +b'\xab\xcd\xef' +b'\xab\xcd\xef' +b'\xab\xcd\xef' +b'\xab\xcd\xef' +ValueError: non-hex digit +ValueError: non-hex digit +ValueError: non-hex digit +ValueError: non-hex digit +ValueError: non-hex digit +ValueError: non-hex digit +ValueError: non-hex digit diff --git a/tests/basics/builtin_super.py b/tests/basics/builtin_super.py new file mode 100644 index 0000000000000..5f7c3ae017e7e --- /dev/null +++ b/tests/basics/builtin_super.py @@ -0,0 +1,15 @@ +# Check that super rejects invalid arguments. +try: + super(str, 0) +except TypeError: + print("TypeError") + +try: + super(str, int) +except TypeError: + print("TypeError") + +try: + super(0, int) +except TypeError: + print("TypeError") diff --git a/tests/basics/bytearray_add.py b/tests/basics/bytearray_add.py index a7e2b57374255..1f30a3b740e95 100644 --- a/tests/basics/bytearray_add.py +++ b/tests/basics/bytearray_add.py @@ -15,4 +15,11 @@ # this inplace add tests the code when the buffer doesn't need to be increased b = bytearray() -b += b'' +b += b"" + +# extend a bytearray from itself +b = bytearray(b"abcdefgh") +for _ in range(4): + c = bytearray(b) # extra allocation, as above + b.extend(b) +print(b) diff --git a/tests/basics/bytearray_add_self.py b/tests/basics/bytearray_add_self.py new file mode 100644 index 0000000000000..94ae8689fd16c --- /dev/null +++ b/tests/basics/bytearray_add_self.py @@ -0,0 +1,8 @@ +# add a bytearray to itself +# This is not supported by CPython as of 3.11.18. + +b = bytearray(b"123456789") +for _ in range(4): + c = bytearray(b) # extra allocation increases chance 'b' has to relocate + b += b +print(b) diff --git a/tests/basics/bytearray_add_self.py.exp b/tests/basics/bytearray_add_self.py.exp new file mode 100644 index 0000000000000..5ef948157ac0f --- /dev/null +++ b/tests/basics/bytearray_add_self.py.exp @@ -0,0 +1 @@ +bytearray(b'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789') diff --git a/tests/basics/bytearray_byte_operations.py b/tests/basics/bytearray_byte_operations.py index 7ce53cac535a1..48b08ab26196f 100644 --- a/tests/basics/bytearray_byte_operations.py +++ b/tests/basics/bytearray_byte_operations.py @@ -1,4 +1,4 @@ -# test bytearray with its re-use of byte functions +# test bytearray with its reuse of byte functions print(bytearray(b"hello world").find(b"ll")) print(bytearray(b"hello\x00world").rfind(b"l")) diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py index fa7878e10ddbb..4de0819042a13 100644 --- a/tests/basics/bytearray_slice_assign.py +++ b/tests/basics/bytearray_slice_assign.py @@ -18,7 +18,7 @@ l[1:3] = bytearray() print(l) l = bytearray(x) -#del l[1:3] +# del l[1:3] print(l) l = bytearray(x) @@ -28,7 +28,7 @@ l[:3] = bytearray() print(l) l = bytearray(x) -#del l[:3] +# del l[:3] print(l) l = bytearray(x) @@ -38,7 +38,7 @@ l[:-3] = bytearray() print(l) l = bytearray(x) -#del l[:-3] +# del l[:-3] print(l) # slice assignment that extends the array @@ -61,8 +61,14 @@ print(b) # Growth of bytearray via slice extension -b = bytearray(b'12345678') -b.append(57) # expand and add a bit of unused space at end of the bytearray +b = bytearray(b"12345678") +b.append(57) # expand and add a bit of unused space at end of the bytearray for i in range(400): - b[-1:] = b'ab' # grow slowly into the unused space + b[-1:] = b"ab" # grow slowly into the unused space +print(len(b), b) + +# Growth of bytearray via slice extension from itself +b = bytearray(b"1234567") +for i in range(3): + b[-1:] = b print(len(b), b) diff --git a/tests/basics/bytes_format_modulo.py.exp b/tests/basics/bytes_format_modulo.py.exp deleted file mode 100644 index 782b7f91fcbfe..0000000000000 --- a/tests/basics/bytes_format_modulo.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -b'%' -b'=1=' -b'=1=2=' -b'=str=' -b"=b'str'=" diff --git a/tests/basics/class_bind_self.py b/tests/basics/class_bind_self.py index 813f876446ef2..8bece902ca254 100644 --- a/tests/basics/class_bind_self.py +++ b/tests/basics/class_bind_self.py @@ -52,7 +52,7 @@ def f4(self, arg): # generator print(C.f8(13)) print(C.f9(14)) -# not working in uPy +# not working in MicroPython #class C(list): # # this acts like a method and binds self # f1 = list.extend diff --git a/tests/basics/class_bytes.py b/tests/basics/class_bytes.py index 75e2e7244e739..eacb69a438adf 100644 --- a/tests/basics/class_bytes.py +++ b/tests/basics/class_bytes.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file class C1: def __init__(self, value): self.value = value diff --git a/tests/basics/class_descriptor.py b/tests/basics/class_descriptor.py index 54f386230fec1..feaed2fbb2a43 100644 --- a/tests/basics/class_descriptor.py +++ b/tests/basics/class_descriptor.py @@ -1,34 +1,67 @@ class Descriptor: def __get__(self, obj, cls): - print('get') + print("get") print(type(obj) is Main) print(cls is Main) - return 'result' + return "result" def __set__(self, obj, val): - print('set') + print("set") print(type(obj) is Main) print(val) def __delete__(self, obj): - print('delete') + print("delete") print(type(obj) is Main) + def __set_name__(self, owner, name): + print("set_name", name) + print(owner.__name__ == "Main") + + class Main: Forward = Descriptor() + m = Main() try: m.__class__ except AttributeError: + # Target doesn't support __class__. print("SKIP") raise SystemExit r = m.Forward -if 'Descriptor' in repr(r.__class__): - print('SKIP') +if "Descriptor" in repr(r.__class__): + # Target doesn't support descriptors. + print("SKIP") raise SystemExit +# Test assignment and deletion. + print(r) -m.Forward = 'a' +m.Forward = "a" del m.Forward + +# Test that lookup of descriptors like __get__ are not passed into __getattr__. + + +class NonDescriptor: + def __getattr__(self, attr): + print("getattr", attr) + + +class TestClass: + non_descriptor = NonDescriptor() + + +print(isinstance(TestClass().non_descriptor, NonDescriptor)) + +t = TestClass() +t.non_descriptor = 123 +print(t.non_descriptor) + +try: + del TestClass().non_descriptor +except AttributeError: + print("AttributeError") diff --git a/tests/basics/class_inplace_op2.py.exp b/tests/basics/class_inplace_op2.py.exp deleted file mode 100644 index 8c323b5178ef4..0000000000000 --- a/tests/basics/class_inplace_op2.py.exp +++ /dev/null @@ -1,12 +0,0 @@ -__imul__ -__imatmul__ -__ifloordiv__ -__itruediv__ -__imod__ -__ipow__ -__ior__ -__ixor__ -__iand__ -__ilshift__ -__irshift__ -TypeError diff --git a/tests/basics/class_ordereddict.py.exp b/tests/basics/class_ordereddict.py.exp deleted file mode 100644 index b723e327515c7..0000000000000 --- a/tests/basics/class_ordereddict.py.exp +++ /dev/null @@ -1 +0,0 @@ -['a', 'b', 'c', 'd', 'e'] diff --git a/tests/basics/class_setname_hazard.py b/tests/basics/class_setname_hazard.py new file mode 100644 index 0000000000000..77c0409346282 --- /dev/null +++ b/tests/basics/class_setname_hazard.py @@ -0,0 +1,182 @@ +# Test that __set_name__ can access and mutate its owner argument. + + +def skip_if_no_descriptors(): + class Descriptor: + def __get__(self, obj, cls): + return + + class TestClass: + Forward = Descriptor() + + a = TestClass() + try: + a.__class__ + except AttributeError: + # Target doesn't support __class__. + print("SKIP") + raise SystemExit + + b = a.Forward + if "Descriptor" in repr(b.__class__): + # Target doesn't support descriptors. + print("SKIP") + raise SystemExit + + +skip_if_no_descriptors() + + +# Test basic accesses and mutations. + + +class GetSibling: + def __set_name__(self, owner, name): + print(getattr(owner, name + "_sib")) + + +class GetSiblingTest: + desc = GetSibling() + desc_sib = 111 + + +t110 = GetSiblingTest() + + +class SetSibling: + def __set_name__(self, owner, name): + setattr(owner, name + "_sib", 121) + + +class SetSiblingTest: + desc = SetSibling() + + +t120 = SetSiblingTest() + +print(t120.desc_sib) + + +class DelSibling: + def __set_name__(self, owner, name): + delattr(owner, name + "_sib") + + +class DelSiblingTest: + desc = DelSibling() + desc_sib = 131 + + +t130 = DelSiblingTest() + +try: + print(t130.desc_sib) +except AttributeError: + print("AttributeError") + + +class GetSelf: + x = 211 + + def __set_name__(self, owner, name): + print(getattr(owner, name).x) + + +class GetSelfTest: + desc = GetSelf() + + +t210 = GetSelfTest() + + +class SetSelf: + def __set_name__(self, owner, name): + setattr(owner, name, 221) + + +class SetSelfTest: + desc = SetSelf() + + +t220 = SetSelfTest() + +print(t220.desc) + + +class DelSelf: + def __set_name__(self, owner, name): + delattr(owner, name) + + +class DelSelfTest: + desc = DelSelf() + + +t230 = DelSelfTest() + +try: + print(t230.desc) +except AttributeError: + print("AttributeError") + + +# Test exception behavior. + + +class Raise: + def __set_name__(self, owner, name): + raise Exception() + + +try: + + class RaiseTest: + desc = Raise() +except Exception as e: # CPython raises RuntimeError, MicroPython propagates the original exception + print("Exception") + + +# Ensure removed/overwritten class members still get __set_name__ called. + + +class SetSpecific: + def __init__(self, sib_name, sib_replace): + self.sib_name = sib_name + self.sib_replace = sib_replace + + def __set_name__(self, owner, name): + setattr(owner, self.sib_name, self.sib_replace) + + +class SetReplaceTest: + a = SetSpecific("b", 312) # one of these is changed first + b = SetSpecific("a", 311) + + +t310 = SetReplaceTest() +print(t310.a) +print(t310.b) + + +class DelSpecific: + def __init__(self, sib_name): + self.sib_name = sib_name + + def __set_name__(self, owner, name): + delattr(owner, self.sib_name) + + +class DelReplaceTest: + a = DelSpecific("b") # one of these is removed first + b = DelSpecific("a") + + +t320 = DelReplaceTest() +try: + print(t320.a) +except AttributeError: + print("AttributeError") +try: + print(t320.b) +except AttributeError: + print("AttributeError") diff --git a/tests/basics/class_setname_hazard_rand.py b/tests/basics/class_setname_hazard_rand.py new file mode 100644 index 0000000000000..4c9934c3bf068 --- /dev/null +++ b/tests/basics/class_setname_hazard_rand.py @@ -0,0 +1,111 @@ +# Test to make sure there's no sequence hazard even when a __set_name__ implementation +# mutates and reorders the namespace of its owner class. +# VERY hard bug to prove out except via a stochastic test. + + +try: + from random import choice + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def skip_if_no_descriptors(): + class Descriptor: + def __get__(self, obj, cls): + return + + class TestClass: + Forward = Descriptor() + + a = TestClass() + try: + a.__class__ + except AttributeError: + # Target doesn't support __class__. + print("SKIP") + raise SystemExit + + b = a.Forward + if "Descriptor" in repr(b.__class__): + # Target doesn't support descriptors. + print("SKIP") + raise SystemExit + + +skip_if_no_descriptors() + +letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + +# Would be r"[A-Z]{5}", but not all ports support the {n} quantifier. +junk_re = re.compile(r"[A-Z][A-Z][A-Z][A-Z][A-Z]") + + +def junk_fill(obj, n=10): # Add randomly-generated attributes to an object. + for i in range(n): + name = "".join(choice(letters) for j in range(5)) + setattr(obj, name, object()) + + +def junk_clear(obj): # Remove attributes added by junk_fill. + to_del = [name for name in dir(obj) if junk_re.match(name)] + for name in to_del: + delattr(obj, name) + + +def junk_sequencer(): + global runs + try: + while True: + owner, name = yield + runs[name] = runs.get(name, 0) + 1 + junk_fill(owner) + finally: + junk_clear(owner) + + +class JunkMaker: + def __set_name__(self, owner, name): + global seq + seq.send((owner, name)) + + +runs = {} +seq = junk_sequencer() +next(seq) + + +class Main: + a = JunkMaker() + b = JunkMaker() + c = JunkMaker() + d = JunkMaker() + e = JunkMaker() + f = JunkMaker() + g = JunkMaker() + h = JunkMaker() + i = JunkMaker() + j = JunkMaker() + k = JunkMaker() + l = JunkMaker() + m = JunkMaker() + n = JunkMaker() + o = JunkMaker() + p = JunkMaker() + q = JunkMaker() + r = JunkMaker() + s = JunkMaker() + t = JunkMaker() + u = JunkMaker() + v = JunkMaker() + w = JunkMaker() + x = JunkMaker() + y = JunkMaker() + z = JunkMaker() + + +seq.close() + +for k in letters.lower(): + print(k, runs.get(k, 0)) diff --git a/tests/basics/core_class_superproperty.py b/tests/basics/core_class_superproperty.py index 3095ab51da105..5c6c78f315e6a 100644 --- a/tests/basics/core_class_superproperty.py +++ b/tests/basics/core_class_superproperty.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file """ test that calling super() getter property in subclass will return the value """ diff --git a/tests/basics/del_attr.py b/tests/basics/del_attr.py index 8487b97e311d0..90a8a5a6f833d 100644 --- a/tests/basics/del_attr.py +++ b/tests/basics/del_attr.py @@ -35,5 +35,5 @@ def f(): try: del int.to_bytes except (AttributeError, TypeError): - # uPy raises AttributeError, CPython raises TypeError + # MicroPython raises AttributeError, CPython raises TypeError print('AttributeError/TypeError') diff --git a/tests/basics/del_global.py b/tests/basics/del_global.py index d740357b0332d..e1aa074b97a43 100644 --- a/tests/basics/del_global.py +++ b/tests/basics/del_global.py @@ -14,7 +14,7 @@ def do_del(): try: do_del() except: # NameError: - # FIXME uPy returns KeyError for this + # FIXME MicroPython returns KeyError for this print("NameError") # delete globals using a list diff --git a/tests/basics/del_name.py b/tests/basics/del_name.py index c92be54d3b655..8393b2df92a72 100644 --- a/tests/basics/del_name.py +++ b/tests/basics/del_name.py @@ -10,7 +10,7 @@ try: del x except: # NameError: - # FIXME uPy returns KeyError for this + # FIXME MicroPython returns KeyError for this print("NameError") class C: diff --git a/tests/basics/deque1.py b/tests/basics/deque1.py index 2cb3c2f87134a..9ca6d434a75f9 100644 --- a/tests/basics/deque1.py +++ b/tests/basics/deque1.py @@ -64,7 +64,7 @@ except TypeError: print("TypeError") -# CIRCUITPY-CHANGE + # Same tests, but now with pop() and appendleft() d = deque((), 2) diff --git a/tests/basics/deque2.py b/tests/basics/deque2.py index 4c3743cf6e8e2..ebc0872c7b4e0 100644 --- a/tests/basics/deque2.py +++ b/tests/basics/deque2.py @@ -1,12 +1,9 @@ -# Tests for deques with "check overflow" flag and other extensions -# wrt to CPython. try: from collections import deque except ImportError: print("SKIP") raise SystemExit -# CIRCUITPY-CHANGE: more functionality # Initial sequence is supported d = deque([1, 2, 3], 10) @@ -34,6 +31,16 @@ d[3] = 5 print(d[3]) +# Access the last element via index, when the last element is at various locations +d = deque((), 2) +for i in range(4): + d.append(i) + print(i, d[-1]) + +# Write the last element then access all elements from the end +d[-1] = 4 +print(d[-2], d[-1]) + # Accessing indices out of bounds raises IndexError try: d[4] @@ -44,69 +51,3 @@ d[4] = 0 except IndexError: print("IndexError") - -# Removing elements with del is not supported, fall back on mp_obj_subscr() error message -try: - del d[0] -except TypeError: - print("TypeError") - - -# Only fixed-size deques are supported, so length arg is mandatory -try: - deque(()) -except TypeError: - print("TypeError") - -d = deque((), 2, True) - -try: - d.popleft() -except IndexError: - print("IndexError") - -try: - d.pop() -except IndexError: - print("IndexError") - -print(d.append(1)) -print(d.popleft()) - -d.append(2) -print(d.popleft()) - -d.append(3) -d.append(4) -print(d.popleft(), d.popleft()) -try: - d.popleft() -except IndexError as e: - print(repr(e)) - -try: - d.pop() -except IndexError as e: - print(repr(e)) - -d.append(5) -d.append(6) -print(len(d)) -try: - d.append(7) -except IndexError as e: - print(repr(e)) - -try: - d.appendleft(8) -except IndexError as e: - print(repr(e)) - -print(len(d)) - -print(d.popleft(), d.popleft()) -print(len(d)) -try: - d.popleft() -except IndexError as e: - print(repr(e)) diff --git a/tests/basics/deque2.py.exp b/tests/basics/deque2.py.exp deleted file mode 100644 index 71f74ed6c4aaf..0000000000000 --- a/tests/basics/deque2.py.exp +++ /dev/null @@ -1,26 +0,0 @@ -1 -2 -3 -[3, 4, 5] -[5, 6, 7] -0 1 3 -5 -IndexError -IndexError -TypeError -TypeError -IndexError -IndexError -None -1 -2 -3 4 -IndexError('empty',) -IndexError('empty',) -2 -IndexError('full',) -IndexError('full',) -2 -5 6 -0 -IndexError('empty',) diff --git a/tests/basics/deque_micropython.py b/tests/basics/deque_micropython.py new file mode 100644 index 0000000000000..5f32bbc496a3c --- /dev/null +++ b/tests/basics/deque_micropython.py @@ -0,0 +1,75 @@ +# Test MicroPython-specific features of collections.deque. + +try: + from collections import deque +except ImportError: + print("SKIP") + raise SystemExit + + +# Only fixed-size deques are supported, so length arg is mandatory. +try: + deque(()) +except TypeError: + print("TypeError") + +# Test third argument: flags when True means check for under/overflow +d = deque((), 2, True) + +try: + d.popleft() +except IndexError: + print("IndexError") + +try: + d.pop() +except IndexError: + print("IndexError") + +# Removing elements with del is not supported, fallback to +# mp_obj_subscr() error message. +try: + del d[0] +except TypeError: + print("TypeError") + +print(d.append(1)) +print(d.popleft()) + +d.append(2) +print(d.popleft()) + +d.append(3) +d.append(4) +print(d.popleft(), d.popleft()) +try: + d.popleft() +except IndexError as e: + print(repr(e)) + +try: + d.pop() +except IndexError as e: + print(repr(e)) + +d.append(5) +d.append(6) +print(len(d)) +try: + d.append(7) +except IndexError as e: + print(repr(e)) + +try: + d.appendleft(8) +except IndexError as e: + print(repr(e)) + +print(len(d)) + +print(d.popleft(), d.popleft()) +print(len(d)) +try: + d.popleft() +except IndexError as e: + print(repr(e)) diff --git a/tests/basics/deque_micropython.py.exp b/tests/basics/deque_micropython.py.exp new file mode 100644 index 0000000000000..f1ff7b77ac880 --- /dev/null +++ b/tests/basics/deque_micropython.py.exp @@ -0,0 +1,17 @@ +TypeError +IndexError +IndexError +TypeError +None +1 +2 +3 4 +IndexError('empty',) +IndexError('empty',) +2 +IndexError('full',) +IndexError('full',) +2 +5 6 +0 +IndexError('empty',) diff --git a/tests/basics/dict_fromkeys_reversed.py b/tests/basics/dict_fromkeys_reversed.py index 34b0ed129c081..7ecd9bfddc75a 100644 --- a/tests/basics/dict_fromkeys_reversed.py +++ b/tests/basics/dict_fromkeys_reversed.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file # Skip this test if reversed() isn't built in. import skip_if skip_if.no_reversed() diff --git a/tests/basics/dict_views.py b/tests/basics/dict_views.py index a82f47b6be26f..45f3238f1c624 100644 --- a/tests/basics/dict_views.py +++ b/tests/basics/dict_views.py @@ -6,6 +6,11 @@ # print a view with more than one item print({1:1, 2:1}.values()) +# `bool` and `len` unary ops +for d in ({}, {1: 2}, {1: 2, 3: 4}): + for op in (bool, len): + print(op(d.keys()), op(d.values()), op(d.items())) + # unsupported binary op on a dict values view try: {1:1}.values() + 1 diff --git a/tests/basics/exception_chain.py b/tests/basics/exception_chain.py index 579756c85fa20..96c06c847ab37 100644 --- a/tests/basics/exception_chain.py +++ b/tests/basics/exception_chain.py @@ -1,5 +1,12 @@ # CIRCUITPY-CHANGE: exception chaining is supported +import sys + +# The unix minimal build doesn't enable MICROPY_WARNINGS (required for this test). +if getattr(sys.implementation, "_build", None) == "minimal": + print("SKIP") + raise SystemExit + try: Exception().__cause__ except AttributeError: diff --git a/tests/basics/frozenset_set.py b/tests/basics/frozenset_set.py index 3bf456acfd70f..2b3c683260989 100644 --- a/tests/basics/frozenset_set.py +++ b/tests/basics/frozenset_set.py @@ -8,5 +8,5 @@ # "Instances of set are compared to instances of frozenset based on their # members. For example:" print(set('abc') == frozenset('abc')) -# This doesn't work in uPy +# This doesn't work in MicroPython #print(set('abc') in set([frozenset('abc')])) diff --git a/tests/basics/fun_code.py b/tests/basics/fun_code.py new file mode 100644 index 0000000000000..59e1f7ec0483d --- /dev/null +++ b/tests/basics/fun_code.py @@ -0,0 +1,36 @@ +# Test function.__code__ attribute. + +try: + (lambda: 0).__code__ +except AttributeError: + print("SKIP") + raise SystemExit + + +def f(): + return a + + +ftype = type(f) + +# Test __code__ access and function constructor. +code = f.__code__ +print(type(ftype(code, {})) is ftype) + +# Test instantiating multiple code's with different globals dicts. +code = f.__code__ +f1 = ftype(code, {"a": 1}) +f2 = ftype(code, {"a": 2}) +print(f1(), f2()) + +# Test bad first argument type. +try: + ftype(None, {}) +except TypeError: + print("TypeError") + +# Test bad second argument type. +try: + ftype(f.__code__, None) +except TypeError: + print("TypeError") diff --git a/tests/basics/fun_code_colines.py b/tests/basics/fun_code_colines.py new file mode 100644 index 0000000000000..a8867770eddf1 --- /dev/null +++ b/tests/basics/fun_code_colines.py @@ -0,0 +1,81 @@ +# Check that we have sensical bytecode offsets in function.__code__.co_lines + +def f1(x, y, obj, obj2, obj3): + a = x + y # line 4: bc+4 line+4 + b = x - y # line 5: bc+4 line+1 + # line 6 + # line 7 + # line 8 + # line 9 + # line 10 + # line 11 + # line 12 + # line 13 + # line 14 + # line 15 + # line 16 + # line 17 + # line 18 + # line 19 + c = a * b # line 20: bc+4 line+15 + obj.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 21: bc+31 line+1; bc+27 line+0 + # line 22 + # line 23 + # line 24: bc+0 line+3 + # line 25 + # line 26 + # line 27: bc+0 line+3 + # line 28 + # line 29 + obj2.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 30: bc+31 line+3; bc+27 line+0 + # line 31 + # line 32 + # line 33: bc+0 line+3 + # line 34 + # line 35 + # line 36 + # line 37 + # line 38 + # line 39 + # line 40 + # line 41 + # line 42 + # line 43 + # line 44 + # line 45 + # line 46 + # line 47 + # line 48 + # line 49 + # line 50 + # line 51 + # line 52 + # line 53 + # line 54 + # line 55 + # line 56 + # line 57 + # line 58 + # line 59 + return obj3.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.fun() # line 60: bc+31 line+27; bc+27 line+0 + +def f2(x, y): + a = x + y # line 63 + b = x - y # line 64 + return a * b # line 65 + +try: + f1.__code__.co_lines +except AttributeError: + print("SKIP") + raise SystemExit + +print("f1") +for start, end, line_no in f1.__code__.co_lines(): + print("line {} start: {}".format(line_no, start)) + print("line {} end: {}".format(line_no, end)) + +print("f2") +for start, end, line_no in f2.__code__.co_lines(): + print("line {} start: {}".format(line_no, start)) + print("line {} end: {}".format(line_no, end)) diff --git a/tests/basics/fun_code_colines.py.exp b/tests/basics/fun_code_colines.py.exp new file mode 100644 index 0000000000000..19bd4ef6e2a5a --- /dev/null +++ b/tests/basics/fun_code_colines.py.exp @@ -0,0 +1,20 @@ +f1 +line 4 start: 0 +line 4 end: 4 +line 5 start: 4 +line 5 end: 8 +line 20 start: 8 +line 20 end: 12 +line 21 start: 12 +line 21 end: 70 +line 30 start: 70 +line 30 end: 128 +line 60 start: 128 +line 60 end: 186 +f2 +line 63 start: 0 +line 63 end: 4 +line 64 start: 4 +line 64 end: 8 +line 65 start: 8 +line 65 end: 12 diff --git a/tests/basics/fun_code_full.py b/tests/basics/fun_code_full.py new file mode 100644 index 0000000000000..538863631a6e0 --- /dev/null +++ b/tests/basics/fun_code_full.py @@ -0,0 +1,38 @@ +# Test function.__code__ attributes not available with MICROPY_PY_BUILTINS_CODE <= MICROPY_PY_BUILTINS_CODE_BASIC + +try: + (lambda: 0).__code__.co_code +except AttributeError: + print("SKIP") + raise SystemExit + +def f(x, y): + a = x + y + b = x - y + return a * b + +code = f.__code__ + +print(type(code.co_code)) # both bytes (but mpy and cpy have different instruction sets) +print(code.co_consts) # (not necessarily the same set, but in this function they are) +print(code.co_filename.rsplit('/')[-1]) # same terminal filename but might be different paths on other ports +print(type(code.co_firstlineno)) # both ints (but mpy points to first line inside, cpy points to declaration) +print(code.co_name) +print(iter(code.co_names) is not None) # both iterable (but mpy returns dict with names as keys, cpy only the names; and not necessarily the same set) + +co_lines = code.co_lines() + +l = list(co_lines) +first_start = l[0][0] +last_end = l[-1][1] +print(first_start) # co_lines should start at the start of the bytecode +print(len(code.co_code) - last_end) # and end at the end of the bytecode + +prev_end = 0 +for start, end, line_no in l: + if end != prev_end: + print("non-contiguous") + break # the offset ranges should be contiguous + prev_end = end +else: + print("contiguous") diff --git a/tests/basics/fun_code_full.py.exp b/tests/basics/fun_code_full.py.exp new file mode 100644 index 0000000000000..830effadfc695 --- /dev/null +++ b/tests/basics/fun_code_full.py.exp @@ -0,0 +1,9 @@ + +(None,) +fun_code_full.py + +f +True +0 +0 +non-contiguous diff --git a/tests/basics/fun_code_lnotab.py b/tests/basics/fun_code_lnotab.py new file mode 100644 index 0000000000000..9223e5730f0ea --- /dev/null +++ b/tests/basics/fun_code_lnotab.py @@ -0,0 +1,34 @@ +# Test deprecation of co_lnotab + +try: + (lambda: 0).__code__.co_code +except AttributeError: + print("SKIP") + raise SystemExit + + +import unittest +import sys + + +mpy_is_v2 = getattr(sys.implementation, '_v2', False) + + +def f(): + pass + + +class Test(unittest.TestCase): + + @unittest.skipIf(mpy_is_v2, "Removed in MicroPython v2 and later.") + def test_co_lnotab_exists(self): + self.assertIsInstance(f.__code__.co_lnotab, bytes) + + @unittest.skipUnless(mpy_is_v2, "Not removed before MicroPython v2.") + def test_co_lnotab_removed(self): + with self.assertRaises(AttributeError): + f.__code__.co_lnotab + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/basics/fun_code_micropython.py b/tests/basics/fun_code_micropython.py new file mode 100644 index 0000000000000..2c319a2db8c75 --- /dev/null +++ b/tests/basics/fun_code_micropython.py @@ -0,0 +1,19 @@ +# Test MicroPython-specific restrictions of function.__code__ attribute. + +try: + (lambda: 0).__code__ +except AttributeError: + print("SKIP") + raise SystemExit + + +def f_with_children(): + def g(): + pass + + +# Can't access __code__ when function has children. +try: + f_with_children.__code__ +except AttributeError: + print("AttributeError") diff --git a/tests/basics/fun_code_micropython.py.exp b/tests/basics/fun_code_micropython.py.exp new file mode 100644 index 0000000000000..d169edffb4cfb --- /dev/null +++ b/tests/basics/fun_code_micropython.py.exp @@ -0,0 +1 @@ +AttributeError diff --git a/tests/basics/fun_name.py b/tests/basics/fun_name.py index b2642280a2a65..8aac35eeafa25 100644 --- a/tests/basics/fun_name.py +++ b/tests/basics/fun_name.py @@ -16,7 +16,7 @@ def Fun(self): print('SKIP') raise SystemExit -# __name__ of a bound native method is not implemented in uPy +# __name__ of a bound native method is not implemented in MicroPython # the test here is to make sure it doesn't crash try: str((1).to_bytes.__name__) diff --git a/tests/basics/gc1.py b/tests/basics/gc1.py index 332bf9744c072..dff9538b14b5c 100644 --- a/tests/basics/gc1.py +++ b/tests/basics/gc1.py @@ -15,13 +15,13 @@ gc.collect() if hasattr(gc, 'mem_free'): - # uPy has these extra functions + # MicroPython has these extra functions # just test they execute and return an int assert type(gc.mem_free()) is int assert type(gc.mem_alloc()) is int if hasattr(gc, 'threshold'): - # uPy has this extra function + # MicroPython has this extra function # check execution and returns assert(gc.threshold(1) is None) assert(gc.threshold() == 0) diff --git a/tests/basics/gen_stack_overflow.py b/tests/basics/gen_stack_overflow.py index 5cba0e0549be4..99fd952444238 100644 --- a/tests/basics/gen_stack_overflow.py +++ b/tests/basics/gen_stack_overflow.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file def gen(): yield from gen() diff --git a/tests/basics/import_instance_method.py b/tests/basics/import_instance_method.py new file mode 100644 index 0000000000000..d25b70ac5f0bf --- /dev/null +++ b/tests/basics/import_instance_method.py @@ -0,0 +1,38 @@ +# Test importing a method from a class instance. +# This is not a common thing to do, but ensures MicroPython has the same semantics as CPython. + +import sys + +if not hasattr(sys, "modules"): + print("SKIP") + raise SystemExit + + +class A: + def __init__(self, value): + self.value = value + + def meth(self): + return self.value + + def meth_with_arg(self, a): + return [self.value, a] + + +# Register a class instance as the module "mod". +sys.modules["mod"] = A(1) + +# Try importing it as a module. +import mod + +print(mod.meth()) +print(mod.meth_with_arg(2)) + +# Change the module. +sys.modules["mod"] = A(3) + +# Try importing it using "from ... import". +from mod import meth, meth_with_arg + +print(meth()) +print(meth_with_arg(4)) diff --git a/tests/basics/int1.py b/tests/basics/int1.py index 2d92105c73e88..94723af4d00b4 100644 --- a/tests/basics/int1.py +++ b/tests/basics/int1.py @@ -13,6 +13,7 @@ print(int('+1')) print(int('-1')) print(int('01')) +print(int('00')) print(int('9')) print(int('10')) print(int('+10')) @@ -31,6 +32,7 @@ print(int('0', 10)) print(int('1', 10)) print(int(' \t 1 \t ', 10)) +print(int(' \t 00 \t ', 10)) print(int('11', 10)) print(int('11', 16)) print(int('11', 8)) @@ -52,6 +54,17 @@ print(int('0o12 \t ', 8)) print(int(b"12", 10)) print(int(b"12")) +print(int('000 ', 0)) +print(int('000 ', 2)) +print(int('000 ', 8)) +print(int('000 ', 10)) +print(int('000 ', 16)) +print(int('000 ', 36)) +print(int('010 ', 2)) +print(int('010 ', 8)) +print(int('010 ', 10)) +print(int('010 ', 16)) +print(int('010 ', 36)) def test(value, base): @@ -79,6 +92,8 @@ def test(value, base): test('0xg', 16) test('1 1', 16) test('123', 37) +test('01', 0) +test('01 ', 0) # check that we don't parse this as a floating point number print(0x1e+1) diff --git a/tests/basics/int_64_basics.py b/tests/basics/int_64_basics.py new file mode 100644 index 0000000000000..ef76793317ec8 --- /dev/null +++ b/tests/basics/int_64_basics.py @@ -0,0 +1,161 @@ +# test support for 64-bit long integers +# (some ports don't support arbitrary precision but do support these) + +# this test is adapted from int_big1.py with numbers kept within 64-bit signed range + +# to test arbitrary precision integers + +x = 1000000000000000000 +xn = -1000000000000000000 +y = 2000000000000000000 + +# printing +print(x) +print(y) +print('%#X' % (x - x)) # print prefix +print('{:#,}'.format(x)) # print with commas + +# construction +print(int(x)) + +# addition +print(x + 1) +print(x + y) +print(x + xn == 0) +print(bool(x + xn)) + +# subtraction +print(x - 1) +print(x - y) +print(y - x) +print(x - x == 0) +print(bool(x - x)) + +# multiplication +print(x * 2) +print(1090511627776 * 1048500) + +# integer division +print(x // 2) +print(y // x) + +# bit inversion +print(~x) +print(~(-x)) + +# left shift +print("left shift positive") +x = 0x40000000 +for i in range(32): + x = x << 1 + print(x) + +# right shift +print("right shift positive") +x = 0x2000000000000000 # TODO: why can't second-tip bit be set? +for i in range(64): + x = x >> 1 + print(x) + +# left shift of a negative number +print("left shift negative") +for i in range(8): + print(-10000000000000000 << i) + print(-10000000000000001 << i) + print(-10000000000000002 << i) + print(-10000000000000003 << i) + print(-10000000000000004 << i) + + +# right shift of a negative number +print("right shift negative") +for i in range(8): + print(-1000000000000000000 >> i) + print(-1000000000000000001 >> i) + print(-1000000000000000002 >> i) + print(-1000000000000000003 >> i) + print(-1000000000000000004 >> i) + +# conversion from string +print(int("1234567890123456789")) +print(int("-1234567890123456789")) +print(int("1234567890abcdef", 16)) +print(int("1234567890ABCDEF", 16)) +print(int("-1234567890ABCDEF", 16)) +print(int("ijklmnopqrsz", 36)) + +# numbers close to 64-bit limits +print(int("-9111222333444555666")) +print(int("9111222333444555666")) + +# numbers with preceding 0s +print(int("-00000000000000000000009111222333444555666")) +print(int("0000000000000000000000009111222333444555666")) + +# invalid characters in string +try: + print(int("1234567890abcdef")) +except ValueError: + print('ValueError'); +try: + print(int("123456789\x01")) +except ValueError: + print('ValueError'); + +# test parsing ints just on threshold of small to big +# for 32 bit archs +x = 1073741823 # small +x = -1073741823 # small +x = 1073741824 # big +x = -1073741824 # big +# for 64 bit archs +x = 4611686018427387903 # small +x = -4611686018427387903 # small +x = 4611686018427387904 # big +x = -4611686018427387904 # big + +# sys.maxsize is a constant bigint, so test it's compatible with dynamic ones +import sys +if hasattr(sys, "maxsize"): + print(sys.maxsize - 1 + 1 == sys.maxsize) +else: + print(True) # No maxsize property in this config + +# test extraction of big int value via mp_obj_get_int_maybe +x = 1 << 62 +print('a' * (x + 4 - x)) + +# test overflow check in mp_obj_get_int_maybe +x = 1 << 32 +r = None +try: + r = range(0, x) +except OverflowError: + # 32-bit target, correctly handled the overflow of x + print("ok") +if r is not None: + if len(r) == x: + # 64-bit target, everything is just a small-int + print("ok") + else: + # 32-bit target that did not handle the overflow of x + print("unhandled overflow") + +# negative shifts are invalid +try: + print((1 << 48) >> -4) +except ValueError as e: + print(e) + +try: + print((1 << 48) << -6) +except ValueError as e: + print(e) + +# Test that the most extreme 64 bit integer values all parse with int() +print(int("-9223372036854775807")) +print(int("-9223372036854775808")) +print(int("9223372036854775807")) + +# Test that the most negative 64 bit integer can be formed via arithmetic +print(-9223372036854775807-1) diff --git a/tests/basics/int_big_to_small.py b/tests/basics/int_big_to_small.py new file mode 100644 index 0000000000000..c92d263fc2837 --- /dev/null +++ b/tests/basics/int_big_to_small.py @@ -0,0 +1,33 @@ +try: + import micropython + micropython.heap_lock +except: + print("SKIP") + raise SystemExit + +# Skip this test on "REPR B" where (1<<29 + 1) is not a small int. +k = 1 << 29 +micropython.heap_lock() +try: + k = k + 1 +except MemoryError: + print("SKIP") + raise SystemExit +finally: + micropython.heap_unlock() + +# All less than small int max. +for d in (0, 27, 1<<29, -1861, -(1<<29)): + i = 1<<70 + print(i) + j = (1<<70) + d + print(j) + # k should now be a small int. + k = j - i + print(k) + + # Now verify that working with k doesn't allocate (i.e. it's a small int). + micropython.heap_lock() + print(k + 20) + print(k // 20) + micropython.heap_unlock() diff --git a/tests/basics/int_big_to_small.py.exp b/tests/basics/int_big_to_small.py.exp new file mode 100644 index 0000000000000..1d4986e044372 --- /dev/null +++ b/tests/basics/int_big_to_small.py.exp @@ -0,0 +1,25 @@ +1180591620717411303424 +1180591620717411303424 +0 +20 +0 +1180591620717411303424 +1180591620717411303451 +27 +47 +1 +1180591620717411303424 +1180591620717948174336 +536870912 +536870932 +26843545 +1180591620717411303424 +1180591620717411301563 +-1861 +-1841 +-94 +1180591620717411303424 +1180591620716874432512 +-536870912 +-536870892 +-26843546 diff --git a/tests/basics/int_big_to_small_int29.py b/tests/basics/int_big_to_small_int29.py new file mode 100644 index 0000000000000..438a74d2bc6a4 --- /dev/null +++ b/tests/basics/int_big_to_small_int29.py @@ -0,0 +1,22 @@ +try: + import micropython + micropython.heap_lock +except: + print("SKIP") + raise SystemExit + +# All less than small int max. +for d in (0, 27, 1<<28, -1861, -(1<<28)): + i = 1<<70 + print(i) + j = (1<<70) + d + print(j) + # k should now be a small int. + k = j - i + print(k) + + # Now verify that working with k doesn't allocate (i.e. it's a small int). + micropython.heap_lock() + print(k + 20) + print(k // 20) + micropython.heap_unlock() diff --git a/tests/basics/int_big_to_small_int29.py.exp b/tests/basics/int_big_to_small_int29.py.exp new file mode 100644 index 0000000000000..0920101924aa8 --- /dev/null +++ b/tests/basics/int_big_to_small_int29.py.exp @@ -0,0 +1,25 @@ +1180591620717411303424 +1180591620717411303424 +0 +20 +0 +1180591620717411303424 +1180591620717411303451 +27 +47 +1 +1180591620717411303424 +1180591620717679738880 +268435456 +268435476 +13421772 +1180591620717411303424 +1180591620717411301563 +-1861 +-1841 +-94 +1180591620717411303424 +1180591620717142867968 +-268435456 +-268435436 +-13421773 diff --git a/tests/basics/int_bytes.py b/tests/basics/int_bytes.py index 3840aa8e4f00e..d1999bebb0e86 100644 --- a/tests/basics/int_bytes.py +++ b/tests/basics/int_bytes.py @@ -26,6 +26,12 @@ except ValueError: print("ValueError") +# zero byte destination should also raise an error +try: + (1).to_bytes(0, "little") +except OverflowError: + print("OverflowError") + # CIRCUITPY-CHANGE: more tests # too small buffer should raise an error try: @@ -39,7 +45,24 @@ except OverflowError: print("OverflowError") +# except for converting 0 to a zero-length byte array +print((0).to_bytes(0, "big")) + +# byte length can fit the integer directly +print((0xFF).to_bytes(1, "little")) +print((0xFF).to_bytes(1, "big")) +print((0xEFF).to_bytes(2, "little")) +print((0xEFF).to_bytes(2, "big")) +print((0xCDEFF).to_bytes(3, "little")) +print((0xCDEFF).to_bytes(3, "big")) + +# OverFlowError if not big enough + try: (-256).to_bytes(2, "little", signed=False) except OverflowError: print("OverflowError") + +# byteorder arg can be omitted; default is "big" +print(int.from_bytes(b"\x01\0")) +print((100).to_bytes(10)) diff --git a/tests/basics/int_bytes_int64.py b/tests/basics/int_bytes_int64.py new file mode 100644 index 0000000000000..032dbccc5b14e --- /dev/null +++ b/tests/basics/int_bytes_int64.py @@ -0,0 +1,52 @@ +import sys + +# Depending on the port, the numbers in this test may be implemented as "small" +# native 64 bit ints, arbitrary precision large ints, or large integers using 64-bit +# long longs. + +try: + x = int.from_bytes(b"\x6F\xAB\xCD\x12\x34\x56\x78\xFB", "big") +except OverflowError: + print("SKIP") # Port can't represent this size of integer at all + raise SystemExit + +print(hex(x)) +b = x.to_bytes(8, "little") +print(b) +print(x.to_bytes(8, "big")) + +# padding in output +print(x.to_bytes(20, "little")) +print(x.to_bytes(20, "big")) + +# check that extra zero bytes don't change the internal int value +print(int.from_bytes(b + bytes(10), "little") == x) + +# can't write to a zero-length bytes object +try: + x.to_bytes(0, "little") +except OverflowError: + print("OverflowError") + +# or one that it too short +try: + x.to_bytes(7, "big") +except OverflowError: + print("OverflowError") + +# negative representations + +# MicroPython int.to_bytes() behaves as if signed=True for negative numbers +if "micropython" in repr(sys.implementation): + + def to_bytes_compat(i, l, e): + return i.to_bytes(l, e) +else: + # Implement MicroPython compatible behaviour for CPython + def to_bytes_compat(i, l, e): + return i.to_bytes(l, e, signed=i < 0) + + +print(to_bytes_compat(-x, 8, "little")) +print(to_bytes_compat(-x, 20, "big")) +print(to_bytes_compat(-x, 20, "little")) diff --git a/tests/basics/int_bytes_intbig.py b/tests/basics/int_bytes_intbig.py index e78f55de01fbc..073c8bf78927f 100644 --- a/tests/basics/int_bytes_intbig.py +++ b/tests/basics/int_bytes_intbig.py @@ -2,6 +2,8 @@ import skip_if skip_if.no_bigint() +import sys + # CIRCUITPY-CHANGE: signed support print((2**64).to_bytes(9, "little")) print((-2**64).to_bytes(9, "little", signed=True)) @@ -17,6 +19,10 @@ print(il.to_bytes(20, "little")) print(ib.to_bytes(20, "big")) +# check padding comes out correctly +print(il.to_bytes(40, "little")) +print(ib.to_bytes(40, "big")) + # check that extra zero bytes don't change the internal int value print(int.from_bytes(b + bytes(10), "little") == int.from_bytes(b, "little")) @@ -32,7 +38,38 @@ (-2**64).to_bytes(9, "little") except OverflowError: print("OverflowError") + +# negative representations + +# MicroPython int.to_bytes() behaves as if signed=True for negative numbers +if "micropython" in repr(sys.implementation): + + def to_bytes_compat(i, l, e): + return i.to_bytes(l, e) +else: + # Implement MicroPython compatible behaviour for CPython + def to_bytes_compat(i, l, e): + return i.to_bytes(l, e, signed=i < 0) + + +print(to_bytes_compat(-ib, 20, "big")) +print(to_bytes_compat(ib * -ib, 40, "big")) + +# case where an additional byte is needed for sign bit +ib = (2**64) - 1 +print(ib.to_bytes(8, "little")) + +ib *= -1 + try: (-2**64).to_bytes(9, "little", signed=False) except OverflowError: print("OverflowError") +try: + print(to_bytes_compat(ib, 8, "little")) +except OverflowError: + print("OverflowError") + + +print(to_bytes_compat(ib, 9, "little")) +print(to_bytes_compat(ib, 9, "big")) diff --git a/tests/basics/int_bytes_optional_args_cp311.py b/tests/basics/int_bytes_optional_args_cp311.py new file mode 100644 index 0000000000000..07fdcdd282110 --- /dev/null +++ b/tests/basics/int_bytes_optional_args_cp311.py @@ -0,0 +1,9 @@ +# Check optional byteorder argument (CPython 3.11+) +print((10).to_bytes(1)) +print((100).to_bytes(10)) +print(int.from_bytes(b"\0\0\0\0\0\0\0\0\0\x01")) +print(int.from_bytes(b"\x01\0")) + +# Check optional length argument (CPython 3.11+) +print((10).to_bytes()) +print((100).to_bytes()) diff --git a/tests/basics/int_bytes_optional_args_cp311.py.exp b/tests/basics/int_bytes_optional_args_cp311.py.exp new file mode 100644 index 0000000000000..6dffa2577fc0b --- /dev/null +++ b/tests/basics/int_bytes_optional_args_cp311.py.exp @@ -0,0 +1,6 @@ +b'\n' +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00d' +1 +256 +b'\n' +b'd' diff --git a/tests/basics/int_length.py b/tests/basics/int_length.py index 56730297c3e92..dd61f4a6b8573 100644 --- a/tests/basics/int_length.py +++ b/tests/basics/int_length.py @@ -1,4 +1,4 @@ -# CIRCUITPY-CHANGE +# CIRCUITPY-CHANGE: micropython does not have this test file # test bit_length for various sizes of ints for x in range(-10, 10): diff --git a/tests/basics/int_longint_bytes.py b/tests/basics/int_longint_bytes.py index 90cbff2f877cf..c68c0d49f434d 100644 --- a/tests/basics/int_longint_bytes.py +++ b/tests/basics/int_longint_bytes.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file # Skip if long ints are not supported. import skip_if skip_if.no_bigint() diff --git a/tests/basics/io_buffered_writer.py b/tests/basics/io_buffered_writer.py index 11df0324e2467..3cfee0103f777 100644 --- a/tests/basics/io_buffered_writer.py +++ b/tests/basics/io_buffered_writer.py @@ -1,10 +1,10 @@ -import io - try: + import io + io.BytesIO io.BufferedWriter -except AttributeError: - print("SKIP") +except (AttributeError, ImportError): + print('SKIP') raise SystemExit bts = io.BytesIO() @@ -28,3 +28,27 @@ # hashing a BufferedWriter print(type(hash(buf))) + +# Test failing flush() +class MyIO(io.IOBase): + def __init__(self): + self.count = 0 + + def write(self, buf): + self.count += 1 + if self.count < 3: + return None + print("writing", buf) + return len(buf) + + +buf = io.BufferedWriter(MyIO(), 8) + +buf.write(b"foobar") + +for _ in range(4): + try: + buf.flush() + print("flushed") + except OSError: + print("OSError") diff --git a/tests/basics/io_buffered_writer.py.exp b/tests/basics/io_buffered_writer.py.exp index 2209348f5af45..d61eb148b453c 100644 --- a/tests/basics/io_buffered_writer.py.exp +++ b/tests/basics/io_buffered_writer.py.exp @@ -4,3 +4,8 @@ b'foobarfoobar' b'foobarfoobar' b'foo' +OSError +OSError +writing bytearray(b'foobar') +flushed +flushed diff --git a/tests/basics/io_bytesio_cow.py b/tests/basics/io_bytesio_cow.py index 2edb7136a9691..543c12ad42ab2 100644 --- a/tests/basics/io_bytesio_cow.py +++ b/tests/basics/io_bytesio_cow.py @@ -1,6 +1,12 @@ # Make sure that write operations on io.BytesIO don't # change original object it was constructed from. -import io + +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + b = b"foobar" a = io.BytesIO(b) diff --git a/tests/basics/io_bytesio_ext.py b/tests/basics/io_bytesio_ext.py index 4d4c60c1363b7..92e715178116c 100644 --- a/tests/basics/io_bytesio_ext.py +++ b/tests/basics/io_bytesio_ext.py @@ -1,5 +1,11 @@ # Extended stream operations on io.BytesIO -import io + +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.BytesIO(b"foobar") a.seek(10) print(a.read(10)) diff --git a/tests/basics/io_bytesio_ext2.py b/tests/basics/io_bytesio_ext2.py index 414ac90a3b083..f60a6a9a6041e 100644 --- a/tests/basics/io_bytesio_ext2.py +++ b/tests/basics/io_bytesio_ext2.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.BytesIO(b"foobar") try: a.seek(-10) diff --git a/tests/basics/io_iobase.py b/tests/basics/io_iobase.py index b2ee5cd63a619..31f2616310e79 100644 --- a/tests/basics/io_iobase.py +++ b/tests/basics/io_iobase.py @@ -1,15 +1,17 @@ import io try: + import io + io.IOBase -except AttributeError: +except (AttributeError, ImportError): print("SKIP") raise SystemExit class MyIO(io.IOBase): def write(self, buf): - # CPython and uPy pass in different types for buf (str vs bytearray) - print("write", len(buf)) + # CPython and MicroPython pass in different types for buf (str vs bytearray) + print('write', len(buf)) return len(buf) -print("test", file=MyIO()) +print('test', file=MyIO()) diff --git a/tests/basics/io_stringio1.py b/tests/basics/io_stringio1.py index 7d355930f5a29..889e3ce697377 100644 --- a/tests/basics/io_stringio1.py +++ b/tests/basics/io_stringio1.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + a = io.StringIO() print('io.StringIO' in repr(a)) print(a.getvalue()) diff --git a/tests/basics/io_stringio_base.py b/tests/basics/io_stringio_base.py index 0f65fb3fabc3b..c8890dab73ab7 100644 --- a/tests/basics/io_stringio_base.py +++ b/tests/basics/io_stringio_base.py @@ -1,7 +1,11 @@ # Checks that an instance type inheriting from a native base that uses # MP_TYPE_FLAG_ITER_IS_STREAM will still have a getiter. -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit a = io.StringIO() a.write("hello\nworld\nmicro\npython\n") diff --git a/tests/basics/io_stringio_with.py b/tests/basics/io_stringio_with.py index a3aa6ec84e066..0155ad5382dcd 100644 --- a/tests/basics/io_stringio_with.py +++ b/tests/basics/io_stringio_with.py @@ -1,4 +1,9 @@ -import io +try: + import io +except ImportError: + print("SKIP") + raise SystemExit + # test __enter__/__exit__ with io.StringIO() as b: b.write("foo") diff --git a/tests/basics/io_write_ext.py b/tests/basics/io_write_ext.py index 79f7450954e4c..5af1de7a6c3aa 100644 --- a/tests/basics/io_write_ext.py +++ b/tests/basics/io_write_ext.py @@ -1,11 +1,12 @@ # This tests extended (MicroPython-specific) form of write: # write(buf, len) and write(buf, offset, len) -import io try: + import io + io.BytesIO -except AttributeError: - print("SKIP") +except (AttributeError, ImportError): + print('SKIP') raise SystemExit buf = io.BytesIO() diff --git a/tests/basics/lexer.py b/tests/basics/lexer.py index 181d62db1aadb..addb8a13df36a 100644 --- a/tests/basics/lexer.py +++ b/tests/basics/lexer.py @@ -83,3 +83,11 @@ def a(x): exec(r"'\U0000000'") except SyntaxError: print("SyntaxError") + +# Properly formed integer literals +print(eval("00")) +# badly formed integer literals +try: + eval("01") +except SyntaxError: + print("SyntaxError") diff --git a/tests/basics/list_pop.py b/tests/basics/list_pop.py index 87ed456f85174..58bcdd91e414c 100644 --- a/tests/basics/list_pop.py +++ b/tests/basics/list_pop.py @@ -10,7 +10,7 @@ else: raise AssertionError("No IndexError raised") -# popping such that list storage shrinks (tests implementation detail of uPy) +# popping such that list storage shrinks (tests implementation detail of MicroPython) l = list(range(20)) for i in range(len(l)): l.pop() diff --git a/tests/basics/memoryview1_slice_assign.py b/tests/basics/memoryview1_slice_assign.py index f272fd392f48a..76952585c30d0 100644 --- a/tests/basics/memoryview1_slice_assign.py +++ b/tests/basics/memoryview1_slice_assign.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file import skip_if try: diff --git a/tests/basics/memoryview_cast.py b/tests/basics/memoryview_cast.py index 24c04e8e5a318..34e8eff931a46 100644 --- a/tests/basics/memoryview_cast.py +++ b/tests/basics/memoryview_cast.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file try: memoryview(b'a').cast except: diff --git a/tests/basics/module2.py b/tests/basics/module2.py index a135601579cd7..d1dc18930f00d 100644 --- a/tests/basics/module2.py +++ b/tests/basics/module2.py @@ -1,4 +1,4 @@ -# uPy behaviour only: builtin modules are read-only +# MicroPython behaviour only: builtin modules are read-only import sys try: sys.x = 1 diff --git a/tests/basics/namedtuple1.py b/tests/basics/namedtuple1.py index 362c60583ec32..b9689b58423b8 100644 --- a/tests/basics/namedtuple1.py +++ b/tests/basics/namedtuple1.py @@ -21,6 +21,9 @@ print(isinstance(t, tuple)) + # a NamedTuple can be used as a tuple + print("(%d, %d)" % t) + # Check tuple can compare equal to namedtuple with same elements print(t == (t[0], t[1]), (t[0], t[1]) == t) diff --git a/tests/basics/namedtuple1_cpython_compat.py b/tests/basics/namedtuple1_cpython_compat.py index 061ae94e587d8..c2d986238e24c 100644 --- a/tests/basics/namedtuple1_cpython_compat.py +++ b/tests/basics/namedtuple1_cpython_compat.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file import skip_if skip_if.no_cpython_compat() diff --git a/tests/basics/nanbox_smallint.py b/tests/basics/nanbox_smallint.py index b3a502e447e3a..9451ab3284661 100644 --- a/tests/basics/nanbox_smallint.py +++ b/tests/basics/nanbox_smallint.py @@ -23,17 +23,17 @@ raise SystemExit micropython.heap_lock() -print(int("0x80000000")) +print(int("0x80000000", 16)) micropython.heap_unlock() # This is the most positive small integer. micropython.heap_lock() -print(int("0x3fffffffffff")) +print(int("0x3fffffffffff", 16)) micropython.heap_unlock() # This is the most negative small integer. micropython.heap_lock() -print(int("-0x3fffffffffff") - 1) +print(int("-0x3fffffffffff", 16) - 1) micropython.heap_unlock() x = 1 diff --git a/tests/basics/ordereddict2.py b/tests/basics/ordereddict2.py index f85b08fea5199..34d5c005a3da6 100644 --- a/tests/basics/ordereddict2.py +++ b/tests/basics/ordereddict2.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file try: from collections import OrderedDict except ImportError: diff --git a/tests/basics/parser.py b/tests/basics/parser.py index 626b67ad7a941..6ae5f05ba458e 100644 --- a/tests/basics/parser.py +++ b/tests/basics/parser.py @@ -7,7 +7,7 @@ raise SystemExit # completely empty string -# uPy and CPy differ for this case +# MPy and CPy differ for this case #try: # compile("", "stdin", "single") #except SyntaxError: diff --git a/tests/basics/python34.py b/tests/basics/python34.py index 922234d22db93..3071b55eff8bf 100644 --- a/tests/basics/python34.py +++ b/tests/basics/python34.py @@ -28,7 +28,7 @@ def test_syntax(code): test_syntax("del ()") # can't delete empty tuple (in 3.6 we can) # from basics/sys1.py -# uPy prints version 3.4 +# MicroPython prints version 3.4 import sys print(sys.version[:3]) print(sys.version_info[0], sys.version_info[1]) diff --git a/tests/basics/python36.py.exp b/tests/basics/python36.py.exp deleted file mode 100644 index 4b65daafa18fe..0000000000000 --- a/tests/basics/python36.py.exp +++ /dev/null @@ -1,5 +0,0 @@ -100000 -165 -65535 -123 -83 diff --git a/tests/basics/self_type_check.py b/tests/basics/self_type_check.py index 3bd5b3eed6058..5f6f6f2ca6585 100644 --- a/tests/basics/self_type_check.py +++ b/tests/basics/self_type_check.py @@ -3,6 +3,14 @@ import skip_if skip_if.board_in("gemma_m0", "trinket_m0") +import sys + +# Minimal builds usually don't enable MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG, +# which is required for this test. +if getattr(sys.implementation, "_build", None) == "minimal": + print("SKIP") + raise SystemExit + list.append try: diff --git a/tests/basics/slice_op.py b/tests/basics/slice_op.py index f1e83c5e27dca..0bb6e365bfd85 100644 --- a/tests/basics/slice_op.py +++ b/tests/basics/slice_op.py @@ -1,3 +1,5 @@ +# Test slice unary operations. +# CPython allows hashing slices, but MicroPython does not. try: t = [][:] diff --git a/tests/basics/slice_optimise.py b/tests/basics/slice_optimise.py new file mode 100644 index 0000000000000..f663e16b8c2f9 --- /dev/null +++ b/tests/basics/slice_optimise.py @@ -0,0 +1,23 @@ +# Test that the slice-on-stack optimisation does not break various uses of slice +# (see MP_TYPE_FLAG_SUBSCR_ALLOWS_STACK_SLICE type option). +# +# Note: this test has a corresponding .py.exp file because hashing slice objects +# was not allowed in CPython until 3.12. + +try: + from collections import OrderedDict +except ImportError: + print("SKIP") + raise SystemExit + +# Attempt to index with a slice, error should contain the slice (failed key). +try: + dict()[:] +except KeyError as e: + print("KeyError", e.args) + +# Put a slice and another object into an OrderedDict, and retrieve them. +x = OrderedDict() +x[:"a"] = 1 +x["b"] = 2 +print(list(x.keys()), list(x.values())) diff --git a/tests/basics/slice_optimise.py.exp b/tests/basics/slice_optimise.py.exp new file mode 100644 index 0000000000000..3fa59aae15ae6 --- /dev/null +++ b/tests/basics/slice_optimise.py.exp @@ -0,0 +1,2 @@ +KeyError (slice(None, None, None),) +[slice(None, 'a', None), 'b'] [1, 2] diff --git a/tests/basics/smallint_array_overflow.py b/tests/basics/smallint_array_overflow.py index 25b457cca1d97..a95060bb3a101 100644 --- a/tests/basics/smallint_array_overflow.py +++ b/tests/basics/smallint_array_overflow.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file try: from array import array except ImportError: diff --git a/tests/basics/special_methods2.py.exp b/tests/basics/special_methods2.py.exp deleted file mode 100644 index a9ae75be55c95..0000000000000 --- a/tests/basics/special_methods2.py.exp +++ /dev/null @@ -1,19 +0,0 @@ -__pos__ called -__pos__ called -__neg__ called -__invert__ called -__mul__ called -__matmul__ called -__truediv__ called -__floordiv__ called -__iadd__ called -__isub__ called -__mod__ called -__pow__ called -__or__ called -__and__ called -__xor__ called -__lshift__ called -__rshift__ called -['a', 'b', 'c'] -False diff --git a/tests/basics/string_endswith.py b/tests/basics/string_endswith.py index 683562d10c32e..2b0a063988b45 100644 --- a/tests/basics/string_endswith.py +++ b/tests/basics/string_endswith.py @@ -5,11 +5,28 @@ print("foobar".endswith("")) print("foobar".endswith("foobarbaz")) -#print("1foobar".startswith("foo", 1)) -#print("1foo".startswith("foo", 1)) -#print("1foo".startswith("1foo", 1)) -#print("1fo".startswith("foo", 1)) -#print("1fo".startswith("foo", 10)) +print("foobar".endswith("bar", 3)) +print("foobar".endswith("bar", 4)) +print("foobar".endswith("foo", 0, 3)) +print("foobar".endswith("foo", 0, 4)) +print("foobar".endswith("foo", 1, 3)) +print("foobar".endswith("foo", 1, 3)) +print("foobar".endswith("oo", 1, 3)) +print("foobar".endswith("o", 2, 3)) +print("foobar".endswith("o", 3, 3)) +print("foobar".endswith("o", 4, 3)) + +print("foobar".endswith("bar", None, None)) +print("foobar".endswith("bar", None, 3)) +print("foobar".endswith("bar", 3, None)) +print("foobar".endswith("bar", 2, None)) +print("foobar".endswith("foo", None, 3)) + +print("foobar".endswith(("bar", "foo"))) +print("foobar".endswith(("foo", "bar"))) +print("foobar".endswith(("foo", "bar1"))) +print("foobar".endswith(("bar", ))) +print("foobar".endswith(("foo", ))) try: "foobar".endswith(1) diff --git a/tests/basics/string_endswith_upy.py b/tests/basics/string_endswith_upy.py deleted file mode 100644 index 06a4e71d2c927..0000000000000 --- a/tests/basics/string_endswith_upy.py +++ /dev/null @@ -1,6 +0,0 @@ -# MicroPython doesn't support tuple argument - -try: - "foobar".endswith(("bar", "sth")) -except TypeError: - print("TypeError") diff --git a/tests/basics/string_endswith_upy.py.exp b/tests/basics/string_endswith_upy.py.exp deleted file mode 100644 index 6002b71c56ea0..0000000000000 --- a/tests/basics/string_endswith_upy.py.exp +++ /dev/null @@ -1 +0,0 @@ -TypeError diff --git a/tests/basics/string_format.py b/tests/basics/string_format.py index e8600f5836139..11e7836a73ece 100644 --- a/tests/basics/string_format.py +++ b/tests/basics/string_format.py @@ -22,7 +22,17 @@ def test(fmt, *args): test("{:4x}", 123) test("{:4X}", 123) +test("{:4,d}", 1) +test("{:4_d}", 1) +test("{:4_o}", 1) +test("{:4_b}", 1) +test("{:4_x}", 1) + test("{:4,d}", 12345678) +test("{:4_d}", 12345678) +test("{:4_o}", 12345678) +test("{:4_b}", 12345678) +test("{:4_x}", 12345678) test("{:#4b}", 10) test("{:#4o}", 123) diff --git a/tests/basics/string_format_intbig.py b/tests/basics/string_format_intbig.py new file mode 100644 index 0000000000000..a36c36752e705 --- /dev/null +++ b/tests/basics/string_format_intbig.py @@ -0,0 +1,15 @@ +# basic functionality test for {} format string using large integers + + +def test(fmt, *args): + print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<") + + +# Separator formatter + +test("{:,}", 123_456_789_012_345_678_901_234_567) +test("{:,}", 23_456_789_012_345_678_901_234_567) +test("{:,}", 3_456_789_012_345_678_901_234_567) +test("{:,}", -123_456_789_012_345_678_901_234_567) +test("{:,}", -23_456_789_012_345_678_901_234_567) +test("{:,}", -3_456_789_012_345_678_901_234_567) diff --git a/tests/basics/string_format_sep.py b/tests/basics/string_format_sep.py new file mode 100644 index 0000000000000..de131fdaf3383 --- /dev/null +++ b/tests/basics/string_format_sep.py @@ -0,0 +1,9 @@ +try: + "%d" % 1 +except TypeError: + print("SKIP") + raise SystemExit + +for v in (0, 0x10, 0x1000, -0x10, -0x1000): + for sz in range(1, 12): print(("{:0%d,d}" % sz).format(v)) + for sz in range(1, 12): print(("{:0%d_x}" % sz).format(v)) diff --git a/tests/basics/string_fstring.py b/tests/basics/string_fstring.py index 42d093b37b508..d94cc0cd3e630 100644 --- a/tests/basics/string_fstring.py +++ b/tests/basics/string_fstring.py @@ -65,3 +65,17 @@ def foo(a, b): # Still allow ! in expressions. print(f"{'1' if a != '456' else '0'!r:8s}") print(f"{'1' if a != '456' else '0'!s:8s}") + +# Concatenation of adjacent f-strings. +print(f"" f"") +print(f"a" f"b") +print(f"{x}" f"{y}") +print( + f"a{x}b---------------------------------" + f"cd---------------------------------" + f"e{y}f---------------------------------" +) + +# Raw f-strings. +print(rf"\r\a\w {'f'} \s\t\r\i\n\g") +print(fr"\r{x}") diff --git a/tests/basics/string_fstring_debug.py.exp b/tests/basics/string_fstring_debug.py.exp deleted file mode 100644 index f0309e1c98aa9..0000000000000 --- a/tests/basics/string_fstring_debug.py.exp +++ /dev/null @@ -1,9 +0,0 @@ -x=1 -x=00000001 -a x=1 b 2 c -a x=00000001 b 2 c -a f() + g("foo") + h()=15 b -a f() + g("foo") + h()=0000000f b -a 1,=(1,) b -a x,y,=(1, 2) b -a x,1=(1, 1) b diff --git a/tests/basics/string_pep498_fstring.py b/tests/basics/string_pep498_fstring.py index 82a2ca38e4b5d..f37229a726d5d 100644 --- a/tests/basics/string_pep498_fstring.py +++ b/tests/basics/string_pep498_fstring.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file # Tests against https://www.python.org/dev/peps/pep-0498/ assert f'no interpolation' == 'no interpolation' diff --git a/tests/basics/string_startswith.py b/tests/basics/string_startswith.py index e63ae3c1866df..eefdea82198f1 100644 --- a/tests/basics/string_startswith.py +++ b/tests/basics/string_startswith.py @@ -10,6 +10,25 @@ print("1fo".startswith("foo", 1)) print("1fo".startswith("foo", 10)) +print("1foobar".startswith("foo", 1, 5)) +print("1foobar".startswith("foo", 1, 4)) +print("1foobar".startswith("foo", 1, 3)) +print("1foobar".startswith("oo", 2, 4)) +print("1foobar".startswith("o", 3, 4)) +print("1foobar".startswith("o", 4, 4)) +print("1foobar".startswith("o", 5, 4)) + +print("foobar".startswith("foo", None, None)) +print("foobar".startswith("foo", None, 3)) +print("foobar".startswith("foo", None, 2)) +print("foobar".startswith("bar", 3, None)) + + +print("foobar".startswith(("foo", "sth"))) +print("foobar".startswith(("sth", "foo"))) +print("foobar".startswith(("sth", "foo2"))) +print("foobar".startswith(("foo", ))) + try: "foobar".startswith(1) except TypeError: diff --git a/tests/basics/string_startswith_upy.py b/tests/basics/string_startswith_upy.py deleted file mode 100644 index 9ea1796c218fd..0000000000000 --- a/tests/basics/string_startswith_upy.py +++ /dev/null @@ -1,6 +0,0 @@ -# MicroPython doesn't support tuple argument - -try: - "foobar".startswith(("foo", "sth")) -except TypeError: - print("TypeError") diff --git a/tests/basics/string_startswith_upy.py.exp b/tests/basics/string_startswith_upy.py.exp deleted file mode 100644 index 6002b71c56ea0..0000000000000 --- a/tests/basics/string_startswith_upy.py.exp +++ /dev/null @@ -1 +0,0 @@ -TypeError diff --git a/tests/basics/struct_overflow.py b/tests/basics/struct_overflow.py index c55870e1b4ae2..a3f9d055e7f8d 100644 --- a/tests/basics/struct_overflow.py +++ b/tests/basics/struct_overflow.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file import skip_if skip_if.no_bigint() diff --git a/tests/basics/subclass_classmethod.py b/tests/basics/subclass_classmethod.py index 00a2ebd7cd3bb..3089726aa9bf5 100644 --- a/tests/basics/subclass_classmethod.py +++ b/tests/basics/subclass_classmethod.py @@ -35,3 +35,34 @@ class B(A): B.bar() # class calling classmethod B().bar() # instance calling classmethod B().baz() # instance calling normal method + +# super inside a classmethod +# ensure the argument of the super method that is called is the child type + + +class C: + @classmethod + def f(cls): + print("C.f", cls.__name__) # cls should be D + + @classmethod + def g(cls): + print("C.g", cls.__name__) # cls should be D + + +class D(C): + @classmethod + def f(cls): + print("D.f", cls.__name__) + super().f() + + @classmethod + def g(cls): + print("D.g", cls.__name__) + super(D, cls).g() + + +D.f() +D.g() +D().f() +D().g() diff --git a/tests/basics/subclass_native1.py b/tests/basics/subclass_native1.py index 288a686d1a756..74b377eac91b9 100644 --- a/tests/basics/subclass_native1.py +++ b/tests/basics/subclass_native1.py @@ -21,11 +21,9 @@ class mylist(list): # TODO: Faults #print(a + a) -def foo(): - print("hello from foo") - +# subclassing a type that doesn't have make_new at the C level (not allowed) try: - class myfunc(type(foo)): + class myfunc(type([].append)): pass except TypeError: print("TypeError") diff --git a/tests/basics/subclass_native_call.py b/tests/basics/subclass_native_call.py new file mode 100644 index 0000000000000..e77287060cc70 --- /dev/null +++ b/tests/basics/subclass_native_call.py @@ -0,0 +1,27 @@ +# test calling a subclass of a native class that supports calling + +# For this test we need a native class that can be subclassed (has make_new) +# and is callable (has call). The only one available is machine.Signal, which +# in turns needs PinBase. +try: + import machine + machine.PinBase + machine.Signal +except: + print("SKIP") + raise SystemExit + +class Pin(machine.PinBase): + #def __init__(self): + # self.v = 0 + + def value(self, v=None): + return 42 + +class MySignal(machine.Signal): + pass + +s = MySignal(Pin()) + +# apply call to the subclass, which should call the native base +print(s()) diff --git a/tests/basics/subclass_native_call.py.exp b/tests/basics/subclass_native_call.py.exp new file mode 100644 index 0000000000000..d81cc0710eb6c --- /dev/null +++ b/tests/basics/subclass_native_call.py.exp @@ -0,0 +1 @@ +42 diff --git a/tests/basics/subclass_native_dict.py b/tests/basics/subclass_native_dict.py index fd333eec69ba6..073213a16766d 100644 --- a/tests/basics/subclass_native_dict.py +++ b/tests/basics/subclass_native_dict.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file class a: def __init__(self): self.d = {} diff --git a/tests/basics/subclass_native_init.py b/tests/basics/subclass_native_init.py index 38d2f23ac3814..102befd551fad 100644 --- a/tests/basics/subclass_native_init.py +++ b/tests/basics/subclass_native_init.py @@ -1,11 +1,44 @@ # test subclassing a native type and overriding __init__ +if not hasattr(object, "__init__"): + print("SKIP") + raise SystemExit + # overriding list.__init__() class L(list): def __init__(self, a, b): super().__init__([a, b]) print(L(2, 3)) +# with keyword arguments, with star arguments and without because those use different C calls +class D(dict): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) +print(D()) +print(D([('a', 1)])) +print(D([('a', 1)], a=2, b=3)) +print(D(a=2, b=3)) + +class D(dict): + def __init__(self): + super().__init__() +print(D()) + +class D(dict): + def __init__(self): + super().__init__([]) +print(D()) + +class D(dict): + def __init__(self): + super().__init__(a=1) +print(D()) + +class D(dict): + def __init__(self): + super().__init__([], a=1) +print(D()) + # inherits implicitly from object class A: def __init__(self): diff --git a/tests/basics/subscr_tuple.py b/tests/basics/subscr_tuple.py index 0210e24df873d..3b2703b829f89 100644 --- a/tests/basics/subscr_tuple.py +++ b/tests/basics/subscr_tuple.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this test file # subscripting a subclassed tuple class Foo(tuple): pass diff --git a/tests/basics/syntaxerror.py b/tests/basics/syntaxerror.py index c0702cb24525e..7b6ef9b7550ea 100644 --- a/tests/basics/syntaxerror.py +++ b/tests/basics/syntaxerror.py @@ -86,7 +86,7 @@ def test_syntax(code): test_syntax("nonlocal a") test_syntax("await 1") -# error on uPy, warning on CPy +# error on MPy, warning on CPy #test_syntax("def f():\n a = 1\n global a") # default except must be last @@ -98,7 +98,7 @@ def test_syntax(code): # non-keyword after keyword test_syntax("f(a=1, 2)") -# doesn't error on uPy but should +# doesn't error on MPy but should #test_syntax("f(1, i for i in i)") # all elements of dict/set must be pairs or singles diff --git a/tests/basics/sys1.py b/tests/basics/sys1.py index 6266440e353ca..02946abc220be 100644 --- a/tests/basics/sys1.py +++ b/tests/basics/sys1.py @@ -25,6 +25,18 @@ # Effectively skip subtests print(int) +if hasattr(sys.implementation, '_build'): + print(type(sys.implementation._build)) +else: + # Effectively skip subtests + print(str) + +if hasattr(sys.implementation, '_thread'): + print(sys.implementation._thread in ("GIL", "unsafe")) +else: + # Effectively skip subtests + print(True) + try: print(sys.intern('micropython') == 'micropython') has_intern = True diff --git a/tests/basics/sys_stdio.py b/tests/basics/sys_stdio.py new file mode 100644 index 0000000000000..8d746b8b4b257 --- /dev/null +++ b/tests/basics/sys_stdio.py @@ -0,0 +1,21 @@ +# Test sys.std* objects. + +import sys + +try: + sys.stdout + sys.stdin + sys.stderr +except AttributeError: + print("SKIP") + raise SystemExit + +# CPython is more verbose; no need to match exactly + +print('TextIOWrapper' in str(sys.stdout)) +print('TextIOWrapper' in str(sys.stderr)) +print('TextIOWrapper' in str(sys.stdin)) + +print('TextIOWrapper' in str(type(sys.stdout))) +print('TextIOWrapper' in str(type(sys.stderr))) +print('TextIOWrapper' in str(type(sys.stdin))) diff --git a/tests/basics/sys_stdio_buffer.py b/tests/basics/sys_stdio_buffer.py new file mode 100644 index 0000000000000..ae354ec7fbec1 --- /dev/null +++ b/tests/basics/sys_stdio_buffer.py @@ -0,0 +1,21 @@ +# Test sys.std*.buffer objects. + +import sys + +try: + sys.stdout.buffer + sys.stdin.buffer + sys.stderr.buffer +except AttributeError: + print("SKIP") + raise SystemExit + +# CPython is more verbose; no need to match exactly + +print('FileIO' in str(sys.stdout.buffer)) +print('FileIO' in str(sys.stderr.buffer)) +print('FileIO' in str(sys.stdin.buffer)) + +print('FileIO' in str(type(sys.stdout.buffer))) +print('FileIO' in str(type(sys.stderr.buffer))) +print('FileIO' in str(type(sys.stdin.buffer))) diff --git a/tests/basics/sys_stdio_buffer.py.exp b/tests/basics/sys_stdio_buffer.py.exp new file mode 100644 index 0000000000000..681c7ec9e8402 --- /dev/null +++ b/tests/basics/sys_stdio_buffer.py.exp @@ -0,0 +1,6 @@ +True +True +True +True +True +True diff --git a/tests/basics/sys_tracebacklimit.py b/tests/basics/sys_tracebacklimit.py index 3ae372b8d524e..6f575fde65404 100644 --- a/tests/basics/sys_tracebacklimit.py +++ b/tests/basics/sys_tracebacklimit.py @@ -30,7 +30,7 @@ def print_exc(e): if l.startswith(" File "): l = l.split('"') print(l[0], l[2]) - # uPy and CPy tracebacks differ in that CPy prints a source line for + # MPy and CPy tracebacks differ in that CPy prints a source line for # each traceback entry. In this case, we know that offending line # has 4-space indent, so filter it out. elif not l.startswith(" "): diff --git a/tests/basics/sys_tracebacklimit.py.native.exp b/tests/basics/sys_tracebacklimit.py.native.exp new file mode 100644 index 0000000000000..f9d30c058564b --- /dev/null +++ b/tests/basics/sys_tracebacklimit.py.native.exp @@ -0,0 +1,22 @@ +ValueError: value + +limit 4 +ValueError: value + +limit 3 +ValueError: value + +limit 2 +ValueError: value + +limit 1 +ValueError: value + +limit 0 +ValueError: value + +limit -1 +ValueError: value + +True +False diff --git a/tests/basics/try_finally_continue.py.exp b/tests/basics/try_finally_continue.py.exp deleted file mode 100644 index 2901997b1aa18..0000000000000 --- a/tests/basics/try_finally_continue.py.exp +++ /dev/null @@ -1,9 +0,0 @@ -4 0 -continue -4 1 -continue -4 2 -continue -4 3 -continue -None diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py index 72bb3f01bff4a..70ae071898e5b 100644 --- a/tests/basics/tuple1.py +++ b/tests/basics/tuple1.py @@ -17,7 +17,7 @@ x += (10, 11, 12) print(x) -# construction of tuple from large iterator (tests implementation detail of uPy) +# construction of tuple from large iterator (tests implementation detail of MicroPython) print(tuple(range(20))) # unsupported unary operation diff --git a/tests/basics/with_return.py b/tests/basics/with_return.py index af65a5b984383..f2083d2aec20d 100644 --- a/tests/basics/with_return.py +++ b/tests/basics/with_return.py @@ -30,7 +30,7 @@ def f(): return (i, j) print(f()) -# multiple for loops within nested with statements +# multiple for loops within nested with's def f(): with CtxMgr(1): for i in [1, 2]: @@ -41,7 +41,7 @@ def f(): return (i, j, k, l) print(f()) -# multiple for loops that are optimised, and nested with statements +# multiple for loops that are optimised, and nested with's def f(): with CtxMgr(1): for i in range(1, 3): diff --git a/tests/circuitpython-manual/audiobusio/i2s_sample_loop.py b/tests/circuitpython-manual/audiobusio/i2s_sample_loop.py index 75ed4c7ae6f30..9778ac2b82025 100644 --- a/tests/circuitpython-manual/audiobusio/i2s_sample_loop.py +++ b/tests/circuitpython-manual/audiobusio/i2s_sample_loop.py @@ -1,35 +1,73 @@ +# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries +# +# SPDX-License-Identifier: MIT import audiocore -import audiobusio import board import digitalio import array +import struct import time import math -import rp2pio -import adafruit_pioasm - -time.sleep(10) trigger = digitalio.DigitalInOut(board.D4) trigger.switch_to_output(True) # Generate one period of sine wav. -length = 8000 // 440 +sample_names = [ + "mono unsigned 8 bit", + "stereo unsigned 8 bit", + "mono signed 8 bit", + "stereo signed 8 bit", + "mono unsigned 16 bit", + "stereo unsigned 16 bit", + "mono signed 16 bit", + "stereo signed 16 bit", +] +sample_config = { + "mono unsigned 8 bit": {"format": "B", "channel_count": 1}, + "stereo unsigned 8 bit": {"format": "B", "channel_count": 2}, + "mono signed 8 bit": {"format": "b", "channel_count": 1}, + "stereo signed 8 bit": {"format": "b", "channel_count": 2}, + "mono unsigned 16 bit": {"format": "H", "channel_count": 1}, + "stereo unsigned 16 bit": {"format": "H", "channel_count": 2}, + "mono signed 16 bit": {"format": "h", "channel_count": 1}, + "stereo signed 16 bit": {"format": "h", "channel_count": 2}, +} -# signed 16 bit -s16 = array.array("h", [0] * length) -for i in range(length): - s16[i] = int(math.sin(math.pi * 2 * i / length) * (2**15)) - print(s16[i]) +for sample_rate in [8000, 16000, 32000, 44100]: + print(f"{sample_rate / 1000} kHz") + length = sample_rate // 440 -sample = audiocore.RawSample(s16, sample_rate=8000) + samples = [] -dac = audiobusio.I2SOut(bit_clock=board.D10, word_select=board.D11, data=board.D12) + for name in sample_names: + config = sample_config[name] + format = config["format"] + channel_count = config["channel_count"] + length = sample_rate // 440 + values = [] + for i in range(length): + range = 2 ** (struct.calcsize(format) * 8 - 1) - 1 + value = int(math.sin(math.pi * 2 * i / length) * range) + if "unsigned" in name: + value += range + values.append(value) + if channel_count == 2: + values.append(value) + sample = audiocore.RawSample( + array.array(format, values), sample_rate=sample_rate, channel_count=channel_count + ) + samples.append(sample) -trigger.value = False -dac.play(sample, loop=True) -time.sleep(1) -dac.stop() -trigger.value = True + dac = board.I2S0() + for sample, name in zip(samples, sample_names): + print(" ", name) + trigger.value = False + dac.play(sample, loop=True) + time.sleep(1) + dac.stop() + time.sleep(0.1) + trigger.value = True + print() print("done") diff --git a/tests/circuitpython-manual/pwmio/code_extremes.py b/tests/circuitpython-manual/pwmio/code_extremes.py index 13dd5c90ad1a2..4ca8b2f70fa24 100644 --- a/tests/circuitpython-manual/pwmio/code_extremes.py +++ b/tests/circuitpython-manual/pwmio/code_extremes.py @@ -80,7 +80,7 @@ if time.monotonic() > freq_time: break t0 = freq_time - print(f"({freq}, {i/freq_duration:.0f}), ", end="") + print(f"({freq}, {i / freq_duration:.0f}), ", end="") print(")") print("done.") pwm.deinit() diff --git a/tests/circuitpython-manual/pwmio/code_ramps.py b/tests/circuitpython-manual/pwmio/code_ramps.py index 6a06e4eff6bbc..e0d4901894f75 100644 --- a/tests/circuitpython-manual/pwmio/code_ramps.py +++ b/tests/circuitpython-manual/pwmio/code_ramps.py @@ -96,7 +96,7 @@ if time.monotonic() > freq_time: break t0 = freq_time - print(f"({freq}, {i/freq_duration:.0f}), ", end="") + print(f"({freq}, {i / freq_duration:.0f}), ", end="") print(")") print("done.") pwm.deinit() diff --git a/tests/circuitpython-manual/pwmio/duty.py b/tests/circuitpython-manual/pwmio/duty.py index 0673f96c2b64a..f5c3abd471ddd 100644 --- a/tests/circuitpython-manual/pwmio/duty.py +++ b/tests/circuitpython-manual/pwmio/duty.py @@ -107,7 +107,7 @@ def read( for duty in duty_labels: draw.text( (left - 10, y0 + (y1 - y0) * (1 - duty)), - f"{int(100*duty):d}%", + f"{int(100 * duty):d}%", duty_color, anchor="rm", ) diff --git a/tests/circuitpython-manual/synthio/note/biquad.py b/tests/circuitpython-manual/synthio/note/biquad.py index b4136a957fca6..306c4fd637fe6 100644 --- a/tests/circuitpython-manual/synthio/note/biquad.py +++ b/tests/circuitpython-manual/synthio/note/biquad.py @@ -24,33 +24,39 @@ ) noise = np.array([random.randint(-VOLUME, VOLUME) for i in range(SAMPLE_SIZE)], dtype=np.int16) bend_out = np.linspace(0, 32767, num=SAMPLE_SIZE, endpoint=True, dtype=np.int16) +sweep = np.linspace(-32767, 32767, num=SAMPLE_SIZE, endpoint=True, dtype=np.int16) + +lfos_of_interest = [] def synthesize(synth): - for waveform in (sine, None, noise): - for biquad in ( - None, - synth.low_pass_filter(120), - ): - for midi_note in range(24, 90, 3): - n = synthio.Note( - frequency=synthio.midi_to_hz(midi_note), - envelope=envelope, - filter=biquad, - waveform=waveform, - bend=synthio.LFO(bend_out, once=True, rate=1 / 2, scale=5), - ) - - synth.press(n) - print(n.frequency) - yield 24 - synth.release_all() - yield 16 - yield 24 - yield 48 - - -with wave.open("biquad.wav", "w") as f: + freq_sweep = synthio.LFO( + sweep, offset=synthio.midi_to_hz(72), scale=synthio.midi_to_hz(72), rate=1, once=True + ) + + for biquad in ( + None, + synthio.Biquad(synthio.FilterMode.LOW_PASS, freq_sweep), + synthio.Biquad(synthio.FilterMode.HIGH_PASS, freq_sweep), + synthio.Biquad(synthio.FilterMode.BAND_PASS, freq_sweep, Q=8), + synthio.Biquad(synthio.FilterMode.NOTCH, freq_sweep, Q=8), + ): + n = synthio.Note( + frequency=synthio.midi_to_hz(72), + envelope=envelope, + filter=biquad, + waveform=sine, + ) + + freq_sweep.retrigger() + synth.press(n) + print("n", n.frequency) + yield 24 * 6 + synth.release_all() + yield 24 + + +with wave.open("blockfilter.wav", "w") as f: f.setnchannels(1) f.setsampwidth(2) f.setframerate(48000) diff --git a/tests/circuitpython-manual/usb/basic_mouse.py b/tests/circuitpython-manual/usb/basic_mouse.py index a3228610a43ea..156895fd25d76 100644 --- a/tests/circuitpython-manual/usb/basic_mouse.py +++ b/tests/circuitpython-manual/usb/basic_mouse.py @@ -17,6 +17,8 @@ if device.is_kernel_driver_active(0): device.detach_kernel_driver(0) +device.set_configuration() + # Boot mice have 4 byte reports buf = array.array("b", [0] * 4) report_count = 0 diff --git a/tests/circuitpython-manual/usb/device_info.py b/tests/circuitpython-manual/usb/device_info.py index 7b8631a8f865a..3481707055507 100644 --- a/tests/circuitpython-manual/usb/device_info.py +++ b/tests/circuitpython-manual/usb/device_info.py @@ -9,7 +9,8 @@ d.switch_to_output(value=True) print("USB power on") -h = usb_host.Port(board.USB_HOST_DP, board.USB_HOST_DM) +if hasattr(board, "USB_HOST_DP") and hasattr(board, "USB_HOST_DM"): + h = usb_host.Port(board.USB_HOST_DP, board.USB_HOST_DM) while True: for device in usb.core.find(find_all=True): diff --git a/tests/circuitpython-manual/usb/displayio_mouse.py b/tests/circuitpython-manual/usb/displayio_mouse.py new file mode 100644 index 0000000000000..8dd2b1e482604 --- /dev/null +++ b/tests/circuitpython-manual/usb/displayio_mouse.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2025 Tim Cocks for Adafruit Industries +# SPDX-License-Identifier: MIT +import terminalio +import array +import usb.core +import supervisor +from displayio import Group, OnDiskBitmap, TileGrid +from adafruit_display_text.bitmap_label import Label + +display = supervisor.runtime.display + +main_group = Group() +display.root_group = main_group + +mouse_bmp = OnDiskBitmap("mouse_cursor.bmp") +mouse_bmp.pixel_shader.make_transparent(0) +mouse_tg = TileGrid(mouse_bmp, pixel_shader=mouse_bmp.pixel_shader) +mouse_tg.x = display.width // 2 +mouse_tg.y = display.height // 2 + +output_lbl = Label(terminalio.FONT, text=f"{mouse_tg.x},{mouse_tg.y}", color=0xFFFFFF, scale=1) +output_lbl.anchor_point = (0, 0) +output_lbl.anchored_position = (1, 1) +main_group.append(output_lbl) + +main_group.append(mouse_tg) + +# This is a basic Microsoft optical mouse with two buttons and a wheel that can +# also be pressed. +USB_VID = 0x046D +USB_PID = 0xC52F +# This is ordered by bit position. +BUTTONS = ["left", "right", "middle"] + +for device in usb.core.find(find_all=True): + print(f"{device.idVendor:04x}:{device.idProduct:04x}") + print(device.manufacturer, device.product) + print(device.serial_number) + if device.idVendor == USB_VID and device.idProduct == USB_PID: + mouse = device +# +print(mouse.manufacturer, mouse.product) + +if mouse.is_kernel_driver_active(0): + mouse.detach_kernel_driver(0) + +mouse.set_configuration() + +# Boot mice have 4 byte reports +buf = array.array("b", [0] * 4) +report_count = 0 + +# try: +while True: + try: + count = mouse.read(0x81, buf, timeout=10) + except usb.core.USBTimeoutError: + continue + + mouse_tg.x = max(0, min(display.width - 1, mouse_tg.x + buf[1])) + mouse_tg.y = max(0, min(display.height - 1, mouse_tg.y + buf[2])) + out_str = f"{mouse_tg.x},{mouse_tg.y}" + for i, button in enumerate(BUTTONS): + if buf[0] & (1 << i) != 0: + out_str += f" {button}" + + output_lbl.text = out_str diff --git a/tests/circuitpython-manual/usb/mouse_cursor.bmp b/tests/circuitpython-manual/usb/mouse_cursor.bmp new file mode 100644 index 0000000000000..94ec328896cfb Binary files /dev/null and b/tests/circuitpython-manual/usb/mouse_cursor.bmp differ diff --git a/tests/circuitpython/aes.py b/tests/circuitpython/aes.py index b47c4279d326b..7e614118e5d5a 100644 --- a/tests/circuitpython/aes.py +++ b/tests/circuitpython/aes.py @@ -100,7 +100,10 @@ print("truncated-CTR-1") ## Truncated CTR test case -plaintext = unhexlify("6bc1bee22e409f96e93d7e117393172a" "ae2d") +plaintext = unhexlify( + "6bc1bee22e409f96e93d7e117393172a" + "ae2d" +) # fmt: skip key = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") counter = unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") @@ -122,7 +125,10 @@ print("truncated-CTR-2") ## Truncated CTR test case #2 -plaintext = unhexlify("6bc1bee22e409f96e93d7e117393172a" "ae") +plaintext = unhexlify( + "6bc1bee22e409f96e93d7e117393172a" + "ae" +) # fmt: skip key = unhexlify("2b7e151628aed2a6abf7158809cf4f3c") counter = unhexlify("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff") diff --git a/tests/circuitpython/audiofilter_filter.py b/tests/circuitpython/audiofilter_filter.py new file mode 100644 index 0000000000000..8081c8a6fbd5f --- /dev/null +++ b/tests/circuitpython/audiofilter_filter.py @@ -0,0 +1,17 @@ +from audiofilters import Filter +from audiofilterhelper import synth_test, sine8k + + +@synth_test +def basic_filter(): + effect = Filter( + bits_per_sample=16, + samples_signed=True, + ) + yield effect, [] + + effect.play(sine8k, loop=True) + yield 4 + + effect.stop() + yield 2 diff --git a/tests/circuitpython/audiofilter_filter.py.exp b/tests/circuitpython/audiofilter_filter.py.exp new file mode 100644 index 0000000000000..734ac16b3a799 --- /dev/null +++ b/tests/circuitpython/audiofilter_filter.py.exp @@ -0,0 +1,1536 @@ +0 0.0 +1 0.010467529296875 +2 0.02093505859375 +3 0.031402587890625 +4 0.0418701171875 +5 0.05230712890625 +6 0.062774658203125 +7 0.073211669921875 +8 0.083648681640625 +9 0.094085693359375 +10 0.104522705078125 +11 0.11492919921875 +12 0.12530517578125 +13 0.13568115234375 +14 0.14605712890625 +15 0.156402587890625 +16 0.166748046875 +17 0.17706298828125 +18 0.187347412109375 +19 0.1976318359375 +20 0.2078857421875 +21 0.218109130859375 +22 0.22833251953125 +23 0.238525390625 +24 0.2486572265625 +25 0.2587890625 +26 0.268890380859375 +27 0.278961181640625 +28 0.28900146484375 +29 0.29901123046875 +30 0.308990478515625 +31 0.318939208984375 +32 0.328826904296875 +33 0.338714599609375 +34 0.348541259765625 +35 0.35833740234375 +36 0.36810302734375 +37 0.3778076171875 +38 0.387481689453125 +39 0.397125244140625 +40 0.406707763671875 +41 0.416259765625 +42 0.425750732421875 +43 0.435211181640625 +44 0.444610595703125 +45 0.453948974609375 +46 0.4632568359375 +47 0.4725341796875 +48 0.481719970703125 +49 0.490875244140625 +50 0.499969482421875 +51 0.509002685546875 +52 0.51800537109375 +53 0.52691650390625 +54 0.535797119140625 +55 0.54461669921875 +56 0.5533447265625 +57 0.562042236328125 +58 0.5706787109375 +59 0.579254150390625 +60 0.587738037109375 +61 0.59619140625 +62 0.60455322265625 +63 0.612884521484375 +64 0.621124267578125 +65 0.6292724609375 +66 0.63739013671875 +67 0.645416259765625 +68 0.65338134765625 +69 0.661285400390625 +70 0.669097900390625 +71 0.676849365234375 +72 0.68450927734375 +73 0.692108154296875 +74 0.699615478515625 +75 0.707061767578125 +76 0.714447021484375 +77 0.721710205078125 +78 0.72894287109375 +79 0.736053466796875 +80 0.74310302734375 +81 0.75006103515625 +82 0.7569580078125 +83 0.763763427734375 +84 0.770477294921875 +85 0.777099609375 +86 0.783660888671875 +87 0.790130615234375 +88 0.796478271484375 +89 0.802764892578125 +90 0.808990478515625 +91 0.815093994140625 +92 0.82110595703125 +93 0.8270263671875 +94 0.8328857421875 +95 0.838623046875 +96 0.84429931640625 +97 0.849853515625 +98 0.855316162109375 +99 0.860687255859375 +100 0.865997314453125 +101 0.871185302734375 +102 0.876251220703125 +103 0.881256103515625 +104 0.88616943359375 +105 0.890960693359375 +106 0.895660400390625 +107 0.9002685546875 +108 0.90478515625 +109 0.9091796875 +110 0.91351318359375 +111 0.917724609375 +112 0.92181396484375 +113 0.92584228515625 +114 0.929718017578125 +115 0.93353271484375 +116 0.937225341796875 +117 0.940826416015625 +118 0.9443359375 +119 0.947723388671875 +120 0.951019287109375 +121 0.954193115234375 +122 0.957275390625 +123 0.960235595703125 +124 0.963104248046875 +125 0.96588134765625 +126 0.968536376953125 +127 0.971099853515625 +128 0.973541259765625 +129 0.975860595703125 +130 0.97808837890625 +131 0.980224609375 +132 0.98223876953125 +133 0.984161376953125 +134 0.9859619140625 +135 0.987640380859375 +136 0.989227294921875 +137 0.990692138671875 +138 0.9920654296875 +139 0.993316650390625 +140 0.994476318359375 +141 0.995513916015625 +142 0.9964599609375 +143 0.997283935546875 +144 0.99798583984375 +145 0.99859619140625 +146 0.99908447265625 +147 0.99945068359375 +148 0.999725341796875 +149 0.999908447265625 +150 0.999969482421875 +151 0.999908447265625 +152 0.999725341796875 +153 0.99945068359375 +154 0.99908447265625 +155 0.99859619140625 +156 0.99798583984375 +157 0.997283935546875 +158 0.9964599609375 +159 0.995513916015625 +160 0.994476318359375 +161 0.993316650390625 +162 0.9920654296875 +163 0.990692138671875 +164 0.989227294921875 +165 0.987640380859375 +166 0.9859619140625 +167 0.984161376953125 +168 0.98223876953125 +169 0.980224609375 +170 0.97808837890625 +171 0.975860595703125 +172 0.973541259765625 +173 0.971099853515625 +174 0.968536376953125 +175 0.96588134765625 +176 0.963104248046875 +177 0.960235595703125 +178 0.957275390625 +179 0.954193115234375 +180 0.951019287109375 +181 0.947723388671875 +182 0.9443359375 +183 0.940826416015625 +184 0.937225341796875 +185 0.93353271484375 +186 0.929718017578125 +187 0.92584228515625 +188 0.92181396484375 +189 0.917724609375 +190 0.91351318359375 +191 0.9091796875 +192 0.90478515625 +193 0.9002685546875 +194 0.895660400390625 +195 0.890960693359375 +196 0.88616943359375 +197 0.881256103515625 +198 0.876251220703125 +199 0.871185302734375 +200 0.865997314453125 +201 0.860687255859375 +202 0.855316162109375 +203 0.849853515625 +204 0.84429931640625 +205 0.838623046875 +206 0.8328857421875 +207 0.8270263671875 +208 0.82110595703125 +209 0.815093994140625 +210 0.808990478515625 +211 0.802764892578125 +212 0.796478271484375 +213 0.790130615234375 +214 0.783660888671875 +215 0.777099609375 +216 0.770477294921875 +217 0.763763427734375 +218 0.7569580078125 +219 0.75006103515625 +220 0.74310302734375 +221 0.736053466796875 +222 0.72894287109375 +223 0.721710205078125 +224 0.714447021484375 +225 0.707061767578125 +226 0.699615478515625 +227 0.692108154296875 +228 0.68450927734375 +229 0.676849365234375 +230 0.669097900390625 +231 0.661285400390625 +232 0.65338134765625 +233 0.645416259765625 +234 0.63739013671875 +235 0.6292724609375 +236 0.621124267578125 +237 0.612884521484375 +238 0.60455322265625 +239 0.59619140625 +240 0.587738037109375 +241 0.579254150390625 +242 0.5706787109375 +243 0.562042236328125 +244 0.5533447265625 +245 0.54461669921875 +246 0.535797119140625 +247 0.52691650390625 +248 0.51800537109375 +249 0.509002685546875 +250 0.499969482421875 +251 0.490875244140625 +252 0.481719970703125 +253 0.4725341796875 +254 0.4632568359375 +255 0.453948974609375 +256 0.444610595703125 +257 0.435211181640625 +258 0.425750732421875 +259 0.416259765625 +260 0.406707763671875 +261 0.397125244140625 +262 0.387481689453125 +263 0.3778076171875 +264 0.36810302734375 +265 0.35833740234375 +266 0.348541259765625 +267 0.338714599609375 +268 0.328826904296875 +269 0.318939208984375 +270 0.308990478515625 +271 0.29901123046875 +272 0.28900146484375 +273 0.278961181640625 +274 0.268890380859375 +275 0.2587890625 +276 0.2486572265625 +277 0.238525390625 +278 0.22833251953125 +279 0.218109130859375 +280 0.2078857421875 +281 0.1976318359375 +282 0.187347412109375 +283 0.17706298828125 +284 0.166748046875 +285 0.156402587890625 +286 0.14605712890625 +287 0.13568115234375 +288 0.12530517578125 +289 0.11492919921875 +290 0.104522705078125 +291 0.094085693359375 +292 0.083648681640625 +293 0.073211669921875 +294 0.062774658203125 +295 0.05230712890625 +296 0.0418701171875 +297 0.031402587890625 +298 0.02093505859375 +299 0.010467529296875 +300 0.0 +301 -0.010467529296875 +302 -0.02093505859375 +303 -0.031402587890625 +304 -0.0418701171875 +305 -0.05230712890625 +306 -0.062774658203125 +307 -0.073211669921875 +308 -0.083648681640625 +309 -0.094085693359375 +310 -0.104522705078125 +311 -0.11492919921875 +312 -0.12530517578125 +313 -0.13568115234375 +314 -0.14605712890625 +315 -0.156402587890625 +316 -0.166748046875 +317 -0.17706298828125 +318 -0.187347412109375 +319 -0.1976318359375 +320 -0.2078857421875 +321 -0.218109130859375 +322 -0.22833251953125 +323 -0.238525390625 +324 -0.2486572265625 +325 -0.2587890625 +326 -0.268890380859375 +327 -0.278961181640625 +328 -0.28900146484375 +329 -0.29901123046875 +330 -0.308990478515625 +331 -0.318939208984375 +332 -0.328826904296875 +333 -0.338714599609375 +334 -0.348541259765625 +335 -0.35833740234375 +336 -0.36810302734375 +337 -0.3778076171875 +338 -0.387481689453125 +339 -0.397125244140625 +340 -0.406707763671875 +341 -0.416259765625 +342 -0.425750732421875 +343 -0.435211181640625 +344 -0.444610595703125 +345 -0.453948974609375 +346 -0.4632568359375 +347 -0.4725341796875 +348 -0.481719970703125 +349 -0.490875244140625 +350 -0.499969482421875 +351 -0.509002685546875 +352 -0.51800537109375 +353 -0.52691650390625 +354 -0.535797119140625 +355 -0.54461669921875 +356 -0.5533447265625 +357 -0.562042236328125 +358 -0.5706787109375 +359 -0.579254150390625 +360 -0.587738037109375 +361 -0.59619140625 +362 -0.60455322265625 +363 -0.612884521484375 +364 -0.621124267578125 +365 -0.6292724609375 +366 -0.63739013671875 +367 -0.645416259765625 +368 -0.65338134765625 +369 -0.661285400390625 +370 -0.669097900390625 +371 -0.676849365234375 +372 -0.68450927734375 +373 -0.692108154296875 +374 -0.699615478515625 +375 -0.707061767578125 +376 -0.714447021484375 +377 -0.721710205078125 +378 -0.72894287109375 +379 -0.736053466796875 +380 -0.74310302734375 +381 -0.75006103515625 +382 -0.7569580078125 +383 -0.763763427734375 +384 -0.770477294921875 +385 -0.777099609375 +386 -0.783660888671875 +387 -0.790130615234375 +388 -0.796478271484375 +389 -0.802764892578125 +390 -0.808990478515625 +391 -0.815093994140625 +392 -0.82110595703125 +393 -0.8270263671875 +394 -0.8328857421875 +395 -0.838623046875 +396 -0.84429931640625 +397 -0.849853515625 +398 -0.855316162109375 +399 -0.860687255859375 +400 -0.865997314453125 +401 -0.871185302734375 +402 -0.876251220703125 +403 -0.881256103515625 +404 -0.88616943359375 +405 -0.890960693359375 +406 -0.895660400390625 +407 -0.9002685546875 +408 -0.90478515625 +409 -0.9091796875 +410 -0.91351318359375 +411 -0.917724609375 +412 -0.92181396484375 +413 -0.92584228515625 +414 -0.929718017578125 +415 -0.93353271484375 +416 -0.937225341796875 +417 -0.940826416015625 +418 -0.9443359375 +419 -0.947723388671875 +420 -0.951019287109375 +421 -0.954193115234375 +422 -0.957275390625 +423 -0.960235595703125 +424 -0.963104248046875 +425 -0.96588134765625 +426 -0.968536376953125 +427 -0.971099853515625 +428 -0.973541259765625 +429 -0.975860595703125 +430 -0.97808837890625 +431 -0.980224609375 +432 -0.98223876953125 +433 -0.984161376953125 +434 -0.9859619140625 +435 -0.987640380859375 +436 -0.989227294921875 +437 -0.990692138671875 +438 -0.9920654296875 +439 -0.993316650390625 +440 -0.994476318359375 +441 -0.995513916015625 +442 -0.9964599609375 +443 -0.997283935546875 +444 -0.99798583984375 +445 -0.99859619140625 +446 -0.99908447265625 +447 -0.99945068359375 +448 -0.999725341796875 +449 -0.999908447265625 +450 -0.999969482421875 +451 -0.999908447265625 +452 -0.999725341796875 +453 -0.99945068359375 +454 -0.99908447265625 +455 -0.99859619140625 +456 -0.99798583984375 +457 -0.997283935546875 +458 -0.9964599609375 +459 -0.995513916015625 +460 -0.994476318359375 +461 -0.993316650390625 +462 -0.9920654296875 +463 -0.990692138671875 +464 -0.989227294921875 +465 -0.987640380859375 +466 -0.9859619140625 +467 -0.984161376953125 +468 -0.98223876953125 +469 -0.980224609375 +470 -0.97808837890625 +471 -0.975860595703125 +472 -0.973541259765625 +473 -0.971099853515625 +474 -0.968536376953125 +475 -0.96588134765625 +476 -0.963104248046875 +477 -0.960235595703125 +478 -0.957275390625 +479 -0.954193115234375 +480 -0.951019287109375 +481 -0.947723388671875 +482 -0.9443359375 +483 -0.940826416015625 +484 -0.937225341796875 +485 -0.93353271484375 +486 -0.929718017578125 +487 -0.92584228515625 +488 -0.92181396484375 +489 -0.917724609375 +490 -0.91351318359375 +491 -0.9091796875 +492 -0.90478515625 +493 -0.9002685546875 +494 -0.895660400390625 +495 -0.890960693359375 +496 -0.88616943359375 +497 -0.881256103515625 +498 -0.876251220703125 +499 -0.871185302734375 +500 -0.865997314453125 +501 -0.860687255859375 +502 -0.855316162109375 +503 -0.849853515625 +504 -0.84429931640625 +505 -0.838623046875 +506 -0.8328857421875 +507 -0.8270263671875 +508 -0.82110595703125 +509 -0.815093994140625 +510 -0.808990478515625 +511 -0.802764892578125 +512 -0.796478271484375 +513 -0.790130615234375 +514 -0.783660888671875 +515 -0.777099609375 +516 -0.770477294921875 +517 -0.763763427734375 +518 -0.7569580078125 +519 -0.75006103515625 +520 -0.74310302734375 +521 -0.736053466796875 +522 -0.72894287109375 +523 -0.721710205078125 +524 -0.714447021484375 +525 -0.707061767578125 +526 -0.699615478515625 +527 -0.692108154296875 +528 -0.68450927734375 +529 -0.676849365234375 +530 -0.669097900390625 +531 -0.661285400390625 +532 -0.65338134765625 +533 -0.645416259765625 +534 -0.63739013671875 +535 -0.6292724609375 +536 -0.621124267578125 +537 -0.612884521484375 +538 -0.60455322265625 +539 -0.59619140625 +540 -0.587738037109375 +541 -0.579254150390625 +542 -0.5706787109375 +543 -0.562042236328125 +544 -0.5533447265625 +545 -0.54461669921875 +546 -0.535797119140625 +547 -0.52691650390625 +548 -0.51800537109375 +549 -0.509002685546875 +550 -0.499969482421875 +551 -0.490875244140625 +552 -0.481719970703125 +553 -0.4725341796875 +554 -0.4632568359375 +555 -0.453948974609375 +556 -0.444610595703125 +557 -0.435211181640625 +558 -0.425750732421875 +559 -0.416259765625 +560 -0.406707763671875 +561 -0.397125244140625 +562 -0.387481689453125 +563 -0.3778076171875 +564 -0.36810302734375 +565 -0.35833740234375 +566 -0.348541259765625 +567 -0.338714599609375 +568 -0.328826904296875 +569 -0.318939208984375 +570 -0.308990478515625 +571 -0.29901123046875 +572 -0.28900146484375 +573 -0.278961181640625 +574 -0.268890380859375 +575 -0.2587890625 +576 -0.2486572265625 +577 -0.238525390625 +578 -0.22833251953125 +579 -0.218109130859375 +580 -0.2078857421875 +581 -0.1976318359375 +582 -0.187347412109375 +583 -0.17706298828125 +584 -0.166748046875 +585 -0.156402587890625 +586 -0.14605712890625 +587 -0.13568115234375 +588 -0.12530517578125 +589 -0.11492919921875 +590 -0.104522705078125 +591 -0.094085693359375 +592 -0.083648681640625 +593 -0.073211669921875 +594 -0.062774658203125 +595 -0.05230712890625 +596 -0.0418701171875 +597 -0.031402587890625 +598 -0.02093505859375 +599 -0.010467529296875 +600 0.0 +601 0.010467529296875 +602 0.02093505859375 +603 0.031402587890625 +604 0.0418701171875 +605 0.05230712890625 +606 0.062774658203125 +607 0.073211669921875 +608 0.083648681640625 +609 0.094085693359375 +610 0.104522705078125 +611 0.11492919921875 +612 0.12530517578125 +613 0.13568115234375 +614 0.14605712890625 +615 0.156402587890625 +616 0.166748046875 +617 0.17706298828125 +618 0.187347412109375 +619 0.1976318359375 +620 0.2078857421875 +621 0.218109130859375 +622 0.22833251953125 +623 0.238525390625 +624 0.2486572265625 +625 0.2587890625 +626 0.268890380859375 +627 0.278961181640625 +628 0.28900146484375 +629 0.29901123046875 +630 0.308990478515625 +631 0.318939208984375 +632 0.328826904296875 +633 0.338714599609375 +634 0.348541259765625 +635 0.35833740234375 +636 0.36810302734375 +637 0.3778076171875 +638 0.387481689453125 +639 0.397125244140625 +640 0.406707763671875 +641 0.416259765625 +642 0.425750732421875 +643 0.435211181640625 +644 0.444610595703125 +645 0.453948974609375 +646 0.4632568359375 +647 0.4725341796875 +648 0.481719970703125 +649 0.490875244140625 +650 0.499969482421875 +651 0.509002685546875 +652 0.51800537109375 +653 0.52691650390625 +654 0.535797119140625 +655 0.54461669921875 +656 0.5533447265625 +657 0.562042236328125 +658 0.5706787109375 +659 0.579254150390625 +660 0.587738037109375 +661 0.59619140625 +662 0.60455322265625 +663 0.612884521484375 +664 0.621124267578125 +665 0.6292724609375 +666 0.63739013671875 +667 0.645416259765625 +668 0.65338134765625 +669 0.661285400390625 +670 0.669097900390625 +671 0.676849365234375 +672 0.68450927734375 +673 0.692108154296875 +674 0.699615478515625 +675 0.707061767578125 +676 0.714447021484375 +677 0.721710205078125 +678 0.72894287109375 +679 0.736053466796875 +680 0.74310302734375 +681 0.75006103515625 +682 0.7569580078125 +683 0.763763427734375 +684 0.770477294921875 +685 0.777099609375 +686 0.783660888671875 +687 0.790130615234375 +688 0.796478271484375 +689 0.802764892578125 +690 0.808990478515625 +691 0.815093994140625 +692 0.82110595703125 +693 0.8270263671875 +694 0.8328857421875 +695 0.838623046875 +696 0.84429931640625 +697 0.849853515625 +698 0.855316162109375 +699 0.860687255859375 +700 0.865997314453125 +701 0.871185302734375 +702 0.876251220703125 +703 0.881256103515625 +704 0.88616943359375 +705 0.890960693359375 +706 0.895660400390625 +707 0.9002685546875 +708 0.90478515625 +709 0.9091796875 +710 0.91351318359375 +711 0.917724609375 +712 0.92181396484375 +713 0.92584228515625 +714 0.929718017578125 +715 0.93353271484375 +716 0.937225341796875 +717 0.940826416015625 +718 0.9443359375 +719 0.947723388671875 +720 0.951019287109375 +721 0.954193115234375 +722 0.957275390625 +723 0.960235595703125 +724 0.963104248046875 +725 0.96588134765625 +726 0.968536376953125 +727 0.971099853515625 +728 0.973541259765625 +729 0.975860595703125 +730 0.97808837890625 +731 0.980224609375 +732 0.98223876953125 +733 0.984161376953125 +734 0.9859619140625 +735 0.987640380859375 +736 0.989227294921875 +737 0.990692138671875 +738 0.9920654296875 +739 0.993316650390625 +740 0.994476318359375 +741 0.995513916015625 +742 0.9964599609375 +743 0.997283935546875 +744 0.99798583984375 +745 0.99859619140625 +746 0.99908447265625 +747 0.99945068359375 +748 0.999725341796875 +749 0.999908447265625 +750 0.999969482421875 +751 0.999908447265625 +752 0.999725341796875 +753 0.99945068359375 +754 0.99908447265625 +755 0.99859619140625 +756 0.99798583984375 +757 0.997283935546875 +758 0.9964599609375 +759 0.995513916015625 +760 0.994476318359375 +761 0.993316650390625 +762 0.9920654296875 +763 0.990692138671875 +764 0.989227294921875 +765 0.987640380859375 +766 0.9859619140625 +767 0.984161376953125 +768 0.98223876953125 +769 0.980224609375 +770 0.97808837890625 +771 0.975860595703125 +772 0.973541259765625 +773 0.971099853515625 +774 0.968536376953125 +775 0.96588134765625 +776 0.963104248046875 +777 0.960235595703125 +778 0.957275390625 +779 0.954193115234375 +780 0.951019287109375 +781 0.947723388671875 +782 0.9443359375 +783 0.940826416015625 +784 0.937225341796875 +785 0.93353271484375 +786 0.929718017578125 +787 0.92584228515625 +788 0.92181396484375 +789 0.917724609375 +790 0.91351318359375 +791 0.9091796875 +792 0.90478515625 +793 0.9002685546875 +794 0.895660400390625 +795 0.890960693359375 +796 0.88616943359375 +797 0.881256103515625 +798 0.876251220703125 +799 0.871185302734375 +800 0.865997314453125 +801 0.860687255859375 +802 0.855316162109375 +803 0.849853515625 +804 0.84429931640625 +805 0.838623046875 +806 0.8328857421875 +807 0.8270263671875 +808 0.82110595703125 +809 0.815093994140625 +810 0.808990478515625 +811 0.802764892578125 +812 0.796478271484375 +813 0.790130615234375 +814 0.783660888671875 +815 0.777099609375 +816 0.770477294921875 +817 0.763763427734375 +818 0.7569580078125 +819 0.75006103515625 +820 0.74310302734375 +821 0.736053466796875 +822 0.72894287109375 +823 0.721710205078125 +824 0.714447021484375 +825 0.707061767578125 +826 0.699615478515625 +827 0.692108154296875 +828 0.68450927734375 +829 0.676849365234375 +830 0.669097900390625 +831 0.661285400390625 +832 0.65338134765625 +833 0.645416259765625 +834 0.63739013671875 +835 0.6292724609375 +836 0.621124267578125 +837 0.612884521484375 +838 0.60455322265625 +839 0.59619140625 +840 0.587738037109375 +841 0.579254150390625 +842 0.5706787109375 +843 0.562042236328125 +844 0.5533447265625 +845 0.54461669921875 +846 0.535797119140625 +847 0.52691650390625 +848 0.51800537109375 +849 0.509002685546875 +850 0.499969482421875 +851 0.490875244140625 +852 0.481719970703125 +853 0.4725341796875 +854 0.4632568359375 +855 0.453948974609375 +856 0.444610595703125 +857 0.435211181640625 +858 0.425750732421875 +859 0.416259765625 +860 0.406707763671875 +861 0.397125244140625 +862 0.387481689453125 +863 0.3778076171875 +864 0.36810302734375 +865 0.35833740234375 +866 0.348541259765625 +867 0.338714599609375 +868 0.328826904296875 +869 0.318939208984375 +870 0.308990478515625 +871 0.29901123046875 +872 0.28900146484375 +873 0.278961181640625 +874 0.268890380859375 +875 0.2587890625 +876 0.2486572265625 +877 0.238525390625 +878 0.22833251953125 +879 0.218109130859375 +880 0.2078857421875 +881 0.1976318359375 +882 0.187347412109375 +883 0.17706298828125 +884 0.166748046875 +885 0.156402587890625 +886 0.14605712890625 +887 0.13568115234375 +888 0.12530517578125 +889 0.11492919921875 +890 0.104522705078125 +891 0.094085693359375 +892 0.083648681640625 +893 0.073211669921875 +894 0.062774658203125 +895 0.05230712890625 +896 0.0418701171875 +897 0.031402587890625 +898 0.02093505859375 +899 0.010467529296875 +900 0.0 +901 -0.010467529296875 +902 -0.02093505859375 +903 -0.031402587890625 +904 -0.0418701171875 +905 -0.05230712890625 +906 -0.062774658203125 +907 -0.073211669921875 +908 -0.083648681640625 +909 -0.094085693359375 +910 -0.104522705078125 +911 -0.11492919921875 +912 -0.12530517578125 +913 -0.13568115234375 +914 -0.14605712890625 +915 -0.156402587890625 +916 -0.166748046875 +917 -0.17706298828125 +918 -0.187347412109375 +919 -0.1976318359375 +920 -0.2078857421875 +921 -0.218109130859375 +922 -0.22833251953125 +923 -0.238525390625 +924 -0.2486572265625 +925 -0.2587890625 +926 -0.268890380859375 +927 -0.278961181640625 +928 -0.28900146484375 +929 -0.29901123046875 +930 -0.308990478515625 +931 -0.318939208984375 +932 -0.328826904296875 +933 -0.338714599609375 +934 -0.348541259765625 +935 -0.35833740234375 +936 -0.36810302734375 +937 -0.3778076171875 +938 -0.387481689453125 +939 -0.397125244140625 +940 -0.406707763671875 +941 -0.416259765625 +942 -0.425750732421875 +943 -0.435211181640625 +944 -0.444610595703125 +945 -0.453948974609375 +946 -0.4632568359375 +947 -0.4725341796875 +948 -0.481719970703125 +949 -0.490875244140625 +950 -0.499969482421875 +951 -0.509002685546875 +952 -0.51800537109375 +953 -0.52691650390625 +954 -0.535797119140625 +955 -0.54461669921875 +956 -0.5533447265625 +957 -0.562042236328125 +958 -0.5706787109375 +959 -0.579254150390625 +960 -0.587738037109375 +961 -0.59619140625 +962 -0.60455322265625 +963 -0.612884521484375 +964 -0.621124267578125 +965 -0.6292724609375 +966 -0.63739013671875 +967 -0.645416259765625 +968 -0.65338134765625 +969 -0.661285400390625 +970 -0.669097900390625 +971 -0.676849365234375 +972 -0.68450927734375 +973 -0.692108154296875 +974 -0.699615478515625 +975 -0.707061767578125 +976 -0.714447021484375 +977 -0.721710205078125 +978 -0.72894287109375 +979 -0.736053466796875 +980 -0.74310302734375 +981 -0.75006103515625 +982 -0.7569580078125 +983 -0.763763427734375 +984 -0.770477294921875 +985 -0.777099609375 +986 -0.783660888671875 +987 -0.790130615234375 +988 -0.796478271484375 +989 -0.802764892578125 +990 -0.808990478515625 +991 -0.815093994140625 +992 -0.82110595703125 +993 -0.8270263671875 +994 -0.8328857421875 +995 -0.838623046875 +996 -0.84429931640625 +997 -0.849853515625 +998 -0.855316162109375 +999 -0.860687255859375 +1000 -0.865997314453125 +1001 -0.871185302734375 +1002 -0.876251220703125 +1003 -0.881256103515625 +1004 -0.88616943359375 +1005 -0.890960693359375 +1006 -0.895660400390625 +1007 -0.9002685546875 +1008 -0.90478515625 +1009 -0.9091796875 +1010 -0.91351318359375 +1011 -0.917724609375 +1012 -0.92181396484375 +1013 -0.92584228515625 +1014 -0.929718017578125 +1015 -0.93353271484375 +1016 -0.937225341796875 +1017 -0.940826416015625 +1018 -0.9443359375 +1019 -0.947723388671875 +1020 -0.951019287109375 +1021 -0.954193115234375 +1022 -0.957275390625 +1023 -0.960235595703125 +1024 0.0 +1025 0.0 +1026 0.0 +1027 0.0 +1028 0.0 +1029 0.0 +1030 0.0 +1031 0.0 +1032 0.0 +1033 0.0 +1034 0.0 +1035 0.0 +1036 0.0 +1037 0.0 +1038 0.0 +1039 0.0 +1040 0.0 +1041 0.0 +1042 0.0 +1043 0.0 +1044 0.0 +1045 0.0 +1046 0.0 +1047 0.0 +1048 0.0 +1049 0.0 +1050 0.0 +1051 0.0 +1052 0.0 +1053 0.0 +1054 0.0 +1055 0.0 +1056 0.0 +1057 0.0 +1058 0.0 +1059 0.0 +1060 0.0 +1061 0.0 +1062 0.0 +1063 0.0 +1064 0.0 +1065 0.0 +1066 0.0 +1067 0.0 +1068 0.0 +1069 0.0 +1070 0.0 +1071 0.0 +1072 0.0 +1073 0.0 +1074 0.0 +1075 0.0 +1076 0.0 +1077 0.0 +1078 0.0 +1079 0.0 +1080 0.0 +1081 0.0 +1082 0.0 +1083 0.0 +1084 0.0 +1085 0.0 +1086 0.0 +1087 0.0 +1088 0.0 +1089 0.0 +1090 0.0 +1091 0.0 +1092 0.0 +1093 0.0 +1094 0.0 +1095 0.0 +1096 0.0 +1097 0.0 +1098 0.0 +1099 0.0 +1100 0.0 +1101 0.0 +1102 0.0 +1103 0.0 +1104 0.0 +1105 0.0 +1106 0.0 +1107 0.0 +1108 0.0 +1109 0.0 +1110 0.0 +1111 0.0 +1112 0.0 +1113 0.0 +1114 0.0 +1115 0.0 +1116 0.0 +1117 0.0 +1118 0.0 +1119 0.0 +1120 0.0 +1121 0.0 +1122 0.0 +1123 0.0 +1124 0.0 +1125 0.0 +1126 0.0 +1127 0.0 +1128 0.0 +1129 0.0 +1130 0.0 +1131 0.0 +1132 0.0 +1133 0.0 +1134 0.0 +1135 0.0 +1136 0.0 +1137 0.0 +1138 0.0 +1139 0.0 +1140 0.0 +1141 0.0 +1142 0.0 +1143 0.0 +1144 0.0 +1145 0.0 +1146 0.0 +1147 0.0 +1148 0.0 +1149 0.0 +1150 0.0 +1151 0.0 +1152 0.0 +1153 0.0 +1154 0.0 +1155 0.0 +1156 0.0 +1157 0.0 +1158 0.0 +1159 0.0 +1160 0.0 +1161 0.0 +1162 0.0 +1163 0.0 +1164 0.0 +1165 0.0 +1166 0.0 +1167 0.0 +1168 0.0 +1169 0.0 +1170 0.0 +1171 0.0 +1172 0.0 +1173 0.0 +1174 0.0 +1175 0.0 +1176 0.0 +1177 0.0 +1178 0.0 +1179 0.0 +1180 0.0 +1181 0.0 +1182 0.0 +1183 0.0 +1184 0.0 +1185 0.0 +1186 0.0 +1187 0.0 +1188 0.0 +1189 0.0 +1190 0.0 +1191 0.0 +1192 0.0 +1193 0.0 +1194 0.0 +1195 0.0 +1196 0.0 +1197 0.0 +1198 0.0 +1199 0.0 +1200 0.0 +1201 0.0 +1202 0.0 +1203 0.0 +1204 0.0 +1205 0.0 +1206 0.0 +1207 0.0 +1208 0.0 +1209 0.0 +1210 0.0 +1211 0.0 +1212 0.0 +1213 0.0 +1214 0.0 +1215 0.0 +1216 0.0 +1217 0.0 +1218 0.0 +1219 0.0 +1220 0.0 +1221 0.0 +1222 0.0 +1223 0.0 +1224 0.0 +1225 0.0 +1226 0.0 +1227 0.0 +1228 0.0 +1229 0.0 +1230 0.0 +1231 0.0 +1232 0.0 +1233 0.0 +1234 0.0 +1235 0.0 +1236 0.0 +1237 0.0 +1238 0.0 +1239 0.0 +1240 0.0 +1241 0.0 +1242 0.0 +1243 0.0 +1244 0.0 +1245 0.0 +1246 0.0 +1247 0.0 +1248 0.0 +1249 0.0 +1250 0.0 +1251 0.0 +1252 0.0 +1253 0.0 +1254 0.0 +1255 0.0 +1256 0.0 +1257 0.0 +1258 0.0 +1259 0.0 +1260 0.0 +1261 0.0 +1262 0.0 +1263 0.0 +1264 0.0 +1265 0.0 +1266 0.0 +1267 0.0 +1268 0.0 +1269 0.0 +1270 0.0 +1271 0.0 +1272 0.0 +1273 0.0 +1274 0.0 +1275 0.0 +1276 0.0 +1277 0.0 +1278 0.0 +1279 0.0 +1280 0.0 +1281 0.0 +1282 0.0 +1283 0.0 +1284 0.0 +1285 0.0 +1286 0.0 +1287 0.0 +1288 0.0 +1289 0.0 +1290 0.0 +1291 0.0 +1292 0.0 +1293 0.0 +1294 0.0 +1295 0.0 +1296 0.0 +1297 0.0 +1298 0.0 +1299 0.0 +1300 0.0 +1301 0.0 +1302 0.0 +1303 0.0 +1304 0.0 +1305 0.0 +1306 0.0 +1307 0.0 +1308 0.0 +1309 0.0 +1310 0.0 +1311 0.0 +1312 0.0 +1313 0.0 +1314 0.0 +1315 0.0 +1316 0.0 +1317 0.0 +1318 0.0 +1319 0.0 +1320 0.0 +1321 0.0 +1322 0.0 +1323 0.0 +1324 0.0 +1325 0.0 +1326 0.0 +1327 0.0 +1328 0.0 +1329 0.0 +1330 0.0 +1331 0.0 +1332 0.0 +1333 0.0 +1334 0.0 +1335 0.0 +1336 0.0 +1337 0.0 +1338 0.0 +1339 0.0 +1340 0.0 +1341 0.0 +1342 0.0 +1343 0.0 +1344 0.0 +1345 0.0 +1346 0.0 +1347 0.0 +1348 0.0 +1349 0.0 +1350 0.0 +1351 0.0 +1352 0.0 +1353 0.0 +1354 0.0 +1355 0.0 +1356 0.0 +1357 0.0 +1358 0.0 +1359 0.0 +1360 0.0 +1361 0.0 +1362 0.0 +1363 0.0 +1364 0.0 +1365 0.0 +1366 0.0 +1367 0.0 +1368 0.0 +1369 0.0 +1370 0.0 +1371 0.0 +1372 0.0 +1373 0.0 +1374 0.0 +1375 0.0 +1376 0.0 +1377 0.0 +1378 0.0 +1379 0.0 +1380 0.0 +1381 0.0 +1382 0.0 +1383 0.0 +1384 0.0 +1385 0.0 +1386 0.0 +1387 0.0 +1388 0.0 +1389 0.0 +1390 0.0 +1391 0.0 +1392 0.0 +1393 0.0 +1394 0.0 +1395 0.0 +1396 0.0 +1397 0.0 +1398 0.0 +1399 0.0 +1400 0.0 +1401 0.0 +1402 0.0 +1403 0.0 +1404 0.0 +1405 0.0 +1406 0.0 +1407 0.0 +1408 0.0 +1409 0.0 +1410 0.0 +1411 0.0 +1412 0.0 +1413 0.0 +1414 0.0 +1415 0.0 +1416 0.0 +1417 0.0 +1418 0.0 +1419 0.0 +1420 0.0 +1421 0.0 +1422 0.0 +1423 0.0 +1424 0.0 +1425 0.0 +1426 0.0 +1427 0.0 +1428 0.0 +1429 0.0 +1430 0.0 +1431 0.0 +1432 0.0 +1433 0.0 +1434 0.0 +1435 0.0 +1436 0.0 +1437 0.0 +1438 0.0 +1439 0.0 +1440 0.0 +1441 0.0 +1442 0.0 +1443 0.0 +1444 0.0 +1445 0.0 +1446 0.0 +1447 0.0 +1448 0.0 +1449 0.0 +1450 0.0 +1451 0.0 +1452 0.0 +1453 0.0 +1454 0.0 +1455 0.0 +1456 0.0 +1457 0.0 +1458 0.0 +1459 0.0 +1460 0.0 +1461 0.0 +1462 0.0 +1463 0.0 +1464 0.0 +1465 0.0 +1466 0.0 +1467 0.0 +1468 0.0 +1469 0.0 +1470 0.0 +1471 0.0 +1472 0.0 +1473 0.0 +1474 0.0 +1475 0.0 +1476 0.0 +1477 0.0 +1478 0.0 +1479 0.0 +1480 0.0 +1481 0.0 +1482 0.0 +1483 0.0 +1484 0.0 +1485 0.0 +1486 0.0 +1487 0.0 +1488 0.0 +1489 0.0 +1490 0.0 +1491 0.0 +1492 0.0 +1493 0.0 +1494 0.0 +1495 0.0 +1496 0.0 +1497 0.0 +1498 0.0 +1499 0.0 +1500 0.0 +1501 0.0 +1502 0.0 +1503 0.0 +1504 0.0 +1505 0.0 +1506 0.0 +1507 0.0 +1508 0.0 +1509 0.0 +1510 0.0 +1511 0.0 +1512 0.0 +1513 0.0 +1514 0.0 +1515 0.0 +1516 0.0 +1517 0.0 +1518 0.0 +1519 0.0 +1520 0.0 +1521 0.0 +1522 0.0 +1523 0.0 +1524 0.0 +1525 0.0 +1526 0.0 +1527 0.0 +1528 0.0 +1529 0.0 +1530 0.0 +1531 0.0 +1532 0.0 +1533 0.0 +1534 0.0 +1535 0.0 diff --git a/tests/circuitpython/audiofilter_filter_biquads.py b/tests/circuitpython/audiofilter_filter_biquads.py new file mode 100644 index 0000000000000..d5897d655daae --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_biquads.py @@ -0,0 +1,19 @@ +from audiofilters import Filter +from audiofilterhelper import synth_test, white8k +from synthio import Biquad, FilterMode + + +@synth_test +def basic_filter(): + effect = Filter( + filter=[ + Biquad(FilterMode.LOW_PASS, 400), + Biquad(FilterMode.HIGH_PASS, 300, Q=8), + ], + bits_per_sample=16, + samples_signed=True, + ) + yield effect, [] + + effect.play(white8k, loop=True) + yield 400 diff --git a/tests/circuitpython/audiofilter_filter_biquads.py.exp b/tests/circuitpython/audiofilter_filter_biquads.py.exp new file mode 100644 index 0000000000000..769b73fa66b8d --- /dev/null +++ b/tests/circuitpython/audiofilter_filter_biquads.py.exp @@ -0,0 +1,102400 @@ +0 0.0030517578125 +1 0.021575927734375 +2 0.05120849609375 +3 0.053802490234375 +4 9.1552734375e-05 +5 -0.09271240234375 +6 -0.1846923828125 +7 -0.237152099609375 +8 -0.21197509765625 +9 -0.140045166015625 +10 -0.070159912109375 +11 0.004425048828125 +12 0.08868408203125 +13 0.1971435546875 +14 0.2984619140625 +15 0.34002685546875 +16 0.338958740234375 +17 0.311431884765625 +18 0.257110595703125 +19 0.169921875 +20 0.048919677734375 +21 -0.074859619140625 +22 -0.196044921875 +23 -0.3184814453125 +24 -0.41741943359375 +25 -0.462921142578125 +26 -0.4158935546875 +27 -0.27197265625 +28 -0.0966796875 +29 0.031219482421875 +30 0.110015869140625 +31 0.166961669921875 +32 0.20819091796875 +33 0.23388671875 +34 0.208282470703125 +35 0.152252197265625 +36 0.123321533203125 +37 0.093414306640625 +38 0.019500732421875 +39 -0.07281494140625 +40 -0.1202392578125 +41 -0.088623046875 +42 -0.024932861328125 +43 -0.00634765625 +44 -0.037872314453125 +45 -0.085601806640625 +46 -0.12237548828125 +47 -0.115478515625 +48 -0.05316162109375 +49 0.02166748046875 +50 0.051025390625 +51 0.041656494140625 +52 0.0546875 +53 0.127197265625 +54 0.21710205078125 +55 0.262786865234375 +56 0.282318115234375 +57 0.311279296875 +58 0.32342529296875 +59 0.273468017578125 +60 0.1549072265625 +61 0.017669677734375 +62 -0.088409423828125 +63 -0.15985107421875 +64 -0.197540283203125 +65 -0.2281494140625 +66 -0.296966552734375 +67 -0.39508056640625 +68 -0.505218505859375 +69 -0.59619140625 +70 -0.62982177734375 +71 -0.59893798828125 +72 -0.47979736328125 +73 -0.286041259765625 +74 -0.07379150390625 +75 0.12548828125 +76 0.278289794921875 +77 0.3721923828125 +78 0.44720458984375 +79 0.511260986328125 +80 0.519073486328125 +81 0.458740234375 +82 0.38153076171875 +83 0.337646484375 +84 0.332916259765625 +85 0.358184814453125 +86 0.379608154296875 +87 0.34600830078125 +88 0.239990234375 +89 0.085784912109375 +90 -0.082061767578125 +91 -0.239288330078125 +92 -0.370361328125 +93 -0.460906982421875 +94 -0.48858642578125 +95 -0.467864990234375 +96 -0.4451904296875 +97 -0.4154052734375 +98 -0.371429443359375 +99 -0.3514404296875 +100 -0.331756591796875 +101 -0.236968994140625 +102 -0.064300537109375 +103 0.137908935546875 +104 0.33056640625 +105 0.488922119140625 +106 0.58294677734375 +107 0.580413818359375 +108 0.497894287109375 +109 0.374176025390625 +110 0.252288818359375 +111 0.157257080078125 +112 0.0562744140625 +113 -0.065643310546875 +114 -0.1624755859375 +115 -0.230316162109375 +116 -0.288909912109375 +117 -0.30181884765625 +118 -0.25982666015625 +119 -0.20831298828125 +120 -0.18756103515625 +121 -0.18359375 +122 -0.147491455078125 +123 -0.077056884765625 +124 -0.011138916015625 +125 0.04608154296875 +126 0.087738037109375 +127 0.091278076171875 +128 0.09515380859375 +129 0.11663818359375 +130 0.1290283203125 +131 0.116546630859375 +132 0.07330322265625 +133 0.026763916015625 +134 -0.02392578125 +135 -0.110504150390625 +136 -0.195220947265625 +137 -0.23822021484375 +138 -0.248016357421875 +139 -0.201385498046875 +140 -0.108489990234375 +141 -0.00311279296875 +142 0.11688232421875 +143 0.21673583984375 +144 0.259368896484375 +145 0.257904052734375 +146 0.221710205078125 +147 0.1727294921875 +148 0.141082763671875 +149 0.106689453125 +150 0.0672607421875 +151 0.052734375 +152 0.08087158203125 +153 0.1357421875 +154 0.171783447265625 +155 0.1658935546875 +156 0.10931396484375 +157 0.007080078125 +158 -0.1170654296875 +159 -0.2578125 +160 -0.404937744140625 +161 -0.5286865234375 +162 -0.58502197265625 +163 -0.531005859375 +164 -0.390411376953125 +165 -0.225616455078125 +166 -0.062255859375 +167 0.100921630859375 +168 0.252532958984375 +169 0.365509033203125 +170 0.422332763671875 +171 0.41949462890625 +172 0.355621337890625 +173 0.254974365234375 +174 0.152984619140625 +175 0.062103271484375 +176 0.00994873046875 +177 -0.00531005859375 +178 -0.015167236328125 +179 -0.000640869140625 +180 0.050628662109375 +181 0.094940185546875 +182 0.079833984375 +183 0.021453857421875 +184 -0.04217529296875 +185 -0.10150146484375 +186 -0.1451416015625 +187 -0.18408203125 +188 -0.224334716796875 +189 -0.2666015625 +190 -0.318572998046875 +191 -0.37030029296875 +192 -0.39410400390625 +193 -0.35247802734375 +194 -0.241973876953125 +195 -0.08026123046875 +196 0.105438232421875 +197 0.25439453125 +198 0.339630126953125 +199 0.379913330078125 +200 0.368316650390625 +201 0.304412841796875 +202 0.239166259765625 +203 0.20916748046875 +204 0.188140869140625 +205 0.159393310546875 +206 0.150543212890625 +207 0.151947021484375 +208 0.122833251953125 +209 0.088531494140625 +210 0.072296142578125 +211 0.038360595703125 +212 -0.026214599609375 +213 -0.1209716796875 +214 -0.245208740234375 +215 -0.369354248046875 +216 -0.45306396484375 +217 -0.481781005859375 +218 -0.46917724609375 +219 -0.41973876953125 +220 -0.331298828125 +221 -0.221527099609375 +222 -0.1141357421875 +223 -0.015960693359375 +224 0.09100341796875 +225 0.22747802734375 +226 0.403167724609375 +227 0.596435546875 +228 0.74627685546875 +229 0.81036376953125 +230 0.7860107421875 +231 0.66998291015625 +232 0.46142578125 +233 0.197906494140625 +234 -0.05487060546875 +235 -0.23974609375 +236 -0.339080810546875 +237 -0.37896728515625 +238 -0.3905029296875 +239 -0.388916015625 +240 -0.391326904296875 +241 -0.4022216796875 +242 -0.39459228515625 +243 -0.3492431640625 +244 -0.287933349609375 +245 -0.254180908203125 +246 -0.26617431640625 +247 -0.270904541015625 +248 -0.21209716796875 +249 -0.121612548828125 +250 -0.059967041015625 +251 -0.03387451171875 +252 -0.01470947265625 +253 0.030426025390625 +254 0.133636474609375 +255 0.2659912109375 +256 0.385772705078125 +257 0.48480224609375 +258 0.531097412109375 +259 0.511962890625 +260 0.454986572265625 +261 0.404327392578125 +262 0.37890625 +263 0.350616455078125 +264 0.3045654296875 +265 0.243011474609375 +266 0.157379150390625 +267 0.027496337890625 +268 -0.149139404296875 +269 -0.3416748046875 +270 -0.53924560546875 +271 -0.725006103515625 +272 -0.838104248046875 +273 -0.832366943359375 +274 -0.727691650390625 +275 -0.579132080078125 +276 -0.435394287109375 +277 -0.318634033203125 +278 -0.195159912109375 +279 -0.038055419921875 +280 0.1104736328125 +281 0.208465576171875 +282 0.26983642578125 +283 0.34326171875 +284 0.446990966796875 +285 0.546905517578125 +286 0.61773681640625 +287 0.6514892578125 +288 0.661102294921875 +289 0.652679443359375 +290 0.602386474609375 +291 0.496124267578125 +292 0.347320556640625 +293 0.170989990234375 +294 -0.0401611328125 +295 -0.263031005859375 +296 -0.446502685546875 +297 -0.578399658203125 +298 -0.65399169921875 +299 -0.642364501953125 +300 -0.561676025390625 +301 -0.456390380859375 +302 -0.347869873046875 +303 -0.256988525390625 +304 -0.18792724609375 +305 -0.137359619140625 +306 -0.09747314453125 +307 -0.058319091796875 +308 -0.007720947265625 +309 0.06646728515625 +310 0.151611328125 +311 0.243743896484375 +312 0.35015869140625 +313 0.457366943359375 +314 0.542999267578125 +315 0.57110595703125 +316 0.504058837890625 +317 0.34808349609375 +318 0.142974853515625 +319 -0.0589599609375 +320 -0.219940185546875 +321 -0.33837890625 +322 -0.406005859375 +323 -0.4437255859375 +324 -0.497528076171875 +325 -0.561126708984375 +326 -0.600860595703125 +327 -0.58355712890625 +328 -0.4779052734375 +329 -0.27734375 +330 -0.00640869140625 +331 0.271636962890625 +332 0.48583984375 +333 0.60675048828125 +334 0.6533203125 +335 0.666595458984375 +336 0.64361572265625 +337 0.5740966796875 +338 0.499053955078125 +339 0.439697265625 +340 0.375091552734375 +341 0.2734375 +342 0.107147216796875 +343 -0.101470947265625 +344 -0.320648193359375 +345 -0.551544189453125 +346 -0.77642822265625 +347 -0.864105224609375 +348 -0.870391845703125 +349 -0.868682861328125 +350 -0.86053466796875 +351 -0.759246826171875 +352 -0.52203369140625 +353 -0.20556640625 +354 0.146942138671875 +355 0.48431396484375 +356 0.771270751953125 +357 0.868316650390625 +358 0.870361328125 +359 0.86395263671875 +360 0.8172607421875 +361 0.657073974609375 +362 0.470733642578125 +363 0.279388427734375 +364 0.086395263671875 +365 -0.140350341796875 +366 -0.40960693359375 +367 -0.6817626953125 +368 -0.859619140625 +369 -0.870391845703125 +370 -0.870391845703125 +371 -0.86444091796875 +372 -0.85723876953125 +373 -0.790008544921875 +374 -0.62847900390625 +375 -0.3956298828125 +376 -0.126708984375 +377 0.150115966796875 +378 0.424041748046875 +379 0.670623779296875 +380 0.854522705078125 +381 0.866485595703125 +382 0.86920166015625 +383 0.8653564453125 +384 0.857147216796875 +385 0.766845703125 +386 0.628509521484375 +387 0.462127685546875 +388 0.297210693359375 +389 0.14862060546875 +390 -0.00537109375 +391 -0.15753173828125 +392 -0.31304931640625 +393 -0.48876953125 +394 -0.6416015625 +395 -0.751373291015625 +396 -0.84619140625 +397 -0.861297607421875 +398 -0.863250732421875 +399 -0.856597900390625 +400 -0.7498779296875 +401 -0.624542236328125 +402 -0.47808837890625 +403 -0.253387451171875 +404 0.003692626953125 +405 0.2257080078125 +406 0.427154541015625 +407 0.643218994140625 +408 0.855926513671875 +409 0.870361328125 +410 0.870361328125 +411 0.862762451171875 +412 0.79669189453125 +413 0.595794677734375 +414 0.362152099609375 +415 0.1270751953125 +416 -0.086944580078125 +417 -0.2784423828125 +418 -0.484832763671875 +419 -0.729583740234375 +420 -0.86688232421875 +421 -0.870391845703125 +422 -0.86859130859375 +423 -0.86279296875 +424 -0.817962646484375 +425 -0.6116943359375 +426 -0.3128662109375 +427 0.039398193359375 +428 0.422821044921875 +429 0.805145263671875 +430 0.870361328125 +431 0.870361328125 +432 0.860015869140625 +433 0.727935791015625 +434 0.48114013671875 +435 0.2059326171875 +436 -0.06103515625 +437 -0.29913330078125 +438 -0.516204833984375 +439 -0.7252197265625 +440 -0.85980224609375 +441 -0.870391845703125 +442 -0.870391845703125 +443 -0.858062744140625 +444 -0.673004150390625 +445 -0.42694091796875 +446 -0.2100830078125 +447 -0.0362548828125 +448 0.10943603515625 +449 0.23516845703125 +450 0.373687744140625 +451 0.517791748046875 +452 0.602783203125 +453 0.635711669921875 +454 0.655181884765625 +455 0.65948486328125 +456 0.651275634765625 +457 0.61846923828125 +458 0.53753662109375 +459 0.404144287109375 +460 0.22186279296875 +461 0.003997802734375 +462 -0.22100830078125 +463 -0.42449951171875 +464 -0.579833984375 +465 -0.641876220703125 +466 -0.6177978515625 +467 -0.575531005859375 +468 -0.526336669921875 +469 -0.42645263671875 +470 -0.2581787109375 +471 -0.068695068359375 +472 0.09222412109375 +473 0.232147216796875 +474 0.3509521484375 +475 0.410064697265625 +476 0.372955322265625 +477 0.2554931640625 +478 0.10711669921875 +479 -0.052886962890625 +480 -0.186279296875 +481 -0.23291015625 +482 -0.209442138671875 +483 -0.174163818359375 +484 -0.126739501953125 +485 -0.048126220703125 +486 0.0426025390625 +487 0.10748291015625 +488 0.1409912109375 +489 0.19708251953125 +490 0.273651123046875 +491 0.31768798828125 +492 0.341094970703125 +493 0.368011474609375 +494 0.37249755859375 +495 0.30072021484375 +496 0.1517333984375 +497 -0.01470947265625 +498 -0.1883544921875 +499 -0.372711181640625 +500 -0.51397705078125 +501 -0.57177734375 +502 -0.53948974609375 +503 -0.43511962890625 +504 -0.2962646484375 +505 -0.161102294921875 +506 -0.0435791015625 +507 0.060394287109375 +508 0.13665771484375 +509 0.170135498046875 +510 0.16552734375 +511 0.15728759765625 +512 0.150787353515625 +513 0.12200927734375 +514 0.080108642578125 +515 0.05126953125 +516 0.062896728515625 +517 0.09271240234375 +518 0.092987060546875 +519 0.07855224609375 +520 0.06427001953125 +521 0.0347900390625 +522 -0.01171875 +523 -0.056060791015625 +524 -0.055511474609375 +525 -0.010467529296875 +526 0.02508544921875 +527 0.025665283203125 +528 0.017333984375 +529 0.00189208984375 +530 -0.03173828125 +531 -0.071502685546875 +532 -0.13543701171875 +533 -0.219970703125 +534 -0.300506591796875 +535 -0.376312255859375 +536 -0.416107177734375 +537 -0.371124267578125 +538 -0.242279052734375 +539 -0.069732666015625 +540 0.125640869140625 +541 0.31268310546875 +542 0.45501708984375 +543 0.554779052734375 +544 0.61065673828125 +545 0.610931396484375 +546 0.531463623046875 +547 0.3883056640625 +548 0.23468017578125 +549 0.095245361328125 +550 -0.00396728515625 +551 -0.04852294921875 +552 -0.055145263671875 +553 -0.0758056640625 +554 -0.138702392578125 +555 -0.209197998046875 +556 -0.289031982421875 +557 -0.37884521484375 +558 -0.456329345703125 +559 -0.51641845703125 +560 -0.519287109375 +561 -0.458251953125 +562 -0.384796142578125 +563 -0.323699951171875 +564 -0.269287109375 +565 -0.1951904296875 +566 -0.100006103515625 +567 -0.01055908203125 +568 0.1033935546875 +569 0.24908447265625 +570 0.373199462890625 +571 0.45806884765625 +572 0.511474609375 +573 0.565399169921875 +574 0.61138916015625 +575 0.5897216796875 +576 0.4906005859375 +577 0.33148193359375 +578 0.147796630859375 +579 -0.01873779296875 +580 -0.140289306640625 +581 -0.191986083984375 +582 -0.184295654296875 +583 -0.161834716796875 +584 -0.166595458984375 +585 -0.19390869140625 +586 -0.22442626953125 +587 -0.279754638671875 +588 -0.3389892578125 +589 -0.3543701171875 +590 -0.348175048828125 +591 -0.32598876953125 +592 -0.2581787109375 +593 -0.139801025390625 +594 0.014617919921875 +595 0.144378662109375 +596 0.221038818359375 +597 0.27069091796875 +598 0.294036865234375 +599 0.311767578125 +600 0.339141845703125 +601 0.360260009765625 +602 0.360504150390625 +603 0.308380126953125 +604 0.18170166015625 +605 0.0047607421875 +606 -0.17559814453125 +607 -0.3143310546875 +608 -0.36785888671875 +609 -0.36248779296875 +610 -0.343536376953125 +611 -0.3018798828125 +612 -0.231414794921875 +613 -0.117645263671875 +614 0.007049560546875 +615 0.087982177734375 +616 0.13946533203125 +617 0.17425537109375 +618 0.188201904296875 +619 0.171234130859375 +620 0.118438720703125 +621 0.05706787109375 +622 -0.010711669921875 +623 -0.0914306640625 +624 -0.162322998046875 +625 -0.194549560546875 +626 -0.1492919921875 +627 -0.02166748046875 +628 0.124053955078125 +629 0.211151123046875 +630 0.240447998046875 +631 0.242218017578125 +632 0.2257080078125 +633 0.194366455078125 +634 0.115509033203125 +635 0.0128173828125 +636 -0.053802490234375 +637 -0.110626220703125 +638 -0.199493408203125 +639 -0.29437255859375 +640 -0.33221435546875 +641 -0.27972412109375 +642 -0.185333251953125 +643 -0.128204345703125 +644 -0.115692138671875 +645 -0.116455078125 +646 -0.105926513671875 +647 -0.053955078125 +648 0.048797607421875 +649 0.157318115234375 +650 0.212005615234375 +651 0.218475341796875 +652 0.23724365234375 +653 0.30535888671875 +654 0.38128662109375 +655 0.404449462890625 +656 0.3944091796875 +657 0.3885498046875 +658 0.362640380859375 +659 0.27362060546875 +660 0.11712646484375 +661 -0.054901123046875 +662 -0.19085693359375 +663 -0.28570556640625 +664 -0.339263916015625 +665 -0.3775634765625 +666 -0.445709228515625 +667 -0.535064697265625 +668 -0.629058837890625 +669 -0.697601318359375 +670 -0.70391845703125 +671 -0.6424560546875 +672 -0.491241455078125 +673 -0.265716552734375 +674 -0.023712158203125 +675 0.201751708984375 +676 0.375823974609375 +677 0.485076904296875 +678 0.56884765625 +679 0.634765625 +680 0.63763427734375 +681 0.5660400390625 +682 0.4720458984375 +683 0.40692138671875 +684 0.3778076171875 +685 0.376953125 +686 0.371978759765625 +687 0.313140869140625 +688 0.184417724609375 +689 0.011199951171875 +690 -0.171051025390625 +691 -0.33740234375 +692 -0.47198486328125 +693 -0.560394287109375 +694 -0.58056640625 +695 -0.54754638671875 +696 -0.508575439453125 +697 -0.459503173828125 +698 -0.394378662109375 +699 -0.35260009765625 +700 -0.31170654296875 +701 -0.197418212890625 +702 -0.007965087890625 +703 0.207489013671875 +704 0.409210205078125 +705 0.57208251953125 +706 0.66595458984375 +707 0.65875244140625 +708 0.56744384765625 +709 0.431396484375 +710 0.29443359375 +711 0.182464599609375 +712 0.06365966796875 +713 -0.075958251953125 +714 -0.189422607421875 +715 -0.271942138671875 +716 -0.342529296875 +717 -0.364166259765625 +718 -0.327239990234375 +719 -0.2769775390625 +720 -0.253692626953125 +721 -0.24365234375 +722 -0.1983642578125 +723 -0.116241455078125 +724 -0.036834716796875 +725 0.034881591796875 +726 0.09124755859375 +727 0.10888671875 +728 0.125518798828125 +729 0.15771484375 +730 0.17828369140625 +731 0.17108154296875 +732 0.129974365234375 +733 0.082427978515625 +734 0.027679443359375 +735 -0.065643310546875 +736 -0.15936279296875 +737 -0.21307373046875 +738 -0.234649658203125 +739 -0.2001953125 +740 -0.119171142578125 +741 -0.024749755859375 +742 0.085784912109375 +743 0.178131103515625 +744 0.215576171875 +745 0.211456298828125 +746 0.17523193359375 +747 0.128753662109375 +748 0.1019287109375 +749 0.0743408203125 +750 0.04327392578125 +751 0.038177490234375 +752 0.076263427734375 +753 0.14105224609375 +754 0.186431884765625 +755 0.188812255859375 +756 0.1390380859375 +757 0.041778564453125 +758 -0.079437255859375 +759 -0.219390869140625 +760 -0.367828369140625 +761 -0.494873046875 +762 -0.556243896484375 +763 -0.508697509765625 +764 -0.3756103515625 +765 -0.218902587890625 +766 -0.063751220703125 +767 0.091552734375 +768 0.23602294921875 +769 0.342987060546875 +770 0.39520263671875 +771 0.389373779296875 +772 0.324249267578125 +773 0.224090576171875 +774 0.124267578125 +775 0.037078857421875 +776 -0.010101318359375 +777 -0.019439697265625 +778 -0.022796630859375 +779 -0.001556396484375 +780 0.056304931640625 +781 0.106719970703125 +782 0.096893310546875 +783 0.042694091796875 +784 -0.018035888671875 +785 -0.07586669921875 +786 -0.11944580078125 +787 -0.15972900390625 +788 -0.202606201171875 +789 -0.24859619140625 +790 -0.30517578125 +791 -0.36212158203125 +792 -0.39141845703125 +793 -0.35528564453125 +794 -0.249969482421875 +795 -0.092864990234375 +796 0.08905029296875 +797 0.2352294921875 +798 0.318817138671875 +799 0.358642578125 +800 0.347747802734375 +801 0.28564453125 +802 0.223175048828125 +803 0.196746826171875 +804 0.179840087890625 +805 0.155548095703125 +806 0.151214599609375 +807 0.156951904296875 +808 0.13177490234375 +809 0.100799560546875 +810 0.087127685546875 +811 0.05487060546875 +812 -0.009002685546875 +813 -0.10400390625 +814 -0.229400634765625 +815 -0.35552978515625 +816 -0.441925048828125 +817 -0.473846435546875 +818 -0.464813232421875 +819 -0.419097900390625 +820 -0.334320068359375 +821 -0.227935791015625 +822 -0.12347412109375 +823 -0.02764892578125 +824 0.077667236328125 +825 0.2132568359375 +826 0.38885498046875 +827 0.582794189453125 +828 0.734039306640625 +829 0.800140380859375 +830 0.7783203125 +831 0.6651611328125 +832 0.45965576171875 +833 0.199188232421875 +834 -0.050689697265625 +835 -0.23297119140625 +836 -0.33013916015625 +837 -0.368408203125 +838 -0.378936767578125 +839 -0.376983642578125 +840 -0.37969970703125 +841 -0.391510009765625 +842 -0.385345458984375 +843 -0.3419189453125 +844 -0.28289794921875 +845 -0.251617431640625 +846 -0.266143798828125 +847 -0.273345947265625 +848 -0.216796875 +849 -0.128265380859375 +850 -0.068145751953125 +851 -0.0430908203125 +852 -0.024444580078125 +853 0.020721435546875 +854 0.124481201171875 +855 0.25787353515625 +856 0.379119873046875 +857 0.47991943359375 +858 0.5281982421875 +859 0.511138916015625 +860 0.456207275390625 +861 0.407470703125 +862 0.383758544921875 +863 0.35687255859375 +864 0.31182861328125 +865 0.250885009765625 +866 0.1654052734375 +867 0.035247802734375 +868 -0.142059326171875 +869 -0.33563232421875 +870 -0.5345458984375 +871 -0.72186279296875 +872 -0.836669921875 +873 -0.8326416015625 +874 -0.7296142578125 +875 -0.582550048828125 +876 -0.440093994140625 +877 -0.324310302734375 +878 -0.20147705078125 +879 -0.044647216796875 +880 0.103973388671875 +881 0.202392578125 +882 0.264495849609375 +883 0.338897705078125 +884 0.443817138671875 +885 0.545074462890625 +886 0.6173095703125 +887 0.6524658203125 +888 0.66339111328125 +889 0.6561279296875 +890 0.606781005859375 +891 0.501190185546875 +892 0.352783203125 +893 0.176544189453125 +894 -0.034820556640625 +895 -0.258209228515625 +896 -0.44244384765625 +897 -0.5753173828125 +898 -0.65203857421875 +899 -0.641632080078125 +900 -0.562164306640625 +901 -0.458038330078125 +902 -0.350555419921875 +903 -0.260528564453125 +904 -0.192108154296875 +905 -0.141937255859375 +906 -0.1021728515625 +907 -0.062896728515625 +908 -0.011932373046875 +909 0.062835693359375 +910 0.148712158203125 +911 0.241729736328125 +912 0.34912109375 +913 0.457305908203125 +914 0.54388427734375 +915 0.5728759765625 +916 0.506591796875 +917 0.351226806640625 +918 0.146514892578125 +919 -0.05523681640625 +920 -0.21624755859375 +921 -0.334930419921875 +922 -0.402984619140625 +923 -0.4412841796875 +924 -0.49578857421875 +925 -0.5601806640625 +926 -0.600738525390625 +927 -0.584228515625 +928 -0.47930908203125 +929 -0.27935791015625 +930 -0.0089111328125 +931 0.268798828125 +932 0.482818603515625 +933 0.60369873046875 +934 0.650421142578125 +935 0.66400146484375 +936 0.6414794921875 +937 0.572540283203125 +938 0.498138427734375 +939 0.439453125 +940 0.375518798828125 +941 0.274505615234375 +942 0.1087646484375 +943 -0.099395751953125 +944 -0.3182373046875 +945 -0.5489501953125 +946 -0.7738037109375 +947 -0.86383056640625 +948 -0.870391845703125 +949 -0.86895751953125 +950 -0.861053466796875 +951 -0.765869140625 +952 -0.5301513671875 +953 -0.214691162109375 +954 0.137359619140625 +955 0.474822998046875 +956 0.76239013671875 +957 0.867462158203125 +958 0.870361328125 +959 0.86480712890625 +960 0.831817626953125 +961 0.677581787109375 +962 0.495880126953125 +963 0.30767822265625 +964 0.116180419921875 +965 -0.110748291015625 +966 -0.381805419921875 +967 -0.6572265625 +968 -0.857421875 +969 -0.870391845703125 +970 -0.870391845703125 +971 -0.86444091796875 +972 -0.85723876953125 +973 -0.790008544921875 +974 -0.62847900390625 +975 -0.3956298828125 +976 -0.126708984375 +977 0.150115966796875 +978 0.424041748046875 +979 0.670623779296875 +980 0.854522705078125 +981 0.866485595703125 +982 0.86920166015625 +983 0.8653564453125 +984 0.857147216796875 +985 0.766845703125 +986 0.628509521484375 +987 0.462127685546875 +988 0.297210693359375 +989 0.14862060546875 +990 -0.00537109375 +991 -0.15753173828125 +992 -0.31304931640625 +993 -0.48876953125 +994 -0.6416015625 +995 -0.751373291015625 +996 -0.84619140625 +997 -0.861297607421875 +998 -0.863250732421875 +999 -0.856597900390625 +1000 -0.7498779296875 +1001 -0.624542236328125 +1002 -0.47808837890625 +1003 -0.253387451171875 +1004 0.003692626953125 +1005 0.2257080078125 +1006 0.427154541015625 +1007 0.643218994140625 +1008 0.855926513671875 +1009 0.870361328125 +1010 0.870361328125 +1011 0.862762451171875 +1012 0.79669189453125 +1013 0.595794677734375 +1014 0.362152099609375 +1015 0.1270751953125 +1016 -0.086944580078125 +1017 -0.2784423828125 +1018 -0.484832763671875 +1019 -0.729583740234375 +1020 -0.86688232421875 +1021 -0.870391845703125 +1022 -0.86859130859375 +1023 -0.86279296875 +1024 -0.817962646484375 +1025 -0.6116943359375 +1026 -0.3128662109375 +1027 0.039398193359375 +1028 0.422821044921875 +1029 0.805145263671875 +1030 0.870361328125 +1031 0.870361328125 +1032 0.860015869140625 +1033 0.727935791015625 +1034 0.48114013671875 +1035 0.2059326171875 +1036 -0.06103515625 +1037 -0.29913330078125 +1038 -0.516204833984375 +1039 -0.7252197265625 +1040 -0.85980224609375 +1041 -0.870391845703125 +1042 -0.870391845703125 +1043 -0.858062744140625 +1044 -0.673004150390625 +1045 -0.42694091796875 +1046 -0.2100830078125 +1047 -0.0362548828125 +1048 0.10943603515625 +1049 0.23516845703125 +1050 0.373687744140625 +1051 0.517791748046875 +1052 0.602783203125 +1053 0.635711669921875 +1054 0.655181884765625 +1055 0.65948486328125 +1056 0.651275634765625 +1057 0.61846923828125 +1058 0.53753662109375 +1059 0.404144287109375 +1060 0.22186279296875 +1061 0.003997802734375 +1062 -0.22100830078125 +1063 -0.42449951171875 +1064 -0.579833984375 +1065 -0.641876220703125 +1066 -0.6177978515625 +1067 -0.575531005859375 +1068 -0.526336669921875 +1069 -0.42645263671875 +1070 -0.2581787109375 +1071 -0.068695068359375 +1072 0.09222412109375 +1073 0.232147216796875 +1074 0.3509521484375 +1075 0.410064697265625 +1076 0.372955322265625 +1077 0.2554931640625 +1078 0.10711669921875 +1079 -0.052886962890625 +1080 -0.186279296875 +1081 -0.23291015625 +1082 -0.209442138671875 +1083 -0.174163818359375 +1084 -0.126739501953125 +1085 -0.048126220703125 +1086 0.0426025390625 +1087 0.10748291015625 +1088 0.1409912109375 +1089 0.19708251953125 +1090 0.273651123046875 +1091 0.31768798828125 +1092 0.341094970703125 +1093 0.368011474609375 +1094 0.37249755859375 +1095 0.30072021484375 +1096 0.1517333984375 +1097 -0.01470947265625 +1098 -0.1883544921875 +1099 -0.372711181640625 +1100 -0.51397705078125 +1101 -0.57177734375 +1102 -0.53948974609375 +1103 -0.43511962890625 +1104 -0.2962646484375 +1105 -0.161102294921875 +1106 -0.0435791015625 +1107 0.060394287109375 +1108 0.13665771484375 +1109 0.170135498046875 +1110 0.16552734375 +1111 0.15728759765625 +1112 0.150787353515625 +1113 0.12200927734375 +1114 0.080108642578125 +1115 0.05126953125 +1116 0.062896728515625 +1117 0.09271240234375 +1118 0.092987060546875 +1119 0.07855224609375 +1120 0.06427001953125 +1121 0.0347900390625 +1122 -0.01171875 +1123 -0.056060791015625 +1124 -0.055511474609375 +1125 -0.010467529296875 +1126 0.02508544921875 +1127 0.025665283203125 +1128 0.017333984375 +1129 0.00189208984375 +1130 -0.03173828125 +1131 -0.071502685546875 +1132 -0.13543701171875 +1133 -0.219970703125 +1134 -0.300506591796875 +1135 -0.376312255859375 +1136 -0.416107177734375 +1137 -0.371124267578125 +1138 -0.242279052734375 +1139 -0.069732666015625 +1140 0.125640869140625 +1141 0.31268310546875 +1142 0.45501708984375 +1143 0.554779052734375 +1144 0.61065673828125 +1145 0.610931396484375 +1146 0.531463623046875 +1147 0.3883056640625 +1148 0.23468017578125 +1149 0.095245361328125 +1150 -0.00396728515625 +1151 -0.04852294921875 +1152 -0.055145263671875 +1153 -0.0758056640625 +1154 -0.138702392578125 +1155 -0.209197998046875 +1156 -0.289031982421875 +1157 -0.37884521484375 +1158 -0.456329345703125 +1159 -0.51641845703125 +1160 -0.519287109375 +1161 -0.458251953125 +1162 -0.384796142578125 +1163 -0.323699951171875 +1164 -0.269287109375 +1165 -0.1951904296875 +1166 -0.100006103515625 +1167 -0.01055908203125 +1168 0.1033935546875 +1169 0.24908447265625 +1170 0.373199462890625 +1171 0.45806884765625 +1172 0.511474609375 +1173 0.565399169921875 +1174 0.61138916015625 +1175 0.5897216796875 +1176 0.4906005859375 +1177 0.33148193359375 +1178 0.147796630859375 +1179 -0.01873779296875 +1180 -0.140289306640625 +1181 -0.191986083984375 +1182 -0.184295654296875 +1183 -0.161834716796875 +1184 -0.166595458984375 +1185 -0.19390869140625 +1186 -0.22442626953125 +1187 -0.279754638671875 +1188 -0.3389892578125 +1189 -0.3543701171875 +1190 -0.348175048828125 +1191 -0.32598876953125 +1192 -0.2581787109375 +1193 -0.139801025390625 +1194 0.014617919921875 +1195 0.144378662109375 +1196 0.221038818359375 +1197 0.27069091796875 +1198 0.294036865234375 +1199 0.311767578125 +1200 0.339141845703125 +1201 0.360260009765625 +1202 0.360504150390625 +1203 0.308380126953125 +1204 0.18170166015625 +1205 0.0047607421875 +1206 -0.17559814453125 +1207 -0.3143310546875 +1208 -0.36785888671875 +1209 -0.36248779296875 +1210 -0.343536376953125 +1211 -0.3018798828125 +1212 -0.231414794921875 +1213 -0.117645263671875 +1214 0.007049560546875 +1215 0.087982177734375 +1216 0.13946533203125 +1217 0.17425537109375 +1218 0.188201904296875 +1219 0.171234130859375 +1220 0.118438720703125 +1221 0.05706787109375 +1222 -0.010711669921875 +1223 -0.0914306640625 +1224 -0.162322998046875 +1225 -0.194549560546875 +1226 -0.1492919921875 +1227 -0.02166748046875 +1228 0.124053955078125 +1229 0.211151123046875 +1230 0.240447998046875 +1231 0.242218017578125 +1232 0.2257080078125 +1233 0.194366455078125 +1234 0.115509033203125 +1235 0.0128173828125 +1236 -0.053802490234375 +1237 -0.110626220703125 +1238 -0.199493408203125 +1239 -0.29437255859375 +1240 -0.33221435546875 +1241 -0.27972412109375 +1242 -0.185333251953125 +1243 -0.128204345703125 +1244 -0.115692138671875 +1245 -0.116455078125 +1246 -0.105926513671875 +1247 -0.053955078125 +1248 0.048797607421875 +1249 0.157318115234375 +1250 0.212005615234375 +1251 0.218475341796875 +1252 0.23724365234375 +1253 0.30535888671875 +1254 0.38128662109375 +1255 0.404449462890625 +1256 0.3944091796875 +1257 0.3885498046875 +1258 0.362640380859375 +1259 0.27362060546875 +1260 0.11712646484375 +1261 -0.054901123046875 +1262 -0.19085693359375 +1263 -0.28570556640625 +1264 -0.339263916015625 +1265 -0.3775634765625 +1266 -0.445709228515625 +1267 -0.535064697265625 +1268 -0.629058837890625 +1269 -0.697601318359375 +1270 -0.70391845703125 +1271 -0.6424560546875 +1272 -0.491241455078125 +1273 -0.265716552734375 +1274 -0.023712158203125 +1275 0.201751708984375 +1276 0.375823974609375 +1277 0.485076904296875 +1278 0.56884765625 +1279 0.634765625 +1280 0.63763427734375 +1281 0.5660400390625 +1282 0.4720458984375 +1283 0.40692138671875 +1284 0.3778076171875 +1285 0.376953125 +1286 0.371978759765625 +1287 0.313140869140625 +1288 0.184417724609375 +1289 0.011199951171875 +1290 -0.171051025390625 +1291 -0.33740234375 +1292 -0.47198486328125 +1293 -0.560394287109375 +1294 -0.58056640625 +1295 -0.54754638671875 +1296 -0.508575439453125 +1297 -0.459503173828125 +1298 -0.394378662109375 +1299 -0.35260009765625 +1300 -0.31170654296875 +1301 -0.197418212890625 +1302 -0.007965087890625 +1303 0.207489013671875 +1304 0.409210205078125 +1305 0.57208251953125 +1306 0.66595458984375 +1307 0.65875244140625 +1308 0.56744384765625 +1309 0.431396484375 +1310 0.29443359375 +1311 0.182464599609375 +1312 0.06365966796875 +1313 -0.075958251953125 +1314 -0.189422607421875 +1315 -0.271942138671875 +1316 -0.342529296875 +1317 -0.364166259765625 +1318 -0.327239990234375 +1319 -0.2769775390625 +1320 -0.253692626953125 +1321 -0.24365234375 +1322 -0.1983642578125 +1323 -0.116241455078125 +1324 -0.036834716796875 +1325 0.034881591796875 +1326 0.09124755859375 +1327 0.10888671875 +1328 0.125518798828125 +1329 0.15771484375 +1330 0.17828369140625 +1331 0.17108154296875 +1332 0.129974365234375 +1333 0.082427978515625 +1334 0.027679443359375 +1335 -0.065643310546875 +1336 -0.15936279296875 +1337 -0.21307373046875 +1338 -0.234649658203125 +1339 -0.2001953125 +1340 -0.119171142578125 +1341 -0.024749755859375 +1342 0.085784912109375 +1343 0.178131103515625 +1344 0.215576171875 +1345 0.211456298828125 +1346 0.17523193359375 +1347 0.128753662109375 +1348 0.1019287109375 +1349 0.0743408203125 +1350 0.04327392578125 +1351 0.038177490234375 +1352 0.076263427734375 +1353 0.14105224609375 +1354 0.186431884765625 +1355 0.188812255859375 +1356 0.1390380859375 +1357 0.041778564453125 +1358 -0.079437255859375 +1359 -0.219390869140625 +1360 -0.367828369140625 +1361 -0.494873046875 +1362 -0.556243896484375 +1363 -0.508697509765625 +1364 -0.3756103515625 +1365 -0.218902587890625 +1366 -0.063751220703125 +1367 0.091552734375 +1368 0.23602294921875 +1369 0.342987060546875 +1370 0.39520263671875 +1371 0.389373779296875 +1372 0.324249267578125 +1373 0.224090576171875 +1374 0.124267578125 +1375 0.037078857421875 +1376 -0.010101318359375 +1377 -0.019439697265625 +1378 -0.022796630859375 +1379 -0.001556396484375 +1380 0.056304931640625 +1381 0.106719970703125 +1382 0.096893310546875 +1383 0.042694091796875 +1384 -0.018035888671875 +1385 -0.07586669921875 +1386 -0.11944580078125 +1387 -0.15972900390625 +1388 -0.202606201171875 +1389 -0.24859619140625 +1390 -0.30517578125 +1391 -0.36212158203125 +1392 -0.39141845703125 +1393 -0.35528564453125 +1394 -0.249969482421875 +1395 -0.092864990234375 +1396 0.08905029296875 +1397 0.2352294921875 +1398 0.318817138671875 +1399 0.358642578125 +1400 0.347747802734375 +1401 0.28564453125 +1402 0.223175048828125 +1403 0.196746826171875 +1404 0.179840087890625 +1405 0.155548095703125 +1406 0.151214599609375 +1407 0.156951904296875 +1408 0.13177490234375 +1409 0.100799560546875 +1410 0.087127685546875 +1411 0.05487060546875 +1412 -0.009002685546875 +1413 -0.10400390625 +1414 -0.229400634765625 +1415 -0.35552978515625 +1416 -0.441925048828125 +1417 -0.473846435546875 +1418 -0.464813232421875 +1419 -0.419097900390625 +1420 -0.334320068359375 +1421 -0.227935791015625 +1422 -0.12347412109375 +1423 -0.02764892578125 +1424 0.077667236328125 +1425 0.2132568359375 +1426 0.38885498046875 +1427 0.582794189453125 +1428 0.734039306640625 +1429 0.800140380859375 +1430 0.7783203125 +1431 0.6651611328125 +1432 0.45965576171875 +1433 0.199188232421875 +1434 -0.050689697265625 +1435 -0.23297119140625 +1436 -0.33013916015625 +1437 -0.368408203125 +1438 -0.378936767578125 +1439 -0.376983642578125 +1440 -0.37969970703125 +1441 -0.391510009765625 +1442 -0.385345458984375 +1443 -0.3419189453125 +1444 -0.28289794921875 +1445 -0.251617431640625 +1446 -0.266143798828125 +1447 -0.273345947265625 +1448 -0.216796875 +1449 -0.128265380859375 +1450 -0.068145751953125 +1451 -0.0430908203125 +1452 -0.024444580078125 +1453 0.020721435546875 +1454 0.124481201171875 +1455 0.25787353515625 +1456 0.379119873046875 +1457 0.47991943359375 +1458 0.5281982421875 +1459 0.511138916015625 +1460 0.456207275390625 +1461 0.407470703125 +1462 0.383758544921875 +1463 0.35687255859375 +1464 0.31182861328125 +1465 0.250885009765625 +1466 0.1654052734375 +1467 0.035247802734375 +1468 -0.142059326171875 +1469 -0.33563232421875 +1470 -0.5345458984375 +1471 -0.72186279296875 +1472 -0.836669921875 +1473 -0.8326416015625 +1474 -0.7296142578125 +1475 -0.582550048828125 +1476 -0.440093994140625 +1477 -0.324310302734375 +1478 -0.20147705078125 +1479 -0.044647216796875 +1480 0.103973388671875 +1481 0.202392578125 +1482 0.264495849609375 +1483 0.338897705078125 +1484 0.443817138671875 +1485 0.545074462890625 +1486 0.6173095703125 +1487 0.6524658203125 +1488 0.66339111328125 +1489 0.6561279296875 +1490 0.606781005859375 +1491 0.501190185546875 +1492 0.352783203125 +1493 0.176544189453125 +1494 -0.034820556640625 +1495 -0.258209228515625 +1496 -0.44244384765625 +1497 -0.5753173828125 +1498 -0.65203857421875 +1499 -0.641632080078125 +1500 -0.562164306640625 +1501 -0.458038330078125 +1502 -0.350555419921875 +1503 -0.260528564453125 +1504 -0.192108154296875 +1505 -0.141937255859375 +1506 -0.1021728515625 +1507 -0.062896728515625 +1508 -0.011932373046875 +1509 0.062835693359375 +1510 0.148712158203125 +1511 0.241729736328125 +1512 0.34912109375 +1513 0.457305908203125 +1514 0.54388427734375 +1515 0.5728759765625 +1516 0.506591796875 +1517 0.351226806640625 +1518 0.146514892578125 +1519 -0.05523681640625 +1520 -0.21624755859375 +1521 -0.334930419921875 +1522 -0.402984619140625 +1523 -0.4412841796875 +1524 -0.49578857421875 +1525 -0.5601806640625 +1526 -0.600738525390625 +1527 -0.584228515625 +1528 -0.47930908203125 +1529 -0.27935791015625 +1530 -0.0089111328125 +1531 0.268798828125 +1532 0.482818603515625 +1533 0.60369873046875 +1534 0.650421142578125 +1535 0.66400146484375 +1536 0.6414794921875 +1537 0.572540283203125 +1538 0.498138427734375 +1539 0.439453125 +1540 0.375518798828125 +1541 0.274505615234375 +1542 0.1087646484375 +1543 -0.099395751953125 +1544 -0.3182373046875 +1545 -0.5489501953125 +1546 -0.7738037109375 +1547 -0.86383056640625 +1548 -0.870391845703125 +1549 -0.86895751953125 +1550 -0.861053466796875 +1551 -0.765869140625 +1552 -0.5301513671875 +1553 -0.214691162109375 +1554 0.137359619140625 +1555 0.474822998046875 +1556 0.76239013671875 +1557 0.867462158203125 +1558 0.870361328125 +1559 0.86480712890625 +1560 0.831817626953125 +1561 0.677581787109375 +1562 0.495880126953125 +1563 0.30767822265625 +1564 0.116180419921875 +1565 -0.110748291015625 +1566 -0.381805419921875 +1567 -0.6572265625 +1568 -0.857421875 +1569 -0.870391845703125 +1570 -0.870391845703125 +1571 -0.86444091796875 +1572 -0.85723876953125 +1573 -0.790008544921875 +1574 -0.62847900390625 +1575 -0.3956298828125 +1576 -0.126708984375 +1577 0.150115966796875 +1578 0.424041748046875 +1579 0.670623779296875 +1580 0.854522705078125 +1581 0.866485595703125 +1582 0.86920166015625 +1583 0.8653564453125 +1584 0.857147216796875 +1585 0.766845703125 +1586 0.628509521484375 +1587 0.462127685546875 +1588 0.297210693359375 +1589 0.14862060546875 +1590 -0.00537109375 +1591 -0.15753173828125 +1592 -0.31304931640625 +1593 -0.48876953125 +1594 -0.6416015625 +1595 -0.751373291015625 +1596 -0.84619140625 +1597 -0.861297607421875 +1598 -0.863250732421875 +1599 -0.856597900390625 +1600 -0.7498779296875 +1601 -0.624542236328125 +1602 -0.47808837890625 +1603 -0.253387451171875 +1604 0.003692626953125 +1605 0.2257080078125 +1606 0.427154541015625 +1607 0.643218994140625 +1608 0.855926513671875 +1609 0.870361328125 +1610 0.870361328125 +1611 0.862762451171875 +1612 0.79669189453125 +1613 0.595794677734375 +1614 0.362152099609375 +1615 0.1270751953125 +1616 -0.086944580078125 +1617 -0.2784423828125 +1618 -0.484832763671875 +1619 -0.729583740234375 +1620 -0.86688232421875 +1621 -0.870391845703125 +1622 -0.86859130859375 +1623 -0.86279296875 +1624 -0.817962646484375 +1625 -0.6116943359375 +1626 -0.3128662109375 +1627 0.039398193359375 +1628 0.422821044921875 +1629 0.805145263671875 +1630 0.870361328125 +1631 0.870361328125 +1632 0.860015869140625 +1633 0.727935791015625 +1634 0.48114013671875 +1635 0.2059326171875 +1636 -0.06103515625 +1637 -0.29913330078125 +1638 -0.516204833984375 +1639 -0.7252197265625 +1640 -0.85980224609375 +1641 -0.870391845703125 +1642 -0.870391845703125 +1643 -0.858062744140625 +1644 -0.673004150390625 +1645 -0.42694091796875 +1646 -0.2100830078125 +1647 -0.0362548828125 +1648 0.10943603515625 +1649 0.23516845703125 +1650 0.373687744140625 +1651 0.517791748046875 +1652 0.602783203125 +1653 0.635711669921875 +1654 0.655181884765625 +1655 0.65948486328125 +1656 0.651275634765625 +1657 0.61846923828125 +1658 0.53753662109375 +1659 0.404144287109375 +1660 0.22186279296875 +1661 0.003997802734375 +1662 -0.22100830078125 +1663 -0.42449951171875 +1664 -0.579833984375 +1665 -0.641876220703125 +1666 -0.6177978515625 +1667 -0.575531005859375 +1668 -0.526336669921875 +1669 -0.42645263671875 +1670 -0.2581787109375 +1671 -0.068695068359375 +1672 0.09222412109375 +1673 0.232147216796875 +1674 0.3509521484375 +1675 0.410064697265625 +1676 0.372955322265625 +1677 0.2554931640625 +1678 0.10711669921875 +1679 -0.052886962890625 +1680 -0.186279296875 +1681 -0.23291015625 +1682 -0.209442138671875 +1683 -0.174163818359375 +1684 -0.126739501953125 +1685 -0.048126220703125 +1686 0.0426025390625 +1687 0.10748291015625 +1688 0.1409912109375 +1689 0.19708251953125 +1690 0.273651123046875 +1691 0.31768798828125 +1692 0.341094970703125 +1693 0.368011474609375 +1694 0.37249755859375 +1695 0.30072021484375 +1696 0.1517333984375 +1697 -0.01470947265625 +1698 -0.1883544921875 +1699 -0.372711181640625 +1700 -0.51397705078125 +1701 -0.57177734375 +1702 -0.53948974609375 +1703 -0.43511962890625 +1704 -0.2962646484375 +1705 -0.161102294921875 +1706 -0.0435791015625 +1707 0.060394287109375 +1708 0.13665771484375 +1709 0.170135498046875 +1710 0.16552734375 +1711 0.15728759765625 +1712 0.150787353515625 +1713 0.12200927734375 +1714 0.080108642578125 +1715 0.05126953125 +1716 0.062896728515625 +1717 0.09271240234375 +1718 0.092987060546875 +1719 0.07855224609375 +1720 0.06427001953125 +1721 0.0347900390625 +1722 -0.01171875 +1723 -0.056060791015625 +1724 -0.055511474609375 +1725 -0.010467529296875 +1726 0.02508544921875 +1727 0.025665283203125 +1728 0.017333984375 +1729 0.00189208984375 +1730 -0.03173828125 +1731 -0.071502685546875 +1732 -0.13543701171875 +1733 -0.219970703125 +1734 -0.300506591796875 +1735 -0.376312255859375 +1736 -0.416107177734375 +1737 -0.371124267578125 +1738 -0.242279052734375 +1739 -0.069732666015625 +1740 0.125640869140625 +1741 0.31268310546875 +1742 0.45501708984375 +1743 0.554779052734375 +1744 0.61065673828125 +1745 0.610931396484375 +1746 0.531463623046875 +1747 0.3883056640625 +1748 0.23468017578125 +1749 0.095245361328125 +1750 -0.00396728515625 +1751 -0.04852294921875 +1752 -0.055145263671875 +1753 -0.0758056640625 +1754 -0.138702392578125 +1755 -0.209197998046875 +1756 -0.289031982421875 +1757 -0.37884521484375 +1758 -0.456329345703125 +1759 -0.51641845703125 +1760 -0.519287109375 +1761 -0.458251953125 +1762 -0.384796142578125 +1763 -0.323699951171875 +1764 -0.269287109375 +1765 -0.1951904296875 +1766 -0.100006103515625 +1767 -0.01055908203125 +1768 0.1033935546875 +1769 0.24908447265625 +1770 0.373199462890625 +1771 0.45806884765625 +1772 0.511474609375 +1773 0.565399169921875 +1774 0.61138916015625 +1775 0.5897216796875 +1776 0.4906005859375 +1777 0.33148193359375 +1778 0.147796630859375 +1779 -0.01873779296875 +1780 -0.140289306640625 +1781 -0.191986083984375 +1782 -0.184295654296875 +1783 -0.161834716796875 +1784 -0.166595458984375 +1785 -0.19390869140625 +1786 -0.22442626953125 +1787 -0.279754638671875 +1788 -0.3389892578125 +1789 -0.3543701171875 +1790 -0.348175048828125 +1791 -0.32598876953125 +1792 -0.2581787109375 +1793 -0.139801025390625 +1794 0.014617919921875 +1795 0.144378662109375 +1796 0.221038818359375 +1797 0.27069091796875 +1798 0.294036865234375 +1799 0.311767578125 +1800 0.339141845703125 +1801 0.360260009765625 +1802 0.360504150390625 +1803 0.308380126953125 +1804 0.18170166015625 +1805 0.0047607421875 +1806 -0.17559814453125 +1807 -0.3143310546875 +1808 -0.36785888671875 +1809 -0.36248779296875 +1810 -0.343536376953125 +1811 -0.3018798828125 +1812 -0.231414794921875 +1813 -0.117645263671875 +1814 0.007049560546875 +1815 0.087982177734375 +1816 0.13946533203125 +1817 0.17425537109375 +1818 0.188201904296875 +1819 0.171234130859375 +1820 0.118438720703125 +1821 0.05706787109375 +1822 -0.010711669921875 +1823 -0.0914306640625 +1824 -0.162322998046875 +1825 -0.194549560546875 +1826 -0.1492919921875 +1827 -0.02166748046875 +1828 0.124053955078125 +1829 0.211151123046875 +1830 0.240447998046875 +1831 0.242218017578125 +1832 0.2257080078125 +1833 0.194366455078125 +1834 0.115509033203125 +1835 0.0128173828125 +1836 -0.053802490234375 +1837 -0.110626220703125 +1838 -0.199493408203125 +1839 -0.29437255859375 +1840 -0.33221435546875 +1841 -0.27972412109375 +1842 -0.185333251953125 +1843 -0.128204345703125 +1844 -0.115692138671875 +1845 -0.116455078125 +1846 -0.105926513671875 +1847 -0.053955078125 +1848 0.048797607421875 +1849 0.157318115234375 +1850 0.212005615234375 +1851 0.218475341796875 +1852 0.23724365234375 +1853 0.30535888671875 +1854 0.38128662109375 +1855 0.404449462890625 +1856 0.3944091796875 +1857 0.3885498046875 +1858 0.362640380859375 +1859 0.27362060546875 +1860 0.11712646484375 +1861 -0.054901123046875 +1862 -0.19085693359375 +1863 -0.28570556640625 +1864 -0.339263916015625 +1865 -0.3775634765625 +1866 -0.445709228515625 +1867 -0.535064697265625 +1868 -0.629058837890625 +1869 -0.697601318359375 +1870 -0.70391845703125 +1871 -0.6424560546875 +1872 -0.491241455078125 +1873 -0.265716552734375 +1874 -0.023712158203125 +1875 0.201751708984375 +1876 0.375823974609375 +1877 0.485076904296875 +1878 0.56884765625 +1879 0.634765625 +1880 0.63763427734375 +1881 0.5660400390625 +1882 0.4720458984375 +1883 0.40692138671875 +1884 0.3778076171875 +1885 0.376953125 +1886 0.371978759765625 +1887 0.313140869140625 +1888 0.184417724609375 +1889 0.011199951171875 +1890 -0.171051025390625 +1891 -0.33740234375 +1892 -0.47198486328125 +1893 -0.560394287109375 +1894 -0.58056640625 +1895 -0.54754638671875 +1896 -0.508575439453125 +1897 -0.459503173828125 +1898 -0.394378662109375 +1899 -0.35260009765625 +1900 -0.31170654296875 +1901 -0.197418212890625 +1902 -0.007965087890625 +1903 0.207489013671875 +1904 0.409210205078125 +1905 0.57208251953125 +1906 0.66595458984375 +1907 0.65875244140625 +1908 0.56744384765625 +1909 0.431396484375 +1910 0.29443359375 +1911 0.182464599609375 +1912 0.06365966796875 +1913 -0.075958251953125 +1914 -0.189422607421875 +1915 -0.271942138671875 +1916 -0.342529296875 +1917 -0.364166259765625 +1918 -0.327239990234375 +1919 -0.2769775390625 +1920 -0.253692626953125 +1921 -0.24365234375 +1922 -0.1983642578125 +1923 -0.116241455078125 +1924 -0.036834716796875 +1925 0.034881591796875 +1926 0.09124755859375 +1927 0.10888671875 +1928 0.125518798828125 +1929 0.15771484375 +1930 0.17828369140625 +1931 0.17108154296875 +1932 0.129974365234375 +1933 0.082427978515625 +1934 0.027679443359375 +1935 -0.065643310546875 +1936 -0.15936279296875 +1937 -0.21307373046875 +1938 -0.234649658203125 +1939 -0.2001953125 +1940 -0.119171142578125 +1941 -0.024749755859375 +1942 0.085784912109375 +1943 0.178131103515625 +1944 0.215576171875 +1945 0.211456298828125 +1946 0.17523193359375 +1947 0.128753662109375 +1948 0.1019287109375 +1949 0.0743408203125 +1950 0.04327392578125 +1951 0.038177490234375 +1952 0.076263427734375 +1953 0.14105224609375 +1954 0.186431884765625 +1955 0.188812255859375 +1956 0.1390380859375 +1957 0.041778564453125 +1958 -0.079437255859375 +1959 -0.219390869140625 +1960 -0.367828369140625 +1961 -0.494873046875 +1962 -0.556243896484375 +1963 -0.508697509765625 +1964 -0.3756103515625 +1965 -0.218902587890625 +1966 -0.063751220703125 +1967 0.091552734375 +1968 0.23602294921875 +1969 0.342987060546875 +1970 0.39520263671875 +1971 0.389373779296875 +1972 0.324249267578125 +1973 0.224090576171875 +1974 0.124267578125 +1975 0.037078857421875 +1976 -0.010101318359375 +1977 -0.019439697265625 +1978 -0.022796630859375 +1979 -0.001556396484375 +1980 0.056304931640625 +1981 0.106719970703125 +1982 0.096893310546875 +1983 0.042694091796875 +1984 -0.018035888671875 +1985 -0.07586669921875 +1986 -0.11944580078125 +1987 -0.15972900390625 +1988 -0.202606201171875 +1989 -0.24859619140625 +1990 -0.30517578125 +1991 -0.36212158203125 +1992 -0.39141845703125 +1993 -0.35528564453125 +1994 -0.249969482421875 +1995 -0.092864990234375 +1996 0.08905029296875 +1997 0.2352294921875 +1998 0.318817138671875 +1999 0.358642578125 +2000 0.347747802734375 +2001 0.28564453125 +2002 0.223175048828125 +2003 0.196746826171875 +2004 0.179840087890625 +2005 0.155548095703125 +2006 0.151214599609375 +2007 0.156951904296875 +2008 0.13177490234375 +2009 0.100799560546875 +2010 0.087127685546875 +2011 0.05487060546875 +2012 -0.009002685546875 +2013 -0.10400390625 +2014 -0.229400634765625 +2015 -0.35552978515625 +2016 -0.441925048828125 +2017 -0.473846435546875 +2018 -0.464813232421875 +2019 -0.419097900390625 +2020 -0.334320068359375 +2021 -0.227935791015625 +2022 -0.12347412109375 +2023 -0.02764892578125 +2024 0.077667236328125 +2025 0.2132568359375 +2026 0.38885498046875 +2027 0.582794189453125 +2028 0.734039306640625 +2029 0.800140380859375 +2030 0.7783203125 +2031 0.6651611328125 +2032 0.45965576171875 +2033 0.199188232421875 +2034 -0.050689697265625 +2035 -0.23297119140625 +2036 -0.33013916015625 +2037 -0.368408203125 +2038 -0.378936767578125 +2039 -0.376983642578125 +2040 -0.37969970703125 +2041 -0.391510009765625 +2042 -0.385345458984375 +2043 -0.3419189453125 +2044 -0.28289794921875 +2045 -0.251617431640625 +2046 -0.266143798828125 +2047 -0.273345947265625 +2048 -0.216796875 +2049 -0.128265380859375 +2050 -0.068145751953125 +2051 -0.0430908203125 +2052 -0.024444580078125 +2053 0.020721435546875 +2054 0.124481201171875 +2055 0.25787353515625 +2056 0.379119873046875 +2057 0.47991943359375 +2058 0.5281982421875 +2059 0.511138916015625 +2060 0.456207275390625 +2061 0.407470703125 +2062 0.383758544921875 +2063 0.35687255859375 +2064 0.31182861328125 +2065 0.250885009765625 +2066 0.1654052734375 +2067 0.035247802734375 +2068 -0.142059326171875 +2069 -0.33563232421875 +2070 -0.5345458984375 +2071 -0.72186279296875 +2072 -0.836669921875 +2073 -0.8326416015625 +2074 -0.7296142578125 +2075 -0.582550048828125 +2076 -0.440093994140625 +2077 -0.324310302734375 +2078 -0.20147705078125 +2079 -0.044647216796875 +2080 0.103973388671875 +2081 0.202392578125 +2082 0.264495849609375 +2083 0.338897705078125 +2084 0.443817138671875 +2085 0.545074462890625 +2086 0.6173095703125 +2087 0.6524658203125 +2088 0.66339111328125 +2089 0.6561279296875 +2090 0.606781005859375 +2091 0.501190185546875 +2092 0.352783203125 +2093 0.176544189453125 +2094 -0.034820556640625 +2095 -0.258209228515625 +2096 -0.44244384765625 +2097 -0.5753173828125 +2098 -0.65203857421875 +2099 -0.641632080078125 +2100 -0.562164306640625 +2101 -0.458038330078125 +2102 -0.350555419921875 +2103 -0.260528564453125 +2104 -0.192108154296875 +2105 -0.141937255859375 +2106 -0.1021728515625 +2107 -0.062896728515625 +2108 -0.011932373046875 +2109 0.062835693359375 +2110 0.148712158203125 +2111 0.241729736328125 +2112 0.34912109375 +2113 0.457305908203125 +2114 0.54388427734375 +2115 0.5728759765625 +2116 0.506591796875 +2117 0.351226806640625 +2118 0.146514892578125 +2119 -0.05523681640625 +2120 -0.21624755859375 +2121 -0.334930419921875 +2122 -0.402984619140625 +2123 -0.4412841796875 +2124 -0.49578857421875 +2125 -0.5601806640625 +2126 -0.600738525390625 +2127 -0.584228515625 +2128 -0.47930908203125 +2129 -0.27935791015625 +2130 -0.0089111328125 +2131 0.268798828125 +2132 0.482818603515625 +2133 0.60369873046875 +2134 0.650421142578125 +2135 0.66400146484375 +2136 0.6414794921875 +2137 0.572540283203125 +2138 0.498138427734375 +2139 0.439453125 +2140 0.375518798828125 +2141 0.274505615234375 +2142 0.1087646484375 +2143 -0.099395751953125 +2144 -0.3182373046875 +2145 -0.5489501953125 +2146 -0.7738037109375 +2147 -0.86383056640625 +2148 -0.870391845703125 +2149 -0.86895751953125 +2150 -0.861053466796875 +2151 -0.765869140625 +2152 -0.5301513671875 +2153 -0.214691162109375 +2154 0.137359619140625 +2155 0.474822998046875 +2156 0.76239013671875 +2157 0.867462158203125 +2158 0.870361328125 +2159 0.86480712890625 +2160 0.831817626953125 +2161 0.677581787109375 +2162 0.495880126953125 +2163 0.30767822265625 +2164 0.116180419921875 +2165 -0.110748291015625 +2166 -0.381805419921875 +2167 -0.6572265625 +2168 -0.857421875 +2169 -0.870391845703125 +2170 -0.870391845703125 +2171 -0.86444091796875 +2172 -0.85723876953125 +2173 -0.790008544921875 +2174 -0.62847900390625 +2175 -0.3956298828125 +2176 -0.126708984375 +2177 0.150115966796875 +2178 0.424041748046875 +2179 0.670623779296875 +2180 0.854522705078125 +2181 0.866485595703125 +2182 0.86920166015625 +2183 0.8653564453125 +2184 0.857147216796875 +2185 0.766845703125 +2186 0.628509521484375 +2187 0.462127685546875 +2188 0.297210693359375 +2189 0.14862060546875 +2190 -0.00537109375 +2191 -0.15753173828125 +2192 -0.31304931640625 +2193 -0.48876953125 +2194 -0.6416015625 +2195 -0.751373291015625 +2196 -0.84619140625 +2197 -0.861297607421875 +2198 -0.863250732421875 +2199 -0.856597900390625 +2200 -0.7498779296875 +2201 -0.624542236328125 +2202 -0.47808837890625 +2203 -0.253387451171875 +2204 0.003692626953125 +2205 0.2257080078125 +2206 0.427154541015625 +2207 0.643218994140625 +2208 0.855926513671875 +2209 0.870361328125 +2210 0.870361328125 +2211 0.862762451171875 +2212 0.79669189453125 +2213 0.595794677734375 +2214 0.362152099609375 +2215 0.1270751953125 +2216 -0.086944580078125 +2217 -0.2784423828125 +2218 -0.484832763671875 +2219 -0.729583740234375 +2220 -0.86688232421875 +2221 -0.870391845703125 +2222 -0.86859130859375 +2223 -0.86279296875 +2224 -0.817962646484375 +2225 -0.6116943359375 +2226 -0.3128662109375 +2227 0.039398193359375 +2228 0.422821044921875 +2229 0.805145263671875 +2230 0.870361328125 +2231 0.870361328125 +2232 0.860015869140625 +2233 0.727935791015625 +2234 0.48114013671875 +2235 0.2059326171875 +2236 -0.06103515625 +2237 -0.29913330078125 +2238 -0.516204833984375 +2239 -0.7252197265625 +2240 -0.85980224609375 +2241 -0.870391845703125 +2242 -0.870391845703125 +2243 -0.858062744140625 +2244 -0.673004150390625 +2245 -0.42694091796875 +2246 -0.2100830078125 +2247 -0.0362548828125 +2248 0.10943603515625 +2249 0.23516845703125 +2250 0.373687744140625 +2251 0.517791748046875 +2252 0.602783203125 +2253 0.635711669921875 +2254 0.655181884765625 +2255 0.65948486328125 +2256 0.651275634765625 +2257 0.61846923828125 +2258 0.53753662109375 +2259 0.404144287109375 +2260 0.22186279296875 +2261 0.003997802734375 +2262 -0.22100830078125 +2263 -0.42449951171875 +2264 -0.579833984375 +2265 -0.641876220703125 +2266 -0.6177978515625 +2267 -0.575531005859375 +2268 -0.526336669921875 +2269 -0.42645263671875 +2270 -0.2581787109375 +2271 -0.068695068359375 +2272 0.09222412109375 +2273 0.232147216796875 +2274 0.3509521484375 +2275 0.410064697265625 +2276 0.372955322265625 +2277 0.2554931640625 +2278 0.10711669921875 +2279 -0.052886962890625 +2280 -0.186279296875 +2281 -0.23291015625 +2282 -0.209442138671875 +2283 -0.174163818359375 +2284 -0.126739501953125 +2285 -0.048126220703125 +2286 0.0426025390625 +2287 0.10748291015625 +2288 0.1409912109375 +2289 0.19708251953125 +2290 0.273651123046875 +2291 0.31768798828125 +2292 0.341094970703125 +2293 0.368011474609375 +2294 0.37249755859375 +2295 0.30072021484375 +2296 0.1517333984375 +2297 -0.01470947265625 +2298 -0.1883544921875 +2299 -0.372711181640625 +2300 -0.51397705078125 +2301 -0.57177734375 +2302 -0.53948974609375 +2303 -0.43511962890625 +2304 -0.2962646484375 +2305 -0.161102294921875 +2306 -0.0435791015625 +2307 0.060394287109375 +2308 0.13665771484375 +2309 0.170135498046875 +2310 0.16552734375 +2311 0.15728759765625 +2312 0.150787353515625 +2313 0.12200927734375 +2314 0.080108642578125 +2315 0.05126953125 +2316 0.062896728515625 +2317 0.09271240234375 +2318 0.092987060546875 +2319 0.07855224609375 +2320 0.06427001953125 +2321 0.0347900390625 +2322 -0.01171875 +2323 -0.056060791015625 +2324 -0.055511474609375 +2325 -0.010467529296875 +2326 0.02508544921875 +2327 0.025665283203125 +2328 0.017333984375 +2329 0.00189208984375 +2330 -0.03173828125 +2331 -0.071502685546875 +2332 -0.13543701171875 +2333 -0.219970703125 +2334 -0.300506591796875 +2335 -0.376312255859375 +2336 -0.416107177734375 +2337 -0.371124267578125 +2338 -0.242279052734375 +2339 -0.069732666015625 +2340 0.125640869140625 +2341 0.31268310546875 +2342 0.45501708984375 +2343 0.554779052734375 +2344 0.61065673828125 +2345 0.610931396484375 +2346 0.531463623046875 +2347 0.3883056640625 +2348 0.23468017578125 +2349 0.095245361328125 +2350 -0.00396728515625 +2351 -0.04852294921875 +2352 -0.055145263671875 +2353 -0.0758056640625 +2354 -0.138702392578125 +2355 -0.209197998046875 +2356 -0.289031982421875 +2357 -0.37884521484375 +2358 -0.456329345703125 +2359 -0.51641845703125 +2360 -0.519287109375 +2361 -0.458251953125 +2362 -0.384796142578125 +2363 -0.323699951171875 +2364 -0.269287109375 +2365 -0.1951904296875 +2366 -0.100006103515625 +2367 -0.01055908203125 +2368 0.1033935546875 +2369 0.24908447265625 +2370 0.373199462890625 +2371 0.45806884765625 +2372 0.511474609375 +2373 0.565399169921875 +2374 0.61138916015625 +2375 0.5897216796875 +2376 0.4906005859375 +2377 0.33148193359375 +2378 0.147796630859375 +2379 -0.01873779296875 +2380 -0.140289306640625 +2381 -0.191986083984375 +2382 -0.184295654296875 +2383 -0.161834716796875 +2384 -0.166595458984375 +2385 -0.19390869140625 +2386 -0.22442626953125 +2387 -0.279754638671875 +2388 -0.3389892578125 +2389 -0.3543701171875 +2390 -0.348175048828125 +2391 -0.32598876953125 +2392 -0.2581787109375 +2393 -0.139801025390625 +2394 0.014617919921875 +2395 0.144378662109375 +2396 0.221038818359375 +2397 0.27069091796875 +2398 0.294036865234375 +2399 0.311767578125 +2400 0.339141845703125 +2401 0.360260009765625 +2402 0.360504150390625 +2403 0.308380126953125 +2404 0.18170166015625 +2405 0.0047607421875 +2406 -0.17559814453125 +2407 -0.3143310546875 +2408 -0.36785888671875 +2409 -0.36248779296875 +2410 -0.343536376953125 +2411 -0.3018798828125 +2412 -0.231414794921875 +2413 -0.117645263671875 +2414 0.007049560546875 +2415 0.087982177734375 +2416 0.13946533203125 +2417 0.17425537109375 +2418 0.188201904296875 +2419 0.171234130859375 +2420 0.118438720703125 +2421 0.05706787109375 +2422 -0.010711669921875 +2423 -0.0914306640625 +2424 -0.162322998046875 +2425 -0.194549560546875 +2426 -0.1492919921875 +2427 -0.02166748046875 +2428 0.124053955078125 +2429 0.211151123046875 +2430 0.240447998046875 +2431 0.242218017578125 +2432 0.2257080078125 +2433 0.194366455078125 +2434 0.115509033203125 +2435 0.0128173828125 +2436 -0.053802490234375 +2437 -0.110626220703125 +2438 -0.199493408203125 +2439 -0.29437255859375 +2440 -0.33221435546875 +2441 -0.27972412109375 +2442 -0.185333251953125 +2443 -0.128204345703125 +2444 -0.115692138671875 +2445 -0.116455078125 +2446 -0.105926513671875 +2447 -0.053955078125 +2448 0.048797607421875 +2449 0.157318115234375 +2450 0.212005615234375 +2451 0.218475341796875 +2452 0.23724365234375 +2453 0.30535888671875 +2454 0.38128662109375 +2455 0.404449462890625 +2456 0.3944091796875 +2457 0.3885498046875 +2458 0.362640380859375 +2459 0.27362060546875 +2460 0.11712646484375 +2461 -0.054901123046875 +2462 -0.19085693359375 +2463 -0.28570556640625 +2464 -0.339263916015625 +2465 -0.3775634765625 +2466 -0.445709228515625 +2467 -0.535064697265625 +2468 -0.629058837890625 +2469 -0.697601318359375 +2470 -0.70391845703125 +2471 -0.6424560546875 +2472 -0.491241455078125 +2473 -0.265716552734375 +2474 -0.023712158203125 +2475 0.201751708984375 +2476 0.375823974609375 +2477 0.485076904296875 +2478 0.56884765625 +2479 0.634765625 +2480 0.63763427734375 +2481 0.5660400390625 +2482 0.4720458984375 +2483 0.40692138671875 +2484 0.3778076171875 +2485 0.376953125 +2486 0.371978759765625 +2487 0.313140869140625 +2488 0.184417724609375 +2489 0.011199951171875 +2490 -0.171051025390625 +2491 -0.33740234375 +2492 -0.47198486328125 +2493 -0.560394287109375 +2494 -0.58056640625 +2495 -0.54754638671875 +2496 -0.508575439453125 +2497 -0.459503173828125 +2498 -0.394378662109375 +2499 -0.35260009765625 +2500 -0.31170654296875 +2501 -0.197418212890625 +2502 -0.007965087890625 +2503 0.207489013671875 +2504 0.409210205078125 +2505 0.57208251953125 +2506 0.66595458984375 +2507 0.65875244140625 +2508 0.56744384765625 +2509 0.431396484375 +2510 0.29443359375 +2511 0.182464599609375 +2512 0.06365966796875 +2513 -0.075958251953125 +2514 -0.189422607421875 +2515 -0.271942138671875 +2516 -0.342529296875 +2517 -0.364166259765625 +2518 -0.327239990234375 +2519 -0.2769775390625 +2520 -0.253692626953125 +2521 -0.24365234375 +2522 -0.1983642578125 +2523 -0.116241455078125 +2524 -0.036834716796875 +2525 0.034881591796875 +2526 0.09124755859375 +2527 0.10888671875 +2528 0.125518798828125 +2529 0.15771484375 +2530 0.17828369140625 +2531 0.17108154296875 +2532 0.129974365234375 +2533 0.082427978515625 +2534 0.027679443359375 +2535 -0.065643310546875 +2536 -0.15936279296875 +2537 -0.21307373046875 +2538 -0.234649658203125 +2539 -0.2001953125 +2540 -0.119171142578125 +2541 -0.024749755859375 +2542 0.085784912109375 +2543 0.178131103515625 +2544 0.215576171875 +2545 0.211456298828125 +2546 0.17523193359375 +2547 0.128753662109375 +2548 0.1019287109375 +2549 0.0743408203125 +2550 0.04327392578125 +2551 0.038177490234375 +2552 0.076263427734375 +2553 0.14105224609375 +2554 0.186431884765625 +2555 0.188812255859375 +2556 0.1390380859375 +2557 0.041778564453125 +2558 -0.079437255859375 +2559 -0.219390869140625 +2560 -0.367828369140625 +2561 -0.494873046875 +2562 -0.556243896484375 +2563 -0.508697509765625 +2564 -0.3756103515625 +2565 -0.218902587890625 +2566 -0.063751220703125 +2567 0.091552734375 +2568 0.23602294921875 +2569 0.342987060546875 +2570 0.39520263671875 +2571 0.389373779296875 +2572 0.324249267578125 +2573 0.224090576171875 +2574 0.124267578125 +2575 0.037078857421875 +2576 -0.010101318359375 +2577 -0.019439697265625 +2578 -0.022796630859375 +2579 -0.001556396484375 +2580 0.056304931640625 +2581 0.106719970703125 +2582 0.096893310546875 +2583 0.042694091796875 +2584 -0.018035888671875 +2585 -0.07586669921875 +2586 -0.11944580078125 +2587 -0.15972900390625 +2588 -0.202606201171875 +2589 -0.24859619140625 +2590 -0.30517578125 +2591 -0.36212158203125 +2592 -0.39141845703125 +2593 -0.35528564453125 +2594 -0.249969482421875 +2595 -0.092864990234375 +2596 0.08905029296875 +2597 0.2352294921875 +2598 0.318817138671875 +2599 0.358642578125 +2600 0.347747802734375 +2601 0.28564453125 +2602 0.223175048828125 +2603 0.196746826171875 +2604 0.179840087890625 +2605 0.155548095703125 +2606 0.151214599609375 +2607 0.156951904296875 +2608 0.13177490234375 +2609 0.100799560546875 +2610 0.087127685546875 +2611 0.05487060546875 +2612 -0.009002685546875 +2613 -0.10400390625 +2614 -0.229400634765625 +2615 -0.35552978515625 +2616 -0.441925048828125 +2617 -0.473846435546875 +2618 -0.464813232421875 +2619 -0.419097900390625 +2620 -0.334320068359375 +2621 -0.227935791015625 +2622 -0.12347412109375 +2623 -0.02764892578125 +2624 0.077667236328125 +2625 0.2132568359375 +2626 0.38885498046875 +2627 0.582794189453125 +2628 0.734039306640625 +2629 0.800140380859375 +2630 0.7783203125 +2631 0.6651611328125 +2632 0.45965576171875 +2633 0.199188232421875 +2634 -0.050689697265625 +2635 -0.23297119140625 +2636 -0.33013916015625 +2637 -0.368408203125 +2638 -0.378936767578125 +2639 -0.376983642578125 +2640 -0.37969970703125 +2641 -0.391510009765625 +2642 -0.385345458984375 +2643 -0.3419189453125 +2644 -0.28289794921875 +2645 -0.251617431640625 +2646 -0.266143798828125 +2647 -0.273345947265625 +2648 -0.216796875 +2649 -0.128265380859375 +2650 -0.068145751953125 +2651 -0.0430908203125 +2652 -0.024444580078125 +2653 0.020721435546875 +2654 0.124481201171875 +2655 0.25787353515625 +2656 0.379119873046875 +2657 0.47991943359375 +2658 0.5281982421875 +2659 0.511138916015625 +2660 0.456207275390625 +2661 0.407470703125 +2662 0.383758544921875 +2663 0.35687255859375 +2664 0.31182861328125 +2665 0.250885009765625 +2666 0.1654052734375 +2667 0.035247802734375 +2668 -0.142059326171875 +2669 -0.33563232421875 +2670 -0.5345458984375 +2671 -0.72186279296875 +2672 -0.836669921875 +2673 -0.8326416015625 +2674 -0.7296142578125 +2675 -0.582550048828125 +2676 -0.440093994140625 +2677 -0.324310302734375 +2678 -0.20147705078125 +2679 -0.044647216796875 +2680 0.103973388671875 +2681 0.202392578125 +2682 0.264495849609375 +2683 0.338897705078125 +2684 0.443817138671875 +2685 0.545074462890625 +2686 0.6173095703125 +2687 0.6524658203125 +2688 0.66339111328125 +2689 0.6561279296875 +2690 0.606781005859375 +2691 0.501190185546875 +2692 0.352783203125 +2693 0.176544189453125 +2694 -0.034820556640625 +2695 -0.258209228515625 +2696 -0.44244384765625 +2697 -0.5753173828125 +2698 -0.65203857421875 +2699 -0.641632080078125 +2700 -0.562164306640625 +2701 -0.458038330078125 +2702 -0.350555419921875 +2703 -0.260528564453125 +2704 -0.192108154296875 +2705 -0.141937255859375 +2706 -0.1021728515625 +2707 -0.062896728515625 +2708 -0.011932373046875 +2709 0.062835693359375 +2710 0.148712158203125 +2711 0.241729736328125 +2712 0.34912109375 +2713 0.457305908203125 +2714 0.54388427734375 +2715 0.5728759765625 +2716 0.506591796875 +2717 0.351226806640625 +2718 0.146514892578125 +2719 -0.05523681640625 +2720 -0.21624755859375 +2721 -0.334930419921875 +2722 -0.402984619140625 +2723 -0.4412841796875 +2724 -0.49578857421875 +2725 -0.5601806640625 +2726 -0.600738525390625 +2727 -0.584228515625 +2728 -0.47930908203125 +2729 -0.27935791015625 +2730 -0.0089111328125 +2731 0.268798828125 +2732 0.482818603515625 +2733 0.60369873046875 +2734 0.650421142578125 +2735 0.66400146484375 +2736 0.6414794921875 +2737 0.572540283203125 +2738 0.498138427734375 +2739 0.439453125 +2740 0.375518798828125 +2741 0.274505615234375 +2742 0.1087646484375 +2743 -0.099395751953125 +2744 -0.3182373046875 +2745 -0.5489501953125 +2746 -0.7738037109375 +2747 -0.86383056640625 +2748 -0.870391845703125 +2749 -0.86895751953125 +2750 -0.861053466796875 +2751 -0.765869140625 +2752 -0.5301513671875 +2753 -0.214691162109375 +2754 0.137359619140625 +2755 0.474822998046875 +2756 0.76239013671875 +2757 0.867462158203125 +2758 0.870361328125 +2759 0.86480712890625 +2760 0.831817626953125 +2761 0.677581787109375 +2762 0.495880126953125 +2763 0.30767822265625 +2764 0.116180419921875 +2765 -0.110748291015625 +2766 -0.381805419921875 +2767 -0.6572265625 +2768 -0.857421875 +2769 -0.870391845703125 +2770 -0.870391845703125 +2771 -0.86444091796875 +2772 -0.85723876953125 +2773 -0.790008544921875 +2774 -0.62847900390625 +2775 -0.3956298828125 +2776 -0.126708984375 +2777 0.150115966796875 +2778 0.424041748046875 +2779 0.670623779296875 +2780 0.854522705078125 +2781 0.866485595703125 +2782 0.86920166015625 +2783 0.8653564453125 +2784 0.857147216796875 +2785 0.766845703125 +2786 0.628509521484375 +2787 0.462127685546875 +2788 0.297210693359375 +2789 0.14862060546875 +2790 -0.00537109375 +2791 -0.15753173828125 +2792 -0.31304931640625 +2793 -0.48876953125 +2794 -0.6416015625 +2795 -0.751373291015625 +2796 -0.84619140625 +2797 -0.861297607421875 +2798 -0.863250732421875 +2799 -0.856597900390625 +2800 -0.7498779296875 +2801 -0.624542236328125 +2802 -0.47808837890625 +2803 -0.253387451171875 +2804 0.003692626953125 +2805 0.2257080078125 +2806 0.427154541015625 +2807 0.643218994140625 +2808 0.855926513671875 +2809 0.870361328125 +2810 0.870361328125 +2811 0.862762451171875 +2812 0.79669189453125 +2813 0.595794677734375 +2814 0.362152099609375 +2815 0.1270751953125 +2816 -0.086944580078125 +2817 -0.2784423828125 +2818 -0.484832763671875 +2819 -0.729583740234375 +2820 -0.86688232421875 +2821 -0.870391845703125 +2822 -0.86859130859375 +2823 -0.86279296875 +2824 -0.817962646484375 +2825 -0.6116943359375 +2826 -0.3128662109375 +2827 0.039398193359375 +2828 0.422821044921875 +2829 0.805145263671875 +2830 0.870361328125 +2831 0.870361328125 +2832 0.860015869140625 +2833 0.727935791015625 +2834 0.48114013671875 +2835 0.2059326171875 +2836 -0.06103515625 +2837 -0.29913330078125 +2838 -0.516204833984375 +2839 -0.7252197265625 +2840 -0.85980224609375 +2841 -0.870391845703125 +2842 -0.870391845703125 +2843 -0.858062744140625 +2844 -0.673004150390625 +2845 -0.42694091796875 +2846 -0.2100830078125 +2847 -0.0362548828125 +2848 0.10943603515625 +2849 0.23516845703125 +2850 0.373687744140625 +2851 0.517791748046875 +2852 0.602783203125 +2853 0.635711669921875 +2854 0.655181884765625 +2855 0.65948486328125 +2856 0.651275634765625 +2857 0.61846923828125 +2858 0.53753662109375 +2859 0.404144287109375 +2860 0.22186279296875 +2861 0.003997802734375 +2862 -0.22100830078125 +2863 -0.42449951171875 +2864 -0.579833984375 +2865 -0.641876220703125 +2866 -0.6177978515625 +2867 -0.575531005859375 +2868 -0.526336669921875 +2869 -0.42645263671875 +2870 -0.2581787109375 +2871 -0.068695068359375 +2872 0.09222412109375 +2873 0.232147216796875 +2874 0.3509521484375 +2875 0.410064697265625 +2876 0.372955322265625 +2877 0.2554931640625 +2878 0.10711669921875 +2879 -0.052886962890625 +2880 -0.186279296875 +2881 -0.23291015625 +2882 -0.209442138671875 +2883 -0.174163818359375 +2884 -0.126739501953125 +2885 -0.048126220703125 +2886 0.0426025390625 +2887 0.10748291015625 +2888 0.1409912109375 +2889 0.19708251953125 +2890 0.273651123046875 +2891 0.31768798828125 +2892 0.341094970703125 +2893 0.368011474609375 +2894 0.37249755859375 +2895 0.30072021484375 +2896 0.1517333984375 +2897 -0.01470947265625 +2898 -0.1883544921875 +2899 -0.372711181640625 +2900 -0.51397705078125 +2901 -0.57177734375 +2902 -0.53948974609375 +2903 -0.43511962890625 +2904 -0.2962646484375 +2905 -0.161102294921875 +2906 -0.0435791015625 +2907 0.060394287109375 +2908 0.13665771484375 +2909 0.170135498046875 +2910 0.16552734375 +2911 0.15728759765625 +2912 0.150787353515625 +2913 0.12200927734375 +2914 0.080108642578125 +2915 0.05126953125 +2916 0.062896728515625 +2917 0.09271240234375 +2918 0.092987060546875 +2919 0.07855224609375 +2920 0.06427001953125 +2921 0.0347900390625 +2922 -0.01171875 +2923 -0.056060791015625 +2924 -0.055511474609375 +2925 -0.010467529296875 +2926 0.02508544921875 +2927 0.025665283203125 +2928 0.017333984375 +2929 0.00189208984375 +2930 -0.03173828125 +2931 -0.071502685546875 +2932 -0.13543701171875 +2933 -0.219970703125 +2934 -0.300506591796875 +2935 -0.376312255859375 +2936 -0.416107177734375 +2937 -0.371124267578125 +2938 -0.242279052734375 +2939 -0.069732666015625 +2940 0.125640869140625 +2941 0.31268310546875 +2942 0.45501708984375 +2943 0.554779052734375 +2944 0.61065673828125 +2945 0.610931396484375 +2946 0.531463623046875 +2947 0.3883056640625 +2948 0.23468017578125 +2949 0.095245361328125 +2950 -0.00396728515625 +2951 -0.04852294921875 +2952 -0.055145263671875 +2953 -0.0758056640625 +2954 -0.138702392578125 +2955 -0.209197998046875 +2956 -0.289031982421875 +2957 -0.37884521484375 +2958 -0.456329345703125 +2959 -0.51641845703125 +2960 -0.519287109375 +2961 -0.458251953125 +2962 -0.384796142578125 +2963 -0.323699951171875 +2964 -0.269287109375 +2965 -0.1951904296875 +2966 -0.100006103515625 +2967 -0.01055908203125 +2968 0.1033935546875 +2969 0.24908447265625 +2970 0.373199462890625 +2971 0.45806884765625 +2972 0.511474609375 +2973 0.565399169921875 +2974 0.61138916015625 +2975 0.5897216796875 +2976 0.4906005859375 +2977 0.33148193359375 +2978 0.147796630859375 +2979 -0.01873779296875 +2980 -0.140289306640625 +2981 -0.191986083984375 +2982 -0.184295654296875 +2983 -0.161834716796875 +2984 -0.166595458984375 +2985 -0.19390869140625 +2986 -0.22442626953125 +2987 -0.279754638671875 +2988 -0.3389892578125 +2989 -0.3543701171875 +2990 -0.348175048828125 +2991 -0.32598876953125 +2992 -0.2581787109375 +2993 -0.139801025390625 +2994 0.014617919921875 +2995 0.144378662109375 +2996 0.221038818359375 +2997 0.27069091796875 +2998 0.294036865234375 +2999 0.311767578125 +3000 0.339141845703125 +3001 0.360260009765625 +3002 0.360504150390625 +3003 0.308380126953125 +3004 0.18170166015625 +3005 0.0047607421875 +3006 -0.17559814453125 +3007 -0.3143310546875 +3008 -0.36785888671875 +3009 -0.36248779296875 +3010 -0.343536376953125 +3011 -0.3018798828125 +3012 -0.231414794921875 +3013 -0.117645263671875 +3014 0.007049560546875 +3015 0.087982177734375 +3016 0.13946533203125 +3017 0.17425537109375 +3018 0.188201904296875 +3019 0.171234130859375 +3020 0.118438720703125 +3021 0.05706787109375 +3022 -0.010711669921875 +3023 -0.0914306640625 +3024 -0.162322998046875 +3025 -0.194549560546875 +3026 -0.1492919921875 +3027 -0.02166748046875 +3028 0.124053955078125 +3029 0.211151123046875 +3030 0.240447998046875 +3031 0.242218017578125 +3032 0.2257080078125 +3033 0.194366455078125 +3034 0.115509033203125 +3035 0.0128173828125 +3036 -0.053802490234375 +3037 -0.110626220703125 +3038 -0.199493408203125 +3039 -0.29437255859375 +3040 -0.33221435546875 +3041 -0.27972412109375 +3042 -0.185333251953125 +3043 -0.128204345703125 +3044 -0.115692138671875 +3045 -0.116455078125 +3046 -0.105926513671875 +3047 -0.053955078125 +3048 0.048797607421875 +3049 0.157318115234375 +3050 0.212005615234375 +3051 0.218475341796875 +3052 0.23724365234375 +3053 0.30535888671875 +3054 0.38128662109375 +3055 0.404449462890625 +3056 0.3944091796875 +3057 0.3885498046875 +3058 0.362640380859375 +3059 0.27362060546875 +3060 0.11712646484375 +3061 -0.054901123046875 +3062 -0.19085693359375 +3063 -0.28570556640625 +3064 -0.339263916015625 +3065 -0.3775634765625 +3066 -0.445709228515625 +3067 -0.535064697265625 +3068 -0.629058837890625 +3069 -0.697601318359375 +3070 -0.70391845703125 +3071 -0.6424560546875 +3072 -0.491241455078125 +3073 -0.265716552734375 +3074 -0.023712158203125 +3075 0.201751708984375 +3076 0.375823974609375 +3077 0.485076904296875 +3078 0.56884765625 +3079 0.634765625 +3080 0.63763427734375 +3081 0.5660400390625 +3082 0.4720458984375 +3083 0.40692138671875 +3084 0.3778076171875 +3085 0.376953125 +3086 0.371978759765625 +3087 0.313140869140625 +3088 0.184417724609375 +3089 0.011199951171875 +3090 -0.171051025390625 +3091 -0.33740234375 +3092 -0.47198486328125 +3093 -0.560394287109375 +3094 -0.58056640625 +3095 -0.54754638671875 +3096 -0.508575439453125 +3097 -0.459503173828125 +3098 -0.394378662109375 +3099 -0.35260009765625 +3100 -0.31170654296875 +3101 -0.197418212890625 +3102 -0.007965087890625 +3103 0.207489013671875 +3104 0.409210205078125 +3105 0.57208251953125 +3106 0.66595458984375 +3107 0.65875244140625 +3108 0.56744384765625 +3109 0.431396484375 +3110 0.29443359375 +3111 0.182464599609375 +3112 0.06365966796875 +3113 -0.075958251953125 +3114 -0.189422607421875 +3115 -0.271942138671875 +3116 -0.342529296875 +3117 -0.364166259765625 +3118 -0.327239990234375 +3119 -0.2769775390625 +3120 -0.253692626953125 +3121 -0.24365234375 +3122 -0.1983642578125 +3123 -0.116241455078125 +3124 -0.036834716796875 +3125 0.034881591796875 +3126 0.09124755859375 +3127 0.10888671875 +3128 0.125518798828125 +3129 0.15771484375 +3130 0.17828369140625 +3131 0.17108154296875 +3132 0.129974365234375 +3133 0.082427978515625 +3134 0.027679443359375 +3135 -0.065643310546875 +3136 -0.15936279296875 +3137 -0.21307373046875 +3138 -0.234649658203125 +3139 -0.2001953125 +3140 -0.119171142578125 +3141 -0.024749755859375 +3142 0.085784912109375 +3143 0.178131103515625 +3144 0.215576171875 +3145 0.211456298828125 +3146 0.17523193359375 +3147 0.128753662109375 +3148 0.1019287109375 +3149 0.0743408203125 +3150 0.04327392578125 +3151 0.038177490234375 +3152 0.076263427734375 +3153 0.14105224609375 +3154 0.186431884765625 +3155 0.188812255859375 +3156 0.1390380859375 +3157 0.041778564453125 +3158 -0.079437255859375 +3159 -0.219390869140625 +3160 -0.367828369140625 +3161 -0.494873046875 +3162 -0.556243896484375 +3163 -0.508697509765625 +3164 -0.3756103515625 +3165 -0.218902587890625 +3166 -0.063751220703125 +3167 0.091552734375 +3168 0.23602294921875 +3169 0.342987060546875 +3170 0.39520263671875 +3171 0.389373779296875 +3172 0.324249267578125 +3173 0.224090576171875 +3174 0.124267578125 +3175 0.037078857421875 +3176 -0.010101318359375 +3177 -0.019439697265625 +3178 -0.022796630859375 +3179 -0.001556396484375 +3180 0.056304931640625 +3181 0.106719970703125 +3182 0.096893310546875 +3183 0.042694091796875 +3184 -0.018035888671875 +3185 -0.07586669921875 +3186 -0.11944580078125 +3187 -0.15972900390625 +3188 -0.202606201171875 +3189 -0.24859619140625 +3190 -0.30517578125 +3191 -0.36212158203125 +3192 -0.39141845703125 +3193 -0.35528564453125 +3194 -0.249969482421875 +3195 -0.092864990234375 +3196 0.08905029296875 +3197 0.2352294921875 +3198 0.318817138671875 +3199 0.358642578125 +3200 0.347747802734375 +3201 0.28564453125 +3202 0.223175048828125 +3203 0.196746826171875 +3204 0.179840087890625 +3205 0.155548095703125 +3206 0.151214599609375 +3207 0.156951904296875 +3208 0.13177490234375 +3209 0.100799560546875 +3210 0.087127685546875 +3211 0.05487060546875 +3212 -0.009002685546875 +3213 -0.10400390625 +3214 -0.229400634765625 +3215 -0.35552978515625 +3216 -0.441925048828125 +3217 -0.473846435546875 +3218 -0.464813232421875 +3219 -0.419097900390625 +3220 -0.334320068359375 +3221 -0.227935791015625 +3222 -0.12347412109375 +3223 -0.02764892578125 +3224 0.077667236328125 +3225 0.2132568359375 +3226 0.38885498046875 +3227 0.582794189453125 +3228 0.734039306640625 +3229 0.800140380859375 +3230 0.7783203125 +3231 0.6651611328125 +3232 0.45965576171875 +3233 0.199188232421875 +3234 -0.050689697265625 +3235 -0.23297119140625 +3236 -0.33013916015625 +3237 -0.368408203125 +3238 -0.378936767578125 +3239 -0.376983642578125 +3240 -0.37969970703125 +3241 -0.391510009765625 +3242 -0.385345458984375 +3243 -0.3419189453125 +3244 -0.28289794921875 +3245 -0.251617431640625 +3246 -0.266143798828125 +3247 -0.273345947265625 +3248 -0.216796875 +3249 -0.128265380859375 +3250 -0.068145751953125 +3251 -0.0430908203125 +3252 -0.024444580078125 +3253 0.020721435546875 +3254 0.124481201171875 +3255 0.25787353515625 +3256 0.379119873046875 +3257 0.47991943359375 +3258 0.5281982421875 +3259 0.511138916015625 +3260 0.456207275390625 +3261 0.407470703125 +3262 0.383758544921875 +3263 0.35687255859375 +3264 0.31182861328125 +3265 0.250885009765625 +3266 0.1654052734375 +3267 0.035247802734375 +3268 -0.142059326171875 +3269 -0.33563232421875 +3270 -0.5345458984375 +3271 -0.72186279296875 +3272 -0.836669921875 +3273 -0.8326416015625 +3274 -0.7296142578125 +3275 -0.582550048828125 +3276 -0.440093994140625 +3277 -0.324310302734375 +3278 -0.20147705078125 +3279 -0.044647216796875 +3280 0.103973388671875 +3281 0.202392578125 +3282 0.264495849609375 +3283 0.338897705078125 +3284 0.443817138671875 +3285 0.545074462890625 +3286 0.6173095703125 +3287 0.6524658203125 +3288 0.66339111328125 +3289 0.6561279296875 +3290 0.606781005859375 +3291 0.501190185546875 +3292 0.352783203125 +3293 0.176544189453125 +3294 -0.034820556640625 +3295 -0.258209228515625 +3296 -0.44244384765625 +3297 -0.5753173828125 +3298 -0.65203857421875 +3299 -0.641632080078125 +3300 -0.562164306640625 +3301 -0.458038330078125 +3302 -0.350555419921875 +3303 -0.260528564453125 +3304 -0.192108154296875 +3305 -0.141937255859375 +3306 -0.1021728515625 +3307 -0.062896728515625 +3308 -0.011932373046875 +3309 0.062835693359375 +3310 0.148712158203125 +3311 0.241729736328125 +3312 0.34912109375 +3313 0.457305908203125 +3314 0.54388427734375 +3315 0.5728759765625 +3316 0.506591796875 +3317 0.351226806640625 +3318 0.146514892578125 +3319 -0.05523681640625 +3320 -0.21624755859375 +3321 -0.334930419921875 +3322 -0.402984619140625 +3323 -0.4412841796875 +3324 -0.49578857421875 +3325 -0.5601806640625 +3326 -0.600738525390625 +3327 -0.584228515625 +3328 -0.47930908203125 +3329 -0.27935791015625 +3330 -0.0089111328125 +3331 0.268798828125 +3332 0.482818603515625 +3333 0.60369873046875 +3334 0.650421142578125 +3335 0.66400146484375 +3336 0.6414794921875 +3337 0.572540283203125 +3338 0.498138427734375 +3339 0.439453125 +3340 0.375518798828125 +3341 0.274505615234375 +3342 0.1087646484375 +3343 -0.099395751953125 +3344 -0.3182373046875 +3345 -0.5489501953125 +3346 -0.7738037109375 +3347 -0.86383056640625 +3348 -0.870391845703125 +3349 -0.86895751953125 +3350 -0.861053466796875 +3351 -0.765869140625 +3352 -0.5301513671875 +3353 -0.214691162109375 +3354 0.137359619140625 +3355 0.474822998046875 +3356 0.76239013671875 +3357 0.867462158203125 +3358 0.870361328125 +3359 0.86480712890625 +3360 0.831817626953125 +3361 0.677581787109375 +3362 0.495880126953125 +3363 0.30767822265625 +3364 0.116180419921875 +3365 -0.110748291015625 +3366 -0.381805419921875 +3367 -0.6572265625 +3368 -0.857421875 +3369 -0.870391845703125 +3370 -0.870391845703125 +3371 -0.86444091796875 +3372 -0.85723876953125 +3373 -0.790008544921875 +3374 -0.62847900390625 +3375 -0.3956298828125 +3376 -0.126708984375 +3377 0.150115966796875 +3378 0.424041748046875 +3379 0.670623779296875 +3380 0.854522705078125 +3381 0.866485595703125 +3382 0.86920166015625 +3383 0.8653564453125 +3384 0.857147216796875 +3385 0.766845703125 +3386 0.628509521484375 +3387 0.462127685546875 +3388 0.297210693359375 +3389 0.14862060546875 +3390 -0.00537109375 +3391 -0.15753173828125 +3392 -0.31304931640625 +3393 -0.48876953125 +3394 -0.6416015625 +3395 -0.751373291015625 +3396 -0.84619140625 +3397 -0.861297607421875 +3398 -0.863250732421875 +3399 -0.856597900390625 +3400 -0.7498779296875 +3401 -0.624542236328125 +3402 -0.47808837890625 +3403 -0.253387451171875 +3404 0.003692626953125 +3405 0.2257080078125 +3406 0.427154541015625 +3407 0.643218994140625 +3408 0.855926513671875 +3409 0.870361328125 +3410 0.870361328125 +3411 0.862762451171875 +3412 0.79669189453125 +3413 0.595794677734375 +3414 0.362152099609375 +3415 0.1270751953125 +3416 -0.086944580078125 +3417 -0.2784423828125 +3418 -0.484832763671875 +3419 -0.729583740234375 +3420 -0.86688232421875 +3421 -0.870391845703125 +3422 -0.86859130859375 +3423 -0.86279296875 +3424 -0.817962646484375 +3425 -0.6116943359375 +3426 -0.3128662109375 +3427 0.039398193359375 +3428 0.422821044921875 +3429 0.805145263671875 +3430 0.870361328125 +3431 0.870361328125 +3432 0.860015869140625 +3433 0.727935791015625 +3434 0.48114013671875 +3435 0.2059326171875 +3436 -0.06103515625 +3437 -0.29913330078125 +3438 -0.516204833984375 +3439 -0.7252197265625 +3440 -0.85980224609375 +3441 -0.870391845703125 +3442 -0.870391845703125 +3443 -0.858062744140625 +3444 -0.673004150390625 +3445 -0.42694091796875 +3446 -0.2100830078125 +3447 -0.0362548828125 +3448 0.10943603515625 +3449 0.23516845703125 +3450 0.373687744140625 +3451 0.517791748046875 +3452 0.602783203125 +3453 0.635711669921875 +3454 0.655181884765625 +3455 0.65948486328125 +3456 0.651275634765625 +3457 0.61846923828125 +3458 0.53753662109375 +3459 0.404144287109375 +3460 0.22186279296875 +3461 0.003997802734375 +3462 -0.22100830078125 +3463 -0.42449951171875 +3464 -0.579833984375 +3465 -0.641876220703125 +3466 -0.6177978515625 +3467 -0.575531005859375 +3468 -0.526336669921875 +3469 -0.42645263671875 +3470 -0.2581787109375 +3471 -0.068695068359375 +3472 0.09222412109375 +3473 0.232147216796875 +3474 0.3509521484375 +3475 0.410064697265625 +3476 0.372955322265625 +3477 0.2554931640625 +3478 0.10711669921875 +3479 -0.052886962890625 +3480 -0.186279296875 +3481 -0.23291015625 +3482 -0.209442138671875 +3483 -0.174163818359375 +3484 -0.126739501953125 +3485 -0.048126220703125 +3486 0.0426025390625 +3487 0.10748291015625 +3488 0.1409912109375 +3489 0.19708251953125 +3490 0.273651123046875 +3491 0.31768798828125 +3492 0.341094970703125 +3493 0.368011474609375 +3494 0.37249755859375 +3495 0.30072021484375 +3496 0.1517333984375 +3497 -0.01470947265625 +3498 -0.1883544921875 +3499 -0.372711181640625 +3500 -0.51397705078125 +3501 -0.57177734375 +3502 -0.53948974609375 +3503 -0.43511962890625 +3504 -0.2962646484375 +3505 -0.161102294921875 +3506 -0.0435791015625 +3507 0.060394287109375 +3508 0.13665771484375 +3509 0.170135498046875 +3510 0.16552734375 +3511 0.15728759765625 +3512 0.150787353515625 +3513 0.12200927734375 +3514 0.080108642578125 +3515 0.05126953125 +3516 0.062896728515625 +3517 0.09271240234375 +3518 0.092987060546875 +3519 0.07855224609375 +3520 0.06427001953125 +3521 0.0347900390625 +3522 -0.01171875 +3523 -0.056060791015625 +3524 -0.055511474609375 +3525 -0.010467529296875 +3526 0.02508544921875 +3527 0.025665283203125 +3528 0.017333984375 +3529 0.00189208984375 +3530 -0.03173828125 +3531 -0.071502685546875 +3532 -0.13543701171875 +3533 -0.219970703125 +3534 -0.300506591796875 +3535 -0.376312255859375 +3536 -0.416107177734375 +3537 -0.371124267578125 +3538 -0.242279052734375 +3539 -0.069732666015625 +3540 0.125640869140625 +3541 0.31268310546875 +3542 0.45501708984375 +3543 0.554779052734375 +3544 0.61065673828125 +3545 0.610931396484375 +3546 0.531463623046875 +3547 0.3883056640625 +3548 0.23468017578125 +3549 0.095245361328125 +3550 -0.00396728515625 +3551 -0.04852294921875 +3552 -0.055145263671875 +3553 -0.0758056640625 +3554 -0.138702392578125 +3555 -0.209197998046875 +3556 -0.289031982421875 +3557 -0.37884521484375 +3558 -0.456329345703125 +3559 -0.51641845703125 +3560 -0.519287109375 +3561 -0.458251953125 +3562 -0.384796142578125 +3563 -0.323699951171875 +3564 -0.269287109375 +3565 -0.1951904296875 +3566 -0.100006103515625 +3567 -0.01055908203125 +3568 0.1033935546875 +3569 0.24908447265625 +3570 0.373199462890625 +3571 0.45806884765625 +3572 0.511474609375 +3573 0.565399169921875 +3574 0.61138916015625 +3575 0.5897216796875 +3576 0.4906005859375 +3577 0.33148193359375 +3578 0.147796630859375 +3579 -0.01873779296875 +3580 -0.140289306640625 +3581 -0.191986083984375 +3582 -0.184295654296875 +3583 -0.161834716796875 +3584 -0.166595458984375 +3585 -0.19390869140625 +3586 -0.22442626953125 +3587 -0.279754638671875 +3588 -0.3389892578125 +3589 -0.3543701171875 +3590 -0.348175048828125 +3591 -0.32598876953125 +3592 -0.2581787109375 +3593 -0.139801025390625 +3594 0.014617919921875 +3595 0.144378662109375 +3596 0.221038818359375 +3597 0.27069091796875 +3598 0.294036865234375 +3599 0.311767578125 +3600 0.339141845703125 +3601 0.360260009765625 +3602 0.360504150390625 +3603 0.308380126953125 +3604 0.18170166015625 +3605 0.0047607421875 +3606 -0.17559814453125 +3607 -0.3143310546875 +3608 -0.36785888671875 +3609 -0.36248779296875 +3610 -0.343536376953125 +3611 -0.3018798828125 +3612 -0.231414794921875 +3613 -0.117645263671875 +3614 0.007049560546875 +3615 0.087982177734375 +3616 0.13946533203125 +3617 0.17425537109375 +3618 0.188201904296875 +3619 0.171234130859375 +3620 0.118438720703125 +3621 0.05706787109375 +3622 -0.010711669921875 +3623 -0.0914306640625 +3624 -0.162322998046875 +3625 -0.194549560546875 +3626 -0.1492919921875 +3627 -0.02166748046875 +3628 0.124053955078125 +3629 0.211151123046875 +3630 0.240447998046875 +3631 0.242218017578125 +3632 0.2257080078125 +3633 0.194366455078125 +3634 0.115509033203125 +3635 0.0128173828125 +3636 -0.053802490234375 +3637 -0.110626220703125 +3638 -0.199493408203125 +3639 -0.29437255859375 +3640 -0.33221435546875 +3641 -0.27972412109375 +3642 -0.185333251953125 +3643 -0.128204345703125 +3644 -0.115692138671875 +3645 -0.116455078125 +3646 -0.105926513671875 +3647 -0.053955078125 +3648 0.048797607421875 +3649 0.157318115234375 +3650 0.212005615234375 +3651 0.218475341796875 +3652 0.23724365234375 +3653 0.30535888671875 +3654 0.38128662109375 +3655 0.404449462890625 +3656 0.3944091796875 +3657 0.3885498046875 +3658 0.362640380859375 +3659 0.27362060546875 +3660 0.11712646484375 +3661 -0.054901123046875 +3662 -0.19085693359375 +3663 -0.28570556640625 +3664 -0.339263916015625 +3665 -0.3775634765625 +3666 -0.445709228515625 +3667 -0.535064697265625 +3668 -0.629058837890625 +3669 -0.697601318359375 +3670 -0.70391845703125 +3671 -0.6424560546875 +3672 -0.491241455078125 +3673 -0.265716552734375 +3674 -0.023712158203125 +3675 0.201751708984375 +3676 0.375823974609375 +3677 0.485076904296875 +3678 0.56884765625 +3679 0.634765625 +3680 0.63763427734375 +3681 0.5660400390625 +3682 0.4720458984375 +3683 0.40692138671875 +3684 0.3778076171875 +3685 0.376953125 +3686 0.371978759765625 +3687 0.313140869140625 +3688 0.184417724609375 +3689 0.011199951171875 +3690 -0.171051025390625 +3691 -0.33740234375 +3692 -0.47198486328125 +3693 -0.560394287109375 +3694 -0.58056640625 +3695 -0.54754638671875 +3696 -0.508575439453125 +3697 -0.459503173828125 +3698 -0.394378662109375 +3699 -0.35260009765625 +3700 -0.31170654296875 +3701 -0.197418212890625 +3702 -0.007965087890625 +3703 0.207489013671875 +3704 0.409210205078125 +3705 0.57208251953125 +3706 0.66595458984375 +3707 0.65875244140625 +3708 0.56744384765625 +3709 0.431396484375 +3710 0.29443359375 +3711 0.182464599609375 +3712 0.06365966796875 +3713 -0.075958251953125 +3714 -0.189422607421875 +3715 -0.271942138671875 +3716 -0.342529296875 +3717 -0.364166259765625 +3718 -0.327239990234375 +3719 -0.2769775390625 +3720 -0.253692626953125 +3721 -0.24365234375 +3722 -0.1983642578125 +3723 -0.116241455078125 +3724 -0.036834716796875 +3725 0.034881591796875 +3726 0.09124755859375 +3727 0.10888671875 +3728 0.125518798828125 +3729 0.15771484375 +3730 0.17828369140625 +3731 0.17108154296875 +3732 0.129974365234375 +3733 0.082427978515625 +3734 0.027679443359375 +3735 -0.065643310546875 +3736 -0.15936279296875 +3737 -0.21307373046875 +3738 -0.234649658203125 +3739 -0.2001953125 +3740 -0.119171142578125 +3741 -0.024749755859375 +3742 0.085784912109375 +3743 0.178131103515625 +3744 0.215576171875 +3745 0.211456298828125 +3746 0.17523193359375 +3747 0.128753662109375 +3748 0.1019287109375 +3749 0.0743408203125 +3750 0.04327392578125 +3751 0.038177490234375 +3752 0.076263427734375 +3753 0.14105224609375 +3754 0.186431884765625 +3755 0.188812255859375 +3756 0.1390380859375 +3757 0.041778564453125 +3758 -0.079437255859375 +3759 -0.219390869140625 +3760 -0.367828369140625 +3761 -0.494873046875 +3762 -0.556243896484375 +3763 -0.508697509765625 +3764 -0.3756103515625 +3765 -0.218902587890625 +3766 -0.063751220703125 +3767 0.091552734375 +3768 0.23602294921875 +3769 0.342987060546875 +3770 0.39520263671875 +3771 0.389373779296875 +3772 0.324249267578125 +3773 0.224090576171875 +3774 0.124267578125 +3775 0.037078857421875 +3776 -0.010101318359375 +3777 -0.019439697265625 +3778 -0.022796630859375 +3779 -0.001556396484375 +3780 0.056304931640625 +3781 0.106719970703125 +3782 0.096893310546875 +3783 0.042694091796875 +3784 -0.018035888671875 +3785 -0.07586669921875 +3786 -0.11944580078125 +3787 -0.15972900390625 +3788 -0.202606201171875 +3789 -0.24859619140625 +3790 -0.30517578125 +3791 -0.36212158203125 +3792 -0.39141845703125 +3793 -0.35528564453125 +3794 -0.249969482421875 +3795 -0.092864990234375 +3796 0.08905029296875 +3797 0.2352294921875 +3798 0.318817138671875 +3799 0.358642578125 +3800 0.347747802734375 +3801 0.28564453125 +3802 0.223175048828125 +3803 0.196746826171875 +3804 0.179840087890625 +3805 0.155548095703125 +3806 0.151214599609375 +3807 0.156951904296875 +3808 0.13177490234375 +3809 0.100799560546875 +3810 0.087127685546875 +3811 0.05487060546875 +3812 -0.009002685546875 +3813 -0.10400390625 +3814 -0.229400634765625 +3815 -0.35552978515625 +3816 -0.441925048828125 +3817 -0.473846435546875 +3818 -0.464813232421875 +3819 -0.419097900390625 +3820 -0.334320068359375 +3821 -0.227935791015625 +3822 -0.12347412109375 +3823 -0.02764892578125 +3824 0.077667236328125 +3825 0.2132568359375 +3826 0.38885498046875 +3827 0.582794189453125 +3828 0.734039306640625 +3829 0.800140380859375 +3830 0.7783203125 +3831 0.6651611328125 +3832 0.45965576171875 +3833 0.199188232421875 +3834 -0.050689697265625 +3835 -0.23297119140625 +3836 -0.33013916015625 +3837 -0.368408203125 +3838 -0.378936767578125 +3839 -0.376983642578125 +3840 -0.37969970703125 +3841 -0.391510009765625 +3842 -0.385345458984375 +3843 -0.3419189453125 +3844 -0.28289794921875 +3845 -0.251617431640625 +3846 -0.266143798828125 +3847 -0.273345947265625 +3848 -0.216796875 +3849 -0.128265380859375 +3850 -0.068145751953125 +3851 -0.0430908203125 +3852 -0.024444580078125 +3853 0.020721435546875 +3854 0.124481201171875 +3855 0.25787353515625 +3856 0.379119873046875 +3857 0.47991943359375 +3858 0.5281982421875 +3859 0.511138916015625 +3860 0.456207275390625 +3861 0.407470703125 +3862 0.383758544921875 +3863 0.35687255859375 +3864 0.31182861328125 +3865 0.250885009765625 +3866 0.1654052734375 +3867 0.035247802734375 +3868 -0.142059326171875 +3869 -0.33563232421875 +3870 -0.5345458984375 +3871 -0.72186279296875 +3872 -0.836669921875 +3873 -0.8326416015625 +3874 -0.7296142578125 +3875 -0.582550048828125 +3876 -0.440093994140625 +3877 -0.324310302734375 +3878 -0.20147705078125 +3879 -0.044647216796875 +3880 0.103973388671875 +3881 0.202392578125 +3882 0.264495849609375 +3883 0.338897705078125 +3884 0.443817138671875 +3885 0.545074462890625 +3886 0.6173095703125 +3887 0.6524658203125 +3888 0.66339111328125 +3889 0.6561279296875 +3890 0.606781005859375 +3891 0.501190185546875 +3892 0.352783203125 +3893 0.176544189453125 +3894 -0.034820556640625 +3895 -0.258209228515625 +3896 -0.44244384765625 +3897 -0.5753173828125 +3898 -0.65203857421875 +3899 -0.641632080078125 +3900 -0.562164306640625 +3901 -0.458038330078125 +3902 -0.350555419921875 +3903 -0.260528564453125 +3904 -0.192108154296875 +3905 -0.141937255859375 +3906 -0.1021728515625 +3907 -0.062896728515625 +3908 -0.011932373046875 +3909 0.062835693359375 +3910 0.148712158203125 +3911 0.241729736328125 +3912 0.34912109375 +3913 0.457305908203125 +3914 0.54388427734375 +3915 0.5728759765625 +3916 0.506591796875 +3917 0.351226806640625 +3918 0.146514892578125 +3919 -0.05523681640625 +3920 -0.21624755859375 +3921 -0.334930419921875 +3922 -0.402984619140625 +3923 -0.4412841796875 +3924 -0.49578857421875 +3925 -0.5601806640625 +3926 -0.600738525390625 +3927 -0.584228515625 +3928 -0.47930908203125 +3929 -0.27935791015625 +3930 -0.0089111328125 +3931 0.268798828125 +3932 0.482818603515625 +3933 0.60369873046875 +3934 0.650421142578125 +3935 0.66400146484375 +3936 0.6414794921875 +3937 0.572540283203125 +3938 0.498138427734375 +3939 0.439453125 +3940 0.375518798828125 +3941 0.274505615234375 +3942 0.1087646484375 +3943 -0.099395751953125 +3944 -0.3182373046875 +3945 -0.5489501953125 +3946 -0.7738037109375 +3947 -0.86383056640625 +3948 -0.870391845703125 +3949 -0.86895751953125 +3950 -0.861053466796875 +3951 -0.765869140625 +3952 -0.5301513671875 +3953 -0.214691162109375 +3954 0.137359619140625 +3955 0.474822998046875 +3956 0.76239013671875 +3957 0.867462158203125 +3958 0.870361328125 +3959 0.86480712890625 +3960 0.831817626953125 +3961 0.677581787109375 +3962 0.495880126953125 +3963 0.30767822265625 +3964 0.116180419921875 +3965 -0.110748291015625 +3966 -0.381805419921875 +3967 -0.6572265625 +3968 -0.857421875 +3969 -0.870391845703125 +3970 -0.870391845703125 +3971 -0.86444091796875 +3972 -0.85723876953125 +3973 -0.790008544921875 +3974 -0.62847900390625 +3975 -0.3956298828125 +3976 -0.126708984375 +3977 0.150115966796875 +3978 0.424041748046875 +3979 0.670623779296875 +3980 0.854522705078125 +3981 0.866485595703125 +3982 0.86920166015625 +3983 0.8653564453125 +3984 0.857147216796875 +3985 0.766845703125 +3986 0.628509521484375 +3987 0.462127685546875 +3988 0.297210693359375 +3989 0.14862060546875 +3990 -0.00537109375 +3991 -0.15753173828125 +3992 -0.31304931640625 +3993 -0.48876953125 +3994 -0.6416015625 +3995 -0.751373291015625 +3996 -0.84619140625 +3997 -0.861297607421875 +3998 -0.863250732421875 +3999 -0.856597900390625 +4000 -0.7498779296875 +4001 -0.624542236328125 +4002 -0.47808837890625 +4003 -0.253387451171875 +4004 0.003692626953125 +4005 0.2257080078125 +4006 0.427154541015625 +4007 0.643218994140625 +4008 0.855926513671875 +4009 0.870361328125 +4010 0.870361328125 +4011 0.862762451171875 +4012 0.79669189453125 +4013 0.595794677734375 +4014 0.362152099609375 +4015 0.1270751953125 +4016 -0.086944580078125 +4017 -0.2784423828125 +4018 -0.484832763671875 +4019 -0.729583740234375 +4020 -0.86688232421875 +4021 -0.870391845703125 +4022 -0.86859130859375 +4023 -0.86279296875 +4024 -0.817962646484375 +4025 -0.6116943359375 +4026 -0.3128662109375 +4027 0.039398193359375 +4028 0.422821044921875 +4029 0.805145263671875 +4030 0.870361328125 +4031 0.870361328125 +4032 0.860015869140625 +4033 0.727935791015625 +4034 0.48114013671875 +4035 0.2059326171875 +4036 -0.06103515625 +4037 -0.29913330078125 +4038 -0.516204833984375 +4039 -0.7252197265625 +4040 -0.85980224609375 +4041 -0.870391845703125 +4042 -0.870391845703125 +4043 -0.858062744140625 +4044 -0.673004150390625 +4045 -0.42694091796875 +4046 -0.2100830078125 +4047 -0.0362548828125 +4048 0.10943603515625 +4049 0.23516845703125 +4050 0.373687744140625 +4051 0.517791748046875 +4052 0.602783203125 +4053 0.635711669921875 +4054 0.655181884765625 +4055 0.65948486328125 +4056 0.651275634765625 +4057 0.61846923828125 +4058 0.53753662109375 +4059 0.404144287109375 +4060 0.22186279296875 +4061 0.003997802734375 +4062 -0.22100830078125 +4063 -0.42449951171875 +4064 -0.579833984375 +4065 -0.641876220703125 +4066 -0.6177978515625 +4067 -0.575531005859375 +4068 -0.526336669921875 +4069 -0.42645263671875 +4070 -0.2581787109375 +4071 -0.068695068359375 +4072 0.09222412109375 +4073 0.232147216796875 +4074 0.3509521484375 +4075 0.410064697265625 +4076 0.372955322265625 +4077 0.2554931640625 +4078 0.10711669921875 +4079 -0.052886962890625 +4080 -0.186279296875 +4081 -0.23291015625 +4082 -0.209442138671875 +4083 -0.174163818359375 +4084 -0.126739501953125 +4085 -0.048126220703125 +4086 0.0426025390625 +4087 0.10748291015625 +4088 0.1409912109375 +4089 0.19708251953125 +4090 0.273651123046875 +4091 0.31768798828125 +4092 0.341094970703125 +4093 0.368011474609375 +4094 0.37249755859375 +4095 0.30072021484375 +4096 0.1517333984375 +4097 -0.01470947265625 +4098 -0.1883544921875 +4099 -0.372711181640625 +4100 -0.51397705078125 +4101 -0.57177734375 +4102 -0.53948974609375 +4103 -0.43511962890625 +4104 -0.2962646484375 +4105 -0.161102294921875 +4106 -0.0435791015625 +4107 0.060394287109375 +4108 0.13665771484375 +4109 0.170135498046875 +4110 0.16552734375 +4111 0.15728759765625 +4112 0.150787353515625 +4113 0.12200927734375 +4114 0.080108642578125 +4115 0.05126953125 +4116 0.062896728515625 +4117 0.09271240234375 +4118 0.092987060546875 +4119 0.07855224609375 +4120 0.06427001953125 +4121 0.0347900390625 +4122 -0.01171875 +4123 -0.056060791015625 +4124 -0.055511474609375 +4125 -0.010467529296875 +4126 0.02508544921875 +4127 0.025665283203125 +4128 0.017333984375 +4129 0.00189208984375 +4130 -0.03173828125 +4131 -0.071502685546875 +4132 -0.13543701171875 +4133 -0.219970703125 +4134 -0.300506591796875 +4135 -0.376312255859375 +4136 -0.416107177734375 +4137 -0.371124267578125 +4138 -0.242279052734375 +4139 -0.069732666015625 +4140 0.125640869140625 +4141 0.31268310546875 +4142 0.45501708984375 +4143 0.554779052734375 +4144 0.61065673828125 +4145 0.610931396484375 +4146 0.531463623046875 +4147 0.3883056640625 +4148 0.23468017578125 +4149 0.095245361328125 +4150 -0.00396728515625 +4151 -0.04852294921875 +4152 -0.055145263671875 +4153 -0.0758056640625 +4154 -0.138702392578125 +4155 -0.209197998046875 +4156 -0.289031982421875 +4157 -0.37884521484375 +4158 -0.456329345703125 +4159 -0.51641845703125 +4160 -0.519287109375 +4161 -0.458251953125 +4162 -0.384796142578125 +4163 -0.323699951171875 +4164 -0.269287109375 +4165 -0.1951904296875 +4166 -0.100006103515625 +4167 -0.01055908203125 +4168 0.1033935546875 +4169 0.24908447265625 +4170 0.373199462890625 +4171 0.45806884765625 +4172 0.511474609375 +4173 0.565399169921875 +4174 0.61138916015625 +4175 0.5897216796875 +4176 0.4906005859375 +4177 0.33148193359375 +4178 0.147796630859375 +4179 -0.01873779296875 +4180 -0.140289306640625 +4181 -0.191986083984375 +4182 -0.184295654296875 +4183 -0.161834716796875 +4184 -0.166595458984375 +4185 -0.19390869140625 +4186 -0.22442626953125 +4187 -0.279754638671875 +4188 -0.3389892578125 +4189 -0.3543701171875 +4190 -0.348175048828125 +4191 -0.32598876953125 +4192 -0.2581787109375 +4193 -0.139801025390625 +4194 0.014617919921875 +4195 0.144378662109375 +4196 0.221038818359375 +4197 0.27069091796875 +4198 0.294036865234375 +4199 0.311767578125 +4200 0.339141845703125 +4201 0.360260009765625 +4202 0.360504150390625 +4203 0.308380126953125 +4204 0.18170166015625 +4205 0.0047607421875 +4206 -0.17559814453125 +4207 -0.3143310546875 +4208 -0.36785888671875 +4209 -0.36248779296875 +4210 -0.343536376953125 +4211 -0.3018798828125 +4212 -0.231414794921875 +4213 -0.117645263671875 +4214 0.007049560546875 +4215 0.087982177734375 +4216 0.13946533203125 +4217 0.17425537109375 +4218 0.188201904296875 +4219 0.171234130859375 +4220 0.118438720703125 +4221 0.05706787109375 +4222 -0.010711669921875 +4223 -0.0914306640625 +4224 -0.162322998046875 +4225 -0.194549560546875 +4226 -0.1492919921875 +4227 -0.02166748046875 +4228 0.124053955078125 +4229 0.211151123046875 +4230 0.240447998046875 +4231 0.242218017578125 +4232 0.2257080078125 +4233 0.194366455078125 +4234 0.115509033203125 +4235 0.0128173828125 +4236 -0.053802490234375 +4237 -0.110626220703125 +4238 -0.199493408203125 +4239 -0.29437255859375 +4240 -0.33221435546875 +4241 -0.27972412109375 +4242 -0.185333251953125 +4243 -0.128204345703125 +4244 -0.115692138671875 +4245 -0.116455078125 +4246 -0.105926513671875 +4247 -0.053955078125 +4248 0.048797607421875 +4249 0.157318115234375 +4250 0.212005615234375 +4251 0.218475341796875 +4252 0.23724365234375 +4253 0.30535888671875 +4254 0.38128662109375 +4255 0.404449462890625 +4256 0.3944091796875 +4257 0.3885498046875 +4258 0.362640380859375 +4259 0.27362060546875 +4260 0.11712646484375 +4261 -0.054901123046875 +4262 -0.19085693359375 +4263 -0.28570556640625 +4264 -0.339263916015625 +4265 -0.3775634765625 +4266 -0.445709228515625 +4267 -0.535064697265625 +4268 -0.629058837890625 +4269 -0.697601318359375 +4270 -0.70391845703125 +4271 -0.6424560546875 +4272 -0.491241455078125 +4273 -0.265716552734375 +4274 -0.023712158203125 +4275 0.201751708984375 +4276 0.375823974609375 +4277 0.485076904296875 +4278 0.56884765625 +4279 0.634765625 +4280 0.63763427734375 +4281 0.5660400390625 +4282 0.4720458984375 +4283 0.40692138671875 +4284 0.3778076171875 +4285 0.376953125 +4286 0.371978759765625 +4287 0.313140869140625 +4288 0.184417724609375 +4289 0.011199951171875 +4290 -0.171051025390625 +4291 -0.33740234375 +4292 -0.47198486328125 +4293 -0.560394287109375 +4294 -0.58056640625 +4295 -0.54754638671875 +4296 -0.508575439453125 +4297 -0.459503173828125 +4298 -0.394378662109375 +4299 -0.35260009765625 +4300 -0.31170654296875 +4301 -0.197418212890625 +4302 -0.007965087890625 +4303 0.207489013671875 +4304 0.409210205078125 +4305 0.57208251953125 +4306 0.66595458984375 +4307 0.65875244140625 +4308 0.56744384765625 +4309 0.431396484375 +4310 0.29443359375 +4311 0.182464599609375 +4312 0.06365966796875 +4313 -0.075958251953125 +4314 -0.189422607421875 +4315 -0.271942138671875 +4316 -0.342529296875 +4317 -0.364166259765625 +4318 -0.327239990234375 +4319 -0.2769775390625 +4320 -0.253692626953125 +4321 -0.24365234375 +4322 -0.1983642578125 +4323 -0.116241455078125 +4324 -0.036834716796875 +4325 0.034881591796875 +4326 0.09124755859375 +4327 0.10888671875 +4328 0.125518798828125 +4329 0.15771484375 +4330 0.17828369140625 +4331 0.17108154296875 +4332 0.129974365234375 +4333 0.082427978515625 +4334 0.027679443359375 +4335 -0.065643310546875 +4336 -0.15936279296875 +4337 -0.21307373046875 +4338 -0.234649658203125 +4339 -0.2001953125 +4340 -0.119171142578125 +4341 -0.024749755859375 +4342 0.085784912109375 +4343 0.178131103515625 +4344 0.215576171875 +4345 0.211456298828125 +4346 0.17523193359375 +4347 0.128753662109375 +4348 0.1019287109375 +4349 0.0743408203125 +4350 0.04327392578125 +4351 0.038177490234375 +4352 0.076263427734375 +4353 0.14105224609375 +4354 0.186431884765625 +4355 0.188812255859375 +4356 0.1390380859375 +4357 0.041778564453125 +4358 -0.079437255859375 +4359 -0.219390869140625 +4360 -0.367828369140625 +4361 -0.494873046875 +4362 -0.556243896484375 +4363 -0.508697509765625 +4364 -0.3756103515625 +4365 -0.218902587890625 +4366 -0.063751220703125 +4367 0.091552734375 +4368 0.23602294921875 +4369 0.342987060546875 +4370 0.39520263671875 +4371 0.389373779296875 +4372 0.324249267578125 +4373 0.224090576171875 +4374 0.124267578125 +4375 0.037078857421875 +4376 -0.010101318359375 +4377 -0.019439697265625 +4378 -0.022796630859375 +4379 -0.001556396484375 +4380 0.056304931640625 +4381 0.106719970703125 +4382 0.096893310546875 +4383 0.042694091796875 +4384 -0.018035888671875 +4385 -0.07586669921875 +4386 -0.11944580078125 +4387 -0.15972900390625 +4388 -0.202606201171875 +4389 -0.24859619140625 +4390 -0.30517578125 +4391 -0.36212158203125 +4392 -0.39141845703125 +4393 -0.35528564453125 +4394 -0.249969482421875 +4395 -0.092864990234375 +4396 0.08905029296875 +4397 0.2352294921875 +4398 0.318817138671875 +4399 0.358642578125 +4400 0.347747802734375 +4401 0.28564453125 +4402 0.223175048828125 +4403 0.196746826171875 +4404 0.179840087890625 +4405 0.155548095703125 +4406 0.151214599609375 +4407 0.156951904296875 +4408 0.13177490234375 +4409 0.100799560546875 +4410 0.087127685546875 +4411 0.05487060546875 +4412 -0.009002685546875 +4413 -0.10400390625 +4414 -0.229400634765625 +4415 -0.35552978515625 +4416 -0.441925048828125 +4417 -0.473846435546875 +4418 -0.464813232421875 +4419 -0.419097900390625 +4420 -0.334320068359375 +4421 -0.227935791015625 +4422 -0.12347412109375 +4423 -0.02764892578125 +4424 0.077667236328125 +4425 0.2132568359375 +4426 0.38885498046875 +4427 0.582794189453125 +4428 0.734039306640625 +4429 0.800140380859375 +4430 0.7783203125 +4431 0.6651611328125 +4432 0.45965576171875 +4433 0.199188232421875 +4434 -0.050689697265625 +4435 -0.23297119140625 +4436 -0.33013916015625 +4437 -0.368408203125 +4438 -0.378936767578125 +4439 -0.376983642578125 +4440 -0.37969970703125 +4441 -0.391510009765625 +4442 -0.385345458984375 +4443 -0.3419189453125 +4444 -0.28289794921875 +4445 -0.251617431640625 +4446 -0.266143798828125 +4447 -0.273345947265625 +4448 -0.216796875 +4449 -0.128265380859375 +4450 -0.068145751953125 +4451 -0.0430908203125 +4452 -0.024444580078125 +4453 0.020721435546875 +4454 0.124481201171875 +4455 0.25787353515625 +4456 0.379119873046875 +4457 0.47991943359375 +4458 0.5281982421875 +4459 0.511138916015625 +4460 0.456207275390625 +4461 0.407470703125 +4462 0.383758544921875 +4463 0.35687255859375 +4464 0.31182861328125 +4465 0.250885009765625 +4466 0.1654052734375 +4467 0.035247802734375 +4468 -0.142059326171875 +4469 -0.33563232421875 +4470 -0.5345458984375 +4471 -0.72186279296875 +4472 -0.836669921875 +4473 -0.8326416015625 +4474 -0.7296142578125 +4475 -0.582550048828125 +4476 -0.440093994140625 +4477 -0.324310302734375 +4478 -0.20147705078125 +4479 -0.044647216796875 +4480 0.103973388671875 +4481 0.202392578125 +4482 0.264495849609375 +4483 0.338897705078125 +4484 0.443817138671875 +4485 0.545074462890625 +4486 0.6173095703125 +4487 0.6524658203125 +4488 0.66339111328125 +4489 0.6561279296875 +4490 0.606781005859375 +4491 0.501190185546875 +4492 0.352783203125 +4493 0.176544189453125 +4494 -0.034820556640625 +4495 -0.258209228515625 +4496 -0.44244384765625 +4497 -0.5753173828125 +4498 -0.65203857421875 +4499 -0.641632080078125 +4500 -0.562164306640625 +4501 -0.458038330078125 +4502 -0.350555419921875 +4503 -0.260528564453125 +4504 -0.192108154296875 +4505 -0.141937255859375 +4506 -0.1021728515625 +4507 -0.062896728515625 +4508 -0.011932373046875 +4509 0.062835693359375 +4510 0.148712158203125 +4511 0.241729736328125 +4512 0.34912109375 +4513 0.457305908203125 +4514 0.54388427734375 +4515 0.5728759765625 +4516 0.506591796875 +4517 0.351226806640625 +4518 0.146514892578125 +4519 -0.05523681640625 +4520 -0.21624755859375 +4521 -0.334930419921875 +4522 -0.402984619140625 +4523 -0.4412841796875 +4524 -0.49578857421875 +4525 -0.5601806640625 +4526 -0.600738525390625 +4527 -0.584228515625 +4528 -0.47930908203125 +4529 -0.27935791015625 +4530 -0.0089111328125 +4531 0.268798828125 +4532 0.482818603515625 +4533 0.60369873046875 +4534 0.650421142578125 +4535 0.66400146484375 +4536 0.6414794921875 +4537 0.572540283203125 +4538 0.498138427734375 +4539 0.439453125 +4540 0.375518798828125 +4541 0.274505615234375 +4542 0.1087646484375 +4543 -0.099395751953125 +4544 -0.3182373046875 +4545 -0.5489501953125 +4546 -0.7738037109375 +4547 -0.86383056640625 +4548 -0.870391845703125 +4549 -0.86895751953125 +4550 -0.861053466796875 +4551 -0.765869140625 +4552 -0.5301513671875 +4553 -0.214691162109375 +4554 0.137359619140625 +4555 0.474822998046875 +4556 0.76239013671875 +4557 0.867462158203125 +4558 0.870361328125 +4559 0.86480712890625 +4560 0.831817626953125 +4561 0.677581787109375 +4562 0.495880126953125 +4563 0.30767822265625 +4564 0.116180419921875 +4565 -0.110748291015625 +4566 -0.381805419921875 +4567 -0.6572265625 +4568 -0.857421875 +4569 -0.870391845703125 +4570 -0.870391845703125 +4571 -0.86444091796875 +4572 -0.85723876953125 +4573 -0.790008544921875 +4574 -0.62847900390625 +4575 -0.3956298828125 +4576 -0.126708984375 +4577 0.150115966796875 +4578 0.424041748046875 +4579 0.670623779296875 +4580 0.854522705078125 +4581 0.866485595703125 +4582 0.86920166015625 +4583 0.8653564453125 +4584 0.857147216796875 +4585 0.766845703125 +4586 0.628509521484375 +4587 0.462127685546875 +4588 0.297210693359375 +4589 0.14862060546875 +4590 -0.00537109375 +4591 -0.15753173828125 +4592 -0.31304931640625 +4593 -0.48876953125 +4594 -0.6416015625 +4595 -0.751373291015625 +4596 -0.84619140625 +4597 -0.861297607421875 +4598 -0.863250732421875 +4599 -0.856597900390625 +4600 -0.7498779296875 +4601 -0.624542236328125 +4602 -0.47808837890625 +4603 -0.253387451171875 +4604 0.003692626953125 +4605 0.2257080078125 +4606 0.427154541015625 +4607 0.643218994140625 +4608 0.855926513671875 +4609 0.870361328125 +4610 0.870361328125 +4611 0.862762451171875 +4612 0.79669189453125 +4613 0.595794677734375 +4614 0.362152099609375 +4615 0.1270751953125 +4616 -0.086944580078125 +4617 -0.2784423828125 +4618 -0.484832763671875 +4619 -0.729583740234375 +4620 -0.86688232421875 +4621 -0.870391845703125 +4622 -0.86859130859375 +4623 -0.86279296875 +4624 -0.817962646484375 +4625 -0.6116943359375 +4626 -0.3128662109375 +4627 0.039398193359375 +4628 0.422821044921875 +4629 0.805145263671875 +4630 0.870361328125 +4631 0.870361328125 +4632 0.860015869140625 +4633 0.727935791015625 +4634 0.48114013671875 +4635 0.2059326171875 +4636 -0.06103515625 +4637 -0.29913330078125 +4638 -0.516204833984375 +4639 -0.7252197265625 +4640 -0.85980224609375 +4641 -0.870391845703125 +4642 -0.870391845703125 +4643 -0.858062744140625 +4644 -0.673004150390625 +4645 -0.42694091796875 +4646 -0.2100830078125 +4647 -0.0362548828125 +4648 0.10943603515625 +4649 0.23516845703125 +4650 0.373687744140625 +4651 0.517791748046875 +4652 0.602783203125 +4653 0.635711669921875 +4654 0.655181884765625 +4655 0.65948486328125 +4656 0.651275634765625 +4657 0.61846923828125 +4658 0.53753662109375 +4659 0.404144287109375 +4660 0.22186279296875 +4661 0.003997802734375 +4662 -0.22100830078125 +4663 -0.42449951171875 +4664 -0.579833984375 +4665 -0.641876220703125 +4666 -0.6177978515625 +4667 -0.575531005859375 +4668 -0.526336669921875 +4669 -0.42645263671875 +4670 -0.2581787109375 +4671 -0.068695068359375 +4672 0.09222412109375 +4673 0.232147216796875 +4674 0.3509521484375 +4675 0.410064697265625 +4676 0.372955322265625 +4677 0.2554931640625 +4678 0.10711669921875 +4679 -0.052886962890625 +4680 -0.186279296875 +4681 -0.23291015625 +4682 -0.209442138671875 +4683 -0.174163818359375 +4684 -0.126739501953125 +4685 -0.048126220703125 +4686 0.0426025390625 +4687 0.10748291015625 +4688 0.1409912109375 +4689 0.19708251953125 +4690 0.273651123046875 +4691 0.31768798828125 +4692 0.341094970703125 +4693 0.368011474609375 +4694 0.37249755859375 +4695 0.30072021484375 +4696 0.1517333984375 +4697 -0.01470947265625 +4698 -0.1883544921875 +4699 -0.372711181640625 +4700 -0.51397705078125 +4701 -0.57177734375 +4702 -0.53948974609375 +4703 -0.43511962890625 +4704 -0.2962646484375 +4705 -0.161102294921875 +4706 -0.0435791015625 +4707 0.060394287109375 +4708 0.13665771484375 +4709 0.170135498046875 +4710 0.16552734375 +4711 0.15728759765625 +4712 0.150787353515625 +4713 0.12200927734375 +4714 0.080108642578125 +4715 0.05126953125 +4716 0.062896728515625 +4717 0.09271240234375 +4718 0.092987060546875 +4719 0.07855224609375 +4720 0.06427001953125 +4721 0.0347900390625 +4722 -0.01171875 +4723 -0.056060791015625 +4724 -0.055511474609375 +4725 -0.010467529296875 +4726 0.02508544921875 +4727 0.025665283203125 +4728 0.017333984375 +4729 0.00189208984375 +4730 -0.03173828125 +4731 -0.071502685546875 +4732 -0.13543701171875 +4733 -0.219970703125 +4734 -0.300506591796875 +4735 -0.376312255859375 +4736 -0.416107177734375 +4737 -0.371124267578125 +4738 -0.242279052734375 +4739 -0.069732666015625 +4740 0.125640869140625 +4741 0.31268310546875 +4742 0.45501708984375 +4743 0.554779052734375 +4744 0.61065673828125 +4745 0.610931396484375 +4746 0.531463623046875 +4747 0.3883056640625 +4748 0.23468017578125 +4749 0.095245361328125 +4750 -0.00396728515625 +4751 -0.04852294921875 +4752 -0.055145263671875 +4753 -0.0758056640625 +4754 -0.138702392578125 +4755 -0.209197998046875 +4756 -0.289031982421875 +4757 -0.37884521484375 +4758 -0.456329345703125 +4759 -0.51641845703125 +4760 -0.519287109375 +4761 -0.458251953125 +4762 -0.384796142578125 +4763 -0.323699951171875 +4764 -0.269287109375 +4765 -0.1951904296875 +4766 -0.100006103515625 +4767 -0.01055908203125 +4768 0.1033935546875 +4769 0.24908447265625 +4770 0.373199462890625 +4771 0.45806884765625 +4772 0.511474609375 +4773 0.565399169921875 +4774 0.61138916015625 +4775 0.5897216796875 +4776 0.4906005859375 +4777 0.33148193359375 +4778 0.147796630859375 +4779 -0.01873779296875 +4780 -0.140289306640625 +4781 -0.191986083984375 +4782 -0.184295654296875 +4783 -0.161834716796875 +4784 -0.166595458984375 +4785 -0.19390869140625 +4786 -0.22442626953125 +4787 -0.279754638671875 +4788 -0.3389892578125 +4789 -0.3543701171875 +4790 -0.348175048828125 +4791 -0.32598876953125 +4792 -0.2581787109375 +4793 -0.139801025390625 +4794 0.014617919921875 +4795 0.144378662109375 +4796 0.221038818359375 +4797 0.27069091796875 +4798 0.294036865234375 +4799 0.311767578125 +4800 0.339141845703125 +4801 0.360260009765625 +4802 0.360504150390625 +4803 0.308380126953125 +4804 0.18170166015625 +4805 0.0047607421875 +4806 -0.17559814453125 +4807 -0.3143310546875 +4808 -0.36785888671875 +4809 -0.36248779296875 +4810 -0.343536376953125 +4811 -0.3018798828125 +4812 -0.231414794921875 +4813 -0.117645263671875 +4814 0.007049560546875 +4815 0.087982177734375 +4816 0.13946533203125 +4817 0.17425537109375 +4818 0.188201904296875 +4819 0.171234130859375 +4820 0.118438720703125 +4821 0.05706787109375 +4822 -0.010711669921875 +4823 -0.0914306640625 +4824 -0.162322998046875 +4825 -0.194549560546875 +4826 -0.1492919921875 +4827 -0.02166748046875 +4828 0.124053955078125 +4829 0.211151123046875 +4830 0.240447998046875 +4831 0.242218017578125 +4832 0.2257080078125 +4833 0.194366455078125 +4834 0.115509033203125 +4835 0.0128173828125 +4836 -0.053802490234375 +4837 -0.110626220703125 +4838 -0.199493408203125 +4839 -0.29437255859375 +4840 -0.33221435546875 +4841 -0.27972412109375 +4842 -0.185333251953125 +4843 -0.128204345703125 +4844 -0.115692138671875 +4845 -0.116455078125 +4846 -0.105926513671875 +4847 -0.053955078125 +4848 0.048797607421875 +4849 0.157318115234375 +4850 0.212005615234375 +4851 0.218475341796875 +4852 0.23724365234375 +4853 0.30535888671875 +4854 0.38128662109375 +4855 0.404449462890625 +4856 0.3944091796875 +4857 0.3885498046875 +4858 0.362640380859375 +4859 0.27362060546875 +4860 0.11712646484375 +4861 -0.054901123046875 +4862 -0.19085693359375 +4863 -0.28570556640625 +4864 -0.339263916015625 +4865 -0.3775634765625 +4866 -0.445709228515625 +4867 -0.535064697265625 +4868 -0.629058837890625 +4869 -0.697601318359375 +4870 -0.70391845703125 +4871 -0.6424560546875 +4872 -0.491241455078125 +4873 -0.265716552734375 +4874 -0.023712158203125 +4875 0.201751708984375 +4876 0.375823974609375 +4877 0.485076904296875 +4878 0.56884765625 +4879 0.634765625 +4880 0.63763427734375 +4881 0.5660400390625 +4882 0.4720458984375 +4883 0.40692138671875 +4884 0.3778076171875 +4885 0.376953125 +4886 0.371978759765625 +4887 0.313140869140625 +4888 0.184417724609375 +4889 0.011199951171875 +4890 -0.171051025390625 +4891 -0.33740234375 +4892 -0.47198486328125 +4893 -0.560394287109375 +4894 -0.58056640625 +4895 -0.54754638671875 +4896 -0.508575439453125 +4897 -0.459503173828125 +4898 -0.394378662109375 +4899 -0.35260009765625 +4900 -0.31170654296875 +4901 -0.197418212890625 +4902 -0.007965087890625 +4903 0.207489013671875 +4904 0.409210205078125 +4905 0.57208251953125 +4906 0.66595458984375 +4907 0.65875244140625 +4908 0.56744384765625 +4909 0.431396484375 +4910 0.29443359375 +4911 0.182464599609375 +4912 0.06365966796875 +4913 -0.075958251953125 +4914 -0.189422607421875 +4915 -0.271942138671875 +4916 -0.342529296875 +4917 -0.364166259765625 +4918 -0.327239990234375 +4919 -0.2769775390625 +4920 -0.253692626953125 +4921 -0.24365234375 +4922 -0.1983642578125 +4923 -0.116241455078125 +4924 -0.036834716796875 +4925 0.034881591796875 +4926 0.09124755859375 +4927 0.10888671875 +4928 0.125518798828125 +4929 0.15771484375 +4930 0.17828369140625 +4931 0.17108154296875 +4932 0.129974365234375 +4933 0.082427978515625 +4934 0.027679443359375 +4935 -0.065643310546875 +4936 -0.15936279296875 +4937 -0.21307373046875 +4938 -0.234649658203125 +4939 -0.2001953125 +4940 -0.119171142578125 +4941 -0.024749755859375 +4942 0.085784912109375 +4943 0.178131103515625 +4944 0.215576171875 +4945 0.211456298828125 +4946 0.17523193359375 +4947 0.128753662109375 +4948 0.1019287109375 +4949 0.0743408203125 +4950 0.04327392578125 +4951 0.038177490234375 +4952 0.076263427734375 +4953 0.14105224609375 +4954 0.186431884765625 +4955 0.188812255859375 +4956 0.1390380859375 +4957 0.041778564453125 +4958 -0.079437255859375 +4959 -0.219390869140625 +4960 -0.367828369140625 +4961 -0.494873046875 +4962 -0.556243896484375 +4963 -0.508697509765625 +4964 -0.3756103515625 +4965 -0.218902587890625 +4966 -0.063751220703125 +4967 0.091552734375 +4968 0.23602294921875 +4969 0.342987060546875 +4970 0.39520263671875 +4971 0.389373779296875 +4972 0.324249267578125 +4973 0.224090576171875 +4974 0.124267578125 +4975 0.037078857421875 +4976 -0.010101318359375 +4977 -0.019439697265625 +4978 -0.022796630859375 +4979 -0.001556396484375 +4980 0.056304931640625 +4981 0.106719970703125 +4982 0.096893310546875 +4983 0.042694091796875 +4984 -0.018035888671875 +4985 -0.07586669921875 +4986 -0.11944580078125 +4987 -0.15972900390625 +4988 -0.202606201171875 +4989 -0.24859619140625 +4990 -0.30517578125 +4991 -0.36212158203125 +4992 -0.39141845703125 +4993 -0.35528564453125 +4994 -0.249969482421875 +4995 -0.092864990234375 +4996 0.08905029296875 +4997 0.2352294921875 +4998 0.318817138671875 +4999 0.358642578125 +5000 0.347747802734375 +5001 0.28564453125 +5002 0.223175048828125 +5003 0.196746826171875 +5004 0.179840087890625 +5005 0.155548095703125 +5006 0.151214599609375 +5007 0.156951904296875 +5008 0.13177490234375 +5009 0.100799560546875 +5010 0.087127685546875 +5011 0.05487060546875 +5012 -0.009002685546875 +5013 -0.10400390625 +5014 -0.229400634765625 +5015 -0.35552978515625 +5016 -0.441925048828125 +5017 -0.473846435546875 +5018 -0.464813232421875 +5019 -0.419097900390625 +5020 -0.334320068359375 +5021 -0.227935791015625 +5022 -0.12347412109375 +5023 -0.02764892578125 +5024 0.077667236328125 +5025 0.2132568359375 +5026 0.38885498046875 +5027 0.582794189453125 +5028 0.734039306640625 +5029 0.800140380859375 +5030 0.7783203125 +5031 0.6651611328125 +5032 0.45965576171875 +5033 0.199188232421875 +5034 -0.050689697265625 +5035 -0.23297119140625 +5036 -0.33013916015625 +5037 -0.368408203125 +5038 -0.378936767578125 +5039 -0.376983642578125 +5040 -0.37969970703125 +5041 -0.391510009765625 +5042 -0.385345458984375 +5043 -0.3419189453125 +5044 -0.28289794921875 +5045 -0.251617431640625 +5046 -0.266143798828125 +5047 -0.273345947265625 +5048 -0.216796875 +5049 -0.128265380859375 +5050 -0.068145751953125 +5051 -0.0430908203125 +5052 -0.024444580078125 +5053 0.020721435546875 +5054 0.124481201171875 +5055 0.25787353515625 +5056 0.379119873046875 +5057 0.47991943359375 +5058 0.5281982421875 +5059 0.511138916015625 +5060 0.456207275390625 +5061 0.407470703125 +5062 0.383758544921875 +5063 0.35687255859375 +5064 0.31182861328125 +5065 0.250885009765625 +5066 0.1654052734375 +5067 0.035247802734375 +5068 -0.142059326171875 +5069 -0.33563232421875 +5070 -0.5345458984375 +5071 -0.72186279296875 +5072 -0.836669921875 +5073 -0.8326416015625 +5074 -0.7296142578125 +5075 -0.582550048828125 +5076 -0.440093994140625 +5077 -0.324310302734375 +5078 -0.20147705078125 +5079 -0.044647216796875 +5080 0.103973388671875 +5081 0.202392578125 +5082 0.264495849609375 +5083 0.338897705078125 +5084 0.443817138671875 +5085 0.545074462890625 +5086 0.6173095703125 +5087 0.6524658203125 +5088 0.66339111328125 +5089 0.6561279296875 +5090 0.606781005859375 +5091 0.501190185546875 +5092 0.352783203125 +5093 0.176544189453125 +5094 -0.034820556640625 +5095 -0.258209228515625 +5096 -0.44244384765625 +5097 -0.5753173828125 +5098 -0.65203857421875 +5099 -0.641632080078125 +5100 -0.562164306640625 +5101 -0.458038330078125 +5102 -0.350555419921875 +5103 -0.260528564453125 +5104 -0.192108154296875 +5105 -0.141937255859375 +5106 -0.1021728515625 +5107 -0.062896728515625 +5108 -0.011932373046875 +5109 0.062835693359375 +5110 0.148712158203125 +5111 0.241729736328125 +5112 0.34912109375 +5113 0.457305908203125 +5114 0.54388427734375 +5115 0.5728759765625 +5116 0.506591796875 +5117 0.351226806640625 +5118 0.146514892578125 +5119 -0.05523681640625 +5120 -0.21624755859375 +5121 -0.334930419921875 +5122 -0.402984619140625 +5123 -0.4412841796875 +5124 -0.49578857421875 +5125 -0.5601806640625 +5126 -0.600738525390625 +5127 -0.584228515625 +5128 -0.47930908203125 +5129 -0.27935791015625 +5130 -0.0089111328125 +5131 0.268798828125 +5132 0.482818603515625 +5133 0.60369873046875 +5134 0.650421142578125 +5135 0.66400146484375 +5136 0.6414794921875 +5137 0.572540283203125 +5138 0.498138427734375 +5139 0.439453125 +5140 0.375518798828125 +5141 0.274505615234375 +5142 0.1087646484375 +5143 -0.099395751953125 +5144 -0.3182373046875 +5145 -0.5489501953125 +5146 -0.7738037109375 +5147 -0.86383056640625 +5148 -0.870391845703125 +5149 -0.86895751953125 +5150 -0.861053466796875 +5151 -0.765869140625 +5152 -0.5301513671875 +5153 -0.214691162109375 +5154 0.137359619140625 +5155 0.474822998046875 +5156 0.76239013671875 +5157 0.867462158203125 +5158 0.870361328125 +5159 0.86480712890625 +5160 0.831817626953125 +5161 0.677581787109375 +5162 0.495880126953125 +5163 0.30767822265625 +5164 0.116180419921875 +5165 -0.110748291015625 +5166 -0.381805419921875 +5167 -0.6572265625 +5168 -0.857421875 +5169 -0.870391845703125 +5170 -0.870391845703125 +5171 -0.86444091796875 +5172 -0.85723876953125 +5173 -0.790008544921875 +5174 -0.62847900390625 +5175 -0.3956298828125 +5176 -0.126708984375 +5177 0.150115966796875 +5178 0.424041748046875 +5179 0.670623779296875 +5180 0.854522705078125 +5181 0.866485595703125 +5182 0.86920166015625 +5183 0.8653564453125 +5184 0.857147216796875 +5185 0.766845703125 +5186 0.628509521484375 +5187 0.462127685546875 +5188 0.297210693359375 +5189 0.14862060546875 +5190 -0.00537109375 +5191 -0.15753173828125 +5192 -0.31304931640625 +5193 -0.48876953125 +5194 -0.6416015625 +5195 -0.751373291015625 +5196 -0.84619140625 +5197 -0.861297607421875 +5198 -0.863250732421875 +5199 -0.856597900390625 +5200 -0.7498779296875 +5201 -0.624542236328125 +5202 -0.47808837890625 +5203 -0.253387451171875 +5204 0.003692626953125 +5205 0.2257080078125 +5206 0.427154541015625 +5207 0.643218994140625 +5208 0.855926513671875 +5209 0.870361328125 +5210 0.870361328125 +5211 0.862762451171875 +5212 0.79669189453125 +5213 0.595794677734375 +5214 0.362152099609375 +5215 0.1270751953125 +5216 -0.086944580078125 +5217 -0.2784423828125 +5218 -0.484832763671875 +5219 -0.729583740234375 +5220 -0.86688232421875 +5221 -0.870391845703125 +5222 -0.86859130859375 +5223 -0.86279296875 +5224 -0.817962646484375 +5225 -0.6116943359375 +5226 -0.3128662109375 +5227 0.039398193359375 +5228 0.422821044921875 +5229 0.805145263671875 +5230 0.870361328125 +5231 0.870361328125 +5232 0.860015869140625 +5233 0.727935791015625 +5234 0.48114013671875 +5235 0.2059326171875 +5236 -0.06103515625 +5237 -0.29913330078125 +5238 -0.516204833984375 +5239 -0.7252197265625 +5240 -0.85980224609375 +5241 -0.870391845703125 +5242 -0.870391845703125 +5243 -0.858062744140625 +5244 -0.673004150390625 +5245 -0.42694091796875 +5246 -0.2100830078125 +5247 -0.0362548828125 +5248 0.10943603515625 +5249 0.23516845703125 +5250 0.373687744140625 +5251 0.517791748046875 +5252 0.602783203125 +5253 0.635711669921875 +5254 0.655181884765625 +5255 0.65948486328125 +5256 0.651275634765625 +5257 0.61846923828125 +5258 0.53753662109375 +5259 0.404144287109375 +5260 0.22186279296875 +5261 0.003997802734375 +5262 -0.22100830078125 +5263 -0.42449951171875 +5264 -0.579833984375 +5265 -0.641876220703125 +5266 -0.6177978515625 +5267 -0.575531005859375 +5268 -0.526336669921875 +5269 -0.42645263671875 +5270 -0.2581787109375 +5271 -0.068695068359375 +5272 0.09222412109375 +5273 0.232147216796875 +5274 0.3509521484375 +5275 0.410064697265625 +5276 0.372955322265625 +5277 0.2554931640625 +5278 0.10711669921875 +5279 -0.052886962890625 +5280 -0.186279296875 +5281 -0.23291015625 +5282 -0.209442138671875 +5283 -0.174163818359375 +5284 -0.126739501953125 +5285 -0.048126220703125 +5286 0.0426025390625 +5287 0.10748291015625 +5288 0.1409912109375 +5289 0.19708251953125 +5290 0.273651123046875 +5291 0.31768798828125 +5292 0.341094970703125 +5293 0.368011474609375 +5294 0.37249755859375 +5295 0.30072021484375 +5296 0.1517333984375 +5297 -0.01470947265625 +5298 -0.1883544921875 +5299 -0.372711181640625 +5300 -0.51397705078125 +5301 -0.57177734375 +5302 -0.53948974609375 +5303 -0.43511962890625 +5304 -0.2962646484375 +5305 -0.161102294921875 +5306 -0.0435791015625 +5307 0.060394287109375 +5308 0.13665771484375 +5309 0.170135498046875 +5310 0.16552734375 +5311 0.15728759765625 +5312 0.150787353515625 +5313 0.12200927734375 +5314 0.080108642578125 +5315 0.05126953125 +5316 0.062896728515625 +5317 0.09271240234375 +5318 0.092987060546875 +5319 0.07855224609375 +5320 0.06427001953125 +5321 0.0347900390625 +5322 -0.01171875 +5323 -0.056060791015625 +5324 -0.055511474609375 +5325 -0.010467529296875 +5326 0.02508544921875 +5327 0.025665283203125 +5328 0.017333984375 +5329 0.00189208984375 +5330 -0.03173828125 +5331 -0.071502685546875 +5332 -0.13543701171875 +5333 -0.219970703125 +5334 -0.300506591796875 +5335 -0.376312255859375 +5336 -0.416107177734375 +5337 -0.371124267578125 +5338 -0.242279052734375 +5339 -0.069732666015625 +5340 0.125640869140625 +5341 0.31268310546875 +5342 0.45501708984375 +5343 0.554779052734375 +5344 0.61065673828125 +5345 0.610931396484375 +5346 0.531463623046875 +5347 0.3883056640625 +5348 0.23468017578125 +5349 0.095245361328125 +5350 -0.00396728515625 +5351 -0.04852294921875 +5352 -0.055145263671875 +5353 -0.0758056640625 +5354 -0.138702392578125 +5355 -0.209197998046875 +5356 -0.289031982421875 +5357 -0.37884521484375 +5358 -0.456329345703125 +5359 -0.51641845703125 +5360 -0.519287109375 +5361 -0.458251953125 +5362 -0.384796142578125 +5363 -0.323699951171875 +5364 -0.269287109375 +5365 -0.1951904296875 +5366 -0.100006103515625 +5367 -0.01055908203125 +5368 0.1033935546875 +5369 0.24908447265625 +5370 0.373199462890625 +5371 0.45806884765625 +5372 0.511474609375 +5373 0.565399169921875 +5374 0.61138916015625 +5375 0.5897216796875 +5376 0.4906005859375 +5377 0.33148193359375 +5378 0.147796630859375 +5379 -0.01873779296875 +5380 -0.140289306640625 +5381 -0.191986083984375 +5382 -0.184295654296875 +5383 -0.161834716796875 +5384 -0.166595458984375 +5385 -0.19390869140625 +5386 -0.22442626953125 +5387 -0.279754638671875 +5388 -0.3389892578125 +5389 -0.3543701171875 +5390 -0.348175048828125 +5391 -0.32598876953125 +5392 -0.2581787109375 +5393 -0.139801025390625 +5394 0.014617919921875 +5395 0.144378662109375 +5396 0.221038818359375 +5397 0.27069091796875 +5398 0.294036865234375 +5399 0.311767578125 +5400 0.339141845703125 +5401 0.360260009765625 +5402 0.360504150390625 +5403 0.308380126953125 +5404 0.18170166015625 +5405 0.0047607421875 +5406 -0.17559814453125 +5407 -0.3143310546875 +5408 -0.36785888671875 +5409 -0.36248779296875 +5410 -0.343536376953125 +5411 -0.3018798828125 +5412 -0.231414794921875 +5413 -0.117645263671875 +5414 0.007049560546875 +5415 0.087982177734375 +5416 0.13946533203125 +5417 0.17425537109375 +5418 0.188201904296875 +5419 0.171234130859375 +5420 0.118438720703125 +5421 0.05706787109375 +5422 -0.010711669921875 +5423 -0.0914306640625 +5424 -0.162322998046875 +5425 -0.194549560546875 +5426 -0.1492919921875 +5427 -0.02166748046875 +5428 0.124053955078125 +5429 0.211151123046875 +5430 0.240447998046875 +5431 0.242218017578125 +5432 0.2257080078125 +5433 0.194366455078125 +5434 0.115509033203125 +5435 0.0128173828125 +5436 -0.053802490234375 +5437 -0.110626220703125 +5438 -0.199493408203125 +5439 -0.29437255859375 +5440 -0.33221435546875 +5441 -0.27972412109375 +5442 -0.185333251953125 +5443 -0.128204345703125 +5444 -0.115692138671875 +5445 -0.116455078125 +5446 -0.105926513671875 +5447 -0.053955078125 +5448 0.048797607421875 +5449 0.157318115234375 +5450 0.212005615234375 +5451 0.218475341796875 +5452 0.23724365234375 +5453 0.30535888671875 +5454 0.38128662109375 +5455 0.404449462890625 +5456 0.3944091796875 +5457 0.3885498046875 +5458 0.362640380859375 +5459 0.27362060546875 +5460 0.11712646484375 +5461 -0.054901123046875 +5462 -0.19085693359375 +5463 -0.28570556640625 +5464 -0.339263916015625 +5465 -0.3775634765625 +5466 -0.445709228515625 +5467 -0.535064697265625 +5468 -0.629058837890625 +5469 -0.697601318359375 +5470 -0.70391845703125 +5471 -0.6424560546875 +5472 -0.491241455078125 +5473 -0.265716552734375 +5474 -0.023712158203125 +5475 0.201751708984375 +5476 0.375823974609375 +5477 0.485076904296875 +5478 0.56884765625 +5479 0.634765625 +5480 0.63763427734375 +5481 0.5660400390625 +5482 0.4720458984375 +5483 0.40692138671875 +5484 0.3778076171875 +5485 0.376953125 +5486 0.371978759765625 +5487 0.313140869140625 +5488 0.184417724609375 +5489 0.011199951171875 +5490 -0.171051025390625 +5491 -0.33740234375 +5492 -0.47198486328125 +5493 -0.560394287109375 +5494 -0.58056640625 +5495 -0.54754638671875 +5496 -0.508575439453125 +5497 -0.459503173828125 +5498 -0.394378662109375 +5499 -0.35260009765625 +5500 -0.31170654296875 +5501 -0.197418212890625 +5502 -0.007965087890625 +5503 0.207489013671875 +5504 0.409210205078125 +5505 0.57208251953125 +5506 0.66595458984375 +5507 0.65875244140625 +5508 0.56744384765625 +5509 0.431396484375 +5510 0.29443359375 +5511 0.182464599609375 +5512 0.06365966796875 +5513 -0.075958251953125 +5514 -0.189422607421875 +5515 -0.271942138671875 +5516 -0.342529296875 +5517 -0.364166259765625 +5518 -0.327239990234375 +5519 -0.2769775390625 +5520 -0.253692626953125 +5521 -0.24365234375 +5522 -0.1983642578125 +5523 -0.116241455078125 +5524 -0.036834716796875 +5525 0.034881591796875 +5526 0.09124755859375 +5527 0.10888671875 +5528 0.125518798828125 +5529 0.15771484375 +5530 0.17828369140625 +5531 0.17108154296875 +5532 0.129974365234375 +5533 0.082427978515625 +5534 0.027679443359375 +5535 -0.065643310546875 +5536 -0.15936279296875 +5537 -0.21307373046875 +5538 -0.234649658203125 +5539 -0.2001953125 +5540 -0.119171142578125 +5541 -0.024749755859375 +5542 0.085784912109375 +5543 0.178131103515625 +5544 0.215576171875 +5545 0.211456298828125 +5546 0.17523193359375 +5547 0.128753662109375 +5548 0.1019287109375 +5549 0.0743408203125 +5550 0.04327392578125 +5551 0.038177490234375 +5552 0.076263427734375 +5553 0.14105224609375 +5554 0.186431884765625 +5555 0.188812255859375 +5556 0.1390380859375 +5557 0.041778564453125 +5558 -0.079437255859375 +5559 -0.219390869140625 +5560 -0.367828369140625 +5561 -0.494873046875 +5562 -0.556243896484375 +5563 -0.508697509765625 +5564 -0.3756103515625 +5565 -0.218902587890625 +5566 -0.063751220703125 +5567 0.091552734375 +5568 0.23602294921875 +5569 0.342987060546875 +5570 0.39520263671875 +5571 0.389373779296875 +5572 0.324249267578125 +5573 0.224090576171875 +5574 0.124267578125 +5575 0.037078857421875 +5576 -0.010101318359375 +5577 -0.019439697265625 +5578 -0.022796630859375 +5579 -0.001556396484375 +5580 0.056304931640625 +5581 0.106719970703125 +5582 0.096893310546875 +5583 0.042694091796875 +5584 -0.018035888671875 +5585 -0.07586669921875 +5586 -0.11944580078125 +5587 -0.15972900390625 +5588 -0.202606201171875 +5589 -0.24859619140625 +5590 -0.30517578125 +5591 -0.36212158203125 +5592 -0.39141845703125 +5593 -0.35528564453125 +5594 -0.249969482421875 +5595 -0.092864990234375 +5596 0.08905029296875 +5597 0.2352294921875 +5598 0.318817138671875 +5599 0.358642578125 +5600 0.347747802734375 +5601 0.28564453125 +5602 0.223175048828125 +5603 0.196746826171875 +5604 0.179840087890625 +5605 0.155548095703125 +5606 0.151214599609375 +5607 0.156951904296875 +5608 0.13177490234375 +5609 0.100799560546875 +5610 0.087127685546875 +5611 0.05487060546875 +5612 -0.009002685546875 +5613 -0.10400390625 +5614 -0.229400634765625 +5615 -0.35552978515625 +5616 -0.441925048828125 +5617 -0.473846435546875 +5618 -0.464813232421875 +5619 -0.419097900390625 +5620 -0.334320068359375 +5621 -0.227935791015625 +5622 -0.12347412109375 +5623 -0.02764892578125 +5624 0.077667236328125 +5625 0.2132568359375 +5626 0.38885498046875 +5627 0.582794189453125 +5628 0.734039306640625 +5629 0.800140380859375 +5630 0.7783203125 +5631 0.6651611328125 +5632 0.45965576171875 +5633 0.199188232421875 +5634 -0.050689697265625 +5635 -0.23297119140625 +5636 -0.33013916015625 +5637 -0.368408203125 +5638 -0.378936767578125 +5639 -0.376983642578125 +5640 -0.37969970703125 +5641 -0.391510009765625 +5642 -0.385345458984375 +5643 -0.3419189453125 +5644 -0.28289794921875 +5645 -0.251617431640625 +5646 -0.266143798828125 +5647 -0.273345947265625 +5648 -0.216796875 +5649 -0.128265380859375 +5650 -0.068145751953125 +5651 -0.0430908203125 +5652 -0.024444580078125 +5653 0.020721435546875 +5654 0.124481201171875 +5655 0.25787353515625 +5656 0.379119873046875 +5657 0.47991943359375 +5658 0.5281982421875 +5659 0.511138916015625 +5660 0.456207275390625 +5661 0.407470703125 +5662 0.383758544921875 +5663 0.35687255859375 +5664 0.31182861328125 +5665 0.250885009765625 +5666 0.1654052734375 +5667 0.035247802734375 +5668 -0.142059326171875 +5669 -0.33563232421875 +5670 -0.5345458984375 +5671 -0.72186279296875 +5672 -0.836669921875 +5673 -0.8326416015625 +5674 -0.7296142578125 +5675 -0.582550048828125 +5676 -0.440093994140625 +5677 -0.324310302734375 +5678 -0.20147705078125 +5679 -0.044647216796875 +5680 0.103973388671875 +5681 0.202392578125 +5682 0.264495849609375 +5683 0.338897705078125 +5684 0.443817138671875 +5685 0.545074462890625 +5686 0.6173095703125 +5687 0.6524658203125 +5688 0.66339111328125 +5689 0.6561279296875 +5690 0.606781005859375 +5691 0.501190185546875 +5692 0.352783203125 +5693 0.176544189453125 +5694 -0.034820556640625 +5695 -0.258209228515625 +5696 -0.44244384765625 +5697 -0.5753173828125 +5698 -0.65203857421875 +5699 -0.641632080078125 +5700 -0.562164306640625 +5701 -0.458038330078125 +5702 -0.350555419921875 +5703 -0.260528564453125 +5704 -0.192108154296875 +5705 -0.141937255859375 +5706 -0.1021728515625 +5707 -0.062896728515625 +5708 -0.011932373046875 +5709 0.062835693359375 +5710 0.148712158203125 +5711 0.241729736328125 +5712 0.34912109375 +5713 0.457305908203125 +5714 0.54388427734375 +5715 0.5728759765625 +5716 0.506591796875 +5717 0.351226806640625 +5718 0.146514892578125 +5719 -0.05523681640625 +5720 -0.21624755859375 +5721 -0.334930419921875 +5722 -0.402984619140625 +5723 -0.4412841796875 +5724 -0.49578857421875 +5725 -0.5601806640625 +5726 -0.600738525390625 +5727 -0.584228515625 +5728 -0.47930908203125 +5729 -0.27935791015625 +5730 -0.0089111328125 +5731 0.268798828125 +5732 0.482818603515625 +5733 0.60369873046875 +5734 0.650421142578125 +5735 0.66400146484375 +5736 0.6414794921875 +5737 0.572540283203125 +5738 0.498138427734375 +5739 0.439453125 +5740 0.375518798828125 +5741 0.274505615234375 +5742 0.1087646484375 +5743 -0.099395751953125 +5744 -0.3182373046875 +5745 -0.5489501953125 +5746 -0.7738037109375 +5747 -0.86383056640625 +5748 -0.870391845703125 +5749 -0.86895751953125 +5750 -0.861053466796875 +5751 -0.765869140625 +5752 -0.5301513671875 +5753 -0.214691162109375 +5754 0.137359619140625 +5755 0.474822998046875 +5756 0.76239013671875 +5757 0.867462158203125 +5758 0.870361328125 +5759 0.86480712890625 +5760 0.831817626953125 +5761 0.677581787109375 +5762 0.495880126953125 +5763 0.30767822265625 +5764 0.116180419921875 +5765 -0.110748291015625 +5766 -0.381805419921875 +5767 -0.6572265625 +5768 -0.857421875 +5769 -0.870391845703125 +5770 -0.870391845703125 +5771 -0.86444091796875 +5772 -0.85723876953125 +5773 -0.790008544921875 +5774 -0.62847900390625 +5775 -0.3956298828125 +5776 -0.126708984375 +5777 0.150115966796875 +5778 0.424041748046875 +5779 0.670623779296875 +5780 0.854522705078125 +5781 0.866485595703125 +5782 0.86920166015625 +5783 0.8653564453125 +5784 0.857147216796875 +5785 0.766845703125 +5786 0.628509521484375 +5787 0.462127685546875 +5788 0.297210693359375 +5789 0.14862060546875 +5790 -0.00537109375 +5791 -0.15753173828125 +5792 -0.31304931640625 +5793 -0.48876953125 +5794 -0.6416015625 +5795 -0.751373291015625 +5796 -0.84619140625 +5797 -0.861297607421875 +5798 -0.863250732421875 +5799 -0.856597900390625 +5800 -0.7498779296875 +5801 -0.624542236328125 +5802 -0.47808837890625 +5803 -0.253387451171875 +5804 0.003692626953125 +5805 0.2257080078125 +5806 0.427154541015625 +5807 0.643218994140625 +5808 0.855926513671875 +5809 0.870361328125 +5810 0.870361328125 +5811 0.862762451171875 +5812 0.79669189453125 +5813 0.595794677734375 +5814 0.362152099609375 +5815 0.1270751953125 +5816 -0.086944580078125 +5817 -0.2784423828125 +5818 -0.484832763671875 +5819 -0.729583740234375 +5820 -0.86688232421875 +5821 -0.870391845703125 +5822 -0.86859130859375 +5823 -0.86279296875 +5824 -0.817962646484375 +5825 -0.6116943359375 +5826 -0.3128662109375 +5827 0.039398193359375 +5828 0.422821044921875 +5829 0.805145263671875 +5830 0.870361328125 +5831 0.870361328125 +5832 0.860015869140625 +5833 0.727935791015625 +5834 0.48114013671875 +5835 0.2059326171875 +5836 -0.06103515625 +5837 -0.29913330078125 +5838 -0.516204833984375 +5839 -0.7252197265625 +5840 -0.85980224609375 +5841 -0.870391845703125 +5842 -0.870391845703125 +5843 -0.858062744140625 +5844 -0.673004150390625 +5845 -0.42694091796875 +5846 -0.2100830078125 +5847 -0.0362548828125 +5848 0.10943603515625 +5849 0.23516845703125 +5850 0.373687744140625 +5851 0.517791748046875 +5852 0.602783203125 +5853 0.635711669921875 +5854 0.655181884765625 +5855 0.65948486328125 +5856 0.651275634765625 +5857 0.61846923828125 +5858 0.53753662109375 +5859 0.404144287109375 +5860 0.22186279296875 +5861 0.003997802734375 +5862 -0.22100830078125 +5863 -0.42449951171875 +5864 -0.579833984375 +5865 -0.641876220703125 +5866 -0.6177978515625 +5867 -0.575531005859375 +5868 -0.526336669921875 +5869 -0.42645263671875 +5870 -0.2581787109375 +5871 -0.068695068359375 +5872 0.09222412109375 +5873 0.232147216796875 +5874 0.3509521484375 +5875 0.410064697265625 +5876 0.372955322265625 +5877 0.2554931640625 +5878 0.10711669921875 +5879 -0.052886962890625 +5880 -0.186279296875 +5881 -0.23291015625 +5882 -0.209442138671875 +5883 -0.174163818359375 +5884 -0.126739501953125 +5885 -0.048126220703125 +5886 0.0426025390625 +5887 0.10748291015625 +5888 0.1409912109375 +5889 0.19708251953125 +5890 0.273651123046875 +5891 0.31768798828125 +5892 0.341094970703125 +5893 0.368011474609375 +5894 0.37249755859375 +5895 0.30072021484375 +5896 0.1517333984375 +5897 -0.01470947265625 +5898 -0.1883544921875 +5899 -0.372711181640625 +5900 -0.51397705078125 +5901 -0.57177734375 +5902 -0.53948974609375 +5903 -0.43511962890625 +5904 -0.2962646484375 +5905 -0.161102294921875 +5906 -0.0435791015625 +5907 0.060394287109375 +5908 0.13665771484375 +5909 0.170135498046875 +5910 0.16552734375 +5911 0.15728759765625 +5912 0.150787353515625 +5913 0.12200927734375 +5914 0.080108642578125 +5915 0.05126953125 +5916 0.062896728515625 +5917 0.09271240234375 +5918 0.092987060546875 +5919 0.07855224609375 +5920 0.06427001953125 +5921 0.0347900390625 +5922 -0.01171875 +5923 -0.056060791015625 +5924 -0.055511474609375 +5925 -0.010467529296875 +5926 0.02508544921875 +5927 0.025665283203125 +5928 0.017333984375 +5929 0.00189208984375 +5930 -0.03173828125 +5931 -0.071502685546875 +5932 -0.13543701171875 +5933 -0.219970703125 +5934 -0.300506591796875 +5935 -0.376312255859375 +5936 -0.416107177734375 +5937 -0.371124267578125 +5938 -0.242279052734375 +5939 -0.069732666015625 +5940 0.125640869140625 +5941 0.31268310546875 +5942 0.45501708984375 +5943 0.554779052734375 +5944 0.61065673828125 +5945 0.610931396484375 +5946 0.531463623046875 +5947 0.3883056640625 +5948 0.23468017578125 +5949 0.095245361328125 +5950 -0.00396728515625 +5951 -0.04852294921875 +5952 -0.055145263671875 +5953 -0.0758056640625 +5954 -0.138702392578125 +5955 -0.209197998046875 +5956 -0.289031982421875 +5957 -0.37884521484375 +5958 -0.456329345703125 +5959 -0.51641845703125 +5960 -0.519287109375 +5961 -0.458251953125 +5962 -0.384796142578125 +5963 -0.323699951171875 +5964 -0.269287109375 +5965 -0.1951904296875 +5966 -0.100006103515625 +5967 -0.01055908203125 +5968 0.1033935546875 +5969 0.24908447265625 +5970 0.373199462890625 +5971 0.45806884765625 +5972 0.511474609375 +5973 0.565399169921875 +5974 0.61138916015625 +5975 0.5897216796875 +5976 0.4906005859375 +5977 0.33148193359375 +5978 0.147796630859375 +5979 -0.01873779296875 +5980 -0.140289306640625 +5981 -0.191986083984375 +5982 -0.184295654296875 +5983 -0.161834716796875 +5984 -0.166595458984375 +5985 -0.19390869140625 +5986 -0.22442626953125 +5987 -0.279754638671875 +5988 -0.3389892578125 +5989 -0.3543701171875 +5990 -0.348175048828125 +5991 -0.32598876953125 +5992 -0.2581787109375 +5993 -0.139801025390625 +5994 0.014617919921875 +5995 0.144378662109375 +5996 0.221038818359375 +5997 0.27069091796875 +5998 0.294036865234375 +5999 0.311767578125 +6000 0.339141845703125 +6001 0.360260009765625 +6002 0.360504150390625 +6003 0.308380126953125 +6004 0.18170166015625 +6005 0.0047607421875 +6006 -0.17559814453125 +6007 -0.3143310546875 +6008 -0.36785888671875 +6009 -0.36248779296875 +6010 -0.343536376953125 +6011 -0.3018798828125 +6012 -0.231414794921875 +6013 -0.117645263671875 +6014 0.007049560546875 +6015 0.087982177734375 +6016 0.13946533203125 +6017 0.17425537109375 +6018 0.188201904296875 +6019 0.171234130859375 +6020 0.118438720703125 +6021 0.05706787109375 +6022 -0.010711669921875 +6023 -0.0914306640625 +6024 -0.162322998046875 +6025 -0.194549560546875 +6026 -0.1492919921875 +6027 -0.02166748046875 +6028 0.124053955078125 +6029 0.211151123046875 +6030 0.240447998046875 +6031 0.242218017578125 +6032 0.2257080078125 +6033 0.194366455078125 +6034 0.115509033203125 +6035 0.0128173828125 +6036 -0.053802490234375 +6037 -0.110626220703125 +6038 -0.199493408203125 +6039 -0.29437255859375 +6040 -0.33221435546875 +6041 -0.27972412109375 +6042 -0.185333251953125 +6043 -0.128204345703125 +6044 -0.115692138671875 +6045 -0.116455078125 +6046 -0.105926513671875 +6047 -0.053955078125 +6048 0.048797607421875 +6049 0.157318115234375 +6050 0.212005615234375 +6051 0.218475341796875 +6052 0.23724365234375 +6053 0.30535888671875 +6054 0.38128662109375 +6055 0.404449462890625 +6056 0.3944091796875 +6057 0.3885498046875 +6058 0.362640380859375 +6059 0.27362060546875 +6060 0.11712646484375 +6061 -0.054901123046875 +6062 -0.19085693359375 +6063 -0.28570556640625 +6064 -0.339263916015625 +6065 -0.3775634765625 +6066 -0.445709228515625 +6067 -0.535064697265625 +6068 -0.629058837890625 +6069 -0.697601318359375 +6070 -0.70391845703125 +6071 -0.6424560546875 +6072 -0.491241455078125 +6073 -0.265716552734375 +6074 -0.023712158203125 +6075 0.201751708984375 +6076 0.375823974609375 +6077 0.485076904296875 +6078 0.56884765625 +6079 0.634765625 +6080 0.63763427734375 +6081 0.5660400390625 +6082 0.4720458984375 +6083 0.40692138671875 +6084 0.3778076171875 +6085 0.376953125 +6086 0.371978759765625 +6087 0.313140869140625 +6088 0.184417724609375 +6089 0.011199951171875 +6090 -0.171051025390625 +6091 -0.33740234375 +6092 -0.47198486328125 +6093 -0.560394287109375 +6094 -0.58056640625 +6095 -0.54754638671875 +6096 -0.508575439453125 +6097 -0.459503173828125 +6098 -0.394378662109375 +6099 -0.35260009765625 +6100 -0.31170654296875 +6101 -0.197418212890625 +6102 -0.007965087890625 +6103 0.207489013671875 +6104 0.409210205078125 +6105 0.57208251953125 +6106 0.66595458984375 +6107 0.65875244140625 +6108 0.56744384765625 +6109 0.431396484375 +6110 0.29443359375 +6111 0.182464599609375 +6112 0.06365966796875 +6113 -0.075958251953125 +6114 -0.189422607421875 +6115 -0.271942138671875 +6116 -0.342529296875 +6117 -0.364166259765625 +6118 -0.327239990234375 +6119 -0.2769775390625 +6120 -0.253692626953125 +6121 -0.24365234375 +6122 -0.1983642578125 +6123 -0.116241455078125 +6124 -0.036834716796875 +6125 0.034881591796875 +6126 0.09124755859375 +6127 0.10888671875 +6128 0.125518798828125 +6129 0.15771484375 +6130 0.17828369140625 +6131 0.17108154296875 +6132 0.129974365234375 +6133 0.082427978515625 +6134 0.027679443359375 +6135 -0.065643310546875 +6136 -0.15936279296875 +6137 -0.21307373046875 +6138 -0.234649658203125 +6139 -0.2001953125 +6140 -0.119171142578125 +6141 -0.024749755859375 +6142 0.085784912109375 +6143 0.178131103515625 +6144 0.215576171875 +6145 0.211456298828125 +6146 0.17523193359375 +6147 0.128753662109375 +6148 0.1019287109375 +6149 0.0743408203125 +6150 0.04327392578125 +6151 0.038177490234375 +6152 0.076263427734375 +6153 0.14105224609375 +6154 0.186431884765625 +6155 0.188812255859375 +6156 0.1390380859375 +6157 0.041778564453125 +6158 -0.079437255859375 +6159 -0.219390869140625 +6160 -0.367828369140625 +6161 -0.494873046875 +6162 -0.556243896484375 +6163 -0.508697509765625 +6164 -0.3756103515625 +6165 -0.218902587890625 +6166 -0.063751220703125 +6167 0.091552734375 +6168 0.23602294921875 +6169 0.342987060546875 +6170 0.39520263671875 +6171 0.389373779296875 +6172 0.324249267578125 +6173 0.224090576171875 +6174 0.124267578125 +6175 0.037078857421875 +6176 -0.010101318359375 +6177 -0.019439697265625 +6178 -0.022796630859375 +6179 -0.001556396484375 +6180 0.056304931640625 +6181 0.106719970703125 +6182 0.096893310546875 +6183 0.042694091796875 +6184 -0.018035888671875 +6185 -0.07586669921875 +6186 -0.11944580078125 +6187 -0.15972900390625 +6188 -0.202606201171875 +6189 -0.24859619140625 +6190 -0.30517578125 +6191 -0.36212158203125 +6192 -0.39141845703125 +6193 -0.35528564453125 +6194 -0.249969482421875 +6195 -0.092864990234375 +6196 0.08905029296875 +6197 0.2352294921875 +6198 0.318817138671875 +6199 0.358642578125 +6200 0.347747802734375 +6201 0.28564453125 +6202 0.223175048828125 +6203 0.196746826171875 +6204 0.179840087890625 +6205 0.155548095703125 +6206 0.151214599609375 +6207 0.156951904296875 +6208 0.13177490234375 +6209 0.100799560546875 +6210 0.087127685546875 +6211 0.05487060546875 +6212 -0.009002685546875 +6213 -0.10400390625 +6214 -0.229400634765625 +6215 -0.35552978515625 +6216 -0.441925048828125 +6217 -0.473846435546875 +6218 -0.464813232421875 +6219 -0.419097900390625 +6220 -0.334320068359375 +6221 -0.227935791015625 +6222 -0.12347412109375 +6223 -0.02764892578125 +6224 0.077667236328125 +6225 0.2132568359375 +6226 0.38885498046875 +6227 0.582794189453125 +6228 0.734039306640625 +6229 0.800140380859375 +6230 0.7783203125 +6231 0.6651611328125 +6232 0.45965576171875 +6233 0.199188232421875 +6234 -0.050689697265625 +6235 -0.23297119140625 +6236 -0.33013916015625 +6237 -0.368408203125 +6238 -0.378936767578125 +6239 -0.376983642578125 +6240 -0.37969970703125 +6241 -0.391510009765625 +6242 -0.385345458984375 +6243 -0.3419189453125 +6244 -0.28289794921875 +6245 -0.251617431640625 +6246 -0.266143798828125 +6247 -0.273345947265625 +6248 -0.216796875 +6249 -0.128265380859375 +6250 -0.068145751953125 +6251 -0.0430908203125 +6252 -0.024444580078125 +6253 0.020721435546875 +6254 0.124481201171875 +6255 0.25787353515625 +6256 0.379119873046875 +6257 0.47991943359375 +6258 0.5281982421875 +6259 0.511138916015625 +6260 0.456207275390625 +6261 0.407470703125 +6262 0.383758544921875 +6263 0.35687255859375 +6264 0.31182861328125 +6265 0.250885009765625 +6266 0.1654052734375 +6267 0.035247802734375 +6268 -0.142059326171875 +6269 -0.33563232421875 +6270 -0.5345458984375 +6271 -0.72186279296875 +6272 -0.836669921875 +6273 -0.8326416015625 +6274 -0.7296142578125 +6275 -0.582550048828125 +6276 -0.440093994140625 +6277 -0.324310302734375 +6278 -0.20147705078125 +6279 -0.044647216796875 +6280 0.103973388671875 +6281 0.202392578125 +6282 0.264495849609375 +6283 0.338897705078125 +6284 0.443817138671875 +6285 0.545074462890625 +6286 0.6173095703125 +6287 0.6524658203125 +6288 0.66339111328125 +6289 0.6561279296875 +6290 0.606781005859375 +6291 0.501190185546875 +6292 0.352783203125 +6293 0.176544189453125 +6294 -0.034820556640625 +6295 -0.258209228515625 +6296 -0.44244384765625 +6297 -0.5753173828125 +6298 -0.65203857421875 +6299 -0.641632080078125 +6300 -0.562164306640625 +6301 -0.458038330078125 +6302 -0.350555419921875 +6303 -0.260528564453125 +6304 -0.192108154296875 +6305 -0.141937255859375 +6306 -0.1021728515625 +6307 -0.062896728515625 +6308 -0.011932373046875 +6309 0.062835693359375 +6310 0.148712158203125 +6311 0.241729736328125 +6312 0.34912109375 +6313 0.457305908203125 +6314 0.54388427734375 +6315 0.5728759765625 +6316 0.506591796875 +6317 0.351226806640625 +6318 0.146514892578125 +6319 -0.05523681640625 +6320 -0.21624755859375 +6321 -0.334930419921875 +6322 -0.402984619140625 +6323 -0.4412841796875 +6324 -0.49578857421875 +6325 -0.5601806640625 +6326 -0.600738525390625 +6327 -0.584228515625 +6328 -0.47930908203125 +6329 -0.27935791015625 +6330 -0.0089111328125 +6331 0.268798828125 +6332 0.482818603515625 +6333 0.60369873046875 +6334 0.650421142578125 +6335 0.66400146484375 +6336 0.6414794921875 +6337 0.572540283203125 +6338 0.498138427734375 +6339 0.439453125 +6340 0.375518798828125 +6341 0.274505615234375 +6342 0.1087646484375 +6343 -0.099395751953125 +6344 -0.3182373046875 +6345 -0.5489501953125 +6346 -0.7738037109375 +6347 -0.86383056640625 +6348 -0.870391845703125 +6349 -0.86895751953125 +6350 -0.861053466796875 +6351 -0.765869140625 +6352 -0.5301513671875 +6353 -0.214691162109375 +6354 0.137359619140625 +6355 0.474822998046875 +6356 0.76239013671875 +6357 0.867462158203125 +6358 0.870361328125 +6359 0.86480712890625 +6360 0.831817626953125 +6361 0.677581787109375 +6362 0.495880126953125 +6363 0.30767822265625 +6364 0.116180419921875 +6365 -0.110748291015625 +6366 -0.381805419921875 +6367 -0.6572265625 +6368 -0.857421875 +6369 -0.870391845703125 +6370 -0.870391845703125 +6371 -0.86444091796875 +6372 -0.85723876953125 +6373 -0.790008544921875 +6374 -0.62847900390625 +6375 -0.3956298828125 +6376 -0.126708984375 +6377 0.150115966796875 +6378 0.424041748046875 +6379 0.670623779296875 +6380 0.854522705078125 +6381 0.866485595703125 +6382 0.86920166015625 +6383 0.8653564453125 +6384 0.857147216796875 +6385 0.766845703125 +6386 0.628509521484375 +6387 0.462127685546875 +6388 0.297210693359375 +6389 0.14862060546875 +6390 -0.00537109375 +6391 -0.15753173828125 +6392 -0.31304931640625 +6393 -0.48876953125 +6394 -0.6416015625 +6395 -0.751373291015625 +6396 -0.84619140625 +6397 -0.861297607421875 +6398 -0.863250732421875 +6399 -0.856597900390625 +6400 -0.7498779296875 +6401 -0.624542236328125 +6402 -0.47808837890625 +6403 -0.253387451171875 +6404 0.003692626953125 +6405 0.2257080078125 +6406 0.427154541015625 +6407 0.643218994140625 +6408 0.855926513671875 +6409 0.870361328125 +6410 0.870361328125 +6411 0.862762451171875 +6412 0.79669189453125 +6413 0.595794677734375 +6414 0.362152099609375 +6415 0.1270751953125 +6416 -0.086944580078125 +6417 -0.2784423828125 +6418 -0.484832763671875 +6419 -0.729583740234375 +6420 -0.86688232421875 +6421 -0.870391845703125 +6422 -0.86859130859375 +6423 -0.86279296875 +6424 -0.817962646484375 +6425 -0.6116943359375 +6426 -0.3128662109375 +6427 0.039398193359375 +6428 0.422821044921875 +6429 0.805145263671875 +6430 0.870361328125 +6431 0.870361328125 +6432 0.860015869140625 +6433 0.727935791015625 +6434 0.48114013671875 +6435 0.2059326171875 +6436 -0.06103515625 +6437 -0.29913330078125 +6438 -0.516204833984375 +6439 -0.7252197265625 +6440 -0.85980224609375 +6441 -0.870391845703125 +6442 -0.870391845703125 +6443 -0.858062744140625 +6444 -0.673004150390625 +6445 -0.42694091796875 +6446 -0.2100830078125 +6447 -0.0362548828125 +6448 0.10943603515625 +6449 0.23516845703125 +6450 0.373687744140625 +6451 0.517791748046875 +6452 0.602783203125 +6453 0.635711669921875 +6454 0.655181884765625 +6455 0.65948486328125 +6456 0.651275634765625 +6457 0.61846923828125 +6458 0.53753662109375 +6459 0.404144287109375 +6460 0.22186279296875 +6461 0.003997802734375 +6462 -0.22100830078125 +6463 -0.42449951171875 +6464 -0.579833984375 +6465 -0.641876220703125 +6466 -0.6177978515625 +6467 -0.575531005859375 +6468 -0.526336669921875 +6469 -0.42645263671875 +6470 -0.2581787109375 +6471 -0.068695068359375 +6472 0.09222412109375 +6473 0.232147216796875 +6474 0.3509521484375 +6475 0.410064697265625 +6476 0.372955322265625 +6477 0.2554931640625 +6478 0.10711669921875 +6479 -0.052886962890625 +6480 -0.186279296875 +6481 -0.23291015625 +6482 -0.209442138671875 +6483 -0.174163818359375 +6484 -0.126739501953125 +6485 -0.048126220703125 +6486 0.0426025390625 +6487 0.10748291015625 +6488 0.1409912109375 +6489 0.19708251953125 +6490 0.273651123046875 +6491 0.31768798828125 +6492 0.341094970703125 +6493 0.368011474609375 +6494 0.37249755859375 +6495 0.30072021484375 +6496 0.1517333984375 +6497 -0.01470947265625 +6498 -0.1883544921875 +6499 -0.372711181640625 +6500 -0.51397705078125 +6501 -0.57177734375 +6502 -0.53948974609375 +6503 -0.43511962890625 +6504 -0.2962646484375 +6505 -0.161102294921875 +6506 -0.0435791015625 +6507 0.060394287109375 +6508 0.13665771484375 +6509 0.170135498046875 +6510 0.16552734375 +6511 0.15728759765625 +6512 0.150787353515625 +6513 0.12200927734375 +6514 0.080108642578125 +6515 0.05126953125 +6516 0.062896728515625 +6517 0.09271240234375 +6518 0.092987060546875 +6519 0.07855224609375 +6520 0.06427001953125 +6521 0.0347900390625 +6522 -0.01171875 +6523 -0.056060791015625 +6524 -0.055511474609375 +6525 -0.010467529296875 +6526 0.02508544921875 +6527 0.025665283203125 +6528 0.017333984375 +6529 0.00189208984375 +6530 -0.03173828125 +6531 -0.071502685546875 +6532 -0.13543701171875 +6533 -0.219970703125 +6534 -0.300506591796875 +6535 -0.376312255859375 +6536 -0.416107177734375 +6537 -0.371124267578125 +6538 -0.242279052734375 +6539 -0.069732666015625 +6540 0.125640869140625 +6541 0.31268310546875 +6542 0.45501708984375 +6543 0.554779052734375 +6544 0.61065673828125 +6545 0.610931396484375 +6546 0.531463623046875 +6547 0.3883056640625 +6548 0.23468017578125 +6549 0.095245361328125 +6550 -0.00396728515625 +6551 -0.04852294921875 +6552 -0.055145263671875 +6553 -0.0758056640625 +6554 -0.138702392578125 +6555 -0.209197998046875 +6556 -0.289031982421875 +6557 -0.37884521484375 +6558 -0.456329345703125 +6559 -0.51641845703125 +6560 -0.519287109375 +6561 -0.458251953125 +6562 -0.384796142578125 +6563 -0.323699951171875 +6564 -0.269287109375 +6565 -0.1951904296875 +6566 -0.100006103515625 +6567 -0.01055908203125 +6568 0.1033935546875 +6569 0.24908447265625 +6570 0.373199462890625 +6571 0.45806884765625 +6572 0.511474609375 +6573 0.565399169921875 +6574 0.61138916015625 +6575 0.5897216796875 +6576 0.4906005859375 +6577 0.33148193359375 +6578 0.147796630859375 +6579 -0.01873779296875 +6580 -0.140289306640625 +6581 -0.191986083984375 +6582 -0.184295654296875 +6583 -0.161834716796875 +6584 -0.166595458984375 +6585 -0.19390869140625 +6586 -0.22442626953125 +6587 -0.279754638671875 +6588 -0.3389892578125 +6589 -0.3543701171875 +6590 -0.348175048828125 +6591 -0.32598876953125 +6592 -0.2581787109375 +6593 -0.139801025390625 +6594 0.014617919921875 +6595 0.144378662109375 +6596 0.221038818359375 +6597 0.27069091796875 +6598 0.294036865234375 +6599 0.311767578125 +6600 0.339141845703125 +6601 0.360260009765625 +6602 0.360504150390625 +6603 0.308380126953125 +6604 0.18170166015625 +6605 0.0047607421875 +6606 -0.17559814453125 +6607 -0.3143310546875 +6608 -0.36785888671875 +6609 -0.36248779296875 +6610 -0.343536376953125 +6611 -0.3018798828125 +6612 -0.231414794921875 +6613 -0.117645263671875 +6614 0.007049560546875 +6615 0.087982177734375 +6616 0.13946533203125 +6617 0.17425537109375 +6618 0.188201904296875 +6619 0.171234130859375 +6620 0.118438720703125 +6621 0.05706787109375 +6622 -0.010711669921875 +6623 -0.0914306640625 +6624 -0.162322998046875 +6625 -0.194549560546875 +6626 -0.1492919921875 +6627 -0.02166748046875 +6628 0.124053955078125 +6629 0.211151123046875 +6630 0.240447998046875 +6631 0.242218017578125 +6632 0.2257080078125 +6633 0.194366455078125 +6634 0.115509033203125 +6635 0.0128173828125 +6636 -0.053802490234375 +6637 -0.110626220703125 +6638 -0.199493408203125 +6639 -0.29437255859375 +6640 -0.33221435546875 +6641 -0.27972412109375 +6642 -0.185333251953125 +6643 -0.128204345703125 +6644 -0.115692138671875 +6645 -0.116455078125 +6646 -0.105926513671875 +6647 -0.053955078125 +6648 0.048797607421875 +6649 0.157318115234375 +6650 0.212005615234375 +6651 0.218475341796875 +6652 0.23724365234375 +6653 0.30535888671875 +6654 0.38128662109375 +6655 0.404449462890625 +6656 0.3944091796875 +6657 0.3885498046875 +6658 0.362640380859375 +6659 0.27362060546875 +6660 0.11712646484375 +6661 -0.054901123046875 +6662 -0.19085693359375 +6663 -0.28570556640625 +6664 -0.339263916015625 +6665 -0.3775634765625 +6666 -0.445709228515625 +6667 -0.535064697265625 +6668 -0.629058837890625 +6669 -0.697601318359375 +6670 -0.70391845703125 +6671 -0.6424560546875 +6672 -0.491241455078125 +6673 -0.265716552734375 +6674 -0.023712158203125 +6675 0.201751708984375 +6676 0.375823974609375 +6677 0.485076904296875 +6678 0.56884765625 +6679 0.634765625 +6680 0.63763427734375 +6681 0.5660400390625 +6682 0.4720458984375 +6683 0.40692138671875 +6684 0.3778076171875 +6685 0.376953125 +6686 0.371978759765625 +6687 0.313140869140625 +6688 0.184417724609375 +6689 0.011199951171875 +6690 -0.171051025390625 +6691 -0.33740234375 +6692 -0.47198486328125 +6693 -0.560394287109375 +6694 -0.58056640625 +6695 -0.54754638671875 +6696 -0.508575439453125 +6697 -0.459503173828125 +6698 -0.394378662109375 +6699 -0.35260009765625 +6700 -0.31170654296875 +6701 -0.197418212890625 +6702 -0.007965087890625 +6703 0.207489013671875 +6704 0.409210205078125 +6705 0.57208251953125 +6706 0.66595458984375 +6707 0.65875244140625 +6708 0.56744384765625 +6709 0.431396484375 +6710 0.29443359375 +6711 0.182464599609375 +6712 0.06365966796875 +6713 -0.075958251953125 +6714 -0.189422607421875 +6715 -0.271942138671875 +6716 -0.342529296875 +6717 -0.364166259765625 +6718 -0.327239990234375 +6719 -0.2769775390625 +6720 -0.253692626953125 +6721 -0.24365234375 +6722 -0.1983642578125 +6723 -0.116241455078125 +6724 -0.036834716796875 +6725 0.034881591796875 +6726 0.09124755859375 +6727 0.10888671875 +6728 0.125518798828125 +6729 0.15771484375 +6730 0.17828369140625 +6731 0.17108154296875 +6732 0.129974365234375 +6733 0.082427978515625 +6734 0.027679443359375 +6735 -0.065643310546875 +6736 -0.15936279296875 +6737 -0.21307373046875 +6738 -0.234649658203125 +6739 -0.2001953125 +6740 -0.119171142578125 +6741 -0.024749755859375 +6742 0.085784912109375 +6743 0.178131103515625 +6744 0.215576171875 +6745 0.211456298828125 +6746 0.17523193359375 +6747 0.128753662109375 +6748 0.1019287109375 +6749 0.0743408203125 +6750 0.04327392578125 +6751 0.038177490234375 +6752 0.076263427734375 +6753 0.14105224609375 +6754 0.186431884765625 +6755 0.188812255859375 +6756 0.1390380859375 +6757 0.041778564453125 +6758 -0.079437255859375 +6759 -0.219390869140625 +6760 -0.367828369140625 +6761 -0.494873046875 +6762 -0.556243896484375 +6763 -0.508697509765625 +6764 -0.3756103515625 +6765 -0.218902587890625 +6766 -0.063751220703125 +6767 0.091552734375 +6768 0.23602294921875 +6769 0.342987060546875 +6770 0.39520263671875 +6771 0.389373779296875 +6772 0.324249267578125 +6773 0.224090576171875 +6774 0.124267578125 +6775 0.037078857421875 +6776 -0.010101318359375 +6777 -0.019439697265625 +6778 -0.022796630859375 +6779 -0.001556396484375 +6780 0.056304931640625 +6781 0.106719970703125 +6782 0.096893310546875 +6783 0.042694091796875 +6784 -0.018035888671875 +6785 -0.07586669921875 +6786 -0.11944580078125 +6787 -0.15972900390625 +6788 -0.202606201171875 +6789 -0.24859619140625 +6790 -0.30517578125 +6791 -0.36212158203125 +6792 -0.39141845703125 +6793 -0.35528564453125 +6794 -0.249969482421875 +6795 -0.092864990234375 +6796 0.08905029296875 +6797 0.2352294921875 +6798 0.318817138671875 +6799 0.358642578125 +6800 0.347747802734375 +6801 0.28564453125 +6802 0.223175048828125 +6803 0.196746826171875 +6804 0.179840087890625 +6805 0.155548095703125 +6806 0.151214599609375 +6807 0.156951904296875 +6808 0.13177490234375 +6809 0.100799560546875 +6810 0.087127685546875 +6811 0.05487060546875 +6812 -0.009002685546875 +6813 -0.10400390625 +6814 -0.229400634765625 +6815 -0.35552978515625 +6816 -0.441925048828125 +6817 -0.473846435546875 +6818 -0.464813232421875 +6819 -0.419097900390625 +6820 -0.334320068359375 +6821 -0.227935791015625 +6822 -0.12347412109375 +6823 -0.02764892578125 +6824 0.077667236328125 +6825 0.2132568359375 +6826 0.38885498046875 +6827 0.582794189453125 +6828 0.734039306640625 +6829 0.800140380859375 +6830 0.7783203125 +6831 0.6651611328125 +6832 0.45965576171875 +6833 0.199188232421875 +6834 -0.050689697265625 +6835 -0.23297119140625 +6836 -0.33013916015625 +6837 -0.368408203125 +6838 -0.378936767578125 +6839 -0.376983642578125 +6840 -0.37969970703125 +6841 -0.391510009765625 +6842 -0.385345458984375 +6843 -0.3419189453125 +6844 -0.28289794921875 +6845 -0.251617431640625 +6846 -0.266143798828125 +6847 -0.273345947265625 +6848 -0.216796875 +6849 -0.128265380859375 +6850 -0.068145751953125 +6851 -0.0430908203125 +6852 -0.024444580078125 +6853 0.020721435546875 +6854 0.124481201171875 +6855 0.25787353515625 +6856 0.379119873046875 +6857 0.47991943359375 +6858 0.5281982421875 +6859 0.511138916015625 +6860 0.456207275390625 +6861 0.407470703125 +6862 0.383758544921875 +6863 0.35687255859375 +6864 0.31182861328125 +6865 0.250885009765625 +6866 0.1654052734375 +6867 0.035247802734375 +6868 -0.142059326171875 +6869 -0.33563232421875 +6870 -0.5345458984375 +6871 -0.72186279296875 +6872 -0.836669921875 +6873 -0.8326416015625 +6874 -0.7296142578125 +6875 -0.582550048828125 +6876 -0.440093994140625 +6877 -0.324310302734375 +6878 -0.20147705078125 +6879 -0.044647216796875 +6880 0.103973388671875 +6881 0.202392578125 +6882 0.264495849609375 +6883 0.338897705078125 +6884 0.443817138671875 +6885 0.545074462890625 +6886 0.6173095703125 +6887 0.6524658203125 +6888 0.66339111328125 +6889 0.6561279296875 +6890 0.606781005859375 +6891 0.501190185546875 +6892 0.352783203125 +6893 0.176544189453125 +6894 -0.034820556640625 +6895 -0.258209228515625 +6896 -0.44244384765625 +6897 -0.5753173828125 +6898 -0.65203857421875 +6899 -0.641632080078125 +6900 -0.562164306640625 +6901 -0.458038330078125 +6902 -0.350555419921875 +6903 -0.260528564453125 +6904 -0.192108154296875 +6905 -0.141937255859375 +6906 -0.1021728515625 +6907 -0.062896728515625 +6908 -0.011932373046875 +6909 0.062835693359375 +6910 0.148712158203125 +6911 0.241729736328125 +6912 0.34912109375 +6913 0.457305908203125 +6914 0.54388427734375 +6915 0.5728759765625 +6916 0.506591796875 +6917 0.351226806640625 +6918 0.146514892578125 +6919 -0.05523681640625 +6920 -0.21624755859375 +6921 -0.334930419921875 +6922 -0.402984619140625 +6923 -0.4412841796875 +6924 -0.49578857421875 +6925 -0.5601806640625 +6926 -0.600738525390625 +6927 -0.584228515625 +6928 -0.47930908203125 +6929 -0.27935791015625 +6930 -0.0089111328125 +6931 0.268798828125 +6932 0.482818603515625 +6933 0.60369873046875 +6934 0.650421142578125 +6935 0.66400146484375 +6936 0.6414794921875 +6937 0.572540283203125 +6938 0.498138427734375 +6939 0.439453125 +6940 0.375518798828125 +6941 0.274505615234375 +6942 0.1087646484375 +6943 -0.099395751953125 +6944 -0.3182373046875 +6945 -0.5489501953125 +6946 -0.7738037109375 +6947 -0.86383056640625 +6948 -0.870391845703125 +6949 -0.86895751953125 +6950 -0.861053466796875 +6951 -0.765869140625 +6952 -0.5301513671875 +6953 -0.214691162109375 +6954 0.137359619140625 +6955 0.474822998046875 +6956 0.76239013671875 +6957 0.867462158203125 +6958 0.870361328125 +6959 0.86480712890625 +6960 0.831817626953125 +6961 0.677581787109375 +6962 0.495880126953125 +6963 0.30767822265625 +6964 0.116180419921875 +6965 -0.110748291015625 +6966 -0.381805419921875 +6967 -0.6572265625 +6968 -0.857421875 +6969 -0.870391845703125 +6970 -0.870391845703125 +6971 -0.86444091796875 +6972 -0.85723876953125 +6973 -0.790008544921875 +6974 -0.62847900390625 +6975 -0.3956298828125 +6976 -0.126708984375 +6977 0.150115966796875 +6978 0.424041748046875 +6979 0.670623779296875 +6980 0.854522705078125 +6981 0.866485595703125 +6982 0.86920166015625 +6983 0.8653564453125 +6984 0.857147216796875 +6985 0.766845703125 +6986 0.628509521484375 +6987 0.462127685546875 +6988 0.297210693359375 +6989 0.14862060546875 +6990 -0.00537109375 +6991 -0.15753173828125 +6992 -0.31304931640625 +6993 -0.48876953125 +6994 -0.6416015625 +6995 -0.751373291015625 +6996 -0.84619140625 +6997 -0.861297607421875 +6998 -0.863250732421875 +6999 -0.856597900390625 +7000 -0.7498779296875 +7001 -0.624542236328125 +7002 -0.47808837890625 +7003 -0.253387451171875 +7004 0.003692626953125 +7005 0.2257080078125 +7006 0.427154541015625 +7007 0.643218994140625 +7008 0.855926513671875 +7009 0.870361328125 +7010 0.870361328125 +7011 0.862762451171875 +7012 0.79669189453125 +7013 0.595794677734375 +7014 0.362152099609375 +7015 0.1270751953125 +7016 -0.086944580078125 +7017 -0.2784423828125 +7018 -0.484832763671875 +7019 -0.729583740234375 +7020 -0.86688232421875 +7021 -0.870391845703125 +7022 -0.86859130859375 +7023 -0.86279296875 +7024 -0.817962646484375 +7025 -0.6116943359375 +7026 -0.3128662109375 +7027 0.039398193359375 +7028 0.422821044921875 +7029 0.805145263671875 +7030 0.870361328125 +7031 0.870361328125 +7032 0.860015869140625 +7033 0.727935791015625 +7034 0.48114013671875 +7035 0.2059326171875 +7036 -0.06103515625 +7037 -0.29913330078125 +7038 -0.516204833984375 +7039 -0.7252197265625 +7040 -0.85980224609375 +7041 -0.870391845703125 +7042 -0.870391845703125 +7043 -0.858062744140625 +7044 -0.673004150390625 +7045 -0.42694091796875 +7046 -0.2100830078125 +7047 -0.0362548828125 +7048 0.10943603515625 +7049 0.23516845703125 +7050 0.373687744140625 +7051 0.517791748046875 +7052 0.602783203125 +7053 0.635711669921875 +7054 0.655181884765625 +7055 0.65948486328125 +7056 0.651275634765625 +7057 0.61846923828125 +7058 0.53753662109375 +7059 0.404144287109375 +7060 0.22186279296875 +7061 0.003997802734375 +7062 -0.22100830078125 +7063 -0.42449951171875 +7064 -0.579833984375 +7065 -0.641876220703125 +7066 -0.6177978515625 +7067 -0.575531005859375 +7068 -0.526336669921875 +7069 -0.42645263671875 +7070 -0.2581787109375 +7071 -0.068695068359375 +7072 0.09222412109375 +7073 0.232147216796875 +7074 0.3509521484375 +7075 0.410064697265625 +7076 0.372955322265625 +7077 0.2554931640625 +7078 0.10711669921875 +7079 -0.052886962890625 +7080 -0.186279296875 +7081 -0.23291015625 +7082 -0.209442138671875 +7083 -0.174163818359375 +7084 -0.126739501953125 +7085 -0.048126220703125 +7086 0.0426025390625 +7087 0.10748291015625 +7088 0.1409912109375 +7089 0.19708251953125 +7090 0.273651123046875 +7091 0.31768798828125 +7092 0.341094970703125 +7093 0.368011474609375 +7094 0.37249755859375 +7095 0.30072021484375 +7096 0.1517333984375 +7097 -0.01470947265625 +7098 -0.1883544921875 +7099 -0.372711181640625 +7100 -0.51397705078125 +7101 -0.57177734375 +7102 -0.53948974609375 +7103 -0.43511962890625 +7104 -0.2962646484375 +7105 -0.161102294921875 +7106 -0.0435791015625 +7107 0.060394287109375 +7108 0.13665771484375 +7109 0.170135498046875 +7110 0.16552734375 +7111 0.15728759765625 +7112 0.150787353515625 +7113 0.12200927734375 +7114 0.080108642578125 +7115 0.05126953125 +7116 0.062896728515625 +7117 0.09271240234375 +7118 0.092987060546875 +7119 0.07855224609375 +7120 0.06427001953125 +7121 0.0347900390625 +7122 -0.01171875 +7123 -0.056060791015625 +7124 -0.055511474609375 +7125 -0.010467529296875 +7126 0.02508544921875 +7127 0.025665283203125 +7128 0.017333984375 +7129 0.00189208984375 +7130 -0.03173828125 +7131 -0.071502685546875 +7132 -0.13543701171875 +7133 -0.219970703125 +7134 -0.300506591796875 +7135 -0.376312255859375 +7136 -0.416107177734375 +7137 -0.371124267578125 +7138 -0.242279052734375 +7139 -0.069732666015625 +7140 0.125640869140625 +7141 0.31268310546875 +7142 0.45501708984375 +7143 0.554779052734375 +7144 0.61065673828125 +7145 0.610931396484375 +7146 0.531463623046875 +7147 0.3883056640625 +7148 0.23468017578125 +7149 0.095245361328125 +7150 -0.00396728515625 +7151 -0.04852294921875 +7152 -0.055145263671875 +7153 -0.0758056640625 +7154 -0.138702392578125 +7155 -0.209197998046875 +7156 -0.289031982421875 +7157 -0.37884521484375 +7158 -0.456329345703125 +7159 -0.51641845703125 +7160 -0.519287109375 +7161 -0.458251953125 +7162 -0.384796142578125 +7163 -0.323699951171875 +7164 -0.269287109375 +7165 -0.1951904296875 +7166 -0.100006103515625 +7167 -0.01055908203125 +7168 0.1033935546875 +7169 0.24908447265625 +7170 0.373199462890625 +7171 0.45806884765625 +7172 0.511474609375 +7173 0.565399169921875 +7174 0.61138916015625 +7175 0.5897216796875 +7176 0.4906005859375 +7177 0.33148193359375 +7178 0.147796630859375 +7179 -0.01873779296875 +7180 -0.140289306640625 +7181 -0.191986083984375 +7182 -0.184295654296875 +7183 -0.161834716796875 +7184 -0.166595458984375 +7185 -0.19390869140625 +7186 -0.22442626953125 +7187 -0.279754638671875 +7188 -0.3389892578125 +7189 -0.3543701171875 +7190 -0.348175048828125 +7191 -0.32598876953125 +7192 -0.2581787109375 +7193 -0.139801025390625 +7194 0.014617919921875 +7195 0.144378662109375 +7196 0.221038818359375 +7197 0.27069091796875 +7198 0.294036865234375 +7199 0.311767578125 +7200 0.339141845703125 +7201 0.360260009765625 +7202 0.360504150390625 +7203 0.308380126953125 +7204 0.18170166015625 +7205 0.0047607421875 +7206 -0.17559814453125 +7207 -0.3143310546875 +7208 -0.36785888671875 +7209 -0.36248779296875 +7210 -0.343536376953125 +7211 -0.3018798828125 +7212 -0.231414794921875 +7213 -0.117645263671875 +7214 0.007049560546875 +7215 0.087982177734375 +7216 0.13946533203125 +7217 0.17425537109375 +7218 0.188201904296875 +7219 0.171234130859375 +7220 0.118438720703125 +7221 0.05706787109375 +7222 -0.010711669921875 +7223 -0.0914306640625 +7224 -0.162322998046875 +7225 -0.194549560546875 +7226 -0.1492919921875 +7227 -0.02166748046875 +7228 0.124053955078125 +7229 0.211151123046875 +7230 0.240447998046875 +7231 0.242218017578125 +7232 0.2257080078125 +7233 0.194366455078125 +7234 0.115509033203125 +7235 0.0128173828125 +7236 -0.053802490234375 +7237 -0.110626220703125 +7238 -0.199493408203125 +7239 -0.29437255859375 +7240 -0.33221435546875 +7241 -0.27972412109375 +7242 -0.185333251953125 +7243 -0.128204345703125 +7244 -0.115692138671875 +7245 -0.116455078125 +7246 -0.105926513671875 +7247 -0.053955078125 +7248 0.048797607421875 +7249 0.157318115234375 +7250 0.212005615234375 +7251 0.218475341796875 +7252 0.23724365234375 +7253 0.30535888671875 +7254 0.38128662109375 +7255 0.404449462890625 +7256 0.3944091796875 +7257 0.3885498046875 +7258 0.362640380859375 +7259 0.27362060546875 +7260 0.11712646484375 +7261 -0.054901123046875 +7262 -0.19085693359375 +7263 -0.28570556640625 +7264 -0.339263916015625 +7265 -0.3775634765625 +7266 -0.445709228515625 +7267 -0.535064697265625 +7268 -0.629058837890625 +7269 -0.697601318359375 +7270 -0.70391845703125 +7271 -0.6424560546875 +7272 -0.491241455078125 +7273 -0.265716552734375 +7274 -0.023712158203125 +7275 0.201751708984375 +7276 0.375823974609375 +7277 0.485076904296875 +7278 0.56884765625 +7279 0.634765625 +7280 0.63763427734375 +7281 0.5660400390625 +7282 0.4720458984375 +7283 0.40692138671875 +7284 0.3778076171875 +7285 0.376953125 +7286 0.371978759765625 +7287 0.313140869140625 +7288 0.184417724609375 +7289 0.011199951171875 +7290 -0.171051025390625 +7291 -0.33740234375 +7292 -0.47198486328125 +7293 -0.560394287109375 +7294 -0.58056640625 +7295 -0.54754638671875 +7296 -0.508575439453125 +7297 -0.459503173828125 +7298 -0.394378662109375 +7299 -0.35260009765625 +7300 -0.31170654296875 +7301 -0.197418212890625 +7302 -0.007965087890625 +7303 0.207489013671875 +7304 0.409210205078125 +7305 0.57208251953125 +7306 0.66595458984375 +7307 0.65875244140625 +7308 0.56744384765625 +7309 0.431396484375 +7310 0.29443359375 +7311 0.182464599609375 +7312 0.06365966796875 +7313 -0.075958251953125 +7314 -0.189422607421875 +7315 -0.271942138671875 +7316 -0.342529296875 +7317 -0.364166259765625 +7318 -0.327239990234375 +7319 -0.2769775390625 +7320 -0.253692626953125 +7321 -0.24365234375 +7322 -0.1983642578125 +7323 -0.116241455078125 +7324 -0.036834716796875 +7325 0.034881591796875 +7326 0.09124755859375 +7327 0.10888671875 +7328 0.125518798828125 +7329 0.15771484375 +7330 0.17828369140625 +7331 0.17108154296875 +7332 0.129974365234375 +7333 0.082427978515625 +7334 0.027679443359375 +7335 -0.065643310546875 +7336 -0.15936279296875 +7337 -0.21307373046875 +7338 -0.234649658203125 +7339 -0.2001953125 +7340 -0.119171142578125 +7341 -0.024749755859375 +7342 0.085784912109375 +7343 0.178131103515625 +7344 0.215576171875 +7345 0.211456298828125 +7346 0.17523193359375 +7347 0.128753662109375 +7348 0.1019287109375 +7349 0.0743408203125 +7350 0.04327392578125 +7351 0.038177490234375 +7352 0.076263427734375 +7353 0.14105224609375 +7354 0.186431884765625 +7355 0.188812255859375 +7356 0.1390380859375 +7357 0.041778564453125 +7358 -0.079437255859375 +7359 -0.219390869140625 +7360 -0.367828369140625 +7361 -0.494873046875 +7362 -0.556243896484375 +7363 -0.508697509765625 +7364 -0.3756103515625 +7365 -0.218902587890625 +7366 -0.063751220703125 +7367 0.091552734375 +7368 0.23602294921875 +7369 0.342987060546875 +7370 0.39520263671875 +7371 0.389373779296875 +7372 0.324249267578125 +7373 0.224090576171875 +7374 0.124267578125 +7375 0.037078857421875 +7376 -0.010101318359375 +7377 -0.019439697265625 +7378 -0.022796630859375 +7379 -0.001556396484375 +7380 0.056304931640625 +7381 0.106719970703125 +7382 0.096893310546875 +7383 0.042694091796875 +7384 -0.018035888671875 +7385 -0.07586669921875 +7386 -0.11944580078125 +7387 -0.15972900390625 +7388 -0.202606201171875 +7389 -0.24859619140625 +7390 -0.30517578125 +7391 -0.36212158203125 +7392 -0.39141845703125 +7393 -0.35528564453125 +7394 -0.249969482421875 +7395 -0.092864990234375 +7396 0.08905029296875 +7397 0.2352294921875 +7398 0.318817138671875 +7399 0.358642578125 +7400 0.347747802734375 +7401 0.28564453125 +7402 0.223175048828125 +7403 0.196746826171875 +7404 0.179840087890625 +7405 0.155548095703125 +7406 0.151214599609375 +7407 0.156951904296875 +7408 0.13177490234375 +7409 0.100799560546875 +7410 0.087127685546875 +7411 0.05487060546875 +7412 -0.009002685546875 +7413 -0.10400390625 +7414 -0.229400634765625 +7415 -0.35552978515625 +7416 -0.441925048828125 +7417 -0.473846435546875 +7418 -0.464813232421875 +7419 -0.419097900390625 +7420 -0.334320068359375 +7421 -0.227935791015625 +7422 -0.12347412109375 +7423 -0.02764892578125 +7424 0.077667236328125 +7425 0.2132568359375 +7426 0.38885498046875 +7427 0.582794189453125 +7428 0.734039306640625 +7429 0.800140380859375 +7430 0.7783203125 +7431 0.6651611328125 +7432 0.45965576171875 +7433 0.199188232421875 +7434 -0.050689697265625 +7435 -0.23297119140625 +7436 -0.33013916015625 +7437 -0.368408203125 +7438 -0.378936767578125 +7439 -0.376983642578125 +7440 -0.37969970703125 +7441 -0.391510009765625 +7442 -0.385345458984375 +7443 -0.3419189453125 +7444 -0.28289794921875 +7445 -0.251617431640625 +7446 -0.266143798828125 +7447 -0.273345947265625 +7448 -0.216796875 +7449 -0.128265380859375 +7450 -0.068145751953125 +7451 -0.0430908203125 +7452 -0.024444580078125 +7453 0.020721435546875 +7454 0.124481201171875 +7455 0.25787353515625 +7456 0.379119873046875 +7457 0.47991943359375 +7458 0.5281982421875 +7459 0.511138916015625 +7460 0.456207275390625 +7461 0.407470703125 +7462 0.383758544921875 +7463 0.35687255859375 +7464 0.31182861328125 +7465 0.250885009765625 +7466 0.1654052734375 +7467 0.035247802734375 +7468 -0.142059326171875 +7469 -0.33563232421875 +7470 -0.5345458984375 +7471 -0.72186279296875 +7472 -0.836669921875 +7473 -0.8326416015625 +7474 -0.7296142578125 +7475 -0.582550048828125 +7476 -0.440093994140625 +7477 -0.324310302734375 +7478 -0.20147705078125 +7479 -0.044647216796875 +7480 0.103973388671875 +7481 0.202392578125 +7482 0.264495849609375 +7483 0.338897705078125 +7484 0.443817138671875 +7485 0.545074462890625 +7486 0.6173095703125 +7487 0.6524658203125 +7488 0.66339111328125 +7489 0.6561279296875 +7490 0.606781005859375 +7491 0.501190185546875 +7492 0.352783203125 +7493 0.176544189453125 +7494 -0.034820556640625 +7495 -0.258209228515625 +7496 -0.44244384765625 +7497 -0.5753173828125 +7498 -0.65203857421875 +7499 -0.641632080078125 +7500 -0.562164306640625 +7501 -0.458038330078125 +7502 -0.350555419921875 +7503 -0.260528564453125 +7504 -0.192108154296875 +7505 -0.141937255859375 +7506 -0.1021728515625 +7507 -0.062896728515625 +7508 -0.011932373046875 +7509 0.062835693359375 +7510 0.148712158203125 +7511 0.241729736328125 +7512 0.34912109375 +7513 0.457305908203125 +7514 0.54388427734375 +7515 0.5728759765625 +7516 0.506591796875 +7517 0.351226806640625 +7518 0.146514892578125 +7519 -0.05523681640625 +7520 -0.21624755859375 +7521 -0.334930419921875 +7522 -0.402984619140625 +7523 -0.4412841796875 +7524 -0.49578857421875 +7525 -0.5601806640625 +7526 -0.600738525390625 +7527 -0.584228515625 +7528 -0.47930908203125 +7529 -0.27935791015625 +7530 -0.0089111328125 +7531 0.268798828125 +7532 0.482818603515625 +7533 0.60369873046875 +7534 0.650421142578125 +7535 0.66400146484375 +7536 0.6414794921875 +7537 0.572540283203125 +7538 0.498138427734375 +7539 0.439453125 +7540 0.375518798828125 +7541 0.274505615234375 +7542 0.1087646484375 +7543 -0.099395751953125 +7544 -0.3182373046875 +7545 -0.5489501953125 +7546 -0.7738037109375 +7547 -0.86383056640625 +7548 -0.870391845703125 +7549 -0.86895751953125 +7550 -0.861053466796875 +7551 -0.765869140625 +7552 -0.5301513671875 +7553 -0.214691162109375 +7554 0.137359619140625 +7555 0.474822998046875 +7556 0.76239013671875 +7557 0.867462158203125 +7558 0.870361328125 +7559 0.86480712890625 +7560 0.831817626953125 +7561 0.677581787109375 +7562 0.495880126953125 +7563 0.30767822265625 +7564 0.116180419921875 +7565 -0.110748291015625 +7566 -0.381805419921875 +7567 -0.6572265625 +7568 -0.857421875 +7569 -0.870391845703125 +7570 -0.870391845703125 +7571 -0.86444091796875 +7572 -0.85723876953125 +7573 -0.790008544921875 +7574 -0.62847900390625 +7575 -0.3956298828125 +7576 -0.126708984375 +7577 0.150115966796875 +7578 0.424041748046875 +7579 0.670623779296875 +7580 0.854522705078125 +7581 0.866485595703125 +7582 0.86920166015625 +7583 0.8653564453125 +7584 0.857147216796875 +7585 0.766845703125 +7586 0.628509521484375 +7587 0.462127685546875 +7588 0.297210693359375 +7589 0.14862060546875 +7590 -0.00537109375 +7591 -0.15753173828125 +7592 -0.31304931640625 +7593 -0.48876953125 +7594 -0.6416015625 +7595 -0.751373291015625 +7596 -0.84619140625 +7597 -0.861297607421875 +7598 -0.863250732421875 +7599 -0.856597900390625 +7600 -0.7498779296875 +7601 -0.624542236328125 +7602 -0.47808837890625 +7603 -0.253387451171875 +7604 0.003692626953125 +7605 0.2257080078125 +7606 0.427154541015625 +7607 0.643218994140625 +7608 0.855926513671875 +7609 0.870361328125 +7610 0.870361328125 +7611 0.862762451171875 +7612 0.79669189453125 +7613 0.595794677734375 +7614 0.362152099609375 +7615 0.1270751953125 +7616 -0.086944580078125 +7617 -0.2784423828125 +7618 -0.484832763671875 +7619 -0.729583740234375 +7620 -0.86688232421875 +7621 -0.870391845703125 +7622 -0.86859130859375 +7623 -0.86279296875 +7624 -0.817962646484375 +7625 -0.6116943359375 +7626 -0.3128662109375 +7627 0.039398193359375 +7628 0.422821044921875 +7629 0.805145263671875 +7630 0.870361328125 +7631 0.870361328125 +7632 0.860015869140625 +7633 0.727935791015625 +7634 0.48114013671875 +7635 0.2059326171875 +7636 -0.06103515625 +7637 -0.29913330078125 +7638 -0.516204833984375 +7639 -0.7252197265625 +7640 -0.85980224609375 +7641 -0.870391845703125 +7642 -0.870391845703125 +7643 -0.858062744140625 +7644 -0.673004150390625 +7645 -0.42694091796875 +7646 -0.2100830078125 +7647 -0.0362548828125 +7648 0.10943603515625 +7649 0.23516845703125 +7650 0.373687744140625 +7651 0.517791748046875 +7652 0.602783203125 +7653 0.635711669921875 +7654 0.655181884765625 +7655 0.65948486328125 +7656 0.651275634765625 +7657 0.61846923828125 +7658 0.53753662109375 +7659 0.404144287109375 +7660 0.22186279296875 +7661 0.003997802734375 +7662 -0.22100830078125 +7663 -0.42449951171875 +7664 -0.579833984375 +7665 -0.641876220703125 +7666 -0.6177978515625 +7667 -0.575531005859375 +7668 -0.526336669921875 +7669 -0.42645263671875 +7670 -0.2581787109375 +7671 -0.068695068359375 +7672 0.09222412109375 +7673 0.232147216796875 +7674 0.3509521484375 +7675 0.410064697265625 +7676 0.372955322265625 +7677 0.2554931640625 +7678 0.10711669921875 +7679 -0.052886962890625 +7680 -0.186279296875 +7681 -0.23291015625 +7682 -0.209442138671875 +7683 -0.174163818359375 +7684 -0.126739501953125 +7685 -0.048126220703125 +7686 0.0426025390625 +7687 0.10748291015625 +7688 0.1409912109375 +7689 0.19708251953125 +7690 0.273651123046875 +7691 0.31768798828125 +7692 0.341094970703125 +7693 0.368011474609375 +7694 0.37249755859375 +7695 0.30072021484375 +7696 0.1517333984375 +7697 -0.01470947265625 +7698 -0.1883544921875 +7699 -0.372711181640625 +7700 -0.51397705078125 +7701 -0.57177734375 +7702 -0.53948974609375 +7703 -0.43511962890625 +7704 -0.2962646484375 +7705 -0.161102294921875 +7706 -0.0435791015625 +7707 0.060394287109375 +7708 0.13665771484375 +7709 0.170135498046875 +7710 0.16552734375 +7711 0.15728759765625 +7712 0.150787353515625 +7713 0.12200927734375 +7714 0.080108642578125 +7715 0.05126953125 +7716 0.062896728515625 +7717 0.09271240234375 +7718 0.092987060546875 +7719 0.07855224609375 +7720 0.06427001953125 +7721 0.0347900390625 +7722 -0.01171875 +7723 -0.056060791015625 +7724 -0.055511474609375 +7725 -0.010467529296875 +7726 0.02508544921875 +7727 0.025665283203125 +7728 0.017333984375 +7729 0.00189208984375 +7730 -0.03173828125 +7731 -0.071502685546875 +7732 -0.13543701171875 +7733 -0.219970703125 +7734 -0.300506591796875 +7735 -0.376312255859375 +7736 -0.416107177734375 +7737 -0.371124267578125 +7738 -0.242279052734375 +7739 -0.069732666015625 +7740 0.125640869140625 +7741 0.31268310546875 +7742 0.45501708984375 +7743 0.554779052734375 +7744 0.61065673828125 +7745 0.610931396484375 +7746 0.531463623046875 +7747 0.3883056640625 +7748 0.23468017578125 +7749 0.095245361328125 +7750 -0.00396728515625 +7751 -0.04852294921875 +7752 -0.055145263671875 +7753 -0.0758056640625 +7754 -0.138702392578125 +7755 -0.209197998046875 +7756 -0.289031982421875 +7757 -0.37884521484375 +7758 -0.456329345703125 +7759 -0.51641845703125 +7760 -0.519287109375 +7761 -0.458251953125 +7762 -0.384796142578125 +7763 -0.323699951171875 +7764 -0.269287109375 +7765 -0.1951904296875 +7766 -0.100006103515625 +7767 -0.01055908203125 +7768 0.1033935546875 +7769 0.24908447265625 +7770 0.373199462890625 +7771 0.45806884765625 +7772 0.511474609375 +7773 0.565399169921875 +7774 0.61138916015625 +7775 0.5897216796875 +7776 0.4906005859375 +7777 0.33148193359375 +7778 0.147796630859375 +7779 -0.01873779296875 +7780 -0.140289306640625 +7781 -0.191986083984375 +7782 -0.184295654296875 +7783 -0.161834716796875 +7784 -0.166595458984375 +7785 -0.19390869140625 +7786 -0.22442626953125 +7787 -0.279754638671875 +7788 -0.3389892578125 +7789 -0.3543701171875 +7790 -0.348175048828125 +7791 -0.32598876953125 +7792 -0.2581787109375 +7793 -0.139801025390625 +7794 0.014617919921875 +7795 0.144378662109375 +7796 0.221038818359375 +7797 0.27069091796875 +7798 0.294036865234375 +7799 0.311767578125 +7800 0.339141845703125 +7801 0.360260009765625 +7802 0.360504150390625 +7803 0.308380126953125 +7804 0.18170166015625 +7805 0.0047607421875 +7806 -0.17559814453125 +7807 -0.3143310546875 +7808 -0.36785888671875 +7809 -0.36248779296875 +7810 -0.343536376953125 +7811 -0.3018798828125 +7812 -0.231414794921875 +7813 -0.117645263671875 +7814 0.007049560546875 +7815 0.087982177734375 +7816 0.13946533203125 +7817 0.17425537109375 +7818 0.188201904296875 +7819 0.171234130859375 +7820 0.118438720703125 +7821 0.05706787109375 +7822 -0.010711669921875 +7823 -0.0914306640625 +7824 -0.162322998046875 +7825 -0.194549560546875 +7826 -0.1492919921875 +7827 -0.02166748046875 +7828 0.124053955078125 +7829 0.211151123046875 +7830 0.240447998046875 +7831 0.242218017578125 +7832 0.2257080078125 +7833 0.194366455078125 +7834 0.115509033203125 +7835 0.0128173828125 +7836 -0.053802490234375 +7837 -0.110626220703125 +7838 -0.199493408203125 +7839 -0.29437255859375 +7840 -0.33221435546875 +7841 -0.27972412109375 +7842 -0.185333251953125 +7843 -0.128204345703125 +7844 -0.115692138671875 +7845 -0.116455078125 +7846 -0.105926513671875 +7847 -0.053955078125 +7848 0.048797607421875 +7849 0.157318115234375 +7850 0.212005615234375 +7851 0.218475341796875 +7852 0.23724365234375 +7853 0.30535888671875 +7854 0.38128662109375 +7855 0.404449462890625 +7856 0.3944091796875 +7857 0.3885498046875 +7858 0.362640380859375 +7859 0.27362060546875 +7860 0.11712646484375 +7861 -0.054901123046875 +7862 -0.19085693359375 +7863 -0.28570556640625 +7864 -0.339263916015625 +7865 -0.3775634765625 +7866 -0.445709228515625 +7867 -0.535064697265625 +7868 -0.629058837890625 +7869 -0.697601318359375 +7870 -0.70391845703125 +7871 -0.6424560546875 +7872 -0.491241455078125 +7873 -0.265716552734375 +7874 -0.023712158203125 +7875 0.201751708984375 +7876 0.375823974609375 +7877 0.485076904296875 +7878 0.56884765625 +7879 0.634765625 +7880 0.63763427734375 +7881 0.5660400390625 +7882 0.4720458984375 +7883 0.40692138671875 +7884 0.3778076171875 +7885 0.376953125 +7886 0.371978759765625 +7887 0.313140869140625 +7888 0.184417724609375 +7889 0.011199951171875 +7890 -0.171051025390625 +7891 -0.33740234375 +7892 -0.47198486328125 +7893 -0.560394287109375 +7894 -0.58056640625 +7895 -0.54754638671875 +7896 -0.508575439453125 +7897 -0.459503173828125 +7898 -0.394378662109375 +7899 -0.35260009765625 +7900 -0.31170654296875 +7901 -0.197418212890625 +7902 -0.007965087890625 +7903 0.207489013671875 +7904 0.409210205078125 +7905 0.57208251953125 +7906 0.66595458984375 +7907 0.65875244140625 +7908 0.56744384765625 +7909 0.431396484375 +7910 0.29443359375 +7911 0.182464599609375 +7912 0.06365966796875 +7913 -0.075958251953125 +7914 -0.189422607421875 +7915 -0.271942138671875 +7916 -0.342529296875 +7917 -0.364166259765625 +7918 -0.327239990234375 +7919 -0.2769775390625 +7920 -0.253692626953125 +7921 -0.24365234375 +7922 -0.1983642578125 +7923 -0.116241455078125 +7924 -0.036834716796875 +7925 0.034881591796875 +7926 0.09124755859375 +7927 0.10888671875 +7928 0.125518798828125 +7929 0.15771484375 +7930 0.17828369140625 +7931 0.17108154296875 +7932 0.129974365234375 +7933 0.082427978515625 +7934 0.027679443359375 +7935 -0.065643310546875 +7936 -0.15936279296875 +7937 -0.21307373046875 +7938 -0.234649658203125 +7939 -0.2001953125 +7940 -0.119171142578125 +7941 -0.024749755859375 +7942 0.085784912109375 +7943 0.178131103515625 +7944 0.215576171875 +7945 0.211456298828125 +7946 0.17523193359375 +7947 0.128753662109375 +7948 0.1019287109375 +7949 0.0743408203125 +7950 0.04327392578125 +7951 0.038177490234375 +7952 0.076263427734375 +7953 0.14105224609375 +7954 0.186431884765625 +7955 0.188812255859375 +7956 0.1390380859375 +7957 0.041778564453125 +7958 -0.079437255859375 +7959 -0.219390869140625 +7960 -0.367828369140625 +7961 -0.494873046875 +7962 -0.556243896484375 +7963 -0.508697509765625 +7964 -0.3756103515625 +7965 -0.218902587890625 +7966 -0.063751220703125 +7967 0.091552734375 +7968 0.23602294921875 +7969 0.342987060546875 +7970 0.39520263671875 +7971 0.389373779296875 +7972 0.324249267578125 +7973 0.224090576171875 +7974 0.124267578125 +7975 0.037078857421875 +7976 -0.010101318359375 +7977 -0.019439697265625 +7978 -0.022796630859375 +7979 -0.001556396484375 +7980 0.056304931640625 +7981 0.106719970703125 +7982 0.096893310546875 +7983 0.042694091796875 +7984 -0.018035888671875 +7985 -0.07586669921875 +7986 -0.11944580078125 +7987 -0.15972900390625 +7988 -0.202606201171875 +7989 -0.24859619140625 +7990 -0.30517578125 +7991 -0.36212158203125 +7992 -0.39141845703125 +7993 -0.35528564453125 +7994 -0.249969482421875 +7995 -0.092864990234375 +7996 0.08905029296875 +7997 0.2352294921875 +7998 0.318817138671875 +7999 0.358642578125 +8000 0.347747802734375 +8001 0.28564453125 +8002 0.223175048828125 +8003 0.196746826171875 +8004 0.179840087890625 +8005 0.155548095703125 +8006 0.151214599609375 +8007 0.156951904296875 +8008 0.13177490234375 +8009 0.100799560546875 +8010 0.087127685546875 +8011 0.05487060546875 +8012 -0.009002685546875 +8013 -0.10400390625 +8014 -0.229400634765625 +8015 -0.35552978515625 +8016 -0.441925048828125 +8017 -0.473846435546875 +8018 -0.464813232421875 +8019 -0.419097900390625 +8020 -0.334320068359375 +8021 -0.227935791015625 +8022 -0.12347412109375 +8023 -0.02764892578125 +8024 0.077667236328125 +8025 0.2132568359375 +8026 0.38885498046875 +8027 0.582794189453125 +8028 0.734039306640625 +8029 0.800140380859375 +8030 0.7783203125 +8031 0.6651611328125 +8032 0.45965576171875 +8033 0.199188232421875 +8034 -0.050689697265625 +8035 -0.23297119140625 +8036 -0.33013916015625 +8037 -0.368408203125 +8038 -0.378936767578125 +8039 -0.376983642578125 +8040 -0.37969970703125 +8041 -0.391510009765625 +8042 -0.385345458984375 +8043 -0.3419189453125 +8044 -0.28289794921875 +8045 -0.251617431640625 +8046 -0.266143798828125 +8047 -0.273345947265625 +8048 -0.216796875 +8049 -0.128265380859375 +8050 -0.068145751953125 +8051 -0.0430908203125 +8052 -0.024444580078125 +8053 0.020721435546875 +8054 0.124481201171875 +8055 0.25787353515625 +8056 0.379119873046875 +8057 0.47991943359375 +8058 0.5281982421875 +8059 0.511138916015625 +8060 0.456207275390625 +8061 0.407470703125 +8062 0.383758544921875 +8063 0.35687255859375 +8064 0.31182861328125 +8065 0.250885009765625 +8066 0.1654052734375 +8067 0.035247802734375 +8068 -0.142059326171875 +8069 -0.33563232421875 +8070 -0.5345458984375 +8071 -0.72186279296875 +8072 -0.836669921875 +8073 -0.8326416015625 +8074 -0.7296142578125 +8075 -0.582550048828125 +8076 -0.440093994140625 +8077 -0.324310302734375 +8078 -0.20147705078125 +8079 -0.044647216796875 +8080 0.103973388671875 +8081 0.202392578125 +8082 0.264495849609375 +8083 0.338897705078125 +8084 0.443817138671875 +8085 0.545074462890625 +8086 0.6173095703125 +8087 0.6524658203125 +8088 0.66339111328125 +8089 0.6561279296875 +8090 0.606781005859375 +8091 0.501190185546875 +8092 0.352783203125 +8093 0.176544189453125 +8094 -0.034820556640625 +8095 -0.258209228515625 +8096 -0.44244384765625 +8097 -0.5753173828125 +8098 -0.65203857421875 +8099 -0.641632080078125 +8100 -0.562164306640625 +8101 -0.458038330078125 +8102 -0.350555419921875 +8103 -0.260528564453125 +8104 -0.192108154296875 +8105 -0.141937255859375 +8106 -0.1021728515625 +8107 -0.062896728515625 +8108 -0.011932373046875 +8109 0.062835693359375 +8110 0.148712158203125 +8111 0.241729736328125 +8112 0.34912109375 +8113 0.457305908203125 +8114 0.54388427734375 +8115 0.5728759765625 +8116 0.506591796875 +8117 0.351226806640625 +8118 0.146514892578125 +8119 -0.05523681640625 +8120 -0.21624755859375 +8121 -0.334930419921875 +8122 -0.402984619140625 +8123 -0.4412841796875 +8124 -0.49578857421875 +8125 -0.5601806640625 +8126 -0.600738525390625 +8127 -0.584228515625 +8128 -0.47930908203125 +8129 -0.27935791015625 +8130 -0.0089111328125 +8131 0.268798828125 +8132 0.482818603515625 +8133 0.60369873046875 +8134 0.650421142578125 +8135 0.66400146484375 +8136 0.6414794921875 +8137 0.572540283203125 +8138 0.498138427734375 +8139 0.439453125 +8140 0.375518798828125 +8141 0.274505615234375 +8142 0.1087646484375 +8143 -0.099395751953125 +8144 -0.3182373046875 +8145 -0.5489501953125 +8146 -0.7738037109375 +8147 -0.86383056640625 +8148 -0.870391845703125 +8149 -0.86895751953125 +8150 -0.861053466796875 +8151 -0.765869140625 +8152 -0.5301513671875 +8153 -0.214691162109375 +8154 0.137359619140625 +8155 0.474822998046875 +8156 0.76239013671875 +8157 0.867462158203125 +8158 0.870361328125 +8159 0.86480712890625 +8160 0.831817626953125 +8161 0.677581787109375 +8162 0.495880126953125 +8163 0.30767822265625 +8164 0.116180419921875 +8165 -0.110748291015625 +8166 -0.381805419921875 +8167 -0.6572265625 +8168 -0.857421875 +8169 -0.870391845703125 +8170 -0.870391845703125 +8171 -0.86444091796875 +8172 -0.85723876953125 +8173 -0.790008544921875 +8174 -0.62847900390625 +8175 -0.3956298828125 +8176 -0.126708984375 +8177 0.150115966796875 +8178 0.424041748046875 +8179 0.670623779296875 +8180 0.854522705078125 +8181 0.866485595703125 +8182 0.86920166015625 +8183 0.8653564453125 +8184 0.857147216796875 +8185 0.766845703125 +8186 0.628509521484375 +8187 0.462127685546875 +8188 0.297210693359375 +8189 0.14862060546875 +8190 -0.00537109375 +8191 -0.15753173828125 +8192 -0.31304931640625 +8193 -0.48876953125 +8194 -0.6416015625 +8195 -0.751373291015625 +8196 -0.84619140625 +8197 -0.861297607421875 +8198 -0.863250732421875 +8199 -0.856597900390625 +8200 -0.7498779296875 +8201 -0.624542236328125 +8202 -0.47808837890625 +8203 -0.253387451171875 +8204 0.003692626953125 +8205 0.2257080078125 +8206 0.427154541015625 +8207 0.643218994140625 +8208 0.855926513671875 +8209 0.870361328125 +8210 0.870361328125 +8211 0.862762451171875 +8212 0.79669189453125 +8213 0.595794677734375 +8214 0.362152099609375 +8215 0.1270751953125 +8216 -0.086944580078125 +8217 -0.2784423828125 +8218 -0.484832763671875 +8219 -0.729583740234375 +8220 -0.86688232421875 +8221 -0.870391845703125 +8222 -0.86859130859375 +8223 -0.86279296875 +8224 -0.817962646484375 +8225 -0.6116943359375 +8226 -0.3128662109375 +8227 0.039398193359375 +8228 0.422821044921875 +8229 0.805145263671875 +8230 0.870361328125 +8231 0.870361328125 +8232 0.860015869140625 +8233 0.727935791015625 +8234 0.48114013671875 +8235 0.2059326171875 +8236 -0.06103515625 +8237 -0.29913330078125 +8238 -0.516204833984375 +8239 -0.7252197265625 +8240 -0.85980224609375 +8241 -0.870391845703125 +8242 -0.870391845703125 +8243 -0.858062744140625 +8244 -0.673004150390625 +8245 -0.42694091796875 +8246 -0.2100830078125 +8247 -0.0362548828125 +8248 0.10943603515625 +8249 0.23516845703125 +8250 0.373687744140625 +8251 0.517791748046875 +8252 0.602783203125 +8253 0.635711669921875 +8254 0.655181884765625 +8255 0.65948486328125 +8256 0.651275634765625 +8257 0.61846923828125 +8258 0.53753662109375 +8259 0.404144287109375 +8260 0.22186279296875 +8261 0.003997802734375 +8262 -0.22100830078125 +8263 -0.42449951171875 +8264 -0.579833984375 +8265 -0.641876220703125 +8266 -0.6177978515625 +8267 -0.575531005859375 +8268 -0.526336669921875 +8269 -0.42645263671875 +8270 -0.2581787109375 +8271 -0.068695068359375 +8272 0.09222412109375 +8273 0.232147216796875 +8274 0.3509521484375 +8275 0.410064697265625 +8276 0.372955322265625 +8277 0.2554931640625 +8278 0.10711669921875 +8279 -0.052886962890625 +8280 -0.186279296875 +8281 -0.23291015625 +8282 -0.209442138671875 +8283 -0.174163818359375 +8284 -0.126739501953125 +8285 -0.048126220703125 +8286 0.0426025390625 +8287 0.10748291015625 +8288 0.1409912109375 +8289 0.19708251953125 +8290 0.273651123046875 +8291 0.31768798828125 +8292 0.341094970703125 +8293 0.368011474609375 +8294 0.37249755859375 +8295 0.30072021484375 +8296 0.1517333984375 +8297 -0.01470947265625 +8298 -0.1883544921875 +8299 -0.372711181640625 +8300 -0.51397705078125 +8301 -0.57177734375 +8302 -0.53948974609375 +8303 -0.43511962890625 +8304 -0.2962646484375 +8305 -0.161102294921875 +8306 -0.0435791015625 +8307 0.060394287109375 +8308 0.13665771484375 +8309 0.170135498046875 +8310 0.16552734375 +8311 0.15728759765625 +8312 0.150787353515625 +8313 0.12200927734375 +8314 0.080108642578125 +8315 0.05126953125 +8316 0.062896728515625 +8317 0.09271240234375 +8318 0.092987060546875 +8319 0.07855224609375 +8320 0.06427001953125 +8321 0.0347900390625 +8322 -0.01171875 +8323 -0.056060791015625 +8324 -0.055511474609375 +8325 -0.010467529296875 +8326 0.02508544921875 +8327 0.025665283203125 +8328 0.017333984375 +8329 0.00189208984375 +8330 -0.03173828125 +8331 -0.071502685546875 +8332 -0.13543701171875 +8333 -0.219970703125 +8334 -0.300506591796875 +8335 -0.376312255859375 +8336 -0.416107177734375 +8337 -0.371124267578125 +8338 -0.242279052734375 +8339 -0.069732666015625 +8340 0.125640869140625 +8341 0.31268310546875 +8342 0.45501708984375 +8343 0.554779052734375 +8344 0.61065673828125 +8345 0.610931396484375 +8346 0.531463623046875 +8347 0.3883056640625 +8348 0.23468017578125 +8349 0.095245361328125 +8350 -0.00396728515625 +8351 -0.04852294921875 +8352 -0.055145263671875 +8353 -0.0758056640625 +8354 -0.138702392578125 +8355 -0.209197998046875 +8356 -0.289031982421875 +8357 -0.37884521484375 +8358 -0.456329345703125 +8359 -0.51641845703125 +8360 -0.519287109375 +8361 -0.458251953125 +8362 -0.384796142578125 +8363 -0.323699951171875 +8364 -0.269287109375 +8365 -0.1951904296875 +8366 -0.100006103515625 +8367 -0.01055908203125 +8368 0.1033935546875 +8369 0.24908447265625 +8370 0.373199462890625 +8371 0.45806884765625 +8372 0.511474609375 +8373 0.565399169921875 +8374 0.61138916015625 +8375 0.5897216796875 +8376 0.4906005859375 +8377 0.33148193359375 +8378 0.147796630859375 +8379 -0.01873779296875 +8380 -0.140289306640625 +8381 -0.191986083984375 +8382 -0.184295654296875 +8383 -0.161834716796875 +8384 -0.166595458984375 +8385 -0.19390869140625 +8386 -0.22442626953125 +8387 -0.279754638671875 +8388 -0.3389892578125 +8389 -0.3543701171875 +8390 -0.348175048828125 +8391 -0.32598876953125 +8392 -0.2581787109375 +8393 -0.139801025390625 +8394 0.014617919921875 +8395 0.144378662109375 +8396 0.221038818359375 +8397 0.27069091796875 +8398 0.294036865234375 +8399 0.311767578125 +8400 0.339141845703125 +8401 0.360260009765625 +8402 0.360504150390625 +8403 0.308380126953125 +8404 0.18170166015625 +8405 0.0047607421875 +8406 -0.17559814453125 +8407 -0.3143310546875 +8408 -0.36785888671875 +8409 -0.36248779296875 +8410 -0.343536376953125 +8411 -0.3018798828125 +8412 -0.231414794921875 +8413 -0.117645263671875 +8414 0.007049560546875 +8415 0.087982177734375 +8416 0.13946533203125 +8417 0.17425537109375 +8418 0.188201904296875 +8419 0.171234130859375 +8420 0.118438720703125 +8421 0.05706787109375 +8422 -0.010711669921875 +8423 -0.0914306640625 +8424 -0.162322998046875 +8425 -0.194549560546875 +8426 -0.1492919921875 +8427 -0.02166748046875 +8428 0.124053955078125 +8429 0.211151123046875 +8430 0.240447998046875 +8431 0.242218017578125 +8432 0.2257080078125 +8433 0.194366455078125 +8434 0.115509033203125 +8435 0.0128173828125 +8436 -0.053802490234375 +8437 -0.110626220703125 +8438 -0.199493408203125 +8439 -0.29437255859375 +8440 -0.33221435546875 +8441 -0.27972412109375 +8442 -0.185333251953125 +8443 -0.128204345703125 +8444 -0.115692138671875 +8445 -0.116455078125 +8446 -0.105926513671875 +8447 -0.053955078125 +8448 0.048797607421875 +8449 0.157318115234375 +8450 0.212005615234375 +8451 0.218475341796875 +8452 0.23724365234375 +8453 0.30535888671875 +8454 0.38128662109375 +8455 0.404449462890625 +8456 0.3944091796875 +8457 0.3885498046875 +8458 0.362640380859375 +8459 0.27362060546875 +8460 0.11712646484375 +8461 -0.054901123046875 +8462 -0.19085693359375 +8463 -0.28570556640625 +8464 -0.339263916015625 +8465 -0.3775634765625 +8466 -0.445709228515625 +8467 -0.535064697265625 +8468 -0.629058837890625 +8469 -0.697601318359375 +8470 -0.70391845703125 +8471 -0.6424560546875 +8472 -0.491241455078125 +8473 -0.265716552734375 +8474 -0.023712158203125 +8475 0.201751708984375 +8476 0.375823974609375 +8477 0.485076904296875 +8478 0.56884765625 +8479 0.634765625 +8480 0.63763427734375 +8481 0.5660400390625 +8482 0.4720458984375 +8483 0.40692138671875 +8484 0.3778076171875 +8485 0.376953125 +8486 0.371978759765625 +8487 0.313140869140625 +8488 0.184417724609375 +8489 0.011199951171875 +8490 -0.171051025390625 +8491 -0.33740234375 +8492 -0.47198486328125 +8493 -0.560394287109375 +8494 -0.58056640625 +8495 -0.54754638671875 +8496 -0.508575439453125 +8497 -0.459503173828125 +8498 -0.394378662109375 +8499 -0.35260009765625 +8500 -0.31170654296875 +8501 -0.197418212890625 +8502 -0.007965087890625 +8503 0.207489013671875 +8504 0.409210205078125 +8505 0.57208251953125 +8506 0.66595458984375 +8507 0.65875244140625 +8508 0.56744384765625 +8509 0.431396484375 +8510 0.29443359375 +8511 0.182464599609375 +8512 0.06365966796875 +8513 -0.075958251953125 +8514 -0.189422607421875 +8515 -0.271942138671875 +8516 -0.342529296875 +8517 -0.364166259765625 +8518 -0.327239990234375 +8519 -0.2769775390625 +8520 -0.253692626953125 +8521 -0.24365234375 +8522 -0.1983642578125 +8523 -0.116241455078125 +8524 -0.036834716796875 +8525 0.034881591796875 +8526 0.09124755859375 +8527 0.10888671875 +8528 0.125518798828125 +8529 0.15771484375 +8530 0.17828369140625 +8531 0.17108154296875 +8532 0.129974365234375 +8533 0.082427978515625 +8534 0.027679443359375 +8535 -0.065643310546875 +8536 -0.15936279296875 +8537 -0.21307373046875 +8538 -0.234649658203125 +8539 -0.2001953125 +8540 -0.119171142578125 +8541 -0.024749755859375 +8542 0.085784912109375 +8543 0.178131103515625 +8544 0.215576171875 +8545 0.211456298828125 +8546 0.17523193359375 +8547 0.128753662109375 +8548 0.1019287109375 +8549 0.0743408203125 +8550 0.04327392578125 +8551 0.038177490234375 +8552 0.076263427734375 +8553 0.14105224609375 +8554 0.186431884765625 +8555 0.188812255859375 +8556 0.1390380859375 +8557 0.041778564453125 +8558 -0.079437255859375 +8559 -0.219390869140625 +8560 -0.367828369140625 +8561 -0.494873046875 +8562 -0.556243896484375 +8563 -0.508697509765625 +8564 -0.3756103515625 +8565 -0.218902587890625 +8566 -0.063751220703125 +8567 0.091552734375 +8568 0.23602294921875 +8569 0.342987060546875 +8570 0.39520263671875 +8571 0.389373779296875 +8572 0.324249267578125 +8573 0.224090576171875 +8574 0.124267578125 +8575 0.037078857421875 +8576 -0.010101318359375 +8577 -0.019439697265625 +8578 -0.022796630859375 +8579 -0.001556396484375 +8580 0.056304931640625 +8581 0.106719970703125 +8582 0.096893310546875 +8583 0.042694091796875 +8584 -0.018035888671875 +8585 -0.07586669921875 +8586 -0.11944580078125 +8587 -0.15972900390625 +8588 -0.202606201171875 +8589 -0.24859619140625 +8590 -0.30517578125 +8591 -0.36212158203125 +8592 -0.39141845703125 +8593 -0.35528564453125 +8594 -0.249969482421875 +8595 -0.092864990234375 +8596 0.08905029296875 +8597 0.2352294921875 +8598 0.318817138671875 +8599 0.358642578125 +8600 0.347747802734375 +8601 0.28564453125 +8602 0.223175048828125 +8603 0.196746826171875 +8604 0.179840087890625 +8605 0.155548095703125 +8606 0.151214599609375 +8607 0.156951904296875 +8608 0.13177490234375 +8609 0.100799560546875 +8610 0.087127685546875 +8611 0.05487060546875 +8612 -0.009002685546875 +8613 -0.10400390625 +8614 -0.229400634765625 +8615 -0.35552978515625 +8616 -0.441925048828125 +8617 -0.473846435546875 +8618 -0.464813232421875 +8619 -0.419097900390625 +8620 -0.334320068359375 +8621 -0.227935791015625 +8622 -0.12347412109375 +8623 -0.02764892578125 +8624 0.077667236328125 +8625 0.2132568359375 +8626 0.38885498046875 +8627 0.582794189453125 +8628 0.734039306640625 +8629 0.800140380859375 +8630 0.7783203125 +8631 0.6651611328125 +8632 0.45965576171875 +8633 0.199188232421875 +8634 -0.050689697265625 +8635 -0.23297119140625 +8636 -0.33013916015625 +8637 -0.368408203125 +8638 -0.378936767578125 +8639 -0.376983642578125 +8640 -0.37969970703125 +8641 -0.391510009765625 +8642 -0.385345458984375 +8643 -0.3419189453125 +8644 -0.28289794921875 +8645 -0.251617431640625 +8646 -0.266143798828125 +8647 -0.273345947265625 +8648 -0.216796875 +8649 -0.128265380859375 +8650 -0.068145751953125 +8651 -0.0430908203125 +8652 -0.024444580078125 +8653 0.020721435546875 +8654 0.124481201171875 +8655 0.25787353515625 +8656 0.379119873046875 +8657 0.47991943359375 +8658 0.5281982421875 +8659 0.511138916015625 +8660 0.456207275390625 +8661 0.407470703125 +8662 0.383758544921875 +8663 0.35687255859375 +8664 0.31182861328125 +8665 0.250885009765625 +8666 0.1654052734375 +8667 0.035247802734375 +8668 -0.142059326171875 +8669 -0.33563232421875 +8670 -0.5345458984375 +8671 -0.72186279296875 +8672 -0.836669921875 +8673 -0.8326416015625 +8674 -0.7296142578125 +8675 -0.582550048828125 +8676 -0.440093994140625 +8677 -0.324310302734375 +8678 -0.20147705078125 +8679 -0.044647216796875 +8680 0.103973388671875 +8681 0.202392578125 +8682 0.264495849609375 +8683 0.338897705078125 +8684 0.443817138671875 +8685 0.545074462890625 +8686 0.6173095703125 +8687 0.6524658203125 +8688 0.66339111328125 +8689 0.6561279296875 +8690 0.606781005859375 +8691 0.501190185546875 +8692 0.352783203125 +8693 0.176544189453125 +8694 -0.034820556640625 +8695 -0.258209228515625 +8696 -0.44244384765625 +8697 -0.5753173828125 +8698 -0.65203857421875 +8699 -0.641632080078125 +8700 -0.562164306640625 +8701 -0.458038330078125 +8702 -0.350555419921875 +8703 -0.260528564453125 +8704 -0.192108154296875 +8705 -0.141937255859375 +8706 -0.1021728515625 +8707 -0.062896728515625 +8708 -0.011932373046875 +8709 0.062835693359375 +8710 0.148712158203125 +8711 0.241729736328125 +8712 0.34912109375 +8713 0.457305908203125 +8714 0.54388427734375 +8715 0.5728759765625 +8716 0.506591796875 +8717 0.351226806640625 +8718 0.146514892578125 +8719 -0.05523681640625 +8720 -0.21624755859375 +8721 -0.334930419921875 +8722 -0.402984619140625 +8723 -0.4412841796875 +8724 -0.49578857421875 +8725 -0.5601806640625 +8726 -0.600738525390625 +8727 -0.584228515625 +8728 -0.47930908203125 +8729 -0.27935791015625 +8730 -0.0089111328125 +8731 0.268798828125 +8732 0.482818603515625 +8733 0.60369873046875 +8734 0.650421142578125 +8735 0.66400146484375 +8736 0.6414794921875 +8737 0.572540283203125 +8738 0.498138427734375 +8739 0.439453125 +8740 0.375518798828125 +8741 0.274505615234375 +8742 0.1087646484375 +8743 -0.099395751953125 +8744 -0.3182373046875 +8745 -0.5489501953125 +8746 -0.7738037109375 +8747 -0.86383056640625 +8748 -0.870391845703125 +8749 -0.86895751953125 +8750 -0.861053466796875 +8751 -0.765869140625 +8752 -0.5301513671875 +8753 -0.214691162109375 +8754 0.137359619140625 +8755 0.474822998046875 +8756 0.76239013671875 +8757 0.867462158203125 +8758 0.870361328125 +8759 0.86480712890625 +8760 0.831817626953125 +8761 0.677581787109375 +8762 0.495880126953125 +8763 0.30767822265625 +8764 0.116180419921875 +8765 -0.110748291015625 +8766 -0.381805419921875 +8767 -0.6572265625 +8768 -0.857421875 +8769 -0.870391845703125 +8770 -0.870391845703125 +8771 -0.86444091796875 +8772 -0.85723876953125 +8773 -0.790008544921875 +8774 -0.62847900390625 +8775 -0.3956298828125 +8776 -0.126708984375 +8777 0.150115966796875 +8778 0.424041748046875 +8779 0.670623779296875 +8780 0.854522705078125 +8781 0.866485595703125 +8782 0.86920166015625 +8783 0.8653564453125 +8784 0.857147216796875 +8785 0.766845703125 +8786 0.628509521484375 +8787 0.462127685546875 +8788 0.297210693359375 +8789 0.14862060546875 +8790 -0.00537109375 +8791 -0.15753173828125 +8792 -0.31304931640625 +8793 -0.48876953125 +8794 -0.6416015625 +8795 -0.751373291015625 +8796 -0.84619140625 +8797 -0.861297607421875 +8798 -0.863250732421875 +8799 -0.856597900390625 +8800 -0.7498779296875 +8801 -0.624542236328125 +8802 -0.47808837890625 +8803 -0.253387451171875 +8804 0.003692626953125 +8805 0.2257080078125 +8806 0.427154541015625 +8807 0.643218994140625 +8808 0.855926513671875 +8809 0.870361328125 +8810 0.870361328125 +8811 0.862762451171875 +8812 0.79669189453125 +8813 0.595794677734375 +8814 0.362152099609375 +8815 0.1270751953125 +8816 -0.086944580078125 +8817 -0.2784423828125 +8818 -0.484832763671875 +8819 -0.729583740234375 +8820 -0.86688232421875 +8821 -0.870391845703125 +8822 -0.86859130859375 +8823 -0.86279296875 +8824 -0.817962646484375 +8825 -0.6116943359375 +8826 -0.3128662109375 +8827 0.039398193359375 +8828 0.422821044921875 +8829 0.805145263671875 +8830 0.870361328125 +8831 0.870361328125 +8832 0.860015869140625 +8833 0.727935791015625 +8834 0.48114013671875 +8835 0.2059326171875 +8836 -0.06103515625 +8837 -0.29913330078125 +8838 -0.516204833984375 +8839 -0.7252197265625 +8840 -0.85980224609375 +8841 -0.870391845703125 +8842 -0.870391845703125 +8843 -0.858062744140625 +8844 -0.673004150390625 +8845 -0.42694091796875 +8846 -0.2100830078125 +8847 -0.0362548828125 +8848 0.10943603515625 +8849 0.23516845703125 +8850 0.373687744140625 +8851 0.517791748046875 +8852 0.602783203125 +8853 0.635711669921875 +8854 0.655181884765625 +8855 0.65948486328125 +8856 0.651275634765625 +8857 0.61846923828125 +8858 0.53753662109375 +8859 0.404144287109375 +8860 0.22186279296875 +8861 0.003997802734375 +8862 -0.22100830078125 +8863 -0.42449951171875 +8864 -0.579833984375 +8865 -0.641876220703125 +8866 -0.6177978515625 +8867 -0.575531005859375 +8868 -0.526336669921875 +8869 -0.42645263671875 +8870 -0.2581787109375 +8871 -0.068695068359375 +8872 0.09222412109375 +8873 0.232147216796875 +8874 0.3509521484375 +8875 0.410064697265625 +8876 0.372955322265625 +8877 0.2554931640625 +8878 0.10711669921875 +8879 -0.052886962890625 +8880 -0.186279296875 +8881 -0.23291015625 +8882 -0.209442138671875 +8883 -0.174163818359375 +8884 -0.126739501953125 +8885 -0.048126220703125 +8886 0.0426025390625 +8887 0.10748291015625 +8888 0.1409912109375 +8889 0.19708251953125 +8890 0.273651123046875 +8891 0.31768798828125 +8892 0.341094970703125 +8893 0.368011474609375 +8894 0.37249755859375 +8895 0.30072021484375 +8896 0.1517333984375 +8897 -0.01470947265625 +8898 -0.1883544921875 +8899 -0.372711181640625 +8900 -0.51397705078125 +8901 -0.57177734375 +8902 -0.53948974609375 +8903 -0.43511962890625 +8904 -0.2962646484375 +8905 -0.161102294921875 +8906 -0.0435791015625 +8907 0.060394287109375 +8908 0.13665771484375 +8909 0.170135498046875 +8910 0.16552734375 +8911 0.15728759765625 +8912 0.150787353515625 +8913 0.12200927734375 +8914 0.080108642578125 +8915 0.05126953125 +8916 0.062896728515625 +8917 0.09271240234375 +8918 0.092987060546875 +8919 0.07855224609375 +8920 0.06427001953125 +8921 0.0347900390625 +8922 -0.01171875 +8923 -0.056060791015625 +8924 -0.055511474609375 +8925 -0.010467529296875 +8926 0.02508544921875 +8927 0.025665283203125 +8928 0.017333984375 +8929 0.00189208984375 +8930 -0.03173828125 +8931 -0.071502685546875 +8932 -0.13543701171875 +8933 -0.219970703125 +8934 -0.300506591796875 +8935 -0.376312255859375 +8936 -0.416107177734375 +8937 -0.371124267578125 +8938 -0.242279052734375 +8939 -0.069732666015625 +8940 0.125640869140625 +8941 0.31268310546875 +8942 0.45501708984375 +8943 0.554779052734375 +8944 0.61065673828125 +8945 0.610931396484375 +8946 0.531463623046875 +8947 0.3883056640625 +8948 0.23468017578125 +8949 0.095245361328125 +8950 -0.00396728515625 +8951 -0.04852294921875 +8952 -0.055145263671875 +8953 -0.0758056640625 +8954 -0.138702392578125 +8955 -0.209197998046875 +8956 -0.289031982421875 +8957 -0.37884521484375 +8958 -0.456329345703125 +8959 -0.51641845703125 +8960 -0.519287109375 +8961 -0.458251953125 +8962 -0.384796142578125 +8963 -0.323699951171875 +8964 -0.269287109375 +8965 -0.1951904296875 +8966 -0.100006103515625 +8967 -0.01055908203125 +8968 0.1033935546875 +8969 0.24908447265625 +8970 0.373199462890625 +8971 0.45806884765625 +8972 0.511474609375 +8973 0.565399169921875 +8974 0.61138916015625 +8975 0.5897216796875 +8976 0.4906005859375 +8977 0.33148193359375 +8978 0.147796630859375 +8979 -0.01873779296875 +8980 -0.140289306640625 +8981 -0.191986083984375 +8982 -0.184295654296875 +8983 -0.161834716796875 +8984 -0.166595458984375 +8985 -0.19390869140625 +8986 -0.22442626953125 +8987 -0.279754638671875 +8988 -0.3389892578125 +8989 -0.3543701171875 +8990 -0.348175048828125 +8991 -0.32598876953125 +8992 -0.2581787109375 +8993 -0.139801025390625 +8994 0.014617919921875 +8995 0.144378662109375 +8996 0.221038818359375 +8997 0.27069091796875 +8998 0.294036865234375 +8999 0.311767578125 +9000 0.339141845703125 +9001 0.360260009765625 +9002 0.360504150390625 +9003 0.308380126953125 +9004 0.18170166015625 +9005 0.0047607421875 +9006 -0.17559814453125 +9007 -0.3143310546875 +9008 -0.36785888671875 +9009 -0.36248779296875 +9010 -0.343536376953125 +9011 -0.3018798828125 +9012 -0.231414794921875 +9013 -0.117645263671875 +9014 0.007049560546875 +9015 0.087982177734375 +9016 0.13946533203125 +9017 0.17425537109375 +9018 0.188201904296875 +9019 0.171234130859375 +9020 0.118438720703125 +9021 0.05706787109375 +9022 -0.010711669921875 +9023 -0.0914306640625 +9024 -0.162322998046875 +9025 -0.194549560546875 +9026 -0.1492919921875 +9027 -0.02166748046875 +9028 0.124053955078125 +9029 0.211151123046875 +9030 0.240447998046875 +9031 0.242218017578125 +9032 0.2257080078125 +9033 0.194366455078125 +9034 0.115509033203125 +9035 0.0128173828125 +9036 -0.053802490234375 +9037 -0.110626220703125 +9038 -0.199493408203125 +9039 -0.29437255859375 +9040 -0.33221435546875 +9041 -0.27972412109375 +9042 -0.185333251953125 +9043 -0.128204345703125 +9044 -0.115692138671875 +9045 -0.116455078125 +9046 -0.105926513671875 +9047 -0.053955078125 +9048 0.048797607421875 +9049 0.157318115234375 +9050 0.212005615234375 +9051 0.218475341796875 +9052 0.23724365234375 +9053 0.30535888671875 +9054 0.38128662109375 +9055 0.404449462890625 +9056 0.3944091796875 +9057 0.3885498046875 +9058 0.362640380859375 +9059 0.27362060546875 +9060 0.11712646484375 +9061 -0.054901123046875 +9062 -0.19085693359375 +9063 -0.28570556640625 +9064 -0.339263916015625 +9065 -0.3775634765625 +9066 -0.445709228515625 +9067 -0.535064697265625 +9068 -0.629058837890625 +9069 -0.697601318359375 +9070 -0.70391845703125 +9071 -0.6424560546875 +9072 -0.491241455078125 +9073 -0.265716552734375 +9074 -0.023712158203125 +9075 0.201751708984375 +9076 0.375823974609375 +9077 0.485076904296875 +9078 0.56884765625 +9079 0.634765625 +9080 0.63763427734375 +9081 0.5660400390625 +9082 0.4720458984375 +9083 0.40692138671875 +9084 0.3778076171875 +9085 0.376953125 +9086 0.371978759765625 +9087 0.313140869140625 +9088 0.184417724609375 +9089 0.011199951171875 +9090 -0.171051025390625 +9091 -0.33740234375 +9092 -0.47198486328125 +9093 -0.560394287109375 +9094 -0.58056640625 +9095 -0.54754638671875 +9096 -0.508575439453125 +9097 -0.459503173828125 +9098 -0.394378662109375 +9099 -0.35260009765625 +9100 -0.31170654296875 +9101 -0.197418212890625 +9102 -0.007965087890625 +9103 0.207489013671875 +9104 0.409210205078125 +9105 0.57208251953125 +9106 0.66595458984375 +9107 0.65875244140625 +9108 0.56744384765625 +9109 0.431396484375 +9110 0.29443359375 +9111 0.182464599609375 +9112 0.06365966796875 +9113 -0.075958251953125 +9114 -0.189422607421875 +9115 -0.271942138671875 +9116 -0.342529296875 +9117 -0.364166259765625 +9118 -0.327239990234375 +9119 -0.2769775390625 +9120 -0.253692626953125 +9121 -0.24365234375 +9122 -0.1983642578125 +9123 -0.116241455078125 +9124 -0.036834716796875 +9125 0.034881591796875 +9126 0.09124755859375 +9127 0.10888671875 +9128 0.125518798828125 +9129 0.15771484375 +9130 0.17828369140625 +9131 0.17108154296875 +9132 0.129974365234375 +9133 0.082427978515625 +9134 0.027679443359375 +9135 -0.065643310546875 +9136 -0.15936279296875 +9137 -0.21307373046875 +9138 -0.234649658203125 +9139 -0.2001953125 +9140 -0.119171142578125 +9141 -0.024749755859375 +9142 0.085784912109375 +9143 0.178131103515625 +9144 0.215576171875 +9145 0.211456298828125 +9146 0.17523193359375 +9147 0.128753662109375 +9148 0.1019287109375 +9149 0.0743408203125 +9150 0.04327392578125 +9151 0.038177490234375 +9152 0.076263427734375 +9153 0.14105224609375 +9154 0.186431884765625 +9155 0.188812255859375 +9156 0.1390380859375 +9157 0.041778564453125 +9158 -0.079437255859375 +9159 -0.219390869140625 +9160 -0.367828369140625 +9161 -0.494873046875 +9162 -0.556243896484375 +9163 -0.508697509765625 +9164 -0.3756103515625 +9165 -0.218902587890625 +9166 -0.063751220703125 +9167 0.091552734375 +9168 0.23602294921875 +9169 0.342987060546875 +9170 0.39520263671875 +9171 0.389373779296875 +9172 0.324249267578125 +9173 0.224090576171875 +9174 0.124267578125 +9175 0.037078857421875 +9176 -0.010101318359375 +9177 -0.019439697265625 +9178 -0.022796630859375 +9179 -0.001556396484375 +9180 0.056304931640625 +9181 0.106719970703125 +9182 0.096893310546875 +9183 0.042694091796875 +9184 -0.018035888671875 +9185 -0.07586669921875 +9186 -0.11944580078125 +9187 -0.15972900390625 +9188 -0.202606201171875 +9189 -0.24859619140625 +9190 -0.30517578125 +9191 -0.36212158203125 +9192 -0.39141845703125 +9193 -0.35528564453125 +9194 -0.249969482421875 +9195 -0.092864990234375 +9196 0.08905029296875 +9197 0.2352294921875 +9198 0.318817138671875 +9199 0.358642578125 +9200 0.347747802734375 +9201 0.28564453125 +9202 0.223175048828125 +9203 0.196746826171875 +9204 0.179840087890625 +9205 0.155548095703125 +9206 0.151214599609375 +9207 0.156951904296875 +9208 0.13177490234375 +9209 0.100799560546875 +9210 0.087127685546875 +9211 0.05487060546875 +9212 -0.009002685546875 +9213 -0.10400390625 +9214 -0.229400634765625 +9215 -0.35552978515625 +9216 -0.441925048828125 +9217 -0.473846435546875 +9218 -0.464813232421875 +9219 -0.419097900390625 +9220 -0.334320068359375 +9221 -0.227935791015625 +9222 -0.12347412109375 +9223 -0.02764892578125 +9224 0.077667236328125 +9225 0.2132568359375 +9226 0.38885498046875 +9227 0.582794189453125 +9228 0.734039306640625 +9229 0.800140380859375 +9230 0.7783203125 +9231 0.6651611328125 +9232 0.45965576171875 +9233 0.199188232421875 +9234 -0.050689697265625 +9235 -0.23297119140625 +9236 -0.33013916015625 +9237 -0.368408203125 +9238 -0.378936767578125 +9239 -0.376983642578125 +9240 -0.37969970703125 +9241 -0.391510009765625 +9242 -0.385345458984375 +9243 -0.3419189453125 +9244 -0.28289794921875 +9245 -0.251617431640625 +9246 -0.266143798828125 +9247 -0.273345947265625 +9248 -0.216796875 +9249 -0.128265380859375 +9250 -0.068145751953125 +9251 -0.0430908203125 +9252 -0.024444580078125 +9253 0.020721435546875 +9254 0.124481201171875 +9255 0.25787353515625 +9256 0.379119873046875 +9257 0.47991943359375 +9258 0.5281982421875 +9259 0.511138916015625 +9260 0.456207275390625 +9261 0.407470703125 +9262 0.383758544921875 +9263 0.35687255859375 +9264 0.31182861328125 +9265 0.250885009765625 +9266 0.1654052734375 +9267 0.035247802734375 +9268 -0.142059326171875 +9269 -0.33563232421875 +9270 -0.5345458984375 +9271 -0.72186279296875 +9272 -0.836669921875 +9273 -0.8326416015625 +9274 -0.7296142578125 +9275 -0.582550048828125 +9276 -0.440093994140625 +9277 -0.324310302734375 +9278 -0.20147705078125 +9279 -0.044647216796875 +9280 0.103973388671875 +9281 0.202392578125 +9282 0.264495849609375 +9283 0.338897705078125 +9284 0.443817138671875 +9285 0.545074462890625 +9286 0.6173095703125 +9287 0.6524658203125 +9288 0.66339111328125 +9289 0.6561279296875 +9290 0.606781005859375 +9291 0.501190185546875 +9292 0.352783203125 +9293 0.176544189453125 +9294 -0.034820556640625 +9295 -0.258209228515625 +9296 -0.44244384765625 +9297 -0.5753173828125 +9298 -0.65203857421875 +9299 -0.641632080078125 +9300 -0.562164306640625 +9301 -0.458038330078125 +9302 -0.350555419921875 +9303 -0.260528564453125 +9304 -0.192108154296875 +9305 -0.141937255859375 +9306 -0.1021728515625 +9307 -0.062896728515625 +9308 -0.011932373046875 +9309 0.062835693359375 +9310 0.148712158203125 +9311 0.241729736328125 +9312 0.34912109375 +9313 0.457305908203125 +9314 0.54388427734375 +9315 0.5728759765625 +9316 0.506591796875 +9317 0.351226806640625 +9318 0.146514892578125 +9319 -0.05523681640625 +9320 -0.21624755859375 +9321 -0.334930419921875 +9322 -0.402984619140625 +9323 -0.4412841796875 +9324 -0.49578857421875 +9325 -0.5601806640625 +9326 -0.600738525390625 +9327 -0.584228515625 +9328 -0.47930908203125 +9329 -0.27935791015625 +9330 -0.0089111328125 +9331 0.268798828125 +9332 0.482818603515625 +9333 0.60369873046875 +9334 0.650421142578125 +9335 0.66400146484375 +9336 0.6414794921875 +9337 0.572540283203125 +9338 0.498138427734375 +9339 0.439453125 +9340 0.375518798828125 +9341 0.274505615234375 +9342 0.1087646484375 +9343 -0.099395751953125 +9344 -0.3182373046875 +9345 -0.5489501953125 +9346 -0.7738037109375 +9347 -0.86383056640625 +9348 -0.870391845703125 +9349 -0.86895751953125 +9350 -0.861053466796875 +9351 -0.765869140625 +9352 -0.5301513671875 +9353 -0.214691162109375 +9354 0.137359619140625 +9355 0.474822998046875 +9356 0.76239013671875 +9357 0.867462158203125 +9358 0.870361328125 +9359 0.86480712890625 +9360 0.831817626953125 +9361 0.677581787109375 +9362 0.495880126953125 +9363 0.30767822265625 +9364 0.116180419921875 +9365 -0.110748291015625 +9366 -0.381805419921875 +9367 -0.6572265625 +9368 -0.857421875 +9369 -0.870391845703125 +9370 -0.870391845703125 +9371 -0.86444091796875 +9372 -0.85723876953125 +9373 -0.790008544921875 +9374 -0.62847900390625 +9375 -0.3956298828125 +9376 -0.126708984375 +9377 0.150115966796875 +9378 0.424041748046875 +9379 0.670623779296875 +9380 0.854522705078125 +9381 0.866485595703125 +9382 0.86920166015625 +9383 0.8653564453125 +9384 0.857147216796875 +9385 0.766845703125 +9386 0.628509521484375 +9387 0.462127685546875 +9388 0.297210693359375 +9389 0.14862060546875 +9390 -0.00537109375 +9391 -0.15753173828125 +9392 -0.31304931640625 +9393 -0.48876953125 +9394 -0.6416015625 +9395 -0.751373291015625 +9396 -0.84619140625 +9397 -0.861297607421875 +9398 -0.863250732421875 +9399 -0.856597900390625 +9400 -0.7498779296875 +9401 -0.624542236328125 +9402 -0.47808837890625 +9403 -0.253387451171875 +9404 0.003692626953125 +9405 0.2257080078125 +9406 0.427154541015625 +9407 0.643218994140625 +9408 0.855926513671875 +9409 0.870361328125 +9410 0.870361328125 +9411 0.862762451171875 +9412 0.79669189453125 +9413 0.595794677734375 +9414 0.362152099609375 +9415 0.1270751953125 +9416 -0.086944580078125 +9417 -0.2784423828125 +9418 -0.484832763671875 +9419 -0.729583740234375 +9420 -0.86688232421875 +9421 -0.870391845703125 +9422 -0.86859130859375 +9423 -0.86279296875 +9424 -0.817962646484375 +9425 -0.6116943359375 +9426 -0.3128662109375 +9427 0.039398193359375 +9428 0.422821044921875 +9429 0.805145263671875 +9430 0.870361328125 +9431 0.870361328125 +9432 0.860015869140625 +9433 0.727935791015625 +9434 0.48114013671875 +9435 0.2059326171875 +9436 -0.06103515625 +9437 -0.29913330078125 +9438 -0.516204833984375 +9439 -0.7252197265625 +9440 -0.85980224609375 +9441 -0.870391845703125 +9442 -0.870391845703125 +9443 -0.858062744140625 +9444 -0.673004150390625 +9445 -0.42694091796875 +9446 -0.2100830078125 +9447 -0.0362548828125 +9448 0.10943603515625 +9449 0.23516845703125 +9450 0.373687744140625 +9451 0.517791748046875 +9452 0.602783203125 +9453 0.635711669921875 +9454 0.655181884765625 +9455 0.65948486328125 +9456 0.651275634765625 +9457 0.61846923828125 +9458 0.53753662109375 +9459 0.404144287109375 +9460 0.22186279296875 +9461 0.003997802734375 +9462 -0.22100830078125 +9463 -0.42449951171875 +9464 -0.579833984375 +9465 -0.641876220703125 +9466 -0.6177978515625 +9467 -0.575531005859375 +9468 -0.526336669921875 +9469 -0.42645263671875 +9470 -0.2581787109375 +9471 -0.068695068359375 +9472 0.09222412109375 +9473 0.232147216796875 +9474 0.3509521484375 +9475 0.410064697265625 +9476 0.372955322265625 +9477 0.2554931640625 +9478 0.10711669921875 +9479 -0.052886962890625 +9480 -0.186279296875 +9481 -0.23291015625 +9482 -0.209442138671875 +9483 -0.174163818359375 +9484 -0.126739501953125 +9485 -0.048126220703125 +9486 0.0426025390625 +9487 0.10748291015625 +9488 0.1409912109375 +9489 0.19708251953125 +9490 0.273651123046875 +9491 0.31768798828125 +9492 0.341094970703125 +9493 0.368011474609375 +9494 0.37249755859375 +9495 0.30072021484375 +9496 0.1517333984375 +9497 -0.01470947265625 +9498 -0.1883544921875 +9499 -0.372711181640625 +9500 -0.51397705078125 +9501 -0.57177734375 +9502 -0.53948974609375 +9503 -0.43511962890625 +9504 -0.2962646484375 +9505 -0.161102294921875 +9506 -0.0435791015625 +9507 0.060394287109375 +9508 0.13665771484375 +9509 0.170135498046875 +9510 0.16552734375 +9511 0.15728759765625 +9512 0.150787353515625 +9513 0.12200927734375 +9514 0.080108642578125 +9515 0.05126953125 +9516 0.062896728515625 +9517 0.09271240234375 +9518 0.092987060546875 +9519 0.07855224609375 +9520 0.06427001953125 +9521 0.0347900390625 +9522 -0.01171875 +9523 -0.056060791015625 +9524 -0.055511474609375 +9525 -0.010467529296875 +9526 0.02508544921875 +9527 0.025665283203125 +9528 0.017333984375 +9529 0.00189208984375 +9530 -0.03173828125 +9531 -0.071502685546875 +9532 -0.13543701171875 +9533 -0.219970703125 +9534 -0.300506591796875 +9535 -0.376312255859375 +9536 -0.416107177734375 +9537 -0.371124267578125 +9538 -0.242279052734375 +9539 -0.069732666015625 +9540 0.125640869140625 +9541 0.31268310546875 +9542 0.45501708984375 +9543 0.554779052734375 +9544 0.61065673828125 +9545 0.610931396484375 +9546 0.531463623046875 +9547 0.3883056640625 +9548 0.23468017578125 +9549 0.095245361328125 +9550 -0.00396728515625 +9551 -0.04852294921875 +9552 -0.055145263671875 +9553 -0.0758056640625 +9554 -0.138702392578125 +9555 -0.209197998046875 +9556 -0.289031982421875 +9557 -0.37884521484375 +9558 -0.456329345703125 +9559 -0.51641845703125 +9560 -0.519287109375 +9561 -0.458251953125 +9562 -0.384796142578125 +9563 -0.323699951171875 +9564 -0.269287109375 +9565 -0.1951904296875 +9566 -0.100006103515625 +9567 -0.01055908203125 +9568 0.1033935546875 +9569 0.24908447265625 +9570 0.373199462890625 +9571 0.45806884765625 +9572 0.511474609375 +9573 0.565399169921875 +9574 0.61138916015625 +9575 0.5897216796875 +9576 0.4906005859375 +9577 0.33148193359375 +9578 0.147796630859375 +9579 -0.01873779296875 +9580 -0.140289306640625 +9581 -0.191986083984375 +9582 -0.184295654296875 +9583 -0.161834716796875 +9584 -0.166595458984375 +9585 -0.19390869140625 +9586 -0.22442626953125 +9587 -0.279754638671875 +9588 -0.3389892578125 +9589 -0.3543701171875 +9590 -0.348175048828125 +9591 -0.32598876953125 +9592 -0.2581787109375 +9593 -0.139801025390625 +9594 0.014617919921875 +9595 0.144378662109375 +9596 0.221038818359375 +9597 0.27069091796875 +9598 0.294036865234375 +9599 0.311767578125 +9600 0.339141845703125 +9601 0.360260009765625 +9602 0.360504150390625 +9603 0.308380126953125 +9604 0.18170166015625 +9605 0.0047607421875 +9606 -0.17559814453125 +9607 -0.3143310546875 +9608 -0.36785888671875 +9609 -0.36248779296875 +9610 -0.343536376953125 +9611 -0.3018798828125 +9612 -0.231414794921875 +9613 -0.117645263671875 +9614 0.007049560546875 +9615 0.087982177734375 +9616 0.13946533203125 +9617 0.17425537109375 +9618 0.188201904296875 +9619 0.171234130859375 +9620 0.118438720703125 +9621 0.05706787109375 +9622 -0.010711669921875 +9623 -0.0914306640625 +9624 -0.162322998046875 +9625 -0.194549560546875 +9626 -0.1492919921875 +9627 -0.02166748046875 +9628 0.124053955078125 +9629 0.211151123046875 +9630 0.240447998046875 +9631 0.242218017578125 +9632 0.2257080078125 +9633 0.194366455078125 +9634 0.115509033203125 +9635 0.0128173828125 +9636 -0.053802490234375 +9637 -0.110626220703125 +9638 -0.199493408203125 +9639 -0.29437255859375 +9640 -0.33221435546875 +9641 -0.27972412109375 +9642 -0.185333251953125 +9643 -0.128204345703125 +9644 -0.115692138671875 +9645 -0.116455078125 +9646 -0.105926513671875 +9647 -0.053955078125 +9648 0.048797607421875 +9649 0.157318115234375 +9650 0.212005615234375 +9651 0.218475341796875 +9652 0.23724365234375 +9653 0.30535888671875 +9654 0.38128662109375 +9655 0.404449462890625 +9656 0.3944091796875 +9657 0.3885498046875 +9658 0.362640380859375 +9659 0.27362060546875 +9660 0.11712646484375 +9661 -0.054901123046875 +9662 -0.19085693359375 +9663 -0.28570556640625 +9664 -0.339263916015625 +9665 -0.3775634765625 +9666 -0.445709228515625 +9667 -0.535064697265625 +9668 -0.629058837890625 +9669 -0.697601318359375 +9670 -0.70391845703125 +9671 -0.6424560546875 +9672 -0.491241455078125 +9673 -0.265716552734375 +9674 -0.023712158203125 +9675 0.201751708984375 +9676 0.375823974609375 +9677 0.485076904296875 +9678 0.56884765625 +9679 0.634765625 +9680 0.63763427734375 +9681 0.5660400390625 +9682 0.4720458984375 +9683 0.40692138671875 +9684 0.3778076171875 +9685 0.376953125 +9686 0.371978759765625 +9687 0.313140869140625 +9688 0.184417724609375 +9689 0.011199951171875 +9690 -0.171051025390625 +9691 -0.33740234375 +9692 -0.47198486328125 +9693 -0.560394287109375 +9694 -0.58056640625 +9695 -0.54754638671875 +9696 -0.508575439453125 +9697 -0.459503173828125 +9698 -0.394378662109375 +9699 -0.35260009765625 +9700 -0.31170654296875 +9701 -0.197418212890625 +9702 -0.007965087890625 +9703 0.207489013671875 +9704 0.409210205078125 +9705 0.57208251953125 +9706 0.66595458984375 +9707 0.65875244140625 +9708 0.56744384765625 +9709 0.431396484375 +9710 0.29443359375 +9711 0.182464599609375 +9712 0.06365966796875 +9713 -0.075958251953125 +9714 -0.189422607421875 +9715 -0.271942138671875 +9716 -0.342529296875 +9717 -0.364166259765625 +9718 -0.327239990234375 +9719 -0.2769775390625 +9720 -0.253692626953125 +9721 -0.24365234375 +9722 -0.1983642578125 +9723 -0.116241455078125 +9724 -0.036834716796875 +9725 0.034881591796875 +9726 0.09124755859375 +9727 0.10888671875 +9728 0.125518798828125 +9729 0.15771484375 +9730 0.17828369140625 +9731 0.17108154296875 +9732 0.129974365234375 +9733 0.082427978515625 +9734 0.027679443359375 +9735 -0.065643310546875 +9736 -0.15936279296875 +9737 -0.21307373046875 +9738 -0.234649658203125 +9739 -0.2001953125 +9740 -0.119171142578125 +9741 -0.024749755859375 +9742 0.085784912109375 +9743 0.178131103515625 +9744 0.215576171875 +9745 0.211456298828125 +9746 0.17523193359375 +9747 0.128753662109375 +9748 0.1019287109375 +9749 0.0743408203125 +9750 0.04327392578125 +9751 0.038177490234375 +9752 0.076263427734375 +9753 0.14105224609375 +9754 0.186431884765625 +9755 0.188812255859375 +9756 0.1390380859375 +9757 0.041778564453125 +9758 -0.079437255859375 +9759 -0.219390869140625 +9760 -0.367828369140625 +9761 -0.494873046875 +9762 -0.556243896484375 +9763 -0.508697509765625 +9764 -0.3756103515625 +9765 -0.218902587890625 +9766 -0.063751220703125 +9767 0.091552734375 +9768 0.23602294921875 +9769 0.342987060546875 +9770 0.39520263671875 +9771 0.389373779296875 +9772 0.324249267578125 +9773 0.224090576171875 +9774 0.124267578125 +9775 0.037078857421875 +9776 -0.010101318359375 +9777 -0.019439697265625 +9778 -0.022796630859375 +9779 -0.001556396484375 +9780 0.056304931640625 +9781 0.106719970703125 +9782 0.096893310546875 +9783 0.042694091796875 +9784 -0.018035888671875 +9785 -0.07586669921875 +9786 -0.11944580078125 +9787 -0.15972900390625 +9788 -0.202606201171875 +9789 -0.24859619140625 +9790 -0.30517578125 +9791 -0.36212158203125 +9792 -0.39141845703125 +9793 -0.35528564453125 +9794 -0.249969482421875 +9795 -0.092864990234375 +9796 0.08905029296875 +9797 0.2352294921875 +9798 0.318817138671875 +9799 0.358642578125 +9800 0.347747802734375 +9801 0.28564453125 +9802 0.223175048828125 +9803 0.196746826171875 +9804 0.179840087890625 +9805 0.155548095703125 +9806 0.151214599609375 +9807 0.156951904296875 +9808 0.13177490234375 +9809 0.100799560546875 +9810 0.087127685546875 +9811 0.05487060546875 +9812 -0.009002685546875 +9813 -0.10400390625 +9814 -0.229400634765625 +9815 -0.35552978515625 +9816 -0.441925048828125 +9817 -0.473846435546875 +9818 -0.464813232421875 +9819 -0.419097900390625 +9820 -0.334320068359375 +9821 -0.227935791015625 +9822 -0.12347412109375 +9823 -0.02764892578125 +9824 0.077667236328125 +9825 0.2132568359375 +9826 0.38885498046875 +9827 0.582794189453125 +9828 0.734039306640625 +9829 0.800140380859375 +9830 0.7783203125 +9831 0.6651611328125 +9832 0.45965576171875 +9833 0.199188232421875 +9834 -0.050689697265625 +9835 -0.23297119140625 +9836 -0.33013916015625 +9837 -0.368408203125 +9838 -0.378936767578125 +9839 -0.376983642578125 +9840 -0.37969970703125 +9841 -0.391510009765625 +9842 -0.385345458984375 +9843 -0.3419189453125 +9844 -0.28289794921875 +9845 -0.251617431640625 +9846 -0.266143798828125 +9847 -0.273345947265625 +9848 -0.216796875 +9849 -0.128265380859375 +9850 -0.068145751953125 +9851 -0.0430908203125 +9852 -0.024444580078125 +9853 0.020721435546875 +9854 0.124481201171875 +9855 0.25787353515625 +9856 0.379119873046875 +9857 0.47991943359375 +9858 0.5281982421875 +9859 0.511138916015625 +9860 0.456207275390625 +9861 0.407470703125 +9862 0.383758544921875 +9863 0.35687255859375 +9864 0.31182861328125 +9865 0.250885009765625 +9866 0.1654052734375 +9867 0.035247802734375 +9868 -0.142059326171875 +9869 -0.33563232421875 +9870 -0.5345458984375 +9871 -0.72186279296875 +9872 -0.836669921875 +9873 -0.8326416015625 +9874 -0.7296142578125 +9875 -0.582550048828125 +9876 -0.440093994140625 +9877 -0.324310302734375 +9878 -0.20147705078125 +9879 -0.044647216796875 +9880 0.103973388671875 +9881 0.202392578125 +9882 0.264495849609375 +9883 0.338897705078125 +9884 0.443817138671875 +9885 0.545074462890625 +9886 0.6173095703125 +9887 0.6524658203125 +9888 0.66339111328125 +9889 0.6561279296875 +9890 0.606781005859375 +9891 0.501190185546875 +9892 0.352783203125 +9893 0.176544189453125 +9894 -0.034820556640625 +9895 -0.258209228515625 +9896 -0.44244384765625 +9897 -0.5753173828125 +9898 -0.65203857421875 +9899 -0.641632080078125 +9900 -0.562164306640625 +9901 -0.458038330078125 +9902 -0.350555419921875 +9903 -0.260528564453125 +9904 -0.192108154296875 +9905 -0.141937255859375 +9906 -0.1021728515625 +9907 -0.062896728515625 +9908 -0.011932373046875 +9909 0.062835693359375 +9910 0.148712158203125 +9911 0.241729736328125 +9912 0.34912109375 +9913 0.457305908203125 +9914 0.54388427734375 +9915 0.5728759765625 +9916 0.506591796875 +9917 0.351226806640625 +9918 0.146514892578125 +9919 -0.05523681640625 +9920 -0.21624755859375 +9921 -0.334930419921875 +9922 -0.402984619140625 +9923 -0.4412841796875 +9924 -0.49578857421875 +9925 -0.5601806640625 +9926 -0.600738525390625 +9927 -0.584228515625 +9928 -0.47930908203125 +9929 -0.27935791015625 +9930 -0.0089111328125 +9931 0.268798828125 +9932 0.482818603515625 +9933 0.60369873046875 +9934 0.650421142578125 +9935 0.66400146484375 +9936 0.6414794921875 +9937 0.572540283203125 +9938 0.498138427734375 +9939 0.439453125 +9940 0.375518798828125 +9941 0.274505615234375 +9942 0.1087646484375 +9943 -0.099395751953125 +9944 -0.3182373046875 +9945 -0.5489501953125 +9946 -0.7738037109375 +9947 -0.86383056640625 +9948 -0.870391845703125 +9949 -0.86895751953125 +9950 -0.861053466796875 +9951 -0.765869140625 +9952 -0.5301513671875 +9953 -0.214691162109375 +9954 0.137359619140625 +9955 0.474822998046875 +9956 0.76239013671875 +9957 0.867462158203125 +9958 0.870361328125 +9959 0.86480712890625 +9960 0.831817626953125 +9961 0.677581787109375 +9962 0.495880126953125 +9963 0.30767822265625 +9964 0.116180419921875 +9965 -0.110748291015625 +9966 -0.381805419921875 +9967 -0.6572265625 +9968 -0.857421875 +9969 -0.870391845703125 +9970 -0.870391845703125 +9971 -0.86444091796875 +9972 -0.85723876953125 +9973 -0.790008544921875 +9974 -0.62847900390625 +9975 -0.3956298828125 +9976 -0.126708984375 +9977 0.150115966796875 +9978 0.424041748046875 +9979 0.670623779296875 +9980 0.854522705078125 +9981 0.866485595703125 +9982 0.86920166015625 +9983 0.8653564453125 +9984 0.857147216796875 +9985 0.766845703125 +9986 0.628509521484375 +9987 0.462127685546875 +9988 0.297210693359375 +9989 0.14862060546875 +9990 -0.00537109375 +9991 -0.15753173828125 +9992 -0.31304931640625 +9993 -0.48876953125 +9994 -0.6416015625 +9995 -0.751373291015625 +9996 -0.84619140625 +9997 -0.861297607421875 +9998 -0.863250732421875 +9999 -0.856597900390625 +10000 -0.7498779296875 +10001 -0.624542236328125 +10002 -0.47808837890625 +10003 -0.253387451171875 +10004 0.003692626953125 +10005 0.2257080078125 +10006 0.427154541015625 +10007 0.643218994140625 +10008 0.855926513671875 +10009 0.870361328125 +10010 0.870361328125 +10011 0.862762451171875 +10012 0.79669189453125 +10013 0.595794677734375 +10014 0.362152099609375 +10015 0.1270751953125 +10016 -0.086944580078125 +10017 -0.2784423828125 +10018 -0.484832763671875 +10019 -0.729583740234375 +10020 -0.86688232421875 +10021 -0.870391845703125 +10022 -0.86859130859375 +10023 -0.86279296875 +10024 -0.817962646484375 +10025 -0.6116943359375 +10026 -0.3128662109375 +10027 0.039398193359375 +10028 0.422821044921875 +10029 0.805145263671875 +10030 0.870361328125 +10031 0.870361328125 +10032 0.860015869140625 +10033 0.727935791015625 +10034 0.48114013671875 +10035 0.2059326171875 +10036 -0.06103515625 +10037 -0.29913330078125 +10038 -0.516204833984375 +10039 -0.7252197265625 +10040 -0.85980224609375 +10041 -0.870391845703125 +10042 -0.870391845703125 +10043 -0.858062744140625 +10044 -0.673004150390625 +10045 -0.42694091796875 +10046 -0.2100830078125 +10047 -0.0362548828125 +10048 0.10943603515625 +10049 0.23516845703125 +10050 0.373687744140625 +10051 0.517791748046875 +10052 0.602783203125 +10053 0.635711669921875 +10054 0.655181884765625 +10055 0.65948486328125 +10056 0.651275634765625 +10057 0.61846923828125 +10058 0.53753662109375 +10059 0.404144287109375 +10060 0.22186279296875 +10061 0.003997802734375 +10062 -0.22100830078125 +10063 -0.42449951171875 +10064 -0.579833984375 +10065 -0.641876220703125 +10066 -0.6177978515625 +10067 -0.575531005859375 +10068 -0.526336669921875 +10069 -0.42645263671875 +10070 -0.2581787109375 +10071 -0.068695068359375 +10072 0.09222412109375 +10073 0.232147216796875 +10074 0.3509521484375 +10075 0.410064697265625 +10076 0.372955322265625 +10077 0.2554931640625 +10078 0.10711669921875 +10079 -0.052886962890625 +10080 -0.186279296875 +10081 -0.23291015625 +10082 -0.209442138671875 +10083 -0.174163818359375 +10084 -0.126739501953125 +10085 -0.048126220703125 +10086 0.0426025390625 +10087 0.10748291015625 +10088 0.1409912109375 +10089 0.19708251953125 +10090 0.273651123046875 +10091 0.31768798828125 +10092 0.341094970703125 +10093 0.368011474609375 +10094 0.37249755859375 +10095 0.30072021484375 +10096 0.1517333984375 +10097 -0.01470947265625 +10098 -0.1883544921875 +10099 -0.372711181640625 +10100 -0.51397705078125 +10101 -0.57177734375 +10102 -0.53948974609375 +10103 -0.43511962890625 +10104 -0.2962646484375 +10105 -0.161102294921875 +10106 -0.0435791015625 +10107 0.060394287109375 +10108 0.13665771484375 +10109 0.170135498046875 +10110 0.16552734375 +10111 0.15728759765625 +10112 0.150787353515625 +10113 0.12200927734375 +10114 0.080108642578125 +10115 0.05126953125 +10116 0.062896728515625 +10117 0.09271240234375 +10118 0.092987060546875 +10119 0.07855224609375 +10120 0.06427001953125 +10121 0.0347900390625 +10122 -0.01171875 +10123 -0.056060791015625 +10124 -0.055511474609375 +10125 -0.010467529296875 +10126 0.02508544921875 +10127 0.025665283203125 +10128 0.017333984375 +10129 0.00189208984375 +10130 -0.03173828125 +10131 -0.071502685546875 +10132 -0.13543701171875 +10133 -0.219970703125 +10134 -0.300506591796875 +10135 -0.376312255859375 +10136 -0.416107177734375 +10137 -0.371124267578125 +10138 -0.242279052734375 +10139 -0.069732666015625 +10140 0.125640869140625 +10141 0.31268310546875 +10142 0.45501708984375 +10143 0.554779052734375 +10144 0.61065673828125 +10145 0.610931396484375 +10146 0.531463623046875 +10147 0.3883056640625 +10148 0.23468017578125 +10149 0.095245361328125 +10150 -0.00396728515625 +10151 -0.04852294921875 +10152 -0.055145263671875 +10153 -0.0758056640625 +10154 -0.138702392578125 +10155 -0.209197998046875 +10156 -0.289031982421875 +10157 -0.37884521484375 +10158 -0.456329345703125 +10159 -0.51641845703125 +10160 -0.519287109375 +10161 -0.458251953125 +10162 -0.384796142578125 +10163 -0.323699951171875 +10164 -0.269287109375 +10165 -0.1951904296875 +10166 -0.100006103515625 +10167 -0.01055908203125 +10168 0.1033935546875 +10169 0.24908447265625 +10170 0.373199462890625 +10171 0.45806884765625 +10172 0.511474609375 +10173 0.565399169921875 +10174 0.61138916015625 +10175 0.5897216796875 +10176 0.4906005859375 +10177 0.33148193359375 +10178 0.147796630859375 +10179 -0.01873779296875 +10180 -0.140289306640625 +10181 -0.191986083984375 +10182 -0.184295654296875 +10183 -0.161834716796875 +10184 -0.166595458984375 +10185 -0.19390869140625 +10186 -0.22442626953125 +10187 -0.279754638671875 +10188 -0.3389892578125 +10189 -0.3543701171875 +10190 -0.348175048828125 +10191 -0.32598876953125 +10192 -0.2581787109375 +10193 -0.139801025390625 +10194 0.014617919921875 +10195 0.144378662109375 +10196 0.221038818359375 +10197 0.27069091796875 +10198 0.294036865234375 +10199 0.311767578125 +10200 0.339141845703125 +10201 0.360260009765625 +10202 0.360504150390625 +10203 0.308380126953125 +10204 0.18170166015625 +10205 0.0047607421875 +10206 -0.17559814453125 +10207 -0.3143310546875 +10208 -0.36785888671875 +10209 -0.36248779296875 +10210 -0.343536376953125 +10211 -0.3018798828125 +10212 -0.231414794921875 +10213 -0.117645263671875 +10214 0.007049560546875 +10215 0.087982177734375 +10216 0.13946533203125 +10217 0.17425537109375 +10218 0.188201904296875 +10219 0.171234130859375 +10220 0.118438720703125 +10221 0.05706787109375 +10222 -0.010711669921875 +10223 -0.0914306640625 +10224 -0.162322998046875 +10225 -0.194549560546875 +10226 -0.1492919921875 +10227 -0.02166748046875 +10228 0.124053955078125 +10229 0.211151123046875 +10230 0.240447998046875 +10231 0.242218017578125 +10232 0.2257080078125 +10233 0.194366455078125 +10234 0.115509033203125 +10235 0.0128173828125 +10236 -0.053802490234375 +10237 -0.110626220703125 +10238 -0.199493408203125 +10239 -0.29437255859375 +10240 -0.33221435546875 +10241 -0.27972412109375 +10242 -0.185333251953125 +10243 -0.128204345703125 +10244 -0.115692138671875 +10245 -0.116455078125 +10246 -0.105926513671875 +10247 -0.053955078125 +10248 0.048797607421875 +10249 0.157318115234375 +10250 0.212005615234375 +10251 0.218475341796875 +10252 0.23724365234375 +10253 0.30535888671875 +10254 0.38128662109375 +10255 0.404449462890625 +10256 0.3944091796875 +10257 0.3885498046875 +10258 0.362640380859375 +10259 0.27362060546875 +10260 0.11712646484375 +10261 -0.054901123046875 +10262 -0.19085693359375 +10263 -0.28570556640625 +10264 -0.339263916015625 +10265 -0.3775634765625 +10266 -0.445709228515625 +10267 -0.535064697265625 +10268 -0.629058837890625 +10269 -0.697601318359375 +10270 -0.70391845703125 +10271 -0.6424560546875 +10272 -0.491241455078125 +10273 -0.265716552734375 +10274 -0.023712158203125 +10275 0.201751708984375 +10276 0.375823974609375 +10277 0.485076904296875 +10278 0.56884765625 +10279 0.634765625 +10280 0.63763427734375 +10281 0.5660400390625 +10282 0.4720458984375 +10283 0.40692138671875 +10284 0.3778076171875 +10285 0.376953125 +10286 0.371978759765625 +10287 0.313140869140625 +10288 0.184417724609375 +10289 0.011199951171875 +10290 -0.171051025390625 +10291 -0.33740234375 +10292 -0.47198486328125 +10293 -0.560394287109375 +10294 -0.58056640625 +10295 -0.54754638671875 +10296 -0.508575439453125 +10297 -0.459503173828125 +10298 -0.394378662109375 +10299 -0.35260009765625 +10300 -0.31170654296875 +10301 -0.197418212890625 +10302 -0.007965087890625 +10303 0.207489013671875 +10304 0.409210205078125 +10305 0.57208251953125 +10306 0.66595458984375 +10307 0.65875244140625 +10308 0.56744384765625 +10309 0.431396484375 +10310 0.29443359375 +10311 0.182464599609375 +10312 0.06365966796875 +10313 -0.075958251953125 +10314 -0.189422607421875 +10315 -0.271942138671875 +10316 -0.342529296875 +10317 -0.364166259765625 +10318 -0.327239990234375 +10319 -0.2769775390625 +10320 -0.253692626953125 +10321 -0.24365234375 +10322 -0.1983642578125 +10323 -0.116241455078125 +10324 -0.036834716796875 +10325 0.034881591796875 +10326 0.09124755859375 +10327 0.10888671875 +10328 0.125518798828125 +10329 0.15771484375 +10330 0.17828369140625 +10331 0.17108154296875 +10332 0.129974365234375 +10333 0.082427978515625 +10334 0.027679443359375 +10335 -0.065643310546875 +10336 -0.15936279296875 +10337 -0.21307373046875 +10338 -0.234649658203125 +10339 -0.2001953125 +10340 -0.119171142578125 +10341 -0.024749755859375 +10342 0.085784912109375 +10343 0.178131103515625 +10344 0.215576171875 +10345 0.211456298828125 +10346 0.17523193359375 +10347 0.128753662109375 +10348 0.1019287109375 +10349 0.0743408203125 +10350 0.04327392578125 +10351 0.038177490234375 +10352 0.076263427734375 +10353 0.14105224609375 +10354 0.186431884765625 +10355 0.188812255859375 +10356 0.1390380859375 +10357 0.041778564453125 +10358 -0.079437255859375 +10359 -0.219390869140625 +10360 -0.367828369140625 +10361 -0.494873046875 +10362 -0.556243896484375 +10363 -0.508697509765625 +10364 -0.3756103515625 +10365 -0.218902587890625 +10366 -0.063751220703125 +10367 0.091552734375 +10368 0.23602294921875 +10369 0.342987060546875 +10370 0.39520263671875 +10371 0.389373779296875 +10372 0.324249267578125 +10373 0.224090576171875 +10374 0.124267578125 +10375 0.037078857421875 +10376 -0.010101318359375 +10377 -0.019439697265625 +10378 -0.022796630859375 +10379 -0.001556396484375 +10380 0.056304931640625 +10381 0.106719970703125 +10382 0.096893310546875 +10383 0.042694091796875 +10384 -0.018035888671875 +10385 -0.07586669921875 +10386 -0.11944580078125 +10387 -0.15972900390625 +10388 -0.202606201171875 +10389 -0.24859619140625 +10390 -0.30517578125 +10391 -0.36212158203125 +10392 -0.39141845703125 +10393 -0.35528564453125 +10394 -0.249969482421875 +10395 -0.092864990234375 +10396 0.08905029296875 +10397 0.2352294921875 +10398 0.318817138671875 +10399 0.358642578125 +10400 0.347747802734375 +10401 0.28564453125 +10402 0.223175048828125 +10403 0.196746826171875 +10404 0.179840087890625 +10405 0.155548095703125 +10406 0.151214599609375 +10407 0.156951904296875 +10408 0.13177490234375 +10409 0.100799560546875 +10410 0.087127685546875 +10411 0.05487060546875 +10412 -0.009002685546875 +10413 -0.10400390625 +10414 -0.229400634765625 +10415 -0.35552978515625 +10416 -0.441925048828125 +10417 -0.473846435546875 +10418 -0.464813232421875 +10419 -0.419097900390625 +10420 -0.334320068359375 +10421 -0.227935791015625 +10422 -0.12347412109375 +10423 -0.02764892578125 +10424 0.077667236328125 +10425 0.2132568359375 +10426 0.38885498046875 +10427 0.582794189453125 +10428 0.734039306640625 +10429 0.800140380859375 +10430 0.7783203125 +10431 0.6651611328125 +10432 0.45965576171875 +10433 0.199188232421875 +10434 -0.050689697265625 +10435 -0.23297119140625 +10436 -0.33013916015625 +10437 -0.368408203125 +10438 -0.378936767578125 +10439 -0.376983642578125 +10440 -0.37969970703125 +10441 -0.391510009765625 +10442 -0.385345458984375 +10443 -0.3419189453125 +10444 -0.28289794921875 +10445 -0.251617431640625 +10446 -0.266143798828125 +10447 -0.273345947265625 +10448 -0.216796875 +10449 -0.128265380859375 +10450 -0.068145751953125 +10451 -0.0430908203125 +10452 -0.024444580078125 +10453 0.020721435546875 +10454 0.124481201171875 +10455 0.25787353515625 +10456 0.379119873046875 +10457 0.47991943359375 +10458 0.5281982421875 +10459 0.511138916015625 +10460 0.456207275390625 +10461 0.407470703125 +10462 0.383758544921875 +10463 0.35687255859375 +10464 0.31182861328125 +10465 0.250885009765625 +10466 0.1654052734375 +10467 0.035247802734375 +10468 -0.142059326171875 +10469 -0.33563232421875 +10470 -0.5345458984375 +10471 -0.72186279296875 +10472 -0.836669921875 +10473 -0.8326416015625 +10474 -0.7296142578125 +10475 -0.582550048828125 +10476 -0.440093994140625 +10477 -0.324310302734375 +10478 -0.20147705078125 +10479 -0.044647216796875 +10480 0.103973388671875 +10481 0.202392578125 +10482 0.264495849609375 +10483 0.338897705078125 +10484 0.443817138671875 +10485 0.545074462890625 +10486 0.6173095703125 +10487 0.6524658203125 +10488 0.66339111328125 +10489 0.6561279296875 +10490 0.606781005859375 +10491 0.501190185546875 +10492 0.352783203125 +10493 0.176544189453125 +10494 -0.034820556640625 +10495 -0.258209228515625 +10496 -0.44244384765625 +10497 -0.5753173828125 +10498 -0.65203857421875 +10499 -0.641632080078125 +10500 -0.562164306640625 +10501 -0.458038330078125 +10502 -0.350555419921875 +10503 -0.260528564453125 +10504 -0.192108154296875 +10505 -0.141937255859375 +10506 -0.1021728515625 +10507 -0.062896728515625 +10508 -0.011932373046875 +10509 0.062835693359375 +10510 0.148712158203125 +10511 0.241729736328125 +10512 0.34912109375 +10513 0.457305908203125 +10514 0.54388427734375 +10515 0.5728759765625 +10516 0.506591796875 +10517 0.351226806640625 +10518 0.146514892578125 +10519 -0.05523681640625 +10520 -0.21624755859375 +10521 -0.334930419921875 +10522 -0.402984619140625 +10523 -0.4412841796875 +10524 -0.49578857421875 +10525 -0.5601806640625 +10526 -0.600738525390625 +10527 -0.584228515625 +10528 -0.47930908203125 +10529 -0.27935791015625 +10530 -0.0089111328125 +10531 0.268798828125 +10532 0.482818603515625 +10533 0.60369873046875 +10534 0.650421142578125 +10535 0.66400146484375 +10536 0.6414794921875 +10537 0.572540283203125 +10538 0.498138427734375 +10539 0.439453125 +10540 0.375518798828125 +10541 0.274505615234375 +10542 0.1087646484375 +10543 -0.099395751953125 +10544 -0.3182373046875 +10545 -0.5489501953125 +10546 -0.7738037109375 +10547 -0.86383056640625 +10548 -0.870391845703125 +10549 -0.86895751953125 +10550 -0.861053466796875 +10551 -0.765869140625 +10552 -0.5301513671875 +10553 -0.214691162109375 +10554 0.137359619140625 +10555 0.474822998046875 +10556 0.76239013671875 +10557 0.867462158203125 +10558 0.870361328125 +10559 0.86480712890625 +10560 0.831817626953125 +10561 0.677581787109375 +10562 0.495880126953125 +10563 0.30767822265625 +10564 0.116180419921875 +10565 -0.110748291015625 +10566 -0.381805419921875 +10567 -0.6572265625 +10568 -0.857421875 +10569 -0.870391845703125 +10570 -0.870391845703125 +10571 -0.86444091796875 +10572 -0.85723876953125 +10573 -0.790008544921875 +10574 -0.62847900390625 +10575 -0.3956298828125 +10576 -0.126708984375 +10577 0.150115966796875 +10578 0.424041748046875 +10579 0.670623779296875 +10580 0.854522705078125 +10581 0.866485595703125 +10582 0.86920166015625 +10583 0.8653564453125 +10584 0.857147216796875 +10585 0.766845703125 +10586 0.628509521484375 +10587 0.462127685546875 +10588 0.297210693359375 +10589 0.14862060546875 +10590 -0.00537109375 +10591 -0.15753173828125 +10592 -0.31304931640625 +10593 -0.48876953125 +10594 -0.6416015625 +10595 -0.751373291015625 +10596 -0.84619140625 +10597 -0.861297607421875 +10598 -0.863250732421875 +10599 -0.856597900390625 +10600 -0.7498779296875 +10601 -0.624542236328125 +10602 -0.47808837890625 +10603 -0.253387451171875 +10604 0.003692626953125 +10605 0.2257080078125 +10606 0.427154541015625 +10607 0.643218994140625 +10608 0.855926513671875 +10609 0.870361328125 +10610 0.870361328125 +10611 0.862762451171875 +10612 0.79669189453125 +10613 0.595794677734375 +10614 0.362152099609375 +10615 0.1270751953125 +10616 -0.086944580078125 +10617 -0.2784423828125 +10618 -0.484832763671875 +10619 -0.729583740234375 +10620 -0.86688232421875 +10621 -0.870391845703125 +10622 -0.86859130859375 +10623 -0.86279296875 +10624 -0.817962646484375 +10625 -0.6116943359375 +10626 -0.3128662109375 +10627 0.039398193359375 +10628 0.422821044921875 +10629 0.805145263671875 +10630 0.870361328125 +10631 0.870361328125 +10632 0.860015869140625 +10633 0.727935791015625 +10634 0.48114013671875 +10635 0.2059326171875 +10636 -0.06103515625 +10637 -0.29913330078125 +10638 -0.516204833984375 +10639 -0.7252197265625 +10640 -0.85980224609375 +10641 -0.870391845703125 +10642 -0.870391845703125 +10643 -0.858062744140625 +10644 -0.673004150390625 +10645 -0.42694091796875 +10646 -0.2100830078125 +10647 -0.0362548828125 +10648 0.10943603515625 +10649 0.23516845703125 +10650 0.373687744140625 +10651 0.517791748046875 +10652 0.602783203125 +10653 0.635711669921875 +10654 0.655181884765625 +10655 0.65948486328125 +10656 0.651275634765625 +10657 0.61846923828125 +10658 0.53753662109375 +10659 0.404144287109375 +10660 0.22186279296875 +10661 0.003997802734375 +10662 -0.22100830078125 +10663 -0.42449951171875 +10664 -0.579833984375 +10665 -0.641876220703125 +10666 -0.6177978515625 +10667 -0.575531005859375 +10668 -0.526336669921875 +10669 -0.42645263671875 +10670 -0.2581787109375 +10671 -0.068695068359375 +10672 0.09222412109375 +10673 0.232147216796875 +10674 0.3509521484375 +10675 0.410064697265625 +10676 0.372955322265625 +10677 0.2554931640625 +10678 0.10711669921875 +10679 -0.052886962890625 +10680 -0.186279296875 +10681 -0.23291015625 +10682 -0.209442138671875 +10683 -0.174163818359375 +10684 -0.126739501953125 +10685 -0.048126220703125 +10686 0.0426025390625 +10687 0.10748291015625 +10688 0.1409912109375 +10689 0.19708251953125 +10690 0.273651123046875 +10691 0.31768798828125 +10692 0.341094970703125 +10693 0.368011474609375 +10694 0.37249755859375 +10695 0.30072021484375 +10696 0.1517333984375 +10697 -0.01470947265625 +10698 -0.1883544921875 +10699 -0.372711181640625 +10700 -0.51397705078125 +10701 -0.57177734375 +10702 -0.53948974609375 +10703 -0.43511962890625 +10704 -0.2962646484375 +10705 -0.161102294921875 +10706 -0.0435791015625 +10707 0.060394287109375 +10708 0.13665771484375 +10709 0.170135498046875 +10710 0.16552734375 +10711 0.15728759765625 +10712 0.150787353515625 +10713 0.12200927734375 +10714 0.080108642578125 +10715 0.05126953125 +10716 0.062896728515625 +10717 0.09271240234375 +10718 0.092987060546875 +10719 0.07855224609375 +10720 0.06427001953125 +10721 0.0347900390625 +10722 -0.01171875 +10723 -0.056060791015625 +10724 -0.055511474609375 +10725 -0.010467529296875 +10726 0.02508544921875 +10727 0.025665283203125 +10728 0.017333984375 +10729 0.00189208984375 +10730 -0.03173828125 +10731 -0.071502685546875 +10732 -0.13543701171875 +10733 -0.219970703125 +10734 -0.300506591796875 +10735 -0.376312255859375 +10736 -0.416107177734375 +10737 -0.371124267578125 +10738 -0.242279052734375 +10739 -0.069732666015625 +10740 0.125640869140625 +10741 0.31268310546875 +10742 0.45501708984375 +10743 0.554779052734375 +10744 0.61065673828125 +10745 0.610931396484375 +10746 0.531463623046875 +10747 0.3883056640625 +10748 0.23468017578125 +10749 0.095245361328125 +10750 -0.00396728515625 +10751 -0.04852294921875 +10752 -0.055145263671875 +10753 -0.0758056640625 +10754 -0.138702392578125 +10755 -0.209197998046875 +10756 -0.289031982421875 +10757 -0.37884521484375 +10758 -0.456329345703125 +10759 -0.51641845703125 +10760 -0.519287109375 +10761 -0.458251953125 +10762 -0.384796142578125 +10763 -0.323699951171875 +10764 -0.269287109375 +10765 -0.1951904296875 +10766 -0.100006103515625 +10767 -0.01055908203125 +10768 0.1033935546875 +10769 0.24908447265625 +10770 0.373199462890625 +10771 0.45806884765625 +10772 0.511474609375 +10773 0.565399169921875 +10774 0.61138916015625 +10775 0.5897216796875 +10776 0.4906005859375 +10777 0.33148193359375 +10778 0.147796630859375 +10779 -0.01873779296875 +10780 -0.140289306640625 +10781 -0.191986083984375 +10782 -0.184295654296875 +10783 -0.161834716796875 +10784 -0.166595458984375 +10785 -0.19390869140625 +10786 -0.22442626953125 +10787 -0.279754638671875 +10788 -0.3389892578125 +10789 -0.3543701171875 +10790 -0.348175048828125 +10791 -0.32598876953125 +10792 -0.2581787109375 +10793 -0.139801025390625 +10794 0.014617919921875 +10795 0.144378662109375 +10796 0.221038818359375 +10797 0.27069091796875 +10798 0.294036865234375 +10799 0.311767578125 +10800 0.339141845703125 +10801 0.360260009765625 +10802 0.360504150390625 +10803 0.308380126953125 +10804 0.18170166015625 +10805 0.0047607421875 +10806 -0.17559814453125 +10807 -0.3143310546875 +10808 -0.36785888671875 +10809 -0.36248779296875 +10810 -0.343536376953125 +10811 -0.3018798828125 +10812 -0.231414794921875 +10813 -0.117645263671875 +10814 0.007049560546875 +10815 0.087982177734375 +10816 0.13946533203125 +10817 0.17425537109375 +10818 0.188201904296875 +10819 0.171234130859375 +10820 0.118438720703125 +10821 0.05706787109375 +10822 -0.010711669921875 +10823 -0.0914306640625 +10824 -0.162322998046875 +10825 -0.194549560546875 +10826 -0.1492919921875 +10827 -0.02166748046875 +10828 0.124053955078125 +10829 0.211151123046875 +10830 0.240447998046875 +10831 0.242218017578125 +10832 0.2257080078125 +10833 0.194366455078125 +10834 0.115509033203125 +10835 0.0128173828125 +10836 -0.053802490234375 +10837 -0.110626220703125 +10838 -0.199493408203125 +10839 -0.29437255859375 +10840 -0.33221435546875 +10841 -0.27972412109375 +10842 -0.185333251953125 +10843 -0.128204345703125 +10844 -0.115692138671875 +10845 -0.116455078125 +10846 -0.105926513671875 +10847 -0.053955078125 +10848 0.048797607421875 +10849 0.157318115234375 +10850 0.212005615234375 +10851 0.218475341796875 +10852 0.23724365234375 +10853 0.30535888671875 +10854 0.38128662109375 +10855 0.404449462890625 +10856 0.3944091796875 +10857 0.3885498046875 +10858 0.362640380859375 +10859 0.27362060546875 +10860 0.11712646484375 +10861 -0.054901123046875 +10862 -0.19085693359375 +10863 -0.28570556640625 +10864 -0.339263916015625 +10865 -0.3775634765625 +10866 -0.445709228515625 +10867 -0.535064697265625 +10868 -0.629058837890625 +10869 -0.697601318359375 +10870 -0.70391845703125 +10871 -0.6424560546875 +10872 -0.491241455078125 +10873 -0.265716552734375 +10874 -0.023712158203125 +10875 0.201751708984375 +10876 0.375823974609375 +10877 0.485076904296875 +10878 0.56884765625 +10879 0.634765625 +10880 0.63763427734375 +10881 0.5660400390625 +10882 0.4720458984375 +10883 0.40692138671875 +10884 0.3778076171875 +10885 0.376953125 +10886 0.371978759765625 +10887 0.313140869140625 +10888 0.184417724609375 +10889 0.011199951171875 +10890 -0.171051025390625 +10891 -0.33740234375 +10892 -0.47198486328125 +10893 -0.560394287109375 +10894 -0.58056640625 +10895 -0.54754638671875 +10896 -0.508575439453125 +10897 -0.459503173828125 +10898 -0.394378662109375 +10899 -0.35260009765625 +10900 -0.31170654296875 +10901 -0.197418212890625 +10902 -0.007965087890625 +10903 0.207489013671875 +10904 0.409210205078125 +10905 0.57208251953125 +10906 0.66595458984375 +10907 0.65875244140625 +10908 0.56744384765625 +10909 0.431396484375 +10910 0.29443359375 +10911 0.182464599609375 +10912 0.06365966796875 +10913 -0.075958251953125 +10914 -0.189422607421875 +10915 -0.271942138671875 +10916 -0.342529296875 +10917 -0.364166259765625 +10918 -0.327239990234375 +10919 -0.2769775390625 +10920 -0.253692626953125 +10921 -0.24365234375 +10922 -0.1983642578125 +10923 -0.116241455078125 +10924 -0.036834716796875 +10925 0.034881591796875 +10926 0.09124755859375 +10927 0.10888671875 +10928 0.125518798828125 +10929 0.15771484375 +10930 0.17828369140625 +10931 0.17108154296875 +10932 0.129974365234375 +10933 0.082427978515625 +10934 0.027679443359375 +10935 -0.065643310546875 +10936 -0.15936279296875 +10937 -0.21307373046875 +10938 -0.234649658203125 +10939 -0.2001953125 +10940 -0.119171142578125 +10941 -0.024749755859375 +10942 0.085784912109375 +10943 0.178131103515625 +10944 0.215576171875 +10945 0.211456298828125 +10946 0.17523193359375 +10947 0.128753662109375 +10948 0.1019287109375 +10949 0.0743408203125 +10950 0.04327392578125 +10951 0.038177490234375 +10952 0.076263427734375 +10953 0.14105224609375 +10954 0.186431884765625 +10955 0.188812255859375 +10956 0.1390380859375 +10957 0.041778564453125 +10958 -0.079437255859375 +10959 -0.219390869140625 +10960 -0.367828369140625 +10961 -0.494873046875 +10962 -0.556243896484375 +10963 -0.508697509765625 +10964 -0.3756103515625 +10965 -0.218902587890625 +10966 -0.063751220703125 +10967 0.091552734375 +10968 0.23602294921875 +10969 0.342987060546875 +10970 0.39520263671875 +10971 0.389373779296875 +10972 0.324249267578125 +10973 0.224090576171875 +10974 0.124267578125 +10975 0.037078857421875 +10976 -0.010101318359375 +10977 -0.019439697265625 +10978 -0.022796630859375 +10979 -0.001556396484375 +10980 0.056304931640625 +10981 0.106719970703125 +10982 0.096893310546875 +10983 0.042694091796875 +10984 -0.018035888671875 +10985 -0.07586669921875 +10986 -0.11944580078125 +10987 -0.15972900390625 +10988 -0.202606201171875 +10989 -0.24859619140625 +10990 -0.30517578125 +10991 -0.36212158203125 +10992 -0.39141845703125 +10993 -0.35528564453125 +10994 -0.249969482421875 +10995 -0.092864990234375 +10996 0.08905029296875 +10997 0.2352294921875 +10998 0.318817138671875 +10999 0.358642578125 +11000 0.347747802734375 +11001 0.28564453125 +11002 0.223175048828125 +11003 0.196746826171875 +11004 0.179840087890625 +11005 0.155548095703125 +11006 0.151214599609375 +11007 0.156951904296875 +11008 0.13177490234375 +11009 0.100799560546875 +11010 0.087127685546875 +11011 0.05487060546875 +11012 -0.009002685546875 +11013 -0.10400390625 +11014 -0.229400634765625 +11015 -0.35552978515625 +11016 -0.441925048828125 +11017 -0.473846435546875 +11018 -0.464813232421875 +11019 -0.419097900390625 +11020 -0.334320068359375 +11021 -0.227935791015625 +11022 -0.12347412109375 +11023 -0.02764892578125 +11024 0.077667236328125 +11025 0.2132568359375 +11026 0.38885498046875 +11027 0.582794189453125 +11028 0.734039306640625 +11029 0.800140380859375 +11030 0.7783203125 +11031 0.6651611328125 +11032 0.45965576171875 +11033 0.199188232421875 +11034 -0.050689697265625 +11035 -0.23297119140625 +11036 -0.33013916015625 +11037 -0.368408203125 +11038 -0.378936767578125 +11039 -0.376983642578125 +11040 -0.37969970703125 +11041 -0.391510009765625 +11042 -0.385345458984375 +11043 -0.3419189453125 +11044 -0.28289794921875 +11045 -0.251617431640625 +11046 -0.266143798828125 +11047 -0.273345947265625 +11048 -0.216796875 +11049 -0.128265380859375 +11050 -0.068145751953125 +11051 -0.0430908203125 +11052 -0.024444580078125 +11053 0.020721435546875 +11054 0.124481201171875 +11055 0.25787353515625 +11056 0.379119873046875 +11057 0.47991943359375 +11058 0.5281982421875 +11059 0.511138916015625 +11060 0.456207275390625 +11061 0.407470703125 +11062 0.383758544921875 +11063 0.35687255859375 +11064 0.31182861328125 +11065 0.250885009765625 +11066 0.1654052734375 +11067 0.035247802734375 +11068 -0.142059326171875 +11069 -0.33563232421875 +11070 -0.5345458984375 +11071 -0.72186279296875 +11072 -0.836669921875 +11073 -0.8326416015625 +11074 -0.7296142578125 +11075 -0.582550048828125 +11076 -0.440093994140625 +11077 -0.324310302734375 +11078 -0.20147705078125 +11079 -0.044647216796875 +11080 0.103973388671875 +11081 0.202392578125 +11082 0.264495849609375 +11083 0.338897705078125 +11084 0.443817138671875 +11085 0.545074462890625 +11086 0.6173095703125 +11087 0.6524658203125 +11088 0.66339111328125 +11089 0.6561279296875 +11090 0.606781005859375 +11091 0.501190185546875 +11092 0.352783203125 +11093 0.176544189453125 +11094 -0.034820556640625 +11095 -0.258209228515625 +11096 -0.44244384765625 +11097 -0.5753173828125 +11098 -0.65203857421875 +11099 -0.641632080078125 +11100 -0.562164306640625 +11101 -0.458038330078125 +11102 -0.350555419921875 +11103 -0.260528564453125 +11104 -0.192108154296875 +11105 -0.141937255859375 +11106 -0.1021728515625 +11107 -0.062896728515625 +11108 -0.011932373046875 +11109 0.062835693359375 +11110 0.148712158203125 +11111 0.241729736328125 +11112 0.34912109375 +11113 0.457305908203125 +11114 0.54388427734375 +11115 0.5728759765625 +11116 0.506591796875 +11117 0.351226806640625 +11118 0.146514892578125 +11119 -0.05523681640625 +11120 -0.21624755859375 +11121 -0.334930419921875 +11122 -0.402984619140625 +11123 -0.4412841796875 +11124 -0.49578857421875 +11125 -0.5601806640625 +11126 -0.600738525390625 +11127 -0.584228515625 +11128 -0.47930908203125 +11129 -0.27935791015625 +11130 -0.0089111328125 +11131 0.268798828125 +11132 0.482818603515625 +11133 0.60369873046875 +11134 0.650421142578125 +11135 0.66400146484375 +11136 0.6414794921875 +11137 0.572540283203125 +11138 0.498138427734375 +11139 0.439453125 +11140 0.375518798828125 +11141 0.274505615234375 +11142 0.1087646484375 +11143 -0.099395751953125 +11144 -0.3182373046875 +11145 -0.5489501953125 +11146 -0.7738037109375 +11147 -0.86383056640625 +11148 -0.870391845703125 +11149 -0.86895751953125 +11150 -0.861053466796875 +11151 -0.765869140625 +11152 -0.5301513671875 +11153 -0.214691162109375 +11154 0.137359619140625 +11155 0.474822998046875 +11156 0.76239013671875 +11157 0.867462158203125 +11158 0.870361328125 +11159 0.86480712890625 +11160 0.831817626953125 +11161 0.677581787109375 +11162 0.495880126953125 +11163 0.30767822265625 +11164 0.116180419921875 +11165 -0.110748291015625 +11166 -0.381805419921875 +11167 -0.6572265625 +11168 -0.857421875 +11169 -0.870391845703125 +11170 -0.870391845703125 +11171 -0.86444091796875 +11172 -0.85723876953125 +11173 -0.790008544921875 +11174 -0.62847900390625 +11175 -0.3956298828125 +11176 -0.126708984375 +11177 0.150115966796875 +11178 0.424041748046875 +11179 0.670623779296875 +11180 0.854522705078125 +11181 0.866485595703125 +11182 0.86920166015625 +11183 0.8653564453125 +11184 0.857147216796875 +11185 0.766845703125 +11186 0.628509521484375 +11187 0.462127685546875 +11188 0.297210693359375 +11189 0.14862060546875 +11190 -0.00537109375 +11191 -0.15753173828125 +11192 -0.31304931640625 +11193 -0.48876953125 +11194 -0.6416015625 +11195 -0.751373291015625 +11196 -0.84619140625 +11197 -0.861297607421875 +11198 -0.863250732421875 +11199 -0.856597900390625 +11200 -0.7498779296875 +11201 -0.624542236328125 +11202 -0.47808837890625 +11203 -0.253387451171875 +11204 0.003692626953125 +11205 0.2257080078125 +11206 0.427154541015625 +11207 0.643218994140625 +11208 0.855926513671875 +11209 0.870361328125 +11210 0.870361328125 +11211 0.862762451171875 +11212 0.79669189453125 +11213 0.595794677734375 +11214 0.362152099609375 +11215 0.1270751953125 +11216 -0.086944580078125 +11217 -0.2784423828125 +11218 -0.484832763671875 +11219 -0.729583740234375 +11220 -0.86688232421875 +11221 -0.870391845703125 +11222 -0.86859130859375 +11223 -0.86279296875 +11224 -0.817962646484375 +11225 -0.6116943359375 +11226 -0.3128662109375 +11227 0.039398193359375 +11228 0.422821044921875 +11229 0.805145263671875 +11230 0.870361328125 +11231 0.870361328125 +11232 0.860015869140625 +11233 0.727935791015625 +11234 0.48114013671875 +11235 0.2059326171875 +11236 -0.06103515625 +11237 -0.29913330078125 +11238 -0.516204833984375 +11239 -0.7252197265625 +11240 -0.85980224609375 +11241 -0.870391845703125 +11242 -0.870391845703125 +11243 -0.858062744140625 +11244 -0.673004150390625 +11245 -0.42694091796875 +11246 -0.2100830078125 +11247 -0.0362548828125 +11248 0.10943603515625 +11249 0.23516845703125 +11250 0.373687744140625 +11251 0.517791748046875 +11252 0.602783203125 +11253 0.635711669921875 +11254 0.655181884765625 +11255 0.65948486328125 +11256 0.651275634765625 +11257 0.61846923828125 +11258 0.53753662109375 +11259 0.404144287109375 +11260 0.22186279296875 +11261 0.003997802734375 +11262 -0.22100830078125 +11263 -0.42449951171875 +11264 -0.579833984375 +11265 -0.641876220703125 +11266 -0.6177978515625 +11267 -0.575531005859375 +11268 -0.526336669921875 +11269 -0.42645263671875 +11270 -0.2581787109375 +11271 -0.068695068359375 +11272 0.09222412109375 +11273 0.232147216796875 +11274 0.3509521484375 +11275 0.410064697265625 +11276 0.372955322265625 +11277 0.2554931640625 +11278 0.10711669921875 +11279 -0.052886962890625 +11280 -0.186279296875 +11281 -0.23291015625 +11282 -0.209442138671875 +11283 -0.174163818359375 +11284 -0.126739501953125 +11285 -0.048126220703125 +11286 0.0426025390625 +11287 0.10748291015625 +11288 0.1409912109375 +11289 0.19708251953125 +11290 0.273651123046875 +11291 0.31768798828125 +11292 0.341094970703125 +11293 0.368011474609375 +11294 0.37249755859375 +11295 0.30072021484375 +11296 0.1517333984375 +11297 -0.01470947265625 +11298 -0.1883544921875 +11299 -0.372711181640625 +11300 -0.51397705078125 +11301 -0.57177734375 +11302 -0.53948974609375 +11303 -0.43511962890625 +11304 -0.2962646484375 +11305 -0.161102294921875 +11306 -0.0435791015625 +11307 0.060394287109375 +11308 0.13665771484375 +11309 0.170135498046875 +11310 0.16552734375 +11311 0.15728759765625 +11312 0.150787353515625 +11313 0.12200927734375 +11314 0.080108642578125 +11315 0.05126953125 +11316 0.062896728515625 +11317 0.09271240234375 +11318 0.092987060546875 +11319 0.07855224609375 +11320 0.06427001953125 +11321 0.0347900390625 +11322 -0.01171875 +11323 -0.056060791015625 +11324 -0.055511474609375 +11325 -0.010467529296875 +11326 0.02508544921875 +11327 0.025665283203125 +11328 0.017333984375 +11329 0.00189208984375 +11330 -0.03173828125 +11331 -0.071502685546875 +11332 -0.13543701171875 +11333 -0.219970703125 +11334 -0.300506591796875 +11335 -0.376312255859375 +11336 -0.416107177734375 +11337 -0.371124267578125 +11338 -0.242279052734375 +11339 -0.069732666015625 +11340 0.125640869140625 +11341 0.31268310546875 +11342 0.45501708984375 +11343 0.554779052734375 +11344 0.61065673828125 +11345 0.610931396484375 +11346 0.531463623046875 +11347 0.3883056640625 +11348 0.23468017578125 +11349 0.095245361328125 +11350 -0.00396728515625 +11351 -0.04852294921875 +11352 -0.055145263671875 +11353 -0.0758056640625 +11354 -0.138702392578125 +11355 -0.209197998046875 +11356 -0.289031982421875 +11357 -0.37884521484375 +11358 -0.456329345703125 +11359 -0.51641845703125 +11360 -0.519287109375 +11361 -0.458251953125 +11362 -0.384796142578125 +11363 -0.323699951171875 +11364 -0.269287109375 +11365 -0.1951904296875 +11366 -0.100006103515625 +11367 -0.01055908203125 +11368 0.1033935546875 +11369 0.24908447265625 +11370 0.373199462890625 +11371 0.45806884765625 +11372 0.511474609375 +11373 0.565399169921875 +11374 0.61138916015625 +11375 0.5897216796875 +11376 0.4906005859375 +11377 0.33148193359375 +11378 0.147796630859375 +11379 -0.01873779296875 +11380 -0.140289306640625 +11381 -0.191986083984375 +11382 -0.184295654296875 +11383 -0.161834716796875 +11384 -0.166595458984375 +11385 -0.19390869140625 +11386 -0.22442626953125 +11387 -0.279754638671875 +11388 -0.3389892578125 +11389 -0.3543701171875 +11390 -0.348175048828125 +11391 -0.32598876953125 +11392 -0.2581787109375 +11393 -0.139801025390625 +11394 0.014617919921875 +11395 0.144378662109375 +11396 0.221038818359375 +11397 0.27069091796875 +11398 0.294036865234375 +11399 0.311767578125 +11400 0.339141845703125 +11401 0.360260009765625 +11402 0.360504150390625 +11403 0.308380126953125 +11404 0.18170166015625 +11405 0.0047607421875 +11406 -0.17559814453125 +11407 -0.3143310546875 +11408 -0.36785888671875 +11409 -0.36248779296875 +11410 -0.343536376953125 +11411 -0.3018798828125 +11412 -0.231414794921875 +11413 -0.117645263671875 +11414 0.007049560546875 +11415 0.087982177734375 +11416 0.13946533203125 +11417 0.17425537109375 +11418 0.188201904296875 +11419 0.171234130859375 +11420 0.118438720703125 +11421 0.05706787109375 +11422 -0.010711669921875 +11423 -0.0914306640625 +11424 -0.162322998046875 +11425 -0.194549560546875 +11426 -0.1492919921875 +11427 -0.02166748046875 +11428 0.124053955078125 +11429 0.211151123046875 +11430 0.240447998046875 +11431 0.242218017578125 +11432 0.2257080078125 +11433 0.194366455078125 +11434 0.115509033203125 +11435 0.0128173828125 +11436 -0.053802490234375 +11437 -0.110626220703125 +11438 -0.199493408203125 +11439 -0.29437255859375 +11440 -0.33221435546875 +11441 -0.27972412109375 +11442 -0.185333251953125 +11443 -0.128204345703125 +11444 -0.115692138671875 +11445 -0.116455078125 +11446 -0.105926513671875 +11447 -0.053955078125 +11448 0.048797607421875 +11449 0.157318115234375 +11450 0.212005615234375 +11451 0.218475341796875 +11452 0.23724365234375 +11453 0.30535888671875 +11454 0.38128662109375 +11455 0.404449462890625 +11456 0.3944091796875 +11457 0.3885498046875 +11458 0.362640380859375 +11459 0.27362060546875 +11460 0.11712646484375 +11461 -0.054901123046875 +11462 -0.19085693359375 +11463 -0.28570556640625 +11464 -0.339263916015625 +11465 -0.3775634765625 +11466 -0.445709228515625 +11467 -0.535064697265625 +11468 -0.629058837890625 +11469 -0.697601318359375 +11470 -0.70391845703125 +11471 -0.6424560546875 +11472 -0.491241455078125 +11473 -0.265716552734375 +11474 -0.023712158203125 +11475 0.201751708984375 +11476 0.375823974609375 +11477 0.485076904296875 +11478 0.56884765625 +11479 0.634765625 +11480 0.63763427734375 +11481 0.5660400390625 +11482 0.4720458984375 +11483 0.40692138671875 +11484 0.3778076171875 +11485 0.376953125 +11486 0.371978759765625 +11487 0.313140869140625 +11488 0.184417724609375 +11489 0.011199951171875 +11490 -0.171051025390625 +11491 -0.33740234375 +11492 -0.47198486328125 +11493 -0.560394287109375 +11494 -0.58056640625 +11495 -0.54754638671875 +11496 -0.508575439453125 +11497 -0.459503173828125 +11498 -0.394378662109375 +11499 -0.35260009765625 +11500 -0.31170654296875 +11501 -0.197418212890625 +11502 -0.007965087890625 +11503 0.207489013671875 +11504 0.409210205078125 +11505 0.57208251953125 +11506 0.66595458984375 +11507 0.65875244140625 +11508 0.56744384765625 +11509 0.431396484375 +11510 0.29443359375 +11511 0.182464599609375 +11512 0.06365966796875 +11513 -0.075958251953125 +11514 -0.189422607421875 +11515 -0.271942138671875 +11516 -0.342529296875 +11517 -0.364166259765625 +11518 -0.327239990234375 +11519 -0.2769775390625 +11520 -0.253692626953125 +11521 -0.24365234375 +11522 -0.1983642578125 +11523 -0.116241455078125 +11524 -0.036834716796875 +11525 0.034881591796875 +11526 0.09124755859375 +11527 0.10888671875 +11528 0.125518798828125 +11529 0.15771484375 +11530 0.17828369140625 +11531 0.17108154296875 +11532 0.129974365234375 +11533 0.082427978515625 +11534 0.027679443359375 +11535 -0.065643310546875 +11536 -0.15936279296875 +11537 -0.21307373046875 +11538 -0.234649658203125 +11539 -0.2001953125 +11540 -0.119171142578125 +11541 -0.024749755859375 +11542 0.085784912109375 +11543 0.178131103515625 +11544 0.215576171875 +11545 0.211456298828125 +11546 0.17523193359375 +11547 0.128753662109375 +11548 0.1019287109375 +11549 0.0743408203125 +11550 0.04327392578125 +11551 0.038177490234375 +11552 0.076263427734375 +11553 0.14105224609375 +11554 0.186431884765625 +11555 0.188812255859375 +11556 0.1390380859375 +11557 0.041778564453125 +11558 -0.079437255859375 +11559 -0.219390869140625 +11560 -0.367828369140625 +11561 -0.494873046875 +11562 -0.556243896484375 +11563 -0.508697509765625 +11564 -0.3756103515625 +11565 -0.218902587890625 +11566 -0.063751220703125 +11567 0.091552734375 +11568 0.23602294921875 +11569 0.342987060546875 +11570 0.39520263671875 +11571 0.389373779296875 +11572 0.324249267578125 +11573 0.224090576171875 +11574 0.124267578125 +11575 0.037078857421875 +11576 -0.010101318359375 +11577 -0.019439697265625 +11578 -0.022796630859375 +11579 -0.001556396484375 +11580 0.056304931640625 +11581 0.106719970703125 +11582 0.096893310546875 +11583 0.042694091796875 +11584 -0.018035888671875 +11585 -0.07586669921875 +11586 -0.11944580078125 +11587 -0.15972900390625 +11588 -0.202606201171875 +11589 -0.24859619140625 +11590 -0.30517578125 +11591 -0.36212158203125 +11592 -0.39141845703125 +11593 -0.35528564453125 +11594 -0.249969482421875 +11595 -0.092864990234375 +11596 0.08905029296875 +11597 0.2352294921875 +11598 0.318817138671875 +11599 0.358642578125 +11600 0.347747802734375 +11601 0.28564453125 +11602 0.223175048828125 +11603 0.196746826171875 +11604 0.179840087890625 +11605 0.155548095703125 +11606 0.151214599609375 +11607 0.156951904296875 +11608 0.13177490234375 +11609 0.100799560546875 +11610 0.087127685546875 +11611 0.05487060546875 +11612 -0.009002685546875 +11613 -0.10400390625 +11614 -0.229400634765625 +11615 -0.35552978515625 +11616 -0.441925048828125 +11617 -0.473846435546875 +11618 -0.464813232421875 +11619 -0.419097900390625 +11620 -0.334320068359375 +11621 -0.227935791015625 +11622 -0.12347412109375 +11623 -0.02764892578125 +11624 0.077667236328125 +11625 0.2132568359375 +11626 0.38885498046875 +11627 0.582794189453125 +11628 0.734039306640625 +11629 0.800140380859375 +11630 0.7783203125 +11631 0.6651611328125 +11632 0.45965576171875 +11633 0.199188232421875 +11634 -0.050689697265625 +11635 -0.23297119140625 +11636 -0.33013916015625 +11637 -0.368408203125 +11638 -0.378936767578125 +11639 -0.376983642578125 +11640 -0.37969970703125 +11641 -0.391510009765625 +11642 -0.385345458984375 +11643 -0.3419189453125 +11644 -0.28289794921875 +11645 -0.251617431640625 +11646 -0.266143798828125 +11647 -0.273345947265625 +11648 -0.216796875 +11649 -0.128265380859375 +11650 -0.068145751953125 +11651 -0.0430908203125 +11652 -0.024444580078125 +11653 0.020721435546875 +11654 0.124481201171875 +11655 0.25787353515625 +11656 0.379119873046875 +11657 0.47991943359375 +11658 0.5281982421875 +11659 0.511138916015625 +11660 0.456207275390625 +11661 0.407470703125 +11662 0.383758544921875 +11663 0.35687255859375 +11664 0.31182861328125 +11665 0.250885009765625 +11666 0.1654052734375 +11667 0.035247802734375 +11668 -0.142059326171875 +11669 -0.33563232421875 +11670 -0.5345458984375 +11671 -0.72186279296875 +11672 -0.836669921875 +11673 -0.8326416015625 +11674 -0.7296142578125 +11675 -0.582550048828125 +11676 -0.440093994140625 +11677 -0.324310302734375 +11678 -0.20147705078125 +11679 -0.044647216796875 +11680 0.103973388671875 +11681 0.202392578125 +11682 0.264495849609375 +11683 0.338897705078125 +11684 0.443817138671875 +11685 0.545074462890625 +11686 0.6173095703125 +11687 0.6524658203125 +11688 0.66339111328125 +11689 0.6561279296875 +11690 0.606781005859375 +11691 0.501190185546875 +11692 0.352783203125 +11693 0.176544189453125 +11694 -0.034820556640625 +11695 -0.258209228515625 +11696 -0.44244384765625 +11697 -0.5753173828125 +11698 -0.65203857421875 +11699 -0.641632080078125 +11700 -0.562164306640625 +11701 -0.458038330078125 +11702 -0.350555419921875 +11703 -0.260528564453125 +11704 -0.192108154296875 +11705 -0.141937255859375 +11706 -0.1021728515625 +11707 -0.062896728515625 +11708 -0.011932373046875 +11709 0.062835693359375 +11710 0.148712158203125 +11711 0.241729736328125 +11712 0.34912109375 +11713 0.457305908203125 +11714 0.54388427734375 +11715 0.5728759765625 +11716 0.506591796875 +11717 0.351226806640625 +11718 0.146514892578125 +11719 -0.05523681640625 +11720 -0.21624755859375 +11721 -0.334930419921875 +11722 -0.402984619140625 +11723 -0.4412841796875 +11724 -0.49578857421875 +11725 -0.5601806640625 +11726 -0.600738525390625 +11727 -0.584228515625 +11728 -0.47930908203125 +11729 -0.27935791015625 +11730 -0.0089111328125 +11731 0.268798828125 +11732 0.482818603515625 +11733 0.60369873046875 +11734 0.650421142578125 +11735 0.66400146484375 +11736 0.6414794921875 +11737 0.572540283203125 +11738 0.498138427734375 +11739 0.439453125 +11740 0.375518798828125 +11741 0.274505615234375 +11742 0.1087646484375 +11743 -0.099395751953125 +11744 -0.3182373046875 +11745 -0.5489501953125 +11746 -0.7738037109375 +11747 -0.86383056640625 +11748 -0.870391845703125 +11749 -0.86895751953125 +11750 -0.861053466796875 +11751 -0.765869140625 +11752 -0.5301513671875 +11753 -0.214691162109375 +11754 0.137359619140625 +11755 0.474822998046875 +11756 0.76239013671875 +11757 0.867462158203125 +11758 0.870361328125 +11759 0.86480712890625 +11760 0.831817626953125 +11761 0.677581787109375 +11762 0.495880126953125 +11763 0.30767822265625 +11764 0.116180419921875 +11765 -0.110748291015625 +11766 -0.381805419921875 +11767 -0.6572265625 +11768 -0.857421875 +11769 -0.870391845703125 +11770 -0.870391845703125 +11771 -0.86444091796875 +11772 -0.85723876953125 +11773 -0.790008544921875 +11774 -0.62847900390625 +11775 -0.3956298828125 +11776 -0.126708984375 +11777 0.150115966796875 +11778 0.424041748046875 +11779 0.670623779296875 +11780 0.854522705078125 +11781 0.866485595703125 +11782 0.86920166015625 +11783 0.8653564453125 +11784 0.857147216796875 +11785 0.766845703125 +11786 0.628509521484375 +11787 0.462127685546875 +11788 0.297210693359375 +11789 0.14862060546875 +11790 -0.00537109375 +11791 -0.15753173828125 +11792 -0.31304931640625 +11793 -0.48876953125 +11794 -0.6416015625 +11795 -0.751373291015625 +11796 -0.84619140625 +11797 -0.861297607421875 +11798 -0.863250732421875 +11799 -0.856597900390625 +11800 -0.7498779296875 +11801 -0.624542236328125 +11802 -0.47808837890625 +11803 -0.253387451171875 +11804 0.003692626953125 +11805 0.2257080078125 +11806 0.427154541015625 +11807 0.643218994140625 +11808 0.855926513671875 +11809 0.870361328125 +11810 0.870361328125 +11811 0.862762451171875 +11812 0.79669189453125 +11813 0.595794677734375 +11814 0.362152099609375 +11815 0.1270751953125 +11816 -0.086944580078125 +11817 -0.2784423828125 +11818 -0.484832763671875 +11819 -0.729583740234375 +11820 -0.86688232421875 +11821 -0.870391845703125 +11822 -0.86859130859375 +11823 -0.86279296875 +11824 -0.817962646484375 +11825 -0.6116943359375 +11826 -0.3128662109375 +11827 0.039398193359375 +11828 0.422821044921875 +11829 0.805145263671875 +11830 0.870361328125 +11831 0.870361328125 +11832 0.860015869140625 +11833 0.727935791015625 +11834 0.48114013671875 +11835 0.2059326171875 +11836 -0.06103515625 +11837 -0.29913330078125 +11838 -0.516204833984375 +11839 -0.7252197265625 +11840 -0.85980224609375 +11841 -0.870391845703125 +11842 -0.870391845703125 +11843 -0.858062744140625 +11844 -0.673004150390625 +11845 -0.42694091796875 +11846 -0.2100830078125 +11847 -0.0362548828125 +11848 0.10943603515625 +11849 0.23516845703125 +11850 0.373687744140625 +11851 0.517791748046875 +11852 0.602783203125 +11853 0.635711669921875 +11854 0.655181884765625 +11855 0.65948486328125 +11856 0.651275634765625 +11857 0.61846923828125 +11858 0.53753662109375 +11859 0.404144287109375 +11860 0.22186279296875 +11861 0.003997802734375 +11862 -0.22100830078125 +11863 -0.42449951171875 +11864 -0.579833984375 +11865 -0.641876220703125 +11866 -0.6177978515625 +11867 -0.575531005859375 +11868 -0.526336669921875 +11869 -0.42645263671875 +11870 -0.2581787109375 +11871 -0.068695068359375 +11872 0.09222412109375 +11873 0.232147216796875 +11874 0.3509521484375 +11875 0.410064697265625 +11876 0.372955322265625 +11877 0.2554931640625 +11878 0.10711669921875 +11879 -0.052886962890625 +11880 -0.186279296875 +11881 -0.23291015625 +11882 -0.209442138671875 +11883 -0.174163818359375 +11884 -0.126739501953125 +11885 -0.048126220703125 +11886 0.0426025390625 +11887 0.10748291015625 +11888 0.1409912109375 +11889 0.19708251953125 +11890 0.273651123046875 +11891 0.31768798828125 +11892 0.341094970703125 +11893 0.368011474609375 +11894 0.37249755859375 +11895 0.30072021484375 +11896 0.1517333984375 +11897 -0.01470947265625 +11898 -0.1883544921875 +11899 -0.372711181640625 +11900 -0.51397705078125 +11901 -0.57177734375 +11902 -0.53948974609375 +11903 -0.43511962890625 +11904 -0.2962646484375 +11905 -0.161102294921875 +11906 -0.0435791015625 +11907 0.060394287109375 +11908 0.13665771484375 +11909 0.170135498046875 +11910 0.16552734375 +11911 0.15728759765625 +11912 0.150787353515625 +11913 0.12200927734375 +11914 0.080108642578125 +11915 0.05126953125 +11916 0.062896728515625 +11917 0.09271240234375 +11918 0.092987060546875 +11919 0.07855224609375 +11920 0.06427001953125 +11921 0.0347900390625 +11922 -0.01171875 +11923 -0.056060791015625 +11924 -0.055511474609375 +11925 -0.010467529296875 +11926 0.02508544921875 +11927 0.025665283203125 +11928 0.017333984375 +11929 0.00189208984375 +11930 -0.03173828125 +11931 -0.071502685546875 +11932 -0.13543701171875 +11933 -0.219970703125 +11934 -0.300506591796875 +11935 -0.376312255859375 +11936 -0.416107177734375 +11937 -0.371124267578125 +11938 -0.242279052734375 +11939 -0.069732666015625 +11940 0.125640869140625 +11941 0.31268310546875 +11942 0.45501708984375 +11943 0.554779052734375 +11944 0.61065673828125 +11945 0.610931396484375 +11946 0.531463623046875 +11947 0.3883056640625 +11948 0.23468017578125 +11949 0.095245361328125 +11950 -0.00396728515625 +11951 -0.04852294921875 +11952 -0.055145263671875 +11953 -0.0758056640625 +11954 -0.138702392578125 +11955 -0.209197998046875 +11956 -0.289031982421875 +11957 -0.37884521484375 +11958 -0.456329345703125 +11959 -0.51641845703125 +11960 -0.519287109375 +11961 -0.458251953125 +11962 -0.384796142578125 +11963 -0.323699951171875 +11964 -0.269287109375 +11965 -0.1951904296875 +11966 -0.100006103515625 +11967 -0.01055908203125 +11968 0.1033935546875 +11969 0.24908447265625 +11970 0.373199462890625 +11971 0.45806884765625 +11972 0.511474609375 +11973 0.565399169921875 +11974 0.61138916015625 +11975 0.5897216796875 +11976 0.4906005859375 +11977 0.33148193359375 +11978 0.147796630859375 +11979 -0.01873779296875 +11980 -0.140289306640625 +11981 -0.191986083984375 +11982 -0.184295654296875 +11983 -0.161834716796875 +11984 -0.166595458984375 +11985 -0.19390869140625 +11986 -0.22442626953125 +11987 -0.279754638671875 +11988 -0.3389892578125 +11989 -0.3543701171875 +11990 -0.348175048828125 +11991 -0.32598876953125 +11992 -0.2581787109375 +11993 -0.139801025390625 +11994 0.014617919921875 +11995 0.144378662109375 +11996 0.221038818359375 +11997 0.27069091796875 +11998 0.294036865234375 +11999 0.311767578125 +12000 0.339141845703125 +12001 0.360260009765625 +12002 0.360504150390625 +12003 0.308380126953125 +12004 0.18170166015625 +12005 0.0047607421875 +12006 -0.17559814453125 +12007 -0.3143310546875 +12008 -0.36785888671875 +12009 -0.36248779296875 +12010 -0.343536376953125 +12011 -0.3018798828125 +12012 -0.231414794921875 +12013 -0.117645263671875 +12014 0.007049560546875 +12015 0.087982177734375 +12016 0.13946533203125 +12017 0.17425537109375 +12018 0.188201904296875 +12019 0.171234130859375 +12020 0.118438720703125 +12021 0.05706787109375 +12022 -0.010711669921875 +12023 -0.0914306640625 +12024 -0.162322998046875 +12025 -0.194549560546875 +12026 -0.1492919921875 +12027 -0.02166748046875 +12028 0.124053955078125 +12029 0.211151123046875 +12030 0.240447998046875 +12031 0.242218017578125 +12032 0.2257080078125 +12033 0.194366455078125 +12034 0.115509033203125 +12035 0.0128173828125 +12036 -0.053802490234375 +12037 -0.110626220703125 +12038 -0.199493408203125 +12039 -0.29437255859375 +12040 -0.33221435546875 +12041 -0.27972412109375 +12042 -0.185333251953125 +12043 -0.128204345703125 +12044 -0.115692138671875 +12045 -0.116455078125 +12046 -0.105926513671875 +12047 -0.053955078125 +12048 0.048797607421875 +12049 0.157318115234375 +12050 0.212005615234375 +12051 0.218475341796875 +12052 0.23724365234375 +12053 0.30535888671875 +12054 0.38128662109375 +12055 0.404449462890625 +12056 0.3944091796875 +12057 0.3885498046875 +12058 0.362640380859375 +12059 0.27362060546875 +12060 0.11712646484375 +12061 -0.054901123046875 +12062 -0.19085693359375 +12063 -0.28570556640625 +12064 -0.339263916015625 +12065 -0.3775634765625 +12066 -0.445709228515625 +12067 -0.535064697265625 +12068 -0.629058837890625 +12069 -0.697601318359375 +12070 -0.70391845703125 +12071 -0.6424560546875 +12072 -0.491241455078125 +12073 -0.265716552734375 +12074 -0.023712158203125 +12075 0.201751708984375 +12076 0.375823974609375 +12077 0.485076904296875 +12078 0.56884765625 +12079 0.634765625 +12080 0.63763427734375 +12081 0.5660400390625 +12082 0.4720458984375 +12083 0.40692138671875 +12084 0.3778076171875 +12085 0.376953125 +12086 0.371978759765625 +12087 0.313140869140625 +12088 0.184417724609375 +12089 0.011199951171875 +12090 -0.171051025390625 +12091 -0.33740234375 +12092 -0.47198486328125 +12093 -0.560394287109375 +12094 -0.58056640625 +12095 -0.54754638671875 +12096 -0.508575439453125 +12097 -0.459503173828125 +12098 -0.394378662109375 +12099 -0.35260009765625 +12100 -0.31170654296875 +12101 -0.197418212890625 +12102 -0.007965087890625 +12103 0.207489013671875 +12104 0.409210205078125 +12105 0.57208251953125 +12106 0.66595458984375 +12107 0.65875244140625 +12108 0.56744384765625 +12109 0.431396484375 +12110 0.29443359375 +12111 0.182464599609375 +12112 0.06365966796875 +12113 -0.075958251953125 +12114 -0.189422607421875 +12115 -0.271942138671875 +12116 -0.342529296875 +12117 -0.364166259765625 +12118 -0.327239990234375 +12119 -0.2769775390625 +12120 -0.253692626953125 +12121 -0.24365234375 +12122 -0.1983642578125 +12123 -0.116241455078125 +12124 -0.036834716796875 +12125 0.034881591796875 +12126 0.09124755859375 +12127 0.10888671875 +12128 0.125518798828125 +12129 0.15771484375 +12130 0.17828369140625 +12131 0.17108154296875 +12132 0.129974365234375 +12133 0.082427978515625 +12134 0.027679443359375 +12135 -0.065643310546875 +12136 -0.15936279296875 +12137 -0.21307373046875 +12138 -0.234649658203125 +12139 -0.2001953125 +12140 -0.119171142578125 +12141 -0.024749755859375 +12142 0.085784912109375 +12143 0.178131103515625 +12144 0.215576171875 +12145 0.211456298828125 +12146 0.17523193359375 +12147 0.128753662109375 +12148 0.1019287109375 +12149 0.0743408203125 +12150 0.04327392578125 +12151 0.038177490234375 +12152 0.076263427734375 +12153 0.14105224609375 +12154 0.186431884765625 +12155 0.188812255859375 +12156 0.1390380859375 +12157 0.041778564453125 +12158 -0.079437255859375 +12159 -0.219390869140625 +12160 -0.367828369140625 +12161 -0.494873046875 +12162 -0.556243896484375 +12163 -0.508697509765625 +12164 -0.3756103515625 +12165 -0.218902587890625 +12166 -0.063751220703125 +12167 0.091552734375 +12168 0.23602294921875 +12169 0.342987060546875 +12170 0.39520263671875 +12171 0.389373779296875 +12172 0.324249267578125 +12173 0.224090576171875 +12174 0.124267578125 +12175 0.037078857421875 +12176 -0.010101318359375 +12177 -0.019439697265625 +12178 -0.022796630859375 +12179 -0.001556396484375 +12180 0.056304931640625 +12181 0.106719970703125 +12182 0.096893310546875 +12183 0.042694091796875 +12184 -0.018035888671875 +12185 -0.07586669921875 +12186 -0.11944580078125 +12187 -0.15972900390625 +12188 -0.202606201171875 +12189 -0.24859619140625 +12190 -0.30517578125 +12191 -0.36212158203125 +12192 -0.39141845703125 +12193 -0.35528564453125 +12194 -0.249969482421875 +12195 -0.092864990234375 +12196 0.08905029296875 +12197 0.2352294921875 +12198 0.318817138671875 +12199 0.358642578125 +12200 0.347747802734375 +12201 0.28564453125 +12202 0.223175048828125 +12203 0.196746826171875 +12204 0.179840087890625 +12205 0.155548095703125 +12206 0.151214599609375 +12207 0.156951904296875 +12208 0.13177490234375 +12209 0.100799560546875 +12210 0.087127685546875 +12211 0.05487060546875 +12212 -0.009002685546875 +12213 -0.10400390625 +12214 -0.229400634765625 +12215 -0.35552978515625 +12216 -0.441925048828125 +12217 -0.473846435546875 +12218 -0.464813232421875 +12219 -0.419097900390625 +12220 -0.334320068359375 +12221 -0.227935791015625 +12222 -0.12347412109375 +12223 -0.02764892578125 +12224 0.077667236328125 +12225 0.2132568359375 +12226 0.38885498046875 +12227 0.582794189453125 +12228 0.734039306640625 +12229 0.800140380859375 +12230 0.7783203125 +12231 0.6651611328125 +12232 0.45965576171875 +12233 0.199188232421875 +12234 -0.050689697265625 +12235 -0.23297119140625 +12236 -0.33013916015625 +12237 -0.368408203125 +12238 -0.378936767578125 +12239 -0.376983642578125 +12240 -0.37969970703125 +12241 -0.391510009765625 +12242 -0.385345458984375 +12243 -0.3419189453125 +12244 -0.28289794921875 +12245 -0.251617431640625 +12246 -0.266143798828125 +12247 -0.273345947265625 +12248 -0.216796875 +12249 -0.128265380859375 +12250 -0.068145751953125 +12251 -0.0430908203125 +12252 -0.024444580078125 +12253 0.020721435546875 +12254 0.124481201171875 +12255 0.25787353515625 +12256 0.379119873046875 +12257 0.47991943359375 +12258 0.5281982421875 +12259 0.511138916015625 +12260 0.456207275390625 +12261 0.407470703125 +12262 0.383758544921875 +12263 0.35687255859375 +12264 0.31182861328125 +12265 0.250885009765625 +12266 0.1654052734375 +12267 0.035247802734375 +12268 -0.142059326171875 +12269 -0.33563232421875 +12270 -0.5345458984375 +12271 -0.72186279296875 +12272 -0.836669921875 +12273 -0.8326416015625 +12274 -0.7296142578125 +12275 -0.582550048828125 +12276 -0.440093994140625 +12277 -0.324310302734375 +12278 -0.20147705078125 +12279 -0.044647216796875 +12280 0.103973388671875 +12281 0.202392578125 +12282 0.264495849609375 +12283 0.338897705078125 +12284 0.443817138671875 +12285 0.545074462890625 +12286 0.6173095703125 +12287 0.6524658203125 +12288 0.66339111328125 +12289 0.6561279296875 +12290 0.606781005859375 +12291 0.501190185546875 +12292 0.352783203125 +12293 0.176544189453125 +12294 -0.034820556640625 +12295 -0.258209228515625 +12296 -0.44244384765625 +12297 -0.5753173828125 +12298 -0.65203857421875 +12299 -0.641632080078125 +12300 -0.562164306640625 +12301 -0.458038330078125 +12302 -0.350555419921875 +12303 -0.260528564453125 +12304 -0.192108154296875 +12305 -0.141937255859375 +12306 -0.1021728515625 +12307 -0.062896728515625 +12308 -0.011932373046875 +12309 0.062835693359375 +12310 0.148712158203125 +12311 0.241729736328125 +12312 0.34912109375 +12313 0.457305908203125 +12314 0.54388427734375 +12315 0.5728759765625 +12316 0.506591796875 +12317 0.351226806640625 +12318 0.146514892578125 +12319 -0.05523681640625 +12320 -0.21624755859375 +12321 -0.334930419921875 +12322 -0.402984619140625 +12323 -0.4412841796875 +12324 -0.49578857421875 +12325 -0.5601806640625 +12326 -0.600738525390625 +12327 -0.584228515625 +12328 -0.47930908203125 +12329 -0.27935791015625 +12330 -0.0089111328125 +12331 0.268798828125 +12332 0.482818603515625 +12333 0.60369873046875 +12334 0.650421142578125 +12335 0.66400146484375 +12336 0.6414794921875 +12337 0.572540283203125 +12338 0.498138427734375 +12339 0.439453125 +12340 0.375518798828125 +12341 0.274505615234375 +12342 0.1087646484375 +12343 -0.099395751953125 +12344 -0.3182373046875 +12345 -0.5489501953125 +12346 -0.7738037109375 +12347 -0.86383056640625 +12348 -0.870391845703125 +12349 -0.86895751953125 +12350 -0.861053466796875 +12351 -0.765869140625 +12352 -0.5301513671875 +12353 -0.214691162109375 +12354 0.137359619140625 +12355 0.474822998046875 +12356 0.76239013671875 +12357 0.867462158203125 +12358 0.870361328125 +12359 0.86480712890625 +12360 0.831817626953125 +12361 0.677581787109375 +12362 0.495880126953125 +12363 0.30767822265625 +12364 0.116180419921875 +12365 -0.110748291015625 +12366 -0.381805419921875 +12367 -0.6572265625 +12368 -0.857421875 +12369 -0.870391845703125 +12370 -0.870391845703125 +12371 -0.86444091796875 +12372 -0.85723876953125 +12373 -0.790008544921875 +12374 -0.62847900390625 +12375 -0.3956298828125 +12376 -0.126708984375 +12377 0.150115966796875 +12378 0.424041748046875 +12379 0.670623779296875 +12380 0.854522705078125 +12381 0.866485595703125 +12382 0.86920166015625 +12383 0.8653564453125 +12384 0.857147216796875 +12385 0.766845703125 +12386 0.628509521484375 +12387 0.462127685546875 +12388 0.297210693359375 +12389 0.14862060546875 +12390 -0.00537109375 +12391 -0.15753173828125 +12392 -0.31304931640625 +12393 -0.48876953125 +12394 -0.6416015625 +12395 -0.751373291015625 +12396 -0.84619140625 +12397 -0.861297607421875 +12398 -0.863250732421875 +12399 -0.856597900390625 +12400 -0.7498779296875 +12401 -0.624542236328125 +12402 -0.47808837890625 +12403 -0.253387451171875 +12404 0.003692626953125 +12405 0.2257080078125 +12406 0.427154541015625 +12407 0.643218994140625 +12408 0.855926513671875 +12409 0.870361328125 +12410 0.870361328125 +12411 0.862762451171875 +12412 0.79669189453125 +12413 0.595794677734375 +12414 0.362152099609375 +12415 0.1270751953125 +12416 -0.086944580078125 +12417 -0.2784423828125 +12418 -0.484832763671875 +12419 -0.729583740234375 +12420 -0.86688232421875 +12421 -0.870391845703125 +12422 -0.86859130859375 +12423 -0.86279296875 +12424 -0.817962646484375 +12425 -0.6116943359375 +12426 -0.3128662109375 +12427 0.039398193359375 +12428 0.422821044921875 +12429 0.805145263671875 +12430 0.870361328125 +12431 0.870361328125 +12432 0.860015869140625 +12433 0.727935791015625 +12434 0.48114013671875 +12435 0.2059326171875 +12436 -0.06103515625 +12437 -0.29913330078125 +12438 -0.516204833984375 +12439 -0.7252197265625 +12440 -0.85980224609375 +12441 -0.870391845703125 +12442 -0.870391845703125 +12443 -0.858062744140625 +12444 -0.673004150390625 +12445 -0.42694091796875 +12446 -0.2100830078125 +12447 -0.0362548828125 +12448 0.10943603515625 +12449 0.23516845703125 +12450 0.373687744140625 +12451 0.517791748046875 +12452 0.602783203125 +12453 0.635711669921875 +12454 0.655181884765625 +12455 0.65948486328125 +12456 0.651275634765625 +12457 0.61846923828125 +12458 0.53753662109375 +12459 0.404144287109375 +12460 0.22186279296875 +12461 0.003997802734375 +12462 -0.22100830078125 +12463 -0.42449951171875 +12464 -0.579833984375 +12465 -0.641876220703125 +12466 -0.6177978515625 +12467 -0.575531005859375 +12468 -0.526336669921875 +12469 -0.42645263671875 +12470 -0.2581787109375 +12471 -0.068695068359375 +12472 0.09222412109375 +12473 0.232147216796875 +12474 0.3509521484375 +12475 0.410064697265625 +12476 0.372955322265625 +12477 0.2554931640625 +12478 0.10711669921875 +12479 -0.052886962890625 +12480 -0.186279296875 +12481 -0.23291015625 +12482 -0.209442138671875 +12483 -0.174163818359375 +12484 -0.126739501953125 +12485 -0.048126220703125 +12486 0.0426025390625 +12487 0.10748291015625 +12488 0.1409912109375 +12489 0.19708251953125 +12490 0.273651123046875 +12491 0.31768798828125 +12492 0.341094970703125 +12493 0.368011474609375 +12494 0.37249755859375 +12495 0.30072021484375 +12496 0.1517333984375 +12497 -0.01470947265625 +12498 -0.1883544921875 +12499 -0.372711181640625 +12500 -0.51397705078125 +12501 -0.57177734375 +12502 -0.53948974609375 +12503 -0.43511962890625 +12504 -0.2962646484375 +12505 -0.161102294921875 +12506 -0.0435791015625 +12507 0.060394287109375 +12508 0.13665771484375 +12509 0.170135498046875 +12510 0.16552734375 +12511 0.15728759765625 +12512 0.150787353515625 +12513 0.12200927734375 +12514 0.080108642578125 +12515 0.05126953125 +12516 0.062896728515625 +12517 0.09271240234375 +12518 0.092987060546875 +12519 0.07855224609375 +12520 0.06427001953125 +12521 0.0347900390625 +12522 -0.01171875 +12523 -0.056060791015625 +12524 -0.055511474609375 +12525 -0.010467529296875 +12526 0.02508544921875 +12527 0.025665283203125 +12528 0.017333984375 +12529 0.00189208984375 +12530 -0.03173828125 +12531 -0.071502685546875 +12532 -0.13543701171875 +12533 -0.219970703125 +12534 -0.300506591796875 +12535 -0.376312255859375 +12536 -0.416107177734375 +12537 -0.371124267578125 +12538 -0.242279052734375 +12539 -0.069732666015625 +12540 0.125640869140625 +12541 0.31268310546875 +12542 0.45501708984375 +12543 0.554779052734375 +12544 0.61065673828125 +12545 0.610931396484375 +12546 0.531463623046875 +12547 0.3883056640625 +12548 0.23468017578125 +12549 0.095245361328125 +12550 -0.00396728515625 +12551 -0.04852294921875 +12552 -0.055145263671875 +12553 -0.0758056640625 +12554 -0.138702392578125 +12555 -0.209197998046875 +12556 -0.289031982421875 +12557 -0.37884521484375 +12558 -0.456329345703125 +12559 -0.51641845703125 +12560 -0.519287109375 +12561 -0.458251953125 +12562 -0.384796142578125 +12563 -0.323699951171875 +12564 -0.269287109375 +12565 -0.1951904296875 +12566 -0.100006103515625 +12567 -0.01055908203125 +12568 0.1033935546875 +12569 0.24908447265625 +12570 0.373199462890625 +12571 0.45806884765625 +12572 0.511474609375 +12573 0.565399169921875 +12574 0.61138916015625 +12575 0.5897216796875 +12576 0.4906005859375 +12577 0.33148193359375 +12578 0.147796630859375 +12579 -0.01873779296875 +12580 -0.140289306640625 +12581 -0.191986083984375 +12582 -0.184295654296875 +12583 -0.161834716796875 +12584 -0.166595458984375 +12585 -0.19390869140625 +12586 -0.22442626953125 +12587 -0.279754638671875 +12588 -0.3389892578125 +12589 -0.3543701171875 +12590 -0.348175048828125 +12591 -0.32598876953125 +12592 -0.2581787109375 +12593 -0.139801025390625 +12594 0.014617919921875 +12595 0.144378662109375 +12596 0.221038818359375 +12597 0.27069091796875 +12598 0.294036865234375 +12599 0.311767578125 +12600 0.339141845703125 +12601 0.360260009765625 +12602 0.360504150390625 +12603 0.308380126953125 +12604 0.18170166015625 +12605 0.0047607421875 +12606 -0.17559814453125 +12607 -0.3143310546875 +12608 -0.36785888671875 +12609 -0.36248779296875 +12610 -0.343536376953125 +12611 -0.3018798828125 +12612 -0.231414794921875 +12613 -0.117645263671875 +12614 0.007049560546875 +12615 0.087982177734375 +12616 0.13946533203125 +12617 0.17425537109375 +12618 0.188201904296875 +12619 0.171234130859375 +12620 0.118438720703125 +12621 0.05706787109375 +12622 -0.010711669921875 +12623 -0.0914306640625 +12624 -0.162322998046875 +12625 -0.194549560546875 +12626 -0.1492919921875 +12627 -0.02166748046875 +12628 0.124053955078125 +12629 0.211151123046875 +12630 0.240447998046875 +12631 0.242218017578125 +12632 0.2257080078125 +12633 0.194366455078125 +12634 0.115509033203125 +12635 0.0128173828125 +12636 -0.053802490234375 +12637 -0.110626220703125 +12638 -0.199493408203125 +12639 -0.29437255859375 +12640 -0.33221435546875 +12641 -0.27972412109375 +12642 -0.185333251953125 +12643 -0.128204345703125 +12644 -0.115692138671875 +12645 -0.116455078125 +12646 -0.105926513671875 +12647 -0.053955078125 +12648 0.048797607421875 +12649 0.157318115234375 +12650 0.212005615234375 +12651 0.218475341796875 +12652 0.23724365234375 +12653 0.30535888671875 +12654 0.38128662109375 +12655 0.404449462890625 +12656 0.3944091796875 +12657 0.3885498046875 +12658 0.362640380859375 +12659 0.27362060546875 +12660 0.11712646484375 +12661 -0.054901123046875 +12662 -0.19085693359375 +12663 -0.28570556640625 +12664 -0.339263916015625 +12665 -0.3775634765625 +12666 -0.445709228515625 +12667 -0.535064697265625 +12668 -0.629058837890625 +12669 -0.697601318359375 +12670 -0.70391845703125 +12671 -0.6424560546875 +12672 -0.491241455078125 +12673 -0.265716552734375 +12674 -0.023712158203125 +12675 0.201751708984375 +12676 0.375823974609375 +12677 0.485076904296875 +12678 0.56884765625 +12679 0.634765625 +12680 0.63763427734375 +12681 0.5660400390625 +12682 0.4720458984375 +12683 0.40692138671875 +12684 0.3778076171875 +12685 0.376953125 +12686 0.371978759765625 +12687 0.313140869140625 +12688 0.184417724609375 +12689 0.011199951171875 +12690 -0.171051025390625 +12691 -0.33740234375 +12692 -0.47198486328125 +12693 -0.560394287109375 +12694 -0.58056640625 +12695 -0.54754638671875 +12696 -0.508575439453125 +12697 -0.459503173828125 +12698 -0.394378662109375 +12699 -0.35260009765625 +12700 -0.31170654296875 +12701 -0.197418212890625 +12702 -0.007965087890625 +12703 0.207489013671875 +12704 0.409210205078125 +12705 0.57208251953125 +12706 0.66595458984375 +12707 0.65875244140625 +12708 0.56744384765625 +12709 0.431396484375 +12710 0.29443359375 +12711 0.182464599609375 +12712 0.06365966796875 +12713 -0.075958251953125 +12714 -0.189422607421875 +12715 -0.271942138671875 +12716 -0.342529296875 +12717 -0.364166259765625 +12718 -0.327239990234375 +12719 -0.2769775390625 +12720 -0.253692626953125 +12721 -0.24365234375 +12722 -0.1983642578125 +12723 -0.116241455078125 +12724 -0.036834716796875 +12725 0.034881591796875 +12726 0.09124755859375 +12727 0.10888671875 +12728 0.125518798828125 +12729 0.15771484375 +12730 0.17828369140625 +12731 0.17108154296875 +12732 0.129974365234375 +12733 0.082427978515625 +12734 0.027679443359375 +12735 -0.065643310546875 +12736 -0.15936279296875 +12737 -0.21307373046875 +12738 -0.234649658203125 +12739 -0.2001953125 +12740 -0.119171142578125 +12741 -0.024749755859375 +12742 0.085784912109375 +12743 0.178131103515625 +12744 0.215576171875 +12745 0.211456298828125 +12746 0.17523193359375 +12747 0.128753662109375 +12748 0.1019287109375 +12749 0.0743408203125 +12750 0.04327392578125 +12751 0.038177490234375 +12752 0.076263427734375 +12753 0.14105224609375 +12754 0.186431884765625 +12755 0.188812255859375 +12756 0.1390380859375 +12757 0.041778564453125 +12758 -0.079437255859375 +12759 -0.219390869140625 +12760 -0.367828369140625 +12761 -0.494873046875 +12762 -0.556243896484375 +12763 -0.508697509765625 +12764 -0.3756103515625 +12765 -0.218902587890625 +12766 -0.063751220703125 +12767 0.091552734375 +12768 0.23602294921875 +12769 0.342987060546875 +12770 0.39520263671875 +12771 0.389373779296875 +12772 0.324249267578125 +12773 0.224090576171875 +12774 0.124267578125 +12775 0.037078857421875 +12776 -0.010101318359375 +12777 -0.019439697265625 +12778 -0.022796630859375 +12779 -0.001556396484375 +12780 0.056304931640625 +12781 0.106719970703125 +12782 0.096893310546875 +12783 0.042694091796875 +12784 -0.018035888671875 +12785 -0.07586669921875 +12786 -0.11944580078125 +12787 -0.15972900390625 +12788 -0.202606201171875 +12789 -0.24859619140625 +12790 -0.30517578125 +12791 -0.36212158203125 +12792 -0.39141845703125 +12793 -0.35528564453125 +12794 -0.249969482421875 +12795 -0.092864990234375 +12796 0.08905029296875 +12797 0.2352294921875 +12798 0.318817138671875 +12799 0.358642578125 +12800 0.347747802734375 +12801 0.28564453125 +12802 0.223175048828125 +12803 0.196746826171875 +12804 0.179840087890625 +12805 0.155548095703125 +12806 0.151214599609375 +12807 0.156951904296875 +12808 0.13177490234375 +12809 0.100799560546875 +12810 0.087127685546875 +12811 0.05487060546875 +12812 -0.009002685546875 +12813 -0.10400390625 +12814 -0.229400634765625 +12815 -0.35552978515625 +12816 -0.441925048828125 +12817 -0.473846435546875 +12818 -0.464813232421875 +12819 -0.419097900390625 +12820 -0.334320068359375 +12821 -0.227935791015625 +12822 -0.12347412109375 +12823 -0.02764892578125 +12824 0.077667236328125 +12825 0.2132568359375 +12826 0.38885498046875 +12827 0.582794189453125 +12828 0.734039306640625 +12829 0.800140380859375 +12830 0.7783203125 +12831 0.6651611328125 +12832 0.45965576171875 +12833 0.199188232421875 +12834 -0.050689697265625 +12835 -0.23297119140625 +12836 -0.33013916015625 +12837 -0.368408203125 +12838 -0.378936767578125 +12839 -0.376983642578125 +12840 -0.37969970703125 +12841 -0.391510009765625 +12842 -0.385345458984375 +12843 -0.3419189453125 +12844 -0.28289794921875 +12845 -0.251617431640625 +12846 -0.266143798828125 +12847 -0.273345947265625 +12848 -0.216796875 +12849 -0.128265380859375 +12850 -0.068145751953125 +12851 -0.0430908203125 +12852 -0.024444580078125 +12853 0.020721435546875 +12854 0.124481201171875 +12855 0.25787353515625 +12856 0.379119873046875 +12857 0.47991943359375 +12858 0.5281982421875 +12859 0.511138916015625 +12860 0.456207275390625 +12861 0.407470703125 +12862 0.383758544921875 +12863 0.35687255859375 +12864 0.31182861328125 +12865 0.250885009765625 +12866 0.1654052734375 +12867 0.035247802734375 +12868 -0.142059326171875 +12869 -0.33563232421875 +12870 -0.5345458984375 +12871 -0.72186279296875 +12872 -0.836669921875 +12873 -0.8326416015625 +12874 -0.7296142578125 +12875 -0.582550048828125 +12876 -0.440093994140625 +12877 -0.324310302734375 +12878 -0.20147705078125 +12879 -0.044647216796875 +12880 0.103973388671875 +12881 0.202392578125 +12882 0.264495849609375 +12883 0.338897705078125 +12884 0.443817138671875 +12885 0.545074462890625 +12886 0.6173095703125 +12887 0.6524658203125 +12888 0.66339111328125 +12889 0.6561279296875 +12890 0.606781005859375 +12891 0.501190185546875 +12892 0.352783203125 +12893 0.176544189453125 +12894 -0.034820556640625 +12895 -0.258209228515625 +12896 -0.44244384765625 +12897 -0.5753173828125 +12898 -0.65203857421875 +12899 -0.641632080078125 +12900 -0.562164306640625 +12901 -0.458038330078125 +12902 -0.350555419921875 +12903 -0.260528564453125 +12904 -0.192108154296875 +12905 -0.141937255859375 +12906 -0.1021728515625 +12907 -0.062896728515625 +12908 -0.011932373046875 +12909 0.062835693359375 +12910 0.148712158203125 +12911 0.241729736328125 +12912 0.34912109375 +12913 0.457305908203125 +12914 0.54388427734375 +12915 0.5728759765625 +12916 0.506591796875 +12917 0.351226806640625 +12918 0.146514892578125 +12919 -0.05523681640625 +12920 -0.21624755859375 +12921 -0.334930419921875 +12922 -0.402984619140625 +12923 -0.4412841796875 +12924 -0.49578857421875 +12925 -0.5601806640625 +12926 -0.600738525390625 +12927 -0.584228515625 +12928 -0.47930908203125 +12929 -0.27935791015625 +12930 -0.0089111328125 +12931 0.268798828125 +12932 0.482818603515625 +12933 0.60369873046875 +12934 0.650421142578125 +12935 0.66400146484375 +12936 0.6414794921875 +12937 0.572540283203125 +12938 0.498138427734375 +12939 0.439453125 +12940 0.375518798828125 +12941 0.274505615234375 +12942 0.1087646484375 +12943 -0.099395751953125 +12944 -0.3182373046875 +12945 -0.5489501953125 +12946 -0.7738037109375 +12947 -0.86383056640625 +12948 -0.870391845703125 +12949 -0.86895751953125 +12950 -0.861053466796875 +12951 -0.765869140625 +12952 -0.5301513671875 +12953 -0.214691162109375 +12954 0.137359619140625 +12955 0.474822998046875 +12956 0.76239013671875 +12957 0.867462158203125 +12958 0.870361328125 +12959 0.86480712890625 +12960 0.831817626953125 +12961 0.677581787109375 +12962 0.495880126953125 +12963 0.30767822265625 +12964 0.116180419921875 +12965 -0.110748291015625 +12966 -0.381805419921875 +12967 -0.6572265625 +12968 -0.857421875 +12969 -0.870391845703125 +12970 -0.870391845703125 +12971 -0.86444091796875 +12972 -0.85723876953125 +12973 -0.790008544921875 +12974 -0.62847900390625 +12975 -0.3956298828125 +12976 -0.126708984375 +12977 0.150115966796875 +12978 0.424041748046875 +12979 0.670623779296875 +12980 0.854522705078125 +12981 0.866485595703125 +12982 0.86920166015625 +12983 0.8653564453125 +12984 0.857147216796875 +12985 0.766845703125 +12986 0.628509521484375 +12987 0.462127685546875 +12988 0.297210693359375 +12989 0.14862060546875 +12990 -0.00537109375 +12991 -0.15753173828125 +12992 -0.31304931640625 +12993 -0.48876953125 +12994 -0.6416015625 +12995 -0.751373291015625 +12996 -0.84619140625 +12997 -0.861297607421875 +12998 -0.863250732421875 +12999 -0.856597900390625 +13000 -0.7498779296875 +13001 -0.624542236328125 +13002 -0.47808837890625 +13003 -0.253387451171875 +13004 0.003692626953125 +13005 0.2257080078125 +13006 0.427154541015625 +13007 0.643218994140625 +13008 0.855926513671875 +13009 0.870361328125 +13010 0.870361328125 +13011 0.862762451171875 +13012 0.79669189453125 +13013 0.595794677734375 +13014 0.362152099609375 +13015 0.1270751953125 +13016 -0.086944580078125 +13017 -0.2784423828125 +13018 -0.484832763671875 +13019 -0.729583740234375 +13020 -0.86688232421875 +13021 -0.870391845703125 +13022 -0.86859130859375 +13023 -0.86279296875 +13024 -0.817962646484375 +13025 -0.6116943359375 +13026 -0.3128662109375 +13027 0.039398193359375 +13028 0.422821044921875 +13029 0.805145263671875 +13030 0.870361328125 +13031 0.870361328125 +13032 0.860015869140625 +13033 0.727935791015625 +13034 0.48114013671875 +13035 0.2059326171875 +13036 -0.06103515625 +13037 -0.29913330078125 +13038 -0.516204833984375 +13039 -0.7252197265625 +13040 -0.85980224609375 +13041 -0.870391845703125 +13042 -0.870391845703125 +13043 -0.858062744140625 +13044 -0.673004150390625 +13045 -0.42694091796875 +13046 -0.2100830078125 +13047 -0.0362548828125 +13048 0.10943603515625 +13049 0.23516845703125 +13050 0.373687744140625 +13051 0.517791748046875 +13052 0.602783203125 +13053 0.635711669921875 +13054 0.655181884765625 +13055 0.65948486328125 +13056 0.651275634765625 +13057 0.61846923828125 +13058 0.53753662109375 +13059 0.404144287109375 +13060 0.22186279296875 +13061 0.003997802734375 +13062 -0.22100830078125 +13063 -0.42449951171875 +13064 -0.579833984375 +13065 -0.641876220703125 +13066 -0.6177978515625 +13067 -0.575531005859375 +13068 -0.526336669921875 +13069 -0.42645263671875 +13070 -0.2581787109375 +13071 -0.068695068359375 +13072 0.09222412109375 +13073 0.232147216796875 +13074 0.3509521484375 +13075 0.410064697265625 +13076 0.372955322265625 +13077 0.2554931640625 +13078 0.10711669921875 +13079 -0.052886962890625 +13080 -0.186279296875 +13081 -0.23291015625 +13082 -0.209442138671875 +13083 -0.174163818359375 +13084 -0.126739501953125 +13085 -0.048126220703125 +13086 0.0426025390625 +13087 0.10748291015625 +13088 0.1409912109375 +13089 0.19708251953125 +13090 0.273651123046875 +13091 0.31768798828125 +13092 0.341094970703125 +13093 0.368011474609375 +13094 0.37249755859375 +13095 0.30072021484375 +13096 0.1517333984375 +13097 -0.01470947265625 +13098 -0.1883544921875 +13099 -0.372711181640625 +13100 -0.51397705078125 +13101 -0.57177734375 +13102 -0.53948974609375 +13103 -0.43511962890625 +13104 -0.2962646484375 +13105 -0.161102294921875 +13106 -0.0435791015625 +13107 0.060394287109375 +13108 0.13665771484375 +13109 0.170135498046875 +13110 0.16552734375 +13111 0.15728759765625 +13112 0.150787353515625 +13113 0.12200927734375 +13114 0.080108642578125 +13115 0.05126953125 +13116 0.062896728515625 +13117 0.09271240234375 +13118 0.092987060546875 +13119 0.07855224609375 +13120 0.06427001953125 +13121 0.0347900390625 +13122 -0.01171875 +13123 -0.056060791015625 +13124 -0.055511474609375 +13125 -0.010467529296875 +13126 0.02508544921875 +13127 0.025665283203125 +13128 0.017333984375 +13129 0.00189208984375 +13130 -0.03173828125 +13131 -0.071502685546875 +13132 -0.13543701171875 +13133 -0.219970703125 +13134 -0.300506591796875 +13135 -0.376312255859375 +13136 -0.416107177734375 +13137 -0.371124267578125 +13138 -0.242279052734375 +13139 -0.069732666015625 +13140 0.125640869140625 +13141 0.31268310546875 +13142 0.45501708984375 +13143 0.554779052734375 +13144 0.61065673828125 +13145 0.610931396484375 +13146 0.531463623046875 +13147 0.3883056640625 +13148 0.23468017578125 +13149 0.095245361328125 +13150 -0.00396728515625 +13151 -0.04852294921875 +13152 -0.055145263671875 +13153 -0.0758056640625 +13154 -0.138702392578125 +13155 -0.209197998046875 +13156 -0.289031982421875 +13157 -0.37884521484375 +13158 -0.456329345703125 +13159 -0.51641845703125 +13160 -0.519287109375 +13161 -0.458251953125 +13162 -0.384796142578125 +13163 -0.323699951171875 +13164 -0.269287109375 +13165 -0.1951904296875 +13166 -0.100006103515625 +13167 -0.01055908203125 +13168 0.1033935546875 +13169 0.24908447265625 +13170 0.373199462890625 +13171 0.45806884765625 +13172 0.511474609375 +13173 0.565399169921875 +13174 0.61138916015625 +13175 0.5897216796875 +13176 0.4906005859375 +13177 0.33148193359375 +13178 0.147796630859375 +13179 -0.01873779296875 +13180 -0.140289306640625 +13181 -0.191986083984375 +13182 -0.184295654296875 +13183 -0.161834716796875 +13184 -0.166595458984375 +13185 -0.19390869140625 +13186 -0.22442626953125 +13187 -0.279754638671875 +13188 -0.3389892578125 +13189 -0.3543701171875 +13190 -0.348175048828125 +13191 -0.32598876953125 +13192 -0.2581787109375 +13193 -0.139801025390625 +13194 0.014617919921875 +13195 0.144378662109375 +13196 0.221038818359375 +13197 0.27069091796875 +13198 0.294036865234375 +13199 0.311767578125 +13200 0.339141845703125 +13201 0.360260009765625 +13202 0.360504150390625 +13203 0.308380126953125 +13204 0.18170166015625 +13205 0.0047607421875 +13206 -0.17559814453125 +13207 -0.3143310546875 +13208 -0.36785888671875 +13209 -0.36248779296875 +13210 -0.343536376953125 +13211 -0.3018798828125 +13212 -0.231414794921875 +13213 -0.117645263671875 +13214 0.007049560546875 +13215 0.087982177734375 +13216 0.13946533203125 +13217 0.17425537109375 +13218 0.188201904296875 +13219 0.171234130859375 +13220 0.118438720703125 +13221 0.05706787109375 +13222 -0.010711669921875 +13223 -0.0914306640625 +13224 -0.162322998046875 +13225 -0.194549560546875 +13226 -0.1492919921875 +13227 -0.02166748046875 +13228 0.124053955078125 +13229 0.211151123046875 +13230 0.240447998046875 +13231 0.242218017578125 +13232 0.2257080078125 +13233 0.194366455078125 +13234 0.115509033203125 +13235 0.0128173828125 +13236 -0.053802490234375 +13237 -0.110626220703125 +13238 -0.199493408203125 +13239 -0.29437255859375 +13240 -0.33221435546875 +13241 -0.27972412109375 +13242 -0.185333251953125 +13243 -0.128204345703125 +13244 -0.115692138671875 +13245 -0.116455078125 +13246 -0.105926513671875 +13247 -0.053955078125 +13248 0.048797607421875 +13249 0.157318115234375 +13250 0.212005615234375 +13251 0.218475341796875 +13252 0.23724365234375 +13253 0.30535888671875 +13254 0.38128662109375 +13255 0.404449462890625 +13256 0.3944091796875 +13257 0.3885498046875 +13258 0.362640380859375 +13259 0.27362060546875 +13260 0.11712646484375 +13261 -0.054901123046875 +13262 -0.19085693359375 +13263 -0.28570556640625 +13264 -0.339263916015625 +13265 -0.3775634765625 +13266 -0.445709228515625 +13267 -0.535064697265625 +13268 -0.629058837890625 +13269 -0.697601318359375 +13270 -0.70391845703125 +13271 -0.6424560546875 +13272 -0.491241455078125 +13273 -0.265716552734375 +13274 -0.023712158203125 +13275 0.201751708984375 +13276 0.375823974609375 +13277 0.485076904296875 +13278 0.56884765625 +13279 0.634765625 +13280 0.63763427734375 +13281 0.5660400390625 +13282 0.4720458984375 +13283 0.40692138671875 +13284 0.3778076171875 +13285 0.376953125 +13286 0.371978759765625 +13287 0.313140869140625 +13288 0.184417724609375 +13289 0.011199951171875 +13290 -0.171051025390625 +13291 -0.33740234375 +13292 -0.47198486328125 +13293 -0.560394287109375 +13294 -0.58056640625 +13295 -0.54754638671875 +13296 -0.508575439453125 +13297 -0.459503173828125 +13298 -0.394378662109375 +13299 -0.35260009765625 +13300 -0.31170654296875 +13301 -0.197418212890625 +13302 -0.007965087890625 +13303 0.207489013671875 +13304 0.409210205078125 +13305 0.57208251953125 +13306 0.66595458984375 +13307 0.65875244140625 +13308 0.56744384765625 +13309 0.431396484375 +13310 0.29443359375 +13311 0.182464599609375 +13312 0.06365966796875 +13313 -0.075958251953125 +13314 -0.189422607421875 +13315 -0.271942138671875 +13316 -0.342529296875 +13317 -0.364166259765625 +13318 -0.327239990234375 +13319 -0.2769775390625 +13320 -0.253692626953125 +13321 -0.24365234375 +13322 -0.1983642578125 +13323 -0.116241455078125 +13324 -0.036834716796875 +13325 0.034881591796875 +13326 0.09124755859375 +13327 0.10888671875 +13328 0.125518798828125 +13329 0.15771484375 +13330 0.17828369140625 +13331 0.17108154296875 +13332 0.129974365234375 +13333 0.082427978515625 +13334 0.027679443359375 +13335 -0.065643310546875 +13336 -0.15936279296875 +13337 -0.21307373046875 +13338 -0.234649658203125 +13339 -0.2001953125 +13340 -0.119171142578125 +13341 -0.024749755859375 +13342 0.085784912109375 +13343 0.178131103515625 +13344 0.215576171875 +13345 0.211456298828125 +13346 0.17523193359375 +13347 0.128753662109375 +13348 0.1019287109375 +13349 0.0743408203125 +13350 0.04327392578125 +13351 0.038177490234375 +13352 0.076263427734375 +13353 0.14105224609375 +13354 0.186431884765625 +13355 0.188812255859375 +13356 0.1390380859375 +13357 0.041778564453125 +13358 -0.079437255859375 +13359 -0.219390869140625 +13360 -0.367828369140625 +13361 -0.494873046875 +13362 -0.556243896484375 +13363 -0.508697509765625 +13364 -0.3756103515625 +13365 -0.218902587890625 +13366 -0.063751220703125 +13367 0.091552734375 +13368 0.23602294921875 +13369 0.342987060546875 +13370 0.39520263671875 +13371 0.389373779296875 +13372 0.324249267578125 +13373 0.224090576171875 +13374 0.124267578125 +13375 0.037078857421875 +13376 -0.010101318359375 +13377 -0.019439697265625 +13378 -0.022796630859375 +13379 -0.001556396484375 +13380 0.056304931640625 +13381 0.106719970703125 +13382 0.096893310546875 +13383 0.042694091796875 +13384 -0.018035888671875 +13385 -0.07586669921875 +13386 -0.11944580078125 +13387 -0.15972900390625 +13388 -0.202606201171875 +13389 -0.24859619140625 +13390 -0.30517578125 +13391 -0.36212158203125 +13392 -0.39141845703125 +13393 -0.35528564453125 +13394 -0.249969482421875 +13395 -0.092864990234375 +13396 0.08905029296875 +13397 0.2352294921875 +13398 0.318817138671875 +13399 0.358642578125 +13400 0.347747802734375 +13401 0.28564453125 +13402 0.223175048828125 +13403 0.196746826171875 +13404 0.179840087890625 +13405 0.155548095703125 +13406 0.151214599609375 +13407 0.156951904296875 +13408 0.13177490234375 +13409 0.100799560546875 +13410 0.087127685546875 +13411 0.05487060546875 +13412 -0.009002685546875 +13413 -0.10400390625 +13414 -0.229400634765625 +13415 -0.35552978515625 +13416 -0.441925048828125 +13417 -0.473846435546875 +13418 -0.464813232421875 +13419 -0.419097900390625 +13420 -0.334320068359375 +13421 -0.227935791015625 +13422 -0.12347412109375 +13423 -0.02764892578125 +13424 0.077667236328125 +13425 0.2132568359375 +13426 0.38885498046875 +13427 0.582794189453125 +13428 0.734039306640625 +13429 0.800140380859375 +13430 0.7783203125 +13431 0.6651611328125 +13432 0.45965576171875 +13433 0.199188232421875 +13434 -0.050689697265625 +13435 -0.23297119140625 +13436 -0.33013916015625 +13437 -0.368408203125 +13438 -0.378936767578125 +13439 -0.376983642578125 +13440 -0.37969970703125 +13441 -0.391510009765625 +13442 -0.385345458984375 +13443 -0.3419189453125 +13444 -0.28289794921875 +13445 -0.251617431640625 +13446 -0.266143798828125 +13447 -0.273345947265625 +13448 -0.216796875 +13449 -0.128265380859375 +13450 -0.068145751953125 +13451 -0.0430908203125 +13452 -0.024444580078125 +13453 0.020721435546875 +13454 0.124481201171875 +13455 0.25787353515625 +13456 0.379119873046875 +13457 0.47991943359375 +13458 0.5281982421875 +13459 0.511138916015625 +13460 0.456207275390625 +13461 0.407470703125 +13462 0.383758544921875 +13463 0.35687255859375 +13464 0.31182861328125 +13465 0.250885009765625 +13466 0.1654052734375 +13467 0.035247802734375 +13468 -0.142059326171875 +13469 -0.33563232421875 +13470 -0.5345458984375 +13471 -0.72186279296875 +13472 -0.836669921875 +13473 -0.8326416015625 +13474 -0.7296142578125 +13475 -0.582550048828125 +13476 -0.440093994140625 +13477 -0.324310302734375 +13478 -0.20147705078125 +13479 -0.044647216796875 +13480 0.103973388671875 +13481 0.202392578125 +13482 0.264495849609375 +13483 0.338897705078125 +13484 0.443817138671875 +13485 0.545074462890625 +13486 0.6173095703125 +13487 0.6524658203125 +13488 0.66339111328125 +13489 0.6561279296875 +13490 0.606781005859375 +13491 0.501190185546875 +13492 0.352783203125 +13493 0.176544189453125 +13494 -0.034820556640625 +13495 -0.258209228515625 +13496 -0.44244384765625 +13497 -0.5753173828125 +13498 -0.65203857421875 +13499 -0.641632080078125 +13500 -0.562164306640625 +13501 -0.458038330078125 +13502 -0.350555419921875 +13503 -0.260528564453125 +13504 -0.192108154296875 +13505 -0.141937255859375 +13506 -0.1021728515625 +13507 -0.062896728515625 +13508 -0.011932373046875 +13509 0.062835693359375 +13510 0.148712158203125 +13511 0.241729736328125 +13512 0.34912109375 +13513 0.457305908203125 +13514 0.54388427734375 +13515 0.5728759765625 +13516 0.506591796875 +13517 0.351226806640625 +13518 0.146514892578125 +13519 -0.05523681640625 +13520 -0.21624755859375 +13521 -0.334930419921875 +13522 -0.402984619140625 +13523 -0.4412841796875 +13524 -0.49578857421875 +13525 -0.5601806640625 +13526 -0.600738525390625 +13527 -0.584228515625 +13528 -0.47930908203125 +13529 -0.27935791015625 +13530 -0.0089111328125 +13531 0.268798828125 +13532 0.482818603515625 +13533 0.60369873046875 +13534 0.650421142578125 +13535 0.66400146484375 +13536 0.6414794921875 +13537 0.572540283203125 +13538 0.498138427734375 +13539 0.439453125 +13540 0.375518798828125 +13541 0.274505615234375 +13542 0.1087646484375 +13543 -0.099395751953125 +13544 -0.3182373046875 +13545 -0.5489501953125 +13546 -0.7738037109375 +13547 -0.86383056640625 +13548 -0.870391845703125 +13549 -0.86895751953125 +13550 -0.861053466796875 +13551 -0.765869140625 +13552 -0.5301513671875 +13553 -0.214691162109375 +13554 0.137359619140625 +13555 0.474822998046875 +13556 0.76239013671875 +13557 0.867462158203125 +13558 0.870361328125 +13559 0.86480712890625 +13560 0.831817626953125 +13561 0.677581787109375 +13562 0.495880126953125 +13563 0.30767822265625 +13564 0.116180419921875 +13565 -0.110748291015625 +13566 -0.381805419921875 +13567 -0.6572265625 +13568 -0.857421875 +13569 -0.870391845703125 +13570 -0.870391845703125 +13571 -0.86444091796875 +13572 -0.85723876953125 +13573 -0.790008544921875 +13574 -0.62847900390625 +13575 -0.3956298828125 +13576 -0.126708984375 +13577 0.150115966796875 +13578 0.424041748046875 +13579 0.670623779296875 +13580 0.854522705078125 +13581 0.866485595703125 +13582 0.86920166015625 +13583 0.8653564453125 +13584 0.857147216796875 +13585 0.766845703125 +13586 0.628509521484375 +13587 0.462127685546875 +13588 0.297210693359375 +13589 0.14862060546875 +13590 -0.00537109375 +13591 -0.15753173828125 +13592 -0.31304931640625 +13593 -0.48876953125 +13594 -0.6416015625 +13595 -0.751373291015625 +13596 -0.84619140625 +13597 -0.861297607421875 +13598 -0.863250732421875 +13599 -0.856597900390625 +13600 -0.7498779296875 +13601 -0.624542236328125 +13602 -0.47808837890625 +13603 -0.253387451171875 +13604 0.003692626953125 +13605 0.2257080078125 +13606 0.427154541015625 +13607 0.643218994140625 +13608 0.855926513671875 +13609 0.870361328125 +13610 0.870361328125 +13611 0.862762451171875 +13612 0.79669189453125 +13613 0.595794677734375 +13614 0.362152099609375 +13615 0.1270751953125 +13616 -0.086944580078125 +13617 -0.2784423828125 +13618 -0.484832763671875 +13619 -0.729583740234375 +13620 -0.86688232421875 +13621 -0.870391845703125 +13622 -0.86859130859375 +13623 -0.86279296875 +13624 -0.817962646484375 +13625 -0.6116943359375 +13626 -0.3128662109375 +13627 0.039398193359375 +13628 0.422821044921875 +13629 0.805145263671875 +13630 0.870361328125 +13631 0.870361328125 +13632 0.860015869140625 +13633 0.727935791015625 +13634 0.48114013671875 +13635 0.2059326171875 +13636 -0.06103515625 +13637 -0.29913330078125 +13638 -0.516204833984375 +13639 -0.7252197265625 +13640 -0.85980224609375 +13641 -0.870391845703125 +13642 -0.870391845703125 +13643 -0.858062744140625 +13644 -0.673004150390625 +13645 -0.42694091796875 +13646 -0.2100830078125 +13647 -0.0362548828125 +13648 0.10943603515625 +13649 0.23516845703125 +13650 0.373687744140625 +13651 0.517791748046875 +13652 0.602783203125 +13653 0.635711669921875 +13654 0.655181884765625 +13655 0.65948486328125 +13656 0.651275634765625 +13657 0.61846923828125 +13658 0.53753662109375 +13659 0.404144287109375 +13660 0.22186279296875 +13661 0.003997802734375 +13662 -0.22100830078125 +13663 -0.42449951171875 +13664 -0.579833984375 +13665 -0.641876220703125 +13666 -0.6177978515625 +13667 -0.575531005859375 +13668 -0.526336669921875 +13669 -0.42645263671875 +13670 -0.2581787109375 +13671 -0.068695068359375 +13672 0.09222412109375 +13673 0.232147216796875 +13674 0.3509521484375 +13675 0.410064697265625 +13676 0.372955322265625 +13677 0.2554931640625 +13678 0.10711669921875 +13679 -0.052886962890625 +13680 -0.186279296875 +13681 -0.23291015625 +13682 -0.209442138671875 +13683 -0.174163818359375 +13684 -0.126739501953125 +13685 -0.048126220703125 +13686 0.0426025390625 +13687 0.10748291015625 +13688 0.1409912109375 +13689 0.19708251953125 +13690 0.273651123046875 +13691 0.31768798828125 +13692 0.341094970703125 +13693 0.368011474609375 +13694 0.37249755859375 +13695 0.30072021484375 +13696 0.1517333984375 +13697 -0.01470947265625 +13698 -0.1883544921875 +13699 -0.372711181640625 +13700 -0.51397705078125 +13701 -0.57177734375 +13702 -0.53948974609375 +13703 -0.43511962890625 +13704 -0.2962646484375 +13705 -0.161102294921875 +13706 -0.0435791015625 +13707 0.060394287109375 +13708 0.13665771484375 +13709 0.170135498046875 +13710 0.16552734375 +13711 0.15728759765625 +13712 0.150787353515625 +13713 0.12200927734375 +13714 0.080108642578125 +13715 0.05126953125 +13716 0.062896728515625 +13717 0.09271240234375 +13718 0.092987060546875 +13719 0.07855224609375 +13720 0.06427001953125 +13721 0.0347900390625 +13722 -0.01171875 +13723 -0.056060791015625 +13724 -0.055511474609375 +13725 -0.010467529296875 +13726 0.02508544921875 +13727 0.025665283203125 +13728 0.017333984375 +13729 0.00189208984375 +13730 -0.03173828125 +13731 -0.071502685546875 +13732 -0.13543701171875 +13733 -0.219970703125 +13734 -0.300506591796875 +13735 -0.376312255859375 +13736 -0.416107177734375 +13737 -0.371124267578125 +13738 -0.242279052734375 +13739 -0.069732666015625 +13740 0.125640869140625 +13741 0.31268310546875 +13742 0.45501708984375 +13743 0.554779052734375 +13744 0.61065673828125 +13745 0.610931396484375 +13746 0.531463623046875 +13747 0.3883056640625 +13748 0.23468017578125 +13749 0.095245361328125 +13750 -0.00396728515625 +13751 -0.04852294921875 +13752 -0.055145263671875 +13753 -0.0758056640625 +13754 -0.138702392578125 +13755 -0.209197998046875 +13756 -0.289031982421875 +13757 -0.37884521484375 +13758 -0.456329345703125 +13759 -0.51641845703125 +13760 -0.519287109375 +13761 -0.458251953125 +13762 -0.384796142578125 +13763 -0.323699951171875 +13764 -0.269287109375 +13765 -0.1951904296875 +13766 -0.100006103515625 +13767 -0.01055908203125 +13768 0.1033935546875 +13769 0.24908447265625 +13770 0.373199462890625 +13771 0.45806884765625 +13772 0.511474609375 +13773 0.565399169921875 +13774 0.61138916015625 +13775 0.5897216796875 +13776 0.4906005859375 +13777 0.33148193359375 +13778 0.147796630859375 +13779 -0.01873779296875 +13780 -0.140289306640625 +13781 -0.191986083984375 +13782 -0.184295654296875 +13783 -0.161834716796875 +13784 -0.166595458984375 +13785 -0.19390869140625 +13786 -0.22442626953125 +13787 -0.279754638671875 +13788 -0.3389892578125 +13789 -0.3543701171875 +13790 -0.348175048828125 +13791 -0.32598876953125 +13792 -0.2581787109375 +13793 -0.139801025390625 +13794 0.014617919921875 +13795 0.144378662109375 +13796 0.221038818359375 +13797 0.27069091796875 +13798 0.294036865234375 +13799 0.311767578125 +13800 0.339141845703125 +13801 0.360260009765625 +13802 0.360504150390625 +13803 0.308380126953125 +13804 0.18170166015625 +13805 0.0047607421875 +13806 -0.17559814453125 +13807 -0.3143310546875 +13808 -0.36785888671875 +13809 -0.36248779296875 +13810 -0.343536376953125 +13811 -0.3018798828125 +13812 -0.231414794921875 +13813 -0.117645263671875 +13814 0.007049560546875 +13815 0.087982177734375 +13816 0.13946533203125 +13817 0.17425537109375 +13818 0.188201904296875 +13819 0.171234130859375 +13820 0.118438720703125 +13821 0.05706787109375 +13822 -0.010711669921875 +13823 -0.0914306640625 +13824 -0.162322998046875 +13825 -0.194549560546875 +13826 -0.1492919921875 +13827 -0.02166748046875 +13828 0.124053955078125 +13829 0.211151123046875 +13830 0.240447998046875 +13831 0.242218017578125 +13832 0.2257080078125 +13833 0.194366455078125 +13834 0.115509033203125 +13835 0.0128173828125 +13836 -0.053802490234375 +13837 -0.110626220703125 +13838 -0.199493408203125 +13839 -0.29437255859375 +13840 -0.33221435546875 +13841 -0.27972412109375 +13842 -0.185333251953125 +13843 -0.128204345703125 +13844 -0.115692138671875 +13845 -0.116455078125 +13846 -0.105926513671875 +13847 -0.053955078125 +13848 0.048797607421875 +13849 0.157318115234375 +13850 0.212005615234375 +13851 0.218475341796875 +13852 0.23724365234375 +13853 0.30535888671875 +13854 0.38128662109375 +13855 0.404449462890625 +13856 0.3944091796875 +13857 0.3885498046875 +13858 0.362640380859375 +13859 0.27362060546875 +13860 0.11712646484375 +13861 -0.054901123046875 +13862 -0.19085693359375 +13863 -0.28570556640625 +13864 -0.339263916015625 +13865 -0.3775634765625 +13866 -0.445709228515625 +13867 -0.535064697265625 +13868 -0.629058837890625 +13869 -0.697601318359375 +13870 -0.70391845703125 +13871 -0.6424560546875 +13872 -0.491241455078125 +13873 -0.265716552734375 +13874 -0.023712158203125 +13875 0.201751708984375 +13876 0.375823974609375 +13877 0.485076904296875 +13878 0.56884765625 +13879 0.634765625 +13880 0.63763427734375 +13881 0.5660400390625 +13882 0.4720458984375 +13883 0.40692138671875 +13884 0.3778076171875 +13885 0.376953125 +13886 0.371978759765625 +13887 0.313140869140625 +13888 0.184417724609375 +13889 0.011199951171875 +13890 -0.171051025390625 +13891 -0.33740234375 +13892 -0.47198486328125 +13893 -0.560394287109375 +13894 -0.58056640625 +13895 -0.54754638671875 +13896 -0.508575439453125 +13897 -0.459503173828125 +13898 -0.394378662109375 +13899 -0.35260009765625 +13900 -0.31170654296875 +13901 -0.197418212890625 +13902 -0.007965087890625 +13903 0.207489013671875 +13904 0.409210205078125 +13905 0.57208251953125 +13906 0.66595458984375 +13907 0.65875244140625 +13908 0.56744384765625 +13909 0.431396484375 +13910 0.29443359375 +13911 0.182464599609375 +13912 0.06365966796875 +13913 -0.075958251953125 +13914 -0.189422607421875 +13915 -0.271942138671875 +13916 -0.342529296875 +13917 -0.364166259765625 +13918 -0.327239990234375 +13919 -0.2769775390625 +13920 -0.253692626953125 +13921 -0.24365234375 +13922 -0.1983642578125 +13923 -0.116241455078125 +13924 -0.036834716796875 +13925 0.034881591796875 +13926 0.09124755859375 +13927 0.10888671875 +13928 0.125518798828125 +13929 0.15771484375 +13930 0.17828369140625 +13931 0.17108154296875 +13932 0.129974365234375 +13933 0.082427978515625 +13934 0.027679443359375 +13935 -0.065643310546875 +13936 -0.15936279296875 +13937 -0.21307373046875 +13938 -0.234649658203125 +13939 -0.2001953125 +13940 -0.119171142578125 +13941 -0.024749755859375 +13942 0.085784912109375 +13943 0.178131103515625 +13944 0.215576171875 +13945 0.211456298828125 +13946 0.17523193359375 +13947 0.128753662109375 +13948 0.1019287109375 +13949 0.0743408203125 +13950 0.04327392578125 +13951 0.038177490234375 +13952 0.076263427734375 +13953 0.14105224609375 +13954 0.186431884765625 +13955 0.188812255859375 +13956 0.1390380859375 +13957 0.041778564453125 +13958 -0.079437255859375 +13959 -0.219390869140625 +13960 -0.367828369140625 +13961 -0.494873046875 +13962 -0.556243896484375 +13963 -0.508697509765625 +13964 -0.3756103515625 +13965 -0.218902587890625 +13966 -0.063751220703125 +13967 0.091552734375 +13968 0.23602294921875 +13969 0.342987060546875 +13970 0.39520263671875 +13971 0.389373779296875 +13972 0.324249267578125 +13973 0.224090576171875 +13974 0.124267578125 +13975 0.037078857421875 +13976 -0.010101318359375 +13977 -0.019439697265625 +13978 -0.022796630859375 +13979 -0.001556396484375 +13980 0.056304931640625 +13981 0.106719970703125 +13982 0.096893310546875 +13983 0.042694091796875 +13984 -0.018035888671875 +13985 -0.07586669921875 +13986 -0.11944580078125 +13987 -0.15972900390625 +13988 -0.202606201171875 +13989 -0.24859619140625 +13990 -0.30517578125 +13991 -0.36212158203125 +13992 -0.39141845703125 +13993 -0.35528564453125 +13994 -0.249969482421875 +13995 -0.092864990234375 +13996 0.08905029296875 +13997 0.2352294921875 +13998 0.318817138671875 +13999 0.358642578125 +14000 0.347747802734375 +14001 0.28564453125 +14002 0.223175048828125 +14003 0.196746826171875 +14004 0.179840087890625 +14005 0.155548095703125 +14006 0.151214599609375 +14007 0.156951904296875 +14008 0.13177490234375 +14009 0.100799560546875 +14010 0.087127685546875 +14011 0.05487060546875 +14012 -0.009002685546875 +14013 -0.10400390625 +14014 -0.229400634765625 +14015 -0.35552978515625 +14016 -0.441925048828125 +14017 -0.473846435546875 +14018 -0.464813232421875 +14019 -0.419097900390625 +14020 -0.334320068359375 +14021 -0.227935791015625 +14022 -0.12347412109375 +14023 -0.02764892578125 +14024 0.077667236328125 +14025 0.2132568359375 +14026 0.38885498046875 +14027 0.582794189453125 +14028 0.734039306640625 +14029 0.800140380859375 +14030 0.7783203125 +14031 0.6651611328125 +14032 0.45965576171875 +14033 0.199188232421875 +14034 -0.050689697265625 +14035 -0.23297119140625 +14036 -0.33013916015625 +14037 -0.368408203125 +14038 -0.378936767578125 +14039 -0.376983642578125 +14040 -0.37969970703125 +14041 -0.391510009765625 +14042 -0.385345458984375 +14043 -0.3419189453125 +14044 -0.28289794921875 +14045 -0.251617431640625 +14046 -0.266143798828125 +14047 -0.273345947265625 +14048 -0.216796875 +14049 -0.128265380859375 +14050 -0.068145751953125 +14051 -0.0430908203125 +14052 -0.024444580078125 +14053 0.020721435546875 +14054 0.124481201171875 +14055 0.25787353515625 +14056 0.379119873046875 +14057 0.47991943359375 +14058 0.5281982421875 +14059 0.511138916015625 +14060 0.456207275390625 +14061 0.407470703125 +14062 0.383758544921875 +14063 0.35687255859375 +14064 0.31182861328125 +14065 0.250885009765625 +14066 0.1654052734375 +14067 0.035247802734375 +14068 -0.142059326171875 +14069 -0.33563232421875 +14070 -0.5345458984375 +14071 -0.72186279296875 +14072 -0.836669921875 +14073 -0.8326416015625 +14074 -0.7296142578125 +14075 -0.582550048828125 +14076 -0.440093994140625 +14077 -0.324310302734375 +14078 -0.20147705078125 +14079 -0.044647216796875 +14080 0.103973388671875 +14081 0.202392578125 +14082 0.264495849609375 +14083 0.338897705078125 +14084 0.443817138671875 +14085 0.545074462890625 +14086 0.6173095703125 +14087 0.6524658203125 +14088 0.66339111328125 +14089 0.6561279296875 +14090 0.606781005859375 +14091 0.501190185546875 +14092 0.352783203125 +14093 0.176544189453125 +14094 -0.034820556640625 +14095 -0.258209228515625 +14096 -0.44244384765625 +14097 -0.5753173828125 +14098 -0.65203857421875 +14099 -0.641632080078125 +14100 -0.562164306640625 +14101 -0.458038330078125 +14102 -0.350555419921875 +14103 -0.260528564453125 +14104 -0.192108154296875 +14105 -0.141937255859375 +14106 -0.1021728515625 +14107 -0.062896728515625 +14108 -0.011932373046875 +14109 0.062835693359375 +14110 0.148712158203125 +14111 0.241729736328125 +14112 0.34912109375 +14113 0.457305908203125 +14114 0.54388427734375 +14115 0.5728759765625 +14116 0.506591796875 +14117 0.351226806640625 +14118 0.146514892578125 +14119 -0.05523681640625 +14120 -0.21624755859375 +14121 -0.334930419921875 +14122 -0.402984619140625 +14123 -0.4412841796875 +14124 -0.49578857421875 +14125 -0.5601806640625 +14126 -0.600738525390625 +14127 -0.584228515625 +14128 -0.47930908203125 +14129 -0.27935791015625 +14130 -0.0089111328125 +14131 0.268798828125 +14132 0.482818603515625 +14133 0.60369873046875 +14134 0.650421142578125 +14135 0.66400146484375 +14136 0.6414794921875 +14137 0.572540283203125 +14138 0.498138427734375 +14139 0.439453125 +14140 0.375518798828125 +14141 0.274505615234375 +14142 0.1087646484375 +14143 -0.099395751953125 +14144 -0.3182373046875 +14145 -0.5489501953125 +14146 -0.7738037109375 +14147 -0.86383056640625 +14148 -0.870391845703125 +14149 -0.86895751953125 +14150 -0.861053466796875 +14151 -0.765869140625 +14152 -0.5301513671875 +14153 -0.214691162109375 +14154 0.137359619140625 +14155 0.474822998046875 +14156 0.76239013671875 +14157 0.867462158203125 +14158 0.870361328125 +14159 0.86480712890625 +14160 0.831817626953125 +14161 0.677581787109375 +14162 0.495880126953125 +14163 0.30767822265625 +14164 0.116180419921875 +14165 -0.110748291015625 +14166 -0.381805419921875 +14167 -0.6572265625 +14168 -0.857421875 +14169 -0.870391845703125 +14170 -0.870391845703125 +14171 -0.86444091796875 +14172 -0.85723876953125 +14173 -0.790008544921875 +14174 -0.62847900390625 +14175 -0.3956298828125 +14176 -0.126708984375 +14177 0.150115966796875 +14178 0.424041748046875 +14179 0.670623779296875 +14180 0.854522705078125 +14181 0.866485595703125 +14182 0.86920166015625 +14183 0.8653564453125 +14184 0.857147216796875 +14185 0.766845703125 +14186 0.628509521484375 +14187 0.462127685546875 +14188 0.297210693359375 +14189 0.14862060546875 +14190 -0.00537109375 +14191 -0.15753173828125 +14192 -0.31304931640625 +14193 -0.48876953125 +14194 -0.6416015625 +14195 -0.751373291015625 +14196 -0.84619140625 +14197 -0.861297607421875 +14198 -0.863250732421875 +14199 -0.856597900390625 +14200 -0.7498779296875 +14201 -0.624542236328125 +14202 -0.47808837890625 +14203 -0.253387451171875 +14204 0.003692626953125 +14205 0.2257080078125 +14206 0.427154541015625 +14207 0.643218994140625 +14208 0.855926513671875 +14209 0.870361328125 +14210 0.870361328125 +14211 0.862762451171875 +14212 0.79669189453125 +14213 0.595794677734375 +14214 0.362152099609375 +14215 0.1270751953125 +14216 -0.086944580078125 +14217 -0.2784423828125 +14218 -0.484832763671875 +14219 -0.729583740234375 +14220 -0.86688232421875 +14221 -0.870391845703125 +14222 -0.86859130859375 +14223 -0.86279296875 +14224 -0.817962646484375 +14225 -0.6116943359375 +14226 -0.3128662109375 +14227 0.039398193359375 +14228 0.422821044921875 +14229 0.805145263671875 +14230 0.870361328125 +14231 0.870361328125 +14232 0.860015869140625 +14233 0.727935791015625 +14234 0.48114013671875 +14235 0.2059326171875 +14236 -0.06103515625 +14237 -0.29913330078125 +14238 -0.516204833984375 +14239 -0.7252197265625 +14240 -0.85980224609375 +14241 -0.870391845703125 +14242 -0.870391845703125 +14243 -0.858062744140625 +14244 -0.673004150390625 +14245 -0.42694091796875 +14246 -0.2100830078125 +14247 -0.0362548828125 +14248 0.10943603515625 +14249 0.23516845703125 +14250 0.373687744140625 +14251 0.517791748046875 +14252 0.602783203125 +14253 0.635711669921875 +14254 0.655181884765625 +14255 0.65948486328125 +14256 0.651275634765625 +14257 0.61846923828125 +14258 0.53753662109375 +14259 0.404144287109375 +14260 0.22186279296875 +14261 0.003997802734375 +14262 -0.22100830078125 +14263 -0.42449951171875 +14264 -0.579833984375 +14265 -0.641876220703125 +14266 -0.6177978515625 +14267 -0.575531005859375 +14268 -0.526336669921875 +14269 -0.42645263671875 +14270 -0.2581787109375 +14271 -0.068695068359375 +14272 0.09222412109375 +14273 0.232147216796875 +14274 0.3509521484375 +14275 0.410064697265625 +14276 0.372955322265625 +14277 0.2554931640625 +14278 0.10711669921875 +14279 -0.052886962890625 +14280 -0.186279296875 +14281 -0.23291015625 +14282 -0.209442138671875 +14283 -0.174163818359375 +14284 -0.126739501953125 +14285 -0.048126220703125 +14286 0.0426025390625 +14287 0.10748291015625 +14288 0.1409912109375 +14289 0.19708251953125 +14290 0.273651123046875 +14291 0.31768798828125 +14292 0.341094970703125 +14293 0.368011474609375 +14294 0.37249755859375 +14295 0.30072021484375 +14296 0.1517333984375 +14297 -0.01470947265625 +14298 -0.1883544921875 +14299 -0.372711181640625 +14300 -0.51397705078125 +14301 -0.57177734375 +14302 -0.53948974609375 +14303 -0.43511962890625 +14304 -0.2962646484375 +14305 -0.161102294921875 +14306 -0.0435791015625 +14307 0.060394287109375 +14308 0.13665771484375 +14309 0.170135498046875 +14310 0.16552734375 +14311 0.15728759765625 +14312 0.150787353515625 +14313 0.12200927734375 +14314 0.080108642578125 +14315 0.05126953125 +14316 0.062896728515625 +14317 0.09271240234375 +14318 0.092987060546875 +14319 0.07855224609375 +14320 0.06427001953125 +14321 0.0347900390625 +14322 -0.01171875 +14323 -0.056060791015625 +14324 -0.055511474609375 +14325 -0.010467529296875 +14326 0.02508544921875 +14327 0.025665283203125 +14328 0.017333984375 +14329 0.00189208984375 +14330 -0.03173828125 +14331 -0.071502685546875 +14332 -0.13543701171875 +14333 -0.219970703125 +14334 -0.300506591796875 +14335 -0.376312255859375 +14336 -0.416107177734375 +14337 -0.371124267578125 +14338 -0.242279052734375 +14339 -0.069732666015625 +14340 0.125640869140625 +14341 0.31268310546875 +14342 0.45501708984375 +14343 0.554779052734375 +14344 0.61065673828125 +14345 0.610931396484375 +14346 0.531463623046875 +14347 0.3883056640625 +14348 0.23468017578125 +14349 0.095245361328125 +14350 -0.00396728515625 +14351 -0.04852294921875 +14352 -0.055145263671875 +14353 -0.0758056640625 +14354 -0.138702392578125 +14355 -0.209197998046875 +14356 -0.289031982421875 +14357 -0.37884521484375 +14358 -0.456329345703125 +14359 -0.51641845703125 +14360 -0.519287109375 +14361 -0.458251953125 +14362 -0.384796142578125 +14363 -0.323699951171875 +14364 -0.269287109375 +14365 -0.1951904296875 +14366 -0.100006103515625 +14367 -0.01055908203125 +14368 0.1033935546875 +14369 0.24908447265625 +14370 0.373199462890625 +14371 0.45806884765625 +14372 0.511474609375 +14373 0.565399169921875 +14374 0.61138916015625 +14375 0.5897216796875 +14376 0.4906005859375 +14377 0.33148193359375 +14378 0.147796630859375 +14379 -0.01873779296875 +14380 -0.140289306640625 +14381 -0.191986083984375 +14382 -0.184295654296875 +14383 -0.161834716796875 +14384 -0.166595458984375 +14385 -0.19390869140625 +14386 -0.22442626953125 +14387 -0.279754638671875 +14388 -0.3389892578125 +14389 -0.3543701171875 +14390 -0.348175048828125 +14391 -0.32598876953125 +14392 -0.2581787109375 +14393 -0.139801025390625 +14394 0.014617919921875 +14395 0.144378662109375 +14396 0.221038818359375 +14397 0.27069091796875 +14398 0.294036865234375 +14399 0.311767578125 +14400 0.339141845703125 +14401 0.360260009765625 +14402 0.360504150390625 +14403 0.308380126953125 +14404 0.18170166015625 +14405 0.0047607421875 +14406 -0.17559814453125 +14407 -0.3143310546875 +14408 -0.36785888671875 +14409 -0.36248779296875 +14410 -0.343536376953125 +14411 -0.3018798828125 +14412 -0.231414794921875 +14413 -0.117645263671875 +14414 0.007049560546875 +14415 0.087982177734375 +14416 0.13946533203125 +14417 0.17425537109375 +14418 0.188201904296875 +14419 0.171234130859375 +14420 0.118438720703125 +14421 0.05706787109375 +14422 -0.010711669921875 +14423 -0.0914306640625 +14424 -0.162322998046875 +14425 -0.194549560546875 +14426 -0.1492919921875 +14427 -0.02166748046875 +14428 0.124053955078125 +14429 0.211151123046875 +14430 0.240447998046875 +14431 0.242218017578125 +14432 0.2257080078125 +14433 0.194366455078125 +14434 0.115509033203125 +14435 0.0128173828125 +14436 -0.053802490234375 +14437 -0.110626220703125 +14438 -0.199493408203125 +14439 -0.29437255859375 +14440 -0.33221435546875 +14441 -0.27972412109375 +14442 -0.185333251953125 +14443 -0.128204345703125 +14444 -0.115692138671875 +14445 -0.116455078125 +14446 -0.105926513671875 +14447 -0.053955078125 +14448 0.048797607421875 +14449 0.157318115234375 +14450 0.212005615234375 +14451 0.218475341796875 +14452 0.23724365234375 +14453 0.30535888671875 +14454 0.38128662109375 +14455 0.404449462890625 +14456 0.3944091796875 +14457 0.3885498046875 +14458 0.362640380859375 +14459 0.27362060546875 +14460 0.11712646484375 +14461 -0.054901123046875 +14462 -0.19085693359375 +14463 -0.28570556640625 +14464 -0.339263916015625 +14465 -0.3775634765625 +14466 -0.445709228515625 +14467 -0.535064697265625 +14468 -0.629058837890625 +14469 -0.697601318359375 +14470 -0.70391845703125 +14471 -0.6424560546875 +14472 -0.491241455078125 +14473 -0.265716552734375 +14474 -0.023712158203125 +14475 0.201751708984375 +14476 0.375823974609375 +14477 0.485076904296875 +14478 0.56884765625 +14479 0.634765625 +14480 0.63763427734375 +14481 0.5660400390625 +14482 0.4720458984375 +14483 0.40692138671875 +14484 0.3778076171875 +14485 0.376953125 +14486 0.371978759765625 +14487 0.313140869140625 +14488 0.184417724609375 +14489 0.011199951171875 +14490 -0.171051025390625 +14491 -0.33740234375 +14492 -0.47198486328125 +14493 -0.560394287109375 +14494 -0.58056640625 +14495 -0.54754638671875 +14496 -0.508575439453125 +14497 -0.459503173828125 +14498 -0.394378662109375 +14499 -0.35260009765625 +14500 -0.31170654296875 +14501 -0.197418212890625 +14502 -0.007965087890625 +14503 0.207489013671875 +14504 0.409210205078125 +14505 0.57208251953125 +14506 0.66595458984375 +14507 0.65875244140625 +14508 0.56744384765625 +14509 0.431396484375 +14510 0.29443359375 +14511 0.182464599609375 +14512 0.06365966796875 +14513 -0.075958251953125 +14514 -0.189422607421875 +14515 -0.271942138671875 +14516 -0.342529296875 +14517 -0.364166259765625 +14518 -0.327239990234375 +14519 -0.2769775390625 +14520 -0.253692626953125 +14521 -0.24365234375 +14522 -0.1983642578125 +14523 -0.116241455078125 +14524 -0.036834716796875 +14525 0.034881591796875 +14526 0.09124755859375 +14527 0.10888671875 +14528 0.125518798828125 +14529 0.15771484375 +14530 0.17828369140625 +14531 0.17108154296875 +14532 0.129974365234375 +14533 0.082427978515625 +14534 0.027679443359375 +14535 -0.065643310546875 +14536 -0.15936279296875 +14537 -0.21307373046875 +14538 -0.234649658203125 +14539 -0.2001953125 +14540 -0.119171142578125 +14541 -0.024749755859375 +14542 0.085784912109375 +14543 0.178131103515625 +14544 0.215576171875 +14545 0.211456298828125 +14546 0.17523193359375 +14547 0.128753662109375 +14548 0.1019287109375 +14549 0.0743408203125 +14550 0.04327392578125 +14551 0.038177490234375 +14552 0.076263427734375 +14553 0.14105224609375 +14554 0.186431884765625 +14555 0.188812255859375 +14556 0.1390380859375 +14557 0.041778564453125 +14558 -0.079437255859375 +14559 -0.219390869140625 +14560 -0.367828369140625 +14561 -0.494873046875 +14562 -0.556243896484375 +14563 -0.508697509765625 +14564 -0.3756103515625 +14565 -0.218902587890625 +14566 -0.063751220703125 +14567 0.091552734375 +14568 0.23602294921875 +14569 0.342987060546875 +14570 0.39520263671875 +14571 0.389373779296875 +14572 0.324249267578125 +14573 0.224090576171875 +14574 0.124267578125 +14575 0.037078857421875 +14576 -0.010101318359375 +14577 -0.019439697265625 +14578 -0.022796630859375 +14579 -0.001556396484375 +14580 0.056304931640625 +14581 0.106719970703125 +14582 0.096893310546875 +14583 0.042694091796875 +14584 -0.018035888671875 +14585 -0.07586669921875 +14586 -0.11944580078125 +14587 -0.15972900390625 +14588 -0.202606201171875 +14589 -0.24859619140625 +14590 -0.30517578125 +14591 -0.36212158203125 +14592 -0.39141845703125 +14593 -0.35528564453125 +14594 -0.249969482421875 +14595 -0.092864990234375 +14596 0.08905029296875 +14597 0.2352294921875 +14598 0.318817138671875 +14599 0.358642578125 +14600 0.347747802734375 +14601 0.28564453125 +14602 0.223175048828125 +14603 0.196746826171875 +14604 0.179840087890625 +14605 0.155548095703125 +14606 0.151214599609375 +14607 0.156951904296875 +14608 0.13177490234375 +14609 0.100799560546875 +14610 0.087127685546875 +14611 0.05487060546875 +14612 -0.009002685546875 +14613 -0.10400390625 +14614 -0.229400634765625 +14615 -0.35552978515625 +14616 -0.441925048828125 +14617 -0.473846435546875 +14618 -0.464813232421875 +14619 -0.419097900390625 +14620 -0.334320068359375 +14621 -0.227935791015625 +14622 -0.12347412109375 +14623 -0.02764892578125 +14624 0.077667236328125 +14625 0.2132568359375 +14626 0.38885498046875 +14627 0.582794189453125 +14628 0.734039306640625 +14629 0.800140380859375 +14630 0.7783203125 +14631 0.6651611328125 +14632 0.45965576171875 +14633 0.199188232421875 +14634 -0.050689697265625 +14635 -0.23297119140625 +14636 -0.33013916015625 +14637 -0.368408203125 +14638 -0.378936767578125 +14639 -0.376983642578125 +14640 -0.37969970703125 +14641 -0.391510009765625 +14642 -0.385345458984375 +14643 -0.3419189453125 +14644 -0.28289794921875 +14645 -0.251617431640625 +14646 -0.266143798828125 +14647 -0.273345947265625 +14648 -0.216796875 +14649 -0.128265380859375 +14650 -0.068145751953125 +14651 -0.0430908203125 +14652 -0.024444580078125 +14653 0.020721435546875 +14654 0.124481201171875 +14655 0.25787353515625 +14656 0.379119873046875 +14657 0.47991943359375 +14658 0.5281982421875 +14659 0.511138916015625 +14660 0.456207275390625 +14661 0.407470703125 +14662 0.383758544921875 +14663 0.35687255859375 +14664 0.31182861328125 +14665 0.250885009765625 +14666 0.1654052734375 +14667 0.035247802734375 +14668 -0.142059326171875 +14669 -0.33563232421875 +14670 -0.5345458984375 +14671 -0.72186279296875 +14672 -0.836669921875 +14673 -0.8326416015625 +14674 -0.7296142578125 +14675 -0.582550048828125 +14676 -0.440093994140625 +14677 -0.324310302734375 +14678 -0.20147705078125 +14679 -0.044647216796875 +14680 0.103973388671875 +14681 0.202392578125 +14682 0.264495849609375 +14683 0.338897705078125 +14684 0.443817138671875 +14685 0.545074462890625 +14686 0.6173095703125 +14687 0.6524658203125 +14688 0.66339111328125 +14689 0.6561279296875 +14690 0.606781005859375 +14691 0.501190185546875 +14692 0.352783203125 +14693 0.176544189453125 +14694 -0.034820556640625 +14695 -0.258209228515625 +14696 -0.44244384765625 +14697 -0.5753173828125 +14698 -0.65203857421875 +14699 -0.641632080078125 +14700 -0.562164306640625 +14701 -0.458038330078125 +14702 -0.350555419921875 +14703 -0.260528564453125 +14704 -0.192108154296875 +14705 -0.141937255859375 +14706 -0.1021728515625 +14707 -0.062896728515625 +14708 -0.011932373046875 +14709 0.062835693359375 +14710 0.148712158203125 +14711 0.241729736328125 +14712 0.34912109375 +14713 0.457305908203125 +14714 0.54388427734375 +14715 0.5728759765625 +14716 0.506591796875 +14717 0.351226806640625 +14718 0.146514892578125 +14719 -0.05523681640625 +14720 -0.21624755859375 +14721 -0.334930419921875 +14722 -0.402984619140625 +14723 -0.4412841796875 +14724 -0.49578857421875 +14725 -0.5601806640625 +14726 -0.600738525390625 +14727 -0.584228515625 +14728 -0.47930908203125 +14729 -0.27935791015625 +14730 -0.0089111328125 +14731 0.268798828125 +14732 0.482818603515625 +14733 0.60369873046875 +14734 0.650421142578125 +14735 0.66400146484375 +14736 0.6414794921875 +14737 0.572540283203125 +14738 0.498138427734375 +14739 0.439453125 +14740 0.375518798828125 +14741 0.274505615234375 +14742 0.1087646484375 +14743 -0.099395751953125 +14744 -0.3182373046875 +14745 -0.5489501953125 +14746 -0.7738037109375 +14747 -0.86383056640625 +14748 -0.870391845703125 +14749 -0.86895751953125 +14750 -0.861053466796875 +14751 -0.765869140625 +14752 -0.5301513671875 +14753 -0.214691162109375 +14754 0.137359619140625 +14755 0.474822998046875 +14756 0.76239013671875 +14757 0.867462158203125 +14758 0.870361328125 +14759 0.86480712890625 +14760 0.831817626953125 +14761 0.677581787109375 +14762 0.495880126953125 +14763 0.30767822265625 +14764 0.116180419921875 +14765 -0.110748291015625 +14766 -0.381805419921875 +14767 -0.6572265625 +14768 -0.857421875 +14769 -0.870391845703125 +14770 -0.870391845703125 +14771 -0.86444091796875 +14772 -0.85723876953125 +14773 -0.790008544921875 +14774 -0.62847900390625 +14775 -0.3956298828125 +14776 -0.126708984375 +14777 0.150115966796875 +14778 0.424041748046875 +14779 0.670623779296875 +14780 0.854522705078125 +14781 0.866485595703125 +14782 0.86920166015625 +14783 0.8653564453125 +14784 0.857147216796875 +14785 0.766845703125 +14786 0.628509521484375 +14787 0.462127685546875 +14788 0.297210693359375 +14789 0.14862060546875 +14790 -0.00537109375 +14791 -0.15753173828125 +14792 -0.31304931640625 +14793 -0.48876953125 +14794 -0.6416015625 +14795 -0.751373291015625 +14796 -0.84619140625 +14797 -0.861297607421875 +14798 -0.863250732421875 +14799 -0.856597900390625 +14800 -0.7498779296875 +14801 -0.624542236328125 +14802 -0.47808837890625 +14803 -0.253387451171875 +14804 0.003692626953125 +14805 0.2257080078125 +14806 0.427154541015625 +14807 0.643218994140625 +14808 0.855926513671875 +14809 0.870361328125 +14810 0.870361328125 +14811 0.862762451171875 +14812 0.79669189453125 +14813 0.595794677734375 +14814 0.362152099609375 +14815 0.1270751953125 +14816 -0.086944580078125 +14817 -0.2784423828125 +14818 -0.484832763671875 +14819 -0.729583740234375 +14820 -0.86688232421875 +14821 -0.870391845703125 +14822 -0.86859130859375 +14823 -0.86279296875 +14824 -0.817962646484375 +14825 -0.6116943359375 +14826 -0.3128662109375 +14827 0.039398193359375 +14828 0.422821044921875 +14829 0.805145263671875 +14830 0.870361328125 +14831 0.870361328125 +14832 0.860015869140625 +14833 0.727935791015625 +14834 0.48114013671875 +14835 0.2059326171875 +14836 -0.06103515625 +14837 -0.29913330078125 +14838 -0.516204833984375 +14839 -0.7252197265625 +14840 -0.85980224609375 +14841 -0.870391845703125 +14842 -0.870391845703125 +14843 -0.858062744140625 +14844 -0.673004150390625 +14845 -0.42694091796875 +14846 -0.2100830078125 +14847 -0.0362548828125 +14848 0.10943603515625 +14849 0.23516845703125 +14850 0.373687744140625 +14851 0.517791748046875 +14852 0.602783203125 +14853 0.635711669921875 +14854 0.655181884765625 +14855 0.65948486328125 +14856 0.651275634765625 +14857 0.61846923828125 +14858 0.53753662109375 +14859 0.404144287109375 +14860 0.22186279296875 +14861 0.003997802734375 +14862 -0.22100830078125 +14863 -0.42449951171875 +14864 -0.579833984375 +14865 -0.641876220703125 +14866 -0.6177978515625 +14867 -0.575531005859375 +14868 -0.526336669921875 +14869 -0.42645263671875 +14870 -0.2581787109375 +14871 -0.068695068359375 +14872 0.09222412109375 +14873 0.232147216796875 +14874 0.3509521484375 +14875 0.410064697265625 +14876 0.372955322265625 +14877 0.2554931640625 +14878 0.10711669921875 +14879 -0.052886962890625 +14880 -0.186279296875 +14881 -0.23291015625 +14882 -0.209442138671875 +14883 -0.174163818359375 +14884 -0.126739501953125 +14885 -0.048126220703125 +14886 0.0426025390625 +14887 0.10748291015625 +14888 0.1409912109375 +14889 0.19708251953125 +14890 0.273651123046875 +14891 0.31768798828125 +14892 0.341094970703125 +14893 0.368011474609375 +14894 0.37249755859375 +14895 0.30072021484375 +14896 0.1517333984375 +14897 -0.01470947265625 +14898 -0.1883544921875 +14899 -0.372711181640625 +14900 -0.51397705078125 +14901 -0.57177734375 +14902 -0.53948974609375 +14903 -0.43511962890625 +14904 -0.2962646484375 +14905 -0.161102294921875 +14906 -0.0435791015625 +14907 0.060394287109375 +14908 0.13665771484375 +14909 0.170135498046875 +14910 0.16552734375 +14911 0.15728759765625 +14912 0.150787353515625 +14913 0.12200927734375 +14914 0.080108642578125 +14915 0.05126953125 +14916 0.062896728515625 +14917 0.09271240234375 +14918 0.092987060546875 +14919 0.07855224609375 +14920 0.06427001953125 +14921 0.0347900390625 +14922 -0.01171875 +14923 -0.056060791015625 +14924 -0.055511474609375 +14925 -0.010467529296875 +14926 0.02508544921875 +14927 0.025665283203125 +14928 0.017333984375 +14929 0.00189208984375 +14930 -0.03173828125 +14931 -0.071502685546875 +14932 -0.13543701171875 +14933 -0.219970703125 +14934 -0.300506591796875 +14935 -0.376312255859375 +14936 -0.416107177734375 +14937 -0.371124267578125 +14938 -0.242279052734375 +14939 -0.069732666015625 +14940 0.125640869140625 +14941 0.31268310546875 +14942 0.45501708984375 +14943 0.554779052734375 +14944 0.61065673828125 +14945 0.610931396484375 +14946 0.531463623046875 +14947 0.3883056640625 +14948 0.23468017578125 +14949 0.095245361328125 +14950 -0.00396728515625 +14951 -0.04852294921875 +14952 -0.055145263671875 +14953 -0.0758056640625 +14954 -0.138702392578125 +14955 -0.209197998046875 +14956 -0.289031982421875 +14957 -0.37884521484375 +14958 -0.456329345703125 +14959 -0.51641845703125 +14960 -0.519287109375 +14961 -0.458251953125 +14962 -0.384796142578125 +14963 -0.323699951171875 +14964 -0.269287109375 +14965 -0.1951904296875 +14966 -0.100006103515625 +14967 -0.01055908203125 +14968 0.1033935546875 +14969 0.24908447265625 +14970 0.373199462890625 +14971 0.45806884765625 +14972 0.511474609375 +14973 0.565399169921875 +14974 0.61138916015625 +14975 0.5897216796875 +14976 0.4906005859375 +14977 0.33148193359375 +14978 0.147796630859375 +14979 -0.01873779296875 +14980 -0.140289306640625 +14981 -0.191986083984375 +14982 -0.184295654296875 +14983 -0.161834716796875 +14984 -0.166595458984375 +14985 -0.19390869140625 +14986 -0.22442626953125 +14987 -0.279754638671875 +14988 -0.3389892578125 +14989 -0.3543701171875 +14990 -0.348175048828125 +14991 -0.32598876953125 +14992 -0.2581787109375 +14993 -0.139801025390625 +14994 0.014617919921875 +14995 0.144378662109375 +14996 0.221038818359375 +14997 0.27069091796875 +14998 0.294036865234375 +14999 0.311767578125 +15000 0.339141845703125 +15001 0.360260009765625 +15002 0.360504150390625 +15003 0.308380126953125 +15004 0.18170166015625 +15005 0.0047607421875 +15006 -0.17559814453125 +15007 -0.3143310546875 +15008 -0.36785888671875 +15009 -0.36248779296875 +15010 -0.343536376953125 +15011 -0.3018798828125 +15012 -0.231414794921875 +15013 -0.117645263671875 +15014 0.007049560546875 +15015 0.087982177734375 +15016 0.13946533203125 +15017 0.17425537109375 +15018 0.188201904296875 +15019 0.171234130859375 +15020 0.118438720703125 +15021 0.05706787109375 +15022 -0.010711669921875 +15023 -0.0914306640625 +15024 -0.162322998046875 +15025 -0.194549560546875 +15026 -0.1492919921875 +15027 -0.02166748046875 +15028 0.124053955078125 +15029 0.211151123046875 +15030 0.240447998046875 +15031 0.242218017578125 +15032 0.2257080078125 +15033 0.194366455078125 +15034 0.115509033203125 +15035 0.0128173828125 +15036 -0.053802490234375 +15037 -0.110626220703125 +15038 -0.199493408203125 +15039 -0.29437255859375 +15040 -0.33221435546875 +15041 -0.27972412109375 +15042 -0.185333251953125 +15043 -0.128204345703125 +15044 -0.115692138671875 +15045 -0.116455078125 +15046 -0.105926513671875 +15047 -0.053955078125 +15048 0.048797607421875 +15049 0.157318115234375 +15050 0.212005615234375 +15051 0.218475341796875 +15052 0.23724365234375 +15053 0.30535888671875 +15054 0.38128662109375 +15055 0.404449462890625 +15056 0.3944091796875 +15057 0.3885498046875 +15058 0.362640380859375 +15059 0.27362060546875 +15060 0.11712646484375 +15061 -0.054901123046875 +15062 -0.19085693359375 +15063 -0.28570556640625 +15064 -0.339263916015625 +15065 -0.3775634765625 +15066 -0.445709228515625 +15067 -0.535064697265625 +15068 -0.629058837890625 +15069 -0.697601318359375 +15070 -0.70391845703125 +15071 -0.6424560546875 +15072 -0.491241455078125 +15073 -0.265716552734375 +15074 -0.023712158203125 +15075 0.201751708984375 +15076 0.375823974609375 +15077 0.485076904296875 +15078 0.56884765625 +15079 0.634765625 +15080 0.63763427734375 +15081 0.5660400390625 +15082 0.4720458984375 +15083 0.40692138671875 +15084 0.3778076171875 +15085 0.376953125 +15086 0.371978759765625 +15087 0.313140869140625 +15088 0.184417724609375 +15089 0.011199951171875 +15090 -0.171051025390625 +15091 -0.33740234375 +15092 -0.47198486328125 +15093 -0.560394287109375 +15094 -0.58056640625 +15095 -0.54754638671875 +15096 -0.508575439453125 +15097 -0.459503173828125 +15098 -0.394378662109375 +15099 -0.35260009765625 +15100 -0.31170654296875 +15101 -0.197418212890625 +15102 -0.007965087890625 +15103 0.207489013671875 +15104 0.409210205078125 +15105 0.57208251953125 +15106 0.66595458984375 +15107 0.65875244140625 +15108 0.56744384765625 +15109 0.431396484375 +15110 0.29443359375 +15111 0.182464599609375 +15112 0.06365966796875 +15113 -0.075958251953125 +15114 -0.189422607421875 +15115 -0.271942138671875 +15116 -0.342529296875 +15117 -0.364166259765625 +15118 -0.327239990234375 +15119 -0.2769775390625 +15120 -0.253692626953125 +15121 -0.24365234375 +15122 -0.1983642578125 +15123 -0.116241455078125 +15124 -0.036834716796875 +15125 0.034881591796875 +15126 0.09124755859375 +15127 0.10888671875 +15128 0.125518798828125 +15129 0.15771484375 +15130 0.17828369140625 +15131 0.17108154296875 +15132 0.129974365234375 +15133 0.082427978515625 +15134 0.027679443359375 +15135 -0.065643310546875 +15136 -0.15936279296875 +15137 -0.21307373046875 +15138 -0.234649658203125 +15139 -0.2001953125 +15140 -0.119171142578125 +15141 -0.024749755859375 +15142 0.085784912109375 +15143 0.178131103515625 +15144 0.215576171875 +15145 0.211456298828125 +15146 0.17523193359375 +15147 0.128753662109375 +15148 0.1019287109375 +15149 0.0743408203125 +15150 0.04327392578125 +15151 0.038177490234375 +15152 0.076263427734375 +15153 0.14105224609375 +15154 0.186431884765625 +15155 0.188812255859375 +15156 0.1390380859375 +15157 0.041778564453125 +15158 -0.079437255859375 +15159 -0.219390869140625 +15160 -0.367828369140625 +15161 -0.494873046875 +15162 -0.556243896484375 +15163 -0.508697509765625 +15164 -0.3756103515625 +15165 -0.218902587890625 +15166 -0.063751220703125 +15167 0.091552734375 +15168 0.23602294921875 +15169 0.342987060546875 +15170 0.39520263671875 +15171 0.389373779296875 +15172 0.324249267578125 +15173 0.224090576171875 +15174 0.124267578125 +15175 0.037078857421875 +15176 -0.010101318359375 +15177 -0.019439697265625 +15178 -0.022796630859375 +15179 -0.001556396484375 +15180 0.056304931640625 +15181 0.106719970703125 +15182 0.096893310546875 +15183 0.042694091796875 +15184 -0.018035888671875 +15185 -0.07586669921875 +15186 -0.11944580078125 +15187 -0.15972900390625 +15188 -0.202606201171875 +15189 -0.24859619140625 +15190 -0.30517578125 +15191 -0.36212158203125 +15192 -0.39141845703125 +15193 -0.35528564453125 +15194 -0.249969482421875 +15195 -0.092864990234375 +15196 0.08905029296875 +15197 0.2352294921875 +15198 0.318817138671875 +15199 0.358642578125 +15200 0.347747802734375 +15201 0.28564453125 +15202 0.223175048828125 +15203 0.196746826171875 +15204 0.179840087890625 +15205 0.155548095703125 +15206 0.151214599609375 +15207 0.156951904296875 +15208 0.13177490234375 +15209 0.100799560546875 +15210 0.087127685546875 +15211 0.05487060546875 +15212 -0.009002685546875 +15213 -0.10400390625 +15214 -0.229400634765625 +15215 -0.35552978515625 +15216 -0.441925048828125 +15217 -0.473846435546875 +15218 -0.464813232421875 +15219 -0.419097900390625 +15220 -0.334320068359375 +15221 -0.227935791015625 +15222 -0.12347412109375 +15223 -0.02764892578125 +15224 0.077667236328125 +15225 0.2132568359375 +15226 0.38885498046875 +15227 0.582794189453125 +15228 0.734039306640625 +15229 0.800140380859375 +15230 0.7783203125 +15231 0.6651611328125 +15232 0.45965576171875 +15233 0.199188232421875 +15234 -0.050689697265625 +15235 -0.23297119140625 +15236 -0.33013916015625 +15237 -0.368408203125 +15238 -0.378936767578125 +15239 -0.376983642578125 +15240 -0.37969970703125 +15241 -0.391510009765625 +15242 -0.385345458984375 +15243 -0.3419189453125 +15244 -0.28289794921875 +15245 -0.251617431640625 +15246 -0.266143798828125 +15247 -0.273345947265625 +15248 -0.216796875 +15249 -0.128265380859375 +15250 -0.068145751953125 +15251 -0.0430908203125 +15252 -0.024444580078125 +15253 0.020721435546875 +15254 0.124481201171875 +15255 0.25787353515625 +15256 0.379119873046875 +15257 0.47991943359375 +15258 0.5281982421875 +15259 0.511138916015625 +15260 0.456207275390625 +15261 0.407470703125 +15262 0.383758544921875 +15263 0.35687255859375 +15264 0.31182861328125 +15265 0.250885009765625 +15266 0.1654052734375 +15267 0.035247802734375 +15268 -0.142059326171875 +15269 -0.33563232421875 +15270 -0.5345458984375 +15271 -0.72186279296875 +15272 -0.836669921875 +15273 -0.8326416015625 +15274 -0.7296142578125 +15275 -0.582550048828125 +15276 -0.440093994140625 +15277 -0.324310302734375 +15278 -0.20147705078125 +15279 -0.044647216796875 +15280 0.103973388671875 +15281 0.202392578125 +15282 0.264495849609375 +15283 0.338897705078125 +15284 0.443817138671875 +15285 0.545074462890625 +15286 0.6173095703125 +15287 0.6524658203125 +15288 0.66339111328125 +15289 0.6561279296875 +15290 0.606781005859375 +15291 0.501190185546875 +15292 0.352783203125 +15293 0.176544189453125 +15294 -0.034820556640625 +15295 -0.258209228515625 +15296 -0.44244384765625 +15297 -0.5753173828125 +15298 -0.65203857421875 +15299 -0.641632080078125 +15300 -0.562164306640625 +15301 -0.458038330078125 +15302 -0.350555419921875 +15303 -0.260528564453125 +15304 -0.192108154296875 +15305 -0.141937255859375 +15306 -0.1021728515625 +15307 -0.062896728515625 +15308 -0.011932373046875 +15309 0.062835693359375 +15310 0.148712158203125 +15311 0.241729736328125 +15312 0.34912109375 +15313 0.457305908203125 +15314 0.54388427734375 +15315 0.5728759765625 +15316 0.506591796875 +15317 0.351226806640625 +15318 0.146514892578125 +15319 -0.05523681640625 +15320 -0.21624755859375 +15321 -0.334930419921875 +15322 -0.402984619140625 +15323 -0.4412841796875 +15324 -0.49578857421875 +15325 -0.5601806640625 +15326 -0.600738525390625 +15327 -0.584228515625 +15328 -0.47930908203125 +15329 -0.27935791015625 +15330 -0.0089111328125 +15331 0.268798828125 +15332 0.482818603515625 +15333 0.60369873046875 +15334 0.650421142578125 +15335 0.66400146484375 +15336 0.6414794921875 +15337 0.572540283203125 +15338 0.498138427734375 +15339 0.439453125 +15340 0.375518798828125 +15341 0.274505615234375 +15342 0.1087646484375 +15343 -0.099395751953125 +15344 -0.3182373046875 +15345 -0.5489501953125 +15346 -0.7738037109375 +15347 -0.86383056640625 +15348 -0.870391845703125 +15349 -0.86895751953125 +15350 -0.861053466796875 +15351 -0.765869140625 +15352 -0.5301513671875 +15353 -0.214691162109375 +15354 0.137359619140625 +15355 0.474822998046875 +15356 0.76239013671875 +15357 0.867462158203125 +15358 0.870361328125 +15359 0.86480712890625 +15360 0.831817626953125 +15361 0.677581787109375 +15362 0.495880126953125 +15363 0.30767822265625 +15364 0.116180419921875 +15365 -0.110748291015625 +15366 -0.381805419921875 +15367 -0.6572265625 +15368 -0.857421875 +15369 -0.870391845703125 +15370 -0.870391845703125 +15371 -0.86444091796875 +15372 -0.85723876953125 +15373 -0.790008544921875 +15374 -0.62847900390625 +15375 -0.3956298828125 +15376 -0.126708984375 +15377 0.150115966796875 +15378 0.424041748046875 +15379 0.670623779296875 +15380 0.854522705078125 +15381 0.866485595703125 +15382 0.86920166015625 +15383 0.8653564453125 +15384 0.857147216796875 +15385 0.766845703125 +15386 0.628509521484375 +15387 0.462127685546875 +15388 0.297210693359375 +15389 0.14862060546875 +15390 -0.00537109375 +15391 -0.15753173828125 +15392 -0.31304931640625 +15393 -0.48876953125 +15394 -0.6416015625 +15395 -0.751373291015625 +15396 -0.84619140625 +15397 -0.861297607421875 +15398 -0.863250732421875 +15399 -0.856597900390625 +15400 -0.7498779296875 +15401 -0.624542236328125 +15402 -0.47808837890625 +15403 -0.253387451171875 +15404 0.003692626953125 +15405 0.2257080078125 +15406 0.427154541015625 +15407 0.643218994140625 +15408 0.855926513671875 +15409 0.870361328125 +15410 0.870361328125 +15411 0.862762451171875 +15412 0.79669189453125 +15413 0.595794677734375 +15414 0.362152099609375 +15415 0.1270751953125 +15416 -0.086944580078125 +15417 -0.2784423828125 +15418 -0.484832763671875 +15419 -0.729583740234375 +15420 -0.86688232421875 +15421 -0.870391845703125 +15422 -0.86859130859375 +15423 -0.86279296875 +15424 -0.817962646484375 +15425 -0.6116943359375 +15426 -0.3128662109375 +15427 0.039398193359375 +15428 0.422821044921875 +15429 0.805145263671875 +15430 0.870361328125 +15431 0.870361328125 +15432 0.860015869140625 +15433 0.727935791015625 +15434 0.48114013671875 +15435 0.2059326171875 +15436 -0.06103515625 +15437 -0.29913330078125 +15438 -0.516204833984375 +15439 -0.7252197265625 +15440 -0.85980224609375 +15441 -0.870391845703125 +15442 -0.870391845703125 +15443 -0.858062744140625 +15444 -0.673004150390625 +15445 -0.42694091796875 +15446 -0.2100830078125 +15447 -0.0362548828125 +15448 0.10943603515625 +15449 0.23516845703125 +15450 0.373687744140625 +15451 0.517791748046875 +15452 0.602783203125 +15453 0.635711669921875 +15454 0.655181884765625 +15455 0.65948486328125 +15456 0.651275634765625 +15457 0.61846923828125 +15458 0.53753662109375 +15459 0.404144287109375 +15460 0.22186279296875 +15461 0.003997802734375 +15462 -0.22100830078125 +15463 -0.42449951171875 +15464 -0.579833984375 +15465 -0.641876220703125 +15466 -0.6177978515625 +15467 -0.575531005859375 +15468 -0.526336669921875 +15469 -0.42645263671875 +15470 -0.2581787109375 +15471 -0.068695068359375 +15472 0.09222412109375 +15473 0.232147216796875 +15474 0.3509521484375 +15475 0.410064697265625 +15476 0.372955322265625 +15477 0.2554931640625 +15478 0.10711669921875 +15479 -0.052886962890625 +15480 -0.186279296875 +15481 -0.23291015625 +15482 -0.209442138671875 +15483 -0.174163818359375 +15484 -0.126739501953125 +15485 -0.048126220703125 +15486 0.0426025390625 +15487 0.10748291015625 +15488 0.1409912109375 +15489 0.19708251953125 +15490 0.273651123046875 +15491 0.31768798828125 +15492 0.341094970703125 +15493 0.368011474609375 +15494 0.37249755859375 +15495 0.30072021484375 +15496 0.1517333984375 +15497 -0.01470947265625 +15498 -0.1883544921875 +15499 -0.372711181640625 +15500 -0.51397705078125 +15501 -0.57177734375 +15502 -0.53948974609375 +15503 -0.43511962890625 +15504 -0.2962646484375 +15505 -0.161102294921875 +15506 -0.0435791015625 +15507 0.060394287109375 +15508 0.13665771484375 +15509 0.170135498046875 +15510 0.16552734375 +15511 0.15728759765625 +15512 0.150787353515625 +15513 0.12200927734375 +15514 0.080108642578125 +15515 0.05126953125 +15516 0.062896728515625 +15517 0.09271240234375 +15518 0.092987060546875 +15519 0.07855224609375 +15520 0.06427001953125 +15521 0.0347900390625 +15522 -0.01171875 +15523 -0.056060791015625 +15524 -0.055511474609375 +15525 -0.010467529296875 +15526 0.02508544921875 +15527 0.025665283203125 +15528 0.017333984375 +15529 0.00189208984375 +15530 -0.03173828125 +15531 -0.071502685546875 +15532 -0.13543701171875 +15533 -0.219970703125 +15534 -0.300506591796875 +15535 -0.376312255859375 +15536 -0.416107177734375 +15537 -0.371124267578125 +15538 -0.242279052734375 +15539 -0.069732666015625 +15540 0.125640869140625 +15541 0.31268310546875 +15542 0.45501708984375 +15543 0.554779052734375 +15544 0.61065673828125 +15545 0.610931396484375 +15546 0.531463623046875 +15547 0.3883056640625 +15548 0.23468017578125 +15549 0.095245361328125 +15550 -0.00396728515625 +15551 -0.04852294921875 +15552 -0.055145263671875 +15553 -0.0758056640625 +15554 -0.138702392578125 +15555 -0.209197998046875 +15556 -0.289031982421875 +15557 -0.37884521484375 +15558 -0.456329345703125 +15559 -0.51641845703125 +15560 -0.519287109375 +15561 -0.458251953125 +15562 -0.384796142578125 +15563 -0.323699951171875 +15564 -0.269287109375 +15565 -0.1951904296875 +15566 -0.100006103515625 +15567 -0.01055908203125 +15568 0.1033935546875 +15569 0.24908447265625 +15570 0.373199462890625 +15571 0.45806884765625 +15572 0.511474609375 +15573 0.565399169921875 +15574 0.61138916015625 +15575 0.5897216796875 +15576 0.4906005859375 +15577 0.33148193359375 +15578 0.147796630859375 +15579 -0.01873779296875 +15580 -0.140289306640625 +15581 -0.191986083984375 +15582 -0.184295654296875 +15583 -0.161834716796875 +15584 -0.166595458984375 +15585 -0.19390869140625 +15586 -0.22442626953125 +15587 -0.279754638671875 +15588 -0.3389892578125 +15589 -0.3543701171875 +15590 -0.348175048828125 +15591 -0.32598876953125 +15592 -0.2581787109375 +15593 -0.139801025390625 +15594 0.014617919921875 +15595 0.144378662109375 +15596 0.221038818359375 +15597 0.27069091796875 +15598 0.294036865234375 +15599 0.311767578125 +15600 0.339141845703125 +15601 0.360260009765625 +15602 0.360504150390625 +15603 0.308380126953125 +15604 0.18170166015625 +15605 0.0047607421875 +15606 -0.17559814453125 +15607 -0.3143310546875 +15608 -0.36785888671875 +15609 -0.36248779296875 +15610 -0.343536376953125 +15611 -0.3018798828125 +15612 -0.231414794921875 +15613 -0.117645263671875 +15614 0.007049560546875 +15615 0.087982177734375 +15616 0.13946533203125 +15617 0.17425537109375 +15618 0.188201904296875 +15619 0.171234130859375 +15620 0.118438720703125 +15621 0.05706787109375 +15622 -0.010711669921875 +15623 -0.0914306640625 +15624 -0.162322998046875 +15625 -0.194549560546875 +15626 -0.1492919921875 +15627 -0.02166748046875 +15628 0.124053955078125 +15629 0.211151123046875 +15630 0.240447998046875 +15631 0.242218017578125 +15632 0.2257080078125 +15633 0.194366455078125 +15634 0.115509033203125 +15635 0.0128173828125 +15636 -0.053802490234375 +15637 -0.110626220703125 +15638 -0.199493408203125 +15639 -0.29437255859375 +15640 -0.33221435546875 +15641 -0.27972412109375 +15642 -0.185333251953125 +15643 -0.128204345703125 +15644 -0.115692138671875 +15645 -0.116455078125 +15646 -0.105926513671875 +15647 -0.053955078125 +15648 0.048797607421875 +15649 0.157318115234375 +15650 0.212005615234375 +15651 0.218475341796875 +15652 0.23724365234375 +15653 0.30535888671875 +15654 0.38128662109375 +15655 0.404449462890625 +15656 0.3944091796875 +15657 0.3885498046875 +15658 0.362640380859375 +15659 0.27362060546875 +15660 0.11712646484375 +15661 -0.054901123046875 +15662 -0.19085693359375 +15663 -0.28570556640625 +15664 -0.339263916015625 +15665 -0.3775634765625 +15666 -0.445709228515625 +15667 -0.535064697265625 +15668 -0.629058837890625 +15669 -0.697601318359375 +15670 -0.70391845703125 +15671 -0.6424560546875 +15672 -0.491241455078125 +15673 -0.265716552734375 +15674 -0.023712158203125 +15675 0.201751708984375 +15676 0.375823974609375 +15677 0.485076904296875 +15678 0.56884765625 +15679 0.634765625 +15680 0.63763427734375 +15681 0.5660400390625 +15682 0.4720458984375 +15683 0.40692138671875 +15684 0.3778076171875 +15685 0.376953125 +15686 0.371978759765625 +15687 0.313140869140625 +15688 0.184417724609375 +15689 0.011199951171875 +15690 -0.171051025390625 +15691 -0.33740234375 +15692 -0.47198486328125 +15693 -0.560394287109375 +15694 -0.58056640625 +15695 -0.54754638671875 +15696 -0.508575439453125 +15697 -0.459503173828125 +15698 -0.394378662109375 +15699 -0.35260009765625 +15700 -0.31170654296875 +15701 -0.197418212890625 +15702 -0.007965087890625 +15703 0.207489013671875 +15704 0.409210205078125 +15705 0.57208251953125 +15706 0.66595458984375 +15707 0.65875244140625 +15708 0.56744384765625 +15709 0.431396484375 +15710 0.29443359375 +15711 0.182464599609375 +15712 0.06365966796875 +15713 -0.075958251953125 +15714 -0.189422607421875 +15715 -0.271942138671875 +15716 -0.342529296875 +15717 -0.364166259765625 +15718 -0.327239990234375 +15719 -0.2769775390625 +15720 -0.253692626953125 +15721 -0.24365234375 +15722 -0.1983642578125 +15723 -0.116241455078125 +15724 -0.036834716796875 +15725 0.034881591796875 +15726 0.09124755859375 +15727 0.10888671875 +15728 0.125518798828125 +15729 0.15771484375 +15730 0.17828369140625 +15731 0.17108154296875 +15732 0.129974365234375 +15733 0.082427978515625 +15734 0.027679443359375 +15735 -0.065643310546875 +15736 -0.15936279296875 +15737 -0.21307373046875 +15738 -0.234649658203125 +15739 -0.2001953125 +15740 -0.119171142578125 +15741 -0.024749755859375 +15742 0.085784912109375 +15743 0.178131103515625 +15744 0.215576171875 +15745 0.211456298828125 +15746 0.17523193359375 +15747 0.128753662109375 +15748 0.1019287109375 +15749 0.0743408203125 +15750 0.04327392578125 +15751 0.038177490234375 +15752 0.076263427734375 +15753 0.14105224609375 +15754 0.186431884765625 +15755 0.188812255859375 +15756 0.1390380859375 +15757 0.041778564453125 +15758 -0.079437255859375 +15759 -0.219390869140625 +15760 -0.367828369140625 +15761 -0.494873046875 +15762 -0.556243896484375 +15763 -0.508697509765625 +15764 -0.3756103515625 +15765 -0.218902587890625 +15766 -0.063751220703125 +15767 0.091552734375 +15768 0.23602294921875 +15769 0.342987060546875 +15770 0.39520263671875 +15771 0.389373779296875 +15772 0.324249267578125 +15773 0.224090576171875 +15774 0.124267578125 +15775 0.037078857421875 +15776 -0.010101318359375 +15777 -0.019439697265625 +15778 -0.022796630859375 +15779 -0.001556396484375 +15780 0.056304931640625 +15781 0.106719970703125 +15782 0.096893310546875 +15783 0.042694091796875 +15784 -0.018035888671875 +15785 -0.07586669921875 +15786 -0.11944580078125 +15787 -0.15972900390625 +15788 -0.202606201171875 +15789 -0.24859619140625 +15790 -0.30517578125 +15791 -0.36212158203125 +15792 -0.39141845703125 +15793 -0.35528564453125 +15794 -0.249969482421875 +15795 -0.092864990234375 +15796 0.08905029296875 +15797 0.2352294921875 +15798 0.318817138671875 +15799 0.358642578125 +15800 0.347747802734375 +15801 0.28564453125 +15802 0.223175048828125 +15803 0.196746826171875 +15804 0.179840087890625 +15805 0.155548095703125 +15806 0.151214599609375 +15807 0.156951904296875 +15808 0.13177490234375 +15809 0.100799560546875 +15810 0.087127685546875 +15811 0.05487060546875 +15812 -0.009002685546875 +15813 -0.10400390625 +15814 -0.229400634765625 +15815 -0.35552978515625 +15816 -0.441925048828125 +15817 -0.473846435546875 +15818 -0.464813232421875 +15819 -0.419097900390625 +15820 -0.334320068359375 +15821 -0.227935791015625 +15822 -0.12347412109375 +15823 -0.02764892578125 +15824 0.077667236328125 +15825 0.2132568359375 +15826 0.38885498046875 +15827 0.582794189453125 +15828 0.734039306640625 +15829 0.800140380859375 +15830 0.7783203125 +15831 0.6651611328125 +15832 0.45965576171875 +15833 0.199188232421875 +15834 -0.050689697265625 +15835 -0.23297119140625 +15836 -0.33013916015625 +15837 -0.368408203125 +15838 -0.378936767578125 +15839 -0.376983642578125 +15840 -0.37969970703125 +15841 -0.391510009765625 +15842 -0.385345458984375 +15843 -0.3419189453125 +15844 -0.28289794921875 +15845 -0.251617431640625 +15846 -0.266143798828125 +15847 -0.273345947265625 +15848 -0.216796875 +15849 -0.128265380859375 +15850 -0.068145751953125 +15851 -0.0430908203125 +15852 -0.024444580078125 +15853 0.020721435546875 +15854 0.124481201171875 +15855 0.25787353515625 +15856 0.379119873046875 +15857 0.47991943359375 +15858 0.5281982421875 +15859 0.511138916015625 +15860 0.456207275390625 +15861 0.407470703125 +15862 0.383758544921875 +15863 0.35687255859375 +15864 0.31182861328125 +15865 0.250885009765625 +15866 0.1654052734375 +15867 0.035247802734375 +15868 -0.142059326171875 +15869 -0.33563232421875 +15870 -0.5345458984375 +15871 -0.72186279296875 +15872 -0.836669921875 +15873 -0.8326416015625 +15874 -0.7296142578125 +15875 -0.582550048828125 +15876 -0.440093994140625 +15877 -0.324310302734375 +15878 -0.20147705078125 +15879 -0.044647216796875 +15880 0.103973388671875 +15881 0.202392578125 +15882 0.264495849609375 +15883 0.338897705078125 +15884 0.443817138671875 +15885 0.545074462890625 +15886 0.6173095703125 +15887 0.6524658203125 +15888 0.66339111328125 +15889 0.6561279296875 +15890 0.606781005859375 +15891 0.501190185546875 +15892 0.352783203125 +15893 0.176544189453125 +15894 -0.034820556640625 +15895 -0.258209228515625 +15896 -0.44244384765625 +15897 -0.5753173828125 +15898 -0.65203857421875 +15899 -0.641632080078125 +15900 -0.562164306640625 +15901 -0.458038330078125 +15902 -0.350555419921875 +15903 -0.260528564453125 +15904 -0.192108154296875 +15905 -0.141937255859375 +15906 -0.1021728515625 +15907 -0.062896728515625 +15908 -0.011932373046875 +15909 0.062835693359375 +15910 0.148712158203125 +15911 0.241729736328125 +15912 0.34912109375 +15913 0.457305908203125 +15914 0.54388427734375 +15915 0.5728759765625 +15916 0.506591796875 +15917 0.351226806640625 +15918 0.146514892578125 +15919 -0.05523681640625 +15920 -0.21624755859375 +15921 -0.334930419921875 +15922 -0.402984619140625 +15923 -0.4412841796875 +15924 -0.49578857421875 +15925 -0.5601806640625 +15926 -0.600738525390625 +15927 -0.584228515625 +15928 -0.47930908203125 +15929 -0.27935791015625 +15930 -0.0089111328125 +15931 0.268798828125 +15932 0.482818603515625 +15933 0.60369873046875 +15934 0.650421142578125 +15935 0.66400146484375 +15936 0.6414794921875 +15937 0.572540283203125 +15938 0.498138427734375 +15939 0.439453125 +15940 0.375518798828125 +15941 0.274505615234375 +15942 0.1087646484375 +15943 -0.099395751953125 +15944 -0.3182373046875 +15945 -0.5489501953125 +15946 -0.7738037109375 +15947 -0.86383056640625 +15948 -0.870391845703125 +15949 -0.86895751953125 +15950 -0.861053466796875 +15951 -0.765869140625 +15952 -0.5301513671875 +15953 -0.214691162109375 +15954 0.137359619140625 +15955 0.474822998046875 +15956 0.76239013671875 +15957 0.867462158203125 +15958 0.870361328125 +15959 0.86480712890625 +15960 0.831817626953125 +15961 0.677581787109375 +15962 0.495880126953125 +15963 0.30767822265625 +15964 0.116180419921875 +15965 -0.110748291015625 +15966 -0.381805419921875 +15967 -0.6572265625 +15968 -0.857421875 +15969 -0.870391845703125 +15970 -0.870391845703125 +15971 -0.86444091796875 +15972 -0.85723876953125 +15973 -0.790008544921875 +15974 -0.62847900390625 +15975 -0.3956298828125 +15976 -0.126708984375 +15977 0.150115966796875 +15978 0.424041748046875 +15979 0.670623779296875 +15980 0.854522705078125 +15981 0.866485595703125 +15982 0.86920166015625 +15983 0.8653564453125 +15984 0.857147216796875 +15985 0.766845703125 +15986 0.628509521484375 +15987 0.462127685546875 +15988 0.297210693359375 +15989 0.14862060546875 +15990 -0.00537109375 +15991 -0.15753173828125 +15992 -0.31304931640625 +15993 -0.48876953125 +15994 -0.6416015625 +15995 -0.751373291015625 +15996 -0.84619140625 +15997 -0.861297607421875 +15998 -0.863250732421875 +15999 -0.856597900390625 +16000 -0.7498779296875 +16001 -0.624542236328125 +16002 -0.47808837890625 +16003 -0.253387451171875 +16004 0.003692626953125 +16005 0.2257080078125 +16006 0.427154541015625 +16007 0.643218994140625 +16008 0.855926513671875 +16009 0.870361328125 +16010 0.870361328125 +16011 0.862762451171875 +16012 0.79669189453125 +16013 0.595794677734375 +16014 0.362152099609375 +16015 0.1270751953125 +16016 -0.086944580078125 +16017 -0.2784423828125 +16018 -0.484832763671875 +16019 -0.729583740234375 +16020 -0.86688232421875 +16021 -0.870391845703125 +16022 -0.86859130859375 +16023 -0.86279296875 +16024 -0.817962646484375 +16025 -0.6116943359375 +16026 -0.3128662109375 +16027 0.039398193359375 +16028 0.422821044921875 +16029 0.805145263671875 +16030 0.870361328125 +16031 0.870361328125 +16032 0.860015869140625 +16033 0.727935791015625 +16034 0.48114013671875 +16035 0.2059326171875 +16036 -0.06103515625 +16037 -0.29913330078125 +16038 -0.516204833984375 +16039 -0.7252197265625 +16040 -0.85980224609375 +16041 -0.870391845703125 +16042 -0.870391845703125 +16043 -0.858062744140625 +16044 -0.673004150390625 +16045 -0.42694091796875 +16046 -0.2100830078125 +16047 -0.0362548828125 +16048 0.10943603515625 +16049 0.23516845703125 +16050 0.373687744140625 +16051 0.517791748046875 +16052 0.602783203125 +16053 0.635711669921875 +16054 0.655181884765625 +16055 0.65948486328125 +16056 0.651275634765625 +16057 0.61846923828125 +16058 0.53753662109375 +16059 0.404144287109375 +16060 0.22186279296875 +16061 0.003997802734375 +16062 -0.22100830078125 +16063 -0.42449951171875 +16064 -0.579833984375 +16065 -0.641876220703125 +16066 -0.6177978515625 +16067 -0.575531005859375 +16068 -0.526336669921875 +16069 -0.42645263671875 +16070 -0.2581787109375 +16071 -0.068695068359375 +16072 0.09222412109375 +16073 0.232147216796875 +16074 0.3509521484375 +16075 0.410064697265625 +16076 0.372955322265625 +16077 0.2554931640625 +16078 0.10711669921875 +16079 -0.052886962890625 +16080 -0.186279296875 +16081 -0.23291015625 +16082 -0.209442138671875 +16083 -0.174163818359375 +16084 -0.126739501953125 +16085 -0.048126220703125 +16086 0.0426025390625 +16087 0.10748291015625 +16088 0.1409912109375 +16089 0.19708251953125 +16090 0.273651123046875 +16091 0.31768798828125 +16092 0.341094970703125 +16093 0.368011474609375 +16094 0.37249755859375 +16095 0.30072021484375 +16096 0.1517333984375 +16097 -0.01470947265625 +16098 -0.1883544921875 +16099 -0.372711181640625 +16100 -0.51397705078125 +16101 -0.57177734375 +16102 -0.53948974609375 +16103 -0.43511962890625 +16104 -0.2962646484375 +16105 -0.161102294921875 +16106 -0.0435791015625 +16107 0.060394287109375 +16108 0.13665771484375 +16109 0.170135498046875 +16110 0.16552734375 +16111 0.15728759765625 +16112 0.150787353515625 +16113 0.12200927734375 +16114 0.080108642578125 +16115 0.05126953125 +16116 0.062896728515625 +16117 0.09271240234375 +16118 0.092987060546875 +16119 0.07855224609375 +16120 0.06427001953125 +16121 0.0347900390625 +16122 -0.01171875 +16123 -0.056060791015625 +16124 -0.055511474609375 +16125 -0.010467529296875 +16126 0.02508544921875 +16127 0.025665283203125 +16128 0.017333984375 +16129 0.00189208984375 +16130 -0.03173828125 +16131 -0.071502685546875 +16132 -0.13543701171875 +16133 -0.219970703125 +16134 -0.300506591796875 +16135 -0.376312255859375 +16136 -0.416107177734375 +16137 -0.371124267578125 +16138 -0.242279052734375 +16139 -0.069732666015625 +16140 0.125640869140625 +16141 0.31268310546875 +16142 0.45501708984375 +16143 0.554779052734375 +16144 0.61065673828125 +16145 0.610931396484375 +16146 0.531463623046875 +16147 0.3883056640625 +16148 0.23468017578125 +16149 0.095245361328125 +16150 -0.00396728515625 +16151 -0.04852294921875 +16152 -0.055145263671875 +16153 -0.0758056640625 +16154 -0.138702392578125 +16155 -0.209197998046875 +16156 -0.289031982421875 +16157 -0.37884521484375 +16158 -0.456329345703125 +16159 -0.51641845703125 +16160 -0.519287109375 +16161 -0.458251953125 +16162 -0.384796142578125 +16163 -0.323699951171875 +16164 -0.269287109375 +16165 -0.1951904296875 +16166 -0.100006103515625 +16167 -0.01055908203125 +16168 0.1033935546875 +16169 0.24908447265625 +16170 0.373199462890625 +16171 0.45806884765625 +16172 0.511474609375 +16173 0.565399169921875 +16174 0.61138916015625 +16175 0.5897216796875 +16176 0.4906005859375 +16177 0.33148193359375 +16178 0.147796630859375 +16179 -0.01873779296875 +16180 -0.140289306640625 +16181 -0.191986083984375 +16182 -0.184295654296875 +16183 -0.161834716796875 +16184 -0.166595458984375 +16185 -0.19390869140625 +16186 -0.22442626953125 +16187 -0.279754638671875 +16188 -0.3389892578125 +16189 -0.3543701171875 +16190 -0.348175048828125 +16191 -0.32598876953125 +16192 -0.2581787109375 +16193 -0.139801025390625 +16194 0.014617919921875 +16195 0.144378662109375 +16196 0.221038818359375 +16197 0.27069091796875 +16198 0.294036865234375 +16199 0.311767578125 +16200 0.339141845703125 +16201 0.360260009765625 +16202 0.360504150390625 +16203 0.308380126953125 +16204 0.18170166015625 +16205 0.0047607421875 +16206 -0.17559814453125 +16207 -0.3143310546875 +16208 -0.36785888671875 +16209 -0.36248779296875 +16210 -0.343536376953125 +16211 -0.3018798828125 +16212 -0.231414794921875 +16213 -0.117645263671875 +16214 0.007049560546875 +16215 0.087982177734375 +16216 0.13946533203125 +16217 0.17425537109375 +16218 0.188201904296875 +16219 0.171234130859375 +16220 0.118438720703125 +16221 0.05706787109375 +16222 -0.010711669921875 +16223 -0.0914306640625 +16224 -0.162322998046875 +16225 -0.194549560546875 +16226 -0.1492919921875 +16227 -0.02166748046875 +16228 0.124053955078125 +16229 0.211151123046875 +16230 0.240447998046875 +16231 0.242218017578125 +16232 0.2257080078125 +16233 0.194366455078125 +16234 0.115509033203125 +16235 0.0128173828125 +16236 -0.053802490234375 +16237 -0.110626220703125 +16238 -0.199493408203125 +16239 -0.29437255859375 +16240 -0.33221435546875 +16241 -0.27972412109375 +16242 -0.185333251953125 +16243 -0.128204345703125 +16244 -0.115692138671875 +16245 -0.116455078125 +16246 -0.105926513671875 +16247 -0.053955078125 +16248 0.048797607421875 +16249 0.157318115234375 +16250 0.212005615234375 +16251 0.218475341796875 +16252 0.23724365234375 +16253 0.30535888671875 +16254 0.38128662109375 +16255 0.404449462890625 +16256 0.3944091796875 +16257 0.3885498046875 +16258 0.362640380859375 +16259 0.27362060546875 +16260 0.11712646484375 +16261 -0.054901123046875 +16262 -0.19085693359375 +16263 -0.28570556640625 +16264 -0.339263916015625 +16265 -0.3775634765625 +16266 -0.445709228515625 +16267 -0.535064697265625 +16268 -0.629058837890625 +16269 -0.697601318359375 +16270 -0.70391845703125 +16271 -0.6424560546875 +16272 -0.491241455078125 +16273 -0.265716552734375 +16274 -0.023712158203125 +16275 0.201751708984375 +16276 0.375823974609375 +16277 0.485076904296875 +16278 0.56884765625 +16279 0.634765625 +16280 0.63763427734375 +16281 0.5660400390625 +16282 0.4720458984375 +16283 0.40692138671875 +16284 0.3778076171875 +16285 0.376953125 +16286 0.371978759765625 +16287 0.313140869140625 +16288 0.184417724609375 +16289 0.011199951171875 +16290 -0.171051025390625 +16291 -0.33740234375 +16292 -0.47198486328125 +16293 -0.560394287109375 +16294 -0.58056640625 +16295 -0.54754638671875 +16296 -0.508575439453125 +16297 -0.459503173828125 +16298 -0.394378662109375 +16299 -0.35260009765625 +16300 -0.31170654296875 +16301 -0.197418212890625 +16302 -0.007965087890625 +16303 0.207489013671875 +16304 0.409210205078125 +16305 0.57208251953125 +16306 0.66595458984375 +16307 0.65875244140625 +16308 0.56744384765625 +16309 0.431396484375 +16310 0.29443359375 +16311 0.182464599609375 +16312 0.06365966796875 +16313 -0.075958251953125 +16314 -0.189422607421875 +16315 -0.271942138671875 +16316 -0.342529296875 +16317 -0.364166259765625 +16318 -0.327239990234375 +16319 -0.2769775390625 +16320 -0.253692626953125 +16321 -0.24365234375 +16322 -0.1983642578125 +16323 -0.116241455078125 +16324 -0.036834716796875 +16325 0.034881591796875 +16326 0.09124755859375 +16327 0.10888671875 +16328 0.125518798828125 +16329 0.15771484375 +16330 0.17828369140625 +16331 0.17108154296875 +16332 0.129974365234375 +16333 0.082427978515625 +16334 0.027679443359375 +16335 -0.065643310546875 +16336 -0.15936279296875 +16337 -0.21307373046875 +16338 -0.234649658203125 +16339 -0.2001953125 +16340 -0.119171142578125 +16341 -0.024749755859375 +16342 0.085784912109375 +16343 0.178131103515625 +16344 0.215576171875 +16345 0.211456298828125 +16346 0.17523193359375 +16347 0.128753662109375 +16348 0.1019287109375 +16349 0.0743408203125 +16350 0.04327392578125 +16351 0.038177490234375 +16352 0.076263427734375 +16353 0.14105224609375 +16354 0.186431884765625 +16355 0.188812255859375 +16356 0.1390380859375 +16357 0.041778564453125 +16358 -0.079437255859375 +16359 -0.219390869140625 +16360 -0.367828369140625 +16361 -0.494873046875 +16362 -0.556243896484375 +16363 -0.508697509765625 +16364 -0.3756103515625 +16365 -0.218902587890625 +16366 -0.063751220703125 +16367 0.091552734375 +16368 0.23602294921875 +16369 0.342987060546875 +16370 0.39520263671875 +16371 0.389373779296875 +16372 0.324249267578125 +16373 0.224090576171875 +16374 0.124267578125 +16375 0.037078857421875 +16376 -0.010101318359375 +16377 -0.019439697265625 +16378 -0.022796630859375 +16379 -0.001556396484375 +16380 0.056304931640625 +16381 0.106719970703125 +16382 0.096893310546875 +16383 0.042694091796875 +16384 -0.018035888671875 +16385 -0.07586669921875 +16386 -0.11944580078125 +16387 -0.15972900390625 +16388 -0.202606201171875 +16389 -0.24859619140625 +16390 -0.30517578125 +16391 -0.36212158203125 +16392 -0.39141845703125 +16393 -0.35528564453125 +16394 -0.249969482421875 +16395 -0.092864990234375 +16396 0.08905029296875 +16397 0.2352294921875 +16398 0.318817138671875 +16399 0.358642578125 +16400 0.347747802734375 +16401 0.28564453125 +16402 0.223175048828125 +16403 0.196746826171875 +16404 0.179840087890625 +16405 0.155548095703125 +16406 0.151214599609375 +16407 0.156951904296875 +16408 0.13177490234375 +16409 0.100799560546875 +16410 0.087127685546875 +16411 0.05487060546875 +16412 -0.009002685546875 +16413 -0.10400390625 +16414 -0.229400634765625 +16415 -0.35552978515625 +16416 -0.441925048828125 +16417 -0.473846435546875 +16418 -0.464813232421875 +16419 -0.419097900390625 +16420 -0.334320068359375 +16421 -0.227935791015625 +16422 -0.12347412109375 +16423 -0.02764892578125 +16424 0.077667236328125 +16425 0.2132568359375 +16426 0.38885498046875 +16427 0.582794189453125 +16428 0.734039306640625 +16429 0.800140380859375 +16430 0.7783203125 +16431 0.6651611328125 +16432 0.45965576171875 +16433 0.199188232421875 +16434 -0.050689697265625 +16435 -0.23297119140625 +16436 -0.33013916015625 +16437 -0.368408203125 +16438 -0.378936767578125 +16439 -0.376983642578125 +16440 -0.37969970703125 +16441 -0.391510009765625 +16442 -0.385345458984375 +16443 -0.3419189453125 +16444 -0.28289794921875 +16445 -0.251617431640625 +16446 -0.266143798828125 +16447 -0.273345947265625 +16448 -0.216796875 +16449 -0.128265380859375 +16450 -0.068145751953125 +16451 -0.0430908203125 +16452 -0.024444580078125 +16453 0.020721435546875 +16454 0.124481201171875 +16455 0.25787353515625 +16456 0.379119873046875 +16457 0.47991943359375 +16458 0.5281982421875 +16459 0.511138916015625 +16460 0.456207275390625 +16461 0.407470703125 +16462 0.383758544921875 +16463 0.35687255859375 +16464 0.31182861328125 +16465 0.250885009765625 +16466 0.1654052734375 +16467 0.035247802734375 +16468 -0.142059326171875 +16469 -0.33563232421875 +16470 -0.5345458984375 +16471 -0.72186279296875 +16472 -0.836669921875 +16473 -0.8326416015625 +16474 -0.7296142578125 +16475 -0.582550048828125 +16476 -0.440093994140625 +16477 -0.324310302734375 +16478 -0.20147705078125 +16479 -0.044647216796875 +16480 0.103973388671875 +16481 0.202392578125 +16482 0.264495849609375 +16483 0.338897705078125 +16484 0.443817138671875 +16485 0.545074462890625 +16486 0.6173095703125 +16487 0.6524658203125 +16488 0.66339111328125 +16489 0.6561279296875 +16490 0.606781005859375 +16491 0.501190185546875 +16492 0.352783203125 +16493 0.176544189453125 +16494 -0.034820556640625 +16495 -0.258209228515625 +16496 -0.44244384765625 +16497 -0.5753173828125 +16498 -0.65203857421875 +16499 -0.641632080078125 +16500 -0.562164306640625 +16501 -0.458038330078125 +16502 -0.350555419921875 +16503 -0.260528564453125 +16504 -0.192108154296875 +16505 -0.141937255859375 +16506 -0.1021728515625 +16507 -0.062896728515625 +16508 -0.011932373046875 +16509 0.062835693359375 +16510 0.148712158203125 +16511 0.241729736328125 +16512 0.34912109375 +16513 0.457305908203125 +16514 0.54388427734375 +16515 0.5728759765625 +16516 0.506591796875 +16517 0.351226806640625 +16518 0.146514892578125 +16519 -0.05523681640625 +16520 -0.21624755859375 +16521 -0.334930419921875 +16522 -0.402984619140625 +16523 -0.4412841796875 +16524 -0.49578857421875 +16525 -0.5601806640625 +16526 -0.600738525390625 +16527 -0.584228515625 +16528 -0.47930908203125 +16529 -0.27935791015625 +16530 -0.0089111328125 +16531 0.268798828125 +16532 0.482818603515625 +16533 0.60369873046875 +16534 0.650421142578125 +16535 0.66400146484375 +16536 0.6414794921875 +16537 0.572540283203125 +16538 0.498138427734375 +16539 0.439453125 +16540 0.375518798828125 +16541 0.274505615234375 +16542 0.1087646484375 +16543 -0.099395751953125 +16544 -0.3182373046875 +16545 -0.5489501953125 +16546 -0.7738037109375 +16547 -0.86383056640625 +16548 -0.870391845703125 +16549 -0.86895751953125 +16550 -0.861053466796875 +16551 -0.765869140625 +16552 -0.5301513671875 +16553 -0.214691162109375 +16554 0.137359619140625 +16555 0.474822998046875 +16556 0.76239013671875 +16557 0.867462158203125 +16558 0.870361328125 +16559 0.86480712890625 +16560 0.831817626953125 +16561 0.677581787109375 +16562 0.495880126953125 +16563 0.30767822265625 +16564 0.116180419921875 +16565 -0.110748291015625 +16566 -0.381805419921875 +16567 -0.6572265625 +16568 -0.857421875 +16569 -0.870391845703125 +16570 -0.870391845703125 +16571 -0.86444091796875 +16572 -0.85723876953125 +16573 -0.790008544921875 +16574 -0.62847900390625 +16575 -0.3956298828125 +16576 -0.126708984375 +16577 0.150115966796875 +16578 0.424041748046875 +16579 0.670623779296875 +16580 0.854522705078125 +16581 0.866485595703125 +16582 0.86920166015625 +16583 0.8653564453125 +16584 0.857147216796875 +16585 0.766845703125 +16586 0.628509521484375 +16587 0.462127685546875 +16588 0.297210693359375 +16589 0.14862060546875 +16590 -0.00537109375 +16591 -0.15753173828125 +16592 -0.31304931640625 +16593 -0.48876953125 +16594 -0.6416015625 +16595 -0.751373291015625 +16596 -0.84619140625 +16597 -0.861297607421875 +16598 -0.863250732421875 +16599 -0.856597900390625 +16600 -0.7498779296875 +16601 -0.624542236328125 +16602 -0.47808837890625 +16603 -0.253387451171875 +16604 0.003692626953125 +16605 0.2257080078125 +16606 0.427154541015625 +16607 0.643218994140625 +16608 0.855926513671875 +16609 0.870361328125 +16610 0.870361328125 +16611 0.862762451171875 +16612 0.79669189453125 +16613 0.595794677734375 +16614 0.362152099609375 +16615 0.1270751953125 +16616 -0.086944580078125 +16617 -0.2784423828125 +16618 -0.484832763671875 +16619 -0.729583740234375 +16620 -0.86688232421875 +16621 -0.870391845703125 +16622 -0.86859130859375 +16623 -0.86279296875 +16624 -0.817962646484375 +16625 -0.6116943359375 +16626 -0.3128662109375 +16627 0.039398193359375 +16628 0.422821044921875 +16629 0.805145263671875 +16630 0.870361328125 +16631 0.870361328125 +16632 0.860015869140625 +16633 0.727935791015625 +16634 0.48114013671875 +16635 0.2059326171875 +16636 -0.06103515625 +16637 -0.29913330078125 +16638 -0.516204833984375 +16639 -0.7252197265625 +16640 -0.85980224609375 +16641 -0.870391845703125 +16642 -0.870391845703125 +16643 -0.858062744140625 +16644 -0.673004150390625 +16645 -0.42694091796875 +16646 -0.2100830078125 +16647 -0.0362548828125 +16648 0.10943603515625 +16649 0.23516845703125 +16650 0.373687744140625 +16651 0.517791748046875 +16652 0.602783203125 +16653 0.635711669921875 +16654 0.655181884765625 +16655 0.65948486328125 +16656 0.651275634765625 +16657 0.61846923828125 +16658 0.53753662109375 +16659 0.404144287109375 +16660 0.22186279296875 +16661 0.003997802734375 +16662 -0.22100830078125 +16663 -0.42449951171875 +16664 -0.579833984375 +16665 -0.641876220703125 +16666 -0.6177978515625 +16667 -0.575531005859375 +16668 -0.526336669921875 +16669 -0.42645263671875 +16670 -0.2581787109375 +16671 -0.068695068359375 +16672 0.09222412109375 +16673 0.232147216796875 +16674 0.3509521484375 +16675 0.410064697265625 +16676 0.372955322265625 +16677 0.2554931640625 +16678 0.10711669921875 +16679 -0.052886962890625 +16680 -0.186279296875 +16681 -0.23291015625 +16682 -0.209442138671875 +16683 -0.174163818359375 +16684 -0.126739501953125 +16685 -0.048126220703125 +16686 0.0426025390625 +16687 0.10748291015625 +16688 0.1409912109375 +16689 0.19708251953125 +16690 0.273651123046875 +16691 0.31768798828125 +16692 0.341094970703125 +16693 0.368011474609375 +16694 0.37249755859375 +16695 0.30072021484375 +16696 0.1517333984375 +16697 -0.01470947265625 +16698 -0.1883544921875 +16699 -0.372711181640625 +16700 -0.51397705078125 +16701 -0.57177734375 +16702 -0.53948974609375 +16703 -0.43511962890625 +16704 -0.2962646484375 +16705 -0.161102294921875 +16706 -0.0435791015625 +16707 0.060394287109375 +16708 0.13665771484375 +16709 0.170135498046875 +16710 0.16552734375 +16711 0.15728759765625 +16712 0.150787353515625 +16713 0.12200927734375 +16714 0.080108642578125 +16715 0.05126953125 +16716 0.062896728515625 +16717 0.09271240234375 +16718 0.092987060546875 +16719 0.07855224609375 +16720 0.06427001953125 +16721 0.0347900390625 +16722 -0.01171875 +16723 -0.056060791015625 +16724 -0.055511474609375 +16725 -0.010467529296875 +16726 0.02508544921875 +16727 0.025665283203125 +16728 0.017333984375 +16729 0.00189208984375 +16730 -0.03173828125 +16731 -0.071502685546875 +16732 -0.13543701171875 +16733 -0.219970703125 +16734 -0.300506591796875 +16735 -0.376312255859375 +16736 -0.416107177734375 +16737 -0.371124267578125 +16738 -0.242279052734375 +16739 -0.069732666015625 +16740 0.125640869140625 +16741 0.31268310546875 +16742 0.45501708984375 +16743 0.554779052734375 +16744 0.61065673828125 +16745 0.610931396484375 +16746 0.531463623046875 +16747 0.3883056640625 +16748 0.23468017578125 +16749 0.095245361328125 +16750 -0.00396728515625 +16751 -0.04852294921875 +16752 -0.055145263671875 +16753 -0.0758056640625 +16754 -0.138702392578125 +16755 -0.209197998046875 +16756 -0.289031982421875 +16757 -0.37884521484375 +16758 -0.456329345703125 +16759 -0.51641845703125 +16760 -0.519287109375 +16761 -0.458251953125 +16762 -0.384796142578125 +16763 -0.323699951171875 +16764 -0.269287109375 +16765 -0.1951904296875 +16766 -0.100006103515625 +16767 -0.01055908203125 +16768 0.1033935546875 +16769 0.24908447265625 +16770 0.373199462890625 +16771 0.45806884765625 +16772 0.511474609375 +16773 0.565399169921875 +16774 0.61138916015625 +16775 0.5897216796875 +16776 0.4906005859375 +16777 0.33148193359375 +16778 0.147796630859375 +16779 -0.01873779296875 +16780 -0.140289306640625 +16781 -0.191986083984375 +16782 -0.184295654296875 +16783 -0.161834716796875 +16784 -0.166595458984375 +16785 -0.19390869140625 +16786 -0.22442626953125 +16787 -0.279754638671875 +16788 -0.3389892578125 +16789 -0.3543701171875 +16790 -0.348175048828125 +16791 -0.32598876953125 +16792 -0.2581787109375 +16793 -0.139801025390625 +16794 0.014617919921875 +16795 0.144378662109375 +16796 0.221038818359375 +16797 0.27069091796875 +16798 0.294036865234375 +16799 0.311767578125 +16800 0.339141845703125 +16801 0.360260009765625 +16802 0.360504150390625 +16803 0.308380126953125 +16804 0.18170166015625 +16805 0.0047607421875 +16806 -0.17559814453125 +16807 -0.3143310546875 +16808 -0.36785888671875 +16809 -0.36248779296875 +16810 -0.343536376953125 +16811 -0.3018798828125 +16812 -0.231414794921875 +16813 -0.117645263671875 +16814 0.007049560546875 +16815 0.087982177734375 +16816 0.13946533203125 +16817 0.17425537109375 +16818 0.188201904296875 +16819 0.171234130859375 +16820 0.118438720703125 +16821 0.05706787109375 +16822 -0.010711669921875 +16823 -0.0914306640625 +16824 -0.162322998046875 +16825 -0.194549560546875 +16826 -0.1492919921875 +16827 -0.02166748046875 +16828 0.124053955078125 +16829 0.211151123046875 +16830 0.240447998046875 +16831 0.242218017578125 +16832 0.2257080078125 +16833 0.194366455078125 +16834 0.115509033203125 +16835 0.0128173828125 +16836 -0.053802490234375 +16837 -0.110626220703125 +16838 -0.199493408203125 +16839 -0.29437255859375 +16840 -0.33221435546875 +16841 -0.27972412109375 +16842 -0.185333251953125 +16843 -0.128204345703125 +16844 -0.115692138671875 +16845 -0.116455078125 +16846 -0.105926513671875 +16847 -0.053955078125 +16848 0.048797607421875 +16849 0.157318115234375 +16850 0.212005615234375 +16851 0.218475341796875 +16852 0.23724365234375 +16853 0.30535888671875 +16854 0.38128662109375 +16855 0.404449462890625 +16856 0.3944091796875 +16857 0.3885498046875 +16858 0.362640380859375 +16859 0.27362060546875 +16860 0.11712646484375 +16861 -0.054901123046875 +16862 -0.19085693359375 +16863 -0.28570556640625 +16864 -0.339263916015625 +16865 -0.3775634765625 +16866 -0.445709228515625 +16867 -0.535064697265625 +16868 -0.629058837890625 +16869 -0.697601318359375 +16870 -0.70391845703125 +16871 -0.6424560546875 +16872 -0.491241455078125 +16873 -0.265716552734375 +16874 -0.023712158203125 +16875 0.201751708984375 +16876 0.375823974609375 +16877 0.485076904296875 +16878 0.56884765625 +16879 0.634765625 +16880 0.63763427734375 +16881 0.5660400390625 +16882 0.4720458984375 +16883 0.40692138671875 +16884 0.3778076171875 +16885 0.376953125 +16886 0.371978759765625 +16887 0.313140869140625 +16888 0.184417724609375 +16889 0.011199951171875 +16890 -0.171051025390625 +16891 -0.33740234375 +16892 -0.47198486328125 +16893 -0.560394287109375 +16894 -0.58056640625 +16895 -0.54754638671875 +16896 -0.508575439453125 +16897 -0.459503173828125 +16898 -0.394378662109375 +16899 -0.35260009765625 +16900 -0.31170654296875 +16901 -0.197418212890625 +16902 -0.007965087890625 +16903 0.207489013671875 +16904 0.409210205078125 +16905 0.57208251953125 +16906 0.66595458984375 +16907 0.65875244140625 +16908 0.56744384765625 +16909 0.431396484375 +16910 0.29443359375 +16911 0.182464599609375 +16912 0.06365966796875 +16913 -0.075958251953125 +16914 -0.189422607421875 +16915 -0.271942138671875 +16916 -0.342529296875 +16917 -0.364166259765625 +16918 -0.327239990234375 +16919 -0.2769775390625 +16920 -0.253692626953125 +16921 -0.24365234375 +16922 -0.1983642578125 +16923 -0.116241455078125 +16924 -0.036834716796875 +16925 0.034881591796875 +16926 0.09124755859375 +16927 0.10888671875 +16928 0.125518798828125 +16929 0.15771484375 +16930 0.17828369140625 +16931 0.17108154296875 +16932 0.129974365234375 +16933 0.082427978515625 +16934 0.027679443359375 +16935 -0.065643310546875 +16936 -0.15936279296875 +16937 -0.21307373046875 +16938 -0.234649658203125 +16939 -0.2001953125 +16940 -0.119171142578125 +16941 -0.024749755859375 +16942 0.085784912109375 +16943 0.178131103515625 +16944 0.215576171875 +16945 0.211456298828125 +16946 0.17523193359375 +16947 0.128753662109375 +16948 0.1019287109375 +16949 0.0743408203125 +16950 0.04327392578125 +16951 0.038177490234375 +16952 0.076263427734375 +16953 0.14105224609375 +16954 0.186431884765625 +16955 0.188812255859375 +16956 0.1390380859375 +16957 0.041778564453125 +16958 -0.079437255859375 +16959 -0.219390869140625 +16960 -0.367828369140625 +16961 -0.494873046875 +16962 -0.556243896484375 +16963 -0.508697509765625 +16964 -0.3756103515625 +16965 -0.218902587890625 +16966 -0.063751220703125 +16967 0.091552734375 +16968 0.23602294921875 +16969 0.342987060546875 +16970 0.39520263671875 +16971 0.389373779296875 +16972 0.324249267578125 +16973 0.224090576171875 +16974 0.124267578125 +16975 0.037078857421875 +16976 -0.010101318359375 +16977 -0.019439697265625 +16978 -0.022796630859375 +16979 -0.001556396484375 +16980 0.056304931640625 +16981 0.106719970703125 +16982 0.096893310546875 +16983 0.042694091796875 +16984 -0.018035888671875 +16985 -0.07586669921875 +16986 -0.11944580078125 +16987 -0.15972900390625 +16988 -0.202606201171875 +16989 -0.24859619140625 +16990 -0.30517578125 +16991 -0.36212158203125 +16992 -0.39141845703125 +16993 -0.35528564453125 +16994 -0.249969482421875 +16995 -0.092864990234375 +16996 0.08905029296875 +16997 0.2352294921875 +16998 0.318817138671875 +16999 0.358642578125 +17000 0.347747802734375 +17001 0.28564453125 +17002 0.223175048828125 +17003 0.196746826171875 +17004 0.179840087890625 +17005 0.155548095703125 +17006 0.151214599609375 +17007 0.156951904296875 +17008 0.13177490234375 +17009 0.100799560546875 +17010 0.087127685546875 +17011 0.05487060546875 +17012 -0.009002685546875 +17013 -0.10400390625 +17014 -0.229400634765625 +17015 -0.35552978515625 +17016 -0.441925048828125 +17017 -0.473846435546875 +17018 -0.464813232421875 +17019 -0.419097900390625 +17020 -0.334320068359375 +17021 -0.227935791015625 +17022 -0.12347412109375 +17023 -0.02764892578125 +17024 0.077667236328125 +17025 0.2132568359375 +17026 0.38885498046875 +17027 0.582794189453125 +17028 0.734039306640625 +17029 0.800140380859375 +17030 0.7783203125 +17031 0.6651611328125 +17032 0.45965576171875 +17033 0.199188232421875 +17034 -0.050689697265625 +17035 -0.23297119140625 +17036 -0.33013916015625 +17037 -0.368408203125 +17038 -0.378936767578125 +17039 -0.376983642578125 +17040 -0.37969970703125 +17041 -0.391510009765625 +17042 -0.385345458984375 +17043 -0.3419189453125 +17044 -0.28289794921875 +17045 -0.251617431640625 +17046 -0.266143798828125 +17047 -0.273345947265625 +17048 -0.216796875 +17049 -0.128265380859375 +17050 -0.068145751953125 +17051 -0.0430908203125 +17052 -0.024444580078125 +17053 0.020721435546875 +17054 0.124481201171875 +17055 0.25787353515625 +17056 0.379119873046875 +17057 0.47991943359375 +17058 0.5281982421875 +17059 0.511138916015625 +17060 0.456207275390625 +17061 0.407470703125 +17062 0.383758544921875 +17063 0.35687255859375 +17064 0.31182861328125 +17065 0.250885009765625 +17066 0.1654052734375 +17067 0.035247802734375 +17068 -0.142059326171875 +17069 -0.33563232421875 +17070 -0.5345458984375 +17071 -0.72186279296875 +17072 -0.836669921875 +17073 -0.8326416015625 +17074 -0.7296142578125 +17075 -0.582550048828125 +17076 -0.440093994140625 +17077 -0.324310302734375 +17078 -0.20147705078125 +17079 -0.044647216796875 +17080 0.103973388671875 +17081 0.202392578125 +17082 0.264495849609375 +17083 0.338897705078125 +17084 0.443817138671875 +17085 0.545074462890625 +17086 0.6173095703125 +17087 0.6524658203125 +17088 0.66339111328125 +17089 0.6561279296875 +17090 0.606781005859375 +17091 0.501190185546875 +17092 0.352783203125 +17093 0.176544189453125 +17094 -0.034820556640625 +17095 -0.258209228515625 +17096 -0.44244384765625 +17097 -0.5753173828125 +17098 -0.65203857421875 +17099 -0.641632080078125 +17100 -0.562164306640625 +17101 -0.458038330078125 +17102 -0.350555419921875 +17103 -0.260528564453125 +17104 -0.192108154296875 +17105 -0.141937255859375 +17106 -0.1021728515625 +17107 -0.062896728515625 +17108 -0.011932373046875 +17109 0.062835693359375 +17110 0.148712158203125 +17111 0.241729736328125 +17112 0.34912109375 +17113 0.457305908203125 +17114 0.54388427734375 +17115 0.5728759765625 +17116 0.506591796875 +17117 0.351226806640625 +17118 0.146514892578125 +17119 -0.05523681640625 +17120 -0.21624755859375 +17121 -0.334930419921875 +17122 -0.402984619140625 +17123 -0.4412841796875 +17124 -0.49578857421875 +17125 -0.5601806640625 +17126 -0.600738525390625 +17127 -0.584228515625 +17128 -0.47930908203125 +17129 -0.27935791015625 +17130 -0.0089111328125 +17131 0.268798828125 +17132 0.482818603515625 +17133 0.60369873046875 +17134 0.650421142578125 +17135 0.66400146484375 +17136 0.6414794921875 +17137 0.572540283203125 +17138 0.498138427734375 +17139 0.439453125 +17140 0.375518798828125 +17141 0.274505615234375 +17142 0.1087646484375 +17143 -0.099395751953125 +17144 -0.3182373046875 +17145 -0.5489501953125 +17146 -0.7738037109375 +17147 -0.86383056640625 +17148 -0.870391845703125 +17149 -0.86895751953125 +17150 -0.861053466796875 +17151 -0.765869140625 +17152 -0.5301513671875 +17153 -0.214691162109375 +17154 0.137359619140625 +17155 0.474822998046875 +17156 0.76239013671875 +17157 0.867462158203125 +17158 0.870361328125 +17159 0.86480712890625 +17160 0.831817626953125 +17161 0.677581787109375 +17162 0.495880126953125 +17163 0.30767822265625 +17164 0.116180419921875 +17165 -0.110748291015625 +17166 -0.381805419921875 +17167 -0.6572265625 +17168 -0.857421875 +17169 -0.870391845703125 +17170 -0.870391845703125 +17171 -0.86444091796875 +17172 -0.85723876953125 +17173 -0.790008544921875 +17174 -0.62847900390625 +17175 -0.3956298828125 +17176 -0.126708984375 +17177 0.150115966796875 +17178 0.424041748046875 +17179 0.670623779296875 +17180 0.854522705078125 +17181 0.866485595703125 +17182 0.86920166015625 +17183 0.8653564453125 +17184 0.857147216796875 +17185 0.766845703125 +17186 0.628509521484375 +17187 0.462127685546875 +17188 0.297210693359375 +17189 0.14862060546875 +17190 -0.00537109375 +17191 -0.15753173828125 +17192 -0.31304931640625 +17193 -0.48876953125 +17194 -0.6416015625 +17195 -0.751373291015625 +17196 -0.84619140625 +17197 -0.861297607421875 +17198 -0.863250732421875 +17199 -0.856597900390625 +17200 -0.7498779296875 +17201 -0.624542236328125 +17202 -0.47808837890625 +17203 -0.253387451171875 +17204 0.003692626953125 +17205 0.2257080078125 +17206 0.427154541015625 +17207 0.643218994140625 +17208 0.855926513671875 +17209 0.870361328125 +17210 0.870361328125 +17211 0.862762451171875 +17212 0.79669189453125 +17213 0.595794677734375 +17214 0.362152099609375 +17215 0.1270751953125 +17216 -0.086944580078125 +17217 -0.2784423828125 +17218 -0.484832763671875 +17219 -0.729583740234375 +17220 -0.86688232421875 +17221 -0.870391845703125 +17222 -0.86859130859375 +17223 -0.86279296875 +17224 -0.817962646484375 +17225 -0.6116943359375 +17226 -0.3128662109375 +17227 0.039398193359375 +17228 0.422821044921875 +17229 0.805145263671875 +17230 0.870361328125 +17231 0.870361328125 +17232 0.860015869140625 +17233 0.727935791015625 +17234 0.48114013671875 +17235 0.2059326171875 +17236 -0.06103515625 +17237 -0.29913330078125 +17238 -0.516204833984375 +17239 -0.7252197265625 +17240 -0.85980224609375 +17241 -0.870391845703125 +17242 -0.870391845703125 +17243 -0.858062744140625 +17244 -0.673004150390625 +17245 -0.42694091796875 +17246 -0.2100830078125 +17247 -0.0362548828125 +17248 0.10943603515625 +17249 0.23516845703125 +17250 0.373687744140625 +17251 0.517791748046875 +17252 0.602783203125 +17253 0.635711669921875 +17254 0.655181884765625 +17255 0.65948486328125 +17256 0.651275634765625 +17257 0.61846923828125 +17258 0.53753662109375 +17259 0.404144287109375 +17260 0.22186279296875 +17261 0.003997802734375 +17262 -0.22100830078125 +17263 -0.42449951171875 +17264 -0.579833984375 +17265 -0.641876220703125 +17266 -0.6177978515625 +17267 -0.575531005859375 +17268 -0.526336669921875 +17269 -0.42645263671875 +17270 -0.2581787109375 +17271 -0.068695068359375 +17272 0.09222412109375 +17273 0.232147216796875 +17274 0.3509521484375 +17275 0.410064697265625 +17276 0.372955322265625 +17277 0.2554931640625 +17278 0.10711669921875 +17279 -0.052886962890625 +17280 -0.186279296875 +17281 -0.23291015625 +17282 -0.209442138671875 +17283 -0.174163818359375 +17284 -0.126739501953125 +17285 -0.048126220703125 +17286 0.0426025390625 +17287 0.10748291015625 +17288 0.1409912109375 +17289 0.19708251953125 +17290 0.273651123046875 +17291 0.31768798828125 +17292 0.341094970703125 +17293 0.368011474609375 +17294 0.37249755859375 +17295 0.30072021484375 +17296 0.1517333984375 +17297 -0.01470947265625 +17298 -0.1883544921875 +17299 -0.372711181640625 +17300 -0.51397705078125 +17301 -0.57177734375 +17302 -0.53948974609375 +17303 -0.43511962890625 +17304 -0.2962646484375 +17305 -0.161102294921875 +17306 -0.0435791015625 +17307 0.060394287109375 +17308 0.13665771484375 +17309 0.170135498046875 +17310 0.16552734375 +17311 0.15728759765625 +17312 0.150787353515625 +17313 0.12200927734375 +17314 0.080108642578125 +17315 0.05126953125 +17316 0.062896728515625 +17317 0.09271240234375 +17318 0.092987060546875 +17319 0.07855224609375 +17320 0.06427001953125 +17321 0.0347900390625 +17322 -0.01171875 +17323 -0.056060791015625 +17324 -0.055511474609375 +17325 -0.010467529296875 +17326 0.02508544921875 +17327 0.025665283203125 +17328 0.017333984375 +17329 0.00189208984375 +17330 -0.03173828125 +17331 -0.071502685546875 +17332 -0.13543701171875 +17333 -0.219970703125 +17334 -0.300506591796875 +17335 -0.376312255859375 +17336 -0.416107177734375 +17337 -0.371124267578125 +17338 -0.242279052734375 +17339 -0.069732666015625 +17340 0.125640869140625 +17341 0.31268310546875 +17342 0.45501708984375 +17343 0.554779052734375 +17344 0.61065673828125 +17345 0.610931396484375 +17346 0.531463623046875 +17347 0.3883056640625 +17348 0.23468017578125 +17349 0.095245361328125 +17350 -0.00396728515625 +17351 -0.04852294921875 +17352 -0.055145263671875 +17353 -0.0758056640625 +17354 -0.138702392578125 +17355 -0.209197998046875 +17356 -0.289031982421875 +17357 -0.37884521484375 +17358 -0.456329345703125 +17359 -0.51641845703125 +17360 -0.519287109375 +17361 -0.458251953125 +17362 -0.384796142578125 +17363 -0.323699951171875 +17364 -0.269287109375 +17365 -0.1951904296875 +17366 -0.100006103515625 +17367 -0.01055908203125 +17368 0.1033935546875 +17369 0.24908447265625 +17370 0.373199462890625 +17371 0.45806884765625 +17372 0.511474609375 +17373 0.565399169921875 +17374 0.61138916015625 +17375 0.5897216796875 +17376 0.4906005859375 +17377 0.33148193359375 +17378 0.147796630859375 +17379 -0.01873779296875 +17380 -0.140289306640625 +17381 -0.191986083984375 +17382 -0.184295654296875 +17383 -0.161834716796875 +17384 -0.166595458984375 +17385 -0.19390869140625 +17386 -0.22442626953125 +17387 -0.279754638671875 +17388 -0.3389892578125 +17389 -0.3543701171875 +17390 -0.348175048828125 +17391 -0.32598876953125 +17392 -0.2581787109375 +17393 -0.139801025390625 +17394 0.014617919921875 +17395 0.144378662109375 +17396 0.221038818359375 +17397 0.27069091796875 +17398 0.294036865234375 +17399 0.311767578125 +17400 0.339141845703125 +17401 0.360260009765625 +17402 0.360504150390625 +17403 0.308380126953125 +17404 0.18170166015625 +17405 0.0047607421875 +17406 -0.17559814453125 +17407 -0.3143310546875 +17408 -0.36785888671875 +17409 -0.36248779296875 +17410 -0.343536376953125 +17411 -0.3018798828125 +17412 -0.231414794921875 +17413 -0.117645263671875 +17414 0.007049560546875 +17415 0.087982177734375 +17416 0.13946533203125 +17417 0.17425537109375 +17418 0.188201904296875 +17419 0.171234130859375 +17420 0.118438720703125 +17421 0.05706787109375 +17422 -0.010711669921875 +17423 -0.0914306640625 +17424 -0.162322998046875 +17425 -0.194549560546875 +17426 -0.1492919921875 +17427 -0.02166748046875 +17428 0.124053955078125 +17429 0.211151123046875 +17430 0.240447998046875 +17431 0.242218017578125 +17432 0.2257080078125 +17433 0.194366455078125 +17434 0.115509033203125 +17435 0.0128173828125 +17436 -0.053802490234375 +17437 -0.110626220703125 +17438 -0.199493408203125 +17439 -0.29437255859375 +17440 -0.33221435546875 +17441 -0.27972412109375 +17442 -0.185333251953125 +17443 -0.128204345703125 +17444 -0.115692138671875 +17445 -0.116455078125 +17446 -0.105926513671875 +17447 -0.053955078125 +17448 0.048797607421875 +17449 0.157318115234375 +17450 0.212005615234375 +17451 0.218475341796875 +17452 0.23724365234375 +17453 0.30535888671875 +17454 0.38128662109375 +17455 0.404449462890625 +17456 0.3944091796875 +17457 0.3885498046875 +17458 0.362640380859375 +17459 0.27362060546875 +17460 0.11712646484375 +17461 -0.054901123046875 +17462 -0.19085693359375 +17463 -0.28570556640625 +17464 -0.339263916015625 +17465 -0.3775634765625 +17466 -0.445709228515625 +17467 -0.535064697265625 +17468 -0.629058837890625 +17469 -0.697601318359375 +17470 -0.70391845703125 +17471 -0.6424560546875 +17472 -0.491241455078125 +17473 -0.265716552734375 +17474 -0.023712158203125 +17475 0.201751708984375 +17476 0.375823974609375 +17477 0.485076904296875 +17478 0.56884765625 +17479 0.634765625 +17480 0.63763427734375 +17481 0.5660400390625 +17482 0.4720458984375 +17483 0.40692138671875 +17484 0.3778076171875 +17485 0.376953125 +17486 0.371978759765625 +17487 0.313140869140625 +17488 0.184417724609375 +17489 0.011199951171875 +17490 -0.171051025390625 +17491 -0.33740234375 +17492 -0.47198486328125 +17493 -0.560394287109375 +17494 -0.58056640625 +17495 -0.54754638671875 +17496 -0.508575439453125 +17497 -0.459503173828125 +17498 -0.394378662109375 +17499 -0.35260009765625 +17500 -0.31170654296875 +17501 -0.197418212890625 +17502 -0.007965087890625 +17503 0.207489013671875 +17504 0.409210205078125 +17505 0.57208251953125 +17506 0.66595458984375 +17507 0.65875244140625 +17508 0.56744384765625 +17509 0.431396484375 +17510 0.29443359375 +17511 0.182464599609375 +17512 0.06365966796875 +17513 -0.075958251953125 +17514 -0.189422607421875 +17515 -0.271942138671875 +17516 -0.342529296875 +17517 -0.364166259765625 +17518 -0.327239990234375 +17519 -0.2769775390625 +17520 -0.253692626953125 +17521 -0.24365234375 +17522 -0.1983642578125 +17523 -0.116241455078125 +17524 -0.036834716796875 +17525 0.034881591796875 +17526 0.09124755859375 +17527 0.10888671875 +17528 0.125518798828125 +17529 0.15771484375 +17530 0.17828369140625 +17531 0.17108154296875 +17532 0.129974365234375 +17533 0.082427978515625 +17534 0.027679443359375 +17535 -0.065643310546875 +17536 -0.15936279296875 +17537 -0.21307373046875 +17538 -0.234649658203125 +17539 -0.2001953125 +17540 -0.119171142578125 +17541 -0.024749755859375 +17542 0.085784912109375 +17543 0.178131103515625 +17544 0.215576171875 +17545 0.211456298828125 +17546 0.17523193359375 +17547 0.128753662109375 +17548 0.1019287109375 +17549 0.0743408203125 +17550 0.04327392578125 +17551 0.038177490234375 +17552 0.076263427734375 +17553 0.14105224609375 +17554 0.186431884765625 +17555 0.188812255859375 +17556 0.1390380859375 +17557 0.041778564453125 +17558 -0.079437255859375 +17559 -0.219390869140625 +17560 -0.367828369140625 +17561 -0.494873046875 +17562 -0.556243896484375 +17563 -0.508697509765625 +17564 -0.3756103515625 +17565 -0.218902587890625 +17566 -0.063751220703125 +17567 0.091552734375 +17568 0.23602294921875 +17569 0.342987060546875 +17570 0.39520263671875 +17571 0.389373779296875 +17572 0.324249267578125 +17573 0.224090576171875 +17574 0.124267578125 +17575 0.037078857421875 +17576 -0.010101318359375 +17577 -0.019439697265625 +17578 -0.022796630859375 +17579 -0.001556396484375 +17580 0.056304931640625 +17581 0.106719970703125 +17582 0.096893310546875 +17583 0.042694091796875 +17584 -0.018035888671875 +17585 -0.07586669921875 +17586 -0.11944580078125 +17587 -0.15972900390625 +17588 -0.202606201171875 +17589 -0.24859619140625 +17590 -0.30517578125 +17591 -0.36212158203125 +17592 -0.39141845703125 +17593 -0.35528564453125 +17594 -0.249969482421875 +17595 -0.092864990234375 +17596 0.08905029296875 +17597 0.2352294921875 +17598 0.318817138671875 +17599 0.358642578125 +17600 0.347747802734375 +17601 0.28564453125 +17602 0.223175048828125 +17603 0.196746826171875 +17604 0.179840087890625 +17605 0.155548095703125 +17606 0.151214599609375 +17607 0.156951904296875 +17608 0.13177490234375 +17609 0.100799560546875 +17610 0.087127685546875 +17611 0.05487060546875 +17612 -0.009002685546875 +17613 -0.10400390625 +17614 -0.229400634765625 +17615 -0.35552978515625 +17616 -0.441925048828125 +17617 -0.473846435546875 +17618 -0.464813232421875 +17619 -0.419097900390625 +17620 -0.334320068359375 +17621 -0.227935791015625 +17622 -0.12347412109375 +17623 -0.02764892578125 +17624 0.077667236328125 +17625 0.2132568359375 +17626 0.38885498046875 +17627 0.582794189453125 +17628 0.734039306640625 +17629 0.800140380859375 +17630 0.7783203125 +17631 0.6651611328125 +17632 0.45965576171875 +17633 0.199188232421875 +17634 -0.050689697265625 +17635 -0.23297119140625 +17636 -0.33013916015625 +17637 -0.368408203125 +17638 -0.378936767578125 +17639 -0.376983642578125 +17640 -0.37969970703125 +17641 -0.391510009765625 +17642 -0.385345458984375 +17643 -0.3419189453125 +17644 -0.28289794921875 +17645 -0.251617431640625 +17646 -0.266143798828125 +17647 -0.273345947265625 +17648 -0.216796875 +17649 -0.128265380859375 +17650 -0.068145751953125 +17651 -0.0430908203125 +17652 -0.024444580078125 +17653 0.020721435546875 +17654 0.124481201171875 +17655 0.25787353515625 +17656 0.379119873046875 +17657 0.47991943359375 +17658 0.5281982421875 +17659 0.511138916015625 +17660 0.456207275390625 +17661 0.407470703125 +17662 0.383758544921875 +17663 0.35687255859375 +17664 0.31182861328125 +17665 0.250885009765625 +17666 0.1654052734375 +17667 0.035247802734375 +17668 -0.142059326171875 +17669 -0.33563232421875 +17670 -0.5345458984375 +17671 -0.72186279296875 +17672 -0.836669921875 +17673 -0.8326416015625 +17674 -0.7296142578125 +17675 -0.582550048828125 +17676 -0.440093994140625 +17677 -0.324310302734375 +17678 -0.20147705078125 +17679 -0.044647216796875 +17680 0.103973388671875 +17681 0.202392578125 +17682 0.264495849609375 +17683 0.338897705078125 +17684 0.443817138671875 +17685 0.545074462890625 +17686 0.6173095703125 +17687 0.6524658203125 +17688 0.66339111328125 +17689 0.6561279296875 +17690 0.606781005859375 +17691 0.501190185546875 +17692 0.352783203125 +17693 0.176544189453125 +17694 -0.034820556640625 +17695 -0.258209228515625 +17696 -0.44244384765625 +17697 -0.5753173828125 +17698 -0.65203857421875 +17699 -0.641632080078125 +17700 -0.562164306640625 +17701 -0.458038330078125 +17702 -0.350555419921875 +17703 -0.260528564453125 +17704 -0.192108154296875 +17705 -0.141937255859375 +17706 -0.1021728515625 +17707 -0.062896728515625 +17708 -0.011932373046875 +17709 0.062835693359375 +17710 0.148712158203125 +17711 0.241729736328125 +17712 0.34912109375 +17713 0.457305908203125 +17714 0.54388427734375 +17715 0.5728759765625 +17716 0.506591796875 +17717 0.351226806640625 +17718 0.146514892578125 +17719 -0.05523681640625 +17720 -0.21624755859375 +17721 -0.334930419921875 +17722 -0.402984619140625 +17723 -0.4412841796875 +17724 -0.49578857421875 +17725 -0.5601806640625 +17726 -0.600738525390625 +17727 -0.584228515625 +17728 -0.47930908203125 +17729 -0.27935791015625 +17730 -0.0089111328125 +17731 0.268798828125 +17732 0.482818603515625 +17733 0.60369873046875 +17734 0.650421142578125 +17735 0.66400146484375 +17736 0.6414794921875 +17737 0.572540283203125 +17738 0.498138427734375 +17739 0.439453125 +17740 0.375518798828125 +17741 0.274505615234375 +17742 0.1087646484375 +17743 -0.099395751953125 +17744 -0.3182373046875 +17745 -0.5489501953125 +17746 -0.7738037109375 +17747 -0.86383056640625 +17748 -0.870391845703125 +17749 -0.86895751953125 +17750 -0.861053466796875 +17751 -0.765869140625 +17752 -0.5301513671875 +17753 -0.214691162109375 +17754 0.137359619140625 +17755 0.474822998046875 +17756 0.76239013671875 +17757 0.867462158203125 +17758 0.870361328125 +17759 0.86480712890625 +17760 0.831817626953125 +17761 0.677581787109375 +17762 0.495880126953125 +17763 0.30767822265625 +17764 0.116180419921875 +17765 -0.110748291015625 +17766 -0.381805419921875 +17767 -0.6572265625 +17768 -0.857421875 +17769 -0.870391845703125 +17770 -0.870391845703125 +17771 -0.86444091796875 +17772 -0.85723876953125 +17773 -0.790008544921875 +17774 -0.62847900390625 +17775 -0.3956298828125 +17776 -0.126708984375 +17777 0.150115966796875 +17778 0.424041748046875 +17779 0.670623779296875 +17780 0.854522705078125 +17781 0.866485595703125 +17782 0.86920166015625 +17783 0.8653564453125 +17784 0.857147216796875 +17785 0.766845703125 +17786 0.628509521484375 +17787 0.462127685546875 +17788 0.297210693359375 +17789 0.14862060546875 +17790 -0.00537109375 +17791 -0.15753173828125 +17792 -0.31304931640625 +17793 -0.48876953125 +17794 -0.6416015625 +17795 -0.751373291015625 +17796 -0.84619140625 +17797 -0.861297607421875 +17798 -0.863250732421875 +17799 -0.856597900390625 +17800 -0.7498779296875 +17801 -0.624542236328125 +17802 -0.47808837890625 +17803 -0.253387451171875 +17804 0.003692626953125 +17805 0.2257080078125 +17806 0.427154541015625 +17807 0.643218994140625 +17808 0.855926513671875 +17809 0.870361328125 +17810 0.870361328125 +17811 0.862762451171875 +17812 0.79669189453125 +17813 0.595794677734375 +17814 0.362152099609375 +17815 0.1270751953125 +17816 -0.086944580078125 +17817 -0.2784423828125 +17818 -0.484832763671875 +17819 -0.729583740234375 +17820 -0.86688232421875 +17821 -0.870391845703125 +17822 -0.86859130859375 +17823 -0.86279296875 +17824 -0.817962646484375 +17825 -0.6116943359375 +17826 -0.3128662109375 +17827 0.039398193359375 +17828 0.422821044921875 +17829 0.805145263671875 +17830 0.870361328125 +17831 0.870361328125 +17832 0.860015869140625 +17833 0.727935791015625 +17834 0.48114013671875 +17835 0.2059326171875 +17836 -0.06103515625 +17837 -0.29913330078125 +17838 -0.516204833984375 +17839 -0.7252197265625 +17840 -0.85980224609375 +17841 -0.870391845703125 +17842 -0.870391845703125 +17843 -0.858062744140625 +17844 -0.673004150390625 +17845 -0.42694091796875 +17846 -0.2100830078125 +17847 -0.0362548828125 +17848 0.10943603515625 +17849 0.23516845703125 +17850 0.373687744140625 +17851 0.517791748046875 +17852 0.602783203125 +17853 0.635711669921875 +17854 0.655181884765625 +17855 0.65948486328125 +17856 0.651275634765625 +17857 0.61846923828125 +17858 0.53753662109375 +17859 0.404144287109375 +17860 0.22186279296875 +17861 0.003997802734375 +17862 -0.22100830078125 +17863 -0.42449951171875 +17864 -0.579833984375 +17865 -0.641876220703125 +17866 -0.6177978515625 +17867 -0.575531005859375 +17868 -0.526336669921875 +17869 -0.42645263671875 +17870 -0.2581787109375 +17871 -0.068695068359375 +17872 0.09222412109375 +17873 0.232147216796875 +17874 0.3509521484375 +17875 0.410064697265625 +17876 0.372955322265625 +17877 0.2554931640625 +17878 0.10711669921875 +17879 -0.052886962890625 +17880 -0.186279296875 +17881 -0.23291015625 +17882 -0.209442138671875 +17883 -0.174163818359375 +17884 -0.126739501953125 +17885 -0.048126220703125 +17886 0.0426025390625 +17887 0.10748291015625 +17888 0.1409912109375 +17889 0.19708251953125 +17890 0.273651123046875 +17891 0.31768798828125 +17892 0.341094970703125 +17893 0.368011474609375 +17894 0.37249755859375 +17895 0.30072021484375 +17896 0.1517333984375 +17897 -0.01470947265625 +17898 -0.1883544921875 +17899 -0.372711181640625 +17900 -0.51397705078125 +17901 -0.57177734375 +17902 -0.53948974609375 +17903 -0.43511962890625 +17904 -0.2962646484375 +17905 -0.161102294921875 +17906 -0.0435791015625 +17907 0.060394287109375 +17908 0.13665771484375 +17909 0.170135498046875 +17910 0.16552734375 +17911 0.15728759765625 +17912 0.150787353515625 +17913 0.12200927734375 +17914 0.080108642578125 +17915 0.05126953125 +17916 0.062896728515625 +17917 0.09271240234375 +17918 0.092987060546875 +17919 0.07855224609375 +17920 0.06427001953125 +17921 0.0347900390625 +17922 -0.01171875 +17923 -0.056060791015625 +17924 -0.055511474609375 +17925 -0.010467529296875 +17926 0.02508544921875 +17927 0.025665283203125 +17928 0.017333984375 +17929 0.00189208984375 +17930 -0.03173828125 +17931 -0.071502685546875 +17932 -0.13543701171875 +17933 -0.219970703125 +17934 -0.300506591796875 +17935 -0.376312255859375 +17936 -0.416107177734375 +17937 -0.371124267578125 +17938 -0.242279052734375 +17939 -0.069732666015625 +17940 0.125640869140625 +17941 0.31268310546875 +17942 0.45501708984375 +17943 0.554779052734375 +17944 0.61065673828125 +17945 0.610931396484375 +17946 0.531463623046875 +17947 0.3883056640625 +17948 0.23468017578125 +17949 0.095245361328125 +17950 -0.00396728515625 +17951 -0.04852294921875 +17952 -0.055145263671875 +17953 -0.0758056640625 +17954 -0.138702392578125 +17955 -0.209197998046875 +17956 -0.289031982421875 +17957 -0.37884521484375 +17958 -0.456329345703125 +17959 -0.51641845703125 +17960 -0.519287109375 +17961 -0.458251953125 +17962 -0.384796142578125 +17963 -0.323699951171875 +17964 -0.269287109375 +17965 -0.1951904296875 +17966 -0.100006103515625 +17967 -0.01055908203125 +17968 0.1033935546875 +17969 0.24908447265625 +17970 0.373199462890625 +17971 0.45806884765625 +17972 0.511474609375 +17973 0.565399169921875 +17974 0.61138916015625 +17975 0.5897216796875 +17976 0.4906005859375 +17977 0.33148193359375 +17978 0.147796630859375 +17979 -0.01873779296875 +17980 -0.140289306640625 +17981 -0.191986083984375 +17982 -0.184295654296875 +17983 -0.161834716796875 +17984 -0.166595458984375 +17985 -0.19390869140625 +17986 -0.22442626953125 +17987 -0.279754638671875 +17988 -0.3389892578125 +17989 -0.3543701171875 +17990 -0.348175048828125 +17991 -0.32598876953125 +17992 -0.2581787109375 +17993 -0.139801025390625 +17994 0.014617919921875 +17995 0.144378662109375 +17996 0.221038818359375 +17997 0.27069091796875 +17998 0.294036865234375 +17999 0.311767578125 +18000 0.339141845703125 +18001 0.360260009765625 +18002 0.360504150390625 +18003 0.308380126953125 +18004 0.18170166015625 +18005 0.0047607421875 +18006 -0.17559814453125 +18007 -0.3143310546875 +18008 -0.36785888671875 +18009 -0.36248779296875 +18010 -0.343536376953125 +18011 -0.3018798828125 +18012 -0.231414794921875 +18013 -0.117645263671875 +18014 0.007049560546875 +18015 0.087982177734375 +18016 0.13946533203125 +18017 0.17425537109375 +18018 0.188201904296875 +18019 0.171234130859375 +18020 0.118438720703125 +18021 0.05706787109375 +18022 -0.010711669921875 +18023 -0.0914306640625 +18024 -0.162322998046875 +18025 -0.194549560546875 +18026 -0.1492919921875 +18027 -0.02166748046875 +18028 0.124053955078125 +18029 0.211151123046875 +18030 0.240447998046875 +18031 0.242218017578125 +18032 0.2257080078125 +18033 0.194366455078125 +18034 0.115509033203125 +18035 0.0128173828125 +18036 -0.053802490234375 +18037 -0.110626220703125 +18038 -0.199493408203125 +18039 -0.29437255859375 +18040 -0.33221435546875 +18041 -0.27972412109375 +18042 -0.185333251953125 +18043 -0.128204345703125 +18044 -0.115692138671875 +18045 -0.116455078125 +18046 -0.105926513671875 +18047 -0.053955078125 +18048 0.048797607421875 +18049 0.157318115234375 +18050 0.212005615234375 +18051 0.218475341796875 +18052 0.23724365234375 +18053 0.30535888671875 +18054 0.38128662109375 +18055 0.404449462890625 +18056 0.3944091796875 +18057 0.3885498046875 +18058 0.362640380859375 +18059 0.27362060546875 +18060 0.11712646484375 +18061 -0.054901123046875 +18062 -0.19085693359375 +18063 -0.28570556640625 +18064 -0.339263916015625 +18065 -0.3775634765625 +18066 -0.445709228515625 +18067 -0.535064697265625 +18068 -0.629058837890625 +18069 -0.697601318359375 +18070 -0.70391845703125 +18071 -0.6424560546875 +18072 -0.491241455078125 +18073 -0.265716552734375 +18074 -0.023712158203125 +18075 0.201751708984375 +18076 0.375823974609375 +18077 0.485076904296875 +18078 0.56884765625 +18079 0.634765625 +18080 0.63763427734375 +18081 0.5660400390625 +18082 0.4720458984375 +18083 0.40692138671875 +18084 0.3778076171875 +18085 0.376953125 +18086 0.371978759765625 +18087 0.313140869140625 +18088 0.184417724609375 +18089 0.011199951171875 +18090 -0.171051025390625 +18091 -0.33740234375 +18092 -0.47198486328125 +18093 -0.560394287109375 +18094 -0.58056640625 +18095 -0.54754638671875 +18096 -0.508575439453125 +18097 -0.459503173828125 +18098 -0.394378662109375 +18099 -0.35260009765625 +18100 -0.31170654296875 +18101 -0.197418212890625 +18102 -0.007965087890625 +18103 0.207489013671875 +18104 0.409210205078125 +18105 0.57208251953125 +18106 0.66595458984375 +18107 0.65875244140625 +18108 0.56744384765625 +18109 0.431396484375 +18110 0.29443359375 +18111 0.182464599609375 +18112 0.06365966796875 +18113 -0.075958251953125 +18114 -0.189422607421875 +18115 -0.271942138671875 +18116 -0.342529296875 +18117 -0.364166259765625 +18118 -0.327239990234375 +18119 -0.2769775390625 +18120 -0.253692626953125 +18121 -0.24365234375 +18122 -0.1983642578125 +18123 -0.116241455078125 +18124 -0.036834716796875 +18125 0.034881591796875 +18126 0.09124755859375 +18127 0.10888671875 +18128 0.125518798828125 +18129 0.15771484375 +18130 0.17828369140625 +18131 0.17108154296875 +18132 0.129974365234375 +18133 0.082427978515625 +18134 0.027679443359375 +18135 -0.065643310546875 +18136 -0.15936279296875 +18137 -0.21307373046875 +18138 -0.234649658203125 +18139 -0.2001953125 +18140 -0.119171142578125 +18141 -0.024749755859375 +18142 0.085784912109375 +18143 0.178131103515625 +18144 0.215576171875 +18145 0.211456298828125 +18146 0.17523193359375 +18147 0.128753662109375 +18148 0.1019287109375 +18149 0.0743408203125 +18150 0.04327392578125 +18151 0.038177490234375 +18152 0.076263427734375 +18153 0.14105224609375 +18154 0.186431884765625 +18155 0.188812255859375 +18156 0.1390380859375 +18157 0.041778564453125 +18158 -0.079437255859375 +18159 -0.219390869140625 +18160 -0.367828369140625 +18161 -0.494873046875 +18162 -0.556243896484375 +18163 -0.508697509765625 +18164 -0.3756103515625 +18165 -0.218902587890625 +18166 -0.063751220703125 +18167 0.091552734375 +18168 0.23602294921875 +18169 0.342987060546875 +18170 0.39520263671875 +18171 0.389373779296875 +18172 0.324249267578125 +18173 0.224090576171875 +18174 0.124267578125 +18175 0.037078857421875 +18176 -0.010101318359375 +18177 -0.019439697265625 +18178 -0.022796630859375 +18179 -0.001556396484375 +18180 0.056304931640625 +18181 0.106719970703125 +18182 0.096893310546875 +18183 0.042694091796875 +18184 -0.018035888671875 +18185 -0.07586669921875 +18186 -0.11944580078125 +18187 -0.15972900390625 +18188 -0.202606201171875 +18189 -0.24859619140625 +18190 -0.30517578125 +18191 -0.36212158203125 +18192 -0.39141845703125 +18193 -0.35528564453125 +18194 -0.249969482421875 +18195 -0.092864990234375 +18196 0.08905029296875 +18197 0.2352294921875 +18198 0.318817138671875 +18199 0.358642578125 +18200 0.347747802734375 +18201 0.28564453125 +18202 0.223175048828125 +18203 0.196746826171875 +18204 0.179840087890625 +18205 0.155548095703125 +18206 0.151214599609375 +18207 0.156951904296875 +18208 0.13177490234375 +18209 0.100799560546875 +18210 0.087127685546875 +18211 0.05487060546875 +18212 -0.009002685546875 +18213 -0.10400390625 +18214 -0.229400634765625 +18215 -0.35552978515625 +18216 -0.441925048828125 +18217 -0.473846435546875 +18218 -0.464813232421875 +18219 -0.419097900390625 +18220 -0.334320068359375 +18221 -0.227935791015625 +18222 -0.12347412109375 +18223 -0.02764892578125 +18224 0.077667236328125 +18225 0.2132568359375 +18226 0.38885498046875 +18227 0.582794189453125 +18228 0.734039306640625 +18229 0.800140380859375 +18230 0.7783203125 +18231 0.6651611328125 +18232 0.45965576171875 +18233 0.199188232421875 +18234 -0.050689697265625 +18235 -0.23297119140625 +18236 -0.33013916015625 +18237 -0.368408203125 +18238 -0.378936767578125 +18239 -0.376983642578125 +18240 -0.37969970703125 +18241 -0.391510009765625 +18242 -0.385345458984375 +18243 -0.3419189453125 +18244 -0.28289794921875 +18245 -0.251617431640625 +18246 -0.266143798828125 +18247 -0.273345947265625 +18248 -0.216796875 +18249 -0.128265380859375 +18250 -0.068145751953125 +18251 -0.0430908203125 +18252 -0.024444580078125 +18253 0.020721435546875 +18254 0.124481201171875 +18255 0.25787353515625 +18256 0.379119873046875 +18257 0.47991943359375 +18258 0.5281982421875 +18259 0.511138916015625 +18260 0.456207275390625 +18261 0.407470703125 +18262 0.383758544921875 +18263 0.35687255859375 +18264 0.31182861328125 +18265 0.250885009765625 +18266 0.1654052734375 +18267 0.035247802734375 +18268 -0.142059326171875 +18269 -0.33563232421875 +18270 -0.5345458984375 +18271 -0.72186279296875 +18272 -0.836669921875 +18273 -0.8326416015625 +18274 -0.7296142578125 +18275 -0.582550048828125 +18276 -0.440093994140625 +18277 -0.324310302734375 +18278 -0.20147705078125 +18279 -0.044647216796875 +18280 0.103973388671875 +18281 0.202392578125 +18282 0.264495849609375 +18283 0.338897705078125 +18284 0.443817138671875 +18285 0.545074462890625 +18286 0.6173095703125 +18287 0.6524658203125 +18288 0.66339111328125 +18289 0.6561279296875 +18290 0.606781005859375 +18291 0.501190185546875 +18292 0.352783203125 +18293 0.176544189453125 +18294 -0.034820556640625 +18295 -0.258209228515625 +18296 -0.44244384765625 +18297 -0.5753173828125 +18298 -0.65203857421875 +18299 -0.641632080078125 +18300 -0.562164306640625 +18301 -0.458038330078125 +18302 -0.350555419921875 +18303 -0.260528564453125 +18304 -0.192108154296875 +18305 -0.141937255859375 +18306 -0.1021728515625 +18307 -0.062896728515625 +18308 -0.011932373046875 +18309 0.062835693359375 +18310 0.148712158203125 +18311 0.241729736328125 +18312 0.34912109375 +18313 0.457305908203125 +18314 0.54388427734375 +18315 0.5728759765625 +18316 0.506591796875 +18317 0.351226806640625 +18318 0.146514892578125 +18319 -0.05523681640625 +18320 -0.21624755859375 +18321 -0.334930419921875 +18322 -0.402984619140625 +18323 -0.4412841796875 +18324 -0.49578857421875 +18325 -0.5601806640625 +18326 -0.600738525390625 +18327 -0.584228515625 +18328 -0.47930908203125 +18329 -0.27935791015625 +18330 -0.0089111328125 +18331 0.268798828125 +18332 0.482818603515625 +18333 0.60369873046875 +18334 0.650421142578125 +18335 0.66400146484375 +18336 0.6414794921875 +18337 0.572540283203125 +18338 0.498138427734375 +18339 0.439453125 +18340 0.375518798828125 +18341 0.274505615234375 +18342 0.1087646484375 +18343 -0.099395751953125 +18344 -0.3182373046875 +18345 -0.5489501953125 +18346 -0.7738037109375 +18347 -0.86383056640625 +18348 -0.870391845703125 +18349 -0.86895751953125 +18350 -0.861053466796875 +18351 -0.765869140625 +18352 -0.5301513671875 +18353 -0.214691162109375 +18354 0.137359619140625 +18355 0.474822998046875 +18356 0.76239013671875 +18357 0.867462158203125 +18358 0.870361328125 +18359 0.86480712890625 +18360 0.831817626953125 +18361 0.677581787109375 +18362 0.495880126953125 +18363 0.30767822265625 +18364 0.116180419921875 +18365 -0.110748291015625 +18366 -0.381805419921875 +18367 -0.6572265625 +18368 -0.857421875 +18369 -0.870391845703125 +18370 -0.870391845703125 +18371 -0.86444091796875 +18372 -0.85723876953125 +18373 -0.790008544921875 +18374 -0.62847900390625 +18375 -0.3956298828125 +18376 -0.126708984375 +18377 0.150115966796875 +18378 0.424041748046875 +18379 0.670623779296875 +18380 0.854522705078125 +18381 0.866485595703125 +18382 0.86920166015625 +18383 0.8653564453125 +18384 0.857147216796875 +18385 0.766845703125 +18386 0.628509521484375 +18387 0.462127685546875 +18388 0.297210693359375 +18389 0.14862060546875 +18390 -0.00537109375 +18391 -0.15753173828125 +18392 -0.31304931640625 +18393 -0.48876953125 +18394 -0.6416015625 +18395 -0.751373291015625 +18396 -0.84619140625 +18397 -0.861297607421875 +18398 -0.863250732421875 +18399 -0.856597900390625 +18400 -0.7498779296875 +18401 -0.624542236328125 +18402 -0.47808837890625 +18403 -0.253387451171875 +18404 0.003692626953125 +18405 0.2257080078125 +18406 0.427154541015625 +18407 0.643218994140625 +18408 0.855926513671875 +18409 0.870361328125 +18410 0.870361328125 +18411 0.862762451171875 +18412 0.79669189453125 +18413 0.595794677734375 +18414 0.362152099609375 +18415 0.1270751953125 +18416 -0.086944580078125 +18417 -0.2784423828125 +18418 -0.484832763671875 +18419 -0.729583740234375 +18420 -0.86688232421875 +18421 -0.870391845703125 +18422 -0.86859130859375 +18423 -0.86279296875 +18424 -0.817962646484375 +18425 -0.6116943359375 +18426 -0.3128662109375 +18427 0.039398193359375 +18428 0.422821044921875 +18429 0.805145263671875 +18430 0.870361328125 +18431 0.870361328125 +18432 0.860015869140625 +18433 0.727935791015625 +18434 0.48114013671875 +18435 0.2059326171875 +18436 -0.06103515625 +18437 -0.29913330078125 +18438 -0.516204833984375 +18439 -0.7252197265625 +18440 -0.85980224609375 +18441 -0.870391845703125 +18442 -0.870391845703125 +18443 -0.858062744140625 +18444 -0.673004150390625 +18445 -0.42694091796875 +18446 -0.2100830078125 +18447 -0.0362548828125 +18448 0.10943603515625 +18449 0.23516845703125 +18450 0.373687744140625 +18451 0.517791748046875 +18452 0.602783203125 +18453 0.635711669921875 +18454 0.655181884765625 +18455 0.65948486328125 +18456 0.651275634765625 +18457 0.61846923828125 +18458 0.53753662109375 +18459 0.404144287109375 +18460 0.22186279296875 +18461 0.003997802734375 +18462 -0.22100830078125 +18463 -0.42449951171875 +18464 -0.579833984375 +18465 -0.641876220703125 +18466 -0.6177978515625 +18467 -0.575531005859375 +18468 -0.526336669921875 +18469 -0.42645263671875 +18470 -0.2581787109375 +18471 -0.068695068359375 +18472 0.09222412109375 +18473 0.232147216796875 +18474 0.3509521484375 +18475 0.410064697265625 +18476 0.372955322265625 +18477 0.2554931640625 +18478 0.10711669921875 +18479 -0.052886962890625 +18480 -0.186279296875 +18481 -0.23291015625 +18482 -0.209442138671875 +18483 -0.174163818359375 +18484 -0.126739501953125 +18485 -0.048126220703125 +18486 0.0426025390625 +18487 0.10748291015625 +18488 0.1409912109375 +18489 0.19708251953125 +18490 0.273651123046875 +18491 0.31768798828125 +18492 0.341094970703125 +18493 0.368011474609375 +18494 0.37249755859375 +18495 0.30072021484375 +18496 0.1517333984375 +18497 -0.01470947265625 +18498 -0.1883544921875 +18499 -0.372711181640625 +18500 -0.51397705078125 +18501 -0.57177734375 +18502 -0.53948974609375 +18503 -0.43511962890625 +18504 -0.2962646484375 +18505 -0.161102294921875 +18506 -0.0435791015625 +18507 0.060394287109375 +18508 0.13665771484375 +18509 0.170135498046875 +18510 0.16552734375 +18511 0.15728759765625 +18512 0.150787353515625 +18513 0.12200927734375 +18514 0.080108642578125 +18515 0.05126953125 +18516 0.062896728515625 +18517 0.09271240234375 +18518 0.092987060546875 +18519 0.07855224609375 +18520 0.06427001953125 +18521 0.0347900390625 +18522 -0.01171875 +18523 -0.056060791015625 +18524 -0.055511474609375 +18525 -0.010467529296875 +18526 0.02508544921875 +18527 0.025665283203125 +18528 0.017333984375 +18529 0.00189208984375 +18530 -0.03173828125 +18531 -0.071502685546875 +18532 -0.13543701171875 +18533 -0.219970703125 +18534 -0.300506591796875 +18535 -0.376312255859375 +18536 -0.416107177734375 +18537 -0.371124267578125 +18538 -0.242279052734375 +18539 -0.069732666015625 +18540 0.125640869140625 +18541 0.31268310546875 +18542 0.45501708984375 +18543 0.554779052734375 +18544 0.61065673828125 +18545 0.610931396484375 +18546 0.531463623046875 +18547 0.3883056640625 +18548 0.23468017578125 +18549 0.095245361328125 +18550 -0.00396728515625 +18551 -0.04852294921875 +18552 -0.055145263671875 +18553 -0.0758056640625 +18554 -0.138702392578125 +18555 -0.209197998046875 +18556 -0.289031982421875 +18557 -0.37884521484375 +18558 -0.456329345703125 +18559 -0.51641845703125 +18560 -0.519287109375 +18561 -0.458251953125 +18562 -0.384796142578125 +18563 -0.323699951171875 +18564 -0.269287109375 +18565 -0.1951904296875 +18566 -0.100006103515625 +18567 -0.01055908203125 +18568 0.1033935546875 +18569 0.24908447265625 +18570 0.373199462890625 +18571 0.45806884765625 +18572 0.511474609375 +18573 0.565399169921875 +18574 0.61138916015625 +18575 0.5897216796875 +18576 0.4906005859375 +18577 0.33148193359375 +18578 0.147796630859375 +18579 -0.01873779296875 +18580 -0.140289306640625 +18581 -0.191986083984375 +18582 -0.184295654296875 +18583 -0.161834716796875 +18584 -0.166595458984375 +18585 -0.19390869140625 +18586 -0.22442626953125 +18587 -0.279754638671875 +18588 -0.3389892578125 +18589 -0.3543701171875 +18590 -0.348175048828125 +18591 -0.32598876953125 +18592 -0.2581787109375 +18593 -0.139801025390625 +18594 0.014617919921875 +18595 0.144378662109375 +18596 0.221038818359375 +18597 0.27069091796875 +18598 0.294036865234375 +18599 0.311767578125 +18600 0.339141845703125 +18601 0.360260009765625 +18602 0.360504150390625 +18603 0.308380126953125 +18604 0.18170166015625 +18605 0.0047607421875 +18606 -0.17559814453125 +18607 -0.3143310546875 +18608 -0.36785888671875 +18609 -0.36248779296875 +18610 -0.343536376953125 +18611 -0.3018798828125 +18612 -0.231414794921875 +18613 -0.117645263671875 +18614 0.007049560546875 +18615 0.087982177734375 +18616 0.13946533203125 +18617 0.17425537109375 +18618 0.188201904296875 +18619 0.171234130859375 +18620 0.118438720703125 +18621 0.05706787109375 +18622 -0.010711669921875 +18623 -0.0914306640625 +18624 -0.162322998046875 +18625 -0.194549560546875 +18626 -0.1492919921875 +18627 -0.02166748046875 +18628 0.124053955078125 +18629 0.211151123046875 +18630 0.240447998046875 +18631 0.242218017578125 +18632 0.2257080078125 +18633 0.194366455078125 +18634 0.115509033203125 +18635 0.0128173828125 +18636 -0.053802490234375 +18637 -0.110626220703125 +18638 -0.199493408203125 +18639 -0.29437255859375 +18640 -0.33221435546875 +18641 -0.27972412109375 +18642 -0.185333251953125 +18643 -0.128204345703125 +18644 -0.115692138671875 +18645 -0.116455078125 +18646 -0.105926513671875 +18647 -0.053955078125 +18648 0.048797607421875 +18649 0.157318115234375 +18650 0.212005615234375 +18651 0.218475341796875 +18652 0.23724365234375 +18653 0.30535888671875 +18654 0.38128662109375 +18655 0.404449462890625 +18656 0.3944091796875 +18657 0.3885498046875 +18658 0.362640380859375 +18659 0.27362060546875 +18660 0.11712646484375 +18661 -0.054901123046875 +18662 -0.19085693359375 +18663 -0.28570556640625 +18664 -0.339263916015625 +18665 -0.3775634765625 +18666 -0.445709228515625 +18667 -0.535064697265625 +18668 -0.629058837890625 +18669 -0.697601318359375 +18670 -0.70391845703125 +18671 -0.6424560546875 +18672 -0.491241455078125 +18673 -0.265716552734375 +18674 -0.023712158203125 +18675 0.201751708984375 +18676 0.375823974609375 +18677 0.485076904296875 +18678 0.56884765625 +18679 0.634765625 +18680 0.63763427734375 +18681 0.5660400390625 +18682 0.4720458984375 +18683 0.40692138671875 +18684 0.3778076171875 +18685 0.376953125 +18686 0.371978759765625 +18687 0.313140869140625 +18688 0.184417724609375 +18689 0.011199951171875 +18690 -0.171051025390625 +18691 -0.33740234375 +18692 -0.47198486328125 +18693 -0.560394287109375 +18694 -0.58056640625 +18695 -0.54754638671875 +18696 -0.508575439453125 +18697 -0.459503173828125 +18698 -0.394378662109375 +18699 -0.35260009765625 +18700 -0.31170654296875 +18701 -0.197418212890625 +18702 -0.007965087890625 +18703 0.207489013671875 +18704 0.409210205078125 +18705 0.57208251953125 +18706 0.66595458984375 +18707 0.65875244140625 +18708 0.56744384765625 +18709 0.431396484375 +18710 0.29443359375 +18711 0.182464599609375 +18712 0.06365966796875 +18713 -0.075958251953125 +18714 -0.189422607421875 +18715 -0.271942138671875 +18716 -0.342529296875 +18717 -0.364166259765625 +18718 -0.327239990234375 +18719 -0.2769775390625 +18720 -0.253692626953125 +18721 -0.24365234375 +18722 -0.1983642578125 +18723 -0.116241455078125 +18724 -0.036834716796875 +18725 0.034881591796875 +18726 0.09124755859375 +18727 0.10888671875 +18728 0.125518798828125 +18729 0.15771484375 +18730 0.17828369140625 +18731 0.17108154296875 +18732 0.129974365234375 +18733 0.082427978515625 +18734 0.027679443359375 +18735 -0.065643310546875 +18736 -0.15936279296875 +18737 -0.21307373046875 +18738 -0.234649658203125 +18739 -0.2001953125 +18740 -0.119171142578125 +18741 -0.024749755859375 +18742 0.085784912109375 +18743 0.178131103515625 +18744 0.215576171875 +18745 0.211456298828125 +18746 0.17523193359375 +18747 0.128753662109375 +18748 0.1019287109375 +18749 0.0743408203125 +18750 0.04327392578125 +18751 0.038177490234375 +18752 0.076263427734375 +18753 0.14105224609375 +18754 0.186431884765625 +18755 0.188812255859375 +18756 0.1390380859375 +18757 0.041778564453125 +18758 -0.079437255859375 +18759 -0.219390869140625 +18760 -0.367828369140625 +18761 -0.494873046875 +18762 -0.556243896484375 +18763 -0.508697509765625 +18764 -0.3756103515625 +18765 -0.218902587890625 +18766 -0.063751220703125 +18767 0.091552734375 +18768 0.23602294921875 +18769 0.342987060546875 +18770 0.39520263671875 +18771 0.389373779296875 +18772 0.324249267578125 +18773 0.224090576171875 +18774 0.124267578125 +18775 0.037078857421875 +18776 -0.010101318359375 +18777 -0.019439697265625 +18778 -0.022796630859375 +18779 -0.001556396484375 +18780 0.056304931640625 +18781 0.106719970703125 +18782 0.096893310546875 +18783 0.042694091796875 +18784 -0.018035888671875 +18785 -0.07586669921875 +18786 -0.11944580078125 +18787 -0.15972900390625 +18788 -0.202606201171875 +18789 -0.24859619140625 +18790 -0.30517578125 +18791 -0.36212158203125 +18792 -0.39141845703125 +18793 -0.35528564453125 +18794 -0.249969482421875 +18795 -0.092864990234375 +18796 0.08905029296875 +18797 0.2352294921875 +18798 0.318817138671875 +18799 0.358642578125 +18800 0.347747802734375 +18801 0.28564453125 +18802 0.223175048828125 +18803 0.196746826171875 +18804 0.179840087890625 +18805 0.155548095703125 +18806 0.151214599609375 +18807 0.156951904296875 +18808 0.13177490234375 +18809 0.100799560546875 +18810 0.087127685546875 +18811 0.05487060546875 +18812 -0.009002685546875 +18813 -0.10400390625 +18814 -0.229400634765625 +18815 -0.35552978515625 +18816 -0.441925048828125 +18817 -0.473846435546875 +18818 -0.464813232421875 +18819 -0.419097900390625 +18820 -0.334320068359375 +18821 -0.227935791015625 +18822 -0.12347412109375 +18823 -0.02764892578125 +18824 0.077667236328125 +18825 0.2132568359375 +18826 0.38885498046875 +18827 0.582794189453125 +18828 0.734039306640625 +18829 0.800140380859375 +18830 0.7783203125 +18831 0.6651611328125 +18832 0.45965576171875 +18833 0.199188232421875 +18834 -0.050689697265625 +18835 -0.23297119140625 +18836 -0.33013916015625 +18837 -0.368408203125 +18838 -0.378936767578125 +18839 -0.376983642578125 +18840 -0.37969970703125 +18841 -0.391510009765625 +18842 -0.385345458984375 +18843 -0.3419189453125 +18844 -0.28289794921875 +18845 -0.251617431640625 +18846 -0.266143798828125 +18847 -0.273345947265625 +18848 -0.216796875 +18849 -0.128265380859375 +18850 -0.068145751953125 +18851 -0.0430908203125 +18852 -0.024444580078125 +18853 0.020721435546875 +18854 0.124481201171875 +18855 0.25787353515625 +18856 0.379119873046875 +18857 0.47991943359375 +18858 0.5281982421875 +18859 0.511138916015625 +18860 0.456207275390625 +18861 0.407470703125 +18862 0.383758544921875 +18863 0.35687255859375 +18864 0.31182861328125 +18865 0.250885009765625 +18866 0.1654052734375 +18867 0.035247802734375 +18868 -0.142059326171875 +18869 -0.33563232421875 +18870 -0.5345458984375 +18871 -0.72186279296875 +18872 -0.836669921875 +18873 -0.8326416015625 +18874 -0.7296142578125 +18875 -0.582550048828125 +18876 -0.440093994140625 +18877 -0.324310302734375 +18878 -0.20147705078125 +18879 -0.044647216796875 +18880 0.103973388671875 +18881 0.202392578125 +18882 0.264495849609375 +18883 0.338897705078125 +18884 0.443817138671875 +18885 0.545074462890625 +18886 0.6173095703125 +18887 0.6524658203125 +18888 0.66339111328125 +18889 0.6561279296875 +18890 0.606781005859375 +18891 0.501190185546875 +18892 0.352783203125 +18893 0.176544189453125 +18894 -0.034820556640625 +18895 -0.258209228515625 +18896 -0.44244384765625 +18897 -0.5753173828125 +18898 -0.65203857421875 +18899 -0.641632080078125 +18900 -0.562164306640625 +18901 -0.458038330078125 +18902 -0.350555419921875 +18903 -0.260528564453125 +18904 -0.192108154296875 +18905 -0.141937255859375 +18906 -0.1021728515625 +18907 -0.062896728515625 +18908 -0.011932373046875 +18909 0.062835693359375 +18910 0.148712158203125 +18911 0.241729736328125 +18912 0.34912109375 +18913 0.457305908203125 +18914 0.54388427734375 +18915 0.5728759765625 +18916 0.506591796875 +18917 0.351226806640625 +18918 0.146514892578125 +18919 -0.05523681640625 +18920 -0.21624755859375 +18921 -0.334930419921875 +18922 -0.402984619140625 +18923 -0.4412841796875 +18924 -0.49578857421875 +18925 -0.5601806640625 +18926 -0.600738525390625 +18927 -0.584228515625 +18928 -0.47930908203125 +18929 -0.27935791015625 +18930 -0.0089111328125 +18931 0.268798828125 +18932 0.482818603515625 +18933 0.60369873046875 +18934 0.650421142578125 +18935 0.66400146484375 +18936 0.6414794921875 +18937 0.572540283203125 +18938 0.498138427734375 +18939 0.439453125 +18940 0.375518798828125 +18941 0.274505615234375 +18942 0.1087646484375 +18943 -0.099395751953125 +18944 -0.3182373046875 +18945 -0.5489501953125 +18946 -0.7738037109375 +18947 -0.86383056640625 +18948 -0.870391845703125 +18949 -0.86895751953125 +18950 -0.861053466796875 +18951 -0.765869140625 +18952 -0.5301513671875 +18953 -0.214691162109375 +18954 0.137359619140625 +18955 0.474822998046875 +18956 0.76239013671875 +18957 0.867462158203125 +18958 0.870361328125 +18959 0.86480712890625 +18960 0.831817626953125 +18961 0.677581787109375 +18962 0.495880126953125 +18963 0.30767822265625 +18964 0.116180419921875 +18965 -0.110748291015625 +18966 -0.381805419921875 +18967 -0.6572265625 +18968 -0.857421875 +18969 -0.870391845703125 +18970 -0.870391845703125 +18971 -0.86444091796875 +18972 -0.85723876953125 +18973 -0.790008544921875 +18974 -0.62847900390625 +18975 -0.3956298828125 +18976 -0.126708984375 +18977 0.150115966796875 +18978 0.424041748046875 +18979 0.670623779296875 +18980 0.854522705078125 +18981 0.866485595703125 +18982 0.86920166015625 +18983 0.8653564453125 +18984 0.857147216796875 +18985 0.766845703125 +18986 0.628509521484375 +18987 0.462127685546875 +18988 0.297210693359375 +18989 0.14862060546875 +18990 -0.00537109375 +18991 -0.15753173828125 +18992 -0.31304931640625 +18993 -0.48876953125 +18994 -0.6416015625 +18995 -0.751373291015625 +18996 -0.84619140625 +18997 -0.861297607421875 +18998 -0.863250732421875 +18999 -0.856597900390625 +19000 -0.7498779296875 +19001 -0.624542236328125 +19002 -0.47808837890625 +19003 -0.253387451171875 +19004 0.003692626953125 +19005 0.2257080078125 +19006 0.427154541015625 +19007 0.643218994140625 +19008 0.855926513671875 +19009 0.870361328125 +19010 0.870361328125 +19011 0.862762451171875 +19012 0.79669189453125 +19013 0.595794677734375 +19014 0.362152099609375 +19015 0.1270751953125 +19016 -0.086944580078125 +19017 -0.2784423828125 +19018 -0.484832763671875 +19019 -0.729583740234375 +19020 -0.86688232421875 +19021 -0.870391845703125 +19022 -0.86859130859375 +19023 -0.86279296875 +19024 -0.817962646484375 +19025 -0.6116943359375 +19026 -0.3128662109375 +19027 0.039398193359375 +19028 0.422821044921875 +19029 0.805145263671875 +19030 0.870361328125 +19031 0.870361328125 +19032 0.860015869140625 +19033 0.727935791015625 +19034 0.48114013671875 +19035 0.2059326171875 +19036 -0.06103515625 +19037 -0.29913330078125 +19038 -0.516204833984375 +19039 -0.7252197265625 +19040 -0.85980224609375 +19041 -0.870391845703125 +19042 -0.870391845703125 +19043 -0.858062744140625 +19044 -0.673004150390625 +19045 -0.42694091796875 +19046 -0.2100830078125 +19047 -0.0362548828125 +19048 0.10943603515625 +19049 0.23516845703125 +19050 0.373687744140625 +19051 0.517791748046875 +19052 0.602783203125 +19053 0.635711669921875 +19054 0.655181884765625 +19055 0.65948486328125 +19056 0.651275634765625 +19057 0.61846923828125 +19058 0.53753662109375 +19059 0.404144287109375 +19060 0.22186279296875 +19061 0.003997802734375 +19062 -0.22100830078125 +19063 -0.42449951171875 +19064 -0.579833984375 +19065 -0.641876220703125 +19066 -0.6177978515625 +19067 -0.575531005859375 +19068 -0.526336669921875 +19069 -0.42645263671875 +19070 -0.2581787109375 +19071 -0.068695068359375 +19072 0.09222412109375 +19073 0.232147216796875 +19074 0.3509521484375 +19075 0.410064697265625 +19076 0.372955322265625 +19077 0.2554931640625 +19078 0.10711669921875 +19079 -0.052886962890625 +19080 -0.186279296875 +19081 -0.23291015625 +19082 -0.209442138671875 +19083 -0.174163818359375 +19084 -0.126739501953125 +19085 -0.048126220703125 +19086 0.0426025390625 +19087 0.10748291015625 +19088 0.1409912109375 +19089 0.19708251953125 +19090 0.273651123046875 +19091 0.31768798828125 +19092 0.341094970703125 +19093 0.368011474609375 +19094 0.37249755859375 +19095 0.30072021484375 +19096 0.1517333984375 +19097 -0.01470947265625 +19098 -0.1883544921875 +19099 -0.372711181640625 +19100 -0.51397705078125 +19101 -0.57177734375 +19102 -0.53948974609375 +19103 -0.43511962890625 +19104 -0.2962646484375 +19105 -0.161102294921875 +19106 -0.0435791015625 +19107 0.060394287109375 +19108 0.13665771484375 +19109 0.170135498046875 +19110 0.16552734375 +19111 0.15728759765625 +19112 0.150787353515625 +19113 0.12200927734375 +19114 0.080108642578125 +19115 0.05126953125 +19116 0.062896728515625 +19117 0.09271240234375 +19118 0.092987060546875 +19119 0.07855224609375 +19120 0.06427001953125 +19121 0.0347900390625 +19122 -0.01171875 +19123 -0.056060791015625 +19124 -0.055511474609375 +19125 -0.010467529296875 +19126 0.02508544921875 +19127 0.025665283203125 +19128 0.017333984375 +19129 0.00189208984375 +19130 -0.03173828125 +19131 -0.071502685546875 +19132 -0.13543701171875 +19133 -0.219970703125 +19134 -0.300506591796875 +19135 -0.376312255859375 +19136 -0.416107177734375 +19137 -0.371124267578125 +19138 -0.242279052734375 +19139 -0.069732666015625 +19140 0.125640869140625 +19141 0.31268310546875 +19142 0.45501708984375 +19143 0.554779052734375 +19144 0.61065673828125 +19145 0.610931396484375 +19146 0.531463623046875 +19147 0.3883056640625 +19148 0.23468017578125 +19149 0.095245361328125 +19150 -0.00396728515625 +19151 -0.04852294921875 +19152 -0.055145263671875 +19153 -0.0758056640625 +19154 -0.138702392578125 +19155 -0.209197998046875 +19156 -0.289031982421875 +19157 -0.37884521484375 +19158 -0.456329345703125 +19159 -0.51641845703125 +19160 -0.519287109375 +19161 -0.458251953125 +19162 -0.384796142578125 +19163 -0.323699951171875 +19164 -0.269287109375 +19165 -0.1951904296875 +19166 -0.100006103515625 +19167 -0.01055908203125 +19168 0.1033935546875 +19169 0.24908447265625 +19170 0.373199462890625 +19171 0.45806884765625 +19172 0.511474609375 +19173 0.565399169921875 +19174 0.61138916015625 +19175 0.5897216796875 +19176 0.4906005859375 +19177 0.33148193359375 +19178 0.147796630859375 +19179 -0.01873779296875 +19180 -0.140289306640625 +19181 -0.191986083984375 +19182 -0.184295654296875 +19183 -0.161834716796875 +19184 -0.166595458984375 +19185 -0.19390869140625 +19186 -0.22442626953125 +19187 -0.279754638671875 +19188 -0.3389892578125 +19189 -0.3543701171875 +19190 -0.348175048828125 +19191 -0.32598876953125 +19192 -0.2581787109375 +19193 -0.139801025390625 +19194 0.014617919921875 +19195 0.144378662109375 +19196 0.221038818359375 +19197 0.27069091796875 +19198 0.294036865234375 +19199 0.311767578125 +19200 0.339141845703125 +19201 0.360260009765625 +19202 0.360504150390625 +19203 0.308380126953125 +19204 0.18170166015625 +19205 0.0047607421875 +19206 -0.17559814453125 +19207 -0.3143310546875 +19208 -0.36785888671875 +19209 -0.36248779296875 +19210 -0.343536376953125 +19211 -0.3018798828125 +19212 -0.231414794921875 +19213 -0.117645263671875 +19214 0.007049560546875 +19215 0.087982177734375 +19216 0.13946533203125 +19217 0.17425537109375 +19218 0.188201904296875 +19219 0.171234130859375 +19220 0.118438720703125 +19221 0.05706787109375 +19222 -0.010711669921875 +19223 -0.0914306640625 +19224 -0.162322998046875 +19225 -0.194549560546875 +19226 -0.1492919921875 +19227 -0.02166748046875 +19228 0.124053955078125 +19229 0.211151123046875 +19230 0.240447998046875 +19231 0.242218017578125 +19232 0.2257080078125 +19233 0.194366455078125 +19234 0.115509033203125 +19235 0.0128173828125 +19236 -0.053802490234375 +19237 -0.110626220703125 +19238 -0.199493408203125 +19239 -0.29437255859375 +19240 -0.33221435546875 +19241 -0.27972412109375 +19242 -0.185333251953125 +19243 -0.128204345703125 +19244 -0.115692138671875 +19245 -0.116455078125 +19246 -0.105926513671875 +19247 -0.053955078125 +19248 0.048797607421875 +19249 0.157318115234375 +19250 0.212005615234375 +19251 0.218475341796875 +19252 0.23724365234375 +19253 0.30535888671875 +19254 0.38128662109375 +19255 0.404449462890625 +19256 0.3944091796875 +19257 0.3885498046875 +19258 0.362640380859375 +19259 0.27362060546875 +19260 0.11712646484375 +19261 -0.054901123046875 +19262 -0.19085693359375 +19263 -0.28570556640625 +19264 -0.339263916015625 +19265 -0.3775634765625 +19266 -0.445709228515625 +19267 -0.535064697265625 +19268 -0.629058837890625 +19269 -0.697601318359375 +19270 -0.70391845703125 +19271 -0.6424560546875 +19272 -0.491241455078125 +19273 -0.265716552734375 +19274 -0.023712158203125 +19275 0.201751708984375 +19276 0.375823974609375 +19277 0.485076904296875 +19278 0.56884765625 +19279 0.634765625 +19280 0.63763427734375 +19281 0.5660400390625 +19282 0.4720458984375 +19283 0.40692138671875 +19284 0.3778076171875 +19285 0.376953125 +19286 0.371978759765625 +19287 0.313140869140625 +19288 0.184417724609375 +19289 0.011199951171875 +19290 -0.171051025390625 +19291 -0.33740234375 +19292 -0.47198486328125 +19293 -0.560394287109375 +19294 -0.58056640625 +19295 -0.54754638671875 +19296 -0.508575439453125 +19297 -0.459503173828125 +19298 -0.394378662109375 +19299 -0.35260009765625 +19300 -0.31170654296875 +19301 -0.197418212890625 +19302 -0.007965087890625 +19303 0.207489013671875 +19304 0.409210205078125 +19305 0.57208251953125 +19306 0.66595458984375 +19307 0.65875244140625 +19308 0.56744384765625 +19309 0.431396484375 +19310 0.29443359375 +19311 0.182464599609375 +19312 0.06365966796875 +19313 -0.075958251953125 +19314 -0.189422607421875 +19315 -0.271942138671875 +19316 -0.342529296875 +19317 -0.364166259765625 +19318 -0.327239990234375 +19319 -0.2769775390625 +19320 -0.253692626953125 +19321 -0.24365234375 +19322 -0.1983642578125 +19323 -0.116241455078125 +19324 -0.036834716796875 +19325 0.034881591796875 +19326 0.09124755859375 +19327 0.10888671875 +19328 0.125518798828125 +19329 0.15771484375 +19330 0.17828369140625 +19331 0.17108154296875 +19332 0.129974365234375 +19333 0.082427978515625 +19334 0.027679443359375 +19335 -0.065643310546875 +19336 -0.15936279296875 +19337 -0.21307373046875 +19338 -0.234649658203125 +19339 -0.2001953125 +19340 -0.119171142578125 +19341 -0.024749755859375 +19342 0.085784912109375 +19343 0.178131103515625 +19344 0.215576171875 +19345 0.211456298828125 +19346 0.17523193359375 +19347 0.128753662109375 +19348 0.1019287109375 +19349 0.0743408203125 +19350 0.04327392578125 +19351 0.038177490234375 +19352 0.076263427734375 +19353 0.14105224609375 +19354 0.186431884765625 +19355 0.188812255859375 +19356 0.1390380859375 +19357 0.041778564453125 +19358 -0.079437255859375 +19359 -0.219390869140625 +19360 -0.367828369140625 +19361 -0.494873046875 +19362 -0.556243896484375 +19363 -0.508697509765625 +19364 -0.3756103515625 +19365 -0.218902587890625 +19366 -0.063751220703125 +19367 0.091552734375 +19368 0.23602294921875 +19369 0.342987060546875 +19370 0.39520263671875 +19371 0.389373779296875 +19372 0.324249267578125 +19373 0.224090576171875 +19374 0.124267578125 +19375 0.037078857421875 +19376 -0.010101318359375 +19377 -0.019439697265625 +19378 -0.022796630859375 +19379 -0.001556396484375 +19380 0.056304931640625 +19381 0.106719970703125 +19382 0.096893310546875 +19383 0.042694091796875 +19384 -0.018035888671875 +19385 -0.07586669921875 +19386 -0.11944580078125 +19387 -0.15972900390625 +19388 -0.202606201171875 +19389 -0.24859619140625 +19390 -0.30517578125 +19391 -0.36212158203125 +19392 -0.39141845703125 +19393 -0.35528564453125 +19394 -0.249969482421875 +19395 -0.092864990234375 +19396 0.08905029296875 +19397 0.2352294921875 +19398 0.318817138671875 +19399 0.358642578125 +19400 0.347747802734375 +19401 0.28564453125 +19402 0.223175048828125 +19403 0.196746826171875 +19404 0.179840087890625 +19405 0.155548095703125 +19406 0.151214599609375 +19407 0.156951904296875 +19408 0.13177490234375 +19409 0.100799560546875 +19410 0.087127685546875 +19411 0.05487060546875 +19412 -0.009002685546875 +19413 -0.10400390625 +19414 -0.229400634765625 +19415 -0.35552978515625 +19416 -0.441925048828125 +19417 -0.473846435546875 +19418 -0.464813232421875 +19419 -0.419097900390625 +19420 -0.334320068359375 +19421 -0.227935791015625 +19422 -0.12347412109375 +19423 -0.02764892578125 +19424 0.077667236328125 +19425 0.2132568359375 +19426 0.38885498046875 +19427 0.582794189453125 +19428 0.734039306640625 +19429 0.800140380859375 +19430 0.7783203125 +19431 0.6651611328125 +19432 0.45965576171875 +19433 0.199188232421875 +19434 -0.050689697265625 +19435 -0.23297119140625 +19436 -0.33013916015625 +19437 -0.368408203125 +19438 -0.378936767578125 +19439 -0.376983642578125 +19440 -0.37969970703125 +19441 -0.391510009765625 +19442 -0.385345458984375 +19443 -0.3419189453125 +19444 -0.28289794921875 +19445 -0.251617431640625 +19446 -0.266143798828125 +19447 -0.273345947265625 +19448 -0.216796875 +19449 -0.128265380859375 +19450 -0.068145751953125 +19451 -0.0430908203125 +19452 -0.024444580078125 +19453 0.020721435546875 +19454 0.124481201171875 +19455 0.25787353515625 +19456 0.379119873046875 +19457 0.47991943359375 +19458 0.5281982421875 +19459 0.511138916015625 +19460 0.456207275390625 +19461 0.407470703125 +19462 0.383758544921875 +19463 0.35687255859375 +19464 0.31182861328125 +19465 0.250885009765625 +19466 0.1654052734375 +19467 0.035247802734375 +19468 -0.142059326171875 +19469 -0.33563232421875 +19470 -0.5345458984375 +19471 -0.72186279296875 +19472 -0.836669921875 +19473 -0.8326416015625 +19474 -0.7296142578125 +19475 -0.582550048828125 +19476 -0.440093994140625 +19477 -0.324310302734375 +19478 -0.20147705078125 +19479 -0.044647216796875 +19480 0.103973388671875 +19481 0.202392578125 +19482 0.264495849609375 +19483 0.338897705078125 +19484 0.443817138671875 +19485 0.545074462890625 +19486 0.6173095703125 +19487 0.6524658203125 +19488 0.66339111328125 +19489 0.6561279296875 +19490 0.606781005859375 +19491 0.501190185546875 +19492 0.352783203125 +19493 0.176544189453125 +19494 -0.034820556640625 +19495 -0.258209228515625 +19496 -0.44244384765625 +19497 -0.5753173828125 +19498 -0.65203857421875 +19499 -0.641632080078125 +19500 -0.562164306640625 +19501 -0.458038330078125 +19502 -0.350555419921875 +19503 -0.260528564453125 +19504 -0.192108154296875 +19505 -0.141937255859375 +19506 -0.1021728515625 +19507 -0.062896728515625 +19508 -0.011932373046875 +19509 0.062835693359375 +19510 0.148712158203125 +19511 0.241729736328125 +19512 0.34912109375 +19513 0.457305908203125 +19514 0.54388427734375 +19515 0.5728759765625 +19516 0.506591796875 +19517 0.351226806640625 +19518 0.146514892578125 +19519 -0.05523681640625 +19520 -0.21624755859375 +19521 -0.334930419921875 +19522 -0.402984619140625 +19523 -0.4412841796875 +19524 -0.49578857421875 +19525 -0.5601806640625 +19526 -0.600738525390625 +19527 -0.584228515625 +19528 -0.47930908203125 +19529 -0.27935791015625 +19530 -0.0089111328125 +19531 0.268798828125 +19532 0.482818603515625 +19533 0.60369873046875 +19534 0.650421142578125 +19535 0.66400146484375 +19536 0.6414794921875 +19537 0.572540283203125 +19538 0.498138427734375 +19539 0.439453125 +19540 0.375518798828125 +19541 0.274505615234375 +19542 0.1087646484375 +19543 -0.099395751953125 +19544 -0.3182373046875 +19545 -0.5489501953125 +19546 -0.7738037109375 +19547 -0.86383056640625 +19548 -0.870391845703125 +19549 -0.86895751953125 +19550 -0.861053466796875 +19551 -0.765869140625 +19552 -0.5301513671875 +19553 -0.214691162109375 +19554 0.137359619140625 +19555 0.474822998046875 +19556 0.76239013671875 +19557 0.867462158203125 +19558 0.870361328125 +19559 0.86480712890625 +19560 0.831817626953125 +19561 0.677581787109375 +19562 0.495880126953125 +19563 0.30767822265625 +19564 0.116180419921875 +19565 -0.110748291015625 +19566 -0.381805419921875 +19567 -0.6572265625 +19568 -0.857421875 +19569 -0.870391845703125 +19570 -0.870391845703125 +19571 -0.86444091796875 +19572 -0.85723876953125 +19573 -0.790008544921875 +19574 -0.62847900390625 +19575 -0.3956298828125 +19576 -0.126708984375 +19577 0.150115966796875 +19578 0.424041748046875 +19579 0.670623779296875 +19580 0.854522705078125 +19581 0.866485595703125 +19582 0.86920166015625 +19583 0.8653564453125 +19584 0.857147216796875 +19585 0.766845703125 +19586 0.628509521484375 +19587 0.462127685546875 +19588 0.297210693359375 +19589 0.14862060546875 +19590 -0.00537109375 +19591 -0.15753173828125 +19592 -0.31304931640625 +19593 -0.48876953125 +19594 -0.6416015625 +19595 -0.751373291015625 +19596 -0.84619140625 +19597 -0.861297607421875 +19598 -0.863250732421875 +19599 -0.856597900390625 +19600 -0.7498779296875 +19601 -0.624542236328125 +19602 -0.47808837890625 +19603 -0.253387451171875 +19604 0.003692626953125 +19605 0.2257080078125 +19606 0.427154541015625 +19607 0.643218994140625 +19608 0.855926513671875 +19609 0.870361328125 +19610 0.870361328125 +19611 0.862762451171875 +19612 0.79669189453125 +19613 0.595794677734375 +19614 0.362152099609375 +19615 0.1270751953125 +19616 -0.086944580078125 +19617 -0.2784423828125 +19618 -0.484832763671875 +19619 -0.729583740234375 +19620 -0.86688232421875 +19621 -0.870391845703125 +19622 -0.86859130859375 +19623 -0.86279296875 +19624 -0.817962646484375 +19625 -0.6116943359375 +19626 -0.3128662109375 +19627 0.039398193359375 +19628 0.422821044921875 +19629 0.805145263671875 +19630 0.870361328125 +19631 0.870361328125 +19632 0.860015869140625 +19633 0.727935791015625 +19634 0.48114013671875 +19635 0.2059326171875 +19636 -0.06103515625 +19637 -0.29913330078125 +19638 -0.516204833984375 +19639 -0.7252197265625 +19640 -0.85980224609375 +19641 -0.870391845703125 +19642 -0.870391845703125 +19643 -0.858062744140625 +19644 -0.673004150390625 +19645 -0.42694091796875 +19646 -0.2100830078125 +19647 -0.0362548828125 +19648 0.10943603515625 +19649 0.23516845703125 +19650 0.373687744140625 +19651 0.517791748046875 +19652 0.602783203125 +19653 0.635711669921875 +19654 0.655181884765625 +19655 0.65948486328125 +19656 0.651275634765625 +19657 0.61846923828125 +19658 0.53753662109375 +19659 0.404144287109375 +19660 0.22186279296875 +19661 0.003997802734375 +19662 -0.22100830078125 +19663 -0.42449951171875 +19664 -0.579833984375 +19665 -0.641876220703125 +19666 -0.6177978515625 +19667 -0.575531005859375 +19668 -0.526336669921875 +19669 -0.42645263671875 +19670 -0.2581787109375 +19671 -0.068695068359375 +19672 0.09222412109375 +19673 0.232147216796875 +19674 0.3509521484375 +19675 0.410064697265625 +19676 0.372955322265625 +19677 0.2554931640625 +19678 0.10711669921875 +19679 -0.052886962890625 +19680 -0.186279296875 +19681 -0.23291015625 +19682 -0.209442138671875 +19683 -0.174163818359375 +19684 -0.126739501953125 +19685 -0.048126220703125 +19686 0.0426025390625 +19687 0.10748291015625 +19688 0.1409912109375 +19689 0.19708251953125 +19690 0.273651123046875 +19691 0.31768798828125 +19692 0.341094970703125 +19693 0.368011474609375 +19694 0.37249755859375 +19695 0.30072021484375 +19696 0.1517333984375 +19697 -0.01470947265625 +19698 -0.1883544921875 +19699 -0.372711181640625 +19700 -0.51397705078125 +19701 -0.57177734375 +19702 -0.53948974609375 +19703 -0.43511962890625 +19704 -0.2962646484375 +19705 -0.161102294921875 +19706 -0.0435791015625 +19707 0.060394287109375 +19708 0.13665771484375 +19709 0.170135498046875 +19710 0.16552734375 +19711 0.15728759765625 +19712 0.150787353515625 +19713 0.12200927734375 +19714 0.080108642578125 +19715 0.05126953125 +19716 0.062896728515625 +19717 0.09271240234375 +19718 0.092987060546875 +19719 0.07855224609375 +19720 0.06427001953125 +19721 0.0347900390625 +19722 -0.01171875 +19723 -0.056060791015625 +19724 -0.055511474609375 +19725 -0.010467529296875 +19726 0.02508544921875 +19727 0.025665283203125 +19728 0.017333984375 +19729 0.00189208984375 +19730 -0.03173828125 +19731 -0.071502685546875 +19732 -0.13543701171875 +19733 -0.219970703125 +19734 -0.300506591796875 +19735 -0.376312255859375 +19736 -0.416107177734375 +19737 -0.371124267578125 +19738 -0.242279052734375 +19739 -0.069732666015625 +19740 0.125640869140625 +19741 0.31268310546875 +19742 0.45501708984375 +19743 0.554779052734375 +19744 0.61065673828125 +19745 0.610931396484375 +19746 0.531463623046875 +19747 0.3883056640625 +19748 0.23468017578125 +19749 0.095245361328125 +19750 -0.00396728515625 +19751 -0.04852294921875 +19752 -0.055145263671875 +19753 -0.0758056640625 +19754 -0.138702392578125 +19755 -0.209197998046875 +19756 -0.289031982421875 +19757 -0.37884521484375 +19758 -0.456329345703125 +19759 -0.51641845703125 +19760 -0.519287109375 +19761 -0.458251953125 +19762 -0.384796142578125 +19763 -0.323699951171875 +19764 -0.269287109375 +19765 -0.1951904296875 +19766 -0.100006103515625 +19767 -0.01055908203125 +19768 0.1033935546875 +19769 0.24908447265625 +19770 0.373199462890625 +19771 0.45806884765625 +19772 0.511474609375 +19773 0.565399169921875 +19774 0.61138916015625 +19775 0.5897216796875 +19776 0.4906005859375 +19777 0.33148193359375 +19778 0.147796630859375 +19779 -0.01873779296875 +19780 -0.140289306640625 +19781 -0.191986083984375 +19782 -0.184295654296875 +19783 -0.161834716796875 +19784 -0.166595458984375 +19785 -0.19390869140625 +19786 -0.22442626953125 +19787 -0.279754638671875 +19788 -0.3389892578125 +19789 -0.3543701171875 +19790 -0.348175048828125 +19791 -0.32598876953125 +19792 -0.2581787109375 +19793 -0.139801025390625 +19794 0.014617919921875 +19795 0.144378662109375 +19796 0.221038818359375 +19797 0.27069091796875 +19798 0.294036865234375 +19799 0.311767578125 +19800 0.339141845703125 +19801 0.360260009765625 +19802 0.360504150390625 +19803 0.308380126953125 +19804 0.18170166015625 +19805 0.0047607421875 +19806 -0.17559814453125 +19807 -0.3143310546875 +19808 -0.36785888671875 +19809 -0.36248779296875 +19810 -0.343536376953125 +19811 -0.3018798828125 +19812 -0.231414794921875 +19813 -0.117645263671875 +19814 0.007049560546875 +19815 0.087982177734375 +19816 0.13946533203125 +19817 0.17425537109375 +19818 0.188201904296875 +19819 0.171234130859375 +19820 0.118438720703125 +19821 0.05706787109375 +19822 -0.010711669921875 +19823 -0.0914306640625 +19824 -0.162322998046875 +19825 -0.194549560546875 +19826 -0.1492919921875 +19827 -0.02166748046875 +19828 0.124053955078125 +19829 0.211151123046875 +19830 0.240447998046875 +19831 0.242218017578125 +19832 0.2257080078125 +19833 0.194366455078125 +19834 0.115509033203125 +19835 0.0128173828125 +19836 -0.053802490234375 +19837 -0.110626220703125 +19838 -0.199493408203125 +19839 -0.29437255859375 +19840 -0.33221435546875 +19841 -0.27972412109375 +19842 -0.185333251953125 +19843 -0.128204345703125 +19844 -0.115692138671875 +19845 -0.116455078125 +19846 -0.105926513671875 +19847 -0.053955078125 +19848 0.048797607421875 +19849 0.157318115234375 +19850 0.212005615234375 +19851 0.218475341796875 +19852 0.23724365234375 +19853 0.30535888671875 +19854 0.38128662109375 +19855 0.404449462890625 +19856 0.3944091796875 +19857 0.3885498046875 +19858 0.362640380859375 +19859 0.27362060546875 +19860 0.11712646484375 +19861 -0.054901123046875 +19862 -0.19085693359375 +19863 -0.28570556640625 +19864 -0.339263916015625 +19865 -0.3775634765625 +19866 -0.445709228515625 +19867 -0.535064697265625 +19868 -0.629058837890625 +19869 -0.697601318359375 +19870 -0.70391845703125 +19871 -0.6424560546875 +19872 -0.491241455078125 +19873 -0.265716552734375 +19874 -0.023712158203125 +19875 0.201751708984375 +19876 0.375823974609375 +19877 0.485076904296875 +19878 0.56884765625 +19879 0.634765625 +19880 0.63763427734375 +19881 0.5660400390625 +19882 0.4720458984375 +19883 0.40692138671875 +19884 0.3778076171875 +19885 0.376953125 +19886 0.371978759765625 +19887 0.313140869140625 +19888 0.184417724609375 +19889 0.011199951171875 +19890 -0.171051025390625 +19891 -0.33740234375 +19892 -0.47198486328125 +19893 -0.560394287109375 +19894 -0.58056640625 +19895 -0.54754638671875 +19896 -0.508575439453125 +19897 -0.459503173828125 +19898 -0.394378662109375 +19899 -0.35260009765625 +19900 -0.31170654296875 +19901 -0.197418212890625 +19902 -0.007965087890625 +19903 0.207489013671875 +19904 0.409210205078125 +19905 0.57208251953125 +19906 0.66595458984375 +19907 0.65875244140625 +19908 0.56744384765625 +19909 0.431396484375 +19910 0.29443359375 +19911 0.182464599609375 +19912 0.06365966796875 +19913 -0.075958251953125 +19914 -0.189422607421875 +19915 -0.271942138671875 +19916 -0.342529296875 +19917 -0.364166259765625 +19918 -0.327239990234375 +19919 -0.2769775390625 +19920 -0.253692626953125 +19921 -0.24365234375 +19922 -0.1983642578125 +19923 -0.116241455078125 +19924 -0.036834716796875 +19925 0.034881591796875 +19926 0.09124755859375 +19927 0.10888671875 +19928 0.125518798828125 +19929 0.15771484375 +19930 0.17828369140625 +19931 0.17108154296875 +19932 0.129974365234375 +19933 0.082427978515625 +19934 0.027679443359375 +19935 -0.065643310546875 +19936 -0.15936279296875 +19937 -0.21307373046875 +19938 -0.234649658203125 +19939 -0.2001953125 +19940 -0.119171142578125 +19941 -0.024749755859375 +19942 0.085784912109375 +19943 0.178131103515625 +19944 0.215576171875 +19945 0.211456298828125 +19946 0.17523193359375 +19947 0.128753662109375 +19948 0.1019287109375 +19949 0.0743408203125 +19950 0.04327392578125 +19951 0.038177490234375 +19952 0.076263427734375 +19953 0.14105224609375 +19954 0.186431884765625 +19955 0.188812255859375 +19956 0.1390380859375 +19957 0.041778564453125 +19958 -0.079437255859375 +19959 -0.219390869140625 +19960 -0.367828369140625 +19961 -0.494873046875 +19962 -0.556243896484375 +19963 -0.508697509765625 +19964 -0.3756103515625 +19965 -0.218902587890625 +19966 -0.063751220703125 +19967 0.091552734375 +19968 0.23602294921875 +19969 0.342987060546875 +19970 0.39520263671875 +19971 0.389373779296875 +19972 0.324249267578125 +19973 0.224090576171875 +19974 0.124267578125 +19975 0.037078857421875 +19976 -0.010101318359375 +19977 -0.019439697265625 +19978 -0.022796630859375 +19979 -0.001556396484375 +19980 0.056304931640625 +19981 0.106719970703125 +19982 0.096893310546875 +19983 0.042694091796875 +19984 -0.018035888671875 +19985 -0.07586669921875 +19986 -0.11944580078125 +19987 -0.15972900390625 +19988 -0.202606201171875 +19989 -0.24859619140625 +19990 -0.30517578125 +19991 -0.36212158203125 +19992 -0.39141845703125 +19993 -0.35528564453125 +19994 -0.249969482421875 +19995 -0.092864990234375 +19996 0.08905029296875 +19997 0.2352294921875 +19998 0.318817138671875 +19999 0.358642578125 +20000 0.347747802734375 +20001 0.28564453125 +20002 0.223175048828125 +20003 0.196746826171875 +20004 0.179840087890625 +20005 0.155548095703125 +20006 0.151214599609375 +20007 0.156951904296875 +20008 0.13177490234375 +20009 0.100799560546875 +20010 0.087127685546875 +20011 0.05487060546875 +20012 -0.009002685546875 +20013 -0.10400390625 +20014 -0.229400634765625 +20015 -0.35552978515625 +20016 -0.441925048828125 +20017 -0.473846435546875 +20018 -0.464813232421875 +20019 -0.419097900390625 +20020 -0.334320068359375 +20021 -0.227935791015625 +20022 -0.12347412109375 +20023 -0.02764892578125 +20024 0.077667236328125 +20025 0.2132568359375 +20026 0.38885498046875 +20027 0.582794189453125 +20028 0.734039306640625 +20029 0.800140380859375 +20030 0.7783203125 +20031 0.6651611328125 +20032 0.45965576171875 +20033 0.199188232421875 +20034 -0.050689697265625 +20035 -0.23297119140625 +20036 -0.33013916015625 +20037 -0.368408203125 +20038 -0.378936767578125 +20039 -0.376983642578125 +20040 -0.37969970703125 +20041 -0.391510009765625 +20042 -0.385345458984375 +20043 -0.3419189453125 +20044 -0.28289794921875 +20045 -0.251617431640625 +20046 -0.266143798828125 +20047 -0.273345947265625 +20048 -0.216796875 +20049 -0.128265380859375 +20050 -0.068145751953125 +20051 -0.0430908203125 +20052 -0.024444580078125 +20053 0.020721435546875 +20054 0.124481201171875 +20055 0.25787353515625 +20056 0.379119873046875 +20057 0.47991943359375 +20058 0.5281982421875 +20059 0.511138916015625 +20060 0.456207275390625 +20061 0.407470703125 +20062 0.383758544921875 +20063 0.35687255859375 +20064 0.31182861328125 +20065 0.250885009765625 +20066 0.1654052734375 +20067 0.035247802734375 +20068 -0.142059326171875 +20069 -0.33563232421875 +20070 -0.5345458984375 +20071 -0.72186279296875 +20072 -0.836669921875 +20073 -0.8326416015625 +20074 -0.7296142578125 +20075 -0.582550048828125 +20076 -0.440093994140625 +20077 -0.324310302734375 +20078 -0.20147705078125 +20079 -0.044647216796875 +20080 0.103973388671875 +20081 0.202392578125 +20082 0.264495849609375 +20083 0.338897705078125 +20084 0.443817138671875 +20085 0.545074462890625 +20086 0.6173095703125 +20087 0.6524658203125 +20088 0.66339111328125 +20089 0.6561279296875 +20090 0.606781005859375 +20091 0.501190185546875 +20092 0.352783203125 +20093 0.176544189453125 +20094 -0.034820556640625 +20095 -0.258209228515625 +20096 -0.44244384765625 +20097 -0.5753173828125 +20098 -0.65203857421875 +20099 -0.641632080078125 +20100 -0.562164306640625 +20101 -0.458038330078125 +20102 -0.350555419921875 +20103 -0.260528564453125 +20104 -0.192108154296875 +20105 -0.141937255859375 +20106 -0.1021728515625 +20107 -0.062896728515625 +20108 -0.011932373046875 +20109 0.062835693359375 +20110 0.148712158203125 +20111 0.241729736328125 +20112 0.34912109375 +20113 0.457305908203125 +20114 0.54388427734375 +20115 0.5728759765625 +20116 0.506591796875 +20117 0.351226806640625 +20118 0.146514892578125 +20119 -0.05523681640625 +20120 -0.21624755859375 +20121 -0.334930419921875 +20122 -0.402984619140625 +20123 -0.4412841796875 +20124 -0.49578857421875 +20125 -0.5601806640625 +20126 -0.600738525390625 +20127 -0.584228515625 +20128 -0.47930908203125 +20129 -0.27935791015625 +20130 -0.0089111328125 +20131 0.268798828125 +20132 0.482818603515625 +20133 0.60369873046875 +20134 0.650421142578125 +20135 0.66400146484375 +20136 0.6414794921875 +20137 0.572540283203125 +20138 0.498138427734375 +20139 0.439453125 +20140 0.375518798828125 +20141 0.274505615234375 +20142 0.1087646484375 +20143 -0.099395751953125 +20144 -0.3182373046875 +20145 -0.5489501953125 +20146 -0.7738037109375 +20147 -0.86383056640625 +20148 -0.870391845703125 +20149 -0.86895751953125 +20150 -0.861053466796875 +20151 -0.765869140625 +20152 -0.5301513671875 +20153 -0.214691162109375 +20154 0.137359619140625 +20155 0.474822998046875 +20156 0.76239013671875 +20157 0.867462158203125 +20158 0.870361328125 +20159 0.86480712890625 +20160 0.831817626953125 +20161 0.677581787109375 +20162 0.495880126953125 +20163 0.30767822265625 +20164 0.116180419921875 +20165 -0.110748291015625 +20166 -0.381805419921875 +20167 -0.6572265625 +20168 -0.857421875 +20169 -0.870391845703125 +20170 -0.870391845703125 +20171 -0.86444091796875 +20172 -0.85723876953125 +20173 -0.790008544921875 +20174 -0.62847900390625 +20175 -0.3956298828125 +20176 -0.126708984375 +20177 0.150115966796875 +20178 0.424041748046875 +20179 0.670623779296875 +20180 0.854522705078125 +20181 0.866485595703125 +20182 0.86920166015625 +20183 0.8653564453125 +20184 0.857147216796875 +20185 0.766845703125 +20186 0.628509521484375 +20187 0.462127685546875 +20188 0.297210693359375 +20189 0.14862060546875 +20190 -0.00537109375 +20191 -0.15753173828125 +20192 -0.31304931640625 +20193 -0.48876953125 +20194 -0.6416015625 +20195 -0.751373291015625 +20196 -0.84619140625 +20197 -0.861297607421875 +20198 -0.863250732421875 +20199 -0.856597900390625 +20200 -0.7498779296875 +20201 -0.624542236328125 +20202 -0.47808837890625 +20203 -0.253387451171875 +20204 0.003692626953125 +20205 0.2257080078125 +20206 0.427154541015625 +20207 0.643218994140625 +20208 0.855926513671875 +20209 0.870361328125 +20210 0.870361328125 +20211 0.862762451171875 +20212 0.79669189453125 +20213 0.595794677734375 +20214 0.362152099609375 +20215 0.1270751953125 +20216 -0.086944580078125 +20217 -0.2784423828125 +20218 -0.484832763671875 +20219 -0.729583740234375 +20220 -0.86688232421875 +20221 -0.870391845703125 +20222 -0.86859130859375 +20223 -0.86279296875 +20224 -0.817962646484375 +20225 -0.6116943359375 +20226 -0.3128662109375 +20227 0.039398193359375 +20228 0.422821044921875 +20229 0.805145263671875 +20230 0.870361328125 +20231 0.870361328125 +20232 0.860015869140625 +20233 0.727935791015625 +20234 0.48114013671875 +20235 0.2059326171875 +20236 -0.06103515625 +20237 -0.29913330078125 +20238 -0.516204833984375 +20239 -0.7252197265625 +20240 -0.85980224609375 +20241 -0.870391845703125 +20242 -0.870391845703125 +20243 -0.858062744140625 +20244 -0.673004150390625 +20245 -0.42694091796875 +20246 -0.2100830078125 +20247 -0.0362548828125 +20248 0.10943603515625 +20249 0.23516845703125 +20250 0.373687744140625 +20251 0.517791748046875 +20252 0.602783203125 +20253 0.635711669921875 +20254 0.655181884765625 +20255 0.65948486328125 +20256 0.651275634765625 +20257 0.61846923828125 +20258 0.53753662109375 +20259 0.404144287109375 +20260 0.22186279296875 +20261 0.003997802734375 +20262 -0.22100830078125 +20263 -0.42449951171875 +20264 -0.579833984375 +20265 -0.641876220703125 +20266 -0.6177978515625 +20267 -0.575531005859375 +20268 -0.526336669921875 +20269 -0.42645263671875 +20270 -0.2581787109375 +20271 -0.068695068359375 +20272 0.09222412109375 +20273 0.232147216796875 +20274 0.3509521484375 +20275 0.410064697265625 +20276 0.372955322265625 +20277 0.2554931640625 +20278 0.10711669921875 +20279 -0.052886962890625 +20280 -0.186279296875 +20281 -0.23291015625 +20282 -0.209442138671875 +20283 -0.174163818359375 +20284 -0.126739501953125 +20285 -0.048126220703125 +20286 0.0426025390625 +20287 0.10748291015625 +20288 0.1409912109375 +20289 0.19708251953125 +20290 0.273651123046875 +20291 0.31768798828125 +20292 0.341094970703125 +20293 0.368011474609375 +20294 0.37249755859375 +20295 0.30072021484375 +20296 0.1517333984375 +20297 -0.01470947265625 +20298 -0.1883544921875 +20299 -0.372711181640625 +20300 -0.51397705078125 +20301 -0.57177734375 +20302 -0.53948974609375 +20303 -0.43511962890625 +20304 -0.2962646484375 +20305 -0.161102294921875 +20306 -0.0435791015625 +20307 0.060394287109375 +20308 0.13665771484375 +20309 0.170135498046875 +20310 0.16552734375 +20311 0.15728759765625 +20312 0.150787353515625 +20313 0.12200927734375 +20314 0.080108642578125 +20315 0.05126953125 +20316 0.062896728515625 +20317 0.09271240234375 +20318 0.092987060546875 +20319 0.07855224609375 +20320 0.06427001953125 +20321 0.0347900390625 +20322 -0.01171875 +20323 -0.056060791015625 +20324 -0.055511474609375 +20325 -0.010467529296875 +20326 0.02508544921875 +20327 0.025665283203125 +20328 0.017333984375 +20329 0.00189208984375 +20330 -0.03173828125 +20331 -0.071502685546875 +20332 -0.13543701171875 +20333 -0.219970703125 +20334 -0.300506591796875 +20335 -0.376312255859375 +20336 -0.416107177734375 +20337 -0.371124267578125 +20338 -0.242279052734375 +20339 -0.069732666015625 +20340 0.125640869140625 +20341 0.31268310546875 +20342 0.45501708984375 +20343 0.554779052734375 +20344 0.61065673828125 +20345 0.610931396484375 +20346 0.531463623046875 +20347 0.3883056640625 +20348 0.23468017578125 +20349 0.095245361328125 +20350 -0.00396728515625 +20351 -0.04852294921875 +20352 -0.055145263671875 +20353 -0.0758056640625 +20354 -0.138702392578125 +20355 -0.209197998046875 +20356 -0.289031982421875 +20357 -0.37884521484375 +20358 -0.456329345703125 +20359 -0.51641845703125 +20360 -0.519287109375 +20361 -0.458251953125 +20362 -0.384796142578125 +20363 -0.323699951171875 +20364 -0.269287109375 +20365 -0.1951904296875 +20366 -0.100006103515625 +20367 -0.01055908203125 +20368 0.1033935546875 +20369 0.24908447265625 +20370 0.373199462890625 +20371 0.45806884765625 +20372 0.511474609375 +20373 0.565399169921875 +20374 0.61138916015625 +20375 0.5897216796875 +20376 0.4906005859375 +20377 0.33148193359375 +20378 0.147796630859375 +20379 -0.01873779296875 +20380 -0.140289306640625 +20381 -0.191986083984375 +20382 -0.184295654296875 +20383 -0.161834716796875 +20384 -0.166595458984375 +20385 -0.19390869140625 +20386 -0.22442626953125 +20387 -0.279754638671875 +20388 -0.3389892578125 +20389 -0.3543701171875 +20390 -0.348175048828125 +20391 -0.32598876953125 +20392 -0.2581787109375 +20393 -0.139801025390625 +20394 0.014617919921875 +20395 0.144378662109375 +20396 0.221038818359375 +20397 0.27069091796875 +20398 0.294036865234375 +20399 0.311767578125 +20400 0.339141845703125 +20401 0.360260009765625 +20402 0.360504150390625 +20403 0.308380126953125 +20404 0.18170166015625 +20405 0.0047607421875 +20406 -0.17559814453125 +20407 -0.3143310546875 +20408 -0.36785888671875 +20409 -0.36248779296875 +20410 -0.343536376953125 +20411 -0.3018798828125 +20412 -0.231414794921875 +20413 -0.117645263671875 +20414 0.007049560546875 +20415 0.087982177734375 +20416 0.13946533203125 +20417 0.17425537109375 +20418 0.188201904296875 +20419 0.171234130859375 +20420 0.118438720703125 +20421 0.05706787109375 +20422 -0.010711669921875 +20423 -0.0914306640625 +20424 -0.162322998046875 +20425 -0.194549560546875 +20426 -0.1492919921875 +20427 -0.02166748046875 +20428 0.124053955078125 +20429 0.211151123046875 +20430 0.240447998046875 +20431 0.242218017578125 +20432 0.2257080078125 +20433 0.194366455078125 +20434 0.115509033203125 +20435 0.0128173828125 +20436 -0.053802490234375 +20437 -0.110626220703125 +20438 -0.199493408203125 +20439 -0.29437255859375 +20440 -0.33221435546875 +20441 -0.27972412109375 +20442 -0.185333251953125 +20443 -0.128204345703125 +20444 -0.115692138671875 +20445 -0.116455078125 +20446 -0.105926513671875 +20447 -0.053955078125 +20448 0.048797607421875 +20449 0.157318115234375 +20450 0.212005615234375 +20451 0.218475341796875 +20452 0.23724365234375 +20453 0.30535888671875 +20454 0.38128662109375 +20455 0.404449462890625 +20456 0.3944091796875 +20457 0.3885498046875 +20458 0.362640380859375 +20459 0.27362060546875 +20460 0.11712646484375 +20461 -0.054901123046875 +20462 -0.19085693359375 +20463 -0.28570556640625 +20464 -0.339263916015625 +20465 -0.3775634765625 +20466 -0.445709228515625 +20467 -0.535064697265625 +20468 -0.629058837890625 +20469 -0.697601318359375 +20470 -0.70391845703125 +20471 -0.6424560546875 +20472 -0.491241455078125 +20473 -0.265716552734375 +20474 -0.023712158203125 +20475 0.201751708984375 +20476 0.375823974609375 +20477 0.485076904296875 +20478 0.56884765625 +20479 0.634765625 +20480 0.63763427734375 +20481 0.5660400390625 +20482 0.4720458984375 +20483 0.40692138671875 +20484 0.3778076171875 +20485 0.376953125 +20486 0.371978759765625 +20487 0.313140869140625 +20488 0.184417724609375 +20489 0.011199951171875 +20490 -0.171051025390625 +20491 -0.33740234375 +20492 -0.47198486328125 +20493 -0.560394287109375 +20494 -0.58056640625 +20495 -0.54754638671875 +20496 -0.508575439453125 +20497 -0.459503173828125 +20498 -0.394378662109375 +20499 -0.35260009765625 +20500 -0.31170654296875 +20501 -0.197418212890625 +20502 -0.007965087890625 +20503 0.207489013671875 +20504 0.409210205078125 +20505 0.57208251953125 +20506 0.66595458984375 +20507 0.65875244140625 +20508 0.56744384765625 +20509 0.431396484375 +20510 0.29443359375 +20511 0.182464599609375 +20512 0.06365966796875 +20513 -0.075958251953125 +20514 -0.189422607421875 +20515 -0.271942138671875 +20516 -0.342529296875 +20517 -0.364166259765625 +20518 -0.327239990234375 +20519 -0.2769775390625 +20520 -0.253692626953125 +20521 -0.24365234375 +20522 -0.1983642578125 +20523 -0.116241455078125 +20524 -0.036834716796875 +20525 0.034881591796875 +20526 0.09124755859375 +20527 0.10888671875 +20528 0.125518798828125 +20529 0.15771484375 +20530 0.17828369140625 +20531 0.17108154296875 +20532 0.129974365234375 +20533 0.082427978515625 +20534 0.027679443359375 +20535 -0.065643310546875 +20536 -0.15936279296875 +20537 -0.21307373046875 +20538 -0.234649658203125 +20539 -0.2001953125 +20540 -0.119171142578125 +20541 -0.024749755859375 +20542 0.085784912109375 +20543 0.178131103515625 +20544 0.215576171875 +20545 0.211456298828125 +20546 0.17523193359375 +20547 0.128753662109375 +20548 0.1019287109375 +20549 0.0743408203125 +20550 0.04327392578125 +20551 0.038177490234375 +20552 0.076263427734375 +20553 0.14105224609375 +20554 0.186431884765625 +20555 0.188812255859375 +20556 0.1390380859375 +20557 0.041778564453125 +20558 -0.079437255859375 +20559 -0.219390869140625 +20560 -0.367828369140625 +20561 -0.494873046875 +20562 -0.556243896484375 +20563 -0.508697509765625 +20564 -0.3756103515625 +20565 -0.218902587890625 +20566 -0.063751220703125 +20567 0.091552734375 +20568 0.23602294921875 +20569 0.342987060546875 +20570 0.39520263671875 +20571 0.389373779296875 +20572 0.324249267578125 +20573 0.224090576171875 +20574 0.124267578125 +20575 0.037078857421875 +20576 -0.010101318359375 +20577 -0.019439697265625 +20578 -0.022796630859375 +20579 -0.001556396484375 +20580 0.056304931640625 +20581 0.106719970703125 +20582 0.096893310546875 +20583 0.042694091796875 +20584 -0.018035888671875 +20585 -0.07586669921875 +20586 -0.11944580078125 +20587 -0.15972900390625 +20588 -0.202606201171875 +20589 -0.24859619140625 +20590 -0.30517578125 +20591 -0.36212158203125 +20592 -0.39141845703125 +20593 -0.35528564453125 +20594 -0.249969482421875 +20595 -0.092864990234375 +20596 0.08905029296875 +20597 0.2352294921875 +20598 0.318817138671875 +20599 0.358642578125 +20600 0.347747802734375 +20601 0.28564453125 +20602 0.223175048828125 +20603 0.196746826171875 +20604 0.179840087890625 +20605 0.155548095703125 +20606 0.151214599609375 +20607 0.156951904296875 +20608 0.13177490234375 +20609 0.100799560546875 +20610 0.087127685546875 +20611 0.05487060546875 +20612 -0.009002685546875 +20613 -0.10400390625 +20614 -0.229400634765625 +20615 -0.35552978515625 +20616 -0.441925048828125 +20617 -0.473846435546875 +20618 -0.464813232421875 +20619 -0.419097900390625 +20620 -0.334320068359375 +20621 -0.227935791015625 +20622 -0.12347412109375 +20623 -0.02764892578125 +20624 0.077667236328125 +20625 0.2132568359375 +20626 0.38885498046875 +20627 0.582794189453125 +20628 0.734039306640625 +20629 0.800140380859375 +20630 0.7783203125 +20631 0.6651611328125 +20632 0.45965576171875 +20633 0.199188232421875 +20634 -0.050689697265625 +20635 -0.23297119140625 +20636 -0.33013916015625 +20637 -0.368408203125 +20638 -0.378936767578125 +20639 -0.376983642578125 +20640 -0.37969970703125 +20641 -0.391510009765625 +20642 -0.385345458984375 +20643 -0.3419189453125 +20644 -0.28289794921875 +20645 -0.251617431640625 +20646 -0.266143798828125 +20647 -0.273345947265625 +20648 -0.216796875 +20649 -0.128265380859375 +20650 -0.068145751953125 +20651 -0.0430908203125 +20652 -0.024444580078125 +20653 0.020721435546875 +20654 0.124481201171875 +20655 0.25787353515625 +20656 0.379119873046875 +20657 0.47991943359375 +20658 0.5281982421875 +20659 0.511138916015625 +20660 0.456207275390625 +20661 0.407470703125 +20662 0.383758544921875 +20663 0.35687255859375 +20664 0.31182861328125 +20665 0.250885009765625 +20666 0.1654052734375 +20667 0.035247802734375 +20668 -0.142059326171875 +20669 -0.33563232421875 +20670 -0.5345458984375 +20671 -0.72186279296875 +20672 -0.836669921875 +20673 -0.8326416015625 +20674 -0.7296142578125 +20675 -0.582550048828125 +20676 -0.440093994140625 +20677 -0.324310302734375 +20678 -0.20147705078125 +20679 -0.044647216796875 +20680 0.103973388671875 +20681 0.202392578125 +20682 0.264495849609375 +20683 0.338897705078125 +20684 0.443817138671875 +20685 0.545074462890625 +20686 0.6173095703125 +20687 0.6524658203125 +20688 0.66339111328125 +20689 0.6561279296875 +20690 0.606781005859375 +20691 0.501190185546875 +20692 0.352783203125 +20693 0.176544189453125 +20694 -0.034820556640625 +20695 -0.258209228515625 +20696 -0.44244384765625 +20697 -0.5753173828125 +20698 -0.65203857421875 +20699 -0.641632080078125 +20700 -0.562164306640625 +20701 -0.458038330078125 +20702 -0.350555419921875 +20703 -0.260528564453125 +20704 -0.192108154296875 +20705 -0.141937255859375 +20706 -0.1021728515625 +20707 -0.062896728515625 +20708 -0.011932373046875 +20709 0.062835693359375 +20710 0.148712158203125 +20711 0.241729736328125 +20712 0.34912109375 +20713 0.457305908203125 +20714 0.54388427734375 +20715 0.5728759765625 +20716 0.506591796875 +20717 0.351226806640625 +20718 0.146514892578125 +20719 -0.05523681640625 +20720 -0.21624755859375 +20721 -0.334930419921875 +20722 -0.402984619140625 +20723 -0.4412841796875 +20724 -0.49578857421875 +20725 -0.5601806640625 +20726 -0.600738525390625 +20727 -0.584228515625 +20728 -0.47930908203125 +20729 -0.27935791015625 +20730 -0.0089111328125 +20731 0.268798828125 +20732 0.482818603515625 +20733 0.60369873046875 +20734 0.650421142578125 +20735 0.66400146484375 +20736 0.6414794921875 +20737 0.572540283203125 +20738 0.498138427734375 +20739 0.439453125 +20740 0.375518798828125 +20741 0.274505615234375 +20742 0.1087646484375 +20743 -0.099395751953125 +20744 -0.3182373046875 +20745 -0.5489501953125 +20746 -0.7738037109375 +20747 -0.86383056640625 +20748 -0.870391845703125 +20749 -0.86895751953125 +20750 -0.861053466796875 +20751 -0.765869140625 +20752 -0.5301513671875 +20753 -0.214691162109375 +20754 0.137359619140625 +20755 0.474822998046875 +20756 0.76239013671875 +20757 0.867462158203125 +20758 0.870361328125 +20759 0.86480712890625 +20760 0.831817626953125 +20761 0.677581787109375 +20762 0.495880126953125 +20763 0.30767822265625 +20764 0.116180419921875 +20765 -0.110748291015625 +20766 -0.381805419921875 +20767 -0.6572265625 +20768 -0.857421875 +20769 -0.870391845703125 +20770 -0.870391845703125 +20771 -0.86444091796875 +20772 -0.85723876953125 +20773 -0.790008544921875 +20774 -0.62847900390625 +20775 -0.3956298828125 +20776 -0.126708984375 +20777 0.150115966796875 +20778 0.424041748046875 +20779 0.670623779296875 +20780 0.854522705078125 +20781 0.866485595703125 +20782 0.86920166015625 +20783 0.8653564453125 +20784 0.857147216796875 +20785 0.766845703125 +20786 0.628509521484375 +20787 0.462127685546875 +20788 0.297210693359375 +20789 0.14862060546875 +20790 -0.00537109375 +20791 -0.15753173828125 +20792 -0.31304931640625 +20793 -0.48876953125 +20794 -0.6416015625 +20795 -0.751373291015625 +20796 -0.84619140625 +20797 -0.861297607421875 +20798 -0.863250732421875 +20799 -0.856597900390625 +20800 -0.7498779296875 +20801 -0.624542236328125 +20802 -0.47808837890625 +20803 -0.253387451171875 +20804 0.003692626953125 +20805 0.2257080078125 +20806 0.427154541015625 +20807 0.643218994140625 +20808 0.855926513671875 +20809 0.870361328125 +20810 0.870361328125 +20811 0.862762451171875 +20812 0.79669189453125 +20813 0.595794677734375 +20814 0.362152099609375 +20815 0.1270751953125 +20816 -0.086944580078125 +20817 -0.2784423828125 +20818 -0.484832763671875 +20819 -0.729583740234375 +20820 -0.86688232421875 +20821 -0.870391845703125 +20822 -0.86859130859375 +20823 -0.86279296875 +20824 -0.817962646484375 +20825 -0.6116943359375 +20826 -0.3128662109375 +20827 0.039398193359375 +20828 0.422821044921875 +20829 0.805145263671875 +20830 0.870361328125 +20831 0.870361328125 +20832 0.860015869140625 +20833 0.727935791015625 +20834 0.48114013671875 +20835 0.2059326171875 +20836 -0.06103515625 +20837 -0.29913330078125 +20838 -0.516204833984375 +20839 -0.7252197265625 +20840 -0.85980224609375 +20841 -0.870391845703125 +20842 -0.870391845703125 +20843 -0.858062744140625 +20844 -0.673004150390625 +20845 -0.42694091796875 +20846 -0.2100830078125 +20847 -0.0362548828125 +20848 0.10943603515625 +20849 0.23516845703125 +20850 0.373687744140625 +20851 0.517791748046875 +20852 0.602783203125 +20853 0.635711669921875 +20854 0.655181884765625 +20855 0.65948486328125 +20856 0.651275634765625 +20857 0.61846923828125 +20858 0.53753662109375 +20859 0.404144287109375 +20860 0.22186279296875 +20861 0.003997802734375 +20862 -0.22100830078125 +20863 -0.42449951171875 +20864 -0.579833984375 +20865 -0.641876220703125 +20866 -0.6177978515625 +20867 -0.575531005859375 +20868 -0.526336669921875 +20869 -0.42645263671875 +20870 -0.2581787109375 +20871 -0.068695068359375 +20872 0.09222412109375 +20873 0.232147216796875 +20874 0.3509521484375 +20875 0.410064697265625 +20876 0.372955322265625 +20877 0.2554931640625 +20878 0.10711669921875 +20879 -0.052886962890625 +20880 -0.186279296875 +20881 -0.23291015625 +20882 -0.209442138671875 +20883 -0.174163818359375 +20884 -0.126739501953125 +20885 -0.048126220703125 +20886 0.0426025390625 +20887 0.10748291015625 +20888 0.1409912109375 +20889 0.19708251953125 +20890 0.273651123046875 +20891 0.31768798828125 +20892 0.341094970703125 +20893 0.368011474609375 +20894 0.37249755859375 +20895 0.30072021484375 +20896 0.1517333984375 +20897 -0.01470947265625 +20898 -0.1883544921875 +20899 -0.372711181640625 +20900 -0.51397705078125 +20901 -0.57177734375 +20902 -0.53948974609375 +20903 -0.43511962890625 +20904 -0.2962646484375 +20905 -0.161102294921875 +20906 -0.0435791015625 +20907 0.060394287109375 +20908 0.13665771484375 +20909 0.170135498046875 +20910 0.16552734375 +20911 0.15728759765625 +20912 0.150787353515625 +20913 0.12200927734375 +20914 0.080108642578125 +20915 0.05126953125 +20916 0.062896728515625 +20917 0.09271240234375 +20918 0.092987060546875 +20919 0.07855224609375 +20920 0.06427001953125 +20921 0.0347900390625 +20922 -0.01171875 +20923 -0.056060791015625 +20924 -0.055511474609375 +20925 -0.010467529296875 +20926 0.02508544921875 +20927 0.025665283203125 +20928 0.017333984375 +20929 0.00189208984375 +20930 -0.03173828125 +20931 -0.071502685546875 +20932 -0.13543701171875 +20933 -0.219970703125 +20934 -0.300506591796875 +20935 -0.376312255859375 +20936 -0.416107177734375 +20937 -0.371124267578125 +20938 -0.242279052734375 +20939 -0.069732666015625 +20940 0.125640869140625 +20941 0.31268310546875 +20942 0.45501708984375 +20943 0.554779052734375 +20944 0.61065673828125 +20945 0.610931396484375 +20946 0.531463623046875 +20947 0.3883056640625 +20948 0.23468017578125 +20949 0.095245361328125 +20950 -0.00396728515625 +20951 -0.04852294921875 +20952 -0.055145263671875 +20953 -0.0758056640625 +20954 -0.138702392578125 +20955 -0.209197998046875 +20956 -0.289031982421875 +20957 -0.37884521484375 +20958 -0.456329345703125 +20959 -0.51641845703125 +20960 -0.519287109375 +20961 -0.458251953125 +20962 -0.384796142578125 +20963 -0.323699951171875 +20964 -0.269287109375 +20965 -0.1951904296875 +20966 -0.100006103515625 +20967 -0.01055908203125 +20968 0.1033935546875 +20969 0.24908447265625 +20970 0.373199462890625 +20971 0.45806884765625 +20972 0.511474609375 +20973 0.565399169921875 +20974 0.61138916015625 +20975 0.5897216796875 +20976 0.4906005859375 +20977 0.33148193359375 +20978 0.147796630859375 +20979 -0.01873779296875 +20980 -0.140289306640625 +20981 -0.191986083984375 +20982 -0.184295654296875 +20983 -0.161834716796875 +20984 -0.166595458984375 +20985 -0.19390869140625 +20986 -0.22442626953125 +20987 -0.279754638671875 +20988 -0.3389892578125 +20989 -0.3543701171875 +20990 -0.348175048828125 +20991 -0.32598876953125 +20992 -0.2581787109375 +20993 -0.139801025390625 +20994 0.014617919921875 +20995 0.144378662109375 +20996 0.221038818359375 +20997 0.27069091796875 +20998 0.294036865234375 +20999 0.311767578125 +21000 0.339141845703125 +21001 0.360260009765625 +21002 0.360504150390625 +21003 0.308380126953125 +21004 0.18170166015625 +21005 0.0047607421875 +21006 -0.17559814453125 +21007 -0.3143310546875 +21008 -0.36785888671875 +21009 -0.36248779296875 +21010 -0.343536376953125 +21011 -0.3018798828125 +21012 -0.231414794921875 +21013 -0.117645263671875 +21014 0.007049560546875 +21015 0.087982177734375 +21016 0.13946533203125 +21017 0.17425537109375 +21018 0.188201904296875 +21019 0.171234130859375 +21020 0.118438720703125 +21021 0.05706787109375 +21022 -0.010711669921875 +21023 -0.0914306640625 +21024 -0.162322998046875 +21025 -0.194549560546875 +21026 -0.1492919921875 +21027 -0.02166748046875 +21028 0.124053955078125 +21029 0.211151123046875 +21030 0.240447998046875 +21031 0.242218017578125 +21032 0.2257080078125 +21033 0.194366455078125 +21034 0.115509033203125 +21035 0.0128173828125 +21036 -0.053802490234375 +21037 -0.110626220703125 +21038 -0.199493408203125 +21039 -0.29437255859375 +21040 -0.33221435546875 +21041 -0.27972412109375 +21042 -0.185333251953125 +21043 -0.128204345703125 +21044 -0.115692138671875 +21045 -0.116455078125 +21046 -0.105926513671875 +21047 -0.053955078125 +21048 0.048797607421875 +21049 0.157318115234375 +21050 0.212005615234375 +21051 0.218475341796875 +21052 0.23724365234375 +21053 0.30535888671875 +21054 0.38128662109375 +21055 0.404449462890625 +21056 0.3944091796875 +21057 0.3885498046875 +21058 0.362640380859375 +21059 0.27362060546875 +21060 0.11712646484375 +21061 -0.054901123046875 +21062 -0.19085693359375 +21063 -0.28570556640625 +21064 -0.339263916015625 +21065 -0.3775634765625 +21066 -0.445709228515625 +21067 -0.535064697265625 +21068 -0.629058837890625 +21069 -0.697601318359375 +21070 -0.70391845703125 +21071 -0.6424560546875 +21072 -0.491241455078125 +21073 -0.265716552734375 +21074 -0.023712158203125 +21075 0.201751708984375 +21076 0.375823974609375 +21077 0.485076904296875 +21078 0.56884765625 +21079 0.634765625 +21080 0.63763427734375 +21081 0.5660400390625 +21082 0.4720458984375 +21083 0.40692138671875 +21084 0.3778076171875 +21085 0.376953125 +21086 0.371978759765625 +21087 0.313140869140625 +21088 0.184417724609375 +21089 0.011199951171875 +21090 -0.171051025390625 +21091 -0.33740234375 +21092 -0.47198486328125 +21093 -0.560394287109375 +21094 -0.58056640625 +21095 -0.54754638671875 +21096 -0.508575439453125 +21097 -0.459503173828125 +21098 -0.394378662109375 +21099 -0.35260009765625 +21100 -0.31170654296875 +21101 -0.197418212890625 +21102 -0.007965087890625 +21103 0.207489013671875 +21104 0.409210205078125 +21105 0.57208251953125 +21106 0.66595458984375 +21107 0.65875244140625 +21108 0.56744384765625 +21109 0.431396484375 +21110 0.29443359375 +21111 0.182464599609375 +21112 0.06365966796875 +21113 -0.075958251953125 +21114 -0.189422607421875 +21115 -0.271942138671875 +21116 -0.342529296875 +21117 -0.364166259765625 +21118 -0.327239990234375 +21119 -0.2769775390625 +21120 -0.253692626953125 +21121 -0.24365234375 +21122 -0.1983642578125 +21123 -0.116241455078125 +21124 -0.036834716796875 +21125 0.034881591796875 +21126 0.09124755859375 +21127 0.10888671875 +21128 0.125518798828125 +21129 0.15771484375 +21130 0.17828369140625 +21131 0.17108154296875 +21132 0.129974365234375 +21133 0.082427978515625 +21134 0.027679443359375 +21135 -0.065643310546875 +21136 -0.15936279296875 +21137 -0.21307373046875 +21138 -0.234649658203125 +21139 -0.2001953125 +21140 -0.119171142578125 +21141 -0.024749755859375 +21142 0.085784912109375 +21143 0.178131103515625 +21144 0.215576171875 +21145 0.211456298828125 +21146 0.17523193359375 +21147 0.128753662109375 +21148 0.1019287109375 +21149 0.0743408203125 +21150 0.04327392578125 +21151 0.038177490234375 +21152 0.076263427734375 +21153 0.14105224609375 +21154 0.186431884765625 +21155 0.188812255859375 +21156 0.1390380859375 +21157 0.041778564453125 +21158 -0.079437255859375 +21159 -0.219390869140625 +21160 -0.367828369140625 +21161 -0.494873046875 +21162 -0.556243896484375 +21163 -0.508697509765625 +21164 -0.3756103515625 +21165 -0.218902587890625 +21166 -0.063751220703125 +21167 0.091552734375 +21168 0.23602294921875 +21169 0.342987060546875 +21170 0.39520263671875 +21171 0.389373779296875 +21172 0.324249267578125 +21173 0.224090576171875 +21174 0.124267578125 +21175 0.037078857421875 +21176 -0.010101318359375 +21177 -0.019439697265625 +21178 -0.022796630859375 +21179 -0.001556396484375 +21180 0.056304931640625 +21181 0.106719970703125 +21182 0.096893310546875 +21183 0.042694091796875 +21184 -0.018035888671875 +21185 -0.07586669921875 +21186 -0.11944580078125 +21187 -0.15972900390625 +21188 -0.202606201171875 +21189 -0.24859619140625 +21190 -0.30517578125 +21191 -0.36212158203125 +21192 -0.39141845703125 +21193 -0.35528564453125 +21194 -0.249969482421875 +21195 -0.092864990234375 +21196 0.08905029296875 +21197 0.2352294921875 +21198 0.318817138671875 +21199 0.358642578125 +21200 0.347747802734375 +21201 0.28564453125 +21202 0.223175048828125 +21203 0.196746826171875 +21204 0.179840087890625 +21205 0.155548095703125 +21206 0.151214599609375 +21207 0.156951904296875 +21208 0.13177490234375 +21209 0.100799560546875 +21210 0.087127685546875 +21211 0.05487060546875 +21212 -0.009002685546875 +21213 -0.10400390625 +21214 -0.229400634765625 +21215 -0.35552978515625 +21216 -0.441925048828125 +21217 -0.473846435546875 +21218 -0.464813232421875 +21219 -0.419097900390625 +21220 -0.334320068359375 +21221 -0.227935791015625 +21222 -0.12347412109375 +21223 -0.02764892578125 +21224 0.077667236328125 +21225 0.2132568359375 +21226 0.38885498046875 +21227 0.582794189453125 +21228 0.734039306640625 +21229 0.800140380859375 +21230 0.7783203125 +21231 0.6651611328125 +21232 0.45965576171875 +21233 0.199188232421875 +21234 -0.050689697265625 +21235 -0.23297119140625 +21236 -0.33013916015625 +21237 -0.368408203125 +21238 -0.378936767578125 +21239 -0.376983642578125 +21240 -0.37969970703125 +21241 -0.391510009765625 +21242 -0.385345458984375 +21243 -0.3419189453125 +21244 -0.28289794921875 +21245 -0.251617431640625 +21246 -0.266143798828125 +21247 -0.273345947265625 +21248 -0.216796875 +21249 -0.128265380859375 +21250 -0.068145751953125 +21251 -0.0430908203125 +21252 -0.024444580078125 +21253 0.020721435546875 +21254 0.124481201171875 +21255 0.25787353515625 +21256 0.379119873046875 +21257 0.47991943359375 +21258 0.5281982421875 +21259 0.511138916015625 +21260 0.456207275390625 +21261 0.407470703125 +21262 0.383758544921875 +21263 0.35687255859375 +21264 0.31182861328125 +21265 0.250885009765625 +21266 0.1654052734375 +21267 0.035247802734375 +21268 -0.142059326171875 +21269 -0.33563232421875 +21270 -0.5345458984375 +21271 -0.72186279296875 +21272 -0.836669921875 +21273 -0.8326416015625 +21274 -0.7296142578125 +21275 -0.582550048828125 +21276 -0.440093994140625 +21277 -0.324310302734375 +21278 -0.20147705078125 +21279 -0.044647216796875 +21280 0.103973388671875 +21281 0.202392578125 +21282 0.264495849609375 +21283 0.338897705078125 +21284 0.443817138671875 +21285 0.545074462890625 +21286 0.6173095703125 +21287 0.6524658203125 +21288 0.66339111328125 +21289 0.6561279296875 +21290 0.606781005859375 +21291 0.501190185546875 +21292 0.352783203125 +21293 0.176544189453125 +21294 -0.034820556640625 +21295 -0.258209228515625 +21296 -0.44244384765625 +21297 -0.5753173828125 +21298 -0.65203857421875 +21299 -0.641632080078125 +21300 -0.562164306640625 +21301 -0.458038330078125 +21302 -0.350555419921875 +21303 -0.260528564453125 +21304 -0.192108154296875 +21305 -0.141937255859375 +21306 -0.1021728515625 +21307 -0.062896728515625 +21308 -0.011932373046875 +21309 0.062835693359375 +21310 0.148712158203125 +21311 0.241729736328125 +21312 0.34912109375 +21313 0.457305908203125 +21314 0.54388427734375 +21315 0.5728759765625 +21316 0.506591796875 +21317 0.351226806640625 +21318 0.146514892578125 +21319 -0.05523681640625 +21320 -0.21624755859375 +21321 -0.334930419921875 +21322 -0.402984619140625 +21323 -0.4412841796875 +21324 -0.49578857421875 +21325 -0.5601806640625 +21326 -0.600738525390625 +21327 -0.584228515625 +21328 -0.47930908203125 +21329 -0.27935791015625 +21330 -0.0089111328125 +21331 0.268798828125 +21332 0.482818603515625 +21333 0.60369873046875 +21334 0.650421142578125 +21335 0.66400146484375 +21336 0.6414794921875 +21337 0.572540283203125 +21338 0.498138427734375 +21339 0.439453125 +21340 0.375518798828125 +21341 0.274505615234375 +21342 0.1087646484375 +21343 -0.099395751953125 +21344 -0.3182373046875 +21345 -0.5489501953125 +21346 -0.7738037109375 +21347 -0.86383056640625 +21348 -0.870391845703125 +21349 -0.86895751953125 +21350 -0.861053466796875 +21351 -0.765869140625 +21352 -0.5301513671875 +21353 -0.214691162109375 +21354 0.137359619140625 +21355 0.474822998046875 +21356 0.76239013671875 +21357 0.867462158203125 +21358 0.870361328125 +21359 0.86480712890625 +21360 0.831817626953125 +21361 0.677581787109375 +21362 0.495880126953125 +21363 0.30767822265625 +21364 0.116180419921875 +21365 -0.110748291015625 +21366 -0.381805419921875 +21367 -0.6572265625 +21368 -0.857421875 +21369 -0.870391845703125 +21370 -0.870391845703125 +21371 -0.86444091796875 +21372 -0.85723876953125 +21373 -0.790008544921875 +21374 -0.62847900390625 +21375 -0.3956298828125 +21376 -0.126708984375 +21377 0.150115966796875 +21378 0.424041748046875 +21379 0.670623779296875 +21380 0.854522705078125 +21381 0.866485595703125 +21382 0.86920166015625 +21383 0.8653564453125 +21384 0.857147216796875 +21385 0.766845703125 +21386 0.628509521484375 +21387 0.462127685546875 +21388 0.297210693359375 +21389 0.14862060546875 +21390 -0.00537109375 +21391 -0.15753173828125 +21392 -0.31304931640625 +21393 -0.48876953125 +21394 -0.6416015625 +21395 -0.751373291015625 +21396 -0.84619140625 +21397 -0.861297607421875 +21398 -0.863250732421875 +21399 -0.856597900390625 +21400 -0.7498779296875 +21401 -0.624542236328125 +21402 -0.47808837890625 +21403 -0.253387451171875 +21404 0.003692626953125 +21405 0.2257080078125 +21406 0.427154541015625 +21407 0.643218994140625 +21408 0.855926513671875 +21409 0.870361328125 +21410 0.870361328125 +21411 0.862762451171875 +21412 0.79669189453125 +21413 0.595794677734375 +21414 0.362152099609375 +21415 0.1270751953125 +21416 -0.086944580078125 +21417 -0.2784423828125 +21418 -0.484832763671875 +21419 -0.729583740234375 +21420 -0.86688232421875 +21421 -0.870391845703125 +21422 -0.86859130859375 +21423 -0.86279296875 +21424 -0.817962646484375 +21425 -0.6116943359375 +21426 -0.3128662109375 +21427 0.039398193359375 +21428 0.422821044921875 +21429 0.805145263671875 +21430 0.870361328125 +21431 0.870361328125 +21432 0.860015869140625 +21433 0.727935791015625 +21434 0.48114013671875 +21435 0.2059326171875 +21436 -0.06103515625 +21437 -0.29913330078125 +21438 -0.516204833984375 +21439 -0.7252197265625 +21440 -0.85980224609375 +21441 -0.870391845703125 +21442 -0.870391845703125 +21443 -0.858062744140625 +21444 -0.673004150390625 +21445 -0.42694091796875 +21446 -0.2100830078125 +21447 -0.0362548828125 +21448 0.10943603515625 +21449 0.23516845703125 +21450 0.373687744140625 +21451 0.517791748046875 +21452 0.602783203125 +21453 0.635711669921875 +21454 0.655181884765625 +21455 0.65948486328125 +21456 0.651275634765625 +21457 0.61846923828125 +21458 0.53753662109375 +21459 0.404144287109375 +21460 0.22186279296875 +21461 0.003997802734375 +21462 -0.22100830078125 +21463 -0.42449951171875 +21464 -0.579833984375 +21465 -0.641876220703125 +21466 -0.6177978515625 +21467 -0.575531005859375 +21468 -0.526336669921875 +21469 -0.42645263671875 +21470 -0.2581787109375 +21471 -0.068695068359375 +21472 0.09222412109375 +21473 0.232147216796875 +21474 0.3509521484375 +21475 0.410064697265625 +21476 0.372955322265625 +21477 0.2554931640625 +21478 0.10711669921875 +21479 -0.052886962890625 +21480 -0.186279296875 +21481 -0.23291015625 +21482 -0.209442138671875 +21483 -0.174163818359375 +21484 -0.126739501953125 +21485 -0.048126220703125 +21486 0.0426025390625 +21487 0.10748291015625 +21488 0.1409912109375 +21489 0.19708251953125 +21490 0.273651123046875 +21491 0.31768798828125 +21492 0.341094970703125 +21493 0.368011474609375 +21494 0.37249755859375 +21495 0.30072021484375 +21496 0.1517333984375 +21497 -0.01470947265625 +21498 -0.1883544921875 +21499 -0.372711181640625 +21500 -0.51397705078125 +21501 -0.57177734375 +21502 -0.53948974609375 +21503 -0.43511962890625 +21504 -0.2962646484375 +21505 -0.161102294921875 +21506 -0.0435791015625 +21507 0.060394287109375 +21508 0.13665771484375 +21509 0.170135498046875 +21510 0.16552734375 +21511 0.15728759765625 +21512 0.150787353515625 +21513 0.12200927734375 +21514 0.080108642578125 +21515 0.05126953125 +21516 0.062896728515625 +21517 0.09271240234375 +21518 0.092987060546875 +21519 0.07855224609375 +21520 0.06427001953125 +21521 0.0347900390625 +21522 -0.01171875 +21523 -0.056060791015625 +21524 -0.055511474609375 +21525 -0.010467529296875 +21526 0.02508544921875 +21527 0.025665283203125 +21528 0.017333984375 +21529 0.00189208984375 +21530 -0.03173828125 +21531 -0.071502685546875 +21532 -0.13543701171875 +21533 -0.219970703125 +21534 -0.300506591796875 +21535 -0.376312255859375 +21536 -0.416107177734375 +21537 -0.371124267578125 +21538 -0.242279052734375 +21539 -0.069732666015625 +21540 0.125640869140625 +21541 0.31268310546875 +21542 0.45501708984375 +21543 0.554779052734375 +21544 0.61065673828125 +21545 0.610931396484375 +21546 0.531463623046875 +21547 0.3883056640625 +21548 0.23468017578125 +21549 0.095245361328125 +21550 -0.00396728515625 +21551 -0.04852294921875 +21552 -0.055145263671875 +21553 -0.0758056640625 +21554 -0.138702392578125 +21555 -0.209197998046875 +21556 -0.289031982421875 +21557 -0.37884521484375 +21558 -0.456329345703125 +21559 -0.51641845703125 +21560 -0.519287109375 +21561 -0.458251953125 +21562 -0.384796142578125 +21563 -0.323699951171875 +21564 -0.269287109375 +21565 -0.1951904296875 +21566 -0.100006103515625 +21567 -0.01055908203125 +21568 0.1033935546875 +21569 0.24908447265625 +21570 0.373199462890625 +21571 0.45806884765625 +21572 0.511474609375 +21573 0.565399169921875 +21574 0.61138916015625 +21575 0.5897216796875 +21576 0.4906005859375 +21577 0.33148193359375 +21578 0.147796630859375 +21579 -0.01873779296875 +21580 -0.140289306640625 +21581 -0.191986083984375 +21582 -0.184295654296875 +21583 -0.161834716796875 +21584 -0.166595458984375 +21585 -0.19390869140625 +21586 -0.22442626953125 +21587 -0.279754638671875 +21588 -0.3389892578125 +21589 -0.3543701171875 +21590 -0.348175048828125 +21591 -0.32598876953125 +21592 -0.2581787109375 +21593 -0.139801025390625 +21594 0.014617919921875 +21595 0.144378662109375 +21596 0.221038818359375 +21597 0.27069091796875 +21598 0.294036865234375 +21599 0.311767578125 +21600 0.339141845703125 +21601 0.360260009765625 +21602 0.360504150390625 +21603 0.308380126953125 +21604 0.18170166015625 +21605 0.0047607421875 +21606 -0.17559814453125 +21607 -0.3143310546875 +21608 -0.36785888671875 +21609 -0.36248779296875 +21610 -0.343536376953125 +21611 -0.3018798828125 +21612 -0.231414794921875 +21613 -0.117645263671875 +21614 0.007049560546875 +21615 0.087982177734375 +21616 0.13946533203125 +21617 0.17425537109375 +21618 0.188201904296875 +21619 0.171234130859375 +21620 0.118438720703125 +21621 0.05706787109375 +21622 -0.010711669921875 +21623 -0.0914306640625 +21624 -0.162322998046875 +21625 -0.194549560546875 +21626 -0.1492919921875 +21627 -0.02166748046875 +21628 0.124053955078125 +21629 0.211151123046875 +21630 0.240447998046875 +21631 0.242218017578125 +21632 0.2257080078125 +21633 0.194366455078125 +21634 0.115509033203125 +21635 0.0128173828125 +21636 -0.053802490234375 +21637 -0.110626220703125 +21638 -0.199493408203125 +21639 -0.29437255859375 +21640 -0.33221435546875 +21641 -0.27972412109375 +21642 -0.185333251953125 +21643 -0.128204345703125 +21644 -0.115692138671875 +21645 -0.116455078125 +21646 -0.105926513671875 +21647 -0.053955078125 +21648 0.048797607421875 +21649 0.157318115234375 +21650 0.212005615234375 +21651 0.218475341796875 +21652 0.23724365234375 +21653 0.30535888671875 +21654 0.38128662109375 +21655 0.404449462890625 +21656 0.3944091796875 +21657 0.3885498046875 +21658 0.362640380859375 +21659 0.27362060546875 +21660 0.11712646484375 +21661 -0.054901123046875 +21662 -0.19085693359375 +21663 -0.28570556640625 +21664 -0.339263916015625 +21665 -0.3775634765625 +21666 -0.445709228515625 +21667 -0.535064697265625 +21668 -0.629058837890625 +21669 -0.697601318359375 +21670 -0.70391845703125 +21671 -0.6424560546875 +21672 -0.491241455078125 +21673 -0.265716552734375 +21674 -0.023712158203125 +21675 0.201751708984375 +21676 0.375823974609375 +21677 0.485076904296875 +21678 0.56884765625 +21679 0.634765625 +21680 0.63763427734375 +21681 0.5660400390625 +21682 0.4720458984375 +21683 0.40692138671875 +21684 0.3778076171875 +21685 0.376953125 +21686 0.371978759765625 +21687 0.313140869140625 +21688 0.184417724609375 +21689 0.011199951171875 +21690 -0.171051025390625 +21691 -0.33740234375 +21692 -0.47198486328125 +21693 -0.560394287109375 +21694 -0.58056640625 +21695 -0.54754638671875 +21696 -0.508575439453125 +21697 -0.459503173828125 +21698 -0.394378662109375 +21699 -0.35260009765625 +21700 -0.31170654296875 +21701 -0.197418212890625 +21702 -0.007965087890625 +21703 0.207489013671875 +21704 0.409210205078125 +21705 0.57208251953125 +21706 0.66595458984375 +21707 0.65875244140625 +21708 0.56744384765625 +21709 0.431396484375 +21710 0.29443359375 +21711 0.182464599609375 +21712 0.06365966796875 +21713 -0.075958251953125 +21714 -0.189422607421875 +21715 -0.271942138671875 +21716 -0.342529296875 +21717 -0.364166259765625 +21718 -0.327239990234375 +21719 -0.2769775390625 +21720 -0.253692626953125 +21721 -0.24365234375 +21722 -0.1983642578125 +21723 -0.116241455078125 +21724 -0.036834716796875 +21725 0.034881591796875 +21726 0.09124755859375 +21727 0.10888671875 +21728 0.125518798828125 +21729 0.15771484375 +21730 0.17828369140625 +21731 0.17108154296875 +21732 0.129974365234375 +21733 0.082427978515625 +21734 0.027679443359375 +21735 -0.065643310546875 +21736 -0.15936279296875 +21737 -0.21307373046875 +21738 -0.234649658203125 +21739 -0.2001953125 +21740 -0.119171142578125 +21741 -0.024749755859375 +21742 0.085784912109375 +21743 0.178131103515625 +21744 0.215576171875 +21745 0.211456298828125 +21746 0.17523193359375 +21747 0.128753662109375 +21748 0.1019287109375 +21749 0.0743408203125 +21750 0.04327392578125 +21751 0.038177490234375 +21752 0.076263427734375 +21753 0.14105224609375 +21754 0.186431884765625 +21755 0.188812255859375 +21756 0.1390380859375 +21757 0.041778564453125 +21758 -0.079437255859375 +21759 -0.219390869140625 +21760 -0.367828369140625 +21761 -0.494873046875 +21762 -0.556243896484375 +21763 -0.508697509765625 +21764 -0.3756103515625 +21765 -0.218902587890625 +21766 -0.063751220703125 +21767 0.091552734375 +21768 0.23602294921875 +21769 0.342987060546875 +21770 0.39520263671875 +21771 0.389373779296875 +21772 0.324249267578125 +21773 0.224090576171875 +21774 0.124267578125 +21775 0.037078857421875 +21776 -0.010101318359375 +21777 -0.019439697265625 +21778 -0.022796630859375 +21779 -0.001556396484375 +21780 0.056304931640625 +21781 0.106719970703125 +21782 0.096893310546875 +21783 0.042694091796875 +21784 -0.018035888671875 +21785 -0.07586669921875 +21786 -0.11944580078125 +21787 -0.15972900390625 +21788 -0.202606201171875 +21789 -0.24859619140625 +21790 -0.30517578125 +21791 -0.36212158203125 +21792 -0.39141845703125 +21793 -0.35528564453125 +21794 -0.249969482421875 +21795 -0.092864990234375 +21796 0.08905029296875 +21797 0.2352294921875 +21798 0.318817138671875 +21799 0.358642578125 +21800 0.347747802734375 +21801 0.28564453125 +21802 0.223175048828125 +21803 0.196746826171875 +21804 0.179840087890625 +21805 0.155548095703125 +21806 0.151214599609375 +21807 0.156951904296875 +21808 0.13177490234375 +21809 0.100799560546875 +21810 0.087127685546875 +21811 0.05487060546875 +21812 -0.009002685546875 +21813 -0.10400390625 +21814 -0.229400634765625 +21815 -0.35552978515625 +21816 -0.441925048828125 +21817 -0.473846435546875 +21818 -0.464813232421875 +21819 -0.419097900390625 +21820 -0.334320068359375 +21821 -0.227935791015625 +21822 -0.12347412109375 +21823 -0.02764892578125 +21824 0.077667236328125 +21825 0.2132568359375 +21826 0.38885498046875 +21827 0.582794189453125 +21828 0.734039306640625 +21829 0.800140380859375 +21830 0.7783203125 +21831 0.6651611328125 +21832 0.45965576171875 +21833 0.199188232421875 +21834 -0.050689697265625 +21835 -0.23297119140625 +21836 -0.33013916015625 +21837 -0.368408203125 +21838 -0.378936767578125 +21839 -0.376983642578125 +21840 -0.37969970703125 +21841 -0.391510009765625 +21842 -0.385345458984375 +21843 -0.3419189453125 +21844 -0.28289794921875 +21845 -0.251617431640625 +21846 -0.266143798828125 +21847 -0.273345947265625 +21848 -0.216796875 +21849 -0.128265380859375 +21850 -0.068145751953125 +21851 -0.0430908203125 +21852 -0.024444580078125 +21853 0.020721435546875 +21854 0.124481201171875 +21855 0.25787353515625 +21856 0.379119873046875 +21857 0.47991943359375 +21858 0.5281982421875 +21859 0.511138916015625 +21860 0.456207275390625 +21861 0.407470703125 +21862 0.383758544921875 +21863 0.35687255859375 +21864 0.31182861328125 +21865 0.250885009765625 +21866 0.1654052734375 +21867 0.035247802734375 +21868 -0.142059326171875 +21869 -0.33563232421875 +21870 -0.5345458984375 +21871 -0.72186279296875 +21872 -0.836669921875 +21873 -0.8326416015625 +21874 -0.7296142578125 +21875 -0.582550048828125 +21876 -0.440093994140625 +21877 -0.324310302734375 +21878 -0.20147705078125 +21879 -0.044647216796875 +21880 0.103973388671875 +21881 0.202392578125 +21882 0.264495849609375 +21883 0.338897705078125 +21884 0.443817138671875 +21885 0.545074462890625 +21886 0.6173095703125 +21887 0.6524658203125 +21888 0.66339111328125 +21889 0.6561279296875 +21890 0.606781005859375 +21891 0.501190185546875 +21892 0.352783203125 +21893 0.176544189453125 +21894 -0.034820556640625 +21895 -0.258209228515625 +21896 -0.44244384765625 +21897 -0.5753173828125 +21898 -0.65203857421875 +21899 -0.641632080078125 +21900 -0.562164306640625 +21901 -0.458038330078125 +21902 -0.350555419921875 +21903 -0.260528564453125 +21904 -0.192108154296875 +21905 -0.141937255859375 +21906 -0.1021728515625 +21907 -0.062896728515625 +21908 -0.011932373046875 +21909 0.062835693359375 +21910 0.148712158203125 +21911 0.241729736328125 +21912 0.34912109375 +21913 0.457305908203125 +21914 0.54388427734375 +21915 0.5728759765625 +21916 0.506591796875 +21917 0.351226806640625 +21918 0.146514892578125 +21919 -0.05523681640625 +21920 -0.21624755859375 +21921 -0.334930419921875 +21922 -0.402984619140625 +21923 -0.4412841796875 +21924 -0.49578857421875 +21925 -0.5601806640625 +21926 -0.600738525390625 +21927 -0.584228515625 +21928 -0.47930908203125 +21929 -0.27935791015625 +21930 -0.0089111328125 +21931 0.268798828125 +21932 0.482818603515625 +21933 0.60369873046875 +21934 0.650421142578125 +21935 0.66400146484375 +21936 0.6414794921875 +21937 0.572540283203125 +21938 0.498138427734375 +21939 0.439453125 +21940 0.375518798828125 +21941 0.274505615234375 +21942 0.1087646484375 +21943 -0.099395751953125 +21944 -0.3182373046875 +21945 -0.5489501953125 +21946 -0.7738037109375 +21947 -0.86383056640625 +21948 -0.870391845703125 +21949 -0.86895751953125 +21950 -0.861053466796875 +21951 -0.765869140625 +21952 -0.5301513671875 +21953 -0.214691162109375 +21954 0.137359619140625 +21955 0.474822998046875 +21956 0.76239013671875 +21957 0.867462158203125 +21958 0.870361328125 +21959 0.86480712890625 +21960 0.831817626953125 +21961 0.677581787109375 +21962 0.495880126953125 +21963 0.30767822265625 +21964 0.116180419921875 +21965 -0.110748291015625 +21966 -0.381805419921875 +21967 -0.6572265625 +21968 -0.857421875 +21969 -0.870391845703125 +21970 -0.870391845703125 +21971 -0.86444091796875 +21972 -0.85723876953125 +21973 -0.790008544921875 +21974 -0.62847900390625 +21975 -0.3956298828125 +21976 -0.126708984375 +21977 0.150115966796875 +21978 0.424041748046875 +21979 0.670623779296875 +21980 0.854522705078125 +21981 0.866485595703125 +21982 0.86920166015625 +21983 0.8653564453125 +21984 0.857147216796875 +21985 0.766845703125 +21986 0.628509521484375 +21987 0.462127685546875 +21988 0.297210693359375 +21989 0.14862060546875 +21990 -0.00537109375 +21991 -0.15753173828125 +21992 -0.31304931640625 +21993 -0.48876953125 +21994 -0.6416015625 +21995 -0.751373291015625 +21996 -0.84619140625 +21997 -0.861297607421875 +21998 -0.863250732421875 +21999 -0.856597900390625 +22000 -0.7498779296875 +22001 -0.624542236328125 +22002 -0.47808837890625 +22003 -0.253387451171875 +22004 0.003692626953125 +22005 0.2257080078125 +22006 0.427154541015625 +22007 0.643218994140625 +22008 0.855926513671875 +22009 0.870361328125 +22010 0.870361328125 +22011 0.862762451171875 +22012 0.79669189453125 +22013 0.595794677734375 +22014 0.362152099609375 +22015 0.1270751953125 +22016 -0.086944580078125 +22017 -0.2784423828125 +22018 -0.484832763671875 +22019 -0.729583740234375 +22020 -0.86688232421875 +22021 -0.870391845703125 +22022 -0.86859130859375 +22023 -0.86279296875 +22024 -0.817962646484375 +22025 -0.6116943359375 +22026 -0.3128662109375 +22027 0.039398193359375 +22028 0.422821044921875 +22029 0.805145263671875 +22030 0.870361328125 +22031 0.870361328125 +22032 0.860015869140625 +22033 0.727935791015625 +22034 0.48114013671875 +22035 0.2059326171875 +22036 -0.06103515625 +22037 -0.29913330078125 +22038 -0.516204833984375 +22039 -0.7252197265625 +22040 -0.85980224609375 +22041 -0.870391845703125 +22042 -0.870391845703125 +22043 -0.858062744140625 +22044 -0.673004150390625 +22045 -0.42694091796875 +22046 -0.2100830078125 +22047 -0.0362548828125 +22048 0.10943603515625 +22049 0.23516845703125 +22050 0.373687744140625 +22051 0.517791748046875 +22052 0.602783203125 +22053 0.635711669921875 +22054 0.655181884765625 +22055 0.65948486328125 +22056 0.651275634765625 +22057 0.61846923828125 +22058 0.53753662109375 +22059 0.404144287109375 +22060 0.22186279296875 +22061 0.003997802734375 +22062 -0.22100830078125 +22063 -0.42449951171875 +22064 -0.579833984375 +22065 -0.641876220703125 +22066 -0.6177978515625 +22067 -0.575531005859375 +22068 -0.526336669921875 +22069 -0.42645263671875 +22070 -0.2581787109375 +22071 -0.068695068359375 +22072 0.09222412109375 +22073 0.232147216796875 +22074 0.3509521484375 +22075 0.410064697265625 +22076 0.372955322265625 +22077 0.2554931640625 +22078 0.10711669921875 +22079 -0.052886962890625 +22080 -0.186279296875 +22081 -0.23291015625 +22082 -0.209442138671875 +22083 -0.174163818359375 +22084 -0.126739501953125 +22085 -0.048126220703125 +22086 0.0426025390625 +22087 0.10748291015625 +22088 0.1409912109375 +22089 0.19708251953125 +22090 0.273651123046875 +22091 0.31768798828125 +22092 0.341094970703125 +22093 0.368011474609375 +22094 0.37249755859375 +22095 0.30072021484375 +22096 0.1517333984375 +22097 -0.01470947265625 +22098 -0.1883544921875 +22099 -0.372711181640625 +22100 -0.51397705078125 +22101 -0.57177734375 +22102 -0.53948974609375 +22103 -0.43511962890625 +22104 -0.2962646484375 +22105 -0.161102294921875 +22106 -0.0435791015625 +22107 0.060394287109375 +22108 0.13665771484375 +22109 0.170135498046875 +22110 0.16552734375 +22111 0.15728759765625 +22112 0.150787353515625 +22113 0.12200927734375 +22114 0.080108642578125 +22115 0.05126953125 +22116 0.062896728515625 +22117 0.09271240234375 +22118 0.092987060546875 +22119 0.07855224609375 +22120 0.06427001953125 +22121 0.0347900390625 +22122 -0.01171875 +22123 -0.056060791015625 +22124 -0.055511474609375 +22125 -0.010467529296875 +22126 0.02508544921875 +22127 0.025665283203125 +22128 0.017333984375 +22129 0.00189208984375 +22130 -0.03173828125 +22131 -0.071502685546875 +22132 -0.13543701171875 +22133 -0.219970703125 +22134 -0.300506591796875 +22135 -0.376312255859375 +22136 -0.416107177734375 +22137 -0.371124267578125 +22138 -0.242279052734375 +22139 -0.069732666015625 +22140 0.125640869140625 +22141 0.31268310546875 +22142 0.45501708984375 +22143 0.554779052734375 +22144 0.61065673828125 +22145 0.610931396484375 +22146 0.531463623046875 +22147 0.3883056640625 +22148 0.23468017578125 +22149 0.095245361328125 +22150 -0.00396728515625 +22151 -0.04852294921875 +22152 -0.055145263671875 +22153 -0.0758056640625 +22154 -0.138702392578125 +22155 -0.209197998046875 +22156 -0.289031982421875 +22157 -0.37884521484375 +22158 -0.456329345703125 +22159 -0.51641845703125 +22160 -0.519287109375 +22161 -0.458251953125 +22162 -0.384796142578125 +22163 -0.323699951171875 +22164 -0.269287109375 +22165 -0.1951904296875 +22166 -0.100006103515625 +22167 -0.01055908203125 +22168 0.1033935546875 +22169 0.24908447265625 +22170 0.373199462890625 +22171 0.45806884765625 +22172 0.511474609375 +22173 0.565399169921875 +22174 0.61138916015625 +22175 0.5897216796875 +22176 0.4906005859375 +22177 0.33148193359375 +22178 0.147796630859375 +22179 -0.01873779296875 +22180 -0.140289306640625 +22181 -0.191986083984375 +22182 -0.184295654296875 +22183 -0.161834716796875 +22184 -0.166595458984375 +22185 -0.19390869140625 +22186 -0.22442626953125 +22187 -0.279754638671875 +22188 -0.3389892578125 +22189 -0.3543701171875 +22190 -0.348175048828125 +22191 -0.32598876953125 +22192 -0.2581787109375 +22193 -0.139801025390625 +22194 0.014617919921875 +22195 0.144378662109375 +22196 0.221038818359375 +22197 0.27069091796875 +22198 0.294036865234375 +22199 0.311767578125 +22200 0.339141845703125 +22201 0.360260009765625 +22202 0.360504150390625 +22203 0.308380126953125 +22204 0.18170166015625 +22205 0.0047607421875 +22206 -0.17559814453125 +22207 -0.3143310546875 +22208 -0.36785888671875 +22209 -0.36248779296875 +22210 -0.343536376953125 +22211 -0.3018798828125 +22212 -0.231414794921875 +22213 -0.117645263671875 +22214 0.007049560546875 +22215 0.087982177734375 +22216 0.13946533203125 +22217 0.17425537109375 +22218 0.188201904296875 +22219 0.171234130859375 +22220 0.118438720703125 +22221 0.05706787109375 +22222 -0.010711669921875 +22223 -0.0914306640625 +22224 -0.162322998046875 +22225 -0.194549560546875 +22226 -0.1492919921875 +22227 -0.02166748046875 +22228 0.124053955078125 +22229 0.211151123046875 +22230 0.240447998046875 +22231 0.242218017578125 +22232 0.2257080078125 +22233 0.194366455078125 +22234 0.115509033203125 +22235 0.0128173828125 +22236 -0.053802490234375 +22237 -0.110626220703125 +22238 -0.199493408203125 +22239 -0.29437255859375 +22240 -0.33221435546875 +22241 -0.27972412109375 +22242 -0.185333251953125 +22243 -0.128204345703125 +22244 -0.115692138671875 +22245 -0.116455078125 +22246 -0.105926513671875 +22247 -0.053955078125 +22248 0.048797607421875 +22249 0.157318115234375 +22250 0.212005615234375 +22251 0.218475341796875 +22252 0.23724365234375 +22253 0.30535888671875 +22254 0.38128662109375 +22255 0.404449462890625 +22256 0.3944091796875 +22257 0.3885498046875 +22258 0.362640380859375 +22259 0.27362060546875 +22260 0.11712646484375 +22261 -0.054901123046875 +22262 -0.19085693359375 +22263 -0.28570556640625 +22264 -0.339263916015625 +22265 -0.3775634765625 +22266 -0.445709228515625 +22267 -0.535064697265625 +22268 -0.629058837890625 +22269 -0.697601318359375 +22270 -0.70391845703125 +22271 -0.6424560546875 +22272 -0.491241455078125 +22273 -0.265716552734375 +22274 -0.023712158203125 +22275 0.201751708984375 +22276 0.375823974609375 +22277 0.485076904296875 +22278 0.56884765625 +22279 0.634765625 +22280 0.63763427734375 +22281 0.5660400390625 +22282 0.4720458984375 +22283 0.40692138671875 +22284 0.3778076171875 +22285 0.376953125 +22286 0.371978759765625 +22287 0.313140869140625 +22288 0.184417724609375 +22289 0.011199951171875 +22290 -0.171051025390625 +22291 -0.33740234375 +22292 -0.47198486328125 +22293 -0.560394287109375 +22294 -0.58056640625 +22295 -0.54754638671875 +22296 -0.508575439453125 +22297 -0.459503173828125 +22298 -0.394378662109375 +22299 -0.35260009765625 +22300 -0.31170654296875 +22301 -0.197418212890625 +22302 -0.007965087890625 +22303 0.207489013671875 +22304 0.409210205078125 +22305 0.57208251953125 +22306 0.66595458984375 +22307 0.65875244140625 +22308 0.56744384765625 +22309 0.431396484375 +22310 0.29443359375 +22311 0.182464599609375 +22312 0.06365966796875 +22313 -0.075958251953125 +22314 -0.189422607421875 +22315 -0.271942138671875 +22316 -0.342529296875 +22317 -0.364166259765625 +22318 -0.327239990234375 +22319 -0.2769775390625 +22320 -0.253692626953125 +22321 -0.24365234375 +22322 -0.1983642578125 +22323 -0.116241455078125 +22324 -0.036834716796875 +22325 0.034881591796875 +22326 0.09124755859375 +22327 0.10888671875 +22328 0.125518798828125 +22329 0.15771484375 +22330 0.17828369140625 +22331 0.17108154296875 +22332 0.129974365234375 +22333 0.082427978515625 +22334 0.027679443359375 +22335 -0.065643310546875 +22336 -0.15936279296875 +22337 -0.21307373046875 +22338 -0.234649658203125 +22339 -0.2001953125 +22340 -0.119171142578125 +22341 -0.024749755859375 +22342 0.085784912109375 +22343 0.178131103515625 +22344 0.215576171875 +22345 0.211456298828125 +22346 0.17523193359375 +22347 0.128753662109375 +22348 0.1019287109375 +22349 0.0743408203125 +22350 0.04327392578125 +22351 0.038177490234375 +22352 0.076263427734375 +22353 0.14105224609375 +22354 0.186431884765625 +22355 0.188812255859375 +22356 0.1390380859375 +22357 0.041778564453125 +22358 -0.079437255859375 +22359 -0.219390869140625 +22360 -0.367828369140625 +22361 -0.494873046875 +22362 -0.556243896484375 +22363 -0.508697509765625 +22364 -0.3756103515625 +22365 -0.218902587890625 +22366 -0.063751220703125 +22367 0.091552734375 +22368 0.23602294921875 +22369 0.342987060546875 +22370 0.39520263671875 +22371 0.389373779296875 +22372 0.324249267578125 +22373 0.224090576171875 +22374 0.124267578125 +22375 0.037078857421875 +22376 -0.010101318359375 +22377 -0.019439697265625 +22378 -0.022796630859375 +22379 -0.001556396484375 +22380 0.056304931640625 +22381 0.106719970703125 +22382 0.096893310546875 +22383 0.042694091796875 +22384 -0.018035888671875 +22385 -0.07586669921875 +22386 -0.11944580078125 +22387 -0.15972900390625 +22388 -0.202606201171875 +22389 -0.24859619140625 +22390 -0.30517578125 +22391 -0.36212158203125 +22392 -0.39141845703125 +22393 -0.35528564453125 +22394 -0.249969482421875 +22395 -0.092864990234375 +22396 0.08905029296875 +22397 0.2352294921875 +22398 0.318817138671875 +22399 0.358642578125 +22400 0.347747802734375 +22401 0.28564453125 +22402 0.223175048828125 +22403 0.196746826171875 +22404 0.179840087890625 +22405 0.155548095703125 +22406 0.151214599609375 +22407 0.156951904296875 +22408 0.13177490234375 +22409 0.100799560546875 +22410 0.087127685546875 +22411 0.05487060546875 +22412 -0.009002685546875 +22413 -0.10400390625 +22414 -0.229400634765625 +22415 -0.35552978515625 +22416 -0.441925048828125 +22417 -0.473846435546875 +22418 -0.464813232421875 +22419 -0.419097900390625 +22420 -0.334320068359375 +22421 -0.227935791015625 +22422 -0.12347412109375 +22423 -0.02764892578125 +22424 0.077667236328125 +22425 0.2132568359375 +22426 0.38885498046875 +22427 0.582794189453125 +22428 0.734039306640625 +22429 0.800140380859375 +22430 0.7783203125 +22431 0.6651611328125 +22432 0.45965576171875 +22433 0.199188232421875 +22434 -0.050689697265625 +22435 -0.23297119140625 +22436 -0.33013916015625 +22437 -0.368408203125 +22438 -0.378936767578125 +22439 -0.376983642578125 +22440 -0.37969970703125 +22441 -0.391510009765625 +22442 -0.385345458984375 +22443 -0.3419189453125 +22444 -0.28289794921875 +22445 -0.251617431640625 +22446 -0.266143798828125 +22447 -0.273345947265625 +22448 -0.216796875 +22449 -0.128265380859375 +22450 -0.068145751953125 +22451 -0.0430908203125 +22452 -0.024444580078125 +22453 0.020721435546875 +22454 0.124481201171875 +22455 0.25787353515625 +22456 0.379119873046875 +22457 0.47991943359375 +22458 0.5281982421875 +22459 0.511138916015625 +22460 0.456207275390625 +22461 0.407470703125 +22462 0.383758544921875 +22463 0.35687255859375 +22464 0.31182861328125 +22465 0.250885009765625 +22466 0.1654052734375 +22467 0.035247802734375 +22468 -0.142059326171875 +22469 -0.33563232421875 +22470 -0.5345458984375 +22471 -0.72186279296875 +22472 -0.836669921875 +22473 -0.8326416015625 +22474 -0.7296142578125 +22475 -0.582550048828125 +22476 -0.440093994140625 +22477 -0.324310302734375 +22478 -0.20147705078125 +22479 -0.044647216796875 +22480 0.103973388671875 +22481 0.202392578125 +22482 0.264495849609375 +22483 0.338897705078125 +22484 0.443817138671875 +22485 0.545074462890625 +22486 0.6173095703125 +22487 0.6524658203125 +22488 0.66339111328125 +22489 0.6561279296875 +22490 0.606781005859375 +22491 0.501190185546875 +22492 0.352783203125 +22493 0.176544189453125 +22494 -0.034820556640625 +22495 -0.258209228515625 +22496 -0.44244384765625 +22497 -0.5753173828125 +22498 -0.65203857421875 +22499 -0.641632080078125 +22500 -0.562164306640625 +22501 -0.458038330078125 +22502 -0.350555419921875 +22503 -0.260528564453125 +22504 -0.192108154296875 +22505 -0.141937255859375 +22506 -0.1021728515625 +22507 -0.062896728515625 +22508 -0.011932373046875 +22509 0.062835693359375 +22510 0.148712158203125 +22511 0.241729736328125 +22512 0.34912109375 +22513 0.457305908203125 +22514 0.54388427734375 +22515 0.5728759765625 +22516 0.506591796875 +22517 0.351226806640625 +22518 0.146514892578125 +22519 -0.05523681640625 +22520 -0.21624755859375 +22521 -0.334930419921875 +22522 -0.402984619140625 +22523 -0.4412841796875 +22524 -0.49578857421875 +22525 -0.5601806640625 +22526 -0.600738525390625 +22527 -0.584228515625 +22528 -0.47930908203125 +22529 -0.27935791015625 +22530 -0.0089111328125 +22531 0.268798828125 +22532 0.482818603515625 +22533 0.60369873046875 +22534 0.650421142578125 +22535 0.66400146484375 +22536 0.6414794921875 +22537 0.572540283203125 +22538 0.498138427734375 +22539 0.439453125 +22540 0.375518798828125 +22541 0.274505615234375 +22542 0.1087646484375 +22543 -0.099395751953125 +22544 -0.3182373046875 +22545 -0.5489501953125 +22546 -0.7738037109375 +22547 -0.86383056640625 +22548 -0.870391845703125 +22549 -0.86895751953125 +22550 -0.861053466796875 +22551 -0.765869140625 +22552 -0.5301513671875 +22553 -0.214691162109375 +22554 0.137359619140625 +22555 0.474822998046875 +22556 0.76239013671875 +22557 0.867462158203125 +22558 0.870361328125 +22559 0.86480712890625 +22560 0.831817626953125 +22561 0.677581787109375 +22562 0.495880126953125 +22563 0.30767822265625 +22564 0.116180419921875 +22565 -0.110748291015625 +22566 -0.381805419921875 +22567 -0.6572265625 +22568 -0.857421875 +22569 -0.870391845703125 +22570 -0.870391845703125 +22571 -0.86444091796875 +22572 -0.85723876953125 +22573 -0.790008544921875 +22574 -0.62847900390625 +22575 -0.3956298828125 +22576 -0.126708984375 +22577 0.150115966796875 +22578 0.424041748046875 +22579 0.670623779296875 +22580 0.854522705078125 +22581 0.866485595703125 +22582 0.86920166015625 +22583 0.8653564453125 +22584 0.857147216796875 +22585 0.766845703125 +22586 0.628509521484375 +22587 0.462127685546875 +22588 0.297210693359375 +22589 0.14862060546875 +22590 -0.00537109375 +22591 -0.15753173828125 +22592 -0.31304931640625 +22593 -0.48876953125 +22594 -0.6416015625 +22595 -0.751373291015625 +22596 -0.84619140625 +22597 -0.861297607421875 +22598 -0.863250732421875 +22599 -0.856597900390625 +22600 -0.7498779296875 +22601 -0.624542236328125 +22602 -0.47808837890625 +22603 -0.253387451171875 +22604 0.003692626953125 +22605 0.2257080078125 +22606 0.427154541015625 +22607 0.643218994140625 +22608 0.855926513671875 +22609 0.870361328125 +22610 0.870361328125 +22611 0.862762451171875 +22612 0.79669189453125 +22613 0.595794677734375 +22614 0.362152099609375 +22615 0.1270751953125 +22616 -0.086944580078125 +22617 -0.2784423828125 +22618 -0.484832763671875 +22619 -0.729583740234375 +22620 -0.86688232421875 +22621 -0.870391845703125 +22622 -0.86859130859375 +22623 -0.86279296875 +22624 -0.817962646484375 +22625 -0.6116943359375 +22626 -0.3128662109375 +22627 0.039398193359375 +22628 0.422821044921875 +22629 0.805145263671875 +22630 0.870361328125 +22631 0.870361328125 +22632 0.860015869140625 +22633 0.727935791015625 +22634 0.48114013671875 +22635 0.2059326171875 +22636 -0.06103515625 +22637 -0.29913330078125 +22638 -0.516204833984375 +22639 -0.7252197265625 +22640 -0.85980224609375 +22641 -0.870391845703125 +22642 -0.870391845703125 +22643 -0.858062744140625 +22644 -0.673004150390625 +22645 -0.42694091796875 +22646 -0.2100830078125 +22647 -0.0362548828125 +22648 0.10943603515625 +22649 0.23516845703125 +22650 0.373687744140625 +22651 0.517791748046875 +22652 0.602783203125 +22653 0.635711669921875 +22654 0.655181884765625 +22655 0.65948486328125 +22656 0.651275634765625 +22657 0.61846923828125 +22658 0.53753662109375 +22659 0.404144287109375 +22660 0.22186279296875 +22661 0.003997802734375 +22662 -0.22100830078125 +22663 -0.42449951171875 +22664 -0.579833984375 +22665 -0.641876220703125 +22666 -0.6177978515625 +22667 -0.575531005859375 +22668 -0.526336669921875 +22669 -0.42645263671875 +22670 -0.2581787109375 +22671 -0.068695068359375 +22672 0.09222412109375 +22673 0.232147216796875 +22674 0.3509521484375 +22675 0.410064697265625 +22676 0.372955322265625 +22677 0.2554931640625 +22678 0.10711669921875 +22679 -0.052886962890625 +22680 -0.186279296875 +22681 -0.23291015625 +22682 -0.209442138671875 +22683 -0.174163818359375 +22684 -0.126739501953125 +22685 -0.048126220703125 +22686 0.0426025390625 +22687 0.10748291015625 +22688 0.1409912109375 +22689 0.19708251953125 +22690 0.273651123046875 +22691 0.31768798828125 +22692 0.341094970703125 +22693 0.368011474609375 +22694 0.37249755859375 +22695 0.30072021484375 +22696 0.1517333984375 +22697 -0.01470947265625 +22698 -0.1883544921875 +22699 -0.372711181640625 +22700 -0.51397705078125 +22701 -0.57177734375 +22702 -0.53948974609375 +22703 -0.43511962890625 +22704 -0.2962646484375 +22705 -0.161102294921875 +22706 -0.0435791015625 +22707 0.060394287109375 +22708 0.13665771484375 +22709 0.170135498046875 +22710 0.16552734375 +22711 0.15728759765625 +22712 0.150787353515625 +22713 0.12200927734375 +22714 0.080108642578125 +22715 0.05126953125 +22716 0.062896728515625 +22717 0.09271240234375 +22718 0.092987060546875 +22719 0.07855224609375 +22720 0.06427001953125 +22721 0.0347900390625 +22722 -0.01171875 +22723 -0.056060791015625 +22724 -0.055511474609375 +22725 -0.010467529296875 +22726 0.02508544921875 +22727 0.025665283203125 +22728 0.017333984375 +22729 0.00189208984375 +22730 -0.03173828125 +22731 -0.071502685546875 +22732 -0.13543701171875 +22733 -0.219970703125 +22734 -0.300506591796875 +22735 -0.376312255859375 +22736 -0.416107177734375 +22737 -0.371124267578125 +22738 -0.242279052734375 +22739 -0.069732666015625 +22740 0.125640869140625 +22741 0.31268310546875 +22742 0.45501708984375 +22743 0.554779052734375 +22744 0.61065673828125 +22745 0.610931396484375 +22746 0.531463623046875 +22747 0.3883056640625 +22748 0.23468017578125 +22749 0.095245361328125 +22750 -0.00396728515625 +22751 -0.04852294921875 +22752 -0.055145263671875 +22753 -0.0758056640625 +22754 -0.138702392578125 +22755 -0.209197998046875 +22756 -0.289031982421875 +22757 -0.37884521484375 +22758 -0.456329345703125 +22759 -0.51641845703125 +22760 -0.519287109375 +22761 -0.458251953125 +22762 -0.384796142578125 +22763 -0.323699951171875 +22764 -0.269287109375 +22765 -0.1951904296875 +22766 -0.100006103515625 +22767 -0.01055908203125 +22768 0.1033935546875 +22769 0.24908447265625 +22770 0.373199462890625 +22771 0.45806884765625 +22772 0.511474609375 +22773 0.565399169921875 +22774 0.61138916015625 +22775 0.5897216796875 +22776 0.4906005859375 +22777 0.33148193359375 +22778 0.147796630859375 +22779 -0.01873779296875 +22780 -0.140289306640625 +22781 -0.191986083984375 +22782 -0.184295654296875 +22783 -0.161834716796875 +22784 -0.166595458984375 +22785 -0.19390869140625 +22786 -0.22442626953125 +22787 -0.279754638671875 +22788 -0.3389892578125 +22789 -0.3543701171875 +22790 -0.348175048828125 +22791 -0.32598876953125 +22792 -0.2581787109375 +22793 -0.139801025390625 +22794 0.014617919921875 +22795 0.144378662109375 +22796 0.221038818359375 +22797 0.27069091796875 +22798 0.294036865234375 +22799 0.311767578125 +22800 0.339141845703125 +22801 0.360260009765625 +22802 0.360504150390625 +22803 0.308380126953125 +22804 0.18170166015625 +22805 0.0047607421875 +22806 -0.17559814453125 +22807 -0.3143310546875 +22808 -0.36785888671875 +22809 -0.36248779296875 +22810 -0.343536376953125 +22811 -0.3018798828125 +22812 -0.231414794921875 +22813 -0.117645263671875 +22814 0.007049560546875 +22815 0.087982177734375 +22816 0.13946533203125 +22817 0.17425537109375 +22818 0.188201904296875 +22819 0.171234130859375 +22820 0.118438720703125 +22821 0.05706787109375 +22822 -0.010711669921875 +22823 -0.0914306640625 +22824 -0.162322998046875 +22825 -0.194549560546875 +22826 -0.1492919921875 +22827 -0.02166748046875 +22828 0.124053955078125 +22829 0.211151123046875 +22830 0.240447998046875 +22831 0.242218017578125 +22832 0.2257080078125 +22833 0.194366455078125 +22834 0.115509033203125 +22835 0.0128173828125 +22836 -0.053802490234375 +22837 -0.110626220703125 +22838 -0.199493408203125 +22839 -0.29437255859375 +22840 -0.33221435546875 +22841 -0.27972412109375 +22842 -0.185333251953125 +22843 -0.128204345703125 +22844 -0.115692138671875 +22845 -0.116455078125 +22846 -0.105926513671875 +22847 -0.053955078125 +22848 0.048797607421875 +22849 0.157318115234375 +22850 0.212005615234375 +22851 0.218475341796875 +22852 0.23724365234375 +22853 0.30535888671875 +22854 0.38128662109375 +22855 0.404449462890625 +22856 0.3944091796875 +22857 0.3885498046875 +22858 0.362640380859375 +22859 0.27362060546875 +22860 0.11712646484375 +22861 -0.054901123046875 +22862 -0.19085693359375 +22863 -0.28570556640625 +22864 -0.339263916015625 +22865 -0.3775634765625 +22866 -0.445709228515625 +22867 -0.535064697265625 +22868 -0.629058837890625 +22869 -0.697601318359375 +22870 -0.70391845703125 +22871 -0.6424560546875 +22872 -0.491241455078125 +22873 -0.265716552734375 +22874 -0.023712158203125 +22875 0.201751708984375 +22876 0.375823974609375 +22877 0.485076904296875 +22878 0.56884765625 +22879 0.634765625 +22880 0.63763427734375 +22881 0.5660400390625 +22882 0.4720458984375 +22883 0.40692138671875 +22884 0.3778076171875 +22885 0.376953125 +22886 0.371978759765625 +22887 0.313140869140625 +22888 0.184417724609375 +22889 0.011199951171875 +22890 -0.171051025390625 +22891 -0.33740234375 +22892 -0.47198486328125 +22893 -0.560394287109375 +22894 -0.58056640625 +22895 -0.54754638671875 +22896 -0.508575439453125 +22897 -0.459503173828125 +22898 -0.394378662109375 +22899 -0.35260009765625 +22900 -0.31170654296875 +22901 -0.197418212890625 +22902 -0.007965087890625 +22903 0.207489013671875 +22904 0.409210205078125 +22905 0.57208251953125 +22906 0.66595458984375 +22907 0.65875244140625 +22908 0.56744384765625 +22909 0.431396484375 +22910 0.29443359375 +22911 0.182464599609375 +22912 0.06365966796875 +22913 -0.075958251953125 +22914 -0.189422607421875 +22915 -0.271942138671875 +22916 -0.342529296875 +22917 -0.364166259765625 +22918 -0.327239990234375 +22919 -0.2769775390625 +22920 -0.253692626953125 +22921 -0.24365234375 +22922 -0.1983642578125 +22923 -0.116241455078125 +22924 -0.036834716796875 +22925 0.034881591796875 +22926 0.09124755859375 +22927 0.10888671875 +22928 0.125518798828125 +22929 0.15771484375 +22930 0.17828369140625 +22931 0.17108154296875 +22932 0.129974365234375 +22933 0.082427978515625 +22934 0.027679443359375 +22935 -0.065643310546875 +22936 -0.15936279296875 +22937 -0.21307373046875 +22938 -0.234649658203125 +22939 -0.2001953125 +22940 -0.119171142578125 +22941 -0.024749755859375 +22942 0.085784912109375 +22943 0.178131103515625 +22944 0.215576171875 +22945 0.211456298828125 +22946 0.17523193359375 +22947 0.128753662109375 +22948 0.1019287109375 +22949 0.0743408203125 +22950 0.04327392578125 +22951 0.038177490234375 +22952 0.076263427734375 +22953 0.14105224609375 +22954 0.186431884765625 +22955 0.188812255859375 +22956 0.1390380859375 +22957 0.041778564453125 +22958 -0.079437255859375 +22959 -0.219390869140625 +22960 -0.367828369140625 +22961 -0.494873046875 +22962 -0.556243896484375 +22963 -0.508697509765625 +22964 -0.3756103515625 +22965 -0.218902587890625 +22966 -0.063751220703125 +22967 0.091552734375 +22968 0.23602294921875 +22969 0.342987060546875 +22970 0.39520263671875 +22971 0.389373779296875 +22972 0.324249267578125 +22973 0.224090576171875 +22974 0.124267578125 +22975 0.037078857421875 +22976 -0.010101318359375 +22977 -0.019439697265625 +22978 -0.022796630859375 +22979 -0.001556396484375 +22980 0.056304931640625 +22981 0.106719970703125 +22982 0.096893310546875 +22983 0.042694091796875 +22984 -0.018035888671875 +22985 -0.07586669921875 +22986 -0.11944580078125 +22987 -0.15972900390625 +22988 -0.202606201171875 +22989 -0.24859619140625 +22990 -0.30517578125 +22991 -0.36212158203125 +22992 -0.39141845703125 +22993 -0.35528564453125 +22994 -0.249969482421875 +22995 -0.092864990234375 +22996 0.08905029296875 +22997 0.2352294921875 +22998 0.318817138671875 +22999 0.358642578125 +23000 0.347747802734375 +23001 0.28564453125 +23002 0.223175048828125 +23003 0.196746826171875 +23004 0.179840087890625 +23005 0.155548095703125 +23006 0.151214599609375 +23007 0.156951904296875 +23008 0.13177490234375 +23009 0.100799560546875 +23010 0.087127685546875 +23011 0.05487060546875 +23012 -0.009002685546875 +23013 -0.10400390625 +23014 -0.229400634765625 +23015 -0.35552978515625 +23016 -0.441925048828125 +23017 -0.473846435546875 +23018 -0.464813232421875 +23019 -0.419097900390625 +23020 -0.334320068359375 +23021 -0.227935791015625 +23022 -0.12347412109375 +23023 -0.02764892578125 +23024 0.077667236328125 +23025 0.2132568359375 +23026 0.38885498046875 +23027 0.582794189453125 +23028 0.734039306640625 +23029 0.800140380859375 +23030 0.7783203125 +23031 0.6651611328125 +23032 0.45965576171875 +23033 0.199188232421875 +23034 -0.050689697265625 +23035 -0.23297119140625 +23036 -0.33013916015625 +23037 -0.368408203125 +23038 -0.378936767578125 +23039 -0.376983642578125 +23040 -0.37969970703125 +23041 -0.391510009765625 +23042 -0.385345458984375 +23043 -0.3419189453125 +23044 -0.28289794921875 +23045 -0.251617431640625 +23046 -0.266143798828125 +23047 -0.273345947265625 +23048 -0.216796875 +23049 -0.128265380859375 +23050 -0.068145751953125 +23051 -0.0430908203125 +23052 -0.024444580078125 +23053 0.020721435546875 +23054 0.124481201171875 +23055 0.25787353515625 +23056 0.379119873046875 +23057 0.47991943359375 +23058 0.5281982421875 +23059 0.511138916015625 +23060 0.456207275390625 +23061 0.407470703125 +23062 0.383758544921875 +23063 0.35687255859375 +23064 0.31182861328125 +23065 0.250885009765625 +23066 0.1654052734375 +23067 0.035247802734375 +23068 -0.142059326171875 +23069 -0.33563232421875 +23070 -0.5345458984375 +23071 -0.72186279296875 +23072 -0.836669921875 +23073 -0.8326416015625 +23074 -0.7296142578125 +23075 -0.582550048828125 +23076 -0.440093994140625 +23077 -0.324310302734375 +23078 -0.20147705078125 +23079 -0.044647216796875 +23080 0.103973388671875 +23081 0.202392578125 +23082 0.264495849609375 +23083 0.338897705078125 +23084 0.443817138671875 +23085 0.545074462890625 +23086 0.6173095703125 +23087 0.6524658203125 +23088 0.66339111328125 +23089 0.6561279296875 +23090 0.606781005859375 +23091 0.501190185546875 +23092 0.352783203125 +23093 0.176544189453125 +23094 -0.034820556640625 +23095 -0.258209228515625 +23096 -0.44244384765625 +23097 -0.5753173828125 +23098 -0.65203857421875 +23099 -0.641632080078125 +23100 -0.562164306640625 +23101 -0.458038330078125 +23102 -0.350555419921875 +23103 -0.260528564453125 +23104 -0.192108154296875 +23105 -0.141937255859375 +23106 -0.1021728515625 +23107 -0.062896728515625 +23108 -0.011932373046875 +23109 0.062835693359375 +23110 0.148712158203125 +23111 0.241729736328125 +23112 0.34912109375 +23113 0.457305908203125 +23114 0.54388427734375 +23115 0.5728759765625 +23116 0.506591796875 +23117 0.351226806640625 +23118 0.146514892578125 +23119 -0.05523681640625 +23120 -0.21624755859375 +23121 -0.334930419921875 +23122 -0.402984619140625 +23123 -0.4412841796875 +23124 -0.49578857421875 +23125 -0.5601806640625 +23126 -0.600738525390625 +23127 -0.584228515625 +23128 -0.47930908203125 +23129 -0.27935791015625 +23130 -0.0089111328125 +23131 0.268798828125 +23132 0.482818603515625 +23133 0.60369873046875 +23134 0.650421142578125 +23135 0.66400146484375 +23136 0.6414794921875 +23137 0.572540283203125 +23138 0.498138427734375 +23139 0.439453125 +23140 0.375518798828125 +23141 0.274505615234375 +23142 0.1087646484375 +23143 -0.099395751953125 +23144 -0.3182373046875 +23145 -0.5489501953125 +23146 -0.7738037109375 +23147 -0.86383056640625 +23148 -0.870391845703125 +23149 -0.86895751953125 +23150 -0.861053466796875 +23151 -0.765869140625 +23152 -0.5301513671875 +23153 -0.214691162109375 +23154 0.137359619140625 +23155 0.474822998046875 +23156 0.76239013671875 +23157 0.867462158203125 +23158 0.870361328125 +23159 0.86480712890625 +23160 0.831817626953125 +23161 0.677581787109375 +23162 0.495880126953125 +23163 0.30767822265625 +23164 0.116180419921875 +23165 -0.110748291015625 +23166 -0.381805419921875 +23167 -0.6572265625 +23168 -0.857421875 +23169 -0.870391845703125 +23170 -0.870391845703125 +23171 -0.86444091796875 +23172 -0.85723876953125 +23173 -0.790008544921875 +23174 -0.62847900390625 +23175 -0.3956298828125 +23176 -0.126708984375 +23177 0.150115966796875 +23178 0.424041748046875 +23179 0.670623779296875 +23180 0.854522705078125 +23181 0.866485595703125 +23182 0.86920166015625 +23183 0.8653564453125 +23184 0.857147216796875 +23185 0.766845703125 +23186 0.628509521484375 +23187 0.462127685546875 +23188 0.297210693359375 +23189 0.14862060546875 +23190 -0.00537109375 +23191 -0.15753173828125 +23192 -0.31304931640625 +23193 -0.48876953125 +23194 -0.6416015625 +23195 -0.751373291015625 +23196 -0.84619140625 +23197 -0.861297607421875 +23198 -0.863250732421875 +23199 -0.856597900390625 +23200 -0.7498779296875 +23201 -0.624542236328125 +23202 -0.47808837890625 +23203 -0.253387451171875 +23204 0.003692626953125 +23205 0.2257080078125 +23206 0.427154541015625 +23207 0.643218994140625 +23208 0.855926513671875 +23209 0.870361328125 +23210 0.870361328125 +23211 0.862762451171875 +23212 0.79669189453125 +23213 0.595794677734375 +23214 0.362152099609375 +23215 0.1270751953125 +23216 -0.086944580078125 +23217 -0.2784423828125 +23218 -0.484832763671875 +23219 -0.729583740234375 +23220 -0.86688232421875 +23221 -0.870391845703125 +23222 -0.86859130859375 +23223 -0.86279296875 +23224 -0.817962646484375 +23225 -0.6116943359375 +23226 -0.3128662109375 +23227 0.039398193359375 +23228 0.422821044921875 +23229 0.805145263671875 +23230 0.870361328125 +23231 0.870361328125 +23232 0.860015869140625 +23233 0.727935791015625 +23234 0.48114013671875 +23235 0.2059326171875 +23236 -0.06103515625 +23237 -0.29913330078125 +23238 -0.516204833984375 +23239 -0.7252197265625 +23240 -0.85980224609375 +23241 -0.870391845703125 +23242 -0.870391845703125 +23243 -0.858062744140625 +23244 -0.673004150390625 +23245 -0.42694091796875 +23246 -0.2100830078125 +23247 -0.0362548828125 +23248 0.10943603515625 +23249 0.23516845703125 +23250 0.373687744140625 +23251 0.517791748046875 +23252 0.602783203125 +23253 0.635711669921875 +23254 0.655181884765625 +23255 0.65948486328125 +23256 0.651275634765625 +23257 0.61846923828125 +23258 0.53753662109375 +23259 0.404144287109375 +23260 0.22186279296875 +23261 0.003997802734375 +23262 -0.22100830078125 +23263 -0.42449951171875 +23264 -0.579833984375 +23265 -0.641876220703125 +23266 -0.6177978515625 +23267 -0.575531005859375 +23268 -0.526336669921875 +23269 -0.42645263671875 +23270 -0.2581787109375 +23271 -0.068695068359375 +23272 0.09222412109375 +23273 0.232147216796875 +23274 0.3509521484375 +23275 0.410064697265625 +23276 0.372955322265625 +23277 0.2554931640625 +23278 0.10711669921875 +23279 -0.052886962890625 +23280 -0.186279296875 +23281 -0.23291015625 +23282 -0.209442138671875 +23283 -0.174163818359375 +23284 -0.126739501953125 +23285 -0.048126220703125 +23286 0.0426025390625 +23287 0.10748291015625 +23288 0.1409912109375 +23289 0.19708251953125 +23290 0.273651123046875 +23291 0.31768798828125 +23292 0.341094970703125 +23293 0.368011474609375 +23294 0.37249755859375 +23295 0.30072021484375 +23296 0.1517333984375 +23297 -0.01470947265625 +23298 -0.1883544921875 +23299 -0.372711181640625 +23300 -0.51397705078125 +23301 -0.57177734375 +23302 -0.53948974609375 +23303 -0.43511962890625 +23304 -0.2962646484375 +23305 -0.161102294921875 +23306 -0.0435791015625 +23307 0.060394287109375 +23308 0.13665771484375 +23309 0.170135498046875 +23310 0.16552734375 +23311 0.15728759765625 +23312 0.150787353515625 +23313 0.12200927734375 +23314 0.080108642578125 +23315 0.05126953125 +23316 0.062896728515625 +23317 0.09271240234375 +23318 0.092987060546875 +23319 0.07855224609375 +23320 0.06427001953125 +23321 0.0347900390625 +23322 -0.01171875 +23323 -0.056060791015625 +23324 -0.055511474609375 +23325 -0.010467529296875 +23326 0.02508544921875 +23327 0.025665283203125 +23328 0.017333984375 +23329 0.00189208984375 +23330 -0.03173828125 +23331 -0.071502685546875 +23332 -0.13543701171875 +23333 -0.219970703125 +23334 -0.300506591796875 +23335 -0.376312255859375 +23336 -0.416107177734375 +23337 -0.371124267578125 +23338 -0.242279052734375 +23339 -0.069732666015625 +23340 0.125640869140625 +23341 0.31268310546875 +23342 0.45501708984375 +23343 0.554779052734375 +23344 0.61065673828125 +23345 0.610931396484375 +23346 0.531463623046875 +23347 0.3883056640625 +23348 0.23468017578125 +23349 0.095245361328125 +23350 -0.00396728515625 +23351 -0.04852294921875 +23352 -0.055145263671875 +23353 -0.0758056640625 +23354 -0.138702392578125 +23355 -0.209197998046875 +23356 -0.289031982421875 +23357 -0.37884521484375 +23358 -0.456329345703125 +23359 -0.51641845703125 +23360 -0.519287109375 +23361 -0.458251953125 +23362 -0.384796142578125 +23363 -0.323699951171875 +23364 -0.269287109375 +23365 -0.1951904296875 +23366 -0.100006103515625 +23367 -0.01055908203125 +23368 0.1033935546875 +23369 0.24908447265625 +23370 0.373199462890625 +23371 0.45806884765625 +23372 0.511474609375 +23373 0.565399169921875 +23374 0.61138916015625 +23375 0.5897216796875 +23376 0.4906005859375 +23377 0.33148193359375 +23378 0.147796630859375 +23379 -0.01873779296875 +23380 -0.140289306640625 +23381 -0.191986083984375 +23382 -0.184295654296875 +23383 -0.161834716796875 +23384 -0.166595458984375 +23385 -0.19390869140625 +23386 -0.22442626953125 +23387 -0.279754638671875 +23388 -0.3389892578125 +23389 -0.3543701171875 +23390 -0.348175048828125 +23391 -0.32598876953125 +23392 -0.2581787109375 +23393 -0.139801025390625 +23394 0.014617919921875 +23395 0.144378662109375 +23396 0.221038818359375 +23397 0.27069091796875 +23398 0.294036865234375 +23399 0.311767578125 +23400 0.339141845703125 +23401 0.360260009765625 +23402 0.360504150390625 +23403 0.308380126953125 +23404 0.18170166015625 +23405 0.0047607421875 +23406 -0.17559814453125 +23407 -0.3143310546875 +23408 -0.36785888671875 +23409 -0.36248779296875 +23410 -0.343536376953125 +23411 -0.3018798828125 +23412 -0.231414794921875 +23413 -0.117645263671875 +23414 0.007049560546875 +23415 0.087982177734375 +23416 0.13946533203125 +23417 0.17425537109375 +23418 0.188201904296875 +23419 0.171234130859375 +23420 0.118438720703125 +23421 0.05706787109375 +23422 -0.010711669921875 +23423 -0.0914306640625 +23424 -0.162322998046875 +23425 -0.194549560546875 +23426 -0.1492919921875 +23427 -0.02166748046875 +23428 0.124053955078125 +23429 0.211151123046875 +23430 0.240447998046875 +23431 0.242218017578125 +23432 0.2257080078125 +23433 0.194366455078125 +23434 0.115509033203125 +23435 0.0128173828125 +23436 -0.053802490234375 +23437 -0.110626220703125 +23438 -0.199493408203125 +23439 -0.29437255859375 +23440 -0.33221435546875 +23441 -0.27972412109375 +23442 -0.185333251953125 +23443 -0.128204345703125 +23444 -0.115692138671875 +23445 -0.116455078125 +23446 -0.105926513671875 +23447 -0.053955078125 +23448 0.048797607421875 +23449 0.157318115234375 +23450 0.212005615234375 +23451 0.218475341796875 +23452 0.23724365234375 +23453 0.30535888671875 +23454 0.38128662109375 +23455 0.404449462890625 +23456 0.3944091796875 +23457 0.3885498046875 +23458 0.362640380859375 +23459 0.27362060546875 +23460 0.11712646484375 +23461 -0.054901123046875 +23462 -0.19085693359375 +23463 -0.28570556640625 +23464 -0.339263916015625 +23465 -0.3775634765625 +23466 -0.445709228515625 +23467 -0.535064697265625 +23468 -0.629058837890625 +23469 -0.697601318359375 +23470 -0.70391845703125 +23471 -0.6424560546875 +23472 -0.491241455078125 +23473 -0.265716552734375 +23474 -0.023712158203125 +23475 0.201751708984375 +23476 0.375823974609375 +23477 0.485076904296875 +23478 0.56884765625 +23479 0.634765625 +23480 0.63763427734375 +23481 0.5660400390625 +23482 0.4720458984375 +23483 0.40692138671875 +23484 0.3778076171875 +23485 0.376953125 +23486 0.371978759765625 +23487 0.313140869140625 +23488 0.184417724609375 +23489 0.011199951171875 +23490 -0.171051025390625 +23491 -0.33740234375 +23492 -0.47198486328125 +23493 -0.560394287109375 +23494 -0.58056640625 +23495 -0.54754638671875 +23496 -0.508575439453125 +23497 -0.459503173828125 +23498 -0.394378662109375 +23499 -0.35260009765625 +23500 -0.31170654296875 +23501 -0.197418212890625 +23502 -0.007965087890625 +23503 0.207489013671875 +23504 0.409210205078125 +23505 0.57208251953125 +23506 0.66595458984375 +23507 0.65875244140625 +23508 0.56744384765625 +23509 0.431396484375 +23510 0.29443359375 +23511 0.182464599609375 +23512 0.06365966796875 +23513 -0.075958251953125 +23514 -0.189422607421875 +23515 -0.271942138671875 +23516 -0.342529296875 +23517 -0.364166259765625 +23518 -0.327239990234375 +23519 -0.2769775390625 +23520 -0.253692626953125 +23521 -0.24365234375 +23522 -0.1983642578125 +23523 -0.116241455078125 +23524 -0.036834716796875 +23525 0.034881591796875 +23526 0.09124755859375 +23527 0.10888671875 +23528 0.125518798828125 +23529 0.15771484375 +23530 0.17828369140625 +23531 0.17108154296875 +23532 0.129974365234375 +23533 0.082427978515625 +23534 0.027679443359375 +23535 -0.065643310546875 +23536 -0.15936279296875 +23537 -0.21307373046875 +23538 -0.234649658203125 +23539 -0.2001953125 +23540 -0.119171142578125 +23541 -0.024749755859375 +23542 0.085784912109375 +23543 0.178131103515625 +23544 0.215576171875 +23545 0.211456298828125 +23546 0.17523193359375 +23547 0.128753662109375 +23548 0.1019287109375 +23549 0.0743408203125 +23550 0.04327392578125 +23551 0.038177490234375 +23552 0.076263427734375 +23553 0.14105224609375 +23554 0.186431884765625 +23555 0.188812255859375 +23556 0.1390380859375 +23557 0.041778564453125 +23558 -0.079437255859375 +23559 -0.219390869140625 +23560 -0.367828369140625 +23561 -0.494873046875 +23562 -0.556243896484375 +23563 -0.508697509765625 +23564 -0.3756103515625 +23565 -0.218902587890625 +23566 -0.063751220703125 +23567 0.091552734375 +23568 0.23602294921875 +23569 0.342987060546875 +23570 0.39520263671875 +23571 0.389373779296875 +23572 0.324249267578125 +23573 0.224090576171875 +23574 0.124267578125 +23575 0.037078857421875 +23576 -0.010101318359375 +23577 -0.019439697265625 +23578 -0.022796630859375 +23579 -0.001556396484375 +23580 0.056304931640625 +23581 0.106719970703125 +23582 0.096893310546875 +23583 0.042694091796875 +23584 -0.018035888671875 +23585 -0.07586669921875 +23586 -0.11944580078125 +23587 -0.15972900390625 +23588 -0.202606201171875 +23589 -0.24859619140625 +23590 -0.30517578125 +23591 -0.36212158203125 +23592 -0.39141845703125 +23593 -0.35528564453125 +23594 -0.249969482421875 +23595 -0.092864990234375 +23596 0.08905029296875 +23597 0.2352294921875 +23598 0.318817138671875 +23599 0.358642578125 +23600 0.347747802734375 +23601 0.28564453125 +23602 0.223175048828125 +23603 0.196746826171875 +23604 0.179840087890625 +23605 0.155548095703125 +23606 0.151214599609375 +23607 0.156951904296875 +23608 0.13177490234375 +23609 0.100799560546875 +23610 0.087127685546875 +23611 0.05487060546875 +23612 -0.009002685546875 +23613 -0.10400390625 +23614 -0.229400634765625 +23615 -0.35552978515625 +23616 -0.441925048828125 +23617 -0.473846435546875 +23618 -0.464813232421875 +23619 -0.419097900390625 +23620 -0.334320068359375 +23621 -0.227935791015625 +23622 -0.12347412109375 +23623 -0.02764892578125 +23624 0.077667236328125 +23625 0.2132568359375 +23626 0.38885498046875 +23627 0.582794189453125 +23628 0.734039306640625 +23629 0.800140380859375 +23630 0.7783203125 +23631 0.6651611328125 +23632 0.45965576171875 +23633 0.199188232421875 +23634 -0.050689697265625 +23635 -0.23297119140625 +23636 -0.33013916015625 +23637 -0.368408203125 +23638 -0.378936767578125 +23639 -0.376983642578125 +23640 -0.37969970703125 +23641 -0.391510009765625 +23642 -0.385345458984375 +23643 -0.3419189453125 +23644 -0.28289794921875 +23645 -0.251617431640625 +23646 -0.266143798828125 +23647 -0.273345947265625 +23648 -0.216796875 +23649 -0.128265380859375 +23650 -0.068145751953125 +23651 -0.0430908203125 +23652 -0.024444580078125 +23653 0.020721435546875 +23654 0.124481201171875 +23655 0.25787353515625 +23656 0.379119873046875 +23657 0.47991943359375 +23658 0.5281982421875 +23659 0.511138916015625 +23660 0.456207275390625 +23661 0.407470703125 +23662 0.383758544921875 +23663 0.35687255859375 +23664 0.31182861328125 +23665 0.250885009765625 +23666 0.1654052734375 +23667 0.035247802734375 +23668 -0.142059326171875 +23669 -0.33563232421875 +23670 -0.5345458984375 +23671 -0.72186279296875 +23672 -0.836669921875 +23673 -0.8326416015625 +23674 -0.7296142578125 +23675 -0.582550048828125 +23676 -0.440093994140625 +23677 -0.324310302734375 +23678 -0.20147705078125 +23679 -0.044647216796875 +23680 0.103973388671875 +23681 0.202392578125 +23682 0.264495849609375 +23683 0.338897705078125 +23684 0.443817138671875 +23685 0.545074462890625 +23686 0.6173095703125 +23687 0.6524658203125 +23688 0.66339111328125 +23689 0.6561279296875 +23690 0.606781005859375 +23691 0.501190185546875 +23692 0.352783203125 +23693 0.176544189453125 +23694 -0.034820556640625 +23695 -0.258209228515625 +23696 -0.44244384765625 +23697 -0.5753173828125 +23698 -0.65203857421875 +23699 -0.641632080078125 +23700 -0.562164306640625 +23701 -0.458038330078125 +23702 -0.350555419921875 +23703 -0.260528564453125 +23704 -0.192108154296875 +23705 -0.141937255859375 +23706 -0.1021728515625 +23707 -0.062896728515625 +23708 -0.011932373046875 +23709 0.062835693359375 +23710 0.148712158203125 +23711 0.241729736328125 +23712 0.34912109375 +23713 0.457305908203125 +23714 0.54388427734375 +23715 0.5728759765625 +23716 0.506591796875 +23717 0.351226806640625 +23718 0.146514892578125 +23719 -0.05523681640625 +23720 -0.21624755859375 +23721 -0.334930419921875 +23722 -0.402984619140625 +23723 -0.4412841796875 +23724 -0.49578857421875 +23725 -0.5601806640625 +23726 -0.600738525390625 +23727 -0.584228515625 +23728 -0.47930908203125 +23729 -0.27935791015625 +23730 -0.0089111328125 +23731 0.268798828125 +23732 0.482818603515625 +23733 0.60369873046875 +23734 0.650421142578125 +23735 0.66400146484375 +23736 0.6414794921875 +23737 0.572540283203125 +23738 0.498138427734375 +23739 0.439453125 +23740 0.375518798828125 +23741 0.274505615234375 +23742 0.1087646484375 +23743 -0.099395751953125 +23744 -0.3182373046875 +23745 -0.5489501953125 +23746 -0.7738037109375 +23747 -0.86383056640625 +23748 -0.870391845703125 +23749 -0.86895751953125 +23750 -0.861053466796875 +23751 -0.765869140625 +23752 -0.5301513671875 +23753 -0.214691162109375 +23754 0.137359619140625 +23755 0.474822998046875 +23756 0.76239013671875 +23757 0.867462158203125 +23758 0.870361328125 +23759 0.86480712890625 +23760 0.831817626953125 +23761 0.677581787109375 +23762 0.495880126953125 +23763 0.30767822265625 +23764 0.116180419921875 +23765 -0.110748291015625 +23766 -0.381805419921875 +23767 -0.6572265625 +23768 -0.857421875 +23769 -0.870391845703125 +23770 -0.870391845703125 +23771 -0.86444091796875 +23772 -0.85723876953125 +23773 -0.790008544921875 +23774 -0.62847900390625 +23775 -0.3956298828125 +23776 -0.126708984375 +23777 0.150115966796875 +23778 0.424041748046875 +23779 0.670623779296875 +23780 0.854522705078125 +23781 0.866485595703125 +23782 0.86920166015625 +23783 0.8653564453125 +23784 0.857147216796875 +23785 0.766845703125 +23786 0.628509521484375 +23787 0.462127685546875 +23788 0.297210693359375 +23789 0.14862060546875 +23790 -0.00537109375 +23791 -0.15753173828125 +23792 -0.31304931640625 +23793 -0.48876953125 +23794 -0.6416015625 +23795 -0.751373291015625 +23796 -0.84619140625 +23797 -0.861297607421875 +23798 -0.863250732421875 +23799 -0.856597900390625 +23800 -0.7498779296875 +23801 -0.624542236328125 +23802 -0.47808837890625 +23803 -0.253387451171875 +23804 0.003692626953125 +23805 0.2257080078125 +23806 0.427154541015625 +23807 0.643218994140625 +23808 0.855926513671875 +23809 0.870361328125 +23810 0.870361328125 +23811 0.862762451171875 +23812 0.79669189453125 +23813 0.595794677734375 +23814 0.362152099609375 +23815 0.1270751953125 +23816 -0.086944580078125 +23817 -0.2784423828125 +23818 -0.484832763671875 +23819 -0.729583740234375 +23820 -0.86688232421875 +23821 -0.870391845703125 +23822 -0.86859130859375 +23823 -0.86279296875 +23824 -0.817962646484375 +23825 -0.6116943359375 +23826 -0.3128662109375 +23827 0.039398193359375 +23828 0.422821044921875 +23829 0.805145263671875 +23830 0.870361328125 +23831 0.870361328125 +23832 0.860015869140625 +23833 0.727935791015625 +23834 0.48114013671875 +23835 0.2059326171875 +23836 -0.06103515625 +23837 -0.29913330078125 +23838 -0.516204833984375 +23839 -0.7252197265625 +23840 -0.85980224609375 +23841 -0.870391845703125 +23842 -0.870391845703125 +23843 -0.858062744140625 +23844 -0.673004150390625 +23845 -0.42694091796875 +23846 -0.2100830078125 +23847 -0.0362548828125 +23848 0.10943603515625 +23849 0.23516845703125 +23850 0.373687744140625 +23851 0.517791748046875 +23852 0.602783203125 +23853 0.635711669921875 +23854 0.655181884765625 +23855 0.65948486328125 +23856 0.651275634765625 +23857 0.61846923828125 +23858 0.53753662109375 +23859 0.404144287109375 +23860 0.22186279296875 +23861 0.003997802734375 +23862 -0.22100830078125 +23863 -0.42449951171875 +23864 -0.579833984375 +23865 -0.641876220703125 +23866 -0.6177978515625 +23867 -0.575531005859375 +23868 -0.526336669921875 +23869 -0.42645263671875 +23870 -0.2581787109375 +23871 -0.068695068359375 +23872 0.09222412109375 +23873 0.232147216796875 +23874 0.3509521484375 +23875 0.410064697265625 +23876 0.372955322265625 +23877 0.2554931640625 +23878 0.10711669921875 +23879 -0.052886962890625 +23880 -0.186279296875 +23881 -0.23291015625 +23882 -0.209442138671875 +23883 -0.174163818359375 +23884 -0.126739501953125 +23885 -0.048126220703125 +23886 0.0426025390625 +23887 0.10748291015625 +23888 0.1409912109375 +23889 0.19708251953125 +23890 0.273651123046875 +23891 0.31768798828125 +23892 0.341094970703125 +23893 0.368011474609375 +23894 0.37249755859375 +23895 0.30072021484375 +23896 0.1517333984375 +23897 -0.01470947265625 +23898 -0.1883544921875 +23899 -0.372711181640625 +23900 -0.51397705078125 +23901 -0.57177734375 +23902 -0.53948974609375 +23903 -0.43511962890625 +23904 -0.2962646484375 +23905 -0.161102294921875 +23906 -0.0435791015625 +23907 0.060394287109375 +23908 0.13665771484375 +23909 0.170135498046875 +23910 0.16552734375 +23911 0.15728759765625 +23912 0.150787353515625 +23913 0.12200927734375 +23914 0.080108642578125 +23915 0.05126953125 +23916 0.062896728515625 +23917 0.09271240234375 +23918 0.092987060546875 +23919 0.07855224609375 +23920 0.06427001953125 +23921 0.0347900390625 +23922 -0.01171875 +23923 -0.056060791015625 +23924 -0.055511474609375 +23925 -0.010467529296875 +23926 0.02508544921875 +23927 0.025665283203125 +23928 0.017333984375 +23929 0.00189208984375 +23930 -0.03173828125 +23931 -0.071502685546875 +23932 -0.13543701171875 +23933 -0.219970703125 +23934 -0.300506591796875 +23935 -0.376312255859375 +23936 -0.416107177734375 +23937 -0.371124267578125 +23938 -0.242279052734375 +23939 -0.069732666015625 +23940 0.125640869140625 +23941 0.31268310546875 +23942 0.45501708984375 +23943 0.554779052734375 +23944 0.61065673828125 +23945 0.610931396484375 +23946 0.531463623046875 +23947 0.3883056640625 +23948 0.23468017578125 +23949 0.095245361328125 +23950 -0.00396728515625 +23951 -0.04852294921875 +23952 -0.055145263671875 +23953 -0.0758056640625 +23954 -0.138702392578125 +23955 -0.209197998046875 +23956 -0.289031982421875 +23957 -0.37884521484375 +23958 -0.456329345703125 +23959 -0.51641845703125 +23960 -0.519287109375 +23961 -0.458251953125 +23962 -0.384796142578125 +23963 -0.323699951171875 +23964 -0.269287109375 +23965 -0.1951904296875 +23966 -0.100006103515625 +23967 -0.01055908203125 +23968 0.1033935546875 +23969 0.24908447265625 +23970 0.373199462890625 +23971 0.45806884765625 +23972 0.511474609375 +23973 0.565399169921875 +23974 0.61138916015625 +23975 0.5897216796875 +23976 0.4906005859375 +23977 0.33148193359375 +23978 0.147796630859375 +23979 -0.01873779296875 +23980 -0.140289306640625 +23981 -0.191986083984375 +23982 -0.184295654296875 +23983 -0.161834716796875 +23984 -0.166595458984375 +23985 -0.19390869140625 +23986 -0.22442626953125 +23987 -0.279754638671875 +23988 -0.3389892578125 +23989 -0.3543701171875 +23990 -0.348175048828125 +23991 -0.32598876953125 +23992 -0.2581787109375 +23993 -0.139801025390625 +23994 0.014617919921875 +23995 0.144378662109375 +23996 0.221038818359375 +23997 0.27069091796875 +23998 0.294036865234375 +23999 0.311767578125 +24000 0.339141845703125 +24001 0.360260009765625 +24002 0.360504150390625 +24003 0.308380126953125 +24004 0.18170166015625 +24005 0.0047607421875 +24006 -0.17559814453125 +24007 -0.3143310546875 +24008 -0.36785888671875 +24009 -0.36248779296875 +24010 -0.343536376953125 +24011 -0.3018798828125 +24012 -0.231414794921875 +24013 -0.117645263671875 +24014 0.007049560546875 +24015 0.087982177734375 +24016 0.13946533203125 +24017 0.17425537109375 +24018 0.188201904296875 +24019 0.171234130859375 +24020 0.118438720703125 +24021 0.05706787109375 +24022 -0.010711669921875 +24023 -0.0914306640625 +24024 -0.162322998046875 +24025 -0.194549560546875 +24026 -0.1492919921875 +24027 -0.02166748046875 +24028 0.124053955078125 +24029 0.211151123046875 +24030 0.240447998046875 +24031 0.242218017578125 +24032 0.2257080078125 +24033 0.194366455078125 +24034 0.115509033203125 +24035 0.0128173828125 +24036 -0.053802490234375 +24037 -0.110626220703125 +24038 -0.199493408203125 +24039 -0.29437255859375 +24040 -0.33221435546875 +24041 -0.27972412109375 +24042 -0.185333251953125 +24043 -0.128204345703125 +24044 -0.115692138671875 +24045 -0.116455078125 +24046 -0.105926513671875 +24047 -0.053955078125 +24048 0.048797607421875 +24049 0.157318115234375 +24050 0.212005615234375 +24051 0.218475341796875 +24052 0.23724365234375 +24053 0.30535888671875 +24054 0.38128662109375 +24055 0.404449462890625 +24056 0.3944091796875 +24057 0.3885498046875 +24058 0.362640380859375 +24059 0.27362060546875 +24060 0.11712646484375 +24061 -0.054901123046875 +24062 -0.19085693359375 +24063 -0.28570556640625 +24064 -0.339263916015625 +24065 -0.3775634765625 +24066 -0.445709228515625 +24067 -0.535064697265625 +24068 -0.629058837890625 +24069 -0.697601318359375 +24070 -0.70391845703125 +24071 -0.6424560546875 +24072 -0.491241455078125 +24073 -0.265716552734375 +24074 -0.023712158203125 +24075 0.201751708984375 +24076 0.375823974609375 +24077 0.485076904296875 +24078 0.56884765625 +24079 0.634765625 +24080 0.63763427734375 +24081 0.5660400390625 +24082 0.4720458984375 +24083 0.40692138671875 +24084 0.3778076171875 +24085 0.376953125 +24086 0.371978759765625 +24087 0.313140869140625 +24088 0.184417724609375 +24089 0.011199951171875 +24090 -0.171051025390625 +24091 -0.33740234375 +24092 -0.47198486328125 +24093 -0.560394287109375 +24094 -0.58056640625 +24095 -0.54754638671875 +24096 -0.508575439453125 +24097 -0.459503173828125 +24098 -0.394378662109375 +24099 -0.35260009765625 +24100 -0.31170654296875 +24101 -0.197418212890625 +24102 -0.007965087890625 +24103 0.207489013671875 +24104 0.409210205078125 +24105 0.57208251953125 +24106 0.66595458984375 +24107 0.65875244140625 +24108 0.56744384765625 +24109 0.431396484375 +24110 0.29443359375 +24111 0.182464599609375 +24112 0.06365966796875 +24113 -0.075958251953125 +24114 -0.189422607421875 +24115 -0.271942138671875 +24116 -0.342529296875 +24117 -0.364166259765625 +24118 -0.327239990234375 +24119 -0.2769775390625 +24120 -0.253692626953125 +24121 -0.24365234375 +24122 -0.1983642578125 +24123 -0.116241455078125 +24124 -0.036834716796875 +24125 0.034881591796875 +24126 0.09124755859375 +24127 0.10888671875 +24128 0.125518798828125 +24129 0.15771484375 +24130 0.17828369140625 +24131 0.17108154296875 +24132 0.129974365234375 +24133 0.082427978515625 +24134 0.027679443359375 +24135 -0.065643310546875 +24136 -0.15936279296875 +24137 -0.21307373046875 +24138 -0.234649658203125 +24139 -0.2001953125 +24140 -0.119171142578125 +24141 -0.024749755859375 +24142 0.085784912109375 +24143 0.178131103515625 +24144 0.215576171875 +24145 0.211456298828125 +24146 0.17523193359375 +24147 0.128753662109375 +24148 0.1019287109375 +24149 0.0743408203125 +24150 0.04327392578125 +24151 0.038177490234375 +24152 0.076263427734375 +24153 0.14105224609375 +24154 0.186431884765625 +24155 0.188812255859375 +24156 0.1390380859375 +24157 0.041778564453125 +24158 -0.079437255859375 +24159 -0.219390869140625 +24160 -0.367828369140625 +24161 -0.494873046875 +24162 -0.556243896484375 +24163 -0.508697509765625 +24164 -0.3756103515625 +24165 -0.218902587890625 +24166 -0.063751220703125 +24167 0.091552734375 +24168 0.23602294921875 +24169 0.342987060546875 +24170 0.39520263671875 +24171 0.389373779296875 +24172 0.324249267578125 +24173 0.224090576171875 +24174 0.124267578125 +24175 0.037078857421875 +24176 -0.010101318359375 +24177 -0.019439697265625 +24178 -0.022796630859375 +24179 -0.001556396484375 +24180 0.056304931640625 +24181 0.106719970703125 +24182 0.096893310546875 +24183 0.042694091796875 +24184 -0.018035888671875 +24185 -0.07586669921875 +24186 -0.11944580078125 +24187 -0.15972900390625 +24188 -0.202606201171875 +24189 -0.24859619140625 +24190 -0.30517578125 +24191 -0.36212158203125 +24192 -0.39141845703125 +24193 -0.35528564453125 +24194 -0.249969482421875 +24195 -0.092864990234375 +24196 0.08905029296875 +24197 0.2352294921875 +24198 0.318817138671875 +24199 0.358642578125 +24200 0.347747802734375 +24201 0.28564453125 +24202 0.223175048828125 +24203 0.196746826171875 +24204 0.179840087890625 +24205 0.155548095703125 +24206 0.151214599609375 +24207 0.156951904296875 +24208 0.13177490234375 +24209 0.100799560546875 +24210 0.087127685546875 +24211 0.05487060546875 +24212 -0.009002685546875 +24213 -0.10400390625 +24214 -0.229400634765625 +24215 -0.35552978515625 +24216 -0.441925048828125 +24217 -0.473846435546875 +24218 -0.464813232421875 +24219 -0.419097900390625 +24220 -0.334320068359375 +24221 -0.227935791015625 +24222 -0.12347412109375 +24223 -0.02764892578125 +24224 0.077667236328125 +24225 0.2132568359375 +24226 0.38885498046875 +24227 0.582794189453125 +24228 0.734039306640625 +24229 0.800140380859375 +24230 0.7783203125 +24231 0.6651611328125 +24232 0.45965576171875 +24233 0.199188232421875 +24234 -0.050689697265625 +24235 -0.23297119140625 +24236 -0.33013916015625 +24237 -0.368408203125 +24238 -0.378936767578125 +24239 -0.376983642578125 +24240 -0.37969970703125 +24241 -0.391510009765625 +24242 -0.385345458984375 +24243 -0.3419189453125 +24244 -0.28289794921875 +24245 -0.251617431640625 +24246 -0.266143798828125 +24247 -0.273345947265625 +24248 -0.216796875 +24249 -0.128265380859375 +24250 -0.068145751953125 +24251 -0.0430908203125 +24252 -0.024444580078125 +24253 0.020721435546875 +24254 0.124481201171875 +24255 0.25787353515625 +24256 0.379119873046875 +24257 0.47991943359375 +24258 0.5281982421875 +24259 0.511138916015625 +24260 0.456207275390625 +24261 0.407470703125 +24262 0.383758544921875 +24263 0.35687255859375 +24264 0.31182861328125 +24265 0.250885009765625 +24266 0.1654052734375 +24267 0.035247802734375 +24268 -0.142059326171875 +24269 -0.33563232421875 +24270 -0.5345458984375 +24271 -0.72186279296875 +24272 -0.836669921875 +24273 -0.8326416015625 +24274 -0.7296142578125 +24275 -0.582550048828125 +24276 -0.440093994140625 +24277 -0.324310302734375 +24278 -0.20147705078125 +24279 -0.044647216796875 +24280 0.103973388671875 +24281 0.202392578125 +24282 0.264495849609375 +24283 0.338897705078125 +24284 0.443817138671875 +24285 0.545074462890625 +24286 0.6173095703125 +24287 0.6524658203125 +24288 0.66339111328125 +24289 0.6561279296875 +24290 0.606781005859375 +24291 0.501190185546875 +24292 0.352783203125 +24293 0.176544189453125 +24294 -0.034820556640625 +24295 -0.258209228515625 +24296 -0.44244384765625 +24297 -0.5753173828125 +24298 -0.65203857421875 +24299 -0.641632080078125 +24300 -0.562164306640625 +24301 -0.458038330078125 +24302 -0.350555419921875 +24303 -0.260528564453125 +24304 -0.192108154296875 +24305 -0.141937255859375 +24306 -0.1021728515625 +24307 -0.062896728515625 +24308 -0.011932373046875 +24309 0.062835693359375 +24310 0.148712158203125 +24311 0.241729736328125 +24312 0.34912109375 +24313 0.457305908203125 +24314 0.54388427734375 +24315 0.5728759765625 +24316 0.506591796875 +24317 0.351226806640625 +24318 0.146514892578125 +24319 -0.05523681640625 +24320 -0.21624755859375 +24321 -0.334930419921875 +24322 -0.402984619140625 +24323 -0.4412841796875 +24324 -0.49578857421875 +24325 -0.5601806640625 +24326 -0.600738525390625 +24327 -0.584228515625 +24328 -0.47930908203125 +24329 -0.27935791015625 +24330 -0.0089111328125 +24331 0.268798828125 +24332 0.482818603515625 +24333 0.60369873046875 +24334 0.650421142578125 +24335 0.66400146484375 +24336 0.6414794921875 +24337 0.572540283203125 +24338 0.498138427734375 +24339 0.439453125 +24340 0.375518798828125 +24341 0.274505615234375 +24342 0.1087646484375 +24343 -0.099395751953125 +24344 -0.3182373046875 +24345 -0.5489501953125 +24346 -0.7738037109375 +24347 -0.86383056640625 +24348 -0.870391845703125 +24349 -0.86895751953125 +24350 -0.861053466796875 +24351 -0.765869140625 +24352 -0.5301513671875 +24353 -0.214691162109375 +24354 0.137359619140625 +24355 0.474822998046875 +24356 0.76239013671875 +24357 0.867462158203125 +24358 0.870361328125 +24359 0.86480712890625 +24360 0.831817626953125 +24361 0.677581787109375 +24362 0.495880126953125 +24363 0.30767822265625 +24364 0.116180419921875 +24365 -0.110748291015625 +24366 -0.381805419921875 +24367 -0.6572265625 +24368 -0.857421875 +24369 -0.870391845703125 +24370 -0.870391845703125 +24371 -0.86444091796875 +24372 -0.85723876953125 +24373 -0.790008544921875 +24374 -0.62847900390625 +24375 -0.3956298828125 +24376 -0.126708984375 +24377 0.150115966796875 +24378 0.424041748046875 +24379 0.670623779296875 +24380 0.854522705078125 +24381 0.866485595703125 +24382 0.86920166015625 +24383 0.8653564453125 +24384 0.857147216796875 +24385 0.766845703125 +24386 0.628509521484375 +24387 0.462127685546875 +24388 0.297210693359375 +24389 0.14862060546875 +24390 -0.00537109375 +24391 -0.15753173828125 +24392 -0.31304931640625 +24393 -0.48876953125 +24394 -0.6416015625 +24395 -0.751373291015625 +24396 -0.84619140625 +24397 -0.861297607421875 +24398 -0.863250732421875 +24399 -0.856597900390625 +24400 -0.7498779296875 +24401 -0.624542236328125 +24402 -0.47808837890625 +24403 -0.253387451171875 +24404 0.003692626953125 +24405 0.2257080078125 +24406 0.427154541015625 +24407 0.643218994140625 +24408 0.855926513671875 +24409 0.870361328125 +24410 0.870361328125 +24411 0.862762451171875 +24412 0.79669189453125 +24413 0.595794677734375 +24414 0.362152099609375 +24415 0.1270751953125 +24416 -0.086944580078125 +24417 -0.2784423828125 +24418 -0.484832763671875 +24419 -0.729583740234375 +24420 -0.86688232421875 +24421 -0.870391845703125 +24422 -0.86859130859375 +24423 -0.86279296875 +24424 -0.817962646484375 +24425 -0.6116943359375 +24426 -0.3128662109375 +24427 0.039398193359375 +24428 0.422821044921875 +24429 0.805145263671875 +24430 0.870361328125 +24431 0.870361328125 +24432 0.860015869140625 +24433 0.727935791015625 +24434 0.48114013671875 +24435 0.2059326171875 +24436 -0.06103515625 +24437 -0.29913330078125 +24438 -0.516204833984375 +24439 -0.7252197265625 +24440 -0.85980224609375 +24441 -0.870391845703125 +24442 -0.870391845703125 +24443 -0.858062744140625 +24444 -0.673004150390625 +24445 -0.42694091796875 +24446 -0.2100830078125 +24447 -0.0362548828125 +24448 0.10943603515625 +24449 0.23516845703125 +24450 0.373687744140625 +24451 0.517791748046875 +24452 0.602783203125 +24453 0.635711669921875 +24454 0.655181884765625 +24455 0.65948486328125 +24456 0.651275634765625 +24457 0.61846923828125 +24458 0.53753662109375 +24459 0.404144287109375 +24460 0.22186279296875 +24461 0.003997802734375 +24462 -0.22100830078125 +24463 -0.42449951171875 +24464 -0.579833984375 +24465 -0.641876220703125 +24466 -0.6177978515625 +24467 -0.575531005859375 +24468 -0.526336669921875 +24469 -0.42645263671875 +24470 -0.2581787109375 +24471 -0.068695068359375 +24472 0.09222412109375 +24473 0.232147216796875 +24474 0.3509521484375 +24475 0.410064697265625 +24476 0.372955322265625 +24477 0.2554931640625 +24478 0.10711669921875 +24479 -0.052886962890625 +24480 -0.186279296875 +24481 -0.23291015625 +24482 -0.209442138671875 +24483 -0.174163818359375 +24484 -0.126739501953125 +24485 -0.048126220703125 +24486 0.0426025390625 +24487 0.10748291015625 +24488 0.1409912109375 +24489 0.19708251953125 +24490 0.273651123046875 +24491 0.31768798828125 +24492 0.341094970703125 +24493 0.368011474609375 +24494 0.37249755859375 +24495 0.30072021484375 +24496 0.1517333984375 +24497 -0.01470947265625 +24498 -0.1883544921875 +24499 -0.372711181640625 +24500 -0.51397705078125 +24501 -0.57177734375 +24502 -0.53948974609375 +24503 -0.43511962890625 +24504 -0.2962646484375 +24505 -0.161102294921875 +24506 -0.0435791015625 +24507 0.060394287109375 +24508 0.13665771484375 +24509 0.170135498046875 +24510 0.16552734375 +24511 0.15728759765625 +24512 0.150787353515625 +24513 0.12200927734375 +24514 0.080108642578125 +24515 0.05126953125 +24516 0.062896728515625 +24517 0.09271240234375 +24518 0.092987060546875 +24519 0.07855224609375 +24520 0.06427001953125 +24521 0.0347900390625 +24522 -0.01171875 +24523 -0.056060791015625 +24524 -0.055511474609375 +24525 -0.010467529296875 +24526 0.02508544921875 +24527 0.025665283203125 +24528 0.017333984375 +24529 0.00189208984375 +24530 -0.03173828125 +24531 -0.071502685546875 +24532 -0.13543701171875 +24533 -0.219970703125 +24534 -0.300506591796875 +24535 -0.376312255859375 +24536 -0.416107177734375 +24537 -0.371124267578125 +24538 -0.242279052734375 +24539 -0.069732666015625 +24540 0.125640869140625 +24541 0.31268310546875 +24542 0.45501708984375 +24543 0.554779052734375 +24544 0.61065673828125 +24545 0.610931396484375 +24546 0.531463623046875 +24547 0.3883056640625 +24548 0.23468017578125 +24549 0.095245361328125 +24550 -0.00396728515625 +24551 -0.04852294921875 +24552 -0.055145263671875 +24553 -0.0758056640625 +24554 -0.138702392578125 +24555 -0.209197998046875 +24556 -0.289031982421875 +24557 -0.37884521484375 +24558 -0.456329345703125 +24559 -0.51641845703125 +24560 -0.519287109375 +24561 -0.458251953125 +24562 -0.384796142578125 +24563 -0.323699951171875 +24564 -0.269287109375 +24565 -0.1951904296875 +24566 -0.100006103515625 +24567 -0.01055908203125 +24568 0.1033935546875 +24569 0.24908447265625 +24570 0.373199462890625 +24571 0.45806884765625 +24572 0.511474609375 +24573 0.565399169921875 +24574 0.61138916015625 +24575 0.5897216796875 +24576 0.4906005859375 +24577 0.33148193359375 +24578 0.147796630859375 +24579 -0.01873779296875 +24580 -0.140289306640625 +24581 -0.191986083984375 +24582 -0.184295654296875 +24583 -0.161834716796875 +24584 -0.166595458984375 +24585 -0.19390869140625 +24586 -0.22442626953125 +24587 -0.279754638671875 +24588 -0.3389892578125 +24589 -0.3543701171875 +24590 -0.348175048828125 +24591 -0.32598876953125 +24592 -0.2581787109375 +24593 -0.139801025390625 +24594 0.014617919921875 +24595 0.144378662109375 +24596 0.221038818359375 +24597 0.27069091796875 +24598 0.294036865234375 +24599 0.311767578125 +24600 0.339141845703125 +24601 0.360260009765625 +24602 0.360504150390625 +24603 0.308380126953125 +24604 0.18170166015625 +24605 0.0047607421875 +24606 -0.17559814453125 +24607 -0.3143310546875 +24608 -0.36785888671875 +24609 -0.36248779296875 +24610 -0.343536376953125 +24611 -0.3018798828125 +24612 -0.231414794921875 +24613 -0.117645263671875 +24614 0.007049560546875 +24615 0.087982177734375 +24616 0.13946533203125 +24617 0.17425537109375 +24618 0.188201904296875 +24619 0.171234130859375 +24620 0.118438720703125 +24621 0.05706787109375 +24622 -0.010711669921875 +24623 -0.0914306640625 +24624 -0.162322998046875 +24625 -0.194549560546875 +24626 -0.1492919921875 +24627 -0.02166748046875 +24628 0.124053955078125 +24629 0.211151123046875 +24630 0.240447998046875 +24631 0.242218017578125 +24632 0.2257080078125 +24633 0.194366455078125 +24634 0.115509033203125 +24635 0.0128173828125 +24636 -0.053802490234375 +24637 -0.110626220703125 +24638 -0.199493408203125 +24639 -0.29437255859375 +24640 -0.33221435546875 +24641 -0.27972412109375 +24642 -0.185333251953125 +24643 -0.128204345703125 +24644 -0.115692138671875 +24645 -0.116455078125 +24646 -0.105926513671875 +24647 -0.053955078125 +24648 0.048797607421875 +24649 0.157318115234375 +24650 0.212005615234375 +24651 0.218475341796875 +24652 0.23724365234375 +24653 0.30535888671875 +24654 0.38128662109375 +24655 0.404449462890625 +24656 0.3944091796875 +24657 0.3885498046875 +24658 0.362640380859375 +24659 0.27362060546875 +24660 0.11712646484375 +24661 -0.054901123046875 +24662 -0.19085693359375 +24663 -0.28570556640625 +24664 -0.339263916015625 +24665 -0.3775634765625 +24666 -0.445709228515625 +24667 -0.535064697265625 +24668 -0.629058837890625 +24669 -0.697601318359375 +24670 -0.70391845703125 +24671 -0.6424560546875 +24672 -0.491241455078125 +24673 -0.265716552734375 +24674 -0.023712158203125 +24675 0.201751708984375 +24676 0.375823974609375 +24677 0.485076904296875 +24678 0.56884765625 +24679 0.634765625 +24680 0.63763427734375 +24681 0.5660400390625 +24682 0.4720458984375 +24683 0.40692138671875 +24684 0.3778076171875 +24685 0.376953125 +24686 0.371978759765625 +24687 0.313140869140625 +24688 0.184417724609375 +24689 0.011199951171875 +24690 -0.171051025390625 +24691 -0.33740234375 +24692 -0.47198486328125 +24693 -0.560394287109375 +24694 -0.58056640625 +24695 -0.54754638671875 +24696 -0.508575439453125 +24697 -0.459503173828125 +24698 -0.394378662109375 +24699 -0.35260009765625 +24700 -0.31170654296875 +24701 -0.197418212890625 +24702 -0.007965087890625 +24703 0.207489013671875 +24704 0.409210205078125 +24705 0.57208251953125 +24706 0.66595458984375 +24707 0.65875244140625 +24708 0.56744384765625 +24709 0.431396484375 +24710 0.29443359375 +24711 0.182464599609375 +24712 0.06365966796875 +24713 -0.075958251953125 +24714 -0.189422607421875 +24715 -0.271942138671875 +24716 -0.342529296875 +24717 -0.364166259765625 +24718 -0.327239990234375 +24719 -0.2769775390625 +24720 -0.253692626953125 +24721 -0.24365234375 +24722 -0.1983642578125 +24723 -0.116241455078125 +24724 -0.036834716796875 +24725 0.034881591796875 +24726 0.09124755859375 +24727 0.10888671875 +24728 0.125518798828125 +24729 0.15771484375 +24730 0.17828369140625 +24731 0.17108154296875 +24732 0.129974365234375 +24733 0.082427978515625 +24734 0.027679443359375 +24735 -0.065643310546875 +24736 -0.15936279296875 +24737 -0.21307373046875 +24738 -0.234649658203125 +24739 -0.2001953125 +24740 -0.119171142578125 +24741 -0.024749755859375 +24742 0.085784912109375 +24743 0.178131103515625 +24744 0.215576171875 +24745 0.211456298828125 +24746 0.17523193359375 +24747 0.128753662109375 +24748 0.1019287109375 +24749 0.0743408203125 +24750 0.04327392578125 +24751 0.038177490234375 +24752 0.076263427734375 +24753 0.14105224609375 +24754 0.186431884765625 +24755 0.188812255859375 +24756 0.1390380859375 +24757 0.041778564453125 +24758 -0.079437255859375 +24759 -0.219390869140625 +24760 -0.367828369140625 +24761 -0.494873046875 +24762 -0.556243896484375 +24763 -0.508697509765625 +24764 -0.3756103515625 +24765 -0.218902587890625 +24766 -0.063751220703125 +24767 0.091552734375 +24768 0.23602294921875 +24769 0.342987060546875 +24770 0.39520263671875 +24771 0.389373779296875 +24772 0.324249267578125 +24773 0.224090576171875 +24774 0.124267578125 +24775 0.037078857421875 +24776 -0.010101318359375 +24777 -0.019439697265625 +24778 -0.022796630859375 +24779 -0.001556396484375 +24780 0.056304931640625 +24781 0.106719970703125 +24782 0.096893310546875 +24783 0.042694091796875 +24784 -0.018035888671875 +24785 -0.07586669921875 +24786 -0.11944580078125 +24787 -0.15972900390625 +24788 -0.202606201171875 +24789 -0.24859619140625 +24790 -0.30517578125 +24791 -0.36212158203125 +24792 -0.39141845703125 +24793 -0.35528564453125 +24794 -0.249969482421875 +24795 -0.092864990234375 +24796 0.08905029296875 +24797 0.2352294921875 +24798 0.318817138671875 +24799 0.358642578125 +24800 0.347747802734375 +24801 0.28564453125 +24802 0.223175048828125 +24803 0.196746826171875 +24804 0.179840087890625 +24805 0.155548095703125 +24806 0.151214599609375 +24807 0.156951904296875 +24808 0.13177490234375 +24809 0.100799560546875 +24810 0.087127685546875 +24811 0.05487060546875 +24812 -0.009002685546875 +24813 -0.10400390625 +24814 -0.229400634765625 +24815 -0.35552978515625 +24816 -0.441925048828125 +24817 -0.473846435546875 +24818 -0.464813232421875 +24819 -0.419097900390625 +24820 -0.334320068359375 +24821 -0.227935791015625 +24822 -0.12347412109375 +24823 -0.02764892578125 +24824 0.077667236328125 +24825 0.2132568359375 +24826 0.38885498046875 +24827 0.582794189453125 +24828 0.734039306640625 +24829 0.800140380859375 +24830 0.7783203125 +24831 0.6651611328125 +24832 0.45965576171875 +24833 0.199188232421875 +24834 -0.050689697265625 +24835 -0.23297119140625 +24836 -0.33013916015625 +24837 -0.368408203125 +24838 -0.378936767578125 +24839 -0.376983642578125 +24840 -0.37969970703125 +24841 -0.391510009765625 +24842 -0.385345458984375 +24843 -0.3419189453125 +24844 -0.28289794921875 +24845 -0.251617431640625 +24846 -0.266143798828125 +24847 -0.273345947265625 +24848 -0.216796875 +24849 -0.128265380859375 +24850 -0.068145751953125 +24851 -0.0430908203125 +24852 -0.024444580078125 +24853 0.020721435546875 +24854 0.124481201171875 +24855 0.25787353515625 +24856 0.379119873046875 +24857 0.47991943359375 +24858 0.5281982421875 +24859 0.511138916015625 +24860 0.456207275390625 +24861 0.407470703125 +24862 0.383758544921875 +24863 0.35687255859375 +24864 0.31182861328125 +24865 0.250885009765625 +24866 0.1654052734375 +24867 0.035247802734375 +24868 -0.142059326171875 +24869 -0.33563232421875 +24870 -0.5345458984375 +24871 -0.72186279296875 +24872 -0.836669921875 +24873 -0.8326416015625 +24874 -0.7296142578125 +24875 -0.582550048828125 +24876 -0.440093994140625 +24877 -0.324310302734375 +24878 -0.20147705078125 +24879 -0.044647216796875 +24880 0.103973388671875 +24881 0.202392578125 +24882 0.264495849609375 +24883 0.338897705078125 +24884 0.443817138671875 +24885 0.545074462890625 +24886 0.6173095703125 +24887 0.6524658203125 +24888 0.66339111328125 +24889 0.6561279296875 +24890 0.606781005859375 +24891 0.501190185546875 +24892 0.352783203125 +24893 0.176544189453125 +24894 -0.034820556640625 +24895 -0.258209228515625 +24896 -0.44244384765625 +24897 -0.5753173828125 +24898 -0.65203857421875 +24899 -0.641632080078125 +24900 -0.562164306640625 +24901 -0.458038330078125 +24902 -0.350555419921875 +24903 -0.260528564453125 +24904 -0.192108154296875 +24905 -0.141937255859375 +24906 -0.1021728515625 +24907 -0.062896728515625 +24908 -0.011932373046875 +24909 0.062835693359375 +24910 0.148712158203125 +24911 0.241729736328125 +24912 0.34912109375 +24913 0.457305908203125 +24914 0.54388427734375 +24915 0.5728759765625 +24916 0.506591796875 +24917 0.351226806640625 +24918 0.146514892578125 +24919 -0.05523681640625 +24920 -0.21624755859375 +24921 -0.334930419921875 +24922 -0.402984619140625 +24923 -0.4412841796875 +24924 -0.49578857421875 +24925 -0.5601806640625 +24926 -0.600738525390625 +24927 -0.584228515625 +24928 -0.47930908203125 +24929 -0.27935791015625 +24930 -0.0089111328125 +24931 0.268798828125 +24932 0.482818603515625 +24933 0.60369873046875 +24934 0.650421142578125 +24935 0.66400146484375 +24936 0.6414794921875 +24937 0.572540283203125 +24938 0.498138427734375 +24939 0.439453125 +24940 0.375518798828125 +24941 0.274505615234375 +24942 0.1087646484375 +24943 -0.099395751953125 +24944 -0.3182373046875 +24945 -0.5489501953125 +24946 -0.7738037109375 +24947 -0.86383056640625 +24948 -0.870391845703125 +24949 -0.86895751953125 +24950 -0.861053466796875 +24951 -0.765869140625 +24952 -0.5301513671875 +24953 -0.214691162109375 +24954 0.137359619140625 +24955 0.474822998046875 +24956 0.76239013671875 +24957 0.867462158203125 +24958 0.870361328125 +24959 0.86480712890625 +24960 0.831817626953125 +24961 0.677581787109375 +24962 0.495880126953125 +24963 0.30767822265625 +24964 0.116180419921875 +24965 -0.110748291015625 +24966 -0.381805419921875 +24967 -0.6572265625 +24968 -0.857421875 +24969 -0.870391845703125 +24970 -0.870391845703125 +24971 -0.86444091796875 +24972 -0.85723876953125 +24973 -0.790008544921875 +24974 -0.62847900390625 +24975 -0.3956298828125 +24976 -0.126708984375 +24977 0.150115966796875 +24978 0.424041748046875 +24979 0.670623779296875 +24980 0.854522705078125 +24981 0.866485595703125 +24982 0.86920166015625 +24983 0.8653564453125 +24984 0.857147216796875 +24985 0.766845703125 +24986 0.628509521484375 +24987 0.462127685546875 +24988 0.297210693359375 +24989 0.14862060546875 +24990 -0.00537109375 +24991 -0.15753173828125 +24992 -0.31304931640625 +24993 -0.48876953125 +24994 -0.6416015625 +24995 -0.751373291015625 +24996 -0.84619140625 +24997 -0.861297607421875 +24998 -0.863250732421875 +24999 -0.856597900390625 +25000 -0.7498779296875 +25001 -0.624542236328125 +25002 -0.47808837890625 +25003 -0.253387451171875 +25004 0.003692626953125 +25005 0.2257080078125 +25006 0.427154541015625 +25007 0.643218994140625 +25008 0.855926513671875 +25009 0.870361328125 +25010 0.870361328125 +25011 0.862762451171875 +25012 0.79669189453125 +25013 0.595794677734375 +25014 0.362152099609375 +25015 0.1270751953125 +25016 -0.086944580078125 +25017 -0.2784423828125 +25018 -0.484832763671875 +25019 -0.729583740234375 +25020 -0.86688232421875 +25021 -0.870391845703125 +25022 -0.86859130859375 +25023 -0.86279296875 +25024 -0.817962646484375 +25025 -0.6116943359375 +25026 -0.3128662109375 +25027 0.039398193359375 +25028 0.422821044921875 +25029 0.805145263671875 +25030 0.870361328125 +25031 0.870361328125 +25032 0.860015869140625 +25033 0.727935791015625 +25034 0.48114013671875 +25035 0.2059326171875 +25036 -0.06103515625 +25037 -0.29913330078125 +25038 -0.516204833984375 +25039 -0.7252197265625 +25040 -0.85980224609375 +25041 -0.870391845703125 +25042 -0.870391845703125 +25043 -0.858062744140625 +25044 -0.673004150390625 +25045 -0.42694091796875 +25046 -0.2100830078125 +25047 -0.0362548828125 +25048 0.10943603515625 +25049 0.23516845703125 +25050 0.373687744140625 +25051 0.517791748046875 +25052 0.602783203125 +25053 0.635711669921875 +25054 0.655181884765625 +25055 0.65948486328125 +25056 0.651275634765625 +25057 0.61846923828125 +25058 0.53753662109375 +25059 0.404144287109375 +25060 0.22186279296875 +25061 0.003997802734375 +25062 -0.22100830078125 +25063 -0.42449951171875 +25064 -0.579833984375 +25065 -0.641876220703125 +25066 -0.6177978515625 +25067 -0.575531005859375 +25068 -0.526336669921875 +25069 -0.42645263671875 +25070 -0.2581787109375 +25071 -0.068695068359375 +25072 0.09222412109375 +25073 0.232147216796875 +25074 0.3509521484375 +25075 0.410064697265625 +25076 0.372955322265625 +25077 0.2554931640625 +25078 0.10711669921875 +25079 -0.052886962890625 +25080 -0.186279296875 +25081 -0.23291015625 +25082 -0.209442138671875 +25083 -0.174163818359375 +25084 -0.126739501953125 +25085 -0.048126220703125 +25086 0.0426025390625 +25087 0.10748291015625 +25088 0.1409912109375 +25089 0.19708251953125 +25090 0.273651123046875 +25091 0.31768798828125 +25092 0.341094970703125 +25093 0.368011474609375 +25094 0.37249755859375 +25095 0.30072021484375 +25096 0.1517333984375 +25097 -0.01470947265625 +25098 -0.1883544921875 +25099 -0.372711181640625 +25100 -0.51397705078125 +25101 -0.57177734375 +25102 -0.53948974609375 +25103 -0.43511962890625 +25104 -0.2962646484375 +25105 -0.161102294921875 +25106 -0.0435791015625 +25107 0.060394287109375 +25108 0.13665771484375 +25109 0.170135498046875 +25110 0.16552734375 +25111 0.15728759765625 +25112 0.150787353515625 +25113 0.12200927734375 +25114 0.080108642578125 +25115 0.05126953125 +25116 0.062896728515625 +25117 0.09271240234375 +25118 0.092987060546875 +25119 0.07855224609375 +25120 0.06427001953125 +25121 0.0347900390625 +25122 -0.01171875 +25123 -0.056060791015625 +25124 -0.055511474609375 +25125 -0.010467529296875 +25126 0.02508544921875 +25127 0.025665283203125 +25128 0.017333984375 +25129 0.00189208984375 +25130 -0.03173828125 +25131 -0.071502685546875 +25132 -0.13543701171875 +25133 -0.219970703125 +25134 -0.300506591796875 +25135 -0.376312255859375 +25136 -0.416107177734375 +25137 -0.371124267578125 +25138 -0.242279052734375 +25139 -0.069732666015625 +25140 0.125640869140625 +25141 0.31268310546875 +25142 0.45501708984375 +25143 0.554779052734375 +25144 0.61065673828125 +25145 0.610931396484375 +25146 0.531463623046875 +25147 0.3883056640625 +25148 0.23468017578125 +25149 0.095245361328125 +25150 -0.00396728515625 +25151 -0.04852294921875 +25152 -0.055145263671875 +25153 -0.0758056640625 +25154 -0.138702392578125 +25155 -0.209197998046875 +25156 -0.289031982421875 +25157 -0.37884521484375 +25158 -0.456329345703125 +25159 -0.51641845703125 +25160 -0.519287109375 +25161 -0.458251953125 +25162 -0.384796142578125 +25163 -0.323699951171875 +25164 -0.269287109375 +25165 -0.1951904296875 +25166 -0.100006103515625 +25167 -0.01055908203125 +25168 0.1033935546875 +25169 0.24908447265625 +25170 0.373199462890625 +25171 0.45806884765625 +25172 0.511474609375 +25173 0.565399169921875 +25174 0.61138916015625 +25175 0.5897216796875 +25176 0.4906005859375 +25177 0.33148193359375 +25178 0.147796630859375 +25179 -0.01873779296875 +25180 -0.140289306640625 +25181 -0.191986083984375 +25182 -0.184295654296875 +25183 -0.161834716796875 +25184 -0.166595458984375 +25185 -0.19390869140625 +25186 -0.22442626953125 +25187 -0.279754638671875 +25188 -0.3389892578125 +25189 -0.3543701171875 +25190 -0.348175048828125 +25191 -0.32598876953125 +25192 -0.2581787109375 +25193 -0.139801025390625 +25194 0.014617919921875 +25195 0.144378662109375 +25196 0.221038818359375 +25197 0.27069091796875 +25198 0.294036865234375 +25199 0.311767578125 +25200 0.339141845703125 +25201 0.360260009765625 +25202 0.360504150390625 +25203 0.308380126953125 +25204 0.18170166015625 +25205 0.0047607421875 +25206 -0.17559814453125 +25207 -0.3143310546875 +25208 -0.36785888671875 +25209 -0.36248779296875 +25210 -0.343536376953125 +25211 -0.3018798828125 +25212 -0.231414794921875 +25213 -0.117645263671875 +25214 0.007049560546875 +25215 0.087982177734375 +25216 0.13946533203125 +25217 0.17425537109375 +25218 0.188201904296875 +25219 0.171234130859375 +25220 0.118438720703125 +25221 0.05706787109375 +25222 -0.010711669921875 +25223 -0.0914306640625 +25224 -0.162322998046875 +25225 -0.194549560546875 +25226 -0.1492919921875 +25227 -0.02166748046875 +25228 0.124053955078125 +25229 0.211151123046875 +25230 0.240447998046875 +25231 0.242218017578125 +25232 0.2257080078125 +25233 0.194366455078125 +25234 0.115509033203125 +25235 0.0128173828125 +25236 -0.053802490234375 +25237 -0.110626220703125 +25238 -0.199493408203125 +25239 -0.29437255859375 +25240 -0.33221435546875 +25241 -0.27972412109375 +25242 -0.185333251953125 +25243 -0.128204345703125 +25244 -0.115692138671875 +25245 -0.116455078125 +25246 -0.105926513671875 +25247 -0.053955078125 +25248 0.048797607421875 +25249 0.157318115234375 +25250 0.212005615234375 +25251 0.218475341796875 +25252 0.23724365234375 +25253 0.30535888671875 +25254 0.38128662109375 +25255 0.404449462890625 +25256 0.3944091796875 +25257 0.3885498046875 +25258 0.362640380859375 +25259 0.27362060546875 +25260 0.11712646484375 +25261 -0.054901123046875 +25262 -0.19085693359375 +25263 -0.28570556640625 +25264 -0.339263916015625 +25265 -0.3775634765625 +25266 -0.445709228515625 +25267 -0.535064697265625 +25268 -0.629058837890625 +25269 -0.697601318359375 +25270 -0.70391845703125 +25271 -0.6424560546875 +25272 -0.491241455078125 +25273 -0.265716552734375 +25274 -0.023712158203125 +25275 0.201751708984375 +25276 0.375823974609375 +25277 0.485076904296875 +25278 0.56884765625 +25279 0.634765625 +25280 0.63763427734375 +25281 0.5660400390625 +25282 0.4720458984375 +25283 0.40692138671875 +25284 0.3778076171875 +25285 0.376953125 +25286 0.371978759765625 +25287 0.313140869140625 +25288 0.184417724609375 +25289 0.011199951171875 +25290 -0.171051025390625 +25291 -0.33740234375 +25292 -0.47198486328125 +25293 -0.560394287109375 +25294 -0.58056640625 +25295 -0.54754638671875 +25296 -0.508575439453125 +25297 -0.459503173828125 +25298 -0.394378662109375 +25299 -0.35260009765625 +25300 -0.31170654296875 +25301 -0.197418212890625 +25302 -0.007965087890625 +25303 0.207489013671875 +25304 0.409210205078125 +25305 0.57208251953125 +25306 0.66595458984375 +25307 0.65875244140625 +25308 0.56744384765625 +25309 0.431396484375 +25310 0.29443359375 +25311 0.182464599609375 +25312 0.06365966796875 +25313 -0.075958251953125 +25314 -0.189422607421875 +25315 -0.271942138671875 +25316 -0.342529296875 +25317 -0.364166259765625 +25318 -0.327239990234375 +25319 -0.2769775390625 +25320 -0.253692626953125 +25321 -0.24365234375 +25322 -0.1983642578125 +25323 -0.116241455078125 +25324 -0.036834716796875 +25325 0.034881591796875 +25326 0.09124755859375 +25327 0.10888671875 +25328 0.125518798828125 +25329 0.15771484375 +25330 0.17828369140625 +25331 0.17108154296875 +25332 0.129974365234375 +25333 0.082427978515625 +25334 0.027679443359375 +25335 -0.065643310546875 +25336 -0.15936279296875 +25337 -0.21307373046875 +25338 -0.234649658203125 +25339 -0.2001953125 +25340 -0.119171142578125 +25341 -0.024749755859375 +25342 0.085784912109375 +25343 0.178131103515625 +25344 0.215576171875 +25345 0.211456298828125 +25346 0.17523193359375 +25347 0.128753662109375 +25348 0.1019287109375 +25349 0.0743408203125 +25350 0.04327392578125 +25351 0.038177490234375 +25352 0.076263427734375 +25353 0.14105224609375 +25354 0.186431884765625 +25355 0.188812255859375 +25356 0.1390380859375 +25357 0.041778564453125 +25358 -0.079437255859375 +25359 -0.219390869140625 +25360 -0.367828369140625 +25361 -0.494873046875 +25362 -0.556243896484375 +25363 -0.508697509765625 +25364 -0.3756103515625 +25365 -0.218902587890625 +25366 -0.063751220703125 +25367 0.091552734375 +25368 0.23602294921875 +25369 0.342987060546875 +25370 0.39520263671875 +25371 0.389373779296875 +25372 0.324249267578125 +25373 0.224090576171875 +25374 0.124267578125 +25375 0.037078857421875 +25376 -0.010101318359375 +25377 -0.019439697265625 +25378 -0.022796630859375 +25379 -0.001556396484375 +25380 0.056304931640625 +25381 0.106719970703125 +25382 0.096893310546875 +25383 0.042694091796875 +25384 -0.018035888671875 +25385 -0.07586669921875 +25386 -0.11944580078125 +25387 -0.15972900390625 +25388 -0.202606201171875 +25389 -0.24859619140625 +25390 -0.30517578125 +25391 -0.36212158203125 +25392 -0.39141845703125 +25393 -0.35528564453125 +25394 -0.249969482421875 +25395 -0.092864990234375 +25396 0.08905029296875 +25397 0.2352294921875 +25398 0.318817138671875 +25399 0.358642578125 +25400 0.347747802734375 +25401 0.28564453125 +25402 0.223175048828125 +25403 0.196746826171875 +25404 0.179840087890625 +25405 0.155548095703125 +25406 0.151214599609375 +25407 0.156951904296875 +25408 0.13177490234375 +25409 0.100799560546875 +25410 0.087127685546875 +25411 0.05487060546875 +25412 -0.009002685546875 +25413 -0.10400390625 +25414 -0.229400634765625 +25415 -0.35552978515625 +25416 -0.441925048828125 +25417 -0.473846435546875 +25418 -0.464813232421875 +25419 -0.419097900390625 +25420 -0.334320068359375 +25421 -0.227935791015625 +25422 -0.12347412109375 +25423 -0.02764892578125 +25424 0.077667236328125 +25425 0.2132568359375 +25426 0.38885498046875 +25427 0.582794189453125 +25428 0.734039306640625 +25429 0.800140380859375 +25430 0.7783203125 +25431 0.6651611328125 +25432 0.45965576171875 +25433 0.199188232421875 +25434 -0.050689697265625 +25435 -0.23297119140625 +25436 -0.33013916015625 +25437 -0.368408203125 +25438 -0.378936767578125 +25439 -0.376983642578125 +25440 -0.37969970703125 +25441 -0.391510009765625 +25442 -0.385345458984375 +25443 -0.3419189453125 +25444 -0.28289794921875 +25445 -0.251617431640625 +25446 -0.266143798828125 +25447 -0.273345947265625 +25448 -0.216796875 +25449 -0.128265380859375 +25450 -0.068145751953125 +25451 -0.0430908203125 +25452 -0.024444580078125 +25453 0.020721435546875 +25454 0.124481201171875 +25455 0.25787353515625 +25456 0.379119873046875 +25457 0.47991943359375 +25458 0.5281982421875 +25459 0.511138916015625 +25460 0.456207275390625 +25461 0.407470703125 +25462 0.383758544921875 +25463 0.35687255859375 +25464 0.31182861328125 +25465 0.250885009765625 +25466 0.1654052734375 +25467 0.035247802734375 +25468 -0.142059326171875 +25469 -0.33563232421875 +25470 -0.5345458984375 +25471 -0.72186279296875 +25472 -0.836669921875 +25473 -0.8326416015625 +25474 -0.7296142578125 +25475 -0.582550048828125 +25476 -0.440093994140625 +25477 -0.324310302734375 +25478 -0.20147705078125 +25479 -0.044647216796875 +25480 0.103973388671875 +25481 0.202392578125 +25482 0.264495849609375 +25483 0.338897705078125 +25484 0.443817138671875 +25485 0.545074462890625 +25486 0.6173095703125 +25487 0.6524658203125 +25488 0.66339111328125 +25489 0.6561279296875 +25490 0.606781005859375 +25491 0.501190185546875 +25492 0.352783203125 +25493 0.176544189453125 +25494 -0.034820556640625 +25495 -0.258209228515625 +25496 -0.44244384765625 +25497 -0.5753173828125 +25498 -0.65203857421875 +25499 -0.641632080078125 +25500 -0.562164306640625 +25501 -0.458038330078125 +25502 -0.350555419921875 +25503 -0.260528564453125 +25504 -0.192108154296875 +25505 -0.141937255859375 +25506 -0.1021728515625 +25507 -0.062896728515625 +25508 -0.011932373046875 +25509 0.062835693359375 +25510 0.148712158203125 +25511 0.241729736328125 +25512 0.34912109375 +25513 0.457305908203125 +25514 0.54388427734375 +25515 0.5728759765625 +25516 0.506591796875 +25517 0.351226806640625 +25518 0.146514892578125 +25519 -0.05523681640625 +25520 -0.21624755859375 +25521 -0.334930419921875 +25522 -0.402984619140625 +25523 -0.4412841796875 +25524 -0.49578857421875 +25525 -0.5601806640625 +25526 -0.600738525390625 +25527 -0.584228515625 +25528 -0.47930908203125 +25529 -0.27935791015625 +25530 -0.0089111328125 +25531 0.268798828125 +25532 0.482818603515625 +25533 0.60369873046875 +25534 0.650421142578125 +25535 0.66400146484375 +25536 0.6414794921875 +25537 0.572540283203125 +25538 0.498138427734375 +25539 0.439453125 +25540 0.375518798828125 +25541 0.274505615234375 +25542 0.1087646484375 +25543 -0.099395751953125 +25544 -0.3182373046875 +25545 -0.5489501953125 +25546 -0.7738037109375 +25547 -0.86383056640625 +25548 -0.870391845703125 +25549 -0.86895751953125 +25550 -0.861053466796875 +25551 -0.765869140625 +25552 -0.5301513671875 +25553 -0.214691162109375 +25554 0.137359619140625 +25555 0.474822998046875 +25556 0.76239013671875 +25557 0.867462158203125 +25558 0.870361328125 +25559 0.86480712890625 +25560 0.831817626953125 +25561 0.677581787109375 +25562 0.495880126953125 +25563 0.30767822265625 +25564 0.116180419921875 +25565 -0.110748291015625 +25566 -0.381805419921875 +25567 -0.6572265625 +25568 -0.857421875 +25569 -0.870391845703125 +25570 -0.870391845703125 +25571 -0.86444091796875 +25572 -0.85723876953125 +25573 -0.790008544921875 +25574 -0.62847900390625 +25575 -0.3956298828125 +25576 -0.126708984375 +25577 0.150115966796875 +25578 0.424041748046875 +25579 0.670623779296875 +25580 0.854522705078125 +25581 0.866485595703125 +25582 0.86920166015625 +25583 0.8653564453125 +25584 0.857147216796875 +25585 0.766845703125 +25586 0.628509521484375 +25587 0.462127685546875 +25588 0.297210693359375 +25589 0.14862060546875 +25590 -0.00537109375 +25591 -0.15753173828125 +25592 -0.31304931640625 +25593 -0.48876953125 +25594 -0.6416015625 +25595 -0.751373291015625 +25596 -0.84619140625 +25597 -0.861297607421875 +25598 -0.863250732421875 +25599 -0.856597900390625 +25600 -0.7498779296875 +25601 -0.624542236328125 +25602 -0.47808837890625 +25603 -0.253387451171875 +25604 0.003692626953125 +25605 0.2257080078125 +25606 0.427154541015625 +25607 0.643218994140625 +25608 0.855926513671875 +25609 0.870361328125 +25610 0.870361328125 +25611 0.862762451171875 +25612 0.79669189453125 +25613 0.595794677734375 +25614 0.362152099609375 +25615 0.1270751953125 +25616 -0.086944580078125 +25617 -0.2784423828125 +25618 -0.484832763671875 +25619 -0.729583740234375 +25620 -0.86688232421875 +25621 -0.870391845703125 +25622 -0.86859130859375 +25623 -0.86279296875 +25624 -0.817962646484375 +25625 -0.6116943359375 +25626 -0.3128662109375 +25627 0.039398193359375 +25628 0.422821044921875 +25629 0.805145263671875 +25630 0.870361328125 +25631 0.870361328125 +25632 0.860015869140625 +25633 0.727935791015625 +25634 0.48114013671875 +25635 0.2059326171875 +25636 -0.06103515625 +25637 -0.29913330078125 +25638 -0.516204833984375 +25639 -0.7252197265625 +25640 -0.85980224609375 +25641 -0.870391845703125 +25642 -0.870391845703125 +25643 -0.858062744140625 +25644 -0.673004150390625 +25645 -0.42694091796875 +25646 -0.2100830078125 +25647 -0.0362548828125 +25648 0.10943603515625 +25649 0.23516845703125 +25650 0.373687744140625 +25651 0.517791748046875 +25652 0.602783203125 +25653 0.635711669921875 +25654 0.655181884765625 +25655 0.65948486328125 +25656 0.651275634765625 +25657 0.61846923828125 +25658 0.53753662109375 +25659 0.404144287109375 +25660 0.22186279296875 +25661 0.003997802734375 +25662 -0.22100830078125 +25663 -0.42449951171875 +25664 -0.579833984375 +25665 -0.641876220703125 +25666 -0.6177978515625 +25667 -0.575531005859375 +25668 -0.526336669921875 +25669 -0.42645263671875 +25670 -0.2581787109375 +25671 -0.068695068359375 +25672 0.09222412109375 +25673 0.232147216796875 +25674 0.3509521484375 +25675 0.410064697265625 +25676 0.372955322265625 +25677 0.2554931640625 +25678 0.10711669921875 +25679 -0.052886962890625 +25680 -0.186279296875 +25681 -0.23291015625 +25682 -0.209442138671875 +25683 -0.174163818359375 +25684 -0.126739501953125 +25685 -0.048126220703125 +25686 0.0426025390625 +25687 0.10748291015625 +25688 0.1409912109375 +25689 0.19708251953125 +25690 0.273651123046875 +25691 0.31768798828125 +25692 0.341094970703125 +25693 0.368011474609375 +25694 0.37249755859375 +25695 0.30072021484375 +25696 0.1517333984375 +25697 -0.01470947265625 +25698 -0.1883544921875 +25699 -0.372711181640625 +25700 -0.51397705078125 +25701 -0.57177734375 +25702 -0.53948974609375 +25703 -0.43511962890625 +25704 -0.2962646484375 +25705 -0.161102294921875 +25706 -0.0435791015625 +25707 0.060394287109375 +25708 0.13665771484375 +25709 0.170135498046875 +25710 0.16552734375 +25711 0.15728759765625 +25712 0.150787353515625 +25713 0.12200927734375 +25714 0.080108642578125 +25715 0.05126953125 +25716 0.062896728515625 +25717 0.09271240234375 +25718 0.092987060546875 +25719 0.07855224609375 +25720 0.06427001953125 +25721 0.0347900390625 +25722 -0.01171875 +25723 -0.056060791015625 +25724 -0.055511474609375 +25725 -0.010467529296875 +25726 0.02508544921875 +25727 0.025665283203125 +25728 0.017333984375 +25729 0.00189208984375 +25730 -0.03173828125 +25731 -0.071502685546875 +25732 -0.13543701171875 +25733 -0.219970703125 +25734 -0.300506591796875 +25735 -0.376312255859375 +25736 -0.416107177734375 +25737 -0.371124267578125 +25738 -0.242279052734375 +25739 -0.069732666015625 +25740 0.125640869140625 +25741 0.31268310546875 +25742 0.45501708984375 +25743 0.554779052734375 +25744 0.61065673828125 +25745 0.610931396484375 +25746 0.531463623046875 +25747 0.3883056640625 +25748 0.23468017578125 +25749 0.095245361328125 +25750 -0.00396728515625 +25751 -0.04852294921875 +25752 -0.055145263671875 +25753 -0.0758056640625 +25754 -0.138702392578125 +25755 -0.209197998046875 +25756 -0.289031982421875 +25757 -0.37884521484375 +25758 -0.456329345703125 +25759 -0.51641845703125 +25760 -0.519287109375 +25761 -0.458251953125 +25762 -0.384796142578125 +25763 -0.323699951171875 +25764 -0.269287109375 +25765 -0.1951904296875 +25766 -0.100006103515625 +25767 -0.01055908203125 +25768 0.1033935546875 +25769 0.24908447265625 +25770 0.373199462890625 +25771 0.45806884765625 +25772 0.511474609375 +25773 0.565399169921875 +25774 0.61138916015625 +25775 0.5897216796875 +25776 0.4906005859375 +25777 0.33148193359375 +25778 0.147796630859375 +25779 -0.01873779296875 +25780 -0.140289306640625 +25781 -0.191986083984375 +25782 -0.184295654296875 +25783 -0.161834716796875 +25784 -0.166595458984375 +25785 -0.19390869140625 +25786 -0.22442626953125 +25787 -0.279754638671875 +25788 -0.3389892578125 +25789 -0.3543701171875 +25790 -0.348175048828125 +25791 -0.32598876953125 +25792 -0.2581787109375 +25793 -0.139801025390625 +25794 0.014617919921875 +25795 0.144378662109375 +25796 0.221038818359375 +25797 0.27069091796875 +25798 0.294036865234375 +25799 0.311767578125 +25800 0.339141845703125 +25801 0.360260009765625 +25802 0.360504150390625 +25803 0.308380126953125 +25804 0.18170166015625 +25805 0.0047607421875 +25806 -0.17559814453125 +25807 -0.3143310546875 +25808 -0.36785888671875 +25809 -0.36248779296875 +25810 -0.343536376953125 +25811 -0.3018798828125 +25812 -0.231414794921875 +25813 -0.117645263671875 +25814 0.007049560546875 +25815 0.087982177734375 +25816 0.13946533203125 +25817 0.17425537109375 +25818 0.188201904296875 +25819 0.171234130859375 +25820 0.118438720703125 +25821 0.05706787109375 +25822 -0.010711669921875 +25823 -0.0914306640625 +25824 -0.162322998046875 +25825 -0.194549560546875 +25826 -0.1492919921875 +25827 -0.02166748046875 +25828 0.124053955078125 +25829 0.211151123046875 +25830 0.240447998046875 +25831 0.242218017578125 +25832 0.2257080078125 +25833 0.194366455078125 +25834 0.115509033203125 +25835 0.0128173828125 +25836 -0.053802490234375 +25837 -0.110626220703125 +25838 -0.199493408203125 +25839 -0.29437255859375 +25840 -0.33221435546875 +25841 -0.27972412109375 +25842 -0.185333251953125 +25843 -0.128204345703125 +25844 -0.115692138671875 +25845 -0.116455078125 +25846 -0.105926513671875 +25847 -0.053955078125 +25848 0.048797607421875 +25849 0.157318115234375 +25850 0.212005615234375 +25851 0.218475341796875 +25852 0.23724365234375 +25853 0.30535888671875 +25854 0.38128662109375 +25855 0.404449462890625 +25856 0.3944091796875 +25857 0.3885498046875 +25858 0.362640380859375 +25859 0.27362060546875 +25860 0.11712646484375 +25861 -0.054901123046875 +25862 -0.19085693359375 +25863 -0.28570556640625 +25864 -0.339263916015625 +25865 -0.3775634765625 +25866 -0.445709228515625 +25867 -0.535064697265625 +25868 -0.629058837890625 +25869 -0.697601318359375 +25870 -0.70391845703125 +25871 -0.6424560546875 +25872 -0.491241455078125 +25873 -0.265716552734375 +25874 -0.023712158203125 +25875 0.201751708984375 +25876 0.375823974609375 +25877 0.485076904296875 +25878 0.56884765625 +25879 0.634765625 +25880 0.63763427734375 +25881 0.5660400390625 +25882 0.4720458984375 +25883 0.40692138671875 +25884 0.3778076171875 +25885 0.376953125 +25886 0.371978759765625 +25887 0.313140869140625 +25888 0.184417724609375 +25889 0.011199951171875 +25890 -0.171051025390625 +25891 -0.33740234375 +25892 -0.47198486328125 +25893 -0.560394287109375 +25894 -0.58056640625 +25895 -0.54754638671875 +25896 -0.508575439453125 +25897 -0.459503173828125 +25898 -0.394378662109375 +25899 -0.35260009765625 +25900 -0.31170654296875 +25901 -0.197418212890625 +25902 -0.007965087890625 +25903 0.207489013671875 +25904 0.409210205078125 +25905 0.57208251953125 +25906 0.66595458984375 +25907 0.65875244140625 +25908 0.56744384765625 +25909 0.431396484375 +25910 0.29443359375 +25911 0.182464599609375 +25912 0.06365966796875 +25913 -0.075958251953125 +25914 -0.189422607421875 +25915 -0.271942138671875 +25916 -0.342529296875 +25917 -0.364166259765625 +25918 -0.327239990234375 +25919 -0.2769775390625 +25920 -0.253692626953125 +25921 -0.24365234375 +25922 -0.1983642578125 +25923 -0.116241455078125 +25924 -0.036834716796875 +25925 0.034881591796875 +25926 0.09124755859375 +25927 0.10888671875 +25928 0.125518798828125 +25929 0.15771484375 +25930 0.17828369140625 +25931 0.17108154296875 +25932 0.129974365234375 +25933 0.082427978515625 +25934 0.027679443359375 +25935 -0.065643310546875 +25936 -0.15936279296875 +25937 -0.21307373046875 +25938 -0.234649658203125 +25939 -0.2001953125 +25940 -0.119171142578125 +25941 -0.024749755859375 +25942 0.085784912109375 +25943 0.178131103515625 +25944 0.215576171875 +25945 0.211456298828125 +25946 0.17523193359375 +25947 0.128753662109375 +25948 0.1019287109375 +25949 0.0743408203125 +25950 0.04327392578125 +25951 0.038177490234375 +25952 0.076263427734375 +25953 0.14105224609375 +25954 0.186431884765625 +25955 0.188812255859375 +25956 0.1390380859375 +25957 0.041778564453125 +25958 -0.079437255859375 +25959 -0.219390869140625 +25960 -0.367828369140625 +25961 -0.494873046875 +25962 -0.556243896484375 +25963 -0.508697509765625 +25964 -0.3756103515625 +25965 -0.218902587890625 +25966 -0.063751220703125 +25967 0.091552734375 +25968 0.23602294921875 +25969 0.342987060546875 +25970 0.39520263671875 +25971 0.389373779296875 +25972 0.324249267578125 +25973 0.224090576171875 +25974 0.124267578125 +25975 0.037078857421875 +25976 -0.010101318359375 +25977 -0.019439697265625 +25978 -0.022796630859375 +25979 -0.001556396484375 +25980 0.056304931640625 +25981 0.106719970703125 +25982 0.096893310546875 +25983 0.042694091796875 +25984 -0.018035888671875 +25985 -0.07586669921875 +25986 -0.11944580078125 +25987 -0.15972900390625 +25988 -0.202606201171875 +25989 -0.24859619140625 +25990 -0.30517578125 +25991 -0.36212158203125 +25992 -0.39141845703125 +25993 -0.35528564453125 +25994 -0.249969482421875 +25995 -0.092864990234375 +25996 0.08905029296875 +25997 0.2352294921875 +25998 0.318817138671875 +25999 0.358642578125 +26000 0.347747802734375 +26001 0.28564453125 +26002 0.223175048828125 +26003 0.196746826171875 +26004 0.179840087890625 +26005 0.155548095703125 +26006 0.151214599609375 +26007 0.156951904296875 +26008 0.13177490234375 +26009 0.100799560546875 +26010 0.087127685546875 +26011 0.05487060546875 +26012 -0.009002685546875 +26013 -0.10400390625 +26014 -0.229400634765625 +26015 -0.35552978515625 +26016 -0.441925048828125 +26017 -0.473846435546875 +26018 -0.464813232421875 +26019 -0.419097900390625 +26020 -0.334320068359375 +26021 -0.227935791015625 +26022 -0.12347412109375 +26023 -0.02764892578125 +26024 0.077667236328125 +26025 0.2132568359375 +26026 0.38885498046875 +26027 0.582794189453125 +26028 0.734039306640625 +26029 0.800140380859375 +26030 0.7783203125 +26031 0.6651611328125 +26032 0.45965576171875 +26033 0.199188232421875 +26034 -0.050689697265625 +26035 -0.23297119140625 +26036 -0.33013916015625 +26037 -0.368408203125 +26038 -0.378936767578125 +26039 -0.376983642578125 +26040 -0.37969970703125 +26041 -0.391510009765625 +26042 -0.385345458984375 +26043 -0.3419189453125 +26044 -0.28289794921875 +26045 -0.251617431640625 +26046 -0.266143798828125 +26047 -0.273345947265625 +26048 -0.216796875 +26049 -0.128265380859375 +26050 -0.068145751953125 +26051 -0.0430908203125 +26052 -0.024444580078125 +26053 0.020721435546875 +26054 0.124481201171875 +26055 0.25787353515625 +26056 0.379119873046875 +26057 0.47991943359375 +26058 0.5281982421875 +26059 0.511138916015625 +26060 0.456207275390625 +26061 0.407470703125 +26062 0.383758544921875 +26063 0.35687255859375 +26064 0.31182861328125 +26065 0.250885009765625 +26066 0.1654052734375 +26067 0.035247802734375 +26068 -0.142059326171875 +26069 -0.33563232421875 +26070 -0.5345458984375 +26071 -0.72186279296875 +26072 -0.836669921875 +26073 -0.8326416015625 +26074 -0.7296142578125 +26075 -0.582550048828125 +26076 -0.440093994140625 +26077 -0.324310302734375 +26078 -0.20147705078125 +26079 -0.044647216796875 +26080 0.103973388671875 +26081 0.202392578125 +26082 0.264495849609375 +26083 0.338897705078125 +26084 0.443817138671875 +26085 0.545074462890625 +26086 0.6173095703125 +26087 0.6524658203125 +26088 0.66339111328125 +26089 0.6561279296875 +26090 0.606781005859375 +26091 0.501190185546875 +26092 0.352783203125 +26093 0.176544189453125 +26094 -0.034820556640625 +26095 -0.258209228515625 +26096 -0.44244384765625 +26097 -0.5753173828125 +26098 -0.65203857421875 +26099 -0.641632080078125 +26100 -0.562164306640625 +26101 -0.458038330078125 +26102 -0.350555419921875 +26103 -0.260528564453125 +26104 -0.192108154296875 +26105 -0.141937255859375 +26106 -0.1021728515625 +26107 -0.062896728515625 +26108 -0.011932373046875 +26109 0.062835693359375 +26110 0.148712158203125 +26111 0.241729736328125 +26112 0.34912109375 +26113 0.457305908203125 +26114 0.54388427734375 +26115 0.5728759765625 +26116 0.506591796875 +26117 0.351226806640625 +26118 0.146514892578125 +26119 -0.05523681640625 +26120 -0.21624755859375 +26121 -0.334930419921875 +26122 -0.402984619140625 +26123 -0.4412841796875 +26124 -0.49578857421875 +26125 -0.5601806640625 +26126 -0.600738525390625 +26127 -0.584228515625 +26128 -0.47930908203125 +26129 -0.27935791015625 +26130 -0.0089111328125 +26131 0.268798828125 +26132 0.482818603515625 +26133 0.60369873046875 +26134 0.650421142578125 +26135 0.66400146484375 +26136 0.6414794921875 +26137 0.572540283203125 +26138 0.498138427734375 +26139 0.439453125 +26140 0.375518798828125 +26141 0.274505615234375 +26142 0.1087646484375 +26143 -0.099395751953125 +26144 -0.3182373046875 +26145 -0.5489501953125 +26146 -0.7738037109375 +26147 -0.86383056640625 +26148 -0.870391845703125 +26149 -0.86895751953125 +26150 -0.861053466796875 +26151 -0.765869140625 +26152 -0.5301513671875 +26153 -0.214691162109375 +26154 0.137359619140625 +26155 0.474822998046875 +26156 0.76239013671875 +26157 0.867462158203125 +26158 0.870361328125 +26159 0.86480712890625 +26160 0.831817626953125 +26161 0.677581787109375 +26162 0.495880126953125 +26163 0.30767822265625 +26164 0.116180419921875 +26165 -0.110748291015625 +26166 -0.381805419921875 +26167 -0.6572265625 +26168 -0.857421875 +26169 -0.870391845703125 +26170 -0.870391845703125 +26171 -0.86444091796875 +26172 -0.85723876953125 +26173 -0.790008544921875 +26174 -0.62847900390625 +26175 -0.3956298828125 +26176 -0.126708984375 +26177 0.150115966796875 +26178 0.424041748046875 +26179 0.670623779296875 +26180 0.854522705078125 +26181 0.866485595703125 +26182 0.86920166015625 +26183 0.8653564453125 +26184 0.857147216796875 +26185 0.766845703125 +26186 0.628509521484375 +26187 0.462127685546875 +26188 0.297210693359375 +26189 0.14862060546875 +26190 -0.00537109375 +26191 -0.15753173828125 +26192 -0.31304931640625 +26193 -0.48876953125 +26194 -0.6416015625 +26195 -0.751373291015625 +26196 -0.84619140625 +26197 -0.861297607421875 +26198 -0.863250732421875 +26199 -0.856597900390625 +26200 -0.7498779296875 +26201 -0.624542236328125 +26202 -0.47808837890625 +26203 -0.253387451171875 +26204 0.003692626953125 +26205 0.2257080078125 +26206 0.427154541015625 +26207 0.643218994140625 +26208 0.855926513671875 +26209 0.870361328125 +26210 0.870361328125 +26211 0.862762451171875 +26212 0.79669189453125 +26213 0.595794677734375 +26214 0.362152099609375 +26215 0.1270751953125 +26216 -0.086944580078125 +26217 -0.2784423828125 +26218 -0.484832763671875 +26219 -0.729583740234375 +26220 -0.86688232421875 +26221 -0.870391845703125 +26222 -0.86859130859375 +26223 -0.86279296875 +26224 -0.817962646484375 +26225 -0.6116943359375 +26226 -0.3128662109375 +26227 0.039398193359375 +26228 0.422821044921875 +26229 0.805145263671875 +26230 0.870361328125 +26231 0.870361328125 +26232 0.860015869140625 +26233 0.727935791015625 +26234 0.48114013671875 +26235 0.2059326171875 +26236 -0.06103515625 +26237 -0.29913330078125 +26238 -0.516204833984375 +26239 -0.7252197265625 +26240 -0.85980224609375 +26241 -0.870391845703125 +26242 -0.870391845703125 +26243 -0.858062744140625 +26244 -0.673004150390625 +26245 -0.42694091796875 +26246 -0.2100830078125 +26247 -0.0362548828125 +26248 0.10943603515625 +26249 0.23516845703125 +26250 0.373687744140625 +26251 0.517791748046875 +26252 0.602783203125 +26253 0.635711669921875 +26254 0.655181884765625 +26255 0.65948486328125 +26256 0.651275634765625 +26257 0.61846923828125 +26258 0.53753662109375 +26259 0.404144287109375 +26260 0.22186279296875 +26261 0.003997802734375 +26262 -0.22100830078125 +26263 -0.42449951171875 +26264 -0.579833984375 +26265 -0.641876220703125 +26266 -0.6177978515625 +26267 -0.575531005859375 +26268 -0.526336669921875 +26269 -0.42645263671875 +26270 -0.2581787109375 +26271 -0.068695068359375 +26272 0.09222412109375 +26273 0.232147216796875 +26274 0.3509521484375 +26275 0.410064697265625 +26276 0.372955322265625 +26277 0.2554931640625 +26278 0.10711669921875 +26279 -0.052886962890625 +26280 -0.186279296875 +26281 -0.23291015625 +26282 -0.209442138671875 +26283 -0.174163818359375 +26284 -0.126739501953125 +26285 -0.048126220703125 +26286 0.0426025390625 +26287 0.10748291015625 +26288 0.1409912109375 +26289 0.19708251953125 +26290 0.273651123046875 +26291 0.31768798828125 +26292 0.341094970703125 +26293 0.368011474609375 +26294 0.37249755859375 +26295 0.30072021484375 +26296 0.1517333984375 +26297 -0.01470947265625 +26298 -0.1883544921875 +26299 -0.372711181640625 +26300 -0.51397705078125 +26301 -0.57177734375 +26302 -0.53948974609375 +26303 -0.43511962890625 +26304 -0.2962646484375 +26305 -0.161102294921875 +26306 -0.0435791015625 +26307 0.060394287109375 +26308 0.13665771484375 +26309 0.170135498046875 +26310 0.16552734375 +26311 0.15728759765625 +26312 0.150787353515625 +26313 0.12200927734375 +26314 0.080108642578125 +26315 0.05126953125 +26316 0.062896728515625 +26317 0.09271240234375 +26318 0.092987060546875 +26319 0.07855224609375 +26320 0.06427001953125 +26321 0.0347900390625 +26322 -0.01171875 +26323 -0.056060791015625 +26324 -0.055511474609375 +26325 -0.010467529296875 +26326 0.02508544921875 +26327 0.025665283203125 +26328 0.017333984375 +26329 0.00189208984375 +26330 -0.03173828125 +26331 -0.071502685546875 +26332 -0.13543701171875 +26333 -0.219970703125 +26334 -0.300506591796875 +26335 -0.376312255859375 +26336 -0.416107177734375 +26337 -0.371124267578125 +26338 -0.242279052734375 +26339 -0.069732666015625 +26340 0.125640869140625 +26341 0.31268310546875 +26342 0.45501708984375 +26343 0.554779052734375 +26344 0.61065673828125 +26345 0.610931396484375 +26346 0.531463623046875 +26347 0.3883056640625 +26348 0.23468017578125 +26349 0.095245361328125 +26350 -0.00396728515625 +26351 -0.04852294921875 +26352 -0.055145263671875 +26353 -0.0758056640625 +26354 -0.138702392578125 +26355 -0.209197998046875 +26356 -0.289031982421875 +26357 -0.37884521484375 +26358 -0.456329345703125 +26359 -0.51641845703125 +26360 -0.519287109375 +26361 -0.458251953125 +26362 -0.384796142578125 +26363 -0.323699951171875 +26364 -0.269287109375 +26365 -0.1951904296875 +26366 -0.100006103515625 +26367 -0.01055908203125 +26368 0.1033935546875 +26369 0.24908447265625 +26370 0.373199462890625 +26371 0.45806884765625 +26372 0.511474609375 +26373 0.565399169921875 +26374 0.61138916015625 +26375 0.5897216796875 +26376 0.4906005859375 +26377 0.33148193359375 +26378 0.147796630859375 +26379 -0.01873779296875 +26380 -0.140289306640625 +26381 -0.191986083984375 +26382 -0.184295654296875 +26383 -0.161834716796875 +26384 -0.166595458984375 +26385 -0.19390869140625 +26386 -0.22442626953125 +26387 -0.279754638671875 +26388 -0.3389892578125 +26389 -0.3543701171875 +26390 -0.348175048828125 +26391 -0.32598876953125 +26392 -0.2581787109375 +26393 -0.139801025390625 +26394 0.014617919921875 +26395 0.144378662109375 +26396 0.221038818359375 +26397 0.27069091796875 +26398 0.294036865234375 +26399 0.311767578125 +26400 0.339141845703125 +26401 0.360260009765625 +26402 0.360504150390625 +26403 0.308380126953125 +26404 0.18170166015625 +26405 0.0047607421875 +26406 -0.17559814453125 +26407 -0.3143310546875 +26408 -0.36785888671875 +26409 -0.36248779296875 +26410 -0.343536376953125 +26411 -0.3018798828125 +26412 -0.231414794921875 +26413 -0.117645263671875 +26414 0.007049560546875 +26415 0.087982177734375 +26416 0.13946533203125 +26417 0.17425537109375 +26418 0.188201904296875 +26419 0.171234130859375 +26420 0.118438720703125 +26421 0.05706787109375 +26422 -0.010711669921875 +26423 -0.0914306640625 +26424 -0.162322998046875 +26425 -0.194549560546875 +26426 -0.1492919921875 +26427 -0.02166748046875 +26428 0.124053955078125 +26429 0.211151123046875 +26430 0.240447998046875 +26431 0.242218017578125 +26432 0.2257080078125 +26433 0.194366455078125 +26434 0.115509033203125 +26435 0.0128173828125 +26436 -0.053802490234375 +26437 -0.110626220703125 +26438 -0.199493408203125 +26439 -0.29437255859375 +26440 -0.33221435546875 +26441 -0.27972412109375 +26442 -0.185333251953125 +26443 -0.128204345703125 +26444 -0.115692138671875 +26445 -0.116455078125 +26446 -0.105926513671875 +26447 -0.053955078125 +26448 0.048797607421875 +26449 0.157318115234375 +26450 0.212005615234375 +26451 0.218475341796875 +26452 0.23724365234375 +26453 0.30535888671875 +26454 0.38128662109375 +26455 0.404449462890625 +26456 0.3944091796875 +26457 0.3885498046875 +26458 0.362640380859375 +26459 0.27362060546875 +26460 0.11712646484375 +26461 -0.054901123046875 +26462 -0.19085693359375 +26463 -0.28570556640625 +26464 -0.339263916015625 +26465 -0.3775634765625 +26466 -0.445709228515625 +26467 -0.535064697265625 +26468 -0.629058837890625 +26469 -0.697601318359375 +26470 -0.70391845703125 +26471 -0.6424560546875 +26472 -0.491241455078125 +26473 -0.265716552734375 +26474 -0.023712158203125 +26475 0.201751708984375 +26476 0.375823974609375 +26477 0.485076904296875 +26478 0.56884765625 +26479 0.634765625 +26480 0.63763427734375 +26481 0.5660400390625 +26482 0.4720458984375 +26483 0.40692138671875 +26484 0.3778076171875 +26485 0.376953125 +26486 0.371978759765625 +26487 0.313140869140625 +26488 0.184417724609375 +26489 0.011199951171875 +26490 -0.171051025390625 +26491 -0.33740234375 +26492 -0.47198486328125 +26493 -0.560394287109375 +26494 -0.58056640625 +26495 -0.54754638671875 +26496 -0.508575439453125 +26497 -0.459503173828125 +26498 -0.394378662109375 +26499 -0.35260009765625 +26500 -0.31170654296875 +26501 -0.197418212890625 +26502 -0.007965087890625 +26503 0.207489013671875 +26504 0.409210205078125 +26505 0.57208251953125 +26506 0.66595458984375 +26507 0.65875244140625 +26508 0.56744384765625 +26509 0.431396484375 +26510 0.29443359375 +26511 0.182464599609375 +26512 0.06365966796875 +26513 -0.075958251953125 +26514 -0.189422607421875 +26515 -0.271942138671875 +26516 -0.342529296875 +26517 -0.364166259765625 +26518 -0.327239990234375 +26519 -0.2769775390625 +26520 -0.253692626953125 +26521 -0.24365234375 +26522 -0.1983642578125 +26523 -0.116241455078125 +26524 -0.036834716796875 +26525 0.034881591796875 +26526 0.09124755859375 +26527 0.10888671875 +26528 0.125518798828125 +26529 0.15771484375 +26530 0.17828369140625 +26531 0.17108154296875 +26532 0.129974365234375 +26533 0.082427978515625 +26534 0.027679443359375 +26535 -0.065643310546875 +26536 -0.15936279296875 +26537 -0.21307373046875 +26538 -0.234649658203125 +26539 -0.2001953125 +26540 -0.119171142578125 +26541 -0.024749755859375 +26542 0.085784912109375 +26543 0.178131103515625 +26544 0.215576171875 +26545 0.211456298828125 +26546 0.17523193359375 +26547 0.128753662109375 +26548 0.1019287109375 +26549 0.0743408203125 +26550 0.04327392578125 +26551 0.038177490234375 +26552 0.076263427734375 +26553 0.14105224609375 +26554 0.186431884765625 +26555 0.188812255859375 +26556 0.1390380859375 +26557 0.041778564453125 +26558 -0.079437255859375 +26559 -0.219390869140625 +26560 -0.367828369140625 +26561 -0.494873046875 +26562 -0.556243896484375 +26563 -0.508697509765625 +26564 -0.3756103515625 +26565 -0.218902587890625 +26566 -0.063751220703125 +26567 0.091552734375 +26568 0.23602294921875 +26569 0.342987060546875 +26570 0.39520263671875 +26571 0.389373779296875 +26572 0.324249267578125 +26573 0.224090576171875 +26574 0.124267578125 +26575 0.037078857421875 +26576 -0.010101318359375 +26577 -0.019439697265625 +26578 -0.022796630859375 +26579 -0.001556396484375 +26580 0.056304931640625 +26581 0.106719970703125 +26582 0.096893310546875 +26583 0.042694091796875 +26584 -0.018035888671875 +26585 -0.07586669921875 +26586 -0.11944580078125 +26587 -0.15972900390625 +26588 -0.202606201171875 +26589 -0.24859619140625 +26590 -0.30517578125 +26591 -0.36212158203125 +26592 -0.39141845703125 +26593 -0.35528564453125 +26594 -0.249969482421875 +26595 -0.092864990234375 +26596 0.08905029296875 +26597 0.2352294921875 +26598 0.318817138671875 +26599 0.358642578125 +26600 0.347747802734375 +26601 0.28564453125 +26602 0.223175048828125 +26603 0.196746826171875 +26604 0.179840087890625 +26605 0.155548095703125 +26606 0.151214599609375 +26607 0.156951904296875 +26608 0.13177490234375 +26609 0.100799560546875 +26610 0.087127685546875 +26611 0.05487060546875 +26612 -0.009002685546875 +26613 -0.10400390625 +26614 -0.229400634765625 +26615 -0.35552978515625 +26616 -0.441925048828125 +26617 -0.473846435546875 +26618 -0.464813232421875 +26619 -0.419097900390625 +26620 -0.334320068359375 +26621 -0.227935791015625 +26622 -0.12347412109375 +26623 -0.02764892578125 +26624 0.077667236328125 +26625 0.2132568359375 +26626 0.38885498046875 +26627 0.582794189453125 +26628 0.734039306640625 +26629 0.800140380859375 +26630 0.7783203125 +26631 0.6651611328125 +26632 0.45965576171875 +26633 0.199188232421875 +26634 -0.050689697265625 +26635 -0.23297119140625 +26636 -0.33013916015625 +26637 -0.368408203125 +26638 -0.378936767578125 +26639 -0.376983642578125 +26640 -0.37969970703125 +26641 -0.391510009765625 +26642 -0.385345458984375 +26643 -0.3419189453125 +26644 -0.28289794921875 +26645 -0.251617431640625 +26646 -0.266143798828125 +26647 -0.273345947265625 +26648 -0.216796875 +26649 -0.128265380859375 +26650 -0.068145751953125 +26651 -0.0430908203125 +26652 -0.024444580078125 +26653 0.020721435546875 +26654 0.124481201171875 +26655 0.25787353515625 +26656 0.379119873046875 +26657 0.47991943359375 +26658 0.5281982421875 +26659 0.511138916015625 +26660 0.456207275390625 +26661 0.407470703125 +26662 0.383758544921875 +26663 0.35687255859375 +26664 0.31182861328125 +26665 0.250885009765625 +26666 0.1654052734375 +26667 0.035247802734375 +26668 -0.142059326171875 +26669 -0.33563232421875 +26670 -0.5345458984375 +26671 -0.72186279296875 +26672 -0.836669921875 +26673 -0.8326416015625 +26674 -0.7296142578125 +26675 -0.582550048828125 +26676 -0.440093994140625 +26677 -0.324310302734375 +26678 -0.20147705078125 +26679 -0.044647216796875 +26680 0.103973388671875 +26681 0.202392578125 +26682 0.264495849609375 +26683 0.338897705078125 +26684 0.443817138671875 +26685 0.545074462890625 +26686 0.6173095703125 +26687 0.6524658203125 +26688 0.66339111328125 +26689 0.6561279296875 +26690 0.606781005859375 +26691 0.501190185546875 +26692 0.352783203125 +26693 0.176544189453125 +26694 -0.034820556640625 +26695 -0.258209228515625 +26696 -0.44244384765625 +26697 -0.5753173828125 +26698 -0.65203857421875 +26699 -0.641632080078125 +26700 -0.562164306640625 +26701 -0.458038330078125 +26702 -0.350555419921875 +26703 -0.260528564453125 +26704 -0.192108154296875 +26705 -0.141937255859375 +26706 -0.1021728515625 +26707 -0.062896728515625 +26708 -0.011932373046875 +26709 0.062835693359375 +26710 0.148712158203125 +26711 0.241729736328125 +26712 0.34912109375 +26713 0.457305908203125 +26714 0.54388427734375 +26715 0.5728759765625 +26716 0.506591796875 +26717 0.351226806640625 +26718 0.146514892578125 +26719 -0.05523681640625 +26720 -0.21624755859375 +26721 -0.334930419921875 +26722 -0.402984619140625 +26723 -0.4412841796875 +26724 -0.49578857421875 +26725 -0.5601806640625 +26726 -0.600738525390625 +26727 -0.584228515625 +26728 -0.47930908203125 +26729 -0.27935791015625 +26730 -0.0089111328125 +26731 0.268798828125 +26732 0.482818603515625 +26733 0.60369873046875 +26734 0.650421142578125 +26735 0.66400146484375 +26736 0.6414794921875 +26737 0.572540283203125 +26738 0.498138427734375 +26739 0.439453125 +26740 0.375518798828125 +26741 0.274505615234375 +26742 0.1087646484375 +26743 -0.099395751953125 +26744 -0.3182373046875 +26745 -0.5489501953125 +26746 -0.7738037109375 +26747 -0.86383056640625 +26748 -0.870391845703125 +26749 -0.86895751953125 +26750 -0.861053466796875 +26751 -0.765869140625 +26752 -0.5301513671875 +26753 -0.214691162109375 +26754 0.137359619140625 +26755 0.474822998046875 +26756 0.76239013671875 +26757 0.867462158203125 +26758 0.870361328125 +26759 0.86480712890625 +26760 0.831817626953125 +26761 0.677581787109375 +26762 0.495880126953125 +26763 0.30767822265625 +26764 0.116180419921875 +26765 -0.110748291015625 +26766 -0.381805419921875 +26767 -0.6572265625 +26768 -0.857421875 +26769 -0.870391845703125 +26770 -0.870391845703125 +26771 -0.86444091796875 +26772 -0.85723876953125 +26773 -0.790008544921875 +26774 -0.62847900390625 +26775 -0.3956298828125 +26776 -0.126708984375 +26777 0.150115966796875 +26778 0.424041748046875 +26779 0.670623779296875 +26780 0.854522705078125 +26781 0.866485595703125 +26782 0.86920166015625 +26783 0.8653564453125 +26784 0.857147216796875 +26785 0.766845703125 +26786 0.628509521484375 +26787 0.462127685546875 +26788 0.297210693359375 +26789 0.14862060546875 +26790 -0.00537109375 +26791 -0.15753173828125 +26792 -0.31304931640625 +26793 -0.48876953125 +26794 -0.6416015625 +26795 -0.751373291015625 +26796 -0.84619140625 +26797 -0.861297607421875 +26798 -0.863250732421875 +26799 -0.856597900390625 +26800 -0.7498779296875 +26801 -0.624542236328125 +26802 -0.47808837890625 +26803 -0.253387451171875 +26804 0.003692626953125 +26805 0.2257080078125 +26806 0.427154541015625 +26807 0.643218994140625 +26808 0.855926513671875 +26809 0.870361328125 +26810 0.870361328125 +26811 0.862762451171875 +26812 0.79669189453125 +26813 0.595794677734375 +26814 0.362152099609375 +26815 0.1270751953125 +26816 -0.086944580078125 +26817 -0.2784423828125 +26818 -0.484832763671875 +26819 -0.729583740234375 +26820 -0.86688232421875 +26821 -0.870391845703125 +26822 -0.86859130859375 +26823 -0.86279296875 +26824 -0.817962646484375 +26825 -0.6116943359375 +26826 -0.3128662109375 +26827 0.039398193359375 +26828 0.422821044921875 +26829 0.805145263671875 +26830 0.870361328125 +26831 0.870361328125 +26832 0.860015869140625 +26833 0.727935791015625 +26834 0.48114013671875 +26835 0.2059326171875 +26836 -0.06103515625 +26837 -0.29913330078125 +26838 -0.516204833984375 +26839 -0.7252197265625 +26840 -0.85980224609375 +26841 -0.870391845703125 +26842 -0.870391845703125 +26843 -0.858062744140625 +26844 -0.673004150390625 +26845 -0.42694091796875 +26846 -0.2100830078125 +26847 -0.0362548828125 +26848 0.10943603515625 +26849 0.23516845703125 +26850 0.373687744140625 +26851 0.517791748046875 +26852 0.602783203125 +26853 0.635711669921875 +26854 0.655181884765625 +26855 0.65948486328125 +26856 0.651275634765625 +26857 0.61846923828125 +26858 0.53753662109375 +26859 0.404144287109375 +26860 0.22186279296875 +26861 0.003997802734375 +26862 -0.22100830078125 +26863 -0.42449951171875 +26864 -0.579833984375 +26865 -0.641876220703125 +26866 -0.6177978515625 +26867 -0.575531005859375 +26868 -0.526336669921875 +26869 -0.42645263671875 +26870 -0.2581787109375 +26871 -0.068695068359375 +26872 0.09222412109375 +26873 0.232147216796875 +26874 0.3509521484375 +26875 0.410064697265625 +26876 0.372955322265625 +26877 0.2554931640625 +26878 0.10711669921875 +26879 -0.052886962890625 +26880 -0.186279296875 +26881 -0.23291015625 +26882 -0.209442138671875 +26883 -0.174163818359375 +26884 -0.126739501953125 +26885 -0.048126220703125 +26886 0.0426025390625 +26887 0.10748291015625 +26888 0.1409912109375 +26889 0.19708251953125 +26890 0.273651123046875 +26891 0.31768798828125 +26892 0.341094970703125 +26893 0.368011474609375 +26894 0.37249755859375 +26895 0.30072021484375 +26896 0.1517333984375 +26897 -0.01470947265625 +26898 -0.1883544921875 +26899 -0.372711181640625 +26900 -0.51397705078125 +26901 -0.57177734375 +26902 -0.53948974609375 +26903 -0.43511962890625 +26904 -0.2962646484375 +26905 -0.161102294921875 +26906 -0.0435791015625 +26907 0.060394287109375 +26908 0.13665771484375 +26909 0.170135498046875 +26910 0.16552734375 +26911 0.15728759765625 +26912 0.150787353515625 +26913 0.12200927734375 +26914 0.080108642578125 +26915 0.05126953125 +26916 0.062896728515625 +26917 0.09271240234375 +26918 0.092987060546875 +26919 0.07855224609375 +26920 0.06427001953125 +26921 0.0347900390625 +26922 -0.01171875 +26923 -0.056060791015625 +26924 -0.055511474609375 +26925 -0.010467529296875 +26926 0.02508544921875 +26927 0.025665283203125 +26928 0.017333984375 +26929 0.00189208984375 +26930 -0.03173828125 +26931 -0.071502685546875 +26932 -0.13543701171875 +26933 -0.219970703125 +26934 -0.300506591796875 +26935 -0.376312255859375 +26936 -0.416107177734375 +26937 -0.371124267578125 +26938 -0.242279052734375 +26939 -0.069732666015625 +26940 0.125640869140625 +26941 0.31268310546875 +26942 0.45501708984375 +26943 0.554779052734375 +26944 0.61065673828125 +26945 0.610931396484375 +26946 0.531463623046875 +26947 0.3883056640625 +26948 0.23468017578125 +26949 0.095245361328125 +26950 -0.00396728515625 +26951 -0.04852294921875 +26952 -0.055145263671875 +26953 -0.0758056640625 +26954 -0.138702392578125 +26955 -0.209197998046875 +26956 -0.289031982421875 +26957 -0.37884521484375 +26958 -0.456329345703125 +26959 -0.51641845703125 +26960 -0.519287109375 +26961 -0.458251953125 +26962 -0.384796142578125 +26963 -0.323699951171875 +26964 -0.269287109375 +26965 -0.1951904296875 +26966 -0.100006103515625 +26967 -0.01055908203125 +26968 0.1033935546875 +26969 0.24908447265625 +26970 0.373199462890625 +26971 0.45806884765625 +26972 0.511474609375 +26973 0.565399169921875 +26974 0.61138916015625 +26975 0.5897216796875 +26976 0.4906005859375 +26977 0.33148193359375 +26978 0.147796630859375 +26979 -0.01873779296875 +26980 -0.140289306640625 +26981 -0.191986083984375 +26982 -0.184295654296875 +26983 -0.161834716796875 +26984 -0.166595458984375 +26985 -0.19390869140625 +26986 -0.22442626953125 +26987 -0.279754638671875 +26988 -0.3389892578125 +26989 -0.3543701171875 +26990 -0.348175048828125 +26991 -0.32598876953125 +26992 -0.2581787109375 +26993 -0.139801025390625 +26994 0.014617919921875 +26995 0.144378662109375 +26996 0.221038818359375 +26997 0.27069091796875 +26998 0.294036865234375 +26999 0.311767578125 +27000 0.339141845703125 +27001 0.360260009765625 +27002 0.360504150390625 +27003 0.308380126953125 +27004 0.18170166015625 +27005 0.0047607421875 +27006 -0.17559814453125 +27007 -0.3143310546875 +27008 -0.36785888671875 +27009 -0.36248779296875 +27010 -0.343536376953125 +27011 -0.3018798828125 +27012 -0.231414794921875 +27013 -0.117645263671875 +27014 0.007049560546875 +27015 0.087982177734375 +27016 0.13946533203125 +27017 0.17425537109375 +27018 0.188201904296875 +27019 0.171234130859375 +27020 0.118438720703125 +27021 0.05706787109375 +27022 -0.010711669921875 +27023 -0.0914306640625 +27024 -0.162322998046875 +27025 -0.194549560546875 +27026 -0.1492919921875 +27027 -0.02166748046875 +27028 0.124053955078125 +27029 0.211151123046875 +27030 0.240447998046875 +27031 0.242218017578125 +27032 0.2257080078125 +27033 0.194366455078125 +27034 0.115509033203125 +27035 0.0128173828125 +27036 -0.053802490234375 +27037 -0.110626220703125 +27038 -0.199493408203125 +27039 -0.29437255859375 +27040 -0.33221435546875 +27041 -0.27972412109375 +27042 -0.185333251953125 +27043 -0.128204345703125 +27044 -0.115692138671875 +27045 -0.116455078125 +27046 -0.105926513671875 +27047 -0.053955078125 +27048 0.048797607421875 +27049 0.157318115234375 +27050 0.212005615234375 +27051 0.218475341796875 +27052 0.23724365234375 +27053 0.30535888671875 +27054 0.38128662109375 +27055 0.404449462890625 +27056 0.3944091796875 +27057 0.3885498046875 +27058 0.362640380859375 +27059 0.27362060546875 +27060 0.11712646484375 +27061 -0.054901123046875 +27062 -0.19085693359375 +27063 -0.28570556640625 +27064 -0.339263916015625 +27065 -0.3775634765625 +27066 -0.445709228515625 +27067 -0.535064697265625 +27068 -0.629058837890625 +27069 -0.697601318359375 +27070 -0.70391845703125 +27071 -0.6424560546875 +27072 -0.491241455078125 +27073 -0.265716552734375 +27074 -0.023712158203125 +27075 0.201751708984375 +27076 0.375823974609375 +27077 0.485076904296875 +27078 0.56884765625 +27079 0.634765625 +27080 0.63763427734375 +27081 0.5660400390625 +27082 0.4720458984375 +27083 0.40692138671875 +27084 0.3778076171875 +27085 0.376953125 +27086 0.371978759765625 +27087 0.313140869140625 +27088 0.184417724609375 +27089 0.011199951171875 +27090 -0.171051025390625 +27091 -0.33740234375 +27092 -0.47198486328125 +27093 -0.560394287109375 +27094 -0.58056640625 +27095 -0.54754638671875 +27096 -0.508575439453125 +27097 -0.459503173828125 +27098 -0.394378662109375 +27099 -0.35260009765625 +27100 -0.31170654296875 +27101 -0.197418212890625 +27102 -0.007965087890625 +27103 0.207489013671875 +27104 0.409210205078125 +27105 0.57208251953125 +27106 0.66595458984375 +27107 0.65875244140625 +27108 0.56744384765625 +27109 0.431396484375 +27110 0.29443359375 +27111 0.182464599609375 +27112 0.06365966796875 +27113 -0.075958251953125 +27114 -0.189422607421875 +27115 -0.271942138671875 +27116 -0.342529296875 +27117 -0.364166259765625 +27118 -0.327239990234375 +27119 -0.2769775390625 +27120 -0.253692626953125 +27121 -0.24365234375 +27122 -0.1983642578125 +27123 -0.116241455078125 +27124 -0.036834716796875 +27125 0.034881591796875 +27126 0.09124755859375 +27127 0.10888671875 +27128 0.125518798828125 +27129 0.15771484375 +27130 0.17828369140625 +27131 0.17108154296875 +27132 0.129974365234375 +27133 0.082427978515625 +27134 0.027679443359375 +27135 -0.065643310546875 +27136 -0.15936279296875 +27137 -0.21307373046875 +27138 -0.234649658203125 +27139 -0.2001953125 +27140 -0.119171142578125 +27141 -0.024749755859375 +27142 0.085784912109375 +27143 0.178131103515625 +27144 0.215576171875 +27145 0.211456298828125 +27146 0.17523193359375 +27147 0.128753662109375 +27148 0.1019287109375 +27149 0.0743408203125 +27150 0.04327392578125 +27151 0.038177490234375 +27152 0.076263427734375 +27153 0.14105224609375 +27154 0.186431884765625 +27155 0.188812255859375 +27156 0.1390380859375 +27157 0.041778564453125 +27158 -0.079437255859375 +27159 -0.219390869140625 +27160 -0.367828369140625 +27161 -0.494873046875 +27162 -0.556243896484375 +27163 -0.508697509765625 +27164 -0.3756103515625 +27165 -0.218902587890625 +27166 -0.063751220703125 +27167 0.091552734375 +27168 0.23602294921875 +27169 0.342987060546875 +27170 0.39520263671875 +27171 0.389373779296875 +27172 0.324249267578125 +27173 0.224090576171875 +27174 0.124267578125 +27175 0.037078857421875 +27176 -0.010101318359375 +27177 -0.019439697265625 +27178 -0.022796630859375 +27179 -0.001556396484375 +27180 0.056304931640625 +27181 0.106719970703125 +27182 0.096893310546875 +27183 0.042694091796875 +27184 -0.018035888671875 +27185 -0.07586669921875 +27186 -0.11944580078125 +27187 -0.15972900390625 +27188 -0.202606201171875 +27189 -0.24859619140625 +27190 -0.30517578125 +27191 -0.36212158203125 +27192 -0.39141845703125 +27193 -0.35528564453125 +27194 -0.249969482421875 +27195 -0.092864990234375 +27196 0.08905029296875 +27197 0.2352294921875 +27198 0.318817138671875 +27199 0.358642578125 +27200 0.347747802734375 +27201 0.28564453125 +27202 0.223175048828125 +27203 0.196746826171875 +27204 0.179840087890625 +27205 0.155548095703125 +27206 0.151214599609375 +27207 0.156951904296875 +27208 0.13177490234375 +27209 0.100799560546875 +27210 0.087127685546875 +27211 0.05487060546875 +27212 -0.009002685546875 +27213 -0.10400390625 +27214 -0.229400634765625 +27215 -0.35552978515625 +27216 -0.441925048828125 +27217 -0.473846435546875 +27218 -0.464813232421875 +27219 -0.419097900390625 +27220 -0.334320068359375 +27221 -0.227935791015625 +27222 -0.12347412109375 +27223 -0.02764892578125 +27224 0.077667236328125 +27225 0.2132568359375 +27226 0.38885498046875 +27227 0.582794189453125 +27228 0.734039306640625 +27229 0.800140380859375 +27230 0.7783203125 +27231 0.6651611328125 +27232 0.45965576171875 +27233 0.199188232421875 +27234 -0.050689697265625 +27235 -0.23297119140625 +27236 -0.33013916015625 +27237 -0.368408203125 +27238 -0.378936767578125 +27239 -0.376983642578125 +27240 -0.37969970703125 +27241 -0.391510009765625 +27242 -0.385345458984375 +27243 -0.3419189453125 +27244 -0.28289794921875 +27245 -0.251617431640625 +27246 -0.266143798828125 +27247 -0.273345947265625 +27248 -0.216796875 +27249 -0.128265380859375 +27250 -0.068145751953125 +27251 -0.0430908203125 +27252 -0.024444580078125 +27253 0.020721435546875 +27254 0.124481201171875 +27255 0.25787353515625 +27256 0.379119873046875 +27257 0.47991943359375 +27258 0.5281982421875 +27259 0.511138916015625 +27260 0.456207275390625 +27261 0.407470703125 +27262 0.383758544921875 +27263 0.35687255859375 +27264 0.31182861328125 +27265 0.250885009765625 +27266 0.1654052734375 +27267 0.035247802734375 +27268 -0.142059326171875 +27269 -0.33563232421875 +27270 -0.5345458984375 +27271 -0.72186279296875 +27272 -0.836669921875 +27273 -0.8326416015625 +27274 -0.7296142578125 +27275 -0.582550048828125 +27276 -0.440093994140625 +27277 -0.324310302734375 +27278 -0.20147705078125 +27279 -0.044647216796875 +27280 0.103973388671875 +27281 0.202392578125 +27282 0.264495849609375 +27283 0.338897705078125 +27284 0.443817138671875 +27285 0.545074462890625 +27286 0.6173095703125 +27287 0.6524658203125 +27288 0.66339111328125 +27289 0.6561279296875 +27290 0.606781005859375 +27291 0.501190185546875 +27292 0.352783203125 +27293 0.176544189453125 +27294 -0.034820556640625 +27295 -0.258209228515625 +27296 -0.44244384765625 +27297 -0.5753173828125 +27298 -0.65203857421875 +27299 -0.641632080078125 +27300 -0.562164306640625 +27301 -0.458038330078125 +27302 -0.350555419921875 +27303 -0.260528564453125 +27304 -0.192108154296875 +27305 -0.141937255859375 +27306 -0.1021728515625 +27307 -0.062896728515625 +27308 -0.011932373046875 +27309 0.062835693359375 +27310 0.148712158203125 +27311 0.241729736328125 +27312 0.34912109375 +27313 0.457305908203125 +27314 0.54388427734375 +27315 0.5728759765625 +27316 0.506591796875 +27317 0.351226806640625 +27318 0.146514892578125 +27319 -0.05523681640625 +27320 -0.21624755859375 +27321 -0.334930419921875 +27322 -0.402984619140625 +27323 -0.4412841796875 +27324 -0.49578857421875 +27325 -0.5601806640625 +27326 -0.600738525390625 +27327 -0.584228515625 +27328 -0.47930908203125 +27329 -0.27935791015625 +27330 -0.0089111328125 +27331 0.268798828125 +27332 0.482818603515625 +27333 0.60369873046875 +27334 0.650421142578125 +27335 0.66400146484375 +27336 0.6414794921875 +27337 0.572540283203125 +27338 0.498138427734375 +27339 0.439453125 +27340 0.375518798828125 +27341 0.274505615234375 +27342 0.1087646484375 +27343 -0.099395751953125 +27344 -0.3182373046875 +27345 -0.5489501953125 +27346 -0.7738037109375 +27347 -0.86383056640625 +27348 -0.870391845703125 +27349 -0.86895751953125 +27350 -0.861053466796875 +27351 -0.765869140625 +27352 -0.5301513671875 +27353 -0.214691162109375 +27354 0.137359619140625 +27355 0.474822998046875 +27356 0.76239013671875 +27357 0.867462158203125 +27358 0.870361328125 +27359 0.86480712890625 +27360 0.831817626953125 +27361 0.677581787109375 +27362 0.495880126953125 +27363 0.30767822265625 +27364 0.116180419921875 +27365 -0.110748291015625 +27366 -0.381805419921875 +27367 -0.6572265625 +27368 -0.857421875 +27369 -0.870391845703125 +27370 -0.870391845703125 +27371 -0.86444091796875 +27372 -0.85723876953125 +27373 -0.790008544921875 +27374 -0.62847900390625 +27375 -0.3956298828125 +27376 -0.126708984375 +27377 0.150115966796875 +27378 0.424041748046875 +27379 0.670623779296875 +27380 0.854522705078125 +27381 0.866485595703125 +27382 0.86920166015625 +27383 0.8653564453125 +27384 0.857147216796875 +27385 0.766845703125 +27386 0.628509521484375 +27387 0.462127685546875 +27388 0.297210693359375 +27389 0.14862060546875 +27390 -0.00537109375 +27391 -0.15753173828125 +27392 -0.31304931640625 +27393 -0.48876953125 +27394 -0.6416015625 +27395 -0.751373291015625 +27396 -0.84619140625 +27397 -0.861297607421875 +27398 -0.863250732421875 +27399 -0.856597900390625 +27400 -0.7498779296875 +27401 -0.624542236328125 +27402 -0.47808837890625 +27403 -0.253387451171875 +27404 0.003692626953125 +27405 0.2257080078125 +27406 0.427154541015625 +27407 0.643218994140625 +27408 0.855926513671875 +27409 0.870361328125 +27410 0.870361328125 +27411 0.862762451171875 +27412 0.79669189453125 +27413 0.595794677734375 +27414 0.362152099609375 +27415 0.1270751953125 +27416 -0.086944580078125 +27417 -0.2784423828125 +27418 -0.484832763671875 +27419 -0.729583740234375 +27420 -0.86688232421875 +27421 -0.870391845703125 +27422 -0.86859130859375 +27423 -0.86279296875 +27424 -0.817962646484375 +27425 -0.6116943359375 +27426 -0.3128662109375 +27427 0.039398193359375 +27428 0.422821044921875 +27429 0.805145263671875 +27430 0.870361328125 +27431 0.870361328125 +27432 0.860015869140625 +27433 0.727935791015625 +27434 0.48114013671875 +27435 0.2059326171875 +27436 -0.06103515625 +27437 -0.29913330078125 +27438 -0.516204833984375 +27439 -0.7252197265625 +27440 -0.85980224609375 +27441 -0.870391845703125 +27442 -0.870391845703125 +27443 -0.858062744140625 +27444 -0.673004150390625 +27445 -0.42694091796875 +27446 -0.2100830078125 +27447 -0.0362548828125 +27448 0.10943603515625 +27449 0.23516845703125 +27450 0.373687744140625 +27451 0.517791748046875 +27452 0.602783203125 +27453 0.635711669921875 +27454 0.655181884765625 +27455 0.65948486328125 +27456 0.651275634765625 +27457 0.61846923828125 +27458 0.53753662109375 +27459 0.404144287109375 +27460 0.22186279296875 +27461 0.003997802734375 +27462 -0.22100830078125 +27463 -0.42449951171875 +27464 -0.579833984375 +27465 -0.641876220703125 +27466 -0.6177978515625 +27467 -0.575531005859375 +27468 -0.526336669921875 +27469 -0.42645263671875 +27470 -0.2581787109375 +27471 -0.068695068359375 +27472 0.09222412109375 +27473 0.232147216796875 +27474 0.3509521484375 +27475 0.410064697265625 +27476 0.372955322265625 +27477 0.2554931640625 +27478 0.10711669921875 +27479 -0.052886962890625 +27480 -0.186279296875 +27481 -0.23291015625 +27482 -0.209442138671875 +27483 -0.174163818359375 +27484 -0.126739501953125 +27485 -0.048126220703125 +27486 0.0426025390625 +27487 0.10748291015625 +27488 0.1409912109375 +27489 0.19708251953125 +27490 0.273651123046875 +27491 0.31768798828125 +27492 0.341094970703125 +27493 0.368011474609375 +27494 0.37249755859375 +27495 0.30072021484375 +27496 0.1517333984375 +27497 -0.01470947265625 +27498 -0.1883544921875 +27499 -0.372711181640625 +27500 -0.51397705078125 +27501 -0.57177734375 +27502 -0.53948974609375 +27503 -0.43511962890625 +27504 -0.2962646484375 +27505 -0.161102294921875 +27506 -0.0435791015625 +27507 0.060394287109375 +27508 0.13665771484375 +27509 0.170135498046875 +27510 0.16552734375 +27511 0.15728759765625 +27512 0.150787353515625 +27513 0.12200927734375 +27514 0.080108642578125 +27515 0.05126953125 +27516 0.062896728515625 +27517 0.09271240234375 +27518 0.092987060546875 +27519 0.07855224609375 +27520 0.06427001953125 +27521 0.0347900390625 +27522 -0.01171875 +27523 -0.056060791015625 +27524 -0.055511474609375 +27525 -0.010467529296875 +27526 0.02508544921875 +27527 0.025665283203125 +27528 0.017333984375 +27529 0.00189208984375 +27530 -0.03173828125 +27531 -0.071502685546875 +27532 -0.13543701171875 +27533 -0.219970703125 +27534 -0.300506591796875 +27535 -0.376312255859375 +27536 -0.416107177734375 +27537 -0.371124267578125 +27538 -0.242279052734375 +27539 -0.069732666015625 +27540 0.125640869140625 +27541 0.31268310546875 +27542 0.45501708984375 +27543 0.554779052734375 +27544 0.61065673828125 +27545 0.610931396484375 +27546 0.531463623046875 +27547 0.3883056640625 +27548 0.23468017578125 +27549 0.095245361328125 +27550 -0.00396728515625 +27551 -0.04852294921875 +27552 -0.055145263671875 +27553 -0.0758056640625 +27554 -0.138702392578125 +27555 -0.209197998046875 +27556 -0.289031982421875 +27557 -0.37884521484375 +27558 -0.456329345703125 +27559 -0.51641845703125 +27560 -0.519287109375 +27561 -0.458251953125 +27562 -0.384796142578125 +27563 -0.323699951171875 +27564 -0.269287109375 +27565 -0.1951904296875 +27566 -0.100006103515625 +27567 -0.01055908203125 +27568 0.1033935546875 +27569 0.24908447265625 +27570 0.373199462890625 +27571 0.45806884765625 +27572 0.511474609375 +27573 0.565399169921875 +27574 0.61138916015625 +27575 0.5897216796875 +27576 0.4906005859375 +27577 0.33148193359375 +27578 0.147796630859375 +27579 -0.01873779296875 +27580 -0.140289306640625 +27581 -0.191986083984375 +27582 -0.184295654296875 +27583 -0.161834716796875 +27584 -0.166595458984375 +27585 -0.19390869140625 +27586 -0.22442626953125 +27587 -0.279754638671875 +27588 -0.3389892578125 +27589 -0.3543701171875 +27590 -0.348175048828125 +27591 -0.32598876953125 +27592 -0.2581787109375 +27593 -0.139801025390625 +27594 0.014617919921875 +27595 0.144378662109375 +27596 0.221038818359375 +27597 0.27069091796875 +27598 0.294036865234375 +27599 0.311767578125 +27600 0.339141845703125 +27601 0.360260009765625 +27602 0.360504150390625 +27603 0.308380126953125 +27604 0.18170166015625 +27605 0.0047607421875 +27606 -0.17559814453125 +27607 -0.3143310546875 +27608 -0.36785888671875 +27609 -0.36248779296875 +27610 -0.343536376953125 +27611 -0.3018798828125 +27612 -0.231414794921875 +27613 -0.117645263671875 +27614 0.007049560546875 +27615 0.087982177734375 +27616 0.13946533203125 +27617 0.17425537109375 +27618 0.188201904296875 +27619 0.171234130859375 +27620 0.118438720703125 +27621 0.05706787109375 +27622 -0.010711669921875 +27623 -0.0914306640625 +27624 -0.162322998046875 +27625 -0.194549560546875 +27626 -0.1492919921875 +27627 -0.02166748046875 +27628 0.124053955078125 +27629 0.211151123046875 +27630 0.240447998046875 +27631 0.242218017578125 +27632 0.2257080078125 +27633 0.194366455078125 +27634 0.115509033203125 +27635 0.0128173828125 +27636 -0.053802490234375 +27637 -0.110626220703125 +27638 -0.199493408203125 +27639 -0.29437255859375 +27640 -0.33221435546875 +27641 -0.27972412109375 +27642 -0.185333251953125 +27643 -0.128204345703125 +27644 -0.115692138671875 +27645 -0.116455078125 +27646 -0.105926513671875 +27647 -0.053955078125 +27648 0.048797607421875 +27649 0.157318115234375 +27650 0.212005615234375 +27651 0.218475341796875 +27652 0.23724365234375 +27653 0.30535888671875 +27654 0.38128662109375 +27655 0.404449462890625 +27656 0.3944091796875 +27657 0.3885498046875 +27658 0.362640380859375 +27659 0.27362060546875 +27660 0.11712646484375 +27661 -0.054901123046875 +27662 -0.19085693359375 +27663 -0.28570556640625 +27664 -0.339263916015625 +27665 -0.3775634765625 +27666 -0.445709228515625 +27667 -0.535064697265625 +27668 -0.629058837890625 +27669 -0.697601318359375 +27670 -0.70391845703125 +27671 -0.6424560546875 +27672 -0.491241455078125 +27673 -0.265716552734375 +27674 -0.023712158203125 +27675 0.201751708984375 +27676 0.375823974609375 +27677 0.485076904296875 +27678 0.56884765625 +27679 0.634765625 +27680 0.63763427734375 +27681 0.5660400390625 +27682 0.4720458984375 +27683 0.40692138671875 +27684 0.3778076171875 +27685 0.376953125 +27686 0.371978759765625 +27687 0.313140869140625 +27688 0.184417724609375 +27689 0.011199951171875 +27690 -0.171051025390625 +27691 -0.33740234375 +27692 -0.47198486328125 +27693 -0.560394287109375 +27694 -0.58056640625 +27695 -0.54754638671875 +27696 -0.508575439453125 +27697 -0.459503173828125 +27698 -0.394378662109375 +27699 -0.35260009765625 +27700 -0.31170654296875 +27701 -0.197418212890625 +27702 -0.007965087890625 +27703 0.207489013671875 +27704 0.409210205078125 +27705 0.57208251953125 +27706 0.66595458984375 +27707 0.65875244140625 +27708 0.56744384765625 +27709 0.431396484375 +27710 0.29443359375 +27711 0.182464599609375 +27712 0.06365966796875 +27713 -0.075958251953125 +27714 -0.189422607421875 +27715 -0.271942138671875 +27716 -0.342529296875 +27717 -0.364166259765625 +27718 -0.327239990234375 +27719 -0.2769775390625 +27720 -0.253692626953125 +27721 -0.24365234375 +27722 -0.1983642578125 +27723 -0.116241455078125 +27724 -0.036834716796875 +27725 0.034881591796875 +27726 0.09124755859375 +27727 0.10888671875 +27728 0.125518798828125 +27729 0.15771484375 +27730 0.17828369140625 +27731 0.17108154296875 +27732 0.129974365234375 +27733 0.082427978515625 +27734 0.027679443359375 +27735 -0.065643310546875 +27736 -0.15936279296875 +27737 -0.21307373046875 +27738 -0.234649658203125 +27739 -0.2001953125 +27740 -0.119171142578125 +27741 -0.024749755859375 +27742 0.085784912109375 +27743 0.178131103515625 +27744 0.215576171875 +27745 0.211456298828125 +27746 0.17523193359375 +27747 0.128753662109375 +27748 0.1019287109375 +27749 0.0743408203125 +27750 0.04327392578125 +27751 0.038177490234375 +27752 0.076263427734375 +27753 0.14105224609375 +27754 0.186431884765625 +27755 0.188812255859375 +27756 0.1390380859375 +27757 0.041778564453125 +27758 -0.079437255859375 +27759 -0.219390869140625 +27760 -0.367828369140625 +27761 -0.494873046875 +27762 -0.556243896484375 +27763 -0.508697509765625 +27764 -0.3756103515625 +27765 -0.218902587890625 +27766 -0.063751220703125 +27767 0.091552734375 +27768 0.23602294921875 +27769 0.342987060546875 +27770 0.39520263671875 +27771 0.389373779296875 +27772 0.324249267578125 +27773 0.224090576171875 +27774 0.124267578125 +27775 0.037078857421875 +27776 -0.010101318359375 +27777 -0.019439697265625 +27778 -0.022796630859375 +27779 -0.001556396484375 +27780 0.056304931640625 +27781 0.106719970703125 +27782 0.096893310546875 +27783 0.042694091796875 +27784 -0.018035888671875 +27785 -0.07586669921875 +27786 -0.11944580078125 +27787 -0.15972900390625 +27788 -0.202606201171875 +27789 -0.24859619140625 +27790 -0.30517578125 +27791 -0.36212158203125 +27792 -0.39141845703125 +27793 -0.35528564453125 +27794 -0.249969482421875 +27795 -0.092864990234375 +27796 0.08905029296875 +27797 0.2352294921875 +27798 0.318817138671875 +27799 0.358642578125 +27800 0.347747802734375 +27801 0.28564453125 +27802 0.223175048828125 +27803 0.196746826171875 +27804 0.179840087890625 +27805 0.155548095703125 +27806 0.151214599609375 +27807 0.156951904296875 +27808 0.13177490234375 +27809 0.100799560546875 +27810 0.087127685546875 +27811 0.05487060546875 +27812 -0.009002685546875 +27813 -0.10400390625 +27814 -0.229400634765625 +27815 -0.35552978515625 +27816 -0.441925048828125 +27817 -0.473846435546875 +27818 -0.464813232421875 +27819 -0.419097900390625 +27820 -0.334320068359375 +27821 -0.227935791015625 +27822 -0.12347412109375 +27823 -0.02764892578125 +27824 0.077667236328125 +27825 0.2132568359375 +27826 0.38885498046875 +27827 0.582794189453125 +27828 0.734039306640625 +27829 0.800140380859375 +27830 0.7783203125 +27831 0.6651611328125 +27832 0.45965576171875 +27833 0.199188232421875 +27834 -0.050689697265625 +27835 -0.23297119140625 +27836 -0.33013916015625 +27837 -0.368408203125 +27838 -0.378936767578125 +27839 -0.376983642578125 +27840 -0.37969970703125 +27841 -0.391510009765625 +27842 -0.385345458984375 +27843 -0.3419189453125 +27844 -0.28289794921875 +27845 -0.251617431640625 +27846 -0.266143798828125 +27847 -0.273345947265625 +27848 -0.216796875 +27849 -0.128265380859375 +27850 -0.068145751953125 +27851 -0.0430908203125 +27852 -0.024444580078125 +27853 0.020721435546875 +27854 0.124481201171875 +27855 0.25787353515625 +27856 0.379119873046875 +27857 0.47991943359375 +27858 0.5281982421875 +27859 0.511138916015625 +27860 0.456207275390625 +27861 0.407470703125 +27862 0.383758544921875 +27863 0.35687255859375 +27864 0.31182861328125 +27865 0.250885009765625 +27866 0.1654052734375 +27867 0.035247802734375 +27868 -0.142059326171875 +27869 -0.33563232421875 +27870 -0.5345458984375 +27871 -0.72186279296875 +27872 -0.836669921875 +27873 -0.8326416015625 +27874 -0.7296142578125 +27875 -0.582550048828125 +27876 -0.440093994140625 +27877 -0.324310302734375 +27878 -0.20147705078125 +27879 -0.044647216796875 +27880 0.103973388671875 +27881 0.202392578125 +27882 0.264495849609375 +27883 0.338897705078125 +27884 0.443817138671875 +27885 0.545074462890625 +27886 0.6173095703125 +27887 0.6524658203125 +27888 0.66339111328125 +27889 0.6561279296875 +27890 0.606781005859375 +27891 0.501190185546875 +27892 0.352783203125 +27893 0.176544189453125 +27894 -0.034820556640625 +27895 -0.258209228515625 +27896 -0.44244384765625 +27897 -0.5753173828125 +27898 -0.65203857421875 +27899 -0.641632080078125 +27900 -0.562164306640625 +27901 -0.458038330078125 +27902 -0.350555419921875 +27903 -0.260528564453125 +27904 -0.192108154296875 +27905 -0.141937255859375 +27906 -0.1021728515625 +27907 -0.062896728515625 +27908 -0.011932373046875 +27909 0.062835693359375 +27910 0.148712158203125 +27911 0.241729736328125 +27912 0.34912109375 +27913 0.457305908203125 +27914 0.54388427734375 +27915 0.5728759765625 +27916 0.506591796875 +27917 0.351226806640625 +27918 0.146514892578125 +27919 -0.05523681640625 +27920 -0.21624755859375 +27921 -0.334930419921875 +27922 -0.402984619140625 +27923 -0.4412841796875 +27924 -0.49578857421875 +27925 -0.5601806640625 +27926 -0.600738525390625 +27927 -0.584228515625 +27928 -0.47930908203125 +27929 -0.27935791015625 +27930 -0.0089111328125 +27931 0.268798828125 +27932 0.482818603515625 +27933 0.60369873046875 +27934 0.650421142578125 +27935 0.66400146484375 +27936 0.6414794921875 +27937 0.572540283203125 +27938 0.498138427734375 +27939 0.439453125 +27940 0.375518798828125 +27941 0.274505615234375 +27942 0.1087646484375 +27943 -0.099395751953125 +27944 -0.3182373046875 +27945 -0.5489501953125 +27946 -0.7738037109375 +27947 -0.86383056640625 +27948 -0.870391845703125 +27949 -0.86895751953125 +27950 -0.861053466796875 +27951 -0.765869140625 +27952 -0.5301513671875 +27953 -0.214691162109375 +27954 0.137359619140625 +27955 0.474822998046875 +27956 0.76239013671875 +27957 0.867462158203125 +27958 0.870361328125 +27959 0.86480712890625 +27960 0.831817626953125 +27961 0.677581787109375 +27962 0.495880126953125 +27963 0.30767822265625 +27964 0.116180419921875 +27965 -0.110748291015625 +27966 -0.381805419921875 +27967 -0.6572265625 +27968 -0.857421875 +27969 -0.870391845703125 +27970 -0.870391845703125 +27971 -0.86444091796875 +27972 -0.85723876953125 +27973 -0.790008544921875 +27974 -0.62847900390625 +27975 -0.3956298828125 +27976 -0.126708984375 +27977 0.150115966796875 +27978 0.424041748046875 +27979 0.670623779296875 +27980 0.854522705078125 +27981 0.866485595703125 +27982 0.86920166015625 +27983 0.8653564453125 +27984 0.857147216796875 +27985 0.766845703125 +27986 0.628509521484375 +27987 0.462127685546875 +27988 0.297210693359375 +27989 0.14862060546875 +27990 -0.00537109375 +27991 -0.15753173828125 +27992 -0.31304931640625 +27993 -0.48876953125 +27994 -0.6416015625 +27995 -0.751373291015625 +27996 -0.84619140625 +27997 -0.861297607421875 +27998 -0.863250732421875 +27999 -0.856597900390625 +28000 -0.7498779296875 +28001 -0.624542236328125 +28002 -0.47808837890625 +28003 -0.253387451171875 +28004 0.003692626953125 +28005 0.2257080078125 +28006 0.427154541015625 +28007 0.643218994140625 +28008 0.855926513671875 +28009 0.870361328125 +28010 0.870361328125 +28011 0.862762451171875 +28012 0.79669189453125 +28013 0.595794677734375 +28014 0.362152099609375 +28015 0.1270751953125 +28016 -0.086944580078125 +28017 -0.2784423828125 +28018 -0.484832763671875 +28019 -0.729583740234375 +28020 -0.86688232421875 +28021 -0.870391845703125 +28022 -0.86859130859375 +28023 -0.86279296875 +28024 -0.817962646484375 +28025 -0.6116943359375 +28026 -0.3128662109375 +28027 0.039398193359375 +28028 0.422821044921875 +28029 0.805145263671875 +28030 0.870361328125 +28031 0.870361328125 +28032 0.860015869140625 +28033 0.727935791015625 +28034 0.48114013671875 +28035 0.2059326171875 +28036 -0.06103515625 +28037 -0.29913330078125 +28038 -0.516204833984375 +28039 -0.7252197265625 +28040 -0.85980224609375 +28041 -0.870391845703125 +28042 -0.870391845703125 +28043 -0.858062744140625 +28044 -0.673004150390625 +28045 -0.42694091796875 +28046 -0.2100830078125 +28047 -0.0362548828125 +28048 0.10943603515625 +28049 0.23516845703125 +28050 0.373687744140625 +28051 0.517791748046875 +28052 0.602783203125 +28053 0.635711669921875 +28054 0.655181884765625 +28055 0.65948486328125 +28056 0.651275634765625 +28057 0.61846923828125 +28058 0.53753662109375 +28059 0.404144287109375 +28060 0.22186279296875 +28061 0.003997802734375 +28062 -0.22100830078125 +28063 -0.42449951171875 +28064 -0.579833984375 +28065 -0.641876220703125 +28066 -0.6177978515625 +28067 -0.575531005859375 +28068 -0.526336669921875 +28069 -0.42645263671875 +28070 -0.2581787109375 +28071 -0.068695068359375 +28072 0.09222412109375 +28073 0.232147216796875 +28074 0.3509521484375 +28075 0.410064697265625 +28076 0.372955322265625 +28077 0.2554931640625 +28078 0.10711669921875 +28079 -0.052886962890625 +28080 -0.186279296875 +28081 -0.23291015625 +28082 -0.209442138671875 +28083 -0.174163818359375 +28084 -0.126739501953125 +28085 -0.048126220703125 +28086 0.0426025390625 +28087 0.10748291015625 +28088 0.1409912109375 +28089 0.19708251953125 +28090 0.273651123046875 +28091 0.31768798828125 +28092 0.341094970703125 +28093 0.368011474609375 +28094 0.37249755859375 +28095 0.30072021484375 +28096 0.1517333984375 +28097 -0.01470947265625 +28098 -0.1883544921875 +28099 -0.372711181640625 +28100 -0.51397705078125 +28101 -0.57177734375 +28102 -0.53948974609375 +28103 -0.43511962890625 +28104 -0.2962646484375 +28105 -0.161102294921875 +28106 -0.0435791015625 +28107 0.060394287109375 +28108 0.13665771484375 +28109 0.170135498046875 +28110 0.16552734375 +28111 0.15728759765625 +28112 0.150787353515625 +28113 0.12200927734375 +28114 0.080108642578125 +28115 0.05126953125 +28116 0.062896728515625 +28117 0.09271240234375 +28118 0.092987060546875 +28119 0.07855224609375 +28120 0.06427001953125 +28121 0.0347900390625 +28122 -0.01171875 +28123 -0.056060791015625 +28124 -0.055511474609375 +28125 -0.010467529296875 +28126 0.02508544921875 +28127 0.025665283203125 +28128 0.017333984375 +28129 0.00189208984375 +28130 -0.03173828125 +28131 -0.071502685546875 +28132 -0.13543701171875 +28133 -0.219970703125 +28134 -0.300506591796875 +28135 -0.376312255859375 +28136 -0.416107177734375 +28137 -0.371124267578125 +28138 -0.242279052734375 +28139 -0.069732666015625 +28140 0.125640869140625 +28141 0.31268310546875 +28142 0.45501708984375 +28143 0.554779052734375 +28144 0.61065673828125 +28145 0.610931396484375 +28146 0.531463623046875 +28147 0.3883056640625 +28148 0.23468017578125 +28149 0.095245361328125 +28150 -0.00396728515625 +28151 -0.04852294921875 +28152 -0.055145263671875 +28153 -0.0758056640625 +28154 -0.138702392578125 +28155 -0.209197998046875 +28156 -0.289031982421875 +28157 -0.37884521484375 +28158 -0.456329345703125 +28159 -0.51641845703125 +28160 -0.519287109375 +28161 -0.458251953125 +28162 -0.384796142578125 +28163 -0.323699951171875 +28164 -0.269287109375 +28165 -0.1951904296875 +28166 -0.100006103515625 +28167 -0.01055908203125 +28168 0.1033935546875 +28169 0.24908447265625 +28170 0.373199462890625 +28171 0.45806884765625 +28172 0.511474609375 +28173 0.565399169921875 +28174 0.61138916015625 +28175 0.5897216796875 +28176 0.4906005859375 +28177 0.33148193359375 +28178 0.147796630859375 +28179 -0.01873779296875 +28180 -0.140289306640625 +28181 -0.191986083984375 +28182 -0.184295654296875 +28183 -0.161834716796875 +28184 -0.166595458984375 +28185 -0.19390869140625 +28186 -0.22442626953125 +28187 -0.279754638671875 +28188 -0.3389892578125 +28189 -0.3543701171875 +28190 -0.348175048828125 +28191 -0.32598876953125 +28192 -0.2581787109375 +28193 -0.139801025390625 +28194 0.014617919921875 +28195 0.144378662109375 +28196 0.221038818359375 +28197 0.27069091796875 +28198 0.294036865234375 +28199 0.311767578125 +28200 0.339141845703125 +28201 0.360260009765625 +28202 0.360504150390625 +28203 0.308380126953125 +28204 0.18170166015625 +28205 0.0047607421875 +28206 -0.17559814453125 +28207 -0.3143310546875 +28208 -0.36785888671875 +28209 -0.36248779296875 +28210 -0.343536376953125 +28211 -0.3018798828125 +28212 -0.231414794921875 +28213 -0.117645263671875 +28214 0.007049560546875 +28215 0.087982177734375 +28216 0.13946533203125 +28217 0.17425537109375 +28218 0.188201904296875 +28219 0.171234130859375 +28220 0.118438720703125 +28221 0.05706787109375 +28222 -0.010711669921875 +28223 -0.0914306640625 +28224 -0.162322998046875 +28225 -0.194549560546875 +28226 -0.1492919921875 +28227 -0.02166748046875 +28228 0.124053955078125 +28229 0.211151123046875 +28230 0.240447998046875 +28231 0.242218017578125 +28232 0.2257080078125 +28233 0.194366455078125 +28234 0.115509033203125 +28235 0.0128173828125 +28236 -0.053802490234375 +28237 -0.110626220703125 +28238 -0.199493408203125 +28239 -0.29437255859375 +28240 -0.33221435546875 +28241 -0.27972412109375 +28242 -0.185333251953125 +28243 -0.128204345703125 +28244 -0.115692138671875 +28245 -0.116455078125 +28246 -0.105926513671875 +28247 -0.053955078125 +28248 0.048797607421875 +28249 0.157318115234375 +28250 0.212005615234375 +28251 0.218475341796875 +28252 0.23724365234375 +28253 0.30535888671875 +28254 0.38128662109375 +28255 0.404449462890625 +28256 0.3944091796875 +28257 0.3885498046875 +28258 0.362640380859375 +28259 0.27362060546875 +28260 0.11712646484375 +28261 -0.054901123046875 +28262 -0.19085693359375 +28263 -0.28570556640625 +28264 -0.339263916015625 +28265 -0.3775634765625 +28266 -0.445709228515625 +28267 -0.535064697265625 +28268 -0.629058837890625 +28269 -0.697601318359375 +28270 -0.70391845703125 +28271 -0.6424560546875 +28272 -0.491241455078125 +28273 -0.265716552734375 +28274 -0.023712158203125 +28275 0.201751708984375 +28276 0.375823974609375 +28277 0.485076904296875 +28278 0.56884765625 +28279 0.634765625 +28280 0.63763427734375 +28281 0.5660400390625 +28282 0.4720458984375 +28283 0.40692138671875 +28284 0.3778076171875 +28285 0.376953125 +28286 0.371978759765625 +28287 0.313140869140625 +28288 0.184417724609375 +28289 0.011199951171875 +28290 -0.171051025390625 +28291 -0.33740234375 +28292 -0.47198486328125 +28293 -0.560394287109375 +28294 -0.58056640625 +28295 -0.54754638671875 +28296 -0.508575439453125 +28297 -0.459503173828125 +28298 -0.394378662109375 +28299 -0.35260009765625 +28300 -0.31170654296875 +28301 -0.197418212890625 +28302 -0.007965087890625 +28303 0.207489013671875 +28304 0.409210205078125 +28305 0.57208251953125 +28306 0.66595458984375 +28307 0.65875244140625 +28308 0.56744384765625 +28309 0.431396484375 +28310 0.29443359375 +28311 0.182464599609375 +28312 0.06365966796875 +28313 -0.075958251953125 +28314 -0.189422607421875 +28315 -0.271942138671875 +28316 -0.342529296875 +28317 -0.364166259765625 +28318 -0.327239990234375 +28319 -0.2769775390625 +28320 -0.253692626953125 +28321 -0.24365234375 +28322 -0.1983642578125 +28323 -0.116241455078125 +28324 -0.036834716796875 +28325 0.034881591796875 +28326 0.09124755859375 +28327 0.10888671875 +28328 0.125518798828125 +28329 0.15771484375 +28330 0.17828369140625 +28331 0.17108154296875 +28332 0.129974365234375 +28333 0.082427978515625 +28334 0.027679443359375 +28335 -0.065643310546875 +28336 -0.15936279296875 +28337 -0.21307373046875 +28338 -0.234649658203125 +28339 -0.2001953125 +28340 -0.119171142578125 +28341 -0.024749755859375 +28342 0.085784912109375 +28343 0.178131103515625 +28344 0.215576171875 +28345 0.211456298828125 +28346 0.17523193359375 +28347 0.128753662109375 +28348 0.1019287109375 +28349 0.0743408203125 +28350 0.04327392578125 +28351 0.038177490234375 +28352 0.076263427734375 +28353 0.14105224609375 +28354 0.186431884765625 +28355 0.188812255859375 +28356 0.1390380859375 +28357 0.041778564453125 +28358 -0.079437255859375 +28359 -0.219390869140625 +28360 -0.367828369140625 +28361 -0.494873046875 +28362 -0.556243896484375 +28363 -0.508697509765625 +28364 -0.3756103515625 +28365 -0.218902587890625 +28366 -0.063751220703125 +28367 0.091552734375 +28368 0.23602294921875 +28369 0.342987060546875 +28370 0.39520263671875 +28371 0.389373779296875 +28372 0.324249267578125 +28373 0.224090576171875 +28374 0.124267578125 +28375 0.037078857421875 +28376 -0.010101318359375 +28377 -0.019439697265625 +28378 -0.022796630859375 +28379 -0.001556396484375 +28380 0.056304931640625 +28381 0.106719970703125 +28382 0.096893310546875 +28383 0.042694091796875 +28384 -0.018035888671875 +28385 -0.07586669921875 +28386 -0.11944580078125 +28387 -0.15972900390625 +28388 -0.202606201171875 +28389 -0.24859619140625 +28390 -0.30517578125 +28391 -0.36212158203125 +28392 -0.39141845703125 +28393 -0.35528564453125 +28394 -0.249969482421875 +28395 -0.092864990234375 +28396 0.08905029296875 +28397 0.2352294921875 +28398 0.318817138671875 +28399 0.358642578125 +28400 0.347747802734375 +28401 0.28564453125 +28402 0.223175048828125 +28403 0.196746826171875 +28404 0.179840087890625 +28405 0.155548095703125 +28406 0.151214599609375 +28407 0.156951904296875 +28408 0.13177490234375 +28409 0.100799560546875 +28410 0.087127685546875 +28411 0.05487060546875 +28412 -0.009002685546875 +28413 -0.10400390625 +28414 -0.229400634765625 +28415 -0.35552978515625 +28416 -0.441925048828125 +28417 -0.473846435546875 +28418 -0.464813232421875 +28419 -0.419097900390625 +28420 -0.334320068359375 +28421 -0.227935791015625 +28422 -0.12347412109375 +28423 -0.02764892578125 +28424 0.077667236328125 +28425 0.2132568359375 +28426 0.38885498046875 +28427 0.582794189453125 +28428 0.734039306640625 +28429 0.800140380859375 +28430 0.7783203125 +28431 0.6651611328125 +28432 0.45965576171875 +28433 0.199188232421875 +28434 -0.050689697265625 +28435 -0.23297119140625 +28436 -0.33013916015625 +28437 -0.368408203125 +28438 -0.378936767578125 +28439 -0.376983642578125 +28440 -0.37969970703125 +28441 -0.391510009765625 +28442 -0.385345458984375 +28443 -0.3419189453125 +28444 -0.28289794921875 +28445 -0.251617431640625 +28446 -0.266143798828125 +28447 -0.273345947265625 +28448 -0.216796875 +28449 -0.128265380859375 +28450 -0.068145751953125 +28451 -0.0430908203125 +28452 -0.024444580078125 +28453 0.020721435546875 +28454 0.124481201171875 +28455 0.25787353515625 +28456 0.379119873046875 +28457 0.47991943359375 +28458 0.5281982421875 +28459 0.511138916015625 +28460 0.456207275390625 +28461 0.407470703125 +28462 0.383758544921875 +28463 0.35687255859375 +28464 0.31182861328125 +28465 0.250885009765625 +28466 0.1654052734375 +28467 0.035247802734375 +28468 -0.142059326171875 +28469 -0.33563232421875 +28470 -0.5345458984375 +28471 -0.72186279296875 +28472 -0.836669921875 +28473 -0.8326416015625 +28474 -0.7296142578125 +28475 -0.582550048828125 +28476 -0.440093994140625 +28477 -0.324310302734375 +28478 -0.20147705078125 +28479 -0.044647216796875 +28480 0.103973388671875 +28481 0.202392578125 +28482 0.264495849609375 +28483 0.338897705078125 +28484 0.443817138671875 +28485 0.545074462890625 +28486 0.6173095703125 +28487 0.6524658203125 +28488 0.66339111328125 +28489 0.6561279296875 +28490 0.606781005859375 +28491 0.501190185546875 +28492 0.352783203125 +28493 0.176544189453125 +28494 -0.034820556640625 +28495 -0.258209228515625 +28496 -0.44244384765625 +28497 -0.5753173828125 +28498 -0.65203857421875 +28499 -0.641632080078125 +28500 -0.562164306640625 +28501 -0.458038330078125 +28502 -0.350555419921875 +28503 -0.260528564453125 +28504 -0.192108154296875 +28505 -0.141937255859375 +28506 -0.1021728515625 +28507 -0.062896728515625 +28508 -0.011932373046875 +28509 0.062835693359375 +28510 0.148712158203125 +28511 0.241729736328125 +28512 0.34912109375 +28513 0.457305908203125 +28514 0.54388427734375 +28515 0.5728759765625 +28516 0.506591796875 +28517 0.351226806640625 +28518 0.146514892578125 +28519 -0.05523681640625 +28520 -0.21624755859375 +28521 -0.334930419921875 +28522 -0.402984619140625 +28523 -0.4412841796875 +28524 -0.49578857421875 +28525 -0.5601806640625 +28526 -0.600738525390625 +28527 -0.584228515625 +28528 -0.47930908203125 +28529 -0.27935791015625 +28530 -0.0089111328125 +28531 0.268798828125 +28532 0.482818603515625 +28533 0.60369873046875 +28534 0.650421142578125 +28535 0.66400146484375 +28536 0.6414794921875 +28537 0.572540283203125 +28538 0.498138427734375 +28539 0.439453125 +28540 0.375518798828125 +28541 0.274505615234375 +28542 0.1087646484375 +28543 -0.099395751953125 +28544 -0.3182373046875 +28545 -0.5489501953125 +28546 -0.7738037109375 +28547 -0.86383056640625 +28548 -0.870391845703125 +28549 -0.86895751953125 +28550 -0.861053466796875 +28551 -0.765869140625 +28552 -0.5301513671875 +28553 -0.214691162109375 +28554 0.137359619140625 +28555 0.474822998046875 +28556 0.76239013671875 +28557 0.867462158203125 +28558 0.870361328125 +28559 0.86480712890625 +28560 0.831817626953125 +28561 0.677581787109375 +28562 0.495880126953125 +28563 0.30767822265625 +28564 0.116180419921875 +28565 -0.110748291015625 +28566 -0.381805419921875 +28567 -0.6572265625 +28568 -0.857421875 +28569 -0.870391845703125 +28570 -0.870391845703125 +28571 -0.86444091796875 +28572 -0.85723876953125 +28573 -0.790008544921875 +28574 -0.62847900390625 +28575 -0.3956298828125 +28576 -0.126708984375 +28577 0.150115966796875 +28578 0.424041748046875 +28579 0.670623779296875 +28580 0.854522705078125 +28581 0.866485595703125 +28582 0.86920166015625 +28583 0.8653564453125 +28584 0.857147216796875 +28585 0.766845703125 +28586 0.628509521484375 +28587 0.462127685546875 +28588 0.297210693359375 +28589 0.14862060546875 +28590 -0.00537109375 +28591 -0.15753173828125 +28592 -0.31304931640625 +28593 -0.48876953125 +28594 -0.6416015625 +28595 -0.751373291015625 +28596 -0.84619140625 +28597 -0.861297607421875 +28598 -0.863250732421875 +28599 -0.856597900390625 +28600 -0.7498779296875 +28601 -0.624542236328125 +28602 -0.47808837890625 +28603 -0.253387451171875 +28604 0.003692626953125 +28605 0.2257080078125 +28606 0.427154541015625 +28607 0.643218994140625 +28608 0.855926513671875 +28609 0.870361328125 +28610 0.870361328125 +28611 0.862762451171875 +28612 0.79669189453125 +28613 0.595794677734375 +28614 0.362152099609375 +28615 0.1270751953125 +28616 -0.086944580078125 +28617 -0.2784423828125 +28618 -0.484832763671875 +28619 -0.729583740234375 +28620 -0.86688232421875 +28621 -0.870391845703125 +28622 -0.86859130859375 +28623 -0.86279296875 +28624 -0.817962646484375 +28625 -0.6116943359375 +28626 -0.3128662109375 +28627 0.039398193359375 +28628 0.422821044921875 +28629 0.805145263671875 +28630 0.870361328125 +28631 0.870361328125 +28632 0.860015869140625 +28633 0.727935791015625 +28634 0.48114013671875 +28635 0.2059326171875 +28636 -0.06103515625 +28637 -0.29913330078125 +28638 -0.516204833984375 +28639 -0.7252197265625 +28640 -0.85980224609375 +28641 -0.870391845703125 +28642 -0.870391845703125 +28643 -0.858062744140625 +28644 -0.673004150390625 +28645 -0.42694091796875 +28646 -0.2100830078125 +28647 -0.0362548828125 +28648 0.10943603515625 +28649 0.23516845703125 +28650 0.373687744140625 +28651 0.517791748046875 +28652 0.602783203125 +28653 0.635711669921875 +28654 0.655181884765625 +28655 0.65948486328125 +28656 0.651275634765625 +28657 0.61846923828125 +28658 0.53753662109375 +28659 0.404144287109375 +28660 0.22186279296875 +28661 0.003997802734375 +28662 -0.22100830078125 +28663 -0.42449951171875 +28664 -0.579833984375 +28665 -0.641876220703125 +28666 -0.6177978515625 +28667 -0.575531005859375 +28668 -0.526336669921875 +28669 -0.42645263671875 +28670 -0.2581787109375 +28671 -0.068695068359375 +28672 0.09222412109375 +28673 0.232147216796875 +28674 0.3509521484375 +28675 0.410064697265625 +28676 0.372955322265625 +28677 0.2554931640625 +28678 0.10711669921875 +28679 -0.052886962890625 +28680 -0.186279296875 +28681 -0.23291015625 +28682 -0.209442138671875 +28683 -0.174163818359375 +28684 -0.126739501953125 +28685 -0.048126220703125 +28686 0.0426025390625 +28687 0.10748291015625 +28688 0.1409912109375 +28689 0.19708251953125 +28690 0.273651123046875 +28691 0.31768798828125 +28692 0.341094970703125 +28693 0.368011474609375 +28694 0.37249755859375 +28695 0.30072021484375 +28696 0.1517333984375 +28697 -0.01470947265625 +28698 -0.1883544921875 +28699 -0.372711181640625 +28700 -0.51397705078125 +28701 -0.57177734375 +28702 -0.53948974609375 +28703 -0.43511962890625 +28704 -0.2962646484375 +28705 -0.161102294921875 +28706 -0.0435791015625 +28707 0.060394287109375 +28708 0.13665771484375 +28709 0.170135498046875 +28710 0.16552734375 +28711 0.15728759765625 +28712 0.150787353515625 +28713 0.12200927734375 +28714 0.080108642578125 +28715 0.05126953125 +28716 0.062896728515625 +28717 0.09271240234375 +28718 0.092987060546875 +28719 0.07855224609375 +28720 0.06427001953125 +28721 0.0347900390625 +28722 -0.01171875 +28723 -0.056060791015625 +28724 -0.055511474609375 +28725 -0.010467529296875 +28726 0.02508544921875 +28727 0.025665283203125 +28728 0.017333984375 +28729 0.00189208984375 +28730 -0.03173828125 +28731 -0.071502685546875 +28732 -0.13543701171875 +28733 -0.219970703125 +28734 -0.300506591796875 +28735 -0.376312255859375 +28736 -0.416107177734375 +28737 -0.371124267578125 +28738 -0.242279052734375 +28739 -0.069732666015625 +28740 0.125640869140625 +28741 0.31268310546875 +28742 0.45501708984375 +28743 0.554779052734375 +28744 0.61065673828125 +28745 0.610931396484375 +28746 0.531463623046875 +28747 0.3883056640625 +28748 0.23468017578125 +28749 0.095245361328125 +28750 -0.00396728515625 +28751 -0.04852294921875 +28752 -0.055145263671875 +28753 -0.0758056640625 +28754 -0.138702392578125 +28755 -0.209197998046875 +28756 -0.289031982421875 +28757 -0.37884521484375 +28758 -0.456329345703125 +28759 -0.51641845703125 +28760 -0.519287109375 +28761 -0.458251953125 +28762 -0.384796142578125 +28763 -0.323699951171875 +28764 -0.269287109375 +28765 -0.1951904296875 +28766 -0.100006103515625 +28767 -0.01055908203125 +28768 0.1033935546875 +28769 0.24908447265625 +28770 0.373199462890625 +28771 0.45806884765625 +28772 0.511474609375 +28773 0.565399169921875 +28774 0.61138916015625 +28775 0.5897216796875 +28776 0.4906005859375 +28777 0.33148193359375 +28778 0.147796630859375 +28779 -0.01873779296875 +28780 -0.140289306640625 +28781 -0.191986083984375 +28782 -0.184295654296875 +28783 -0.161834716796875 +28784 -0.166595458984375 +28785 -0.19390869140625 +28786 -0.22442626953125 +28787 -0.279754638671875 +28788 -0.3389892578125 +28789 -0.3543701171875 +28790 -0.348175048828125 +28791 -0.32598876953125 +28792 -0.2581787109375 +28793 -0.139801025390625 +28794 0.014617919921875 +28795 0.144378662109375 +28796 0.221038818359375 +28797 0.27069091796875 +28798 0.294036865234375 +28799 0.311767578125 +28800 0.339141845703125 +28801 0.360260009765625 +28802 0.360504150390625 +28803 0.308380126953125 +28804 0.18170166015625 +28805 0.0047607421875 +28806 -0.17559814453125 +28807 -0.3143310546875 +28808 -0.36785888671875 +28809 -0.36248779296875 +28810 -0.343536376953125 +28811 -0.3018798828125 +28812 -0.231414794921875 +28813 -0.117645263671875 +28814 0.007049560546875 +28815 0.087982177734375 +28816 0.13946533203125 +28817 0.17425537109375 +28818 0.188201904296875 +28819 0.171234130859375 +28820 0.118438720703125 +28821 0.05706787109375 +28822 -0.010711669921875 +28823 -0.0914306640625 +28824 -0.162322998046875 +28825 -0.194549560546875 +28826 -0.1492919921875 +28827 -0.02166748046875 +28828 0.124053955078125 +28829 0.211151123046875 +28830 0.240447998046875 +28831 0.242218017578125 +28832 0.2257080078125 +28833 0.194366455078125 +28834 0.115509033203125 +28835 0.0128173828125 +28836 -0.053802490234375 +28837 -0.110626220703125 +28838 -0.199493408203125 +28839 -0.29437255859375 +28840 -0.33221435546875 +28841 -0.27972412109375 +28842 -0.185333251953125 +28843 -0.128204345703125 +28844 -0.115692138671875 +28845 -0.116455078125 +28846 -0.105926513671875 +28847 -0.053955078125 +28848 0.048797607421875 +28849 0.157318115234375 +28850 0.212005615234375 +28851 0.218475341796875 +28852 0.23724365234375 +28853 0.30535888671875 +28854 0.38128662109375 +28855 0.404449462890625 +28856 0.3944091796875 +28857 0.3885498046875 +28858 0.362640380859375 +28859 0.27362060546875 +28860 0.11712646484375 +28861 -0.054901123046875 +28862 -0.19085693359375 +28863 -0.28570556640625 +28864 -0.339263916015625 +28865 -0.3775634765625 +28866 -0.445709228515625 +28867 -0.535064697265625 +28868 -0.629058837890625 +28869 -0.697601318359375 +28870 -0.70391845703125 +28871 -0.6424560546875 +28872 -0.491241455078125 +28873 -0.265716552734375 +28874 -0.023712158203125 +28875 0.201751708984375 +28876 0.375823974609375 +28877 0.485076904296875 +28878 0.56884765625 +28879 0.634765625 +28880 0.63763427734375 +28881 0.5660400390625 +28882 0.4720458984375 +28883 0.40692138671875 +28884 0.3778076171875 +28885 0.376953125 +28886 0.371978759765625 +28887 0.313140869140625 +28888 0.184417724609375 +28889 0.011199951171875 +28890 -0.171051025390625 +28891 -0.33740234375 +28892 -0.47198486328125 +28893 -0.560394287109375 +28894 -0.58056640625 +28895 -0.54754638671875 +28896 -0.508575439453125 +28897 -0.459503173828125 +28898 -0.394378662109375 +28899 -0.35260009765625 +28900 -0.31170654296875 +28901 -0.197418212890625 +28902 -0.007965087890625 +28903 0.207489013671875 +28904 0.409210205078125 +28905 0.57208251953125 +28906 0.66595458984375 +28907 0.65875244140625 +28908 0.56744384765625 +28909 0.431396484375 +28910 0.29443359375 +28911 0.182464599609375 +28912 0.06365966796875 +28913 -0.075958251953125 +28914 -0.189422607421875 +28915 -0.271942138671875 +28916 -0.342529296875 +28917 -0.364166259765625 +28918 -0.327239990234375 +28919 -0.2769775390625 +28920 -0.253692626953125 +28921 -0.24365234375 +28922 -0.1983642578125 +28923 -0.116241455078125 +28924 -0.036834716796875 +28925 0.034881591796875 +28926 0.09124755859375 +28927 0.10888671875 +28928 0.125518798828125 +28929 0.15771484375 +28930 0.17828369140625 +28931 0.17108154296875 +28932 0.129974365234375 +28933 0.082427978515625 +28934 0.027679443359375 +28935 -0.065643310546875 +28936 -0.15936279296875 +28937 -0.21307373046875 +28938 -0.234649658203125 +28939 -0.2001953125 +28940 -0.119171142578125 +28941 -0.024749755859375 +28942 0.085784912109375 +28943 0.178131103515625 +28944 0.215576171875 +28945 0.211456298828125 +28946 0.17523193359375 +28947 0.128753662109375 +28948 0.1019287109375 +28949 0.0743408203125 +28950 0.04327392578125 +28951 0.038177490234375 +28952 0.076263427734375 +28953 0.14105224609375 +28954 0.186431884765625 +28955 0.188812255859375 +28956 0.1390380859375 +28957 0.041778564453125 +28958 -0.079437255859375 +28959 -0.219390869140625 +28960 -0.367828369140625 +28961 -0.494873046875 +28962 -0.556243896484375 +28963 -0.508697509765625 +28964 -0.3756103515625 +28965 -0.218902587890625 +28966 -0.063751220703125 +28967 0.091552734375 +28968 0.23602294921875 +28969 0.342987060546875 +28970 0.39520263671875 +28971 0.389373779296875 +28972 0.324249267578125 +28973 0.224090576171875 +28974 0.124267578125 +28975 0.037078857421875 +28976 -0.010101318359375 +28977 -0.019439697265625 +28978 -0.022796630859375 +28979 -0.001556396484375 +28980 0.056304931640625 +28981 0.106719970703125 +28982 0.096893310546875 +28983 0.042694091796875 +28984 -0.018035888671875 +28985 -0.07586669921875 +28986 -0.11944580078125 +28987 -0.15972900390625 +28988 -0.202606201171875 +28989 -0.24859619140625 +28990 -0.30517578125 +28991 -0.36212158203125 +28992 -0.39141845703125 +28993 -0.35528564453125 +28994 -0.249969482421875 +28995 -0.092864990234375 +28996 0.08905029296875 +28997 0.2352294921875 +28998 0.318817138671875 +28999 0.358642578125 +29000 0.347747802734375 +29001 0.28564453125 +29002 0.223175048828125 +29003 0.196746826171875 +29004 0.179840087890625 +29005 0.155548095703125 +29006 0.151214599609375 +29007 0.156951904296875 +29008 0.13177490234375 +29009 0.100799560546875 +29010 0.087127685546875 +29011 0.05487060546875 +29012 -0.009002685546875 +29013 -0.10400390625 +29014 -0.229400634765625 +29015 -0.35552978515625 +29016 -0.441925048828125 +29017 -0.473846435546875 +29018 -0.464813232421875 +29019 -0.419097900390625 +29020 -0.334320068359375 +29021 -0.227935791015625 +29022 -0.12347412109375 +29023 -0.02764892578125 +29024 0.077667236328125 +29025 0.2132568359375 +29026 0.38885498046875 +29027 0.582794189453125 +29028 0.734039306640625 +29029 0.800140380859375 +29030 0.7783203125 +29031 0.6651611328125 +29032 0.45965576171875 +29033 0.199188232421875 +29034 -0.050689697265625 +29035 -0.23297119140625 +29036 -0.33013916015625 +29037 -0.368408203125 +29038 -0.378936767578125 +29039 -0.376983642578125 +29040 -0.37969970703125 +29041 -0.391510009765625 +29042 -0.385345458984375 +29043 -0.3419189453125 +29044 -0.28289794921875 +29045 -0.251617431640625 +29046 -0.266143798828125 +29047 -0.273345947265625 +29048 -0.216796875 +29049 -0.128265380859375 +29050 -0.068145751953125 +29051 -0.0430908203125 +29052 -0.024444580078125 +29053 0.020721435546875 +29054 0.124481201171875 +29055 0.25787353515625 +29056 0.379119873046875 +29057 0.47991943359375 +29058 0.5281982421875 +29059 0.511138916015625 +29060 0.456207275390625 +29061 0.407470703125 +29062 0.383758544921875 +29063 0.35687255859375 +29064 0.31182861328125 +29065 0.250885009765625 +29066 0.1654052734375 +29067 0.035247802734375 +29068 -0.142059326171875 +29069 -0.33563232421875 +29070 -0.5345458984375 +29071 -0.72186279296875 +29072 -0.836669921875 +29073 -0.8326416015625 +29074 -0.7296142578125 +29075 -0.582550048828125 +29076 -0.440093994140625 +29077 -0.324310302734375 +29078 -0.20147705078125 +29079 -0.044647216796875 +29080 0.103973388671875 +29081 0.202392578125 +29082 0.264495849609375 +29083 0.338897705078125 +29084 0.443817138671875 +29085 0.545074462890625 +29086 0.6173095703125 +29087 0.6524658203125 +29088 0.66339111328125 +29089 0.6561279296875 +29090 0.606781005859375 +29091 0.501190185546875 +29092 0.352783203125 +29093 0.176544189453125 +29094 -0.034820556640625 +29095 -0.258209228515625 +29096 -0.44244384765625 +29097 -0.5753173828125 +29098 -0.65203857421875 +29099 -0.641632080078125 +29100 -0.562164306640625 +29101 -0.458038330078125 +29102 -0.350555419921875 +29103 -0.260528564453125 +29104 -0.192108154296875 +29105 -0.141937255859375 +29106 -0.1021728515625 +29107 -0.062896728515625 +29108 -0.011932373046875 +29109 0.062835693359375 +29110 0.148712158203125 +29111 0.241729736328125 +29112 0.34912109375 +29113 0.457305908203125 +29114 0.54388427734375 +29115 0.5728759765625 +29116 0.506591796875 +29117 0.351226806640625 +29118 0.146514892578125 +29119 -0.05523681640625 +29120 -0.21624755859375 +29121 -0.334930419921875 +29122 -0.402984619140625 +29123 -0.4412841796875 +29124 -0.49578857421875 +29125 -0.5601806640625 +29126 -0.600738525390625 +29127 -0.584228515625 +29128 -0.47930908203125 +29129 -0.27935791015625 +29130 -0.0089111328125 +29131 0.268798828125 +29132 0.482818603515625 +29133 0.60369873046875 +29134 0.650421142578125 +29135 0.66400146484375 +29136 0.6414794921875 +29137 0.572540283203125 +29138 0.498138427734375 +29139 0.439453125 +29140 0.375518798828125 +29141 0.274505615234375 +29142 0.1087646484375 +29143 -0.099395751953125 +29144 -0.3182373046875 +29145 -0.5489501953125 +29146 -0.7738037109375 +29147 -0.86383056640625 +29148 -0.870391845703125 +29149 -0.86895751953125 +29150 -0.861053466796875 +29151 -0.765869140625 +29152 -0.5301513671875 +29153 -0.214691162109375 +29154 0.137359619140625 +29155 0.474822998046875 +29156 0.76239013671875 +29157 0.867462158203125 +29158 0.870361328125 +29159 0.86480712890625 +29160 0.831817626953125 +29161 0.677581787109375 +29162 0.495880126953125 +29163 0.30767822265625 +29164 0.116180419921875 +29165 -0.110748291015625 +29166 -0.381805419921875 +29167 -0.6572265625 +29168 -0.857421875 +29169 -0.870391845703125 +29170 -0.870391845703125 +29171 -0.86444091796875 +29172 -0.85723876953125 +29173 -0.790008544921875 +29174 -0.62847900390625 +29175 -0.3956298828125 +29176 -0.126708984375 +29177 0.150115966796875 +29178 0.424041748046875 +29179 0.670623779296875 +29180 0.854522705078125 +29181 0.866485595703125 +29182 0.86920166015625 +29183 0.8653564453125 +29184 0.857147216796875 +29185 0.766845703125 +29186 0.628509521484375 +29187 0.462127685546875 +29188 0.297210693359375 +29189 0.14862060546875 +29190 -0.00537109375 +29191 -0.15753173828125 +29192 -0.31304931640625 +29193 -0.48876953125 +29194 -0.6416015625 +29195 -0.751373291015625 +29196 -0.84619140625 +29197 -0.861297607421875 +29198 -0.863250732421875 +29199 -0.856597900390625 +29200 -0.7498779296875 +29201 -0.624542236328125 +29202 -0.47808837890625 +29203 -0.253387451171875 +29204 0.003692626953125 +29205 0.2257080078125 +29206 0.427154541015625 +29207 0.643218994140625 +29208 0.855926513671875 +29209 0.870361328125 +29210 0.870361328125 +29211 0.862762451171875 +29212 0.79669189453125 +29213 0.595794677734375 +29214 0.362152099609375 +29215 0.1270751953125 +29216 -0.086944580078125 +29217 -0.2784423828125 +29218 -0.484832763671875 +29219 -0.729583740234375 +29220 -0.86688232421875 +29221 -0.870391845703125 +29222 -0.86859130859375 +29223 -0.86279296875 +29224 -0.817962646484375 +29225 -0.6116943359375 +29226 -0.3128662109375 +29227 0.039398193359375 +29228 0.422821044921875 +29229 0.805145263671875 +29230 0.870361328125 +29231 0.870361328125 +29232 0.860015869140625 +29233 0.727935791015625 +29234 0.48114013671875 +29235 0.2059326171875 +29236 -0.06103515625 +29237 -0.29913330078125 +29238 -0.516204833984375 +29239 -0.7252197265625 +29240 -0.85980224609375 +29241 -0.870391845703125 +29242 -0.870391845703125 +29243 -0.858062744140625 +29244 -0.673004150390625 +29245 -0.42694091796875 +29246 -0.2100830078125 +29247 -0.0362548828125 +29248 0.10943603515625 +29249 0.23516845703125 +29250 0.373687744140625 +29251 0.517791748046875 +29252 0.602783203125 +29253 0.635711669921875 +29254 0.655181884765625 +29255 0.65948486328125 +29256 0.651275634765625 +29257 0.61846923828125 +29258 0.53753662109375 +29259 0.404144287109375 +29260 0.22186279296875 +29261 0.003997802734375 +29262 -0.22100830078125 +29263 -0.42449951171875 +29264 -0.579833984375 +29265 -0.641876220703125 +29266 -0.6177978515625 +29267 -0.575531005859375 +29268 -0.526336669921875 +29269 -0.42645263671875 +29270 -0.2581787109375 +29271 -0.068695068359375 +29272 0.09222412109375 +29273 0.232147216796875 +29274 0.3509521484375 +29275 0.410064697265625 +29276 0.372955322265625 +29277 0.2554931640625 +29278 0.10711669921875 +29279 -0.052886962890625 +29280 -0.186279296875 +29281 -0.23291015625 +29282 -0.209442138671875 +29283 -0.174163818359375 +29284 -0.126739501953125 +29285 -0.048126220703125 +29286 0.0426025390625 +29287 0.10748291015625 +29288 0.1409912109375 +29289 0.19708251953125 +29290 0.273651123046875 +29291 0.31768798828125 +29292 0.341094970703125 +29293 0.368011474609375 +29294 0.37249755859375 +29295 0.30072021484375 +29296 0.1517333984375 +29297 -0.01470947265625 +29298 -0.1883544921875 +29299 -0.372711181640625 +29300 -0.51397705078125 +29301 -0.57177734375 +29302 -0.53948974609375 +29303 -0.43511962890625 +29304 -0.2962646484375 +29305 -0.161102294921875 +29306 -0.0435791015625 +29307 0.060394287109375 +29308 0.13665771484375 +29309 0.170135498046875 +29310 0.16552734375 +29311 0.15728759765625 +29312 0.150787353515625 +29313 0.12200927734375 +29314 0.080108642578125 +29315 0.05126953125 +29316 0.062896728515625 +29317 0.09271240234375 +29318 0.092987060546875 +29319 0.07855224609375 +29320 0.06427001953125 +29321 0.0347900390625 +29322 -0.01171875 +29323 -0.056060791015625 +29324 -0.055511474609375 +29325 -0.010467529296875 +29326 0.02508544921875 +29327 0.025665283203125 +29328 0.017333984375 +29329 0.00189208984375 +29330 -0.03173828125 +29331 -0.071502685546875 +29332 -0.13543701171875 +29333 -0.219970703125 +29334 -0.300506591796875 +29335 -0.376312255859375 +29336 -0.416107177734375 +29337 -0.371124267578125 +29338 -0.242279052734375 +29339 -0.069732666015625 +29340 0.125640869140625 +29341 0.31268310546875 +29342 0.45501708984375 +29343 0.554779052734375 +29344 0.61065673828125 +29345 0.610931396484375 +29346 0.531463623046875 +29347 0.3883056640625 +29348 0.23468017578125 +29349 0.095245361328125 +29350 -0.00396728515625 +29351 -0.04852294921875 +29352 -0.055145263671875 +29353 -0.0758056640625 +29354 -0.138702392578125 +29355 -0.209197998046875 +29356 -0.289031982421875 +29357 -0.37884521484375 +29358 -0.456329345703125 +29359 -0.51641845703125 +29360 -0.519287109375 +29361 -0.458251953125 +29362 -0.384796142578125 +29363 -0.323699951171875 +29364 -0.269287109375 +29365 -0.1951904296875 +29366 -0.100006103515625 +29367 -0.01055908203125 +29368 0.1033935546875 +29369 0.24908447265625 +29370 0.373199462890625 +29371 0.45806884765625 +29372 0.511474609375 +29373 0.565399169921875 +29374 0.61138916015625 +29375 0.5897216796875 +29376 0.4906005859375 +29377 0.33148193359375 +29378 0.147796630859375 +29379 -0.01873779296875 +29380 -0.140289306640625 +29381 -0.191986083984375 +29382 -0.184295654296875 +29383 -0.161834716796875 +29384 -0.166595458984375 +29385 -0.19390869140625 +29386 -0.22442626953125 +29387 -0.279754638671875 +29388 -0.3389892578125 +29389 -0.3543701171875 +29390 -0.348175048828125 +29391 -0.32598876953125 +29392 -0.2581787109375 +29393 -0.139801025390625 +29394 0.014617919921875 +29395 0.144378662109375 +29396 0.221038818359375 +29397 0.27069091796875 +29398 0.294036865234375 +29399 0.311767578125 +29400 0.339141845703125 +29401 0.360260009765625 +29402 0.360504150390625 +29403 0.308380126953125 +29404 0.18170166015625 +29405 0.0047607421875 +29406 -0.17559814453125 +29407 -0.3143310546875 +29408 -0.36785888671875 +29409 -0.36248779296875 +29410 -0.343536376953125 +29411 -0.3018798828125 +29412 -0.231414794921875 +29413 -0.117645263671875 +29414 0.007049560546875 +29415 0.087982177734375 +29416 0.13946533203125 +29417 0.17425537109375 +29418 0.188201904296875 +29419 0.171234130859375 +29420 0.118438720703125 +29421 0.05706787109375 +29422 -0.010711669921875 +29423 -0.0914306640625 +29424 -0.162322998046875 +29425 -0.194549560546875 +29426 -0.1492919921875 +29427 -0.02166748046875 +29428 0.124053955078125 +29429 0.211151123046875 +29430 0.240447998046875 +29431 0.242218017578125 +29432 0.2257080078125 +29433 0.194366455078125 +29434 0.115509033203125 +29435 0.0128173828125 +29436 -0.053802490234375 +29437 -0.110626220703125 +29438 -0.199493408203125 +29439 -0.29437255859375 +29440 -0.33221435546875 +29441 -0.27972412109375 +29442 -0.185333251953125 +29443 -0.128204345703125 +29444 -0.115692138671875 +29445 -0.116455078125 +29446 -0.105926513671875 +29447 -0.053955078125 +29448 0.048797607421875 +29449 0.157318115234375 +29450 0.212005615234375 +29451 0.218475341796875 +29452 0.23724365234375 +29453 0.30535888671875 +29454 0.38128662109375 +29455 0.404449462890625 +29456 0.3944091796875 +29457 0.3885498046875 +29458 0.362640380859375 +29459 0.27362060546875 +29460 0.11712646484375 +29461 -0.054901123046875 +29462 -0.19085693359375 +29463 -0.28570556640625 +29464 -0.339263916015625 +29465 -0.3775634765625 +29466 -0.445709228515625 +29467 -0.535064697265625 +29468 -0.629058837890625 +29469 -0.697601318359375 +29470 -0.70391845703125 +29471 -0.6424560546875 +29472 -0.491241455078125 +29473 -0.265716552734375 +29474 -0.023712158203125 +29475 0.201751708984375 +29476 0.375823974609375 +29477 0.485076904296875 +29478 0.56884765625 +29479 0.634765625 +29480 0.63763427734375 +29481 0.5660400390625 +29482 0.4720458984375 +29483 0.40692138671875 +29484 0.3778076171875 +29485 0.376953125 +29486 0.371978759765625 +29487 0.313140869140625 +29488 0.184417724609375 +29489 0.011199951171875 +29490 -0.171051025390625 +29491 -0.33740234375 +29492 -0.47198486328125 +29493 -0.560394287109375 +29494 -0.58056640625 +29495 -0.54754638671875 +29496 -0.508575439453125 +29497 -0.459503173828125 +29498 -0.394378662109375 +29499 -0.35260009765625 +29500 -0.31170654296875 +29501 -0.197418212890625 +29502 -0.007965087890625 +29503 0.207489013671875 +29504 0.409210205078125 +29505 0.57208251953125 +29506 0.66595458984375 +29507 0.65875244140625 +29508 0.56744384765625 +29509 0.431396484375 +29510 0.29443359375 +29511 0.182464599609375 +29512 0.06365966796875 +29513 -0.075958251953125 +29514 -0.189422607421875 +29515 -0.271942138671875 +29516 -0.342529296875 +29517 -0.364166259765625 +29518 -0.327239990234375 +29519 -0.2769775390625 +29520 -0.253692626953125 +29521 -0.24365234375 +29522 -0.1983642578125 +29523 -0.116241455078125 +29524 -0.036834716796875 +29525 0.034881591796875 +29526 0.09124755859375 +29527 0.10888671875 +29528 0.125518798828125 +29529 0.15771484375 +29530 0.17828369140625 +29531 0.17108154296875 +29532 0.129974365234375 +29533 0.082427978515625 +29534 0.027679443359375 +29535 -0.065643310546875 +29536 -0.15936279296875 +29537 -0.21307373046875 +29538 -0.234649658203125 +29539 -0.2001953125 +29540 -0.119171142578125 +29541 -0.024749755859375 +29542 0.085784912109375 +29543 0.178131103515625 +29544 0.215576171875 +29545 0.211456298828125 +29546 0.17523193359375 +29547 0.128753662109375 +29548 0.1019287109375 +29549 0.0743408203125 +29550 0.04327392578125 +29551 0.038177490234375 +29552 0.076263427734375 +29553 0.14105224609375 +29554 0.186431884765625 +29555 0.188812255859375 +29556 0.1390380859375 +29557 0.041778564453125 +29558 -0.079437255859375 +29559 -0.219390869140625 +29560 -0.367828369140625 +29561 -0.494873046875 +29562 -0.556243896484375 +29563 -0.508697509765625 +29564 -0.3756103515625 +29565 -0.218902587890625 +29566 -0.063751220703125 +29567 0.091552734375 +29568 0.23602294921875 +29569 0.342987060546875 +29570 0.39520263671875 +29571 0.389373779296875 +29572 0.324249267578125 +29573 0.224090576171875 +29574 0.124267578125 +29575 0.037078857421875 +29576 -0.010101318359375 +29577 -0.019439697265625 +29578 -0.022796630859375 +29579 -0.001556396484375 +29580 0.056304931640625 +29581 0.106719970703125 +29582 0.096893310546875 +29583 0.042694091796875 +29584 -0.018035888671875 +29585 -0.07586669921875 +29586 -0.11944580078125 +29587 -0.15972900390625 +29588 -0.202606201171875 +29589 -0.24859619140625 +29590 -0.30517578125 +29591 -0.36212158203125 +29592 -0.39141845703125 +29593 -0.35528564453125 +29594 -0.249969482421875 +29595 -0.092864990234375 +29596 0.08905029296875 +29597 0.2352294921875 +29598 0.318817138671875 +29599 0.358642578125 +29600 0.347747802734375 +29601 0.28564453125 +29602 0.223175048828125 +29603 0.196746826171875 +29604 0.179840087890625 +29605 0.155548095703125 +29606 0.151214599609375 +29607 0.156951904296875 +29608 0.13177490234375 +29609 0.100799560546875 +29610 0.087127685546875 +29611 0.05487060546875 +29612 -0.009002685546875 +29613 -0.10400390625 +29614 -0.229400634765625 +29615 -0.35552978515625 +29616 -0.441925048828125 +29617 -0.473846435546875 +29618 -0.464813232421875 +29619 -0.419097900390625 +29620 -0.334320068359375 +29621 -0.227935791015625 +29622 -0.12347412109375 +29623 -0.02764892578125 +29624 0.077667236328125 +29625 0.2132568359375 +29626 0.38885498046875 +29627 0.582794189453125 +29628 0.734039306640625 +29629 0.800140380859375 +29630 0.7783203125 +29631 0.6651611328125 +29632 0.45965576171875 +29633 0.199188232421875 +29634 -0.050689697265625 +29635 -0.23297119140625 +29636 -0.33013916015625 +29637 -0.368408203125 +29638 -0.378936767578125 +29639 -0.376983642578125 +29640 -0.37969970703125 +29641 -0.391510009765625 +29642 -0.385345458984375 +29643 -0.3419189453125 +29644 -0.28289794921875 +29645 -0.251617431640625 +29646 -0.266143798828125 +29647 -0.273345947265625 +29648 -0.216796875 +29649 -0.128265380859375 +29650 -0.068145751953125 +29651 -0.0430908203125 +29652 -0.024444580078125 +29653 0.020721435546875 +29654 0.124481201171875 +29655 0.25787353515625 +29656 0.379119873046875 +29657 0.47991943359375 +29658 0.5281982421875 +29659 0.511138916015625 +29660 0.456207275390625 +29661 0.407470703125 +29662 0.383758544921875 +29663 0.35687255859375 +29664 0.31182861328125 +29665 0.250885009765625 +29666 0.1654052734375 +29667 0.035247802734375 +29668 -0.142059326171875 +29669 -0.33563232421875 +29670 -0.5345458984375 +29671 -0.72186279296875 +29672 -0.836669921875 +29673 -0.8326416015625 +29674 -0.7296142578125 +29675 -0.582550048828125 +29676 -0.440093994140625 +29677 -0.324310302734375 +29678 -0.20147705078125 +29679 -0.044647216796875 +29680 0.103973388671875 +29681 0.202392578125 +29682 0.264495849609375 +29683 0.338897705078125 +29684 0.443817138671875 +29685 0.545074462890625 +29686 0.6173095703125 +29687 0.6524658203125 +29688 0.66339111328125 +29689 0.6561279296875 +29690 0.606781005859375 +29691 0.501190185546875 +29692 0.352783203125 +29693 0.176544189453125 +29694 -0.034820556640625 +29695 -0.258209228515625 +29696 -0.44244384765625 +29697 -0.5753173828125 +29698 -0.65203857421875 +29699 -0.641632080078125 +29700 -0.562164306640625 +29701 -0.458038330078125 +29702 -0.350555419921875 +29703 -0.260528564453125 +29704 -0.192108154296875 +29705 -0.141937255859375 +29706 -0.1021728515625 +29707 -0.062896728515625 +29708 -0.011932373046875 +29709 0.062835693359375 +29710 0.148712158203125 +29711 0.241729736328125 +29712 0.34912109375 +29713 0.457305908203125 +29714 0.54388427734375 +29715 0.5728759765625 +29716 0.506591796875 +29717 0.351226806640625 +29718 0.146514892578125 +29719 -0.05523681640625 +29720 -0.21624755859375 +29721 -0.334930419921875 +29722 -0.402984619140625 +29723 -0.4412841796875 +29724 -0.49578857421875 +29725 -0.5601806640625 +29726 -0.600738525390625 +29727 -0.584228515625 +29728 -0.47930908203125 +29729 -0.27935791015625 +29730 -0.0089111328125 +29731 0.268798828125 +29732 0.482818603515625 +29733 0.60369873046875 +29734 0.650421142578125 +29735 0.66400146484375 +29736 0.6414794921875 +29737 0.572540283203125 +29738 0.498138427734375 +29739 0.439453125 +29740 0.375518798828125 +29741 0.274505615234375 +29742 0.1087646484375 +29743 -0.099395751953125 +29744 -0.3182373046875 +29745 -0.5489501953125 +29746 -0.7738037109375 +29747 -0.86383056640625 +29748 -0.870391845703125 +29749 -0.86895751953125 +29750 -0.861053466796875 +29751 -0.765869140625 +29752 -0.5301513671875 +29753 -0.214691162109375 +29754 0.137359619140625 +29755 0.474822998046875 +29756 0.76239013671875 +29757 0.867462158203125 +29758 0.870361328125 +29759 0.86480712890625 +29760 0.831817626953125 +29761 0.677581787109375 +29762 0.495880126953125 +29763 0.30767822265625 +29764 0.116180419921875 +29765 -0.110748291015625 +29766 -0.381805419921875 +29767 -0.6572265625 +29768 -0.857421875 +29769 -0.870391845703125 +29770 -0.870391845703125 +29771 -0.86444091796875 +29772 -0.85723876953125 +29773 -0.790008544921875 +29774 -0.62847900390625 +29775 -0.3956298828125 +29776 -0.126708984375 +29777 0.150115966796875 +29778 0.424041748046875 +29779 0.670623779296875 +29780 0.854522705078125 +29781 0.866485595703125 +29782 0.86920166015625 +29783 0.8653564453125 +29784 0.857147216796875 +29785 0.766845703125 +29786 0.628509521484375 +29787 0.462127685546875 +29788 0.297210693359375 +29789 0.14862060546875 +29790 -0.00537109375 +29791 -0.15753173828125 +29792 -0.31304931640625 +29793 -0.48876953125 +29794 -0.6416015625 +29795 -0.751373291015625 +29796 -0.84619140625 +29797 -0.861297607421875 +29798 -0.863250732421875 +29799 -0.856597900390625 +29800 -0.7498779296875 +29801 -0.624542236328125 +29802 -0.47808837890625 +29803 -0.253387451171875 +29804 0.003692626953125 +29805 0.2257080078125 +29806 0.427154541015625 +29807 0.643218994140625 +29808 0.855926513671875 +29809 0.870361328125 +29810 0.870361328125 +29811 0.862762451171875 +29812 0.79669189453125 +29813 0.595794677734375 +29814 0.362152099609375 +29815 0.1270751953125 +29816 -0.086944580078125 +29817 -0.2784423828125 +29818 -0.484832763671875 +29819 -0.729583740234375 +29820 -0.86688232421875 +29821 -0.870391845703125 +29822 -0.86859130859375 +29823 -0.86279296875 +29824 -0.817962646484375 +29825 -0.6116943359375 +29826 -0.3128662109375 +29827 0.039398193359375 +29828 0.422821044921875 +29829 0.805145263671875 +29830 0.870361328125 +29831 0.870361328125 +29832 0.860015869140625 +29833 0.727935791015625 +29834 0.48114013671875 +29835 0.2059326171875 +29836 -0.06103515625 +29837 -0.29913330078125 +29838 -0.516204833984375 +29839 -0.7252197265625 +29840 -0.85980224609375 +29841 -0.870391845703125 +29842 -0.870391845703125 +29843 -0.858062744140625 +29844 -0.673004150390625 +29845 -0.42694091796875 +29846 -0.2100830078125 +29847 -0.0362548828125 +29848 0.10943603515625 +29849 0.23516845703125 +29850 0.373687744140625 +29851 0.517791748046875 +29852 0.602783203125 +29853 0.635711669921875 +29854 0.655181884765625 +29855 0.65948486328125 +29856 0.651275634765625 +29857 0.61846923828125 +29858 0.53753662109375 +29859 0.404144287109375 +29860 0.22186279296875 +29861 0.003997802734375 +29862 -0.22100830078125 +29863 -0.42449951171875 +29864 -0.579833984375 +29865 -0.641876220703125 +29866 -0.6177978515625 +29867 -0.575531005859375 +29868 -0.526336669921875 +29869 -0.42645263671875 +29870 -0.2581787109375 +29871 -0.068695068359375 +29872 0.09222412109375 +29873 0.232147216796875 +29874 0.3509521484375 +29875 0.410064697265625 +29876 0.372955322265625 +29877 0.2554931640625 +29878 0.10711669921875 +29879 -0.052886962890625 +29880 -0.186279296875 +29881 -0.23291015625 +29882 -0.209442138671875 +29883 -0.174163818359375 +29884 -0.126739501953125 +29885 -0.048126220703125 +29886 0.0426025390625 +29887 0.10748291015625 +29888 0.1409912109375 +29889 0.19708251953125 +29890 0.273651123046875 +29891 0.31768798828125 +29892 0.341094970703125 +29893 0.368011474609375 +29894 0.37249755859375 +29895 0.30072021484375 +29896 0.1517333984375 +29897 -0.01470947265625 +29898 -0.1883544921875 +29899 -0.372711181640625 +29900 -0.51397705078125 +29901 -0.57177734375 +29902 -0.53948974609375 +29903 -0.43511962890625 +29904 -0.2962646484375 +29905 -0.161102294921875 +29906 -0.0435791015625 +29907 0.060394287109375 +29908 0.13665771484375 +29909 0.170135498046875 +29910 0.16552734375 +29911 0.15728759765625 +29912 0.150787353515625 +29913 0.12200927734375 +29914 0.080108642578125 +29915 0.05126953125 +29916 0.062896728515625 +29917 0.09271240234375 +29918 0.092987060546875 +29919 0.07855224609375 +29920 0.06427001953125 +29921 0.0347900390625 +29922 -0.01171875 +29923 -0.056060791015625 +29924 -0.055511474609375 +29925 -0.010467529296875 +29926 0.02508544921875 +29927 0.025665283203125 +29928 0.017333984375 +29929 0.00189208984375 +29930 -0.03173828125 +29931 -0.071502685546875 +29932 -0.13543701171875 +29933 -0.219970703125 +29934 -0.300506591796875 +29935 -0.376312255859375 +29936 -0.416107177734375 +29937 -0.371124267578125 +29938 -0.242279052734375 +29939 -0.069732666015625 +29940 0.125640869140625 +29941 0.31268310546875 +29942 0.45501708984375 +29943 0.554779052734375 +29944 0.61065673828125 +29945 0.610931396484375 +29946 0.531463623046875 +29947 0.3883056640625 +29948 0.23468017578125 +29949 0.095245361328125 +29950 -0.00396728515625 +29951 -0.04852294921875 +29952 -0.055145263671875 +29953 -0.0758056640625 +29954 -0.138702392578125 +29955 -0.209197998046875 +29956 -0.289031982421875 +29957 -0.37884521484375 +29958 -0.456329345703125 +29959 -0.51641845703125 +29960 -0.519287109375 +29961 -0.458251953125 +29962 -0.384796142578125 +29963 -0.323699951171875 +29964 -0.269287109375 +29965 -0.1951904296875 +29966 -0.100006103515625 +29967 -0.01055908203125 +29968 0.1033935546875 +29969 0.24908447265625 +29970 0.373199462890625 +29971 0.45806884765625 +29972 0.511474609375 +29973 0.565399169921875 +29974 0.61138916015625 +29975 0.5897216796875 +29976 0.4906005859375 +29977 0.33148193359375 +29978 0.147796630859375 +29979 -0.01873779296875 +29980 -0.140289306640625 +29981 -0.191986083984375 +29982 -0.184295654296875 +29983 -0.161834716796875 +29984 -0.166595458984375 +29985 -0.19390869140625 +29986 -0.22442626953125 +29987 -0.279754638671875 +29988 -0.3389892578125 +29989 -0.3543701171875 +29990 -0.348175048828125 +29991 -0.32598876953125 +29992 -0.2581787109375 +29993 -0.139801025390625 +29994 0.014617919921875 +29995 0.144378662109375 +29996 0.221038818359375 +29997 0.27069091796875 +29998 0.294036865234375 +29999 0.311767578125 +30000 0.339141845703125 +30001 0.360260009765625 +30002 0.360504150390625 +30003 0.308380126953125 +30004 0.18170166015625 +30005 0.0047607421875 +30006 -0.17559814453125 +30007 -0.3143310546875 +30008 -0.36785888671875 +30009 -0.36248779296875 +30010 -0.343536376953125 +30011 -0.3018798828125 +30012 -0.231414794921875 +30013 -0.117645263671875 +30014 0.007049560546875 +30015 0.087982177734375 +30016 0.13946533203125 +30017 0.17425537109375 +30018 0.188201904296875 +30019 0.171234130859375 +30020 0.118438720703125 +30021 0.05706787109375 +30022 -0.010711669921875 +30023 -0.0914306640625 +30024 -0.162322998046875 +30025 -0.194549560546875 +30026 -0.1492919921875 +30027 -0.02166748046875 +30028 0.124053955078125 +30029 0.211151123046875 +30030 0.240447998046875 +30031 0.242218017578125 +30032 0.2257080078125 +30033 0.194366455078125 +30034 0.115509033203125 +30035 0.0128173828125 +30036 -0.053802490234375 +30037 -0.110626220703125 +30038 -0.199493408203125 +30039 -0.29437255859375 +30040 -0.33221435546875 +30041 -0.27972412109375 +30042 -0.185333251953125 +30043 -0.128204345703125 +30044 -0.115692138671875 +30045 -0.116455078125 +30046 -0.105926513671875 +30047 -0.053955078125 +30048 0.048797607421875 +30049 0.157318115234375 +30050 0.212005615234375 +30051 0.218475341796875 +30052 0.23724365234375 +30053 0.30535888671875 +30054 0.38128662109375 +30055 0.404449462890625 +30056 0.3944091796875 +30057 0.3885498046875 +30058 0.362640380859375 +30059 0.27362060546875 +30060 0.11712646484375 +30061 -0.054901123046875 +30062 -0.19085693359375 +30063 -0.28570556640625 +30064 -0.339263916015625 +30065 -0.3775634765625 +30066 -0.445709228515625 +30067 -0.535064697265625 +30068 -0.629058837890625 +30069 -0.697601318359375 +30070 -0.70391845703125 +30071 -0.6424560546875 +30072 -0.491241455078125 +30073 -0.265716552734375 +30074 -0.023712158203125 +30075 0.201751708984375 +30076 0.375823974609375 +30077 0.485076904296875 +30078 0.56884765625 +30079 0.634765625 +30080 0.63763427734375 +30081 0.5660400390625 +30082 0.4720458984375 +30083 0.40692138671875 +30084 0.3778076171875 +30085 0.376953125 +30086 0.371978759765625 +30087 0.313140869140625 +30088 0.184417724609375 +30089 0.011199951171875 +30090 -0.171051025390625 +30091 -0.33740234375 +30092 -0.47198486328125 +30093 -0.560394287109375 +30094 -0.58056640625 +30095 -0.54754638671875 +30096 -0.508575439453125 +30097 -0.459503173828125 +30098 -0.394378662109375 +30099 -0.35260009765625 +30100 -0.31170654296875 +30101 -0.197418212890625 +30102 -0.007965087890625 +30103 0.207489013671875 +30104 0.409210205078125 +30105 0.57208251953125 +30106 0.66595458984375 +30107 0.65875244140625 +30108 0.56744384765625 +30109 0.431396484375 +30110 0.29443359375 +30111 0.182464599609375 +30112 0.06365966796875 +30113 -0.075958251953125 +30114 -0.189422607421875 +30115 -0.271942138671875 +30116 -0.342529296875 +30117 -0.364166259765625 +30118 -0.327239990234375 +30119 -0.2769775390625 +30120 -0.253692626953125 +30121 -0.24365234375 +30122 -0.1983642578125 +30123 -0.116241455078125 +30124 -0.036834716796875 +30125 0.034881591796875 +30126 0.09124755859375 +30127 0.10888671875 +30128 0.125518798828125 +30129 0.15771484375 +30130 0.17828369140625 +30131 0.17108154296875 +30132 0.129974365234375 +30133 0.082427978515625 +30134 0.027679443359375 +30135 -0.065643310546875 +30136 -0.15936279296875 +30137 -0.21307373046875 +30138 -0.234649658203125 +30139 -0.2001953125 +30140 -0.119171142578125 +30141 -0.024749755859375 +30142 0.085784912109375 +30143 0.178131103515625 +30144 0.215576171875 +30145 0.211456298828125 +30146 0.17523193359375 +30147 0.128753662109375 +30148 0.1019287109375 +30149 0.0743408203125 +30150 0.04327392578125 +30151 0.038177490234375 +30152 0.076263427734375 +30153 0.14105224609375 +30154 0.186431884765625 +30155 0.188812255859375 +30156 0.1390380859375 +30157 0.041778564453125 +30158 -0.079437255859375 +30159 -0.219390869140625 +30160 -0.367828369140625 +30161 -0.494873046875 +30162 -0.556243896484375 +30163 -0.508697509765625 +30164 -0.3756103515625 +30165 -0.218902587890625 +30166 -0.063751220703125 +30167 0.091552734375 +30168 0.23602294921875 +30169 0.342987060546875 +30170 0.39520263671875 +30171 0.389373779296875 +30172 0.324249267578125 +30173 0.224090576171875 +30174 0.124267578125 +30175 0.037078857421875 +30176 -0.010101318359375 +30177 -0.019439697265625 +30178 -0.022796630859375 +30179 -0.001556396484375 +30180 0.056304931640625 +30181 0.106719970703125 +30182 0.096893310546875 +30183 0.042694091796875 +30184 -0.018035888671875 +30185 -0.07586669921875 +30186 -0.11944580078125 +30187 -0.15972900390625 +30188 -0.202606201171875 +30189 -0.24859619140625 +30190 -0.30517578125 +30191 -0.36212158203125 +30192 -0.39141845703125 +30193 -0.35528564453125 +30194 -0.249969482421875 +30195 -0.092864990234375 +30196 0.08905029296875 +30197 0.2352294921875 +30198 0.318817138671875 +30199 0.358642578125 +30200 0.347747802734375 +30201 0.28564453125 +30202 0.223175048828125 +30203 0.196746826171875 +30204 0.179840087890625 +30205 0.155548095703125 +30206 0.151214599609375 +30207 0.156951904296875 +30208 0.13177490234375 +30209 0.100799560546875 +30210 0.087127685546875 +30211 0.05487060546875 +30212 -0.009002685546875 +30213 -0.10400390625 +30214 -0.229400634765625 +30215 -0.35552978515625 +30216 -0.441925048828125 +30217 -0.473846435546875 +30218 -0.464813232421875 +30219 -0.419097900390625 +30220 -0.334320068359375 +30221 -0.227935791015625 +30222 -0.12347412109375 +30223 -0.02764892578125 +30224 0.077667236328125 +30225 0.2132568359375 +30226 0.38885498046875 +30227 0.582794189453125 +30228 0.734039306640625 +30229 0.800140380859375 +30230 0.7783203125 +30231 0.6651611328125 +30232 0.45965576171875 +30233 0.199188232421875 +30234 -0.050689697265625 +30235 -0.23297119140625 +30236 -0.33013916015625 +30237 -0.368408203125 +30238 -0.378936767578125 +30239 -0.376983642578125 +30240 -0.37969970703125 +30241 -0.391510009765625 +30242 -0.385345458984375 +30243 -0.3419189453125 +30244 -0.28289794921875 +30245 -0.251617431640625 +30246 -0.266143798828125 +30247 -0.273345947265625 +30248 -0.216796875 +30249 -0.128265380859375 +30250 -0.068145751953125 +30251 -0.0430908203125 +30252 -0.024444580078125 +30253 0.020721435546875 +30254 0.124481201171875 +30255 0.25787353515625 +30256 0.379119873046875 +30257 0.47991943359375 +30258 0.5281982421875 +30259 0.511138916015625 +30260 0.456207275390625 +30261 0.407470703125 +30262 0.383758544921875 +30263 0.35687255859375 +30264 0.31182861328125 +30265 0.250885009765625 +30266 0.1654052734375 +30267 0.035247802734375 +30268 -0.142059326171875 +30269 -0.33563232421875 +30270 -0.5345458984375 +30271 -0.72186279296875 +30272 -0.836669921875 +30273 -0.8326416015625 +30274 -0.7296142578125 +30275 -0.582550048828125 +30276 -0.440093994140625 +30277 -0.324310302734375 +30278 -0.20147705078125 +30279 -0.044647216796875 +30280 0.103973388671875 +30281 0.202392578125 +30282 0.264495849609375 +30283 0.338897705078125 +30284 0.443817138671875 +30285 0.545074462890625 +30286 0.6173095703125 +30287 0.6524658203125 +30288 0.66339111328125 +30289 0.6561279296875 +30290 0.606781005859375 +30291 0.501190185546875 +30292 0.352783203125 +30293 0.176544189453125 +30294 -0.034820556640625 +30295 -0.258209228515625 +30296 -0.44244384765625 +30297 -0.5753173828125 +30298 -0.65203857421875 +30299 -0.641632080078125 +30300 -0.562164306640625 +30301 -0.458038330078125 +30302 -0.350555419921875 +30303 -0.260528564453125 +30304 -0.192108154296875 +30305 -0.141937255859375 +30306 -0.1021728515625 +30307 -0.062896728515625 +30308 -0.011932373046875 +30309 0.062835693359375 +30310 0.148712158203125 +30311 0.241729736328125 +30312 0.34912109375 +30313 0.457305908203125 +30314 0.54388427734375 +30315 0.5728759765625 +30316 0.506591796875 +30317 0.351226806640625 +30318 0.146514892578125 +30319 -0.05523681640625 +30320 -0.21624755859375 +30321 -0.334930419921875 +30322 -0.402984619140625 +30323 -0.4412841796875 +30324 -0.49578857421875 +30325 -0.5601806640625 +30326 -0.600738525390625 +30327 -0.584228515625 +30328 -0.47930908203125 +30329 -0.27935791015625 +30330 -0.0089111328125 +30331 0.268798828125 +30332 0.482818603515625 +30333 0.60369873046875 +30334 0.650421142578125 +30335 0.66400146484375 +30336 0.6414794921875 +30337 0.572540283203125 +30338 0.498138427734375 +30339 0.439453125 +30340 0.375518798828125 +30341 0.274505615234375 +30342 0.1087646484375 +30343 -0.099395751953125 +30344 -0.3182373046875 +30345 -0.5489501953125 +30346 -0.7738037109375 +30347 -0.86383056640625 +30348 -0.870391845703125 +30349 -0.86895751953125 +30350 -0.861053466796875 +30351 -0.765869140625 +30352 -0.5301513671875 +30353 -0.214691162109375 +30354 0.137359619140625 +30355 0.474822998046875 +30356 0.76239013671875 +30357 0.867462158203125 +30358 0.870361328125 +30359 0.86480712890625 +30360 0.831817626953125 +30361 0.677581787109375 +30362 0.495880126953125 +30363 0.30767822265625 +30364 0.116180419921875 +30365 -0.110748291015625 +30366 -0.381805419921875 +30367 -0.6572265625 +30368 -0.857421875 +30369 -0.870391845703125 +30370 -0.870391845703125 +30371 -0.86444091796875 +30372 -0.85723876953125 +30373 -0.790008544921875 +30374 -0.62847900390625 +30375 -0.3956298828125 +30376 -0.126708984375 +30377 0.150115966796875 +30378 0.424041748046875 +30379 0.670623779296875 +30380 0.854522705078125 +30381 0.866485595703125 +30382 0.86920166015625 +30383 0.8653564453125 +30384 0.857147216796875 +30385 0.766845703125 +30386 0.628509521484375 +30387 0.462127685546875 +30388 0.297210693359375 +30389 0.14862060546875 +30390 -0.00537109375 +30391 -0.15753173828125 +30392 -0.31304931640625 +30393 -0.48876953125 +30394 -0.6416015625 +30395 -0.751373291015625 +30396 -0.84619140625 +30397 -0.861297607421875 +30398 -0.863250732421875 +30399 -0.856597900390625 +30400 -0.7498779296875 +30401 -0.624542236328125 +30402 -0.47808837890625 +30403 -0.253387451171875 +30404 0.003692626953125 +30405 0.2257080078125 +30406 0.427154541015625 +30407 0.643218994140625 +30408 0.855926513671875 +30409 0.870361328125 +30410 0.870361328125 +30411 0.862762451171875 +30412 0.79669189453125 +30413 0.595794677734375 +30414 0.362152099609375 +30415 0.1270751953125 +30416 -0.086944580078125 +30417 -0.2784423828125 +30418 -0.484832763671875 +30419 -0.729583740234375 +30420 -0.86688232421875 +30421 -0.870391845703125 +30422 -0.86859130859375 +30423 -0.86279296875 +30424 -0.817962646484375 +30425 -0.6116943359375 +30426 -0.3128662109375 +30427 0.039398193359375 +30428 0.422821044921875 +30429 0.805145263671875 +30430 0.870361328125 +30431 0.870361328125 +30432 0.860015869140625 +30433 0.727935791015625 +30434 0.48114013671875 +30435 0.2059326171875 +30436 -0.06103515625 +30437 -0.29913330078125 +30438 -0.516204833984375 +30439 -0.7252197265625 +30440 -0.85980224609375 +30441 -0.870391845703125 +30442 -0.870391845703125 +30443 -0.858062744140625 +30444 -0.673004150390625 +30445 -0.42694091796875 +30446 -0.2100830078125 +30447 -0.0362548828125 +30448 0.10943603515625 +30449 0.23516845703125 +30450 0.373687744140625 +30451 0.517791748046875 +30452 0.602783203125 +30453 0.635711669921875 +30454 0.655181884765625 +30455 0.65948486328125 +30456 0.651275634765625 +30457 0.61846923828125 +30458 0.53753662109375 +30459 0.404144287109375 +30460 0.22186279296875 +30461 0.003997802734375 +30462 -0.22100830078125 +30463 -0.42449951171875 +30464 -0.579833984375 +30465 -0.641876220703125 +30466 -0.6177978515625 +30467 -0.575531005859375 +30468 -0.526336669921875 +30469 -0.42645263671875 +30470 -0.2581787109375 +30471 -0.068695068359375 +30472 0.09222412109375 +30473 0.232147216796875 +30474 0.3509521484375 +30475 0.410064697265625 +30476 0.372955322265625 +30477 0.2554931640625 +30478 0.10711669921875 +30479 -0.052886962890625 +30480 -0.186279296875 +30481 -0.23291015625 +30482 -0.209442138671875 +30483 -0.174163818359375 +30484 -0.126739501953125 +30485 -0.048126220703125 +30486 0.0426025390625 +30487 0.10748291015625 +30488 0.1409912109375 +30489 0.19708251953125 +30490 0.273651123046875 +30491 0.31768798828125 +30492 0.341094970703125 +30493 0.368011474609375 +30494 0.37249755859375 +30495 0.30072021484375 +30496 0.1517333984375 +30497 -0.01470947265625 +30498 -0.1883544921875 +30499 -0.372711181640625 +30500 -0.51397705078125 +30501 -0.57177734375 +30502 -0.53948974609375 +30503 -0.43511962890625 +30504 -0.2962646484375 +30505 -0.161102294921875 +30506 -0.0435791015625 +30507 0.060394287109375 +30508 0.13665771484375 +30509 0.170135498046875 +30510 0.16552734375 +30511 0.15728759765625 +30512 0.150787353515625 +30513 0.12200927734375 +30514 0.080108642578125 +30515 0.05126953125 +30516 0.062896728515625 +30517 0.09271240234375 +30518 0.092987060546875 +30519 0.07855224609375 +30520 0.06427001953125 +30521 0.0347900390625 +30522 -0.01171875 +30523 -0.056060791015625 +30524 -0.055511474609375 +30525 -0.010467529296875 +30526 0.02508544921875 +30527 0.025665283203125 +30528 0.017333984375 +30529 0.00189208984375 +30530 -0.03173828125 +30531 -0.071502685546875 +30532 -0.13543701171875 +30533 -0.219970703125 +30534 -0.300506591796875 +30535 -0.376312255859375 +30536 -0.416107177734375 +30537 -0.371124267578125 +30538 -0.242279052734375 +30539 -0.069732666015625 +30540 0.125640869140625 +30541 0.31268310546875 +30542 0.45501708984375 +30543 0.554779052734375 +30544 0.61065673828125 +30545 0.610931396484375 +30546 0.531463623046875 +30547 0.3883056640625 +30548 0.23468017578125 +30549 0.095245361328125 +30550 -0.00396728515625 +30551 -0.04852294921875 +30552 -0.055145263671875 +30553 -0.0758056640625 +30554 -0.138702392578125 +30555 -0.209197998046875 +30556 -0.289031982421875 +30557 -0.37884521484375 +30558 -0.456329345703125 +30559 -0.51641845703125 +30560 -0.519287109375 +30561 -0.458251953125 +30562 -0.384796142578125 +30563 -0.323699951171875 +30564 -0.269287109375 +30565 -0.1951904296875 +30566 -0.100006103515625 +30567 -0.01055908203125 +30568 0.1033935546875 +30569 0.24908447265625 +30570 0.373199462890625 +30571 0.45806884765625 +30572 0.511474609375 +30573 0.565399169921875 +30574 0.61138916015625 +30575 0.5897216796875 +30576 0.4906005859375 +30577 0.33148193359375 +30578 0.147796630859375 +30579 -0.01873779296875 +30580 -0.140289306640625 +30581 -0.191986083984375 +30582 -0.184295654296875 +30583 -0.161834716796875 +30584 -0.166595458984375 +30585 -0.19390869140625 +30586 -0.22442626953125 +30587 -0.279754638671875 +30588 -0.3389892578125 +30589 -0.3543701171875 +30590 -0.348175048828125 +30591 -0.32598876953125 +30592 -0.2581787109375 +30593 -0.139801025390625 +30594 0.014617919921875 +30595 0.144378662109375 +30596 0.221038818359375 +30597 0.27069091796875 +30598 0.294036865234375 +30599 0.311767578125 +30600 0.339141845703125 +30601 0.360260009765625 +30602 0.360504150390625 +30603 0.308380126953125 +30604 0.18170166015625 +30605 0.0047607421875 +30606 -0.17559814453125 +30607 -0.3143310546875 +30608 -0.36785888671875 +30609 -0.36248779296875 +30610 -0.343536376953125 +30611 -0.3018798828125 +30612 -0.231414794921875 +30613 -0.117645263671875 +30614 0.007049560546875 +30615 0.087982177734375 +30616 0.13946533203125 +30617 0.17425537109375 +30618 0.188201904296875 +30619 0.171234130859375 +30620 0.118438720703125 +30621 0.05706787109375 +30622 -0.010711669921875 +30623 -0.0914306640625 +30624 -0.162322998046875 +30625 -0.194549560546875 +30626 -0.1492919921875 +30627 -0.02166748046875 +30628 0.124053955078125 +30629 0.211151123046875 +30630 0.240447998046875 +30631 0.242218017578125 +30632 0.2257080078125 +30633 0.194366455078125 +30634 0.115509033203125 +30635 0.0128173828125 +30636 -0.053802490234375 +30637 -0.110626220703125 +30638 -0.199493408203125 +30639 -0.29437255859375 +30640 -0.33221435546875 +30641 -0.27972412109375 +30642 -0.185333251953125 +30643 -0.128204345703125 +30644 -0.115692138671875 +30645 -0.116455078125 +30646 -0.105926513671875 +30647 -0.053955078125 +30648 0.048797607421875 +30649 0.157318115234375 +30650 0.212005615234375 +30651 0.218475341796875 +30652 0.23724365234375 +30653 0.30535888671875 +30654 0.38128662109375 +30655 0.404449462890625 +30656 0.3944091796875 +30657 0.3885498046875 +30658 0.362640380859375 +30659 0.27362060546875 +30660 0.11712646484375 +30661 -0.054901123046875 +30662 -0.19085693359375 +30663 -0.28570556640625 +30664 -0.339263916015625 +30665 -0.3775634765625 +30666 -0.445709228515625 +30667 -0.535064697265625 +30668 -0.629058837890625 +30669 -0.697601318359375 +30670 -0.70391845703125 +30671 -0.6424560546875 +30672 -0.491241455078125 +30673 -0.265716552734375 +30674 -0.023712158203125 +30675 0.201751708984375 +30676 0.375823974609375 +30677 0.485076904296875 +30678 0.56884765625 +30679 0.634765625 +30680 0.63763427734375 +30681 0.5660400390625 +30682 0.4720458984375 +30683 0.40692138671875 +30684 0.3778076171875 +30685 0.376953125 +30686 0.371978759765625 +30687 0.313140869140625 +30688 0.184417724609375 +30689 0.011199951171875 +30690 -0.171051025390625 +30691 -0.33740234375 +30692 -0.47198486328125 +30693 -0.560394287109375 +30694 -0.58056640625 +30695 -0.54754638671875 +30696 -0.508575439453125 +30697 -0.459503173828125 +30698 -0.394378662109375 +30699 -0.35260009765625 +30700 -0.31170654296875 +30701 -0.197418212890625 +30702 -0.007965087890625 +30703 0.207489013671875 +30704 0.409210205078125 +30705 0.57208251953125 +30706 0.66595458984375 +30707 0.65875244140625 +30708 0.56744384765625 +30709 0.431396484375 +30710 0.29443359375 +30711 0.182464599609375 +30712 0.06365966796875 +30713 -0.075958251953125 +30714 -0.189422607421875 +30715 -0.271942138671875 +30716 -0.342529296875 +30717 -0.364166259765625 +30718 -0.327239990234375 +30719 -0.2769775390625 +30720 -0.253692626953125 +30721 -0.24365234375 +30722 -0.1983642578125 +30723 -0.116241455078125 +30724 -0.036834716796875 +30725 0.034881591796875 +30726 0.09124755859375 +30727 0.10888671875 +30728 0.125518798828125 +30729 0.15771484375 +30730 0.17828369140625 +30731 0.17108154296875 +30732 0.129974365234375 +30733 0.082427978515625 +30734 0.027679443359375 +30735 -0.065643310546875 +30736 -0.15936279296875 +30737 -0.21307373046875 +30738 -0.234649658203125 +30739 -0.2001953125 +30740 -0.119171142578125 +30741 -0.024749755859375 +30742 0.085784912109375 +30743 0.178131103515625 +30744 0.215576171875 +30745 0.211456298828125 +30746 0.17523193359375 +30747 0.128753662109375 +30748 0.1019287109375 +30749 0.0743408203125 +30750 0.04327392578125 +30751 0.038177490234375 +30752 0.076263427734375 +30753 0.14105224609375 +30754 0.186431884765625 +30755 0.188812255859375 +30756 0.1390380859375 +30757 0.041778564453125 +30758 -0.079437255859375 +30759 -0.219390869140625 +30760 -0.367828369140625 +30761 -0.494873046875 +30762 -0.556243896484375 +30763 -0.508697509765625 +30764 -0.3756103515625 +30765 -0.218902587890625 +30766 -0.063751220703125 +30767 0.091552734375 +30768 0.23602294921875 +30769 0.342987060546875 +30770 0.39520263671875 +30771 0.389373779296875 +30772 0.324249267578125 +30773 0.224090576171875 +30774 0.124267578125 +30775 0.037078857421875 +30776 -0.010101318359375 +30777 -0.019439697265625 +30778 -0.022796630859375 +30779 -0.001556396484375 +30780 0.056304931640625 +30781 0.106719970703125 +30782 0.096893310546875 +30783 0.042694091796875 +30784 -0.018035888671875 +30785 -0.07586669921875 +30786 -0.11944580078125 +30787 -0.15972900390625 +30788 -0.202606201171875 +30789 -0.24859619140625 +30790 -0.30517578125 +30791 -0.36212158203125 +30792 -0.39141845703125 +30793 -0.35528564453125 +30794 -0.249969482421875 +30795 -0.092864990234375 +30796 0.08905029296875 +30797 0.2352294921875 +30798 0.318817138671875 +30799 0.358642578125 +30800 0.347747802734375 +30801 0.28564453125 +30802 0.223175048828125 +30803 0.196746826171875 +30804 0.179840087890625 +30805 0.155548095703125 +30806 0.151214599609375 +30807 0.156951904296875 +30808 0.13177490234375 +30809 0.100799560546875 +30810 0.087127685546875 +30811 0.05487060546875 +30812 -0.009002685546875 +30813 -0.10400390625 +30814 -0.229400634765625 +30815 -0.35552978515625 +30816 -0.441925048828125 +30817 -0.473846435546875 +30818 -0.464813232421875 +30819 -0.419097900390625 +30820 -0.334320068359375 +30821 -0.227935791015625 +30822 -0.12347412109375 +30823 -0.02764892578125 +30824 0.077667236328125 +30825 0.2132568359375 +30826 0.38885498046875 +30827 0.582794189453125 +30828 0.734039306640625 +30829 0.800140380859375 +30830 0.7783203125 +30831 0.6651611328125 +30832 0.45965576171875 +30833 0.199188232421875 +30834 -0.050689697265625 +30835 -0.23297119140625 +30836 -0.33013916015625 +30837 -0.368408203125 +30838 -0.378936767578125 +30839 -0.376983642578125 +30840 -0.37969970703125 +30841 -0.391510009765625 +30842 -0.385345458984375 +30843 -0.3419189453125 +30844 -0.28289794921875 +30845 -0.251617431640625 +30846 -0.266143798828125 +30847 -0.273345947265625 +30848 -0.216796875 +30849 -0.128265380859375 +30850 -0.068145751953125 +30851 -0.0430908203125 +30852 -0.024444580078125 +30853 0.020721435546875 +30854 0.124481201171875 +30855 0.25787353515625 +30856 0.379119873046875 +30857 0.47991943359375 +30858 0.5281982421875 +30859 0.511138916015625 +30860 0.456207275390625 +30861 0.407470703125 +30862 0.383758544921875 +30863 0.35687255859375 +30864 0.31182861328125 +30865 0.250885009765625 +30866 0.1654052734375 +30867 0.035247802734375 +30868 -0.142059326171875 +30869 -0.33563232421875 +30870 -0.5345458984375 +30871 -0.72186279296875 +30872 -0.836669921875 +30873 -0.8326416015625 +30874 -0.7296142578125 +30875 -0.582550048828125 +30876 -0.440093994140625 +30877 -0.324310302734375 +30878 -0.20147705078125 +30879 -0.044647216796875 +30880 0.103973388671875 +30881 0.202392578125 +30882 0.264495849609375 +30883 0.338897705078125 +30884 0.443817138671875 +30885 0.545074462890625 +30886 0.6173095703125 +30887 0.6524658203125 +30888 0.66339111328125 +30889 0.6561279296875 +30890 0.606781005859375 +30891 0.501190185546875 +30892 0.352783203125 +30893 0.176544189453125 +30894 -0.034820556640625 +30895 -0.258209228515625 +30896 -0.44244384765625 +30897 -0.5753173828125 +30898 -0.65203857421875 +30899 -0.641632080078125 +30900 -0.562164306640625 +30901 -0.458038330078125 +30902 -0.350555419921875 +30903 -0.260528564453125 +30904 -0.192108154296875 +30905 -0.141937255859375 +30906 -0.1021728515625 +30907 -0.062896728515625 +30908 -0.011932373046875 +30909 0.062835693359375 +30910 0.148712158203125 +30911 0.241729736328125 +30912 0.34912109375 +30913 0.457305908203125 +30914 0.54388427734375 +30915 0.5728759765625 +30916 0.506591796875 +30917 0.351226806640625 +30918 0.146514892578125 +30919 -0.05523681640625 +30920 -0.21624755859375 +30921 -0.334930419921875 +30922 -0.402984619140625 +30923 -0.4412841796875 +30924 -0.49578857421875 +30925 -0.5601806640625 +30926 -0.600738525390625 +30927 -0.584228515625 +30928 -0.47930908203125 +30929 -0.27935791015625 +30930 -0.0089111328125 +30931 0.268798828125 +30932 0.482818603515625 +30933 0.60369873046875 +30934 0.650421142578125 +30935 0.66400146484375 +30936 0.6414794921875 +30937 0.572540283203125 +30938 0.498138427734375 +30939 0.439453125 +30940 0.375518798828125 +30941 0.274505615234375 +30942 0.1087646484375 +30943 -0.099395751953125 +30944 -0.3182373046875 +30945 -0.5489501953125 +30946 -0.7738037109375 +30947 -0.86383056640625 +30948 -0.870391845703125 +30949 -0.86895751953125 +30950 -0.861053466796875 +30951 -0.765869140625 +30952 -0.5301513671875 +30953 -0.214691162109375 +30954 0.137359619140625 +30955 0.474822998046875 +30956 0.76239013671875 +30957 0.867462158203125 +30958 0.870361328125 +30959 0.86480712890625 +30960 0.831817626953125 +30961 0.677581787109375 +30962 0.495880126953125 +30963 0.30767822265625 +30964 0.116180419921875 +30965 -0.110748291015625 +30966 -0.381805419921875 +30967 -0.6572265625 +30968 -0.857421875 +30969 -0.870391845703125 +30970 -0.870391845703125 +30971 -0.86444091796875 +30972 -0.85723876953125 +30973 -0.790008544921875 +30974 -0.62847900390625 +30975 -0.3956298828125 +30976 -0.126708984375 +30977 0.150115966796875 +30978 0.424041748046875 +30979 0.670623779296875 +30980 0.854522705078125 +30981 0.866485595703125 +30982 0.86920166015625 +30983 0.8653564453125 +30984 0.857147216796875 +30985 0.766845703125 +30986 0.628509521484375 +30987 0.462127685546875 +30988 0.297210693359375 +30989 0.14862060546875 +30990 -0.00537109375 +30991 -0.15753173828125 +30992 -0.31304931640625 +30993 -0.48876953125 +30994 -0.6416015625 +30995 -0.751373291015625 +30996 -0.84619140625 +30997 -0.861297607421875 +30998 -0.863250732421875 +30999 -0.856597900390625 +31000 -0.7498779296875 +31001 -0.624542236328125 +31002 -0.47808837890625 +31003 -0.253387451171875 +31004 0.003692626953125 +31005 0.2257080078125 +31006 0.427154541015625 +31007 0.643218994140625 +31008 0.855926513671875 +31009 0.870361328125 +31010 0.870361328125 +31011 0.862762451171875 +31012 0.79669189453125 +31013 0.595794677734375 +31014 0.362152099609375 +31015 0.1270751953125 +31016 -0.086944580078125 +31017 -0.2784423828125 +31018 -0.484832763671875 +31019 -0.729583740234375 +31020 -0.86688232421875 +31021 -0.870391845703125 +31022 -0.86859130859375 +31023 -0.86279296875 +31024 -0.817962646484375 +31025 -0.6116943359375 +31026 -0.3128662109375 +31027 0.039398193359375 +31028 0.422821044921875 +31029 0.805145263671875 +31030 0.870361328125 +31031 0.870361328125 +31032 0.860015869140625 +31033 0.727935791015625 +31034 0.48114013671875 +31035 0.2059326171875 +31036 -0.06103515625 +31037 -0.29913330078125 +31038 -0.516204833984375 +31039 -0.7252197265625 +31040 -0.85980224609375 +31041 -0.870391845703125 +31042 -0.870391845703125 +31043 -0.858062744140625 +31044 -0.673004150390625 +31045 -0.42694091796875 +31046 -0.2100830078125 +31047 -0.0362548828125 +31048 0.10943603515625 +31049 0.23516845703125 +31050 0.373687744140625 +31051 0.517791748046875 +31052 0.602783203125 +31053 0.635711669921875 +31054 0.655181884765625 +31055 0.65948486328125 +31056 0.651275634765625 +31057 0.61846923828125 +31058 0.53753662109375 +31059 0.404144287109375 +31060 0.22186279296875 +31061 0.003997802734375 +31062 -0.22100830078125 +31063 -0.42449951171875 +31064 -0.579833984375 +31065 -0.641876220703125 +31066 -0.6177978515625 +31067 -0.575531005859375 +31068 -0.526336669921875 +31069 -0.42645263671875 +31070 -0.2581787109375 +31071 -0.068695068359375 +31072 0.09222412109375 +31073 0.232147216796875 +31074 0.3509521484375 +31075 0.410064697265625 +31076 0.372955322265625 +31077 0.2554931640625 +31078 0.10711669921875 +31079 -0.052886962890625 +31080 -0.186279296875 +31081 -0.23291015625 +31082 -0.209442138671875 +31083 -0.174163818359375 +31084 -0.126739501953125 +31085 -0.048126220703125 +31086 0.0426025390625 +31087 0.10748291015625 +31088 0.1409912109375 +31089 0.19708251953125 +31090 0.273651123046875 +31091 0.31768798828125 +31092 0.341094970703125 +31093 0.368011474609375 +31094 0.37249755859375 +31095 0.30072021484375 +31096 0.1517333984375 +31097 -0.01470947265625 +31098 -0.1883544921875 +31099 -0.372711181640625 +31100 -0.51397705078125 +31101 -0.57177734375 +31102 -0.53948974609375 +31103 -0.43511962890625 +31104 -0.2962646484375 +31105 -0.161102294921875 +31106 -0.0435791015625 +31107 0.060394287109375 +31108 0.13665771484375 +31109 0.170135498046875 +31110 0.16552734375 +31111 0.15728759765625 +31112 0.150787353515625 +31113 0.12200927734375 +31114 0.080108642578125 +31115 0.05126953125 +31116 0.062896728515625 +31117 0.09271240234375 +31118 0.092987060546875 +31119 0.07855224609375 +31120 0.06427001953125 +31121 0.0347900390625 +31122 -0.01171875 +31123 -0.056060791015625 +31124 -0.055511474609375 +31125 -0.010467529296875 +31126 0.02508544921875 +31127 0.025665283203125 +31128 0.017333984375 +31129 0.00189208984375 +31130 -0.03173828125 +31131 -0.071502685546875 +31132 -0.13543701171875 +31133 -0.219970703125 +31134 -0.300506591796875 +31135 -0.376312255859375 +31136 -0.416107177734375 +31137 -0.371124267578125 +31138 -0.242279052734375 +31139 -0.069732666015625 +31140 0.125640869140625 +31141 0.31268310546875 +31142 0.45501708984375 +31143 0.554779052734375 +31144 0.61065673828125 +31145 0.610931396484375 +31146 0.531463623046875 +31147 0.3883056640625 +31148 0.23468017578125 +31149 0.095245361328125 +31150 -0.00396728515625 +31151 -0.04852294921875 +31152 -0.055145263671875 +31153 -0.0758056640625 +31154 -0.138702392578125 +31155 -0.209197998046875 +31156 -0.289031982421875 +31157 -0.37884521484375 +31158 -0.456329345703125 +31159 -0.51641845703125 +31160 -0.519287109375 +31161 -0.458251953125 +31162 -0.384796142578125 +31163 -0.323699951171875 +31164 -0.269287109375 +31165 -0.1951904296875 +31166 -0.100006103515625 +31167 -0.01055908203125 +31168 0.1033935546875 +31169 0.24908447265625 +31170 0.373199462890625 +31171 0.45806884765625 +31172 0.511474609375 +31173 0.565399169921875 +31174 0.61138916015625 +31175 0.5897216796875 +31176 0.4906005859375 +31177 0.33148193359375 +31178 0.147796630859375 +31179 -0.01873779296875 +31180 -0.140289306640625 +31181 -0.191986083984375 +31182 -0.184295654296875 +31183 -0.161834716796875 +31184 -0.166595458984375 +31185 -0.19390869140625 +31186 -0.22442626953125 +31187 -0.279754638671875 +31188 -0.3389892578125 +31189 -0.3543701171875 +31190 -0.348175048828125 +31191 -0.32598876953125 +31192 -0.2581787109375 +31193 -0.139801025390625 +31194 0.014617919921875 +31195 0.144378662109375 +31196 0.221038818359375 +31197 0.27069091796875 +31198 0.294036865234375 +31199 0.311767578125 +31200 0.339141845703125 +31201 0.360260009765625 +31202 0.360504150390625 +31203 0.308380126953125 +31204 0.18170166015625 +31205 0.0047607421875 +31206 -0.17559814453125 +31207 -0.3143310546875 +31208 -0.36785888671875 +31209 -0.36248779296875 +31210 -0.343536376953125 +31211 -0.3018798828125 +31212 -0.231414794921875 +31213 -0.117645263671875 +31214 0.007049560546875 +31215 0.087982177734375 +31216 0.13946533203125 +31217 0.17425537109375 +31218 0.188201904296875 +31219 0.171234130859375 +31220 0.118438720703125 +31221 0.05706787109375 +31222 -0.010711669921875 +31223 -0.0914306640625 +31224 -0.162322998046875 +31225 -0.194549560546875 +31226 -0.1492919921875 +31227 -0.02166748046875 +31228 0.124053955078125 +31229 0.211151123046875 +31230 0.240447998046875 +31231 0.242218017578125 +31232 0.2257080078125 +31233 0.194366455078125 +31234 0.115509033203125 +31235 0.0128173828125 +31236 -0.053802490234375 +31237 -0.110626220703125 +31238 -0.199493408203125 +31239 -0.29437255859375 +31240 -0.33221435546875 +31241 -0.27972412109375 +31242 -0.185333251953125 +31243 -0.128204345703125 +31244 -0.115692138671875 +31245 -0.116455078125 +31246 -0.105926513671875 +31247 -0.053955078125 +31248 0.048797607421875 +31249 0.157318115234375 +31250 0.212005615234375 +31251 0.218475341796875 +31252 0.23724365234375 +31253 0.30535888671875 +31254 0.38128662109375 +31255 0.404449462890625 +31256 0.3944091796875 +31257 0.3885498046875 +31258 0.362640380859375 +31259 0.27362060546875 +31260 0.11712646484375 +31261 -0.054901123046875 +31262 -0.19085693359375 +31263 -0.28570556640625 +31264 -0.339263916015625 +31265 -0.3775634765625 +31266 -0.445709228515625 +31267 -0.535064697265625 +31268 -0.629058837890625 +31269 -0.697601318359375 +31270 -0.70391845703125 +31271 -0.6424560546875 +31272 -0.491241455078125 +31273 -0.265716552734375 +31274 -0.023712158203125 +31275 0.201751708984375 +31276 0.375823974609375 +31277 0.485076904296875 +31278 0.56884765625 +31279 0.634765625 +31280 0.63763427734375 +31281 0.5660400390625 +31282 0.4720458984375 +31283 0.40692138671875 +31284 0.3778076171875 +31285 0.376953125 +31286 0.371978759765625 +31287 0.313140869140625 +31288 0.184417724609375 +31289 0.011199951171875 +31290 -0.171051025390625 +31291 -0.33740234375 +31292 -0.47198486328125 +31293 -0.560394287109375 +31294 -0.58056640625 +31295 -0.54754638671875 +31296 -0.508575439453125 +31297 -0.459503173828125 +31298 -0.394378662109375 +31299 -0.35260009765625 +31300 -0.31170654296875 +31301 -0.197418212890625 +31302 -0.007965087890625 +31303 0.207489013671875 +31304 0.409210205078125 +31305 0.57208251953125 +31306 0.66595458984375 +31307 0.65875244140625 +31308 0.56744384765625 +31309 0.431396484375 +31310 0.29443359375 +31311 0.182464599609375 +31312 0.06365966796875 +31313 -0.075958251953125 +31314 -0.189422607421875 +31315 -0.271942138671875 +31316 -0.342529296875 +31317 -0.364166259765625 +31318 -0.327239990234375 +31319 -0.2769775390625 +31320 -0.253692626953125 +31321 -0.24365234375 +31322 -0.1983642578125 +31323 -0.116241455078125 +31324 -0.036834716796875 +31325 0.034881591796875 +31326 0.09124755859375 +31327 0.10888671875 +31328 0.125518798828125 +31329 0.15771484375 +31330 0.17828369140625 +31331 0.17108154296875 +31332 0.129974365234375 +31333 0.082427978515625 +31334 0.027679443359375 +31335 -0.065643310546875 +31336 -0.15936279296875 +31337 -0.21307373046875 +31338 -0.234649658203125 +31339 -0.2001953125 +31340 -0.119171142578125 +31341 -0.024749755859375 +31342 0.085784912109375 +31343 0.178131103515625 +31344 0.215576171875 +31345 0.211456298828125 +31346 0.17523193359375 +31347 0.128753662109375 +31348 0.1019287109375 +31349 0.0743408203125 +31350 0.04327392578125 +31351 0.038177490234375 +31352 0.076263427734375 +31353 0.14105224609375 +31354 0.186431884765625 +31355 0.188812255859375 +31356 0.1390380859375 +31357 0.041778564453125 +31358 -0.079437255859375 +31359 -0.219390869140625 +31360 -0.367828369140625 +31361 -0.494873046875 +31362 -0.556243896484375 +31363 -0.508697509765625 +31364 -0.3756103515625 +31365 -0.218902587890625 +31366 -0.063751220703125 +31367 0.091552734375 +31368 0.23602294921875 +31369 0.342987060546875 +31370 0.39520263671875 +31371 0.389373779296875 +31372 0.324249267578125 +31373 0.224090576171875 +31374 0.124267578125 +31375 0.037078857421875 +31376 -0.010101318359375 +31377 -0.019439697265625 +31378 -0.022796630859375 +31379 -0.001556396484375 +31380 0.056304931640625 +31381 0.106719970703125 +31382 0.096893310546875 +31383 0.042694091796875 +31384 -0.018035888671875 +31385 -0.07586669921875 +31386 -0.11944580078125 +31387 -0.15972900390625 +31388 -0.202606201171875 +31389 -0.24859619140625 +31390 -0.30517578125 +31391 -0.36212158203125 +31392 -0.39141845703125 +31393 -0.35528564453125 +31394 -0.249969482421875 +31395 -0.092864990234375 +31396 0.08905029296875 +31397 0.2352294921875 +31398 0.318817138671875 +31399 0.358642578125 +31400 0.347747802734375 +31401 0.28564453125 +31402 0.223175048828125 +31403 0.196746826171875 +31404 0.179840087890625 +31405 0.155548095703125 +31406 0.151214599609375 +31407 0.156951904296875 +31408 0.13177490234375 +31409 0.100799560546875 +31410 0.087127685546875 +31411 0.05487060546875 +31412 -0.009002685546875 +31413 -0.10400390625 +31414 -0.229400634765625 +31415 -0.35552978515625 +31416 -0.441925048828125 +31417 -0.473846435546875 +31418 -0.464813232421875 +31419 -0.419097900390625 +31420 -0.334320068359375 +31421 -0.227935791015625 +31422 -0.12347412109375 +31423 -0.02764892578125 +31424 0.077667236328125 +31425 0.2132568359375 +31426 0.38885498046875 +31427 0.582794189453125 +31428 0.734039306640625 +31429 0.800140380859375 +31430 0.7783203125 +31431 0.6651611328125 +31432 0.45965576171875 +31433 0.199188232421875 +31434 -0.050689697265625 +31435 -0.23297119140625 +31436 -0.33013916015625 +31437 -0.368408203125 +31438 -0.378936767578125 +31439 -0.376983642578125 +31440 -0.37969970703125 +31441 -0.391510009765625 +31442 -0.385345458984375 +31443 -0.3419189453125 +31444 -0.28289794921875 +31445 -0.251617431640625 +31446 -0.266143798828125 +31447 -0.273345947265625 +31448 -0.216796875 +31449 -0.128265380859375 +31450 -0.068145751953125 +31451 -0.0430908203125 +31452 -0.024444580078125 +31453 0.020721435546875 +31454 0.124481201171875 +31455 0.25787353515625 +31456 0.379119873046875 +31457 0.47991943359375 +31458 0.5281982421875 +31459 0.511138916015625 +31460 0.456207275390625 +31461 0.407470703125 +31462 0.383758544921875 +31463 0.35687255859375 +31464 0.31182861328125 +31465 0.250885009765625 +31466 0.1654052734375 +31467 0.035247802734375 +31468 -0.142059326171875 +31469 -0.33563232421875 +31470 -0.5345458984375 +31471 -0.72186279296875 +31472 -0.836669921875 +31473 -0.8326416015625 +31474 -0.7296142578125 +31475 -0.582550048828125 +31476 -0.440093994140625 +31477 -0.324310302734375 +31478 -0.20147705078125 +31479 -0.044647216796875 +31480 0.103973388671875 +31481 0.202392578125 +31482 0.264495849609375 +31483 0.338897705078125 +31484 0.443817138671875 +31485 0.545074462890625 +31486 0.6173095703125 +31487 0.6524658203125 +31488 0.66339111328125 +31489 0.6561279296875 +31490 0.606781005859375 +31491 0.501190185546875 +31492 0.352783203125 +31493 0.176544189453125 +31494 -0.034820556640625 +31495 -0.258209228515625 +31496 -0.44244384765625 +31497 -0.5753173828125 +31498 -0.65203857421875 +31499 -0.641632080078125 +31500 -0.562164306640625 +31501 -0.458038330078125 +31502 -0.350555419921875 +31503 -0.260528564453125 +31504 -0.192108154296875 +31505 -0.141937255859375 +31506 -0.1021728515625 +31507 -0.062896728515625 +31508 -0.011932373046875 +31509 0.062835693359375 +31510 0.148712158203125 +31511 0.241729736328125 +31512 0.34912109375 +31513 0.457305908203125 +31514 0.54388427734375 +31515 0.5728759765625 +31516 0.506591796875 +31517 0.351226806640625 +31518 0.146514892578125 +31519 -0.05523681640625 +31520 -0.21624755859375 +31521 -0.334930419921875 +31522 -0.402984619140625 +31523 -0.4412841796875 +31524 -0.49578857421875 +31525 -0.5601806640625 +31526 -0.600738525390625 +31527 -0.584228515625 +31528 -0.47930908203125 +31529 -0.27935791015625 +31530 -0.0089111328125 +31531 0.268798828125 +31532 0.482818603515625 +31533 0.60369873046875 +31534 0.650421142578125 +31535 0.66400146484375 +31536 0.6414794921875 +31537 0.572540283203125 +31538 0.498138427734375 +31539 0.439453125 +31540 0.375518798828125 +31541 0.274505615234375 +31542 0.1087646484375 +31543 -0.099395751953125 +31544 -0.3182373046875 +31545 -0.5489501953125 +31546 -0.7738037109375 +31547 -0.86383056640625 +31548 -0.870391845703125 +31549 -0.86895751953125 +31550 -0.861053466796875 +31551 -0.765869140625 +31552 -0.5301513671875 +31553 -0.214691162109375 +31554 0.137359619140625 +31555 0.474822998046875 +31556 0.76239013671875 +31557 0.867462158203125 +31558 0.870361328125 +31559 0.86480712890625 +31560 0.831817626953125 +31561 0.677581787109375 +31562 0.495880126953125 +31563 0.30767822265625 +31564 0.116180419921875 +31565 -0.110748291015625 +31566 -0.381805419921875 +31567 -0.6572265625 +31568 -0.857421875 +31569 -0.870391845703125 +31570 -0.870391845703125 +31571 -0.86444091796875 +31572 -0.85723876953125 +31573 -0.790008544921875 +31574 -0.62847900390625 +31575 -0.3956298828125 +31576 -0.126708984375 +31577 0.150115966796875 +31578 0.424041748046875 +31579 0.670623779296875 +31580 0.854522705078125 +31581 0.866485595703125 +31582 0.86920166015625 +31583 0.8653564453125 +31584 0.857147216796875 +31585 0.766845703125 +31586 0.628509521484375 +31587 0.462127685546875 +31588 0.297210693359375 +31589 0.14862060546875 +31590 -0.00537109375 +31591 -0.15753173828125 +31592 -0.31304931640625 +31593 -0.48876953125 +31594 -0.6416015625 +31595 -0.751373291015625 +31596 -0.84619140625 +31597 -0.861297607421875 +31598 -0.863250732421875 +31599 -0.856597900390625 +31600 -0.7498779296875 +31601 -0.624542236328125 +31602 -0.47808837890625 +31603 -0.253387451171875 +31604 0.003692626953125 +31605 0.2257080078125 +31606 0.427154541015625 +31607 0.643218994140625 +31608 0.855926513671875 +31609 0.870361328125 +31610 0.870361328125 +31611 0.862762451171875 +31612 0.79669189453125 +31613 0.595794677734375 +31614 0.362152099609375 +31615 0.1270751953125 +31616 -0.086944580078125 +31617 -0.2784423828125 +31618 -0.484832763671875 +31619 -0.729583740234375 +31620 -0.86688232421875 +31621 -0.870391845703125 +31622 -0.86859130859375 +31623 -0.86279296875 +31624 -0.817962646484375 +31625 -0.6116943359375 +31626 -0.3128662109375 +31627 0.039398193359375 +31628 0.422821044921875 +31629 0.805145263671875 +31630 0.870361328125 +31631 0.870361328125 +31632 0.860015869140625 +31633 0.727935791015625 +31634 0.48114013671875 +31635 0.2059326171875 +31636 -0.06103515625 +31637 -0.29913330078125 +31638 -0.516204833984375 +31639 -0.7252197265625 +31640 -0.85980224609375 +31641 -0.870391845703125 +31642 -0.870391845703125 +31643 -0.858062744140625 +31644 -0.673004150390625 +31645 -0.42694091796875 +31646 -0.2100830078125 +31647 -0.0362548828125 +31648 0.10943603515625 +31649 0.23516845703125 +31650 0.373687744140625 +31651 0.517791748046875 +31652 0.602783203125 +31653 0.635711669921875 +31654 0.655181884765625 +31655 0.65948486328125 +31656 0.651275634765625 +31657 0.61846923828125 +31658 0.53753662109375 +31659 0.404144287109375 +31660 0.22186279296875 +31661 0.003997802734375 +31662 -0.22100830078125 +31663 -0.42449951171875 +31664 -0.579833984375 +31665 -0.641876220703125 +31666 -0.6177978515625 +31667 -0.575531005859375 +31668 -0.526336669921875 +31669 -0.42645263671875 +31670 -0.2581787109375 +31671 -0.068695068359375 +31672 0.09222412109375 +31673 0.232147216796875 +31674 0.3509521484375 +31675 0.410064697265625 +31676 0.372955322265625 +31677 0.2554931640625 +31678 0.10711669921875 +31679 -0.052886962890625 +31680 -0.186279296875 +31681 -0.23291015625 +31682 -0.209442138671875 +31683 -0.174163818359375 +31684 -0.126739501953125 +31685 -0.048126220703125 +31686 0.0426025390625 +31687 0.10748291015625 +31688 0.1409912109375 +31689 0.19708251953125 +31690 0.273651123046875 +31691 0.31768798828125 +31692 0.341094970703125 +31693 0.368011474609375 +31694 0.37249755859375 +31695 0.30072021484375 +31696 0.1517333984375 +31697 -0.01470947265625 +31698 -0.1883544921875 +31699 -0.372711181640625 +31700 -0.51397705078125 +31701 -0.57177734375 +31702 -0.53948974609375 +31703 -0.43511962890625 +31704 -0.2962646484375 +31705 -0.161102294921875 +31706 -0.0435791015625 +31707 0.060394287109375 +31708 0.13665771484375 +31709 0.170135498046875 +31710 0.16552734375 +31711 0.15728759765625 +31712 0.150787353515625 +31713 0.12200927734375 +31714 0.080108642578125 +31715 0.05126953125 +31716 0.062896728515625 +31717 0.09271240234375 +31718 0.092987060546875 +31719 0.07855224609375 +31720 0.06427001953125 +31721 0.0347900390625 +31722 -0.01171875 +31723 -0.056060791015625 +31724 -0.055511474609375 +31725 -0.010467529296875 +31726 0.02508544921875 +31727 0.025665283203125 +31728 0.017333984375 +31729 0.00189208984375 +31730 -0.03173828125 +31731 -0.071502685546875 +31732 -0.13543701171875 +31733 -0.219970703125 +31734 -0.300506591796875 +31735 -0.376312255859375 +31736 -0.416107177734375 +31737 -0.371124267578125 +31738 -0.242279052734375 +31739 -0.069732666015625 +31740 0.125640869140625 +31741 0.31268310546875 +31742 0.45501708984375 +31743 0.554779052734375 +31744 0.61065673828125 +31745 0.610931396484375 +31746 0.531463623046875 +31747 0.3883056640625 +31748 0.23468017578125 +31749 0.095245361328125 +31750 -0.00396728515625 +31751 -0.04852294921875 +31752 -0.055145263671875 +31753 -0.0758056640625 +31754 -0.138702392578125 +31755 -0.209197998046875 +31756 -0.289031982421875 +31757 -0.37884521484375 +31758 -0.456329345703125 +31759 -0.51641845703125 +31760 -0.519287109375 +31761 -0.458251953125 +31762 -0.384796142578125 +31763 -0.323699951171875 +31764 -0.269287109375 +31765 -0.1951904296875 +31766 -0.100006103515625 +31767 -0.01055908203125 +31768 0.1033935546875 +31769 0.24908447265625 +31770 0.373199462890625 +31771 0.45806884765625 +31772 0.511474609375 +31773 0.565399169921875 +31774 0.61138916015625 +31775 0.5897216796875 +31776 0.4906005859375 +31777 0.33148193359375 +31778 0.147796630859375 +31779 -0.01873779296875 +31780 -0.140289306640625 +31781 -0.191986083984375 +31782 -0.184295654296875 +31783 -0.161834716796875 +31784 -0.166595458984375 +31785 -0.19390869140625 +31786 -0.22442626953125 +31787 -0.279754638671875 +31788 -0.3389892578125 +31789 -0.3543701171875 +31790 -0.348175048828125 +31791 -0.32598876953125 +31792 -0.2581787109375 +31793 -0.139801025390625 +31794 0.014617919921875 +31795 0.144378662109375 +31796 0.221038818359375 +31797 0.27069091796875 +31798 0.294036865234375 +31799 0.311767578125 +31800 0.339141845703125 +31801 0.360260009765625 +31802 0.360504150390625 +31803 0.308380126953125 +31804 0.18170166015625 +31805 0.0047607421875 +31806 -0.17559814453125 +31807 -0.3143310546875 +31808 -0.36785888671875 +31809 -0.36248779296875 +31810 -0.343536376953125 +31811 -0.3018798828125 +31812 -0.231414794921875 +31813 -0.117645263671875 +31814 0.007049560546875 +31815 0.087982177734375 +31816 0.13946533203125 +31817 0.17425537109375 +31818 0.188201904296875 +31819 0.171234130859375 +31820 0.118438720703125 +31821 0.05706787109375 +31822 -0.010711669921875 +31823 -0.0914306640625 +31824 -0.162322998046875 +31825 -0.194549560546875 +31826 -0.1492919921875 +31827 -0.02166748046875 +31828 0.124053955078125 +31829 0.211151123046875 +31830 0.240447998046875 +31831 0.242218017578125 +31832 0.2257080078125 +31833 0.194366455078125 +31834 0.115509033203125 +31835 0.0128173828125 +31836 -0.053802490234375 +31837 -0.110626220703125 +31838 -0.199493408203125 +31839 -0.29437255859375 +31840 -0.33221435546875 +31841 -0.27972412109375 +31842 -0.185333251953125 +31843 -0.128204345703125 +31844 -0.115692138671875 +31845 -0.116455078125 +31846 -0.105926513671875 +31847 -0.053955078125 +31848 0.048797607421875 +31849 0.157318115234375 +31850 0.212005615234375 +31851 0.218475341796875 +31852 0.23724365234375 +31853 0.30535888671875 +31854 0.38128662109375 +31855 0.404449462890625 +31856 0.3944091796875 +31857 0.3885498046875 +31858 0.362640380859375 +31859 0.27362060546875 +31860 0.11712646484375 +31861 -0.054901123046875 +31862 -0.19085693359375 +31863 -0.28570556640625 +31864 -0.339263916015625 +31865 -0.3775634765625 +31866 -0.445709228515625 +31867 -0.535064697265625 +31868 -0.629058837890625 +31869 -0.697601318359375 +31870 -0.70391845703125 +31871 -0.6424560546875 +31872 -0.491241455078125 +31873 -0.265716552734375 +31874 -0.023712158203125 +31875 0.201751708984375 +31876 0.375823974609375 +31877 0.485076904296875 +31878 0.56884765625 +31879 0.634765625 +31880 0.63763427734375 +31881 0.5660400390625 +31882 0.4720458984375 +31883 0.40692138671875 +31884 0.3778076171875 +31885 0.376953125 +31886 0.371978759765625 +31887 0.313140869140625 +31888 0.184417724609375 +31889 0.011199951171875 +31890 -0.171051025390625 +31891 -0.33740234375 +31892 -0.47198486328125 +31893 -0.560394287109375 +31894 -0.58056640625 +31895 -0.54754638671875 +31896 -0.508575439453125 +31897 -0.459503173828125 +31898 -0.394378662109375 +31899 -0.35260009765625 +31900 -0.31170654296875 +31901 -0.197418212890625 +31902 -0.007965087890625 +31903 0.207489013671875 +31904 0.409210205078125 +31905 0.57208251953125 +31906 0.66595458984375 +31907 0.65875244140625 +31908 0.56744384765625 +31909 0.431396484375 +31910 0.29443359375 +31911 0.182464599609375 +31912 0.06365966796875 +31913 -0.075958251953125 +31914 -0.189422607421875 +31915 -0.271942138671875 +31916 -0.342529296875 +31917 -0.364166259765625 +31918 -0.327239990234375 +31919 -0.2769775390625 +31920 -0.253692626953125 +31921 -0.24365234375 +31922 -0.1983642578125 +31923 -0.116241455078125 +31924 -0.036834716796875 +31925 0.034881591796875 +31926 0.09124755859375 +31927 0.10888671875 +31928 0.125518798828125 +31929 0.15771484375 +31930 0.17828369140625 +31931 0.17108154296875 +31932 0.129974365234375 +31933 0.082427978515625 +31934 0.027679443359375 +31935 -0.065643310546875 +31936 -0.15936279296875 +31937 -0.21307373046875 +31938 -0.234649658203125 +31939 -0.2001953125 +31940 -0.119171142578125 +31941 -0.024749755859375 +31942 0.085784912109375 +31943 0.178131103515625 +31944 0.215576171875 +31945 0.211456298828125 +31946 0.17523193359375 +31947 0.128753662109375 +31948 0.1019287109375 +31949 0.0743408203125 +31950 0.04327392578125 +31951 0.038177490234375 +31952 0.076263427734375 +31953 0.14105224609375 +31954 0.186431884765625 +31955 0.188812255859375 +31956 0.1390380859375 +31957 0.041778564453125 +31958 -0.079437255859375 +31959 -0.219390869140625 +31960 -0.367828369140625 +31961 -0.494873046875 +31962 -0.556243896484375 +31963 -0.508697509765625 +31964 -0.3756103515625 +31965 -0.218902587890625 +31966 -0.063751220703125 +31967 0.091552734375 +31968 0.23602294921875 +31969 0.342987060546875 +31970 0.39520263671875 +31971 0.389373779296875 +31972 0.324249267578125 +31973 0.224090576171875 +31974 0.124267578125 +31975 0.037078857421875 +31976 -0.010101318359375 +31977 -0.019439697265625 +31978 -0.022796630859375 +31979 -0.001556396484375 +31980 0.056304931640625 +31981 0.106719970703125 +31982 0.096893310546875 +31983 0.042694091796875 +31984 -0.018035888671875 +31985 -0.07586669921875 +31986 -0.11944580078125 +31987 -0.15972900390625 +31988 -0.202606201171875 +31989 -0.24859619140625 +31990 -0.30517578125 +31991 -0.36212158203125 +31992 -0.39141845703125 +31993 -0.35528564453125 +31994 -0.249969482421875 +31995 -0.092864990234375 +31996 0.08905029296875 +31997 0.2352294921875 +31998 0.318817138671875 +31999 0.358642578125 +32000 0.347747802734375 +32001 0.28564453125 +32002 0.223175048828125 +32003 0.196746826171875 +32004 0.179840087890625 +32005 0.155548095703125 +32006 0.151214599609375 +32007 0.156951904296875 +32008 0.13177490234375 +32009 0.100799560546875 +32010 0.087127685546875 +32011 0.05487060546875 +32012 -0.009002685546875 +32013 -0.10400390625 +32014 -0.229400634765625 +32015 -0.35552978515625 +32016 -0.441925048828125 +32017 -0.473846435546875 +32018 -0.464813232421875 +32019 -0.419097900390625 +32020 -0.334320068359375 +32021 -0.227935791015625 +32022 -0.12347412109375 +32023 -0.02764892578125 +32024 0.077667236328125 +32025 0.2132568359375 +32026 0.38885498046875 +32027 0.582794189453125 +32028 0.734039306640625 +32029 0.800140380859375 +32030 0.7783203125 +32031 0.6651611328125 +32032 0.45965576171875 +32033 0.199188232421875 +32034 -0.050689697265625 +32035 -0.23297119140625 +32036 -0.33013916015625 +32037 -0.368408203125 +32038 -0.378936767578125 +32039 -0.376983642578125 +32040 -0.37969970703125 +32041 -0.391510009765625 +32042 -0.385345458984375 +32043 -0.3419189453125 +32044 -0.28289794921875 +32045 -0.251617431640625 +32046 -0.266143798828125 +32047 -0.273345947265625 +32048 -0.216796875 +32049 -0.128265380859375 +32050 -0.068145751953125 +32051 -0.0430908203125 +32052 -0.024444580078125 +32053 0.020721435546875 +32054 0.124481201171875 +32055 0.25787353515625 +32056 0.379119873046875 +32057 0.47991943359375 +32058 0.5281982421875 +32059 0.511138916015625 +32060 0.456207275390625 +32061 0.407470703125 +32062 0.383758544921875 +32063 0.35687255859375 +32064 0.31182861328125 +32065 0.250885009765625 +32066 0.1654052734375 +32067 0.035247802734375 +32068 -0.142059326171875 +32069 -0.33563232421875 +32070 -0.5345458984375 +32071 -0.72186279296875 +32072 -0.836669921875 +32073 -0.8326416015625 +32074 -0.7296142578125 +32075 -0.582550048828125 +32076 -0.440093994140625 +32077 -0.324310302734375 +32078 -0.20147705078125 +32079 -0.044647216796875 +32080 0.103973388671875 +32081 0.202392578125 +32082 0.264495849609375 +32083 0.338897705078125 +32084 0.443817138671875 +32085 0.545074462890625 +32086 0.6173095703125 +32087 0.6524658203125 +32088 0.66339111328125 +32089 0.6561279296875 +32090 0.606781005859375 +32091 0.501190185546875 +32092 0.352783203125 +32093 0.176544189453125 +32094 -0.034820556640625 +32095 -0.258209228515625 +32096 -0.44244384765625 +32097 -0.5753173828125 +32098 -0.65203857421875 +32099 -0.641632080078125 +32100 -0.562164306640625 +32101 -0.458038330078125 +32102 -0.350555419921875 +32103 -0.260528564453125 +32104 -0.192108154296875 +32105 -0.141937255859375 +32106 -0.1021728515625 +32107 -0.062896728515625 +32108 -0.011932373046875 +32109 0.062835693359375 +32110 0.148712158203125 +32111 0.241729736328125 +32112 0.34912109375 +32113 0.457305908203125 +32114 0.54388427734375 +32115 0.5728759765625 +32116 0.506591796875 +32117 0.351226806640625 +32118 0.146514892578125 +32119 -0.05523681640625 +32120 -0.21624755859375 +32121 -0.334930419921875 +32122 -0.402984619140625 +32123 -0.4412841796875 +32124 -0.49578857421875 +32125 -0.5601806640625 +32126 -0.600738525390625 +32127 -0.584228515625 +32128 -0.47930908203125 +32129 -0.27935791015625 +32130 -0.0089111328125 +32131 0.268798828125 +32132 0.482818603515625 +32133 0.60369873046875 +32134 0.650421142578125 +32135 0.66400146484375 +32136 0.6414794921875 +32137 0.572540283203125 +32138 0.498138427734375 +32139 0.439453125 +32140 0.375518798828125 +32141 0.274505615234375 +32142 0.1087646484375 +32143 -0.099395751953125 +32144 -0.3182373046875 +32145 -0.5489501953125 +32146 -0.7738037109375 +32147 -0.86383056640625 +32148 -0.870391845703125 +32149 -0.86895751953125 +32150 -0.861053466796875 +32151 -0.765869140625 +32152 -0.5301513671875 +32153 -0.214691162109375 +32154 0.137359619140625 +32155 0.474822998046875 +32156 0.76239013671875 +32157 0.867462158203125 +32158 0.870361328125 +32159 0.86480712890625 +32160 0.831817626953125 +32161 0.677581787109375 +32162 0.495880126953125 +32163 0.30767822265625 +32164 0.116180419921875 +32165 -0.110748291015625 +32166 -0.381805419921875 +32167 -0.6572265625 +32168 -0.857421875 +32169 -0.870391845703125 +32170 -0.870391845703125 +32171 -0.86444091796875 +32172 -0.85723876953125 +32173 -0.790008544921875 +32174 -0.62847900390625 +32175 -0.3956298828125 +32176 -0.126708984375 +32177 0.150115966796875 +32178 0.424041748046875 +32179 0.670623779296875 +32180 0.854522705078125 +32181 0.866485595703125 +32182 0.86920166015625 +32183 0.8653564453125 +32184 0.857147216796875 +32185 0.766845703125 +32186 0.628509521484375 +32187 0.462127685546875 +32188 0.297210693359375 +32189 0.14862060546875 +32190 -0.00537109375 +32191 -0.15753173828125 +32192 -0.31304931640625 +32193 -0.48876953125 +32194 -0.6416015625 +32195 -0.751373291015625 +32196 -0.84619140625 +32197 -0.861297607421875 +32198 -0.863250732421875 +32199 -0.856597900390625 +32200 -0.7498779296875 +32201 -0.624542236328125 +32202 -0.47808837890625 +32203 -0.253387451171875 +32204 0.003692626953125 +32205 0.2257080078125 +32206 0.427154541015625 +32207 0.643218994140625 +32208 0.855926513671875 +32209 0.870361328125 +32210 0.870361328125 +32211 0.862762451171875 +32212 0.79669189453125 +32213 0.595794677734375 +32214 0.362152099609375 +32215 0.1270751953125 +32216 -0.086944580078125 +32217 -0.2784423828125 +32218 -0.484832763671875 +32219 -0.729583740234375 +32220 -0.86688232421875 +32221 -0.870391845703125 +32222 -0.86859130859375 +32223 -0.86279296875 +32224 -0.817962646484375 +32225 -0.6116943359375 +32226 -0.3128662109375 +32227 0.039398193359375 +32228 0.422821044921875 +32229 0.805145263671875 +32230 0.870361328125 +32231 0.870361328125 +32232 0.860015869140625 +32233 0.727935791015625 +32234 0.48114013671875 +32235 0.2059326171875 +32236 -0.06103515625 +32237 -0.29913330078125 +32238 -0.516204833984375 +32239 -0.7252197265625 +32240 -0.85980224609375 +32241 -0.870391845703125 +32242 -0.870391845703125 +32243 -0.858062744140625 +32244 -0.673004150390625 +32245 -0.42694091796875 +32246 -0.2100830078125 +32247 -0.0362548828125 +32248 0.10943603515625 +32249 0.23516845703125 +32250 0.373687744140625 +32251 0.517791748046875 +32252 0.602783203125 +32253 0.635711669921875 +32254 0.655181884765625 +32255 0.65948486328125 +32256 0.651275634765625 +32257 0.61846923828125 +32258 0.53753662109375 +32259 0.404144287109375 +32260 0.22186279296875 +32261 0.003997802734375 +32262 -0.22100830078125 +32263 -0.42449951171875 +32264 -0.579833984375 +32265 -0.641876220703125 +32266 -0.6177978515625 +32267 -0.575531005859375 +32268 -0.526336669921875 +32269 -0.42645263671875 +32270 -0.2581787109375 +32271 -0.068695068359375 +32272 0.09222412109375 +32273 0.232147216796875 +32274 0.3509521484375 +32275 0.410064697265625 +32276 0.372955322265625 +32277 0.2554931640625 +32278 0.10711669921875 +32279 -0.052886962890625 +32280 -0.186279296875 +32281 -0.23291015625 +32282 -0.209442138671875 +32283 -0.174163818359375 +32284 -0.126739501953125 +32285 -0.048126220703125 +32286 0.0426025390625 +32287 0.10748291015625 +32288 0.1409912109375 +32289 0.19708251953125 +32290 0.273651123046875 +32291 0.31768798828125 +32292 0.341094970703125 +32293 0.368011474609375 +32294 0.37249755859375 +32295 0.30072021484375 +32296 0.1517333984375 +32297 -0.01470947265625 +32298 -0.1883544921875 +32299 -0.372711181640625 +32300 -0.51397705078125 +32301 -0.57177734375 +32302 -0.53948974609375 +32303 -0.43511962890625 +32304 -0.2962646484375 +32305 -0.161102294921875 +32306 -0.0435791015625 +32307 0.060394287109375 +32308 0.13665771484375 +32309 0.170135498046875 +32310 0.16552734375 +32311 0.15728759765625 +32312 0.150787353515625 +32313 0.12200927734375 +32314 0.080108642578125 +32315 0.05126953125 +32316 0.062896728515625 +32317 0.09271240234375 +32318 0.092987060546875 +32319 0.07855224609375 +32320 0.06427001953125 +32321 0.0347900390625 +32322 -0.01171875 +32323 -0.056060791015625 +32324 -0.055511474609375 +32325 -0.010467529296875 +32326 0.02508544921875 +32327 0.025665283203125 +32328 0.017333984375 +32329 0.00189208984375 +32330 -0.03173828125 +32331 -0.071502685546875 +32332 -0.13543701171875 +32333 -0.219970703125 +32334 -0.300506591796875 +32335 -0.376312255859375 +32336 -0.416107177734375 +32337 -0.371124267578125 +32338 -0.242279052734375 +32339 -0.069732666015625 +32340 0.125640869140625 +32341 0.31268310546875 +32342 0.45501708984375 +32343 0.554779052734375 +32344 0.61065673828125 +32345 0.610931396484375 +32346 0.531463623046875 +32347 0.3883056640625 +32348 0.23468017578125 +32349 0.095245361328125 +32350 -0.00396728515625 +32351 -0.04852294921875 +32352 -0.055145263671875 +32353 -0.0758056640625 +32354 -0.138702392578125 +32355 -0.209197998046875 +32356 -0.289031982421875 +32357 -0.37884521484375 +32358 -0.456329345703125 +32359 -0.51641845703125 +32360 -0.519287109375 +32361 -0.458251953125 +32362 -0.384796142578125 +32363 -0.323699951171875 +32364 -0.269287109375 +32365 -0.1951904296875 +32366 -0.100006103515625 +32367 -0.01055908203125 +32368 0.1033935546875 +32369 0.24908447265625 +32370 0.373199462890625 +32371 0.45806884765625 +32372 0.511474609375 +32373 0.565399169921875 +32374 0.61138916015625 +32375 0.5897216796875 +32376 0.4906005859375 +32377 0.33148193359375 +32378 0.147796630859375 +32379 -0.01873779296875 +32380 -0.140289306640625 +32381 -0.191986083984375 +32382 -0.184295654296875 +32383 -0.161834716796875 +32384 -0.166595458984375 +32385 -0.19390869140625 +32386 -0.22442626953125 +32387 -0.279754638671875 +32388 -0.3389892578125 +32389 -0.3543701171875 +32390 -0.348175048828125 +32391 -0.32598876953125 +32392 -0.2581787109375 +32393 -0.139801025390625 +32394 0.014617919921875 +32395 0.144378662109375 +32396 0.221038818359375 +32397 0.27069091796875 +32398 0.294036865234375 +32399 0.311767578125 +32400 0.339141845703125 +32401 0.360260009765625 +32402 0.360504150390625 +32403 0.308380126953125 +32404 0.18170166015625 +32405 0.0047607421875 +32406 -0.17559814453125 +32407 -0.3143310546875 +32408 -0.36785888671875 +32409 -0.36248779296875 +32410 -0.343536376953125 +32411 -0.3018798828125 +32412 -0.231414794921875 +32413 -0.117645263671875 +32414 0.007049560546875 +32415 0.087982177734375 +32416 0.13946533203125 +32417 0.17425537109375 +32418 0.188201904296875 +32419 0.171234130859375 +32420 0.118438720703125 +32421 0.05706787109375 +32422 -0.010711669921875 +32423 -0.0914306640625 +32424 -0.162322998046875 +32425 -0.194549560546875 +32426 -0.1492919921875 +32427 -0.02166748046875 +32428 0.124053955078125 +32429 0.211151123046875 +32430 0.240447998046875 +32431 0.242218017578125 +32432 0.2257080078125 +32433 0.194366455078125 +32434 0.115509033203125 +32435 0.0128173828125 +32436 -0.053802490234375 +32437 -0.110626220703125 +32438 -0.199493408203125 +32439 -0.29437255859375 +32440 -0.33221435546875 +32441 -0.27972412109375 +32442 -0.185333251953125 +32443 -0.128204345703125 +32444 -0.115692138671875 +32445 -0.116455078125 +32446 -0.105926513671875 +32447 -0.053955078125 +32448 0.048797607421875 +32449 0.157318115234375 +32450 0.212005615234375 +32451 0.218475341796875 +32452 0.23724365234375 +32453 0.30535888671875 +32454 0.38128662109375 +32455 0.404449462890625 +32456 0.3944091796875 +32457 0.3885498046875 +32458 0.362640380859375 +32459 0.27362060546875 +32460 0.11712646484375 +32461 -0.054901123046875 +32462 -0.19085693359375 +32463 -0.28570556640625 +32464 -0.339263916015625 +32465 -0.3775634765625 +32466 -0.445709228515625 +32467 -0.535064697265625 +32468 -0.629058837890625 +32469 -0.697601318359375 +32470 -0.70391845703125 +32471 -0.6424560546875 +32472 -0.491241455078125 +32473 -0.265716552734375 +32474 -0.023712158203125 +32475 0.201751708984375 +32476 0.375823974609375 +32477 0.485076904296875 +32478 0.56884765625 +32479 0.634765625 +32480 0.63763427734375 +32481 0.5660400390625 +32482 0.4720458984375 +32483 0.40692138671875 +32484 0.3778076171875 +32485 0.376953125 +32486 0.371978759765625 +32487 0.313140869140625 +32488 0.184417724609375 +32489 0.011199951171875 +32490 -0.171051025390625 +32491 -0.33740234375 +32492 -0.47198486328125 +32493 -0.560394287109375 +32494 -0.58056640625 +32495 -0.54754638671875 +32496 -0.508575439453125 +32497 -0.459503173828125 +32498 -0.394378662109375 +32499 -0.35260009765625 +32500 -0.31170654296875 +32501 -0.197418212890625 +32502 -0.007965087890625 +32503 0.207489013671875 +32504 0.409210205078125 +32505 0.57208251953125 +32506 0.66595458984375 +32507 0.65875244140625 +32508 0.56744384765625 +32509 0.431396484375 +32510 0.29443359375 +32511 0.182464599609375 +32512 0.06365966796875 +32513 -0.075958251953125 +32514 -0.189422607421875 +32515 -0.271942138671875 +32516 -0.342529296875 +32517 -0.364166259765625 +32518 -0.327239990234375 +32519 -0.2769775390625 +32520 -0.253692626953125 +32521 -0.24365234375 +32522 -0.1983642578125 +32523 -0.116241455078125 +32524 -0.036834716796875 +32525 0.034881591796875 +32526 0.09124755859375 +32527 0.10888671875 +32528 0.125518798828125 +32529 0.15771484375 +32530 0.17828369140625 +32531 0.17108154296875 +32532 0.129974365234375 +32533 0.082427978515625 +32534 0.027679443359375 +32535 -0.065643310546875 +32536 -0.15936279296875 +32537 -0.21307373046875 +32538 -0.234649658203125 +32539 -0.2001953125 +32540 -0.119171142578125 +32541 -0.024749755859375 +32542 0.085784912109375 +32543 0.178131103515625 +32544 0.215576171875 +32545 0.211456298828125 +32546 0.17523193359375 +32547 0.128753662109375 +32548 0.1019287109375 +32549 0.0743408203125 +32550 0.04327392578125 +32551 0.038177490234375 +32552 0.076263427734375 +32553 0.14105224609375 +32554 0.186431884765625 +32555 0.188812255859375 +32556 0.1390380859375 +32557 0.041778564453125 +32558 -0.079437255859375 +32559 -0.219390869140625 +32560 -0.367828369140625 +32561 -0.494873046875 +32562 -0.556243896484375 +32563 -0.508697509765625 +32564 -0.3756103515625 +32565 -0.218902587890625 +32566 -0.063751220703125 +32567 0.091552734375 +32568 0.23602294921875 +32569 0.342987060546875 +32570 0.39520263671875 +32571 0.389373779296875 +32572 0.324249267578125 +32573 0.224090576171875 +32574 0.124267578125 +32575 0.037078857421875 +32576 -0.010101318359375 +32577 -0.019439697265625 +32578 -0.022796630859375 +32579 -0.001556396484375 +32580 0.056304931640625 +32581 0.106719970703125 +32582 0.096893310546875 +32583 0.042694091796875 +32584 -0.018035888671875 +32585 -0.07586669921875 +32586 -0.11944580078125 +32587 -0.15972900390625 +32588 -0.202606201171875 +32589 -0.24859619140625 +32590 -0.30517578125 +32591 -0.36212158203125 +32592 -0.39141845703125 +32593 -0.35528564453125 +32594 -0.249969482421875 +32595 -0.092864990234375 +32596 0.08905029296875 +32597 0.2352294921875 +32598 0.318817138671875 +32599 0.358642578125 +32600 0.347747802734375 +32601 0.28564453125 +32602 0.223175048828125 +32603 0.196746826171875 +32604 0.179840087890625 +32605 0.155548095703125 +32606 0.151214599609375 +32607 0.156951904296875 +32608 0.13177490234375 +32609 0.100799560546875 +32610 0.087127685546875 +32611 0.05487060546875 +32612 -0.009002685546875 +32613 -0.10400390625 +32614 -0.229400634765625 +32615 -0.35552978515625 +32616 -0.441925048828125 +32617 -0.473846435546875 +32618 -0.464813232421875 +32619 -0.419097900390625 +32620 -0.334320068359375 +32621 -0.227935791015625 +32622 -0.12347412109375 +32623 -0.02764892578125 +32624 0.077667236328125 +32625 0.2132568359375 +32626 0.38885498046875 +32627 0.582794189453125 +32628 0.734039306640625 +32629 0.800140380859375 +32630 0.7783203125 +32631 0.6651611328125 +32632 0.45965576171875 +32633 0.199188232421875 +32634 -0.050689697265625 +32635 -0.23297119140625 +32636 -0.33013916015625 +32637 -0.368408203125 +32638 -0.378936767578125 +32639 -0.376983642578125 +32640 -0.37969970703125 +32641 -0.391510009765625 +32642 -0.385345458984375 +32643 -0.3419189453125 +32644 -0.28289794921875 +32645 -0.251617431640625 +32646 -0.266143798828125 +32647 -0.273345947265625 +32648 -0.216796875 +32649 -0.128265380859375 +32650 -0.068145751953125 +32651 -0.0430908203125 +32652 -0.024444580078125 +32653 0.020721435546875 +32654 0.124481201171875 +32655 0.25787353515625 +32656 0.379119873046875 +32657 0.47991943359375 +32658 0.5281982421875 +32659 0.511138916015625 +32660 0.456207275390625 +32661 0.407470703125 +32662 0.383758544921875 +32663 0.35687255859375 +32664 0.31182861328125 +32665 0.250885009765625 +32666 0.1654052734375 +32667 0.035247802734375 +32668 -0.142059326171875 +32669 -0.33563232421875 +32670 -0.5345458984375 +32671 -0.72186279296875 +32672 -0.836669921875 +32673 -0.8326416015625 +32674 -0.7296142578125 +32675 -0.582550048828125 +32676 -0.440093994140625 +32677 -0.324310302734375 +32678 -0.20147705078125 +32679 -0.044647216796875 +32680 0.103973388671875 +32681 0.202392578125 +32682 0.264495849609375 +32683 0.338897705078125 +32684 0.443817138671875 +32685 0.545074462890625 +32686 0.6173095703125 +32687 0.6524658203125 +32688 0.66339111328125 +32689 0.6561279296875 +32690 0.606781005859375 +32691 0.501190185546875 +32692 0.352783203125 +32693 0.176544189453125 +32694 -0.034820556640625 +32695 -0.258209228515625 +32696 -0.44244384765625 +32697 -0.5753173828125 +32698 -0.65203857421875 +32699 -0.641632080078125 +32700 -0.562164306640625 +32701 -0.458038330078125 +32702 -0.350555419921875 +32703 -0.260528564453125 +32704 -0.192108154296875 +32705 -0.141937255859375 +32706 -0.1021728515625 +32707 -0.062896728515625 +32708 -0.011932373046875 +32709 0.062835693359375 +32710 0.148712158203125 +32711 0.241729736328125 +32712 0.34912109375 +32713 0.457305908203125 +32714 0.54388427734375 +32715 0.5728759765625 +32716 0.506591796875 +32717 0.351226806640625 +32718 0.146514892578125 +32719 -0.05523681640625 +32720 -0.21624755859375 +32721 -0.334930419921875 +32722 -0.402984619140625 +32723 -0.4412841796875 +32724 -0.49578857421875 +32725 -0.5601806640625 +32726 -0.600738525390625 +32727 -0.584228515625 +32728 -0.47930908203125 +32729 -0.27935791015625 +32730 -0.0089111328125 +32731 0.268798828125 +32732 0.482818603515625 +32733 0.60369873046875 +32734 0.650421142578125 +32735 0.66400146484375 +32736 0.6414794921875 +32737 0.572540283203125 +32738 0.498138427734375 +32739 0.439453125 +32740 0.375518798828125 +32741 0.274505615234375 +32742 0.1087646484375 +32743 -0.099395751953125 +32744 -0.3182373046875 +32745 -0.5489501953125 +32746 -0.7738037109375 +32747 -0.86383056640625 +32748 -0.870391845703125 +32749 -0.86895751953125 +32750 -0.861053466796875 +32751 -0.765869140625 +32752 -0.5301513671875 +32753 -0.214691162109375 +32754 0.137359619140625 +32755 0.474822998046875 +32756 0.76239013671875 +32757 0.867462158203125 +32758 0.870361328125 +32759 0.86480712890625 +32760 0.831817626953125 +32761 0.677581787109375 +32762 0.495880126953125 +32763 0.30767822265625 +32764 0.116180419921875 +32765 -0.110748291015625 +32766 -0.381805419921875 +32767 -0.6572265625 +32768 -0.857421875 +32769 -0.870391845703125 +32770 -0.870391845703125 +32771 -0.86444091796875 +32772 -0.85723876953125 +32773 -0.790008544921875 +32774 -0.62847900390625 +32775 -0.3956298828125 +32776 -0.126708984375 +32777 0.150115966796875 +32778 0.424041748046875 +32779 0.670623779296875 +32780 0.854522705078125 +32781 0.866485595703125 +32782 0.86920166015625 +32783 0.8653564453125 +32784 0.857147216796875 +32785 0.766845703125 +32786 0.628509521484375 +32787 0.462127685546875 +32788 0.297210693359375 +32789 0.14862060546875 +32790 -0.00537109375 +32791 -0.15753173828125 +32792 -0.31304931640625 +32793 -0.48876953125 +32794 -0.6416015625 +32795 -0.751373291015625 +32796 -0.84619140625 +32797 -0.861297607421875 +32798 -0.863250732421875 +32799 -0.856597900390625 +32800 -0.7498779296875 +32801 -0.624542236328125 +32802 -0.47808837890625 +32803 -0.253387451171875 +32804 0.003692626953125 +32805 0.2257080078125 +32806 0.427154541015625 +32807 0.643218994140625 +32808 0.855926513671875 +32809 0.870361328125 +32810 0.870361328125 +32811 0.862762451171875 +32812 0.79669189453125 +32813 0.595794677734375 +32814 0.362152099609375 +32815 0.1270751953125 +32816 -0.086944580078125 +32817 -0.2784423828125 +32818 -0.484832763671875 +32819 -0.729583740234375 +32820 -0.86688232421875 +32821 -0.870391845703125 +32822 -0.86859130859375 +32823 -0.86279296875 +32824 -0.817962646484375 +32825 -0.6116943359375 +32826 -0.3128662109375 +32827 0.039398193359375 +32828 0.422821044921875 +32829 0.805145263671875 +32830 0.870361328125 +32831 0.870361328125 +32832 0.860015869140625 +32833 0.727935791015625 +32834 0.48114013671875 +32835 0.2059326171875 +32836 -0.06103515625 +32837 -0.29913330078125 +32838 -0.516204833984375 +32839 -0.7252197265625 +32840 -0.85980224609375 +32841 -0.870391845703125 +32842 -0.870391845703125 +32843 -0.858062744140625 +32844 -0.673004150390625 +32845 -0.42694091796875 +32846 -0.2100830078125 +32847 -0.0362548828125 +32848 0.10943603515625 +32849 0.23516845703125 +32850 0.373687744140625 +32851 0.517791748046875 +32852 0.602783203125 +32853 0.635711669921875 +32854 0.655181884765625 +32855 0.65948486328125 +32856 0.651275634765625 +32857 0.61846923828125 +32858 0.53753662109375 +32859 0.404144287109375 +32860 0.22186279296875 +32861 0.003997802734375 +32862 -0.22100830078125 +32863 -0.42449951171875 +32864 -0.579833984375 +32865 -0.641876220703125 +32866 -0.6177978515625 +32867 -0.575531005859375 +32868 -0.526336669921875 +32869 -0.42645263671875 +32870 -0.2581787109375 +32871 -0.068695068359375 +32872 0.09222412109375 +32873 0.232147216796875 +32874 0.3509521484375 +32875 0.410064697265625 +32876 0.372955322265625 +32877 0.2554931640625 +32878 0.10711669921875 +32879 -0.052886962890625 +32880 -0.186279296875 +32881 -0.23291015625 +32882 -0.209442138671875 +32883 -0.174163818359375 +32884 -0.126739501953125 +32885 -0.048126220703125 +32886 0.0426025390625 +32887 0.10748291015625 +32888 0.1409912109375 +32889 0.19708251953125 +32890 0.273651123046875 +32891 0.31768798828125 +32892 0.341094970703125 +32893 0.368011474609375 +32894 0.37249755859375 +32895 0.30072021484375 +32896 0.1517333984375 +32897 -0.01470947265625 +32898 -0.1883544921875 +32899 -0.372711181640625 +32900 -0.51397705078125 +32901 -0.57177734375 +32902 -0.53948974609375 +32903 -0.43511962890625 +32904 -0.2962646484375 +32905 -0.161102294921875 +32906 -0.0435791015625 +32907 0.060394287109375 +32908 0.13665771484375 +32909 0.170135498046875 +32910 0.16552734375 +32911 0.15728759765625 +32912 0.150787353515625 +32913 0.12200927734375 +32914 0.080108642578125 +32915 0.05126953125 +32916 0.062896728515625 +32917 0.09271240234375 +32918 0.092987060546875 +32919 0.07855224609375 +32920 0.06427001953125 +32921 0.0347900390625 +32922 -0.01171875 +32923 -0.056060791015625 +32924 -0.055511474609375 +32925 -0.010467529296875 +32926 0.02508544921875 +32927 0.025665283203125 +32928 0.017333984375 +32929 0.00189208984375 +32930 -0.03173828125 +32931 -0.071502685546875 +32932 -0.13543701171875 +32933 -0.219970703125 +32934 -0.300506591796875 +32935 -0.376312255859375 +32936 -0.416107177734375 +32937 -0.371124267578125 +32938 -0.242279052734375 +32939 -0.069732666015625 +32940 0.125640869140625 +32941 0.31268310546875 +32942 0.45501708984375 +32943 0.554779052734375 +32944 0.61065673828125 +32945 0.610931396484375 +32946 0.531463623046875 +32947 0.3883056640625 +32948 0.23468017578125 +32949 0.095245361328125 +32950 -0.00396728515625 +32951 -0.04852294921875 +32952 -0.055145263671875 +32953 -0.0758056640625 +32954 -0.138702392578125 +32955 -0.209197998046875 +32956 -0.289031982421875 +32957 -0.37884521484375 +32958 -0.456329345703125 +32959 -0.51641845703125 +32960 -0.519287109375 +32961 -0.458251953125 +32962 -0.384796142578125 +32963 -0.323699951171875 +32964 -0.269287109375 +32965 -0.1951904296875 +32966 -0.100006103515625 +32967 -0.01055908203125 +32968 0.1033935546875 +32969 0.24908447265625 +32970 0.373199462890625 +32971 0.45806884765625 +32972 0.511474609375 +32973 0.565399169921875 +32974 0.61138916015625 +32975 0.5897216796875 +32976 0.4906005859375 +32977 0.33148193359375 +32978 0.147796630859375 +32979 -0.01873779296875 +32980 -0.140289306640625 +32981 -0.191986083984375 +32982 -0.184295654296875 +32983 -0.161834716796875 +32984 -0.166595458984375 +32985 -0.19390869140625 +32986 -0.22442626953125 +32987 -0.279754638671875 +32988 -0.3389892578125 +32989 -0.3543701171875 +32990 -0.348175048828125 +32991 -0.32598876953125 +32992 -0.2581787109375 +32993 -0.139801025390625 +32994 0.014617919921875 +32995 0.144378662109375 +32996 0.221038818359375 +32997 0.27069091796875 +32998 0.294036865234375 +32999 0.311767578125 +33000 0.339141845703125 +33001 0.360260009765625 +33002 0.360504150390625 +33003 0.308380126953125 +33004 0.18170166015625 +33005 0.0047607421875 +33006 -0.17559814453125 +33007 -0.3143310546875 +33008 -0.36785888671875 +33009 -0.36248779296875 +33010 -0.343536376953125 +33011 -0.3018798828125 +33012 -0.231414794921875 +33013 -0.117645263671875 +33014 0.007049560546875 +33015 0.087982177734375 +33016 0.13946533203125 +33017 0.17425537109375 +33018 0.188201904296875 +33019 0.171234130859375 +33020 0.118438720703125 +33021 0.05706787109375 +33022 -0.010711669921875 +33023 -0.0914306640625 +33024 -0.162322998046875 +33025 -0.194549560546875 +33026 -0.1492919921875 +33027 -0.02166748046875 +33028 0.124053955078125 +33029 0.211151123046875 +33030 0.240447998046875 +33031 0.242218017578125 +33032 0.2257080078125 +33033 0.194366455078125 +33034 0.115509033203125 +33035 0.0128173828125 +33036 -0.053802490234375 +33037 -0.110626220703125 +33038 -0.199493408203125 +33039 -0.29437255859375 +33040 -0.33221435546875 +33041 -0.27972412109375 +33042 -0.185333251953125 +33043 -0.128204345703125 +33044 -0.115692138671875 +33045 -0.116455078125 +33046 -0.105926513671875 +33047 -0.053955078125 +33048 0.048797607421875 +33049 0.157318115234375 +33050 0.212005615234375 +33051 0.218475341796875 +33052 0.23724365234375 +33053 0.30535888671875 +33054 0.38128662109375 +33055 0.404449462890625 +33056 0.3944091796875 +33057 0.3885498046875 +33058 0.362640380859375 +33059 0.27362060546875 +33060 0.11712646484375 +33061 -0.054901123046875 +33062 -0.19085693359375 +33063 -0.28570556640625 +33064 -0.339263916015625 +33065 -0.3775634765625 +33066 -0.445709228515625 +33067 -0.535064697265625 +33068 -0.629058837890625 +33069 -0.697601318359375 +33070 -0.70391845703125 +33071 -0.6424560546875 +33072 -0.491241455078125 +33073 -0.265716552734375 +33074 -0.023712158203125 +33075 0.201751708984375 +33076 0.375823974609375 +33077 0.485076904296875 +33078 0.56884765625 +33079 0.634765625 +33080 0.63763427734375 +33081 0.5660400390625 +33082 0.4720458984375 +33083 0.40692138671875 +33084 0.3778076171875 +33085 0.376953125 +33086 0.371978759765625 +33087 0.313140869140625 +33088 0.184417724609375 +33089 0.011199951171875 +33090 -0.171051025390625 +33091 -0.33740234375 +33092 -0.47198486328125 +33093 -0.560394287109375 +33094 -0.58056640625 +33095 -0.54754638671875 +33096 -0.508575439453125 +33097 -0.459503173828125 +33098 -0.394378662109375 +33099 -0.35260009765625 +33100 -0.31170654296875 +33101 -0.197418212890625 +33102 -0.007965087890625 +33103 0.207489013671875 +33104 0.409210205078125 +33105 0.57208251953125 +33106 0.66595458984375 +33107 0.65875244140625 +33108 0.56744384765625 +33109 0.431396484375 +33110 0.29443359375 +33111 0.182464599609375 +33112 0.06365966796875 +33113 -0.075958251953125 +33114 -0.189422607421875 +33115 -0.271942138671875 +33116 -0.342529296875 +33117 -0.364166259765625 +33118 -0.327239990234375 +33119 -0.2769775390625 +33120 -0.253692626953125 +33121 -0.24365234375 +33122 -0.1983642578125 +33123 -0.116241455078125 +33124 -0.036834716796875 +33125 0.034881591796875 +33126 0.09124755859375 +33127 0.10888671875 +33128 0.125518798828125 +33129 0.15771484375 +33130 0.17828369140625 +33131 0.17108154296875 +33132 0.129974365234375 +33133 0.082427978515625 +33134 0.027679443359375 +33135 -0.065643310546875 +33136 -0.15936279296875 +33137 -0.21307373046875 +33138 -0.234649658203125 +33139 -0.2001953125 +33140 -0.119171142578125 +33141 -0.024749755859375 +33142 0.085784912109375 +33143 0.178131103515625 +33144 0.215576171875 +33145 0.211456298828125 +33146 0.17523193359375 +33147 0.128753662109375 +33148 0.1019287109375 +33149 0.0743408203125 +33150 0.04327392578125 +33151 0.038177490234375 +33152 0.076263427734375 +33153 0.14105224609375 +33154 0.186431884765625 +33155 0.188812255859375 +33156 0.1390380859375 +33157 0.041778564453125 +33158 -0.079437255859375 +33159 -0.219390869140625 +33160 -0.367828369140625 +33161 -0.494873046875 +33162 -0.556243896484375 +33163 -0.508697509765625 +33164 -0.3756103515625 +33165 -0.218902587890625 +33166 -0.063751220703125 +33167 0.091552734375 +33168 0.23602294921875 +33169 0.342987060546875 +33170 0.39520263671875 +33171 0.389373779296875 +33172 0.324249267578125 +33173 0.224090576171875 +33174 0.124267578125 +33175 0.037078857421875 +33176 -0.010101318359375 +33177 -0.019439697265625 +33178 -0.022796630859375 +33179 -0.001556396484375 +33180 0.056304931640625 +33181 0.106719970703125 +33182 0.096893310546875 +33183 0.042694091796875 +33184 -0.018035888671875 +33185 -0.07586669921875 +33186 -0.11944580078125 +33187 -0.15972900390625 +33188 -0.202606201171875 +33189 -0.24859619140625 +33190 -0.30517578125 +33191 -0.36212158203125 +33192 -0.39141845703125 +33193 -0.35528564453125 +33194 -0.249969482421875 +33195 -0.092864990234375 +33196 0.08905029296875 +33197 0.2352294921875 +33198 0.318817138671875 +33199 0.358642578125 +33200 0.347747802734375 +33201 0.28564453125 +33202 0.223175048828125 +33203 0.196746826171875 +33204 0.179840087890625 +33205 0.155548095703125 +33206 0.151214599609375 +33207 0.156951904296875 +33208 0.13177490234375 +33209 0.100799560546875 +33210 0.087127685546875 +33211 0.05487060546875 +33212 -0.009002685546875 +33213 -0.10400390625 +33214 -0.229400634765625 +33215 -0.35552978515625 +33216 -0.441925048828125 +33217 -0.473846435546875 +33218 -0.464813232421875 +33219 -0.419097900390625 +33220 -0.334320068359375 +33221 -0.227935791015625 +33222 -0.12347412109375 +33223 -0.02764892578125 +33224 0.077667236328125 +33225 0.2132568359375 +33226 0.38885498046875 +33227 0.582794189453125 +33228 0.734039306640625 +33229 0.800140380859375 +33230 0.7783203125 +33231 0.6651611328125 +33232 0.45965576171875 +33233 0.199188232421875 +33234 -0.050689697265625 +33235 -0.23297119140625 +33236 -0.33013916015625 +33237 -0.368408203125 +33238 -0.378936767578125 +33239 -0.376983642578125 +33240 -0.37969970703125 +33241 -0.391510009765625 +33242 -0.385345458984375 +33243 -0.3419189453125 +33244 -0.28289794921875 +33245 -0.251617431640625 +33246 -0.266143798828125 +33247 -0.273345947265625 +33248 -0.216796875 +33249 -0.128265380859375 +33250 -0.068145751953125 +33251 -0.0430908203125 +33252 -0.024444580078125 +33253 0.020721435546875 +33254 0.124481201171875 +33255 0.25787353515625 +33256 0.379119873046875 +33257 0.47991943359375 +33258 0.5281982421875 +33259 0.511138916015625 +33260 0.456207275390625 +33261 0.407470703125 +33262 0.383758544921875 +33263 0.35687255859375 +33264 0.31182861328125 +33265 0.250885009765625 +33266 0.1654052734375 +33267 0.035247802734375 +33268 -0.142059326171875 +33269 -0.33563232421875 +33270 -0.5345458984375 +33271 -0.72186279296875 +33272 -0.836669921875 +33273 -0.8326416015625 +33274 -0.7296142578125 +33275 -0.582550048828125 +33276 -0.440093994140625 +33277 -0.324310302734375 +33278 -0.20147705078125 +33279 -0.044647216796875 +33280 0.103973388671875 +33281 0.202392578125 +33282 0.264495849609375 +33283 0.338897705078125 +33284 0.443817138671875 +33285 0.545074462890625 +33286 0.6173095703125 +33287 0.6524658203125 +33288 0.66339111328125 +33289 0.6561279296875 +33290 0.606781005859375 +33291 0.501190185546875 +33292 0.352783203125 +33293 0.176544189453125 +33294 -0.034820556640625 +33295 -0.258209228515625 +33296 -0.44244384765625 +33297 -0.5753173828125 +33298 -0.65203857421875 +33299 -0.641632080078125 +33300 -0.562164306640625 +33301 -0.458038330078125 +33302 -0.350555419921875 +33303 -0.260528564453125 +33304 -0.192108154296875 +33305 -0.141937255859375 +33306 -0.1021728515625 +33307 -0.062896728515625 +33308 -0.011932373046875 +33309 0.062835693359375 +33310 0.148712158203125 +33311 0.241729736328125 +33312 0.34912109375 +33313 0.457305908203125 +33314 0.54388427734375 +33315 0.5728759765625 +33316 0.506591796875 +33317 0.351226806640625 +33318 0.146514892578125 +33319 -0.05523681640625 +33320 -0.21624755859375 +33321 -0.334930419921875 +33322 -0.402984619140625 +33323 -0.4412841796875 +33324 -0.49578857421875 +33325 -0.5601806640625 +33326 -0.600738525390625 +33327 -0.584228515625 +33328 -0.47930908203125 +33329 -0.27935791015625 +33330 -0.0089111328125 +33331 0.268798828125 +33332 0.482818603515625 +33333 0.60369873046875 +33334 0.650421142578125 +33335 0.66400146484375 +33336 0.6414794921875 +33337 0.572540283203125 +33338 0.498138427734375 +33339 0.439453125 +33340 0.375518798828125 +33341 0.274505615234375 +33342 0.1087646484375 +33343 -0.099395751953125 +33344 -0.3182373046875 +33345 -0.5489501953125 +33346 -0.7738037109375 +33347 -0.86383056640625 +33348 -0.870391845703125 +33349 -0.86895751953125 +33350 -0.861053466796875 +33351 -0.765869140625 +33352 -0.5301513671875 +33353 -0.214691162109375 +33354 0.137359619140625 +33355 0.474822998046875 +33356 0.76239013671875 +33357 0.867462158203125 +33358 0.870361328125 +33359 0.86480712890625 +33360 0.831817626953125 +33361 0.677581787109375 +33362 0.495880126953125 +33363 0.30767822265625 +33364 0.116180419921875 +33365 -0.110748291015625 +33366 -0.381805419921875 +33367 -0.6572265625 +33368 -0.857421875 +33369 -0.870391845703125 +33370 -0.870391845703125 +33371 -0.86444091796875 +33372 -0.85723876953125 +33373 -0.790008544921875 +33374 -0.62847900390625 +33375 -0.3956298828125 +33376 -0.126708984375 +33377 0.150115966796875 +33378 0.424041748046875 +33379 0.670623779296875 +33380 0.854522705078125 +33381 0.866485595703125 +33382 0.86920166015625 +33383 0.8653564453125 +33384 0.857147216796875 +33385 0.766845703125 +33386 0.628509521484375 +33387 0.462127685546875 +33388 0.297210693359375 +33389 0.14862060546875 +33390 -0.00537109375 +33391 -0.15753173828125 +33392 -0.31304931640625 +33393 -0.48876953125 +33394 -0.6416015625 +33395 -0.751373291015625 +33396 -0.84619140625 +33397 -0.861297607421875 +33398 -0.863250732421875 +33399 -0.856597900390625 +33400 -0.7498779296875 +33401 -0.624542236328125 +33402 -0.47808837890625 +33403 -0.253387451171875 +33404 0.003692626953125 +33405 0.2257080078125 +33406 0.427154541015625 +33407 0.643218994140625 +33408 0.855926513671875 +33409 0.870361328125 +33410 0.870361328125 +33411 0.862762451171875 +33412 0.79669189453125 +33413 0.595794677734375 +33414 0.362152099609375 +33415 0.1270751953125 +33416 -0.086944580078125 +33417 -0.2784423828125 +33418 -0.484832763671875 +33419 -0.729583740234375 +33420 -0.86688232421875 +33421 -0.870391845703125 +33422 -0.86859130859375 +33423 -0.86279296875 +33424 -0.817962646484375 +33425 -0.6116943359375 +33426 -0.3128662109375 +33427 0.039398193359375 +33428 0.422821044921875 +33429 0.805145263671875 +33430 0.870361328125 +33431 0.870361328125 +33432 0.860015869140625 +33433 0.727935791015625 +33434 0.48114013671875 +33435 0.2059326171875 +33436 -0.06103515625 +33437 -0.29913330078125 +33438 -0.516204833984375 +33439 -0.7252197265625 +33440 -0.85980224609375 +33441 -0.870391845703125 +33442 -0.870391845703125 +33443 -0.858062744140625 +33444 -0.673004150390625 +33445 -0.42694091796875 +33446 -0.2100830078125 +33447 -0.0362548828125 +33448 0.10943603515625 +33449 0.23516845703125 +33450 0.373687744140625 +33451 0.517791748046875 +33452 0.602783203125 +33453 0.635711669921875 +33454 0.655181884765625 +33455 0.65948486328125 +33456 0.651275634765625 +33457 0.61846923828125 +33458 0.53753662109375 +33459 0.404144287109375 +33460 0.22186279296875 +33461 0.003997802734375 +33462 -0.22100830078125 +33463 -0.42449951171875 +33464 -0.579833984375 +33465 -0.641876220703125 +33466 -0.6177978515625 +33467 -0.575531005859375 +33468 -0.526336669921875 +33469 -0.42645263671875 +33470 -0.2581787109375 +33471 -0.068695068359375 +33472 0.09222412109375 +33473 0.232147216796875 +33474 0.3509521484375 +33475 0.410064697265625 +33476 0.372955322265625 +33477 0.2554931640625 +33478 0.10711669921875 +33479 -0.052886962890625 +33480 -0.186279296875 +33481 -0.23291015625 +33482 -0.209442138671875 +33483 -0.174163818359375 +33484 -0.126739501953125 +33485 -0.048126220703125 +33486 0.0426025390625 +33487 0.10748291015625 +33488 0.1409912109375 +33489 0.19708251953125 +33490 0.273651123046875 +33491 0.31768798828125 +33492 0.341094970703125 +33493 0.368011474609375 +33494 0.37249755859375 +33495 0.30072021484375 +33496 0.1517333984375 +33497 -0.01470947265625 +33498 -0.1883544921875 +33499 -0.372711181640625 +33500 -0.51397705078125 +33501 -0.57177734375 +33502 -0.53948974609375 +33503 -0.43511962890625 +33504 -0.2962646484375 +33505 -0.161102294921875 +33506 -0.0435791015625 +33507 0.060394287109375 +33508 0.13665771484375 +33509 0.170135498046875 +33510 0.16552734375 +33511 0.15728759765625 +33512 0.150787353515625 +33513 0.12200927734375 +33514 0.080108642578125 +33515 0.05126953125 +33516 0.062896728515625 +33517 0.09271240234375 +33518 0.092987060546875 +33519 0.07855224609375 +33520 0.06427001953125 +33521 0.0347900390625 +33522 -0.01171875 +33523 -0.056060791015625 +33524 -0.055511474609375 +33525 -0.010467529296875 +33526 0.02508544921875 +33527 0.025665283203125 +33528 0.017333984375 +33529 0.00189208984375 +33530 -0.03173828125 +33531 -0.071502685546875 +33532 -0.13543701171875 +33533 -0.219970703125 +33534 -0.300506591796875 +33535 -0.376312255859375 +33536 -0.416107177734375 +33537 -0.371124267578125 +33538 -0.242279052734375 +33539 -0.069732666015625 +33540 0.125640869140625 +33541 0.31268310546875 +33542 0.45501708984375 +33543 0.554779052734375 +33544 0.61065673828125 +33545 0.610931396484375 +33546 0.531463623046875 +33547 0.3883056640625 +33548 0.23468017578125 +33549 0.095245361328125 +33550 -0.00396728515625 +33551 -0.04852294921875 +33552 -0.055145263671875 +33553 -0.0758056640625 +33554 -0.138702392578125 +33555 -0.209197998046875 +33556 -0.289031982421875 +33557 -0.37884521484375 +33558 -0.456329345703125 +33559 -0.51641845703125 +33560 -0.519287109375 +33561 -0.458251953125 +33562 -0.384796142578125 +33563 -0.323699951171875 +33564 -0.269287109375 +33565 -0.1951904296875 +33566 -0.100006103515625 +33567 -0.01055908203125 +33568 0.1033935546875 +33569 0.24908447265625 +33570 0.373199462890625 +33571 0.45806884765625 +33572 0.511474609375 +33573 0.565399169921875 +33574 0.61138916015625 +33575 0.5897216796875 +33576 0.4906005859375 +33577 0.33148193359375 +33578 0.147796630859375 +33579 -0.01873779296875 +33580 -0.140289306640625 +33581 -0.191986083984375 +33582 -0.184295654296875 +33583 -0.161834716796875 +33584 -0.166595458984375 +33585 -0.19390869140625 +33586 -0.22442626953125 +33587 -0.279754638671875 +33588 -0.3389892578125 +33589 -0.3543701171875 +33590 -0.348175048828125 +33591 -0.32598876953125 +33592 -0.2581787109375 +33593 -0.139801025390625 +33594 0.014617919921875 +33595 0.144378662109375 +33596 0.221038818359375 +33597 0.27069091796875 +33598 0.294036865234375 +33599 0.311767578125 +33600 0.339141845703125 +33601 0.360260009765625 +33602 0.360504150390625 +33603 0.308380126953125 +33604 0.18170166015625 +33605 0.0047607421875 +33606 -0.17559814453125 +33607 -0.3143310546875 +33608 -0.36785888671875 +33609 -0.36248779296875 +33610 -0.343536376953125 +33611 -0.3018798828125 +33612 -0.231414794921875 +33613 -0.117645263671875 +33614 0.007049560546875 +33615 0.087982177734375 +33616 0.13946533203125 +33617 0.17425537109375 +33618 0.188201904296875 +33619 0.171234130859375 +33620 0.118438720703125 +33621 0.05706787109375 +33622 -0.010711669921875 +33623 -0.0914306640625 +33624 -0.162322998046875 +33625 -0.194549560546875 +33626 -0.1492919921875 +33627 -0.02166748046875 +33628 0.124053955078125 +33629 0.211151123046875 +33630 0.240447998046875 +33631 0.242218017578125 +33632 0.2257080078125 +33633 0.194366455078125 +33634 0.115509033203125 +33635 0.0128173828125 +33636 -0.053802490234375 +33637 -0.110626220703125 +33638 -0.199493408203125 +33639 -0.29437255859375 +33640 -0.33221435546875 +33641 -0.27972412109375 +33642 -0.185333251953125 +33643 -0.128204345703125 +33644 -0.115692138671875 +33645 -0.116455078125 +33646 -0.105926513671875 +33647 -0.053955078125 +33648 0.048797607421875 +33649 0.157318115234375 +33650 0.212005615234375 +33651 0.218475341796875 +33652 0.23724365234375 +33653 0.30535888671875 +33654 0.38128662109375 +33655 0.404449462890625 +33656 0.3944091796875 +33657 0.3885498046875 +33658 0.362640380859375 +33659 0.27362060546875 +33660 0.11712646484375 +33661 -0.054901123046875 +33662 -0.19085693359375 +33663 -0.28570556640625 +33664 -0.339263916015625 +33665 -0.3775634765625 +33666 -0.445709228515625 +33667 -0.535064697265625 +33668 -0.629058837890625 +33669 -0.697601318359375 +33670 -0.70391845703125 +33671 -0.6424560546875 +33672 -0.491241455078125 +33673 -0.265716552734375 +33674 -0.023712158203125 +33675 0.201751708984375 +33676 0.375823974609375 +33677 0.485076904296875 +33678 0.56884765625 +33679 0.634765625 +33680 0.63763427734375 +33681 0.5660400390625 +33682 0.4720458984375 +33683 0.40692138671875 +33684 0.3778076171875 +33685 0.376953125 +33686 0.371978759765625 +33687 0.313140869140625 +33688 0.184417724609375 +33689 0.011199951171875 +33690 -0.171051025390625 +33691 -0.33740234375 +33692 -0.47198486328125 +33693 -0.560394287109375 +33694 -0.58056640625 +33695 -0.54754638671875 +33696 -0.508575439453125 +33697 -0.459503173828125 +33698 -0.394378662109375 +33699 -0.35260009765625 +33700 -0.31170654296875 +33701 -0.197418212890625 +33702 -0.007965087890625 +33703 0.207489013671875 +33704 0.409210205078125 +33705 0.57208251953125 +33706 0.66595458984375 +33707 0.65875244140625 +33708 0.56744384765625 +33709 0.431396484375 +33710 0.29443359375 +33711 0.182464599609375 +33712 0.06365966796875 +33713 -0.075958251953125 +33714 -0.189422607421875 +33715 -0.271942138671875 +33716 -0.342529296875 +33717 -0.364166259765625 +33718 -0.327239990234375 +33719 -0.2769775390625 +33720 -0.253692626953125 +33721 -0.24365234375 +33722 -0.1983642578125 +33723 -0.116241455078125 +33724 -0.036834716796875 +33725 0.034881591796875 +33726 0.09124755859375 +33727 0.10888671875 +33728 0.125518798828125 +33729 0.15771484375 +33730 0.17828369140625 +33731 0.17108154296875 +33732 0.129974365234375 +33733 0.082427978515625 +33734 0.027679443359375 +33735 -0.065643310546875 +33736 -0.15936279296875 +33737 -0.21307373046875 +33738 -0.234649658203125 +33739 -0.2001953125 +33740 -0.119171142578125 +33741 -0.024749755859375 +33742 0.085784912109375 +33743 0.178131103515625 +33744 0.215576171875 +33745 0.211456298828125 +33746 0.17523193359375 +33747 0.128753662109375 +33748 0.1019287109375 +33749 0.0743408203125 +33750 0.04327392578125 +33751 0.038177490234375 +33752 0.076263427734375 +33753 0.14105224609375 +33754 0.186431884765625 +33755 0.188812255859375 +33756 0.1390380859375 +33757 0.041778564453125 +33758 -0.079437255859375 +33759 -0.219390869140625 +33760 -0.367828369140625 +33761 -0.494873046875 +33762 -0.556243896484375 +33763 -0.508697509765625 +33764 -0.3756103515625 +33765 -0.218902587890625 +33766 -0.063751220703125 +33767 0.091552734375 +33768 0.23602294921875 +33769 0.342987060546875 +33770 0.39520263671875 +33771 0.389373779296875 +33772 0.324249267578125 +33773 0.224090576171875 +33774 0.124267578125 +33775 0.037078857421875 +33776 -0.010101318359375 +33777 -0.019439697265625 +33778 -0.022796630859375 +33779 -0.001556396484375 +33780 0.056304931640625 +33781 0.106719970703125 +33782 0.096893310546875 +33783 0.042694091796875 +33784 -0.018035888671875 +33785 -0.07586669921875 +33786 -0.11944580078125 +33787 -0.15972900390625 +33788 -0.202606201171875 +33789 -0.24859619140625 +33790 -0.30517578125 +33791 -0.36212158203125 +33792 -0.39141845703125 +33793 -0.35528564453125 +33794 -0.249969482421875 +33795 -0.092864990234375 +33796 0.08905029296875 +33797 0.2352294921875 +33798 0.318817138671875 +33799 0.358642578125 +33800 0.347747802734375 +33801 0.28564453125 +33802 0.223175048828125 +33803 0.196746826171875 +33804 0.179840087890625 +33805 0.155548095703125 +33806 0.151214599609375 +33807 0.156951904296875 +33808 0.13177490234375 +33809 0.100799560546875 +33810 0.087127685546875 +33811 0.05487060546875 +33812 -0.009002685546875 +33813 -0.10400390625 +33814 -0.229400634765625 +33815 -0.35552978515625 +33816 -0.441925048828125 +33817 -0.473846435546875 +33818 -0.464813232421875 +33819 -0.419097900390625 +33820 -0.334320068359375 +33821 -0.227935791015625 +33822 -0.12347412109375 +33823 -0.02764892578125 +33824 0.077667236328125 +33825 0.2132568359375 +33826 0.38885498046875 +33827 0.582794189453125 +33828 0.734039306640625 +33829 0.800140380859375 +33830 0.7783203125 +33831 0.6651611328125 +33832 0.45965576171875 +33833 0.199188232421875 +33834 -0.050689697265625 +33835 -0.23297119140625 +33836 -0.33013916015625 +33837 -0.368408203125 +33838 -0.378936767578125 +33839 -0.376983642578125 +33840 -0.37969970703125 +33841 -0.391510009765625 +33842 -0.385345458984375 +33843 -0.3419189453125 +33844 -0.28289794921875 +33845 -0.251617431640625 +33846 -0.266143798828125 +33847 -0.273345947265625 +33848 -0.216796875 +33849 -0.128265380859375 +33850 -0.068145751953125 +33851 -0.0430908203125 +33852 -0.024444580078125 +33853 0.020721435546875 +33854 0.124481201171875 +33855 0.25787353515625 +33856 0.379119873046875 +33857 0.47991943359375 +33858 0.5281982421875 +33859 0.511138916015625 +33860 0.456207275390625 +33861 0.407470703125 +33862 0.383758544921875 +33863 0.35687255859375 +33864 0.31182861328125 +33865 0.250885009765625 +33866 0.1654052734375 +33867 0.035247802734375 +33868 -0.142059326171875 +33869 -0.33563232421875 +33870 -0.5345458984375 +33871 -0.72186279296875 +33872 -0.836669921875 +33873 -0.8326416015625 +33874 -0.7296142578125 +33875 -0.582550048828125 +33876 -0.440093994140625 +33877 -0.324310302734375 +33878 -0.20147705078125 +33879 -0.044647216796875 +33880 0.103973388671875 +33881 0.202392578125 +33882 0.264495849609375 +33883 0.338897705078125 +33884 0.443817138671875 +33885 0.545074462890625 +33886 0.6173095703125 +33887 0.6524658203125 +33888 0.66339111328125 +33889 0.6561279296875 +33890 0.606781005859375 +33891 0.501190185546875 +33892 0.352783203125 +33893 0.176544189453125 +33894 -0.034820556640625 +33895 -0.258209228515625 +33896 -0.44244384765625 +33897 -0.5753173828125 +33898 -0.65203857421875 +33899 -0.641632080078125 +33900 -0.562164306640625 +33901 -0.458038330078125 +33902 -0.350555419921875 +33903 -0.260528564453125 +33904 -0.192108154296875 +33905 -0.141937255859375 +33906 -0.1021728515625 +33907 -0.062896728515625 +33908 -0.011932373046875 +33909 0.062835693359375 +33910 0.148712158203125 +33911 0.241729736328125 +33912 0.34912109375 +33913 0.457305908203125 +33914 0.54388427734375 +33915 0.5728759765625 +33916 0.506591796875 +33917 0.351226806640625 +33918 0.146514892578125 +33919 -0.05523681640625 +33920 -0.21624755859375 +33921 -0.334930419921875 +33922 -0.402984619140625 +33923 -0.4412841796875 +33924 -0.49578857421875 +33925 -0.5601806640625 +33926 -0.600738525390625 +33927 -0.584228515625 +33928 -0.47930908203125 +33929 -0.27935791015625 +33930 -0.0089111328125 +33931 0.268798828125 +33932 0.482818603515625 +33933 0.60369873046875 +33934 0.650421142578125 +33935 0.66400146484375 +33936 0.6414794921875 +33937 0.572540283203125 +33938 0.498138427734375 +33939 0.439453125 +33940 0.375518798828125 +33941 0.274505615234375 +33942 0.1087646484375 +33943 -0.099395751953125 +33944 -0.3182373046875 +33945 -0.5489501953125 +33946 -0.7738037109375 +33947 -0.86383056640625 +33948 -0.870391845703125 +33949 -0.86895751953125 +33950 -0.861053466796875 +33951 -0.765869140625 +33952 -0.5301513671875 +33953 -0.214691162109375 +33954 0.137359619140625 +33955 0.474822998046875 +33956 0.76239013671875 +33957 0.867462158203125 +33958 0.870361328125 +33959 0.86480712890625 +33960 0.831817626953125 +33961 0.677581787109375 +33962 0.495880126953125 +33963 0.30767822265625 +33964 0.116180419921875 +33965 -0.110748291015625 +33966 -0.381805419921875 +33967 -0.6572265625 +33968 -0.857421875 +33969 -0.870391845703125 +33970 -0.870391845703125 +33971 -0.86444091796875 +33972 -0.85723876953125 +33973 -0.790008544921875 +33974 -0.62847900390625 +33975 -0.3956298828125 +33976 -0.126708984375 +33977 0.150115966796875 +33978 0.424041748046875 +33979 0.670623779296875 +33980 0.854522705078125 +33981 0.866485595703125 +33982 0.86920166015625 +33983 0.8653564453125 +33984 0.857147216796875 +33985 0.766845703125 +33986 0.628509521484375 +33987 0.462127685546875 +33988 0.297210693359375 +33989 0.14862060546875 +33990 -0.00537109375 +33991 -0.15753173828125 +33992 -0.31304931640625 +33993 -0.48876953125 +33994 -0.6416015625 +33995 -0.751373291015625 +33996 -0.84619140625 +33997 -0.861297607421875 +33998 -0.863250732421875 +33999 -0.856597900390625 +34000 -0.7498779296875 +34001 -0.624542236328125 +34002 -0.47808837890625 +34003 -0.253387451171875 +34004 0.003692626953125 +34005 0.2257080078125 +34006 0.427154541015625 +34007 0.643218994140625 +34008 0.855926513671875 +34009 0.870361328125 +34010 0.870361328125 +34011 0.862762451171875 +34012 0.79669189453125 +34013 0.595794677734375 +34014 0.362152099609375 +34015 0.1270751953125 +34016 -0.086944580078125 +34017 -0.2784423828125 +34018 -0.484832763671875 +34019 -0.729583740234375 +34020 -0.86688232421875 +34021 -0.870391845703125 +34022 -0.86859130859375 +34023 -0.86279296875 +34024 -0.817962646484375 +34025 -0.6116943359375 +34026 -0.3128662109375 +34027 0.039398193359375 +34028 0.422821044921875 +34029 0.805145263671875 +34030 0.870361328125 +34031 0.870361328125 +34032 0.860015869140625 +34033 0.727935791015625 +34034 0.48114013671875 +34035 0.2059326171875 +34036 -0.06103515625 +34037 -0.29913330078125 +34038 -0.516204833984375 +34039 -0.7252197265625 +34040 -0.85980224609375 +34041 -0.870391845703125 +34042 -0.870391845703125 +34043 -0.858062744140625 +34044 -0.673004150390625 +34045 -0.42694091796875 +34046 -0.2100830078125 +34047 -0.0362548828125 +34048 0.10943603515625 +34049 0.23516845703125 +34050 0.373687744140625 +34051 0.517791748046875 +34052 0.602783203125 +34053 0.635711669921875 +34054 0.655181884765625 +34055 0.65948486328125 +34056 0.651275634765625 +34057 0.61846923828125 +34058 0.53753662109375 +34059 0.404144287109375 +34060 0.22186279296875 +34061 0.003997802734375 +34062 -0.22100830078125 +34063 -0.42449951171875 +34064 -0.579833984375 +34065 -0.641876220703125 +34066 -0.6177978515625 +34067 -0.575531005859375 +34068 -0.526336669921875 +34069 -0.42645263671875 +34070 -0.2581787109375 +34071 -0.068695068359375 +34072 0.09222412109375 +34073 0.232147216796875 +34074 0.3509521484375 +34075 0.410064697265625 +34076 0.372955322265625 +34077 0.2554931640625 +34078 0.10711669921875 +34079 -0.052886962890625 +34080 -0.186279296875 +34081 -0.23291015625 +34082 -0.209442138671875 +34083 -0.174163818359375 +34084 -0.126739501953125 +34085 -0.048126220703125 +34086 0.0426025390625 +34087 0.10748291015625 +34088 0.1409912109375 +34089 0.19708251953125 +34090 0.273651123046875 +34091 0.31768798828125 +34092 0.341094970703125 +34093 0.368011474609375 +34094 0.37249755859375 +34095 0.30072021484375 +34096 0.1517333984375 +34097 -0.01470947265625 +34098 -0.1883544921875 +34099 -0.372711181640625 +34100 -0.51397705078125 +34101 -0.57177734375 +34102 -0.53948974609375 +34103 -0.43511962890625 +34104 -0.2962646484375 +34105 -0.161102294921875 +34106 -0.0435791015625 +34107 0.060394287109375 +34108 0.13665771484375 +34109 0.170135498046875 +34110 0.16552734375 +34111 0.15728759765625 +34112 0.150787353515625 +34113 0.12200927734375 +34114 0.080108642578125 +34115 0.05126953125 +34116 0.062896728515625 +34117 0.09271240234375 +34118 0.092987060546875 +34119 0.07855224609375 +34120 0.06427001953125 +34121 0.0347900390625 +34122 -0.01171875 +34123 -0.056060791015625 +34124 -0.055511474609375 +34125 -0.010467529296875 +34126 0.02508544921875 +34127 0.025665283203125 +34128 0.017333984375 +34129 0.00189208984375 +34130 -0.03173828125 +34131 -0.071502685546875 +34132 -0.13543701171875 +34133 -0.219970703125 +34134 -0.300506591796875 +34135 -0.376312255859375 +34136 -0.416107177734375 +34137 -0.371124267578125 +34138 -0.242279052734375 +34139 -0.069732666015625 +34140 0.125640869140625 +34141 0.31268310546875 +34142 0.45501708984375 +34143 0.554779052734375 +34144 0.61065673828125 +34145 0.610931396484375 +34146 0.531463623046875 +34147 0.3883056640625 +34148 0.23468017578125 +34149 0.095245361328125 +34150 -0.00396728515625 +34151 -0.04852294921875 +34152 -0.055145263671875 +34153 -0.0758056640625 +34154 -0.138702392578125 +34155 -0.209197998046875 +34156 -0.289031982421875 +34157 -0.37884521484375 +34158 -0.456329345703125 +34159 -0.51641845703125 +34160 -0.519287109375 +34161 -0.458251953125 +34162 -0.384796142578125 +34163 -0.323699951171875 +34164 -0.269287109375 +34165 -0.1951904296875 +34166 -0.100006103515625 +34167 -0.01055908203125 +34168 0.1033935546875 +34169 0.24908447265625 +34170 0.373199462890625 +34171 0.45806884765625 +34172 0.511474609375 +34173 0.565399169921875 +34174 0.61138916015625 +34175 0.5897216796875 +34176 0.4906005859375 +34177 0.33148193359375 +34178 0.147796630859375 +34179 -0.01873779296875 +34180 -0.140289306640625 +34181 -0.191986083984375 +34182 -0.184295654296875 +34183 -0.161834716796875 +34184 -0.166595458984375 +34185 -0.19390869140625 +34186 -0.22442626953125 +34187 -0.279754638671875 +34188 -0.3389892578125 +34189 -0.3543701171875 +34190 -0.348175048828125 +34191 -0.32598876953125 +34192 -0.2581787109375 +34193 -0.139801025390625 +34194 0.014617919921875 +34195 0.144378662109375 +34196 0.221038818359375 +34197 0.27069091796875 +34198 0.294036865234375 +34199 0.311767578125 +34200 0.339141845703125 +34201 0.360260009765625 +34202 0.360504150390625 +34203 0.308380126953125 +34204 0.18170166015625 +34205 0.0047607421875 +34206 -0.17559814453125 +34207 -0.3143310546875 +34208 -0.36785888671875 +34209 -0.36248779296875 +34210 -0.343536376953125 +34211 -0.3018798828125 +34212 -0.231414794921875 +34213 -0.117645263671875 +34214 0.007049560546875 +34215 0.087982177734375 +34216 0.13946533203125 +34217 0.17425537109375 +34218 0.188201904296875 +34219 0.171234130859375 +34220 0.118438720703125 +34221 0.05706787109375 +34222 -0.010711669921875 +34223 -0.0914306640625 +34224 -0.162322998046875 +34225 -0.194549560546875 +34226 -0.1492919921875 +34227 -0.02166748046875 +34228 0.124053955078125 +34229 0.211151123046875 +34230 0.240447998046875 +34231 0.242218017578125 +34232 0.2257080078125 +34233 0.194366455078125 +34234 0.115509033203125 +34235 0.0128173828125 +34236 -0.053802490234375 +34237 -0.110626220703125 +34238 -0.199493408203125 +34239 -0.29437255859375 +34240 -0.33221435546875 +34241 -0.27972412109375 +34242 -0.185333251953125 +34243 -0.128204345703125 +34244 -0.115692138671875 +34245 -0.116455078125 +34246 -0.105926513671875 +34247 -0.053955078125 +34248 0.048797607421875 +34249 0.157318115234375 +34250 0.212005615234375 +34251 0.218475341796875 +34252 0.23724365234375 +34253 0.30535888671875 +34254 0.38128662109375 +34255 0.404449462890625 +34256 0.3944091796875 +34257 0.3885498046875 +34258 0.362640380859375 +34259 0.27362060546875 +34260 0.11712646484375 +34261 -0.054901123046875 +34262 -0.19085693359375 +34263 -0.28570556640625 +34264 -0.339263916015625 +34265 -0.3775634765625 +34266 -0.445709228515625 +34267 -0.535064697265625 +34268 -0.629058837890625 +34269 -0.697601318359375 +34270 -0.70391845703125 +34271 -0.6424560546875 +34272 -0.491241455078125 +34273 -0.265716552734375 +34274 -0.023712158203125 +34275 0.201751708984375 +34276 0.375823974609375 +34277 0.485076904296875 +34278 0.56884765625 +34279 0.634765625 +34280 0.63763427734375 +34281 0.5660400390625 +34282 0.4720458984375 +34283 0.40692138671875 +34284 0.3778076171875 +34285 0.376953125 +34286 0.371978759765625 +34287 0.313140869140625 +34288 0.184417724609375 +34289 0.011199951171875 +34290 -0.171051025390625 +34291 -0.33740234375 +34292 -0.47198486328125 +34293 -0.560394287109375 +34294 -0.58056640625 +34295 -0.54754638671875 +34296 -0.508575439453125 +34297 -0.459503173828125 +34298 -0.394378662109375 +34299 -0.35260009765625 +34300 -0.31170654296875 +34301 -0.197418212890625 +34302 -0.007965087890625 +34303 0.207489013671875 +34304 0.409210205078125 +34305 0.57208251953125 +34306 0.66595458984375 +34307 0.65875244140625 +34308 0.56744384765625 +34309 0.431396484375 +34310 0.29443359375 +34311 0.182464599609375 +34312 0.06365966796875 +34313 -0.075958251953125 +34314 -0.189422607421875 +34315 -0.271942138671875 +34316 -0.342529296875 +34317 -0.364166259765625 +34318 -0.327239990234375 +34319 -0.2769775390625 +34320 -0.253692626953125 +34321 -0.24365234375 +34322 -0.1983642578125 +34323 -0.116241455078125 +34324 -0.036834716796875 +34325 0.034881591796875 +34326 0.09124755859375 +34327 0.10888671875 +34328 0.125518798828125 +34329 0.15771484375 +34330 0.17828369140625 +34331 0.17108154296875 +34332 0.129974365234375 +34333 0.082427978515625 +34334 0.027679443359375 +34335 -0.065643310546875 +34336 -0.15936279296875 +34337 -0.21307373046875 +34338 -0.234649658203125 +34339 -0.2001953125 +34340 -0.119171142578125 +34341 -0.024749755859375 +34342 0.085784912109375 +34343 0.178131103515625 +34344 0.215576171875 +34345 0.211456298828125 +34346 0.17523193359375 +34347 0.128753662109375 +34348 0.1019287109375 +34349 0.0743408203125 +34350 0.04327392578125 +34351 0.038177490234375 +34352 0.076263427734375 +34353 0.14105224609375 +34354 0.186431884765625 +34355 0.188812255859375 +34356 0.1390380859375 +34357 0.041778564453125 +34358 -0.079437255859375 +34359 -0.219390869140625 +34360 -0.367828369140625 +34361 -0.494873046875 +34362 -0.556243896484375 +34363 -0.508697509765625 +34364 -0.3756103515625 +34365 -0.218902587890625 +34366 -0.063751220703125 +34367 0.091552734375 +34368 0.23602294921875 +34369 0.342987060546875 +34370 0.39520263671875 +34371 0.389373779296875 +34372 0.324249267578125 +34373 0.224090576171875 +34374 0.124267578125 +34375 0.037078857421875 +34376 -0.010101318359375 +34377 -0.019439697265625 +34378 -0.022796630859375 +34379 -0.001556396484375 +34380 0.056304931640625 +34381 0.106719970703125 +34382 0.096893310546875 +34383 0.042694091796875 +34384 -0.018035888671875 +34385 -0.07586669921875 +34386 -0.11944580078125 +34387 -0.15972900390625 +34388 -0.202606201171875 +34389 -0.24859619140625 +34390 -0.30517578125 +34391 -0.36212158203125 +34392 -0.39141845703125 +34393 -0.35528564453125 +34394 -0.249969482421875 +34395 -0.092864990234375 +34396 0.08905029296875 +34397 0.2352294921875 +34398 0.318817138671875 +34399 0.358642578125 +34400 0.347747802734375 +34401 0.28564453125 +34402 0.223175048828125 +34403 0.196746826171875 +34404 0.179840087890625 +34405 0.155548095703125 +34406 0.151214599609375 +34407 0.156951904296875 +34408 0.13177490234375 +34409 0.100799560546875 +34410 0.087127685546875 +34411 0.05487060546875 +34412 -0.009002685546875 +34413 -0.10400390625 +34414 -0.229400634765625 +34415 -0.35552978515625 +34416 -0.441925048828125 +34417 -0.473846435546875 +34418 -0.464813232421875 +34419 -0.419097900390625 +34420 -0.334320068359375 +34421 -0.227935791015625 +34422 -0.12347412109375 +34423 -0.02764892578125 +34424 0.077667236328125 +34425 0.2132568359375 +34426 0.38885498046875 +34427 0.582794189453125 +34428 0.734039306640625 +34429 0.800140380859375 +34430 0.7783203125 +34431 0.6651611328125 +34432 0.45965576171875 +34433 0.199188232421875 +34434 -0.050689697265625 +34435 -0.23297119140625 +34436 -0.33013916015625 +34437 -0.368408203125 +34438 -0.378936767578125 +34439 -0.376983642578125 +34440 -0.37969970703125 +34441 -0.391510009765625 +34442 -0.385345458984375 +34443 -0.3419189453125 +34444 -0.28289794921875 +34445 -0.251617431640625 +34446 -0.266143798828125 +34447 -0.273345947265625 +34448 -0.216796875 +34449 -0.128265380859375 +34450 -0.068145751953125 +34451 -0.0430908203125 +34452 -0.024444580078125 +34453 0.020721435546875 +34454 0.124481201171875 +34455 0.25787353515625 +34456 0.379119873046875 +34457 0.47991943359375 +34458 0.5281982421875 +34459 0.511138916015625 +34460 0.456207275390625 +34461 0.407470703125 +34462 0.383758544921875 +34463 0.35687255859375 +34464 0.31182861328125 +34465 0.250885009765625 +34466 0.1654052734375 +34467 0.035247802734375 +34468 -0.142059326171875 +34469 -0.33563232421875 +34470 -0.5345458984375 +34471 -0.72186279296875 +34472 -0.836669921875 +34473 -0.8326416015625 +34474 -0.7296142578125 +34475 -0.582550048828125 +34476 -0.440093994140625 +34477 -0.324310302734375 +34478 -0.20147705078125 +34479 -0.044647216796875 +34480 0.103973388671875 +34481 0.202392578125 +34482 0.264495849609375 +34483 0.338897705078125 +34484 0.443817138671875 +34485 0.545074462890625 +34486 0.6173095703125 +34487 0.6524658203125 +34488 0.66339111328125 +34489 0.6561279296875 +34490 0.606781005859375 +34491 0.501190185546875 +34492 0.352783203125 +34493 0.176544189453125 +34494 -0.034820556640625 +34495 -0.258209228515625 +34496 -0.44244384765625 +34497 -0.5753173828125 +34498 -0.65203857421875 +34499 -0.641632080078125 +34500 -0.562164306640625 +34501 -0.458038330078125 +34502 -0.350555419921875 +34503 -0.260528564453125 +34504 -0.192108154296875 +34505 -0.141937255859375 +34506 -0.1021728515625 +34507 -0.062896728515625 +34508 -0.011932373046875 +34509 0.062835693359375 +34510 0.148712158203125 +34511 0.241729736328125 +34512 0.34912109375 +34513 0.457305908203125 +34514 0.54388427734375 +34515 0.5728759765625 +34516 0.506591796875 +34517 0.351226806640625 +34518 0.146514892578125 +34519 -0.05523681640625 +34520 -0.21624755859375 +34521 -0.334930419921875 +34522 -0.402984619140625 +34523 -0.4412841796875 +34524 -0.49578857421875 +34525 -0.5601806640625 +34526 -0.600738525390625 +34527 -0.584228515625 +34528 -0.47930908203125 +34529 -0.27935791015625 +34530 -0.0089111328125 +34531 0.268798828125 +34532 0.482818603515625 +34533 0.60369873046875 +34534 0.650421142578125 +34535 0.66400146484375 +34536 0.6414794921875 +34537 0.572540283203125 +34538 0.498138427734375 +34539 0.439453125 +34540 0.375518798828125 +34541 0.274505615234375 +34542 0.1087646484375 +34543 -0.099395751953125 +34544 -0.3182373046875 +34545 -0.5489501953125 +34546 -0.7738037109375 +34547 -0.86383056640625 +34548 -0.870391845703125 +34549 -0.86895751953125 +34550 -0.861053466796875 +34551 -0.765869140625 +34552 -0.5301513671875 +34553 -0.214691162109375 +34554 0.137359619140625 +34555 0.474822998046875 +34556 0.76239013671875 +34557 0.867462158203125 +34558 0.870361328125 +34559 0.86480712890625 +34560 0.831817626953125 +34561 0.677581787109375 +34562 0.495880126953125 +34563 0.30767822265625 +34564 0.116180419921875 +34565 -0.110748291015625 +34566 -0.381805419921875 +34567 -0.6572265625 +34568 -0.857421875 +34569 -0.870391845703125 +34570 -0.870391845703125 +34571 -0.86444091796875 +34572 -0.85723876953125 +34573 -0.790008544921875 +34574 -0.62847900390625 +34575 -0.3956298828125 +34576 -0.126708984375 +34577 0.150115966796875 +34578 0.424041748046875 +34579 0.670623779296875 +34580 0.854522705078125 +34581 0.866485595703125 +34582 0.86920166015625 +34583 0.8653564453125 +34584 0.857147216796875 +34585 0.766845703125 +34586 0.628509521484375 +34587 0.462127685546875 +34588 0.297210693359375 +34589 0.14862060546875 +34590 -0.00537109375 +34591 -0.15753173828125 +34592 -0.31304931640625 +34593 -0.48876953125 +34594 -0.6416015625 +34595 -0.751373291015625 +34596 -0.84619140625 +34597 -0.861297607421875 +34598 -0.863250732421875 +34599 -0.856597900390625 +34600 -0.7498779296875 +34601 -0.624542236328125 +34602 -0.47808837890625 +34603 -0.253387451171875 +34604 0.003692626953125 +34605 0.2257080078125 +34606 0.427154541015625 +34607 0.643218994140625 +34608 0.855926513671875 +34609 0.870361328125 +34610 0.870361328125 +34611 0.862762451171875 +34612 0.79669189453125 +34613 0.595794677734375 +34614 0.362152099609375 +34615 0.1270751953125 +34616 -0.086944580078125 +34617 -0.2784423828125 +34618 -0.484832763671875 +34619 -0.729583740234375 +34620 -0.86688232421875 +34621 -0.870391845703125 +34622 -0.86859130859375 +34623 -0.86279296875 +34624 -0.817962646484375 +34625 -0.6116943359375 +34626 -0.3128662109375 +34627 0.039398193359375 +34628 0.422821044921875 +34629 0.805145263671875 +34630 0.870361328125 +34631 0.870361328125 +34632 0.860015869140625 +34633 0.727935791015625 +34634 0.48114013671875 +34635 0.2059326171875 +34636 -0.06103515625 +34637 -0.29913330078125 +34638 -0.516204833984375 +34639 -0.7252197265625 +34640 -0.85980224609375 +34641 -0.870391845703125 +34642 -0.870391845703125 +34643 -0.858062744140625 +34644 -0.673004150390625 +34645 -0.42694091796875 +34646 -0.2100830078125 +34647 -0.0362548828125 +34648 0.10943603515625 +34649 0.23516845703125 +34650 0.373687744140625 +34651 0.517791748046875 +34652 0.602783203125 +34653 0.635711669921875 +34654 0.655181884765625 +34655 0.65948486328125 +34656 0.651275634765625 +34657 0.61846923828125 +34658 0.53753662109375 +34659 0.404144287109375 +34660 0.22186279296875 +34661 0.003997802734375 +34662 -0.22100830078125 +34663 -0.42449951171875 +34664 -0.579833984375 +34665 -0.641876220703125 +34666 -0.6177978515625 +34667 -0.575531005859375 +34668 -0.526336669921875 +34669 -0.42645263671875 +34670 -0.2581787109375 +34671 -0.068695068359375 +34672 0.09222412109375 +34673 0.232147216796875 +34674 0.3509521484375 +34675 0.410064697265625 +34676 0.372955322265625 +34677 0.2554931640625 +34678 0.10711669921875 +34679 -0.052886962890625 +34680 -0.186279296875 +34681 -0.23291015625 +34682 -0.209442138671875 +34683 -0.174163818359375 +34684 -0.126739501953125 +34685 -0.048126220703125 +34686 0.0426025390625 +34687 0.10748291015625 +34688 0.1409912109375 +34689 0.19708251953125 +34690 0.273651123046875 +34691 0.31768798828125 +34692 0.341094970703125 +34693 0.368011474609375 +34694 0.37249755859375 +34695 0.30072021484375 +34696 0.1517333984375 +34697 -0.01470947265625 +34698 -0.1883544921875 +34699 -0.372711181640625 +34700 -0.51397705078125 +34701 -0.57177734375 +34702 -0.53948974609375 +34703 -0.43511962890625 +34704 -0.2962646484375 +34705 -0.161102294921875 +34706 -0.0435791015625 +34707 0.060394287109375 +34708 0.13665771484375 +34709 0.170135498046875 +34710 0.16552734375 +34711 0.15728759765625 +34712 0.150787353515625 +34713 0.12200927734375 +34714 0.080108642578125 +34715 0.05126953125 +34716 0.062896728515625 +34717 0.09271240234375 +34718 0.092987060546875 +34719 0.07855224609375 +34720 0.06427001953125 +34721 0.0347900390625 +34722 -0.01171875 +34723 -0.056060791015625 +34724 -0.055511474609375 +34725 -0.010467529296875 +34726 0.02508544921875 +34727 0.025665283203125 +34728 0.017333984375 +34729 0.00189208984375 +34730 -0.03173828125 +34731 -0.071502685546875 +34732 -0.13543701171875 +34733 -0.219970703125 +34734 -0.300506591796875 +34735 -0.376312255859375 +34736 -0.416107177734375 +34737 -0.371124267578125 +34738 -0.242279052734375 +34739 -0.069732666015625 +34740 0.125640869140625 +34741 0.31268310546875 +34742 0.45501708984375 +34743 0.554779052734375 +34744 0.61065673828125 +34745 0.610931396484375 +34746 0.531463623046875 +34747 0.3883056640625 +34748 0.23468017578125 +34749 0.095245361328125 +34750 -0.00396728515625 +34751 -0.04852294921875 +34752 -0.055145263671875 +34753 -0.0758056640625 +34754 -0.138702392578125 +34755 -0.209197998046875 +34756 -0.289031982421875 +34757 -0.37884521484375 +34758 -0.456329345703125 +34759 -0.51641845703125 +34760 -0.519287109375 +34761 -0.458251953125 +34762 -0.384796142578125 +34763 -0.323699951171875 +34764 -0.269287109375 +34765 -0.1951904296875 +34766 -0.100006103515625 +34767 -0.01055908203125 +34768 0.1033935546875 +34769 0.24908447265625 +34770 0.373199462890625 +34771 0.45806884765625 +34772 0.511474609375 +34773 0.565399169921875 +34774 0.61138916015625 +34775 0.5897216796875 +34776 0.4906005859375 +34777 0.33148193359375 +34778 0.147796630859375 +34779 -0.01873779296875 +34780 -0.140289306640625 +34781 -0.191986083984375 +34782 -0.184295654296875 +34783 -0.161834716796875 +34784 -0.166595458984375 +34785 -0.19390869140625 +34786 -0.22442626953125 +34787 -0.279754638671875 +34788 -0.3389892578125 +34789 -0.3543701171875 +34790 -0.348175048828125 +34791 -0.32598876953125 +34792 -0.2581787109375 +34793 -0.139801025390625 +34794 0.014617919921875 +34795 0.144378662109375 +34796 0.221038818359375 +34797 0.27069091796875 +34798 0.294036865234375 +34799 0.311767578125 +34800 0.339141845703125 +34801 0.360260009765625 +34802 0.360504150390625 +34803 0.308380126953125 +34804 0.18170166015625 +34805 0.0047607421875 +34806 -0.17559814453125 +34807 -0.3143310546875 +34808 -0.36785888671875 +34809 -0.36248779296875 +34810 -0.343536376953125 +34811 -0.3018798828125 +34812 -0.231414794921875 +34813 -0.117645263671875 +34814 0.007049560546875 +34815 0.087982177734375 +34816 0.13946533203125 +34817 0.17425537109375 +34818 0.188201904296875 +34819 0.171234130859375 +34820 0.118438720703125 +34821 0.05706787109375 +34822 -0.010711669921875 +34823 -0.0914306640625 +34824 -0.162322998046875 +34825 -0.194549560546875 +34826 -0.1492919921875 +34827 -0.02166748046875 +34828 0.124053955078125 +34829 0.211151123046875 +34830 0.240447998046875 +34831 0.242218017578125 +34832 0.2257080078125 +34833 0.194366455078125 +34834 0.115509033203125 +34835 0.0128173828125 +34836 -0.053802490234375 +34837 -0.110626220703125 +34838 -0.199493408203125 +34839 -0.29437255859375 +34840 -0.33221435546875 +34841 -0.27972412109375 +34842 -0.185333251953125 +34843 -0.128204345703125 +34844 -0.115692138671875 +34845 -0.116455078125 +34846 -0.105926513671875 +34847 -0.053955078125 +34848 0.048797607421875 +34849 0.157318115234375 +34850 0.212005615234375 +34851 0.218475341796875 +34852 0.23724365234375 +34853 0.30535888671875 +34854 0.38128662109375 +34855 0.404449462890625 +34856 0.3944091796875 +34857 0.3885498046875 +34858 0.362640380859375 +34859 0.27362060546875 +34860 0.11712646484375 +34861 -0.054901123046875 +34862 -0.19085693359375 +34863 -0.28570556640625 +34864 -0.339263916015625 +34865 -0.3775634765625 +34866 -0.445709228515625 +34867 -0.535064697265625 +34868 -0.629058837890625 +34869 -0.697601318359375 +34870 -0.70391845703125 +34871 -0.6424560546875 +34872 -0.491241455078125 +34873 -0.265716552734375 +34874 -0.023712158203125 +34875 0.201751708984375 +34876 0.375823974609375 +34877 0.485076904296875 +34878 0.56884765625 +34879 0.634765625 +34880 0.63763427734375 +34881 0.5660400390625 +34882 0.4720458984375 +34883 0.40692138671875 +34884 0.3778076171875 +34885 0.376953125 +34886 0.371978759765625 +34887 0.313140869140625 +34888 0.184417724609375 +34889 0.011199951171875 +34890 -0.171051025390625 +34891 -0.33740234375 +34892 -0.47198486328125 +34893 -0.560394287109375 +34894 -0.58056640625 +34895 -0.54754638671875 +34896 -0.508575439453125 +34897 -0.459503173828125 +34898 -0.394378662109375 +34899 -0.35260009765625 +34900 -0.31170654296875 +34901 -0.197418212890625 +34902 -0.007965087890625 +34903 0.207489013671875 +34904 0.409210205078125 +34905 0.57208251953125 +34906 0.66595458984375 +34907 0.65875244140625 +34908 0.56744384765625 +34909 0.431396484375 +34910 0.29443359375 +34911 0.182464599609375 +34912 0.06365966796875 +34913 -0.075958251953125 +34914 -0.189422607421875 +34915 -0.271942138671875 +34916 -0.342529296875 +34917 -0.364166259765625 +34918 -0.327239990234375 +34919 -0.2769775390625 +34920 -0.253692626953125 +34921 -0.24365234375 +34922 -0.1983642578125 +34923 -0.116241455078125 +34924 -0.036834716796875 +34925 0.034881591796875 +34926 0.09124755859375 +34927 0.10888671875 +34928 0.125518798828125 +34929 0.15771484375 +34930 0.17828369140625 +34931 0.17108154296875 +34932 0.129974365234375 +34933 0.082427978515625 +34934 0.027679443359375 +34935 -0.065643310546875 +34936 -0.15936279296875 +34937 -0.21307373046875 +34938 -0.234649658203125 +34939 -0.2001953125 +34940 -0.119171142578125 +34941 -0.024749755859375 +34942 0.085784912109375 +34943 0.178131103515625 +34944 0.215576171875 +34945 0.211456298828125 +34946 0.17523193359375 +34947 0.128753662109375 +34948 0.1019287109375 +34949 0.0743408203125 +34950 0.04327392578125 +34951 0.038177490234375 +34952 0.076263427734375 +34953 0.14105224609375 +34954 0.186431884765625 +34955 0.188812255859375 +34956 0.1390380859375 +34957 0.041778564453125 +34958 -0.079437255859375 +34959 -0.219390869140625 +34960 -0.367828369140625 +34961 -0.494873046875 +34962 -0.556243896484375 +34963 -0.508697509765625 +34964 -0.3756103515625 +34965 -0.218902587890625 +34966 -0.063751220703125 +34967 0.091552734375 +34968 0.23602294921875 +34969 0.342987060546875 +34970 0.39520263671875 +34971 0.389373779296875 +34972 0.324249267578125 +34973 0.224090576171875 +34974 0.124267578125 +34975 0.037078857421875 +34976 -0.010101318359375 +34977 -0.019439697265625 +34978 -0.022796630859375 +34979 -0.001556396484375 +34980 0.056304931640625 +34981 0.106719970703125 +34982 0.096893310546875 +34983 0.042694091796875 +34984 -0.018035888671875 +34985 -0.07586669921875 +34986 -0.11944580078125 +34987 -0.15972900390625 +34988 -0.202606201171875 +34989 -0.24859619140625 +34990 -0.30517578125 +34991 -0.36212158203125 +34992 -0.39141845703125 +34993 -0.35528564453125 +34994 -0.249969482421875 +34995 -0.092864990234375 +34996 0.08905029296875 +34997 0.2352294921875 +34998 0.318817138671875 +34999 0.358642578125 +35000 0.347747802734375 +35001 0.28564453125 +35002 0.223175048828125 +35003 0.196746826171875 +35004 0.179840087890625 +35005 0.155548095703125 +35006 0.151214599609375 +35007 0.156951904296875 +35008 0.13177490234375 +35009 0.100799560546875 +35010 0.087127685546875 +35011 0.05487060546875 +35012 -0.009002685546875 +35013 -0.10400390625 +35014 -0.229400634765625 +35015 -0.35552978515625 +35016 -0.441925048828125 +35017 -0.473846435546875 +35018 -0.464813232421875 +35019 -0.419097900390625 +35020 -0.334320068359375 +35021 -0.227935791015625 +35022 -0.12347412109375 +35023 -0.02764892578125 +35024 0.077667236328125 +35025 0.2132568359375 +35026 0.38885498046875 +35027 0.582794189453125 +35028 0.734039306640625 +35029 0.800140380859375 +35030 0.7783203125 +35031 0.6651611328125 +35032 0.45965576171875 +35033 0.199188232421875 +35034 -0.050689697265625 +35035 -0.23297119140625 +35036 -0.33013916015625 +35037 -0.368408203125 +35038 -0.378936767578125 +35039 -0.376983642578125 +35040 -0.37969970703125 +35041 -0.391510009765625 +35042 -0.385345458984375 +35043 -0.3419189453125 +35044 -0.28289794921875 +35045 -0.251617431640625 +35046 -0.266143798828125 +35047 -0.273345947265625 +35048 -0.216796875 +35049 -0.128265380859375 +35050 -0.068145751953125 +35051 -0.0430908203125 +35052 -0.024444580078125 +35053 0.020721435546875 +35054 0.124481201171875 +35055 0.25787353515625 +35056 0.379119873046875 +35057 0.47991943359375 +35058 0.5281982421875 +35059 0.511138916015625 +35060 0.456207275390625 +35061 0.407470703125 +35062 0.383758544921875 +35063 0.35687255859375 +35064 0.31182861328125 +35065 0.250885009765625 +35066 0.1654052734375 +35067 0.035247802734375 +35068 -0.142059326171875 +35069 -0.33563232421875 +35070 -0.5345458984375 +35071 -0.72186279296875 +35072 -0.836669921875 +35073 -0.8326416015625 +35074 -0.7296142578125 +35075 -0.582550048828125 +35076 -0.440093994140625 +35077 -0.324310302734375 +35078 -0.20147705078125 +35079 -0.044647216796875 +35080 0.103973388671875 +35081 0.202392578125 +35082 0.264495849609375 +35083 0.338897705078125 +35084 0.443817138671875 +35085 0.545074462890625 +35086 0.6173095703125 +35087 0.6524658203125 +35088 0.66339111328125 +35089 0.6561279296875 +35090 0.606781005859375 +35091 0.501190185546875 +35092 0.352783203125 +35093 0.176544189453125 +35094 -0.034820556640625 +35095 -0.258209228515625 +35096 -0.44244384765625 +35097 -0.5753173828125 +35098 -0.65203857421875 +35099 -0.641632080078125 +35100 -0.562164306640625 +35101 -0.458038330078125 +35102 -0.350555419921875 +35103 -0.260528564453125 +35104 -0.192108154296875 +35105 -0.141937255859375 +35106 -0.1021728515625 +35107 -0.062896728515625 +35108 -0.011932373046875 +35109 0.062835693359375 +35110 0.148712158203125 +35111 0.241729736328125 +35112 0.34912109375 +35113 0.457305908203125 +35114 0.54388427734375 +35115 0.5728759765625 +35116 0.506591796875 +35117 0.351226806640625 +35118 0.146514892578125 +35119 -0.05523681640625 +35120 -0.21624755859375 +35121 -0.334930419921875 +35122 -0.402984619140625 +35123 -0.4412841796875 +35124 -0.49578857421875 +35125 -0.5601806640625 +35126 -0.600738525390625 +35127 -0.584228515625 +35128 -0.47930908203125 +35129 -0.27935791015625 +35130 -0.0089111328125 +35131 0.268798828125 +35132 0.482818603515625 +35133 0.60369873046875 +35134 0.650421142578125 +35135 0.66400146484375 +35136 0.6414794921875 +35137 0.572540283203125 +35138 0.498138427734375 +35139 0.439453125 +35140 0.375518798828125 +35141 0.274505615234375 +35142 0.1087646484375 +35143 -0.099395751953125 +35144 -0.3182373046875 +35145 -0.5489501953125 +35146 -0.7738037109375 +35147 -0.86383056640625 +35148 -0.870391845703125 +35149 -0.86895751953125 +35150 -0.861053466796875 +35151 -0.765869140625 +35152 -0.5301513671875 +35153 -0.214691162109375 +35154 0.137359619140625 +35155 0.474822998046875 +35156 0.76239013671875 +35157 0.867462158203125 +35158 0.870361328125 +35159 0.86480712890625 +35160 0.831817626953125 +35161 0.677581787109375 +35162 0.495880126953125 +35163 0.30767822265625 +35164 0.116180419921875 +35165 -0.110748291015625 +35166 -0.381805419921875 +35167 -0.6572265625 +35168 -0.857421875 +35169 -0.870391845703125 +35170 -0.870391845703125 +35171 -0.86444091796875 +35172 -0.85723876953125 +35173 -0.790008544921875 +35174 -0.62847900390625 +35175 -0.3956298828125 +35176 -0.126708984375 +35177 0.150115966796875 +35178 0.424041748046875 +35179 0.670623779296875 +35180 0.854522705078125 +35181 0.866485595703125 +35182 0.86920166015625 +35183 0.8653564453125 +35184 0.857147216796875 +35185 0.766845703125 +35186 0.628509521484375 +35187 0.462127685546875 +35188 0.297210693359375 +35189 0.14862060546875 +35190 -0.00537109375 +35191 -0.15753173828125 +35192 -0.31304931640625 +35193 -0.48876953125 +35194 -0.6416015625 +35195 -0.751373291015625 +35196 -0.84619140625 +35197 -0.861297607421875 +35198 -0.863250732421875 +35199 -0.856597900390625 +35200 -0.7498779296875 +35201 -0.624542236328125 +35202 -0.47808837890625 +35203 -0.253387451171875 +35204 0.003692626953125 +35205 0.2257080078125 +35206 0.427154541015625 +35207 0.643218994140625 +35208 0.855926513671875 +35209 0.870361328125 +35210 0.870361328125 +35211 0.862762451171875 +35212 0.79669189453125 +35213 0.595794677734375 +35214 0.362152099609375 +35215 0.1270751953125 +35216 -0.086944580078125 +35217 -0.2784423828125 +35218 -0.484832763671875 +35219 -0.729583740234375 +35220 -0.86688232421875 +35221 -0.870391845703125 +35222 -0.86859130859375 +35223 -0.86279296875 +35224 -0.817962646484375 +35225 -0.6116943359375 +35226 -0.3128662109375 +35227 0.039398193359375 +35228 0.422821044921875 +35229 0.805145263671875 +35230 0.870361328125 +35231 0.870361328125 +35232 0.860015869140625 +35233 0.727935791015625 +35234 0.48114013671875 +35235 0.2059326171875 +35236 -0.06103515625 +35237 -0.29913330078125 +35238 -0.516204833984375 +35239 -0.7252197265625 +35240 -0.85980224609375 +35241 -0.870391845703125 +35242 -0.870391845703125 +35243 -0.858062744140625 +35244 -0.673004150390625 +35245 -0.42694091796875 +35246 -0.2100830078125 +35247 -0.0362548828125 +35248 0.10943603515625 +35249 0.23516845703125 +35250 0.373687744140625 +35251 0.517791748046875 +35252 0.602783203125 +35253 0.635711669921875 +35254 0.655181884765625 +35255 0.65948486328125 +35256 0.651275634765625 +35257 0.61846923828125 +35258 0.53753662109375 +35259 0.404144287109375 +35260 0.22186279296875 +35261 0.003997802734375 +35262 -0.22100830078125 +35263 -0.42449951171875 +35264 -0.579833984375 +35265 -0.641876220703125 +35266 -0.6177978515625 +35267 -0.575531005859375 +35268 -0.526336669921875 +35269 -0.42645263671875 +35270 -0.2581787109375 +35271 -0.068695068359375 +35272 0.09222412109375 +35273 0.232147216796875 +35274 0.3509521484375 +35275 0.410064697265625 +35276 0.372955322265625 +35277 0.2554931640625 +35278 0.10711669921875 +35279 -0.052886962890625 +35280 -0.186279296875 +35281 -0.23291015625 +35282 -0.209442138671875 +35283 -0.174163818359375 +35284 -0.126739501953125 +35285 -0.048126220703125 +35286 0.0426025390625 +35287 0.10748291015625 +35288 0.1409912109375 +35289 0.19708251953125 +35290 0.273651123046875 +35291 0.31768798828125 +35292 0.341094970703125 +35293 0.368011474609375 +35294 0.37249755859375 +35295 0.30072021484375 +35296 0.1517333984375 +35297 -0.01470947265625 +35298 -0.1883544921875 +35299 -0.372711181640625 +35300 -0.51397705078125 +35301 -0.57177734375 +35302 -0.53948974609375 +35303 -0.43511962890625 +35304 -0.2962646484375 +35305 -0.161102294921875 +35306 -0.0435791015625 +35307 0.060394287109375 +35308 0.13665771484375 +35309 0.170135498046875 +35310 0.16552734375 +35311 0.15728759765625 +35312 0.150787353515625 +35313 0.12200927734375 +35314 0.080108642578125 +35315 0.05126953125 +35316 0.062896728515625 +35317 0.09271240234375 +35318 0.092987060546875 +35319 0.07855224609375 +35320 0.06427001953125 +35321 0.0347900390625 +35322 -0.01171875 +35323 -0.056060791015625 +35324 -0.055511474609375 +35325 -0.010467529296875 +35326 0.02508544921875 +35327 0.025665283203125 +35328 0.017333984375 +35329 0.00189208984375 +35330 -0.03173828125 +35331 -0.071502685546875 +35332 -0.13543701171875 +35333 -0.219970703125 +35334 -0.300506591796875 +35335 -0.376312255859375 +35336 -0.416107177734375 +35337 -0.371124267578125 +35338 -0.242279052734375 +35339 -0.069732666015625 +35340 0.125640869140625 +35341 0.31268310546875 +35342 0.45501708984375 +35343 0.554779052734375 +35344 0.61065673828125 +35345 0.610931396484375 +35346 0.531463623046875 +35347 0.3883056640625 +35348 0.23468017578125 +35349 0.095245361328125 +35350 -0.00396728515625 +35351 -0.04852294921875 +35352 -0.055145263671875 +35353 -0.0758056640625 +35354 -0.138702392578125 +35355 -0.209197998046875 +35356 -0.289031982421875 +35357 -0.37884521484375 +35358 -0.456329345703125 +35359 -0.51641845703125 +35360 -0.519287109375 +35361 -0.458251953125 +35362 -0.384796142578125 +35363 -0.323699951171875 +35364 -0.269287109375 +35365 -0.1951904296875 +35366 -0.100006103515625 +35367 -0.01055908203125 +35368 0.1033935546875 +35369 0.24908447265625 +35370 0.373199462890625 +35371 0.45806884765625 +35372 0.511474609375 +35373 0.565399169921875 +35374 0.61138916015625 +35375 0.5897216796875 +35376 0.4906005859375 +35377 0.33148193359375 +35378 0.147796630859375 +35379 -0.01873779296875 +35380 -0.140289306640625 +35381 -0.191986083984375 +35382 -0.184295654296875 +35383 -0.161834716796875 +35384 -0.166595458984375 +35385 -0.19390869140625 +35386 -0.22442626953125 +35387 -0.279754638671875 +35388 -0.3389892578125 +35389 -0.3543701171875 +35390 -0.348175048828125 +35391 -0.32598876953125 +35392 -0.2581787109375 +35393 -0.139801025390625 +35394 0.014617919921875 +35395 0.144378662109375 +35396 0.221038818359375 +35397 0.27069091796875 +35398 0.294036865234375 +35399 0.311767578125 +35400 0.339141845703125 +35401 0.360260009765625 +35402 0.360504150390625 +35403 0.308380126953125 +35404 0.18170166015625 +35405 0.0047607421875 +35406 -0.17559814453125 +35407 -0.3143310546875 +35408 -0.36785888671875 +35409 -0.36248779296875 +35410 -0.343536376953125 +35411 -0.3018798828125 +35412 -0.231414794921875 +35413 -0.117645263671875 +35414 0.007049560546875 +35415 0.087982177734375 +35416 0.13946533203125 +35417 0.17425537109375 +35418 0.188201904296875 +35419 0.171234130859375 +35420 0.118438720703125 +35421 0.05706787109375 +35422 -0.010711669921875 +35423 -0.0914306640625 +35424 -0.162322998046875 +35425 -0.194549560546875 +35426 -0.1492919921875 +35427 -0.02166748046875 +35428 0.124053955078125 +35429 0.211151123046875 +35430 0.240447998046875 +35431 0.242218017578125 +35432 0.2257080078125 +35433 0.194366455078125 +35434 0.115509033203125 +35435 0.0128173828125 +35436 -0.053802490234375 +35437 -0.110626220703125 +35438 -0.199493408203125 +35439 -0.29437255859375 +35440 -0.33221435546875 +35441 -0.27972412109375 +35442 -0.185333251953125 +35443 -0.128204345703125 +35444 -0.115692138671875 +35445 -0.116455078125 +35446 -0.105926513671875 +35447 -0.053955078125 +35448 0.048797607421875 +35449 0.157318115234375 +35450 0.212005615234375 +35451 0.218475341796875 +35452 0.23724365234375 +35453 0.30535888671875 +35454 0.38128662109375 +35455 0.404449462890625 +35456 0.3944091796875 +35457 0.3885498046875 +35458 0.362640380859375 +35459 0.27362060546875 +35460 0.11712646484375 +35461 -0.054901123046875 +35462 -0.19085693359375 +35463 -0.28570556640625 +35464 -0.339263916015625 +35465 -0.3775634765625 +35466 -0.445709228515625 +35467 -0.535064697265625 +35468 -0.629058837890625 +35469 -0.697601318359375 +35470 -0.70391845703125 +35471 -0.6424560546875 +35472 -0.491241455078125 +35473 -0.265716552734375 +35474 -0.023712158203125 +35475 0.201751708984375 +35476 0.375823974609375 +35477 0.485076904296875 +35478 0.56884765625 +35479 0.634765625 +35480 0.63763427734375 +35481 0.5660400390625 +35482 0.4720458984375 +35483 0.40692138671875 +35484 0.3778076171875 +35485 0.376953125 +35486 0.371978759765625 +35487 0.313140869140625 +35488 0.184417724609375 +35489 0.011199951171875 +35490 -0.171051025390625 +35491 -0.33740234375 +35492 -0.47198486328125 +35493 -0.560394287109375 +35494 -0.58056640625 +35495 -0.54754638671875 +35496 -0.508575439453125 +35497 -0.459503173828125 +35498 -0.394378662109375 +35499 -0.35260009765625 +35500 -0.31170654296875 +35501 -0.197418212890625 +35502 -0.007965087890625 +35503 0.207489013671875 +35504 0.409210205078125 +35505 0.57208251953125 +35506 0.66595458984375 +35507 0.65875244140625 +35508 0.56744384765625 +35509 0.431396484375 +35510 0.29443359375 +35511 0.182464599609375 +35512 0.06365966796875 +35513 -0.075958251953125 +35514 -0.189422607421875 +35515 -0.271942138671875 +35516 -0.342529296875 +35517 -0.364166259765625 +35518 -0.327239990234375 +35519 -0.2769775390625 +35520 -0.253692626953125 +35521 -0.24365234375 +35522 -0.1983642578125 +35523 -0.116241455078125 +35524 -0.036834716796875 +35525 0.034881591796875 +35526 0.09124755859375 +35527 0.10888671875 +35528 0.125518798828125 +35529 0.15771484375 +35530 0.17828369140625 +35531 0.17108154296875 +35532 0.129974365234375 +35533 0.082427978515625 +35534 0.027679443359375 +35535 -0.065643310546875 +35536 -0.15936279296875 +35537 -0.21307373046875 +35538 -0.234649658203125 +35539 -0.2001953125 +35540 -0.119171142578125 +35541 -0.024749755859375 +35542 0.085784912109375 +35543 0.178131103515625 +35544 0.215576171875 +35545 0.211456298828125 +35546 0.17523193359375 +35547 0.128753662109375 +35548 0.1019287109375 +35549 0.0743408203125 +35550 0.04327392578125 +35551 0.038177490234375 +35552 0.076263427734375 +35553 0.14105224609375 +35554 0.186431884765625 +35555 0.188812255859375 +35556 0.1390380859375 +35557 0.041778564453125 +35558 -0.079437255859375 +35559 -0.219390869140625 +35560 -0.367828369140625 +35561 -0.494873046875 +35562 -0.556243896484375 +35563 -0.508697509765625 +35564 -0.3756103515625 +35565 -0.218902587890625 +35566 -0.063751220703125 +35567 0.091552734375 +35568 0.23602294921875 +35569 0.342987060546875 +35570 0.39520263671875 +35571 0.389373779296875 +35572 0.324249267578125 +35573 0.224090576171875 +35574 0.124267578125 +35575 0.037078857421875 +35576 -0.010101318359375 +35577 -0.019439697265625 +35578 -0.022796630859375 +35579 -0.001556396484375 +35580 0.056304931640625 +35581 0.106719970703125 +35582 0.096893310546875 +35583 0.042694091796875 +35584 -0.018035888671875 +35585 -0.07586669921875 +35586 -0.11944580078125 +35587 -0.15972900390625 +35588 -0.202606201171875 +35589 -0.24859619140625 +35590 -0.30517578125 +35591 -0.36212158203125 +35592 -0.39141845703125 +35593 -0.35528564453125 +35594 -0.249969482421875 +35595 -0.092864990234375 +35596 0.08905029296875 +35597 0.2352294921875 +35598 0.318817138671875 +35599 0.358642578125 +35600 0.347747802734375 +35601 0.28564453125 +35602 0.223175048828125 +35603 0.196746826171875 +35604 0.179840087890625 +35605 0.155548095703125 +35606 0.151214599609375 +35607 0.156951904296875 +35608 0.13177490234375 +35609 0.100799560546875 +35610 0.087127685546875 +35611 0.05487060546875 +35612 -0.009002685546875 +35613 -0.10400390625 +35614 -0.229400634765625 +35615 -0.35552978515625 +35616 -0.441925048828125 +35617 -0.473846435546875 +35618 -0.464813232421875 +35619 -0.419097900390625 +35620 -0.334320068359375 +35621 -0.227935791015625 +35622 -0.12347412109375 +35623 -0.02764892578125 +35624 0.077667236328125 +35625 0.2132568359375 +35626 0.38885498046875 +35627 0.582794189453125 +35628 0.734039306640625 +35629 0.800140380859375 +35630 0.7783203125 +35631 0.6651611328125 +35632 0.45965576171875 +35633 0.199188232421875 +35634 -0.050689697265625 +35635 -0.23297119140625 +35636 -0.33013916015625 +35637 -0.368408203125 +35638 -0.378936767578125 +35639 -0.376983642578125 +35640 -0.37969970703125 +35641 -0.391510009765625 +35642 -0.385345458984375 +35643 -0.3419189453125 +35644 -0.28289794921875 +35645 -0.251617431640625 +35646 -0.266143798828125 +35647 -0.273345947265625 +35648 -0.216796875 +35649 -0.128265380859375 +35650 -0.068145751953125 +35651 -0.0430908203125 +35652 -0.024444580078125 +35653 0.020721435546875 +35654 0.124481201171875 +35655 0.25787353515625 +35656 0.379119873046875 +35657 0.47991943359375 +35658 0.5281982421875 +35659 0.511138916015625 +35660 0.456207275390625 +35661 0.407470703125 +35662 0.383758544921875 +35663 0.35687255859375 +35664 0.31182861328125 +35665 0.250885009765625 +35666 0.1654052734375 +35667 0.035247802734375 +35668 -0.142059326171875 +35669 -0.33563232421875 +35670 -0.5345458984375 +35671 -0.72186279296875 +35672 -0.836669921875 +35673 -0.8326416015625 +35674 -0.7296142578125 +35675 -0.582550048828125 +35676 -0.440093994140625 +35677 -0.324310302734375 +35678 -0.20147705078125 +35679 -0.044647216796875 +35680 0.103973388671875 +35681 0.202392578125 +35682 0.264495849609375 +35683 0.338897705078125 +35684 0.443817138671875 +35685 0.545074462890625 +35686 0.6173095703125 +35687 0.6524658203125 +35688 0.66339111328125 +35689 0.6561279296875 +35690 0.606781005859375 +35691 0.501190185546875 +35692 0.352783203125 +35693 0.176544189453125 +35694 -0.034820556640625 +35695 -0.258209228515625 +35696 -0.44244384765625 +35697 -0.5753173828125 +35698 -0.65203857421875 +35699 -0.641632080078125 +35700 -0.562164306640625 +35701 -0.458038330078125 +35702 -0.350555419921875 +35703 -0.260528564453125 +35704 -0.192108154296875 +35705 -0.141937255859375 +35706 -0.1021728515625 +35707 -0.062896728515625 +35708 -0.011932373046875 +35709 0.062835693359375 +35710 0.148712158203125 +35711 0.241729736328125 +35712 0.34912109375 +35713 0.457305908203125 +35714 0.54388427734375 +35715 0.5728759765625 +35716 0.506591796875 +35717 0.351226806640625 +35718 0.146514892578125 +35719 -0.05523681640625 +35720 -0.21624755859375 +35721 -0.334930419921875 +35722 -0.402984619140625 +35723 -0.4412841796875 +35724 -0.49578857421875 +35725 -0.5601806640625 +35726 -0.600738525390625 +35727 -0.584228515625 +35728 -0.47930908203125 +35729 -0.27935791015625 +35730 -0.0089111328125 +35731 0.268798828125 +35732 0.482818603515625 +35733 0.60369873046875 +35734 0.650421142578125 +35735 0.66400146484375 +35736 0.6414794921875 +35737 0.572540283203125 +35738 0.498138427734375 +35739 0.439453125 +35740 0.375518798828125 +35741 0.274505615234375 +35742 0.1087646484375 +35743 -0.099395751953125 +35744 -0.3182373046875 +35745 -0.5489501953125 +35746 -0.7738037109375 +35747 -0.86383056640625 +35748 -0.870391845703125 +35749 -0.86895751953125 +35750 -0.861053466796875 +35751 -0.765869140625 +35752 -0.5301513671875 +35753 -0.214691162109375 +35754 0.137359619140625 +35755 0.474822998046875 +35756 0.76239013671875 +35757 0.867462158203125 +35758 0.870361328125 +35759 0.86480712890625 +35760 0.831817626953125 +35761 0.677581787109375 +35762 0.495880126953125 +35763 0.30767822265625 +35764 0.116180419921875 +35765 -0.110748291015625 +35766 -0.381805419921875 +35767 -0.6572265625 +35768 -0.857421875 +35769 -0.870391845703125 +35770 -0.870391845703125 +35771 -0.86444091796875 +35772 -0.85723876953125 +35773 -0.790008544921875 +35774 -0.62847900390625 +35775 -0.3956298828125 +35776 -0.126708984375 +35777 0.150115966796875 +35778 0.424041748046875 +35779 0.670623779296875 +35780 0.854522705078125 +35781 0.866485595703125 +35782 0.86920166015625 +35783 0.8653564453125 +35784 0.857147216796875 +35785 0.766845703125 +35786 0.628509521484375 +35787 0.462127685546875 +35788 0.297210693359375 +35789 0.14862060546875 +35790 -0.00537109375 +35791 -0.15753173828125 +35792 -0.31304931640625 +35793 -0.48876953125 +35794 -0.6416015625 +35795 -0.751373291015625 +35796 -0.84619140625 +35797 -0.861297607421875 +35798 -0.863250732421875 +35799 -0.856597900390625 +35800 -0.7498779296875 +35801 -0.624542236328125 +35802 -0.47808837890625 +35803 -0.253387451171875 +35804 0.003692626953125 +35805 0.2257080078125 +35806 0.427154541015625 +35807 0.643218994140625 +35808 0.855926513671875 +35809 0.870361328125 +35810 0.870361328125 +35811 0.862762451171875 +35812 0.79669189453125 +35813 0.595794677734375 +35814 0.362152099609375 +35815 0.1270751953125 +35816 -0.086944580078125 +35817 -0.2784423828125 +35818 -0.484832763671875 +35819 -0.729583740234375 +35820 -0.86688232421875 +35821 -0.870391845703125 +35822 -0.86859130859375 +35823 -0.86279296875 +35824 -0.817962646484375 +35825 -0.6116943359375 +35826 -0.3128662109375 +35827 0.039398193359375 +35828 0.422821044921875 +35829 0.805145263671875 +35830 0.870361328125 +35831 0.870361328125 +35832 0.860015869140625 +35833 0.727935791015625 +35834 0.48114013671875 +35835 0.2059326171875 +35836 -0.06103515625 +35837 -0.29913330078125 +35838 -0.516204833984375 +35839 -0.7252197265625 +35840 -0.85980224609375 +35841 -0.870391845703125 +35842 -0.870391845703125 +35843 -0.858062744140625 +35844 -0.673004150390625 +35845 -0.42694091796875 +35846 -0.2100830078125 +35847 -0.0362548828125 +35848 0.10943603515625 +35849 0.23516845703125 +35850 0.373687744140625 +35851 0.517791748046875 +35852 0.602783203125 +35853 0.635711669921875 +35854 0.655181884765625 +35855 0.65948486328125 +35856 0.651275634765625 +35857 0.61846923828125 +35858 0.53753662109375 +35859 0.404144287109375 +35860 0.22186279296875 +35861 0.003997802734375 +35862 -0.22100830078125 +35863 -0.42449951171875 +35864 -0.579833984375 +35865 -0.641876220703125 +35866 -0.6177978515625 +35867 -0.575531005859375 +35868 -0.526336669921875 +35869 -0.42645263671875 +35870 -0.2581787109375 +35871 -0.068695068359375 +35872 0.09222412109375 +35873 0.232147216796875 +35874 0.3509521484375 +35875 0.410064697265625 +35876 0.372955322265625 +35877 0.2554931640625 +35878 0.10711669921875 +35879 -0.052886962890625 +35880 -0.186279296875 +35881 -0.23291015625 +35882 -0.209442138671875 +35883 -0.174163818359375 +35884 -0.126739501953125 +35885 -0.048126220703125 +35886 0.0426025390625 +35887 0.10748291015625 +35888 0.1409912109375 +35889 0.19708251953125 +35890 0.273651123046875 +35891 0.31768798828125 +35892 0.341094970703125 +35893 0.368011474609375 +35894 0.37249755859375 +35895 0.30072021484375 +35896 0.1517333984375 +35897 -0.01470947265625 +35898 -0.1883544921875 +35899 -0.372711181640625 +35900 -0.51397705078125 +35901 -0.57177734375 +35902 -0.53948974609375 +35903 -0.43511962890625 +35904 -0.2962646484375 +35905 -0.161102294921875 +35906 -0.0435791015625 +35907 0.060394287109375 +35908 0.13665771484375 +35909 0.170135498046875 +35910 0.16552734375 +35911 0.15728759765625 +35912 0.150787353515625 +35913 0.12200927734375 +35914 0.080108642578125 +35915 0.05126953125 +35916 0.062896728515625 +35917 0.09271240234375 +35918 0.092987060546875 +35919 0.07855224609375 +35920 0.06427001953125 +35921 0.0347900390625 +35922 -0.01171875 +35923 -0.056060791015625 +35924 -0.055511474609375 +35925 -0.010467529296875 +35926 0.02508544921875 +35927 0.025665283203125 +35928 0.017333984375 +35929 0.00189208984375 +35930 -0.03173828125 +35931 -0.071502685546875 +35932 -0.13543701171875 +35933 -0.219970703125 +35934 -0.300506591796875 +35935 -0.376312255859375 +35936 -0.416107177734375 +35937 -0.371124267578125 +35938 -0.242279052734375 +35939 -0.069732666015625 +35940 0.125640869140625 +35941 0.31268310546875 +35942 0.45501708984375 +35943 0.554779052734375 +35944 0.61065673828125 +35945 0.610931396484375 +35946 0.531463623046875 +35947 0.3883056640625 +35948 0.23468017578125 +35949 0.095245361328125 +35950 -0.00396728515625 +35951 -0.04852294921875 +35952 -0.055145263671875 +35953 -0.0758056640625 +35954 -0.138702392578125 +35955 -0.209197998046875 +35956 -0.289031982421875 +35957 -0.37884521484375 +35958 -0.456329345703125 +35959 -0.51641845703125 +35960 -0.519287109375 +35961 -0.458251953125 +35962 -0.384796142578125 +35963 -0.323699951171875 +35964 -0.269287109375 +35965 -0.1951904296875 +35966 -0.100006103515625 +35967 -0.01055908203125 +35968 0.1033935546875 +35969 0.24908447265625 +35970 0.373199462890625 +35971 0.45806884765625 +35972 0.511474609375 +35973 0.565399169921875 +35974 0.61138916015625 +35975 0.5897216796875 +35976 0.4906005859375 +35977 0.33148193359375 +35978 0.147796630859375 +35979 -0.01873779296875 +35980 -0.140289306640625 +35981 -0.191986083984375 +35982 -0.184295654296875 +35983 -0.161834716796875 +35984 -0.166595458984375 +35985 -0.19390869140625 +35986 -0.22442626953125 +35987 -0.279754638671875 +35988 -0.3389892578125 +35989 -0.3543701171875 +35990 -0.348175048828125 +35991 -0.32598876953125 +35992 -0.2581787109375 +35993 -0.139801025390625 +35994 0.014617919921875 +35995 0.144378662109375 +35996 0.221038818359375 +35997 0.27069091796875 +35998 0.294036865234375 +35999 0.311767578125 +36000 0.339141845703125 +36001 0.360260009765625 +36002 0.360504150390625 +36003 0.308380126953125 +36004 0.18170166015625 +36005 0.0047607421875 +36006 -0.17559814453125 +36007 -0.3143310546875 +36008 -0.36785888671875 +36009 -0.36248779296875 +36010 -0.343536376953125 +36011 -0.3018798828125 +36012 -0.231414794921875 +36013 -0.117645263671875 +36014 0.007049560546875 +36015 0.087982177734375 +36016 0.13946533203125 +36017 0.17425537109375 +36018 0.188201904296875 +36019 0.171234130859375 +36020 0.118438720703125 +36021 0.05706787109375 +36022 -0.010711669921875 +36023 -0.0914306640625 +36024 -0.162322998046875 +36025 -0.194549560546875 +36026 -0.1492919921875 +36027 -0.02166748046875 +36028 0.124053955078125 +36029 0.211151123046875 +36030 0.240447998046875 +36031 0.242218017578125 +36032 0.2257080078125 +36033 0.194366455078125 +36034 0.115509033203125 +36035 0.0128173828125 +36036 -0.053802490234375 +36037 -0.110626220703125 +36038 -0.199493408203125 +36039 -0.29437255859375 +36040 -0.33221435546875 +36041 -0.27972412109375 +36042 -0.185333251953125 +36043 -0.128204345703125 +36044 -0.115692138671875 +36045 -0.116455078125 +36046 -0.105926513671875 +36047 -0.053955078125 +36048 0.048797607421875 +36049 0.157318115234375 +36050 0.212005615234375 +36051 0.218475341796875 +36052 0.23724365234375 +36053 0.30535888671875 +36054 0.38128662109375 +36055 0.404449462890625 +36056 0.3944091796875 +36057 0.3885498046875 +36058 0.362640380859375 +36059 0.27362060546875 +36060 0.11712646484375 +36061 -0.054901123046875 +36062 -0.19085693359375 +36063 -0.28570556640625 +36064 -0.339263916015625 +36065 -0.3775634765625 +36066 -0.445709228515625 +36067 -0.535064697265625 +36068 -0.629058837890625 +36069 -0.697601318359375 +36070 -0.70391845703125 +36071 -0.6424560546875 +36072 -0.491241455078125 +36073 -0.265716552734375 +36074 -0.023712158203125 +36075 0.201751708984375 +36076 0.375823974609375 +36077 0.485076904296875 +36078 0.56884765625 +36079 0.634765625 +36080 0.63763427734375 +36081 0.5660400390625 +36082 0.4720458984375 +36083 0.40692138671875 +36084 0.3778076171875 +36085 0.376953125 +36086 0.371978759765625 +36087 0.313140869140625 +36088 0.184417724609375 +36089 0.011199951171875 +36090 -0.171051025390625 +36091 -0.33740234375 +36092 -0.47198486328125 +36093 -0.560394287109375 +36094 -0.58056640625 +36095 -0.54754638671875 +36096 -0.508575439453125 +36097 -0.459503173828125 +36098 -0.394378662109375 +36099 -0.35260009765625 +36100 -0.31170654296875 +36101 -0.197418212890625 +36102 -0.007965087890625 +36103 0.207489013671875 +36104 0.409210205078125 +36105 0.57208251953125 +36106 0.66595458984375 +36107 0.65875244140625 +36108 0.56744384765625 +36109 0.431396484375 +36110 0.29443359375 +36111 0.182464599609375 +36112 0.06365966796875 +36113 -0.075958251953125 +36114 -0.189422607421875 +36115 -0.271942138671875 +36116 -0.342529296875 +36117 -0.364166259765625 +36118 -0.327239990234375 +36119 -0.2769775390625 +36120 -0.253692626953125 +36121 -0.24365234375 +36122 -0.1983642578125 +36123 -0.116241455078125 +36124 -0.036834716796875 +36125 0.034881591796875 +36126 0.09124755859375 +36127 0.10888671875 +36128 0.125518798828125 +36129 0.15771484375 +36130 0.17828369140625 +36131 0.17108154296875 +36132 0.129974365234375 +36133 0.082427978515625 +36134 0.027679443359375 +36135 -0.065643310546875 +36136 -0.15936279296875 +36137 -0.21307373046875 +36138 -0.234649658203125 +36139 -0.2001953125 +36140 -0.119171142578125 +36141 -0.024749755859375 +36142 0.085784912109375 +36143 0.178131103515625 +36144 0.215576171875 +36145 0.211456298828125 +36146 0.17523193359375 +36147 0.128753662109375 +36148 0.1019287109375 +36149 0.0743408203125 +36150 0.04327392578125 +36151 0.038177490234375 +36152 0.076263427734375 +36153 0.14105224609375 +36154 0.186431884765625 +36155 0.188812255859375 +36156 0.1390380859375 +36157 0.041778564453125 +36158 -0.079437255859375 +36159 -0.219390869140625 +36160 -0.367828369140625 +36161 -0.494873046875 +36162 -0.556243896484375 +36163 -0.508697509765625 +36164 -0.3756103515625 +36165 -0.218902587890625 +36166 -0.063751220703125 +36167 0.091552734375 +36168 0.23602294921875 +36169 0.342987060546875 +36170 0.39520263671875 +36171 0.389373779296875 +36172 0.324249267578125 +36173 0.224090576171875 +36174 0.124267578125 +36175 0.037078857421875 +36176 -0.010101318359375 +36177 -0.019439697265625 +36178 -0.022796630859375 +36179 -0.001556396484375 +36180 0.056304931640625 +36181 0.106719970703125 +36182 0.096893310546875 +36183 0.042694091796875 +36184 -0.018035888671875 +36185 -0.07586669921875 +36186 -0.11944580078125 +36187 -0.15972900390625 +36188 -0.202606201171875 +36189 -0.24859619140625 +36190 -0.30517578125 +36191 -0.36212158203125 +36192 -0.39141845703125 +36193 -0.35528564453125 +36194 -0.249969482421875 +36195 -0.092864990234375 +36196 0.08905029296875 +36197 0.2352294921875 +36198 0.318817138671875 +36199 0.358642578125 +36200 0.347747802734375 +36201 0.28564453125 +36202 0.223175048828125 +36203 0.196746826171875 +36204 0.179840087890625 +36205 0.155548095703125 +36206 0.151214599609375 +36207 0.156951904296875 +36208 0.13177490234375 +36209 0.100799560546875 +36210 0.087127685546875 +36211 0.05487060546875 +36212 -0.009002685546875 +36213 -0.10400390625 +36214 -0.229400634765625 +36215 -0.35552978515625 +36216 -0.441925048828125 +36217 -0.473846435546875 +36218 -0.464813232421875 +36219 -0.419097900390625 +36220 -0.334320068359375 +36221 -0.227935791015625 +36222 -0.12347412109375 +36223 -0.02764892578125 +36224 0.077667236328125 +36225 0.2132568359375 +36226 0.38885498046875 +36227 0.582794189453125 +36228 0.734039306640625 +36229 0.800140380859375 +36230 0.7783203125 +36231 0.6651611328125 +36232 0.45965576171875 +36233 0.199188232421875 +36234 -0.050689697265625 +36235 -0.23297119140625 +36236 -0.33013916015625 +36237 -0.368408203125 +36238 -0.378936767578125 +36239 -0.376983642578125 +36240 -0.37969970703125 +36241 -0.391510009765625 +36242 -0.385345458984375 +36243 -0.3419189453125 +36244 -0.28289794921875 +36245 -0.251617431640625 +36246 -0.266143798828125 +36247 -0.273345947265625 +36248 -0.216796875 +36249 -0.128265380859375 +36250 -0.068145751953125 +36251 -0.0430908203125 +36252 -0.024444580078125 +36253 0.020721435546875 +36254 0.124481201171875 +36255 0.25787353515625 +36256 0.379119873046875 +36257 0.47991943359375 +36258 0.5281982421875 +36259 0.511138916015625 +36260 0.456207275390625 +36261 0.407470703125 +36262 0.383758544921875 +36263 0.35687255859375 +36264 0.31182861328125 +36265 0.250885009765625 +36266 0.1654052734375 +36267 0.035247802734375 +36268 -0.142059326171875 +36269 -0.33563232421875 +36270 -0.5345458984375 +36271 -0.72186279296875 +36272 -0.836669921875 +36273 -0.8326416015625 +36274 -0.7296142578125 +36275 -0.582550048828125 +36276 -0.440093994140625 +36277 -0.324310302734375 +36278 -0.20147705078125 +36279 -0.044647216796875 +36280 0.103973388671875 +36281 0.202392578125 +36282 0.264495849609375 +36283 0.338897705078125 +36284 0.443817138671875 +36285 0.545074462890625 +36286 0.6173095703125 +36287 0.6524658203125 +36288 0.66339111328125 +36289 0.6561279296875 +36290 0.606781005859375 +36291 0.501190185546875 +36292 0.352783203125 +36293 0.176544189453125 +36294 -0.034820556640625 +36295 -0.258209228515625 +36296 -0.44244384765625 +36297 -0.5753173828125 +36298 -0.65203857421875 +36299 -0.641632080078125 +36300 -0.562164306640625 +36301 -0.458038330078125 +36302 -0.350555419921875 +36303 -0.260528564453125 +36304 -0.192108154296875 +36305 -0.141937255859375 +36306 -0.1021728515625 +36307 -0.062896728515625 +36308 -0.011932373046875 +36309 0.062835693359375 +36310 0.148712158203125 +36311 0.241729736328125 +36312 0.34912109375 +36313 0.457305908203125 +36314 0.54388427734375 +36315 0.5728759765625 +36316 0.506591796875 +36317 0.351226806640625 +36318 0.146514892578125 +36319 -0.05523681640625 +36320 -0.21624755859375 +36321 -0.334930419921875 +36322 -0.402984619140625 +36323 -0.4412841796875 +36324 -0.49578857421875 +36325 -0.5601806640625 +36326 -0.600738525390625 +36327 -0.584228515625 +36328 -0.47930908203125 +36329 -0.27935791015625 +36330 -0.0089111328125 +36331 0.268798828125 +36332 0.482818603515625 +36333 0.60369873046875 +36334 0.650421142578125 +36335 0.66400146484375 +36336 0.6414794921875 +36337 0.572540283203125 +36338 0.498138427734375 +36339 0.439453125 +36340 0.375518798828125 +36341 0.274505615234375 +36342 0.1087646484375 +36343 -0.099395751953125 +36344 -0.3182373046875 +36345 -0.5489501953125 +36346 -0.7738037109375 +36347 -0.86383056640625 +36348 -0.870391845703125 +36349 -0.86895751953125 +36350 -0.861053466796875 +36351 -0.765869140625 +36352 -0.5301513671875 +36353 -0.214691162109375 +36354 0.137359619140625 +36355 0.474822998046875 +36356 0.76239013671875 +36357 0.867462158203125 +36358 0.870361328125 +36359 0.86480712890625 +36360 0.831817626953125 +36361 0.677581787109375 +36362 0.495880126953125 +36363 0.30767822265625 +36364 0.116180419921875 +36365 -0.110748291015625 +36366 -0.381805419921875 +36367 -0.6572265625 +36368 -0.857421875 +36369 -0.870391845703125 +36370 -0.870391845703125 +36371 -0.86444091796875 +36372 -0.85723876953125 +36373 -0.790008544921875 +36374 -0.62847900390625 +36375 -0.3956298828125 +36376 -0.126708984375 +36377 0.150115966796875 +36378 0.424041748046875 +36379 0.670623779296875 +36380 0.854522705078125 +36381 0.866485595703125 +36382 0.86920166015625 +36383 0.8653564453125 +36384 0.857147216796875 +36385 0.766845703125 +36386 0.628509521484375 +36387 0.462127685546875 +36388 0.297210693359375 +36389 0.14862060546875 +36390 -0.00537109375 +36391 -0.15753173828125 +36392 -0.31304931640625 +36393 -0.48876953125 +36394 -0.6416015625 +36395 -0.751373291015625 +36396 -0.84619140625 +36397 -0.861297607421875 +36398 -0.863250732421875 +36399 -0.856597900390625 +36400 -0.7498779296875 +36401 -0.624542236328125 +36402 -0.47808837890625 +36403 -0.253387451171875 +36404 0.003692626953125 +36405 0.2257080078125 +36406 0.427154541015625 +36407 0.643218994140625 +36408 0.855926513671875 +36409 0.870361328125 +36410 0.870361328125 +36411 0.862762451171875 +36412 0.79669189453125 +36413 0.595794677734375 +36414 0.362152099609375 +36415 0.1270751953125 +36416 -0.086944580078125 +36417 -0.2784423828125 +36418 -0.484832763671875 +36419 -0.729583740234375 +36420 -0.86688232421875 +36421 -0.870391845703125 +36422 -0.86859130859375 +36423 -0.86279296875 +36424 -0.817962646484375 +36425 -0.6116943359375 +36426 -0.3128662109375 +36427 0.039398193359375 +36428 0.422821044921875 +36429 0.805145263671875 +36430 0.870361328125 +36431 0.870361328125 +36432 0.860015869140625 +36433 0.727935791015625 +36434 0.48114013671875 +36435 0.2059326171875 +36436 -0.06103515625 +36437 -0.29913330078125 +36438 -0.516204833984375 +36439 -0.7252197265625 +36440 -0.85980224609375 +36441 -0.870391845703125 +36442 -0.870391845703125 +36443 -0.858062744140625 +36444 -0.673004150390625 +36445 -0.42694091796875 +36446 -0.2100830078125 +36447 -0.0362548828125 +36448 0.10943603515625 +36449 0.23516845703125 +36450 0.373687744140625 +36451 0.517791748046875 +36452 0.602783203125 +36453 0.635711669921875 +36454 0.655181884765625 +36455 0.65948486328125 +36456 0.651275634765625 +36457 0.61846923828125 +36458 0.53753662109375 +36459 0.404144287109375 +36460 0.22186279296875 +36461 0.003997802734375 +36462 -0.22100830078125 +36463 -0.42449951171875 +36464 -0.579833984375 +36465 -0.641876220703125 +36466 -0.6177978515625 +36467 -0.575531005859375 +36468 -0.526336669921875 +36469 -0.42645263671875 +36470 -0.2581787109375 +36471 -0.068695068359375 +36472 0.09222412109375 +36473 0.232147216796875 +36474 0.3509521484375 +36475 0.410064697265625 +36476 0.372955322265625 +36477 0.2554931640625 +36478 0.10711669921875 +36479 -0.052886962890625 +36480 -0.186279296875 +36481 -0.23291015625 +36482 -0.209442138671875 +36483 -0.174163818359375 +36484 -0.126739501953125 +36485 -0.048126220703125 +36486 0.0426025390625 +36487 0.10748291015625 +36488 0.1409912109375 +36489 0.19708251953125 +36490 0.273651123046875 +36491 0.31768798828125 +36492 0.341094970703125 +36493 0.368011474609375 +36494 0.37249755859375 +36495 0.30072021484375 +36496 0.1517333984375 +36497 -0.01470947265625 +36498 -0.1883544921875 +36499 -0.372711181640625 +36500 -0.51397705078125 +36501 -0.57177734375 +36502 -0.53948974609375 +36503 -0.43511962890625 +36504 -0.2962646484375 +36505 -0.161102294921875 +36506 -0.0435791015625 +36507 0.060394287109375 +36508 0.13665771484375 +36509 0.170135498046875 +36510 0.16552734375 +36511 0.15728759765625 +36512 0.150787353515625 +36513 0.12200927734375 +36514 0.080108642578125 +36515 0.05126953125 +36516 0.062896728515625 +36517 0.09271240234375 +36518 0.092987060546875 +36519 0.07855224609375 +36520 0.06427001953125 +36521 0.0347900390625 +36522 -0.01171875 +36523 -0.056060791015625 +36524 -0.055511474609375 +36525 -0.010467529296875 +36526 0.02508544921875 +36527 0.025665283203125 +36528 0.017333984375 +36529 0.00189208984375 +36530 -0.03173828125 +36531 -0.071502685546875 +36532 -0.13543701171875 +36533 -0.219970703125 +36534 -0.300506591796875 +36535 -0.376312255859375 +36536 -0.416107177734375 +36537 -0.371124267578125 +36538 -0.242279052734375 +36539 -0.069732666015625 +36540 0.125640869140625 +36541 0.31268310546875 +36542 0.45501708984375 +36543 0.554779052734375 +36544 0.61065673828125 +36545 0.610931396484375 +36546 0.531463623046875 +36547 0.3883056640625 +36548 0.23468017578125 +36549 0.095245361328125 +36550 -0.00396728515625 +36551 -0.04852294921875 +36552 -0.055145263671875 +36553 -0.0758056640625 +36554 -0.138702392578125 +36555 -0.209197998046875 +36556 -0.289031982421875 +36557 -0.37884521484375 +36558 -0.456329345703125 +36559 -0.51641845703125 +36560 -0.519287109375 +36561 -0.458251953125 +36562 -0.384796142578125 +36563 -0.323699951171875 +36564 -0.269287109375 +36565 -0.1951904296875 +36566 -0.100006103515625 +36567 -0.01055908203125 +36568 0.1033935546875 +36569 0.24908447265625 +36570 0.373199462890625 +36571 0.45806884765625 +36572 0.511474609375 +36573 0.565399169921875 +36574 0.61138916015625 +36575 0.5897216796875 +36576 0.4906005859375 +36577 0.33148193359375 +36578 0.147796630859375 +36579 -0.01873779296875 +36580 -0.140289306640625 +36581 -0.191986083984375 +36582 -0.184295654296875 +36583 -0.161834716796875 +36584 -0.166595458984375 +36585 -0.19390869140625 +36586 -0.22442626953125 +36587 -0.279754638671875 +36588 -0.3389892578125 +36589 -0.3543701171875 +36590 -0.348175048828125 +36591 -0.32598876953125 +36592 -0.2581787109375 +36593 -0.139801025390625 +36594 0.014617919921875 +36595 0.144378662109375 +36596 0.221038818359375 +36597 0.27069091796875 +36598 0.294036865234375 +36599 0.311767578125 +36600 0.339141845703125 +36601 0.360260009765625 +36602 0.360504150390625 +36603 0.308380126953125 +36604 0.18170166015625 +36605 0.0047607421875 +36606 -0.17559814453125 +36607 -0.3143310546875 +36608 -0.36785888671875 +36609 -0.36248779296875 +36610 -0.343536376953125 +36611 -0.3018798828125 +36612 -0.231414794921875 +36613 -0.117645263671875 +36614 0.007049560546875 +36615 0.087982177734375 +36616 0.13946533203125 +36617 0.17425537109375 +36618 0.188201904296875 +36619 0.171234130859375 +36620 0.118438720703125 +36621 0.05706787109375 +36622 -0.010711669921875 +36623 -0.0914306640625 +36624 -0.162322998046875 +36625 -0.194549560546875 +36626 -0.1492919921875 +36627 -0.02166748046875 +36628 0.124053955078125 +36629 0.211151123046875 +36630 0.240447998046875 +36631 0.242218017578125 +36632 0.2257080078125 +36633 0.194366455078125 +36634 0.115509033203125 +36635 0.0128173828125 +36636 -0.053802490234375 +36637 -0.110626220703125 +36638 -0.199493408203125 +36639 -0.29437255859375 +36640 -0.33221435546875 +36641 -0.27972412109375 +36642 -0.185333251953125 +36643 -0.128204345703125 +36644 -0.115692138671875 +36645 -0.116455078125 +36646 -0.105926513671875 +36647 -0.053955078125 +36648 0.048797607421875 +36649 0.157318115234375 +36650 0.212005615234375 +36651 0.218475341796875 +36652 0.23724365234375 +36653 0.30535888671875 +36654 0.38128662109375 +36655 0.404449462890625 +36656 0.3944091796875 +36657 0.3885498046875 +36658 0.362640380859375 +36659 0.27362060546875 +36660 0.11712646484375 +36661 -0.054901123046875 +36662 -0.19085693359375 +36663 -0.28570556640625 +36664 -0.339263916015625 +36665 -0.3775634765625 +36666 -0.445709228515625 +36667 -0.535064697265625 +36668 -0.629058837890625 +36669 -0.697601318359375 +36670 -0.70391845703125 +36671 -0.6424560546875 +36672 -0.491241455078125 +36673 -0.265716552734375 +36674 -0.023712158203125 +36675 0.201751708984375 +36676 0.375823974609375 +36677 0.485076904296875 +36678 0.56884765625 +36679 0.634765625 +36680 0.63763427734375 +36681 0.5660400390625 +36682 0.4720458984375 +36683 0.40692138671875 +36684 0.3778076171875 +36685 0.376953125 +36686 0.371978759765625 +36687 0.313140869140625 +36688 0.184417724609375 +36689 0.011199951171875 +36690 -0.171051025390625 +36691 -0.33740234375 +36692 -0.47198486328125 +36693 -0.560394287109375 +36694 -0.58056640625 +36695 -0.54754638671875 +36696 -0.508575439453125 +36697 -0.459503173828125 +36698 -0.394378662109375 +36699 -0.35260009765625 +36700 -0.31170654296875 +36701 -0.197418212890625 +36702 -0.007965087890625 +36703 0.207489013671875 +36704 0.409210205078125 +36705 0.57208251953125 +36706 0.66595458984375 +36707 0.65875244140625 +36708 0.56744384765625 +36709 0.431396484375 +36710 0.29443359375 +36711 0.182464599609375 +36712 0.06365966796875 +36713 -0.075958251953125 +36714 -0.189422607421875 +36715 -0.271942138671875 +36716 -0.342529296875 +36717 -0.364166259765625 +36718 -0.327239990234375 +36719 -0.2769775390625 +36720 -0.253692626953125 +36721 -0.24365234375 +36722 -0.1983642578125 +36723 -0.116241455078125 +36724 -0.036834716796875 +36725 0.034881591796875 +36726 0.09124755859375 +36727 0.10888671875 +36728 0.125518798828125 +36729 0.15771484375 +36730 0.17828369140625 +36731 0.17108154296875 +36732 0.129974365234375 +36733 0.082427978515625 +36734 0.027679443359375 +36735 -0.065643310546875 +36736 -0.15936279296875 +36737 -0.21307373046875 +36738 -0.234649658203125 +36739 -0.2001953125 +36740 -0.119171142578125 +36741 -0.024749755859375 +36742 0.085784912109375 +36743 0.178131103515625 +36744 0.215576171875 +36745 0.211456298828125 +36746 0.17523193359375 +36747 0.128753662109375 +36748 0.1019287109375 +36749 0.0743408203125 +36750 0.04327392578125 +36751 0.038177490234375 +36752 0.076263427734375 +36753 0.14105224609375 +36754 0.186431884765625 +36755 0.188812255859375 +36756 0.1390380859375 +36757 0.041778564453125 +36758 -0.079437255859375 +36759 -0.219390869140625 +36760 -0.367828369140625 +36761 -0.494873046875 +36762 -0.556243896484375 +36763 -0.508697509765625 +36764 -0.3756103515625 +36765 -0.218902587890625 +36766 -0.063751220703125 +36767 0.091552734375 +36768 0.23602294921875 +36769 0.342987060546875 +36770 0.39520263671875 +36771 0.389373779296875 +36772 0.324249267578125 +36773 0.224090576171875 +36774 0.124267578125 +36775 0.037078857421875 +36776 -0.010101318359375 +36777 -0.019439697265625 +36778 -0.022796630859375 +36779 -0.001556396484375 +36780 0.056304931640625 +36781 0.106719970703125 +36782 0.096893310546875 +36783 0.042694091796875 +36784 -0.018035888671875 +36785 -0.07586669921875 +36786 -0.11944580078125 +36787 -0.15972900390625 +36788 -0.202606201171875 +36789 -0.24859619140625 +36790 -0.30517578125 +36791 -0.36212158203125 +36792 -0.39141845703125 +36793 -0.35528564453125 +36794 -0.249969482421875 +36795 -0.092864990234375 +36796 0.08905029296875 +36797 0.2352294921875 +36798 0.318817138671875 +36799 0.358642578125 +36800 0.347747802734375 +36801 0.28564453125 +36802 0.223175048828125 +36803 0.196746826171875 +36804 0.179840087890625 +36805 0.155548095703125 +36806 0.151214599609375 +36807 0.156951904296875 +36808 0.13177490234375 +36809 0.100799560546875 +36810 0.087127685546875 +36811 0.05487060546875 +36812 -0.009002685546875 +36813 -0.10400390625 +36814 -0.229400634765625 +36815 -0.35552978515625 +36816 -0.441925048828125 +36817 -0.473846435546875 +36818 -0.464813232421875 +36819 -0.419097900390625 +36820 -0.334320068359375 +36821 -0.227935791015625 +36822 -0.12347412109375 +36823 -0.02764892578125 +36824 0.077667236328125 +36825 0.2132568359375 +36826 0.38885498046875 +36827 0.582794189453125 +36828 0.734039306640625 +36829 0.800140380859375 +36830 0.7783203125 +36831 0.6651611328125 +36832 0.45965576171875 +36833 0.199188232421875 +36834 -0.050689697265625 +36835 -0.23297119140625 +36836 -0.33013916015625 +36837 -0.368408203125 +36838 -0.378936767578125 +36839 -0.376983642578125 +36840 -0.37969970703125 +36841 -0.391510009765625 +36842 -0.385345458984375 +36843 -0.3419189453125 +36844 -0.28289794921875 +36845 -0.251617431640625 +36846 -0.266143798828125 +36847 -0.273345947265625 +36848 -0.216796875 +36849 -0.128265380859375 +36850 -0.068145751953125 +36851 -0.0430908203125 +36852 -0.024444580078125 +36853 0.020721435546875 +36854 0.124481201171875 +36855 0.25787353515625 +36856 0.379119873046875 +36857 0.47991943359375 +36858 0.5281982421875 +36859 0.511138916015625 +36860 0.456207275390625 +36861 0.407470703125 +36862 0.383758544921875 +36863 0.35687255859375 +36864 0.31182861328125 +36865 0.250885009765625 +36866 0.1654052734375 +36867 0.035247802734375 +36868 -0.142059326171875 +36869 -0.33563232421875 +36870 -0.5345458984375 +36871 -0.72186279296875 +36872 -0.836669921875 +36873 -0.8326416015625 +36874 -0.7296142578125 +36875 -0.582550048828125 +36876 -0.440093994140625 +36877 -0.324310302734375 +36878 -0.20147705078125 +36879 -0.044647216796875 +36880 0.103973388671875 +36881 0.202392578125 +36882 0.264495849609375 +36883 0.338897705078125 +36884 0.443817138671875 +36885 0.545074462890625 +36886 0.6173095703125 +36887 0.6524658203125 +36888 0.66339111328125 +36889 0.6561279296875 +36890 0.606781005859375 +36891 0.501190185546875 +36892 0.352783203125 +36893 0.176544189453125 +36894 -0.034820556640625 +36895 -0.258209228515625 +36896 -0.44244384765625 +36897 -0.5753173828125 +36898 -0.65203857421875 +36899 -0.641632080078125 +36900 -0.562164306640625 +36901 -0.458038330078125 +36902 -0.350555419921875 +36903 -0.260528564453125 +36904 -0.192108154296875 +36905 -0.141937255859375 +36906 -0.1021728515625 +36907 -0.062896728515625 +36908 -0.011932373046875 +36909 0.062835693359375 +36910 0.148712158203125 +36911 0.241729736328125 +36912 0.34912109375 +36913 0.457305908203125 +36914 0.54388427734375 +36915 0.5728759765625 +36916 0.506591796875 +36917 0.351226806640625 +36918 0.146514892578125 +36919 -0.05523681640625 +36920 -0.21624755859375 +36921 -0.334930419921875 +36922 -0.402984619140625 +36923 -0.4412841796875 +36924 -0.49578857421875 +36925 -0.5601806640625 +36926 -0.600738525390625 +36927 -0.584228515625 +36928 -0.47930908203125 +36929 -0.27935791015625 +36930 -0.0089111328125 +36931 0.268798828125 +36932 0.482818603515625 +36933 0.60369873046875 +36934 0.650421142578125 +36935 0.66400146484375 +36936 0.6414794921875 +36937 0.572540283203125 +36938 0.498138427734375 +36939 0.439453125 +36940 0.375518798828125 +36941 0.274505615234375 +36942 0.1087646484375 +36943 -0.099395751953125 +36944 -0.3182373046875 +36945 -0.5489501953125 +36946 -0.7738037109375 +36947 -0.86383056640625 +36948 -0.870391845703125 +36949 -0.86895751953125 +36950 -0.861053466796875 +36951 -0.765869140625 +36952 -0.5301513671875 +36953 -0.214691162109375 +36954 0.137359619140625 +36955 0.474822998046875 +36956 0.76239013671875 +36957 0.867462158203125 +36958 0.870361328125 +36959 0.86480712890625 +36960 0.831817626953125 +36961 0.677581787109375 +36962 0.495880126953125 +36963 0.30767822265625 +36964 0.116180419921875 +36965 -0.110748291015625 +36966 -0.381805419921875 +36967 -0.6572265625 +36968 -0.857421875 +36969 -0.870391845703125 +36970 -0.870391845703125 +36971 -0.86444091796875 +36972 -0.85723876953125 +36973 -0.790008544921875 +36974 -0.62847900390625 +36975 -0.3956298828125 +36976 -0.126708984375 +36977 0.150115966796875 +36978 0.424041748046875 +36979 0.670623779296875 +36980 0.854522705078125 +36981 0.866485595703125 +36982 0.86920166015625 +36983 0.8653564453125 +36984 0.857147216796875 +36985 0.766845703125 +36986 0.628509521484375 +36987 0.462127685546875 +36988 0.297210693359375 +36989 0.14862060546875 +36990 -0.00537109375 +36991 -0.15753173828125 +36992 -0.31304931640625 +36993 -0.48876953125 +36994 -0.6416015625 +36995 -0.751373291015625 +36996 -0.84619140625 +36997 -0.861297607421875 +36998 -0.863250732421875 +36999 -0.856597900390625 +37000 -0.7498779296875 +37001 -0.624542236328125 +37002 -0.47808837890625 +37003 -0.253387451171875 +37004 0.003692626953125 +37005 0.2257080078125 +37006 0.427154541015625 +37007 0.643218994140625 +37008 0.855926513671875 +37009 0.870361328125 +37010 0.870361328125 +37011 0.862762451171875 +37012 0.79669189453125 +37013 0.595794677734375 +37014 0.362152099609375 +37015 0.1270751953125 +37016 -0.086944580078125 +37017 -0.2784423828125 +37018 -0.484832763671875 +37019 -0.729583740234375 +37020 -0.86688232421875 +37021 -0.870391845703125 +37022 -0.86859130859375 +37023 -0.86279296875 +37024 -0.817962646484375 +37025 -0.6116943359375 +37026 -0.3128662109375 +37027 0.039398193359375 +37028 0.422821044921875 +37029 0.805145263671875 +37030 0.870361328125 +37031 0.870361328125 +37032 0.860015869140625 +37033 0.727935791015625 +37034 0.48114013671875 +37035 0.2059326171875 +37036 -0.06103515625 +37037 -0.29913330078125 +37038 -0.516204833984375 +37039 -0.7252197265625 +37040 -0.85980224609375 +37041 -0.870391845703125 +37042 -0.870391845703125 +37043 -0.858062744140625 +37044 -0.673004150390625 +37045 -0.42694091796875 +37046 -0.2100830078125 +37047 -0.0362548828125 +37048 0.10943603515625 +37049 0.23516845703125 +37050 0.373687744140625 +37051 0.517791748046875 +37052 0.602783203125 +37053 0.635711669921875 +37054 0.655181884765625 +37055 0.65948486328125 +37056 0.651275634765625 +37057 0.61846923828125 +37058 0.53753662109375 +37059 0.404144287109375 +37060 0.22186279296875 +37061 0.003997802734375 +37062 -0.22100830078125 +37063 -0.42449951171875 +37064 -0.579833984375 +37065 -0.641876220703125 +37066 -0.6177978515625 +37067 -0.575531005859375 +37068 -0.526336669921875 +37069 -0.42645263671875 +37070 -0.2581787109375 +37071 -0.068695068359375 +37072 0.09222412109375 +37073 0.232147216796875 +37074 0.3509521484375 +37075 0.410064697265625 +37076 0.372955322265625 +37077 0.2554931640625 +37078 0.10711669921875 +37079 -0.052886962890625 +37080 -0.186279296875 +37081 -0.23291015625 +37082 -0.209442138671875 +37083 -0.174163818359375 +37084 -0.126739501953125 +37085 -0.048126220703125 +37086 0.0426025390625 +37087 0.10748291015625 +37088 0.1409912109375 +37089 0.19708251953125 +37090 0.273651123046875 +37091 0.31768798828125 +37092 0.341094970703125 +37093 0.368011474609375 +37094 0.37249755859375 +37095 0.30072021484375 +37096 0.1517333984375 +37097 -0.01470947265625 +37098 -0.1883544921875 +37099 -0.372711181640625 +37100 -0.51397705078125 +37101 -0.57177734375 +37102 -0.53948974609375 +37103 -0.43511962890625 +37104 -0.2962646484375 +37105 -0.161102294921875 +37106 -0.0435791015625 +37107 0.060394287109375 +37108 0.13665771484375 +37109 0.170135498046875 +37110 0.16552734375 +37111 0.15728759765625 +37112 0.150787353515625 +37113 0.12200927734375 +37114 0.080108642578125 +37115 0.05126953125 +37116 0.062896728515625 +37117 0.09271240234375 +37118 0.092987060546875 +37119 0.07855224609375 +37120 0.06427001953125 +37121 0.0347900390625 +37122 -0.01171875 +37123 -0.056060791015625 +37124 -0.055511474609375 +37125 -0.010467529296875 +37126 0.02508544921875 +37127 0.025665283203125 +37128 0.017333984375 +37129 0.00189208984375 +37130 -0.03173828125 +37131 -0.071502685546875 +37132 -0.13543701171875 +37133 -0.219970703125 +37134 -0.300506591796875 +37135 -0.376312255859375 +37136 -0.416107177734375 +37137 -0.371124267578125 +37138 -0.242279052734375 +37139 -0.069732666015625 +37140 0.125640869140625 +37141 0.31268310546875 +37142 0.45501708984375 +37143 0.554779052734375 +37144 0.61065673828125 +37145 0.610931396484375 +37146 0.531463623046875 +37147 0.3883056640625 +37148 0.23468017578125 +37149 0.095245361328125 +37150 -0.00396728515625 +37151 -0.04852294921875 +37152 -0.055145263671875 +37153 -0.0758056640625 +37154 -0.138702392578125 +37155 -0.209197998046875 +37156 -0.289031982421875 +37157 -0.37884521484375 +37158 -0.456329345703125 +37159 -0.51641845703125 +37160 -0.519287109375 +37161 -0.458251953125 +37162 -0.384796142578125 +37163 -0.323699951171875 +37164 -0.269287109375 +37165 -0.1951904296875 +37166 -0.100006103515625 +37167 -0.01055908203125 +37168 0.1033935546875 +37169 0.24908447265625 +37170 0.373199462890625 +37171 0.45806884765625 +37172 0.511474609375 +37173 0.565399169921875 +37174 0.61138916015625 +37175 0.5897216796875 +37176 0.4906005859375 +37177 0.33148193359375 +37178 0.147796630859375 +37179 -0.01873779296875 +37180 -0.140289306640625 +37181 -0.191986083984375 +37182 -0.184295654296875 +37183 -0.161834716796875 +37184 -0.166595458984375 +37185 -0.19390869140625 +37186 -0.22442626953125 +37187 -0.279754638671875 +37188 -0.3389892578125 +37189 -0.3543701171875 +37190 -0.348175048828125 +37191 -0.32598876953125 +37192 -0.2581787109375 +37193 -0.139801025390625 +37194 0.014617919921875 +37195 0.144378662109375 +37196 0.221038818359375 +37197 0.27069091796875 +37198 0.294036865234375 +37199 0.311767578125 +37200 0.339141845703125 +37201 0.360260009765625 +37202 0.360504150390625 +37203 0.308380126953125 +37204 0.18170166015625 +37205 0.0047607421875 +37206 -0.17559814453125 +37207 -0.3143310546875 +37208 -0.36785888671875 +37209 -0.36248779296875 +37210 -0.343536376953125 +37211 -0.3018798828125 +37212 -0.231414794921875 +37213 -0.117645263671875 +37214 0.007049560546875 +37215 0.087982177734375 +37216 0.13946533203125 +37217 0.17425537109375 +37218 0.188201904296875 +37219 0.171234130859375 +37220 0.118438720703125 +37221 0.05706787109375 +37222 -0.010711669921875 +37223 -0.0914306640625 +37224 -0.162322998046875 +37225 -0.194549560546875 +37226 -0.1492919921875 +37227 -0.02166748046875 +37228 0.124053955078125 +37229 0.211151123046875 +37230 0.240447998046875 +37231 0.242218017578125 +37232 0.2257080078125 +37233 0.194366455078125 +37234 0.115509033203125 +37235 0.0128173828125 +37236 -0.053802490234375 +37237 -0.110626220703125 +37238 -0.199493408203125 +37239 -0.29437255859375 +37240 -0.33221435546875 +37241 -0.27972412109375 +37242 -0.185333251953125 +37243 -0.128204345703125 +37244 -0.115692138671875 +37245 -0.116455078125 +37246 -0.105926513671875 +37247 -0.053955078125 +37248 0.048797607421875 +37249 0.157318115234375 +37250 0.212005615234375 +37251 0.218475341796875 +37252 0.23724365234375 +37253 0.30535888671875 +37254 0.38128662109375 +37255 0.404449462890625 +37256 0.3944091796875 +37257 0.3885498046875 +37258 0.362640380859375 +37259 0.27362060546875 +37260 0.11712646484375 +37261 -0.054901123046875 +37262 -0.19085693359375 +37263 -0.28570556640625 +37264 -0.339263916015625 +37265 -0.3775634765625 +37266 -0.445709228515625 +37267 -0.535064697265625 +37268 -0.629058837890625 +37269 -0.697601318359375 +37270 -0.70391845703125 +37271 -0.6424560546875 +37272 -0.491241455078125 +37273 -0.265716552734375 +37274 -0.023712158203125 +37275 0.201751708984375 +37276 0.375823974609375 +37277 0.485076904296875 +37278 0.56884765625 +37279 0.634765625 +37280 0.63763427734375 +37281 0.5660400390625 +37282 0.4720458984375 +37283 0.40692138671875 +37284 0.3778076171875 +37285 0.376953125 +37286 0.371978759765625 +37287 0.313140869140625 +37288 0.184417724609375 +37289 0.011199951171875 +37290 -0.171051025390625 +37291 -0.33740234375 +37292 -0.47198486328125 +37293 -0.560394287109375 +37294 -0.58056640625 +37295 -0.54754638671875 +37296 -0.508575439453125 +37297 -0.459503173828125 +37298 -0.394378662109375 +37299 -0.35260009765625 +37300 -0.31170654296875 +37301 -0.197418212890625 +37302 -0.007965087890625 +37303 0.207489013671875 +37304 0.409210205078125 +37305 0.57208251953125 +37306 0.66595458984375 +37307 0.65875244140625 +37308 0.56744384765625 +37309 0.431396484375 +37310 0.29443359375 +37311 0.182464599609375 +37312 0.06365966796875 +37313 -0.075958251953125 +37314 -0.189422607421875 +37315 -0.271942138671875 +37316 -0.342529296875 +37317 -0.364166259765625 +37318 -0.327239990234375 +37319 -0.2769775390625 +37320 -0.253692626953125 +37321 -0.24365234375 +37322 -0.1983642578125 +37323 -0.116241455078125 +37324 -0.036834716796875 +37325 0.034881591796875 +37326 0.09124755859375 +37327 0.10888671875 +37328 0.125518798828125 +37329 0.15771484375 +37330 0.17828369140625 +37331 0.17108154296875 +37332 0.129974365234375 +37333 0.082427978515625 +37334 0.027679443359375 +37335 -0.065643310546875 +37336 -0.15936279296875 +37337 -0.21307373046875 +37338 -0.234649658203125 +37339 -0.2001953125 +37340 -0.119171142578125 +37341 -0.024749755859375 +37342 0.085784912109375 +37343 0.178131103515625 +37344 0.215576171875 +37345 0.211456298828125 +37346 0.17523193359375 +37347 0.128753662109375 +37348 0.1019287109375 +37349 0.0743408203125 +37350 0.04327392578125 +37351 0.038177490234375 +37352 0.076263427734375 +37353 0.14105224609375 +37354 0.186431884765625 +37355 0.188812255859375 +37356 0.1390380859375 +37357 0.041778564453125 +37358 -0.079437255859375 +37359 -0.219390869140625 +37360 -0.367828369140625 +37361 -0.494873046875 +37362 -0.556243896484375 +37363 -0.508697509765625 +37364 -0.3756103515625 +37365 -0.218902587890625 +37366 -0.063751220703125 +37367 0.091552734375 +37368 0.23602294921875 +37369 0.342987060546875 +37370 0.39520263671875 +37371 0.389373779296875 +37372 0.324249267578125 +37373 0.224090576171875 +37374 0.124267578125 +37375 0.037078857421875 +37376 -0.010101318359375 +37377 -0.019439697265625 +37378 -0.022796630859375 +37379 -0.001556396484375 +37380 0.056304931640625 +37381 0.106719970703125 +37382 0.096893310546875 +37383 0.042694091796875 +37384 -0.018035888671875 +37385 -0.07586669921875 +37386 -0.11944580078125 +37387 -0.15972900390625 +37388 -0.202606201171875 +37389 -0.24859619140625 +37390 -0.30517578125 +37391 -0.36212158203125 +37392 -0.39141845703125 +37393 -0.35528564453125 +37394 -0.249969482421875 +37395 -0.092864990234375 +37396 0.08905029296875 +37397 0.2352294921875 +37398 0.318817138671875 +37399 0.358642578125 +37400 0.347747802734375 +37401 0.28564453125 +37402 0.223175048828125 +37403 0.196746826171875 +37404 0.179840087890625 +37405 0.155548095703125 +37406 0.151214599609375 +37407 0.156951904296875 +37408 0.13177490234375 +37409 0.100799560546875 +37410 0.087127685546875 +37411 0.05487060546875 +37412 -0.009002685546875 +37413 -0.10400390625 +37414 -0.229400634765625 +37415 -0.35552978515625 +37416 -0.441925048828125 +37417 -0.473846435546875 +37418 -0.464813232421875 +37419 -0.419097900390625 +37420 -0.334320068359375 +37421 -0.227935791015625 +37422 -0.12347412109375 +37423 -0.02764892578125 +37424 0.077667236328125 +37425 0.2132568359375 +37426 0.38885498046875 +37427 0.582794189453125 +37428 0.734039306640625 +37429 0.800140380859375 +37430 0.7783203125 +37431 0.6651611328125 +37432 0.45965576171875 +37433 0.199188232421875 +37434 -0.050689697265625 +37435 -0.23297119140625 +37436 -0.33013916015625 +37437 -0.368408203125 +37438 -0.378936767578125 +37439 -0.376983642578125 +37440 -0.37969970703125 +37441 -0.391510009765625 +37442 -0.385345458984375 +37443 -0.3419189453125 +37444 -0.28289794921875 +37445 -0.251617431640625 +37446 -0.266143798828125 +37447 -0.273345947265625 +37448 -0.216796875 +37449 -0.128265380859375 +37450 -0.068145751953125 +37451 -0.0430908203125 +37452 -0.024444580078125 +37453 0.020721435546875 +37454 0.124481201171875 +37455 0.25787353515625 +37456 0.379119873046875 +37457 0.47991943359375 +37458 0.5281982421875 +37459 0.511138916015625 +37460 0.456207275390625 +37461 0.407470703125 +37462 0.383758544921875 +37463 0.35687255859375 +37464 0.31182861328125 +37465 0.250885009765625 +37466 0.1654052734375 +37467 0.035247802734375 +37468 -0.142059326171875 +37469 -0.33563232421875 +37470 -0.5345458984375 +37471 -0.72186279296875 +37472 -0.836669921875 +37473 -0.8326416015625 +37474 -0.7296142578125 +37475 -0.582550048828125 +37476 -0.440093994140625 +37477 -0.324310302734375 +37478 -0.20147705078125 +37479 -0.044647216796875 +37480 0.103973388671875 +37481 0.202392578125 +37482 0.264495849609375 +37483 0.338897705078125 +37484 0.443817138671875 +37485 0.545074462890625 +37486 0.6173095703125 +37487 0.6524658203125 +37488 0.66339111328125 +37489 0.6561279296875 +37490 0.606781005859375 +37491 0.501190185546875 +37492 0.352783203125 +37493 0.176544189453125 +37494 -0.034820556640625 +37495 -0.258209228515625 +37496 -0.44244384765625 +37497 -0.5753173828125 +37498 -0.65203857421875 +37499 -0.641632080078125 +37500 -0.562164306640625 +37501 -0.458038330078125 +37502 -0.350555419921875 +37503 -0.260528564453125 +37504 -0.192108154296875 +37505 -0.141937255859375 +37506 -0.1021728515625 +37507 -0.062896728515625 +37508 -0.011932373046875 +37509 0.062835693359375 +37510 0.148712158203125 +37511 0.241729736328125 +37512 0.34912109375 +37513 0.457305908203125 +37514 0.54388427734375 +37515 0.5728759765625 +37516 0.506591796875 +37517 0.351226806640625 +37518 0.146514892578125 +37519 -0.05523681640625 +37520 -0.21624755859375 +37521 -0.334930419921875 +37522 -0.402984619140625 +37523 -0.4412841796875 +37524 -0.49578857421875 +37525 -0.5601806640625 +37526 -0.600738525390625 +37527 -0.584228515625 +37528 -0.47930908203125 +37529 -0.27935791015625 +37530 -0.0089111328125 +37531 0.268798828125 +37532 0.482818603515625 +37533 0.60369873046875 +37534 0.650421142578125 +37535 0.66400146484375 +37536 0.6414794921875 +37537 0.572540283203125 +37538 0.498138427734375 +37539 0.439453125 +37540 0.375518798828125 +37541 0.274505615234375 +37542 0.1087646484375 +37543 -0.099395751953125 +37544 -0.3182373046875 +37545 -0.5489501953125 +37546 -0.7738037109375 +37547 -0.86383056640625 +37548 -0.870391845703125 +37549 -0.86895751953125 +37550 -0.861053466796875 +37551 -0.765869140625 +37552 -0.5301513671875 +37553 -0.214691162109375 +37554 0.137359619140625 +37555 0.474822998046875 +37556 0.76239013671875 +37557 0.867462158203125 +37558 0.870361328125 +37559 0.86480712890625 +37560 0.831817626953125 +37561 0.677581787109375 +37562 0.495880126953125 +37563 0.30767822265625 +37564 0.116180419921875 +37565 -0.110748291015625 +37566 -0.381805419921875 +37567 -0.6572265625 +37568 -0.857421875 +37569 -0.870391845703125 +37570 -0.870391845703125 +37571 -0.86444091796875 +37572 -0.85723876953125 +37573 -0.790008544921875 +37574 -0.62847900390625 +37575 -0.3956298828125 +37576 -0.126708984375 +37577 0.150115966796875 +37578 0.424041748046875 +37579 0.670623779296875 +37580 0.854522705078125 +37581 0.866485595703125 +37582 0.86920166015625 +37583 0.8653564453125 +37584 0.857147216796875 +37585 0.766845703125 +37586 0.628509521484375 +37587 0.462127685546875 +37588 0.297210693359375 +37589 0.14862060546875 +37590 -0.00537109375 +37591 -0.15753173828125 +37592 -0.31304931640625 +37593 -0.48876953125 +37594 -0.6416015625 +37595 -0.751373291015625 +37596 -0.84619140625 +37597 -0.861297607421875 +37598 -0.863250732421875 +37599 -0.856597900390625 +37600 -0.7498779296875 +37601 -0.624542236328125 +37602 -0.47808837890625 +37603 -0.253387451171875 +37604 0.003692626953125 +37605 0.2257080078125 +37606 0.427154541015625 +37607 0.643218994140625 +37608 0.855926513671875 +37609 0.870361328125 +37610 0.870361328125 +37611 0.862762451171875 +37612 0.79669189453125 +37613 0.595794677734375 +37614 0.362152099609375 +37615 0.1270751953125 +37616 -0.086944580078125 +37617 -0.2784423828125 +37618 -0.484832763671875 +37619 -0.729583740234375 +37620 -0.86688232421875 +37621 -0.870391845703125 +37622 -0.86859130859375 +37623 -0.86279296875 +37624 -0.817962646484375 +37625 -0.6116943359375 +37626 -0.3128662109375 +37627 0.039398193359375 +37628 0.422821044921875 +37629 0.805145263671875 +37630 0.870361328125 +37631 0.870361328125 +37632 0.860015869140625 +37633 0.727935791015625 +37634 0.48114013671875 +37635 0.2059326171875 +37636 -0.06103515625 +37637 -0.29913330078125 +37638 -0.516204833984375 +37639 -0.7252197265625 +37640 -0.85980224609375 +37641 -0.870391845703125 +37642 -0.870391845703125 +37643 -0.858062744140625 +37644 -0.673004150390625 +37645 -0.42694091796875 +37646 -0.2100830078125 +37647 -0.0362548828125 +37648 0.10943603515625 +37649 0.23516845703125 +37650 0.373687744140625 +37651 0.517791748046875 +37652 0.602783203125 +37653 0.635711669921875 +37654 0.655181884765625 +37655 0.65948486328125 +37656 0.651275634765625 +37657 0.61846923828125 +37658 0.53753662109375 +37659 0.404144287109375 +37660 0.22186279296875 +37661 0.003997802734375 +37662 -0.22100830078125 +37663 -0.42449951171875 +37664 -0.579833984375 +37665 -0.641876220703125 +37666 -0.6177978515625 +37667 -0.575531005859375 +37668 -0.526336669921875 +37669 -0.42645263671875 +37670 -0.2581787109375 +37671 -0.068695068359375 +37672 0.09222412109375 +37673 0.232147216796875 +37674 0.3509521484375 +37675 0.410064697265625 +37676 0.372955322265625 +37677 0.2554931640625 +37678 0.10711669921875 +37679 -0.052886962890625 +37680 -0.186279296875 +37681 -0.23291015625 +37682 -0.209442138671875 +37683 -0.174163818359375 +37684 -0.126739501953125 +37685 -0.048126220703125 +37686 0.0426025390625 +37687 0.10748291015625 +37688 0.1409912109375 +37689 0.19708251953125 +37690 0.273651123046875 +37691 0.31768798828125 +37692 0.341094970703125 +37693 0.368011474609375 +37694 0.37249755859375 +37695 0.30072021484375 +37696 0.1517333984375 +37697 -0.01470947265625 +37698 -0.1883544921875 +37699 -0.372711181640625 +37700 -0.51397705078125 +37701 -0.57177734375 +37702 -0.53948974609375 +37703 -0.43511962890625 +37704 -0.2962646484375 +37705 -0.161102294921875 +37706 -0.0435791015625 +37707 0.060394287109375 +37708 0.13665771484375 +37709 0.170135498046875 +37710 0.16552734375 +37711 0.15728759765625 +37712 0.150787353515625 +37713 0.12200927734375 +37714 0.080108642578125 +37715 0.05126953125 +37716 0.062896728515625 +37717 0.09271240234375 +37718 0.092987060546875 +37719 0.07855224609375 +37720 0.06427001953125 +37721 0.0347900390625 +37722 -0.01171875 +37723 -0.056060791015625 +37724 -0.055511474609375 +37725 -0.010467529296875 +37726 0.02508544921875 +37727 0.025665283203125 +37728 0.017333984375 +37729 0.00189208984375 +37730 -0.03173828125 +37731 -0.071502685546875 +37732 -0.13543701171875 +37733 -0.219970703125 +37734 -0.300506591796875 +37735 -0.376312255859375 +37736 -0.416107177734375 +37737 -0.371124267578125 +37738 -0.242279052734375 +37739 -0.069732666015625 +37740 0.125640869140625 +37741 0.31268310546875 +37742 0.45501708984375 +37743 0.554779052734375 +37744 0.61065673828125 +37745 0.610931396484375 +37746 0.531463623046875 +37747 0.3883056640625 +37748 0.23468017578125 +37749 0.095245361328125 +37750 -0.00396728515625 +37751 -0.04852294921875 +37752 -0.055145263671875 +37753 -0.0758056640625 +37754 -0.138702392578125 +37755 -0.209197998046875 +37756 -0.289031982421875 +37757 -0.37884521484375 +37758 -0.456329345703125 +37759 -0.51641845703125 +37760 -0.519287109375 +37761 -0.458251953125 +37762 -0.384796142578125 +37763 -0.323699951171875 +37764 -0.269287109375 +37765 -0.1951904296875 +37766 -0.100006103515625 +37767 -0.01055908203125 +37768 0.1033935546875 +37769 0.24908447265625 +37770 0.373199462890625 +37771 0.45806884765625 +37772 0.511474609375 +37773 0.565399169921875 +37774 0.61138916015625 +37775 0.5897216796875 +37776 0.4906005859375 +37777 0.33148193359375 +37778 0.147796630859375 +37779 -0.01873779296875 +37780 -0.140289306640625 +37781 -0.191986083984375 +37782 -0.184295654296875 +37783 -0.161834716796875 +37784 -0.166595458984375 +37785 -0.19390869140625 +37786 -0.22442626953125 +37787 -0.279754638671875 +37788 -0.3389892578125 +37789 -0.3543701171875 +37790 -0.348175048828125 +37791 -0.32598876953125 +37792 -0.2581787109375 +37793 -0.139801025390625 +37794 0.014617919921875 +37795 0.144378662109375 +37796 0.221038818359375 +37797 0.27069091796875 +37798 0.294036865234375 +37799 0.311767578125 +37800 0.339141845703125 +37801 0.360260009765625 +37802 0.360504150390625 +37803 0.308380126953125 +37804 0.18170166015625 +37805 0.0047607421875 +37806 -0.17559814453125 +37807 -0.3143310546875 +37808 -0.36785888671875 +37809 -0.36248779296875 +37810 -0.343536376953125 +37811 -0.3018798828125 +37812 -0.231414794921875 +37813 -0.117645263671875 +37814 0.007049560546875 +37815 0.087982177734375 +37816 0.13946533203125 +37817 0.17425537109375 +37818 0.188201904296875 +37819 0.171234130859375 +37820 0.118438720703125 +37821 0.05706787109375 +37822 -0.010711669921875 +37823 -0.0914306640625 +37824 -0.162322998046875 +37825 -0.194549560546875 +37826 -0.1492919921875 +37827 -0.02166748046875 +37828 0.124053955078125 +37829 0.211151123046875 +37830 0.240447998046875 +37831 0.242218017578125 +37832 0.2257080078125 +37833 0.194366455078125 +37834 0.115509033203125 +37835 0.0128173828125 +37836 -0.053802490234375 +37837 -0.110626220703125 +37838 -0.199493408203125 +37839 -0.29437255859375 +37840 -0.33221435546875 +37841 -0.27972412109375 +37842 -0.185333251953125 +37843 -0.128204345703125 +37844 -0.115692138671875 +37845 -0.116455078125 +37846 -0.105926513671875 +37847 -0.053955078125 +37848 0.048797607421875 +37849 0.157318115234375 +37850 0.212005615234375 +37851 0.218475341796875 +37852 0.23724365234375 +37853 0.30535888671875 +37854 0.38128662109375 +37855 0.404449462890625 +37856 0.3944091796875 +37857 0.3885498046875 +37858 0.362640380859375 +37859 0.27362060546875 +37860 0.11712646484375 +37861 -0.054901123046875 +37862 -0.19085693359375 +37863 -0.28570556640625 +37864 -0.339263916015625 +37865 -0.3775634765625 +37866 -0.445709228515625 +37867 -0.535064697265625 +37868 -0.629058837890625 +37869 -0.697601318359375 +37870 -0.70391845703125 +37871 -0.6424560546875 +37872 -0.491241455078125 +37873 -0.265716552734375 +37874 -0.023712158203125 +37875 0.201751708984375 +37876 0.375823974609375 +37877 0.485076904296875 +37878 0.56884765625 +37879 0.634765625 +37880 0.63763427734375 +37881 0.5660400390625 +37882 0.4720458984375 +37883 0.40692138671875 +37884 0.3778076171875 +37885 0.376953125 +37886 0.371978759765625 +37887 0.313140869140625 +37888 0.184417724609375 +37889 0.011199951171875 +37890 -0.171051025390625 +37891 -0.33740234375 +37892 -0.47198486328125 +37893 -0.560394287109375 +37894 -0.58056640625 +37895 -0.54754638671875 +37896 -0.508575439453125 +37897 -0.459503173828125 +37898 -0.394378662109375 +37899 -0.35260009765625 +37900 -0.31170654296875 +37901 -0.197418212890625 +37902 -0.007965087890625 +37903 0.207489013671875 +37904 0.409210205078125 +37905 0.57208251953125 +37906 0.66595458984375 +37907 0.65875244140625 +37908 0.56744384765625 +37909 0.431396484375 +37910 0.29443359375 +37911 0.182464599609375 +37912 0.06365966796875 +37913 -0.075958251953125 +37914 -0.189422607421875 +37915 -0.271942138671875 +37916 -0.342529296875 +37917 -0.364166259765625 +37918 -0.327239990234375 +37919 -0.2769775390625 +37920 -0.253692626953125 +37921 -0.24365234375 +37922 -0.1983642578125 +37923 -0.116241455078125 +37924 -0.036834716796875 +37925 0.034881591796875 +37926 0.09124755859375 +37927 0.10888671875 +37928 0.125518798828125 +37929 0.15771484375 +37930 0.17828369140625 +37931 0.17108154296875 +37932 0.129974365234375 +37933 0.082427978515625 +37934 0.027679443359375 +37935 -0.065643310546875 +37936 -0.15936279296875 +37937 -0.21307373046875 +37938 -0.234649658203125 +37939 -0.2001953125 +37940 -0.119171142578125 +37941 -0.024749755859375 +37942 0.085784912109375 +37943 0.178131103515625 +37944 0.215576171875 +37945 0.211456298828125 +37946 0.17523193359375 +37947 0.128753662109375 +37948 0.1019287109375 +37949 0.0743408203125 +37950 0.04327392578125 +37951 0.038177490234375 +37952 0.076263427734375 +37953 0.14105224609375 +37954 0.186431884765625 +37955 0.188812255859375 +37956 0.1390380859375 +37957 0.041778564453125 +37958 -0.079437255859375 +37959 -0.219390869140625 +37960 -0.367828369140625 +37961 -0.494873046875 +37962 -0.556243896484375 +37963 -0.508697509765625 +37964 -0.3756103515625 +37965 -0.218902587890625 +37966 -0.063751220703125 +37967 0.091552734375 +37968 0.23602294921875 +37969 0.342987060546875 +37970 0.39520263671875 +37971 0.389373779296875 +37972 0.324249267578125 +37973 0.224090576171875 +37974 0.124267578125 +37975 0.037078857421875 +37976 -0.010101318359375 +37977 -0.019439697265625 +37978 -0.022796630859375 +37979 -0.001556396484375 +37980 0.056304931640625 +37981 0.106719970703125 +37982 0.096893310546875 +37983 0.042694091796875 +37984 -0.018035888671875 +37985 -0.07586669921875 +37986 -0.11944580078125 +37987 -0.15972900390625 +37988 -0.202606201171875 +37989 -0.24859619140625 +37990 -0.30517578125 +37991 -0.36212158203125 +37992 -0.39141845703125 +37993 -0.35528564453125 +37994 -0.249969482421875 +37995 -0.092864990234375 +37996 0.08905029296875 +37997 0.2352294921875 +37998 0.318817138671875 +37999 0.358642578125 +38000 0.347747802734375 +38001 0.28564453125 +38002 0.223175048828125 +38003 0.196746826171875 +38004 0.179840087890625 +38005 0.155548095703125 +38006 0.151214599609375 +38007 0.156951904296875 +38008 0.13177490234375 +38009 0.100799560546875 +38010 0.087127685546875 +38011 0.05487060546875 +38012 -0.009002685546875 +38013 -0.10400390625 +38014 -0.229400634765625 +38015 -0.35552978515625 +38016 -0.441925048828125 +38017 -0.473846435546875 +38018 -0.464813232421875 +38019 -0.419097900390625 +38020 -0.334320068359375 +38021 -0.227935791015625 +38022 -0.12347412109375 +38023 -0.02764892578125 +38024 0.077667236328125 +38025 0.2132568359375 +38026 0.38885498046875 +38027 0.582794189453125 +38028 0.734039306640625 +38029 0.800140380859375 +38030 0.7783203125 +38031 0.6651611328125 +38032 0.45965576171875 +38033 0.199188232421875 +38034 -0.050689697265625 +38035 -0.23297119140625 +38036 -0.33013916015625 +38037 -0.368408203125 +38038 -0.378936767578125 +38039 -0.376983642578125 +38040 -0.37969970703125 +38041 -0.391510009765625 +38042 -0.385345458984375 +38043 -0.3419189453125 +38044 -0.28289794921875 +38045 -0.251617431640625 +38046 -0.266143798828125 +38047 -0.273345947265625 +38048 -0.216796875 +38049 -0.128265380859375 +38050 -0.068145751953125 +38051 -0.0430908203125 +38052 -0.024444580078125 +38053 0.020721435546875 +38054 0.124481201171875 +38055 0.25787353515625 +38056 0.379119873046875 +38057 0.47991943359375 +38058 0.5281982421875 +38059 0.511138916015625 +38060 0.456207275390625 +38061 0.407470703125 +38062 0.383758544921875 +38063 0.35687255859375 +38064 0.31182861328125 +38065 0.250885009765625 +38066 0.1654052734375 +38067 0.035247802734375 +38068 -0.142059326171875 +38069 -0.33563232421875 +38070 -0.5345458984375 +38071 -0.72186279296875 +38072 -0.836669921875 +38073 -0.8326416015625 +38074 -0.7296142578125 +38075 -0.582550048828125 +38076 -0.440093994140625 +38077 -0.324310302734375 +38078 -0.20147705078125 +38079 -0.044647216796875 +38080 0.103973388671875 +38081 0.202392578125 +38082 0.264495849609375 +38083 0.338897705078125 +38084 0.443817138671875 +38085 0.545074462890625 +38086 0.6173095703125 +38087 0.6524658203125 +38088 0.66339111328125 +38089 0.6561279296875 +38090 0.606781005859375 +38091 0.501190185546875 +38092 0.352783203125 +38093 0.176544189453125 +38094 -0.034820556640625 +38095 -0.258209228515625 +38096 -0.44244384765625 +38097 -0.5753173828125 +38098 -0.65203857421875 +38099 -0.641632080078125 +38100 -0.562164306640625 +38101 -0.458038330078125 +38102 -0.350555419921875 +38103 -0.260528564453125 +38104 -0.192108154296875 +38105 -0.141937255859375 +38106 -0.1021728515625 +38107 -0.062896728515625 +38108 -0.011932373046875 +38109 0.062835693359375 +38110 0.148712158203125 +38111 0.241729736328125 +38112 0.34912109375 +38113 0.457305908203125 +38114 0.54388427734375 +38115 0.5728759765625 +38116 0.506591796875 +38117 0.351226806640625 +38118 0.146514892578125 +38119 -0.05523681640625 +38120 -0.21624755859375 +38121 -0.334930419921875 +38122 -0.402984619140625 +38123 -0.4412841796875 +38124 -0.49578857421875 +38125 -0.5601806640625 +38126 -0.600738525390625 +38127 -0.584228515625 +38128 -0.47930908203125 +38129 -0.27935791015625 +38130 -0.0089111328125 +38131 0.268798828125 +38132 0.482818603515625 +38133 0.60369873046875 +38134 0.650421142578125 +38135 0.66400146484375 +38136 0.6414794921875 +38137 0.572540283203125 +38138 0.498138427734375 +38139 0.439453125 +38140 0.375518798828125 +38141 0.274505615234375 +38142 0.1087646484375 +38143 -0.099395751953125 +38144 -0.3182373046875 +38145 -0.5489501953125 +38146 -0.7738037109375 +38147 -0.86383056640625 +38148 -0.870391845703125 +38149 -0.86895751953125 +38150 -0.861053466796875 +38151 -0.765869140625 +38152 -0.5301513671875 +38153 -0.214691162109375 +38154 0.137359619140625 +38155 0.474822998046875 +38156 0.76239013671875 +38157 0.867462158203125 +38158 0.870361328125 +38159 0.86480712890625 +38160 0.831817626953125 +38161 0.677581787109375 +38162 0.495880126953125 +38163 0.30767822265625 +38164 0.116180419921875 +38165 -0.110748291015625 +38166 -0.381805419921875 +38167 -0.6572265625 +38168 -0.857421875 +38169 -0.870391845703125 +38170 -0.870391845703125 +38171 -0.86444091796875 +38172 -0.85723876953125 +38173 -0.790008544921875 +38174 -0.62847900390625 +38175 -0.3956298828125 +38176 -0.126708984375 +38177 0.150115966796875 +38178 0.424041748046875 +38179 0.670623779296875 +38180 0.854522705078125 +38181 0.866485595703125 +38182 0.86920166015625 +38183 0.8653564453125 +38184 0.857147216796875 +38185 0.766845703125 +38186 0.628509521484375 +38187 0.462127685546875 +38188 0.297210693359375 +38189 0.14862060546875 +38190 -0.00537109375 +38191 -0.15753173828125 +38192 -0.31304931640625 +38193 -0.48876953125 +38194 -0.6416015625 +38195 -0.751373291015625 +38196 -0.84619140625 +38197 -0.861297607421875 +38198 -0.863250732421875 +38199 -0.856597900390625 +38200 -0.7498779296875 +38201 -0.624542236328125 +38202 -0.47808837890625 +38203 -0.253387451171875 +38204 0.003692626953125 +38205 0.2257080078125 +38206 0.427154541015625 +38207 0.643218994140625 +38208 0.855926513671875 +38209 0.870361328125 +38210 0.870361328125 +38211 0.862762451171875 +38212 0.79669189453125 +38213 0.595794677734375 +38214 0.362152099609375 +38215 0.1270751953125 +38216 -0.086944580078125 +38217 -0.2784423828125 +38218 -0.484832763671875 +38219 -0.729583740234375 +38220 -0.86688232421875 +38221 -0.870391845703125 +38222 -0.86859130859375 +38223 -0.86279296875 +38224 -0.817962646484375 +38225 -0.6116943359375 +38226 -0.3128662109375 +38227 0.039398193359375 +38228 0.422821044921875 +38229 0.805145263671875 +38230 0.870361328125 +38231 0.870361328125 +38232 0.860015869140625 +38233 0.727935791015625 +38234 0.48114013671875 +38235 0.2059326171875 +38236 -0.06103515625 +38237 -0.29913330078125 +38238 -0.516204833984375 +38239 -0.7252197265625 +38240 -0.85980224609375 +38241 -0.870391845703125 +38242 -0.870391845703125 +38243 -0.858062744140625 +38244 -0.673004150390625 +38245 -0.42694091796875 +38246 -0.2100830078125 +38247 -0.0362548828125 +38248 0.10943603515625 +38249 0.23516845703125 +38250 0.373687744140625 +38251 0.517791748046875 +38252 0.602783203125 +38253 0.635711669921875 +38254 0.655181884765625 +38255 0.65948486328125 +38256 0.651275634765625 +38257 0.61846923828125 +38258 0.53753662109375 +38259 0.404144287109375 +38260 0.22186279296875 +38261 0.003997802734375 +38262 -0.22100830078125 +38263 -0.42449951171875 +38264 -0.579833984375 +38265 -0.641876220703125 +38266 -0.6177978515625 +38267 -0.575531005859375 +38268 -0.526336669921875 +38269 -0.42645263671875 +38270 -0.2581787109375 +38271 -0.068695068359375 +38272 0.09222412109375 +38273 0.232147216796875 +38274 0.3509521484375 +38275 0.410064697265625 +38276 0.372955322265625 +38277 0.2554931640625 +38278 0.10711669921875 +38279 -0.052886962890625 +38280 -0.186279296875 +38281 -0.23291015625 +38282 -0.209442138671875 +38283 -0.174163818359375 +38284 -0.126739501953125 +38285 -0.048126220703125 +38286 0.0426025390625 +38287 0.10748291015625 +38288 0.1409912109375 +38289 0.19708251953125 +38290 0.273651123046875 +38291 0.31768798828125 +38292 0.341094970703125 +38293 0.368011474609375 +38294 0.37249755859375 +38295 0.30072021484375 +38296 0.1517333984375 +38297 -0.01470947265625 +38298 -0.1883544921875 +38299 -0.372711181640625 +38300 -0.51397705078125 +38301 -0.57177734375 +38302 -0.53948974609375 +38303 -0.43511962890625 +38304 -0.2962646484375 +38305 -0.161102294921875 +38306 -0.0435791015625 +38307 0.060394287109375 +38308 0.13665771484375 +38309 0.170135498046875 +38310 0.16552734375 +38311 0.15728759765625 +38312 0.150787353515625 +38313 0.12200927734375 +38314 0.080108642578125 +38315 0.05126953125 +38316 0.062896728515625 +38317 0.09271240234375 +38318 0.092987060546875 +38319 0.07855224609375 +38320 0.06427001953125 +38321 0.0347900390625 +38322 -0.01171875 +38323 -0.056060791015625 +38324 -0.055511474609375 +38325 -0.010467529296875 +38326 0.02508544921875 +38327 0.025665283203125 +38328 0.017333984375 +38329 0.00189208984375 +38330 -0.03173828125 +38331 -0.071502685546875 +38332 -0.13543701171875 +38333 -0.219970703125 +38334 -0.300506591796875 +38335 -0.376312255859375 +38336 -0.416107177734375 +38337 -0.371124267578125 +38338 -0.242279052734375 +38339 -0.069732666015625 +38340 0.125640869140625 +38341 0.31268310546875 +38342 0.45501708984375 +38343 0.554779052734375 +38344 0.61065673828125 +38345 0.610931396484375 +38346 0.531463623046875 +38347 0.3883056640625 +38348 0.23468017578125 +38349 0.095245361328125 +38350 -0.00396728515625 +38351 -0.04852294921875 +38352 -0.055145263671875 +38353 -0.0758056640625 +38354 -0.138702392578125 +38355 -0.209197998046875 +38356 -0.289031982421875 +38357 -0.37884521484375 +38358 -0.456329345703125 +38359 -0.51641845703125 +38360 -0.519287109375 +38361 -0.458251953125 +38362 -0.384796142578125 +38363 -0.323699951171875 +38364 -0.269287109375 +38365 -0.1951904296875 +38366 -0.100006103515625 +38367 -0.01055908203125 +38368 0.1033935546875 +38369 0.24908447265625 +38370 0.373199462890625 +38371 0.45806884765625 +38372 0.511474609375 +38373 0.565399169921875 +38374 0.61138916015625 +38375 0.5897216796875 +38376 0.4906005859375 +38377 0.33148193359375 +38378 0.147796630859375 +38379 -0.01873779296875 +38380 -0.140289306640625 +38381 -0.191986083984375 +38382 -0.184295654296875 +38383 -0.161834716796875 +38384 -0.166595458984375 +38385 -0.19390869140625 +38386 -0.22442626953125 +38387 -0.279754638671875 +38388 -0.3389892578125 +38389 -0.3543701171875 +38390 -0.348175048828125 +38391 -0.32598876953125 +38392 -0.2581787109375 +38393 -0.139801025390625 +38394 0.014617919921875 +38395 0.144378662109375 +38396 0.221038818359375 +38397 0.27069091796875 +38398 0.294036865234375 +38399 0.311767578125 +38400 0.339141845703125 +38401 0.360260009765625 +38402 0.360504150390625 +38403 0.308380126953125 +38404 0.18170166015625 +38405 0.0047607421875 +38406 -0.17559814453125 +38407 -0.3143310546875 +38408 -0.36785888671875 +38409 -0.36248779296875 +38410 -0.343536376953125 +38411 -0.3018798828125 +38412 -0.231414794921875 +38413 -0.117645263671875 +38414 0.007049560546875 +38415 0.087982177734375 +38416 0.13946533203125 +38417 0.17425537109375 +38418 0.188201904296875 +38419 0.171234130859375 +38420 0.118438720703125 +38421 0.05706787109375 +38422 -0.010711669921875 +38423 -0.0914306640625 +38424 -0.162322998046875 +38425 -0.194549560546875 +38426 -0.1492919921875 +38427 -0.02166748046875 +38428 0.124053955078125 +38429 0.211151123046875 +38430 0.240447998046875 +38431 0.242218017578125 +38432 0.2257080078125 +38433 0.194366455078125 +38434 0.115509033203125 +38435 0.0128173828125 +38436 -0.053802490234375 +38437 -0.110626220703125 +38438 -0.199493408203125 +38439 -0.29437255859375 +38440 -0.33221435546875 +38441 -0.27972412109375 +38442 -0.185333251953125 +38443 -0.128204345703125 +38444 -0.115692138671875 +38445 -0.116455078125 +38446 -0.105926513671875 +38447 -0.053955078125 +38448 0.048797607421875 +38449 0.157318115234375 +38450 0.212005615234375 +38451 0.218475341796875 +38452 0.23724365234375 +38453 0.30535888671875 +38454 0.38128662109375 +38455 0.404449462890625 +38456 0.3944091796875 +38457 0.3885498046875 +38458 0.362640380859375 +38459 0.27362060546875 +38460 0.11712646484375 +38461 -0.054901123046875 +38462 -0.19085693359375 +38463 -0.28570556640625 +38464 -0.339263916015625 +38465 -0.3775634765625 +38466 -0.445709228515625 +38467 -0.535064697265625 +38468 -0.629058837890625 +38469 -0.697601318359375 +38470 -0.70391845703125 +38471 -0.6424560546875 +38472 -0.491241455078125 +38473 -0.265716552734375 +38474 -0.023712158203125 +38475 0.201751708984375 +38476 0.375823974609375 +38477 0.485076904296875 +38478 0.56884765625 +38479 0.634765625 +38480 0.63763427734375 +38481 0.5660400390625 +38482 0.4720458984375 +38483 0.40692138671875 +38484 0.3778076171875 +38485 0.376953125 +38486 0.371978759765625 +38487 0.313140869140625 +38488 0.184417724609375 +38489 0.011199951171875 +38490 -0.171051025390625 +38491 -0.33740234375 +38492 -0.47198486328125 +38493 -0.560394287109375 +38494 -0.58056640625 +38495 -0.54754638671875 +38496 -0.508575439453125 +38497 -0.459503173828125 +38498 -0.394378662109375 +38499 -0.35260009765625 +38500 -0.31170654296875 +38501 -0.197418212890625 +38502 -0.007965087890625 +38503 0.207489013671875 +38504 0.409210205078125 +38505 0.57208251953125 +38506 0.66595458984375 +38507 0.65875244140625 +38508 0.56744384765625 +38509 0.431396484375 +38510 0.29443359375 +38511 0.182464599609375 +38512 0.06365966796875 +38513 -0.075958251953125 +38514 -0.189422607421875 +38515 -0.271942138671875 +38516 -0.342529296875 +38517 -0.364166259765625 +38518 -0.327239990234375 +38519 -0.2769775390625 +38520 -0.253692626953125 +38521 -0.24365234375 +38522 -0.1983642578125 +38523 -0.116241455078125 +38524 -0.036834716796875 +38525 0.034881591796875 +38526 0.09124755859375 +38527 0.10888671875 +38528 0.125518798828125 +38529 0.15771484375 +38530 0.17828369140625 +38531 0.17108154296875 +38532 0.129974365234375 +38533 0.082427978515625 +38534 0.027679443359375 +38535 -0.065643310546875 +38536 -0.15936279296875 +38537 -0.21307373046875 +38538 -0.234649658203125 +38539 -0.2001953125 +38540 -0.119171142578125 +38541 -0.024749755859375 +38542 0.085784912109375 +38543 0.178131103515625 +38544 0.215576171875 +38545 0.211456298828125 +38546 0.17523193359375 +38547 0.128753662109375 +38548 0.1019287109375 +38549 0.0743408203125 +38550 0.04327392578125 +38551 0.038177490234375 +38552 0.076263427734375 +38553 0.14105224609375 +38554 0.186431884765625 +38555 0.188812255859375 +38556 0.1390380859375 +38557 0.041778564453125 +38558 -0.079437255859375 +38559 -0.219390869140625 +38560 -0.367828369140625 +38561 -0.494873046875 +38562 -0.556243896484375 +38563 -0.508697509765625 +38564 -0.3756103515625 +38565 -0.218902587890625 +38566 -0.063751220703125 +38567 0.091552734375 +38568 0.23602294921875 +38569 0.342987060546875 +38570 0.39520263671875 +38571 0.389373779296875 +38572 0.324249267578125 +38573 0.224090576171875 +38574 0.124267578125 +38575 0.037078857421875 +38576 -0.010101318359375 +38577 -0.019439697265625 +38578 -0.022796630859375 +38579 -0.001556396484375 +38580 0.056304931640625 +38581 0.106719970703125 +38582 0.096893310546875 +38583 0.042694091796875 +38584 -0.018035888671875 +38585 -0.07586669921875 +38586 -0.11944580078125 +38587 -0.15972900390625 +38588 -0.202606201171875 +38589 -0.24859619140625 +38590 -0.30517578125 +38591 -0.36212158203125 +38592 -0.39141845703125 +38593 -0.35528564453125 +38594 -0.249969482421875 +38595 -0.092864990234375 +38596 0.08905029296875 +38597 0.2352294921875 +38598 0.318817138671875 +38599 0.358642578125 +38600 0.347747802734375 +38601 0.28564453125 +38602 0.223175048828125 +38603 0.196746826171875 +38604 0.179840087890625 +38605 0.155548095703125 +38606 0.151214599609375 +38607 0.156951904296875 +38608 0.13177490234375 +38609 0.100799560546875 +38610 0.087127685546875 +38611 0.05487060546875 +38612 -0.009002685546875 +38613 -0.10400390625 +38614 -0.229400634765625 +38615 -0.35552978515625 +38616 -0.441925048828125 +38617 -0.473846435546875 +38618 -0.464813232421875 +38619 -0.419097900390625 +38620 -0.334320068359375 +38621 -0.227935791015625 +38622 -0.12347412109375 +38623 -0.02764892578125 +38624 0.077667236328125 +38625 0.2132568359375 +38626 0.38885498046875 +38627 0.582794189453125 +38628 0.734039306640625 +38629 0.800140380859375 +38630 0.7783203125 +38631 0.6651611328125 +38632 0.45965576171875 +38633 0.199188232421875 +38634 -0.050689697265625 +38635 -0.23297119140625 +38636 -0.33013916015625 +38637 -0.368408203125 +38638 -0.378936767578125 +38639 -0.376983642578125 +38640 -0.37969970703125 +38641 -0.391510009765625 +38642 -0.385345458984375 +38643 -0.3419189453125 +38644 -0.28289794921875 +38645 -0.251617431640625 +38646 -0.266143798828125 +38647 -0.273345947265625 +38648 -0.216796875 +38649 -0.128265380859375 +38650 -0.068145751953125 +38651 -0.0430908203125 +38652 -0.024444580078125 +38653 0.020721435546875 +38654 0.124481201171875 +38655 0.25787353515625 +38656 0.379119873046875 +38657 0.47991943359375 +38658 0.5281982421875 +38659 0.511138916015625 +38660 0.456207275390625 +38661 0.407470703125 +38662 0.383758544921875 +38663 0.35687255859375 +38664 0.31182861328125 +38665 0.250885009765625 +38666 0.1654052734375 +38667 0.035247802734375 +38668 -0.142059326171875 +38669 -0.33563232421875 +38670 -0.5345458984375 +38671 -0.72186279296875 +38672 -0.836669921875 +38673 -0.8326416015625 +38674 -0.7296142578125 +38675 -0.582550048828125 +38676 -0.440093994140625 +38677 -0.324310302734375 +38678 -0.20147705078125 +38679 -0.044647216796875 +38680 0.103973388671875 +38681 0.202392578125 +38682 0.264495849609375 +38683 0.338897705078125 +38684 0.443817138671875 +38685 0.545074462890625 +38686 0.6173095703125 +38687 0.6524658203125 +38688 0.66339111328125 +38689 0.6561279296875 +38690 0.606781005859375 +38691 0.501190185546875 +38692 0.352783203125 +38693 0.176544189453125 +38694 -0.034820556640625 +38695 -0.258209228515625 +38696 -0.44244384765625 +38697 -0.5753173828125 +38698 -0.65203857421875 +38699 -0.641632080078125 +38700 -0.562164306640625 +38701 -0.458038330078125 +38702 -0.350555419921875 +38703 -0.260528564453125 +38704 -0.192108154296875 +38705 -0.141937255859375 +38706 -0.1021728515625 +38707 -0.062896728515625 +38708 -0.011932373046875 +38709 0.062835693359375 +38710 0.148712158203125 +38711 0.241729736328125 +38712 0.34912109375 +38713 0.457305908203125 +38714 0.54388427734375 +38715 0.5728759765625 +38716 0.506591796875 +38717 0.351226806640625 +38718 0.146514892578125 +38719 -0.05523681640625 +38720 -0.21624755859375 +38721 -0.334930419921875 +38722 -0.402984619140625 +38723 -0.4412841796875 +38724 -0.49578857421875 +38725 -0.5601806640625 +38726 -0.600738525390625 +38727 -0.584228515625 +38728 -0.47930908203125 +38729 -0.27935791015625 +38730 -0.0089111328125 +38731 0.268798828125 +38732 0.482818603515625 +38733 0.60369873046875 +38734 0.650421142578125 +38735 0.66400146484375 +38736 0.6414794921875 +38737 0.572540283203125 +38738 0.498138427734375 +38739 0.439453125 +38740 0.375518798828125 +38741 0.274505615234375 +38742 0.1087646484375 +38743 -0.099395751953125 +38744 -0.3182373046875 +38745 -0.5489501953125 +38746 -0.7738037109375 +38747 -0.86383056640625 +38748 -0.870391845703125 +38749 -0.86895751953125 +38750 -0.861053466796875 +38751 -0.765869140625 +38752 -0.5301513671875 +38753 -0.214691162109375 +38754 0.137359619140625 +38755 0.474822998046875 +38756 0.76239013671875 +38757 0.867462158203125 +38758 0.870361328125 +38759 0.86480712890625 +38760 0.831817626953125 +38761 0.677581787109375 +38762 0.495880126953125 +38763 0.30767822265625 +38764 0.116180419921875 +38765 -0.110748291015625 +38766 -0.381805419921875 +38767 -0.6572265625 +38768 -0.857421875 +38769 -0.870391845703125 +38770 -0.870391845703125 +38771 -0.86444091796875 +38772 -0.85723876953125 +38773 -0.790008544921875 +38774 -0.62847900390625 +38775 -0.3956298828125 +38776 -0.126708984375 +38777 0.150115966796875 +38778 0.424041748046875 +38779 0.670623779296875 +38780 0.854522705078125 +38781 0.866485595703125 +38782 0.86920166015625 +38783 0.8653564453125 +38784 0.857147216796875 +38785 0.766845703125 +38786 0.628509521484375 +38787 0.462127685546875 +38788 0.297210693359375 +38789 0.14862060546875 +38790 -0.00537109375 +38791 -0.15753173828125 +38792 -0.31304931640625 +38793 -0.48876953125 +38794 -0.6416015625 +38795 -0.751373291015625 +38796 -0.84619140625 +38797 -0.861297607421875 +38798 -0.863250732421875 +38799 -0.856597900390625 +38800 -0.7498779296875 +38801 -0.624542236328125 +38802 -0.47808837890625 +38803 -0.253387451171875 +38804 0.003692626953125 +38805 0.2257080078125 +38806 0.427154541015625 +38807 0.643218994140625 +38808 0.855926513671875 +38809 0.870361328125 +38810 0.870361328125 +38811 0.862762451171875 +38812 0.79669189453125 +38813 0.595794677734375 +38814 0.362152099609375 +38815 0.1270751953125 +38816 -0.086944580078125 +38817 -0.2784423828125 +38818 -0.484832763671875 +38819 -0.729583740234375 +38820 -0.86688232421875 +38821 -0.870391845703125 +38822 -0.86859130859375 +38823 -0.86279296875 +38824 -0.817962646484375 +38825 -0.6116943359375 +38826 -0.3128662109375 +38827 0.039398193359375 +38828 0.422821044921875 +38829 0.805145263671875 +38830 0.870361328125 +38831 0.870361328125 +38832 0.860015869140625 +38833 0.727935791015625 +38834 0.48114013671875 +38835 0.2059326171875 +38836 -0.06103515625 +38837 -0.29913330078125 +38838 -0.516204833984375 +38839 -0.7252197265625 +38840 -0.85980224609375 +38841 -0.870391845703125 +38842 -0.870391845703125 +38843 -0.858062744140625 +38844 -0.673004150390625 +38845 -0.42694091796875 +38846 -0.2100830078125 +38847 -0.0362548828125 +38848 0.10943603515625 +38849 0.23516845703125 +38850 0.373687744140625 +38851 0.517791748046875 +38852 0.602783203125 +38853 0.635711669921875 +38854 0.655181884765625 +38855 0.65948486328125 +38856 0.651275634765625 +38857 0.61846923828125 +38858 0.53753662109375 +38859 0.404144287109375 +38860 0.22186279296875 +38861 0.003997802734375 +38862 -0.22100830078125 +38863 -0.42449951171875 +38864 -0.579833984375 +38865 -0.641876220703125 +38866 -0.6177978515625 +38867 -0.575531005859375 +38868 -0.526336669921875 +38869 -0.42645263671875 +38870 -0.2581787109375 +38871 -0.068695068359375 +38872 0.09222412109375 +38873 0.232147216796875 +38874 0.3509521484375 +38875 0.410064697265625 +38876 0.372955322265625 +38877 0.2554931640625 +38878 0.10711669921875 +38879 -0.052886962890625 +38880 -0.186279296875 +38881 -0.23291015625 +38882 -0.209442138671875 +38883 -0.174163818359375 +38884 -0.126739501953125 +38885 -0.048126220703125 +38886 0.0426025390625 +38887 0.10748291015625 +38888 0.1409912109375 +38889 0.19708251953125 +38890 0.273651123046875 +38891 0.31768798828125 +38892 0.341094970703125 +38893 0.368011474609375 +38894 0.37249755859375 +38895 0.30072021484375 +38896 0.1517333984375 +38897 -0.01470947265625 +38898 -0.1883544921875 +38899 -0.372711181640625 +38900 -0.51397705078125 +38901 -0.57177734375 +38902 -0.53948974609375 +38903 -0.43511962890625 +38904 -0.2962646484375 +38905 -0.161102294921875 +38906 -0.0435791015625 +38907 0.060394287109375 +38908 0.13665771484375 +38909 0.170135498046875 +38910 0.16552734375 +38911 0.15728759765625 +38912 0.150787353515625 +38913 0.12200927734375 +38914 0.080108642578125 +38915 0.05126953125 +38916 0.062896728515625 +38917 0.09271240234375 +38918 0.092987060546875 +38919 0.07855224609375 +38920 0.06427001953125 +38921 0.0347900390625 +38922 -0.01171875 +38923 -0.056060791015625 +38924 -0.055511474609375 +38925 -0.010467529296875 +38926 0.02508544921875 +38927 0.025665283203125 +38928 0.017333984375 +38929 0.00189208984375 +38930 -0.03173828125 +38931 -0.071502685546875 +38932 -0.13543701171875 +38933 -0.219970703125 +38934 -0.300506591796875 +38935 -0.376312255859375 +38936 -0.416107177734375 +38937 -0.371124267578125 +38938 -0.242279052734375 +38939 -0.069732666015625 +38940 0.125640869140625 +38941 0.31268310546875 +38942 0.45501708984375 +38943 0.554779052734375 +38944 0.61065673828125 +38945 0.610931396484375 +38946 0.531463623046875 +38947 0.3883056640625 +38948 0.23468017578125 +38949 0.095245361328125 +38950 -0.00396728515625 +38951 -0.04852294921875 +38952 -0.055145263671875 +38953 -0.0758056640625 +38954 -0.138702392578125 +38955 -0.209197998046875 +38956 -0.289031982421875 +38957 -0.37884521484375 +38958 -0.456329345703125 +38959 -0.51641845703125 +38960 -0.519287109375 +38961 -0.458251953125 +38962 -0.384796142578125 +38963 -0.323699951171875 +38964 -0.269287109375 +38965 -0.1951904296875 +38966 -0.100006103515625 +38967 -0.01055908203125 +38968 0.1033935546875 +38969 0.24908447265625 +38970 0.373199462890625 +38971 0.45806884765625 +38972 0.511474609375 +38973 0.565399169921875 +38974 0.61138916015625 +38975 0.5897216796875 +38976 0.4906005859375 +38977 0.33148193359375 +38978 0.147796630859375 +38979 -0.01873779296875 +38980 -0.140289306640625 +38981 -0.191986083984375 +38982 -0.184295654296875 +38983 -0.161834716796875 +38984 -0.166595458984375 +38985 -0.19390869140625 +38986 -0.22442626953125 +38987 -0.279754638671875 +38988 -0.3389892578125 +38989 -0.3543701171875 +38990 -0.348175048828125 +38991 -0.32598876953125 +38992 -0.2581787109375 +38993 -0.139801025390625 +38994 0.014617919921875 +38995 0.144378662109375 +38996 0.221038818359375 +38997 0.27069091796875 +38998 0.294036865234375 +38999 0.311767578125 +39000 0.339141845703125 +39001 0.360260009765625 +39002 0.360504150390625 +39003 0.308380126953125 +39004 0.18170166015625 +39005 0.0047607421875 +39006 -0.17559814453125 +39007 -0.3143310546875 +39008 -0.36785888671875 +39009 -0.36248779296875 +39010 -0.343536376953125 +39011 -0.3018798828125 +39012 -0.231414794921875 +39013 -0.117645263671875 +39014 0.007049560546875 +39015 0.087982177734375 +39016 0.13946533203125 +39017 0.17425537109375 +39018 0.188201904296875 +39019 0.171234130859375 +39020 0.118438720703125 +39021 0.05706787109375 +39022 -0.010711669921875 +39023 -0.0914306640625 +39024 -0.162322998046875 +39025 -0.194549560546875 +39026 -0.1492919921875 +39027 -0.02166748046875 +39028 0.124053955078125 +39029 0.211151123046875 +39030 0.240447998046875 +39031 0.242218017578125 +39032 0.2257080078125 +39033 0.194366455078125 +39034 0.115509033203125 +39035 0.0128173828125 +39036 -0.053802490234375 +39037 -0.110626220703125 +39038 -0.199493408203125 +39039 -0.29437255859375 +39040 -0.33221435546875 +39041 -0.27972412109375 +39042 -0.185333251953125 +39043 -0.128204345703125 +39044 -0.115692138671875 +39045 -0.116455078125 +39046 -0.105926513671875 +39047 -0.053955078125 +39048 0.048797607421875 +39049 0.157318115234375 +39050 0.212005615234375 +39051 0.218475341796875 +39052 0.23724365234375 +39053 0.30535888671875 +39054 0.38128662109375 +39055 0.404449462890625 +39056 0.3944091796875 +39057 0.3885498046875 +39058 0.362640380859375 +39059 0.27362060546875 +39060 0.11712646484375 +39061 -0.054901123046875 +39062 -0.19085693359375 +39063 -0.28570556640625 +39064 -0.339263916015625 +39065 -0.3775634765625 +39066 -0.445709228515625 +39067 -0.535064697265625 +39068 -0.629058837890625 +39069 -0.697601318359375 +39070 -0.70391845703125 +39071 -0.6424560546875 +39072 -0.491241455078125 +39073 -0.265716552734375 +39074 -0.023712158203125 +39075 0.201751708984375 +39076 0.375823974609375 +39077 0.485076904296875 +39078 0.56884765625 +39079 0.634765625 +39080 0.63763427734375 +39081 0.5660400390625 +39082 0.4720458984375 +39083 0.40692138671875 +39084 0.3778076171875 +39085 0.376953125 +39086 0.371978759765625 +39087 0.313140869140625 +39088 0.184417724609375 +39089 0.011199951171875 +39090 -0.171051025390625 +39091 -0.33740234375 +39092 -0.47198486328125 +39093 -0.560394287109375 +39094 -0.58056640625 +39095 -0.54754638671875 +39096 -0.508575439453125 +39097 -0.459503173828125 +39098 -0.394378662109375 +39099 -0.35260009765625 +39100 -0.31170654296875 +39101 -0.197418212890625 +39102 -0.007965087890625 +39103 0.207489013671875 +39104 0.409210205078125 +39105 0.57208251953125 +39106 0.66595458984375 +39107 0.65875244140625 +39108 0.56744384765625 +39109 0.431396484375 +39110 0.29443359375 +39111 0.182464599609375 +39112 0.06365966796875 +39113 -0.075958251953125 +39114 -0.189422607421875 +39115 -0.271942138671875 +39116 -0.342529296875 +39117 -0.364166259765625 +39118 -0.327239990234375 +39119 -0.2769775390625 +39120 -0.253692626953125 +39121 -0.24365234375 +39122 -0.1983642578125 +39123 -0.116241455078125 +39124 -0.036834716796875 +39125 0.034881591796875 +39126 0.09124755859375 +39127 0.10888671875 +39128 0.125518798828125 +39129 0.15771484375 +39130 0.17828369140625 +39131 0.17108154296875 +39132 0.129974365234375 +39133 0.082427978515625 +39134 0.027679443359375 +39135 -0.065643310546875 +39136 -0.15936279296875 +39137 -0.21307373046875 +39138 -0.234649658203125 +39139 -0.2001953125 +39140 -0.119171142578125 +39141 -0.024749755859375 +39142 0.085784912109375 +39143 0.178131103515625 +39144 0.215576171875 +39145 0.211456298828125 +39146 0.17523193359375 +39147 0.128753662109375 +39148 0.1019287109375 +39149 0.0743408203125 +39150 0.04327392578125 +39151 0.038177490234375 +39152 0.076263427734375 +39153 0.14105224609375 +39154 0.186431884765625 +39155 0.188812255859375 +39156 0.1390380859375 +39157 0.041778564453125 +39158 -0.079437255859375 +39159 -0.219390869140625 +39160 -0.367828369140625 +39161 -0.494873046875 +39162 -0.556243896484375 +39163 -0.508697509765625 +39164 -0.3756103515625 +39165 -0.218902587890625 +39166 -0.063751220703125 +39167 0.091552734375 +39168 0.23602294921875 +39169 0.342987060546875 +39170 0.39520263671875 +39171 0.389373779296875 +39172 0.324249267578125 +39173 0.224090576171875 +39174 0.124267578125 +39175 0.037078857421875 +39176 -0.010101318359375 +39177 -0.019439697265625 +39178 -0.022796630859375 +39179 -0.001556396484375 +39180 0.056304931640625 +39181 0.106719970703125 +39182 0.096893310546875 +39183 0.042694091796875 +39184 -0.018035888671875 +39185 -0.07586669921875 +39186 -0.11944580078125 +39187 -0.15972900390625 +39188 -0.202606201171875 +39189 -0.24859619140625 +39190 -0.30517578125 +39191 -0.36212158203125 +39192 -0.39141845703125 +39193 -0.35528564453125 +39194 -0.249969482421875 +39195 -0.092864990234375 +39196 0.08905029296875 +39197 0.2352294921875 +39198 0.318817138671875 +39199 0.358642578125 +39200 0.347747802734375 +39201 0.28564453125 +39202 0.223175048828125 +39203 0.196746826171875 +39204 0.179840087890625 +39205 0.155548095703125 +39206 0.151214599609375 +39207 0.156951904296875 +39208 0.13177490234375 +39209 0.100799560546875 +39210 0.087127685546875 +39211 0.05487060546875 +39212 -0.009002685546875 +39213 -0.10400390625 +39214 -0.229400634765625 +39215 -0.35552978515625 +39216 -0.441925048828125 +39217 -0.473846435546875 +39218 -0.464813232421875 +39219 -0.419097900390625 +39220 -0.334320068359375 +39221 -0.227935791015625 +39222 -0.12347412109375 +39223 -0.02764892578125 +39224 0.077667236328125 +39225 0.2132568359375 +39226 0.38885498046875 +39227 0.582794189453125 +39228 0.734039306640625 +39229 0.800140380859375 +39230 0.7783203125 +39231 0.6651611328125 +39232 0.45965576171875 +39233 0.199188232421875 +39234 -0.050689697265625 +39235 -0.23297119140625 +39236 -0.33013916015625 +39237 -0.368408203125 +39238 -0.378936767578125 +39239 -0.376983642578125 +39240 -0.37969970703125 +39241 -0.391510009765625 +39242 -0.385345458984375 +39243 -0.3419189453125 +39244 -0.28289794921875 +39245 -0.251617431640625 +39246 -0.266143798828125 +39247 -0.273345947265625 +39248 -0.216796875 +39249 -0.128265380859375 +39250 -0.068145751953125 +39251 -0.0430908203125 +39252 -0.024444580078125 +39253 0.020721435546875 +39254 0.124481201171875 +39255 0.25787353515625 +39256 0.379119873046875 +39257 0.47991943359375 +39258 0.5281982421875 +39259 0.511138916015625 +39260 0.456207275390625 +39261 0.407470703125 +39262 0.383758544921875 +39263 0.35687255859375 +39264 0.31182861328125 +39265 0.250885009765625 +39266 0.1654052734375 +39267 0.035247802734375 +39268 -0.142059326171875 +39269 -0.33563232421875 +39270 -0.5345458984375 +39271 -0.72186279296875 +39272 -0.836669921875 +39273 -0.8326416015625 +39274 -0.7296142578125 +39275 -0.582550048828125 +39276 -0.440093994140625 +39277 -0.324310302734375 +39278 -0.20147705078125 +39279 -0.044647216796875 +39280 0.103973388671875 +39281 0.202392578125 +39282 0.264495849609375 +39283 0.338897705078125 +39284 0.443817138671875 +39285 0.545074462890625 +39286 0.6173095703125 +39287 0.6524658203125 +39288 0.66339111328125 +39289 0.6561279296875 +39290 0.606781005859375 +39291 0.501190185546875 +39292 0.352783203125 +39293 0.176544189453125 +39294 -0.034820556640625 +39295 -0.258209228515625 +39296 -0.44244384765625 +39297 -0.5753173828125 +39298 -0.65203857421875 +39299 -0.641632080078125 +39300 -0.562164306640625 +39301 -0.458038330078125 +39302 -0.350555419921875 +39303 -0.260528564453125 +39304 -0.192108154296875 +39305 -0.141937255859375 +39306 -0.1021728515625 +39307 -0.062896728515625 +39308 -0.011932373046875 +39309 0.062835693359375 +39310 0.148712158203125 +39311 0.241729736328125 +39312 0.34912109375 +39313 0.457305908203125 +39314 0.54388427734375 +39315 0.5728759765625 +39316 0.506591796875 +39317 0.351226806640625 +39318 0.146514892578125 +39319 -0.05523681640625 +39320 -0.21624755859375 +39321 -0.334930419921875 +39322 -0.402984619140625 +39323 -0.4412841796875 +39324 -0.49578857421875 +39325 -0.5601806640625 +39326 -0.600738525390625 +39327 -0.584228515625 +39328 -0.47930908203125 +39329 -0.27935791015625 +39330 -0.0089111328125 +39331 0.268798828125 +39332 0.482818603515625 +39333 0.60369873046875 +39334 0.650421142578125 +39335 0.66400146484375 +39336 0.6414794921875 +39337 0.572540283203125 +39338 0.498138427734375 +39339 0.439453125 +39340 0.375518798828125 +39341 0.274505615234375 +39342 0.1087646484375 +39343 -0.099395751953125 +39344 -0.3182373046875 +39345 -0.5489501953125 +39346 -0.7738037109375 +39347 -0.86383056640625 +39348 -0.870391845703125 +39349 -0.86895751953125 +39350 -0.861053466796875 +39351 -0.765869140625 +39352 -0.5301513671875 +39353 -0.214691162109375 +39354 0.137359619140625 +39355 0.474822998046875 +39356 0.76239013671875 +39357 0.867462158203125 +39358 0.870361328125 +39359 0.86480712890625 +39360 0.831817626953125 +39361 0.677581787109375 +39362 0.495880126953125 +39363 0.30767822265625 +39364 0.116180419921875 +39365 -0.110748291015625 +39366 -0.381805419921875 +39367 -0.6572265625 +39368 -0.857421875 +39369 -0.870391845703125 +39370 -0.870391845703125 +39371 -0.86444091796875 +39372 -0.85723876953125 +39373 -0.790008544921875 +39374 -0.62847900390625 +39375 -0.3956298828125 +39376 -0.126708984375 +39377 0.150115966796875 +39378 0.424041748046875 +39379 0.670623779296875 +39380 0.854522705078125 +39381 0.866485595703125 +39382 0.86920166015625 +39383 0.8653564453125 +39384 0.857147216796875 +39385 0.766845703125 +39386 0.628509521484375 +39387 0.462127685546875 +39388 0.297210693359375 +39389 0.14862060546875 +39390 -0.00537109375 +39391 -0.15753173828125 +39392 -0.31304931640625 +39393 -0.48876953125 +39394 -0.6416015625 +39395 -0.751373291015625 +39396 -0.84619140625 +39397 -0.861297607421875 +39398 -0.863250732421875 +39399 -0.856597900390625 +39400 -0.7498779296875 +39401 -0.624542236328125 +39402 -0.47808837890625 +39403 -0.253387451171875 +39404 0.003692626953125 +39405 0.2257080078125 +39406 0.427154541015625 +39407 0.643218994140625 +39408 0.855926513671875 +39409 0.870361328125 +39410 0.870361328125 +39411 0.862762451171875 +39412 0.79669189453125 +39413 0.595794677734375 +39414 0.362152099609375 +39415 0.1270751953125 +39416 -0.086944580078125 +39417 -0.2784423828125 +39418 -0.484832763671875 +39419 -0.729583740234375 +39420 -0.86688232421875 +39421 -0.870391845703125 +39422 -0.86859130859375 +39423 -0.86279296875 +39424 -0.817962646484375 +39425 -0.6116943359375 +39426 -0.3128662109375 +39427 0.039398193359375 +39428 0.422821044921875 +39429 0.805145263671875 +39430 0.870361328125 +39431 0.870361328125 +39432 0.860015869140625 +39433 0.727935791015625 +39434 0.48114013671875 +39435 0.2059326171875 +39436 -0.06103515625 +39437 -0.29913330078125 +39438 -0.516204833984375 +39439 -0.7252197265625 +39440 -0.85980224609375 +39441 -0.870391845703125 +39442 -0.870391845703125 +39443 -0.858062744140625 +39444 -0.673004150390625 +39445 -0.42694091796875 +39446 -0.2100830078125 +39447 -0.0362548828125 +39448 0.10943603515625 +39449 0.23516845703125 +39450 0.373687744140625 +39451 0.517791748046875 +39452 0.602783203125 +39453 0.635711669921875 +39454 0.655181884765625 +39455 0.65948486328125 +39456 0.651275634765625 +39457 0.61846923828125 +39458 0.53753662109375 +39459 0.404144287109375 +39460 0.22186279296875 +39461 0.003997802734375 +39462 -0.22100830078125 +39463 -0.42449951171875 +39464 -0.579833984375 +39465 -0.641876220703125 +39466 -0.6177978515625 +39467 -0.575531005859375 +39468 -0.526336669921875 +39469 -0.42645263671875 +39470 -0.2581787109375 +39471 -0.068695068359375 +39472 0.09222412109375 +39473 0.232147216796875 +39474 0.3509521484375 +39475 0.410064697265625 +39476 0.372955322265625 +39477 0.2554931640625 +39478 0.10711669921875 +39479 -0.052886962890625 +39480 -0.186279296875 +39481 -0.23291015625 +39482 -0.209442138671875 +39483 -0.174163818359375 +39484 -0.126739501953125 +39485 -0.048126220703125 +39486 0.0426025390625 +39487 0.10748291015625 +39488 0.1409912109375 +39489 0.19708251953125 +39490 0.273651123046875 +39491 0.31768798828125 +39492 0.341094970703125 +39493 0.368011474609375 +39494 0.37249755859375 +39495 0.30072021484375 +39496 0.1517333984375 +39497 -0.01470947265625 +39498 -0.1883544921875 +39499 -0.372711181640625 +39500 -0.51397705078125 +39501 -0.57177734375 +39502 -0.53948974609375 +39503 -0.43511962890625 +39504 -0.2962646484375 +39505 -0.161102294921875 +39506 -0.0435791015625 +39507 0.060394287109375 +39508 0.13665771484375 +39509 0.170135498046875 +39510 0.16552734375 +39511 0.15728759765625 +39512 0.150787353515625 +39513 0.12200927734375 +39514 0.080108642578125 +39515 0.05126953125 +39516 0.062896728515625 +39517 0.09271240234375 +39518 0.092987060546875 +39519 0.07855224609375 +39520 0.06427001953125 +39521 0.0347900390625 +39522 -0.01171875 +39523 -0.056060791015625 +39524 -0.055511474609375 +39525 -0.010467529296875 +39526 0.02508544921875 +39527 0.025665283203125 +39528 0.017333984375 +39529 0.00189208984375 +39530 -0.03173828125 +39531 -0.071502685546875 +39532 -0.13543701171875 +39533 -0.219970703125 +39534 -0.300506591796875 +39535 -0.376312255859375 +39536 -0.416107177734375 +39537 -0.371124267578125 +39538 -0.242279052734375 +39539 -0.069732666015625 +39540 0.125640869140625 +39541 0.31268310546875 +39542 0.45501708984375 +39543 0.554779052734375 +39544 0.61065673828125 +39545 0.610931396484375 +39546 0.531463623046875 +39547 0.3883056640625 +39548 0.23468017578125 +39549 0.095245361328125 +39550 -0.00396728515625 +39551 -0.04852294921875 +39552 -0.055145263671875 +39553 -0.0758056640625 +39554 -0.138702392578125 +39555 -0.209197998046875 +39556 -0.289031982421875 +39557 -0.37884521484375 +39558 -0.456329345703125 +39559 -0.51641845703125 +39560 -0.519287109375 +39561 -0.458251953125 +39562 -0.384796142578125 +39563 -0.323699951171875 +39564 -0.269287109375 +39565 -0.1951904296875 +39566 -0.100006103515625 +39567 -0.01055908203125 +39568 0.1033935546875 +39569 0.24908447265625 +39570 0.373199462890625 +39571 0.45806884765625 +39572 0.511474609375 +39573 0.565399169921875 +39574 0.61138916015625 +39575 0.5897216796875 +39576 0.4906005859375 +39577 0.33148193359375 +39578 0.147796630859375 +39579 -0.01873779296875 +39580 -0.140289306640625 +39581 -0.191986083984375 +39582 -0.184295654296875 +39583 -0.161834716796875 +39584 -0.166595458984375 +39585 -0.19390869140625 +39586 -0.22442626953125 +39587 -0.279754638671875 +39588 -0.3389892578125 +39589 -0.3543701171875 +39590 -0.348175048828125 +39591 -0.32598876953125 +39592 -0.2581787109375 +39593 -0.139801025390625 +39594 0.014617919921875 +39595 0.144378662109375 +39596 0.221038818359375 +39597 0.27069091796875 +39598 0.294036865234375 +39599 0.311767578125 +39600 0.339141845703125 +39601 0.360260009765625 +39602 0.360504150390625 +39603 0.308380126953125 +39604 0.18170166015625 +39605 0.0047607421875 +39606 -0.17559814453125 +39607 -0.3143310546875 +39608 -0.36785888671875 +39609 -0.36248779296875 +39610 -0.343536376953125 +39611 -0.3018798828125 +39612 -0.231414794921875 +39613 -0.117645263671875 +39614 0.007049560546875 +39615 0.087982177734375 +39616 0.13946533203125 +39617 0.17425537109375 +39618 0.188201904296875 +39619 0.171234130859375 +39620 0.118438720703125 +39621 0.05706787109375 +39622 -0.010711669921875 +39623 -0.0914306640625 +39624 -0.162322998046875 +39625 -0.194549560546875 +39626 -0.1492919921875 +39627 -0.02166748046875 +39628 0.124053955078125 +39629 0.211151123046875 +39630 0.240447998046875 +39631 0.242218017578125 +39632 0.2257080078125 +39633 0.194366455078125 +39634 0.115509033203125 +39635 0.0128173828125 +39636 -0.053802490234375 +39637 -0.110626220703125 +39638 -0.199493408203125 +39639 -0.29437255859375 +39640 -0.33221435546875 +39641 -0.27972412109375 +39642 -0.185333251953125 +39643 -0.128204345703125 +39644 -0.115692138671875 +39645 -0.116455078125 +39646 -0.105926513671875 +39647 -0.053955078125 +39648 0.048797607421875 +39649 0.157318115234375 +39650 0.212005615234375 +39651 0.218475341796875 +39652 0.23724365234375 +39653 0.30535888671875 +39654 0.38128662109375 +39655 0.404449462890625 +39656 0.3944091796875 +39657 0.3885498046875 +39658 0.362640380859375 +39659 0.27362060546875 +39660 0.11712646484375 +39661 -0.054901123046875 +39662 -0.19085693359375 +39663 -0.28570556640625 +39664 -0.339263916015625 +39665 -0.3775634765625 +39666 -0.445709228515625 +39667 -0.535064697265625 +39668 -0.629058837890625 +39669 -0.697601318359375 +39670 -0.70391845703125 +39671 -0.6424560546875 +39672 -0.491241455078125 +39673 -0.265716552734375 +39674 -0.023712158203125 +39675 0.201751708984375 +39676 0.375823974609375 +39677 0.485076904296875 +39678 0.56884765625 +39679 0.634765625 +39680 0.63763427734375 +39681 0.5660400390625 +39682 0.4720458984375 +39683 0.40692138671875 +39684 0.3778076171875 +39685 0.376953125 +39686 0.371978759765625 +39687 0.313140869140625 +39688 0.184417724609375 +39689 0.011199951171875 +39690 -0.171051025390625 +39691 -0.33740234375 +39692 -0.47198486328125 +39693 -0.560394287109375 +39694 -0.58056640625 +39695 -0.54754638671875 +39696 -0.508575439453125 +39697 -0.459503173828125 +39698 -0.394378662109375 +39699 -0.35260009765625 +39700 -0.31170654296875 +39701 -0.197418212890625 +39702 -0.007965087890625 +39703 0.207489013671875 +39704 0.409210205078125 +39705 0.57208251953125 +39706 0.66595458984375 +39707 0.65875244140625 +39708 0.56744384765625 +39709 0.431396484375 +39710 0.29443359375 +39711 0.182464599609375 +39712 0.06365966796875 +39713 -0.075958251953125 +39714 -0.189422607421875 +39715 -0.271942138671875 +39716 -0.342529296875 +39717 -0.364166259765625 +39718 -0.327239990234375 +39719 -0.2769775390625 +39720 -0.253692626953125 +39721 -0.24365234375 +39722 -0.1983642578125 +39723 -0.116241455078125 +39724 -0.036834716796875 +39725 0.034881591796875 +39726 0.09124755859375 +39727 0.10888671875 +39728 0.125518798828125 +39729 0.15771484375 +39730 0.17828369140625 +39731 0.17108154296875 +39732 0.129974365234375 +39733 0.082427978515625 +39734 0.027679443359375 +39735 -0.065643310546875 +39736 -0.15936279296875 +39737 -0.21307373046875 +39738 -0.234649658203125 +39739 -0.2001953125 +39740 -0.119171142578125 +39741 -0.024749755859375 +39742 0.085784912109375 +39743 0.178131103515625 +39744 0.215576171875 +39745 0.211456298828125 +39746 0.17523193359375 +39747 0.128753662109375 +39748 0.1019287109375 +39749 0.0743408203125 +39750 0.04327392578125 +39751 0.038177490234375 +39752 0.076263427734375 +39753 0.14105224609375 +39754 0.186431884765625 +39755 0.188812255859375 +39756 0.1390380859375 +39757 0.041778564453125 +39758 -0.079437255859375 +39759 -0.219390869140625 +39760 -0.367828369140625 +39761 -0.494873046875 +39762 -0.556243896484375 +39763 -0.508697509765625 +39764 -0.3756103515625 +39765 -0.218902587890625 +39766 -0.063751220703125 +39767 0.091552734375 +39768 0.23602294921875 +39769 0.342987060546875 +39770 0.39520263671875 +39771 0.389373779296875 +39772 0.324249267578125 +39773 0.224090576171875 +39774 0.124267578125 +39775 0.037078857421875 +39776 -0.010101318359375 +39777 -0.019439697265625 +39778 -0.022796630859375 +39779 -0.001556396484375 +39780 0.056304931640625 +39781 0.106719970703125 +39782 0.096893310546875 +39783 0.042694091796875 +39784 -0.018035888671875 +39785 -0.07586669921875 +39786 -0.11944580078125 +39787 -0.15972900390625 +39788 -0.202606201171875 +39789 -0.24859619140625 +39790 -0.30517578125 +39791 -0.36212158203125 +39792 -0.39141845703125 +39793 -0.35528564453125 +39794 -0.249969482421875 +39795 -0.092864990234375 +39796 0.08905029296875 +39797 0.2352294921875 +39798 0.318817138671875 +39799 0.358642578125 +39800 0.347747802734375 +39801 0.28564453125 +39802 0.223175048828125 +39803 0.196746826171875 +39804 0.179840087890625 +39805 0.155548095703125 +39806 0.151214599609375 +39807 0.156951904296875 +39808 0.13177490234375 +39809 0.100799560546875 +39810 0.087127685546875 +39811 0.05487060546875 +39812 -0.009002685546875 +39813 -0.10400390625 +39814 -0.229400634765625 +39815 -0.35552978515625 +39816 -0.441925048828125 +39817 -0.473846435546875 +39818 -0.464813232421875 +39819 -0.419097900390625 +39820 -0.334320068359375 +39821 -0.227935791015625 +39822 -0.12347412109375 +39823 -0.02764892578125 +39824 0.077667236328125 +39825 0.2132568359375 +39826 0.38885498046875 +39827 0.582794189453125 +39828 0.734039306640625 +39829 0.800140380859375 +39830 0.7783203125 +39831 0.6651611328125 +39832 0.45965576171875 +39833 0.199188232421875 +39834 -0.050689697265625 +39835 -0.23297119140625 +39836 -0.33013916015625 +39837 -0.368408203125 +39838 -0.378936767578125 +39839 -0.376983642578125 +39840 -0.37969970703125 +39841 -0.391510009765625 +39842 -0.385345458984375 +39843 -0.3419189453125 +39844 -0.28289794921875 +39845 -0.251617431640625 +39846 -0.266143798828125 +39847 -0.273345947265625 +39848 -0.216796875 +39849 -0.128265380859375 +39850 -0.068145751953125 +39851 -0.0430908203125 +39852 -0.024444580078125 +39853 0.020721435546875 +39854 0.124481201171875 +39855 0.25787353515625 +39856 0.379119873046875 +39857 0.47991943359375 +39858 0.5281982421875 +39859 0.511138916015625 +39860 0.456207275390625 +39861 0.407470703125 +39862 0.383758544921875 +39863 0.35687255859375 +39864 0.31182861328125 +39865 0.250885009765625 +39866 0.1654052734375 +39867 0.035247802734375 +39868 -0.142059326171875 +39869 -0.33563232421875 +39870 -0.5345458984375 +39871 -0.72186279296875 +39872 -0.836669921875 +39873 -0.8326416015625 +39874 -0.7296142578125 +39875 -0.582550048828125 +39876 -0.440093994140625 +39877 -0.324310302734375 +39878 -0.20147705078125 +39879 -0.044647216796875 +39880 0.103973388671875 +39881 0.202392578125 +39882 0.264495849609375 +39883 0.338897705078125 +39884 0.443817138671875 +39885 0.545074462890625 +39886 0.6173095703125 +39887 0.6524658203125 +39888 0.66339111328125 +39889 0.6561279296875 +39890 0.606781005859375 +39891 0.501190185546875 +39892 0.352783203125 +39893 0.176544189453125 +39894 -0.034820556640625 +39895 -0.258209228515625 +39896 -0.44244384765625 +39897 -0.5753173828125 +39898 -0.65203857421875 +39899 -0.641632080078125 +39900 -0.562164306640625 +39901 -0.458038330078125 +39902 -0.350555419921875 +39903 -0.260528564453125 +39904 -0.192108154296875 +39905 -0.141937255859375 +39906 -0.1021728515625 +39907 -0.062896728515625 +39908 -0.011932373046875 +39909 0.062835693359375 +39910 0.148712158203125 +39911 0.241729736328125 +39912 0.34912109375 +39913 0.457305908203125 +39914 0.54388427734375 +39915 0.5728759765625 +39916 0.506591796875 +39917 0.351226806640625 +39918 0.146514892578125 +39919 -0.05523681640625 +39920 -0.21624755859375 +39921 -0.334930419921875 +39922 -0.402984619140625 +39923 -0.4412841796875 +39924 -0.49578857421875 +39925 -0.5601806640625 +39926 -0.600738525390625 +39927 -0.584228515625 +39928 -0.47930908203125 +39929 -0.27935791015625 +39930 -0.0089111328125 +39931 0.268798828125 +39932 0.482818603515625 +39933 0.60369873046875 +39934 0.650421142578125 +39935 0.66400146484375 +39936 0.6414794921875 +39937 0.572540283203125 +39938 0.498138427734375 +39939 0.439453125 +39940 0.375518798828125 +39941 0.274505615234375 +39942 0.1087646484375 +39943 -0.099395751953125 +39944 -0.3182373046875 +39945 -0.5489501953125 +39946 -0.7738037109375 +39947 -0.86383056640625 +39948 -0.870391845703125 +39949 -0.86895751953125 +39950 -0.861053466796875 +39951 -0.765869140625 +39952 -0.5301513671875 +39953 -0.214691162109375 +39954 0.137359619140625 +39955 0.474822998046875 +39956 0.76239013671875 +39957 0.867462158203125 +39958 0.870361328125 +39959 0.86480712890625 +39960 0.831817626953125 +39961 0.677581787109375 +39962 0.495880126953125 +39963 0.30767822265625 +39964 0.116180419921875 +39965 -0.110748291015625 +39966 -0.381805419921875 +39967 -0.6572265625 +39968 -0.857421875 +39969 -0.870391845703125 +39970 -0.870391845703125 +39971 -0.86444091796875 +39972 -0.85723876953125 +39973 -0.790008544921875 +39974 -0.62847900390625 +39975 -0.3956298828125 +39976 -0.126708984375 +39977 0.150115966796875 +39978 0.424041748046875 +39979 0.670623779296875 +39980 0.854522705078125 +39981 0.866485595703125 +39982 0.86920166015625 +39983 0.8653564453125 +39984 0.857147216796875 +39985 0.766845703125 +39986 0.628509521484375 +39987 0.462127685546875 +39988 0.297210693359375 +39989 0.14862060546875 +39990 -0.00537109375 +39991 -0.15753173828125 +39992 -0.31304931640625 +39993 -0.48876953125 +39994 -0.6416015625 +39995 -0.751373291015625 +39996 -0.84619140625 +39997 -0.861297607421875 +39998 -0.863250732421875 +39999 -0.856597900390625 +40000 -0.7498779296875 +40001 -0.624542236328125 +40002 -0.47808837890625 +40003 -0.253387451171875 +40004 0.003692626953125 +40005 0.2257080078125 +40006 0.427154541015625 +40007 0.643218994140625 +40008 0.855926513671875 +40009 0.870361328125 +40010 0.870361328125 +40011 0.862762451171875 +40012 0.79669189453125 +40013 0.595794677734375 +40014 0.362152099609375 +40015 0.1270751953125 +40016 -0.086944580078125 +40017 -0.2784423828125 +40018 -0.484832763671875 +40019 -0.729583740234375 +40020 -0.86688232421875 +40021 -0.870391845703125 +40022 -0.86859130859375 +40023 -0.86279296875 +40024 -0.817962646484375 +40025 -0.6116943359375 +40026 -0.3128662109375 +40027 0.039398193359375 +40028 0.422821044921875 +40029 0.805145263671875 +40030 0.870361328125 +40031 0.870361328125 +40032 0.860015869140625 +40033 0.727935791015625 +40034 0.48114013671875 +40035 0.2059326171875 +40036 -0.06103515625 +40037 -0.29913330078125 +40038 -0.516204833984375 +40039 -0.7252197265625 +40040 -0.85980224609375 +40041 -0.870391845703125 +40042 -0.870391845703125 +40043 -0.858062744140625 +40044 -0.673004150390625 +40045 -0.42694091796875 +40046 -0.2100830078125 +40047 -0.0362548828125 +40048 0.10943603515625 +40049 0.23516845703125 +40050 0.373687744140625 +40051 0.517791748046875 +40052 0.602783203125 +40053 0.635711669921875 +40054 0.655181884765625 +40055 0.65948486328125 +40056 0.651275634765625 +40057 0.61846923828125 +40058 0.53753662109375 +40059 0.404144287109375 +40060 0.22186279296875 +40061 0.003997802734375 +40062 -0.22100830078125 +40063 -0.42449951171875 +40064 -0.579833984375 +40065 -0.641876220703125 +40066 -0.6177978515625 +40067 -0.575531005859375 +40068 -0.526336669921875 +40069 -0.42645263671875 +40070 -0.2581787109375 +40071 -0.068695068359375 +40072 0.09222412109375 +40073 0.232147216796875 +40074 0.3509521484375 +40075 0.410064697265625 +40076 0.372955322265625 +40077 0.2554931640625 +40078 0.10711669921875 +40079 -0.052886962890625 +40080 -0.186279296875 +40081 -0.23291015625 +40082 -0.209442138671875 +40083 -0.174163818359375 +40084 -0.126739501953125 +40085 -0.048126220703125 +40086 0.0426025390625 +40087 0.10748291015625 +40088 0.1409912109375 +40089 0.19708251953125 +40090 0.273651123046875 +40091 0.31768798828125 +40092 0.341094970703125 +40093 0.368011474609375 +40094 0.37249755859375 +40095 0.30072021484375 +40096 0.1517333984375 +40097 -0.01470947265625 +40098 -0.1883544921875 +40099 -0.372711181640625 +40100 -0.51397705078125 +40101 -0.57177734375 +40102 -0.53948974609375 +40103 -0.43511962890625 +40104 -0.2962646484375 +40105 -0.161102294921875 +40106 -0.0435791015625 +40107 0.060394287109375 +40108 0.13665771484375 +40109 0.170135498046875 +40110 0.16552734375 +40111 0.15728759765625 +40112 0.150787353515625 +40113 0.12200927734375 +40114 0.080108642578125 +40115 0.05126953125 +40116 0.062896728515625 +40117 0.09271240234375 +40118 0.092987060546875 +40119 0.07855224609375 +40120 0.06427001953125 +40121 0.0347900390625 +40122 -0.01171875 +40123 -0.056060791015625 +40124 -0.055511474609375 +40125 -0.010467529296875 +40126 0.02508544921875 +40127 0.025665283203125 +40128 0.017333984375 +40129 0.00189208984375 +40130 -0.03173828125 +40131 -0.071502685546875 +40132 -0.13543701171875 +40133 -0.219970703125 +40134 -0.300506591796875 +40135 -0.376312255859375 +40136 -0.416107177734375 +40137 -0.371124267578125 +40138 -0.242279052734375 +40139 -0.069732666015625 +40140 0.125640869140625 +40141 0.31268310546875 +40142 0.45501708984375 +40143 0.554779052734375 +40144 0.61065673828125 +40145 0.610931396484375 +40146 0.531463623046875 +40147 0.3883056640625 +40148 0.23468017578125 +40149 0.095245361328125 +40150 -0.00396728515625 +40151 -0.04852294921875 +40152 -0.055145263671875 +40153 -0.0758056640625 +40154 -0.138702392578125 +40155 -0.209197998046875 +40156 -0.289031982421875 +40157 -0.37884521484375 +40158 -0.456329345703125 +40159 -0.51641845703125 +40160 -0.519287109375 +40161 -0.458251953125 +40162 -0.384796142578125 +40163 -0.323699951171875 +40164 -0.269287109375 +40165 -0.1951904296875 +40166 -0.100006103515625 +40167 -0.01055908203125 +40168 0.1033935546875 +40169 0.24908447265625 +40170 0.373199462890625 +40171 0.45806884765625 +40172 0.511474609375 +40173 0.565399169921875 +40174 0.61138916015625 +40175 0.5897216796875 +40176 0.4906005859375 +40177 0.33148193359375 +40178 0.147796630859375 +40179 -0.01873779296875 +40180 -0.140289306640625 +40181 -0.191986083984375 +40182 -0.184295654296875 +40183 -0.161834716796875 +40184 -0.166595458984375 +40185 -0.19390869140625 +40186 -0.22442626953125 +40187 -0.279754638671875 +40188 -0.3389892578125 +40189 -0.3543701171875 +40190 -0.348175048828125 +40191 -0.32598876953125 +40192 -0.2581787109375 +40193 -0.139801025390625 +40194 0.014617919921875 +40195 0.144378662109375 +40196 0.221038818359375 +40197 0.27069091796875 +40198 0.294036865234375 +40199 0.311767578125 +40200 0.339141845703125 +40201 0.360260009765625 +40202 0.360504150390625 +40203 0.308380126953125 +40204 0.18170166015625 +40205 0.0047607421875 +40206 -0.17559814453125 +40207 -0.3143310546875 +40208 -0.36785888671875 +40209 -0.36248779296875 +40210 -0.343536376953125 +40211 -0.3018798828125 +40212 -0.231414794921875 +40213 -0.117645263671875 +40214 0.007049560546875 +40215 0.087982177734375 +40216 0.13946533203125 +40217 0.17425537109375 +40218 0.188201904296875 +40219 0.171234130859375 +40220 0.118438720703125 +40221 0.05706787109375 +40222 -0.010711669921875 +40223 -0.0914306640625 +40224 -0.162322998046875 +40225 -0.194549560546875 +40226 -0.1492919921875 +40227 -0.02166748046875 +40228 0.124053955078125 +40229 0.211151123046875 +40230 0.240447998046875 +40231 0.242218017578125 +40232 0.2257080078125 +40233 0.194366455078125 +40234 0.115509033203125 +40235 0.0128173828125 +40236 -0.053802490234375 +40237 -0.110626220703125 +40238 -0.199493408203125 +40239 -0.29437255859375 +40240 -0.33221435546875 +40241 -0.27972412109375 +40242 -0.185333251953125 +40243 -0.128204345703125 +40244 -0.115692138671875 +40245 -0.116455078125 +40246 -0.105926513671875 +40247 -0.053955078125 +40248 0.048797607421875 +40249 0.157318115234375 +40250 0.212005615234375 +40251 0.218475341796875 +40252 0.23724365234375 +40253 0.30535888671875 +40254 0.38128662109375 +40255 0.404449462890625 +40256 0.3944091796875 +40257 0.3885498046875 +40258 0.362640380859375 +40259 0.27362060546875 +40260 0.11712646484375 +40261 -0.054901123046875 +40262 -0.19085693359375 +40263 -0.28570556640625 +40264 -0.339263916015625 +40265 -0.3775634765625 +40266 -0.445709228515625 +40267 -0.535064697265625 +40268 -0.629058837890625 +40269 -0.697601318359375 +40270 -0.70391845703125 +40271 -0.6424560546875 +40272 -0.491241455078125 +40273 -0.265716552734375 +40274 -0.023712158203125 +40275 0.201751708984375 +40276 0.375823974609375 +40277 0.485076904296875 +40278 0.56884765625 +40279 0.634765625 +40280 0.63763427734375 +40281 0.5660400390625 +40282 0.4720458984375 +40283 0.40692138671875 +40284 0.3778076171875 +40285 0.376953125 +40286 0.371978759765625 +40287 0.313140869140625 +40288 0.184417724609375 +40289 0.011199951171875 +40290 -0.171051025390625 +40291 -0.33740234375 +40292 -0.47198486328125 +40293 -0.560394287109375 +40294 -0.58056640625 +40295 -0.54754638671875 +40296 -0.508575439453125 +40297 -0.459503173828125 +40298 -0.394378662109375 +40299 -0.35260009765625 +40300 -0.31170654296875 +40301 -0.197418212890625 +40302 -0.007965087890625 +40303 0.207489013671875 +40304 0.409210205078125 +40305 0.57208251953125 +40306 0.66595458984375 +40307 0.65875244140625 +40308 0.56744384765625 +40309 0.431396484375 +40310 0.29443359375 +40311 0.182464599609375 +40312 0.06365966796875 +40313 -0.075958251953125 +40314 -0.189422607421875 +40315 -0.271942138671875 +40316 -0.342529296875 +40317 -0.364166259765625 +40318 -0.327239990234375 +40319 -0.2769775390625 +40320 -0.253692626953125 +40321 -0.24365234375 +40322 -0.1983642578125 +40323 -0.116241455078125 +40324 -0.036834716796875 +40325 0.034881591796875 +40326 0.09124755859375 +40327 0.10888671875 +40328 0.125518798828125 +40329 0.15771484375 +40330 0.17828369140625 +40331 0.17108154296875 +40332 0.129974365234375 +40333 0.082427978515625 +40334 0.027679443359375 +40335 -0.065643310546875 +40336 -0.15936279296875 +40337 -0.21307373046875 +40338 -0.234649658203125 +40339 -0.2001953125 +40340 -0.119171142578125 +40341 -0.024749755859375 +40342 0.085784912109375 +40343 0.178131103515625 +40344 0.215576171875 +40345 0.211456298828125 +40346 0.17523193359375 +40347 0.128753662109375 +40348 0.1019287109375 +40349 0.0743408203125 +40350 0.04327392578125 +40351 0.038177490234375 +40352 0.076263427734375 +40353 0.14105224609375 +40354 0.186431884765625 +40355 0.188812255859375 +40356 0.1390380859375 +40357 0.041778564453125 +40358 -0.079437255859375 +40359 -0.219390869140625 +40360 -0.367828369140625 +40361 -0.494873046875 +40362 -0.556243896484375 +40363 -0.508697509765625 +40364 -0.3756103515625 +40365 -0.218902587890625 +40366 -0.063751220703125 +40367 0.091552734375 +40368 0.23602294921875 +40369 0.342987060546875 +40370 0.39520263671875 +40371 0.389373779296875 +40372 0.324249267578125 +40373 0.224090576171875 +40374 0.124267578125 +40375 0.037078857421875 +40376 -0.010101318359375 +40377 -0.019439697265625 +40378 -0.022796630859375 +40379 -0.001556396484375 +40380 0.056304931640625 +40381 0.106719970703125 +40382 0.096893310546875 +40383 0.042694091796875 +40384 -0.018035888671875 +40385 -0.07586669921875 +40386 -0.11944580078125 +40387 -0.15972900390625 +40388 -0.202606201171875 +40389 -0.24859619140625 +40390 -0.30517578125 +40391 -0.36212158203125 +40392 -0.39141845703125 +40393 -0.35528564453125 +40394 -0.249969482421875 +40395 -0.092864990234375 +40396 0.08905029296875 +40397 0.2352294921875 +40398 0.318817138671875 +40399 0.358642578125 +40400 0.347747802734375 +40401 0.28564453125 +40402 0.223175048828125 +40403 0.196746826171875 +40404 0.179840087890625 +40405 0.155548095703125 +40406 0.151214599609375 +40407 0.156951904296875 +40408 0.13177490234375 +40409 0.100799560546875 +40410 0.087127685546875 +40411 0.05487060546875 +40412 -0.009002685546875 +40413 -0.10400390625 +40414 -0.229400634765625 +40415 -0.35552978515625 +40416 -0.441925048828125 +40417 -0.473846435546875 +40418 -0.464813232421875 +40419 -0.419097900390625 +40420 -0.334320068359375 +40421 -0.227935791015625 +40422 -0.12347412109375 +40423 -0.02764892578125 +40424 0.077667236328125 +40425 0.2132568359375 +40426 0.38885498046875 +40427 0.582794189453125 +40428 0.734039306640625 +40429 0.800140380859375 +40430 0.7783203125 +40431 0.6651611328125 +40432 0.45965576171875 +40433 0.199188232421875 +40434 -0.050689697265625 +40435 -0.23297119140625 +40436 -0.33013916015625 +40437 -0.368408203125 +40438 -0.378936767578125 +40439 -0.376983642578125 +40440 -0.37969970703125 +40441 -0.391510009765625 +40442 -0.385345458984375 +40443 -0.3419189453125 +40444 -0.28289794921875 +40445 -0.251617431640625 +40446 -0.266143798828125 +40447 -0.273345947265625 +40448 -0.216796875 +40449 -0.128265380859375 +40450 -0.068145751953125 +40451 -0.0430908203125 +40452 -0.024444580078125 +40453 0.020721435546875 +40454 0.124481201171875 +40455 0.25787353515625 +40456 0.379119873046875 +40457 0.47991943359375 +40458 0.5281982421875 +40459 0.511138916015625 +40460 0.456207275390625 +40461 0.407470703125 +40462 0.383758544921875 +40463 0.35687255859375 +40464 0.31182861328125 +40465 0.250885009765625 +40466 0.1654052734375 +40467 0.035247802734375 +40468 -0.142059326171875 +40469 -0.33563232421875 +40470 -0.5345458984375 +40471 -0.72186279296875 +40472 -0.836669921875 +40473 -0.8326416015625 +40474 -0.7296142578125 +40475 -0.582550048828125 +40476 -0.440093994140625 +40477 -0.324310302734375 +40478 -0.20147705078125 +40479 -0.044647216796875 +40480 0.103973388671875 +40481 0.202392578125 +40482 0.264495849609375 +40483 0.338897705078125 +40484 0.443817138671875 +40485 0.545074462890625 +40486 0.6173095703125 +40487 0.6524658203125 +40488 0.66339111328125 +40489 0.6561279296875 +40490 0.606781005859375 +40491 0.501190185546875 +40492 0.352783203125 +40493 0.176544189453125 +40494 -0.034820556640625 +40495 -0.258209228515625 +40496 -0.44244384765625 +40497 -0.5753173828125 +40498 -0.65203857421875 +40499 -0.641632080078125 +40500 -0.562164306640625 +40501 -0.458038330078125 +40502 -0.350555419921875 +40503 -0.260528564453125 +40504 -0.192108154296875 +40505 -0.141937255859375 +40506 -0.1021728515625 +40507 -0.062896728515625 +40508 -0.011932373046875 +40509 0.062835693359375 +40510 0.148712158203125 +40511 0.241729736328125 +40512 0.34912109375 +40513 0.457305908203125 +40514 0.54388427734375 +40515 0.5728759765625 +40516 0.506591796875 +40517 0.351226806640625 +40518 0.146514892578125 +40519 -0.05523681640625 +40520 -0.21624755859375 +40521 -0.334930419921875 +40522 -0.402984619140625 +40523 -0.4412841796875 +40524 -0.49578857421875 +40525 -0.5601806640625 +40526 -0.600738525390625 +40527 -0.584228515625 +40528 -0.47930908203125 +40529 -0.27935791015625 +40530 -0.0089111328125 +40531 0.268798828125 +40532 0.482818603515625 +40533 0.60369873046875 +40534 0.650421142578125 +40535 0.66400146484375 +40536 0.6414794921875 +40537 0.572540283203125 +40538 0.498138427734375 +40539 0.439453125 +40540 0.375518798828125 +40541 0.274505615234375 +40542 0.1087646484375 +40543 -0.099395751953125 +40544 -0.3182373046875 +40545 -0.5489501953125 +40546 -0.7738037109375 +40547 -0.86383056640625 +40548 -0.870391845703125 +40549 -0.86895751953125 +40550 -0.861053466796875 +40551 -0.765869140625 +40552 -0.5301513671875 +40553 -0.214691162109375 +40554 0.137359619140625 +40555 0.474822998046875 +40556 0.76239013671875 +40557 0.867462158203125 +40558 0.870361328125 +40559 0.86480712890625 +40560 0.831817626953125 +40561 0.677581787109375 +40562 0.495880126953125 +40563 0.30767822265625 +40564 0.116180419921875 +40565 -0.110748291015625 +40566 -0.381805419921875 +40567 -0.6572265625 +40568 -0.857421875 +40569 -0.870391845703125 +40570 -0.870391845703125 +40571 -0.86444091796875 +40572 -0.85723876953125 +40573 -0.790008544921875 +40574 -0.62847900390625 +40575 -0.3956298828125 +40576 -0.126708984375 +40577 0.150115966796875 +40578 0.424041748046875 +40579 0.670623779296875 +40580 0.854522705078125 +40581 0.866485595703125 +40582 0.86920166015625 +40583 0.8653564453125 +40584 0.857147216796875 +40585 0.766845703125 +40586 0.628509521484375 +40587 0.462127685546875 +40588 0.297210693359375 +40589 0.14862060546875 +40590 -0.00537109375 +40591 -0.15753173828125 +40592 -0.31304931640625 +40593 -0.48876953125 +40594 -0.6416015625 +40595 -0.751373291015625 +40596 -0.84619140625 +40597 -0.861297607421875 +40598 -0.863250732421875 +40599 -0.856597900390625 +40600 -0.7498779296875 +40601 -0.624542236328125 +40602 -0.47808837890625 +40603 -0.253387451171875 +40604 0.003692626953125 +40605 0.2257080078125 +40606 0.427154541015625 +40607 0.643218994140625 +40608 0.855926513671875 +40609 0.870361328125 +40610 0.870361328125 +40611 0.862762451171875 +40612 0.79669189453125 +40613 0.595794677734375 +40614 0.362152099609375 +40615 0.1270751953125 +40616 -0.086944580078125 +40617 -0.2784423828125 +40618 -0.484832763671875 +40619 -0.729583740234375 +40620 -0.86688232421875 +40621 -0.870391845703125 +40622 -0.86859130859375 +40623 -0.86279296875 +40624 -0.817962646484375 +40625 -0.6116943359375 +40626 -0.3128662109375 +40627 0.039398193359375 +40628 0.422821044921875 +40629 0.805145263671875 +40630 0.870361328125 +40631 0.870361328125 +40632 0.860015869140625 +40633 0.727935791015625 +40634 0.48114013671875 +40635 0.2059326171875 +40636 -0.06103515625 +40637 -0.29913330078125 +40638 -0.516204833984375 +40639 -0.7252197265625 +40640 -0.85980224609375 +40641 -0.870391845703125 +40642 -0.870391845703125 +40643 -0.858062744140625 +40644 -0.673004150390625 +40645 -0.42694091796875 +40646 -0.2100830078125 +40647 -0.0362548828125 +40648 0.10943603515625 +40649 0.23516845703125 +40650 0.373687744140625 +40651 0.517791748046875 +40652 0.602783203125 +40653 0.635711669921875 +40654 0.655181884765625 +40655 0.65948486328125 +40656 0.651275634765625 +40657 0.61846923828125 +40658 0.53753662109375 +40659 0.404144287109375 +40660 0.22186279296875 +40661 0.003997802734375 +40662 -0.22100830078125 +40663 -0.42449951171875 +40664 -0.579833984375 +40665 -0.641876220703125 +40666 -0.6177978515625 +40667 -0.575531005859375 +40668 -0.526336669921875 +40669 -0.42645263671875 +40670 -0.2581787109375 +40671 -0.068695068359375 +40672 0.09222412109375 +40673 0.232147216796875 +40674 0.3509521484375 +40675 0.410064697265625 +40676 0.372955322265625 +40677 0.2554931640625 +40678 0.10711669921875 +40679 -0.052886962890625 +40680 -0.186279296875 +40681 -0.23291015625 +40682 -0.209442138671875 +40683 -0.174163818359375 +40684 -0.126739501953125 +40685 -0.048126220703125 +40686 0.0426025390625 +40687 0.10748291015625 +40688 0.1409912109375 +40689 0.19708251953125 +40690 0.273651123046875 +40691 0.31768798828125 +40692 0.341094970703125 +40693 0.368011474609375 +40694 0.37249755859375 +40695 0.30072021484375 +40696 0.1517333984375 +40697 -0.01470947265625 +40698 -0.1883544921875 +40699 -0.372711181640625 +40700 -0.51397705078125 +40701 -0.57177734375 +40702 -0.53948974609375 +40703 -0.43511962890625 +40704 -0.2962646484375 +40705 -0.161102294921875 +40706 -0.0435791015625 +40707 0.060394287109375 +40708 0.13665771484375 +40709 0.170135498046875 +40710 0.16552734375 +40711 0.15728759765625 +40712 0.150787353515625 +40713 0.12200927734375 +40714 0.080108642578125 +40715 0.05126953125 +40716 0.062896728515625 +40717 0.09271240234375 +40718 0.092987060546875 +40719 0.07855224609375 +40720 0.06427001953125 +40721 0.0347900390625 +40722 -0.01171875 +40723 -0.056060791015625 +40724 -0.055511474609375 +40725 -0.010467529296875 +40726 0.02508544921875 +40727 0.025665283203125 +40728 0.017333984375 +40729 0.00189208984375 +40730 -0.03173828125 +40731 -0.071502685546875 +40732 -0.13543701171875 +40733 -0.219970703125 +40734 -0.300506591796875 +40735 -0.376312255859375 +40736 -0.416107177734375 +40737 -0.371124267578125 +40738 -0.242279052734375 +40739 -0.069732666015625 +40740 0.125640869140625 +40741 0.31268310546875 +40742 0.45501708984375 +40743 0.554779052734375 +40744 0.61065673828125 +40745 0.610931396484375 +40746 0.531463623046875 +40747 0.3883056640625 +40748 0.23468017578125 +40749 0.095245361328125 +40750 -0.00396728515625 +40751 -0.04852294921875 +40752 -0.055145263671875 +40753 -0.0758056640625 +40754 -0.138702392578125 +40755 -0.209197998046875 +40756 -0.289031982421875 +40757 -0.37884521484375 +40758 -0.456329345703125 +40759 -0.51641845703125 +40760 -0.519287109375 +40761 -0.458251953125 +40762 -0.384796142578125 +40763 -0.323699951171875 +40764 -0.269287109375 +40765 -0.1951904296875 +40766 -0.100006103515625 +40767 -0.01055908203125 +40768 0.1033935546875 +40769 0.24908447265625 +40770 0.373199462890625 +40771 0.45806884765625 +40772 0.511474609375 +40773 0.565399169921875 +40774 0.61138916015625 +40775 0.5897216796875 +40776 0.4906005859375 +40777 0.33148193359375 +40778 0.147796630859375 +40779 -0.01873779296875 +40780 -0.140289306640625 +40781 -0.191986083984375 +40782 -0.184295654296875 +40783 -0.161834716796875 +40784 -0.166595458984375 +40785 -0.19390869140625 +40786 -0.22442626953125 +40787 -0.279754638671875 +40788 -0.3389892578125 +40789 -0.3543701171875 +40790 -0.348175048828125 +40791 -0.32598876953125 +40792 -0.2581787109375 +40793 -0.139801025390625 +40794 0.014617919921875 +40795 0.144378662109375 +40796 0.221038818359375 +40797 0.27069091796875 +40798 0.294036865234375 +40799 0.311767578125 +40800 0.339141845703125 +40801 0.360260009765625 +40802 0.360504150390625 +40803 0.308380126953125 +40804 0.18170166015625 +40805 0.0047607421875 +40806 -0.17559814453125 +40807 -0.3143310546875 +40808 -0.36785888671875 +40809 -0.36248779296875 +40810 -0.343536376953125 +40811 -0.3018798828125 +40812 -0.231414794921875 +40813 -0.117645263671875 +40814 0.007049560546875 +40815 0.087982177734375 +40816 0.13946533203125 +40817 0.17425537109375 +40818 0.188201904296875 +40819 0.171234130859375 +40820 0.118438720703125 +40821 0.05706787109375 +40822 -0.010711669921875 +40823 -0.0914306640625 +40824 -0.162322998046875 +40825 -0.194549560546875 +40826 -0.1492919921875 +40827 -0.02166748046875 +40828 0.124053955078125 +40829 0.211151123046875 +40830 0.240447998046875 +40831 0.242218017578125 +40832 0.2257080078125 +40833 0.194366455078125 +40834 0.115509033203125 +40835 0.0128173828125 +40836 -0.053802490234375 +40837 -0.110626220703125 +40838 -0.199493408203125 +40839 -0.29437255859375 +40840 -0.33221435546875 +40841 -0.27972412109375 +40842 -0.185333251953125 +40843 -0.128204345703125 +40844 -0.115692138671875 +40845 -0.116455078125 +40846 -0.105926513671875 +40847 -0.053955078125 +40848 0.048797607421875 +40849 0.157318115234375 +40850 0.212005615234375 +40851 0.218475341796875 +40852 0.23724365234375 +40853 0.30535888671875 +40854 0.38128662109375 +40855 0.404449462890625 +40856 0.3944091796875 +40857 0.3885498046875 +40858 0.362640380859375 +40859 0.27362060546875 +40860 0.11712646484375 +40861 -0.054901123046875 +40862 -0.19085693359375 +40863 -0.28570556640625 +40864 -0.339263916015625 +40865 -0.3775634765625 +40866 -0.445709228515625 +40867 -0.535064697265625 +40868 -0.629058837890625 +40869 -0.697601318359375 +40870 -0.70391845703125 +40871 -0.6424560546875 +40872 -0.491241455078125 +40873 -0.265716552734375 +40874 -0.023712158203125 +40875 0.201751708984375 +40876 0.375823974609375 +40877 0.485076904296875 +40878 0.56884765625 +40879 0.634765625 +40880 0.63763427734375 +40881 0.5660400390625 +40882 0.4720458984375 +40883 0.40692138671875 +40884 0.3778076171875 +40885 0.376953125 +40886 0.371978759765625 +40887 0.313140869140625 +40888 0.184417724609375 +40889 0.011199951171875 +40890 -0.171051025390625 +40891 -0.33740234375 +40892 -0.47198486328125 +40893 -0.560394287109375 +40894 -0.58056640625 +40895 -0.54754638671875 +40896 -0.508575439453125 +40897 -0.459503173828125 +40898 -0.394378662109375 +40899 -0.35260009765625 +40900 -0.31170654296875 +40901 -0.197418212890625 +40902 -0.007965087890625 +40903 0.207489013671875 +40904 0.409210205078125 +40905 0.57208251953125 +40906 0.66595458984375 +40907 0.65875244140625 +40908 0.56744384765625 +40909 0.431396484375 +40910 0.29443359375 +40911 0.182464599609375 +40912 0.06365966796875 +40913 -0.075958251953125 +40914 -0.189422607421875 +40915 -0.271942138671875 +40916 -0.342529296875 +40917 -0.364166259765625 +40918 -0.327239990234375 +40919 -0.2769775390625 +40920 -0.253692626953125 +40921 -0.24365234375 +40922 -0.1983642578125 +40923 -0.116241455078125 +40924 -0.036834716796875 +40925 0.034881591796875 +40926 0.09124755859375 +40927 0.10888671875 +40928 0.125518798828125 +40929 0.15771484375 +40930 0.17828369140625 +40931 0.17108154296875 +40932 0.129974365234375 +40933 0.082427978515625 +40934 0.027679443359375 +40935 -0.065643310546875 +40936 -0.15936279296875 +40937 -0.21307373046875 +40938 -0.234649658203125 +40939 -0.2001953125 +40940 -0.119171142578125 +40941 -0.024749755859375 +40942 0.085784912109375 +40943 0.178131103515625 +40944 0.215576171875 +40945 0.211456298828125 +40946 0.17523193359375 +40947 0.128753662109375 +40948 0.1019287109375 +40949 0.0743408203125 +40950 0.04327392578125 +40951 0.038177490234375 +40952 0.076263427734375 +40953 0.14105224609375 +40954 0.186431884765625 +40955 0.188812255859375 +40956 0.1390380859375 +40957 0.041778564453125 +40958 -0.079437255859375 +40959 -0.219390869140625 +40960 -0.367828369140625 +40961 -0.494873046875 +40962 -0.556243896484375 +40963 -0.508697509765625 +40964 -0.3756103515625 +40965 -0.218902587890625 +40966 -0.063751220703125 +40967 0.091552734375 +40968 0.23602294921875 +40969 0.342987060546875 +40970 0.39520263671875 +40971 0.389373779296875 +40972 0.324249267578125 +40973 0.224090576171875 +40974 0.124267578125 +40975 0.037078857421875 +40976 -0.010101318359375 +40977 -0.019439697265625 +40978 -0.022796630859375 +40979 -0.001556396484375 +40980 0.056304931640625 +40981 0.106719970703125 +40982 0.096893310546875 +40983 0.042694091796875 +40984 -0.018035888671875 +40985 -0.07586669921875 +40986 -0.11944580078125 +40987 -0.15972900390625 +40988 -0.202606201171875 +40989 -0.24859619140625 +40990 -0.30517578125 +40991 -0.36212158203125 +40992 -0.39141845703125 +40993 -0.35528564453125 +40994 -0.249969482421875 +40995 -0.092864990234375 +40996 0.08905029296875 +40997 0.2352294921875 +40998 0.318817138671875 +40999 0.358642578125 +41000 0.347747802734375 +41001 0.28564453125 +41002 0.223175048828125 +41003 0.196746826171875 +41004 0.179840087890625 +41005 0.155548095703125 +41006 0.151214599609375 +41007 0.156951904296875 +41008 0.13177490234375 +41009 0.100799560546875 +41010 0.087127685546875 +41011 0.05487060546875 +41012 -0.009002685546875 +41013 -0.10400390625 +41014 -0.229400634765625 +41015 -0.35552978515625 +41016 -0.441925048828125 +41017 -0.473846435546875 +41018 -0.464813232421875 +41019 -0.419097900390625 +41020 -0.334320068359375 +41021 -0.227935791015625 +41022 -0.12347412109375 +41023 -0.02764892578125 +41024 0.077667236328125 +41025 0.2132568359375 +41026 0.38885498046875 +41027 0.582794189453125 +41028 0.734039306640625 +41029 0.800140380859375 +41030 0.7783203125 +41031 0.6651611328125 +41032 0.45965576171875 +41033 0.199188232421875 +41034 -0.050689697265625 +41035 -0.23297119140625 +41036 -0.33013916015625 +41037 -0.368408203125 +41038 -0.378936767578125 +41039 -0.376983642578125 +41040 -0.37969970703125 +41041 -0.391510009765625 +41042 -0.385345458984375 +41043 -0.3419189453125 +41044 -0.28289794921875 +41045 -0.251617431640625 +41046 -0.266143798828125 +41047 -0.273345947265625 +41048 -0.216796875 +41049 -0.128265380859375 +41050 -0.068145751953125 +41051 -0.0430908203125 +41052 -0.024444580078125 +41053 0.020721435546875 +41054 0.124481201171875 +41055 0.25787353515625 +41056 0.379119873046875 +41057 0.47991943359375 +41058 0.5281982421875 +41059 0.511138916015625 +41060 0.456207275390625 +41061 0.407470703125 +41062 0.383758544921875 +41063 0.35687255859375 +41064 0.31182861328125 +41065 0.250885009765625 +41066 0.1654052734375 +41067 0.035247802734375 +41068 -0.142059326171875 +41069 -0.33563232421875 +41070 -0.5345458984375 +41071 -0.72186279296875 +41072 -0.836669921875 +41073 -0.8326416015625 +41074 -0.7296142578125 +41075 -0.582550048828125 +41076 -0.440093994140625 +41077 -0.324310302734375 +41078 -0.20147705078125 +41079 -0.044647216796875 +41080 0.103973388671875 +41081 0.202392578125 +41082 0.264495849609375 +41083 0.338897705078125 +41084 0.443817138671875 +41085 0.545074462890625 +41086 0.6173095703125 +41087 0.6524658203125 +41088 0.66339111328125 +41089 0.6561279296875 +41090 0.606781005859375 +41091 0.501190185546875 +41092 0.352783203125 +41093 0.176544189453125 +41094 -0.034820556640625 +41095 -0.258209228515625 +41096 -0.44244384765625 +41097 -0.5753173828125 +41098 -0.65203857421875 +41099 -0.641632080078125 +41100 -0.562164306640625 +41101 -0.458038330078125 +41102 -0.350555419921875 +41103 -0.260528564453125 +41104 -0.192108154296875 +41105 -0.141937255859375 +41106 -0.1021728515625 +41107 -0.062896728515625 +41108 -0.011932373046875 +41109 0.062835693359375 +41110 0.148712158203125 +41111 0.241729736328125 +41112 0.34912109375 +41113 0.457305908203125 +41114 0.54388427734375 +41115 0.5728759765625 +41116 0.506591796875 +41117 0.351226806640625 +41118 0.146514892578125 +41119 -0.05523681640625 +41120 -0.21624755859375 +41121 -0.334930419921875 +41122 -0.402984619140625 +41123 -0.4412841796875 +41124 -0.49578857421875 +41125 -0.5601806640625 +41126 -0.600738525390625 +41127 -0.584228515625 +41128 -0.47930908203125 +41129 -0.27935791015625 +41130 -0.0089111328125 +41131 0.268798828125 +41132 0.482818603515625 +41133 0.60369873046875 +41134 0.650421142578125 +41135 0.66400146484375 +41136 0.6414794921875 +41137 0.572540283203125 +41138 0.498138427734375 +41139 0.439453125 +41140 0.375518798828125 +41141 0.274505615234375 +41142 0.1087646484375 +41143 -0.099395751953125 +41144 -0.3182373046875 +41145 -0.5489501953125 +41146 -0.7738037109375 +41147 -0.86383056640625 +41148 -0.870391845703125 +41149 -0.86895751953125 +41150 -0.861053466796875 +41151 -0.765869140625 +41152 -0.5301513671875 +41153 -0.214691162109375 +41154 0.137359619140625 +41155 0.474822998046875 +41156 0.76239013671875 +41157 0.867462158203125 +41158 0.870361328125 +41159 0.86480712890625 +41160 0.831817626953125 +41161 0.677581787109375 +41162 0.495880126953125 +41163 0.30767822265625 +41164 0.116180419921875 +41165 -0.110748291015625 +41166 -0.381805419921875 +41167 -0.6572265625 +41168 -0.857421875 +41169 -0.870391845703125 +41170 -0.870391845703125 +41171 -0.86444091796875 +41172 -0.85723876953125 +41173 -0.790008544921875 +41174 -0.62847900390625 +41175 -0.3956298828125 +41176 -0.126708984375 +41177 0.150115966796875 +41178 0.424041748046875 +41179 0.670623779296875 +41180 0.854522705078125 +41181 0.866485595703125 +41182 0.86920166015625 +41183 0.8653564453125 +41184 0.857147216796875 +41185 0.766845703125 +41186 0.628509521484375 +41187 0.462127685546875 +41188 0.297210693359375 +41189 0.14862060546875 +41190 -0.00537109375 +41191 -0.15753173828125 +41192 -0.31304931640625 +41193 -0.48876953125 +41194 -0.6416015625 +41195 -0.751373291015625 +41196 -0.84619140625 +41197 -0.861297607421875 +41198 -0.863250732421875 +41199 -0.856597900390625 +41200 -0.7498779296875 +41201 -0.624542236328125 +41202 -0.47808837890625 +41203 -0.253387451171875 +41204 0.003692626953125 +41205 0.2257080078125 +41206 0.427154541015625 +41207 0.643218994140625 +41208 0.855926513671875 +41209 0.870361328125 +41210 0.870361328125 +41211 0.862762451171875 +41212 0.79669189453125 +41213 0.595794677734375 +41214 0.362152099609375 +41215 0.1270751953125 +41216 -0.086944580078125 +41217 -0.2784423828125 +41218 -0.484832763671875 +41219 -0.729583740234375 +41220 -0.86688232421875 +41221 -0.870391845703125 +41222 -0.86859130859375 +41223 -0.86279296875 +41224 -0.817962646484375 +41225 -0.6116943359375 +41226 -0.3128662109375 +41227 0.039398193359375 +41228 0.422821044921875 +41229 0.805145263671875 +41230 0.870361328125 +41231 0.870361328125 +41232 0.860015869140625 +41233 0.727935791015625 +41234 0.48114013671875 +41235 0.2059326171875 +41236 -0.06103515625 +41237 -0.29913330078125 +41238 -0.516204833984375 +41239 -0.7252197265625 +41240 -0.85980224609375 +41241 -0.870391845703125 +41242 -0.870391845703125 +41243 -0.858062744140625 +41244 -0.673004150390625 +41245 -0.42694091796875 +41246 -0.2100830078125 +41247 -0.0362548828125 +41248 0.10943603515625 +41249 0.23516845703125 +41250 0.373687744140625 +41251 0.517791748046875 +41252 0.602783203125 +41253 0.635711669921875 +41254 0.655181884765625 +41255 0.65948486328125 +41256 0.651275634765625 +41257 0.61846923828125 +41258 0.53753662109375 +41259 0.404144287109375 +41260 0.22186279296875 +41261 0.003997802734375 +41262 -0.22100830078125 +41263 -0.42449951171875 +41264 -0.579833984375 +41265 -0.641876220703125 +41266 -0.6177978515625 +41267 -0.575531005859375 +41268 -0.526336669921875 +41269 -0.42645263671875 +41270 -0.2581787109375 +41271 -0.068695068359375 +41272 0.09222412109375 +41273 0.232147216796875 +41274 0.3509521484375 +41275 0.410064697265625 +41276 0.372955322265625 +41277 0.2554931640625 +41278 0.10711669921875 +41279 -0.052886962890625 +41280 -0.186279296875 +41281 -0.23291015625 +41282 -0.209442138671875 +41283 -0.174163818359375 +41284 -0.126739501953125 +41285 -0.048126220703125 +41286 0.0426025390625 +41287 0.10748291015625 +41288 0.1409912109375 +41289 0.19708251953125 +41290 0.273651123046875 +41291 0.31768798828125 +41292 0.341094970703125 +41293 0.368011474609375 +41294 0.37249755859375 +41295 0.30072021484375 +41296 0.1517333984375 +41297 -0.01470947265625 +41298 -0.1883544921875 +41299 -0.372711181640625 +41300 -0.51397705078125 +41301 -0.57177734375 +41302 -0.53948974609375 +41303 -0.43511962890625 +41304 -0.2962646484375 +41305 -0.161102294921875 +41306 -0.0435791015625 +41307 0.060394287109375 +41308 0.13665771484375 +41309 0.170135498046875 +41310 0.16552734375 +41311 0.15728759765625 +41312 0.150787353515625 +41313 0.12200927734375 +41314 0.080108642578125 +41315 0.05126953125 +41316 0.062896728515625 +41317 0.09271240234375 +41318 0.092987060546875 +41319 0.07855224609375 +41320 0.06427001953125 +41321 0.0347900390625 +41322 -0.01171875 +41323 -0.056060791015625 +41324 -0.055511474609375 +41325 -0.010467529296875 +41326 0.02508544921875 +41327 0.025665283203125 +41328 0.017333984375 +41329 0.00189208984375 +41330 -0.03173828125 +41331 -0.071502685546875 +41332 -0.13543701171875 +41333 -0.219970703125 +41334 -0.300506591796875 +41335 -0.376312255859375 +41336 -0.416107177734375 +41337 -0.371124267578125 +41338 -0.242279052734375 +41339 -0.069732666015625 +41340 0.125640869140625 +41341 0.31268310546875 +41342 0.45501708984375 +41343 0.554779052734375 +41344 0.61065673828125 +41345 0.610931396484375 +41346 0.531463623046875 +41347 0.3883056640625 +41348 0.23468017578125 +41349 0.095245361328125 +41350 -0.00396728515625 +41351 -0.04852294921875 +41352 -0.055145263671875 +41353 -0.0758056640625 +41354 -0.138702392578125 +41355 -0.209197998046875 +41356 -0.289031982421875 +41357 -0.37884521484375 +41358 -0.456329345703125 +41359 -0.51641845703125 +41360 -0.519287109375 +41361 -0.458251953125 +41362 -0.384796142578125 +41363 -0.323699951171875 +41364 -0.269287109375 +41365 -0.1951904296875 +41366 -0.100006103515625 +41367 -0.01055908203125 +41368 0.1033935546875 +41369 0.24908447265625 +41370 0.373199462890625 +41371 0.45806884765625 +41372 0.511474609375 +41373 0.565399169921875 +41374 0.61138916015625 +41375 0.5897216796875 +41376 0.4906005859375 +41377 0.33148193359375 +41378 0.147796630859375 +41379 -0.01873779296875 +41380 -0.140289306640625 +41381 -0.191986083984375 +41382 -0.184295654296875 +41383 -0.161834716796875 +41384 -0.166595458984375 +41385 -0.19390869140625 +41386 -0.22442626953125 +41387 -0.279754638671875 +41388 -0.3389892578125 +41389 -0.3543701171875 +41390 -0.348175048828125 +41391 -0.32598876953125 +41392 -0.2581787109375 +41393 -0.139801025390625 +41394 0.014617919921875 +41395 0.144378662109375 +41396 0.221038818359375 +41397 0.27069091796875 +41398 0.294036865234375 +41399 0.311767578125 +41400 0.339141845703125 +41401 0.360260009765625 +41402 0.360504150390625 +41403 0.308380126953125 +41404 0.18170166015625 +41405 0.0047607421875 +41406 -0.17559814453125 +41407 -0.3143310546875 +41408 -0.36785888671875 +41409 -0.36248779296875 +41410 -0.343536376953125 +41411 -0.3018798828125 +41412 -0.231414794921875 +41413 -0.117645263671875 +41414 0.007049560546875 +41415 0.087982177734375 +41416 0.13946533203125 +41417 0.17425537109375 +41418 0.188201904296875 +41419 0.171234130859375 +41420 0.118438720703125 +41421 0.05706787109375 +41422 -0.010711669921875 +41423 -0.0914306640625 +41424 -0.162322998046875 +41425 -0.194549560546875 +41426 -0.1492919921875 +41427 -0.02166748046875 +41428 0.124053955078125 +41429 0.211151123046875 +41430 0.240447998046875 +41431 0.242218017578125 +41432 0.2257080078125 +41433 0.194366455078125 +41434 0.115509033203125 +41435 0.0128173828125 +41436 -0.053802490234375 +41437 -0.110626220703125 +41438 -0.199493408203125 +41439 -0.29437255859375 +41440 -0.33221435546875 +41441 -0.27972412109375 +41442 -0.185333251953125 +41443 -0.128204345703125 +41444 -0.115692138671875 +41445 -0.116455078125 +41446 -0.105926513671875 +41447 -0.053955078125 +41448 0.048797607421875 +41449 0.157318115234375 +41450 0.212005615234375 +41451 0.218475341796875 +41452 0.23724365234375 +41453 0.30535888671875 +41454 0.38128662109375 +41455 0.404449462890625 +41456 0.3944091796875 +41457 0.3885498046875 +41458 0.362640380859375 +41459 0.27362060546875 +41460 0.11712646484375 +41461 -0.054901123046875 +41462 -0.19085693359375 +41463 -0.28570556640625 +41464 -0.339263916015625 +41465 -0.3775634765625 +41466 -0.445709228515625 +41467 -0.535064697265625 +41468 -0.629058837890625 +41469 -0.697601318359375 +41470 -0.70391845703125 +41471 -0.6424560546875 +41472 -0.491241455078125 +41473 -0.265716552734375 +41474 -0.023712158203125 +41475 0.201751708984375 +41476 0.375823974609375 +41477 0.485076904296875 +41478 0.56884765625 +41479 0.634765625 +41480 0.63763427734375 +41481 0.5660400390625 +41482 0.4720458984375 +41483 0.40692138671875 +41484 0.3778076171875 +41485 0.376953125 +41486 0.371978759765625 +41487 0.313140869140625 +41488 0.184417724609375 +41489 0.011199951171875 +41490 -0.171051025390625 +41491 -0.33740234375 +41492 -0.47198486328125 +41493 -0.560394287109375 +41494 -0.58056640625 +41495 -0.54754638671875 +41496 -0.508575439453125 +41497 -0.459503173828125 +41498 -0.394378662109375 +41499 -0.35260009765625 +41500 -0.31170654296875 +41501 -0.197418212890625 +41502 -0.007965087890625 +41503 0.207489013671875 +41504 0.409210205078125 +41505 0.57208251953125 +41506 0.66595458984375 +41507 0.65875244140625 +41508 0.56744384765625 +41509 0.431396484375 +41510 0.29443359375 +41511 0.182464599609375 +41512 0.06365966796875 +41513 -0.075958251953125 +41514 -0.189422607421875 +41515 -0.271942138671875 +41516 -0.342529296875 +41517 -0.364166259765625 +41518 -0.327239990234375 +41519 -0.2769775390625 +41520 -0.253692626953125 +41521 -0.24365234375 +41522 -0.1983642578125 +41523 -0.116241455078125 +41524 -0.036834716796875 +41525 0.034881591796875 +41526 0.09124755859375 +41527 0.10888671875 +41528 0.125518798828125 +41529 0.15771484375 +41530 0.17828369140625 +41531 0.17108154296875 +41532 0.129974365234375 +41533 0.082427978515625 +41534 0.027679443359375 +41535 -0.065643310546875 +41536 -0.15936279296875 +41537 -0.21307373046875 +41538 -0.234649658203125 +41539 -0.2001953125 +41540 -0.119171142578125 +41541 -0.024749755859375 +41542 0.085784912109375 +41543 0.178131103515625 +41544 0.215576171875 +41545 0.211456298828125 +41546 0.17523193359375 +41547 0.128753662109375 +41548 0.1019287109375 +41549 0.0743408203125 +41550 0.04327392578125 +41551 0.038177490234375 +41552 0.076263427734375 +41553 0.14105224609375 +41554 0.186431884765625 +41555 0.188812255859375 +41556 0.1390380859375 +41557 0.041778564453125 +41558 -0.079437255859375 +41559 -0.219390869140625 +41560 -0.367828369140625 +41561 -0.494873046875 +41562 -0.556243896484375 +41563 -0.508697509765625 +41564 -0.3756103515625 +41565 -0.218902587890625 +41566 -0.063751220703125 +41567 0.091552734375 +41568 0.23602294921875 +41569 0.342987060546875 +41570 0.39520263671875 +41571 0.389373779296875 +41572 0.324249267578125 +41573 0.224090576171875 +41574 0.124267578125 +41575 0.037078857421875 +41576 -0.010101318359375 +41577 -0.019439697265625 +41578 -0.022796630859375 +41579 -0.001556396484375 +41580 0.056304931640625 +41581 0.106719970703125 +41582 0.096893310546875 +41583 0.042694091796875 +41584 -0.018035888671875 +41585 -0.07586669921875 +41586 -0.11944580078125 +41587 -0.15972900390625 +41588 -0.202606201171875 +41589 -0.24859619140625 +41590 -0.30517578125 +41591 -0.36212158203125 +41592 -0.39141845703125 +41593 -0.35528564453125 +41594 -0.249969482421875 +41595 -0.092864990234375 +41596 0.08905029296875 +41597 0.2352294921875 +41598 0.318817138671875 +41599 0.358642578125 +41600 0.347747802734375 +41601 0.28564453125 +41602 0.223175048828125 +41603 0.196746826171875 +41604 0.179840087890625 +41605 0.155548095703125 +41606 0.151214599609375 +41607 0.156951904296875 +41608 0.13177490234375 +41609 0.100799560546875 +41610 0.087127685546875 +41611 0.05487060546875 +41612 -0.009002685546875 +41613 -0.10400390625 +41614 -0.229400634765625 +41615 -0.35552978515625 +41616 -0.441925048828125 +41617 -0.473846435546875 +41618 -0.464813232421875 +41619 -0.419097900390625 +41620 -0.334320068359375 +41621 -0.227935791015625 +41622 -0.12347412109375 +41623 -0.02764892578125 +41624 0.077667236328125 +41625 0.2132568359375 +41626 0.38885498046875 +41627 0.582794189453125 +41628 0.734039306640625 +41629 0.800140380859375 +41630 0.7783203125 +41631 0.6651611328125 +41632 0.45965576171875 +41633 0.199188232421875 +41634 -0.050689697265625 +41635 -0.23297119140625 +41636 -0.33013916015625 +41637 -0.368408203125 +41638 -0.378936767578125 +41639 -0.376983642578125 +41640 -0.37969970703125 +41641 -0.391510009765625 +41642 -0.385345458984375 +41643 -0.3419189453125 +41644 -0.28289794921875 +41645 -0.251617431640625 +41646 -0.266143798828125 +41647 -0.273345947265625 +41648 -0.216796875 +41649 -0.128265380859375 +41650 -0.068145751953125 +41651 -0.0430908203125 +41652 -0.024444580078125 +41653 0.020721435546875 +41654 0.124481201171875 +41655 0.25787353515625 +41656 0.379119873046875 +41657 0.47991943359375 +41658 0.5281982421875 +41659 0.511138916015625 +41660 0.456207275390625 +41661 0.407470703125 +41662 0.383758544921875 +41663 0.35687255859375 +41664 0.31182861328125 +41665 0.250885009765625 +41666 0.1654052734375 +41667 0.035247802734375 +41668 -0.142059326171875 +41669 -0.33563232421875 +41670 -0.5345458984375 +41671 -0.72186279296875 +41672 -0.836669921875 +41673 -0.8326416015625 +41674 -0.7296142578125 +41675 -0.582550048828125 +41676 -0.440093994140625 +41677 -0.324310302734375 +41678 -0.20147705078125 +41679 -0.044647216796875 +41680 0.103973388671875 +41681 0.202392578125 +41682 0.264495849609375 +41683 0.338897705078125 +41684 0.443817138671875 +41685 0.545074462890625 +41686 0.6173095703125 +41687 0.6524658203125 +41688 0.66339111328125 +41689 0.6561279296875 +41690 0.606781005859375 +41691 0.501190185546875 +41692 0.352783203125 +41693 0.176544189453125 +41694 -0.034820556640625 +41695 -0.258209228515625 +41696 -0.44244384765625 +41697 -0.5753173828125 +41698 -0.65203857421875 +41699 -0.641632080078125 +41700 -0.562164306640625 +41701 -0.458038330078125 +41702 -0.350555419921875 +41703 -0.260528564453125 +41704 -0.192108154296875 +41705 -0.141937255859375 +41706 -0.1021728515625 +41707 -0.062896728515625 +41708 -0.011932373046875 +41709 0.062835693359375 +41710 0.148712158203125 +41711 0.241729736328125 +41712 0.34912109375 +41713 0.457305908203125 +41714 0.54388427734375 +41715 0.5728759765625 +41716 0.506591796875 +41717 0.351226806640625 +41718 0.146514892578125 +41719 -0.05523681640625 +41720 -0.21624755859375 +41721 -0.334930419921875 +41722 -0.402984619140625 +41723 -0.4412841796875 +41724 -0.49578857421875 +41725 -0.5601806640625 +41726 -0.600738525390625 +41727 -0.584228515625 +41728 -0.47930908203125 +41729 -0.27935791015625 +41730 -0.0089111328125 +41731 0.268798828125 +41732 0.482818603515625 +41733 0.60369873046875 +41734 0.650421142578125 +41735 0.66400146484375 +41736 0.6414794921875 +41737 0.572540283203125 +41738 0.498138427734375 +41739 0.439453125 +41740 0.375518798828125 +41741 0.274505615234375 +41742 0.1087646484375 +41743 -0.099395751953125 +41744 -0.3182373046875 +41745 -0.5489501953125 +41746 -0.7738037109375 +41747 -0.86383056640625 +41748 -0.870391845703125 +41749 -0.86895751953125 +41750 -0.861053466796875 +41751 -0.765869140625 +41752 -0.5301513671875 +41753 -0.214691162109375 +41754 0.137359619140625 +41755 0.474822998046875 +41756 0.76239013671875 +41757 0.867462158203125 +41758 0.870361328125 +41759 0.86480712890625 +41760 0.831817626953125 +41761 0.677581787109375 +41762 0.495880126953125 +41763 0.30767822265625 +41764 0.116180419921875 +41765 -0.110748291015625 +41766 -0.381805419921875 +41767 -0.6572265625 +41768 -0.857421875 +41769 -0.870391845703125 +41770 -0.870391845703125 +41771 -0.86444091796875 +41772 -0.85723876953125 +41773 -0.790008544921875 +41774 -0.62847900390625 +41775 -0.3956298828125 +41776 -0.126708984375 +41777 0.150115966796875 +41778 0.424041748046875 +41779 0.670623779296875 +41780 0.854522705078125 +41781 0.866485595703125 +41782 0.86920166015625 +41783 0.8653564453125 +41784 0.857147216796875 +41785 0.766845703125 +41786 0.628509521484375 +41787 0.462127685546875 +41788 0.297210693359375 +41789 0.14862060546875 +41790 -0.00537109375 +41791 -0.15753173828125 +41792 -0.31304931640625 +41793 -0.48876953125 +41794 -0.6416015625 +41795 -0.751373291015625 +41796 -0.84619140625 +41797 -0.861297607421875 +41798 -0.863250732421875 +41799 -0.856597900390625 +41800 -0.7498779296875 +41801 -0.624542236328125 +41802 -0.47808837890625 +41803 -0.253387451171875 +41804 0.003692626953125 +41805 0.2257080078125 +41806 0.427154541015625 +41807 0.643218994140625 +41808 0.855926513671875 +41809 0.870361328125 +41810 0.870361328125 +41811 0.862762451171875 +41812 0.79669189453125 +41813 0.595794677734375 +41814 0.362152099609375 +41815 0.1270751953125 +41816 -0.086944580078125 +41817 -0.2784423828125 +41818 -0.484832763671875 +41819 -0.729583740234375 +41820 -0.86688232421875 +41821 -0.870391845703125 +41822 -0.86859130859375 +41823 -0.86279296875 +41824 -0.817962646484375 +41825 -0.6116943359375 +41826 -0.3128662109375 +41827 0.039398193359375 +41828 0.422821044921875 +41829 0.805145263671875 +41830 0.870361328125 +41831 0.870361328125 +41832 0.860015869140625 +41833 0.727935791015625 +41834 0.48114013671875 +41835 0.2059326171875 +41836 -0.06103515625 +41837 -0.29913330078125 +41838 -0.516204833984375 +41839 -0.7252197265625 +41840 -0.85980224609375 +41841 -0.870391845703125 +41842 -0.870391845703125 +41843 -0.858062744140625 +41844 -0.673004150390625 +41845 -0.42694091796875 +41846 -0.2100830078125 +41847 -0.0362548828125 +41848 0.10943603515625 +41849 0.23516845703125 +41850 0.373687744140625 +41851 0.517791748046875 +41852 0.602783203125 +41853 0.635711669921875 +41854 0.655181884765625 +41855 0.65948486328125 +41856 0.651275634765625 +41857 0.61846923828125 +41858 0.53753662109375 +41859 0.404144287109375 +41860 0.22186279296875 +41861 0.003997802734375 +41862 -0.22100830078125 +41863 -0.42449951171875 +41864 -0.579833984375 +41865 -0.641876220703125 +41866 -0.6177978515625 +41867 -0.575531005859375 +41868 -0.526336669921875 +41869 -0.42645263671875 +41870 -0.2581787109375 +41871 -0.068695068359375 +41872 0.09222412109375 +41873 0.232147216796875 +41874 0.3509521484375 +41875 0.410064697265625 +41876 0.372955322265625 +41877 0.2554931640625 +41878 0.10711669921875 +41879 -0.052886962890625 +41880 -0.186279296875 +41881 -0.23291015625 +41882 -0.209442138671875 +41883 -0.174163818359375 +41884 -0.126739501953125 +41885 -0.048126220703125 +41886 0.0426025390625 +41887 0.10748291015625 +41888 0.1409912109375 +41889 0.19708251953125 +41890 0.273651123046875 +41891 0.31768798828125 +41892 0.341094970703125 +41893 0.368011474609375 +41894 0.37249755859375 +41895 0.30072021484375 +41896 0.1517333984375 +41897 -0.01470947265625 +41898 -0.1883544921875 +41899 -0.372711181640625 +41900 -0.51397705078125 +41901 -0.57177734375 +41902 -0.53948974609375 +41903 -0.43511962890625 +41904 -0.2962646484375 +41905 -0.161102294921875 +41906 -0.0435791015625 +41907 0.060394287109375 +41908 0.13665771484375 +41909 0.170135498046875 +41910 0.16552734375 +41911 0.15728759765625 +41912 0.150787353515625 +41913 0.12200927734375 +41914 0.080108642578125 +41915 0.05126953125 +41916 0.062896728515625 +41917 0.09271240234375 +41918 0.092987060546875 +41919 0.07855224609375 +41920 0.06427001953125 +41921 0.0347900390625 +41922 -0.01171875 +41923 -0.056060791015625 +41924 -0.055511474609375 +41925 -0.010467529296875 +41926 0.02508544921875 +41927 0.025665283203125 +41928 0.017333984375 +41929 0.00189208984375 +41930 -0.03173828125 +41931 -0.071502685546875 +41932 -0.13543701171875 +41933 -0.219970703125 +41934 -0.300506591796875 +41935 -0.376312255859375 +41936 -0.416107177734375 +41937 -0.371124267578125 +41938 -0.242279052734375 +41939 -0.069732666015625 +41940 0.125640869140625 +41941 0.31268310546875 +41942 0.45501708984375 +41943 0.554779052734375 +41944 0.61065673828125 +41945 0.610931396484375 +41946 0.531463623046875 +41947 0.3883056640625 +41948 0.23468017578125 +41949 0.095245361328125 +41950 -0.00396728515625 +41951 -0.04852294921875 +41952 -0.055145263671875 +41953 -0.0758056640625 +41954 -0.138702392578125 +41955 -0.209197998046875 +41956 -0.289031982421875 +41957 -0.37884521484375 +41958 -0.456329345703125 +41959 -0.51641845703125 +41960 -0.519287109375 +41961 -0.458251953125 +41962 -0.384796142578125 +41963 -0.323699951171875 +41964 -0.269287109375 +41965 -0.1951904296875 +41966 -0.100006103515625 +41967 -0.01055908203125 +41968 0.1033935546875 +41969 0.24908447265625 +41970 0.373199462890625 +41971 0.45806884765625 +41972 0.511474609375 +41973 0.565399169921875 +41974 0.61138916015625 +41975 0.5897216796875 +41976 0.4906005859375 +41977 0.33148193359375 +41978 0.147796630859375 +41979 -0.01873779296875 +41980 -0.140289306640625 +41981 -0.191986083984375 +41982 -0.184295654296875 +41983 -0.161834716796875 +41984 -0.166595458984375 +41985 -0.19390869140625 +41986 -0.22442626953125 +41987 -0.279754638671875 +41988 -0.3389892578125 +41989 -0.3543701171875 +41990 -0.348175048828125 +41991 -0.32598876953125 +41992 -0.2581787109375 +41993 -0.139801025390625 +41994 0.014617919921875 +41995 0.144378662109375 +41996 0.221038818359375 +41997 0.27069091796875 +41998 0.294036865234375 +41999 0.311767578125 +42000 0.339141845703125 +42001 0.360260009765625 +42002 0.360504150390625 +42003 0.308380126953125 +42004 0.18170166015625 +42005 0.0047607421875 +42006 -0.17559814453125 +42007 -0.3143310546875 +42008 -0.36785888671875 +42009 -0.36248779296875 +42010 -0.343536376953125 +42011 -0.3018798828125 +42012 -0.231414794921875 +42013 -0.117645263671875 +42014 0.007049560546875 +42015 0.087982177734375 +42016 0.13946533203125 +42017 0.17425537109375 +42018 0.188201904296875 +42019 0.171234130859375 +42020 0.118438720703125 +42021 0.05706787109375 +42022 -0.010711669921875 +42023 -0.0914306640625 +42024 -0.162322998046875 +42025 -0.194549560546875 +42026 -0.1492919921875 +42027 -0.02166748046875 +42028 0.124053955078125 +42029 0.211151123046875 +42030 0.240447998046875 +42031 0.242218017578125 +42032 0.2257080078125 +42033 0.194366455078125 +42034 0.115509033203125 +42035 0.0128173828125 +42036 -0.053802490234375 +42037 -0.110626220703125 +42038 -0.199493408203125 +42039 -0.29437255859375 +42040 -0.33221435546875 +42041 -0.27972412109375 +42042 -0.185333251953125 +42043 -0.128204345703125 +42044 -0.115692138671875 +42045 -0.116455078125 +42046 -0.105926513671875 +42047 -0.053955078125 +42048 0.048797607421875 +42049 0.157318115234375 +42050 0.212005615234375 +42051 0.218475341796875 +42052 0.23724365234375 +42053 0.30535888671875 +42054 0.38128662109375 +42055 0.404449462890625 +42056 0.3944091796875 +42057 0.3885498046875 +42058 0.362640380859375 +42059 0.27362060546875 +42060 0.11712646484375 +42061 -0.054901123046875 +42062 -0.19085693359375 +42063 -0.28570556640625 +42064 -0.339263916015625 +42065 -0.3775634765625 +42066 -0.445709228515625 +42067 -0.535064697265625 +42068 -0.629058837890625 +42069 -0.697601318359375 +42070 -0.70391845703125 +42071 -0.6424560546875 +42072 -0.491241455078125 +42073 -0.265716552734375 +42074 -0.023712158203125 +42075 0.201751708984375 +42076 0.375823974609375 +42077 0.485076904296875 +42078 0.56884765625 +42079 0.634765625 +42080 0.63763427734375 +42081 0.5660400390625 +42082 0.4720458984375 +42083 0.40692138671875 +42084 0.3778076171875 +42085 0.376953125 +42086 0.371978759765625 +42087 0.313140869140625 +42088 0.184417724609375 +42089 0.011199951171875 +42090 -0.171051025390625 +42091 -0.33740234375 +42092 -0.47198486328125 +42093 -0.560394287109375 +42094 -0.58056640625 +42095 -0.54754638671875 +42096 -0.508575439453125 +42097 -0.459503173828125 +42098 -0.394378662109375 +42099 -0.35260009765625 +42100 -0.31170654296875 +42101 -0.197418212890625 +42102 -0.007965087890625 +42103 0.207489013671875 +42104 0.409210205078125 +42105 0.57208251953125 +42106 0.66595458984375 +42107 0.65875244140625 +42108 0.56744384765625 +42109 0.431396484375 +42110 0.29443359375 +42111 0.182464599609375 +42112 0.06365966796875 +42113 -0.075958251953125 +42114 -0.189422607421875 +42115 -0.271942138671875 +42116 -0.342529296875 +42117 -0.364166259765625 +42118 -0.327239990234375 +42119 -0.2769775390625 +42120 -0.253692626953125 +42121 -0.24365234375 +42122 -0.1983642578125 +42123 -0.116241455078125 +42124 -0.036834716796875 +42125 0.034881591796875 +42126 0.09124755859375 +42127 0.10888671875 +42128 0.125518798828125 +42129 0.15771484375 +42130 0.17828369140625 +42131 0.17108154296875 +42132 0.129974365234375 +42133 0.082427978515625 +42134 0.027679443359375 +42135 -0.065643310546875 +42136 -0.15936279296875 +42137 -0.21307373046875 +42138 -0.234649658203125 +42139 -0.2001953125 +42140 -0.119171142578125 +42141 -0.024749755859375 +42142 0.085784912109375 +42143 0.178131103515625 +42144 0.215576171875 +42145 0.211456298828125 +42146 0.17523193359375 +42147 0.128753662109375 +42148 0.1019287109375 +42149 0.0743408203125 +42150 0.04327392578125 +42151 0.038177490234375 +42152 0.076263427734375 +42153 0.14105224609375 +42154 0.186431884765625 +42155 0.188812255859375 +42156 0.1390380859375 +42157 0.041778564453125 +42158 -0.079437255859375 +42159 -0.219390869140625 +42160 -0.367828369140625 +42161 -0.494873046875 +42162 -0.556243896484375 +42163 -0.508697509765625 +42164 -0.3756103515625 +42165 -0.218902587890625 +42166 -0.063751220703125 +42167 0.091552734375 +42168 0.23602294921875 +42169 0.342987060546875 +42170 0.39520263671875 +42171 0.389373779296875 +42172 0.324249267578125 +42173 0.224090576171875 +42174 0.124267578125 +42175 0.037078857421875 +42176 -0.010101318359375 +42177 -0.019439697265625 +42178 -0.022796630859375 +42179 -0.001556396484375 +42180 0.056304931640625 +42181 0.106719970703125 +42182 0.096893310546875 +42183 0.042694091796875 +42184 -0.018035888671875 +42185 -0.07586669921875 +42186 -0.11944580078125 +42187 -0.15972900390625 +42188 -0.202606201171875 +42189 -0.24859619140625 +42190 -0.30517578125 +42191 -0.36212158203125 +42192 -0.39141845703125 +42193 -0.35528564453125 +42194 -0.249969482421875 +42195 -0.092864990234375 +42196 0.08905029296875 +42197 0.2352294921875 +42198 0.318817138671875 +42199 0.358642578125 +42200 0.347747802734375 +42201 0.28564453125 +42202 0.223175048828125 +42203 0.196746826171875 +42204 0.179840087890625 +42205 0.155548095703125 +42206 0.151214599609375 +42207 0.156951904296875 +42208 0.13177490234375 +42209 0.100799560546875 +42210 0.087127685546875 +42211 0.05487060546875 +42212 -0.009002685546875 +42213 -0.10400390625 +42214 -0.229400634765625 +42215 -0.35552978515625 +42216 -0.441925048828125 +42217 -0.473846435546875 +42218 -0.464813232421875 +42219 -0.419097900390625 +42220 -0.334320068359375 +42221 -0.227935791015625 +42222 -0.12347412109375 +42223 -0.02764892578125 +42224 0.077667236328125 +42225 0.2132568359375 +42226 0.38885498046875 +42227 0.582794189453125 +42228 0.734039306640625 +42229 0.800140380859375 +42230 0.7783203125 +42231 0.6651611328125 +42232 0.45965576171875 +42233 0.199188232421875 +42234 -0.050689697265625 +42235 -0.23297119140625 +42236 -0.33013916015625 +42237 -0.368408203125 +42238 -0.378936767578125 +42239 -0.376983642578125 +42240 -0.37969970703125 +42241 -0.391510009765625 +42242 -0.385345458984375 +42243 -0.3419189453125 +42244 -0.28289794921875 +42245 -0.251617431640625 +42246 -0.266143798828125 +42247 -0.273345947265625 +42248 -0.216796875 +42249 -0.128265380859375 +42250 -0.068145751953125 +42251 -0.0430908203125 +42252 -0.024444580078125 +42253 0.020721435546875 +42254 0.124481201171875 +42255 0.25787353515625 +42256 0.379119873046875 +42257 0.47991943359375 +42258 0.5281982421875 +42259 0.511138916015625 +42260 0.456207275390625 +42261 0.407470703125 +42262 0.383758544921875 +42263 0.35687255859375 +42264 0.31182861328125 +42265 0.250885009765625 +42266 0.1654052734375 +42267 0.035247802734375 +42268 -0.142059326171875 +42269 -0.33563232421875 +42270 -0.5345458984375 +42271 -0.72186279296875 +42272 -0.836669921875 +42273 -0.8326416015625 +42274 -0.7296142578125 +42275 -0.582550048828125 +42276 -0.440093994140625 +42277 -0.324310302734375 +42278 -0.20147705078125 +42279 -0.044647216796875 +42280 0.103973388671875 +42281 0.202392578125 +42282 0.264495849609375 +42283 0.338897705078125 +42284 0.443817138671875 +42285 0.545074462890625 +42286 0.6173095703125 +42287 0.6524658203125 +42288 0.66339111328125 +42289 0.6561279296875 +42290 0.606781005859375 +42291 0.501190185546875 +42292 0.352783203125 +42293 0.176544189453125 +42294 -0.034820556640625 +42295 -0.258209228515625 +42296 -0.44244384765625 +42297 -0.5753173828125 +42298 -0.65203857421875 +42299 -0.641632080078125 +42300 -0.562164306640625 +42301 -0.458038330078125 +42302 -0.350555419921875 +42303 -0.260528564453125 +42304 -0.192108154296875 +42305 -0.141937255859375 +42306 -0.1021728515625 +42307 -0.062896728515625 +42308 -0.011932373046875 +42309 0.062835693359375 +42310 0.148712158203125 +42311 0.241729736328125 +42312 0.34912109375 +42313 0.457305908203125 +42314 0.54388427734375 +42315 0.5728759765625 +42316 0.506591796875 +42317 0.351226806640625 +42318 0.146514892578125 +42319 -0.05523681640625 +42320 -0.21624755859375 +42321 -0.334930419921875 +42322 -0.402984619140625 +42323 -0.4412841796875 +42324 -0.49578857421875 +42325 -0.5601806640625 +42326 -0.600738525390625 +42327 -0.584228515625 +42328 -0.47930908203125 +42329 -0.27935791015625 +42330 -0.0089111328125 +42331 0.268798828125 +42332 0.482818603515625 +42333 0.60369873046875 +42334 0.650421142578125 +42335 0.66400146484375 +42336 0.6414794921875 +42337 0.572540283203125 +42338 0.498138427734375 +42339 0.439453125 +42340 0.375518798828125 +42341 0.274505615234375 +42342 0.1087646484375 +42343 -0.099395751953125 +42344 -0.3182373046875 +42345 -0.5489501953125 +42346 -0.7738037109375 +42347 -0.86383056640625 +42348 -0.870391845703125 +42349 -0.86895751953125 +42350 -0.861053466796875 +42351 -0.765869140625 +42352 -0.5301513671875 +42353 -0.214691162109375 +42354 0.137359619140625 +42355 0.474822998046875 +42356 0.76239013671875 +42357 0.867462158203125 +42358 0.870361328125 +42359 0.86480712890625 +42360 0.831817626953125 +42361 0.677581787109375 +42362 0.495880126953125 +42363 0.30767822265625 +42364 0.116180419921875 +42365 -0.110748291015625 +42366 -0.381805419921875 +42367 -0.6572265625 +42368 -0.857421875 +42369 -0.870391845703125 +42370 -0.870391845703125 +42371 -0.86444091796875 +42372 -0.85723876953125 +42373 -0.790008544921875 +42374 -0.62847900390625 +42375 -0.3956298828125 +42376 -0.126708984375 +42377 0.150115966796875 +42378 0.424041748046875 +42379 0.670623779296875 +42380 0.854522705078125 +42381 0.866485595703125 +42382 0.86920166015625 +42383 0.8653564453125 +42384 0.857147216796875 +42385 0.766845703125 +42386 0.628509521484375 +42387 0.462127685546875 +42388 0.297210693359375 +42389 0.14862060546875 +42390 -0.00537109375 +42391 -0.15753173828125 +42392 -0.31304931640625 +42393 -0.48876953125 +42394 -0.6416015625 +42395 -0.751373291015625 +42396 -0.84619140625 +42397 -0.861297607421875 +42398 -0.863250732421875 +42399 -0.856597900390625 +42400 -0.7498779296875 +42401 -0.624542236328125 +42402 -0.47808837890625 +42403 -0.253387451171875 +42404 0.003692626953125 +42405 0.2257080078125 +42406 0.427154541015625 +42407 0.643218994140625 +42408 0.855926513671875 +42409 0.870361328125 +42410 0.870361328125 +42411 0.862762451171875 +42412 0.79669189453125 +42413 0.595794677734375 +42414 0.362152099609375 +42415 0.1270751953125 +42416 -0.086944580078125 +42417 -0.2784423828125 +42418 -0.484832763671875 +42419 -0.729583740234375 +42420 -0.86688232421875 +42421 -0.870391845703125 +42422 -0.86859130859375 +42423 -0.86279296875 +42424 -0.817962646484375 +42425 -0.6116943359375 +42426 -0.3128662109375 +42427 0.039398193359375 +42428 0.422821044921875 +42429 0.805145263671875 +42430 0.870361328125 +42431 0.870361328125 +42432 0.860015869140625 +42433 0.727935791015625 +42434 0.48114013671875 +42435 0.2059326171875 +42436 -0.06103515625 +42437 -0.29913330078125 +42438 -0.516204833984375 +42439 -0.7252197265625 +42440 -0.85980224609375 +42441 -0.870391845703125 +42442 -0.870391845703125 +42443 -0.858062744140625 +42444 -0.673004150390625 +42445 -0.42694091796875 +42446 -0.2100830078125 +42447 -0.0362548828125 +42448 0.10943603515625 +42449 0.23516845703125 +42450 0.373687744140625 +42451 0.517791748046875 +42452 0.602783203125 +42453 0.635711669921875 +42454 0.655181884765625 +42455 0.65948486328125 +42456 0.651275634765625 +42457 0.61846923828125 +42458 0.53753662109375 +42459 0.404144287109375 +42460 0.22186279296875 +42461 0.003997802734375 +42462 -0.22100830078125 +42463 -0.42449951171875 +42464 -0.579833984375 +42465 -0.641876220703125 +42466 -0.6177978515625 +42467 -0.575531005859375 +42468 -0.526336669921875 +42469 -0.42645263671875 +42470 -0.2581787109375 +42471 -0.068695068359375 +42472 0.09222412109375 +42473 0.232147216796875 +42474 0.3509521484375 +42475 0.410064697265625 +42476 0.372955322265625 +42477 0.2554931640625 +42478 0.10711669921875 +42479 -0.052886962890625 +42480 -0.186279296875 +42481 -0.23291015625 +42482 -0.209442138671875 +42483 -0.174163818359375 +42484 -0.126739501953125 +42485 -0.048126220703125 +42486 0.0426025390625 +42487 0.10748291015625 +42488 0.1409912109375 +42489 0.19708251953125 +42490 0.273651123046875 +42491 0.31768798828125 +42492 0.341094970703125 +42493 0.368011474609375 +42494 0.37249755859375 +42495 0.30072021484375 +42496 0.1517333984375 +42497 -0.01470947265625 +42498 -0.1883544921875 +42499 -0.372711181640625 +42500 -0.51397705078125 +42501 -0.57177734375 +42502 -0.53948974609375 +42503 -0.43511962890625 +42504 -0.2962646484375 +42505 -0.161102294921875 +42506 -0.0435791015625 +42507 0.060394287109375 +42508 0.13665771484375 +42509 0.170135498046875 +42510 0.16552734375 +42511 0.15728759765625 +42512 0.150787353515625 +42513 0.12200927734375 +42514 0.080108642578125 +42515 0.05126953125 +42516 0.062896728515625 +42517 0.09271240234375 +42518 0.092987060546875 +42519 0.07855224609375 +42520 0.06427001953125 +42521 0.0347900390625 +42522 -0.01171875 +42523 -0.056060791015625 +42524 -0.055511474609375 +42525 -0.010467529296875 +42526 0.02508544921875 +42527 0.025665283203125 +42528 0.017333984375 +42529 0.00189208984375 +42530 -0.03173828125 +42531 -0.071502685546875 +42532 -0.13543701171875 +42533 -0.219970703125 +42534 -0.300506591796875 +42535 -0.376312255859375 +42536 -0.416107177734375 +42537 -0.371124267578125 +42538 -0.242279052734375 +42539 -0.069732666015625 +42540 0.125640869140625 +42541 0.31268310546875 +42542 0.45501708984375 +42543 0.554779052734375 +42544 0.61065673828125 +42545 0.610931396484375 +42546 0.531463623046875 +42547 0.3883056640625 +42548 0.23468017578125 +42549 0.095245361328125 +42550 -0.00396728515625 +42551 -0.04852294921875 +42552 -0.055145263671875 +42553 -0.0758056640625 +42554 -0.138702392578125 +42555 -0.209197998046875 +42556 -0.289031982421875 +42557 -0.37884521484375 +42558 -0.456329345703125 +42559 -0.51641845703125 +42560 -0.519287109375 +42561 -0.458251953125 +42562 -0.384796142578125 +42563 -0.323699951171875 +42564 -0.269287109375 +42565 -0.1951904296875 +42566 -0.100006103515625 +42567 -0.01055908203125 +42568 0.1033935546875 +42569 0.24908447265625 +42570 0.373199462890625 +42571 0.45806884765625 +42572 0.511474609375 +42573 0.565399169921875 +42574 0.61138916015625 +42575 0.5897216796875 +42576 0.4906005859375 +42577 0.33148193359375 +42578 0.147796630859375 +42579 -0.01873779296875 +42580 -0.140289306640625 +42581 -0.191986083984375 +42582 -0.184295654296875 +42583 -0.161834716796875 +42584 -0.166595458984375 +42585 -0.19390869140625 +42586 -0.22442626953125 +42587 -0.279754638671875 +42588 -0.3389892578125 +42589 -0.3543701171875 +42590 -0.348175048828125 +42591 -0.32598876953125 +42592 -0.2581787109375 +42593 -0.139801025390625 +42594 0.014617919921875 +42595 0.144378662109375 +42596 0.221038818359375 +42597 0.27069091796875 +42598 0.294036865234375 +42599 0.311767578125 +42600 0.339141845703125 +42601 0.360260009765625 +42602 0.360504150390625 +42603 0.308380126953125 +42604 0.18170166015625 +42605 0.0047607421875 +42606 -0.17559814453125 +42607 -0.3143310546875 +42608 -0.36785888671875 +42609 -0.36248779296875 +42610 -0.343536376953125 +42611 -0.3018798828125 +42612 -0.231414794921875 +42613 -0.117645263671875 +42614 0.007049560546875 +42615 0.087982177734375 +42616 0.13946533203125 +42617 0.17425537109375 +42618 0.188201904296875 +42619 0.171234130859375 +42620 0.118438720703125 +42621 0.05706787109375 +42622 -0.010711669921875 +42623 -0.0914306640625 +42624 -0.162322998046875 +42625 -0.194549560546875 +42626 -0.1492919921875 +42627 -0.02166748046875 +42628 0.124053955078125 +42629 0.211151123046875 +42630 0.240447998046875 +42631 0.242218017578125 +42632 0.2257080078125 +42633 0.194366455078125 +42634 0.115509033203125 +42635 0.0128173828125 +42636 -0.053802490234375 +42637 -0.110626220703125 +42638 -0.199493408203125 +42639 -0.29437255859375 +42640 -0.33221435546875 +42641 -0.27972412109375 +42642 -0.185333251953125 +42643 -0.128204345703125 +42644 -0.115692138671875 +42645 -0.116455078125 +42646 -0.105926513671875 +42647 -0.053955078125 +42648 0.048797607421875 +42649 0.157318115234375 +42650 0.212005615234375 +42651 0.218475341796875 +42652 0.23724365234375 +42653 0.30535888671875 +42654 0.38128662109375 +42655 0.404449462890625 +42656 0.3944091796875 +42657 0.3885498046875 +42658 0.362640380859375 +42659 0.27362060546875 +42660 0.11712646484375 +42661 -0.054901123046875 +42662 -0.19085693359375 +42663 -0.28570556640625 +42664 -0.339263916015625 +42665 -0.3775634765625 +42666 -0.445709228515625 +42667 -0.535064697265625 +42668 -0.629058837890625 +42669 -0.697601318359375 +42670 -0.70391845703125 +42671 -0.6424560546875 +42672 -0.491241455078125 +42673 -0.265716552734375 +42674 -0.023712158203125 +42675 0.201751708984375 +42676 0.375823974609375 +42677 0.485076904296875 +42678 0.56884765625 +42679 0.634765625 +42680 0.63763427734375 +42681 0.5660400390625 +42682 0.4720458984375 +42683 0.40692138671875 +42684 0.3778076171875 +42685 0.376953125 +42686 0.371978759765625 +42687 0.313140869140625 +42688 0.184417724609375 +42689 0.011199951171875 +42690 -0.171051025390625 +42691 -0.33740234375 +42692 -0.47198486328125 +42693 -0.560394287109375 +42694 -0.58056640625 +42695 -0.54754638671875 +42696 -0.508575439453125 +42697 -0.459503173828125 +42698 -0.394378662109375 +42699 -0.35260009765625 +42700 -0.31170654296875 +42701 -0.197418212890625 +42702 -0.007965087890625 +42703 0.207489013671875 +42704 0.409210205078125 +42705 0.57208251953125 +42706 0.66595458984375 +42707 0.65875244140625 +42708 0.56744384765625 +42709 0.431396484375 +42710 0.29443359375 +42711 0.182464599609375 +42712 0.06365966796875 +42713 -0.075958251953125 +42714 -0.189422607421875 +42715 -0.271942138671875 +42716 -0.342529296875 +42717 -0.364166259765625 +42718 -0.327239990234375 +42719 -0.2769775390625 +42720 -0.253692626953125 +42721 -0.24365234375 +42722 -0.1983642578125 +42723 -0.116241455078125 +42724 -0.036834716796875 +42725 0.034881591796875 +42726 0.09124755859375 +42727 0.10888671875 +42728 0.125518798828125 +42729 0.15771484375 +42730 0.17828369140625 +42731 0.17108154296875 +42732 0.129974365234375 +42733 0.082427978515625 +42734 0.027679443359375 +42735 -0.065643310546875 +42736 -0.15936279296875 +42737 -0.21307373046875 +42738 -0.234649658203125 +42739 -0.2001953125 +42740 -0.119171142578125 +42741 -0.024749755859375 +42742 0.085784912109375 +42743 0.178131103515625 +42744 0.215576171875 +42745 0.211456298828125 +42746 0.17523193359375 +42747 0.128753662109375 +42748 0.1019287109375 +42749 0.0743408203125 +42750 0.04327392578125 +42751 0.038177490234375 +42752 0.076263427734375 +42753 0.14105224609375 +42754 0.186431884765625 +42755 0.188812255859375 +42756 0.1390380859375 +42757 0.041778564453125 +42758 -0.079437255859375 +42759 -0.219390869140625 +42760 -0.367828369140625 +42761 -0.494873046875 +42762 -0.556243896484375 +42763 -0.508697509765625 +42764 -0.3756103515625 +42765 -0.218902587890625 +42766 -0.063751220703125 +42767 0.091552734375 +42768 0.23602294921875 +42769 0.342987060546875 +42770 0.39520263671875 +42771 0.389373779296875 +42772 0.324249267578125 +42773 0.224090576171875 +42774 0.124267578125 +42775 0.037078857421875 +42776 -0.010101318359375 +42777 -0.019439697265625 +42778 -0.022796630859375 +42779 -0.001556396484375 +42780 0.056304931640625 +42781 0.106719970703125 +42782 0.096893310546875 +42783 0.042694091796875 +42784 -0.018035888671875 +42785 -0.07586669921875 +42786 -0.11944580078125 +42787 -0.15972900390625 +42788 -0.202606201171875 +42789 -0.24859619140625 +42790 -0.30517578125 +42791 -0.36212158203125 +42792 -0.39141845703125 +42793 -0.35528564453125 +42794 -0.249969482421875 +42795 -0.092864990234375 +42796 0.08905029296875 +42797 0.2352294921875 +42798 0.318817138671875 +42799 0.358642578125 +42800 0.347747802734375 +42801 0.28564453125 +42802 0.223175048828125 +42803 0.196746826171875 +42804 0.179840087890625 +42805 0.155548095703125 +42806 0.151214599609375 +42807 0.156951904296875 +42808 0.13177490234375 +42809 0.100799560546875 +42810 0.087127685546875 +42811 0.05487060546875 +42812 -0.009002685546875 +42813 -0.10400390625 +42814 -0.229400634765625 +42815 -0.35552978515625 +42816 -0.441925048828125 +42817 -0.473846435546875 +42818 -0.464813232421875 +42819 -0.419097900390625 +42820 -0.334320068359375 +42821 -0.227935791015625 +42822 -0.12347412109375 +42823 -0.02764892578125 +42824 0.077667236328125 +42825 0.2132568359375 +42826 0.38885498046875 +42827 0.582794189453125 +42828 0.734039306640625 +42829 0.800140380859375 +42830 0.7783203125 +42831 0.6651611328125 +42832 0.45965576171875 +42833 0.199188232421875 +42834 -0.050689697265625 +42835 -0.23297119140625 +42836 -0.33013916015625 +42837 -0.368408203125 +42838 -0.378936767578125 +42839 -0.376983642578125 +42840 -0.37969970703125 +42841 -0.391510009765625 +42842 -0.385345458984375 +42843 -0.3419189453125 +42844 -0.28289794921875 +42845 -0.251617431640625 +42846 -0.266143798828125 +42847 -0.273345947265625 +42848 -0.216796875 +42849 -0.128265380859375 +42850 -0.068145751953125 +42851 -0.0430908203125 +42852 -0.024444580078125 +42853 0.020721435546875 +42854 0.124481201171875 +42855 0.25787353515625 +42856 0.379119873046875 +42857 0.47991943359375 +42858 0.5281982421875 +42859 0.511138916015625 +42860 0.456207275390625 +42861 0.407470703125 +42862 0.383758544921875 +42863 0.35687255859375 +42864 0.31182861328125 +42865 0.250885009765625 +42866 0.1654052734375 +42867 0.035247802734375 +42868 -0.142059326171875 +42869 -0.33563232421875 +42870 -0.5345458984375 +42871 -0.72186279296875 +42872 -0.836669921875 +42873 -0.8326416015625 +42874 -0.7296142578125 +42875 -0.582550048828125 +42876 -0.440093994140625 +42877 -0.324310302734375 +42878 -0.20147705078125 +42879 -0.044647216796875 +42880 0.103973388671875 +42881 0.202392578125 +42882 0.264495849609375 +42883 0.338897705078125 +42884 0.443817138671875 +42885 0.545074462890625 +42886 0.6173095703125 +42887 0.6524658203125 +42888 0.66339111328125 +42889 0.6561279296875 +42890 0.606781005859375 +42891 0.501190185546875 +42892 0.352783203125 +42893 0.176544189453125 +42894 -0.034820556640625 +42895 -0.258209228515625 +42896 -0.44244384765625 +42897 -0.5753173828125 +42898 -0.65203857421875 +42899 -0.641632080078125 +42900 -0.562164306640625 +42901 -0.458038330078125 +42902 -0.350555419921875 +42903 -0.260528564453125 +42904 -0.192108154296875 +42905 -0.141937255859375 +42906 -0.1021728515625 +42907 -0.062896728515625 +42908 -0.011932373046875 +42909 0.062835693359375 +42910 0.148712158203125 +42911 0.241729736328125 +42912 0.34912109375 +42913 0.457305908203125 +42914 0.54388427734375 +42915 0.5728759765625 +42916 0.506591796875 +42917 0.351226806640625 +42918 0.146514892578125 +42919 -0.05523681640625 +42920 -0.21624755859375 +42921 -0.334930419921875 +42922 -0.402984619140625 +42923 -0.4412841796875 +42924 -0.49578857421875 +42925 -0.5601806640625 +42926 -0.600738525390625 +42927 -0.584228515625 +42928 -0.47930908203125 +42929 -0.27935791015625 +42930 -0.0089111328125 +42931 0.268798828125 +42932 0.482818603515625 +42933 0.60369873046875 +42934 0.650421142578125 +42935 0.66400146484375 +42936 0.6414794921875 +42937 0.572540283203125 +42938 0.498138427734375 +42939 0.439453125 +42940 0.375518798828125 +42941 0.274505615234375 +42942 0.1087646484375 +42943 -0.099395751953125 +42944 -0.3182373046875 +42945 -0.5489501953125 +42946 -0.7738037109375 +42947 -0.86383056640625 +42948 -0.870391845703125 +42949 -0.86895751953125 +42950 -0.861053466796875 +42951 -0.765869140625 +42952 -0.5301513671875 +42953 -0.214691162109375 +42954 0.137359619140625 +42955 0.474822998046875 +42956 0.76239013671875 +42957 0.867462158203125 +42958 0.870361328125 +42959 0.86480712890625 +42960 0.831817626953125 +42961 0.677581787109375 +42962 0.495880126953125 +42963 0.30767822265625 +42964 0.116180419921875 +42965 -0.110748291015625 +42966 -0.381805419921875 +42967 -0.6572265625 +42968 -0.857421875 +42969 -0.870391845703125 +42970 -0.870391845703125 +42971 -0.86444091796875 +42972 -0.85723876953125 +42973 -0.790008544921875 +42974 -0.62847900390625 +42975 -0.3956298828125 +42976 -0.126708984375 +42977 0.150115966796875 +42978 0.424041748046875 +42979 0.670623779296875 +42980 0.854522705078125 +42981 0.866485595703125 +42982 0.86920166015625 +42983 0.8653564453125 +42984 0.857147216796875 +42985 0.766845703125 +42986 0.628509521484375 +42987 0.462127685546875 +42988 0.297210693359375 +42989 0.14862060546875 +42990 -0.00537109375 +42991 -0.15753173828125 +42992 -0.31304931640625 +42993 -0.48876953125 +42994 -0.6416015625 +42995 -0.751373291015625 +42996 -0.84619140625 +42997 -0.861297607421875 +42998 -0.863250732421875 +42999 -0.856597900390625 +43000 -0.7498779296875 +43001 -0.624542236328125 +43002 -0.47808837890625 +43003 -0.253387451171875 +43004 0.003692626953125 +43005 0.2257080078125 +43006 0.427154541015625 +43007 0.643218994140625 +43008 0.855926513671875 +43009 0.870361328125 +43010 0.870361328125 +43011 0.862762451171875 +43012 0.79669189453125 +43013 0.595794677734375 +43014 0.362152099609375 +43015 0.1270751953125 +43016 -0.086944580078125 +43017 -0.2784423828125 +43018 -0.484832763671875 +43019 -0.729583740234375 +43020 -0.86688232421875 +43021 -0.870391845703125 +43022 -0.86859130859375 +43023 -0.86279296875 +43024 -0.817962646484375 +43025 -0.6116943359375 +43026 -0.3128662109375 +43027 0.039398193359375 +43028 0.422821044921875 +43029 0.805145263671875 +43030 0.870361328125 +43031 0.870361328125 +43032 0.860015869140625 +43033 0.727935791015625 +43034 0.48114013671875 +43035 0.2059326171875 +43036 -0.06103515625 +43037 -0.29913330078125 +43038 -0.516204833984375 +43039 -0.7252197265625 +43040 -0.85980224609375 +43041 -0.870391845703125 +43042 -0.870391845703125 +43043 -0.858062744140625 +43044 -0.673004150390625 +43045 -0.42694091796875 +43046 -0.2100830078125 +43047 -0.0362548828125 +43048 0.10943603515625 +43049 0.23516845703125 +43050 0.373687744140625 +43051 0.517791748046875 +43052 0.602783203125 +43053 0.635711669921875 +43054 0.655181884765625 +43055 0.65948486328125 +43056 0.651275634765625 +43057 0.61846923828125 +43058 0.53753662109375 +43059 0.404144287109375 +43060 0.22186279296875 +43061 0.003997802734375 +43062 -0.22100830078125 +43063 -0.42449951171875 +43064 -0.579833984375 +43065 -0.641876220703125 +43066 -0.6177978515625 +43067 -0.575531005859375 +43068 -0.526336669921875 +43069 -0.42645263671875 +43070 -0.2581787109375 +43071 -0.068695068359375 +43072 0.09222412109375 +43073 0.232147216796875 +43074 0.3509521484375 +43075 0.410064697265625 +43076 0.372955322265625 +43077 0.2554931640625 +43078 0.10711669921875 +43079 -0.052886962890625 +43080 -0.186279296875 +43081 -0.23291015625 +43082 -0.209442138671875 +43083 -0.174163818359375 +43084 -0.126739501953125 +43085 -0.048126220703125 +43086 0.0426025390625 +43087 0.10748291015625 +43088 0.1409912109375 +43089 0.19708251953125 +43090 0.273651123046875 +43091 0.31768798828125 +43092 0.341094970703125 +43093 0.368011474609375 +43094 0.37249755859375 +43095 0.30072021484375 +43096 0.1517333984375 +43097 -0.01470947265625 +43098 -0.1883544921875 +43099 -0.372711181640625 +43100 -0.51397705078125 +43101 -0.57177734375 +43102 -0.53948974609375 +43103 -0.43511962890625 +43104 -0.2962646484375 +43105 -0.161102294921875 +43106 -0.0435791015625 +43107 0.060394287109375 +43108 0.13665771484375 +43109 0.170135498046875 +43110 0.16552734375 +43111 0.15728759765625 +43112 0.150787353515625 +43113 0.12200927734375 +43114 0.080108642578125 +43115 0.05126953125 +43116 0.062896728515625 +43117 0.09271240234375 +43118 0.092987060546875 +43119 0.07855224609375 +43120 0.06427001953125 +43121 0.0347900390625 +43122 -0.01171875 +43123 -0.056060791015625 +43124 -0.055511474609375 +43125 -0.010467529296875 +43126 0.02508544921875 +43127 0.025665283203125 +43128 0.017333984375 +43129 0.00189208984375 +43130 -0.03173828125 +43131 -0.071502685546875 +43132 -0.13543701171875 +43133 -0.219970703125 +43134 -0.300506591796875 +43135 -0.376312255859375 +43136 -0.416107177734375 +43137 -0.371124267578125 +43138 -0.242279052734375 +43139 -0.069732666015625 +43140 0.125640869140625 +43141 0.31268310546875 +43142 0.45501708984375 +43143 0.554779052734375 +43144 0.61065673828125 +43145 0.610931396484375 +43146 0.531463623046875 +43147 0.3883056640625 +43148 0.23468017578125 +43149 0.095245361328125 +43150 -0.00396728515625 +43151 -0.04852294921875 +43152 -0.055145263671875 +43153 -0.0758056640625 +43154 -0.138702392578125 +43155 -0.209197998046875 +43156 -0.289031982421875 +43157 -0.37884521484375 +43158 -0.456329345703125 +43159 -0.51641845703125 +43160 -0.519287109375 +43161 -0.458251953125 +43162 -0.384796142578125 +43163 -0.323699951171875 +43164 -0.269287109375 +43165 -0.1951904296875 +43166 -0.100006103515625 +43167 -0.01055908203125 +43168 0.1033935546875 +43169 0.24908447265625 +43170 0.373199462890625 +43171 0.45806884765625 +43172 0.511474609375 +43173 0.565399169921875 +43174 0.61138916015625 +43175 0.5897216796875 +43176 0.4906005859375 +43177 0.33148193359375 +43178 0.147796630859375 +43179 -0.01873779296875 +43180 -0.140289306640625 +43181 -0.191986083984375 +43182 -0.184295654296875 +43183 -0.161834716796875 +43184 -0.166595458984375 +43185 -0.19390869140625 +43186 -0.22442626953125 +43187 -0.279754638671875 +43188 -0.3389892578125 +43189 -0.3543701171875 +43190 -0.348175048828125 +43191 -0.32598876953125 +43192 -0.2581787109375 +43193 -0.139801025390625 +43194 0.014617919921875 +43195 0.144378662109375 +43196 0.221038818359375 +43197 0.27069091796875 +43198 0.294036865234375 +43199 0.311767578125 +43200 0.339141845703125 +43201 0.360260009765625 +43202 0.360504150390625 +43203 0.308380126953125 +43204 0.18170166015625 +43205 0.0047607421875 +43206 -0.17559814453125 +43207 -0.3143310546875 +43208 -0.36785888671875 +43209 -0.36248779296875 +43210 -0.343536376953125 +43211 -0.3018798828125 +43212 -0.231414794921875 +43213 -0.117645263671875 +43214 0.007049560546875 +43215 0.087982177734375 +43216 0.13946533203125 +43217 0.17425537109375 +43218 0.188201904296875 +43219 0.171234130859375 +43220 0.118438720703125 +43221 0.05706787109375 +43222 -0.010711669921875 +43223 -0.0914306640625 +43224 -0.162322998046875 +43225 -0.194549560546875 +43226 -0.1492919921875 +43227 -0.02166748046875 +43228 0.124053955078125 +43229 0.211151123046875 +43230 0.240447998046875 +43231 0.242218017578125 +43232 0.2257080078125 +43233 0.194366455078125 +43234 0.115509033203125 +43235 0.0128173828125 +43236 -0.053802490234375 +43237 -0.110626220703125 +43238 -0.199493408203125 +43239 -0.29437255859375 +43240 -0.33221435546875 +43241 -0.27972412109375 +43242 -0.185333251953125 +43243 -0.128204345703125 +43244 -0.115692138671875 +43245 -0.116455078125 +43246 -0.105926513671875 +43247 -0.053955078125 +43248 0.048797607421875 +43249 0.157318115234375 +43250 0.212005615234375 +43251 0.218475341796875 +43252 0.23724365234375 +43253 0.30535888671875 +43254 0.38128662109375 +43255 0.404449462890625 +43256 0.3944091796875 +43257 0.3885498046875 +43258 0.362640380859375 +43259 0.27362060546875 +43260 0.11712646484375 +43261 -0.054901123046875 +43262 -0.19085693359375 +43263 -0.28570556640625 +43264 -0.339263916015625 +43265 -0.3775634765625 +43266 -0.445709228515625 +43267 -0.535064697265625 +43268 -0.629058837890625 +43269 -0.697601318359375 +43270 -0.70391845703125 +43271 -0.6424560546875 +43272 -0.491241455078125 +43273 -0.265716552734375 +43274 -0.023712158203125 +43275 0.201751708984375 +43276 0.375823974609375 +43277 0.485076904296875 +43278 0.56884765625 +43279 0.634765625 +43280 0.63763427734375 +43281 0.5660400390625 +43282 0.4720458984375 +43283 0.40692138671875 +43284 0.3778076171875 +43285 0.376953125 +43286 0.371978759765625 +43287 0.313140869140625 +43288 0.184417724609375 +43289 0.011199951171875 +43290 -0.171051025390625 +43291 -0.33740234375 +43292 -0.47198486328125 +43293 -0.560394287109375 +43294 -0.58056640625 +43295 -0.54754638671875 +43296 -0.508575439453125 +43297 -0.459503173828125 +43298 -0.394378662109375 +43299 -0.35260009765625 +43300 -0.31170654296875 +43301 -0.197418212890625 +43302 -0.007965087890625 +43303 0.207489013671875 +43304 0.409210205078125 +43305 0.57208251953125 +43306 0.66595458984375 +43307 0.65875244140625 +43308 0.56744384765625 +43309 0.431396484375 +43310 0.29443359375 +43311 0.182464599609375 +43312 0.06365966796875 +43313 -0.075958251953125 +43314 -0.189422607421875 +43315 -0.271942138671875 +43316 -0.342529296875 +43317 -0.364166259765625 +43318 -0.327239990234375 +43319 -0.2769775390625 +43320 -0.253692626953125 +43321 -0.24365234375 +43322 -0.1983642578125 +43323 -0.116241455078125 +43324 -0.036834716796875 +43325 0.034881591796875 +43326 0.09124755859375 +43327 0.10888671875 +43328 0.125518798828125 +43329 0.15771484375 +43330 0.17828369140625 +43331 0.17108154296875 +43332 0.129974365234375 +43333 0.082427978515625 +43334 0.027679443359375 +43335 -0.065643310546875 +43336 -0.15936279296875 +43337 -0.21307373046875 +43338 -0.234649658203125 +43339 -0.2001953125 +43340 -0.119171142578125 +43341 -0.024749755859375 +43342 0.085784912109375 +43343 0.178131103515625 +43344 0.215576171875 +43345 0.211456298828125 +43346 0.17523193359375 +43347 0.128753662109375 +43348 0.1019287109375 +43349 0.0743408203125 +43350 0.04327392578125 +43351 0.038177490234375 +43352 0.076263427734375 +43353 0.14105224609375 +43354 0.186431884765625 +43355 0.188812255859375 +43356 0.1390380859375 +43357 0.041778564453125 +43358 -0.079437255859375 +43359 -0.219390869140625 +43360 -0.367828369140625 +43361 -0.494873046875 +43362 -0.556243896484375 +43363 -0.508697509765625 +43364 -0.3756103515625 +43365 -0.218902587890625 +43366 -0.063751220703125 +43367 0.091552734375 +43368 0.23602294921875 +43369 0.342987060546875 +43370 0.39520263671875 +43371 0.389373779296875 +43372 0.324249267578125 +43373 0.224090576171875 +43374 0.124267578125 +43375 0.037078857421875 +43376 -0.010101318359375 +43377 -0.019439697265625 +43378 -0.022796630859375 +43379 -0.001556396484375 +43380 0.056304931640625 +43381 0.106719970703125 +43382 0.096893310546875 +43383 0.042694091796875 +43384 -0.018035888671875 +43385 -0.07586669921875 +43386 -0.11944580078125 +43387 -0.15972900390625 +43388 -0.202606201171875 +43389 -0.24859619140625 +43390 -0.30517578125 +43391 -0.36212158203125 +43392 -0.39141845703125 +43393 -0.35528564453125 +43394 -0.249969482421875 +43395 -0.092864990234375 +43396 0.08905029296875 +43397 0.2352294921875 +43398 0.318817138671875 +43399 0.358642578125 +43400 0.347747802734375 +43401 0.28564453125 +43402 0.223175048828125 +43403 0.196746826171875 +43404 0.179840087890625 +43405 0.155548095703125 +43406 0.151214599609375 +43407 0.156951904296875 +43408 0.13177490234375 +43409 0.100799560546875 +43410 0.087127685546875 +43411 0.05487060546875 +43412 -0.009002685546875 +43413 -0.10400390625 +43414 -0.229400634765625 +43415 -0.35552978515625 +43416 -0.441925048828125 +43417 -0.473846435546875 +43418 -0.464813232421875 +43419 -0.419097900390625 +43420 -0.334320068359375 +43421 -0.227935791015625 +43422 -0.12347412109375 +43423 -0.02764892578125 +43424 0.077667236328125 +43425 0.2132568359375 +43426 0.38885498046875 +43427 0.582794189453125 +43428 0.734039306640625 +43429 0.800140380859375 +43430 0.7783203125 +43431 0.6651611328125 +43432 0.45965576171875 +43433 0.199188232421875 +43434 -0.050689697265625 +43435 -0.23297119140625 +43436 -0.33013916015625 +43437 -0.368408203125 +43438 -0.378936767578125 +43439 -0.376983642578125 +43440 -0.37969970703125 +43441 -0.391510009765625 +43442 -0.385345458984375 +43443 -0.3419189453125 +43444 -0.28289794921875 +43445 -0.251617431640625 +43446 -0.266143798828125 +43447 -0.273345947265625 +43448 -0.216796875 +43449 -0.128265380859375 +43450 -0.068145751953125 +43451 -0.0430908203125 +43452 -0.024444580078125 +43453 0.020721435546875 +43454 0.124481201171875 +43455 0.25787353515625 +43456 0.379119873046875 +43457 0.47991943359375 +43458 0.5281982421875 +43459 0.511138916015625 +43460 0.456207275390625 +43461 0.407470703125 +43462 0.383758544921875 +43463 0.35687255859375 +43464 0.31182861328125 +43465 0.250885009765625 +43466 0.1654052734375 +43467 0.035247802734375 +43468 -0.142059326171875 +43469 -0.33563232421875 +43470 -0.5345458984375 +43471 -0.72186279296875 +43472 -0.836669921875 +43473 -0.8326416015625 +43474 -0.7296142578125 +43475 -0.582550048828125 +43476 -0.440093994140625 +43477 -0.324310302734375 +43478 -0.20147705078125 +43479 -0.044647216796875 +43480 0.103973388671875 +43481 0.202392578125 +43482 0.264495849609375 +43483 0.338897705078125 +43484 0.443817138671875 +43485 0.545074462890625 +43486 0.6173095703125 +43487 0.6524658203125 +43488 0.66339111328125 +43489 0.6561279296875 +43490 0.606781005859375 +43491 0.501190185546875 +43492 0.352783203125 +43493 0.176544189453125 +43494 -0.034820556640625 +43495 -0.258209228515625 +43496 -0.44244384765625 +43497 -0.5753173828125 +43498 -0.65203857421875 +43499 -0.641632080078125 +43500 -0.562164306640625 +43501 -0.458038330078125 +43502 -0.350555419921875 +43503 -0.260528564453125 +43504 -0.192108154296875 +43505 -0.141937255859375 +43506 -0.1021728515625 +43507 -0.062896728515625 +43508 -0.011932373046875 +43509 0.062835693359375 +43510 0.148712158203125 +43511 0.241729736328125 +43512 0.34912109375 +43513 0.457305908203125 +43514 0.54388427734375 +43515 0.5728759765625 +43516 0.506591796875 +43517 0.351226806640625 +43518 0.146514892578125 +43519 -0.05523681640625 +43520 -0.21624755859375 +43521 -0.334930419921875 +43522 -0.402984619140625 +43523 -0.4412841796875 +43524 -0.49578857421875 +43525 -0.5601806640625 +43526 -0.600738525390625 +43527 -0.584228515625 +43528 -0.47930908203125 +43529 -0.27935791015625 +43530 -0.0089111328125 +43531 0.268798828125 +43532 0.482818603515625 +43533 0.60369873046875 +43534 0.650421142578125 +43535 0.66400146484375 +43536 0.6414794921875 +43537 0.572540283203125 +43538 0.498138427734375 +43539 0.439453125 +43540 0.375518798828125 +43541 0.274505615234375 +43542 0.1087646484375 +43543 -0.099395751953125 +43544 -0.3182373046875 +43545 -0.5489501953125 +43546 -0.7738037109375 +43547 -0.86383056640625 +43548 -0.870391845703125 +43549 -0.86895751953125 +43550 -0.861053466796875 +43551 -0.765869140625 +43552 -0.5301513671875 +43553 -0.214691162109375 +43554 0.137359619140625 +43555 0.474822998046875 +43556 0.76239013671875 +43557 0.867462158203125 +43558 0.870361328125 +43559 0.86480712890625 +43560 0.831817626953125 +43561 0.677581787109375 +43562 0.495880126953125 +43563 0.30767822265625 +43564 0.116180419921875 +43565 -0.110748291015625 +43566 -0.381805419921875 +43567 -0.6572265625 +43568 -0.857421875 +43569 -0.870391845703125 +43570 -0.870391845703125 +43571 -0.86444091796875 +43572 -0.85723876953125 +43573 -0.790008544921875 +43574 -0.62847900390625 +43575 -0.3956298828125 +43576 -0.126708984375 +43577 0.150115966796875 +43578 0.424041748046875 +43579 0.670623779296875 +43580 0.854522705078125 +43581 0.866485595703125 +43582 0.86920166015625 +43583 0.8653564453125 +43584 0.857147216796875 +43585 0.766845703125 +43586 0.628509521484375 +43587 0.462127685546875 +43588 0.297210693359375 +43589 0.14862060546875 +43590 -0.00537109375 +43591 -0.15753173828125 +43592 -0.31304931640625 +43593 -0.48876953125 +43594 -0.6416015625 +43595 -0.751373291015625 +43596 -0.84619140625 +43597 -0.861297607421875 +43598 -0.863250732421875 +43599 -0.856597900390625 +43600 -0.7498779296875 +43601 -0.624542236328125 +43602 -0.47808837890625 +43603 -0.253387451171875 +43604 0.003692626953125 +43605 0.2257080078125 +43606 0.427154541015625 +43607 0.643218994140625 +43608 0.855926513671875 +43609 0.870361328125 +43610 0.870361328125 +43611 0.862762451171875 +43612 0.79669189453125 +43613 0.595794677734375 +43614 0.362152099609375 +43615 0.1270751953125 +43616 -0.086944580078125 +43617 -0.2784423828125 +43618 -0.484832763671875 +43619 -0.729583740234375 +43620 -0.86688232421875 +43621 -0.870391845703125 +43622 -0.86859130859375 +43623 -0.86279296875 +43624 -0.817962646484375 +43625 -0.6116943359375 +43626 -0.3128662109375 +43627 0.039398193359375 +43628 0.422821044921875 +43629 0.805145263671875 +43630 0.870361328125 +43631 0.870361328125 +43632 0.860015869140625 +43633 0.727935791015625 +43634 0.48114013671875 +43635 0.2059326171875 +43636 -0.06103515625 +43637 -0.29913330078125 +43638 -0.516204833984375 +43639 -0.7252197265625 +43640 -0.85980224609375 +43641 -0.870391845703125 +43642 -0.870391845703125 +43643 -0.858062744140625 +43644 -0.673004150390625 +43645 -0.42694091796875 +43646 -0.2100830078125 +43647 -0.0362548828125 +43648 0.10943603515625 +43649 0.23516845703125 +43650 0.373687744140625 +43651 0.517791748046875 +43652 0.602783203125 +43653 0.635711669921875 +43654 0.655181884765625 +43655 0.65948486328125 +43656 0.651275634765625 +43657 0.61846923828125 +43658 0.53753662109375 +43659 0.404144287109375 +43660 0.22186279296875 +43661 0.003997802734375 +43662 -0.22100830078125 +43663 -0.42449951171875 +43664 -0.579833984375 +43665 -0.641876220703125 +43666 -0.6177978515625 +43667 -0.575531005859375 +43668 -0.526336669921875 +43669 -0.42645263671875 +43670 -0.2581787109375 +43671 -0.068695068359375 +43672 0.09222412109375 +43673 0.232147216796875 +43674 0.3509521484375 +43675 0.410064697265625 +43676 0.372955322265625 +43677 0.2554931640625 +43678 0.10711669921875 +43679 -0.052886962890625 +43680 -0.186279296875 +43681 -0.23291015625 +43682 -0.209442138671875 +43683 -0.174163818359375 +43684 -0.126739501953125 +43685 -0.048126220703125 +43686 0.0426025390625 +43687 0.10748291015625 +43688 0.1409912109375 +43689 0.19708251953125 +43690 0.273651123046875 +43691 0.31768798828125 +43692 0.341094970703125 +43693 0.368011474609375 +43694 0.37249755859375 +43695 0.30072021484375 +43696 0.1517333984375 +43697 -0.01470947265625 +43698 -0.1883544921875 +43699 -0.372711181640625 +43700 -0.51397705078125 +43701 -0.57177734375 +43702 -0.53948974609375 +43703 -0.43511962890625 +43704 -0.2962646484375 +43705 -0.161102294921875 +43706 -0.0435791015625 +43707 0.060394287109375 +43708 0.13665771484375 +43709 0.170135498046875 +43710 0.16552734375 +43711 0.15728759765625 +43712 0.150787353515625 +43713 0.12200927734375 +43714 0.080108642578125 +43715 0.05126953125 +43716 0.062896728515625 +43717 0.09271240234375 +43718 0.092987060546875 +43719 0.07855224609375 +43720 0.06427001953125 +43721 0.0347900390625 +43722 -0.01171875 +43723 -0.056060791015625 +43724 -0.055511474609375 +43725 -0.010467529296875 +43726 0.02508544921875 +43727 0.025665283203125 +43728 0.017333984375 +43729 0.00189208984375 +43730 -0.03173828125 +43731 -0.071502685546875 +43732 -0.13543701171875 +43733 -0.219970703125 +43734 -0.300506591796875 +43735 -0.376312255859375 +43736 -0.416107177734375 +43737 -0.371124267578125 +43738 -0.242279052734375 +43739 -0.069732666015625 +43740 0.125640869140625 +43741 0.31268310546875 +43742 0.45501708984375 +43743 0.554779052734375 +43744 0.61065673828125 +43745 0.610931396484375 +43746 0.531463623046875 +43747 0.3883056640625 +43748 0.23468017578125 +43749 0.095245361328125 +43750 -0.00396728515625 +43751 -0.04852294921875 +43752 -0.055145263671875 +43753 -0.0758056640625 +43754 -0.138702392578125 +43755 -0.209197998046875 +43756 -0.289031982421875 +43757 -0.37884521484375 +43758 -0.456329345703125 +43759 -0.51641845703125 +43760 -0.519287109375 +43761 -0.458251953125 +43762 -0.384796142578125 +43763 -0.323699951171875 +43764 -0.269287109375 +43765 -0.1951904296875 +43766 -0.100006103515625 +43767 -0.01055908203125 +43768 0.1033935546875 +43769 0.24908447265625 +43770 0.373199462890625 +43771 0.45806884765625 +43772 0.511474609375 +43773 0.565399169921875 +43774 0.61138916015625 +43775 0.5897216796875 +43776 0.4906005859375 +43777 0.33148193359375 +43778 0.147796630859375 +43779 -0.01873779296875 +43780 -0.140289306640625 +43781 -0.191986083984375 +43782 -0.184295654296875 +43783 -0.161834716796875 +43784 -0.166595458984375 +43785 -0.19390869140625 +43786 -0.22442626953125 +43787 -0.279754638671875 +43788 -0.3389892578125 +43789 -0.3543701171875 +43790 -0.348175048828125 +43791 -0.32598876953125 +43792 -0.2581787109375 +43793 -0.139801025390625 +43794 0.014617919921875 +43795 0.144378662109375 +43796 0.221038818359375 +43797 0.27069091796875 +43798 0.294036865234375 +43799 0.311767578125 +43800 0.339141845703125 +43801 0.360260009765625 +43802 0.360504150390625 +43803 0.308380126953125 +43804 0.18170166015625 +43805 0.0047607421875 +43806 -0.17559814453125 +43807 -0.3143310546875 +43808 -0.36785888671875 +43809 -0.36248779296875 +43810 -0.343536376953125 +43811 -0.3018798828125 +43812 -0.231414794921875 +43813 -0.117645263671875 +43814 0.007049560546875 +43815 0.087982177734375 +43816 0.13946533203125 +43817 0.17425537109375 +43818 0.188201904296875 +43819 0.171234130859375 +43820 0.118438720703125 +43821 0.05706787109375 +43822 -0.010711669921875 +43823 -0.0914306640625 +43824 -0.162322998046875 +43825 -0.194549560546875 +43826 -0.1492919921875 +43827 -0.02166748046875 +43828 0.124053955078125 +43829 0.211151123046875 +43830 0.240447998046875 +43831 0.242218017578125 +43832 0.2257080078125 +43833 0.194366455078125 +43834 0.115509033203125 +43835 0.0128173828125 +43836 -0.053802490234375 +43837 -0.110626220703125 +43838 -0.199493408203125 +43839 -0.29437255859375 +43840 -0.33221435546875 +43841 -0.27972412109375 +43842 -0.185333251953125 +43843 -0.128204345703125 +43844 -0.115692138671875 +43845 -0.116455078125 +43846 -0.105926513671875 +43847 -0.053955078125 +43848 0.048797607421875 +43849 0.157318115234375 +43850 0.212005615234375 +43851 0.218475341796875 +43852 0.23724365234375 +43853 0.30535888671875 +43854 0.38128662109375 +43855 0.404449462890625 +43856 0.3944091796875 +43857 0.3885498046875 +43858 0.362640380859375 +43859 0.27362060546875 +43860 0.11712646484375 +43861 -0.054901123046875 +43862 -0.19085693359375 +43863 -0.28570556640625 +43864 -0.339263916015625 +43865 -0.3775634765625 +43866 -0.445709228515625 +43867 -0.535064697265625 +43868 -0.629058837890625 +43869 -0.697601318359375 +43870 -0.70391845703125 +43871 -0.6424560546875 +43872 -0.491241455078125 +43873 -0.265716552734375 +43874 -0.023712158203125 +43875 0.201751708984375 +43876 0.375823974609375 +43877 0.485076904296875 +43878 0.56884765625 +43879 0.634765625 +43880 0.63763427734375 +43881 0.5660400390625 +43882 0.4720458984375 +43883 0.40692138671875 +43884 0.3778076171875 +43885 0.376953125 +43886 0.371978759765625 +43887 0.313140869140625 +43888 0.184417724609375 +43889 0.011199951171875 +43890 -0.171051025390625 +43891 -0.33740234375 +43892 -0.47198486328125 +43893 -0.560394287109375 +43894 -0.58056640625 +43895 -0.54754638671875 +43896 -0.508575439453125 +43897 -0.459503173828125 +43898 -0.394378662109375 +43899 -0.35260009765625 +43900 -0.31170654296875 +43901 -0.197418212890625 +43902 -0.007965087890625 +43903 0.207489013671875 +43904 0.409210205078125 +43905 0.57208251953125 +43906 0.66595458984375 +43907 0.65875244140625 +43908 0.56744384765625 +43909 0.431396484375 +43910 0.29443359375 +43911 0.182464599609375 +43912 0.06365966796875 +43913 -0.075958251953125 +43914 -0.189422607421875 +43915 -0.271942138671875 +43916 -0.342529296875 +43917 -0.364166259765625 +43918 -0.327239990234375 +43919 -0.2769775390625 +43920 -0.253692626953125 +43921 -0.24365234375 +43922 -0.1983642578125 +43923 -0.116241455078125 +43924 -0.036834716796875 +43925 0.034881591796875 +43926 0.09124755859375 +43927 0.10888671875 +43928 0.125518798828125 +43929 0.15771484375 +43930 0.17828369140625 +43931 0.17108154296875 +43932 0.129974365234375 +43933 0.082427978515625 +43934 0.027679443359375 +43935 -0.065643310546875 +43936 -0.15936279296875 +43937 -0.21307373046875 +43938 -0.234649658203125 +43939 -0.2001953125 +43940 -0.119171142578125 +43941 -0.024749755859375 +43942 0.085784912109375 +43943 0.178131103515625 +43944 0.215576171875 +43945 0.211456298828125 +43946 0.17523193359375 +43947 0.128753662109375 +43948 0.1019287109375 +43949 0.0743408203125 +43950 0.04327392578125 +43951 0.038177490234375 +43952 0.076263427734375 +43953 0.14105224609375 +43954 0.186431884765625 +43955 0.188812255859375 +43956 0.1390380859375 +43957 0.041778564453125 +43958 -0.079437255859375 +43959 -0.219390869140625 +43960 -0.367828369140625 +43961 -0.494873046875 +43962 -0.556243896484375 +43963 -0.508697509765625 +43964 -0.3756103515625 +43965 -0.218902587890625 +43966 -0.063751220703125 +43967 0.091552734375 +43968 0.23602294921875 +43969 0.342987060546875 +43970 0.39520263671875 +43971 0.389373779296875 +43972 0.324249267578125 +43973 0.224090576171875 +43974 0.124267578125 +43975 0.037078857421875 +43976 -0.010101318359375 +43977 -0.019439697265625 +43978 -0.022796630859375 +43979 -0.001556396484375 +43980 0.056304931640625 +43981 0.106719970703125 +43982 0.096893310546875 +43983 0.042694091796875 +43984 -0.018035888671875 +43985 -0.07586669921875 +43986 -0.11944580078125 +43987 -0.15972900390625 +43988 -0.202606201171875 +43989 -0.24859619140625 +43990 -0.30517578125 +43991 -0.36212158203125 +43992 -0.39141845703125 +43993 -0.35528564453125 +43994 -0.249969482421875 +43995 -0.092864990234375 +43996 0.08905029296875 +43997 0.2352294921875 +43998 0.318817138671875 +43999 0.358642578125 +44000 0.347747802734375 +44001 0.28564453125 +44002 0.223175048828125 +44003 0.196746826171875 +44004 0.179840087890625 +44005 0.155548095703125 +44006 0.151214599609375 +44007 0.156951904296875 +44008 0.13177490234375 +44009 0.100799560546875 +44010 0.087127685546875 +44011 0.05487060546875 +44012 -0.009002685546875 +44013 -0.10400390625 +44014 -0.229400634765625 +44015 -0.35552978515625 +44016 -0.441925048828125 +44017 -0.473846435546875 +44018 -0.464813232421875 +44019 -0.419097900390625 +44020 -0.334320068359375 +44021 -0.227935791015625 +44022 -0.12347412109375 +44023 -0.02764892578125 +44024 0.077667236328125 +44025 0.2132568359375 +44026 0.38885498046875 +44027 0.582794189453125 +44028 0.734039306640625 +44029 0.800140380859375 +44030 0.7783203125 +44031 0.6651611328125 +44032 0.45965576171875 +44033 0.199188232421875 +44034 -0.050689697265625 +44035 -0.23297119140625 +44036 -0.33013916015625 +44037 -0.368408203125 +44038 -0.378936767578125 +44039 -0.376983642578125 +44040 -0.37969970703125 +44041 -0.391510009765625 +44042 -0.385345458984375 +44043 -0.3419189453125 +44044 -0.28289794921875 +44045 -0.251617431640625 +44046 -0.266143798828125 +44047 -0.273345947265625 +44048 -0.216796875 +44049 -0.128265380859375 +44050 -0.068145751953125 +44051 -0.0430908203125 +44052 -0.024444580078125 +44053 0.020721435546875 +44054 0.124481201171875 +44055 0.25787353515625 +44056 0.379119873046875 +44057 0.47991943359375 +44058 0.5281982421875 +44059 0.511138916015625 +44060 0.456207275390625 +44061 0.407470703125 +44062 0.383758544921875 +44063 0.35687255859375 +44064 0.31182861328125 +44065 0.250885009765625 +44066 0.1654052734375 +44067 0.035247802734375 +44068 -0.142059326171875 +44069 -0.33563232421875 +44070 -0.5345458984375 +44071 -0.72186279296875 +44072 -0.836669921875 +44073 -0.8326416015625 +44074 -0.7296142578125 +44075 -0.582550048828125 +44076 -0.440093994140625 +44077 -0.324310302734375 +44078 -0.20147705078125 +44079 -0.044647216796875 +44080 0.103973388671875 +44081 0.202392578125 +44082 0.264495849609375 +44083 0.338897705078125 +44084 0.443817138671875 +44085 0.545074462890625 +44086 0.6173095703125 +44087 0.6524658203125 +44088 0.66339111328125 +44089 0.6561279296875 +44090 0.606781005859375 +44091 0.501190185546875 +44092 0.352783203125 +44093 0.176544189453125 +44094 -0.034820556640625 +44095 -0.258209228515625 +44096 -0.44244384765625 +44097 -0.5753173828125 +44098 -0.65203857421875 +44099 -0.641632080078125 +44100 -0.562164306640625 +44101 -0.458038330078125 +44102 -0.350555419921875 +44103 -0.260528564453125 +44104 -0.192108154296875 +44105 -0.141937255859375 +44106 -0.1021728515625 +44107 -0.062896728515625 +44108 -0.011932373046875 +44109 0.062835693359375 +44110 0.148712158203125 +44111 0.241729736328125 +44112 0.34912109375 +44113 0.457305908203125 +44114 0.54388427734375 +44115 0.5728759765625 +44116 0.506591796875 +44117 0.351226806640625 +44118 0.146514892578125 +44119 -0.05523681640625 +44120 -0.21624755859375 +44121 -0.334930419921875 +44122 -0.402984619140625 +44123 -0.4412841796875 +44124 -0.49578857421875 +44125 -0.5601806640625 +44126 -0.600738525390625 +44127 -0.584228515625 +44128 -0.47930908203125 +44129 -0.27935791015625 +44130 -0.0089111328125 +44131 0.268798828125 +44132 0.482818603515625 +44133 0.60369873046875 +44134 0.650421142578125 +44135 0.66400146484375 +44136 0.6414794921875 +44137 0.572540283203125 +44138 0.498138427734375 +44139 0.439453125 +44140 0.375518798828125 +44141 0.274505615234375 +44142 0.1087646484375 +44143 -0.099395751953125 +44144 -0.3182373046875 +44145 -0.5489501953125 +44146 -0.7738037109375 +44147 -0.86383056640625 +44148 -0.870391845703125 +44149 -0.86895751953125 +44150 -0.861053466796875 +44151 -0.765869140625 +44152 -0.5301513671875 +44153 -0.214691162109375 +44154 0.137359619140625 +44155 0.474822998046875 +44156 0.76239013671875 +44157 0.867462158203125 +44158 0.870361328125 +44159 0.86480712890625 +44160 0.831817626953125 +44161 0.677581787109375 +44162 0.495880126953125 +44163 0.30767822265625 +44164 0.116180419921875 +44165 -0.110748291015625 +44166 -0.381805419921875 +44167 -0.6572265625 +44168 -0.857421875 +44169 -0.870391845703125 +44170 -0.870391845703125 +44171 -0.86444091796875 +44172 -0.85723876953125 +44173 -0.790008544921875 +44174 -0.62847900390625 +44175 -0.3956298828125 +44176 -0.126708984375 +44177 0.150115966796875 +44178 0.424041748046875 +44179 0.670623779296875 +44180 0.854522705078125 +44181 0.866485595703125 +44182 0.86920166015625 +44183 0.8653564453125 +44184 0.857147216796875 +44185 0.766845703125 +44186 0.628509521484375 +44187 0.462127685546875 +44188 0.297210693359375 +44189 0.14862060546875 +44190 -0.00537109375 +44191 -0.15753173828125 +44192 -0.31304931640625 +44193 -0.48876953125 +44194 -0.6416015625 +44195 -0.751373291015625 +44196 -0.84619140625 +44197 -0.861297607421875 +44198 -0.863250732421875 +44199 -0.856597900390625 +44200 -0.7498779296875 +44201 -0.624542236328125 +44202 -0.47808837890625 +44203 -0.253387451171875 +44204 0.003692626953125 +44205 0.2257080078125 +44206 0.427154541015625 +44207 0.643218994140625 +44208 0.855926513671875 +44209 0.870361328125 +44210 0.870361328125 +44211 0.862762451171875 +44212 0.79669189453125 +44213 0.595794677734375 +44214 0.362152099609375 +44215 0.1270751953125 +44216 -0.086944580078125 +44217 -0.2784423828125 +44218 -0.484832763671875 +44219 -0.729583740234375 +44220 -0.86688232421875 +44221 -0.870391845703125 +44222 -0.86859130859375 +44223 -0.86279296875 +44224 -0.817962646484375 +44225 -0.6116943359375 +44226 -0.3128662109375 +44227 0.039398193359375 +44228 0.422821044921875 +44229 0.805145263671875 +44230 0.870361328125 +44231 0.870361328125 +44232 0.860015869140625 +44233 0.727935791015625 +44234 0.48114013671875 +44235 0.2059326171875 +44236 -0.06103515625 +44237 -0.29913330078125 +44238 -0.516204833984375 +44239 -0.7252197265625 +44240 -0.85980224609375 +44241 -0.870391845703125 +44242 -0.870391845703125 +44243 -0.858062744140625 +44244 -0.673004150390625 +44245 -0.42694091796875 +44246 -0.2100830078125 +44247 -0.0362548828125 +44248 0.10943603515625 +44249 0.23516845703125 +44250 0.373687744140625 +44251 0.517791748046875 +44252 0.602783203125 +44253 0.635711669921875 +44254 0.655181884765625 +44255 0.65948486328125 +44256 0.651275634765625 +44257 0.61846923828125 +44258 0.53753662109375 +44259 0.404144287109375 +44260 0.22186279296875 +44261 0.003997802734375 +44262 -0.22100830078125 +44263 -0.42449951171875 +44264 -0.579833984375 +44265 -0.641876220703125 +44266 -0.6177978515625 +44267 -0.575531005859375 +44268 -0.526336669921875 +44269 -0.42645263671875 +44270 -0.2581787109375 +44271 -0.068695068359375 +44272 0.09222412109375 +44273 0.232147216796875 +44274 0.3509521484375 +44275 0.410064697265625 +44276 0.372955322265625 +44277 0.2554931640625 +44278 0.10711669921875 +44279 -0.052886962890625 +44280 -0.186279296875 +44281 -0.23291015625 +44282 -0.209442138671875 +44283 -0.174163818359375 +44284 -0.126739501953125 +44285 -0.048126220703125 +44286 0.0426025390625 +44287 0.10748291015625 +44288 0.1409912109375 +44289 0.19708251953125 +44290 0.273651123046875 +44291 0.31768798828125 +44292 0.341094970703125 +44293 0.368011474609375 +44294 0.37249755859375 +44295 0.30072021484375 +44296 0.1517333984375 +44297 -0.01470947265625 +44298 -0.1883544921875 +44299 -0.372711181640625 +44300 -0.51397705078125 +44301 -0.57177734375 +44302 -0.53948974609375 +44303 -0.43511962890625 +44304 -0.2962646484375 +44305 -0.161102294921875 +44306 -0.0435791015625 +44307 0.060394287109375 +44308 0.13665771484375 +44309 0.170135498046875 +44310 0.16552734375 +44311 0.15728759765625 +44312 0.150787353515625 +44313 0.12200927734375 +44314 0.080108642578125 +44315 0.05126953125 +44316 0.062896728515625 +44317 0.09271240234375 +44318 0.092987060546875 +44319 0.07855224609375 +44320 0.06427001953125 +44321 0.0347900390625 +44322 -0.01171875 +44323 -0.056060791015625 +44324 -0.055511474609375 +44325 -0.010467529296875 +44326 0.02508544921875 +44327 0.025665283203125 +44328 0.017333984375 +44329 0.00189208984375 +44330 -0.03173828125 +44331 -0.071502685546875 +44332 -0.13543701171875 +44333 -0.219970703125 +44334 -0.300506591796875 +44335 -0.376312255859375 +44336 -0.416107177734375 +44337 -0.371124267578125 +44338 -0.242279052734375 +44339 -0.069732666015625 +44340 0.125640869140625 +44341 0.31268310546875 +44342 0.45501708984375 +44343 0.554779052734375 +44344 0.61065673828125 +44345 0.610931396484375 +44346 0.531463623046875 +44347 0.3883056640625 +44348 0.23468017578125 +44349 0.095245361328125 +44350 -0.00396728515625 +44351 -0.04852294921875 +44352 -0.055145263671875 +44353 -0.0758056640625 +44354 -0.138702392578125 +44355 -0.209197998046875 +44356 -0.289031982421875 +44357 -0.37884521484375 +44358 -0.456329345703125 +44359 -0.51641845703125 +44360 -0.519287109375 +44361 -0.458251953125 +44362 -0.384796142578125 +44363 -0.323699951171875 +44364 -0.269287109375 +44365 -0.1951904296875 +44366 -0.100006103515625 +44367 -0.01055908203125 +44368 0.1033935546875 +44369 0.24908447265625 +44370 0.373199462890625 +44371 0.45806884765625 +44372 0.511474609375 +44373 0.565399169921875 +44374 0.61138916015625 +44375 0.5897216796875 +44376 0.4906005859375 +44377 0.33148193359375 +44378 0.147796630859375 +44379 -0.01873779296875 +44380 -0.140289306640625 +44381 -0.191986083984375 +44382 -0.184295654296875 +44383 -0.161834716796875 +44384 -0.166595458984375 +44385 -0.19390869140625 +44386 -0.22442626953125 +44387 -0.279754638671875 +44388 -0.3389892578125 +44389 -0.3543701171875 +44390 -0.348175048828125 +44391 -0.32598876953125 +44392 -0.2581787109375 +44393 -0.139801025390625 +44394 0.014617919921875 +44395 0.144378662109375 +44396 0.221038818359375 +44397 0.27069091796875 +44398 0.294036865234375 +44399 0.311767578125 +44400 0.339141845703125 +44401 0.360260009765625 +44402 0.360504150390625 +44403 0.308380126953125 +44404 0.18170166015625 +44405 0.0047607421875 +44406 -0.17559814453125 +44407 -0.3143310546875 +44408 -0.36785888671875 +44409 -0.36248779296875 +44410 -0.343536376953125 +44411 -0.3018798828125 +44412 -0.231414794921875 +44413 -0.117645263671875 +44414 0.007049560546875 +44415 0.087982177734375 +44416 0.13946533203125 +44417 0.17425537109375 +44418 0.188201904296875 +44419 0.171234130859375 +44420 0.118438720703125 +44421 0.05706787109375 +44422 -0.010711669921875 +44423 -0.0914306640625 +44424 -0.162322998046875 +44425 -0.194549560546875 +44426 -0.1492919921875 +44427 -0.02166748046875 +44428 0.124053955078125 +44429 0.211151123046875 +44430 0.240447998046875 +44431 0.242218017578125 +44432 0.2257080078125 +44433 0.194366455078125 +44434 0.115509033203125 +44435 0.0128173828125 +44436 -0.053802490234375 +44437 -0.110626220703125 +44438 -0.199493408203125 +44439 -0.29437255859375 +44440 -0.33221435546875 +44441 -0.27972412109375 +44442 -0.185333251953125 +44443 -0.128204345703125 +44444 -0.115692138671875 +44445 -0.116455078125 +44446 -0.105926513671875 +44447 -0.053955078125 +44448 0.048797607421875 +44449 0.157318115234375 +44450 0.212005615234375 +44451 0.218475341796875 +44452 0.23724365234375 +44453 0.30535888671875 +44454 0.38128662109375 +44455 0.404449462890625 +44456 0.3944091796875 +44457 0.3885498046875 +44458 0.362640380859375 +44459 0.27362060546875 +44460 0.11712646484375 +44461 -0.054901123046875 +44462 -0.19085693359375 +44463 -0.28570556640625 +44464 -0.339263916015625 +44465 -0.3775634765625 +44466 -0.445709228515625 +44467 -0.535064697265625 +44468 -0.629058837890625 +44469 -0.697601318359375 +44470 -0.70391845703125 +44471 -0.6424560546875 +44472 -0.491241455078125 +44473 -0.265716552734375 +44474 -0.023712158203125 +44475 0.201751708984375 +44476 0.375823974609375 +44477 0.485076904296875 +44478 0.56884765625 +44479 0.634765625 +44480 0.63763427734375 +44481 0.5660400390625 +44482 0.4720458984375 +44483 0.40692138671875 +44484 0.3778076171875 +44485 0.376953125 +44486 0.371978759765625 +44487 0.313140869140625 +44488 0.184417724609375 +44489 0.011199951171875 +44490 -0.171051025390625 +44491 -0.33740234375 +44492 -0.47198486328125 +44493 -0.560394287109375 +44494 -0.58056640625 +44495 -0.54754638671875 +44496 -0.508575439453125 +44497 -0.459503173828125 +44498 -0.394378662109375 +44499 -0.35260009765625 +44500 -0.31170654296875 +44501 -0.197418212890625 +44502 -0.007965087890625 +44503 0.207489013671875 +44504 0.409210205078125 +44505 0.57208251953125 +44506 0.66595458984375 +44507 0.65875244140625 +44508 0.56744384765625 +44509 0.431396484375 +44510 0.29443359375 +44511 0.182464599609375 +44512 0.06365966796875 +44513 -0.075958251953125 +44514 -0.189422607421875 +44515 -0.271942138671875 +44516 -0.342529296875 +44517 -0.364166259765625 +44518 -0.327239990234375 +44519 -0.2769775390625 +44520 -0.253692626953125 +44521 -0.24365234375 +44522 -0.1983642578125 +44523 -0.116241455078125 +44524 -0.036834716796875 +44525 0.034881591796875 +44526 0.09124755859375 +44527 0.10888671875 +44528 0.125518798828125 +44529 0.15771484375 +44530 0.17828369140625 +44531 0.17108154296875 +44532 0.129974365234375 +44533 0.082427978515625 +44534 0.027679443359375 +44535 -0.065643310546875 +44536 -0.15936279296875 +44537 -0.21307373046875 +44538 -0.234649658203125 +44539 -0.2001953125 +44540 -0.119171142578125 +44541 -0.024749755859375 +44542 0.085784912109375 +44543 0.178131103515625 +44544 0.215576171875 +44545 0.211456298828125 +44546 0.17523193359375 +44547 0.128753662109375 +44548 0.1019287109375 +44549 0.0743408203125 +44550 0.04327392578125 +44551 0.038177490234375 +44552 0.076263427734375 +44553 0.14105224609375 +44554 0.186431884765625 +44555 0.188812255859375 +44556 0.1390380859375 +44557 0.041778564453125 +44558 -0.079437255859375 +44559 -0.219390869140625 +44560 -0.367828369140625 +44561 -0.494873046875 +44562 -0.556243896484375 +44563 -0.508697509765625 +44564 -0.3756103515625 +44565 -0.218902587890625 +44566 -0.063751220703125 +44567 0.091552734375 +44568 0.23602294921875 +44569 0.342987060546875 +44570 0.39520263671875 +44571 0.389373779296875 +44572 0.324249267578125 +44573 0.224090576171875 +44574 0.124267578125 +44575 0.037078857421875 +44576 -0.010101318359375 +44577 -0.019439697265625 +44578 -0.022796630859375 +44579 -0.001556396484375 +44580 0.056304931640625 +44581 0.106719970703125 +44582 0.096893310546875 +44583 0.042694091796875 +44584 -0.018035888671875 +44585 -0.07586669921875 +44586 -0.11944580078125 +44587 -0.15972900390625 +44588 -0.202606201171875 +44589 -0.24859619140625 +44590 -0.30517578125 +44591 -0.36212158203125 +44592 -0.39141845703125 +44593 -0.35528564453125 +44594 -0.249969482421875 +44595 -0.092864990234375 +44596 0.08905029296875 +44597 0.2352294921875 +44598 0.318817138671875 +44599 0.358642578125 +44600 0.347747802734375 +44601 0.28564453125 +44602 0.223175048828125 +44603 0.196746826171875 +44604 0.179840087890625 +44605 0.155548095703125 +44606 0.151214599609375 +44607 0.156951904296875 +44608 0.13177490234375 +44609 0.100799560546875 +44610 0.087127685546875 +44611 0.05487060546875 +44612 -0.009002685546875 +44613 -0.10400390625 +44614 -0.229400634765625 +44615 -0.35552978515625 +44616 -0.441925048828125 +44617 -0.473846435546875 +44618 -0.464813232421875 +44619 -0.419097900390625 +44620 -0.334320068359375 +44621 -0.227935791015625 +44622 -0.12347412109375 +44623 -0.02764892578125 +44624 0.077667236328125 +44625 0.2132568359375 +44626 0.38885498046875 +44627 0.582794189453125 +44628 0.734039306640625 +44629 0.800140380859375 +44630 0.7783203125 +44631 0.6651611328125 +44632 0.45965576171875 +44633 0.199188232421875 +44634 -0.050689697265625 +44635 -0.23297119140625 +44636 -0.33013916015625 +44637 -0.368408203125 +44638 -0.378936767578125 +44639 -0.376983642578125 +44640 -0.37969970703125 +44641 -0.391510009765625 +44642 -0.385345458984375 +44643 -0.3419189453125 +44644 -0.28289794921875 +44645 -0.251617431640625 +44646 -0.266143798828125 +44647 -0.273345947265625 +44648 -0.216796875 +44649 -0.128265380859375 +44650 -0.068145751953125 +44651 -0.0430908203125 +44652 -0.024444580078125 +44653 0.020721435546875 +44654 0.124481201171875 +44655 0.25787353515625 +44656 0.379119873046875 +44657 0.47991943359375 +44658 0.5281982421875 +44659 0.511138916015625 +44660 0.456207275390625 +44661 0.407470703125 +44662 0.383758544921875 +44663 0.35687255859375 +44664 0.31182861328125 +44665 0.250885009765625 +44666 0.1654052734375 +44667 0.035247802734375 +44668 -0.142059326171875 +44669 -0.33563232421875 +44670 -0.5345458984375 +44671 -0.72186279296875 +44672 -0.836669921875 +44673 -0.8326416015625 +44674 -0.7296142578125 +44675 -0.582550048828125 +44676 -0.440093994140625 +44677 -0.324310302734375 +44678 -0.20147705078125 +44679 -0.044647216796875 +44680 0.103973388671875 +44681 0.202392578125 +44682 0.264495849609375 +44683 0.338897705078125 +44684 0.443817138671875 +44685 0.545074462890625 +44686 0.6173095703125 +44687 0.6524658203125 +44688 0.66339111328125 +44689 0.6561279296875 +44690 0.606781005859375 +44691 0.501190185546875 +44692 0.352783203125 +44693 0.176544189453125 +44694 -0.034820556640625 +44695 -0.258209228515625 +44696 -0.44244384765625 +44697 -0.5753173828125 +44698 -0.65203857421875 +44699 -0.641632080078125 +44700 -0.562164306640625 +44701 -0.458038330078125 +44702 -0.350555419921875 +44703 -0.260528564453125 +44704 -0.192108154296875 +44705 -0.141937255859375 +44706 -0.1021728515625 +44707 -0.062896728515625 +44708 -0.011932373046875 +44709 0.062835693359375 +44710 0.148712158203125 +44711 0.241729736328125 +44712 0.34912109375 +44713 0.457305908203125 +44714 0.54388427734375 +44715 0.5728759765625 +44716 0.506591796875 +44717 0.351226806640625 +44718 0.146514892578125 +44719 -0.05523681640625 +44720 -0.21624755859375 +44721 -0.334930419921875 +44722 -0.402984619140625 +44723 -0.4412841796875 +44724 -0.49578857421875 +44725 -0.5601806640625 +44726 -0.600738525390625 +44727 -0.584228515625 +44728 -0.47930908203125 +44729 -0.27935791015625 +44730 -0.0089111328125 +44731 0.268798828125 +44732 0.482818603515625 +44733 0.60369873046875 +44734 0.650421142578125 +44735 0.66400146484375 +44736 0.6414794921875 +44737 0.572540283203125 +44738 0.498138427734375 +44739 0.439453125 +44740 0.375518798828125 +44741 0.274505615234375 +44742 0.1087646484375 +44743 -0.099395751953125 +44744 -0.3182373046875 +44745 -0.5489501953125 +44746 -0.7738037109375 +44747 -0.86383056640625 +44748 -0.870391845703125 +44749 -0.86895751953125 +44750 -0.861053466796875 +44751 -0.765869140625 +44752 -0.5301513671875 +44753 -0.214691162109375 +44754 0.137359619140625 +44755 0.474822998046875 +44756 0.76239013671875 +44757 0.867462158203125 +44758 0.870361328125 +44759 0.86480712890625 +44760 0.831817626953125 +44761 0.677581787109375 +44762 0.495880126953125 +44763 0.30767822265625 +44764 0.116180419921875 +44765 -0.110748291015625 +44766 -0.381805419921875 +44767 -0.6572265625 +44768 -0.857421875 +44769 -0.870391845703125 +44770 -0.870391845703125 +44771 -0.86444091796875 +44772 -0.85723876953125 +44773 -0.790008544921875 +44774 -0.62847900390625 +44775 -0.3956298828125 +44776 -0.126708984375 +44777 0.150115966796875 +44778 0.424041748046875 +44779 0.670623779296875 +44780 0.854522705078125 +44781 0.866485595703125 +44782 0.86920166015625 +44783 0.8653564453125 +44784 0.857147216796875 +44785 0.766845703125 +44786 0.628509521484375 +44787 0.462127685546875 +44788 0.297210693359375 +44789 0.14862060546875 +44790 -0.00537109375 +44791 -0.15753173828125 +44792 -0.31304931640625 +44793 -0.48876953125 +44794 -0.6416015625 +44795 -0.751373291015625 +44796 -0.84619140625 +44797 -0.861297607421875 +44798 -0.863250732421875 +44799 -0.856597900390625 +44800 -0.7498779296875 +44801 -0.624542236328125 +44802 -0.47808837890625 +44803 -0.253387451171875 +44804 0.003692626953125 +44805 0.2257080078125 +44806 0.427154541015625 +44807 0.643218994140625 +44808 0.855926513671875 +44809 0.870361328125 +44810 0.870361328125 +44811 0.862762451171875 +44812 0.79669189453125 +44813 0.595794677734375 +44814 0.362152099609375 +44815 0.1270751953125 +44816 -0.086944580078125 +44817 -0.2784423828125 +44818 -0.484832763671875 +44819 -0.729583740234375 +44820 -0.86688232421875 +44821 -0.870391845703125 +44822 -0.86859130859375 +44823 -0.86279296875 +44824 -0.817962646484375 +44825 -0.6116943359375 +44826 -0.3128662109375 +44827 0.039398193359375 +44828 0.422821044921875 +44829 0.805145263671875 +44830 0.870361328125 +44831 0.870361328125 +44832 0.860015869140625 +44833 0.727935791015625 +44834 0.48114013671875 +44835 0.2059326171875 +44836 -0.06103515625 +44837 -0.29913330078125 +44838 -0.516204833984375 +44839 -0.7252197265625 +44840 -0.85980224609375 +44841 -0.870391845703125 +44842 -0.870391845703125 +44843 -0.858062744140625 +44844 -0.673004150390625 +44845 -0.42694091796875 +44846 -0.2100830078125 +44847 -0.0362548828125 +44848 0.10943603515625 +44849 0.23516845703125 +44850 0.373687744140625 +44851 0.517791748046875 +44852 0.602783203125 +44853 0.635711669921875 +44854 0.655181884765625 +44855 0.65948486328125 +44856 0.651275634765625 +44857 0.61846923828125 +44858 0.53753662109375 +44859 0.404144287109375 +44860 0.22186279296875 +44861 0.003997802734375 +44862 -0.22100830078125 +44863 -0.42449951171875 +44864 -0.579833984375 +44865 -0.641876220703125 +44866 -0.6177978515625 +44867 -0.575531005859375 +44868 -0.526336669921875 +44869 -0.42645263671875 +44870 -0.2581787109375 +44871 -0.068695068359375 +44872 0.09222412109375 +44873 0.232147216796875 +44874 0.3509521484375 +44875 0.410064697265625 +44876 0.372955322265625 +44877 0.2554931640625 +44878 0.10711669921875 +44879 -0.052886962890625 +44880 -0.186279296875 +44881 -0.23291015625 +44882 -0.209442138671875 +44883 -0.174163818359375 +44884 -0.126739501953125 +44885 -0.048126220703125 +44886 0.0426025390625 +44887 0.10748291015625 +44888 0.1409912109375 +44889 0.19708251953125 +44890 0.273651123046875 +44891 0.31768798828125 +44892 0.341094970703125 +44893 0.368011474609375 +44894 0.37249755859375 +44895 0.30072021484375 +44896 0.1517333984375 +44897 -0.01470947265625 +44898 -0.1883544921875 +44899 -0.372711181640625 +44900 -0.51397705078125 +44901 -0.57177734375 +44902 -0.53948974609375 +44903 -0.43511962890625 +44904 -0.2962646484375 +44905 -0.161102294921875 +44906 -0.0435791015625 +44907 0.060394287109375 +44908 0.13665771484375 +44909 0.170135498046875 +44910 0.16552734375 +44911 0.15728759765625 +44912 0.150787353515625 +44913 0.12200927734375 +44914 0.080108642578125 +44915 0.05126953125 +44916 0.062896728515625 +44917 0.09271240234375 +44918 0.092987060546875 +44919 0.07855224609375 +44920 0.06427001953125 +44921 0.0347900390625 +44922 -0.01171875 +44923 -0.056060791015625 +44924 -0.055511474609375 +44925 -0.010467529296875 +44926 0.02508544921875 +44927 0.025665283203125 +44928 0.017333984375 +44929 0.00189208984375 +44930 -0.03173828125 +44931 -0.071502685546875 +44932 -0.13543701171875 +44933 -0.219970703125 +44934 -0.300506591796875 +44935 -0.376312255859375 +44936 -0.416107177734375 +44937 -0.371124267578125 +44938 -0.242279052734375 +44939 -0.069732666015625 +44940 0.125640869140625 +44941 0.31268310546875 +44942 0.45501708984375 +44943 0.554779052734375 +44944 0.61065673828125 +44945 0.610931396484375 +44946 0.531463623046875 +44947 0.3883056640625 +44948 0.23468017578125 +44949 0.095245361328125 +44950 -0.00396728515625 +44951 -0.04852294921875 +44952 -0.055145263671875 +44953 -0.0758056640625 +44954 -0.138702392578125 +44955 -0.209197998046875 +44956 -0.289031982421875 +44957 -0.37884521484375 +44958 -0.456329345703125 +44959 -0.51641845703125 +44960 -0.519287109375 +44961 -0.458251953125 +44962 -0.384796142578125 +44963 -0.323699951171875 +44964 -0.269287109375 +44965 -0.1951904296875 +44966 -0.100006103515625 +44967 -0.01055908203125 +44968 0.1033935546875 +44969 0.24908447265625 +44970 0.373199462890625 +44971 0.45806884765625 +44972 0.511474609375 +44973 0.565399169921875 +44974 0.61138916015625 +44975 0.5897216796875 +44976 0.4906005859375 +44977 0.33148193359375 +44978 0.147796630859375 +44979 -0.01873779296875 +44980 -0.140289306640625 +44981 -0.191986083984375 +44982 -0.184295654296875 +44983 -0.161834716796875 +44984 -0.166595458984375 +44985 -0.19390869140625 +44986 -0.22442626953125 +44987 -0.279754638671875 +44988 -0.3389892578125 +44989 -0.3543701171875 +44990 -0.348175048828125 +44991 -0.32598876953125 +44992 -0.2581787109375 +44993 -0.139801025390625 +44994 0.014617919921875 +44995 0.144378662109375 +44996 0.221038818359375 +44997 0.27069091796875 +44998 0.294036865234375 +44999 0.311767578125 +45000 0.339141845703125 +45001 0.360260009765625 +45002 0.360504150390625 +45003 0.308380126953125 +45004 0.18170166015625 +45005 0.0047607421875 +45006 -0.17559814453125 +45007 -0.3143310546875 +45008 -0.36785888671875 +45009 -0.36248779296875 +45010 -0.343536376953125 +45011 -0.3018798828125 +45012 -0.231414794921875 +45013 -0.117645263671875 +45014 0.007049560546875 +45015 0.087982177734375 +45016 0.13946533203125 +45017 0.17425537109375 +45018 0.188201904296875 +45019 0.171234130859375 +45020 0.118438720703125 +45021 0.05706787109375 +45022 -0.010711669921875 +45023 -0.0914306640625 +45024 -0.162322998046875 +45025 -0.194549560546875 +45026 -0.1492919921875 +45027 -0.02166748046875 +45028 0.124053955078125 +45029 0.211151123046875 +45030 0.240447998046875 +45031 0.242218017578125 +45032 0.2257080078125 +45033 0.194366455078125 +45034 0.115509033203125 +45035 0.0128173828125 +45036 -0.053802490234375 +45037 -0.110626220703125 +45038 -0.199493408203125 +45039 -0.29437255859375 +45040 -0.33221435546875 +45041 -0.27972412109375 +45042 -0.185333251953125 +45043 -0.128204345703125 +45044 -0.115692138671875 +45045 -0.116455078125 +45046 -0.105926513671875 +45047 -0.053955078125 +45048 0.048797607421875 +45049 0.157318115234375 +45050 0.212005615234375 +45051 0.218475341796875 +45052 0.23724365234375 +45053 0.30535888671875 +45054 0.38128662109375 +45055 0.404449462890625 +45056 0.3944091796875 +45057 0.3885498046875 +45058 0.362640380859375 +45059 0.27362060546875 +45060 0.11712646484375 +45061 -0.054901123046875 +45062 -0.19085693359375 +45063 -0.28570556640625 +45064 -0.339263916015625 +45065 -0.3775634765625 +45066 -0.445709228515625 +45067 -0.535064697265625 +45068 -0.629058837890625 +45069 -0.697601318359375 +45070 -0.70391845703125 +45071 -0.6424560546875 +45072 -0.491241455078125 +45073 -0.265716552734375 +45074 -0.023712158203125 +45075 0.201751708984375 +45076 0.375823974609375 +45077 0.485076904296875 +45078 0.56884765625 +45079 0.634765625 +45080 0.63763427734375 +45081 0.5660400390625 +45082 0.4720458984375 +45083 0.40692138671875 +45084 0.3778076171875 +45085 0.376953125 +45086 0.371978759765625 +45087 0.313140869140625 +45088 0.184417724609375 +45089 0.011199951171875 +45090 -0.171051025390625 +45091 -0.33740234375 +45092 -0.47198486328125 +45093 -0.560394287109375 +45094 -0.58056640625 +45095 -0.54754638671875 +45096 -0.508575439453125 +45097 -0.459503173828125 +45098 -0.394378662109375 +45099 -0.35260009765625 +45100 -0.31170654296875 +45101 -0.197418212890625 +45102 -0.007965087890625 +45103 0.207489013671875 +45104 0.409210205078125 +45105 0.57208251953125 +45106 0.66595458984375 +45107 0.65875244140625 +45108 0.56744384765625 +45109 0.431396484375 +45110 0.29443359375 +45111 0.182464599609375 +45112 0.06365966796875 +45113 -0.075958251953125 +45114 -0.189422607421875 +45115 -0.271942138671875 +45116 -0.342529296875 +45117 -0.364166259765625 +45118 -0.327239990234375 +45119 -0.2769775390625 +45120 -0.253692626953125 +45121 -0.24365234375 +45122 -0.1983642578125 +45123 -0.116241455078125 +45124 -0.036834716796875 +45125 0.034881591796875 +45126 0.09124755859375 +45127 0.10888671875 +45128 0.125518798828125 +45129 0.15771484375 +45130 0.17828369140625 +45131 0.17108154296875 +45132 0.129974365234375 +45133 0.082427978515625 +45134 0.027679443359375 +45135 -0.065643310546875 +45136 -0.15936279296875 +45137 -0.21307373046875 +45138 -0.234649658203125 +45139 -0.2001953125 +45140 -0.119171142578125 +45141 -0.024749755859375 +45142 0.085784912109375 +45143 0.178131103515625 +45144 0.215576171875 +45145 0.211456298828125 +45146 0.17523193359375 +45147 0.128753662109375 +45148 0.1019287109375 +45149 0.0743408203125 +45150 0.04327392578125 +45151 0.038177490234375 +45152 0.076263427734375 +45153 0.14105224609375 +45154 0.186431884765625 +45155 0.188812255859375 +45156 0.1390380859375 +45157 0.041778564453125 +45158 -0.079437255859375 +45159 -0.219390869140625 +45160 -0.367828369140625 +45161 -0.494873046875 +45162 -0.556243896484375 +45163 -0.508697509765625 +45164 -0.3756103515625 +45165 -0.218902587890625 +45166 -0.063751220703125 +45167 0.091552734375 +45168 0.23602294921875 +45169 0.342987060546875 +45170 0.39520263671875 +45171 0.389373779296875 +45172 0.324249267578125 +45173 0.224090576171875 +45174 0.124267578125 +45175 0.037078857421875 +45176 -0.010101318359375 +45177 -0.019439697265625 +45178 -0.022796630859375 +45179 -0.001556396484375 +45180 0.056304931640625 +45181 0.106719970703125 +45182 0.096893310546875 +45183 0.042694091796875 +45184 -0.018035888671875 +45185 -0.07586669921875 +45186 -0.11944580078125 +45187 -0.15972900390625 +45188 -0.202606201171875 +45189 -0.24859619140625 +45190 -0.30517578125 +45191 -0.36212158203125 +45192 -0.39141845703125 +45193 -0.35528564453125 +45194 -0.249969482421875 +45195 -0.092864990234375 +45196 0.08905029296875 +45197 0.2352294921875 +45198 0.318817138671875 +45199 0.358642578125 +45200 0.347747802734375 +45201 0.28564453125 +45202 0.223175048828125 +45203 0.196746826171875 +45204 0.179840087890625 +45205 0.155548095703125 +45206 0.151214599609375 +45207 0.156951904296875 +45208 0.13177490234375 +45209 0.100799560546875 +45210 0.087127685546875 +45211 0.05487060546875 +45212 -0.009002685546875 +45213 -0.10400390625 +45214 -0.229400634765625 +45215 -0.35552978515625 +45216 -0.441925048828125 +45217 -0.473846435546875 +45218 -0.464813232421875 +45219 -0.419097900390625 +45220 -0.334320068359375 +45221 -0.227935791015625 +45222 -0.12347412109375 +45223 -0.02764892578125 +45224 0.077667236328125 +45225 0.2132568359375 +45226 0.38885498046875 +45227 0.582794189453125 +45228 0.734039306640625 +45229 0.800140380859375 +45230 0.7783203125 +45231 0.6651611328125 +45232 0.45965576171875 +45233 0.199188232421875 +45234 -0.050689697265625 +45235 -0.23297119140625 +45236 -0.33013916015625 +45237 -0.368408203125 +45238 -0.378936767578125 +45239 -0.376983642578125 +45240 -0.37969970703125 +45241 -0.391510009765625 +45242 -0.385345458984375 +45243 -0.3419189453125 +45244 -0.28289794921875 +45245 -0.251617431640625 +45246 -0.266143798828125 +45247 -0.273345947265625 +45248 -0.216796875 +45249 -0.128265380859375 +45250 -0.068145751953125 +45251 -0.0430908203125 +45252 -0.024444580078125 +45253 0.020721435546875 +45254 0.124481201171875 +45255 0.25787353515625 +45256 0.379119873046875 +45257 0.47991943359375 +45258 0.5281982421875 +45259 0.511138916015625 +45260 0.456207275390625 +45261 0.407470703125 +45262 0.383758544921875 +45263 0.35687255859375 +45264 0.31182861328125 +45265 0.250885009765625 +45266 0.1654052734375 +45267 0.035247802734375 +45268 -0.142059326171875 +45269 -0.33563232421875 +45270 -0.5345458984375 +45271 -0.72186279296875 +45272 -0.836669921875 +45273 -0.8326416015625 +45274 -0.7296142578125 +45275 -0.582550048828125 +45276 -0.440093994140625 +45277 -0.324310302734375 +45278 -0.20147705078125 +45279 -0.044647216796875 +45280 0.103973388671875 +45281 0.202392578125 +45282 0.264495849609375 +45283 0.338897705078125 +45284 0.443817138671875 +45285 0.545074462890625 +45286 0.6173095703125 +45287 0.6524658203125 +45288 0.66339111328125 +45289 0.6561279296875 +45290 0.606781005859375 +45291 0.501190185546875 +45292 0.352783203125 +45293 0.176544189453125 +45294 -0.034820556640625 +45295 -0.258209228515625 +45296 -0.44244384765625 +45297 -0.5753173828125 +45298 -0.65203857421875 +45299 -0.641632080078125 +45300 -0.562164306640625 +45301 -0.458038330078125 +45302 -0.350555419921875 +45303 -0.260528564453125 +45304 -0.192108154296875 +45305 -0.141937255859375 +45306 -0.1021728515625 +45307 -0.062896728515625 +45308 -0.011932373046875 +45309 0.062835693359375 +45310 0.148712158203125 +45311 0.241729736328125 +45312 0.34912109375 +45313 0.457305908203125 +45314 0.54388427734375 +45315 0.5728759765625 +45316 0.506591796875 +45317 0.351226806640625 +45318 0.146514892578125 +45319 -0.05523681640625 +45320 -0.21624755859375 +45321 -0.334930419921875 +45322 -0.402984619140625 +45323 -0.4412841796875 +45324 -0.49578857421875 +45325 -0.5601806640625 +45326 -0.600738525390625 +45327 -0.584228515625 +45328 -0.47930908203125 +45329 -0.27935791015625 +45330 -0.0089111328125 +45331 0.268798828125 +45332 0.482818603515625 +45333 0.60369873046875 +45334 0.650421142578125 +45335 0.66400146484375 +45336 0.6414794921875 +45337 0.572540283203125 +45338 0.498138427734375 +45339 0.439453125 +45340 0.375518798828125 +45341 0.274505615234375 +45342 0.1087646484375 +45343 -0.099395751953125 +45344 -0.3182373046875 +45345 -0.5489501953125 +45346 -0.7738037109375 +45347 -0.86383056640625 +45348 -0.870391845703125 +45349 -0.86895751953125 +45350 -0.861053466796875 +45351 -0.765869140625 +45352 -0.5301513671875 +45353 -0.214691162109375 +45354 0.137359619140625 +45355 0.474822998046875 +45356 0.76239013671875 +45357 0.867462158203125 +45358 0.870361328125 +45359 0.86480712890625 +45360 0.831817626953125 +45361 0.677581787109375 +45362 0.495880126953125 +45363 0.30767822265625 +45364 0.116180419921875 +45365 -0.110748291015625 +45366 -0.381805419921875 +45367 -0.6572265625 +45368 -0.857421875 +45369 -0.870391845703125 +45370 -0.870391845703125 +45371 -0.86444091796875 +45372 -0.85723876953125 +45373 -0.790008544921875 +45374 -0.62847900390625 +45375 -0.3956298828125 +45376 -0.126708984375 +45377 0.150115966796875 +45378 0.424041748046875 +45379 0.670623779296875 +45380 0.854522705078125 +45381 0.866485595703125 +45382 0.86920166015625 +45383 0.8653564453125 +45384 0.857147216796875 +45385 0.766845703125 +45386 0.628509521484375 +45387 0.462127685546875 +45388 0.297210693359375 +45389 0.14862060546875 +45390 -0.00537109375 +45391 -0.15753173828125 +45392 -0.31304931640625 +45393 -0.48876953125 +45394 -0.6416015625 +45395 -0.751373291015625 +45396 -0.84619140625 +45397 -0.861297607421875 +45398 -0.863250732421875 +45399 -0.856597900390625 +45400 -0.7498779296875 +45401 -0.624542236328125 +45402 -0.47808837890625 +45403 -0.253387451171875 +45404 0.003692626953125 +45405 0.2257080078125 +45406 0.427154541015625 +45407 0.643218994140625 +45408 0.855926513671875 +45409 0.870361328125 +45410 0.870361328125 +45411 0.862762451171875 +45412 0.79669189453125 +45413 0.595794677734375 +45414 0.362152099609375 +45415 0.1270751953125 +45416 -0.086944580078125 +45417 -0.2784423828125 +45418 -0.484832763671875 +45419 -0.729583740234375 +45420 -0.86688232421875 +45421 -0.870391845703125 +45422 -0.86859130859375 +45423 -0.86279296875 +45424 -0.817962646484375 +45425 -0.6116943359375 +45426 -0.3128662109375 +45427 0.039398193359375 +45428 0.422821044921875 +45429 0.805145263671875 +45430 0.870361328125 +45431 0.870361328125 +45432 0.860015869140625 +45433 0.727935791015625 +45434 0.48114013671875 +45435 0.2059326171875 +45436 -0.06103515625 +45437 -0.29913330078125 +45438 -0.516204833984375 +45439 -0.7252197265625 +45440 -0.85980224609375 +45441 -0.870391845703125 +45442 -0.870391845703125 +45443 -0.858062744140625 +45444 -0.673004150390625 +45445 -0.42694091796875 +45446 -0.2100830078125 +45447 -0.0362548828125 +45448 0.10943603515625 +45449 0.23516845703125 +45450 0.373687744140625 +45451 0.517791748046875 +45452 0.602783203125 +45453 0.635711669921875 +45454 0.655181884765625 +45455 0.65948486328125 +45456 0.651275634765625 +45457 0.61846923828125 +45458 0.53753662109375 +45459 0.404144287109375 +45460 0.22186279296875 +45461 0.003997802734375 +45462 -0.22100830078125 +45463 -0.42449951171875 +45464 -0.579833984375 +45465 -0.641876220703125 +45466 -0.6177978515625 +45467 -0.575531005859375 +45468 -0.526336669921875 +45469 -0.42645263671875 +45470 -0.2581787109375 +45471 -0.068695068359375 +45472 0.09222412109375 +45473 0.232147216796875 +45474 0.3509521484375 +45475 0.410064697265625 +45476 0.372955322265625 +45477 0.2554931640625 +45478 0.10711669921875 +45479 -0.052886962890625 +45480 -0.186279296875 +45481 -0.23291015625 +45482 -0.209442138671875 +45483 -0.174163818359375 +45484 -0.126739501953125 +45485 -0.048126220703125 +45486 0.0426025390625 +45487 0.10748291015625 +45488 0.1409912109375 +45489 0.19708251953125 +45490 0.273651123046875 +45491 0.31768798828125 +45492 0.341094970703125 +45493 0.368011474609375 +45494 0.37249755859375 +45495 0.30072021484375 +45496 0.1517333984375 +45497 -0.01470947265625 +45498 -0.1883544921875 +45499 -0.372711181640625 +45500 -0.51397705078125 +45501 -0.57177734375 +45502 -0.53948974609375 +45503 -0.43511962890625 +45504 -0.2962646484375 +45505 -0.161102294921875 +45506 -0.0435791015625 +45507 0.060394287109375 +45508 0.13665771484375 +45509 0.170135498046875 +45510 0.16552734375 +45511 0.15728759765625 +45512 0.150787353515625 +45513 0.12200927734375 +45514 0.080108642578125 +45515 0.05126953125 +45516 0.062896728515625 +45517 0.09271240234375 +45518 0.092987060546875 +45519 0.07855224609375 +45520 0.06427001953125 +45521 0.0347900390625 +45522 -0.01171875 +45523 -0.056060791015625 +45524 -0.055511474609375 +45525 -0.010467529296875 +45526 0.02508544921875 +45527 0.025665283203125 +45528 0.017333984375 +45529 0.00189208984375 +45530 -0.03173828125 +45531 -0.071502685546875 +45532 -0.13543701171875 +45533 -0.219970703125 +45534 -0.300506591796875 +45535 -0.376312255859375 +45536 -0.416107177734375 +45537 -0.371124267578125 +45538 -0.242279052734375 +45539 -0.069732666015625 +45540 0.125640869140625 +45541 0.31268310546875 +45542 0.45501708984375 +45543 0.554779052734375 +45544 0.61065673828125 +45545 0.610931396484375 +45546 0.531463623046875 +45547 0.3883056640625 +45548 0.23468017578125 +45549 0.095245361328125 +45550 -0.00396728515625 +45551 -0.04852294921875 +45552 -0.055145263671875 +45553 -0.0758056640625 +45554 -0.138702392578125 +45555 -0.209197998046875 +45556 -0.289031982421875 +45557 -0.37884521484375 +45558 -0.456329345703125 +45559 -0.51641845703125 +45560 -0.519287109375 +45561 -0.458251953125 +45562 -0.384796142578125 +45563 -0.323699951171875 +45564 -0.269287109375 +45565 -0.1951904296875 +45566 -0.100006103515625 +45567 -0.01055908203125 +45568 0.1033935546875 +45569 0.24908447265625 +45570 0.373199462890625 +45571 0.45806884765625 +45572 0.511474609375 +45573 0.565399169921875 +45574 0.61138916015625 +45575 0.5897216796875 +45576 0.4906005859375 +45577 0.33148193359375 +45578 0.147796630859375 +45579 -0.01873779296875 +45580 -0.140289306640625 +45581 -0.191986083984375 +45582 -0.184295654296875 +45583 -0.161834716796875 +45584 -0.166595458984375 +45585 -0.19390869140625 +45586 -0.22442626953125 +45587 -0.279754638671875 +45588 -0.3389892578125 +45589 -0.3543701171875 +45590 -0.348175048828125 +45591 -0.32598876953125 +45592 -0.2581787109375 +45593 -0.139801025390625 +45594 0.014617919921875 +45595 0.144378662109375 +45596 0.221038818359375 +45597 0.27069091796875 +45598 0.294036865234375 +45599 0.311767578125 +45600 0.339141845703125 +45601 0.360260009765625 +45602 0.360504150390625 +45603 0.308380126953125 +45604 0.18170166015625 +45605 0.0047607421875 +45606 -0.17559814453125 +45607 -0.3143310546875 +45608 -0.36785888671875 +45609 -0.36248779296875 +45610 -0.343536376953125 +45611 -0.3018798828125 +45612 -0.231414794921875 +45613 -0.117645263671875 +45614 0.007049560546875 +45615 0.087982177734375 +45616 0.13946533203125 +45617 0.17425537109375 +45618 0.188201904296875 +45619 0.171234130859375 +45620 0.118438720703125 +45621 0.05706787109375 +45622 -0.010711669921875 +45623 -0.0914306640625 +45624 -0.162322998046875 +45625 -0.194549560546875 +45626 -0.1492919921875 +45627 -0.02166748046875 +45628 0.124053955078125 +45629 0.211151123046875 +45630 0.240447998046875 +45631 0.242218017578125 +45632 0.2257080078125 +45633 0.194366455078125 +45634 0.115509033203125 +45635 0.0128173828125 +45636 -0.053802490234375 +45637 -0.110626220703125 +45638 -0.199493408203125 +45639 -0.29437255859375 +45640 -0.33221435546875 +45641 -0.27972412109375 +45642 -0.185333251953125 +45643 -0.128204345703125 +45644 -0.115692138671875 +45645 -0.116455078125 +45646 -0.105926513671875 +45647 -0.053955078125 +45648 0.048797607421875 +45649 0.157318115234375 +45650 0.212005615234375 +45651 0.218475341796875 +45652 0.23724365234375 +45653 0.30535888671875 +45654 0.38128662109375 +45655 0.404449462890625 +45656 0.3944091796875 +45657 0.3885498046875 +45658 0.362640380859375 +45659 0.27362060546875 +45660 0.11712646484375 +45661 -0.054901123046875 +45662 -0.19085693359375 +45663 -0.28570556640625 +45664 -0.339263916015625 +45665 -0.3775634765625 +45666 -0.445709228515625 +45667 -0.535064697265625 +45668 -0.629058837890625 +45669 -0.697601318359375 +45670 -0.70391845703125 +45671 -0.6424560546875 +45672 -0.491241455078125 +45673 -0.265716552734375 +45674 -0.023712158203125 +45675 0.201751708984375 +45676 0.375823974609375 +45677 0.485076904296875 +45678 0.56884765625 +45679 0.634765625 +45680 0.63763427734375 +45681 0.5660400390625 +45682 0.4720458984375 +45683 0.40692138671875 +45684 0.3778076171875 +45685 0.376953125 +45686 0.371978759765625 +45687 0.313140869140625 +45688 0.184417724609375 +45689 0.011199951171875 +45690 -0.171051025390625 +45691 -0.33740234375 +45692 -0.47198486328125 +45693 -0.560394287109375 +45694 -0.58056640625 +45695 -0.54754638671875 +45696 -0.508575439453125 +45697 -0.459503173828125 +45698 -0.394378662109375 +45699 -0.35260009765625 +45700 -0.31170654296875 +45701 -0.197418212890625 +45702 -0.007965087890625 +45703 0.207489013671875 +45704 0.409210205078125 +45705 0.57208251953125 +45706 0.66595458984375 +45707 0.65875244140625 +45708 0.56744384765625 +45709 0.431396484375 +45710 0.29443359375 +45711 0.182464599609375 +45712 0.06365966796875 +45713 -0.075958251953125 +45714 -0.189422607421875 +45715 -0.271942138671875 +45716 -0.342529296875 +45717 -0.364166259765625 +45718 -0.327239990234375 +45719 -0.2769775390625 +45720 -0.253692626953125 +45721 -0.24365234375 +45722 -0.1983642578125 +45723 -0.116241455078125 +45724 -0.036834716796875 +45725 0.034881591796875 +45726 0.09124755859375 +45727 0.10888671875 +45728 0.125518798828125 +45729 0.15771484375 +45730 0.17828369140625 +45731 0.17108154296875 +45732 0.129974365234375 +45733 0.082427978515625 +45734 0.027679443359375 +45735 -0.065643310546875 +45736 -0.15936279296875 +45737 -0.21307373046875 +45738 -0.234649658203125 +45739 -0.2001953125 +45740 -0.119171142578125 +45741 -0.024749755859375 +45742 0.085784912109375 +45743 0.178131103515625 +45744 0.215576171875 +45745 0.211456298828125 +45746 0.17523193359375 +45747 0.128753662109375 +45748 0.1019287109375 +45749 0.0743408203125 +45750 0.04327392578125 +45751 0.038177490234375 +45752 0.076263427734375 +45753 0.14105224609375 +45754 0.186431884765625 +45755 0.188812255859375 +45756 0.1390380859375 +45757 0.041778564453125 +45758 -0.079437255859375 +45759 -0.219390869140625 +45760 -0.367828369140625 +45761 -0.494873046875 +45762 -0.556243896484375 +45763 -0.508697509765625 +45764 -0.3756103515625 +45765 -0.218902587890625 +45766 -0.063751220703125 +45767 0.091552734375 +45768 0.23602294921875 +45769 0.342987060546875 +45770 0.39520263671875 +45771 0.389373779296875 +45772 0.324249267578125 +45773 0.224090576171875 +45774 0.124267578125 +45775 0.037078857421875 +45776 -0.010101318359375 +45777 -0.019439697265625 +45778 -0.022796630859375 +45779 -0.001556396484375 +45780 0.056304931640625 +45781 0.106719970703125 +45782 0.096893310546875 +45783 0.042694091796875 +45784 -0.018035888671875 +45785 -0.07586669921875 +45786 -0.11944580078125 +45787 -0.15972900390625 +45788 -0.202606201171875 +45789 -0.24859619140625 +45790 -0.30517578125 +45791 -0.36212158203125 +45792 -0.39141845703125 +45793 -0.35528564453125 +45794 -0.249969482421875 +45795 -0.092864990234375 +45796 0.08905029296875 +45797 0.2352294921875 +45798 0.318817138671875 +45799 0.358642578125 +45800 0.347747802734375 +45801 0.28564453125 +45802 0.223175048828125 +45803 0.196746826171875 +45804 0.179840087890625 +45805 0.155548095703125 +45806 0.151214599609375 +45807 0.156951904296875 +45808 0.13177490234375 +45809 0.100799560546875 +45810 0.087127685546875 +45811 0.05487060546875 +45812 -0.009002685546875 +45813 -0.10400390625 +45814 -0.229400634765625 +45815 -0.35552978515625 +45816 -0.441925048828125 +45817 -0.473846435546875 +45818 -0.464813232421875 +45819 -0.419097900390625 +45820 -0.334320068359375 +45821 -0.227935791015625 +45822 -0.12347412109375 +45823 -0.02764892578125 +45824 0.077667236328125 +45825 0.2132568359375 +45826 0.38885498046875 +45827 0.582794189453125 +45828 0.734039306640625 +45829 0.800140380859375 +45830 0.7783203125 +45831 0.6651611328125 +45832 0.45965576171875 +45833 0.199188232421875 +45834 -0.050689697265625 +45835 -0.23297119140625 +45836 -0.33013916015625 +45837 -0.368408203125 +45838 -0.378936767578125 +45839 -0.376983642578125 +45840 -0.37969970703125 +45841 -0.391510009765625 +45842 -0.385345458984375 +45843 -0.3419189453125 +45844 -0.28289794921875 +45845 -0.251617431640625 +45846 -0.266143798828125 +45847 -0.273345947265625 +45848 -0.216796875 +45849 -0.128265380859375 +45850 -0.068145751953125 +45851 -0.0430908203125 +45852 -0.024444580078125 +45853 0.020721435546875 +45854 0.124481201171875 +45855 0.25787353515625 +45856 0.379119873046875 +45857 0.47991943359375 +45858 0.5281982421875 +45859 0.511138916015625 +45860 0.456207275390625 +45861 0.407470703125 +45862 0.383758544921875 +45863 0.35687255859375 +45864 0.31182861328125 +45865 0.250885009765625 +45866 0.1654052734375 +45867 0.035247802734375 +45868 -0.142059326171875 +45869 -0.33563232421875 +45870 -0.5345458984375 +45871 -0.72186279296875 +45872 -0.836669921875 +45873 -0.8326416015625 +45874 -0.7296142578125 +45875 -0.582550048828125 +45876 -0.440093994140625 +45877 -0.324310302734375 +45878 -0.20147705078125 +45879 -0.044647216796875 +45880 0.103973388671875 +45881 0.202392578125 +45882 0.264495849609375 +45883 0.338897705078125 +45884 0.443817138671875 +45885 0.545074462890625 +45886 0.6173095703125 +45887 0.6524658203125 +45888 0.66339111328125 +45889 0.6561279296875 +45890 0.606781005859375 +45891 0.501190185546875 +45892 0.352783203125 +45893 0.176544189453125 +45894 -0.034820556640625 +45895 -0.258209228515625 +45896 -0.44244384765625 +45897 -0.5753173828125 +45898 -0.65203857421875 +45899 -0.641632080078125 +45900 -0.562164306640625 +45901 -0.458038330078125 +45902 -0.350555419921875 +45903 -0.260528564453125 +45904 -0.192108154296875 +45905 -0.141937255859375 +45906 -0.1021728515625 +45907 -0.062896728515625 +45908 -0.011932373046875 +45909 0.062835693359375 +45910 0.148712158203125 +45911 0.241729736328125 +45912 0.34912109375 +45913 0.457305908203125 +45914 0.54388427734375 +45915 0.5728759765625 +45916 0.506591796875 +45917 0.351226806640625 +45918 0.146514892578125 +45919 -0.05523681640625 +45920 -0.21624755859375 +45921 -0.334930419921875 +45922 -0.402984619140625 +45923 -0.4412841796875 +45924 -0.49578857421875 +45925 -0.5601806640625 +45926 -0.600738525390625 +45927 -0.584228515625 +45928 -0.47930908203125 +45929 -0.27935791015625 +45930 -0.0089111328125 +45931 0.268798828125 +45932 0.482818603515625 +45933 0.60369873046875 +45934 0.650421142578125 +45935 0.66400146484375 +45936 0.6414794921875 +45937 0.572540283203125 +45938 0.498138427734375 +45939 0.439453125 +45940 0.375518798828125 +45941 0.274505615234375 +45942 0.1087646484375 +45943 -0.099395751953125 +45944 -0.3182373046875 +45945 -0.5489501953125 +45946 -0.7738037109375 +45947 -0.86383056640625 +45948 -0.870391845703125 +45949 -0.86895751953125 +45950 -0.861053466796875 +45951 -0.765869140625 +45952 -0.5301513671875 +45953 -0.214691162109375 +45954 0.137359619140625 +45955 0.474822998046875 +45956 0.76239013671875 +45957 0.867462158203125 +45958 0.870361328125 +45959 0.86480712890625 +45960 0.831817626953125 +45961 0.677581787109375 +45962 0.495880126953125 +45963 0.30767822265625 +45964 0.116180419921875 +45965 -0.110748291015625 +45966 -0.381805419921875 +45967 -0.6572265625 +45968 -0.857421875 +45969 -0.870391845703125 +45970 -0.870391845703125 +45971 -0.86444091796875 +45972 -0.85723876953125 +45973 -0.790008544921875 +45974 -0.62847900390625 +45975 -0.3956298828125 +45976 -0.126708984375 +45977 0.150115966796875 +45978 0.424041748046875 +45979 0.670623779296875 +45980 0.854522705078125 +45981 0.866485595703125 +45982 0.86920166015625 +45983 0.8653564453125 +45984 0.857147216796875 +45985 0.766845703125 +45986 0.628509521484375 +45987 0.462127685546875 +45988 0.297210693359375 +45989 0.14862060546875 +45990 -0.00537109375 +45991 -0.15753173828125 +45992 -0.31304931640625 +45993 -0.48876953125 +45994 -0.6416015625 +45995 -0.751373291015625 +45996 -0.84619140625 +45997 -0.861297607421875 +45998 -0.863250732421875 +45999 -0.856597900390625 +46000 -0.7498779296875 +46001 -0.624542236328125 +46002 -0.47808837890625 +46003 -0.253387451171875 +46004 0.003692626953125 +46005 0.2257080078125 +46006 0.427154541015625 +46007 0.643218994140625 +46008 0.855926513671875 +46009 0.870361328125 +46010 0.870361328125 +46011 0.862762451171875 +46012 0.79669189453125 +46013 0.595794677734375 +46014 0.362152099609375 +46015 0.1270751953125 +46016 -0.086944580078125 +46017 -0.2784423828125 +46018 -0.484832763671875 +46019 -0.729583740234375 +46020 -0.86688232421875 +46021 -0.870391845703125 +46022 -0.86859130859375 +46023 -0.86279296875 +46024 -0.817962646484375 +46025 -0.6116943359375 +46026 -0.3128662109375 +46027 0.039398193359375 +46028 0.422821044921875 +46029 0.805145263671875 +46030 0.870361328125 +46031 0.870361328125 +46032 0.860015869140625 +46033 0.727935791015625 +46034 0.48114013671875 +46035 0.2059326171875 +46036 -0.06103515625 +46037 -0.29913330078125 +46038 -0.516204833984375 +46039 -0.7252197265625 +46040 -0.85980224609375 +46041 -0.870391845703125 +46042 -0.870391845703125 +46043 -0.858062744140625 +46044 -0.673004150390625 +46045 -0.42694091796875 +46046 -0.2100830078125 +46047 -0.0362548828125 +46048 0.10943603515625 +46049 0.23516845703125 +46050 0.373687744140625 +46051 0.517791748046875 +46052 0.602783203125 +46053 0.635711669921875 +46054 0.655181884765625 +46055 0.65948486328125 +46056 0.651275634765625 +46057 0.61846923828125 +46058 0.53753662109375 +46059 0.404144287109375 +46060 0.22186279296875 +46061 0.003997802734375 +46062 -0.22100830078125 +46063 -0.42449951171875 +46064 -0.579833984375 +46065 -0.641876220703125 +46066 -0.6177978515625 +46067 -0.575531005859375 +46068 -0.526336669921875 +46069 -0.42645263671875 +46070 -0.2581787109375 +46071 -0.068695068359375 +46072 0.09222412109375 +46073 0.232147216796875 +46074 0.3509521484375 +46075 0.410064697265625 +46076 0.372955322265625 +46077 0.2554931640625 +46078 0.10711669921875 +46079 -0.052886962890625 +46080 -0.186279296875 +46081 -0.23291015625 +46082 -0.209442138671875 +46083 -0.174163818359375 +46084 -0.126739501953125 +46085 -0.048126220703125 +46086 0.0426025390625 +46087 0.10748291015625 +46088 0.1409912109375 +46089 0.19708251953125 +46090 0.273651123046875 +46091 0.31768798828125 +46092 0.341094970703125 +46093 0.368011474609375 +46094 0.37249755859375 +46095 0.30072021484375 +46096 0.1517333984375 +46097 -0.01470947265625 +46098 -0.1883544921875 +46099 -0.372711181640625 +46100 -0.51397705078125 +46101 -0.57177734375 +46102 -0.53948974609375 +46103 -0.43511962890625 +46104 -0.2962646484375 +46105 -0.161102294921875 +46106 -0.0435791015625 +46107 0.060394287109375 +46108 0.13665771484375 +46109 0.170135498046875 +46110 0.16552734375 +46111 0.15728759765625 +46112 0.150787353515625 +46113 0.12200927734375 +46114 0.080108642578125 +46115 0.05126953125 +46116 0.062896728515625 +46117 0.09271240234375 +46118 0.092987060546875 +46119 0.07855224609375 +46120 0.06427001953125 +46121 0.0347900390625 +46122 -0.01171875 +46123 -0.056060791015625 +46124 -0.055511474609375 +46125 -0.010467529296875 +46126 0.02508544921875 +46127 0.025665283203125 +46128 0.017333984375 +46129 0.00189208984375 +46130 -0.03173828125 +46131 -0.071502685546875 +46132 -0.13543701171875 +46133 -0.219970703125 +46134 -0.300506591796875 +46135 -0.376312255859375 +46136 -0.416107177734375 +46137 -0.371124267578125 +46138 -0.242279052734375 +46139 -0.069732666015625 +46140 0.125640869140625 +46141 0.31268310546875 +46142 0.45501708984375 +46143 0.554779052734375 +46144 0.61065673828125 +46145 0.610931396484375 +46146 0.531463623046875 +46147 0.3883056640625 +46148 0.23468017578125 +46149 0.095245361328125 +46150 -0.00396728515625 +46151 -0.04852294921875 +46152 -0.055145263671875 +46153 -0.0758056640625 +46154 -0.138702392578125 +46155 -0.209197998046875 +46156 -0.289031982421875 +46157 -0.37884521484375 +46158 -0.456329345703125 +46159 -0.51641845703125 +46160 -0.519287109375 +46161 -0.458251953125 +46162 -0.384796142578125 +46163 -0.323699951171875 +46164 -0.269287109375 +46165 -0.1951904296875 +46166 -0.100006103515625 +46167 -0.01055908203125 +46168 0.1033935546875 +46169 0.24908447265625 +46170 0.373199462890625 +46171 0.45806884765625 +46172 0.511474609375 +46173 0.565399169921875 +46174 0.61138916015625 +46175 0.5897216796875 +46176 0.4906005859375 +46177 0.33148193359375 +46178 0.147796630859375 +46179 -0.01873779296875 +46180 -0.140289306640625 +46181 -0.191986083984375 +46182 -0.184295654296875 +46183 -0.161834716796875 +46184 -0.166595458984375 +46185 -0.19390869140625 +46186 -0.22442626953125 +46187 -0.279754638671875 +46188 -0.3389892578125 +46189 -0.3543701171875 +46190 -0.348175048828125 +46191 -0.32598876953125 +46192 -0.2581787109375 +46193 -0.139801025390625 +46194 0.014617919921875 +46195 0.144378662109375 +46196 0.221038818359375 +46197 0.27069091796875 +46198 0.294036865234375 +46199 0.311767578125 +46200 0.339141845703125 +46201 0.360260009765625 +46202 0.360504150390625 +46203 0.308380126953125 +46204 0.18170166015625 +46205 0.0047607421875 +46206 -0.17559814453125 +46207 -0.3143310546875 +46208 -0.36785888671875 +46209 -0.36248779296875 +46210 -0.343536376953125 +46211 -0.3018798828125 +46212 -0.231414794921875 +46213 -0.117645263671875 +46214 0.007049560546875 +46215 0.087982177734375 +46216 0.13946533203125 +46217 0.17425537109375 +46218 0.188201904296875 +46219 0.171234130859375 +46220 0.118438720703125 +46221 0.05706787109375 +46222 -0.010711669921875 +46223 -0.0914306640625 +46224 -0.162322998046875 +46225 -0.194549560546875 +46226 -0.1492919921875 +46227 -0.02166748046875 +46228 0.124053955078125 +46229 0.211151123046875 +46230 0.240447998046875 +46231 0.242218017578125 +46232 0.2257080078125 +46233 0.194366455078125 +46234 0.115509033203125 +46235 0.0128173828125 +46236 -0.053802490234375 +46237 -0.110626220703125 +46238 -0.199493408203125 +46239 -0.29437255859375 +46240 -0.33221435546875 +46241 -0.27972412109375 +46242 -0.185333251953125 +46243 -0.128204345703125 +46244 -0.115692138671875 +46245 -0.116455078125 +46246 -0.105926513671875 +46247 -0.053955078125 +46248 0.048797607421875 +46249 0.157318115234375 +46250 0.212005615234375 +46251 0.218475341796875 +46252 0.23724365234375 +46253 0.30535888671875 +46254 0.38128662109375 +46255 0.404449462890625 +46256 0.3944091796875 +46257 0.3885498046875 +46258 0.362640380859375 +46259 0.27362060546875 +46260 0.11712646484375 +46261 -0.054901123046875 +46262 -0.19085693359375 +46263 -0.28570556640625 +46264 -0.339263916015625 +46265 -0.3775634765625 +46266 -0.445709228515625 +46267 -0.535064697265625 +46268 -0.629058837890625 +46269 -0.697601318359375 +46270 -0.70391845703125 +46271 -0.6424560546875 +46272 -0.491241455078125 +46273 -0.265716552734375 +46274 -0.023712158203125 +46275 0.201751708984375 +46276 0.375823974609375 +46277 0.485076904296875 +46278 0.56884765625 +46279 0.634765625 +46280 0.63763427734375 +46281 0.5660400390625 +46282 0.4720458984375 +46283 0.40692138671875 +46284 0.3778076171875 +46285 0.376953125 +46286 0.371978759765625 +46287 0.313140869140625 +46288 0.184417724609375 +46289 0.011199951171875 +46290 -0.171051025390625 +46291 -0.33740234375 +46292 -0.47198486328125 +46293 -0.560394287109375 +46294 -0.58056640625 +46295 -0.54754638671875 +46296 -0.508575439453125 +46297 -0.459503173828125 +46298 -0.394378662109375 +46299 -0.35260009765625 +46300 -0.31170654296875 +46301 -0.197418212890625 +46302 -0.007965087890625 +46303 0.207489013671875 +46304 0.409210205078125 +46305 0.57208251953125 +46306 0.66595458984375 +46307 0.65875244140625 +46308 0.56744384765625 +46309 0.431396484375 +46310 0.29443359375 +46311 0.182464599609375 +46312 0.06365966796875 +46313 -0.075958251953125 +46314 -0.189422607421875 +46315 -0.271942138671875 +46316 -0.342529296875 +46317 -0.364166259765625 +46318 -0.327239990234375 +46319 -0.2769775390625 +46320 -0.253692626953125 +46321 -0.24365234375 +46322 -0.1983642578125 +46323 -0.116241455078125 +46324 -0.036834716796875 +46325 0.034881591796875 +46326 0.09124755859375 +46327 0.10888671875 +46328 0.125518798828125 +46329 0.15771484375 +46330 0.17828369140625 +46331 0.17108154296875 +46332 0.129974365234375 +46333 0.082427978515625 +46334 0.027679443359375 +46335 -0.065643310546875 +46336 -0.15936279296875 +46337 -0.21307373046875 +46338 -0.234649658203125 +46339 -0.2001953125 +46340 -0.119171142578125 +46341 -0.024749755859375 +46342 0.085784912109375 +46343 0.178131103515625 +46344 0.215576171875 +46345 0.211456298828125 +46346 0.17523193359375 +46347 0.128753662109375 +46348 0.1019287109375 +46349 0.0743408203125 +46350 0.04327392578125 +46351 0.038177490234375 +46352 0.076263427734375 +46353 0.14105224609375 +46354 0.186431884765625 +46355 0.188812255859375 +46356 0.1390380859375 +46357 0.041778564453125 +46358 -0.079437255859375 +46359 -0.219390869140625 +46360 -0.367828369140625 +46361 -0.494873046875 +46362 -0.556243896484375 +46363 -0.508697509765625 +46364 -0.3756103515625 +46365 -0.218902587890625 +46366 -0.063751220703125 +46367 0.091552734375 +46368 0.23602294921875 +46369 0.342987060546875 +46370 0.39520263671875 +46371 0.389373779296875 +46372 0.324249267578125 +46373 0.224090576171875 +46374 0.124267578125 +46375 0.037078857421875 +46376 -0.010101318359375 +46377 -0.019439697265625 +46378 -0.022796630859375 +46379 -0.001556396484375 +46380 0.056304931640625 +46381 0.106719970703125 +46382 0.096893310546875 +46383 0.042694091796875 +46384 -0.018035888671875 +46385 -0.07586669921875 +46386 -0.11944580078125 +46387 -0.15972900390625 +46388 -0.202606201171875 +46389 -0.24859619140625 +46390 -0.30517578125 +46391 -0.36212158203125 +46392 -0.39141845703125 +46393 -0.35528564453125 +46394 -0.249969482421875 +46395 -0.092864990234375 +46396 0.08905029296875 +46397 0.2352294921875 +46398 0.318817138671875 +46399 0.358642578125 +46400 0.347747802734375 +46401 0.28564453125 +46402 0.223175048828125 +46403 0.196746826171875 +46404 0.179840087890625 +46405 0.155548095703125 +46406 0.151214599609375 +46407 0.156951904296875 +46408 0.13177490234375 +46409 0.100799560546875 +46410 0.087127685546875 +46411 0.05487060546875 +46412 -0.009002685546875 +46413 -0.10400390625 +46414 -0.229400634765625 +46415 -0.35552978515625 +46416 -0.441925048828125 +46417 -0.473846435546875 +46418 -0.464813232421875 +46419 -0.419097900390625 +46420 -0.334320068359375 +46421 -0.227935791015625 +46422 -0.12347412109375 +46423 -0.02764892578125 +46424 0.077667236328125 +46425 0.2132568359375 +46426 0.38885498046875 +46427 0.582794189453125 +46428 0.734039306640625 +46429 0.800140380859375 +46430 0.7783203125 +46431 0.6651611328125 +46432 0.45965576171875 +46433 0.199188232421875 +46434 -0.050689697265625 +46435 -0.23297119140625 +46436 -0.33013916015625 +46437 -0.368408203125 +46438 -0.378936767578125 +46439 -0.376983642578125 +46440 -0.37969970703125 +46441 -0.391510009765625 +46442 -0.385345458984375 +46443 -0.3419189453125 +46444 -0.28289794921875 +46445 -0.251617431640625 +46446 -0.266143798828125 +46447 -0.273345947265625 +46448 -0.216796875 +46449 -0.128265380859375 +46450 -0.068145751953125 +46451 -0.0430908203125 +46452 -0.024444580078125 +46453 0.020721435546875 +46454 0.124481201171875 +46455 0.25787353515625 +46456 0.379119873046875 +46457 0.47991943359375 +46458 0.5281982421875 +46459 0.511138916015625 +46460 0.456207275390625 +46461 0.407470703125 +46462 0.383758544921875 +46463 0.35687255859375 +46464 0.31182861328125 +46465 0.250885009765625 +46466 0.1654052734375 +46467 0.035247802734375 +46468 -0.142059326171875 +46469 -0.33563232421875 +46470 -0.5345458984375 +46471 -0.72186279296875 +46472 -0.836669921875 +46473 -0.8326416015625 +46474 -0.7296142578125 +46475 -0.582550048828125 +46476 -0.440093994140625 +46477 -0.324310302734375 +46478 -0.20147705078125 +46479 -0.044647216796875 +46480 0.103973388671875 +46481 0.202392578125 +46482 0.264495849609375 +46483 0.338897705078125 +46484 0.443817138671875 +46485 0.545074462890625 +46486 0.6173095703125 +46487 0.6524658203125 +46488 0.66339111328125 +46489 0.6561279296875 +46490 0.606781005859375 +46491 0.501190185546875 +46492 0.352783203125 +46493 0.176544189453125 +46494 -0.034820556640625 +46495 -0.258209228515625 +46496 -0.44244384765625 +46497 -0.5753173828125 +46498 -0.65203857421875 +46499 -0.641632080078125 +46500 -0.562164306640625 +46501 -0.458038330078125 +46502 -0.350555419921875 +46503 -0.260528564453125 +46504 -0.192108154296875 +46505 -0.141937255859375 +46506 -0.1021728515625 +46507 -0.062896728515625 +46508 -0.011932373046875 +46509 0.062835693359375 +46510 0.148712158203125 +46511 0.241729736328125 +46512 0.34912109375 +46513 0.457305908203125 +46514 0.54388427734375 +46515 0.5728759765625 +46516 0.506591796875 +46517 0.351226806640625 +46518 0.146514892578125 +46519 -0.05523681640625 +46520 -0.21624755859375 +46521 -0.334930419921875 +46522 -0.402984619140625 +46523 -0.4412841796875 +46524 -0.49578857421875 +46525 -0.5601806640625 +46526 -0.600738525390625 +46527 -0.584228515625 +46528 -0.47930908203125 +46529 -0.27935791015625 +46530 -0.0089111328125 +46531 0.268798828125 +46532 0.482818603515625 +46533 0.60369873046875 +46534 0.650421142578125 +46535 0.66400146484375 +46536 0.6414794921875 +46537 0.572540283203125 +46538 0.498138427734375 +46539 0.439453125 +46540 0.375518798828125 +46541 0.274505615234375 +46542 0.1087646484375 +46543 -0.099395751953125 +46544 -0.3182373046875 +46545 -0.5489501953125 +46546 -0.7738037109375 +46547 -0.86383056640625 +46548 -0.870391845703125 +46549 -0.86895751953125 +46550 -0.861053466796875 +46551 -0.765869140625 +46552 -0.5301513671875 +46553 -0.214691162109375 +46554 0.137359619140625 +46555 0.474822998046875 +46556 0.76239013671875 +46557 0.867462158203125 +46558 0.870361328125 +46559 0.86480712890625 +46560 0.831817626953125 +46561 0.677581787109375 +46562 0.495880126953125 +46563 0.30767822265625 +46564 0.116180419921875 +46565 -0.110748291015625 +46566 -0.381805419921875 +46567 -0.6572265625 +46568 -0.857421875 +46569 -0.870391845703125 +46570 -0.870391845703125 +46571 -0.86444091796875 +46572 -0.85723876953125 +46573 -0.790008544921875 +46574 -0.62847900390625 +46575 -0.3956298828125 +46576 -0.126708984375 +46577 0.150115966796875 +46578 0.424041748046875 +46579 0.670623779296875 +46580 0.854522705078125 +46581 0.866485595703125 +46582 0.86920166015625 +46583 0.8653564453125 +46584 0.857147216796875 +46585 0.766845703125 +46586 0.628509521484375 +46587 0.462127685546875 +46588 0.297210693359375 +46589 0.14862060546875 +46590 -0.00537109375 +46591 -0.15753173828125 +46592 -0.31304931640625 +46593 -0.48876953125 +46594 -0.6416015625 +46595 -0.751373291015625 +46596 -0.84619140625 +46597 -0.861297607421875 +46598 -0.863250732421875 +46599 -0.856597900390625 +46600 -0.7498779296875 +46601 -0.624542236328125 +46602 -0.47808837890625 +46603 -0.253387451171875 +46604 0.003692626953125 +46605 0.2257080078125 +46606 0.427154541015625 +46607 0.643218994140625 +46608 0.855926513671875 +46609 0.870361328125 +46610 0.870361328125 +46611 0.862762451171875 +46612 0.79669189453125 +46613 0.595794677734375 +46614 0.362152099609375 +46615 0.1270751953125 +46616 -0.086944580078125 +46617 -0.2784423828125 +46618 -0.484832763671875 +46619 -0.729583740234375 +46620 -0.86688232421875 +46621 -0.870391845703125 +46622 -0.86859130859375 +46623 -0.86279296875 +46624 -0.817962646484375 +46625 -0.6116943359375 +46626 -0.3128662109375 +46627 0.039398193359375 +46628 0.422821044921875 +46629 0.805145263671875 +46630 0.870361328125 +46631 0.870361328125 +46632 0.860015869140625 +46633 0.727935791015625 +46634 0.48114013671875 +46635 0.2059326171875 +46636 -0.06103515625 +46637 -0.29913330078125 +46638 -0.516204833984375 +46639 -0.7252197265625 +46640 -0.85980224609375 +46641 -0.870391845703125 +46642 -0.870391845703125 +46643 -0.858062744140625 +46644 -0.673004150390625 +46645 -0.42694091796875 +46646 -0.2100830078125 +46647 -0.0362548828125 +46648 0.10943603515625 +46649 0.23516845703125 +46650 0.373687744140625 +46651 0.517791748046875 +46652 0.602783203125 +46653 0.635711669921875 +46654 0.655181884765625 +46655 0.65948486328125 +46656 0.651275634765625 +46657 0.61846923828125 +46658 0.53753662109375 +46659 0.404144287109375 +46660 0.22186279296875 +46661 0.003997802734375 +46662 -0.22100830078125 +46663 -0.42449951171875 +46664 -0.579833984375 +46665 -0.641876220703125 +46666 -0.6177978515625 +46667 -0.575531005859375 +46668 -0.526336669921875 +46669 -0.42645263671875 +46670 -0.2581787109375 +46671 -0.068695068359375 +46672 0.09222412109375 +46673 0.232147216796875 +46674 0.3509521484375 +46675 0.410064697265625 +46676 0.372955322265625 +46677 0.2554931640625 +46678 0.10711669921875 +46679 -0.052886962890625 +46680 -0.186279296875 +46681 -0.23291015625 +46682 -0.209442138671875 +46683 -0.174163818359375 +46684 -0.126739501953125 +46685 -0.048126220703125 +46686 0.0426025390625 +46687 0.10748291015625 +46688 0.1409912109375 +46689 0.19708251953125 +46690 0.273651123046875 +46691 0.31768798828125 +46692 0.341094970703125 +46693 0.368011474609375 +46694 0.37249755859375 +46695 0.30072021484375 +46696 0.1517333984375 +46697 -0.01470947265625 +46698 -0.1883544921875 +46699 -0.372711181640625 +46700 -0.51397705078125 +46701 -0.57177734375 +46702 -0.53948974609375 +46703 -0.43511962890625 +46704 -0.2962646484375 +46705 -0.161102294921875 +46706 -0.0435791015625 +46707 0.060394287109375 +46708 0.13665771484375 +46709 0.170135498046875 +46710 0.16552734375 +46711 0.15728759765625 +46712 0.150787353515625 +46713 0.12200927734375 +46714 0.080108642578125 +46715 0.05126953125 +46716 0.062896728515625 +46717 0.09271240234375 +46718 0.092987060546875 +46719 0.07855224609375 +46720 0.06427001953125 +46721 0.0347900390625 +46722 -0.01171875 +46723 -0.056060791015625 +46724 -0.055511474609375 +46725 -0.010467529296875 +46726 0.02508544921875 +46727 0.025665283203125 +46728 0.017333984375 +46729 0.00189208984375 +46730 -0.03173828125 +46731 -0.071502685546875 +46732 -0.13543701171875 +46733 -0.219970703125 +46734 -0.300506591796875 +46735 -0.376312255859375 +46736 -0.416107177734375 +46737 -0.371124267578125 +46738 -0.242279052734375 +46739 -0.069732666015625 +46740 0.125640869140625 +46741 0.31268310546875 +46742 0.45501708984375 +46743 0.554779052734375 +46744 0.61065673828125 +46745 0.610931396484375 +46746 0.531463623046875 +46747 0.3883056640625 +46748 0.23468017578125 +46749 0.095245361328125 +46750 -0.00396728515625 +46751 -0.04852294921875 +46752 -0.055145263671875 +46753 -0.0758056640625 +46754 -0.138702392578125 +46755 -0.209197998046875 +46756 -0.289031982421875 +46757 -0.37884521484375 +46758 -0.456329345703125 +46759 -0.51641845703125 +46760 -0.519287109375 +46761 -0.458251953125 +46762 -0.384796142578125 +46763 -0.323699951171875 +46764 -0.269287109375 +46765 -0.1951904296875 +46766 -0.100006103515625 +46767 -0.01055908203125 +46768 0.1033935546875 +46769 0.24908447265625 +46770 0.373199462890625 +46771 0.45806884765625 +46772 0.511474609375 +46773 0.565399169921875 +46774 0.61138916015625 +46775 0.5897216796875 +46776 0.4906005859375 +46777 0.33148193359375 +46778 0.147796630859375 +46779 -0.01873779296875 +46780 -0.140289306640625 +46781 -0.191986083984375 +46782 -0.184295654296875 +46783 -0.161834716796875 +46784 -0.166595458984375 +46785 -0.19390869140625 +46786 -0.22442626953125 +46787 -0.279754638671875 +46788 -0.3389892578125 +46789 -0.3543701171875 +46790 -0.348175048828125 +46791 -0.32598876953125 +46792 -0.2581787109375 +46793 -0.139801025390625 +46794 0.014617919921875 +46795 0.144378662109375 +46796 0.221038818359375 +46797 0.27069091796875 +46798 0.294036865234375 +46799 0.311767578125 +46800 0.339141845703125 +46801 0.360260009765625 +46802 0.360504150390625 +46803 0.308380126953125 +46804 0.18170166015625 +46805 0.0047607421875 +46806 -0.17559814453125 +46807 -0.3143310546875 +46808 -0.36785888671875 +46809 -0.36248779296875 +46810 -0.343536376953125 +46811 -0.3018798828125 +46812 -0.231414794921875 +46813 -0.117645263671875 +46814 0.007049560546875 +46815 0.087982177734375 +46816 0.13946533203125 +46817 0.17425537109375 +46818 0.188201904296875 +46819 0.171234130859375 +46820 0.118438720703125 +46821 0.05706787109375 +46822 -0.010711669921875 +46823 -0.0914306640625 +46824 -0.162322998046875 +46825 -0.194549560546875 +46826 -0.1492919921875 +46827 -0.02166748046875 +46828 0.124053955078125 +46829 0.211151123046875 +46830 0.240447998046875 +46831 0.242218017578125 +46832 0.2257080078125 +46833 0.194366455078125 +46834 0.115509033203125 +46835 0.0128173828125 +46836 -0.053802490234375 +46837 -0.110626220703125 +46838 -0.199493408203125 +46839 -0.29437255859375 +46840 -0.33221435546875 +46841 -0.27972412109375 +46842 -0.185333251953125 +46843 -0.128204345703125 +46844 -0.115692138671875 +46845 -0.116455078125 +46846 -0.105926513671875 +46847 -0.053955078125 +46848 0.048797607421875 +46849 0.157318115234375 +46850 0.212005615234375 +46851 0.218475341796875 +46852 0.23724365234375 +46853 0.30535888671875 +46854 0.38128662109375 +46855 0.404449462890625 +46856 0.3944091796875 +46857 0.3885498046875 +46858 0.362640380859375 +46859 0.27362060546875 +46860 0.11712646484375 +46861 -0.054901123046875 +46862 -0.19085693359375 +46863 -0.28570556640625 +46864 -0.339263916015625 +46865 -0.3775634765625 +46866 -0.445709228515625 +46867 -0.535064697265625 +46868 -0.629058837890625 +46869 -0.697601318359375 +46870 -0.70391845703125 +46871 -0.6424560546875 +46872 -0.491241455078125 +46873 -0.265716552734375 +46874 -0.023712158203125 +46875 0.201751708984375 +46876 0.375823974609375 +46877 0.485076904296875 +46878 0.56884765625 +46879 0.634765625 +46880 0.63763427734375 +46881 0.5660400390625 +46882 0.4720458984375 +46883 0.40692138671875 +46884 0.3778076171875 +46885 0.376953125 +46886 0.371978759765625 +46887 0.313140869140625 +46888 0.184417724609375 +46889 0.011199951171875 +46890 -0.171051025390625 +46891 -0.33740234375 +46892 -0.47198486328125 +46893 -0.560394287109375 +46894 -0.58056640625 +46895 -0.54754638671875 +46896 -0.508575439453125 +46897 -0.459503173828125 +46898 -0.394378662109375 +46899 -0.35260009765625 +46900 -0.31170654296875 +46901 -0.197418212890625 +46902 -0.007965087890625 +46903 0.207489013671875 +46904 0.409210205078125 +46905 0.57208251953125 +46906 0.66595458984375 +46907 0.65875244140625 +46908 0.56744384765625 +46909 0.431396484375 +46910 0.29443359375 +46911 0.182464599609375 +46912 0.06365966796875 +46913 -0.075958251953125 +46914 -0.189422607421875 +46915 -0.271942138671875 +46916 -0.342529296875 +46917 -0.364166259765625 +46918 -0.327239990234375 +46919 -0.2769775390625 +46920 -0.253692626953125 +46921 -0.24365234375 +46922 -0.1983642578125 +46923 -0.116241455078125 +46924 -0.036834716796875 +46925 0.034881591796875 +46926 0.09124755859375 +46927 0.10888671875 +46928 0.125518798828125 +46929 0.15771484375 +46930 0.17828369140625 +46931 0.17108154296875 +46932 0.129974365234375 +46933 0.082427978515625 +46934 0.027679443359375 +46935 -0.065643310546875 +46936 -0.15936279296875 +46937 -0.21307373046875 +46938 -0.234649658203125 +46939 -0.2001953125 +46940 -0.119171142578125 +46941 -0.024749755859375 +46942 0.085784912109375 +46943 0.178131103515625 +46944 0.215576171875 +46945 0.211456298828125 +46946 0.17523193359375 +46947 0.128753662109375 +46948 0.1019287109375 +46949 0.0743408203125 +46950 0.04327392578125 +46951 0.038177490234375 +46952 0.076263427734375 +46953 0.14105224609375 +46954 0.186431884765625 +46955 0.188812255859375 +46956 0.1390380859375 +46957 0.041778564453125 +46958 -0.079437255859375 +46959 -0.219390869140625 +46960 -0.367828369140625 +46961 -0.494873046875 +46962 -0.556243896484375 +46963 -0.508697509765625 +46964 -0.3756103515625 +46965 -0.218902587890625 +46966 -0.063751220703125 +46967 0.091552734375 +46968 0.23602294921875 +46969 0.342987060546875 +46970 0.39520263671875 +46971 0.389373779296875 +46972 0.324249267578125 +46973 0.224090576171875 +46974 0.124267578125 +46975 0.037078857421875 +46976 -0.010101318359375 +46977 -0.019439697265625 +46978 -0.022796630859375 +46979 -0.001556396484375 +46980 0.056304931640625 +46981 0.106719970703125 +46982 0.096893310546875 +46983 0.042694091796875 +46984 -0.018035888671875 +46985 -0.07586669921875 +46986 -0.11944580078125 +46987 -0.15972900390625 +46988 -0.202606201171875 +46989 -0.24859619140625 +46990 -0.30517578125 +46991 -0.36212158203125 +46992 -0.39141845703125 +46993 -0.35528564453125 +46994 -0.249969482421875 +46995 -0.092864990234375 +46996 0.08905029296875 +46997 0.2352294921875 +46998 0.318817138671875 +46999 0.358642578125 +47000 0.347747802734375 +47001 0.28564453125 +47002 0.223175048828125 +47003 0.196746826171875 +47004 0.179840087890625 +47005 0.155548095703125 +47006 0.151214599609375 +47007 0.156951904296875 +47008 0.13177490234375 +47009 0.100799560546875 +47010 0.087127685546875 +47011 0.05487060546875 +47012 -0.009002685546875 +47013 -0.10400390625 +47014 -0.229400634765625 +47015 -0.35552978515625 +47016 -0.441925048828125 +47017 -0.473846435546875 +47018 -0.464813232421875 +47019 -0.419097900390625 +47020 -0.334320068359375 +47021 -0.227935791015625 +47022 -0.12347412109375 +47023 -0.02764892578125 +47024 0.077667236328125 +47025 0.2132568359375 +47026 0.38885498046875 +47027 0.582794189453125 +47028 0.734039306640625 +47029 0.800140380859375 +47030 0.7783203125 +47031 0.6651611328125 +47032 0.45965576171875 +47033 0.199188232421875 +47034 -0.050689697265625 +47035 -0.23297119140625 +47036 -0.33013916015625 +47037 -0.368408203125 +47038 -0.378936767578125 +47039 -0.376983642578125 +47040 -0.37969970703125 +47041 -0.391510009765625 +47042 -0.385345458984375 +47043 -0.3419189453125 +47044 -0.28289794921875 +47045 -0.251617431640625 +47046 -0.266143798828125 +47047 -0.273345947265625 +47048 -0.216796875 +47049 -0.128265380859375 +47050 -0.068145751953125 +47051 -0.0430908203125 +47052 -0.024444580078125 +47053 0.020721435546875 +47054 0.124481201171875 +47055 0.25787353515625 +47056 0.379119873046875 +47057 0.47991943359375 +47058 0.5281982421875 +47059 0.511138916015625 +47060 0.456207275390625 +47061 0.407470703125 +47062 0.383758544921875 +47063 0.35687255859375 +47064 0.31182861328125 +47065 0.250885009765625 +47066 0.1654052734375 +47067 0.035247802734375 +47068 -0.142059326171875 +47069 -0.33563232421875 +47070 -0.5345458984375 +47071 -0.72186279296875 +47072 -0.836669921875 +47073 -0.8326416015625 +47074 -0.7296142578125 +47075 -0.582550048828125 +47076 -0.440093994140625 +47077 -0.324310302734375 +47078 -0.20147705078125 +47079 -0.044647216796875 +47080 0.103973388671875 +47081 0.202392578125 +47082 0.264495849609375 +47083 0.338897705078125 +47084 0.443817138671875 +47085 0.545074462890625 +47086 0.6173095703125 +47087 0.6524658203125 +47088 0.66339111328125 +47089 0.6561279296875 +47090 0.606781005859375 +47091 0.501190185546875 +47092 0.352783203125 +47093 0.176544189453125 +47094 -0.034820556640625 +47095 -0.258209228515625 +47096 -0.44244384765625 +47097 -0.5753173828125 +47098 -0.65203857421875 +47099 -0.641632080078125 +47100 -0.562164306640625 +47101 -0.458038330078125 +47102 -0.350555419921875 +47103 -0.260528564453125 +47104 -0.192108154296875 +47105 -0.141937255859375 +47106 -0.1021728515625 +47107 -0.062896728515625 +47108 -0.011932373046875 +47109 0.062835693359375 +47110 0.148712158203125 +47111 0.241729736328125 +47112 0.34912109375 +47113 0.457305908203125 +47114 0.54388427734375 +47115 0.5728759765625 +47116 0.506591796875 +47117 0.351226806640625 +47118 0.146514892578125 +47119 -0.05523681640625 +47120 -0.21624755859375 +47121 -0.334930419921875 +47122 -0.402984619140625 +47123 -0.4412841796875 +47124 -0.49578857421875 +47125 -0.5601806640625 +47126 -0.600738525390625 +47127 -0.584228515625 +47128 -0.47930908203125 +47129 -0.27935791015625 +47130 -0.0089111328125 +47131 0.268798828125 +47132 0.482818603515625 +47133 0.60369873046875 +47134 0.650421142578125 +47135 0.66400146484375 +47136 0.6414794921875 +47137 0.572540283203125 +47138 0.498138427734375 +47139 0.439453125 +47140 0.375518798828125 +47141 0.274505615234375 +47142 0.1087646484375 +47143 -0.099395751953125 +47144 -0.3182373046875 +47145 -0.5489501953125 +47146 -0.7738037109375 +47147 -0.86383056640625 +47148 -0.870391845703125 +47149 -0.86895751953125 +47150 -0.861053466796875 +47151 -0.765869140625 +47152 -0.5301513671875 +47153 -0.214691162109375 +47154 0.137359619140625 +47155 0.474822998046875 +47156 0.76239013671875 +47157 0.867462158203125 +47158 0.870361328125 +47159 0.86480712890625 +47160 0.831817626953125 +47161 0.677581787109375 +47162 0.495880126953125 +47163 0.30767822265625 +47164 0.116180419921875 +47165 -0.110748291015625 +47166 -0.381805419921875 +47167 -0.6572265625 +47168 -0.857421875 +47169 -0.870391845703125 +47170 -0.870391845703125 +47171 -0.86444091796875 +47172 -0.85723876953125 +47173 -0.790008544921875 +47174 -0.62847900390625 +47175 -0.3956298828125 +47176 -0.126708984375 +47177 0.150115966796875 +47178 0.424041748046875 +47179 0.670623779296875 +47180 0.854522705078125 +47181 0.866485595703125 +47182 0.86920166015625 +47183 0.8653564453125 +47184 0.857147216796875 +47185 0.766845703125 +47186 0.628509521484375 +47187 0.462127685546875 +47188 0.297210693359375 +47189 0.14862060546875 +47190 -0.00537109375 +47191 -0.15753173828125 +47192 -0.31304931640625 +47193 -0.48876953125 +47194 -0.6416015625 +47195 -0.751373291015625 +47196 -0.84619140625 +47197 -0.861297607421875 +47198 -0.863250732421875 +47199 -0.856597900390625 +47200 -0.7498779296875 +47201 -0.624542236328125 +47202 -0.47808837890625 +47203 -0.253387451171875 +47204 0.003692626953125 +47205 0.2257080078125 +47206 0.427154541015625 +47207 0.643218994140625 +47208 0.855926513671875 +47209 0.870361328125 +47210 0.870361328125 +47211 0.862762451171875 +47212 0.79669189453125 +47213 0.595794677734375 +47214 0.362152099609375 +47215 0.1270751953125 +47216 -0.086944580078125 +47217 -0.2784423828125 +47218 -0.484832763671875 +47219 -0.729583740234375 +47220 -0.86688232421875 +47221 -0.870391845703125 +47222 -0.86859130859375 +47223 -0.86279296875 +47224 -0.817962646484375 +47225 -0.6116943359375 +47226 -0.3128662109375 +47227 0.039398193359375 +47228 0.422821044921875 +47229 0.805145263671875 +47230 0.870361328125 +47231 0.870361328125 +47232 0.860015869140625 +47233 0.727935791015625 +47234 0.48114013671875 +47235 0.2059326171875 +47236 -0.06103515625 +47237 -0.29913330078125 +47238 -0.516204833984375 +47239 -0.7252197265625 +47240 -0.85980224609375 +47241 -0.870391845703125 +47242 -0.870391845703125 +47243 -0.858062744140625 +47244 -0.673004150390625 +47245 -0.42694091796875 +47246 -0.2100830078125 +47247 -0.0362548828125 +47248 0.10943603515625 +47249 0.23516845703125 +47250 0.373687744140625 +47251 0.517791748046875 +47252 0.602783203125 +47253 0.635711669921875 +47254 0.655181884765625 +47255 0.65948486328125 +47256 0.651275634765625 +47257 0.61846923828125 +47258 0.53753662109375 +47259 0.404144287109375 +47260 0.22186279296875 +47261 0.003997802734375 +47262 -0.22100830078125 +47263 -0.42449951171875 +47264 -0.579833984375 +47265 -0.641876220703125 +47266 -0.6177978515625 +47267 -0.575531005859375 +47268 -0.526336669921875 +47269 -0.42645263671875 +47270 -0.2581787109375 +47271 -0.068695068359375 +47272 0.09222412109375 +47273 0.232147216796875 +47274 0.3509521484375 +47275 0.410064697265625 +47276 0.372955322265625 +47277 0.2554931640625 +47278 0.10711669921875 +47279 -0.052886962890625 +47280 -0.186279296875 +47281 -0.23291015625 +47282 -0.209442138671875 +47283 -0.174163818359375 +47284 -0.126739501953125 +47285 -0.048126220703125 +47286 0.0426025390625 +47287 0.10748291015625 +47288 0.1409912109375 +47289 0.19708251953125 +47290 0.273651123046875 +47291 0.31768798828125 +47292 0.341094970703125 +47293 0.368011474609375 +47294 0.37249755859375 +47295 0.30072021484375 +47296 0.1517333984375 +47297 -0.01470947265625 +47298 -0.1883544921875 +47299 -0.372711181640625 +47300 -0.51397705078125 +47301 -0.57177734375 +47302 -0.53948974609375 +47303 -0.43511962890625 +47304 -0.2962646484375 +47305 -0.161102294921875 +47306 -0.0435791015625 +47307 0.060394287109375 +47308 0.13665771484375 +47309 0.170135498046875 +47310 0.16552734375 +47311 0.15728759765625 +47312 0.150787353515625 +47313 0.12200927734375 +47314 0.080108642578125 +47315 0.05126953125 +47316 0.062896728515625 +47317 0.09271240234375 +47318 0.092987060546875 +47319 0.07855224609375 +47320 0.06427001953125 +47321 0.0347900390625 +47322 -0.01171875 +47323 -0.056060791015625 +47324 -0.055511474609375 +47325 -0.010467529296875 +47326 0.02508544921875 +47327 0.025665283203125 +47328 0.017333984375 +47329 0.00189208984375 +47330 -0.03173828125 +47331 -0.071502685546875 +47332 -0.13543701171875 +47333 -0.219970703125 +47334 -0.300506591796875 +47335 -0.376312255859375 +47336 -0.416107177734375 +47337 -0.371124267578125 +47338 -0.242279052734375 +47339 -0.069732666015625 +47340 0.125640869140625 +47341 0.31268310546875 +47342 0.45501708984375 +47343 0.554779052734375 +47344 0.61065673828125 +47345 0.610931396484375 +47346 0.531463623046875 +47347 0.3883056640625 +47348 0.23468017578125 +47349 0.095245361328125 +47350 -0.00396728515625 +47351 -0.04852294921875 +47352 -0.055145263671875 +47353 -0.0758056640625 +47354 -0.138702392578125 +47355 -0.209197998046875 +47356 -0.289031982421875 +47357 -0.37884521484375 +47358 -0.456329345703125 +47359 -0.51641845703125 +47360 -0.519287109375 +47361 -0.458251953125 +47362 -0.384796142578125 +47363 -0.323699951171875 +47364 -0.269287109375 +47365 -0.1951904296875 +47366 -0.100006103515625 +47367 -0.01055908203125 +47368 0.1033935546875 +47369 0.24908447265625 +47370 0.373199462890625 +47371 0.45806884765625 +47372 0.511474609375 +47373 0.565399169921875 +47374 0.61138916015625 +47375 0.5897216796875 +47376 0.4906005859375 +47377 0.33148193359375 +47378 0.147796630859375 +47379 -0.01873779296875 +47380 -0.140289306640625 +47381 -0.191986083984375 +47382 -0.184295654296875 +47383 -0.161834716796875 +47384 -0.166595458984375 +47385 -0.19390869140625 +47386 -0.22442626953125 +47387 -0.279754638671875 +47388 -0.3389892578125 +47389 -0.3543701171875 +47390 -0.348175048828125 +47391 -0.32598876953125 +47392 -0.2581787109375 +47393 -0.139801025390625 +47394 0.014617919921875 +47395 0.144378662109375 +47396 0.221038818359375 +47397 0.27069091796875 +47398 0.294036865234375 +47399 0.311767578125 +47400 0.339141845703125 +47401 0.360260009765625 +47402 0.360504150390625 +47403 0.308380126953125 +47404 0.18170166015625 +47405 0.0047607421875 +47406 -0.17559814453125 +47407 -0.3143310546875 +47408 -0.36785888671875 +47409 -0.36248779296875 +47410 -0.343536376953125 +47411 -0.3018798828125 +47412 -0.231414794921875 +47413 -0.117645263671875 +47414 0.007049560546875 +47415 0.087982177734375 +47416 0.13946533203125 +47417 0.17425537109375 +47418 0.188201904296875 +47419 0.171234130859375 +47420 0.118438720703125 +47421 0.05706787109375 +47422 -0.010711669921875 +47423 -0.0914306640625 +47424 -0.162322998046875 +47425 -0.194549560546875 +47426 -0.1492919921875 +47427 -0.02166748046875 +47428 0.124053955078125 +47429 0.211151123046875 +47430 0.240447998046875 +47431 0.242218017578125 +47432 0.2257080078125 +47433 0.194366455078125 +47434 0.115509033203125 +47435 0.0128173828125 +47436 -0.053802490234375 +47437 -0.110626220703125 +47438 -0.199493408203125 +47439 -0.29437255859375 +47440 -0.33221435546875 +47441 -0.27972412109375 +47442 -0.185333251953125 +47443 -0.128204345703125 +47444 -0.115692138671875 +47445 -0.116455078125 +47446 -0.105926513671875 +47447 -0.053955078125 +47448 0.048797607421875 +47449 0.157318115234375 +47450 0.212005615234375 +47451 0.218475341796875 +47452 0.23724365234375 +47453 0.30535888671875 +47454 0.38128662109375 +47455 0.404449462890625 +47456 0.3944091796875 +47457 0.3885498046875 +47458 0.362640380859375 +47459 0.27362060546875 +47460 0.11712646484375 +47461 -0.054901123046875 +47462 -0.19085693359375 +47463 -0.28570556640625 +47464 -0.339263916015625 +47465 -0.3775634765625 +47466 -0.445709228515625 +47467 -0.535064697265625 +47468 -0.629058837890625 +47469 -0.697601318359375 +47470 -0.70391845703125 +47471 -0.6424560546875 +47472 -0.491241455078125 +47473 -0.265716552734375 +47474 -0.023712158203125 +47475 0.201751708984375 +47476 0.375823974609375 +47477 0.485076904296875 +47478 0.56884765625 +47479 0.634765625 +47480 0.63763427734375 +47481 0.5660400390625 +47482 0.4720458984375 +47483 0.40692138671875 +47484 0.3778076171875 +47485 0.376953125 +47486 0.371978759765625 +47487 0.313140869140625 +47488 0.184417724609375 +47489 0.011199951171875 +47490 -0.171051025390625 +47491 -0.33740234375 +47492 -0.47198486328125 +47493 -0.560394287109375 +47494 -0.58056640625 +47495 -0.54754638671875 +47496 -0.508575439453125 +47497 -0.459503173828125 +47498 -0.394378662109375 +47499 -0.35260009765625 +47500 -0.31170654296875 +47501 -0.197418212890625 +47502 -0.007965087890625 +47503 0.207489013671875 +47504 0.409210205078125 +47505 0.57208251953125 +47506 0.66595458984375 +47507 0.65875244140625 +47508 0.56744384765625 +47509 0.431396484375 +47510 0.29443359375 +47511 0.182464599609375 +47512 0.06365966796875 +47513 -0.075958251953125 +47514 -0.189422607421875 +47515 -0.271942138671875 +47516 -0.342529296875 +47517 -0.364166259765625 +47518 -0.327239990234375 +47519 -0.2769775390625 +47520 -0.253692626953125 +47521 -0.24365234375 +47522 -0.1983642578125 +47523 -0.116241455078125 +47524 -0.036834716796875 +47525 0.034881591796875 +47526 0.09124755859375 +47527 0.10888671875 +47528 0.125518798828125 +47529 0.15771484375 +47530 0.17828369140625 +47531 0.17108154296875 +47532 0.129974365234375 +47533 0.082427978515625 +47534 0.027679443359375 +47535 -0.065643310546875 +47536 -0.15936279296875 +47537 -0.21307373046875 +47538 -0.234649658203125 +47539 -0.2001953125 +47540 -0.119171142578125 +47541 -0.024749755859375 +47542 0.085784912109375 +47543 0.178131103515625 +47544 0.215576171875 +47545 0.211456298828125 +47546 0.17523193359375 +47547 0.128753662109375 +47548 0.1019287109375 +47549 0.0743408203125 +47550 0.04327392578125 +47551 0.038177490234375 +47552 0.076263427734375 +47553 0.14105224609375 +47554 0.186431884765625 +47555 0.188812255859375 +47556 0.1390380859375 +47557 0.041778564453125 +47558 -0.079437255859375 +47559 -0.219390869140625 +47560 -0.367828369140625 +47561 -0.494873046875 +47562 -0.556243896484375 +47563 -0.508697509765625 +47564 -0.3756103515625 +47565 -0.218902587890625 +47566 -0.063751220703125 +47567 0.091552734375 +47568 0.23602294921875 +47569 0.342987060546875 +47570 0.39520263671875 +47571 0.389373779296875 +47572 0.324249267578125 +47573 0.224090576171875 +47574 0.124267578125 +47575 0.037078857421875 +47576 -0.010101318359375 +47577 -0.019439697265625 +47578 -0.022796630859375 +47579 -0.001556396484375 +47580 0.056304931640625 +47581 0.106719970703125 +47582 0.096893310546875 +47583 0.042694091796875 +47584 -0.018035888671875 +47585 -0.07586669921875 +47586 -0.11944580078125 +47587 -0.15972900390625 +47588 -0.202606201171875 +47589 -0.24859619140625 +47590 -0.30517578125 +47591 -0.36212158203125 +47592 -0.39141845703125 +47593 -0.35528564453125 +47594 -0.249969482421875 +47595 -0.092864990234375 +47596 0.08905029296875 +47597 0.2352294921875 +47598 0.318817138671875 +47599 0.358642578125 +47600 0.347747802734375 +47601 0.28564453125 +47602 0.223175048828125 +47603 0.196746826171875 +47604 0.179840087890625 +47605 0.155548095703125 +47606 0.151214599609375 +47607 0.156951904296875 +47608 0.13177490234375 +47609 0.100799560546875 +47610 0.087127685546875 +47611 0.05487060546875 +47612 -0.009002685546875 +47613 -0.10400390625 +47614 -0.229400634765625 +47615 -0.35552978515625 +47616 -0.441925048828125 +47617 -0.473846435546875 +47618 -0.464813232421875 +47619 -0.419097900390625 +47620 -0.334320068359375 +47621 -0.227935791015625 +47622 -0.12347412109375 +47623 -0.02764892578125 +47624 0.077667236328125 +47625 0.2132568359375 +47626 0.38885498046875 +47627 0.582794189453125 +47628 0.734039306640625 +47629 0.800140380859375 +47630 0.7783203125 +47631 0.6651611328125 +47632 0.45965576171875 +47633 0.199188232421875 +47634 -0.050689697265625 +47635 -0.23297119140625 +47636 -0.33013916015625 +47637 -0.368408203125 +47638 -0.378936767578125 +47639 -0.376983642578125 +47640 -0.37969970703125 +47641 -0.391510009765625 +47642 -0.385345458984375 +47643 -0.3419189453125 +47644 -0.28289794921875 +47645 -0.251617431640625 +47646 -0.266143798828125 +47647 -0.273345947265625 +47648 -0.216796875 +47649 -0.128265380859375 +47650 -0.068145751953125 +47651 -0.0430908203125 +47652 -0.024444580078125 +47653 0.020721435546875 +47654 0.124481201171875 +47655 0.25787353515625 +47656 0.379119873046875 +47657 0.47991943359375 +47658 0.5281982421875 +47659 0.511138916015625 +47660 0.456207275390625 +47661 0.407470703125 +47662 0.383758544921875 +47663 0.35687255859375 +47664 0.31182861328125 +47665 0.250885009765625 +47666 0.1654052734375 +47667 0.035247802734375 +47668 -0.142059326171875 +47669 -0.33563232421875 +47670 -0.5345458984375 +47671 -0.72186279296875 +47672 -0.836669921875 +47673 -0.8326416015625 +47674 -0.7296142578125 +47675 -0.582550048828125 +47676 -0.440093994140625 +47677 -0.324310302734375 +47678 -0.20147705078125 +47679 -0.044647216796875 +47680 0.103973388671875 +47681 0.202392578125 +47682 0.264495849609375 +47683 0.338897705078125 +47684 0.443817138671875 +47685 0.545074462890625 +47686 0.6173095703125 +47687 0.6524658203125 +47688 0.66339111328125 +47689 0.6561279296875 +47690 0.606781005859375 +47691 0.501190185546875 +47692 0.352783203125 +47693 0.176544189453125 +47694 -0.034820556640625 +47695 -0.258209228515625 +47696 -0.44244384765625 +47697 -0.5753173828125 +47698 -0.65203857421875 +47699 -0.641632080078125 +47700 -0.562164306640625 +47701 -0.458038330078125 +47702 -0.350555419921875 +47703 -0.260528564453125 +47704 -0.192108154296875 +47705 -0.141937255859375 +47706 -0.1021728515625 +47707 -0.062896728515625 +47708 -0.011932373046875 +47709 0.062835693359375 +47710 0.148712158203125 +47711 0.241729736328125 +47712 0.34912109375 +47713 0.457305908203125 +47714 0.54388427734375 +47715 0.5728759765625 +47716 0.506591796875 +47717 0.351226806640625 +47718 0.146514892578125 +47719 -0.05523681640625 +47720 -0.21624755859375 +47721 -0.334930419921875 +47722 -0.402984619140625 +47723 -0.4412841796875 +47724 -0.49578857421875 +47725 -0.5601806640625 +47726 -0.600738525390625 +47727 -0.584228515625 +47728 -0.47930908203125 +47729 -0.27935791015625 +47730 -0.0089111328125 +47731 0.268798828125 +47732 0.482818603515625 +47733 0.60369873046875 +47734 0.650421142578125 +47735 0.66400146484375 +47736 0.6414794921875 +47737 0.572540283203125 +47738 0.498138427734375 +47739 0.439453125 +47740 0.375518798828125 +47741 0.274505615234375 +47742 0.1087646484375 +47743 -0.099395751953125 +47744 -0.3182373046875 +47745 -0.5489501953125 +47746 -0.7738037109375 +47747 -0.86383056640625 +47748 -0.870391845703125 +47749 -0.86895751953125 +47750 -0.861053466796875 +47751 -0.765869140625 +47752 -0.5301513671875 +47753 -0.214691162109375 +47754 0.137359619140625 +47755 0.474822998046875 +47756 0.76239013671875 +47757 0.867462158203125 +47758 0.870361328125 +47759 0.86480712890625 +47760 0.831817626953125 +47761 0.677581787109375 +47762 0.495880126953125 +47763 0.30767822265625 +47764 0.116180419921875 +47765 -0.110748291015625 +47766 -0.381805419921875 +47767 -0.6572265625 +47768 -0.857421875 +47769 -0.870391845703125 +47770 -0.870391845703125 +47771 -0.86444091796875 +47772 -0.85723876953125 +47773 -0.790008544921875 +47774 -0.62847900390625 +47775 -0.3956298828125 +47776 -0.126708984375 +47777 0.150115966796875 +47778 0.424041748046875 +47779 0.670623779296875 +47780 0.854522705078125 +47781 0.866485595703125 +47782 0.86920166015625 +47783 0.8653564453125 +47784 0.857147216796875 +47785 0.766845703125 +47786 0.628509521484375 +47787 0.462127685546875 +47788 0.297210693359375 +47789 0.14862060546875 +47790 -0.00537109375 +47791 -0.15753173828125 +47792 -0.31304931640625 +47793 -0.48876953125 +47794 -0.6416015625 +47795 -0.751373291015625 +47796 -0.84619140625 +47797 -0.861297607421875 +47798 -0.863250732421875 +47799 -0.856597900390625 +47800 -0.7498779296875 +47801 -0.624542236328125 +47802 -0.47808837890625 +47803 -0.253387451171875 +47804 0.003692626953125 +47805 0.2257080078125 +47806 0.427154541015625 +47807 0.643218994140625 +47808 0.855926513671875 +47809 0.870361328125 +47810 0.870361328125 +47811 0.862762451171875 +47812 0.79669189453125 +47813 0.595794677734375 +47814 0.362152099609375 +47815 0.1270751953125 +47816 -0.086944580078125 +47817 -0.2784423828125 +47818 -0.484832763671875 +47819 -0.729583740234375 +47820 -0.86688232421875 +47821 -0.870391845703125 +47822 -0.86859130859375 +47823 -0.86279296875 +47824 -0.817962646484375 +47825 -0.6116943359375 +47826 -0.3128662109375 +47827 0.039398193359375 +47828 0.422821044921875 +47829 0.805145263671875 +47830 0.870361328125 +47831 0.870361328125 +47832 0.860015869140625 +47833 0.727935791015625 +47834 0.48114013671875 +47835 0.2059326171875 +47836 -0.06103515625 +47837 -0.29913330078125 +47838 -0.516204833984375 +47839 -0.7252197265625 +47840 -0.85980224609375 +47841 -0.870391845703125 +47842 -0.870391845703125 +47843 -0.858062744140625 +47844 -0.673004150390625 +47845 -0.42694091796875 +47846 -0.2100830078125 +47847 -0.0362548828125 +47848 0.10943603515625 +47849 0.23516845703125 +47850 0.373687744140625 +47851 0.517791748046875 +47852 0.602783203125 +47853 0.635711669921875 +47854 0.655181884765625 +47855 0.65948486328125 +47856 0.651275634765625 +47857 0.61846923828125 +47858 0.53753662109375 +47859 0.404144287109375 +47860 0.22186279296875 +47861 0.003997802734375 +47862 -0.22100830078125 +47863 -0.42449951171875 +47864 -0.579833984375 +47865 -0.641876220703125 +47866 -0.6177978515625 +47867 -0.575531005859375 +47868 -0.526336669921875 +47869 -0.42645263671875 +47870 -0.2581787109375 +47871 -0.068695068359375 +47872 0.09222412109375 +47873 0.232147216796875 +47874 0.3509521484375 +47875 0.410064697265625 +47876 0.372955322265625 +47877 0.2554931640625 +47878 0.10711669921875 +47879 -0.052886962890625 +47880 -0.186279296875 +47881 -0.23291015625 +47882 -0.209442138671875 +47883 -0.174163818359375 +47884 -0.126739501953125 +47885 -0.048126220703125 +47886 0.0426025390625 +47887 0.10748291015625 +47888 0.1409912109375 +47889 0.19708251953125 +47890 0.273651123046875 +47891 0.31768798828125 +47892 0.341094970703125 +47893 0.368011474609375 +47894 0.37249755859375 +47895 0.30072021484375 +47896 0.1517333984375 +47897 -0.01470947265625 +47898 -0.1883544921875 +47899 -0.372711181640625 +47900 -0.51397705078125 +47901 -0.57177734375 +47902 -0.53948974609375 +47903 -0.43511962890625 +47904 -0.2962646484375 +47905 -0.161102294921875 +47906 -0.0435791015625 +47907 0.060394287109375 +47908 0.13665771484375 +47909 0.170135498046875 +47910 0.16552734375 +47911 0.15728759765625 +47912 0.150787353515625 +47913 0.12200927734375 +47914 0.080108642578125 +47915 0.05126953125 +47916 0.062896728515625 +47917 0.09271240234375 +47918 0.092987060546875 +47919 0.07855224609375 +47920 0.06427001953125 +47921 0.0347900390625 +47922 -0.01171875 +47923 -0.056060791015625 +47924 -0.055511474609375 +47925 -0.010467529296875 +47926 0.02508544921875 +47927 0.025665283203125 +47928 0.017333984375 +47929 0.00189208984375 +47930 -0.03173828125 +47931 -0.071502685546875 +47932 -0.13543701171875 +47933 -0.219970703125 +47934 -0.300506591796875 +47935 -0.376312255859375 +47936 -0.416107177734375 +47937 -0.371124267578125 +47938 -0.242279052734375 +47939 -0.069732666015625 +47940 0.125640869140625 +47941 0.31268310546875 +47942 0.45501708984375 +47943 0.554779052734375 +47944 0.61065673828125 +47945 0.610931396484375 +47946 0.531463623046875 +47947 0.3883056640625 +47948 0.23468017578125 +47949 0.095245361328125 +47950 -0.00396728515625 +47951 -0.04852294921875 +47952 -0.055145263671875 +47953 -0.0758056640625 +47954 -0.138702392578125 +47955 -0.209197998046875 +47956 -0.289031982421875 +47957 -0.37884521484375 +47958 -0.456329345703125 +47959 -0.51641845703125 +47960 -0.519287109375 +47961 -0.458251953125 +47962 -0.384796142578125 +47963 -0.323699951171875 +47964 -0.269287109375 +47965 -0.1951904296875 +47966 -0.100006103515625 +47967 -0.01055908203125 +47968 0.1033935546875 +47969 0.24908447265625 +47970 0.373199462890625 +47971 0.45806884765625 +47972 0.511474609375 +47973 0.565399169921875 +47974 0.61138916015625 +47975 0.5897216796875 +47976 0.4906005859375 +47977 0.33148193359375 +47978 0.147796630859375 +47979 -0.01873779296875 +47980 -0.140289306640625 +47981 -0.191986083984375 +47982 -0.184295654296875 +47983 -0.161834716796875 +47984 -0.166595458984375 +47985 -0.19390869140625 +47986 -0.22442626953125 +47987 -0.279754638671875 +47988 -0.3389892578125 +47989 -0.3543701171875 +47990 -0.348175048828125 +47991 -0.32598876953125 +47992 -0.2581787109375 +47993 -0.139801025390625 +47994 0.014617919921875 +47995 0.144378662109375 +47996 0.221038818359375 +47997 0.27069091796875 +47998 0.294036865234375 +47999 0.311767578125 +48000 0.339141845703125 +48001 0.360260009765625 +48002 0.360504150390625 +48003 0.308380126953125 +48004 0.18170166015625 +48005 0.0047607421875 +48006 -0.17559814453125 +48007 -0.3143310546875 +48008 -0.36785888671875 +48009 -0.36248779296875 +48010 -0.343536376953125 +48011 -0.3018798828125 +48012 -0.231414794921875 +48013 -0.117645263671875 +48014 0.007049560546875 +48015 0.087982177734375 +48016 0.13946533203125 +48017 0.17425537109375 +48018 0.188201904296875 +48019 0.171234130859375 +48020 0.118438720703125 +48021 0.05706787109375 +48022 -0.010711669921875 +48023 -0.0914306640625 +48024 -0.162322998046875 +48025 -0.194549560546875 +48026 -0.1492919921875 +48027 -0.02166748046875 +48028 0.124053955078125 +48029 0.211151123046875 +48030 0.240447998046875 +48031 0.242218017578125 +48032 0.2257080078125 +48033 0.194366455078125 +48034 0.115509033203125 +48035 0.0128173828125 +48036 -0.053802490234375 +48037 -0.110626220703125 +48038 -0.199493408203125 +48039 -0.29437255859375 +48040 -0.33221435546875 +48041 -0.27972412109375 +48042 -0.185333251953125 +48043 -0.128204345703125 +48044 -0.115692138671875 +48045 -0.116455078125 +48046 -0.105926513671875 +48047 -0.053955078125 +48048 0.048797607421875 +48049 0.157318115234375 +48050 0.212005615234375 +48051 0.218475341796875 +48052 0.23724365234375 +48053 0.30535888671875 +48054 0.38128662109375 +48055 0.404449462890625 +48056 0.3944091796875 +48057 0.3885498046875 +48058 0.362640380859375 +48059 0.27362060546875 +48060 0.11712646484375 +48061 -0.054901123046875 +48062 -0.19085693359375 +48063 -0.28570556640625 +48064 -0.339263916015625 +48065 -0.3775634765625 +48066 -0.445709228515625 +48067 -0.535064697265625 +48068 -0.629058837890625 +48069 -0.697601318359375 +48070 -0.70391845703125 +48071 -0.6424560546875 +48072 -0.491241455078125 +48073 -0.265716552734375 +48074 -0.023712158203125 +48075 0.201751708984375 +48076 0.375823974609375 +48077 0.485076904296875 +48078 0.56884765625 +48079 0.634765625 +48080 0.63763427734375 +48081 0.5660400390625 +48082 0.4720458984375 +48083 0.40692138671875 +48084 0.3778076171875 +48085 0.376953125 +48086 0.371978759765625 +48087 0.313140869140625 +48088 0.184417724609375 +48089 0.011199951171875 +48090 -0.171051025390625 +48091 -0.33740234375 +48092 -0.47198486328125 +48093 -0.560394287109375 +48094 -0.58056640625 +48095 -0.54754638671875 +48096 -0.508575439453125 +48097 -0.459503173828125 +48098 -0.394378662109375 +48099 -0.35260009765625 +48100 -0.31170654296875 +48101 -0.197418212890625 +48102 -0.007965087890625 +48103 0.207489013671875 +48104 0.409210205078125 +48105 0.57208251953125 +48106 0.66595458984375 +48107 0.65875244140625 +48108 0.56744384765625 +48109 0.431396484375 +48110 0.29443359375 +48111 0.182464599609375 +48112 0.06365966796875 +48113 -0.075958251953125 +48114 -0.189422607421875 +48115 -0.271942138671875 +48116 -0.342529296875 +48117 -0.364166259765625 +48118 -0.327239990234375 +48119 -0.2769775390625 +48120 -0.253692626953125 +48121 -0.24365234375 +48122 -0.1983642578125 +48123 -0.116241455078125 +48124 -0.036834716796875 +48125 0.034881591796875 +48126 0.09124755859375 +48127 0.10888671875 +48128 0.125518798828125 +48129 0.15771484375 +48130 0.17828369140625 +48131 0.17108154296875 +48132 0.129974365234375 +48133 0.082427978515625 +48134 0.027679443359375 +48135 -0.065643310546875 +48136 -0.15936279296875 +48137 -0.21307373046875 +48138 -0.234649658203125 +48139 -0.2001953125 +48140 -0.119171142578125 +48141 -0.024749755859375 +48142 0.085784912109375 +48143 0.178131103515625 +48144 0.215576171875 +48145 0.211456298828125 +48146 0.17523193359375 +48147 0.128753662109375 +48148 0.1019287109375 +48149 0.0743408203125 +48150 0.04327392578125 +48151 0.038177490234375 +48152 0.076263427734375 +48153 0.14105224609375 +48154 0.186431884765625 +48155 0.188812255859375 +48156 0.1390380859375 +48157 0.041778564453125 +48158 -0.079437255859375 +48159 -0.219390869140625 +48160 -0.367828369140625 +48161 -0.494873046875 +48162 -0.556243896484375 +48163 -0.508697509765625 +48164 -0.3756103515625 +48165 -0.218902587890625 +48166 -0.063751220703125 +48167 0.091552734375 +48168 0.23602294921875 +48169 0.342987060546875 +48170 0.39520263671875 +48171 0.389373779296875 +48172 0.324249267578125 +48173 0.224090576171875 +48174 0.124267578125 +48175 0.037078857421875 +48176 -0.010101318359375 +48177 -0.019439697265625 +48178 -0.022796630859375 +48179 -0.001556396484375 +48180 0.056304931640625 +48181 0.106719970703125 +48182 0.096893310546875 +48183 0.042694091796875 +48184 -0.018035888671875 +48185 -0.07586669921875 +48186 -0.11944580078125 +48187 -0.15972900390625 +48188 -0.202606201171875 +48189 -0.24859619140625 +48190 -0.30517578125 +48191 -0.36212158203125 +48192 -0.39141845703125 +48193 -0.35528564453125 +48194 -0.249969482421875 +48195 -0.092864990234375 +48196 0.08905029296875 +48197 0.2352294921875 +48198 0.318817138671875 +48199 0.358642578125 +48200 0.347747802734375 +48201 0.28564453125 +48202 0.223175048828125 +48203 0.196746826171875 +48204 0.179840087890625 +48205 0.155548095703125 +48206 0.151214599609375 +48207 0.156951904296875 +48208 0.13177490234375 +48209 0.100799560546875 +48210 0.087127685546875 +48211 0.05487060546875 +48212 -0.009002685546875 +48213 -0.10400390625 +48214 -0.229400634765625 +48215 -0.35552978515625 +48216 -0.441925048828125 +48217 -0.473846435546875 +48218 -0.464813232421875 +48219 -0.419097900390625 +48220 -0.334320068359375 +48221 -0.227935791015625 +48222 -0.12347412109375 +48223 -0.02764892578125 +48224 0.077667236328125 +48225 0.2132568359375 +48226 0.38885498046875 +48227 0.582794189453125 +48228 0.734039306640625 +48229 0.800140380859375 +48230 0.7783203125 +48231 0.6651611328125 +48232 0.45965576171875 +48233 0.199188232421875 +48234 -0.050689697265625 +48235 -0.23297119140625 +48236 -0.33013916015625 +48237 -0.368408203125 +48238 -0.378936767578125 +48239 -0.376983642578125 +48240 -0.37969970703125 +48241 -0.391510009765625 +48242 -0.385345458984375 +48243 -0.3419189453125 +48244 -0.28289794921875 +48245 -0.251617431640625 +48246 -0.266143798828125 +48247 -0.273345947265625 +48248 -0.216796875 +48249 -0.128265380859375 +48250 -0.068145751953125 +48251 -0.0430908203125 +48252 -0.024444580078125 +48253 0.020721435546875 +48254 0.124481201171875 +48255 0.25787353515625 +48256 0.379119873046875 +48257 0.47991943359375 +48258 0.5281982421875 +48259 0.511138916015625 +48260 0.456207275390625 +48261 0.407470703125 +48262 0.383758544921875 +48263 0.35687255859375 +48264 0.31182861328125 +48265 0.250885009765625 +48266 0.1654052734375 +48267 0.035247802734375 +48268 -0.142059326171875 +48269 -0.33563232421875 +48270 -0.5345458984375 +48271 -0.72186279296875 +48272 -0.836669921875 +48273 -0.8326416015625 +48274 -0.7296142578125 +48275 -0.582550048828125 +48276 -0.440093994140625 +48277 -0.324310302734375 +48278 -0.20147705078125 +48279 -0.044647216796875 +48280 0.103973388671875 +48281 0.202392578125 +48282 0.264495849609375 +48283 0.338897705078125 +48284 0.443817138671875 +48285 0.545074462890625 +48286 0.6173095703125 +48287 0.6524658203125 +48288 0.66339111328125 +48289 0.6561279296875 +48290 0.606781005859375 +48291 0.501190185546875 +48292 0.352783203125 +48293 0.176544189453125 +48294 -0.034820556640625 +48295 -0.258209228515625 +48296 -0.44244384765625 +48297 -0.5753173828125 +48298 -0.65203857421875 +48299 -0.641632080078125 +48300 -0.562164306640625 +48301 -0.458038330078125 +48302 -0.350555419921875 +48303 -0.260528564453125 +48304 -0.192108154296875 +48305 -0.141937255859375 +48306 -0.1021728515625 +48307 -0.062896728515625 +48308 -0.011932373046875 +48309 0.062835693359375 +48310 0.148712158203125 +48311 0.241729736328125 +48312 0.34912109375 +48313 0.457305908203125 +48314 0.54388427734375 +48315 0.5728759765625 +48316 0.506591796875 +48317 0.351226806640625 +48318 0.146514892578125 +48319 -0.05523681640625 +48320 -0.21624755859375 +48321 -0.334930419921875 +48322 -0.402984619140625 +48323 -0.4412841796875 +48324 -0.49578857421875 +48325 -0.5601806640625 +48326 -0.600738525390625 +48327 -0.584228515625 +48328 -0.47930908203125 +48329 -0.27935791015625 +48330 -0.0089111328125 +48331 0.268798828125 +48332 0.482818603515625 +48333 0.60369873046875 +48334 0.650421142578125 +48335 0.66400146484375 +48336 0.6414794921875 +48337 0.572540283203125 +48338 0.498138427734375 +48339 0.439453125 +48340 0.375518798828125 +48341 0.274505615234375 +48342 0.1087646484375 +48343 -0.099395751953125 +48344 -0.3182373046875 +48345 -0.5489501953125 +48346 -0.7738037109375 +48347 -0.86383056640625 +48348 -0.870391845703125 +48349 -0.86895751953125 +48350 -0.861053466796875 +48351 -0.765869140625 +48352 -0.5301513671875 +48353 -0.214691162109375 +48354 0.137359619140625 +48355 0.474822998046875 +48356 0.76239013671875 +48357 0.867462158203125 +48358 0.870361328125 +48359 0.86480712890625 +48360 0.831817626953125 +48361 0.677581787109375 +48362 0.495880126953125 +48363 0.30767822265625 +48364 0.116180419921875 +48365 -0.110748291015625 +48366 -0.381805419921875 +48367 -0.6572265625 +48368 -0.857421875 +48369 -0.870391845703125 +48370 -0.870391845703125 +48371 -0.86444091796875 +48372 -0.85723876953125 +48373 -0.790008544921875 +48374 -0.62847900390625 +48375 -0.3956298828125 +48376 -0.126708984375 +48377 0.150115966796875 +48378 0.424041748046875 +48379 0.670623779296875 +48380 0.854522705078125 +48381 0.866485595703125 +48382 0.86920166015625 +48383 0.8653564453125 +48384 0.857147216796875 +48385 0.766845703125 +48386 0.628509521484375 +48387 0.462127685546875 +48388 0.297210693359375 +48389 0.14862060546875 +48390 -0.00537109375 +48391 -0.15753173828125 +48392 -0.31304931640625 +48393 -0.48876953125 +48394 -0.6416015625 +48395 -0.751373291015625 +48396 -0.84619140625 +48397 -0.861297607421875 +48398 -0.863250732421875 +48399 -0.856597900390625 +48400 -0.7498779296875 +48401 -0.624542236328125 +48402 -0.47808837890625 +48403 -0.253387451171875 +48404 0.003692626953125 +48405 0.2257080078125 +48406 0.427154541015625 +48407 0.643218994140625 +48408 0.855926513671875 +48409 0.870361328125 +48410 0.870361328125 +48411 0.862762451171875 +48412 0.79669189453125 +48413 0.595794677734375 +48414 0.362152099609375 +48415 0.1270751953125 +48416 -0.086944580078125 +48417 -0.2784423828125 +48418 -0.484832763671875 +48419 -0.729583740234375 +48420 -0.86688232421875 +48421 -0.870391845703125 +48422 -0.86859130859375 +48423 -0.86279296875 +48424 -0.817962646484375 +48425 -0.6116943359375 +48426 -0.3128662109375 +48427 0.039398193359375 +48428 0.422821044921875 +48429 0.805145263671875 +48430 0.870361328125 +48431 0.870361328125 +48432 0.860015869140625 +48433 0.727935791015625 +48434 0.48114013671875 +48435 0.2059326171875 +48436 -0.06103515625 +48437 -0.29913330078125 +48438 -0.516204833984375 +48439 -0.7252197265625 +48440 -0.85980224609375 +48441 -0.870391845703125 +48442 -0.870391845703125 +48443 -0.858062744140625 +48444 -0.673004150390625 +48445 -0.42694091796875 +48446 -0.2100830078125 +48447 -0.0362548828125 +48448 0.10943603515625 +48449 0.23516845703125 +48450 0.373687744140625 +48451 0.517791748046875 +48452 0.602783203125 +48453 0.635711669921875 +48454 0.655181884765625 +48455 0.65948486328125 +48456 0.651275634765625 +48457 0.61846923828125 +48458 0.53753662109375 +48459 0.404144287109375 +48460 0.22186279296875 +48461 0.003997802734375 +48462 -0.22100830078125 +48463 -0.42449951171875 +48464 -0.579833984375 +48465 -0.641876220703125 +48466 -0.6177978515625 +48467 -0.575531005859375 +48468 -0.526336669921875 +48469 -0.42645263671875 +48470 -0.2581787109375 +48471 -0.068695068359375 +48472 0.09222412109375 +48473 0.232147216796875 +48474 0.3509521484375 +48475 0.410064697265625 +48476 0.372955322265625 +48477 0.2554931640625 +48478 0.10711669921875 +48479 -0.052886962890625 +48480 -0.186279296875 +48481 -0.23291015625 +48482 -0.209442138671875 +48483 -0.174163818359375 +48484 -0.126739501953125 +48485 -0.048126220703125 +48486 0.0426025390625 +48487 0.10748291015625 +48488 0.1409912109375 +48489 0.19708251953125 +48490 0.273651123046875 +48491 0.31768798828125 +48492 0.341094970703125 +48493 0.368011474609375 +48494 0.37249755859375 +48495 0.30072021484375 +48496 0.1517333984375 +48497 -0.01470947265625 +48498 -0.1883544921875 +48499 -0.372711181640625 +48500 -0.51397705078125 +48501 -0.57177734375 +48502 -0.53948974609375 +48503 -0.43511962890625 +48504 -0.2962646484375 +48505 -0.161102294921875 +48506 -0.0435791015625 +48507 0.060394287109375 +48508 0.13665771484375 +48509 0.170135498046875 +48510 0.16552734375 +48511 0.15728759765625 +48512 0.150787353515625 +48513 0.12200927734375 +48514 0.080108642578125 +48515 0.05126953125 +48516 0.062896728515625 +48517 0.09271240234375 +48518 0.092987060546875 +48519 0.07855224609375 +48520 0.06427001953125 +48521 0.0347900390625 +48522 -0.01171875 +48523 -0.056060791015625 +48524 -0.055511474609375 +48525 -0.010467529296875 +48526 0.02508544921875 +48527 0.025665283203125 +48528 0.017333984375 +48529 0.00189208984375 +48530 -0.03173828125 +48531 -0.071502685546875 +48532 -0.13543701171875 +48533 -0.219970703125 +48534 -0.300506591796875 +48535 -0.376312255859375 +48536 -0.416107177734375 +48537 -0.371124267578125 +48538 -0.242279052734375 +48539 -0.069732666015625 +48540 0.125640869140625 +48541 0.31268310546875 +48542 0.45501708984375 +48543 0.554779052734375 +48544 0.61065673828125 +48545 0.610931396484375 +48546 0.531463623046875 +48547 0.3883056640625 +48548 0.23468017578125 +48549 0.095245361328125 +48550 -0.00396728515625 +48551 -0.04852294921875 +48552 -0.055145263671875 +48553 -0.0758056640625 +48554 -0.138702392578125 +48555 -0.209197998046875 +48556 -0.289031982421875 +48557 -0.37884521484375 +48558 -0.456329345703125 +48559 -0.51641845703125 +48560 -0.519287109375 +48561 -0.458251953125 +48562 -0.384796142578125 +48563 -0.323699951171875 +48564 -0.269287109375 +48565 -0.1951904296875 +48566 -0.100006103515625 +48567 -0.01055908203125 +48568 0.1033935546875 +48569 0.24908447265625 +48570 0.373199462890625 +48571 0.45806884765625 +48572 0.511474609375 +48573 0.565399169921875 +48574 0.61138916015625 +48575 0.5897216796875 +48576 0.4906005859375 +48577 0.33148193359375 +48578 0.147796630859375 +48579 -0.01873779296875 +48580 -0.140289306640625 +48581 -0.191986083984375 +48582 -0.184295654296875 +48583 -0.161834716796875 +48584 -0.166595458984375 +48585 -0.19390869140625 +48586 -0.22442626953125 +48587 -0.279754638671875 +48588 -0.3389892578125 +48589 -0.3543701171875 +48590 -0.348175048828125 +48591 -0.32598876953125 +48592 -0.2581787109375 +48593 -0.139801025390625 +48594 0.014617919921875 +48595 0.144378662109375 +48596 0.221038818359375 +48597 0.27069091796875 +48598 0.294036865234375 +48599 0.311767578125 +48600 0.339141845703125 +48601 0.360260009765625 +48602 0.360504150390625 +48603 0.308380126953125 +48604 0.18170166015625 +48605 0.0047607421875 +48606 -0.17559814453125 +48607 -0.3143310546875 +48608 -0.36785888671875 +48609 -0.36248779296875 +48610 -0.343536376953125 +48611 -0.3018798828125 +48612 -0.231414794921875 +48613 -0.117645263671875 +48614 0.007049560546875 +48615 0.087982177734375 +48616 0.13946533203125 +48617 0.17425537109375 +48618 0.188201904296875 +48619 0.171234130859375 +48620 0.118438720703125 +48621 0.05706787109375 +48622 -0.010711669921875 +48623 -0.0914306640625 +48624 -0.162322998046875 +48625 -0.194549560546875 +48626 -0.1492919921875 +48627 -0.02166748046875 +48628 0.124053955078125 +48629 0.211151123046875 +48630 0.240447998046875 +48631 0.242218017578125 +48632 0.2257080078125 +48633 0.194366455078125 +48634 0.115509033203125 +48635 0.0128173828125 +48636 -0.053802490234375 +48637 -0.110626220703125 +48638 -0.199493408203125 +48639 -0.29437255859375 +48640 -0.33221435546875 +48641 -0.27972412109375 +48642 -0.185333251953125 +48643 -0.128204345703125 +48644 -0.115692138671875 +48645 -0.116455078125 +48646 -0.105926513671875 +48647 -0.053955078125 +48648 0.048797607421875 +48649 0.157318115234375 +48650 0.212005615234375 +48651 0.218475341796875 +48652 0.23724365234375 +48653 0.30535888671875 +48654 0.38128662109375 +48655 0.404449462890625 +48656 0.3944091796875 +48657 0.3885498046875 +48658 0.362640380859375 +48659 0.27362060546875 +48660 0.11712646484375 +48661 -0.054901123046875 +48662 -0.19085693359375 +48663 -0.28570556640625 +48664 -0.339263916015625 +48665 -0.3775634765625 +48666 -0.445709228515625 +48667 -0.535064697265625 +48668 -0.629058837890625 +48669 -0.697601318359375 +48670 -0.70391845703125 +48671 -0.6424560546875 +48672 -0.491241455078125 +48673 -0.265716552734375 +48674 -0.023712158203125 +48675 0.201751708984375 +48676 0.375823974609375 +48677 0.485076904296875 +48678 0.56884765625 +48679 0.634765625 +48680 0.63763427734375 +48681 0.5660400390625 +48682 0.4720458984375 +48683 0.40692138671875 +48684 0.3778076171875 +48685 0.376953125 +48686 0.371978759765625 +48687 0.313140869140625 +48688 0.184417724609375 +48689 0.011199951171875 +48690 -0.171051025390625 +48691 -0.33740234375 +48692 -0.47198486328125 +48693 -0.560394287109375 +48694 -0.58056640625 +48695 -0.54754638671875 +48696 -0.508575439453125 +48697 -0.459503173828125 +48698 -0.394378662109375 +48699 -0.35260009765625 +48700 -0.31170654296875 +48701 -0.197418212890625 +48702 -0.007965087890625 +48703 0.207489013671875 +48704 0.409210205078125 +48705 0.57208251953125 +48706 0.66595458984375 +48707 0.65875244140625 +48708 0.56744384765625 +48709 0.431396484375 +48710 0.29443359375 +48711 0.182464599609375 +48712 0.06365966796875 +48713 -0.075958251953125 +48714 -0.189422607421875 +48715 -0.271942138671875 +48716 -0.342529296875 +48717 -0.364166259765625 +48718 -0.327239990234375 +48719 -0.2769775390625 +48720 -0.253692626953125 +48721 -0.24365234375 +48722 -0.1983642578125 +48723 -0.116241455078125 +48724 -0.036834716796875 +48725 0.034881591796875 +48726 0.09124755859375 +48727 0.10888671875 +48728 0.125518798828125 +48729 0.15771484375 +48730 0.17828369140625 +48731 0.17108154296875 +48732 0.129974365234375 +48733 0.082427978515625 +48734 0.027679443359375 +48735 -0.065643310546875 +48736 -0.15936279296875 +48737 -0.21307373046875 +48738 -0.234649658203125 +48739 -0.2001953125 +48740 -0.119171142578125 +48741 -0.024749755859375 +48742 0.085784912109375 +48743 0.178131103515625 +48744 0.215576171875 +48745 0.211456298828125 +48746 0.17523193359375 +48747 0.128753662109375 +48748 0.1019287109375 +48749 0.0743408203125 +48750 0.04327392578125 +48751 0.038177490234375 +48752 0.076263427734375 +48753 0.14105224609375 +48754 0.186431884765625 +48755 0.188812255859375 +48756 0.1390380859375 +48757 0.041778564453125 +48758 -0.079437255859375 +48759 -0.219390869140625 +48760 -0.367828369140625 +48761 -0.494873046875 +48762 -0.556243896484375 +48763 -0.508697509765625 +48764 -0.3756103515625 +48765 -0.218902587890625 +48766 -0.063751220703125 +48767 0.091552734375 +48768 0.23602294921875 +48769 0.342987060546875 +48770 0.39520263671875 +48771 0.389373779296875 +48772 0.324249267578125 +48773 0.224090576171875 +48774 0.124267578125 +48775 0.037078857421875 +48776 -0.010101318359375 +48777 -0.019439697265625 +48778 -0.022796630859375 +48779 -0.001556396484375 +48780 0.056304931640625 +48781 0.106719970703125 +48782 0.096893310546875 +48783 0.042694091796875 +48784 -0.018035888671875 +48785 -0.07586669921875 +48786 -0.11944580078125 +48787 -0.15972900390625 +48788 -0.202606201171875 +48789 -0.24859619140625 +48790 -0.30517578125 +48791 -0.36212158203125 +48792 -0.39141845703125 +48793 -0.35528564453125 +48794 -0.249969482421875 +48795 -0.092864990234375 +48796 0.08905029296875 +48797 0.2352294921875 +48798 0.318817138671875 +48799 0.358642578125 +48800 0.347747802734375 +48801 0.28564453125 +48802 0.223175048828125 +48803 0.196746826171875 +48804 0.179840087890625 +48805 0.155548095703125 +48806 0.151214599609375 +48807 0.156951904296875 +48808 0.13177490234375 +48809 0.100799560546875 +48810 0.087127685546875 +48811 0.05487060546875 +48812 -0.009002685546875 +48813 -0.10400390625 +48814 -0.229400634765625 +48815 -0.35552978515625 +48816 -0.441925048828125 +48817 -0.473846435546875 +48818 -0.464813232421875 +48819 -0.419097900390625 +48820 -0.334320068359375 +48821 -0.227935791015625 +48822 -0.12347412109375 +48823 -0.02764892578125 +48824 0.077667236328125 +48825 0.2132568359375 +48826 0.38885498046875 +48827 0.582794189453125 +48828 0.734039306640625 +48829 0.800140380859375 +48830 0.7783203125 +48831 0.6651611328125 +48832 0.45965576171875 +48833 0.199188232421875 +48834 -0.050689697265625 +48835 -0.23297119140625 +48836 -0.33013916015625 +48837 -0.368408203125 +48838 -0.378936767578125 +48839 -0.376983642578125 +48840 -0.37969970703125 +48841 -0.391510009765625 +48842 -0.385345458984375 +48843 -0.3419189453125 +48844 -0.28289794921875 +48845 -0.251617431640625 +48846 -0.266143798828125 +48847 -0.273345947265625 +48848 -0.216796875 +48849 -0.128265380859375 +48850 -0.068145751953125 +48851 -0.0430908203125 +48852 -0.024444580078125 +48853 0.020721435546875 +48854 0.124481201171875 +48855 0.25787353515625 +48856 0.379119873046875 +48857 0.47991943359375 +48858 0.5281982421875 +48859 0.511138916015625 +48860 0.456207275390625 +48861 0.407470703125 +48862 0.383758544921875 +48863 0.35687255859375 +48864 0.31182861328125 +48865 0.250885009765625 +48866 0.1654052734375 +48867 0.035247802734375 +48868 -0.142059326171875 +48869 -0.33563232421875 +48870 -0.5345458984375 +48871 -0.72186279296875 +48872 -0.836669921875 +48873 -0.8326416015625 +48874 -0.7296142578125 +48875 -0.582550048828125 +48876 -0.440093994140625 +48877 -0.324310302734375 +48878 -0.20147705078125 +48879 -0.044647216796875 +48880 0.103973388671875 +48881 0.202392578125 +48882 0.264495849609375 +48883 0.338897705078125 +48884 0.443817138671875 +48885 0.545074462890625 +48886 0.6173095703125 +48887 0.6524658203125 +48888 0.66339111328125 +48889 0.6561279296875 +48890 0.606781005859375 +48891 0.501190185546875 +48892 0.352783203125 +48893 0.176544189453125 +48894 -0.034820556640625 +48895 -0.258209228515625 +48896 -0.44244384765625 +48897 -0.5753173828125 +48898 -0.65203857421875 +48899 -0.641632080078125 +48900 -0.562164306640625 +48901 -0.458038330078125 +48902 -0.350555419921875 +48903 -0.260528564453125 +48904 -0.192108154296875 +48905 -0.141937255859375 +48906 -0.1021728515625 +48907 -0.062896728515625 +48908 -0.011932373046875 +48909 0.062835693359375 +48910 0.148712158203125 +48911 0.241729736328125 +48912 0.34912109375 +48913 0.457305908203125 +48914 0.54388427734375 +48915 0.5728759765625 +48916 0.506591796875 +48917 0.351226806640625 +48918 0.146514892578125 +48919 -0.05523681640625 +48920 -0.21624755859375 +48921 -0.334930419921875 +48922 -0.402984619140625 +48923 -0.4412841796875 +48924 -0.49578857421875 +48925 -0.5601806640625 +48926 -0.600738525390625 +48927 -0.584228515625 +48928 -0.47930908203125 +48929 -0.27935791015625 +48930 -0.0089111328125 +48931 0.268798828125 +48932 0.482818603515625 +48933 0.60369873046875 +48934 0.650421142578125 +48935 0.66400146484375 +48936 0.6414794921875 +48937 0.572540283203125 +48938 0.498138427734375 +48939 0.439453125 +48940 0.375518798828125 +48941 0.274505615234375 +48942 0.1087646484375 +48943 -0.099395751953125 +48944 -0.3182373046875 +48945 -0.5489501953125 +48946 -0.7738037109375 +48947 -0.86383056640625 +48948 -0.870391845703125 +48949 -0.86895751953125 +48950 -0.861053466796875 +48951 -0.765869140625 +48952 -0.5301513671875 +48953 -0.214691162109375 +48954 0.137359619140625 +48955 0.474822998046875 +48956 0.76239013671875 +48957 0.867462158203125 +48958 0.870361328125 +48959 0.86480712890625 +48960 0.831817626953125 +48961 0.677581787109375 +48962 0.495880126953125 +48963 0.30767822265625 +48964 0.116180419921875 +48965 -0.110748291015625 +48966 -0.381805419921875 +48967 -0.6572265625 +48968 -0.857421875 +48969 -0.870391845703125 +48970 -0.870391845703125 +48971 -0.86444091796875 +48972 -0.85723876953125 +48973 -0.790008544921875 +48974 -0.62847900390625 +48975 -0.3956298828125 +48976 -0.126708984375 +48977 0.150115966796875 +48978 0.424041748046875 +48979 0.670623779296875 +48980 0.854522705078125 +48981 0.866485595703125 +48982 0.86920166015625 +48983 0.8653564453125 +48984 0.857147216796875 +48985 0.766845703125 +48986 0.628509521484375 +48987 0.462127685546875 +48988 0.297210693359375 +48989 0.14862060546875 +48990 -0.00537109375 +48991 -0.15753173828125 +48992 -0.31304931640625 +48993 -0.48876953125 +48994 -0.6416015625 +48995 -0.751373291015625 +48996 -0.84619140625 +48997 -0.861297607421875 +48998 -0.863250732421875 +48999 -0.856597900390625 +49000 -0.7498779296875 +49001 -0.624542236328125 +49002 -0.47808837890625 +49003 -0.253387451171875 +49004 0.003692626953125 +49005 0.2257080078125 +49006 0.427154541015625 +49007 0.643218994140625 +49008 0.855926513671875 +49009 0.870361328125 +49010 0.870361328125 +49011 0.862762451171875 +49012 0.79669189453125 +49013 0.595794677734375 +49014 0.362152099609375 +49015 0.1270751953125 +49016 -0.086944580078125 +49017 -0.2784423828125 +49018 -0.484832763671875 +49019 -0.729583740234375 +49020 -0.86688232421875 +49021 -0.870391845703125 +49022 -0.86859130859375 +49023 -0.86279296875 +49024 -0.817962646484375 +49025 -0.6116943359375 +49026 -0.3128662109375 +49027 0.039398193359375 +49028 0.422821044921875 +49029 0.805145263671875 +49030 0.870361328125 +49031 0.870361328125 +49032 0.860015869140625 +49033 0.727935791015625 +49034 0.48114013671875 +49035 0.2059326171875 +49036 -0.06103515625 +49037 -0.29913330078125 +49038 -0.516204833984375 +49039 -0.7252197265625 +49040 -0.85980224609375 +49041 -0.870391845703125 +49042 -0.870391845703125 +49043 -0.858062744140625 +49044 -0.673004150390625 +49045 -0.42694091796875 +49046 -0.2100830078125 +49047 -0.0362548828125 +49048 0.10943603515625 +49049 0.23516845703125 +49050 0.373687744140625 +49051 0.517791748046875 +49052 0.602783203125 +49053 0.635711669921875 +49054 0.655181884765625 +49055 0.65948486328125 +49056 0.651275634765625 +49057 0.61846923828125 +49058 0.53753662109375 +49059 0.404144287109375 +49060 0.22186279296875 +49061 0.003997802734375 +49062 -0.22100830078125 +49063 -0.42449951171875 +49064 -0.579833984375 +49065 -0.641876220703125 +49066 -0.6177978515625 +49067 -0.575531005859375 +49068 -0.526336669921875 +49069 -0.42645263671875 +49070 -0.2581787109375 +49071 -0.068695068359375 +49072 0.09222412109375 +49073 0.232147216796875 +49074 0.3509521484375 +49075 0.410064697265625 +49076 0.372955322265625 +49077 0.2554931640625 +49078 0.10711669921875 +49079 -0.052886962890625 +49080 -0.186279296875 +49081 -0.23291015625 +49082 -0.209442138671875 +49083 -0.174163818359375 +49084 -0.126739501953125 +49085 -0.048126220703125 +49086 0.0426025390625 +49087 0.10748291015625 +49088 0.1409912109375 +49089 0.19708251953125 +49090 0.273651123046875 +49091 0.31768798828125 +49092 0.341094970703125 +49093 0.368011474609375 +49094 0.37249755859375 +49095 0.30072021484375 +49096 0.1517333984375 +49097 -0.01470947265625 +49098 -0.1883544921875 +49099 -0.372711181640625 +49100 -0.51397705078125 +49101 -0.57177734375 +49102 -0.53948974609375 +49103 -0.43511962890625 +49104 -0.2962646484375 +49105 -0.161102294921875 +49106 -0.0435791015625 +49107 0.060394287109375 +49108 0.13665771484375 +49109 0.170135498046875 +49110 0.16552734375 +49111 0.15728759765625 +49112 0.150787353515625 +49113 0.12200927734375 +49114 0.080108642578125 +49115 0.05126953125 +49116 0.062896728515625 +49117 0.09271240234375 +49118 0.092987060546875 +49119 0.07855224609375 +49120 0.06427001953125 +49121 0.0347900390625 +49122 -0.01171875 +49123 -0.056060791015625 +49124 -0.055511474609375 +49125 -0.010467529296875 +49126 0.02508544921875 +49127 0.025665283203125 +49128 0.017333984375 +49129 0.00189208984375 +49130 -0.03173828125 +49131 -0.071502685546875 +49132 -0.13543701171875 +49133 -0.219970703125 +49134 -0.300506591796875 +49135 -0.376312255859375 +49136 -0.416107177734375 +49137 -0.371124267578125 +49138 -0.242279052734375 +49139 -0.069732666015625 +49140 0.125640869140625 +49141 0.31268310546875 +49142 0.45501708984375 +49143 0.554779052734375 +49144 0.61065673828125 +49145 0.610931396484375 +49146 0.531463623046875 +49147 0.3883056640625 +49148 0.23468017578125 +49149 0.095245361328125 +49150 -0.00396728515625 +49151 -0.04852294921875 +49152 -0.055145263671875 +49153 -0.0758056640625 +49154 -0.138702392578125 +49155 -0.209197998046875 +49156 -0.289031982421875 +49157 -0.37884521484375 +49158 -0.456329345703125 +49159 -0.51641845703125 +49160 -0.519287109375 +49161 -0.458251953125 +49162 -0.384796142578125 +49163 -0.323699951171875 +49164 -0.269287109375 +49165 -0.1951904296875 +49166 -0.100006103515625 +49167 -0.01055908203125 +49168 0.1033935546875 +49169 0.24908447265625 +49170 0.373199462890625 +49171 0.45806884765625 +49172 0.511474609375 +49173 0.565399169921875 +49174 0.61138916015625 +49175 0.5897216796875 +49176 0.4906005859375 +49177 0.33148193359375 +49178 0.147796630859375 +49179 -0.01873779296875 +49180 -0.140289306640625 +49181 -0.191986083984375 +49182 -0.184295654296875 +49183 -0.161834716796875 +49184 -0.166595458984375 +49185 -0.19390869140625 +49186 -0.22442626953125 +49187 -0.279754638671875 +49188 -0.3389892578125 +49189 -0.3543701171875 +49190 -0.348175048828125 +49191 -0.32598876953125 +49192 -0.2581787109375 +49193 -0.139801025390625 +49194 0.014617919921875 +49195 0.144378662109375 +49196 0.221038818359375 +49197 0.27069091796875 +49198 0.294036865234375 +49199 0.311767578125 +49200 0.339141845703125 +49201 0.360260009765625 +49202 0.360504150390625 +49203 0.308380126953125 +49204 0.18170166015625 +49205 0.0047607421875 +49206 -0.17559814453125 +49207 -0.3143310546875 +49208 -0.36785888671875 +49209 -0.36248779296875 +49210 -0.343536376953125 +49211 -0.3018798828125 +49212 -0.231414794921875 +49213 -0.117645263671875 +49214 0.007049560546875 +49215 0.087982177734375 +49216 0.13946533203125 +49217 0.17425537109375 +49218 0.188201904296875 +49219 0.171234130859375 +49220 0.118438720703125 +49221 0.05706787109375 +49222 -0.010711669921875 +49223 -0.0914306640625 +49224 -0.162322998046875 +49225 -0.194549560546875 +49226 -0.1492919921875 +49227 -0.02166748046875 +49228 0.124053955078125 +49229 0.211151123046875 +49230 0.240447998046875 +49231 0.242218017578125 +49232 0.2257080078125 +49233 0.194366455078125 +49234 0.115509033203125 +49235 0.0128173828125 +49236 -0.053802490234375 +49237 -0.110626220703125 +49238 -0.199493408203125 +49239 -0.29437255859375 +49240 -0.33221435546875 +49241 -0.27972412109375 +49242 -0.185333251953125 +49243 -0.128204345703125 +49244 -0.115692138671875 +49245 -0.116455078125 +49246 -0.105926513671875 +49247 -0.053955078125 +49248 0.048797607421875 +49249 0.157318115234375 +49250 0.212005615234375 +49251 0.218475341796875 +49252 0.23724365234375 +49253 0.30535888671875 +49254 0.38128662109375 +49255 0.404449462890625 +49256 0.3944091796875 +49257 0.3885498046875 +49258 0.362640380859375 +49259 0.27362060546875 +49260 0.11712646484375 +49261 -0.054901123046875 +49262 -0.19085693359375 +49263 -0.28570556640625 +49264 -0.339263916015625 +49265 -0.3775634765625 +49266 -0.445709228515625 +49267 -0.535064697265625 +49268 -0.629058837890625 +49269 -0.697601318359375 +49270 -0.70391845703125 +49271 -0.6424560546875 +49272 -0.491241455078125 +49273 -0.265716552734375 +49274 -0.023712158203125 +49275 0.201751708984375 +49276 0.375823974609375 +49277 0.485076904296875 +49278 0.56884765625 +49279 0.634765625 +49280 0.63763427734375 +49281 0.5660400390625 +49282 0.4720458984375 +49283 0.40692138671875 +49284 0.3778076171875 +49285 0.376953125 +49286 0.371978759765625 +49287 0.313140869140625 +49288 0.184417724609375 +49289 0.011199951171875 +49290 -0.171051025390625 +49291 -0.33740234375 +49292 -0.47198486328125 +49293 -0.560394287109375 +49294 -0.58056640625 +49295 -0.54754638671875 +49296 -0.508575439453125 +49297 -0.459503173828125 +49298 -0.394378662109375 +49299 -0.35260009765625 +49300 -0.31170654296875 +49301 -0.197418212890625 +49302 -0.007965087890625 +49303 0.207489013671875 +49304 0.409210205078125 +49305 0.57208251953125 +49306 0.66595458984375 +49307 0.65875244140625 +49308 0.56744384765625 +49309 0.431396484375 +49310 0.29443359375 +49311 0.182464599609375 +49312 0.06365966796875 +49313 -0.075958251953125 +49314 -0.189422607421875 +49315 -0.271942138671875 +49316 -0.342529296875 +49317 -0.364166259765625 +49318 -0.327239990234375 +49319 -0.2769775390625 +49320 -0.253692626953125 +49321 -0.24365234375 +49322 -0.1983642578125 +49323 -0.116241455078125 +49324 -0.036834716796875 +49325 0.034881591796875 +49326 0.09124755859375 +49327 0.10888671875 +49328 0.125518798828125 +49329 0.15771484375 +49330 0.17828369140625 +49331 0.17108154296875 +49332 0.129974365234375 +49333 0.082427978515625 +49334 0.027679443359375 +49335 -0.065643310546875 +49336 -0.15936279296875 +49337 -0.21307373046875 +49338 -0.234649658203125 +49339 -0.2001953125 +49340 -0.119171142578125 +49341 -0.024749755859375 +49342 0.085784912109375 +49343 0.178131103515625 +49344 0.215576171875 +49345 0.211456298828125 +49346 0.17523193359375 +49347 0.128753662109375 +49348 0.1019287109375 +49349 0.0743408203125 +49350 0.04327392578125 +49351 0.038177490234375 +49352 0.076263427734375 +49353 0.14105224609375 +49354 0.186431884765625 +49355 0.188812255859375 +49356 0.1390380859375 +49357 0.041778564453125 +49358 -0.079437255859375 +49359 -0.219390869140625 +49360 -0.367828369140625 +49361 -0.494873046875 +49362 -0.556243896484375 +49363 -0.508697509765625 +49364 -0.3756103515625 +49365 -0.218902587890625 +49366 -0.063751220703125 +49367 0.091552734375 +49368 0.23602294921875 +49369 0.342987060546875 +49370 0.39520263671875 +49371 0.389373779296875 +49372 0.324249267578125 +49373 0.224090576171875 +49374 0.124267578125 +49375 0.037078857421875 +49376 -0.010101318359375 +49377 -0.019439697265625 +49378 -0.022796630859375 +49379 -0.001556396484375 +49380 0.056304931640625 +49381 0.106719970703125 +49382 0.096893310546875 +49383 0.042694091796875 +49384 -0.018035888671875 +49385 -0.07586669921875 +49386 -0.11944580078125 +49387 -0.15972900390625 +49388 -0.202606201171875 +49389 -0.24859619140625 +49390 -0.30517578125 +49391 -0.36212158203125 +49392 -0.39141845703125 +49393 -0.35528564453125 +49394 -0.249969482421875 +49395 -0.092864990234375 +49396 0.08905029296875 +49397 0.2352294921875 +49398 0.318817138671875 +49399 0.358642578125 +49400 0.347747802734375 +49401 0.28564453125 +49402 0.223175048828125 +49403 0.196746826171875 +49404 0.179840087890625 +49405 0.155548095703125 +49406 0.151214599609375 +49407 0.156951904296875 +49408 0.13177490234375 +49409 0.100799560546875 +49410 0.087127685546875 +49411 0.05487060546875 +49412 -0.009002685546875 +49413 -0.10400390625 +49414 -0.229400634765625 +49415 -0.35552978515625 +49416 -0.441925048828125 +49417 -0.473846435546875 +49418 -0.464813232421875 +49419 -0.419097900390625 +49420 -0.334320068359375 +49421 -0.227935791015625 +49422 -0.12347412109375 +49423 -0.02764892578125 +49424 0.077667236328125 +49425 0.2132568359375 +49426 0.38885498046875 +49427 0.582794189453125 +49428 0.734039306640625 +49429 0.800140380859375 +49430 0.7783203125 +49431 0.6651611328125 +49432 0.45965576171875 +49433 0.199188232421875 +49434 -0.050689697265625 +49435 -0.23297119140625 +49436 -0.33013916015625 +49437 -0.368408203125 +49438 -0.378936767578125 +49439 -0.376983642578125 +49440 -0.37969970703125 +49441 -0.391510009765625 +49442 -0.385345458984375 +49443 -0.3419189453125 +49444 -0.28289794921875 +49445 -0.251617431640625 +49446 -0.266143798828125 +49447 -0.273345947265625 +49448 -0.216796875 +49449 -0.128265380859375 +49450 -0.068145751953125 +49451 -0.0430908203125 +49452 -0.024444580078125 +49453 0.020721435546875 +49454 0.124481201171875 +49455 0.25787353515625 +49456 0.379119873046875 +49457 0.47991943359375 +49458 0.5281982421875 +49459 0.511138916015625 +49460 0.456207275390625 +49461 0.407470703125 +49462 0.383758544921875 +49463 0.35687255859375 +49464 0.31182861328125 +49465 0.250885009765625 +49466 0.1654052734375 +49467 0.035247802734375 +49468 -0.142059326171875 +49469 -0.33563232421875 +49470 -0.5345458984375 +49471 -0.72186279296875 +49472 -0.836669921875 +49473 -0.8326416015625 +49474 -0.7296142578125 +49475 -0.582550048828125 +49476 -0.440093994140625 +49477 -0.324310302734375 +49478 -0.20147705078125 +49479 -0.044647216796875 +49480 0.103973388671875 +49481 0.202392578125 +49482 0.264495849609375 +49483 0.338897705078125 +49484 0.443817138671875 +49485 0.545074462890625 +49486 0.6173095703125 +49487 0.6524658203125 +49488 0.66339111328125 +49489 0.6561279296875 +49490 0.606781005859375 +49491 0.501190185546875 +49492 0.352783203125 +49493 0.176544189453125 +49494 -0.034820556640625 +49495 -0.258209228515625 +49496 -0.44244384765625 +49497 -0.5753173828125 +49498 -0.65203857421875 +49499 -0.641632080078125 +49500 -0.562164306640625 +49501 -0.458038330078125 +49502 -0.350555419921875 +49503 -0.260528564453125 +49504 -0.192108154296875 +49505 -0.141937255859375 +49506 -0.1021728515625 +49507 -0.062896728515625 +49508 -0.011932373046875 +49509 0.062835693359375 +49510 0.148712158203125 +49511 0.241729736328125 +49512 0.34912109375 +49513 0.457305908203125 +49514 0.54388427734375 +49515 0.5728759765625 +49516 0.506591796875 +49517 0.351226806640625 +49518 0.146514892578125 +49519 -0.05523681640625 +49520 -0.21624755859375 +49521 -0.334930419921875 +49522 -0.402984619140625 +49523 -0.4412841796875 +49524 -0.49578857421875 +49525 -0.5601806640625 +49526 -0.600738525390625 +49527 -0.584228515625 +49528 -0.47930908203125 +49529 -0.27935791015625 +49530 -0.0089111328125 +49531 0.268798828125 +49532 0.482818603515625 +49533 0.60369873046875 +49534 0.650421142578125 +49535 0.66400146484375 +49536 0.6414794921875 +49537 0.572540283203125 +49538 0.498138427734375 +49539 0.439453125 +49540 0.375518798828125 +49541 0.274505615234375 +49542 0.1087646484375 +49543 -0.099395751953125 +49544 -0.3182373046875 +49545 -0.5489501953125 +49546 -0.7738037109375 +49547 -0.86383056640625 +49548 -0.870391845703125 +49549 -0.86895751953125 +49550 -0.861053466796875 +49551 -0.765869140625 +49552 -0.5301513671875 +49553 -0.214691162109375 +49554 0.137359619140625 +49555 0.474822998046875 +49556 0.76239013671875 +49557 0.867462158203125 +49558 0.870361328125 +49559 0.86480712890625 +49560 0.831817626953125 +49561 0.677581787109375 +49562 0.495880126953125 +49563 0.30767822265625 +49564 0.116180419921875 +49565 -0.110748291015625 +49566 -0.381805419921875 +49567 -0.6572265625 +49568 -0.857421875 +49569 -0.870391845703125 +49570 -0.870391845703125 +49571 -0.86444091796875 +49572 -0.85723876953125 +49573 -0.790008544921875 +49574 -0.62847900390625 +49575 -0.3956298828125 +49576 -0.126708984375 +49577 0.150115966796875 +49578 0.424041748046875 +49579 0.670623779296875 +49580 0.854522705078125 +49581 0.866485595703125 +49582 0.86920166015625 +49583 0.8653564453125 +49584 0.857147216796875 +49585 0.766845703125 +49586 0.628509521484375 +49587 0.462127685546875 +49588 0.297210693359375 +49589 0.14862060546875 +49590 -0.00537109375 +49591 -0.15753173828125 +49592 -0.31304931640625 +49593 -0.48876953125 +49594 -0.6416015625 +49595 -0.751373291015625 +49596 -0.84619140625 +49597 -0.861297607421875 +49598 -0.863250732421875 +49599 -0.856597900390625 +49600 -0.7498779296875 +49601 -0.624542236328125 +49602 -0.47808837890625 +49603 -0.253387451171875 +49604 0.003692626953125 +49605 0.2257080078125 +49606 0.427154541015625 +49607 0.643218994140625 +49608 0.855926513671875 +49609 0.870361328125 +49610 0.870361328125 +49611 0.862762451171875 +49612 0.79669189453125 +49613 0.595794677734375 +49614 0.362152099609375 +49615 0.1270751953125 +49616 -0.086944580078125 +49617 -0.2784423828125 +49618 -0.484832763671875 +49619 -0.729583740234375 +49620 -0.86688232421875 +49621 -0.870391845703125 +49622 -0.86859130859375 +49623 -0.86279296875 +49624 -0.817962646484375 +49625 -0.6116943359375 +49626 -0.3128662109375 +49627 0.039398193359375 +49628 0.422821044921875 +49629 0.805145263671875 +49630 0.870361328125 +49631 0.870361328125 +49632 0.860015869140625 +49633 0.727935791015625 +49634 0.48114013671875 +49635 0.2059326171875 +49636 -0.06103515625 +49637 -0.29913330078125 +49638 -0.516204833984375 +49639 -0.7252197265625 +49640 -0.85980224609375 +49641 -0.870391845703125 +49642 -0.870391845703125 +49643 -0.858062744140625 +49644 -0.673004150390625 +49645 -0.42694091796875 +49646 -0.2100830078125 +49647 -0.0362548828125 +49648 0.10943603515625 +49649 0.23516845703125 +49650 0.373687744140625 +49651 0.517791748046875 +49652 0.602783203125 +49653 0.635711669921875 +49654 0.655181884765625 +49655 0.65948486328125 +49656 0.651275634765625 +49657 0.61846923828125 +49658 0.53753662109375 +49659 0.404144287109375 +49660 0.22186279296875 +49661 0.003997802734375 +49662 -0.22100830078125 +49663 -0.42449951171875 +49664 -0.579833984375 +49665 -0.641876220703125 +49666 -0.6177978515625 +49667 -0.575531005859375 +49668 -0.526336669921875 +49669 -0.42645263671875 +49670 -0.2581787109375 +49671 -0.068695068359375 +49672 0.09222412109375 +49673 0.232147216796875 +49674 0.3509521484375 +49675 0.410064697265625 +49676 0.372955322265625 +49677 0.2554931640625 +49678 0.10711669921875 +49679 -0.052886962890625 +49680 -0.186279296875 +49681 -0.23291015625 +49682 -0.209442138671875 +49683 -0.174163818359375 +49684 -0.126739501953125 +49685 -0.048126220703125 +49686 0.0426025390625 +49687 0.10748291015625 +49688 0.1409912109375 +49689 0.19708251953125 +49690 0.273651123046875 +49691 0.31768798828125 +49692 0.341094970703125 +49693 0.368011474609375 +49694 0.37249755859375 +49695 0.30072021484375 +49696 0.1517333984375 +49697 -0.01470947265625 +49698 -0.1883544921875 +49699 -0.372711181640625 +49700 -0.51397705078125 +49701 -0.57177734375 +49702 -0.53948974609375 +49703 -0.43511962890625 +49704 -0.2962646484375 +49705 -0.161102294921875 +49706 -0.0435791015625 +49707 0.060394287109375 +49708 0.13665771484375 +49709 0.170135498046875 +49710 0.16552734375 +49711 0.15728759765625 +49712 0.150787353515625 +49713 0.12200927734375 +49714 0.080108642578125 +49715 0.05126953125 +49716 0.062896728515625 +49717 0.09271240234375 +49718 0.092987060546875 +49719 0.07855224609375 +49720 0.06427001953125 +49721 0.0347900390625 +49722 -0.01171875 +49723 -0.056060791015625 +49724 -0.055511474609375 +49725 -0.010467529296875 +49726 0.02508544921875 +49727 0.025665283203125 +49728 0.017333984375 +49729 0.00189208984375 +49730 -0.03173828125 +49731 -0.071502685546875 +49732 -0.13543701171875 +49733 -0.219970703125 +49734 -0.300506591796875 +49735 -0.376312255859375 +49736 -0.416107177734375 +49737 -0.371124267578125 +49738 -0.242279052734375 +49739 -0.069732666015625 +49740 0.125640869140625 +49741 0.31268310546875 +49742 0.45501708984375 +49743 0.554779052734375 +49744 0.61065673828125 +49745 0.610931396484375 +49746 0.531463623046875 +49747 0.3883056640625 +49748 0.23468017578125 +49749 0.095245361328125 +49750 -0.00396728515625 +49751 -0.04852294921875 +49752 -0.055145263671875 +49753 -0.0758056640625 +49754 -0.138702392578125 +49755 -0.209197998046875 +49756 -0.289031982421875 +49757 -0.37884521484375 +49758 -0.456329345703125 +49759 -0.51641845703125 +49760 -0.519287109375 +49761 -0.458251953125 +49762 -0.384796142578125 +49763 -0.323699951171875 +49764 -0.269287109375 +49765 -0.1951904296875 +49766 -0.100006103515625 +49767 -0.01055908203125 +49768 0.1033935546875 +49769 0.24908447265625 +49770 0.373199462890625 +49771 0.45806884765625 +49772 0.511474609375 +49773 0.565399169921875 +49774 0.61138916015625 +49775 0.5897216796875 +49776 0.4906005859375 +49777 0.33148193359375 +49778 0.147796630859375 +49779 -0.01873779296875 +49780 -0.140289306640625 +49781 -0.191986083984375 +49782 -0.184295654296875 +49783 -0.161834716796875 +49784 -0.166595458984375 +49785 -0.19390869140625 +49786 -0.22442626953125 +49787 -0.279754638671875 +49788 -0.3389892578125 +49789 -0.3543701171875 +49790 -0.348175048828125 +49791 -0.32598876953125 +49792 -0.2581787109375 +49793 -0.139801025390625 +49794 0.014617919921875 +49795 0.144378662109375 +49796 0.221038818359375 +49797 0.27069091796875 +49798 0.294036865234375 +49799 0.311767578125 +49800 0.339141845703125 +49801 0.360260009765625 +49802 0.360504150390625 +49803 0.308380126953125 +49804 0.18170166015625 +49805 0.0047607421875 +49806 -0.17559814453125 +49807 -0.3143310546875 +49808 -0.36785888671875 +49809 -0.36248779296875 +49810 -0.343536376953125 +49811 -0.3018798828125 +49812 -0.231414794921875 +49813 -0.117645263671875 +49814 0.007049560546875 +49815 0.087982177734375 +49816 0.13946533203125 +49817 0.17425537109375 +49818 0.188201904296875 +49819 0.171234130859375 +49820 0.118438720703125 +49821 0.05706787109375 +49822 -0.010711669921875 +49823 -0.0914306640625 +49824 -0.162322998046875 +49825 -0.194549560546875 +49826 -0.1492919921875 +49827 -0.02166748046875 +49828 0.124053955078125 +49829 0.211151123046875 +49830 0.240447998046875 +49831 0.242218017578125 +49832 0.2257080078125 +49833 0.194366455078125 +49834 0.115509033203125 +49835 0.0128173828125 +49836 -0.053802490234375 +49837 -0.110626220703125 +49838 -0.199493408203125 +49839 -0.29437255859375 +49840 -0.33221435546875 +49841 -0.27972412109375 +49842 -0.185333251953125 +49843 -0.128204345703125 +49844 -0.115692138671875 +49845 -0.116455078125 +49846 -0.105926513671875 +49847 -0.053955078125 +49848 0.048797607421875 +49849 0.157318115234375 +49850 0.212005615234375 +49851 0.218475341796875 +49852 0.23724365234375 +49853 0.30535888671875 +49854 0.38128662109375 +49855 0.404449462890625 +49856 0.3944091796875 +49857 0.3885498046875 +49858 0.362640380859375 +49859 0.27362060546875 +49860 0.11712646484375 +49861 -0.054901123046875 +49862 -0.19085693359375 +49863 -0.28570556640625 +49864 -0.339263916015625 +49865 -0.3775634765625 +49866 -0.445709228515625 +49867 -0.535064697265625 +49868 -0.629058837890625 +49869 -0.697601318359375 +49870 -0.70391845703125 +49871 -0.6424560546875 +49872 -0.491241455078125 +49873 -0.265716552734375 +49874 -0.023712158203125 +49875 0.201751708984375 +49876 0.375823974609375 +49877 0.485076904296875 +49878 0.56884765625 +49879 0.634765625 +49880 0.63763427734375 +49881 0.5660400390625 +49882 0.4720458984375 +49883 0.40692138671875 +49884 0.3778076171875 +49885 0.376953125 +49886 0.371978759765625 +49887 0.313140869140625 +49888 0.184417724609375 +49889 0.011199951171875 +49890 -0.171051025390625 +49891 -0.33740234375 +49892 -0.47198486328125 +49893 -0.560394287109375 +49894 -0.58056640625 +49895 -0.54754638671875 +49896 -0.508575439453125 +49897 -0.459503173828125 +49898 -0.394378662109375 +49899 -0.35260009765625 +49900 -0.31170654296875 +49901 -0.197418212890625 +49902 -0.007965087890625 +49903 0.207489013671875 +49904 0.409210205078125 +49905 0.57208251953125 +49906 0.66595458984375 +49907 0.65875244140625 +49908 0.56744384765625 +49909 0.431396484375 +49910 0.29443359375 +49911 0.182464599609375 +49912 0.06365966796875 +49913 -0.075958251953125 +49914 -0.189422607421875 +49915 -0.271942138671875 +49916 -0.342529296875 +49917 -0.364166259765625 +49918 -0.327239990234375 +49919 -0.2769775390625 +49920 -0.253692626953125 +49921 -0.24365234375 +49922 -0.1983642578125 +49923 -0.116241455078125 +49924 -0.036834716796875 +49925 0.034881591796875 +49926 0.09124755859375 +49927 0.10888671875 +49928 0.125518798828125 +49929 0.15771484375 +49930 0.17828369140625 +49931 0.17108154296875 +49932 0.129974365234375 +49933 0.082427978515625 +49934 0.027679443359375 +49935 -0.065643310546875 +49936 -0.15936279296875 +49937 -0.21307373046875 +49938 -0.234649658203125 +49939 -0.2001953125 +49940 -0.119171142578125 +49941 -0.024749755859375 +49942 0.085784912109375 +49943 0.178131103515625 +49944 0.215576171875 +49945 0.211456298828125 +49946 0.17523193359375 +49947 0.128753662109375 +49948 0.1019287109375 +49949 0.0743408203125 +49950 0.04327392578125 +49951 0.038177490234375 +49952 0.076263427734375 +49953 0.14105224609375 +49954 0.186431884765625 +49955 0.188812255859375 +49956 0.1390380859375 +49957 0.041778564453125 +49958 -0.079437255859375 +49959 -0.219390869140625 +49960 -0.367828369140625 +49961 -0.494873046875 +49962 -0.556243896484375 +49963 -0.508697509765625 +49964 -0.3756103515625 +49965 -0.218902587890625 +49966 -0.063751220703125 +49967 0.091552734375 +49968 0.23602294921875 +49969 0.342987060546875 +49970 0.39520263671875 +49971 0.389373779296875 +49972 0.324249267578125 +49973 0.224090576171875 +49974 0.124267578125 +49975 0.037078857421875 +49976 -0.010101318359375 +49977 -0.019439697265625 +49978 -0.022796630859375 +49979 -0.001556396484375 +49980 0.056304931640625 +49981 0.106719970703125 +49982 0.096893310546875 +49983 0.042694091796875 +49984 -0.018035888671875 +49985 -0.07586669921875 +49986 -0.11944580078125 +49987 -0.15972900390625 +49988 -0.202606201171875 +49989 -0.24859619140625 +49990 -0.30517578125 +49991 -0.36212158203125 +49992 -0.39141845703125 +49993 -0.35528564453125 +49994 -0.249969482421875 +49995 -0.092864990234375 +49996 0.08905029296875 +49997 0.2352294921875 +49998 0.318817138671875 +49999 0.358642578125 +50000 0.347747802734375 +50001 0.28564453125 +50002 0.223175048828125 +50003 0.196746826171875 +50004 0.179840087890625 +50005 0.155548095703125 +50006 0.151214599609375 +50007 0.156951904296875 +50008 0.13177490234375 +50009 0.100799560546875 +50010 0.087127685546875 +50011 0.05487060546875 +50012 -0.009002685546875 +50013 -0.10400390625 +50014 -0.229400634765625 +50015 -0.35552978515625 +50016 -0.441925048828125 +50017 -0.473846435546875 +50018 -0.464813232421875 +50019 -0.419097900390625 +50020 -0.334320068359375 +50021 -0.227935791015625 +50022 -0.12347412109375 +50023 -0.02764892578125 +50024 0.077667236328125 +50025 0.2132568359375 +50026 0.38885498046875 +50027 0.582794189453125 +50028 0.734039306640625 +50029 0.800140380859375 +50030 0.7783203125 +50031 0.6651611328125 +50032 0.45965576171875 +50033 0.199188232421875 +50034 -0.050689697265625 +50035 -0.23297119140625 +50036 -0.33013916015625 +50037 -0.368408203125 +50038 -0.378936767578125 +50039 -0.376983642578125 +50040 -0.37969970703125 +50041 -0.391510009765625 +50042 -0.385345458984375 +50043 -0.3419189453125 +50044 -0.28289794921875 +50045 -0.251617431640625 +50046 -0.266143798828125 +50047 -0.273345947265625 +50048 -0.216796875 +50049 -0.128265380859375 +50050 -0.068145751953125 +50051 -0.0430908203125 +50052 -0.024444580078125 +50053 0.020721435546875 +50054 0.124481201171875 +50055 0.25787353515625 +50056 0.379119873046875 +50057 0.47991943359375 +50058 0.5281982421875 +50059 0.511138916015625 +50060 0.456207275390625 +50061 0.407470703125 +50062 0.383758544921875 +50063 0.35687255859375 +50064 0.31182861328125 +50065 0.250885009765625 +50066 0.1654052734375 +50067 0.035247802734375 +50068 -0.142059326171875 +50069 -0.33563232421875 +50070 -0.5345458984375 +50071 -0.72186279296875 +50072 -0.836669921875 +50073 -0.8326416015625 +50074 -0.7296142578125 +50075 -0.582550048828125 +50076 -0.440093994140625 +50077 -0.324310302734375 +50078 -0.20147705078125 +50079 -0.044647216796875 +50080 0.103973388671875 +50081 0.202392578125 +50082 0.264495849609375 +50083 0.338897705078125 +50084 0.443817138671875 +50085 0.545074462890625 +50086 0.6173095703125 +50087 0.6524658203125 +50088 0.66339111328125 +50089 0.6561279296875 +50090 0.606781005859375 +50091 0.501190185546875 +50092 0.352783203125 +50093 0.176544189453125 +50094 -0.034820556640625 +50095 -0.258209228515625 +50096 -0.44244384765625 +50097 -0.5753173828125 +50098 -0.65203857421875 +50099 -0.641632080078125 +50100 -0.562164306640625 +50101 -0.458038330078125 +50102 -0.350555419921875 +50103 -0.260528564453125 +50104 -0.192108154296875 +50105 -0.141937255859375 +50106 -0.1021728515625 +50107 -0.062896728515625 +50108 -0.011932373046875 +50109 0.062835693359375 +50110 0.148712158203125 +50111 0.241729736328125 +50112 0.34912109375 +50113 0.457305908203125 +50114 0.54388427734375 +50115 0.5728759765625 +50116 0.506591796875 +50117 0.351226806640625 +50118 0.146514892578125 +50119 -0.05523681640625 +50120 -0.21624755859375 +50121 -0.334930419921875 +50122 -0.402984619140625 +50123 -0.4412841796875 +50124 -0.49578857421875 +50125 -0.5601806640625 +50126 -0.600738525390625 +50127 -0.584228515625 +50128 -0.47930908203125 +50129 -0.27935791015625 +50130 -0.0089111328125 +50131 0.268798828125 +50132 0.482818603515625 +50133 0.60369873046875 +50134 0.650421142578125 +50135 0.66400146484375 +50136 0.6414794921875 +50137 0.572540283203125 +50138 0.498138427734375 +50139 0.439453125 +50140 0.375518798828125 +50141 0.274505615234375 +50142 0.1087646484375 +50143 -0.099395751953125 +50144 -0.3182373046875 +50145 -0.5489501953125 +50146 -0.7738037109375 +50147 -0.86383056640625 +50148 -0.870391845703125 +50149 -0.86895751953125 +50150 -0.861053466796875 +50151 -0.765869140625 +50152 -0.5301513671875 +50153 -0.214691162109375 +50154 0.137359619140625 +50155 0.474822998046875 +50156 0.76239013671875 +50157 0.867462158203125 +50158 0.870361328125 +50159 0.86480712890625 +50160 0.831817626953125 +50161 0.677581787109375 +50162 0.495880126953125 +50163 0.30767822265625 +50164 0.116180419921875 +50165 -0.110748291015625 +50166 -0.381805419921875 +50167 -0.6572265625 +50168 -0.857421875 +50169 -0.870391845703125 +50170 -0.870391845703125 +50171 -0.86444091796875 +50172 -0.85723876953125 +50173 -0.790008544921875 +50174 -0.62847900390625 +50175 -0.3956298828125 +50176 -0.126708984375 +50177 0.150115966796875 +50178 0.424041748046875 +50179 0.670623779296875 +50180 0.854522705078125 +50181 0.866485595703125 +50182 0.86920166015625 +50183 0.8653564453125 +50184 0.857147216796875 +50185 0.766845703125 +50186 0.628509521484375 +50187 0.462127685546875 +50188 0.297210693359375 +50189 0.14862060546875 +50190 -0.00537109375 +50191 -0.15753173828125 +50192 -0.31304931640625 +50193 -0.48876953125 +50194 -0.6416015625 +50195 -0.751373291015625 +50196 -0.84619140625 +50197 -0.861297607421875 +50198 -0.863250732421875 +50199 -0.856597900390625 +50200 -0.7498779296875 +50201 -0.624542236328125 +50202 -0.47808837890625 +50203 -0.253387451171875 +50204 0.003692626953125 +50205 0.2257080078125 +50206 0.427154541015625 +50207 0.643218994140625 +50208 0.855926513671875 +50209 0.870361328125 +50210 0.870361328125 +50211 0.862762451171875 +50212 0.79669189453125 +50213 0.595794677734375 +50214 0.362152099609375 +50215 0.1270751953125 +50216 -0.086944580078125 +50217 -0.2784423828125 +50218 -0.484832763671875 +50219 -0.729583740234375 +50220 -0.86688232421875 +50221 -0.870391845703125 +50222 -0.86859130859375 +50223 -0.86279296875 +50224 -0.817962646484375 +50225 -0.6116943359375 +50226 -0.3128662109375 +50227 0.039398193359375 +50228 0.422821044921875 +50229 0.805145263671875 +50230 0.870361328125 +50231 0.870361328125 +50232 0.860015869140625 +50233 0.727935791015625 +50234 0.48114013671875 +50235 0.2059326171875 +50236 -0.06103515625 +50237 -0.29913330078125 +50238 -0.516204833984375 +50239 -0.7252197265625 +50240 -0.85980224609375 +50241 -0.870391845703125 +50242 -0.870391845703125 +50243 -0.858062744140625 +50244 -0.673004150390625 +50245 -0.42694091796875 +50246 -0.2100830078125 +50247 -0.0362548828125 +50248 0.10943603515625 +50249 0.23516845703125 +50250 0.373687744140625 +50251 0.517791748046875 +50252 0.602783203125 +50253 0.635711669921875 +50254 0.655181884765625 +50255 0.65948486328125 +50256 0.651275634765625 +50257 0.61846923828125 +50258 0.53753662109375 +50259 0.404144287109375 +50260 0.22186279296875 +50261 0.003997802734375 +50262 -0.22100830078125 +50263 -0.42449951171875 +50264 -0.579833984375 +50265 -0.641876220703125 +50266 -0.6177978515625 +50267 -0.575531005859375 +50268 -0.526336669921875 +50269 -0.42645263671875 +50270 -0.2581787109375 +50271 -0.068695068359375 +50272 0.09222412109375 +50273 0.232147216796875 +50274 0.3509521484375 +50275 0.410064697265625 +50276 0.372955322265625 +50277 0.2554931640625 +50278 0.10711669921875 +50279 -0.052886962890625 +50280 -0.186279296875 +50281 -0.23291015625 +50282 -0.209442138671875 +50283 -0.174163818359375 +50284 -0.126739501953125 +50285 -0.048126220703125 +50286 0.0426025390625 +50287 0.10748291015625 +50288 0.1409912109375 +50289 0.19708251953125 +50290 0.273651123046875 +50291 0.31768798828125 +50292 0.341094970703125 +50293 0.368011474609375 +50294 0.37249755859375 +50295 0.30072021484375 +50296 0.1517333984375 +50297 -0.01470947265625 +50298 -0.1883544921875 +50299 -0.372711181640625 +50300 -0.51397705078125 +50301 -0.57177734375 +50302 -0.53948974609375 +50303 -0.43511962890625 +50304 -0.2962646484375 +50305 -0.161102294921875 +50306 -0.0435791015625 +50307 0.060394287109375 +50308 0.13665771484375 +50309 0.170135498046875 +50310 0.16552734375 +50311 0.15728759765625 +50312 0.150787353515625 +50313 0.12200927734375 +50314 0.080108642578125 +50315 0.05126953125 +50316 0.062896728515625 +50317 0.09271240234375 +50318 0.092987060546875 +50319 0.07855224609375 +50320 0.06427001953125 +50321 0.0347900390625 +50322 -0.01171875 +50323 -0.056060791015625 +50324 -0.055511474609375 +50325 -0.010467529296875 +50326 0.02508544921875 +50327 0.025665283203125 +50328 0.017333984375 +50329 0.00189208984375 +50330 -0.03173828125 +50331 -0.071502685546875 +50332 -0.13543701171875 +50333 -0.219970703125 +50334 -0.300506591796875 +50335 -0.376312255859375 +50336 -0.416107177734375 +50337 -0.371124267578125 +50338 -0.242279052734375 +50339 -0.069732666015625 +50340 0.125640869140625 +50341 0.31268310546875 +50342 0.45501708984375 +50343 0.554779052734375 +50344 0.61065673828125 +50345 0.610931396484375 +50346 0.531463623046875 +50347 0.3883056640625 +50348 0.23468017578125 +50349 0.095245361328125 +50350 -0.00396728515625 +50351 -0.04852294921875 +50352 -0.055145263671875 +50353 -0.0758056640625 +50354 -0.138702392578125 +50355 -0.209197998046875 +50356 -0.289031982421875 +50357 -0.37884521484375 +50358 -0.456329345703125 +50359 -0.51641845703125 +50360 -0.519287109375 +50361 -0.458251953125 +50362 -0.384796142578125 +50363 -0.323699951171875 +50364 -0.269287109375 +50365 -0.1951904296875 +50366 -0.100006103515625 +50367 -0.01055908203125 +50368 0.1033935546875 +50369 0.24908447265625 +50370 0.373199462890625 +50371 0.45806884765625 +50372 0.511474609375 +50373 0.565399169921875 +50374 0.61138916015625 +50375 0.5897216796875 +50376 0.4906005859375 +50377 0.33148193359375 +50378 0.147796630859375 +50379 -0.01873779296875 +50380 -0.140289306640625 +50381 -0.191986083984375 +50382 -0.184295654296875 +50383 -0.161834716796875 +50384 -0.166595458984375 +50385 -0.19390869140625 +50386 -0.22442626953125 +50387 -0.279754638671875 +50388 -0.3389892578125 +50389 -0.3543701171875 +50390 -0.348175048828125 +50391 -0.32598876953125 +50392 -0.2581787109375 +50393 -0.139801025390625 +50394 0.014617919921875 +50395 0.144378662109375 +50396 0.221038818359375 +50397 0.27069091796875 +50398 0.294036865234375 +50399 0.311767578125 +50400 0.339141845703125 +50401 0.360260009765625 +50402 0.360504150390625 +50403 0.308380126953125 +50404 0.18170166015625 +50405 0.0047607421875 +50406 -0.17559814453125 +50407 -0.3143310546875 +50408 -0.36785888671875 +50409 -0.36248779296875 +50410 -0.343536376953125 +50411 -0.3018798828125 +50412 -0.231414794921875 +50413 -0.117645263671875 +50414 0.007049560546875 +50415 0.087982177734375 +50416 0.13946533203125 +50417 0.17425537109375 +50418 0.188201904296875 +50419 0.171234130859375 +50420 0.118438720703125 +50421 0.05706787109375 +50422 -0.010711669921875 +50423 -0.0914306640625 +50424 -0.162322998046875 +50425 -0.194549560546875 +50426 -0.1492919921875 +50427 -0.02166748046875 +50428 0.124053955078125 +50429 0.211151123046875 +50430 0.240447998046875 +50431 0.242218017578125 +50432 0.2257080078125 +50433 0.194366455078125 +50434 0.115509033203125 +50435 0.0128173828125 +50436 -0.053802490234375 +50437 -0.110626220703125 +50438 -0.199493408203125 +50439 -0.29437255859375 +50440 -0.33221435546875 +50441 -0.27972412109375 +50442 -0.185333251953125 +50443 -0.128204345703125 +50444 -0.115692138671875 +50445 -0.116455078125 +50446 -0.105926513671875 +50447 -0.053955078125 +50448 0.048797607421875 +50449 0.157318115234375 +50450 0.212005615234375 +50451 0.218475341796875 +50452 0.23724365234375 +50453 0.30535888671875 +50454 0.38128662109375 +50455 0.404449462890625 +50456 0.3944091796875 +50457 0.3885498046875 +50458 0.362640380859375 +50459 0.27362060546875 +50460 0.11712646484375 +50461 -0.054901123046875 +50462 -0.19085693359375 +50463 -0.28570556640625 +50464 -0.339263916015625 +50465 -0.3775634765625 +50466 -0.445709228515625 +50467 -0.535064697265625 +50468 -0.629058837890625 +50469 -0.697601318359375 +50470 -0.70391845703125 +50471 -0.6424560546875 +50472 -0.491241455078125 +50473 -0.265716552734375 +50474 -0.023712158203125 +50475 0.201751708984375 +50476 0.375823974609375 +50477 0.485076904296875 +50478 0.56884765625 +50479 0.634765625 +50480 0.63763427734375 +50481 0.5660400390625 +50482 0.4720458984375 +50483 0.40692138671875 +50484 0.3778076171875 +50485 0.376953125 +50486 0.371978759765625 +50487 0.313140869140625 +50488 0.184417724609375 +50489 0.011199951171875 +50490 -0.171051025390625 +50491 -0.33740234375 +50492 -0.47198486328125 +50493 -0.560394287109375 +50494 -0.58056640625 +50495 -0.54754638671875 +50496 -0.508575439453125 +50497 -0.459503173828125 +50498 -0.394378662109375 +50499 -0.35260009765625 +50500 -0.31170654296875 +50501 -0.197418212890625 +50502 -0.007965087890625 +50503 0.207489013671875 +50504 0.409210205078125 +50505 0.57208251953125 +50506 0.66595458984375 +50507 0.65875244140625 +50508 0.56744384765625 +50509 0.431396484375 +50510 0.29443359375 +50511 0.182464599609375 +50512 0.06365966796875 +50513 -0.075958251953125 +50514 -0.189422607421875 +50515 -0.271942138671875 +50516 -0.342529296875 +50517 -0.364166259765625 +50518 -0.327239990234375 +50519 -0.2769775390625 +50520 -0.253692626953125 +50521 -0.24365234375 +50522 -0.1983642578125 +50523 -0.116241455078125 +50524 -0.036834716796875 +50525 0.034881591796875 +50526 0.09124755859375 +50527 0.10888671875 +50528 0.125518798828125 +50529 0.15771484375 +50530 0.17828369140625 +50531 0.17108154296875 +50532 0.129974365234375 +50533 0.082427978515625 +50534 0.027679443359375 +50535 -0.065643310546875 +50536 -0.15936279296875 +50537 -0.21307373046875 +50538 -0.234649658203125 +50539 -0.2001953125 +50540 -0.119171142578125 +50541 -0.024749755859375 +50542 0.085784912109375 +50543 0.178131103515625 +50544 0.215576171875 +50545 0.211456298828125 +50546 0.17523193359375 +50547 0.128753662109375 +50548 0.1019287109375 +50549 0.0743408203125 +50550 0.04327392578125 +50551 0.038177490234375 +50552 0.076263427734375 +50553 0.14105224609375 +50554 0.186431884765625 +50555 0.188812255859375 +50556 0.1390380859375 +50557 0.041778564453125 +50558 -0.079437255859375 +50559 -0.219390869140625 +50560 -0.367828369140625 +50561 -0.494873046875 +50562 -0.556243896484375 +50563 -0.508697509765625 +50564 -0.3756103515625 +50565 -0.218902587890625 +50566 -0.063751220703125 +50567 0.091552734375 +50568 0.23602294921875 +50569 0.342987060546875 +50570 0.39520263671875 +50571 0.389373779296875 +50572 0.324249267578125 +50573 0.224090576171875 +50574 0.124267578125 +50575 0.037078857421875 +50576 -0.010101318359375 +50577 -0.019439697265625 +50578 -0.022796630859375 +50579 -0.001556396484375 +50580 0.056304931640625 +50581 0.106719970703125 +50582 0.096893310546875 +50583 0.042694091796875 +50584 -0.018035888671875 +50585 -0.07586669921875 +50586 -0.11944580078125 +50587 -0.15972900390625 +50588 -0.202606201171875 +50589 -0.24859619140625 +50590 -0.30517578125 +50591 -0.36212158203125 +50592 -0.39141845703125 +50593 -0.35528564453125 +50594 -0.249969482421875 +50595 -0.092864990234375 +50596 0.08905029296875 +50597 0.2352294921875 +50598 0.318817138671875 +50599 0.358642578125 +50600 0.347747802734375 +50601 0.28564453125 +50602 0.223175048828125 +50603 0.196746826171875 +50604 0.179840087890625 +50605 0.155548095703125 +50606 0.151214599609375 +50607 0.156951904296875 +50608 0.13177490234375 +50609 0.100799560546875 +50610 0.087127685546875 +50611 0.05487060546875 +50612 -0.009002685546875 +50613 -0.10400390625 +50614 -0.229400634765625 +50615 -0.35552978515625 +50616 -0.441925048828125 +50617 -0.473846435546875 +50618 -0.464813232421875 +50619 -0.419097900390625 +50620 -0.334320068359375 +50621 -0.227935791015625 +50622 -0.12347412109375 +50623 -0.02764892578125 +50624 0.077667236328125 +50625 0.2132568359375 +50626 0.38885498046875 +50627 0.582794189453125 +50628 0.734039306640625 +50629 0.800140380859375 +50630 0.7783203125 +50631 0.6651611328125 +50632 0.45965576171875 +50633 0.199188232421875 +50634 -0.050689697265625 +50635 -0.23297119140625 +50636 -0.33013916015625 +50637 -0.368408203125 +50638 -0.378936767578125 +50639 -0.376983642578125 +50640 -0.37969970703125 +50641 -0.391510009765625 +50642 -0.385345458984375 +50643 -0.3419189453125 +50644 -0.28289794921875 +50645 -0.251617431640625 +50646 -0.266143798828125 +50647 -0.273345947265625 +50648 -0.216796875 +50649 -0.128265380859375 +50650 -0.068145751953125 +50651 -0.0430908203125 +50652 -0.024444580078125 +50653 0.020721435546875 +50654 0.124481201171875 +50655 0.25787353515625 +50656 0.379119873046875 +50657 0.47991943359375 +50658 0.5281982421875 +50659 0.511138916015625 +50660 0.456207275390625 +50661 0.407470703125 +50662 0.383758544921875 +50663 0.35687255859375 +50664 0.31182861328125 +50665 0.250885009765625 +50666 0.1654052734375 +50667 0.035247802734375 +50668 -0.142059326171875 +50669 -0.33563232421875 +50670 -0.5345458984375 +50671 -0.72186279296875 +50672 -0.836669921875 +50673 -0.8326416015625 +50674 -0.7296142578125 +50675 -0.582550048828125 +50676 -0.440093994140625 +50677 -0.324310302734375 +50678 -0.20147705078125 +50679 -0.044647216796875 +50680 0.103973388671875 +50681 0.202392578125 +50682 0.264495849609375 +50683 0.338897705078125 +50684 0.443817138671875 +50685 0.545074462890625 +50686 0.6173095703125 +50687 0.6524658203125 +50688 0.66339111328125 +50689 0.6561279296875 +50690 0.606781005859375 +50691 0.501190185546875 +50692 0.352783203125 +50693 0.176544189453125 +50694 -0.034820556640625 +50695 -0.258209228515625 +50696 -0.44244384765625 +50697 -0.5753173828125 +50698 -0.65203857421875 +50699 -0.641632080078125 +50700 -0.562164306640625 +50701 -0.458038330078125 +50702 -0.350555419921875 +50703 -0.260528564453125 +50704 -0.192108154296875 +50705 -0.141937255859375 +50706 -0.1021728515625 +50707 -0.062896728515625 +50708 -0.011932373046875 +50709 0.062835693359375 +50710 0.148712158203125 +50711 0.241729736328125 +50712 0.34912109375 +50713 0.457305908203125 +50714 0.54388427734375 +50715 0.5728759765625 +50716 0.506591796875 +50717 0.351226806640625 +50718 0.146514892578125 +50719 -0.05523681640625 +50720 -0.21624755859375 +50721 -0.334930419921875 +50722 -0.402984619140625 +50723 -0.4412841796875 +50724 -0.49578857421875 +50725 -0.5601806640625 +50726 -0.600738525390625 +50727 -0.584228515625 +50728 -0.47930908203125 +50729 -0.27935791015625 +50730 -0.0089111328125 +50731 0.268798828125 +50732 0.482818603515625 +50733 0.60369873046875 +50734 0.650421142578125 +50735 0.66400146484375 +50736 0.6414794921875 +50737 0.572540283203125 +50738 0.498138427734375 +50739 0.439453125 +50740 0.375518798828125 +50741 0.274505615234375 +50742 0.1087646484375 +50743 -0.099395751953125 +50744 -0.3182373046875 +50745 -0.5489501953125 +50746 -0.7738037109375 +50747 -0.86383056640625 +50748 -0.870391845703125 +50749 -0.86895751953125 +50750 -0.861053466796875 +50751 -0.765869140625 +50752 -0.5301513671875 +50753 -0.214691162109375 +50754 0.137359619140625 +50755 0.474822998046875 +50756 0.76239013671875 +50757 0.867462158203125 +50758 0.870361328125 +50759 0.86480712890625 +50760 0.831817626953125 +50761 0.677581787109375 +50762 0.495880126953125 +50763 0.30767822265625 +50764 0.116180419921875 +50765 -0.110748291015625 +50766 -0.381805419921875 +50767 -0.6572265625 +50768 -0.857421875 +50769 -0.870391845703125 +50770 -0.870391845703125 +50771 -0.86444091796875 +50772 -0.85723876953125 +50773 -0.790008544921875 +50774 -0.62847900390625 +50775 -0.3956298828125 +50776 -0.126708984375 +50777 0.150115966796875 +50778 0.424041748046875 +50779 0.670623779296875 +50780 0.854522705078125 +50781 0.866485595703125 +50782 0.86920166015625 +50783 0.8653564453125 +50784 0.857147216796875 +50785 0.766845703125 +50786 0.628509521484375 +50787 0.462127685546875 +50788 0.297210693359375 +50789 0.14862060546875 +50790 -0.00537109375 +50791 -0.15753173828125 +50792 -0.31304931640625 +50793 -0.48876953125 +50794 -0.6416015625 +50795 -0.751373291015625 +50796 -0.84619140625 +50797 -0.861297607421875 +50798 -0.863250732421875 +50799 -0.856597900390625 +50800 -0.7498779296875 +50801 -0.624542236328125 +50802 -0.47808837890625 +50803 -0.253387451171875 +50804 0.003692626953125 +50805 0.2257080078125 +50806 0.427154541015625 +50807 0.643218994140625 +50808 0.855926513671875 +50809 0.870361328125 +50810 0.870361328125 +50811 0.862762451171875 +50812 0.79669189453125 +50813 0.595794677734375 +50814 0.362152099609375 +50815 0.1270751953125 +50816 -0.086944580078125 +50817 -0.2784423828125 +50818 -0.484832763671875 +50819 -0.729583740234375 +50820 -0.86688232421875 +50821 -0.870391845703125 +50822 -0.86859130859375 +50823 -0.86279296875 +50824 -0.817962646484375 +50825 -0.6116943359375 +50826 -0.3128662109375 +50827 0.039398193359375 +50828 0.422821044921875 +50829 0.805145263671875 +50830 0.870361328125 +50831 0.870361328125 +50832 0.860015869140625 +50833 0.727935791015625 +50834 0.48114013671875 +50835 0.2059326171875 +50836 -0.06103515625 +50837 -0.29913330078125 +50838 -0.516204833984375 +50839 -0.7252197265625 +50840 -0.85980224609375 +50841 -0.870391845703125 +50842 -0.870391845703125 +50843 -0.858062744140625 +50844 -0.673004150390625 +50845 -0.42694091796875 +50846 -0.2100830078125 +50847 -0.0362548828125 +50848 0.10943603515625 +50849 0.23516845703125 +50850 0.373687744140625 +50851 0.517791748046875 +50852 0.602783203125 +50853 0.635711669921875 +50854 0.655181884765625 +50855 0.65948486328125 +50856 0.651275634765625 +50857 0.61846923828125 +50858 0.53753662109375 +50859 0.404144287109375 +50860 0.22186279296875 +50861 0.003997802734375 +50862 -0.22100830078125 +50863 -0.42449951171875 +50864 -0.579833984375 +50865 -0.641876220703125 +50866 -0.6177978515625 +50867 -0.575531005859375 +50868 -0.526336669921875 +50869 -0.42645263671875 +50870 -0.2581787109375 +50871 -0.068695068359375 +50872 0.09222412109375 +50873 0.232147216796875 +50874 0.3509521484375 +50875 0.410064697265625 +50876 0.372955322265625 +50877 0.2554931640625 +50878 0.10711669921875 +50879 -0.052886962890625 +50880 -0.186279296875 +50881 -0.23291015625 +50882 -0.209442138671875 +50883 -0.174163818359375 +50884 -0.126739501953125 +50885 -0.048126220703125 +50886 0.0426025390625 +50887 0.10748291015625 +50888 0.1409912109375 +50889 0.19708251953125 +50890 0.273651123046875 +50891 0.31768798828125 +50892 0.341094970703125 +50893 0.368011474609375 +50894 0.37249755859375 +50895 0.30072021484375 +50896 0.1517333984375 +50897 -0.01470947265625 +50898 -0.1883544921875 +50899 -0.372711181640625 +50900 -0.51397705078125 +50901 -0.57177734375 +50902 -0.53948974609375 +50903 -0.43511962890625 +50904 -0.2962646484375 +50905 -0.161102294921875 +50906 -0.0435791015625 +50907 0.060394287109375 +50908 0.13665771484375 +50909 0.170135498046875 +50910 0.16552734375 +50911 0.15728759765625 +50912 0.150787353515625 +50913 0.12200927734375 +50914 0.080108642578125 +50915 0.05126953125 +50916 0.062896728515625 +50917 0.09271240234375 +50918 0.092987060546875 +50919 0.07855224609375 +50920 0.06427001953125 +50921 0.0347900390625 +50922 -0.01171875 +50923 -0.056060791015625 +50924 -0.055511474609375 +50925 -0.010467529296875 +50926 0.02508544921875 +50927 0.025665283203125 +50928 0.017333984375 +50929 0.00189208984375 +50930 -0.03173828125 +50931 -0.071502685546875 +50932 -0.13543701171875 +50933 -0.219970703125 +50934 -0.300506591796875 +50935 -0.376312255859375 +50936 -0.416107177734375 +50937 -0.371124267578125 +50938 -0.242279052734375 +50939 -0.069732666015625 +50940 0.125640869140625 +50941 0.31268310546875 +50942 0.45501708984375 +50943 0.554779052734375 +50944 0.61065673828125 +50945 0.610931396484375 +50946 0.531463623046875 +50947 0.3883056640625 +50948 0.23468017578125 +50949 0.095245361328125 +50950 -0.00396728515625 +50951 -0.04852294921875 +50952 -0.055145263671875 +50953 -0.0758056640625 +50954 -0.138702392578125 +50955 -0.209197998046875 +50956 -0.289031982421875 +50957 -0.37884521484375 +50958 -0.456329345703125 +50959 -0.51641845703125 +50960 -0.519287109375 +50961 -0.458251953125 +50962 -0.384796142578125 +50963 -0.323699951171875 +50964 -0.269287109375 +50965 -0.1951904296875 +50966 -0.100006103515625 +50967 -0.01055908203125 +50968 0.1033935546875 +50969 0.24908447265625 +50970 0.373199462890625 +50971 0.45806884765625 +50972 0.511474609375 +50973 0.565399169921875 +50974 0.61138916015625 +50975 0.5897216796875 +50976 0.4906005859375 +50977 0.33148193359375 +50978 0.147796630859375 +50979 -0.01873779296875 +50980 -0.140289306640625 +50981 -0.191986083984375 +50982 -0.184295654296875 +50983 -0.161834716796875 +50984 -0.166595458984375 +50985 -0.19390869140625 +50986 -0.22442626953125 +50987 -0.279754638671875 +50988 -0.3389892578125 +50989 -0.3543701171875 +50990 -0.348175048828125 +50991 -0.32598876953125 +50992 -0.2581787109375 +50993 -0.139801025390625 +50994 0.014617919921875 +50995 0.144378662109375 +50996 0.221038818359375 +50997 0.27069091796875 +50998 0.294036865234375 +50999 0.311767578125 +51000 0.339141845703125 +51001 0.360260009765625 +51002 0.360504150390625 +51003 0.308380126953125 +51004 0.18170166015625 +51005 0.0047607421875 +51006 -0.17559814453125 +51007 -0.3143310546875 +51008 -0.36785888671875 +51009 -0.36248779296875 +51010 -0.343536376953125 +51011 -0.3018798828125 +51012 -0.231414794921875 +51013 -0.117645263671875 +51014 0.007049560546875 +51015 0.087982177734375 +51016 0.13946533203125 +51017 0.17425537109375 +51018 0.188201904296875 +51019 0.171234130859375 +51020 0.118438720703125 +51021 0.05706787109375 +51022 -0.010711669921875 +51023 -0.0914306640625 +51024 -0.162322998046875 +51025 -0.194549560546875 +51026 -0.1492919921875 +51027 -0.02166748046875 +51028 0.124053955078125 +51029 0.211151123046875 +51030 0.240447998046875 +51031 0.242218017578125 +51032 0.2257080078125 +51033 0.194366455078125 +51034 0.115509033203125 +51035 0.0128173828125 +51036 -0.053802490234375 +51037 -0.110626220703125 +51038 -0.199493408203125 +51039 -0.29437255859375 +51040 -0.33221435546875 +51041 -0.27972412109375 +51042 -0.185333251953125 +51043 -0.128204345703125 +51044 -0.115692138671875 +51045 -0.116455078125 +51046 -0.105926513671875 +51047 -0.053955078125 +51048 0.048797607421875 +51049 0.157318115234375 +51050 0.212005615234375 +51051 0.218475341796875 +51052 0.23724365234375 +51053 0.30535888671875 +51054 0.38128662109375 +51055 0.404449462890625 +51056 0.3944091796875 +51057 0.3885498046875 +51058 0.362640380859375 +51059 0.27362060546875 +51060 0.11712646484375 +51061 -0.054901123046875 +51062 -0.19085693359375 +51063 -0.28570556640625 +51064 -0.339263916015625 +51065 -0.3775634765625 +51066 -0.445709228515625 +51067 -0.535064697265625 +51068 -0.629058837890625 +51069 -0.697601318359375 +51070 -0.70391845703125 +51071 -0.6424560546875 +51072 -0.491241455078125 +51073 -0.265716552734375 +51074 -0.023712158203125 +51075 0.201751708984375 +51076 0.375823974609375 +51077 0.485076904296875 +51078 0.56884765625 +51079 0.634765625 +51080 0.63763427734375 +51081 0.5660400390625 +51082 0.4720458984375 +51083 0.40692138671875 +51084 0.3778076171875 +51085 0.376953125 +51086 0.371978759765625 +51087 0.313140869140625 +51088 0.184417724609375 +51089 0.011199951171875 +51090 -0.171051025390625 +51091 -0.33740234375 +51092 -0.47198486328125 +51093 -0.560394287109375 +51094 -0.58056640625 +51095 -0.54754638671875 +51096 -0.508575439453125 +51097 -0.459503173828125 +51098 -0.394378662109375 +51099 -0.35260009765625 +51100 -0.31170654296875 +51101 -0.197418212890625 +51102 -0.007965087890625 +51103 0.207489013671875 +51104 0.409210205078125 +51105 0.57208251953125 +51106 0.66595458984375 +51107 0.65875244140625 +51108 0.56744384765625 +51109 0.431396484375 +51110 0.29443359375 +51111 0.182464599609375 +51112 0.06365966796875 +51113 -0.075958251953125 +51114 -0.189422607421875 +51115 -0.271942138671875 +51116 -0.342529296875 +51117 -0.364166259765625 +51118 -0.327239990234375 +51119 -0.2769775390625 +51120 -0.253692626953125 +51121 -0.24365234375 +51122 -0.1983642578125 +51123 -0.116241455078125 +51124 -0.036834716796875 +51125 0.034881591796875 +51126 0.09124755859375 +51127 0.10888671875 +51128 0.125518798828125 +51129 0.15771484375 +51130 0.17828369140625 +51131 0.17108154296875 +51132 0.129974365234375 +51133 0.082427978515625 +51134 0.027679443359375 +51135 -0.065643310546875 +51136 -0.15936279296875 +51137 -0.21307373046875 +51138 -0.234649658203125 +51139 -0.2001953125 +51140 -0.119171142578125 +51141 -0.024749755859375 +51142 0.085784912109375 +51143 0.178131103515625 +51144 0.215576171875 +51145 0.211456298828125 +51146 0.17523193359375 +51147 0.128753662109375 +51148 0.1019287109375 +51149 0.0743408203125 +51150 0.04327392578125 +51151 0.038177490234375 +51152 0.076263427734375 +51153 0.14105224609375 +51154 0.186431884765625 +51155 0.188812255859375 +51156 0.1390380859375 +51157 0.041778564453125 +51158 -0.079437255859375 +51159 -0.219390869140625 +51160 -0.367828369140625 +51161 -0.494873046875 +51162 -0.556243896484375 +51163 -0.508697509765625 +51164 -0.3756103515625 +51165 -0.218902587890625 +51166 -0.063751220703125 +51167 0.091552734375 +51168 0.23602294921875 +51169 0.342987060546875 +51170 0.39520263671875 +51171 0.389373779296875 +51172 0.324249267578125 +51173 0.224090576171875 +51174 0.124267578125 +51175 0.037078857421875 +51176 -0.010101318359375 +51177 -0.019439697265625 +51178 -0.022796630859375 +51179 -0.001556396484375 +51180 0.056304931640625 +51181 0.106719970703125 +51182 0.096893310546875 +51183 0.042694091796875 +51184 -0.018035888671875 +51185 -0.07586669921875 +51186 -0.11944580078125 +51187 -0.15972900390625 +51188 -0.202606201171875 +51189 -0.24859619140625 +51190 -0.30517578125 +51191 -0.36212158203125 +51192 -0.39141845703125 +51193 -0.35528564453125 +51194 -0.249969482421875 +51195 -0.092864990234375 +51196 0.08905029296875 +51197 0.2352294921875 +51198 0.318817138671875 +51199 0.358642578125 +51200 0.347747802734375 +51201 0.28564453125 +51202 0.223175048828125 +51203 0.196746826171875 +51204 0.179840087890625 +51205 0.155548095703125 +51206 0.151214599609375 +51207 0.156951904296875 +51208 0.13177490234375 +51209 0.100799560546875 +51210 0.087127685546875 +51211 0.05487060546875 +51212 -0.009002685546875 +51213 -0.10400390625 +51214 -0.229400634765625 +51215 -0.35552978515625 +51216 -0.441925048828125 +51217 -0.473846435546875 +51218 -0.464813232421875 +51219 -0.419097900390625 +51220 -0.334320068359375 +51221 -0.227935791015625 +51222 -0.12347412109375 +51223 -0.02764892578125 +51224 0.077667236328125 +51225 0.2132568359375 +51226 0.38885498046875 +51227 0.582794189453125 +51228 0.734039306640625 +51229 0.800140380859375 +51230 0.7783203125 +51231 0.6651611328125 +51232 0.45965576171875 +51233 0.199188232421875 +51234 -0.050689697265625 +51235 -0.23297119140625 +51236 -0.33013916015625 +51237 -0.368408203125 +51238 -0.378936767578125 +51239 -0.376983642578125 +51240 -0.37969970703125 +51241 -0.391510009765625 +51242 -0.385345458984375 +51243 -0.3419189453125 +51244 -0.28289794921875 +51245 -0.251617431640625 +51246 -0.266143798828125 +51247 -0.273345947265625 +51248 -0.216796875 +51249 -0.128265380859375 +51250 -0.068145751953125 +51251 -0.0430908203125 +51252 -0.024444580078125 +51253 0.020721435546875 +51254 0.124481201171875 +51255 0.25787353515625 +51256 0.379119873046875 +51257 0.47991943359375 +51258 0.5281982421875 +51259 0.511138916015625 +51260 0.456207275390625 +51261 0.407470703125 +51262 0.383758544921875 +51263 0.35687255859375 +51264 0.31182861328125 +51265 0.250885009765625 +51266 0.1654052734375 +51267 0.035247802734375 +51268 -0.142059326171875 +51269 -0.33563232421875 +51270 -0.5345458984375 +51271 -0.72186279296875 +51272 -0.836669921875 +51273 -0.8326416015625 +51274 -0.7296142578125 +51275 -0.582550048828125 +51276 -0.440093994140625 +51277 -0.324310302734375 +51278 -0.20147705078125 +51279 -0.044647216796875 +51280 0.103973388671875 +51281 0.202392578125 +51282 0.264495849609375 +51283 0.338897705078125 +51284 0.443817138671875 +51285 0.545074462890625 +51286 0.6173095703125 +51287 0.6524658203125 +51288 0.66339111328125 +51289 0.6561279296875 +51290 0.606781005859375 +51291 0.501190185546875 +51292 0.352783203125 +51293 0.176544189453125 +51294 -0.034820556640625 +51295 -0.258209228515625 +51296 -0.44244384765625 +51297 -0.5753173828125 +51298 -0.65203857421875 +51299 -0.641632080078125 +51300 -0.562164306640625 +51301 -0.458038330078125 +51302 -0.350555419921875 +51303 -0.260528564453125 +51304 -0.192108154296875 +51305 -0.141937255859375 +51306 -0.1021728515625 +51307 -0.062896728515625 +51308 -0.011932373046875 +51309 0.062835693359375 +51310 0.148712158203125 +51311 0.241729736328125 +51312 0.34912109375 +51313 0.457305908203125 +51314 0.54388427734375 +51315 0.5728759765625 +51316 0.506591796875 +51317 0.351226806640625 +51318 0.146514892578125 +51319 -0.05523681640625 +51320 -0.21624755859375 +51321 -0.334930419921875 +51322 -0.402984619140625 +51323 -0.4412841796875 +51324 -0.49578857421875 +51325 -0.5601806640625 +51326 -0.600738525390625 +51327 -0.584228515625 +51328 -0.47930908203125 +51329 -0.27935791015625 +51330 -0.0089111328125 +51331 0.268798828125 +51332 0.482818603515625 +51333 0.60369873046875 +51334 0.650421142578125 +51335 0.66400146484375 +51336 0.6414794921875 +51337 0.572540283203125 +51338 0.498138427734375 +51339 0.439453125 +51340 0.375518798828125 +51341 0.274505615234375 +51342 0.1087646484375 +51343 -0.099395751953125 +51344 -0.3182373046875 +51345 -0.5489501953125 +51346 -0.7738037109375 +51347 -0.86383056640625 +51348 -0.870391845703125 +51349 -0.86895751953125 +51350 -0.861053466796875 +51351 -0.765869140625 +51352 -0.5301513671875 +51353 -0.214691162109375 +51354 0.137359619140625 +51355 0.474822998046875 +51356 0.76239013671875 +51357 0.867462158203125 +51358 0.870361328125 +51359 0.86480712890625 +51360 0.831817626953125 +51361 0.677581787109375 +51362 0.495880126953125 +51363 0.30767822265625 +51364 0.116180419921875 +51365 -0.110748291015625 +51366 -0.381805419921875 +51367 -0.6572265625 +51368 -0.857421875 +51369 -0.870391845703125 +51370 -0.870391845703125 +51371 -0.86444091796875 +51372 -0.85723876953125 +51373 -0.790008544921875 +51374 -0.62847900390625 +51375 -0.3956298828125 +51376 -0.126708984375 +51377 0.150115966796875 +51378 0.424041748046875 +51379 0.670623779296875 +51380 0.854522705078125 +51381 0.866485595703125 +51382 0.86920166015625 +51383 0.8653564453125 +51384 0.857147216796875 +51385 0.766845703125 +51386 0.628509521484375 +51387 0.462127685546875 +51388 0.297210693359375 +51389 0.14862060546875 +51390 -0.00537109375 +51391 -0.15753173828125 +51392 -0.31304931640625 +51393 -0.48876953125 +51394 -0.6416015625 +51395 -0.751373291015625 +51396 -0.84619140625 +51397 -0.861297607421875 +51398 -0.863250732421875 +51399 -0.856597900390625 +51400 -0.7498779296875 +51401 -0.624542236328125 +51402 -0.47808837890625 +51403 -0.253387451171875 +51404 0.003692626953125 +51405 0.2257080078125 +51406 0.427154541015625 +51407 0.643218994140625 +51408 0.855926513671875 +51409 0.870361328125 +51410 0.870361328125 +51411 0.862762451171875 +51412 0.79669189453125 +51413 0.595794677734375 +51414 0.362152099609375 +51415 0.1270751953125 +51416 -0.086944580078125 +51417 -0.2784423828125 +51418 -0.484832763671875 +51419 -0.729583740234375 +51420 -0.86688232421875 +51421 -0.870391845703125 +51422 -0.86859130859375 +51423 -0.86279296875 +51424 -0.817962646484375 +51425 -0.6116943359375 +51426 -0.3128662109375 +51427 0.039398193359375 +51428 0.422821044921875 +51429 0.805145263671875 +51430 0.870361328125 +51431 0.870361328125 +51432 0.860015869140625 +51433 0.727935791015625 +51434 0.48114013671875 +51435 0.2059326171875 +51436 -0.06103515625 +51437 -0.29913330078125 +51438 -0.516204833984375 +51439 -0.7252197265625 +51440 -0.85980224609375 +51441 -0.870391845703125 +51442 -0.870391845703125 +51443 -0.858062744140625 +51444 -0.673004150390625 +51445 -0.42694091796875 +51446 -0.2100830078125 +51447 -0.0362548828125 +51448 0.10943603515625 +51449 0.23516845703125 +51450 0.373687744140625 +51451 0.517791748046875 +51452 0.602783203125 +51453 0.635711669921875 +51454 0.655181884765625 +51455 0.65948486328125 +51456 0.651275634765625 +51457 0.61846923828125 +51458 0.53753662109375 +51459 0.404144287109375 +51460 0.22186279296875 +51461 0.003997802734375 +51462 -0.22100830078125 +51463 -0.42449951171875 +51464 -0.579833984375 +51465 -0.641876220703125 +51466 -0.6177978515625 +51467 -0.575531005859375 +51468 -0.526336669921875 +51469 -0.42645263671875 +51470 -0.2581787109375 +51471 -0.068695068359375 +51472 0.09222412109375 +51473 0.232147216796875 +51474 0.3509521484375 +51475 0.410064697265625 +51476 0.372955322265625 +51477 0.2554931640625 +51478 0.10711669921875 +51479 -0.052886962890625 +51480 -0.186279296875 +51481 -0.23291015625 +51482 -0.209442138671875 +51483 -0.174163818359375 +51484 -0.126739501953125 +51485 -0.048126220703125 +51486 0.0426025390625 +51487 0.10748291015625 +51488 0.1409912109375 +51489 0.19708251953125 +51490 0.273651123046875 +51491 0.31768798828125 +51492 0.341094970703125 +51493 0.368011474609375 +51494 0.37249755859375 +51495 0.30072021484375 +51496 0.1517333984375 +51497 -0.01470947265625 +51498 -0.1883544921875 +51499 -0.372711181640625 +51500 -0.51397705078125 +51501 -0.57177734375 +51502 -0.53948974609375 +51503 -0.43511962890625 +51504 -0.2962646484375 +51505 -0.161102294921875 +51506 -0.0435791015625 +51507 0.060394287109375 +51508 0.13665771484375 +51509 0.170135498046875 +51510 0.16552734375 +51511 0.15728759765625 +51512 0.150787353515625 +51513 0.12200927734375 +51514 0.080108642578125 +51515 0.05126953125 +51516 0.062896728515625 +51517 0.09271240234375 +51518 0.092987060546875 +51519 0.07855224609375 +51520 0.06427001953125 +51521 0.0347900390625 +51522 -0.01171875 +51523 -0.056060791015625 +51524 -0.055511474609375 +51525 -0.010467529296875 +51526 0.02508544921875 +51527 0.025665283203125 +51528 0.017333984375 +51529 0.00189208984375 +51530 -0.03173828125 +51531 -0.071502685546875 +51532 -0.13543701171875 +51533 -0.219970703125 +51534 -0.300506591796875 +51535 -0.376312255859375 +51536 -0.416107177734375 +51537 -0.371124267578125 +51538 -0.242279052734375 +51539 -0.069732666015625 +51540 0.125640869140625 +51541 0.31268310546875 +51542 0.45501708984375 +51543 0.554779052734375 +51544 0.61065673828125 +51545 0.610931396484375 +51546 0.531463623046875 +51547 0.3883056640625 +51548 0.23468017578125 +51549 0.095245361328125 +51550 -0.00396728515625 +51551 -0.04852294921875 +51552 -0.055145263671875 +51553 -0.0758056640625 +51554 -0.138702392578125 +51555 -0.209197998046875 +51556 -0.289031982421875 +51557 -0.37884521484375 +51558 -0.456329345703125 +51559 -0.51641845703125 +51560 -0.519287109375 +51561 -0.458251953125 +51562 -0.384796142578125 +51563 -0.323699951171875 +51564 -0.269287109375 +51565 -0.1951904296875 +51566 -0.100006103515625 +51567 -0.01055908203125 +51568 0.1033935546875 +51569 0.24908447265625 +51570 0.373199462890625 +51571 0.45806884765625 +51572 0.511474609375 +51573 0.565399169921875 +51574 0.61138916015625 +51575 0.5897216796875 +51576 0.4906005859375 +51577 0.33148193359375 +51578 0.147796630859375 +51579 -0.01873779296875 +51580 -0.140289306640625 +51581 -0.191986083984375 +51582 -0.184295654296875 +51583 -0.161834716796875 +51584 -0.166595458984375 +51585 -0.19390869140625 +51586 -0.22442626953125 +51587 -0.279754638671875 +51588 -0.3389892578125 +51589 -0.3543701171875 +51590 -0.348175048828125 +51591 -0.32598876953125 +51592 -0.2581787109375 +51593 -0.139801025390625 +51594 0.014617919921875 +51595 0.144378662109375 +51596 0.221038818359375 +51597 0.27069091796875 +51598 0.294036865234375 +51599 0.311767578125 +51600 0.339141845703125 +51601 0.360260009765625 +51602 0.360504150390625 +51603 0.308380126953125 +51604 0.18170166015625 +51605 0.0047607421875 +51606 -0.17559814453125 +51607 -0.3143310546875 +51608 -0.36785888671875 +51609 -0.36248779296875 +51610 -0.343536376953125 +51611 -0.3018798828125 +51612 -0.231414794921875 +51613 -0.117645263671875 +51614 0.007049560546875 +51615 0.087982177734375 +51616 0.13946533203125 +51617 0.17425537109375 +51618 0.188201904296875 +51619 0.171234130859375 +51620 0.118438720703125 +51621 0.05706787109375 +51622 -0.010711669921875 +51623 -0.0914306640625 +51624 -0.162322998046875 +51625 -0.194549560546875 +51626 -0.1492919921875 +51627 -0.02166748046875 +51628 0.124053955078125 +51629 0.211151123046875 +51630 0.240447998046875 +51631 0.242218017578125 +51632 0.2257080078125 +51633 0.194366455078125 +51634 0.115509033203125 +51635 0.0128173828125 +51636 -0.053802490234375 +51637 -0.110626220703125 +51638 -0.199493408203125 +51639 -0.29437255859375 +51640 -0.33221435546875 +51641 -0.27972412109375 +51642 -0.185333251953125 +51643 -0.128204345703125 +51644 -0.115692138671875 +51645 -0.116455078125 +51646 -0.105926513671875 +51647 -0.053955078125 +51648 0.048797607421875 +51649 0.157318115234375 +51650 0.212005615234375 +51651 0.218475341796875 +51652 0.23724365234375 +51653 0.30535888671875 +51654 0.38128662109375 +51655 0.404449462890625 +51656 0.3944091796875 +51657 0.3885498046875 +51658 0.362640380859375 +51659 0.27362060546875 +51660 0.11712646484375 +51661 -0.054901123046875 +51662 -0.19085693359375 +51663 -0.28570556640625 +51664 -0.339263916015625 +51665 -0.3775634765625 +51666 -0.445709228515625 +51667 -0.535064697265625 +51668 -0.629058837890625 +51669 -0.697601318359375 +51670 -0.70391845703125 +51671 -0.6424560546875 +51672 -0.491241455078125 +51673 -0.265716552734375 +51674 -0.023712158203125 +51675 0.201751708984375 +51676 0.375823974609375 +51677 0.485076904296875 +51678 0.56884765625 +51679 0.634765625 +51680 0.63763427734375 +51681 0.5660400390625 +51682 0.4720458984375 +51683 0.40692138671875 +51684 0.3778076171875 +51685 0.376953125 +51686 0.371978759765625 +51687 0.313140869140625 +51688 0.184417724609375 +51689 0.011199951171875 +51690 -0.171051025390625 +51691 -0.33740234375 +51692 -0.47198486328125 +51693 -0.560394287109375 +51694 -0.58056640625 +51695 -0.54754638671875 +51696 -0.508575439453125 +51697 -0.459503173828125 +51698 -0.394378662109375 +51699 -0.35260009765625 +51700 -0.31170654296875 +51701 -0.197418212890625 +51702 -0.007965087890625 +51703 0.207489013671875 +51704 0.409210205078125 +51705 0.57208251953125 +51706 0.66595458984375 +51707 0.65875244140625 +51708 0.56744384765625 +51709 0.431396484375 +51710 0.29443359375 +51711 0.182464599609375 +51712 0.06365966796875 +51713 -0.075958251953125 +51714 -0.189422607421875 +51715 -0.271942138671875 +51716 -0.342529296875 +51717 -0.364166259765625 +51718 -0.327239990234375 +51719 -0.2769775390625 +51720 -0.253692626953125 +51721 -0.24365234375 +51722 -0.1983642578125 +51723 -0.116241455078125 +51724 -0.036834716796875 +51725 0.034881591796875 +51726 0.09124755859375 +51727 0.10888671875 +51728 0.125518798828125 +51729 0.15771484375 +51730 0.17828369140625 +51731 0.17108154296875 +51732 0.129974365234375 +51733 0.082427978515625 +51734 0.027679443359375 +51735 -0.065643310546875 +51736 -0.15936279296875 +51737 -0.21307373046875 +51738 -0.234649658203125 +51739 -0.2001953125 +51740 -0.119171142578125 +51741 -0.024749755859375 +51742 0.085784912109375 +51743 0.178131103515625 +51744 0.215576171875 +51745 0.211456298828125 +51746 0.17523193359375 +51747 0.128753662109375 +51748 0.1019287109375 +51749 0.0743408203125 +51750 0.04327392578125 +51751 0.038177490234375 +51752 0.076263427734375 +51753 0.14105224609375 +51754 0.186431884765625 +51755 0.188812255859375 +51756 0.1390380859375 +51757 0.041778564453125 +51758 -0.079437255859375 +51759 -0.219390869140625 +51760 -0.367828369140625 +51761 -0.494873046875 +51762 -0.556243896484375 +51763 -0.508697509765625 +51764 -0.3756103515625 +51765 -0.218902587890625 +51766 -0.063751220703125 +51767 0.091552734375 +51768 0.23602294921875 +51769 0.342987060546875 +51770 0.39520263671875 +51771 0.389373779296875 +51772 0.324249267578125 +51773 0.224090576171875 +51774 0.124267578125 +51775 0.037078857421875 +51776 -0.010101318359375 +51777 -0.019439697265625 +51778 -0.022796630859375 +51779 -0.001556396484375 +51780 0.056304931640625 +51781 0.106719970703125 +51782 0.096893310546875 +51783 0.042694091796875 +51784 -0.018035888671875 +51785 -0.07586669921875 +51786 -0.11944580078125 +51787 -0.15972900390625 +51788 -0.202606201171875 +51789 -0.24859619140625 +51790 -0.30517578125 +51791 -0.36212158203125 +51792 -0.39141845703125 +51793 -0.35528564453125 +51794 -0.249969482421875 +51795 -0.092864990234375 +51796 0.08905029296875 +51797 0.2352294921875 +51798 0.318817138671875 +51799 0.358642578125 +51800 0.347747802734375 +51801 0.28564453125 +51802 0.223175048828125 +51803 0.196746826171875 +51804 0.179840087890625 +51805 0.155548095703125 +51806 0.151214599609375 +51807 0.156951904296875 +51808 0.13177490234375 +51809 0.100799560546875 +51810 0.087127685546875 +51811 0.05487060546875 +51812 -0.009002685546875 +51813 -0.10400390625 +51814 -0.229400634765625 +51815 -0.35552978515625 +51816 -0.441925048828125 +51817 -0.473846435546875 +51818 -0.464813232421875 +51819 -0.419097900390625 +51820 -0.334320068359375 +51821 -0.227935791015625 +51822 -0.12347412109375 +51823 -0.02764892578125 +51824 0.077667236328125 +51825 0.2132568359375 +51826 0.38885498046875 +51827 0.582794189453125 +51828 0.734039306640625 +51829 0.800140380859375 +51830 0.7783203125 +51831 0.6651611328125 +51832 0.45965576171875 +51833 0.199188232421875 +51834 -0.050689697265625 +51835 -0.23297119140625 +51836 -0.33013916015625 +51837 -0.368408203125 +51838 -0.378936767578125 +51839 -0.376983642578125 +51840 -0.37969970703125 +51841 -0.391510009765625 +51842 -0.385345458984375 +51843 -0.3419189453125 +51844 -0.28289794921875 +51845 -0.251617431640625 +51846 -0.266143798828125 +51847 -0.273345947265625 +51848 -0.216796875 +51849 -0.128265380859375 +51850 -0.068145751953125 +51851 -0.0430908203125 +51852 -0.024444580078125 +51853 0.020721435546875 +51854 0.124481201171875 +51855 0.25787353515625 +51856 0.379119873046875 +51857 0.47991943359375 +51858 0.5281982421875 +51859 0.511138916015625 +51860 0.456207275390625 +51861 0.407470703125 +51862 0.383758544921875 +51863 0.35687255859375 +51864 0.31182861328125 +51865 0.250885009765625 +51866 0.1654052734375 +51867 0.035247802734375 +51868 -0.142059326171875 +51869 -0.33563232421875 +51870 -0.5345458984375 +51871 -0.72186279296875 +51872 -0.836669921875 +51873 -0.8326416015625 +51874 -0.7296142578125 +51875 -0.582550048828125 +51876 -0.440093994140625 +51877 -0.324310302734375 +51878 -0.20147705078125 +51879 -0.044647216796875 +51880 0.103973388671875 +51881 0.202392578125 +51882 0.264495849609375 +51883 0.338897705078125 +51884 0.443817138671875 +51885 0.545074462890625 +51886 0.6173095703125 +51887 0.6524658203125 +51888 0.66339111328125 +51889 0.6561279296875 +51890 0.606781005859375 +51891 0.501190185546875 +51892 0.352783203125 +51893 0.176544189453125 +51894 -0.034820556640625 +51895 -0.258209228515625 +51896 -0.44244384765625 +51897 -0.5753173828125 +51898 -0.65203857421875 +51899 -0.641632080078125 +51900 -0.562164306640625 +51901 -0.458038330078125 +51902 -0.350555419921875 +51903 -0.260528564453125 +51904 -0.192108154296875 +51905 -0.141937255859375 +51906 -0.1021728515625 +51907 -0.062896728515625 +51908 -0.011932373046875 +51909 0.062835693359375 +51910 0.148712158203125 +51911 0.241729736328125 +51912 0.34912109375 +51913 0.457305908203125 +51914 0.54388427734375 +51915 0.5728759765625 +51916 0.506591796875 +51917 0.351226806640625 +51918 0.146514892578125 +51919 -0.05523681640625 +51920 -0.21624755859375 +51921 -0.334930419921875 +51922 -0.402984619140625 +51923 -0.4412841796875 +51924 -0.49578857421875 +51925 -0.5601806640625 +51926 -0.600738525390625 +51927 -0.584228515625 +51928 -0.47930908203125 +51929 -0.27935791015625 +51930 -0.0089111328125 +51931 0.268798828125 +51932 0.482818603515625 +51933 0.60369873046875 +51934 0.650421142578125 +51935 0.66400146484375 +51936 0.6414794921875 +51937 0.572540283203125 +51938 0.498138427734375 +51939 0.439453125 +51940 0.375518798828125 +51941 0.274505615234375 +51942 0.1087646484375 +51943 -0.099395751953125 +51944 -0.3182373046875 +51945 -0.5489501953125 +51946 -0.7738037109375 +51947 -0.86383056640625 +51948 -0.870391845703125 +51949 -0.86895751953125 +51950 -0.861053466796875 +51951 -0.765869140625 +51952 -0.5301513671875 +51953 -0.214691162109375 +51954 0.137359619140625 +51955 0.474822998046875 +51956 0.76239013671875 +51957 0.867462158203125 +51958 0.870361328125 +51959 0.86480712890625 +51960 0.831817626953125 +51961 0.677581787109375 +51962 0.495880126953125 +51963 0.30767822265625 +51964 0.116180419921875 +51965 -0.110748291015625 +51966 -0.381805419921875 +51967 -0.6572265625 +51968 -0.857421875 +51969 -0.870391845703125 +51970 -0.870391845703125 +51971 -0.86444091796875 +51972 -0.85723876953125 +51973 -0.790008544921875 +51974 -0.62847900390625 +51975 -0.3956298828125 +51976 -0.126708984375 +51977 0.150115966796875 +51978 0.424041748046875 +51979 0.670623779296875 +51980 0.854522705078125 +51981 0.866485595703125 +51982 0.86920166015625 +51983 0.8653564453125 +51984 0.857147216796875 +51985 0.766845703125 +51986 0.628509521484375 +51987 0.462127685546875 +51988 0.297210693359375 +51989 0.14862060546875 +51990 -0.00537109375 +51991 -0.15753173828125 +51992 -0.31304931640625 +51993 -0.48876953125 +51994 -0.6416015625 +51995 -0.751373291015625 +51996 -0.84619140625 +51997 -0.861297607421875 +51998 -0.863250732421875 +51999 -0.856597900390625 +52000 -0.7498779296875 +52001 -0.624542236328125 +52002 -0.47808837890625 +52003 -0.253387451171875 +52004 0.003692626953125 +52005 0.2257080078125 +52006 0.427154541015625 +52007 0.643218994140625 +52008 0.855926513671875 +52009 0.870361328125 +52010 0.870361328125 +52011 0.862762451171875 +52012 0.79669189453125 +52013 0.595794677734375 +52014 0.362152099609375 +52015 0.1270751953125 +52016 -0.086944580078125 +52017 -0.2784423828125 +52018 -0.484832763671875 +52019 -0.729583740234375 +52020 -0.86688232421875 +52021 -0.870391845703125 +52022 -0.86859130859375 +52023 -0.86279296875 +52024 -0.817962646484375 +52025 -0.6116943359375 +52026 -0.3128662109375 +52027 0.039398193359375 +52028 0.422821044921875 +52029 0.805145263671875 +52030 0.870361328125 +52031 0.870361328125 +52032 0.860015869140625 +52033 0.727935791015625 +52034 0.48114013671875 +52035 0.2059326171875 +52036 -0.06103515625 +52037 -0.29913330078125 +52038 -0.516204833984375 +52039 -0.7252197265625 +52040 -0.85980224609375 +52041 -0.870391845703125 +52042 -0.870391845703125 +52043 -0.858062744140625 +52044 -0.673004150390625 +52045 -0.42694091796875 +52046 -0.2100830078125 +52047 -0.0362548828125 +52048 0.10943603515625 +52049 0.23516845703125 +52050 0.373687744140625 +52051 0.517791748046875 +52052 0.602783203125 +52053 0.635711669921875 +52054 0.655181884765625 +52055 0.65948486328125 +52056 0.651275634765625 +52057 0.61846923828125 +52058 0.53753662109375 +52059 0.404144287109375 +52060 0.22186279296875 +52061 0.003997802734375 +52062 -0.22100830078125 +52063 -0.42449951171875 +52064 -0.579833984375 +52065 -0.641876220703125 +52066 -0.6177978515625 +52067 -0.575531005859375 +52068 -0.526336669921875 +52069 -0.42645263671875 +52070 -0.2581787109375 +52071 -0.068695068359375 +52072 0.09222412109375 +52073 0.232147216796875 +52074 0.3509521484375 +52075 0.410064697265625 +52076 0.372955322265625 +52077 0.2554931640625 +52078 0.10711669921875 +52079 -0.052886962890625 +52080 -0.186279296875 +52081 -0.23291015625 +52082 -0.209442138671875 +52083 -0.174163818359375 +52084 -0.126739501953125 +52085 -0.048126220703125 +52086 0.0426025390625 +52087 0.10748291015625 +52088 0.1409912109375 +52089 0.19708251953125 +52090 0.273651123046875 +52091 0.31768798828125 +52092 0.341094970703125 +52093 0.368011474609375 +52094 0.37249755859375 +52095 0.30072021484375 +52096 0.1517333984375 +52097 -0.01470947265625 +52098 -0.1883544921875 +52099 -0.372711181640625 +52100 -0.51397705078125 +52101 -0.57177734375 +52102 -0.53948974609375 +52103 -0.43511962890625 +52104 -0.2962646484375 +52105 -0.161102294921875 +52106 -0.0435791015625 +52107 0.060394287109375 +52108 0.13665771484375 +52109 0.170135498046875 +52110 0.16552734375 +52111 0.15728759765625 +52112 0.150787353515625 +52113 0.12200927734375 +52114 0.080108642578125 +52115 0.05126953125 +52116 0.062896728515625 +52117 0.09271240234375 +52118 0.092987060546875 +52119 0.07855224609375 +52120 0.06427001953125 +52121 0.0347900390625 +52122 -0.01171875 +52123 -0.056060791015625 +52124 -0.055511474609375 +52125 -0.010467529296875 +52126 0.02508544921875 +52127 0.025665283203125 +52128 0.017333984375 +52129 0.00189208984375 +52130 -0.03173828125 +52131 -0.071502685546875 +52132 -0.13543701171875 +52133 -0.219970703125 +52134 -0.300506591796875 +52135 -0.376312255859375 +52136 -0.416107177734375 +52137 -0.371124267578125 +52138 -0.242279052734375 +52139 -0.069732666015625 +52140 0.125640869140625 +52141 0.31268310546875 +52142 0.45501708984375 +52143 0.554779052734375 +52144 0.61065673828125 +52145 0.610931396484375 +52146 0.531463623046875 +52147 0.3883056640625 +52148 0.23468017578125 +52149 0.095245361328125 +52150 -0.00396728515625 +52151 -0.04852294921875 +52152 -0.055145263671875 +52153 -0.0758056640625 +52154 -0.138702392578125 +52155 -0.209197998046875 +52156 -0.289031982421875 +52157 -0.37884521484375 +52158 -0.456329345703125 +52159 -0.51641845703125 +52160 -0.519287109375 +52161 -0.458251953125 +52162 -0.384796142578125 +52163 -0.323699951171875 +52164 -0.269287109375 +52165 -0.1951904296875 +52166 -0.100006103515625 +52167 -0.01055908203125 +52168 0.1033935546875 +52169 0.24908447265625 +52170 0.373199462890625 +52171 0.45806884765625 +52172 0.511474609375 +52173 0.565399169921875 +52174 0.61138916015625 +52175 0.5897216796875 +52176 0.4906005859375 +52177 0.33148193359375 +52178 0.147796630859375 +52179 -0.01873779296875 +52180 -0.140289306640625 +52181 -0.191986083984375 +52182 -0.184295654296875 +52183 -0.161834716796875 +52184 -0.166595458984375 +52185 -0.19390869140625 +52186 -0.22442626953125 +52187 -0.279754638671875 +52188 -0.3389892578125 +52189 -0.3543701171875 +52190 -0.348175048828125 +52191 -0.32598876953125 +52192 -0.2581787109375 +52193 -0.139801025390625 +52194 0.014617919921875 +52195 0.144378662109375 +52196 0.221038818359375 +52197 0.27069091796875 +52198 0.294036865234375 +52199 0.311767578125 +52200 0.339141845703125 +52201 0.360260009765625 +52202 0.360504150390625 +52203 0.308380126953125 +52204 0.18170166015625 +52205 0.0047607421875 +52206 -0.17559814453125 +52207 -0.3143310546875 +52208 -0.36785888671875 +52209 -0.36248779296875 +52210 -0.343536376953125 +52211 -0.3018798828125 +52212 -0.231414794921875 +52213 -0.117645263671875 +52214 0.007049560546875 +52215 0.087982177734375 +52216 0.13946533203125 +52217 0.17425537109375 +52218 0.188201904296875 +52219 0.171234130859375 +52220 0.118438720703125 +52221 0.05706787109375 +52222 -0.010711669921875 +52223 -0.0914306640625 +52224 -0.162322998046875 +52225 -0.194549560546875 +52226 -0.1492919921875 +52227 -0.02166748046875 +52228 0.124053955078125 +52229 0.211151123046875 +52230 0.240447998046875 +52231 0.242218017578125 +52232 0.2257080078125 +52233 0.194366455078125 +52234 0.115509033203125 +52235 0.0128173828125 +52236 -0.053802490234375 +52237 -0.110626220703125 +52238 -0.199493408203125 +52239 -0.29437255859375 +52240 -0.33221435546875 +52241 -0.27972412109375 +52242 -0.185333251953125 +52243 -0.128204345703125 +52244 -0.115692138671875 +52245 -0.116455078125 +52246 -0.105926513671875 +52247 -0.053955078125 +52248 0.048797607421875 +52249 0.157318115234375 +52250 0.212005615234375 +52251 0.218475341796875 +52252 0.23724365234375 +52253 0.30535888671875 +52254 0.38128662109375 +52255 0.404449462890625 +52256 0.3944091796875 +52257 0.3885498046875 +52258 0.362640380859375 +52259 0.27362060546875 +52260 0.11712646484375 +52261 -0.054901123046875 +52262 -0.19085693359375 +52263 -0.28570556640625 +52264 -0.339263916015625 +52265 -0.3775634765625 +52266 -0.445709228515625 +52267 -0.535064697265625 +52268 -0.629058837890625 +52269 -0.697601318359375 +52270 -0.70391845703125 +52271 -0.6424560546875 +52272 -0.491241455078125 +52273 -0.265716552734375 +52274 -0.023712158203125 +52275 0.201751708984375 +52276 0.375823974609375 +52277 0.485076904296875 +52278 0.56884765625 +52279 0.634765625 +52280 0.63763427734375 +52281 0.5660400390625 +52282 0.4720458984375 +52283 0.40692138671875 +52284 0.3778076171875 +52285 0.376953125 +52286 0.371978759765625 +52287 0.313140869140625 +52288 0.184417724609375 +52289 0.011199951171875 +52290 -0.171051025390625 +52291 -0.33740234375 +52292 -0.47198486328125 +52293 -0.560394287109375 +52294 -0.58056640625 +52295 -0.54754638671875 +52296 -0.508575439453125 +52297 -0.459503173828125 +52298 -0.394378662109375 +52299 -0.35260009765625 +52300 -0.31170654296875 +52301 -0.197418212890625 +52302 -0.007965087890625 +52303 0.207489013671875 +52304 0.409210205078125 +52305 0.57208251953125 +52306 0.66595458984375 +52307 0.65875244140625 +52308 0.56744384765625 +52309 0.431396484375 +52310 0.29443359375 +52311 0.182464599609375 +52312 0.06365966796875 +52313 -0.075958251953125 +52314 -0.189422607421875 +52315 -0.271942138671875 +52316 -0.342529296875 +52317 -0.364166259765625 +52318 -0.327239990234375 +52319 -0.2769775390625 +52320 -0.253692626953125 +52321 -0.24365234375 +52322 -0.1983642578125 +52323 -0.116241455078125 +52324 -0.036834716796875 +52325 0.034881591796875 +52326 0.09124755859375 +52327 0.10888671875 +52328 0.125518798828125 +52329 0.15771484375 +52330 0.17828369140625 +52331 0.17108154296875 +52332 0.129974365234375 +52333 0.082427978515625 +52334 0.027679443359375 +52335 -0.065643310546875 +52336 -0.15936279296875 +52337 -0.21307373046875 +52338 -0.234649658203125 +52339 -0.2001953125 +52340 -0.119171142578125 +52341 -0.024749755859375 +52342 0.085784912109375 +52343 0.178131103515625 +52344 0.215576171875 +52345 0.211456298828125 +52346 0.17523193359375 +52347 0.128753662109375 +52348 0.1019287109375 +52349 0.0743408203125 +52350 0.04327392578125 +52351 0.038177490234375 +52352 0.076263427734375 +52353 0.14105224609375 +52354 0.186431884765625 +52355 0.188812255859375 +52356 0.1390380859375 +52357 0.041778564453125 +52358 -0.079437255859375 +52359 -0.219390869140625 +52360 -0.367828369140625 +52361 -0.494873046875 +52362 -0.556243896484375 +52363 -0.508697509765625 +52364 -0.3756103515625 +52365 -0.218902587890625 +52366 -0.063751220703125 +52367 0.091552734375 +52368 0.23602294921875 +52369 0.342987060546875 +52370 0.39520263671875 +52371 0.389373779296875 +52372 0.324249267578125 +52373 0.224090576171875 +52374 0.124267578125 +52375 0.037078857421875 +52376 -0.010101318359375 +52377 -0.019439697265625 +52378 -0.022796630859375 +52379 -0.001556396484375 +52380 0.056304931640625 +52381 0.106719970703125 +52382 0.096893310546875 +52383 0.042694091796875 +52384 -0.018035888671875 +52385 -0.07586669921875 +52386 -0.11944580078125 +52387 -0.15972900390625 +52388 -0.202606201171875 +52389 -0.24859619140625 +52390 -0.30517578125 +52391 -0.36212158203125 +52392 -0.39141845703125 +52393 -0.35528564453125 +52394 -0.249969482421875 +52395 -0.092864990234375 +52396 0.08905029296875 +52397 0.2352294921875 +52398 0.318817138671875 +52399 0.358642578125 +52400 0.347747802734375 +52401 0.28564453125 +52402 0.223175048828125 +52403 0.196746826171875 +52404 0.179840087890625 +52405 0.155548095703125 +52406 0.151214599609375 +52407 0.156951904296875 +52408 0.13177490234375 +52409 0.100799560546875 +52410 0.087127685546875 +52411 0.05487060546875 +52412 -0.009002685546875 +52413 -0.10400390625 +52414 -0.229400634765625 +52415 -0.35552978515625 +52416 -0.441925048828125 +52417 -0.473846435546875 +52418 -0.464813232421875 +52419 -0.419097900390625 +52420 -0.334320068359375 +52421 -0.227935791015625 +52422 -0.12347412109375 +52423 -0.02764892578125 +52424 0.077667236328125 +52425 0.2132568359375 +52426 0.38885498046875 +52427 0.582794189453125 +52428 0.734039306640625 +52429 0.800140380859375 +52430 0.7783203125 +52431 0.6651611328125 +52432 0.45965576171875 +52433 0.199188232421875 +52434 -0.050689697265625 +52435 -0.23297119140625 +52436 -0.33013916015625 +52437 -0.368408203125 +52438 -0.378936767578125 +52439 -0.376983642578125 +52440 -0.37969970703125 +52441 -0.391510009765625 +52442 -0.385345458984375 +52443 -0.3419189453125 +52444 -0.28289794921875 +52445 -0.251617431640625 +52446 -0.266143798828125 +52447 -0.273345947265625 +52448 -0.216796875 +52449 -0.128265380859375 +52450 -0.068145751953125 +52451 -0.0430908203125 +52452 -0.024444580078125 +52453 0.020721435546875 +52454 0.124481201171875 +52455 0.25787353515625 +52456 0.379119873046875 +52457 0.47991943359375 +52458 0.5281982421875 +52459 0.511138916015625 +52460 0.456207275390625 +52461 0.407470703125 +52462 0.383758544921875 +52463 0.35687255859375 +52464 0.31182861328125 +52465 0.250885009765625 +52466 0.1654052734375 +52467 0.035247802734375 +52468 -0.142059326171875 +52469 -0.33563232421875 +52470 -0.5345458984375 +52471 -0.72186279296875 +52472 -0.836669921875 +52473 -0.8326416015625 +52474 -0.7296142578125 +52475 -0.582550048828125 +52476 -0.440093994140625 +52477 -0.324310302734375 +52478 -0.20147705078125 +52479 -0.044647216796875 +52480 0.103973388671875 +52481 0.202392578125 +52482 0.264495849609375 +52483 0.338897705078125 +52484 0.443817138671875 +52485 0.545074462890625 +52486 0.6173095703125 +52487 0.6524658203125 +52488 0.66339111328125 +52489 0.6561279296875 +52490 0.606781005859375 +52491 0.501190185546875 +52492 0.352783203125 +52493 0.176544189453125 +52494 -0.034820556640625 +52495 -0.258209228515625 +52496 -0.44244384765625 +52497 -0.5753173828125 +52498 -0.65203857421875 +52499 -0.641632080078125 +52500 -0.562164306640625 +52501 -0.458038330078125 +52502 -0.350555419921875 +52503 -0.260528564453125 +52504 -0.192108154296875 +52505 -0.141937255859375 +52506 -0.1021728515625 +52507 -0.062896728515625 +52508 -0.011932373046875 +52509 0.062835693359375 +52510 0.148712158203125 +52511 0.241729736328125 +52512 0.34912109375 +52513 0.457305908203125 +52514 0.54388427734375 +52515 0.5728759765625 +52516 0.506591796875 +52517 0.351226806640625 +52518 0.146514892578125 +52519 -0.05523681640625 +52520 -0.21624755859375 +52521 -0.334930419921875 +52522 -0.402984619140625 +52523 -0.4412841796875 +52524 -0.49578857421875 +52525 -0.5601806640625 +52526 -0.600738525390625 +52527 -0.584228515625 +52528 -0.47930908203125 +52529 -0.27935791015625 +52530 -0.0089111328125 +52531 0.268798828125 +52532 0.482818603515625 +52533 0.60369873046875 +52534 0.650421142578125 +52535 0.66400146484375 +52536 0.6414794921875 +52537 0.572540283203125 +52538 0.498138427734375 +52539 0.439453125 +52540 0.375518798828125 +52541 0.274505615234375 +52542 0.1087646484375 +52543 -0.099395751953125 +52544 -0.3182373046875 +52545 -0.5489501953125 +52546 -0.7738037109375 +52547 -0.86383056640625 +52548 -0.870391845703125 +52549 -0.86895751953125 +52550 -0.861053466796875 +52551 -0.765869140625 +52552 -0.5301513671875 +52553 -0.214691162109375 +52554 0.137359619140625 +52555 0.474822998046875 +52556 0.76239013671875 +52557 0.867462158203125 +52558 0.870361328125 +52559 0.86480712890625 +52560 0.831817626953125 +52561 0.677581787109375 +52562 0.495880126953125 +52563 0.30767822265625 +52564 0.116180419921875 +52565 -0.110748291015625 +52566 -0.381805419921875 +52567 -0.6572265625 +52568 -0.857421875 +52569 -0.870391845703125 +52570 -0.870391845703125 +52571 -0.86444091796875 +52572 -0.85723876953125 +52573 -0.790008544921875 +52574 -0.62847900390625 +52575 -0.3956298828125 +52576 -0.126708984375 +52577 0.150115966796875 +52578 0.424041748046875 +52579 0.670623779296875 +52580 0.854522705078125 +52581 0.866485595703125 +52582 0.86920166015625 +52583 0.8653564453125 +52584 0.857147216796875 +52585 0.766845703125 +52586 0.628509521484375 +52587 0.462127685546875 +52588 0.297210693359375 +52589 0.14862060546875 +52590 -0.00537109375 +52591 -0.15753173828125 +52592 -0.31304931640625 +52593 -0.48876953125 +52594 -0.6416015625 +52595 -0.751373291015625 +52596 -0.84619140625 +52597 -0.861297607421875 +52598 -0.863250732421875 +52599 -0.856597900390625 +52600 -0.7498779296875 +52601 -0.624542236328125 +52602 -0.47808837890625 +52603 -0.253387451171875 +52604 0.003692626953125 +52605 0.2257080078125 +52606 0.427154541015625 +52607 0.643218994140625 +52608 0.855926513671875 +52609 0.870361328125 +52610 0.870361328125 +52611 0.862762451171875 +52612 0.79669189453125 +52613 0.595794677734375 +52614 0.362152099609375 +52615 0.1270751953125 +52616 -0.086944580078125 +52617 -0.2784423828125 +52618 -0.484832763671875 +52619 -0.729583740234375 +52620 -0.86688232421875 +52621 -0.870391845703125 +52622 -0.86859130859375 +52623 -0.86279296875 +52624 -0.817962646484375 +52625 -0.6116943359375 +52626 -0.3128662109375 +52627 0.039398193359375 +52628 0.422821044921875 +52629 0.805145263671875 +52630 0.870361328125 +52631 0.870361328125 +52632 0.860015869140625 +52633 0.727935791015625 +52634 0.48114013671875 +52635 0.2059326171875 +52636 -0.06103515625 +52637 -0.29913330078125 +52638 -0.516204833984375 +52639 -0.7252197265625 +52640 -0.85980224609375 +52641 -0.870391845703125 +52642 -0.870391845703125 +52643 -0.858062744140625 +52644 -0.673004150390625 +52645 -0.42694091796875 +52646 -0.2100830078125 +52647 -0.0362548828125 +52648 0.10943603515625 +52649 0.23516845703125 +52650 0.373687744140625 +52651 0.517791748046875 +52652 0.602783203125 +52653 0.635711669921875 +52654 0.655181884765625 +52655 0.65948486328125 +52656 0.651275634765625 +52657 0.61846923828125 +52658 0.53753662109375 +52659 0.404144287109375 +52660 0.22186279296875 +52661 0.003997802734375 +52662 -0.22100830078125 +52663 -0.42449951171875 +52664 -0.579833984375 +52665 -0.641876220703125 +52666 -0.6177978515625 +52667 -0.575531005859375 +52668 -0.526336669921875 +52669 -0.42645263671875 +52670 -0.2581787109375 +52671 -0.068695068359375 +52672 0.09222412109375 +52673 0.232147216796875 +52674 0.3509521484375 +52675 0.410064697265625 +52676 0.372955322265625 +52677 0.2554931640625 +52678 0.10711669921875 +52679 -0.052886962890625 +52680 -0.186279296875 +52681 -0.23291015625 +52682 -0.209442138671875 +52683 -0.174163818359375 +52684 -0.126739501953125 +52685 -0.048126220703125 +52686 0.0426025390625 +52687 0.10748291015625 +52688 0.1409912109375 +52689 0.19708251953125 +52690 0.273651123046875 +52691 0.31768798828125 +52692 0.341094970703125 +52693 0.368011474609375 +52694 0.37249755859375 +52695 0.30072021484375 +52696 0.1517333984375 +52697 -0.01470947265625 +52698 -0.1883544921875 +52699 -0.372711181640625 +52700 -0.51397705078125 +52701 -0.57177734375 +52702 -0.53948974609375 +52703 -0.43511962890625 +52704 -0.2962646484375 +52705 -0.161102294921875 +52706 -0.0435791015625 +52707 0.060394287109375 +52708 0.13665771484375 +52709 0.170135498046875 +52710 0.16552734375 +52711 0.15728759765625 +52712 0.150787353515625 +52713 0.12200927734375 +52714 0.080108642578125 +52715 0.05126953125 +52716 0.062896728515625 +52717 0.09271240234375 +52718 0.092987060546875 +52719 0.07855224609375 +52720 0.06427001953125 +52721 0.0347900390625 +52722 -0.01171875 +52723 -0.056060791015625 +52724 -0.055511474609375 +52725 -0.010467529296875 +52726 0.02508544921875 +52727 0.025665283203125 +52728 0.017333984375 +52729 0.00189208984375 +52730 -0.03173828125 +52731 -0.071502685546875 +52732 -0.13543701171875 +52733 -0.219970703125 +52734 -0.300506591796875 +52735 -0.376312255859375 +52736 -0.416107177734375 +52737 -0.371124267578125 +52738 -0.242279052734375 +52739 -0.069732666015625 +52740 0.125640869140625 +52741 0.31268310546875 +52742 0.45501708984375 +52743 0.554779052734375 +52744 0.61065673828125 +52745 0.610931396484375 +52746 0.531463623046875 +52747 0.3883056640625 +52748 0.23468017578125 +52749 0.095245361328125 +52750 -0.00396728515625 +52751 -0.04852294921875 +52752 -0.055145263671875 +52753 -0.0758056640625 +52754 -0.138702392578125 +52755 -0.209197998046875 +52756 -0.289031982421875 +52757 -0.37884521484375 +52758 -0.456329345703125 +52759 -0.51641845703125 +52760 -0.519287109375 +52761 -0.458251953125 +52762 -0.384796142578125 +52763 -0.323699951171875 +52764 -0.269287109375 +52765 -0.1951904296875 +52766 -0.100006103515625 +52767 -0.01055908203125 +52768 0.1033935546875 +52769 0.24908447265625 +52770 0.373199462890625 +52771 0.45806884765625 +52772 0.511474609375 +52773 0.565399169921875 +52774 0.61138916015625 +52775 0.5897216796875 +52776 0.4906005859375 +52777 0.33148193359375 +52778 0.147796630859375 +52779 -0.01873779296875 +52780 -0.140289306640625 +52781 -0.191986083984375 +52782 -0.184295654296875 +52783 -0.161834716796875 +52784 -0.166595458984375 +52785 -0.19390869140625 +52786 -0.22442626953125 +52787 -0.279754638671875 +52788 -0.3389892578125 +52789 -0.3543701171875 +52790 -0.348175048828125 +52791 -0.32598876953125 +52792 -0.2581787109375 +52793 -0.139801025390625 +52794 0.014617919921875 +52795 0.144378662109375 +52796 0.221038818359375 +52797 0.27069091796875 +52798 0.294036865234375 +52799 0.311767578125 +52800 0.339141845703125 +52801 0.360260009765625 +52802 0.360504150390625 +52803 0.308380126953125 +52804 0.18170166015625 +52805 0.0047607421875 +52806 -0.17559814453125 +52807 -0.3143310546875 +52808 -0.36785888671875 +52809 -0.36248779296875 +52810 -0.343536376953125 +52811 -0.3018798828125 +52812 -0.231414794921875 +52813 -0.117645263671875 +52814 0.007049560546875 +52815 0.087982177734375 +52816 0.13946533203125 +52817 0.17425537109375 +52818 0.188201904296875 +52819 0.171234130859375 +52820 0.118438720703125 +52821 0.05706787109375 +52822 -0.010711669921875 +52823 -0.0914306640625 +52824 -0.162322998046875 +52825 -0.194549560546875 +52826 -0.1492919921875 +52827 -0.02166748046875 +52828 0.124053955078125 +52829 0.211151123046875 +52830 0.240447998046875 +52831 0.242218017578125 +52832 0.2257080078125 +52833 0.194366455078125 +52834 0.115509033203125 +52835 0.0128173828125 +52836 -0.053802490234375 +52837 -0.110626220703125 +52838 -0.199493408203125 +52839 -0.29437255859375 +52840 -0.33221435546875 +52841 -0.27972412109375 +52842 -0.185333251953125 +52843 -0.128204345703125 +52844 -0.115692138671875 +52845 -0.116455078125 +52846 -0.105926513671875 +52847 -0.053955078125 +52848 0.048797607421875 +52849 0.157318115234375 +52850 0.212005615234375 +52851 0.218475341796875 +52852 0.23724365234375 +52853 0.30535888671875 +52854 0.38128662109375 +52855 0.404449462890625 +52856 0.3944091796875 +52857 0.3885498046875 +52858 0.362640380859375 +52859 0.27362060546875 +52860 0.11712646484375 +52861 -0.054901123046875 +52862 -0.19085693359375 +52863 -0.28570556640625 +52864 -0.339263916015625 +52865 -0.3775634765625 +52866 -0.445709228515625 +52867 -0.535064697265625 +52868 -0.629058837890625 +52869 -0.697601318359375 +52870 -0.70391845703125 +52871 -0.6424560546875 +52872 -0.491241455078125 +52873 -0.265716552734375 +52874 -0.023712158203125 +52875 0.201751708984375 +52876 0.375823974609375 +52877 0.485076904296875 +52878 0.56884765625 +52879 0.634765625 +52880 0.63763427734375 +52881 0.5660400390625 +52882 0.4720458984375 +52883 0.40692138671875 +52884 0.3778076171875 +52885 0.376953125 +52886 0.371978759765625 +52887 0.313140869140625 +52888 0.184417724609375 +52889 0.011199951171875 +52890 -0.171051025390625 +52891 -0.33740234375 +52892 -0.47198486328125 +52893 -0.560394287109375 +52894 -0.58056640625 +52895 -0.54754638671875 +52896 -0.508575439453125 +52897 -0.459503173828125 +52898 -0.394378662109375 +52899 -0.35260009765625 +52900 -0.31170654296875 +52901 -0.197418212890625 +52902 -0.007965087890625 +52903 0.207489013671875 +52904 0.409210205078125 +52905 0.57208251953125 +52906 0.66595458984375 +52907 0.65875244140625 +52908 0.56744384765625 +52909 0.431396484375 +52910 0.29443359375 +52911 0.182464599609375 +52912 0.06365966796875 +52913 -0.075958251953125 +52914 -0.189422607421875 +52915 -0.271942138671875 +52916 -0.342529296875 +52917 -0.364166259765625 +52918 -0.327239990234375 +52919 -0.2769775390625 +52920 -0.253692626953125 +52921 -0.24365234375 +52922 -0.1983642578125 +52923 -0.116241455078125 +52924 -0.036834716796875 +52925 0.034881591796875 +52926 0.09124755859375 +52927 0.10888671875 +52928 0.125518798828125 +52929 0.15771484375 +52930 0.17828369140625 +52931 0.17108154296875 +52932 0.129974365234375 +52933 0.082427978515625 +52934 0.027679443359375 +52935 -0.065643310546875 +52936 -0.15936279296875 +52937 -0.21307373046875 +52938 -0.234649658203125 +52939 -0.2001953125 +52940 -0.119171142578125 +52941 -0.024749755859375 +52942 0.085784912109375 +52943 0.178131103515625 +52944 0.215576171875 +52945 0.211456298828125 +52946 0.17523193359375 +52947 0.128753662109375 +52948 0.1019287109375 +52949 0.0743408203125 +52950 0.04327392578125 +52951 0.038177490234375 +52952 0.076263427734375 +52953 0.14105224609375 +52954 0.186431884765625 +52955 0.188812255859375 +52956 0.1390380859375 +52957 0.041778564453125 +52958 -0.079437255859375 +52959 -0.219390869140625 +52960 -0.367828369140625 +52961 -0.494873046875 +52962 -0.556243896484375 +52963 -0.508697509765625 +52964 -0.3756103515625 +52965 -0.218902587890625 +52966 -0.063751220703125 +52967 0.091552734375 +52968 0.23602294921875 +52969 0.342987060546875 +52970 0.39520263671875 +52971 0.389373779296875 +52972 0.324249267578125 +52973 0.224090576171875 +52974 0.124267578125 +52975 0.037078857421875 +52976 -0.010101318359375 +52977 -0.019439697265625 +52978 -0.022796630859375 +52979 -0.001556396484375 +52980 0.056304931640625 +52981 0.106719970703125 +52982 0.096893310546875 +52983 0.042694091796875 +52984 -0.018035888671875 +52985 -0.07586669921875 +52986 -0.11944580078125 +52987 -0.15972900390625 +52988 -0.202606201171875 +52989 -0.24859619140625 +52990 -0.30517578125 +52991 -0.36212158203125 +52992 -0.39141845703125 +52993 -0.35528564453125 +52994 -0.249969482421875 +52995 -0.092864990234375 +52996 0.08905029296875 +52997 0.2352294921875 +52998 0.318817138671875 +52999 0.358642578125 +53000 0.347747802734375 +53001 0.28564453125 +53002 0.223175048828125 +53003 0.196746826171875 +53004 0.179840087890625 +53005 0.155548095703125 +53006 0.151214599609375 +53007 0.156951904296875 +53008 0.13177490234375 +53009 0.100799560546875 +53010 0.087127685546875 +53011 0.05487060546875 +53012 -0.009002685546875 +53013 -0.10400390625 +53014 -0.229400634765625 +53015 -0.35552978515625 +53016 -0.441925048828125 +53017 -0.473846435546875 +53018 -0.464813232421875 +53019 -0.419097900390625 +53020 -0.334320068359375 +53021 -0.227935791015625 +53022 -0.12347412109375 +53023 -0.02764892578125 +53024 0.077667236328125 +53025 0.2132568359375 +53026 0.38885498046875 +53027 0.582794189453125 +53028 0.734039306640625 +53029 0.800140380859375 +53030 0.7783203125 +53031 0.6651611328125 +53032 0.45965576171875 +53033 0.199188232421875 +53034 -0.050689697265625 +53035 -0.23297119140625 +53036 -0.33013916015625 +53037 -0.368408203125 +53038 -0.378936767578125 +53039 -0.376983642578125 +53040 -0.37969970703125 +53041 -0.391510009765625 +53042 -0.385345458984375 +53043 -0.3419189453125 +53044 -0.28289794921875 +53045 -0.251617431640625 +53046 -0.266143798828125 +53047 -0.273345947265625 +53048 -0.216796875 +53049 -0.128265380859375 +53050 -0.068145751953125 +53051 -0.0430908203125 +53052 -0.024444580078125 +53053 0.020721435546875 +53054 0.124481201171875 +53055 0.25787353515625 +53056 0.379119873046875 +53057 0.47991943359375 +53058 0.5281982421875 +53059 0.511138916015625 +53060 0.456207275390625 +53061 0.407470703125 +53062 0.383758544921875 +53063 0.35687255859375 +53064 0.31182861328125 +53065 0.250885009765625 +53066 0.1654052734375 +53067 0.035247802734375 +53068 -0.142059326171875 +53069 -0.33563232421875 +53070 -0.5345458984375 +53071 -0.72186279296875 +53072 -0.836669921875 +53073 -0.8326416015625 +53074 -0.7296142578125 +53075 -0.582550048828125 +53076 -0.440093994140625 +53077 -0.324310302734375 +53078 -0.20147705078125 +53079 -0.044647216796875 +53080 0.103973388671875 +53081 0.202392578125 +53082 0.264495849609375 +53083 0.338897705078125 +53084 0.443817138671875 +53085 0.545074462890625 +53086 0.6173095703125 +53087 0.6524658203125 +53088 0.66339111328125 +53089 0.6561279296875 +53090 0.606781005859375 +53091 0.501190185546875 +53092 0.352783203125 +53093 0.176544189453125 +53094 -0.034820556640625 +53095 -0.258209228515625 +53096 -0.44244384765625 +53097 -0.5753173828125 +53098 -0.65203857421875 +53099 -0.641632080078125 +53100 -0.562164306640625 +53101 -0.458038330078125 +53102 -0.350555419921875 +53103 -0.260528564453125 +53104 -0.192108154296875 +53105 -0.141937255859375 +53106 -0.1021728515625 +53107 -0.062896728515625 +53108 -0.011932373046875 +53109 0.062835693359375 +53110 0.148712158203125 +53111 0.241729736328125 +53112 0.34912109375 +53113 0.457305908203125 +53114 0.54388427734375 +53115 0.5728759765625 +53116 0.506591796875 +53117 0.351226806640625 +53118 0.146514892578125 +53119 -0.05523681640625 +53120 -0.21624755859375 +53121 -0.334930419921875 +53122 -0.402984619140625 +53123 -0.4412841796875 +53124 -0.49578857421875 +53125 -0.5601806640625 +53126 -0.600738525390625 +53127 -0.584228515625 +53128 -0.47930908203125 +53129 -0.27935791015625 +53130 -0.0089111328125 +53131 0.268798828125 +53132 0.482818603515625 +53133 0.60369873046875 +53134 0.650421142578125 +53135 0.66400146484375 +53136 0.6414794921875 +53137 0.572540283203125 +53138 0.498138427734375 +53139 0.439453125 +53140 0.375518798828125 +53141 0.274505615234375 +53142 0.1087646484375 +53143 -0.099395751953125 +53144 -0.3182373046875 +53145 -0.5489501953125 +53146 -0.7738037109375 +53147 -0.86383056640625 +53148 -0.870391845703125 +53149 -0.86895751953125 +53150 -0.861053466796875 +53151 -0.765869140625 +53152 -0.5301513671875 +53153 -0.214691162109375 +53154 0.137359619140625 +53155 0.474822998046875 +53156 0.76239013671875 +53157 0.867462158203125 +53158 0.870361328125 +53159 0.86480712890625 +53160 0.831817626953125 +53161 0.677581787109375 +53162 0.495880126953125 +53163 0.30767822265625 +53164 0.116180419921875 +53165 -0.110748291015625 +53166 -0.381805419921875 +53167 -0.6572265625 +53168 -0.857421875 +53169 -0.870391845703125 +53170 -0.870391845703125 +53171 -0.86444091796875 +53172 -0.85723876953125 +53173 -0.790008544921875 +53174 -0.62847900390625 +53175 -0.3956298828125 +53176 -0.126708984375 +53177 0.150115966796875 +53178 0.424041748046875 +53179 0.670623779296875 +53180 0.854522705078125 +53181 0.866485595703125 +53182 0.86920166015625 +53183 0.8653564453125 +53184 0.857147216796875 +53185 0.766845703125 +53186 0.628509521484375 +53187 0.462127685546875 +53188 0.297210693359375 +53189 0.14862060546875 +53190 -0.00537109375 +53191 -0.15753173828125 +53192 -0.31304931640625 +53193 -0.48876953125 +53194 -0.6416015625 +53195 -0.751373291015625 +53196 -0.84619140625 +53197 -0.861297607421875 +53198 -0.863250732421875 +53199 -0.856597900390625 +53200 -0.7498779296875 +53201 -0.624542236328125 +53202 -0.47808837890625 +53203 -0.253387451171875 +53204 0.003692626953125 +53205 0.2257080078125 +53206 0.427154541015625 +53207 0.643218994140625 +53208 0.855926513671875 +53209 0.870361328125 +53210 0.870361328125 +53211 0.862762451171875 +53212 0.79669189453125 +53213 0.595794677734375 +53214 0.362152099609375 +53215 0.1270751953125 +53216 -0.086944580078125 +53217 -0.2784423828125 +53218 -0.484832763671875 +53219 -0.729583740234375 +53220 -0.86688232421875 +53221 -0.870391845703125 +53222 -0.86859130859375 +53223 -0.86279296875 +53224 -0.817962646484375 +53225 -0.6116943359375 +53226 -0.3128662109375 +53227 0.039398193359375 +53228 0.422821044921875 +53229 0.805145263671875 +53230 0.870361328125 +53231 0.870361328125 +53232 0.860015869140625 +53233 0.727935791015625 +53234 0.48114013671875 +53235 0.2059326171875 +53236 -0.06103515625 +53237 -0.29913330078125 +53238 -0.516204833984375 +53239 -0.7252197265625 +53240 -0.85980224609375 +53241 -0.870391845703125 +53242 -0.870391845703125 +53243 -0.858062744140625 +53244 -0.673004150390625 +53245 -0.42694091796875 +53246 -0.2100830078125 +53247 -0.0362548828125 +53248 0.10943603515625 +53249 0.23516845703125 +53250 0.373687744140625 +53251 0.517791748046875 +53252 0.602783203125 +53253 0.635711669921875 +53254 0.655181884765625 +53255 0.65948486328125 +53256 0.651275634765625 +53257 0.61846923828125 +53258 0.53753662109375 +53259 0.404144287109375 +53260 0.22186279296875 +53261 0.003997802734375 +53262 -0.22100830078125 +53263 -0.42449951171875 +53264 -0.579833984375 +53265 -0.641876220703125 +53266 -0.6177978515625 +53267 -0.575531005859375 +53268 -0.526336669921875 +53269 -0.42645263671875 +53270 -0.2581787109375 +53271 -0.068695068359375 +53272 0.09222412109375 +53273 0.232147216796875 +53274 0.3509521484375 +53275 0.410064697265625 +53276 0.372955322265625 +53277 0.2554931640625 +53278 0.10711669921875 +53279 -0.052886962890625 +53280 -0.186279296875 +53281 -0.23291015625 +53282 -0.209442138671875 +53283 -0.174163818359375 +53284 -0.126739501953125 +53285 -0.048126220703125 +53286 0.0426025390625 +53287 0.10748291015625 +53288 0.1409912109375 +53289 0.19708251953125 +53290 0.273651123046875 +53291 0.31768798828125 +53292 0.341094970703125 +53293 0.368011474609375 +53294 0.37249755859375 +53295 0.30072021484375 +53296 0.1517333984375 +53297 -0.01470947265625 +53298 -0.1883544921875 +53299 -0.372711181640625 +53300 -0.51397705078125 +53301 -0.57177734375 +53302 -0.53948974609375 +53303 -0.43511962890625 +53304 -0.2962646484375 +53305 -0.161102294921875 +53306 -0.0435791015625 +53307 0.060394287109375 +53308 0.13665771484375 +53309 0.170135498046875 +53310 0.16552734375 +53311 0.15728759765625 +53312 0.150787353515625 +53313 0.12200927734375 +53314 0.080108642578125 +53315 0.05126953125 +53316 0.062896728515625 +53317 0.09271240234375 +53318 0.092987060546875 +53319 0.07855224609375 +53320 0.06427001953125 +53321 0.0347900390625 +53322 -0.01171875 +53323 -0.056060791015625 +53324 -0.055511474609375 +53325 -0.010467529296875 +53326 0.02508544921875 +53327 0.025665283203125 +53328 0.017333984375 +53329 0.00189208984375 +53330 -0.03173828125 +53331 -0.071502685546875 +53332 -0.13543701171875 +53333 -0.219970703125 +53334 -0.300506591796875 +53335 -0.376312255859375 +53336 -0.416107177734375 +53337 -0.371124267578125 +53338 -0.242279052734375 +53339 -0.069732666015625 +53340 0.125640869140625 +53341 0.31268310546875 +53342 0.45501708984375 +53343 0.554779052734375 +53344 0.61065673828125 +53345 0.610931396484375 +53346 0.531463623046875 +53347 0.3883056640625 +53348 0.23468017578125 +53349 0.095245361328125 +53350 -0.00396728515625 +53351 -0.04852294921875 +53352 -0.055145263671875 +53353 -0.0758056640625 +53354 -0.138702392578125 +53355 -0.209197998046875 +53356 -0.289031982421875 +53357 -0.37884521484375 +53358 -0.456329345703125 +53359 -0.51641845703125 +53360 -0.519287109375 +53361 -0.458251953125 +53362 -0.384796142578125 +53363 -0.323699951171875 +53364 -0.269287109375 +53365 -0.1951904296875 +53366 -0.100006103515625 +53367 -0.01055908203125 +53368 0.1033935546875 +53369 0.24908447265625 +53370 0.373199462890625 +53371 0.45806884765625 +53372 0.511474609375 +53373 0.565399169921875 +53374 0.61138916015625 +53375 0.5897216796875 +53376 0.4906005859375 +53377 0.33148193359375 +53378 0.147796630859375 +53379 -0.01873779296875 +53380 -0.140289306640625 +53381 -0.191986083984375 +53382 -0.184295654296875 +53383 -0.161834716796875 +53384 -0.166595458984375 +53385 -0.19390869140625 +53386 -0.22442626953125 +53387 -0.279754638671875 +53388 -0.3389892578125 +53389 -0.3543701171875 +53390 -0.348175048828125 +53391 -0.32598876953125 +53392 -0.2581787109375 +53393 -0.139801025390625 +53394 0.014617919921875 +53395 0.144378662109375 +53396 0.221038818359375 +53397 0.27069091796875 +53398 0.294036865234375 +53399 0.311767578125 +53400 0.339141845703125 +53401 0.360260009765625 +53402 0.360504150390625 +53403 0.308380126953125 +53404 0.18170166015625 +53405 0.0047607421875 +53406 -0.17559814453125 +53407 -0.3143310546875 +53408 -0.36785888671875 +53409 -0.36248779296875 +53410 -0.343536376953125 +53411 -0.3018798828125 +53412 -0.231414794921875 +53413 -0.117645263671875 +53414 0.007049560546875 +53415 0.087982177734375 +53416 0.13946533203125 +53417 0.17425537109375 +53418 0.188201904296875 +53419 0.171234130859375 +53420 0.118438720703125 +53421 0.05706787109375 +53422 -0.010711669921875 +53423 -0.0914306640625 +53424 -0.162322998046875 +53425 -0.194549560546875 +53426 -0.1492919921875 +53427 -0.02166748046875 +53428 0.124053955078125 +53429 0.211151123046875 +53430 0.240447998046875 +53431 0.242218017578125 +53432 0.2257080078125 +53433 0.194366455078125 +53434 0.115509033203125 +53435 0.0128173828125 +53436 -0.053802490234375 +53437 -0.110626220703125 +53438 -0.199493408203125 +53439 -0.29437255859375 +53440 -0.33221435546875 +53441 -0.27972412109375 +53442 -0.185333251953125 +53443 -0.128204345703125 +53444 -0.115692138671875 +53445 -0.116455078125 +53446 -0.105926513671875 +53447 -0.053955078125 +53448 0.048797607421875 +53449 0.157318115234375 +53450 0.212005615234375 +53451 0.218475341796875 +53452 0.23724365234375 +53453 0.30535888671875 +53454 0.38128662109375 +53455 0.404449462890625 +53456 0.3944091796875 +53457 0.3885498046875 +53458 0.362640380859375 +53459 0.27362060546875 +53460 0.11712646484375 +53461 -0.054901123046875 +53462 -0.19085693359375 +53463 -0.28570556640625 +53464 -0.339263916015625 +53465 -0.3775634765625 +53466 -0.445709228515625 +53467 -0.535064697265625 +53468 -0.629058837890625 +53469 -0.697601318359375 +53470 -0.70391845703125 +53471 -0.6424560546875 +53472 -0.491241455078125 +53473 -0.265716552734375 +53474 -0.023712158203125 +53475 0.201751708984375 +53476 0.375823974609375 +53477 0.485076904296875 +53478 0.56884765625 +53479 0.634765625 +53480 0.63763427734375 +53481 0.5660400390625 +53482 0.4720458984375 +53483 0.40692138671875 +53484 0.3778076171875 +53485 0.376953125 +53486 0.371978759765625 +53487 0.313140869140625 +53488 0.184417724609375 +53489 0.011199951171875 +53490 -0.171051025390625 +53491 -0.33740234375 +53492 -0.47198486328125 +53493 -0.560394287109375 +53494 -0.58056640625 +53495 -0.54754638671875 +53496 -0.508575439453125 +53497 -0.459503173828125 +53498 -0.394378662109375 +53499 -0.35260009765625 +53500 -0.31170654296875 +53501 -0.197418212890625 +53502 -0.007965087890625 +53503 0.207489013671875 +53504 0.409210205078125 +53505 0.57208251953125 +53506 0.66595458984375 +53507 0.65875244140625 +53508 0.56744384765625 +53509 0.431396484375 +53510 0.29443359375 +53511 0.182464599609375 +53512 0.06365966796875 +53513 -0.075958251953125 +53514 -0.189422607421875 +53515 -0.271942138671875 +53516 -0.342529296875 +53517 -0.364166259765625 +53518 -0.327239990234375 +53519 -0.2769775390625 +53520 -0.253692626953125 +53521 -0.24365234375 +53522 -0.1983642578125 +53523 -0.116241455078125 +53524 -0.036834716796875 +53525 0.034881591796875 +53526 0.09124755859375 +53527 0.10888671875 +53528 0.125518798828125 +53529 0.15771484375 +53530 0.17828369140625 +53531 0.17108154296875 +53532 0.129974365234375 +53533 0.082427978515625 +53534 0.027679443359375 +53535 -0.065643310546875 +53536 -0.15936279296875 +53537 -0.21307373046875 +53538 -0.234649658203125 +53539 -0.2001953125 +53540 -0.119171142578125 +53541 -0.024749755859375 +53542 0.085784912109375 +53543 0.178131103515625 +53544 0.215576171875 +53545 0.211456298828125 +53546 0.17523193359375 +53547 0.128753662109375 +53548 0.1019287109375 +53549 0.0743408203125 +53550 0.04327392578125 +53551 0.038177490234375 +53552 0.076263427734375 +53553 0.14105224609375 +53554 0.186431884765625 +53555 0.188812255859375 +53556 0.1390380859375 +53557 0.041778564453125 +53558 -0.079437255859375 +53559 -0.219390869140625 +53560 -0.367828369140625 +53561 -0.494873046875 +53562 -0.556243896484375 +53563 -0.508697509765625 +53564 -0.3756103515625 +53565 -0.218902587890625 +53566 -0.063751220703125 +53567 0.091552734375 +53568 0.23602294921875 +53569 0.342987060546875 +53570 0.39520263671875 +53571 0.389373779296875 +53572 0.324249267578125 +53573 0.224090576171875 +53574 0.124267578125 +53575 0.037078857421875 +53576 -0.010101318359375 +53577 -0.019439697265625 +53578 -0.022796630859375 +53579 -0.001556396484375 +53580 0.056304931640625 +53581 0.106719970703125 +53582 0.096893310546875 +53583 0.042694091796875 +53584 -0.018035888671875 +53585 -0.07586669921875 +53586 -0.11944580078125 +53587 -0.15972900390625 +53588 -0.202606201171875 +53589 -0.24859619140625 +53590 -0.30517578125 +53591 -0.36212158203125 +53592 -0.39141845703125 +53593 -0.35528564453125 +53594 -0.249969482421875 +53595 -0.092864990234375 +53596 0.08905029296875 +53597 0.2352294921875 +53598 0.318817138671875 +53599 0.358642578125 +53600 0.347747802734375 +53601 0.28564453125 +53602 0.223175048828125 +53603 0.196746826171875 +53604 0.179840087890625 +53605 0.155548095703125 +53606 0.151214599609375 +53607 0.156951904296875 +53608 0.13177490234375 +53609 0.100799560546875 +53610 0.087127685546875 +53611 0.05487060546875 +53612 -0.009002685546875 +53613 -0.10400390625 +53614 -0.229400634765625 +53615 -0.35552978515625 +53616 -0.441925048828125 +53617 -0.473846435546875 +53618 -0.464813232421875 +53619 -0.419097900390625 +53620 -0.334320068359375 +53621 -0.227935791015625 +53622 -0.12347412109375 +53623 -0.02764892578125 +53624 0.077667236328125 +53625 0.2132568359375 +53626 0.38885498046875 +53627 0.582794189453125 +53628 0.734039306640625 +53629 0.800140380859375 +53630 0.7783203125 +53631 0.6651611328125 +53632 0.45965576171875 +53633 0.199188232421875 +53634 -0.050689697265625 +53635 -0.23297119140625 +53636 -0.33013916015625 +53637 -0.368408203125 +53638 -0.378936767578125 +53639 -0.376983642578125 +53640 -0.37969970703125 +53641 -0.391510009765625 +53642 -0.385345458984375 +53643 -0.3419189453125 +53644 -0.28289794921875 +53645 -0.251617431640625 +53646 -0.266143798828125 +53647 -0.273345947265625 +53648 -0.216796875 +53649 -0.128265380859375 +53650 -0.068145751953125 +53651 -0.0430908203125 +53652 -0.024444580078125 +53653 0.020721435546875 +53654 0.124481201171875 +53655 0.25787353515625 +53656 0.379119873046875 +53657 0.47991943359375 +53658 0.5281982421875 +53659 0.511138916015625 +53660 0.456207275390625 +53661 0.407470703125 +53662 0.383758544921875 +53663 0.35687255859375 +53664 0.31182861328125 +53665 0.250885009765625 +53666 0.1654052734375 +53667 0.035247802734375 +53668 -0.142059326171875 +53669 -0.33563232421875 +53670 -0.5345458984375 +53671 -0.72186279296875 +53672 -0.836669921875 +53673 -0.8326416015625 +53674 -0.7296142578125 +53675 -0.582550048828125 +53676 -0.440093994140625 +53677 -0.324310302734375 +53678 -0.20147705078125 +53679 -0.044647216796875 +53680 0.103973388671875 +53681 0.202392578125 +53682 0.264495849609375 +53683 0.338897705078125 +53684 0.443817138671875 +53685 0.545074462890625 +53686 0.6173095703125 +53687 0.6524658203125 +53688 0.66339111328125 +53689 0.6561279296875 +53690 0.606781005859375 +53691 0.501190185546875 +53692 0.352783203125 +53693 0.176544189453125 +53694 -0.034820556640625 +53695 -0.258209228515625 +53696 -0.44244384765625 +53697 -0.5753173828125 +53698 -0.65203857421875 +53699 -0.641632080078125 +53700 -0.562164306640625 +53701 -0.458038330078125 +53702 -0.350555419921875 +53703 -0.260528564453125 +53704 -0.192108154296875 +53705 -0.141937255859375 +53706 -0.1021728515625 +53707 -0.062896728515625 +53708 -0.011932373046875 +53709 0.062835693359375 +53710 0.148712158203125 +53711 0.241729736328125 +53712 0.34912109375 +53713 0.457305908203125 +53714 0.54388427734375 +53715 0.5728759765625 +53716 0.506591796875 +53717 0.351226806640625 +53718 0.146514892578125 +53719 -0.05523681640625 +53720 -0.21624755859375 +53721 -0.334930419921875 +53722 -0.402984619140625 +53723 -0.4412841796875 +53724 -0.49578857421875 +53725 -0.5601806640625 +53726 -0.600738525390625 +53727 -0.584228515625 +53728 -0.47930908203125 +53729 -0.27935791015625 +53730 -0.0089111328125 +53731 0.268798828125 +53732 0.482818603515625 +53733 0.60369873046875 +53734 0.650421142578125 +53735 0.66400146484375 +53736 0.6414794921875 +53737 0.572540283203125 +53738 0.498138427734375 +53739 0.439453125 +53740 0.375518798828125 +53741 0.274505615234375 +53742 0.1087646484375 +53743 -0.099395751953125 +53744 -0.3182373046875 +53745 -0.5489501953125 +53746 -0.7738037109375 +53747 -0.86383056640625 +53748 -0.870391845703125 +53749 -0.86895751953125 +53750 -0.861053466796875 +53751 -0.765869140625 +53752 -0.5301513671875 +53753 -0.214691162109375 +53754 0.137359619140625 +53755 0.474822998046875 +53756 0.76239013671875 +53757 0.867462158203125 +53758 0.870361328125 +53759 0.86480712890625 +53760 0.831817626953125 +53761 0.677581787109375 +53762 0.495880126953125 +53763 0.30767822265625 +53764 0.116180419921875 +53765 -0.110748291015625 +53766 -0.381805419921875 +53767 -0.6572265625 +53768 -0.857421875 +53769 -0.870391845703125 +53770 -0.870391845703125 +53771 -0.86444091796875 +53772 -0.85723876953125 +53773 -0.790008544921875 +53774 -0.62847900390625 +53775 -0.3956298828125 +53776 -0.126708984375 +53777 0.150115966796875 +53778 0.424041748046875 +53779 0.670623779296875 +53780 0.854522705078125 +53781 0.866485595703125 +53782 0.86920166015625 +53783 0.8653564453125 +53784 0.857147216796875 +53785 0.766845703125 +53786 0.628509521484375 +53787 0.462127685546875 +53788 0.297210693359375 +53789 0.14862060546875 +53790 -0.00537109375 +53791 -0.15753173828125 +53792 -0.31304931640625 +53793 -0.48876953125 +53794 -0.6416015625 +53795 -0.751373291015625 +53796 -0.84619140625 +53797 -0.861297607421875 +53798 -0.863250732421875 +53799 -0.856597900390625 +53800 -0.7498779296875 +53801 -0.624542236328125 +53802 -0.47808837890625 +53803 -0.253387451171875 +53804 0.003692626953125 +53805 0.2257080078125 +53806 0.427154541015625 +53807 0.643218994140625 +53808 0.855926513671875 +53809 0.870361328125 +53810 0.870361328125 +53811 0.862762451171875 +53812 0.79669189453125 +53813 0.595794677734375 +53814 0.362152099609375 +53815 0.1270751953125 +53816 -0.086944580078125 +53817 -0.2784423828125 +53818 -0.484832763671875 +53819 -0.729583740234375 +53820 -0.86688232421875 +53821 -0.870391845703125 +53822 -0.86859130859375 +53823 -0.86279296875 +53824 -0.817962646484375 +53825 -0.6116943359375 +53826 -0.3128662109375 +53827 0.039398193359375 +53828 0.422821044921875 +53829 0.805145263671875 +53830 0.870361328125 +53831 0.870361328125 +53832 0.860015869140625 +53833 0.727935791015625 +53834 0.48114013671875 +53835 0.2059326171875 +53836 -0.06103515625 +53837 -0.29913330078125 +53838 -0.516204833984375 +53839 -0.7252197265625 +53840 -0.85980224609375 +53841 -0.870391845703125 +53842 -0.870391845703125 +53843 -0.858062744140625 +53844 -0.673004150390625 +53845 -0.42694091796875 +53846 -0.2100830078125 +53847 -0.0362548828125 +53848 0.10943603515625 +53849 0.23516845703125 +53850 0.373687744140625 +53851 0.517791748046875 +53852 0.602783203125 +53853 0.635711669921875 +53854 0.655181884765625 +53855 0.65948486328125 +53856 0.651275634765625 +53857 0.61846923828125 +53858 0.53753662109375 +53859 0.404144287109375 +53860 0.22186279296875 +53861 0.003997802734375 +53862 -0.22100830078125 +53863 -0.42449951171875 +53864 -0.579833984375 +53865 -0.641876220703125 +53866 -0.6177978515625 +53867 -0.575531005859375 +53868 -0.526336669921875 +53869 -0.42645263671875 +53870 -0.2581787109375 +53871 -0.068695068359375 +53872 0.09222412109375 +53873 0.232147216796875 +53874 0.3509521484375 +53875 0.410064697265625 +53876 0.372955322265625 +53877 0.2554931640625 +53878 0.10711669921875 +53879 -0.052886962890625 +53880 -0.186279296875 +53881 -0.23291015625 +53882 -0.209442138671875 +53883 -0.174163818359375 +53884 -0.126739501953125 +53885 -0.048126220703125 +53886 0.0426025390625 +53887 0.10748291015625 +53888 0.1409912109375 +53889 0.19708251953125 +53890 0.273651123046875 +53891 0.31768798828125 +53892 0.341094970703125 +53893 0.368011474609375 +53894 0.37249755859375 +53895 0.30072021484375 +53896 0.1517333984375 +53897 -0.01470947265625 +53898 -0.1883544921875 +53899 -0.372711181640625 +53900 -0.51397705078125 +53901 -0.57177734375 +53902 -0.53948974609375 +53903 -0.43511962890625 +53904 -0.2962646484375 +53905 -0.161102294921875 +53906 -0.0435791015625 +53907 0.060394287109375 +53908 0.13665771484375 +53909 0.170135498046875 +53910 0.16552734375 +53911 0.15728759765625 +53912 0.150787353515625 +53913 0.12200927734375 +53914 0.080108642578125 +53915 0.05126953125 +53916 0.062896728515625 +53917 0.09271240234375 +53918 0.092987060546875 +53919 0.07855224609375 +53920 0.06427001953125 +53921 0.0347900390625 +53922 -0.01171875 +53923 -0.056060791015625 +53924 -0.055511474609375 +53925 -0.010467529296875 +53926 0.02508544921875 +53927 0.025665283203125 +53928 0.017333984375 +53929 0.00189208984375 +53930 -0.03173828125 +53931 -0.071502685546875 +53932 -0.13543701171875 +53933 -0.219970703125 +53934 -0.300506591796875 +53935 -0.376312255859375 +53936 -0.416107177734375 +53937 -0.371124267578125 +53938 -0.242279052734375 +53939 -0.069732666015625 +53940 0.125640869140625 +53941 0.31268310546875 +53942 0.45501708984375 +53943 0.554779052734375 +53944 0.61065673828125 +53945 0.610931396484375 +53946 0.531463623046875 +53947 0.3883056640625 +53948 0.23468017578125 +53949 0.095245361328125 +53950 -0.00396728515625 +53951 -0.04852294921875 +53952 -0.055145263671875 +53953 -0.0758056640625 +53954 -0.138702392578125 +53955 -0.209197998046875 +53956 -0.289031982421875 +53957 -0.37884521484375 +53958 -0.456329345703125 +53959 -0.51641845703125 +53960 -0.519287109375 +53961 -0.458251953125 +53962 -0.384796142578125 +53963 -0.323699951171875 +53964 -0.269287109375 +53965 -0.1951904296875 +53966 -0.100006103515625 +53967 -0.01055908203125 +53968 0.1033935546875 +53969 0.24908447265625 +53970 0.373199462890625 +53971 0.45806884765625 +53972 0.511474609375 +53973 0.565399169921875 +53974 0.61138916015625 +53975 0.5897216796875 +53976 0.4906005859375 +53977 0.33148193359375 +53978 0.147796630859375 +53979 -0.01873779296875 +53980 -0.140289306640625 +53981 -0.191986083984375 +53982 -0.184295654296875 +53983 -0.161834716796875 +53984 -0.166595458984375 +53985 -0.19390869140625 +53986 -0.22442626953125 +53987 -0.279754638671875 +53988 -0.3389892578125 +53989 -0.3543701171875 +53990 -0.348175048828125 +53991 -0.32598876953125 +53992 -0.2581787109375 +53993 -0.139801025390625 +53994 0.014617919921875 +53995 0.144378662109375 +53996 0.221038818359375 +53997 0.27069091796875 +53998 0.294036865234375 +53999 0.311767578125 +54000 0.339141845703125 +54001 0.360260009765625 +54002 0.360504150390625 +54003 0.308380126953125 +54004 0.18170166015625 +54005 0.0047607421875 +54006 -0.17559814453125 +54007 -0.3143310546875 +54008 -0.36785888671875 +54009 -0.36248779296875 +54010 -0.343536376953125 +54011 -0.3018798828125 +54012 -0.231414794921875 +54013 -0.117645263671875 +54014 0.007049560546875 +54015 0.087982177734375 +54016 0.13946533203125 +54017 0.17425537109375 +54018 0.188201904296875 +54019 0.171234130859375 +54020 0.118438720703125 +54021 0.05706787109375 +54022 -0.010711669921875 +54023 -0.0914306640625 +54024 -0.162322998046875 +54025 -0.194549560546875 +54026 -0.1492919921875 +54027 -0.02166748046875 +54028 0.124053955078125 +54029 0.211151123046875 +54030 0.240447998046875 +54031 0.242218017578125 +54032 0.2257080078125 +54033 0.194366455078125 +54034 0.115509033203125 +54035 0.0128173828125 +54036 -0.053802490234375 +54037 -0.110626220703125 +54038 -0.199493408203125 +54039 -0.29437255859375 +54040 -0.33221435546875 +54041 -0.27972412109375 +54042 -0.185333251953125 +54043 -0.128204345703125 +54044 -0.115692138671875 +54045 -0.116455078125 +54046 -0.105926513671875 +54047 -0.053955078125 +54048 0.048797607421875 +54049 0.157318115234375 +54050 0.212005615234375 +54051 0.218475341796875 +54052 0.23724365234375 +54053 0.30535888671875 +54054 0.38128662109375 +54055 0.404449462890625 +54056 0.3944091796875 +54057 0.3885498046875 +54058 0.362640380859375 +54059 0.27362060546875 +54060 0.11712646484375 +54061 -0.054901123046875 +54062 -0.19085693359375 +54063 -0.28570556640625 +54064 -0.339263916015625 +54065 -0.3775634765625 +54066 -0.445709228515625 +54067 -0.535064697265625 +54068 -0.629058837890625 +54069 -0.697601318359375 +54070 -0.70391845703125 +54071 -0.6424560546875 +54072 -0.491241455078125 +54073 -0.265716552734375 +54074 -0.023712158203125 +54075 0.201751708984375 +54076 0.375823974609375 +54077 0.485076904296875 +54078 0.56884765625 +54079 0.634765625 +54080 0.63763427734375 +54081 0.5660400390625 +54082 0.4720458984375 +54083 0.40692138671875 +54084 0.3778076171875 +54085 0.376953125 +54086 0.371978759765625 +54087 0.313140869140625 +54088 0.184417724609375 +54089 0.011199951171875 +54090 -0.171051025390625 +54091 -0.33740234375 +54092 -0.47198486328125 +54093 -0.560394287109375 +54094 -0.58056640625 +54095 -0.54754638671875 +54096 -0.508575439453125 +54097 -0.459503173828125 +54098 -0.394378662109375 +54099 -0.35260009765625 +54100 -0.31170654296875 +54101 -0.197418212890625 +54102 -0.007965087890625 +54103 0.207489013671875 +54104 0.409210205078125 +54105 0.57208251953125 +54106 0.66595458984375 +54107 0.65875244140625 +54108 0.56744384765625 +54109 0.431396484375 +54110 0.29443359375 +54111 0.182464599609375 +54112 0.06365966796875 +54113 -0.075958251953125 +54114 -0.189422607421875 +54115 -0.271942138671875 +54116 -0.342529296875 +54117 -0.364166259765625 +54118 -0.327239990234375 +54119 -0.2769775390625 +54120 -0.253692626953125 +54121 -0.24365234375 +54122 -0.1983642578125 +54123 -0.116241455078125 +54124 -0.036834716796875 +54125 0.034881591796875 +54126 0.09124755859375 +54127 0.10888671875 +54128 0.125518798828125 +54129 0.15771484375 +54130 0.17828369140625 +54131 0.17108154296875 +54132 0.129974365234375 +54133 0.082427978515625 +54134 0.027679443359375 +54135 -0.065643310546875 +54136 -0.15936279296875 +54137 -0.21307373046875 +54138 -0.234649658203125 +54139 -0.2001953125 +54140 -0.119171142578125 +54141 -0.024749755859375 +54142 0.085784912109375 +54143 0.178131103515625 +54144 0.215576171875 +54145 0.211456298828125 +54146 0.17523193359375 +54147 0.128753662109375 +54148 0.1019287109375 +54149 0.0743408203125 +54150 0.04327392578125 +54151 0.038177490234375 +54152 0.076263427734375 +54153 0.14105224609375 +54154 0.186431884765625 +54155 0.188812255859375 +54156 0.1390380859375 +54157 0.041778564453125 +54158 -0.079437255859375 +54159 -0.219390869140625 +54160 -0.367828369140625 +54161 -0.494873046875 +54162 -0.556243896484375 +54163 -0.508697509765625 +54164 -0.3756103515625 +54165 -0.218902587890625 +54166 -0.063751220703125 +54167 0.091552734375 +54168 0.23602294921875 +54169 0.342987060546875 +54170 0.39520263671875 +54171 0.389373779296875 +54172 0.324249267578125 +54173 0.224090576171875 +54174 0.124267578125 +54175 0.037078857421875 +54176 -0.010101318359375 +54177 -0.019439697265625 +54178 -0.022796630859375 +54179 -0.001556396484375 +54180 0.056304931640625 +54181 0.106719970703125 +54182 0.096893310546875 +54183 0.042694091796875 +54184 -0.018035888671875 +54185 -0.07586669921875 +54186 -0.11944580078125 +54187 -0.15972900390625 +54188 -0.202606201171875 +54189 -0.24859619140625 +54190 -0.30517578125 +54191 -0.36212158203125 +54192 -0.39141845703125 +54193 -0.35528564453125 +54194 -0.249969482421875 +54195 -0.092864990234375 +54196 0.08905029296875 +54197 0.2352294921875 +54198 0.318817138671875 +54199 0.358642578125 +54200 0.347747802734375 +54201 0.28564453125 +54202 0.223175048828125 +54203 0.196746826171875 +54204 0.179840087890625 +54205 0.155548095703125 +54206 0.151214599609375 +54207 0.156951904296875 +54208 0.13177490234375 +54209 0.100799560546875 +54210 0.087127685546875 +54211 0.05487060546875 +54212 -0.009002685546875 +54213 -0.10400390625 +54214 -0.229400634765625 +54215 -0.35552978515625 +54216 -0.441925048828125 +54217 -0.473846435546875 +54218 -0.464813232421875 +54219 -0.419097900390625 +54220 -0.334320068359375 +54221 -0.227935791015625 +54222 -0.12347412109375 +54223 -0.02764892578125 +54224 0.077667236328125 +54225 0.2132568359375 +54226 0.38885498046875 +54227 0.582794189453125 +54228 0.734039306640625 +54229 0.800140380859375 +54230 0.7783203125 +54231 0.6651611328125 +54232 0.45965576171875 +54233 0.199188232421875 +54234 -0.050689697265625 +54235 -0.23297119140625 +54236 -0.33013916015625 +54237 -0.368408203125 +54238 -0.378936767578125 +54239 -0.376983642578125 +54240 -0.37969970703125 +54241 -0.391510009765625 +54242 -0.385345458984375 +54243 -0.3419189453125 +54244 -0.28289794921875 +54245 -0.251617431640625 +54246 -0.266143798828125 +54247 -0.273345947265625 +54248 -0.216796875 +54249 -0.128265380859375 +54250 -0.068145751953125 +54251 -0.0430908203125 +54252 -0.024444580078125 +54253 0.020721435546875 +54254 0.124481201171875 +54255 0.25787353515625 +54256 0.379119873046875 +54257 0.47991943359375 +54258 0.5281982421875 +54259 0.511138916015625 +54260 0.456207275390625 +54261 0.407470703125 +54262 0.383758544921875 +54263 0.35687255859375 +54264 0.31182861328125 +54265 0.250885009765625 +54266 0.1654052734375 +54267 0.035247802734375 +54268 -0.142059326171875 +54269 -0.33563232421875 +54270 -0.5345458984375 +54271 -0.72186279296875 +54272 -0.836669921875 +54273 -0.8326416015625 +54274 -0.7296142578125 +54275 -0.582550048828125 +54276 -0.440093994140625 +54277 -0.324310302734375 +54278 -0.20147705078125 +54279 -0.044647216796875 +54280 0.103973388671875 +54281 0.202392578125 +54282 0.264495849609375 +54283 0.338897705078125 +54284 0.443817138671875 +54285 0.545074462890625 +54286 0.6173095703125 +54287 0.6524658203125 +54288 0.66339111328125 +54289 0.6561279296875 +54290 0.606781005859375 +54291 0.501190185546875 +54292 0.352783203125 +54293 0.176544189453125 +54294 -0.034820556640625 +54295 -0.258209228515625 +54296 -0.44244384765625 +54297 -0.5753173828125 +54298 -0.65203857421875 +54299 -0.641632080078125 +54300 -0.562164306640625 +54301 -0.458038330078125 +54302 -0.350555419921875 +54303 -0.260528564453125 +54304 -0.192108154296875 +54305 -0.141937255859375 +54306 -0.1021728515625 +54307 -0.062896728515625 +54308 -0.011932373046875 +54309 0.062835693359375 +54310 0.148712158203125 +54311 0.241729736328125 +54312 0.34912109375 +54313 0.457305908203125 +54314 0.54388427734375 +54315 0.5728759765625 +54316 0.506591796875 +54317 0.351226806640625 +54318 0.146514892578125 +54319 -0.05523681640625 +54320 -0.21624755859375 +54321 -0.334930419921875 +54322 -0.402984619140625 +54323 -0.4412841796875 +54324 -0.49578857421875 +54325 -0.5601806640625 +54326 -0.600738525390625 +54327 -0.584228515625 +54328 -0.47930908203125 +54329 -0.27935791015625 +54330 -0.0089111328125 +54331 0.268798828125 +54332 0.482818603515625 +54333 0.60369873046875 +54334 0.650421142578125 +54335 0.66400146484375 +54336 0.6414794921875 +54337 0.572540283203125 +54338 0.498138427734375 +54339 0.439453125 +54340 0.375518798828125 +54341 0.274505615234375 +54342 0.1087646484375 +54343 -0.099395751953125 +54344 -0.3182373046875 +54345 -0.5489501953125 +54346 -0.7738037109375 +54347 -0.86383056640625 +54348 -0.870391845703125 +54349 -0.86895751953125 +54350 -0.861053466796875 +54351 -0.765869140625 +54352 -0.5301513671875 +54353 -0.214691162109375 +54354 0.137359619140625 +54355 0.474822998046875 +54356 0.76239013671875 +54357 0.867462158203125 +54358 0.870361328125 +54359 0.86480712890625 +54360 0.831817626953125 +54361 0.677581787109375 +54362 0.495880126953125 +54363 0.30767822265625 +54364 0.116180419921875 +54365 -0.110748291015625 +54366 -0.381805419921875 +54367 -0.6572265625 +54368 -0.857421875 +54369 -0.870391845703125 +54370 -0.870391845703125 +54371 -0.86444091796875 +54372 -0.85723876953125 +54373 -0.790008544921875 +54374 -0.62847900390625 +54375 -0.3956298828125 +54376 -0.126708984375 +54377 0.150115966796875 +54378 0.424041748046875 +54379 0.670623779296875 +54380 0.854522705078125 +54381 0.866485595703125 +54382 0.86920166015625 +54383 0.8653564453125 +54384 0.857147216796875 +54385 0.766845703125 +54386 0.628509521484375 +54387 0.462127685546875 +54388 0.297210693359375 +54389 0.14862060546875 +54390 -0.00537109375 +54391 -0.15753173828125 +54392 -0.31304931640625 +54393 -0.48876953125 +54394 -0.6416015625 +54395 -0.751373291015625 +54396 -0.84619140625 +54397 -0.861297607421875 +54398 -0.863250732421875 +54399 -0.856597900390625 +54400 -0.7498779296875 +54401 -0.624542236328125 +54402 -0.47808837890625 +54403 -0.253387451171875 +54404 0.003692626953125 +54405 0.2257080078125 +54406 0.427154541015625 +54407 0.643218994140625 +54408 0.855926513671875 +54409 0.870361328125 +54410 0.870361328125 +54411 0.862762451171875 +54412 0.79669189453125 +54413 0.595794677734375 +54414 0.362152099609375 +54415 0.1270751953125 +54416 -0.086944580078125 +54417 -0.2784423828125 +54418 -0.484832763671875 +54419 -0.729583740234375 +54420 -0.86688232421875 +54421 -0.870391845703125 +54422 -0.86859130859375 +54423 -0.86279296875 +54424 -0.817962646484375 +54425 -0.6116943359375 +54426 -0.3128662109375 +54427 0.039398193359375 +54428 0.422821044921875 +54429 0.805145263671875 +54430 0.870361328125 +54431 0.870361328125 +54432 0.860015869140625 +54433 0.727935791015625 +54434 0.48114013671875 +54435 0.2059326171875 +54436 -0.06103515625 +54437 -0.29913330078125 +54438 -0.516204833984375 +54439 -0.7252197265625 +54440 -0.85980224609375 +54441 -0.870391845703125 +54442 -0.870391845703125 +54443 -0.858062744140625 +54444 -0.673004150390625 +54445 -0.42694091796875 +54446 -0.2100830078125 +54447 -0.0362548828125 +54448 0.10943603515625 +54449 0.23516845703125 +54450 0.373687744140625 +54451 0.517791748046875 +54452 0.602783203125 +54453 0.635711669921875 +54454 0.655181884765625 +54455 0.65948486328125 +54456 0.651275634765625 +54457 0.61846923828125 +54458 0.53753662109375 +54459 0.404144287109375 +54460 0.22186279296875 +54461 0.003997802734375 +54462 -0.22100830078125 +54463 -0.42449951171875 +54464 -0.579833984375 +54465 -0.641876220703125 +54466 -0.6177978515625 +54467 -0.575531005859375 +54468 -0.526336669921875 +54469 -0.42645263671875 +54470 -0.2581787109375 +54471 -0.068695068359375 +54472 0.09222412109375 +54473 0.232147216796875 +54474 0.3509521484375 +54475 0.410064697265625 +54476 0.372955322265625 +54477 0.2554931640625 +54478 0.10711669921875 +54479 -0.052886962890625 +54480 -0.186279296875 +54481 -0.23291015625 +54482 -0.209442138671875 +54483 -0.174163818359375 +54484 -0.126739501953125 +54485 -0.048126220703125 +54486 0.0426025390625 +54487 0.10748291015625 +54488 0.1409912109375 +54489 0.19708251953125 +54490 0.273651123046875 +54491 0.31768798828125 +54492 0.341094970703125 +54493 0.368011474609375 +54494 0.37249755859375 +54495 0.30072021484375 +54496 0.1517333984375 +54497 -0.01470947265625 +54498 -0.1883544921875 +54499 -0.372711181640625 +54500 -0.51397705078125 +54501 -0.57177734375 +54502 -0.53948974609375 +54503 -0.43511962890625 +54504 -0.2962646484375 +54505 -0.161102294921875 +54506 -0.0435791015625 +54507 0.060394287109375 +54508 0.13665771484375 +54509 0.170135498046875 +54510 0.16552734375 +54511 0.15728759765625 +54512 0.150787353515625 +54513 0.12200927734375 +54514 0.080108642578125 +54515 0.05126953125 +54516 0.062896728515625 +54517 0.09271240234375 +54518 0.092987060546875 +54519 0.07855224609375 +54520 0.06427001953125 +54521 0.0347900390625 +54522 -0.01171875 +54523 -0.056060791015625 +54524 -0.055511474609375 +54525 -0.010467529296875 +54526 0.02508544921875 +54527 0.025665283203125 +54528 0.017333984375 +54529 0.00189208984375 +54530 -0.03173828125 +54531 -0.071502685546875 +54532 -0.13543701171875 +54533 -0.219970703125 +54534 -0.300506591796875 +54535 -0.376312255859375 +54536 -0.416107177734375 +54537 -0.371124267578125 +54538 -0.242279052734375 +54539 -0.069732666015625 +54540 0.125640869140625 +54541 0.31268310546875 +54542 0.45501708984375 +54543 0.554779052734375 +54544 0.61065673828125 +54545 0.610931396484375 +54546 0.531463623046875 +54547 0.3883056640625 +54548 0.23468017578125 +54549 0.095245361328125 +54550 -0.00396728515625 +54551 -0.04852294921875 +54552 -0.055145263671875 +54553 -0.0758056640625 +54554 -0.138702392578125 +54555 -0.209197998046875 +54556 -0.289031982421875 +54557 -0.37884521484375 +54558 -0.456329345703125 +54559 -0.51641845703125 +54560 -0.519287109375 +54561 -0.458251953125 +54562 -0.384796142578125 +54563 -0.323699951171875 +54564 -0.269287109375 +54565 -0.1951904296875 +54566 -0.100006103515625 +54567 -0.01055908203125 +54568 0.1033935546875 +54569 0.24908447265625 +54570 0.373199462890625 +54571 0.45806884765625 +54572 0.511474609375 +54573 0.565399169921875 +54574 0.61138916015625 +54575 0.5897216796875 +54576 0.4906005859375 +54577 0.33148193359375 +54578 0.147796630859375 +54579 -0.01873779296875 +54580 -0.140289306640625 +54581 -0.191986083984375 +54582 -0.184295654296875 +54583 -0.161834716796875 +54584 -0.166595458984375 +54585 -0.19390869140625 +54586 -0.22442626953125 +54587 -0.279754638671875 +54588 -0.3389892578125 +54589 -0.3543701171875 +54590 -0.348175048828125 +54591 -0.32598876953125 +54592 -0.2581787109375 +54593 -0.139801025390625 +54594 0.014617919921875 +54595 0.144378662109375 +54596 0.221038818359375 +54597 0.27069091796875 +54598 0.294036865234375 +54599 0.311767578125 +54600 0.339141845703125 +54601 0.360260009765625 +54602 0.360504150390625 +54603 0.308380126953125 +54604 0.18170166015625 +54605 0.0047607421875 +54606 -0.17559814453125 +54607 -0.3143310546875 +54608 -0.36785888671875 +54609 -0.36248779296875 +54610 -0.343536376953125 +54611 -0.3018798828125 +54612 -0.231414794921875 +54613 -0.117645263671875 +54614 0.007049560546875 +54615 0.087982177734375 +54616 0.13946533203125 +54617 0.17425537109375 +54618 0.188201904296875 +54619 0.171234130859375 +54620 0.118438720703125 +54621 0.05706787109375 +54622 -0.010711669921875 +54623 -0.0914306640625 +54624 -0.162322998046875 +54625 -0.194549560546875 +54626 -0.1492919921875 +54627 -0.02166748046875 +54628 0.124053955078125 +54629 0.211151123046875 +54630 0.240447998046875 +54631 0.242218017578125 +54632 0.2257080078125 +54633 0.194366455078125 +54634 0.115509033203125 +54635 0.0128173828125 +54636 -0.053802490234375 +54637 -0.110626220703125 +54638 -0.199493408203125 +54639 -0.29437255859375 +54640 -0.33221435546875 +54641 -0.27972412109375 +54642 -0.185333251953125 +54643 -0.128204345703125 +54644 -0.115692138671875 +54645 -0.116455078125 +54646 -0.105926513671875 +54647 -0.053955078125 +54648 0.048797607421875 +54649 0.157318115234375 +54650 0.212005615234375 +54651 0.218475341796875 +54652 0.23724365234375 +54653 0.30535888671875 +54654 0.38128662109375 +54655 0.404449462890625 +54656 0.3944091796875 +54657 0.3885498046875 +54658 0.362640380859375 +54659 0.27362060546875 +54660 0.11712646484375 +54661 -0.054901123046875 +54662 -0.19085693359375 +54663 -0.28570556640625 +54664 -0.339263916015625 +54665 -0.3775634765625 +54666 -0.445709228515625 +54667 -0.535064697265625 +54668 -0.629058837890625 +54669 -0.697601318359375 +54670 -0.70391845703125 +54671 -0.6424560546875 +54672 -0.491241455078125 +54673 -0.265716552734375 +54674 -0.023712158203125 +54675 0.201751708984375 +54676 0.375823974609375 +54677 0.485076904296875 +54678 0.56884765625 +54679 0.634765625 +54680 0.63763427734375 +54681 0.5660400390625 +54682 0.4720458984375 +54683 0.40692138671875 +54684 0.3778076171875 +54685 0.376953125 +54686 0.371978759765625 +54687 0.313140869140625 +54688 0.184417724609375 +54689 0.011199951171875 +54690 -0.171051025390625 +54691 -0.33740234375 +54692 -0.47198486328125 +54693 -0.560394287109375 +54694 -0.58056640625 +54695 -0.54754638671875 +54696 -0.508575439453125 +54697 -0.459503173828125 +54698 -0.394378662109375 +54699 -0.35260009765625 +54700 -0.31170654296875 +54701 -0.197418212890625 +54702 -0.007965087890625 +54703 0.207489013671875 +54704 0.409210205078125 +54705 0.57208251953125 +54706 0.66595458984375 +54707 0.65875244140625 +54708 0.56744384765625 +54709 0.431396484375 +54710 0.29443359375 +54711 0.182464599609375 +54712 0.06365966796875 +54713 -0.075958251953125 +54714 -0.189422607421875 +54715 -0.271942138671875 +54716 -0.342529296875 +54717 -0.364166259765625 +54718 -0.327239990234375 +54719 -0.2769775390625 +54720 -0.253692626953125 +54721 -0.24365234375 +54722 -0.1983642578125 +54723 -0.116241455078125 +54724 -0.036834716796875 +54725 0.034881591796875 +54726 0.09124755859375 +54727 0.10888671875 +54728 0.125518798828125 +54729 0.15771484375 +54730 0.17828369140625 +54731 0.17108154296875 +54732 0.129974365234375 +54733 0.082427978515625 +54734 0.027679443359375 +54735 -0.065643310546875 +54736 -0.15936279296875 +54737 -0.21307373046875 +54738 -0.234649658203125 +54739 -0.2001953125 +54740 -0.119171142578125 +54741 -0.024749755859375 +54742 0.085784912109375 +54743 0.178131103515625 +54744 0.215576171875 +54745 0.211456298828125 +54746 0.17523193359375 +54747 0.128753662109375 +54748 0.1019287109375 +54749 0.0743408203125 +54750 0.04327392578125 +54751 0.038177490234375 +54752 0.076263427734375 +54753 0.14105224609375 +54754 0.186431884765625 +54755 0.188812255859375 +54756 0.1390380859375 +54757 0.041778564453125 +54758 -0.079437255859375 +54759 -0.219390869140625 +54760 -0.367828369140625 +54761 -0.494873046875 +54762 -0.556243896484375 +54763 -0.508697509765625 +54764 -0.3756103515625 +54765 -0.218902587890625 +54766 -0.063751220703125 +54767 0.091552734375 +54768 0.23602294921875 +54769 0.342987060546875 +54770 0.39520263671875 +54771 0.389373779296875 +54772 0.324249267578125 +54773 0.224090576171875 +54774 0.124267578125 +54775 0.037078857421875 +54776 -0.010101318359375 +54777 -0.019439697265625 +54778 -0.022796630859375 +54779 -0.001556396484375 +54780 0.056304931640625 +54781 0.106719970703125 +54782 0.096893310546875 +54783 0.042694091796875 +54784 -0.018035888671875 +54785 -0.07586669921875 +54786 -0.11944580078125 +54787 -0.15972900390625 +54788 -0.202606201171875 +54789 -0.24859619140625 +54790 -0.30517578125 +54791 -0.36212158203125 +54792 -0.39141845703125 +54793 -0.35528564453125 +54794 -0.249969482421875 +54795 -0.092864990234375 +54796 0.08905029296875 +54797 0.2352294921875 +54798 0.318817138671875 +54799 0.358642578125 +54800 0.347747802734375 +54801 0.28564453125 +54802 0.223175048828125 +54803 0.196746826171875 +54804 0.179840087890625 +54805 0.155548095703125 +54806 0.151214599609375 +54807 0.156951904296875 +54808 0.13177490234375 +54809 0.100799560546875 +54810 0.087127685546875 +54811 0.05487060546875 +54812 -0.009002685546875 +54813 -0.10400390625 +54814 -0.229400634765625 +54815 -0.35552978515625 +54816 -0.441925048828125 +54817 -0.473846435546875 +54818 -0.464813232421875 +54819 -0.419097900390625 +54820 -0.334320068359375 +54821 -0.227935791015625 +54822 -0.12347412109375 +54823 -0.02764892578125 +54824 0.077667236328125 +54825 0.2132568359375 +54826 0.38885498046875 +54827 0.582794189453125 +54828 0.734039306640625 +54829 0.800140380859375 +54830 0.7783203125 +54831 0.6651611328125 +54832 0.45965576171875 +54833 0.199188232421875 +54834 -0.050689697265625 +54835 -0.23297119140625 +54836 -0.33013916015625 +54837 -0.368408203125 +54838 -0.378936767578125 +54839 -0.376983642578125 +54840 -0.37969970703125 +54841 -0.391510009765625 +54842 -0.385345458984375 +54843 -0.3419189453125 +54844 -0.28289794921875 +54845 -0.251617431640625 +54846 -0.266143798828125 +54847 -0.273345947265625 +54848 -0.216796875 +54849 -0.128265380859375 +54850 -0.068145751953125 +54851 -0.0430908203125 +54852 -0.024444580078125 +54853 0.020721435546875 +54854 0.124481201171875 +54855 0.25787353515625 +54856 0.379119873046875 +54857 0.47991943359375 +54858 0.5281982421875 +54859 0.511138916015625 +54860 0.456207275390625 +54861 0.407470703125 +54862 0.383758544921875 +54863 0.35687255859375 +54864 0.31182861328125 +54865 0.250885009765625 +54866 0.1654052734375 +54867 0.035247802734375 +54868 -0.142059326171875 +54869 -0.33563232421875 +54870 -0.5345458984375 +54871 -0.72186279296875 +54872 -0.836669921875 +54873 -0.8326416015625 +54874 -0.7296142578125 +54875 -0.582550048828125 +54876 -0.440093994140625 +54877 -0.324310302734375 +54878 -0.20147705078125 +54879 -0.044647216796875 +54880 0.103973388671875 +54881 0.202392578125 +54882 0.264495849609375 +54883 0.338897705078125 +54884 0.443817138671875 +54885 0.545074462890625 +54886 0.6173095703125 +54887 0.6524658203125 +54888 0.66339111328125 +54889 0.6561279296875 +54890 0.606781005859375 +54891 0.501190185546875 +54892 0.352783203125 +54893 0.176544189453125 +54894 -0.034820556640625 +54895 -0.258209228515625 +54896 -0.44244384765625 +54897 -0.5753173828125 +54898 -0.65203857421875 +54899 -0.641632080078125 +54900 -0.562164306640625 +54901 -0.458038330078125 +54902 -0.350555419921875 +54903 -0.260528564453125 +54904 -0.192108154296875 +54905 -0.141937255859375 +54906 -0.1021728515625 +54907 -0.062896728515625 +54908 -0.011932373046875 +54909 0.062835693359375 +54910 0.148712158203125 +54911 0.241729736328125 +54912 0.34912109375 +54913 0.457305908203125 +54914 0.54388427734375 +54915 0.5728759765625 +54916 0.506591796875 +54917 0.351226806640625 +54918 0.146514892578125 +54919 -0.05523681640625 +54920 -0.21624755859375 +54921 -0.334930419921875 +54922 -0.402984619140625 +54923 -0.4412841796875 +54924 -0.49578857421875 +54925 -0.5601806640625 +54926 -0.600738525390625 +54927 -0.584228515625 +54928 -0.47930908203125 +54929 -0.27935791015625 +54930 -0.0089111328125 +54931 0.268798828125 +54932 0.482818603515625 +54933 0.60369873046875 +54934 0.650421142578125 +54935 0.66400146484375 +54936 0.6414794921875 +54937 0.572540283203125 +54938 0.498138427734375 +54939 0.439453125 +54940 0.375518798828125 +54941 0.274505615234375 +54942 0.1087646484375 +54943 -0.099395751953125 +54944 -0.3182373046875 +54945 -0.5489501953125 +54946 -0.7738037109375 +54947 -0.86383056640625 +54948 -0.870391845703125 +54949 -0.86895751953125 +54950 -0.861053466796875 +54951 -0.765869140625 +54952 -0.5301513671875 +54953 -0.214691162109375 +54954 0.137359619140625 +54955 0.474822998046875 +54956 0.76239013671875 +54957 0.867462158203125 +54958 0.870361328125 +54959 0.86480712890625 +54960 0.831817626953125 +54961 0.677581787109375 +54962 0.495880126953125 +54963 0.30767822265625 +54964 0.116180419921875 +54965 -0.110748291015625 +54966 -0.381805419921875 +54967 -0.6572265625 +54968 -0.857421875 +54969 -0.870391845703125 +54970 -0.870391845703125 +54971 -0.86444091796875 +54972 -0.85723876953125 +54973 -0.790008544921875 +54974 -0.62847900390625 +54975 -0.3956298828125 +54976 -0.126708984375 +54977 0.150115966796875 +54978 0.424041748046875 +54979 0.670623779296875 +54980 0.854522705078125 +54981 0.866485595703125 +54982 0.86920166015625 +54983 0.8653564453125 +54984 0.857147216796875 +54985 0.766845703125 +54986 0.628509521484375 +54987 0.462127685546875 +54988 0.297210693359375 +54989 0.14862060546875 +54990 -0.00537109375 +54991 -0.15753173828125 +54992 -0.31304931640625 +54993 -0.48876953125 +54994 -0.6416015625 +54995 -0.751373291015625 +54996 -0.84619140625 +54997 -0.861297607421875 +54998 -0.863250732421875 +54999 -0.856597900390625 +55000 -0.7498779296875 +55001 -0.624542236328125 +55002 -0.47808837890625 +55003 -0.253387451171875 +55004 0.003692626953125 +55005 0.2257080078125 +55006 0.427154541015625 +55007 0.643218994140625 +55008 0.855926513671875 +55009 0.870361328125 +55010 0.870361328125 +55011 0.862762451171875 +55012 0.79669189453125 +55013 0.595794677734375 +55014 0.362152099609375 +55015 0.1270751953125 +55016 -0.086944580078125 +55017 -0.2784423828125 +55018 -0.484832763671875 +55019 -0.729583740234375 +55020 -0.86688232421875 +55021 -0.870391845703125 +55022 -0.86859130859375 +55023 -0.86279296875 +55024 -0.817962646484375 +55025 -0.6116943359375 +55026 -0.3128662109375 +55027 0.039398193359375 +55028 0.422821044921875 +55029 0.805145263671875 +55030 0.870361328125 +55031 0.870361328125 +55032 0.860015869140625 +55033 0.727935791015625 +55034 0.48114013671875 +55035 0.2059326171875 +55036 -0.06103515625 +55037 -0.29913330078125 +55038 -0.516204833984375 +55039 -0.7252197265625 +55040 -0.85980224609375 +55041 -0.870391845703125 +55042 -0.870391845703125 +55043 -0.858062744140625 +55044 -0.673004150390625 +55045 -0.42694091796875 +55046 -0.2100830078125 +55047 -0.0362548828125 +55048 0.10943603515625 +55049 0.23516845703125 +55050 0.373687744140625 +55051 0.517791748046875 +55052 0.602783203125 +55053 0.635711669921875 +55054 0.655181884765625 +55055 0.65948486328125 +55056 0.651275634765625 +55057 0.61846923828125 +55058 0.53753662109375 +55059 0.404144287109375 +55060 0.22186279296875 +55061 0.003997802734375 +55062 -0.22100830078125 +55063 -0.42449951171875 +55064 -0.579833984375 +55065 -0.641876220703125 +55066 -0.6177978515625 +55067 -0.575531005859375 +55068 -0.526336669921875 +55069 -0.42645263671875 +55070 -0.2581787109375 +55071 -0.068695068359375 +55072 0.09222412109375 +55073 0.232147216796875 +55074 0.3509521484375 +55075 0.410064697265625 +55076 0.372955322265625 +55077 0.2554931640625 +55078 0.10711669921875 +55079 -0.052886962890625 +55080 -0.186279296875 +55081 -0.23291015625 +55082 -0.209442138671875 +55083 -0.174163818359375 +55084 -0.126739501953125 +55085 -0.048126220703125 +55086 0.0426025390625 +55087 0.10748291015625 +55088 0.1409912109375 +55089 0.19708251953125 +55090 0.273651123046875 +55091 0.31768798828125 +55092 0.341094970703125 +55093 0.368011474609375 +55094 0.37249755859375 +55095 0.30072021484375 +55096 0.1517333984375 +55097 -0.01470947265625 +55098 -0.1883544921875 +55099 -0.372711181640625 +55100 -0.51397705078125 +55101 -0.57177734375 +55102 -0.53948974609375 +55103 -0.43511962890625 +55104 -0.2962646484375 +55105 -0.161102294921875 +55106 -0.0435791015625 +55107 0.060394287109375 +55108 0.13665771484375 +55109 0.170135498046875 +55110 0.16552734375 +55111 0.15728759765625 +55112 0.150787353515625 +55113 0.12200927734375 +55114 0.080108642578125 +55115 0.05126953125 +55116 0.062896728515625 +55117 0.09271240234375 +55118 0.092987060546875 +55119 0.07855224609375 +55120 0.06427001953125 +55121 0.0347900390625 +55122 -0.01171875 +55123 -0.056060791015625 +55124 -0.055511474609375 +55125 -0.010467529296875 +55126 0.02508544921875 +55127 0.025665283203125 +55128 0.017333984375 +55129 0.00189208984375 +55130 -0.03173828125 +55131 -0.071502685546875 +55132 -0.13543701171875 +55133 -0.219970703125 +55134 -0.300506591796875 +55135 -0.376312255859375 +55136 -0.416107177734375 +55137 -0.371124267578125 +55138 -0.242279052734375 +55139 -0.069732666015625 +55140 0.125640869140625 +55141 0.31268310546875 +55142 0.45501708984375 +55143 0.554779052734375 +55144 0.61065673828125 +55145 0.610931396484375 +55146 0.531463623046875 +55147 0.3883056640625 +55148 0.23468017578125 +55149 0.095245361328125 +55150 -0.00396728515625 +55151 -0.04852294921875 +55152 -0.055145263671875 +55153 -0.0758056640625 +55154 -0.138702392578125 +55155 -0.209197998046875 +55156 -0.289031982421875 +55157 -0.37884521484375 +55158 -0.456329345703125 +55159 -0.51641845703125 +55160 -0.519287109375 +55161 -0.458251953125 +55162 -0.384796142578125 +55163 -0.323699951171875 +55164 -0.269287109375 +55165 -0.1951904296875 +55166 -0.100006103515625 +55167 -0.01055908203125 +55168 0.1033935546875 +55169 0.24908447265625 +55170 0.373199462890625 +55171 0.45806884765625 +55172 0.511474609375 +55173 0.565399169921875 +55174 0.61138916015625 +55175 0.5897216796875 +55176 0.4906005859375 +55177 0.33148193359375 +55178 0.147796630859375 +55179 -0.01873779296875 +55180 -0.140289306640625 +55181 -0.191986083984375 +55182 -0.184295654296875 +55183 -0.161834716796875 +55184 -0.166595458984375 +55185 -0.19390869140625 +55186 -0.22442626953125 +55187 -0.279754638671875 +55188 -0.3389892578125 +55189 -0.3543701171875 +55190 -0.348175048828125 +55191 -0.32598876953125 +55192 -0.2581787109375 +55193 -0.139801025390625 +55194 0.014617919921875 +55195 0.144378662109375 +55196 0.221038818359375 +55197 0.27069091796875 +55198 0.294036865234375 +55199 0.311767578125 +55200 0.339141845703125 +55201 0.360260009765625 +55202 0.360504150390625 +55203 0.308380126953125 +55204 0.18170166015625 +55205 0.0047607421875 +55206 -0.17559814453125 +55207 -0.3143310546875 +55208 -0.36785888671875 +55209 -0.36248779296875 +55210 -0.343536376953125 +55211 -0.3018798828125 +55212 -0.231414794921875 +55213 -0.117645263671875 +55214 0.007049560546875 +55215 0.087982177734375 +55216 0.13946533203125 +55217 0.17425537109375 +55218 0.188201904296875 +55219 0.171234130859375 +55220 0.118438720703125 +55221 0.05706787109375 +55222 -0.010711669921875 +55223 -0.0914306640625 +55224 -0.162322998046875 +55225 -0.194549560546875 +55226 -0.1492919921875 +55227 -0.02166748046875 +55228 0.124053955078125 +55229 0.211151123046875 +55230 0.240447998046875 +55231 0.242218017578125 +55232 0.2257080078125 +55233 0.194366455078125 +55234 0.115509033203125 +55235 0.0128173828125 +55236 -0.053802490234375 +55237 -0.110626220703125 +55238 -0.199493408203125 +55239 -0.29437255859375 +55240 -0.33221435546875 +55241 -0.27972412109375 +55242 -0.185333251953125 +55243 -0.128204345703125 +55244 -0.115692138671875 +55245 -0.116455078125 +55246 -0.105926513671875 +55247 -0.053955078125 +55248 0.048797607421875 +55249 0.157318115234375 +55250 0.212005615234375 +55251 0.218475341796875 +55252 0.23724365234375 +55253 0.30535888671875 +55254 0.38128662109375 +55255 0.404449462890625 +55256 0.3944091796875 +55257 0.3885498046875 +55258 0.362640380859375 +55259 0.27362060546875 +55260 0.11712646484375 +55261 -0.054901123046875 +55262 -0.19085693359375 +55263 -0.28570556640625 +55264 -0.339263916015625 +55265 -0.3775634765625 +55266 -0.445709228515625 +55267 -0.535064697265625 +55268 -0.629058837890625 +55269 -0.697601318359375 +55270 -0.70391845703125 +55271 -0.6424560546875 +55272 -0.491241455078125 +55273 -0.265716552734375 +55274 -0.023712158203125 +55275 0.201751708984375 +55276 0.375823974609375 +55277 0.485076904296875 +55278 0.56884765625 +55279 0.634765625 +55280 0.63763427734375 +55281 0.5660400390625 +55282 0.4720458984375 +55283 0.40692138671875 +55284 0.3778076171875 +55285 0.376953125 +55286 0.371978759765625 +55287 0.313140869140625 +55288 0.184417724609375 +55289 0.011199951171875 +55290 -0.171051025390625 +55291 -0.33740234375 +55292 -0.47198486328125 +55293 -0.560394287109375 +55294 -0.58056640625 +55295 -0.54754638671875 +55296 -0.508575439453125 +55297 -0.459503173828125 +55298 -0.394378662109375 +55299 -0.35260009765625 +55300 -0.31170654296875 +55301 -0.197418212890625 +55302 -0.007965087890625 +55303 0.207489013671875 +55304 0.409210205078125 +55305 0.57208251953125 +55306 0.66595458984375 +55307 0.65875244140625 +55308 0.56744384765625 +55309 0.431396484375 +55310 0.29443359375 +55311 0.182464599609375 +55312 0.06365966796875 +55313 -0.075958251953125 +55314 -0.189422607421875 +55315 -0.271942138671875 +55316 -0.342529296875 +55317 -0.364166259765625 +55318 -0.327239990234375 +55319 -0.2769775390625 +55320 -0.253692626953125 +55321 -0.24365234375 +55322 -0.1983642578125 +55323 -0.116241455078125 +55324 -0.036834716796875 +55325 0.034881591796875 +55326 0.09124755859375 +55327 0.10888671875 +55328 0.125518798828125 +55329 0.15771484375 +55330 0.17828369140625 +55331 0.17108154296875 +55332 0.129974365234375 +55333 0.082427978515625 +55334 0.027679443359375 +55335 -0.065643310546875 +55336 -0.15936279296875 +55337 -0.21307373046875 +55338 -0.234649658203125 +55339 -0.2001953125 +55340 -0.119171142578125 +55341 -0.024749755859375 +55342 0.085784912109375 +55343 0.178131103515625 +55344 0.215576171875 +55345 0.211456298828125 +55346 0.17523193359375 +55347 0.128753662109375 +55348 0.1019287109375 +55349 0.0743408203125 +55350 0.04327392578125 +55351 0.038177490234375 +55352 0.076263427734375 +55353 0.14105224609375 +55354 0.186431884765625 +55355 0.188812255859375 +55356 0.1390380859375 +55357 0.041778564453125 +55358 -0.079437255859375 +55359 -0.219390869140625 +55360 -0.367828369140625 +55361 -0.494873046875 +55362 -0.556243896484375 +55363 -0.508697509765625 +55364 -0.3756103515625 +55365 -0.218902587890625 +55366 -0.063751220703125 +55367 0.091552734375 +55368 0.23602294921875 +55369 0.342987060546875 +55370 0.39520263671875 +55371 0.389373779296875 +55372 0.324249267578125 +55373 0.224090576171875 +55374 0.124267578125 +55375 0.037078857421875 +55376 -0.010101318359375 +55377 -0.019439697265625 +55378 -0.022796630859375 +55379 -0.001556396484375 +55380 0.056304931640625 +55381 0.106719970703125 +55382 0.096893310546875 +55383 0.042694091796875 +55384 -0.018035888671875 +55385 -0.07586669921875 +55386 -0.11944580078125 +55387 -0.15972900390625 +55388 -0.202606201171875 +55389 -0.24859619140625 +55390 -0.30517578125 +55391 -0.36212158203125 +55392 -0.39141845703125 +55393 -0.35528564453125 +55394 -0.249969482421875 +55395 -0.092864990234375 +55396 0.08905029296875 +55397 0.2352294921875 +55398 0.318817138671875 +55399 0.358642578125 +55400 0.347747802734375 +55401 0.28564453125 +55402 0.223175048828125 +55403 0.196746826171875 +55404 0.179840087890625 +55405 0.155548095703125 +55406 0.151214599609375 +55407 0.156951904296875 +55408 0.13177490234375 +55409 0.100799560546875 +55410 0.087127685546875 +55411 0.05487060546875 +55412 -0.009002685546875 +55413 -0.10400390625 +55414 -0.229400634765625 +55415 -0.35552978515625 +55416 -0.441925048828125 +55417 -0.473846435546875 +55418 -0.464813232421875 +55419 -0.419097900390625 +55420 -0.334320068359375 +55421 -0.227935791015625 +55422 -0.12347412109375 +55423 -0.02764892578125 +55424 0.077667236328125 +55425 0.2132568359375 +55426 0.38885498046875 +55427 0.582794189453125 +55428 0.734039306640625 +55429 0.800140380859375 +55430 0.7783203125 +55431 0.6651611328125 +55432 0.45965576171875 +55433 0.199188232421875 +55434 -0.050689697265625 +55435 -0.23297119140625 +55436 -0.33013916015625 +55437 -0.368408203125 +55438 -0.378936767578125 +55439 -0.376983642578125 +55440 -0.37969970703125 +55441 -0.391510009765625 +55442 -0.385345458984375 +55443 -0.3419189453125 +55444 -0.28289794921875 +55445 -0.251617431640625 +55446 -0.266143798828125 +55447 -0.273345947265625 +55448 -0.216796875 +55449 -0.128265380859375 +55450 -0.068145751953125 +55451 -0.0430908203125 +55452 -0.024444580078125 +55453 0.020721435546875 +55454 0.124481201171875 +55455 0.25787353515625 +55456 0.379119873046875 +55457 0.47991943359375 +55458 0.5281982421875 +55459 0.511138916015625 +55460 0.456207275390625 +55461 0.407470703125 +55462 0.383758544921875 +55463 0.35687255859375 +55464 0.31182861328125 +55465 0.250885009765625 +55466 0.1654052734375 +55467 0.035247802734375 +55468 -0.142059326171875 +55469 -0.33563232421875 +55470 -0.5345458984375 +55471 -0.72186279296875 +55472 -0.836669921875 +55473 -0.8326416015625 +55474 -0.7296142578125 +55475 -0.582550048828125 +55476 -0.440093994140625 +55477 -0.324310302734375 +55478 -0.20147705078125 +55479 -0.044647216796875 +55480 0.103973388671875 +55481 0.202392578125 +55482 0.264495849609375 +55483 0.338897705078125 +55484 0.443817138671875 +55485 0.545074462890625 +55486 0.6173095703125 +55487 0.6524658203125 +55488 0.66339111328125 +55489 0.6561279296875 +55490 0.606781005859375 +55491 0.501190185546875 +55492 0.352783203125 +55493 0.176544189453125 +55494 -0.034820556640625 +55495 -0.258209228515625 +55496 -0.44244384765625 +55497 -0.5753173828125 +55498 -0.65203857421875 +55499 -0.641632080078125 +55500 -0.562164306640625 +55501 -0.458038330078125 +55502 -0.350555419921875 +55503 -0.260528564453125 +55504 -0.192108154296875 +55505 -0.141937255859375 +55506 -0.1021728515625 +55507 -0.062896728515625 +55508 -0.011932373046875 +55509 0.062835693359375 +55510 0.148712158203125 +55511 0.241729736328125 +55512 0.34912109375 +55513 0.457305908203125 +55514 0.54388427734375 +55515 0.5728759765625 +55516 0.506591796875 +55517 0.351226806640625 +55518 0.146514892578125 +55519 -0.05523681640625 +55520 -0.21624755859375 +55521 -0.334930419921875 +55522 -0.402984619140625 +55523 -0.4412841796875 +55524 -0.49578857421875 +55525 -0.5601806640625 +55526 -0.600738525390625 +55527 -0.584228515625 +55528 -0.47930908203125 +55529 -0.27935791015625 +55530 -0.0089111328125 +55531 0.268798828125 +55532 0.482818603515625 +55533 0.60369873046875 +55534 0.650421142578125 +55535 0.66400146484375 +55536 0.6414794921875 +55537 0.572540283203125 +55538 0.498138427734375 +55539 0.439453125 +55540 0.375518798828125 +55541 0.274505615234375 +55542 0.1087646484375 +55543 -0.099395751953125 +55544 -0.3182373046875 +55545 -0.5489501953125 +55546 -0.7738037109375 +55547 -0.86383056640625 +55548 -0.870391845703125 +55549 -0.86895751953125 +55550 -0.861053466796875 +55551 -0.765869140625 +55552 -0.5301513671875 +55553 -0.214691162109375 +55554 0.137359619140625 +55555 0.474822998046875 +55556 0.76239013671875 +55557 0.867462158203125 +55558 0.870361328125 +55559 0.86480712890625 +55560 0.831817626953125 +55561 0.677581787109375 +55562 0.495880126953125 +55563 0.30767822265625 +55564 0.116180419921875 +55565 -0.110748291015625 +55566 -0.381805419921875 +55567 -0.6572265625 +55568 -0.857421875 +55569 -0.870391845703125 +55570 -0.870391845703125 +55571 -0.86444091796875 +55572 -0.85723876953125 +55573 -0.790008544921875 +55574 -0.62847900390625 +55575 -0.3956298828125 +55576 -0.126708984375 +55577 0.150115966796875 +55578 0.424041748046875 +55579 0.670623779296875 +55580 0.854522705078125 +55581 0.866485595703125 +55582 0.86920166015625 +55583 0.8653564453125 +55584 0.857147216796875 +55585 0.766845703125 +55586 0.628509521484375 +55587 0.462127685546875 +55588 0.297210693359375 +55589 0.14862060546875 +55590 -0.00537109375 +55591 -0.15753173828125 +55592 -0.31304931640625 +55593 -0.48876953125 +55594 -0.6416015625 +55595 -0.751373291015625 +55596 -0.84619140625 +55597 -0.861297607421875 +55598 -0.863250732421875 +55599 -0.856597900390625 +55600 -0.7498779296875 +55601 -0.624542236328125 +55602 -0.47808837890625 +55603 -0.253387451171875 +55604 0.003692626953125 +55605 0.2257080078125 +55606 0.427154541015625 +55607 0.643218994140625 +55608 0.855926513671875 +55609 0.870361328125 +55610 0.870361328125 +55611 0.862762451171875 +55612 0.79669189453125 +55613 0.595794677734375 +55614 0.362152099609375 +55615 0.1270751953125 +55616 -0.086944580078125 +55617 -0.2784423828125 +55618 -0.484832763671875 +55619 -0.729583740234375 +55620 -0.86688232421875 +55621 -0.870391845703125 +55622 -0.86859130859375 +55623 -0.86279296875 +55624 -0.817962646484375 +55625 -0.6116943359375 +55626 -0.3128662109375 +55627 0.039398193359375 +55628 0.422821044921875 +55629 0.805145263671875 +55630 0.870361328125 +55631 0.870361328125 +55632 0.860015869140625 +55633 0.727935791015625 +55634 0.48114013671875 +55635 0.2059326171875 +55636 -0.06103515625 +55637 -0.29913330078125 +55638 -0.516204833984375 +55639 -0.7252197265625 +55640 -0.85980224609375 +55641 -0.870391845703125 +55642 -0.870391845703125 +55643 -0.858062744140625 +55644 -0.673004150390625 +55645 -0.42694091796875 +55646 -0.2100830078125 +55647 -0.0362548828125 +55648 0.10943603515625 +55649 0.23516845703125 +55650 0.373687744140625 +55651 0.517791748046875 +55652 0.602783203125 +55653 0.635711669921875 +55654 0.655181884765625 +55655 0.65948486328125 +55656 0.651275634765625 +55657 0.61846923828125 +55658 0.53753662109375 +55659 0.404144287109375 +55660 0.22186279296875 +55661 0.003997802734375 +55662 -0.22100830078125 +55663 -0.42449951171875 +55664 -0.579833984375 +55665 -0.641876220703125 +55666 -0.6177978515625 +55667 -0.575531005859375 +55668 -0.526336669921875 +55669 -0.42645263671875 +55670 -0.2581787109375 +55671 -0.068695068359375 +55672 0.09222412109375 +55673 0.232147216796875 +55674 0.3509521484375 +55675 0.410064697265625 +55676 0.372955322265625 +55677 0.2554931640625 +55678 0.10711669921875 +55679 -0.052886962890625 +55680 -0.186279296875 +55681 -0.23291015625 +55682 -0.209442138671875 +55683 -0.174163818359375 +55684 -0.126739501953125 +55685 -0.048126220703125 +55686 0.0426025390625 +55687 0.10748291015625 +55688 0.1409912109375 +55689 0.19708251953125 +55690 0.273651123046875 +55691 0.31768798828125 +55692 0.341094970703125 +55693 0.368011474609375 +55694 0.37249755859375 +55695 0.30072021484375 +55696 0.1517333984375 +55697 -0.01470947265625 +55698 -0.1883544921875 +55699 -0.372711181640625 +55700 -0.51397705078125 +55701 -0.57177734375 +55702 -0.53948974609375 +55703 -0.43511962890625 +55704 -0.2962646484375 +55705 -0.161102294921875 +55706 -0.0435791015625 +55707 0.060394287109375 +55708 0.13665771484375 +55709 0.170135498046875 +55710 0.16552734375 +55711 0.15728759765625 +55712 0.150787353515625 +55713 0.12200927734375 +55714 0.080108642578125 +55715 0.05126953125 +55716 0.062896728515625 +55717 0.09271240234375 +55718 0.092987060546875 +55719 0.07855224609375 +55720 0.06427001953125 +55721 0.0347900390625 +55722 -0.01171875 +55723 -0.056060791015625 +55724 -0.055511474609375 +55725 -0.010467529296875 +55726 0.02508544921875 +55727 0.025665283203125 +55728 0.017333984375 +55729 0.00189208984375 +55730 -0.03173828125 +55731 -0.071502685546875 +55732 -0.13543701171875 +55733 -0.219970703125 +55734 -0.300506591796875 +55735 -0.376312255859375 +55736 -0.416107177734375 +55737 -0.371124267578125 +55738 -0.242279052734375 +55739 -0.069732666015625 +55740 0.125640869140625 +55741 0.31268310546875 +55742 0.45501708984375 +55743 0.554779052734375 +55744 0.61065673828125 +55745 0.610931396484375 +55746 0.531463623046875 +55747 0.3883056640625 +55748 0.23468017578125 +55749 0.095245361328125 +55750 -0.00396728515625 +55751 -0.04852294921875 +55752 -0.055145263671875 +55753 -0.0758056640625 +55754 -0.138702392578125 +55755 -0.209197998046875 +55756 -0.289031982421875 +55757 -0.37884521484375 +55758 -0.456329345703125 +55759 -0.51641845703125 +55760 -0.519287109375 +55761 -0.458251953125 +55762 -0.384796142578125 +55763 -0.323699951171875 +55764 -0.269287109375 +55765 -0.1951904296875 +55766 -0.100006103515625 +55767 -0.01055908203125 +55768 0.1033935546875 +55769 0.24908447265625 +55770 0.373199462890625 +55771 0.45806884765625 +55772 0.511474609375 +55773 0.565399169921875 +55774 0.61138916015625 +55775 0.5897216796875 +55776 0.4906005859375 +55777 0.33148193359375 +55778 0.147796630859375 +55779 -0.01873779296875 +55780 -0.140289306640625 +55781 -0.191986083984375 +55782 -0.184295654296875 +55783 -0.161834716796875 +55784 -0.166595458984375 +55785 -0.19390869140625 +55786 -0.22442626953125 +55787 -0.279754638671875 +55788 -0.3389892578125 +55789 -0.3543701171875 +55790 -0.348175048828125 +55791 -0.32598876953125 +55792 -0.2581787109375 +55793 -0.139801025390625 +55794 0.014617919921875 +55795 0.144378662109375 +55796 0.221038818359375 +55797 0.27069091796875 +55798 0.294036865234375 +55799 0.311767578125 +55800 0.339141845703125 +55801 0.360260009765625 +55802 0.360504150390625 +55803 0.308380126953125 +55804 0.18170166015625 +55805 0.0047607421875 +55806 -0.17559814453125 +55807 -0.3143310546875 +55808 -0.36785888671875 +55809 -0.36248779296875 +55810 -0.343536376953125 +55811 -0.3018798828125 +55812 -0.231414794921875 +55813 -0.117645263671875 +55814 0.007049560546875 +55815 0.087982177734375 +55816 0.13946533203125 +55817 0.17425537109375 +55818 0.188201904296875 +55819 0.171234130859375 +55820 0.118438720703125 +55821 0.05706787109375 +55822 -0.010711669921875 +55823 -0.0914306640625 +55824 -0.162322998046875 +55825 -0.194549560546875 +55826 -0.1492919921875 +55827 -0.02166748046875 +55828 0.124053955078125 +55829 0.211151123046875 +55830 0.240447998046875 +55831 0.242218017578125 +55832 0.2257080078125 +55833 0.194366455078125 +55834 0.115509033203125 +55835 0.0128173828125 +55836 -0.053802490234375 +55837 -0.110626220703125 +55838 -0.199493408203125 +55839 -0.29437255859375 +55840 -0.33221435546875 +55841 -0.27972412109375 +55842 -0.185333251953125 +55843 -0.128204345703125 +55844 -0.115692138671875 +55845 -0.116455078125 +55846 -0.105926513671875 +55847 -0.053955078125 +55848 0.048797607421875 +55849 0.157318115234375 +55850 0.212005615234375 +55851 0.218475341796875 +55852 0.23724365234375 +55853 0.30535888671875 +55854 0.38128662109375 +55855 0.404449462890625 +55856 0.3944091796875 +55857 0.3885498046875 +55858 0.362640380859375 +55859 0.27362060546875 +55860 0.11712646484375 +55861 -0.054901123046875 +55862 -0.19085693359375 +55863 -0.28570556640625 +55864 -0.339263916015625 +55865 -0.3775634765625 +55866 -0.445709228515625 +55867 -0.535064697265625 +55868 -0.629058837890625 +55869 -0.697601318359375 +55870 -0.70391845703125 +55871 -0.6424560546875 +55872 -0.491241455078125 +55873 -0.265716552734375 +55874 -0.023712158203125 +55875 0.201751708984375 +55876 0.375823974609375 +55877 0.485076904296875 +55878 0.56884765625 +55879 0.634765625 +55880 0.63763427734375 +55881 0.5660400390625 +55882 0.4720458984375 +55883 0.40692138671875 +55884 0.3778076171875 +55885 0.376953125 +55886 0.371978759765625 +55887 0.313140869140625 +55888 0.184417724609375 +55889 0.011199951171875 +55890 -0.171051025390625 +55891 -0.33740234375 +55892 -0.47198486328125 +55893 -0.560394287109375 +55894 -0.58056640625 +55895 -0.54754638671875 +55896 -0.508575439453125 +55897 -0.459503173828125 +55898 -0.394378662109375 +55899 -0.35260009765625 +55900 -0.31170654296875 +55901 -0.197418212890625 +55902 -0.007965087890625 +55903 0.207489013671875 +55904 0.409210205078125 +55905 0.57208251953125 +55906 0.66595458984375 +55907 0.65875244140625 +55908 0.56744384765625 +55909 0.431396484375 +55910 0.29443359375 +55911 0.182464599609375 +55912 0.06365966796875 +55913 -0.075958251953125 +55914 -0.189422607421875 +55915 -0.271942138671875 +55916 -0.342529296875 +55917 -0.364166259765625 +55918 -0.327239990234375 +55919 -0.2769775390625 +55920 -0.253692626953125 +55921 -0.24365234375 +55922 -0.1983642578125 +55923 -0.116241455078125 +55924 -0.036834716796875 +55925 0.034881591796875 +55926 0.09124755859375 +55927 0.10888671875 +55928 0.125518798828125 +55929 0.15771484375 +55930 0.17828369140625 +55931 0.17108154296875 +55932 0.129974365234375 +55933 0.082427978515625 +55934 0.027679443359375 +55935 -0.065643310546875 +55936 -0.15936279296875 +55937 -0.21307373046875 +55938 -0.234649658203125 +55939 -0.2001953125 +55940 -0.119171142578125 +55941 -0.024749755859375 +55942 0.085784912109375 +55943 0.178131103515625 +55944 0.215576171875 +55945 0.211456298828125 +55946 0.17523193359375 +55947 0.128753662109375 +55948 0.1019287109375 +55949 0.0743408203125 +55950 0.04327392578125 +55951 0.038177490234375 +55952 0.076263427734375 +55953 0.14105224609375 +55954 0.186431884765625 +55955 0.188812255859375 +55956 0.1390380859375 +55957 0.041778564453125 +55958 -0.079437255859375 +55959 -0.219390869140625 +55960 -0.367828369140625 +55961 -0.494873046875 +55962 -0.556243896484375 +55963 -0.508697509765625 +55964 -0.3756103515625 +55965 -0.218902587890625 +55966 -0.063751220703125 +55967 0.091552734375 +55968 0.23602294921875 +55969 0.342987060546875 +55970 0.39520263671875 +55971 0.389373779296875 +55972 0.324249267578125 +55973 0.224090576171875 +55974 0.124267578125 +55975 0.037078857421875 +55976 -0.010101318359375 +55977 -0.019439697265625 +55978 -0.022796630859375 +55979 -0.001556396484375 +55980 0.056304931640625 +55981 0.106719970703125 +55982 0.096893310546875 +55983 0.042694091796875 +55984 -0.018035888671875 +55985 -0.07586669921875 +55986 -0.11944580078125 +55987 -0.15972900390625 +55988 -0.202606201171875 +55989 -0.24859619140625 +55990 -0.30517578125 +55991 -0.36212158203125 +55992 -0.39141845703125 +55993 -0.35528564453125 +55994 -0.249969482421875 +55995 -0.092864990234375 +55996 0.08905029296875 +55997 0.2352294921875 +55998 0.318817138671875 +55999 0.358642578125 +56000 0.347747802734375 +56001 0.28564453125 +56002 0.223175048828125 +56003 0.196746826171875 +56004 0.179840087890625 +56005 0.155548095703125 +56006 0.151214599609375 +56007 0.156951904296875 +56008 0.13177490234375 +56009 0.100799560546875 +56010 0.087127685546875 +56011 0.05487060546875 +56012 -0.009002685546875 +56013 -0.10400390625 +56014 -0.229400634765625 +56015 -0.35552978515625 +56016 -0.441925048828125 +56017 -0.473846435546875 +56018 -0.464813232421875 +56019 -0.419097900390625 +56020 -0.334320068359375 +56021 -0.227935791015625 +56022 -0.12347412109375 +56023 -0.02764892578125 +56024 0.077667236328125 +56025 0.2132568359375 +56026 0.38885498046875 +56027 0.582794189453125 +56028 0.734039306640625 +56029 0.800140380859375 +56030 0.7783203125 +56031 0.6651611328125 +56032 0.45965576171875 +56033 0.199188232421875 +56034 -0.050689697265625 +56035 -0.23297119140625 +56036 -0.33013916015625 +56037 -0.368408203125 +56038 -0.378936767578125 +56039 -0.376983642578125 +56040 -0.37969970703125 +56041 -0.391510009765625 +56042 -0.385345458984375 +56043 -0.3419189453125 +56044 -0.28289794921875 +56045 -0.251617431640625 +56046 -0.266143798828125 +56047 -0.273345947265625 +56048 -0.216796875 +56049 -0.128265380859375 +56050 -0.068145751953125 +56051 -0.0430908203125 +56052 -0.024444580078125 +56053 0.020721435546875 +56054 0.124481201171875 +56055 0.25787353515625 +56056 0.379119873046875 +56057 0.47991943359375 +56058 0.5281982421875 +56059 0.511138916015625 +56060 0.456207275390625 +56061 0.407470703125 +56062 0.383758544921875 +56063 0.35687255859375 +56064 0.31182861328125 +56065 0.250885009765625 +56066 0.1654052734375 +56067 0.035247802734375 +56068 -0.142059326171875 +56069 -0.33563232421875 +56070 -0.5345458984375 +56071 -0.72186279296875 +56072 -0.836669921875 +56073 -0.8326416015625 +56074 -0.7296142578125 +56075 -0.582550048828125 +56076 -0.440093994140625 +56077 -0.324310302734375 +56078 -0.20147705078125 +56079 -0.044647216796875 +56080 0.103973388671875 +56081 0.202392578125 +56082 0.264495849609375 +56083 0.338897705078125 +56084 0.443817138671875 +56085 0.545074462890625 +56086 0.6173095703125 +56087 0.6524658203125 +56088 0.66339111328125 +56089 0.6561279296875 +56090 0.606781005859375 +56091 0.501190185546875 +56092 0.352783203125 +56093 0.176544189453125 +56094 -0.034820556640625 +56095 -0.258209228515625 +56096 -0.44244384765625 +56097 -0.5753173828125 +56098 -0.65203857421875 +56099 -0.641632080078125 +56100 -0.562164306640625 +56101 -0.458038330078125 +56102 -0.350555419921875 +56103 -0.260528564453125 +56104 -0.192108154296875 +56105 -0.141937255859375 +56106 -0.1021728515625 +56107 -0.062896728515625 +56108 -0.011932373046875 +56109 0.062835693359375 +56110 0.148712158203125 +56111 0.241729736328125 +56112 0.34912109375 +56113 0.457305908203125 +56114 0.54388427734375 +56115 0.5728759765625 +56116 0.506591796875 +56117 0.351226806640625 +56118 0.146514892578125 +56119 -0.05523681640625 +56120 -0.21624755859375 +56121 -0.334930419921875 +56122 -0.402984619140625 +56123 -0.4412841796875 +56124 -0.49578857421875 +56125 -0.5601806640625 +56126 -0.600738525390625 +56127 -0.584228515625 +56128 -0.47930908203125 +56129 -0.27935791015625 +56130 -0.0089111328125 +56131 0.268798828125 +56132 0.482818603515625 +56133 0.60369873046875 +56134 0.650421142578125 +56135 0.66400146484375 +56136 0.6414794921875 +56137 0.572540283203125 +56138 0.498138427734375 +56139 0.439453125 +56140 0.375518798828125 +56141 0.274505615234375 +56142 0.1087646484375 +56143 -0.099395751953125 +56144 -0.3182373046875 +56145 -0.5489501953125 +56146 -0.7738037109375 +56147 -0.86383056640625 +56148 -0.870391845703125 +56149 -0.86895751953125 +56150 -0.861053466796875 +56151 -0.765869140625 +56152 -0.5301513671875 +56153 -0.214691162109375 +56154 0.137359619140625 +56155 0.474822998046875 +56156 0.76239013671875 +56157 0.867462158203125 +56158 0.870361328125 +56159 0.86480712890625 +56160 0.831817626953125 +56161 0.677581787109375 +56162 0.495880126953125 +56163 0.30767822265625 +56164 0.116180419921875 +56165 -0.110748291015625 +56166 -0.381805419921875 +56167 -0.6572265625 +56168 -0.857421875 +56169 -0.870391845703125 +56170 -0.870391845703125 +56171 -0.86444091796875 +56172 -0.85723876953125 +56173 -0.790008544921875 +56174 -0.62847900390625 +56175 -0.3956298828125 +56176 -0.126708984375 +56177 0.150115966796875 +56178 0.424041748046875 +56179 0.670623779296875 +56180 0.854522705078125 +56181 0.866485595703125 +56182 0.86920166015625 +56183 0.8653564453125 +56184 0.857147216796875 +56185 0.766845703125 +56186 0.628509521484375 +56187 0.462127685546875 +56188 0.297210693359375 +56189 0.14862060546875 +56190 -0.00537109375 +56191 -0.15753173828125 +56192 -0.31304931640625 +56193 -0.48876953125 +56194 -0.6416015625 +56195 -0.751373291015625 +56196 -0.84619140625 +56197 -0.861297607421875 +56198 -0.863250732421875 +56199 -0.856597900390625 +56200 -0.7498779296875 +56201 -0.624542236328125 +56202 -0.47808837890625 +56203 -0.253387451171875 +56204 0.003692626953125 +56205 0.2257080078125 +56206 0.427154541015625 +56207 0.643218994140625 +56208 0.855926513671875 +56209 0.870361328125 +56210 0.870361328125 +56211 0.862762451171875 +56212 0.79669189453125 +56213 0.595794677734375 +56214 0.362152099609375 +56215 0.1270751953125 +56216 -0.086944580078125 +56217 -0.2784423828125 +56218 -0.484832763671875 +56219 -0.729583740234375 +56220 -0.86688232421875 +56221 -0.870391845703125 +56222 -0.86859130859375 +56223 -0.86279296875 +56224 -0.817962646484375 +56225 -0.6116943359375 +56226 -0.3128662109375 +56227 0.039398193359375 +56228 0.422821044921875 +56229 0.805145263671875 +56230 0.870361328125 +56231 0.870361328125 +56232 0.860015869140625 +56233 0.727935791015625 +56234 0.48114013671875 +56235 0.2059326171875 +56236 -0.06103515625 +56237 -0.29913330078125 +56238 -0.516204833984375 +56239 -0.7252197265625 +56240 -0.85980224609375 +56241 -0.870391845703125 +56242 -0.870391845703125 +56243 -0.858062744140625 +56244 -0.673004150390625 +56245 -0.42694091796875 +56246 -0.2100830078125 +56247 -0.0362548828125 +56248 0.10943603515625 +56249 0.23516845703125 +56250 0.373687744140625 +56251 0.517791748046875 +56252 0.602783203125 +56253 0.635711669921875 +56254 0.655181884765625 +56255 0.65948486328125 +56256 0.651275634765625 +56257 0.61846923828125 +56258 0.53753662109375 +56259 0.404144287109375 +56260 0.22186279296875 +56261 0.003997802734375 +56262 -0.22100830078125 +56263 -0.42449951171875 +56264 -0.579833984375 +56265 -0.641876220703125 +56266 -0.6177978515625 +56267 -0.575531005859375 +56268 -0.526336669921875 +56269 -0.42645263671875 +56270 -0.2581787109375 +56271 -0.068695068359375 +56272 0.09222412109375 +56273 0.232147216796875 +56274 0.3509521484375 +56275 0.410064697265625 +56276 0.372955322265625 +56277 0.2554931640625 +56278 0.10711669921875 +56279 -0.052886962890625 +56280 -0.186279296875 +56281 -0.23291015625 +56282 -0.209442138671875 +56283 -0.174163818359375 +56284 -0.126739501953125 +56285 -0.048126220703125 +56286 0.0426025390625 +56287 0.10748291015625 +56288 0.1409912109375 +56289 0.19708251953125 +56290 0.273651123046875 +56291 0.31768798828125 +56292 0.341094970703125 +56293 0.368011474609375 +56294 0.37249755859375 +56295 0.30072021484375 +56296 0.1517333984375 +56297 -0.01470947265625 +56298 -0.1883544921875 +56299 -0.372711181640625 +56300 -0.51397705078125 +56301 -0.57177734375 +56302 -0.53948974609375 +56303 -0.43511962890625 +56304 -0.2962646484375 +56305 -0.161102294921875 +56306 -0.0435791015625 +56307 0.060394287109375 +56308 0.13665771484375 +56309 0.170135498046875 +56310 0.16552734375 +56311 0.15728759765625 +56312 0.150787353515625 +56313 0.12200927734375 +56314 0.080108642578125 +56315 0.05126953125 +56316 0.062896728515625 +56317 0.09271240234375 +56318 0.092987060546875 +56319 0.07855224609375 +56320 0.06427001953125 +56321 0.0347900390625 +56322 -0.01171875 +56323 -0.056060791015625 +56324 -0.055511474609375 +56325 -0.010467529296875 +56326 0.02508544921875 +56327 0.025665283203125 +56328 0.017333984375 +56329 0.00189208984375 +56330 -0.03173828125 +56331 -0.071502685546875 +56332 -0.13543701171875 +56333 -0.219970703125 +56334 -0.300506591796875 +56335 -0.376312255859375 +56336 -0.416107177734375 +56337 -0.371124267578125 +56338 -0.242279052734375 +56339 -0.069732666015625 +56340 0.125640869140625 +56341 0.31268310546875 +56342 0.45501708984375 +56343 0.554779052734375 +56344 0.61065673828125 +56345 0.610931396484375 +56346 0.531463623046875 +56347 0.3883056640625 +56348 0.23468017578125 +56349 0.095245361328125 +56350 -0.00396728515625 +56351 -0.04852294921875 +56352 -0.055145263671875 +56353 -0.0758056640625 +56354 -0.138702392578125 +56355 -0.209197998046875 +56356 -0.289031982421875 +56357 -0.37884521484375 +56358 -0.456329345703125 +56359 -0.51641845703125 +56360 -0.519287109375 +56361 -0.458251953125 +56362 -0.384796142578125 +56363 -0.323699951171875 +56364 -0.269287109375 +56365 -0.1951904296875 +56366 -0.100006103515625 +56367 -0.01055908203125 +56368 0.1033935546875 +56369 0.24908447265625 +56370 0.373199462890625 +56371 0.45806884765625 +56372 0.511474609375 +56373 0.565399169921875 +56374 0.61138916015625 +56375 0.5897216796875 +56376 0.4906005859375 +56377 0.33148193359375 +56378 0.147796630859375 +56379 -0.01873779296875 +56380 -0.140289306640625 +56381 -0.191986083984375 +56382 -0.184295654296875 +56383 -0.161834716796875 +56384 -0.166595458984375 +56385 -0.19390869140625 +56386 -0.22442626953125 +56387 -0.279754638671875 +56388 -0.3389892578125 +56389 -0.3543701171875 +56390 -0.348175048828125 +56391 -0.32598876953125 +56392 -0.2581787109375 +56393 -0.139801025390625 +56394 0.014617919921875 +56395 0.144378662109375 +56396 0.221038818359375 +56397 0.27069091796875 +56398 0.294036865234375 +56399 0.311767578125 +56400 0.339141845703125 +56401 0.360260009765625 +56402 0.360504150390625 +56403 0.308380126953125 +56404 0.18170166015625 +56405 0.0047607421875 +56406 -0.17559814453125 +56407 -0.3143310546875 +56408 -0.36785888671875 +56409 -0.36248779296875 +56410 -0.343536376953125 +56411 -0.3018798828125 +56412 -0.231414794921875 +56413 -0.117645263671875 +56414 0.007049560546875 +56415 0.087982177734375 +56416 0.13946533203125 +56417 0.17425537109375 +56418 0.188201904296875 +56419 0.171234130859375 +56420 0.118438720703125 +56421 0.05706787109375 +56422 -0.010711669921875 +56423 -0.0914306640625 +56424 -0.162322998046875 +56425 -0.194549560546875 +56426 -0.1492919921875 +56427 -0.02166748046875 +56428 0.124053955078125 +56429 0.211151123046875 +56430 0.240447998046875 +56431 0.242218017578125 +56432 0.2257080078125 +56433 0.194366455078125 +56434 0.115509033203125 +56435 0.0128173828125 +56436 -0.053802490234375 +56437 -0.110626220703125 +56438 -0.199493408203125 +56439 -0.29437255859375 +56440 -0.33221435546875 +56441 -0.27972412109375 +56442 -0.185333251953125 +56443 -0.128204345703125 +56444 -0.115692138671875 +56445 -0.116455078125 +56446 -0.105926513671875 +56447 -0.053955078125 +56448 0.048797607421875 +56449 0.157318115234375 +56450 0.212005615234375 +56451 0.218475341796875 +56452 0.23724365234375 +56453 0.30535888671875 +56454 0.38128662109375 +56455 0.404449462890625 +56456 0.3944091796875 +56457 0.3885498046875 +56458 0.362640380859375 +56459 0.27362060546875 +56460 0.11712646484375 +56461 -0.054901123046875 +56462 -0.19085693359375 +56463 -0.28570556640625 +56464 -0.339263916015625 +56465 -0.3775634765625 +56466 -0.445709228515625 +56467 -0.535064697265625 +56468 -0.629058837890625 +56469 -0.697601318359375 +56470 -0.70391845703125 +56471 -0.6424560546875 +56472 -0.491241455078125 +56473 -0.265716552734375 +56474 -0.023712158203125 +56475 0.201751708984375 +56476 0.375823974609375 +56477 0.485076904296875 +56478 0.56884765625 +56479 0.634765625 +56480 0.63763427734375 +56481 0.5660400390625 +56482 0.4720458984375 +56483 0.40692138671875 +56484 0.3778076171875 +56485 0.376953125 +56486 0.371978759765625 +56487 0.313140869140625 +56488 0.184417724609375 +56489 0.011199951171875 +56490 -0.171051025390625 +56491 -0.33740234375 +56492 -0.47198486328125 +56493 -0.560394287109375 +56494 -0.58056640625 +56495 -0.54754638671875 +56496 -0.508575439453125 +56497 -0.459503173828125 +56498 -0.394378662109375 +56499 -0.35260009765625 +56500 -0.31170654296875 +56501 -0.197418212890625 +56502 -0.007965087890625 +56503 0.207489013671875 +56504 0.409210205078125 +56505 0.57208251953125 +56506 0.66595458984375 +56507 0.65875244140625 +56508 0.56744384765625 +56509 0.431396484375 +56510 0.29443359375 +56511 0.182464599609375 +56512 0.06365966796875 +56513 -0.075958251953125 +56514 -0.189422607421875 +56515 -0.271942138671875 +56516 -0.342529296875 +56517 -0.364166259765625 +56518 -0.327239990234375 +56519 -0.2769775390625 +56520 -0.253692626953125 +56521 -0.24365234375 +56522 -0.1983642578125 +56523 -0.116241455078125 +56524 -0.036834716796875 +56525 0.034881591796875 +56526 0.09124755859375 +56527 0.10888671875 +56528 0.125518798828125 +56529 0.15771484375 +56530 0.17828369140625 +56531 0.17108154296875 +56532 0.129974365234375 +56533 0.082427978515625 +56534 0.027679443359375 +56535 -0.065643310546875 +56536 -0.15936279296875 +56537 -0.21307373046875 +56538 -0.234649658203125 +56539 -0.2001953125 +56540 -0.119171142578125 +56541 -0.024749755859375 +56542 0.085784912109375 +56543 0.178131103515625 +56544 0.215576171875 +56545 0.211456298828125 +56546 0.17523193359375 +56547 0.128753662109375 +56548 0.1019287109375 +56549 0.0743408203125 +56550 0.04327392578125 +56551 0.038177490234375 +56552 0.076263427734375 +56553 0.14105224609375 +56554 0.186431884765625 +56555 0.188812255859375 +56556 0.1390380859375 +56557 0.041778564453125 +56558 -0.079437255859375 +56559 -0.219390869140625 +56560 -0.367828369140625 +56561 -0.494873046875 +56562 -0.556243896484375 +56563 -0.508697509765625 +56564 -0.3756103515625 +56565 -0.218902587890625 +56566 -0.063751220703125 +56567 0.091552734375 +56568 0.23602294921875 +56569 0.342987060546875 +56570 0.39520263671875 +56571 0.389373779296875 +56572 0.324249267578125 +56573 0.224090576171875 +56574 0.124267578125 +56575 0.037078857421875 +56576 -0.010101318359375 +56577 -0.019439697265625 +56578 -0.022796630859375 +56579 -0.001556396484375 +56580 0.056304931640625 +56581 0.106719970703125 +56582 0.096893310546875 +56583 0.042694091796875 +56584 -0.018035888671875 +56585 -0.07586669921875 +56586 -0.11944580078125 +56587 -0.15972900390625 +56588 -0.202606201171875 +56589 -0.24859619140625 +56590 -0.30517578125 +56591 -0.36212158203125 +56592 -0.39141845703125 +56593 -0.35528564453125 +56594 -0.249969482421875 +56595 -0.092864990234375 +56596 0.08905029296875 +56597 0.2352294921875 +56598 0.318817138671875 +56599 0.358642578125 +56600 0.347747802734375 +56601 0.28564453125 +56602 0.223175048828125 +56603 0.196746826171875 +56604 0.179840087890625 +56605 0.155548095703125 +56606 0.151214599609375 +56607 0.156951904296875 +56608 0.13177490234375 +56609 0.100799560546875 +56610 0.087127685546875 +56611 0.05487060546875 +56612 -0.009002685546875 +56613 -0.10400390625 +56614 -0.229400634765625 +56615 -0.35552978515625 +56616 -0.441925048828125 +56617 -0.473846435546875 +56618 -0.464813232421875 +56619 -0.419097900390625 +56620 -0.334320068359375 +56621 -0.227935791015625 +56622 -0.12347412109375 +56623 -0.02764892578125 +56624 0.077667236328125 +56625 0.2132568359375 +56626 0.38885498046875 +56627 0.582794189453125 +56628 0.734039306640625 +56629 0.800140380859375 +56630 0.7783203125 +56631 0.6651611328125 +56632 0.45965576171875 +56633 0.199188232421875 +56634 -0.050689697265625 +56635 -0.23297119140625 +56636 -0.33013916015625 +56637 -0.368408203125 +56638 -0.378936767578125 +56639 -0.376983642578125 +56640 -0.37969970703125 +56641 -0.391510009765625 +56642 -0.385345458984375 +56643 -0.3419189453125 +56644 -0.28289794921875 +56645 -0.251617431640625 +56646 -0.266143798828125 +56647 -0.273345947265625 +56648 -0.216796875 +56649 -0.128265380859375 +56650 -0.068145751953125 +56651 -0.0430908203125 +56652 -0.024444580078125 +56653 0.020721435546875 +56654 0.124481201171875 +56655 0.25787353515625 +56656 0.379119873046875 +56657 0.47991943359375 +56658 0.5281982421875 +56659 0.511138916015625 +56660 0.456207275390625 +56661 0.407470703125 +56662 0.383758544921875 +56663 0.35687255859375 +56664 0.31182861328125 +56665 0.250885009765625 +56666 0.1654052734375 +56667 0.035247802734375 +56668 -0.142059326171875 +56669 -0.33563232421875 +56670 -0.5345458984375 +56671 -0.72186279296875 +56672 -0.836669921875 +56673 -0.8326416015625 +56674 -0.7296142578125 +56675 -0.582550048828125 +56676 -0.440093994140625 +56677 -0.324310302734375 +56678 -0.20147705078125 +56679 -0.044647216796875 +56680 0.103973388671875 +56681 0.202392578125 +56682 0.264495849609375 +56683 0.338897705078125 +56684 0.443817138671875 +56685 0.545074462890625 +56686 0.6173095703125 +56687 0.6524658203125 +56688 0.66339111328125 +56689 0.6561279296875 +56690 0.606781005859375 +56691 0.501190185546875 +56692 0.352783203125 +56693 0.176544189453125 +56694 -0.034820556640625 +56695 -0.258209228515625 +56696 -0.44244384765625 +56697 -0.5753173828125 +56698 -0.65203857421875 +56699 -0.641632080078125 +56700 -0.562164306640625 +56701 -0.458038330078125 +56702 -0.350555419921875 +56703 -0.260528564453125 +56704 -0.192108154296875 +56705 -0.141937255859375 +56706 -0.1021728515625 +56707 -0.062896728515625 +56708 -0.011932373046875 +56709 0.062835693359375 +56710 0.148712158203125 +56711 0.241729736328125 +56712 0.34912109375 +56713 0.457305908203125 +56714 0.54388427734375 +56715 0.5728759765625 +56716 0.506591796875 +56717 0.351226806640625 +56718 0.146514892578125 +56719 -0.05523681640625 +56720 -0.21624755859375 +56721 -0.334930419921875 +56722 -0.402984619140625 +56723 -0.4412841796875 +56724 -0.49578857421875 +56725 -0.5601806640625 +56726 -0.600738525390625 +56727 -0.584228515625 +56728 -0.47930908203125 +56729 -0.27935791015625 +56730 -0.0089111328125 +56731 0.268798828125 +56732 0.482818603515625 +56733 0.60369873046875 +56734 0.650421142578125 +56735 0.66400146484375 +56736 0.6414794921875 +56737 0.572540283203125 +56738 0.498138427734375 +56739 0.439453125 +56740 0.375518798828125 +56741 0.274505615234375 +56742 0.1087646484375 +56743 -0.099395751953125 +56744 -0.3182373046875 +56745 -0.5489501953125 +56746 -0.7738037109375 +56747 -0.86383056640625 +56748 -0.870391845703125 +56749 -0.86895751953125 +56750 -0.861053466796875 +56751 -0.765869140625 +56752 -0.5301513671875 +56753 -0.214691162109375 +56754 0.137359619140625 +56755 0.474822998046875 +56756 0.76239013671875 +56757 0.867462158203125 +56758 0.870361328125 +56759 0.86480712890625 +56760 0.831817626953125 +56761 0.677581787109375 +56762 0.495880126953125 +56763 0.30767822265625 +56764 0.116180419921875 +56765 -0.110748291015625 +56766 -0.381805419921875 +56767 -0.6572265625 +56768 -0.857421875 +56769 -0.870391845703125 +56770 -0.870391845703125 +56771 -0.86444091796875 +56772 -0.85723876953125 +56773 -0.790008544921875 +56774 -0.62847900390625 +56775 -0.3956298828125 +56776 -0.126708984375 +56777 0.150115966796875 +56778 0.424041748046875 +56779 0.670623779296875 +56780 0.854522705078125 +56781 0.866485595703125 +56782 0.86920166015625 +56783 0.8653564453125 +56784 0.857147216796875 +56785 0.766845703125 +56786 0.628509521484375 +56787 0.462127685546875 +56788 0.297210693359375 +56789 0.14862060546875 +56790 -0.00537109375 +56791 -0.15753173828125 +56792 -0.31304931640625 +56793 -0.48876953125 +56794 -0.6416015625 +56795 -0.751373291015625 +56796 -0.84619140625 +56797 -0.861297607421875 +56798 -0.863250732421875 +56799 -0.856597900390625 +56800 -0.7498779296875 +56801 -0.624542236328125 +56802 -0.47808837890625 +56803 -0.253387451171875 +56804 0.003692626953125 +56805 0.2257080078125 +56806 0.427154541015625 +56807 0.643218994140625 +56808 0.855926513671875 +56809 0.870361328125 +56810 0.870361328125 +56811 0.862762451171875 +56812 0.79669189453125 +56813 0.595794677734375 +56814 0.362152099609375 +56815 0.1270751953125 +56816 -0.086944580078125 +56817 -0.2784423828125 +56818 -0.484832763671875 +56819 -0.729583740234375 +56820 -0.86688232421875 +56821 -0.870391845703125 +56822 -0.86859130859375 +56823 -0.86279296875 +56824 -0.817962646484375 +56825 -0.6116943359375 +56826 -0.3128662109375 +56827 0.039398193359375 +56828 0.422821044921875 +56829 0.805145263671875 +56830 0.870361328125 +56831 0.870361328125 +56832 0.860015869140625 +56833 0.727935791015625 +56834 0.48114013671875 +56835 0.2059326171875 +56836 -0.06103515625 +56837 -0.29913330078125 +56838 -0.516204833984375 +56839 -0.7252197265625 +56840 -0.85980224609375 +56841 -0.870391845703125 +56842 -0.870391845703125 +56843 -0.858062744140625 +56844 -0.673004150390625 +56845 -0.42694091796875 +56846 -0.2100830078125 +56847 -0.0362548828125 +56848 0.10943603515625 +56849 0.23516845703125 +56850 0.373687744140625 +56851 0.517791748046875 +56852 0.602783203125 +56853 0.635711669921875 +56854 0.655181884765625 +56855 0.65948486328125 +56856 0.651275634765625 +56857 0.61846923828125 +56858 0.53753662109375 +56859 0.404144287109375 +56860 0.22186279296875 +56861 0.003997802734375 +56862 -0.22100830078125 +56863 -0.42449951171875 +56864 -0.579833984375 +56865 -0.641876220703125 +56866 -0.6177978515625 +56867 -0.575531005859375 +56868 -0.526336669921875 +56869 -0.42645263671875 +56870 -0.2581787109375 +56871 -0.068695068359375 +56872 0.09222412109375 +56873 0.232147216796875 +56874 0.3509521484375 +56875 0.410064697265625 +56876 0.372955322265625 +56877 0.2554931640625 +56878 0.10711669921875 +56879 -0.052886962890625 +56880 -0.186279296875 +56881 -0.23291015625 +56882 -0.209442138671875 +56883 -0.174163818359375 +56884 -0.126739501953125 +56885 -0.048126220703125 +56886 0.0426025390625 +56887 0.10748291015625 +56888 0.1409912109375 +56889 0.19708251953125 +56890 0.273651123046875 +56891 0.31768798828125 +56892 0.341094970703125 +56893 0.368011474609375 +56894 0.37249755859375 +56895 0.30072021484375 +56896 0.1517333984375 +56897 -0.01470947265625 +56898 -0.1883544921875 +56899 -0.372711181640625 +56900 -0.51397705078125 +56901 -0.57177734375 +56902 -0.53948974609375 +56903 -0.43511962890625 +56904 -0.2962646484375 +56905 -0.161102294921875 +56906 -0.0435791015625 +56907 0.060394287109375 +56908 0.13665771484375 +56909 0.170135498046875 +56910 0.16552734375 +56911 0.15728759765625 +56912 0.150787353515625 +56913 0.12200927734375 +56914 0.080108642578125 +56915 0.05126953125 +56916 0.062896728515625 +56917 0.09271240234375 +56918 0.092987060546875 +56919 0.07855224609375 +56920 0.06427001953125 +56921 0.0347900390625 +56922 -0.01171875 +56923 -0.056060791015625 +56924 -0.055511474609375 +56925 -0.010467529296875 +56926 0.02508544921875 +56927 0.025665283203125 +56928 0.017333984375 +56929 0.00189208984375 +56930 -0.03173828125 +56931 -0.071502685546875 +56932 -0.13543701171875 +56933 -0.219970703125 +56934 -0.300506591796875 +56935 -0.376312255859375 +56936 -0.416107177734375 +56937 -0.371124267578125 +56938 -0.242279052734375 +56939 -0.069732666015625 +56940 0.125640869140625 +56941 0.31268310546875 +56942 0.45501708984375 +56943 0.554779052734375 +56944 0.61065673828125 +56945 0.610931396484375 +56946 0.531463623046875 +56947 0.3883056640625 +56948 0.23468017578125 +56949 0.095245361328125 +56950 -0.00396728515625 +56951 -0.04852294921875 +56952 -0.055145263671875 +56953 -0.0758056640625 +56954 -0.138702392578125 +56955 -0.209197998046875 +56956 -0.289031982421875 +56957 -0.37884521484375 +56958 -0.456329345703125 +56959 -0.51641845703125 +56960 -0.519287109375 +56961 -0.458251953125 +56962 -0.384796142578125 +56963 -0.323699951171875 +56964 -0.269287109375 +56965 -0.1951904296875 +56966 -0.100006103515625 +56967 -0.01055908203125 +56968 0.1033935546875 +56969 0.24908447265625 +56970 0.373199462890625 +56971 0.45806884765625 +56972 0.511474609375 +56973 0.565399169921875 +56974 0.61138916015625 +56975 0.5897216796875 +56976 0.4906005859375 +56977 0.33148193359375 +56978 0.147796630859375 +56979 -0.01873779296875 +56980 -0.140289306640625 +56981 -0.191986083984375 +56982 -0.184295654296875 +56983 -0.161834716796875 +56984 -0.166595458984375 +56985 -0.19390869140625 +56986 -0.22442626953125 +56987 -0.279754638671875 +56988 -0.3389892578125 +56989 -0.3543701171875 +56990 -0.348175048828125 +56991 -0.32598876953125 +56992 -0.2581787109375 +56993 -0.139801025390625 +56994 0.014617919921875 +56995 0.144378662109375 +56996 0.221038818359375 +56997 0.27069091796875 +56998 0.294036865234375 +56999 0.311767578125 +57000 0.339141845703125 +57001 0.360260009765625 +57002 0.360504150390625 +57003 0.308380126953125 +57004 0.18170166015625 +57005 0.0047607421875 +57006 -0.17559814453125 +57007 -0.3143310546875 +57008 -0.36785888671875 +57009 -0.36248779296875 +57010 -0.343536376953125 +57011 -0.3018798828125 +57012 -0.231414794921875 +57013 -0.117645263671875 +57014 0.007049560546875 +57015 0.087982177734375 +57016 0.13946533203125 +57017 0.17425537109375 +57018 0.188201904296875 +57019 0.171234130859375 +57020 0.118438720703125 +57021 0.05706787109375 +57022 -0.010711669921875 +57023 -0.0914306640625 +57024 -0.162322998046875 +57025 -0.194549560546875 +57026 -0.1492919921875 +57027 -0.02166748046875 +57028 0.124053955078125 +57029 0.211151123046875 +57030 0.240447998046875 +57031 0.242218017578125 +57032 0.2257080078125 +57033 0.194366455078125 +57034 0.115509033203125 +57035 0.0128173828125 +57036 -0.053802490234375 +57037 -0.110626220703125 +57038 -0.199493408203125 +57039 -0.29437255859375 +57040 -0.33221435546875 +57041 -0.27972412109375 +57042 -0.185333251953125 +57043 -0.128204345703125 +57044 -0.115692138671875 +57045 -0.116455078125 +57046 -0.105926513671875 +57047 -0.053955078125 +57048 0.048797607421875 +57049 0.157318115234375 +57050 0.212005615234375 +57051 0.218475341796875 +57052 0.23724365234375 +57053 0.30535888671875 +57054 0.38128662109375 +57055 0.404449462890625 +57056 0.3944091796875 +57057 0.3885498046875 +57058 0.362640380859375 +57059 0.27362060546875 +57060 0.11712646484375 +57061 -0.054901123046875 +57062 -0.19085693359375 +57063 -0.28570556640625 +57064 -0.339263916015625 +57065 -0.3775634765625 +57066 -0.445709228515625 +57067 -0.535064697265625 +57068 -0.629058837890625 +57069 -0.697601318359375 +57070 -0.70391845703125 +57071 -0.6424560546875 +57072 -0.491241455078125 +57073 -0.265716552734375 +57074 -0.023712158203125 +57075 0.201751708984375 +57076 0.375823974609375 +57077 0.485076904296875 +57078 0.56884765625 +57079 0.634765625 +57080 0.63763427734375 +57081 0.5660400390625 +57082 0.4720458984375 +57083 0.40692138671875 +57084 0.3778076171875 +57085 0.376953125 +57086 0.371978759765625 +57087 0.313140869140625 +57088 0.184417724609375 +57089 0.011199951171875 +57090 -0.171051025390625 +57091 -0.33740234375 +57092 -0.47198486328125 +57093 -0.560394287109375 +57094 -0.58056640625 +57095 -0.54754638671875 +57096 -0.508575439453125 +57097 -0.459503173828125 +57098 -0.394378662109375 +57099 -0.35260009765625 +57100 -0.31170654296875 +57101 -0.197418212890625 +57102 -0.007965087890625 +57103 0.207489013671875 +57104 0.409210205078125 +57105 0.57208251953125 +57106 0.66595458984375 +57107 0.65875244140625 +57108 0.56744384765625 +57109 0.431396484375 +57110 0.29443359375 +57111 0.182464599609375 +57112 0.06365966796875 +57113 -0.075958251953125 +57114 -0.189422607421875 +57115 -0.271942138671875 +57116 -0.342529296875 +57117 -0.364166259765625 +57118 -0.327239990234375 +57119 -0.2769775390625 +57120 -0.253692626953125 +57121 -0.24365234375 +57122 -0.1983642578125 +57123 -0.116241455078125 +57124 -0.036834716796875 +57125 0.034881591796875 +57126 0.09124755859375 +57127 0.10888671875 +57128 0.125518798828125 +57129 0.15771484375 +57130 0.17828369140625 +57131 0.17108154296875 +57132 0.129974365234375 +57133 0.082427978515625 +57134 0.027679443359375 +57135 -0.065643310546875 +57136 -0.15936279296875 +57137 -0.21307373046875 +57138 -0.234649658203125 +57139 -0.2001953125 +57140 -0.119171142578125 +57141 -0.024749755859375 +57142 0.085784912109375 +57143 0.178131103515625 +57144 0.215576171875 +57145 0.211456298828125 +57146 0.17523193359375 +57147 0.128753662109375 +57148 0.1019287109375 +57149 0.0743408203125 +57150 0.04327392578125 +57151 0.038177490234375 +57152 0.076263427734375 +57153 0.14105224609375 +57154 0.186431884765625 +57155 0.188812255859375 +57156 0.1390380859375 +57157 0.041778564453125 +57158 -0.079437255859375 +57159 -0.219390869140625 +57160 -0.367828369140625 +57161 -0.494873046875 +57162 -0.556243896484375 +57163 -0.508697509765625 +57164 -0.3756103515625 +57165 -0.218902587890625 +57166 -0.063751220703125 +57167 0.091552734375 +57168 0.23602294921875 +57169 0.342987060546875 +57170 0.39520263671875 +57171 0.389373779296875 +57172 0.324249267578125 +57173 0.224090576171875 +57174 0.124267578125 +57175 0.037078857421875 +57176 -0.010101318359375 +57177 -0.019439697265625 +57178 -0.022796630859375 +57179 -0.001556396484375 +57180 0.056304931640625 +57181 0.106719970703125 +57182 0.096893310546875 +57183 0.042694091796875 +57184 -0.018035888671875 +57185 -0.07586669921875 +57186 -0.11944580078125 +57187 -0.15972900390625 +57188 -0.202606201171875 +57189 -0.24859619140625 +57190 -0.30517578125 +57191 -0.36212158203125 +57192 -0.39141845703125 +57193 -0.35528564453125 +57194 -0.249969482421875 +57195 -0.092864990234375 +57196 0.08905029296875 +57197 0.2352294921875 +57198 0.318817138671875 +57199 0.358642578125 +57200 0.347747802734375 +57201 0.28564453125 +57202 0.223175048828125 +57203 0.196746826171875 +57204 0.179840087890625 +57205 0.155548095703125 +57206 0.151214599609375 +57207 0.156951904296875 +57208 0.13177490234375 +57209 0.100799560546875 +57210 0.087127685546875 +57211 0.05487060546875 +57212 -0.009002685546875 +57213 -0.10400390625 +57214 -0.229400634765625 +57215 -0.35552978515625 +57216 -0.441925048828125 +57217 -0.473846435546875 +57218 -0.464813232421875 +57219 -0.419097900390625 +57220 -0.334320068359375 +57221 -0.227935791015625 +57222 -0.12347412109375 +57223 -0.02764892578125 +57224 0.077667236328125 +57225 0.2132568359375 +57226 0.38885498046875 +57227 0.582794189453125 +57228 0.734039306640625 +57229 0.800140380859375 +57230 0.7783203125 +57231 0.6651611328125 +57232 0.45965576171875 +57233 0.199188232421875 +57234 -0.050689697265625 +57235 -0.23297119140625 +57236 -0.33013916015625 +57237 -0.368408203125 +57238 -0.378936767578125 +57239 -0.376983642578125 +57240 -0.37969970703125 +57241 -0.391510009765625 +57242 -0.385345458984375 +57243 -0.3419189453125 +57244 -0.28289794921875 +57245 -0.251617431640625 +57246 -0.266143798828125 +57247 -0.273345947265625 +57248 -0.216796875 +57249 -0.128265380859375 +57250 -0.068145751953125 +57251 -0.0430908203125 +57252 -0.024444580078125 +57253 0.020721435546875 +57254 0.124481201171875 +57255 0.25787353515625 +57256 0.379119873046875 +57257 0.47991943359375 +57258 0.5281982421875 +57259 0.511138916015625 +57260 0.456207275390625 +57261 0.407470703125 +57262 0.383758544921875 +57263 0.35687255859375 +57264 0.31182861328125 +57265 0.250885009765625 +57266 0.1654052734375 +57267 0.035247802734375 +57268 -0.142059326171875 +57269 -0.33563232421875 +57270 -0.5345458984375 +57271 -0.72186279296875 +57272 -0.836669921875 +57273 -0.8326416015625 +57274 -0.7296142578125 +57275 -0.582550048828125 +57276 -0.440093994140625 +57277 -0.324310302734375 +57278 -0.20147705078125 +57279 -0.044647216796875 +57280 0.103973388671875 +57281 0.202392578125 +57282 0.264495849609375 +57283 0.338897705078125 +57284 0.443817138671875 +57285 0.545074462890625 +57286 0.6173095703125 +57287 0.6524658203125 +57288 0.66339111328125 +57289 0.6561279296875 +57290 0.606781005859375 +57291 0.501190185546875 +57292 0.352783203125 +57293 0.176544189453125 +57294 -0.034820556640625 +57295 -0.258209228515625 +57296 -0.44244384765625 +57297 -0.5753173828125 +57298 -0.65203857421875 +57299 -0.641632080078125 +57300 -0.562164306640625 +57301 -0.458038330078125 +57302 -0.350555419921875 +57303 -0.260528564453125 +57304 -0.192108154296875 +57305 -0.141937255859375 +57306 -0.1021728515625 +57307 -0.062896728515625 +57308 -0.011932373046875 +57309 0.062835693359375 +57310 0.148712158203125 +57311 0.241729736328125 +57312 0.34912109375 +57313 0.457305908203125 +57314 0.54388427734375 +57315 0.5728759765625 +57316 0.506591796875 +57317 0.351226806640625 +57318 0.146514892578125 +57319 -0.05523681640625 +57320 -0.21624755859375 +57321 -0.334930419921875 +57322 -0.402984619140625 +57323 -0.4412841796875 +57324 -0.49578857421875 +57325 -0.5601806640625 +57326 -0.600738525390625 +57327 -0.584228515625 +57328 -0.47930908203125 +57329 -0.27935791015625 +57330 -0.0089111328125 +57331 0.268798828125 +57332 0.482818603515625 +57333 0.60369873046875 +57334 0.650421142578125 +57335 0.66400146484375 +57336 0.6414794921875 +57337 0.572540283203125 +57338 0.498138427734375 +57339 0.439453125 +57340 0.375518798828125 +57341 0.274505615234375 +57342 0.1087646484375 +57343 -0.099395751953125 +57344 -0.3182373046875 +57345 -0.5489501953125 +57346 -0.7738037109375 +57347 -0.86383056640625 +57348 -0.870391845703125 +57349 -0.86895751953125 +57350 -0.861053466796875 +57351 -0.765869140625 +57352 -0.5301513671875 +57353 -0.214691162109375 +57354 0.137359619140625 +57355 0.474822998046875 +57356 0.76239013671875 +57357 0.867462158203125 +57358 0.870361328125 +57359 0.86480712890625 +57360 0.831817626953125 +57361 0.677581787109375 +57362 0.495880126953125 +57363 0.30767822265625 +57364 0.116180419921875 +57365 -0.110748291015625 +57366 -0.381805419921875 +57367 -0.6572265625 +57368 -0.857421875 +57369 -0.870391845703125 +57370 -0.870391845703125 +57371 -0.86444091796875 +57372 -0.85723876953125 +57373 -0.790008544921875 +57374 -0.62847900390625 +57375 -0.3956298828125 +57376 -0.126708984375 +57377 0.150115966796875 +57378 0.424041748046875 +57379 0.670623779296875 +57380 0.854522705078125 +57381 0.866485595703125 +57382 0.86920166015625 +57383 0.8653564453125 +57384 0.857147216796875 +57385 0.766845703125 +57386 0.628509521484375 +57387 0.462127685546875 +57388 0.297210693359375 +57389 0.14862060546875 +57390 -0.00537109375 +57391 -0.15753173828125 +57392 -0.31304931640625 +57393 -0.48876953125 +57394 -0.6416015625 +57395 -0.751373291015625 +57396 -0.84619140625 +57397 -0.861297607421875 +57398 -0.863250732421875 +57399 -0.856597900390625 +57400 -0.7498779296875 +57401 -0.624542236328125 +57402 -0.47808837890625 +57403 -0.253387451171875 +57404 0.003692626953125 +57405 0.2257080078125 +57406 0.427154541015625 +57407 0.643218994140625 +57408 0.855926513671875 +57409 0.870361328125 +57410 0.870361328125 +57411 0.862762451171875 +57412 0.79669189453125 +57413 0.595794677734375 +57414 0.362152099609375 +57415 0.1270751953125 +57416 -0.086944580078125 +57417 -0.2784423828125 +57418 -0.484832763671875 +57419 -0.729583740234375 +57420 -0.86688232421875 +57421 -0.870391845703125 +57422 -0.86859130859375 +57423 -0.86279296875 +57424 -0.817962646484375 +57425 -0.6116943359375 +57426 -0.3128662109375 +57427 0.039398193359375 +57428 0.422821044921875 +57429 0.805145263671875 +57430 0.870361328125 +57431 0.870361328125 +57432 0.860015869140625 +57433 0.727935791015625 +57434 0.48114013671875 +57435 0.2059326171875 +57436 -0.06103515625 +57437 -0.29913330078125 +57438 -0.516204833984375 +57439 -0.7252197265625 +57440 -0.85980224609375 +57441 -0.870391845703125 +57442 -0.870391845703125 +57443 -0.858062744140625 +57444 -0.673004150390625 +57445 -0.42694091796875 +57446 -0.2100830078125 +57447 -0.0362548828125 +57448 0.10943603515625 +57449 0.23516845703125 +57450 0.373687744140625 +57451 0.517791748046875 +57452 0.602783203125 +57453 0.635711669921875 +57454 0.655181884765625 +57455 0.65948486328125 +57456 0.651275634765625 +57457 0.61846923828125 +57458 0.53753662109375 +57459 0.404144287109375 +57460 0.22186279296875 +57461 0.003997802734375 +57462 -0.22100830078125 +57463 -0.42449951171875 +57464 -0.579833984375 +57465 -0.641876220703125 +57466 -0.6177978515625 +57467 -0.575531005859375 +57468 -0.526336669921875 +57469 -0.42645263671875 +57470 -0.2581787109375 +57471 -0.068695068359375 +57472 0.09222412109375 +57473 0.232147216796875 +57474 0.3509521484375 +57475 0.410064697265625 +57476 0.372955322265625 +57477 0.2554931640625 +57478 0.10711669921875 +57479 -0.052886962890625 +57480 -0.186279296875 +57481 -0.23291015625 +57482 -0.209442138671875 +57483 -0.174163818359375 +57484 -0.126739501953125 +57485 -0.048126220703125 +57486 0.0426025390625 +57487 0.10748291015625 +57488 0.1409912109375 +57489 0.19708251953125 +57490 0.273651123046875 +57491 0.31768798828125 +57492 0.341094970703125 +57493 0.368011474609375 +57494 0.37249755859375 +57495 0.30072021484375 +57496 0.1517333984375 +57497 -0.01470947265625 +57498 -0.1883544921875 +57499 -0.372711181640625 +57500 -0.51397705078125 +57501 -0.57177734375 +57502 -0.53948974609375 +57503 -0.43511962890625 +57504 -0.2962646484375 +57505 -0.161102294921875 +57506 -0.0435791015625 +57507 0.060394287109375 +57508 0.13665771484375 +57509 0.170135498046875 +57510 0.16552734375 +57511 0.15728759765625 +57512 0.150787353515625 +57513 0.12200927734375 +57514 0.080108642578125 +57515 0.05126953125 +57516 0.062896728515625 +57517 0.09271240234375 +57518 0.092987060546875 +57519 0.07855224609375 +57520 0.06427001953125 +57521 0.0347900390625 +57522 -0.01171875 +57523 -0.056060791015625 +57524 -0.055511474609375 +57525 -0.010467529296875 +57526 0.02508544921875 +57527 0.025665283203125 +57528 0.017333984375 +57529 0.00189208984375 +57530 -0.03173828125 +57531 -0.071502685546875 +57532 -0.13543701171875 +57533 -0.219970703125 +57534 -0.300506591796875 +57535 -0.376312255859375 +57536 -0.416107177734375 +57537 -0.371124267578125 +57538 -0.242279052734375 +57539 -0.069732666015625 +57540 0.125640869140625 +57541 0.31268310546875 +57542 0.45501708984375 +57543 0.554779052734375 +57544 0.61065673828125 +57545 0.610931396484375 +57546 0.531463623046875 +57547 0.3883056640625 +57548 0.23468017578125 +57549 0.095245361328125 +57550 -0.00396728515625 +57551 -0.04852294921875 +57552 -0.055145263671875 +57553 -0.0758056640625 +57554 -0.138702392578125 +57555 -0.209197998046875 +57556 -0.289031982421875 +57557 -0.37884521484375 +57558 -0.456329345703125 +57559 -0.51641845703125 +57560 -0.519287109375 +57561 -0.458251953125 +57562 -0.384796142578125 +57563 -0.323699951171875 +57564 -0.269287109375 +57565 -0.1951904296875 +57566 -0.100006103515625 +57567 -0.01055908203125 +57568 0.1033935546875 +57569 0.24908447265625 +57570 0.373199462890625 +57571 0.45806884765625 +57572 0.511474609375 +57573 0.565399169921875 +57574 0.61138916015625 +57575 0.5897216796875 +57576 0.4906005859375 +57577 0.33148193359375 +57578 0.147796630859375 +57579 -0.01873779296875 +57580 -0.140289306640625 +57581 -0.191986083984375 +57582 -0.184295654296875 +57583 -0.161834716796875 +57584 -0.166595458984375 +57585 -0.19390869140625 +57586 -0.22442626953125 +57587 -0.279754638671875 +57588 -0.3389892578125 +57589 -0.3543701171875 +57590 -0.348175048828125 +57591 -0.32598876953125 +57592 -0.2581787109375 +57593 -0.139801025390625 +57594 0.014617919921875 +57595 0.144378662109375 +57596 0.221038818359375 +57597 0.27069091796875 +57598 0.294036865234375 +57599 0.311767578125 +57600 0.339141845703125 +57601 0.360260009765625 +57602 0.360504150390625 +57603 0.308380126953125 +57604 0.18170166015625 +57605 0.0047607421875 +57606 -0.17559814453125 +57607 -0.3143310546875 +57608 -0.36785888671875 +57609 -0.36248779296875 +57610 -0.343536376953125 +57611 -0.3018798828125 +57612 -0.231414794921875 +57613 -0.117645263671875 +57614 0.007049560546875 +57615 0.087982177734375 +57616 0.13946533203125 +57617 0.17425537109375 +57618 0.188201904296875 +57619 0.171234130859375 +57620 0.118438720703125 +57621 0.05706787109375 +57622 -0.010711669921875 +57623 -0.0914306640625 +57624 -0.162322998046875 +57625 -0.194549560546875 +57626 -0.1492919921875 +57627 -0.02166748046875 +57628 0.124053955078125 +57629 0.211151123046875 +57630 0.240447998046875 +57631 0.242218017578125 +57632 0.2257080078125 +57633 0.194366455078125 +57634 0.115509033203125 +57635 0.0128173828125 +57636 -0.053802490234375 +57637 -0.110626220703125 +57638 -0.199493408203125 +57639 -0.29437255859375 +57640 -0.33221435546875 +57641 -0.27972412109375 +57642 -0.185333251953125 +57643 -0.128204345703125 +57644 -0.115692138671875 +57645 -0.116455078125 +57646 -0.105926513671875 +57647 -0.053955078125 +57648 0.048797607421875 +57649 0.157318115234375 +57650 0.212005615234375 +57651 0.218475341796875 +57652 0.23724365234375 +57653 0.30535888671875 +57654 0.38128662109375 +57655 0.404449462890625 +57656 0.3944091796875 +57657 0.3885498046875 +57658 0.362640380859375 +57659 0.27362060546875 +57660 0.11712646484375 +57661 -0.054901123046875 +57662 -0.19085693359375 +57663 -0.28570556640625 +57664 -0.339263916015625 +57665 -0.3775634765625 +57666 -0.445709228515625 +57667 -0.535064697265625 +57668 -0.629058837890625 +57669 -0.697601318359375 +57670 -0.70391845703125 +57671 -0.6424560546875 +57672 -0.491241455078125 +57673 -0.265716552734375 +57674 -0.023712158203125 +57675 0.201751708984375 +57676 0.375823974609375 +57677 0.485076904296875 +57678 0.56884765625 +57679 0.634765625 +57680 0.63763427734375 +57681 0.5660400390625 +57682 0.4720458984375 +57683 0.40692138671875 +57684 0.3778076171875 +57685 0.376953125 +57686 0.371978759765625 +57687 0.313140869140625 +57688 0.184417724609375 +57689 0.011199951171875 +57690 -0.171051025390625 +57691 -0.33740234375 +57692 -0.47198486328125 +57693 -0.560394287109375 +57694 -0.58056640625 +57695 -0.54754638671875 +57696 -0.508575439453125 +57697 -0.459503173828125 +57698 -0.394378662109375 +57699 -0.35260009765625 +57700 -0.31170654296875 +57701 -0.197418212890625 +57702 -0.007965087890625 +57703 0.207489013671875 +57704 0.409210205078125 +57705 0.57208251953125 +57706 0.66595458984375 +57707 0.65875244140625 +57708 0.56744384765625 +57709 0.431396484375 +57710 0.29443359375 +57711 0.182464599609375 +57712 0.06365966796875 +57713 -0.075958251953125 +57714 -0.189422607421875 +57715 -0.271942138671875 +57716 -0.342529296875 +57717 -0.364166259765625 +57718 -0.327239990234375 +57719 -0.2769775390625 +57720 -0.253692626953125 +57721 -0.24365234375 +57722 -0.1983642578125 +57723 -0.116241455078125 +57724 -0.036834716796875 +57725 0.034881591796875 +57726 0.09124755859375 +57727 0.10888671875 +57728 0.125518798828125 +57729 0.15771484375 +57730 0.17828369140625 +57731 0.17108154296875 +57732 0.129974365234375 +57733 0.082427978515625 +57734 0.027679443359375 +57735 -0.065643310546875 +57736 -0.15936279296875 +57737 -0.21307373046875 +57738 -0.234649658203125 +57739 -0.2001953125 +57740 -0.119171142578125 +57741 -0.024749755859375 +57742 0.085784912109375 +57743 0.178131103515625 +57744 0.215576171875 +57745 0.211456298828125 +57746 0.17523193359375 +57747 0.128753662109375 +57748 0.1019287109375 +57749 0.0743408203125 +57750 0.04327392578125 +57751 0.038177490234375 +57752 0.076263427734375 +57753 0.14105224609375 +57754 0.186431884765625 +57755 0.188812255859375 +57756 0.1390380859375 +57757 0.041778564453125 +57758 -0.079437255859375 +57759 -0.219390869140625 +57760 -0.367828369140625 +57761 -0.494873046875 +57762 -0.556243896484375 +57763 -0.508697509765625 +57764 -0.3756103515625 +57765 -0.218902587890625 +57766 -0.063751220703125 +57767 0.091552734375 +57768 0.23602294921875 +57769 0.342987060546875 +57770 0.39520263671875 +57771 0.389373779296875 +57772 0.324249267578125 +57773 0.224090576171875 +57774 0.124267578125 +57775 0.037078857421875 +57776 -0.010101318359375 +57777 -0.019439697265625 +57778 -0.022796630859375 +57779 -0.001556396484375 +57780 0.056304931640625 +57781 0.106719970703125 +57782 0.096893310546875 +57783 0.042694091796875 +57784 -0.018035888671875 +57785 -0.07586669921875 +57786 -0.11944580078125 +57787 -0.15972900390625 +57788 -0.202606201171875 +57789 -0.24859619140625 +57790 -0.30517578125 +57791 -0.36212158203125 +57792 -0.39141845703125 +57793 -0.35528564453125 +57794 -0.249969482421875 +57795 -0.092864990234375 +57796 0.08905029296875 +57797 0.2352294921875 +57798 0.318817138671875 +57799 0.358642578125 +57800 0.347747802734375 +57801 0.28564453125 +57802 0.223175048828125 +57803 0.196746826171875 +57804 0.179840087890625 +57805 0.155548095703125 +57806 0.151214599609375 +57807 0.156951904296875 +57808 0.13177490234375 +57809 0.100799560546875 +57810 0.087127685546875 +57811 0.05487060546875 +57812 -0.009002685546875 +57813 -0.10400390625 +57814 -0.229400634765625 +57815 -0.35552978515625 +57816 -0.441925048828125 +57817 -0.473846435546875 +57818 -0.464813232421875 +57819 -0.419097900390625 +57820 -0.334320068359375 +57821 -0.227935791015625 +57822 -0.12347412109375 +57823 -0.02764892578125 +57824 0.077667236328125 +57825 0.2132568359375 +57826 0.38885498046875 +57827 0.582794189453125 +57828 0.734039306640625 +57829 0.800140380859375 +57830 0.7783203125 +57831 0.6651611328125 +57832 0.45965576171875 +57833 0.199188232421875 +57834 -0.050689697265625 +57835 -0.23297119140625 +57836 -0.33013916015625 +57837 -0.368408203125 +57838 -0.378936767578125 +57839 -0.376983642578125 +57840 -0.37969970703125 +57841 -0.391510009765625 +57842 -0.385345458984375 +57843 -0.3419189453125 +57844 -0.28289794921875 +57845 -0.251617431640625 +57846 -0.266143798828125 +57847 -0.273345947265625 +57848 -0.216796875 +57849 -0.128265380859375 +57850 -0.068145751953125 +57851 -0.0430908203125 +57852 -0.024444580078125 +57853 0.020721435546875 +57854 0.124481201171875 +57855 0.25787353515625 +57856 0.379119873046875 +57857 0.47991943359375 +57858 0.5281982421875 +57859 0.511138916015625 +57860 0.456207275390625 +57861 0.407470703125 +57862 0.383758544921875 +57863 0.35687255859375 +57864 0.31182861328125 +57865 0.250885009765625 +57866 0.1654052734375 +57867 0.035247802734375 +57868 -0.142059326171875 +57869 -0.33563232421875 +57870 -0.5345458984375 +57871 -0.72186279296875 +57872 -0.836669921875 +57873 -0.8326416015625 +57874 -0.7296142578125 +57875 -0.582550048828125 +57876 -0.440093994140625 +57877 -0.324310302734375 +57878 -0.20147705078125 +57879 -0.044647216796875 +57880 0.103973388671875 +57881 0.202392578125 +57882 0.264495849609375 +57883 0.338897705078125 +57884 0.443817138671875 +57885 0.545074462890625 +57886 0.6173095703125 +57887 0.6524658203125 +57888 0.66339111328125 +57889 0.6561279296875 +57890 0.606781005859375 +57891 0.501190185546875 +57892 0.352783203125 +57893 0.176544189453125 +57894 -0.034820556640625 +57895 -0.258209228515625 +57896 -0.44244384765625 +57897 -0.5753173828125 +57898 -0.65203857421875 +57899 -0.641632080078125 +57900 -0.562164306640625 +57901 -0.458038330078125 +57902 -0.350555419921875 +57903 -0.260528564453125 +57904 -0.192108154296875 +57905 -0.141937255859375 +57906 -0.1021728515625 +57907 -0.062896728515625 +57908 -0.011932373046875 +57909 0.062835693359375 +57910 0.148712158203125 +57911 0.241729736328125 +57912 0.34912109375 +57913 0.457305908203125 +57914 0.54388427734375 +57915 0.5728759765625 +57916 0.506591796875 +57917 0.351226806640625 +57918 0.146514892578125 +57919 -0.05523681640625 +57920 -0.21624755859375 +57921 -0.334930419921875 +57922 -0.402984619140625 +57923 -0.4412841796875 +57924 -0.49578857421875 +57925 -0.5601806640625 +57926 -0.600738525390625 +57927 -0.584228515625 +57928 -0.47930908203125 +57929 -0.27935791015625 +57930 -0.0089111328125 +57931 0.268798828125 +57932 0.482818603515625 +57933 0.60369873046875 +57934 0.650421142578125 +57935 0.66400146484375 +57936 0.6414794921875 +57937 0.572540283203125 +57938 0.498138427734375 +57939 0.439453125 +57940 0.375518798828125 +57941 0.274505615234375 +57942 0.1087646484375 +57943 -0.099395751953125 +57944 -0.3182373046875 +57945 -0.5489501953125 +57946 -0.7738037109375 +57947 -0.86383056640625 +57948 -0.870391845703125 +57949 -0.86895751953125 +57950 -0.861053466796875 +57951 -0.765869140625 +57952 -0.5301513671875 +57953 -0.214691162109375 +57954 0.137359619140625 +57955 0.474822998046875 +57956 0.76239013671875 +57957 0.867462158203125 +57958 0.870361328125 +57959 0.86480712890625 +57960 0.831817626953125 +57961 0.677581787109375 +57962 0.495880126953125 +57963 0.30767822265625 +57964 0.116180419921875 +57965 -0.110748291015625 +57966 -0.381805419921875 +57967 -0.6572265625 +57968 -0.857421875 +57969 -0.870391845703125 +57970 -0.870391845703125 +57971 -0.86444091796875 +57972 -0.85723876953125 +57973 -0.790008544921875 +57974 -0.62847900390625 +57975 -0.3956298828125 +57976 -0.126708984375 +57977 0.150115966796875 +57978 0.424041748046875 +57979 0.670623779296875 +57980 0.854522705078125 +57981 0.866485595703125 +57982 0.86920166015625 +57983 0.8653564453125 +57984 0.857147216796875 +57985 0.766845703125 +57986 0.628509521484375 +57987 0.462127685546875 +57988 0.297210693359375 +57989 0.14862060546875 +57990 -0.00537109375 +57991 -0.15753173828125 +57992 -0.31304931640625 +57993 -0.48876953125 +57994 -0.6416015625 +57995 -0.751373291015625 +57996 -0.84619140625 +57997 -0.861297607421875 +57998 -0.863250732421875 +57999 -0.856597900390625 +58000 -0.7498779296875 +58001 -0.624542236328125 +58002 -0.47808837890625 +58003 -0.253387451171875 +58004 0.003692626953125 +58005 0.2257080078125 +58006 0.427154541015625 +58007 0.643218994140625 +58008 0.855926513671875 +58009 0.870361328125 +58010 0.870361328125 +58011 0.862762451171875 +58012 0.79669189453125 +58013 0.595794677734375 +58014 0.362152099609375 +58015 0.1270751953125 +58016 -0.086944580078125 +58017 -0.2784423828125 +58018 -0.484832763671875 +58019 -0.729583740234375 +58020 -0.86688232421875 +58021 -0.870391845703125 +58022 -0.86859130859375 +58023 -0.86279296875 +58024 -0.817962646484375 +58025 -0.6116943359375 +58026 -0.3128662109375 +58027 0.039398193359375 +58028 0.422821044921875 +58029 0.805145263671875 +58030 0.870361328125 +58031 0.870361328125 +58032 0.860015869140625 +58033 0.727935791015625 +58034 0.48114013671875 +58035 0.2059326171875 +58036 -0.06103515625 +58037 -0.29913330078125 +58038 -0.516204833984375 +58039 -0.7252197265625 +58040 -0.85980224609375 +58041 -0.870391845703125 +58042 -0.870391845703125 +58043 -0.858062744140625 +58044 -0.673004150390625 +58045 -0.42694091796875 +58046 -0.2100830078125 +58047 -0.0362548828125 +58048 0.10943603515625 +58049 0.23516845703125 +58050 0.373687744140625 +58051 0.517791748046875 +58052 0.602783203125 +58053 0.635711669921875 +58054 0.655181884765625 +58055 0.65948486328125 +58056 0.651275634765625 +58057 0.61846923828125 +58058 0.53753662109375 +58059 0.404144287109375 +58060 0.22186279296875 +58061 0.003997802734375 +58062 -0.22100830078125 +58063 -0.42449951171875 +58064 -0.579833984375 +58065 -0.641876220703125 +58066 -0.6177978515625 +58067 -0.575531005859375 +58068 -0.526336669921875 +58069 -0.42645263671875 +58070 -0.2581787109375 +58071 -0.068695068359375 +58072 0.09222412109375 +58073 0.232147216796875 +58074 0.3509521484375 +58075 0.410064697265625 +58076 0.372955322265625 +58077 0.2554931640625 +58078 0.10711669921875 +58079 -0.052886962890625 +58080 -0.186279296875 +58081 -0.23291015625 +58082 -0.209442138671875 +58083 -0.174163818359375 +58084 -0.126739501953125 +58085 -0.048126220703125 +58086 0.0426025390625 +58087 0.10748291015625 +58088 0.1409912109375 +58089 0.19708251953125 +58090 0.273651123046875 +58091 0.31768798828125 +58092 0.341094970703125 +58093 0.368011474609375 +58094 0.37249755859375 +58095 0.30072021484375 +58096 0.1517333984375 +58097 -0.01470947265625 +58098 -0.1883544921875 +58099 -0.372711181640625 +58100 -0.51397705078125 +58101 -0.57177734375 +58102 -0.53948974609375 +58103 -0.43511962890625 +58104 -0.2962646484375 +58105 -0.161102294921875 +58106 -0.0435791015625 +58107 0.060394287109375 +58108 0.13665771484375 +58109 0.170135498046875 +58110 0.16552734375 +58111 0.15728759765625 +58112 0.150787353515625 +58113 0.12200927734375 +58114 0.080108642578125 +58115 0.05126953125 +58116 0.062896728515625 +58117 0.09271240234375 +58118 0.092987060546875 +58119 0.07855224609375 +58120 0.06427001953125 +58121 0.0347900390625 +58122 -0.01171875 +58123 -0.056060791015625 +58124 -0.055511474609375 +58125 -0.010467529296875 +58126 0.02508544921875 +58127 0.025665283203125 +58128 0.017333984375 +58129 0.00189208984375 +58130 -0.03173828125 +58131 -0.071502685546875 +58132 -0.13543701171875 +58133 -0.219970703125 +58134 -0.300506591796875 +58135 -0.376312255859375 +58136 -0.416107177734375 +58137 -0.371124267578125 +58138 -0.242279052734375 +58139 -0.069732666015625 +58140 0.125640869140625 +58141 0.31268310546875 +58142 0.45501708984375 +58143 0.554779052734375 +58144 0.61065673828125 +58145 0.610931396484375 +58146 0.531463623046875 +58147 0.3883056640625 +58148 0.23468017578125 +58149 0.095245361328125 +58150 -0.00396728515625 +58151 -0.04852294921875 +58152 -0.055145263671875 +58153 -0.0758056640625 +58154 -0.138702392578125 +58155 -0.209197998046875 +58156 -0.289031982421875 +58157 -0.37884521484375 +58158 -0.456329345703125 +58159 -0.51641845703125 +58160 -0.519287109375 +58161 -0.458251953125 +58162 -0.384796142578125 +58163 -0.323699951171875 +58164 -0.269287109375 +58165 -0.1951904296875 +58166 -0.100006103515625 +58167 -0.01055908203125 +58168 0.1033935546875 +58169 0.24908447265625 +58170 0.373199462890625 +58171 0.45806884765625 +58172 0.511474609375 +58173 0.565399169921875 +58174 0.61138916015625 +58175 0.5897216796875 +58176 0.4906005859375 +58177 0.33148193359375 +58178 0.147796630859375 +58179 -0.01873779296875 +58180 -0.140289306640625 +58181 -0.191986083984375 +58182 -0.184295654296875 +58183 -0.161834716796875 +58184 -0.166595458984375 +58185 -0.19390869140625 +58186 -0.22442626953125 +58187 -0.279754638671875 +58188 -0.3389892578125 +58189 -0.3543701171875 +58190 -0.348175048828125 +58191 -0.32598876953125 +58192 -0.2581787109375 +58193 -0.139801025390625 +58194 0.014617919921875 +58195 0.144378662109375 +58196 0.221038818359375 +58197 0.27069091796875 +58198 0.294036865234375 +58199 0.311767578125 +58200 0.339141845703125 +58201 0.360260009765625 +58202 0.360504150390625 +58203 0.308380126953125 +58204 0.18170166015625 +58205 0.0047607421875 +58206 -0.17559814453125 +58207 -0.3143310546875 +58208 -0.36785888671875 +58209 -0.36248779296875 +58210 -0.343536376953125 +58211 -0.3018798828125 +58212 -0.231414794921875 +58213 -0.117645263671875 +58214 0.007049560546875 +58215 0.087982177734375 +58216 0.13946533203125 +58217 0.17425537109375 +58218 0.188201904296875 +58219 0.171234130859375 +58220 0.118438720703125 +58221 0.05706787109375 +58222 -0.010711669921875 +58223 -0.0914306640625 +58224 -0.162322998046875 +58225 -0.194549560546875 +58226 -0.1492919921875 +58227 -0.02166748046875 +58228 0.124053955078125 +58229 0.211151123046875 +58230 0.240447998046875 +58231 0.242218017578125 +58232 0.2257080078125 +58233 0.194366455078125 +58234 0.115509033203125 +58235 0.0128173828125 +58236 -0.053802490234375 +58237 -0.110626220703125 +58238 -0.199493408203125 +58239 -0.29437255859375 +58240 -0.33221435546875 +58241 -0.27972412109375 +58242 -0.185333251953125 +58243 -0.128204345703125 +58244 -0.115692138671875 +58245 -0.116455078125 +58246 -0.105926513671875 +58247 -0.053955078125 +58248 0.048797607421875 +58249 0.157318115234375 +58250 0.212005615234375 +58251 0.218475341796875 +58252 0.23724365234375 +58253 0.30535888671875 +58254 0.38128662109375 +58255 0.404449462890625 +58256 0.3944091796875 +58257 0.3885498046875 +58258 0.362640380859375 +58259 0.27362060546875 +58260 0.11712646484375 +58261 -0.054901123046875 +58262 -0.19085693359375 +58263 -0.28570556640625 +58264 -0.339263916015625 +58265 -0.3775634765625 +58266 -0.445709228515625 +58267 -0.535064697265625 +58268 -0.629058837890625 +58269 -0.697601318359375 +58270 -0.70391845703125 +58271 -0.6424560546875 +58272 -0.491241455078125 +58273 -0.265716552734375 +58274 -0.023712158203125 +58275 0.201751708984375 +58276 0.375823974609375 +58277 0.485076904296875 +58278 0.56884765625 +58279 0.634765625 +58280 0.63763427734375 +58281 0.5660400390625 +58282 0.4720458984375 +58283 0.40692138671875 +58284 0.3778076171875 +58285 0.376953125 +58286 0.371978759765625 +58287 0.313140869140625 +58288 0.184417724609375 +58289 0.011199951171875 +58290 -0.171051025390625 +58291 -0.33740234375 +58292 -0.47198486328125 +58293 -0.560394287109375 +58294 -0.58056640625 +58295 -0.54754638671875 +58296 -0.508575439453125 +58297 -0.459503173828125 +58298 -0.394378662109375 +58299 -0.35260009765625 +58300 -0.31170654296875 +58301 -0.197418212890625 +58302 -0.007965087890625 +58303 0.207489013671875 +58304 0.409210205078125 +58305 0.57208251953125 +58306 0.66595458984375 +58307 0.65875244140625 +58308 0.56744384765625 +58309 0.431396484375 +58310 0.29443359375 +58311 0.182464599609375 +58312 0.06365966796875 +58313 -0.075958251953125 +58314 -0.189422607421875 +58315 -0.271942138671875 +58316 -0.342529296875 +58317 -0.364166259765625 +58318 -0.327239990234375 +58319 -0.2769775390625 +58320 -0.253692626953125 +58321 -0.24365234375 +58322 -0.1983642578125 +58323 -0.116241455078125 +58324 -0.036834716796875 +58325 0.034881591796875 +58326 0.09124755859375 +58327 0.10888671875 +58328 0.125518798828125 +58329 0.15771484375 +58330 0.17828369140625 +58331 0.17108154296875 +58332 0.129974365234375 +58333 0.082427978515625 +58334 0.027679443359375 +58335 -0.065643310546875 +58336 -0.15936279296875 +58337 -0.21307373046875 +58338 -0.234649658203125 +58339 -0.2001953125 +58340 -0.119171142578125 +58341 -0.024749755859375 +58342 0.085784912109375 +58343 0.178131103515625 +58344 0.215576171875 +58345 0.211456298828125 +58346 0.17523193359375 +58347 0.128753662109375 +58348 0.1019287109375 +58349 0.0743408203125 +58350 0.04327392578125 +58351 0.038177490234375 +58352 0.076263427734375 +58353 0.14105224609375 +58354 0.186431884765625 +58355 0.188812255859375 +58356 0.1390380859375 +58357 0.041778564453125 +58358 -0.079437255859375 +58359 -0.219390869140625 +58360 -0.367828369140625 +58361 -0.494873046875 +58362 -0.556243896484375 +58363 -0.508697509765625 +58364 -0.3756103515625 +58365 -0.218902587890625 +58366 -0.063751220703125 +58367 0.091552734375 +58368 0.23602294921875 +58369 0.342987060546875 +58370 0.39520263671875 +58371 0.389373779296875 +58372 0.324249267578125 +58373 0.224090576171875 +58374 0.124267578125 +58375 0.037078857421875 +58376 -0.010101318359375 +58377 -0.019439697265625 +58378 -0.022796630859375 +58379 -0.001556396484375 +58380 0.056304931640625 +58381 0.106719970703125 +58382 0.096893310546875 +58383 0.042694091796875 +58384 -0.018035888671875 +58385 -0.07586669921875 +58386 -0.11944580078125 +58387 -0.15972900390625 +58388 -0.202606201171875 +58389 -0.24859619140625 +58390 -0.30517578125 +58391 -0.36212158203125 +58392 -0.39141845703125 +58393 -0.35528564453125 +58394 -0.249969482421875 +58395 -0.092864990234375 +58396 0.08905029296875 +58397 0.2352294921875 +58398 0.318817138671875 +58399 0.358642578125 +58400 0.347747802734375 +58401 0.28564453125 +58402 0.223175048828125 +58403 0.196746826171875 +58404 0.179840087890625 +58405 0.155548095703125 +58406 0.151214599609375 +58407 0.156951904296875 +58408 0.13177490234375 +58409 0.100799560546875 +58410 0.087127685546875 +58411 0.05487060546875 +58412 -0.009002685546875 +58413 -0.10400390625 +58414 -0.229400634765625 +58415 -0.35552978515625 +58416 -0.441925048828125 +58417 -0.473846435546875 +58418 -0.464813232421875 +58419 -0.419097900390625 +58420 -0.334320068359375 +58421 -0.227935791015625 +58422 -0.12347412109375 +58423 -0.02764892578125 +58424 0.077667236328125 +58425 0.2132568359375 +58426 0.38885498046875 +58427 0.582794189453125 +58428 0.734039306640625 +58429 0.800140380859375 +58430 0.7783203125 +58431 0.6651611328125 +58432 0.45965576171875 +58433 0.199188232421875 +58434 -0.050689697265625 +58435 -0.23297119140625 +58436 -0.33013916015625 +58437 -0.368408203125 +58438 -0.378936767578125 +58439 -0.376983642578125 +58440 -0.37969970703125 +58441 -0.391510009765625 +58442 -0.385345458984375 +58443 -0.3419189453125 +58444 -0.28289794921875 +58445 -0.251617431640625 +58446 -0.266143798828125 +58447 -0.273345947265625 +58448 -0.216796875 +58449 -0.128265380859375 +58450 -0.068145751953125 +58451 -0.0430908203125 +58452 -0.024444580078125 +58453 0.020721435546875 +58454 0.124481201171875 +58455 0.25787353515625 +58456 0.379119873046875 +58457 0.47991943359375 +58458 0.5281982421875 +58459 0.511138916015625 +58460 0.456207275390625 +58461 0.407470703125 +58462 0.383758544921875 +58463 0.35687255859375 +58464 0.31182861328125 +58465 0.250885009765625 +58466 0.1654052734375 +58467 0.035247802734375 +58468 -0.142059326171875 +58469 -0.33563232421875 +58470 -0.5345458984375 +58471 -0.72186279296875 +58472 -0.836669921875 +58473 -0.8326416015625 +58474 -0.7296142578125 +58475 -0.582550048828125 +58476 -0.440093994140625 +58477 -0.324310302734375 +58478 -0.20147705078125 +58479 -0.044647216796875 +58480 0.103973388671875 +58481 0.202392578125 +58482 0.264495849609375 +58483 0.338897705078125 +58484 0.443817138671875 +58485 0.545074462890625 +58486 0.6173095703125 +58487 0.6524658203125 +58488 0.66339111328125 +58489 0.6561279296875 +58490 0.606781005859375 +58491 0.501190185546875 +58492 0.352783203125 +58493 0.176544189453125 +58494 -0.034820556640625 +58495 -0.258209228515625 +58496 -0.44244384765625 +58497 -0.5753173828125 +58498 -0.65203857421875 +58499 -0.641632080078125 +58500 -0.562164306640625 +58501 -0.458038330078125 +58502 -0.350555419921875 +58503 -0.260528564453125 +58504 -0.192108154296875 +58505 -0.141937255859375 +58506 -0.1021728515625 +58507 -0.062896728515625 +58508 -0.011932373046875 +58509 0.062835693359375 +58510 0.148712158203125 +58511 0.241729736328125 +58512 0.34912109375 +58513 0.457305908203125 +58514 0.54388427734375 +58515 0.5728759765625 +58516 0.506591796875 +58517 0.351226806640625 +58518 0.146514892578125 +58519 -0.05523681640625 +58520 -0.21624755859375 +58521 -0.334930419921875 +58522 -0.402984619140625 +58523 -0.4412841796875 +58524 -0.49578857421875 +58525 -0.5601806640625 +58526 -0.600738525390625 +58527 -0.584228515625 +58528 -0.47930908203125 +58529 -0.27935791015625 +58530 -0.0089111328125 +58531 0.268798828125 +58532 0.482818603515625 +58533 0.60369873046875 +58534 0.650421142578125 +58535 0.66400146484375 +58536 0.6414794921875 +58537 0.572540283203125 +58538 0.498138427734375 +58539 0.439453125 +58540 0.375518798828125 +58541 0.274505615234375 +58542 0.1087646484375 +58543 -0.099395751953125 +58544 -0.3182373046875 +58545 -0.5489501953125 +58546 -0.7738037109375 +58547 -0.86383056640625 +58548 -0.870391845703125 +58549 -0.86895751953125 +58550 -0.861053466796875 +58551 -0.765869140625 +58552 -0.5301513671875 +58553 -0.214691162109375 +58554 0.137359619140625 +58555 0.474822998046875 +58556 0.76239013671875 +58557 0.867462158203125 +58558 0.870361328125 +58559 0.86480712890625 +58560 0.831817626953125 +58561 0.677581787109375 +58562 0.495880126953125 +58563 0.30767822265625 +58564 0.116180419921875 +58565 -0.110748291015625 +58566 -0.381805419921875 +58567 -0.6572265625 +58568 -0.857421875 +58569 -0.870391845703125 +58570 -0.870391845703125 +58571 -0.86444091796875 +58572 -0.85723876953125 +58573 -0.790008544921875 +58574 -0.62847900390625 +58575 -0.3956298828125 +58576 -0.126708984375 +58577 0.150115966796875 +58578 0.424041748046875 +58579 0.670623779296875 +58580 0.854522705078125 +58581 0.866485595703125 +58582 0.86920166015625 +58583 0.8653564453125 +58584 0.857147216796875 +58585 0.766845703125 +58586 0.628509521484375 +58587 0.462127685546875 +58588 0.297210693359375 +58589 0.14862060546875 +58590 -0.00537109375 +58591 -0.15753173828125 +58592 -0.31304931640625 +58593 -0.48876953125 +58594 -0.6416015625 +58595 -0.751373291015625 +58596 -0.84619140625 +58597 -0.861297607421875 +58598 -0.863250732421875 +58599 -0.856597900390625 +58600 -0.7498779296875 +58601 -0.624542236328125 +58602 -0.47808837890625 +58603 -0.253387451171875 +58604 0.003692626953125 +58605 0.2257080078125 +58606 0.427154541015625 +58607 0.643218994140625 +58608 0.855926513671875 +58609 0.870361328125 +58610 0.870361328125 +58611 0.862762451171875 +58612 0.79669189453125 +58613 0.595794677734375 +58614 0.362152099609375 +58615 0.1270751953125 +58616 -0.086944580078125 +58617 -0.2784423828125 +58618 -0.484832763671875 +58619 -0.729583740234375 +58620 -0.86688232421875 +58621 -0.870391845703125 +58622 -0.86859130859375 +58623 -0.86279296875 +58624 -0.817962646484375 +58625 -0.6116943359375 +58626 -0.3128662109375 +58627 0.039398193359375 +58628 0.422821044921875 +58629 0.805145263671875 +58630 0.870361328125 +58631 0.870361328125 +58632 0.860015869140625 +58633 0.727935791015625 +58634 0.48114013671875 +58635 0.2059326171875 +58636 -0.06103515625 +58637 -0.29913330078125 +58638 -0.516204833984375 +58639 -0.7252197265625 +58640 -0.85980224609375 +58641 -0.870391845703125 +58642 -0.870391845703125 +58643 -0.858062744140625 +58644 -0.673004150390625 +58645 -0.42694091796875 +58646 -0.2100830078125 +58647 -0.0362548828125 +58648 0.10943603515625 +58649 0.23516845703125 +58650 0.373687744140625 +58651 0.517791748046875 +58652 0.602783203125 +58653 0.635711669921875 +58654 0.655181884765625 +58655 0.65948486328125 +58656 0.651275634765625 +58657 0.61846923828125 +58658 0.53753662109375 +58659 0.404144287109375 +58660 0.22186279296875 +58661 0.003997802734375 +58662 -0.22100830078125 +58663 -0.42449951171875 +58664 -0.579833984375 +58665 -0.641876220703125 +58666 -0.6177978515625 +58667 -0.575531005859375 +58668 -0.526336669921875 +58669 -0.42645263671875 +58670 -0.2581787109375 +58671 -0.068695068359375 +58672 0.09222412109375 +58673 0.232147216796875 +58674 0.3509521484375 +58675 0.410064697265625 +58676 0.372955322265625 +58677 0.2554931640625 +58678 0.10711669921875 +58679 -0.052886962890625 +58680 -0.186279296875 +58681 -0.23291015625 +58682 -0.209442138671875 +58683 -0.174163818359375 +58684 -0.126739501953125 +58685 -0.048126220703125 +58686 0.0426025390625 +58687 0.10748291015625 +58688 0.1409912109375 +58689 0.19708251953125 +58690 0.273651123046875 +58691 0.31768798828125 +58692 0.341094970703125 +58693 0.368011474609375 +58694 0.37249755859375 +58695 0.30072021484375 +58696 0.1517333984375 +58697 -0.01470947265625 +58698 -0.1883544921875 +58699 -0.372711181640625 +58700 -0.51397705078125 +58701 -0.57177734375 +58702 -0.53948974609375 +58703 -0.43511962890625 +58704 -0.2962646484375 +58705 -0.161102294921875 +58706 -0.0435791015625 +58707 0.060394287109375 +58708 0.13665771484375 +58709 0.170135498046875 +58710 0.16552734375 +58711 0.15728759765625 +58712 0.150787353515625 +58713 0.12200927734375 +58714 0.080108642578125 +58715 0.05126953125 +58716 0.062896728515625 +58717 0.09271240234375 +58718 0.092987060546875 +58719 0.07855224609375 +58720 0.06427001953125 +58721 0.0347900390625 +58722 -0.01171875 +58723 -0.056060791015625 +58724 -0.055511474609375 +58725 -0.010467529296875 +58726 0.02508544921875 +58727 0.025665283203125 +58728 0.017333984375 +58729 0.00189208984375 +58730 -0.03173828125 +58731 -0.071502685546875 +58732 -0.13543701171875 +58733 -0.219970703125 +58734 -0.300506591796875 +58735 -0.376312255859375 +58736 -0.416107177734375 +58737 -0.371124267578125 +58738 -0.242279052734375 +58739 -0.069732666015625 +58740 0.125640869140625 +58741 0.31268310546875 +58742 0.45501708984375 +58743 0.554779052734375 +58744 0.61065673828125 +58745 0.610931396484375 +58746 0.531463623046875 +58747 0.3883056640625 +58748 0.23468017578125 +58749 0.095245361328125 +58750 -0.00396728515625 +58751 -0.04852294921875 +58752 -0.055145263671875 +58753 -0.0758056640625 +58754 -0.138702392578125 +58755 -0.209197998046875 +58756 -0.289031982421875 +58757 -0.37884521484375 +58758 -0.456329345703125 +58759 -0.51641845703125 +58760 -0.519287109375 +58761 -0.458251953125 +58762 -0.384796142578125 +58763 -0.323699951171875 +58764 -0.269287109375 +58765 -0.1951904296875 +58766 -0.100006103515625 +58767 -0.01055908203125 +58768 0.1033935546875 +58769 0.24908447265625 +58770 0.373199462890625 +58771 0.45806884765625 +58772 0.511474609375 +58773 0.565399169921875 +58774 0.61138916015625 +58775 0.5897216796875 +58776 0.4906005859375 +58777 0.33148193359375 +58778 0.147796630859375 +58779 -0.01873779296875 +58780 -0.140289306640625 +58781 -0.191986083984375 +58782 -0.184295654296875 +58783 -0.161834716796875 +58784 -0.166595458984375 +58785 -0.19390869140625 +58786 -0.22442626953125 +58787 -0.279754638671875 +58788 -0.3389892578125 +58789 -0.3543701171875 +58790 -0.348175048828125 +58791 -0.32598876953125 +58792 -0.2581787109375 +58793 -0.139801025390625 +58794 0.014617919921875 +58795 0.144378662109375 +58796 0.221038818359375 +58797 0.27069091796875 +58798 0.294036865234375 +58799 0.311767578125 +58800 0.339141845703125 +58801 0.360260009765625 +58802 0.360504150390625 +58803 0.308380126953125 +58804 0.18170166015625 +58805 0.0047607421875 +58806 -0.17559814453125 +58807 -0.3143310546875 +58808 -0.36785888671875 +58809 -0.36248779296875 +58810 -0.343536376953125 +58811 -0.3018798828125 +58812 -0.231414794921875 +58813 -0.117645263671875 +58814 0.007049560546875 +58815 0.087982177734375 +58816 0.13946533203125 +58817 0.17425537109375 +58818 0.188201904296875 +58819 0.171234130859375 +58820 0.118438720703125 +58821 0.05706787109375 +58822 -0.010711669921875 +58823 -0.0914306640625 +58824 -0.162322998046875 +58825 -0.194549560546875 +58826 -0.1492919921875 +58827 -0.02166748046875 +58828 0.124053955078125 +58829 0.211151123046875 +58830 0.240447998046875 +58831 0.242218017578125 +58832 0.2257080078125 +58833 0.194366455078125 +58834 0.115509033203125 +58835 0.0128173828125 +58836 -0.053802490234375 +58837 -0.110626220703125 +58838 -0.199493408203125 +58839 -0.29437255859375 +58840 -0.33221435546875 +58841 -0.27972412109375 +58842 -0.185333251953125 +58843 -0.128204345703125 +58844 -0.115692138671875 +58845 -0.116455078125 +58846 -0.105926513671875 +58847 -0.053955078125 +58848 0.048797607421875 +58849 0.157318115234375 +58850 0.212005615234375 +58851 0.218475341796875 +58852 0.23724365234375 +58853 0.30535888671875 +58854 0.38128662109375 +58855 0.404449462890625 +58856 0.3944091796875 +58857 0.3885498046875 +58858 0.362640380859375 +58859 0.27362060546875 +58860 0.11712646484375 +58861 -0.054901123046875 +58862 -0.19085693359375 +58863 -0.28570556640625 +58864 -0.339263916015625 +58865 -0.3775634765625 +58866 -0.445709228515625 +58867 -0.535064697265625 +58868 -0.629058837890625 +58869 -0.697601318359375 +58870 -0.70391845703125 +58871 -0.6424560546875 +58872 -0.491241455078125 +58873 -0.265716552734375 +58874 -0.023712158203125 +58875 0.201751708984375 +58876 0.375823974609375 +58877 0.485076904296875 +58878 0.56884765625 +58879 0.634765625 +58880 0.63763427734375 +58881 0.5660400390625 +58882 0.4720458984375 +58883 0.40692138671875 +58884 0.3778076171875 +58885 0.376953125 +58886 0.371978759765625 +58887 0.313140869140625 +58888 0.184417724609375 +58889 0.011199951171875 +58890 -0.171051025390625 +58891 -0.33740234375 +58892 -0.47198486328125 +58893 -0.560394287109375 +58894 -0.58056640625 +58895 -0.54754638671875 +58896 -0.508575439453125 +58897 -0.459503173828125 +58898 -0.394378662109375 +58899 -0.35260009765625 +58900 -0.31170654296875 +58901 -0.197418212890625 +58902 -0.007965087890625 +58903 0.207489013671875 +58904 0.409210205078125 +58905 0.57208251953125 +58906 0.66595458984375 +58907 0.65875244140625 +58908 0.56744384765625 +58909 0.431396484375 +58910 0.29443359375 +58911 0.182464599609375 +58912 0.06365966796875 +58913 -0.075958251953125 +58914 -0.189422607421875 +58915 -0.271942138671875 +58916 -0.342529296875 +58917 -0.364166259765625 +58918 -0.327239990234375 +58919 -0.2769775390625 +58920 -0.253692626953125 +58921 -0.24365234375 +58922 -0.1983642578125 +58923 -0.116241455078125 +58924 -0.036834716796875 +58925 0.034881591796875 +58926 0.09124755859375 +58927 0.10888671875 +58928 0.125518798828125 +58929 0.15771484375 +58930 0.17828369140625 +58931 0.17108154296875 +58932 0.129974365234375 +58933 0.082427978515625 +58934 0.027679443359375 +58935 -0.065643310546875 +58936 -0.15936279296875 +58937 -0.21307373046875 +58938 -0.234649658203125 +58939 -0.2001953125 +58940 -0.119171142578125 +58941 -0.024749755859375 +58942 0.085784912109375 +58943 0.178131103515625 +58944 0.215576171875 +58945 0.211456298828125 +58946 0.17523193359375 +58947 0.128753662109375 +58948 0.1019287109375 +58949 0.0743408203125 +58950 0.04327392578125 +58951 0.038177490234375 +58952 0.076263427734375 +58953 0.14105224609375 +58954 0.186431884765625 +58955 0.188812255859375 +58956 0.1390380859375 +58957 0.041778564453125 +58958 -0.079437255859375 +58959 -0.219390869140625 +58960 -0.367828369140625 +58961 -0.494873046875 +58962 -0.556243896484375 +58963 -0.508697509765625 +58964 -0.3756103515625 +58965 -0.218902587890625 +58966 -0.063751220703125 +58967 0.091552734375 +58968 0.23602294921875 +58969 0.342987060546875 +58970 0.39520263671875 +58971 0.389373779296875 +58972 0.324249267578125 +58973 0.224090576171875 +58974 0.124267578125 +58975 0.037078857421875 +58976 -0.010101318359375 +58977 -0.019439697265625 +58978 -0.022796630859375 +58979 -0.001556396484375 +58980 0.056304931640625 +58981 0.106719970703125 +58982 0.096893310546875 +58983 0.042694091796875 +58984 -0.018035888671875 +58985 -0.07586669921875 +58986 -0.11944580078125 +58987 -0.15972900390625 +58988 -0.202606201171875 +58989 -0.24859619140625 +58990 -0.30517578125 +58991 -0.36212158203125 +58992 -0.39141845703125 +58993 -0.35528564453125 +58994 -0.249969482421875 +58995 -0.092864990234375 +58996 0.08905029296875 +58997 0.2352294921875 +58998 0.318817138671875 +58999 0.358642578125 +59000 0.347747802734375 +59001 0.28564453125 +59002 0.223175048828125 +59003 0.196746826171875 +59004 0.179840087890625 +59005 0.155548095703125 +59006 0.151214599609375 +59007 0.156951904296875 +59008 0.13177490234375 +59009 0.100799560546875 +59010 0.087127685546875 +59011 0.05487060546875 +59012 -0.009002685546875 +59013 -0.10400390625 +59014 -0.229400634765625 +59015 -0.35552978515625 +59016 -0.441925048828125 +59017 -0.473846435546875 +59018 -0.464813232421875 +59019 -0.419097900390625 +59020 -0.334320068359375 +59021 -0.227935791015625 +59022 -0.12347412109375 +59023 -0.02764892578125 +59024 0.077667236328125 +59025 0.2132568359375 +59026 0.38885498046875 +59027 0.582794189453125 +59028 0.734039306640625 +59029 0.800140380859375 +59030 0.7783203125 +59031 0.6651611328125 +59032 0.45965576171875 +59033 0.199188232421875 +59034 -0.050689697265625 +59035 -0.23297119140625 +59036 -0.33013916015625 +59037 -0.368408203125 +59038 -0.378936767578125 +59039 -0.376983642578125 +59040 -0.37969970703125 +59041 -0.391510009765625 +59042 -0.385345458984375 +59043 -0.3419189453125 +59044 -0.28289794921875 +59045 -0.251617431640625 +59046 -0.266143798828125 +59047 -0.273345947265625 +59048 -0.216796875 +59049 -0.128265380859375 +59050 -0.068145751953125 +59051 -0.0430908203125 +59052 -0.024444580078125 +59053 0.020721435546875 +59054 0.124481201171875 +59055 0.25787353515625 +59056 0.379119873046875 +59057 0.47991943359375 +59058 0.5281982421875 +59059 0.511138916015625 +59060 0.456207275390625 +59061 0.407470703125 +59062 0.383758544921875 +59063 0.35687255859375 +59064 0.31182861328125 +59065 0.250885009765625 +59066 0.1654052734375 +59067 0.035247802734375 +59068 -0.142059326171875 +59069 -0.33563232421875 +59070 -0.5345458984375 +59071 -0.72186279296875 +59072 -0.836669921875 +59073 -0.8326416015625 +59074 -0.7296142578125 +59075 -0.582550048828125 +59076 -0.440093994140625 +59077 -0.324310302734375 +59078 -0.20147705078125 +59079 -0.044647216796875 +59080 0.103973388671875 +59081 0.202392578125 +59082 0.264495849609375 +59083 0.338897705078125 +59084 0.443817138671875 +59085 0.545074462890625 +59086 0.6173095703125 +59087 0.6524658203125 +59088 0.66339111328125 +59089 0.6561279296875 +59090 0.606781005859375 +59091 0.501190185546875 +59092 0.352783203125 +59093 0.176544189453125 +59094 -0.034820556640625 +59095 -0.258209228515625 +59096 -0.44244384765625 +59097 -0.5753173828125 +59098 -0.65203857421875 +59099 -0.641632080078125 +59100 -0.562164306640625 +59101 -0.458038330078125 +59102 -0.350555419921875 +59103 -0.260528564453125 +59104 -0.192108154296875 +59105 -0.141937255859375 +59106 -0.1021728515625 +59107 -0.062896728515625 +59108 -0.011932373046875 +59109 0.062835693359375 +59110 0.148712158203125 +59111 0.241729736328125 +59112 0.34912109375 +59113 0.457305908203125 +59114 0.54388427734375 +59115 0.5728759765625 +59116 0.506591796875 +59117 0.351226806640625 +59118 0.146514892578125 +59119 -0.05523681640625 +59120 -0.21624755859375 +59121 -0.334930419921875 +59122 -0.402984619140625 +59123 -0.4412841796875 +59124 -0.49578857421875 +59125 -0.5601806640625 +59126 -0.600738525390625 +59127 -0.584228515625 +59128 -0.47930908203125 +59129 -0.27935791015625 +59130 -0.0089111328125 +59131 0.268798828125 +59132 0.482818603515625 +59133 0.60369873046875 +59134 0.650421142578125 +59135 0.66400146484375 +59136 0.6414794921875 +59137 0.572540283203125 +59138 0.498138427734375 +59139 0.439453125 +59140 0.375518798828125 +59141 0.274505615234375 +59142 0.1087646484375 +59143 -0.099395751953125 +59144 -0.3182373046875 +59145 -0.5489501953125 +59146 -0.7738037109375 +59147 -0.86383056640625 +59148 -0.870391845703125 +59149 -0.86895751953125 +59150 -0.861053466796875 +59151 -0.765869140625 +59152 -0.5301513671875 +59153 -0.214691162109375 +59154 0.137359619140625 +59155 0.474822998046875 +59156 0.76239013671875 +59157 0.867462158203125 +59158 0.870361328125 +59159 0.86480712890625 +59160 0.831817626953125 +59161 0.677581787109375 +59162 0.495880126953125 +59163 0.30767822265625 +59164 0.116180419921875 +59165 -0.110748291015625 +59166 -0.381805419921875 +59167 -0.6572265625 +59168 -0.857421875 +59169 -0.870391845703125 +59170 -0.870391845703125 +59171 -0.86444091796875 +59172 -0.85723876953125 +59173 -0.790008544921875 +59174 -0.62847900390625 +59175 -0.3956298828125 +59176 -0.126708984375 +59177 0.150115966796875 +59178 0.424041748046875 +59179 0.670623779296875 +59180 0.854522705078125 +59181 0.866485595703125 +59182 0.86920166015625 +59183 0.8653564453125 +59184 0.857147216796875 +59185 0.766845703125 +59186 0.628509521484375 +59187 0.462127685546875 +59188 0.297210693359375 +59189 0.14862060546875 +59190 -0.00537109375 +59191 -0.15753173828125 +59192 -0.31304931640625 +59193 -0.48876953125 +59194 -0.6416015625 +59195 -0.751373291015625 +59196 -0.84619140625 +59197 -0.861297607421875 +59198 -0.863250732421875 +59199 -0.856597900390625 +59200 -0.7498779296875 +59201 -0.624542236328125 +59202 -0.47808837890625 +59203 -0.253387451171875 +59204 0.003692626953125 +59205 0.2257080078125 +59206 0.427154541015625 +59207 0.643218994140625 +59208 0.855926513671875 +59209 0.870361328125 +59210 0.870361328125 +59211 0.862762451171875 +59212 0.79669189453125 +59213 0.595794677734375 +59214 0.362152099609375 +59215 0.1270751953125 +59216 -0.086944580078125 +59217 -0.2784423828125 +59218 -0.484832763671875 +59219 -0.729583740234375 +59220 -0.86688232421875 +59221 -0.870391845703125 +59222 -0.86859130859375 +59223 -0.86279296875 +59224 -0.817962646484375 +59225 -0.6116943359375 +59226 -0.3128662109375 +59227 0.039398193359375 +59228 0.422821044921875 +59229 0.805145263671875 +59230 0.870361328125 +59231 0.870361328125 +59232 0.860015869140625 +59233 0.727935791015625 +59234 0.48114013671875 +59235 0.2059326171875 +59236 -0.06103515625 +59237 -0.29913330078125 +59238 -0.516204833984375 +59239 -0.7252197265625 +59240 -0.85980224609375 +59241 -0.870391845703125 +59242 -0.870391845703125 +59243 -0.858062744140625 +59244 -0.673004150390625 +59245 -0.42694091796875 +59246 -0.2100830078125 +59247 -0.0362548828125 +59248 0.10943603515625 +59249 0.23516845703125 +59250 0.373687744140625 +59251 0.517791748046875 +59252 0.602783203125 +59253 0.635711669921875 +59254 0.655181884765625 +59255 0.65948486328125 +59256 0.651275634765625 +59257 0.61846923828125 +59258 0.53753662109375 +59259 0.404144287109375 +59260 0.22186279296875 +59261 0.003997802734375 +59262 -0.22100830078125 +59263 -0.42449951171875 +59264 -0.579833984375 +59265 -0.641876220703125 +59266 -0.6177978515625 +59267 -0.575531005859375 +59268 -0.526336669921875 +59269 -0.42645263671875 +59270 -0.2581787109375 +59271 -0.068695068359375 +59272 0.09222412109375 +59273 0.232147216796875 +59274 0.3509521484375 +59275 0.410064697265625 +59276 0.372955322265625 +59277 0.2554931640625 +59278 0.10711669921875 +59279 -0.052886962890625 +59280 -0.186279296875 +59281 -0.23291015625 +59282 -0.209442138671875 +59283 -0.174163818359375 +59284 -0.126739501953125 +59285 -0.048126220703125 +59286 0.0426025390625 +59287 0.10748291015625 +59288 0.1409912109375 +59289 0.19708251953125 +59290 0.273651123046875 +59291 0.31768798828125 +59292 0.341094970703125 +59293 0.368011474609375 +59294 0.37249755859375 +59295 0.30072021484375 +59296 0.1517333984375 +59297 -0.01470947265625 +59298 -0.1883544921875 +59299 -0.372711181640625 +59300 -0.51397705078125 +59301 -0.57177734375 +59302 -0.53948974609375 +59303 -0.43511962890625 +59304 -0.2962646484375 +59305 -0.161102294921875 +59306 -0.0435791015625 +59307 0.060394287109375 +59308 0.13665771484375 +59309 0.170135498046875 +59310 0.16552734375 +59311 0.15728759765625 +59312 0.150787353515625 +59313 0.12200927734375 +59314 0.080108642578125 +59315 0.05126953125 +59316 0.062896728515625 +59317 0.09271240234375 +59318 0.092987060546875 +59319 0.07855224609375 +59320 0.06427001953125 +59321 0.0347900390625 +59322 -0.01171875 +59323 -0.056060791015625 +59324 -0.055511474609375 +59325 -0.010467529296875 +59326 0.02508544921875 +59327 0.025665283203125 +59328 0.017333984375 +59329 0.00189208984375 +59330 -0.03173828125 +59331 -0.071502685546875 +59332 -0.13543701171875 +59333 -0.219970703125 +59334 -0.300506591796875 +59335 -0.376312255859375 +59336 -0.416107177734375 +59337 -0.371124267578125 +59338 -0.242279052734375 +59339 -0.069732666015625 +59340 0.125640869140625 +59341 0.31268310546875 +59342 0.45501708984375 +59343 0.554779052734375 +59344 0.61065673828125 +59345 0.610931396484375 +59346 0.531463623046875 +59347 0.3883056640625 +59348 0.23468017578125 +59349 0.095245361328125 +59350 -0.00396728515625 +59351 -0.04852294921875 +59352 -0.055145263671875 +59353 -0.0758056640625 +59354 -0.138702392578125 +59355 -0.209197998046875 +59356 -0.289031982421875 +59357 -0.37884521484375 +59358 -0.456329345703125 +59359 -0.51641845703125 +59360 -0.519287109375 +59361 -0.458251953125 +59362 -0.384796142578125 +59363 -0.323699951171875 +59364 -0.269287109375 +59365 -0.1951904296875 +59366 -0.100006103515625 +59367 -0.01055908203125 +59368 0.1033935546875 +59369 0.24908447265625 +59370 0.373199462890625 +59371 0.45806884765625 +59372 0.511474609375 +59373 0.565399169921875 +59374 0.61138916015625 +59375 0.5897216796875 +59376 0.4906005859375 +59377 0.33148193359375 +59378 0.147796630859375 +59379 -0.01873779296875 +59380 -0.140289306640625 +59381 -0.191986083984375 +59382 -0.184295654296875 +59383 -0.161834716796875 +59384 -0.166595458984375 +59385 -0.19390869140625 +59386 -0.22442626953125 +59387 -0.279754638671875 +59388 -0.3389892578125 +59389 -0.3543701171875 +59390 -0.348175048828125 +59391 -0.32598876953125 +59392 -0.2581787109375 +59393 -0.139801025390625 +59394 0.014617919921875 +59395 0.144378662109375 +59396 0.221038818359375 +59397 0.27069091796875 +59398 0.294036865234375 +59399 0.311767578125 +59400 0.339141845703125 +59401 0.360260009765625 +59402 0.360504150390625 +59403 0.308380126953125 +59404 0.18170166015625 +59405 0.0047607421875 +59406 -0.17559814453125 +59407 -0.3143310546875 +59408 -0.36785888671875 +59409 -0.36248779296875 +59410 -0.343536376953125 +59411 -0.3018798828125 +59412 -0.231414794921875 +59413 -0.117645263671875 +59414 0.007049560546875 +59415 0.087982177734375 +59416 0.13946533203125 +59417 0.17425537109375 +59418 0.188201904296875 +59419 0.171234130859375 +59420 0.118438720703125 +59421 0.05706787109375 +59422 -0.010711669921875 +59423 -0.0914306640625 +59424 -0.162322998046875 +59425 -0.194549560546875 +59426 -0.1492919921875 +59427 -0.02166748046875 +59428 0.124053955078125 +59429 0.211151123046875 +59430 0.240447998046875 +59431 0.242218017578125 +59432 0.2257080078125 +59433 0.194366455078125 +59434 0.115509033203125 +59435 0.0128173828125 +59436 -0.053802490234375 +59437 -0.110626220703125 +59438 -0.199493408203125 +59439 -0.29437255859375 +59440 -0.33221435546875 +59441 -0.27972412109375 +59442 -0.185333251953125 +59443 -0.128204345703125 +59444 -0.115692138671875 +59445 -0.116455078125 +59446 -0.105926513671875 +59447 -0.053955078125 +59448 0.048797607421875 +59449 0.157318115234375 +59450 0.212005615234375 +59451 0.218475341796875 +59452 0.23724365234375 +59453 0.30535888671875 +59454 0.38128662109375 +59455 0.404449462890625 +59456 0.3944091796875 +59457 0.3885498046875 +59458 0.362640380859375 +59459 0.27362060546875 +59460 0.11712646484375 +59461 -0.054901123046875 +59462 -0.19085693359375 +59463 -0.28570556640625 +59464 -0.339263916015625 +59465 -0.3775634765625 +59466 -0.445709228515625 +59467 -0.535064697265625 +59468 -0.629058837890625 +59469 -0.697601318359375 +59470 -0.70391845703125 +59471 -0.6424560546875 +59472 -0.491241455078125 +59473 -0.265716552734375 +59474 -0.023712158203125 +59475 0.201751708984375 +59476 0.375823974609375 +59477 0.485076904296875 +59478 0.56884765625 +59479 0.634765625 +59480 0.63763427734375 +59481 0.5660400390625 +59482 0.4720458984375 +59483 0.40692138671875 +59484 0.3778076171875 +59485 0.376953125 +59486 0.371978759765625 +59487 0.313140869140625 +59488 0.184417724609375 +59489 0.011199951171875 +59490 -0.171051025390625 +59491 -0.33740234375 +59492 -0.47198486328125 +59493 -0.560394287109375 +59494 -0.58056640625 +59495 -0.54754638671875 +59496 -0.508575439453125 +59497 -0.459503173828125 +59498 -0.394378662109375 +59499 -0.35260009765625 +59500 -0.31170654296875 +59501 -0.197418212890625 +59502 -0.007965087890625 +59503 0.207489013671875 +59504 0.409210205078125 +59505 0.57208251953125 +59506 0.66595458984375 +59507 0.65875244140625 +59508 0.56744384765625 +59509 0.431396484375 +59510 0.29443359375 +59511 0.182464599609375 +59512 0.06365966796875 +59513 -0.075958251953125 +59514 -0.189422607421875 +59515 -0.271942138671875 +59516 -0.342529296875 +59517 -0.364166259765625 +59518 -0.327239990234375 +59519 -0.2769775390625 +59520 -0.253692626953125 +59521 -0.24365234375 +59522 -0.1983642578125 +59523 -0.116241455078125 +59524 -0.036834716796875 +59525 0.034881591796875 +59526 0.09124755859375 +59527 0.10888671875 +59528 0.125518798828125 +59529 0.15771484375 +59530 0.17828369140625 +59531 0.17108154296875 +59532 0.129974365234375 +59533 0.082427978515625 +59534 0.027679443359375 +59535 -0.065643310546875 +59536 -0.15936279296875 +59537 -0.21307373046875 +59538 -0.234649658203125 +59539 -0.2001953125 +59540 -0.119171142578125 +59541 -0.024749755859375 +59542 0.085784912109375 +59543 0.178131103515625 +59544 0.215576171875 +59545 0.211456298828125 +59546 0.17523193359375 +59547 0.128753662109375 +59548 0.1019287109375 +59549 0.0743408203125 +59550 0.04327392578125 +59551 0.038177490234375 +59552 0.076263427734375 +59553 0.14105224609375 +59554 0.186431884765625 +59555 0.188812255859375 +59556 0.1390380859375 +59557 0.041778564453125 +59558 -0.079437255859375 +59559 -0.219390869140625 +59560 -0.367828369140625 +59561 -0.494873046875 +59562 -0.556243896484375 +59563 -0.508697509765625 +59564 -0.3756103515625 +59565 -0.218902587890625 +59566 -0.063751220703125 +59567 0.091552734375 +59568 0.23602294921875 +59569 0.342987060546875 +59570 0.39520263671875 +59571 0.389373779296875 +59572 0.324249267578125 +59573 0.224090576171875 +59574 0.124267578125 +59575 0.037078857421875 +59576 -0.010101318359375 +59577 -0.019439697265625 +59578 -0.022796630859375 +59579 -0.001556396484375 +59580 0.056304931640625 +59581 0.106719970703125 +59582 0.096893310546875 +59583 0.042694091796875 +59584 -0.018035888671875 +59585 -0.07586669921875 +59586 -0.11944580078125 +59587 -0.15972900390625 +59588 -0.202606201171875 +59589 -0.24859619140625 +59590 -0.30517578125 +59591 -0.36212158203125 +59592 -0.39141845703125 +59593 -0.35528564453125 +59594 -0.249969482421875 +59595 -0.092864990234375 +59596 0.08905029296875 +59597 0.2352294921875 +59598 0.318817138671875 +59599 0.358642578125 +59600 0.347747802734375 +59601 0.28564453125 +59602 0.223175048828125 +59603 0.196746826171875 +59604 0.179840087890625 +59605 0.155548095703125 +59606 0.151214599609375 +59607 0.156951904296875 +59608 0.13177490234375 +59609 0.100799560546875 +59610 0.087127685546875 +59611 0.05487060546875 +59612 -0.009002685546875 +59613 -0.10400390625 +59614 -0.229400634765625 +59615 -0.35552978515625 +59616 -0.441925048828125 +59617 -0.473846435546875 +59618 -0.464813232421875 +59619 -0.419097900390625 +59620 -0.334320068359375 +59621 -0.227935791015625 +59622 -0.12347412109375 +59623 -0.02764892578125 +59624 0.077667236328125 +59625 0.2132568359375 +59626 0.38885498046875 +59627 0.582794189453125 +59628 0.734039306640625 +59629 0.800140380859375 +59630 0.7783203125 +59631 0.6651611328125 +59632 0.45965576171875 +59633 0.199188232421875 +59634 -0.050689697265625 +59635 -0.23297119140625 +59636 -0.33013916015625 +59637 -0.368408203125 +59638 -0.378936767578125 +59639 -0.376983642578125 +59640 -0.37969970703125 +59641 -0.391510009765625 +59642 -0.385345458984375 +59643 -0.3419189453125 +59644 -0.28289794921875 +59645 -0.251617431640625 +59646 -0.266143798828125 +59647 -0.273345947265625 +59648 -0.216796875 +59649 -0.128265380859375 +59650 -0.068145751953125 +59651 -0.0430908203125 +59652 -0.024444580078125 +59653 0.020721435546875 +59654 0.124481201171875 +59655 0.25787353515625 +59656 0.379119873046875 +59657 0.47991943359375 +59658 0.5281982421875 +59659 0.511138916015625 +59660 0.456207275390625 +59661 0.407470703125 +59662 0.383758544921875 +59663 0.35687255859375 +59664 0.31182861328125 +59665 0.250885009765625 +59666 0.1654052734375 +59667 0.035247802734375 +59668 -0.142059326171875 +59669 -0.33563232421875 +59670 -0.5345458984375 +59671 -0.72186279296875 +59672 -0.836669921875 +59673 -0.8326416015625 +59674 -0.7296142578125 +59675 -0.582550048828125 +59676 -0.440093994140625 +59677 -0.324310302734375 +59678 -0.20147705078125 +59679 -0.044647216796875 +59680 0.103973388671875 +59681 0.202392578125 +59682 0.264495849609375 +59683 0.338897705078125 +59684 0.443817138671875 +59685 0.545074462890625 +59686 0.6173095703125 +59687 0.6524658203125 +59688 0.66339111328125 +59689 0.6561279296875 +59690 0.606781005859375 +59691 0.501190185546875 +59692 0.352783203125 +59693 0.176544189453125 +59694 -0.034820556640625 +59695 -0.258209228515625 +59696 -0.44244384765625 +59697 -0.5753173828125 +59698 -0.65203857421875 +59699 -0.641632080078125 +59700 -0.562164306640625 +59701 -0.458038330078125 +59702 -0.350555419921875 +59703 -0.260528564453125 +59704 -0.192108154296875 +59705 -0.141937255859375 +59706 -0.1021728515625 +59707 -0.062896728515625 +59708 -0.011932373046875 +59709 0.062835693359375 +59710 0.148712158203125 +59711 0.241729736328125 +59712 0.34912109375 +59713 0.457305908203125 +59714 0.54388427734375 +59715 0.5728759765625 +59716 0.506591796875 +59717 0.351226806640625 +59718 0.146514892578125 +59719 -0.05523681640625 +59720 -0.21624755859375 +59721 -0.334930419921875 +59722 -0.402984619140625 +59723 -0.4412841796875 +59724 -0.49578857421875 +59725 -0.5601806640625 +59726 -0.600738525390625 +59727 -0.584228515625 +59728 -0.47930908203125 +59729 -0.27935791015625 +59730 -0.0089111328125 +59731 0.268798828125 +59732 0.482818603515625 +59733 0.60369873046875 +59734 0.650421142578125 +59735 0.66400146484375 +59736 0.6414794921875 +59737 0.572540283203125 +59738 0.498138427734375 +59739 0.439453125 +59740 0.375518798828125 +59741 0.274505615234375 +59742 0.1087646484375 +59743 -0.099395751953125 +59744 -0.3182373046875 +59745 -0.5489501953125 +59746 -0.7738037109375 +59747 -0.86383056640625 +59748 -0.870391845703125 +59749 -0.86895751953125 +59750 -0.861053466796875 +59751 -0.765869140625 +59752 -0.5301513671875 +59753 -0.214691162109375 +59754 0.137359619140625 +59755 0.474822998046875 +59756 0.76239013671875 +59757 0.867462158203125 +59758 0.870361328125 +59759 0.86480712890625 +59760 0.831817626953125 +59761 0.677581787109375 +59762 0.495880126953125 +59763 0.30767822265625 +59764 0.116180419921875 +59765 -0.110748291015625 +59766 -0.381805419921875 +59767 -0.6572265625 +59768 -0.857421875 +59769 -0.870391845703125 +59770 -0.870391845703125 +59771 -0.86444091796875 +59772 -0.85723876953125 +59773 -0.790008544921875 +59774 -0.62847900390625 +59775 -0.3956298828125 +59776 -0.126708984375 +59777 0.150115966796875 +59778 0.424041748046875 +59779 0.670623779296875 +59780 0.854522705078125 +59781 0.866485595703125 +59782 0.86920166015625 +59783 0.8653564453125 +59784 0.857147216796875 +59785 0.766845703125 +59786 0.628509521484375 +59787 0.462127685546875 +59788 0.297210693359375 +59789 0.14862060546875 +59790 -0.00537109375 +59791 -0.15753173828125 +59792 -0.31304931640625 +59793 -0.48876953125 +59794 -0.6416015625 +59795 -0.751373291015625 +59796 -0.84619140625 +59797 -0.861297607421875 +59798 -0.863250732421875 +59799 -0.856597900390625 +59800 -0.7498779296875 +59801 -0.624542236328125 +59802 -0.47808837890625 +59803 -0.253387451171875 +59804 0.003692626953125 +59805 0.2257080078125 +59806 0.427154541015625 +59807 0.643218994140625 +59808 0.855926513671875 +59809 0.870361328125 +59810 0.870361328125 +59811 0.862762451171875 +59812 0.79669189453125 +59813 0.595794677734375 +59814 0.362152099609375 +59815 0.1270751953125 +59816 -0.086944580078125 +59817 -0.2784423828125 +59818 -0.484832763671875 +59819 -0.729583740234375 +59820 -0.86688232421875 +59821 -0.870391845703125 +59822 -0.86859130859375 +59823 -0.86279296875 +59824 -0.817962646484375 +59825 -0.6116943359375 +59826 -0.3128662109375 +59827 0.039398193359375 +59828 0.422821044921875 +59829 0.805145263671875 +59830 0.870361328125 +59831 0.870361328125 +59832 0.860015869140625 +59833 0.727935791015625 +59834 0.48114013671875 +59835 0.2059326171875 +59836 -0.06103515625 +59837 -0.29913330078125 +59838 -0.516204833984375 +59839 -0.7252197265625 +59840 -0.85980224609375 +59841 -0.870391845703125 +59842 -0.870391845703125 +59843 -0.858062744140625 +59844 -0.673004150390625 +59845 -0.42694091796875 +59846 -0.2100830078125 +59847 -0.0362548828125 +59848 0.10943603515625 +59849 0.23516845703125 +59850 0.373687744140625 +59851 0.517791748046875 +59852 0.602783203125 +59853 0.635711669921875 +59854 0.655181884765625 +59855 0.65948486328125 +59856 0.651275634765625 +59857 0.61846923828125 +59858 0.53753662109375 +59859 0.404144287109375 +59860 0.22186279296875 +59861 0.003997802734375 +59862 -0.22100830078125 +59863 -0.42449951171875 +59864 -0.579833984375 +59865 -0.641876220703125 +59866 -0.6177978515625 +59867 -0.575531005859375 +59868 -0.526336669921875 +59869 -0.42645263671875 +59870 -0.2581787109375 +59871 -0.068695068359375 +59872 0.09222412109375 +59873 0.232147216796875 +59874 0.3509521484375 +59875 0.410064697265625 +59876 0.372955322265625 +59877 0.2554931640625 +59878 0.10711669921875 +59879 -0.052886962890625 +59880 -0.186279296875 +59881 -0.23291015625 +59882 -0.209442138671875 +59883 -0.174163818359375 +59884 -0.126739501953125 +59885 -0.048126220703125 +59886 0.0426025390625 +59887 0.10748291015625 +59888 0.1409912109375 +59889 0.19708251953125 +59890 0.273651123046875 +59891 0.31768798828125 +59892 0.341094970703125 +59893 0.368011474609375 +59894 0.37249755859375 +59895 0.30072021484375 +59896 0.1517333984375 +59897 -0.01470947265625 +59898 -0.1883544921875 +59899 -0.372711181640625 +59900 -0.51397705078125 +59901 -0.57177734375 +59902 -0.53948974609375 +59903 -0.43511962890625 +59904 -0.2962646484375 +59905 -0.161102294921875 +59906 -0.0435791015625 +59907 0.060394287109375 +59908 0.13665771484375 +59909 0.170135498046875 +59910 0.16552734375 +59911 0.15728759765625 +59912 0.150787353515625 +59913 0.12200927734375 +59914 0.080108642578125 +59915 0.05126953125 +59916 0.062896728515625 +59917 0.09271240234375 +59918 0.092987060546875 +59919 0.07855224609375 +59920 0.06427001953125 +59921 0.0347900390625 +59922 -0.01171875 +59923 -0.056060791015625 +59924 -0.055511474609375 +59925 -0.010467529296875 +59926 0.02508544921875 +59927 0.025665283203125 +59928 0.017333984375 +59929 0.00189208984375 +59930 -0.03173828125 +59931 -0.071502685546875 +59932 -0.13543701171875 +59933 -0.219970703125 +59934 -0.300506591796875 +59935 -0.376312255859375 +59936 -0.416107177734375 +59937 -0.371124267578125 +59938 -0.242279052734375 +59939 -0.069732666015625 +59940 0.125640869140625 +59941 0.31268310546875 +59942 0.45501708984375 +59943 0.554779052734375 +59944 0.61065673828125 +59945 0.610931396484375 +59946 0.531463623046875 +59947 0.3883056640625 +59948 0.23468017578125 +59949 0.095245361328125 +59950 -0.00396728515625 +59951 -0.04852294921875 +59952 -0.055145263671875 +59953 -0.0758056640625 +59954 -0.138702392578125 +59955 -0.209197998046875 +59956 -0.289031982421875 +59957 -0.37884521484375 +59958 -0.456329345703125 +59959 -0.51641845703125 +59960 -0.519287109375 +59961 -0.458251953125 +59962 -0.384796142578125 +59963 -0.323699951171875 +59964 -0.269287109375 +59965 -0.1951904296875 +59966 -0.100006103515625 +59967 -0.01055908203125 +59968 0.1033935546875 +59969 0.24908447265625 +59970 0.373199462890625 +59971 0.45806884765625 +59972 0.511474609375 +59973 0.565399169921875 +59974 0.61138916015625 +59975 0.5897216796875 +59976 0.4906005859375 +59977 0.33148193359375 +59978 0.147796630859375 +59979 -0.01873779296875 +59980 -0.140289306640625 +59981 -0.191986083984375 +59982 -0.184295654296875 +59983 -0.161834716796875 +59984 -0.166595458984375 +59985 -0.19390869140625 +59986 -0.22442626953125 +59987 -0.279754638671875 +59988 -0.3389892578125 +59989 -0.3543701171875 +59990 -0.348175048828125 +59991 -0.32598876953125 +59992 -0.2581787109375 +59993 -0.139801025390625 +59994 0.014617919921875 +59995 0.144378662109375 +59996 0.221038818359375 +59997 0.27069091796875 +59998 0.294036865234375 +59999 0.311767578125 +60000 0.339141845703125 +60001 0.360260009765625 +60002 0.360504150390625 +60003 0.308380126953125 +60004 0.18170166015625 +60005 0.0047607421875 +60006 -0.17559814453125 +60007 -0.3143310546875 +60008 -0.36785888671875 +60009 -0.36248779296875 +60010 -0.343536376953125 +60011 -0.3018798828125 +60012 -0.231414794921875 +60013 -0.117645263671875 +60014 0.007049560546875 +60015 0.087982177734375 +60016 0.13946533203125 +60017 0.17425537109375 +60018 0.188201904296875 +60019 0.171234130859375 +60020 0.118438720703125 +60021 0.05706787109375 +60022 -0.010711669921875 +60023 -0.0914306640625 +60024 -0.162322998046875 +60025 -0.194549560546875 +60026 -0.1492919921875 +60027 -0.02166748046875 +60028 0.124053955078125 +60029 0.211151123046875 +60030 0.240447998046875 +60031 0.242218017578125 +60032 0.2257080078125 +60033 0.194366455078125 +60034 0.115509033203125 +60035 0.0128173828125 +60036 -0.053802490234375 +60037 -0.110626220703125 +60038 -0.199493408203125 +60039 -0.29437255859375 +60040 -0.33221435546875 +60041 -0.27972412109375 +60042 -0.185333251953125 +60043 -0.128204345703125 +60044 -0.115692138671875 +60045 -0.116455078125 +60046 -0.105926513671875 +60047 -0.053955078125 +60048 0.048797607421875 +60049 0.157318115234375 +60050 0.212005615234375 +60051 0.218475341796875 +60052 0.23724365234375 +60053 0.30535888671875 +60054 0.38128662109375 +60055 0.404449462890625 +60056 0.3944091796875 +60057 0.3885498046875 +60058 0.362640380859375 +60059 0.27362060546875 +60060 0.11712646484375 +60061 -0.054901123046875 +60062 -0.19085693359375 +60063 -0.28570556640625 +60064 -0.339263916015625 +60065 -0.3775634765625 +60066 -0.445709228515625 +60067 -0.535064697265625 +60068 -0.629058837890625 +60069 -0.697601318359375 +60070 -0.70391845703125 +60071 -0.6424560546875 +60072 -0.491241455078125 +60073 -0.265716552734375 +60074 -0.023712158203125 +60075 0.201751708984375 +60076 0.375823974609375 +60077 0.485076904296875 +60078 0.56884765625 +60079 0.634765625 +60080 0.63763427734375 +60081 0.5660400390625 +60082 0.4720458984375 +60083 0.40692138671875 +60084 0.3778076171875 +60085 0.376953125 +60086 0.371978759765625 +60087 0.313140869140625 +60088 0.184417724609375 +60089 0.011199951171875 +60090 -0.171051025390625 +60091 -0.33740234375 +60092 -0.47198486328125 +60093 -0.560394287109375 +60094 -0.58056640625 +60095 -0.54754638671875 +60096 -0.508575439453125 +60097 -0.459503173828125 +60098 -0.394378662109375 +60099 -0.35260009765625 +60100 -0.31170654296875 +60101 -0.197418212890625 +60102 -0.007965087890625 +60103 0.207489013671875 +60104 0.409210205078125 +60105 0.57208251953125 +60106 0.66595458984375 +60107 0.65875244140625 +60108 0.56744384765625 +60109 0.431396484375 +60110 0.29443359375 +60111 0.182464599609375 +60112 0.06365966796875 +60113 -0.075958251953125 +60114 -0.189422607421875 +60115 -0.271942138671875 +60116 -0.342529296875 +60117 -0.364166259765625 +60118 -0.327239990234375 +60119 -0.2769775390625 +60120 -0.253692626953125 +60121 -0.24365234375 +60122 -0.1983642578125 +60123 -0.116241455078125 +60124 -0.036834716796875 +60125 0.034881591796875 +60126 0.09124755859375 +60127 0.10888671875 +60128 0.125518798828125 +60129 0.15771484375 +60130 0.17828369140625 +60131 0.17108154296875 +60132 0.129974365234375 +60133 0.082427978515625 +60134 0.027679443359375 +60135 -0.065643310546875 +60136 -0.15936279296875 +60137 -0.21307373046875 +60138 -0.234649658203125 +60139 -0.2001953125 +60140 -0.119171142578125 +60141 -0.024749755859375 +60142 0.085784912109375 +60143 0.178131103515625 +60144 0.215576171875 +60145 0.211456298828125 +60146 0.17523193359375 +60147 0.128753662109375 +60148 0.1019287109375 +60149 0.0743408203125 +60150 0.04327392578125 +60151 0.038177490234375 +60152 0.076263427734375 +60153 0.14105224609375 +60154 0.186431884765625 +60155 0.188812255859375 +60156 0.1390380859375 +60157 0.041778564453125 +60158 -0.079437255859375 +60159 -0.219390869140625 +60160 -0.367828369140625 +60161 -0.494873046875 +60162 -0.556243896484375 +60163 -0.508697509765625 +60164 -0.3756103515625 +60165 -0.218902587890625 +60166 -0.063751220703125 +60167 0.091552734375 +60168 0.23602294921875 +60169 0.342987060546875 +60170 0.39520263671875 +60171 0.389373779296875 +60172 0.324249267578125 +60173 0.224090576171875 +60174 0.124267578125 +60175 0.037078857421875 +60176 -0.010101318359375 +60177 -0.019439697265625 +60178 -0.022796630859375 +60179 -0.001556396484375 +60180 0.056304931640625 +60181 0.106719970703125 +60182 0.096893310546875 +60183 0.042694091796875 +60184 -0.018035888671875 +60185 -0.07586669921875 +60186 -0.11944580078125 +60187 -0.15972900390625 +60188 -0.202606201171875 +60189 -0.24859619140625 +60190 -0.30517578125 +60191 -0.36212158203125 +60192 -0.39141845703125 +60193 -0.35528564453125 +60194 -0.249969482421875 +60195 -0.092864990234375 +60196 0.08905029296875 +60197 0.2352294921875 +60198 0.318817138671875 +60199 0.358642578125 +60200 0.347747802734375 +60201 0.28564453125 +60202 0.223175048828125 +60203 0.196746826171875 +60204 0.179840087890625 +60205 0.155548095703125 +60206 0.151214599609375 +60207 0.156951904296875 +60208 0.13177490234375 +60209 0.100799560546875 +60210 0.087127685546875 +60211 0.05487060546875 +60212 -0.009002685546875 +60213 -0.10400390625 +60214 -0.229400634765625 +60215 -0.35552978515625 +60216 -0.441925048828125 +60217 -0.473846435546875 +60218 -0.464813232421875 +60219 -0.419097900390625 +60220 -0.334320068359375 +60221 -0.227935791015625 +60222 -0.12347412109375 +60223 -0.02764892578125 +60224 0.077667236328125 +60225 0.2132568359375 +60226 0.38885498046875 +60227 0.582794189453125 +60228 0.734039306640625 +60229 0.800140380859375 +60230 0.7783203125 +60231 0.6651611328125 +60232 0.45965576171875 +60233 0.199188232421875 +60234 -0.050689697265625 +60235 -0.23297119140625 +60236 -0.33013916015625 +60237 -0.368408203125 +60238 -0.378936767578125 +60239 -0.376983642578125 +60240 -0.37969970703125 +60241 -0.391510009765625 +60242 -0.385345458984375 +60243 -0.3419189453125 +60244 -0.28289794921875 +60245 -0.251617431640625 +60246 -0.266143798828125 +60247 -0.273345947265625 +60248 -0.216796875 +60249 -0.128265380859375 +60250 -0.068145751953125 +60251 -0.0430908203125 +60252 -0.024444580078125 +60253 0.020721435546875 +60254 0.124481201171875 +60255 0.25787353515625 +60256 0.379119873046875 +60257 0.47991943359375 +60258 0.5281982421875 +60259 0.511138916015625 +60260 0.456207275390625 +60261 0.407470703125 +60262 0.383758544921875 +60263 0.35687255859375 +60264 0.31182861328125 +60265 0.250885009765625 +60266 0.1654052734375 +60267 0.035247802734375 +60268 -0.142059326171875 +60269 -0.33563232421875 +60270 -0.5345458984375 +60271 -0.72186279296875 +60272 -0.836669921875 +60273 -0.8326416015625 +60274 -0.7296142578125 +60275 -0.582550048828125 +60276 -0.440093994140625 +60277 -0.324310302734375 +60278 -0.20147705078125 +60279 -0.044647216796875 +60280 0.103973388671875 +60281 0.202392578125 +60282 0.264495849609375 +60283 0.338897705078125 +60284 0.443817138671875 +60285 0.545074462890625 +60286 0.6173095703125 +60287 0.6524658203125 +60288 0.66339111328125 +60289 0.6561279296875 +60290 0.606781005859375 +60291 0.501190185546875 +60292 0.352783203125 +60293 0.176544189453125 +60294 -0.034820556640625 +60295 -0.258209228515625 +60296 -0.44244384765625 +60297 -0.5753173828125 +60298 -0.65203857421875 +60299 -0.641632080078125 +60300 -0.562164306640625 +60301 -0.458038330078125 +60302 -0.350555419921875 +60303 -0.260528564453125 +60304 -0.192108154296875 +60305 -0.141937255859375 +60306 -0.1021728515625 +60307 -0.062896728515625 +60308 -0.011932373046875 +60309 0.062835693359375 +60310 0.148712158203125 +60311 0.241729736328125 +60312 0.34912109375 +60313 0.457305908203125 +60314 0.54388427734375 +60315 0.5728759765625 +60316 0.506591796875 +60317 0.351226806640625 +60318 0.146514892578125 +60319 -0.05523681640625 +60320 -0.21624755859375 +60321 -0.334930419921875 +60322 -0.402984619140625 +60323 -0.4412841796875 +60324 -0.49578857421875 +60325 -0.5601806640625 +60326 -0.600738525390625 +60327 -0.584228515625 +60328 -0.47930908203125 +60329 -0.27935791015625 +60330 -0.0089111328125 +60331 0.268798828125 +60332 0.482818603515625 +60333 0.60369873046875 +60334 0.650421142578125 +60335 0.66400146484375 +60336 0.6414794921875 +60337 0.572540283203125 +60338 0.498138427734375 +60339 0.439453125 +60340 0.375518798828125 +60341 0.274505615234375 +60342 0.1087646484375 +60343 -0.099395751953125 +60344 -0.3182373046875 +60345 -0.5489501953125 +60346 -0.7738037109375 +60347 -0.86383056640625 +60348 -0.870391845703125 +60349 -0.86895751953125 +60350 -0.861053466796875 +60351 -0.765869140625 +60352 -0.5301513671875 +60353 -0.214691162109375 +60354 0.137359619140625 +60355 0.474822998046875 +60356 0.76239013671875 +60357 0.867462158203125 +60358 0.870361328125 +60359 0.86480712890625 +60360 0.831817626953125 +60361 0.677581787109375 +60362 0.495880126953125 +60363 0.30767822265625 +60364 0.116180419921875 +60365 -0.110748291015625 +60366 -0.381805419921875 +60367 -0.6572265625 +60368 -0.857421875 +60369 -0.870391845703125 +60370 -0.870391845703125 +60371 -0.86444091796875 +60372 -0.85723876953125 +60373 -0.790008544921875 +60374 -0.62847900390625 +60375 -0.3956298828125 +60376 -0.126708984375 +60377 0.150115966796875 +60378 0.424041748046875 +60379 0.670623779296875 +60380 0.854522705078125 +60381 0.866485595703125 +60382 0.86920166015625 +60383 0.8653564453125 +60384 0.857147216796875 +60385 0.766845703125 +60386 0.628509521484375 +60387 0.462127685546875 +60388 0.297210693359375 +60389 0.14862060546875 +60390 -0.00537109375 +60391 -0.15753173828125 +60392 -0.31304931640625 +60393 -0.48876953125 +60394 -0.6416015625 +60395 -0.751373291015625 +60396 -0.84619140625 +60397 -0.861297607421875 +60398 -0.863250732421875 +60399 -0.856597900390625 +60400 -0.7498779296875 +60401 -0.624542236328125 +60402 -0.47808837890625 +60403 -0.253387451171875 +60404 0.003692626953125 +60405 0.2257080078125 +60406 0.427154541015625 +60407 0.643218994140625 +60408 0.855926513671875 +60409 0.870361328125 +60410 0.870361328125 +60411 0.862762451171875 +60412 0.79669189453125 +60413 0.595794677734375 +60414 0.362152099609375 +60415 0.1270751953125 +60416 -0.086944580078125 +60417 -0.2784423828125 +60418 -0.484832763671875 +60419 -0.729583740234375 +60420 -0.86688232421875 +60421 -0.870391845703125 +60422 -0.86859130859375 +60423 -0.86279296875 +60424 -0.817962646484375 +60425 -0.6116943359375 +60426 -0.3128662109375 +60427 0.039398193359375 +60428 0.422821044921875 +60429 0.805145263671875 +60430 0.870361328125 +60431 0.870361328125 +60432 0.860015869140625 +60433 0.727935791015625 +60434 0.48114013671875 +60435 0.2059326171875 +60436 -0.06103515625 +60437 -0.29913330078125 +60438 -0.516204833984375 +60439 -0.7252197265625 +60440 -0.85980224609375 +60441 -0.870391845703125 +60442 -0.870391845703125 +60443 -0.858062744140625 +60444 -0.673004150390625 +60445 -0.42694091796875 +60446 -0.2100830078125 +60447 -0.0362548828125 +60448 0.10943603515625 +60449 0.23516845703125 +60450 0.373687744140625 +60451 0.517791748046875 +60452 0.602783203125 +60453 0.635711669921875 +60454 0.655181884765625 +60455 0.65948486328125 +60456 0.651275634765625 +60457 0.61846923828125 +60458 0.53753662109375 +60459 0.404144287109375 +60460 0.22186279296875 +60461 0.003997802734375 +60462 -0.22100830078125 +60463 -0.42449951171875 +60464 -0.579833984375 +60465 -0.641876220703125 +60466 -0.6177978515625 +60467 -0.575531005859375 +60468 -0.526336669921875 +60469 -0.42645263671875 +60470 -0.2581787109375 +60471 -0.068695068359375 +60472 0.09222412109375 +60473 0.232147216796875 +60474 0.3509521484375 +60475 0.410064697265625 +60476 0.372955322265625 +60477 0.2554931640625 +60478 0.10711669921875 +60479 -0.052886962890625 +60480 -0.186279296875 +60481 -0.23291015625 +60482 -0.209442138671875 +60483 -0.174163818359375 +60484 -0.126739501953125 +60485 -0.048126220703125 +60486 0.0426025390625 +60487 0.10748291015625 +60488 0.1409912109375 +60489 0.19708251953125 +60490 0.273651123046875 +60491 0.31768798828125 +60492 0.341094970703125 +60493 0.368011474609375 +60494 0.37249755859375 +60495 0.30072021484375 +60496 0.1517333984375 +60497 -0.01470947265625 +60498 -0.1883544921875 +60499 -0.372711181640625 +60500 -0.51397705078125 +60501 -0.57177734375 +60502 -0.53948974609375 +60503 -0.43511962890625 +60504 -0.2962646484375 +60505 -0.161102294921875 +60506 -0.0435791015625 +60507 0.060394287109375 +60508 0.13665771484375 +60509 0.170135498046875 +60510 0.16552734375 +60511 0.15728759765625 +60512 0.150787353515625 +60513 0.12200927734375 +60514 0.080108642578125 +60515 0.05126953125 +60516 0.062896728515625 +60517 0.09271240234375 +60518 0.092987060546875 +60519 0.07855224609375 +60520 0.06427001953125 +60521 0.0347900390625 +60522 -0.01171875 +60523 -0.056060791015625 +60524 -0.055511474609375 +60525 -0.010467529296875 +60526 0.02508544921875 +60527 0.025665283203125 +60528 0.017333984375 +60529 0.00189208984375 +60530 -0.03173828125 +60531 -0.071502685546875 +60532 -0.13543701171875 +60533 -0.219970703125 +60534 -0.300506591796875 +60535 -0.376312255859375 +60536 -0.416107177734375 +60537 -0.371124267578125 +60538 -0.242279052734375 +60539 -0.069732666015625 +60540 0.125640869140625 +60541 0.31268310546875 +60542 0.45501708984375 +60543 0.554779052734375 +60544 0.61065673828125 +60545 0.610931396484375 +60546 0.531463623046875 +60547 0.3883056640625 +60548 0.23468017578125 +60549 0.095245361328125 +60550 -0.00396728515625 +60551 -0.04852294921875 +60552 -0.055145263671875 +60553 -0.0758056640625 +60554 -0.138702392578125 +60555 -0.209197998046875 +60556 -0.289031982421875 +60557 -0.37884521484375 +60558 -0.456329345703125 +60559 -0.51641845703125 +60560 -0.519287109375 +60561 -0.458251953125 +60562 -0.384796142578125 +60563 -0.323699951171875 +60564 -0.269287109375 +60565 -0.1951904296875 +60566 -0.100006103515625 +60567 -0.01055908203125 +60568 0.1033935546875 +60569 0.24908447265625 +60570 0.373199462890625 +60571 0.45806884765625 +60572 0.511474609375 +60573 0.565399169921875 +60574 0.61138916015625 +60575 0.5897216796875 +60576 0.4906005859375 +60577 0.33148193359375 +60578 0.147796630859375 +60579 -0.01873779296875 +60580 -0.140289306640625 +60581 -0.191986083984375 +60582 -0.184295654296875 +60583 -0.161834716796875 +60584 -0.166595458984375 +60585 -0.19390869140625 +60586 -0.22442626953125 +60587 -0.279754638671875 +60588 -0.3389892578125 +60589 -0.3543701171875 +60590 -0.348175048828125 +60591 -0.32598876953125 +60592 -0.2581787109375 +60593 -0.139801025390625 +60594 0.014617919921875 +60595 0.144378662109375 +60596 0.221038818359375 +60597 0.27069091796875 +60598 0.294036865234375 +60599 0.311767578125 +60600 0.339141845703125 +60601 0.360260009765625 +60602 0.360504150390625 +60603 0.308380126953125 +60604 0.18170166015625 +60605 0.0047607421875 +60606 -0.17559814453125 +60607 -0.3143310546875 +60608 -0.36785888671875 +60609 -0.36248779296875 +60610 -0.343536376953125 +60611 -0.3018798828125 +60612 -0.231414794921875 +60613 -0.117645263671875 +60614 0.007049560546875 +60615 0.087982177734375 +60616 0.13946533203125 +60617 0.17425537109375 +60618 0.188201904296875 +60619 0.171234130859375 +60620 0.118438720703125 +60621 0.05706787109375 +60622 -0.010711669921875 +60623 -0.0914306640625 +60624 -0.162322998046875 +60625 -0.194549560546875 +60626 -0.1492919921875 +60627 -0.02166748046875 +60628 0.124053955078125 +60629 0.211151123046875 +60630 0.240447998046875 +60631 0.242218017578125 +60632 0.2257080078125 +60633 0.194366455078125 +60634 0.115509033203125 +60635 0.0128173828125 +60636 -0.053802490234375 +60637 -0.110626220703125 +60638 -0.199493408203125 +60639 -0.29437255859375 +60640 -0.33221435546875 +60641 -0.27972412109375 +60642 -0.185333251953125 +60643 -0.128204345703125 +60644 -0.115692138671875 +60645 -0.116455078125 +60646 -0.105926513671875 +60647 -0.053955078125 +60648 0.048797607421875 +60649 0.157318115234375 +60650 0.212005615234375 +60651 0.218475341796875 +60652 0.23724365234375 +60653 0.30535888671875 +60654 0.38128662109375 +60655 0.404449462890625 +60656 0.3944091796875 +60657 0.3885498046875 +60658 0.362640380859375 +60659 0.27362060546875 +60660 0.11712646484375 +60661 -0.054901123046875 +60662 -0.19085693359375 +60663 -0.28570556640625 +60664 -0.339263916015625 +60665 -0.3775634765625 +60666 -0.445709228515625 +60667 -0.535064697265625 +60668 -0.629058837890625 +60669 -0.697601318359375 +60670 -0.70391845703125 +60671 -0.6424560546875 +60672 -0.491241455078125 +60673 -0.265716552734375 +60674 -0.023712158203125 +60675 0.201751708984375 +60676 0.375823974609375 +60677 0.485076904296875 +60678 0.56884765625 +60679 0.634765625 +60680 0.63763427734375 +60681 0.5660400390625 +60682 0.4720458984375 +60683 0.40692138671875 +60684 0.3778076171875 +60685 0.376953125 +60686 0.371978759765625 +60687 0.313140869140625 +60688 0.184417724609375 +60689 0.011199951171875 +60690 -0.171051025390625 +60691 -0.33740234375 +60692 -0.47198486328125 +60693 -0.560394287109375 +60694 -0.58056640625 +60695 -0.54754638671875 +60696 -0.508575439453125 +60697 -0.459503173828125 +60698 -0.394378662109375 +60699 -0.35260009765625 +60700 -0.31170654296875 +60701 -0.197418212890625 +60702 -0.007965087890625 +60703 0.207489013671875 +60704 0.409210205078125 +60705 0.57208251953125 +60706 0.66595458984375 +60707 0.65875244140625 +60708 0.56744384765625 +60709 0.431396484375 +60710 0.29443359375 +60711 0.182464599609375 +60712 0.06365966796875 +60713 -0.075958251953125 +60714 -0.189422607421875 +60715 -0.271942138671875 +60716 -0.342529296875 +60717 -0.364166259765625 +60718 -0.327239990234375 +60719 -0.2769775390625 +60720 -0.253692626953125 +60721 -0.24365234375 +60722 -0.1983642578125 +60723 -0.116241455078125 +60724 -0.036834716796875 +60725 0.034881591796875 +60726 0.09124755859375 +60727 0.10888671875 +60728 0.125518798828125 +60729 0.15771484375 +60730 0.17828369140625 +60731 0.17108154296875 +60732 0.129974365234375 +60733 0.082427978515625 +60734 0.027679443359375 +60735 -0.065643310546875 +60736 -0.15936279296875 +60737 -0.21307373046875 +60738 -0.234649658203125 +60739 -0.2001953125 +60740 -0.119171142578125 +60741 -0.024749755859375 +60742 0.085784912109375 +60743 0.178131103515625 +60744 0.215576171875 +60745 0.211456298828125 +60746 0.17523193359375 +60747 0.128753662109375 +60748 0.1019287109375 +60749 0.0743408203125 +60750 0.04327392578125 +60751 0.038177490234375 +60752 0.076263427734375 +60753 0.14105224609375 +60754 0.186431884765625 +60755 0.188812255859375 +60756 0.1390380859375 +60757 0.041778564453125 +60758 -0.079437255859375 +60759 -0.219390869140625 +60760 -0.367828369140625 +60761 -0.494873046875 +60762 -0.556243896484375 +60763 -0.508697509765625 +60764 -0.3756103515625 +60765 -0.218902587890625 +60766 -0.063751220703125 +60767 0.091552734375 +60768 0.23602294921875 +60769 0.342987060546875 +60770 0.39520263671875 +60771 0.389373779296875 +60772 0.324249267578125 +60773 0.224090576171875 +60774 0.124267578125 +60775 0.037078857421875 +60776 -0.010101318359375 +60777 -0.019439697265625 +60778 -0.022796630859375 +60779 -0.001556396484375 +60780 0.056304931640625 +60781 0.106719970703125 +60782 0.096893310546875 +60783 0.042694091796875 +60784 -0.018035888671875 +60785 -0.07586669921875 +60786 -0.11944580078125 +60787 -0.15972900390625 +60788 -0.202606201171875 +60789 -0.24859619140625 +60790 -0.30517578125 +60791 -0.36212158203125 +60792 -0.39141845703125 +60793 -0.35528564453125 +60794 -0.249969482421875 +60795 -0.092864990234375 +60796 0.08905029296875 +60797 0.2352294921875 +60798 0.318817138671875 +60799 0.358642578125 +60800 0.347747802734375 +60801 0.28564453125 +60802 0.223175048828125 +60803 0.196746826171875 +60804 0.179840087890625 +60805 0.155548095703125 +60806 0.151214599609375 +60807 0.156951904296875 +60808 0.13177490234375 +60809 0.100799560546875 +60810 0.087127685546875 +60811 0.05487060546875 +60812 -0.009002685546875 +60813 -0.10400390625 +60814 -0.229400634765625 +60815 -0.35552978515625 +60816 -0.441925048828125 +60817 -0.473846435546875 +60818 -0.464813232421875 +60819 -0.419097900390625 +60820 -0.334320068359375 +60821 -0.227935791015625 +60822 -0.12347412109375 +60823 -0.02764892578125 +60824 0.077667236328125 +60825 0.2132568359375 +60826 0.38885498046875 +60827 0.582794189453125 +60828 0.734039306640625 +60829 0.800140380859375 +60830 0.7783203125 +60831 0.6651611328125 +60832 0.45965576171875 +60833 0.199188232421875 +60834 -0.050689697265625 +60835 -0.23297119140625 +60836 -0.33013916015625 +60837 -0.368408203125 +60838 -0.378936767578125 +60839 -0.376983642578125 +60840 -0.37969970703125 +60841 -0.391510009765625 +60842 -0.385345458984375 +60843 -0.3419189453125 +60844 -0.28289794921875 +60845 -0.251617431640625 +60846 -0.266143798828125 +60847 -0.273345947265625 +60848 -0.216796875 +60849 -0.128265380859375 +60850 -0.068145751953125 +60851 -0.0430908203125 +60852 -0.024444580078125 +60853 0.020721435546875 +60854 0.124481201171875 +60855 0.25787353515625 +60856 0.379119873046875 +60857 0.47991943359375 +60858 0.5281982421875 +60859 0.511138916015625 +60860 0.456207275390625 +60861 0.407470703125 +60862 0.383758544921875 +60863 0.35687255859375 +60864 0.31182861328125 +60865 0.250885009765625 +60866 0.1654052734375 +60867 0.035247802734375 +60868 -0.142059326171875 +60869 -0.33563232421875 +60870 -0.5345458984375 +60871 -0.72186279296875 +60872 -0.836669921875 +60873 -0.8326416015625 +60874 -0.7296142578125 +60875 -0.582550048828125 +60876 -0.440093994140625 +60877 -0.324310302734375 +60878 -0.20147705078125 +60879 -0.044647216796875 +60880 0.103973388671875 +60881 0.202392578125 +60882 0.264495849609375 +60883 0.338897705078125 +60884 0.443817138671875 +60885 0.545074462890625 +60886 0.6173095703125 +60887 0.6524658203125 +60888 0.66339111328125 +60889 0.6561279296875 +60890 0.606781005859375 +60891 0.501190185546875 +60892 0.352783203125 +60893 0.176544189453125 +60894 -0.034820556640625 +60895 -0.258209228515625 +60896 -0.44244384765625 +60897 -0.5753173828125 +60898 -0.65203857421875 +60899 -0.641632080078125 +60900 -0.562164306640625 +60901 -0.458038330078125 +60902 -0.350555419921875 +60903 -0.260528564453125 +60904 -0.192108154296875 +60905 -0.141937255859375 +60906 -0.1021728515625 +60907 -0.062896728515625 +60908 -0.011932373046875 +60909 0.062835693359375 +60910 0.148712158203125 +60911 0.241729736328125 +60912 0.34912109375 +60913 0.457305908203125 +60914 0.54388427734375 +60915 0.5728759765625 +60916 0.506591796875 +60917 0.351226806640625 +60918 0.146514892578125 +60919 -0.05523681640625 +60920 -0.21624755859375 +60921 -0.334930419921875 +60922 -0.402984619140625 +60923 -0.4412841796875 +60924 -0.49578857421875 +60925 -0.5601806640625 +60926 -0.600738525390625 +60927 -0.584228515625 +60928 -0.47930908203125 +60929 -0.27935791015625 +60930 -0.0089111328125 +60931 0.268798828125 +60932 0.482818603515625 +60933 0.60369873046875 +60934 0.650421142578125 +60935 0.66400146484375 +60936 0.6414794921875 +60937 0.572540283203125 +60938 0.498138427734375 +60939 0.439453125 +60940 0.375518798828125 +60941 0.274505615234375 +60942 0.1087646484375 +60943 -0.099395751953125 +60944 -0.3182373046875 +60945 -0.5489501953125 +60946 -0.7738037109375 +60947 -0.86383056640625 +60948 -0.870391845703125 +60949 -0.86895751953125 +60950 -0.861053466796875 +60951 -0.765869140625 +60952 -0.5301513671875 +60953 -0.214691162109375 +60954 0.137359619140625 +60955 0.474822998046875 +60956 0.76239013671875 +60957 0.867462158203125 +60958 0.870361328125 +60959 0.86480712890625 +60960 0.831817626953125 +60961 0.677581787109375 +60962 0.495880126953125 +60963 0.30767822265625 +60964 0.116180419921875 +60965 -0.110748291015625 +60966 -0.381805419921875 +60967 -0.6572265625 +60968 -0.857421875 +60969 -0.870391845703125 +60970 -0.870391845703125 +60971 -0.86444091796875 +60972 -0.85723876953125 +60973 -0.790008544921875 +60974 -0.62847900390625 +60975 -0.3956298828125 +60976 -0.126708984375 +60977 0.150115966796875 +60978 0.424041748046875 +60979 0.670623779296875 +60980 0.854522705078125 +60981 0.866485595703125 +60982 0.86920166015625 +60983 0.8653564453125 +60984 0.857147216796875 +60985 0.766845703125 +60986 0.628509521484375 +60987 0.462127685546875 +60988 0.297210693359375 +60989 0.14862060546875 +60990 -0.00537109375 +60991 -0.15753173828125 +60992 -0.31304931640625 +60993 -0.48876953125 +60994 -0.6416015625 +60995 -0.751373291015625 +60996 -0.84619140625 +60997 -0.861297607421875 +60998 -0.863250732421875 +60999 -0.856597900390625 +61000 -0.7498779296875 +61001 -0.624542236328125 +61002 -0.47808837890625 +61003 -0.253387451171875 +61004 0.003692626953125 +61005 0.2257080078125 +61006 0.427154541015625 +61007 0.643218994140625 +61008 0.855926513671875 +61009 0.870361328125 +61010 0.870361328125 +61011 0.862762451171875 +61012 0.79669189453125 +61013 0.595794677734375 +61014 0.362152099609375 +61015 0.1270751953125 +61016 -0.086944580078125 +61017 -0.2784423828125 +61018 -0.484832763671875 +61019 -0.729583740234375 +61020 -0.86688232421875 +61021 -0.870391845703125 +61022 -0.86859130859375 +61023 -0.86279296875 +61024 -0.817962646484375 +61025 -0.6116943359375 +61026 -0.3128662109375 +61027 0.039398193359375 +61028 0.422821044921875 +61029 0.805145263671875 +61030 0.870361328125 +61031 0.870361328125 +61032 0.860015869140625 +61033 0.727935791015625 +61034 0.48114013671875 +61035 0.2059326171875 +61036 -0.06103515625 +61037 -0.29913330078125 +61038 -0.516204833984375 +61039 -0.7252197265625 +61040 -0.85980224609375 +61041 -0.870391845703125 +61042 -0.870391845703125 +61043 -0.858062744140625 +61044 -0.673004150390625 +61045 -0.42694091796875 +61046 -0.2100830078125 +61047 -0.0362548828125 +61048 0.10943603515625 +61049 0.23516845703125 +61050 0.373687744140625 +61051 0.517791748046875 +61052 0.602783203125 +61053 0.635711669921875 +61054 0.655181884765625 +61055 0.65948486328125 +61056 0.651275634765625 +61057 0.61846923828125 +61058 0.53753662109375 +61059 0.404144287109375 +61060 0.22186279296875 +61061 0.003997802734375 +61062 -0.22100830078125 +61063 -0.42449951171875 +61064 -0.579833984375 +61065 -0.641876220703125 +61066 -0.6177978515625 +61067 -0.575531005859375 +61068 -0.526336669921875 +61069 -0.42645263671875 +61070 -0.2581787109375 +61071 -0.068695068359375 +61072 0.09222412109375 +61073 0.232147216796875 +61074 0.3509521484375 +61075 0.410064697265625 +61076 0.372955322265625 +61077 0.2554931640625 +61078 0.10711669921875 +61079 -0.052886962890625 +61080 -0.186279296875 +61081 -0.23291015625 +61082 -0.209442138671875 +61083 -0.174163818359375 +61084 -0.126739501953125 +61085 -0.048126220703125 +61086 0.0426025390625 +61087 0.10748291015625 +61088 0.1409912109375 +61089 0.19708251953125 +61090 0.273651123046875 +61091 0.31768798828125 +61092 0.341094970703125 +61093 0.368011474609375 +61094 0.37249755859375 +61095 0.30072021484375 +61096 0.1517333984375 +61097 -0.01470947265625 +61098 -0.1883544921875 +61099 -0.372711181640625 +61100 -0.51397705078125 +61101 -0.57177734375 +61102 -0.53948974609375 +61103 -0.43511962890625 +61104 -0.2962646484375 +61105 -0.161102294921875 +61106 -0.0435791015625 +61107 0.060394287109375 +61108 0.13665771484375 +61109 0.170135498046875 +61110 0.16552734375 +61111 0.15728759765625 +61112 0.150787353515625 +61113 0.12200927734375 +61114 0.080108642578125 +61115 0.05126953125 +61116 0.062896728515625 +61117 0.09271240234375 +61118 0.092987060546875 +61119 0.07855224609375 +61120 0.06427001953125 +61121 0.0347900390625 +61122 -0.01171875 +61123 -0.056060791015625 +61124 -0.055511474609375 +61125 -0.010467529296875 +61126 0.02508544921875 +61127 0.025665283203125 +61128 0.017333984375 +61129 0.00189208984375 +61130 -0.03173828125 +61131 -0.071502685546875 +61132 -0.13543701171875 +61133 -0.219970703125 +61134 -0.300506591796875 +61135 -0.376312255859375 +61136 -0.416107177734375 +61137 -0.371124267578125 +61138 -0.242279052734375 +61139 -0.069732666015625 +61140 0.125640869140625 +61141 0.31268310546875 +61142 0.45501708984375 +61143 0.554779052734375 +61144 0.61065673828125 +61145 0.610931396484375 +61146 0.531463623046875 +61147 0.3883056640625 +61148 0.23468017578125 +61149 0.095245361328125 +61150 -0.00396728515625 +61151 -0.04852294921875 +61152 -0.055145263671875 +61153 -0.0758056640625 +61154 -0.138702392578125 +61155 -0.209197998046875 +61156 -0.289031982421875 +61157 -0.37884521484375 +61158 -0.456329345703125 +61159 -0.51641845703125 +61160 -0.519287109375 +61161 -0.458251953125 +61162 -0.384796142578125 +61163 -0.323699951171875 +61164 -0.269287109375 +61165 -0.1951904296875 +61166 -0.100006103515625 +61167 -0.01055908203125 +61168 0.1033935546875 +61169 0.24908447265625 +61170 0.373199462890625 +61171 0.45806884765625 +61172 0.511474609375 +61173 0.565399169921875 +61174 0.61138916015625 +61175 0.5897216796875 +61176 0.4906005859375 +61177 0.33148193359375 +61178 0.147796630859375 +61179 -0.01873779296875 +61180 -0.140289306640625 +61181 -0.191986083984375 +61182 -0.184295654296875 +61183 -0.161834716796875 +61184 -0.166595458984375 +61185 -0.19390869140625 +61186 -0.22442626953125 +61187 -0.279754638671875 +61188 -0.3389892578125 +61189 -0.3543701171875 +61190 -0.348175048828125 +61191 -0.32598876953125 +61192 -0.2581787109375 +61193 -0.139801025390625 +61194 0.014617919921875 +61195 0.144378662109375 +61196 0.221038818359375 +61197 0.27069091796875 +61198 0.294036865234375 +61199 0.311767578125 +61200 0.339141845703125 +61201 0.360260009765625 +61202 0.360504150390625 +61203 0.308380126953125 +61204 0.18170166015625 +61205 0.0047607421875 +61206 -0.17559814453125 +61207 -0.3143310546875 +61208 -0.36785888671875 +61209 -0.36248779296875 +61210 -0.343536376953125 +61211 -0.3018798828125 +61212 -0.231414794921875 +61213 -0.117645263671875 +61214 0.007049560546875 +61215 0.087982177734375 +61216 0.13946533203125 +61217 0.17425537109375 +61218 0.188201904296875 +61219 0.171234130859375 +61220 0.118438720703125 +61221 0.05706787109375 +61222 -0.010711669921875 +61223 -0.0914306640625 +61224 -0.162322998046875 +61225 -0.194549560546875 +61226 -0.1492919921875 +61227 -0.02166748046875 +61228 0.124053955078125 +61229 0.211151123046875 +61230 0.240447998046875 +61231 0.242218017578125 +61232 0.2257080078125 +61233 0.194366455078125 +61234 0.115509033203125 +61235 0.0128173828125 +61236 -0.053802490234375 +61237 -0.110626220703125 +61238 -0.199493408203125 +61239 -0.29437255859375 +61240 -0.33221435546875 +61241 -0.27972412109375 +61242 -0.185333251953125 +61243 -0.128204345703125 +61244 -0.115692138671875 +61245 -0.116455078125 +61246 -0.105926513671875 +61247 -0.053955078125 +61248 0.048797607421875 +61249 0.157318115234375 +61250 0.212005615234375 +61251 0.218475341796875 +61252 0.23724365234375 +61253 0.30535888671875 +61254 0.38128662109375 +61255 0.404449462890625 +61256 0.3944091796875 +61257 0.3885498046875 +61258 0.362640380859375 +61259 0.27362060546875 +61260 0.11712646484375 +61261 -0.054901123046875 +61262 -0.19085693359375 +61263 -0.28570556640625 +61264 -0.339263916015625 +61265 -0.3775634765625 +61266 -0.445709228515625 +61267 -0.535064697265625 +61268 -0.629058837890625 +61269 -0.697601318359375 +61270 -0.70391845703125 +61271 -0.6424560546875 +61272 -0.491241455078125 +61273 -0.265716552734375 +61274 -0.023712158203125 +61275 0.201751708984375 +61276 0.375823974609375 +61277 0.485076904296875 +61278 0.56884765625 +61279 0.634765625 +61280 0.63763427734375 +61281 0.5660400390625 +61282 0.4720458984375 +61283 0.40692138671875 +61284 0.3778076171875 +61285 0.376953125 +61286 0.371978759765625 +61287 0.313140869140625 +61288 0.184417724609375 +61289 0.011199951171875 +61290 -0.171051025390625 +61291 -0.33740234375 +61292 -0.47198486328125 +61293 -0.560394287109375 +61294 -0.58056640625 +61295 -0.54754638671875 +61296 -0.508575439453125 +61297 -0.459503173828125 +61298 -0.394378662109375 +61299 -0.35260009765625 +61300 -0.31170654296875 +61301 -0.197418212890625 +61302 -0.007965087890625 +61303 0.207489013671875 +61304 0.409210205078125 +61305 0.57208251953125 +61306 0.66595458984375 +61307 0.65875244140625 +61308 0.56744384765625 +61309 0.431396484375 +61310 0.29443359375 +61311 0.182464599609375 +61312 0.06365966796875 +61313 -0.075958251953125 +61314 -0.189422607421875 +61315 -0.271942138671875 +61316 -0.342529296875 +61317 -0.364166259765625 +61318 -0.327239990234375 +61319 -0.2769775390625 +61320 -0.253692626953125 +61321 -0.24365234375 +61322 -0.1983642578125 +61323 -0.116241455078125 +61324 -0.036834716796875 +61325 0.034881591796875 +61326 0.09124755859375 +61327 0.10888671875 +61328 0.125518798828125 +61329 0.15771484375 +61330 0.17828369140625 +61331 0.17108154296875 +61332 0.129974365234375 +61333 0.082427978515625 +61334 0.027679443359375 +61335 -0.065643310546875 +61336 -0.15936279296875 +61337 -0.21307373046875 +61338 -0.234649658203125 +61339 -0.2001953125 +61340 -0.119171142578125 +61341 -0.024749755859375 +61342 0.085784912109375 +61343 0.178131103515625 +61344 0.215576171875 +61345 0.211456298828125 +61346 0.17523193359375 +61347 0.128753662109375 +61348 0.1019287109375 +61349 0.0743408203125 +61350 0.04327392578125 +61351 0.038177490234375 +61352 0.076263427734375 +61353 0.14105224609375 +61354 0.186431884765625 +61355 0.188812255859375 +61356 0.1390380859375 +61357 0.041778564453125 +61358 -0.079437255859375 +61359 -0.219390869140625 +61360 -0.367828369140625 +61361 -0.494873046875 +61362 -0.556243896484375 +61363 -0.508697509765625 +61364 -0.3756103515625 +61365 -0.218902587890625 +61366 -0.063751220703125 +61367 0.091552734375 +61368 0.23602294921875 +61369 0.342987060546875 +61370 0.39520263671875 +61371 0.389373779296875 +61372 0.324249267578125 +61373 0.224090576171875 +61374 0.124267578125 +61375 0.037078857421875 +61376 -0.010101318359375 +61377 -0.019439697265625 +61378 -0.022796630859375 +61379 -0.001556396484375 +61380 0.056304931640625 +61381 0.106719970703125 +61382 0.096893310546875 +61383 0.042694091796875 +61384 -0.018035888671875 +61385 -0.07586669921875 +61386 -0.11944580078125 +61387 -0.15972900390625 +61388 -0.202606201171875 +61389 -0.24859619140625 +61390 -0.30517578125 +61391 -0.36212158203125 +61392 -0.39141845703125 +61393 -0.35528564453125 +61394 -0.249969482421875 +61395 -0.092864990234375 +61396 0.08905029296875 +61397 0.2352294921875 +61398 0.318817138671875 +61399 0.358642578125 +61400 0.347747802734375 +61401 0.28564453125 +61402 0.223175048828125 +61403 0.196746826171875 +61404 0.179840087890625 +61405 0.155548095703125 +61406 0.151214599609375 +61407 0.156951904296875 +61408 0.13177490234375 +61409 0.100799560546875 +61410 0.087127685546875 +61411 0.05487060546875 +61412 -0.009002685546875 +61413 -0.10400390625 +61414 -0.229400634765625 +61415 -0.35552978515625 +61416 -0.441925048828125 +61417 -0.473846435546875 +61418 -0.464813232421875 +61419 -0.419097900390625 +61420 -0.334320068359375 +61421 -0.227935791015625 +61422 -0.12347412109375 +61423 -0.02764892578125 +61424 0.077667236328125 +61425 0.2132568359375 +61426 0.38885498046875 +61427 0.582794189453125 +61428 0.734039306640625 +61429 0.800140380859375 +61430 0.7783203125 +61431 0.6651611328125 +61432 0.45965576171875 +61433 0.199188232421875 +61434 -0.050689697265625 +61435 -0.23297119140625 +61436 -0.33013916015625 +61437 -0.368408203125 +61438 -0.378936767578125 +61439 -0.376983642578125 +61440 -0.37969970703125 +61441 -0.391510009765625 +61442 -0.385345458984375 +61443 -0.3419189453125 +61444 -0.28289794921875 +61445 -0.251617431640625 +61446 -0.266143798828125 +61447 -0.273345947265625 +61448 -0.216796875 +61449 -0.128265380859375 +61450 -0.068145751953125 +61451 -0.0430908203125 +61452 -0.024444580078125 +61453 0.020721435546875 +61454 0.124481201171875 +61455 0.25787353515625 +61456 0.379119873046875 +61457 0.47991943359375 +61458 0.5281982421875 +61459 0.511138916015625 +61460 0.456207275390625 +61461 0.407470703125 +61462 0.383758544921875 +61463 0.35687255859375 +61464 0.31182861328125 +61465 0.250885009765625 +61466 0.1654052734375 +61467 0.035247802734375 +61468 -0.142059326171875 +61469 -0.33563232421875 +61470 -0.5345458984375 +61471 -0.72186279296875 +61472 -0.836669921875 +61473 -0.8326416015625 +61474 -0.7296142578125 +61475 -0.582550048828125 +61476 -0.440093994140625 +61477 -0.324310302734375 +61478 -0.20147705078125 +61479 -0.044647216796875 +61480 0.103973388671875 +61481 0.202392578125 +61482 0.264495849609375 +61483 0.338897705078125 +61484 0.443817138671875 +61485 0.545074462890625 +61486 0.6173095703125 +61487 0.6524658203125 +61488 0.66339111328125 +61489 0.6561279296875 +61490 0.606781005859375 +61491 0.501190185546875 +61492 0.352783203125 +61493 0.176544189453125 +61494 -0.034820556640625 +61495 -0.258209228515625 +61496 -0.44244384765625 +61497 -0.5753173828125 +61498 -0.65203857421875 +61499 -0.641632080078125 +61500 -0.562164306640625 +61501 -0.458038330078125 +61502 -0.350555419921875 +61503 -0.260528564453125 +61504 -0.192108154296875 +61505 -0.141937255859375 +61506 -0.1021728515625 +61507 -0.062896728515625 +61508 -0.011932373046875 +61509 0.062835693359375 +61510 0.148712158203125 +61511 0.241729736328125 +61512 0.34912109375 +61513 0.457305908203125 +61514 0.54388427734375 +61515 0.5728759765625 +61516 0.506591796875 +61517 0.351226806640625 +61518 0.146514892578125 +61519 -0.05523681640625 +61520 -0.21624755859375 +61521 -0.334930419921875 +61522 -0.402984619140625 +61523 -0.4412841796875 +61524 -0.49578857421875 +61525 -0.5601806640625 +61526 -0.600738525390625 +61527 -0.584228515625 +61528 -0.47930908203125 +61529 -0.27935791015625 +61530 -0.0089111328125 +61531 0.268798828125 +61532 0.482818603515625 +61533 0.60369873046875 +61534 0.650421142578125 +61535 0.66400146484375 +61536 0.6414794921875 +61537 0.572540283203125 +61538 0.498138427734375 +61539 0.439453125 +61540 0.375518798828125 +61541 0.274505615234375 +61542 0.1087646484375 +61543 -0.099395751953125 +61544 -0.3182373046875 +61545 -0.5489501953125 +61546 -0.7738037109375 +61547 -0.86383056640625 +61548 -0.870391845703125 +61549 -0.86895751953125 +61550 -0.861053466796875 +61551 -0.765869140625 +61552 -0.5301513671875 +61553 -0.214691162109375 +61554 0.137359619140625 +61555 0.474822998046875 +61556 0.76239013671875 +61557 0.867462158203125 +61558 0.870361328125 +61559 0.86480712890625 +61560 0.831817626953125 +61561 0.677581787109375 +61562 0.495880126953125 +61563 0.30767822265625 +61564 0.116180419921875 +61565 -0.110748291015625 +61566 -0.381805419921875 +61567 -0.6572265625 +61568 -0.857421875 +61569 -0.870391845703125 +61570 -0.870391845703125 +61571 -0.86444091796875 +61572 -0.85723876953125 +61573 -0.790008544921875 +61574 -0.62847900390625 +61575 -0.3956298828125 +61576 -0.126708984375 +61577 0.150115966796875 +61578 0.424041748046875 +61579 0.670623779296875 +61580 0.854522705078125 +61581 0.866485595703125 +61582 0.86920166015625 +61583 0.8653564453125 +61584 0.857147216796875 +61585 0.766845703125 +61586 0.628509521484375 +61587 0.462127685546875 +61588 0.297210693359375 +61589 0.14862060546875 +61590 -0.00537109375 +61591 -0.15753173828125 +61592 -0.31304931640625 +61593 -0.48876953125 +61594 -0.6416015625 +61595 -0.751373291015625 +61596 -0.84619140625 +61597 -0.861297607421875 +61598 -0.863250732421875 +61599 -0.856597900390625 +61600 -0.7498779296875 +61601 -0.624542236328125 +61602 -0.47808837890625 +61603 -0.253387451171875 +61604 0.003692626953125 +61605 0.2257080078125 +61606 0.427154541015625 +61607 0.643218994140625 +61608 0.855926513671875 +61609 0.870361328125 +61610 0.870361328125 +61611 0.862762451171875 +61612 0.79669189453125 +61613 0.595794677734375 +61614 0.362152099609375 +61615 0.1270751953125 +61616 -0.086944580078125 +61617 -0.2784423828125 +61618 -0.484832763671875 +61619 -0.729583740234375 +61620 -0.86688232421875 +61621 -0.870391845703125 +61622 -0.86859130859375 +61623 -0.86279296875 +61624 -0.817962646484375 +61625 -0.6116943359375 +61626 -0.3128662109375 +61627 0.039398193359375 +61628 0.422821044921875 +61629 0.805145263671875 +61630 0.870361328125 +61631 0.870361328125 +61632 0.860015869140625 +61633 0.727935791015625 +61634 0.48114013671875 +61635 0.2059326171875 +61636 -0.06103515625 +61637 -0.29913330078125 +61638 -0.516204833984375 +61639 -0.7252197265625 +61640 -0.85980224609375 +61641 -0.870391845703125 +61642 -0.870391845703125 +61643 -0.858062744140625 +61644 -0.673004150390625 +61645 -0.42694091796875 +61646 -0.2100830078125 +61647 -0.0362548828125 +61648 0.10943603515625 +61649 0.23516845703125 +61650 0.373687744140625 +61651 0.517791748046875 +61652 0.602783203125 +61653 0.635711669921875 +61654 0.655181884765625 +61655 0.65948486328125 +61656 0.651275634765625 +61657 0.61846923828125 +61658 0.53753662109375 +61659 0.404144287109375 +61660 0.22186279296875 +61661 0.003997802734375 +61662 -0.22100830078125 +61663 -0.42449951171875 +61664 -0.579833984375 +61665 -0.641876220703125 +61666 -0.6177978515625 +61667 -0.575531005859375 +61668 -0.526336669921875 +61669 -0.42645263671875 +61670 -0.2581787109375 +61671 -0.068695068359375 +61672 0.09222412109375 +61673 0.232147216796875 +61674 0.3509521484375 +61675 0.410064697265625 +61676 0.372955322265625 +61677 0.2554931640625 +61678 0.10711669921875 +61679 -0.052886962890625 +61680 -0.186279296875 +61681 -0.23291015625 +61682 -0.209442138671875 +61683 -0.174163818359375 +61684 -0.126739501953125 +61685 -0.048126220703125 +61686 0.0426025390625 +61687 0.10748291015625 +61688 0.1409912109375 +61689 0.19708251953125 +61690 0.273651123046875 +61691 0.31768798828125 +61692 0.341094970703125 +61693 0.368011474609375 +61694 0.37249755859375 +61695 0.30072021484375 +61696 0.1517333984375 +61697 -0.01470947265625 +61698 -0.1883544921875 +61699 -0.372711181640625 +61700 -0.51397705078125 +61701 -0.57177734375 +61702 -0.53948974609375 +61703 -0.43511962890625 +61704 -0.2962646484375 +61705 -0.161102294921875 +61706 -0.0435791015625 +61707 0.060394287109375 +61708 0.13665771484375 +61709 0.170135498046875 +61710 0.16552734375 +61711 0.15728759765625 +61712 0.150787353515625 +61713 0.12200927734375 +61714 0.080108642578125 +61715 0.05126953125 +61716 0.062896728515625 +61717 0.09271240234375 +61718 0.092987060546875 +61719 0.07855224609375 +61720 0.06427001953125 +61721 0.0347900390625 +61722 -0.01171875 +61723 -0.056060791015625 +61724 -0.055511474609375 +61725 -0.010467529296875 +61726 0.02508544921875 +61727 0.025665283203125 +61728 0.017333984375 +61729 0.00189208984375 +61730 -0.03173828125 +61731 -0.071502685546875 +61732 -0.13543701171875 +61733 -0.219970703125 +61734 -0.300506591796875 +61735 -0.376312255859375 +61736 -0.416107177734375 +61737 -0.371124267578125 +61738 -0.242279052734375 +61739 -0.069732666015625 +61740 0.125640869140625 +61741 0.31268310546875 +61742 0.45501708984375 +61743 0.554779052734375 +61744 0.61065673828125 +61745 0.610931396484375 +61746 0.531463623046875 +61747 0.3883056640625 +61748 0.23468017578125 +61749 0.095245361328125 +61750 -0.00396728515625 +61751 -0.04852294921875 +61752 -0.055145263671875 +61753 -0.0758056640625 +61754 -0.138702392578125 +61755 -0.209197998046875 +61756 -0.289031982421875 +61757 -0.37884521484375 +61758 -0.456329345703125 +61759 -0.51641845703125 +61760 -0.519287109375 +61761 -0.458251953125 +61762 -0.384796142578125 +61763 -0.323699951171875 +61764 -0.269287109375 +61765 -0.1951904296875 +61766 -0.100006103515625 +61767 -0.01055908203125 +61768 0.1033935546875 +61769 0.24908447265625 +61770 0.373199462890625 +61771 0.45806884765625 +61772 0.511474609375 +61773 0.565399169921875 +61774 0.61138916015625 +61775 0.5897216796875 +61776 0.4906005859375 +61777 0.33148193359375 +61778 0.147796630859375 +61779 -0.01873779296875 +61780 -0.140289306640625 +61781 -0.191986083984375 +61782 -0.184295654296875 +61783 -0.161834716796875 +61784 -0.166595458984375 +61785 -0.19390869140625 +61786 -0.22442626953125 +61787 -0.279754638671875 +61788 -0.3389892578125 +61789 -0.3543701171875 +61790 -0.348175048828125 +61791 -0.32598876953125 +61792 -0.2581787109375 +61793 -0.139801025390625 +61794 0.014617919921875 +61795 0.144378662109375 +61796 0.221038818359375 +61797 0.27069091796875 +61798 0.294036865234375 +61799 0.311767578125 +61800 0.339141845703125 +61801 0.360260009765625 +61802 0.360504150390625 +61803 0.308380126953125 +61804 0.18170166015625 +61805 0.0047607421875 +61806 -0.17559814453125 +61807 -0.3143310546875 +61808 -0.36785888671875 +61809 -0.36248779296875 +61810 -0.343536376953125 +61811 -0.3018798828125 +61812 -0.231414794921875 +61813 -0.117645263671875 +61814 0.007049560546875 +61815 0.087982177734375 +61816 0.13946533203125 +61817 0.17425537109375 +61818 0.188201904296875 +61819 0.171234130859375 +61820 0.118438720703125 +61821 0.05706787109375 +61822 -0.010711669921875 +61823 -0.0914306640625 +61824 -0.162322998046875 +61825 -0.194549560546875 +61826 -0.1492919921875 +61827 -0.02166748046875 +61828 0.124053955078125 +61829 0.211151123046875 +61830 0.240447998046875 +61831 0.242218017578125 +61832 0.2257080078125 +61833 0.194366455078125 +61834 0.115509033203125 +61835 0.0128173828125 +61836 -0.053802490234375 +61837 -0.110626220703125 +61838 -0.199493408203125 +61839 -0.29437255859375 +61840 -0.33221435546875 +61841 -0.27972412109375 +61842 -0.185333251953125 +61843 -0.128204345703125 +61844 -0.115692138671875 +61845 -0.116455078125 +61846 -0.105926513671875 +61847 -0.053955078125 +61848 0.048797607421875 +61849 0.157318115234375 +61850 0.212005615234375 +61851 0.218475341796875 +61852 0.23724365234375 +61853 0.30535888671875 +61854 0.38128662109375 +61855 0.404449462890625 +61856 0.3944091796875 +61857 0.3885498046875 +61858 0.362640380859375 +61859 0.27362060546875 +61860 0.11712646484375 +61861 -0.054901123046875 +61862 -0.19085693359375 +61863 -0.28570556640625 +61864 -0.339263916015625 +61865 -0.3775634765625 +61866 -0.445709228515625 +61867 -0.535064697265625 +61868 -0.629058837890625 +61869 -0.697601318359375 +61870 -0.70391845703125 +61871 -0.6424560546875 +61872 -0.491241455078125 +61873 -0.265716552734375 +61874 -0.023712158203125 +61875 0.201751708984375 +61876 0.375823974609375 +61877 0.485076904296875 +61878 0.56884765625 +61879 0.634765625 +61880 0.63763427734375 +61881 0.5660400390625 +61882 0.4720458984375 +61883 0.40692138671875 +61884 0.3778076171875 +61885 0.376953125 +61886 0.371978759765625 +61887 0.313140869140625 +61888 0.184417724609375 +61889 0.011199951171875 +61890 -0.171051025390625 +61891 -0.33740234375 +61892 -0.47198486328125 +61893 -0.560394287109375 +61894 -0.58056640625 +61895 -0.54754638671875 +61896 -0.508575439453125 +61897 -0.459503173828125 +61898 -0.394378662109375 +61899 -0.35260009765625 +61900 -0.31170654296875 +61901 -0.197418212890625 +61902 -0.007965087890625 +61903 0.207489013671875 +61904 0.409210205078125 +61905 0.57208251953125 +61906 0.66595458984375 +61907 0.65875244140625 +61908 0.56744384765625 +61909 0.431396484375 +61910 0.29443359375 +61911 0.182464599609375 +61912 0.06365966796875 +61913 -0.075958251953125 +61914 -0.189422607421875 +61915 -0.271942138671875 +61916 -0.342529296875 +61917 -0.364166259765625 +61918 -0.327239990234375 +61919 -0.2769775390625 +61920 -0.253692626953125 +61921 -0.24365234375 +61922 -0.1983642578125 +61923 -0.116241455078125 +61924 -0.036834716796875 +61925 0.034881591796875 +61926 0.09124755859375 +61927 0.10888671875 +61928 0.125518798828125 +61929 0.15771484375 +61930 0.17828369140625 +61931 0.17108154296875 +61932 0.129974365234375 +61933 0.082427978515625 +61934 0.027679443359375 +61935 -0.065643310546875 +61936 -0.15936279296875 +61937 -0.21307373046875 +61938 -0.234649658203125 +61939 -0.2001953125 +61940 -0.119171142578125 +61941 -0.024749755859375 +61942 0.085784912109375 +61943 0.178131103515625 +61944 0.215576171875 +61945 0.211456298828125 +61946 0.17523193359375 +61947 0.128753662109375 +61948 0.1019287109375 +61949 0.0743408203125 +61950 0.04327392578125 +61951 0.038177490234375 +61952 0.076263427734375 +61953 0.14105224609375 +61954 0.186431884765625 +61955 0.188812255859375 +61956 0.1390380859375 +61957 0.041778564453125 +61958 -0.079437255859375 +61959 -0.219390869140625 +61960 -0.367828369140625 +61961 -0.494873046875 +61962 -0.556243896484375 +61963 -0.508697509765625 +61964 -0.3756103515625 +61965 -0.218902587890625 +61966 -0.063751220703125 +61967 0.091552734375 +61968 0.23602294921875 +61969 0.342987060546875 +61970 0.39520263671875 +61971 0.389373779296875 +61972 0.324249267578125 +61973 0.224090576171875 +61974 0.124267578125 +61975 0.037078857421875 +61976 -0.010101318359375 +61977 -0.019439697265625 +61978 -0.022796630859375 +61979 -0.001556396484375 +61980 0.056304931640625 +61981 0.106719970703125 +61982 0.096893310546875 +61983 0.042694091796875 +61984 -0.018035888671875 +61985 -0.07586669921875 +61986 -0.11944580078125 +61987 -0.15972900390625 +61988 -0.202606201171875 +61989 -0.24859619140625 +61990 -0.30517578125 +61991 -0.36212158203125 +61992 -0.39141845703125 +61993 -0.35528564453125 +61994 -0.249969482421875 +61995 -0.092864990234375 +61996 0.08905029296875 +61997 0.2352294921875 +61998 0.318817138671875 +61999 0.358642578125 +62000 0.347747802734375 +62001 0.28564453125 +62002 0.223175048828125 +62003 0.196746826171875 +62004 0.179840087890625 +62005 0.155548095703125 +62006 0.151214599609375 +62007 0.156951904296875 +62008 0.13177490234375 +62009 0.100799560546875 +62010 0.087127685546875 +62011 0.05487060546875 +62012 -0.009002685546875 +62013 -0.10400390625 +62014 -0.229400634765625 +62015 -0.35552978515625 +62016 -0.441925048828125 +62017 -0.473846435546875 +62018 -0.464813232421875 +62019 -0.419097900390625 +62020 -0.334320068359375 +62021 -0.227935791015625 +62022 -0.12347412109375 +62023 -0.02764892578125 +62024 0.077667236328125 +62025 0.2132568359375 +62026 0.38885498046875 +62027 0.582794189453125 +62028 0.734039306640625 +62029 0.800140380859375 +62030 0.7783203125 +62031 0.6651611328125 +62032 0.45965576171875 +62033 0.199188232421875 +62034 -0.050689697265625 +62035 -0.23297119140625 +62036 -0.33013916015625 +62037 -0.368408203125 +62038 -0.378936767578125 +62039 -0.376983642578125 +62040 -0.37969970703125 +62041 -0.391510009765625 +62042 -0.385345458984375 +62043 -0.3419189453125 +62044 -0.28289794921875 +62045 -0.251617431640625 +62046 -0.266143798828125 +62047 -0.273345947265625 +62048 -0.216796875 +62049 -0.128265380859375 +62050 -0.068145751953125 +62051 -0.0430908203125 +62052 -0.024444580078125 +62053 0.020721435546875 +62054 0.124481201171875 +62055 0.25787353515625 +62056 0.379119873046875 +62057 0.47991943359375 +62058 0.5281982421875 +62059 0.511138916015625 +62060 0.456207275390625 +62061 0.407470703125 +62062 0.383758544921875 +62063 0.35687255859375 +62064 0.31182861328125 +62065 0.250885009765625 +62066 0.1654052734375 +62067 0.035247802734375 +62068 -0.142059326171875 +62069 -0.33563232421875 +62070 -0.5345458984375 +62071 -0.72186279296875 +62072 -0.836669921875 +62073 -0.8326416015625 +62074 -0.7296142578125 +62075 -0.582550048828125 +62076 -0.440093994140625 +62077 -0.324310302734375 +62078 -0.20147705078125 +62079 -0.044647216796875 +62080 0.103973388671875 +62081 0.202392578125 +62082 0.264495849609375 +62083 0.338897705078125 +62084 0.443817138671875 +62085 0.545074462890625 +62086 0.6173095703125 +62087 0.6524658203125 +62088 0.66339111328125 +62089 0.6561279296875 +62090 0.606781005859375 +62091 0.501190185546875 +62092 0.352783203125 +62093 0.176544189453125 +62094 -0.034820556640625 +62095 -0.258209228515625 +62096 -0.44244384765625 +62097 -0.5753173828125 +62098 -0.65203857421875 +62099 -0.641632080078125 +62100 -0.562164306640625 +62101 -0.458038330078125 +62102 -0.350555419921875 +62103 -0.260528564453125 +62104 -0.192108154296875 +62105 -0.141937255859375 +62106 -0.1021728515625 +62107 -0.062896728515625 +62108 -0.011932373046875 +62109 0.062835693359375 +62110 0.148712158203125 +62111 0.241729736328125 +62112 0.34912109375 +62113 0.457305908203125 +62114 0.54388427734375 +62115 0.5728759765625 +62116 0.506591796875 +62117 0.351226806640625 +62118 0.146514892578125 +62119 -0.05523681640625 +62120 -0.21624755859375 +62121 -0.334930419921875 +62122 -0.402984619140625 +62123 -0.4412841796875 +62124 -0.49578857421875 +62125 -0.5601806640625 +62126 -0.600738525390625 +62127 -0.584228515625 +62128 -0.47930908203125 +62129 -0.27935791015625 +62130 -0.0089111328125 +62131 0.268798828125 +62132 0.482818603515625 +62133 0.60369873046875 +62134 0.650421142578125 +62135 0.66400146484375 +62136 0.6414794921875 +62137 0.572540283203125 +62138 0.498138427734375 +62139 0.439453125 +62140 0.375518798828125 +62141 0.274505615234375 +62142 0.1087646484375 +62143 -0.099395751953125 +62144 -0.3182373046875 +62145 -0.5489501953125 +62146 -0.7738037109375 +62147 -0.86383056640625 +62148 -0.870391845703125 +62149 -0.86895751953125 +62150 -0.861053466796875 +62151 -0.765869140625 +62152 -0.5301513671875 +62153 -0.214691162109375 +62154 0.137359619140625 +62155 0.474822998046875 +62156 0.76239013671875 +62157 0.867462158203125 +62158 0.870361328125 +62159 0.86480712890625 +62160 0.831817626953125 +62161 0.677581787109375 +62162 0.495880126953125 +62163 0.30767822265625 +62164 0.116180419921875 +62165 -0.110748291015625 +62166 -0.381805419921875 +62167 -0.6572265625 +62168 -0.857421875 +62169 -0.870391845703125 +62170 -0.870391845703125 +62171 -0.86444091796875 +62172 -0.85723876953125 +62173 -0.790008544921875 +62174 -0.62847900390625 +62175 -0.3956298828125 +62176 -0.126708984375 +62177 0.150115966796875 +62178 0.424041748046875 +62179 0.670623779296875 +62180 0.854522705078125 +62181 0.866485595703125 +62182 0.86920166015625 +62183 0.8653564453125 +62184 0.857147216796875 +62185 0.766845703125 +62186 0.628509521484375 +62187 0.462127685546875 +62188 0.297210693359375 +62189 0.14862060546875 +62190 -0.00537109375 +62191 -0.15753173828125 +62192 -0.31304931640625 +62193 -0.48876953125 +62194 -0.6416015625 +62195 -0.751373291015625 +62196 -0.84619140625 +62197 -0.861297607421875 +62198 -0.863250732421875 +62199 -0.856597900390625 +62200 -0.7498779296875 +62201 -0.624542236328125 +62202 -0.47808837890625 +62203 -0.253387451171875 +62204 0.003692626953125 +62205 0.2257080078125 +62206 0.427154541015625 +62207 0.643218994140625 +62208 0.855926513671875 +62209 0.870361328125 +62210 0.870361328125 +62211 0.862762451171875 +62212 0.79669189453125 +62213 0.595794677734375 +62214 0.362152099609375 +62215 0.1270751953125 +62216 -0.086944580078125 +62217 -0.2784423828125 +62218 -0.484832763671875 +62219 -0.729583740234375 +62220 -0.86688232421875 +62221 -0.870391845703125 +62222 -0.86859130859375 +62223 -0.86279296875 +62224 -0.817962646484375 +62225 -0.6116943359375 +62226 -0.3128662109375 +62227 0.039398193359375 +62228 0.422821044921875 +62229 0.805145263671875 +62230 0.870361328125 +62231 0.870361328125 +62232 0.860015869140625 +62233 0.727935791015625 +62234 0.48114013671875 +62235 0.2059326171875 +62236 -0.06103515625 +62237 -0.29913330078125 +62238 -0.516204833984375 +62239 -0.7252197265625 +62240 -0.85980224609375 +62241 -0.870391845703125 +62242 -0.870391845703125 +62243 -0.858062744140625 +62244 -0.673004150390625 +62245 -0.42694091796875 +62246 -0.2100830078125 +62247 -0.0362548828125 +62248 0.10943603515625 +62249 0.23516845703125 +62250 0.373687744140625 +62251 0.517791748046875 +62252 0.602783203125 +62253 0.635711669921875 +62254 0.655181884765625 +62255 0.65948486328125 +62256 0.651275634765625 +62257 0.61846923828125 +62258 0.53753662109375 +62259 0.404144287109375 +62260 0.22186279296875 +62261 0.003997802734375 +62262 -0.22100830078125 +62263 -0.42449951171875 +62264 -0.579833984375 +62265 -0.641876220703125 +62266 -0.6177978515625 +62267 -0.575531005859375 +62268 -0.526336669921875 +62269 -0.42645263671875 +62270 -0.2581787109375 +62271 -0.068695068359375 +62272 0.09222412109375 +62273 0.232147216796875 +62274 0.3509521484375 +62275 0.410064697265625 +62276 0.372955322265625 +62277 0.2554931640625 +62278 0.10711669921875 +62279 -0.052886962890625 +62280 -0.186279296875 +62281 -0.23291015625 +62282 -0.209442138671875 +62283 -0.174163818359375 +62284 -0.126739501953125 +62285 -0.048126220703125 +62286 0.0426025390625 +62287 0.10748291015625 +62288 0.1409912109375 +62289 0.19708251953125 +62290 0.273651123046875 +62291 0.31768798828125 +62292 0.341094970703125 +62293 0.368011474609375 +62294 0.37249755859375 +62295 0.30072021484375 +62296 0.1517333984375 +62297 -0.01470947265625 +62298 -0.1883544921875 +62299 -0.372711181640625 +62300 -0.51397705078125 +62301 -0.57177734375 +62302 -0.53948974609375 +62303 -0.43511962890625 +62304 -0.2962646484375 +62305 -0.161102294921875 +62306 -0.0435791015625 +62307 0.060394287109375 +62308 0.13665771484375 +62309 0.170135498046875 +62310 0.16552734375 +62311 0.15728759765625 +62312 0.150787353515625 +62313 0.12200927734375 +62314 0.080108642578125 +62315 0.05126953125 +62316 0.062896728515625 +62317 0.09271240234375 +62318 0.092987060546875 +62319 0.07855224609375 +62320 0.06427001953125 +62321 0.0347900390625 +62322 -0.01171875 +62323 -0.056060791015625 +62324 -0.055511474609375 +62325 -0.010467529296875 +62326 0.02508544921875 +62327 0.025665283203125 +62328 0.017333984375 +62329 0.00189208984375 +62330 -0.03173828125 +62331 -0.071502685546875 +62332 -0.13543701171875 +62333 -0.219970703125 +62334 -0.300506591796875 +62335 -0.376312255859375 +62336 -0.416107177734375 +62337 -0.371124267578125 +62338 -0.242279052734375 +62339 -0.069732666015625 +62340 0.125640869140625 +62341 0.31268310546875 +62342 0.45501708984375 +62343 0.554779052734375 +62344 0.61065673828125 +62345 0.610931396484375 +62346 0.531463623046875 +62347 0.3883056640625 +62348 0.23468017578125 +62349 0.095245361328125 +62350 -0.00396728515625 +62351 -0.04852294921875 +62352 -0.055145263671875 +62353 -0.0758056640625 +62354 -0.138702392578125 +62355 -0.209197998046875 +62356 -0.289031982421875 +62357 -0.37884521484375 +62358 -0.456329345703125 +62359 -0.51641845703125 +62360 -0.519287109375 +62361 -0.458251953125 +62362 -0.384796142578125 +62363 -0.323699951171875 +62364 -0.269287109375 +62365 -0.1951904296875 +62366 -0.100006103515625 +62367 -0.01055908203125 +62368 0.1033935546875 +62369 0.24908447265625 +62370 0.373199462890625 +62371 0.45806884765625 +62372 0.511474609375 +62373 0.565399169921875 +62374 0.61138916015625 +62375 0.5897216796875 +62376 0.4906005859375 +62377 0.33148193359375 +62378 0.147796630859375 +62379 -0.01873779296875 +62380 -0.140289306640625 +62381 -0.191986083984375 +62382 -0.184295654296875 +62383 -0.161834716796875 +62384 -0.166595458984375 +62385 -0.19390869140625 +62386 -0.22442626953125 +62387 -0.279754638671875 +62388 -0.3389892578125 +62389 -0.3543701171875 +62390 -0.348175048828125 +62391 -0.32598876953125 +62392 -0.2581787109375 +62393 -0.139801025390625 +62394 0.014617919921875 +62395 0.144378662109375 +62396 0.221038818359375 +62397 0.27069091796875 +62398 0.294036865234375 +62399 0.311767578125 +62400 0.339141845703125 +62401 0.360260009765625 +62402 0.360504150390625 +62403 0.308380126953125 +62404 0.18170166015625 +62405 0.0047607421875 +62406 -0.17559814453125 +62407 -0.3143310546875 +62408 -0.36785888671875 +62409 -0.36248779296875 +62410 -0.343536376953125 +62411 -0.3018798828125 +62412 -0.231414794921875 +62413 -0.117645263671875 +62414 0.007049560546875 +62415 0.087982177734375 +62416 0.13946533203125 +62417 0.17425537109375 +62418 0.188201904296875 +62419 0.171234130859375 +62420 0.118438720703125 +62421 0.05706787109375 +62422 -0.010711669921875 +62423 -0.0914306640625 +62424 -0.162322998046875 +62425 -0.194549560546875 +62426 -0.1492919921875 +62427 -0.02166748046875 +62428 0.124053955078125 +62429 0.211151123046875 +62430 0.240447998046875 +62431 0.242218017578125 +62432 0.2257080078125 +62433 0.194366455078125 +62434 0.115509033203125 +62435 0.0128173828125 +62436 -0.053802490234375 +62437 -0.110626220703125 +62438 -0.199493408203125 +62439 -0.29437255859375 +62440 -0.33221435546875 +62441 -0.27972412109375 +62442 -0.185333251953125 +62443 -0.128204345703125 +62444 -0.115692138671875 +62445 -0.116455078125 +62446 -0.105926513671875 +62447 -0.053955078125 +62448 0.048797607421875 +62449 0.157318115234375 +62450 0.212005615234375 +62451 0.218475341796875 +62452 0.23724365234375 +62453 0.30535888671875 +62454 0.38128662109375 +62455 0.404449462890625 +62456 0.3944091796875 +62457 0.3885498046875 +62458 0.362640380859375 +62459 0.27362060546875 +62460 0.11712646484375 +62461 -0.054901123046875 +62462 -0.19085693359375 +62463 -0.28570556640625 +62464 -0.339263916015625 +62465 -0.3775634765625 +62466 -0.445709228515625 +62467 -0.535064697265625 +62468 -0.629058837890625 +62469 -0.697601318359375 +62470 -0.70391845703125 +62471 -0.6424560546875 +62472 -0.491241455078125 +62473 -0.265716552734375 +62474 -0.023712158203125 +62475 0.201751708984375 +62476 0.375823974609375 +62477 0.485076904296875 +62478 0.56884765625 +62479 0.634765625 +62480 0.63763427734375 +62481 0.5660400390625 +62482 0.4720458984375 +62483 0.40692138671875 +62484 0.3778076171875 +62485 0.376953125 +62486 0.371978759765625 +62487 0.313140869140625 +62488 0.184417724609375 +62489 0.011199951171875 +62490 -0.171051025390625 +62491 -0.33740234375 +62492 -0.47198486328125 +62493 -0.560394287109375 +62494 -0.58056640625 +62495 -0.54754638671875 +62496 -0.508575439453125 +62497 -0.459503173828125 +62498 -0.394378662109375 +62499 -0.35260009765625 +62500 -0.31170654296875 +62501 -0.197418212890625 +62502 -0.007965087890625 +62503 0.207489013671875 +62504 0.409210205078125 +62505 0.57208251953125 +62506 0.66595458984375 +62507 0.65875244140625 +62508 0.56744384765625 +62509 0.431396484375 +62510 0.29443359375 +62511 0.182464599609375 +62512 0.06365966796875 +62513 -0.075958251953125 +62514 -0.189422607421875 +62515 -0.271942138671875 +62516 -0.342529296875 +62517 -0.364166259765625 +62518 -0.327239990234375 +62519 -0.2769775390625 +62520 -0.253692626953125 +62521 -0.24365234375 +62522 -0.1983642578125 +62523 -0.116241455078125 +62524 -0.036834716796875 +62525 0.034881591796875 +62526 0.09124755859375 +62527 0.10888671875 +62528 0.125518798828125 +62529 0.15771484375 +62530 0.17828369140625 +62531 0.17108154296875 +62532 0.129974365234375 +62533 0.082427978515625 +62534 0.027679443359375 +62535 -0.065643310546875 +62536 -0.15936279296875 +62537 -0.21307373046875 +62538 -0.234649658203125 +62539 -0.2001953125 +62540 -0.119171142578125 +62541 -0.024749755859375 +62542 0.085784912109375 +62543 0.178131103515625 +62544 0.215576171875 +62545 0.211456298828125 +62546 0.17523193359375 +62547 0.128753662109375 +62548 0.1019287109375 +62549 0.0743408203125 +62550 0.04327392578125 +62551 0.038177490234375 +62552 0.076263427734375 +62553 0.14105224609375 +62554 0.186431884765625 +62555 0.188812255859375 +62556 0.1390380859375 +62557 0.041778564453125 +62558 -0.079437255859375 +62559 -0.219390869140625 +62560 -0.367828369140625 +62561 -0.494873046875 +62562 -0.556243896484375 +62563 -0.508697509765625 +62564 -0.3756103515625 +62565 -0.218902587890625 +62566 -0.063751220703125 +62567 0.091552734375 +62568 0.23602294921875 +62569 0.342987060546875 +62570 0.39520263671875 +62571 0.389373779296875 +62572 0.324249267578125 +62573 0.224090576171875 +62574 0.124267578125 +62575 0.037078857421875 +62576 -0.010101318359375 +62577 -0.019439697265625 +62578 -0.022796630859375 +62579 -0.001556396484375 +62580 0.056304931640625 +62581 0.106719970703125 +62582 0.096893310546875 +62583 0.042694091796875 +62584 -0.018035888671875 +62585 -0.07586669921875 +62586 -0.11944580078125 +62587 -0.15972900390625 +62588 -0.202606201171875 +62589 -0.24859619140625 +62590 -0.30517578125 +62591 -0.36212158203125 +62592 -0.39141845703125 +62593 -0.35528564453125 +62594 -0.249969482421875 +62595 -0.092864990234375 +62596 0.08905029296875 +62597 0.2352294921875 +62598 0.318817138671875 +62599 0.358642578125 +62600 0.347747802734375 +62601 0.28564453125 +62602 0.223175048828125 +62603 0.196746826171875 +62604 0.179840087890625 +62605 0.155548095703125 +62606 0.151214599609375 +62607 0.156951904296875 +62608 0.13177490234375 +62609 0.100799560546875 +62610 0.087127685546875 +62611 0.05487060546875 +62612 -0.009002685546875 +62613 -0.10400390625 +62614 -0.229400634765625 +62615 -0.35552978515625 +62616 -0.441925048828125 +62617 -0.473846435546875 +62618 -0.464813232421875 +62619 -0.419097900390625 +62620 -0.334320068359375 +62621 -0.227935791015625 +62622 -0.12347412109375 +62623 -0.02764892578125 +62624 0.077667236328125 +62625 0.2132568359375 +62626 0.38885498046875 +62627 0.582794189453125 +62628 0.734039306640625 +62629 0.800140380859375 +62630 0.7783203125 +62631 0.6651611328125 +62632 0.45965576171875 +62633 0.199188232421875 +62634 -0.050689697265625 +62635 -0.23297119140625 +62636 -0.33013916015625 +62637 -0.368408203125 +62638 -0.378936767578125 +62639 -0.376983642578125 +62640 -0.37969970703125 +62641 -0.391510009765625 +62642 -0.385345458984375 +62643 -0.3419189453125 +62644 -0.28289794921875 +62645 -0.251617431640625 +62646 -0.266143798828125 +62647 -0.273345947265625 +62648 -0.216796875 +62649 -0.128265380859375 +62650 -0.068145751953125 +62651 -0.0430908203125 +62652 -0.024444580078125 +62653 0.020721435546875 +62654 0.124481201171875 +62655 0.25787353515625 +62656 0.379119873046875 +62657 0.47991943359375 +62658 0.5281982421875 +62659 0.511138916015625 +62660 0.456207275390625 +62661 0.407470703125 +62662 0.383758544921875 +62663 0.35687255859375 +62664 0.31182861328125 +62665 0.250885009765625 +62666 0.1654052734375 +62667 0.035247802734375 +62668 -0.142059326171875 +62669 -0.33563232421875 +62670 -0.5345458984375 +62671 -0.72186279296875 +62672 -0.836669921875 +62673 -0.8326416015625 +62674 -0.7296142578125 +62675 -0.582550048828125 +62676 -0.440093994140625 +62677 -0.324310302734375 +62678 -0.20147705078125 +62679 -0.044647216796875 +62680 0.103973388671875 +62681 0.202392578125 +62682 0.264495849609375 +62683 0.338897705078125 +62684 0.443817138671875 +62685 0.545074462890625 +62686 0.6173095703125 +62687 0.6524658203125 +62688 0.66339111328125 +62689 0.6561279296875 +62690 0.606781005859375 +62691 0.501190185546875 +62692 0.352783203125 +62693 0.176544189453125 +62694 -0.034820556640625 +62695 -0.258209228515625 +62696 -0.44244384765625 +62697 -0.5753173828125 +62698 -0.65203857421875 +62699 -0.641632080078125 +62700 -0.562164306640625 +62701 -0.458038330078125 +62702 -0.350555419921875 +62703 -0.260528564453125 +62704 -0.192108154296875 +62705 -0.141937255859375 +62706 -0.1021728515625 +62707 -0.062896728515625 +62708 -0.011932373046875 +62709 0.062835693359375 +62710 0.148712158203125 +62711 0.241729736328125 +62712 0.34912109375 +62713 0.457305908203125 +62714 0.54388427734375 +62715 0.5728759765625 +62716 0.506591796875 +62717 0.351226806640625 +62718 0.146514892578125 +62719 -0.05523681640625 +62720 -0.21624755859375 +62721 -0.334930419921875 +62722 -0.402984619140625 +62723 -0.4412841796875 +62724 -0.49578857421875 +62725 -0.5601806640625 +62726 -0.600738525390625 +62727 -0.584228515625 +62728 -0.47930908203125 +62729 -0.27935791015625 +62730 -0.0089111328125 +62731 0.268798828125 +62732 0.482818603515625 +62733 0.60369873046875 +62734 0.650421142578125 +62735 0.66400146484375 +62736 0.6414794921875 +62737 0.572540283203125 +62738 0.498138427734375 +62739 0.439453125 +62740 0.375518798828125 +62741 0.274505615234375 +62742 0.1087646484375 +62743 -0.099395751953125 +62744 -0.3182373046875 +62745 -0.5489501953125 +62746 -0.7738037109375 +62747 -0.86383056640625 +62748 -0.870391845703125 +62749 -0.86895751953125 +62750 -0.861053466796875 +62751 -0.765869140625 +62752 -0.5301513671875 +62753 -0.214691162109375 +62754 0.137359619140625 +62755 0.474822998046875 +62756 0.76239013671875 +62757 0.867462158203125 +62758 0.870361328125 +62759 0.86480712890625 +62760 0.831817626953125 +62761 0.677581787109375 +62762 0.495880126953125 +62763 0.30767822265625 +62764 0.116180419921875 +62765 -0.110748291015625 +62766 -0.381805419921875 +62767 -0.6572265625 +62768 -0.857421875 +62769 -0.870391845703125 +62770 -0.870391845703125 +62771 -0.86444091796875 +62772 -0.85723876953125 +62773 -0.790008544921875 +62774 -0.62847900390625 +62775 -0.3956298828125 +62776 -0.126708984375 +62777 0.150115966796875 +62778 0.424041748046875 +62779 0.670623779296875 +62780 0.854522705078125 +62781 0.866485595703125 +62782 0.86920166015625 +62783 0.8653564453125 +62784 0.857147216796875 +62785 0.766845703125 +62786 0.628509521484375 +62787 0.462127685546875 +62788 0.297210693359375 +62789 0.14862060546875 +62790 -0.00537109375 +62791 -0.15753173828125 +62792 -0.31304931640625 +62793 -0.48876953125 +62794 -0.6416015625 +62795 -0.751373291015625 +62796 -0.84619140625 +62797 -0.861297607421875 +62798 -0.863250732421875 +62799 -0.856597900390625 +62800 -0.7498779296875 +62801 -0.624542236328125 +62802 -0.47808837890625 +62803 -0.253387451171875 +62804 0.003692626953125 +62805 0.2257080078125 +62806 0.427154541015625 +62807 0.643218994140625 +62808 0.855926513671875 +62809 0.870361328125 +62810 0.870361328125 +62811 0.862762451171875 +62812 0.79669189453125 +62813 0.595794677734375 +62814 0.362152099609375 +62815 0.1270751953125 +62816 -0.086944580078125 +62817 -0.2784423828125 +62818 -0.484832763671875 +62819 -0.729583740234375 +62820 -0.86688232421875 +62821 -0.870391845703125 +62822 -0.86859130859375 +62823 -0.86279296875 +62824 -0.817962646484375 +62825 -0.6116943359375 +62826 -0.3128662109375 +62827 0.039398193359375 +62828 0.422821044921875 +62829 0.805145263671875 +62830 0.870361328125 +62831 0.870361328125 +62832 0.860015869140625 +62833 0.727935791015625 +62834 0.48114013671875 +62835 0.2059326171875 +62836 -0.06103515625 +62837 -0.29913330078125 +62838 -0.516204833984375 +62839 -0.7252197265625 +62840 -0.85980224609375 +62841 -0.870391845703125 +62842 -0.870391845703125 +62843 -0.858062744140625 +62844 -0.673004150390625 +62845 -0.42694091796875 +62846 -0.2100830078125 +62847 -0.0362548828125 +62848 0.10943603515625 +62849 0.23516845703125 +62850 0.373687744140625 +62851 0.517791748046875 +62852 0.602783203125 +62853 0.635711669921875 +62854 0.655181884765625 +62855 0.65948486328125 +62856 0.651275634765625 +62857 0.61846923828125 +62858 0.53753662109375 +62859 0.404144287109375 +62860 0.22186279296875 +62861 0.003997802734375 +62862 -0.22100830078125 +62863 -0.42449951171875 +62864 -0.579833984375 +62865 -0.641876220703125 +62866 -0.6177978515625 +62867 -0.575531005859375 +62868 -0.526336669921875 +62869 -0.42645263671875 +62870 -0.2581787109375 +62871 -0.068695068359375 +62872 0.09222412109375 +62873 0.232147216796875 +62874 0.3509521484375 +62875 0.410064697265625 +62876 0.372955322265625 +62877 0.2554931640625 +62878 0.10711669921875 +62879 -0.052886962890625 +62880 -0.186279296875 +62881 -0.23291015625 +62882 -0.209442138671875 +62883 -0.174163818359375 +62884 -0.126739501953125 +62885 -0.048126220703125 +62886 0.0426025390625 +62887 0.10748291015625 +62888 0.1409912109375 +62889 0.19708251953125 +62890 0.273651123046875 +62891 0.31768798828125 +62892 0.341094970703125 +62893 0.368011474609375 +62894 0.37249755859375 +62895 0.30072021484375 +62896 0.1517333984375 +62897 -0.01470947265625 +62898 -0.1883544921875 +62899 -0.372711181640625 +62900 -0.51397705078125 +62901 -0.57177734375 +62902 -0.53948974609375 +62903 -0.43511962890625 +62904 -0.2962646484375 +62905 -0.161102294921875 +62906 -0.0435791015625 +62907 0.060394287109375 +62908 0.13665771484375 +62909 0.170135498046875 +62910 0.16552734375 +62911 0.15728759765625 +62912 0.150787353515625 +62913 0.12200927734375 +62914 0.080108642578125 +62915 0.05126953125 +62916 0.062896728515625 +62917 0.09271240234375 +62918 0.092987060546875 +62919 0.07855224609375 +62920 0.06427001953125 +62921 0.0347900390625 +62922 -0.01171875 +62923 -0.056060791015625 +62924 -0.055511474609375 +62925 -0.010467529296875 +62926 0.02508544921875 +62927 0.025665283203125 +62928 0.017333984375 +62929 0.00189208984375 +62930 -0.03173828125 +62931 -0.071502685546875 +62932 -0.13543701171875 +62933 -0.219970703125 +62934 -0.300506591796875 +62935 -0.376312255859375 +62936 -0.416107177734375 +62937 -0.371124267578125 +62938 -0.242279052734375 +62939 -0.069732666015625 +62940 0.125640869140625 +62941 0.31268310546875 +62942 0.45501708984375 +62943 0.554779052734375 +62944 0.61065673828125 +62945 0.610931396484375 +62946 0.531463623046875 +62947 0.3883056640625 +62948 0.23468017578125 +62949 0.095245361328125 +62950 -0.00396728515625 +62951 -0.04852294921875 +62952 -0.055145263671875 +62953 -0.0758056640625 +62954 -0.138702392578125 +62955 -0.209197998046875 +62956 -0.289031982421875 +62957 -0.37884521484375 +62958 -0.456329345703125 +62959 -0.51641845703125 +62960 -0.519287109375 +62961 -0.458251953125 +62962 -0.384796142578125 +62963 -0.323699951171875 +62964 -0.269287109375 +62965 -0.1951904296875 +62966 -0.100006103515625 +62967 -0.01055908203125 +62968 0.1033935546875 +62969 0.24908447265625 +62970 0.373199462890625 +62971 0.45806884765625 +62972 0.511474609375 +62973 0.565399169921875 +62974 0.61138916015625 +62975 0.5897216796875 +62976 0.4906005859375 +62977 0.33148193359375 +62978 0.147796630859375 +62979 -0.01873779296875 +62980 -0.140289306640625 +62981 -0.191986083984375 +62982 -0.184295654296875 +62983 -0.161834716796875 +62984 -0.166595458984375 +62985 -0.19390869140625 +62986 -0.22442626953125 +62987 -0.279754638671875 +62988 -0.3389892578125 +62989 -0.3543701171875 +62990 -0.348175048828125 +62991 -0.32598876953125 +62992 -0.2581787109375 +62993 -0.139801025390625 +62994 0.014617919921875 +62995 0.144378662109375 +62996 0.221038818359375 +62997 0.27069091796875 +62998 0.294036865234375 +62999 0.311767578125 +63000 0.339141845703125 +63001 0.360260009765625 +63002 0.360504150390625 +63003 0.308380126953125 +63004 0.18170166015625 +63005 0.0047607421875 +63006 -0.17559814453125 +63007 -0.3143310546875 +63008 -0.36785888671875 +63009 -0.36248779296875 +63010 -0.343536376953125 +63011 -0.3018798828125 +63012 -0.231414794921875 +63013 -0.117645263671875 +63014 0.007049560546875 +63015 0.087982177734375 +63016 0.13946533203125 +63017 0.17425537109375 +63018 0.188201904296875 +63019 0.171234130859375 +63020 0.118438720703125 +63021 0.05706787109375 +63022 -0.010711669921875 +63023 -0.0914306640625 +63024 -0.162322998046875 +63025 -0.194549560546875 +63026 -0.1492919921875 +63027 -0.02166748046875 +63028 0.124053955078125 +63029 0.211151123046875 +63030 0.240447998046875 +63031 0.242218017578125 +63032 0.2257080078125 +63033 0.194366455078125 +63034 0.115509033203125 +63035 0.0128173828125 +63036 -0.053802490234375 +63037 -0.110626220703125 +63038 -0.199493408203125 +63039 -0.29437255859375 +63040 -0.33221435546875 +63041 -0.27972412109375 +63042 -0.185333251953125 +63043 -0.128204345703125 +63044 -0.115692138671875 +63045 -0.116455078125 +63046 -0.105926513671875 +63047 -0.053955078125 +63048 0.048797607421875 +63049 0.157318115234375 +63050 0.212005615234375 +63051 0.218475341796875 +63052 0.23724365234375 +63053 0.30535888671875 +63054 0.38128662109375 +63055 0.404449462890625 +63056 0.3944091796875 +63057 0.3885498046875 +63058 0.362640380859375 +63059 0.27362060546875 +63060 0.11712646484375 +63061 -0.054901123046875 +63062 -0.19085693359375 +63063 -0.28570556640625 +63064 -0.339263916015625 +63065 -0.3775634765625 +63066 -0.445709228515625 +63067 -0.535064697265625 +63068 -0.629058837890625 +63069 -0.697601318359375 +63070 -0.70391845703125 +63071 -0.6424560546875 +63072 -0.491241455078125 +63073 -0.265716552734375 +63074 -0.023712158203125 +63075 0.201751708984375 +63076 0.375823974609375 +63077 0.485076904296875 +63078 0.56884765625 +63079 0.634765625 +63080 0.63763427734375 +63081 0.5660400390625 +63082 0.4720458984375 +63083 0.40692138671875 +63084 0.3778076171875 +63085 0.376953125 +63086 0.371978759765625 +63087 0.313140869140625 +63088 0.184417724609375 +63089 0.011199951171875 +63090 -0.171051025390625 +63091 -0.33740234375 +63092 -0.47198486328125 +63093 -0.560394287109375 +63094 -0.58056640625 +63095 -0.54754638671875 +63096 -0.508575439453125 +63097 -0.459503173828125 +63098 -0.394378662109375 +63099 -0.35260009765625 +63100 -0.31170654296875 +63101 -0.197418212890625 +63102 -0.007965087890625 +63103 0.207489013671875 +63104 0.409210205078125 +63105 0.57208251953125 +63106 0.66595458984375 +63107 0.65875244140625 +63108 0.56744384765625 +63109 0.431396484375 +63110 0.29443359375 +63111 0.182464599609375 +63112 0.06365966796875 +63113 -0.075958251953125 +63114 -0.189422607421875 +63115 -0.271942138671875 +63116 -0.342529296875 +63117 -0.364166259765625 +63118 -0.327239990234375 +63119 -0.2769775390625 +63120 -0.253692626953125 +63121 -0.24365234375 +63122 -0.1983642578125 +63123 -0.116241455078125 +63124 -0.036834716796875 +63125 0.034881591796875 +63126 0.09124755859375 +63127 0.10888671875 +63128 0.125518798828125 +63129 0.15771484375 +63130 0.17828369140625 +63131 0.17108154296875 +63132 0.129974365234375 +63133 0.082427978515625 +63134 0.027679443359375 +63135 -0.065643310546875 +63136 -0.15936279296875 +63137 -0.21307373046875 +63138 -0.234649658203125 +63139 -0.2001953125 +63140 -0.119171142578125 +63141 -0.024749755859375 +63142 0.085784912109375 +63143 0.178131103515625 +63144 0.215576171875 +63145 0.211456298828125 +63146 0.17523193359375 +63147 0.128753662109375 +63148 0.1019287109375 +63149 0.0743408203125 +63150 0.04327392578125 +63151 0.038177490234375 +63152 0.076263427734375 +63153 0.14105224609375 +63154 0.186431884765625 +63155 0.188812255859375 +63156 0.1390380859375 +63157 0.041778564453125 +63158 -0.079437255859375 +63159 -0.219390869140625 +63160 -0.367828369140625 +63161 -0.494873046875 +63162 -0.556243896484375 +63163 -0.508697509765625 +63164 -0.3756103515625 +63165 -0.218902587890625 +63166 -0.063751220703125 +63167 0.091552734375 +63168 0.23602294921875 +63169 0.342987060546875 +63170 0.39520263671875 +63171 0.389373779296875 +63172 0.324249267578125 +63173 0.224090576171875 +63174 0.124267578125 +63175 0.037078857421875 +63176 -0.010101318359375 +63177 -0.019439697265625 +63178 -0.022796630859375 +63179 -0.001556396484375 +63180 0.056304931640625 +63181 0.106719970703125 +63182 0.096893310546875 +63183 0.042694091796875 +63184 -0.018035888671875 +63185 -0.07586669921875 +63186 -0.11944580078125 +63187 -0.15972900390625 +63188 -0.202606201171875 +63189 -0.24859619140625 +63190 -0.30517578125 +63191 -0.36212158203125 +63192 -0.39141845703125 +63193 -0.35528564453125 +63194 -0.249969482421875 +63195 -0.092864990234375 +63196 0.08905029296875 +63197 0.2352294921875 +63198 0.318817138671875 +63199 0.358642578125 +63200 0.347747802734375 +63201 0.28564453125 +63202 0.223175048828125 +63203 0.196746826171875 +63204 0.179840087890625 +63205 0.155548095703125 +63206 0.151214599609375 +63207 0.156951904296875 +63208 0.13177490234375 +63209 0.100799560546875 +63210 0.087127685546875 +63211 0.05487060546875 +63212 -0.009002685546875 +63213 -0.10400390625 +63214 -0.229400634765625 +63215 -0.35552978515625 +63216 -0.441925048828125 +63217 -0.473846435546875 +63218 -0.464813232421875 +63219 -0.419097900390625 +63220 -0.334320068359375 +63221 -0.227935791015625 +63222 -0.12347412109375 +63223 -0.02764892578125 +63224 0.077667236328125 +63225 0.2132568359375 +63226 0.38885498046875 +63227 0.582794189453125 +63228 0.734039306640625 +63229 0.800140380859375 +63230 0.7783203125 +63231 0.6651611328125 +63232 0.45965576171875 +63233 0.199188232421875 +63234 -0.050689697265625 +63235 -0.23297119140625 +63236 -0.33013916015625 +63237 -0.368408203125 +63238 -0.378936767578125 +63239 -0.376983642578125 +63240 -0.37969970703125 +63241 -0.391510009765625 +63242 -0.385345458984375 +63243 -0.3419189453125 +63244 -0.28289794921875 +63245 -0.251617431640625 +63246 -0.266143798828125 +63247 -0.273345947265625 +63248 -0.216796875 +63249 -0.128265380859375 +63250 -0.068145751953125 +63251 -0.0430908203125 +63252 -0.024444580078125 +63253 0.020721435546875 +63254 0.124481201171875 +63255 0.25787353515625 +63256 0.379119873046875 +63257 0.47991943359375 +63258 0.5281982421875 +63259 0.511138916015625 +63260 0.456207275390625 +63261 0.407470703125 +63262 0.383758544921875 +63263 0.35687255859375 +63264 0.31182861328125 +63265 0.250885009765625 +63266 0.1654052734375 +63267 0.035247802734375 +63268 -0.142059326171875 +63269 -0.33563232421875 +63270 -0.5345458984375 +63271 -0.72186279296875 +63272 -0.836669921875 +63273 -0.8326416015625 +63274 -0.7296142578125 +63275 -0.582550048828125 +63276 -0.440093994140625 +63277 -0.324310302734375 +63278 -0.20147705078125 +63279 -0.044647216796875 +63280 0.103973388671875 +63281 0.202392578125 +63282 0.264495849609375 +63283 0.338897705078125 +63284 0.443817138671875 +63285 0.545074462890625 +63286 0.6173095703125 +63287 0.6524658203125 +63288 0.66339111328125 +63289 0.6561279296875 +63290 0.606781005859375 +63291 0.501190185546875 +63292 0.352783203125 +63293 0.176544189453125 +63294 -0.034820556640625 +63295 -0.258209228515625 +63296 -0.44244384765625 +63297 -0.5753173828125 +63298 -0.65203857421875 +63299 -0.641632080078125 +63300 -0.562164306640625 +63301 -0.458038330078125 +63302 -0.350555419921875 +63303 -0.260528564453125 +63304 -0.192108154296875 +63305 -0.141937255859375 +63306 -0.1021728515625 +63307 -0.062896728515625 +63308 -0.011932373046875 +63309 0.062835693359375 +63310 0.148712158203125 +63311 0.241729736328125 +63312 0.34912109375 +63313 0.457305908203125 +63314 0.54388427734375 +63315 0.5728759765625 +63316 0.506591796875 +63317 0.351226806640625 +63318 0.146514892578125 +63319 -0.05523681640625 +63320 -0.21624755859375 +63321 -0.334930419921875 +63322 -0.402984619140625 +63323 -0.4412841796875 +63324 -0.49578857421875 +63325 -0.5601806640625 +63326 -0.600738525390625 +63327 -0.584228515625 +63328 -0.47930908203125 +63329 -0.27935791015625 +63330 -0.0089111328125 +63331 0.268798828125 +63332 0.482818603515625 +63333 0.60369873046875 +63334 0.650421142578125 +63335 0.66400146484375 +63336 0.6414794921875 +63337 0.572540283203125 +63338 0.498138427734375 +63339 0.439453125 +63340 0.375518798828125 +63341 0.274505615234375 +63342 0.1087646484375 +63343 -0.099395751953125 +63344 -0.3182373046875 +63345 -0.5489501953125 +63346 -0.7738037109375 +63347 -0.86383056640625 +63348 -0.870391845703125 +63349 -0.86895751953125 +63350 -0.861053466796875 +63351 -0.765869140625 +63352 -0.5301513671875 +63353 -0.214691162109375 +63354 0.137359619140625 +63355 0.474822998046875 +63356 0.76239013671875 +63357 0.867462158203125 +63358 0.870361328125 +63359 0.86480712890625 +63360 0.831817626953125 +63361 0.677581787109375 +63362 0.495880126953125 +63363 0.30767822265625 +63364 0.116180419921875 +63365 -0.110748291015625 +63366 -0.381805419921875 +63367 -0.6572265625 +63368 -0.857421875 +63369 -0.870391845703125 +63370 -0.870391845703125 +63371 -0.86444091796875 +63372 -0.85723876953125 +63373 -0.790008544921875 +63374 -0.62847900390625 +63375 -0.3956298828125 +63376 -0.126708984375 +63377 0.150115966796875 +63378 0.424041748046875 +63379 0.670623779296875 +63380 0.854522705078125 +63381 0.866485595703125 +63382 0.86920166015625 +63383 0.8653564453125 +63384 0.857147216796875 +63385 0.766845703125 +63386 0.628509521484375 +63387 0.462127685546875 +63388 0.297210693359375 +63389 0.14862060546875 +63390 -0.00537109375 +63391 -0.15753173828125 +63392 -0.31304931640625 +63393 -0.48876953125 +63394 -0.6416015625 +63395 -0.751373291015625 +63396 -0.84619140625 +63397 -0.861297607421875 +63398 -0.863250732421875 +63399 -0.856597900390625 +63400 -0.7498779296875 +63401 -0.624542236328125 +63402 -0.47808837890625 +63403 -0.253387451171875 +63404 0.003692626953125 +63405 0.2257080078125 +63406 0.427154541015625 +63407 0.643218994140625 +63408 0.855926513671875 +63409 0.870361328125 +63410 0.870361328125 +63411 0.862762451171875 +63412 0.79669189453125 +63413 0.595794677734375 +63414 0.362152099609375 +63415 0.1270751953125 +63416 -0.086944580078125 +63417 -0.2784423828125 +63418 -0.484832763671875 +63419 -0.729583740234375 +63420 -0.86688232421875 +63421 -0.870391845703125 +63422 -0.86859130859375 +63423 -0.86279296875 +63424 -0.817962646484375 +63425 -0.6116943359375 +63426 -0.3128662109375 +63427 0.039398193359375 +63428 0.422821044921875 +63429 0.805145263671875 +63430 0.870361328125 +63431 0.870361328125 +63432 0.860015869140625 +63433 0.727935791015625 +63434 0.48114013671875 +63435 0.2059326171875 +63436 -0.06103515625 +63437 -0.29913330078125 +63438 -0.516204833984375 +63439 -0.7252197265625 +63440 -0.85980224609375 +63441 -0.870391845703125 +63442 -0.870391845703125 +63443 -0.858062744140625 +63444 -0.673004150390625 +63445 -0.42694091796875 +63446 -0.2100830078125 +63447 -0.0362548828125 +63448 0.10943603515625 +63449 0.23516845703125 +63450 0.373687744140625 +63451 0.517791748046875 +63452 0.602783203125 +63453 0.635711669921875 +63454 0.655181884765625 +63455 0.65948486328125 +63456 0.651275634765625 +63457 0.61846923828125 +63458 0.53753662109375 +63459 0.404144287109375 +63460 0.22186279296875 +63461 0.003997802734375 +63462 -0.22100830078125 +63463 -0.42449951171875 +63464 -0.579833984375 +63465 -0.641876220703125 +63466 -0.6177978515625 +63467 -0.575531005859375 +63468 -0.526336669921875 +63469 -0.42645263671875 +63470 -0.2581787109375 +63471 -0.068695068359375 +63472 0.09222412109375 +63473 0.232147216796875 +63474 0.3509521484375 +63475 0.410064697265625 +63476 0.372955322265625 +63477 0.2554931640625 +63478 0.10711669921875 +63479 -0.052886962890625 +63480 -0.186279296875 +63481 -0.23291015625 +63482 -0.209442138671875 +63483 -0.174163818359375 +63484 -0.126739501953125 +63485 -0.048126220703125 +63486 0.0426025390625 +63487 0.10748291015625 +63488 0.1409912109375 +63489 0.19708251953125 +63490 0.273651123046875 +63491 0.31768798828125 +63492 0.341094970703125 +63493 0.368011474609375 +63494 0.37249755859375 +63495 0.30072021484375 +63496 0.1517333984375 +63497 -0.01470947265625 +63498 -0.1883544921875 +63499 -0.372711181640625 +63500 -0.51397705078125 +63501 -0.57177734375 +63502 -0.53948974609375 +63503 -0.43511962890625 +63504 -0.2962646484375 +63505 -0.161102294921875 +63506 -0.0435791015625 +63507 0.060394287109375 +63508 0.13665771484375 +63509 0.170135498046875 +63510 0.16552734375 +63511 0.15728759765625 +63512 0.150787353515625 +63513 0.12200927734375 +63514 0.080108642578125 +63515 0.05126953125 +63516 0.062896728515625 +63517 0.09271240234375 +63518 0.092987060546875 +63519 0.07855224609375 +63520 0.06427001953125 +63521 0.0347900390625 +63522 -0.01171875 +63523 -0.056060791015625 +63524 -0.055511474609375 +63525 -0.010467529296875 +63526 0.02508544921875 +63527 0.025665283203125 +63528 0.017333984375 +63529 0.00189208984375 +63530 -0.03173828125 +63531 -0.071502685546875 +63532 -0.13543701171875 +63533 -0.219970703125 +63534 -0.300506591796875 +63535 -0.376312255859375 +63536 -0.416107177734375 +63537 -0.371124267578125 +63538 -0.242279052734375 +63539 -0.069732666015625 +63540 0.125640869140625 +63541 0.31268310546875 +63542 0.45501708984375 +63543 0.554779052734375 +63544 0.61065673828125 +63545 0.610931396484375 +63546 0.531463623046875 +63547 0.3883056640625 +63548 0.23468017578125 +63549 0.095245361328125 +63550 -0.00396728515625 +63551 -0.04852294921875 +63552 -0.055145263671875 +63553 -0.0758056640625 +63554 -0.138702392578125 +63555 -0.209197998046875 +63556 -0.289031982421875 +63557 -0.37884521484375 +63558 -0.456329345703125 +63559 -0.51641845703125 +63560 -0.519287109375 +63561 -0.458251953125 +63562 -0.384796142578125 +63563 -0.323699951171875 +63564 -0.269287109375 +63565 -0.1951904296875 +63566 -0.100006103515625 +63567 -0.01055908203125 +63568 0.1033935546875 +63569 0.24908447265625 +63570 0.373199462890625 +63571 0.45806884765625 +63572 0.511474609375 +63573 0.565399169921875 +63574 0.61138916015625 +63575 0.5897216796875 +63576 0.4906005859375 +63577 0.33148193359375 +63578 0.147796630859375 +63579 -0.01873779296875 +63580 -0.140289306640625 +63581 -0.191986083984375 +63582 -0.184295654296875 +63583 -0.161834716796875 +63584 -0.166595458984375 +63585 -0.19390869140625 +63586 -0.22442626953125 +63587 -0.279754638671875 +63588 -0.3389892578125 +63589 -0.3543701171875 +63590 -0.348175048828125 +63591 -0.32598876953125 +63592 -0.2581787109375 +63593 -0.139801025390625 +63594 0.014617919921875 +63595 0.144378662109375 +63596 0.221038818359375 +63597 0.27069091796875 +63598 0.294036865234375 +63599 0.311767578125 +63600 0.339141845703125 +63601 0.360260009765625 +63602 0.360504150390625 +63603 0.308380126953125 +63604 0.18170166015625 +63605 0.0047607421875 +63606 -0.17559814453125 +63607 -0.3143310546875 +63608 -0.36785888671875 +63609 -0.36248779296875 +63610 -0.343536376953125 +63611 -0.3018798828125 +63612 -0.231414794921875 +63613 -0.117645263671875 +63614 0.007049560546875 +63615 0.087982177734375 +63616 0.13946533203125 +63617 0.17425537109375 +63618 0.188201904296875 +63619 0.171234130859375 +63620 0.118438720703125 +63621 0.05706787109375 +63622 -0.010711669921875 +63623 -0.0914306640625 +63624 -0.162322998046875 +63625 -0.194549560546875 +63626 -0.1492919921875 +63627 -0.02166748046875 +63628 0.124053955078125 +63629 0.211151123046875 +63630 0.240447998046875 +63631 0.242218017578125 +63632 0.2257080078125 +63633 0.194366455078125 +63634 0.115509033203125 +63635 0.0128173828125 +63636 -0.053802490234375 +63637 -0.110626220703125 +63638 -0.199493408203125 +63639 -0.29437255859375 +63640 -0.33221435546875 +63641 -0.27972412109375 +63642 -0.185333251953125 +63643 -0.128204345703125 +63644 -0.115692138671875 +63645 -0.116455078125 +63646 -0.105926513671875 +63647 -0.053955078125 +63648 0.048797607421875 +63649 0.157318115234375 +63650 0.212005615234375 +63651 0.218475341796875 +63652 0.23724365234375 +63653 0.30535888671875 +63654 0.38128662109375 +63655 0.404449462890625 +63656 0.3944091796875 +63657 0.3885498046875 +63658 0.362640380859375 +63659 0.27362060546875 +63660 0.11712646484375 +63661 -0.054901123046875 +63662 -0.19085693359375 +63663 -0.28570556640625 +63664 -0.339263916015625 +63665 -0.3775634765625 +63666 -0.445709228515625 +63667 -0.535064697265625 +63668 -0.629058837890625 +63669 -0.697601318359375 +63670 -0.70391845703125 +63671 -0.6424560546875 +63672 -0.491241455078125 +63673 -0.265716552734375 +63674 -0.023712158203125 +63675 0.201751708984375 +63676 0.375823974609375 +63677 0.485076904296875 +63678 0.56884765625 +63679 0.634765625 +63680 0.63763427734375 +63681 0.5660400390625 +63682 0.4720458984375 +63683 0.40692138671875 +63684 0.3778076171875 +63685 0.376953125 +63686 0.371978759765625 +63687 0.313140869140625 +63688 0.184417724609375 +63689 0.011199951171875 +63690 -0.171051025390625 +63691 -0.33740234375 +63692 -0.47198486328125 +63693 -0.560394287109375 +63694 -0.58056640625 +63695 -0.54754638671875 +63696 -0.508575439453125 +63697 -0.459503173828125 +63698 -0.394378662109375 +63699 -0.35260009765625 +63700 -0.31170654296875 +63701 -0.197418212890625 +63702 -0.007965087890625 +63703 0.207489013671875 +63704 0.409210205078125 +63705 0.57208251953125 +63706 0.66595458984375 +63707 0.65875244140625 +63708 0.56744384765625 +63709 0.431396484375 +63710 0.29443359375 +63711 0.182464599609375 +63712 0.06365966796875 +63713 -0.075958251953125 +63714 -0.189422607421875 +63715 -0.271942138671875 +63716 -0.342529296875 +63717 -0.364166259765625 +63718 -0.327239990234375 +63719 -0.2769775390625 +63720 -0.253692626953125 +63721 -0.24365234375 +63722 -0.1983642578125 +63723 -0.116241455078125 +63724 -0.036834716796875 +63725 0.034881591796875 +63726 0.09124755859375 +63727 0.10888671875 +63728 0.125518798828125 +63729 0.15771484375 +63730 0.17828369140625 +63731 0.17108154296875 +63732 0.129974365234375 +63733 0.082427978515625 +63734 0.027679443359375 +63735 -0.065643310546875 +63736 -0.15936279296875 +63737 -0.21307373046875 +63738 -0.234649658203125 +63739 -0.2001953125 +63740 -0.119171142578125 +63741 -0.024749755859375 +63742 0.085784912109375 +63743 0.178131103515625 +63744 0.215576171875 +63745 0.211456298828125 +63746 0.17523193359375 +63747 0.128753662109375 +63748 0.1019287109375 +63749 0.0743408203125 +63750 0.04327392578125 +63751 0.038177490234375 +63752 0.076263427734375 +63753 0.14105224609375 +63754 0.186431884765625 +63755 0.188812255859375 +63756 0.1390380859375 +63757 0.041778564453125 +63758 -0.079437255859375 +63759 -0.219390869140625 +63760 -0.367828369140625 +63761 -0.494873046875 +63762 -0.556243896484375 +63763 -0.508697509765625 +63764 -0.3756103515625 +63765 -0.218902587890625 +63766 -0.063751220703125 +63767 0.091552734375 +63768 0.23602294921875 +63769 0.342987060546875 +63770 0.39520263671875 +63771 0.389373779296875 +63772 0.324249267578125 +63773 0.224090576171875 +63774 0.124267578125 +63775 0.037078857421875 +63776 -0.010101318359375 +63777 -0.019439697265625 +63778 -0.022796630859375 +63779 -0.001556396484375 +63780 0.056304931640625 +63781 0.106719970703125 +63782 0.096893310546875 +63783 0.042694091796875 +63784 -0.018035888671875 +63785 -0.07586669921875 +63786 -0.11944580078125 +63787 -0.15972900390625 +63788 -0.202606201171875 +63789 -0.24859619140625 +63790 -0.30517578125 +63791 -0.36212158203125 +63792 -0.39141845703125 +63793 -0.35528564453125 +63794 -0.249969482421875 +63795 -0.092864990234375 +63796 0.08905029296875 +63797 0.2352294921875 +63798 0.318817138671875 +63799 0.358642578125 +63800 0.347747802734375 +63801 0.28564453125 +63802 0.223175048828125 +63803 0.196746826171875 +63804 0.179840087890625 +63805 0.155548095703125 +63806 0.151214599609375 +63807 0.156951904296875 +63808 0.13177490234375 +63809 0.100799560546875 +63810 0.087127685546875 +63811 0.05487060546875 +63812 -0.009002685546875 +63813 -0.10400390625 +63814 -0.229400634765625 +63815 -0.35552978515625 +63816 -0.441925048828125 +63817 -0.473846435546875 +63818 -0.464813232421875 +63819 -0.419097900390625 +63820 -0.334320068359375 +63821 -0.227935791015625 +63822 -0.12347412109375 +63823 -0.02764892578125 +63824 0.077667236328125 +63825 0.2132568359375 +63826 0.38885498046875 +63827 0.582794189453125 +63828 0.734039306640625 +63829 0.800140380859375 +63830 0.7783203125 +63831 0.6651611328125 +63832 0.45965576171875 +63833 0.199188232421875 +63834 -0.050689697265625 +63835 -0.23297119140625 +63836 -0.33013916015625 +63837 -0.368408203125 +63838 -0.378936767578125 +63839 -0.376983642578125 +63840 -0.37969970703125 +63841 -0.391510009765625 +63842 -0.385345458984375 +63843 -0.3419189453125 +63844 -0.28289794921875 +63845 -0.251617431640625 +63846 -0.266143798828125 +63847 -0.273345947265625 +63848 -0.216796875 +63849 -0.128265380859375 +63850 -0.068145751953125 +63851 -0.0430908203125 +63852 -0.024444580078125 +63853 0.020721435546875 +63854 0.124481201171875 +63855 0.25787353515625 +63856 0.379119873046875 +63857 0.47991943359375 +63858 0.5281982421875 +63859 0.511138916015625 +63860 0.456207275390625 +63861 0.407470703125 +63862 0.383758544921875 +63863 0.35687255859375 +63864 0.31182861328125 +63865 0.250885009765625 +63866 0.1654052734375 +63867 0.035247802734375 +63868 -0.142059326171875 +63869 -0.33563232421875 +63870 -0.5345458984375 +63871 -0.72186279296875 +63872 -0.836669921875 +63873 -0.8326416015625 +63874 -0.7296142578125 +63875 -0.582550048828125 +63876 -0.440093994140625 +63877 -0.324310302734375 +63878 -0.20147705078125 +63879 -0.044647216796875 +63880 0.103973388671875 +63881 0.202392578125 +63882 0.264495849609375 +63883 0.338897705078125 +63884 0.443817138671875 +63885 0.545074462890625 +63886 0.6173095703125 +63887 0.6524658203125 +63888 0.66339111328125 +63889 0.6561279296875 +63890 0.606781005859375 +63891 0.501190185546875 +63892 0.352783203125 +63893 0.176544189453125 +63894 -0.034820556640625 +63895 -0.258209228515625 +63896 -0.44244384765625 +63897 -0.5753173828125 +63898 -0.65203857421875 +63899 -0.641632080078125 +63900 -0.562164306640625 +63901 -0.458038330078125 +63902 -0.350555419921875 +63903 -0.260528564453125 +63904 -0.192108154296875 +63905 -0.141937255859375 +63906 -0.1021728515625 +63907 -0.062896728515625 +63908 -0.011932373046875 +63909 0.062835693359375 +63910 0.148712158203125 +63911 0.241729736328125 +63912 0.34912109375 +63913 0.457305908203125 +63914 0.54388427734375 +63915 0.5728759765625 +63916 0.506591796875 +63917 0.351226806640625 +63918 0.146514892578125 +63919 -0.05523681640625 +63920 -0.21624755859375 +63921 -0.334930419921875 +63922 -0.402984619140625 +63923 -0.4412841796875 +63924 -0.49578857421875 +63925 -0.5601806640625 +63926 -0.600738525390625 +63927 -0.584228515625 +63928 -0.47930908203125 +63929 -0.27935791015625 +63930 -0.0089111328125 +63931 0.268798828125 +63932 0.482818603515625 +63933 0.60369873046875 +63934 0.650421142578125 +63935 0.66400146484375 +63936 0.6414794921875 +63937 0.572540283203125 +63938 0.498138427734375 +63939 0.439453125 +63940 0.375518798828125 +63941 0.274505615234375 +63942 0.1087646484375 +63943 -0.099395751953125 +63944 -0.3182373046875 +63945 -0.5489501953125 +63946 -0.7738037109375 +63947 -0.86383056640625 +63948 -0.870391845703125 +63949 -0.86895751953125 +63950 -0.861053466796875 +63951 -0.765869140625 +63952 -0.5301513671875 +63953 -0.214691162109375 +63954 0.137359619140625 +63955 0.474822998046875 +63956 0.76239013671875 +63957 0.867462158203125 +63958 0.870361328125 +63959 0.86480712890625 +63960 0.831817626953125 +63961 0.677581787109375 +63962 0.495880126953125 +63963 0.30767822265625 +63964 0.116180419921875 +63965 -0.110748291015625 +63966 -0.381805419921875 +63967 -0.6572265625 +63968 -0.857421875 +63969 -0.870391845703125 +63970 -0.870391845703125 +63971 -0.86444091796875 +63972 -0.85723876953125 +63973 -0.790008544921875 +63974 -0.62847900390625 +63975 -0.3956298828125 +63976 -0.126708984375 +63977 0.150115966796875 +63978 0.424041748046875 +63979 0.670623779296875 +63980 0.854522705078125 +63981 0.866485595703125 +63982 0.86920166015625 +63983 0.8653564453125 +63984 0.857147216796875 +63985 0.766845703125 +63986 0.628509521484375 +63987 0.462127685546875 +63988 0.297210693359375 +63989 0.14862060546875 +63990 -0.00537109375 +63991 -0.15753173828125 +63992 -0.31304931640625 +63993 -0.48876953125 +63994 -0.6416015625 +63995 -0.751373291015625 +63996 -0.84619140625 +63997 -0.861297607421875 +63998 -0.863250732421875 +63999 -0.856597900390625 +64000 -0.7498779296875 +64001 -0.624542236328125 +64002 -0.47808837890625 +64003 -0.253387451171875 +64004 0.003692626953125 +64005 0.2257080078125 +64006 0.427154541015625 +64007 0.643218994140625 +64008 0.855926513671875 +64009 0.870361328125 +64010 0.870361328125 +64011 0.862762451171875 +64012 0.79669189453125 +64013 0.595794677734375 +64014 0.362152099609375 +64015 0.1270751953125 +64016 -0.086944580078125 +64017 -0.2784423828125 +64018 -0.484832763671875 +64019 -0.729583740234375 +64020 -0.86688232421875 +64021 -0.870391845703125 +64022 -0.86859130859375 +64023 -0.86279296875 +64024 -0.817962646484375 +64025 -0.6116943359375 +64026 -0.3128662109375 +64027 0.039398193359375 +64028 0.422821044921875 +64029 0.805145263671875 +64030 0.870361328125 +64031 0.870361328125 +64032 0.860015869140625 +64033 0.727935791015625 +64034 0.48114013671875 +64035 0.2059326171875 +64036 -0.06103515625 +64037 -0.29913330078125 +64038 -0.516204833984375 +64039 -0.7252197265625 +64040 -0.85980224609375 +64041 -0.870391845703125 +64042 -0.870391845703125 +64043 -0.858062744140625 +64044 -0.673004150390625 +64045 -0.42694091796875 +64046 -0.2100830078125 +64047 -0.0362548828125 +64048 0.10943603515625 +64049 0.23516845703125 +64050 0.373687744140625 +64051 0.517791748046875 +64052 0.602783203125 +64053 0.635711669921875 +64054 0.655181884765625 +64055 0.65948486328125 +64056 0.651275634765625 +64057 0.61846923828125 +64058 0.53753662109375 +64059 0.404144287109375 +64060 0.22186279296875 +64061 0.003997802734375 +64062 -0.22100830078125 +64063 -0.42449951171875 +64064 -0.579833984375 +64065 -0.641876220703125 +64066 -0.6177978515625 +64067 -0.575531005859375 +64068 -0.526336669921875 +64069 -0.42645263671875 +64070 -0.2581787109375 +64071 -0.068695068359375 +64072 0.09222412109375 +64073 0.232147216796875 +64074 0.3509521484375 +64075 0.410064697265625 +64076 0.372955322265625 +64077 0.2554931640625 +64078 0.10711669921875 +64079 -0.052886962890625 +64080 -0.186279296875 +64081 -0.23291015625 +64082 -0.209442138671875 +64083 -0.174163818359375 +64084 -0.126739501953125 +64085 -0.048126220703125 +64086 0.0426025390625 +64087 0.10748291015625 +64088 0.1409912109375 +64089 0.19708251953125 +64090 0.273651123046875 +64091 0.31768798828125 +64092 0.341094970703125 +64093 0.368011474609375 +64094 0.37249755859375 +64095 0.30072021484375 +64096 0.1517333984375 +64097 -0.01470947265625 +64098 -0.1883544921875 +64099 -0.372711181640625 +64100 -0.51397705078125 +64101 -0.57177734375 +64102 -0.53948974609375 +64103 -0.43511962890625 +64104 -0.2962646484375 +64105 -0.161102294921875 +64106 -0.0435791015625 +64107 0.060394287109375 +64108 0.13665771484375 +64109 0.170135498046875 +64110 0.16552734375 +64111 0.15728759765625 +64112 0.150787353515625 +64113 0.12200927734375 +64114 0.080108642578125 +64115 0.05126953125 +64116 0.062896728515625 +64117 0.09271240234375 +64118 0.092987060546875 +64119 0.07855224609375 +64120 0.06427001953125 +64121 0.0347900390625 +64122 -0.01171875 +64123 -0.056060791015625 +64124 -0.055511474609375 +64125 -0.010467529296875 +64126 0.02508544921875 +64127 0.025665283203125 +64128 0.017333984375 +64129 0.00189208984375 +64130 -0.03173828125 +64131 -0.071502685546875 +64132 -0.13543701171875 +64133 -0.219970703125 +64134 -0.300506591796875 +64135 -0.376312255859375 +64136 -0.416107177734375 +64137 -0.371124267578125 +64138 -0.242279052734375 +64139 -0.069732666015625 +64140 0.125640869140625 +64141 0.31268310546875 +64142 0.45501708984375 +64143 0.554779052734375 +64144 0.61065673828125 +64145 0.610931396484375 +64146 0.531463623046875 +64147 0.3883056640625 +64148 0.23468017578125 +64149 0.095245361328125 +64150 -0.00396728515625 +64151 -0.04852294921875 +64152 -0.055145263671875 +64153 -0.0758056640625 +64154 -0.138702392578125 +64155 -0.209197998046875 +64156 -0.289031982421875 +64157 -0.37884521484375 +64158 -0.456329345703125 +64159 -0.51641845703125 +64160 -0.519287109375 +64161 -0.458251953125 +64162 -0.384796142578125 +64163 -0.323699951171875 +64164 -0.269287109375 +64165 -0.1951904296875 +64166 -0.100006103515625 +64167 -0.01055908203125 +64168 0.1033935546875 +64169 0.24908447265625 +64170 0.373199462890625 +64171 0.45806884765625 +64172 0.511474609375 +64173 0.565399169921875 +64174 0.61138916015625 +64175 0.5897216796875 +64176 0.4906005859375 +64177 0.33148193359375 +64178 0.147796630859375 +64179 -0.01873779296875 +64180 -0.140289306640625 +64181 -0.191986083984375 +64182 -0.184295654296875 +64183 -0.161834716796875 +64184 -0.166595458984375 +64185 -0.19390869140625 +64186 -0.22442626953125 +64187 -0.279754638671875 +64188 -0.3389892578125 +64189 -0.3543701171875 +64190 -0.348175048828125 +64191 -0.32598876953125 +64192 -0.2581787109375 +64193 -0.139801025390625 +64194 0.014617919921875 +64195 0.144378662109375 +64196 0.221038818359375 +64197 0.27069091796875 +64198 0.294036865234375 +64199 0.311767578125 +64200 0.339141845703125 +64201 0.360260009765625 +64202 0.360504150390625 +64203 0.308380126953125 +64204 0.18170166015625 +64205 0.0047607421875 +64206 -0.17559814453125 +64207 -0.3143310546875 +64208 -0.36785888671875 +64209 -0.36248779296875 +64210 -0.343536376953125 +64211 -0.3018798828125 +64212 -0.231414794921875 +64213 -0.117645263671875 +64214 0.007049560546875 +64215 0.087982177734375 +64216 0.13946533203125 +64217 0.17425537109375 +64218 0.188201904296875 +64219 0.171234130859375 +64220 0.118438720703125 +64221 0.05706787109375 +64222 -0.010711669921875 +64223 -0.0914306640625 +64224 -0.162322998046875 +64225 -0.194549560546875 +64226 -0.1492919921875 +64227 -0.02166748046875 +64228 0.124053955078125 +64229 0.211151123046875 +64230 0.240447998046875 +64231 0.242218017578125 +64232 0.2257080078125 +64233 0.194366455078125 +64234 0.115509033203125 +64235 0.0128173828125 +64236 -0.053802490234375 +64237 -0.110626220703125 +64238 -0.199493408203125 +64239 -0.29437255859375 +64240 -0.33221435546875 +64241 -0.27972412109375 +64242 -0.185333251953125 +64243 -0.128204345703125 +64244 -0.115692138671875 +64245 -0.116455078125 +64246 -0.105926513671875 +64247 -0.053955078125 +64248 0.048797607421875 +64249 0.157318115234375 +64250 0.212005615234375 +64251 0.218475341796875 +64252 0.23724365234375 +64253 0.30535888671875 +64254 0.38128662109375 +64255 0.404449462890625 +64256 0.3944091796875 +64257 0.3885498046875 +64258 0.362640380859375 +64259 0.27362060546875 +64260 0.11712646484375 +64261 -0.054901123046875 +64262 -0.19085693359375 +64263 -0.28570556640625 +64264 -0.339263916015625 +64265 -0.3775634765625 +64266 -0.445709228515625 +64267 -0.535064697265625 +64268 -0.629058837890625 +64269 -0.697601318359375 +64270 -0.70391845703125 +64271 -0.6424560546875 +64272 -0.491241455078125 +64273 -0.265716552734375 +64274 -0.023712158203125 +64275 0.201751708984375 +64276 0.375823974609375 +64277 0.485076904296875 +64278 0.56884765625 +64279 0.634765625 +64280 0.63763427734375 +64281 0.5660400390625 +64282 0.4720458984375 +64283 0.40692138671875 +64284 0.3778076171875 +64285 0.376953125 +64286 0.371978759765625 +64287 0.313140869140625 +64288 0.184417724609375 +64289 0.011199951171875 +64290 -0.171051025390625 +64291 -0.33740234375 +64292 -0.47198486328125 +64293 -0.560394287109375 +64294 -0.58056640625 +64295 -0.54754638671875 +64296 -0.508575439453125 +64297 -0.459503173828125 +64298 -0.394378662109375 +64299 -0.35260009765625 +64300 -0.31170654296875 +64301 -0.197418212890625 +64302 -0.007965087890625 +64303 0.207489013671875 +64304 0.409210205078125 +64305 0.57208251953125 +64306 0.66595458984375 +64307 0.65875244140625 +64308 0.56744384765625 +64309 0.431396484375 +64310 0.29443359375 +64311 0.182464599609375 +64312 0.06365966796875 +64313 -0.075958251953125 +64314 -0.189422607421875 +64315 -0.271942138671875 +64316 -0.342529296875 +64317 -0.364166259765625 +64318 -0.327239990234375 +64319 -0.2769775390625 +64320 -0.253692626953125 +64321 -0.24365234375 +64322 -0.1983642578125 +64323 -0.116241455078125 +64324 -0.036834716796875 +64325 0.034881591796875 +64326 0.09124755859375 +64327 0.10888671875 +64328 0.125518798828125 +64329 0.15771484375 +64330 0.17828369140625 +64331 0.17108154296875 +64332 0.129974365234375 +64333 0.082427978515625 +64334 0.027679443359375 +64335 -0.065643310546875 +64336 -0.15936279296875 +64337 -0.21307373046875 +64338 -0.234649658203125 +64339 -0.2001953125 +64340 -0.119171142578125 +64341 -0.024749755859375 +64342 0.085784912109375 +64343 0.178131103515625 +64344 0.215576171875 +64345 0.211456298828125 +64346 0.17523193359375 +64347 0.128753662109375 +64348 0.1019287109375 +64349 0.0743408203125 +64350 0.04327392578125 +64351 0.038177490234375 +64352 0.076263427734375 +64353 0.14105224609375 +64354 0.186431884765625 +64355 0.188812255859375 +64356 0.1390380859375 +64357 0.041778564453125 +64358 -0.079437255859375 +64359 -0.219390869140625 +64360 -0.367828369140625 +64361 -0.494873046875 +64362 -0.556243896484375 +64363 -0.508697509765625 +64364 -0.3756103515625 +64365 -0.218902587890625 +64366 -0.063751220703125 +64367 0.091552734375 +64368 0.23602294921875 +64369 0.342987060546875 +64370 0.39520263671875 +64371 0.389373779296875 +64372 0.324249267578125 +64373 0.224090576171875 +64374 0.124267578125 +64375 0.037078857421875 +64376 -0.010101318359375 +64377 -0.019439697265625 +64378 -0.022796630859375 +64379 -0.001556396484375 +64380 0.056304931640625 +64381 0.106719970703125 +64382 0.096893310546875 +64383 0.042694091796875 +64384 -0.018035888671875 +64385 -0.07586669921875 +64386 -0.11944580078125 +64387 -0.15972900390625 +64388 -0.202606201171875 +64389 -0.24859619140625 +64390 -0.30517578125 +64391 -0.36212158203125 +64392 -0.39141845703125 +64393 -0.35528564453125 +64394 -0.249969482421875 +64395 -0.092864990234375 +64396 0.08905029296875 +64397 0.2352294921875 +64398 0.318817138671875 +64399 0.358642578125 +64400 0.347747802734375 +64401 0.28564453125 +64402 0.223175048828125 +64403 0.196746826171875 +64404 0.179840087890625 +64405 0.155548095703125 +64406 0.151214599609375 +64407 0.156951904296875 +64408 0.13177490234375 +64409 0.100799560546875 +64410 0.087127685546875 +64411 0.05487060546875 +64412 -0.009002685546875 +64413 -0.10400390625 +64414 -0.229400634765625 +64415 -0.35552978515625 +64416 -0.441925048828125 +64417 -0.473846435546875 +64418 -0.464813232421875 +64419 -0.419097900390625 +64420 -0.334320068359375 +64421 -0.227935791015625 +64422 -0.12347412109375 +64423 -0.02764892578125 +64424 0.077667236328125 +64425 0.2132568359375 +64426 0.38885498046875 +64427 0.582794189453125 +64428 0.734039306640625 +64429 0.800140380859375 +64430 0.7783203125 +64431 0.6651611328125 +64432 0.45965576171875 +64433 0.199188232421875 +64434 -0.050689697265625 +64435 -0.23297119140625 +64436 -0.33013916015625 +64437 -0.368408203125 +64438 -0.378936767578125 +64439 -0.376983642578125 +64440 -0.37969970703125 +64441 -0.391510009765625 +64442 -0.385345458984375 +64443 -0.3419189453125 +64444 -0.28289794921875 +64445 -0.251617431640625 +64446 -0.266143798828125 +64447 -0.273345947265625 +64448 -0.216796875 +64449 -0.128265380859375 +64450 -0.068145751953125 +64451 -0.0430908203125 +64452 -0.024444580078125 +64453 0.020721435546875 +64454 0.124481201171875 +64455 0.25787353515625 +64456 0.379119873046875 +64457 0.47991943359375 +64458 0.5281982421875 +64459 0.511138916015625 +64460 0.456207275390625 +64461 0.407470703125 +64462 0.383758544921875 +64463 0.35687255859375 +64464 0.31182861328125 +64465 0.250885009765625 +64466 0.1654052734375 +64467 0.035247802734375 +64468 -0.142059326171875 +64469 -0.33563232421875 +64470 -0.5345458984375 +64471 -0.72186279296875 +64472 -0.836669921875 +64473 -0.8326416015625 +64474 -0.7296142578125 +64475 -0.582550048828125 +64476 -0.440093994140625 +64477 -0.324310302734375 +64478 -0.20147705078125 +64479 -0.044647216796875 +64480 0.103973388671875 +64481 0.202392578125 +64482 0.264495849609375 +64483 0.338897705078125 +64484 0.443817138671875 +64485 0.545074462890625 +64486 0.6173095703125 +64487 0.6524658203125 +64488 0.66339111328125 +64489 0.6561279296875 +64490 0.606781005859375 +64491 0.501190185546875 +64492 0.352783203125 +64493 0.176544189453125 +64494 -0.034820556640625 +64495 -0.258209228515625 +64496 -0.44244384765625 +64497 -0.5753173828125 +64498 -0.65203857421875 +64499 -0.641632080078125 +64500 -0.562164306640625 +64501 -0.458038330078125 +64502 -0.350555419921875 +64503 -0.260528564453125 +64504 -0.192108154296875 +64505 -0.141937255859375 +64506 -0.1021728515625 +64507 -0.062896728515625 +64508 -0.011932373046875 +64509 0.062835693359375 +64510 0.148712158203125 +64511 0.241729736328125 +64512 0.34912109375 +64513 0.457305908203125 +64514 0.54388427734375 +64515 0.5728759765625 +64516 0.506591796875 +64517 0.351226806640625 +64518 0.146514892578125 +64519 -0.05523681640625 +64520 -0.21624755859375 +64521 -0.334930419921875 +64522 -0.402984619140625 +64523 -0.4412841796875 +64524 -0.49578857421875 +64525 -0.5601806640625 +64526 -0.600738525390625 +64527 -0.584228515625 +64528 -0.47930908203125 +64529 -0.27935791015625 +64530 -0.0089111328125 +64531 0.268798828125 +64532 0.482818603515625 +64533 0.60369873046875 +64534 0.650421142578125 +64535 0.66400146484375 +64536 0.6414794921875 +64537 0.572540283203125 +64538 0.498138427734375 +64539 0.439453125 +64540 0.375518798828125 +64541 0.274505615234375 +64542 0.1087646484375 +64543 -0.099395751953125 +64544 -0.3182373046875 +64545 -0.5489501953125 +64546 -0.7738037109375 +64547 -0.86383056640625 +64548 -0.870391845703125 +64549 -0.86895751953125 +64550 -0.861053466796875 +64551 -0.765869140625 +64552 -0.5301513671875 +64553 -0.214691162109375 +64554 0.137359619140625 +64555 0.474822998046875 +64556 0.76239013671875 +64557 0.867462158203125 +64558 0.870361328125 +64559 0.86480712890625 +64560 0.831817626953125 +64561 0.677581787109375 +64562 0.495880126953125 +64563 0.30767822265625 +64564 0.116180419921875 +64565 -0.110748291015625 +64566 -0.381805419921875 +64567 -0.6572265625 +64568 -0.857421875 +64569 -0.870391845703125 +64570 -0.870391845703125 +64571 -0.86444091796875 +64572 -0.85723876953125 +64573 -0.790008544921875 +64574 -0.62847900390625 +64575 -0.3956298828125 +64576 -0.126708984375 +64577 0.150115966796875 +64578 0.424041748046875 +64579 0.670623779296875 +64580 0.854522705078125 +64581 0.866485595703125 +64582 0.86920166015625 +64583 0.8653564453125 +64584 0.857147216796875 +64585 0.766845703125 +64586 0.628509521484375 +64587 0.462127685546875 +64588 0.297210693359375 +64589 0.14862060546875 +64590 -0.00537109375 +64591 -0.15753173828125 +64592 -0.31304931640625 +64593 -0.48876953125 +64594 -0.6416015625 +64595 -0.751373291015625 +64596 -0.84619140625 +64597 -0.861297607421875 +64598 -0.863250732421875 +64599 -0.856597900390625 +64600 -0.7498779296875 +64601 -0.624542236328125 +64602 -0.47808837890625 +64603 -0.253387451171875 +64604 0.003692626953125 +64605 0.2257080078125 +64606 0.427154541015625 +64607 0.643218994140625 +64608 0.855926513671875 +64609 0.870361328125 +64610 0.870361328125 +64611 0.862762451171875 +64612 0.79669189453125 +64613 0.595794677734375 +64614 0.362152099609375 +64615 0.1270751953125 +64616 -0.086944580078125 +64617 -0.2784423828125 +64618 -0.484832763671875 +64619 -0.729583740234375 +64620 -0.86688232421875 +64621 -0.870391845703125 +64622 -0.86859130859375 +64623 -0.86279296875 +64624 -0.817962646484375 +64625 -0.6116943359375 +64626 -0.3128662109375 +64627 0.039398193359375 +64628 0.422821044921875 +64629 0.805145263671875 +64630 0.870361328125 +64631 0.870361328125 +64632 0.860015869140625 +64633 0.727935791015625 +64634 0.48114013671875 +64635 0.2059326171875 +64636 -0.06103515625 +64637 -0.29913330078125 +64638 -0.516204833984375 +64639 -0.7252197265625 +64640 -0.85980224609375 +64641 -0.870391845703125 +64642 -0.870391845703125 +64643 -0.858062744140625 +64644 -0.673004150390625 +64645 -0.42694091796875 +64646 -0.2100830078125 +64647 -0.0362548828125 +64648 0.10943603515625 +64649 0.23516845703125 +64650 0.373687744140625 +64651 0.517791748046875 +64652 0.602783203125 +64653 0.635711669921875 +64654 0.655181884765625 +64655 0.65948486328125 +64656 0.651275634765625 +64657 0.61846923828125 +64658 0.53753662109375 +64659 0.404144287109375 +64660 0.22186279296875 +64661 0.003997802734375 +64662 -0.22100830078125 +64663 -0.42449951171875 +64664 -0.579833984375 +64665 -0.641876220703125 +64666 -0.6177978515625 +64667 -0.575531005859375 +64668 -0.526336669921875 +64669 -0.42645263671875 +64670 -0.2581787109375 +64671 -0.068695068359375 +64672 0.09222412109375 +64673 0.232147216796875 +64674 0.3509521484375 +64675 0.410064697265625 +64676 0.372955322265625 +64677 0.2554931640625 +64678 0.10711669921875 +64679 -0.052886962890625 +64680 -0.186279296875 +64681 -0.23291015625 +64682 -0.209442138671875 +64683 -0.174163818359375 +64684 -0.126739501953125 +64685 -0.048126220703125 +64686 0.0426025390625 +64687 0.10748291015625 +64688 0.1409912109375 +64689 0.19708251953125 +64690 0.273651123046875 +64691 0.31768798828125 +64692 0.341094970703125 +64693 0.368011474609375 +64694 0.37249755859375 +64695 0.30072021484375 +64696 0.1517333984375 +64697 -0.01470947265625 +64698 -0.1883544921875 +64699 -0.372711181640625 +64700 -0.51397705078125 +64701 -0.57177734375 +64702 -0.53948974609375 +64703 -0.43511962890625 +64704 -0.2962646484375 +64705 -0.161102294921875 +64706 -0.0435791015625 +64707 0.060394287109375 +64708 0.13665771484375 +64709 0.170135498046875 +64710 0.16552734375 +64711 0.15728759765625 +64712 0.150787353515625 +64713 0.12200927734375 +64714 0.080108642578125 +64715 0.05126953125 +64716 0.062896728515625 +64717 0.09271240234375 +64718 0.092987060546875 +64719 0.07855224609375 +64720 0.06427001953125 +64721 0.0347900390625 +64722 -0.01171875 +64723 -0.056060791015625 +64724 -0.055511474609375 +64725 -0.010467529296875 +64726 0.02508544921875 +64727 0.025665283203125 +64728 0.017333984375 +64729 0.00189208984375 +64730 -0.03173828125 +64731 -0.071502685546875 +64732 -0.13543701171875 +64733 -0.219970703125 +64734 -0.300506591796875 +64735 -0.376312255859375 +64736 -0.416107177734375 +64737 -0.371124267578125 +64738 -0.242279052734375 +64739 -0.069732666015625 +64740 0.125640869140625 +64741 0.31268310546875 +64742 0.45501708984375 +64743 0.554779052734375 +64744 0.61065673828125 +64745 0.610931396484375 +64746 0.531463623046875 +64747 0.3883056640625 +64748 0.23468017578125 +64749 0.095245361328125 +64750 -0.00396728515625 +64751 -0.04852294921875 +64752 -0.055145263671875 +64753 -0.0758056640625 +64754 -0.138702392578125 +64755 -0.209197998046875 +64756 -0.289031982421875 +64757 -0.37884521484375 +64758 -0.456329345703125 +64759 -0.51641845703125 +64760 -0.519287109375 +64761 -0.458251953125 +64762 -0.384796142578125 +64763 -0.323699951171875 +64764 -0.269287109375 +64765 -0.1951904296875 +64766 -0.100006103515625 +64767 -0.01055908203125 +64768 0.1033935546875 +64769 0.24908447265625 +64770 0.373199462890625 +64771 0.45806884765625 +64772 0.511474609375 +64773 0.565399169921875 +64774 0.61138916015625 +64775 0.5897216796875 +64776 0.4906005859375 +64777 0.33148193359375 +64778 0.147796630859375 +64779 -0.01873779296875 +64780 -0.140289306640625 +64781 -0.191986083984375 +64782 -0.184295654296875 +64783 -0.161834716796875 +64784 -0.166595458984375 +64785 -0.19390869140625 +64786 -0.22442626953125 +64787 -0.279754638671875 +64788 -0.3389892578125 +64789 -0.3543701171875 +64790 -0.348175048828125 +64791 -0.32598876953125 +64792 -0.2581787109375 +64793 -0.139801025390625 +64794 0.014617919921875 +64795 0.144378662109375 +64796 0.221038818359375 +64797 0.27069091796875 +64798 0.294036865234375 +64799 0.311767578125 +64800 0.339141845703125 +64801 0.360260009765625 +64802 0.360504150390625 +64803 0.308380126953125 +64804 0.18170166015625 +64805 0.0047607421875 +64806 -0.17559814453125 +64807 -0.3143310546875 +64808 -0.36785888671875 +64809 -0.36248779296875 +64810 -0.343536376953125 +64811 -0.3018798828125 +64812 -0.231414794921875 +64813 -0.117645263671875 +64814 0.007049560546875 +64815 0.087982177734375 +64816 0.13946533203125 +64817 0.17425537109375 +64818 0.188201904296875 +64819 0.171234130859375 +64820 0.118438720703125 +64821 0.05706787109375 +64822 -0.010711669921875 +64823 -0.0914306640625 +64824 -0.162322998046875 +64825 -0.194549560546875 +64826 -0.1492919921875 +64827 -0.02166748046875 +64828 0.124053955078125 +64829 0.211151123046875 +64830 0.240447998046875 +64831 0.242218017578125 +64832 0.2257080078125 +64833 0.194366455078125 +64834 0.115509033203125 +64835 0.0128173828125 +64836 -0.053802490234375 +64837 -0.110626220703125 +64838 -0.199493408203125 +64839 -0.29437255859375 +64840 -0.33221435546875 +64841 -0.27972412109375 +64842 -0.185333251953125 +64843 -0.128204345703125 +64844 -0.115692138671875 +64845 -0.116455078125 +64846 -0.105926513671875 +64847 -0.053955078125 +64848 0.048797607421875 +64849 0.157318115234375 +64850 0.212005615234375 +64851 0.218475341796875 +64852 0.23724365234375 +64853 0.30535888671875 +64854 0.38128662109375 +64855 0.404449462890625 +64856 0.3944091796875 +64857 0.3885498046875 +64858 0.362640380859375 +64859 0.27362060546875 +64860 0.11712646484375 +64861 -0.054901123046875 +64862 -0.19085693359375 +64863 -0.28570556640625 +64864 -0.339263916015625 +64865 -0.3775634765625 +64866 -0.445709228515625 +64867 -0.535064697265625 +64868 -0.629058837890625 +64869 -0.697601318359375 +64870 -0.70391845703125 +64871 -0.6424560546875 +64872 -0.491241455078125 +64873 -0.265716552734375 +64874 -0.023712158203125 +64875 0.201751708984375 +64876 0.375823974609375 +64877 0.485076904296875 +64878 0.56884765625 +64879 0.634765625 +64880 0.63763427734375 +64881 0.5660400390625 +64882 0.4720458984375 +64883 0.40692138671875 +64884 0.3778076171875 +64885 0.376953125 +64886 0.371978759765625 +64887 0.313140869140625 +64888 0.184417724609375 +64889 0.011199951171875 +64890 -0.171051025390625 +64891 -0.33740234375 +64892 -0.47198486328125 +64893 -0.560394287109375 +64894 -0.58056640625 +64895 -0.54754638671875 +64896 -0.508575439453125 +64897 -0.459503173828125 +64898 -0.394378662109375 +64899 -0.35260009765625 +64900 -0.31170654296875 +64901 -0.197418212890625 +64902 -0.007965087890625 +64903 0.207489013671875 +64904 0.409210205078125 +64905 0.57208251953125 +64906 0.66595458984375 +64907 0.65875244140625 +64908 0.56744384765625 +64909 0.431396484375 +64910 0.29443359375 +64911 0.182464599609375 +64912 0.06365966796875 +64913 -0.075958251953125 +64914 -0.189422607421875 +64915 -0.271942138671875 +64916 -0.342529296875 +64917 -0.364166259765625 +64918 -0.327239990234375 +64919 -0.2769775390625 +64920 -0.253692626953125 +64921 -0.24365234375 +64922 -0.1983642578125 +64923 -0.116241455078125 +64924 -0.036834716796875 +64925 0.034881591796875 +64926 0.09124755859375 +64927 0.10888671875 +64928 0.125518798828125 +64929 0.15771484375 +64930 0.17828369140625 +64931 0.17108154296875 +64932 0.129974365234375 +64933 0.082427978515625 +64934 0.027679443359375 +64935 -0.065643310546875 +64936 -0.15936279296875 +64937 -0.21307373046875 +64938 -0.234649658203125 +64939 -0.2001953125 +64940 -0.119171142578125 +64941 -0.024749755859375 +64942 0.085784912109375 +64943 0.178131103515625 +64944 0.215576171875 +64945 0.211456298828125 +64946 0.17523193359375 +64947 0.128753662109375 +64948 0.1019287109375 +64949 0.0743408203125 +64950 0.04327392578125 +64951 0.038177490234375 +64952 0.076263427734375 +64953 0.14105224609375 +64954 0.186431884765625 +64955 0.188812255859375 +64956 0.1390380859375 +64957 0.041778564453125 +64958 -0.079437255859375 +64959 -0.219390869140625 +64960 -0.367828369140625 +64961 -0.494873046875 +64962 -0.556243896484375 +64963 -0.508697509765625 +64964 -0.3756103515625 +64965 -0.218902587890625 +64966 -0.063751220703125 +64967 0.091552734375 +64968 0.23602294921875 +64969 0.342987060546875 +64970 0.39520263671875 +64971 0.389373779296875 +64972 0.324249267578125 +64973 0.224090576171875 +64974 0.124267578125 +64975 0.037078857421875 +64976 -0.010101318359375 +64977 -0.019439697265625 +64978 -0.022796630859375 +64979 -0.001556396484375 +64980 0.056304931640625 +64981 0.106719970703125 +64982 0.096893310546875 +64983 0.042694091796875 +64984 -0.018035888671875 +64985 -0.07586669921875 +64986 -0.11944580078125 +64987 -0.15972900390625 +64988 -0.202606201171875 +64989 -0.24859619140625 +64990 -0.30517578125 +64991 -0.36212158203125 +64992 -0.39141845703125 +64993 -0.35528564453125 +64994 -0.249969482421875 +64995 -0.092864990234375 +64996 0.08905029296875 +64997 0.2352294921875 +64998 0.318817138671875 +64999 0.358642578125 +65000 0.347747802734375 +65001 0.28564453125 +65002 0.223175048828125 +65003 0.196746826171875 +65004 0.179840087890625 +65005 0.155548095703125 +65006 0.151214599609375 +65007 0.156951904296875 +65008 0.13177490234375 +65009 0.100799560546875 +65010 0.087127685546875 +65011 0.05487060546875 +65012 -0.009002685546875 +65013 -0.10400390625 +65014 -0.229400634765625 +65015 -0.35552978515625 +65016 -0.441925048828125 +65017 -0.473846435546875 +65018 -0.464813232421875 +65019 -0.419097900390625 +65020 -0.334320068359375 +65021 -0.227935791015625 +65022 -0.12347412109375 +65023 -0.02764892578125 +65024 0.077667236328125 +65025 0.2132568359375 +65026 0.38885498046875 +65027 0.582794189453125 +65028 0.734039306640625 +65029 0.800140380859375 +65030 0.7783203125 +65031 0.6651611328125 +65032 0.45965576171875 +65033 0.199188232421875 +65034 -0.050689697265625 +65035 -0.23297119140625 +65036 -0.33013916015625 +65037 -0.368408203125 +65038 -0.378936767578125 +65039 -0.376983642578125 +65040 -0.37969970703125 +65041 -0.391510009765625 +65042 -0.385345458984375 +65043 -0.3419189453125 +65044 -0.28289794921875 +65045 -0.251617431640625 +65046 -0.266143798828125 +65047 -0.273345947265625 +65048 -0.216796875 +65049 -0.128265380859375 +65050 -0.068145751953125 +65051 -0.0430908203125 +65052 -0.024444580078125 +65053 0.020721435546875 +65054 0.124481201171875 +65055 0.25787353515625 +65056 0.379119873046875 +65057 0.47991943359375 +65058 0.5281982421875 +65059 0.511138916015625 +65060 0.456207275390625 +65061 0.407470703125 +65062 0.383758544921875 +65063 0.35687255859375 +65064 0.31182861328125 +65065 0.250885009765625 +65066 0.1654052734375 +65067 0.035247802734375 +65068 -0.142059326171875 +65069 -0.33563232421875 +65070 -0.5345458984375 +65071 -0.72186279296875 +65072 -0.836669921875 +65073 -0.8326416015625 +65074 -0.7296142578125 +65075 -0.582550048828125 +65076 -0.440093994140625 +65077 -0.324310302734375 +65078 -0.20147705078125 +65079 -0.044647216796875 +65080 0.103973388671875 +65081 0.202392578125 +65082 0.264495849609375 +65083 0.338897705078125 +65084 0.443817138671875 +65085 0.545074462890625 +65086 0.6173095703125 +65087 0.6524658203125 +65088 0.66339111328125 +65089 0.6561279296875 +65090 0.606781005859375 +65091 0.501190185546875 +65092 0.352783203125 +65093 0.176544189453125 +65094 -0.034820556640625 +65095 -0.258209228515625 +65096 -0.44244384765625 +65097 -0.5753173828125 +65098 -0.65203857421875 +65099 -0.641632080078125 +65100 -0.562164306640625 +65101 -0.458038330078125 +65102 -0.350555419921875 +65103 -0.260528564453125 +65104 -0.192108154296875 +65105 -0.141937255859375 +65106 -0.1021728515625 +65107 -0.062896728515625 +65108 -0.011932373046875 +65109 0.062835693359375 +65110 0.148712158203125 +65111 0.241729736328125 +65112 0.34912109375 +65113 0.457305908203125 +65114 0.54388427734375 +65115 0.5728759765625 +65116 0.506591796875 +65117 0.351226806640625 +65118 0.146514892578125 +65119 -0.05523681640625 +65120 -0.21624755859375 +65121 -0.334930419921875 +65122 -0.402984619140625 +65123 -0.4412841796875 +65124 -0.49578857421875 +65125 -0.5601806640625 +65126 -0.600738525390625 +65127 -0.584228515625 +65128 -0.47930908203125 +65129 -0.27935791015625 +65130 -0.0089111328125 +65131 0.268798828125 +65132 0.482818603515625 +65133 0.60369873046875 +65134 0.650421142578125 +65135 0.66400146484375 +65136 0.6414794921875 +65137 0.572540283203125 +65138 0.498138427734375 +65139 0.439453125 +65140 0.375518798828125 +65141 0.274505615234375 +65142 0.1087646484375 +65143 -0.099395751953125 +65144 -0.3182373046875 +65145 -0.5489501953125 +65146 -0.7738037109375 +65147 -0.86383056640625 +65148 -0.870391845703125 +65149 -0.86895751953125 +65150 -0.861053466796875 +65151 -0.765869140625 +65152 -0.5301513671875 +65153 -0.214691162109375 +65154 0.137359619140625 +65155 0.474822998046875 +65156 0.76239013671875 +65157 0.867462158203125 +65158 0.870361328125 +65159 0.86480712890625 +65160 0.831817626953125 +65161 0.677581787109375 +65162 0.495880126953125 +65163 0.30767822265625 +65164 0.116180419921875 +65165 -0.110748291015625 +65166 -0.381805419921875 +65167 -0.6572265625 +65168 -0.857421875 +65169 -0.870391845703125 +65170 -0.870391845703125 +65171 -0.86444091796875 +65172 -0.85723876953125 +65173 -0.790008544921875 +65174 -0.62847900390625 +65175 -0.3956298828125 +65176 -0.126708984375 +65177 0.150115966796875 +65178 0.424041748046875 +65179 0.670623779296875 +65180 0.854522705078125 +65181 0.866485595703125 +65182 0.86920166015625 +65183 0.8653564453125 +65184 0.857147216796875 +65185 0.766845703125 +65186 0.628509521484375 +65187 0.462127685546875 +65188 0.297210693359375 +65189 0.14862060546875 +65190 -0.00537109375 +65191 -0.15753173828125 +65192 -0.31304931640625 +65193 -0.48876953125 +65194 -0.6416015625 +65195 -0.751373291015625 +65196 -0.84619140625 +65197 -0.861297607421875 +65198 -0.863250732421875 +65199 -0.856597900390625 +65200 -0.7498779296875 +65201 -0.624542236328125 +65202 -0.47808837890625 +65203 -0.253387451171875 +65204 0.003692626953125 +65205 0.2257080078125 +65206 0.427154541015625 +65207 0.643218994140625 +65208 0.855926513671875 +65209 0.870361328125 +65210 0.870361328125 +65211 0.862762451171875 +65212 0.79669189453125 +65213 0.595794677734375 +65214 0.362152099609375 +65215 0.1270751953125 +65216 -0.086944580078125 +65217 -0.2784423828125 +65218 -0.484832763671875 +65219 -0.729583740234375 +65220 -0.86688232421875 +65221 -0.870391845703125 +65222 -0.86859130859375 +65223 -0.86279296875 +65224 -0.817962646484375 +65225 -0.6116943359375 +65226 -0.3128662109375 +65227 0.039398193359375 +65228 0.422821044921875 +65229 0.805145263671875 +65230 0.870361328125 +65231 0.870361328125 +65232 0.860015869140625 +65233 0.727935791015625 +65234 0.48114013671875 +65235 0.2059326171875 +65236 -0.06103515625 +65237 -0.29913330078125 +65238 -0.516204833984375 +65239 -0.7252197265625 +65240 -0.85980224609375 +65241 -0.870391845703125 +65242 -0.870391845703125 +65243 -0.858062744140625 +65244 -0.673004150390625 +65245 -0.42694091796875 +65246 -0.2100830078125 +65247 -0.0362548828125 +65248 0.10943603515625 +65249 0.23516845703125 +65250 0.373687744140625 +65251 0.517791748046875 +65252 0.602783203125 +65253 0.635711669921875 +65254 0.655181884765625 +65255 0.65948486328125 +65256 0.651275634765625 +65257 0.61846923828125 +65258 0.53753662109375 +65259 0.404144287109375 +65260 0.22186279296875 +65261 0.003997802734375 +65262 -0.22100830078125 +65263 -0.42449951171875 +65264 -0.579833984375 +65265 -0.641876220703125 +65266 -0.6177978515625 +65267 -0.575531005859375 +65268 -0.526336669921875 +65269 -0.42645263671875 +65270 -0.2581787109375 +65271 -0.068695068359375 +65272 0.09222412109375 +65273 0.232147216796875 +65274 0.3509521484375 +65275 0.410064697265625 +65276 0.372955322265625 +65277 0.2554931640625 +65278 0.10711669921875 +65279 -0.052886962890625 +65280 -0.186279296875 +65281 -0.23291015625 +65282 -0.209442138671875 +65283 -0.174163818359375 +65284 -0.126739501953125 +65285 -0.048126220703125 +65286 0.0426025390625 +65287 0.10748291015625 +65288 0.1409912109375 +65289 0.19708251953125 +65290 0.273651123046875 +65291 0.31768798828125 +65292 0.341094970703125 +65293 0.368011474609375 +65294 0.37249755859375 +65295 0.30072021484375 +65296 0.1517333984375 +65297 -0.01470947265625 +65298 -0.1883544921875 +65299 -0.372711181640625 +65300 -0.51397705078125 +65301 -0.57177734375 +65302 -0.53948974609375 +65303 -0.43511962890625 +65304 -0.2962646484375 +65305 -0.161102294921875 +65306 -0.0435791015625 +65307 0.060394287109375 +65308 0.13665771484375 +65309 0.170135498046875 +65310 0.16552734375 +65311 0.15728759765625 +65312 0.150787353515625 +65313 0.12200927734375 +65314 0.080108642578125 +65315 0.05126953125 +65316 0.062896728515625 +65317 0.09271240234375 +65318 0.092987060546875 +65319 0.07855224609375 +65320 0.06427001953125 +65321 0.0347900390625 +65322 -0.01171875 +65323 -0.056060791015625 +65324 -0.055511474609375 +65325 -0.010467529296875 +65326 0.02508544921875 +65327 0.025665283203125 +65328 0.017333984375 +65329 0.00189208984375 +65330 -0.03173828125 +65331 -0.071502685546875 +65332 -0.13543701171875 +65333 -0.219970703125 +65334 -0.300506591796875 +65335 -0.376312255859375 +65336 -0.416107177734375 +65337 -0.371124267578125 +65338 -0.242279052734375 +65339 -0.069732666015625 +65340 0.125640869140625 +65341 0.31268310546875 +65342 0.45501708984375 +65343 0.554779052734375 +65344 0.61065673828125 +65345 0.610931396484375 +65346 0.531463623046875 +65347 0.3883056640625 +65348 0.23468017578125 +65349 0.095245361328125 +65350 -0.00396728515625 +65351 -0.04852294921875 +65352 -0.055145263671875 +65353 -0.0758056640625 +65354 -0.138702392578125 +65355 -0.209197998046875 +65356 -0.289031982421875 +65357 -0.37884521484375 +65358 -0.456329345703125 +65359 -0.51641845703125 +65360 -0.519287109375 +65361 -0.458251953125 +65362 -0.384796142578125 +65363 -0.323699951171875 +65364 -0.269287109375 +65365 -0.1951904296875 +65366 -0.100006103515625 +65367 -0.01055908203125 +65368 0.1033935546875 +65369 0.24908447265625 +65370 0.373199462890625 +65371 0.45806884765625 +65372 0.511474609375 +65373 0.565399169921875 +65374 0.61138916015625 +65375 0.5897216796875 +65376 0.4906005859375 +65377 0.33148193359375 +65378 0.147796630859375 +65379 -0.01873779296875 +65380 -0.140289306640625 +65381 -0.191986083984375 +65382 -0.184295654296875 +65383 -0.161834716796875 +65384 -0.166595458984375 +65385 -0.19390869140625 +65386 -0.22442626953125 +65387 -0.279754638671875 +65388 -0.3389892578125 +65389 -0.3543701171875 +65390 -0.348175048828125 +65391 -0.32598876953125 +65392 -0.2581787109375 +65393 -0.139801025390625 +65394 0.014617919921875 +65395 0.144378662109375 +65396 0.221038818359375 +65397 0.27069091796875 +65398 0.294036865234375 +65399 0.311767578125 +65400 0.339141845703125 +65401 0.360260009765625 +65402 0.360504150390625 +65403 0.308380126953125 +65404 0.18170166015625 +65405 0.0047607421875 +65406 -0.17559814453125 +65407 -0.3143310546875 +65408 -0.36785888671875 +65409 -0.36248779296875 +65410 -0.343536376953125 +65411 -0.3018798828125 +65412 -0.231414794921875 +65413 -0.117645263671875 +65414 0.007049560546875 +65415 0.087982177734375 +65416 0.13946533203125 +65417 0.17425537109375 +65418 0.188201904296875 +65419 0.171234130859375 +65420 0.118438720703125 +65421 0.05706787109375 +65422 -0.010711669921875 +65423 -0.0914306640625 +65424 -0.162322998046875 +65425 -0.194549560546875 +65426 -0.1492919921875 +65427 -0.02166748046875 +65428 0.124053955078125 +65429 0.211151123046875 +65430 0.240447998046875 +65431 0.242218017578125 +65432 0.2257080078125 +65433 0.194366455078125 +65434 0.115509033203125 +65435 0.0128173828125 +65436 -0.053802490234375 +65437 -0.110626220703125 +65438 -0.199493408203125 +65439 -0.29437255859375 +65440 -0.33221435546875 +65441 -0.27972412109375 +65442 -0.185333251953125 +65443 -0.128204345703125 +65444 -0.115692138671875 +65445 -0.116455078125 +65446 -0.105926513671875 +65447 -0.053955078125 +65448 0.048797607421875 +65449 0.157318115234375 +65450 0.212005615234375 +65451 0.218475341796875 +65452 0.23724365234375 +65453 0.30535888671875 +65454 0.38128662109375 +65455 0.404449462890625 +65456 0.3944091796875 +65457 0.3885498046875 +65458 0.362640380859375 +65459 0.27362060546875 +65460 0.11712646484375 +65461 -0.054901123046875 +65462 -0.19085693359375 +65463 -0.28570556640625 +65464 -0.339263916015625 +65465 -0.3775634765625 +65466 -0.445709228515625 +65467 -0.535064697265625 +65468 -0.629058837890625 +65469 -0.697601318359375 +65470 -0.70391845703125 +65471 -0.6424560546875 +65472 -0.491241455078125 +65473 -0.265716552734375 +65474 -0.023712158203125 +65475 0.201751708984375 +65476 0.375823974609375 +65477 0.485076904296875 +65478 0.56884765625 +65479 0.634765625 +65480 0.63763427734375 +65481 0.5660400390625 +65482 0.4720458984375 +65483 0.40692138671875 +65484 0.3778076171875 +65485 0.376953125 +65486 0.371978759765625 +65487 0.313140869140625 +65488 0.184417724609375 +65489 0.011199951171875 +65490 -0.171051025390625 +65491 -0.33740234375 +65492 -0.47198486328125 +65493 -0.560394287109375 +65494 -0.58056640625 +65495 -0.54754638671875 +65496 -0.508575439453125 +65497 -0.459503173828125 +65498 -0.394378662109375 +65499 -0.35260009765625 +65500 -0.31170654296875 +65501 -0.197418212890625 +65502 -0.007965087890625 +65503 0.207489013671875 +65504 0.409210205078125 +65505 0.57208251953125 +65506 0.66595458984375 +65507 0.65875244140625 +65508 0.56744384765625 +65509 0.431396484375 +65510 0.29443359375 +65511 0.182464599609375 +65512 0.06365966796875 +65513 -0.075958251953125 +65514 -0.189422607421875 +65515 -0.271942138671875 +65516 -0.342529296875 +65517 -0.364166259765625 +65518 -0.327239990234375 +65519 -0.2769775390625 +65520 -0.253692626953125 +65521 -0.24365234375 +65522 -0.1983642578125 +65523 -0.116241455078125 +65524 -0.036834716796875 +65525 0.034881591796875 +65526 0.09124755859375 +65527 0.10888671875 +65528 0.125518798828125 +65529 0.15771484375 +65530 0.17828369140625 +65531 0.17108154296875 +65532 0.129974365234375 +65533 0.082427978515625 +65534 0.027679443359375 +65535 -0.065643310546875 +65536 -0.15936279296875 +65537 -0.21307373046875 +65538 -0.234649658203125 +65539 -0.2001953125 +65540 -0.119171142578125 +65541 -0.024749755859375 +65542 0.085784912109375 +65543 0.178131103515625 +65544 0.215576171875 +65545 0.211456298828125 +65546 0.17523193359375 +65547 0.128753662109375 +65548 0.1019287109375 +65549 0.0743408203125 +65550 0.04327392578125 +65551 0.038177490234375 +65552 0.076263427734375 +65553 0.14105224609375 +65554 0.186431884765625 +65555 0.188812255859375 +65556 0.1390380859375 +65557 0.041778564453125 +65558 -0.079437255859375 +65559 -0.219390869140625 +65560 -0.367828369140625 +65561 -0.494873046875 +65562 -0.556243896484375 +65563 -0.508697509765625 +65564 -0.3756103515625 +65565 -0.218902587890625 +65566 -0.063751220703125 +65567 0.091552734375 +65568 0.23602294921875 +65569 0.342987060546875 +65570 0.39520263671875 +65571 0.389373779296875 +65572 0.324249267578125 +65573 0.224090576171875 +65574 0.124267578125 +65575 0.037078857421875 +65576 -0.010101318359375 +65577 -0.019439697265625 +65578 -0.022796630859375 +65579 -0.001556396484375 +65580 0.056304931640625 +65581 0.106719970703125 +65582 0.096893310546875 +65583 0.042694091796875 +65584 -0.018035888671875 +65585 -0.07586669921875 +65586 -0.11944580078125 +65587 -0.15972900390625 +65588 -0.202606201171875 +65589 -0.24859619140625 +65590 -0.30517578125 +65591 -0.36212158203125 +65592 -0.39141845703125 +65593 -0.35528564453125 +65594 -0.249969482421875 +65595 -0.092864990234375 +65596 0.08905029296875 +65597 0.2352294921875 +65598 0.318817138671875 +65599 0.358642578125 +65600 0.347747802734375 +65601 0.28564453125 +65602 0.223175048828125 +65603 0.196746826171875 +65604 0.179840087890625 +65605 0.155548095703125 +65606 0.151214599609375 +65607 0.156951904296875 +65608 0.13177490234375 +65609 0.100799560546875 +65610 0.087127685546875 +65611 0.05487060546875 +65612 -0.009002685546875 +65613 -0.10400390625 +65614 -0.229400634765625 +65615 -0.35552978515625 +65616 -0.441925048828125 +65617 -0.473846435546875 +65618 -0.464813232421875 +65619 -0.419097900390625 +65620 -0.334320068359375 +65621 -0.227935791015625 +65622 -0.12347412109375 +65623 -0.02764892578125 +65624 0.077667236328125 +65625 0.2132568359375 +65626 0.38885498046875 +65627 0.582794189453125 +65628 0.734039306640625 +65629 0.800140380859375 +65630 0.7783203125 +65631 0.6651611328125 +65632 0.45965576171875 +65633 0.199188232421875 +65634 -0.050689697265625 +65635 -0.23297119140625 +65636 -0.33013916015625 +65637 -0.368408203125 +65638 -0.378936767578125 +65639 -0.376983642578125 +65640 -0.37969970703125 +65641 -0.391510009765625 +65642 -0.385345458984375 +65643 -0.3419189453125 +65644 -0.28289794921875 +65645 -0.251617431640625 +65646 -0.266143798828125 +65647 -0.273345947265625 +65648 -0.216796875 +65649 -0.128265380859375 +65650 -0.068145751953125 +65651 -0.0430908203125 +65652 -0.024444580078125 +65653 0.020721435546875 +65654 0.124481201171875 +65655 0.25787353515625 +65656 0.379119873046875 +65657 0.47991943359375 +65658 0.5281982421875 +65659 0.511138916015625 +65660 0.456207275390625 +65661 0.407470703125 +65662 0.383758544921875 +65663 0.35687255859375 +65664 0.31182861328125 +65665 0.250885009765625 +65666 0.1654052734375 +65667 0.035247802734375 +65668 -0.142059326171875 +65669 -0.33563232421875 +65670 -0.5345458984375 +65671 -0.72186279296875 +65672 -0.836669921875 +65673 -0.8326416015625 +65674 -0.7296142578125 +65675 -0.582550048828125 +65676 -0.440093994140625 +65677 -0.324310302734375 +65678 -0.20147705078125 +65679 -0.044647216796875 +65680 0.103973388671875 +65681 0.202392578125 +65682 0.264495849609375 +65683 0.338897705078125 +65684 0.443817138671875 +65685 0.545074462890625 +65686 0.6173095703125 +65687 0.6524658203125 +65688 0.66339111328125 +65689 0.6561279296875 +65690 0.606781005859375 +65691 0.501190185546875 +65692 0.352783203125 +65693 0.176544189453125 +65694 -0.034820556640625 +65695 -0.258209228515625 +65696 -0.44244384765625 +65697 -0.5753173828125 +65698 -0.65203857421875 +65699 -0.641632080078125 +65700 -0.562164306640625 +65701 -0.458038330078125 +65702 -0.350555419921875 +65703 -0.260528564453125 +65704 -0.192108154296875 +65705 -0.141937255859375 +65706 -0.1021728515625 +65707 -0.062896728515625 +65708 -0.011932373046875 +65709 0.062835693359375 +65710 0.148712158203125 +65711 0.241729736328125 +65712 0.34912109375 +65713 0.457305908203125 +65714 0.54388427734375 +65715 0.5728759765625 +65716 0.506591796875 +65717 0.351226806640625 +65718 0.146514892578125 +65719 -0.05523681640625 +65720 -0.21624755859375 +65721 -0.334930419921875 +65722 -0.402984619140625 +65723 -0.4412841796875 +65724 -0.49578857421875 +65725 -0.5601806640625 +65726 -0.600738525390625 +65727 -0.584228515625 +65728 -0.47930908203125 +65729 -0.27935791015625 +65730 -0.0089111328125 +65731 0.268798828125 +65732 0.482818603515625 +65733 0.60369873046875 +65734 0.650421142578125 +65735 0.66400146484375 +65736 0.6414794921875 +65737 0.572540283203125 +65738 0.498138427734375 +65739 0.439453125 +65740 0.375518798828125 +65741 0.274505615234375 +65742 0.1087646484375 +65743 -0.099395751953125 +65744 -0.3182373046875 +65745 -0.5489501953125 +65746 -0.7738037109375 +65747 -0.86383056640625 +65748 -0.870391845703125 +65749 -0.86895751953125 +65750 -0.861053466796875 +65751 -0.765869140625 +65752 -0.5301513671875 +65753 -0.214691162109375 +65754 0.137359619140625 +65755 0.474822998046875 +65756 0.76239013671875 +65757 0.867462158203125 +65758 0.870361328125 +65759 0.86480712890625 +65760 0.831817626953125 +65761 0.677581787109375 +65762 0.495880126953125 +65763 0.30767822265625 +65764 0.116180419921875 +65765 -0.110748291015625 +65766 -0.381805419921875 +65767 -0.6572265625 +65768 -0.857421875 +65769 -0.870391845703125 +65770 -0.870391845703125 +65771 -0.86444091796875 +65772 -0.85723876953125 +65773 -0.790008544921875 +65774 -0.62847900390625 +65775 -0.3956298828125 +65776 -0.126708984375 +65777 0.150115966796875 +65778 0.424041748046875 +65779 0.670623779296875 +65780 0.854522705078125 +65781 0.866485595703125 +65782 0.86920166015625 +65783 0.8653564453125 +65784 0.857147216796875 +65785 0.766845703125 +65786 0.628509521484375 +65787 0.462127685546875 +65788 0.297210693359375 +65789 0.14862060546875 +65790 -0.00537109375 +65791 -0.15753173828125 +65792 -0.31304931640625 +65793 -0.48876953125 +65794 -0.6416015625 +65795 -0.751373291015625 +65796 -0.84619140625 +65797 -0.861297607421875 +65798 -0.863250732421875 +65799 -0.856597900390625 +65800 -0.7498779296875 +65801 -0.624542236328125 +65802 -0.47808837890625 +65803 -0.253387451171875 +65804 0.003692626953125 +65805 0.2257080078125 +65806 0.427154541015625 +65807 0.643218994140625 +65808 0.855926513671875 +65809 0.870361328125 +65810 0.870361328125 +65811 0.862762451171875 +65812 0.79669189453125 +65813 0.595794677734375 +65814 0.362152099609375 +65815 0.1270751953125 +65816 -0.086944580078125 +65817 -0.2784423828125 +65818 -0.484832763671875 +65819 -0.729583740234375 +65820 -0.86688232421875 +65821 -0.870391845703125 +65822 -0.86859130859375 +65823 -0.86279296875 +65824 -0.817962646484375 +65825 -0.6116943359375 +65826 -0.3128662109375 +65827 0.039398193359375 +65828 0.422821044921875 +65829 0.805145263671875 +65830 0.870361328125 +65831 0.870361328125 +65832 0.860015869140625 +65833 0.727935791015625 +65834 0.48114013671875 +65835 0.2059326171875 +65836 -0.06103515625 +65837 -0.29913330078125 +65838 -0.516204833984375 +65839 -0.7252197265625 +65840 -0.85980224609375 +65841 -0.870391845703125 +65842 -0.870391845703125 +65843 -0.858062744140625 +65844 -0.673004150390625 +65845 -0.42694091796875 +65846 -0.2100830078125 +65847 -0.0362548828125 +65848 0.10943603515625 +65849 0.23516845703125 +65850 0.373687744140625 +65851 0.517791748046875 +65852 0.602783203125 +65853 0.635711669921875 +65854 0.655181884765625 +65855 0.65948486328125 +65856 0.651275634765625 +65857 0.61846923828125 +65858 0.53753662109375 +65859 0.404144287109375 +65860 0.22186279296875 +65861 0.003997802734375 +65862 -0.22100830078125 +65863 -0.42449951171875 +65864 -0.579833984375 +65865 -0.641876220703125 +65866 -0.6177978515625 +65867 -0.575531005859375 +65868 -0.526336669921875 +65869 -0.42645263671875 +65870 -0.2581787109375 +65871 -0.068695068359375 +65872 0.09222412109375 +65873 0.232147216796875 +65874 0.3509521484375 +65875 0.410064697265625 +65876 0.372955322265625 +65877 0.2554931640625 +65878 0.10711669921875 +65879 -0.052886962890625 +65880 -0.186279296875 +65881 -0.23291015625 +65882 -0.209442138671875 +65883 -0.174163818359375 +65884 -0.126739501953125 +65885 -0.048126220703125 +65886 0.0426025390625 +65887 0.10748291015625 +65888 0.1409912109375 +65889 0.19708251953125 +65890 0.273651123046875 +65891 0.31768798828125 +65892 0.341094970703125 +65893 0.368011474609375 +65894 0.37249755859375 +65895 0.30072021484375 +65896 0.1517333984375 +65897 -0.01470947265625 +65898 -0.1883544921875 +65899 -0.372711181640625 +65900 -0.51397705078125 +65901 -0.57177734375 +65902 -0.53948974609375 +65903 -0.43511962890625 +65904 -0.2962646484375 +65905 -0.161102294921875 +65906 -0.0435791015625 +65907 0.060394287109375 +65908 0.13665771484375 +65909 0.170135498046875 +65910 0.16552734375 +65911 0.15728759765625 +65912 0.150787353515625 +65913 0.12200927734375 +65914 0.080108642578125 +65915 0.05126953125 +65916 0.062896728515625 +65917 0.09271240234375 +65918 0.092987060546875 +65919 0.07855224609375 +65920 0.06427001953125 +65921 0.0347900390625 +65922 -0.01171875 +65923 -0.056060791015625 +65924 -0.055511474609375 +65925 -0.010467529296875 +65926 0.02508544921875 +65927 0.025665283203125 +65928 0.017333984375 +65929 0.00189208984375 +65930 -0.03173828125 +65931 -0.071502685546875 +65932 -0.13543701171875 +65933 -0.219970703125 +65934 -0.300506591796875 +65935 -0.376312255859375 +65936 -0.416107177734375 +65937 -0.371124267578125 +65938 -0.242279052734375 +65939 -0.069732666015625 +65940 0.125640869140625 +65941 0.31268310546875 +65942 0.45501708984375 +65943 0.554779052734375 +65944 0.61065673828125 +65945 0.610931396484375 +65946 0.531463623046875 +65947 0.3883056640625 +65948 0.23468017578125 +65949 0.095245361328125 +65950 -0.00396728515625 +65951 -0.04852294921875 +65952 -0.055145263671875 +65953 -0.0758056640625 +65954 -0.138702392578125 +65955 -0.209197998046875 +65956 -0.289031982421875 +65957 -0.37884521484375 +65958 -0.456329345703125 +65959 -0.51641845703125 +65960 -0.519287109375 +65961 -0.458251953125 +65962 -0.384796142578125 +65963 -0.323699951171875 +65964 -0.269287109375 +65965 -0.1951904296875 +65966 -0.100006103515625 +65967 -0.01055908203125 +65968 0.1033935546875 +65969 0.24908447265625 +65970 0.373199462890625 +65971 0.45806884765625 +65972 0.511474609375 +65973 0.565399169921875 +65974 0.61138916015625 +65975 0.5897216796875 +65976 0.4906005859375 +65977 0.33148193359375 +65978 0.147796630859375 +65979 -0.01873779296875 +65980 -0.140289306640625 +65981 -0.191986083984375 +65982 -0.184295654296875 +65983 -0.161834716796875 +65984 -0.166595458984375 +65985 -0.19390869140625 +65986 -0.22442626953125 +65987 -0.279754638671875 +65988 -0.3389892578125 +65989 -0.3543701171875 +65990 -0.348175048828125 +65991 -0.32598876953125 +65992 -0.2581787109375 +65993 -0.139801025390625 +65994 0.014617919921875 +65995 0.144378662109375 +65996 0.221038818359375 +65997 0.27069091796875 +65998 0.294036865234375 +65999 0.311767578125 +66000 0.339141845703125 +66001 0.360260009765625 +66002 0.360504150390625 +66003 0.308380126953125 +66004 0.18170166015625 +66005 0.0047607421875 +66006 -0.17559814453125 +66007 -0.3143310546875 +66008 -0.36785888671875 +66009 -0.36248779296875 +66010 -0.343536376953125 +66011 -0.3018798828125 +66012 -0.231414794921875 +66013 -0.117645263671875 +66014 0.007049560546875 +66015 0.087982177734375 +66016 0.13946533203125 +66017 0.17425537109375 +66018 0.188201904296875 +66019 0.171234130859375 +66020 0.118438720703125 +66021 0.05706787109375 +66022 -0.010711669921875 +66023 -0.0914306640625 +66024 -0.162322998046875 +66025 -0.194549560546875 +66026 -0.1492919921875 +66027 -0.02166748046875 +66028 0.124053955078125 +66029 0.211151123046875 +66030 0.240447998046875 +66031 0.242218017578125 +66032 0.2257080078125 +66033 0.194366455078125 +66034 0.115509033203125 +66035 0.0128173828125 +66036 -0.053802490234375 +66037 -0.110626220703125 +66038 -0.199493408203125 +66039 -0.29437255859375 +66040 -0.33221435546875 +66041 -0.27972412109375 +66042 -0.185333251953125 +66043 -0.128204345703125 +66044 -0.115692138671875 +66045 -0.116455078125 +66046 -0.105926513671875 +66047 -0.053955078125 +66048 0.048797607421875 +66049 0.157318115234375 +66050 0.212005615234375 +66051 0.218475341796875 +66052 0.23724365234375 +66053 0.30535888671875 +66054 0.38128662109375 +66055 0.404449462890625 +66056 0.3944091796875 +66057 0.3885498046875 +66058 0.362640380859375 +66059 0.27362060546875 +66060 0.11712646484375 +66061 -0.054901123046875 +66062 -0.19085693359375 +66063 -0.28570556640625 +66064 -0.339263916015625 +66065 -0.3775634765625 +66066 -0.445709228515625 +66067 -0.535064697265625 +66068 -0.629058837890625 +66069 -0.697601318359375 +66070 -0.70391845703125 +66071 -0.6424560546875 +66072 -0.491241455078125 +66073 -0.265716552734375 +66074 -0.023712158203125 +66075 0.201751708984375 +66076 0.375823974609375 +66077 0.485076904296875 +66078 0.56884765625 +66079 0.634765625 +66080 0.63763427734375 +66081 0.5660400390625 +66082 0.4720458984375 +66083 0.40692138671875 +66084 0.3778076171875 +66085 0.376953125 +66086 0.371978759765625 +66087 0.313140869140625 +66088 0.184417724609375 +66089 0.011199951171875 +66090 -0.171051025390625 +66091 -0.33740234375 +66092 -0.47198486328125 +66093 -0.560394287109375 +66094 -0.58056640625 +66095 -0.54754638671875 +66096 -0.508575439453125 +66097 -0.459503173828125 +66098 -0.394378662109375 +66099 -0.35260009765625 +66100 -0.31170654296875 +66101 -0.197418212890625 +66102 -0.007965087890625 +66103 0.207489013671875 +66104 0.409210205078125 +66105 0.57208251953125 +66106 0.66595458984375 +66107 0.65875244140625 +66108 0.56744384765625 +66109 0.431396484375 +66110 0.29443359375 +66111 0.182464599609375 +66112 0.06365966796875 +66113 -0.075958251953125 +66114 -0.189422607421875 +66115 -0.271942138671875 +66116 -0.342529296875 +66117 -0.364166259765625 +66118 -0.327239990234375 +66119 -0.2769775390625 +66120 -0.253692626953125 +66121 -0.24365234375 +66122 -0.1983642578125 +66123 -0.116241455078125 +66124 -0.036834716796875 +66125 0.034881591796875 +66126 0.09124755859375 +66127 0.10888671875 +66128 0.125518798828125 +66129 0.15771484375 +66130 0.17828369140625 +66131 0.17108154296875 +66132 0.129974365234375 +66133 0.082427978515625 +66134 0.027679443359375 +66135 -0.065643310546875 +66136 -0.15936279296875 +66137 -0.21307373046875 +66138 -0.234649658203125 +66139 -0.2001953125 +66140 -0.119171142578125 +66141 -0.024749755859375 +66142 0.085784912109375 +66143 0.178131103515625 +66144 0.215576171875 +66145 0.211456298828125 +66146 0.17523193359375 +66147 0.128753662109375 +66148 0.1019287109375 +66149 0.0743408203125 +66150 0.04327392578125 +66151 0.038177490234375 +66152 0.076263427734375 +66153 0.14105224609375 +66154 0.186431884765625 +66155 0.188812255859375 +66156 0.1390380859375 +66157 0.041778564453125 +66158 -0.079437255859375 +66159 -0.219390869140625 +66160 -0.367828369140625 +66161 -0.494873046875 +66162 -0.556243896484375 +66163 -0.508697509765625 +66164 -0.3756103515625 +66165 -0.218902587890625 +66166 -0.063751220703125 +66167 0.091552734375 +66168 0.23602294921875 +66169 0.342987060546875 +66170 0.39520263671875 +66171 0.389373779296875 +66172 0.324249267578125 +66173 0.224090576171875 +66174 0.124267578125 +66175 0.037078857421875 +66176 -0.010101318359375 +66177 -0.019439697265625 +66178 -0.022796630859375 +66179 -0.001556396484375 +66180 0.056304931640625 +66181 0.106719970703125 +66182 0.096893310546875 +66183 0.042694091796875 +66184 -0.018035888671875 +66185 -0.07586669921875 +66186 -0.11944580078125 +66187 -0.15972900390625 +66188 -0.202606201171875 +66189 -0.24859619140625 +66190 -0.30517578125 +66191 -0.36212158203125 +66192 -0.39141845703125 +66193 -0.35528564453125 +66194 -0.249969482421875 +66195 -0.092864990234375 +66196 0.08905029296875 +66197 0.2352294921875 +66198 0.318817138671875 +66199 0.358642578125 +66200 0.347747802734375 +66201 0.28564453125 +66202 0.223175048828125 +66203 0.196746826171875 +66204 0.179840087890625 +66205 0.155548095703125 +66206 0.151214599609375 +66207 0.156951904296875 +66208 0.13177490234375 +66209 0.100799560546875 +66210 0.087127685546875 +66211 0.05487060546875 +66212 -0.009002685546875 +66213 -0.10400390625 +66214 -0.229400634765625 +66215 -0.35552978515625 +66216 -0.441925048828125 +66217 -0.473846435546875 +66218 -0.464813232421875 +66219 -0.419097900390625 +66220 -0.334320068359375 +66221 -0.227935791015625 +66222 -0.12347412109375 +66223 -0.02764892578125 +66224 0.077667236328125 +66225 0.2132568359375 +66226 0.38885498046875 +66227 0.582794189453125 +66228 0.734039306640625 +66229 0.800140380859375 +66230 0.7783203125 +66231 0.6651611328125 +66232 0.45965576171875 +66233 0.199188232421875 +66234 -0.050689697265625 +66235 -0.23297119140625 +66236 -0.33013916015625 +66237 -0.368408203125 +66238 -0.378936767578125 +66239 -0.376983642578125 +66240 -0.37969970703125 +66241 -0.391510009765625 +66242 -0.385345458984375 +66243 -0.3419189453125 +66244 -0.28289794921875 +66245 -0.251617431640625 +66246 -0.266143798828125 +66247 -0.273345947265625 +66248 -0.216796875 +66249 -0.128265380859375 +66250 -0.068145751953125 +66251 -0.0430908203125 +66252 -0.024444580078125 +66253 0.020721435546875 +66254 0.124481201171875 +66255 0.25787353515625 +66256 0.379119873046875 +66257 0.47991943359375 +66258 0.5281982421875 +66259 0.511138916015625 +66260 0.456207275390625 +66261 0.407470703125 +66262 0.383758544921875 +66263 0.35687255859375 +66264 0.31182861328125 +66265 0.250885009765625 +66266 0.1654052734375 +66267 0.035247802734375 +66268 -0.142059326171875 +66269 -0.33563232421875 +66270 -0.5345458984375 +66271 -0.72186279296875 +66272 -0.836669921875 +66273 -0.8326416015625 +66274 -0.7296142578125 +66275 -0.582550048828125 +66276 -0.440093994140625 +66277 -0.324310302734375 +66278 -0.20147705078125 +66279 -0.044647216796875 +66280 0.103973388671875 +66281 0.202392578125 +66282 0.264495849609375 +66283 0.338897705078125 +66284 0.443817138671875 +66285 0.545074462890625 +66286 0.6173095703125 +66287 0.6524658203125 +66288 0.66339111328125 +66289 0.6561279296875 +66290 0.606781005859375 +66291 0.501190185546875 +66292 0.352783203125 +66293 0.176544189453125 +66294 -0.034820556640625 +66295 -0.258209228515625 +66296 -0.44244384765625 +66297 -0.5753173828125 +66298 -0.65203857421875 +66299 -0.641632080078125 +66300 -0.562164306640625 +66301 -0.458038330078125 +66302 -0.350555419921875 +66303 -0.260528564453125 +66304 -0.192108154296875 +66305 -0.141937255859375 +66306 -0.1021728515625 +66307 -0.062896728515625 +66308 -0.011932373046875 +66309 0.062835693359375 +66310 0.148712158203125 +66311 0.241729736328125 +66312 0.34912109375 +66313 0.457305908203125 +66314 0.54388427734375 +66315 0.5728759765625 +66316 0.506591796875 +66317 0.351226806640625 +66318 0.146514892578125 +66319 -0.05523681640625 +66320 -0.21624755859375 +66321 -0.334930419921875 +66322 -0.402984619140625 +66323 -0.4412841796875 +66324 -0.49578857421875 +66325 -0.5601806640625 +66326 -0.600738525390625 +66327 -0.584228515625 +66328 -0.47930908203125 +66329 -0.27935791015625 +66330 -0.0089111328125 +66331 0.268798828125 +66332 0.482818603515625 +66333 0.60369873046875 +66334 0.650421142578125 +66335 0.66400146484375 +66336 0.6414794921875 +66337 0.572540283203125 +66338 0.498138427734375 +66339 0.439453125 +66340 0.375518798828125 +66341 0.274505615234375 +66342 0.1087646484375 +66343 -0.099395751953125 +66344 -0.3182373046875 +66345 -0.5489501953125 +66346 -0.7738037109375 +66347 -0.86383056640625 +66348 -0.870391845703125 +66349 -0.86895751953125 +66350 -0.861053466796875 +66351 -0.765869140625 +66352 -0.5301513671875 +66353 -0.214691162109375 +66354 0.137359619140625 +66355 0.474822998046875 +66356 0.76239013671875 +66357 0.867462158203125 +66358 0.870361328125 +66359 0.86480712890625 +66360 0.831817626953125 +66361 0.677581787109375 +66362 0.495880126953125 +66363 0.30767822265625 +66364 0.116180419921875 +66365 -0.110748291015625 +66366 -0.381805419921875 +66367 -0.6572265625 +66368 -0.857421875 +66369 -0.870391845703125 +66370 -0.870391845703125 +66371 -0.86444091796875 +66372 -0.85723876953125 +66373 -0.790008544921875 +66374 -0.62847900390625 +66375 -0.3956298828125 +66376 -0.126708984375 +66377 0.150115966796875 +66378 0.424041748046875 +66379 0.670623779296875 +66380 0.854522705078125 +66381 0.866485595703125 +66382 0.86920166015625 +66383 0.8653564453125 +66384 0.857147216796875 +66385 0.766845703125 +66386 0.628509521484375 +66387 0.462127685546875 +66388 0.297210693359375 +66389 0.14862060546875 +66390 -0.00537109375 +66391 -0.15753173828125 +66392 -0.31304931640625 +66393 -0.48876953125 +66394 -0.6416015625 +66395 -0.751373291015625 +66396 -0.84619140625 +66397 -0.861297607421875 +66398 -0.863250732421875 +66399 -0.856597900390625 +66400 -0.7498779296875 +66401 -0.624542236328125 +66402 -0.47808837890625 +66403 -0.253387451171875 +66404 0.003692626953125 +66405 0.2257080078125 +66406 0.427154541015625 +66407 0.643218994140625 +66408 0.855926513671875 +66409 0.870361328125 +66410 0.870361328125 +66411 0.862762451171875 +66412 0.79669189453125 +66413 0.595794677734375 +66414 0.362152099609375 +66415 0.1270751953125 +66416 -0.086944580078125 +66417 -0.2784423828125 +66418 -0.484832763671875 +66419 -0.729583740234375 +66420 -0.86688232421875 +66421 -0.870391845703125 +66422 -0.86859130859375 +66423 -0.86279296875 +66424 -0.817962646484375 +66425 -0.6116943359375 +66426 -0.3128662109375 +66427 0.039398193359375 +66428 0.422821044921875 +66429 0.805145263671875 +66430 0.870361328125 +66431 0.870361328125 +66432 0.860015869140625 +66433 0.727935791015625 +66434 0.48114013671875 +66435 0.2059326171875 +66436 -0.06103515625 +66437 -0.29913330078125 +66438 -0.516204833984375 +66439 -0.7252197265625 +66440 -0.85980224609375 +66441 -0.870391845703125 +66442 -0.870391845703125 +66443 -0.858062744140625 +66444 -0.673004150390625 +66445 -0.42694091796875 +66446 -0.2100830078125 +66447 -0.0362548828125 +66448 0.10943603515625 +66449 0.23516845703125 +66450 0.373687744140625 +66451 0.517791748046875 +66452 0.602783203125 +66453 0.635711669921875 +66454 0.655181884765625 +66455 0.65948486328125 +66456 0.651275634765625 +66457 0.61846923828125 +66458 0.53753662109375 +66459 0.404144287109375 +66460 0.22186279296875 +66461 0.003997802734375 +66462 -0.22100830078125 +66463 -0.42449951171875 +66464 -0.579833984375 +66465 -0.641876220703125 +66466 -0.6177978515625 +66467 -0.575531005859375 +66468 -0.526336669921875 +66469 -0.42645263671875 +66470 -0.2581787109375 +66471 -0.068695068359375 +66472 0.09222412109375 +66473 0.232147216796875 +66474 0.3509521484375 +66475 0.410064697265625 +66476 0.372955322265625 +66477 0.2554931640625 +66478 0.10711669921875 +66479 -0.052886962890625 +66480 -0.186279296875 +66481 -0.23291015625 +66482 -0.209442138671875 +66483 -0.174163818359375 +66484 -0.126739501953125 +66485 -0.048126220703125 +66486 0.0426025390625 +66487 0.10748291015625 +66488 0.1409912109375 +66489 0.19708251953125 +66490 0.273651123046875 +66491 0.31768798828125 +66492 0.341094970703125 +66493 0.368011474609375 +66494 0.37249755859375 +66495 0.30072021484375 +66496 0.1517333984375 +66497 -0.01470947265625 +66498 -0.1883544921875 +66499 -0.372711181640625 +66500 -0.51397705078125 +66501 -0.57177734375 +66502 -0.53948974609375 +66503 -0.43511962890625 +66504 -0.2962646484375 +66505 -0.161102294921875 +66506 -0.0435791015625 +66507 0.060394287109375 +66508 0.13665771484375 +66509 0.170135498046875 +66510 0.16552734375 +66511 0.15728759765625 +66512 0.150787353515625 +66513 0.12200927734375 +66514 0.080108642578125 +66515 0.05126953125 +66516 0.062896728515625 +66517 0.09271240234375 +66518 0.092987060546875 +66519 0.07855224609375 +66520 0.06427001953125 +66521 0.0347900390625 +66522 -0.01171875 +66523 -0.056060791015625 +66524 -0.055511474609375 +66525 -0.010467529296875 +66526 0.02508544921875 +66527 0.025665283203125 +66528 0.017333984375 +66529 0.00189208984375 +66530 -0.03173828125 +66531 -0.071502685546875 +66532 -0.13543701171875 +66533 -0.219970703125 +66534 -0.300506591796875 +66535 -0.376312255859375 +66536 -0.416107177734375 +66537 -0.371124267578125 +66538 -0.242279052734375 +66539 -0.069732666015625 +66540 0.125640869140625 +66541 0.31268310546875 +66542 0.45501708984375 +66543 0.554779052734375 +66544 0.61065673828125 +66545 0.610931396484375 +66546 0.531463623046875 +66547 0.3883056640625 +66548 0.23468017578125 +66549 0.095245361328125 +66550 -0.00396728515625 +66551 -0.04852294921875 +66552 -0.055145263671875 +66553 -0.0758056640625 +66554 -0.138702392578125 +66555 -0.209197998046875 +66556 -0.289031982421875 +66557 -0.37884521484375 +66558 -0.456329345703125 +66559 -0.51641845703125 +66560 -0.519287109375 +66561 -0.458251953125 +66562 -0.384796142578125 +66563 -0.323699951171875 +66564 -0.269287109375 +66565 -0.1951904296875 +66566 -0.100006103515625 +66567 -0.01055908203125 +66568 0.1033935546875 +66569 0.24908447265625 +66570 0.373199462890625 +66571 0.45806884765625 +66572 0.511474609375 +66573 0.565399169921875 +66574 0.61138916015625 +66575 0.5897216796875 +66576 0.4906005859375 +66577 0.33148193359375 +66578 0.147796630859375 +66579 -0.01873779296875 +66580 -0.140289306640625 +66581 -0.191986083984375 +66582 -0.184295654296875 +66583 -0.161834716796875 +66584 -0.166595458984375 +66585 -0.19390869140625 +66586 -0.22442626953125 +66587 -0.279754638671875 +66588 -0.3389892578125 +66589 -0.3543701171875 +66590 -0.348175048828125 +66591 -0.32598876953125 +66592 -0.2581787109375 +66593 -0.139801025390625 +66594 0.014617919921875 +66595 0.144378662109375 +66596 0.221038818359375 +66597 0.27069091796875 +66598 0.294036865234375 +66599 0.311767578125 +66600 0.339141845703125 +66601 0.360260009765625 +66602 0.360504150390625 +66603 0.308380126953125 +66604 0.18170166015625 +66605 0.0047607421875 +66606 -0.17559814453125 +66607 -0.3143310546875 +66608 -0.36785888671875 +66609 -0.36248779296875 +66610 -0.343536376953125 +66611 -0.3018798828125 +66612 -0.231414794921875 +66613 -0.117645263671875 +66614 0.007049560546875 +66615 0.087982177734375 +66616 0.13946533203125 +66617 0.17425537109375 +66618 0.188201904296875 +66619 0.171234130859375 +66620 0.118438720703125 +66621 0.05706787109375 +66622 -0.010711669921875 +66623 -0.0914306640625 +66624 -0.162322998046875 +66625 -0.194549560546875 +66626 -0.1492919921875 +66627 -0.02166748046875 +66628 0.124053955078125 +66629 0.211151123046875 +66630 0.240447998046875 +66631 0.242218017578125 +66632 0.2257080078125 +66633 0.194366455078125 +66634 0.115509033203125 +66635 0.0128173828125 +66636 -0.053802490234375 +66637 -0.110626220703125 +66638 -0.199493408203125 +66639 -0.29437255859375 +66640 -0.33221435546875 +66641 -0.27972412109375 +66642 -0.185333251953125 +66643 -0.128204345703125 +66644 -0.115692138671875 +66645 -0.116455078125 +66646 -0.105926513671875 +66647 -0.053955078125 +66648 0.048797607421875 +66649 0.157318115234375 +66650 0.212005615234375 +66651 0.218475341796875 +66652 0.23724365234375 +66653 0.30535888671875 +66654 0.38128662109375 +66655 0.404449462890625 +66656 0.3944091796875 +66657 0.3885498046875 +66658 0.362640380859375 +66659 0.27362060546875 +66660 0.11712646484375 +66661 -0.054901123046875 +66662 -0.19085693359375 +66663 -0.28570556640625 +66664 -0.339263916015625 +66665 -0.3775634765625 +66666 -0.445709228515625 +66667 -0.535064697265625 +66668 -0.629058837890625 +66669 -0.697601318359375 +66670 -0.70391845703125 +66671 -0.6424560546875 +66672 -0.491241455078125 +66673 -0.265716552734375 +66674 -0.023712158203125 +66675 0.201751708984375 +66676 0.375823974609375 +66677 0.485076904296875 +66678 0.56884765625 +66679 0.634765625 +66680 0.63763427734375 +66681 0.5660400390625 +66682 0.4720458984375 +66683 0.40692138671875 +66684 0.3778076171875 +66685 0.376953125 +66686 0.371978759765625 +66687 0.313140869140625 +66688 0.184417724609375 +66689 0.011199951171875 +66690 -0.171051025390625 +66691 -0.33740234375 +66692 -0.47198486328125 +66693 -0.560394287109375 +66694 -0.58056640625 +66695 -0.54754638671875 +66696 -0.508575439453125 +66697 -0.459503173828125 +66698 -0.394378662109375 +66699 -0.35260009765625 +66700 -0.31170654296875 +66701 -0.197418212890625 +66702 -0.007965087890625 +66703 0.207489013671875 +66704 0.409210205078125 +66705 0.57208251953125 +66706 0.66595458984375 +66707 0.65875244140625 +66708 0.56744384765625 +66709 0.431396484375 +66710 0.29443359375 +66711 0.182464599609375 +66712 0.06365966796875 +66713 -0.075958251953125 +66714 -0.189422607421875 +66715 -0.271942138671875 +66716 -0.342529296875 +66717 -0.364166259765625 +66718 -0.327239990234375 +66719 -0.2769775390625 +66720 -0.253692626953125 +66721 -0.24365234375 +66722 -0.1983642578125 +66723 -0.116241455078125 +66724 -0.036834716796875 +66725 0.034881591796875 +66726 0.09124755859375 +66727 0.10888671875 +66728 0.125518798828125 +66729 0.15771484375 +66730 0.17828369140625 +66731 0.17108154296875 +66732 0.129974365234375 +66733 0.082427978515625 +66734 0.027679443359375 +66735 -0.065643310546875 +66736 -0.15936279296875 +66737 -0.21307373046875 +66738 -0.234649658203125 +66739 -0.2001953125 +66740 -0.119171142578125 +66741 -0.024749755859375 +66742 0.085784912109375 +66743 0.178131103515625 +66744 0.215576171875 +66745 0.211456298828125 +66746 0.17523193359375 +66747 0.128753662109375 +66748 0.1019287109375 +66749 0.0743408203125 +66750 0.04327392578125 +66751 0.038177490234375 +66752 0.076263427734375 +66753 0.14105224609375 +66754 0.186431884765625 +66755 0.188812255859375 +66756 0.1390380859375 +66757 0.041778564453125 +66758 -0.079437255859375 +66759 -0.219390869140625 +66760 -0.367828369140625 +66761 -0.494873046875 +66762 -0.556243896484375 +66763 -0.508697509765625 +66764 -0.3756103515625 +66765 -0.218902587890625 +66766 -0.063751220703125 +66767 0.091552734375 +66768 0.23602294921875 +66769 0.342987060546875 +66770 0.39520263671875 +66771 0.389373779296875 +66772 0.324249267578125 +66773 0.224090576171875 +66774 0.124267578125 +66775 0.037078857421875 +66776 -0.010101318359375 +66777 -0.019439697265625 +66778 -0.022796630859375 +66779 -0.001556396484375 +66780 0.056304931640625 +66781 0.106719970703125 +66782 0.096893310546875 +66783 0.042694091796875 +66784 -0.018035888671875 +66785 -0.07586669921875 +66786 -0.11944580078125 +66787 -0.15972900390625 +66788 -0.202606201171875 +66789 -0.24859619140625 +66790 -0.30517578125 +66791 -0.36212158203125 +66792 -0.39141845703125 +66793 -0.35528564453125 +66794 -0.249969482421875 +66795 -0.092864990234375 +66796 0.08905029296875 +66797 0.2352294921875 +66798 0.318817138671875 +66799 0.358642578125 +66800 0.347747802734375 +66801 0.28564453125 +66802 0.223175048828125 +66803 0.196746826171875 +66804 0.179840087890625 +66805 0.155548095703125 +66806 0.151214599609375 +66807 0.156951904296875 +66808 0.13177490234375 +66809 0.100799560546875 +66810 0.087127685546875 +66811 0.05487060546875 +66812 -0.009002685546875 +66813 -0.10400390625 +66814 -0.229400634765625 +66815 -0.35552978515625 +66816 -0.441925048828125 +66817 -0.473846435546875 +66818 -0.464813232421875 +66819 -0.419097900390625 +66820 -0.334320068359375 +66821 -0.227935791015625 +66822 -0.12347412109375 +66823 -0.02764892578125 +66824 0.077667236328125 +66825 0.2132568359375 +66826 0.38885498046875 +66827 0.582794189453125 +66828 0.734039306640625 +66829 0.800140380859375 +66830 0.7783203125 +66831 0.6651611328125 +66832 0.45965576171875 +66833 0.199188232421875 +66834 -0.050689697265625 +66835 -0.23297119140625 +66836 -0.33013916015625 +66837 -0.368408203125 +66838 -0.378936767578125 +66839 -0.376983642578125 +66840 -0.37969970703125 +66841 -0.391510009765625 +66842 -0.385345458984375 +66843 -0.3419189453125 +66844 -0.28289794921875 +66845 -0.251617431640625 +66846 -0.266143798828125 +66847 -0.273345947265625 +66848 -0.216796875 +66849 -0.128265380859375 +66850 -0.068145751953125 +66851 -0.0430908203125 +66852 -0.024444580078125 +66853 0.020721435546875 +66854 0.124481201171875 +66855 0.25787353515625 +66856 0.379119873046875 +66857 0.47991943359375 +66858 0.5281982421875 +66859 0.511138916015625 +66860 0.456207275390625 +66861 0.407470703125 +66862 0.383758544921875 +66863 0.35687255859375 +66864 0.31182861328125 +66865 0.250885009765625 +66866 0.1654052734375 +66867 0.035247802734375 +66868 -0.142059326171875 +66869 -0.33563232421875 +66870 -0.5345458984375 +66871 -0.72186279296875 +66872 -0.836669921875 +66873 -0.8326416015625 +66874 -0.7296142578125 +66875 -0.582550048828125 +66876 -0.440093994140625 +66877 -0.324310302734375 +66878 -0.20147705078125 +66879 -0.044647216796875 +66880 0.103973388671875 +66881 0.202392578125 +66882 0.264495849609375 +66883 0.338897705078125 +66884 0.443817138671875 +66885 0.545074462890625 +66886 0.6173095703125 +66887 0.6524658203125 +66888 0.66339111328125 +66889 0.6561279296875 +66890 0.606781005859375 +66891 0.501190185546875 +66892 0.352783203125 +66893 0.176544189453125 +66894 -0.034820556640625 +66895 -0.258209228515625 +66896 -0.44244384765625 +66897 -0.5753173828125 +66898 -0.65203857421875 +66899 -0.641632080078125 +66900 -0.562164306640625 +66901 -0.458038330078125 +66902 -0.350555419921875 +66903 -0.260528564453125 +66904 -0.192108154296875 +66905 -0.141937255859375 +66906 -0.1021728515625 +66907 -0.062896728515625 +66908 -0.011932373046875 +66909 0.062835693359375 +66910 0.148712158203125 +66911 0.241729736328125 +66912 0.34912109375 +66913 0.457305908203125 +66914 0.54388427734375 +66915 0.5728759765625 +66916 0.506591796875 +66917 0.351226806640625 +66918 0.146514892578125 +66919 -0.05523681640625 +66920 -0.21624755859375 +66921 -0.334930419921875 +66922 -0.402984619140625 +66923 -0.4412841796875 +66924 -0.49578857421875 +66925 -0.5601806640625 +66926 -0.600738525390625 +66927 -0.584228515625 +66928 -0.47930908203125 +66929 -0.27935791015625 +66930 -0.0089111328125 +66931 0.268798828125 +66932 0.482818603515625 +66933 0.60369873046875 +66934 0.650421142578125 +66935 0.66400146484375 +66936 0.6414794921875 +66937 0.572540283203125 +66938 0.498138427734375 +66939 0.439453125 +66940 0.375518798828125 +66941 0.274505615234375 +66942 0.1087646484375 +66943 -0.099395751953125 +66944 -0.3182373046875 +66945 -0.5489501953125 +66946 -0.7738037109375 +66947 -0.86383056640625 +66948 -0.870391845703125 +66949 -0.86895751953125 +66950 -0.861053466796875 +66951 -0.765869140625 +66952 -0.5301513671875 +66953 -0.214691162109375 +66954 0.137359619140625 +66955 0.474822998046875 +66956 0.76239013671875 +66957 0.867462158203125 +66958 0.870361328125 +66959 0.86480712890625 +66960 0.831817626953125 +66961 0.677581787109375 +66962 0.495880126953125 +66963 0.30767822265625 +66964 0.116180419921875 +66965 -0.110748291015625 +66966 -0.381805419921875 +66967 -0.6572265625 +66968 -0.857421875 +66969 -0.870391845703125 +66970 -0.870391845703125 +66971 -0.86444091796875 +66972 -0.85723876953125 +66973 -0.790008544921875 +66974 -0.62847900390625 +66975 -0.3956298828125 +66976 -0.126708984375 +66977 0.150115966796875 +66978 0.424041748046875 +66979 0.670623779296875 +66980 0.854522705078125 +66981 0.866485595703125 +66982 0.86920166015625 +66983 0.8653564453125 +66984 0.857147216796875 +66985 0.766845703125 +66986 0.628509521484375 +66987 0.462127685546875 +66988 0.297210693359375 +66989 0.14862060546875 +66990 -0.00537109375 +66991 -0.15753173828125 +66992 -0.31304931640625 +66993 -0.48876953125 +66994 -0.6416015625 +66995 -0.751373291015625 +66996 -0.84619140625 +66997 -0.861297607421875 +66998 -0.863250732421875 +66999 -0.856597900390625 +67000 -0.7498779296875 +67001 -0.624542236328125 +67002 -0.47808837890625 +67003 -0.253387451171875 +67004 0.003692626953125 +67005 0.2257080078125 +67006 0.427154541015625 +67007 0.643218994140625 +67008 0.855926513671875 +67009 0.870361328125 +67010 0.870361328125 +67011 0.862762451171875 +67012 0.79669189453125 +67013 0.595794677734375 +67014 0.362152099609375 +67015 0.1270751953125 +67016 -0.086944580078125 +67017 -0.2784423828125 +67018 -0.484832763671875 +67019 -0.729583740234375 +67020 -0.86688232421875 +67021 -0.870391845703125 +67022 -0.86859130859375 +67023 -0.86279296875 +67024 -0.817962646484375 +67025 -0.6116943359375 +67026 -0.3128662109375 +67027 0.039398193359375 +67028 0.422821044921875 +67029 0.805145263671875 +67030 0.870361328125 +67031 0.870361328125 +67032 0.860015869140625 +67033 0.727935791015625 +67034 0.48114013671875 +67035 0.2059326171875 +67036 -0.06103515625 +67037 -0.29913330078125 +67038 -0.516204833984375 +67039 -0.7252197265625 +67040 -0.85980224609375 +67041 -0.870391845703125 +67042 -0.870391845703125 +67043 -0.858062744140625 +67044 -0.673004150390625 +67045 -0.42694091796875 +67046 -0.2100830078125 +67047 -0.0362548828125 +67048 0.10943603515625 +67049 0.23516845703125 +67050 0.373687744140625 +67051 0.517791748046875 +67052 0.602783203125 +67053 0.635711669921875 +67054 0.655181884765625 +67055 0.65948486328125 +67056 0.651275634765625 +67057 0.61846923828125 +67058 0.53753662109375 +67059 0.404144287109375 +67060 0.22186279296875 +67061 0.003997802734375 +67062 -0.22100830078125 +67063 -0.42449951171875 +67064 -0.579833984375 +67065 -0.641876220703125 +67066 -0.6177978515625 +67067 -0.575531005859375 +67068 -0.526336669921875 +67069 -0.42645263671875 +67070 -0.2581787109375 +67071 -0.068695068359375 +67072 0.09222412109375 +67073 0.232147216796875 +67074 0.3509521484375 +67075 0.410064697265625 +67076 0.372955322265625 +67077 0.2554931640625 +67078 0.10711669921875 +67079 -0.052886962890625 +67080 -0.186279296875 +67081 -0.23291015625 +67082 -0.209442138671875 +67083 -0.174163818359375 +67084 -0.126739501953125 +67085 -0.048126220703125 +67086 0.0426025390625 +67087 0.10748291015625 +67088 0.1409912109375 +67089 0.19708251953125 +67090 0.273651123046875 +67091 0.31768798828125 +67092 0.341094970703125 +67093 0.368011474609375 +67094 0.37249755859375 +67095 0.30072021484375 +67096 0.1517333984375 +67097 -0.01470947265625 +67098 -0.1883544921875 +67099 -0.372711181640625 +67100 -0.51397705078125 +67101 -0.57177734375 +67102 -0.53948974609375 +67103 -0.43511962890625 +67104 -0.2962646484375 +67105 -0.161102294921875 +67106 -0.0435791015625 +67107 0.060394287109375 +67108 0.13665771484375 +67109 0.170135498046875 +67110 0.16552734375 +67111 0.15728759765625 +67112 0.150787353515625 +67113 0.12200927734375 +67114 0.080108642578125 +67115 0.05126953125 +67116 0.062896728515625 +67117 0.09271240234375 +67118 0.092987060546875 +67119 0.07855224609375 +67120 0.06427001953125 +67121 0.0347900390625 +67122 -0.01171875 +67123 -0.056060791015625 +67124 -0.055511474609375 +67125 -0.010467529296875 +67126 0.02508544921875 +67127 0.025665283203125 +67128 0.017333984375 +67129 0.00189208984375 +67130 -0.03173828125 +67131 -0.071502685546875 +67132 -0.13543701171875 +67133 -0.219970703125 +67134 -0.300506591796875 +67135 -0.376312255859375 +67136 -0.416107177734375 +67137 -0.371124267578125 +67138 -0.242279052734375 +67139 -0.069732666015625 +67140 0.125640869140625 +67141 0.31268310546875 +67142 0.45501708984375 +67143 0.554779052734375 +67144 0.61065673828125 +67145 0.610931396484375 +67146 0.531463623046875 +67147 0.3883056640625 +67148 0.23468017578125 +67149 0.095245361328125 +67150 -0.00396728515625 +67151 -0.04852294921875 +67152 -0.055145263671875 +67153 -0.0758056640625 +67154 -0.138702392578125 +67155 -0.209197998046875 +67156 -0.289031982421875 +67157 -0.37884521484375 +67158 -0.456329345703125 +67159 -0.51641845703125 +67160 -0.519287109375 +67161 -0.458251953125 +67162 -0.384796142578125 +67163 -0.323699951171875 +67164 -0.269287109375 +67165 -0.1951904296875 +67166 -0.100006103515625 +67167 -0.01055908203125 +67168 0.1033935546875 +67169 0.24908447265625 +67170 0.373199462890625 +67171 0.45806884765625 +67172 0.511474609375 +67173 0.565399169921875 +67174 0.61138916015625 +67175 0.5897216796875 +67176 0.4906005859375 +67177 0.33148193359375 +67178 0.147796630859375 +67179 -0.01873779296875 +67180 -0.140289306640625 +67181 -0.191986083984375 +67182 -0.184295654296875 +67183 -0.161834716796875 +67184 -0.166595458984375 +67185 -0.19390869140625 +67186 -0.22442626953125 +67187 -0.279754638671875 +67188 -0.3389892578125 +67189 -0.3543701171875 +67190 -0.348175048828125 +67191 -0.32598876953125 +67192 -0.2581787109375 +67193 -0.139801025390625 +67194 0.014617919921875 +67195 0.144378662109375 +67196 0.221038818359375 +67197 0.27069091796875 +67198 0.294036865234375 +67199 0.311767578125 +67200 0.339141845703125 +67201 0.360260009765625 +67202 0.360504150390625 +67203 0.308380126953125 +67204 0.18170166015625 +67205 0.0047607421875 +67206 -0.17559814453125 +67207 -0.3143310546875 +67208 -0.36785888671875 +67209 -0.36248779296875 +67210 -0.343536376953125 +67211 -0.3018798828125 +67212 -0.231414794921875 +67213 -0.117645263671875 +67214 0.007049560546875 +67215 0.087982177734375 +67216 0.13946533203125 +67217 0.17425537109375 +67218 0.188201904296875 +67219 0.171234130859375 +67220 0.118438720703125 +67221 0.05706787109375 +67222 -0.010711669921875 +67223 -0.0914306640625 +67224 -0.162322998046875 +67225 -0.194549560546875 +67226 -0.1492919921875 +67227 -0.02166748046875 +67228 0.124053955078125 +67229 0.211151123046875 +67230 0.240447998046875 +67231 0.242218017578125 +67232 0.2257080078125 +67233 0.194366455078125 +67234 0.115509033203125 +67235 0.0128173828125 +67236 -0.053802490234375 +67237 -0.110626220703125 +67238 -0.199493408203125 +67239 -0.29437255859375 +67240 -0.33221435546875 +67241 -0.27972412109375 +67242 -0.185333251953125 +67243 -0.128204345703125 +67244 -0.115692138671875 +67245 -0.116455078125 +67246 -0.105926513671875 +67247 -0.053955078125 +67248 0.048797607421875 +67249 0.157318115234375 +67250 0.212005615234375 +67251 0.218475341796875 +67252 0.23724365234375 +67253 0.30535888671875 +67254 0.38128662109375 +67255 0.404449462890625 +67256 0.3944091796875 +67257 0.3885498046875 +67258 0.362640380859375 +67259 0.27362060546875 +67260 0.11712646484375 +67261 -0.054901123046875 +67262 -0.19085693359375 +67263 -0.28570556640625 +67264 -0.339263916015625 +67265 -0.3775634765625 +67266 -0.445709228515625 +67267 -0.535064697265625 +67268 -0.629058837890625 +67269 -0.697601318359375 +67270 -0.70391845703125 +67271 -0.6424560546875 +67272 -0.491241455078125 +67273 -0.265716552734375 +67274 -0.023712158203125 +67275 0.201751708984375 +67276 0.375823974609375 +67277 0.485076904296875 +67278 0.56884765625 +67279 0.634765625 +67280 0.63763427734375 +67281 0.5660400390625 +67282 0.4720458984375 +67283 0.40692138671875 +67284 0.3778076171875 +67285 0.376953125 +67286 0.371978759765625 +67287 0.313140869140625 +67288 0.184417724609375 +67289 0.011199951171875 +67290 -0.171051025390625 +67291 -0.33740234375 +67292 -0.47198486328125 +67293 -0.560394287109375 +67294 -0.58056640625 +67295 -0.54754638671875 +67296 -0.508575439453125 +67297 -0.459503173828125 +67298 -0.394378662109375 +67299 -0.35260009765625 +67300 -0.31170654296875 +67301 -0.197418212890625 +67302 -0.007965087890625 +67303 0.207489013671875 +67304 0.409210205078125 +67305 0.57208251953125 +67306 0.66595458984375 +67307 0.65875244140625 +67308 0.56744384765625 +67309 0.431396484375 +67310 0.29443359375 +67311 0.182464599609375 +67312 0.06365966796875 +67313 -0.075958251953125 +67314 -0.189422607421875 +67315 -0.271942138671875 +67316 -0.342529296875 +67317 -0.364166259765625 +67318 -0.327239990234375 +67319 -0.2769775390625 +67320 -0.253692626953125 +67321 -0.24365234375 +67322 -0.1983642578125 +67323 -0.116241455078125 +67324 -0.036834716796875 +67325 0.034881591796875 +67326 0.09124755859375 +67327 0.10888671875 +67328 0.125518798828125 +67329 0.15771484375 +67330 0.17828369140625 +67331 0.17108154296875 +67332 0.129974365234375 +67333 0.082427978515625 +67334 0.027679443359375 +67335 -0.065643310546875 +67336 -0.15936279296875 +67337 -0.21307373046875 +67338 -0.234649658203125 +67339 -0.2001953125 +67340 -0.119171142578125 +67341 -0.024749755859375 +67342 0.085784912109375 +67343 0.178131103515625 +67344 0.215576171875 +67345 0.211456298828125 +67346 0.17523193359375 +67347 0.128753662109375 +67348 0.1019287109375 +67349 0.0743408203125 +67350 0.04327392578125 +67351 0.038177490234375 +67352 0.076263427734375 +67353 0.14105224609375 +67354 0.186431884765625 +67355 0.188812255859375 +67356 0.1390380859375 +67357 0.041778564453125 +67358 -0.079437255859375 +67359 -0.219390869140625 +67360 -0.367828369140625 +67361 -0.494873046875 +67362 -0.556243896484375 +67363 -0.508697509765625 +67364 -0.3756103515625 +67365 -0.218902587890625 +67366 -0.063751220703125 +67367 0.091552734375 +67368 0.23602294921875 +67369 0.342987060546875 +67370 0.39520263671875 +67371 0.389373779296875 +67372 0.324249267578125 +67373 0.224090576171875 +67374 0.124267578125 +67375 0.037078857421875 +67376 -0.010101318359375 +67377 -0.019439697265625 +67378 -0.022796630859375 +67379 -0.001556396484375 +67380 0.056304931640625 +67381 0.106719970703125 +67382 0.096893310546875 +67383 0.042694091796875 +67384 -0.018035888671875 +67385 -0.07586669921875 +67386 -0.11944580078125 +67387 -0.15972900390625 +67388 -0.202606201171875 +67389 -0.24859619140625 +67390 -0.30517578125 +67391 -0.36212158203125 +67392 -0.39141845703125 +67393 -0.35528564453125 +67394 -0.249969482421875 +67395 -0.092864990234375 +67396 0.08905029296875 +67397 0.2352294921875 +67398 0.318817138671875 +67399 0.358642578125 +67400 0.347747802734375 +67401 0.28564453125 +67402 0.223175048828125 +67403 0.196746826171875 +67404 0.179840087890625 +67405 0.155548095703125 +67406 0.151214599609375 +67407 0.156951904296875 +67408 0.13177490234375 +67409 0.100799560546875 +67410 0.087127685546875 +67411 0.05487060546875 +67412 -0.009002685546875 +67413 -0.10400390625 +67414 -0.229400634765625 +67415 -0.35552978515625 +67416 -0.441925048828125 +67417 -0.473846435546875 +67418 -0.464813232421875 +67419 -0.419097900390625 +67420 -0.334320068359375 +67421 -0.227935791015625 +67422 -0.12347412109375 +67423 -0.02764892578125 +67424 0.077667236328125 +67425 0.2132568359375 +67426 0.38885498046875 +67427 0.582794189453125 +67428 0.734039306640625 +67429 0.800140380859375 +67430 0.7783203125 +67431 0.6651611328125 +67432 0.45965576171875 +67433 0.199188232421875 +67434 -0.050689697265625 +67435 -0.23297119140625 +67436 -0.33013916015625 +67437 -0.368408203125 +67438 -0.378936767578125 +67439 -0.376983642578125 +67440 -0.37969970703125 +67441 -0.391510009765625 +67442 -0.385345458984375 +67443 -0.3419189453125 +67444 -0.28289794921875 +67445 -0.251617431640625 +67446 -0.266143798828125 +67447 -0.273345947265625 +67448 -0.216796875 +67449 -0.128265380859375 +67450 -0.068145751953125 +67451 -0.0430908203125 +67452 -0.024444580078125 +67453 0.020721435546875 +67454 0.124481201171875 +67455 0.25787353515625 +67456 0.379119873046875 +67457 0.47991943359375 +67458 0.5281982421875 +67459 0.511138916015625 +67460 0.456207275390625 +67461 0.407470703125 +67462 0.383758544921875 +67463 0.35687255859375 +67464 0.31182861328125 +67465 0.250885009765625 +67466 0.1654052734375 +67467 0.035247802734375 +67468 -0.142059326171875 +67469 -0.33563232421875 +67470 -0.5345458984375 +67471 -0.72186279296875 +67472 -0.836669921875 +67473 -0.8326416015625 +67474 -0.7296142578125 +67475 -0.582550048828125 +67476 -0.440093994140625 +67477 -0.324310302734375 +67478 -0.20147705078125 +67479 -0.044647216796875 +67480 0.103973388671875 +67481 0.202392578125 +67482 0.264495849609375 +67483 0.338897705078125 +67484 0.443817138671875 +67485 0.545074462890625 +67486 0.6173095703125 +67487 0.6524658203125 +67488 0.66339111328125 +67489 0.6561279296875 +67490 0.606781005859375 +67491 0.501190185546875 +67492 0.352783203125 +67493 0.176544189453125 +67494 -0.034820556640625 +67495 -0.258209228515625 +67496 -0.44244384765625 +67497 -0.5753173828125 +67498 -0.65203857421875 +67499 -0.641632080078125 +67500 -0.562164306640625 +67501 -0.458038330078125 +67502 -0.350555419921875 +67503 -0.260528564453125 +67504 -0.192108154296875 +67505 -0.141937255859375 +67506 -0.1021728515625 +67507 -0.062896728515625 +67508 -0.011932373046875 +67509 0.062835693359375 +67510 0.148712158203125 +67511 0.241729736328125 +67512 0.34912109375 +67513 0.457305908203125 +67514 0.54388427734375 +67515 0.5728759765625 +67516 0.506591796875 +67517 0.351226806640625 +67518 0.146514892578125 +67519 -0.05523681640625 +67520 -0.21624755859375 +67521 -0.334930419921875 +67522 -0.402984619140625 +67523 -0.4412841796875 +67524 -0.49578857421875 +67525 -0.5601806640625 +67526 -0.600738525390625 +67527 -0.584228515625 +67528 -0.47930908203125 +67529 -0.27935791015625 +67530 -0.0089111328125 +67531 0.268798828125 +67532 0.482818603515625 +67533 0.60369873046875 +67534 0.650421142578125 +67535 0.66400146484375 +67536 0.6414794921875 +67537 0.572540283203125 +67538 0.498138427734375 +67539 0.439453125 +67540 0.375518798828125 +67541 0.274505615234375 +67542 0.1087646484375 +67543 -0.099395751953125 +67544 -0.3182373046875 +67545 -0.5489501953125 +67546 -0.7738037109375 +67547 -0.86383056640625 +67548 -0.870391845703125 +67549 -0.86895751953125 +67550 -0.861053466796875 +67551 -0.765869140625 +67552 -0.5301513671875 +67553 -0.214691162109375 +67554 0.137359619140625 +67555 0.474822998046875 +67556 0.76239013671875 +67557 0.867462158203125 +67558 0.870361328125 +67559 0.86480712890625 +67560 0.831817626953125 +67561 0.677581787109375 +67562 0.495880126953125 +67563 0.30767822265625 +67564 0.116180419921875 +67565 -0.110748291015625 +67566 -0.381805419921875 +67567 -0.6572265625 +67568 -0.857421875 +67569 -0.870391845703125 +67570 -0.870391845703125 +67571 -0.86444091796875 +67572 -0.85723876953125 +67573 -0.790008544921875 +67574 -0.62847900390625 +67575 -0.3956298828125 +67576 -0.126708984375 +67577 0.150115966796875 +67578 0.424041748046875 +67579 0.670623779296875 +67580 0.854522705078125 +67581 0.866485595703125 +67582 0.86920166015625 +67583 0.8653564453125 +67584 0.857147216796875 +67585 0.766845703125 +67586 0.628509521484375 +67587 0.462127685546875 +67588 0.297210693359375 +67589 0.14862060546875 +67590 -0.00537109375 +67591 -0.15753173828125 +67592 -0.31304931640625 +67593 -0.48876953125 +67594 -0.6416015625 +67595 -0.751373291015625 +67596 -0.84619140625 +67597 -0.861297607421875 +67598 -0.863250732421875 +67599 -0.856597900390625 +67600 -0.7498779296875 +67601 -0.624542236328125 +67602 -0.47808837890625 +67603 -0.253387451171875 +67604 0.003692626953125 +67605 0.2257080078125 +67606 0.427154541015625 +67607 0.643218994140625 +67608 0.855926513671875 +67609 0.870361328125 +67610 0.870361328125 +67611 0.862762451171875 +67612 0.79669189453125 +67613 0.595794677734375 +67614 0.362152099609375 +67615 0.1270751953125 +67616 -0.086944580078125 +67617 -0.2784423828125 +67618 -0.484832763671875 +67619 -0.729583740234375 +67620 -0.86688232421875 +67621 -0.870391845703125 +67622 -0.86859130859375 +67623 -0.86279296875 +67624 -0.817962646484375 +67625 -0.6116943359375 +67626 -0.3128662109375 +67627 0.039398193359375 +67628 0.422821044921875 +67629 0.805145263671875 +67630 0.870361328125 +67631 0.870361328125 +67632 0.860015869140625 +67633 0.727935791015625 +67634 0.48114013671875 +67635 0.2059326171875 +67636 -0.06103515625 +67637 -0.29913330078125 +67638 -0.516204833984375 +67639 -0.7252197265625 +67640 -0.85980224609375 +67641 -0.870391845703125 +67642 -0.870391845703125 +67643 -0.858062744140625 +67644 -0.673004150390625 +67645 -0.42694091796875 +67646 -0.2100830078125 +67647 -0.0362548828125 +67648 0.10943603515625 +67649 0.23516845703125 +67650 0.373687744140625 +67651 0.517791748046875 +67652 0.602783203125 +67653 0.635711669921875 +67654 0.655181884765625 +67655 0.65948486328125 +67656 0.651275634765625 +67657 0.61846923828125 +67658 0.53753662109375 +67659 0.404144287109375 +67660 0.22186279296875 +67661 0.003997802734375 +67662 -0.22100830078125 +67663 -0.42449951171875 +67664 -0.579833984375 +67665 -0.641876220703125 +67666 -0.6177978515625 +67667 -0.575531005859375 +67668 -0.526336669921875 +67669 -0.42645263671875 +67670 -0.2581787109375 +67671 -0.068695068359375 +67672 0.09222412109375 +67673 0.232147216796875 +67674 0.3509521484375 +67675 0.410064697265625 +67676 0.372955322265625 +67677 0.2554931640625 +67678 0.10711669921875 +67679 -0.052886962890625 +67680 -0.186279296875 +67681 -0.23291015625 +67682 -0.209442138671875 +67683 -0.174163818359375 +67684 -0.126739501953125 +67685 -0.048126220703125 +67686 0.0426025390625 +67687 0.10748291015625 +67688 0.1409912109375 +67689 0.19708251953125 +67690 0.273651123046875 +67691 0.31768798828125 +67692 0.341094970703125 +67693 0.368011474609375 +67694 0.37249755859375 +67695 0.30072021484375 +67696 0.1517333984375 +67697 -0.01470947265625 +67698 -0.1883544921875 +67699 -0.372711181640625 +67700 -0.51397705078125 +67701 -0.57177734375 +67702 -0.53948974609375 +67703 -0.43511962890625 +67704 -0.2962646484375 +67705 -0.161102294921875 +67706 -0.0435791015625 +67707 0.060394287109375 +67708 0.13665771484375 +67709 0.170135498046875 +67710 0.16552734375 +67711 0.15728759765625 +67712 0.150787353515625 +67713 0.12200927734375 +67714 0.080108642578125 +67715 0.05126953125 +67716 0.062896728515625 +67717 0.09271240234375 +67718 0.092987060546875 +67719 0.07855224609375 +67720 0.06427001953125 +67721 0.0347900390625 +67722 -0.01171875 +67723 -0.056060791015625 +67724 -0.055511474609375 +67725 -0.010467529296875 +67726 0.02508544921875 +67727 0.025665283203125 +67728 0.017333984375 +67729 0.00189208984375 +67730 -0.03173828125 +67731 -0.071502685546875 +67732 -0.13543701171875 +67733 -0.219970703125 +67734 -0.300506591796875 +67735 -0.376312255859375 +67736 -0.416107177734375 +67737 -0.371124267578125 +67738 -0.242279052734375 +67739 -0.069732666015625 +67740 0.125640869140625 +67741 0.31268310546875 +67742 0.45501708984375 +67743 0.554779052734375 +67744 0.61065673828125 +67745 0.610931396484375 +67746 0.531463623046875 +67747 0.3883056640625 +67748 0.23468017578125 +67749 0.095245361328125 +67750 -0.00396728515625 +67751 -0.04852294921875 +67752 -0.055145263671875 +67753 -0.0758056640625 +67754 -0.138702392578125 +67755 -0.209197998046875 +67756 -0.289031982421875 +67757 -0.37884521484375 +67758 -0.456329345703125 +67759 -0.51641845703125 +67760 -0.519287109375 +67761 -0.458251953125 +67762 -0.384796142578125 +67763 -0.323699951171875 +67764 -0.269287109375 +67765 -0.1951904296875 +67766 -0.100006103515625 +67767 -0.01055908203125 +67768 0.1033935546875 +67769 0.24908447265625 +67770 0.373199462890625 +67771 0.45806884765625 +67772 0.511474609375 +67773 0.565399169921875 +67774 0.61138916015625 +67775 0.5897216796875 +67776 0.4906005859375 +67777 0.33148193359375 +67778 0.147796630859375 +67779 -0.01873779296875 +67780 -0.140289306640625 +67781 -0.191986083984375 +67782 -0.184295654296875 +67783 -0.161834716796875 +67784 -0.166595458984375 +67785 -0.19390869140625 +67786 -0.22442626953125 +67787 -0.279754638671875 +67788 -0.3389892578125 +67789 -0.3543701171875 +67790 -0.348175048828125 +67791 -0.32598876953125 +67792 -0.2581787109375 +67793 -0.139801025390625 +67794 0.014617919921875 +67795 0.144378662109375 +67796 0.221038818359375 +67797 0.27069091796875 +67798 0.294036865234375 +67799 0.311767578125 +67800 0.339141845703125 +67801 0.360260009765625 +67802 0.360504150390625 +67803 0.308380126953125 +67804 0.18170166015625 +67805 0.0047607421875 +67806 -0.17559814453125 +67807 -0.3143310546875 +67808 -0.36785888671875 +67809 -0.36248779296875 +67810 -0.343536376953125 +67811 -0.3018798828125 +67812 -0.231414794921875 +67813 -0.117645263671875 +67814 0.007049560546875 +67815 0.087982177734375 +67816 0.13946533203125 +67817 0.17425537109375 +67818 0.188201904296875 +67819 0.171234130859375 +67820 0.118438720703125 +67821 0.05706787109375 +67822 -0.010711669921875 +67823 -0.0914306640625 +67824 -0.162322998046875 +67825 -0.194549560546875 +67826 -0.1492919921875 +67827 -0.02166748046875 +67828 0.124053955078125 +67829 0.211151123046875 +67830 0.240447998046875 +67831 0.242218017578125 +67832 0.2257080078125 +67833 0.194366455078125 +67834 0.115509033203125 +67835 0.0128173828125 +67836 -0.053802490234375 +67837 -0.110626220703125 +67838 -0.199493408203125 +67839 -0.29437255859375 +67840 -0.33221435546875 +67841 -0.27972412109375 +67842 -0.185333251953125 +67843 -0.128204345703125 +67844 -0.115692138671875 +67845 -0.116455078125 +67846 -0.105926513671875 +67847 -0.053955078125 +67848 0.048797607421875 +67849 0.157318115234375 +67850 0.212005615234375 +67851 0.218475341796875 +67852 0.23724365234375 +67853 0.30535888671875 +67854 0.38128662109375 +67855 0.404449462890625 +67856 0.3944091796875 +67857 0.3885498046875 +67858 0.362640380859375 +67859 0.27362060546875 +67860 0.11712646484375 +67861 -0.054901123046875 +67862 -0.19085693359375 +67863 -0.28570556640625 +67864 -0.339263916015625 +67865 -0.3775634765625 +67866 -0.445709228515625 +67867 -0.535064697265625 +67868 -0.629058837890625 +67869 -0.697601318359375 +67870 -0.70391845703125 +67871 -0.6424560546875 +67872 -0.491241455078125 +67873 -0.265716552734375 +67874 -0.023712158203125 +67875 0.201751708984375 +67876 0.375823974609375 +67877 0.485076904296875 +67878 0.56884765625 +67879 0.634765625 +67880 0.63763427734375 +67881 0.5660400390625 +67882 0.4720458984375 +67883 0.40692138671875 +67884 0.3778076171875 +67885 0.376953125 +67886 0.371978759765625 +67887 0.313140869140625 +67888 0.184417724609375 +67889 0.011199951171875 +67890 -0.171051025390625 +67891 -0.33740234375 +67892 -0.47198486328125 +67893 -0.560394287109375 +67894 -0.58056640625 +67895 -0.54754638671875 +67896 -0.508575439453125 +67897 -0.459503173828125 +67898 -0.394378662109375 +67899 -0.35260009765625 +67900 -0.31170654296875 +67901 -0.197418212890625 +67902 -0.007965087890625 +67903 0.207489013671875 +67904 0.409210205078125 +67905 0.57208251953125 +67906 0.66595458984375 +67907 0.65875244140625 +67908 0.56744384765625 +67909 0.431396484375 +67910 0.29443359375 +67911 0.182464599609375 +67912 0.06365966796875 +67913 -0.075958251953125 +67914 -0.189422607421875 +67915 -0.271942138671875 +67916 -0.342529296875 +67917 -0.364166259765625 +67918 -0.327239990234375 +67919 -0.2769775390625 +67920 -0.253692626953125 +67921 -0.24365234375 +67922 -0.1983642578125 +67923 -0.116241455078125 +67924 -0.036834716796875 +67925 0.034881591796875 +67926 0.09124755859375 +67927 0.10888671875 +67928 0.125518798828125 +67929 0.15771484375 +67930 0.17828369140625 +67931 0.17108154296875 +67932 0.129974365234375 +67933 0.082427978515625 +67934 0.027679443359375 +67935 -0.065643310546875 +67936 -0.15936279296875 +67937 -0.21307373046875 +67938 -0.234649658203125 +67939 -0.2001953125 +67940 -0.119171142578125 +67941 -0.024749755859375 +67942 0.085784912109375 +67943 0.178131103515625 +67944 0.215576171875 +67945 0.211456298828125 +67946 0.17523193359375 +67947 0.128753662109375 +67948 0.1019287109375 +67949 0.0743408203125 +67950 0.04327392578125 +67951 0.038177490234375 +67952 0.076263427734375 +67953 0.14105224609375 +67954 0.186431884765625 +67955 0.188812255859375 +67956 0.1390380859375 +67957 0.041778564453125 +67958 -0.079437255859375 +67959 -0.219390869140625 +67960 -0.367828369140625 +67961 -0.494873046875 +67962 -0.556243896484375 +67963 -0.508697509765625 +67964 -0.3756103515625 +67965 -0.218902587890625 +67966 -0.063751220703125 +67967 0.091552734375 +67968 0.23602294921875 +67969 0.342987060546875 +67970 0.39520263671875 +67971 0.389373779296875 +67972 0.324249267578125 +67973 0.224090576171875 +67974 0.124267578125 +67975 0.037078857421875 +67976 -0.010101318359375 +67977 -0.019439697265625 +67978 -0.022796630859375 +67979 -0.001556396484375 +67980 0.056304931640625 +67981 0.106719970703125 +67982 0.096893310546875 +67983 0.042694091796875 +67984 -0.018035888671875 +67985 -0.07586669921875 +67986 -0.11944580078125 +67987 -0.15972900390625 +67988 -0.202606201171875 +67989 -0.24859619140625 +67990 -0.30517578125 +67991 -0.36212158203125 +67992 -0.39141845703125 +67993 -0.35528564453125 +67994 -0.249969482421875 +67995 -0.092864990234375 +67996 0.08905029296875 +67997 0.2352294921875 +67998 0.318817138671875 +67999 0.358642578125 +68000 0.347747802734375 +68001 0.28564453125 +68002 0.223175048828125 +68003 0.196746826171875 +68004 0.179840087890625 +68005 0.155548095703125 +68006 0.151214599609375 +68007 0.156951904296875 +68008 0.13177490234375 +68009 0.100799560546875 +68010 0.087127685546875 +68011 0.05487060546875 +68012 -0.009002685546875 +68013 -0.10400390625 +68014 -0.229400634765625 +68015 -0.35552978515625 +68016 -0.441925048828125 +68017 -0.473846435546875 +68018 -0.464813232421875 +68019 -0.419097900390625 +68020 -0.334320068359375 +68021 -0.227935791015625 +68022 -0.12347412109375 +68023 -0.02764892578125 +68024 0.077667236328125 +68025 0.2132568359375 +68026 0.38885498046875 +68027 0.582794189453125 +68028 0.734039306640625 +68029 0.800140380859375 +68030 0.7783203125 +68031 0.6651611328125 +68032 0.45965576171875 +68033 0.199188232421875 +68034 -0.050689697265625 +68035 -0.23297119140625 +68036 -0.33013916015625 +68037 -0.368408203125 +68038 -0.378936767578125 +68039 -0.376983642578125 +68040 -0.37969970703125 +68041 -0.391510009765625 +68042 -0.385345458984375 +68043 -0.3419189453125 +68044 -0.28289794921875 +68045 -0.251617431640625 +68046 -0.266143798828125 +68047 -0.273345947265625 +68048 -0.216796875 +68049 -0.128265380859375 +68050 -0.068145751953125 +68051 -0.0430908203125 +68052 -0.024444580078125 +68053 0.020721435546875 +68054 0.124481201171875 +68055 0.25787353515625 +68056 0.379119873046875 +68057 0.47991943359375 +68058 0.5281982421875 +68059 0.511138916015625 +68060 0.456207275390625 +68061 0.407470703125 +68062 0.383758544921875 +68063 0.35687255859375 +68064 0.31182861328125 +68065 0.250885009765625 +68066 0.1654052734375 +68067 0.035247802734375 +68068 -0.142059326171875 +68069 -0.33563232421875 +68070 -0.5345458984375 +68071 -0.72186279296875 +68072 -0.836669921875 +68073 -0.8326416015625 +68074 -0.7296142578125 +68075 -0.582550048828125 +68076 -0.440093994140625 +68077 -0.324310302734375 +68078 -0.20147705078125 +68079 -0.044647216796875 +68080 0.103973388671875 +68081 0.202392578125 +68082 0.264495849609375 +68083 0.338897705078125 +68084 0.443817138671875 +68085 0.545074462890625 +68086 0.6173095703125 +68087 0.6524658203125 +68088 0.66339111328125 +68089 0.6561279296875 +68090 0.606781005859375 +68091 0.501190185546875 +68092 0.352783203125 +68093 0.176544189453125 +68094 -0.034820556640625 +68095 -0.258209228515625 +68096 -0.44244384765625 +68097 -0.5753173828125 +68098 -0.65203857421875 +68099 -0.641632080078125 +68100 -0.562164306640625 +68101 -0.458038330078125 +68102 -0.350555419921875 +68103 -0.260528564453125 +68104 -0.192108154296875 +68105 -0.141937255859375 +68106 -0.1021728515625 +68107 -0.062896728515625 +68108 -0.011932373046875 +68109 0.062835693359375 +68110 0.148712158203125 +68111 0.241729736328125 +68112 0.34912109375 +68113 0.457305908203125 +68114 0.54388427734375 +68115 0.5728759765625 +68116 0.506591796875 +68117 0.351226806640625 +68118 0.146514892578125 +68119 -0.05523681640625 +68120 -0.21624755859375 +68121 -0.334930419921875 +68122 -0.402984619140625 +68123 -0.4412841796875 +68124 -0.49578857421875 +68125 -0.5601806640625 +68126 -0.600738525390625 +68127 -0.584228515625 +68128 -0.47930908203125 +68129 -0.27935791015625 +68130 -0.0089111328125 +68131 0.268798828125 +68132 0.482818603515625 +68133 0.60369873046875 +68134 0.650421142578125 +68135 0.66400146484375 +68136 0.6414794921875 +68137 0.572540283203125 +68138 0.498138427734375 +68139 0.439453125 +68140 0.375518798828125 +68141 0.274505615234375 +68142 0.1087646484375 +68143 -0.099395751953125 +68144 -0.3182373046875 +68145 -0.5489501953125 +68146 -0.7738037109375 +68147 -0.86383056640625 +68148 -0.870391845703125 +68149 -0.86895751953125 +68150 -0.861053466796875 +68151 -0.765869140625 +68152 -0.5301513671875 +68153 -0.214691162109375 +68154 0.137359619140625 +68155 0.474822998046875 +68156 0.76239013671875 +68157 0.867462158203125 +68158 0.870361328125 +68159 0.86480712890625 +68160 0.831817626953125 +68161 0.677581787109375 +68162 0.495880126953125 +68163 0.30767822265625 +68164 0.116180419921875 +68165 -0.110748291015625 +68166 -0.381805419921875 +68167 -0.6572265625 +68168 -0.857421875 +68169 -0.870391845703125 +68170 -0.870391845703125 +68171 -0.86444091796875 +68172 -0.85723876953125 +68173 -0.790008544921875 +68174 -0.62847900390625 +68175 -0.3956298828125 +68176 -0.126708984375 +68177 0.150115966796875 +68178 0.424041748046875 +68179 0.670623779296875 +68180 0.854522705078125 +68181 0.866485595703125 +68182 0.86920166015625 +68183 0.8653564453125 +68184 0.857147216796875 +68185 0.766845703125 +68186 0.628509521484375 +68187 0.462127685546875 +68188 0.297210693359375 +68189 0.14862060546875 +68190 -0.00537109375 +68191 -0.15753173828125 +68192 -0.31304931640625 +68193 -0.48876953125 +68194 -0.6416015625 +68195 -0.751373291015625 +68196 -0.84619140625 +68197 -0.861297607421875 +68198 -0.863250732421875 +68199 -0.856597900390625 +68200 -0.7498779296875 +68201 -0.624542236328125 +68202 -0.47808837890625 +68203 -0.253387451171875 +68204 0.003692626953125 +68205 0.2257080078125 +68206 0.427154541015625 +68207 0.643218994140625 +68208 0.855926513671875 +68209 0.870361328125 +68210 0.870361328125 +68211 0.862762451171875 +68212 0.79669189453125 +68213 0.595794677734375 +68214 0.362152099609375 +68215 0.1270751953125 +68216 -0.086944580078125 +68217 -0.2784423828125 +68218 -0.484832763671875 +68219 -0.729583740234375 +68220 -0.86688232421875 +68221 -0.870391845703125 +68222 -0.86859130859375 +68223 -0.86279296875 +68224 -0.817962646484375 +68225 -0.6116943359375 +68226 -0.3128662109375 +68227 0.039398193359375 +68228 0.422821044921875 +68229 0.805145263671875 +68230 0.870361328125 +68231 0.870361328125 +68232 0.860015869140625 +68233 0.727935791015625 +68234 0.48114013671875 +68235 0.2059326171875 +68236 -0.06103515625 +68237 -0.29913330078125 +68238 -0.516204833984375 +68239 -0.7252197265625 +68240 -0.85980224609375 +68241 -0.870391845703125 +68242 -0.870391845703125 +68243 -0.858062744140625 +68244 -0.673004150390625 +68245 -0.42694091796875 +68246 -0.2100830078125 +68247 -0.0362548828125 +68248 0.10943603515625 +68249 0.23516845703125 +68250 0.373687744140625 +68251 0.517791748046875 +68252 0.602783203125 +68253 0.635711669921875 +68254 0.655181884765625 +68255 0.65948486328125 +68256 0.651275634765625 +68257 0.61846923828125 +68258 0.53753662109375 +68259 0.404144287109375 +68260 0.22186279296875 +68261 0.003997802734375 +68262 -0.22100830078125 +68263 -0.42449951171875 +68264 -0.579833984375 +68265 -0.641876220703125 +68266 -0.6177978515625 +68267 -0.575531005859375 +68268 -0.526336669921875 +68269 -0.42645263671875 +68270 -0.2581787109375 +68271 -0.068695068359375 +68272 0.09222412109375 +68273 0.232147216796875 +68274 0.3509521484375 +68275 0.410064697265625 +68276 0.372955322265625 +68277 0.2554931640625 +68278 0.10711669921875 +68279 -0.052886962890625 +68280 -0.186279296875 +68281 -0.23291015625 +68282 -0.209442138671875 +68283 -0.174163818359375 +68284 -0.126739501953125 +68285 -0.048126220703125 +68286 0.0426025390625 +68287 0.10748291015625 +68288 0.1409912109375 +68289 0.19708251953125 +68290 0.273651123046875 +68291 0.31768798828125 +68292 0.341094970703125 +68293 0.368011474609375 +68294 0.37249755859375 +68295 0.30072021484375 +68296 0.1517333984375 +68297 -0.01470947265625 +68298 -0.1883544921875 +68299 -0.372711181640625 +68300 -0.51397705078125 +68301 -0.57177734375 +68302 -0.53948974609375 +68303 -0.43511962890625 +68304 -0.2962646484375 +68305 -0.161102294921875 +68306 -0.0435791015625 +68307 0.060394287109375 +68308 0.13665771484375 +68309 0.170135498046875 +68310 0.16552734375 +68311 0.15728759765625 +68312 0.150787353515625 +68313 0.12200927734375 +68314 0.080108642578125 +68315 0.05126953125 +68316 0.062896728515625 +68317 0.09271240234375 +68318 0.092987060546875 +68319 0.07855224609375 +68320 0.06427001953125 +68321 0.0347900390625 +68322 -0.01171875 +68323 -0.056060791015625 +68324 -0.055511474609375 +68325 -0.010467529296875 +68326 0.02508544921875 +68327 0.025665283203125 +68328 0.017333984375 +68329 0.00189208984375 +68330 -0.03173828125 +68331 -0.071502685546875 +68332 -0.13543701171875 +68333 -0.219970703125 +68334 -0.300506591796875 +68335 -0.376312255859375 +68336 -0.416107177734375 +68337 -0.371124267578125 +68338 -0.242279052734375 +68339 -0.069732666015625 +68340 0.125640869140625 +68341 0.31268310546875 +68342 0.45501708984375 +68343 0.554779052734375 +68344 0.61065673828125 +68345 0.610931396484375 +68346 0.531463623046875 +68347 0.3883056640625 +68348 0.23468017578125 +68349 0.095245361328125 +68350 -0.00396728515625 +68351 -0.04852294921875 +68352 -0.055145263671875 +68353 -0.0758056640625 +68354 -0.138702392578125 +68355 -0.209197998046875 +68356 -0.289031982421875 +68357 -0.37884521484375 +68358 -0.456329345703125 +68359 -0.51641845703125 +68360 -0.519287109375 +68361 -0.458251953125 +68362 -0.384796142578125 +68363 -0.323699951171875 +68364 -0.269287109375 +68365 -0.1951904296875 +68366 -0.100006103515625 +68367 -0.01055908203125 +68368 0.1033935546875 +68369 0.24908447265625 +68370 0.373199462890625 +68371 0.45806884765625 +68372 0.511474609375 +68373 0.565399169921875 +68374 0.61138916015625 +68375 0.5897216796875 +68376 0.4906005859375 +68377 0.33148193359375 +68378 0.147796630859375 +68379 -0.01873779296875 +68380 -0.140289306640625 +68381 -0.191986083984375 +68382 -0.184295654296875 +68383 -0.161834716796875 +68384 -0.166595458984375 +68385 -0.19390869140625 +68386 -0.22442626953125 +68387 -0.279754638671875 +68388 -0.3389892578125 +68389 -0.3543701171875 +68390 -0.348175048828125 +68391 -0.32598876953125 +68392 -0.2581787109375 +68393 -0.139801025390625 +68394 0.014617919921875 +68395 0.144378662109375 +68396 0.221038818359375 +68397 0.27069091796875 +68398 0.294036865234375 +68399 0.311767578125 +68400 0.339141845703125 +68401 0.360260009765625 +68402 0.360504150390625 +68403 0.308380126953125 +68404 0.18170166015625 +68405 0.0047607421875 +68406 -0.17559814453125 +68407 -0.3143310546875 +68408 -0.36785888671875 +68409 -0.36248779296875 +68410 -0.343536376953125 +68411 -0.3018798828125 +68412 -0.231414794921875 +68413 -0.117645263671875 +68414 0.007049560546875 +68415 0.087982177734375 +68416 0.13946533203125 +68417 0.17425537109375 +68418 0.188201904296875 +68419 0.171234130859375 +68420 0.118438720703125 +68421 0.05706787109375 +68422 -0.010711669921875 +68423 -0.0914306640625 +68424 -0.162322998046875 +68425 -0.194549560546875 +68426 -0.1492919921875 +68427 -0.02166748046875 +68428 0.124053955078125 +68429 0.211151123046875 +68430 0.240447998046875 +68431 0.242218017578125 +68432 0.2257080078125 +68433 0.194366455078125 +68434 0.115509033203125 +68435 0.0128173828125 +68436 -0.053802490234375 +68437 -0.110626220703125 +68438 -0.199493408203125 +68439 -0.29437255859375 +68440 -0.33221435546875 +68441 -0.27972412109375 +68442 -0.185333251953125 +68443 -0.128204345703125 +68444 -0.115692138671875 +68445 -0.116455078125 +68446 -0.105926513671875 +68447 -0.053955078125 +68448 0.048797607421875 +68449 0.157318115234375 +68450 0.212005615234375 +68451 0.218475341796875 +68452 0.23724365234375 +68453 0.30535888671875 +68454 0.38128662109375 +68455 0.404449462890625 +68456 0.3944091796875 +68457 0.3885498046875 +68458 0.362640380859375 +68459 0.27362060546875 +68460 0.11712646484375 +68461 -0.054901123046875 +68462 -0.19085693359375 +68463 -0.28570556640625 +68464 -0.339263916015625 +68465 -0.3775634765625 +68466 -0.445709228515625 +68467 -0.535064697265625 +68468 -0.629058837890625 +68469 -0.697601318359375 +68470 -0.70391845703125 +68471 -0.6424560546875 +68472 -0.491241455078125 +68473 -0.265716552734375 +68474 -0.023712158203125 +68475 0.201751708984375 +68476 0.375823974609375 +68477 0.485076904296875 +68478 0.56884765625 +68479 0.634765625 +68480 0.63763427734375 +68481 0.5660400390625 +68482 0.4720458984375 +68483 0.40692138671875 +68484 0.3778076171875 +68485 0.376953125 +68486 0.371978759765625 +68487 0.313140869140625 +68488 0.184417724609375 +68489 0.011199951171875 +68490 -0.171051025390625 +68491 -0.33740234375 +68492 -0.47198486328125 +68493 -0.560394287109375 +68494 -0.58056640625 +68495 -0.54754638671875 +68496 -0.508575439453125 +68497 -0.459503173828125 +68498 -0.394378662109375 +68499 -0.35260009765625 +68500 -0.31170654296875 +68501 -0.197418212890625 +68502 -0.007965087890625 +68503 0.207489013671875 +68504 0.409210205078125 +68505 0.57208251953125 +68506 0.66595458984375 +68507 0.65875244140625 +68508 0.56744384765625 +68509 0.431396484375 +68510 0.29443359375 +68511 0.182464599609375 +68512 0.06365966796875 +68513 -0.075958251953125 +68514 -0.189422607421875 +68515 -0.271942138671875 +68516 -0.342529296875 +68517 -0.364166259765625 +68518 -0.327239990234375 +68519 -0.2769775390625 +68520 -0.253692626953125 +68521 -0.24365234375 +68522 -0.1983642578125 +68523 -0.116241455078125 +68524 -0.036834716796875 +68525 0.034881591796875 +68526 0.09124755859375 +68527 0.10888671875 +68528 0.125518798828125 +68529 0.15771484375 +68530 0.17828369140625 +68531 0.17108154296875 +68532 0.129974365234375 +68533 0.082427978515625 +68534 0.027679443359375 +68535 -0.065643310546875 +68536 -0.15936279296875 +68537 -0.21307373046875 +68538 -0.234649658203125 +68539 -0.2001953125 +68540 -0.119171142578125 +68541 -0.024749755859375 +68542 0.085784912109375 +68543 0.178131103515625 +68544 0.215576171875 +68545 0.211456298828125 +68546 0.17523193359375 +68547 0.128753662109375 +68548 0.1019287109375 +68549 0.0743408203125 +68550 0.04327392578125 +68551 0.038177490234375 +68552 0.076263427734375 +68553 0.14105224609375 +68554 0.186431884765625 +68555 0.188812255859375 +68556 0.1390380859375 +68557 0.041778564453125 +68558 -0.079437255859375 +68559 -0.219390869140625 +68560 -0.367828369140625 +68561 -0.494873046875 +68562 -0.556243896484375 +68563 -0.508697509765625 +68564 -0.3756103515625 +68565 -0.218902587890625 +68566 -0.063751220703125 +68567 0.091552734375 +68568 0.23602294921875 +68569 0.342987060546875 +68570 0.39520263671875 +68571 0.389373779296875 +68572 0.324249267578125 +68573 0.224090576171875 +68574 0.124267578125 +68575 0.037078857421875 +68576 -0.010101318359375 +68577 -0.019439697265625 +68578 -0.022796630859375 +68579 -0.001556396484375 +68580 0.056304931640625 +68581 0.106719970703125 +68582 0.096893310546875 +68583 0.042694091796875 +68584 -0.018035888671875 +68585 -0.07586669921875 +68586 -0.11944580078125 +68587 -0.15972900390625 +68588 -0.202606201171875 +68589 -0.24859619140625 +68590 -0.30517578125 +68591 -0.36212158203125 +68592 -0.39141845703125 +68593 -0.35528564453125 +68594 -0.249969482421875 +68595 -0.092864990234375 +68596 0.08905029296875 +68597 0.2352294921875 +68598 0.318817138671875 +68599 0.358642578125 +68600 0.347747802734375 +68601 0.28564453125 +68602 0.223175048828125 +68603 0.196746826171875 +68604 0.179840087890625 +68605 0.155548095703125 +68606 0.151214599609375 +68607 0.156951904296875 +68608 0.13177490234375 +68609 0.100799560546875 +68610 0.087127685546875 +68611 0.05487060546875 +68612 -0.009002685546875 +68613 -0.10400390625 +68614 -0.229400634765625 +68615 -0.35552978515625 +68616 -0.441925048828125 +68617 -0.473846435546875 +68618 -0.464813232421875 +68619 -0.419097900390625 +68620 -0.334320068359375 +68621 -0.227935791015625 +68622 -0.12347412109375 +68623 -0.02764892578125 +68624 0.077667236328125 +68625 0.2132568359375 +68626 0.38885498046875 +68627 0.582794189453125 +68628 0.734039306640625 +68629 0.800140380859375 +68630 0.7783203125 +68631 0.6651611328125 +68632 0.45965576171875 +68633 0.199188232421875 +68634 -0.050689697265625 +68635 -0.23297119140625 +68636 -0.33013916015625 +68637 -0.368408203125 +68638 -0.378936767578125 +68639 -0.376983642578125 +68640 -0.37969970703125 +68641 -0.391510009765625 +68642 -0.385345458984375 +68643 -0.3419189453125 +68644 -0.28289794921875 +68645 -0.251617431640625 +68646 -0.266143798828125 +68647 -0.273345947265625 +68648 -0.216796875 +68649 -0.128265380859375 +68650 -0.068145751953125 +68651 -0.0430908203125 +68652 -0.024444580078125 +68653 0.020721435546875 +68654 0.124481201171875 +68655 0.25787353515625 +68656 0.379119873046875 +68657 0.47991943359375 +68658 0.5281982421875 +68659 0.511138916015625 +68660 0.456207275390625 +68661 0.407470703125 +68662 0.383758544921875 +68663 0.35687255859375 +68664 0.31182861328125 +68665 0.250885009765625 +68666 0.1654052734375 +68667 0.035247802734375 +68668 -0.142059326171875 +68669 -0.33563232421875 +68670 -0.5345458984375 +68671 -0.72186279296875 +68672 -0.836669921875 +68673 -0.8326416015625 +68674 -0.7296142578125 +68675 -0.582550048828125 +68676 -0.440093994140625 +68677 -0.324310302734375 +68678 -0.20147705078125 +68679 -0.044647216796875 +68680 0.103973388671875 +68681 0.202392578125 +68682 0.264495849609375 +68683 0.338897705078125 +68684 0.443817138671875 +68685 0.545074462890625 +68686 0.6173095703125 +68687 0.6524658203125 +68688 0.66339111328125 +68689 0.6561279296875 +68690 0.606781005859375 +68691 0.501190185546875 +68692 0.352783203125 +68693 0.176544189453125 +68694 -0.034820556640625 +68695 -0.258209228515625 +68696 -0.44244384765625 +68697 -0.5753173828125 +68698 -0.65203857421875 +68699 -0.641632080078125 +68700 -0.562164306640625 +68701 -0.458038330078125 +68702 -0.350555419921875 +68703 -0.260528564453125 +68704 -0.192108154296875 +68705 -0.141937255859375 +68706 -0.1021728515625 +68707 -0.062896728515625 +68708 -0.011932373046875 +68709 0.062835693359375 +68710 0.148712158203125 +68711 0.241729736328125 +68712 0.34912109375 +68713 0.457305908203125 +68714 0.54388427734375 +68715 0.5728759765625 +68716 0.506591796875 +68717 0.351226806640625 +68718 0.146514892578125 +68719 -0.05523681640625 +68720 -0.21624755859375 +68721 -0.334930419921875 +68722 -0.402984619140625 +68723 -0.4412841796875 +68724 -0.49578857421875 +68725 -0.5601806640625 +68726 -0.600738525390625 +68727 -0.584228515625 +68728 -0.47930908203125 +68729 -0.27935791015625 +68730 -0.0089111328125 +68731 0.268798828125 +68732 0.482818603515625 +68733 0.60369873046875 +68734 0.650421142578125 +68735 0.66400146484375 +68736 0.6414794921875 +68737 0.572540283203125 +68738 0.498138427734375 +68739 0.439453125 +68740 0.375518798828125 +68741 0.274505615234375 +68742 0.1087646484375 +68743 -0.099395751953125 +68744 -0.3182373046875 +68745 -0.5489501953125 +68746 -0.7738037109375 +68747 -0.86383056640625 +68748 -0.870391845703125 +68749 -0.86895751953125 +68750 -0.861053466796875 +68751 -0.765869140625 +68752 -0.5301513671875 +68753 -0.214691162109375 +68754 0.137359619140625 +68755 0.474822998046875 +68756 0.76239013671875 +68757 0.867462158203125 +68758 0.870361328125 +68759 0.86480712890625 +68760 0.831817626953125 +68761 0.677581787109375 +68762 0.495880126953125 +68763 0.30767822265625 +68764 0.116180419921875 +68765 -0.110748291015625 +68766 -0.381805419921875 +68767 -0.6572265625 +68768 -0.857421875 +68769 -0.870391845703125 +68770 -0.870391845703125 +68771 -0.86444091796875 +68772 -0.85723876953125 +68773 -0.790008544921875 +68774 -0.62847900390625 +68775 -0.3956298828125 +68776 -0.126708984375 +68777 0.150115966796875 +68778 0.424041748046875 +68779 0.670623779296875 +68780 0.854522705078125 +68781 0.866485595703125 +68782 0.86920166015625 +68783 0.8653564453125 +68784 0.857147216796875 +68785 0.766845703125 +68786 0.628509521484375 +68787 0.462127685546875 +68788 0.297210693359375 +68789 0.14862060546875 +68790 -0.00537109375 +68791 -0.15753173828125 +68792 -0.31304931640625 +68793 -0.48876953125 +68794 -0.6416015625 +68795 -0.751373291015625 +68796 -0.84619140625 +68797 -0.861297607421875 +68798 -0.863250732421875 +68799 -0.856597900390625 +68800 -0.7498779296875 +68801 -0.624542236328125 +68802 -0.47808837890625 +68803 -0.253387451171875 +68804 0.003692626953125 +68805 0.2257080078125 +68806 0.427154541015625 +68807 0.643218994140625 +68808 0.855926513671875 +68809 0.870361328125 +68810 0.870361328125 +68811 0.862762451171875 +68812 0.79669189453125 +68813 0.595794677734375 +68814 0.362152099609375 +68815 0.1270751953125 +68816 -0.086944580078125 +68817 -0.2784423828125 +68818 -0.484832763671875 +68819 -0.729583740234375 +68820 -0.86688232421875 +68821 -0.870391845703125 +68822 -0.86859130859375 +68823 -0.86279296875 +68824 -0.817962646484375 +68825 -0.6116943359375 +68826 -0.3128662109375 +68827 0.039398193359375 +68828 0.422821044921875 +68829 0.805145263671875 +68830 0.870361328125 +68831 0.870361328125 +68832 0.860015869140625 +68833 0.727935791015625 +68834 0.48114013671875 +68835 0.2059326171875 +68836 -0.06103515625 +68837 -0.29913330078125 +68838 -0.516204833984375 +68839 -0.7252197265625 +68840 -0.85980224609375 +68841 -0.870391845703125 +68842 -0.870391845703125 +68843 -0.858062744140625 +68844 -0.673004150390625 +68845 -0.42694091796875 +68846 -0.2100830078125 +68847 -0.0362548828125 +68848 0.10943603515625 +68849 0.23516845703125 +68850 0.373687744140625 +68851 0.517791748046875 +68852 0.602783203125 +68853 0.635711669921875 +68854 0.655181884765625 +68855 0.65948486328125 +68856 0.651275634765625 +68857 0.61846923828125 +68858 0.53753662109375 +68859 0.404144287109375 +68860 0.22186279296875 +68861 0.003997802734375 +68862 -0.22100830078125 +68863 -0.42449951171875 +68864 -0.579833984375 +68865 -0.641876220703125 +68866 -0.6177978515625 +68867 -0.575531005859375 +68868 -0.526336669921875 +68869 -0.42645263671875 +68870 -0.2581787109375 +68871 -0.068695068359375 +68872 0.09222412109375 +68873 0.232147216796875 +68874 0.3509521484375 +68875 0.410064697265625 +68876 0.372955322265625 +68877 0.2554931640625 +68878 0.10711669921875 +68879 -0.052886962890625 +68880 -0.186279296875 +68881 -0.23291015625 +68882 -0.209442138671875 +68883 -0.174163818359375 +68884 -0.126739501953125 +68885 -0.048126220703125 +68886 0.0426025390625 +68887 0.10748291015625 +68888 0.1409912109375 +68889 0.19708251953125 +68890 0.273651123046875 +68891 0.31768798828125 +68892 0.341094970703125 +68893 0.368011474609375 +68894 0.37249755859375 +68895 0.30072021484375 +68896 0.1517333984375 +68897 -0.01470947265625 +68898 -0.1883544921875 +68899 -0.372711181640625 +68900 -0.51397705078125 +68901 -0.57177734375 +68902 -0.53948974609375 +68903 -0.43511962890625 +68904 -0.2962646484375 +68905 -0.161102294921875 +68906 -0.0435791015625 +68907 0.060394287109375 +68908 0.13665771484375 +68909 0.170135498046875 +68910 0.16552734375 +68911 0.15728759765625 +68912 0.150787353515625 +68913 0.12200927734375 +68914 0.080108642578125 +68915 0.05126953125 +68916 0.062896728515625 +68917 0.09271240234375 +68918 0.092987060546875 +68919 0.07855224609375 +68920 0.06427001953125 +68921 0.0347900390625 +68922 -0.01171875 +68923 -0.056060791015625 +68924 -0.055511474609375 +68925 -0.010467529296875 +68926 0.02508544921875 +68927 0.025665283203125 +68928 0.017333984375 +68929 0.00189208984375 +68930 -0.03173828125 +68931 -0.071502685546875 +68932 -0.13543701171875 +68933 -0.219970703125 +68934 -0.300506591796875 +68935 -0.376312255859375 +68936 -0.416107177734375 +68937 -0.371124267578125 +68938 -0.242279052734375 +68939 -0.069732666015625 +68940 0.125640869140625 +68941 0.31268310546875 +68942 0.45501708984375 +68943 0.554779052734375 +68944 0.61065673828125 +68945 0.610931396484375 +68946 0.531463623046875 +68947 0.3883056640625 +68948 0.23468017578125 +68949 0.095245361328125 +68950 -0.00396728515625 +68951 -0.04852294921875 +68952 -0.055145263671875 +68953 -0.0758056640625 +68954 -0.138702392578125 +68955 -0.209197998046875 +68956 -0.289031982421875 +68957 -0.37884521484375 +68958 -0.456329345703125 +68959 -0.51641845703125 +68960 -0.519287109375 +68961 -0.458251953125 +68962 -0.384796142578125 +68963 -0.323699951171875 +68964 -0.269287109375 +68965 -0.1951904296875 +68966 -0.100006103515625 +68967 -0.01055908203125 +68968 0.1033935546875 +68969 0.24908447265625 +68970 0.373199462890625 +68971 0.45806884765625 +68972 0.511474609375 +68973 0.565399169921875 +68974 0.61138916015625 +68975 0.5897216796875 +68976 0.4906005859375 +68977 0.33148193359375 +68978 0.147796630859375 +68979 -0.01873779296875 +68980 -0.140289306640625 +68981 -0.191986083984375 +68982 -0.184295654296875 +68983 -0.161834716796875 +68984 -0.166595458984375 +68985 -0.19390869140625 +68986 -0.22442626953125 +68987 -0.279754638671875 +68988 -0.3389892578125 +68989 -0.3543701171875 +68990 -0.348175048828125 +68991 -0.32598876953125 +68992 -0.2581787109375 +68993 -0.139801025390625 +68994 0.014617919921875 +68995 0.144378662109375 +68996 0.221038818359375 +68997 0.27069091796875 +68998 0.294036865234375 +68999 0.311767578125 +69000 0.339141845703125 +69001 0.360260009765625 +69002 0.360504150390625 +69003 0.308380126953125 +69004 0.18170166015625 +69005 0.0047607421875 +69006 -0.17559814453125 +69007 -0.3143310546875 +69008 -0.36785888671875 +69009 -0.36248779296875 +69010 -0.343536376953125 +69011 -0.3018798828125 +69012 -0.231414794921875 +69013 -0.117645263671875 +69014 0.007049560546875 +69015 0.087982177734375 +69016 0.13946533203125 +69017 0.17425537109375 +69018 0.188201904296875 +69019 0.171234130859375 +69020 0.118438720703125 +69021 0.05706787109375 +69022 -0.010711669921875 +69023 -0.0914306640625 +69024 -0.162322998046875 +69025 -0.194549560546875 +69026 -0.1492919921875 +69027 -0.02166748046875 +69028 0.124053955078125 +69029 0.211151123046875 +69030 0.240447998046875 +69031 0.242218017578125 +69032 0.2257080078125 +69033 0.194366455078125 +69034 0.115509033203125 +69035 0.0128173828125 +69036 -0.053802490234375 +69037 -0.110626220703125 +69038 -0.199493408203125 +69039 -0.29437255859375 +69040 -0.33221435546875 +69041 -0.27972412109375 +69042 -0.185333251953125 +69043 -0.128204345703125 +69044 -0.115692138671875 +69045 -0.116455078125 +69046 -0.105926513671875 +69047 -0.053955078125 +69048 0.048797607421875 +69049 0.157318115234375 +69050 0.212005615234375 +69051 0.218475341796875 +69052 0.23724365234375 +69053 0.30535888671875 +69054 0.38128662109375 +69055 0.404449462890625 +69056 0.3944091796875 +69057 0.3885498046875 +69058 0.362640380859375 +69059 0.27362060546875 +69060 0.11712646484375 +69061 -0.054901123046875 +69062 -0.19085693359375 +69063 -0.28570556640625 +69064 -0.339263916015625 +69065 -0.3775634765625 +69066 -0.445709228515625 +69067 -0.535064697265625 +69068 -0.629058837890625 +69069 -0.697601318359375 +69070 -0.70391845703125 +69071 -0.6424560546875 +69072 -0.491241455078125 +69073 -0.265716552734375 +69074 -0.023712158203125 +69075 0.201751708984375 +69076 0.375823974609375 +69077 0.485076904296875 +69078 0.56884765625 +69079 0.634765625 +69080 0.63763427734375 +69081 0.5660400390625 +69082 0.4720458984375 +69083 0.40692138671875 +69084 0.3778076171875 +69085 0.376953125 +69086 0.371978759765625 +69087 0.313140869140625 +69088 0.184417724609375 +69089 0.011199951171875 +69090 -0.171051025390625 +69091 -0.33740234375 +69092 -0.47198486328125 +69093 -0.560394287109375 +69094 -0.58056640625 +69095 -0.54754638671875 +69096 -0.508575439453125 +69097 -0.459503173828125 +69098 -0.394378662109375 +69099 -0.35260009765625 +69100 -0.31170654296875 +69101 -0.197418212890625 +69102 -0.007965087890625 +69103 0.207489013671875 +69104 0.409210205078125 +69105 0.57208251953125 +69106 0.66595458984375 +69107 0.65875244140625 +69108 0.56744384765625 +69109 0.431396484375 +69110 0.29443359375 +69111 0.182464599609375 +69112 0.06365966796875 +69113 -0.075958251953125 +69114 -0.189422607421875 +69115 -0.271942138671875 +69116 -0.342529296875 +69117 -0.364166259765625 +69118 -0.327239990234375 +69119 -0.2769775390625 +69120 -0.253692626953125 +69121 -0.24365234375 +69122 -0.1983642578125 +69123 -0.116241455078125 +69124 -0.036834716796875 +69125 0.034881591796875 +69126 0.09124755859375 +69127 0.10888671875 +69128 0.125518798828125 +69129 0.15771484375 +69130 0.17828369140625 +69131 0.17108154296875 +69132 0.129974365234375 +69133 0.082427978515625 +69134 0.027679443359375 +69135 -0.065643310546875 +69136 -0.15936279296875 +69137 -0.21307373046875 +69138 -0.234649658203125 +69139 -0.2001953125 +69140 -0.119171142578125 +69141 -0.024749755859375 +69142 0.085784912109375 +69143 0.178131103515625 +69144 0.215576171875 +69145 0.211456298828125 +69146 0.17523193359375 +69147 0.128753662109375 +69148 0.1019287109375 +69149 0.0743408203125 +69150 0.04327392578125 +69151 0.038177490234375 +69152 0.076263427734375 +69153 0.14105224609375 +69154 0.186431884765625 +69155 0.188812255859375 +69156 0.1390380859375 +69157 0.041778564453125 +69158 -0.079437255859375 +69159 -0.219390869140625 +69160 -0.367828369140625 +69161 -0.494873046875 +69162 -0.556243896484375 +69163 -0.508697509765625 +69164 -0.3756103515625 +69165 -0.218902587890625 +69166 -0.063751220703125 +69167 0.091552734375 +69168 0.23602294921875 +69169 0.342987060546875 +69170 0.39520263671875 +69171 0.389373779296875 +69172 0.324249267578125 +69173 0.224090576171875 +69174 0.124267578125 +69175 0.037078857421875 +69176 -0.010101318359375 +69177 -0.019439697265625 +69178 -0.022796630859375 +69179 -0.001556396484375 +69180 0.056304931640625 +69181 0.106719970703125 +69182 0.096893310546875 +69183 0.042694091796875 +69184 -0.018035888671875 +69185 -0.07586669921875 +69186 -0.11944580078125 +69187 -0.15972900390625 +69188 -0.202606201171875 +69189 -0.24859619140625 +69190 -0.30517578125 +69191 -0.36212158203125 +69192 -0.39141845703125 +69193 -0.35528564453125 +69194 -0.249969482421875 +69195 -0.092864990234375 +69196 0.08905029296875 +69197 0.2352294921875 +69198 0.318817138671875 +69199 0.358642578125 +69200 0.347747802734375 +69201 0.28564453125 +69202 0.223175048828125 +69203 0.196746826171875 +69204 0.179840087890625 +69205 0.155548095703125 +69206 0.151214599609375 +69207 0.156951904296875 +69208 0.13177490234375 +69209 0.100799560546875 +69210 0.087127685546875 +69211 0.05487060546875 +69212 -0.009002685546875 +69213 -0.10400390625 +69214 -0.229400634765625 +69215 -0.35552978515625 +69216 -0.441925048828125 +69217 -0.473846435546875 +69218 -0.464813232421875 +69219 -0.419097900390625 +69220 -0.334320068359375 +69221 -0.227935791015625 +69222 -0.12347412109375 +69223 -0.02764892578125 +69224 0.077667236328125 +69225 0.2132568359375 +69226 0.38885498046875 +69227 0.582794189453125 +69228 0.734039306640625 +69229 0.800140380859375 +69230 0.7783203125 +69231 0.6651611328125 +69232 0.45965576171875 +69233 0.199188232421875 +69234 -0.050689697265625 +69235 -0.23297119140625 +69236 -0.33013916015625 +69237 -0.368408203125 +69238 -0.378936767578125 +69239 -0.376983642578125 +69240 -0.37969970703125 +69241 -0.391510009765625 +69242 -0.385345458984375 +69243 -0.3419189453125 +69244 -0.28289794921875 +69245 -0.251617431640625 +69246 -0.266143798828125 +69247 -0.273345947265625 +69248 -0.216796875 +69249 -0.128265380859375 +69250 -0.068145751953125 +69251 -0.0430908203125 +69252 -0.024444580078125 +69253 0.020721435546875 +69254 0.124481201171875 +69255 0.25787353515625 +69256 0.379119873046875 +69257 0.47991943359375 +69258 0.5281982421875 +69259 0.511138916015625 +69260 0.456207275390625 +69261 0.407470703125 +69262 0.383758544921875 +69263 0.35687255859375 +69264 0.31182861328125 +69265 0.250885009765625 +69266 0.1654052734375 +69267 0.035247802734375 +69268 -0.142059326171875 +69269 -0.33563232421875 +69270 -0.5345458984375 +69271 -0.72186279296875 +69272 -0.836669921875 +69273 -0.8326416015625 +69274 -0.7296142578125 +69275 -0.582550048828125 +69276 -0.440093994140625 +69277 -0.324310302734375 +69278 -0.20147705078125 +69279 -0.044647216796875 +69280 0.103973388671875 +69281 0.202392578125 +69282 0.264495849609375 +69283 0.338897705078125 +69284 0.443817138671875 +69285 0.545074462890625 +69286 0.6173095703125 +69287 0.6524658203125 +69288 0.66339111328125 +69289 0.6561279296875 +69290 0.606781005859375 +69291 0.501190185546875 +69292 0.352783203125 +69293 0.176544189453125 +69294 -0.034820556640625 +69295 -0.258209228515625 +69296 -0.44244384765625 +69297 -0.5753173828125 +69298 -0.65203857421875 +69299 -0.641632080078125 +69300 -0.562164306640625 +69301 -0.458038330078125 +69302 -0.350555419921875 +69303 -0.260528564453125 +69304 -0.192108154296875 +69305 -0.141937255859375 +69306 -0.1021728515625 +69307 -0.062896728515625 +69308 -0.011932373046875 +69309 0.062835693359375 +69310 0.148712158203125 +69311 0.241729736328125 +69312 0.34912109375 +69313 0.457305908203125 +69314 0.54388427734375 +69315 0.5728759765625 +69316 0.506591796875 +69317 0.351226806640625 +69318 0.146514892578125 +69319 -0.05523681640625 +69320 -0.21624755859375 +69321 -0.334930419921875 +69322 -0.402984619140625 +69323 -0.4412841796875 +69324 -0.49578857421875 +69325 -0.5601806640625 +69326 -0.600738525390625 +69327 -0.584228515625 +69328 -0.47930908203125 +69329 -0.27935791015625 +69330 -0.0089111328125 +69331 0.268798828125 +69332 0.482818603515625 +69333 0.60369873046875 +69334 0.650421142578125 +69335 0.66400146484375 +69336 0.6414794921875 +69337 0.572540283203125 +69338 0.498138427734375 +69339 0.439453125 +69340 0.375518798828125 +69341 0.274505615234375 +69342 0.1087646484375 +69343 -0.099395751953125 +69344 -0.3182373046875 +69345 -0.5489501953125 +69346 -0.7738037109375 +69347 -0.86383056640625 +69348 -0.870391845703125 +69349 -0.86895751953125 +69350 -0.861053466796875 +69351 -0.765869140625 +69352 -0.5301513671875 +69353 -0.214691162109375 +69354 0.137359619140625 +69355 0.474822998046875 +69356 0.76239013671875 +69357 0.867462158203125 +69358 0.870361328125 +69359 0.86480712890625 +69360 0.831817626953125 +69361 0.677581787109375 +69362 0.495880126953125 +69363 0.30767822265625 +69364 0.116180419921875 +69365 -0.110748291015625 +69366 -0.381805419921875 +69367 -0.6572265625 +69368 -0.857421875 +69369 -0.870391845703125 +69370 -0.870391845703125 +69371 -0.86444091796875 +69372 -0.85723876953125 +69373 -0.790008544921875 +69374 -0.62847900390625 +69375 -0.3956298828125 +69376 -0.126708984375 +69377 0.150115966796875 +69378 0.424041748046875 +69379 0.670623779296875 +69380 0.854522705078125 +69381 0.866485595703125 +69382 0.86920166015625 +69383 0.8653564453125 +69384 0.857147216796875 +69385 0.766845703125 +69386 0.628509521484375 +69387 0.462127685546875 +69388 0.297210693359375 +69389 0.14862060546875 +69390 -0.00537109375 +69391 -0.15753173828125 +69392 -0.31304931640625 +69393 -0.48876953125 +69394 -0.6416015625 +69395 -0.751373291015625 +69396 -0.84619140625 +69397 -0.861297607421875 +69398 -0.863250732421875 +69399 -0.856597900390625 +69400 -0.7498779296875 +69401 -0.624542236328125 +69402 -0.47808837890625 +69403 -0.253387451171875 +69404 0.003692626953125 +69405 0.2257080078125 +69406 0.427154541015625 +69407 0.643218994140625 +69408 0.855926513671875 +69409 0.870361328125 +69410 0.870361328125 +69411 0.862762451171875 +69412 0.79669189453125 +69413 0.595794677734375 +69414 0.362152099609375 +69415 0.1270751953125 +69416 -0.086944580078125 +69417 -0.2784423828125 +69418 -0.484832763671875 +69419 -0.729583740234375 +69420 -0.86688232421875 +69421 -0.870391845703125 +69422 -0.86859130859375 +69423 -0.86279296875 +69424 -0.817962646484375 +69425 -0.6116943359375 +69426 -0.3128662109375 +69427 0.039398193359375 +69428 0.422821044921875 +69429 0.805145263671875 +69430 0.870361328125 +69431 0.870361328125 +69432 0.860015869140625 +69433 0.727935791015625 +69434 0.48114013671875 +69435 0.2059326171875 +69436 -0.06103515625 +69437 -0.29913330078125 +69438 -0.516204833984375 +69439 -0.7252197265625 +69440 -0.85980224609375 +69441 -0.870391845703125 +69442 -0.870391845703125 +69443 -0.858062744140625 +69444 -0.673004150390625 +69445 -0.42694091796875 +69446 -0.2100830078125 +69447 -0.0362548828125 +69448 0.10943603515625 +69449 0.23516845703125 +69450 0.373687744140625 +69451 0.517791748046875 +69452 0.602783203125 +69453 0.635711669921875 +69454 0.655181884765625 +69455 0.65948486328125 +69456 0.651275634765625 +69457 0.61846923828125 +69458 0.53753662109375 +69459 0.404144287109375 +69460 0.22186279296875 +69461 0.003997802734375 +69462 -0.22100830078125 +69463 -0.42449951171875 +69464 -0.579833984375 +69465 -0.641876220703125 +69466 -0.6177978515625 +69467 -0.575531005859375 +69468 -0.526336669921875 +69469 -0.42645263671875 +69470 -0.2581787109375 +69471 -0.068695068359375 +69472 0.09222412109375 +69473 0.232147216796875 +69474 0.3509521484375 +69475 0.410064697265625 +69476 0.372955322265625 +69477 0.2554931640625 +69478 0.10711669921875 +69479 -0.052886962890625 +69480 -0.186279296875 +69481 -0.23291015625 +69482 -0.209442138671875 +69483 -0.174163818359375 +69484 -0.126739501953125 +69485 -0.048126220703125 +69486 0.0426025390625 +69487 0.10748291015625 +69488 0.1409912109375 +69489 0.19708251953125 +69490 0.273651123046875 +69491 0.31768798828125 +69492 0.341094970703125 +69493 0.368011474609375 +69494 0.37249755859375 +69495 0.30072021484375 +69496 0.1517333984375 +69497 -0.01470947265625 +69498 -0.1883544921875 +69499 -0.372711181640625 +69500 -0.51397705078125 +69501 -0.57177734375 +69502 -0.53948974609375 +69503 -0.43511962890625 +69504 -0.2962646484375 +69505 -0.161102294921875 +69506 -0.0435791015625 +69507 0.060394287109375 +69508 0.13665771484375 +69509 0.170135498046875 +69510 0.16552734375 +69511 0.15728759765625 +69512 0.150787353515625 +69513 0.12200927734375 +69514 0.080108642578125 +69515 0.05126953125 +69516 0.062896728515625 +69517 0.09271240234375 +69518 0.092987060546875 +69519 0.07855224609375 +69520 0.06427001953125 +69521 0.0347900390625 +69522 -0.01171875 +69523 -0.056060791015625 +69524 -0.055511474609375 +69525 -0.010467529296875 +69526 0.02508544921875 +69527 0.025665283203125 +69528 0.017333984375 +69529 0.00189208984375 +69530 -0.03173828125 +69531 -0.071502685546875 +69532 -0.13543701171875 +69533 -0.219970703125 +69534 -0.300506591796875 +69535 -0.376312255859375 +69536 -0.416107177734375 +69537 -0.371124267578125 +69538 -0.242279052734375 +69539 -0.069732666015625 +69540 0.125640869140625 +69541 0.31268310546875 +69542 0.45501708984375 +69543 0.554779052734375 +69544 0.61065673828125 +69545 0.610931396484375 +69546 0.531463623046875 +69547 0.3883056640625 +69548 0.23468017578125 +69549 0.095245361328125 +69550 -0.00396728515625 +69551 -0.04852294921875 +69552 -0.055145263671875 +69553 -0.0758056640625 +69554 -0.138702392578125 +69555 -0.209197998046875 +69556 -0.289031982421875 +69557 -0.37884521484375 +69558 -0.456329345703125 +69559 -0.51641845703125 +69560 -0.519287109375 +69561 -0.458251953125 +69562 -0.384796142578125 +69563 -0.323699951171875 +69564 -0.269287109375 +69565 -0.1951904296875 +69566 -0.100006103515625 +69567 -0.01055908203125 +69568 0.1033935546875 +69569 0.24908447265625 +69570 0.373199462890625 +69571 0.45806884765625 +69572 0.511474609375 +69573 0.565399169921875 +69574 0.61138916015625 +69575 0.5897216796875 +69576 0.4906005859375 +69577 0.33148193359375 +69578 0.147796630859375 +69579 -0.01873779296875 +69580 -0.140289306640625 +69581 -0.191986083984375 +69582 -0.184295654296875 +69583 -0.161834716796875 +69584 -0.166595458984375 +69585 -0.19390869140625 +69586 -0.22442626953125 +69587 -0.279754638671875 +69588 -0.3389892578125 +69589 -0.3543701171875 +69590 -0.348175048828125 +69591 -0.32598876953125 +69592 -0.2581787109375 +69593 -0.139801025390625 +69594 0.014617919921875 +69595 0.144378662109375 +69596 0.221038818359375 +69597 0.27069091796875 +69598 0.294036865234375 +69599 0.311767578125 +69600 0.339141845703125 +69601 0.360260009765625 +69602 0.360504150390625 +69603 0.308380126953125 +69604 0.18170166015625 +69605 0.0047607421875 +69606 -0.17559814453125 +69607 -0.3143310546875 +69608 -0.36785888671875 +69609 -0.36248779296875 +69610 -0.343536376953125 +69611 -0.3018798828125 +69612 -0.231414794921875 +69613 -0.117645263671875 +69614 0.007049560546875 +69615 0.087982177734375 +69616 0.13946533203125 +69617 0.17425537109375 +69618 0.188201904296875 +69619 0.171234130859375 +69620 0.118438720703125 +69621 0.05706787109375 +69622 -0.010711669921875 +69623 -0.0914306640625 +69624 -0.162322998046875 +69625 -0.194549560546875 +69626 -0.1492919921875 +69627 -0.02166748046875 +69628 0.124053955078125 +69629 0.211151123046875 +69630 0.240447998046875 +69631 0.242218017578125 +69632 0.2257080078125 +69633 0.194366455078125 +69634 0.115509033203125 +69635 0.0128173828125 +69636 -0.053802490234375 +69637 -0.110626220703125 +69638 -0.199493408203125 +69639 -0.29437255859375 +69640 -0.33221435546875 +69641 -0.27972412109375 +69642 -0.185333251953125 +69643 -0.128204345703125 +69644 -0.115692138671875 +69645 -0.116455078125 +69646 -0.105926513671875 +69647 -0.053955078125 +69648 0.048797607421875 +69649 0.157318115234375 +69650 0.212005615234375 +69651 0.218475341796875 +69652 0.23724365234375 +69653 0.30535888671875 +69654 0.38128662109375 +69655 0.404449462890625 +69656 0.3944091796875 +69657 0.3885498046875 +69658 0.362640380859375 +69659 0.27362060546875 +69660 0.11712646484375 +69661 -0.054901123046875 +69662 -0.19085693359375 +69663 -0.28570556640625 +69664 -0.339263916015625 +69665 -0.3775634765625 +69666 -0.445709228515625 +69667 -0.535064697265625 +69668 -0.629058837890625 +69669 -0.697601318359375 +69670 -0.70391845703125 +69671 -0.6424560546875 +69672 -0.491241455078125 +69673 -0.265716552734375 +69674 -0.023712158203125 +69675 0.201751708984375 +69676 0.375823974609375 +69677 0.485076904296875 +69678 0.56884765625 +69679 0.634765625 +69680 0.63763427734375 +69681 0.5660400390625 +69682 0.4720458984375 +69683 0.40692138671875 +69684 0.3778076171875 +69685 0.376953125 +69686 0.371978759765625 +69687 0.313140869140625 +69688 0.184417724609375 +69689 0.011199951171875 +69690 -0.171051025390625 +69691 -0.33740234375 +69692 -0.47198486328125 +69693 -0.560394287109375 +69694 -0.58056640625 +69695 -0.54754638671875 +69696 -0.508575439453125 +69697 -0.459503173828125 +69698 -0.394378662109375 +69699 -0.35260009765625 +69700 -0.31170654296875 +69701 -0.197418212890625 +69702 -0.007965087890625 +69703 0.207489013671875 +69704 0.409210205078125 +69705 0.57208251953125 +69706 0.66595458984375 +69707 0.65875244140625 +69708 0.56744384765625 +69709 0.431396484375 +69710 0.29443359375 +69711 0.182464599609375 +69712 0.06365966796875 +69713 -0.075958251953125 +69714 -0.189422607421875 +69715 -0.271942138671875 +69716 -0.342529296875 +69717 -0.364166259765625 +69718 -0.327239990234375 +69719 -0.2769775390625 +69720 -0.253692626953125 +69721 -0.24365234375 +69722 -0.1983642578125 +69723 -0.116241455078125 +69724 -0.036834716796875 +69725 0.034881591796875 +69726 0.09124755859375 +69727 0.10888671875 +69728 0.125518798828125 +69729 0.15771484375 +69730 0.17828369140625 +69731 0.17108154296875 +69732 0.129974365234375 +69733 0.082427978515625 +69734 0.027679443359375 +69735 -0.065643310546875 +69736 -0.15936279296875 +69737 -0.21307373046875 +69738 -0.234649658203125 +69739 -0.2001953125 +69740 -0.119171142578125 +69741 -0.024749755859375 +69742 0.085784912109375 +69743 0.178131103515625 +69744 0.215576171875 +69745 0.211456298828125 +69746 0.17523193359375 +69747 0.128753662109375 +69748 0.1019287109375 +69749 0.0743408203125 +69750 0.04327392578125 +69751 0.038177490234375 +69752 0.076263427734375 +69753 0.14105224609375 +69754 0.186431884765625 +69755 0.188812255859375 +69756 0.1390380859375 +69757 0.041778564453125 +69758 -0.079437255859375 +69759 -0.219390869140625 +69760 -0.367828369140625 +69761 -0.494873046875 +69762 -0.556243896484375 +69763 -0.508697509765625 +69764 -0.3756103515625 +69765 -0.218902587890625 +69766 -0.063751220703125 +69767 0.091552734375 +69768 0.23602294921875 +69769 0.342987060546875 +69770 0.39520263671875 +69771 0.389373779296875 +69772 0.324249267578125 +69773 0.224090576171875 +69774 0.124267578125 +69775 0.037078857421875 +69776 -0.010101318359375 +69777 -0.019439697265625 +69778 -0.022796630859375 +69779 -0.001556396484375 +69780 0.056304931640625 +69781 0.106719970703125 +69782 0.096893310546875 +69783 0.042694091796875 +69784 -0.018035888671875 +69785 -0.07586669921875 +69786 -0.11944580078125 +69787 -0.15972900390625 +69788 -0.202606201171875 +69789 -0.24859619140625 +69790 -0.30517578125 +69791 -0.36212158203125 +69792 -0.39141845703125 +69793 -0.35528564453125 +69794 -0.249969482421875 +69795 -0.092864990234375 +69796 0.08905029296875 +69797 0.2352294921875 +69798 0.318817138671875 +69799 0.358642578125 +69800 0.347747802734375 +69801 0.28564453125 +69802 0.223175048828125 +69803 0.196746826171875 +69804 0.179840087890625 +69805 0.155548095703125 +69806 0.151214599609375 +69807 0.156951904296875 +69808 0.13177490234375 +69809 0.100799560546875 +69810 0.087127685546875 +69811 0.05487060546875 +69812 -0.009002685546875 +69813 -0.10400390625 +69814 -0.229400634765625 +69815 -0.35552978515625 +69816 -0.441925048828125 +69817 -0.473846435546875 +69818 -0.464813232421875 +69819 -0.419097900390625 +69820 -0.334320068359375 +69821 -0.227935791015625 +69822 -0.12347412109375 +69823 -0.02764892578125 +69824 0.077667236328125 +69825 0.2132568359375 +69826 0.38885498046875 +69827 0.582794189453125 +69828 0.734039306640625 +69829 0.800140380859375 +69830 0.7783203125 +69831 0.6651611328125 +69832 0.45965576171875 +69833 0.199188232421875 +69834 -0.050689697265625 +69835 -0.23297119140625 +69836 -0.33013916015625 +69837 -0.368408203125 +69838 -0.378936767578125 +69839 -0.376983642578125 +69840 -0.37969970703125 +69841 -0.391510009765625 +69842 -0.385345458984375 +69843 -0.3419189453125 +69844 -0.28289794921875 +69845 -0.251617431640625 +69846 -0.266143798828125 +69847 -0.273345947265625 +69848 -0.216796875 +69849 -0.128265380859375 +69850 -0.068145751953125 +69851 -0.0430908203125 +69852 -0.024444580078125 +69853 0.020721435546875 +69854 0.124481201171875 +69855 0.25787353515625 +69856 0.379119873046875 +69857 0.47991943359375 +69858 0.5281982421875 +69859 0.511138916015625 +69860 0.456207275390625 +69861 0.407470703125 +69862 0.383758544921875 +69863 0.35687255859375 +69864 0.31182861328125 +69865 0.250885009765625 +69866 0.1654052734375 +69867 0.035247802734375 +69868 -0.142059326171875 +69869 -0.33563232421875 +69870 -0.5345458984375 +69871 -0.72186279296875 +69872 -0.836669921875 +69873 -0.8326416015625 +69874 -0.7296142578125 +69875 -0.582550048828125 +69876 -0.440093994140625 +69877 -0.324310302734375 +69878 -0.20147705078125 +69879 -0.044647216796875 +69880 0.103973388671875 +69881 0.202392578125 +69882 0.264495849609375 +69883 0.338897705078125 +69884 0.443817138671875 +69885 0.545074462890625 +69886 0.6173095703125 +69887 0.6524658203125 +69888 0.66339111328125 +69889 0.6561279296875 +69890 0.606781005859375 +69891 0.501190185546875 +69892 0.352783203125 +69893 0.176544189453125 +69894 -0.034820556640625 +69895 -0.258209228515625 +69896 -0.44244384765625 +69897 -0.5753173828125 +69898 -0.65203857421875 +69899 -0.641632080078125 +69900 -0.562164306640625 +69901 -0.458038330078125 +69902 -0.350555419921875 +69903 -0.260528564453125 +69904 -0.192108154296875 +69905 -0.141937255859375 +69906 -0.1021728515625 +69907 -0.062896728515625 +69908 -0.011932373046875 +69909 0.062835693359375 +69910 0.148712158203125 +69911 0.241729736328125 +69912 0.34912109375 +69913 0.457305908203125 +69914 0.54388427734375 +69915 0.5728759765625 +69916 0.506591796875 +69917 0.351226806640625 +69918 0.146514892578125 +69919 -0.05523681640625 +69920 -0.21624755859375 +69921 -0.334930419921875 +69922 -0.402984619140625 +69923 -0.4412841796875 +69924 -0.49578857421875 +69925 -0.5601806640625 +69926 -0.600738525390625 +69927 -0.584228515625 +69928 -0.47930908203125 +69929 -0.27935791015625 +69930 -0.0089111328125 +69931 0.268798828125 +69932 0.482818603515625 +69933 0.60369873046875 +69934 0.650421142578125 +69935 0.66400146484375 +69936 0.6414794921875 +69937 0.572540283203125 +69938 0.498138427734375 +69939 0.439453125 +69940 0.375518798828125 +69941 0.274505615234375 +69942 0.1087646484375 +69943 -0.099395751953125 +69944 -0.3182373046875 +69945 -0.5489501953125 +69946 -0.7738037109375 +69947 -0.86383056640625 +69948 -0.870391845703125 +69949 -0.86895751953125 +69950 -0.861053466796875 +69951 -0.765869140625 +69952 -0.5301513671875 +69953 -0.214691162109375 +69954 0.137359619140625 +69955 0.474822998046875 +69956 0.76239013671875 +69957 0.867462158203125 +69958 0.870361328125 +69959 0.86480712890625 +69960 0.831817626953125 +69961 0.677581787109375 +69962 0.495880126953125 +69963 0.30767822265625 +69964 0.116180419921875 +69965 -0.110748291015625 +69966 -0.381805419921875 +69967 -0.6572265625 +69968 -0.857421875 +69969 -0.870391845703125 +69970 -0.870391845703125 +69971 -0.86444091796875 +69972 -0.85723876953125 +69973 -0.790008544921875 +69974 -0.62847900390625 +69975 -0.3956298828125 +69976 -0.126708984375 +69977 0.150115966796875 +69978 0.424041748046875 +69979 0.670623779296875 +69980 0.854522705078125 +69981 0.866485595703125 +69982 0.86920166015625 +69983 0.8653564453125 +69984 0.857147216796875 +69985 0.766845703125 +69986 0.628509521484375 +69987 0.462127685546875 +69988 0.297210693359375 +69989 0.14862060546875 +69990 -0.00537109375 +69991 -0.15753173828125 +69992 -0.31304931640625 +69993 -0.48876953125 +69994 -0.6416015625 +69995 -0.751373291015625 +69996 -0.84619140625 +69997 -0.861297607421875 +69998 -0.863250732421875 +69999 -0.856597900390625 +70000 -0.7498779296875 +70001 -0.624542236328125 +70002 -0.47808837890625 +70003 -0.253387451171875 +70004 0.003692626953125 +70005 0.2257080078125 +70006 0.427154541015625 +70007 0.643218994140625 +70008 0.855926513671875 +70009 0.870361328125 +70010 0.870361328125 +70011 0.862762451171875 +70012 0.79669189453125 +70013 0.595794677734375 +70014 0.362152099609375 +70015 0.1270751953125 +70016 -0.086944580078125 +70017 -0.2784423828125 +70018 -0.484832763671875 +70019 -0.729583740234375 +70020 -0.86688232421875 +70021 -0.870391845703125 +70022 -0.86859130859375 +70023 -0.86279296875 +70024 -0.817962646484375 +70025 -0.6116943359375 +70026 -0.3128662109375 +70027 0.039398193359375 +70028 0.422821044921875 +70029 0.805145263671875 +70030 0.870361328125 +70031 0.870361328125 +70032 0.860015869140625 +70033 0.727935791015625 +70034 0.48114013671875 +70035 0.2059326171875 +70036 -0.06103515625 +70037 -0.29913330078125 +70038 -0.516204833984375 +70039 -0.7252197265625 +70040 -0.85980224609375 +70041 -0.870391845703125 +70042 -0.870391845703125 +70043 -0.858062744140625 +70044 -0.673004150390625 +70045 -0.42694091796875 +70046 -0.2100830078125 +70047 -0.0362548828125 +70048 0.10943603515625 +70049 0.23516845703125 +70050 0.373687744140625 +70051 0.517791748046875 +70052 0.602783203125 +70053 0.635711669921875 +70054 0.655181884765625 +70055 0.65948486328125 +70056 0.651275634765625 +70057 0.61846923828125 +70058 0.53753662109375 +70059 0.404144287109375 +70060 0.22186279296875 +70061 0.003997802734375 +70062 -0.22100830078125 +70063 -0.42449951171875 +70064 -0.579833984375 +70065 -0.641876220703125 +70066 -0.6177978515625 +70067 -0.575531005859375 +70068 -0.526336669921875 +70069 -0.42645263671875 +70070 -0.2581787109375 +70071 -0.068695068359375 +70072 0.09222412109375 +70073 0.232147216796875 +70074 0.3509521484375 +70075 0.410064697265625 +70076 0.372955322265625 +70077 0.2554931640625 +70078 0.10711669921875 +70079 -0.052886962890625 +70080 -0.186279296875 +70081 -0.23291015625 +70082 -0.209442138671875 +70083 -0.174163818359375 +70084 -0.126739501953125 +70085 -0.048126220703125 +70086 0.0426025390625 +70087 0.10748291015625 +70088 0.1409912109375 +70089 0.19708251953125 +70090 0.273651123046875 +70091 0.31768798828125 +70092 0.341094970703125 +70093 0.368011474609375 +70094 0.37249755859375 +70095 0.30072021484375 +70096 0.1517333984375 +70097 -0.01470947265625 +70098 -0.1883544921875 +70099 -0.372711181640625 +70100 -0.51397705078125 +70101 -0.57177734375 +70102 -0.53948974609375 +70103 -0.43511962890625 +70104 -0.2962646484375 +70105 -0.161102294921875 +70106 -0.0435791015625 +70107 0.060394287109375 +70108 0.13665771484375 +70109 0.170135498046875 +70110 0.16552734375 +70111 0.15728759765625 +70112 0.150787353515625 +70113 0.12200927734375 +70114 0.080108642578125 +70115 0.05126953125 +70116 0.062896728515625 +70117 0.09271240234375 +70118 0.092987060546875 +70119 0.07855224609375 +70120 0.06427001953125 +70121 0.0347900390625 +70122 -0.01171875 +70123 -0.056060791015625 +70124 -0.055511474609375 +70125 -0.010467529296875 +70126 0.02508544921875 +70127 0.025665283203125 +70128 0.017333984375 +70129 0.00189208984375 +70130 -0.03173828125 +70131 -0.071502685546875 +70132 -0.13543701171875 +70133 -0.219970703125 +70134 -0.300506591796875 +70135 -0.376312255859375 +70136 -0.416107177734375 +70137 -0.371124267578125 +70138 -0.242279052734375 +70139 -0.069732666015625 +70140 0.125640869140625 +70141 0.31268310546875 +70142 0.45501708984375 +70143 0.554779052734375 +70144 0.61065673828125 +70145 0.610931396484375 +70146 0.531463623046875 +70147 0.3883056640625 +70148 0.23468017578125 +70149 0.095245361328125 +70150 -0.00396728515625 +70151 -0.04852294921875 +70152 -0.055145263671875 +70153 -0.0758056640625 +70154 -0.138702392578125 +70155 -0.209197998046875 +70156 -0.289031982421875 +70157 -0.37884521484375 +70158 -0.456329345703125 +70159 -0.51641845703125 +70160 -0.519287109375 +70161 -0.458251953125 +70162 -0.384796142578125 +70163 -0.323699951171875 +70164 -0.269287109375 +70165 -0.1951904296875 +70166 -0.100006103515625 +70167 -0.01055908203125 +70168 0.1033935546875 +70169 0.24908447265625 +70170 0.373199462890625 +70171 0.45806884765625 +70172 0.511474609375 +70173 0.565399169921875 +70174 0.61138916015625 +70175 0.5897216796875 +70176 0.4906005859375 +70177 0.33148193359375 +70178 0.147796630859375 +70179 -0.01873779296875 +70180 -0.140289306640625 +70181 -0.191986083984375 +70182 -0.184295654296875 +70183 -0.161834716796875 +70184 -0.166595458984375 +70185 -0.19390869140625 +70186 -0.22442626953125 +70187 -0.279754638671875 +70188 -0.3389892578125 +70189 -0.3543701171875 +70190 -0.348175048828125 +70191 -0.32598876953125 +70192 -0.2581787109375 +70193 -0.139801025390625 +70194 0.014617919921875 +70195 0.144378662109375 +70196 0.221038818359375 +70197 0.27069091796875 +70198 0.294036865234375 +70199 0.311767578125 +70200 0.339141845703125 +70201 0.360260009765625 +70202 0.360504150390625 +70203 0.308380126953125 +70204 0.18170166015625 +70205 0.0047607421875 +70206 -0.17559814453125 +70207 -0.3143310546875 +70208 -0.36785888671875 +70209 -0.36248779296875 +70210 -0.343536376953125 +70211 -0.3018798828125 +70212 -0.231414794921875 +70213 -0.117645263671875 +70214 0.007049560546875 +70215 0.087982177734375 +70216 0.13946533203125 +70217 0.17425537109375 +70218 0.188201904296875 +70219 0.171234130859375 +70220 0.118438720703125 +70221 0.05706787109375 +70222 -0.010711669921875 +70223 -0.0914306640625 +70224 -0.162322998046875 +70225 -0.194549560546875 +70226 -0.1492919921875 +70227 -0.02166748046875 +70228 0.124053955078125 +70229 0.211151123046875 +70230 0.240447998046875 +70231 0.242218017578125 +70232 0.2257080078125 +70233 0.194366455078125 +70234 0.115509033203125 +70235 0.0128173828125 +70236 -0.053802490234375 +70237 -0.110626220703125 +70238 -0.199493408203125 +70239 -0.29437255859375 +70240 -0.33221435546875 +70241 -0.27972412109375 +70242 -0.185333251953125 +70243 -0.128204345703125 +70244 -0.115692138671875 +70245 -0.116455078125 +70246 -0.105926513671875 +70247 -0.053955078125 +70248 0.048797607421875 +70249 0.157318115234375 +70250 0.212005615234375 +70251 0.218475341796875 +70252 0.23724365234375 +70253 0.30535888671875 +70254 0.38128662109375 +70255 0.404449462890625 +70256 0.3944091796875 +70257 0.3885498046875 +70258 0.362640380859375 +70259 0.27362060546875 +70260 0.11712646484375 +70261 -0.054901123046875 +70262 -0.19085693359375 +70263 -0.28570556640625 +70264 -0.339263916015625 +70265 -0.3775634765625 +70266 -0.445709228515625 +70267 -0.535064697265625 +70268 -0.629058837890625 +70269 -0.697601318359375 +70270 -0.70391845703125 +70271 -0.6424560546875 +70272 -0.491241455078125 +70273 -0.265716552734375 +70274 -0.023712158203125 +70275 0.201751708984375 +70276 0.375823974609375 +70277 0.485076904296875 +70278 0.56884765625 +70279 0.634765625 +70280 0.63763427734375 +70281 0.5660400390625 +70282 0.4720458984375 +70283 0.40692138671875 +70284 0.3778076171875 +70285 0.376953125 +70286 0.371978759765625 +70287 0.313140869140625 +70288 0.184417724609375 +70289 0.011199951171875 +70290 -0.171051025390625 +70291 -0.33740234375 +70292 -0.47198486328125 +70293 -0.560394287109375 +70294 -0.58056640625 +70295 -0.54754638671875 +70296 -0.508575439453125 +70297 -0.459503173828125 +70298 -0.394378662109375 +70299 -0.35260009765625 +70300 -0.31170654296875 +70301 -0.197418212890625 +70302 -0.007965087890625 +70303 0.207489013671875 +70304 0.409210205078125 +70305 0.57208251953125 +70306 0.66595458984375 +70307 0.65875244140625 +70308 0.56744384765625 +70309 0.431396484375 +70310 0.29443359375 +70311 0.182464599609375 +70312 0.06365966796875 +70313 -0.075958251953125 +70314 -0.189422607421875 +70315 -0.271942138671875 +70316 -0.342529296875 +70317 -0.364166259765625 +70318 -0.327239990234375 +70319 -0.2769775390625 +70320 -0.253692626953125 +70321 -0.24365234375 +70322 -0.1983642578125 +70323 -0.116241455078125 +70324 -0.036834716796875 +70325 0.034881591796875 +70326 0.09124755859375 +70327 0.10888671875 +70328 0.125518798828125 +70329 0.15771484375 +70330 0.17828369140625 +70331 0.17108154296875 +70332 0.129974365234375 +70333 0.082427978515625 +70334 0.027679443359375 +70335 -0.065643310546875 +70336 -0.15936279296875 +70337 -0.21307373046875 +70338 -0.234649658203125 +70339 -0.2001953125 +70340 -0.119171142578125 +70341 -0.024749755859375 +70342 0.085784912109375 +70343 0.178131103515625 +70344 0.215576171875 +70345 0.211456298828125 +70346 0.17523193359375 +70347 0.128753662109375 +70348 0.1019287109375 +70349 0.0743408203125 +70350 0.04327392578125 +70351 0.038177490234375 +70352 0.076263427734375 +70353 0.14105224609375 +70354 0.186431884765625 +70355 0.188812255859375 +70356 0.1390380859375 +70357 0.041778564453125 +70358 -0.079437255859375 +70359 -0.219390869140625 +70360 -0.367828369140625 +70361 -0.494873046875 +70362 -0.556243896484375 +70363 -0.508697509765625 +70364 -0.3756103515625 +70365 -0.218902587890625 +70366 -0.063751220703125 +70367 0.091552734375 +70368 0.23602294921875 +70369 0.342987060546875 +70370 0.39520263671875 +70371 0.389373779296875 +70372 0.324249267578125 +70373 0.224090576171875 +70374 0.124267578125 +70375 0.037078857421875 +70376 -0.010101318359375 +70377 -0.019439697265625 +70378 -0.022796630859375 +70379 -0.001556396484375 +70380 0.056304931640625 +70381 0.106719970703125 +70382 0.096893310546875 +70383 0.042694091796875 +70384 -0.018035888671875 +70385 -0.07586669921875 +70386 -0.11944580078125 +70387 -0.15972900390625 +70388 -0.202606201171875 +70389 -0.24859619140625 +70390 -0.30517578125 +70391 -0.36212158203125 +70392 -0.39141845703125 +70393 -0.35528564453125 +70394 -0.249969482421875 +70395 -0.092864990234375 +70396 0.08905029296875 +70397 0.2352294921875 +70398 0.318817138671875 +70399 0.358642578125 +70400 0.347747802734375 +70401 0.28564453125 +70402 0.223175048828125 +70403 0.196746826171875 +70404 0.179840087890625 +70405 0.155548095703125 +70406 0.151214599609375 +70407 0.156951904296875 +70408 0.13177490234375 +70409 0.100799560546875 +70410 0.087127685546875 +70411 0.05487060546875 +70412 -0.009002685546875 +70413 -0.10400390625 +70414 -0.229400634765625 +70415 -0.35552978515625 +70416 -0.441925048828125 +70417 -0.473846435546875 +70418 -0.464813232421875 +70419 -0.419097900390625 +70420 -0.334320068359375 +70421 -0.227935791015625 +70422 -0.12347412109375 +70423 -0.02764892578125 +70424 0.077667236328125 +70425 0.2132568359375 +70426 0.38885498046875 +70427 0.582794189453125 +70428 0.734039306640625 +70429 0.800140380859375 +70430 0.7783203125 +70431 0.6651611328125 +70432 0.45965576171875 +70433 0.199188232421875 +70434 -0.050689697265625 +70435 -0.23297119140625 +70436 -0.33013916015625 +70437 -0.368408203125 +70438 -0.378936767578125 +70439 -0.376983642578125 +70440 -0.37969970703125 +70441 -0.391510009765625 +70442 -0.385345458984375 +70443 -0.3419189453125 +70444 -0.28289794921875 +70445 -0.251617431640625 +70446 -0.266143798828125 +70447 -0.273345947265625 +70448 -0.216796875 +70449 -0.128265380859375 +70450 -0.068145751953125 +70451 -0.0430908203125 +70452 -0.024444580078125 +70453 0.020721435546875 +70454 0.124481201171875 +70455 0.25787353515625 +70456 0.379119873046875 +70457 0.47991943359375 +70458 0.5281982421875 +70459 0.511138916015625 +70460 0.456207275390625 +70461 0.407470703125 +70462 0.383758544921875 +70463 0.35687255859375 +70464 0.31182861328125 +70465 0.250885009765625 +70466 0.1654052734375 +70467 0.035247802734375 +70468 -0.142059326171875 +70469 -0.33563232421875 +70470 -0.5345458984375 +70471 -0.72186279296875 +70472 -0.836669921875 +70473 -0.8326416015625 +70474 -0.7296142578125 +70475 -0.582550048828125 +70476 -0.440093994140625 +70477 -0.324310302734375 +70478 -0.20147705078125 +70479 -0.044647216796875 +70480 0.103973388671875 +70481 0.202392578125 +70482 0.264495849609375 +70483 0.338897705078125 +70484 0.443817138671875 +70485 0.545074462890625 +70486 0.6173095703125 +70487 0.6524658203125 +70488 0.66339111328125 +70489 0.6561279296875 +70490 0.606781005859375 +70491 0.501190185546875 +70492 0.352783203125 +70493 0.176544189453125 +70494 -0.034820556640625 +70495 -0.258209228515625 +70496 -0.44244384765625 +70497 -0.5753173828125 +70498 -0.65203857421875 +70499 -0.641632080078125 +70500 -0.562164306640625 +70501 -0.458038330078125 +70502 -0.350555419921875 +70503 -0.260528564453125 +70504 -0.192108154296875 +70505 -0.141937255859375 +70506 -0.1021728515625 +70507 -0.062896728515625 +70508 -0.011932373046875 +70509 0.062835693359375 +70510 0.148712158203125 +70511 0.241729736328125 +70512 0.34912109375 +70513 0.457305908203125 +70514 0.54388427734375 +70515 0.5728759765625 +70516 0.506591796875 +70517 0.351226806640625 +70518 0.146514892578125 +70519 -0.05523681640625 +70520 -0.21624755859375 +70521 -0.334930419921875 +70522 -0.402984619140625 +70523 -0.4412841796875 +70524 -0.49578857421875 +70525 -0.5601806640625 +70526 -0.600738525390625 +70527 -0.584228515625 +70528 -0.47930908203125 +70529 -0.27935791015625 +70530 -0.0089111328125 +70531 0.268798828125 +70532 0.482818603515625 +70533 0.60369873046875 +70534 0.650421142578125 +70535 0.66400146484375 +70536 0.6414794921875 +70537 0.572540283203125 +70538 0.498138427734375 +70539 0.439453125 +70540 0.375518798828125 +70541 0.274505615234375 +70542 0.1087646484375 +70543 -0.099395751953125 +70544 -0.3182373046875 +70545 -0.5489501953125 +70546 -0.7738037109375 +70547 -0.86383056640625 +70548 -0.870391845703125 +70549 -0.86895751953125 +70550 -0.861053466796875 +70551 -0.765869140625 +70552 -0.5301513671875 +70553 -0.214691162109375 +70554 0.137359619140625 +70555 0.474822998046875 +70556 0.76239013671875 +70557 0.867462158203125 +70558 0.870361328125 +70559 0.86480712890625 +70560 0.831817626953125 +70561 0.677581787109375 +70562 0.495880126953125 +70563 0.30767822265625 +70564 0.116180419921875 +70565 -0.110748291015625 +70566 -0.381805419921875 +70567 -0.6572265625 +70568 -0.857421875 +70569 -0.870391845703125 +70570 -0.870391845703125 +70571 -0.86444091796875 +70572 -0.85723876953125 +70573 -0.790008544921875 +70574 -0.62847900390625 +70575 -0.3956298828125 +70576 -0.126708984375 +70577 0.150115966796875 +70578 0.424041748046875 +70579 0.670623779296875 +70580 0.854522705078125 +70581 0.866485595703125 +70582 0.86920166015625 +70583 0.8653564453125 +70584 0.857147216796875 +70585 0.766845703125 +70586 0.628509521484375 +70587 0.462127685546875 +70588 0.297210693359375 +70589 0.14862060546875 +70590 -0.00537109375 +70591 -0.15753173828125 +70592 -0.31304931640625 +70593 -0.48876953125 +70594 -0.6416015625 +70595 -0.751373291015625 +70596 -0.84619140625 +70597 -0.861297607421875 +70598 -0.863250732421875 +70599 -0.856597900390625 +70600 -0.7498779296875 +70601 -0.624542236328125 +70602 -0.47808837890625 +70603 -0.253387451171875 +70604 0.003692626953125 +70605 0.2257080078125 +70606 0.427154541015625 +70607 0.643218994140625 +70608 0.855926513671875 +70609 0.870361328125 +70610 0.870361328125 +70611 0.862762451171875 +70612 0.79669189453125 +70613 0.595794677734375 +70614 0.362152099609375 +70615 0.1270751953125 +70616 -0.086944580078125 +70617 -0.2784423828125 +70618 -0.484832763671875 +70619 -0.729583740234375 +70620 -0.86688232421875 +70621 -0.870391845703125 +70622 -0.86859130859375 +70623 -0.86279296875 +70624 -0.817962646484375 +70625 -0.6116943359375 +70626 -0.3128662109375 +70627 0.039398193359375 +70628 0.422821044921875 +70629 0.805145263671875 +70630 0.870361328125 +70631 0.870361328125 +70632 0.860015869140625 +70633 0.727935791015625 +70634 0.48114013671875 +70635 0.2059326171875 +70636 -0.06103515625 +70637 -0.29913330078125 +70638 -0.516204833984375 +70639 -0.7252197265625 +70640 -0.85980224609375 +70641 -0.870391845703125 +70642 -0.870391845703125 +70643 -0.858062744140625 +70644 -0.673004150390625 +70645 -0.42694091796875 +70646 -0.2100830078125 +70647 -0.0362548828125 +70648 0.10943603515625 +70649 0.23516845703125 +70650 0.373687744140625 +70651 0.517791748046875 +70652 0.602783203125 +70653 0.635711669921875 +70654 0.655181884765625 +70655 0.65948486328125 +70656 0.651275634765625 +70657 0.61846923828125 +70658 0.53753662109375 +70659 0.404144287109375 +70660 0.22186279296875 +70661 0.003997802734375 +70662 -0.22100830078125 +70663 -0.42449951171875 +70664 -0.579833984375 +70665 -0.641876220703125 +70666 -0.6177978515625 +70667 -0.575531005859375 +70668 -0.526336669921875 +70669 -0.42645263671875 +70670 -0.2581787109375 +70671 -0.068695068359375 +70672 0.09222412109375 +70673 0.232147216796875 +70674 0.3509521484375 +70675 0.410064697265625 +70676 0.372955322265625 +70677 0.2554931640625 +70678 0.10711669921875 +70679 -0.052886962890625 +70680 -0.186279296875 +70681 -0.23291015625 +70682 -0.209442138671875 +70683 -0.174163818359375 +70684 -0.126739501953125 +70685 -0.048126220703125 +70686 0.0426025390625 +70687 0.10748291015625 +70688 0.1409912109375 +70689 0.19708251953125 +70690 0.273651123046875 +70691 0.31768798828125 +70692 0.341094970703125 +70693 0.368011474609375 +70694 0.37249755859375 +70695 0.30072021484375 +70696 0.1517333984375 +70697 -0.01470947265625 +70698 -0.1883544921875 +70699 -0.372711181640625 +70700 -0.51397705078125 +70701 -0.57177734375 +70702 -0.53948974609375 +70703 -0.43511962890625 +70704 -0.2962646484375 +70705 -0.161102294921875 +70706 -0.0435791015625 +70707 0.060394287109375 +70708 0.13665771484375 +70709 0.170135498046875 +70710 0.16552734375 +70711 0.15728759765625 +70712 0.150787353515625 +70713 0.12200927734375 +70714 0.080108642578125 +70715 0.05126953125 +70716 0.062896728515625 +70717 0.09271240234375 +70718 0.092987060546875 +70719 0.07855224609375 +70720 0.06427001953125 +70721 0.0347900390625 +70722 -0.01171875 +70723 -0.056060791015625 +70724 -0.055511474609375 +70725 -0.010467529296875 +70726 0.02508544921875 +70727 0.025665283203125 +70728 0.017333984375 +70729 0.00189208984375 +70730 -0.03173828125 +70731 -0.071502685546875 +70732 -0.13543701171875 +70733 -0.219970703125 +70734 -0.300506591796875 +70735 -0.376312255859375 +70736 -0.416107177734375 +70737 -0.371124267578125 +70738 -0.242279052734375 +70739 -0.069732666015625 +70740 0.125640869140625 +70741 0.31268310546875 +70742 0.45501708984375 +70743 0.554779052734375 +70744 0.61065673828125 +70745 0.610931396484375 +70746 0.531463623046875 +70747 0.3883056640625 +70748 0.23468017578125 +70749 0.095245361328125 +70750 -0.00396728515625 +70751 -0.04852294921875 +70752 -0.055145263671875 +70753 -0.0758056640625 +70754 -0.138702392578125 +70755 -0.209197998046875 +70756 -0.289031982421875 +70757 -0.37884521484375 +70758 -0.456329345703125 +70759 -0.51641845703125 +70760 -0.519287109375 +70761 -0.458251953125 +70762 -0.384796142578125 +70763 -0.323699951171875 +70764 -0.269287109375 +70765 -0.1951904296875 +70766 -0.100006103515625 +70767 -0.01055908203125 +70768 0.1033935546875 +70769 0.24908447265625 +70770 0.373199462890625 +70771 0.45806884765625 +70772 0.511474609375 +70773 0.565399169921875 +70774 0.61138916015625 +70775 0.5897216796875 +70776 0.4906005859375 +70777 0.33148193359375 +70778 0.147796630859375 +70779 -0.01873779296875 +70780 -0.140289306640625 +70781 -0.191986083984375 +70782 -0.184295654296875 +70783 -0.161834716796875 +70784 -0.166595458984375 +70785 -0.19390869140625 +70786 -0.22442626953125 +70787 -0.279754638671875 +70788 -0.3389892578125 +70789 -0.3543701171875 +70790 -0.348175048828125 +70791 -0.32598876953125 +70792 -0.2581787109375 +70793 -0.139801025390625 +70794 0.014617919921875 +70795 0.144378662109375 +70796 0.221038818359375 +70797 0.27069091796875 +70798 0.294036865234375 +70799 0.311767578125 +70800 0.339141845703125 +70801 0.360260009765625 +70802 0.360504150390625 +70803 0.308380126953125 +70804 0.18170166015625 +70805 0.0047607421875 +70806 -0.17559814453125 +70807 -0.3143310546875 +70808 -0.36785888671875 +70809 -0.36248779296875 +70810 -0.343536376953125 +70811 -0.3018798828125 +70812 -0.231414794921875 +70813 -0.117645263671875 +70814 0.007049560546875 +70815 0.087982177734375 +70816 0.13946533203125 +70817 0.17425537109375 +70818 0.188201904296875 +70819 0.171234130859375 +70820 0.118438720703125 +70821 0.05706787109375 +70822 -0.010711669921875 +70823 -0.0914306640625 +70824 -0.162322998046875 +70825 -0.194549560546875 +70826 -0.1492919921875 +70827 -0.02166748046875 +70828 0.124053955078125 +70829 0.211151123046875 +70830 0.240447998046875 +70831 0.242218017578125 +70832 0.2257080078125 +70833 0.194366455078125 +70834 0.115509033203125 +70835 0.0128173828125 +70836 -0.053802490234375 +70837 -0.110626220703125 +70838 -0.199493408203125 +70839 -0.29437255859375 +70840 -0.33221435546875 +70841 -0.27972412109375 +70842 -0.185333251953125 +70843 -0.128204345703125 +70844 -0.115692138671875 +70845 -0.116455078125 +70846 -0.105926513671875 +70847 -0.053955078125 +70848 0.048797607421875 +70849 0.157318115234375 +70850 0.212005615234375 +70851 0.218475341796875 +70852 0.23724365234375 +70853 0.30535888671875 +70854 0.38128662109375 +70855 0.404449462890625 +70856 0.3944091796875 +70857 0.3885498046875 +70858 0.362640380859375 +70859 0.27362060546875 +70860 0.11712646484375 +70861 -0.054901123046875 +70862 -0.19085693359375 +70863 -0.28570556640625 +70864 -0.339263916015625 +70865 -0.3775634765625 +70866 -0.445709228515625 +70867 -0.535064697265625 +70868 -0.629058837890625 +70869 -0.697601318359375 +70870 -0.70391845703125 +70871 -0.6424560546875 +70872 -0.491241455078125 +70873 -0.265716552734375 +70874 -0.023712158203125 +70875 0.201751708984375 +70876 0.375823974609375 +70877 0.485076904296875 +70878 0.56884765625 +70879 0.634765625 +70880 0.63763427734375 +70881 0.5660400390625 +70882 0.4720458984375 +70883 0.40692138671875 +70884 0.3778076171875 +70885 0.376953125 +70886 0.371978759765625 +70887 0.313140869140625 +70888 0.184417724609375 +70889 0.011199951171875 +70890 -0.171051025390625 +70891 -0.33740234375 +70892 -0.47198486328125 +70893 -0.560394287109375 +70894 -0.58056640625 +70895 -0.54754638671875 +70896 -0.508575439453125 +70897 -0.459503173828125 +70898 -0.394378662109375 +70899 -0.35260009765625 +70900 -0.31170654296875 +70901 -0.197418212890625 +70902 -0.007965087890625 +70903 0.207489013671875 +70904 0.409210205078125 +70905 0.57208251953125 +70906 0.66595458984375 +70907 0.65875244140625 +70908 0.56744384765625 +70909 0.431396484375 +70910 0.29443359375 +70911 0.182464599609375 +70912 0.06365966796875 +70913 -0.075958251953125 +70914 -0.189422607421875 +70915 -0.271942138671875 +70916 -0.342529296875 +70917 -0.364166259765625 +70918 -0.327239990234375 +70919 -0.2769775390625 +70920 -0.253692626953125 +70921 -0.24365234375 +70922 -0.1983642578125 +70923 -0.116241455078125 +70924 -0.036834716796875 +70925 0.034881591796875 +70926 0.09124755859375 +70927 0.10888671875 +70928 0.125518798828125 +70929 0.15771484375 +70930 0.17828369140625 +70931 0.17108154296875 +70932 0.129974365234375 +70933 0.082427978515625 +70934 0.027679443359375 +70935 -0.065643310546875 +70936 -0.15936279296875 +70937 -0.21307373046875 +70938 -0.234649658203125 +70939 -0.2001953125 +70940 -0.119171142578125 +70941 -0.024749755859375 +70942 0.085784912109375 +70943 0.178131103515625 +70944 0.215576171875 +70945 0.211456298828125 +70946 0.17523193359375 +70947 0.128753662109375 +70948 0.1019287109375 +70949 0.0743408203125 +70950 0.04327392578125 +70951 0.038177490234375 +70952 0.076263427734375 +70953 0.14105224609375 +70954 0.186431884765625 +70955 0.188812255859375 +70956 0.1390380859375 +70957 0.041778564453125 +70958 -0.079437255859375 +70959 -0.219390869140625 +70960 -0.367828369140625 +70961 -0.494873046875 +70962 -0.556243896484375 +70963 -0.508697509765625 +70964 -0.3756103515625 +70965 -0.218902587890625 +70966 -0.063751220703125 +70967 0.091552734375 +70968 0.23602294921875 +70969 0.342987060546875 +70970 0.39520263671875 +70971 0.389373779296875 +70972 0.324249267578125 +70973 0.224090576171875 +70974 0.124267578125 +70975 0.037078857421875 +70976 -0.010101318359375 +70977 -0.019439697265625 +70978 -0.022796630859375 +70979 -0.001556396484375 +70980 0.056304931640625 +70981 0.106719970703125 +70982 0.096893310546875 +70983 0.042694091796875 +70984 -0.018035888671875 +70985 -0.07586669921875 +70986 -0.11944580078125 +70987 -0.15972900390625 +70988 -0.202606201171875 +70989 -0.24859619140625 +70990 -0.30517578125 +70991 -0.36212158203125 +70992 -0.39141845703125 +70993 -0.35528564453125 +70994 -0.249969482421875 +70995 -0.092864990234375 +70996 0.08905029296875 +70997 0.2352294921875 +70998 0.318817138671875 +70999 0.358642578125 +71000 0.347747802734375 +71001 0.28564453125 +71002 0.223175048828125 +71003 0.196746826171875 +71004 0.179840087890625 +71005 0.155548095703125 +71006 0.151214599609375 +71007 0.156951904296875 +71008 0.13177490234375 +71009 0.100799560546875 +71010 0.087127685546875 +71011 0.05487060546875 +71012 -0.009002685546875 +71013 -0.10400390625 +71014 -0.229400634765625 +71015 -0.35552978515625 +71016 -0.441925048828125 +71017 -0.473846435546875 +71018 -0.464813232421875 +71019 -0.419097900390625 +71020 -0.334320068359375 +71021 -0.227935791015625 +71022 -0.12347412109375 +71023 -0.02764892578125 +71024 0.077667236328125 +71025 0.2132568359375 +71026 0.38885498046875 +71027 0.582794189453125 +71028 0.734039306640625 +71029 0.800140380859375 +71030 0.7783203125 +71031 0.6651611328125 +71032 0.45965576171875 +71033 0.199188232421875 +71034 -0.050689697265625 +71035 -0.23297119140625 +71036 -0.33013916015625 +71037 -0.368408203125 +71038 -0.378936767578125 +71039 -0.376983642578125 +71040 -0.37969970703125 +71041 -0.391510009765625 +71042 -0.385345458984375 +71043 -0.3419189453125 +71044 -0.28289794921875 +71045 -0.251617431640625 +71046 -0.266143798828125 +71047 -0.273345947265625 +71048 -0.216796875 +71049 -0.128265380859375 +71050 -0.068145751953125 +71051 -0.0430908203125 +71052 -0.024444580078125 +71053 0.020721435546875 +71054 0.124481201171875 +71055 0.25787353515625 +71056 0.379119873046875 +71057 0.47991943359375 +71058 0.5281982421875 +71059 0.511138916015625 +71060 0.456207275390625 +71061 0.407470703125 +71062 0.383758544921875 +71063 0.35687255859375 +71064 0.31182861328125 +71065 0.250885009765625 +71066 0.1654052734375 +71067 0.035247802734375 +71068 -0.142059326171875 +71069 -0.33563232421875 +71070 -0.5345458984375 +71071 -0.72186279296875 +71072 -0.836669921875 +71073 -0.8326416015625 +71074 -0.7296142578125 +71075 -0.582550048828125 +71076 -0.440093994140625 +71077 -0.324310302734375 +71078 -0.20147705078125 +71079 -0.044647216796875 +71080 0.103973388671875 +71081 0.202392578125 +71082 0.264495849609375 +71083 0.338897705078125 +71084 0.443817138671875 +71085 0.545074462890625 +71086 0.6173095703125 +71087 0.6524658203125 +71088 0.66339111328125 +71089 0.6561279296875 +71090 0.606781005859375 +71091 0.501190185546875 +71092 0.352783203125 +71093 0.176544189453125 +71094 -0.034820556640625 +71095 -0.258209228515625 +71096 -0.44244384765625 +71097 -0.5753173828125 +71098 -0.65203857421875 +71099 -0.641632080078125 +71100 -0.562164306640625 +71101 -0.458038330078125 +71102 -0.350555419921875 +71103 -0.260528564453125 +71104 -0.192108154296875 +71105 -0.141937255859375 +71106 -0.1021728515625 +71107 -0.062896728515625 +71108 -0.011932373046875 +71109 0.062835693359375 +71110 0.148712158203125 +71111 0.241729736328125 +71112 0.34912109375 +71113 0.457305908203125 +71114 0.54388427734375 +71115 0.5728759765625 +71116 0.506591796875 +71117 0.351226806640625 +71118 0.146514892578125 +71119 -0.05523681640625 +71120 -0.21624755859375 +71121 -0.334930419921875 +71122 -0.402984619140625 +71123 -0.4412841796875 +71124 -0.49578857421875 +71125 -0.5601806640625 +71126 -0.600738525390625 +71127 -0.584228515625 +71128 -0.47930908203125 +71129 -0.27935791015625 +71130 -0.0089111328125 +71131 0.268798828125 +71132 0.482818603515625 +71133 0.60369873046875 +71134 0.650421142578125 +71135 0.66400146484375 +71136 0.6414794921875 +71137 0.572540283203125 +71138 0.498138427734375 +71139 0.439453125 +71140 0.375518798828125 +71141 0.274505615234375 +71142 0.1087646484375 +71143 -0.099395751953125 +71144 -0.3182373046875 +71145 -0.5489501953125 +71146 -0.7738037109375 +71147 -0.86383056640625 +71148 -0.870391845703125 +71149 -0.86895751953125 +71150 -0.861053466796875 +71151 -0.765869140625 +71152 -0.5301513671875 +71153 -0.214691162109375 +71154 0.137359619140625 +71155 0.474822998046875 +71156 0.76239013671875 +71157 0.867462158203125 +71158 0.870361328125 +71159 0.86480712890625 +71160 0.831817626953125 +71161 0.677581787109375 +71162 0.495880126953125 +71163 0.30767822265625 +71164 0.116180419921875 +71165 -0.110748291015625 +71166 -0.381805419921875 +71167 -0.6572265625 +71168 -0.857421875 +71169 -0.870391845703125 +71170 -0.870391845703125 +71171 -0.86444091796875 +71172 -0.85723876953125 +71173 -0.790008544921875 +71174 -0.62847900390625 +71175 -0.3956298828125 +71176 -0.126708984375 +71177 0.150115966796875 +71178 0.424041748046875 +71179 0.670623779296875 +71180 0.854522705078125 +71181 0.866485595703125 +71182 0.86920166015625 +71183 0.8653564453125 +71184 0.857147216796875 +71185 0.766845703125 +71186 0.628509521484375 +71187 0.462127685546875 +71188 0.297210693359375 +71189 0.14862060546875 +71190 -0.00537109375 +71191 -0.15753173828125 +71192 -0.31304931640625 +71193 -0.48876953125 +71194 -0.6416015625 +71195 -0.751373291015625 +71196 -0.84619140625 +71197 -0.861297607421875 +71198 -0.863250732421875 +71199 -0.856597900390625 +71200 -0.7498779296875 +71201 -0.624542236328125 +71202 -0.47808837890625 +71203 -0.253387451171875 +71204 0.003692626953125 +71205 0.2257080078125 +71206 0.427154541015625 +71207 0.643218994140625 +71208 0.855926513671875 +71209 0.870361328125 +71210 0.870361328125 +71211 0.862762451171875 +71212 0.79669189453125 +71213 0.595794677734375 +71214 0.362152099609375 +71215 0.1270751953125 +71216 -0.086944580078125 +71217 -0.2784423828125 +71218 -0.484832763671875 +71219 -0.729583740234375 +71220 -0.86688232421875 +71221 -0.870391845703125 +71222 -0.86859130859375 +71223 -0.86279296875 +71224 -0.817962646484375 +71225 -0.6116943359375 +71226 -0.3128662109375 +71227 0.039398193359375 +71228 0.422821044921875 +71229 0.805145263671875 +71230 0.870361328125 +71231 0.870361328125 +71232 0.860015869140625 +71233 0.727935791015625 +71234 0.48114013671875 +71235 0.2059326171875 +71236 -0.06103515625 +71237 -0.29913330078125 +71238 -0.516204833984375 +71239 -0.7252197265625 +71240 -0.85980224609375 +71241 -0.870391845703125 +71242 -0.870391845703125 +71243 -0.858062744140625 +71244 -0.673004150390625 +71245 -0.42694091796875 +71246 -0.2100830078125 +71247 -0.0362548828125 +71248 0.10943603515625 +71249 0.23516845703125 +71250 0.373687744140625 +71251 0.517791748046875 +71252 0.602783203125 +71253 0.635711669921875 +71254 0.655181884765625 +71255 0.65948486328125 +71256 0.651275634765625 +71257 0.61846923828125 +71258 0.53753662109375 +71259 0.404144287109375 +71260 0.22186279296875 +71261 0.003997802734375 +71262 -0.22100830078125 +71263 -0.42449951171875 +71264 -0.579833984375 +71265 -0.641876220703125 +71266 -0.6177978515625 +71267 -0.575531005859375 +71268 -0.526336669921875 +71269 -0.42645263671875 +71270 -0.2581787109375 +71271 -0.068695068359375 +71272 0.09222412109375 +71273 0.232147216796875 +71274 0.3509521484375 +71275 0.410064697265625 +71276 0.372955322265625 +71277 0.2554931640625 +71278 0.10711669921875 +71279 -0.052886962890625 +71280 -0.186279296875 +71281 -0.23291015625 +71282 -0.209442138671875 +71283 -0.174163818359375 +71284 -0.126739501953125 +71285 -0.048126220703125 +71286 0.0426025390625 +71287 0.10748291015625 +71288 0.1409912109375 +71289 0.19708251953125 +71290 0.273651123046875 +71291 0.31768798828125 +71292 0.341094970703125 +71293 0.368011474609375 +71294 0.37249755859375 +71295 0.30072021484375 +71296 0.1517333984375 +71297 -0.01470947265625 +71298 -0.1883544921875 +71299 -0.372711181640625 +71300 -0.51397705078125 +71301 -0.57177734375 +71302 -0.53948974609375 +71303 -0.43511962890625 +71304 -0.2962646484375 +71305 -0.161102294921875 +71306 -0.0435791015625 +71307 0.060394287109375 +71308 0.13665771484375 +71309 0.170135498046875 +71310 0.16552734375 +71311 0.15728759765625 +71312 0.150787353515625 +71313 0.12200927734375 +71314 0.080108642578125 +71315 0.05126953125 +71316 0.062896728515625 +71317 0.09271240234375 +71318 0.092987060546875 +71319 0.07855224609375 +71320 0.06427001953125 +71321 0.0347900390625 +71322 -0.01171875 +71323 -0.056060791015625 +71324 -0.055511474609375 +71325 -0.010467529296875 +71326 0.02508544921875 +71327 0.025665283203125 +71328 0.017333984375 +71329 0.00189208984375 +71330 -0.03173828125 +71331 -0.071502685546875 +71332 -0.13543701171875 +71333 -0.219970703125 +71334 -0.300506591796875 +71335 -0.376312255859375 +71336 -0.416107177734375 +71337 -0.371124267578125 +71338 -0.242279052734375 +71339 -0.069732666015625 +71340 0.125640869140625 +71341 0.31268310546875 +71342 0.45501708984375 +71343 0.554779052734375 +71344 0.61065673828125 +71345 0.610931396484375 +71346 0.531463623046875 +71347 0.3883056640625 +71348 0.23468017578125 +71349 0.095245361328125 +71350 -0.00396728515625 +71351 -0.04852294921875 +71352 -0.055145263671875 +71353 -0.0758056640625 +71354 -0.138702392578125 +71355 -0.209197998046875 +71356 -0.289031982421875 +71357 -0.37884521484375 +71358 -0.456329345703125 +71359 -0.51641845703125 +71360 -0.519287109375 +71361 -0.458251953125 +71362 -0.384796142578125 +71363 -0.323699951171875 +71364 -0.269287109375 +71365 -0.1951904296875 +71366 -0.100006103515625 +71367 -0.01055908203125 +71368 0.1033935546875 +71369 0.24908447265625 +71370 0.373199462890625 +71371 0.45806884765625 +71372 0.511474609375 +71373 0.565399169921875 +71374 0.61138916015625 +71375 0.5897216796875 +71376 0.4906005859375 +71377 0.33148193359375 +71378 0.147796630859375 +71379 -0.01873779296875 +71380 -0.140289306640625 +71381 -0.191986083984375 +71382 -0.184295654296875 +71383 -0.161834716796875 +71384 -0.166595458984375 +71385 -0.19390869140625 +71386 -0.22442626953125 +71387 -0.279754638671875 +71388 -0.3389892578125 +71389 -0.3543701171875 +71390 -0.348175048828125 +71391 -0.32598876953125 +71392 -0.2581787109375 +71393 -0.139801025390625 +71394 0.014617919921875 +71395 0.144378662109375 +71396 0.221038818359375 +71397 0.27069091796875 +71398 0.294036865234375 +71399 0.311767578125 +71400 0.339141845703125 +71401 0.360260009765625 +71402 0.360504150390625 +71403 0.308380126953125 +71404 0.18170166015625 +71405 0.0047607421875 +71406 -0.17559814453125 +71407 -0.3143310546875 +71408 -0.36785888671875 +71409 -0.36248779296875 +71410 -0.343536376953125 +71411 -0.3018798828125 +71412 -0.231414794921875 +71413 -0.117645263671875 +71414 0.007049560546875 +71415 0.087982177734375 +71416 0.13946533203125 +71417 0.17425537109375 +71418 0.188201904296875 +71419 0.171234130859375 +71420 0.118438720703125 +71421 0.05706787109375 +71422 -0.010711669921875 +71423 -0.0914306640625 +71424 -0.162322998046875 +71425 -0.194549560546875 +71426 -0.1492919921875 +71427 -0.02166748046875 +71428 0.124053955078125 +71429 0.211151123046875 +71430 0.240447998046875 +71431 0.242218017578125 +71432 0.2257080078125 +71433 0.194366455078125 +71434 0.115509033203125 +71435 0.0128173828125 +71436 -0.053802490234375 +71437 -0.110626220703125 +71438 -0.199493408203125 +71439 -0.29437255859375 +71440 -0.33221435546875 +71441 -0.27972412109375 +71442 -0.185333251953125 +71443 -0.128204345703125 +71444 -0.115692138671875 +71445 -0.116455078125 +71446 -0.105926513671875 +71447 -0.053955078125 +71448 0.048797607421875 +71449 0.157318115234375 +71450 0.212005615234375 +71451 0.218475341796875 +71452 0.23724365234375 +71453 0.30535888671875 +71454 0.38128662109375 +71455 0.404449462890625 +71456 0.3944091796875 +71457 0.3885498046875 +71458 0.362640380859375 +71459 0.27362060546875 +71460 0.11712646484375 +71461 -0.054901123046875 +71462 -0.19085693359375 +71463 -0.28570556640625 +71464 -0.339263916015625 +71465 -0.3775634765625 +71466 -0.445709228515625 +71467 -0.535064697265625 +71468 -0.629058837890625 +71469 -0.697601318359375 +71470 -0.70391845703125 +71471 -0.6424560546875 +71472 -0.491241455078125 +71473 -0.265716552734375 +71474 -0.023712158203125 +71475 0.201751708984375 +71476 0.375823974609375 +71477 0.485076904296875 +71478 0.56884765625 +71479 0.634765625 +71480 0.63763427734375 +71481 0.5660400390625 +71482 0.4720458984375 +71483 0.40692138671875 +71484 0.3778076171875 +71485 0.376953125 +71486 0.371978759765625 +71487 0.313140869140625 +71488 0.184417724609375 +71489 0.011199951171875 +71490 -0.171051025390625 +71491 -0.33740234375 +71492 -0.47198486328125 +71493 -0.560394287109375 +71494 -0.58056640625 +71495 -0.54754638671875 +71496 -0.508575439453125 +71497 -0.459503173828125 +71498 -0.394378662109375 +71499 -0.35260009765625 +71500 -0.31170654296875 +71501 -0.197418212890625 +71502 -0.007965087890625 +71503 0.207489013671875 +71504 0.409210205078125 +71505 0.57208251953125 +71506 0.66595458984375 +71507 0.65875244140625 +71508 0.56744384765625 +71509 0.431396484375 +71510 0.29443359375 +71511 0.182464599609375 +71512 0.06365966796875 +71513 -0.075958251953125 +71514 -0.189422607421875 +71515 -0.271942138671875 +71516 -0.342529296875 +71517 -0.364166259765625 +71518 -0.327239990234375 +71519 -0.2769775390625 +71520 -0.253692626953125 +71521 -0.24365234375 +71522 -0.1983642578125 +71523 -0.116241455078125 +71524 -0.036834716796875 +71525 0.034881591796875 +71526 0.09124755859375 +71527 0.10888671875 +71528 0.125518798828125 +71529 0.15771484375 +71530 0.17828369140625 +71531 0.17108154296875 +71532 0.129974365234375 +71533 0.082427978515625 +71534 0.027679443359375 +71535 -0.065643310546875 +71536 -0.15936279296875 +71537 -0.21307373046875 +71538 -0.234649658203125 +71539 -0.2001953125 +71540 -0.119171142578125 +71541 -0.024749755859375 +71542 0.085784912109375 +71543 0.178131103515625 +71544 0.215576171875 +71545 0.211456298828125 +71546 0.17523193359375 +71547 0.128753662109375 +71548 0.1019287109375 +71549 0.0743408203125 +71550 0.04327392578125 +71551 0.038177490234375 +71552 0.076263427734375 +71553 0.14105224609375 +71554 0.186431884765625 +71555 0.188812255859375 +71556 0.1390380859375 +71557 0.041778564453125 +71558 -0.079437255859375 +71559 -0.219390869140625 +71560 -0.367828369140625 +71561 -0.494873046875 +71562 -0.556243896484375 +71563 -0.508697509765625 +71564 -0.3756103515625 +71565 -0.218902587890625 +71566 -0.063751220703125 +71567 0.091552734375 +71568 0.23602294921875 +71569 0.342987060546875 +71570 0.39520263671875 +71571 0.389373779296875 +71572 0.324249267578125 +71573 0.224090576171875 +71574 0.124267578125 +71575 0.037078857421875 +71576 -0.010101318359375 +71577 -0.019439697265625 +71578 -0.022796630859375 +71579 -0.001556396484375 +71580 0.056304931640625 +71581 0.106719970703125 +71582 0.096893310546875 +71583 0.042694091796875 +71584 -0.018035888671875 +71585 -0.07586669921875 +71586 -0.11944580078125 +71587 -0.15972900390625 +71588 -0.202606201171875 +71589 -0.24859619140625 +71590 -0.30517578125 +71591 -0.36212158203125 +71592 -0.39141845703125 +71593 -0.35528564453125 +71594 -0.249969482421875 +71595 -0.092864990234375 +71596 0.08905029296875 +71597 0.2352294921875 +71598 0.318817138671875 +71599 0.358642578125 +71600 0.347747802734375 +71601 0.28564453125 +71602 0.223175048828125 +71603 0.196746826171875 +71604 0.179840087890625 +71605 0.155548095703125 +71606 0.151214599609375 +71607 0.156951904296875 +71608 0.13177490234375 +71609 0.100799560546875 +71610 0.087127685546875 +71611 0.05487060546875 +71612 -0.009002685546875 +71613 -0.10400390625 +71614 -0.229400634765625 +71615 -0.35552978515625 +71616 -0.441925048828125 +71617 -0.473846435546875 +71618 -0.464813232421875 +71619 -0.419097900390625 +71620 -0.334320068359375 +71621 -0.227935791015625 +71622 -0.12347412109375 +71623 -0.02764892578125 +71624 0.077667236328125 +71625 0.2132568359375 +71626 0.38885498046875 +71627 0.582794189453125 +71628 0.734039306640625 +71629 0.800140380859375 +71630 0.7783203125 +71631 0.6651611328125 +71632 0.45965576171875 +71633 0.199188232421875 +71634 -0.050689697265625 +71635 -0.23297119140625 +71636 -0.33013916015625 +71637 -0.368408203125 +71638 -0.378936767578125 +71639 -0.376983642578125 +71640 -0.37969970703125 +71641 -0.391510009765625 +71642 -0.385345458984375 +71643 -0.3419189453125 +71644 -0.28289794921875 +71645 -0.251617431640625 +71646 -0.266143798828125 +71647 -0.273345947265625 +71648 -0.216796875 +71649 -0.128265380859375 +71650 -0.068145751953125 +71651 -0.0430908203125 +71652 -0.024444580078125 +71653 0.020721435546875 +71654 0.124481201171875 +71655 0.25787353515625 +71656 0.379119873046875 +71657 0.47991943359375 +71658 0.5281982421875 +71659 0.511138916015625 +71660 0.456207275390625 +71661 0.407470703125 +71662 0.383758544921875 +71663 0.35687255859375 +71664 0.31182861328125 +71665 0.250885009765625 +71666 0.1654052734375 +71667 0.035247802734375 +71668 -0.142059326171875 +71669 -0.33563232421875 +71670 -0.5345458984375 +71671 -0.72186279296875 +71672 -0.836669921875 +71673 -0.8326416015625 +71674 -0.7296142578125 +71675 -0.582550048828125 +71676 -0.440093994140625 +71677 -0.324310302734375 +71678 -0.20147705078125 +71679 -0.044647216796875 +71680 0.103973388671875 +71681 0.202392578125 +71682 0.264495849609375 +71683 0.338897705078125 +71684 0.443817138671875 +71685 0.545074462890625 +71686 0.6173095703125 +71687 0.6524658203125 +71688 0.66339111328125 +71689 0.6561279296875 +71690 0.606781005859375 +71691 0.501190185546875 +71692 0.352783203125 +71693 0.176544189453125 +71694 -0.034820556640625 +71695 -0.258209228515625 +71696 -0.44244384765625 +71697 -0.5753173828125 +71698 -0.65203857421875 +71699 -0.641632080078125 +71700 -0.562164306640625 +71701 -0.458038330078125 +71702 -0.350555419921875 +71703 -0.260528564453125 +71704 -0.192108154296875 +71705 -0.141937255859375 +71706 -0.1021728515625 +71707 -0.062896728515625 +71708 -0.011932373046875 +71709 0.062835693359375 +71710 0.148712158203125 +71711 0.241729736328125 +71712 0.34912109375 +71713 0.457305908203125 +71714 0.54388427734375 +71715 0.5728759765625 +71716 0.506591796875 +71717 0.351226806640625 +71718 0.146514892578125 +71719 -0.05523681640625 +71720 -0.21624755859375 +71721 -0.334930419921875 +71722 -0.402984619140625 +71723 -0.4412841796875 +71724 -0.49578857421875 +71725 -0.5601806640625 +71726 -0.600738525390625 +71727 -0.584228515625 +71728 -0.47930908203125 +71729 -0.27935791015625 +71730 -0.0089111328125 +71731 0.268798828125 +71732 0.482818603515625 +71733 0.60369873046875 +71734 0.650421142578125 +71735 0.66400146484375 +71736 0.6414794921875 +71737 0.572540283203125 +71738 0.498138427734375 +71739 0.439453125 +71740 0.375518798828125 +71741 0.274505615234375 +71742 0.1087646484375 +71743 -0.099395751953125 +71744 -0.3182373046875 +71745 -0.5489501953125 +71746 -0.7738037109375 +71747 -0.86383056640625 +71748 -0.870391845703125 +71749 -0.86895751953125 +71750 -0.861053466796875 +71751 -0.765869140625 +71752 -0.5301513671875 +71753 -0.214691162109375 +71754 0.137359619140625 +71755 0.474822998046875 +71756 0.76239013671875 +71757 0.867462158203125 +71758 0.870361328125 +71759 0.86480712890625 +71760 0.831817626953125 +71761 0.677581787109375 +71762 0.495880126953125 +71763 0.30767822265625 +71764 0.116180419921875 +71765 -0.110748291015625 +71766 -0.381805419921875 +71767 -0.6572265625 +71768 -0.857421875 +71769 -0.870391845703125 +71770 -0.870391845703125 +71771 -0.86444091796875 +71772 -0.85723876953125 +71773 -0.790008544921875 +71774 -0.62847900390625 +71775 -0.3956298828125 +71776 -0.126708984375 +71777 0.150115966796875 +71778 0.424041748046875 +71779 0.670623779296875 +71780 0.854522705078125 +71781 0.866485595703125 +71782 0.86920166015625 +71783 0.8653564453125 +71784 0.857147216796875 +71785 0.766845703125 +71786 0.628509521484375 +71787 0.462127685546875 +71788 0.297210693359375 +71789 0.14862060546875 +71790 -0.00537109375 +71791 -0.15753173828125 +71792 -0.31304931640625 +71793 -0.48876953125 +71794 -0.6416015625 +71795 -0.751373291015625 +71796 -0.84619140625 +71797 -0.861297607421875 +71798 -0.863250732421875 +71799 -0.856597900390625 +71800 -0.7498779296875 +71801 -0.624542236328125 +71802 -0.47808837890625 +71803 -0.253387451171875 +71804 0.003692626953125 +71805 0.2257080078125 +71806 0.427154541015625 +71807 0.643218994140625 +71808 0.855926513671875 +71809 0.870361328125 +71810 0.870361328125 +71811 0.862762451171875 +71812 0.79669189453125 +71813 0.595794677734375 +71814 0.362152099609375 +71815 0.1270751953125 +71816 -0.086944580078125 +71817 -0.2784423828125 +71818 -0.484832763671875 +71819 -0.729583740234375 +71820 -0.86688232421875 +71821 -0.870391845703125 +71822 -0.86859130859375 +71823 -0.86279296875 +71824 -0.817962646484375 +71825 -0.6116943359375 +71826 -0.3128662109375 +71827 0.039398193359375 +71828 0.422821044921875 +71829 0.805145263671875 +71830 0.870361328125 +71831 0.870361328125 +71832 0.860015869140625 +71833 0.727935791015625 +71834 0.48114013671875 +71835 0.2059326171875 +71836 -0.06103515625 +71837 -0.29913330078125 +71838 -0.516204833984375 +71839 -0.7252197265625 +71840 -0.85980224609375 +71841 -0.870391845703125 +71842 -0.870391845703125 +71843 -0.858062744140625 +71844 -0.673004150390625 +71845 -0.42694091796875 +71846 -0.2100830078125 +71847 -0.0362548828125 +71848 0.10943603515625 +71849 0.23516845703125 +71850 0.373687744140625 +71851 0.517791748046875 +71852 0.602783203125 +71853 0.635711669921875 +71854 0.655181884765625 +71855 0.65948486328125 +71856 0.651275634765625 +71857 0.61846923828125 +71858 0.53753662109375 +71859 0.404144287109375 +71860 0.22186279296875 +71861 0.003997802734375 +71862 -0.22100830078125 +71863 -0.42449951171875 +71864 -0.579833984375 +71865 -0.641876220703125 +71866 -0.6177978515625 +71867 -0.575531005859375 +71868 -0.526336669921875 +71869 -0.42645263671875 +71870 -0.2581787109375 +71871 -0.068695068359375 +71872 0.09222412109375 +71873 0.232147216796875 +71874 0.3509521484375 +71875 0.410064697265625 +71876 0.372955322265625 +71877 0.2554931640625 +71878 0.10711669921875 +71879 -0.052886962890625 +71880 -0.186279296875 +71881 -0.23291015625 +71882 -0.209442138671875 +71883 -0.174163818359375 +71884 -0.126739501953125 +71885 -0.048126220703125 +71886 0.0426025390625 +71887 0.10748291015625 +71888 0.1409912109375 +71889 0.19708251953125 +71890 0.273651123046875 +71891 0.31768798828125 +71892 0.341094970703125 +71893 0.368011474609375 +71894 0.37249755859375 +71895 0.30072021484375 +71896 0.1517333984375 +71897 -0.01470947265625 +71898 -0.1883544921875 +71899 -0.372711181640625 +71900 -0.51397705078125 +71901 -0.57177734375 +71902 -0.53948974609375 +71903 -0.43511962890625 +71904 -0.2962646484375 +71905 -0.161102294921875 +71906 -0.0435791015625 +71907 0.060394287109375 +71908 0.13665771484375 +71909 0.170135498046875 +71910 0.16552734375 +71911 0.15728759765625 +71912 0.150787353515625 +71913 0.12200927734375 +71914 0.080108642578125 +71915 0.05126953125 +71916 0.062896728515625 +71917 0.09271240234375 +71918 0.092987060546875 +71919 0.07855224609375 +71920 0.06427001953125 +71921 0.0347900390625 +71922 -0.01171875 +71923 -0.056060791015625 +71924 -0.055511474609375 +71925 -0.010467529296875 +71926 0.02508544921875 +71927 0.025665283203125 +71928 0.017333984375 +71929 0.00189208984375 +71930 -0.03173828125 +71931 -0.071502685546875 +71932 -0.13543701171875 +71933 -0.219970703125 +71934 -0.300506591796875 +71935 -0.376312255859375 +71936 -0.416107177734375 +71937 -0.371124267578125 +71938 -0.242279052734375 +71939 -0.069732666015625 +71940 0.125640869140625 +71941 0.31268310546875 +71942 0.45501708984375 +71943 0.554779052734375 +71944 0.61065673828125 +71945 0.610931396484375 +71946 0.531463623046875 +71947 0.3883056640625 +71948 0.23468017578125 +71949 0.095245361328125 +71950 -0.00396728515625 +71951 -0.04852294921875 +71952 -0.055145263671875 +71953 -0.0758056640625 +71954 -0.138702392578125 +71955 -0.209197998046875 +71956 -0.289031982421875 +71957 -0.37884521484375 +71958 -0.456329345703125 +71959 -0.51641845703125 +71960 -0.519287109375 +71961 -0.458251953125 +71962 -0.384796142578125 +71963 -0.323699951171875 +71964 -0.269287109375 +71965 -0.1951904296875 +71966 -0.100006103515625 +71967 -0.01055908203125 +71968 0.1033935546875 +71969 0.24908447265625 +71970 0.373199462890625 +71971 0.45806884765625 +71972 0.511474609375 +71973 0.565399169921875 +71974 0.61138916015625 +71975 0.5897216796875 +71976 0.4906005859375 +71977 0.33148193359375 +71978 0.147796630859375 +71979 -0.01873779296875 +71980 -0.140289306640625 +71981 -0.191986083984375 +71982 -0.184295654296875 +71983 -0.161834716796875 +71984 -0.166595458984375 +71985 -0.19390869140625 +71986 -0.22442626953125 +71987 -0.279754638671875 +71988 -0.3389892578125 +71989 -0.3543701171875 +71990 -0.348175048828125 +71991 -0.32598876953125 +71992 -0.2581787109375 +71993 -0.139801025390625 +71994 0.014617919921875 +71995 0.144378662109375 +71996 0.221038818359375 +71997 0.27069091796875 +71998 0.294036865234375 +71999 0.311767578125 +72000 0.339141845703125 +72001 0.360260009765625 +72002 0.360504150390625 +72003 0.308380126953125 +72004 0.18170166015625 +72005 0.0047607421875 +72006 -0.17559814453125 +72007 -0.3143310546875 +72008 -0.36785888671875 +72009 -0.36248779296875 +72010 -0.343536376953125 +72011 -0.3018798828125 +72012 -0.231414794921875 +72013 -0.117645263671875 +72014 0.007049560546875 +72015 0.087982177734375 +72016 0.13946533203125 +72017 0.17425537109375 +72018 0.188201904296875 +72019 0.171234130859375 +72020 0.118438720703125 +72021 0.05706787109375 +72022 -0.010711669921875 +72023 -0.0914306640625 +72024 -0.162322998046875 +72025 -0.194549560546875 +72026 -0.1492919921875 +72027 -0.02166748046875 +72028 0.124053955078125 +72029 0.211151123046875 +72030 0.240447998046875 +72031 0.242218017578125 +72032 0.2257080078125 +72033 0.194366455078125 +72034 0.115509033203125 +72035 0.0128173828125 +72036 -0.053802490234375 +72037 -0.110626220703125 +72038 -0.199493408203125 +72039 -0.29437255859375 +72040 -0.33221435546875 +72041 -0.27972412109375 +72042 -0.185333251953125 +72043 -0.128204345703125 +72044 -0.115692138671875 +72045 -0.116455078125 +72046 -0.105926513671875 +72047 -0.053955078125 +72048 0.048797607421875 +72049 0.157318115234375 +72050 0.212005615234375 +72051 0.218475341796875 +72052 0.23724365234375 +72053 0.30535888671875 +72054 0.38128662109375 +72055 0.404449462890625 +72056 0.3944091796875 +72057 0.3885498046875 +72058 0.362640380859375 +72059 0.27362060546875 +72060 0.11712646484375 +72061 -0.054901123046875 +72062 -0.19085693359375 +72063 -0.28570556640625 +72064 -0.339263916015625 +72065 -0.3775634765625 +72066 -0.445709228515625 +72067 -0.535064697265625 +72068 -0.629058837890625 +72069 -0.697601318359375 +72070 -0.70391845703125 +72071 -0.6424560546875 +72072 -0.491241455078125 +72073 -0.265716552734375 +72074 -0.023712158203125 +72075 0.201751708984375 +72076 0.375823974609375 +72077 0.485076904296875 +72078 0.56884765625 +72079 0.634765625 +72080 0.63763427734375 +72081 0.5660400390625 +72082 0.4720458984375 +72083 0.40692138671875 +72084 0.3778076171875 +72085 0.376953125 +72086 0.371978759765625 +72087 0.313140869140625 +72088 0.184417724609375 +72089 0.011199951171875 +72090 -0.171051025390625 +72091 -0.33740234375 +72092 -0.47198486328125 +72093 -0.560394287109375 +72094 -0.58056640625 +72095 -0.54754638671875 +72096 -0.508575439453125 +72097 -0.459503173828125 +72098 -0.394378662109375 +72099 -0.35260009765625 +72100 -0.31170654296875 +72101 -0.197418212890625 +72102 -0.007965087890625 +72103 0.207489013671875 +72104 0.409210205078125 +72105 0.57208251953125 +72106 0.66595458984375 +72107 0.65875244140625 +72108 0.56744384765625 +72109 0.431396484375 +72110 0.29443359375 +72111 0.182464599609375 +72112 0.06365966796875 +72113 -0.075958251953125 +72114 -0.189422607421875 +72115 -0.271942138671875 +72116 -0.342529296875 +72117 -0.364166259765625 +72118 -0.327239990234375 +72119 -0.2769775390625 +72120 -0.253692626953125 +72121 -0.24365234375 +72122 -0.1983642578125 +72123 -0.116241455078125 +72124 -0.036834716796875 +72125 0.034881591796875 +72126 0.09124755859375 +72127 0.10888671875 +72128 0.125518798828125 +72129 0.15771484375 +72130 0.17828369140625 +72131 0.17108154296875 +72132 0.129974365234375 +72133 0.082427978515625 +72134 0.027679443359375 +72135 -0.065643310546875 +72136 -0.15936279296875 +72137 -0.21307373046875 +72138 -0.234649658203125 +72139 -0.2001953125 +72140 -0.119171142578125 +72141 -0.024749755859375 +72142 0.085784912109375 +72143 0.178131103515625 +72144 0.215576171875 +72145 0.211456298828125 +72146 0.17523193359375 +72147 0.128753662109375 +72148 0.1019287109375 +72149 0.0743408203125 +72150 0.04327392578125 +72151 0.038177490234375 +72152 0.076263427734375 +72153 0.14105224609375 +72154 0.186431884765625 +72155 0.188812255859375 +72156 0.1390380859375 +72157 0.041778564453125 +72158 -0.079437255859375 +72159 -0.219390869140625 +72160 -0.367828369140625 +72161 -0.494873046875 +72162 -0.556243896484375 +72163 -0.508697509765625 +72164 -0.3756103515625 +72165 -0.218902587890625 +72166 -0.063751220703125 +72167 0.091552734375 +72168 0.23602294921875 +72169 0.342987060546875 +72170 0.39520263671875 +72171 0.389373779296875 +72172 0.324249267578125 +72173 0.224090576171875 +72174 0.124267578125 +72175 0.037078857421875 +72176 -0.010101318359375 +72177 -0.019439697265625 +72178 -0.022796630859375 +72179 -0.001556396484375 +72180 0.056304931640625 +72181 0.106719970703125 +72182 0.096893310546875 +72183 0.042694091796875 +72184 -0.018035888671875 +72185 -0.07586669921875 +72186 -0.11944580078125 +72187 -0.15972900390625 +72188 -0.202606201171875 +72189 -0.24859619140625 +72190 -0.30517578125 +72191 -0.36212158203125 +72192 -0.39141845703125 +72193 -0.35528564453125 +72194 -0.249969482421875 +72195 -0.092864990234375 +72196 0.08905029296875 +72197 0.2352294921875 +72198 0.318817138671875 +72199 0.358642578125 +72200 0.347747802734375 +72201 0.28564453125 +72202 0.223175048828125 +72203 0.196746826171875 +72204 0.179840087890625 +72205 0.155548095703125 +72206 0.151214599609375 +72207 0.156951904296875 +72208 0.13177490234375 +72209 0.100799560546875 +72210 0.087127685546875 +72211 0.05487060546875 +72212 -0.009002685546875 +72213 -0.10400390625 +72214 -0.229400634765625 +72215 -0.35552978515625 +72216 -0.441925048828125 +72217 -0.473846435546875 +72218 -0.464813232421875 +72219 -0.419097900390625 +72220 -0.334320068359375 +72221 -0.227935791015625 +72222 -0.12347412109375 +72223 -0.02764892578125 +72224 0.077667236328125 +72225 0.2132568359375 +72226 0.38885498046875 +72227 0.582794189453125 +72228 0.734039306640625 +72229 0.800140380859375 +72230 0.7783203125 +72231 0.6651611328125 +72232 0.45965576171875 +72233 0.199188232421875 +72234 -0.050689697265625 +72235 -0.23297119140625 +72236 -0.33013916015625 +72237 -0.368408203125 +72238 -0.378936767578125 +72239 -0.376983642578125 +72240 -0.37969970703125 +72241 -0.391510009765625 +72242 -0.385345458984375 +72243 -0.3419189453125 +72244 -0.28289794921875 +72245 -0.251617431640625 +72246 -0.266143798828125 +72247 -0.273345947265625 +72248 -0.216796875 +72249 -0.128265380859375 +72250 -0.068145751953125 +72251 -0.0430908203125 +72252 -0.024444580078125 +72253 0.020721435546875 +72254 0.124481201171875 +72255 0.25787353515625 +72256 0.379119873046875 +72257 0.47991943359375 +72258 0.5281982421875 +72259 0.511138916015625 +72260 0.456207275390625 +72261 0.407470703125 +72262 0.383758544921875 +72263 0.35687255859375 +72264 0.31182861328125 +72265 0.250885009765625 +72266 0.1654052734375 +72267 0.035247802734375 +72268 -0.142059326171875 +72269 -0.33563232421875 +72270 -0.5345458984375 +72271 -0.72186279296875 +72272 -0.836669921875 +72273 -0.8326416015625 +72274 -0.7296142578125 +72275 -0.582550048828125 +72276 -0.440093994140625 +72277 -0.324310302734375 +72278 -0.20147705078125 +72279 -0.044647216796875 +72280 0.103973388671875 +72281 0.202392578125 +72282 0.264495849609375 +72283 0.338897705078125 +72284 0.443817138671875 +72285 0.545074462890625 +72286 0.6173095703125 +72287 0.6524658203125 +72288 0.66339111328125 +72289 0.6561279296875 +72290 0.606781005859375 +72291 0.501190185546875 +72292 0.352783203125 +72293 0.176544189453125 +72294 -0.034820556640625 +72295 -0.258209228515625 +72296 -0.44244384765625 +72297 -0.5753173828125 +72298 -0.65203857421875 +72299 -0.641632080078125 +72300 -0.562164306640625 +72301 -0.458038330078125 +72302 -0.350555419921875 +72303 -0.260528564453125 +72304 -0.192108154296875 +72305 -0.141937255859375 +72306 -0.1021728515625 +72307 -0.062896728515625 +72308 -0.011932373046875 +72309 0.062835693359375 +72310 0.148712158203125 +72311 0.241729736328125 +72312 0.34912109375 +72313 0.457305908203125 +72314 0.54388427734375 +72315 0.5728759765625 +72316 0.506591796875 +72317 0.351226806640625 +72318 0.146514892578125 +72319 -0.05523681640625 +72320 -0.21624755859375 +72321 -0.334930419921875 +72322 -0.402984619140625 +72323 -0.4412841796875 +72324 -0.49578857421875 +72325 -0.5601806640625 +72326 -0.600738525390625 +72327 -0.584228515625 +72328 -0.47930908203125 +72329 -0.27935791015625 +72330 -0.0089111328125 +72331 0.268798828125 +72332 0.482818603515625 +72333 0.60369873046875 +72334 0.650421142578125 +72335 0.66400146484375 +72336 0.6414794921875 +72337 0.572540283203125 +72338 0.498138427734375 +72339 0.439453125 +72340 0.375518798828125 +72341 0.274505615234375 +72342 0.1087646484375 +72343 -0.099395751953125 +72344 -0.3182373046875 +72345 -0.5489501953125 +72346 -0.7738037109375 +72347 -0.86383056640625 +72348 -0.870391845703125 +72349 -0.86895751953125 +72350 -0.861053466796875 +72351 -0.765869140625 +72352 -0.5301513671875 +72353 -0.214691162109375 +72354 0.137359619140625 +72355 0.474822998046875 +72356 0.76239013671875 +72357 0.867462158203125 +72358 0.870361328125 +72359 0.86480712890625 +72360 0.831817626953125 +72361 0.677581787109375 +72362 0.495880126953125 +72363 0.30767822265625 +72364 0.116180419921875 +72365 -0.110748291015625 +72366 -0.381805419921875 +72367 -0.6572265625 +72368 -0.857421875 +72369 -0.870391845703125 +72370 -0.870391845703125 +72371 -0.86444091796875 +72372 -0.85723876953125 +72373 -0.790008544921875 +72374 -0.62847900390625 +72375 -0.3956298828125 +72376 -0.126708984375 +72377 0.150115966796875 +72378 0.424041748046875 +72379 0.670623779296875 +72380 0.854522705078125 +72381 0.866485595703125 +72382 0.86920166015625 +72383 0.8653564453125 +72384 0.857147216796875 +72385 0.766845703125 +72386 0.628509521484375 +72387 0.462127685546875 +72388 0.297210693359375 +72389 0.14862060546875 +72390 -0.00537109375 +72391 -0.15753173828125 +72392 -0.31304931640625 +72393 -0.48876953125 +72394 -0.6416015625 +72395 -0.751373291015625 +72396 -0.84619140625 +72397 -0.861297607421875 +72398 -0.863250732421875 +72399 -0.856597900390625 +72400 -0.7498779296875 +72401 -0.624542236328125 +72402 -0.47808837890625 +72403 -0.253387451171875 +72404 0.003692626953125 +72405 0.2257080078125 +72406 0.427154541015625 +72407 0.643218994140625 +72408 0.855926513671875 +72409 0.870361328125 +72410 0.870361328125 +72411 0.862762451171875 +72412 0.79669189453125 +72413 0.595794677734375 +72414 0.362152099609375 +72415 0.1270751953125 +72416 -0.086944580078125 +72417 -0.2784423828125 +72418 -0.484832763671875 +72419 -0.729583740234375 +72420 -0.86688232421875 +72421 -0.870391845703125 +72422 -0.86859130859375 +72423 -0.86279296875 +72424 -0.817962646484375 +72425 -0.6116943359375 +72426 -0.3128662109375 +72427 0.039398193359375 +72428 0.422821044921875 +72429 0.805145263671875 +72430 0.870361328125 +72431 0.870361328125 +72432 0.860015869140625 +72433 0.727935791015625 +72434 0.48114013671875 +72435 0.2059326171875 +72436 -0.06103515625 +72437 -0.29913330078125 +72438 -0.516204833984375 +72439 -0.7252197265625 +72440 -0.85980224609375 +72441 -0.870391845703125 +72442 -0.870391845703125 +72443 -0.858062744140625 +72444 -0.673004150390625 +72445 -0.42694091796875 +72446 -0.2100830078125 +72447 -0.0362548828125 +72448 0.10943603515625 +72449 0.23516845703125 +72450 0.373687744140625 +72451 0.517791748046875 +72452 0.602783203125 +72453 0.635711669921875 +72454 0.655181884765625 +72455 0.65948486328125 +72456 0.651275634765625 +72457 0.61846923828125 +72458 0.53753662109375 +72459 0.404144287109375 +72460 0.22186279296875 +72461 0.003997802734375 +72462 -0.22100830078125 +72463 -0.42449951171875 +72464 -0.579833984375 +72465 -0.641876220703125 +72466 -0.6177978515625 +72467 -0.575531005859375 +72468 -0.526336669921875 +72469 -0.42645263671875 +72470 -0.2581787109375 +72471 -0.068695068359375 +72472 0.09222412109375 +72473 0.232147216796875 +72474 0.3509521484375 +72475 0.410064697265625 +72476 0.372955322265625 +72477 0.2554931640625 +72478 0.10711669921875 +72479 -0.052886962890625 +72480 -0.186279296875 +72481 -0.23291015625 +72482 -0.209442138671875 +72483 -0.174163818359375 +72484 -0.126739501953125 +72485 -0.048126220703125 +72486 0.0426025390625 +72487 0.10748291015625 +72488 0.1409912109375 +72489 0.19708251953125 +72490 0.273651123046875 +72491 0.31768798828125 +72492 0.341094970703125 +72493 0.368011474609375 +72494 0.37249755859375 +72495 0.30072021484375 +72496 0.1517333984375 +72497 -0.01470947265625 +72498 -0.1883544921875 +72499 -0.372711181640625 +72500 -0.51397705078125 +72501 -0.57177734375 +72502 -0.53948974609375 +72503 -0.43511962890625 +72504 -0.2962646484375 +72505 -0.161102294921875 +72506 -0.0435791015625 +72507 0.060394287109375 +72508 0.13665771484375 +72509 0.170135498046875 +72510 0.16552734375 +72511 0.15728759765625 +72512 0.150787353515625 +72513 0.12200927734375 +72514 0.080108642578125 +72515 0.05126953125 +72516 0.062896728515625 +72517 0.09271240234375 +72518 0.092987060546875 +72519 0.07855224609375 +72520 0.06427001953125 +72521 0.0347900390625 +72522 -0.01171875 +72523 -0.056060791015625 +72524 -0.055511474609375 +72525 -0.010467529296875 +72526 0.02508544921875 +72527 0.025665283203125 +72528 0.017333984375 +72529 0.00189208984375 +72530 -0.03173828125 +72531 -0.071502685546875 +72532 -0.13543701171875 +72533 -0.219970703125 +72534 -0.300506591796875 +72535 -0.376312255859375 +72536 -0.416107177734375 +72537 -0.371124267578125 +72538 -0.242279052734375 +72539 -0.069732666015625 +72540 0.125640869140625 +72541 0.31268310546875 +72542 0.45501708984375 +72543 0.554779052734375 +72544 0.61065673828125 +72545 0.610931396484375 +72546 0.531463623046875 +72547 0.3883056640625 +72548 0.23468017578125 +72549 0.095245361328125 +72550 -0.00396728515625 +72551 -0.04852294921875 +72552 -0.055145263671875 +72553 -0.0758056640625 +72554 -0.138702392578125 +72555 -0.209197998046875 +72556 -0.289031982421875 +72557 -0.37884521484375 +72558 -0.456329345703125 +72559 -0.51641845703125 +72560 -0.519287109375 +72561 -0.458251953125 +72562 -0.384796142578125 +72563 -0.323699951171875 +72564 -0.269287109375 +72565 -0.1951904296875 +72566 -0.100006103515625 +72567 -0.01055908203125 +72568 0.1033935546875 +72569 0.24908447265625 +72570 0.373199462890625 +72571 0.45806884765625 +72572 0.511474609375 +72573 0.565399169921875 +72574 0.61138916015625 +72575 0.5897216796875 +72576 0.4906005859375 +72577 0.33148193359375 +72578 0.147796630859375 +72579 -0.01873779296875 +72580 -0.140289306640625 +72581 -0.191986083984375 +72582 -0.184295654296875 +72583 -0.161834716796875 +72584 -0.166595458984375 +72585 -0.19390869140625 +72586 -0.22442626953125 +72587 -0.279754638671875 +72588 -0.3389892578125 +72589 -0.3543701171875 +72590 -0.348175048828125 +72591 -0.32598876953125 +72592 -0.2581787109375 +72593 -0.139801025390625 +72594 0.014617919921875 +72595 0.144378662109375 +72596 0.221038818359375 +72597 0.27069091796875 +72598 0.294036865234375 +72599 0.311767578125 +72600 0.339141845703125 +72601 0.360260009765625 +72602 0.360504150390625 +72603 0.308380126953125 +72604 0.18170166015625 +72605 0.0047607421875 +72606 -0.17559814453125 +72607 -0.3143310546875 +72608 -0.36785888671875 +72609 -0.36248779296875 +72610 -0.343536376953125 +72611 -0.3018798828125 +72612 -0.231414794921875 +72613 -0.117645263671875 +72614 0.007049560546875 +72615 0.087982177734375 +72616 0.13946533203125 +72617 0.17425537109375 +72618 0.188201904296875 +72619 0.171234130859375 +72620 0.118438720703125 +72621 0.05706787109375 +72622 -0.010711669921875 +72623 -0.0914306640625 +72624 -0.162322998046875 +72625 -0.194549560546875 +72626 -0.1492919921875 +72627 -0.02166748046875 +72628 0.124053955078125 +72629 0.211151123046875 +72630 0.240447998046875 +72631 0.242218017578125 +72632 0.2257080078125 +72633 0.194366455078125 +72634 0.115509033203125 +72635 0.0128173828125 +72636 -0.053802490234375 +72637 -0.110626220703125 +72638 -0.199493408203125 +72639 -0.29437255859375 +72640 -0.33221435546875 +72641 -0.27972412109375 +72642 -0.185333251953125 +72643 -0.128204345703125 +72644 -0.115692138671875 +72645 -0.116455078125 +72646 -0.105926513671875 +72647 -0.053955078125 +72648 0.048797607421875 +72649 0.157318115234375 +72650 0.212005615234375 +72651 0.218475341796875 +72652 0.23724365234375 +72653 0.30535888671875 +72654 0.38128662109375 +72655 0.404449462890625 +72656 0.3944091796875 +72657 0.3885498046875 +72658 0.362640380859375 +72659 0.27362060546875 +72660 0.11712646484375 +72661 -0.054901123046875 +72662 -0.19085693359375 +72663 -0.28570556640625 +72664 -0.339263916015625 +72665 -0.3775634765625 +72666 -0.445709228515625 +72667 -0.535064697265625 +72668 -0.629058837890625 +72669 -0.697601318359375 +72670 -0.70391845703125 +72671 -0.6424560546875 +72672 -0.491241455078125 +72673 -0.265716552734375 +72674 -0.023712158203125 +72675 0.201751708984375 +72676 0.375823974609375 +72677 0.485076904296875 +72678 0.56884765625 +72679 0.634765625 +72680 0.63763427734375 +72681 0.5660400390625 +72682 0.4720458984375 +72683 0.40692138671875 +72684 0.3778076171875 +72685 0.376953125 +72686 0.371978759765625 +72687 0.313140869140625 +72688 0.184417724609375 +72689 0.011199951171875 +72690 -0.171051025390625 +72691 -0.33740234375 +72692 -0.47198486328125 +72693 -0.560394287109375 +72694 -0.58056640625 +72695 -0.54754638671875 +72696 -0.508575439453125 +72697 -0.459503173828125 +72698 -0.394378662109375 +72699 -0.35260009765625 +72700 -0.31170654296875 +72701 -0.197418212890625 +72702 -0.007965087890625 +72703 0.207489013671875 +72704 0.409210205078125 +72705 0.57208251953125 +72706 0.66595458984375 +72707 0.65875244140625 +72708 0.56744384765625 +72709 0.431396484375 +72710 0.29443359375 +72711 0.182464599609375 +72712 0.06365966796875 +72713 -0.075958251953125 +72714 -0.189422607421875 +72715 -0.271942138671875 +72716 -0.342529296875 +72717 -0.364166259765625 +72718 -0.327239990234375 +72719 -0.2769775390625 +72720 -0.253692626953125 +72721 -0.24365234375 +72722 -0.1983642578125 +72723 -0.116241455078125 +72724 -0.036834716796875 +72725 0.034881591796875 +72726 0.09124755859375 +72727 0.10888671875 +72728 0.125518798828125 +72729 0.15771484375 +72730 0.17828369140625 +72731 0.17108154296875 +72732 0.129974365234375 +72733 0.082427978515625 +72734 0.027679443359375 +72735 -0.065643310546875 +72736 -0.15936279296875 +72737 -0.21307373046875 +72738 -0.234649658203125 +72739 -0.2001953125 +72740 -0.119171142578125 +72741 -0.024749755859375 +72742 0.085784912109375 +72743 0.178131103515625 +72744 0.215576171875 +72745 0.211456298828125 +72746 0.17523193359375 +72747 0.128753662109375 +72748 0.1019287109375 +72749 0.0743408203125 +72750 0.04327392578125 +72751 0.038177490234375 +72752 0.076263427734375 +72753 0.14105224609375 +72754 0.186431884765625 +72755 0.188812255859375 +72756 0.1390380859375 +72757 0.041778564453125 +72758 -0.079437255859375 +72759 -0.219390869140625 +72760 -0.367828369140625 +72761 -0.494873046875 +72762 -0.556243896484375 +72763 -0.508697509765625 +72764 -0.3756103515625 +72765 -0.218902587890625 +72766 -0.063751220703125 +72767 0.091552734375 +72768 0.23602294921875 +72769 0.342987060546875 +72770 0.39520263671875 +72771 0.389373779296875 +72772 0.324249267578125 +72773 0.224090576171875 +72774 0.124267578125 +72775 0.037078857421875 +72776 -0.010101318359375 +72777 -0.019439697265625 +72778 -0.022796630859375 +72779 -0.001556396484375 +72780 0.056304931640625 +72781 0.106719970703125 +72782 0.096893310546875 +72783 0.042694091796875 +72784 -0.018035888671875 +72785 -0.07586669921875 +72786 -0.11944580078125 +72787 -0.15972900390625 +72788 -0.202606201171875 +72789 -0.24859619140625 +72790 -0.30517578125 +72791 -0.36212158203125 +72792 -0.39141845703125 +72793 -0.35528564453125 +72794 -0.249969482421875 +72795 -0.092864990234375 +72796 0.08905029296875 +72797 0.2352294921875 +72798 0.318817138671875 +72799 0.358642578125 +72800 0.347747802734375 +72801 0.28564453125 +72802 0.223175048828125 +72803 0.196746826171875 +72804 0.179840087890625 +72805 0.155548095703125 +72806 0.151214599609375 +72807 0.156951904296875 +72808 0.13177490234375 +72809 0.100799560546875 +72810 0.087127685546875 +72811 0.05487060546875 +72812 -0.009002685546875 +72813 -0.10400390625 +72814 -0.229400634765625 +72815 -0.35552978515625 +72816 -0.441925048828125 +72817 -0.473846435546875 +72818 -0.464813232421875 +72819 -0.419097900390625 +72820 -0.334320068359375 +72821 -0.227935791015625 +72822 -0.12347412109375 +72823 -0.02764892578125 +72824 0.077667236328125 +72825 0.2132568359375 +72826 0.38885498046875 +72827 0.582794189453125 +72828 0.734039306640625 +72829 0.800140380859375 +72830 0.7783203125 +72831 0.6651611328125 +72832 0.45965576171875 +72833 0.199188232421875 +72834 -0.050689697265625 +72835 -0.23297119140625 +72836 -0.33013916015625 +72837 -0.368408203125 +72838 -0.378936767578125 +72839 -0.376983642578125 +72840 -0.37969970703125 +72841 -0.391510009765625 +72842 -0.385345458984375 +72843 -0.3419189453125 +72844 -0.28289794921875 +72845 -0.251617431640625 +72846 -0.266143798828125 +72847 -0.273345947265625 +72848 -0.216796875 +72849 -0.128265380859375 +72850 -0.068145751953125 +72851 -0.0430908203125 +72852 -0.024444580078125 +72853 0.020721435546875 +72854 0.124481201171875 +72855 0.25787353515625 +72856 0.379119873046875 +72857 0.47991943359375 +72858 0.5281982421875 +72859 0.511138916015625 +72860 0.456207275390625 +72861 0.407470703125 +72862 0.383758544921875 +72863 0.35687255859375 +72864 0.31182861328125 +72865 0.250885009765625 +72866 0.1654052734375 +72867 0.035247802734375 +72868 -0.142059326171875 +72869 -0.33563232421875 +72870 -0.5345458984375 +72871 -0.72186279296875 +72872 -0.836669921875 +72873 -0.8326416015625 +72874 -0.7296142578125 +72875 -0.582550048828125 +72876 -0.440093994140625 +72877 -0.324310302734375 +72878 -0.20147705078125 +72879 -0.044647216796875 +72880 0.103973388671875 +72881 0.202392578125 +72882 0.264495849609375 +72883 0.338897705078125 +72884 0.443817138671875 +72885 0.545074462890625 +72886 0.6173095703125 +72887 0.6524658203125 +72888 0.66339111328125 +72889 0.6561279296875 +72890 0.606781005859375 +72891 0.501190185546875 +72892 0.352783203125 +72893 0.176544189453125 +72894 -0.034820556640625 +72895 -0.258209228515625 +72896 -0.44244384765625 +72897 -0.5753173828125 +72898 -0.65203857421875 +72899 -0.641632080078125 +72900 -0.562164306640625 +72901 -0.458038330078125 +72902 -0.350555419921875 +72903 -0.260528564453125 +72904 -0.192108154296875 +72905 -0.141937255859375 +72906 -0.1021728515625 +72907 -0.062896728515625 +72908 -0.011932373046875 +72909 0.062835693359375 +72910 0.148712158203125 +72911 0.241729736328125 +72912 0.34912109375 +72913 0.457305908203125 +72914 0.54388427734375 +72915 0.5728759765625 +72916 0.506591796875 +72917 0.351226806640625 +72918 0.146514892578125 +72919 -0.05523681640625 +72920 -0.21624755859375 +72921 -0.334930419921875 +72922 -0.402984619140625 +72923 -0.4412841796875 +72924 -0.49578857421875 +72925 -0.5601806640625 +72926 -0.600738525390625 +72927 -0.584228515625 +72928 -0.47930908203125 +72929 -0.27935791015625 +72930 -0.0089111328125 +72931 0.268798828125 +72932 0.482818603515625 +72933 0.60369873046875 +72934 0.650421142578125 +72935 0.66400146484375 +72936 0.6414794921875 +72937 0.572540283203125 +72938 0.498138427734375 +72939 0.439453125 +72940 0.375518798828125 +72941 0.274505615234375 +72942 0.1087646484375 +72943 -0.099395751953125 +72944 -0.3182373046875 +72945 -0.5489501953125 +72946 -0.7738037109375 +72947 -0.86383056640625 +72948 -0.870391845703125 +72949 -0.86895751953125 +72950 -0.861053466796875 +72951 -0.765869140625 +72952 -0.5301513671875 +72953 -0.214691162109375 +72954 0.137359619140625 +72955 0.474822998046875 +72956 0.76239013671875 +72957 0.867462158203125 +72958 0.870361328125 +72959 0.86480712890625 +72960 0.831817626953125 +72961 0.677581787109375 +72962 0.495880126953125 +72963 0.30767822265625 +72964 0.116180419921875 +72965 -0.110748291015625 +72966 -0.381805419921875 +72967 -0.6572265625 +72968 -0.857421875 +72969 -0.870391845703125 +72970 -0.870391845703125 +72971 -0.86444091796875 +72972 -0.85723876953125 +72973 -0.790008544921875 +72974 -0.62847900390625 +72975 -0.3956298828125 +72976 -0.126708984375 +72977 0.150115966796875 +72978 0.424041748046875 +72979 0.670623779296875 +72980 0.854522705078125 +72981 0.866485595703125 +72982 0.86920166015625 +72983 0.8653564453125 +72984 0.857147216796875 +72985 0.766845703125 +72986 0.628509521484375 +72987 0.462127685546875 +72988 0.297210693359375 +72989 0.14862060546875 +72990 -0.00537109375 +72991 -0.15753173828125 +72992 -0.31304931640625 +72993 -0.48876953125 +72994 -0.6416015625 +72995 -0.751373291015625 +72996 -0.84619140625 +72997 -0.861297607421875 +72998 -0.863250732421875 +72999 -0.856597900390625 +73000 -0.7498779296875 +73001 -0.624542236328125 +73002 -0.47808837890625 +73003 -0.253387451171875 +73004 0.003692626953125 +73005 0.2257080078125 +73006 0.427154541015625 +73007 0.643218994140625 +73008 0.855926513671875 +73009 0.870361328125 +73010 0.870361328125 +73011 0.862762451171875 +73012 0.79669189453125 +73013 0.595794677734375 +73014 0.362152099609375 +73015 0.1270751953125 +73016 -0.086944580078125 +73017 -0.2784423828125 +73018 -0.484832763671875 +73019 -0.729583740234375 +73020 -0.86688232421875 +73021 -0.870391845703125 +73022 -0.86859130859375 +73023 -0.86279296875 +73024 -0.817962646484375 +73025 -0.6116943359375 +73026 -0.3128662109375 +73027 0.039398193359375 +73028 0.422821044921875 +73029 0.805145263671875 +73030 0.870361328125 +73031 0.870361328125 +73032 0.860015869140625 +73033 0.727935791015625 +73034 0.48114013671875 +73035 0.2059326171875 +73036 -0.06103515625 +73037 -0.29913330078125 +73038 -0.516204833984375 +73039 -0.7252197265625 +73040 -0.85980224609375 +73041 -0.870391845703125 +73042 -0.870391845703125 +73043 -0.858062744140625 +73044 -0.673004150390625 +73045 -0.42694091796875 +73046 -0.2100830078125 +73047 -0.0362548828125 +73048 0.10943603515625 +73049 0.23516845703125 +73050 0.373687744140625 +73051 0.517791748046875 +73052 0.602783203125 +73053 0.635711669921875 +73054 0.655181884765625 +73055 0.65948486328125 +73056 0.651275634765625 +73057 0.61846923828125 +73058 0.53753662109375 +73059 0.404144287109375 +73060 0.22186279296875 +73061 0.003997802734375 +73062 -0.22100830078125 +73063 -0.42449951171875 +73064 -0.579833984375 +73065 -0.641876220703125 +73066 -0.6177978515625 +73067 -0.575531005859375 +73068 -0.526336669921875 +73069 -0.42645263671875 +73070 -0.2581787109375 +73071 -0.068695068359375 +73072 0.09222412109375 +73073 0.232147216796875 +73074 0.3509521484375 +73075 0.410064697265625 +73076 0.372955322265625 +73077 0.2554931640625 +73078 0.10711669921875 +73079 -0.052886962890625 +73080 -0.186279296875 +73081 -0.23291015625 +73082 -0.209442138671875 +73083 -0.174163818359375 +73084 -0.126739501953125 +73085 -0.048126220703125 +73086 0.0426025390625 +73087 0.10748291015625 +73088 0.1409912109375 +73089 0.19708251953125 +73090 0.273651123046875 +73091 0.31768798828125 +73092 0.341094970703125 +73093 0.368011474609375 +73094 0.37249755859375 +73095 0.30072021484375 +73096 0.1517333984375 +73097 -0.01470947265625 +73098 -0.1883544921875 +73099 -0.372711181640625 +73100 -0.51397705078125 +73101 -0.57177734375 +73102 -0.53948974609375 +73103 -0.43511962890625 +73104 -0.2962646484375 +73105 -0.161102294921875 +73106 -0.0435791015625 +73107 0.060394287109375 +73108 0.13665771484375 +73109 0.170135498046875 +73110 0.16552734375 +73111 0.15728759765625 +73112 0.150787353515625 +73113 0.12200927734375 +73114 0.080108642578125 +73115 0.05126953125 +73116 0.062896728515625 +73117 0.09271240234375 +73118 0.092987060546875 +73119 0.07855224609375 +73120 0.06427001953125 +73121 0.0347900390625 +73122 -0.01171875 +73123 -0.056060791015625 +73124 -0.055511474609375 +73125 -0.010467529296875 +73126 0.02508544921875 +73127 0.025665283203125 +73128 0.017333984375 +73129 0.00189208984375 +73130 -0.03173828125 +73131 -0.071502685546875 +73132 -0.13543701171875 +73133 -0.219970703125 +73134 -0.300506591796875 +73135 -0.376312255859375 +73136 -0.416107177734375 +73137 -0.371124267578125 +73138 -0.242279052734375 +73139 -0.069732666015625 +73140 0.125640869140625 +73141 0.31268310546875 +73142 0.45501708984375 +73143 0.554779052734375 +73144 0.61065673828125 +73145 0.610931396484375 +73146 0.531463623046875 +73147 0.3883056640625 +73148 0.23468017578125 +73149 0.095245361328125 +73150 -0.00396728515625 +73151 -0.04852294921875 +73152 -0.055145263671875 +73153 -0.0758056640625 +73154 -0.138702392578125 +73155 -0.209197998046875 +73156 -0.289031982421875 +73157 -0.37884521484375 +73158 -0.456329345703125 +73159 -0.51641845703125 +73160 -0.519287109375 +73161 -0.458251953125 +73162 -0.384796142578125 +73163 -0.323699951171875 +73164 -0.269287109375 +73165 -0.1951904296875 +73166 -0.100006103515625 +73167 -0.01055908203125 +73168 0.1033935546875 +73169 0.24908447265625 +73170 0.373199462890625 +73171 0.45806884765625 +73172 0.511474609375 +73173 0.565399169921875 +73174 0.61138916015625 +73175 0.5897216796875 +73176 0.4906005859375 +73177 0.33148193359375 +73178 0.147796630859375 +73179 -0.01873779296875 +73180 -0.140289306640625 +73181 -0.191986083984375 +73182 -0.184295654296875 +73183 -0.161834716796875 +73184 -0.166595458984375 +73185 -0.19390869140625 +73186 -0.22442626953125 +73187 -0.279754638671875 +73188 -0.3389892578125 +73189 -0.3543701171875 +73190 -0.348175048828125 +73191 -0.32598876953125 +73192 -0.2581787109375 +73193 -0.139801025390625 +73194 0.014617919921875 +73195 0.144378662109375 +73196 0.221038818359375 +73197 0.27069091796875 +73198 0.294036865234375 +73199 0.311767578125 +73200 0.339141845703125 +73201 0.360260009765625 +73202 0.360504150390625 +73203 0.308380126953125 +73204 0.18170166015625 +73205 0.0047607421875 +73206 -0.17559814453125 +73207 -0.3143310546875 +73208 -0.36785888671875 +73209 -0.36248779296875 +73210 -0.343536376953125 +73211 -0.3018798828125 +73212 -0.231414794921875 +73213 -0.117645263671875 +73214 0.007049560546875 +73215 0.087982177734375 +73216 0.13946533203125 +73217 0.17425537109375 +73218 0.188201904296875 +73219 0.171234130859375 +73220 0.118438720703125 +73221 0.05706787109375 +73222 -0.010711669921875 +73223 -0.0914306640625 +73224 -0.162322998046875 +73225 -0.194549560546875 +73226 -0.1492919921875 +73227 -0.02166748046875 +73228 0.124053955078125 +73229 0.211151123046875 +73230 0.240447998046875 +73231 0.242218017578125 +73232 0.2257080078125 +73233 0.194366455078125 +73234 0.115509033203125 +73235 0.0128173828125 +73236 -0.053802490234375 +73237 -0.110626220703125 +73238 -0.199493408203125 +73239 -0.29437255859375 +73240 -0.33221435546875 +73241 -0.27972412109375 +73242 -0.185333251953125 +73243 -0.128204345703125 +73244 -0.115692138671875 +73245 -0.116455078125 +73246 -0.105926513671875 +73247 -0.053955078125 +73248 0.048797607421875 +73249 0.157318115234375 +73250 0.212005615234375 +73251 0.218475341796875 +73252 0.23724365234375 +73253 0.30535888671875 +73254 0.38128662109375 +73255 0.404449462890625 +73256 0.3944091796875 +73257 0.3885498046875 +73258 0.362640380859375 +73259 0.27362060546875 +73260 0.11712646484375 +73261 -0.054901123046875 +73262 -0.19085693359375 +73263 -0.28570556640625 +73264 -0.339263916015625 +73265 -0.3775634765625 +73266 -0.445709228515625 +73267 -0.535064697265625 +73268 -0.629058837890625 +73269 -0.697601318359375 +73270 -0.70391845703125 +73271 -0.6424560546875 +73272 -0.491241455078125 +73273 -0.265716552734375 +73274 -0.023712158203125 +73275 0.201751708984375 +73276 0.375823974609375 +73277 0.485076904296875 +73278 0.56884765625 +73279 0.634765625 +73280 0.63763427734375 +73281 0.5660400390625 +73282 0.4720458984375 +73283 0.40692138671875 +73284 0.3778076171875 +73285 0.376953125 +73286 0.371978759765625 +73287 0.313140869140625 +73288 0.184417724609375 +73289 0.011199951171875 +73290 -0.171051025390625 +73291 -0.33740234375 +73292 -0.47198486328125 +73293 -0.560394287109375 +73294 -0.58056640625 +73295 -0.54754638671875 +73296 -0.508575439453125 +73297 -0.459503173828125 +73298 -0.394378662109375 +73299 -0.35260009765625 +73300 -0.31170654296875 +73301 -0.197418212890625 +73302 -0.007965087890625 +73303 0.207489013671875 +73304 0.409210205078125 +73305 0.57208251953125 +73306 0.66595458984375 +73307 0.65875244140625 +73308 0.56744384765625 +73309 0.431396484375 +73310 0.29443359375 +73311 0.182464599609375 +73312 0.06365966796875 +73313 -0.075958251953125 +73314 -0.189422607421875 +73315 -0.271942138671875 +73316 -0.342529296875 +73317 -0.364166259765625 +73318 -0.327239990234375 +73319 -0.2769775390625 +73320 -0.253692626953125 +73321 -0.24365234375 +73322 -0.1983642578125 +73323 -0.116241455078125 +73324 -0.036834716796875 +73325 0.034881591796875 +73326 0.09124755859375 +73327 0.10888671875 +73328 0.125518798828125 +73329 0.15771484375 +73330 0.17828369140625 +73331 0.17108154296875 +73332 0.129974365234375 +73333 0.082427978515625 +73334 0.027679443359375 +73335 -0.065643310546875 +73336 -0.15936279296875 +73337 -0.21307373046875 +73338 -0.234649658203125 +73339 -0.2001953125 +73340 -0.119171142578125 +73341 -0.024749755859375 +73342 0.085784912109375 +73343 0.178131103515625 +73344 0.215576171875 +73345 0.211456298828125 +73346 0.17523193359375 +73347 0.128753662109375 +73348 0.1019287109375 +73349 0.0743408203125 +73350 0.04327392578125 +73351 0.038177490234375 +73352 0.076263427734375 +73353 0.14105224609375 +73354 0.186431884765625 +73355 0.188812255859375 +73356 0.1390380859375 +73357 0.041778564453125 +73358 -0.079437255859375 +73359 -0.219390869140625 +73360 -0.367828369140625 +73361 -0.494873046875 +73362 -0.556243896484375 +73363 -0.508697509765625 +73364 -0.3756103515625 +73365 -0.218902587890625 +73366 -0.063751220703125 +73367 0.091552734375 +73368 0.23602294921875 +73369 0.342987060546875 +73370 0.39520263671875 +73371 0.389373779296875 +73372 0.324249267578125 +73373 0.224090576171875 +73374 0.124267578125 +73375 0.037078857421875 +73376 -0.010101318359375 +73377 -0.019439697265625 +73378 -0.022796630859375 +73379 -0.001556396484375 +73380 0.056304931640625 +73381 0.106719970703125 +73382 0.096893310546875 +73383 0.042694091796875 +73384 -0.018035888671875 +73385 -0.07586669921875 +73386 -0.11944580078125 +73387 -0.15972900390625 +73388 -0.202606201171875 +73389 -0.24859619140625 +73390 -0.30517578125 +73391 -0.36212158203125 +73392 -0.39141845703125 +73393 -0.35528564453125 +73394 -0.249969482421875 +73395 -0.092864990234375 +73396 0.08905029296875 +73397 0.2352294921875 +73398 0.318817138671875 +73399 0.358642578125 +73400 0.347747802734375 +73401 0.28564453125 +73402 0.223175048828125 +73403 0.196746826171875 +73404 0.179840087890625 +73405 0.155548095703125 +73406 0.151214599609375 +73407 0.156951904296875 +73408 0.13177490234375 +73409 0.100799560546875 +73410 0.087127685546875 +73411 0.05487060546875 +73412 -0.009002685546875 +73413 -0.10400390625 +73414 -0.229400634765625 +73415 -0.35552978515625 +73416 -0.441925048828125 +73417 -0.473846435546875 +73418 -0.464813232421875 +73419 -0.419097900390625 +73420 -0.334320068359375 +73421 -0.227935791015625 +73422 -0.12347412109375 +73423 -0.02764892578125 +73424 0.077667236328125 +73425 0.2132568359375 +73426 0.38885498046875 +73427 0.582794189453125 +73428 0.734039306640625 +73429 0.800140380859375 +73430 0.7783203125 +73431 0.6651611328125 +73432 0.45965576171875 +73433 0.199188232421875 +73434 -0.050689697265625 +73435 -0.23297119140625 +73436 -0.33013916015625 +73437 -0.368408203125 +73438 -0.378936767578125 +73439 -0.376983642578125 +73440 -0.37969970703125 +73441 -0.391510009765625 +73442 -0.385345458984375 +73443 -0.3419189453125 +73444 -0.28289794921875 +73445 -0.251617431640625 +73446 -0.266143798828125 +73447 -0.273345947265625 +73448 -0.216796875 +73449 -0.128265380859375 +73450 -0.068145751953125 +73451 -0.0430908203125 +73452 -0.024444580078125 +73453 0.020721435546875 +73454 0.124481201171875 +73455 0.25787353515625 +73456 0.379119873046875 +73457 0.47991943359375 +73458 0.5281982421875 +73459 0.511138916015625 +73460 0.456207275390625 +73461 0.407470703125 +73462 0.383758544921875 +73463 0.35687255859375 +73464 0.31182861328125 +73465 0.250885009765625 +73466 0.1654052734375 +73467 0.035247802734375 +73468 -0.142059326171875 +73469 -0.33563232421875 +73470 -0.5345458984375 +73471 -0.72186279296875 +73472 -0.836669921875 +73473 -0.8326416015625 +73474 -0.7296142578125 +73475 -0.582550048828125 +73476 -0.440093994140625 +73477 -0.324310302734375 +73478 -0.20147705078125 +73479 -0.044647216796875 +73480 0.103973388671875 +73481 0.202392578125 +73482 0.264495849609375 +73483 0.338897705078125 +73484 0.443817138671875 +73485 0.545074462890625 +73486 0.6173095703125 +73487 0.6524658203125 +73488 0.66339111328125 +73489 0.6561279296875 +73490 0.606781005859375 +73491 0.501190185546875 +73492 0.352783203125 +73493 0.176544189453125 +73494 -0.034820556640625 +73495 -0.258209228515625 +73496 -0.44244384765625 +73497 -0.5753173828125 +73498 -0.65203857421875 +73499 -0.641632080078125 +73500 -0.562164306640625 +73501 -0.458038330078125 +73502 -0.350555419921875 +73503 -0.260528564453125 +73504 -0.192108154296875 +73505 -0.141937255859375 +73506 -0.1021728515625 +73507 -0.062896728515625 +73508 -0.011932373046875 +73509 0.062835693359375 +73510 0.148712158203125 +73511 0.241729736328125 +73512 0.34912109375 +73513 0.457305908203125 +73514 0.54388427734375 +73515 0.5728759765625 +73516 0.506591796875 +73517 0.351226806640625 +73518 0.146514892578125 +73519 -0.05523681640625 +73520 -0.21624755859375 +73521 -0.334930419921875 +73522 -0.402984619140625 +73523 -0.4412841796875 +73524 -0.49578857421875 +73525 -0.5601806640625 +73526 -0.600738525390625 +73527 -0.584228515625 +73528 -0.47930908203125 +73529 -0.27935791015625 +73530 -0.0089111328125 +73531 0.268798828125 +73532 0.482818603515625 +73533 0.60369873046875 +73534 0.650421142578125 +73535 0.66400146484375 +73536 0.6414794921875 +73537 0.572540283203125 +73538 0.498138427734375 +73539 0.439453125 +73540 0.375518798828125 +73541 0.274505615234375 +73542 0.1087646484375 +73543 -0.099395751953125 +73544 -0.3182373046875 +73545 -0.5489501953125 +73546 -0.7738037109375 +73547 -0.86383056640625 +73548 -0.870391845703125 +73549 -0.86895751953125 +73550 -0.861053466796875 +73551 -0.765869140625 +73552 -0.5301513671875 +73553 -0.214691162109375 +73554 0.137359619140625 +73555 0.474822998046875 +73556 0.76239013671875 +73557 0.867462158203125 +73558 0.870361328125 +73559 0.86480712890625 +73560 0.831817626953125 +73561 0.677581787109375 +73562 0.495880126953125 +73563 0.30767822265625 +73564 0.116180419921875 +73565 -0.110748291015625 +73566 -0.381805419921875 +73567 -0.6572265625 +73568 -0.857421875 +73569 -0.870391845703125 +73570 -0.870391845703125 +73571 -0.86444091796875 +73572 -0.85723876953125 +73573 -0.790008544921875 +73574 -0.62847900390625 +73575 -0.3956298828125 +73576 -0.126708984375 +73577 0.150115966796875 +73578 0.424041748046875 +73579 0.670623779296875 +73580 0.854522705078125 +73581 0.866485595703125 +73582 0.86920166015625 +73583 0.8653564453125 +73584 0.857147216796875 +73585 0.766845703125 +73586 0.628509521484375 +73587 0.462127685546875 +73588 0.297210693359375 +73589 0.14862060546875 +73590 -0.00537109375 +73591 -0.15753173828125 +73592 -0.31304931640625 +73593 -0.48876953125 +73594 -0.6416015625 +73595 -0.751373291015625 +73596 -0.84619140625 +73597 -0.861297607421875 +73598 -0.863250732421875 +73599 -0.856597900390625 +73600 -0.7498779296875 +73601 -0.624542236328125 +73602 -0.47808837890625 +73603 -0.253387451171875 +73604 0.003692626953125 +73605 0.2257080078125 +73606 0.427154541015625 +73607 0.643218994140625 +73608 0.855926513671875 +73609 0.870361328125 +73610 0.870361328125 +73611 0.862762451171875 +73612 0.79669189453125 +73613 0.595794677734375 +73614 0.362152099609375 +73615 0.1270751953125 +73616 -0.086944580078125 +73617 -0.2784423828125 +73618 -0.484832763671875 +73619 -0.729583740234375 +73620 -0.86688232421875 +73621 -0.870391845703125 +73622 -0.86859130859375 +73623 -0.86279296875 +73624 -0.817962646484375 +73625 -0.6116943359375 +73626 -0.3128662109375 +73627 0.039398193359375 +73628 0.422821044921875 +73629 0.805145263671875 +73630 0.870361328125 +73631 0.870361328125 +73632 0.860015869140625 +73633 0.727935791015625 +73634 0.48114013671875 +73635 0.2059326171875 +73636 -0.06103515625 +73637 -0.29913330078125 +73638 -0.516204833984375 +73639 -0.7252197265625 +73640 -0.85980224609375 +73641 -0.870391845703125 +73642 -0.870391845703125 +73643 -0.858062744140625 +73644 -0.673004150390625 +73645 -0.42694091796875 +73646 -0.2100830078125 +73647 -0.0362548828125 +73648 0.10943603515625 +73649 0.23516845703125 +73650 0.373687744140625 +73651 0.517791748046875 +73652 0.602783203125 +73653 0.635711669921875 +73654 0.655181884765625 +73655 0.65948486328125 +73656 0.651275634765625 +73657 0.61846923828125 +73658 0.53753662109375 +73659 0.404144287109375 +73660 0.22186279296875 +73661 0.003997802734375 +73662 -0.22100830078125 +73663 -0.42449951171875 +73664 -0.579833984375 +73665 -0.641876220703125 +73666 -0.6177978515625 +73667 -0.575531005859375 +73668 -0.526336669921875 +73669 -0.42645263671875 +73670 -0.2581787109375 +73671 -0.068695068359375 +73672 0.09222412109375 +73673 0.232147216796875 +73674 0.3509521484375 +73675 0.410064697265625 +73676 0.372955322265625 +73677 0.2554931640625 +73678 0.10711669921875 +73679 -0.052886962890625 +73680 -0.186279296875 +73681 -0.23291015625 +73682 -0.209442138671875 +73683 -0.174163818359375 +73684 -0.126739501953125 +73685 -0.048126220703125 +73686 0.0426025390625 +73687 0.10748291015625 +73688 0.1409912109375 +73689 0.19708251953125 +73690 0.273651123046875 +73691 0.31768798828125 +73692 0.341094970703125 +73693 0.368011474609375 +73694 0.37249755859375 +73695 0.30072021484375 +73696 0.1517333984375 +73697 -0.01470947265625 +73698 -0.1883544921875 +73699 -0.372711181640625 +73700 -0.51397705078125 +73701 -0.57177734375 +73702 -0.53948974609375 +73703 -0.43511962890625 +73704 -0.2962646484375 +73705 -0.161102294921875 +73706 -0.0435791015625 +73707 0.060394287109375 +73708 0.13665771484375 +73709 0.170135498046875 +73710 0.16552734375 +73711 0.15728759765625 +73712 0.150787353515625 +73713 0.12200927734375 +73714 0.080108642578125 +73715 0.05126953125 +73716 0.062896728515625 +73717 0.09271240234375 +73718 0.092987060546875 +73719 0.07855224609375 +73720 0.06427001953125 +73721 0.0347900390625 +73722 -0.01171875 +73723 -0.056060791015625 +73724 -0.055511474609375 +73725 -0.010467529296875 +73726 0.02508544921875 +73727 0.025665283203125 +73728 0.017333984375 +73729 0.00189208984375 +73730 -0.03173828125 +73731 -0.071502685546875 +73732 -0.13543701171875 +73733 -0.219970703125 +73734 -0.300506591796875 +73735 -0.376312255859375 +73736 -0.416107177734375 +73737 -0.371124267578125 +73738 -0.242279052734375 +73739 -0.069732666015625 +73740 0.125640869140625 +73741 0.31268310546875 +73742 0.45501708984375 +73743 0.554779052734375 +73744 0.61065673828125 +73745 0.610931396484375 +73746 0.531463623046875 +73747 0.3883056640625 +73748 0.23468017578125 +73749 0.095245361328125 +73750 -0.00396728515625 +73751 -0.04852294921875 +73752 -0.055145263671875 +73753 -0.0758056640625 +73754 -0.138702392578125 +73755 -0.209197998046875 +73756 -0.289031982421875 +73757 -0.37884521484375 +73758 -0.456329345703125 +73759 -0.51641845703125 +73760 -0.519287109375 +73761 -0.458251953125 +73762 -0.384796142578125 +73763 -0.323699951171875 +73764 -0.269287109375 +73765 -0.1951904296875 +73766 -0.100006103515625 +73767 -0.01055908203125 +73768 0.1033935546875 +73769 0.24908447265625 +73770 0.373199462890625 +73771 0.45806884765625 +73772 0.511474609375 +73773 0.565399169921875 +73774 0.61138916015625 +73775 0.5897216796875 +73776 0.4906005859375 +73777 0.33148193359375 +73778 0.147796630859375 +73779 -0.01873779296875 +73780 -0.140289306640625 +73781 -0.191986083984375 +73782 -0.184295654296875 +73783 -0.161834716796875 +73784 -0.166595458984375 +73785 -0.19390869140625 +73786 -0.22442626953125 +73787 -0.279754638671875 +73788 -0.3389892578125 +73789 -0.3543701171875 +73790 -0.348175048828125 +73791 -0.32598876953125 +73792 -0.2581787109375 +73793 -0.139801025390625 +73794 0.014617919921875 +73795 0.144378662109375 +73796 0.221038818359375 +73797 0.27069091796875 +73798 0.294036865234375 +73799 0.311767578125 +73800 0.339141845703125 +73801 0.360260009765625 +73802 0.360504150390625 +73803 0.308380126953125 +73804 0.18170166015625 +73805 0.0047607421875 +73806 -0.17559814453125 +73807 -0.3143310546875 +73808 -0.36785888671875 +73809 -0.36248779296875 +73810 -0.343536376953125 +73811 -0.3018798828125 +73812 -0.231414794921875 +73813 -0.117645263671875 +73814 0.007049560546875 +73815 0.087982177734375 +73816 0.13946533203125 +73817 0.17425537109375 +73818 0.188201904296875 +73819 0.171234130859375 +73820 0.118438720703125 +73821 0.05706787109375 +73822 -0.010711669921875 +73823 -0.0914306640625 +73824 -0.162322998046875 +73825 -0.194549560546875 +73826 -0.1492919921875 +73827 -0.02166748046875 +73828 0.124053955078125 +73829 0.211151123046875 +73830 0.240447998046875 +73831 0.242218017578125 +73832 0.2257080078125 +73833 0.194366455078125 +73834 0.115509033203125 +73835 0.0128173828125 +73836 -0.053802490234375 +73837 -0.110626220703125 +73838 -0.199493408203125 +73839 -0.29437255859375 +73840 -0.33221435546875 +73841 -0.27972412109375 +73842 -0.185333251953125 +73843 -0.128204345703125 +73844 -0.115692138671875 +73845 -0.116455078125 +73846 -0.105926513671875 +73847 -0.053955078125 +73848 0.048797607421875 +73849 0.157318115234375 +73850 0.212005615234375 +73851 0.218475341796875 +73852 0.23724365234375 +73853 0.30535888671875 +73854 0.38128662109375 +73855 0.404449462890625 +73856 0.3944091796875 +73857 0.3885498046875 +73858 0.362640380859375 +73859 0.27362060546875 +73860 0.11712646484375 +73861 -0.054901123046875 +73862 -0.19085693359375 +73863 -0.28570556640625 +73864 -0.339263916015625 +73865 -0.3775634765625 +73866 -0.445709228515625 +73867 -0.535064697265625 +73868 -0.629058837890625 +73869 -0.697601318359375 +73870 -0.70391845703125 +73871 -0.6424560546875 +73872 -0.491241455078125 +73873 -0.265716552734375 +73874 -0.023712158203125 +73875 0.201751708984375 +73876 0.375823974609375 +73877 0.485076904296875 +73878 0.56884765625 +73879 0.634765625 +73880 0.63763427734375 +73881 0.5660400390625 +73882 0.4720458984375 +73883 0.40692138671875 +73884 0.3778076171875 +73885 0.376953125 +73886 0.371978759765625 +73887 0.313140869140625 +73888 0.184417724609375 +73889 0.011199951171875 +73890 -0.171051025390625 +73891 -0.33740234375 +73892 -0.47198486328125 +73893 -0.560394287109375 +73894 -0.58056640625 +73895 -0.54754638671875 +73896 -0.508575439453125 +73897 -0.459503173828125 +73898 -0.394378662109375 +73899 -0.35260009765625 +73900 -0.31170654296875 +73901 -0.197418212890625 +73902 -0.007965087890625 +73903 0.207489013671875 +73904 0.409210205078125 +73905 0.57208251953125 +73906 0.66595458984375 +73907 0.65875244140625 +73908 0.56744384765625 +73909 0.431396484375 +73910 0.29443359375 +73911 0.182464599609375 +73912 0.06365966796875 +73913 -0.075958251953125 +73914 -0.189422607421875 +73915 -0.271942138671875 +73916 -0.342529296875 +73917 -0.364166259765625 +73918 -0.327239990234375 +73919 -0.2769775390625 +73920 -0.253692626953125 +73921 -0.24365234375 +73922 -0.1983642578125 +73923 -0.116241455078125 +73924 -0.036834716796875 +73925 0.034881591796875 +73926 0.09124755859375 +73927 0.10888671875 +73928 0.125518798828125 +73929 0.15771484375 +73930 0.17828369140625 +73931 0.17108154296875 +73932 0.129974365234375 +73933 0.082427978515625 +73934 0.027679443359375 +73935 -0.065643310546875 +73936 -0.15936279296875 +73937 -0.21307373046875 +73938 -0.234649658203125 +73939 -0.2001953125 +73940 -0.119171142578125 +73941 -0.024749755859375 +73942 0.085784912109375 +73943 0.178131103515625 +73944 0.215576171875 +73945 0.211456298828125 +73946 0.17523193359375 +73947 0.128753662109375 +73948 0.1019287109375 +73949 0.0743408203125 +73950 0.04327392578125 +73951 0.038177490234375 +73952 0.076263427734375 +73953 0.14105224609375 +73954 0.186431884765625 +73955 0.188812255859375 +73956 0.1390380859375 +73957 0.041778564453125 +73958 -0.079437255859375 +73959 -0.219390869140625 +73960 -0.367828369140625 +73961 -0.494873046875 +73962 -0.556243896484375 +73963 -0.508697509765625 +73964 -0.3756103515625 +73965 -0.218902587890625 +73966 -0.063751220703125 +73967 0.091552734375 +73968 0.23602294921875 +73969 0.342987060546875 +73970 0.39520263671875 +73971 0.389373779296875 +73972 0.324249267578125 +73973 0.224090576171875 +73974 0.124267578125 +73975 0.037078857421875 +73976 -0.010101318359375 +73977 -0.019439697265625 +73978 -0.022796630859375 +73979 -0.001556396484375 +73980 0.056304931640625 +73981 0.106719970703125 +73982 0.096893310546875 +73983 0.042694091796875 +73984 -0.018035888671875 +73985 -0.07586669921875 +73986 -0.11944580078125 +73987 -0.15972900390625 +73988 -0.202606201171875 +73989 -0.24859619140625 +73990 -0.30517578125 +73991 -0.36212158203125 +73992 -0.39141845703125 +73993 -0.35528564453125 +73994 -0.249969482421875 +73995 -0.092864990234375 +73996 0.08905029296875 +73997 0.2352294921875 +73998 0.318817138671875 +73999 0.358642578125 +74000 0.347747802734375 +74001 0.28564453125 +74002 0.223175048828125 +74003 0.196746826171875 +74004 0.179840087890625 +74005 0.155548095703125 +74006 0.151214599609375 +74007 0.156951904296875 +74008 0.13177490234375 +74009 0.100799560546875 +74010 0.087127685546875 +74011 0.05487060546875 +74012 -0.009002685546875 +74013 -0.10400390625 +74014 -0.229400634765625 +74015 -0.35552978515625 +74016 -0.441925048828125 +74017 -0.473846435546875 +74018 -0.464813232421875 +74019 -0.419097900390625 +74020 -0.334320068359375 +74021 -0.227935791015625 +74022 -0.12347412109375 +74023 -0.02764892578125 +74024 0.077667236328125 +74025 0.2132568359375 +74026 0.38885498046875 +74027 0.582794189453125 +74028 0.734039306640625 +74029 0.800140380859375 +74030 0.7783203125 +74031 0.6651611328125 +74032 0.45965576171875 +74033 0.199188232421875 +74034 -0.050689697265625 +74035 -0.23297119140625 +74036 -0.33013916015625 +74037 -0.368408203125 +74038 -0.378936767578125 +74039 -0.376983642578125 +74040 -0.37969970703125 +74041 -0.391510009765625 +74042 -0.385345458984375 +74043 -0.3419189453125 +74044 -0.28289794921875 +74045 -0.251617431640625 +74046 -0.266143798828125 +74047 -0.273345947265625 +74048 -0.216796875 +74049 -0.128265380859375 +74050 -0.068145751953125 +74051 -0.0430908203125 +74052 -0.024444580078125 +74053 0.020721435546875 +74054 0.124481201171875 +74055 0.25787353515625 +74056 0.379119873046875 +74057 0.47991943359375 +74058 0.5281982421875 +74059 0.511138916015625 +74060 0.456207275390625 +74061 0.407470703125 +74062 0.383758544921875 +74063 0.35687255859375 +74064 0.31182861328125 +74065 0.250885009765625 +74066 0.1654052734375 +74067 0.035247802734375 +74068 -0.142059326171875 +74069 -0.33563232421875 +74070 -0.5345458984375 +74071 -0.72186279296875 +74072 -0.836669921875 +74073 -0.8326416015625 +74074 -0.7296142578125 +74075 -0.582550048828125 +74076 -0.440093994140625 +74077 -0.324310302734375 +74078 -0.20147705078125 +74079 -0.044647216796875 +74080 0.103973388671875 +74081 0.202392578125 +74082 0.264495849609375 +74083 0.338897705078125 +74084 0.443817138671875 +74085 0.545074462890625 +74086 0.6173095703125 +74087 0.6524658203125 +74088 0.66339111328125 +74089 0.6561279296875 +74090 0.606781005859375 +74091 0.501190185546875 +74092 0.352783203125 +74093 0.176544189453125 +74094 -0.034820556640625 +74095 -0.258209228515625 +74096 -0.44244384765625 +74097 -0.5753173828125 +74098 -0.65203857421875 +74099 -0.641632080078125 +74100 -0.562164306640625 +74101 -0.458038330078125 +74102 -0.350555419921875 +74103 -0.260528564453125 +74104 -0.192108154296875 +74105 -0.141937255859375 +74106 -0.1021728515625 +74107 -0.062896728515625 +74108 -0.011932373046875 +74109 0.062835693359375 +74110 0.148712158203125 +74111 0.241729736328125 +74112 0.34912109375 +74113 0.457305908203125 +74114 0.54388427734375 +74115 0.5728759765625 +74116 0.506591796875 +74117 0.351226806640625 +74118 0.146514892578125 +74119 -0.05523681640625 +74120 -0.21624755859375 +74121 -0.334930419921875 +74122 -0.402984619140625 +74123 -0.4412841796875 +74124 -0.49578857421875 +74125 -0.5601806640625 +74126 -0.600738525390625 +74127 -0.584228515625 +74128 -0.47930908203125 +74129 -0.27935791015625 +74130 -0.0089111328125 +74131 0.268798828125 +74132 0.482818603515625 +74133 0.60369873046875 +74134 0.650421142578125 +74135 0.66400146484375 +74136 0.6414794921875 +74137 0.572540283203125 +74138 0.498138427734375 +74139 0.439453125 +74140 0.375518798828125 +74141 0.274505615234375 +74142 0.1087646484375 +74143 -0.099395751953125 +74144 -0.3182373046875 +74145 -0.5489501953125 +74146 -0.7738037109375 +74147 -0.86383056640625 +74148 -0.870391845703125 +74149 -0.86895751953125 +74150 -0.861053466796875 +74151 -0.765869140625 +74152 -0.5301513671875 +74153 -0.214691162109375 +74154 0.137359619140625 +74155 0.474822998046875 +74156 0.76239013671875 +74157 0.867462158203125 +74158 0.870361328125 +74159 0.86480712890625 +74160 0.831817626953125 +74161 0.677581787109375 +74162 0.495880126953125 +74163 0.30767822265625 +74164 0.116180419921875 +74165 -0.110748291015625 +74166 -0.381805419921875 +74167 -0.6572265625 +74168 -0.857421875 +74169 -0.870391845703125 +74170 -0.870391845703125 +74171 -0.86444091796875 +74172 -0.85723876953125 +74173 -0.790008544921875 +74174 -0.62847900390625 +74175 -0.3956298828125 +74176 -0.126708984375 +74177 0.150115966796875 +74178 0.424041748046875 +74179 0.670623779296875 +74180 0.854522705078125 +74181 0.866485595703125 +74182 0.86920166015625 +74183 0.8653564453125 +74184 0.857147216796875 +74185 0.766845703125 +74186 0.628509521484375 +74187 0.462127685546875 +74188 0.297210693359375 +74189 0.14862060546875 +74190 -0.00537109375 +74191 -0.15753173828125 +74192 -0.31304931640625 +74193 -0.48876953125 +74194 -0.6416015625 +74195 -0.751373291015625 +74196 -0.84619140625 +74197 -0.861297607421875 +74198 -0.863250732421875 +74199 -0.856597900390625 +74200 -0.7498779296875 +74201 -0.624542236328125 +74202 -0.47808837890625 +74203 -0.253387451171875 +74204 0.003692626953125 +74205 0.2257080078125 +74206 0.427154541015625 +74207 0.643218994140625 +74208 0.855926513671875 +74209 0.870361328125 +74210 0.870361328125 +74211 0.862762451171875 +74212 0.79669189453125 +74213 0.595794677734375 +74214 0.362152099609375 +74215 0.1270751953125 +74216 -0.086944580078125 +74217 -0.2784423828125 +74218 -0.484832763671875 +74219 -0.729583740234375 +74220 -0.86688232421875 +74221 -0.870391845703125 +74222 -0.86859130859375 +74223 -0.86279296875 +74224 -0.817962646484375 +74225 -0.6116943359375 +74226 -0.3128662109375 +74227 0.039398193359375 +74228 0.422821044921875 +74229 0.805145263671875 +74230 0.870361328125 +74231 0.870361328125 +74232 0.860015869140625 +74233 0.727935791015625 +74234 0.48114013671875 +74235 0.2059326171875 +74236 -0.06103515625 +74237 -0.29913330078125 +74238 -0.516204833984375 +74239 -0.7252197265625 +74240 -0.85980224609375 +74241 -0.870391845703125 +74242 -0.870391845703125 +74243 -0.858062744140625 +74244 -0.673004150390625 +74245 -0.42694091796875 +74246 -0.2100830078125 +74247 -0.0362548828125 +74248 0.10943603515625 +74249 0.23516845703125 +74250 0.373687744140625 +74251 0.517791748046875 +74252 0.602783203125 +74253 0.635711669921875 +74254 0.655181884765625 +74255 0.65948486328125 +74256 0.651275634765625 +74257 0.61846923828125 +74258 0.53753662109375 +74259 0.404144287109375 +74260 0.22186279296875 +74261 0.003997802734375 +74262 -0.22100830078125 +74263 -0.42449951171875 +74264 -0.579833984375 +74265 -0.641876220703125 +74266 -0.6177978515625 +74267 -0.575531005859375 +74268 -0.526336669921875 +74269 -0.42645263671875 +74270 -0.2581787109375 +74271 -0.068695068359375 +74272 0.09222412109375 +74273 0.232147216796875 +74274 0.3509521484375 +74275 0.410064697265625 +74276 0.372955322265625 +74277 0.2554931640625 +74278 0.10711669921875 +74279 -0.052886962890625 +74280 -0.186279296875 +74281 -0.23291015625 +74282 -0.209442138671875 +74283 -0.174163818359375 +74284 -0.126739501953125 +74285 -0.048126220703125 +74286 0.0426025390625 +74287 0.10748291015625 +74288 0.1409912109375 +74289 0.19708251953125 +74290 0.273651123046875 +74291 0.31768798828125 +74292 0.341094970703125 +74293 0.368011474609375 +74294 0.37249755859375 +74295 0.30072021484375 +74296 0.1517333984375 +74297 -0.01470947265625 +74298 -0.1883544921875 +74299 -0.372711181640625 +74300 -0.51397705078125 +74301 -0.57177734375 +74302 -0.53948974609375 +74303 -0.43511962890625 +74304 -0.2962646484375 +74305 -0.161102294921875 +74306 -0.0435791015625 +74307 0.060394287109375 +74308 0.13665771484375 +74309 0.170135498046875 +74310 0.16552734375 +74311 0.15728759765625 +74312 0.150787353515625 +74313 0.12200927734375 +74314 0.080108642578125 +74315 0.05126953125 +74316 0.062896728515625 +74317 0.09271240234375 +74318 0.092987060546875 +74319 0.07855224609375 +74320 0.06427001953125 +74321 0.0347900390625 +74322 -0.01171875 +74323 -0.056060791015625 +74324 -0.055511474609375 +74325 -0.010467529296875 +74326 0.02508544921875 +74327 0.025665283203125 +74328 0.017333984375 +74329 0.00189208984375 +74330 -0.03173828125 +74331 -0.071502685546875 +74332 -0.13543701171875 +74333 -0.219970703125 +74334 -0.300506591796875 +74335 -0.376312255859375 +74336 -0.416107177734375 +74337 -0.371124267578125 +74338 -0.242279052734375 +74339 -0.069732666015625 +74340 0.125640869140625 +74341 0.31268310546875 +74342 0.45501708984375 +74343 0.554779052734375 +74344 0.61065673828125 +74345 0.610931396484375 +74346 0.531463623046875 +74347 0.3883056640625 +74348 0.23468017578125 +74349 0.095245361328125 +74350 -0.00396728515625 +74351 -0.04852294921875 +74352 -0.055145263671875 +74353 -0.0758056640625 +74354 -0.138702392578125 +74355 -0.209197998046875 +74356 -0.289031982421875 +74357 -0.37884521484375 +74358 -0.456329345703125 +74359 -0.51641845703125 +74360 -0.519287109375 +74361 -0.458251953125 +74362 -0.384796142578125 +74363 -0.323699951171875 +74364 -0.269287109375 +74365 -0.1951904296875 +74366 -0.100006103515625 +74367 -0.01055908203125 +74368 0.1033935546875 +74369 0.24908447265625 +74370 0.373199462890625 +74371 0.45806884765625 +74372 0.511474609375 +74373 0.565399169921875 +74374 0.61138916015625 +74375 0.5897216796875 +74376 0.4906005859375 +74377 0.33148193359375 +74378 0.147796630859375 +74379 -0.01873779296875 +74380 -0.140289306640625 +74381 -0.191986083984375 +74382 -0.184295654296875 +74383 -0.161834716796875 +74384 -0.166595458984375 +74385 -0.19390869140625 +74386 -0.22442626953125 +74387 -0.279754638671875 +74388 -0.3389892578125 +74389 -0.3543701171875 +74390 -0.348175048828125 +74391 -0.32598876953125 +74392 -0.2581787109375 +74393 -0.139801025390625 +74394 0.014617919921875 +74395 0.144378662109375 +74396 0.221038818359375 +74397 0.27069091796875 +74398 0.294036865234375 +74399 0.311767578125 +74400 0.339141845703125 +74401 0.360260009765625 +74402 0.360504150390625 +74403 0.308380126953125 +74404 0.18170166015625 +74405 0.0047607421875 +74406 -0.17559814453125 +74407 -0.3143310546875 +74408 -0.36785888671875 +74409 -0.36248779296875 +74410 -0.343536376953125 +74411 -0.3018798828125 +74412 -0.231414794921875 +74413 -0.117645263671875 +74414 0.007049560546875 +74415 0.087982177734375 +74416 0.13946533203125 +74417 0.17425537109375 +74418 0.188201904296875 +74419 0.171234130859375 +74420 0.118438720703125 +74421 0.05706787109375 +74422 -0.010711669921875 +74423 -0.0914306640625 +74424 -0.162322998046875 +74425 -0.194549560546875 +74426 -0.1492919921875 +74427 -0.02166748046875 +74428 0.124053955078125 +74429 0.211151123046875 +74430 0.240447998046875 +74431 0.242218017578125 +74432 0.2257080078125 +74433 0.194366455078125 +74434 0.115509033203125 +74435 0.0128173828125 +74436 -0.053802490234375 +74437 -0.110626220703125 +74438 -0.199493408203125 +74439 -0.29437255859375 +74440 -0.33221435546875 +74441 -0.27972412109375 +74442 -0.185333251953125 +74443 -0.128204345703125 +74444 -0.115692138671875 +74445 -0.116455078125 +74446 -0.105926513671875 +74447 -0.053955078125 +74448 0.048797607421875 +74449 0.157318115234375 +74450 0.212005615234375 +74451 0.218475341796875 +74452 0.23724365234375 +74453 0.30535888671875 +74454 0.38128662109375 +74455 0.404449462890625 +74456 0.3944091796875 +74457 0.3885498046875 +74458 0.362640380859375 +74459 0.27362060546875 +74460 0.11712646484375 +74461 -0.054901123046875 +74462 -0.19085693359375 +74463 -0.28570556640625 +74464 -0.339263916015625 +74465 -0.3775634765625 +74466 -0.445709228515625 +74467 -0.535064697265625 +74468 -0.629058837890625 +74469 -0.697601318359375 +74470 -0.70391845703125 +74471 -0.6424560546875 +74472 -0.491241455078125 +74473 -0.265716552734375 +74474 -0.023712158203125 +74475 0.201751708984375 +74476 0.375823974609375 +74477 0.485076904296875 +74478 0.56884765625 +74479 0.634765625 +74480 0.63763427734375 +74481 0.5660400390625 +74482 0.4720458984375 +74483 0.40692138671875 +74484 0.3778076171875 +74485 0.376953125 +74486 0.371978759765625 +74487 0.313140869140625 +74488 0.184417724609375 +74489 0.011199951171875 +74490 -0.171051025390625 +74491 -0.33740234375 +74492 -0.47198486328125 +74493 -0.560394287109375 +74494 -0.58056640625 +74495 -0.54754638671875 +74496 -0.508575439453125 +74497 -0.459503173828125 +74498 -0.394378662109375 +74499 -0.35260009765625 +74500 -0.31170654296875 +74501 -0.197418212890625 +74502 -0.007965087890625 +74503 0.207489013671875 +74504 0.409210205078125 +74505 0.57208251953125 +74506 0.66595458984375 +74507 0.65875244140625 +74508 0.56744384765625 +74509 0.431396484375 +74510 0.29443359375 +74511 0.182464599609375 +74512 0.06365966796875 +74513 -0.075958251953125 +74514 -0.189422607421875 +74515 -0.271942138671875 +74516 -0.342529296875 +74517 -0.364166259765625 +74518 -0.327239990234375 +74519 -0.2769775390625 +74520 -0.253692626953125 +74521 -0.24365234375 +74522 -0.1983642578125 +74523 -0.116241455078125 +74524 -0.036834716796875 +74525 0.034881591796875 +74526 0.09124755859375 +74527 0.10888671875 +74528 0.125518798828125 +74529 0.15771484375 +74530 0.17828369140625 +74531 0.17108154296875 +74532 0.129974365234375 +74533 0.082427978515625 +74534 0.027679443359375 +74535 -0.065643310546875 +74536 -0.15936279296875 +74537 -0.21307373046875 +74538 -0.234649658203125 +74539 -0.2001953125 +74540 -0.119171142578125 +74541 -0.024749755859375 +74542 0.085784912109375 +74543 0.178131103515625 +74544 0.215576171875 +74545 0.211456298828125 +74546 0.17523193359375 +74547 0.128753662109375 +74548 0.1019287109375 +74549 0.0743408203125 +74550 0.04327392578125 +74551 0.038177490234375 +74552 0.076263427734375 +74553 0.14105224609375 +74554 0.186431884765625 +74555 0.188812255859375 +74556 0.1390380859375 +74557 0.041778564453125 +74558 -0.079437255859375 +74559 -0.219390869140625 +74560 -0.367828369140625 +74561 -0.494873046875 +74562 -0.556243896484375 +74563 -0.508697509765625 +74564 -0.3756103515625 +74565 -0.218902587890625 +74566 -0.063751220703125 +74567 0.091552734375 +74568 0.23602294921875 +74569 0.342987060546875 +74570 0.39520263671875 +74571 0.389373779296875 +74572 0.324249267578125 +74573 0.224090576171875 +74574 0.124267578125 +74575 0.037078857421875 +74576 -0.010101318359375 +74577 -0.019439697265625 +74578 -0.022796630859375 +74579 -0.001556396484375 +74580 0.056304931640625 +74581 0.106719970703125 +74582 0.096893310546875 +74583 0.042694091796875 +74584 -0.018035888671875 +74585 -0.07586669921875 +74586 -0.11944580078125 +74587 -0.15972900390625 +74588 -0.202606201171875 +74589 -0.24859619140625 +74590 -0.30517578125 +74591 -0.36212158203125 +74592 -0.39141845703125 +74593 -0.35528564453125 +74594 -0.249969482421875 +74595 -0.092864990234375 +74596 0.08905029296875 +74597 0.2352294921875 +74598 0.318817138671875 +74599 0.358642578125 +74600 0.347747802734375 +74601 0.28564453125 +74602 0.223175048828125 +74603 0.196746826171875 +74604 0.179840087890625 +74605 0.155548095703125 +74606 0.151214599609375 +74607 0.156951904296875 +74608 0.13177490234375 +74609 0.100799560546875 +74610 0.087127685546875 +74611 0.05487060546875 +74612 -0.009002685546875 +74613 -0.10400390625 +74614 -0.229400634765625 +74615 -0.35552978515625 +74616 -0.441925048828125 +74617 -0.473846435546875 +74618 -0.464813232421875 +74619 -0.419097900390625 +74620 -0.334320068359375 +74621 -0.227935791015625 +74622 -0.12347412109375 +74623 -0.02764892578125 +74624 0.077667236328125 +74625 0.2132568359375 +74626 0.38885498046875 +74627 0.582794189453125 +74628 0.734039306640625 +74629 0.800140380859375 +74630 0.7783203125 +74631 0.6651611328125 +74632 0.45965576171875 +74633 0.199188232421875 +74634 -0.050689697265625 +74635 -0.23297119140625 +74636 -0.33013916015625 +74637 -0.368408203125 +74638 -0.378936767578125 +74639 -0.376983642578125 +74640 -0.37969970703125 +74641 -0.391510009765625 +74642 -0.385345458984375 +74643 -0.3419189453125 +74644 -0.28289794921875 +74645 -0.251617431640625 +74646 -0.266143798828125 +74647 -0.273345947265625 +74648 -0.216796875 +74649 -0.128265380859375 +74650 -0.068145751953125 +74651 -0.0430908203125 +74652 -0.024444580078125 +74653 0.020721435546875 +74654 0.124481201171875 +74655 0.25787353515625 +74656 0.379119873046875 +74657 0.47991943359375 +74658 0.5281982421875 +74659 0.511138916015625 +74660 0.456207275390625 +74661 0.407470703125 +74662 0.383758544921875 +74663 0.35687255859375 +74664 0.31182861328125 +74665 0.250885009765625 +74666 0.1654052734375 +74667 0.035247802734375 +74668 -0.142059326171875 +74669 -0.33563232421875 +74670 -0.5345458984375 +74671 -0.72186279296875 +74672 -0.836669921875 +74673 -0.8326416015625 +74674 -0.7296142578125 +74675 -0.582550048828125 +74676 -0.440093994140625 +74677 -0.324310302734375 +74678 -0.20147705078125 +74679 -0.044647216796875 +74680 0.103973388671875 +74681 0.202392578125 +74682 0.264495849609375 +74683 0.338897705078125 +74684 0.443817138671875 +74685 0.545074462890625 +74686 0.6173095703125 +74687 0.6524658203125 +74688 0.66339111328125 +74689 0.6561279296875 +74690 0.606781005859375 +74691 0.501190185546875 +74692 0.352783203125 +74693 0.176544189453125 +74694 -0.034820556640625 +74695 -0.258209228515625 +74696 -0.44244384765625 +74697 -0.5753173828125 +74698 -0.65203857421875 +74699 -0.641632080078125 +74700 -0.562164306640625 +74701 -0.458038330078125 +74702 -0.350555419921875 +74703 -0.260528564453125 +74704 -0.192108154296875 +74705 -0.141937255859375 +74706 -0.1021728515625 +74707 -0.062896728515625 +74708 -0.011932373046875 +74709 0.062835693359375 +74710 0.148712158203125 +74711 0.241729736328125 +74712 0.34912109375 +74713 0.457305908203125 +74714 0.54388427734375 +74715 0.5728759765625 +74716 0.506591796875 +74717 0.351226806640625 +74718 0.146514892578125 +74719 -0.05523681640625 +74720 -0.21624755859375 +74721 -0.334930419921875 +74722 -0.402984619140625 +74723 -0.4412841796875 +74724 -0.49578857421875 +74725 -0.5601806640625 +74726 -0.600738525390625 +74727 -0.584228515625 +74728 -0.47930908203125 +74729 -0.27935791015625 +74730 -0.0089111328125 +74731 0.268798828125 +74732 0.482818603515625 +74733 0.60369873046875 +74734 0.650421142578125 +74735 0.66400146484375 +74736 0.6414794921875 +74737 0.572540283203125 +74738 0.498138427734375 +74739 0.439453125 +74740 0.375518798828125 +74741 0.274505615234375 +74742 0.1087646484375 +74743 -0.099395751953125 +74744 -0.3182373046875 +74745 -0.5489501953125 +74746 -0.7738037109375 +74747 -0.86383056640625 +74748 -0.870391845703125 +74749 -0.86895751953125 +74750 -0.861053466796875 +74751 -0.765869140625 +74752 -0.5301513671875 +74753 -0.214691162109375 +74754 0.137359619140625 +74755 0.474822998046875 +74756 0.76239013671875 +74757 0.867462158203125 +74758 0.870361328125 +74759 0.86480712890625 +74760 0.831817626953125 +74761 0.677581787109375 +74762 0.495880126953125 +74763 0.30767822265625 +74764 0.116180419921875 +74765 -0.110748291015625 +74766 -0.381805419921875 +74767 -0.6572265625 +74768 -0.857421875 +74769 -0.870391845703125 +74770 -0.870391845703125 +74771 -0.86444091796875 +74772 -0.85723876953125 +74773 -0.790008544921875 +74774 -0.62847900390625 +74775 -0.3956298828125 +74776 -0.126708984375 +74777 0.150115966796875 +74778 0.424041748046875 +74779 0.670623779296875 +74780 0.854522705078125 +74781 0.866485595703125 +74782 0.86920166015625 +74783 0.8653564453125 +74784 0.857147216796875 +74785 0.766845703125 +74786 0.628509521484375 +74787 0.462127685546875 +74788 0.297210693359375 +74789 0.14862060546875 +74790 -0.00537109375 +74791 -0.15753173828125 +74792 -0.31304931640625 +74793 -0.48876953125 +74794 -0.6416015625 +74795 -0.751373291015625 +74796 -0.84619140625 +74797 -0.861297607421875 +74798 -0.863250732421875 +74799 -0.856597900390625 +74800 -0.7498779296875 +74801 -0.624542236328125 +74802 -0.47808837890625 +74803 -0.253387451171875 +74804 0.003692626953125 +74805 0.2257080078125 +74806 0.427154541015625 +74807 0.643218994140625 +74808 0.855926513671875 +74809 0.870361328125 +74810 0.870361328125 +74811 0.862762451171875 +74812 0.79669189453125 +74813 0.595794677734375 +74814 0.362152099609375 +74815 0.1270751953125 +74816 -0.086944580078125 +74817 -0.2784423828125 +74818 -0.484832763671875 +74819 -0.729583740234375 +74820 -0.86688232421875 +74821 -0.870391845703125 +74822 -0.86859130859375 +74823 -0.86279296875 +74824 -0.817962646484375 +74825 -0.6116943359375 +74826 -0.3128662109375 +74827 0.039398193359375 +74828 0.422821044921875 +74829 0.805145263671875 +74830 0.870361328125 +74831 0.870361328125 +74832 0.860015869140625 +74833 0.727935791015625 +74834 0.48114013671875 +74835 0.2059326171875 +74836 -0.06103515625 +74837 -0.29913330078125 +74838 -0.516204833984375 +74839 -0.7252197265625 +74840 -0.85980224609375 +74841 -0.870391845703125 +74842 -0.870391845703125 +74843 -0.858062744140625 +74844 -0.673004150390625 +74845 -0.42694091796875 +74846 -0.2100830078125 +74847 -0.0362548828125 +74848 0.10943603515625 +74849 0.23516845703125 +74850 0.373687744140625 +74851 0.517791748046875 +74852 0.602783203125 +74853 0.635711669921875 +74854 0.655181884765625 +74855 0.65948486328125 +74856 0.651275634765625 +74857 0.61846923828125 +74858 0.53753662109375 +74859 0.404144287109375 +74860 0.22186279296875 +74861 0.003997802734375 +74862 -0.22100830078125 +74863 -0.42449951171875 +74864 -0.579833984375 +74865 -0.641876220703125 +74866 -0.6177978515625 +74867 -0.575531005859375 +74868 -0.526336669921875 +74869 -0.42645263671875 +74870 -0.2581787109375 +74871 -0.068695068359375 +74872 0.09222412109375 +74873 0.232147216796875 +74874 0.3509521484375 +74875 0.410064697265625 +74876 0.372955322265625 +74877 0.2554931640625 +74878 0.10711669921875 +74879 -0.052886962890625 +74880 -0.186279296875 +74881 -0.23291015625 +74882 -0.209442138671875 +74883 -0.174163818359375 +74884 -0.126739501953125 +74885 -0.048126220703125 +74886 0.0426025390625 +74887 0.10748291015625 +74888 0.1409912109375 +74889 0.19708251953125 +74890 0.273651123046875 +74891 0.31768798828125 +74892 0.341094970703125 +74893 0.368011474609375 +74894 0.37249755859375 +74895 0.30072021484375 +74896 0.1517333984375 +74897 -0.01470947265625 +74898 -0.1883544921875 +74899 -0.372711181640625 +74900 -0.51397705078125 +74901 -0.57177734375 +74902 -0.53948974609375 +74903 -0.43511962890625 +74904 -0.2962646484375 +74905 -0.161102294921875 +74906 -0.0435791015625 +74907 0.060394287109375 +74908 0.13665771484375 +74909 0.170135498046875 +74910 0.16552734375 +74911 0.15728759765625 +74912 0.150787353515625 +74913 0.12200927734375 +74914 0.080108642578125 +74915 0.05126953125 +74916 0.062896728515625 +74917 0.09271240234375 +74918 0.092987060546875 +74919 0.07855224609375 +74920 0.06427001953125 +74921 0.0347900390625 +74922 -0.01171875 +74923 -0.056060791015625 +74924 -0.055511474609375 +74925 -0.010467529296875 +74926 0.02508544921875 +74927 0.025665283203125 +74928 0.017333984375 +74929 0.00189208984375 +74930 -0.03173828125 +74931 -0.071502685546875 +74932 -0.13543701171875 +74933 -0.219970703125 +74934 -0.300506591796875 +74935 -0.376312255859375 +74936 -0.416107177734375 +74937 -0.371124267578125 +74938 -0.242279052734375 +74939 -0.069732666015625 +74940 0.125640869140625 +74941 0.31268310546875 +74942 0.45501708984375 +74943 0.554779052734375 +74944 0.61065673828125 +74945 0.610931396484375 +74946 0.531463623046875 +74947 0.3883056640625 +74948 0.23468017578125 +74949 0.095245361328125 +74950 -0.00396728515625 +74951 -0.04852294921875 +74952 -0.055145263671875 +74953 -0.0758056640625 +74954 -0.138702392578125 +74955 -0.209197998046875 +74956 -0.289031982421875 +74957 -0.37884521484375 +74958 -0.456329345703125 +74959 -0.51641845703125 +74960 -0.519287109375 +74961 -0.458251953125 +74962 -0.384796142578125 +74963 -0.323699951171875 +74964 -0.269287109375 +74965 -0.1951904296875 +74966 -0.100006103515625 +74967 -0.01055908203125 +74968 0.1033935546875 +74969 0.24908447265625 +74970 0.373199462890625 +74971 0.45806884765625 +74972 0.511474609375 +74973 0.565399169921875 +74974 0.61138916015625 +74975 0.5897216796875 +74976 0.4906005859375 +74977 0.33148193359375 +74978 0.147796630859375 +74979 -0.01873779296875 +74980 -0.140289306640625 +74981 -0.191986083984375 +74982 -0.184295654296875 +74983 -0.161834716796875 +74984 -0.166595458984375 +74985 -0.19390869140625 +74986 -0.22442626953125 +74987 -0.279754638671875 +74988 -0.3389892578125 +74989 -0.3543701171875 +74990 -0.348175048828125 +74991 -0.32598876953125 +74992 -0.2581787109375 +74993 -0.139801025390625 +74994 0.014617919921875 +74995 0.144378662109375 +74996 0.221038818359375 +74997 0.27069091796875 +74998 0.294036865234375 +74999 0.311767578125 +75000 0.339141845703125 +75001 0.360260009765625 +75002 0.360504150390625 +75003 0.308380126953125 +75004 0.18170166015625 +75005 0.0047607421875 +75006 -0.17559814453125 +75007 -0.3143310546875 +75008 -0.36785888671875 +75009 -0.36248779296875 +75010 -0.343536376953125 +75011 -0.3018798828125 +75012 -0.231414794921875 +75013 -0.117645263671875 +75014 0.007049560546875 +75015 0.087982177734375 +75016 0.13946533203125 +75017 0.17425537109375 +75018 0.188201904296875 +75019 0.171234130859375 +75020 0.118438720703125 +75021 0.05706787109375 +75022 -0.010711669921875 +75023 -0.0914306640625 +75024 -0.162322998046875 +75025 -0.194549560546875 +75026 -0.1492919921875 +75027 -0.02166748046875 +75028 0.124053955078125 +75029 0.211151123046875 +75030 0.240447998046875 +75031 0.242218017578125 +75032 0.2257080078125 +75033 0.194366455078125 +75034 0.115509033203125 +75035 0.0128173828125 +75036 -0.053802490234375 +75037 -0.110626220703125 +75038 -0.199493408203125 +75039 -0.29437255859375 +75040 -0.33221435546875 +75041 -0.27972412109375 +75042 -0.185333251953125 +75043 -0.128204345703125 +75044 -0.115692138671875 +75045 -0.116455078125 +75046 -0.105926513671875 +75047 -0.053955078125 +75048 0.048797607421875 +75049 0.157318115234375 +75050 0.212005615234375 +75051 0.218475341796875 +75052 0.23724365234375 +75053 0.30535888671875 +75054 0.38128662109375 +75055 0.404449462890625 +75056 0.3944091796875 +75057 0.3885498046875 +75058 0.362640380859375 +75059 0.27362060546875 +75060 0.11712646484375 +75061 -0.054901123046875 +75062 -0.19085693359375 +75063 -0.28570556640625 +75064 -0.339263916015625 +75065 -0.3775634765625 +75066 -0.445709228515625 +75067 -0.535064697265625 +75068 -0.629058837890625 +75069 -0.697601318359375 +75070 -0.70391845703125 +75071 -0.6424560546875 +75072 -0.491241455078125 +75073 -0.265716552734375 +75074 -0.023712158203125 +75075 0.201751708984375 +75076 0.375823974609375 +75077 0.485076904296875 +75078 0.56884765625 +75079 0.634765625 +75080 0.63763427734375 +75081 0.5660400390625 +75082 0.4720458984375 +75083 0.40692138671875 +75084 0.3778076171875 +75085 0.376953125 +75086 0.371978759765625 +75087 0.313140869140625 +75088 0.184417724609375 +75089 0.011199951171875 +75090 -0.171051025390625 +75091 -0.33740234375 +75092 -0.47198486328125 +75093 -0.560394287109375 +75094 -0.58056640625 +75095 -0.54754638671875 +75096 -0.508575439453125 +75097 -0.459503173828125 +75098 -0.394378662109375 +75099 -0.35260009765625 +75100 -0.31170654296875 +75101 -0.197418212890625 +75102 -0.007965087890625 +75103 0.207489013671875 +75104 0.409210205078125 +75105 0.57208251953125 +75106 0.66595458984375 +75107 0.65875244140625 +75108 0.56744384765625 +75109 0.431396484375 +75110 0.29443359375 +75111 0.182464599609375 +75112 0.06365966796875 +75113 -0.075958251953125 +75114 -0.189422607421875 +75115 -0.271942138671875 +75116 -0.342529296875 +75117 -0.364166259765625 +75118 -0.327239990234375 +75119 -0.2769775390625 +75120 -0.253692626953125 +75121 -0.24365234375 +75122 -0.1983642578125 +75123 -0.116241455078125 +75124 -0.036834716796875 +75125 0.034881591796875 +75126 0.09124755859375 +75127 0.10888671875 +75128 0.125518798828125 +75129 0.15771484375 +75130 0.17828369140625 +75131 0.17108154296875 +75132 0.129974365234375 +75133 0.082427978515625 +75134 0.027679443359375 +75135 -0.065643310546875 +75136 -0.15936279296875 +75137 -0.21307373046875 +75138 -0.234649658203125 +75139 -0.2001953125 +75140 -0.119171142578125 +75141 -0.024749755859375 +75142 0.085784912109375 +75143 0.178131103515625 +75144 0.215576171875 +75145 0.211456298828125 +75146 0.17523193359375 +75147 0.128753662109375 +75148 0.1019287109375 +75149 0.0743408203125 +75150 0.04327392578125 +75151 0.038177490234375 +75152 0.076263427734375 +75153 0.14105224609375 +75154 0.186431884765625 +75155 0.188812255859375 +75156 0.1390380859375 +75157 0.041778564453125 +75158 -0.079437255859375 +75159 -0.219390869140625 +75160 -0.367828369140625 +75161 -0.494873046875 +75162 -0.556243896484375 +75163 -0.508697509765625 +75164 -0.3756103515625 +75165 -0.218902587890625 +75166 -0.063751220703125 +75167 0.091552734375 +75168 0.23602294921875 +75169 0.342987060546875 +75170 0.39520263671875 +75171 0.389373779296875 +75172 0.324249267578125 +75173 0.224090576171875 +75174 0.124267578125 +75175 0.037078857421875 +75176 -0.010101318359375 +75177 -0.019439697265625 +75178 -0.022796630859375 +75179 -0.001556396484375 +75180 0.056304931640625 +75181 0.106719970703125 +75182 0.096893310546875 +75183 0.042694091796875 +75184 -0.018035888671875 +75185 -0.07586669921875 +75186 -0.11944580078125 +75187 -0.15972900390625 +75188 -0.202606201171875 +75189 -0.24859619140625 +75190 -0.30517578125 +75191 -0.36212158203125 +75192 -0.39141845703125 +75193 -0.35528564453125 +75194 -0.249969482421875 +75195 -0.092864990234375 +75196 0.08905029296875 +75197 0.2352294921875 +75198 0.318817138671875 +75199 0.358642578125 +75200 0.347747802734375 +75201 0.28564453125 +75202 0.223175048828125 +75203 0.196746826171875 +75204 0.179840087890625 +75205 0.155548095703125 +75206 0.151214599609375 +75207 0.156951904296875 +75208 0.13177490234375 +75209 0.100799560546875 +75210 0.087127685546875 +75211 0.05487060546875 +75212 -0.009002685546875 +75213 -0.10400390625 +75214 -0.229400634765625 +75215 -0.35552978515625 +75216 -0.441925048828125 +75217 -0.473846435546875 +75218 -0.464813232421875 +75219 -0.419097900390625 +75220 -0.334320068359375 +75221 -0.227935791015625 +75222 -0.12347412109375 +75223 -0.02764892578125 +75224 0.077667236328125 +75225 0.2132568359375 +75226 0.38885498046875 +75227 0.582794189453125 +75228 0.734039306640625 +75229 0.800140380859375 +75230 0.7783203125 +75231 0.6651611328125 +75232 0.45965576171875 +75233 0.199188232421875 +75234 -0.050689697265625 +75235 -0.23297119140625 +75236 -0.33013916015625 +75237 -0.368408203125 +75238 -0.378936767578125 +75239 -0.376983642578125 +75240 -0.37969970703125 +75241 -0.391510009765625 +75242 -0.385345458984375 +75243 -0.3419189453125 +75244 -0.28289794921875 +75245 -0.251617431640625 +75246 -0.266143798828125 +75247 -0.273345947265625 +75248 -0.216796875 +75249 -0.128265380859375 +75250 -0.068145751953125 +75251 -0.0430908203125 +75252 -0.024444580078125 +75253 0.020721435546875 +75254 0.124481201171875 +75255 0.25787353515625 +75256 0.379119873046875 +75257 0.47991943359375 +75258 0.5281982421875 +75259 0.511138916015625 +75260 0.456207275390625 +75261 0.407470703125 +75262 0.383758544921875 +75263 0.35687255859375 +75264 0.31182861328125 +75265 0.250885009765625 +75266 0.1654052734375 +75267 0.035247802734375 +75268 -0.142059326171875 +75269 -0.33563232421875 +75270 -0.5345458984375 +75271 -0.72186279296875 +75272 -0.836669921875 +75273 -0.8326416015625 +75274 -0.7296142578125 +75275 -0.582550048828125 +75276 -0.440093994140625 +75277 -0.324310302734375 +75278 -0.20147705078125 +75279 -0.044647216796875 +75280 0.103973388671875 +75281 0.202392578125 +75282 0.264495849609375 +75283 0.338897705078125 +75284 0.443817138671875 +75285 0.545074462890625 +75286 0.6173095703125 +75287 0.6524658203125 +75288 0.66339111328125 +75289 0.6561279296875 +75290 0.606781005859375 +75291 0.501190185546875 +75292 0.352783203125 +75293 0.176544189453125 +75294 -0.034820556640625 +75295 -0.258209228515625 +75296 -0.44244384765625 +75297 -0.5753173828125 +75298 -0.65203857421875 +75299 -0.641632080078125 +75300 -0.562164306640625 +75301 -0.458038330078125 +75302 -0.350555419921875 +75303 -0.260528564453125 +75304 -0.192108154296875 +75305 -0.141937255859375 +75306 -0.1021728515625 +75307 -0.062896728515625 +75308 -0.011932373046875 +75309 0.062835693359375 +75310 0.148712158203125 +75311 0.241729736328125 +75312 0.34912109375 +75313 0.457305908203125 +75314 0.54388427734375 +75315 0.5728759765625 +75316 0.506591796875 +75317 0.351226806640625 +75318 0.146514892578125 +75319 -0.05523681640625 +75320 -0.21624755859375 +75321 -0.334930419921875 +75322 -0.402984619140625 +75323 -0.4412841796875 +75324 -0.49578857421875 +75325 -0.5601806640625 +75326 -0.600738525390625 +75327 -0.584228515625 +75328 -0.47930908203125 +75329 -0.27935791015625 +75330 -0.0089111328125 +75331 0.268798828125 +75332 0.482818603515625 +75333 0.60369873046875 +75334 0.650421142578125 +75335 0.66400146484375 +75336 0.6414794921875 +75337 0.572540283203125 +75338 0.498138427734375 +75339 0.439453125 +75340 0.375518798828125 +75341 0.274505615234375 +75342 0.1087646484375 +75343 -0.099395751953125 +75344 -0.3182373046875 +75345 -0.5489501953125 +75346 -0.7738037109375 +75347 -0.86383056640625 +75348 -0.870391845703125 +75349 -0.86895751953125 +75350 -0.861053466796875 +75351 -0.765869140625 +75352 -0.5301513671875 +75353 -0.214691162109375 +75354 0.137359619140625 +75355 0.474822998046875 +75356 0.76239013671875 +75357 0.867462158203125 +75358 0.870361328125 +75359 0.86480712890625 +75360 0.831817626953125 +75361 0.677581787109375 +75362 0.495880126953125 +75363 0.30767822265625 +75364 0.116180419921875 +75365 -0.110748291015625 +75366 -0.381805419921875 +75367 -0.6572265625 +75368 -0.857421875 +75369 -0.870391845703125 +75370 -0.870391845703125 +75371 -0.86444091796875 +75372 -0.85723876953125 +75373 -0.790008544921875 +75374 -0.62847900390625 +75375 -0.3956298828125 +75376 -0.126708984375 +75377 0.150115966796875 +75378 0.424041748046875 +75379 0.670623779296875 +75380 0.854522705078125 +75381 0.866485595703125 +75382 0.86920166015625 +75383 0.8653564453125 +75384 0.857147216796875 +75385 0.766845703125 +75386 0.628509521484375 +75387 0.462127685546875 +75388 0.297210693359375 +75389 0.14862060546875 +75390 -0.00537109375 +75391 -0.15753173828125 +75392 -0.31304931640625 +75393 -0.48876953125 +75394 -0.6416015625 +75395 -0.751373291015625 +75396 -0.84619140625 +75397 -0.861297607421875 +75398 -0.863250732421875 +75399 -0.856597900390625 +75400 -0.7498779296875 +75401 -0.624542236328125 +75402 -0.47808837890625 +75403 -0.253387451171875 +75404 0.003692626953125 +75405 0.2257080078125 +75406 0.427154541015625 +75407 0.643218994140625 +75408 0.855926513671875 +75409 0.870361328125 +75410 0.870361328125 +75411 0.862762451171875 +75412 0.79669189453125 +75413 0.595794677734375 +75414 0.362152099609375 +75415 0.1270751953125 +75416 -0.086944580078125 +75417 -0.2784423828125 +75418 -0.484832763671875 +75419 -0.729583740234375 +75420 -0.86688232421875 +75421 -0.870391845703125 +75422 -0.86859130859375 +75423 -0.86279296875 +75424 -0.817962646484375 +75425 -0.6116943359375 +75426 -0.3128662109375 +75427 0.039398193359375 +75428 0.422821044921875 +75429 0.805145263671875 +75430 0.870361328125 +75431 0.870361328125 +75432 0.860015869140625 +75433 0.727935791015625 +75434 0.48114013671875 +75435 0.2059326171875 +75436 -0.06103515625 +75437 -0.29913330078125 +75438 -0.516204833984375 +75439 -0.7252197265625 +75440 -0.85980224609375 +75441 -0.870391845703125 +75442 -0.870391845703125 +75443 -0.858062744140625 +75444 -0.673004150390625 +75445 -0.42694091796875 +75446 -0.2100830078125 +75447 -0.0362548828125 +75448 0.10943603515625 +75449 0.23516845703125 +75450 0.373687744140625 +75451 0.517791748046875 +75452 0.602783203125 +75453 0.635711669921875 +75454 0.655181884765625 +75455 0.65948486328125 +75456 0.651275634765625 +75457 0.61846923828125 +75458 0.53753662109375 +75459 0.404144287109375 +75460 0.22186279296875 +75461 0.003997802734375 +75462 -0.22100830078125 +75463 -0.42449951171875 +75464 -0.579833984375 +75465 -0.641876220703125 +75466 -0.6177978515625 +75467 -0.575531005859375 +75468 -0.526336669921875 +75469 -0.42645263671875 +75470 -0.2581787109375 +75471 -0.068695068359375 +75472 0.09222412109375 +75473 0.232147216796875 +75474 0.3509521484375 +75475 0.410064697265625 +75476 0.372955322265625 +75477 0.2554931640625 +75478 0.10711669921875 +75479 -0.052886962890625 +75480 -0.186279296875 +75481 -0.23291015625 +75482 -0.209442138671875 +75483 -0.174163818359375 +75484 -0.126739501953125 +75485 -0.048126220703125 +75486 0.0426025390625 +75487 0.10748291015625 +75488 0.1409912109375 +75489 0.19708251953125 +75490 0.273651123046875 +75491 0.31768798828125 +75492 0.341094970703125 +75493 0.368011474609375 +75494 0.37249755859375 +75495 0.30072021484375 +75496 0.1517333984375 +75497 -0.01470947265625 +75498 -0.1883544921875 +75499 -0.372711181640625 +75500 -0.51397705078125 +75501 -0.57177734375 +75502 -0.53948974609375 +75503 -0.43511962890625 +75504 -0.2962646484375 +75505 -0.161102294921875 +75506 -0.0435791015625 +75507 0.060394287109375 +75508 0.13665771484375 +75509 0.170135498046875 +75510 0.16552734375 +75511 0.15728759765625 +75512 0.150787353515625 +75513 0.12200927734375 +75514 0.080108642578125 +75515 0.05126953125 +75516 0.062896728515625 +75517 0.09271240234375 +75518 0.092987060546875 +75519 0.07855224609375 +75520 0.06427001953125 +75521 0.0347900390625 +75522 -0.01171875 +75523 -0.056060791015625 +75524 -0.055511474609375 +75525 -0.010467529296875 +75526 0.02508544921875 +75527 0.025665283203125 +75528 0.017333984375 +75529 0.00189208984375 +75530 -0.03173828125 +75531 -0.071502685546875 +75532 -0.13543701171875 +75533 -0.219970703125 +75534 -0.300506591796875 +75535 -0.376312255859375 +75536 -0.416107177734375 +75537 -0.371124267578125 +75538 -0.242279052734375 +75539 -0.069732666015625 +75540 0.125640869140625 +75541 0.31268310546875 +75542 0.45501708984375 +75543 0.554779052734375 +75544 0.61065673828125 +75545 0.610931396484375 +75546 0.531463623046875 +75547 0.3883056640625 +75548 0.23468017578125 +75549 0.095245361328125 +75550 -0.00396728515625 +75551 -0.04852294921875 +75552 -0.055145263671875 +75553 -0.0758056640625 +75554 -0.138702392578125 +75555 -0.209197998046875 +75556 -0.289031982421875 +75557 -0.37884521484375 +75558 -0.456329345703125 +75559 -0.51641845703125 +75560 -0.519287109375 +75561 -0.458251953125 +75562 -0.384796142578125 +75563 -0.323699951171875 +75564 -0.269287109375 +75565 -0.1951904296875 +75566 -0.100006103515625 +75567 -0.01055908203125 +75568 0.1033935546875 +75569 0.24908447265625 +75570 0.373199462890625 +75571 0.45806884765625 +75572 0.511474609375 +75573 0.565399169921875 +75574 0.61138916015625 +75575 0.5897216796875 +75576 0.4906005859375 +75577 0.33148193359375 +75578 0.147796630859375 +75579 -0.01873779296875 +75580 -0.140289306640625 +75581 -0.191986083984375 +75582 -0.184295654296875 +75583 -0.161834716796875 +75584 -0.166595458984375 +75585 -0.19390869140625 +75586 -0.22442626953125 +75587 -0.279754638671875 +75588 -0.3389892578125 +75589 -0.3543701171875 +75590 -0.348175048828125 +75591 -0.32598876953125 +75592 -0.2581787109375 +75593 -0.139801025390625 +75594 0.014617919921875 +75595 0.144378662109375 +75596 0.221038818359375 +75597 0.27069091796875 +75598 0.294036865234375 +75599 0.311767578125 +75600 0.339141845703125 +75601 0.360260009765625 +75602 0.360504150390625 +75603 0.308380126953125 +75604 0.18170166015625 +75605 0.0047607421875 +75606 -0.17559814453125 +75607 -0.3143310546875 +75608 -0.36785888671875 +75609 -0.36248779296875 +75610 -0.343536376953125 +75611 -0.3018798828125 +75612 -0.231414794921875 +75613 -0.117645263671875 +75614 0.007049560546875 +75615 0.087982177734375 +75616 0.13946533203125 +75617 0.17425537109375 +75618 0.188201904296875 +75619 0.171234130859375 +75620 0.118438720703125 +75621 0.05706787109375 +75622 -0.010711669921875 +75623 -0.0914306640625 +75624 -0.162322998046875 +75625 -0.194549560546875 +75626 -0.1492919921875 +75627 -0.02166748046875 +75628 0.124053955078125 +75629 0.211151123046875 +75630 0.240447998046875 +75631 0.242218017578125 +75632 0.2257080078125 +75633 0.194366455078125 +75634 0.115509033203125 +75635 0.0128173828125 +75636 -0.053802490234375 +75637 -0.110626220703125 +75638 -0.199493408203125 +75639 -0.29437255859375 +75640 -0.33221435546875 +75641 -0.27972412109375 +75642 -0.185333251953125 +75643 -0.128204345703125 +75644 -0.115692138671875 +75645 -0.116455078125 +75646 -0.105926513671875 +75647 -0.053955078125 +75648 0.048797607421875 +75649 0.157318115234375 +75650 0.212005615234375 +75651 0.218475341796875 +75652 0.23724365234375 +75653 0.30535888671875 +75654 0.38128662109375 +75655 0.404449462890625 +75656 0.3944091796875 +75657 0.3885498046875 +75658 0.362640380859375 +75659 0.27362060546875 +75660 0.11712646484375 +75661 -0.054901123046875 +75662 -0.19085693359375 +75663 -0.28570556640625 +75664 -0.339263916015625 +75665 -0.3775634765625 +75666 -0.445709228515625 +75667 -0.535064697265625 +75668 -0.629058837890625 +75669 -0.697601318359375 +75670 -0.70391845703125 +75671 -0.6424560546875 +75672 -0.491241455078125 +75673 -0.265716552734375 +75674 -0.023712158203125 +75675 0.201751708984375 +75676 0.375823974609375 +75677 0.485076904296875 +75678 0.56884765625 +75679 0.634765625 +75680 0.63763427734375 +75681 0.5660400390625 +75682 0.4720458984375 +75683 0.40692138671875 +75684 0.3778076171875 +75685 0.376953125 +75686 0.371978759765625 +75687 0.313140869140625 +75688 0.184417724609375 +75689 0.011199951171875 +75690 -0.171051025390625 +75691 -0.33740234375 +75692 -0.47198486328125 +75693 -0.560394287109375 +75694 -0.58056640625 +75695 -0.54754638671875 +75696 -0.508575439453125 +75697 -0.459503173828125 +75698 -0.394378662109375 +75699 -0.35260009765625 +75700 -0.31170654296875 +75701 -0.197418212890625 +75702 -0.007965087890625 +75703 0.207489013671875 +75704 0.409210205078125 +75705 0.57208251953125 +75706 0.66595458984375 +75707 0.65875244140625 +75708 0.56744384765625 +75709 0.431396484375 +75710 0.29443359375 +75711 0.182464599609375 +75712 0.06365966796875 +75713 -0.075958251953125 +75714 -0.189422607421875 +75715 -0.271942138671875 +75716 -0.342529296875 +75717 -0.364166259765625 +75718 -0.327239990234375 +75719 -0.2769775390625 +75720 -0.253692626953125 +75721 -0.24365234375 +75722 -0.1983642578125 +75723 -0.116241455078125 +75724 -0.036834716796875 +75725 0.034881591796875 +75726 0.09124755859375 +75727 0.10888671875 +75728 0.125518798828125 +75729 0.15771484375 +75730 0.17828369140625 +75731 0.17108154296875 +75732 0.129974365234375 +75733 0.082427978515625 +75734 0.027679443359375 +75735 -0.065643310546875 +75736 -0.15936279296875 +75737 -0.21307373046875 +75738 -0.234649658203125 +75739 -0.2001953125 +75740 -0.119171142578125 +75741 -0.024749755859375 +75742 0.085784912109375 +75743 0.178131103515625 +75744 0.215576171875 +75745 0.211456298828125 +75746 0.17523193359375 +75747 0.128753662109375 +75748 0.1019287109375 +75749 0.0743408203125 +75750 0.04327392578125 +75751 0.038177490234375 +75752 0.076263427734375 +75753 0.14105224609375 +75754 0.186431884765625 +75755 0.188812255859375 +75756 0.1390380859375 +75757 0.041778564453125 +75758 -0.079437255859375 +75759 -0.219390869140625 +75760 -0.367828369140625 +75761 -0.494873046875 +75762 -0.556243896484375 +75763 -0.508697509765625 +75764 -0.3756103515625 +75765 -0.218902587890625 +75766 -0.063751220703125 +75767 0.091552734375 +75768 0.23602294921875 +75769 0.342987060546875 +75770 0.39520263671875 +75771 0.389373779296875 +75772 0.324249267578125 +75773 0.224090576171875 +75774 0.124267578125 +75775 0.037078857421875 +75776 -0.010101318359375 +75777 -0.019439697265625 +75778 -0.022796630859375 +75779 -0.001556396484375 +75780 0.056304931640625 +75781 0.106719970703125 +75782 0.096893310546875 +75783 0.042694091796875 +75784 -0.018035888671875 +75785 -0.07586669921875 +75786 -0.11944580078125 +75787 -0.15972900390625 +75788 -0.202606201171875 +75789 -0.24859619140625 +75790 -0.30517578125 +75791 -0.36212158203125 +75792 -0.39141845703125 +75793 -0.35528564453125 +75794 -0.249969482421875 +75795 -0.092864990234375 +75796 0.08905029296875 +75797 0.2352294921875 +75798 0.318817138671875 +75799 0.358642578125 +75800 0.347747802734375 +75801 0.28564453125 +75802 0.223175048828125 +75803 0.196746826171875 +75804 0.179840087890625 +75805 0.155548095703125 +75806 0.151214599609375 +75807 0.156951904296875 +75808 0.13177490234375 +75809 0.100799560546875 +75810 0.087127685546875 +75811 0.05487060546875 +75812 -0.009002685546875 +75813 -0.10400390625 +75814 -0.229400634765625 +75815 -0.35552978515625 +75816 -0.441925048828125 +75817 -0.473846435546875 +75818 -0.464813232421875 +75819 -0.419097900390625 +75820 -0.334320068359375 +75821 -0.227935791015625 +75822 -0.12347412109375 +75823 -0.02764892578125 +75824 0.077667236328125 +75825 0.2132568359375 +75826 0.38885498046875 +75827 0.582794189453125 +75828 0.734039306640625 +75829 0.800140380859375 +75830 0.7783203125 +75831 0.6651611328125 +75832 0.45965576171875 +75833 0.199188232421875 +75834 -0.050689697265625 +75835 -0.23297119140625 +75836 -0.33013916015625 +75837 -0.368408203125 +75838 -0.378936767578125 +75839 -0.376983642578125 +75840 -0.37969970703125 +75841 -0.391510009765625 +75842 -0.385345458984375 +75843 -0.3419189453125 +75844 -0.28289794921875 +75845 -0.251617431640625 +75846 -0.266143798828125 +75847 -0.273345947265625 +75848 -0.216796875 +75849 -0.128265380859375 +75850 -0.068145751953125 +75851 -0.0430908203125 +75852 -0.024444580078125 +75853 0.020721435546875 +75854 0.124481201171875 +75855 0.25787353515625 +75856 0.379119873046875 +75857 0.47991943359375 +75858 0.5281982421875 +75859 0.511138916015625 +75860 0.456207275390625 +75861 0.407470703125 +75862 0.383758544921875 +75863 0.35687255859375 +75864 0.31182861328125 +75865 0.250885009765625 +75866 0.1654052734375 +75867 0.035247802734375 +75868 -0.142059326171875 +75869 -0.33563232421875 +75870 -0.5345458984375 +75871 -0.72186279296875 +75872 -0.836669921875 +75873 -0.8326416015625 +75874 -0.7296142578125 +75875 -0.582550048828125 +75876 -0.440093994140625 +75877 -0.324310302734375 +75878 -0.20147705078125 +75879 -0.044647216796875 +75880 0.103973388671875 +75881 0.202392578125 +75882 0.264495849609375 +75883 0.338897705078125 +75884 0.443817138671875 +75885 0.545074462890625 +75886 0.6173095703125 +75887 0.6524658203125 +75888 0.66339111328125 +75889 0.6561279296875 +75890 0.606781005859375 +75891 0.501190185546875 +75892 0.352783203125 +75893 0.176544189453125 +75894 -0.034820556640625 +75895 -0.258209228515625 +75896 -0.44244384765625 +75897 -0.5753173828125 +75898 -0.65203857421875 +75899 -0.641632080078125 +75900 -0.562164306640625 +75901 -0.458038330078125 +75902 -0.350555419921875 +75903 -0.260528564453125 +75904 -0.192108154296875 +75905 -0.141937255859375 +75906 -0.1021728515625 +75907 -0.062896728515625 +75908 -0.011932373046875 +75909 0.062835693359375 +75910 0.148712158203125 +75911 0.241729736328125 +75912 0.34912109375 +75913 0.457305908203125 +75914 0.54388427734375 +75915 0.5728759765625 +75916 0.506591796875 +75917 0.351226806640625 +75918 0.146514892578125 +75919 -0.05523681640625 +75920 -0.21624755859375 +75921 -0.334930419921875 +75922 -0.402984619140625 +75923 -0.4412841796875 +75924 -0.49578857421875 +75925 -0.5601806640625 +75926 -0.600738525390625 +75927 -0.584228515625 +75928 -0.47930908203125 +75929 -0.27935791015625 +75930 -0.0089111328125 +75931 0.268798828125 +75932 0.482818603515625 +75933 0.60369873046875 +75934 0.650421142578125 +75935 0.66400146484375 +75936 0.6414794921875 +75937 0.572540283203125 +75938 0.498138427734375 +75939 0.439453125 +75940 0.375518798828125 +75941 0.274505615234375 +75942 0.1087646484375 +75943 -0.099395751953125 +75944 -0.3182373046875 +75945 -0.5489501953125 +75946 -0.7738037109375 +75947 -0.86383056640625 +75948 -0.870391845703125 +75949 -0.86895751953125 +75950 -0.861053466796875 +75951 -0.765869140625 +75952 -0.5301513671875 +75953 -0.214691162109375 +75954 0.137359619140625 +75955 0.474822998046875 +75956 0.76239013671875 +75957 0.867462158203125 +75958 0.870361328125 +75959 0.86480712890625 +75960 0.831817626953125 +75961 0.677581787109375 +75962 0.495880126953125 +75963 0.30767822265625 +75964 0.116180419921875 +75965 -0.110748291015625 +75966 -0.381805419921875 +75967 -0.6572265625 +75968 -0.857421875 +75969 -0.870391845703125 +75970 -0.870391845703125 +75971 -0.86444091796875 +75972 -0.85723876953125 +75973 -0.790008544921875 +75974 -0.62847900390625 +75975 -0.3956298828125 +75976 -0.126708984375 +75977 0.150115966796875 +75978 0.424041748046875 +75979 0.670623779296875 +75980 0.854522705078125 +75981 0.866485595703125 +75982 0.86920166015625 +75983 0.8653564453125 +75984 0.857147216796875 +75985 0.766845703125 +75986 0.628509521484375 +75987 0.462127685546875 +75988 0.297210693359375 +75989 0.14862060546875 +75990 -0.00537109375 +75991 -0.15753173828125 +75992 -0.31304931640625 +75993 -0.48876953125 +75994 -0.6416015625 +75995 -0.751373291015625 +75996 -0.84619140625 +75997 -0.861297607421875 +75998 -0.863250732421875 +75999 -0.856597900390625 +76000 -0.7498779296875 +76001 -0.624542236328125 +76002 -0.47808837890625 +76003 -0.253387451171875 +76004 0.003692626953125 +76005 0.2257080078125 +76006 0.427154541015625 +76007 0.643218994140625 +76008 0.855926513671875 +76009 0.870361328125 +76010 0.870361328125 +76011 0.862762451171875 +76012 0.79669189453125 +76013 0.595794677734375 +76014 0.362152099609375 +76015 0.1270751953125 +76016 -0.086944580078125 +76017 -0.2784423828125 +76018 -0.484832763671875 +76019 -0.729583740234375 +76020 -0.86688232421875 +76021 -0.870391845703125 +76022 -0.86859130859375 +76023 -0.86279296875 +76024 -0.817962646484375 +76025 -0.6116943359375 +76026 -0.3128662109375 +76027 0.039398193359375 +76028 0.422821044921875 +76029 0.805145263671875 +76030 0.870361328125 +76031 0.870361328125 +76032 0.860015869140625 +76033 0.727935791015625 +76034 0.48114013671875 +76035 0.2059326171875 +76036 -0.06103515625 +76037 -0.29913330078125 +76038 -0.516204833984375 +76039 -0.7252197265625 +76040 -0.85980224609375 +76041 -0.870391845703125 +76042 -0.870391845703125 +76043 -0.858062744140625 +76044 -0.673004150390625 +76045 -0.42694091796875 +76046 -0.2100830078125 +76047 -0.0362548828125 +76048 0.10943603515625 +76049 0.23516845703125 +76050 0.373687744140625 +76051 0.517791748046875 +76052 0.602783203125 +76053 0.635711669921875 +76054 0.655181884765625 +76055 0.65948486328125 +76056 0.651275634765625 +76057 0.61846923828125 +76058 0.53753662109375 +76059 0.404144287109375 +76060 0.22186279296875 +76061 0.003997802734375 +76062 -0.22100830078125 +76063 -0.42449951171875 +76064 -0.579833984375 +76065 -0.641876220703125 +76066 -0.6177978515625 +76067 -0.575531005859375 +76068 -0.526336669921875 +76069 -0.42645263671875 +76070 -0.2581787109375 +76071 -0.068695068359375 +76072 0.09222412109375 +76073 0.232147216796875 +76074 0.3509521484375 +76075 0.410064697265625 +76076 0.372955322265625 +76077 0.2554931640625 +76078 0.10711669921875 +76079 -0.052886962890625 +76080 -0.186279296875 +76081 -0.23291015625 +76082 -0.209442138671875 +76083 -0.174163818359375 +76084 -0.126739501953125 +76085 -0.048126220703125 +76086 0.0426025390625 +76087 0.10748291015625 +76088 0.1409912109375 +76089 0.19708251953125 +76090 0.273651123046875 +76091 0.31768798828125 +76092 0.341094970703125 +76093 0.368011474609375 +76094 0.37249755859375 +76095 0.30072021484375 +76096 0.1517333984375 +76097 -0.01470947265625 +76098 -0.1883544921875 +76099 -0.372711181640625 +76100 -0.51397705078125 +76101 -0.57177734375 +76102 -0.53948974609375 +76103 -0.43511962890625 +76104 -0.2962646484375 +76105 -0.161102294921875 +76106 -0.0435791015625 +76107 0.060394287109375 +76108 0.13665771484375 +76109 0.170135498046875 +76110 0.16552734375 +76111 0.15728759765625 +76112 0.150787353515625 +76113 0.12200927734375 +76114 0.080108642578125 +76115 0.05126953125 +76116 0.062896728515625 +76117 0.09271240234375 +76118 0.092987060546875 +76119 0.07855224609375 +76120 0.06427001953125 +76121 0.0347900390625 +76122 -0.01171875 +76123 -0.056060791015625 +76124 -0.055511474609375 +76125 -0.010467529296875 +76126 0.02508544921875 +76127 0.025665283203125 +76128 0.017333984375 +76129 0.00189208984375 +76130 -0.03173828125 +76131 -0.071502685546875 +76132 -0.13543701171875 +76133 -0.219970703125 +76134 -0.300506591796875 +76135 -0.376312255859375 +76136 -0.416107177734375 +76137 -0.371124267578125 +76138 -0.242279052734375 +76139 -0.069732666015625 +76140 0.125640869140625 +76141 0.31268310546875 +76142 0.45501708984375 +76143 0.554779052734375 +76144 0.61065673828125 +76145 0.610931396484375 +76146 0.531463623046875 +76147 0.3883056640625 +76148 0.23468017578125 +76149 0.095245361328125 +76150 -0.00396728515625 +76151 -0.04852294921875 +76152 -0.055145263671875 +76153 -0.0758056640625 +76154 -0.138702392578125 +76155 -0.209197998046875 +76156 -0.289031982421875 +76157 -0.37884521484375 +76158 -0.456329345703125 +76159 -0.51641845703125 +76160 -0.519287109375 +76161 -0.458251953125 +76162 -0.384796142578125 +76163 -0.323699951171875 +76164 -0.269287109375 +76165 -0.1951904296875 +76166 -0.100006103515625 +76167 -0.01055908203125 +76168 0.1033935546875 +76169 0.24908447265625 +76170 0.373199462890625 +76171 0.45806884765625 +76172 0.511474609375 +76173 0.565399169921875 +76174 0.61138916015625 +76175 0.5897216796875 +76176 0.4906005859375 +76177 0.33148193359375 +76178 0.147796630859375 +76179 -0.01873779296875 +76180 -0.140289306640625 +76181 -0.191986083984375 +76182 -0.184295654296875 +76183 -0.161834716796875 +76184 -0.166595458984375 +76185 -0.19390869140625 +76186 -0.22442626953125 +76187 -0.279754638671875 +76188 -0.3389892578125 +76189 -0.3543701171875 +76190 -0.348175048828125 +76191 -0.32598876953125 +76192 -0.2581787109375 +76193 -0.139801025390625 +76194 0.014617919921875 +76195 0.144378662109375 +76196 0.221038818359375 +76197 0.27069091796875 +76198 0.294036865234375 +76199 0.311767578125 +76200 0.339141845703125 +76201 0.360260009765625 +76202 0.360504150390625 +76203 0.308380126953125 +76204 0.18170166015625 +76205 0.0047607421875 +76206 -0.17559814453125 +76207 -0.3143310546875 +76208 -0.36785888671875 +76209 -0.36248779296875 +76210 -0.343536376953125 +76211 -0.3018798828125 +76212 -0.231414794921875 +76213 -0.117645263671875 +76214 0.007049560546875 +76215 0.087982177734375 +76216 0.13946533203125 +76217 0.17425537109375 +76218 0.188201904296875 +76219 0.171234130859375 +76220 0.118438720703125 +76221 0.05706787109375 +76222 -0.010711669921875 +76223 -0.0914306640625 +76224 -0.162322998046875 +76225 -0.194549560546875 +76226 -0.1492919921875 +76227 -0.02166748046875 +76228 0.124053955078125 +76229 0.211151123046875 +76230 0.240447998046875 +76231 0.242218017578125 +76232 0.2257080078125 +76233 0.194366455078125 +76234 0.115509033203125 +76235 0.0128173828125 +76236 -0.053802490234375 +76237 -0.110626220703125 +76238 -0.199493408203125 +76239 -0.29437255859375 +76240 -0.33221435546875 +76241 -0.27972412109375 +76242 -0.185333251953125 +76243 -0.128204345703125 +76244 -0.115692138671875 +76245 -0.116455078125 +76246 -0.105926513671875 +76247 -0.053955078125 +76248 0.048797607421875 +76249 0.157318115234375 +76250 0.212005615234375 +76251 0.218475341796875 +76252 0.23724365234375 +76253 0.30535888671875 +76254 0.38128662109375 +76255 0.404449462890625 +76256 0.3944091796875 +76257 0.3885498046875 +76258 0.362640380859375 +76259 0.27362060546875 +76260 0.11712646484375 +76261 -0.054901123046875 +76262 -0.19085693359375 +76263 -0.28570556640625 +76264 -0.339263916015625 +76265 -0.3775634765625 +76266 -0.445709228515625 +76267 -0.535064697265625 +76268 -0.629058837890625 +76269 -0.697601318359375 +76270 -0.70391845703125 +76271 -0.6424560546875 +76272 -0.491241455078125 +76273 -0.265716552734375 +76274 -0.023712158203125 +76275 0.201751708984375 +76276 0.375823974609375 +76277 0.485076904296875 +76278 0.56884765625 +76279 0.634765625 +76280 0.63763427734375 +76281 0.5660400390625 +76282 0.4720458984375 +76283 0.40692138671875 +76284 0.3778076171875 +76285 0.376953125 +76286 0.371978759765625 +76287 0.313140869140625 +76288 0.184417724609375 +76289 0.011199951171875 +76290 -0.171051025390625 +76291 -0.33740234375 +76292 -0.47198486328125 +76293 -0.560394287109375 +76294 -0.58056640625 +76295 -0.54754638671875 +76296 -0.508575439453125 +76297 -0.459503173828125 +76298 -0.394378662109375 +76299 -0.35260009765625 +76300 -0.31170654296875 +76301 -0.197418212890625 +76302 -0.007965087890625 +76303 0.207489013671875 +76304 0.409210205078125 +76305 0.57208251953125 +76306 0.66595458984375 +76307 0.65875244140625 +76308 0.56744384765625 +76309 0.431396484375 +76310 0.29443359375 +76311 0.182464599609375 +76312 0.06365966796875 +76313 -0.075958251953125 +76314 -0.189422607421875 +76315 -0.271942138671875 +76316 -0.342529296875 +76317 -0.364166259765625 +76318 -0.327239990234375 +76319 -0.2769775390625 +76320 -0.253692626953125 +76321 -0.24365234375 +76322 -0.1983642578125 +76323 -0.116241455078125 +76324 -0.036834716796875 +76325 0.034881591796875 +76326 0.09124755859375 +76327 0.10888671875 +76328 0.125518798828125 +76329 0.15771484375 +76330 0.17828369140625 +76331 0.17108154296875 +76332 0.129974365234375 +76333 0.082427978515625 +76334 0.027679443359375 +76335 -0.065643310546875 +76336 -0.15936279296875 +76337 -0.21307373046875 +76338 -0.234649658203125 +76339 -0.2001953125 +76340 -0.119171142578125 +76341 -0.024749755859375 +76342 0.085784912109375 +76343 0.178131103515625 +76344 0.215576171875 +76345 0.211456298828125 +76346 0.17523193359375 +76347 0.128753662109375 +76348 0.1019287109375 +76349 0.0743408203125 +76350 0.04327392578125 +76351 0.038177490234375 +76352 0.076263427734375 +76353 0.14105224609375 +76354 0.186431884765625 +76355 0.188812255859375 +76356 0.1390380859375 +76357 0.041778564453125 +76358 -0.079437255859375 +76359 -0.219390869140625 +76360 -0.367828369140625 +76361 -0.494873046875 +76362 -0.556243896484375 +76363 -0.508697509765625 +76364 -0.3756103515625 +76365 -0.218902587890625 +76366 -0.063751220703125 +76367 0.091552734375 +76368 0.23602294921875 +76369 0.342987060546875 +76370 0.39520263671875 +76371 0.389373779296875 +76372 0.324249267578125 +76373 0.224090576171875 +76374 0.124267578125 +76375 0.037078857421875 +76376 -0.010101318359375 +76377 -0.019439697265625 +76378 -0.022796630859375 +76379 -0.001556396484375 +76380 0.056304931640625 +76381 0.106719970703125 +76382 0.096893310546875 +76383 0.042694091796875 +76384 -0.018035888671875 +76385 -0.07586669921875 +76386 -0.11944580078125 +76387 -0.15972900390625 +76388 -0.202606201171875 +76389 -0.24859619140625 +76390 -0.30517578125 +76391 -0.36212158203125 +76392 -0.39141845703125 +76393 -0.35528564453125 +76394 -0.249969482421875 +76395 -0.092864990234375 +76396 0.08905029296875 +76397 0.2352294921875 +76398 0.318817138671875 +76399 0.358642578125 +76400 0.347747802734375 +76401 0.28564453125 +76402 0.223175048828125 +76403 0.196746826171875 +76404 0.179840087890625 +76405 0.155548095703125 +76406 0.151214599609375 +76407 0.156951904296875 +76408 0.13177490234375 +76409 0.100799560546875 +76410 0.087127685546875 +76411 0.05487060546875 +76412 -0.009002685546875 +76413 -0.10400390625 +76414 -0.229400634765625 +76415 -0.35552978515625 +76416 -0.441925048828125 +76417 -0.473846435546875 +76418 -0.464813232421875 +76419 -0.419097900390625 +76420 -0.334320068359375 +76421 -0.227935791015625 +76422 -0.12347412109375 +76423 -0.02764892578125 +76424 0.077667236328125 +76425 0.2132568359375 +76426 0.38885498046875 +76427 0.582794189453125 +76428 0.734039306640625 +76429 0.800140380859375 +76430 0.7783203125 +76431 0.6651611328125 +76432 0.45965576171875 +76433 0.199188232421875 +76434 -0.050689697265625 +76435 -0.23297119140625 +76436 -0.33013916015625 +76437 -0.368408203125 +76438 -0.378936767578125 +76439 -0.376983642578125 +76440 -0.37969970703125 +76441 -0.391510009765625 +76442 -0.385345458984375 +76443 -0.3419189453125 +76444 -0.28289794921875 +76445 -0.251617431640625 +76446 -0.266143798828125 +76447 -0.273345947265625 +76448 -0.216796875 +76449 -0.128265380859375 +76450 -0.068145751953125 +76451 -0.0430908203125 +76452 -0.024444580078125 +76453 0.020721435546875 +76454 0.124481201171875 +76455 0.25787353515625 +76456 0.379119873046875 +76457 0.47991943359375 +76458 0.5281982421875 +76459 0.511138916015625 +76460 0.456207275390625 +76461 0.407470703125 +76462 0.383758544921875 +76463 0.35687255859375 +76464 0.31182861328125 +76465 0.250885009765625 +76466 0.1654052734375 +76467 0.035247802734375 +76468 -0.142059326171875 +76469 -0.33563232421875 +76470 -0.5345458984375 +76471 -0.72186279296875 +76472 -0.836669921875 +76473 -0.8326416015625 +76474 -0.7296142578125 +76475 -0.582550048828125 +76476 -0.440093994140625 +76477 -0.324310302734375 +76478 -0.20147705078125 +76479 -0.044647216796875 +76480 0.103973388671875 +76481 0.202392578125 +76482 0.264495849609375 +76483 0.338897705078125 +76484 0.443817138671875 +76485 0.545074462890625 +76486 0.6173095703125 +76487 0.6524658203125 +76488 0.66339111328125 +76489 0.6561279296875 +76490 0.606781005859375 +76491 0.501190185546875 +76492 0.352783203125 +76493 0.176544189453125 +76494 -0.034820556640625 +76495 -0.258209228515625 +76496 -0.44244384765625 +76497 -0.5753173828125 +76498 -0.65203857421875 +76499 -0.641632080078125 +76500 -0.562164306640625 +76501 -0.458038330078125 +76502 -0.350555419921875 +76503 -0.260528564453125 +76504 -0.192108154296875 +76505 -0.141937255859375 +76506 -0.1021728515625 +76507 -0.062896728515625 +76508 -0.011932373046875 +76509 0.062835693359375 +76510 0.148712158203125 +76511 0.241729736328125 +76512 0.34912109375 +76513 0.457305908203125 +76514 0.54388427734375 +76515 0.5728759765625 +76516 0.506591796875 +76517 0.351226806640625 +76518 0.146514892578125 +76519 -0.05523681640625 +76520 -0.21624755859375 +76521 -0.334930419921875 +76522 -0.402984619140625 +76523 -0.4412841796875 +76524 -0.49578857421875 +76525 -0.5601806640625 +76526 -0.600738525390625 +76527 -0.584228515625 +76528 -0.47930908203125 +76529 -0.27935791015625 +76530 -0.0089111328125 +76531 0.268798828125 +76532 0.482818603515625 +76533 0.60369873046875 +76534 0.650421142578125 +76535 0.66400146484375 +76536 0.6414794921875 +76537 0.572540283203125 +76538 0.498138427734375 +76539 0.439453125 +76540 0.375518798828125 +76541 0.274505615234375 +76542 0.1087646484375 +76543 -0.099395751953125 +76544 -0.3182373046875 +76545 -0.5489501953125 +76546 -0.7738037109375 +76547 -0.86383056640625 +76548 -0.870391845703125 +76549 -0.86895751953125 +76550 -0.861053466796875 +76551 -0.765869140625 +76552 -0.5301513671875 +76553 -0.214691162109375 +76554 0.137359619140625 +76555 0.474822998046875 +76556 0.76239013671875 +76557 0.867462158203125 +76558 0.870361328125 +76559 0.86480712890625 +76560 0.831817626953125 +76561 0.677581787109375 +76562 0.495880126953125 +76563 0.30767822265625 +76564 0.116180419921875 +76565 -0.110748291015625 +76566 -0.381805419921875 +76567 -0.6572265625 +76568 -0.857421875 +76569 -0.870391845703125 +76570 -0.870391845703125 +76571 -0.86444091796875 +76572 -0.85723876953125 +76573 -0.790008544921875 +76574 -0.62847900390625 +76575 -0.3956298828125 +76576 -0.126708984375 +76577 0.150115966796875 +76578 0.424041748046875 +76579 0.670623779296875 +76580 0.854522705078125 +76581 0.866485595703125 +76582 0.86920166015625 +76583 0.8653564453125 +76584 0.857147216796875 +76585 0.766845703125 +76586 0.628509521484375 +76587 0.462127685546875 +76588 0.297210693359375 +76589 0.14862060546875 +76590 -0.00537109375 +76591 -0.15753173828125 +76592 -0.31304931640625 +76593 -0.48876953125 +76594 -0.6416015625 +76595 -0.751373291015625 +76596 -0.84619140625 +76597 -0.861297607421875 +76598 -0.863250732421875 +76599 -0.856597900390625 +76600 -0.7498779296875 +76601 -0.624542236328125 +76602 -0.47808837890625 +76603 -0.253387451171875 +76604 0.003692626953125 +76605 0.2257080078125 +76606 0.427154541015625 +76607 0.643218994140625 +76608 0.855926513671875 +76609 0.870361328125 +76610 0.870361328125 +76611 0.862762451171875 +76612 0.79669189453125 +76613 0.595794677734375 +76614 0.362152099609375 +76615 0.1270751953125 +76616 -0.086944580078125 +76617 -0.2784423828125 +76618 -0.484832763671875 +76619 -0.729583740234375 +76620 -0.86688232421875 +76621 -0.870391845703125 +76622 -0.86859130859375 +76623 -0.86279296875 +76624 -0.817962646484375 +76625 -0.6116943359375 +76626 -0.3128662109375 +76627 0.039398193359375 +76628 0.422821044921875 +76629 0.805145263671875 +76630 0.870361328125 +76631 0.870361328125 +76632 0.860015869140625 +76633 0.727935791015625 +76634 0.48114013671875 +76635 0.2059326171875 +76636 -0.06103515625 +76637 -0.29913330078125 +76638 -0.516204833984375 +76639 -0.7252197265625 +76640 -0.85980224609375 +76641 -0.870391845703125 +76642 -0.870391845703125 +76643 -0.858062744140625 +76644 -0.673004150390625 +76645 -0.42694091796875 +76646 -0.2100830078125 +76647 -0.0362548828125 +76648 0.10943603515625 +76649 0.23516845703125 +76650 0.373687744140625 +76651 0.517791748046875 +76652 0.602783203125 +76653 0.635711669921875 +76654 0.655181884765625 +76655 0.65948486328125 +76656 0.651275634765625 +76657 0.61846923828125 +76658 0.53753662109375 +76659 0.404144287109375 +76660 0.22186279296875 +76661 0.003997802734375 +76662 -0.22100830078125 +76663 -0.42449951171875 +76664 -0.579833984375 +76665 -0.641876220703125 +76666 -0.6177978515625 +76667 -0.575531005859375 +76668 -0.526336669921875 +76669 -0.42645263671875 +76670 -0.2581787109375 +76671 -0.068695068359375 +76672 0.09222412109375 +76673 0.232147216796875 +76674 0.3509521484375 +76675 0.410064697265625 +76676 0.372955322265625 +76677 0.2554931640625 +76678 0.10711669921875 +76679 -0.052886962890625 +76680 -0.186279296875 +76681 -0.23291015625 +76682 -0.209442138671875 +76683 -0.174163818359375 +76684 -0.126739501953125 +76685 -0.048126220703125 +76686 0.0426025390625 +76687 0.10748291015625 +76688 0.1409912109375 +76689 0.19708251953125 +76690 0.273651123046875 +76691 0.31768798828125 +76692 0.341094970703125 +76693 0.368011474609375 +76694 0.37249755859375 +76695 0.30072021484375 +76696 0.1517333984375 +76697 -0.01470947265625 +76698 -0.1883544921875 +76699 -0.372711181640625 +76700 -0.51397705078125 +76701 -0.57177734375 +76702 -0.53948974609375 +76703 -0.43511962890625 +76704 -0.2962646484375 +76705 -0.161102294921875 +76706 -0.0435791015625 +76707 0.060394287109375 +76708 0.13665771484375 +76709 0.170135498046875 +76710 0.16552734375 +76711 0.15728759765625 +76712 0.150787353515625 +76713 0.12200927734375 +76714 0.080108642578125 +76715 0.05126953125 +76716 0.062896728515625 +76717 0.09271240234375 +76718 0.092987060546875 +76719 0.07855224609375 +76720 0.06427001953125 +76721 0.0347900390625 +76722 -0.01171875 +76723 -0.056060791015625 +76724 -0.055511474609375 +76725 -0.010467529296875 +76726 0.02508544921875 +76727 0.025665283203125 +76728 0.017333984375 +76729 0.00189208984375 +76730 -0.03173828125 +76731 -0.071502685546875 +76732 -0.13543701171875 +76733 -0.219970703125 +76734 -0.300506591796875 +76735 -0.376312255859375 +76736 -0.416107177734375 +76737 -0.371124267578125 +76738 -0.242279052734375 +76739 -0.069732666015625 +76740 0.125640869140625 +76741 0.31268310546875 +76742 0.45501708984375 +76743 0.554779052734375 +76744 0.61065673828125 +76745 0.610931396484375 +76746 0.531463623046875 +76747 0.3883056640625 +76748 0.23468017578125 +76749 0.095245361328125 +76750 -0.00396728515625 +76751 -0.04852294921875 +76752 -0.055145263671875 +76753 -0.0758056640625 +76754 -0.138702392578125 +76755 -0.209197998046875 +76756 -0.289031982421875 +76757 -0.37884521484375 +76758 -0.456329345703125 +76759 -0.51641845703125 +76760 -0.519287109375 +76761 -0.458251953125 +76762 -0.384796142578125 +76763 -0.323699951171875 +76764 -0.269287109375 +76765 -0.1951904296875 +76766 -0.100006103515625 +76767 -0.01055908203125 +76768 0.1033935546875 +76769 0.24908447265625 +76770 0.373199462890625 +76771 0.45806884765625 +76772 0.511474609375 +76773 0.565399169921875 +76774 0.61138916015625 +76775 0.5897216796875 +76776 0.4906005859375 +76777 0.33148193359375 +76778 0.147796630859375 +76779 -0.01873779296875 +76780 -0.140289306640625 +76781 -0.191986083984375 +76782 -0.184295654296875 +76783 -0.161834716796875 +76784 -0.166595458984375 +76785 -0.19390869140625 +76786 -0.22442626953125 +76787 -0.279754638671875 +76788 -0.3389892578125 +76789 -0.3543701171875 +76790 -0.348175048828125 +76791 -0.32598876953125 +76792 -0.2581787109375 +76793 -0.139801025390625 +76794 0.014617919921875 +76795 0.144378662109375 +76796 0.221038818359375 +76797 0.27069091796875 +76798 0.294036865234375 +76799 0.311767578125 +76800 0.339141845703125 +76801 0.360260009765625 +76802 0.360504150390625 +76803 0.308380126953125 +76804 0.18170166015625 +76805 0.0047607421875 +76806 -0.17559814453125 +76807 -0.3143310546875 +76808 -0.36785888671875 +76809 -0.36248779296875 +76810 -0.343536376953125 +76811 -0.3018798828125 +76812 -0.231414794921875 +76813 -0.117645263671875 +76814 0.007049560546875 +76815 0.087982177734375 +76816 0.13946533203125 +76817 0.17425537109375 +76818 0.188201904296875 +76819 0.171234130859375 +76820 0.118438720703125 +76821 0.05706787109375 +76822 -0.010711669921875 +76823 -0.0914306640625 +76824 -0.162322998046875 +76825 -0.194549560546875 +76826 -0.1492919921875 +76827 -0.02166748046875 +76828 0.124053955078125 +76829 0.211151123046875 +76830 0.240447998046875 +76831 0.242218017578125 +76832 0.2257080078125 +76833 0.194366455078125 +76834 0.115509033203125 +76835 0.0128173828125 +76836 -0.053802490234375 +76837 -0.110626220703125 +76838 -0.199493408203125 +76839 -0.29437255859375 +76840 -0.33221435546875 +76841 -0.27972412109375 +76842 -0.185333251953125 +76843 -0.128204345703125 +76844 -0.115692138671875 +76845 -0.116455078125 +76846 -0.105926513671875 +76847 -0.053955078125 +76848 0.048797607421875 +76849 0.157318115234375 +76850 0.212005615234375 +76851 0.218475341796875 +76852 0.23724365234375 +76853 0.30535888671875 +76854 0.38128662109375 +76855 0.404449462890625 +76856 0.3944091796875 +76857 0.3885498046875 +76858 0.362640380859375 +76859 0.27362060546875 +76860 0.11712646484375 +76861 -0.054901123046875 +76862 -0.19085693359375 +76863 -0.28570556640625 +76864 -0.339263916015625 +76865 -0.3775634765625 +76866 -0.445709228515625 +76867 -0.535064697265625 +76868 -0.629058837890625 +76869 -0.697601318359375 +76870 -0.70391845703125 +76871 -0.6424560546875 +76872 -0.491241455078125 +76873 -0.265716552734375 +76874 -0.023712158203125 +76875 0.201751708984375 +76876 0.375823974609375 +76877 0.485076904296875 +76878 0.56884765625 +76879 0.634765625 +76880 0.63763427734375 +76881 0.5660400390625 +76882 0.4720458984375 +76883 0.40692138671875 +76884 0.3778076171875 +76885 0.376953125 +76886 0.371978759765625 +76887 0.313140869140625 +76888 0.184417724609375 +76889 0.011199951171875 +76890 -0.171051025390625 +76891 -0.33740234375 +76892 -0.47198486328125 +76893 -0.560394287109375 +76894 -0.58056640625 +76895 -0.54754638671875 +76896 -0.508575439453125 +76897 -0.459503173828125 +76898 -0.394378662109375 +76899 -0.35260009765625 +76900 -0.31170654296875 +76901 -0.197418212890625 +76902 -0.007965087890625 +76903 0.207489013671875 +76904 0.409210205078125 +76905 0.57208251953125 +76906 0.66595458984375 +76907 0.65875244140625 +76908 0.56744384765625 +76909 0.431396484375 +76910 0.29443359375 +76911 0.182464599609375 +76912 0.06365966796875 +76913 -0.075958251953125 +76914 -0.189422607421875 +76915 -0.271942138671875 +76916 -0.342529296875 +76917 -0.364166259765625 +76918 -0.327239990234375 +76919 -0.2769775390625 +76920 -0.253692626953125 +76921 -0.24365234375 +76922 -0.1983642578125 +76923 -0.116241455078125 +76924 -0.036834716796875 +76925 0.034881591796875 +76926 0.09124755859375 +76927 0.10888671875 +76928 0.125518798828125 +76929 0.15771484375 +76930 0.17828369140625 +76931 0.17108154296875 +76932 0.129974365234375 +76933 0.082427978515625 +76934 0.027679443359375 +76935 -0.065643310546875 +76936 -0.15936279296875 +76937 -0.21307373046875 +76938 -0.234649658203125 +76939 -0.2001953125 +76940 -0.119171142578125 +76941 -0.024749755859375 +76942 0.085784912109375 +76943 0.178131103515625 +76944 0.215576171875 +76945 0.211456298828125 +76946 0.17523193359375 +76947 0.128753662109375 +76948 0.1019287109375 +76949 0.0743408203125 +76950 0.04327392578125 +76951 0.038177490234375 +76952 0.076263427734375 +76953 0.14105224609375 +76954 0.186431884765625 +76955 0.188812255859375 +76956 0.1390380859375 +76957 0.041778564453125 +76958 -0.079437255859375 +76959 -0.219390869140625 +76960 -0.367828369140625 +76961 -0.494873046875 +76962 -0.556243896484375 +76963 -0.508697509765625 +76964 -0.3756103515625 +76965 -0.218902587890625 +76966 -0.063751220703125 +76967 0.091552734375 +76968 0.23602294921875 +76969 0.342987060546875 +76970 0.39520263671875 +76971 0.389373779296875 +76972 0.324249267578125 +76973 0.224090576171875 +76974 0.124267578125 +76975 0.037078857421875 +76976 -0.010101318359375 +76977 -0.019439697265625 +76978 -0.022796630859375 +76979 -0.001556396484375 +76980 0.056304931640625 +76981 0.106719970703125 +76982 0.096893310546875 +76983 0.042694091796875 +76984 -0.018035888671875 +76985 -0.07586669921875 +76986 -0.11944580078125 +76987 -0.15972900390625 +76988 -0.202606201171875 +76989 -0.24859619140625 +76990 -0.30517578125 +76991 -0.36212158203125 +76992 -0.39141845703125 +76993 -0.35528564453125 +76994 -0.249969482421875 +76995 -0.092864990234375 +76996 0.08905029296875 +76997 0.2352294921875 +76998 0.318817138671875 +76999 0.358642578125 +77000 0.347747802734375 +77001 0.28564453125 +77002 0.223175048828125 +77003 0.196746826171875 +77004 0.179840087890625 +77005 0.155548095703125 +77006 0.151214599609375 +77007 0.156951904296875 +77008 0.13177490234375 +77009 0.100799560546875 +77010 0.087127685546875 +77011 0.05487060546875 +77012 -0.009002685546875 +77013 -0.10400390625 +77014 -0.229400634765625 +77015 -0.35552978515625 +77016 -0.441925048828125 +77017 -0.473846435546875 +77018 -0.464813232421875 +77019 -0.419097900390625 +77020 -0.334320068359375 +77021 -0.227935791015625 +77022 -0.12347412109375 +77023 -0.02764892578125 +77024 0.077667236328125 +77025 0.2132568359375 +77026 0.38885498046875 +77027 0.582794189453125 +77028 0.734039306640625 +77029 0.800140380859375 +77030 0.7783203125 +77031 0.6651611328125 +77032 0.45965576171875 +77033 0.199188232421875 +77034 -0.050689697265625 +77035 -0.23297119140625 +77036 -0.33013916015625 +77037 -0.368408203125 +77038 -0.378936767578125 +77039 -0.376983642578125 +77040 -0.37969970703125 +77041 -0.391510009765625 +77042 -0.385345458984375 +77043 -0.3419189453125 +77044 -0.28289794921875 +77045 -0.251617431640625 +77046 -0.266143798828125 +77047 -0.273345947265625 +77048 -0.216796875 +77049 -0.128265380859375 +77050 -0.068145751953125 +77051 -0.0430908203125 +77052 -0.024444580078125 +77053 0.020721435546875 +77054 0.124481201171875 +77055 0.25787353515625 +77056 0.379119873046875 +77057 0.47991943359375 +77058 0.5281982421875 +77059 0.511138916015625 +77060 0.456207275390625 +77061 0.407470703125 +77062 0.383758544921875 +77063 0.35687255859375 +77064 0.31182861328125 +77065 0.250885009765625 +77066 0.1654052734375 +77067 0.035247802734375 +77068 -0.142059326171875 +77069 -0.33563232421875 +77070 -0.5345458984375 +77071 -0.72186279296875 +77072 -0.836669921875 +77073 -0.8326416015625 +77074 -0.7296142578125 +77075 -0.582550048828125 +77076 -0.440093994140625 +77077 -0.324310302734375 +77078 -0.20147705078125 +77079 -0.044647216796875 +77080 0.103973388671875 +77081 0.202392578125 +77082 0.264495849609375 +77083 0.338897705078125 +77084 0.443817138671875 +77085 0.545074462890625 +77086 0.6173095703125 +77087 0.6524658203125 +77088 0.66339111328125 +77089 0.6561279296875 +77090 0.606781005859375 +77091 0.501190185546875 +77092 0.352783203125 +77093 0.176544189453125 +77094 -0.034820556640625 +77095 -0.258209228515625 +77096 -0.44244384765625 +77097 -0.5753173828125 +77098 -0.65203857421875 +77099 -0.641632080078125 +77100 -0.562164306640625 +77101 -0.458038330078125 +77102 -0.350555419921875 +77103 -0.260528564453125 +77104 -0.192108154296875 +77105 -0.141937255859375 +77106 -0.1021728515625 +77107 -0.062896728515625 +77108 -0.011932373046875 +77109 0.062835693359375 +77110 0.148712158203125 +77111 0.241729736328125 +77112 0.34912109375 +77113 0.457305908203125 +77114 0.54388427734375 +77115 0.5728759765625 +77116 0.506591796875 +77117 0.351226806640625 +77118 0.146514892578125 +77119 -0.05523681640625 +77120 -0.21624755859375 +77121 -0.334930419921875 +77122 -0.402984619140625 +77123 -0.4412841796875 +77124 -0.49578857421875 +77125 -0.5601806640625 +77126 -0.600738525390625 +77127 -0.584228515625 +77128 -0.47930908203125 +77129 -0.27935791015625 +77130 -0.0089111328125 +77131 0.268798828125 +77132 0.482818603515625 +77133 0.60369873046875 +77134 0.650421142578125 +77135 0.66400146484375 +77136 0.6414794921875 +77137 0.572540283203125 +77138 0.498138427734375 +77139 0.439453125 +77140 0.375518798828125 +77141 0.274505615234375 +77142 0.1087646484375 +77143 -0.099395751953125 +77144 -0.3182373046875 +77145 -0.5489501953125 +77146 -0.7738037109375 +77147 -0.86383056640625 +77148 -0.870391845703125 +77149 -0.86895751953125 +77150 -0.861053466796875 +77151 -0.765869140625 +77152 -0.5301513671875 +77153 -0.214691162109375 +77154 0.137359619140625 +77155 0.474822998046875 +77156 0.76239013671875 +77157 0.867462158203125 +77158 0.870361328125 +77159 0.86480712890625 +77160 0.831817626953125 +77161 0.677581787109375 +77162 0.495880126953125 +77163 0.30767822265625 +77164 0.116180419921875 +77165 -0.110748291015625 +77166 -0.381805419921875 +77167 -0.6572265625 +77168 -0.857421875 +77169 -0.870391845703125 +77170 -0.870391845703125 +77171 -0.86444091796875 +77172 -0.85723876953125 +77173 -0.790008544921875 +77174 -0.62847900390625 +77175 -0.3956298828125 +77176 -0.126708984375 +77177 0.150115966796875 +77178 0.424041748046875 +77179 0.670623779296875 +77180 0.854522705078125 +77181 0.866485595703125 +77182 0.86920166015625 +77183 0.8653564453125 +77184 0.857147216796875 +77185 0.766845703125 +77186 0.628509521484375 +77187 0.462127685546875 +77188 0.297210693359375 +77189 0.14862060546875 +77190 -0.00537109375 +77191 -0.15753173828125 +77192 -0.31304931640625 +77193 -0.48876953125 +77194 -0.6416015625 +77195 -0.751373291015625 +77196 -0.84619140625 +77197 -0.861297607421875 +77198 -0.863250732421875 +77199 -0.856597900390625 +77200 -0.7498779296875 +77201 -0.624542236328125 +77202 -0.47808837890625 +77203 -0.253387451171875 +77204 0.003692626953125 +77205 0.2257080078125 +77206 0.427154541015625 +77207 0.643218994140625 +77208 0.855926513671875 +77209 0.870361328125 +77210 0.870361328125 +77211 0.862762451171875 +77212 0.79669189453125 +77213 0.595794677734375 +77214 0.362152099609375 +77215 0.1270751953125 +77216 -0.086944580078125 +77217 -0.2784423828125 +77218 -0.484832763671875 +77219 -0.729583740234375 +77220 -0.86688232421875 +77221 -0.870391845703125 +77222 -0.86859130859375 +77223 -0.86279296875 +77224 -0.817962646484375 +77225 -0.6116943359375 +77226 -0.3128662109375 +77227 0.039398193359375 +77228 0.422821044921875 +77229 0.805145263671875 +77230 0.870361328125 +77231 0.870361328125 +77232 0.860015869140625 +77233 0.727935791015625 +77234 0.48114013671875 +77235 0.2059326171875 +77236 -0.06103515625 +77237 -0.29913330078125 +77238 -0.516204833984375 +77239 -0.7252197265625 +77240 -0.85980224609375 +77241 -0.870391845703125 +77242 -0.870391845703125 +77243 -0.858062744140625 +77244 -0.673004150390625 +77245 -0.42694091796875 +77246 -0.2100830078125 +77247 -0.0362548828125 +77248 0.10943603515625 +77249 0.23516845703125 +77250 0.373687744140625 +77251 0.517791748046875 +77252 0.602783203125 +77253 0.635711669921875 +77254 0.655181884765625 +77255 0.65948486328125 +77256 0.651275634765625 +77257 0.61846923828125 +77258 0.53753662109375 +77259 0.404144287109375 +77260 0.22186279296875 +77261 0.003997802734375 +77262 -0.22100830078125 +77263 -0.42449951171875 +77264 -0.579833984375 +77265 -0.641876220703125 +77266 -0.6177978515625 +77267 -0.575531005859375 +77268 -0.526336669921875 +77269 -0.42645263671875 +77270 -0.2581787109375 +77271 -0.068695068359375 +77272 0.09222412109375 +77273 0.232147216796875 +77274 0.3509521484375 +77275 0.410064697265625 +77276 0.372955322265625 +77277 0.2554931640625 +77278 0.10711669921875 +77279 -0.052886962890625 +77280 -0.186279296875 +77281 -0.23291015625 +77282 -0.209442138671875 +77283 -0.174163818359375 +77284 -0.126739501953125 +77285 -0.048126220703125 +77286 0.0426025390625 +77287 0.10748291015625 +77288 0.1409912109375 +77289 0.19708251953125 +77290 0.273651123046875 +77291 0.31768798828125 +77292 0.341094970703125 +77293 0.368011474609375 +77294 0.37249755859375 +77295 0.30072021484375 +77296 0.1517333984375 +77297 -0.01470947265625 +77298 -0.1883544921875 +77299 -0.372711181640625 +77300 -0.51397705078125 +77301 -0.57177734375 +77302 -0.53948974609375 +77303 -0.43511962890625 +77304 -0.2962646484375 +77305 -0.161102294921875 +77306 -0.0435791015625 +77307 0.060394287109375 +77308 0.13665771484375 +77309 0.170135498046875 +77310 0.16552734375 +77311 0.15728759765625 +77312 0.150787353515625 +77313 0.12200927734375 +77314 0.080108642578125 +77315 0.05126953125 +77316 0.062896728515625 +77317 0.09271240234375 +77318 0.092987060546875 +77319 0.07855224609375 +77320 0.06427001953125 +77321 0.0347900390625 +77322 -0.01171875 +77323 -0.056060791015625 +77324 -0.055511474609375 +77325 -0.010467529296875 +77326 0.02508544921875 +77327 0.025665283203125 +77328 0.017333984375 +77329 0.00189208984375 +77330 -0.03173828125 +77331 -0.071502685546875 +77332 -0.13543701171875 +77333 -0.219970703125 +77334 -0.300506591796875 +77335 -0.376312255859375 +77336 -0.416107177734375 +77337 -0.371124267578125 +77338 -0.242279052734375 +77339 -0.069732666015625 +77340 0.125640869140625 +77341 0.31268310546875 +77342 0.45501708984375 +77343 0.554779052734375 +77344 0.61065673828125 +77345 0.610931396484375 +77346 0.531463623046875 +77347 0.3883056640625 +77348 0.23468017578125 +77349 0.095245361328125 +77350 -0.00396728515625 +77351 -0.04852294921875 +77352 -0.055145263671875 +77353 -0.0758056640625 +77354 -0.138702392578125 +77355 -0.209197998046875 +77356 -0.289031982421875 +77357 -0.37884521484375 +77358 -0.456329345703125 +77359 -0.51641845703125 +77360 -0.519287109375 +77361 -0.458251953125 +77362 -0.384796142578125 +77363 -0.323699951171875 +77364 -0.269287109375 +77365 -0.1951904296875 +77366 -0.100006103515625 +77367 -0.01055908203125 +77368 0.1033935546875 +77369 0.24908447265625 +77370 0.373199462890625 +77371 0.45806884765625 +77372 0.511474609375 +77373 0.565399169921875 +77374 0.61138916015625 +77375 0.5897216796875 +77376 0.4906005859375 +77377 0.33148193359375 +77378 0.147796630859375 +77379 -0.01873779296875 +77380 -0.140289306640625 +77381 -0.191986083984375 +77382 -0.184295654296875 +77383 -0.161834716796875 +77384 -0.166595458984375 +77385 -0.19390869140625 +77386 -0.22442626953125 +77387 -0.279754638671875 +77388 -0.3389892578125 +77389 -0.3543701171875 +77390 -0.348175048828125 +77391 -0.32598876953125 +77392 -0.2581787109375 +77393 -0.139801025390625 +77394 0.014617919921875 +77395 0.144378662109375 +77396 0.221038818359375 +77397 0.27069091796875 +77398 0.294036865234375 +77399 0.311767578125 +77400 0.339141845703125 +77401 0.360260009765625 +77402 0.360504150390625 +77403 0.308380126953125 +77404 0.18170166015625 +77405 0.0047607421875 +77406 -0.17559814453125 +77407 -0.3143310546875 +77408 -0.36785888671875 +77409 -0.36248779296875 +77410 -0.343536376953125 +77411 -0.3018798828125 +77412 -0.231414794921875 +77413 -0.117645263671875 +77414 0.007049560546875 +77415 0.087982177734375 +77416 0.13946533203125 +77417 0.17425537109375 +77418 0.188201904296875 +77419 0.171234130859375 +77420 0.118438720703125 +77421 0.05706787109375 +77422 -0.010711669921875 +77423 -0.0914306640625 +77424 -0.162322998046875 +77425 -0.194549560546875 +77426 -0.1492919921875 +77427 -0.02166748046875 +77428 0.124053955078125 +77429 0.211151123046875 +77430 0.240447998046875 +77431 0.242218017578125 +77432 0.2257080078125 +77433 0.194366455078125 +77434 0.115509033203125 +77435 0.0128173828125 +77436 -0.053802490234375 +77437 -0.110626220703125 +77438 -0.199493408203125 +77439 -0.29437255859375 +77440 -0.33221435546875 +77441 -0.27972412109375 +77442 -0.185333251953125 +77443 -0.128204345703125 +77444 -0.115692138671875 +77445 -0.116455078125 +77446 -0.105926513671875 +77447 -0.053955078125 +77448 0.048797607421875 +77449 0.157318115234375 +77450 0.212005615234375 +77451 0.218475341796875 +77452 0.23724365234375 +77453 0.30535888671875 +77454 0.38128662109375 +77455 0.404449462890625 +77456 0.3944091796875 +77457 0.3885498046875 +77458 0.362640380859375 +77459 0.27362060546875 +77460 0.11712646484375 +77461 -0.054901123046875 +77462 -0.19085693359375 +77463 -0.28570556640625 +77464 -0.339263916015625 +77465 -0.3775634765625 +77466 -0.445709228515625 +77467 -0.535064697265625 +77468 -0.629058837890625 +77469 -0.697601318359375 +77470 -0.70391845703125 +77471 -0.6424560546875 +77472 -0.491241455078125 +77473 -0.265716552734375 +77474 -0.023712158203125 +77475 0.201751708984375 +77476 0.375823974609375 +77477 0.485076904296875 +77478 0.56884765625 +77479 0.634765625 +77480 0.63763427734375 +77481 0.5660400390625 +77482 0.4720458984375 +77483 0.40692138671875 +77484 0.3778076171875 +77485 0.376953125 +77486 0.371978759765625 +77487 0.313140869140625 +77488 0.184417724609375 +77489 0.011199951171875 +77490 -0.171051025390625 +77491 -0.33740234375 +77492 -0.47198486328125 +77493 -0.560394287109375 +77494 -0.58056640625 +77495 -0.54754638671875 +77496 -0.508575439453125 +77497 -0.459503173828125 +77498 -0.394378662109375 +77499 -0.35260009765625 +77500 -0.31170654296875 +77501 -0.197418212890625 +77502 -0.007965087890625 +77503 0.207489013671875 +77504 0.409210205078125 +77505 0.57208251953125 +77506 0.66595458984375 +77507 0.65875244140625 +77508 0.56744384765625 +77509 0.431396484375 +77510 0.29443359375 +77511 0.182464599609375 +77512 0.06365966796875 +77513 -0.075958251953125 +77514 -0.189422607421875 +77515 -0.271942138671875 +77516 -0.342529296875 +77517 -0.364166259765625 +77518 -0.327239990234375 +77519 -0.2769775390625 +77520 -0.253692626953125 +77521 -0.24365234375 +77522 -0.1983642578125 +77523 -0.116241455078125 +77524 -0.036834716796875 +77525 0.034881591796875 +77526 0.09124755859375 +77527 0.10888671875 +77528 0.125518798828125 +77529 0.15771484375 +77530 0.17828369140625 +77531 0.17108154296875 +77532 0.129974365234375 +77533 0.082427978515625 +77534 0.027679443359375 +77535 -0.065643310546875 +77536 -0.15936279296875 +77537 -0.21307373046875 +77538 -0.234649658203125 +77539 -0.2001953125 +77540 -0.119171142578125 +77541 -0.024749755859375 +77542 0.085784912109375 +77543 0.178131103515625 +77544 0.215576171875 +77545 0.211456298828125 +77546 0.17523193359375 +77547 0.128753662109375 +77548 0.1019287109375 +77549 0.0743408203125 +77550 0.04327392578125 +77551 0.038177490234375 +77552 0.076263427734375 +77553 0.14105224609375 +77554 0.186431884765625 +77555 0.188812255859375 +77556 0.1390380859375 +77557 0.041778564453125 +77558 -0.079437255859375 +77559 -0.219390869140625 +77560 -0.367828369140625 +77561 -0.494873046875 +77562 -0.556243896484375 +77563 -0.508697509765625 +77564 -0.3756103515625 +77565 -0.218902587890625 +77566 -0.063751220703125 +77567 0.091552734375 +77568 0.23602294921875 +77569 0.342987060546875 +77570 0.39520263671875 +77571 0.389373779296875 +77572 0.324249267578125 +77573 0.224090576171875 +77574 0.124267578125 +77575 0.037078857421875 +77576 -0.010101318359375 +77577 -0.019439697265625 +77578 -0.022796630859375 +77579 -0.001556396484375 +77580 0.056304931640625 +77581 0.106719970703125 +77582 0.096893310546875 +77583 0.042694091796875 +77584 -0.018035888671875 +77585 -0.07586669921875 +77586 -0.11944580078125 +77587 -0.15972900390625 +77588 -0.202606201171875 +77589 -0.24859619140625 +77590 -0.30517578125 +77591 -0.36212158203125 +77592 -0.39141845703125 +77593 -0.35528564453125 +77594 -0.249969482421875 +77595 -0.092864990234375 +77596 0.08905029296875 +77597 0.2352294921875 +77598 0.318817138671875 +77599 0.358642578125 +77600 0.347747802734375 +77601 0.28564453125 +77602 0.223175048828125 +77603 0.196746826171875 +77604 0.179840087890625 +77605 0.155548095703125 +77606 0.151214599609375 +77607 0.156951904296875 +77608 0.13177490234375 +77609 0.100799560546875 +77610 0.087127685546875 +77611 0.05487060546875 +77612 -0.009002685546875 +77613 -0.10400390625 +77614 -0.229400634765625 +77615 -0.35552978515625 +77616 -0.441925048828125 +77617 -0.473846435546875 +77618 -0.464813232421875 +77619 -0.419097900390625 +77620 -0.334320068359375 +77621 -0.227935791015625 +77622 -0.12347412109375 +77623 -0.02764892578125 +77624 0.077667236328125 +77625 0.2132568359375 +77626 0.38885498046875 +77627 0.582794189453125 +77628 0.734039306640625 +77629 0.800140380859375 +77630 0.7783203125 +77631 0.6651611328125 +77632 0.45965576171875 +77633 0.199188232421875 +77634 -0.050689697265625 +77635 -0.23297119140625 +77636 -0.33013916015625 +77637 -0.368408203125 +77638 -0.378936767578125 +77639 -0.376983642578125 +77640 -0.37969970703125 +77641 -0.391510009765625 +77642 -0.385345458984375 +77643 -0.3419189453125 +77644 -0.28289794921875 +77645 -0.251617431640625 +77646 -0.266143798828125 +77647 -0.273345947265625 +77648 -0.216796875 +77649 -0.128265380859375 +77650 -0.068145751953125 +77651 -0.0430908203125 +77652 -0.024444580078125 +77653 0.020721435546875 +77654 0.124481201171875 +77655 0.25787353515625 +77656 0.379119873046875 +77657 0.47991943359375 +77658 0.5281982421875 +77659 0.511138916015625 +77660 0.456207275390625 +77661 0.407470703125 +77662 0.383758544921875 +77663 0.35687255859375 +77664 0.31182861328125 +77665 0.250885009765625 +77666 0.1654052734375 +77667 0.035247802734375 +77668 -0.142059326171875 +77669 -0.33563232421875 +77670 -0.5345458984375 +77671 -0.72186279296875 +77672 -0.836669921875 +77673 -0.8326416015625 +77674 -0.7296142578125 +77675 -0.582550048828125 +77676 -0.440093994140625 +77677 -0.324310302734375 +77678 -0.20147705078125 +77679 -0.044647216796875 +77680 0.103973388671875 +77681 0.202392578125 +77682 0.264495849609375 +77683 0.338897705078125 +77684 0.443817138671875 +77685 0.545074462890625 +77686 0.6173095703125 +77687 0.6524658203125 +77688 0.66339111328125 +77689 0.6561279296875 +77690 0.606781005859375 +77691 0.501190185546875 +77692 0.352783203125 +77693 0.176544189453125 +77694 -0.034820556640625 +77695 -0.258209228515625 +77696 -0.44244384765625 +77697 -0.5753173828125 +77698 -0.65203857421875 +77699 -0.641632080078125 +77700 -0.562164306640625 +77701 -0.458038330078125 +77702 -0.350555419921875 +77703 -0.260528564453125 +77704 -0.192108154296875 +77705 -0.141937255859375 +77706 -0.1021728515625 +77707 -0.062896728515625 +77708 -0.011932373046875 +77709 0.062835693359375 +77710 0.148712158203125 +77711 0.241729736328125 +77712 0.34912109375 +77713 0.457305908203125 +77714 0.54388427734375 +77715 0.5728759765625 +77716 0.506591796875 +77717 0.351226806640625 +77718 0.146514892578125 +77719 -0.05523681640625 +77720 -0.21624755859375 +77721 -0.334930419921875 +77722 -0.402984619140625 +77723 -0.4412841796875 +77724 -0.49578857421875 +77725 -0.5601806640625 +77726 -0.600738525390625 +77727 -0.584228515625 +77728 -0.47930908203125 +77729 -0.27935791015625 +77730 -0.0089111328125 +77731 0.268798828125 +77732 0.482818603515625 +77733 0.60369873046875 +77734 0.650421142578125 +77735 0.66400146484375 +77736 0.6414794921875 +77737 0.572540283203125 +77738 0.498138427734375 +77739 0.439453125 +77740 0.375518798828125 +77741 0.274505615234375 +77742 0.1087646484375 +77743 -0.099395751953125 +77744 -0.3182373046875 +77745 -0.5489501953125 +77746 -0.7738037109375 +77747 -0.86383056640625 +77748 -0.870391845703125 +77749 -0.86895751953125 +77750 -0.861053466796875 +77751 -0.765869140625 +77752 -0.5301513671875 +77753 -0.214691162109375 +77754 0.137359619140625 +77755 0.474822998046875 +77756 0.76239013671875 +77757 0.867462158203125 +77758 0.870361328125 +77759 0.86480712890625 +77760 0.831817626953125 +77761 0.677581787109375 +77762 0.495880126953125 +77763 0.30767822265625 +77764 0.116180419921875 +77765 -0.110748291015625 +77766 -0.381805419921875 +77767 -0.6572265625 +77768 -0.857421875 +77769 -0.870391845703125 +77770 -0.870391845703125 +77771 -0.86444091796875 +77772 -0.85723876953125 +77773 -0.790008544921875 +77774 -0.62847900390625 +77775 -0.3956298828125 +77776 -0.126708984375 +77777 0.150115966796875 +77778 0.424041748046875 +77779 0.670623779296875 +77780 0.854522705078125 +77781 0.866485595703125 +77782 0.86920166015625 +77783 0.8653564453125 +77784 0.857147216796875 +77785 0.766845703125 +77786 0.628509521484375 +77787 0.462127685546875 +77788 0.297210693359375 +77789 0.14862060546875 +77790 -0.00537109375 +77791 -0.15753173828125 +77792 -0.31304931640625 +77793 -0.48876953125 +77794 -0.6416015625 +77795 -0.751373291015625 +77796 -0.84619140625 +77797 -0.861297607421875 +77798 -0.863250732421875 +77799 -0.856597900390625 +77800 -0.7498779296875 +77801 -0.624542236328125 +77802 -0.47808837890625 +77803 -0.253387451171875 +77804 0.003692626953125 +77805 0.2257080078125 +77806 0.427154541015625 +77807 0.643218994140625 +77808 0.855926513671875 +77809 0.870361328125 +77810 0.870361328125 +77811 0.862762451171875 +77812 0.79669189453125 +77813 0.595794677734375 +77814 0.362152099609375 +77815 0.1270751953125 +77816 -0.086944580078125 +77817 -0.2784423828125 +77818 -0.484832763671875 +77819 -0.729583740234375 +77820 -0.86688232421875 +77821 -0.870391845703125 +77822 -0.86859130859375 +77823 -0.86279296875 +77824 -0.817962646484375 +77825 -0.6116943359375 +77826 -0.3128662109375 +77827 0.039398193359375 +77828 0.422821044921875 +77829 0.805145263671875 +77830 0.870361328125 +77831 0.870361328125 +77832 0.860015869140625 +77833 0.727935791015625 +77834 0.48114013671875 +77835 0.2059326171875 +77836 -0.06103515625 +77837 -0.29913330078125 +77838 -0.516204833984375 +77839 -0.7252197265625 +77840 -0.85980224609375 +77841 -0.870391845703125 +77842 -0.870391845703125 +77843 -0.858062744140625 +77844 -0.673004150390625 +77845 -0.42694091796875 +77846 -0.2100830078125 +77847 -0.0362548828125 +77848 0.10943603515625 +77849 0.23516845703125 +77850 0.373687744140625 +77851 0.517791748046875 +77852 0.602783203125 +77853 0.635711669921875 +77854 0.655181884765625 +77855 0.65948486328125 +77856 0.651275634765625 +77857 0.61846923828125 +77858 0.53753662109375 +77859 0.404144287109375 +77860 0.22186279296875 +77861 0.003997802734375 +77862 -0.22100830078125 +77863 -0.42449951171875 +77864 -0.579833984375 +77865 -0.641876220703125 +77866 -0.6177978515625 +77867 -0.575531005859375 +77868 -0.526336669921875 +77869 -0.42645263671875 +77870 -0.2581787109375 +77871 -0.068695068359375 +77872 0.09222412109375 +77873 0.232147216796875 +77874 0.3509521484375 +77875 0.410064697265625 +77876 0.372955322265625 +77877 0.2554931640625 +77878 0.10711669921875 +77879 -0.052886962890625 +77880 -0.186279296875 +77881 -0.23291015625 +77882 -0.209442138671875 +77883 -0.174163818359375 +77884 -0.126739501953125 +77885 -0.048126220703125 +77886 0.0426025390625 +77887 0.10748291015625 +77888 0.1409912109375 +77889 0.19708251953125 +77890 0.273651123046875 +77891 0.31768798828125 +77892 0.341094970703125 +77893 0.368011474609375 +77894 0.37249755859375 +77895 0.30072021484375 +77896 0.1517333984375 +77897 -0.01470947265625 +77898 -0.1883544921875 +77899 -0.372711181640625 +77900 -0.51397705078125 +77901 -0.57177734375 +77902 -0.53948974609375 +77903 -0.43511962890625 +77904 -0.2962646484375 +77905 -0.161102294921875 +77906 -0.0435791015625 +77907 0.060394287109375 +77908 0.13665771484375 +77909 0.170135498046875 +77910 0.16552734375 +77911 0.15728759765625 +77912 0.150787353515625 +77913 0.12200927734375 +77914 0.080108642578125 +77915 0.05126953125 +77916 0.062896728515625 +77917 0.09271240234375 +77918 0.092987060546875 +77919 0.07855224609375 +77920 0.06427001953125 +77921 0.0347900390625 +77922 -0.01171875 +77923 -0.056060791015625 +77924 -0.055511474609375 +77925 -0.010467529296875 +77926 0.02508544921875 +77927 0.025665283203125 +77928 0.017333984375 +77929 0.00189208984375 +77930 -0.03173828125 +77931 -0.071502685546875 +77932 -0.13543701171875 +77933 -0.219970703125 +77934 -0.300506591796875 +77935 -0.376312255859375 +77936 -0.416107177734375 +77937 -0.371124267578125 +77938 -0.242279052734375 +77939 -0.069732666015625 +77940 0.125640869140625 +77941 0.31268310546875 +77942 0.45501708984375 +77943 0.554779052734375 +77944 0.61065673828125 +77945 0.610931396484375 +77946 0.531463623046875 +77947 0.3883056640625 +77948 0.23468017578125 +77949 0.095245361328125 +77950 -0.00396728515625 +77951 -0.04852294921875 +77952 -0.055145263671875 +77953 -0.0758056640625 +77954 -0.138702392578125 +77955 -0.209197998046875 +77956 -0.289031982421875 +77957 -0.37884521484375 +77958 -0.456329345703125 +77959 -0.51641845703125 +77960 -0.519287109375 +77961 -0.458251953125 +77962 -0.384796142578125 +77963 -0.323699951171875 +77964 -0.269287109375 +77965 -0.1951904296875 +77966 -0.100006103515625 +77967 -0.01055908203125 +77968 0.1033935546875 +77969 0.24908447265625 +77970 0.373199462890625 +77971 0.45806884765625 +77972 0.511474609375 +77973 0.565399169921875 +77974 0.61138916015625 +77975 0.5897216796875 +77976 0.4906005859375 +77977 0.33148193359375 +77978 0.147796630859375 +77979 -0.01873779296875 +77980 -0.140289306640625 +77981 -0.191986083984375 +77982 -0.184295654296875 +77983 -0.161834716796875 +77984 -0.166595458984375 +77985 -0.19390869140625 +77986 -0.22442626953125 +77987 -0.279754638671875 +77988 -0.3389892578125 +77989 -0.3543701171875 +77990 -0.348175048828125 +77991 -0.32598876953125 +77992 -0.2581787109375 +77993 -0.139801025390625 +77994 0.014617919921875 +77995 0.144378662109375 +77996 0.221038818359375 +77997 0.27069091796875 +77998 0.294036865234375 +77999 0.311767578125 +78000 0.339141845703125 +78001 0.360260009765625 +78002 0.360504150390625 +78003 0.308380126953125 +78004 0.18170166015625 +78005 0.0047607421875 +78006 -0.17559814453125 +78007 -0.3143310546875 +78008 -0.36785888671875 +78009 -0.36248779296875 +78010 -0.343536376953125 +78011 -0.3018798828125 +78012 -0.231414794921875 +78013 -0.117645263671875 +78014 0.007049560546875 +78015 0.087982177734375 +78016 0.13946533203125 +78017 0.17425537109375 +78018 0.188201904296875 +78019 0.171234130859375 +78020 0.118438720703125 +78021 0.05706787109375 +78022 -0.010711669921875 +78023 -0.0914306640625 +78024 -0.162322998046875 +78025 -0.194549560546875 +78026 -0.1492919921875 +78027 -0.02166748046875 +78028 0.124053955078125 +78029 0.211151123046875 +78030 0.240447998046875 +78031 0.242218017578125 +78032 0.2257080078125 +78033 0.194366455078125 +78034 0.115509033203125 +78035 0.0128173828125 +78036 -0.053802490234375 +78037 -0.110626220703125 +78038 -0.199493408203125 +78039 -0.29437255859375 +78040 -0.33221435546875 +78041 -0.27972412109375 +78042 -0.185333251953125 +78043 -0.128204345703125 +78044 -0.115692138671875 +78045 -0.116455078125 +78046 -0.105926513671875 +78047 -0.053955078125 +78048 0.048797607421875 +78049 0.157318115234375 +78050 0.212005615234375 +78051 0.218475341796875 +78052 0.23724365234375 +78053 0.30535888671875 +78054 0.38128662109375 +78055 0.404449462890625 +78056 0.3944091796875 +78057 0.3885498046875 +78058 0.362640380859375 +78059 0.27362060546875 +78060 0.11712646484375 +78061 -0.054901123046875 +78062 -0.19085693359375 +78063 -0.28570556640625 +78064 -0.339263916015625 +78065 -0.3775634765625 +78066 -0.445709228515625 +78067 -0.535064697265625 +78068 -0.629058837890625 +78069 -0.697601318359375 +78070 -0.70391845703125 +78071 -0.6424560546875 +78072 -0.491241455078125 +78073 -0.265716552734375 +78074 -0.023712158203125 +78075 0.201751708984375 +78076 0.375823974609375 +78077 0.485076904296875 +78078 0.56884765625 +78079 0.634765625 +78080 0.63763427734375 +78081 0.5660400390625 +78082 0.4720458984375 +78083 0.40692138671875 +78084 0.3778076171875 +78085 0.376953125 +78086 0.371978759765625 +78087 0.313140869140625 +78088 0.184417724609375 +78089 0.011199951171875 +78090 -0.171051025390625 +78091 -0.33740234375 +78092 -0.47198486328125 +78093 -0.560394287109375 +78094 -0.58056640625 +78095 -0.54754638671875 +78096 -0.508575439453125 +78097 -0.459503173828125 +78098 -0.394378662109375 +78099 -0.35260009765625 +78100 -0.31170654296875 +78101 -0.197418212890625 +78102 -0.007965087890625 +78103 0.207489013671875 +78104 0.409210205078125 +78105 0.57208251953125 +78106 0.66595458984375 +78107 0.65875244140625 +78108 0.56744384765625 +78109 0.431396484375 +78110 0.29443359375 +78111 0.182464599609375 +78112 0.06365966796875 +78113 -0.075958251953125 +78114 -0.189422607421875 +78115 -0.271942138671875 +78116 -0.342529296875 +78117 -0.364166259765625 +78118 -0.327239990234375 +78119 -0.2769775390625 +78120 -0.253692626953125 +78121 -0.24365234375 +78122 -0.1983642578125 +78123 -0.116241455078125 +78124 -0.036834716796875 +78125 0.034881591796875 +78126 0.09124755859375 +78127 0.10888671875 +78128 0.125518798828125 +78129 0.15771484375 +78130 0.17828369140625 +78131 0.17108154296875 +78132 0.129974365234375 +78133 0.082427978515625 +78134 0.027679443359375 +78135 -0.065643310546875 +78136 -0.15936279296875 +78137 -0.21307373046875 +78138 -0.234649658203125 +78139 -0.2001953125 +78140 -0.119171142578125 +78141 -0.024749755859375 +78142 0.085784912109375 +78143 0.178131103515625 +78144 0.215576171875 +78145 0.211456298828125 +78146 0.17523193359375 +78147 0.128753662109375 +78148 0.1019287109375 +78149 0.0743408203125 +78150 0.04327392578125 +78151 0.038177490234375 +78152 0.076263427734375 +78153 0.14105224609375 +78154 0.186431884765625 +78155 0.188812255859375 +78156 0.1390380859375 +78157 0.041778564453125 +78158 -0.079437255859375 +78159 -0.219390869140625 +78160 -0.367828369140625 +78161 -0.494873046875 +78162 -0.556243896484375 +78163 -0.508697509765625 +78164 -0.3756103515625 +78165 -0.218902587890625 +78166 -0.063751220703125 +78167 0.091552734375 +78168 0.23602294921875 +78169 0.342987060546875 +78170 0.39520263671875 +78171 0.389373779296875 +78172 0.324249267578125 +78173 0.224090576171875 +78174 0.124267578125 +78175 0.037078857421875 +78176 -0.010101318359375 +78177 -0.019439697265625 +78178 -0.022796630859375 +78179 -0.001556396484375 +78180 0.056304931640625 +78181 0.106719970703125 +78182 0.096893310546875 +78183 0.042694091796875 +78184 -0.018035888671875 +78185 -0.07586669921875 +78186 -0.11944580078125 +78187 -0.15972900390625 +78188 -0.202606201171875 +78189 -0.24859619140625 +78190 -0.30517578125 +78191 -0.36212158203125 +78192 -0.39141845703125 +78193 -0.35528564453125 +78194 -0.249969482421875 +78195 -0.092864990234375 +78196 0.08905029296875 +78197 0.2352294921875 +78198 0.318817138671875 +78199 0.358642578125 +78200 0.347747802734375 +78201 0.28564453125 +78202 0.223175048828125 +78203 0.196746826171875 +78204 0.179840087890625 +78205 0.155548095703125 +78206 0.151214599609375 +78207 0.156951904296875 +78208 0.13177490234375 +78209 0.100799560546875 +78210 0.087127685546875 +78211 0.05487060546875 +78212 -0.009002685546875 +78213 -0.10400390625 +78214 -0.229400634765625 +78215 -0.35552978515625 +78216 -0.441925048828125 +78217 -0.473846435546875 +78218 -0.464813232421875 +78219 -0.419097900390625 +78220 -0.334320068359375 +78221 -0.227935791015625 +78222 -0.12347412109375 +78223 -0.02764892578125 +78224 0.077667236328125 +78225 0.2132568359375 +78226 0.38885498046875 +78227 0.582794189453125 +78228 0.734039306640625 +78229 0.800140380859375 +78230 0.7783203125 +78231 0.6651611328125 +78232 0.45965576171875 +78233 0.199188232421875 +78234 -0.050689697265625 +78235 -0.23297119140625 +78236 -0.33013916015625 +78237 -0.368408203125 +78238 -0.378936767578125 +78239 -0.376983642578125 +78240 -0.37969970703125 +78241 -0.391510009765625 +78242 -0.385345458984375 +78243 -0.3419189453125 +78244 -0.28289794921875 +78245 -0.251617431640625 +78246 -0.266143798828125 +78247 -0.273345947265625 +78248 -0.216796875 +78249 -0.128265380859375 +78250 -0.068145751953125 +78251 -0.0430908203125 +78252 -0.024444580078125 +78253 0.020721435546875 +78254 0.124481201171875 +78255 0.25787353515625 +78256 0.379119873046875 +78257 0.47991943359375 +78258 0.5281982421875 +78259 0.511138916015625 +78260 0.456207275390625 +78261 0.407470703125 +78262 0.383758544921875 +78263 0.35687255859375 +78264 0.31182861328125 +78265 0.250885009765625 +78266 0.1654052734375 +78267 0.035247802734375 +78268 -0.142059326171875 +78269 -0.33563232421875 +78270 -0.5345458984375 +78271 -0.72186279296875 +78272 -0.836669921875 +78273 -0.8326416015625 +78274 -0.7296142578125 +78275 -0.582550048828125 +78276 -0.440093994140625 +78277 -0.324310302734375 +78278 -0.20147705078125 +78279 -0.044647216796875 +78280 0.103973388671875 +78281 0.202392578125 +78282 0.264495849609375 +78283 0.338897705078125 +78284 0.443817138671875 +78285 0.545074462890625 +78286 0.6173095703125 +78287 0.6524658203125 +78288 0.66339111328125 +78289 0.6561279296875 +78290 0.606781005859375 +78291 0.501190185546875 +78292 0.352783203125 +78293 0.176544189453125 +78294 -0.034820556640625 +78295 -0.258209228515625 +78296 -0.44244384765625 +78297 -0.5753173828125 +78298 -0.65203857421875 +78299 -0.641632080078125 +78300 -0.562164306640625 +78301 -0.458038330078125 +78302 -0.350555419921875 +78303 -0.260528564453125 +78304 -0.192108154296875 +78305 -0.141937255859375 +78306 -0.1021728515625 +78307 -0.062896728515625 +78308 -0.011932373046875 +78309 0.062835693359375 +78310 0.148712158203125 +78311 0.241729736328125 +78312 0.34912109375 +78313 0.457305908203125 +78314 0.54388427734375 +78315 0.5728759765625 +78316 0.506591796875 +78317 0.351226806640625 +78318 0.146514892578125 +78319 -0.05523681640625 +78320 -0.21624755859375 +78321 -0.334930419921875 +78322 -0.402984619140625 +78323 -0.4412841796875 +78324 -0.49578857421875 +78325 -0.5601806640625 +78326 -0.600738525390625 +78327 -0.584228515625 +78328 -0.47930908203125 +78329 -0.27935791015625 +78330 -0.0089111328125 +78331 0.268798828125 +78332 0.482818603515625 +78333 0.60369873046875 +78334 0.650421142578125 +78335 0.66400146484375 +78336 0.6414794921875 +78337 0.572540283203125 +78338 0.498138427734375 +78339 0.439453125 +78340 0.375518798828125 +78341 0.274505615234375 +78342 0.1087646484375 +78343 -0.099395751953125 +78344 -0.3182373046875 +78345 -0.5489501953125 +78346 -0.7738037109375 +78347 -0.86383056640625 +78348 -0.870391845703125 +78349 -0.86895751953125 +78350 -0.861053466796875 +78351 -0.765869140625 +78352 -0.5301513671875 +78353 -0.214691162109375 +78354 0.137359619140625 +78355 0.474822998046875 +78356 0.76239013671875 +78357 0.867462158203125 +78358 0.870361328125 +78359 0.86480712890625 +78360 0.831817626953125 +78361 0.677581787109375 +78362 0.495880126953125 +78363 0.30767822265625 +78364 0.116180419921875 +78365 -0.110748291015625 +78366 -0.381805419921875 +78367 -0.6572265625 +78368 -0.857421875 +78369 -0.870391845703125 +78370 -0.870391845703125 +78371 -0.86444091796875 +78372 -0.85723876953125 +78373 -0.790008544921875 +78374 -0.62847900390625 +78375 -0.3956298828125 +78376 -0.126708984375 +78377 0.150115966796875 +78378 0.424041748046875 +78379 0.670623779296875 +78380 0.854522705078125 +78381 0.866485595703125 +78382 0.86920166015625 +78383 0.8653564453125 +78384 0.857147216796875 +78385 0.766845703125 +78386 0.628509521484375 +78387 0.462127685546875 +78388 0.297210693359375 +78389 0.14862060546875 +78390 -0.00537109375 +78391 -0.15753173828125 +78392 -0.31304931640625 +78393 -0.48876953125 +78394 -0.6416015625 +78395 -0.751373291015625 +78396 -0.84619140625 +78397 -0.861297607421875 +78398 -0.863250732421875 +78399 -0.856597900390625 +78400 -0.7498779296875 +78401 -0.624542236328125 +78402 -0.47808837890625 +78403 -0.253387451171875 +78404 0.003692626953125 +78405 0.2257080078125 +78406 0.427154541015625 +78407 0.643218994140625 +78408 0.855926513671875 +78409 0.870361328125 +78410 0.870361328125 +78411 0.862762451171875 +78412 0.79669189453125 +78413 0.595794677734375 +78414 0.362152099609375 +78415 0.1270751953125 +78416 -0.086944580078125 +78417 -0.2784423828125 +78418 -0.484832763671875 +78419 -0.729583740234375 +78420 -0.86688232421875 +78421 -0.870391845703125 +78422 -0.86859130859375 +78423 -0.86279296875 +78424 -0.817962646484375 +78425 -0.6116943359375 +78426 -0.3128662109375 +78427 0.039398193359375 +78428 0.422821044921875 +78429 0.805145263671875 +78430 0.870361328125 +78431 0.870361328125 +78432 0.860015869140625 +78433 0.727935791015625 +78434 0.48114013671875 +78435 0.2059326171875 +78436 -0.06103515625 +78437 -0.29913330078125 +78438 -0.516204833984375 +78439 -0.7252197265625 +78440 -0.85980224609375 +78441 -0.870391845703125 +78442 -0.870391845703125 +78443 -0.858062744140625 +78444 -0.673004150390625 +78445 -0.42694091796875 +78446 -0.2100830078125 +78447 -0.0362548828125 +78448 0.10943603515625 +78449 0.23516845703125 +78450 0.373687744140625 +78451 0.517791748046875 +78452 0.602783203125 +78453 0.635711669921875 +78454 0.655181884765625 +78455 0.65948486328125 +78456 0.651275634765625 +78457 0.61846923828125 +78458 0.53753662109375 +78459 0.404144287109375 +78460 0.22186279296875 +78461 0.003997802734375 +78462 -0.22100830078125 +78463 -0.42449951171875 +78464 -0.579833984375 +78465 -0.641876220703125 +78466 -0.6177978515625 +78467 -0.575531005859375 +78468 -0.526336669921875 +78469 -0.42645263671875 +78470 -0.2581787109375 +78471 -0.068695068359375 +78472 0.09222412109375 +78473 0.232147216796875 +78474 0.3509521484375 +78475 0.410064697265625 +78476 0.372955322265625 +78477 0.2554931640625 +78478 0.10711669921875 +78479 -0.052886962890625 +78480 -0.186279296875 +78481 -0.23291015625 +78482 -0.209442138671875 +78483 -0.174163818359375 +78484 -0.126739501953125 +78485 -0.048126220703125 +78486 0.0426025390625 +78487 0.10748291015625 +78488 0.1409912109375 +78489 0.19708251953125 +78490 0.273651123046875 +78491 0.31768798828125 +78492 0.341094970703125 +78493 0.368011474609375 +78494 0.37249755859375 +78495 0.30072021484375 +78496 0.1517333984375 +78497 -0.01470947265625 +78498 -0.1883544921875 +78499 -0.372711181640625 +78500 -0.51397705078125 +78501 -0.57177734375 +78502 -0.53948974609375 +78503 -0.43511962890625 +78504 -0.2962646484375 +78505 -0.161102294921875 +78506 -0.0435791015625 +78507 0.060394287109375 +78508 0.13665771484375 +78509 0.170135498046875 +78510 0.16552734375 +78511 0.15728759765625 +78512 0.150787353515625 +78513 0.12200927734375 +78514 0.080108642578125 +78515 0.05126953125 +78516 0.062896728515625 +78517 0.09271240234375 +78518 0.092987060546875 +78519 0.07855224609375 +78520 0.06427001953125 +78521 0.0347900390625 +78522 -0.01171875 +78523 -0.056060791015625 +78524 -0.055511474609375 +78525 -0.010467529296875 +78526 0.02508544921875 +78527 0.025665283203125 +78528 0.017333984375 +78529 0.00189208984375 +78530 -0.03173828125 +78531 -0.071502685546875 +78532 -0.13543701171875 +78533 -0.219970703125 +78534 -0.300506591796875 +78535 -0.376312255859375 +78536 -0.416107177734375 +78537 -0.371124267578125 +78538 -0.242279052734375 +78539 -0.069732666015625 +78540 0.125640869140625 +78541 0.31268310546875 +78542 0.45501708984375 +78543 0.554779052734375 +78544 0.61065673828125 +78545 0.610931396484375 +78546 0.531463623046875 +78547 0.3883056640625 +78548 0.23468017578125 +78549 0.095245361328125 +78550 -0.00396728515625 +78551 -0.04852294921875 +78552 -0.055145263671875 +78553 -0.0758056640625 +78554 -0.138702392578125 +78555 -0.209197998046875 +78556 -0.289031982421875 +78557 -0.37884521484375 +78558 -0.456329345703125 +78559 -0.51641845703125 +78560 -0.519287109375 +78561 -0.458251953125 +78562 -0.384796142578125 +78563 -0.323699951171875 +78564 -0.269287109375 +78565 -0.1951904296875 +78566 -0.100006103515625 +78567 -0.01055908203125 +78568 0.1033935546875 +78569 0.24908447265625 +78570 0.373199462890625 +78571 0.45806884765625 +78572 0.511474609375 +78573 0.565399169921875 +78574 0.61138916015625 +78575 0.5897216796875 +78576 0.4906005859375 +78577 0.33148193359375 +78578 0.147796630859375 +78579 -0.01873779296875 +78580 -0.140289306640625 +78581 -0.191986083984375 +78582 -0.184295654296875 +78583 -0.161834716796875 +78584 -0.166595458984375 +78585 -0.19390869140625 +78586 -0.22442626953125 +78587 -0.279754638671875 +78588 -0.3389892578125 +78589 -0.3543701171875 +78590 -0.348175048828125 +78591 -0.32598876953125 +78592 -0.2581787109375 +78593 -0.139801025390625 +78594 0.014617919921875 +78595 0.144378662109375 +78596 0.221038818359375 +78597 0.27069091796875 +78598 0.294036865234375 +78599 0.311767578125 +78600 0.339141845703125 +78601 0.360260009765625 +78602 0.360504150390625 +78603 0.308380126953125 +78604 0.18170166015625 +78605 0.0047607421875 +78606 -0.17559814453125 +78607 -0.3143310546875 +78608 -0.36785888671875 +78609 -0.36248779296875 +78610 -0.343536376953125 +78611 -0.3018798828125 +78612 -0.231414794921875 +78613 -0.117645263671875 +78614 0.007049560546875 +78615 0.087982177734375 +78616 0.13946533203125 +78617 0.17425537109375 +78618 0.188201904296875 +78619 0.171234130859375 +78620 0.118438720703125 +78621 0.05706787109375 +78622 -0.010711669921875 +78623 -0.0914306640625 +78624 -0.162322998046875 +78625 -0.194549560546875 +78626 -0.1492919921875 +78627 -0.02166748046875 +78628 0.124053955078125 +78629 0.211151123046875 +78630 0.240447998046875 +78631 0.242218017578125 +78632 0.2257080078125 +78633 0.194366455078125 +78634 0.115509033203125 +78635 0.0128173828125 +78636 -0.053802490234375 +78637 -0.110626220703125 +78638 -0.199493408203125 +78639 -0.29437255859375 +78640 -0.33221435546875 +78641 -0.27972412109375 +78642 -0.185333251953125 +78643 -0.128204345703125 +78644 -0.115692138671875 +78645 -0.116455078125 +78646 -0.105926513671875 +78647 -0.053955078125 +78648 0.048797607421875 +78649 0.157318115234375 +78650 0.212005615234375 +78651 0.218475341796875 +78652 0.23724365234375 +78653 0.30535888671875 +78654 0.38128662109375 +78655 0.404449462890625 +78656 0.3944091796875 +78657 0.3885498046875 +78658 0.362640380859375 +78659 0.27362060546875 +78660 0.11712646484375 +78661 -0.054901123046875 +78662 -0.19085693359375 +78663 -0.28570556640625 +78664 -0.339263916015625 +78665 -0.3775634765625 +78666 -0.445709228515625 +78667 -0.535064697265625 +78668 -0.629058837890625 +78669 -0.697601318359375 +78670 -0.70391845703125 +78671 -0.6424560546875 +78672 -0.491241455078125 +78673 -0.265716552734375 +78674 -0.023712158203125 +78675 0.201751708984375 +78676 0.375823974609375 +78677 0.485076904296875 +78678 0.56884765625 +78679 0.634765625 +78680 0.63763427734375 +78681 0.5660400390625 +78682 0.4720458984375 +78683 0.40692138671875 +78684 0.3778076171875 +78685 0.376953125 +78686 0.371978759765625 +78687 0.313140869140625 +78688 0.184417724609375 +78689 0.011199951171875 +78690 -0.171051025390625 +78691 -0.33740234375 +78692 -0.47198486328125 +78693 -0.560394287109375 +78694 -0.58056640625 +78695 -0.54754638671875 +78696 -0.508575439453125 +78697 -0.459503173828125 +78698 -0.394378662109375 +78699 -0.35260009765625 +78700 -0.31170654296875 +78701 -0.197418212890625 +78702 -0.007965087890625 +78703 0.207489013671875 +78704 0.409210205078125 +78705 0.57208251953125 +78706 0.66595458984375 +78707 0.65875244140625 +78708 0.56744384765625 +78709 0.431396484375 +78710 0.29443359375 +78711 0.182464599609375 +78712 0.06365966796875 +78713 -0.075958251953125 +78714 -0.189422607421875 +78715 -0.271942138671875 +78716 -0.342529296875 +78717 -0.364166259765625 +78718 -0.327239990234375 +78719 -0.2769775390625 +78720 -0.253692626953125 +78721 -0.24365234375 +78722 -0.1983642578125 +78723 -0.116241455078125 +78724 -0.036834716796875 +78725 0.034881591796875 +78726 0.09124755859375 +78727 0.10888671875 +78728 0.125518798828125 +78729 0.15771484375 +78730 0.17828369140625 +78731 0.17108154296875 +78732 0.129974365234375 +78733 0.082427978515625 +78734 0.027679443359375 +78735 -0.065643310546875 +78736 -0.15936279296875 +78737 -0.21307373046875 +78738 -0.234649658203125 +78739 -0.2001953125 +78740 -0.119171142578125 +78741 -0.024749755859375 +78742 0.085784912109375 +78743 0.178131103515625 +78744 0.215576171875 +78745 0.211456298828125 +78746 0.17523193359375 +78747 0.128753662109375 +78748 0.1019287109375 +78749 0.0743408203125 +78750 0.04327392578125 +78751 0.038177490234375 +78752 0.076263427734375 +78753 0.14105224609375 +78754 0.186431884765625 +78755 0.188812255859375 +78756 0.1390380859375 +78757 0.041778564453125 +78758 -0.079437255859375 +78759 -0.219390869140625 +78760 -0.367828369140625 +78761 -0.494873046875 +78762 -0.556243896484375 +78763 -0.508697509765625 +78764 -0.3756103515625 +78765 -0.218902587890625 +78766 -0.063751220703125 +78767 0.091552734375 +78768 0.23602294921875 +78769 0.342987060546875 +78770 0.39520263671875 +78771 0.389373779296875 +78772 0.324249267578125 +78773 0.224090576171875 +78774 0.124267578125 +78775 0.037078857421875 +78776 -0.010101318359375 +78777 -0.019439697265625 +78778 -0.022796630859375 +78779 -0.001556396484375 +78780 0.056304931640625 +78781 0.106719970703125 +78782 0.096893310546875 +78783 0.042694091796875 +78784 -0.018035888671875 +78785 -0.07586669921875 +78786 -0.11944580078125 +78787 -0.15972900390625 +78788 -0.202606201171875 +78789 -0.24859619140625 +78790 -0.30517578125 +78791 -0.36212158203125 +78792 -0.39141845703125 +78793 -0.35528564453125 +78794 -0.249969482421875 +78795 -0.092864990234375 +78796 0.08905029296875 +78797 0.2352294921875 +78798 0.318817138671875 +78799 0.358642578125 +78800 0.347747802734375 +78801 0.28564453125 +78802 0.223175048828125 +78803 0.196746826171875 +78804 0.179840087890625 +78805 0.155548095703125 +78806 0.151214599609375 +78807 0.156951904296875 +78808 0.13177490234375 +78809 0.100799560546875 +78810 0.087127685546875 +78811 0.05487060546875 +78812 -0.009002685546875 +78813 -0.10400390625 +78814 -0.229400634765625 +78815 -0.35552978515625 +78816 -0.441925048828125 +78817 -0.473846435546875 +78818 -0.464813232421875 +78819 -0.419097900390625 +78820 -0.334320068359375 +78821 -0.227935791015625 +78822 -0.12347412109375 +78823 -0.02764892578125 +78824 0.077667236328125 +78825 0.2132568359375 +78826 0.38885498046875 +78827 0.582794189453125 +78828 0.734039306640625 +78829 0.800140380859375 +78830 0.7783203125 +78831 0.6651611328125 +78832 0.45965576171875 +78833 0.199188232421875 +78834 -0.050689697265625 +78835 -0.23297119140625 +78836 -0.33013916015625 +78837 -0.368408203125 +78838 -0.378936767578125 +78839 -0.376983642578125 +78840 -0.37969970703125 +78841 -0.391510009765625 +78842 -0.385345458984375 +78843 -0.3419189453125 +78844 -0.28289794921875 +78845 -0.251617431640625 +78846 -0.266143798828125 +78847 -0.273345947265625 +78848 -0.216796875 +78849 -0.128265380859375 +78850 -0.068145751953125 +78851 -0.0430908203125 +78852 -0.024444580078125 +78853 0.020721435546875 +78854 0.124481201171875 +78855 0.25787353515625 +78856 0.379119873046875 +78857 0.47991943359375 +78858 0.5281982421875 +78859 0.511138916015625 +78860 0.456207275390625 +78861 0.407470703125 +78862 0.383758544921875 +78863 0.35687255859375 +78864 0.31182861328125 +78865 0.250885009765625 +78866 0.1654052734375 +78867 0.035247802734375 +78868 -0.142059326171875 +78869 -0.33563232421875 +78870 -0.5345458984375 +78871 -0.72186279296875 +78872 -0.836669921875 +78873 -0.8326416015625 +78874 -0.7296142578125 +78875 -0.582550048828125 +78876 -0.440093994140625 +78877 -0.324310302734375 +78878 -0.20147705078125 +78879 -0.044647216796875 +78880 0.103973388671875 +78881 0.202392578125 +78882 0.264495849609375 +78883 0.338897705078125 +78884 0.443817138671875 +78885 0.545074462890625 +78886 0.6173095703125 +78887 0.6524658203125 +78888 0.66339111328125 +78889 0.6561279296875 +78890 0.606781005859375 +78891 0.501190185546875 +78892 0.352783203125 +78893 0.176544189453125 +78894 -0.034820556640625 +78895 -0.258209228515625 +78896 -0.44244384765625 +78897 -0.5753173828125 +78898 -0.65203857421875 +78899 -0.641632080078125 +78900 -0.562164306640625 +78901 -0.458038330078125 +78902 -0.350555419921875 +78903 -0.260528564453125 +78904 -0.192108154296875 +78905 -0.141937255859375 +78906 -0.1021728515625 +78907 -0.062896728515625 +78908 -0.011932373046875 +78909 0.062835693359375 +78910 0.148712158203125 +78911 0.241729736328125 +78912 0.34912109375 +78913 0.457305908203125 +78914 0.54388427734375 +78915 0.5728759765625 +78916 0.506591796875 +78917 0.351226806640625 +78918 0.146514892578125 +78919 -0.05523681640625 +78920 -0.21624755859375 +78921 -0.334930419921875 +78922 -0.402984619140625 +78923 -0.4412841796875 +78924 -0.49578857421875 +78925 -0.5601806640625 +78926 -0.600738525390625 +78927 -0.584228515625 +78928 -0.47930908203125 +78929 -0.27935791015625 +78930 -0.0089111328125 +78931 0.268798828125 +78932 0.482818603515625 +78933 0.60369873046875 +78934 0.650421142578125 +78935 0.66400146484375 +78936 0.6414794921875 +78937 0.572540283203125 +78938 0.498138427734375 +78939 0.439453125 +78940 0.375518798828125 +78941 0.274505615234375 +78942 0.1087646484375 +78943 -0.099395751953125 +78944 -0.3182373046875 +78945 -0.5489501953125 +78946 -0.7738037109375 +78947 -0.86383056640625 +78948 -0.870391845703125 +78949 -0.86895751953125 +78950 -0.861053466796875 +78951 -0.765869140625 +78952 -0.5301513671875 +78953 -0.214691162109375 +78954 0.137359619140625 +78955 0.474822998046875 +78956 0.76239013671875 +78957 0.867462158203125 +78958 0.870361328125 +78959 0.86480712890625 +78960 0.831817626953125 +78961 0.677581787109375 +78962 0.495880126953125 +78963 0.30767822265625 +78964 0.116180419921875 +78965 -0.110748291015625 +78966 -0.381805419921875 +78967 -0.6572265625 +78968 -0.857421875 +78969 -0.870391845703125 +78970 -0.870391845703125 +78971 -0.86444091796875 +78972 -0.85723876953125 +78973 -0.790008544921875 +78974 -0.62847900390625 +78975 -0.3956298828125 +78976 -0.126708984375 +78977 0.150115966796875 +78978 0.424041748046875 +78979 0.670623779296875 +78980 0.854522705078125 +78981 0.866485595703125 +78982 0.86920166015625 +78983 0.8653564453125 +78984 0.857147216796875 +78985 0.766845703125 +78986 0.628509521484375 +78987 0.462127685546875 +78988 0.297210693359375 +78989 0.14862060546875 +78990 -0.00537109375 +78991 -0.15753173828125 +78992 -0.31304931640625 +78993 -0.48876953125 +78994 -0.6416015625 +78995 -0.751373291015625 +78996 -0.84619140625 +78997 -0.861297607421875 +78998 -0.863250732421875 +78999 -0.856597900390625 +79000 -0.7498779296875 +79001 -0.624542236328125 +79002 -0.47808837890625 +79003 -0.253387451171875 +79004 0.003692626953125 +79005 0.2257080078125 +79006 0.427154541015625 +79007 0.643218994140625 +79008 0.855926513671875 +79009 0.870361328125 +79010 0.870361328125 +79011 0.862762451171875 +79012 0.79669189453125 +79013 0.595794677734375 +79014 0.362152099609375 +79015 0.1270751953125 +79016 -0.086944580078125 +79017 -0.2784423828125 +79018 -0.484832763671875 +79019 -0.729583740234375 +79020 -0.86688232421875 +79021 -0.870391845703125 +79022 -0.86859130859375 +79023 -0.86279296875 +79024 -0.817962646484375 +79025 -0.6116943359375 +79026 -0.3128662109375 +79027 0.039398193359375 +79028 0.422821044921875 +79029 0.805145263671875 +79030 0.870361328125 +79031 0.870361328125 +79032 0.860015869140625 +79033 0.727935791015625 +79034 0.48114013671875 +79035 0.2059326171875 +79036 -0.06103515625 +79037 -0.29913330078125 +79038 -0.516204833984375 +79039 -0.7252197265625 +79040 -0.85980224609375 +79041 -0.870391845703125 +79042 -0.870391845703125 +79043 -0.858062744140625 +79044 -0.673004150390625 +79045 -0.42694091796875 +79046 -0.2100830078125 +79047 -0.0362548828125 +79048 0.10943603515625 +79049 0.23516845703125 +79050 0.373687744140625 +79051 0.517791748046875 +79052 0.602783203125 +79053 0.635711669921875 +79054 0.655181884765625 +79055 0.65948486328125 +79056 0.651275634765625 +79057 0.61846923828125 +79058 0.53753662109375 +79059 0.404144287109375 +79060 0.22186279296875 +79061 0.003997802734375 +79062 -0.22100830078125 +79063 -0.42449951171875 +79064 -0.579833984375 +79065 -0.641876220703125 +79066 -0.6177978515625 +79067 -0.575531005859375 +79068 -0.526336669921875 +79069 -0.42645263671875 +79070 -0.2581787109375 +79071 -0.068695068359375 +79072 0.09222412109375 +79073 0.232147216796875 +79074 0.3509521484375 +79075 0.410064697265625 +79076 0.372955322265625 +79077 0.2554931640625 +79078 0.10711669921875 +79079 -0.052886962890625 +79080 -0.186279296875 +79081 -0.23291015625 +79082 -0.209442138671875 +79083 -0.174163818359375 +79084 -0.126739501953125 +79085 -0.048126220703125 +79086 0.0426025390625 +79087 0.10748291015625 +79088 0.1409912109375 +79089 0.19708251953125 +79090 0.273651123046875 +79091 0.31768798828125 +79092 0.341094970703125 +79093 0.368011474609375 +79094 0.37249755859375 +79095 0.30072021484375 +79096 0.1517333984375 +79097 -0.01470947265625 +79098 -0.1883544921875 +79099 -0.372711181640625 +79100 -0.51397705078125 +79101 -0.57177734375 +79102 -0.53948974609375 +79103 -0.43511962890625 +79104 -0.2962646484375 +79105 -0.161102294921875 +79106 -0.0435791015625 +79107 0.060394287109375 +79108 0.13665771484375 +79109 0.170135498046875 +79110 0.16552734375 +79111 0.15728759765625 +79112 0.150787353515625 +79113 0.12200927734375 +79114 0.080108642578125 +79115 0.05126953125 +79116 0.062896728515625 +79117 0.09271240234375 +79118 0.092987060546875 +79119 0.07855224609375 +79120 0.06427001953125 +79121 0.0347900390625 +79122 -0.01171875 +79123 -0.056060791015625 +79124 -0.055511474609375 +79125 -0.010467529296875 +79126 0.02508544921875 +79127 0.025665283203125 +79128 0.017333984375 +79129 0.00189208984375 +79130 -0.03173828125 +79131 -0.071502685546875 +79132 -0.13543701171875 +79133 -0.219970703125 +79134 -0.300506591796875 +79135 -0.376312255859375 +79136 -0.416107177734375 +79137 -0.371124267578125 +79138 -0.242279052734375 +79139 -0.069732666015625 +79140 0.125640869140625 +79141 0.31268310546875 +79142 0.45501708984375 +79143 0.554779052734375 +79144 0.61065673828125 +79145 0.610931396484375 +79146 0.531463623046875 +79147 0.3883056640625 +79148 0.23468017578125 +79149 0.095245361328125 +79150 -0.00396728515625 +79151 -0.04852294921875 +79152 -0.055145263671875 +79153 -0.0758056640625 +79154 -0.138702392578125 +79155 -0.209197998046875 +79156 -0.289031982421875 +79157 -0.37884521484375 +79158 -0.456329345703125 +79159 -0.51641845703125 +79160 -0.519287109375 +79161 -0.458251953125 +79162 -0.384796142578125 +79163 -0.323699951171875 +79164 -0.269287109375 +79165 -0.1951904296875 +79166 -0.100006103515625 +79167 -0.01055908203125 +79168 0.1033935546875 +79169 0.24908447265625 +79170 0.373199462890625 +79171 0.45806884765625 +79172 0.511474609375 +79173 0.565399169921875 +79174 0.61138916015625 +79175 0.5897216796875 +79176 0.4906005859375 +79177 0.33148193359375 +79178 0.147796630859375 +79179 -0.01873779296875 +79180 -0.140289306640625 +79181 -0.191986083984375 +79182 -0.184295654296875 +79183 -0.161834716796875 +79184 -0.166595458984375 +79185 -0.19390869140625 +79186 -0.22442626953125 +79187 -0.279754638671875 +79188 -0.3389892578125 +79189 -0.3543701171875 +79190 -0.348175048828125 +79191 -0.32598876953125 +79192 -0.2581787109375 +79193 -0.139801025390625 +79194 0.014617919921875 +79195 0.144378662109375 +79196 0.221038818359375 +79197 0.27069091796875 +79198 0.294036865234375 +79199 0.311767578125 +79200 0.339141845703125 +79201 0.360260009765625 +79202 0.360504150390625 +79203 0.308380126953125 +79204 0.18170166015625 +79205 0.0047607421875 +79206 -0.17559814453125 +79207 -0.3143310546875 +79208 -0.36785888671875 +79209 -0.36248779296875 +79210 -0.343536376953125 +79211 -0.3018798828125 +79212 -0.231414794921875 +79213 -0.117645263671875 +79214 0.007049560546875 +79215 0.087982177734375 +79216 0.13946533203125 +79217 0.17425537109375 +79218 0.188201904296875 +79219 0.171234130859375 +79220 0.118438720703125 +79221 0.05706787109375 +79222 -0.010711669921875 +79223 -0.0914306640625 +79224 -0.162322998046875 +79225 -0.194549560546875 +79226 -0.1492919921875 +79227 -0.02166748046875 +79228 0.124053955078125 +79229 0.211151123046875 +79230 0.240447998046875 +79231 0.242218017578125 +79232 0.2257080078125 +79233 0.194366455078125 +79234 0.115509033203125 +79235 0.0128173828125 +79236 -0.053802490234375 +79237 -0.110626220703125 +79238 -0.199493408203125 +79239 -0.29437255859375 +79240 -0.33221435546875 +79241 -0.27972412109375 +79242 -0.185333251953125 +79243 -0.128204345703125 +79244 -0.115692138671875 +79245 -0.116455078125 +79246 -0.105926513671875 +79247 -0.053955078125 +79248 0.048797607421875 +79249 0.157318115234375 +79250 0.212005615234375 +79251 0.218475341796875 +79252 0.23724365234375 +79253 0.30535888671875 +79254 0.38128662109375 +79255 0.404449462890625 +79256 0.3944091796875 +79257 0.3885498046875 +79258 0.362640380859375 +79259 0.27362060546875 +79260 0.11712646484375 +79261 -0.054901123046875 +79262 -0.19085693359375 +79263 -0.28570556640625 +79264 -0.339263916015625 +79265 -0.3775634765625 +79266 -0.445709228515625 +79267 -0.535064697265625 +79268 -0.629058837890625 +79269 -0.697601318359375 +79270 -0.70391845703125 +79271 -0.6424560546875 +79272 -0.491241455078125 +79273 -0.265716552734375 +79274 -0.023712158203125 +79275 0.201751708984375 +79276 0.375823974609375 +79277 0.485076904296875 +79278 0.56884765625 +79279 0.634765625 +79280 0.63763427734375 +79281 0.5660400390625 +79282 0.4720458984375 +79283 0.40692138671875 +79284 0.3778076171875 +79285 0.376953125 +79286 0.371978759765625 +79287 0.313140869140625 +79288 0.184417724609375 +79289 0.011199951171875 +79290 -0.171051025390625 +79291 -0.33740234375 +79292 -0.47198486328125 +79293 -0.560394287109375 +79294 -0.58056640625 +79295 -0.54754638671875 +79296 -0.508575439453125 +79297 -0.459503173828125 +79298 -0.394378662109375 +79299 -0.35260009765625 +79300 -0.31170654296875 +79301 -0.197418212890625 +79302 -0.007965087890625 +79303 0.207489013671875 +79304 0.409210205078125 +79305 0.57208251953125 +79306 0.66595458984375 +79307 0.65875244140625 +79308 0.56744384765625 +79309 0.431396484375 +79310 0.29443359375 +79311 0.182464599609375 +79312 0.06365966796875 +79313 -0.075958251953125 +79314 -0.189422607421875 +79315 -0.271942138671875 +79316 -0.342529296875 +79317 -0.364166259765625 +79318 -0.327239990234375 +79319 -0.2769775390625 +79320 -0.253692626953125 +79321 -0.24365234375 +79322 -0.1983642578125 +79323 -0.116241455078125 +79324 -0.036834716796875 +79325 0.034881591796875 +79326 0.09124755859375 +79327 0.10888671875 +79328 0.125518798828125 +79329 0.15771484375 +79330 0.17828369140625 +79331 0.17108154296875 +79332 0.129974365234375 +79333 0.082427978515625 +79334 0.027679443359375 +79335 -0.065643310546875 +79336 -0.15936279296875 +79337 -0.21307373046875 +79338 -0.234649658203125 +79339 -0.2001953125 +79340 -0.119171142578125 +79341 -0.024749755859375 +79342 0.085784912109375 +79343 0.178131103515625 +79344 0.215576171875 +79345 0.211456298828125 +79346 0.17523193359375 +79347 0.128753662109375 +79348 0.1019287109375 +79349 0.0743408203125 +79350 0.04327392578125 +79351 0.038177490234375 +79352 0.076263427734375 +79353 0.14105224609375 +79354 0.186431884765625 +79355 0.188812255859375 +79356 0.1390380859375 +79357 0.041778564453125 +79358 -0.079437255859375 +79359 -0.219390869140625 +79360 -0.367828369140625 +79361 -0.494873046875 +79362 -0.556243896484375 +79363 -0.508697509765625 +79364 -0.3756103515625 +79365 -0.218902587890625 +79366 -0.063751220703125 +79367 0.091552734375 +79368 0.23602294921875 +79369 0.342987060546875 +79370 0.39520263671875 +79371 0.389373779296875 +79372 0.324249267578125 +79373 0.224090576171875 +79374 0.124267578125 +79375 0.037078857421875 +79376 -0.010101318359375 +79377 -0.019439697265625 +79378 -0.022796630859375 +79379 -0.001556396484375 +79380 0.056304931640625 +79381 0.106719970703125 +79382 0.096893310546875 +79383 0.042694091796875 +79384 -0.018035888671875 +79385 -0.07586669921875 +79386 -0.11944580078125 +79387 -0.15972900390625 +79388 -0.202606201171875 +79389 -0.24859619140625 +79390 -0.30517578125 +79391 -0.36212158203125 +79392 -0.39141845703125 +79393 -0.35528564453125 +79394 -0.249969482421875 +79395 -0.092864990234375 +79396 0.08905029296875 +79397 0.2352294921875 +79398 0.318817138671875 +79399 0.358642578125 +79400 0.347747802734375 +79401 0.28564453125 +79402 0.223175048828125 +79403 0.196746826171875 +79404 0.179840087890625 +79405 0.155548095703125 +79406 0.151214599609375 +79407 0.156951904296875 +79408 0.13177490234375 +79409 0.100799560546875 +79410 0.087127685546875 +79411 0.05487060546875 +79412 -0.009002685546875 +79413 -0.10400390625 +79414 -0.229400634765625 +79415 -0.35552978515625 +79416 -0.441925048828125 +79417 -0.473846435546875 +79418 -0.464813232421875 +79419 -0.419097900390625 +79420 -0.334320068359375 +79421 -0.227935791015625 +79422 -0.12347412109375 +79423 -0.02764892578125 +79424 0.077667236328125 +79425 0.2132568359375 +79426 0.38885498046875 +79427 0.582794189453125 +79428 0.734039306640625 +79429 0.800140380859375 +79430 0.7783203125 +79431 0.6651611328125 +79432 0.45965576171875 +79433 0.199188232421875 +79434 -0.050689697265625 +79435 -0.23297119140625 +79436 -0.33013916015625 +79437 -0.368408203125 +79438 -0.378936767578125 +79439 -0.376983642578125 +79440 -0.37969970703125 +79441 -0.391510009765625 +79442 -0.385345458984375 +79443 -0.3419189453125 +79444 -0.28289794921875 +79445 -0.251617431640625 +79446 -0.266143798828125 +79447 -0.273345947265625 +79448 -0.216796875 +79449 -0.128265380859375 +79450 -0.068145751953125 +79451 -0.0430908203125 +79452 -0.024444580078125 +79453 0.020721435546875 +79454 0.124481201171875 +79455 0.25787353515625 +79456 0.379119873046875 +79457 0.47991943359375 +79458 0.5281982421875 +79459 0.511138916015625 +79460 0.456207275390625 +79461 0.407470703125 +79462 0.383758544921875 +79463 0.35687255859375 +79464 0.31182861328125 +79465 0.250885009765625 +79466 0.1654052734375 +79467 0.035247802734375 +79468 -0.142059326171875 +79469 -0.33563232421875 +79470 -0.5345458984375 +79471 -0.72186279296875 +79472 -0.836669921875 +79473 -0.8326416015625 +79474 -0.7296142578125 +79475 -0.582550048828125 +79476 -0.440093994140625 +79477 -0.324310302734375 +79478 -0.20147705078125 +79479 -0.044647216796875 +79480 0.103973388671875 +79481 0.202392578125 +79482 0.264495849609375 +79483 0.338897705078125 +79484 0.443817138671875 +79485 0.545074462890625 +79486 0.6173095703125 +79487 0.6524658203125 +79488 0.66339111328125 +79489 0.6561279296875 +79490 0.606781005859375 +79491 0.501190185546875 +79492 0.352783203125 +79493 0.176544189453125 +79494 -0.034820556640625 +79495 -0.258209228515625 +79496 -0.44244384765625 +79497 -0.5753173828125 +79498 -0.65203857421875 +79499 -0.641632080078125 +79500 -0.562164306640625 +79501 -0.458038330078125 +79502 -0.350555419921875 +79503 -0.260528564453125 +79504 -0.192108154296875 +79505 -0.141937255859375 +79506 -0.1021728515625 +79507 -0.062896728515625 +79508 -0.011932373046875 +79509 0.062835693359375 +79510 0.148712158203125 +79511 0.241729736328125 +79512 0.34912109375 +79513 0.457305908203125 +79514 0.54388427734375 +79515 0.5728759765625 +79516 0.506591796875 +79517 0.351226806640625 +79518 0.146514892578125 +79519 -0.05523681640625 +79520 -0.21624755859375 +79521 -0.334930419921875 +79522 -0.402984619140625 +79523 -0.4412841796875 +79524 -0.49578857421875 +79525 -0.5601806640625 +79526 -0.600738525390625 +79527 -0.584228515625 +79528 -0.47930908203125 +79529 -0.27935791015625 +79530 -0.0089111328125 +79531 0.268798828125 +79532 0.482818603515625 +79533 0.60369873046875 +79534 0.650421142578125 +79535 0.66400146484375 +79536 0.6414794921875 +79537 0.572540283203125 +79538 0.498138427734375 +79539 0.439453125 +79540 0.375518798828125 +79541 0.274505615234375 +79542 0.1087646484375 +79543 -0.099395751953125 +79544 -0.3182373046875 +79545 -0.5489501953125 +79546 -0.7738037109375 +79547 -0.86383056640625 +79548 -0.870391845703125 +79549 -0.86895751953125 +79550 -0.861053466796875 +79551 -0.765869140625 +79552 -0.5301513671875 +79553 -0.214691162109375 +79554 0.137359619140625 +79555 0.474822998046875 +79556 0.76239013671875 +79557 0.867462158203125 +79558 0.870361328125 +79559 0.86480712890625 +79560 0.831817626953125 +79561 0.677581787109375 +79562 0.495880126953125 +79563 0.30767822265625 +79564 0.116180419921875 +79565 -0.110748291015625 +79566 -0.381805419921875 +79567 -0.6572265625 +79568 -0.857421875 +79569 -0.870391845703125 +79570 -0.870391845703125 +79571 -0.86444091796875 +79572 -0.85723876953125 +79573 -0.790008544921875 +79574 -0.62847900390625 +79575 -0.3956298828125 +79576 -0.126708984375 +79577 0.150115966796875 +79578 0.424041748046875 +79579 0.670623779296875 +79580 0.854522705078125 +79581 0.866485595703125 +79582 0.86920166015625 +79583 0.8653564453125 +79584 0.857147216796875 +79585 0.766845703125 +79586 0.628509521484375 +79587 0.462127685546875 +79588 0.297210693359375 +79589 0.14862060546875 +79590 -0.00537109375 +79591 -0.15753173828125 +79592 -0.31304931640625 +79593 -0.48876953125 +79594 -0.6416015625 +79595 -0.751373291015625 +79596 -0.84619140625 +79597 -0.861297607421875 +79598 -0.863250732421875 +79599 -0.856597900390625 +79600 -0.7498779296875 +79601 -0.624542236328125 +79602 -0.47808837890625 +79603 -0.253387451171875 +79604 0.003692626953125 +79605 0.2257080078125 +79606 0.427154541015625 +79607 0.643218994140625 +79608 0.855926513671875 +79609 0.870361328125 +79610 0.870361328125 +79611 0.862762451171875 +79612 0.79669189453125 +79613 0.595794677734375 +79614 0.362152099609375 +79615 0.1270751953125 +79616 -0.086944580078125 +79617 -0.2784423828125 +79618 -0.484832763671875 +79619 -0.729583740234375 +79620 -0.86688232421875 +79621 -0.870391845703125 +79622 -0.86859130859375 +79623 -0.86279296875 +79624 -0.817962646484375 +79625 -0.6116943359375 +79626 -0.3128662109375 +79627 0.039398193359375 +79628 0.422821044921875 +79629 0.805145263671875 +79630 0.870361328125 +79631 0.870361328125 +79632 0.860015869140625 +79633 0.727935791015625 +79634 0.48114013671875 +79635 0.2059326171875 +79636 -0.06103515625 +79637 -0.29913330078125 +79638 -0.516204833984375 +79639 -0.7252197265625 +79640 -0.85980224609375 +79641 -0.870391845703125 +79642 -0.870391845703125 +79643 -0.858062744140625 +79644 -0.673004150390625 +79645 -0.42694091796875 +79646 -0.2100830078125 +79647 -0.0362548828125 +79648 0.10943603515625 +79649 0.23516845703125 +79650 0.373687744140625 +79651 0.517791748046875 +79652 0.602783203125 +79653 0.635711669921875 +79654 0.655181884765625 +79655 0.65948486328125 +79656 0.651275634765625 +79657 0.61846923828125 +79658 0.53753662109375 +79659 0.404144287109375 +79660 0.22186279296875 +79661 0.003997802734375 +79662 -0.22100830078125 +79663 -0.42449951171875 +79664 -0.579833984375 +79665 -0.641876220703125 +79666 -0.6177978515625 +79667 -0.575531005859375 +79668 -0.526336669921875 +79669 -0.42645263671875 +79670 -0.2581787109375 +79671 -0.068695068359375 +79672 0.09222412109375 +79673 0.232147216796875 +79674 0.3509521484375 +79675 0.410064697265625 +79676 0.372955322265625 +79677 0.2554931640625 +79678 0.10711669921875 +79679 -0.052886962890625 +79680 -0.186279296875 +79681 -0.23291015625 +79682 -0.209442138671875 +79683 -0.174163818359375 +79684 -0.126739501953125 +79685 -0.048126220703125 +79686 0.0426025390625 +79687 0.10748291015625 +79688 0.1409912109375 +79689 0.19708251953125 +79690 0.273651123046875 +79691 0.31768798828125 +79692 0.341094970703125 +79693 0.368011474609375 +79694 0.37249755859375 +79695 0.30072021484375 +79696 0.1517333984375 +79697 -0.01470947265625 +79698 -0.1883544921875 +79699 -0.372711181640625 +79700 -0.51397705078125 +79701 -0.57177734375 +79702 -0.53948974609375 +79703 -0.43511962890625 +79704 -0.2962646484375 +79705 -0.161102294921875 +79706 -0.0435791015625 +79707 0.060394287109375 +79708 0.13665771484375 +79709 0.170135498046875 +79710 0.16552734375 +79711 0.15728759765625 +79712 0.150787353515625 +79713 0.12200927734375 +79714 0.080108642578125 +79715 0.05126953125 +79716 0.062896728515625 +79717 0.09271240234375 +79718 0.092987060546875 +79719 0.07855224609375 +79720 0.06427001953125 +79721 0.0347900390625 +79722 -0.01171875 +79723 -0.056060791015625 +79724 -0.055511474609375 +79725 -0.010467529296875 +79726 0.02508544921875 +79727 0.025665283203125 +79728 0.017333984375 +79729 0.00189208984375 +79730 -0.03173828125 +79731 -0.071502685546875 +79732 -0.13543701171875 +79733 -0.219970703125 +79734 -0.300506591796875 +79735 -0.376312255859375 +79736 -0.416107177734375 +79737 -0.371124267578125 +79738 -0.242279052734375 +79739 -0.069732666015625 +79740 0.125640869140625 +79741 0.31268310546875 +79742 0.45501708984375 +79743 0.554779052734375 +79744 0.61065673828125 +79745 0.610931396484375 +79746 0.531463623046875 +79747 0.3883056640625 +79748 0.23468017578125 +79749 0.095245361328125 +79750 -0.00396728515625 +79751 -0.04852294921875 +79752 -0.055145263671875 +79753 -0.0758056640625 +79754 -0.138702392578125 +79755 -0.209197998046875 +79756 -0.289031982421875 +79757 -0.37884521484375 +79758 -0.456329345703125 +79759 -0.51641845703125 +79760 -0.519287109375 +79761 -0.458251953125 +79762 -0.384796142578125 +79763 -0.323699951171875 +79764 -0.269287109375 +79765 -0.1951904296875 +79766 -0.100006103515625 +79767 -0.01055908203125 +79768 0.1033935546875 +79769 0.24908447265625 +79770 0.373199462890625 +79771 0.45806884765625 +79772 0.511474609375 +79773 0.565399169921875 +79774 0.61138916015625 +79775 0.5897216796875 +79776 0.4906005859375 +79777 0.33148193359375 +79778 0.147796630859375 +79779 -0.01873779296875 +79780 -0.140289306640625 +79781 -0.191986083984375 +79782 -0.184295654296875 +79783 -0.161834716796875 +79784 -0.166595458984375 +79785 -0.19390869140625 +79786 -0.22442626953125 +79787 -0.279754638671875 +79788 -0.3389892578125 +79789 -0.3543701171875 +79790 -0.348175048828125 +79791 -0.32598876953125 +79792 -0.2581787109375 +79793 -0.139801025390625 +79794 0.014617919921875 +79795 0.144378662109375 +79796 0.221038818359375 +79797 0.27069091796875 +79798 0.294036865234375 +79799 0.311767578125 +79800 0.339141845703125 +79801 0.360260009765625 +79802 0.360504150390625 +79803 0.308380126953125 +79804 0.18170166015625 +79805 0.0047607421875 +79806 -0.17559814453125 +79807 -0.3143310546875 +79808 -0.36785888671875 +79809 -0.36248779296875 +79810 -0.343536376953125 +79811 -0.3018798828125 +79812 -0.231414794921875 +79813 -0.117645263671875 +79814 0.007049560546875 +79815 0.087982177734375 +79816 0.13946533203125 +79817 0.17425537109375 +79818 0.188201904296875 +79819 0.171234130859375 +79820 0.118438720703125 +79821 0.05706787109375 +79822 -0.010711669921875 +79823 -0.0914306640625 +79824 -0.162322998046875 +79825 -0.194549560546875 +79826 -0.1492919921875 +79827 -0.02166748046875 +79828 0.124053955078125 +79829 0.211151123046875 +79830 0.240447998046875 +79831 0.242218017578125 +79832 0.2257080078125 +79833 0.194366455078125 +79834 0.115509033203125 +79835 0.0128173828125 +79836 -0.053802490234375 +79837 -0.110626220703125 +79838 -0.199493408203125 +79839 -0.29437255859375 +79840 -0.33221435546875 +79841 -0.27972412109375 +79842 -0.185333251953125 +79843 -0.128204345703125 +79844 -0.115692138671875 +79845 -0.116455078125 +79846 -0.105926513671875 +79847 -0.053955078125 +79848 0.048797607421875 +79849 0.157318115234375 +79850 0.212005615234375 +79851 0.218475341796875 +79852 0.23724365234375 +79853 0.30535888671875 +79854 0.38128662109375 +79855 0.404449462890625 +79856 0.3944091796875 +79857 0.3885498046875 +79858 0.362640380859375 +79859 0.27362060546875 +79860 0.11712646484375 +79861 -0.054901123046875 +79862 -0.19085693359375 +79863 -0.28570556640625 +79864 -0.339263916015625 +79865 -0.3775634765625 +79866 -0.445709228515625 +79867 -0.535064697265625 +79868 -0.629058837890625 +79869 -0.697601318359375 +79870 -0.70391845703125 +79871 -0.6424560546875 +79872 -0.491241455078125 +79873 -0.265716552734375 +79874 -0.023712158203125 +79875 0.201751708984375 +79876 0.375823974609375 +79877 0.485076904296875 +79878 0.56884765625 +79879 0.634765625 +79880 0.63763427734375 +79881 0.5660400390625 +79882 0.4720458984375 +79883 0.40692138671875 +79884 0.3778076171875 +79885 0.376953125 +79886 0.371978759765625 +79887 0.313140869140625 +79888 0.184417724609375 +79889 0.011199951171875 +79890 -0.171051025390625 +79891 -0.33740234375 +79892 -0.47198486328125 +79893 -0.560394287109375 +79894 -0.58056640625 +79895 -0.54754638671875 +79896 -0.508575439453125 +79897 -0.459503173828125 +79898 -0.394378662109375 +79899 -0.35260009765625 +79900 -0.31170654296875 +79901 -0.197418212890625 +79902 -0.007965087890625 +79903 0.207489013671875 +79904 0.409210205078125 +79905 0.57208251953125 +79906 0.66595458984375 +79907 0.65875244140625 +79908 0.56744384765625 +79909 0.431396484375 +79910 0.29443359375 +79911 0.182464599609375 +79912 0.06365966796875 +79913 -0.075958251953125 +79914 -0.189422607421875 +79915 -0.271942138671875 +79916 -0.342529296875 +79917 -0.364166259765625 +79918 -0.327239990234375 +79919 -0.2769775390625 +79920 -0.253692626953125 +79921 -0.24365234375 +79922 -0.1983642578125 +79923 -0.116241455078125 +79924 -0.036834716796875 +79925 0.034881591796875 +79926 0.09124755859375 +79927 0.10888671875 +79928 0.125518798828125 +79929 0.15771484375 +79930 0.17828369140625 +79931 0.17108154296875 +79932 0.129974365234375 +79933 0.082427978515625 +79934 0.027679443359375 +79935 -0.065643310546875 +79936 -0.15936279296875 +79937 -0.21307373046875 +79938 -0.234649658203125 +79939 -0.2001953125 +79940 -0.119171142578125 +79941 -0.024749755859375 +79942 0.085784912109375 +79943 0.178131103515625 +79944 0.215576171875 +79945 0.211456298828125 +79946 0.17523193359375 +79947 0.128753662109375 +79948 0.1019287109375 +79949 0.0743408203125 +79950 0.04327392578125 +79951 0.038177490234375 +79952 0.076263427734375 +79953 0.14105224609375 +79954 0.186431884765625 +79955 0.188812255859375 +79956 0.1390380859375 +79957 0.041778564453125 +79958 -0.079437255859375 +79959 -0.219390869140625 +79960 -0.367828369140625 +79961 -0.494873046875 +79962 -0.556243896484375 +79963 -0.508697509765625 +79964 -0.3756103515625 +79965 -0.218902587890625 +79966 -0.063751220703125 +79967 0.091552734375 +79968 0.23602294921875 +79969 0.342987060546875 +79970 0.39520263671875 +79971 0.389373779296875 +79972 0.324249267578125 +79973 0.224090576171875 +79974 0.124267578125 +79975 0.037078857421875 +79976 -0.010101318359375 +79977 -0.019439697265625 +79978 -0.022796630859375 +79979 -0.001556396484375 +79980 0.056304931640625 +79981 0.106719970703125 +79982 0.096893310546875 +79983 0.042694091796875 +79984 -0.018035888671875 +79985 -0.07586669921875 +79986 -0.11944580078125 +79987 -0.15972900390625 +79988 -0.202606201171875 +79989 -0.24859619140625 +79990 -0.30517578125 +79991 -0.36212158203125 +79992 -0.39141845703125 +79993 -0.35528564453125 +79994 -0.249969482421875 +79995 -0.092864990234375 +79996 0.08905029296875 +79997 0.2352294921875 +79998 0.318817138671875 +79999 0.358642578125 +80000 0.347747802734375 +80001 0.28564453125 +80002 0.223175048828125 +80003 0.196746826171875 +80004 0.179840087890625 +80005 0.155548095703125 +80006 0.151214599609375 +80007 0.156951904296875 +80008 0.13177490234375 +80009 0.100799560546875 +80010 0.087127685546875 +80011 0.05487060546875 +80012 -0.009002685546875 +80013 -0.10400390625 +80014 -0.229400634765625 +80015 -0.35552978515625 +80016 -0.441925048828125 +80017 -0.473846435546875 +80018 -0.464813232421875 +80019 -0.419097900390625 +80020 -0.334320068359375 +80021 -0.227935791015625 +80022 -0.12347412109375 +80023 -0.02764892578125 +80024 0.077667236328125 +80025 0.2132568359375 +80026 0.38885498046875 +80027 0.582794189453125 +80028 0.734039306640625 +80029 0.800140380859375 +80030 0.7783203125 +80031 0.6651611328125 +80032 0.45965576171875 +80033 0.199188232421875 +80034 -0.050689697265625 +80035 -0.23297119140625 +80036 -0.33013916015625 +80037 -0.368408203125 +80038 -0.378936767578125 +80039 -0.376983642578125 +80040 -0.37969970703125 +80041 -0.391510009765625 +80042 -0.385345458984375 +80043 -0.3419189453125 +80044 -0.28289794921875 +80045 -0.251617431640625 +80046 -0.266143798828125 +80047 -0.273345947265625 +80048 -0.216796875 +80049 -0.128265380859375 +80050 -0.068145751953125 +80051 -0.0430908203125 +80052 -0.024444580078125 +80053 0.020721435546875 +80054 0.124481201171875 +80055 0.25787353515625 +80056 0.379119873046875 +80057 0.47991943359375 +80058 0.5281982421875 +80059 0.511138916015625 +80060 0.456207275390625 +80061 0.407470703125 +80062 0.383758544921875 +80063 0.35687255859375 +80064 0.31182861328125 +80065 0.250885009765625 +80066 0.1654052734375 +80067 0.035247802734375 +80068 -0.142059326171875 +80069 -0.33563232421875 +80070 -0.5345458984375 +80071 -0.72186279296875 +80072 -0.836669921875 +80073 -0.8326416015625 +80074 -0.7296142578125 +80075 -0.582550048828125 +80076 -0.440093994140625 +80077 -0.324310302734375 +80078 -0.20147705078125 +80079 -0.044647216796875 +80080 0.103973388671875 +80081 0.202392578125 +80082 0.264495849609375 +80083 0.338897705078125 +80084 0.443817138671875 +80085 0.545074462890625 +80086 0.6173095703125 +80087 0.6524658203125 +80088 0.66339111328125 +80089 0.6561279296875 +80090 0.606781005859375 +80091 0.501190185546875 +80092 0.352783203125 +80093 0.176544189453125 +80094 -0.034820556640625 +80095 -0.258209228515625 +80096 -0.44244384765625 +80097 -0.5753173828125 +80098 -0.65203857421875 +80099 -0.641632080078125 +80100 -0.562164306640625 +80101 -0.458038330078125 +80102 -0.350555419921875 +80103 -0.260528564453125 +80104 -0.192108154296875 +80105 -0.141937255859375 +80106 -0.1021728515625 +80107 -0.062896728515625 +80108 -0.011932373046875 +80109 0.062835693359375 +80110 0.148712158203125 +80111 0.241729736328125 +80112 0.34912109375 +80113 0.457305908203125 +80114 0.54388427734375 +80115 0.5728759765625 +80116 0.506591796875 +80117 0.351226806640625 +80118 0.146514892578125 +80119 -0.05523681640625 +80120 -0.21624755859375 +80121 -0.334930419921875 +80122 -0.402984619140625 +80123 -0.4412841796875 +80124 -0.49578857421875 +80125 -0.5601806640625 +80126 -0.600738525390625 +80127 -0.584228515625 +80128 -0.47930908203125 +80129 -0.27935791015625 +80130 -0.0089111328125 +80131 0.268798828125 +80132 0.482818603515625 +80133 0.60369873046875 +80134 0.650421142578125 +80135 0.66400146484375 +80136 0.6414794921875 +80137 0.572540283203125 +80138 0.498138427734375 +80139 0.439453125 +80140 0.375518798828125 +80141 0.274505615234375 +80142 0.1087646484375 +80143 -0.099395751953125 +80144 -0.3182373046875 +80145 -0.5489501953125 +80146 -0.7738037109375 +80147 -0.86383056640625 +80148 -0.870391845703125 +80149 -0.86895751953125 +80150 -0.861053466796875 +80151 -0.765869140625 +80152 -0.5301513671875 +80153 -0.214691162109375 +80154 0.137359619140625 +80155 0.474822998046875 +80156 0.76239013671875 +80157 0.867462158203125 +80158 0.870361328125 +80159 0.86480712890625 +80160 0.831817626953125 +80161 0.677581787109375 +80162 0.495880126953125 +80163 0.30767822265625 +80164 0.116180419921875 +80165 -0.110748291015625 +80166 -0.381805419921875 +80167 -0.6572265625 +80168 -0.857421875 +80169 -0.870391845703125 +80170 -0.870391845703125 +80171 -0.86444091796875 +80172 -0.85723876953125 +80173 -0.790008544921875 +80174 -0.62847900390625 +80175 -0.3956298828125 +80176 -0.126708984375 +80177 0.150115966796875 +80178 0.424041748046875 +80179 0.670623779296875 +80180 0.854522705078125 +80181 0.866485595703125 +80182 0.86920166015625 +80183 0.8653564453125 +80184 0.857147216796875 +80185 0.766845703125 +80186 0.628509521484375 +80187 0.462127685546875 +80188 0.297210693359375 +80189 0.14862060546875 +80190 -0.00537109375 +80191 -0.15753173828125 +80192 -0.31304931640625 +80193 -0.48876953125 +80194 -0.6416015625 +80195 -0.751373291015625 +80196 -0.84619140625 +80197 -0.861297607421875 +80198 -0.863250732421875 +80199 -0.856597900390625 +80200 -0.7498779296875 +80201 -0.624542236328125 +80202 -0.47808837890625 +80203 -0.253387451171875 +80204 0.003692626953125 +80205 0.2257080078125 +80206 0.427154541015625 +80207 0.643218994140625 +80208 0.855926513671875 +80209 0.870361328125 +80210 0.870361328125 +80211 0.862762451171875 +80212 0.79669189453125 +80213 0.595794677734375 +80214 0.362152099609375 +80215 0.1270751953125 +80216 -0.086944580078125 +80217 -0.2784423828125 +80218 -0.484832763671875 +80219 -0.729583740234375 +80220 -0.86688232421875 +80221 -0.870391845703125 +80222 -0.86859130859375 +80223 -0.86279296875 +80224 -0.817962646484375 +80225 -0.6116943359375 +80226 -0.3128662109375 +80227 0.039398193359375 +80228 0.422821044921875 +80229 0.805145263671875 +80230 0.870361328125 +80231 0.870361328125 +80232 0.860015869140625 +80233 0.727935791015625 +80234 0.48114013671875 +80235 0.2059326171875 +80236 -0.06103515625 +80237 -0.29913330078125 +80238 -0.516204833984375 +80239 -0.7252197265625 +80240 -0.85980224609375 +80241 -0.870391845703125 +80242 -0.870391845703125 +80243 -0.858062744140625 +80244 -0.673004150390625 +80245 -0.42694091796875 +80246 -0.2100830078125 +80247 -0.0362548828125 +80248 0.10943603515625 +80249 0.23516845703125 +80250 0.373687744140625 +80251 0.517791748046875 +80252 0.602783203125 +80253 0.635711669921875 +80254 0.655181884765625 +80255 0.65948486328125 +80256 0.651275634765625 +80257 0.61846923828125 +80258 0.53753662109375 +80259 0.404144287109375 +80260 0.22186279296875 +80261 0.003997802734375 +80262 -0.22100830078125 +80263 -0.42449951171875 +80264 -0.579833984375 +80265 -0.641876220703125 +80266 -0.6177978515625 +80267 -0.575531005859375 +80268 -0.526336669921875 +80269 -0.42645263671875 +80270 -0.2581787109375 +80271 -0.068695068359375 +80272 0.09222412109375 +80273 0.232147216796875 +80274 0.3509521484375 +80275 0.410064697265625 +80276 0.372955322265625 +80277 0.2554931640625 +80278 0.10711669921875 +80279 -0.052886962890625 +80280 -0.186279296875 +80281 -0.23291015625 +80282 -0.209442138671875 +80283 -0.174163818359375 +80284 -0.126739501953125 +80285 -0.048126220703125 +80286 0.0426025390625 +80287 0.10748291015625 +80288 0.1409912109375 +80289 0.19708251953125 +80290 0.273651123046875 +80291 0.31768798828125 +80292 0.341094970703125 +80293 0.368011474609375 +80294 0.37249755859375 +80295 0.30072021484375 +80296 0.1517333984375 +80297 -0.01470947265625 +80298 -0.1883544921875 +80299 -0.372711181640625 +80300 -0.51397705078125 +80301 -0.57177734375 +80302 -0.53948974609375 +80303 -0.43511962890625 +80304 -0.2962646484375 +80305 -0.161102294921875 +80306 -0.0435791015625 +80307 0.060394287109375 +80308 0.13665771484375 +80309 0.170135498046875 +80310 0.16552734375 +80311 0.15728759765625 +80312 0.150787353515625 +80313 0.12200927734375 +80314 0.080108642578125 +80315 0.05126953125 +80316 0.062896728515625 +80317 0.09271240234375 +80318 0.092987060546875 +80319 0.07855224609375 +80320 0.06427001953125 +80321 0.0347900390625 +80322 -0.01171875 +80323 -0.056060791015625 +80324 -0.055511474609375 +80325 -0.010467529296875 +80326 0.02508544921875 +80327 0.025665283203125 +80328 0.017333984375 +80329 0.00189208984375 +80330 -0.03173828125 +80331 -0.071502685546875 +80332 -0.13543701171875 +80333 -0.219970703125 +80334 -0.300506591796875 +80335 -0.376312255859375 +80336 -0.416107177734375 +80337 -0.371124267578125 +80338 -0.242279052734375 +80339 -0.069732666015625 +80340 0.125640869140625 +80341 0.31268310546875 +80342 0.45501708984375 +80343 0.554779052734375 +80344 0.61065673828125 +80345 0.610931396484375 +80346 0.531463623046875 +80347 0.3883056640625 +80348 0.23468017578125 +80349 0.095245361328125 +80350 -0.00396728515625 +80351 -0.04852294921875 +80352 -0.055145263671875 +80353 -0.0758056640625 +80354 -0.138702392578125 +80355 -0.209197998046875 +80356 -0.289031982421875 +80357 -0.37884521484375 +80358 -0.456329345703125 +80359 -0.51641845703125 +80360 -0.519287109375 +80361 -0.458251953125 +80362 -0.384796142578125 +80363 -0.323699951171875 +80364 -0.269287109375 +80365 -0.1951904296875 +80366 -0.100006103515625 +80367 -0.01055908203125 +80368 0.1033935546875 +80369 0.24908447265625 +80370 0.373199462890625 +80371 0.45806884765625 +80372 0.511474609375 +80373 0.565399169921875 +80374 0.61138916015625 +80375 0.5897216796875 +80376 0.4906005859375 +80377 0.33148193359375 +80378 0.147796630859375 +80379 -0.01873779296875 +80380 -0.140289306640625 +80381 -0.191986083984375 +80382 -0.184295654296875 +80383 -0.161834716796875 +80384 -0.166595458984375 +80385 -0.19390869140625 +80386 -0.22442626953125 +80387 -0.279754638671875 +80388 -0.3389892578125 +80389 -0.3543701171875 +80390 -0.348175048828125 +80391 -0.32598876953125 +80392 -0.2581787109375 +80393 -0.139801025390625 +80394 0.014617919921875 +80395 0.144378662109375 +80396 0.221038818359375 +80397 0.27069091796875 +80398 0.294036865234375 +80399 0.311767578125 +80400 0.339141845703125 +80401 0.360260009765625 +80402 0.360504150390625 +80403 0.308380126953125 +80404 0.18170166015625 +80405 0.0047607421875 +80406 -0.17559814453125 +80407 -0.3143310546875 +80408 -0.36785888671875 +80409 -0.36248779296875 +80410 -0.343536376953125 +80411 -0.3018798828125 +80412 -0.231414794921875 +80413 -0.117645263671875 +80414 0.007049560546875 +80415 0.087982177734375 +80416 0.13946533203125 +80417 0.17425537109375 +80418 0.188201904296875 +80419 0.171234130859375 +80420 0.118438720703125 +80421 0.05706787109375 +80422 -0.010711669921875 +80423 -0.0914306640625 +80424 -0.162322998046875 +80425 -0.194549560546875 +80426 -0.1492919921875 +80427 -0.02166748046875 +80428 0.124053955078125 +80429 0.211151123046875 +80430 0.240447998046875 +80431 0.242218017578125 +80432 0.2257080078125 +80433 0.194366455078125 +80434 0.115509033203125 +80435 0.0128173828125 +80436 -0.053802490234375 +80437 -0.110626220703125 +80438 -0.199493408203125 +80439 -0.29437255859375 +80440 -0.33221435546875 +80441 -0.27972412109375 +80442 -0.185333251953125 +80443 -0.128204345703125 +80444 -0.115692138671875 +80445 -0.116455078125 +80446 -0.105926513671875 +80447 -0.053955078125 +80448 0.048797607421875 +80449 0.157318115234375 +80450 0.212005615234375 +80451 0.218475341796875 +80452 0.23724365234375 +80453 0.30535888671875 +80454 0.38128662109375 +80455 0.404449462890625 +80456 0.3944091796875 +80457 0.3885498046875 +80458 0.362640380859375 +80459 0.27362060546875 +80460 0.11712646484375 +80461 -0.054901123046875 +80462 -0.19085693359375 +80463 -0.28570556640625 +80464 -0.339263916015625 +80465 -0.3775634765625 +80466 -0.445709228515625 +80467 -0.535064697265625 +80468 -0.629058837890625 +80469 -0.697601318359375 +80470 -0.70391845703125 +80471 -0.6424560546875 +80472 -0.491241455078125 +80473 -0.265716552734375 +80474 -0.023712158203125 +80475 0.201751708984375 +80476 0.375823974609375 +80477 0.485076904296875 +80478 0.56884765625 +80479 0.634765625 +80480 0.63763427734375 +80481 0.5660400390625 +80482 0.4720458984375 +80483 0.40692138671875 +80484 0.3778076171875 +80485 0.376953125 +80486 0.371978759765625 +80487 0.313140869140625 +80488 0.184417724609375 +80489 0.011199951171875 +80490 -0.171051025390625 +80491 -0.33740234375 +80492 -0.47198486328125 +80493 -0.560394287109375 +80494 -0.58056640625 +80495 -0.54754638671875 +80496 -0.508575439453125 +80497 -0.459503173828125 +80498 -0.394378662109375 +80499 -0.35260009765625 +80500 -0.31170654296875 +80501 -0.197418212890625 +80502 -0.007965087890625 +80503 0.207489013671875 +80504 0.409210205078125 +80505 0.57208251953125 +80506 0.66595458984375 +80507 0.65875244140625 +80508 0.56744384765625 +80509 0.431396484375 +80510 0.29443359375 +80511 0.182464599609375 +80512 0.06365966796875 +80513 -0.075958251953125 +80514 -0.189422607421875 +80515 -0.271942138671875 +80516 -0.342529296875 +80517 -0.364166259765625 +80518 -0.327239990234375 +80519 -0.2769775390625 +80520 -0.253692626953125 +80521 -0.24365234375 +80522 -0.1983642578125 +80523 -0.116241455078125 +80524 -0.036834716796875 +80525 0.034881591796875 +80526 0.09124755859375 +80527 0.10888671875 +80528 0.125518798828125 +80529 0.15771484375 +80530 0.17828369140625 +80531 0.17108154296875 +80532 0.129974365234375 +80533 0.082427978515625 +80534 0.027679443359375 +80535 -0.065643310546875 +80536 -0.15936279296875 +80537 -0.21307373046875 +80538 -0.234649658203125 +80539 -0.2001953125 +80540 -0.119171142578125 +80541 -0.024749755859375 +80542 0.085784912109375 +80543 0.178131103515625 +80544 0.215576171875 +80545 0.211456298828125 +80546 0.17523193359375 +80547 0.128753662109375 +80548 0.1019287109375 +80549 0.0743408203125 +80550 0.04327392578125 +80551 0.038177490234375 +80552 0.076263427734375 +80553 0.14105224609375 +80554 0.186431884765625 +80555 0.188812255859375 +80556 0.1390380859375 +80557 0.041778564453125 +80558 -0.079437255859375 +80559 -0.219390869140625 +80560 -0.367828369140625 +80561 -0.494873046875 +80562 -0.556243896484375 +80563 -0.508697509765625 +80564 -0.3756103515625 +80565 -0.218902587890625 +80566 -0.063751220703125 +80567 0.091552734375 +80568 0.23602294921875 +80569 0.342987060546875 +80570 0.39520263671875 +80571 0.389373779296875 +80572 0.324249267578125 +80573 0.224090576171875 +80574 0.124267578125 +80575 0.037078857421875 +80576 -0.010101318359375 +80577 -0.019439697265625 +80578 -0.022796630859375 +80579 -0.001556396484375 +80580 0.056304931640625 +80581 0.106719970703125 +80582 0.096893310546875 +80583 0.042694091796875 +80584 -0.018035888671875 +80585 -0.07586669921875 +80586 -0.11944580078125 +80587 -0.15972900390625 +80588 -0.202606201171875 +80589 -0.24859619140625 +80590 -0.30517578125 +80591 -0.36212158203125 +80592 -0.39141845703125 +80593 -0.35528564453125 +80594 -0.249969482421875 +80595 -0.092864990234375 +80596 0.08905029296875 +80597 0.2352294921875 +80598 0.318817138671875 +80599 0.358642578125 +80600 0.347747802734375 +80601 0.28564453125 +80602 0.223175048828125 +80603 0.196746826171875 +80604 0.179840087890625 +80605 0.155548095703125 +80606 0.151214599609375 +80607 0.156951904296875 +80608 0.13177490234375 +80609 0.100799560546875 +80610 0.087127685546875 +80611 0.05487060546875 +80612 -0.009002685546875 +80613 -0.10400390625 +80614 -0.229400634765625 +80615 -0.35552978515625 +80616 -0.441925048828125 +80617 -0.473846435546875 +80618 -0.464813232421875 +80619 -0.419097900390625 +80620 -0.334320068359375 +80621 -0.227935791015625 +80622 -0.12347412109375 +80623 -0.02764892578125 +80624 0.077667236328125 +80625 0.2132568359375 +80626 0.38885498046875 +80627 0.582794189453125 +80628 0.734039306640625 +80629 0.800140380859375 +80630 0.7783203125 +80631 0.6651611328125 +80632 0.45965576171875 +80633 0.199188232421875 +80634 -0.050689697265625 +80635 -0.23297119140625 +80636 -0.33013916015625 +80637 -0.368408203125 +80638 -0.378936767578125 +80639 -0.376983642578125 +80640 -0.37969970703125 +80641 -0.391510009765625 +80642 -0.385345458984375 +80643 -0.3419189453125 +80644 -0.28289794921875 +80645 -0.251617431640625 +80646 -0.266143798828125 +80647 -0.273345947265625 +80648 -0.216796875 +80649 -0.128265380859375 +80650 -0.068145751953125 +80651 -0.0430908203125 +80652 -0.024444580078125 +80653 0.020721435546875 +80654 0.124481201171875 +80655 0.25787353515625 +80656 0.379119873046875 +80657 0.47991943359375 +80658 0.5281982421875 +80659 0.511138916015625 +80660 0.456207275390625 +80661 0.407470703125 +80662 0.383758544921875 +80663 0.35687255859375 +80664 0.31182861328125 +80665 0.250885009765625 +80666 0.1654052734375 +80667 0.035247802734375 +80668 -0.142059326171875 +80669 -0.33563232421875 +80670 -0.5345458984375 +80671 -0.72186279296875 +80672 -0.836669921875 +80673 -0.8326416015625 +80674 -0.7296142578125 +80675 -0.582550048828125 +80676 -0.440093994140625 +80677 -0.324310302734375 +80678 -0.20147705078125 +80679 -0.044647216796875 +80680 0.103973388671875 +80681 0.202392578125 +80682 0.264495849609375 +80683 0.338897705078125 +80684 0.443817138671875 +80685 0.545074462890625 +80686 0.6173095703125 +80687 0.6524658203125 +80688 0.66339111328125 +80689 0.6561279296875 +80690 0.606781005859375 +80691 0.501190185546875 +80692 0.352783203125 +80693 0.176544189453125 +80694 -0.034820556640625 +80695 -0.258209228515625 +80696 -0.44244384765625 +80697 -0.5753173828125 +80698 -0.65203857421875 +80699 -0.641632080078125 +80700 -0.562164306640625 +80701 -0.458038330078125 +80702 -0.350555419921875 +80703 -0.260528564453125 +80704 -0.192108154296875 +80705 -0.141937255859375 +80706 -0.1021728515625 +80707 -0.062896728515625 +80708 -0.011932373046875 +80709 0.062835693359375 +80710 0.148712158203125 +80711 0.241729736328125 +80712 0.34912109375 +80713 0.457305908203125 +80714 0.54388427734375 +80715 0.5728759765625 +80716 0.506591796875 +80717 0.351226806640625 +80718 0.146514892578125 +80719 -0.05523681640625 +80720 -0.21624755859375 +80721 -0.334930419921875 +80722 -0.402984619140625 +80723 -0.4412841796875 +80724 -0.49578857421875 +80725 -0.5601806640625 +80726 -0.600738525390625 +80727 -0.584228515625 +80728 -0.47930908203125 +80729 -0.27935791015625 +80730 -0.0089111328125 +80731 0.268798828125 +80732 0.482818603515625 +80733 0.60369873046875 +80734 0.650421142578125 +80735 0.66400146484375 +80736 0.6414794921875 +80737 0.572540283203125 +80738 0.498138427734375 +80739 0.439453125 +80740 0.375518798828125 +80741 0.274505615234375 +80742 0.1087646484375 +80743 -0.099395751953125 +80744 -0.3182373046875 +80745 -0.5489501953125 +80746 -0.7738037109375 +80747 -0.86383056640625 +80748 -0.870391845703125 +80749 -0.86895751953125 +80750 -0.861053466796875 +80751 -0.765869140625 +80752 -0.5301513671875 +80753 -0.214691162109375 +80754 0.137359619140625 +80755 0.474822998046875 +80756 0.76239013671875 +80757 0.867462158203125 +80758 0.870361328125 +80759 0.86480712890625 +80760 0.831817626953125 +80761 0.677581787109375 +80762 0.495880126953125 +80763 0.30767822265625 +80764 0.116180419921875 +80765 -0.110748291015625 +80766 -0.381805419921875 +80767 -0.6572265625 +80768 -0.857421875 +80769 -0.870391845703125 +80770 -0.870391845703125 +80771 -0.86444091796875 +80772 -0.85723876953125 +80773 -0.790008544921875 +80774 -0.62847900390625 +80775 -0.3956298828125 +80776 -0.126708984375 +80777 0.150115966796875 +80778 0.424041748046875 +80779 0.670623779296875 +80780 0.854522705078125 +80781 0.866485595703125 +80782 0.86920166015625 +80783 0.8653564453125 +80784 0.857147216796875 +80785 0.766845703125 +80786 0.628509521484375 +80787 0.462127685546875 +80788 0.297210693359375 +80789 0.14862060546875 +80790 -0.00537109375 +80791 -0.15753173828125 +80792 -0.31304931640625 +80793 -0.48876953125 +80794 -0.6416015625 +80795 -0.751373291015625 +80796 -0.84619140625 +80797 -0.861297607421875 +80798 -0.863250732421875 +80799 -0.856597900390625 +80800 -0.7498779296875 +80801 -0.624542236328125 +80802 -0.47808837890625 +80803 -0.253387451171875 +80804 0.003692626953125 +80805 0.2257080078125 +80806 0.427154541015625 +80807 0.643218994140625 +80808 0.855926513671875 +80809 0.870361328125 +80810 0.870361328125 +80811 0.862762451171875 +80812 0.79669189453125 +80813 0.595794677734375 +80814 0.362152099609375 +80815 0.1270751953125 +80816 -0.086944580078125 +80817 -0.2784423828125 +80818 -0.484832763671875 +80819 -0.729583740234375 +80820 -0.86688232421875 +80821 -0.870391845703125 +80822 -0.86859130859375 +80823 -0.86279296875 +80824 -0.817962646484375 +80825 -0.6116943359375 +80826 -0.3128662109375 +80827 0.039398193359375 +80828 0.422821044921875 +80829 0.805145263671875 +80830 0.870361328125 +80831 0.870361328125 +80832 0.860015869140625 +80833 0.727935791015625 +80834 0.48114013671875 +80835 0.2059326171875 +80836 -0.06103515625 +80837 -0.29913330078125 +80838 -0.516204833984375 +80839 -0.7252197265625 +80840 -0.85980224609375 +80841 -0.870391845703125 +80842 -0.870391845703125 +80843 -0.858062744140625 +80844 -0.673004150390625 +80845 -0.42694091796875 +80846 -0.2100830078125 +80847 -0.0362548828125 +80848 0.10943603515625 +80849 0.23516845703125 +80850 0.373687744140625 +80851 0.517791748046875 +80852 0.602783203125 +80853 0.635711669921875 +80854 0.655181884765625 +80855 0.65948486328125 +80856 0.651275634765625 +80857 0.61846923828125 +80858 0.53753662109375 +80859 0.404144287109375 +80860 0.22186279296875 +80861 0.003997802734375 +80862 -0.22100830078125 +80863 -0.42449951171875 +80864 -0.579833984375 +80865 -0.641876220703125 +80866 -0.6177978515625 +80867 -0.575531005859375 +80868 -0.526336669921875 +80869 -0.42645263671875 +80870 -0.2581787109375 +80871 -0.068695068359375 +80872 0.09222412109375 +80873 0.232147216796875 +80874 0.3509521484375 +80875 0.410064697265625 +80876 0.372955322265625 +80877 0.2554931640625 +80878 0.10711669921875 +80879 -0.052886962890625 +80880 -0.186279296875 +80881 -0.23291015625 +80882 -0.209442138671875 +80883 -0.174163818359375 +80884 -0.126739501953125 +80885 -0.048126220703125 +80886 0.0426025390625 +80887 0.10748291015625 +80888 0.1409912109375 +80889 0.19708251953125 +80890 0.273651123046875 +80891 0.31768798828125 +80892 0.341094970703125 +80893 0.368011474609375 +80894 0.37249755859375 +80895 0.30072021484375 +80896 0.1517333984375 +80897 -0.01470947265625 +80898 -0.1883544921875 +80899 -0.372711181640625 +80900 -0.51397705078125 +80901 -0.57177734375 +80902 -0.53948974609375 +80903 -0.43511962890625 +80904 -0.2962646484375 +80905 -0.161102294921875 +80906 -0.0435791015625 +80907 0.060394287109375 +80908 0.13665771484375 +80909 0.170135498046875 +80910 0.16552734375 +80911 0.15728759765625 +80912 0.150787353515625 +80913 0.12200927734375 +80914 0.080108642578125 +80915 0.05126953125 +80916 0.062896728515625 +80917 0.09271240234375 +80918 0.092987060546875 +80919 0.07855224609375 +80920 0.06427001953125 +80921 0.0347900390625 +80922 -0.01171875 +80923 -0.056060791015625 +80924 -0.055511474609375 +80925 -0.010467529296875 +80926 0.02508544921875 +80927 0.025665283203125 +80928 0.017333984375 +80929 0.00189208984375 +80930 -0.03173828125 +80931 -0.071502685546875 +80932 -0.13543701171875 +80933 -0.219970703125 +80934 -0.300506591796875 +80935 -0.376312255859375 +80936 -0.416107177734375 +80937 -0.371124267578125 +80938 -0.242279052734375 +80939 -0.069732666015625 +80940 0.125640869140625 +80941 0.31268310546875 +80942 0.45501708984375 +80943 0.554779052734375 +80944 0.61065673828125 +80945 0.610931396484375 +80946 0.531463623046875 +80947 0.3883056640625 +80948 0.23468017578125 +80949 0.095245361328125 +80950 -0.00396728515625 +80951 -0.04852294921875 +80952 -0.055145263671875 +80953 -0.0758056640625 +80954 -0.138702392578125 +80955 -0.209197998046875 +80956 -0.289031982421875 +80957 -0.37884521484375 +80958 -0.456329345703125 +80959 -0.51641845703125 +80960 -0.519287109375 +80961 -0.458251953125 +80962 -0.384796142578125 +80963 -0.323699951171875 +80964 -0.269287109375 +80965 -0.1951904296875 +80966 -0.100006103515625 +80967 -0.01055908203125 +80968 0.1033935546875 +80969 0.24908447265625 +80970 0.373199462890625 +80971 0.45806884765625 +80972 0.511474609375 +80973 0.565399169921875 +80974 0.61138916015625 +80975 0.5897216796875 +80976 0.4906005859375 +80977 0.33148193359375 +80978 0.147796630859375 +80979 -0.01873779296875 +80980 -0.140289306640625 +80981 -0.191986083984375 +80982 -0.184295654296875 +80983 -0.161834716796875 +80984 -0.166595458984375 +80985 -0.19390869140625 +80986 -0.22442626953125 +80987 -0.279754638671875 +80988 -0.3389892578125 +80989 -0.3543701171875 +80990 -0.348175048828125 +80991 -0.32598876953125 +80992 -0.2581787109375 +80993 -0.139801025390625 +80994 0.014617919921875 +80995 0.144378662109375 +80996 0.221038818359375 +80997 0.27069091796875 +80998 0.294036865234375 +80999 0.311767578125 +81000 0.339141845703125 +81001 0.360260009765625 +81002 0.360504150390625 +81003 0.308380126953125 +81004 0.18170166015625 +81005 0.0047607421875 +81006 -0.17559814453125 +81007 -0.3143310546875 +81008 -0.36785888671875 +81009 -0.36248779296875 +81010 -0.343536376953125 +81011 -0.3018798828125 +81012 -0.231414794921875 +81013 -0.117645263671875 +81014 0.007049560546875 +81015 0.087982177734375 +81016 0.13946533203125 +81017 0.17425537109375 +81018 0.188201904296875 +81019 0.171234130859375 +81020 0.118438720703125 +81021 0.05706787109375 +81022 -0.010711669921875 +81023 -0.0914306640625 +81024 -0.162322998046875 +81025 -0.194549560546875 +81026 -0.1492919921875 +81027 -0.02166748046875 +81028 0.124053955078125 +81029 0.211151123046875 +81030 0.240447998046875 +81031 0.242218017578125 +81032 0.2257080078125 +81033 0.194366455078125 +81034 0.115509033203125 +81035 0.0128173828125 +81036 -0.053802490234375 +81037 -0.110626220703125 +81038 -0.199493408203125 +81039 -0.29437255859375 +81040 -0.33221435546875 +81041 -0.27972412109375 +81042 -0.185333251953125 +81043 -0.128204345703125 +81044 -0.115692138671875 +81045 -0.116455078125 +81046 -0.105926513671875 +81047 -0.053955078125 +81048 0.048797607421875 +81049 0.157318115234375 +81050 0.212005615234375 +81051 0.218475341796875 +81052 0.23724365234375 +81053 0.30535888671875 +81054 0.38128662109375 +81055 0.404449462890625 +81056 0.3944091796875 +81057 0.3885498046875 +81058 0.362640380859375 +81059 0.27362060546875 +81060 0.11712646484375 +81061 -0.054901123046875 +81062 -0.19085693359375 +81063 -0.28570556640625 +81064 -0.339263916015625 +81065 -0.3775634765625 +81066 -0.445709228515625 +81067 -0.535064697265625 +81068 -0.629058837890625 +81069 -0.697601318359375 +81070 -0.70391845703125 +81071 -0.6424560546875 +81072 -0.491241455078125 +81073 -0.265716552734375 +81074 -0.023712158203125 +81075 0.201751708984375 +81076 0.375823974609375 +81077 0.485076904296875 +81078 0.56884765625 +81079 0.634765625 +81080 0.63763427734375 +81081 0.5660400390625 +81082 0.4720458984375 +81083 0.40692138671875 +81084 0.3778076171875 +81085 0.376953125 +81086 0.371978759765625 +81087 0.313140869140625 +81088 0.184417724609375 +81089 0.011199951171875 +81090 -0.171051025390625 +81091 -0.33740234375 +81092 -0.47198486328125 +81093 -0.560394287109375 +81094 -0.58056640625 +81095 -0.54754638671875 +81096 -0.508575439453125 +81097 -0.459503173828125 +81098 -0.394378662109375 +81099 -0.35260009765625 +81100 -0.31170654296875 +81101 -0.197418212890625 +81102 -0.007965087890625 +81103 0.207489013671875 +81104 0.409210205078125 +81105 0.57208251953125 +81106 0.66595458984375 +81107 0.65875244140625 +81108 0.56744384765625 +81109 0.431396484375 +81110 0.29443359375 +81111 0.182464599609375 +81112 0.06365966796875 +81113 -0.075958251953125 +81114 -0.189422607421875 +81115 -0.271942138671875 +81116 -0.342529296875 +81117 -0.364166259765625 +81118 -0.327239990234375 +81119 -0.2769775390625 +81120 -0.253692626953125 +81121 -0.24365234375 +81122 -0.1983642578125 +81123 -0.116241455078125 +81124 -0.036834716796875 +81125 0.034881591796875 +81126 0.09124755859375 +81127 0.10888671875 +81128 0.125518798828125 +81129 0.15771484375 +81130 0.17828369140625 +81131 0.17108154296875 +81132 0.129974365234375 +81133 0.082427978515625 +81134 0.027679443359375 +81135 -0.065643310546875 +81136 -0.15936279296875 +81137 -0.21307373046875 +81138 -0.234649658203125 +81139 -0.2001953125 +81140 -0.119171142578125 +81141 -0.024749755859375 +81142 0.085784912109375 +81143 0.178131103515625 +81144 0.215576171875 +81145 0.211456298828125 +81146 0.17523193359375 +81147 0.128753662109375 +81148 0.1019287109375 +81149 0.0743408203125 +81150 0.04327392578125 +81151 0.038177490234375 +81152 0.076263427734375 +81153 0.14105224609375 +81154 0.186431884765625 +81155 0.188812255859375 +81156 0.1390380859375 +81157 0.041778564453125 +81158 -0.079437255859375 +81159 -0.219390869140625 +81160 -0.367828369140625 +81161 -0.494873046875 +81162 -0.556243896484375 +81163 -0.508697509765625 +81164 -0.3756103515625 +81165 -0.218902587890625 +81166 -0.063751220703125 +81167 0.091552734375 +81168 0.23602294921875 +81169 0.342987060546875 +81170 0.39520263671875 +81171 0.389373779296875 +81172 0.324249267578125 +81173 0.224090576171875 +81174 0.124267578125 +81175 0.037078857421875 +81176 -0.010101318359375 +81177 -0.019439697265625 +81178 -0.022796630859375 +81179 -0.001556396484375 +81180 0.056304931640625 +81181 0.106719970703125 +81182 0.096893310546875 +81183 0.042694091796875 +81184 -0.018035888671875 +81185 -0.07586669921875 +81186 -0.11944580078125 +81187 -0.15972900390625 +81188 -0.202606201171875 +81189 -0.24859619140625 +81190 -0.30517578125 +81191 -0.36212158203125 +81192 -0.39141845703125 +81193 -0.35528564453125 +81194 -0.249969482421875 +81195 -0.092864990234375 +81196 0.08905029296875 +81197 0.2352294921875 +81198 0.318817138671875 +81199 0.358642578125 +81200 0.347747802734375 +81201 0.28564453125 +81202 0.223175048828125 +81203 0.196746826171875 +81204 0.179840087890625 +81205 0.155548095703125 +81206 0.151214599609375 +81207 0.156951904296875 +81208 0.13177490234375 +81209 0.100799560546875 +81210 0.087127685546875 +81211 0.05487060546875 +81212 -0.009002685546875 +81213 -0.10400390625 +81214 -0.229400634765625 +81215 -0.35552978515625 +81216 -0.441925048828125 +81217 -0.473846435546875 +81218 -0.464813232421875 +81219 -0.419097900390625 +81220 -0.334320068359375 +81221 -0.227935791015625 +81222 -0.12347412109375 +81223 -0.02764892578125 +81224 0.077667236328125 +81225 0.2132568359375 +81226 0.38885498046875 +81227 0.582794189453125 +81228 0.734039306640625 +81229 0.800140380859375 +81230 0.7783203125 +81231 0.6651611328125 +81232 0.45965576171875 +81233 0.199188232421875 +81234 -0.050689697265625 +81235 -0.23297119140625 +81236 -0.33013916015625 +81237 -0.368408203125 +81238 -0.378936767578125 +81239 -0.376983642578125 +81240 -0.37969970703125 +81241 -0.391510009765625 +81242 -0.385345458984375 +81243 -0.3419189453125 +81244 -0.28289794921875 +81245 -0.251617431640625 +81246 -0.266143798828125 +81247 -0.273345947265625 +81248 -0.216796875 +81249 -0.128265380859375 +81250 -0.068145751953125 +81251 -0.0430908203125 +81252 -0.024444580078125 +81253 0.020721435546875 +81254 0.124481201171875 +81255 0.25787353515625 +81256 0.379119873046875 +81257 0.47991943359375 +81258 0.5281982421875 +81259 0.511138916015625 +81260 0.456207275390625 +81261 0.407470703125 +81262 0.383758544921875 +81263 0.35687255859375 +81264 0.31182861328125 +81265 0.250885009765625 +81266 0.1654052734375 +81267 0.035247802734375 +81268 -0.142059326171875 +81269 -0.33563232421875 +81270 -0.5345458984375 +81271 -0.72186279296875 +81272 -0.836669921875 +81273 -0.8326416015625 +81274 -0.7296142578125 +81275 -0.582550048828125 +81276 -0.440093994140625 +81277 -0.324310302734375 +81278 -0.20147705078125 +81279 -0.044647216796875 +81280 0.103973388671875 +81281 0.202392578125 +81282 0.264495849609375 +81283 0.338897705078125 +81284 0.443817138671875 +81285 0.545074462890625 +81286 0.6173095703125 +81287 0.6524658203125 +81288 0.66339111328125 +81289 0.6561279296875 +81290 0.606781005859375 +81291 0.501190185546875 +81292 0.352783203125 +81293 0.176544189453125 +81294 -0.034820556640625 +81295 -0.258209228515625 +81296 -0.44244384765625 +81297 -0.5753173828125 +81298 -0.65203857421875 +81299 -0.641632080078125 +81300 -0.562164306640625 +81301 -0.458038330078125 +81302 -0.350555419921875 +81303 -0.260528564453125 +81304 -0.192108154296875 +81305 -0.141937255859375 +81306 -0.1021728515625 +81307 -0.062896728515625 +81308 -0.011932373046875 +81309 0.062835693359375 +81310 0.148712158203125 +81311 0.241729736328125 +81312 0.34912109375 +81313 0.457305908203125 +81314 0.54388427734375 +81315 0.5728759765625 +81316 0.506591796875 +81317 0.351226806640625 +81318 0.146514892578125 +81319 -0.05523681640625 +81320 -0.21624755859375 +81321 -0.334930419921875 +81322 -0.402984619140625 +81323 -0.4412841796875 +81324 -0.49578857421875 +81325 -0.5601806640625 +81326 -0.600738525390625 +81327 -0.584228515625 +81328 -0.47930908203125 +81329 -0.27935791015625 +81330 -0.0089111328125 +81331 0.268798828125 +81332 0.482818603515625 +81333 0.60369873046875 +81334 0.650421142578125 +81335 0.66400146484375 +81336 0.6414794921875 +81337 0.572540283203125 +81338 0.498138427734375 +81339 0.439453125 +81340 0.375518798828125 +81341 0.274505615234375 +81342 0.1087646484375 +81343 -0.099395751953125 +81344 -0.3182373046875 +81345 -0.5489501953125 +81346 -0.7738037109375 +81347 -0.86383056640625 +81348 -0.870391845703125 +81349 -0.86895751953125 +81350 -0.861053466796875 +81351 -0.765869140625 +81352 -0.5301513671875 +81353 -0.214691162109375 +81354 0.137359619140625 +81355 0.474822998046875 +81356 0.76239013671875 +81357 0.867462158203125 +81358 0.870361328125 +81359 0.86480712890625 +81360 0.831817626953125 +81361 0.677581787109375 +81362 0.495880126953125 +81363 0.30767822265625 +81364 0.116180419921875 +81365 -0.110748291015625 +81366 -0.381805419921875 +81367 -0.6572265625 +81368 -0.857421875 +81369 -0.870391845703125 +81370 -0.870391845703125 +81371 -0.86444091796875 +81372 -0.85723876953125 +81373 -0.790008544921875 +81374 -0.62847900390625 +81375 -0.3956298828125 +81376 -0.126708984375 +81377 0.150115966796875 +81378 0.424041748046875 +81379 0.670623779296875 +81380 0.854522705078125 +81381 0.866485595703125 +81382 0.86920166015625 +81383 0.8653564453125 +81384 0.857147216796875 +81385 0.766845703125 +81386 0.628509521484375 +81387 0.462127685546875 +81388 0.297210693359375 +81389 0.14862060546875 +81390 -0.00537109375 +81391 -0.15753173828125 +81392 -0.31304931640625 +81393 -0.48876953125 +81394 -0.6416015625 +81395 -0.751373291015625 +81396 -0.84619140625 +81397 -0.861297607421875 +81398 -0.863250732421875 +81399 -0.856597900390625 +81400 -0.7498779296875 +81401 -0.624542236328125 +81402 -0.47808837890625 +81403 -0.253387451171875 +81404 0.003692626953125 +81405 0.2257080078125 +81406 0.427154541015625 +81407 0.643218994140625 +81408 0.855926513671875 +81409 0.870361328125 +81410 0.870361328125 +81411 0.862762451171875 +81412 0.79669189453125 +81413 0.595794677734375 +81414 0.362152099609375 +81415 0.1270751953125 +81416 -0.086944580078125 +81417 -0.2784423828125 +81418 -0.484832763671875 +81419 -0.729583740234375 +81420 -0.86688232421875 +81421 -0.870391845703125 +81422 -0.86859130859375 +81423 -0.86279296875 +81424 -0.817962646484375 +81425 -0.6116943359375 +81426 -0.3128662109375 +81427 0.039398193359375 +81428 0.422821044921875 +81429 0.805145263671875 +81430 0.870361328125 +81431 0.870361328125 +81432 0.860015869140625 +81433 0.727935791015625 +81434 0.48114013671875 +81435 0.2059326171875 +81436 -0.06103515625 +81437 -0.29913330078125 +81438 -0.516204833984375 +81439 -0.7252197265625 +81440 -0.85980224609375 +81441 -0.870391845703125 +81442 -0.870391845703125 +81443 -0.858062744140625 +81444 -0.673004150390625 +81445 -0.42694091796875 +81446 -0.2100830078125 +81447 -0.0362548828125 +81448 0.10943603515625 +81449 0.23516845703125 +81450 0.373687744140625 +81451 0.517791748046875 +81452 0.602783203125 +81453 0.635711669921875 +81454 0.655181884765625 +81455 0.65948486328125 +81456 0.651275634765625 +81457 0.61846923828125 +81458 0.53753662109375 +81459 0.404144287109375 +81460 0.22186279296875 +81461 0.003997802734375 +81462 -0.22100830078125 +81463 -0.42449951171875 +81464 -0.579833984375 +81465 -0.641876220703125 +81466 -0.6177978515625 +81467 -0.575531005859375 +81468 -0.526336669921875 +81469 -0.42645263671875 +81470 -0.2581787109375 +81471 -0.068695068359375 +81472 0.09222412109375 +81473 0.232147216796875 +81474 0.3509521484375 +81475 0.410064697265625 +81476 0.372955322265625 +81477 0.2554931640625 +81478 0.10711669921875 +81479 -0.052886962890625 +81480 -0.186279296875 +81481 -0.23291015625 +81482 -0.209442138671875 +81483 -0.174163818359375 +81484 -0.126739501953125 +81485 -0.048126220703125 +81486 0.0426025390625 +81487 0.10748291015625 +81488 0.1409912109375 +81489 0.19708251953125 +81490 0.273651123046875 +81491 0.31768798828125 +81492 0.341094970703125 +81493 0.368011474609375 +81494 0.37249755859375 +81495 0.30072021484375 +81496 0.1517333984375 +81497 -0.01470947265625 +81498 -0.1883544921875 +81499 -0.372711181640625 +81500 -0.51397705078125 +81501 -0.57177734375 +81502 -0.53948974609375 +81503 -0.43511962890625 +81504 -0.2962646484375 +81505 -0.161102294921875 +81506 -0.0435791015625 +81507 0.060394287109375 +81508 0.13665771484375 +81509 0.170135498046875 +81510 0.16552734375 +81511 0.15728759765625 +81512 0.150787353515625 +81513 0.12200927734375 +81514 0.080108642578125 +81515 0.05126953125 +81516 0.062896728515625 +81517 0.09271240234375 +81518 0.092987060546875 +81519 0.07855224609375 +81520 0.06427001953125 +81521 0.0347900390625 +81522 -0.01171875 +81523 -0.056060791015625 +81524 -0.055511474609375 +81525 -0.010467529296875 +81526 0.02508544921875 +81527 0.025665283203125 +81528 0.017333984375 +81529 0.00189208984375 +81530 -0.03173828125 +81531 -0.071502685546875 +81532 -0.13543701171875 +81533 -0.219970703125 +81534 -0.300506591796875 +81535 -0.376312255859375 +81536 -0.416107177734375 +81537 -0.371124267578125 +81538 -0.242279052734375 +81539 -0.069732666015625 +81540 0.125640869140625 +81541 0.31268310546875 +81542 0.45501708984375 +81543 0.554779052734375 +81544 0.61065673828125 +81545 0.610931396484375 +81546 0.531463623046875 +81547 0.3883056640625 +81548 0.23468017578125 +81549 0.095245361328125 +81550 -0.00396728515625 +81551 -0.04852294921875 +81552 -0.055145263671875 +81553 -0.0758056640625 +81554 -0.138702392578125 +81555 -0.209197998046875 +81556 -0.289031982421875 +81557 -0.37884521484375 +81558 -0.456329345703125 +81559 -0.51641845703125 +81560 -0.519287109375 +81561 -0.458251953125 +81562 -0.384796142578125 +81563 -0.323699951171875 +81564 -0.269287109375 +81565 -0.1951904296875 +81566 -0.100006103515625 +81567 -0.01055908203125 +81568 0.1033935546875 +81569 0.24908447265625 +81570 0.373199462890625 +81571 0.45806884765625 +81572 0.511474609375 +81573 0.565399169921875 +81574 0.61138916015625 +81575 0.5897216796875 +81576 0.4906005859375 +81577 0.33148193359375 +81578 0.147796630859375 +81579 -0.01873779296875 +81580 -0.140289306640625 +81581 -0.191986083984375 +81582 -0.184295654296875 +81583 -0.161834716796875 +81584 -0.166595458984375 +81585 -0.19390869140625 +81586 -0.22442626953125 +81587 -0.279754638671875 +81588 -0.3389892578125 +81589 -0.3543701171875 +81590 -0.348175048828125 +81591 -0.32598876953125 +81592 -0.2581787109375 +81593 -0.139801025390625 +81594 0.014617919921875 +81595 0.144378662109375 +81596 0.221038818359375 +81597 0.27069091796875 +81598 0.294036865234375 +81599 0.311767578125 +81600 0.339141845703125 +81601 0.360260009765625 +81602 0.360504150390625 +81603 0.308380126953125 +81604 0.18170166015625 +81605 0.0047607421875 +81606 -0.17559814453125 +81607 -0.3143310546875 +81608 -0.36785888671875 +81609 -0.36248779296875 +81610 -0.343536376953125 +81611 -0.3018798828125 +81612 -0.231414794921875 +81613 -0.117645263671875 +81614 0.007049560546875 +81615 0.087982177734375 +81616 0.13946533203125 +81617 0.17425537109375 +81618 0.188201904296875 +81619 0.171234130859375 +81620 0.118438720703125 +81621 0.05706787109375 +81622 -0.010711669921875 +81623 -0.0914306640625 +81624 -0.162322998046875 +81625 -0.194549560546875 +81626 -0.1492919921875 +81627 -0.02166748046875 +81628 0.124053955078125 +81629 0.211151123046875 +81630 0.240447998046875 +81631 0.242218017578125 +81632 0.2257080078125 +81633 0.194366455078125 +81634 0.115509033203125 +81635 0.0128173828125 +81636 -0.053802490234375 +81637 -0.110626220703125 +81638 -0.199493408203125 +81639 -0.29437255859375 +81640 -0.33221435546875 +81641 -0.27972412109375 +81642 -0.185333251953125 +81643 -0.128204345703125 +81644 -0.115692138671875 +81645 -0.116455078125 +81646 -0.105926513671875 +81647 -0.053955078125 +81648 0.048797607421875 +81649 0.157318115234375 +81650 0.212005615234375 +81651 0.218475341796875 +81652 0.23724365234375 +81653 0.30535888671875 +81654 0.38128662109375 +81655 0.404449462890625 +81656 0.3944091796875 +81657 0.3885498046875 +81658 0.362640380859375 +81659 0.27362060546875 +81660 0.11712646484375 +81661 -0.054901123046875 +81662 -0.19085693359375 +81663 -0.28570556640625 +81664 -0.339263916015625 +81665 -0.3775634765625 +81666 -0.445709228515625 +81667 -0.535064697265625 +81668 -0.629058837890625 +81669 -0.697601318359375 +81670 -0.70391845703125 +81671 -0.6424560546875 +81672 -0.491241455078125 +81673 -0.265716552734375 +81674 -0.023712158203125 +81675 0.201751708984375 +81676 0.375823974609375 +81677 0.485076904296875 +81678 0.56884765625 +81679 0.634765625 +81680 0.63763427734375 +81681 0.5660400390625 +81682 0.4720458984375 +81683 0.40692138671875 +81684 0.3778076171875 +81685 0.376953125 +81686 0.371978759765625 +81687 0.313140869140625 +81688 0.184417724609375 +81689 0.011199951171875 +81690 -0.171051025390625 +81691 -0.33740234375 +81692 -0.47198486328125 +81693 -0.560394287109375 +81694 -0.58056640625 +81695 -0.54754638671875 +81696 -0.508575439453125 +81697 -0.459503173828125 +81698 -0.394378662109375 +81699 -0.35260009765625 +81700 -0.31170654296875 +81701 -0.197418212890625 +81702 -0.007965087890625 +81703 0.207489013671875 +81704 0.409210205078125 +81705 0.57208251953125 +81706 0.66595458984375 +81707 0.65875244140625 +81708 0.56744384765625 +81709 0.431396484375 +81710 0.29443359375 +81711 0.182464599609375 +81712 0.06365966796875 +81713 -0.075958251953125 +81714 -0.189422607421875 +81715 -0.271942138671875 +81716 -0.342529296875 +81717 -0.364166259765625 +81718 -0.327239990234375 +81719 -0.2769775390625 +81720 -0.253692626953125 +81721 -0.24365234375 +81722 -0.1983642578125 +81723 -0.116241455078125 +81724 -0.036834716796875 +81725 0.034881591796875 +81726 0.09124755859375 +81727 0.10888671875 +81728 0.125518798828125 +81729 0.15771484375 +81730 0.17828369140625 +81731 0.17108154296875 +81732 0.129974365234375 +81733 0.082427978515625 +81734 0.027679443359375 +81735 -0.065643310546875 +81736 -0.15936279296875 +81737 -0.21307373046875 +81738 -0.234649658203125 +81739 -0.2001953125 +81740 -0.119171142578125 +81741 -0.024749755859375 +81742 0.085784912109375 +81743 0.178131103515625 +81744 0.215576171875 +81745 0.211456298828125 +81746 0.17523193359375 +81747 0.128753662109375 +81748 0.1019287109375 +81749 0.0743408203125 +81750 0.04327392578125 +81751 0.038177490234375 +81752 0.076263427734375 +81753 0.14105224609375 +81754 0.186431884765625 +81755 0.188812255859375 +81756 0.1390380859375 +81757 0.041778564453125 +81758 -0.079437255859375 +81759 -0.219390869140625 +81760 -0.367828369140625 +81761 -0.494873046875 +81762 -0.556243896484375 +81763 -0.508697509765625 +81764 -0.3756103515625 +81765 -0.218902587890625 +81766 -0.063751220703125 +81767 0.091552734375 +81768 0.23602294921875 +81769 0.342987060546875 +81770 0.39520263671875 +81771 0.389373779296875 +81772 0.324249267578125 +81773 0.224090576171875 +81774 0.124267578125 +81775 0.037078857421875 +81776 -0.010101318359375 +81777 -0.019439697265625 +81778 -0.022796630859375 +81779 -0.001556396484375 +81780 0.056304931640625 +81781 0.106719970703125 +81782 0.096893310546875 +81783 0.042694091796875 +81784 -0.018035888671875 +81785 -0.07586669921875 +81786 -0.11944580078125 +81787 -0.15972900390625 +81788 -0.202606201171875 +81789 -0.24859619140625 +81790 -0.30517578125 +81791 -0.36212158203125 +81792 -0.39141845703125 +81793 -0.35528564453125 +81794 -0.249969482421875 +81795 -0.092864990234375 +81796 0.08905029296875 +81797 0.2352294921875 +81798 0.318817138671875 +81799 0.358642578125 +81800 0.347747802734375 +81801 0.28564453125 +81802 0.223175048828125 +81803 0.196746826171875 +81804 0.179840087890625 +81805 0.155548095703125 +81806 0.151214599609375 +81807 0.156951904296875 +81808 0.13177490234375 +81809 0.100799560546875 +81810 0.087127685546875 +81811 0.05487060546875 +81812 -0.009002685546875 +81813 -0.10400390625 +81814 -0.229400634765625 +81815 -0.35552978515625 +81816 -0.441925048828125 +81817 -0.473846435546875 +81818 -0.464813232421875 +81819 -0.419097900390625 +81820 -0.334320068359375 +81821 -0.227935791015625 +81822 -0.12347412109375 +81823 -0.02764892578125 +81824 0.077667236328125 +81825 0.2132568359375 +81826 0.38885498046875 +81827 0.582794189453125 +81828 0.734039306640625 +81829 0.800140380859375 +81830 0.7783203125 +81831 0.6651611328125 +81832 0.45965576171875 +81833 0.199188232421875 +81834 -0.050689697265625 +81835 -0.23297119140625 +81836 -0.33013916015625 +81837 -0.368408203125 +81838 -0.378936767578125 +81839 -0.376983642578125 +81840 -0.37969970703125 +81841 -0.391510009765625 +81842 -0.385345458984375 +81843 -0.3419189453125 +81844 -0.28289794921875 +81845 -0.251617431640625 +81846 -0.266143798828125 +81847 -0.273345947265625 +81848 -0.216796875 +81849 -0.128265380859375 +81850 -0.068145751953125 +81851 -0.0430908203125 +81852 -0.024444580078125 +81853 0.020721435546875 +81854 0.124481201171875 +81855 0.25787353515625 +81856 0.379119873046875 +81857 0.47991943359375 +81858 0.5281982421875 +81859 0.511138916015625 +81860 0.456207275390625 +81861 0.407470703125 +81862 0.383758544921875 +81863 0.35687255859375 +81864 0.31182861328125 +81865 0.250885009765625 +81866 0.1654052734375 +81867 0.035247802734375 +81868 -0.142059326171875 +81869 -0.33563232421875 +81870 -0.5345458984375 +81871 -0.72186279296875 +81872 -0.836669921875 +81873 -0.8326416015625 +81874 -0.7296142578125 +81875 -0.582550048828125 +81876 -0.440093994140625 +81877 -0.324310302734375 +81878 -0.20147705078125 +81879 -0.044647216796875 +81880 0.103973388671875 +81881 0.202392578125 +81882 0.264495849609375 +81883 0.338897705078125 +81884 0.443817138671875 +81885 0.545074462890625 +81886 0.6173095703125 +81887 0.6524658203125 +81888 0.66339111328125 +81889 0.6561279296875 +81890 0.606781005859375 +81891 0.501190185546875 +81892 0.352783203125 +81893 0.176544189453125 +81894 -0.034820556640625 +81895 -0.258209228515625 +81896 -0.44244384765625 +81897 -0.5753173828125 +81898 -0.65203857421875 +81899 -0.641632080078125 +81900 -0.562164306640625 +81901 -0.458038330078125 +81902 -0.350555419921875 +81903 -0.260528564453125 +81904 -0.192108154296875 +81905 -0.141937255859375 +81906 -0.1021728515625 +81907 -0.062896728515625 +81908 -0.011932373046875 +81909 0.062835693359375 +81910 0.148712158203125 +81911 0.241729736328125 +81912 0.34912109375 +81913 0.457305908203125 +81914 0.54388427734375 +81915 0.5728759765625 +81916 0.506591796875 +81917 0.351226806640625 +81918 0.146514892578125 +81919 -0.05523681640625 +81920 -0.21624755859375 +81921 -0.334930419921875 +81922 -0.402984619140625 +81923 -0.4412841796875 +81924 -0.49578857421875 +81925 -0.5601806640625 +81926 -0.600738525390625 +81927 -0.584228515625 +81928 -0.47930908203125 +81929 -0.27935791015625 +81930 -0.0089111328125 +81931 0.268798828125 +81932 0.482818603515625 +81933 0.60369873046875 +81934 0.650421142578125 +81935 0.66400146484375 +81936 0.6414794921875 +81937 0.572540283203125 +81938 0.498138427734375 +81939 0.439453125 +81940 0.375518798828125 +81941 0.274505615234375 +81942 0.1087646484375 +81943 -0.099395751953125 +81944 -0.3182373046875 +81945 -0.5489501953125 +81946 -0.7738037109375 +81947 -0.86383056640625 +81948 -0.870391845703125 +81949 -0.86895751953125 +81950 -0.861053466796875 +81951 -0.765869140625 +81952 -0.5301513671875 +81953 -0.214691162109375 +81954 0.137359619140625 +81955 0.474822998046875 +81956 0.76239013671875 +81957 0.867462158203125 +81958 0.870361328125 +81959 0.86480712890625 +81960 0.831817626953125 +81961 0.677581787109375 +81962 0.495880126953125 +81963 0.30767822265625 +81964 0.116180419921875 +81965 -0.110748291015625 +81966 -0.381805419921875 +81967 -0.6572265625 +81968 -0.857421875 +81969 -0.870391845703125 +81970 -0.870391845703125 +81971 -0.86444091796875 +81972 -0.85723876953125 +81973 -0.790008544921875 +81974 -0.62847900390625 +81975 -0.3956298828125 +81976 -0.126708984375 +81977 0.150115966796875 +81978 0.424041748046875 +81979 0.670623779296875 +81980 0.854522705078125 +81981 0.866485595703125 +81982 0.86920166015625 +81983 0.8653564453125 +81984 0.857147216796875 +81985 0.766845703125 +81986 0.628509521484375 +81987 0.462127685546875 +81988 0.297210693359375 +81989 0.14862060546875 +81990 -0.00537109375 +81991 -0.15753173828125 +81992 -0.31304931640625 +81993 -0.48876953125 +81994 -0.6416015625 +81995 -0.751373291015625 +81996 -0.84619140625 +81997 -0.861297607421875 +81998 -0.863250732421875 +81999 -0.856597900390625 +82000 -0.7498779296875 +82001 -0.624542236328125 +82002 -0.47808837890625 +82003 -0.253387451171875 +82004 0.003692626953125 +82005 0.2257080078125 +82006 0.427154541015625 +82007 0.643218994140625 +82008 0.855926513671875 +82009 0.870361328125 +82010 0.870361328125 +82011 0.862762451171875 +82012 0.79669189453125 +82013 0.595794677734375 +82014 0.362152099609375 +82015 0.1270751953125 +82016 -0.086944580078125 +82017 -0.2784423828125 +82018 -0.484832763671875 +82019 -0.729583740234375 +82020 -0.86688232421875 +82021 -0.870391845703125 +82022 -0.86859130859375 +82023 -0.86279296875 +82024 -0.817962646484375 +82025 -0.6116943359375 +82026 -0.3128662109375 +82027 0.039398193359375 +82028 0.422821044921875 +82029 0.805145263671875 +82030 0.870361328125 +82031 0.870361328125 +82032 0.860015869140625 +82033 0.727935791015625 +82034 0.48114013671875 +82035 0.2059326171875 +82036 -0.06103515625 +82037 -0.29913330078125 +82038 -0.516204833984375 +82039 -0.7252197265625 +82040 -0.85980224609375 +82041 -0.870391845703125 +82042 -0.870391845703125 +82043 -0.858062744140625 +82044 -0.673004150390625 +82045 -0.42694091796875 +82046 -0.2100830078125 +82047 -0.0362548828125 +82048 0.10943603515625 +82049 0.23516845703125 +82050 0.373687744140625 +82051 0.517791748046875 +82052 0.602783203125 +82053 0.635711669921875 +82054 0.655181884765625 +82055 0.65948486328125 +82056 0.651275634765625 +82057 0.61846923828125 +82058 0.53753662109375 +82059 0.404144287109375 +82060 0.22186279296875 +82061 0.003997802734375 +82062 -0.22100830078125 +82063 -0.42449951171875 +82064 -0.579833984375 +82065 -0.641876220703125 +82066 -0.6177978515625 +82067 -0.575531005859375 +82068 -0.526336669921875 +82069 -0.42645263671875 +82070 -0.2581787109375 +82071 -0.068695068359375 +82072 0.09222412109375 +82073 0.232147216796875 +82074 0.3509521484375 +82075 0.410064697265625 +82076 0.372955322265625 +82077 0.2554931640625 +82078 0.10711669921875 +82079 -0.052886962890625 +82080 -0.186279296875 +82081 -0.23291015625 +82082 -0.209442138671875 +82083 -0.174163818359375 +82084 -0.126739501953125 +82085 -0.048126220703125 +82086 0.0426025390625 +82087 0.10748291015625 +82088 0.1409912109375 +82089 0.19708251953125 +82090 0.273651123046875 +82091 0.31768798828125 +82092 0.341094970703125 +82093 0.368011474609375 +82094 0.37249755859375 +82095 0.30072021484375 +82096 0.1517333984375 +82097 -0.01470947265625 +82098 -0.1883544921875 +82099 -0.372711181640625 +82100 -0.51397705078125 +82101 -0.57177734375 +82102 -0.53948974609375 +82103 -0.43511962890625 +82104 -0.2962646484375 +82105 -0.161102294921875 +82106 -0.0435791015625 +82107 0.060394287109375 +82108 0.13665771484375 +82109 0.170135498046875 +82110 0.16552734375 +82111 0.15728759765625 +82112 0.150787353515625 +82113 0.12200927734375 +82114 0.080108642578125 +82115 0.05126953125 +82116 0.062896728515625 +82117 0.09271240234375 +82118 0.092987060546875 +82119 0.07855224609375 +82120 0.06427001953125 +82121 0.0347900390625 +82122 -0.01171875 +82123 -0.056060791015625 +82124 -0.055511474609375 +82125 -0.010467529296875 +82126 0.02508544921875 +82127 0.025665283203125 +82128 0.017333984375 +82129 0.00189208984375 +82130 -0.03173828125 +82131 -0.071502685546875 +82132 -0.13543701171875 +82133 -0.219970703125 +82134 -0.300506591796875 +82135 -0.376312255859375 +82136 -0.416107177734375 +82137 -0.371124267578125 +82138 -0.242279052734375 +82139 -0.069732666015625 +82140 0.125640869140625 +82141 0.31268310546875 +82142 0.45501708984375 +82143 0.554779052734375 +82144 0.61065673828125 +82145 0.610931396484375 +82146 0.531463623046875 +82147 0.3883056640625 +82148 0.23468017578125 +82149 0.095245361328125 +82150 -0.00396728515625 +82151 -0.04852294921875 +82152 -0.055145263671875 +82153 -0.0758056640625 +82154 -0.138702392578125 +82155 -0.209197998046875 +82156 -0.289031982421875 +82157 -0.37884521484375 +82158 -0.456329345703125 +82159 -0.51641845703125 +82160 -0.519287109375 +82161 -0.458251953125 +82162 -0.384796142578125 +82163 -0.323699951171875 +82164 -0.269287109375 +82165 -0.1951904296875 +82166 -0.100006103515625 +82167 -0.01055908203125 +82168 0.1033935546875 +82169 0.24908447265625 +82170 0.373199462890625 +82171 0.45806884765625 +82172 0.511474609375 +82173 0.565399169921875 +82174 0.61138916015625 +82175 0.5897216796875 +82176 0.4906005859375 +82177 0.33148193359375 +82178 0.147796630859375 +82179 -0.01873779296875 +82180 -0.140289306640625 +82181 -0.191986083984375 +82182 -0.184295654296875 +82183 -0.161834716796875 +82184 -0.166595458984375 +82185 -0.19390869140625 +82186 -0.22442626953125 +82187 -0.279754638671875 +82188 -0.3389892578125 +82189 -0.3543701171875 +82190 -0.348175048828125 +82191 -0.32598876953125 +82192 -0.2581787109375 +82193 -0.139801025390625 +82194 0.014617919921875 +82195 0.144378662109375 +82196 0.221038818359375 +82197 0.27069091796875 +82198 0.294036865234375 +82199 0.311767578125 +82200 0.339141845703125 +82201 0.360260009765625 +82202 0.360504150390625 +82203 0.308380126953125 +82204 0.18170166015625 +82205 0.0047607421875 +82206 -0.17559814453125 +82207 -0.3143310546875 +82208 -0.36785888671875 +82209 -0.36248779296875 +82210 -0.343536376953125 +82211 -0.3018798828125 +82212 -0.231414794921875 +82213 -0.117645263671875 +82214 0.007049560546875 +82215 0.087982177734375 +82216 0.13946533203125 +82217 0.17425537109375 +82218 0.188201904296875 +82219 0.171234130859375 +82220 0.118438720703125 +82221 0.05706787109375 +82222 -0.010711669921875 +82223 -0.0914306640625 +82224 -0.162322998046875 +82225 -0.194549560546875 +82226 -0.1492919921875 +82227 -0.02166748046875 +82228 0.124053955078125 +82229 0.211151123046875 +82230 0.240447998046875 +82231 0.242218017578125 +82232 0.2257080078125 +82233 0.194366455078125 +82234 0.115509033203125 +82235 0.0128173828125 +82236 -0.053802490234375 +82237 -0.110626220703125 +82238 -0.199493408203125 +82239 -0.29437255859375 +82240 -0.33221435546875 +82241 -0.27972412109375 +82242 -0.185333251953125 +82243 -0.128204345703125 +82244 -0.115692138671875 +82245 -0.116455078125 +82246 -0.105926513671875 +82247 -0.053955078125 +82248 0.048797607421875 +82249 0.157318115234375 +82250 0.212005615234375 +82251 0.218475341796875 +82252 0.23724365234375 +82253 0.30535888671875 +82254 0.38128662109375 +82255 0.404449462890625 +82256 0.3944091796875 +82257 0.3885498046875 +82258 0.362640380859375 +82259 0.27362060546875 +82260 0.11712646484375 +82261 -0.054901123046875 +82262 -0.19085693359375 +82263 -0.28570556640625 +82264 -0.339263916015625 +82265 -0.3775634765625 +82266 -0.445709228515625 +82267 -0.535064697265625 +82268 -0.629058837890625 +82269 -0.697601318359375 +82270 -0.70391845703125 +82271 -0.6424560546875 +82272 -0.491241455078125 +82273 -0.265716552734375 +82274 -0.023712158203125 +82275 0.201751708984375 +82276 0.375823974609375 +82277 0.485076904296875 +82278 0.56884765625 +82279 0.634765625 +82280 0.63763427734375 +82281 0.5660400390625 +82282 0.4720458984375 +82283 0.40692138671875 +82284 0.3778076171875 +82285 0.376953125 +82286 0.371978759765625 +82287 0.313140869140625 +82288 0.184417724609375 +82289 0.011199951171875 +82290 -0.171051025390625 +82291 -0.33740234375 +82292 -0.47198486328125 +82293 -0.560394287109375 +82294 -0.58056640625 +82295 -0.54754638671875 +82296 -0.508575439453125 +82297 -0.459503173828125 +82298 -0.394378662109375 +82299 -0.35260009765625 +82300 -0.31170654296875 +82301 -0.197418212890625 +82302 -0.007965087890625 +82303 0.207489013671875 +82304 0.409210205078125 +82305 0.57208251953125 +82306 0.66595458984375 +82307 0.65875244140625 +82308 0.56744384765625 +82309 0.431396484375 +82310 0.29443359375 +82311 0.182464599609375 +82312 0.06365966796875 +82313 -0.075958251953125 +82314 -0.189422607421875 +82315 -0.271942138671875 +82316 -0.342529296875 +82317 -0.364166259765625 +82318 -0.327239990234375 +82319 -0.2769775390625 +82320 -0.253692626953125 +82321 -0.24365234375 +82322 -0.1983642578125 +82323 -0.116241455078125 +82324 -0.036834716796875 +82325 0.034881591796875 +82326 0.09124755859375 +82327 0.10888671875 +82328 0.125518798828125 +82329 0.15771484375 +82330 0.17828369140625 +82331 0.17108154296875 +82332 0.129974365234375 +82333 0.082427978515625 +82334 0.027679443359375 +82335 -0.065643310546875 +82336 -0.15936279296875 +82337 -0.21307373046875 +82338 -0.234649658203125 +82339 -0.2001953125 +82340 -0.119171142578125 +82341 -0.024749755859375 +82342 0.085784912109375 +82343 0.178131103515625 +82344 0.215576171875 +82345 0.211456298828125 +82346 0.17523193359375 +82347 0.128753662109375 +82348 0.1019287109375 +82349 0.0743408203125 +82350 0.04327392578125 +82351 0.038177490234375 +82352 0.076263427734375 +82353 0.14105224609375 +82354 0.186431884765625 +82355 0.188812255859375 +82356 0.1390380859375 +82357 0.041778564453125 +82358 -0.079437255859375 +82359 -0.219390869140625 +82360 -0.367828369140625 +82361 -0.494873046875 +82362 -0.556243896484375 +82363 -0.508697509765625 +82364 -0.3756103515625 +82365 -0.218902587890625 +82366 -0.063751220703125 +82367 0.091552734375 +82368 0.23602294921875 +82369 0.342987060546875 +82370 0.39520263671875 +82371 0.389373779296875 +82372 0.324249267578125 +82373 0.224090576171875 +82374 0.124267578125 +82375 0.037078857421875 +82376 -0.010101318359375 +82377 -0.019439697265625 +82378 -0.022796630859375 +82379 -0.001556396484375 +82380 0.056304931640625 +82381 0.106719970703125 +82382 0.096893310546875 +82383 0.042694091796875 +82384 -0.018035888671875 +82385 -0.07586669921875 +82386 -0.11944580078125 +82387 -0.15972900390625 +82388 -0.202606201171875 +82389 -0.24859619140625 +82390 -0.30517578125 +82391 -0.36212158203125 +82392 -0.39141845703125 +82393 -0.35528564453125 +82394 -0.249969482421875 +82395 -0.092864990234375 +82396 0.08905029296875 +82397 0.2352294921875 +82398 0.318817138671875 +82399 0.358642578125 +82400 0.347747802734375 +82401 0.28564453125 +82402 0.223175048828125 +82403 0.196746826171875 +82404 0.179840087890625 +82405 0.155548095703125 +82406 0.151214599609375 +82407 0.156951904296875 +82408 0.13177490234375 +82409 0.100799560546875 +82410 0.087127685546875 +82411 0.05487060546875 +82412 -0.009002685546875 +82413 -0.10400390625 +82414 -0.229400634765625 +82415 -0.35552978515625 +82416 -0.441925048828125 +82417 -0.473846435546875 +82418 -0.464813232421875 +82419 -0.419097900390625 +82420 -0.334320068359375 +82421 -0.227935791015625 +82422 -0.12347412109375 +82423 -0.02764892578125 +82424 0.077667236328125 +82425 0.2132568359375 +82426 0.38885498046875 +82427 0.582794189453125 +82428 0.734039306640625 +82429 0.800140380859375 +82430 0.7783203125 +82431 0.6651611328125 +82432 0.45965576171875 +82433 0.199188232421875 +82434 -0.050689697265625 +82435 -0.23297119140625 +82436 -0.33013916015625 +82437 -0.368408203125 +82438 -0.378936767578125 +82439 -0.376983642578125 +82440 -0.37969970703125 +82441 -0.391510009765625 +82442 -0.385345458984375 +82443 -0.3419189453125 +82444 -0.28289794921875 +82445 -0.251617431640625 +82446 -0.266143798828125 +82447 -0.273345947265625 +82448 -0.216796875 +82449 -0.128265380859375 +82450 -0.068145751953125 +82451 -0.0430908203125 +82452 -0.024444580078125 +82453 0.020721435546875 +82454 0.124481201171875 +82455 0.25787353515625 +82456 0.379119873046875 +82457 0.47991943359375 +82458 0.5281982421875 +82459 0.511138916015625 +82460 0.456207275390625 +82461 0.407470703125 +82462 0.383758544921875 +82463 0.35687255859375 +82464 0.31182861328125 +82465 0.250885009765625 +82466 0.1654052734375 +82467 0.035247802734375 +82468 -0.142059326171875 +82469 -0.33563232421875 +82470 -0.5345458984375 +82471 -0.72186279296875 +82472 -0.836669921875 +82473 -0.8326416015625 +82474 -0.7296142578125 +82475 -0.582550048828125 +82476 -0.440093994140625 +82477 -0.324310302734375 +82478 -0.20147705078125 +82479 -0.044647216796875 +82480 0.103973388671875 +82481 0.202392578125 +82482 0.264495849609375 +82483 0.338897705078125 +82484 0.443817138671875 +82485 0.545074462890625 +82486 0.6173095703125 +82487 0.6524658203125 +82488 0.66339111328125 +82489 0.6561279296875 +82490 0.606781005859375 +82491 0.501190185546875 +82492 0.352783203125 +82493 0.176544189453125 +82494 -0.034820556640625 +82495 -0.258209228515625 +82496 -0.44244384765625 +82497 -0.5753173828125 +82498 -0.65203857421875 +82499 -0.641632080078125 +82500 -0.562164306640625 +82501 -0.458038330078125 +82502 -0.350555419921875 +82503 -0.260528564453125 +82504 -0.192108154296875 +82505 -0.141937255859375 +82506 -0.1021728515625 +82507 -0.062896728515625 +82508 -0.011932373046875 +82509 0.062835693359375 +82510 0.148712158203125 +82511 0.241729736328125 +82512 0.34912109375 +82513 0.457305908203125 +82514 0.54388427734375 +82515 0.5728759765625 +82516 0.506591796875 +82517 0.351226806640625 +82518 0.146514892578125 +82519 -0.05523681640625 +82520 -0.21624755859375 +82521 -0.334930419921875 +82522 -0.402984619140625 +82523 -0.4412841796875 +82524 -0.49578857421875 +82525 -0.5601806640625 +82526 -0.600738525390625 +82527 -0.584228515625 +82528 -0.47930908203125 +82529 -0.27935791015625 +82530 -0.0089111328125 +82531 0.268798828125 +82532 0.482818603515625 +82533 0.60369873046875 +82534 0.650421142578125 +82535 0.66400146484375 +82536 0.6414794921875 +82537 0.572540283203125 +82538 0.498138427734375 +82539 0.439453125 +82540 0.375518798828125 +82541 0.274505615234375 +82542 0.1087646484375 +82543 -0.099395751953125 +82544 -0.3182373046875 +82545 -0.5489501953125 +82546 -0.7738037109375 +82547 -0.86383056640625 +82548 -0.870391845703125 +82549 -0.86895751953125 +82550 -0.861053466796875 +82551 -0.765869140625 +82552 -0.5301513671875 +82553 -0.214691162109375 +82554 0.137359619140625 +82555 0.474822998046875 +82556 0.76239013671875 +82557 0.867462158203125 +82558 0.870361328125 +82559 0.86480712890625 +82560 0.831817626953125 +82561 0.677581787109375 +82562 0.495880126953125 +82563 0.30767822265625 +82564 0.116180419921875 +82565 -0.110748291015625 +82566 -0.381805419921875 +82567 -0.6572265625 +82568 -0.857421875 +82569 -0.870391845703125 +82570 -0.870391845703125 +82571 -0.86444091796875 +82572 -0.85723876953125 +82573 -0.790008544921875 +82574 -0.62847900390625 +82575 -0.3956298828125 +82576 -0.126708984375 +82577 0.150115966796875 +82578 0.424041748046875 +82579 0.670623779296875 +82580 0.854522705078125 +82581 0.866485595703125 +82582 0.86920166015625 +82583 0.8653564453125 +82584 0.857147216796875 +82585 0.766845703125 +82586 0.628509521484375 +82587 0.462127685546875 +82588 0.297210693359375 +82589 0.14862060546875 +82590 -0.00537109375 +82591 -0.15753173828125 +82592 -0.31304931640625 +82593 -0.48876953125 +82594 -0.6416015625 +82595 -0.751373291015625 +82596 -0.84619140625 +82597 -0.861297607421875 +82598 -0.863250732421875 +82599 -0.856597900390625 +82600 -0.7498779296875 +82601 -0.624542236328125 +82602 -0.47808837890625 +82603 -0.253387451171875 +82604 0.003692626953125 +82605 0.2257080078125 +82606 0.427154541015625 +82607 0.643218994140625 +82608 0.855926513671875 +82609 0.870361328125 +82610 0.870361328125 +82611 0.862762451171875 +82612 0.79669189453125 +82613 0.595794677734375 +82614 0.362152099609375 +82615 0.1270751953125 +82616 -0.086944580078125 +82617 -0.2784423828125 +82618 -0.484832763671875 +82619 -0.729583740234375 +82620 -0.86688232421875 +82621 -0.870391845703125 +82622 -0.86859130859375 +82623 -0.86279296875 +82624 -0.817962646484375 +82625 -0.6116943359375 +82626 -0.3128662109375 +82627 0.039398193359375 +82628 0.422821044921875 +82629 0.805145263671875 +82630 0.870361328125 +82631 0.870361328125 +82632 0.860015869140625 +82633 0.727935791015625 +82634 0.48114013671875 +82635 0.2059326171875 +82636 -0.06103515625 +82637 -0.29913330078125 +82638 -0.516204833984375 +82639 -0.7252197265625 +82640 -0.85980224609375 +82641 -0.870391845703125 +82642 -0.870391845703125 +82643 -0.858062744140625 +82644 -0.673004150390625 +82645 -0.42694091796875 +82646 -0.2100830078125 +82647 -0.0362548828125 +82648 0.10943603515625 +82649 0.23516845703125 +82650 0.373687744140625 +82651 0.517791748046875 +82652 0.602783203125 +82653 0.635711669921875 +82654 0.655181884765625 +82655 0.65948486328125 +82656 0.651275634765625 +82657 0.61846923828125 +82658 0.53753662109375 +82659 0.404144287109375 +82660 0.22186279296875 +82661 0.003997802734375 +82662 -0.22100830078125 +82663 -0.42449951171875 +82664 -0.579833984375 +82665 -0.641876220703125 +82666 -0.6177978515625 +82667 -0.575531005859375 +82668 -0.526336669921875 +82669 -0.42645263671875 +82670 -0.2581787109375 +82671 -0.068695068359375 +82672 0.09222412109375 +82673 0.232147216796875 +82674 0.3509521484375 +82675 0.410064697265625 +82676 0.372955322265625 +82677 0.2554931640625 +82678 0.10711669921875 +82679 -0.052886962890625 +82680 -0.186279296875 +82681 -0.23291015625 +82682 -0.209442138671875 +82683 -0.174163818359375 +82684 -0.126739501953125 +82685 -0.048126220703125 +82686 0.0426025390625 +82687 0.10748291015625 +82688 0.1409912109375 +82689 0.19708251953125 +82690 0.273651123046875 +82691 0.31768798828125 +82692 0.341094970703125 +82693 0.368011474609375 +82694 0.37249755859375 +82695 0.30072021484375 +82696 0.1517333984375 +82697 -0.01470947265625 +82698 -0.1883544921875 +82699 -0.372711181640625 +82700 -0.51397705078125 +82701 -0.57177734375 +82702 -0.53948974609375 +82703 -0.43511962890625 +82704 -0.2962646484375 +82705 -0.161102294921875 +82706 -0.0435791015625 +82707 0.060394287109375 +82708 0.13665771484375 +82709 0.170135498046875 +82710 0.16552734375 +82711 0.15728759765625 +82712 0.150787353515625 +82713 0.12200927734375 +82714 0.080108642578125 +82715 0.05126953125 +82716 0.062896728515625 +82717 0.09271240234375 +82718 0.092987060546875 +82719 0.07855224609375 +82720 0.06427001953125 +82721 0.0347900390625 +82722 -0.01171875 +82723 -0.056060791015625 +82724 -0.055511474609375 +82725 -0.010467529296875 +82726 0.02508544921875 +82727 0.025665283203125 +82728 0.017333984375 +82729 0.00189208984375 +82730 -0.03173828125 +82731 -0.071502685546875 +82732 -0.13543701171875 +82733 -0.219970703125 +82734 -0.300506591796875 +82735 -0.376312255859375 +82736 -0.416107177734375 +82737 -0.371124267578125 +82738 -0.242279052734375 +82739 -0.069732666015625 +82740 0.125640869140625 +82741 0.31268310546875 +82742 0.45501708984375 +82743 0.554779052734375 +82744 0.61065673828125 +82745 0.610931396484375 +82746 0.531463623046875 +82747 0.3883056640625 +82748 0.23468017578125 +82749 0.095245361328125 +82750 -0.00396728515625 +82751 -0.04852294921875 +82752 -0.055145263671875 +82753 -0.0758056640625 +82754 -0.138702392578125 +82755 -0.209197998046875 +82756 -0.289031982421875 +82757 -0.37884521484375 +82758 -0.456329345703125 +82759 -0.51641845703125 +82760 -0.519287109375 +82761 -0.458251953125 +82762 -0.384796142578125 +82763 -0.323699951171875 +82764 -0.269287109375 +82765 -0.1951904296875 +82766 -0.100006103515625 +82767 -0.01055908203125 +82768 0.1033935546875 +82769 0.24908447265625 +82770 0.373199462890625 +82771 0.45806884765625 +82772 0.511474609375 +82773 0.565399169921875 +82774 0.61138916015625 +82775 0.5897216796875 +82776 0.4906005859375 +82777 0.33148193359375 +82778 0.147796630859375 +82779 -0.01873779296875 +82780 -0.140289306640625 +82781 -0.191986083984375 +82782 -0.184295654296875 +82783 -0.161834716796875 +82784 -0.166595458984375 +82785 -0.19390869140625 +82786 -0.22442626953125 +82787 -0.279754638671875 +82788 -0.3389892578125 +82789 -0.3543701171875 +82790 -0.348175048828125 +82791 -0.32598876953125 +82792 -0.2581787109375 +82793 -0.139801025390625 +82794 0.014617919921875 +82795 0.144378662109375 +82796 0.221038818359375 +82797 0.27069091796875 +82798 0.294036865234375 +82799 0.311767578125 +82800 0.339141845703125 +82801 0.360260009765625 +82802 0.360504150390625 +82803 0.308380126953125 +82804 0.18170166015625 +82805 0.0047607421875 +82806 -0.17559814453125 +82807 -0.3143310546875 +82808 -0.36785888671875 +82809 -0.36248779296875 +82810 -0.343536376953125 +82811 -0.3018798828125 +82812 -0.231414794921875 +82813 -0.117645263671875 +82814 0.007049560546875 +82815 0.087982177734375 +82816 0.13946533203125 +82817 0.17425537109375 +82818 0.188201904296875 +82819 0.171234130859375 +82820 0.118438720703125 +82821 0.05706787109375 +82822 -0.010711669921875 +82823 -0.0914306640625 +82824 -0.162322998046875 +82825 -0.194549560546875 +82826 -0.1492919921875 +82827 -0.02166748046875 +82828 0.124053955078125 +82829 0.211151123046875 +82830 0.240447998046875 +82831 0.242218017578125 +82832 0.2257080078125 +82833 0.194366455078125 +82834 0.115509033203125 +82835 0.0128173828125 +82836 -0.053802490234375 +82837 -0.110626220703125 +82838 -0.199493408203125 +82839 -0.29437255859375 +82840 -0.33221435546875 +82841 -0.27972412109375 +82842 -0.185333251953125 +82843 -0.128204345703125 +82844 -0.115692138671875 +82845 -0.116455078125 +82846 -0.105926513671875 +82847 -0.053955078125 +82848 0.048797607421875 +82849 0.157318115234375 +82850 0.212005615234375 +82851 0.218475341796875 +82852 0.23724365234375 +82853 0.30535888671875 +82854 0.38128662109375 +82855 0.404449462890625 +82856 0.3944091796875 +82857 0.3885498046875 +82858 0.362640380859375 +82859 0.27362060546875 +82860 0.11712646484375 +82861 -0.054901123046875 +82862 -0.19085693359375 +82863 -0.28570556640625 +82864 -0.339263916015625 +82865 -0.3775634765625 +82866 -0.445709228515625 +82867 -0.535064697265625 +82868 -0.629058837890625 +82869 -0.697601318359375 +82870 -0.70391845703125 +82871 -0.6424560546875 +82872 -0.491241455078125 +82873 -0.265716552734375 +82874 -0.023712158203125 +82875 0.201751708984375 +82876 0.375823974609375 +82877 0.485076904296875 +82878 0.56884765625 +82879 0.634765625 +82880 0.63763427734375 +82881 0.5660400390625 +82882 0.4720458984375 +82883 0.40692138671875 +82884 0.3778076171875 +82885 0.376953125 +82886 0.371978759765625 +82887 0.313140869140625 +82888 0.184417724609375 +82889 0.011199951171875 +82890 -0.171051025390625 +82891 -0.33740234375 +82892 -0.47198486328125 +82893 -0.560394287109375 +82894 -0.58056640625 +82895 -0.54754638671875 +82896 -0.508575439453125 +82897 -0.459503173828125 +82898 -0.394378662109375 +82899 -0.35260009765625 +82900 -0.31170654296875 +82901 -0.197418212890625 +82902 -0.007965087890625 +82903 0.207489013671875 +82904 0.409210205078125 +82905 0.57208251953125 +82906 0.66595458984375 +82907 0.65875244140625 +82908 0.56744384765625 +82909 0.431396484375 +82910 0.29443359375 +82911 0.182464599609375 +82912 0.06365966796875 +82913 -0.075958251953125 +82914 -0.189422607421875 +82915 -0.271942138671875 +82916 -0.342529296875 +82917 -0.364166259765625 +82918 -0.327239990234375 +82919 -0.2769775390625 +82920 -0.253692626953125 +82921 -0.24365234375 +82922 -0.1983642578125 +82923 -0.116241455078125 +82924 -0.036834716796875 +82925 0.034881591796875 +82926 0.09124755859375 +82927 0.10888671875 +82928 0.125518798828125 +82929 0.15771484375 +82930 0.17828369140625 +82931 0.17108154296875 +82932 0.129974365234375 +82933 0.082427978515625 +82934 0.027679443359375 +82935 -0.065643310546875 +82936 -0.15936279296875 +82937 -0.21307373046875 +82938 -0.234649658203125 +82939 -0.2001953125 +82940 -0.119171142578125 +82941 -0.024749755859375 +82942 0.085784912109375 +82943 0.178131103515625 +82944 0.215576171875 +82945 0.211456298828125 +82946 0.17523193359375 +82947 0.128753662109375 +82948 0.1019287109375 +82949 0.0743408203125 +82950 0.04327392578125 +82951 0.038177490234375 +82952 0.076263427734375 +82953 0.14105224609375 +82954 0.186431884765625 +82955 0.188812255859375 +82956 0.1390380859375 +82957 0.041778564453125 +82958 -0.079437255859375 +82959 -0.219390869140625 +82960 -0.367828369140625 +82961 -0.494873046875 +82962 -0.556243896484375 +82963 -0.508697509765625 +82964 -0.3756103515625 +82965 -0.218902587890625 +82966 -0.063751220703125 +82967 0.091552734375 +82968 0.23602294921875 +82969 0.342987060546875 +82970 0.39520263671875 +82971 0.389373779296875 +82972 0.324249267578125 +82973 0.224090576171875 +82974 0.124267578125 +82975 0.037078857421875 +82976 -0.010101318359375 +82977 -0.019439697265625 +82978 -0.022796630859375 +82979 -0.001556396484375 +82980 0.056304931640625 +82981 0.106719970703125 +82982 0.096893310546875 +82983 0.042694091796875 +82984 -0.018035888671875 +82985 -0.07586669921875 +82986 -0.11944580078125 +82987 -0.15972900390625 +82988 -0.202606201171875 +82989 -0.24859619140625 +82990 -0.30517578125 +82991 -0.36212158203125 +82992 -0.39141845703125 +82993 -0.35528564453125 +82994 -0.249969482421875 +82995 -0.092864990234375 +82996 0.08905029296875 +82997 0.2352294921875 +82998 0.318817138671875 +82999 0.358642578125 +83000 0.347747802734375 +83001 0.28564453125 +83002 0.223175048828125 +83003 0.196746826171875 +83004 0.179840087890625 +83005 0.155548095703125 +83006 0.151214599609375 +83007 0.156951904296875 +83008 0.13177490234375 +83009 0.100799560546875 +83010 0.087127685546875 +83011 0.05487060546875 +83012 -0.009002685546875 +83013 -0.10400390625 +83014 -0.229400634765625 +83015 -0.35552978515625 +83016 -0.441925048828125 +83017 -0.473846435546875 +83018 -0.464813232421875 +83019 -0.419097900390625 +83020 -0.334320068359375 +83021 -0.227935791015625 +83022 -0.12347412109375 +83023 -0.02764892578125 +83024 0.077667236328125 +83025 0.2132568359375 +83026 0.38885498046875 +83027 0.582794189453125 +83028 0.734039306640625 +83029 0.800140380859375 +83030 0.7783203125 +83031 0.6651611328125 +83032 0.45965576171875 +83033 0.199188232421875 +83034 -0.050689697265625 +83035 -0.23297119140625 +83036 -0.33013916015625 +83037 -0.368408203125 +83038 -0.378936767578125 +83039 -0.376983642578125 +83040 -0.37969970703125 +83041 -0.391510009765625 +83042 -0.385345458984375 +83043 -0.3419189453125 +83044 -0.28289794921875 +83045 -0.251617431640625 +83046 -0.266143798828125 +83047 -0.273345947265625 +83048 -0.216796875 +83049 -0.128265380859375 +83050 -0.068145751953125 +83051 -0.0430908203125 +83052 -0.024444580078125 +83053 0.020721435546875 +83054 0.124481201171875 +83055 0.25787353515625 +83056 0.379119873046875 +83057 0.47991943359375 +83058 0.5281982421875 +83059 0.511138916015625 +83060 0.456207275390625 +83061 0.407470703125 +83062 0.383758544921875 +83063 0.35687255859375 +83064 0.31182861328125 +83065 0.250885009765625 +83066 0.1654052734375 +83067 0.035247802734375 +83068 -0.142059326171875 +83069 -0.33563232421875 +83070 -0.5345458984375 +83071 -0.72186279296875 +83072 -0.836669921875 +83073 -0.8326416015625 +83074 -0.7296142578125 +83075 -0.582550048828125 +83076 -0.440093994140625 +83077 -0.324310302734375 +83078 -0.20147705078125 +83079 -0.044647216796875 +83080 0.103973388671875 +83081 0.202392578125 +83082 0.264495849609375 +83083 0.338897705078125 +83084 0.443817138671875 +83085 0.545074462890625 +83086 0.6173095703125 +83087 0.6524658203125 +83088 0.66339111328125 +83089 0.6561279296875 +83090 0.606781005859375 +83091 0.501190185546875 +83092 0.352783203125 +83093 0.176544189453125 +83094 -0.034820556640625 +83095 -0.258209228515625 +83096 -0.44244384765625 +83097 -0.5753173828125 +83098 -0.65203857421875 +83099 -0.641632080078125 +83100 -0.562164306640625 +83101 -0.458038330078125 +83102 -0.350555419921875 +83103 -0.260528564453125 +83104 -0.192108154296875 +83105 -0.141937255859375 +83106 -0.1021728515625 +83107 -0.062896728515625 +83108 -0.011932373046875 +83109 0.062835693359375 +83110 0.148712158203125 +83111 0.241729736328125 +83112 0.34912109375 +83113 0.457305908203125 +83114 0.54388427734375 +83115 0.5728759765625 +83116 0.506591796875 +83117 0.351226806640625 +83118 0.146514892578125 +83119 -0.05523681640625 +83120 -0.21624755859375 +83121 -0.334930419921875 +83122 -0.402984619140625 +83123 -0.4412841796875 +83124 -0.49578857421875 +83125 -0.5601806640625 +83126 -0.600738525390625 +83127 -0.584228515625 +83128 -0.47930908203125 +83129 -0.27935791015625 +83130 -0.0089111328125 +83131 0.268798828125 +83132 0.482818603515625 +83133 0.60369873046875 +83134 0.650421142578125 +83135 0.66400146484375 +83136 0.6414794921875 +83137 0.572540283203125 +83138 0.498138427734375 +83139 0.439453125 +83140 0.375518798828125 +83141 0.274505615234375 +83142 0.1087646484375 +83143 -0.099395751953125 +83144 -0.3182373046875 +83145 -0.5489501953125 +83146 -0.7738037109375 +83147 -0.86383056640625 +83148 -0.870391845703125 +83149 -0.86895751953125 +83150 -0.861053466796875 +83151 -0.765869140625 +83152 -0.5301513671875 +83153 -0.214691162109375 +83154 0.137359619140625 +83155 0.474822998046875 +83156 0.76239013671875 +83157 0.867462158203125 +83158 0.870361328125 +83159 0.86480712890625 +83160 0.831817626953125 +83161 0.677581787109375 +83162 0.495880126953125 +83163 0.30767822265625 +83164 0.116180419921875 +83165 -0.110748291015625 +83166 -0.381805419921875 +83167 -0.6572265625 +83168 -0.857421875 +83169 -0.870391845703125 +83170 -0.870391845703125 +83171 -0.86444091796875 +83172 -0.85723876953125 +83173 -0.790008544921875 +83174 -0.62847900390625 +83175 -0.3956298828125 +83176 -0.126708984375 +83177 0.150115966796875 +83178 0.424041748046875 +83179 0.670623779296875 +83180 0.854522705078125 +83181 0.866485595703125 +83182 0.86920166015625 +83183 0.8653564453125 +83184 0.857147216796875 +83185 0.766845703125 +83186 0.628509521484375 +83187 0.462127685546875 +83188 0.297210693359375 +83189 0.14862060546875 +83190 -0.00537109375 +83191 -0.15753173828125 +83192 -0.31304931640625 +83193 -0.48876953125 +83194 -0.6416015625 +83195 -0.751373291015625 +83196 -0.84619140625 +83197 -0.861297607421875 +83198 -0.863250732421875 +83199 -0.856597900390625 +83200 -0.7498779296875 +83201 -0.624542236328125 +83202 -0.47808837890625 +83203 -0.253387451171875 +83204 0.003692626953125 +83205 0.2257080078125 +83206 0.427154541015625 +83207 0.643218994140625 +83208 0.855926513671875 +83209 0.870361328125 +83210 0.870361328125 +83211 0.862762451171875 +83212 0.79669189453125 +83213 0.595794677734375 +83214 0.362152099609375 +83215 0.1270751953125 +83216 -0.086944580078125 +83217 -0.2784423828125 +83218 -0.484832763671875 +83219 -0.729583740234375 +83220 -0.86688232421875 +83221 -0.870391845703125 +83222 -0.86859130859375 +83223 -0.86279296875 +83224 -0.817962646484375 +83225 -0.6116943359375 +83226 -0.3128662109375 +83227 0.039398193359375 +83228 0.422821044921875 +83229 0.805145263671875 +83230 0.870361328125 +83231 0.870361328125 +83232 0.860015869140625 +83233 0.727935791015625 +83234 0.48114013671875 +83235 0.2059326171875 +83236 -0.06103515625 +83237 -0.29913330078125 +83238 -0.516204833984375 +83239 -0.7252197265625 +83240 -0.85980224609375 +83241 -0.870391845703125 +83242 -0.870391845703125 +83243 -0.858062744140625 +83244 -0.673004150390625 +83245 -0.42694091796875 +83246 -0.2100830078125 +83247 -0.0362548828125 +83248 0.10943603515625 +83249 0.23516845703125 +83250 0.373687744140625 +83251 0.517791748046875 +83252 0.602783203125 +83253 0.635711669921875 +83254 0.655181884765625 +83255 0.65948486328125 +83256 0.651275634765625 +83257 0.61846923828125 +83258 0.53753662109375 +83259 0.404144287109375 +83260 0.22186279296875 +83261 0.003997802734375 +83262 -0.22100830078125 +83263 -0.42449951171875 +83264 -0.579833984375 +83265 -0.641876220703125 +83266 -0.6177978515625 +83267 -0.575531005859375 +83268 -0.526336669921875 +83269 -0.42645263671875 +83270 -0.2581787109375 +83271 -0.068695068359375 +83272 0.09222412109375 +83273 0.232147216796875 +83274 0.3509521484375 +83275 0.410064697265625 +83276 0.372955322265625 +83277 0.2554931640625 +83278 0.10711669921875 +83279 -0.052886962890625 +83280 -0.186279296875 +83281 -0.23291015625 +83282 -0.209442138671875 +83283 -0.174163818359375 +83284 -0.126739501953125 +83285 -0.048126220703125 +83286 0.0426025390625 +83287 0.10748291015625 +83288 0.1409912109375 +83289 0.19708251953125 +83290 0.273651123046875 +83291 0.31768798828125 +83292 0.341094970703125 +83293 0.368011474609375 +83294 0.37249755859375 +83295 0.30072021484375 +83296 0.1517333984375 +83297 -0.01470947265625 +83298 -0.1883544921875 +83299 -0.372711181640625 +83300 -0.51397705078125 +83301 -0.57177734375 +83302 -0.53948974609375 +83303 -0.43511962890625 +83304 -0.2962646484375 +83305 -0.161102294921875 +83306 -0.0435791015625 +83307 0.060394287109375 +83308 0.13665771484375 +83309 0.170135498046875 +83310 0.16552734375 +83311 0.15728759765625 +83312 0.150787353515625 +83313 0.12200927734375 +83314 0.080108642578125 +83315 0.05126953125 +83316 0.062896728515625 +83317 0.09271240234375 +83318 0.092987060546875 +83319 0.07855224609375 +83320 0.06427001953125 +83321 0.0347900390625 +83322 -0.01171875 +83323 -0.056060791015625 +83324 -0.055511474609375 +83325 -0.010467529296875 +83326 0.02508544921875 +83327 0.025665283203125 +83328 0.017333984375 +83329 0.00189208984375 +83330 -0.03173828125 +83331 -0.071502685546875 +83332 -0.13543701171875 +83333 -0.219970703125 +83334 -0.300506591796875 +83335 -0.376312255859375 +83336 -0.416107177734375 +83337 -0.371124267578125 +83338 -0.242279052734375 +83339 -0.069732666015625 +83340 0.125640869140625 +83341 0.31268310546875 +83342 0.45501708984375 +83343 0.554779052734375 +83344 0.61065673828125 +83345 0.610931396484375 +83346 0.531463623046875 +83347 0.3883056640625 +83348 0.23468017578125 +83349 0.095245361328125 +83350 -0.00396728515625 +83351 -0.04852294921875 +83352 -0.055145263671875 +83353 -0.0758056640625 +83354 -0.138702392578125 +83355 -0.209197998046875 +83356 -0.289031982421875 +83357 -0.37884521484375 +83358 -0.456329345703125 +83359 -0.51641845703125 +83360 -0.519287109375 +83361 -0.458251953125 +83362 -0.384796142578125 +83363 -0.323699951171875 +83364 -0.269287109375 +83365 -0.1951904296875 +83366 -0.100006103515625 +83367 -0.01055908203125 +83368 0.1033935546875 +83369 0.24908447265625 +83370 0.373199462890625 +83371 0.45806884765625 +83372 0.511474609375 +83373 0.565399169921875 +83374 0.61138916015625 +83375 0.5897216796875 +83376 0.4906005859375 +83377 0.33148193359375 +83378 0.147796630859375 +83379 -0.01873779296875 +83380 -0.140289306640625 +83381 -0.191986083984375 +83382 -0.184295654296875 +83383 -0.161834716796875 +83384 -0.166595458984375 +83385 -0.19390869140625 +83386 -0.22442626953125 +83387 -0.279754638671875 +83388 -0.3389892578125 +83389 -0.3543701171875 +83390 -0.348175048828125 +83391 -0.32598876953125 +83392 -0.2581787109375 +83393 -0.139801025390625 +83394 0.014617919921875 +83395 0.144378662109375 +83396 0.221038818359375 +83397 0.27069091796875 +83398 0.294036865234375 +83399 0.311767578125 +83400 0.339141845703125 +83401 0.360260009765625 +83402 0.360504150390625 +83403 0.308380126953125 +83404 0.18170166015625 +83405 0.0047607421875 +83406 -0.17559814453125 +83407 -0.3143310546875 +83408 -0.36785888671875 +83409 -0.36248779296875 +83410 -0.343536376953125 +83411 -0.3018798828125 +83412 -0.231414794921875 +83413 -0.117645263671875 +83414 0.007049560546875 +83415 0.087982177734375 +83416 0.13946533203125 +83417 0.17425537109375 +83418 0.188201904296875 +83419 0.171234130859375 +83420 0.118438720703125 +83421 0.05706787109375 +83422 -0.010711669921875 +83423 -0.0914306640625 +83424 -0.162322998046875 +83425 -0.194549560546875 +83426 -0.1492919921875 +83427 -0.02166748046875 +83428 0.124053955078125 +83429 0.211151123046875 +83430 0.240447998046875 +83431 0.242218017578125 +83432 0.2257080078125 +83433 0.194366455078125 +83434 0.115509033203125 +83435 0.0128173828125 +83436 -0.053802490234375 +83437 -0.110626220703125 +83438 -0.199493408203125 +83439 -0.29437255859375 +83440 -0.33221435546875 +83441 -0.27972412109375 +83442 -0.185333251953125 +83443 -0.128204345703125 +83444 -0.115692138671875 +83445 -0.116455078125 +83446 -0.105926513671875 +83447 -0.053955078125 +83448 0.048797607421875 +83449 0.157318115234375 +83450 0.212005615234375 +83451 0.218475341796875 +83452 0.23724365234375 +83453 0.30535888671875 +83454 0.38128662109375 +83455 0.404449462890625 +83456 0.3944091796875 +83457 0.3885498046875 +83458 0.362640380859375 +83459 0.27362060546875 +83460 0.11712646484375 +83461 -0.054901123046875 +83462 -0.19085693359375 +83463 -0.28570556640625 +83464 -0.339263916015625 +83465 -0.3775634765625 +83466 -0.445709228515625 +83467 -0.535064697265625 +83468 -0.629058837890625 +83469 -0.697601318359375 +83470 -0.70391845703125 +83471 -0.6424560546875 +83472 -0.491241455078125 +83473 -0.265716552734375 +83474 -0.023712158203125 +83475 0.201751708984375 +83476 0.375823974609375 +83477 0.485076904296875 +83478 0.56884765625 +83479 0.634765625 +83480 0.63763427734375 +83481 0.5660400390625 +83482 0.4720458984375 +83483 0.40692138671875 +83484 0.3778076171875 +83485 0.376953125 +83486 0.371978759765625 +83487 0.313140869140625 +83488 0.184417724609375 +83489 0.011199951171875 +83490 -0.171051025390625 +83491 -0.33740234375 +83492 -0.47198486328125 +83493 -0.560394287109375 +83494 -0.58056640625 +83495 -0.54754638671875 +83496 -0.508575439453125 +83497 -0.459503173828125 +83498 -0.394378662109375 +83499 -0.35260009765625 +83500 -0.31170654296875 +83501 -0.197418212890625 +83502 -0.007965087890625 +83503 0.207489013671875 +83504 0.409210205078125 +83505 0.57208251953125 +83506 0.66595458984375 +83507 0.65875244140625 +83508 0.56744384765625 +83509 0.431396484375 +83510 0.29443359375 +83511 0.182464599609375 +83512 0.06365966796875 +83513 -0.075958251953125 +83514 -0.189422607421875 +83515 -0.271942138671875 +83516 -0.342529296875 +83517 -0.364166259765625 +83518 -0.327239990234375 +83519 -0.2769775390625 +83520 -0.253692626953125 +83521 -0.24365234375 +83522 -0.1983642578125 +83523 -0.116241455078125 +83524 -0.036834716796875 +83525 0.034881591796875 +83526 0.09124755859375 +83527 0.10888671875 +83528 0.125518798828125 +83529 0.15771484375 +83530 0.17828369140625 +83531 0.17108154296875 +83532 0.129974365234375 +83533 0.082427978515625 +83534 0.027679443359375 +83535 -0.065643310546875 +83536 -0.15936279296875 +83537 -0.21307373046875 +83538 -0.234649658203125 +83539 -0.2001953125 +83540 -0.119171142578125 +83541 -0.024749755859375 +83542 0.085784912109375 +83543 0.178131103515625 +83544 0.215576171875 +83545 0.211456298828125 +83546 0.17523193359375 +83547 0.128753662109375 +83548 0.1019287109375 +83549 0.0743408203125 +83550 0.04327392578125 +83551 0.038177490234375 +83552 0.076263427734375 +83553 0.14105224609375 +83554 0.186431884765625 +83555 0.188812255859375 +83556 0.1390380859375 +83557 0.041778564453125 +83558 -0.079437255859375 +83559 -0.219390869140625 +83560 -0.367828369140625 +83561 -0.494873046875 +83562 -0.556243896484375 +83563 -0.508697509765625 +83564 -0.3756103515625 +83565 -0.218902587890625 +83566 -0.063751220703125 +83567 0.091552734375 +83568 0.23602294921875 +83569 0.342987060546875 +83570 0.39520263671875 +83571 0.389373779296875 +83572 0.324249267578125 +83573 0.224090576171875 +83574 0.124267578125 +83575 0.037078857421875 +83576 -0.010101318359375 +83577 -0.019439697265625 +83578 -0.022796630859375 +83579 -0.001556396484375 +83580 0.056304931640625 +83581 0.106719970703125 +83582 0.096893310546875 +83583 0.042694091796875 +83584 -0.018035888671875 +83585 -0.07586669921875 +83586 -0.11944580078125 +83587 -0.15972900390625 +83588 -0.202606201171875 +83589 -0.24859619140625 +83590 -0.30517578125 +83591 -0.36212158203125 +83592 -0.39141845703125 +83593 -0.35528564453125 +83594 -0.249969482421875 +83595 -0.092864990234375 +83596 0.08905029296875 +83597 0.2352294921875 +83598 0.318817138671875 +83599 0.358642578125 +83600 0.347747802734375 +83601 0.28564453125 +83602 0.223175048828125 +83603 0.196746826171875 +83604 0.179840087890625 +83605 0.155548095703125 +83606 0.151214599609375 +83607 0.156951904296875 +83608 0.13177490234375 +83609 0.100799560546875 +83610 0.087127685546875 +83611 0.05487060546875 +83612 -0.009002685546875 +83613 -0.10400390625 +83614 -0.229400634765625 +83615 -0.35552978515625 +83616 -0.441925048828125 +83617 -0.473846435546875 +83618 -0.464813232421875 +83619 -0.419097900390625 +83620 -0.334320068359375 +83621 -0.227935791015625 +83622 -0.12347412109375 +83623 -0.02764892578125 +83624 0.077667236328125 +83625 0.2132568359375 +83626 0.38885498046875 +83627 0.582794189453125 +83628 0.734039306640625 +83629 0.800140380859375 +83630 0.7783203125 +83631 0.6651611328125 +83632 0.45965576171875 +83633 0.199188232421875 +83634 -0.050689697265625 +83635 -0.23297119140625 +83636 -0.33013916015625 +83637 -0.368408203125 +83638 -0.378936767578125 +83639 -0.376983642578125 +83640 -0.37969970703125 +83641 -0.391510009765625 +83642 -0.385345458984375 +83643 -0.3419189453125 +83644 -0.28289794921875 +83645 -0.251617431640625 +83646 -0.266143798828125 +83647 -0.273345947265625 +83648 -0.216796875 +83649 -0.128265380859375 +83650 -0.068145751953125 +83651 -0.0430908203125 +83652 -0.024444580078125 +83653 0.020721435546875 +83654 0.124481201171875 +83655 0.25787353515625 +83656 0.379119873046875 +83657 0.47991943359375 +83658 0.5281982421875 +83659 0.511138916015625 +83660 0.456207275390625 +83661 0.407470703125 +83662 0.383758544921875 +83663 0.35687255859375 +83664 0.31182861328125 +83665 0.250885009765625 +83666 0.1654052734375 +83667 0.035247802734375 +83668 -0.142059326171875 +83669 -0.33563232421875 +83670 -0.5345458984375 +83671 -0.72186279296875 +83672 -0.836669921875 +83673 -0.8326416015625 +83674 -0.7296142578125 +83675 -0.582550048828125 +83676 -0.440093994140625 +83677 -0.324310302734375 +83678 -0.20147705078125 +83679 -0.044647216796875 +83680 0.103973388671875 +83681 0.202392578125 +83682 0.264495849609375 +83683 0.338897705078125 +83684 0.443817138671875 +83685 0.545074462890625 +83686 0.6173095703125 +83687 0.6524658203125 +83688 0.66339111328125 +83689 0.6561279296875 +83690 0.606781005859375 +83691 0.501190185546875 +83692 0.352783203125 +83693 0.176544189453125 +83694 -0.034820556640625 +83695 -0.258209228515625 +83696 -0.44244384765625 +83697 -0.5753173828125 +83698 -0.65203857421875 +83699 -0.641632080078125 +83700 -0.562164306640625 +83701 -0.458038330078125 +83702 -0.350555419921875 +83703 -0.260528564453125 +83704 -0.192108154296875 +83705 -0.141937255859375 +83706 -0.1021728515625 +83707 -0.062896728515625 +83708 -0.011932373046875 +83709 0.062835693359375 +83710 0.148712158203125 +83711 0.241729736328125 +83712 0.34912109375 +83713 0.457305908203125 +83714 0.54388427734375 +83715 0.5728759765625 +83716 0.506591796875 +83717 0.351226806640625 +83718 0.146514892578125 +83719 -0.05523681640625 +83720 -0.21624755859375 +83721 -0.334930419921875 +83722 -0.402984619140625 +83723 -0.4412841796875 +83724 -0.49578857421875 +83725 -0.5601806640625 +83726 -0.600738525390625 +83727 -0.584228515625 +83728 -0.47930908203125 +83729 -0.27935791015625 +83730 -0.0089111328125 +83731 0.268798828125 +83732 0.482818603515625 +83733 0.60369873046875 +83734 0.650421142578125 +83735 0.66400146484375 +83736 0.6414794921875 +83737 0.572540283203125 +83738 0.498138427734375 +83739 0.439453125 +83740 0.375518798828125 +83741 0.274505615234375 +83742 0.1087646484375 +83743 -0.099395751953125 +83744 -0.3182373046875 +83745 -0.5489501953125 +83746 -0.7738037109375 +83747 -0.86383056640625 +83748 -0.870391845703125 +83749 -0.86895751953125 +83750 -0.861053466796875 +83751 -0.765869140625 +83752 -0.5301513671875 +83753 -0.214691162109375 +83754 0.137359619140625 +83755 0.474822998046875 +83756 0.76239013671875 +83757 0.867462158203125 +83758 0.870361328125 +83759 0.86480712890625 +83760 0.831817626953125 +83761 0.677581787109375 +83762 0.495880126953125 +83763 0.30767822265625 +83764 0.116180419921875 +83765 -0.110748291015625 +83766 -0.381805419921875 +83767 -0.6572265625 +83768 -0.857421875 +83769 -0.870391845703125 +83770 -0.870391845703125 +83771 -0.86444091796875 +83772 -0.85723876953125 +83773 -0.790008544921875 +83774 -0.62847900390625 +83775 -0.3956298828125 +83776 -0.126708984375 +83777 0.150115966796875 +83778 0.424041748046875 +83779 0.670623779296875 +83780 0.854522705078125 +83781 0.866485595703125 +83782 0.86920166015625 +83783 0.8653564453125 +83784 0.857147216796875 +83785 0.766845703125 +83786 0.628509521484375 +83787 0.462127685546875 +83788 0.297210693359375 +83789 0.14862060546875 +83790 -0.00537109375 +83791 -0.15753173828125 +83792 -0.31304931640625 +83793 -0.48876953125 +83794 -0.6416015625 +83795 -0.751373291015625 +83796 -0.84619140625 +83797 -0.861297607421875 +83798 -0.863250732421875 +83799 -0.856597900390625 +83800 -0.7498779296875 +83801 -0.624542236328125 +83802 -0.47808837890625 +83803 -0.253387451171875 +83804 0.003692626953125 +83805 0.2257080078125 +83806 0.427154541015625 +83807 0.643218994140625 +83808 0.855926513671875 +83809 0.870361328125 +83810 0.870361328125 +83811 0.862762451171875 +83812 0.79669189453125 +83813 0.595794677734375 +83814 0.362152099609375 +83815 0.1270751953125 +83816 -0.086944580078125 +83817 -0.2784423828125 +83818 -0.484832763671875 +83819 -0.729583740234375 +83820 -0.86688232421875 +83821 -0.870391845703125 +83822 -0.86859130859375 +83823 -0.86279296875 +83824 -0.817962646484375 +83825 -0.6116943359375 +83826 -0.3128662109375 +83827 0.039398193359375 +83828 0.422821044921875 +83829 0.805145263671875 +83830 0.870361328125 +83831 0.870361328125 +83832 0.860015869140625 +83833 0.727935791015625 +83834 0.48114013671875 +83835 0.2059326171875 +83836 -0.06103515625 +83837 -0.29913330078125 +83838 -0.516204833984375 +83839 -0.7252197265625 +83840 -0.85980224609375 +83841 -0.870391845703125 +83842 -0.870391845703125 +83843 -0.858062744140625 +83844 -0.673004150390625 +83845 -0.42694091796875 +83846 -0.2100830078125 +83847 -0.0362548828125 +83848 0.10943603515625 +83849 0.23516845703125 +83850 0.373687744140625 +83851 0.517791748046875 +83852 0.602783203125 +83853 0.635711669921875 +83854 0.655181884765625 +83855 0.65948486328125 +83856 0.651275634765625 +83857 0.61846923828125 +83858 0.53753662109375 +83859 0.404144287109375 +83860 0.22186279296875 +83861 0.003997802734375 +83862 -0.22100830078125 +83863 -0.42449951171875 +83864 -0.579833984375 +83865 -0.641876220703125 +83866 -0.6177978515625 +83867 -0.575531005859375 +83868 -0.526336669921875 +83869 -0.42645263671875 +83870 -0.2581787109375 +83871 -0.068695068359375 +83872 0.09222412109375 +83873 0.232147216796875 +83874 0.3509521484375 +83875 0.410064697265625 +83876 0.372955322265625 +83877 0.2554931640625 +83878 0.10711669921875 +83879 -0.052886962890625 +83880 -0.186279296875 +83881 -0.23291015625 +83882 -0.209442138671875 +83883 -0.174163818359375 +83884 -0.126739501953125 +83885 -0.048126220703125 +83886 0.0426025390625 +83887 0.10748291015625 +83888 0.1409912109375 +83889 0.19708251953125 +83890 0.273651123046875 +83891 0.31768798828125 +83892 0.341094970703125 +83893 0.368011474609375 +83894 0.37249755859375 +83895 0.30072021484375 +83896 0.1517333984375 +83897 -0.01470947265625 +83898 -0.1883544921875 +83899 -0.372711181640625 +83900 -0.51397705078125 +83901 -0.57177734375 +83902 -0.53948974609375 +83903 -0.43511962890625 +83904 -0.2962646484375 +83905 -0.161102294921875 +83906 -0.0435791015625 +83907 0.060394287109375 +83908 0.13665771484375 +83909 0.170135498046875 +83910 0.16552734375 +83911 0.15728759765625 +83912 0.150787353515625 +83913 0.12200927734375 +83914 0.080108642578125 +83915 0.05126953125 +83916 0.062896728515625 +83917 0.09271240234375 +83918 0.092987060546875 +83919 0.07855224609375 +83920 0.06427001953125 +83921 0.0347900390625 +83922 -0.01171875 +83923 -0.056060791015625 +83924 -0.055511474609375 +83925 -0.010467529296875 +83926 0.02508544921875 +83927 0.025665283203125 +83928 0.017333984375 +83929 0.00189208984375 +83930 -0.03173828125 +83931 -0.071502685546875 +83932 -0.13543701171875 +83933 -0.219970703125 +83934 -0.300506591796875 +83935 -0.376312255859375 +83936 -0.416107177734375 +83937 -0.371124267578125 +83938 -0.242279052734375 +83939 -0.069732666015625 +83940 0.125640869140625 +83941 0.31268310546875 +83942 0.45501708984375 +83943 0.554779052734375 +83944 0.61065673828125 +83945 0.610931396484375 +83946 0.531463623046875 +83947 0.3883056640625 +83948 0.23468017578125 +83949 0.095245361328125 +83950 -0.00396728515625 +83951 -0.04852294921875 +83952 -0.055145263671875 +83953 -0.0758056640625 +83954 -0.138702392578125 +83955 -0.209197998046875 +83956 -0.289031982421875 +83957 -0.37884521484375 +83958 -0.456329345703125 +83959 -0.51641845703125 +83960 -0.519287109375 +83961 -0.458251953125 +83962 -0.384796142578125 +83963 -0.323699951171875 +83964 -0.269287109375 +83965 -0.1951904296875 +83966 -0.100006103515625 +83967 -0.01055908203125 +83968 0.1033935546875 +83969 0.24908447265625 +83970 0.373199462890625 +83971 0.45806884765625 +83972 0.511474609375 +83973 0.565399169921875 +83974 0.61138916015625 +83975 0.5897216796875 +83976 0.4906005859375 +83977 0.33148193359375 +83978 0.147796630859375 +83979 -0.01873779296875 +83980 -0.140289306640625 +83981 -0.191986083984375 +83982 -0.184295654296875 +83983 -0.161834716796875 +83984 -0.166595458984375 +83985 -0.19390869140625 +83986 -0.22442626953125 +83987 -0.279754638671875 +83988 -0.3389892578125 +83989 -0.3543701171875 +83990 -0.348175048828125 +83991 -0.32598876953125 +83992 -0.2581787109375 +83993 -0.139801025390625 +83994 0.014617919921875 +83995 0.144378662109375 +83996 0.221038818359375 +83997 0.27069091796875 +83998 0.294036865234375 +83999 0.311767578125 +84000 0.339141845703125 +84001 0.360260009765625 +84002 0.360504150390625 +84003 0.308380126953125 +84004 0.18170166015625 +84005 0.0047607421875 +84006 -0.17559814453125 +84007 -0.3143310546875 +84008 -0.36785888671875 +84009 -0.36248779296875 +84010 -0.343536376953125 +84011 -0.3018798828125 +84012 -0.231414794921875 +84013 -0.117645263671875 +84014 0.007049560546875 +84015 0.087982177734375 +84016 0.13946533203125 +84017 0.17425537109375 +84018 0.188201904296875 +84019 0.171234130859375 +84020 0.118438720703125 +84021 0.05706787109375 +84022 -0.010711669921875 +84023 -0.0914306640625 +84024 -0.162322998046875 +84025 -0.194549560546875 +84026 -0.1492919921875 +84027 -0.02166748046875 +84028 0.124053955078125 +84029 0.211151123046875 +84030 0.240447998046875 +84031 0.242218017578125 +84032 0.2257080078125 +84033 0.194366455078125 +84034 0.115509033203125 +84035 0.0128173828125 +84036 -0.053802490234375 +84037 -0.110626220703125 +84038 -0.199493408203125 +84039 -0.29437255859375 +84040 -0.33221435546875 +84041 -0.27972412109375 +84042 -0.185333251953125 +84043 -0.128204345703125 +84044 -0.115692138671875 +84045 -0.116455078125 +84046 -0.105926513671875 +84047 -0.053955078125 +84048 0.048797607421875 +84049 0.157318115234375 +84050 0.212005615234375 +84051 0.218475341796875 +84052 0.23724365234375 +84053 0.30535888671875 +84054 0.38128662109375 +84055 0.404449462890625 +84056 0.3944091796875 +84057 0.3885498046875 +84058 0.362640380859375 +84059 0.27362060546875 +84060 0.11712646484375 +84061 -0.054901123046875 +84062 -0.19085693359375 +84063 -0.28570556640625 +84064 -0.339263916015625 +84065 -0.3775634765625 +84066 -0.445709228515625 +84067 -0.535064697265625 +84068 -0.629058837890625 +84069 -0.697601318359375 +84070 -0.70391845703125 +84071 -0.6424560546875 +84072 -0.491241455078125 +84073 -0.265716552734375 +84074 -0.023712158203125 +84075 0.201751708984375 +84076 0.375823974609375 +84077 0.485076904296875 +84078 0.56884765625 +84079 0.634765625 +84080 0.63763427734375 +84081 0.5660400390625 +84082 0.4720458984375 +84083 0.40692138671875 +84084 0.3778076171875 +84085 0.376953125 +84086 0.371978759765625 +84087 0.313140869140625 +84088 0.184417724609375 +84089 0.011199951171875 +84090 -0.171051025390625 +84091 -0.33740234375 +84092 -0.47198486328125 +84093 -0.560394287109375 +84094 -0.58056640625 +84095 -0.54754638671875 +84096 -0.508575439453125 +84097 -0.459503173828125 +84098 -0.394378662109375 +84099 -0.35260009765625 +84100 -0.31170654296875 +84101 -0.197418212890625 +84102 -0.007965087890625 +84103 0.207489013671875 +84104 0.409210205078125 +84105 0.57208251953125 +84106 0.66595458984375 +84107 0.65875244140625 +84108 0.56744384765625 +84109 0.431396484375 +84110 0.29443359375 +84111 0.182464599609375 +84112 0.06365966796875 +84113 -0.075958251953125 +84114 -0.189422607421875 +84115 -0.271942138671875 +84116 -0.342529296875 +84117 -0.364166259765625 +84118 -0.327239990234375 +84119 -0.2769775390625 +84120 -0.253692626953125 +84121 -0.24365234375 +84122 -0.1983642578125 +84123 -0.116241455078125 +84124 -0.036834716796875 +84125 0.034881591796875 +84126 0.09124755859375 +84127 0.10888671875 +84128 0.125518798828125 +84129 0.15771484375 +84130 0.17828369140625 +84131 0.17108154296875 +84132 0.129974365234375 +84133 0.082427978515625 +84134 0.027679443359375 +84135 -0.065643310546875 +84136 -0.15936279296875 +84137 -0.21307373046875 +84138 -0.234649658203125 +84139 -0.2001953125 +84140 -0.119171142578125 +84141 -0.024749755859375 +84142 0.085784912109375 +84143 0.178131103515625 +84144 0.215576171875 +84145 0.211456298828125 +84146 0.17523193359375 +84147 0.128753662109375 +84148 0.1019287109375 +84149 0.0743408203125 +84150 0.04327392578125 +84151 0.038177490234375 +84152 0.076263427734375 +84153 0.14105224609375 +84154 0.186431884765625 +84155 0.188812255859375 +84156 0.1390380859375 +84157 0.041778564453125 +84158 -0.079437255859375 +84159 -0.219390869140625 +84160 -0.367828369140625 +84161 -0.494873046875 +84162 -0.556243896484375 +84163 -0.508697509765625 +84164 -0.3756103515625 +84165 -0.218902587890625 +84166 -0.063751220703125 +84167 0.091552734375 +84168 0.23602294921875 +84169 0.342987060546875 +84170 0.39520263671875 +84171 0.389373779296875 +84172 0.324249267578125 +84173 0.224090576171875 +84174 0.124267578125 +84175 0.037078857421875 +84176 -0.010101318359375 +84177 -0.019439697265625 +84178 -0.022796630859375 +84179 -0.001556396484375 +84180 0.056304931640625 +84181 0.106719970703125 +84182 0.096893310546875 +84183 0.042694091796875 +84184 -0.018035888671875 +84185 -0.07586669921875 +84186 -0.11944580078125 +84187 -0.15972900390625 +84188 -0.202606201171875 +84189 -0.24859619140625 +84190 -0.30517578125 +84191 -0.36212158203125 +84192 -0.39141845703125 +84193 -0.35528564453125 +84194 -0.249969482421875 +84195 -0.092864990234375 +84196 0.08905029296875 +84197 0.2352294921875 +84198 0.318817138671875 +84199 0.358642578125 +84200 0.347747802734375 +84201 0.28564453125 +84202 0.223175048828125 +84203 0.196746826171875 +84204 0.179840087890625 +84205 0.155548095703125 +84206 0.151214599609375 +84207 0.156951904296875 +84208 0.13177490234375 +84209 0.100799560546875 +84210 0.087127685546875 +84211 0.05487060546875 +84212 -0.009002685546875 +84213 -0.10400390625 +84214 -0.229400634765625 +84215 -0.35552978515625 +84216 -0.441925048828125 +84217 -0.473846435546875 +84218 -0.464813232421875 +84219 -0.419097900390625 +84220 -0.334320068359375 +84221 -0.227935791015625 +84222 -0.12347412109375 +84223 -0.02764892578125 +84224 0.077667236328125 +84225 0.2132568359375 +84226 0.38885498046875 +84227 0.582794189453125 +84228 0.734039306640625 +84229 0.800140380859375 +84230 0.7783203125 +84231 0.6651611328125 +84232 0.45965576171875 +84233 0.199188232421875 +84234 -0.050689697265625 +84235 -0.23297119140625 +84236 -0.33013916015625 +84237 -0.368408203125 +84238 -0.378936767578125 +84239 -0.376983642578125 +84240 -0.37969970703125 +84241 -0.391510009765625 +84242 -0.385345458984375 +84243 -0.3419189453125 +84244 -0.28289794921875 +84245 -0.251617431640625 +84246 -0.266143798828125 +84247 -0.273345947265625 +84248 -0.216796875 +84249 -0.128265380859375 +84250 -0.068145751953125 +84251 -0.0430908203125 +84252 -0.024444580078125 +84253 0.020721435546875 +84254 0.124481201171875 +84255 0.25787353515625 +84256 0.379119873046875 +84257 0.47991943359375 +84258 0.5281982421875 +84259 0.511138916015625 +84260 0.456207275390625 +84261 0.407470703125 +84262 0.383758544921875 +84263 0.35687255859375 +84264 0.31182861328125 +84265 0.250885009765625 +84266 0.1654052734375 +84267 0.035247802734375 +84268 -0.142059326171875 +84269 -0.33563232421875 +84270 -0.5345458984375 +84271 -0.72186279296875 +84272 -0.836669921875 +84273 -0.8326416015625 +84274 -0.7296142578125 +84275 -0.582550048828125 +84276 -0.440093994140625 +84277 -0.324310302734375 +84278 -0.20147705078125 +84279 -0.044647216796875 +84280 0.103973388671875 +84281 0.202392578125 +84282 0.264495849609375 +84283 0.338897705078125 +84284 0.443817138671875 +84285 0.545074462890625 +84286 0.6173095703125 +84287 0.6524658203125 +84288 0.66339111328125 +84289 0.6561279296875 +84290 0.606781005859375 +84291 0.501190185546875 +84292 0.352783203125 +84293 0.176544189453125 +84294 -0.034820556640625 +84295 -0.258209228515625 +84296 -0.44244384765625 +84297 -0.5753173828125 +84298 -0.65203857421875 +84299 -0.641632080078125 +84300 -0.562164306640625 +84301 -0.458038330078125 +84302 -0.350555419921875 +84303 -0.260528564453125 +84304 -0.192108154296875 +84305 -0.141937255859375 +84306 -0.1021728515625 +84307 -0.062896728515625 +84308 -0.011932373046875 +84309 0.062835693359375 +84310 0.148712158203125 +84311 0.241729736328125 +84312 0.34912109375 +84313 0.457305908203125 +84314 0.54388427734375 +84315 0.5728759765625 +84316 0.506591796875 +84317 0.351226806640625 +84318 0.146514892578125 +84319 -0.05523681640625 +84320 -0.21624755859375 +84321 -0.334930419921875 +84322 -0.402984619140625 +84323 -0.4412841796875 +84324 -0.49578857421875 +84325 -0.5601806640625 +84326 -0.600738525390625 +84327 -0.584228515625 +84328 -0.47930908203125 +84329 -0.27935791015625 +84330 -0.0089111328125 +84331 0.268798828125 +84332 0.482818603515625 +84333 0.60369873046875 +84334 0.650421142578125 +84335 0.66400146484375 +84336 0.6414794921875 +84337 0.572540283203125 +84338 0.498138427734375 +84339 0.439453125 +84340 0.375518798828125 +84341 0.274505615234375 +84342 0.1087646484375 +84343 -0.099395751953125 +84344 -0.3182373046875 +84345 -0.5489501953125 +84346 -0.7738037109375 +84347 -0.86383056640625 +84348 -0.870391845703125 +84349 -0.86895751953125 +84350 -0.861053466796875 +84351 -0.765869140625 +84352 -0.5301513671875 +84353 -0.214691162109375 +84354 0.137359619140625 +84355 0.474822998046875 +84356 0.76239013671875 +84357 0.867462158203125 +84358 0.870361328125 +84359 0.86480712890625 +84360 0.831817626953125 +84361 0.677581787109375 +84362 0.495880126953125 +84363 0.30767822265625 +84364 0.116180419921875 +84365 -0.110748291015625 +84366 -0.381805419921875 +84367 -0.6572265625 +84368 -0.857421875 +84369 -0.870391845703125 +84370 -0.870391845703125 +84371 -0.86444091796875 +84372 -0.85723876953125 +84373 -0.790008544921875 +84374 -0.62847900390625 +84375 -0.3956298828125 +84376 -0.126708984375 +84377 0.150115966796875 +84378 0.424041748046875 +84379 0.670623779296875 +84380 0.854522705078125 +84381 0.866485595703125 +84382 0.86920166015625 +84383 0.8653564453125 +84384 0.857147216796875 +84385 0.766845703125 +84386 0.628509521484375 +84387 0.462127685546875 +84388 0.297210693359375 +84389 0.14862060546875 +84390 -0.00537109375 +84391 -0.15753173828125 +84392 -0.31304931640625 +84393 -0.48876953125 +84394 -0.6416015625 +84395 -0.751373291015625 +84396 -0.84619140625 +84397 -0.861297607421875 +84398 -0.863250732421875 +84399 -0.856597900390625 +84400 -0.7498779296875 +84401 -0.624542236328125 +84402 -0.47808837890625 +84403 -0.253387451171875 +84404 0.003692626953125 +84405 0.2257080078125 +84406 0.427154541015625 +84407 0.643218994140625 +84408 0.855926513671875 +84409 0.870361328125 +84410 0.870361328125 +84411 0.862762451171875 +84412 0.79669189453125 +84413 0.595794677734375 +84414 0.362152099609375 +84415 0.1270751953125 +84416 -0.086944580078125 +84417 -0.2784423828125 +84418 -0.484832763671875 +84419 -0.729583740234375 +84420 -0.86688232421875 +84421 -0.870391845703125 +84422 -0.86859130859375 +84423 -0.86279296875 +84424 -0.817962646484375 +84425 -0.6116943359375 +84426 -0.3128662109375 +84427 0.039398193359375 +84428 0.422821044921875 +84429 0.805145263671875 +84430 0.870361328125 +84431 0.870361328125 +84432 0.860015869140625 +84433 0.727935791015625 +84434 0.48114013671875 +84435 0.2059326171875 +84436 -0.06103515625 +84437 -0.29913330078125 +84438 -0.516204833984375 +84439 -0.7252197265625 +84440 -0.85980224609375 +84441 -0.870391845703125 +84442 -0.870391845703125 +84443 -0.858062744140625 +84444 -0.673004150390625 +84445 -0.42694091796875 +84446 -0.2100830078125 +84447 -0.0362548828125 +84448 0.10943603515625 +84449 0.23516845703125 +84450 0.373687744140625 +84451 0.517791748046875 +84452 0.602783203125 +84453 0.635711669921875 +84454 0.655181884765625 +84455 0.65948486328125 +84456 0.651275634765625 +84457 0.61846923828125 +84458 0.53753662109375 +84459 0.404144287109375 +84460 0.22186279296875 +84461 0.003997802734375 +84462 -0.22100830078125 +84463 -0.42449951171875 +84464 -0.579833984375 +84465 -0.641876220703125 +84466 -0.6177978515625 +84467 -0.575531005859375 +84468 -0.526336669921875 +84469 -0.42645263671875 +84470 -0.2581787109375 +84471 -0.068695068359375 +84472 0.09222412109375 +84473 0.232147216796875 +84474 0.3509521484375 +84475 0.410064697265625 +84476 0.372955322265625 +84477 0.2554931640625 +84478 0.10711669921875 +84479 -0.052886962890625 +84480 -0.186279296875 +84481 -0.23291015625 +84482 -0.209442138671875 +84483 -0.174163818359375 +84484 -0.126739501953125 +84485 -0.048126220703125 +84486 0.0426025390625 +84487 0.10748291015625 +84488 0.1409912109375 +84489 0.19708251953125 +84490 0.273651123046875 +84491 0.31768798828125 +84492 0.341094970703125 +84493 0.368011474609375 +84494 0.37249755859375 +84495 0.30072021484375 +84496 0.1517333984375 +84497 -0.01470947265625 +84498 -0.1883544921875 +84499 -0.372711181640625 +84500 -0.51397705078125 +84501 -0.57177734375 +84502 -0.53948974609375 +84503 -0.43511962890625 +84504 -0.2962646484375 +84505 -0.161102294921875 +84506 -0.0435791015625 +84507 0.060394287109375 +84508 0.13665771484375 +84509 0.170135498046875 +84510 0.16552734375 +84511 0.15728759765625 +84512 0.150787353515625 +84513 0.12200927734375 +84514 0.080108642578125 +84515 0.05126953125 +84516 0.062896728515625 +84517 0.09271240234375 +84518 0.092987060546875 +84519 0.07855224609375 +84520 0.06427001953125 +84521 0.0347900390625 +84522 -0.01171875 +84523 -0.056060791015625 +84524 -0.055511474609375 +84525 -0.010467529296875 +84526 0.02508544921875 +84527 0.025665283203125 +84528 0.017333984375 +84529 0.00189208984375 +84530 -0.03173828125 +84531 -0.071502685546875 +84532 -0.13543701171875 +84533 -0.219970703125 +84534 -0.300506591796875 +84535 -0.376312255859375 +84536 -0.416107177734375 +84537 -0.371124267578125 +84538 -0.242279052734375 +84539 -0.069732666015625 +84540 0.125640869140625 +84541 0.31268310546875 +84542 0.45501708984375 +84543 0.554779052734375 +84544 0.61065673828125 +84545 0.610931396484375 +84546 0.531463623046875 +84547 0.3883056640625 +84548 0.23468017578125 +84549 0.095245361328125 +84550 -0.00396728515625 +84551 -0.04852294921875 +84552 -0.055145263671875 +84553 -0.0758056640625 +84554 -0.138702392578125 +84555 -0.209197998046875 +84556 -0.289031982421875 +84557 -0.37884521484375 +84558 -0.456329345703125 +84559 -0.51641845703125 +84560 -0.519287109375 +84561 -0.458251953125 +84562 -0.384796142578125 +84563 -0.323699951171875 +84564 -0.269287109375 +84565 -0.1951904296875 +84566 -0.100006103515625 +84567 -0.01055908203125 +84568 0.1033935546875 +84569 0.24908447265625 +84570 0.373199462890625 +84571 0.45806884765625 +84572 0.511474609375 +84573 0.565399169921875 +84574 0.61138916015625 +84575 0.5897216796875 +84576 0.4906005859375 +84577 0.33148193359375 +84578 0.147796630859375 +84579 -0.01873779296875 +84580 -0.140289306640625 +84581 -0.191986083984375 +84582 -0.184295654296875 +84583 -0.161834716796875 +84584 -0.166595458984375 +84585 -0.19390869140625 +84586 -0.22442626953125 +84587 -0.279754638671875 +84588 -0.3389892578125 +84589 -0.3543701171875 +84590 -0.348175048828125 +84591 -0.32598876953125 +84592 -0.2581787109375 +84593 -0.139801025390625 +84594 0.014617919921875 +84595 0.144378662109375 +84596 0.221038818359375 +84597 0.27069091796875 +84598 0.294036865234375 +84599 0.311767578125 +84600 0.339141845703125 +84601 0.360260009765625 +84602 0.360504150390625 +84603 0.308380126953125 +84604 0.18170166015625 +84605 0.0047607421875 +84606 -0.17559814453125 +84607 -0.3143310546875 +84608 -0.36785888671875 +84609 -0.36248779296875 +84610 -0.343536376953125 +84611 -0.3018798828125 +84612 -0.231414794921875 +84613 -0.117645263671875 +84614 0.007049560546875 +84615 0.087982177734375 +84616 0.13946533203125 +84617 0.17425537109375 +84618 0.188201904296875 +84619 0.171234130859375 +84620 0.118438720703125 +84621 0.05706787109375 +84622 -0.010711669921875 +84623 -0.0914306640625 +84624 -0.162322998046875 +84625 -0.194549560546875 +84626 -0.1492919921875 +84627 -0.02166748046875 +84628 0.124053955078125 +84629 0.211151123046875 +84630 0.240447998046875 +84631 0.242218017578125 +84632 0.2257080078125 +84633 0.194366455078125 +84634 0.115509033203125 +84635 0.0128173828125 +84636 -0.053802490234375 +84637 -0.110626220703125 +84638 -0.199493408203125 +84639 -0.29437255859375 +84640 -0.33221435546875 +84641 -0.27972412109375 +84642 -0.185333251953125 +84643 -0.128204345703125 +84644 -0.115692138671875 +84645 -0.116455078125 +84646 -0.105926513671875 +84647 -0.053955078125 +84648 0.048797607421875 +84649 0.157318115234375 +84650 0.212005615234375 +84651 0.218475341796875 +84652 0.23724365234375 +84653 0.30535888671875 +84654 0.38128662109375 +84655 0.404449462890625 +84656 0.3944091796875 +84657 0.3885498046875 +84658 0.362640380859375 +84659 0.27362060546875 +84660 0.11712646484375 +84661 -0.054901123046875 +84662 -0.19085693359375 +84663 -0.28570556640625 +84664 -0.339263916015625 +84665 -0.3775634765625 +84666 -0.445709228515625 +84667 -0.535064697265625 +84668 -0.629058837890625 +84669 -0.697601318359375 +84670 -0.70391845703125 +84671 -0.6424560546875 +84672 -0.491241455078125 +84673 -0.265716552734375 +84674 -0.023712158203125 +84675 0.201751708984375 +84676 0.375823974609375 +84677 0.485076904296875 +84678 0.56884765625 +84679 0.634765625 +84680 0.63763427734375 +84681 0.5660400390625 +84682 0.4720458984375 +84683 0.40692138671875 +84684 0.3778076171875 +84685 0.376953125 +84686 0.371978759765625 +84687 0.313140869140625 +84688 0.184417724609375 +84689 0.011199951171875 +84690 -0.171051025390625 +84691 -0.33740234375 +84692 -0.47198486328125 +84693 -0.560394287109375 +84694 -0.58056640625 +84695 -0.54754638671875 +84696 -0.508575439453125 +84697 -0.459503173828125 +84698 -0.394378662109375 +84699 -0.35260009765625 +84700 -0.31170654296875 +84701 -0.197418212890625 +84702 -0.007965087890625 +84703 0.207489013671875 +84704 0.409210205078125 +84705 0.57208251953125 +84706 0.66595458984375 +84707 0.65875244140625 +84708 0.56744384765625 +84709 0.431396484375 +84710 0.29443359375 +84711 0.182464599609375 +84712 0.06365966796875 +84713 -0.075958251953125 +84714 -0.189422607421875 +84715 -0.271942138671875 +84716 -0.342529296875 +84717 -0.364166259765625 +84718 -0.327239990234375 +84719 -0.2769775390625 +84720 -0.253692626953125 +84721 -0.24365234375 +84722 -0.1983642578125 +84723 -0.116241455078125 +84724 -0.036834716796875 +84725 0.034881591796875 +84726 0.09124755859375 +84727 0.10888671875 +84728 0.125518798828125 +84729 0.15771484375 +84730 0.17828369140625 +84731 0.17108154296875 +84732 0.129974365234375 +84733 0.082427978515625 +84734 0.027679443359375 +84735 -0.065643310546875 +84736 -0.15936279296875 +84737 -0.21307373046875 +84738 -0.234649658203125 +84739 -0.2001953125 +84740 -0.119171142578125 +84741 -0.024749755859375 +84742 0.085784912109375 +84743 0.178131103515625 +84744 0.215576171875 +84745 0.211456298828125 +84746 0.17523193359375 +84747 0.128753662109375 +84748 0.1019287109375 +84749 0.0743408203125 +84750 0.04327392578125 +84751 0.038177490234375 +84752 0.076263427734375 +84753 0.14105224609375 +84754 0.186431884765625 +84755 0.188812255859375 +84756 0.1390380859375 +84757 0.041778564453125 +84758 -0.079437255859375 +84759 -0.219390869140625 +84760 -0.367828369140625 +84761 -0.494873046875 +84762 -0.556243896484375 +84763 -0.508697509765625 +84764 -0.3756103515625 +84765 -0.218902587890625 +84766 -0.063751220703125 +84767 0.091552734375 +84768 0.23602294921875 +84769 0.342987060546875 +84770 0.39520263671875 +84771 0.389373779296875 +84772 0.324249267578125 +84773 0.224090576171875 +84774 0.124267578125 +84775 0.037078857421875 +84776 -0.010101318359375 +84777 -0.019439697265625 +84778 -0.022796630859375 +84779 -0.001556396484375 +84780 0.056304931640625 +84781 0.106719970703125 +84782 0.096893310546875 +84783 0.042694091796875 +84784 -0.018035888671875 +84785 -0.07586669921875 +84786 -0.11944580078125 +84787 -0.15972900390625 +84788 -0.202606201171875 +84789 -0.24859619140625 +84790 -0.30517578125 +84791 -0.36212158203125 +84792 -0.39141845703125 +84793 -0.35528564453125 +84794 -0.249969482421875 +84795 -0.092864990234375 +84796 0.08905029296875 +84797 0.2352294921875 +84798 0.318817138671875 +84799 0.358642578125 +84800 0.347747802734375 +84801 0.28564453125 +84802 0.223175048828125 +84803 0.196746826171875 +84804 0.179840087890625 +84805 0.155548095703125 +84806 0.151214599609375 +84807 0.156951904296875 +84808 0.13177490234375 +84809 0.100799560546875 +84810 0.087127685546875 +84811 0.05487060546875 +84812 -0.009002685546875 +84813 -0.10400390625 +84814 -0.229400634765625 +84815 -0.35552978515625 +84816 -0.441925048828125 +84817 -0.473846435546875 +84818 -0.464813232421875 +84819 -0.419097900390625 +84820 -0.334320068359375 +84821 -0.227935791015625 +84822 -0.12347412109375 +84823 -0.02764892578125 +84824 0.077667236328125 +84825 0.2132568359375 +84826 0.38885498046875 +84827 0.582794189453125 +84828 0.734039306640625 +84829 0.800140380859375 +84830 0.7783203125 +84831 0.6651611328125 +84832 0.45965576171875 +84833 0.199188232421875 +84834 -0.050689697265625 +84835 -0.23297119140625 +84836 -0.33013916015625 +84837 -0.368408203125 +84838 -0.378936767578125 +84839 -0.376983642578125 +84840 -0.37969970703125 +84841 -0.391510009765625 +84842 -0.385345458984375 +84843 -0.3419189453125 +84844 -0.28289794921875 +84845 -0.251617431640625 +84846 -0.266143798828125 +84847 -0.273345947265625 +84848 -0.216796875 +84849 -0.128265380859375 +84850 -0.068145751953125 +84851 -0.0430908203125 +84852 -0.024444580078125 +84853 0.020721435546875 +84854 0.124481201171875 +84855 0.25787353515625 +84856 0.379119873046875 +84857 0.47991943359375 +84858 0.5281982421875 +84859 0.511138916015625 +84860 0.456207275390625 +84861 0.407470703125 +84862 0.383758544921875 +84863 0.35687255859375 +84864 0.31182861328125 +84865 0.250885009765625 +84866 0.1654052734375 +84867 0.035247802734375 +84868 -0.142059326171875 +84869 -0.33563232421875 +84870 -0.5345458984375 +84871 -0.72186279296875 +84872 -0.836669921875 +84873 -0.8326416015625 +84874 -0.7296142578125 +84875 -0.582550048828125 +84876 -0.440093994140625 +84877 -0.324310302734375 +84878 -0.20147705078125 +84879 -0.044647216796875 +84880 0.103973388671875 +84881 0.202392578125 +84882 0.264495849609375 +84883 0.338897705078125 +84884 0.443817138671875 +84885 0.545074462890625 +84886 0.6173095703125 +84887 0.6524658203125 +84888 0.66339111328125 +84889 0.6561279296875 +84890 0.606781005859375 +84891 0.501190185546875 +84892 0.352783203125 +84893 0.176544189453125 +84894 -0.034820556640625 +84895 -0.258209228515625 +84896 -0.44244384765625 +84897 -0.5753173828125 +84898 -0.65203857421875 +84899 -0.641632080078125 +84900 -0.562164306640625 +84901 -0.458038330078125 +84902 -0.350555419921875 +84903 -0.260528564453125 +84904 -0.192108154296875 +84905 -0.141937255859375 +84906 -0.1021728515625 +84907 -0.062896728515625 +84908 -0.011932373046875 +84909 0.062835693359375 +84910 0.148712158203125 +84911 0.241729736328125 +84912 0.34912109375 +84913 0.457305908203125 +84914 0.54388427734375 +84915 0.5728759765625 +84916 0.506591796875 +84917 0.351226806640625 +84918 0.146514892578125 +84919 -0.05523681640625 +84920 -0.21624755859375 +84921 -0.334930419921875 +84922 -0.402984619140625 +84923 -0.4412841796875 +84924 -0.49578857421875 +84925 -0.5601806640625 +84926 -0.600738525390625 +84927 -0.584228515625 +84928 -0.47930908203125 +84929 -0.27935791015625 +84930 -0.0089111328125 +84931 0.268798828125 +84932 0.482818603515625 +84933 0.60369873046875 +84934 0.650421142578125 +84935 0.66400146484375 +84936 0.6414794921875 +84937 0.572540283203125 +84938 0.498138427734375 +84939 0.439453125 +84940 0.375518798828125 +84941 0.274505615234375 +84942 0.1087646484375 +84943 -0.099395751953125 +84944 -0.3182373046875 +84945 -0.5489501953125 +84946 -0.7738037109375 +84947 -0.86383056640625 +84948 -0.870391845703125 +84949 -0.86895751953125 +84950 -0.861053466796875 +84951 -0.765869140625 +84952 -0.5301513671875 +84953 -0.214691162109375 +84954 0.137359619140625 +84955 0.474822998046875 +84956 0.76239013671875 +84957 0.867462158203125 +84958 0.870361328125 +84959 0.86480712890625 +84960 0.831817626953125 +84961 0.677581787109375 +84962 0.495880126953125 +84963 0.30767822265625 +84964 0.116180419921875 +84965 -0.110748291015625 +84966 -0.381805419921875 +84967 -0.6572265625 +84968 -0.857421875 +84969 -0.870391845703125 +84970 -0.870391845703125 +84971 -0.86444091796875 +84972 -0.85723876953125 +84973 -0.790008544921875 +84974 -0.62847900390625 +84975 -0.3956298828125 +84976 -0.126708984375 +84977 0.150115966796875 +84978 0.424041748046875 +84979 0.670623779296875 +84980 0.854522705078125 +84981 0.866485595703125 +84982 0.86920166015625 +84983 0.8653564453125 +84984 0.857147216796875 +84985 0.766845703125 +84986 0.628509521484375 +84987 0.462127685546875 +84988 0.297210693359375 +84989 0.14862060546875 +84990 -0.00537109375 +84991 -0.15753173828125 +84992 -0.31304931640625 +84993 -0.48876953125 +84994 -0.6416015625 +84995 -0.751373291015625 +84996 -0.84619140625 +84997 -0.861297607421875 +84998 -0.863250732421875 +84999 -0.856597900390625 +85000 -0.7498779296875 +85001 -0.624542236328125 +85002 -0.47808837890625 +85003 -0.253387451171875 +85004 0.003692626953125 +85005 0.2257080078125 +85006 0.427154541015625 +85007 0.643218994140625 +85008 0.855926513671875 +85009 0.870361328125 +85010 0.870361328125 +85011 0.862762451171875 +85012 0.79669189453125 +85013 0.595794677734375 +85014 0.362152099609375 +85015 0.1270751953125 +85016 -0.086944580078125 +85017 -0.2784423828125 +85018 -0.484832763671875 +85019 -0.729583740234375 +85020 -0.86688232421875 +85021 -0.870391845703125 +85022 -0.86859130859375 +85023 -0.86279296875 +85024 -0.817962646484375 +85025 -0.6116943359375 +85026 -0.3128662109375 +85027 0.039398193359375 +85028 0.422821044921875 +85029 0.805145263671875 +85030 0.870361328125 +85031 0.870361328125 +85032 0.860015869140625 +85033 0.727935791015625 +85034 0.48114013671875 +85035 0.2059326171875 +85036 -0.06103515625 +85037 -0.29913330078125 +85038 -0.516204833984375 +85039 -0.7252197265625 +85040 -0.85980224609375 +85041 -0.870391845703125 +85042 -0.870391845703125 +85043 -0.858062744140625 +85044 -0.673004150390625 +85045 -0.42694091796875 +85046 -0.2100830078125 +85047 -0.0362548828125 +85048 0.10943603515625 +85049 0.23516845703125 +85050 0.373687744140625 +85051 0.517791748046875 +85052 0.602783203125 +85053 0.635711669921875 +85054 0.655181884765625 +85055 0.65948486328125 +85056 0.651275634765625 +85057 0.61846923828125 +85058 0.53753662109375 +85059 0.404144287109375 +85060 0.22186279296875 +85061 0.003997802734375 +85062 -0.22100830078125 +85063 -0.42449951171875 +85064 -0.579833984375 +85065 -0.641876220703125 +85066 -0.6177978515625 +85067 -0.575531005859375 +85068 -0.526336669921875 +85069 -0.42645263671875 +85070 -0.2581787109375 +85071 -0.068695068359375 +85072 0.09222412109375 +85073 0.232147216796875 +85074 0.3509521484375 +85075 0.410064697265625 +85076 0.372955322265625 +85077 0.2554931640625 +85078 0.10711669921875 +85079 -0.052886962890625 +85080 -0.186279296875 +85081 -0.23291015625 +85082 -0.209442138671875 +85083 -0.174163818359375 +85084 -0.126739501953125 +85085 -0.048126220703125 +85086 0.0426025390625 +85087 0.10748291015625 +85088 0.1409912109375 +85089 0.19708251953125 +85090 0.273651123046875 +85091 0.31768798828125 +85092 0.341094970703125 +85093 0.368011474609375 +85094 0.37249755859375 +85095 0.30072021484375 +85096 0.1517333984375 +85097 -0.01470947265625 +85098 -0.1883544921875 +85099 -0.372711181640625 +85100 -0.51397705078125 +85101 -0.57177734375 +85102 -0.53948974609375 +85103 -0.43511962890625 +85104 -0.2962646484375 +85105 -0.161102294921875 +85106 -0.0435791015625 +85107 0.060394287109375 +85108 0.13665771484375 +85109 0.170135498046875 +85110 0.16552734375 +85111 0.15728759765625 +85112 0.150787353515625 +85113 0.12200927734375 +85114 0.080108642578125 +85115 0.05126953125 +85116 0.062896728515625 +85117 0.09271240234375 +85118 0.092987060546875 +85119 0.07855224609375 +85120 0.06427001953125 +85121 0.0347900390625 +85122 -0.01171875 +85123 -0.056060791015625 +85124 -0.055511474609375 +85125 -0.010467529296875 +85126 0.02508544921875 +85127 0.025665283203125 +85128 0.017333984375 +85129 0.00189208984375 +85130 -0.03173828125 +85131 -0.071502685546875 +85132 -0.13543701171875 +85133 -0.219970703125 +85134 -0.300506591796875 +85135 -0.376312255859375 +85136 -0.416107177734375 +85137 -0.371124267578125 +85138 -0.242279052734375 +85139 -0.069732666015625 +85140 0.125640869140625 +85141 0.31268310546875 +85142 0.45501708984375 +85143 0.554779052734375 +85144 0.61065673828125 +85145 0.610931396484375 +85146 0.531463623046875 +85147 0.3883056640625 +85148 0.23468017578125 +85149 0.095245361328125 +85150 -0.00396728515625 +85151 -0.04852294921875 +85152 -0.055145263671875 +85153 -0.0758056640625 +85154 -0.138702392578125 +85155 -0.209197998046875 +85156 -0.289031982421875 +85157 -0.37884521484375 +85158 -0.456329345703125 +85159 -0.51641845703125 +85160 -0.519287109375 +85161 -0.458251953125 +85162 -0.384796142578125 +85163 -0.323699951171875 +85164 -0.269287109375 +85165 -0.1951904296875 +85166 -0.100006103515625 +85167 -0.01055908203125 +85168 0.1033935546875 +85169 0.24908447265625 +85170 0.373199462890625 +85171 0.45806884765625 +85172 0.511474609375 +85173 0.565399169921875 +85174 0.61138916015625 +85175 0.5897216796875 +85176 0.4906005859375 +85177 0.33148193359375 +85178 0.147796630859375 +85179 -0.01873779296875 +85180 -0.140289306640625 +85181 -0.191986083984375 +85182 -0.184295654296875 +85183 -0.161834716796875 +85184 -0.166595458984375 +85185 -0.19390869140625 +85186 -0.22442626953125 +85187 -0.279754638671875 +85188 -0.3389892578125 +85189 -0.3543701171875 +85190 -0.348175048828125 +85191 -0.32598876953125 +85192 -0.2581787109375 +85193 -0.139801025390625 +85194 0.014617919921875 +85195 0.144378662109375 +85196 0.221038818359375 +85197 0.27069091796875 +85198 0.294036865234375 +85199 0.311767578125 +85200 0.339141845703125 +85201 0.360260009765625 +85202 0.360504150390625 +85203 0.308380126953125 +85204 0.18170166015625 +85205 0.0047607421875 +85206 -0.17559814453125 +85207 -0.3143310546875 +85208 -0.36785888671875 +85209 -0.36248779296875 +85210 -0.343536376953125 +85211 -0.3018798828125 +85212 -0.231414794921875 +85213 -0.117645263671875 +85214 0.007049560546875 +85215 0.087982177734375 +85216 0.13946533203125 +85217 0.17425537109375 +85218 0.188201904296875 +85219 0.171234130859375 +85220 0.118438720703125 +85221 0.05706787109375 +85222 -0.010711669921875 +85223 -0.0914306640625 +85224 -0.162322998046875 +85225 -0.194549560546875 +85226 -0.1492919921875 +85227 -0.02166748046875 +85228 0.124053955078125 +85229 0.211151123046875 +85230 0.240447998046875 +85231 0.242218017578125 +85232 0.2257080078125 +85233 0.194366455078125 +85234 0.115509033203125 +85235 0.0128173828125 +85236 -0.053802490234375 +85237 -0.110626220703125 +85238 -0.199493408203125 +85239 -0.29437255859375 +85240 -0.33221435546875 +85241 -0.27972412109375 +85242 -0.185333251953125 +85243 -0.128204345703125 +85244 -0.115692138671875 +85245 -0.116455078125 +85246 -0.105926513671875 +85247 -0.053955078125 +85248 0.048797607421875 +85249 0.157318115234375 +85250 0.212005615234375 +85251 0.218475341796875 +85252 0.23724365234375 +85253 0.30535888671875 +85254 0.38128662109375 +85255 0.404449462890625 +85256 0.3944091796875 +85257 0.3885498046875 +85258 0.362640380859375 +85259 0.27362060546875 +85260 0.11712646484375 +85261 -0.054901123046875 +85262 -0.19085693359375 +85263 -0.28570556640625 +85264 -0.339263916015625 +85265 -0.3775634765625 +85266 -0.445709228515625 +85267 -0.535064697265625 +85268 -0.629058837890625 +85269 -0.697601318359375 +85270 -0.70391845703125 +85271 -0.6424560546875 +85272 -0.491241455078125 +85273 -0.265716552734375 +85274 -0.023712158203125 +85275 0.201751708984375 +85276 0.375823974609375 +85277 0.485076904296875 +85278 0.56884765625 +85279 0.634765625 +85280 0.63763427734375 +85281 0.5660400390625 +85282 0.4720458984375 +85283 0.40692138671875 +85284 0.3778076171875 +85285 0.376953125 +85286 0.371978759765625 +85287 0.313140869140625 +85288 0.184417724609375 +85289 0.011199951171875 +85290 -0.171051025390625 +85291 -0.33740234375 +85292 -0.47198486328125 +85293 -0.560394287109375 +85294 -0.58056640625 +85295 -0.54754638671875 +85296 -0.508575439453125 +85297 -0.459503173828125 +85298 -0.394378662109375 +85299 -0.35260009765625 +85300 -0.31170654296875 +85301 -0.197418212890625 +85302 -0.007965087890625 +85303 0.207489013671875 +85304 0.409210205078125 +85305 0.57208251953125 +85306 0.66595458984375 +85307 0.65875244140625 +85308 0.56744384765625 +85309 0.431396484375 +85310 0.29443359375 +85311 0.182464599609375 +85312 0.06365966796875 +85313 -0.075958251953125 +85314 -0.189422607421875 +85315 -0.271942138671875 +85316 -0.342529296875 +85317 -0.364166259765625 +85318 -0.327239990234375 +85319 -0.2769775390625 +85320 -0.253692626953125 +85321 -0.24365234375 +85322 -0.1983642578125 +85323 -0.116241455078125 +85324 -0.036834716796875 +85325 0.034881591796875 +85326 0.09124755859375 +85327 0.10888671875 +85328 0.125518798828125 +85329 0.15771484375 +85330 0.17828369140625 +85331 0.17108154296875 +85332 0.129974365234375 +85333 0.082427978515625 +85334 0.027679443359375 +85335 -0.065643310546875 +85336 -0.15936279296875 +85337 -0.21307373046875 +85338 -0.234649658203125 +85339 -0.2001953125 +85340 -0.119171142578125 +85341 -0.024749755859375 +85342 0.085784912109375 +85343 0.178131103515625 +85344 0.215576171875 +85345 0.211456298828125 +85346 0.17523193359375 +85347 0.128753662109375 +85348 0.1019287109375 +85349 0.0743408203125 +85350 0.04327392578125 +85351 0.038177490234375 +85352 0.076263427734375 +85353 0.14105224609375 +85354 0.186431884765625 +85355 0.188812255859375 +85356 0.1390380859375 +85357 0.041778564453125 +85358 -0.079437255859375 +85359 -0.219390869140625 +85360 -0.367828369140625 +85361 -0.494873046875 +85362 -0.556243896484375 +85363 -0.508697509765625 +85364 -0.3756103515625 +85365 -0.218902587890625 +85366 -0.063751220703125 +85367 0.091552734375 +85368 0.23602294921875 +85369 0.342987060546875 +85370 0.39520263671875 +85371 0.389373779296875 +85372 0.324249267578125 +85373 0.224090576171875 +85374 0.124267578125 +85375 0.037078857421875 +85376 -0.010101318359375 +85377 -0.019439697265625 +85378 -0.022796630859375 +85379 -0.001556396484375 +85380 0.056304931640625 +85381 0.106719970703125 +85382 0.096893310546875 +85383 0.042694091796875 +85384 -0.018035888671875 +85385 -0.07586669921875 +85386 -0.11944580078125 +85387 -0.15972900390625 +85388 -0.202606201171875 +85389 -0.24859619140625 +85390 -0.30517578125 +85391 -0.36212158203125 +85392 -0.39141845703125 +85393 -0.35528564453125 +85394 -0.249969482421875 +85395 -0.092864990234375 +85396 0.08905029296875 +85397 0.2352294921875 +85398 0.318817138671875 +85399 0.358642578125 +85400 0.347747802734375 +85401 0.28564453125 +85402 0.223175048828125 +85403 0.196746826171875 +85404 0.179840087890625 +85405 0.155548095703125 +85406 0.151214599609375 +85407 0.156951904296875 +85408 0.13177490234375 +85409 0.100799560546875 +85410 0.087127685546875 +85411 0.05487060546875 +85412 -0.009002685546875 +85413 -0.10400390625 +85414 -0.229400634765625 +85415 -0.35552978515625 +85416 -0.441925048828125 +85417 -0.473846435546875 +85418 -0.464813232421875 +85419 -0.419097900390625 +85420 -0.334320068359375 +85421 -0.227935791015625 +85422 -0.12347412109375 +85423 -0.02764892578125 +85424 0.077667236328125 +85425 0.2132568359375 +85426 0.38885498046875 +85427 0.582794189453125 +85428 0.734039306640625 +85429 0.800140380859375 +85430 0.7783203125 +85431 0.6651611328125 +85432 0.45965576171875 +85433 0.199188232421875 +85434 -0.050689697265625 +85435 -0.23297119140625 +85436 -0.33013916015625 +85437 -0.368408203125 +85438 -0.378936767578125 +85439 -0.376983642578125 +85440 -0.37969970703125 +85441 -0.391510009765625 +85442 -0.385345458984375 +85443 -0.3419189453125 +85444 -0.28289794921875 +85445 -0.251617431640625 +85446 -0.266143798828125 +85447 -0.273345947265625 +85448 -0.216796875 +85449 -0.128265380859375 +85450 -0.068145751953125 +85451 -0.0430908203125 +85452 -0.024444580078125 +85453 0.020721435546875 +85454 0.124481201171875 +85455 0.25787353515625 +85456 0.379119873046875 +85457 0.47991943359375 +85458 0.5281982421875 +85459 0.511138916015625 +85460 0.456207275390625 +85461 0.407470703125 +85462 0.383758544921875 +85463 0.35687255859375 +85464 0.31182861328125 +85465 0.250885009765625 +85466 0.1654052734375 +85467 0.035247802734375 +85468 -0.142059326171875 +85469 -0.33563232421875 +85470 -0.5345458984375 +85471 -0.72186279296875 +85472 -0.836669921875 +85473 -0.8326416015625 +85474 -0.7296142578125 +85475 -0.582550048828125 +85476 -0.440093994140625 +85477 -0.324310302734375 +85478 -0.20147705078125 +85479 -0.044647216796875 +85480 0.103973388671875 +85481 0.202392578125 +85482 0.264495849609375 +85483 0.338897705078125 +85484 0.443817138671875 +85485 0.545074462890625 +85486 0.6173095703125 +85487 0.6524658203125 +85488 0.66339111328125 +85489 0.6561279296875 +85490 0.606781005859375 +85491 0.501190185546875 +85492 0.352783203125 +85493 0.176544189453125 +85494 -0.034820556640625 +85495 -0.258209228515625 +85496 -0.44244384765625 +85497 -0.5753173828125 +85498 -0.65203857421875 +85499 -0.641632080078125 +85500 -0.562164306640625 +85501 -0.458038330078125 +85502 -0.350555419921875 +85503 -0.260528564453125 +85504 -0.192108154296875 +85505 -0.141937255859375 +85506 -0.1021728515625 +85507 -0.062896728515625 +85508 -0.011932373046875 +85509 0.062835693359375 +85510 0.148712158203125 +85511 0.241729736328125 +85512 0.34912109375 +85513 0.457305908203125 +85514 0.54388427734375 +85515 0.5728759765625 +85516 0.506591796875 +85517 0.351226806640625 +85518 0.146514892578125 +85519 -0.05523681640625 +85520 -0.21624755859375 +85521 -0.334930419921875 +85522 -0.402984619140625 +85523 -0.4412841796875 +85524 -0.49578857421875 +85525 -0.5601806640625 +85526 -0.600738525390625 +85527 -0.584228515625 +85528 -0.47930908203125 +85529 -0.27935791015625 +85530 -0.0089111328125 +85531 0.268798828125 +85532 0.482818603515625 +85533 0.60369873046875 +85534 0.650421142578125 +85535 0.66400146484375 +85536 0.6414794921875 +85537 0.572540283203125 +85538 0.498138427734375 +85539 0.439453125 +85540 0.375518798828125 +85541 0.274505615234375 +85542 0.1087646484375 +85543 -0.099395751953125 +85544 -0.3182373046875 +85545 -0.5489501953125 +85546 -0.7738037109375 +85547 -0.86383056640625 +85548 -0.870391845703125 +85549 -0.86895751953125 +85550 -0.861053466796875 +85551 -0.765869140625 +85552 -0.5301513671875 +85553 -0.214691162109375 +85554 0.137359619140625 +85555 0.474822998046875 +85556 0.76239013671875 +85557 0.867462158203125 +85558 0.870361328125 +85559 0.86480712890625 +85560 0.831817626953125 +85561 0.677581787109375 +85562 0.495880126953125 +85563 0.30767822265625 +85564 0.116180419921875 +85565 -0.110748291015625 +85566 -0.381805419921875 +85567 -0.6572265625 +85568 -0.857421875 +85569 -0.870391845703125 +85570 -0.870391845703125 +85571 -0.86444091796875 +85572 -0.85723876953125 +85573 -0.790008544921875 +85574 -0.62847900390625 +85575 -0.3956298828125 +85576 -0.126708984375 +85577 0.150115966796875 +85578 0.424041748046875 +85579 0.670623779296875 +85580 0.854522705078125 +85581 0.866485595703125 +85582 0.86920166015625 +85583 0.8653564453125 +85584 0.857147216796875 +85585 0.766845703125 +85586 0.628509521484375 +85587 0.462127685546875 +85588 0.297210693359375 +85589 0.14862060546875 +85590 -0.00537109375 +85591 -0.15753173828125 +85592 -0.31304931640625 +85593 -0.48876953125 +85594 -0.6416015625 +85595 -0.751373291015625 +85596 -0.84619140625 +85597 -0.861297607421875 +85598 -0.863250732421875 +85599 -0.856597900390625 +85600 -0.7498779296875 +85601 -0.624542236328125 +85602 -0.47808837890625 +85603 -0.253387451171875 +85604 0.003692626953125 +85605 0.2257080078125 +85606 0.427154541015625 +85607 0.643218994140625 +85608 0.855926513671875 +85609 0.870361328125 +85610 0.870361328125 +85611 0.862762451171875 +85612 0.79669189453125 +85613 0.595794677734375 +85614 0.362152099609375 +85615 0.1270751953125 +85616 -0.086944580078125 +85617 -0.2784423828125 +85618 -0.484832763671875 +85619 -0.729583740234375 +85620 -0.86688232421875 +85621 -0.870391845703125 +85622 -0.86859130859375 +85623 -0.86279296875 +85624 -0.817962646484375 +85625 -0.6116943359375 +85626 -0.3128662109375 +85627 0.039398193359375 +85628 0.422821044921875 +85629 0.805145263671875 +85630 0.870361328125 +85631 0.870361328125 +85632 0.860015869140625 +85633 0.727935791015625 +85634 0.48114013671875 +85635 0.2059326171875 +85636 -0.06103515625 +85637 -0.29913330078125 +85638 -0.516204833984375 +85639 -0.7252197265625 +85640 -0.85980224609375 +85641 -0.870391845703125 +85642 -0.870391845703125 +85643 -0.858062744140625 +85644 -0.673004150390625 +85645 -0.42694091796875 +85646 -0.2100830078125 +85647 -0.0362548828125 +85648 0.10943603515625 +85649 0.23516845703125 +85650 0.373687744140625 +85651 0.517791748046875 +85652 0.602783203125 +85653 0.635711669921875 +85654 0.655181884765625 +85655 0.65948486328125 +85656 0.651275634765625 +85657 0.61846923828125 +85658 0.53753662109375 +85659 0.404144287109375 +85660 0.22186279296875 +85661 0.003997802734375 +85662 -0.22100830078125 +85663 -0.42449951171875 +85664 -0.579833984375 +85665 -0.641876220703125 +85666 -0.6177978515625 +85667 -0.575531005859375 +85668 -0.526336669921875 +85669 -0.42645263671875 +85670 -0.2581787109375 +85671 -0.068695068359375 +85672 0.09222412109375 +85673 0.232147216796875 +85674 0.3509521484375 +85675 0.410064697265625 +85676 0.372955322265625 +85677 0.2554931640625 +85678 0.10711669921875 +85679 -0.052886962890625 +85680 -0.186279296875 +85681 -0.23291015625 +85682 -0.209442138671875 +85683 -0.174163818359375 +85684 -0.126739501953125 +85685 -0.048126220703125 +85686 0.0426025390625 +85687 0.10748291015625 +85688 0.1409912109375 +85689 0.19708251953125 +85690 0.273651123046875 +85691 0.31768798828125 +85692 0.341094970703125 +85693 0.368011474609375 +85694 0.37249755859375 +85695 0.30072021484375 +85696 0.1517333984375 +85697 -0.01470947265625 +85698 -0.1883544921875 +85699 -0.372711181640625 +85700 -0.51397705078125 +85701 -0.57177734375 +85702 -0.53948974609375 +85703 -0.43511962890625 +85704 -0.2962646484375 +85705 -0.161102294921875 +85706 -0.0435791015625 +85707 0.060394287109375 +85708 0.13665771484375 +85709 0.170135498046875 +85710 0.16552734375 +85711 0.15728759765625 +85712 0.150787353515625 +85713 0.12200927734375 +85714 0.080108642578125 +85715 0.05126953125 +85716 0.062896728515625 +85717 0.09271240234375 +85718 0.092987060546875 +85719 0.07855224609375 +85720 0.06427001953125 +85721 0.0347900390625 +85722 -0.01171875 +85723 -0.056060791015625 +85724 -0.055511474609375 +85725 -0.010467529296875 +85726 0.02508544921875 +85727 0.025665283203125 +85728 0.017333984375 +85729 0.00189208984375 +85730 -0.03173828125 +85731 -0.071502685546875 +85732 -0.13543701171875 +85733 -0.219970703125 +85734 -0.300506591796875 +85735 -0.376312255859375 +85736 -0.416107177734375 +85737 -0.371124267578125 +85738 -0.242279052734375 +85739 -0.069732666015625 +85740 0.125640869140625 +85741 0.31268310546875 +85742 0.45501708984375 +85743 0.554779052734375 +85744 0.61065673828125 +85745 0.610931396484375 +85746 0.531463623046875 +85747 0.3883056640625 +85748 0.23468017578125 +85749 0.095245361328125 +85750 -0.00396728515625 +85751 -0.04852294921875 +85752 -0.055145263671875 +85753 -0.0758056640625 +85754 -0.138702392578125 +85755 -0.209197998046875 +85756 -0.289031982421875 +85757 -0.37884521484375 +85758 -0.456329345703125 +85759 -0.51641845703125 +85760 -0.519287109375 +85761 -0.458251953125 +85762 -0.384796142578125 +85763 -0.323699951171875 +85764 -0.269287109375 +85765 -0.1951904296875 +85766 -0.100006103515625 +85767 -0.01055908203125 +85768 0.1033935546875 +85769 0.24908447265625 +85770 0.373199462890625 +85771 0.45806884765625 +85772 0.511474609375 +85773 0.565399169921875 +85774 0.61138916015625 +85775 0.5897216796875 +85776 0.4906005859375 +85777 0.33148193359375 +85778 0.147796630859375 +85779 -0.01873779296875 +85780 -0.140289306640625 +85781 -0.191986083984375 +85782 -0.184295654296875 +85783 -0.161834716796875 +85784 -0.166595458984375 +85785 -0.19390869140625 +85786 -0.22442626953125 +85787 -0.279754638671875 +85788 -0.3389892578125 +85789 -0.3543701171875 +85790 -0.348175048828125 +85791 -0.32598876953125 +85792 -0.2581787109375 +85793 -0.139801025390625 +85794 0.014617919921875 +85795 0.144378662109375 +85796 0.221038818359375 +85797 0.27069091796875 +85798 0.294036865234375 +85799 0.311767578125 +85800 0.339141845703125 +85801 0.360260009765625 +85802 0.360504150390625 +85803 0.308380126953125 +85804 0.18170166015625 +85805 0.0047607421875 +85806 -0.17559814453125 +85807 -0.3143310546875 +85808 -0.36785888671875 +85809 -0.36248779296875 +85810 -0.343536376953125 +85811 -0.3018798828125 +85812 -0.231414794921875 +85813 -0.117645263671875 +85814 0.007049560546875 +85815 0.087982177734375 +85816 0.13946533203125 +85817 0.17425537109375 +85818 0.188201904296875 +85819 0.171234130859375 +85820 0.118438720703125 +85821 0.05706787109375 +85822 -0.010711669921875 +85823 -0.0914306640625 +85824 -0.162322998046875 +85825 -0.194549560546875 +85826 -0.1492919921875 +85827 -0.02166748046875 +85828 0.124053955078125 +85829 0.211151123046875 +85830 0.240447998046875 +85831 0.242218017578125 +85832 0.2257080078125 +85833 0.194366455078125 +85834 0.115509033203125 +85835 0.0128173828125 +85836 -0.053802490234375 +85837 -0.110626220703125 +85838 -0.199493408203125 +85839 -0.29437255859375 +85840 -0.33221435546875 +85841 -0.27972412109375 +85842 -0.185333251953125 +85843 -0.128204345703125 +85844 -0.115692138671875 +85845 -0.116455078125 +85846 -0.105926513671875 +85847 -0.053955078125 +85848 0.048797607421875 +85849 0.157318115234375 +85850 0.212005615234375 +85851 0.218475341796875 +85852 0.23724365234375 +85853 0.30535888671875 +85854 0.38128662109375 +85855 0.404449462890625 +85856 0.3944091796875 +85857 0.3885498046875 +85858 0.362640380859375 +85859 0.27362060546875 +85860 0.11712646484375 +85861 -0.054901123046875 +85862 -0.19085693359375 +85863 -0.28570556640625 +85864 -0.339263916015625 +85865 -0.3775634765625 +85866 -0.445709228515625 +85867 -0.535064697265625 +85868 -0.629058837890625 +85869 -0.697601318359375 +85870 -0.70391845703125 +85871 -0.6424560546875 +85872 -0.491241455078125 +85873 -0.265716552734375 +85874 -0.023712158203125 +85875 0.201751708984375 +85876 0.375823974609375 +85877 0.485076904296875 +85878 0.56884765625 +85879 0.634765625 +85880 0.63763427734375 +85881 0.5660400390625 +85882 0.4720458984375 +85883 0.40692138671875 +85884 0.3778076171875 +85885 0.376953125 +85886 0.371978759765625 +85887 0.313140869140625 +85888 0.184417724609375 +85889 0.011199951171875 +85890 -0.171051025390625 +85891 -0.33740234375 +85892 -0.47198486328125 +85893 -0.560394287109375 +85894 -0.58056640625 +85895 -0.54754638671875 +85896 -0.508575439453125 +85897 -0.459503173828125 +85898 -0.394378662109375 +85899 -0.35260009765625 +85900 -0.31170654296875 +85901 -0.197418212890625 +85902 -0.007965087890625 +85903 0.207489013671875 +85904 0.409210205078125 +85905 0.57208251953125 +85906 0.66595458984375 +85907 0.65875244140625 +85908 0.56744384765625 +85909 0.431396484375 +85910 0.29443359375 +85911 0.182464599609375 +85912 0.06365966796875 +85913 -0.075958251953125 +85914 -0.189422607421875 +85915 -0.271942138671875 +85916 -0.342529296875 +85917 -0.364166259765625 +85918 -0.327239990234375 +85919 -0.2769775390625 +85920 -0.253692626953125 +85921 -0.24365234375 +85922 -0.1983642578125 +85923 -0.116241455078125 +85924 -0.036834716796875 +85925 0.034881591796875 +85926 0.09124755859375 +85927 0.10888671875 +85928 0.125518798828125 +85929 0.15771484375 +85930 0.17828369140625 +85931 0.17108154296875 +85932 0.129974365234375 +85933 0.082427978515625 +85934 0.027679443359375 +85935 -0.065643310546875 +85936 -0.15936279296875 +85937 -0.21307373046875 +85938 -0.234649658203125 +85939 -0.2001953125 +85940 -0.119171142578125 +85941 -0.024749755859375 +85942 0.085784912109375 +85943 0.178131103515625 +85944 0.215576171875 +85945 0.211456298828125 +85946 0.17523193359375 +85947 0.128753662109375 +85948 0.1019287109375 +85949 0.0743408203125 +85950 0.04327392578125 +85951 0.038177490234375 +85952 0.076263427734375 +85953 0.14105224609375 +85954 0.186431884765625 +85955 0.188812255859375 +85956 0.1390380859375 +85957 0.041778564453125 +85958 -0.079437255859375 +85959 -0.219390869140625 +85960 -0.367828369140625 +85961 -0.494873046875 +85962 -0.556243896484375 +85963 -0.508697509765625 +85964 -0.3756103515625 +85965 -0.218902587890625 +85966 -0.063751220703125 +85967 0.091552734375 +85968 0.23602294921875 +85969 0.342987060546875 +85970 0.39520263671875 +85971 0.389373779296875 +85972 0.324249267578125 +85973 0.224090576171875 +85974 0.124267578125 +85975 0.037078857421875 +85976 -0.010101318359375 +85977 -0.019439697265625 +85978 -0.022796630859375 +85979 -0.001556396484375 +85980 0.056304931640625 +85981 0.106719970703125 +85982 0.096893310546875 +85983 0.042694091796875 +85984 -0.018035888671875 +85985 -0.07586669921875 +85986 -0.11944580078125 +85987 -0.15972900390625 +85988 -0.202606201171875 +85989 -0.24859619140625 +85990 -0.30517578125 +85991 -0.36212158203125 +85992 -0.39141845703125 +85993 -0.35528564453125 +85994 -0.249969482421875 +85995 -0.092864990234375 +85996 0.08905029296875 +85997 0.2352294921875 +85998 0.318817138671875 +85999 0.358642578125 +86000 0.347747802734375 +86001 0.28564453125 +86002 0.223175048828125 +86003 0.196746826171875 +86004 0.179840087890625 +86005 0.155548095703125 +86006 0.151214599609375 +86007 0.156951904296875 +86008 0.13177490234375 +86009 0.100799560546875 +86010 0.087127685546875 +86011 0.05487060546875 +86012 -0.009002685546875 +86013 -0.10400390625 +86014 -0.229400634765625 +86015 -0.35552978515625 +86016 -0.441925048828125 +86017 -0.473846435546875 +86018 -0.464813232421875 +86019 -0.419097900390625 +86020 -0.334320068359375 +86021 -0.227935791015625 +86022 -0.12347412109375 +86023 -0.02764892578125 +86024 0.077667236328125 +86025 0.2132568359375 +86026 0.38885498046875 +86027 0.582794189453125 +86028 0.734039306640625 +86029 0.800140380859375 +86030 0.7783203125 +86031 0.6651611328125 +86032 0.45965576171875 +86033 0.199188232421875 +86034 -0.050689697265625 +86035 -0.23297119140625 +86036 -0.33013916015625 +86037 -0.368408203125 +86038 -0.378936767578125 +86039 -0.376983642578125 +86040 -0.37969970703125 +86041 -0.391510009765625 +86042 -0.385345458984375 +86043 -0.3419189453125 +86044 -0.28289794921875 +86045 -0.251617431640625 +86046 -0.266143798828125 +86047 -0.273345947265625 +86048 -0.216796875 +86049 -0.128265380859375 +86050 -0.068145751953125 +86051 -0.0430908203125 +86052 -0.024444580078125 +86053 0.020721435546875 +86054 0.124481201171875 +86055 0.25787353515625 +86056 0.379119873046875 +86057 0.47991943359375 +86058 0.5281982421875 +86059 0.511138916015625 +86060 0.456207275390625 +86061 0.407470703125 +86062 0.383758544921875 +86063 0.35687255859375 +86064 0.31182861328125 +86065 0.250885009765625 +86066 0.1654052734375 +86067 0.035247802734375 +86068 -0.142059326171875 +86069 -0.33563232421875 +86070 -0.5345458984375 +86071 -0.72186279296875 +86072 -0.836669921875 +86073 -0.8326416015625 +86074 -0.7296142578125 +86075 -0.582550048828125 +86076 -0.440093994140625 +86077 -0.324310302734375 +86078 -0.20147705078125 +86079 -0.044647216796875 +86080 0.103973388671875 +86081 0.202392578125 +86082 0.264495849609375 +86083 0.338897705078125 +86084 0.443817138671875 +86085 0.545074462890625 +86086 0.6173095703125 +86087 0.6524658203125 +86088 0.66339111328125 +86089 0.6561279296875 +86090 0.606781005859375 +86091 0.501190185546875 +86092 0.352783203125 +86093 0.176544189453125 +86094 -0.034820556640625 +86095 -0.258209228515625 +86096 -0.44244384765625 +86097 -0.5753173828125 +86098 -0.65203857421875 +86099 -0.641632080078125 +86100 -0.562164306640625 +86101 -0.458038330078125 +86102 -0.350555419921875 +86103 -0.260528564453125 +86104 -0.192108154296875 +86105 -0.141937255859375 +86106 -0.1021728515625 +86107 -0.062896728515625 +86108 -0.011932373046875 +86109 0.062835693359375 +86110 0.148712158203125 +86111 0.241729736328125 +86112 0.34912109375 +86113 0.457305908203125 +86114 0.54388427734375 +86115 0.5728759765625 +86116 0.506591796875 +86117 0.351226806640625 +86118 0.146514892578125 +86119 -0.05523681640625 +86120 -0.21624755859375 +86121 -0.334930419921875 +86122 -0.402984619140625 +86123 -0.4412841796875 +86124 -0.49578857421875 +86125 -0.5601806640625 +86126 -0.600738525390625 +86127 -0.584228515625 +86128 -0.47930908203125 +86129 -0.27935791015625 +86130 -0.0089111328125 +86131 0.268798828125 +86132 0.482818603515625 +86133 0.60369873046875 +86134 0.650421142578125 +86135 0.66400146484375 +86136 0.6414794921875 +86137 0.572540283203125 +86138 0.498138427734375 +86139 0.439453125 +86140 0.375518798828125 +86141 0.274505615234375 +86142 0.1087646484375 +86143 -0.099395751953125 +86144 -0.3182373046875 +86145 -0.5489501953125 +86146 -0.7738037109375 +86147 -0.86383056640625 +86148 -0.870391845703125 +86149 -0.86895751953125 +86150 -0.861053466796875 +86151 -0.765869140625 +86152 -0.5301513671875 +86153 -0.214691162109375 +86154 0.137359619140625 +86155 0.474822998046875 +86156 0.76239013671875 +86157 0.867462158203125 +86158 0.870361328125 +86159 0.86480712890625 +86160 0.831817626953125 +86161 0.677581787109375 +86162 0.495880126953125 +86163 0.30767822265625 +86164 0.116180419921875 +86165 -0.110748291015625 +86166 -0.381805419921875 +86167 -0.6572265625 +86168 -0.857421875 +86169 -0.870391845703125 +86170 -0.870391845703125 +86171 -0.86444091796875 +86172 -0.85723876953125 +86173 -0.790008544921875 +86174 -0.62847900390625 +86175 -0.3956298828125 +86176 -0.126708984375 +86177 0.150115966796875 +86178 0.424041748046875 +86179 0.670623779296875 +86180 0.854522705078125 +86181 0.866485595703125 +86182 0.86920166015625 +86183 0.8653564453125 +86184 0.857147216796875 +86185 0.766845703125 +86186 0.628509521484375 +86187 0.462127685546875 +86188 0.297210693359375 +86189 0.14862060546875 +86190 -0.00537109375 +86191 -0.15753173828125 +86192 -0.31304931640625 +86193 -0.48876953125 +86194 -0.6416015625 +86195 -0.751373291015625 +86196 -0.84619140625 +86197 -0.861297607421875 +86198 -0.863250732421875 +86199 -0.856597900390625 +86200 -0.7498779296875 +86201 -0.624542236328125 +86202 -0.47808837890625 +86203 -0.253387451171875 +86204 0.003692626953125 +86205 0.2257080078125 +86206 0.427154541015625 +86207 0.643218994140625 +86208 0.855926513671875 +86209 0.870361328125 +86210 0.870361328125 +86211 0.862762451171875 +86212 0.79669189453125 +86213 0.595794677734375 +86214 0.362152099609375 +86215 0.1270751953125 +86216 -0.086944580078125 +86217 -0.2784423828125 +86218 -0.484832763671875 +86219 -0.729583740234375 +86220 -0.86688232421875 +86221 -0.870391845703125 +86222 -0.86859130859375 +86223 -0.86279296875 +86224 -0.817962646484375 +86225 -0.6116943359375 +86226 -0.3128662109375 +86227 0.039398193359375 +86228 0.422821044921875 +86229 0.805145263671875 +86230 0.870361328125 +86231 0.870361328125 +86232 0.860015869140625 +86233 0.727935791015625 +86234 0.48114013671875 +86235 0.2059326171875 +86236 -0.06103515625 +86237 -0.29913330078125 +86238 -0.516204833984375 +86239 -0.7252197265625 +86240 -0.85980224609375 +86241 -0.870391845703125 +86242 -0.870391845703125 +86243 -0.858062744140625 +86244 -0.673004150390625 +86245 -0.42694091796875 +86246 -0.2100830078125 +86247 -0.0362548828125 +86248 0.10943603515625 +86249 0.23516845703125 +86250 0.373687744140625 +86251 0.517791748046875 +86252 0.602783203125 +86253 0.635711669921875 +86254 0.655181884765625 +86255 0.65948486328125 +86256 0.651275634765625 +86257 0.61846923828125 +86258 0.53753662109375 +86259 0.404144287109375 +86260 0.22186279296875 +86261 0.003997802734375 +86262 -0.22100830078125 +86263 -0.42449951171875 +86264 -0.579833984375 +86265 -0.641876220703125 +86266 -0.6177978515625 +86267 -0.575531005859375 +86268 -0.526336669921875 +86269 -0.42645263671875 +86270 -0.2581787109375 +86271 -0.068695068359375 +86272 0.09222412109375 +86273 0.232147216796875 +86274 0.3509521484375 +86275 0.410064697265625 +86276 0.372955322265625 +86277 0.2554931640625 +86278 0.10711669921875 +86279 -0.052886962890625 +86280 -0.186279296875 +86281 -0.23291015625 +86282 -0.209442138671875 +86283 -0.174163818359375 +86284 -0.126739501953125 +86285 -0.048126220703125 +86286 0.0426025390625 +86287 0.10748291015625 +86288 0.1409912109375 +86289 0.19708251953125 +86290 0.273651123046875 +86291 0.31768798828125 +86292 0.341094970703125 +86293 0.368011474609375 +86294 0.37249755859375 +86295 0.30072021484375 +86296 0.1517333984375 +86297 -0.01470947265625 +86298 -0.1883544921875 +86299 -0.372711181640625 +86300 -0.51397705078125 +86301 -0.57177734375 +86302 -0.53948974609375 +86303 -0.43511962890625 +86304 -0.2962646484375 +86305 -0.161102294921875 +86306 -0.0435791015625 +86307 0.060394287109375 +86308 0.13665771484375 +86309 0.170135498046875 +86310 0.16552734375 +86311 0.15728759765625 +86312 0.150787353515625 +86313 0.12200927734375 +86314 0.080108642578125 +86315 0.05126953125 +86316 0.062896728515625 +86317 0.09271240234375 +86318 0.092987060546875 +86319 0.07855224609375 +86320 0.06427001953125 +86321 0.0347900390625 +86322 -0.01171875 +86323 -0.056060791015625 +86324 -0.055511474609375 +86325 -0.010467529296875 +86326 0.02508544921875 +86327 0.025665283203125 +86328 0.017333984375 +86329 0.00189208984375 +86330 -0.03173828125 +86331 -0.071502685546875 +86332 -0.13543701171875 +86333 -0.219970703125 +86334 -0.300506591796875 +86335 -0.376312255859375 +86336 -0.416107177734375 +86337 -0.371124267578125 +86338 -0.242279052734375 +86339 -0.069732666015625 +86340 0.125640869140625 +86341 0.31268310546875 +86342 0.45501708984375 +86343 0.554779052734375 +86344 0.61065673828125 +86345 0.610931396484375 +86346 0.531463623046875 +86347 0.3883056640625 +86348 0.23468017578125 +86349 0.095245361328125 +86350 -0.00396728515625 +86351 -0.04852294921875 +86352 -0.055145263671875 +86353 -0.0758056640625 +86354 -0.138702392578125 +86355 -0.209197998046875 +86356 -0.289031982421875 +86357 -0.37884521484375 +86358 -0.456329345703125 +86359 -0.51641845703125 +86360 -0.519287109375 +86361 -0.458251953125 +86362 -0.384796142578125 +86363 -0.323699951171875 +86364 -0.269287109375 +86365 -0.1951904296875 +86366 -0.100006103515625 +86367 -0.01055908203125 +86368 0.1033935546875 +86369 0.24908447265625 +86370 0.373199462890625 +86371 0.45806884765625 +86372 0.511474609375 +86373 0.565399169921875 +86374 0.61138916015625 +86375 0.5897216796875 +86376 0.4906005859375 +86377 0.33148193359375 +86378 0.147796630859375 +86379 -0.01873779296875 +86380 -0.140289306640625 +86381 -0.191986083984375 +86382 -0.184295654296875 +86383 -0.161834716796875 +86384 -0.166595458984375 +86385 -0.19390869140625 +86386 -0.22442626953125 +86387 -0.279754638671875 +86388 -0.3389892578125 +86389 -0.3543701171875 +86390 -0.348175048828125 +86391 -0.32598876953125 +86392 -0.2581787109375 +86393 -0.139801025390625 +86394 0.014617919921875 +86395 0.144378662109375 +86396 0.221038818359375 +86397 0.27069091796875 +86398 0.294036865234375 +86399 0.311767578125 +86400 0.339141845703125 +86401 0.360260009765625 +86402 0.360504150390625 +86403 0.308380126953125 +86404 0.18170166015625 +86405 0.0047607421875 +86406 -0.17559814453125 +86407 -0.3143310546875 +86408 -0.36785888671875 +86409 -0.36248779296875 +86410 -0.343536376953125 +86411 -0.3018798828125 +86412 -0.231414794921875 +86413 -0.117645263671875 +86414 0.007049560546875 +86415 0.087982177734375 +86416 0.13946533203125 +86417 0.17425537109375 +86418 0.188201904296875 +86419 0.171234130859375 +86420 0.118438720703125 +86421 0.05706787109375 +86422 -0.010711669921875 +86423 -0.0914306640625 +86424 -0.162322998046875 +86425 -0.194549560546875 +86426 -0.1492919921875 +86427 -0.02166748046875 +86428 0.124053955078125 +86429 0.211151123046875 +86430 0.240447998046875 +86431 0.242218017578125 +86432 0.2257080078125 +86433 0.194366455078125 +86434 0.115509033203125 +86435 0.0128173828125 +86436 -0.053802490234375 +86437 -0.110626220703125 +86438 -0.199493408203125 +86439 -0.29437255859375 +86440 -0.33221435546875 +86441 -0.27972412109375 +86442 -0.185333251953125 +86443 -0.128204345703125 +86444 -0.115692138671875 +86445 -0.116455078125 +86446 -0.105926513671875 +86447 -0.053955078125 +86448 0.048797607421875 +86449 0.157318115234375 +86450 0.212005615234375 +86451 0.218475341796875 +86452 0.23724365234375 +86453 0.30535888671875 +86454 0.38128662109375 +86455 0.404449462890625 +86456 0.3944091796875 +86457 0.3885498046875 +86458 0.362640380859375 +86459 0.27362060546875 +86460 0.11712646484375 +86461 -0.054901123046875 +86462 -0.19085693359375 +86463 -0.28570556640625 +86464 -0.339263916015625 +86465 -0.3775634765625 +86466 -0.445709228515625 +86467 -0.535064697265625 +86468 -0.629058837890625 +86469 -0.697601318359375 +86470 -0.70391845703125 +86471 -0.6424560546875 +86472 -0.491241455078125 +86473 -0.265716552734375 +86474 -0.023712158203125 +86475 0.201751708984375 +86476 0.375823974609375 +86477 0.485076904296875 +86478 0.56884765625 +86479 0.634765625 +86480 0.63763427734375 +86481 0.5660400390625 +86482 0.4720458984375 +86483 0.40692138671875 +86484 0.3778076171875 +86485 0.376953125 +86486 0.371978759765625 +86487 0.313140869140625 +86488 0.184417724609375 +86489 0.011199951171875 +86490 -0.171051025390625 +86491 -0.33740234375 +86492 -0.47198486328125 +86493 -0.560394287109375 +86494 -0.58056640625 +86495 -0.54754638671875 +86496 -0.508575439453125 +86497 -0.459503173828125 +86498 -0.394378662109375 +86499 -0.35260009765625 +86500 -0.31170654296875 +86501 -0.197418212890625 +86502 -0.007965087890625 +86503 0.207489013671875 +86504 0.409210205078125 +86505 0.57208251953125 +86506 0.66595458984375 +86507 0.65875244140625 +86508 0.56744384765625 +86509 0.431396484375 +86510 0.29443359375 +86511 0.182464599609375 +86512 0.06365966796875 +86513 -0.075958251953125 +86514 -0.189422607421875 +86515 -0.271942138671875 +86516 -0.342529296875 +86517 -0.364166259765625 +86518 -0.327239990234375 +86519 -0.2769775390625 +86520 -0.253692626953125 +86521 -0.24365234375 +86522 -0.1983642578125 +86523 -0.116241455078125 +86524 -0.036834716796875 +86525 0.034881591796875 +86526 0.09124755859375 +86527 0.10888671875 +86528 0.125518798828125 +86529 0.15771484375 +86530 0.17828369140625 +86531 0.17108154296875 +86532 0.129974365234375 +86533 0.082427978515625 +86534 0.027679443359375 +86535 -0.065643310546875 +86536 -0.15936279296875 +86537 -0.21307373046875 +86538 -0.234649658203125 +86539 -0.2001953125 +86540 -0.119171142578125 +86541 -0.024749755859375 +86542 0.085784912109375 +86543 0.178131103515625 +86544 0.215576171875 +86545 0.211456298828125 +86546 0.17523193359375 +86547 0.128753662109375 +86548 0.1019287109375 +86549 0.0743408203125 +86550 0.04327392578125 +86551 0.038177490234375 +86552 0.076263427734375 +86553 0.14105224609375 +86554 0.186431884765625 +86555 0.188812255859375 +86556 0.1390380859375 +86557 0.041778564453125 +86558 -0.079437255859375 +86559 -0.219390869140625 +86560 -0.367828369140625 +86561 -0.494873046875 +86562 -0.556243896484375 +86563 -0.508697509765625 +86564 -0.3756103515625 +86565 -0.218902587890625 +86566 -0.063751220703125 +86567 0.091552734375 +86568 0.23602294921875 +86569 0.342987060546875 +86570 0.39520263671875 +86571 0.389373779296875 +86572 0.324249267578125 +86573 0.224090576171875 +86574 0.124267578125 +86575 0.037078857421875 +86576 -0.010101318359375 +86577 -0.019439697265625 +86578 -0.022796630859375 +86579 -0.001556396484375 +86580 0.056304931640625 +86581 0.106719970703125 +86582 0.096893310546875 +86583 0.042694091796875 +86584 -0.018035888671875 +86585 -0.07586669921875 +86586 -0.11944580078125 +86587 -0.15972900390625 +86588 -0.202606201171875 +86589 -0.24859619140625 +86590 -0.30517578125 +86591 -0.36212158203125 +86592 -0.39141845703125 +86593 -0.35528564453125 +86594 -0.249969482421875 +86595 -0.092864990234375 +86596 0.08905029296875 +86597 0.2352294921875 +86598 0.318817138671875 +86599 0.358642578125 +86600 0.347747802734375 +86601 0.28564453125 +86602 0.223175048828125 +86603 0.196746826171875 +86604 0.179840087890625 +86605 0.155548095703125 +86606 0.151214599609375 +86607 0.156951904296875 +86608 0.13177490234375 +86609 0.100799560546875 +86610 0.087127685546875 +86611 0.05487060546875 +86612 -0.009002685546875 +86613 -0.10400390625 +86614 -0.229400634765625 +86615 -0.35552978515625 +86616 -0.441925048828125 +86617 -0.473846435546875 +86618 -0.464813232421875 +86619 -0.419097900390625 +86620 -0.334320068359375 +86621 -0.227935791015625 +86622 -0.12347412109375 +86623 -0.02764892578125 +86624 0.077667236328125 +86625 0.2132568359375 +86626 0.38885498046875 +86627 0.582794189453125 +86628 0.734039306640625 +86629 0.800140380859375 +86630 0.7783203125 +86631 0.6651611328125 +86632 0.45965576171875 +86633 0.199188232421875 +86634 -0.050689697265625 +86635 -0.23297119140625 +86636 -0.33013916015625 +86637 -0.368408203125 +86638 -0.378936767578125 +86639 -0.376983642578125 +86640 -0.37969970703125 +86641 -0.391510009765625 +86642 -0.385345458984375 +86643 -0.3419189453125 +86644 -0.28289794921875 +86645 -0.251617431640625 +86646 -0.266143798828125 +86647 -0.273345947265625 +86648 -0.216796875 +86649 -0.128265380859375 +86650 -0.068145751953125 +86651 -0.0430908203125 +86652 -0.024444580078125 +86653 0.020721435546875 +86654 0.124481201171875 +86655 0.25787353515625 +86656 0.379119873046875 +86657 0.47991943359375 +86658 0.5281982421875 +86659 0.511138916015625 +86660 0.456207275390625 +86661 0.407470703125 +86662 0.383758544921875 +86663 0.35687255859375 +86664 0.31182861328125 +86665 0.250885009765625 +86666 0.1654052734375 +86667 0.035247802734375 +86668 -0.142059326171875 +86669 -0.33563232421875 +86670 -0.5345458984375 +86671 -0.72186279296875 +86672 -0.836669921875 +86673 -0.8326416015625 +86674 -0.7296142578125 +86675 -0.582550048828125 +86676 -0.440093994140625 +86677 -0.324310302734375 +86678 -0.20147705078125 +86679 -0.044647216796875 +86680 0.103973388671875 +86681 0.202392578125 +86682 0.264495849609375 +86683 0.338897705078125 +86684 0.443817138671875 +86685 0.545074462890625 +86686 0.6173095703125 +86687 0.6524658203125 +86688 0.66339111328125 +86689 0.6561279296875 +86690 0.606781005859375 +86691 0.501190185546875 +86692 0.352783203125 +86693 0.176544189453125 +86694 -0.034820556640625 +86695 -0.258209228515625 +86696 -0.44244384765625 +86697 -0.5753173828125 +86698 -0.65203857421875 +86699 -0.641632080078125 +86700 -0.562164306640625 +86701 -0.458038330078125 +86702 -0.350555419921875 +86703 -0.260528564453125 +86704 -0.192108154296875 +86705 -0.141937255859375 +86706 -0.1021728515625 +86707 -0.062896728515625 +86708 -0.011932373046875 +86709 0.062835693359375 +86710 0.148712158203125 +86711 0.241729736328125 +86712 0.34912109375 +86713 0.457305908203125 +86714 0.54388427734375 +86715 0.5728759765625 +86716 0.506591796875 +86717 0.351226806640625 +86718 0.146514892578125 +86719 -0.05523681640625 +86720 -0.21624755859375 +86721 -0.334930419921875 +86722 -0.402984619140625 +86723 -0.4412841796875 +86724 -0.49578857421875 +86725 -0.5601806640625 +86726 -0.600738525390625 +86727 -0.584228515625 +86728 -0.47930908203125 +86729 -0.27935791015625 +86730 -0.0089111328125 +86731 0.268798828125 +86732 0.482818603515625 +86733 0.60369873046875 +86734 0.650421142578125 +86735 0.66400146484375 +86736 0.6414794921875 +86737 0.572540283203125 +86738 0.498138427734375 +86739 0.439453125 +86740 0.375518798828125 +86741 0.274505615234375 +86742 0.1087646484375 +86743 -0.099395751953125 +86744 -0.3182373046875 +86745 -0.5489501953125 +86746 -0.7738037109375 +86747 -0.86383056640625 +86748 -0.870391845703125 +86749 -0.86895751953125 +86750 -0.861053466796875 +86751 -0.765869140625 +86752 -0.5301513671875 +86753 -0.214691162109375 +86754 0.137359619140625 +86755 0.474822998046875 +86756 0.76239013671875 +86757 0.867462158203125 +86758 0.870361328125 +86759 0.86480712890625 +86760 0.831817626953125 +86761 0.677581787109375 +86762 0.495880126953125 +86763 0.30767822265625 +86764 0.116180419921875 +86765 -0.110748291015625 +86766 -0.381805419921875 +86767 -0.6572265625 +86768 -0.857421875 +86769 -0.870391845703125 +86770 -0.870391845703125 +86771 -0.86444091796875 +86772 -0.85723876953125 +86773 -0.790008544921875 +86774 -0.62847900390625 +86775 -0.3956298828125 +86776 -0.126708984375 +86777 0.150115966796875 +86778 0.424041748046875 +86779 0.670623779296875 +86780 0.854522705078125 +86781 0.866485595703125 +86782 0.86920166015625 +86783 0.8653564453125 +86784 0.857147216796875 +86785 0.766845703125 +86786 0.628509521484375 +86787 0.462127685546875 +86788 0.297210693359375 +86789 0.14862060546875 +86790 -0.00537109375 +86791 -0.15753173828125 +86792 -0.31304931640625 +86793 -0.48876953125 +86794 -0.6416015625 +86795 -0.751373291015625 +86796 -0.84619140625 +86797 -0.861297607421875 +86798 -0.863250732421875 +86799 -0.856597900390625 +86800 -0.7498779296875 +86801 -0.624542236328125 +86802 -0.47808837890625 +86803 -0.253387451171875 +86804 0.003692626953125 +86805 0.2257080078125 +86806 0.427154541015625 +86807 0.643218994140625 +86808 0.855926513671875 +86809 0.870361328125 +86810 0.870361328125 +86811 0.862762451171875 +86812 0.79669189453125 +86813 0.595794677734375 +86814 0.362152099609375 +86815 0.1270751953125 +86816 -0.086944580078125 +86817 -0.2784423828125 +86818 -0.484832763671875 +86819 -0.729583740234375 +86820 -0.86688232421875 +86821 -0.870391845703125 +86822 -0.86859130859375 +86823 -0.86279296875 +86824 -0.817962646484375 +86825 -0.6116943359375 +86826 -0.3128662109375 +86827 0.039398193359375 +86828 0.422821044921875 +86829 0.805145263671875 +86830 0.870361328125 +86831 0.870361328125 +86832 0.860015869140625 +86833 0.727935791015625 +86834 0.48114013671875 +86835 0.2059326171875 +86836 -0.06103515625 +86837 -0.29913330078125 +86838 -0.516204833984375 +86839 -0.7252197265625 +86840 -0.85980224609375 +86841 -0.870391845703125 +86842 -0.870391845703125 +86843 -0.858062744140625 +86844 -0.673004150390625 +86845 -0.42694091796875 +86846 -0.2100830078125 +86847 -0.0362548828125 +86848 0.10943603515625 +86849 0.23516845703125 +86850 0.373687744140625 +86851 0.517791748046875 +86852 0.602783203125 +86853 0.635711669921875 +86854 0.655181884765625 +86855 0.65948486328125 +86856 0.651275634765625 +86857 0.61846923828125 +86858 0.53753662109375 +86859 0.404144287109375 +86860 0.22186279296875 +86861 0.003997802734375 +86862 -0.22100830078125 +86863 -0.42449951171875 +86864 -0.579833984375 +86865 -0.641876220703125 +86866 -0.6177978515625 +86867 -0.575531005859375 +86868 -0.526336669921875 +86869 -0.42645263671875 +86870 -0.2581787109375 +86871 -0.068695068359375 +86872 0.09222412109375 +86873 0.232147216796875 +86874 0.3509521484375 +86875 0.410064697265625 +86876 0.372955322265625 +86877 0.2554931640625 +86878 0.10711669921875 +86879 -0.052886962890625 +86880 -0.186279296875 +86881 -0.23291015625 +86882 -0.209442138671875 +86883 -0.174163818359375 +86884 -0.126739501953125 +86885 -0.048126220703125 +86886 0.0426025390625 +86887 0.10748291015625 +86888 0.1409912109375 +86889 0.19708251953125 +86890 0.273651123046875 +86891 0.31768798828125 +86892 0.341094970703125 +86893 0.368011474609375 +86894 0.37249755859375 +86895 0.30072021484375 +86896 0.1517333984375 +86897 -0.01470947265625 +86898 -0.1883544921875 +86899 -0.372711181640625 +86900 -0.51397705078125 +86901 -0.57177734375 +86902 -0.53948974609375 +86903 -0.43511962890625 +86904 -0.2962646484375 +86905 -0.161102294921875 +86906 -0.0435791015625 +86907 0.060394287109375 +86908 0.13665771484375 +86909 0.170135498046875 +86910 0.16552734375 +86911 0.15728759765625 +86912 0.150787353515625 +86913 0.12200927734375 +86914 0.080108642578125 +86915 0.05126953125 +86916 0.062896728515625 +86917 0.09271240234375 +86918 0.092987060546875 +86919 0.07855224609375 +86920 0.06427001953125 +86921 0.0347900390625 +86922 -0.01171875 +86923 -0.056060791015625 +86924 -0.055511474609375 +86925 -0.010467529296875 +86926 0.02508544921875 +86927 0.025665283203125 +86928 0.017333984375 +86929 0.00189208984375 +86930 -0.03173828125 +86931 -0.071502685546875 +86932 -0.13543701171875 +86933 -0.219970703125 +86934 -0.300506591796875 +86935 -0.376312255859375 +86936 -0.416107177734375 +86937 -0.371124267578125 +86938 -0.242279052734375 +86939 -0.069732666015625 +86940 0.125640869140625 +86941 0.31268310546875 +86942 0.45501708984375 +86943 0.554779052734375 +86944 0.61065673828125 +86945 0.610931396484375 +86946 0.531463623046875 +86947 0.3883056640625 +86948 0.23468017578125 +86949 0.095245361328125 +86950 -0.00396728515625 +86951 -0.04852294921875 +86952 -0.055145263671875 +86953 -0.0758056640625 +86954 -0.138702392578125 +86955 -0.209197998046875 +86956 -0.289031982421875 +86957 -0.37884521484375 +86958 -0.456329345703125 +86959 -0.51641845703125 +86960 -0.519287109375 +86961 -0.458251953125 +86962 -0.384796142578125 +86963 -0.323699951171875 +86964 -0.269287109375 +86965 -0.1951904296875 +86966 -0.100006103515625 +86967 -0.01055908203125 +86968 0.1033935546875 +86969 0.24908447265625 +86970 0.373199462890625 +86971 0.45806884765625 +86972 0.511474609375 +86973 0.565399169921875 +86974 0.61138916015625 +86975 0.5897216796875 +86976 0.4906005859375 +86977 0.33148193359375 +86978 0.147796630859375 +86979 -0.01873779296875 +86980 -0.140289306640625 +86981 -0.191986083984375 +86982 -0.184295654296875 +86983 -0.161834716796875 +86984 -0.166595458984375 +86985 -0.19390869140625 +86986 -0.22442626953125 +86987 -0.279754638671875 +86988 -0.3389892578125 +86989 -0.3543701171875 +86990 -0.348175048828125 +86991 -0.32598876953125 +86992 -0.2581787109375 +86993 -0.139801025390625 +86994 0.014617919921875 +86995 0.144378662109375 +86996 0.221038818359375 +86997 0.27069091796875 +86998 0.294036865234375 +86999 0.311767578125 +87000 0.339141845703125 +87001 0.360260009765625 +87002 0.360504150390625 +87003 0.308380126953125 +87004 0.18170166015625 +87005 0.0047607421875 +87006 -0.17559814453125 +87007 -0.3143310546875 +87008 -0.36785888671875 +87009 -0.36248779296875 +87010 -0.343536376953125 +87011 -0.3018798828125 +87012 -0.231414794921875 +87013 -0.117645263671875 +87014 0.007049560546875 +87015 0.087982177734375 +87016 0.13946533203125 +87017 0.17425537109375 +87018 0.188201904296875 +87019 0.171234130859375 +87020 0.118438720703125 +87021 0.05706787109375 +87022 -0.010711669921875 +87023 -0.0914306640625 +87024 -0.162322998046875 +87025 -0.194549560546875 +87026 -0.1492919921875 +87027 -0.02166748046875 +87028 0.124053955078125 +87029 0.211151123046875 +87030 0.240447998046875 +87031 0.242218017578125 +87032 0.2257080078125 +87033 0.194366455078125 +87034 0.115509033203125 +87035 0.0128173828125 +87036 -0.053802490234375 +87037 -0.110626220703125 +87038 -0.199493408203125 +87039 -0.29437255859375 +87040 -0.33221435546875 +87041 -0.27972412109375 +87042 -0.185333251953125 +87043 -0.128204345703125 +87044 -0.115692138671875 +87045 -0.116455078125 +87046 -0.105926513671875 +87047 -0.053955078125 +87048 0.048797607421875 +87049 0.157318115234375 +87050 0.212005615234375 +87051 0.218475341796875 +87052 0.23724365234375 +87053 0.30535888671875 +87054 0.38128662109375 +87055 0.404449462890625 +87056 0.3944091796875 +87057 0.3885498046875 +87058 0.362640380859375 +87059 0.27362060546875 +87060 0.11712646484375 +87061 -0.054901123046875 +87062 -0.19085693359375 +87063 -0.28570556640625 +87064 -0.339263916015625 +87065 -0.3775634765625 +87066 -0.445709228515625 +87067 -0.535064697265625 +87068 -0.629058837890625 +87069 -0.697601318359375 +87070 -0.70391845703125 +87071 -0.6424560546875 +87072 -0.491241455078125 +87073 -0.265716552734375 +87074 -0.023712158203125 +87075 0.201751708984375 +87076 0.375823974609375 +87077 0.485076904296875 +87078 0.56884765625 +87079 0.634765625 +87080 0.63763427734375 +87081 0.5660400390625 +87082 0.4720458984375 +87083 0.40692138671875 +87084 0.3778076171875 +87085 0.376953125 +87086 0.371978759765625 +87087 0.313140869140625 +87088 0.184417724609375 +87089 0.011199951171875 +87090 -0.171051025390625 +87091 -0.33740234375 +87092 -0.47198486328125 +87093 -0.560394287109375 +87094 -0.58056640625 +87095 -0.54754638671875 +87096 -0.508575439453125 +87097 -0.459503173828125 +87098 -0.394378662109375 +87099 -0.35260009765625 +87100 -0.31170654296875 +87101 -0.197418212890625 +87102 -0.007965087890625 +87103 0.207489013671875 +87104 0.409210205078125 +87105 0.57208251953125 +87106 0.66595458984375 +87107 0.65875244140625 +87108 0.56744384765625 +87109 0.431396484375 +87110 0.29443359375 +87111 0.182464599609375 +87112 0.06365966796875 +87113 -0.075958251953125 +87114 -0.189422607421875 +87115 -0.271942138671875 +87116 -0.342529296875 +87117 -0.364166259765625 +87118 -0.327239990234375 +87119 -0.2769775390625 +87120 -0.253692626953125 +87121 -0.24365234375 +87122 -0.1983642578125 +87123 -0.116241455078125 +87124 -0.036834716796875 +87125 0.034881591796875 +87126 0.09124755859375 +87127 0.10888671875 +87128 0.125518798828125 +87129 0.15771484375 +87130 0.17828369140625 +87131 0.17108154296875 +87132 0.129974365234375 +87133 0.082427978515625 +87134 0.027679443359375 +87135 -0.065643310546875 +87136 -0.15936279296875 +87137 -0.21307373046875 +87138 -0.234649658203125 +87139 -0.2001953125 +87140 -0.119171142578125 +87141 -0.024749755859375 +87142 0.085784912109375 +87143 0.178131103515625 +87144 0.215576171875 +87145 0.211456298828125 +87146 0.17523193359375 +87147 0.128753662109375 +87148 0.1019287109375 +87149 0.0743408203125 +87150 0.04327392578125 +87151 0.038177490234375 +87152 0.076263427734375 +87153 0.14105224609375 +87154 0.186431884765625 +87155 0.188812255859375 +87156 0.1390380859375 +87157 0.041778564453125 +87158 -0.079437255859375 +87159 -0.219390869140625 +87160 -0.367828369140625 +87161 -0.494873046875 +87162 -0.556243896484375 +87163 -0.508697509765625 +87164 -0.3756103515625 +87165 -0.218902587890625 +87166 -0.063751220703125 +87167 0.091552734375 +87168 0.23602294921875 +87169 0.342987060546875 +87170 0.39520263671875 +87171 0.389373779296875 +87172 0.324249267578125 +87173 0.224090576171875 +87174 0.124267578125 +87175 0.037078857421875 +87176 -0.010101318359375 +87177 -0.019439697265625 +87178 -0.022796630859375 +87179 -0.001556396484375 +87180 0.056304931640625 +87181 0.106719970703125 +87182 0.096893310546875 +87183 0.042694091796875 +87184 -0.018035888671875 +87185 -0.07586669921875 +87186 -0.11944580078125 +87187 -0.15972900390625 +87188 -0.202606201171875 +87189 -0.24859619140625 +87190 -0.30517578125 +87191 -0.36212158203125 +87192 -0.39141845703125 +87193 -0.35528564453125 +87194 -0.249969482421875 +87195 -0.092864990234375 +87196 0.08905029296875 +87197 0.2352294921875 +87198 0.318817138671875 +87199 0.358642578125 +87200 0.347747802734375 +87201 0.28564453125 +87202 0.223175048828125 +87203 0.196746826171875 +87204 0.179840087890625 +87205 0.155548095703125 +87206 0.151214599609375 +87207 0.156951904296875 +87208 0.13177490234375 +87209 0.100799560546875 +87210 0.087127685546875 +87211 0.05487060546875 +87212 -0.009002685546875 +87213 -0.10400390625 +87214 -0.229400634765625 +87215 -0.35552978515625 +87216 -0.441925048828125 +87217 -0.473846435546875 +87218 -0.464813232421875 +87219 -0.419097900390625 +87220 -0.334320068359375 +87221 -0.227935791015625 +87222 -0.12347412109375 +87223 -0.02764892578125 +87224 0.077667236328125 +87225 0.2132568359375 +87226 0.38885498046875 +87227 0.582794189453125 +87228 0.734039306640625 +87229 0.800140380859375 +87230 0.7783203125 +87231 0.6651611328125 +87232 0.45965576171875 +87233 0.199188232421875 +87234 -0.050689697265625 +87235 -0.23297119140625 +87236 -0.33013916015625 +87237 -0.368408203125 +87238 -0.378936767578125 +87239 -0.376983642578125 +87240 -0.37969970703125 +87241 -0.391510009765625 +87242 -0.385345458984375 +87243 -0.3419189453125 +87244 -0.28289794921875 +87245 -0.251617431640625 +87246 -0.266143798828125 +87247 -0.273345947265625 +87248 -0.216796875 +87249 -0.128265380859375 +87250 -0.068145751953125 +87251 -0.0430908203125 +87252 -0.024444580078125 +87253 0.020721435546875 +87254 0.124481201171875 +87255 0.25787353515625 +87256 0.379119873046875 +87257 0.47991943359375 +87258 0.5281982421875 +87259 0.511138916015625 +87260 0.456207275390625 +87261 0.407470703125 +87262 0.383758544921875 +87263 0.35687255859375 +87264 0.31182861328125 +87265 0.250885009765625 +87266 0.1654052734375 +87267 0.035247802734375 +87268 -0.142059326171875 +87269 -0.33563232421875 +87270 -0.5345458984375 +87271 -0.72186279296875 +87272 -0.836669921875 +87273 -0.8326416015625 +87274 -0.7296142578125 +87275 -0.582550048828125 +87276 -0.440093994140625 +87277 -0.324310302734375 +87278 -0.20147705078125 +87279 -0.044647216796875 +87280 0.103973388671875 +87281 0.202392578125 +87282 0.264495849609375 +87283 0.338897705078125 +87284 0.443817138671875 +87285 0.545074462890625 +87286 0.6173095703125 +87287 0.6524658203125 +87288 0.66339111328125 +87289 0.6561279296875 +87290 0.606781005859375 +87291 0.501190185546875 +87292 0.352783203125 +87293 0.176544189453125 +87294 -0.034820556640625 +87295 -0.258209228515625 +87296 -0.44244384765625 +87297 -0.5753173828125 +87298 -0.65203857421875 +87299 -0.641632080078125 +87300 -0.562164306640625 +87301 -0.458038330078125 +87302 -0.350555419921875 +87303 -0.260528564453125 +87304 -0.192108154296875 +87305 -0.141937255859375 +87306 -0.1021728515625 +87307 -0.062896728515625 +87308 -0.011932373046875 +87309 0.062835693359375 +87310 0.148712158203125 +87311 0.241729736328125 +87312 0.34912109375 +87313 0.457305908203125 +87314 0.54388427734375 +87315 0.5728759765625 +87316 0.506591796875 +87317 0.351226806640625 +87318 0.146514892578125 +87319 -0.05523681640625 +87320 -0.21624755859375 +87321 -0.334930419921875 +87322 -0.402984619140625 +87323 -0.4412841796875 +87324 -0.49578857421875 +87325 -0.5601806640625 +87326 -0.600738525390625 +87327 -0.584228515625 +87328 -0.47930908203125 +87329 -0.27935791015625 +87330 -0.0089111328125 +87331 0.268798828125 +87332 0.482818603515625 +87333 0.60369873046875 +87334 0.650421142578125 +87335 0.66400146484375 +87336 0.6414794921875 +87337 0.572540283203125 +87338 0.498138427734375 +87339 0.439453125 +87340 0.375518798828125 +87341 0.274505615234375 +87342 0.1087646484375 +87343 -0.099395751953125 +87344 -0.3182373046875 +87345 -0.5489501953125 +87346 -0.7738037109375 +87347 -0.86383056640625 +87348 -0.870391845703125 +87349 -0.86895751953125 +87350 -0.861053466796875 +87351 -0.765869140625 +87352 -0.5301513671875 +87353 -0.214691162109375 +87354 0.137359619140625 +87355 0.474822998046875 +87356 0.76239013671875 +87357 0.867462158203125 +87358 0.870361328125 +87359 0.86480712890625 +87360 0.831817626953125 +87361 0.677581787109375 +87362 0.495880126953125 +87363 0.30767822265625 +87364 0.116180419921875 +87365 -0.110748291015625 +87366 -0.381805419921875 +87367 -0.6572265625 +87368 -0.857421875 +87369 -0.870391845703125 +87370 -0.870391845703125 +87371 -0.86444091796875 +87372 -0.85723876953125 +87373 -0.790008544921875 +87374 -0.62847900390625 +87375 -0.3956298828125 +87376 -0.126708984375 +87377 0.150115966796875 +87378 0.424041748046875 +87379 0.670623779296875 +87380 0.854522705078125 +87381 0.866485595703125 +87382 0.86920166015625 +87383 0.8653564453125 +87384 0.857147216796875 +87385 0.766845703125 +87386 0.628509521484375 +87387 0.462127685546875 +87388 0.297210693359375 +87389 0.14862060546875 +87390 -0.00537109375 +87391 -0.15753173828125 +87392 -0.31304931640625 +87393 -0.48876953125 +87394 -0.6416015625 +87395 -0.751373291015625 +87396 -0.84619140625 +87397 -0.861297607421875 +87398 -0.863250732421875 +87399 -0.856597900390625 +87400 -0.7498779296875 +87401 -0.624542236328125 +87402 -0.47808837890625 +87403 -0.253387451171875 +87404 0.003692626953125 +87405 0.2257080078125 +87406 0.427154541015625 +87407 0.643218994140625 +87408 0.855926513671875 +87409 0.870361328125 +87410 0.870361328125 +87411 0.862762451171875 +87412 0.79669189453125 +87413 0.595794677734375 +87414 0.362152099609375 +87415 0.1270751953125 +87416 -0.086944580078125 +87417 -0.2784423828125 +87418 -0.484832763671875 +87419 -0.729583740234375 +87420 -0.86688232421875 +87421 -0.870391845703125 +87422 -0.86859130859375 +87423 -0.86279296875 +87424 -0.817962646484375 +87425 -0.6116943359375 +87426 -0.3128662109375 +87427 0.039398193359375 +87428 0.422821044921875 +87429 0.805145263671875 +87430 0.870361328125 +87431 0.870361328125 +87432 0.860015869140625 +87433 0.727935791015625 +87434 0.48114013671875 +87435 0.2059326171875 +87436 -0.06103515625 +87437 -0.29913330078125 +87438 -0.516204833984375 +87439 -0.7252197265625 +87440 -0.85980224609375 +87441 -0.870391845703125 +87442 -0.870391845703125 +87443 -0.858062744140625 +87444 -0.673004150390625 +87445 -0.42694091796875 +87446 -0.2100830078125 +87447 -0.0362548828125 +87448 0.10943603515625 +87449 0.23516845703125 +87450 0.373687744140625 +87451 0.517791748046875 +87452 0.602783203125 +87453 0.635711669921875 +87454 0.655181884765625 +87455 0.65948486328125 +87456 0.651275634765625 +87457 0.61846923828125 +87458 0.53753662109375 +87459 0.404144287109375 +87460 0.22186279296875 +87461 0.003997802734375 +87462 -0.22100830078125 +87463 -0.42449951171875 +87464 -0.579833984375 +87465 -0.641876220703125 +87466 -0.6177978515625 +87467 -0.575531005859375 +87468 -0.526336669921875 +87469 -0.42645263671875 +87470 -0.2581787109375 +87471 -0.068695068359375 +87472 0.09222412109375 +87473 0.232147216796875 +87474 0.3509521484375 +87475 0.410064697265625 +87476 0.372955322265625 +87477 0.2554931640625 +87478 0.10711669921875 +87479 -0.052886962890625 +87480 -0.186279296875 +87481 -0.23291015625 +87482 -0.209442138671875 +87483 -0.174163818359375 +87484 -0.126739501953125 +87485 -0.048126220703125 +87486 0.0426025390625 +87487 0.10748291015625 +87488 0.1409912109375 +87489 0.19708251953125 +87490 0.273651123046875 +87491 0.31768798828125 +87492 0.341094970703125 +87493 0.368011474609375 +87494 0.37249755859375 +87495 0.30072021484375 +87496 0.1517333984375 +87497 -0.01470947265625 +87498 -0.1883544921875 +87499 -0.372711181640625 +87500 -0.51397705078125 +87501 -0.57177734375 +87502 -0.53948974609375 +87503 -0.43511962890625 +87504 -0.2962646484375 +87505 -0.161102294921875 +87506 -0.0435791015625 +87507 0.060394287109375 +87508 0.13665771484375 +87509 0.170135498046875 +87510 0.16552734375 +87511 0.15728759765625 +87512 0.150787353515625 +87513 0.12200927734375 +87514 0.080108642578125 +87515 0.05126953125 +87516 0.062896728515625 +87517 0.09271240234375 +87518 0.092987060546875 +87519 0.07855224609375 +87520 0.06427001953125 +87521 0.0347900390625 +87522 -0.01171875 +87523 -0.056060791015625 +87524 -0.055511474609375 +87525 -0.010467529296875 +87526 0.02508544921875 +87527 0.025665283203125 +87528 0.017333984375 +87529 0.00189208984375 +87530 -0.03173828125 +87531 -0.071502685546875 +87532 -0.13543701171875 +87533 -0.219970703125 +87534 -0.300506591796875 +87535 -0.376312255859375 +87536 -0.416107177734375 +87537 -0.371124267578125 +87538 -0.242279052734375 +87539 -0.069732666015625 +87540 0.125640869140625 +87541 0.31268310546875 +87542 0.45501708984375 +87543 0.554779052734375 +87544 0.61065673828125 +87545 0.610931396484375 +87546 0.531463623046875 +87547 0.3883056640625 +87548 0.23468017578125 +87549 0.095245361328125 +87550 -0.00396728515625 +87551 -0.04852294921875 +87552 -0.055145263671875 +87553 -0.0758056640625 +87554 -0.138702392578125 +87555 -0.209197998046875 +87556 -0.289031982421875 +87557 -0.37884521484375 +87558 -0.456329345703125 +87559 -0.51641845703125 +87560 -0.519287109375 +87561 -0.458251953125 +87562 -0.384796142578125 +87563 -0.323699951171875 +87564 -0.269287109375 +87565 -0.1951904296875 +87566 -0.100006103515625 +87567 -0.01055908203125 +87568 0.1033935546875 +87569 0.24908447265625 +87570 0.373199462890625 +87571 0.45806884765625 +87572 0.511474609375 +87573 0.565399169921875 +87574 0.61138916015625 +87575 0.5897216796875 +87576 0.4906005859375 +87577 0.33148193359375 +87578 0.147796630859375 +87579 -0.01873779296875 +87580 -0.140289306640625 +87581 -0.191986083984375 +87582 -0.184295654296875 +87583 -0.161834716796875 +87584 -0.166595458984375 +87585 -0.19390869140625 +87586 -0.22442626953125 +87587 -0.279754638671875 +87588 -0.3389892578125 +87589 -0.3543701171875 +87590 -0.348175048828125 +87591 -0.32598876953125 +87592 -0.2581787109375 +87593 -0.139801025390625 +87594 0.014617919921875 +87595 0.144378662109375 +87596 0.221038818359375 +87597 0.27069091796875 +87598 0.294036865234375 +87599 0.311767578125 +87600 0.339141845703125 +87601 0.360260009765625 +87602 0.360504150390625 +87603 0.308380126953125 +87604 0.18170166015625 +87605 0.0047607421875 +87606 -0.17559814453125 +87607 -0.3143310546875 +87608 -0.36785888671875 +87609 -0.36248779296875 +87610 -0.343536376953125 +87611 -0.3018798828125 +87612 -0.231414794921875 +87613 -0.117645263671875 +87614 0.007049560546875 +87615 0.087982177734375 +87616 0.13946533203125 +87617 0.17425537109375 +87618 0.188201904296875 +87619 0.171234130859375 +87620 0.118438720703125 +87621 0.05706787109375 +87622 -0.010711669921875 +87623 -0.0914306640625 +87624 -0.162322998046875 +87625 -0.194549560546875 +87626 -0.1492919921875 +87627 -0.02166748046875 +87628 0.124053955078125 +87629 0.211151123046875 +87630 0.240447998046875 +87631 0.242218017578125 +87632 0.2257080078125 +87633 0.194366455078125 +87634 0.115509033203125 +87635 0.0128173828125 +87636 -0.053802490234375 +87637 -0.110626220703125 +87638 -0.199493408203125 +87639 -0.29437255859375 +87640 -0.33221435546875 +87641 -0.27972412109375 +87642 -0.185333251953125 +87643 -0.128204345703125 +87644 -0.115692138671875 +87645 -0.116455078125 +87646 -0.105926513671875 +87647 -0.053955078125 +87648 0.048797607421875 +87649 0.157318115234375 +87650 0.212005615234375 +87651 0.218475341796875 +87652 0.23724365234375 +87653 0.30535888671875 +87654 0.38128662109375 +87655 0.404449462890625 +87656 0.3944091796875 +87657 0.3885498046875 +87658 0.362640380859375 +87659 0.27362060546875 +87660 0.11712646484375 +87661 -0.054901123046875 +87662 -0.19085693359375 +87663 -0.28570556640625 +87664 -0.339263916015625 +87665 -0.3775634765625 +87666 -0.445709228515625 +87667 -0.535064697265625 +87668 -0.629058837890625 +87669 -0.697601318359375 +87670 -0.70391845703125 +87671 -0.6424560546875 +87672 -0.491241455078125 +87673 -0.265716552734375 +87674 -0.023712158203125 +87675 0.201751708984375 +87676 0.375823974609375 +87677 0.485076904296875 +87678 0.56884765625 +87679 0.634765625 +87680 0.63763427734375 +87681 0.5660400390625 +87682 0.4720458984375 +87683 0.40692138671875 +87684 0.3778076171875 +87685 0.376953125 +87686 0.371978759765625 +87687 0.313140869140625 +87688 0.184417724609375 +87689 0.011199951171875 +87690 -0.171051025390625 +87691 -0.33740234375 +87692 -0.47198486328125 +87693 -0.560394287109375 +87694 -0.58056640625 +87695 -0.54754638671875 +87696 -0.508575439453125 +87697 -0.459503173828125 +87698 -0.394378662109375 +87699 -0.35260009765625 +87700 -0.31170654296875 +87701 -0.197418212890625 +87702 -0.007965087890625 +87703 0.207489013671875 +87704 0.409210205078125 +87705 0.57208251953125 +87706 0.66595458984375 +87707 0.65875244140625 +87708 0.56744384765625 +87709 0.431396484375 +87710 0.29443359375 +87711 0.182464599609375 +87712 0.06365966796875 +87713 -0.075958251953125 +87714 -0.189422607421875 +87715 -0.271942138671875 +87716 -0.342529296875 +87717 -0.364166259765625 +87718 -0.327239990234375 +87719 -0.2769775390625 +87720 -0.253692626953125 +87721 -0.24365234375 +87722 -0.1983642578125 +87723 -0.116241455078125 +87724 -0.036834716796875 +87725 0.034881591796875 +87726 0.09124755859375 +87727 0.10888671875 +87728 0.125518798828125 +87729 0.15771484375 +87730 0.17828369140625 +87731 0.17108154296875 +87732 0.129974365234375 +87733 0.082427978515625 +87734 0.027679443359375 +87735 -0.065643310546875 +87736 -0.15936279296875 +87737 -0.21307373046875 +87738 -0.234649658203125 +87739 -0.2001953125 +87740 -0.119171142578125 +87741 -0.024749755859375 +87742 0.085784912109375 +87743 0.178131103515625 +87744 0.215576171875 +87745 0.211456298828125 +87746 0.17523193359375 +87747 0.128753662109375 +87748 0.1019287109375 +87749 0.0743408203125 +87750 0.04327392578125 +87751 0.038177490234375 +87752 0.076263427734375 +87753 0.14105224609375 +87754 0.186431884765625 +87755 0.188812255859375 +87756 0.1390380859375 +87757 0.041778564453125 +87758 -0.079437255859375 +87759 -0.219390869140625 +87760 -0.367828369140625 +87761 -0.494873046875 +87762 -0.556243896484375 +87763 -0.508697509765625 +87764 -0.3756103515625 +87765 -0.218902587890625 +87766 -0.063751220703125 +87767 0.091552734375 +87768 0.23602294921875 +87769 0.342987060546875 +87770 0.39520263671875 +87771 0.389373779296875 +87772 0.324249267578125 +87773 0.224090576171875 +87774 0.124267578125 +87775 0.037078857421875 +87776 -0.010101318359375 +87777 -0.019439697265625 +87778 -0.022796630859375 +87779 -0.001556396484375 +87780 0.056304931640625 +87781 0.106719970703125 +87782 0.096893310546875 +87783 0.042694091796875 +87784 -0.018035888671875 +87785 -0.07586669921875 +87786 -0.11944580078125 +87787 -0.15972900390625 +87788 -0.202606201171875 +87789 -0.24859619140625 +87790 -0.30517578125 +87791 -0.36212158203125 +87792 -0.39141845703125 +87793 -0.35528564453125 +87794 -0.249969482421875 +87795 -0.092864990234375 +87796 0.08905029296875 +87797 0.2352294921875 +87798 0.318817138671875 +87799 0.358642578125 +87800 0.347747802734375 +87801 0.28564453125 +87802 0.223175048828125 +87803 0.196746826171875 +87804 0.179840087890625 +87805 0.155548095703125 +87806 0.151214599609375 +87807 0.156951904296875 +87808 0.13177490234375 +87809 0.100799560546875 +87810 0.087127685546875 +87811 0.05487060546875 +87812 -0.009002685546875 +87813 -0.10400390625 +87814 -0.229400634765625 +87815 -0.35552978515625 +87816 -0.441925048828125 +87817 -0.473846435546875 +87818 -0.464813232421875 +87819 -0.419097900390625 +87820 -0.334320068359375 +87821 -0.227935791015625 +87822 -0.12347412109375 +87823 -0.02764892578125 +87824 0.077667236328125 +87825 0.2132568359375 +87826 0.38885498046875 +87827 0.582794189453125 +87828 0.734039306640625 +87829 0.800140380859375 +87830 0.7783203125 +87831 0.6651611328125 +87832 0.45965576171875 +87833 0.199188232421875 +87834 -0.050689697265625 +87835 -0.23297119140625 +87836 -0.33013916015625 +87837 -0.368408203125 +87838 -0.378936767578125 +87839 -0.376983642578125 +87840 -0.37969970703125 +87841 -0.391510009765625 +87842 -0.385345458984375 +87843 -0.3419189453125 +87844 -0.28289794921875 +87845 -0.251617431640625 +87846 -0.266143798828125 +87847 -0.273345947265625 +87848 -0.216796875 +87849 -0.128265380859375 +87850 -0.068145751953125 +87851 -0.0430908203125 +87852 -0.024444580078125 +87853 0.020721435546875 +87854 0.124481201171875 +87855 0.25787353515625 +87856 0.379119873046875 +87857 0.47991943359375 +87858 0.5281982421875 +87859 0.511138916015625 +87860 0.456207275390625 +87861 0.407470703125 +87862 0.383758544921875 +87863 0.35687255859375 +87864 0.31182861328125 +87865 0.250885009765625 +87866 0.1654052734375 +87867 0.035247802734375 +87868 -0.142059326171875 +87869 -0.33563232421875 +87870 -0.5345458984375 +87871 -0.72186279296875 +87872 -0.836669921875 +87873 -0.8326416015625 +87874 -0.7296142578125 +87875 -0.582550048828125 +87876 -0.440093994140625 +87877 -0.324310302734375 +87878 -0.20147705078125 +87879 -0.044647216796875 +87880 0.103973388671875 +87881 0.202392578125 +87882 0.264495849609375 +87883 0.338897705078125 +87884 0.443817138671875 +87885 0.545074462890625 +87886 0.6173095703125 +87887 0.6524658203125 +87888 0.66339111328125 +87889 0.6561279296875 +87890 0.606781005859375 +87891 0.501190185546875 +87892 0.352783203125 +87893 0.176544189453125 +87894 -0.034820556640625 +87895 -0.258209228515625 +87896 -0.44244384765625 +87897 -0.5753173828125 +87898 -0.65203857421875 +87899 -0.641632080078125 +87900 -0.562164306640625 +87901 -0.458038330078125 +87902 -0.350555419921875 +87903 -0.260528564453125 +87904 -0.192108154296875 +87905 -0.141937255859375 +87906 -0.1021728515625 +87907 -0.062896728515625 +87908 -0.011932373046875 +87909 0.062835693359375 +87910 0.148712158203125 +87911 0.241729736328125 +87912 0.34912109375 +87913 0.457305908203125 +87914 0.54388427734375 +87915 0.5728759765625 +87916 0.506591796875 +87917 0.351226806640625 +87918 0.146514892578125 +87919 -0.05523681640625 +87920 -0.21624755859375 +87921 -0.334930419921875 +87922 -0.402984619140625 +87923 -0.4412841796875 +87924 -0.49578857421875 +87925 -0.5601806640625 +87926 -0.600738525390625 +87927 -0.584228515625 +87928 -0.47930908203125 +87929 -0.27935791015625 +87930 -0.0089111328125 +87931 0.268798828125 +87932 0.482818603515625 +87933 0.60369873046875 +87934 0.650421142578125 +87935 0.66400146484375 +87936 0.6414794921875 +87937 0.572540283203125 +87938 0.498138427734375 +87939 0.439453125 +87940 0.375518798828125 +87941 0.274505615234375 +87942 0.1087646484375 +87943 -0.099395751953125 +87944 -0.3182373046875 +87945 -0.5489501953125 +87946 -0.7738037109375 +87947 -0.86383056640625 +87948 -0.870391845703125 +87949 -0.86895751953125 +87950 -0.861053466796875 +87951 -0.765869140625 +87952 -0.5301513671875 +87953 -0.214691162109375 +87954 0.137359619140625 +87955 0.474822998046875 +87956 0.76239013671875 +87957 0.867462158203125 +87958 0.870361328125 +87959 0.86480712890625 +87960 0.831817626953125 +87961 0.677581787109375 +87962 0.495880126953125 +87963 0.30767822265625 +87964 0.116180419921875 +87965 -0.110748291015625 +87966 -0.381805419921875 +87967 -0.6572265625 +87968 -0.857421875 +87969 -0.870391845703125 +87970 -0.870391845703125 +87971 -0.86444091796875 +87972 -0.85723876953125 +87973 -0.790008544921875 +87974 -0.62847900390625 +87975 -0.3956298828125 +87976 -0.126708984375 +87977 0.150115966796875 +87978 0.424041748046875 +87979 0.670623779296875 +87980 0.854522705078125 +87981 0.866485595703125 +87982 0.86920166015625 +87983 0.8653564453125 +87984 0.857147216796875 +87985 0.766845703125 +87986 0.628509521484375 +87987 0.462127685546875 +87988 0.297210693359375 +87989 0.14862060546875 +87990 -0.00537109375 +87991 -0.15753173828125 +87992 -0.31304931640625 +87993 -0.48876953125 +87994 -0.6416015625 +87995 -0.751373291015625 +87996 -0.84619140625 +87997 -0.861297607421875 +87998 -0.863250732421875 +87999 -0.856597900390625 +88000 -0.7498779296875 +88001 -0.624542236328125 +88002 -0.47808837890625 +88003 -0.253387451171875 +88004 0.003692626953125 +88005 0.2257080078125 +88006 0.427154541015625 +88007 0.643218994140625 +88008 0.855926513671875 +88009 0.870361328125 +88010 0.870361328125 +88011 0.862762451171875 +88012 0.79669189453125 +88013 0.595794677734375 +88014 0.362152099609375 +88015 0.1270751953125 +88016 -0.086944580078125 +88017 -0.2784423828125 +88018 -0.484832763671875 +88019 -0.729583740234375 +88020 -0.86688232421875 +88021 -0.870391845703125 +88022 -0.86859130859375 +88023 -0.86279296875 +88024 -0.817962646484375 +88025 -0.6116943359375 +88026 -0.3128662109375 +88027 0.039398193359375 +88028 0.422821044921875 +88029 0.805145263671875 +88030 0.870361328125 +88031 0.870361328125 +88032 0.860015869140625 +88033 0.727935791015625 +88034 0.48114013671875 +88035 0.2059326171875 +88036 -0.06103515625 +88037 -0.29913330078125 +88038 -0.516204833984375 +88039 -0.7252197265625 +88040 -0.85980224609375 +88041 -0.870391845703125 +88042 -0.870391845703125 +88043 -0.858062744140625 +88044 -0.673004150390625 +88045 -0.42694091796875 +88046 -0.2100830078125 +88047 -0.0362548828125 +88048 0.10943603515625 +88049 0.23516845703125 +88050 0.373687744140625 +88051 0.517791748046875 +88052 0.602783203125 +88053 0.635711669921875 +88054 0.655181884765625 +88055 0.65948486328125 +88056 0.651275634765625 +88057 0.61846923828125 +88058 0.53753662109375 +88059 0.404144287109375 +88060 0.22186279296875 +88061 0.003997802734375 +88062 -0.22100830078125 +88063 -0.42449951171875 +88064 -0.579833984375 +88065 -0.641876220703125 +88066 -0.6177978515625 +88067 -0.575531005859375 +88068 -0.526336669921875 +88069 -0.42645263671875 +88070 -0.2581787109375 +88071 -0.068695068359375 +88072 0.09222412109375 +88073 0.232147216796875 +88074 0.3509521484375 +88075 0.410064697265625 +88076 0.372955322265625 +88077 0.2554931640625 +88078 0.10711669921875 +88079 -0.052886962890625 +88080 -0.186279296875 +88081 -0.23291015625 +88082 -0.209442138671875 +88083 -0.174163818359375 +88084 -0.126739501953125 +88085 -0.048126220703125 +88086 0.0426025390625 +88087 0.10748291015625 +88088 0.1409912109375 +88089 0.19708251953125 +88090 0.273651123046875 +88091 0.31768798828125 +88092 0.341094970703125 +88093 0.368011474609375 +88094 0.37249755859375 +88095 0.30072021484375 +88096 0.1517333984375 +88097 -0.01470947265625 +88098 -0.1883544921875 +88099 -0.372711181640625 +88100 -0.51397705078125 +88101 -0.57177734375 +88102 -0.53948974609375 +88103 -0.43511962890625 +88104 -0.2962646484375 +88105 -0.161102294921875 +88106 -0.0435791015625 +88107 0.060394287109375 +88108 0.13665771484375 +88109 0.170135498046875 +88110 0.16552734375 +88111 0.15728759765625 +88112 0.150787353515625 +88113 0.12200927734375 +88114 0.080108642578125 +88115 0.05126953125 +88116 0.062896728515625 +88117 0.09271240234375 +88118 0.092987060546875 +88119 0.07855224609375 +88120 0.06427001953125 +88121 0.0347900390625 +88122 -0.01171875 +88123 -0.056060791015625 +88124 -0.055511474609375 +88125 -0.010467529296875 +88126 0.02508544921875 +88127 0.025665283203125 +88128 0.017333984375 +88129 0.00189208984375 +88130 -0.03173828125 +88131 -0.071502685546875 +88132 -0.13543701171875 +88133 -0.219970703125 +88134 -0.300506591796875 +88135 -0.376312255859375 +88136 -0.416107177734375 +88137 -0.371124267578125 +88138 -0.242279052734375 +88139 -0.069732666015625 +88140 0.125640869140625 +88141 0.31268310546875 +88142 0.45501708984375 +88143 0.554779052734375 +88144 0.61065673828125 +88145 0.610931396484375 +88146 0.531463623046875 +88147 0.3883056640625 +88148 0.23468017578125 +88149 0.095245361328125 +88150 -0.00396728515625 +88151 -0.04852294921875 +88152 -0.055145263671875 +88153 -0.0758056640625 +88154 -0.138702392578125 +88155 -0.209197998046875 +88156 -0.289031982421875 +88157 -0.37884521484375 +88158 -0.456329345703125 +88159 -0.51641845703125 +88160 -0.519287109375 +88161 -0.458251953125 +88162 -0.384796142578125 +88163 -0.323699951171875 +88164 -0.269287109375 +88165 -0.1951904296875 +88166 -0.100006103515625 +88167 -0.01055908203125 +88168 0.1033935546875 +88169 0.24908447265625 +88170 0.373199462890625 +88171 0.45806884765625 +88172 0.511474609375 +88173 0.565399169921875 +88174 0.61138916015625 +88175 0.5897216796875 +88176 0.4906005859375 +88177 0.33148193359375 +88178 0.147796630859375 +88179 -0.01873779296875 +88180 -0.140289306640625 +88181 -0.191986083984375 +88182 -0.184295654296875 +88183 -0.161834716796875 +88184 -0.166595458984375 +88185 -0.19390869140625 +88186 -0.22442626953125 +88187 -0.279754638671875 +88188 -0.3389892578125 +88189 -0.3543701171875 +88190 -0.348175048828125 +88191 -0.32598876953125 +88192 -0.2581787109375 +88193 -0.139801025390625 +88194 0.014617919921875 +88195 0.144378662109375 +88196 0.221038818359375 +88197 0.27069091796875 +88198 0.294036865234375 +88199 0.311767578125 +88200 0.339141845703125 +88201 0.360260009765625 +88202 0.360504150390625 +88203 0.308380126953125 +88204 0.18170166015625 +88205 0.0047607421875 +88206 -0.17559814453125 +88207 -0.3143310546875 +88208 -0.36785888671875 +88209 -0.36248779296875 +88210 -0.343536376953125 +88211 -0.3018798828125 +88212 -0.231414794921875 +88213 -0.117645263671875 +88214 0.007049560546875 +88215 0.087982177734375 +88216 0.13946533203125 +88217 0.17425537109375 +88218 0.188201904296875 +88219 0.171234130859375 +88220 0.118438720703125 +88221 0.05706787109375 +88222 -0.010711669921875 +88223 -0.0914306640625 +88224 -0.162322998046875 +88225 -0.194549560546875 +88226 -0.1492919921875 +88227 -0.02166748046875 +88228 0.124053955078125 +88229 0.211151123046875 +88230 0.240447998046875 +88231 0.242218017578125 +88232 0.2257080078125 +88233 0.194366455078125 +88234 0.115509033203125 +88235 0.0128173828125 +88236 -0.053802490234375 +88237 -0.110626220703125 +88238 -0.199493408203125 +88239 -0.29437255859375 +88240 -0.33221435546875 +88241 -0.27972412109375 +88242 -0.185333251953125 +88243 -0.128204345703125 +88244 -0.115692138671875 +88245 -0.116455078125 +88246 -0.105926513671875 +88247 -0.053955078125 +88248 0.048797607421875 +88249 0.157318115234375 +88250 0.212005615234375 +88251 0.218475341796875 +88252 0.23724365234375 +88253 0.30535888671875 +88254 0.38128662109375 +88255 0.404449462890625 +88256 0.3944091796875 +88257 0.3885498046875 +88258 0.362640380859375 +88259 0.27362060546875 +88260 0.11712646484375 +88261 -0.054901123046875 +88262 -0.19085693359375 +88263 -0.28570556640625 +88264 -0.339263916015625 +88265 -0.3775634765625 +88266 -0.445709228515625 +88267 -0.535064697265625 +88268 -0.629058837890625 +88269 -0.697601318359375 +88270 -0.70391845703125 +88271 -0.6424560546875 +88272 -0.491241455078125 +88273 -0.265716552734375 +88274 -0.023712158203125 +88275 0.201751708984375 +88276 0.375823974609375 +88277 0.485076904296875 +88278 0.56884765625 +88279 0.634765625 +88280 0.63763427734375 +88281 0.5660400390625 +88282 0.4720458984375 +88283 0.40692138671875 +88284 0.3778076171875 +88285 0.376953125 +88286 0.371978759765625 +88287 0.313140869140625 +88288 0.184417724609375 +88289 0.011199951171875 +88290 -0.171051025390625 +88291 -0.33740234375 +88292 -0.47198486328125 +88293 -0.560394287109375 +88294 -0.58056640625 +88295 -0.54754638671875 +88296 -0.508575439453125 +88297 -0.459503173828125 +88298 -0.394378662109375 +88299 -0.35260009765625 +88300 -0.31170654296875 +88301 -0.197418212890625 +88302 -0.007965087890625 +88303 0.207489013671875 +88304 0.409210205078125 +88305 0.57208251953125 +88306 0.66595458984375 +88307 0.65875244140625 +88308 0.56744384765625 +88309 0.431396484375 +88310 0.29443359375 +88311 0.182464599609375 +88312 0.06365966796875 +88313 -0.075958251953125 +88314 -0.189422607421875 +88315 -0.271942138671875 +88316 -0.342529296875 +88317 -0.364166259765625 +88318 -0.327239990234375 +88319 -0.2769775390625 +88320 -0.253692626953125 +88321 -0.24365234375 +88322 -0.1983642578125 +88323 -0.116241455078125 +88324 -0.036834716796875 +88325 0.034881591796875 +88326 0.09124755859375 +88327 0.10888671875 +88328 0.125518798828125 +88329 0.15771484375 +88330 0.17828369140625 +88331 0.17108154296875 +88332 0.129974365234375 +88333 0.082427978515625 +88334 0.027679443359375 +88335 -0.065643310546875 +88336 -0.15936279296875 +88337 -0.21307373046875 +88338 -0.234649658203125 +88339 -0.2001953125 +88340 -0.119171142578125 +88341 -0.024749755859375 +88342 0.085784912109375 +88343 0.178131103515625 +88344 0.215576171875 +88345 0.211456298828125 +88346 0.17523193359375 +88347 0.128753662109375 +88348 0.1019287109375 +88349 0.0743408203125 +88350 0.04327392578125 +88351 0.038177490234375 +88352 0.076263427734375 +88353 0.14105224609375 +88354 0.186431884765625 +88355 0.188812255859375 +88356 0.1390380859375 +88357 0.041778564453125 +88358 -0.079437255859375 +88359 -0.219390869140625 +88360 -0.367828369140625 +88361 -0.494873046875 +88362 -0.556243896484375 +88363 -0.508697509765625 +88364 -0.3756103515625 +88365 -0.218902587890625 +88366 -0.063751220703125 +88367 0.091552734375 +88368 0.23602294921875 +88369 0.342987060546875 +88370 0.39520263671875 +88371 0.389373779296875 +88372 0.324249267578125 +88373 0.224090576171875 +88374 0.124267578125 +88375 0.037078857421875 +88376 -0.010101318359375 +88377 -0.019439697265625 +88378 -0.022796630859375 +88379 -0.001556396484375 +88380 0.056304931640625 +88381 0.106719970703125 +88382 0.096893310546875 +88383 0.042694091796875 +88384 -0.018035888671875 +88385 -0.07586669921875 +88386 -0.11944580078125 +88387 -0.15972900390625 +88388 -0.202606201171875 +88389 -0.24859619140625 +88390 -0.30517578125 +88391 -0.36212158203125 +88392 -0.39141845703125 +88393 -0.35528564453125 +88394 -0.249969482421875 +88395 -0.092864990234375 +88396 0.08905029296875 +88397 0.2352294921875 +88398 0.318817138671875 +88399 0.358642578125 +88400 0.347747802734375 +88401 0.28564453125 +88402 0.223175048828125 +88403 0.196746826171875 +88404 0.179840087890625 +88405 0.155548095703125 +88406 0.151214599609375 +88407 0.156951904296875 +88408 0.13177490234375 +88409 0.100799560546875 +88410 0.087127685546875 +88411 0.05487060546875 +88412 -0.009002685546875 +88413 -0.10400390625 +88414 -0.229400634765625 +88415 -0.35552978515625 +88416 -0.441925048828125 +88417 -0.473846435546875 +88418 -0.464813232421875 +88419 -0.419097900390625 +88420 -0.334320068359375 +88421 -0.227935791015625 +88422 -0.12347412109375 +88423 -0.02764892578125 +88424 0.077667236328125 +88425 0.2132568359375 +88426 0.38885498046875 +88427 0.582794189453125 +88428 0.734039306640625 +88429 0.800140380859375 +88430 0.7783203125 +88431 0.6651611328125 +88432 0.45965576171875 +88433 0.199188232421875 +88434 -0.050689697265625 +88435 -0.23297119140625 +88436 -0.33013916015625 +88437 -0.368408203125 +88438 -0.378936767578125 +88439 -0.376983642578125 +88440 -0.37969970703125 +88441 -0.391510009765625 +88442 -0.385345458984375 +88443 -0.3419189453125 +88444 -0.28289794921875 +88445 -0.251617431640625 +88446 -0.266143798828125 +88447 -0.273345947265625 +88448 -0.216796875 +88449 -0.128265380859375 +88450 -0.068145751953125 +88451 -0.0430908203125 +88452 -0.024444580078125 +88453 0.020721435546875 +88454 0.124481201171875 +88455 0.25787353515625 +88456 0.379119873046875 +88457 0.47991943359375 +88458 0.5281982421875 +88459 0.511138916015625 +88460 0.456207275390625 +88461 0.407470703125 +88462 0.383758544921875 +88463 0.35687255859375 +88464 0.31182861328125 +88465 0.250885009765625 +88466 0.1654052734375 +88467 0.035247802734375 +88468 -0.142059326171875 +88469 -0.33563232421875 +88470 -0.5345458984375 +88471 -0.72186279296875 +88472 -0.836669921875 +88473 -0.8326416015625 +88474 -0.7296142578125 +88475 -0.582550048828125 +88476 -0.440093994140625 +88477 -0.324310302734375 +88478 -0.20147705078125 +88479 -0.044647216796875 +88480 0.103973388671875 +88481 0.202392578125 +88482 0.264495849609375 +88483 0.338897705078125 +88484 0.443817138671875 +88485 0.545074462890625 +88486 0.6173095703125 +88487 0.6524658203125 +88488 0.66339111328125 +88489 0.6561279296875 +88490 0.606781005859375 +88491 0.501190185546875 +88492 0.352783203125 +88493 0.176544189453125 +88494 -0.034820556640625 +88495 -0.258209228515625 +88496 -0.44244384765625 +88497 -0.5753173828125 +88498 -0.65203857421875 +88499 -0.641632080078125 +88500 -0.562164306640625 +88501 -0.458038330078125 +88502 -0.350555419921875 +88503 -0.260528564453125 +88504 -0.192108154296875 +88505 -0.141937255859375 +88506 -0.1021728515625 +88507 -0.062896728515625 +88508 -0.011932373046875 +88509 0.062835693359375 +88510 0.148712158203125 +88511 0.241729736328125 +88512 0.34912109375 +88513 0.457305908203125 +88514 0.54388427734375 +88515 0.5728759765625 +88516 0.506591796875 +88517 0.351226806640625 +88518 0.146514892578125 +88519 -0.05523681640625 +88520 -0.21624755859375 +88521 -0.334930419921875 +88522 -0.402984619140625 +88523 -0.4412841796875 +88524 -0.49578857421875 +88525 -0.5601806640625 +88526 -0.600738525390625 +88527 -0.584228515625 +88528 -0.47930908203125 +88529 -0.27935791015625 +88530 -0.0089111328125 +88531 0.268798828125 +88532 0.482818603515625 +88533 0.60369873046875 +88534 0.650421142578125 +88535 0.66400146484375 +88536 0.6414794921875 +88537 0.572540283203125 +88538 0.498138427734375 +88539 0.439453125 +88540 0.375518798828125 +88541 0.274505615234375 +88542 0.1087646484375 +88543 -0.099395751953125 +88544 -0.3182373046875 +88545 -0.5489501953125 +88546 -0.7738037109375 +88547 -0.86383056640625 +88548 -0.870391845703125 +88549 -0.86895751953125 +88550 -0.861053466796875 +88551 -0.765869140625 +88552 -0.5301513671875 +88553 -0.214691162109375 +88554 0.137359619140625 +88555 0.474822998046875 +88556 0.76239013671875 +88557 0.867462158203125 +88558 0.870361328125 +88559 0.86480712890625 +88560 0.831817626953125 +88561 0.677581787109375 +88562 0.495880126953125 +88563 0.30767822265625 +88564 0.116180419921875 +88565 -0.110748291015625 +88566 -0.381805419921875 +88567 -0.6572265625 +88568 -0.857421875 +88569 -0.870391845703125 +88570 -0.870391845703125 +88571 -0.86444091796875 +88572 -0.85723876953125 +88573 -0.790008544921875 +88574 -0.62847900390625 +88575 -0.3956298828125 +88576 -0.126708984375 +88577 0.150115966796875 +88578 0.424041748046875 +88579 0.670623779296875 +88580 0.854522705078125 +88581 0.866485595703125 +88582 0.86920166015625 +88583 0.8653564453125 +88584 0.857147216796875 +88585 0.766845703125 +88586 0.628509521484375 +88587 0.462127685546875 +88588 0.297210693359375 +88589 0.14862060546875 +88590 -0.00537109375 +88591 -0.15753173828125 +88592 -0.31304931640625 +88593 -0.48876953125 +88594 -0.6416015625 +88595 -0.751373291015625 +88596 -0.84619140625 +88597 -0.861297607421875 +88598 -0.863250732421875 +88599 -0.856597900390625 +88600 -0.7498779296875 +88601 -0.624542236328125 +88602 -0.47808837890625 +88603 -0.253387451171875 +88604 0.003692626953125 +88605 0.2257080078125 +88606 0.427154541015625 +88607 0.643218994140625 +88608 0.855926513671875 +88609 0.870361328125 +88610 0.870361328125 +88611 0.862762451171875 +88612 0.79669189453125 +88613 0.595794677734375 +88614 0.362152099609375 +88615 0.1270751953125 +88616 -0.086944580078125 +88617 -0.2784423828125 +88618 -0.484832763671875 +88619 -0.729583740234375 +88620 -0.86688232421875 +88621 -0.870391845703125 +88622 -0.86859130859375 +88623 -0.86279296875 +88624 -0.817962646484375 +88625 -0.6116943359375 +88626 -0.3128662109375 +88627 0.039398193359375 +88628 0.422821044921875 +88629 0.805145263671875 +88630 0.870361328125 +88631 0.870361328125 +88632 0.860015869140625 +88633 0.727935791015625 +88634 0.48114013671875 +88635 0.2059326171875 +88636 -0.06103515625 +88637 -0.29913330078125 +88638 -0.516204833984375 +88639 -0.7252197265625 +88640 -0.85980224609375 +88641 -0.870391845703125 +88642 -0.870391845703125 +88643 -0.858062744140625 +88644 -0.673004150390625 +88645 -0.42694091796875 +88646 -0.2100830078125 +88647 -0.0362548828125 +88648 0.10943603515625 +88649 0.23516845703125 +88650 0.373687744140625 +88651 0.517791748046875 +88652 0.602783203125 +88653 0.635711669921875 +88654 0.655181884765625 +88655 0.65948486328125 +88656 0.651275634765625 +88657 0.61846923828125 +88658 0.53753662109375 +88659 0.404144287109375 +88660 0.22186279296875 +88661 0.003997802734375 +88662 -0.22100830078125 +88663 -0.42449951171875 +88664 -0.579833984375 +88665 -0.641876220703125 +88666 -0.6177978515625 +88667 -0.575531005859375 +88668 -0.526336669921875 +88669 -0.42645263671875 +88670 -0.2581787109375 +88671 -0.068695068359375 +88672 0.09222412109375 +88673 0.232147216796875 +88674 0.3509521484375 +88675 0.410064697265625 +88676 0.372955322265625 +88677 0.2554931640625 +88678 0.10711669921875 +88679 -0.052886962890625 +88680 -0.186279296875 +88681 -0.23291015625 +88682 -0.209442138671875 +88683 -0.174163818359375 +88684 -0.126739501953125 +88685 -0.048126220703125 +88686 0.0426025390625 +88687 0.10748291015625 +88688 0.1409912109375 +88689 0.19708251953125 +88690 0.273651123046875 +88691 0.31768798828125 +88692 0.341094970703125 +88693 0.368011474609375 +88694 0.37249755859375 +88695 0.30072021484375 +88696 0.1517333984375 +88697 -0.01470947265625 +88698 -0.1883544921875 +88699 -0.372711181640625 +88700 -0.51397705078125 +88701 -0.57177734375 +88702 -0.53948974609375 +88703 -0.43511962890625 +88704 -0.2962646484375 +88705 -0.161102294921875 +88706 -0.0435791015625 +88707 0.060394287109375 +88708 0.13665771484375 +88709 0.170135498046875 +88710 0.16552734375 +88711 0.15728759765625 +88712 0.150787353515625 +88713 0.12200927734375 +88714 0.080108642578125 +88715 0.05126953125 +88716 0.062896728515625 +88717 0.09271240234375 +88718 0.092987060546875 +88719 0.07855224609375 +88720 0.06427001953125 +88721 0.0347900390625 +88722 -0.01171875 +88723 -0.056060791015625 +88724 -0.055511474609375 +88725 -0.010467529296875 +88726 0.02508544921875 +88727 0.025665283203125 +88728 0.017333984375 +88729 0.00189208984375 +88730 -0.03173828125 +88731 -0.071502685546875 +88732 -0.13543701171875 +88733 -0.219970703125 +88734 -0.300506591796875 +88735 -0.376312255859375 +88736 -0.416107177734375 +88737 -0.371124267578125 +88738 -0.242279052734375 +88739 -0.069732666015625 +88740 0.125640869140625 +88741 0.31268310546875 +88742 0.45501708984375 +88743 0.554779052734375 +88744 0.61065673828125 +88745 0.610931396484375 +88746 0.531463623046875 +88747 0.3883056640625 +88748 0.23468017578125 +88749 0.095245361328125 +88750 -0.00396728515625 +88751 -0.04852294921875 +88752 -0.055145263671875 +88753 -0.0758056640625 +88754 -0.138702392578125 +88755 -0.209197998046875 +88756 -0.289031982421875 +88757 -0.37884521484375 +88758 -0.456329345703125 +88759 -0.51641845703125 +88760 -0.519287109375 +88761 -0.458251953125 +88762 -0.384796142578125 +88763 -0.323699951171875 +88764 -0.269287109375 +88765 -0.1951904296875 +88766 -0.100006103515625 +88767 -0.01055908203125 +88768 0.1033935546875 +88769 0.24908447265625 +88770 0.373199462890625 +88771 0.45806884765625 +88772 0.511474609375 +88773 0.565399169921875 +88774 0.61138916015625 +88775 0.5897216796875 +88776 0.4906005859375 +88777 0.33148193359375 +88778 0.147796630859375 +88779 -0.01873779296875 +88780 -0.140289306640625 +88781 -0.191986083984375 +88782 -0.184295654296875 +88783 -0.161834716796875 +88784 -0.166595458984375 +88785 -0.19390869140625 +88786 -0.22442626953125 +88787 -0.279754638671875 +88788 -0.3389892578125 +88789 -0.3543701171875 +88790 -0.348175048828125 +88791 -0.32598876953125 +88792 -0.2581787109375 +88793 -0.139801025390625 +88794 0.014617919921875 +88795 0.144378662109375 +88796 0.221038818359375 +88797 0.27069091796875 +88798 0.294036865234375 +88799 0.311767578125 +88800 0.339141845703125 +88801 0.360260009765625 +88802 0.360504150390625 +88803 0.308380126953125 +88804 0.18170166015625 +88805 0.0047607421875 +88806 -0.17559814453125 +88807 -0.3143310546875 +88808 -0.36785888671875 +88809 -0.36248779296875 +88810 -0.343536376953125 +88811 -0.3018798828125 +88812 -0.231414794921875 +88813 -0.117645263671875 +88814 0.007049560546875 +88815 0.087982177734375 +88816 0.13946533203125 +88817 0.17425537109375 +88818 0.188201904296875 +88819 0.171234130859375 +88820 0.118438720703125 +88821 0.05706787109375 +88822 -0.010711669921875 +88823 -0.0914306640625 +88824 -0.162322998046875 +88825 -0.194549560546875 +88826 -0.1492919921875 +88827 -0.02166748046875 +88828 0.124053955078125 +88829 0.211151123046875 +88830 0.240447998046875 +88831 0.242218017578125 +88832 0.2257080078125 +88833 0.194366455078125 +88834 0.115509033203125 +88835 0.0128173828125 +88836 -0.053802490234375 +88837 -0.110626220703125 +88838 -0.199493408203125 +88839 -0.29437255859375 +88840 -0.33221435546875 +88841 -0.27972412109375 +88842 -0.185333251953125 +88843 -0.128204345703125 +88844 -0.115692138671875 +88845 -0.116455078125 +88846 -0.105926513671875 +88847 -0.053955078125 +88848 0.048797607421875 +88849 0.157318115234375 +88850 0.212005615234375 +88851 0.218475341796875 +88852 0.23724365234375 +88853 0.30535888671875 +88854 0.38128662109375 +88855 0.404449462890625 +88856 0.3944091796875 +88857 0.3885498046875 +88858 0.362640380859375 +88859 0.27362060546875 +88860 0.11712646484375 +88861 -0.054901123046875 +88862 -0.19085693359375 +88863 -0.28570556640625 +88864 -0.339263916015625 +88865 -0.3775634765625 +88866 -0.445709228515625 +88867 -0.535064697265625 +88868 -0.629058837890625 +88869 -0.697601318359375 +88870 -0.70391845703125 +88871 -0.6424560546875 +88872 -0.491241455078125 +88873 -0.265716552734375 +88874 -0.023712158203125 +88875 0.201751708984375 +88876 0.375823974609375 +88877 0.485076904296875 +88878 0.56884765625 +88879 0.634765625 +88880 0.63763427734375 +88881 0.5660400390625 +88882 0.4720458984375 +88883 0.40692138671875 +88884 0.3778076171875 +88885 0.376953125 +88886 0.371978759765625 +88887 0.313140869140625 +88888 0.184417724609375 +88889 0.011199951171875 +88890 -0.171051025390625 +88891 -0.33740234375 +88892 -0.47198486328125 +88893 -0.560394287109375 +88894 -0.58056640625 +88895 -0.54754638671875 +88896 -0.508575439453125 +88897 -0.459503173828125 +88898 -0.394378662109375 +88899 -0.35260009765625 +88900 -0.31170654296875 +88901 -0.197418212890625 +88902 -0.007965087890625 +88903 0.207489013671875 +88904 0.409210205078125 +88905 0.57208251953125 +88906 0.66595458984375 +88907 0.65875244140625 +88908 0.56744384765625 +88909 0.431396484375 +88910 0.29443359375 +88911 0.182464599609375 +88912 0.06365966796875 +88913 -0.075958251953125 +88914 -0.189422607421875 +88915 -0.271942138671875 +88916 -0.342529296875 +88917 -0.364166259765625 +88918 -0.327239990234375 +88919 -0.2769775390625 +88920 -0.253692626953125 +88921 -0.24365234375 +88922 -0.1983642578125 +88923 -0.116241455078125 +88924 -0.036834716796875 +88925 0.034881591796875 +88926 0.09124755859375 +88927 0.10888671875 +88928 0.125518798828125 +88929 0.15771484375 +88930 0.17828369140625 +88931 0.17108154296875 +88932 0.129974365234375 +88933 0.082427978515625 +88934 0.027679443359375 +88935 -0.065643310546875 +88936 -0.15936279296875 +88937 -0.21307373046875 +88938 -0.234649658203125 +88939 -0.2001953125 +88940 -0.119171142578125 +88941 -0.024749755859375 +88942 0.085784912109375 +88943 0.178131103515625 +88944 0.215576171875 +88945 0.211456298828125 +88946 0.17523193359375 +88947 0.128753662109375 +88948 0.1019287109375 +88949 0.0743408203125 +88950 0.04327392578125 +88951 0.038177490234375 +88952 0.076263427734375 +88953 0.14105224609375 +88954 0.186431884765625 +88955 0.188812255859375 +88956 0.1390380859375 +88957 0.041778564453125 +88958 -0.079437255859375 +88959 -0.219390869140625 +88960 -0.367828369140625 +88961 -0.494873046875 +88962 -0.556243896484375 +88963 -0.508697509765625 +88964 -0.3756103515625 +88965 -0.218902587890625 +88966 -0.063751220703125 +88967 0.091552734375 +88968 0.23602294921875 +88969 0.342987060546875 +88970 0.39520263671875 +88971 0.389373779296875 +88972 0.324249267578125 +88973 0.224090576171875 +88974 0.124267578125 +88975 0.037078857421875 +88976 -0.010101318359375 +88977 -0.019439697265625 +88978 -0.022796630859375 +88979 -0.001556396484375 +88980 0.056304931640625 +88981 0.106719970703125 +88982 0.096893310546875 +88983 0.042694091796875 +88984 -0.018035888671875 +88985 -0.07586669921875 +88986 -0.11944580078125 +88987 -0.15972900390625 +88988 -0.202606201171875 +88989 -0.24859619140625 +88990 -0.30517578125 +88991 -0.36212158203125 +88992 -0.39141845703125 +88993 -0.35528564453125 +88994 -0.249969482421875 +88995 -0.092864990234375 +88996 0.08905029296875 +88997 0.2352294921875 +88998 0.318817138671875 +88999 0.358642578125 +89000 0.347747802734375 +89001 0.28564453125 +89002 0.223175048828125 +89003 0.196746826171875 +89004 0.179840087890625 +89005 0.155548095703125 +89006 0.151214599609375 +89007 0.156951904296875 +89008 0.13177490234375 +89009 0.100799560546875 +89010 0.087127685546875 +89011 0.05487060546875 +89012 -0.009002685546875 +89013 -0.10400390625 +89014 -0.229400634765625 +89015 -0.35552978515625 +89016 -0.441925048828125 +89017 -0.473846435546875 +89018 -0.464813232421875 +89019 -0.419097900390625 +89020 -0.334320068359375 +89021 -0.227935791015625 +89022 -0.12347412109375 +89023 -0.02764892578125 +89024 0.077667236328125 +89025 0.2132568359375 +89026 0.38885498046875 +89027 0.582794189453125 +89028 0.734039306640625 +89029 0.800140380859375 +89030 0.7783203125 +89031 0.6651611328125 +89032 0.45965576171875 +89033 0.199188232421875 +89034 -0.050689697265625 +89035 -0.23297119140625 +89036 -0.33013916015625 +89037 -0.368408203125 +89038 -0.378936767578125 +89039 -0.376983642578125 +89040 -0.37969970703125 +89041 -0.391510009765625 +89042 -0.385345458984375 +89043 -0.3419189453125 +89044 -0.28289794921875 +89045 -0.251617431640625 +89046 -0.266143798828125 +89047 -0.273345947265625 +89048 -0.216796875 +89049 -0.128265380859375 +89050 -0.068145751953125 +89051 -0.0430908203125 +89052 -0.024444580078125 +89053 0.020721435546875 +89054 0.124481201171875 +89055 0.25787353515625 +89056 0.379119873046875 +89057 0.47991943359375 +89058 0.5281982421875 +89059 0.511138916015625 +89060 0.456207275390625 +89061 0.407470703125 +89062 0.383758544921875 +89063 0.35687255859375 +89064 0.31182861328125 +89065 0.250885009765625 +89066 0.1654052734375 +89067 0.035247802734375 +89068 -0.142059326171875 +89069 -0.33563232421875 +89070 -0.5345458984375 +89071 -0.72186279296875 +89072 -0.836669921875 +89073 -0.8326416015625 +89074 -0.7296142578125 +89075 -0.582550048828125 +89076 -0.440093994140625 +89077 -0.324310302734375 +89078 -0.20147705078125 +89079 -0.044647216796875 +89080 0.103973388671875 +89081 0.202392578125 +89082 0.264495849609375 +89083 0.338897705078125 +89084 0.443817138671875 +89085 0.545074462890625 +89086 0.6173095703125 +89087 0.6524658203125 +89088 0.66339111328125 +89089 0.6561279296875 +89090 0.606781005859375 +89091 0.501190185546875 +89092 0.352783203125 +89093 0.176544189453125 +89094 -0.034820556640625 +89095 -0.258209228515625 +89096 -0.44244384765625 +89097 -0.5753173828125 +89098 -0.65203857421875 +89099 -0.641632080078125 +89100 -0.562164306640625 +89101 -0.458038330078125 +89102 -0.350555419921875 +89103 -0.260528564453125 +89104 -0.192108154296875 +89105 -0.141937255859375 +89106 -0.1021728515625 +89107 -0.062896728515625 +89108 -0.011932373046875 +89109 0.062835693359375 +89110 0.148712158203125 +89111 0.241729736328125 +89112 0.34912109375 +89113 0.457305908203125 +89114 0.54388427734375 +89115 0.5728759765625 +89116 0.506591796875 +89117 0.351226806640625 +89118 0.146514892578125 +89119 -0.05523681640625 +89120 -0.21624755859375 +89121 -0.334930419921875 +89122 -0.402984619140625 +89123 -0.4412841796875 +89124 -0.49578857421875 +89125 -0.5601806640625 +89126 -0.600738525390625 +89127 -0.584228515625 +89128 -0.47930908203125 +89129 -0.27935791015625 +89130 -0.0089111328125 +89131 0.268798828125 +89132 0.482818603515625 +89133 0.60369873046875 +89134 0.650421142578125 +89135 0.66400146484375 +89136 0.6414794921875 +89137 0.572540283203125 +89138 0.498138427734375 +89139 0.439453125 +89140 0.375518798828125 +89141 0.274505615234375 +89142 0.1087646484375 +89143 -0.099395751953125 +89144 -0.3182373046875 +89145 -0.5489501953125 +89146 -0.7738037109375 +89147 -0.86383056640625 +89148 -0.870391845703125 +89149 -0.86895751953125 +89150 -0.861053466796875 +89151 -0.765869140625 +89152 -0.5301513671875 +89153 -0.214691162109375 +89154 0.137359619140625 +89155 0.474822998046875 +89156 0.76239013671875 +89157 0.867462158203125 +89158 0.870361328125 +89159 0.86480712890625 +89160 0.831817626953125 +89161 0.677581787109375 +89162 0.495880126953125 +89163 0.30767822265625 +89164 0.116180419921875 +89165 -0.110748291015625 +89166 -0.381805419921875 +89167 -0.6572265625 +89168 -0.857421875 +89169 -0.870391845703125 +89170 -0.870391845703125 +89171 -0.86444091796875 +89172 -0.85723876953125 +89173 -0.790008544921875 +89174 -0.62847900390625 +89175 -0.3956298828125 +89176 -0.126708984375 +89177 0.150115966796875 +89178 0.424041748046875 +89179 0.670623779296875 +89180 0.854522705078125 +89181 0.866485595703125 +89182 0.86920166015625 +89183 0.8653564453125 +89184 0.857147216796875 +89185 0.766845703125 +89186 0.628509521484375 +89187 0.462127685546875 +89188 0.297210693359375 +89189 0.14862060546875 +89190 -0.00537109375 +89191 -0.15753173828125 +89192 -0.31304931640625 +89193 -0.48876953125 +89194 -0.6416015625 +89195 -0.751373291015625 +89196 -0.84619140625 +89197 -0.861297607421875 +89198 -0.863250732421875 +89199 -0.856597900390625 +89200 -0.7498779296875 +89201 -0.624542236328125 +89202 -0.47808837890625 +89203 -0.253387451171875 +89204 0.003692626953125 +89205 0.2257080078125 +89206 0.427154541015625 +89207 0.643218994140625 +89208 0.855926513671875 +89209 0.870361328125 +89210 0.870361328125 +89211 0.862762451171875 +89212 0.79669189453125 +89213 0.595794677734375 +89214 0.362152099609375 +89215 0.1270751953125 +89216 -0.086944580078125 +89217 -0.2784423828125 +89218 -0.484832763671875 +89219 -0.729583740234375 +89220 -0.86688232421875 +89221 -0.870391845703125 +89222 -0.86859130859375 +89223 -0.86279296875 +89224 -0.817962646484375 +89225 -0.6116943359375 +89226 -0.3128662109375 +89227 0.039398193359375 +89228 0.422821044921875 +89229 0.805145263671875 +89230 0.870361328125 +89231 0.870361328125 +89232 0.860015869140625 +89233 0.727935791015625 +89234 0.48114013671875 +89235 0.2059326171875 +89236 -0.06103515625 +89237 -0.29913330078125 +89238 -0.516204833984375 +89239 -0.7252197265625 +89240 -0.85980224609375 +89241 -0.870391845703125 +89242 -0.870391845703125 +89243 -0.858062744140625 +89244 -0.673004150390625 +89245 -0.42694091796875 +89246 -0.2100830078125 +89247 -0.0362548828125 +89248 0.10943603515625 +89249 0.23516845703125 +89250 0.373687744140625 +89251 0.517791748046875 +89252 0.602783203125 +89253 0.635711669921875 +89254 0.655181884765625 +89255 0.65948486328125 +89256 0.651275634765625 +89257 0.61846923828125 +89258 0.53753662109375 +89259 0.404144287109375 +89260 0.22186279296875 +89261 0.003997802734375 +89262 -0.22100830078125 +89263 -0.42449951171875 +89264 -0.579833984375 +89265 -0.641876220703125 +89266 -0.6177978515625 +89267 -0.575531005859375 +89268 -0.526336669921875 +89269 -0.42645263671875 +89270 -0.2581787109375 +89271 -0.068695068359375 +89272 0.09222412109375 +89273 0.232147216796875 +89274 0.3509521484375 +89275 0.410064697265625 +89276 0.372955322265625 +89277 0.2554931640625 +89278 0.10711669921875 +89279 -0.052886962890625 +89280 -0.186279296875 +89281 -0.23291015625 +89282 -0.209442138671875 +89283 -0.174163818359375 +89284 -0.126739501953125 +89285 -0.048126220703125 +89286 0.0426025390625 +89287 0.10748291015625 +89288 0.1409912109375 +89289 0.19708251953125 +89290 0.273651123046875 +89291 0.31768798828125 +89292 0.341094970703125 +89293 0.368011474609375 +89294 0.37249755859375 +89295 0.30072021484375 +89296 0.1517333984375 +89297 -0.01470947265625 +89298 -0.1883544921875 +89299 -0.372711181640625 +89300 -0.51397705078125 +89301 -0.57177734375 +89302 -0.53948974609375 +89303 -0.43511962890625 +89304 -0.2962646484375 +89305 -0.161102294921875 +89306 -0.0435791015625 +89307 0.060394287109375 +89308 0.13665771484375 +89309 0.170135498046875 +89310 0.16552734375 +89311 0.15728759765625 +89312 0.150787353515625 +89313 0.12200927734375 +89314 0.080108642578125 +89315 0.05126953125 +89316 0.062896728515625 +89317 0.09271240234375 +89318 0.092987060546875 +89319 0.07855224609375 +89320 0.06427001953125 +89321 0.0347900390625 +89322 -0.01171875 +89323 -0.056060791015625 +89324 -0.055511474609375 +89325 -0.010467529296875 +89326 0.02508544921875 +89327 0.025665283203125 +89328 0.017333984375 +89329 0.00189208984375 +89330 -0.03173828125 +89331 -0.071502685546875 +89332 -0.13543701171875 +89333 -0.219970703125 +89334 -0.300506591796875 +89335 -0.376312255859375 +89336 -0.416107177734375 +89337 -0.371124267578125 +89338 -0.242279052734375 +89339 -0.069732666015625 +89340 0.125640869140625 +89341 0.31268310546875 +89342 0.45501708984375 +89343 0.554779052734375 +89344 0.61065673828125 +89345 0.610931396484375 +89346 0.531463623046875 +89347 0.3883056640625 +89348 0.23468017578125 +89349 0.095245361328125 +89350 -0.00396728515625 +89351 -0.04852294921875 +89352 -0.055145263671875 +89353 -0.0758056640625 +89354 -0.138702392578125 +89355 -0.209197998046875 +89356 -0.289031982421875 +89357 -0.37884521484375 +89358 -0.456329345703125 +89359 -0.51641845703125 +89360 -0.519287109375 +89361 -0.458251953125 +89362 -0.384796142578125 +89363 -0.323699951171875 +89364 -0.269287109375 +89365 -0.1951904296875 +89366 -0.100006103515625 +89367 -0.01055908203125 +89368 0.1033935546875 +89369 0.24908447265625 +89370 0.373199462890625 +89371 0.45806884765625 +89372 0.511474609375 +89373 0.565399169921875 +89374 0.61138916015625 +89375 0.5897216796875 +89376 0.4906005859375 +89377 0.33148193359375 +89378 0.147796630859375 +89379 -0.01873779296875 +89380 -0.140289306640625 +89381 -0.191986083984375 +89382 -0.184295654296875 +89383 -0.161834716796875 +89384 -0.166595458984375 +89385 -0.19390869140625 +89386 -0.22442626953125 +89387 -0.279754638671875 +89388 -0.3389892578125 +89389 -0.3543701171875 +89390 -0.348175048828125 +89391 -0.32598876953125 +89392 -0.2581787109375 +89393 -0.139801025390625 +89394 0.014617919921875 +89395 0.144378662109375 +89396 0.221038818359375 +89397 0.27069091796875 +89398 0.294036865234375 +89399 0.311767578125 +89400 0.339141845703125 +89401 0.360260009765625 +89402 0.360504150390625 +89403 0.308380126953125 +89404 0.18170166015625 +89405 0.0047607421875 +89406 -0.17559814453125 +89407 -0.3143310546875 +89408 -0.36785888671875 +89409 -0.36248779296875 +89410 -0.343536376953125 +89411 -0.3018798828125 +89412 -0.231414794921875 +89413 -0.117645263671875 +89414 0.007049560546875 +89415 0.087982177734375 +89416 0.13946533203125 +89417 0.17425537109375 +89418 0.188201904296875 +89419 0.171234130859375 +89420 0.118438720703125 +89421 0.05706787109375 +89422 -0.010711669921875 +89423 -0.0914306640625 +89424 -0.162322998046875 +89425 -0.194549560546875 +89426 -0.1492919921875 +89427 -0.02166748046875 +89428 0.124053955078125 +89429 0.211151123046875 +89430 0.240447998046875 +89431 0.242218017578125 +89432 0.2257080078125 +89433 0.194366455078125 +89434 0.115509033203125 +89435 0.0128173828125 +89436 -0.053802490234375 +89437 -0.110626220703125 +89438 -0.199493408203125 +89439 -0.29437255859375 +89440 -0.33221435546875 +89441 -0.27972412109375 +89442 -0.185333251953125 +89443 -0.128204345703125 +89444 -0.115692138671875 +89445 -0.116455078125 +89446 -0.105926513671875 +89447 -0.053955078125 +89448 0.048797607421875 +89449 0.157318115234375 +89450 0.212005615234375 +89451 0.218475341796875 +89452 0.23724365234375 +89453 0.30535888671875 +89454 0.38128662109375 +89455 0.404449462890625 +89456 0.3944091796875 +89457 0.3885498046875 +89458 0.362640380859375 +89459 0.27362060546875 +89460 0.11712646484375 +89461 -0.054901123046875 +89462 -0.19085693359375 +89463 -0.28570556640625 +89464 -0.339263916015625 +89465 -0.3775634765625 +89466 -0.445709228515625 +89467 -0.535064697265625 +89468 -0.629058837890625 +89469 -0.697601318359375 +89470 -0.70391845703125 +89471 -0.6424560546875 +89472 -0.491241455078125 +89473 -0.265716552734375 +89474 -0.023712158203125 +89475 0.201751708984375 +89476 0.375823974609375 +89477 0.485076904296875 +89478 0.56884765625 +89479 0.634765625 +89480 0.63763427734375 +89481 0.5660400390625 +89482 0.4720458984375 +89483 0.40692138671875 +89484 0.3778076171875 +89485 0.376953125 +89486 0.371978759765625 +89487 0.313140869140625 +89488 0.184417724609375 +89489 0.011199951171875 +89490 -0.171051025390625 +89491 -0.33740234375 +89492 -0.47198486328125 +89493 -0.560394287109375 +89494 -0.58056640625 +89495 -0.54754638671875 +89496 -0.508575439453125 +89497 -0.459503173828125 +89498 -0.394378662109375 +89499 -0.35260009765625 +89500 -0.31170654296875 +89501 -0.197418212890625 +89502 -0.007965087890625 +89503 0.207489013671875 +89504 0.409210205078125 +89505 0.57208251953125 +89506 0.66595458984375 +89507 0.65875244140625 +89508 0.56744384765625 +89509 0.431396484375 +89510 0.29443359375 +89511 0.182464599609375 +89512 0.06365966796875 +89513 -0.075958251953125 +89514 -0.189422607421875 +89515 -0.271942138671875 +89516 -0.342529296875 +89517 -0.364166259765625 +89518 -0.327239990234375 +89519 -0.2769775390625 +89520 -0.253692626953125 +89521 -0.24365234375 +89522 -0.1983642578125 +89523 -0.116241455078125 +89524 -0.036834716796875 +89525 0.034881591796875 +89526 0.09124755859375 +89527 0.10888671875 +89528 0.125518798828125 +89529 0.15771484375 +89530 0.17828369140625 +89531 0.17108154296875 +89532 0.129974365234375 +89533 0.082427978515625 +89534 0.027679443359375 +89535 -0.065643310546875 +89536 -0.15936279296875 +89537 -0.21307373046875 +89538 -0.234649658203125 +89539 -0.2001953125 +89540 -0.119171142578125 +89541 -0.024749755859375 +89542 0.085784912109375 +89543 0.178131103515625 +89544 0.215576171875 +89545 0.211456298828125 +89546 0.17523193359375 +89547 0.128753662109375 +89548 0.1019287109375 +89549 0.0743408203125 +89550 0.04327392578125 +89551 0.038177490234375 +89552 0.076263427734375 +89553 0.14105224609375 +89554 0.186431884765625 +89555 0.188812255859375 +89556 0.1390380859375 +89557 0.041778564453125 +89558 -0.079437255859375 +89559 -0.219390869140625 +89560 -0.367828369140625 +89561 -0.494873046875 +89562 -0.556243896484375 +89563 -0.508697509765625 +89564 -0.3756103515625 +89565 -0.218902587890625 +89566 -0.063751220703125 +89567 0.091552734375 +89568 0.23602294921875 +89569 0.342987060546875 +89570 0.39520263671875 +89571 0.389373779296875 +89572 0.324249267578125 +89573 0.224090576171875 +89574 0.124267578125 +89575 0.037078857421875 +89576 -0.010101318359375 +89577 -0.019439697265625 +89578 -0.022796630859375 +89579 -0.001556396484375 +89580 0.056304931640625 +89581 0.106719970703125 +89582 0.096893310546875 +89583 0.042694091796875 +89584 -0.018035888671875 +89585 -0.07586669921875 +89586 -0.11944580078125 +89587 -0.15972900390625 +89588 -0.202606201171875 +89589 -0.24859619140625 +89590 -0.30517578125 +89591 -0.36212158203125 +89592 -0.39141845703125 +89593 -0.35528564453125 +89594 -0.249969482421875 +89595 -0.092864990234375 +89596 0.08905029296875 +89597 0.2352294921875 +89598 0.318817138671875 +89599 0.358642578125 +89600 0.347747802734375 +89601 0.28564453125 +89602 0.223175048828125 +89603 0.196746826171875 +89604 0.179840087890625 +89605 0.155548095703125 +89606 0.151214599609375 +89607 0.156951904296875 +89608 0.13177490234375 +89609 0.100799560546875 +89610 0.087127685546875 +89611 0.05487060546875 +89612 -0.009002685546875 +89613 -0.10400390625 +89614 -0.229400634765625 +89615 -0.35552978515625 +89616 -0.441925048828125 +89617 -0.473846435546875 +89618 -0.464813232421875 +89619 -0.419097900390625 +89620 -0.334320068359375 +89621 -0.227935791015625 +89622 -0.12347412109375 +89623 -0.02764892578125 +89624 0.077667236328125 +89625 0.2132568359375 +89626 0.38885498046875 +89627 0.582794189453125 +89628 0.734039306640625 +89629 0.800140380859375 +89630 0.7783203125 +89631 0.6651611328125 +89632 0.45965576171875 +89633 0.199188232421875 +89634 -0.050689697265625 +89635 -0.23297119140625 +89636 -0.33013916015625 +89637 -0.368408203125 +89638 -0.378936767578125 +89639 -0.376983642578125 +89640 -0.37969970703125 +89641 -0.391510009765625 +89642 -0.385345458984375 +89643 -0.3419189453125 +89644 -0.28289794921875 +89645 -0.251617431640625 +89646 -0.266143798828125 +89647 -0.273345947265625 +89648 -0.216796875 +89649 -0.128265380859375 +89650 -0.068145751953125 +89651 -0.0430908203125 +89652 -0.024444580078125 +89653 0.020721435546875 +89654 0.124481201171875 +89655 0.25787353515625 +89656 0.379119873046875 +89657 0.47991943359375 +89658 0.5281982421875 +89659 0.511138916015625 +89660 0.456207275390625 +89661 0.407470703125 +89662 0.383758544921875 +89663 0.35687255859375 +89664 0.31182861328125 +89665 0.250885009765625 +89666 0.1654052734375 +89667 0.035247802734375 +89668 -0.142059326171875 +89669 -0.33563232421875 +89670 -0.5345458984375 +89671 -0.72186279296875 +89672 -0.836669921875 +89673 -0.8326416015625 +89674 -0.7296142578125 +89675 -0.582550048828125 +89676 -0.440093994140625 +89677 -0.324310302734375 +89678 -0.20147705078125 +89679 -0.044647216796875 +89680 0.103973388671875 +89681 0.202392578125 +89682 0.264495849609375 +89683 0.338897705078125 +89684 0.443817138671875 +89685 0.545074462890625 +89686 0.6173095703125 +89687 0.6524658203125 +89688 0.66339111328125 +89689 0.6561279296875 +89690 0.606781005859375 +89691 0.501190185546875 +89692 0.352783203125 +89693 0.176544189453125 +89694 -0.034820556640625 +89695 -0.258209228515625 +89696 -0.44244384765625 +89697 -0.5753173828125 +89698 -0.65203857421875 +89699 -0.641632080078125 +89700 -0.562164306640625 +89701 -0.458038330078125 +89702 -0.350555419921875 +89703 -0.260528564453125 +89704 -0.192108154296875 +89705 -0.141937255859375 +89706 -0.1021728515625 +89707 -0.062896728515625 +89708 -0.011932373046875 +89709 0.062835693359375 +89710 0.148712158203125 +89711 0.241729736328125 +89712 0.34912109375 +89713 0.457305908203125 +89714 0.54388427734375 +89715 0.5728759765625 +89716 0.506591796875 +89717 0.351226806640625 +89718 0.146514892578125 +89719 -0.05523681640625 +89720 -0.21624755859375 +89721 -0.334930419921875 +89722 -0.402984619140625 +89723 -0.4412841796875 +89724 -0.49578857421875 +89725 -0.5601806640625 +89726 -0.600738525390625 +89727 -0.584228515625 +89728 -0.47930908203125 +89729 -0.27935791015625 +89730 -0.0089111328125 +89731 0.268798828125 +89732 0.482818603515625 +89733 0.60369873046875 +89734 0.650421142578125 +89735 0.66400146484375 +89736 0.6414794921875 +89737 0.572540283203125 +89738 0.498138427734375 +89739 0.439453125 +89740 0.375518798828125 +89741 0.274505615234375 +89742 0.1087646484375 +89743 -0.099395751953125 +89744 -0.3182373046875 +89745 -0.5489501953125 +89746 -0.7738037109375 +89747 -0.86383056640625 +89748 -0.870391845703125 +89749 -0.86895751953125 +89750 -0.861053466796875 +89751 -0.765869140625 +89752 -0.5301513671875 +89753 -0.214691162109375 +89754 0.137359619140625 +89755 0.474822998046875 +89756 0.76239013671875 +89757 0.867462158203125 +89758 0.870361328125 +89759 0.86480712890625 +89760 0.831817626953125 +89761 0.677581787109375 +89762 0.495880126953125 +89763 0.30767822265625 +89764 0.116180419921875 +89765 -0.110748291015625 +89766 -0.381805419921875 +89767 -0.6572265625 +89768 -0.857421875 +89769 -0.870391845703125 +89770 -0.870391845703125 +89771 -0.86444091796875 +89772 -0.85723876953125 +89773 -0.790008544921875 +89774 -0.62847900390625 +89775 -0.3956298828125 +89776 -0.126708984375 +89777 0.150115966796875 +89778 0.424041748046875 +89779 0.670623779296875 +89780 0.854522705078125 +89781 0.866485595703125 +89782 0.86920166015625 +89783 0.8653564453125 +89784 0.857147216796875 +89785 0.766845703125 +89786 0.628509521484375 +89787 0.462127685546875 +89788 0.297210693359375 +89789 0.14862060546875 +89790 -0.00537109375 +89791 -0.15753173828125 +89792 -0.31304931640625 +89793 -0.48876953125 +89794 -0.6416015625 +89795 -0.751373291015625 +89796 -0.84619140625 +89797 -0.861297607421875 +89798 -0.863250732421875 +89799 -0.856597900390625 +89800 -0.7498779296875 +89801 -0.624542236328125 +89802 -0.47808837890625 +89803 -0.253387451171875 +89804 0.003692626953125 +89805 0.2257080078125 +89806 0.427154541015625 +89807 0.643218994140625 +89808 0.855926513671875 +89809 0.870361328125 +89810 0.870361328125 +89811 0.862762451171875 +89812 0.79669189453125 +89813 0.595794677734375 +89814 0.362152099609375 +89815 0.1270751953125 +89816 -0.086944580078125 +89817 -0.2784423828125 +89818 -0.484832763671875 +89819 -0.729583740234375 +89820 -0.86688232421875 +89821 -0.870391845703125 +89822 -0.86859130859375 +89823 -0.86279296875 +89824 -0.817962646484375 +89825 -0.6116943359375 +89826 -0.3128662109375 +89827 0.039398193359375 +89828 0.422821044921875 +89829 0.805145263671875 +89830 0.870361328125 +89831 0.870361328125 +89832 0.860015869140625 +89833 0.727935791015625 +89834 0.48114013671875 +89835 0.2059326171875 +89836 -0.06103515625 +89837 -0.29913330078125 +89838 -0.516204833984375 +89839 -0.7252197265625 +89840 -0.85980224609375 +89841 -0.870391845703125 +89842 -0.870391845703125 +89843 -0.858062744140625 +89844 -0.673004150390625 +89845 -0.42694091796875 +89846 -0.2100830078125 +89847 -0.0362548828125 +89848 0.10943603515625 +89849 0.23516845703125 +89850 0.373687744140625 +89851 0.517791748046875 +89852 0.602783203125 +89853 0.635711669921875 +89854 0.655181884765625 +89855 0.65948486328125 +89856 0.651275634765625 +89857 0.61846923828125 +89858 0.53753662109375 +89859 0.404144287109375 +89860 0.22186279296875 +89861 0.003997802734375 +89862 -0.22100830078125 +89863 -0.42449951171875 +89864 -0.579833984375 +89865 -0.641876220703125 +89866 -0.6177978515625 +89867 -0.575531005859375 +89868 -0.526336669921875 +89869 -0.42645263671875 +89870 -0.2581787109375 +89871 -0.068695068359375 +89872 0.09222412109375 +89873 0.232147216796875 +89874 0.3509521484375 +89875 0.410064697265625 +89876 0.372955322265625 +89877 0.2554931640625 +89878 0.10711669921875 +89879 -0.052886962890625 +89880 -0.186279296875 +89881 -0.23291015625 +89882 -0.209442138671875 +89883 -0.174163818359375 +89884 -0.126739501953125 +89885 -0.048126220703125 +89886 0.0426025390625 +89887 0.10748291015625 +89888 0.1409912109375 +89889 0.19708251953125 +89890 0.273651123046875 +89891 0.31768798828125 +89892 0.341094970703125 +89893 0.368011474609375 +89894 0.37249755859375 +89895 0.30072021484375 +89896 0.1517333984375 +89897 -0.01470947265625 +89898 -0.1883544921875 +89899 -0.372711181640625 +89900 -0.51397705078125 +89901 -0.57177734375 +89902 -0.53948974609375 +89903 -0.43511962890625 +89904 -0.2962646484375 +89905 -0.161102294921875 +89906 -0.0435791015625 +89907 0.060394287109375 +89908 0.13665771484375 +89909 0.170135498046875 +89910 0.16552734375 +89911 0.15728759765625 +89912 0.150787353515625 +89913 0.12200927734375 +89914 0.080108642578125 +89915 0.05126953125 +89916 0.062896728515625 +89917 0.09271240234375 +89918 0.092987060546875 +89919 0.07855224609375 +89920 0.06427001953125 +89921 0.0347900390625 +89922 -0.01171875 +89923 -0.056060791015625 +89924 -0.055511474609375 +89925 -0.010467529296875 +89926 0.02508544921875 +89927 0.025665283203125 +89928 0.017333984375 +89929 0.00189208984375 +89930 -0.03173828125 +89931 -0.071502685546875 +89932 -0.13543701171875 +89933 -0.219970703125 +89934 -0.300506591796875 +89935 -0.376312255859375 +89936 -0.416107177734375 +89937 -0.371124267578125 +89938 -0.242279052734375 +89939 -0.069732666015625 +89940 0.125640869140625 +89941 0.31268310546875 +89942 0.45501708984375 +89943 0.554779052734375 +89944 0.61065673828125 +89945 0.610931396484375 +89946 0.531463623046875 +89947 0.3883056640625 +89948 0.23468017578125 +89949 0.095245361328125 +89950 -0.00396728515625 +89951 -0.04852294921875 +89952 -0.055145263671875 +89953 -0.0758056640625 +89954 -0.138702392578125 +89955 -0.209197998046875 +89956 -0.289031982421875 +89957 -0.37884521484375 +89958 -0.456329345703125 +89959 -0.51641845703125 +89960 -0.519287109375 +89961 -0.458251953125 +89962 -0.384796142578125 +89963 -0.323699951171875 +89964 -0.269287109375 +89965 -0.1951904296875 +89966 -0.100006103515625 +89967 -0.01055908203125 +89968 0.1033935546875 +89969 0.24908447265625 +89970 0.373199462890625 +89971 0.45806884765625 +89972 0.511474609375 +89973 0.565399169921875 +89974 0.61138916015625 +89975 0.5897216796875 +89976 0.4906005859375 +89977 0.33148193359375 +89978 0.147796630859375 +89979 -0.01873779296875 +89980 -0.140289306640625 +89981 -0.191986083984375 +89982 -0.184295654296875 +89983 -0.161834716796875 +89984 -0.166595458984375 +89985 -0.19390869140625 +89986 -0.22442626953125 +89987 -0.279754638671875 +89988 -0.3389892578125 +89989 -0.3543701171875 +89990 -0.348175048828125 +89991 -0.32598876953125 +89992 -0.2581787109375 +89993 -0.139801025390625 +89994 0.014617919921875 +89995 0.144378662109375 +89996 0.221038818359375 +89997 0.27069091796875 +89998 0.294036865234375 +89999 0.311767578125 +90000 0.339141845703125 +90001 0.360260009765625 +90002 0.360504150390625 +90003 0.308380126953125 +90004 0.18170166015625 +90005 0.0047607421875 +90006 -0.17559814453125 +90007 -0.3143310546875 +90008 -0.36785888671875 +90009 -0.36248779296875 +90010 -0.343536376953125 +90011 -0.3018798828125 +90012 -0.231414794921875 +90013 -0.117645263671875 +90014 0.007049560546875 +90015 0.087982177734375 +90016 0.13946533203125 +90017 0.17425537109375 +90018 0.188201904296875 +90019 0.171234130859375 +90020 0.118438720703125 +90021 0.05706787109375 +90022 -0.010711669921875 +90023 -0.0914306640625 +90024 -0.162322998046875 +90025 -0.194549560546875 +90026 -0.1492919921875 +90027 -0.02166748046875 +90028 0.124053955078125 +90029 0.211151123046875 +90030 0.240447998046875 +90031 0.242218017578125 +90032 0.2257080078125 +90033 0.194366455078125 +90034 0.115509033203125 +90035 0.0128173828125 +90036 -0.053802490234375 +90037 -0.110626220703125 +90038 -0.199493408203125 +90039 -0.29437255859375 +90040 -0.33221435546875 +90041 -0.27972412109375 +90042 -0.185333251953125 +90043 -0.128204345703125 +90044 -0.115692138671875 +90045 -0.116455078125 +90046 -0.105926513671875 +90047 -0.053955078125 +90048 0.048797607421875 +90049 0.157318115234375 +90050 0.212005615234375 +90051 0.218475341796875 +90052 0.23724365234375 +90053 0.30535888671875 +90054 0.38128662109375 +90055 0.404449462890625 +90056 0.3944091796875 +90057 0.3885498046875 +90058 0.362640380859375 +90059 0.27362060546875 +90060 0.11712646484375 +90061 -0.054901123046875 +90062 -0.19085693359375 +90063 -0.28570556640625 +90064 -0.339263916015625 +90065 -0.3775634765625 +90066 -0.445709228515625 +90067 -0.535064697265625 +90068 -0.629058837890625 +90069 -0.697601318359375 +90070 -0.70391845703125 +90071 -0.6424560546875 +90072 -0.491241455078125 +90073 -0.265716552734375 +90074 -0.023712158203125 +90075 0.201751708984375 +90076 0.375823974609375 +90077 0.485076904296875 +90078 0.56884765625 +90079 0.634765625 +90080 0.63763427734375 +90081 0.5660400390625 +90082 0.4720458984375 +90083 0.40692138671875 +90084 0.3778076171875 +90085 0.376953125 +90086 0.371978759765625 +90087 0.313140869140625 +90088 0.184417724609375 +90089 0.011199951171875 +90090 -0.171051025390625 +90091 -0.33740234375 +90092 -0.47198486328125 +90093 -0.560394287109375 +90094 -0.58056640625 +90095 -0.54754638671875 +90096 -0.508575439453125 +90097 -0.459503173828125 +90098 -0.394378662109375 +90099 -0.35260009765625 +90100 -0.31170654296875 +90101 -0.197418212890625 +90102 -0.007965087890625 +90103 0.207489013671875 +90104 0.409210205078125 +90105 0.57208251953125 +90106 0.66595458984375 +90107 0.65875244140625 +90108 0.56744384765625 +90109 0.431396484375 +90110 0.29443359375 +90111 0.182464599609375 +90112 0.06365966796875 +90113 -0.075958251953125 +90114 -0.189422607421875 +90115 -0.271942138671875 +90116 -0.342529296875 +90117 -0.364166259765625 +90118 -0.327239990234375 +90119 -0.2769775390625 +90120 -0.253692626953125 +90121 -0.24365234375 +90122 -0.1983642578125 +90123 -0.116241455078125 +90124 -0.036834716796875 +90125 0.034881591796875 +90126 0.09124755859375 +90127 0.10888671875 +90128 0.125518798828125 +90129 0.15771484375 +90130 0.17828369140625 +90131 0.17108154296875 +90132 0.129974365234375 +90133 0.082427978515625 +90134 0.027679443359375 +90135 -0.065643310546875 +90136 -0.15936279296875 +90137 -0.21307373046875 +90138 -0.234649658203125 +90139 -0.2001953125 +90140 -0.119171142578125 +90141 -0.024749755859375 +90142 0.085784912109375 +90143 0.178131103515625 +90144 0.215576171875 +90145 0.211456298828125 +90146 0.17523193359375 +90147 0.128753662109375 +90148 0.1019287109375 +90149 0.0743408203125 +90150 0.04327392578125 +90151 0.038177490234375 +90152 0.076263427734375 +90153 0.14105224609375 +90154 0.186431884765625 +90155 0.188812255859375 +90156 0.1390380859375 +90157 0.041778564453125 +90158 -0.079437255859375 +90159 -0.219390869140625 +90160 -0.367828369140625 +90161 -0.494873046875 +90162 -0.556243896484375 +90163 -0.508697509765625 +90164 -0.3756103515625 +90165 -0.218902587890625 +90166 -0.063751220703125 +90167 0.091552734375 +90168 0.23602294921875 +90169 0.342987060546875 +90170 0.39520263671875 +90171 0.389373779296875 +90172 0.324249267578125 +90173 0.224090576171875 +90174 0.124267578125 +90175 0.037078857421875 +90176 -0.010101318359375 +90177 -0.019439697265625 +90178 -0.022796630859375 +90179 -0.001556396484375 +90180 0.056304931640625 +90181 0.106719970703125 +90182 0.096893310546875 +90183 0.042694091796875 +90184 -0.018035888671875 +90185 -0.07586669921875 +90186 -0.11944580078125 +90187 -0.15972900390625 +90188 -0.202606201171875 +90189 -0.24859619140625 +90190 -0.30517578125 +90191 -0.36212158203125 +90192 -0.39141845703125 +90193 -0.35528564453125 +90194 -0.249969482421875 +90195 -0.092864990234375 +90196 0.08905029296875 +90197 0.2352294921875 +90198 0.318817138671875 +90199 0.358642578125 +90200 0.347747802734375 +90201 0.28564453125 +90202 0.223175048828125 +90203 0.196746826171875 +90204 0.179840087890625 +90205 0.155548095703125 +90206 0.151214599609375 +90207 0.156951904296875 +90208 0.13177490234375 +90209 0.100799560546875 +90210 0.087127685546875 +90211 0.05487060546875 +90212 -0.009002685546875 +90213 -0.10400390625 +90214 -0.229400634765625 +90215 -0.35552978515625 +90216 -0.441925048828125 +90217 -0.473846435546875 +90218 -0.464813232421875 +90219 -0.419097900390625 +90220 -0.334320068359375 +90221 -0.227935791015625 +90222 -0.12347412109375 +90223 -0.02764892578125 +90224 0.077667236328125 +90225 0.2132568359375 +90226 0.38885498046875 +90227 0.582794189453125 +90228 0.734039306640625 +90229 0.800140380859375 +90230 0.7783203125 +90231 0.6651611328125 +90232 0.45965576171875 +90233 0.199188232421875 +90234 -0.050689697265625 +90235 -0.23297119140625 +90236 -0.33013916015625 +90237 -0.368408203125 +90238 -0.378936767578125 +90239 -0.376983642578125 +90240 -0.37969970703125 +90241 -0.391510009765625 +90242 -0.385345458984375 +90243 -0.3419189453125 +90244 -0.28289794921875 +90245 -0.251617431640625 +90246 -0.266143798828125 +90247 -0.273345947265625 +90248 -0.216796875 +90249 -0.128265380859375 +90250 -0.068145751953125 +90251 -0.0430908203125 +90252 -0.024444580078125 +90253 0.020721435546875 +90254 0.124481201171875 +90255 0.25787353515625 +90256 0.379119873046875 +90257 0.47991943359375 +90258 0.5281982421875 +90259 0.511138916015625 +90260 0.456207275390625 +90261 0.407470703125 +90262 0.383758544921875 +90263 0.35687255859375 +90264 0.31182861328125 +90265 0.250885009765625 +90266 0.1654052734375 +90267 0.035247802734375 +90268 -0.142059326171875 +90269 -0.33563232421875 +90270 -0.5345458984375 +90271 -0.72186279296875 +90272 -0.836669921875 +90273 -0.8326416015625 +90274 -0.7296142578125 +90275 -0.582550048828125 +90276 -0.440093994140625 +90277 -0.324310302734375 +90278 -0.20147705078125 +90279 -0.044647216796875 +90280 0.103973388671875 +90281 0.202392578125 +90282 0.264495849609375 +90283 0.338897705078125 +90284 0.443817138671875 +90285 0.545074462890625 +90286 0.6173095703125 +90287 0.6524658203125 +90288 0.66339111328125 +90289 0.6561279296875 +90290 0.606781005859375 +90291 0.501190185546875 +90292 0.352783203125 +90293 0.176544189453125 +90294 -0.034820556640625 +90295 -0.258209228515625 +90296 -0.44244384765625 +90297 -0.5753173828125 +90298 -0.65203857421875 +90299 -0.641632080078125 +90300 -0.562164306640625 +90301 -0.458038330078125 +90302 -0.350555419921875 +90303 -0.260528564453125 +90304 -0.192108154296875 +90305 -0.141937255859375 +90306 -0.1021728515625 +90307 -0.062896728515625 +90308 -0.011932373046875 +90309 0.062835693359375 +90310 0.148712158203125 +90311 0.241729736328125 +90312 0.34912109375 +90313 0.457305908203125 +90314 0.54388427734375 +90315 0.5728759765625 +90316 0.506591796875 +90317 0.351226806640625 +90318 0.146514892578125 +90319 -0.05523681640625 +90320 -0.21624755859375 +90321 -0.334930419921875 +90322 -0.402984619140625 +90323 -0.4412841796875 +90324 -0.49578857421875 +90325 -0.5601806640625 +90326 -0.600738525390625 +90327 -0.584228515625 +90328 -0.47930908203125 +90329 -0.27935791015625 +90330 -0.0089111328125 +90331 0.268798828125 +90332 0.482818603515625 +90333 0.60369873046875 +90334 0.650421142578125 +90335 0.66400146484375 +90336 0.6414794921875 +90337 0.572540283203125 +90338 0.498138427734375 +90339 0.439453125 +90340 0.375518798828125 +90341 0.274505615234375 +90342 0.1087646484375 +90343 -0.099395751953125 +90344 -0.3182373046875 +90345 -0.5489501953125 +90346 -0.7738037109375 +90347 -0.86383056640625 +90348 -0.870391845703125 +90349 -0.86895751953125 +90350 -0.861053466796875 +90351 -0.765869140625 +90352 -0.5301513671875 +90353 -0.214691162109375 +90354 0.137359619140625 +90355 0.474822998046875 +90356 0.76239013671875 +90357 0.867462158203125 +90358 0.870361328125 +90359 0.86480712890625 +90360 0.831817626953125 +90361 0.677581787109375 +90362 0.495880126953125 +90363 0.30767822265625 +90364 0.116180419921875 +90365 -0.110748291015625 +90366 -0.381805419921875 +90367 -0.6572265625 +90368 -0.857421875 +90369 -0.870391845703125 +90370 -0.870391845703125 +90371 -0.86444091796875 +90372 -0.85723876953125 +90373 -0.790008544921875 +90374 -0.62847900390625 +90375 -0.3956298828125 +90376 -0.126708984375 +90377 0.150115966796875 +90378 0.424041748046875 +90379 0.670623779296875 +90380 0.854522705078125 +90381 0.866485595703125 +90382 0.86920166015625 +90383 0.8653564453125 +90384 0.857147216796875 +90385 0.766845703125 +90386 0.628509521484375 +90387 0.462127685546875 +90388 0.297210693359375 +90389 0.14862060546875 +90390 -0.00537109375 +90391 -0.15753173828125 +90392 -0.31304931640625 +90393 -0.48876953125 +90394 -0.6416015625 +90395 -0.751373291015625 +90396 -0.84619140625 +90397 -0.861297607421875 +90398 -0.863250732421875 +90399 -0.856597900390625 +90400 -0.7498779296875 +90401 -0.624542236328125 +90402 -0.47808837890625 +90403 -0.253387451171875 +90404 0.003692626953125 +90405 0.2257080078125 +90406 0.427154541015625 +90407 0.643218994140625 +90408 0.855926513671875 +90409 0.870361328125 +90410 0.870361328125 +90411 0.862762451171875 +90412 0.79669189453125 +90413 0.595794677734375 +90414 0.362152099609375 +90415 0.1270751953125 +90416 -0.086944580078125 +90417 -0.2784423828125 +90418 -0.484832763671875 +90419 -0.729583740234375 +90420 -0.86688232421875 +90421 -0.870391845703125 +90422 -0.86859130859375 +90423 -0.86279296875 +90424 -0.817962646484375 +90425 -0.6116943359375 +90426 -0.3128662109375 +90427 0.039398193359375 +90428 0.422821044921875 +90429 0.805145263671875 +90430 0.870361328125 +90431 0.870361328125 +90432 0.860015869140625 +90433 0.727935791015625 +90434 0.48114013671875 +90435 0.2059326171875 +90436 -0.06103515625 +90437 -0.29913330078125 +90438 -0.516204833984375 +90439 -0.7252197265625 +90440 -0.85980224609375 +90441 -0.870391845703125 +90442 -0.870391845703125 +90443 -0.858062744140625 +90444 -0.673004150390625 +90445 -0.42694091796875 +90446 -0.2100830078125 +90447 -0.0362548828125 +90448 0.10943603515625 +90449 0.23516845703125 +90450 0.373687744140625 +90451 0.517791748046875 +90452 0.602783203125 +90453 0.635711669921875 +90454 0.655181884765625 +90455 0.65948486328125 +90456 0.651275634765625 +90457 0.61846923828125 +90458 0.53753662109375 +90459 0.404144287109375 +90460 0.22186279296875 +90461 0.003997802734375 +90462 -0.22100830078125 +90463 -0.42449951171875 +90464 -0.579833984375 +90465 -0.641876220703125 +90466 -0.6177978515625 +90467 -0.575531005859375 +90468 -0.526336669921875 +90469 -0.42645263671875 +90470 -0.2581787109375 +90471 -0.068695068359375 +90472 0.09222412109375 +90473 0.232147216796875 +90474 0.3509521484375 +90475 0.410064697265625 +90476 0.372955322265625 +90477 0.2554931640625 +90478 0.10711669921875 +90479 -0.052886962890625 +90480 -0.186279296875 +90481 -0.23291015625 +90482 -0.209442138671875 +90483 -0.174163818359375 +90484 -0.126739501953125 +90485 -0.048126220703125 +90486 0.0426025390625 +90487 0.10748291015625 +90488 0.1409912109375 +90489 0.19708251953125 +90490 0.273651123046875 +90491 0.31768798828125 +90492 0.341094970703125 +90493 0.368011474609375 +90494 0.37249755859375 +90495 0.30072021484375 +90496 0.1517333984375 +90497 -0.01470947265625 +90498 -0.1883544921875 +90499 -0.372711181640625 +90500 -0.51397705078125 +90501 -0.57177734375 +90502 -0.53948974609375 +90503 -0.43511962890625 +90504 -0.2962646484375 +90505 -0.161102294921875 +90506 -0.0435791015625 +90507 0.060394287109375 +90508 0.13665771484375 +90509 0.170135498046875 +90510 0.16552734375 +90511 0.15728759765625 +90512 0.150787353515625 +90513 0.12200927734375 +90514 0.080108642578125 +90515 0.05126953125 +90516 0.062896728515625 +90517 0.09271240234375 +90518 0.092987060546875 +90519 0.07855224609375 +90520 0.06427001953125 +90521 0.0347900390625 +90522 -0.01171875 +90523 -0.056060791015625 +90524 -0.055511474609375 +90525 -0.010467529296875 +90526 0.02508544921875 +90527 0.025665283203125 +90528 0.017333984375 +90529 0.00189208984375 +90530 -0.03173828125 +90531 -0.071502685546875 +90532 -0.13543701171875 +90533 -0.219970703125 +90534 -0.300506591796875 +90535 -0.376312255859375 +90536 -0.416107177734375 +90537 -0.371124267578125 +90538 -0.242279052734375 +90539 -0.069732666015625 +90540 0.125640869140625 +90541 0.31268310546875 +90542 0.45501708984375 +90543 0.554779052734375 +90544 0.61065673828125 +90545 0.610931396484375 +90546 0.531463623046875 +90547 0.3883056640625 +90548 0.23468017578125 +90549 0.095245361328125 +90550 -0.00396728515625 +90551 -0.04852294921875 +90552 -0.055145263671875 +90553 -0.0758056640625 +90554 -0.138702392578125 +90555 -0.209197998046875 +90556 -0.289031982421875 +90557 -0.37884521484375 +90558 -0.456329345703125 +90559 -0.51641845703125 +90560 -0.519287109375 +90561 -0.458251953125 +90562 -0.384796142578125 +90563 -0.323699951171875 +90564 -0.269287109375 +90565 -0.1951904296875 +90566 -0.100006103515625 +90567 -0.01055908203125 +90568 0.1033935546875 +90569 0.24908447265625 +90570 0.373199462890625 +90571 0.45806884765625 +90572 0.511474609375 +90573 0.565399169921875 +90574 0.61138916015625 +90575 0.5897216796875 +90576 0.4906005859375 +90577 0.33148193359375 +90578 0.147796630859375 +90579 -0.01873779296875 +90580 -0.140289306640625 +90581 -0.191986083984375 +90582 -0.184295654296875 +90583 -0.161834716796875 +90584 -0.166595458984375 +90585 -0.19390869140625 +90586 -0.22442626953125 +90587 -0.279754638671875 +90588 -0.3389892578125 +90589 -0.3543701171875 +90590 -0.348175048828125 +90591 -0.32598876953125 +90592 -0.2581787109375 +90593 -0.139801025390625 +90594 0.014617919921875 +90595 0.144378662109375 +90596 0.221038818359375 +90597 0.27069091796875 +90598 0.294036865234375 +90599 0.311767578125 +90600 0.339141845703125 +90601 0.360260009765625 +90602 0.360504150390625 +90603 0.308380126953125 +90604 0.18170166015625 +90605 0.0047607421875 +90606 -0.17559814453125 +90607 -0.3143310546875 +90608 -0.36785888671875 +90609 -0.36248779296875 +90610 -0.343536376953125 +90611 -0.3018798828125 +90612 -0.231414794921875 +90613 -0.117645263671875 +90614 0.007049560546875 +90615 0.087982177734375 +90616 0.13946533203125 +90617 0.17425537109375 +90618 0.188201904296875 +90619 0.171234130859375 +90620 0.118438720703125 +90621 0.05706787109375 +90622 -0.010711669921875 +90623 -0.0914306640625 +90624 -0.162322998046875 +90625 -0.194549560546875 +90626 -0.1492919921875 +90627 -0.02166748046875 +90628 0.124053955078125 +90629 0.211151123046875 +90630 0.240447998046875 +90631 0.242218017578125 +90632 0.2257080078125 +90633 0.194366455078125 +90634 0.115509033203125 +90635 0.0128173828125 +90636 -0.053802490234375 +90637 -0.110626220703125 +90638 -0.199493408203125 +90639 -0.29437255859375 +90640 -0.33221435546875 +90641 -0.27972412109375 +90642 -0.185333251953125 +90643 -0.128204345703125 +90644 -0.115692138671875 +90645 -0.116455078125 +90646 -0.105926513671875 +90647 -0.053955078125 +90648 0.048797607421875 +90649 0.157318115234375 +90650 0.212005615234375 +90651 0.218475341796875 +90652 0.23724365234375 +90653 0.30535888671875 +90654 0.38128662109375 +90655 0.404449462890625 +90656 0.3944091796875 +90657 0.3885498046875 +90658 0.362640380859375 +90659 0.27362060546875 +90660 0.11712646484375 +90661 -0.054901123046875 +90662 -0.19085693359375 +90663 -0.28570556640625 +90664 -0.339263916015625 +90665 -0.3775634765625 +90666 -0.445709228515625 +90667 -0.535064697265625 +90668 -0.629058837890625 +90669 -0.697601318359375 +90670 -0.70391845703125 +90671 -0.6424560546875 +90672 -0.491241455078125 +90673 -0.265716552734375 +90674 -0.023712158203125 +90675 0.201751708984375 +90676 0.375823974609375 +90677 0.485076904296875 +90678 0.56884765625 +90679 0.634765625 +90680 0.63763427734375 +90681 0.5660400390625 +90682 0.4720458984375 +90683 0.40692138671875 +90684 0.3778076171875 +90685 0.376953125 +90686 0.371978759765625 +90687 0.313140869140625 +90688 0.184417724609375 +90689 0.011199951171875 +90690 -0.171051025390625 +90691 -0.33740234375 +90692 -0.47198486328125 +90693 -0.560394287109375 +90694 -0.58056640625 +90695 -0.54754638671875 +90696 -0.508575439453125 +90697 -0.459503173828125 +90698 -0.394378662109375 +90699 -0.35260009765625 +90700 -0.31170654296875 +90701 -0.197418212890625 +90702 -0.007965087890625 +90703 0.207489013671875 +90704 0.409210205078125 +90705 0.57208251953125 +90706 0.66595458984375 +90707 0.65875244140625 +90708 0.56744384765625 +90709 0.431396484375 +90710 0.29443359375 +90711 0.182464599609375 +90712 0.06365966796875 +90713 -0.075958251953125 +90714 -0.189422607421875 +90715 -0.271942138671875 +90716 -0.342529296875 +90717 -0.364166259765625 +90718 -0.327239990234375 +90719 -0.2769775390625 +90720 -0.253692626953125 +90721 -0.24365234375 +90722 -0.1983642578125 +90723 -0.116241455078125 +90724 -0.036834716796875 +90725 0.034881591796875 +90726 0.09124755859375 +90727 0.10888671875 +90728 0.125518798828125 +90729 0.15771484375 +90730 0.17828369140625 +90731 0.17108154296875 +90732 0.129974365234375 +90733 0.082427978515625 +90734 0.027679443359375 +90735 -0.065643310546875 +90736 -0.15936279296875 +90737 -0.21307373046875 +90738 -0.234649658203125 +90739 -0.2001953125 +90740 -0.119171142578125 +90741 -0.024749755859375 +90742 0.085784912109375 +90743 0.178131103515625 +90744 0.215576171875 +90745 0.211456298828125 +90746 0.17523193359375 +90747 0.128753662109375 +90748 0.1019287109375 +90749 0.0743408203125 +90750 0.04327392578125 +90751 0.038177490234375 +90752 0.076263427734375 +90753 0.14105224609375 +90754 0.186431884765625 +90755 0.188812255859375 +90756 0.1390380859375 +90757 0.041778564453125 +90758 -0.079437255859375 +90759 -0.219390869140625 +90760 -0.367828369140625 +90761 -0.494873046875 +90762 -0.556243896484375 +90763 -0.508697509765625 +90764 -0.3756103515625 +90765 -0.218902587890625 +90766 -0.063751220703125 +90767 0.091552734375 +90768 0.23602294921875 +90769 0.342987060546875 +90770 0.39520263671875 +90771 0.389373779296875 +90772 0.324249267578125 +90773 0.224090576171875 +90774 0.124267578125 +90775 0.037078857421875 +90776 -0.010101318359375 +90777 -0.019439697265625 +90778 -0.022796630859375 +90779 -0.001556396484375 +90780 0.056304931640625 +90781 0.106719970703125 +90782 0.096893310546875 +90783 0.042694091796875 +90784 -0.018035888671875 +90785 -0.07586669921875 +90786 -0.11944580078125 +90787 -0.15972900390625 +90788 -0.202606201171875 +90789 -0.24859619140625 +90790 -0.30517578125 +90791 -0.36212158203125 +90792 -0.39141845703125 +90793 -0.35528564453125 +90794 -0.249969482421875 +90795 -0.092864990234375 +90796 0.08905029296875 +90797 0.2352294921875 +90798 0.318817138671875 +90799 0.358642578125 +90800 0.347747802734375 +90801 0.28564453125 +90802 0.223175048828125 +90803 0.196746826171875 +90804 0.179840087890625 +90805 0.155548095703125 +90806 0.151214599609375 +90807 0.156951904296875 +90808 0.13177490234375 +90809 0.100799560546875 +90810 0.087127685546875 +90811 0.05487060546875 +90812 -0.009002685546875 +90813 -0.10400390625 +90814 -0.229400634765625 +90815 -0.35552978515625 +90816 -0.441925048828125 +90817 -0.473846435546875 +90818 -0.464813232421875 +90819 -0.419097900390625 +90820 -0.334320068359375 +90821 -0.227935791015625 +90822 -0.12347412109375 +90823 -0.02764892578125 +90824 0.077667236328125 +90825 0.2132568359375 +90826 0.38885498046875 +90827 0.582794189453125 +90828 0.734039306640625 +90829 0.800140380859375 +90830 0.7783203125 +90831 0.6651611328125 +90832 0.45965576171875 +90833 0.199188232421875 +90834 -0.050689697265625 +90835 -0.23297119140625 +90836 -0.33013916015625 +90837 -0.368408203125 +90838 -0.378936767578125 +90839 -0.376983642578125 +90840 -0.37969970703125 +90841 -0.391510009765625 +90842 -0.385345458984375 +90843 -0.3419189453125 +90844 -0.28289794921875 +90845 -0.251617431640625 +90846 -0.266143798828125 +90847 -0.273345947265625 +90848 -0.216796875 +90849 -0.128265380859375 +90850 -0.068145751953125 +90851 -0.0430908203125 +90852 -0.024444580078125 +90853 0.020721435546875 +90854 0.124481201171875 +90855 0.25787353515625 +90856 0.379119873046875 +90857 0.47991943359375 +90858 0.5281982421875 +90859 0.511138916015625 +90860 0.456207275390625 +90861 0.407470703125 +90862 0.383758544921875 +90863 0.35687255859375 +90864 0.31182861328125 +90865 0.250885009765625 +90866 0.1654052734375 +90867 0.035247802734375 +90868 -0.142059326171875 +90869 -0.33563232421875 +90870 -0.5345458984375 +90871 -0.72186279296875 +90872 -0.836669921875 +90873 -0.8326416015625 +90874 -0.7296142578125 +90875 -0.582550048828125 +90876 -0.440093994140625 +90877 -0.324310302734375 +90878 -0.20147705078125 +90879 -0.044647216796875 +90880 0.103973388671875 +90881 0.202392578125 +90882 0.264495849609375 +90883 0.338897705078125 +90884 0.443817138671875 +90885 0.545074462890625 +90886 0.6173095703125 +90887 0.6524658203125 +90888 0.66339111328125 +90889 0.6561279296875 +90890 0.606781005859375 +90891 0.501190185546875 +90892 0.352783203125 +90893 0.176544189453125 +90894 -0.034820556640625 +90895 -0.258209228515625 +90896 -0.44244384765625 +90897 -0.5753173828125 +90898 -0.65203857421875 +90899 -0.641632080078125 +90900 -0.562164306640625 +90901 -0.458038330078125 +90902 -0.350555419921875 +90903 -0.260528564453125 +90904 -0.192108154296875 +90905 -0.141937255859375 +90906 -0.1021728515625 +90907 -0.062896728515625 +90908 -0.011932373046875 +90909 0.062835693359375 +90910 0.148712158203125 +90911 0.241729736328125 +90912 0.34912109375 +90913 0.457305908203125 +90914 0.54388427734375 +90915 0.5728759765625 +90916 0.506591796875 +90917 0.351226806640625 +90918 0.146514892578125 +90919 -0.05523681640625 +90920 -0.21624755859375 +90921 -0.334930419921875 +90922 -0.402984619140625 +90923 -0.4412841796875 +90924 -0.49578857421875 +90925 -0.5601806640625 +90926 -0.600738525390625 +90927 -0.584228515625 +90928 -0.47930908203125 +90929 -0.27935791015625 +90930 -0.0089111328125 +90931 0.268798828125 +90932 0.482818603515625 +90933 0.60369873046875 +90934 0.650421142578125 +90935 0.66400146484375 +90936 0.6414794921875 +90937 0.572540283203125 +90938 0.498138427734375 +90939 0.439453125 +90940 0.375518798828125 +90941 0.274505615234375 +90942 0.1087646484375 +90943 -0.099395751953125 +90944 -0.3182373046875 +90945 -0.5489501953125 +90946 -0.7738037109375 +90947 -0.86383056640625 +90948 -0.870391845703125 +90949 -0.86895751953125 +90950 -0.861053466796875 +90951 -0.765869140625 +90952 -0.5301513671875 +90953 -0.214691162109375 +90954 0.137359619140625 +90955 0.474822998046875 +90956 0.76239013671875 +90957 0.867462158203125 +90958 0.870361328125 +90959 0.86480712890625 +90960 0.831817626953125 +90961 0.677581787109375 +90962 0.495880126953125 +90963 0.30767822265625 +90964 0.116180419921875 +90965 -0.110748291015625 +90966 -0.381805419921875 +90967 -0.6572265625 +90968 -0.857421875 +90969 -0.870391845703125 +90970 -0.870391845703125 +90971 -0.86444091796875 +90972 -0.85723876953125 +90973 -0.790008544921875 +90974 -0.62847900390625 +90975 -0.3956298828125 +90976 -0.126708984375 +90977 0.150115966796875 +90978 0.424041748046875 +90979 0.670623779296875 +90980 0.854522705078125 +90981 0.866485595703125 +90982 0.86920166015625 +90983 0.8653564453125 +90984 0.857147216796875 +90985 0.766845703125 +90986 0.628509521484375 +90987 0.462127685546875 +90988 0.297210693359375 +90989 0.14862060546875 +90990 -0.00537109375 +90991 -0.15753173828125 +90992 -0.31304931640625 +90993 -0.48876953125 +90994 -0.6416015625 +90995 -0.751373291015625 +90996 -0.84619140625 +90997 -0.861297607421875 +90998 -0.863250732421875 +90999 -0.856597900390625 +91000 -0.7498779296875 +91001 -0.624542236328125 +91002 -0.47808837890625 +91003 -0.253387451171875 +91004 0.003692626953125 +91005 0.2257080078125 +91006 0.427154541015625 +91007 0.643218994140625 +91008 0.855926513671875 +91009 0.870361328125 +91010 0.870361328125 +91011 0.862762451171875 +91012 0.79669189453125 +91013 0.595794677734375 +91014 0.362152099609375 +91015 0.1270751953125 +91016 -0.086944580078125 +91017 -0.2784423828125 +91018 -0.484832763671875 +91019 -0.729583740234375 +91020 -0.86688232421875 +91021 -0.870391845703125 +91022 -0.86859130859375 +91023 -0.86279296875 +91024 -0.817962646484375 +91025 -0.6116943359375 +91026 -0.3128662109375 +91027 0.039398193359375 +91028 0.422821044921875 +91029 0.805145263671875 +91030 0.870361328125 +91031 0.870361328125 +91032 0.860015869140625 +91033 0.727935791015625 +91034 0.48114013671875 +91035 0.2059326171875 +91036 -0.06103515625 +91037 -0.29913330078125 +91038 -0.516204833984375 +91039 -0.7252197265625 +91040 -0.85980224609375 +91041 -0.870391845703125 +91042 -0.870391845703125 +91043 -0.858062744140625 +91044 -0.673004150390625 +91045 -0.42694091796875 +91046 -0.2100830078125 +91047 -0.0362548828125 +91048 0.10943603515625 +91049 0.23516845703125 +91050 0.373687744140625 +91051 0.517791748046875 +91052 0.602783203125 +91053 0.635711669921875 +91054 0.655181884765625 +91055 0.65948486328125 +91056 0.651275634765625 +91057 0.61846923828125 +91058 0.53753662109375 +91059 0.404144287109375 +91060 0.22186279296875 +91061 0.003997802734375 +91062 -0.22100830078125 +91063 -0.42449951171875 +91064 -0.579833984375 +91065 -0.641876220703125 +91066 -0.6177978515625 +91067 -0.575531005859375 +91068 -0.526336669921875 +91069 -0.42645263671875 +91070 -0.2581787109375 +91071 -0.068695068359375 +91072 0.09222412109375 +91073 0.232147216796875 +91074 0.3509521484375 +91075 0.410064697265625 +91076 0.372955322265625 +91077 0.2554931640625 +91078 0.10711669921875 +91079 -0.052886962890625 +91080 -0.186279296875 +91081 -0.23291015625 +91082 -0.209442138671875 +91083 -0.174163818359375 +91084 -0.126739501953125 +91085 -0.048126220703125 +91086 0.0426025390625 +91087 0.10748291015625 +91088 0.1409912109375 +91089 0.19708251953125 +91090 0.273651123046875 +91091 0.31768798828125 +91092 0.341094970703125 +91093 0.368011474609375 +91094 0.37249755859375 +91095 0.30072021484375 +91096 0.1517333984375 +91097 -0.01470947265625 +91098 -0.1883544921875 +91099 -0.372711181640625 +91100 -0.51397705078125 +91101 -0.57177734375 +91102 -0.53948974609375 +91103 -0.43511962890625 +91104 -0.2962646484375 +91105 -0.161102294921875 +91106 -0.0435791015625 +91107 0.060394287109375 +91108 0.13665771484375 +91109 0.170135498046875 +91110 0.16552734375 +91111 0.15728759765625 +91112 0.150787353515625 +91113 0.12200927734375 +91114 0.080108642578125 +91115 0.05126953125 +91116 0.062896728515625 +91117 0.09271240234375 +91118 0.092987060546875 +91119 0.07855224609375 +91120 0.06427001953125 +91121 0.0347900390625 +91122 -0.01171875 +91123 -0.056060791015625 +91124 -0.055511474609375 +91125 -0.010467529296875 +91126 0.02508544921875 +91127 0.025665283203125 +91128 0.017333984375 +91129 0.00189208984375 +91130 -0.03173828125 +91131 -0.071502685546875 +91132 -0.13543701171875 +91133 -0.219970703125 +91134 -0.300506591796875 +91135 -0.376312255859375 +91136 -0.416107177734375 +91137 -0.371124267578125 +91138 -0.242279052734375 +91139 -0.069732666015625 +91140 0.125640869140625 +91141 0.31268310546875 +91142 0.45501708984375 +91143 0.554779052734375 +91144 0.61065673828125 +91145 0.610931396484375 +91146 0.531463623046875 +91147 0.3883056640625 +91148 0.23468017578125 +91149 0.095245361328125 +91150 -0.00396728515625 +91151 -0.04852294921875 +91152 -0.055145263671875 +91153 -0.0758056640625 +91154 -0.138702392578125 +91155 -0.209197998046875 +91156 -0.289031982421875 +91157 -0.37884521484375 +91158 -0.456329345703125 +91159 -0.51641845703125 +91160 -0.519287109375 +91161 -0.458251953125 +91162 -0.384796142578125 +91163 -0.323699951171875 +91164 -0.269287109375 +91165 -0.1951904296875 +91166 -0.100006103515625 +91167 -0.01055908203125 +91168 0.1033935546875 +91169 0.24908447265625 +91170 0.373199462890625 +91171 0.45806884765625 +91172 0.511474609375 +91173 0.565399169921875 +91174 0.61138916015625 +91175 0.5897216796875 +91176 0.4906005859375 +91177 0.33148193359375 +91178 0.147796630859375 +91179 -0.01873779296875 +91180 -0.140289306640625 +91181 -0.191986083984375 +91182 -0.184295654296875 +91183 -0.161834716796875 +91184 -0.166595458984375 +91185 -0.19390869140625 +91186 -0.22442626953125 +91187 -0.279754638671875 +91188 -0.3389892578125 +91189 -0.3543701171875 +91190 -0.348175048828125 +91191 -0.32598876953125 +91192 -0.2581787109375 +91193 -0.139801025390625 +91194 0.014617919921875 +91195 0.144378662109375 +91196 0.221038818359375 +91197 0.27069091796875 +91198 0.294036865234375 +91199 0.311767578125 +91200 0.339141845703125 +91201 0.360260009765625 +91202 0.360504150390625 +91203 0.308380126953125 +91204 0.18170166015625 +91205 0.0047607421875 +91206 -0.17559814453125 +91207 -0.3143310546875 +91208 -0.36785888671875 +91209 -0.36248779296875 +91210 -0.343536376953125 +91211 -0.3018798828125 +91212 -0.231414794921875 +91213 -0.117645263671875 +91214 0.007049560546875 +91215 0.087982177734375 +91216 0.13946533203125 +91217 0.17425537109375 +91218 0.188201904296875 +91219 0.171234130859375 +91220 0.118438720703125 +91221 0.05706787109375 +91222 -0.010711669921875 +91223 -0.0914306640625 +91224 -0.162322998046875 +91225 -0.194549560546875 +91226 -0.1492919921875 +91227 -0.02166748046875 +91228 0.124053955078125 +91229 0.211151123046875 +91230 0.240447998046875 +91231 0.242218017578125 +91232 0.2257080078125 +91233 0.194366455078125 +91234 0.115509033203125 +91235 0.0128173828125 +91236 -0.053802490234375 +91237 -0.110626220703125 +91238 -0.199493408203125 +91239 -0.29437255859375 +91240 -0.33221435546875 +91241 -0.27972412109375 +91242 -0.185333251953125 +91243 -0.128204345703125 +91244 -0.115692138671875 +91245 -0.116455078125 +91246 -0.105926513671875 +91247 -0.053955078125 +91248 0.048797607421875 +91249 0.157318115234375 +91250 0.212005615234375 +91251 0.218475341796875 +91252 0.23724365234375 +91253 0.30535888671875 +91254 0.38128662109375 +91255 0.404449462890625 +91256 0.3944091796875 +91257 0.3885498046875 +91258 0.362640380859375 +91259 0.27362060546875 +91260 0.11712646484375 +91261 -0.054901123046875 +91262 -0.19085693359375 +91263 -0.28570556640625 +91264 -0.339263916015625 +91265 -0.3775634765625 +91266 -0.445709228515625 +91267 -0.535064697265625 +91268 -0.629058837890625 +91269 -0.697601318359375 +91270 -0.70391845703125 +91271 -0.6424560546875 +91272 -0.491241455078125 +91273 -0.265716552734375 +91274 -0.023712158203125 +91275 0.201751708984375 +91276 0.375823974609375 +91277 0.485076904296875 +91278 0.56884765625 +91279 0.634765625 +91280 0.63763427734375 +91281 0.5660400390625 +91282 0.4720458984375 +91283 0.40692138671875 +91284 0.3778076171875 +91285 0.376953125 +91286 0.371978759765625 +91287 0.313140869140625 +91288 0.184417724609375 +91289 0.011199951171875 +91290 -0.171051025390625 +91291 -0.33740234375 +91292 -0.47198486328125 +91293 -0.560394287109375 +91294 -0.58056640625 +91295 -0.54754638671875 +91296 -0.508575439453125 +91297 -0.459503173828125 +91298 -0.394378662109375 +91299 -0.35260009765625 +91300 -0.31170654296875 +91301 -0.197418212890625 +91302 -0.007965087890625 +91303 0.207489013671875 +91304 0.409210205078125 +91305 0.57208251953125 +91306 0.66595458984375 +91307 0.65875244140625 +91308 0.56744384765625 +91309 0.431396484375 +91310 0.29443359375 +91311 0.182464599609375 +91312 0.06365966796875 +91313 -0.075958251953125 +91314 -0.189422607421875 +91315 -0.271942138671875 +91316 -0.342529296875 +91317 -0.364166259765625 +91318 -0.327239990234375 +91319 -0.2769775390625 +91320 -0.253692626953125 +91321 -0.24365234375 +91322 -0.1983642578125 +91323 -0.116241455078125 +91324 -0.036834716796875 +91325 0.034881591796875 +91326 0.09124755859375 +91327 0.10888671875 +91328 0.125518798828125 +91329 0.15771484375 +91330 0.17828369140625 +91331 0.17108154296875 +91332 0.129974365234375 +91333 0.082427978515625 +91334 0.027679443359375 +91335 -0.065643310546875 +91336 -0.15936279296875 +91337 -0.21307373046875 +91338 -0.234649658203125 +91339 -0.2001953125 +91340 -0.119171142578125 +91341 -0.024749755859375 +91342 0.085784912109375 +91343 0.178131103515625 +91344 0.215576171875 +91345 0.211456298828125 +91346 0.17523193359375 +91347 0.128753662109375 +91348 0.1019287109375 +91349 0.0743408203125 +91350 0.04327392578125 +91351 0.038177490234375 +91352 0.076263427734375 +91353 0.14105224609375 +91354 0.186431884765625 +91355 0.188812255859375 +91356 0.1390380859375 +91357 0.041778564453125 +91358 -0.079437255859375 +91359 -0.219390869140625 +91360 -0.367828369140625 +91361 -0.494873046875 +91362 -0.556243896484375 +91363 -0.508697509765625 +91364 -0.3756103515625 +91365 -0.218902587890625 +91366 -0.063751220703125 +91367 0.091552734375 +91368 0.23602294921875 +91369 0.342987060546875 +91370 0.39520263671875 +91371 0.389373779296875 +91372 0.324249267578125 +91373 0.224090576171875 +91374 0.124267578125 +91375 0.037078857421875 +91376 -0.010101318359375 +91377 -0.019439697265625 +91378 -0.022796630859375 +91379 -0.001556396484375 +91380 0.056304931640625 +91381 0.106719970703125 +91382 0.096893310546875 +91383 0.042694091796875 +91384 -0.018035888671875 +91385 -0.07586669921875 +91386 -0.11944580078125 +91387 -0.15972900390625 +91388 -0.202606201171875 +91389 -0.24859619140625 +91390 -0.30517578125 +91391 -0.36212158203125 +91392 -0.39141845703125 +91393 -0.35528564453125 +91394 -0.249969482421875 +91395 -0.092864990234375 +91396 0.08905029296875 +91397 0.2352294921875 +91398 0.318817138671875 +91399 0.358642578125 +91400 0.347747802734375 +91401 0.28564453125 +91402 0.223175048828125 +91403 0.196746826171875 +91404 0.179840087890625 +91405 0.155548095703125 +91406 0.151214599609375 +91407 0.156951904296875 +91408 0.13177490234375 +91409 0.100799560546875 +91410 0.087127685546875 +91411 0.05487060546875 +91412 -0.009002685546875 +91413 -0.10400390625 +91414 -0.229400634765625 +91415 -0.35552978515625 +91416 -0.441925048828125 +91417 -0.473846435546875 +91418 -0.464813232421875 +91419 -0.419097900390625 +91420 -0.334320068359375 +91421 -0.227935791015625 +91422 -0.12347412109375 +91423 -0.02764892578125 +91424 0.077667236328125 +91425 0.2132568359375 +91426 0.38885498046875 +91427 0.582794189453125 +91428 0.734039306640625 +91429 0.800140380859375 +91430 0.7783203125 +91431 0.6651611328125 +91432 0.45965576171875 +91433 0.199188232421875 +91434 -0.050689697265625 +91435 -0.23297119140625 +91436 -0.33013916015625 +91437 -0.368408203125 +91438 -0.378936767578125 +91439 -0.376983642578125 +91440 -0.37969970703125 +91441 -0.391510009765625 +91442 -0.385345458984375 +91443 -0.3419189453125 +91444 -0.28289794921875 +91445 -0.251617431640625 +91446 -0.266143798828125 +91447 -0.273345947265625 +91448 -0.216796875 +91449 -0.128265380859375 +91450 -0.068145751953125 +91451 -0.0430908203125 +91452 -0.024444580078125 +91453 0.020721435546875 +91454 0.124481201171875 +91455 0.25787353515625 +91456 0.379119873046875 +91457 0.47991943359375 +91458 0.5281982421875 +91459 0.511138916015625 +91460 0.456207275390625 +91461 0.407470703125 +91462 0.383758544921875 +91463 0.35687255859375 +91464 0.31182861328125 +91465 0.250885009765625 +91466 0.1654052734375 +91467 0.035247802734375 +91468 -0.142059326171875 +91469 -0.33563232421875 +91470 -0.5345458984375 +91471 -0.72186279296875 +91472 -0.836669921875 +91473 -0.8326416015625 +91474 -0.7296142578125 +91475 -0.582550048828125 +91476 -0.440093994140625 +91477 -0.324310302734375 +91478 -0.20147705078125 +91479 -0.044647216796875 +91480 0.103973388671875 +91481 0.202392578125 +91482 0.264495849609375 +91483 0.338897705078125 +91484 0.443817138671875 +91485 0.545074462890625 +91486 0.6173095703125 +91487 0.6524658203125 +91488 0.66339111328125 +91489 0.6561279296875 +91490 0.606781005859375 +91491 0.501190185546875 +91492 0.352783203125 +91493 0.176544189453125 +91494 -0.034820556640625 +91495 -0.258209228515625 +91496 -0.44244384765625 +91497 -0.5753173828125 +91498 -0.65203857421875 +91499 -0.641632080078125 +91500 -0.562164306640625 +91501 -0.458038330078125 +91502 -0.350555419921875 +91503 -0.260528564453125 +91504 -0.192108154296875 +91505 -0.141937255859375 +91506 -0.1021728515625 +91507 -0.062896728515625 +91508 -0.011932373046875 +91509 0.062835693359375 +91510 0.148712158203125 +91511 0.241729736328125 +91512 0.34912109375 +91513 0.457305908203125 +91514 0.54388427734375 +91515 0.5728759765625 +91516 0.506591796875 +91517 0.351226806640625 +91518 0.146514892578125 +91519 -0.05523681640625 +91520 -0.21624755859375 +91521 -0.334930419921875 +91522 -0.402984619140625 +91523 -0.4412841796875 +91524 -0.49578857421875 +91525 -0.5601806640625 +91526 -0.600738525390625 +91527 -0.584228515625 +91528 -0.47930908203125 +91529 -0.27935791015625 +91530 -0.0089111328125 +91531 0.268798828125 +91532 0.482818603515625 +91533 0.60369873046875 +91534 0.650421142578125 +91535 0.66400146484375 +91536 0.6414794921875 +91537 0.572540283203125 +91538 0.498138427734375 +91539 0.439453125 +91540 0.375518798828125 +91541 0.274505615234375 +91542 0.1087646484375 +91543 -0.099395751953125 +91544 -0.3182373046875 +91545 -0.5489501953125 +91546 -0.7738037109375 +91547 -0.86383056640625 +91548 -0.870391845703125 +91549 -0.86895751953125 +91550 -0.861053466796875 +91551 -0.765869140625 +91552 -0.5301513671875 +91553 -0.214691162109375 +91554 0.137359619140625 +91555 0.474822998046875 +91556 0.76239013671875 +91557 0.867462158203125 +91558 0.870361328125 +91559 0.86480712890625 +91560 0.831817626953125 +91561 0.677581787109375 +91562 0.495880126953125 +91563 0.30767822265625 +91564 0.116180419921875 +91565 -0.110748291015625 +91566 -0.381805419921875 +91567 -0.6572265625 +91568 -0.857421875 +91569 -0.870391845703125 +91570 -0.870391845703125 +91571 -0.86444091796875 +91572 -0.85723876953125 +91573 -0.790008544921875 +91574 -0.62847900390625 +91575 -0.3956298828125 +91576 -0.126708984375 +91577 0.150115966796875 +91578 0.424041748046875 +91579 0.670623779296875 +91580 0.854522705078125 +91581 0.866485595703125 +91582 0.86920166015625 +91583 0.8653564453125 +91584 0.857147216796875 +91585 0.766845703125 +91586 0.628509521484375 +91587 0.462127685546875 +91588 0.297210693359375 +91589 0.14862060546875 +91590 -0.00537109375 +91591 -0.15753173828125 +91592 -0.31304931640625 +91593 -0.48876953125 +91594 -0.6416015625 +91595 -0.751373291015625 +91596 -0.84619140625 +91597 -0.861297607421875 +91598 -0.863250732421875 +91599 -0.856597900390625 +91600 -0.7498779296875 +91601 -0.624542236328125 +91602 -0.47808837890625 +91603 -0.253387451171875 +91604 0.003692626953125 +91605 0.2257080078125 +91606 0.427154541015625 +91607 0.643218994140625 +91608 0.855926513671875 +91609 0.870361328125 +91610 0.870361328125 +91611 0.862762451171875 +91612 0.79669189453125 +91613 0.595794677734375 +91614 0.362152099609375 +91615 0.1270751953125 +91616 -0.086944580078125 +91617 -0.2784423828125 +91618 -0.484832763671875 +91619 -0.729583740234375 +91620 -0.86688232421875 +91621 -0.870391845703125 +91622 -0.86859130859375 +91623 -0.86279296875 +91624 -0.817962646484375 +91625 -0.6116943359375 +91626 -0.3128662109375 +91627 0.039398193359375 +91628 0.422821044921875 +91629 0.805145263671875 +91630 0.870361328125 +91631 0.870361328125 +91632 0.860015869140625 +91633 0.727935791015625 +91634 0.48114013671875 +91635 0.2059326171875 +91636 -0.06103515625 +91637 -0.29913330078125 +91638 -0.516204833984375 +91639 -0.7252197265625 +91640 -0.85980224609375 +91641 -0.870391845703125 +91642 -0.870391845703125 +91643 -0.858062744140625 +91644 -0.673004150390625 +91645 -0.42694091796875 +91646 -0.2100830078125 +91647 -0.0362548828125 +91648 0.10943603515625 +91649 0.23516845703125 +91650 0.373687744140625 +91651 0.517791748046875 +91652 0.602783203125 +91653 0.635711669921875 +91654 0.655181884765625 +91655 0.65948486328125 +91656 0.651275634765625 +91657 0.61846923828125 +91658 0.53753662109375 +91659 0.404144287109375 +91660 0.22186279296875 +91661 0.003997802734375 +91662 -0.22100830078125 +91663 -0.42449951171875 +91664 -0.579833984375 +91665 -0.641876220703125 +91666 -0.6177978515625 +91667 -0.575531005859375 +91668 -0.526336669921875 +91669 -0.42645263671875 +91670 -0.2581787109375 +91671 -0.068695068359375 +91672 0.09222412109375 +91673 0.232147216796875 +91674 0.3509521484375 +91675 0.410064697265625 +91676 0.372955322265625 +91677 0.2554931640625 +91678 0.10711669921875 +91679 -0.052886962890625 +91680 -0.186279296875 +91681 -0.23291015625 +91682 -0.209442138671875 +91683 -0.174163818359375 +91684 -0.126739501953125 +91685 -0.048126220703125 +91686 0.0426025390625 +91687 0.10748291015625 +91688 0.1409912109375 +91689 0.19708251953125 +91690 0.273651123046875 +91691 0.31768798828125 +91692 0.341094970703125 +91693 0.368011474609375 +91694 0.37249755859375 +91695 0.30072021484375 +91696 0.1517333984375 +91697 -0.01470947265625 +91698 -0.1883544921875 +91699 -0.372711181640625 +91700 -0.51397705078125 +91701 -0.57177734375 +91702 -0.53948974609375 +91703 -0.43511962890625 +91704 -0.2962646484375 +91705 -0.161102294921875 +91706 -0.0435791015625 +91707 0.060394287109375 +91708 0.13665771484375 +91709 0.170135498046875 +91710 0.16552734375 +91711 0.15728759765625 +91712 0.150787353515625 +91713 0.12200927734375 +91714 0.080108642578125 +91715 0.05126953125 +91716 0.062896728515625 +91717 0.09271240234375 +91718 0.092987060546875 +91719 0.07855224609375 +91720 0.06427001953125 +91721 0.0347900390625 +91722 -0.01171875 +91723 -0.056060791015625 +91724 -0.055511474609375 +91725 -0.010467529296875 +91726 0.02508544921875 +91727 0.025665283203125 +91728 0.017333984375 +91729 0.00189208984375 +91730 -0.03173828125 +91731 -0.071502685546875 +91732 -0.13543701171875 +91733 -0.219970703125 +91734 -0.300506591796875 +91735 -0.376312255859375 +91736 -0.416107177734375 +91737 -0.371124267578125 +91738 -0.242279052734375 +91739 -0.069732666015625 +91740 0.125640869140625 +91741 0.31268310546875 +91742 0.45501708984375 +91743 0.554779052734375 +91744 0.61065673828125 +91745 0.610931396484375 +91746 0.531463623046875 +91747 0.3883056640625 +91748 0.23468017578125 +91749 0.095245361328125 +91750 -0.00396728515625 +91751 -0.04852294921875 +91752 -0.055145263671875 +91753 -0.0758056640625 +91754 -0.138702392578125 +91755 -0.209197998046875 +91756 -0.289031982421875 +91757 -0.37884521484375 +91758 -0.456329345703125 +91759 -0.51641845703125 +91760 -0.519287109375 +91761 -0.458251953125 +91762 -0.384796142578125 +91763 -0.323699951171875 +91764 -0.269287109375 +91765 -0.1951904296875 +91766 -0.100006103515625 +91767 -0.01055908203125 +91768 0.1033935546875 +91769 0.24908447265625 +91770 0.373199462890625 +91771 0.45806884765625 +91772 0.511474609375 +91773 0.565399169921875 +91774 0.61138916015625 +91775 0.5897216796875 +91776 0.4906005859375 +91777 0.33148193359375 +91778 0.147796630859375 +91779 -0.01873779296875 +91780 -0.140289306640625 +91781 -0.191986083984375 +91782 -0.184295654296875 +91783 -0.161834716796875 +91784 -0.166595458984375 +91785 -0.19390869140625 +91786 -0.22442626953125 +91787 -0.279754638671875 +91788 -0.3389892578125 +91789 -0.3543701171875 +91790 -0.348175048828125 +91791 -0.32598876953125 +91792 -0.2581787109375 +91793 -0.139801025390625 +91794 0.014617919921875 +91795 0.144378662109375 +91796 0.221038818359375 +91797 0.27069091796875 +91798 0.294036865234375 +91799 0.311767578125 +91800 0.339141845703125 +91801 0.360260009765625 +91802 0.360504150390625 +91803 0.308380126953125 +91804 0.18170166015625 +91805 0.0047607421875 +91806 -0.17559814453125 +91807 -0.3143310546875 +91808 -0.36785888671875 +91809 -0.36248779296875 +91810 -0.343536376953125 +91811 -0.3018798828125 +91812 -0.231414794921875 +91813 -0.117645263671875 +91814 0.007049560546875 +91815 0.087982177734375 +91816 0.13946533203125 +91817 0.17425537109375 +91818 0.188201904296875 +91819 0.171234130859375 +91820 0.118438720703125 +91821 0.05706787109375 +91822 -0.010711669921875 +91823 -0.0914306640625 +91824 -0.162322998046875 +91825 -0.194549560546875 +91826 -0.1492919921875 +91827 -0.02166748046875 +91828 0.124053955078125 +91829 0.211151123046875 +91830 0.240447998046875 +91831 0.242218017578125 +91832 0.2257080078125 +91833 0.194366455078125 +91834 0.115509033203125 +91835 0.0128173828125 +91836 -0.053802490234375 +91837 -0.110626220703125 +91838 -0.199493408203125 +91839 -0.29437255859375 +91840 -0.33221435546875 +91841 -0.27972412109375 +91842 -0.185333251953125 +91843 -0.128204345703125 +91844 -0.115692138671875 +91845 -0.116455078125 +91846 -0.105926513671875 +91847 -0.053955078125 +91848 0.048797607421875 +91849 0.157318115234375 +91850 0.212005615234375 +91851 0.218475341796875 +91852 0.23724365234375 +91853 0.30535888671875 +91854 0.38128662109375 +91855 0.404449462890625 +91856 0.3944091796875 +91857 0.3885498046875 +91858 0.362640380859375 +91859 0.27362060546875 +91860 0.11712646484375 +91861 -0.054901123046875 +91862 -0.19085693359375 +91863 -0.28570556640625 +91864 -0.339263916015625 +91865 -0.3775634765625 +91866 -0.445709228515625 +91867 -0.535064697265625 +91868 -0.629058837890625 +91869 -0.697601318359375 +91870 -0.70391845703125 +91871 -0.6424560546875 +91872 -0.491241455078125 +91873 -0.265716552734375 +91874 -0.023712158203125 +91875 0.201751708984375 +91876 0.375823974609375 +91877 0.485076904296875 +91878 0.56884765625 +91879 0.634765625 +91880 0.63763427734375 +91881 0.5660400390625 +91882 0.4720458984375 +91883 0.40692138671875 +91884 0.3778076171875 +91885 0.376953125 +91886 0.371978759765625 +91887 0.313140869140625 +91888 0.184417724609375 +91889 0.011199951171875 +91890 -0.171051025390625 +91891 -0.33740234375 +91892 -0.47198486328125 +91893 -0.560394287109375 +91894 -0.58056640625 +91895 -0.54754638671875 +91896 -0.508575439453125 +91897 -0.459503173828125 +91898 -0.394378662109375 +91899 -0.35260009765625 +91900 -0.31170654296875 +91901 -0.197418212890625 +91902 -0.007965087890625 +91903 0.207489013671875 +91904 0.409210205078125 +91905 0.57208251953125 +91906 0.66595458984375 +91907 0.65875244140625 +91908 0.56744384765625 +91909 0.431396484375 +91910 0.29443359375 +91911 0.182464599609375 +91912 0.06365966796875 +91913 -0.075958251953125 +91914 -0.189422607421875 +91915 -0.271942138671875 +91916 -0.342529296875 +91917 -0.364166259765625 +91918 -0.327239990234375 +91919 -0.2769775390625 +91920 -0.253692626953125 +91921 -0.24365234375 +91922 -0.1983642578125 +91923 -0.116241455078125 +91924 -0.036834716796875 +91925 0.034881591796875 +91926 0.09124755859375 +91927 0.10888671875 +91928 0.125518798828125 +91929 0.15771484375 +91930 0.17828369140625 +91931 0.17108154296875 +91932 0.129974365234375 +91933 0.082427978515625 +91934 0.027679443359375 +91935 -0.065643310546875 +91936 -0.15936279296875 +91937 -0.21307373046875 +91938 -0.234649658203125 +91939 -0.2001953125 +91940 -0.119171142578125 +91941 -0.024749755859375 +91942 0.085784912109375 +91943 0.178131103515625 +91944 0.215576171875 +91945 0.211456298828125 +91946 0.17523193359375 +91947 0.128753662109375 +91948 0.1019287109375 +91949 0.0743408203125 +91950 0.04327392578125 +91951 0.038177490234375 +91952 0.076263427734375 +91953 0.14105224609375 +91954 0.186431884765625 +91955 0.188812255859375 +91956 0.1390380859375 +91957 0.041778564453125 +91958 -0.079437255859375 +91959 -0.219390869140625 +91960 -0.367828369140625 +91961 -0.494873046875 +91962 -0.556243896484375 +91963 -0.508697509765625 +91964 -0.3756103515625 +91965 -0.218902587890625 +91966 -0.063751220703125 +91967 0.091552734375 +91968 0.23602294921875 +91969 0.342987060546875 +91970 0.39520263671875 +91971 0.389373779296875 +91972 0.324249267578125 +91973 0.224090576171875 +91974 0.124267578125 +91975 0.037078857421875 +91976 -0.010101318359375 +91977 -0.019439697265625 +91978 -0.022796630859375 +91979 -0.001556396484375 +91980 0.056304931640625 +91981 0.106719970703125 +91982 0.096893310546875 +91983 0.042694091796875 +91984 -0.018035888671875 +91985 -0.07586669921875 +91986 -0.11944580078125 +91987 -0.15972900390625 +91988 -0.202606201171875 +91989 -0.24859619140625 +91990 -0.30517578125 +91991 -0.36212158203125 +91992 -0.39141845703125 +91993 -0.35528564453125 +91994 -0.249969482421875 +91995 -0.092864990234375 +91996 0.08905029296875 +91997 0.2352294921875 +91998 0.318817138671875 +91999 0.358642578125 +92000 0.347747802734375 +92001 0.28564453125 +92002 0.223175048828125 +92003 0.196746826171875 +92004 0.179840087890625 +92005 0.155548095703125 +92006 0.151214599609375 +92007 0.156951904296875 +92008 0.13177490234375 +92009 0.100799560546875 +92010 0.087127685546875 +92011 0.05487060546875 +92012 -0.009002685546875 +92013 -0.10400390625 +92014 -0.229400634765625 +92015 -0.35552978515625 +92016 -0.441925048828125 +92017 -0.473846435546875 +92018 -0.464813232421875 +92019 -0.419097900390625 +92020 -0.334320068359375 +92021 -0.227935791015625 +92022 -0.12347412109375 +92023 -0.02764892578125 +92024 0.077667236328125 +92025 0.2132568359375 +92026 0.38885498046875 +92027 0.582794189453125 +92028 0.734039306640625 +92029 0.800140380859375 +92030 0.7783203125 +92031 0.6651611328125 +92032 0.45965576171875 +92033 0.199188232421875 +92034 -0.050689697265625 +92035 -0.23297119140625 +92036 -0.33013916015625 +92037 -0.368408203125 +92038 -0.378936767578125 +92039 -0.376983642578125 +92040 -0.37969970703125 +92041 -0.391510009765625 +92042 -0.385345458984375 +92043 -0.3419189453125 +92044 -0.28289794921875 +92045 -0.251617431640625 +92046 -0.266143798828125 +92047 -0.273345947265625 +92048 -0.216796875 +92049 -0.128265380859375 +92050 -0.068145751953125 +92051 -0.0430908203125 +92052 -0.024444580078125 +92053 0.020721435546875 +92054 0.124481201171875 +92055 0.25787353515625 +92056 0.379119873046875 +92057 0.47991943359375 +92058 0.5281982421875 +92059 0.511138916015625 +92060 0.456207275390625 +92061 0.407470703125 +92062 0.383758544921875 +92063 0.35687255859375 +92064 0.31182861328125 +92065 0.250885009765625 +92066 0.1654052734375 +92067 0.035247802734375 +92068 -0.142059326171875 +92069 -0.33563232421875 +92070 -0.5345458984375 +92071 -0.72186279296875 +92072 -0.836669921875 +92073 -0.8326416015625 +92074 -0.7296142578125 +92075 -0.582550048828125 +92076 -0.440093994140625 +92077 -0.324310302734375 +92078 -0.20147705078125 +92079 -0.044647216796875 +92080 0.103973388671875 +92081 0.202392578125 +92082 0.264495849609375 +92083 0.338897705078125 +92084 0.443817138671875 +92085 0.545074462890625 +92086 0.6173095703125 +92087 0.6524658203125 +92088 0.66339111328125 +92089 0.6561279296875 +92090 0.606781005859375 +92091 0.501190185546875 +92092 0.352783203125 +92093 0.176544189453125 +92094 -0.034820556640625 +92095 -0.258209228515625 +92096 -0.44244384765625 +92097 -0.5753173828125 +92098 -0.65203857421875 +92099 -0.641632080078125 +92100 -0.562164306640625 +92101 -0.458038330078125 +92102 -0.350555419921875 +92103 -0.260528564453125 +92104 -0.192108154296875 +92105 -0.141937255859375 +92106 -0.1021728515625 +92107 -0.062896728515625 +92108 -0.011932373046875 +92109 0.062835693359375 +92110 0.148712158203125 +92111 0.241729736328125 +92112 0.34912109375 +92113 0.457305908203125 +92114 0.54388427734375 +92115 0.5728759765625 +92116 0.506591796875 +92117 0.351226806640625 +92118 0.146514892578125 +92119 -0.05523681640625 +92120 -0.21624755859375 +92121 -0.334930419921875 +92122 -0.402984619140625 +92123 -0.4412841796875 +92124 -0.49578857421875 +92125 -0.5601806640625 +92126 -0.600738525390625 +92127 -0.584228515625 +92128 -0.47930908203125 +92129 -0.27935791015625 +92130 -0.0089111328125 +92131 0.268798828125 +92132 0.482818603515625 +92133 0.60369873046875 +92134 0.650421142578125 +92135 0.66400146484375 +92136 0.6414794921875 +92137 0.572540283203125 +92138 0.498138427734375 +92139 0.439453125 +92140 0.375518798828125 +92141 0.274505615234375 +92142 0.1087646484375 +92143 -0.099395751953125 +92144 -0.3182373046875 +92145 -0.5489501953125 +92146 -0.7738037109375 +92147 -0.86383056640625 +92148 -0.870391845703125 +92149 -0.86895751953125 +92150 -0.861053466796875 +92151 -0.765869140625 +92152 -0.5301513671875 +92153 -0.214691162109375 +92154 0.137359619140625 +92155 0.474822998046875 +92156 0.76239013671875 +92157 0.867462158203125 +92158 0.870361328125 +92159 0.86480712890625 +92160 0.831817626953125 +92161 0.677581787109375 +92162 0.495880126953125 +92163 0.30767822265625 +92164 0.116180419921875 +92165 -0.110748291015625 +92166 -0.381805419921875 +92167 -0.6572265625 +92168 -0.857421875 +92169 -0.870391845703125 +92170 -0.870391845703125 +92171 -0.86444091796875 +92172 -0.85723876953125 +92173 -0.790008544921875 +92174 -0.62847900390625 +92175 -0.3956298828125 +92176 -0.126708984375 +92177 0.150115966796875 +92178 0.424041748046875 +92179 0.670623779296875 +92180 0.854522705078125 +92181 0.866485595703125 +92182 0.86920166015625 +92183 0.8653564453125 +92184 0.857147216796875 +92185 0.766845703125 +92186 0.628509521484375 +92187 0.462127685546875 +92188 0.297210693359375 +92189 0.14862060546875 +92190 -0.00537109375 +92191 -0.15753173828125 +92192 -0.31304931640625 +92193 -0.48876953125 +92194 -0.6416015625 +92195 -0.751373291015625 +92196 -0.84619140625 +92197 -0.861297607421875 +92198 -0.863250732421875 +92199 -0.856597900390625 +92200 -0.7498779296875 +92201 -0.624542236328125 +92202 -0.47808837890625 +92203 -0.253387451171875 +92204 0.003692626953125 +92205 0.2257080078125 +92206 0.427154541015625 +92207 0.643218994140625 +92208 0.855926513671875 +92209 0.870361328125 +92210 0.870361328125 +92211 0.862762451171875 +92212 0.79669189453125 +92213 0.595794677734375 +92214 0.362152099609375 +92215 0.1270751953125 +92216 -0.086944580078125 +92217 -0.2784423828125 +92218 -0.484832763671875 +92219 -0.729583740234375 +92220 -0.86688232421875 +92221 -0.870391845703125 +92222 -0.86859130859375 +92223 -0.86279296875 +92224 -0.817962646484375 +92225 -0.6116943359375 +92226 -0.3128662109375 +92227 0.039398193359375 +92228 0.422821044921875 +92229 0.805145263671875 +92230 0.870361328125 +92231 0.870361328125 +92232 0.860015869140625 +92233 0.727935791015625 +92234 0.48114013671875 +92235 0.2059326171875 +92236 -0.06103515625 +92237 -0.29913330078125 +92238 -0.516204833984375 +92239 -0.7252197265625 +92240 -0.85980224609375 +92241 -0.870391845703125 +92242 -0.870391845703125 +92243 -0.858062744140625 +92244 -0.673004150390625 +92245 -0.42694091796875 +92246 -0.2100830078125 +92247 -0.0362548828125 +92248 0.10943603515625 +92249 0.23516845703125 +92250 0.373687744140625 +92251 0.517791748046875 +92252 0.602783203125 +92253 0.635711669921875 +92254 0.655181884765625 +92255 0.65948486328125 +92256 0.651275634765625 +92257 0.61846923828125 +92258 0.53753662109375 +92259 0.404144287109375 +92260 0.22186279296875 +92261 0.003997802734375 +92262 -0.22100830078125 +92263 -0.42449951171875 +92264 -0.579833984375 +92265 -0.641876220703125 +92266 -0.6177978515625 +92267 -0.575531005859375 +92268 -0.526336669921875 +92269 -0.42645263671875 +92270 -0.2581787109375 +92271 -0.068695068359375 +92272 0.09222412109375 +92273 0.232147216796875 +92274 0.3509521484375 +92275 0.410064697265625 +92276 0.372955322265625 +92277 0.2554931640625 +92278 0.10711669921875 +92279 -0.052886962890625 +92280 -0.186279296875 +92281 -0.23291015625 +92282 -0.209442138671875 +92283 -0.174163818359375 +92284 -0.126739501953125 +92285 -0.048126220703125 +92286 0.0426025390625 +92287 0.10748291015625 +92288 0.1409912109375 +92289 0.19708251953125 +92290 0.273651123046875 +92291 0.31768798828125 +92292 0.341094970703125 +92293 0.368011474609375 +92294 0.37249755859375 +92295 0.30072021484375 +92296 0.1517333984375 +92297 -0.01470947265625 +92298 -0.1883544921875 +92299 -0.372711181640625 +92300 -0.51397705078125 +92301 -0.57177734375 +92302 -0.53948974609375 +92303 -0.43511962890625 +92304 -0.2962646484375 +92305 -0.161102294921875 +92306 -0.0435791015625 +92307 0.060394287109375 +92308 0.13665771484375 +92309 0.170135498046875 +92310 0.16552734375 +92311 0.15728759765625 +92312 0.150787353515625 +92313 0.12200927734375 +92314 0.080108642578125 +92315 0.05126953125 +92316 0.062896728515625 +92317 0.09271240234375 +92318 0.092987060546875 +92319 0.07855224609375 +92320 0.06427001953125 +92321 0.0347900390625 +92322 -0.01171875 +92323 -0.056060791015625 +92324 -0.055511474609375 +92325 -0.010467529296875 +92326 0.02508544921875 +92327 0.025665283203125 +92328 0.017333984375 +92329 0.00189208984375 +92330 -0.03173828125 +92331 -0.071502685546875 +92332 -0.13543701171875 +92333 -0.219970703125 +92334 -0.300506591796875 +92335 -0.376312255859375 +92336 -0.416107177734375 +92337 -0.371124267578125 +92338 -0.242279052734375 +92339 -0.069732666015625 +92340 0.125640869140625 +92341 0.31268310546875 +92342 0.45501708984375 +92343 0.554779052734375 +92344 0.61065673828125 +92345 0.610931396484375 +92346 0.531463623046875 +92347 0.3883056640625 +92348 0.23468017578125 +92349 0.095245361328125 +92350 -0.00396728515625 +92351 -0.04852294921875 +92352 -0.055145263671875 +92353 -0.0758056640625 +92354 -0.138702392578125 +92355 -0.209197998046875 +92356 -0.289031982421875 +92357 -0.37884521484375 +92358 -0.456329345703125 +92359 -0.51641845703125 +92360 -0.519287109375 +92361 -0.458251953125 +92362 -0.384796142578125 +92363 -0.323699951171875 +92364 -0.269287109375 +92365 -0.1951904296875 +92366 -0.100006103515625 +92367 -0.01055908203125 +92368 0.1033935546875 +92369 0.24908447265625 +92370 0.373199462890625 +92371 0.45806884765625 +92372 0.511474609375 +92373 0.565399169921875 +92374 0.61138916015625 +92375 0.5897216796875 +92376 0.4906005859375 +92377 0.33148193359375 +92378 0.147796630859375 +92379 -0.01873779296875 +92380 -0.140289306640625 +92381 -0.191986083984375 +92382 -0.184295654296875 +92383 -0.161834716796875 +92384 -0.166595458984375 +92385 -0.19390869140625 +92386 -0.22442626953125 +92387 -0.279754638671875 +92388 -0.3389892578125 +92389 -0.3543701171875 +92390 -0.348175048828125 +92391 -0.32598876953125 +92392 -0.2581787109375 +92393 -0.139801025390625 +92394 0.014617919921875 +92395 0.144378662109375 +92396 0.221038818359375 +92397 0.27069091796875 +92398 0.294036865234375 +92399 0.311767578125 +92400 0.339141845703125 +92401 0.360260009765625 +92402 0.360504150390625 +92403 0.308380126953125 +92404 0.18170166015625 +92405 0.0047607421875 +92406 -0.17559814453125 +92407 -0.3143310546875 +92408 -0.36785888671875 +92409 -0.36248779296875 +92410 -0.343536376953125 +92411 -0.3018798828125 +92412 -0.231414794921875 +92413 -0.117645263671875 +92414 0.007049560546875 +92415 0.087982177734375 +92416 0.13946533203125 +92417 0.17425537109375 +92418 0.188201904296875 +92419 0.171234130859375 +92420 0.118438720703125 +92421 0.05706787109375 +92422 -0.010711669921875 +92423 -0.0914306640625 +92424 -0.162322998046875 +92425 -0.194549560546875 +92426 -0.1492919921875 +92427 -0.02166748046875 +92428 0.124053955078125 +92429 0.211151123046875 +92430 0.240447998046875 +92431 0.242218017578125 +92432 0.2257080078125 +92433 0.194366455078125 +92434 0.115509033203125 +92435 0.0128173828125 +92436 -0.053802490234375 +92437 -0.110626220703125 +92438 -0.199493408203125 +92439 -0.29437255859375 +92440 -0.33221435546875 +92441 -0.27972412109375 +92442 -0.185333251953125 +92443 -0.128204345703125 +92444 -0.115692138671875 +92445 -0.116455078125 +92446 -0.105926513671875 +92447 -0.053955078125 +92448 0.048797607421875 +92449 0.157318115234375 +92450 0.212005615234375 +92451 0.218475341796875 +92452 0.23724365234375 +92453 0.30535888671875 +92454 0.38128662109375 +92455 0.404449462890625 +92456 0.3944091796875 +92457 0.3885498046875 +92458 0.362640380859375 +92459 0.27362060546875 +92460 0.11712646484375 +92461 -0.054901123046875 +92462 -0.19085693359375 +92463 -0.28570556640625 +92464 -0.339263916015625 +92465 -0.3775634765625 +92466 -0.445709228515625 +92467 -0.535064697265625 +92468 -0.629058837890625 +92469 -0.697601318359375 +92470 -0.70391845703125 +92471 -0.6424560546875 +92472 -0.491241455078125 +92473 -0.265716552734375 +92474 -0.023712158203125 +92475 0.201751708984375 +92476 0.375823974609375 +92477 0.485076904296875 +92478 0.56884765625 +92479 0.634765625 +92480 0.63763427734375 +92481 0.5660400390625 +92482 0.4720458984375 +92483 0.40692138671875 +92484 0.3778076171875 +92485 0.376953125 +92486 0.371978759765625 +92487 0.313140869140625 +92488 0.184417724609375 +92489 0.011199951171875 +92490 -0.171051025390625 +92491 -0.33740234375 +92492 -0.47198486328125 +92493 -0.560394287109375 +92494 -0.58056640625 +92495 -0.54754638671875 +92496 -0.508575439453125 +92497 -0.459503173828125 +92498 -0.394378662109375 +92499 -0.35260009765625 +92500 -0.31170654296875 +92501 -0.197418212890625 +92502 -0.007965087890625 +92503 0.207489013671875 +92504 0.409210205078125 +92505 0.57208251953125 +92506 0.66595458984375 +92507 0.65875244140625 +92508 0.56744384765625 +92509 0.431396484375 +92510 0.29443359375 +92511 0.182464599609375 +92512 0.06365966796875 +92513 -0.075958251953125 +92514 -0.189422607421875 +92515 -0.271942138671875 +92516 -0.342529296875 +92517 -0.364166259765625 +92518 -0.327239990234375 +92519 -0.2769775390625 +92520 -0.253692626953125 +92521 -0.24365234375 +92522 -0.1983642578125 +92523 -0.116241455078125 +92524 -0.036834716796875 +92525 0.034881591796875 +92526 0.09124755859375 +92527 0.10888671875 +92528 0.125518798828125 +92529 0.15771484375 +92530 0.17828369140625 +92531 0.17108154296875 +92532 0.129974365234375 +92533 0.082427978515625 +92534 0.027679443359375 +92535 -0.065643310546875 +92536 -0.15936279296875 +92537 -0.21307373046875 +92538 -0.234649658203125 +92539 -0.2001953125 +92540 -0.119171142578125 +92541 -0.024749755859375 +92542 0.085784912109375 +92543 0.178131103515625 +92544 0.215576171875 +92545 0.211456298828125 +92546 0.17523193359375 +92547 0.128753662109375 +92548 0.1019287109375 +92549 0.0743408203125 +92550 0.04327392578125 +92551 0.038177490234375 +92552 0.076263427734375 +92553 0.14105224609375 +92554 0.186431884765625 +92555 0.188812255859375 +92556 0.1390380859375 +92557 0.041778564453125 +92558 -0.079437255859375 +92559 -0.219390869140625 +92560 -0.367828369140625 +92561 -0.494873046875 +92562 -0.556243896484375 +92563 -0.508697509765625 +92564 -0.3756103515625 +92565 -0.218902587890625 +92566 -0.063751220703125 +92567 0.091552734375 +92568 0.23602294921875 +92569 0.342987060546875 +92570 0.39520263671875 +92571 0.389373779296875 +92572 0.324249267578125 +92573 0.224090576171875 +92574 0.124267578125 +92575 0.037078857421875 +92576 -0.010101318359375 +92577 -0.019439697265625 +92578 -0.022796630859375 +92579 -0.001556396484375 +92580 0.056304931640625 +92581 0.106719970703125 +92582 0.096893310546875 +92583 0.042694091796875 +92584 -0.018035888671875 +92585 -0.07586669921875 +92586 -0.11944580078125 +92587 -0.15972900390625 +92588 -0.202606201171875 +92589 -0.24859619140625 +92590 -0.30517578125 +92591 -0.36212158203125 +92592 -0.39141845703125 +92593 -0.35528564453125 +92594 -0.249969482421875 +92595 -0.092864990234375 +92596 0.08905029296875 +92597 0.2352294921875 +92598 0.318817138671875 +92599 0.358642578125 +92600 0.347747802734375 +92601 0.28564453125 +92602 0.223175048828125 +92603 0.196746826171875 +92604 0.179840087890625 +92605 0.155548095703125 +92606 0.151214599609375 +92607 0.156951904296875 +92608 0.13177490234375 +92609 0.100799560546875 +92610 0.087127685546875 +92611 0.05487060546875 +92612 -0.009002685546875 +92613 -0.10400390625 +92614 -0.229400634765625 +92615 -0.35552978515625 +92616 -0.441925048828125 +92617 -0.473846435546875 +92618 -0.464813232421875 +92619 -0.419097900390625 +92620 -0.334320068359375 +92621 -0.227935791015625 +92622 -0.12347412109375 +92623 -0.02764892578125 +92624 0.077667236328125 +92625 0.2132568359375 +92626 0.38885498046875 +92627 0.582794189453125 +92628 0.734039306640625 +92629 0.800140380859375 +92630 0.7783203125 +92631 0.6651611328125 +92632 0.45965576171875 +92633 0.199188232421875 +92634 -0.050689697265625 +92635 -0.23297119140625 +92636 -0.33013916015625 +92637 -0.368408203125 +92638 -0.378936767578125 +92639 -0.376983642578125 +92640 -0.37969970703125 +92641 -0.391510009765625 +92642 -0.385345458984375 +92643 -0.3419189453125 +92644 -0.28289794921875 +92645 -0.251617431640625 +92646 -0.266143798828125 +92647 -0.273345947265625 +92648 -0.216796875 +92649 -0.128265380859375 +92650 -0.068145751953125 +92651 -0.0430908203125 +92652 -0.024444580078125 +92653 0.020721435546875 +92654 0.124481201171875 +92655 0.25787353515625 +92656 0.379119873046875 +92657 0.47991943359375 +92658 0.5281982421875 +92659 0.511138916015625 +92660 0.456207275390625 +92661 0.407470703125 +92662 0.383758544921875 +92663 0.35687255859375 +92664 0.31182861328125 +92665 0.250885009765625 +92666 0.1654052734375 +92667 0.035247802734375 +92668 -0.142059326171875 +92669 -0.33563232421875 +92670 -0.5345458984375 +92671 -0.72186279296875 +92672 -0.836669921875 +92673 -0.8326416015625 +92674 -0.7296142578125 +92675 -0.582550048828125 +92676 -0.440093994140625 +92677 -0.324310302734375 +92678 -0.20147705078125 +92679 -0.044647216796875 +92680 0.103973388671875 +92681 0.202392578125 +92682 0.264495849609375 +92683 0.338897705078125 +92684 0.443817138671875 +92685 0.545074462890625 +92686 0.6173095703125 +92687 0.6524658203125 +92688 0.66339111328125 +92689 0.6561279296875 +92690 0.606781005859375 +92691 0.501190185546875 +92692 0.352783203125 +92693 0.176544189453125 +92694 -0.034820556640625 +92695 -0.258209228515625 +92696 -0.44244384765625 +92697 -0.5753173828125 +92698 -0.65203857421875 +92699 -0.641632080078125 +92700 -0.562164306640625 +92701 -0.458038330078125 +92702 -0.350555419921875 +92703 -0.260528564453125 +92704 -0.192108154296875 +92705 -0.141937255859375 +92706 -0.1021728515625 +92707 -0.062896728515625 +92708 -0.011932373046875 +92709 0.062835693359375 +92710 0.148712158203125 +92711 0.241729736328125 +92712 0.34912109375 +92713 0.457305908203125 +92714 0.54388427734375 +92715 0.5728759765625 +92716 0.506591796875 +92717 0.351226806640625 +92718 0.146514892578125 +92719 -0.05523681640625 +92720 -0.21624755859375 +92721 -0.334930419921875 +92722 -0.402984619140625 +92723 -0.4412841796875 +92724 -0.49578857421875 +92725 -0.5601806640625 +92726 -0.600738525390625 +92727 -0.584228515625 +92728 -0.47930908203125 +92729 -0.27935791015625 +92730 -0.0089111328125 +92731 0.268798828125 +92732 0.482818603515625 +92733 0.60369873046875 +92734 0.650421142578125 +92735 0.66400146484375 +92736 0.6414794921875 +92737 0.572540283203125 +92738 0.498138427734375 +92739 0.439453125 +92740 0.375518798828125 +92741 0.274505615234375 +92742 0.1087646484375 +92743 -0.099395751953125 +92744 -0.3182373046875 +92745 -0.5489501953125 +92746 -0.7738037109375 +92747 -0.86383056640625 +92748 -0.870391845703125 +92749 -0.86895751953125 +92750 -0.861053466796875 +92751 -0.765869140625 +92752 -0.5301513671875 +92753 -0.214691162109375 +92754 0.137359619140625 +92755 0.474822998046875 +92756 0.76239013671875 +92757 0.867462158203125 +92758 0.870361328125 +92759 0.86480712890625 +92760 0.831817626953125 +92761 0.677581787109375 +92762 0.495880126953125 +92763 0.30767822265625 +92764 0.116180419921875 +92765 -0.110748291015625 +92766 -0.381805419921875 +92767 -0.6572265625 +92768 -0.857421875 +92769 -0.870391845703125 +92770 -0.870391845703125 +92771 -0.86444091796875 +92772 -0.85723876953125 +92773 -0.790008544921875 +92774 -0.62847900390625 +92775 -0.3956298828125 +92776 -0.126708984375 +92777 0.150115966796875 +92778 0.424041748046875 +92779 0.670623779296875 +92780 0.854522705078125 +92781 0.866485595703125 +92782 0.86920166015625 +92783 0.8653564453125 +92784 0.857147216796875 +92785 0.766845703125 +92786 0.628509521484375 +92787 0.462127685546875 +92788 0.297210693359375 +92789 0.14862060546875 +92790 -0.00537109375 +92791 -0.15753173828125 +92792 -0.31304931640625 +92793 -0.48876953125 +92794 -0.6416015625 +92795 -0.751373291015625 +92796 -0.84619140625 +92797 -0.861297607421875 +92798 -0.863250732421875 +92799 -0.856597900390625 +92800 -0.7498779296875 +92801 -0.624542236328125 +92802 -0.47808837890625 +92803 -0.253387451171875 +92804 0.003692626953125 +92805 0.2257080078125 +92806 0.427154541015625 +92807 0.643218994140625 +92808 0.855926513671875 +92809 0.870361328125 +92810 0.870361328125 +92811 0.862762451171875 +92812 0.79669189453125 +92813 0.595794677734375 +92814 0.362152099609375 +92815 0.1270751953125 +92816 -0.086944580078125 +92817 -0.2784423828125 +92818 -0.484832763671875 +92819 -0.729583740234375 +92820 -0.86688232421875 +92821 -0.870391845703125 +92822 -0.86859130859375 +92823 -0.86279296875 +92824 -0.817962646484375 +92825 -0.6116943359375 +92826 -0.3128662109375 +92827 0.039398193359375 +92828 0.422821044921875 +92829 0.805145263671875 +92830 0.870361328125 +92831 0.870361328125 +92832 0.860015869140625 +92833 0.727935791015625 +92834 0.48114013671875 +92835 0.2059326171875 +92836 -0.06103515625 +92837 -0.29913330078125 +92838 -0.516204833984375 +92839 -0.7252197265625 +92840 -0.85980224609375 +92841 -0.870391845703125 +92842 -0.870391845703125 +92843 -0.858062744140625 +92844 -0.673004150390625 +92845 -0.42694091796875 +92846 -0.2100830078125 +92847 -0.0362548828125 +92848 0.10943603515625 +92849 0.23516845703125 +92850 0.373687744140625 +92851 0.517791748046875 +92852 0.602783203125 +92853 0.635711669921875 +92854 0.655181884765625 +92855 0.65948486328125 +92856 0.651275634765625 +92857 0.61846923828125 +92858 0.53753662109375 +92859 0.404144287109375 +92860 0.22186279296875 +92861 0.003997802734375 +92862 -0.22100830078125 +92863 -0.42449951171875 +92864 -0.579833984375 +92865 -0.641876220703125 +92866 -0.6177978515625 +92867 -0.575531005859375 +92868 -0.526336669921875 +92869 -0.42645263671875 +92870 -0.2581787109375 +92871 -0.068695068359375 +92872 0.09222412109375 +92873 0.232147216796875 +92874 0.3509521484375 +92875 0.410064697265625 +92876 0.372955322265625 +92877 0.2554931640625 +92878 0.10711669921875 +92879 -0.052886962890625 +92880 -0.186279296875 +92881 -0.23291015625 +92882 -0.209442138671875 +92883 -0.174163818359375 +92884 -0.126739501953125 +92885 -0.048126220703125 +92886 0.0426025390625 +92887 0.10748291015625 +92888 0.1409912109375 +92889 0.19708251953125 +92890 0.273651123046875 +92891 0.31768798828125 +92892 0.341094970703125 +92893 0.368011474609375 +92894 0.37249755859375 +92895 0.30072021484375 +92896 0.1517333984375 +92897 -0.01470947265625 +92898 -0.1883544921875 +92899 -0.372711181640625 +92900 -0.51397705078125 +92901 -0.57177734375 +92902 -0.53948974609375 +92903 -0.43511962890625 +92904 -0.2962646484375 +92905 -0.161102294921875 +92906 -0.0435791015625 +92907 0.060394287109375 +92908 0.13665771484375 +92909 0.170135498046875 +92910 0.16552734375 +92911 0.15728759765625 +92912 0.150787353515625 +92913 0.12200927734375 +92914 0.080108642578125 +92915 0.05126953125 +92916 0.062896728515625 +92917 0.09271240234375 +92918 0.092987060546875 +92919 0.07855224609375 +92920 0.06427001953125 +92921 0.0347900390625 +92922 -0.01171875 +92923 -0.056060791015625 +92924 -0.055511474609375 +92925 -0.010467529296875 +92926 0.02508544921875 +92927 0.025665283203125 +92928 0.017333984375 +92929 0.00189208984375 +92930 -0.03173828125 +92931 -0.071502685546875 +92932 -0.13543701171875 +92933 -0.219970703125 +92934 -0.300506591796875 +92935 -0.376312255859375 +92936 -0.416107177734375 +92937 -0.371124267578125 +92938 -0.242279052734375 +92939 -0.069732666015625 +92940 0.125640869140625 +92941 0.31268310546875 +92942 0.45501708984375 +92943 0.554779052734375 +92944 0.61065673828125 +92945 0.610931396484375 +92946 0.531463623046875 +92947 0.3883056640625 +92948 0.23468017578125 +92949 0.095245361328125 +92950 -0.00396728515625 +92951 -0.04852294921875 +92952 -0.055145263671875 +92953 -0.0758056640625 +92954 -0.138702392578125 +92955 -0.209197998046875 +92956 -0.289031982421875 +92957 -0.37884521484375 +92958 -0.456329345703125 +92959 -0.51641845703125 +92960 -0.519287109375 +92961 -0.458251953125 +92962 -0.384796142578125 +92963 -0.323699951171875 +92964 -0.269287109375 +92965 -0.1951904296875 +92966 -0.100006103515625 +92967 -0.01055908203125 +92968 0.1033935546875 +92969 0.24908447265625 +92970 0.373199462890625 +92971 0.45806884765625 +92972 0.511474609375 +92973 0.565399169921875 +92974 0.61138916015625 +92975 0.5897216796875 +92976 0.4906005859375 +92977 0.33148193359375 +92978 0.147796630859375 +92979 -0.01873779296875 +92980 -0.140289306640625 +92981 -0.191986083984375 +92982 -0.184295654296875 +92983 -0.161834716796875 +92984 -0.166595458984375 +92985 -0.19390869140625 +92986 -0.22442626953125 +92987 -0.279754638671875 +92988 -0.3389892578125 +92989 -0.3543701171875 +92990 -0.348175048828125 +92991 -0.32598876953125 +92992 -0.2581787109375 +92993 -0.139801025390625 +92994 0.014617919921875 +92995 0.144378662109375 +92996 0.221038818359375 +92997 0.27069091796875 +92998 0.294036865234375 +92999 0.311767578125 +93000 0.339141845703125 +93001 0.360260009765625 +93002 0.360504150390625 +93003 0.308380126953125 +93004 0.18170166015625 +93005 0.0047607421875 +93006 -0.17559814453125 +93007 -0.3143310546875 +93008 -0.36785888671875 +93009 -0.36248779296875 +93010 -0.343536376953125 +93011 -0.3018798828125 +93012 -0.231414794921875 +93013 -0.117645263671875 +93014 0.007049560546875 +93015 0.087982177734375 +93016 0.13946533203125 +93017 0.17425537109375 +93018 0.188201904296875 +93019 0.171234130859375 +93020 0.118438720703125 +93021 0.05706787109375 +93022 -0.010711669921875 +93023 -0.0914306640625 +93024 -0.162322998046875 +93025 -0.194549560546875 +93026 -0.1492919921875 +93027 -0.02166748046875 +93028 0.124053955078125 +93029 0.211151123046875 +93030 0.240447998046875 +93031 0.242218017578125 +93032 0.2257080078125 +93033 0.194366455078125 +93034 0.115509033203125 +93035 0.0128173828125 +93036 -0.053802490234375 +93037 -0.110626220703125 +93038 -0.199493408203125 +93039 -0.29437255859375 +93040 -0.33221435546875 +93041 -0.27972412109375 +93042 -0.185333251953125 +93043 -0.128204345703125 +93044 -0.115692138671875 +93045 -0.116455078125 +93046 -0.105926513671875 +93047 -0.053955078125 +93048 0.048797607421875 +93049 0.157318115234375 +93050 0.212005615234375 +93051 0.218475341796875 +93052 0.23724365234375 +93053 0.30535888671875 +93054 0.38128662109375 +93055 0.404449462890625 +93056 0.3944091796875 +93057 0.3885498046875 +93058 0.362640380859375 +93059 0.27362060546875 +93060 0.11712646484375 +93061 -0.054901123046875 +93062 -0.19085693359375 +93063 -0.28570556640625 +93064 -0.339263916015625 +93065 -0.3775634765625 +93066 -0.445709228515625 +93067 -0.535064697265625 +93068 -0.629058837890625 +93069 -0.697601318359375 +93070 -0.70391845703125 +93071 -0.6424560546875 +93072 -0.491241455078125 +93073 -0.265716552734375 +93074 -0.023712158203125 +93075 0.201751708984375 +93076 0.375823974609375 +93077 0.485076904296875 +93078 0.56884765625 +93079 0.634765625 +93080 0.63763427734375 +93081 0.5660400390625 +93082 0.4720458984375 +93083 0.40692138671875 +93084 0.3778076171875 +93085 0.376953125 +93086 0.371978759765625 +93087 0.313140869140625 +93088 0.184417724609375 +93089 0.011199951171875 +93090 -0.171051025390625 +93091 -0.33740234375 +93092 -0.47198486328125 +93093 -0.560394287109375 +93094 -0.58056640625 +93095 -0.54754638671875 +93096 -0.508575439453125 +93097 -0.459503173828125 +93098 -0.394378662109375 +93099 -0.35260009765625 +93100 -0.31170654296875 +93101 -0.197418212890625 +93102 -0.007965087890625 +93103 0.207489013671875 +93104 0.409210205078125 +93105 0.57208251953125 +93106 0.66595458984375 +93107 0.65875244140625 +93108 0.56744384765625 +93109 0.431396484375 +93110 0.29443359375 +93111 0.182464599609375 +93112 0.06365966796875 +93113 -0.075958251953125 +93114 -0.189422607421875 +93115 -0.271942138671875 +93116 -0.342529296875 +93117 -0.364166259765625 +93118 -0.327239990234375 +93119 -0.2769775390625 +93120 -0.253692626953125 +93121 -0.24365234375 +93122 -0.1983642578125 +93123 -0.116241455078125 +93124 -0.036834716796875 +93125 0.034881591796875 +93126 0.09124755859375 +93127 0.10888671875 +93128 0.125518798828125 +93129 0.15771484375 +93130 0.17828369140625 +93131 0.17108154296875 +93132 0.129974365234375 +93133 0.082427978515625 +93134 0.027679443359375 +93135 -0.065643310546875 +93136 -0.15936279296875 +93137 -0.21307373046875 +93138 -0.234649658203125 +93139 -0.2001953125 +93140 -0.119171142578125 +93141 -0.024749755859375 +93142 0.085784912109375 +93143 0.178131103515625 +93144 0.215576171875 +93145 0.211456298828125 +93146 0.17523193359375 +93147 0.128753662109375 +93148 0.1019287109375 +93149 0.0743408203125 +93150 0.04327392578125 +93151 0.038177490234375 +93152 0.076263427734375 +93153 0.14105224609375 +93154 0.186431884765625 +93155 0.188812255859375 +93156 0.1390380859375 +93157 0.041778564453125 +93158 -0.079437255859375 +93159 -0.219390869140625 +93160 -0.367828369140625 +93161 -0.494873046875 +93162 -0.556243896484375 +93163 -0.508697509765625 +93164 -0.3756103515625 +93165 -0.218902587890625 +93166 -0.063751220703125 +93167 0.091552734375 +93168 0.23602294921875 +93169 0.342987060546875 +93170 0.39520263671875 +93171 0.389373779296875 +93172 0.324249267578125 +93173 0.224090576171875 +93174 0.124267578125 +93175 0.037078857421875 +93176 -0.010101318359375 +93177 -0.019439697265625 +93178 -0.022796630859375 +93179 -0.001556396484375 +93180 0.056304931640625 +93181 0.106719970703125 +93182 0.096893310546875 +93183 0.042694091796875 +93184 -0.018035888671875 +93185 -0.07586669921875 +93186 -0.11944580078125 +93187 -0.15972900390625 +93188 -0.202606201171875 +93189 -0.24859619140625 +93190 -0.30517578125 +93191 -0.36212158203125 +93192 -0.39141845703125 +93193 -0.35528564453125 +93194 -0.249969482421875 +93195 -0.092864990234375 +93196 0.08905029296875 +93197 0.2352294921875 +93198 0.318817138671875 +93199 0.358642578125 +93200 0.347747802734375 +93201 0.28564453125 +93202 0.223175048828125 +93203 0.196746826171875 +93204 0.179840087890625 +93205 0.155548095703125 +93206 0.151214599609375 +93207 0.156951904296875 +93208 0.13177490234375 +93209 0.100799560546875 +93210 0.087127685546875 +93211 0.05487060546875 +93212 -0.009002685546875 +93213 -0.10400390625 +93214 -0.229400634765625 +93215 -0.35552978515625 +93216 -0.441925048828125 +93217 -0.473846435546875 +93218 -0.464813232421875 +93219 -0.419097900390625 +93220 -0.334320068359375 +93221 -0.227935791015625 +93222 -0.12347412109375 +93223 -0.02764892578125 +93224 0.077667236328125 +93225 0.2132568359375 +93226 0.38885498046875 +93227 0.582794189453125 +93228 0.734039306640625 +93229 0.800140380859375 +93230 0.7783203125 +93231 0.6651611328125 +93232 0.45965576171875 +93233 0.199188232421875 +93234 -0.050689697265625 +93235 -0.23297119140625 +93236 -0.33013916015625 +93237 -0.368408203125 +93238 -0.378936767578125 +93239 -0.376983642578125 +93240 -0.37969970703125 +93241 -0.391510009765625 +93242 -0.385345458984375 +93243 -0.3419189453125 +93244 -0.28289794921875 +93245 -0.251617431640625 +93246 -0.266143798828125 +93247 -0.273345947265625 +93248 -0.216796875 +93249 -0.128265380859375 +93250 -0.068145751953125 +93251 -0.0430908203125 +93252 -0.024444580078125 +93253 0.020721435546875 +93254 0.124481201171875 +93255 0.25787353515625 +93256 0.379119873046875 +93257 0.47991943359375 +93258 0.5281982421875 +93259 0.511138916015625 +93260 0.456207275390625 +93261 0.407470703125 +93262 0.383758544921875 +93263 0.35687255859375 +93264 0.31182861328125 +93265 0.250885009765625 +93266 0.1654052734375 +93267 0.035247802734375 +93268 -0.142059326171875 +93269 -0.33563232421875 +93270 -0.5345458984375 +93271 -0.72186279296875 +93272 -0.836669921875 +93273 -0.8326416015625 +93274 -0.7296142578125 +93275 -0.582550048828125 +93276 -0.440093994140625 +93277 -0.324310302734375 +93278 -0.20147705078125 +93279 -0.044647216796875 +93280 0.103973388671875 +93281 0.202392578125 +93282 0.264495849609375 +93283 0.338897705078125 +93284 0.443817138671875 +93285 0.545074462890625 +93286 0.6173095703125 +93287 0.6524658203125 +93288 0.66339111328125 +93289 0.6561279296875 +93290 0.606781005859375 +93291 0.501190185546875 +93292 0.352783203125 +93293 0.176544189453125 +93294 -0.034820556640625 +93295 -0.258209228515625 +93296 -0.44244384765625 +93297 -0.5753173828125 +93298 -0.65203857421875 +93299 -0.641632080078125 +93300 -0.562164306640625 +93301 -0.458038330078125 +93302 -0.350555419921875 +93303 -0.260528564453125 +93304 -0.192108154296875 +93305 -0.141937255859375 +93306 -0.1021728515625 +93307 -0.062896728515625 +93308 -0.011932373046875 +93309 0.062835693359375 +93310 0.148712158203125 +93311 0.241729736328125 +93312 0.34912109375 +93313 0.457305908203125 +93314 0.54388427734375 +93315 0.5728759765625 +93316 0.506591796875 +93317 0.351226806640625 +93318 0.146514892578125 +93319 -0.05523681640625 +93320 -0.21624755859375 +93321 -0.334930419921875 +93322 -0.402984619140625 +93323 -0.4412841796875 +93324 -0.49578857421875 +93325 -0.5601806640625 +93326 -0.600738525390625 +93327 -0.584228515625 +93328 -0.47930908203125 +93329 -0.27935791015625 +93330 -0.0089111328125 +93331 0.268798828125 +93332 0.482818603515625 +93333 0.60369873046875 +93334 0.650421142578125 +93335 0.66400146484375 +93336 0.6414794921875 +93337 0.572540283203125 +93338 0.498138427734375 +93339 0.439453125 +93340 0.375518798828125 +93341 0.274505615234375 +93342 0.1087646484375 +93343 -0.099395751953125 +93344 -0.3182373046875 +93345 -0.5489501953125 +93346 -0.7738037109375 +93347 -0.86383056640625 +93348 -0.870391845703125 +93349 -0.86895751953125 +93350 -0.861053466796875 +93351 -0.765869140625 +93352 -0.5301513671875 +93353 -0.214691162109375 +93354 0.137359619140625 +93355 0.474822998046875 +93356 0.76239013671875 +93357 0.867462158203125 +93358 0.870361328125 +93359 0.86480712890625 +93360 0.831817626953125 +93361 0.677581787109375 +93362 0.495880126953125 +93363 0.30767822265625 +93364 0.116180419921875 +93365 -0.110748291015625 +93366 -0.381805419921875 +93367 -0.6572265625 +93368 -0.857421875 +93369 -0.870391845703125 +93370 -0.870391845703125 +93371 -0.86444091796875 +93372 -0.85723876953125 +93373 -0.790008544921875 +93374 -0.62847900390625 +93375 -0.3956298828125 +93376 -0.126708984375 +93377 0.150115966796875 +93378 0.424041748046875 +93379 0.670623779296875 +93380 0.854522705078125 +93381 0.866485595703125 +93382 0.86920166015625 +93383 0.8653564453125 +93384 0.857147216796875 +93385 0.766845703125 +93386 0.628509521484375 +93387 0.462127685546875 +93388 0.297210693359375 +93389 0.14862060546875 +93390 -0.00537109375 +93391 -0.15753173828125 +93392 -0.31304931640625 +93393 -0.48876953125 +93394 -0.6416015625 +93395 -0.751373291015625 +93396 -0.84619140625 +93397 -0.861297607421875 +93398 -0.863250732421875 +93399 -0.856597900390625 +93400 -0.7498779296875 +93401 -0.624542236328125 +93402 -0.47808837890625 +93403 -0.253387451171875 +93404 0.003692626953125 +93405 0.2257080078125 +93406 0.427154541015625 +93407 0.643218994140625 +93408 0.855926513671875 +93409 0.870361328125 +93410 0.870361328125 +93411 0.862762451171875 +93412 0.79669189453125 +93413 0.595794677734375 +93414 0.362152099609375 +93415 0.1270751953125 +93416 -0.086944580078125 +93417 -0.2784423828125 +93418 -0.484832763671875 +93419 -0.729583740234375 +93420 -0.86688232421875 +93421 -0.870391845703125 +93422 -0.86859130859375 +93423 -0.86279296875 +93424 -0.817962646484375 +93425 -0.6116943359375 +93426 -0.3128662109375 +93427 0.039398193359375 +93428 0.422821044921875 +93429 0.805145263671875 +93430 0.870361328125 +93431 0.870361328125 +93432 0.860015869140625 +93433 0.727935791015625 +93434 0.48114013671875 +93435 0.2059326171875 +93436 -0.06103515625 +93437 -0.29913330078125 +93438 -0.516204833984375 +93439 -0.7252197265625 +93440 -0.85980224609375 +93441 -0.870391845703125 +93442 -0.870391845703125 +93443 -0.858062744140625 +93444 -0.673004150390625 +93445 -0.42694091796875 +93446 -0.2100830078125 +93447 -0.0362548828125 +93448 0.10943603515625 +93449 0.23516845703125 +93450 0.373687744140625 +93451 0.517791748046875 +93452 0.602783203125 +93453 0.635711669921875 +93454 0.655181884765625 +93455 0.65948486328125 +93456 0.651275634765625 +93457 0.61846923828125 +93458 0.53753662109375 +93459 0.404144287109375 +93460 0.22186279296875 +93461 0.003997802734375 +93462 -0.22100830078125 +93463 -0.42449951171875 +93464 -0.579833984375 +93465 -0.641876220703125 +93466 -0.6177978515625 +93467 -0.575531005859375 +93468 -0.526336669921875 +93469 -0.42645263671875 +93470 -0.2581787109375 +93471 -0.068695068359375 +93472 0.09222412109375 +93473 0.232147216796875 +93474 0.3509521484375 +93475 0.410064697265625 +93476 0.372955322265625 +93477 0.2554931640625 +93478 0.10711669921875 +93479 -0.052886962890625 +93480 -0.186279296875 +93481 -0.23291015625 +93482 -0.209442138671875 +93483 -0.174163818359375 +93484 -0.126739501953125 +93485 -0.048126220703125 +93486 0.0426025390625 +93487 0.10748291015625 +93488 0.1409912109375 +93489 0.19708251953125 +93490 0.273651123046875 +93491 0.31768798828125 +93492 0.341094970703125 +93493 0.368011474609375 +93494 0.37249755859375 +93495 0.30072021484375 +93496 0.1517333984375 +93497 -0.01470947265625 +93498 -0.1883544921875 +93499 -0.372711181640625 +93500 -0.51397705078125 +93501 -0.57177734375 +93502 -0.53948974609375 +93503 -0.43511962890625 +93504 -0.2962646484375 +93505 -0.161102294921875 +93506 -0.0435791015625 +93507 0.060394287109375 +93508 0.13665771484375 +93509 0.170135498046875 +93510 0.16552734375 +93511 0.15728759765625 +93512 0.150787353515625 +93513 0.12200927734375 +93514 0.080108642578125 +93515 0.05126953125 +93516 0.062896728515625 +93517 0.09271240234375 +93518 0.092987060546875 +93519 0.07855224609375 +93520 0.06427001953125 +93521 0.0347900390625 +93522 -0.01171875 +93523 -0.056060791015625 +93524 -0.055511474609375 +93525 -0.010467529296875 +93526 0.02508544921875 +93527 0.025665283203125 +93528 0.017333984375 +93529 0.00189208984375 +93530 -0.03173828125 +93531 -0.071502685546875 +93532 -0.13543701171875 +93533 -0.219970703125 +93534 -0.300506591796875 +93535 -0.376312255859375 +93536 -0.416107177734375 +93537 -0.371124267578125 +93538 -0.242279052734375 +93539 -0.069732666015625 +93540 0.125640869140625 +93541 0.31268310546875 +93542 0.45501708984375 +93543 0.554779052734375 +93544 0.61065673828125 +93545 0.610931396484375 +93546 0.531463623046875 +93547 0.3883056640625 +93548 0.23468017578125 +93549 0.095245361328125 +93550 -0.00396728515625 +93551 -0.04852294921875 +93552 -0.055145263671875 +93553 -0.0758056640625 +93554 -0.138702392578125 +93555 -0.209197998046875 +93556 -0.289031982421875 +93557 -0.37884521484375 +93558 -0.456329345703125 +93559 -0.51641845703125 +93560 -0.519287109375 +93561 -0.458251953125 +93562 -0.384796142578125 +93563 -0.323699951171875 +93564 -0.269287109375 +93565 -0.1951904296875 +93566 -0.100006103515625 +93567 -0.01055908203125 +93568 0.1033935546875 +93569 0.24908447265625 +93570 0.373199462890625 +93571 0.45806884765625 +93572 0.511474609375 +93573 0.565399169921875 +93574 0.61138916015625 +93575 0.5897216796875 +93576 0.4906005859375 +93577 0.33148193359375 +93578 0.147796630859375 +93579 -0.01873779296875 +93580 -0.140289306640625 +93581 -0.191986083984375 +93582 -0.184295654296875 +93583 -0.161834716796875 +93584 -0.166595458984375 +93585 -0.19390869140625 +93586 -0.22442626953125 +93587 -0.279754638671875 +93588 -0.3389892578125 +93589 -0.3543701171875 +93590 -0.348175048828125 +93591 -0.32598876953125 +93592 -0.2581787109375 +93593 -0.139801025390625 +93594 0.014617919921875 +93595 0.144378662109375 +93596 0.221038818359375 +93597 0.27069091796875 +93598 0.294036865234375 +93599 0.311767578125 +93600 0.339141845703125 +93601 0.360260009765625 +93602 0.360504150390625 +93603 0.308380126953125 +93604 0.18170166015625 +93605 0.0047607421875 +93606 -0.17559814453125 +93607 -0.3143310546875 +93608 -0.36785888671875 +93609 -0.36248779296875 +93610 -0.343536376953125 +93611 -0.3018798828125 +93612 -0.231414794921875 +93613 -0.117645263671875 +93614 0.007049560546875 +93615 0.087982177734375 +93616 0.13946533203125 +93617 0.17425537109375 +93618 0.188201904296875 +93619 0.171234130859375 +93620 0.118438720703125 +93621 0.05706787109375 +93622 -0.010711669921875 +93623 -0.0914306640625 +93624 -0.162322998046875 +93625 -0.194549560546875 +93626 -0.1492919921875 +93627 -0.02166748046875 +93628 0.124053955078125 +93629 0.211151123046875 +93630 0.240447998046875 +93631 0.242218017578125 +93632 0.2257080078125 +93633 0.194366455078125 +93634 0.115509033203125 +93635 0.0128173828125 +93636 -0.053802490234375 +93637 -0.110626220703125 +93638 -0.199493408203125 +93639 -0.29437255859375 +93640 -0.33221435546875 +93641 -0.27972412109375 +93642 -0.185333251953125 +93643 -0.128204345703125 +93644 -0.115692138671875 +93645 -0.116455078125 +93646 -0.105926513671875 +93647 -0.053955078125 +93648 0.048797607421875 +93649 0.157318115234375 +93650 0.212005615234375 +93651 0.218475341796875 +93652 0.23724365234375 +93653 0.30535888671875 +93654 0.38128662109375 +93655 0.404449462890625 +93656 0.3944091796875 +93657 0.3885498046875 +93658 0.362640380859375 +93659 0.27362060546875 +93660 0.11712646484375 +93661 -0.054901123046875 +93662 -0.19085693359375 +93663 -0.28570556640625 +93664 -0.339263916015625 +93665 -0.3775634765625 +93666 -0.445709228515625 +93667 -0.535064697265625 +93668 -0.629058837890625 +93669 -0.697601318359375 +93670 -0.70391845703125 +93671 -0.6424560546875 +93672 -0.491241455078125 +93673 -0.265716552734375 +93674 -0.023712158203125 +93675 0.201751708984375 +93676 0.375823974609375 +93677 0.485076904296875 +93678 0.56884765625 +93679 0.634765625 +93680 0.63763427734375 +93681 0.5660400390625 +93682 0.4720458984375 +93683 0.40692138671875 +93684 0.3778076171875 +93685 0.376953125 +93686 0.371978759765625 +93687 0.313140869140625 +93688 0.184417724609375 +93689 0.011199951171875 +93690 -0.171051025390625 +93691 -0.33740234375 +93692 -0.47198486328125 +93693 -0.560394287109375 +93694 -0.58056640625 +93695 -0.54754638671875 +93696 -0.508575439453125 +93697 -0.459503173828125 +93698 -0.394378662109375 +93699 -0.35260009765625 +93700 -0.31170654296875 +93701 -0.197418212890625 +93702 -0.007965087890625 +93703 0.207489013671875 +93704 0.409210205078125 +93705 0.57208251953125 +93706 0.66595458984375 +93707 0.65875244140625 +93708 0.56744384765625 +93709 0.431396484375 +93710 0.29443359375 +93711 0.182464599609375 +93712 0.06365966796875 +93713 -0.075958251953125 +93714 -0.189422607421875 +93715 -0.271942138671875 +93716 -0.342529296875 +93717 -0.364166259765625 +93718 -0.327239990234375 +93719 -0.2769775390625 +93720 -0.253692626953125 +93721 -0.24365234375 +93722 -0.1983642578125 +93723 -0.116241455078125 +93724 -0.036834716796875 +93725 0.034881591796875 +93726 0.09124755859375 +93727 0.10888671875 +93728 0.125518798828125 +93729 0.15771484375 +93730 0.17828369140625 +93731 0.17108154296875 +93732 0.129974365234375 +93733 0.082427978515625 +93734 0.027679443359375 +93735 -0.065643310546875 +93736 -0.15936279296875 +93737 -0.21307373046875 +93738 -0.234649658203125 +93739 -0.2001953125 +93740 -0.119171142578125 +93741 -0.024749755859375 +93742 0.085784912109375 +93743 0.178131103515625 +93744 0.215576171875 +93745 0.211456298828125 +93746 0.17523193359375 +93747 0.128753662109375 +93748 0.1019287109375 +93749 0.0743408203125 +93750 0.04327392578125 +93751 0.038177490234375 +93752 0.076263427734375 +93753 0.14105224609375 +93754 0.186431884765625 +93755 0.188812255859375 +93756 0.1390380859375 +93757 0.041778564453125 +93758 -0.079437255859375 +93759 -0.219390869140625 +93760 -0.367828369140625 +93761 -0.494873046875 +93762 -0.556243896484375 +93763 -0.508697509765625 +93764 -0.3756103515625 +93765 -0.218902587890625 +93766 -0.063751220703125 +93767 0.091552734375 +93768 0.23602294921875 +93769 0.342987060546875 +93770 0.39520263671875 +93771 0.389373779296875 +93772 0.324249267578125 +93773 0.224090576171875 +93774 0.124267578125 +93775 0.037078857421875 +93776 -0.010101318359375 +93777 -0.019439697265625 +93778 -0.022796630859375 +93779 -0.001556396484375 +93780 0.056304931640625 +93781 0.106719970703125 +93782 0.096893310546875 +93783 0.042694091796875 +93784 -0.018035888671875 +93785 -0.07586669921875 +93786 -0.11944580078125 +93787 -0.15972900390625 +93788 -0.202606201171875 +93789 -0.24859619140625 +93790 -0.30517578125 +93791 -0.36212158203125 +93792 -0.39141845703125 +93793 -0.35528564453125 +93794 -0.249969482421875 +93795 -0.092864990234375 +93796 0.08905029296875 +93797 0.2352294921875 +93798 0.318817138671875 +93799 0.358642578125 +93800 0.347747802734375 +93801 0.28564453125 +93802 0.223175048828125 +93803 0.196746826171875 +93804 0.179840087890625 +93805 0.155548095703125 +93806 0.151214599609375 +93807 0.156951904296875 +93808 0.13177490234375 +93809 0.100799560546875 +93810 0.087127685546875 +93811 0.05487060546875 +93812 -0.009002685546875 +93813 -0.10400390625 +93814 -0.229400634765625 +93815 -0.35552978515625 +93816 -0.441925048828125 +93817 -0.473846435546875 +93818 -0.464813232421875 +93819 -0.419097900390625 +93820 -0.334320068359375 +93821 -0.227935791015625 +93822 -0.12347412109375 +93823 -0.02764892578125 +93824 0.077667236328125 +93825 0.2132568359375 +93826 0.38885498046875 +93827 0.582794189453125 +93828 0.734039306640625 +93829 0.800140380859375 +93830 0.7783203125 +93831 0.6651611328125 +93832 0.45965576171875 +93833 0.199188232421875 +93834 -0.050689697265625 +93835 -0.23297119140625 +93836 -0.33013916015625 +93837 -0.368408203125 +93838 -0.378936767578125 +93839 -0.376983642578125 +93840 -0.37969970703125 +93841 -0.391510009765625 +93842 -0.385345458984375 +93843 -0.3419189453125 +93844 -0.28289794921875 +93845 -0.251617431640625 +93846 -0.266143798828125 +93847 -0.273345947265625 +93848 -0.216796875 +93849 -0.128265380859375 +93850 -0.068145751953125 +93851 -0.0430908203125 +93852 -0.024444580078125 +93853 0.020721435546875 +93854 0.124481201171875 +93855 0.25787353515625 +93856 0.379119873046875 +93857 0.47991943359375 +93858 0.5281982421875 +93859 0.511138916015625 +93860 0.456207275390625 +93861 0.407470703125 +93862 0.383758544921875 +93863 0.35687255859375 +93864 0.31182861328125 +93865 0.250885009765625 +93866 0.1654052734375 +93867 0.035247802734375 +93868 -0.142059326171875 +93869 -0.33563232421875 +93870 -0.5345458984375 +93871 -0.72186279296875 +93872 -0.836669921875 +93873 -0.8326416015625 +93874 -0.7296142578125 +93875 -0.582550048828125 +93876 -0.440093994140625 +93877 -0.324310302734375 +93878 -0.20147705078125 +93879 -0.044647216796875 +93880 0.103973388671875 +93881 0.202392578125 +93882 0.264495849609375 +93883 0.338897705078125 +93884 0.443817138671875 +93885 0.545074462890625 +93886 0.6173095703125 +93887 0.6524658203125 +93888 0.66339111328125 +93889 0.6561279296875 +93890 0.606781005859375 +93891 0.501190185546875 +93892 0.352783203125 +93893 0.176544189453125 +93894 -0.034820556640625 +93895 -0.258209228515625 +93896 -0.44244384765625 +93897 -0.5753173828125 +93898 -0.65203857421875 +93899 -0.641632080078125 +93900 -0.562164306640625 +93901 -0.458038330078125 +93902 -0.350555419921875 +93903 -0.260528564453125 +93904 -0.192108154296875 +93905 -0.141937255859375 +93906 -0.1021728515625 +93907 -0.062896728515625 +93908 -0.011932373046875 +93909 0.062835693359375 +93910 0.148712158203125 +93911 0.241729736328125 +93912 0.34912109375 +93913 0.457305908203125 +93914 0.54388427734375 +93915 0.5728759765625 +93916 0.506591796875 +93917 0.351226806640625 +93918 0.146514892578125 +93919 -0.05523681640625 +93920 -0.21624755859375 +93921 -0.334930419921875 +93922 -0.402984619140625 +93923 -0.4412841796875 +93924 -0.49578857421875 +93925 -0.5601806640625 +93926 -0.600738525390625 +93927 -0.584228515625 +93928 -0.47930908203125 +93929 -0.27935791015625 +93930 -0.0089111328125 +93931 0.268798828125 +93932 0.482818603515625 +93933 0.60369873046875 +93934 0.650421142578125 +93935 0.66400146484375 +93936 0.6414794921875 +93937 0.572540283203125 +93938 0.498138427734375 +93939 0.439453125 +93940 0.375518798828125 +93941 0.274505615234375 +93942 0.1087646484375 +93943 -0.099395751953125 +93944 -0.3182373046875 +93945 -0.5489501953125 +93946 -0.7738037109375 +93947 -0.86383056640625 +93948 -0.870391845703125 +93949 -0.86895751953125 +93950 -0.861053466796875 +93951 -0.765869140625 +93952 -0.5301513671875 +93953 -0.214691162109375 +93954 0.137359619140625 +93955 0.474822998046875 +93956 0.76239013671875 +93957 0.867462158203125 +93958 0.870361328125 +93959 0.86480712890625 +93960 0.831817626953125 +93961 0.677581787109375 +93962 0.495880126953125 +93963 0.30767822265625 +93964 0.116180419921875 +93965 -0.110748291015625 +93966 -0.381805419921875 +93967 -0.6572265625 +93968 -0.857421875 +93969 -0.870391845703125 +93970 -0.870391845703125 +93971 -0.86444091796875 +93972 -0.85723876953125 +93973 -0.790008544921875 +93974 -0.62847900390625 +93975 -0.3956298828125 +93976 -0.126708984375 +93977 0.150115966796875 +93978 0.424041748046875 +93979 0.670623779296875 +93980 0.854522705078125 +93981 0.866485595703125 +93982 0.86920166015625 +93983 0.8653564453125 +93984 0.857147216796875 +93985 0.766845703125 +93986 0.628509521484375 +93987 0.462127685546875 +93988 0.297210693359375 +93989 0.14862060546875 +93990 -0.00537109375 +93991 -0.15753173828125 +93992 -0.31304931640625 +93993 -0.48876953125 +93994 -0.6416015625 +93995 -0.751373291015625 +93996 -0.84619140625 +93997 -0.861297607421875 +93998 -0.863250732421875 +93999 -0.856597900390625 +94000 -0.7498779296875 +94001 -0.624542236328125 +94002 -0.47808837890625 +94003 -0.253387451171875 +94004 0.003692626953125 +94005 0.2257080078125 +94006 0.427154541015625 +94007 0.643218994140625 +94008 0.855926513671875 +94009 0.870361328125 +94010 0.870361328125 +94011 0.862762451171875 +94012 0.79669189453125 +94013 0.595794677734375 +94014 0.362152099609375 +94015 0.1270751953125 +94016 -0.086944580078125 +94017 -0.2784423828125 +94018 -0.484832763671875 +94019 -0.729583740234375 +94020 -0.86688232421875 +94021 -0.870391845703125 +94022 -0.86859130859375 +94023 -0.86279296875 +94024 -0.817962646484375 +94025 -0.6116943359375 +94026 -0.3128662109375 +94027 0.039398193359375 +94028 0.422821044921875 +94029 0.805145263671875 +94030 0.870361328125 +94031 0.870361328125 +94032 0.860015869140625 +94033 0.727935791015625 +94034 0.48114013671875 +94035 0.2059326171875 +94036 -0.06103515625 +94037 -0.29913330078125 +94038 -0.516204833984375 +94039 -0.7252197265625 +94040 -0.85980224609375 +94041 -0.870391845703125 +94042 -0.870391845703125 +94043 -0.858062744140625 +94044 -0.673004150390625 +94045 -0.42694091796875 +94046 -0.2100830078125 +94047 -0.0362548828125 +94048 0.10943603515625 +94049 0.23516845703125 +94050 0.373687744140625 +94051 0.517791748046875 +94052 0.602783203125 +94053 0.635711669921875 +94054 0.655181884765625 +94055 0.65948486328125 +94056 0.651275634765625 +94057 0.61846923828125 +94058 0.53753662109375 +94059 0.404144287109375 +94060 0.22186279296875 +94061 0.003997802734375 +94062 -0.22100830078125 +94063 -0.42449951171875 +94064 -0.579833984375 +94065 -0.641876220703125 +94066 -0.6177978515625 +94067 -0.575531005859375 +94068 -0.526336669921875 +94069 -0.42645263671875 +94070 -0.2581787109375 +94071 -0.068695068359375 +94072 0.09222412109375 +94073 0.232147216796875 +94074 0.3509521484375 +94075 0.410064697265625 +94076 0.372955322265625 +94077 0.2554931640625 +94078 0.10711669921875 +94079 -0.052886962890625 +94080 -0.186279296875 +94081 -0.23291015625 +94082 -0.209442138671875 +94083 -0.174163818359375 +94084 -0.126739501953125 +94085 -0.048126220703125 +94086 0.0426025390625 +94087 0.10748291015625 +94088 0.1409912109375 +94089 0.19708251953125 +94090 0.273651123046875 +94091 0.31768798828125 +94092 0.341094970703125 +94093 0.368011474609375 +94094 0.37249755859375 +94095 0.30072021484375 +94096 0.1517333984375 +94097 -0.01470947265625 +94098 -0.1883544921875 +94099 -0.372711181640625 +94100 -0.51397705078125 +94101 -0.57177734375 +94102 -0.53948974609375 +94103 -0.43511962890625 +94104 -0.2962646484375 +94105 -0.161102294921875 +94106 -0.0435791015625 +94107 0.060394287109375 +94108 0.13665771484375 +94109 0.170135498046875 +94110 0.16552734375 +94111 0.15728759765625 +94112 0.150787353515625 +94113 0.12200927734375 +94114 0.080108642578125 +94115 0.05126953125 +94116 0.062896728515625 +94117 0.09271240234375 +94118 0.092987060546875 +94119 0.07855224609375 +94120 0.06427001953125 +94121 0.0347900390625 +94122 -0.01171875 +94123 -0.056060791015625 +94124 -0.055511474609375 +94125 -0.010467529296875 +94126 0.02508544921875 +94127 0.025665283203125 +94128 0.017333984375 +94129 0.00189208984375 +94130 -0.03173828125 +94131 -0.071502685546875 +94132 -0.13543701171875 +94133 -0.219970703125 +94134 -0.300506591796875 +94135 -0.376312255859375 +94136 -0.416107177734375 +94137 -0.371124267578125 +94138 -0.242279052734375 +94139 -0.069732666015625 +94140 0.125640869140625 +94141 0.31268310546875 +94142 0.45501708984375 +94143 0.554779052734375 +94144 0.61065673828125 +94145 0.610931396484375 +94146 0.531463623046875 +94147 0.3883056640625 +94148 0.23468017578125 +94149 0.095245361328125 +94150 -0.00396728515625 +94151 -0.04852294921875 +94152 -0.055145263671875 +94153 -0.0758056640625 +94154 -0.138702392578125 +94155 -0.209197998046875 +94156 -0.289031982421875 +94157 -0.37884521484375 +94158 -0.456329345703125 +94159 -0.51641845703125 +94160 -0.519287109375 +94161 -0.458251953125 +94162 -0.384796142578125 +94163 -0.323699951171875 +94164 -0.269287109375 +94165 -0.1951904296875 +94166 -0.100006103515625 +94167 -0.01055908203125 +94168 0.1033935546875 +94169 0.24908447265625 +94170 0.373199462890625 +94171 0.45806884765625 +94172 0.511474609375 +94173 0.565399169921875 +94174 0.61138916015625 +94175 0.5897216796875 +94176 0.4906005859375 +94177 0.33148193359375 +94178 0.147796630859375 +94179 -0.01873779296875 +94180 -0.140289306640625 +94181 -0.191986083984375 +94182 -0.184295654296875 +94183 -0.161834716796875 +94184 -0.166595458984375 +94185 -0.19390869140625 +94186 -0.22442626953125 +94187 -0.279754638671875 +94188 -0.3389892578125 +94189 -0.3543701171875 +94190 -0.348175048828125 +94191 -0.32598876953125 +94192 -0.2581787109375 +94193 -0.139801025390625 +94194 0.014617919921875 +94195 0.144378662109375 +94196 0.221038818359375 +94197 0.27069091796875 +94198 0.294036865234375 +94199 0.311767578125 +94200 0.339141845703125 +94201 0.360260009765625 +94202 0.360504150390625 +94203 0.308380126953125 +94204 0.18170166015625 +94205 0.0047607421875 +94206 -0.17559814453125 +94207 -0.3143310546875 +94208 -0.36785888671875 +94209 -0.36248779296875 +94210 -0.343536376953125 +94211 -0.3018798828125 +94212 -0.231414794921875 +94213 -0.117645263671875 +94214 0.007049560546875 +94215 0.087982177734375 +94216 0.13946533203125 +94217 0.17425537109375 +94218 0.188201904296875 +94219 0.171234130859375 +94220 0.118438720703125 +94221 0.05706787109375 +94222 -0.010711669921875 +94223 -0.0914306640625 +94224 -0.162322998046875 +94225 -0.194549560546875 +94226 -0.1492919921875 +94227 -0.02166748046875 +94228 0.124053955078125 +94229 0.211151123046875 +94230 0.240447998046875 +94231 0.242218017578125 +94232 0.2257080078125 +94233 0.194366455078125 +94234 0.115509033203125 +94235 0.0128173828125 +94236 -0.053802490234375 +94237 -0.110626220703125 +94238 -0.199493408203125 +94239 -0.29437255859375 +94240 -0.33221435546875 +94241 -0.27972412109375 +94242 -0.185333251953125 +94243 -0.128204345703125 +94244 -0.115692138671875 +94245 -0.116455078125 +94246 -0.105926513671875 +94247 -0.053955078125 +94248 0.048797607421875 +94249 0.157318115234375 +94250 0.212005615234375 +94251 0.218475341796875 +94252 0.23724365234375 +94253 0.30535888671875 +94254 0.38128662109375 +94255 0.404449462890625 +94256 0.3944091796875 +94257 0.3885498046875 +94258 0.362640380859375 +94259 0.27362060546875 +94260 0.11712646484375 +94261 -0.054901123046875 +94262 -0.19085693359375 +94263 -0.28570556640625 +94264 -0.339263916015625 +94265 -0.3775634765625 +94266 -0.445709228515625 +94267 -0.535064697265625 +94268 -0.629058837890625 +94269 -0.697601318359375 +94270 -0.70391845703125 +94271 -0.6424560546875 +94272 -0.491241455078125 +94273 -0.265716552734375 +94274 -0.023712158203125 +94275 0.201751708984375 +94276 0.375823974609375 +94277 0.485076904296875 +94278 0.56884765625 +94279 0.634765625 +94280 0.63763427734375 +94281 0.5660400390625 +94282 0.4720458984375 +94283 0.40692138671875 +94284 0.3778076171875 +94285 0.376953125 +94286 0.371978759765625 +94287 0.313140869140625 +94288 0.184417724609375 +94289 0.011199951171875 +94290 -0.171051025390625 +94291 -0.33740234375 +94292 -0.47198486328125 +94293 -0.560394287109375 +94294 -0.58056640625 +94295 -0.54754638671875 +94296 -0.508575439453125 +94297 -0.459503173828125 +94298 -0.394378662109375 +94299 -0.35260009765625 +94300 -0.31170654296875 +94301 -0.197418212890625 +94302 -0.007965087890625 +94303 0.207489013671875 +94304 0.409210205078125 +94305 0.57208251953125 +94306 0.66595458984375 +94307 0.65875244140625 +94308 0.56744384765625 +94309 0.431396484375 +94310 0.29443359375 +94311 0.182464599609375 +94312 0.06365966796875 +94313 -0.075958251953125 +94314 -0.189422607421875 +94315 -0.271942138671875 +94316 -0.342529296875 +94317 -0.364166259765625 +94318 -0.327239990234375 +94319 -0.2769775390625 +94320 -0.253692626953125 +94321 -0.24365234375 +94322 -0.1983642578125 +94323 -0.116241455078125 +94324 -0.036834716796875 +94325 0.034881591796875 +94326 0.09124755859375 +94327 0.10888671875 +94328 0.125518798828125 +94329 0.15771484375 +94330 0.17828369140625 +94331 0.17108154296875 +94332 0.129974365234375 +94333 0.082427978515625 +94334 0.027679443359375 +94335 -0.065643310546875 +94336 -0.15936279296875 +94337 -0.21307373046875 +94338 -0.234649658203125 +94339 -0.2001953125 +94340 -0.119171142578125 +94341 -0.024749755859375 +94342 0.085784912109375 +94343 0.178131103515625 +94344 0.215576171875 +94345 0.211456298828125 +94346 0.17523193359375 +94347 0.128753662109375 +94348 0.1019287109375 +94349 0.0743408203125 +94350 0.04327392578125 +94351 0.038177490234375 +94352 0.076263427734375 +94353 0.14105224609375 +94354 0.186431884765625 +94355 0.188812255859375 +94356 0.1390380859375 +94357 0.041778564453125 +94358 -0.079437255859375 +94359 -0.219390869140625 +94360 -0.367828369140625 +94361 -0.494873046875 +94362 -0.556243896484375 +94363 -0.508697509765625 +94364 -0.3756103515625 +94365 -0.218902587890625 +94366 -0.063751220703125 +94367 0.091552734375 +94368 0.23602294921875 +94369 0.342987060546875 +94370 0.39520263671875 +94371 0.389373779296875 +94372 0.324249267578125 +94373 0.224090576171875 +94374 0.124267578125 +94375 0.037078857421875 +94376 -0.010101318359375 +94377 -0.019439697265625 +94378 -0.022796630859375 +94379 -0.001556396484375 +94380 0.056304931640625 +94381 0.106719970703125 +94382 0.096893310546875 +94383 0.042694091796875 +94384 -0.018035888671875 +94385 -0.07586669921875 +94386 -0.11944580078125 +94387 -0.15972900390625 +94388 -0.202606201171875 +94389 -0.24859619140625 +94390 -0.30517578125 +94391 -0.36212158203125 +94392 -0.39141845703125 +94393 -0.35528564453125 +94394 -0.249969482421875 +94395 -0.092864990234375 +94396 0.08905029296875 +94397 0.2352294921875 +94398 0.318817138671875 +94399 0.358642578125 +94400 0.347747802734375 +94401 0.28564453125 +94402 0.223175048828125 +94403 0.196746826171875 +94404 0.179840087890625 +94405 0.155548095703125 +94406 0.151214599609375 +94407 0.156951904296875 +94408 0.13177490234375 +94409 0.100799560546875 +94410 0.087127685546875 +94411 0.05487060546875 +94412 -0.009002685546875 +94413 -0.10400390625 +94414 -0.229400634765625 +94415 -0.35552978515625 +94416 -0.441925048828125 +94417 -0.473846435546875 +94418 -0.464813232421875 +94419 -0.419097900390625 +94420 -0.334320068359375 +94421 -0.227935791015625 +94422 -0.12347412109375 +94423 -0.02764892578125 +94424 0.077667236328125 +94425 0.2132568359375 +94426 0.38885498046875 +94427 0.582794189453125 +94428 0.734039306640625 +94429 0.800140380859375 +94430 0.7783203125 +94431 0.6651611328125 +94432 0.45965576171875 +94433 0.199188232421875 +94434 -0.050689697265625 +94435 -0.23297119140625 +94436 -0.33013916015625 +94437 -0.368408203125 +94438 -0.378936767578125 +94439 -0.376983642578125 +94440 -0.37969970703125 +94441 -0.391510009765625 +94442 -0.385345458984375 +94443 -0.3419189453125 +94444 -0.28289794921875 +94445 -0.251617431640625 +94446 -0.266143798828125 +94447 -0.273345947265625 +94448 -0.216796875 +94449 -0.128265380859375 +94450 -0.068145751953125 +94451 -0.0430908203125 +94452 -0.024444580078125 +94453 0.020721435546875 +94454 0.124481201171875 +94455 0.25787353515625 +94456 0.379119873046875 +94457 0.47991943359375 +94458 0.5281982421875 +94459 0.511138916015625 +94460 0.456207275390625 +94461 0.407470703125 +94462 0.383758544921875 +94463 0.35687255859375 +94464 0.31182861328125 +94465 0.250885009765625 +94466 0.1654052734375 +94467 0.035247802734375 +94468 -0.142059326171875 +94469 -0.33563232421875 +94470 -0.5345458984375 +94471 -0.72186279296875 +94472 -0.836669921875 +94473 -0.8326416015625 +94474 -0.7296142578125 +94475 -0.582550048828125 +94476 -0.440093994140625 +94477 -0.324310302734375 +94478 -0.20147705078125 +94479 -0.044647216796875 +94480 0.103973388671875 +94481 0.202392578125 +94482 0.264495849609375 +94483 0.338897705078125 +94484 0.443817138671875 +94485 0.545074462890625 +94486 0.6173095703125 +94487 0.6524658203125 +94488 0.66339111328125 +94489 0.6561279296875 +94490 0.606781005859375 +94491 0.501190185546875 +94492 0.352783203125 +94493 0.176544189453125 +94494 -0.034820556640625 +94495 -0.258209228515625 +94496 -0.44244384765625 +94497 -0.5753173828125 +94498 -0.65203857421875 +94499 -0.641632080078125 +94500 -0.562164306640625 +94501 -0.458038330078125 +94502 -0.350555419921875 +94503 -0.260528564453125 +94504 -0.192108154296875 +94505 -0.141937255859375 +94506 -0.1021728515625 +94507 -0.062896728515625 +94508 -0.011932373046875 +94509 0.062835693359375 +94510 0.148712158203125 +94511 0.241729736328125 +94512 0.34912109375 +94513 0.457305908203125 +94514 0.54388427734375 +94515 0.5728759765625 +94516 0.506591796875 +94517 0.351226806640625 +94518 0.146514892578125 +94519 -0.05523681640625 +94520 -0.21624755859375 +94521 -0.334930419921875 +94522 -0.402984619140625 +94523 -0.4412841796875 +94524 -0.49578857421875 +94525 -0.5601806640625 +94526 -0.600738525390625 +94527 -0.584228515625 +94528 -0.47930908203125 +94529 -0.27935791015625 +94530 -0.0089111328125 +94531 0.268798828125 +94532 0.482818603515625 +94533 0.60369873046875 +94534 0.650421142578125 +94535 0.66400146484375 +94536 0.6414794921875 +94537 0.572540283203125 +94538 0.498138427734375 +94539 0.439453125 +94540 0.375518798828125 +94541 0.274505615234375 +94542 0.1087646484375 +94543 -0.099395751953125 +94544 -0.3182373046875 +94545 -0.5489501953125 +94546 -0.7738037109375 +94547 -0.86383056640625 +94548 -0.870391845703125 +94549 -0.86895751953125 +94550 -0.861053466796875 +94551 -0.765869140625 +94552 -0.5301513671875 +94553 -0.214691162109375 +94554 0.137359619140625 +94555 0.474822998046875 +94556 0.76239013671875 +94557 0.867462158203125 +94558 0.870361328125 +94559 0.86480712890625 +94560 0.831817626953125 +94561 0.677581787109375 +94562 0.495880126953125 +94563 0.30767822265625 +94564 0.116180419921875 +94565 -0.110748291015625 +94566 -0.381805419921875 +94567 -0.6572265625 +94568 -0.857421875 +94569 -0.870391845703125 +94570 -0.870391845703125 +94571 -0.86444091796875 +94572 -0.85723876953125 +94573 -0.790008544921875 +94574 -0.62847900390625 +94575 -0.3956298828125 +94576 -0.126708984375 +94577 0.150115966796875 +94578 0.424041748046875 +94579 0.670623779296875 +94580 0.854522705078125 +94581 0.866485595703125 +94582 0.86920166015625 +94583 0.8653564453125 +94584 0.857147216796875 +94585 0.766845703125 +94586 0.628509521484375 +94587 0.462127685546875 +94588 0.297210693359375 +94589 0.14862060546875 +94590 -0.00537109375 +94591 -0.15753173828125 +94592 -0.31304931640625 +94593 -0.48876953125 +94594 -0.6416015625 +94595 -0.751373291015625 +94596 -0.84619140625 +94597 -0.861297607421875 +94598 -0.863250732421875 +94599 -0.856597900390625 +94600 -0.7498779296875 +94601 -0.624542236328125 +94602 -0.47808837890625 +94603 -0.253387451171875 +94604 0.003692626953125 +94605 0.2257080078125 +94606 0.427154541015625 +94607 0.643218994140625 +94608 0.855926513671875 +94609 0.870361328125 +94610 0.870361328125 +94611 0.862762451171875 +94612 0.79669189453125 +94613 0.595794677734375 +94614 0.362152099609375 +94615 0.1270751953125 +94616 -0.086944580078125 +94617 -0.2784423828125 +94618 -0.484832763671875 +94619 -0.729583740234375 +94620 -0.86688232421875 +94621 -0.870391845703125 +94622 -0.86859130859375 +94623 -0.86279296875 +94624 -0.817962646484375 +94625 -0.6116943359375 +94626 -0.3128662109375 +94627 0.039398193359375 +94628 0.422821044921875 +94629 0.805145263671875 +94630 0.870361328125 +94631 0.870361328125 +94632 0.860015869140625 +94633 0.727935791015625 +94634 0.48114013671875 +94635 0.2059326171875 +94636 -0.06103515625 +94637 -0.29913330078125 +94638 -0.516204833984375 +94639 -0.7252197265625 +94640 -0.85980224609375 +94641 -0.870391845703125 +94642 -0.870391845703125 +94643 -0.858062744140625 +94644 -0.673004150390625 +94645 -0.42694091796875 +94646 -0.2100830078125 +94647 -0.0362548828125 +94648 0.10943603515625 +94649 0.23516845703125 +94650 0.373687744140625 +94651 0.517791748046875 +94652 0.602783203125 +94653 0.635711669921875 +94654 0.655181884765625 +94655 0.65948486328125 +94656 0.651275634765625 +94657 0.61846923828125 +94658 0.53753662109375 +94659 0.404144287109375 +94660 0.22186279296875 +94661 0.003997802734375 +94662 -0.22100830078125 +94663 -0.42449951171875 +94664 -0.579833984375 +94665 -0.641876220703125 +94666 -0.6177978515625 +94667 -0.575531005859375 +94668 -0.526336669921875 +94669 -0.42645263671875 +94670 -0.2581787109375 +94671 -0.068695068359375 +94672 0.09222412109375 +94673 0.232147216796875 +94674 0.3509521484375 +94675 0.410064697265625 +94676 0.372955322265625 +94677 0.2554931640625 +94678 0.10711669921875 +94679 -0.052886962890625 +94680 -0.186279296875 +94681 -0.23291015625 +94682 -0.209442138671875 +94683 -0.174163818359375 +94684 -0.126739501953125 +94685 -0.048126220703125 +94686 0.0426025390625 +94687 0.10748291015625 +94688 0.1409912109375 +94689 0.19708251953125 +94690 0.273651123046875 +94691 0.31768798828125 +94692 0.341094970703125 +94693 0.368011474609375 +94694 0.37249755859375 +94695 0.30072021484375 +94696 0.1517333984375 +94697 -0.01470947265625 +94698 -0.1883544921875 +94699 -0.372711181640625 +94700 -0.51397705078125 +94701 -0.57177734375 +94702 -0.53948974609375 +94703 -0.43511962890625 +94704 -0.2962646484375 +94705 -0.161102294921875 +94706 -0.0435791015625 +94707 0.060394287109375 +94708 0.13665771484375 +94709 0.170135498046875 +94710 0.16552734375 +94711 0.15728759765625 +94712 0.150787353515625 +94713 0.12200927734375 +94714 0.080108642578125 +94715 0.05126953125 +94716 0.062896728515625 +94717 0.09271240234375 +94718 0.092987060546875 +94719 0.07855224609375 +94720 0.06427001953125 +94721 0.0347900390625 +94722 -0.01171875 +94723 -0.056060791015625 +94724 -0.055511474609375 +94725 -0.010467529296875 +94726 0.02508544921875 +94727 0.025665283203125 +94728 0.017333984375 +94729 0.00189208984375 +94730 -0.03173828125 +94731 -0.071502685546875 +94732 -0.13543701171875 +94733 -0.219970703125 +94734 -0.300506591796875 +94735 -0.376312255859375 +94736 -0.416107177734375 +94737 -0.371124267578125 +94738 -0.242279052734375 +94739 -0.069732666015625 +94740 0.125640869140625 +94741 0.31268310546875 +94742 0.45501708984375 +94743 0.554779052734375 +94744 0.61065673828125 +94745 0.610931396484375 +94746 0.531463623046875 +94747 0.3883056640625 +94748 0.23468017578125 +94749 0.095245361328125 +94750 -0.00396728515625 +94751 -0.04852294921875 +94752 -0.055145263671875 +94753 -0.0758056640625 +94754 -0.138702392578125 +94755 -0.209197998046875 +94756 -0.289031982421875 +94757 -0.37884521484375 +94758 -0.456329345703125 +94759 -0.51641845703125 +94760 -0.519287109375 +94761 -0.458251953125 +94762 -0.384796142578125 +94763 -0.323699951171875 +94764 -0.269287109375 +94765 -0.1951904296875 +94766 -0.100006103515625 +94767 -0.01055908203125 +94768 0.1033935546875 +94769 0.24908447265625 +94770 0.373199462890625 +94771 0.45806884765625 +94772 0.511474609375 +94773 0.565399169921875 +94774 0.61138916015625 +94775 0.5897216796875 +94776 0.4906005859375 +94777 0.33148193359375 +94778 0.147796630859375 +94779 -0.01873779296875 +94780 -0.140289306640625 +94781 -0.191986083984375 +94782 -0.184295654296875 +94783 -0.161834716796875 +94784 -0.166595458984375 +94785 -0.19390869140625 +94786 -0.22442626953125 +94787 -0.279754638671875 +94788 -0.3389892578125 +94789 -0.3543701171875 +94790 -0.348175048828125 +94791 -0.32598876953125 +94792 -0.2581787109375 +94793 -0.139801025390625 +94794 0.014617919921875 +94795 0.144378662109375 +94796 0.221038818359375 +94797 0.27069091796875 +94798 0.294036865234375 +94799 0.311767578125 +94800 0.339141845703125 +94801 0.360260009765625 +94802 0.360504150390625 +94803 0.308380126953125 +94804 0.18170166015625 +94805 0.0047607421875 +94806 -0.17559814453125 +94807 -0.3143310546875 +94808 -0.36785888671875 +94809 -0.36248779296875 +94810 -0.343536376953125 +94811 -0.3018798828125 +94812 -0.231414794921875 +94813 -0.117645263671875 +94814 0.007049560546875 +94815 0.087982177734375 +94816 0.13946533203125 +94817 0.17425537109375 +94818 0.188201904296875 +94819 0.171234130859375 +94820 0.118438720703125 +94821 0.05706787109375 +94822 -0.010711669921875 +94823 -0.0914306640625 +94824 -0.162322998046875 +94825 -0.194549560546875 +94826 -0.1492919921875 +94827 -0.02166748046875 +94828 0.124053955078125 +94829 0.211151123046875 +94830 0.240447998046875 +94831 0.242218017578125 +94832 0.2257080078125 +94833 0.194366455078125 +94834 0.115509033203125 +94835 0.0128173828125 +94836 -0.053802490234375 +94837 -0.110626220703125 +94838 -0.199493408203125 +94839 -0.29437255859375 +94840 -0.33221435546875 +94841 -0.27972412109375 +94842 -0.185333251953125 +94843 -0.128204345703125 +94844 -0.115692138671875 +94845 -0.116455078125 +94846 -0.105926513671875 +94847 -0.053955078125 +94848 0.048797607421875 +94849 0.157318115234375 +94850 0.212005615234375 +94851 0.218475341796875 +94852 0.23724365234375 +94853 0.30535888671875 +94854 0.38128662109375 +94855 0.404449462890625 +94856 0.3944091796875 +94857 0.3885498046875 +94858 0.362640380859375 +94859 0.27362060546875 +94860 0.11712646484375 +94861 -0.054901123046875 +94862 -0.19085693359375 +94863 -0.28570556640625 +94864 -0.339263916015625 +94865 -0.3775634765625 +94866 -0.445709228515625 +94867 -0.535064697265625 +94868 -0.629058837890625 +94869 -0.697601318359375 +94870 -0.70391845703125 +94871 -0.6424560546875 +94872 -0.491241455078125 +94873 -0.265716552734375 +94874 -0.023712158203125 +94875 0.201751708984375 +94876 0.375823974609375 +94877 0.485076904296875 +94878 0.56884765625 +94879 0.634765625 +94880 0.63763427734375 +94881 0.5660400390625 +94882 0.4720458984375 +94883 0.40692138671875 +94884 0.3778076171875 +94885 0.376953125 +94886 0.371978759765625 +94887 0.313140869140625 +94888 0.184417724609375 +94889 0.011199951171875 +94890 -0.171051025390625 +94891 -0.33740234375 +94892 -0.47198486328125 +94893 -0.560394287109375 +94894 -0.58056640625 +94895 -0.54754638671875 +94896 -0.508575439453125 +94897 -0.459503173828125 +94898 -0.394378662109375 +94899 -0.35260009765625 +94900 -0.31170654296875 +94901 -0.197418212890625 +94902 -0.007965087890625 +94903 0.207489013671875 +94904 0.409210205078125 +94905 0.57208251953125 +94906 0.66595458984375 +94907 0.65875244140625 +94908 0.56744384765625 +94909 0.431396484375 +94910 0.29443359375 +94911 0.182464599609375 +94912 0.06365966796875 +94913 -0.075958251953125 +94914 -0.189422607421875 +94915 -0.271942138671875 +94916 -0.342529296875 +94917 -0.364166259765625 +94918 -0.327239990234375 +94919 -0.2769775390625 +94920 -0.253692626953125 +94921 -0.24365234375 +94922 -0.1983642578125 +94923 -0.116241455078125 +94924 -0.036834716796875 +94925 0.034881591796875 +94926 0.09124755859375 +94927 0.10888671875 +94928 0.125518798828125 +94929 0.15771484375 +94930 0.17828369140625 +94931 0.17108154296875 +94932 0.129974365234375 +94933 0.082427978515625 +94934 0.027679443359375 +94935 -0.065643310546875 +94936 -0.15936279296875 +94937 -0.21307373046875 +94938 -0.234649658203125 +94939 -0.2001953125 +94940 -0.119171142578125 +94941 -0.024749755859375 +94942 0.085784912109375 +94943 0.178131103515625 +94944 0.215576171875 +94945 0.211456298828125 +94946 0.17523193359375 +94947 0.128753662109375 +94948 0.1019287109375 +94949 0.0743408203125 +94950 0.04327392578125 +94951 0.038177490234375 +94952 0.076263427734375 +94953 0.14105224609375 +94954 0.186431884765625 +94955 0.188812255859375 +94956 0.1390380859375 +94957 0.041778564453125 +94958 -0.079437255859375 +94959 -0.219390869140625 +94960 -0.367828369140625 +94961 -0.494873046875 +94962 -0.556243896484375 +94963 -0.508697509765625 +94964 -0.3756103515625 +94965 -0.218902587890625 +94966 -0.063751220703125 +94967 0.091552734375 +94968 0.23602294921875 +94969 0.342987060546875 +94970 0.39520263671875 +94971 0.389373779296875 +94972 0.324249267578125 +94973 0.224090576171875 +94974 0.124267578125 +94975 0.037078857421875 +94976 -0.010101318359375 +94977 -0.019439697265625 +94978 -0.022796630859375 +94979 -0.001556396484375 +94980 0.056304931640625 +94981 0.106719970703125 +94982 0.096893310546875 +94983 0.042694091796875 +94984 -0.018035888671875 +94985 -0.07586669921875 +94986 -0.11944580078125 +94987 -0.15972900390625 +94988 -0.202606201171875 +94989 -0.24859619140625 +94990 -0.30517578125 +94991 -0.36212158203125 +94992 -0.39141845703125 +94993 -0.35528564453125 +94994 -0.249969482421875 +94995 -0.092864990234375 +94996 0.08905029296875 +94997 0.2352294921875 +94998 0.318817138671875 +94999 0.358642578125 +95000 0.347747802734375 +95001 0.28564453125 +95002 0.223175048828125 +95003 0.196746826171875 +95004 0.179840087890625 +95005 0.155548095703125 +95006 0.151214599609375 +95007 0.156951904296875 +95008 0.13177490234375 +95009 0.100799560546875 +95010 0.087127685546875 +95011 0.05487060546875 +95012 -0.009002685546875 +95013 -0.10400390625 +95014 -0.229400634765625 +95015 -0.35552978515625 +95016 -0.441925048828125 +95017 -0.473846435546875 +95018 -0.464813232421875 +95019 -0.419097900390625 +95020 -0.334320068359375 +95021 -0.227935791015625 +95022 -0.12347412109375 +95023 -0.02764892578125 +95024 0.077667236328125 +95025 0.2132568359375 +95026 0.38885498046875 +95027 0.582794189453125 +95028 0.734039306640625 +95029 0.800140380859375 +95030 0.7783203125 +95031 0.6651611328125 +95032 0.45965576171875 +95033 0.199188232421875 +95034 -0.050689697265625 +95035 -0.23297119140625 +95036 -0.33013916015625 +95037 -0.368408203125 +95038 -0.378936767578125 +95039 -0.376983642578125 +95040 -0.37969970703125 +95041 -0.391510009765625 +95042 -0.385345458984375 +95043 -0.3419189453125 +95044 -0.28289794921875 +95045 -0.251617431640625 +95046 -0.266143798828125 +95047 -0.273345947265625 +95048 -0.216796875 +95049 -0.128265380859375 +95050 -0.068145751953125 +95051 -0.0430908203125 +95052 -0.024444580078125 +95053 0.020721435546875 +95054 0.124481201171875 +95055 0.25787353515625 +95056 0.379119873046875 +95057 0.47991943359375 +95058 0.5281982421875 +95059 0.511138916015625 +95060 0.456207275390625 +95061 0.407470703125 +95062 0.383758544921875 +95063 0.35687255859375 +95064 0.31182861328125 +95065 0.250885009765625 +95066 0.1654052734375 +95067 0.035247802734375 +95068 -0.142059326171875 +95069 -0.33563232421875 +95070 -0.5345458984375 +95071 -0.72186279296875 +95072 -0.836669921875 +95073 -0.8326416015625 +95074 -0.7296142578125 +95075 -0.582550048828125 +95076 -0.440093994140625 +95077 -0.324310302734375 +95078 -0.20147705078125 +95079 -0.044647216796875 +95080 0.103973388671875 +95081 0.202392578125 +95082 0.264495849609375 +95083 0.338897705078125 +95084 0.443817138671875 +95085 0.545074462890625 +95086 0.6173095703125 +95087 0.6524658203125 +95088 0.66339111328125 +95089 0.6561279296875 +95090 0.606781005859375 +95091 0.501190185546875 +95092 0.352783203125 +95093 0.176544189453125 +95094 -0.034820556640625 +95095 -0.258209228515625 +95096 -0.44244384765625 +95097 -0.5753173828125 +95098 -0.65203857421875 +95099 -0.641632080078125 +95100 -0.562164306640625 +95101 -0.458038330078125 +95102 -0.350555419921875 +95103 -0.260528564453125 +95104 -0.192108154296875 +95105 -0.141937255859375 +95106 -0.1021728515625 +95107 -0.062896728515625 +95108 -0.011932373046875 +95109 0.062835693359375 +95110 0.148712158203125 +95111 0.241729736328125 +95112 0.34912109375 +95113 0.457305908203125 +95114 0.54388427734375 +95115 0.5728759765625 +95116 0.506591796875 +95117 0.351226806640625 +95118 0.146514892578125 +95119 -0.05523681640625 +95120 -0.21624755859375 +95121 -0.334930419921875 +95122 -0.402984619140625 +95123 -0.4412841796875 +95124 -0.49578857421875 +95125 -0.5601806640625 +95126 -0.600738525390625 +95127 -0.584228515625 +95128 -0.47930908203125 +95129 -0.27935791015625 +95130 -0.0089111328125 +95131 0.268798828125 +95132 0.482818603515625 +95133 0.60369873046875 +95134 0.650421142578125 +95135 0.66400146484375 +95136 0.6414794921875 +95137 0.572540283203125 +95138 0.498138427734375 +95139 0.439453125 +95140 0.375518798828125 +95141 0.274505615234375 +95142 0.1087646484375 +95143 -0.099395751953125 +95144 -0.3182373046875 +95145 -0.5489501953125 +95146 -0.7738037109375 +95147 -0.86383056640625 +95148 -0.870391845703125 +95149 -0.86895751953125 +95150 -0.861053466796875 +95151 -0.765869140625 +95152 -0.5301513671875 +95153 -0.214691162109375 +95154 0.137359619140625 +95155 0.474822998046875 +95156 0.76239013671875 +95157 0.867462158203125 +95158 0.870361328125 +95159 0.86480712890625 +95160 0.831817626953125 +95161 0.677581787109375 +95162 0.495880126953125 +95163 0.30767822265625 +95164 0.116180419921875 +95165 -0.110748291015625 +95166 -0.381805419921875 +95167 -0.6572265625 +95168 -0.857421875 +95169 -0.870391845703125 +95170 -0.870391845703125 +95171 -0.86444091796875 +95172 -0.85723876953125 +95173 -0.790008544921875 +95174 -0.62847900390625 +95175 -0.3956298828125 +95176 -0.126708984375 +95177 0.150115966796875 +95178 0.424041748046875 +95179 0.670623779296875 +95180 0.854522705078125 +95181 0.866485595703125 +95182 0.86920166015625 +95183 0.8653564453125 +95184 0.857147216796875 +95185 0.766845703125 +95186 0.628509521484375 +95187 0.462127685546875 +95188 0.297210693359375 +95189 0.14862060546875 +95190 -0.00537109375 +95191 -0.15753173828125 +95192 -0.31304931640625 +95193 -0.48876953125 +95194 -0.6416015625 +95195 -0.751373291015625 +95196 -0.84619140625 +95197 -0.861297607421875 +95198 -0.863250732421875 +95199 -0.856597900390625 +95200 -0.7498779296875 +95201 -0.624542236328125 +95202 -0.47808837890625 +95203 -0.253387451171875 +95204 0.003692626953125 +95205 0.2257080078125 +95206 0.427154541015625 +95207 0.643218994140625 +95208 0.855926513671875 +95209 0.870361328125 +95210 0.870361328125 +95211 0.862762451171875 +95212 0.79669189453125 +95213 0.595794677734375 +95214 0.362152099609375 +95215 0.1270751953125 +95216 -0.086944580078125 +95217 -0.2784423828125 +95218 -0.484832763671875 +95219 -0.729583740234375 +95220 -0.86688232421875 +95221 -0.870391845703125 +95222 -0.86859130859375 +95223 -0.86279296875 +95224 -0.817962646484375 +95225 -0.6116943359375 +95226 -0.3128662109375 +95227 0.039398193359375 +95228 0.422821044921875 +95229 0.805145263671875 +95230 0.870361328125 +95231 0.870361328125 +95232 0.860015869140625 +95233 0.727935791015625 +95234 0.48114013671875 +95235 0.2059326171875 +95236 -0.06103515625 +95237 -0.29913330078125 +95238 -0.516204833984375 +95239 -0.7252197265625 +95240 -0.85980224609375 +95241 -0.870391845703125 +95242 -0.870391845703125 +95243 -0.858062744140625 +95244 -0.673004150390625 +95245 -0.42694091796875 +95246 -0.2100830078125 +95247 -0.0362548828125 +95248 0.10943603515625 +95249 0.23516845703125 +95250 0.373687744140625 +95251 0.517791748046875 +95252 0.602783203125 +95253 0.635711669921875 +95254 0.655181884765625 +95255 0.65948486328125 +95256 0.651275634765625 +95257 0.61846923828125 +95258 0.53753662109375 +95259 0.404144287109375 +95260 0.22186279296875 +95261 0.003997802734375 +95262 -0.22100830078125 +95263 -0.42449951171875 +95264 -0.579833984375 +95265 -0.641876220703125 +95266 -0.6177978515625 +95267 -0.575531005859375 +95268 -0.526336669921875 +95269 -0.42645263671875 +95270 -0.2581787109375 +95271 -0.068695068359375 +95272 0.09222412109375 +95273 0.232147216796875 +95274 0.3509521484375 +95275 0.410064697265625 +95276 0.372955322265625 +95277 0.2554931640625 +95278 0.10711669921875 +95279 -0.052886962890625 +95280 -0.186279296875 +95281 -0.23291015625 +95282 -0.209442138671875 +95283 -0.174163818359375 +95284 -0.126739501953125 +95285 -0.048126220703125 +95286 0.0426025390625 +95287 0.10748291015625 +95288 0.1409912109375 +95289 0.19708251953125 +95290 0.273651123046875 +95291 0.31768798828125 +95292 0.341094970703125 +95293 0.368011474609375 +95294 0.37249755859375 +95295 0.30072021484375 +95296 0.1517333984375 +95297 -0.01470947265625 +95298 -0.1883544921875 +95299 -0.372711181640625 +95300 -0.51397705078125 +95301 -0.57177734375 +95302 -0.53948974609375 +95303 -0.43511962890625 +95304 -0.2962646484375 +95305 -0.161102294921875 +95306 -0.0435791015625 +95307 0.060394287109375 +95308 0.13665771484375 +95309 0.170135498046875 +95310 0.16552734375 +95311 0.15728759765625 +95312 0.150787353515625 +95313 0.12200927734375 +95314 0.080108642578125 +95315 0.05126953125 +95316 0.062896728515625 +95317 0.09271240234375 +95318 0.092987060546875 +95319 0.07855224609375 +95320 0.06427001953125 +95321 0.0347900390625 +95322 -0.01171875 +95323 -0.056060791015625 +95324 -0.055511474609375 +95325 -0.010467529296875 +95326 0.02508544921875 +95327 0.025665283203125 +95328 0.017333984375 +95329 0.00189208984375 +95330 -0.03173828125 +95331 -0.071502685546875 +95332 -0.13543701171875 +95333 -0.219970703125 +95334 -0.300506591796875 +95335 -0.376312255859375 +95336 -0.416107177734375 +95337 -0.371124267578125 +95338 -0.242279052734375 +95339 -0.069732666015625 +95340 0.125640869140625 +95341 0.31268310546875 +95342 0.45501708984375 +95343 0.554779052734375 +95344 0.61065673828125 +95345 0.610931396484375 +95346 0.531463623046875 +95347 0.3883056640625 +95348 0.23468017578125 +95349 0.095245361328125 +95350 -0.00396728515625 +95351 -0.04852294921875 +95352 -0.055145263671875 +95353 -0.0758056640625 +95354 -0.138702392578125 +95355 -0.209197998046875 +95356 -0.289031982421875 +95357 -0.37884521484375 +95358 -0.456329345703125 +95359 -0.51641845703125 +95360 -0.519287109375 +95361 -0.458251953125 +95362 -0.384796142578125 +95363 -0.323699951171875 +95364 -0.269287109375 +95365 -0.1951904296875 +95366 -0.100006103515625 +95367 -0.01055908203125 +95368 0.1033935546875 +95369 0.24908447265625 +95370 0.373199462890625 +95371 0.45806884765625 +95372 0.511474609375 +95373 0.565399169921875 +95374 0.61138916015625 +95375 0.5897216796875 +95376 0.4906005859375 +95377 0.33148193359375 +95378 0.147796630859375 +95379 -0.01873779296875 +95380 -0.140289306640625 +95381 -0.191986083984375 +95382 -0.184295654296875 +95383 -0.161834716796875 +95384 -0.166595458984375 +95385 -0.19390869140625 +95386 -0.22442626953125 +95387 -0.279754638671875 +95388 -0.3389892578125 +95389 -0.3543701171875 +95390 -0.348175048828125 +95391 -0.32598876953125 +95392 -0.2581787109375 +95393 -0.139801025390625 +95394 0.014617919921875 +95395 0.144378662109375 +95396 0.221038818359375 +95397 0.27069091796875 +95398 0.294036865234375 +95399 0.311767578125 +95400 0.339141845703125 +95401 0.360260009765625 +95402 0.360504150390625 +95403 0.308380126953125 +95404 0.18170166015625 +95405 0.0047607421875 +95406 -0.17559814453125 +95407 -0.3143310546875 +95408 -0.36785888671875 +95409 -0.36248779296875 +95410 -0.343536376953125 +95411 -0.3018798828125 +95412 -0.231414794921875 +95413 -0.117645263671875 +95414 0.007049560546875 +95415 0.087982177734375 +95416 0.13946533203125 +95417 0.17425537109375 +95418 0.188201904296875 +95419 0.171234130859375 +95420 0.118438720703125 +95421 0.05706787109375 +95422 -0.010711669921875 +95423 -0.0914306640625 +95424 -0.162322998046875 +95425 -0.194549560546875 +95426 -0.1492919921875 +95427 -0.02166748046875 +95428 0.124053955078125 +95429 0.211151123046875 +95430 0.240447998046875 +95431 0.242218017578125 +95432 0.2257080078125 +95433 0.194366455078125 +95434 0.115509033203125 +95435 0.0128173828125 +95436 -0.053802490234375 +95437 -0.110626220703125 +95438 -0.199493408203125 +95439 -0.29437255859375 +95440 -0.33221435546875 +95441 -0.27972412109375 +95442 -0.185333251953125 +95443 -0.128204345703125 +95444 -0.115692138671875 +95445 -0.116455078125 +95446 -0.105926513671875 +95447 -0.053955078125 +95448 0.048797607421875 +95449 0.157318115234375 +95450 0.212005615234375 +95451 0.218475341796875 +95452 0.23724365234375 +95453 0.30535888671875 +95454 0.38128662109375 +95455 0.404449462890625 +95456 0.3944091796875 +95457 0.3885498046875 +95458 0.362640380859375 +95459 0.27362060546875 +95460 0.11712646484375 +95461 -0.054901123046875 +95462 -0.19085693359375 +95463 -0.28570556640625 +95464 -0.339263916015625 +95465 -0.3775634765625 +95466 -0.445709228515625 +95467 -0.535064697265625 +95468 -0.629058837890625 +95469 -0.697601318359375 +95470 -0.70391845703125 +95471 -0.6424560546875 +95472 -0.491241455078125 +95473 -0.265716552734375 +95474 -0.023712158203125 +95475 0.201751708984375 +95476 0.375823974609375 +95477 0.485076904296875 +95478 0.56884765625 +95479 0.634765625 +95480 0.63763427734375 +95481 0.5660400390625 +95482 0.4720458984375 +95483 0.40692138671875 +95484 0.3778076171875 +95485 0.376953125 +95486 0.371978759765625 +95487 0.313140869140625 +95488 0.184417724609375 +95489 0.011199951171875 +95490 -0.171051025390625 +95491 -0.33740234375 +95492 -0.47198486328125 +95493 -0.560394287109375 +95494 -0.58056640625 +95495 -0.54754638671875 +95496 -0.508575439453125 +95497 -0.459503173828125 +95498 -0.394378662109375 +95499 -0.35260009765625 +95500 -0.31170654296875 +95501 -0.197418212890625 +95502 -0.007965087890625 +95503 0.207489013671875 +95504 0.409210205078125 +95505 0.57208251953125 +95506 0.66595458984375 +95507 0.65875244140625 +95508 0.56744384765625 +95509 0.431396484375 +95510 0.29443359375 +95511 0.182464599609375 +95512 0.06365966796875 +95513 -0.075958251953125 +95514 -0.189422607421875 +95515 -0.271942138671875 +95516 -0.342529296875 +95517 -0.364166259765625 +95518 -0.327239990234375 +95519 -0.2769775390625 +95520 -0.253692626953125 +95521 -0.24365234375 +95522 -0.1983642578125 +95523 -0.116241455078125 +95524 -0.036834716796875 +95525 0.034881591796875 +95526 0.09124755859375 +95527 0.10888671875 +95528 0.125518798828125 +95529 0.15771484375 +95530 0.17828369140625 +95531 0.17108154296875 +95532 0.129974365234375 +95533 0.082427978515625 +95534 0.027679443359375 +95535 -0.065643310546875 +95536 -0.15936279296875 +95537 -0.21307373046875 +95538 -0.234649658203125 +95539 -0.2001953125 +95540 -0.119171142578125 +95541 -0.024749755859375 +95542 0.085784912109375 +95543 0.178131103515625 +95544 0.215576171875 +95545 0.211456298828125 +95546 0.17523193359375 +95547 0.128753662109375 +95548 0.1019287109375 +95549 0.0743408203125 +95550 0.04327392578125 +95551 0.038177490234375 +95552 0.076263427734375 +95553 0.14105224609375 +95554 0.186431884765625 +95555 0.188812255859375 +95556 0.1390380859375 +95557 0.041778564453125 +95558 -0.079437255859375 +95559 -0.219390869140625 +95560 -0.367828369140625 +95561 -0.494873046875 +95562 -0.556243896484375 +95563 -0.508697509765625 +95564 -0.3756103515625 +95565 -0.218902587890625 +95566 -0.063751220703125 +95567 0.091552734375 +95568 0.23602294921875 +95569 0.342987060546875 +95570 0.39520263671875 +95571 0.389373779296875 +95572 0.324249267578125 +95573 0.224090576171875 +95574 0.124267578125 +95575 0.037078857421875 +95576 -0.010101318359375 +95577 -0.019439697265625 +95578 -0.022796630859375 +95579 -0.001556396484375 +95580 0.056304931640625 +95581 0.106719970703125 +95582 0.096893310546875 +95583 0.042694091796875 +95584 -0.018035888671875 +95585 -0.07586669921875 +95586 -0.11944580078125 +95587 -0.15972900390625 +95588 -0.202606201171875 +95589 -0.24859619140625 +95590 -0.30517578125 +95591 -0.36212158203125 +95592 -0.39141845703125 +95593 -0.35528564453125 +95594 -0.249969482421875 +95595 -0.092864990234375 +95596 0.08905029296875 +95597 0.2352294921875 +95598 0.318817138671875 +95599 0.358642578125 +95600 0.347747802734375 +95601 0.28564453125 +95602 0.223175048828125 +95603 0.196746826171875 +95604 0.179840087890625 +95605 0.155548095703125 +95606 0.151214599609375 +95607 0.156951904296875 +95608 0.13177490234375 +95609 0.100799560546875 +95610 0.087127685546875 +95611 0.05487060546875 +95612 -0.009002685546875 +95613 -0.10400390625 +95614 -0.229400634765625 +95615 -0.35552978515625 +95616 -0.441925048828125 +95617 -0.473846435546875 +95618 -0.464813232421875 +95619 -0.419097900390625 +95620 -0.334320068359375 +95621 -0.227935791015625 +95622 -0.12347412109375 +95623 -0.02764892578125 +95624 0.077667236328125 +95625 0.2132568359375 +95626 0.38885498046875 +95627 0.582794189453125 +95628 0.734039306640625 +95629 0.800140380859375 +95630 0.7783203125 +95631 0.6651611328125 +95632 0.45965576171875 +95633 0.199188232421875 +95634 -0.050689697265625 +95635 -0.23297119140625 +95636 -0.33013916015625 +95637 -0.368408203125 +95638 -0.378936767578125 +95639 -0.376983642578125 +95640 -0.37969970703125 +95641 -0.391510009765625 +95642 -0.385345458984375 +95643 -0.3419189453125 +95644 -0.28289794921875 +95645 -0.251617431640625 +95646 -0.266143798828125 +95647 -0.273345947265625 +95648 -0.216796875 +95649 -0.128265380859375 +95650 -0.068145751953125 +95651 -0.0430908203125 +95652 -0.024444580078125 +95653 0.020721435546875 +95654 0.124481201171875 +95655 0.25787353515625 +95656 0.379119873046875 +95657 0.47991943359375 +95658 0.5281982421875 +95659 0.511138916015625 +95660 0.456207275390625 +95661 0.407470703125 +95662 0.383758544921875 +95663 0.35687255859375 +95664 0.31182861328125 +95665 0.250885009765625 +95666 0.1654052734375 +95667 0.035247802734375 +95668 -0.142059326171875 +95669 -0.33563232421875 +95670 -0.5345458984375 +95671 -0.72186279296875 +95672 -0.836669921875 +95673 -0.8326416015625 +95674 -0.7296142578125 +95675 -0.582550048828125 +95676 -0.440093994140625 +95677 -0.324310302734375 +95678 -0.20147705078125 +95679 -0.044647216796875 +95680 0.103973388671875 +95681 0.202392578125 +95682 0.264495849609375 +95683 0.338897705078125 +95684 0.443817138671875 +95685 0.545074462890625 +95686 0.6173095703125 +95687 0.6524658203125 +95688 0.66339111328125 +95689 0.6561279296875 +95690 0.606781005859375 +95691 0.501190185546875 +95692 0.352783203125 +95693 0.176544189453125 +95694 -0.034820556640625 +95695 -0.258209228515625 +95696 -0.44244384765625 +95697 -0.5753173828125 +95698 -0.65203857421875 +95699 -0.641632080078125 +95700 -0.562164306640625 +95701 -0.458038330078125 +95702 -0.350555419921875 +95703 -0.260528564453125 +95704 -0.192108154296875 +95705 -0.141937255859375 +95706 -0.1021728515625 +95707 -0.062896728515625 +95708 -0.011932373046875 +95709 0.062835693359375 +95710 0.148712158203125 +95711 0.241729736328125 +95712 0.34912109375 +95713 0.457305908203125 +95714 0.54388427734375 +95715 0.5728759765625 +95716 0.506591796875 +95717 0.351226806640625 +95718 0.146514892578125 +95719 -0.05523681640625 +95720 -0.21624755859375 +95721 -0.334930419921875 +95722 -0.402984619140625 +95723 -0.4412841796875 +95724 -0.49578857421875 +95725 -0.5601806640625 +95726 -0.600738525390625 +95727 -0.584228515625 +95728 -0.47930908203125 +95729 -0.27935791015625 +95730 -0.0089111328125 +95731 0.268798828125 +95732 0.482818603515625 +95733 0.60369873046875 +95734 0.650421142578125 +95735 0.66400146484375 +95736 0.6414794921875 +95737 0.572540283203125 +95738 0.498138427734375 +95739 0.439453125 +95740 0.375518798828125 +95741 0.274505615234375 +95742 0.1087646484375 +95743 -0.099395751953125 +95744 -0.3182373046875 +95745 -0.5489501953125 +95746 -0.7738037109375 +95747 -0.86383056640625 +95748 -0.870391845703125 +95749 -0.86895751953125 +95750 -0.861053466796875 +95751 -0.765869140625 +95752 -0.5301513671875 +95753 -0.214691162109375 +95754 0.137359619140625 +95755 0.474822998046875 +95756 0.76239013671875 +95757 0.867462158203125 +95758 0.870361328125 +95759 0.86480712890625 +95760 0.831817626953125 +95761 0.677581787109375 +95762 0.495880126953125 +95763 0.30767822265625 +95764 0.116180419921875 +95765 -0.110748291015625 +95766 -0.381805419921875 +95767 -0.6572265625 +95768 -0.857421875 +95769 -0.870391845703125 +95770 -0.870391845703125 +95771 -0.86444091796875 +95772 -0.85723876953125 +95773 -0.790008544921875 +95774 -0.62847900390625 +95775 -0.3956298828125 +95776 -0.126708984375 +95777 0.150115966796875 +95778 0.424041748046875 +95779 0.670623779296875 +95780 0.854522705078125 +95781 0.866485595703125 +95782 0.86920166015625 +95783 0.8653564453125 +95784 0.857147216796875 +95785 0.766845703125 +95786 0.628509521484375 +95787 0.462127685546875 +95788 0.297210693359375 +95789 0.14862060546875 +95790 -0.00537109375 +95791 -0.15753173828125 +95792 -0.31304931640625 +95793 -0.48876953125 +95794 -0.6416015625 +95795 -0.751373291015625 +95796 -0.84619140625 +95797 -0.861297607421875 +95798 -0.863250732421875 +95799 -0.856597900390625 +95800 -0.7498779296875 +95801 -0.624542236328125 +95802 -0.47808837890625 +95803 -0.253387451171875 +95804 0.003692626953125 +95805 0.2257080078125 +95806 0.427154541015625 +95807 0.643218994140625 +95808 0.855926513671875 +95809 0.870361328125 +95810 0.870361328125 +95811 0.862762451171875 +95812 0.79669189453125 +95813 0.595794677734375 +95814 0.362152099609375 +95815 0.1270751953125 +95816 -0.086944580078125 +95817 -0.2784423828125 +95818 -0.484832763671875 +95819 -0.729583740234375 +95820 -0.86688232421875 +95821 -0.870391845703125 +95822 -0.86859130859375 +95823 -0.86279296875 +95824 -0.817962646484375 +95825 -0.6116943359375 +95826 -0.3128662109375 +95827 0.039398193359375 +95828 0.422821044921875 +95829 0.805145263671875 +95830 0.870361328125 +95831 0.870361328125 +95832 0.860015869140625 +95833 0.727935791015625 +95834 0.48114013671875 +95835 0.2059326171875 +95836 -0.06103515625 +95837 -0.29913330078125 +95838 -0.516204833984375 +95839 -0.7252197265625 +95840 -0.85980224609375 +95841 -0.870391845703125 +95842 -0.870391845703125 +95843 -0.858062744140625 +95844 -0.673004150390625 +95845 -0.42694091796875 +95846 -0.2100830078125 +95847 -0.0362548828125 +95848 0.10943603515625 +95849 0.23516845703125 +95850 0.373687744140625 +95851 0.517791748046875 +95852 0.602783203125 +95853 0.635711669921875 +95854 0.655181884765625 +95855 0.65948486328125 +95856 0.651275634765625 +95857 0.61846923828125 +95858 0.53753662109375 +95859 0.404144287109375 +95860 0.22186279296875 +95861 0.003997802734375 +95862 -0.22100830078125 +95863 -0.42449951171875 +95864 -0.579833984375 +95865 -0.641876220703125 +95866 -0.6177978515625 +95867 -0.575531005859375 +95868 -0.526336669921875 +95869 -0.42645263671875 +95870 -0.2581787109375 +95871 -0.068695068359375 +95872 0.09222412109375 +95873 0.232147216796875 +95874 0.3509521484375 +95875 0.410064697265625 +95876 0.372955322265625 +95877 0.2554931640625 +95878 0.10711669921875 +95879 -0.052886962890625 +95880 -0.186279296875 +95881 -0.23291015625 +95882 -0.209442138671875 +95883 -0.174163818359375 +95884 -0.126739501953125 +95885 -0.048126220703125 +95886 0.0426025390625 +95887 0.10748291015625 +95888 0.1409912109375 +95889 0.19708251953125 +95890 0.273651123046875 +95891 0.31768798828125 +95892 0.341094970703125 +95893 0.368011474609375 +95894 0.37249755859375 +95895 0.30072021484375 +95896 0.1517333984375 +95897 -0.01470947265625 +95898 -0.1883544921875 +95899 -0.372711181640625 +95900 -0.51397705078125 +95901 -0.57177734375 +95902 -0.53948974609375 +95903 -0.43511962890625 +95904 -0.2962646484375 +95905 -0.161102294921875 +95906 -0.0435791015625 +95907 0.060394287109375 +95908 0.13665771484375 +95909 0.170135498046875 +95910 0.16552734375 +95911 0.15728759765625 +95912 0.150787353515625 +95913 0.12200927734375 +95914 0.080108642578125 +95915 0.05126953125 +95916 0.062896728515625 +95917 0.09271240234375 +95918 0.092987060546875 +95919 0.07855224609375 +95920 0.06427001953125 +95921 0.0347900390625 +95922 -0.01171875 +95923 -0.056060791015625 +95924 -0.055511474609375 +95925 -0.010467529296875 +95926 0.02508544921875 +95927 0.025665283203125 +95928 0.017333984375 +95929 0.00189208984375 +95930 -0.03173828125 +95931 -0.071502685546875 +95932 -0.13543701171875 +95933 -0.219970703125 +95934 -0.300506591796875 +95935 -0.376312255859375 +95936 -0.416107177734375 +95937 -0.371124267578125 +95938 -0.242279052734375 +95939 -0.069732666015625 +95940 0.125640869140625 +95941 0.31268310546875 +95942 0.45501708984375 +95943 0.554779052734375 +95944 0.61065673828125 +95945 0.610931396484375 +95946 0.531463623046875 +95947 0.3883056640625 +95948 0.23468017578125 +95949 0.095245361328125 +95950 -0.00396728515625 +95951 -0.04852294921875 +95952 -0.055145263671875 +95953 -0.0758056640625 +95954 -0.138702392578125 +95955 -0.209197998046875 +95956 -0.289031982421875 +95957 -0.37884521484375 +95958 -0.456329345703125 +95959 -0.51641845703125 +95960 -0.519287109375 +95961 -0.458251953125 +95962 -0.384796142578125 +95963 -0.323699951171875 +95964 -0.269287109375 +95965 -0.1951904296875 +95966 -0.100006103515625 +95967 -0.01055908203125 +95968 0.1033935546875 +95969 0.24908447265625 +95970 0.373199462890625 +95971 0.45806884765625 +95972 0.511474609375 +95973 0.565399169921875 +95974 0.61138916015625 +95975 0.5897216796875 +95976 0.4906005859375 +95977 0.33148193359375 +95978 0.147796630859375 +95979 -0.01873779296875 +95980 -0.140289306640625 +95981 -0.191986083984375 +95982 -0.184295654296875 +95983 -0.161834716796875 +95984 -0.166595458984375 +95985 -0.19390869140625 +95986 -0.22442626953125 +95987 -0.279754638671875 +95988 -0.3389892578125 +95989 -0.3543701171875 +95990 -0.348175048828125 +95991 -0.32598876953125 +95992 -0.2581787109375 +95993 -0.139801025390625 +95994 0.014617919921875 +95995 0.144378662109375 +95996 0.221038818359375 +95997 0.27069091796875 +95998 0.294036865234375 +95999 0.311767578125 +96000 0.339141845703125 +96001 0.360260009765625 +96002 0.360504150390625 +96003 0.308380126953125 +96004 0.18170166015625 +96005 0.0047607421875 +96006 -0.17559814453125 +96007 -0.3143310546875 +96008 -0.36785888671875 +96009 -0.36248779296875 +96010 -0.343536376953125 +96011 -0.3018798828125 +96012 -0.231414794921875 +96013 -0.117645263671875 +96014 0.007049560546875 +96015 0.087982177734375 +96016 0.13946533203125 +96017 0.17425537109375 +96018 0.188201904296875 +96019 0.171234130859375 +96020 0.118438720703125 +96021 0.05706787109375 +96022 -0.010711669921875 +96023 -0.0914306640625 +96024 -0.162322998046875 +96025 -0.194549560546875 +96026 -0.1492919921875 +96027 -0.02166748046875 +96028 0.124053955078125 +96029 0.211151123046875 +96030 0.240447998046875 +96031 0.242218017578125 +96032 0.2257080078125 +96033 0.194366455078125 +96034 0.115509033203125 +96035 0.0128173828125 +96036 -0.053802490234375 +96037 -0.110626220703125 +96038 -0.199493408203125 +96039 -0.29437255859375 +96040 -0.33221435546875 +96041 -0.27972412109375 +96042 -0.185333251953125 +96043 -0.128204345703125 +96044 -0.115692138671875 +96045 -0.116455078125 +96046 -0.105926513671875 +96047 -0.053955078125 +96048 0.048797607421875 +96049 0.157318115234375 +96050 0.212005615234375 +96051 0.218475341796875 +96052 0.23724365234375 +96053 0.30535888671875 +96054 0.38128662109375 +96055 0.404449462890625 +96056 0.3944091796875 +96057 0.3885498046875 +96058 0.362640380859375 +96059 0.27362060546875 +96060 0.11712646484375 +96061 -0.054901123046875 +96062 -0.19085693359375 +96063 -0.28570556640625 +96064 -0.339263916015625 +96065 -0.3775634765625 +96066 -0.445709228515625 +96067 -0.535064697265625 +96068 -0.629058837890625 +96069 -0.697601318359375 +96070 -0.70391845703125 +96071 -0.6424560546875 +96072 -0.491241455078125 +96073 -0.265716552734375 +96074 -0.023712158203125 +96075 0.201751708984375 +96076 0.375823974609375 +96077 0.485076904296875 +96078 0.56884765625 +96079 0.634765625 +96080 0.63763427734375 +96081 0.5660400390625 +96082 0.4720458984375 +96083 0.40692138671875 +96084 0.3778076171875 +96085 0.376953125 +96086 0.371978759765625 +96087 0.313140869140625 +96088 0.184417724609375 +96089 0.011199951171875 +96090 -0.171051025390625 +96091 -0.33740234375 +96092 -0.47198486328125 +96093 -0.560394287109375 +96094 -0.58056640625 +96095 -0.54754638671875 +96096 -0.508575439453125 +96097 -0.459503173828125 +96098 -0.394378662109375 +96099 -0.35260009765625 +96100 -0.31170654296875 +96101 -0.197418212890625 +96102 -0.007965087890625 +96103 0.207489013671875 +96104 0.409210205078125 +96105 0.57208251953125 +96106 0.66595458984375 +96107 0.65875244140625 +96108 0.56744384765625 +96109 0.431396484375 +96110 0.29443359375 +96111 0.182464599609375 +96112 0.06365966796875 +96113 -0.075958251953125 +96114 -0.189422607421875 +96115 -0.271942138671875 +96116 -0.342529296875 +96117 -0.364166259765625 +96118 -0.327239990234375 +96119 -0.2769775390625 +96120 -0.253692626953125 +96121 -0.24365234375 +96122 -0.1983642578125 +96123 -0.116241455078125 +96124 -0.036834716796875 +96125 0.034881591796875 +96126 0.09124755859375 +96127 0.10888671875 +96128 0.125518798828125 +96129 0.15771484375 +96130 0.17828369140625 +96131 0.17108154296875 +96132 0.129974365234375 +96133 0.082427978515625 +96134 0.027679443359375 +96135 -0.065643310546875 +96136 -0.15936279296875 +96137 -0.21307373046875 +96138 -0.234649658203125 +96139 -0.2001953125 +96140 -0.119171142578125 +96141 -0.024749755859375 +96142 0.085784912109375 +96143 0.178131103515625 +96144 0.215576171875 +96145 0.211456298828125 +96146 0.17523193359375 +96147 0.128753662109375 +96148 0.1019287109375 +96149 0.0743408203125 +96150 0.04327392578125 +96151 0.038177490234375 +96152 0.076263427734375 +96153 0.14105224609375 +96154 0.186431884765625 +96155 0.188812255859375 +96156 0.1390380859375 +96157 0.041778564453125 +96158 -0.079437255859375 +96159 -0.219390869140625 +96160 -0.367828369140625 +96161 -0.494873046875 +96162 -0.556243896484375 +96163 -0.508697509765625 +96164 -0.3756103515625 +96165 -0.218902587890625 +96166 -0.063751220703125 +96167 0.091552734375 +96168 0.23602294921875 +96169 0.342987060546875 +96170 0.39520263671875 +96171 0.389373779296875 +96172 0.324249267578125 +96173 0.224090576171875 +96174 0.124267578125 +96175 0.037078857421875 +96176 -0.010101318359375 +96177 -0.019439697265625 +96178 -0.022796630859375 +96179 -0.001556396484375 +96180 0.056304931640625 +96181 0.106719970703125 +96182 0.096893310546875 +96183 0.042694091796875 +96184 -0.018035888671875 +96185 -0.07586669921875 +96186 -0.11944580078125 +96187 -0.15972900390625 +96188 -0.202606201171875 +96189 -0.24859619140625 +96190 -0.30517578125 +96191 -0.36212158203125 +96192 -0.39141845703125 +96193 -0.35528564453125 +96194 -0.249969482421875 +96195 -0.092864990234375 +96196 0.08905029296875 +96197 0.2352294921875 +96198 0.318817138671875 +96199 0.358642578125 +96200 0.347747802734375 +96201 0.28564453125 +96202 0.223175048828125 +96203 0.196746826171875 +96204 0.179840087890625 +96205 0.155548095703125 +96206 0.151214599609375 +96207 0.156951904296875 +96208 0.13177490234375 +96209 0.100799560546875 +96210 0.087127685546875 +96211 0.05487060546875 +96212 -0.009002685546875 +96213 -0.10400390625 +96214 -0.229400634765625 +96215 -0.35552978515625 +96216 -0.441925048828125 +96217 -0.473846435546875 +96218 -0.464813232421875 +96219 -0.419097900390625 +96220 -0.334320068359375 +96221 -0.227935791015625 +96222 -0.12347412109375 +96223 -0.02764892578125 +96224 0.077667236328125 +96225 0.2132568359375 +96226 0.38885498046875 +96227 0.582794189453125 +96228 0.734039306640625 +96229 0.800140380859375 +96230 0.7783203125 +96231 0.6651611328125 +96232 0.45965576171875 +96233 0.199188232421875 +96234 -0.050689697265625 +96235 -0.23297119140625 +96236 -0.33013916015625 +96237 -0.368408203125 +96238 -0.378936767578125 +96239 -0.376983642578125 +96240 -0.37969970703125 +96241 -0.391510009765625 +96242 -0.385345458984375 +96243 -0.3419189453125 +96244 -0.28289794921875 +96245 -0.251617431640625 +96246 -0.266143798828125 +96247 -0.273345947265625 +96248 -0.216796875 +96249 -0.128265380859375 +96250 -0.068145751953125 +96251 -0.0430908203125 +96252 -0.024444580078125 +96253 0.020721435546875 +96254 0.124481201171875 +96255 0.25787353515625 +96256 0.379119873046875 +96257 0.47991943359375 +96258 0.5281982421875 +96259 0.511138916015625 +96260 0.456207275390625 +96261 0.407470703125 +96262 0.383758544921875 +96263 0.35687255859375 +96264 0.31182861328125 +96265 0.250885009765625 +96266 0.1654052734375 +96267 0.035247802734375 +96268 -0.142059326171875 +96269 -0.33563232421875 +96270 -0.5345458984375 +96271 -0.72186279296875 +96272 -0.836669921875 +96273 -0.8326416015625 +96274 -0.7296142578125 +96275 -0.582550048828125 +96276 -0.440093994140625 +96277 -0.324310302734375 +96278 -0.20147705078125 +96279 -0.044647216796875 +96280 0.103973388671875 +96281 0.202392578125 +96282 0.264495849609375 +96283 0.338897705078125 +96284 0.443817138671875 +96285 0.545074462890625 +96286 0.6173095703125 +96287 0.6524658203125 +96288 0.66339111328125 +96289 0.6561279296875 +96290 0.606781005859375 +96291 0.501190185546875 +96292 0.352783203125 +96293 0.176544189453125 +96294 -0.034820556640625 +96295 -0.258209228515625 +96296 -0.44244384765625 +96297 -0.5753173828125 +96298 -0.65203857421875 +96299 -0.641632080078125 +96300 -0.562164306640625 +96301 -0.458038330078125 +96302 -0.350555419921875 +96303 -0.260528564453125 +96304 -0.192108154296875 +96305 -0.141937255859375 +96306 -0.1021728515625 +96307 -0.062896728515625 +96308 -0.011932373046875 +96309 0.062835693359375 +96310 0.148712158203125 +96311 0.241729736328125 +96312 0.34912109375 +96313 0.457305908203125 +96314 0.54388427734375 +96315 0.5728759765625 +96316 0.506591796875 +96317 0.351226806640625 +96318 0.146514892578125 +96319 -0.05523681640625 +96320 -0.21624755859375 +96321 -0.334930419921875 +96322 -0.402984619140625 +96323 -0.4412841796875 +96324 -0.49578857421875 +96325 -0.5601806640625 +96326 -0.600738525390625 +96327 -0.584228515625 +96328 -0.47930908203125 +96329 -0.27935791015625 +96330 -0.0089111328125 +96331 0.268798828125 +96332 0.482818603515625 +96333 0.60369873046875 +96334 0.650421142578125 +96335 0.66400146484375 +96336 0.6414794921875 +96337 0.572540283203125 +96338 0.498138427734375 +96339 0.439453125 +96340 0.375518798828125 +96341 0.274505615234375 +96342 0.1087646484375 +96343 -0.099395751953125 +96344 -0.3182373046875 +96345 -0.5489501953125 +96346 -0.7738037109375 +96347 -0.86383056640625 +96348 -0.870391845703125 +96349 -0.86895751953125 +96350 -0.861053466796875 +96351 -0.765869140625 +96352 -0.5301513671875 +96353 -0.214691162109375 +96354 0.137359619140625 +96355 0.474822998046875 +96356 0.76239013671875 +96357 0.867462158203125 +96358 0.870361328125 +96359 0.86480712890625 +96360 0.831817626953125 +96361 0.677581787109375 +96362 0.495880126953125 +96363 0.30767822265625 +96364 0.116180419921875 +96365 -0.110748291015625 +96366 -0.381805419921875 +96367 -0.6572265625 +96368 -0.857421875 +96369 -0.870391845703125 +96370 -0.870391845703125 +96371 -0.86444091796875 +96372 -0.85723876953125 +96373 -0.790008544921875 +96374 -0.62847900390625 +96375 -0.3956298828125 +96376 -0.126708984375 +96377 0.150115966796875 +96378 0.424041748046875 +96379 0.670623779296875 +96380 0.854522705078125 +96381 0.866485595703125 +96382 0.86920166015625 +96383 0.8653564453125 +96384 0.857147216796875 +96385 0.766845703125 +96386 0.628509521484375 +96387 0.462127685546875 +96388 0.297210693359375 +96389 0.14862060546875 +96390 -0.00537109375 +96391 -0.15753173828125 +96392 -0.31304931640625 +96393 -0.48876953125 +96394 -0.6416015625 +96395 -0.751373291015625 +96396 -0.84619140625 +96397 -0.861297607421875 +96398 -0.863250732421875 +96399 -0.856597900390625 +96400 -0.7498779296875 +96401 -0.624542236328125 +96402 -0.47808837890625 +96403 -0.253387451171875 +96404 0.003692626953125 +96405 0.2257080078125 +96406 0.427154541015625 +96407 0.643218994140625 +96408 0.855926513671875 +96409 0.870361328125 +96410 0.870361328125 +96411 0.862762451171875 +96412 0.79669189453125 +96413 0.595794677734375 +96414 0.362152099609375 +96415 0.1270751953125 +96416 -0.086944580078125 +96417 -0.2784423828125 +96418 -0.484832763671875 +96419 -0.729583740234375 +96420 -0.86688232421875 +96421 -0.870391845703125 +96422 -0.86859130859375 +96423 -0.86279296875 +96424 -0.817962646484375 +96425 -0.6116943359375 +96426 -0.3128662109375 +96427 0.039398193359375 +96428 0.422821044921875 +96429 0.805145263671875 +96430 0.870361328125 +96431 0.870361328125 +96432 0.860015869140625 +96433 0.727935791015625 +96434 0.48114013671875 +96435 0.2059326171875 +96436 -0.06103515625 +96437 -0.29913330078125 +96438 -0.516204833984375 +96439 -0.7252197265625 +96440 -0.85980224609375 +96441 -0.870391845703125 +96442 -0.870391845703125 +96443 -0.858062744140625 +96444 -0.673004150390625 +96445 -0.42694091796875 +96446 -0.2100830078125 +96447 -0.0362548828125 +96448 0.10943603515625 +96449 0.23516845703125 +96450 0.373687744140625 +96451 0.517791748046875 +96452 0.602783203125 +96453 0.635711669921875 +96454 0.655181884765625 +96455 0.65948486328125 +96456 0.651275634765625 +96457 0.61846923828125 +96458 0.53753662109375 +96459 0.404144287109375 +96460 0.22186279296875 +96461 0.003997802734375 +96462 -0.22100830078125 +96463 -0.42449951171875 +96464 -0.579833984375 +96465 -0.641876220703125 +96466 -0.6177978515625 +96467 -0.575531005859375 +96468 -0.526336669921875 +96469 -0.42645263671875 +96470 -0.2581787109375 +96471 -0.068695068359375 +96472 0.09222412109375 +96473 0.232147216796875 +96474 0.3509521484375 +96475 0.410064697265625 +96476 0.372955322265625 +96477 0.2554931640625 +96478 0.10711669921875 +96479 -0.052886962890625 +96480 -0.186279296875 +96481 -0.23291015625 +96482 -0.209442138671875 +96483 -0.174163818359375 +96484 -0.126739501953125 +96485 -0.048126220703125 +96486 0.0426025390625 +96487 0.10748291015625 +96488 0.1409912109375 +96489 0.19708251953125 +96490 0.273651123046875 +96491 0.31768798828125 +96492 0.341094970703125 +96493 0.368011474609375 +96494 0.37249755859375 +96495 0.30072021484375 +96496 0.1517333984375 +96497 -0.01470947265625 +96498 -0.1883544921875 +96499 -0.372711181640625 +96500 -0.51397705078125 +96501 -0.57177734375 +96502 -0.53948974609375 +96503 -0.43511962890625 +96504 -0.2962646484375 +96505 -0.161102294921875 +96506 -0.0435791015625 +96507 0.060394287109375 +96508 0.13665771484375 +96509 0.170135498046875 +96510 0.16552734375 +96511 0.15728759765625 +96512 0.150787353515625 +96513 0.12200927734375 +96514 0.080108642578125 +96515 0.05126953125 +96516 0.062896728515625 +96517 0.09271240234375 +96518 0.092987060546875 +96519 0.07855224609375 +96520 0.06427001953125 +96521 0.0347900390625 +96522 -0.01171875 +96523 -0.056060791015625 +96524 -0.055511474609375 +96525 -0.010467529296875 +96526 0.02508544921875 +96527 0.025665283203125 +96528 0.017333984375 +96529 0.00189208984375 +96530 -0.03173828125 +96531 -0.071502685546875 +96532 -0.13543701171875 +96533 -0.219970703125 +96534 -0.300506591796875 +96535 -0.376312255859375 +96536 -0.416107177734375 +96537 -0.371124267578125 +96538 -0.242279052734375 +96539 -0.069732666015625 +96540 0.125640869140625 +96541 0.31268310546875 +96542 0.45501708984375 +96543 0.554779052734375 +96544 0.61065673828125 +96545 0.610931396484375 +96546 0.531463623046875 +96547 0.3883056640625 +96548 0.23468017578125 +96549 0.095245361328125 +96550 -0.00396728515625 +96551 -0.04852294921875 +96552 -0.055145263671875 +96553 -0.0758056640625 +96554 -0.138702392578125 +96555 -0.209197998046875 +96556 -0.289031982421875 +96557 -0.37884521484375 +96558 -0.456329345703125 +96559 -0.51641845703125 +96560 -0.519287109375 +96561 -0.458251953125 +96562 -0.384796142578125 +96563 -0.323699951171875 +96564 -0.269287109375 +96565 -0.1951904296875 +96566 -0.100006103515625 +96567 -0.01055908203125 +96568 0.1033935546875 +96569 0.24908447265625 +96570 0.373199462890625 +96571 0.45806884765625 +96572 0.511474609375 +96573 0.565399169921875 +96574 0.61138916015625 +96575 0.5897216796875 +96576 0.4906005859375 +96577 0.33148193359375 +96578 0.147796630859375 +96579 -0.01873779296875 +96580 -0.140289306640625 +96581 -0.191986083984375 +96582 -0.184295654296875 +96583 -0.161834716796875 +96584 -0.166595458984375 +96585 -0.19390869140625 +96586 -0.22442626953125 +96587 -0.279754638671875 +96588 -0.3389892578125 +96589 -0.3543701171875 +96590 -0.348175048828125 +96591 -0.32598876953125 +96592 -0.2581787109375 +96593 -0.139801025390625 +96594 0.014617919921875 +96595 0.144378662109375 +96596 0.221038818359375 +96597 0.27069091796875 +96598 0.294036865234375 +96599 0.311767578125 +96600 0.339141845703125 +96601 0.360260009765625 +96602 0.360504150390625 +96603 0.308380126953125 +96604 0.18170166015625 +96605 0.0047607421875 +96606 -0.17559814453125 +96607 -0.3143310546875 +96608 -0.36785888671875 +96609 -0.36248779296875 +96610 -0.343536376953125 +96611 -0.3018798828125 +96612 -0.231414794921875 +96613 -0.117645263671875 +96614 0.007049560546875 +96615 0.087982177734375 +96616 0.13946533203125 +96617 0.17425537109375 +96618 0.188201904296875 +96619 0.171234130859375 +96620 0.118438720703125 +96621 0.05706787109375 +96622 -0.010711669921875 +96623 -0.0914306640625 +96624 -0.162322998046875 +96625 -0.194549560546875 +96626 -0.1492919921875 +96627 -0.02166748046875 +96628 0.124053955078125 +96629 0.211151123046875 +96630 0.240447998046875 +96631 0.242218017578125 +96632 0.2257080078125 +96633 0.194366455078125 +96634 0.115509033203125 +96635 0.0128173828125 +96636 -0.053802490234375 +96637 -0.110626220703125 +96638 -0.199493408203125 +96639 -0.29437255859375 +96640 -0.33221435546875 +96641 -0.27972412109375 +96642 -0.185333251953125 +96643 -0.128204345703125 +96644 -0.115692138671875 +96645 -0.116455078125 +96646 -0.105926513671875 +96647 -0.053955078125 +96648 0.048797607421875 +96649 0.157318115234375 +96650 0.212005615234375 +96651 0.218475341796875 +96652 0.23724365234375 +96653 0.30535888671875 +96654 0.38128662109375 +96655 0.404449462890625 +96656 0.3944091796875 +96657 0.3885498046875 +96658 0.362640380859375 +96659 0.27362060546875 +96660 0.11712646484375 +96661 -0.054901123046875 +96662 -0.19085693359375 +96663 -0.28570556640625 +96664 -0.339263916015625 +96665 -0.3775634765625 +96666 -0.445709228515625 +96667 -0.535064697265625 +96668 -0.629058837890625 +96669 -0.697601318359375 +96670 -0.70391845703125 +96671 -0.6424560546875 +96672 -0.491241455078125 +96673 -0.265716552734375 +96674 -0.023712158203125 +96675 0.201751708984375 +96676 0.375823974609375 +96677 0.485076904296875 +96678 0.56884765625 +96679 0.634765625 +96680 0.63763427734375 +96681 0.5660400390625 +96682 0.4720458984375 +96683 0.40692138671875 +96684 0.3778076171875 +96685 0.376953125 +96686 0.371978759765625 +96687 0.313140869140625 +96688 0.184417724609375 +96689 0.011199951171875 +96690 -0.171051025390625 +96691 -0.33740234375 +96692 -0.47198486328125 +96693 -0.560394287109375 +96694 -0.58056640625 +96695 -0.54754638671875 +96696 -0.508575439453125 +96697 -0.459503173828125 +96698 -0.394378662109375 +96699 -0.35260009765625 +96700 -0.31170654296875 +96701 -0.197418212890625 +96702 -0.007965087890625 +96703 0.207489013671875 +96704 0.409210205078125 +96705 0.57208251953125 +96706 0.66595458984375 +96707 0.65875244140625 +96708 0.56744384765625 +96709 0.431396484375 +96710 0.29443359375 +96711 0.182464599609375 +96712 0.06365966796875 +96713 -0.075958251953125 +96714 -0.189422607421875 +96715 -0.271942138671875 +96716 -0.342529296875 +96717 -0.364166259765625 +96718 -0.327239990234375 +96719 -0.2769775390625 +96720 -0.253692626953125 +96721 -0.24365234375 +96722 -0.1983642578125 +96723 -0.116241455078125 +96724 -0.036834716796875 +96725 0.034881591796875 +96726 0.09124755859375 +96727 0.10888671875 +96728 0.125518798828125 +96729 0.15771484375 +96730 0.17828369140625 +96731 0.17108154296875 +96732 0.129974365234375 +96733 0.082427978515625 +96734 0.027679443359375 +96735 -0.065643310546875 +96736 -0.15936279296875 +96737 -0.21307373046875 +96738 -0.234649658203125 +96739 -0.2001953125 +96740 -0.119171142578125 +96741 -0.024749755859375 +96742 0.085784912109375 +96743 0.178131103515625 +96744 0.215576171875 +96745 0.211456298828125 +96746 0.17523193359375 +96747 0.128753662109375 +96748 0.1019287109375 +96749 0.0743408203125 +96750 0.04327392578125 +96751 0.038177490234375 +96752 0.076263427734375 +96753 0.14105224609375 +96754 0.186431884765625 +96755 0.188812255859375 +96756 0.1390380859375 +96757 0.041778564453125 +96758 -0.079437255859375 +96759 -0.219390869140625 +96760 -0.367828369140625 +96761 -0.494873046875 +96762 -0.556243896484375 +96763 -0.508697509765625 +96764 -0.3756103515625 +96765 -0.218902587890625 +96766 -0.063751220703125 +96767 0.091552734375 +96768 0.23602294921875 +96769 0.342987060546875 +96770 0.39520263671875 +96771 0.389373779296875 +96772 0.324249267578125 +96773 0.224090576171875 +96774 0.124267578125 +96775 0.037078857421875 +96776 -0.010101318359375 +96777 -0.019439697265625 +96778 -0.022796630859375 +96779 -0.001556396484375 +96780 0.056304931640625 +96781 0.106719970703125 +96782 0.096893310546875 +96783 0.042694091796875 +96784 -0.018035888671875 +96785 -0.07586669921875 +96786 -0.11944580078125 +96787 -0.15972900390625 +96788 -0.202606201171875 +96789 -0.24859619140625 +96790 -0.30517578125 +96791 -0.36212158203125 +96792 -0.39141845703125 +96793 -0.35528564453125 +96794 -0.249969482421875 +96795 -0.092864990234375 +96796 0.08905029296875 +96797 0.2352294921875 +96798 0.318817138671875 +96799 0.358642578125 +96800 0.347747802734375 +96801 0.28564453125 +96802 0.223175048828125 +96803 0.196746826171875 +96804 0.179840087890625 +96805 0.155548095703125 +96806 0.151214599609375 +96807 0.156951904296875 +96808 0.13177490234375 +96809 0.100799560546875 +96810 0.087127685546875 +96811 0.05487060546875 +96812 -0.009002685546875 +96813 -0.10400390625 +96814 -0.229400634765625 +96815 -0.35552978515625 +96816 -0.441925048828125 +96817 -0.473846435546875 +96818 -0.464813232421875 +96819 -0.419097900390625 +96820 -0.334320068359375 +96821 -0.227935791015625 +96822 -0.12347412109375 +96823 -0.02764892578125 +96824 0.077667236328125 +96825 0.2132568359375 +96826 0.38885498046875 +96827 0.582794189453125 +96828 0.734039306640625 +96829 0.800140380859375 +96830 0.7783203125 +96831 0.6651611328125 +96832 0.45965576171875 +96833 0.199188232421875 +96834 -0.050689697265625 +96835 -0.23297119140625 +96836 -0.33013916015625 +96837 -0.368408203125 +96838 -0.378936767578125 +96839 -0.376983642578125 +96840 -0.37969970703125 +96841 -0.391510009765625 +96842 -0.385345458984375 +96843 -0.3419189453125 +96844 -0.28289794921875 +96845 -0.251617431640625 +96846 -0.266143798828125 +96847 -0.273345947265625 +96848 -0.216796875 +96849 -0.128265380859375 +96850 -0.068145751953125 +96851 -0.0430908203125 +96852 -0.024444580078125 +96853 0.020721435546875 +96854 0.124481201171875 +96855 0.25787353515625 +96856 0.379119873046875 +96857 0.47991943359375 +96858 0.5281982421875 +96859 0.511138916015625 +96860 0.456207275390625 +96861 0.407470703125 +96862 0.383758544921875 +96863 0.35687255859375 +96864 0.31182861328125 +96865 0.250885009765625 +96866 0.1654052734375 +96867 0.035247802734375 +96868 -0.142059326171875 +96869 -0.33563232421875 +96870 -0.5345458984375 +96871 -0.72186279296875 +96872 -0.836669921875 +96873 -0.8326416015625 +96874 -0.7296142578125 +96875 -0.582550048828125 +96876 -0.440093994140625 +96877 -0.324310302734375 +96878 -0.20147705078125 +96879 -0.044647216796875 +96880 0.103973388671875 +96881 0.202392578125 +96882 0.264495849609375 +96883 0.338897705078125 +96884 0.443817138671875 +96885 0.545074462890625 +96886 0.6173095703125 +96887 0.6524658203125 +96888 0.66339111328125 +96889 0.6561279296875 +96890 0.606781005859375 +96891 0.501190185546875 +96892 0.352783203125 +96893 0.176544189453125 +96894 -0.034820556640625 +96895 -0.258209228515625 +96896 -0.44244384765625 +96897 -0.5753173828125 +96898 -0.65203857421875 +96899 -0.641632080078125 +96900 -0.562164306640625 +96901 -0.458038330078125 +96902 -0.350555419921875 +96903 -0.260528564453125 +96904 -0.192108154296875 +96905 -0.141937255859375 +96906 -0.1021728515625 +96907 -0.062896728515625 +96908 -0.011932373046875 +96909 0.062835693359375 +96910 0.148712158203125 +96911 0.241729736328125 +96912 0.34912109375 +96913 0.457305908203125 +96914 0.54388427734375 +96915 0.5728759765625 +96916 0.506591796875 +96917 0.351226806640625 +96918 0.146514892578125 +96919 -0.05523681640625 +96920 -0.21624755859375 +96921 -0.334930419921875 +96922 -0.402984619140625 +96923 -0.4412841796875 +96924 -0.49578857421875 +96925 -0.5601806640625 +96926 -0.600738525390625 +96927 -0.584228515625 +96928 -0.47930908203125 +96929 -0.27935791015625 +96930 -0.0089111328125 +96931 0.268798828125 +96932 0.482818603515625 +96933 0.60369873046875 +96934 0.650421142578125 +96935 0.66400146484375 +96936 0.6414794921875 +96937 0.572540283203125 +96938 0.498138427734375 +96939 0.439453125 +96940 0.375518798828125 +96941 0.274505615234375 +96942 0.1087646484375 +96943 -0.099395751953125 +96944 -0.3182373046875 +96945 -0.5489501953125 +96946 -0.7738037109375 +96947 -0.86383056640625 +96948 -0.870391845703125 +96949 -0.86895751953125 +96950 -0.861053466796875 +96951 -0.765869140625 +96952 -0.5301513671875 +96953 -0.214691162109375 +96954 0.137359619140625 +96955 0.474822998046875 +96956 0.76239013671875 +96957 0.867462158203125 +96958 0.870361328125 +96959 0.86480712890625 +96960 0.831817626953125 +96961 0.677581787109375 +96962 0.495880126953125 +96963 0.30767822265625 +96964 0.116180419921875 +96965 -0.110748291015625 +96966 -0.381805419921875 +96967 -0.6572265625 +96968 -0.857421875 +96969 -0.870391845703125 +96970 -0.870391845703125 +96971 -0.86444091796875 +96972 -0.85723876953125 +96973 -0.790008544921875 +96974 -0.62847900390625 +96975 -0.3956298828125 +96976 -0.126708984375 +96977 0.150115966796875 +96978 0.424041748046875 +96979 0.670623779296875 +96980 0.854522705078125 +96981 0.866485595703125 +96982 0.86920166015625 +96983 0.8653564453125 +96984 0.857147216796875 +96985 0.766845703125 +96986 0.628509521484375 +96987 0.462127685546875 +96988 0.297210693359375 +96989 0.14862060546875 +96990 -0.00537109375 +96991 -0.15753173828125 +96992 -0.31304931640625 +96993 -0.48876953125 +96994 -0.6416015625 +96995 -0.751373291015625 +96996 -0.84619140625 +96997 -0.861297607421875 +96998 -0.863250732421875 +96999 -0.856597900390625 +97000 -0.7498779296875 +97001 -0.624542236328125 +97002 -0.47808837890625 +97003 -0.253387451171875 +97004 0.003692626953125 +97005 0.2257080078125 +97006 0.427154541015625 +97007 0.643218994140625 +97008 0.855926513671875 +97009 0.870361328125 +97010 0.870361328125 +97011 0.862762451171875 +97012 0.79669189453125 +97013 0.595794677734375 +97014 0.362152099609375 +97015 0.1270751953125 +97016 -0.086944580078125 +97017 -0.2784423828125 +97018 -0.484832763671875 +97019 -0.729583740234375 +97020 -0.86688232421875 +97021 -0.870391845703125 +97022 -0.86859130859375 +97023 -0.86279296875 +97024 -0.817962646484375 +97025 -0.6116943359375 +97026 -0.3128662109375 +97027 0.039398193359375 +97028 0.422821044921875 +97029 0.805145263671875 +97030 0.870361328125 +97031 0.870361328125 +97032 0.860015869140625 +97033 0.727935791015625 +97034 0.48114013671875 +97035 0.2059326171875 +97036 -0.06103515625 +97037 -0.29913330078125 +97038 -0.516204833984375 +97039 -0.7252197265625 +97040 -0.85980224609375 +97041 -0.870391845703125 +97042 -0.870391845703125 +97043 -0.858062744140625 +97044 -0.673004150390625 +97045 -0.42694091796875 +97046 -0.2100830078125 +97047 -0.0362548828125 +97048 0.10943603515625 +97049 0.23516845703125 +97050 0.373687744140625 +97051 0.517791748046875 +97052 0.602783203125 +97053 0.635711669921875 +97054 0.655181884765625 +97055 0.65948486328125 +97056 0.651275634765625 +97057 0.61846923828125 +97058 0.53753662109375 +97059 0.404144287109375 +97060 0.22186279296875 +97061 0.003997802734375 +97062 -0.22100830078125 +97063 -0.42449951171875 +97064 -0.579833984375 +97065 -0.641876220703125 +97066 -0.6177978515625 +97067 -0.575531005859375 +97068 -0.526336669921875 +97069 -0.42645263671875 +97070 -0.2581787109375 +97071 -0.068695068359375 +97072 0.09222412109375 +97073 0.232147216796875 +97074 0.3509521484375 +97075 0.410064697265625 +97076 0.372955322265625 +97077 0.2554931640625 +97078 0.10711669921875 +97079 -0.052886962890625 +97080 -0.186279296875 +97081 -0.23291015625 +97082 -0.209442138671875 +97083 -0.174163818359375 +97084 -0.126739501953125 +97085 -0.048126220703125 +97086 0.0426025390625 +97087 0.10748291015625 +97088 0.1409912109375 +97089 0.19708251953125 +97090 0.273651123046875 +97091 0.31768798828125 +97092 0.341094970703125 +97093 0.368011474609375 +97094 0.37249755859375 +97095 0.30072021484375 +97096 0.1517333984375 +97097 -0.01470947265625 +97098 -0.1883544921875 +97099 -0.372711181640625 +97100 -0.51397705078125 +97101 -0.57177734375 +97102 -0.53948974609375 +97103 -0.43511962890625 +97104 -0.2962646484375 +97105 -0.161102294921875 +97106 -0.0435791015625 +97107 0.060394287109375 +97108 0.13665771484375 +97109 0.170135498046875 +97110 0.16552734375 +97111 0.15728759765625 +97112 0.150787353515625 +97113 0.12200927734375 +97114 0.080108642578125 +97115 0.05126953125 +97116 0.062896728515625 +97117 0.09271240234375 +97118 0.092987060546875 +97119 0.07855224609375 +97120 0.06427001953125 +97121 0.0347900390625 +97122 -0.01171875 +97123 -0.056060791015625 +97124 -0.055511474609375 +97125 -0.010467529296875 +97126 0.02508544921875 +97127 0.025665283203125 +97128 0.017333984375 +97129 0.00189208984375 +97130 -0.03173828125 +97131 -0.071502685546875 +97132 -0.13543701171875 +97133 -0.219970703125 +97134 -0.300506591796875 +97135 -0.376312255859375 +97136 -0.416107177734375 +97137 -0.371124267578125 +97138 -0.242279052734375 +97139 -0.069732666015625 +97140 0.125640869140625 +97141 0.31268310546875 +97142 0.45501708984375 +97143 0.554779052734375 +97144 0.61065673828125 +97145 0.610931396484375 +97146 0.531463623046875 +97147 0.3883056640625 +97148 0.23468017578125 +97149 0.095245361328125 +97150 -0.00396728515625 +97151 -0.04852294921875 +97152 -0.055145263671875 +97153 -0.0758056640625 +97154 -0.138702392578125 +97155 -0.209197998046875 +97156 -0.289031982421875 +97157 -0.37884521484375 +97158 -0.456329345703125 +97159 -0.51641845703125 +97160 -0.519287109375 +97161 -0.458251953125 +97162 -0.384796142578125 +97163 -0.323699951171875 +97164 -0.269287109375 +97165 -0.1951904296875 +97166 -0.100006103515625 +97167 -0.01055908203125 +97168 0.1033935546875 +97169 0.24908447265625 +97170 0.373199462890625 +97171 0.45806884765625 +97172 0.511474609375 +97173 0.565399169921875 +97174 0.61138916015625 +97175 0.5897216796875 +97176 0.4906005859375 +97177 0.33148193359375 +97178 0.147796630859375 +97179 -0.01873779296875 +97180 -0.140289306640625 +97181 -0.191986083984375 +97182 -0.184295654296875 +97183 -0.161834716796875 +97184 -0.166595458984375 +97185 -0.19390869140625 +97186 -0.22442626953125 +97187 -0.279754638671875 +97188 -0.3389892578125 +97189 -0.3543701171875 +97190 -0.348175048828125 +97191 -0.32598876953125 +97192 -0.2581787109375 +97193 -0.139801025390625 +97194 0.014617919921875 +97195 0.144378662109375 +97196 0.221038818359375 +97197 0.27069091796875 +97198 0.294036865234375 +97199 0.311767578125 +97200 0.339141845703125 +97201 0.360260009765625 +97202 0.360504150390625 +97203 0.308380126953125 +97204 0.18170166015625 +97205 0.0047607421875 +97206 -0.17559814453125 +97207 -0.3143310546875 +97208 -0.36785888671875 +97209 -0.36248779296875 +97210 -0.343536376953125 +97211 -0.3018798828125 +97212 -0.231414794921875 +97213 -0.117645263671875 +97214 0.007049560546875 +97215 0.087982177734375 +97216 0.13946533203125 +97217 0.17425537109375 +97218 0.188201904296875 +97219 0.171234130859375 +97220 0.118438720703125 +97221 0.05706787109375 +97222 -0.010711669921875 +97223 -0.0914306640625 +97224 -0.162322998046875 +97225 -0.194549560546875 +97226 -0.1492919921875 +97227 -0.02166748046875 +97228 0.124053955078125 +97229 0.211151123046875 +97230 0.240447998046875 +97231 0.242218017578125 +97232 0.2257080078125 +97233 0.194366455078125 +97234 0.115509033203125 +97235 0.0128173828125 +97236 -0.053802490234375 +97237 -0.110626220703125 +97238 -0.199493408203125 +97239 -0.29437255859375 +97240 -0.33221435546875 +97241 -0.27972412109375 +97242 -0.185333251953125 +97243 -0.128204345703125 +97244 -0.115692138671875 +97245 -0.116455078125 +97246 -0.105926513671875 +97247 -0.053955078125 +97248 0.048797607421875 +97249 0.157318115234375 +97250 0.212005615234375 +97251 0.218475341796875 +97252 0.23724365234375 +97253 0.30535888671875 +97254 0.38128662109375 +97255 0.404449462890625 +97256 0.3944091796875 +97257 0.3885498046875 +97258 0.362640380859375 +97259 0.27362060546875 +97260 0.11712646484375 +97261 -0.054901123046875 +97262 -0.19085693359375 +97263 -0.28570556640625 +97264 -0.339263916015625 +97265 -0.3775634765625 +97266 -0.445709228515625 +97267 -0.535064697265625 +97268 -0.629058837890625 +97269 -0.697601318359375 +97270 -0.70391845703125 +97271 -0.6424560546875 +97272 -0.491241455078125 +97273 -0.265716552734375 +97274 -0.023712158203125 +97275 0.201751708984375 +97276 0.375823974609375 +97277 0.485076904296875 +97278 0.56884765625 +97279 0.634765625 +97280 0.63763427734375 +97281 0.5660400390625 +97282 0.4720458984375 +97283 0.40692138671875 +97284 0.3778076171875 +97285 0.376953125 +97286 0.371978759765625 +97287 0.313140869140625 +97288 0.184417724609375 +97289 0.011199951171875 +97290 -0.171051025390625 +97291 -0.33740234375 +97292 -0.47198486328125 +97293 -0.560394287109375 +97294 -0.58056640625 +97295 -0.54754638671875 +97296 -0.508575439453125 +97297 -0.459503173828125 +97298 -0.394378662109375 +97299 -0.35260009765625 +97300 -0.31170654296875 +97301 -0.197418212890625 +97302 -0.007965087890625 +97303 0.207489013671875 +97304 0.409210205078125 +97305 0.57208251953125 +97306 0.66595458984375 +97307 0.65875244140625 +97308 0.56744384765625 +97309 0.431396484375 +97310 0.29443359375 +97311 0.182464599609375 +97312 0.06365966796875 +97313 -0.075958251953125 +97314 -0.189422607421875 +97315 -0.271942138671875 +97316 -0.342529296875 +97317 -0.364166259765625 +97318 -0.327239990234375 +97319 -0.2769775390625 +97320 -0.253692626953125 +97321 -0.24365234375 +97322 -0.1983642578125 +97323 -0.116241455078125 +97324 -0.036834716796875 +97325 0.034881591796875 +97326 0.09124755859375 +97327 0.10888671875 +97328 0.125518798828125 +97329 0.15771484375 +97330 0.17828369140625 +97331 0.17108154296875 +97332 0.129974365234375 +97333 0.082427978515625 +97334 0.027679443359375 +97335 -0.065643310546875 +97336 -0.15936279296875 +97337 -0.21307373046875 +97338 -0.234649658203125 +97339 -0.2001953125 +97340 -0.119171142578125 +97341 -0.024749755859375 +97342 0.085784912109375 +97343 0.178131103515625 +97344 0.215576171875 +97345 0.211456298828125 +97346 0.17523193359375 +97347 0.128753662109375 +97348 0.1019287109375 +97349 0.0743408203125 +97350 0.04327392578125 +97351 0.038177490234375 +97352 0.076263427734375 +97353 0.14105224609375 +97354 0.186431884765625 +97355 0.188812255859375 +97356 0.1390380859375 +97357 0.041778564453125 +97358 -0.079437255859375 +97359 -0.219390869140625 +97360 -0.367828369140625 +97361 -0.494873046875 +97362 -0.556243896484375 +97363 -0.508697509765625 +97364 -0.3756103515625 +97365 -0.218902587890625 +97366 -0.063751220703125 +97367 0.091552734375 +97368 0.23602294921875 +97369 0.342987060546875 +97370 0.39520263671875 +97371 0.389373779296875 +97372 0.324249267578125 +97373 0.224090576171875 +97374 0.124267578125 +97375 0.037078857421875 +97376 -0.010101318359375 +97377 -0.019439697265625 +97378 -0.022796630859375 +97379 -0.001556396484375 +97380 0.056304931640625 +97381 0.106719970703125 +97382 0.096893310546875 +97383 0.042694091796875 +97384 -0.018035888671875 +97385 -0.07586669921875 +97386 -0.11944580078125 +97387 -0.15972900390625 +97388 -0.202606201171875 +97389 -0.24859619140625 +97390 -0.30517578125 +97391 -0.36212158203125 +97392 -0.39141845703125 +97393 -0.35528564453125 +97394 -0.249969482421875 +97395 -0.092864990234375 +97396 0.08905029296875 +97397 0.2352294921875 +97398 0.318817138671875 +97399 0.358642578125 +97400 0.347747802734375 +97401 0.28564453125 +97402 0.223175048828125 +97403 0.196746826171875 +97404 0.179840087890625 +97405 0.155548095703125 +97406 0.151214599609375 +97407 0.156951904296875 +97408 0.13177490234375 +97409 0.100799560546875 +97410 0.087127685546875 +97411 0.05487060546875 +97412 -0.009002685546875 +97413 -0.10400390625 +97414 -0.229400634765625 +97415 -0.35552978515625 +97416 -0.441925048828125 +97417 -0.473846435546875 +97418 -0.464813232421875 +97419 -0.419097900390625 +97420 -0.334320068359375 +97421 -0.227935791015625 +97422 -0.12347412109375 +97423 -0.02764892578125 +97424 0.077667236328125 +97425 0.2132568359375 +97426 0.38885498046875 +97427 0.582794189453125 +97428 0.734039306640625 +97429 0.800140380859375 +97430 0.7783203125 +97431 0.6651611328125 +97432 0.45965576171875 +97433 0.199188232421875 +97434 -0.050689697265625 +97435 -0.23297119140625 +97436 -0.33013916015625 +97437 -0.368408203125 +97438 -0.378936767578125 +97439 -0.376983642578125 +97440 -0.37969970703125 +97441 -0.391510009765625 +97442 -0.385345458984375 +97443 -0.3419189453125 +97444 -0.28289794921875 +97445 -0.251617431640625 +97446 -0.266143798828125 +97447 -0.273345947265625 +97448 -0.216796875 +97449 -0.128265380859375 +97450 -0.068145751953125 +97451 -0.0430908203125 +97452 -0.024444580078125 +97453 0.020721435546875 +97454 0.124481201171875 +97455 0.25787353515625 +97456 0.379119873046875 +97457 0.47991943359375 +97458 0.5281982421875 +97459 0.511138916015625 +97460 0.456207275390625 +97461 0.407470703125 +97462 0.383758544921875 +97463 0.35687255859375 +97464 0.31182861328125 +97465 0.250885009765625 +97466 0.1654052734375 +97467 0.035247802734375 +97468 -0.142059326171875 +97469 -0.33563232421875 +97470 -0.5345458984375 +97471 -0.72186279296875 +97472 -0.836669921875 +97473 -0.8326416015625 +97474 -0.7296142578125 +97475 -0.582550048828125 +97476 -0.440093994140625 +97477 -0.324310302734375 +97478 -0.20147705078125 +97479 -0.044647216796875 +97480 0.103973388671875 +97481 0.202392578125 +97482 0.264495849609375 +97483 0.338897705078125 +97484 0.443817138671875 +97485 0.545074462890625 +97486 0.6173095703125 +97487 0.6524658203125 +97488 0.66339111328125 +97489 0.6561279296875 +97490 0.606781005859375 +97491 0.501190185546875 +97492 0.352783203125 +97493 0.176544189453125 +97494 -0.034820556640625 +97495 -0.258209228515625 +97496 -0.44244384765625 +97497 -0.5753173828125 +97498 -0.65203857421875 +97499 -0.641632080078125 +97500 -0.562164306640625 +97501 -0.458038330078125 +97502 -0.350555419921875 +97503 -0.260528564453125 +97504 -0.192108154296875 +97505 -0.141937255859375 +97506 -0.1021728515625 +97507 -0.062896728515625 +97508 -0.011932373046875 +97509 0.062835693359375 +97510 0.148712158203125 +97511 0.241729736328125 +97512 0.34912109375 +97513 0.457305908203125 +97514 0.54388427734375 +97515 0.5728759765625 +97516 0.506591796875 +97517 0.351226806640625 +97518 0.146514892578125 +97519 -0.05523681640625 +97520 -0.21624755859375 +97521 -0.334930419921875 +97522 -0.402984619140625 +97523 -0.4412841796875 +97524 -0.49578857421875 +97525 -0.5601806640625 +97526 -0.600738525390625 +97527 -0.584228515625 +97528 -0.47930908203125 +97529 -0.27935791015625 +97530 -0.0089111328125 +97531 0.268798828125 +97532 0.482818603515625 +97533 0.60369873046875 +97534 0.650421142578125 +97535 0.66400146484375 +97536 0.6414794921875 +97537 0.572540283203125 +97538 0.498138427734375 +97539 0.439453125 +97540 0.375518798828125 +97541 0.274505615234375 +97542 0.1087646484375 +97543 -0.099395751953125 +97544 -0.3182373046875 +97545 -0.5489501953125 +97546 -0.7738037109375 +97547 -0.86383056640625 +97548 -0.870391845703125 +97549 -0.86895751953125 +97550 -0.861053466796875 +97551 -0.765869140625 +97552 -0.5301513671875 +97553 -0.214691162109375 +97554 0.137359619140625 +97555 0.474822998046875 +97556 0.76239013671875 +97557 0.867462158203125 +97558 0.870361328125 +97559 0.86480712890625 +97560 0.831817626953125 +97561 0.677581787109375 +97562 0.495880126953125 +97563 0.30767822265625 +97564 0.116180419921875 +97565 -0.110748291015625 +97566 -0.381805419921875 +97567 -0.6572265625 +97568 -0.857421875 +97569 -0.870391845703125 +97570 -0.870391845703125 +97571 -0.86444091796875 +97572 -0.85723876953125 +97573 -0.790008544921875 +97574 -0.62847900390625 +97575 -0.3956298828125 +97576 -0.126708984375 +97577 0.150115966796875 +97578 0.424041748046875 +97579 0.670623779296875 +97580 0.854522705078125 +97581 0.866485595703125 +97582 0.86920166015625 +97583 0.8653564453125 +97584 0.857147216796875 +97585 0.766845703125 +97586 0.628509521484375 +97587 0.462127685546875 +97588 0.297210693359375 +97589 0.14862060546875 +97590 -0.00537109375 +97591 -0.15753173828125 +97592 -0.31304931640625 +97593 -0.48876953125 +97594 -0.6416015625 +97595 -0.751373291015625 +97596 -0.84619140625 +97597 -0.861297607421875 +97598 -0.863250732421875 +97599 -0.856597900390625 +97600 -0.7498779296875 +97601 -0.624542236328125 +97602 -0.47808837890625 +97603 -0.253387451171875 +97604 0.003692626953125 +97605 0.2257080078125 +97606 0.427154541015625 +97607 0.643218994140625 +97608 0.855926513671875 +97609 0.870361328125 +97610 0.870361328125 +97611 0.862762451171875 +97612 0.79669189453125 +97613 0.595794677734375 +97614 0.362152099609375 +97615 0.1270751953125 +97616 -0.086944580078125 +97617 -0.2784423828125 +97618 -0.484832763671875 +97619 -0.729583740234375 +97620 -0.86688232421875 +97621 -0.870391845703125 +97622 -0.86859130859375 +97623 -0.86279296875 +97624 -0.817962646484375 +97625 -0.6116943359375 +97626 -0.3128662109375 +97627 0.039398193359375 +97628 0.422821044921875 +97629 0.805145263671875 +97630 0.870361328125 +97631 0.870361328125 +97632 0.860015869140625 +97633 0.727935791015625 +97634 0.48114013671875 +97635 0.2059326171875 +97636 -0.06103515625 +97637 -0.29913330078125 +97638 -0.516204833984375 +97639 -0.7252197265625 +97640 -0.85980224609375 +97641 -0.870391845703125 +97642 -0.870391845703125 +97643 -0.858062744140625 +97644 -0.673004150390625 +97645 -0.42694091796875 +97646 -0.2100830078125 +97647 -0.0362548828125 +97648 0.10943603515625 +97649 0.23516845703125 +97650 0.373687744140625 +97651 0.517791748046875 +97652 0.602783203125 +97653 0.635711669921875 +97654 0.655181884765625 +97655 0.65948486328125 +97656 0.651275634765625 +97657 0.61846923828125 +97658 0.53753662109375 +97659 0.404144287109375 +97660 0.22186279296875 +97661 0.003997802734375 +97662 -0.22100830078125 +97663 -0.42449951171875 +97664 -0.579833984375 +97665 -0.641876220703125 +97666 -0.6177978515625 +97667 -0.575531005859375 +97668 -0.526336669921875 +97669 -0.42645263671875 +97670 -0.2581787109375 +97671 -0.068695068359375 +97672 0.09222412109375 +97673 0.232147216796875 +97674 0.3509521484375 +97675 0.410064697265625 +97676 0.372955322265625 +97677 0.2554931640625 +97678 0.10711669921875 +97679 -0.052886962890625 +97680 -0.186279296875 +97681 -0.23291015625 +97682 -0.209442138671875 +97683 -0.174163818359375 +97684 -0.126739501953125 +97685 -0.048126220703125 +97686 0.0426025390625 +97687 0.10748291015625 +97688 0.1409912109375 +97689 0.19708251953125 +97690 0.273651123046875 +97691 0.31768798828125 +97692 0.341094970703125 +97693 0.368011474609375 +97694 0.37249755859375 +97695 0.30072021484375 +97696 0.1517333984375 +97697 -0.01470947265625 +97698 -0.1883544921875 +97699 -0.372711181640625 +97700 -0.51397705078125 +97701 -0.57177734375 +97702 -0.53948974609375 +97703 -0.43511962890625 +97704 -0.2962646484375 +97705 -0.161102294921875 +97706 -0.0435791015625 +97707 0.060394287109375 +97708 0.13665771484375 +97709 0.170135498046875 +97710 0.16552734375 +97711 0.15728759765625 +97712 0.150787353515625 +97713 0.12200927734375 +97714 0.080108642578125 +97715 0.05126953125 +97716 0.062896728515625 +97717 0.09271240234375 +97718 0.092987060546875 +97719 0.07855224609375 +97720 0.06427001953125 +97721 0.0347900390625 +97722 -0.01171875 +97723 -0.056060791015625 +97724 -0.055511474609375 +97725 -0.010467529296875 +97726 0.02508544921875 +97727 0.025665283203125 +97728 0.017333984375 +97729 0.00189208984375 +97730 -0.03173828125 +97731 -0.071502685546875 +97732 -0.13543701171875 +97733 -0.219970703125 +97734 -0.300506591796875 +97735 -0.376312255859375 +97736 -0.416107177734375 +97737 -0.371124267578125 +97738 -0.242279052734375 +97739 -0.069732666015625 +97740 0.125640869140625 +97741 0.31268310546875 +97742 0.45501708984375 +97743 0.554779052734375 +97744 0.61065673828125 +97745 0.610931396484375 +97746 0.531463623046875 +97747 0.3883056640625 +97748 0.23468017578125 +97749 0.095245361328125 +97750 -0.00396728515625 +97751 -0.04852294921875 +97752 -0.055145263671875 +97753 -0.0758056640625 +97754 -0.138702392578125 +97755 -0.209197998046875 +97756 -0.289031982421875 +97757 -0.37884521484375 +97758 -0.456329345703125 +97759 -0.51641845703125 +97760 -0.519287109375 +97761 -0.458251953125 +97762 -0.384796142578125 +97763 -0.323699951171875 +97764 -0.269287109375 +97765 -0.1951904296875 +97766 -0.100006103515625 +97767 -0.01055908203125 +97768 0.1033935546875 +97769 0.24908447265625 +97770 0.373199462890625 +97771 0.45806884765625 +97772 0.511474609375 +97773 0.565399169921875 +97774 0.61138916015625 +97775 0.5897216796875 +97776 0.4906005859375 +97777 0.33148193359375 +97778 0.147796630859375 +97779 -0.01873779296875 +97780 -0.140289306640625 +97781 -0.191986083984375 +97782 -0.184295654296875 +97783 -0.161834716796875 +97784 -0.166595458984375 +97785 -0.19390869140625 +97786 -0.22442626953125 +97787 -0.279754638671875 +97788 -0.3389892578125 +97789 -0.3543701171875 +97790 -0.348175048828125 +97791 -0.32598876953125 +97792 -0.2581787109375 +97793 -0.139801025390625 +97794 0.014617919921875 +97795 0.144378662109375 +97796 0.221038818359375 +97797 0.27069091796875 +97798 0.294036865234375 +97799 0.311767578125 +97800 0.339141845703125 +97801 0.360260009765625 +97802 0.360504150390625 +97803 0.308380126953125 +97804 0.18170166015625 +97805 0.0047607421875 +97806 -0.17559814453125 +97807 -0.3143310546875 +97808 -0.36785888671875 +97809 -0.36248779296875 +97810 -0.343536376953125 +97811 -0.3018798828125 +97812 -0.231414794921875 +97813 -0.117645263671875 +97814 0.007049560546875 +97815 0.087982177734375 +97816 0.13946533203125 +97817 0.17425537109375 +97818 0.188201904296875 +97819 0.171234130859375 +97820 0.118438720703125 +97821 0.05706787109375 +97822 -0.010711669921875 +97823 -0.0914306640625 +97824 -0.162322998046875 +97825 -0.194549560546875 +97826 -0.1492919921875 +97827 -0.02166748046875 +97828 0.124053955078125 +97829 0.211151123046875 +97830 0.240447998046875 +97831 0.242218017578125 +97832 0.2257080078125 +97833 0.194366455078125 +97834 0.115509033203125 +97835 0.0128173828125 +97836 -0.053802490234375 +97837 -0.110626220703125 +97838 -0.199493408203125 +97839 -0.29437255859375 +97840 -0.33221435546875 +97841 -0.27972412109375 +97842 -0.185333251953125 +97843 -0.128204345703125 +97844 -0.115692138671875 +97845 -0.116455078125 +97846 -0.105926513671875 +97847 -0.053955078125 +97848 0.048797607421875 +97849 0.157318115234375 +97850 0.212005615234375 +97851 0.218475341796875 +97852 0.23724365234375 +97853 0.30535888671875 +97854 0.38128662109375 +97855 0.404449462890625 +97856 0.3944091796875 +97857 0.3885498046875 +97858 0.362640380859375 +97859 0.27362060546875 +97860 0.11712646484375 +97861 -0.054901123046875 +97862 -0.19085693359375 +97863 -0.28570556640625 +97864 -0.339263916015625 +97865 -0.3775634765625 +97866 -0.445709228515625 +97867 -0.535064697265625 +97868 -0.629058837890625 +97869 -0.697601318359375 +97870 -0.70391845703125 +97871 -0.6424560546875 +97872 -0.491241455078125 +97873 -0.265716552734375 +97874 -0.023712158203125 +97875 0.201751708984375 +97876 0.375823974609375 +97877 0.485076904296875 +97878 0.56884765625 +97879 0.634765625 +97880 0.63763427734375 +97881 0.5660400390625 +97882 0.4720458984375 +97883 0.40692138671875 +97884 0.3778076171875 +97885 0.376953125 +97886 0.371978759765625 +97887 0.313140869140625 +97888 0.184417724609375 +97889 0.011199951171875 +97890 -0.171051025390625 +97891 -0.33740234375 +97892 -0.47198486328125 +97893 -0.560394287109375 +97894 -0.58056640625 +97895 -0.54754638671875 +97896 -0.508575439453125 +97897 -0.459503173828125 +97898 -0.394378662109375 +97899 -0.35260009765625 +97900 -0.31170654296875 +97901 -0.197418212890625 +97902 -0.007965087890625 +97903 0.207489013671875 +97904 0.409210205078125 +97905 0.57208251953125 +97906 0.66595458984375 +97907 0.65875244140625 +97908 0.56744384765625 +97909 0.431396484375 +97910 0.29443359375 +97911 0.182464599609375 +97912 0.06365966796875 +97913 -0.075958251953125 +97914 -0.189422607421875 +97915 -0.271942138671875 +97916 -0.342529296875 +97917 -0.364166259765625 +97918 -0.327239990234375 +97919 -0.2769775390625 +97920 -0.253692626953125 +97921 -0.24365234375 +97922 -0.1983642578125 +97923 -0.116241455078125 +97924 -0.036834716796875 +97925 0.034881591796875 +97926 0.09124755859375 +97927 0.10888671875 +97928 0.125518798828125 +97929 0.15771484375 +97930 0.17828369140625 +97931 0.17108154296875 +97932 0.129974365234375 +97933 0.082427978515625 +97934 0.027679443359375 +97935 -0.065643310546875 +97936 -0.15936279296875 +97937 -0.21307373046875 +97938 -0.234649658203125 +97939 -0.2001953125 +97940 -0.119171142578125 +97941 -0.024749755859375 +97942 0.085784912109375 +97943 0.178131103515625 +97944 0.215576171875 +97945 0.211456298828125 +97946 0.17523193359375 +97947 0.128753662109375 +97948 0.1019287109375 +97949 0.0743408203125 +97950 0.04327392578125 +97951 0.038177490234375 +97952 0.076263427734375 +97953 0.14105224609375 +97954 0.186431884765625 +97955 0.188812255859375 +97956 0.1390380859375 +97957 0.041778564453125 +97958 -0.079437255859375 +97959 -0.219390869140625 +97960 -0.367828369140625 +97961 -0.494873046875 +97962 -0.556243896484375 +97963 -0.508697509765625 +97964 -0.3756103515625 +97965 -0.218902587890625 +97966 -0.063751220703125 +97967 0.091552734375 +97968 0.23602294921875 +97969 0.342987060546875 +97970 0.39520263671875 +97971 0.389373779296875 +97972 0.324249267578125 +97973 0.224090576171875 +97974 0.124267578125 +97975 0.037078857421875 +97976 -0.010101318359375 +97977 -0.019439697265625 +97978 -0.022796630859375 +97979 -0.001556396484375 +97980 0.056304931640625 +97981 0.106719970703125 +97982 0.096893310546875 +97983 0.042694091796875 +97984 -0.018035888671875 +97985 -0.07586669921875 +97986 -0.11944580078125 +97987 -0.15972900390625 +97988 -0.202606201171875 +97989 -0.24859619140625 +97990 -0.30517578125 +97991 -0.36212158203125 +97992 -0.39141845703125 +97993 -0.35528564453125 +97994 -0.249969482421875 +97995 -0.092864990234375 +97996 0.08905029296875 +97997 0.2352294921875 +97998 0.318817138671875 +97999 0.358642578125 +98000 0.347747802734375 +98001 0.28564453125 +98002 0.223175048828125 +98003 0.196746826171875 +98004 0.179840087890625 +98005 0.155548095703125 +98006 0.151214599609375 +98007 0.156951904296875 +98008 0.13177490234375 +98009 0.100799560546875 +98010 0.087127685546875 +98011 0.05487060546875 +98012 -0.009002685546875 +98013 -0.10400390625 +98014 -0.229400634765625 +98015 -0.35552978515625 +98016 -0.441925048828125 +98017 -0.473846435546875 +98018 -0.464813232421875 +98019 -0.419097900390625 +98020 -0.334320068359375 +98021 -0.227935791015625 +98022 -0.12347412109375 +98023 -0.02764892578125 +98024 0.077667236328125 +98025 0.2132568359375 +98026 0.38885498046875 +98027 0.582794189453125 +98028 0.734039306640625 +98029 0.800140380859375 +98030 0.7783203125 +98031 0.6651611328125 +98032 0.45965576171875 +98033 0.199188232421875 +98034 -0.050689697265625 +98035 -0.23297119140625 +98036 -0.33013916015625 +98037 -0.368408203125 +98038 -0.378936767578125 +98039 -0.376983642578125 +98040 -0.37969970703125 +98041 -0.391510009765625 +98042 -0.385345458984375 +98043 -0.3419189453125 +98044 -0.28289794921875 +98045 -0.251617431640625 +98046 -0.266143798828125 +98047 -0.273345947265625 +98048 -0.216796875 +98049 -0.128265380859375 +98050 -0.068145751953125 +98051 -0.0430908203125 +98052 -0.024444580078125 +98053 0.020721435546875 +98054 0.124481201171875 +98055 0.25787353515625 +98056 0.379119873046875 +98057 0.47991943359375 +98058 0.5281982421875 +98059 0.511138916015625 +98060 0.456207275390625 +98061 0.407470703125 +98062 0.383758544921875 +98063 0.35687255859375 +98064 0.31182861328125 +98065 0.250885009765625 +98066 0.1654052734375 +98067 0.035247802734375 +98068 -0.142059326171875 +98069 -0.33563232421875 +98070 -0.5345458984375 +98071 -0.72186279296875 +98072 -0.836669921875 +98073 -0.8326416015625 +98074 -0.7296142578125 +98075 -0.582550048828125 +98076 -0.440093994140625 +98077 -0.324310302734375 +98078 -0.20147705078125 +98079 -0.044647216796875 +98080 0.103973388671875 +98081 0.202392578125 +98082 0.264495849609375 +98083 0.338897705078125 +98084 0.443817138671875 +98085 0.545074462890625 +98086 0.6173095703125 +98087 0.6524658203125 +98088 0.66339111328125 +98089 0.6561279296875 +98090 0.606781005859375 +98091 0.501190185546875 +98092 0.352783203125 +98093 0.176544189453125 +98094 -0.034820556640625 +98095 -0.258209228515625 +98096 -0.44244384765625 +98097 -0.5753173828125 +98098 -0.65203857421875 +98099 -0.641632080078125 +98100 -0.562164306640625 +98101 -0.458038330078125 +98102 -0.350555419921875 +98103 -0.260528564453125 +98104 -0.192108154296875 +98105 -0.141937255859375 +98106 -0.1021728515625 +98107 -0.062896728515625 +98108 -0.011932373046875 +98109 0.062835693359375 +98110 0.148712158203125 +98111 0.241729736328125 +98112 0.34912109375 +98113 0.457305908203125 +98114 0.54388427734375 +98115 0.5728759765625 +98116 0.506591796875 +98117 0.351226806640625 +98118 0.146514892578125 +98119 -0.05523681640625 +98120 -0.21624755859375 +98121 -0.334930419921875 +98122 -0.402984619140625 +98123 -0.4412841796875 +98124 -0.49578857421875 +98125 -0.5601806640625 +98126 -0.600738525390625 +98127 -0.584228515625 +98128 -0.47930908203125 +98129 -0.27935791015625 +98130 -0.0089111328125 +98131 0.268798828125 +98132 0.482818603515625 +98133 0.60369873046875 +98134 0.650421142578125 +98135 0.66400146484375 +98136 0.6414794921875 +98137 0.572540283203125 +98138 0.498138427734375 +98139 0.439453125 +98140 0.375518798828125 +98141 0.274505615234375 +98142 0.1087646484375 +98143 -0.099395751953125 +98144 -0.3182373046875 +98145 -0.5489501953125 +98146 -0.7738037109375 +98147 -0.86383056640625 +98148 -0.870391845703125 +98149 -0.86895751953125 +98150 -0.861053466796875 +98151 -0.765869140625 +98152 -0.5301513671875 +98153 -0.214691162109375 +98154 0.137359619140625 +98155 0.474822998046875 +98156 0.76239013671875 +98157 0.867462158203125 +98158 0.870361328125 +98159 0.86480712890625 +98160 0.831817626953125 +98161 0.677581787109375 +98162 0.495880126953125 +98163 0.30767822265625 +98164 0.116180419921875 +98165 -0.110748291015625 +98166 -0.381805419921875 +98167 -0.6572265625 +98168 -0.857421875 +98169 -0.870391845703125 +98170 -0.870391845703125 +98171 -0.86444091796875 +98172 -0.85723876953125 +98173 -0.790008544921875 +98174 -0.62847900390625 +98175 -0.3956298828125 +98176 -0.126708984375 +98177 0.150115966796875 +98178 0.424041748046875 +98179 0.670623779296875 +98180 0.854522705078125 +98181 0.866485595703125 +98182 0.86920166015625 +98183 0.8653564453125 +98184 0.857147216796875 +98185 0.766845703125 +98186 0.628509521484375 +98187 0.462127685546875 +98188 0.297210693359375 +98189 0.14862060546875 +98190 -0.00537109375 +98191 -0.15753173828125 +98192 -0.31304931640625 +98193 -0.48876953125 +98194 -0.6416015625 +98195 -0.751373291015625 +98196 -0.84619140625 +98197 -0.861297607421875 +98198 -0.863250732421875 +98199 -0.856597900390625 +98200 -0.7498779296875 +98201 -0.624542236328125 +98202 -0.47808837890625 +98203 -0.253387451171875 +98204 0.003692626953125 +98205 0.2257080078125 +98206 0.427154541015625 +98207 0.643218994140625 +98208 0.855926513671875 +98209 0.870361328125 +98210 0.870361328125 +98211 0.862762451171875 +98212 0.79669189453125 +98213 0.595794677734375 +98214 0.362152099609375 +98215 0.1270751953125 +98216 -0.086944580078125 +98217 -0.2784423828125 +98218 -0.484832763671875 +98219 -0.729583740234375 +98220 -0.86688232421875 +98221 -0.870391845703125 +98222 -0.86859130859375 +98223 -0.86279296875 +98224 -0.817962646484375 +98225 -0.6116943359375 +98226 -0.3128662109375 +98227 0.039398193359375 +98228 0.422821044921875 +98229 0.805145263671875 +98230 0.870361328125 +98231 0.870361328125 +98232 0.860015869140625 +98233 0.727935791015625 +98234 0.48114013671875 +98235 0.2059326171875 +98236 -0.06103515625 +98237 -0.29913330078125 +98238 -0.516204833984375 +98239 -0.7252197265625 +98240 -0.85980224609375 +98241 -0.870391845703125 +98242 -0.870391845703125 +98243 -0.858062744140625 +98244 -0.673004150390625 +98245 -0.42694091796875 +98246 -0.2100830078125 +98247 -0.0362548828125 +98248 0.10943603515625 +98249 0.23516845703125 +98250 0.373687744140625 +98251 0.517791748046875 +98252 0.602783203125 +98253 0.635711669921875 +98254 0.655181884765625 +98255 0.65948486328125 +98256 0.651275634765625 +98257 0.61846923828125 +98258 0.53753662109375 +98259 0.404144287109375 +98260 0.22186279296875 +98261 0.003997802734375 +98262 -0.22100830078125 +98263 -0.42449951171875 +98264 -0.579833984375 +98265 -0.641876220703125 +98266 -0.6177978515625 +98267 -0.575531005859375 +98268 -0.526336669921875 +98269 -0.42645263671875 +98270 -0.2581787109375 +98271 -0.068695068359375 +98272 0.09222412109375 +98273 0.232147216796875 +98274 0.3509521484375 +98275 0.410064697265625 +98276 0.372955322265625 +98277 0.2554931640625 +98278 0.10711669921875 +98279 -0.052886962890625 +98280 -0.186279296875 +98281 -0.23291015625 +98282 -0.209442138671875 +98283 -0.174163818359375 +98284 -0.126739501953125 +98285 -0.048126220703125 +98286 0.0426025390625 +98287 0.10748291015625 +98288 0.1409912109375 +98289 0.19708251953125 +98290 0.273651123046875 +98291 0.31768798828125 +98292 0.341094970703125 +98293 0.368011474609375 +98294 0.37249755859375 +98295 0.30072021484375 +98296 0.1517333984375 +98297 -0.01470947265625 +98298 -0.1883544921875 +98299 -0.372711181640625 +98300 -0.51397705078125 +98301 -0.57177734375 +98302 -0.53948974609375 +98303 -0.43511962890625 +98304 -0.2962646484375 +98305 -0.161102294921875 +98306 -0.0435791015625 +98307 0.060394287109375 +98308 0.13665771484375 +98309 0.170135498046875 +98310 0.16552734375 +98311 0.15728759765625 +98312 0.150787353515625 +98313 0.12200927734375 +98314 0.080108642578125 +98315 0.05126953125 +98316 0.062896728515625 +98317 0.09271240234375 +98318 0.092987060546875 +98319 0.07855224609375 +98320 0.06427001953125 +98321 0.0347900390625 +98322 -0.01171875 +98323 -0.056060791015625 +98324 -0.055511474609375 +98325 -0.010467529296875 +98326 0.02508544921875 +98327 0.025665283203125 +98328 0.017333984375 +98329 0.00189208984375 +98330 -0.03173828125 +98331 -0.071502685546875 +98332 -0.13543701171875 +98333 -0.219970703125 +98334 -0.300506591796875 +98335 -0.376312255859375 +98336 -0.416107177734375 +98337 -0.371124267578125 +98338 -0.242279052734375 +98339 -0.069732666015625 +98340 0.125640869140625 +98341 0.31268310546875 +98342 0.45501708984375 +98343 0.554779052734375 +98344 0.61065673828125 +98345 0.610931396484375 +98346 0.531463623046875 +98347 0.3883056640625 +98348 0.23468017578125 +98349 0.095245361328125 +98350 -0.00396728515625 +98351 -0.04852294921875 +98352 -0.055145263671875 +98353 -0.0758056640625 +98354 -0.138702392578125 +98355 -0.209197998046875 +98356 -0.289031982421875 +98357 -0.37884521484375 +98358 -0.456329345703125 +98359 -0.51641845703125 +98360 -0.519287109375 +98361 -0.458251953125 +98362 -0.384796142578125 +98363 -0.323699951171875 +98364 -0.269287109375 +98365 -0.1951904296875 +98366 -0.100006103515625 +98367 -0.01055908203125 +98368 0.1033935546875 +98369 0.24908447265625 +98370 0.373199462890625 +98371 0.45806884765625 +98372 0.511474609375 +98373 0.565399169921875 +98374 0.61138916015625 +98375 0.5897216796875 +98376 0.4906005859375 +98377 0.33148193359375 +98378 0.147796630859375 +98379 -0.01873779296875 +98380 -0.140289306640625 +98381 -0.191986083984375 +98382 -0.184295654296875 +98383 -0.161834716796875 +98384 -0.166595458984375 +98385 -0.19390869140625 +98386 -0.22442626953125 +98387 -0.279754638671875 +98388 -0.3389892578125 +98389 -0.3543701171875 +98390 -0.348175048828125 +98391 -0.32598876953125 +98392 -0.2581787109375 +98393 -0.139801025390625 +98394 0.014617919921875 +98395 0.144378662109375 +98396 0.221038818359375 +98397 0.27069091796875 +98398 0.294036865234375 +98399 0.311767578125 +98400 0.339141845703125 +98401 0.360260009765625 +98402 0.360504150390625 +98403 0.308380126953125 +98404 0.18170166015625 +98405 0.0047607421875 +98406 -0.17559814453125 +98407 -0.3143310546875 +98408 -0.36785888671875 +98409 -0.36248779296875 +98410 -0.343536376953125 +98411 -0.3018798828125 +98412 -0.231414794921875 +98413 -0.117645263671875 +98414 0.007049560546875 +98415 0.087982177734375 +98416 0.13946533203125 +98417 0.17425537109375 +98418 0.188201904296875 +98419 0.171234130859375 +98420 0.118438720703125 +98421 0.05706787109375 +98422 -0.010711669921875 +98423 -0.0914306640625 +98424 -0.162322998046875 +98425 -0.194549560546875 +98426 -0.1492919921875 +98427 -0.02166748046875 +98428 0.124053955078125 +98429 0.211151123046875 +98430 0.240447998046875 +98431 0.242218017578125 +98432 0.2257080078125 +98433 0.194366455078125 +98434 0.115509033203125 +98435 0.0128173828125 +98436 -0.053802490234375 +98437 -0.110626220703125 +98438 -0.199493408203125 +98439 -0.29437255859375 +98440 -0.33221435546875 +98441 -0.27972412109375 +98442 -0.185333251953125 +98443 -0.128204345703125 +98444 -0.115692138671875 +98445 -0.116455078125 +98446 -0.105926513671875 +98447 -0.053955078125 +98448 0.048797607421875 +98449 0.157318115234375 +98450 0.212005615234375 +98451 0.218475341796875 +98452 0.23724365234375 +98453 0.30535888671875 +98454 0.38128662109375 +98455 0.404449462890625 +98456 0.3944091796875 +98457 0.3885498046875 +98458 0.362640380859375 +98459 0.27362060546875 +98460 0.11712646484375 +98461 -0.054901123046875 +98462 -0.19085693359375 +98463 -0.28570556640625 +98464 -0.339263916015625 +98465 -0.3775634765625 +98466 -0.445709228515625 +98467 -0.535064697265625 +98468 -0.629058837890625 +98469 -0.697601318359375 +98470 -0.70391845703125 +98471 -0.6424560546875 +98472 -0.491241455078125 +98473 -0.265716552734375 +98474 -0.023712158203125 +98475 0.201751708984375 +98476 0.375823974609375 +98477 0.485076904296875 +98478 0.56884765625 +98479 0.634765625 +98480 0.63763427734375 +98481 0.5660400390625 +98482 0.4720458984375 +98483 0.40692138671875 +98484 0.3778076171875 +98485 0.376953125 +98486 0.371978759765625 +98487 0.313140869140625 +98488 0.184417724609375 +98489 0.011199951171875 +98490 -0.171051025390625 +98491 -0.33740234375 +98492 -0.47198486328125 +98493 -0.560394287109375 +98494 -0.58056640625 +98495 -0.54754638671875 +98496 -0.508575439453125 +98497 -0.459503173828125 +98498 -0.394378662109375 +98499 -0.35260009765625 +98500 -0.31170654296875 +98501 -0.197418212890625 +98502 -0.007965087890625 +98503 0.207489013671875 +98504 0.409210205078125 +98505 0.57208251953125 +98506 0.66595458984375 +98507 0.65875244140625 +98508 0.56744384765625 +98509 0.431396484375 +98510 0.29443359375 +98511 0.182464599609375 +98512 0.06365966796875 +98513 -0.075958251953125 +98514 -0.189422607421875 +98515 -0.271942138671875 +98516 -0.342529296875 +98517 -0.364166259765625 +98518 -0.327239990234375 +98519 -0.2769775390625 +98520 -0.253692626953125 +98521 -0.24365234375 +98522 -0.1983642578125 +98523 -0.116241455078125 +98524 -0.036834716796875 +98525 0.034881591796875 +98526 0.09124755859375 +98527 0.10888671875 +98528 0.125518798828125 +98529 0.15771484375 +98530 0.17828369140625 +98531 0.17108154296875 +98532 0.129974365234375 +98533 0.082427978515625 +98534 0.027679443359375 +98535 -0.065643310546875 +98536 -0.15936279296875 +98537 -0.21307373046875 +98538 -0.234649658203125 +98539 -0.2001953125 +98540 -0.119171142578125 +98541 -0.024749755859375 +98542 0.085784912109375 +98543 0.178131103515625 +98544 0.215576171875 +98545 0.211456298828125 +98546 0.17523193359375 +98547 0.128753662109375 +98548 0.1019287109375 +98549 0.0743408203125 +98550 0.04327392578125 +98551 0.038177490234375 +98552 0.076263427734375 +98553 0.14105224609375 +98554 0.186431884765625 +98555 0.188812255859375 +98556 0.1390380859375 +98557 0.041778564453125 +98558 -0.079437255859375 +98559 -0.219390869140625 +98560 -0.367828369140625 +98561 -0.494873046875 +98562 -0.556243896484375 +98563 -0.508697509765625 +98564 -0.3756103515625 +98565 -0.218902587890625 +98566 -0.063751220703125 +98567 0.091552734375 +98568 0.23602294921875 +98569 0.342987060546875 +98570 0.39520263671875 +98571 0.389373779296875 +98572 0.324249267578125 +98573 0.224090576171875 +98574 0.124267578125 +98575 0.037078857421875 +98576 -0.010101318359375 +98577 -0.019439697265625 +98578 -0.022796630859375 +98579 -0.001556396484375 +98580 0.056304931640625 +98581 0.106719970703125 +98582 0.096893310546875 +98583 0.042694091796875 +98584 -0.018035888671875 +98585 -0.07586669921875 +98586 -0.11944580078125 +98587 -0.15972900390625 +98588 -0.202606201171875 +98589 -0.24859619140625 +98590 -0.30517578125 +98591 -0.36212158203125 +98592 -0.39141845703125 +98593 -0.35528564453125 +98594 -0.249969482421875 +98595 -0.092864990234375 +98596 0.08905029296875 +98597 0.2352294921875 +98598 0.318817138671875 +98599 0.358642578125 +98600 0.347747802734375 +98601 0.28564453125 +98602 0.223175048828125 +98603 0.196746826171875 +98604 0.179840087890625 +98605 0.155548095703125 +98606 0.151214599609375 +98607 0.156951904296875 +98608 0.13177490234375 +98609 0.100799560546875 +98610 0.087127685546875 +98611 0.05487060546875 +98612 -0.009002685546875 +98613 -0.10400390625 +98614 -0.229400634765625 +98615 -0.35552978515625 +98616 -0.441925048828125 +98617 -0.473846435546875 +98618 -0.464813232421875 +98619 -0.419097900390625 +98620 -0.334320068359375 +98621 -0.227935791015625 +98622 -0.12347412109375 +98623 -0.02764892578125 +98624 0.077667236328125 +98625 0.2132568359375 +98626 0.38885498046875 +98627 0.582794189453125 +98628 0.734039306640625 +98629 0.800140380859375 +98630 0.7783203125 +98631 0.6651611328125 +98632 0.45965576171875 +98633 0.199188232421875 +98634 -0.050689697265625 +98635 -0.23297119140625 +98636 -0.33013916015625 +98637 -0.368408203125 +98638 -0.378936767578125 +98639 -0.376983642578125 +98640 -0.37969970703125 +98641 -0.391510009765625 +98642 -0.385345458984375 +98643 -0.3419189453125 +98644 -0.28289794921875 +98645 -0.251617431640625 +98646 -0.266143798828125 +98647 -0.273345947265625 +98648 -0.216796875 +98649 -0.128265380859375 +98650 -0.068145751953125 +98651 -0.0430908203125 +98652 -0.024444580078125 +98653 0.020721435546875 +98654 0.124481201171875 +98655 0.25787353515625 +98656 0.379119873046875 +98657 0.47991943359375 +98658 0.5281982421875 +98659 0.511138916015625 +98660 0.456207275390625 +98661 0.407470703125 +98662 0.383758544921875 +98663 0.35687255859375 +98664 0.31182861328125 +98665 0.250885009765625 +98666 0.1654052734375 +98667 0.035247802734375 +98668 -0.142059326171875 +98669 -0.33563232421875 +98670 -0.5345458984375 +98671 -0.72186279296875 +98672 -0.836669921875 +98673 -0.8326416015625 +98674 -0.7296142578125 +98675 -0.582550048828125 +98676 -0.440093994140625 +98677 -0.324310302734375 +98678 -0.20147705078125 +98679 -0.044647216796875 +98680 0.103973388671875 +98681 0.202392578125 +98682 0.264495849609375 +98683 0.338897705078125 +98684 0.443817138671875 +98685 0.545074462890625 +98686 0.6173095703125 +98687 0.6524658203125 +98688 0.66339111328125 +98689 0.6561279296875 +98690 0.606781005859375 +98691 0.501190185546875 +98692 0.352783203125 +98693 0.176544189453125 +98694 -0.034820556640625 +98695 -0.258209228515625 +98696 -0.44244384765625 +98697 -0.5753173828125 +98698 -0.65203857421875 +98699 -0.641632080078125 +98700 -0.562164306640625 +98701 -0.458038330078125 +98702 -0.350555419921875 +98703 -0.260528564453125 +98704 -0.192108154296875 +98705 -0.141937255859375 +98706 -0.1021728515625 +98707 -0.062896728515625 +98708 -0.011932373046875 +98709 0.062835693359375 +98710 0.148712158203125 +98711 0.241729736328125 +98712 0.34912109375 +98713 0.457305908203125 +98714 0.54388427734375 +98715 0.5728759765625 +98716 0.506591796875 +98717 0.351226806640625 +98718 0.146514892578125 +98719 -0.05523681640625 +98720 -0.21624755859375 +98721 -0.334930419921875 +98722 -0.402984619140625 +98723 -0.4412841796875 +98724 -0.49578857421875 +98725 -0.5601806640625 +98726 -0.600738525390625 +98727 -0.584228515625 +98728 -0.47930908203125 +98729 -0.27935791015625 +98730 -0.0089111328125 +98731 0.268798828125 +98732 0.482818603515625 +98733 0.60369873046875 +98734 0.650421142578125 +98735 0.66400146484375 +98736 0.6414794921875 +98737 0.572540283203125 +98738 0.498138427734375 +98739 0.439453125 +98740 0.375518798828125 +98741 0.274505615234375 +98742 0.1087646484375 +98743 -0.099395751953125 +98744 -0.3182373046875 +98745 -0.5489501953125 +98746 -0.7738037109375 +98747 -0.86383056640625 +98748 -0.870391845703125 +98749 -0.86895751953125 +98750 -0.861053466796875 +98751 -0.765869140625 +98752 -0.5301513671875 +98753 -0.214691162109375 +98754 0.137359619140625 +98755 0.474822998046875 +98756 0.76239013671875 +98757 0.867462158203125 +98758 0.870361328125 +98759 0.86480712890625 +98760 0.831817626953125 +98761 0.677581787109375 +98762 0.495880126953125 +98763 0.30767822265625 +98764 0.116180419921875 +98765 -0.110748291015625 +98766 -0.381805419921875 +98767 -0.6572265625 +98768 -0.857421875 +98769 -0.870391845703125 +98770 -0.870391845703125 +98771 -0.86444091796875 +98772 -0.85723876953125 +98773 -0.790008544921875 +98774 -0.62847900390625 +98775 -0.3956298828125 +98776 -0.126708984375 +98777 0.150115966796875 +98778 0.424041748046875 +98779 0.670623779296875 +98780 0.854522705078125 +98781 0.866485595703125 +98782 0.86920166015625 +98783 0.8653564453125 +98784 0.857147216796875 +98785 0.766845703125 +98786 0.628509521484375 +98787 0.462127685546875 +98788 0.297210693359375 +98789 0.14862060546875 +98790 -0.00537109375 +98791 -0.15753173828125 +98792 -0.31304931640625 +98793 -0.48876953125 +98794 -0.6416015625 +98795 -0.751373291015625 +98796 -0.84619140625 +98797 -0.861297607421875 +98798 -0.863250732421875 +98799 -0.856597900390625 +98800 -0.7498779296875 +98801 -0.624542236328125 +98802 -0.47808837890625 +98803 -0.253387451171875 +98804 0.003692626953125 +98805 0.2257080078125 +98806 0.427154541015625 +98807 0.643218994140625 +98808 0.855926513671875 +98809 0.870361328125 +98810 0.870361328125 +98811 0.862762451171875 +98812 0.79669189453125 +98813 0.595794677734375 +98814 0.362152099609375 +98815 0.1270751953125 +98816 -0.086944580078125 +98817 -0.2784423828125 +98818 -0.484832763671875 +98819 -0.729583740234375 +98820 -0.86688232421875 +98821 -0.870391845703125 +98822 -0.86859130859375 +98823 -0.86279296875 +98824 -0.817962646484375 +98825 -0.6116943359375 +98826 -0.3128662109375 +98827 0.039398193359375 +98828 0.422821044921875 +98829 0.805145263671875 +98830 0.870361328125 +98831 0.870361328125 +98832 0.860015869140625 +98833 0.727935791015625 +98834 0.48114013671875 +98835 0.2059326171875 +98836 -0.06103515625 +98837 -0.29913330078125 +98838 -0.516204833984375 +98839 -0.7252197265625 +98840 -0.85980224609375 +98841 -0.870391845703125 +98842 -0.870391845703125 +98843 -0.858062744140625 +98844 -0.673004150390625 +98845 -0.42694091796875 +98846 -0.2100830078125 +98847 -0.0362548828125 +98848 0.10943603515625 +98849 0.23516845703125 +98850 0.373687744140625 +98851 0.517791748046875 +98852 0.602783203125 +98853 0.635711669921875 +98854 0.655181884765625 +98855 0.65948486328125 +98856 0.651275634765625 +98857 0.61846923828125 +98858 0.53753662109375 +98859 0.404144287109375 +98860 0.22186279296875 +98861 0.003997802734375 +98862 -0.22100830078125 +98863 -0.42449951171875 +98864 -0.579833984375 +98865 -0.641876220703125 +98866 -0.6177978515625 +98867 -0.575531005859375 +98868 -0.526336669921875 +98869 -0.42645263671875 +98870 -0.2581787109375 +98871 -0.068695068359375 +98872 0.09222412109375 +98873 0.232147216796875 +98874 0.3509521484375 +98875 0.410064697265625 +98876 0.372955322265625 +98877 0.2554931640625 +98878 0.10711669921875 +98879 -0.052886962890625 +98880 -0.186279296875 +98881 -0.23291015625 +98882 -0.209442138671875 +98883 -0.174163818359375 +98884 -0.126739501953125 +98885 -0.048126220703125 +98886 0.0426025390625 +98887 0.10748291015625 +98888 0.1409912109375 +98889 0.19708251953125 +98890 0.273651123046875 +98891 0.31768798828125 +98892 0.341094970703125 +98893 0.368011474609375 +98894 0.37249755859375 +98895 0.30072021484375 +98896 0.1517333984375 +98897 -0.01470947265625 +98898 -0.1883544921875 +98899 -0.372711181640625 +98900 -0.51397705078125 +98901 -0.57177734375 +98902 -0.53948974609375 +98903 -0.43511962890625 +98904 -0.2962646484375 +98905 -0.161102294921875 +98906 -0.0435791015625 +98907 0.060394287109375 +98908 0.13665771484375 +98909 0.170135498046875 +98910 0.16552734375 +98911 0.15728759765625 +98912 0.150787353515625 +98913 0.12200927734375 +98914 0.080108642578125 +98915 0.05126953125 +98916 0.062896728515625 +98917 0.09271240234375 +98918 0.092987060546875 +98919 0.07855224609375 +98920 0.06427001953125 +98921 0.0347900390625 +98922 -0.01171875 +98923 -0.056060791015625 +98924 -0.055511474609375 +98925 -0.010467529296875 +98926 0.02508544921875 +98927 0.025665283203125 +98928 0.017333984375 +98929 0.00189208984375 +98930 -0.03173828125 +98931 -0.071502685546875 +98932 -0.13543701171875 +98933 -0.219970703125 +98934 -0.300506591796875 +98935 -0.376312255859375 +98936 -0.416107177734375 +98937 -0.371124267578125 +98938 -0.242279052734375 +98939 -0.069732666015625 +98940 0.125640869140625 +98941 0.31268310546875 +98942 0.45501708984375 +98943 0.554779052734375 +98944 0.61065673828125 +98945 0.610931396484375 +98946 0.531463623046875 +98947 0.3883056640625 +98948 0.23468017578125 +98949 0.095245361328125 +98950 -0.00396728515625 +98951 -0.04852294921875 +98952 -0.055145263671875 +98953 -0.0758056640625 +98954 -0.138702392578125 +98955 -0.209197998046875 +98956 -0.289031982421875 +98957 -0.37884521484375 +98958 -0.456329345703125 +98959 -0.51641845703125 +98960 -0.519287109375 +98961 -0.458251953125 +98962 -0.384796142578125 +98963 -0.323699951171875 +98964 -0.269287109375 +98965 -0.1951904296875 +98966 -0.100006103515625 +98967 -0.01055908203125 +98968 0.1033935546875 +98969 0.24908447265625 +98970 0.373199462890625 +98971 0.45806884765625 +98972 0.511474609375 +98973 0.565399169921875 +98974 0.61138916015625 +98975 0.5897216796875 +98976 0.4906005859375 +98977 0.33148193359375 +98978 0.147796630859375 +98979 -0.01873779296875 +98980 -0.140289306640625 +98981 -0.191986083984375 +98982 -0.184295654296875 +98983 -0.161834716796875 +98984 -0.166595458984375 +98985 -0.19390869140625 +98986 -0.22442626953125 +98987 -0.279754638671875 +98988 -0.3389892578125 +98989 -0.3543701171875 +98990 -0.348175048828125 +98991 -0.32598876953125 +98992 -0.2581787109375 +98993 -0.139801025390625 +98994 0.014617919921875 +98995 0.144378662109375 +98996 0.221038818359375 +98997 0.27069091796875 +98998 0.294036865234375 +98999 0.311767578125 +99000 0.339141845703125 +99001 0.360260009765625 +99002 0.360504150390625 +99003 0.308380126953125 +99004 0.18170166015625 +99005 0.0047607421875 +99006 -0.17559814453125 +99007 -0.3143310546875 +99008 -0.36785888671875 +99009 -0.36248779296875 +99010 -0.343536376953125 +99011 -0.3018798828125 +99012 -0.231414794921875 +99013 -0.117645263671875 +99014 0.007049560546875 +99015 0.087982177734375 +99016 0.13946533203125 +99017 0.17425537109375 +99018 0.188201904296875 +99019 0.171234130859375 +99020 0.118438720703125 +99021 0.05706787109375 +99022 -0.010711669921875 +99023 -0.0914306640625 +99024 -0.162322998046875 +99025 -0.194549560546875 +99026 -0.1492919921875 +99027 -0.02166748046875 +99028 0.124053955078125 +99029 0.211151123046875 +99030 0.240447998046875 +99031 0.242218017578125 +99032 0.2257080078125 +99033 0.194366455078125 +99034 0.115509033203125 +99035 0.0128173828125 +99036 -0.053802490234375 +99037 -0.110626220703125 +99038 -0.199493408203125 +99039 -0.29437255859375 +99040 -0.33221435546875 +99041 -0.27972412109375 +99042 -0.185333251953125 +99043 -0.128204345703125 +99044 -0.115692138671875 +99045 -0.116455078125 +99046 -0.105926513671875 +99047 -0.053955078125 +99048 0.048797607421875 +99049 0.157318115234375 +99050 0.212005615234375 +99051 0.218475341796875 +99052 0.23724365234375 +99053 0.30535888671875 +99054 0.38128662109375 +99055 0.404449462890625 +99056 0.3944091796875 +99057 0.3885498046875 +99058 0.362640380859375 +99059 0.27362060546875 +99060 0.11712646484375 +99061 -0.054901123046875 +99062 -0.19085693359375 +99063 -0.28570556640625 +99064 -0.339263916015625 +99065 -0.3775634765625 +99066 -0.445709228515625 +99067 -0.535064697265625 +99068 -0.629058837890625 +99069 -0.697601318359375 +99070 -0.70391845703125 +99071 -0.6424560546875 +99072 -0.491241455078125 +99073 -0.265716552734375 +99074 -0.023712158203125 +99075 0.201751708984375 +99076 0.375823974609375 +99077 0.485076904296875 +99078 0.56884765625 +99079 0.634765625 +99080 0.63763427734375 +99081 0.5660400390625 +99082 0.4720458984375 +99083 0.40692138671875 +99084 0.3778076171875 +99085 0.376953125 +99086 0.371978759765625 +99087 0.313140869140625 +99088 0.184417724609375 +99089 0.011199951171875 +99090 -0.171051025390625 +99091 -0.33740234375 +99092 -0.47198486328125 +99093 -0.560394287109375 +99094 -0.58056640625 +99095 -0.54754638671875 +99096 -0.508575439453125 +99097 -0.459503173828125 +99098 -0.394378662109375 +99099 -0.35260009765625 +99100 -0.31170654296875 +99101 -0.197418212890625 +99102 -0.007965087890625 +99103 0.207489013671875 +99104 0.409210205078125 +99105 0.57208251953125 +99106 0.66595458984375 +99107 0.65875244140625 +99108 0.56744384765625 +99109 0.431396484375 +99110 0.29443359375 +99111 0.182464599609375 +99112 0.06365966796875 +99113 -0.075958251953125 +99114 -0.189422607421875 +99115 -0.271942138671875 +99116 -0.342529296875 +99117 -0.364166259765625 +99118 -0.327239990234375 +99119 -0.2769775390625 +99120 -0.253692626953125 +99121 -0.24365234375 +99122 -0.1983642578125 +99123 -0.116241455078125 +99124 -0.036834716796875 +99125 0.034881591796875 +99126 0.09124755859375 +99127 0.10888671875 +99128 0.125518798828125 +99129 0.15771484375 +99130 0.17828369140625 +99131 0.17108154296875 +99132 0.129974365234375 +99133 0.082427978515625 +99134 0.027679443359375 +99135 -0.065643310546875 +99136 -0.15936279296875 +99137 -0.21307373046875 +99138 -0.234649658203125 +99139 -0.2001953125 +99140 -0.119171142578125 +99141 -0.024749755859375 +99142 0.085784912109375 +99143 0.178131103515625 +99144 0.215576171875 +99145 0.211456298828125 +99146 0.17523193359375 +99147 0.128753662109375 +99148 0.1019287109375 +99149 0.0743408203125 +99150 0.04327392578125 +99151 0.038177490234375 +99152 0.076263427734375 +99153 0.14105224609375 +99154 0.186431884765625 +99155 0.188812255859375 +99156 0.1390380859375 +99157 0.041778564453125 +99158 -0.079437255859375 +99159 -0.219390869140625 +99160 -0.367828369140625 +99161 -0.494873046875 +99162 -0.556243896484375 +99163 -0.508697509765625 +99164 -0.3756103515625 +99165 -0.218902587890625 +99166 -0.063751220703125 +99167 0.091552734375 +99168 0.23602294921875 +99169 0.342987060546875 +99170 0.39520263671875 +99171 0.389373779296875 +99172 0.324249267578125 +99173 0.224090576171875 +99174 0.124267578125 +99175 0.037078857421875 +99176 -0.010101318359375 +99177 -0.019439697265625 +99178 -0.022796630859375 +99179 -0.001556396484375 +99180 0.056304931640625 +99181 0.106719970703125 +99182 0.096893310546875 +99183 0.042694091796875 +99184 -0.018035888671875 +99185 -0.07586669921875 +99186 -0.11944580078125 +99187 -0.15972900390625 +99188 -0.202606201171875 +99189 -0.24859619140625 +99190 -0.30517578125 +99191 -0.36212158203125 +99192 -0.39141845703125 +99193 -0.35528564453125 +99194 -0.249969482421875 +99195 -0.092864990234375 +99196 0.08905029296875 +99197 0.2352294921875 +99198 0.318817138671875 +99199 0.358642578125 +99200 0.347747802734375 +99201 0.28564453125 +99202 0.223175048828125 +99203 0.196746826171875 +99204 0.179840087890625 +99205 0.155548095703125 +99206 0.151214599609375 +99207 0.156951904296875 +99208 0.13177490234375 +99209 0.100799560546875 +99210 0.087127685546875 +99211 0.05487060546875 +99212 -0.009002685546875 +99213 -0.10400390625 +99214 -0.229400634765625 +99215 -0.35552978515625 +99216 -0.441925048828125 +99217 -0.473846435546875 +99218 -0.464813232421875 +99219 -0.419097900390625 +99220 -0.334320068359375 +99221 -0.227935791015625 +99222 -0.12347412109375 +99223 -0.02764892578125 +99224 0.077667236328125 +99225 0.2132568359375 +99226 0.38885498046875 +99227 0.582794189453125 +99228 0.734039306640625 +99229 0.800140380859375 +99230 0.7783203125 +99231 0.6651611328125 +99232 0.45965576171875 +99233 0.199188232421875 +99234 -0.050689697265625 +99235 -0.23297119140625 +99236 -0.33013916015625 +99237 -0.368408203125 +99238 -0.378936767578125 +99239 -0.376983642578125 +99240 -0.37969970703125 +99241 -0.391510009765625 +99242 -0.385345458984375 +99243 -0.3419189453125 +99244 -0.28289794921875 +99245 -0.251617431640625 +99246 -0.266143798828125 +99247 -0.273345947265625 +99248 -0.216796875 +99249 -0.128265380859375 +99250 -0.068145751953125 +99251 -0.0430908203125 +99252 -0.024444580078125 +99253 0.020721435546875 +99254 0.124481201171875 +99255 0.25787353515625 +99256 0.379119873046875 +99257 0.47991943359375 +99258 0.5281982421875 +99259 0.511138916015625 +99260 0.456207275390625 +99261 0.407470703125 +99262 0.383758544921875 +99263 0.35687255859375 +99264 0.31182861328125 +99265 0.250885009765625 +99266 0.1654052734375 +99267 0.035247802734375 +99268 -0.142059326171875 +99269 -0.33563232421875 +99270 -0.5345458984375 +99271 -0.72186279296875 +99272 -0.836669921875 +99273 -0.8326416015625 +99274 -0.7296142578125 +99275 -0.582550048828125 +99276 -0.440093994140625 +99277 -0.324310302734375 +99278 -0.20147705078125 +99279 -0.044647216796875 +99280 0.103973388671875 +99281 0.202392578125 +99282 0.264495849609375 +99283 0.338897705078125 +99284 0.443817138671875 +99285 0.545074462890625 +99286 0.6173095703125 +99287 0.6524658203125 +99288 0.66339111328125 +99289 0.6561279296875 +99290 0.606781005859375 +99291 0.501190185546875 +99292 0.352783203125 +99293 0.176544189453125 +99294 -0.034820556640625 +99295 -0.258209228515625 +99296 -0.44244384765625 +99297 -0.5753173828125 +99298 -0.65203857421875 +99299 -0.641632080078125 +99300 -0.562164306640625 +99301 -0.458038330078125 +99302 -0.350555419921875 +99303 -0.260528564453125 +99304 -0.192108154296875 +99305 -0.141937255859375 +99306 -0.1021728515625 +99307 -0.062896728515625 +99308 -0.011932373046875 +99309 0.062835693359375 +99310 0.148712158203125 +99311 0.241729736328125 +99312 0.34912109375 +99313 0.457305908203125 +99314 0.54388427734375 +99315 0.5728759765625 +99316 0.506591796875 +99317 0.351226806640625 +99318 0.146514892578125 +99319 -0.05523681640625 +99320 -0.21624755859375 +99321 -0.334930419921875 +99322 -0.402984619140625 +99323 -0.4412841796875 +99324 -0.49578857421875 +99325 -0.5601806640625 +99326 -0.600738525390625 +99327 -0.584228515625 +99328 -0.47930908203125 +99329 -0.27935791015625 +99330 -0.0089111328125 +99331 0.268798828125 +99332 0.482818603515625 +99333 0.60369873046875 +99334 0.650421142578125 +99335 0.66400146484375 +99336 0.6414794921875 +99337 0.572540283203125 +99338 0.498138427734375 +99339 0.439453125 +99340 0.375518798828125 +99341 0.274505615234375 +99342 0.1087646484375 +99343 -0.099395751953125 +99344 -0.3182373046875 +99345 -0.5489501953125 +99346 -0.7738037109375 +99347 -0.86383056640625 +99348 -0.870391845703125 +99349 -0.86895751953125 +99350 -0.861053466796875 +99351 -0.765869140625 +99352 -0.5301513671875 +99353 -0.214691162109375 +99354 0.137359619140625 +99355 0.474822998046875 +99356 0.76239013671875 +99357 0.867462158203125 +99358 0.870361328125 +99359 0.86480712890625 +99360 0.831817626953125 +99361 0.677581787109375 +99362 0.495880126953125 +99363 0.30767822265625 +99364 0.116180419921875 +99365 -0.110748291015625 +99366 -0.381805419921875 +99367 -0.6572265625 +99368 -0.857421875 +99369 -0.870391845703125 +99370 -0.870391845703125 +99371 -0.86444091796875 +99372 -0.85723876953125 +99373 -0.790008544921875 +99374 -0.62847900390625 +99375 -0.3956298828125 +99376 -0.126708984375 +99377 0.150115966796875 +99378 0.424041748046875 +99379 0.670623779296875 +99380 0.854522705078125 +99381 0.866485595703125 +99382 0.86920166015625 +99383 0.8653564453125 +99384 0.857147216796875 +99385 0.766845703125 +99386 0.628509521484375 +99387 0.462127685546875 +99388 0.297210693359375 +99389 0.14862060546875 +99390 -0.00537109375 +99391 -0.15753173828125 +99392 -0.31304931640625 +99393 -0.48876953125 +99394 -0.6416015625 +99395 -0.751373291015625 +99396 -0.84619140625 +99397 -0.861297607421875 +99398 -0.863250732421875 +99399 -0.856597900390625 +99400 -0.7498779296875 +99401 -0.624542236328125 +99402 -0.47808837890625 +99403 -0.253387451171875 +99404 0.003692626953125 +99405 0.2257080078125 +99406 0.427154541015625 +99407 0.643218994140625 +99408 0.855926513671875 +99409 0.870361328125 +99410 0.870361328125 +99411 0.862762451171875 +99412 0.79669189453125 +99413 0.595794677734375 +99414 0.362152099609375 +99415 0.1270751953125 +99416 -0.086944580078125 +99417 -0.2784423828125 +99418 -0.484832763671875 +99419 -0.729583740234375 +99420 -0.86688232421875 +99421 -0.870391845703125 +99422 -0.86859130859375 +99423 -0.86279296875 +99424 -0.817962646484375 +99425 -0.6116943359375 +99426 -0.3128662109375 +99427 0.039398193359375 +99428 0.422821044921875 +99429 0.805145263671875 +99430 0.870361328125 +99431 0.870361328125 +99432 0.860015869140625 +99433 0.727935791015625 +99434 0.48114013671875 +99435 0.2059326171875 +99436 -0.06103515625 +99437 -0.29913330078125 +99438 -0.516204833984375 +99439 -0.7252197265625 +99440 -0.85980224609375 +99441 -0.870391845703125 +99442 -0.870391845703125 +99443 -0.858062744140625 +99444 -0.673004150390625 +99445 -0.42694091796875 +99446 -0.2100830078125 +99447 -0.0362548828125 +99448 0.10943603515625 +99449 0.23516845703125 +99450 0.373687744140625 +99451 0.517791748046875 +99452 0.602783203125 +99453 0.635711669921875 +99454 0.655181884765625 +99455 0.65948486328125 +99456 0.651275634765625 +99457 0.61846923828125 +99458 0.53753662109375 +99459 0.404144287109375 +99460 0.22186279296875 +99461 0.003997802734375 +99462 -0.22100830078125 +99463 -0.42449951171875 +99464 -0.579833984375 +99465 -0.641876220703125 +99466 -0.6177978515625 +99467 -0.575531005859375 +99468 -0.526336669921875 +99469 -0.42645263671875 +99470 -0.2581787109375 +99471 -0.068695068359375 +99472 0.09222412109375 +99473 0.232147216796875 +99474 0.3509521484375 +99475 0.410064697265625 +99476 0.372955322265625 +99477 0.2554931640625 +99478 0.10711669921875 +99479 -0.052886962890625 +99480 -0.186279296875 +99481 -0.23291015625 +99482 -0.209442138671875 +99483 -0.174163818359375 +99484 -0.126739501953125 +99485 -0.048126220703125 +99486 0.0426025390625 +99487 0.10748291015625 +99488 0.1409912109375 +99489 0.19708251953125 +99490 0.273651123046875 +99491 0.31768798828125 +99492 0.341094970703125 +99493 0.368011474609375 +99494 0.37249755859375 +99495 0.30072021484375 +99496 0.1517333984375 +99497 -0.01470947265625 +99498 -0.1883544921875 +99499 -0.372711181640625 +99500 -0.51397705078125 +99501 -0.57177734375 +99502 -0.53948974609375 +99503 -0.43511962890625 +99504 -0.2962646484375 +99505 -0.161102294921875 +99506 -0.0435791015625 +99507 0.060394287109375 +99508 0.13665771484375 +99509 0.170135498046875 +99510 0.16552734375 +99511 0.15728759765625 +99512 0.150787353515625 +99513 0.12200927734375 +99514 0.080108642578125 +99515 0.05126953125 +99516 0.062896728515625 +99517 0.09271240234375 +99518 0.092987060546875 +99519 0.07855224609375 +99520 0.06427001953125 +99521 0.0347900390625 +99522 -0.01171875 +99523 -0.056060791015625 +99524 -0.055511474609375 +99525 -0.010467529296875 +99526 0.02508544921875 +99527 0.025665283203125 +99528 0.017333984375 +99529 0.00189208984375 +99530 -0.03173828125 +99531 -0.071502685546875 +99532 -0.13543701171875 +99533 -0.219970703125 +99534 -0.300506591796875 +99535 -0.376312255859375 +99536 -0.416107177734375 +99537 -0.371124267578125 +99538 -0.242279052734375 +99539 -0.069732666015625 +99540 0.125640869140625 +99541 0.31268310546875 +99542 0.45501708984375 +99543 0.554779052734375 +99544 0.61065673828125 +99545 0.610931396484375 +99546 0.531463623046875 +99547 0.3883056640625 +99548 0.23468017578125 +99549 0.095245361328125 +99550 -0.00396728515625 +99551 -0.04852294921875 +99552 -0.055145263671875 +99553 -0.0758056640625 +99554 -0.138702392578125 +99555 -0.209197998046875 +99556 -0.289031982421875 +99557 -0.37884521484375 +99558 -0.456329345703125 +99559 -0.51641845703125 +99560 -0.519287109375 +99561 -0.458251953125 +99562 -0.384796142578125 +99563 -0.323699951171875 +99564 -0.269287109375 +99565 -0.1951904296875 +99566 -0.100006103515625 +99567 -0.01055908203125 +99568 0.1033935546875 +99569 0.24908447265625 +99570 0.373199462890625 +99571 0.45806884765625 +99572 0.511474609375 +99573 0.565399169921875 +99574 0.61138916015625 +99575 0.5897216796875 +99576 0.4906005859375 +99577 0.33148193359375 +99578 0.147796630859375 +99579 -0.01873779296875 +99580 -0.140289306640625 +99581 -0.191986083984375 +99582 -0.184295654296875 +99583 -0.161834716796875 +99584 -0.166595458984375 +99585 -0.19390869140625 +99586 -0.22442626953125 +99587 -0.279754638671875 +99588 -0.3389892578125 +99589 -0.3543701171875 +99590 -0.348175048828125 +99591 -0.32598876953125 +99592 -0.2581787109375 +99593 -0.139801025390625 +99594 0.014617919921875 +99595 0.144378662109375 +99596 0.221038818359375 +99597 0.27069091796875 +99598 0.294036865234375 +99599 0.311767578125 +99600 0.339141845703125 +99601 0.360260009765625 +99602 0.360504150390625 +99603 0.308380126953125 +99604 0.18170166015625 +99605 0.0047607421875 +99606 -0.17559814453125 +99607 -0.3143310546875 +99608 -0.36785888671875 +99609 -0.36248779296875 +99610 -0.343536376953125 +99611 -0.3018798828125 +99612 -0.231414794921875 +99613 -0.117645263671875 +99614 0.007049560546875 +99615 0.087982177734375 +99616 0.13946533203125 +99617 0.17425537109375 +99618 0.188201904296875 +99619 0.171234130859375 +99620 0.118438720703125 +99621 0.05706787109375 +99622 -0.010711669921875 +99623 -0.0914306640625 +99624 -0.162322998046875 +99625 -0.194549560546875 +99626 -0.1492919921875 +99627 -0.02166748046875 +99628 0.124053955078125 +99629 0.211151123046875 +99630 0.240447998046875 +99631 0.242218017578125 +99632 0.2257080078125 +99633 0.194366455078125 +99634 0.115509033203125 +99635 0.0128173828125 +99636 -0.053802490234375 +99637 -0.110626220703125 +99638 -0.199493408203125 +99639 -0.29437255859375 +99640 -0.33221435546875 +99641 -0.27972412109375 +99642 -0.185333251953125 +99643 -0.128204345703125 +99644 -0.115692138671875 +99645 -0.116455078125 +99646 -0.105926513671875 +99647 -0.053955078125 +99648 0.048797607421875 +99649 0.157318115234375 +99650 0.212005615234375 +99651 0.218475341796875 +99652 0.23724365234375 +99653 0.30535888671875 +99654 0.38128662109375 +99655 0.404449462890625 +99656 0.3944091796875 +99657 0.3885498046875 +99658 0.362640380859375 +99659 0.27362060546875 +99660 0.11712646484375 +99661 -0.054901123046875 +99662 -0.19085693359375 +99663 -0.28570556640625 +99664 -0.339263916015625 +99665 -0.3775634765625 +99666 -0.445709228515625 +99667 -0.535064697265625 +99668 -0.629058837890625 +99669 -0.697601318359375 +99670 -0.70391845703125 +99671 -0.6424560546875 +99672 -0.491241455078125 +99673 -0.265716552734375 +99674 -0.023712158203125 +99675 0.201751708984375 +99676 0.375823974609375 +99677 0.485076904296875 +99678 0.56884765625 +99679 0.634765625 +99680 0.63763427734375 +99681 0.5660400390625 +99682 0.4720458984375 +99683 0.40692138671875 +99684 0.3778076171875 +99685 0.376953125 +99686 0.371978759765625 +99687 0.313140869140625 +99688 0.184417724609375 +99689 0.011199951171875 +99690 -0.171051025390625 +99691 -0.33740234375 +99692 -0.47198486328125 +99693 -0.560394287109375 +99694 -0.58056640625 +99695 -0.54754638671875 +99696 -0.508575439453125 +99697 -0.459503173828125 +99698 -0.394378662109375 +99699 -0.35260009765625 +99700 -0.31170654296875 +99701 -0.197418212890625 +99702 -0.007965087890625 +99703 0.207489013671875 +99704 0.409210205078125 +99705 0.57208251953125 +99706 0.66595458984375 +99707 0.65875244140625 +99708 0.56744384765625 +99709 0.431396484375 +99710 0.29443359375 +99711 0.182464599609375 +99712 0.06365966796875 +99713 -0.075958251953125 +99714 -0.189422607421875 +99715 -0.271942138671875 +99716 -0.342529296875 +99717 -0.364166259765625 +99718 -0.327239990234375 +99719 -0.2769775390625 +99720 -0.253692626953125 +99721 -0.24365234375 +99722 -0.1983642578125 +99723 -0.116241455078125 +99724 -0.036834716796875 +99725 0.034881591796875 +99726 0.09124755859375 +99727 0.10888671875 +99728 0.125518798828125 +99729 0.15771484375 +99730 0.17828369140625 +99731 0.17108154296875 +99732 0.129974365234375 +99733 0.082427978515625 +99734 0.027679443359375 +99735 -0.065643310546875 +99736 -0.15936279296875 +99737 -0.21307373046875 +99738 -0.234649658203125 +99739 -0.2001953125 +99740 -0.119171142578125 +99741 -0.024749755859375 +99742 0.085784912109375 +99743 0.178131103515625 +99744 0.215576171875 +99745 0.211456298828125 +99746 0.17523193359375 +99747 0.128753662109375 +99748 0.1019287109375 +99749 0.0743408203125 +99750 0.04327392578125 +99751 0.038177490234375 +99752 0.076263427734375 +99753 0.14105224609375 +99754 0.186431884765625 +99755 0.188812255859375 +99756 0.1390380859375 +99757 0.041778564453125 +99758 -0.079437255859375 +99759 -0.219390869140625 +99760 -0.367828369140625 +99761 -0.494873046875 +99762 -0.556243896484375 +99763 -0.508697509765625 +99764 -0.3756103515625 +99765 -0.218902587890625 +99766 -0.063751220703125 +99767 0.091552734375 +99768 0.23602294921875 +99769 0.342987060546875 +99770 0.39520263671875 +99771 0.389373779296875 +99772 0.324249267578125 +99773 0.224090576171875 +99774 0.124267578125 +99775 0.037078857421875 +99776 -0.010101318359375 +99777 -0.019439697265625 +99778 -0.022796630859375 +99779 -0.001556396484375 +99780 0.056304931640625 +99781 0.106719970703125 +99782 0.096893310546875 +99783 0.042694091796875 +99784 -0.018035888671875 +99785 -0.07586669921875 +99786 -0.11944580078125 +99787 -0.15972900390625 +99788 -0.202606201171875 +99789 -0.24859619140625 +99790 -0.30517578125 +99791 -0.36212158203125 +99792 -0.39141845703125 +99793 -0.35528564453125 +99794 -0.249969482421875 +99795 -0.092864990234375 +99796 0.08905029296875 +99797 0.2352294921875 +99798 0.318817138671875 +99799 0.358642578125 +99800 0.347747802734375 +99801 0.28564453125 +99802 0.223175048828125 +99803 0.196746826171875 +99804 0.179840087890625 +99805 0.155548095703125 +99806 0.151214599609375 +99807 0.156951904296875 +99808 0.13177490234375 +99809 0.100799560546875 +99810 0.087127685546875 +99811 0.05487060546875 +99812 -0.009002685546875 +99813 -0.10400390625 +99814 -0.229400634765625 +99815 -0.35552978515625 +99816 -0.441925048828125 +99817 -0.473846435546875 +99818 -0.464813232421875 +99819 -0.419097900390625 +99820 -0.334320068359375 +99821 -0.227935791015625 +99822 -0.12347412109375 +99823 -0.02764892578125 +99824 0.077667236328125 +99825 0.2132568359375 +99826 0.38885498046875 +99827 0.582794189453125 +99828 0.734039306640625 +99829 0.800140380859375 +99830 0.7783203125 +99831 0.6651611328125 +99832 0.45965576171875 +99833 0.199188232421875 +99834 -0.050689697265625 +99835 -0.23297119140625 +99836 -0.33013916015625 +99837 -0.368408203125 +99838 -0.378936767578125 +99839 -0.376983642578125 +99840 -0.37969970703125 +99841 -0.391510009765625 +99842 -0.385345458984375 +99843 -0.3419189453125 +99844 -0.28289794921875 +99845 -0.251617431640625 +99846 -0.266143798828125 +99847 -0.273345947265625 +99848 -0.216796875 +99849 -0.128265380859375 +99850 -0.068145751953125 +99851 -0.0430908203125 +99852 -0.024444580078125 +99853 0.020721435546875 +99854 0.124481201171875 +99855 0.25787353515625 +99856 0.379119873046875 +99857 0.47991943359375 +99858 0.5281982421875 +99859 0.511138916015625 +99860 0.456207275390625 +99861 0.407470703125 +99862 0.383758544921875 +99863 0.35687255859375 +99864 0.31182861328125 +99865 0.250885009765625 +99866 0.1654052734375 +99867 0.035247802734375 +99868 -0.142059326171875 +99869 -0.33563232421875 +99870 -0.5345458984375 +99871 -0.72186279296875 +99872 -0.836669921875 +99873 -0.8326416015625 +99874 -0.7296142578125 +99875 -0.582550048828125 +99876 -0.440093994140625 +99877 -0.324310302734375 +99878 -0.20147705078125 +99879 -0.044647216796875 +99880 0.103973388671875 +99881 0.202392578125 +99882 0.264495849609375 +99883 0.338897705078125 +99884 0.443817138671875 +99885 0.545074462890625 +99886 0.6173095703125 +99887 0.6524658203125 +99888 0.66339111328125 +99889 0.6561279296875 +99890 0.606781005859375 +99891 0.501190185546875 +99892 0.352783203125 +99893 0.176544189453125 +99894 -0.034820556640625 +99895 -0.258209228515625 +99896 -0.44244384765625 +99897 -0.5753173828125 +99898 -0.65203857421875 +99899 -0.641632080078125 +99900 -0.562164306640625 +99901 -0.458038330078125 +99902 -0.350555419921875 +99903 -0.260528564453125 +99904 -0.192108154296875 +99905 -0.141937255859375 +99906 -0.1021728515625 +99907 -0.062896728515625 +99908 -0.011932373046875 +99909 0.062835693359375 +99910 0.148712158203125 +99911 0.241729736328125 +99912 0.34912109375 +99913 0.457305908203125 +99914 0.54388427734375 +99915 0.5728759765625 +99916 0.506591796875 +99917 0.351226806640625 +99918 0.146514892578125 +99919 -0.05523681640625 +99920 -0.21624755859375 +99921 -0.334930419921875 +99922 -0.402984619140625 +99923 -0.4412841796875 +99924 -0.49578857421875 +99925 -0.5601806640625 +99926 -0.600738525390625 +99927 -0.584228515625 +99928 -0.47930908203125 +99929 -0.27935791015625 +99930 -0.0089111328125 +99931 0.268798828125 +99932 0.482818603515625 +99933 0.60369873046875 +99934 0.650421142578125 +99935 0.66400146484375 +99936 0.6414794921875 +99937 0.572540283203125 +99938 0.498138427734375 +99939 0.439453125 +99940 0.375518798828125 +99941 0.274505615234375 +99942 0.1087646484375 +99943 -0.099395751953125 +99944 -0.3182373046875 +99945 -0.5489501953125 +99946 -0.7738037109375 +99947 -0.86383056640625 +99948 -0.870391845703125 +99949 -0.86895751953125 +99950 -0.861053466796875 +99951 -0.765869140625 +99952 -0.5301513671875 +99953 -0.214691162109375 +99954 0.137359619140625 +99955 0.474822998046875 +99956 0.76239013671875 +99957 0.867462158203125 +99958 0.870361328125 +99959 0.86480712890625 +99960 0.831817626953125 +99961 0.677581787109375 +99962 0.495880126953125 +99963 0.30767822265625 +99964 0.116180419921875 +99965 -0.110748291015625 +99966 -0.381805419921875 +99967 -0.6572265625 +99968 -0.857421875 +99969 -0.870391845703125 +99970 -0.870391845703125 +99971 -0.86444091796875 +99972 -0.85723876953125 +99973 -0.790008544921875 +99974 -0.62847900390625 +99975 -0.3956298828125 +99976 -0.126708984375 +99977 0.150115966796875 +99978 0.424041748046875 +99979 0.670623779296875 +99980 0.854522705078125 +99981 0.866485595703125 +99982 0.86920166015625 +99983 0.8653564453125 +99984 0.857147216796875 +99985 0.766845703125 +99986 0.628509521484375 +99987 0.462127685546875 +99988 0.297210693359375 +99989 0.14862060546875 +99990 -0.00537109375 +99991 -0.15753173828125 +99992 -0.31304931640625 +99993 -0.48876953125 +99994 -0.6416015625 +99995 -0.751373291015625 +99996 -0.84619140625 +99997 -0.861297607421875 +99998 -0.863250732421875 +99999 -0.856597900390625 +100000 -0.7498779296875 +100001 -0.624542236328125 +100002 -0.47808837890625 +100003 -0.253387451171875 +100004 0.003692626953125 +100005 0.2257080078125 +100006 0.427154541015625 +100007 0.643218994140625 +100008 0.855926513671875 +100009 0.870361328125 +100010 0.870361328125 +100011 0.862762451171875 +100012 0.79669189453125 +100013 0.595794677734375 +100014 0.362152099609375 +100015 0.1270751953125 +100016 -0.086944580078125 +100017 -0.2784423828125 +100018 -0.484832763671875 +100019 -0.729583740234375 +100020 -0.86688232421875 +100021 -0.870391845703125 +100022 -0.86859130859375 +100023 -0.86279296875 +100024 -0.817962646484375 +100025 -0.6116943359375 +100026 -0.3128662109375 +100027 0.039398193359375 +100028 0.422821044921875 +100029 0.805145263671875 +100030 0.870361328125 +100031 0.870361328125 +100032 0.860015869140625 +100033 0.727935791015625 +100034 0.48114013671875 +100035 0.2059326171875 +100036 -0.06103515625 +100037 -0.29913330078125 +100038 -0.516204833984375 +100039 -0.7252197265625 +100040 -0.85980224609375 +100041 -0.870391845703125 +100042 -0.870391845703125 +100043 -0.858062744140625 +100044 -0.673004150390625 +100045 -0.42694091796875 +100046 -0.2100830078125 +100047 -0.0362548828125 +100048 0.10943603515625 +100049 0.23516845703125 +100050 0.373687744140625 +100051 0.517791748046875 +100052 0.602783203125 +100053 0.635711669921875 +100054 0.655181884765625 +100055 0.65948486328125 +100056 0.651275634765625 +100057 0.61846923828125 +100058 0.53753662109375 +100059 0.404144287109375 +100060 0.22186279296875 +100061 0.003997802734375 +100062 -0.22100830078125 +100063 -0.42449951171875 +100064 -0.579833984375 +100065 -0.641876220703125 +100066 -0.6177978515625 +100067 -0.575531005859375 +100068 -0.526336669921875 +100069 -0.42645263671875 +100070 -0.2581787109375 +100071 -0.068695068359375 +100072 0.09222412109375 +100073 0.232147216796875 +100074 0.3509521484375 +100075 0.410064697265625 +100076 0.372955322265625 +100077 0.2554931640625 +100078 0.10711669921875 +100079 -0.052886962890625 +100080 -0.186279296875 +100081 -0.23291015625 +100082 -0.209442138671875 +100083 -0.174163818359375 +100084 -0.126739501953125 +100085 -0.048126220703125 +100086 0.0426025390625 +100087 0.10748291015625 +100088 0.1409912109375 +100089 0.19708251953125 +100090 0.273651123046875 +100091 0.31768798828125 +100092 0.341094970703125 +100093 0.368011474609375 +100094 0.37249755859375 +100095 0.30072021484375 +100096 0.1517333984375 +100097 -0.01470947265625 +100098 -0.1883544921875 +100099 -0.372711181640625 +100100 -0.51397705078125 +100101 -0.57177734375 +100102 -0.53948974609375 +100103 -0.43511962890625 +100104 -0.2962646484375 +100105 -0.161102294921875 +100106 -0.0435791015625 +100107 0.060394287109375 +100108 0.13665771484375 +100109 0.170135498046875 +100110 0.16552734375 +100111 0.15728759765625 +100112 0.150787353515625 +100113 0.12200927734375 +100114 0.080108642578125 +100115 0.05126953125 +100116 0.062896728515625 +100117 0.09271240234375 +100118 0.092987060546875 +100119 0.07855224609375 +100120 0.06427001953125 +100121 0.0347900390625 +100122 -0.01171875 +100123 -0.056060791015625 +100124 -0.055511474609375 +100125 -0.010467529296875 +100126 0.02508544921875 +100127 0.025665283203125 +100128 0.017333984375 +100129 0.00189208984375 +100130 -0.03173828125 +100131 -0.071502685546875 +100132 -0.13543701171875 +100133 -0.219970703125 +100134 -0.300506591796875 +100135 -0.376312255859375 +100136 -0.416107177734375 +100137 -0.371124267578125 +100138 -0.242279052734375 +100139 -0.069732666015625 +100140 0.125640869140625 +100141 0.31268310546875 +100142 0.45501708984375 +100143 0.554779052734375 +100144 0.61065673828125 +100145 0.610931396484375 +100146 0.531463623046875 +100147 0.3883056640625 +100148 0.23468017578125 +100149 0.095245361328125 +100150 -0.00396728515625 +100151 -0.04852294921875 +100152 -0.055145263671875 +100153 -0.0758056640625 +100154 -0.138702392578125 +100155 -0.209197998046875 +100156 -0.289031982421875 +100157 -0.37884521484375 +100158 -0.456329345703125 +100159 -0.51641845703125 +100160 -0.519287109375 +100161 -0.458251953125 +100162 -0.384796142578125 +100163 -0.323699951171875 +100164 -0.269287109375 +100165 -0.1951904296875 +100166 -0.100006103515625 +100167 -0.01055908203125 +100168 0.1033935546875 +100169 0.24908447265625 +100170 0.373199462890625 +100171 0.45806884765625 +100172 0.511474609375 +100173 0.565399169921875 +100174 0.61138916015625 +100175 0.5897216796875 +100176 0.4906005859375 +100177 0.33148193359375 +100178 0.147796630859375 +100179 -0.01873779296875 +100180 -0.140289306640625 +100181 -0.191986083984375 +100182 -0.184295654296875 +100183 -0.161834716796875 +100184 -0.166595458984375 +100185 -0.19390869140625 +100186 -0.22442626953125 +100187 -0.279754638671875 +100188 -0.3389892578125 +100189 -0.3543701171875 +100190 -0.348175048828125 +100191 -0.32598876953125 +100192 -0.2581787109375 +100193 -0.139801025390625 +100194 0.014617919921875 +100195 0.144378662109375 +100196 0.221038818359375 +100197 0.27069091796875 +100198 0.294036865234375 +100199 0.311767578125 +100200 0.339141845703125 +100201 0.360260009765625 +100202 0.360504150390625 +100203 0.308380126953125 +100204 0.18170166015625 +100205 0.0047607421875 +100206 -0.17559814453125 +100207 -0.3143310546875 +100208 -0.36785888671875 +100209 -0.36248779296875 +100210 -0.343536376953125 +100211 -0.3018798828125 +100212 -0.231414794921875 +100213 -0.117645263671875 +100214 0.007049560546875 +100215 0.087982177734375 +100216 0.13946533203125 +100217 0.17425537109375 +100218 0.188201904296875 +100219 0.171234130859375 +100220 0.118438720703125 +100221 0.05706787109375 +100222 -0.010711669921875 +100223 -0.0914306640625 +100224 -0.162322998046875 +100225 -0.194549560546875 +100226 -0.1492919921875 +100227 -0.02166748046875 +100228 0.124053955078125 +100229 0.211151123046875 +100230 0.240447998046875 +100231 0.242218017578125 +100232 0.2257080078125 +100233 0.194366455078125 +100234 0.115509033203125 +100235 0.0128173828125 +100236 -0.053802490234375 +100237 -0.110626220703125 +100238 -0.199493408203125 +100239 -0.29437255859375 +100240 -0.33221435546875 +100241 -0.27972412109375 +100242 -0.185333251953125 +100243 -0.128204345703125 +100244 -0.115692138671875 +100245 -0.116455078125 +100246 -0.105926513671875 +100247 -0.053955078125 +100248 0.048797607421875 +100249 0.157318115234375 +100250 0.212005615234375 +100251 0.218475341796875 +100252 0.23724365234375 +100253 0.30535888671875 +100254 0.38128662109375 +100255 0.404449462890625 +100256 0.3944091796875 +100257 0.3885498046875 +100258 0.362640380859375 +100259 0.27362060546875 +100260 0.11712646484375 +100261 -0.054901123046875 +100262 -0.19085693359375 +100263 -0.28570556640625 +100264 -0.339263916015625 +100265 -0.3775634765625 +100266 -0.445709228515625 +100267 -0.535064697265625 +100268 -0.629058837890625 +100269 -0.697601318359375 +100270 -0.70391845703125 +100271 -0.6424560546875 +100272 -0.491241455078125 +100273 -0.265716552734375 +100274 -0.023712158203125 +100275 0.201751708984375 +100276 0.375823974609375 +100277 0.485076904296875 +100278 0.56884765625 +100279 0.634765625 +100280 0.63763427734375 +100281 0.5660400390625 +100282 0.4720458984375 +100283 0.40692138671875 +100284 0.3778076171875 +100285 0.376953125 +100286 0.371978759765625 +100287 0.313140869140625 +100288 0.184417724609375 +100289 0.011199951171875 +100290 -0.171051025390625 +100291 -0.33740234375 +100292 -0.47198486328125 +100293 -0.560394287109375 +100294 -0.58056640625 +100295 -0.54754638671875 +100296 -0.508575439453125 +100297 -0.459503173828125 +100298 -0.394378662109375 +100299 -0.35260009765625 +100300 -0.31170654296875 +100301 -0.197418212890625 +100302 -0.007965087890625 +100303 0.207489013671875 +100304 0.409210205078125 +100305 0.57208251953125 +100306 0.66595458984375 +100307 0.65875244140625 +100308 0.56744384765625 +100309 0.431396484375 +100310 0.29443359375 +100311 0.182464599609375 +100312 0.06365966796875 +100313 -0.075958251953125 +100314 -0.189422607421875 +100315 -0.271942138671875 +100316 -0.342529296875 +100317 -0.364166259765625 +100318 -0.327239990234375 +100319 -0.2769775390625 +100320 -0.253692626953125 +100321 -0.24365234375 +100322 -0.1983642578125 +100323 -0.116241455078125 +100324 -0.036834716796875 +100325 0.034881591796875 +100326 0.09124755859375 +100327 0.10888671875 +100328 0.125518798828125 +100329 0.15771484375 +100330 0.17828369140625 +100331 0.17108154296875 +100332 0.129974365234375 +100333 0.082427978515625 +100334 0.027679443359375 +100335 -0.065643310546875 +100336 -0.15936279296875 +100337 -0.21307373046875 +100338 -0.234649658203125 +100339 -0.2001953125 +100340 -0.119171142578125 +100341 -0.024749755859375 +100342 0.085784912109375 +100343 0.178131103515625 +100344 0.215576171875 +100345 0.211456298828125 +100346 0.17523193359375 +100347 0.128753662109375 +100348 0.1019287109375 +100349 0.0743408203125 +100350 0.04327392578125 +100351 0.038177490234375 +100352 0.076263427734375 +100353 0.14105224609375 +100354 0.186431884765625 +100355 0.188812255859375 +100356 0.1390380859375 +100357 0.041778564453125 +100358 -0.079437255859375 +100359 -0.219390869140625 +100360 -0.367828369140625 +100361 -0.494873046875 +100362 -0.556243896484375 +100363 -0.508697509765625 +100364 -0.3756103515625 +100365 -0.218902587890625 +100366 -0.063751220703125 +100367 0.091552734375 +100368 0.23602294921875 +100369 0.342987060546875 +100370 0.39520263671875 +100371 0.389373779296875 +100372 0.324249267578125 +100373 0.224090576171875 +100374 0.124267578125 +100375 0.037078857421875 +100376 -0.010101318359375 +100377 -0.019439697265625 +100378 -0.022796630859375 +100379 -0.001556396484375 +100380 0.056304931640625 +100381 0.106719970703125 +100382 0.096893310546875 +100383 0.042694091796875 +100384 -0.018035888671875 +100385 -0.07586669921875 +100386 -0.11944580078125 +100387 -0.15972900390625 +100388 -0.202606201171875 +100389 -0.24859619140625 +100390 -0.30517578125 +100391 -0.36212158203125 +100392 -0.39141845703125 +100393 -0.35528564453125 +100394 -0.249969482421875 +100395 -0.092864990234375 +100396 0.08905029296875 +100397 0.2352294921875 +100398 0.318817138671875 +100399 0.358642578125 +100400 0.347747802734375 +100401 0.28564453125 +100402 0.223175048828125 +100403 0.196746826171875 +100404 0.179840087890625 +100405 0.155548095703125 +100406 0.151214599609375 +100407 0.156951904296875 +100408 0.13177490234375 +100409 0.100799560546875 +100410 0.087127685546875 +100411 0.05487060546875 +100412 -0.009002685546875 +100413 -0.10400390625 +100414 -0.229400634765625 +100415 -0.35552978515625 +100416 -0.441925048828125 +100417 -0.473846435546875 +100418 -0.464813232421875 +100419 -0.419097900390625 +100420 -0.334320068359375 +100421 -0.227935791015625 +100422 -0.12347412109375 +100423 -0.02764892578125 +100424 0.077667236328125 +100425 0.2132568359375 +100426 0.38885498046875 +100427 0.582794189453125 +100428 0.734039306640625 +100429 0.800140380859375 +100430 0.7783203125 +100431 0.6651611328125 +100432 0.45965576171875 +100433 0.199188232421875 +100434 -0.050689697265625 +100435 -0.23297119140625 +100436 -0.33013916015625 +100437 -0.368408203125 +100438 -0.378936767578125 +100439 -0.376983642578125 +100440 -0.37969970703125 +100441 -0.391510009765625 +100442 -0.385345458984375 +100443 -0.3419189453125 +100444 -0.28289794921875 +100445 -0.251617431640625 +100446 -0.266143798828125 +100447 -0.273345947265625 +100448 -0.216796875 +100449 -0.128265380859375 +100450 -0.068145751953125 +100451 -0.0430908203125 +100452 -0.024444580078125 +100453 0.020721435546875 +100454 0.124481201171875 +100455 0.25787353515625 +100456 0.379119873046875 +100457 0.47991943359375 +100458 0.5281982421875 +100459 0.511138916015625 +100460 0.456207275390625 +100461 0.407470703125 +100462 0.383758544921875 +100463 0.35687255859375 +100464 0.31182861328125 +100465 0.250885009765625 +100466 0.1654052734375 +100467 0.035247802734375 +100468 -0.142059326171875 +100469 -0.33563232421875 +100470 -0.5345458984375 +100471 -0.72186279296875 +100472 -0.836669921875 +100473 -0.8326416015625 +100474 -0.7296142578125 +100475 -0.582550048828125 +100476 -0.440093994140625 +100477 -0.324310302734375 +100478 -0.20147705078125 +100479 -0.044647216796875 +100480 0.103973388671875 +100481 0.202392578125 +100482 0.264495849609375 +100483 0.338897705078125 +100484 0.443817138671875 +100485 0.545074462890625 +100486 0.6173095703125 +100487 0.6524658203125 +100488 0.66339111328125 +100489 0.6561279296875 +100490 0.606781005859375 +100491 0.501190185546875 +100492 0.352783203125 +100493 0.176544189453125 +100494 -0.034820556640625 +100495 -0.258209228515625 +100496 -0.44244384765625 +100497 -0.5753173828125 +100498 -0.65203857421875 +100499 -0.641632080078125 +100500 -0.562164306640625 +100501 -0.458038330078125 +100502 -0.350555419921875 +100503 -0.260528564453125 +100504 -0.192108154296875 +100505 -0.141937255859375 +100506 -0.1021728515625 +100507 -0.062896728515625 +100508 -0.011932373046875 +100509 0.062835693359375 +100510 0.148712158203125 +100511 0.241729736328125 +100512 0.34912109375 +100513 0.457305908203125 +100514 0.54388427734375 +100515 0.5728759765625 +100516 0.506591796875 +100517 0.351226806640625 +100518 0.146514892578125 +100519 -0.05523681640625 +100520 -0.21624755859375 +100521 -0.334930419921875 +100522 -0.402984619140625 +100523 -0.4412841796875 +100524 -0.49578857421875 +100525 -0.5601806640625 +100526 -0.600738525390625 +100527 -0.584228515625 +100528 -0.47930908203125 +100529 -0.27935791015625 +100530 -0.0089111328125 +100531 0.268798828125 +100532 0.482818603515625 +100533 0.60369873046875 +100534 0.650421142578125 +100535 0.66400146484375 +100536 0.6414794921875 +100537 0.572540283203125 +100538 0.498138427734375 +100539 0.439453125 +100540 0.375518798828125 +100541 0.274505615234375 +100542 0.1087646484375 +100543 -0.099395751953125 +100544 -0.3182373046875 +100545 -0.5489501953125 +100546 -0.7738037109375 +100547 -0.86383056640625 +100548 -0.870391845703125 +100549 -0.86895751953125 +100550 -0.861053466796875 +100551 -0.765869140625 +100552 -0.5301513671875 +100553 -0.214691162109375 +100554 0.137359619140625 +100555 0.474822998046875 +100556 0.76239013671875 +100557 0.867462158203125 +100558 0.870361328125 +100559 0.86480712890625 +100560 0.831817626953125 +100561 0.677581787109375 +100562 0.495880126953125 +100563 0.30767822265625 +100564 0.116180419921875 +100565 -0.110748291015625 +100566 -0.381805419921875 +100567 -0.6572265625 +100568 -0.857421875 +100569 -0.870391845703125 +100570 -0.870391845703125 +100571 -0.86444091796875 +100572 -0.85723876953125 +100573 -0.790008544921875 +100574 -0.62847900390625 +100575 -0.3956298828125 +100576 -0.126708984375 +100577 0.150115966796875 +100578 0.424041748046875 +100579 0.670623779296875 +100580 0.854522705078125 +100581 0.866485595703125 +100582 0.86920166015625 +100583 0.8653564453125 +100584 0.857147216796875 +100585 0.766845703125 +100586 0.628509521484375 +100587 0.462127685546875 +100588 0.297210693359375 +100589 0.14862060546875 +100590 -0.00537109375 +100591 -0.15753173828125 +100592 -0.31304931640625 +100593 -0.48876953125 +100594 -0.6416015625 +100595 -0.751373291015625 +100596 -0.84619140625 +100597 -0.861297607421875 +100598 -0.863250732421875 +100599 -0.856597900390625 +100600 -0.7498779296875 +100601 -0.624542236328125 +100602 -0.47808837890625 +100603 -0.253387451171875 +100604 0.003692626953125 +100605 0.2257080078125 +100606 0.427154541015625 +100607 0.643218994140625 +100608 0.855926513671875 +100609 0.870361328125 +100610 0.870361328125 +100611 0.862762451171875 +100612 0.79669189453125 +100613 0.595794677734375 +100614 0.362152099609375 +100615 0.1270751953125 +100616 -0.086944580078125 +100617 -0.2784423828125 +100618 -0.484832763671875 +100619 -0.729583740234375 +100620 -0.86688232421875 +100621 -0.870391845703125 +100622 -0.86859130859375 +100623 -0.86279296875 +100624 -0.817962646484375 +100625 -0.6116943359375 +100626 -0.3128662109375 +100627 0.039398193359375 +100628 0.422821044921875 +100629 0.805145263671875 +100630 0.870361328125 +100631 0.870361328125 +100632 0.860015869140625 +100633 0.727935791015625 +100634 0.48114013671875 +100635 0.2059326171875 +100636 -0.06103515625 +100637 -0.29913330078125 +100638 -0.516204833984375 +100639 -0.7252197265625 +100640 -0.85980224609375 +100641 -0.870391845703125 +100642 -0.870391845703125 +100643 -0.858062744140625 +100644 -0.673004150390625 +100645 -0.42694091796875 +100646 -0.2100830078125 +100647 -0.0362548828125 +100648 0.10943603515625 +100649 0.23516845703125 +100650 0.373687744140625 +100651 0.517791748046875 +100652 0.602783203125 +100653 0.635711669921875 +100654 0.655181884765625 +100655 0.65948486328125 +100656 0.651275634765625 +100657 0.61846923828125 +100658 0.53753662109375 +100659 0.404144287109375 +100660 0.22186279296875 +100661 0.003997802734375 +100662 -0.22100830078125 +100663 -0.42449951171875 +100664 -0.579833984375 +100665 -0.641876220703125 +100666 -0.6177978515625 +100667 -0.575531005859375 +100668 -0.526336669921875 +100669 -0.42645263671875 +100670 -0.2581787109375 +100671 -0.068695068359375 +100672 0.09222412109375 +100673 0.232147216796875 +100674 0.3509521484375 +100675 0.410064697265625 +100676 0.372955322265625 +100677 0.2554931640625 +100678 0.10711669921875 +100679 -0.052886962890625 +100680 -0.186279296875 +100681 -0.23291015625 +100682 -0.209442138671875 +100683 -0.174163818359375 +100684 -0.126739501953125 +100685 -0.048126220703125 +100686 0.0426025390625 +100687 0.10748291015625 +100688 0.1409912109375 +100689 0.19708251953125 +100690 0.273651123046875 +100691 0.31768798828125 +100692 0.341094970703125 +100693 0.368011474609375 +100694 0.37249755859375 +100695 0.30072021484375 +100696 0.1517333984375 +100697 -0.01470947265625 +100698 -0.1883544921875 +100699 -0.372711181640625 +100700 -0.51397705078125 +100701 -0.57177734375 +100702 -0.53948974609375 +100703 -0.43511962890625 +100704 -0.2962646484375 +100705 -0.161102294921875 +100706 -0.0435791015625 +100707 0.060394287109375 +100708 0.13665771484375 +100709 0.170135498046875 +100710 0.16552734375 +100711 0.15728759765625 +100712 0.150787353515625 +100713 0.12200927734375 +100714 0.080108642578125 +100715 0.05126953125 +100716 0.062896728515625 +100717 0.09271240234375 +100718 0.092987060546875 +100719 0.07855224609375 +100720 0.06427001953125 +100721 0.0347900390625 +100722 -0.01171875 +100723 -0.056060791015625 +100724 -0.055511474609375 +100725 -0.010467529296875 +100726 0.02508544921875 +100727 0.025665283203125 +100728 0.017333984375 +100729 0.00189208984375 +100730 -0.03173828125 +100731 -0.071502685546875 +100732 -0.13543701171875 +100733 -0.219970703125 +100734 -0.300506591796875 +100735 -0.376312255859375 +100736 -0.416107177734375 +100737 -0.371124267578125 +100738 -0.242279052734375 +100739 -0.069732666015625 +100740 0.125640869140625 +100741 0.31268310546875 +100742 0.45501708984375 +100743 0.554779052734375 +100744 0.61065673828125 +100745 0.610931396484375 +100746 0.531463623046875 +100747 0.3883056640625 +100748 0.23468017578125 +100749 0.095245361328125 +100750 -0.00396728515625 +100751 -0.04852294921875 +100752 -0.055145263671875 +100753 -0.0758056640625 +100754 -0.138702392578125 +100755 -0.209197998046875 +100756 -0.289031982421875 +100757 -0.37884521484375 +100758 -0.456329345703125 +100759 -0.51641845703125 +100760 -0.519287109375 +100761 -0.458251953125 +100762 -0.384796142578125 +100763 -0.323699951171875 +100764 -0.269287109375 +100765 -0.1951904296875 +100766 -0.100006103515625 +100767 -0.01055908203125 +100768 0.1033935546875 +100769 0.24908447265625 +100770 0.373199462890625 +100771 0.45806884765625 +100772 0.511474609375 +100773 0.565399169921875 +100774 0.61138916015625 +100775 0.5897216796875 +100776 0.4906005859375 +100777 0.33148193359375 +100778 0.147796630859375 +100779 -0.01873779296875 +100780 -0.140289306640625 +100781 -0.191986083984375 +100782 -0.184295654296875 +100783 -0.161834716796875 +100784 -0.166595458984375 +100785 -0.19390869140625 +100786 -0.22442626953125 +100787 -0.279754638671875 +100788 -0.3389892578125 +100789 -0.3543701171875 +100790 -0.348175048828125 +100791 -0.32598876953125 +100792 -0.2581787109375 +100793 -0.139801025390625 +100794 0.014617919921875 +100795 0.144378662109375 +100796 0.221038818359375 +100797 0.27069091796875 +100798 0.294036865234375 +100799 0.311767578125 +100800 0.339141845703125 +100801 0.360260009765625 +100802 0.360504150390625 +100803 0.308380126953125 +100804 0.18170166015625 +100805 0.0047607421875 +100806 -0.17559814453125 +100807 -0.3143310546875 +100808 -0.36785888671875 +100809 -0.36248779296875 +100810 -0.343536376953125 +100811 -0.3018798828125 +100812 -0.231414794921875 +100813 -0.117645263671875 +100814 0.007049560546875 +100815 0.087982177734375 +100816 0.13946533203125 +100817 0.17425537109375 +100818 0.188201904296875 +100819 0.171234130859375 +100820 0.118438720703125 +100821 0.05706787109375 +100822 -0.010711669921875 +100823 -0.0914306640625 +100824 -0.162322998046875 +100825 -0.194549560546875 +100826 -0.1492919921875 +100827 -0.02166748046875 +100828 0.124053955078125 +100829 0.211151123046875 +100830 0.240447998046875 +100831 0.242218017578125 +100832 0.2257080078125 +100833 0.194366455078125 +100834 0.115509033203125 +100835 0.0128173828125 +100836 -0.053802490234375 +100837 -0.110626220703125 +100838 -0.199493408203125 +100839 -0.29437255859375 +100840 -0.33221435546875 +100841 -0.27972412109375 +100842 -0.185333251953125 +100843 -0.128204345703125 +100844 -0.115692138671875 +100845 -0.116455078125 +100846 -0.105926513671875 +100847 -0.053955078125 +100848 0.048797607421875 +100849 0.157318115234375 +100850 0.212005615234375 +100851 0.218475341796875 +100852 0.23724365234375 +100853 0.30535888671875 +100854 0.38128662109375 +100855 0.404449462890625 +100856 0.3944091796875 +100857 0.3885498046875 +100858 0.362640380859375 +100859 0.27362060546875 +100860 0.11712646484375 +100861 -0.054901123046875 +100862 -0.19085693359375 +100863 -0.28570556640625 +100864 -0.339263916015625 +100865 -0.3775634765625 +100866 -0.445709228515625 +100867 -0.535064697265625 +100868 -0.629058837890625 +100869 -0.697601318359375 +100870 -0.70391845703125 +100871 -0.6424560546875 +100872 -0.491241455078125 +100873 -0.265716552734375 +100874 -0.023712158203125 +100875 0.201751708984375 +100876 0.375823974609375 +100877 0.485076904296875 +100878 0.56884765625 +100879 0.634765625 +100880 0.63763427734375 +100881 0.5660400390625 +100882 0.4720458984375 +100883 0.40692138671875 +100884 0.3778076171875 +100885 0.376953125 +100886 0.371978759765625 +100887 0.313140869140625 +100888 0.184417724609375 +100889 0.011199951171875 +100890 -0.171051025390625 +100891 -0.33740234375 +100892 -0.47198486328125 +100893 -0.560394287109375 +100894 -0.58056640625 +100895 -0.54754638671875 +100896 -0.508575439453125 +100897 -0.459503173828125 +100898 -0.394378662109375 +100899 -0.35260009765625 +100900 -0.31170654296875 +100901 -0.197418212890625 +100902 -0.007965087890625 +100903 0.207489013671875 +100904 0.409210205078125 +100905 0.57208251953125 +100906 0.66595458984375 +100907 0.65875244140625 +100908 0.56744384765625 +100909 0.431396484375 +100910 0.29443359375 +100911 0.182464599609375 +100912 0.06365966796875 +100913 -0.075958251953125 +100914 -0.189422607421875 +100915 -0.271942138671875 +100916 -0.342529296875 +100917 -0.364166259765625 +100918 -0.327239990234375 +100919 -0.2769775390625 +100920 -0.253692626953125 +100921 -0.24365234375 +100922 -0.1983642578125 +100923 -0.116241455078125 +100924 -0.036834716796875 +100925 0.034881591796875 +100926 0.09124755859375 +100927 0.10888671875 +100928 0.125518798828125 +100929 0.15771484375 +100930 0.17828369140625 +100931 0.17108154296875 +100932 0.129974365234375 +100933 0.082427978515625 +100934 0.027679443359375 +100935 -0.065643310546875 +100936 -0.15936279296875 +100937 -0.21307373046875 +100938 -0.234649658203125 +100939 -0.2001953125 +100940 -0.119171142578125 +100941 -0.024749755859375 +100942 0.085784912109375 +100943 0.178131103515625 +100944 0.215576171875 +100945 0.211456298828125 +100946 0.17523193359375 +100947 0.128753662109375 +100948 0.1019287109375 +100949 0.0743408203125 +100950 0.04327392578125 +100951 0.038177490234375 +100952 0.076263427734375 +100953 0.14105224609375 +100954 0.186431884765625 +100955 0.188812255859375 +100956 0.1390380859375 +100957 0.041778564453125 +100958 -0.079437255859375 +100959 -0.219390869140625 +100960 -0.367828369140625 +100961 -0.494873046875 +100962 -0.556243896484375 +100963 -0.508697509765625 +100964 -0.3756103515625 +100965 -0.218902587890625 +100966 -0.063751220703125 +100967 0.091552734375 +100968 0.23602294921875 +100969 0.342987060546875 +100970 0.39520263671875 +100971 0.389373779296875 +100972 0.324249267578125 +100973 0.224090576171875 +100974 0.124267578125 +100975 0.037078857421875 +100976 -0.010101318359375 +100977 -0.019439697265625 +100978 -0.022796630859375 +100979 -0.001556396484375 +100980 0.056304931640625 +100981 0.106719970703125 +100982 0.096893310546875 +100983 0.042694091796875 +100984 -0.018035888671875 +100985 -0.07586669921875 +100986 -0.11944580078125 +100987 -0.15972900390625 +100988 -0.202606201171875 +100989 -0.24859619140625 +100990 -0.30517578125 +100991 -0.36212158203125 +100992 -0.39141845703125 +100993 -0.35528564453125 +100994 -0.249969482421875 +100995 -0.092864990234375 +100996 0.08905029296875 +100997 0.2352294921875 +100998 0.318817138671875 +100999 0.358642578125 +101000 0.347747802734375 +101001 0.28564453125 +101002 0.223175048828125 +101003 0.196746826171875 +101004 0.179840087890625 +101005 0.155548095703125 +101006 0.151214599609375 +101007 0.156951904296875 +101008 0.13177490234375 +101009 0.100799560546875 +101010 0.087127685546875 +101011 0.05487060546875 +101012 -0.009002685546875 +101013 -0.10400390625 +101014 -0.229400634765625 +101015 -0.35552978515625 +101016 -0.441925048828125 +101017 -0.473846435546875 +101018 -0.464813232421875 +101019 -0.419097900390625 +101020 -0.334320068359375 +101021 -0.227935791015625 +101022 -0.12347412109375 +101023 -0.02764892578125 +101024 0.077667236328125 +101025 0.2132568359375 +101026 0.38885498046875 +101027 0.582794189453125 +101028 0.734039306640625 +101029 0.800140380859375 +101030 0.7783203125 +101031 0.6651611328125 +101032 0.45965576171875 +101033 0.199188232421875 +101034 -0.050689697265625 +101035 -0.23297119140625 +101036 -0.33013916015625 +101037 -0.368408203125 +101038 -0.378936767578125 +101039 -0.376983642578125 +101040 -0.37969970703125 +101041 -0.391510009765625 +101042 -0.385345458984375 +101043 -0.3419189453125 +101044 -0.28289794921875 +101045 -0.251617431640625 +101046 -0.266143798828125 +101047 -0.273345947265625 +101048 -0.216796875 +101049 -0.128265380859375 +101050 -0.068145751953125 +101051 -0.0430908203125 +101052 -0.024444580078125 +101053 0.020721435546875 +101054 0.124481201171875 +101055 0.25787353515625 +101056 0.379119873046875 +101057 0.47991943359375 +101058 0.5281982421875 +101059 0.511138916015625 +101060 0.456207275390625 +101061 0.407470703125 +101062 0.383758544921875 +101063 0.35687255859375 +101064 0.31182861328125 +101065 0.250885009765625 +101066 0.1654052734375 +101067 0.035247802734375 +101068 -0.142059326171875 +101069 -0.33563232421875 +101070 -0.5345458984375 +101071 -0.72186279296875 +101072 -0.836669921875 +101073 -0.8326416015625 +101074 -0.7296142578125 +101075 -0.582550048828125 +101076 -0.440093994140625 +101077 -0.324310302734375 +101078 -0.20147705078125 +101079 -0.044647216796875 +101080 0.103973388671875 +101081 0.202392578125 +101082 0.264495849609375 +101083 0.338897705078125 +101084 0.443817138671875 +101085 0.545074462890625 +101086 0.6173095703125 +101087 0.6524658203125 +101088 0.66339111328125 +101089 0.6561279296875 +101090 0.606781005859375 +101091 0.501190185546875 +101092 0.352783203125 +101093 0.176544189453125 +101094 -0.034820556640625 +101095 -0.258209228515625 +101096 -0.44244384765625 +101097 -0.5753173828125 +101098 -0.65203857421875 +101099 -0.641632080078125 +101100 -0.562164306640625 +101101 -0.458038330078125 +101102 -0.350555419921875 +101103 -0.260528564453125 +101104 -0.192108154296875 +101105 -0.141937255859375 +101106 -0.1021728515625 +101107 -0.062896728515625 +101108 -0.011932373046875 +101109 0.062835693359375 +101110 0.148712158203125 +101111 0.241729736328125 +101112 0.34912109375 +101113 0.457305908203125 +101114 0.54388427734375 +101115 0.5728759765625 +101116 0.506591796875 +101117 0.351226806640625 +101118 0.146514892578125 +101119 -0.05523681640625 +101120 -0.21624755859375 +101121 -0.334930419921875 +101122 -0.402984619140625 +101123 -0.4412841796875 +101124 -0.49578857421875 +101125 -0.5601806640625 +101126 -0.600738525390625 +101127 -0.584228515625 +101128 -0.47930908203125 +101129 -0.27935791015625 +101130 -0.0089111328125 +101131 0.268798828125 +101132 0.482818603515625 +101133 0.60369873046875 +101134 0.650421142578125 +101135 0.66400146484375 +101136 0.6414794921875 +101137 0.572540283203125 +101138 0.498138427734375 +101139 0.439453125 +101140 0.375518798828125 +101141 0.274505615234375 +101142 0.1087646484375 +101143 -0.099395751953125 +101144 -0.3182373046875 +101145 -0.5489501953125 +101146 -0.7738037109375 +101147 -0.86383056640625 +101148 -0.870391845703125 +101149 -0.86895751953125 +101150 -0.861053466796875 +101151 -0.765869140625 +101152 -0.5301513671875 +101153 -0.214691162109375 +101154 0.137359619140625 +101155 0.474822998046875 +101156 0.76239013671875 +101157 0.867462158203125 +101158 0.870361328125 +101159 0.86480712890625 +101160 0.831817626953125 +101161 0.677581787109375 +101162 0.495880126953125 +101163 0.30767822265625 +101164 0.116180419921875 +101165 -0.110748291015625 +101166 -0.381805419921875 +101167 -0.6572265625 +101168 -0.857421875 +101169 -0.870391845703125 +101170 -0.870391845703125 +101171 -0.86444091796875 +101172 -0.85723876953125 +101173 -0.790008544921875 +101174 -0.62847900390625 +101175 -0.3956298828125 +101176 -0.126708984375 +101177 0.150115966796875 +101178 0.424041748046875 +101179 0.670623779296875 +101180 0.854522705078125 +101181 0.866485595703125 +101182 0.86920166015625 +101183 0.8653564453125 +101184 0.857147216796875 +101185 0.766845703125 +101186 0.628509521484375 +101187 0.462127685546875 +101188 0.297210693359375 +101189 0.14862060546875 +101190 -0.00537109375 +101191 -0.15753173828125 +101192 -0.31304931640625 +101193 -0.48876953125 +101194 -0.6416015625 +101195 -0.751373291015625 +101196 -0.84619140625 +101197 -0.861297607421875 +101198 -0.863250732421875 +101199 -0.856597900390625 +101200 -0.7498779296875 +101201 -0.624542236328125 +101202 -0.47808837890625 +101203 -0.253387451171875 +101204 0.003692626953125 +101205 0.2257080078125 +101206 0.427154541015625 +101207 0.643218994140625 +101208 0.855926513671875 +101209 0.870361328125 +101210 0.870361328125 +101211 0.862762451171875 +101212 0.79669189453125 +101213 0.595794677734375 +101214 0.362152099609375 +101215 0.1270751953125 +101216 -0.086944580078125 +101217 -0.2784423828125 +101218 -0.484832763671875 +101219 -0.729583740234375 +101220 -0.86688232421875 +101221 -0.870391845703125 +101222 -0.86859130859375 +101223 -0.86279296875 +101224 -0.817962646484375 +101225 -0.6116943359375 +101226 -0.3128662109375 +101227 0.039398193359375 +101228 0.422821044921875 +101229 0.805145263671875 +101230 0.870361328125 +101231 0.870361328125 +101232 0.860015869140625 +101233 0.727935791015625 +101234 0.48114013671875 +101235 0.2059326171875 +101236 -0.06103515625 +101237 -0.29913330078125 +101238 -0.516204833984375 +101239 -0.7252197265625 +101240 -0.85980224609375 +101241 -0.870391845703125 +101242 -0.870391845703125 +101243 -0.858062744140625 +101244 -0.673004150390625 +101245 -0.42694091796875 +101246 -0.2100830078125 +101247 -0.0362548828125 +101248 0.10943603515625 +101249 0.23516845703125 +101250 0.373687744140625 +101251 0.517791748046875 +101252 0.602783203125 +101253 0.635711669921875 +101254 0.655181884765625 +101255 0.65948486328125 +101256 0.651275634765625 +101257 0.61846923828125 +101258 0.53753662109375 +101259 0.404144287109375 +101260 0.22186279296875 +101261 0.003997802734375 +101262 -0.22100830078125 +101263 -0.42449951171875 +101264 -0.579833984375 +101265 -0.641876220703125 +101266 -0.6177978515625 +101267 -0.575531005859375 +101268 -0.526336669921875 +101269 -0.42645263671875 +101270 -0.2581787109375 +101271 -0.068695068359375 +101272 0.09222412109375 +101273 0.232147216796875 +101274 0.3509521484375 +101275 0.410064697265625 +101276 0.372955322265625 +101277 0.2554931640625 +101278 0.10711669921875 +101279 -0.052886962890625 +101280 -0.186279296875 +101281 -0.23291015625 +101282 -0.209442138671875 +101283 -0.174163818359375 +101284 -0.126739501953125 +101285 -0.048126220703125 +101286 0.0426025390625 +101287 0.10748291015625 +101288 0.1409912109375 +101289 0.19708251953125 +101290 0.273651123046875 +101291 0.31768798828125 +101292 0.341094970703125 +101293 0.368011474609375 +101294 0.37249755859375 +101295 0.30072021484375 +101296 0.1517333984375 +101297 -0.01470947265625 +101298 -0.1883544921875 +101299 -0.372711181640625 +101300 -0.51397705078125 +101301 -0.57177734375 +101302 -0.53948974609375 +101303 -0.43511962890625 +101304 -0.2962646484375 +101305 -0.161102294921875 +101306 -0.0435791015625 +101307 0.060394287109375 +101308 0.13665771484375 +101309 0.170135498046875 +101310 0.16552734375 +101311 0.15728759765625 +101312 0.150787353515625 +101313 0.12200927734375 +101314 0.080108642578125 +101315 0.05126953125 +101316 0.062896728515625 +101317 0.09271240234375 +101318 0.092987060546875 +101319 0.07855224609375 +101320 0.06427001953125 +101321 0.0347900390625 +101322 -0.01171875 +101323 -0.056060791015625 +101324 -0.055511474609375 +101325 -0.010467529296875 +101326 0.02508544921875 +101327 0.025665283203125 +101328 0.017333984375 +101329 0.00189208984375 +101330 -0.03173828125 +101331 -0.071502685546875 +101332 -0.13543701171875 +101333 -0.219970703125 +101334 -0.300506591796875 +101335 -0.376312255859375 +101336 -0.416107177734375 +101337 -0.371124267578125 +101338 -0.242279052734375 +101339 -0.069732666015625 +101340 0.125640869140625 +101341 0.31268310546875 +101342 0.45501708984375 +101343 0.554779052734375 +101344 0.61065673828125 +101345 0.610931396484375 +101346 0.531463623046875 +101347 0.3883056640625 +101348 0.23468017578125 +101349 0.095245361328125 +101350 -0.00396728515625 +101351 -0.04852294921875 +101352 -0.055145263671875 +101353 -0.0758056640625 +101354 -0.138702392578125 +101355 -0.209197998046875 +101356 -0.289031982421875 +101357 -0.37884521484375 +101358 -0.456329345703125 +101359 -0.51641845703125 +101360 -0.519287109375 +101361 -0.458251953125 +101362 -0.384796142578125 +101363 -0.323699951171875 +101364 -0.269287109375 +101365 -0.1951904296875 +101366 -0.100006103515625 +101367 -0.01055908203125 +101368 0.1033935546875 +101369 0.24908447265625 +101370 0.373199462890625 +101371 0.45806884765625 +101372 0.511474609375 +101373 0.565399169921875 +101374 0.61138916015625 +101375 0.5897216796875 +101376 0.4906005859375 +101377 0.33148193359375 +101378 0.147796630859375 +101379 -0.01873779296875 +101380 -0.140289306640625 +101381 -0.191986083984375 +101382 -0.184295654296875 +101383 -0.161834716796875 +101384 -0.166595458984375 +101385 -0.19390869140625 +101386 -0.22442626953125 +101387 -0.279754638671875 +101388 -0.3389892578125 +101389 -0.3543701171875 +101390 -0.348175048828125 +101391 -0.32598876953125 +101392 -0.2581787109375 +101393 -0.139801025390625 +101394 0.014617919921875 +101395 0.144378662109375 +101396 0.221038818359375 +101397 0.27069091796875 +101398 0.294036865234375 +101399 0.311767578125 +101400 0.339141845703125 +101401 0.360260009765625 +101402 0.360504150390625 +101403 0.308380126953125 +101404 0.18170166015625 +101405 0.0047607421875 +101406 -0.17559814453125 +101407 -0.3143310546875 +101408 -0.36785888671875 +101409 -0.36248779296875 +101410 -0.343536376953125 +101411 -0.3018798828125 +101412 -0.231414794921875 +101413 -0.117645263671875 +101414 0.007049560546875 +101415 0.087982177734375 +101416 0.13946533203125 +101417 0.17425537109375 +101418 0.188201904296875 +101419 0.171234130859375 +101420 0.118438720703125 +101421 0.05706787109375 +101422 -0.010711669921875 +101423 -0.0914306640625 +101424 -0.162322998046875 +101425 -0.194549560546875 +101426 -0.1492919921875 +101427 -0.02166748046875 +101428 0.124053955078125 +101429 0.211151123046875 +101430 0.240447998046875 +101431 0.242218017578125 +101432 0.2257080078125 +101433 0.194366455078125 +101434 0.115509033203125 +101435 0.0128173828125 +101436 -0.053802490234375 +101437 -0.110626220703125 +101438 -0.199493408203125 +101439 -0.29437255859375 +101440 -0.33221435546875 +101441 -0.27972412109375 +101442 -0.185333251953125 +101443 -0.128204345703125 +101444 -0.115692138671875 +101445 -0.116455078125 +101446 -0.105926513671875 +101447 -0.053955078125 +101448 0.048797607421875 +101449 0.157318115234375 +101450 0.212005615234375 +101451 0.218475341796875 +101452 0.23724365234375 +101453 0.30535888671875 +101454 0.38128662109375 +101455 0.404449462890625 +101456 0.3944091796875 +101457 0.3885498046875 +101458 0.362640380859375 +101459 0.27362060546875 +101460 0.11712646484375 +101461 -0.054901123046875 +101462 -0.19085693359375 +101463 -0.28570556640625 +101464 -0.339263916015625 +101465 -0.3775634765625 +101466 -0.445709228515625 +101467 -0.535064697265625 +101468 -0.629058837890625 +101469 -0.697601318359375 +101470 -0.70391845703125 +101471 -0.6424560546875 +101472 -0.491241455078125 +101473 -0.265716552734375 +101474 -0.023712158203125 +101475 0.201751708984375 +101476 0.375823974609375 +101477 0.485076904296875 +101478 0.56884765625 +101479 0.634765625 +101480 0.63763427734375 +101481 0.5660400390625 +101482 0.4720458984375 +101483 0.40692138671875 +101484 0.3778076171875 +101485 0.376953125 +101486 0.371978759765625 +101487 0.313140869140625 +101488 0.184417724609375 +101489 0.011199951171875 +101490 -0.171051025390625 +101491 -0.33740234375 +101492 -0.47198486328125 +101493 -0.560394287109375 +101494 -0.58056640625 +101495 -0.54754638671875 +101496 -0.508575439453125 +101497 -0.459503173828125 +101498 -0.394378662109375 +101499 -0.35260009765625 +101500 -0.31170654296875 +101501 -0.197418212890625 +101502 -0.007965087890625 +101503 0.207489013671875 +101504 0.409210205078125 +101505 0.57208251953125 +101506 0.66595458984375 +101507 0.65875244140625 +101508 0.56744384765625 +101509 0.431396484375 +101510 0.29443359375 +101511 0.182464599609375 +101512 0.06365966796875 +101513 -0.075958251953125 +101514 -0.189422607421875 +101515 -0.271942138671875 +101516 -0.342529296875 +101517 -0.364166259765625 +101518 -0.327239990234375 +101519 -0.2769775390625 +101520 -0.253692626953125 +101521 -0.24365234375 +101522 -0.1983642578125 +101523 -0.116241455078125 +101524 -0.036834716796875 +101525 0.034881591796875 +101526 0.09124755859375 +101527 0.10888671875 +101528 0.125518798828125 +101529 0.15771484375 +101530 0.17828369140625 +101531 0.17108154296875 +101532 0.129974365234375 +101533 0.082427978515625 +101534 0.027679443359375 +101535 -0.065643310546875 +101536 -0.15936279296875 +101537 -0.21307373046875 +101538 -0.234649658203125 +101539 -0.2001953125 +101540 -0.119171142578125 +101541 -0.024749755859375 +101542 0.085784912109375 +101543 0.178131103515625 +101544 0.215576171875 +101545 0.211456298828125 +101546 0.17523193359375 +101547 0.128753662109375 +101548 0.1019287109375 +101549 0.0743408203125 +101550 0.04327392578125 +101551 0.038177490234375 +101552 0.076263427734375 +101553 0.14105224609375 +101554 0.186431884765625 +101555 0.188812255859375 +101556 0.1390380859375 +101557 0.041778564453125 +101558 -0.079437255859375 +101559 -0.219390869140625 +101560 -0.367828369140625 +101561 -0.494873046875 +101562 -0.556243896484375 +101563 -0.508697509765625 +101564 -0.3756103515625 +101565 -0.218902587890625 +101566 -0.063751220703125 +101567 0.091552734375 +101568 0.23602294921875 +101569 0.342987060546875 +101570 0.39520263671875 +101571 0.389373779296875 +101572 0.324249267578125 +101573 0.224090576171875 +101574 0.124267578125 +101575 0.037078857421875 +101576 -0.010101318359375 +101577 -0.019439697265625 +101578 -0.022796630859375 +101579 -0.001556396484375 +101580 0.056304931640625 +101581 0.106719970703125 +101582 0.096893310546875 +101583 0.042694091796875 +101584 -0.018035888671875 +101585 -0.07586669921875 +101586 -0.11944580078125 +101587 -0.15972900390625 +101588 -0.202606201171875 +101589 -0.24859619140625 +101590 -0.30517578125 +101591 -0.36212158203125 +101592 -0.39141845703125 +101593 -0.35528564453125 +101594 -0.249969482421875 +101595 -0.092864990234375 +101596 0.08905029296875 +101597 0.2352294921875 +101598 0.318817138671875 +101599 0.358642578125 +101600 0.347747802734375 +101601 0.28564453125 +101602 0.223175048828125 +101603 0.196746826171875 +101604 0.179840087890625 +101605 0.155548095703125 +101606 0.151214599609375 +101607 0.156951904296875 +101608 0.13177490234375 +101609 0.100799560546875 +101610 0.087127685546875 +101611 0.05487060546875 +101612 -0.009002685546875 +101613 -0.10400390625 +101614 -0.229400634765625 +101615 -0.35552978515625 +101616 -0.441925048828125 +101617 -0.473846435546875 +101618 -0.464813232421875 +101619 -0.419097900390625 +101620 -0.334320068359375 +101621 -0.227935791015625 +101622 -0.12347412109375 +101623 -0.02764892578125 +101624 0.077667236328125 +101625 0.2132568359375 +101626 0.38885498046875 +101627 0.582794189453125 +101628 0.734039306640625 +101629 0.800140380859375 +101630 0.7783203125 +101631 0.6651611328125 +101632 0.45965576171875 +101633 0.199188232421875 +101634 -0.050689697265625 +101635 -0.23297119140625 +101636 -0.33013916015625 +101637 -0.368408203125 +101638 -0.378936767578125 +101639 -0.376983642578125 +101640 -0.37969970703125 +101641 -0.391510009765625 +101642 -0.385345458984375 +101643 -0.3419189453125 +101644 -0.28289794921875 +101645 -0.251617431640625 +101646 -0.266143798828125 +101647 -0.273345947265625 +101648 -0.216796875 +101649 -0.128265380859375 +101650 -0.068145751953125 +101651 -0.0430908203125 +101652 -0.024444580078125 +101653 0.020721435546875 +101654 0.124481201171875 +101655 0.25787353515625 +101656 0.379119873046875 +101657 0.47991943359375 +101658 0.5281982421875 +101659 0.511138916015625 +101660 0.456207275390625 +101661 0.407470703125 +101662 0.383758544921875 +101663 0.35687255859375 +101664 0.31182861328125 +101665 0.250885009765625 +101666 0.1654052734375 +101667 0.035247802734375 +101668 -0.142059326171875 +101669 -0.33563232421875 +101670 -0.5345458984375 +101671 -0.72186279296875 +101672 -0.836669921875 +101673 -0.8326416015625 +101674 -0.7296142578125 +101675 -0.582550048828125 +101676 -0.440093994140625 +101677 -0.324310302734375 +101678 -0.20147705078125 +101679 -0.044647216796875 +101680 0.103973388671875 +101681 0.202392578125 +101682 0.264495849609375 +101683 0.338897705078125 +101684 0.443817138671875 +101685 0.545074462890625 +101686 0.6173095703125 +101687 0.6524658203125 +101688 0.66339111328125 +101689 0.6561279296875 +101690 0.606781005859375 +101691 0.501190185546875 +101692 0.352783203125 +101693 0.176544189453125 +101694 -0.034820556640625 +101695 -0.258209228515625 +101696 -0.44244384765625 +101697 -0.5753173828125 +101698 -0.65203857421875 +101699 -0.641632080078125 +101700 -0.562164306640625 +101701 -0.458038330078125 +101702 -0.350555419921875 +101703 -0.260528564453125 +101704 -0.192108154296875 +101705 -0.141937255859375 +101706 -0.1021728515625 +101707 -0.062896728515625 +101708 -0.011932373046875 +101709 0.062835693359375 +101710 0.148712158203125 +101711 0.241729736328125 +101712 0.34912109375 +101713 0.457305908203125 +101714 0.54388427734375 +101715 0.5728759765625 +101716 0.506591796875 +101717 0.351226806640625 +101718 0.146514892578125 +101719 -0.05523681640625 +101720 -0.21624755859375 +101721 -0.334930419921875 +101722 -0.402984619140625 +101723 -0.4412841796875 +101724 -0.49578857421875 +101725 -0.5601806640625 +101726 -0.600738525390625 +101727 -0.584228515625 +101728 -0.47930908203125 +101729 -0.27935791015625 +101730 -0.0089111328125 +101731 0.268798828125 +101732 0.482818603515625 +101733 0.60369873046875 +101734 0.650421142578125 +101735 0.66400146484375 +101736 0.6414794921875 +101737 0.572540283203125 +101738 0.498138427734375 +101739 0.439453125 +101740 0.375518798828125 +101741 0.274505615234375 +101742 0.1087646484375 +101743 -0.099395751953125 +101744 -0.3182373046875 +101745 -0.5489501953125 +101746 -0.7738037109375 +101747 -0.86383056640625 +101748 -0.870391845703125 +101749 -0.86895751953125 +101750 -0.861053466796875 +101751 -0.765869140625 +101752 -0.5301513671875 +101753 -0.214691162109375 +101754 0.137359619140625 +101755 0.474822998046875 +101756 0.76239013671875 +101757 0.867462158203125 +101758 0.870361328125 +101759 0.86480712890625 +101760 0.831817626953125 +101761 0.677581787109375 +101762 0.495880126953125 +101763 0.30767822265625 +101764 0.116180419921875 +101765 -0.110748291015625 +101766 -0.381805419921875 +101767 -0.6572265625 +101768 -0.857421875 +101769 -0.870391845703125 +101770 -0.870391845703125 +101771 -0.86444091796875 +101772 -0.85723876953125 +101773 -0.790008544921875 +101774 -0.62847900390625 +101775 -0.3956298828125 +101776 -0.126708984375 +101777 0.150115966796875 +101778 0.424041748046875 +101779 0.670623779296875 +101780 0.854522705078125 +101781 0.866485595703125 +101782 0.86920166015625 +101783 0.8653564453125 +101784 0.857147216796875 +101785 0.766845703125 +101786 0.628509521484375 +101787 0.462127685546875 +101788 0.297210693359375 +101789 0.14862060546875 +101790 -0.00537109375 +101791 -0.15753173828125 +101792 -0.31304931640625 +101793 -0.48876953125 +101794 -0.6416015625 +101795 -0.751373291015625 +101796 -0.84619140625 +101797 -0.861297607421875 +101798 -0.863250732421875 +101799 -0.856597900390625 +101800 -0.7498779296875 +101801 -0.624542236328125 +101802 -0.47808837890625 +101803 -0.253387451171875 +101804 0.003692626953125 +101805 0.2257080078125 +101806 0.427154541015625 +101807 0.643218994140625 +101808 0.855926513671875 +101809 0.870361328125 +101810 0.870361328125 +101811 0.862762451171875 +101812 0.79669189453125 +101813 0.595794677734375 +101814 0.362152099609375 +101815 0.1270751953125 +101816 -0.086944580078125 +101817 -0.2784423828125 +101818 -0.484832763671875 +101819 -0.729583740234375 +101820 -0.86688232421875 +101821 -0.870391845703125 +101822 -0.86859130859375 +101823 -0.86279296875 +101824 -0.817962646484375 +101825 -0.6116943359375 +101826 -0.3128662109375 +101827 0.039398193359375 +101828 0.422821044921875 +101829 0.805145263671875 +101830 0.870361328125 +101831 0.870361328125 +101832 0.860015869140625 +101833 0.727935791015625 +101834 0.48114013671875 +101835 0.2059326171875 +101836 -0.06103515625 +101837 -0.29913330078125 +101838 -0.516204833984375 +101839 -0.7252197265625 +101840 -0.85980224609375 +101841 -0.870391845703125 +101842 -0.870391845703125 +101843 -0.858062744140625 +101844 -0.673004150390625 +101845 -0.42694091796875 +101846 -0.2100830078125 +101847 -0.0362548828125 +101848 0.10943603515625 +101849 0.23516845703125 +101850 0.373687744140625 +101851 0.517791748046875 +101852 0.602783203125 +101853 0.635711669921875 +101854 0.655181884765625 +101855 0.65948486328125 +101856 0.651275634765625 +101857 0.61846923828125 +101858 0.53753662109375 +101859 0.404144287109375 +101860 0.22186279296875 +101861 0.003997802734375 +101862 -0.22100830078125 +101863 -0.42449951171875 +101864 -0.579833984375 +101865 -0.641876220703125 +101866 -0.6177978515625 +101867 -0.575531005859375 +101868 -0.526336669921875 +101869 -0.42645263671875 +101870 -0.2581787109375 +101871 -0.068695068359375 +101872 0.09222412109375 +101873 0.232147216796875 +101874 0.3509521484375 +101875 0.410064697265625 +101876 0.372955322265625 +101877 0.2554931640625 +101878 0.10711669921875 +101879 -0.052886962890625 +101880 -0.186279296875 +101881 -0.23291015625 +101882 -0.209442138671875 +101883 -0.174163818359375 +101884 -0.126739501953125 +101885 -0.048126220703125 +101886 0.0426025390625 +101887 0.10748291015625 +101888 0.1409912109375 +101889 0.19708251953125 +101890 0.273651123046875 +101891 0.31768798828125 +101892 0.341094970703125 +101893 0.368011474609375 +101894 0.37249755859375 +101895 0.30072021484375 +101896 0.1517333984375 +101897 -0.01470947265625 +101898 -0.1883544921875 +101899 -0.372711181640625 +101900 -0.51397705078125 +101901 -0.57177734375 +101902 -0.53948974609375 +101903 -0.43511962890625 +101904 -0.2962646484375 +101905 -0.161102294921875 +101906 -0.0435791015625 +101907 0.060394287109375 +101908 0.13665771484375 +101909 0.170135498046875 +101910 0.16552734375 +101911 0.15728759765625 +101912 0.150787353515625 +101913 0.12200927734375 +101914 0.080108642578125 +101915 0.05126953125 +101916 0.062896728515625 +101917 0.09271240234375 +101918 0.092987060546875 +101919 0.07855224609375 +101920 0.06427001953125 +101921 0.0347900390625 +101922 -0.01171875 +101923 -0.056060791015625 +101924 -0.055511474609375 +101925 -0.010467529296875 +101926 0.02508544921875 +101927 0.025665283203125 +101928 0.017333984375 +101929 0.00189208984375 +101930 -0.03173828125 +101931 -0.071502685546875 +101932 -0.13543701171875 +101933 -0.219970703125 +101934 -0.300506591796875 +101935 -0.376312255859375 +101936 -0.416107177734375 +101937 -0.371124267578125 +101938 -0.242279052734375 +101939 -0.069732666015625 +101940 0.125640869140625 +101941 0.31268310546875 +101942 0.45501708984375 +101943 0.554779052734375 +101944 0.61065673828125 +101945 0.610931396484375 +101946 0.531463623046875 +101947 0.3883056640625 +101948 0.23468017578125 +101949 0.095245361328125 +101950 -0.00396728515625 +101951 -0.04852294921875 +101952 -0.055145263671875 +101953 -0.0758056640625 +101954 -0.138702392578125 +101955 -0.209197998046875 +101956 -0.289031982421875 +101957 -0.37884521484375 +101958 -0.456329345703125 +101959 -0.51641845703125 +101960 -0.519287109375 +101961 -0.458251953125 +101962 -0.384796142578125 +101963 -0.323699951171875 +101964 -0.269287109375 +101965 -0.1951904296875 +101966 -0.100006103515625 +101967 -0.01055908203125 +101968 0.1033935546875 +101969 0.24908447265625 +101970 0.373199462890625 +101971 0.45806884765625 +101972 0.511474609375 +101973 0.565399169921875 +101974 0.61138916015625 +101975 0.5897216796875 +101976 0.4906005859375 +101977 0.33148193359375 +101978 0.147796630859375 +101979 -0.01873779296875 +101980 -0.140289306640625 +101981 -0.191986083984375 +101982 -0.184295654296875 +101983 -0.161834716796875 +101984 -0.166595458984375 +101985 -0.19390869140625 +101986 -0.22442626953125 +101987 -0.279754638671875 +101988 -0.3389892578125 +101989 -0.3543701171875 +101990 -0.348175048828125 +101991 -0.32598876953125 +101992 -0.2581787109375 +101993 -0.139801025390625 +101994 0.014617919921875 +101995 0.144378662109375 +101996 0.221038818359375 +101997 0.27069091796875 +101998 0.294036865234375 +101999 0.311767578125 +102000 0.339141845703125 +102001 0.360260009765625 +102002 0.360504150390625 +102003 0.308380126953125 +102004 0.18170166015625 +102005 0.0047607421875 +102006 -0.17559814453125 +102007 -0.3143310546875 +102008 -0.36785888671875 +102009 -0.36248779296875 +102010 -0.343536376953125 +102011 -0.3018798828125 +102012 -0.231414794921875 +102013 -0.117645263671875 +102014 0.007049560546875 +102015 0.087982177734375 +102016 0.13946533203125 +102017 0.17425537109375 +102018 0.188201904296875 +102019 0.171234130859375 +102020 0.118438720703125 +102021 0.05706787109375 +102022 -0.010711669921875 +102023 -0.0914306640625 +102024 -0.162322998046875 +102025 -0.194549560546875 +102026 -0.1492919921875 +102027 -0.02166748046875 +102028 0.124053955078125 +102029 0.211151123046875 +102030 0.240447998046875 +102031 0.242218017578125 +102032 0.2257080078125 +102033 0.194366455078125 +102034 0.115509033203125 +102035 0.0128173828125 +102036 -0.053802490234375 +102037 -0.110626220703125 +102038 -0.199493408203125 +102039 -0.29437255859375 +102040 -0.33221435546875 +102041 -0.27972412109375 +102042 -0.185333251953125 +102043 -0.128204345703125 +102044 -0.115692138671875 +102045 -0.116455078125 +102046 -0.105926513671875 +102047 -0.053955078125 +102048 0.048797607421875 +102049 0.157318115234375 +102050 0.212005615234375 +102051 0.218475341796875 +102052 0.23724365234375 +102053 0.30535888671875 +102054 0.38128662109375 +102055 0.404449462890625 +102056 0.3944091796875 +102057 0.3885498046875 +102058 0.362640380859375 +102059 0.27362060546875 +102060 0.11712646484375 +102061 -0.054901123046875 +102062 -0.19085693359375 +102063 -0.28570556640625 +102064 -0.339263916015625 +102065 -0.3775634765625 +102066 -0.445709228515625 +102067 -0.535064697265625 +102068 -0.629058837890625 +102069 -0.697601318359375 +102070 -0.70391845703125 +102071 -0.6424560546875 +102072 -0.491241455078125 +102073 -0.265716552734375 +102074 -0.023712158203125 +102075 0.201751708984375 +102076 0.375823974609375 +102077 0.485076904296875 +102078 0.56884765625 +102079 0.634765625 +102080 0.63763427734375 +102081 0.5660400390625 +102082 0.4720458984375 +102083 0.40692138671875 +102084 0.3778076171875 +102085 0.376953125 +102086 0.371978759765625 +102087 0.313140869140625 +102088 0.184417724609375 +102089 0.011199951171875 +102090 -0.171051025390625 +102091 -0.33740234375 +102092 -0.47198486328125 +102093 -0.560394287109375 +102094 -0.58056640625 +102095 -0.54754638671875 +102096 -0.508575439453125 +102097 -0.459503173828125 +102098 -0.394378662109375 +102099 -0.35260009765625 +102100 -0.31170654296875 +102101 -0.197418212890625 +102102 -0.007965087890625 +102103 0.207489013671875 +102104 0.409210205078125 +102105 0.57208251953125 +102106 0.66595458984375 +102107 0.65875244140625 +102108 0.56744384765625 +102109 0.431396484375 +102110 0.29443359375 +102111 0.182464599609375 +102112 0.06365966796875 +102113 -0.075958251953125 +102114 -0.189422607421875 +102115 -0.271942138671875 +102116 -0.342529296875 +102117 -0.364166259765625 +102118 -0.327239990234375 +102119 -0.2769775390625 +102120 -0.253692626953125 +102121 -0.24365234375 +102122 -0.1983642578125 +102123 -0.116241455078125 +102124 -0.036834716796875 +102125 0.034881591796875 +102126 0.09124755859375 +102127 0.10888671875 +102128 0.125518798828125 +102129 0.15771484375 +102130 0.17828369140625 +102131 0.17108154296875 +102132 0.129974365234375 +102133 0.082427978515625 +102134 0.027679443359375 +102135 -0.065643310546875 +102136 -0.15936279296875 +102137 -0.21307373046875 +102138 -0.234649658203125 +102139 -0.2001953125 +102140 -0.119171142578125 +102141 -0.024749755859375 +102142 0.085784912109375 +102143 0.178131103515625 +102144 0.215576171875 +102145 0.211456298828125 +102146 0.17523193359375 +102147 0.128753662109375 +102148 0.1019287109375 +102149 0.0743408203125 +102150 0.04327392578125 +102151 0.038177490234375 +102152 0.076263427734375 +102153 0.14105224609375 +102154 0.186431884765625 +102155 0.188812255859375 +102156 0.1390380859375 +102157 0.041778564453125 +102158 -0.079437255859375 +102159 -0.219390869140625 +102160 -0.367828369140625 +102161 -0.494873046875 +102162 -0.556243896484375 +102163 -0.508697509765625 +102164 -0.3756103515625 +102165 -0.218902587890625 +102166 -0.063751220703125 +102167 0.091552734375 +102168 0.23602294921875 +102169 0.342987060546875 +102170 0.39520263671875 +102171 0.389373779296875 +102172 0.324249267578125 +102173 0.224090576171875 +102174 0.124267578125 +102175 0.037078857421875 +102176 -0.010101318359375 +102177 -0.019439697265625 +102178 -0.022796630859375 +102179 -0.001556396484375 +102180 0.056304931640625 +102181 0.106719970703125 +102182 0.096893310546875 +102183 0.042694091796875 +102184 -0.018035888671875 +102185 -0.07586669921875 +102186 -0.11944580078125 +102187 -0.15972900390625 +102188 -0.202606201171875 +102189 -0.24859619140625 +102190 -0.30517578125 +102191 -0.36212158203125 +102192 -0.39141845703125 +102193 -0.35528564453125 +102194 -0.249969482421875 +102195 -0.092864990234375 +102196 0.08905029296875 +102197 0.2352294921875 +102198 0.318817138671875 +102199 0.358642578125 +102200 0.347747802734375 +102201 0.28564453125 +102202 0.223175048828125 +102203 0.196746826171875 +102204 0.179840087890625 +102205 0.155548095703125 +102206 0.151214599609375 +102207 0.156951904296875 +102208 0.13177490234375 +102209 0.100799560546875 +102210 0.087127685546875 +102211 0.05487060546875 +102212 -0.009002685546875 +102213 -0.10400390625 +102214 -0.229400634765625 +102215 -0.35552978515625 +102216 -0.441925048828125 +102217 -0.473846435546875 +102218 -0.464813232421875 +102219 -0.419097900390625 +102220 -0.334320068359375 +102221 -0.227935791015625 +102222 -0.12347412109375 +102223 -0.02764892578125 +102224 0.077667236328125 +102225 0.2132568359375 +102226 0.38885498046875 +102227 0.582794189453125 +102228 0.734039306640625 +102229 0.800140380859375 +102230 0.7783203125 +102231 0.6651611328125 +102232 0.45965576171875 +102233 0.199188232421875 +102234 -0.050689697265625 +102235 -0.23297119140625 +102236 -0.33013916015625 +102237 -0.368408203125 +102238 -0.378936767578125 +102239 -0.376983642578125 +102240 -0.37969970703125 +102241 -0.391510009765625 +102242 -0.385345458984375 +102243 -0.3419189453125 +102244 -0.28289794921875 +102245 -0.251617431640625 +102246 -0.266143798828125 +102247 -0.273345947265625 +102248 -0.216796875 +102249 -0.128265380859375 +102250 -0.068145751953125 +102251 -0.0430908203125 +102252 -0.024444580078125 +102253 0.020721435546875 +102254 0.124481201171875 +102255 0.25787353515625 +102256 0.379119873046875 +102257 0.47991943359375 +102258 0.5281982421875 +102259 0.511138916015625 +102260 0.456207275390625 +102261 0.407470703125 +102262 0.383758544921875 +102263 0.35687255859375 +102264 0.31182861328125 +102265 0.250885009765625 +102266 0.1654052734375 +102267 0.035247802734375 +102268 -0.142059326171875 +102269 -0.33563232421875 +102270 -0.5345458984375 +102271 -0.72186279296875 +102272 -0.836669921875 +102273 -0.8326416015625 +102274 -0.7296142578125 +102275 -0.582550048828125 +102276 -0.440093994140625 +102277 -0.324310302734375 +102278 -0.20147705078125 +102279 -0.044647216796875 +102280 0.103973388671875 +102281 0.202392578125 +102282 0.264495849609375 +102283 0.338897705078125 +102284 0.443817138671875 +102285 0.545074462890625 +102286 0.6173095703125 +102287 0.6524658203125 +102288 0.66339111328125 +102289 0.6561279296875 +102290 0.606781005859375 +102291 0.501190185546875 +102292 0.352783203125 +102293 0.176544189453125 +102294 -0.034820556640625 +102295 -0.258209228515625 +102296 -0.44244384765625 +102297 -0.5753173828125 +102298 -0.65203857421875 +102299 -0.641632080078125 +102300 -0.562164306640625 +102301 -0.458038330078125 +102302 -0.350555419921875 +102303 -0.260528564453125 +102304 -0.192108154296875 +102305 -0.141937255859375 +102306 -0.1021728515625 +102307 -0.062896728515625 +102308 -0.011932373046875 +102309 0.062835693359375 +102310 0.148712158203125 +102311 0.241729736328125 +102312 0.34912109375 +102313 0.457305908203125 +102314 0.54388427734375 +102315 0.5728759765625 +102316 0.506591796875 +102317 0.351226806640625 +102318 0.146514892578125 +102319 -0.05523681640625 +102320 -0.21624755859375 +102321 -0.334930419921875 +102322 -0.402984619140625 +102323 -0.4412841796875 +102324 -0.49578857421875 +102325 -0.5601806640625 +102326 -0.600738525390625 +102327 -0.584228515625 +102328 -0.47930908203125 +102329 -0.27935791015625 +102330 -0.0089111328125 +102331 0.268798828125 +102332 0.482818603515625 +102333 0.60369873046875 +102334 0.650421142578125 +102335 0.66400146484375 +102336 0.6414794921875 +102337 0.572540283203125 +102338 0.498138427734375 +102339 0.439453125 +102340 0.375518798828125 +102341 0.274505615234375 +102342 0.1087646484375 +102343 -0.099395751953125 +102344 -0.3182373046875 +102345 -0.5489501953125 +102346 -0.7738037109375 +102347 -0.86383056640625 +102348 -0.870391845703125 +102349 -0.86895751953125 +102350 -0.861053466796875 +102351 -0.765869140625 +102352 -0.5301513671875 +102353 -0.214691162109375 +102354 0.137359619140625 +102355 0.474822998046875 +102356 0.76239013671875 +102357 0.867462158203125 +102358 0.870361328125 +102359 0.86480712890625 +102360 0.831817626953125 +102361 0.677581787109375 +102362 0.495880126953125 +102363 0.30767822265625 +102364 0.116180419921875 +102365 -0.110748291015625 +102366 -0.381805419921875 +102367 -0.6572265625 +102368 -0.857421875 +102369 -0.870391845703125 +102370 -0.870391845703125 +102371 -0.86444091796875 +102372 -0.85723876953125 +102373 -0.790008544921875 +102374 -0.62847900390625 +102375 -0.3956298828125 +102376 -0.126708984375 +102377 0.150115966796875 +102378 0.424041748046875 +102379 0.670623779296875 +102380 0.854522705078125 +102381 0.866485595703125 +102382 0.86920166015625 +102383 0.8653564453125 +102384 0.857147216796875 +102385 0.766845703125 +102386 0.628509521484375 +102387 0.462127685546875 +102388 0.297210693359375 +102389 0.14862060546875 +102390 -0.00537109375 +102391 -0.15753173828125 +102392 -0.31304931640625 +102393 -0.48876953125 +102394 -0.6416015625 +102395 -0.751373291015625 +102396 -0.84619140625 +102397 -0.861297607421875 +102398 -0.863250732421875 +102399 -0.856597900390625 diff --git a/tests/circuitpython/deque_subclass.py b/tests/circuitpython/deque_subclass.py new file mode 100644 index 0000000000000..5708407a9b630 --- /dev/null +++ b/tests/circuitpython/deque_subclass.py @@ -0,0 +1,40 @@ +try: + from collections import deque +except ImportError: + print("SKIP") + raise SystemExit + + +class DequeSubclass(deque): + def __init__(self, values, maxlen): + super().__init__(values, maxlen) + + def pop(self): + print("pop") + return super().pop() + + def popleft(self): + print("popleft") + return super().popleft() + + def append(self, value): + print("append") + return super().append(value) + + def appendleft(self, value): + print("appendleft") + return super().appendleft(value) + + def extend(self, value): + print("extend") + return super().extend(value) + + +d = DequeSubclass([1, 2, 3], 10) +print(d.append(4)) +print(d.appendleft(0)) +print(d.pop()) +print(d.popleft()) +d.extend([6, 7]) +# calling list() tests iteration. +print(list(d)) diff --git a/tests/circuitpython/getenv.py b/tests/circuitpython/getenv.py index 941674d114a91..3647b562eed13 100644 --- a/tests/circuitpython/getenv.py +++ b/tests/circuitpython/getenv.py @@ -58,7 +58,7 @@ def ioctl(self, op, arg): b'key = """\n', b"key =\n", b'key="', - b'key = strings must be quoted\n', + b"key = this is an unquoted string\n", ] @@ -75,6 +75,7 @@ def run_test(key, content): run_test("key", b"") +# key12 does not exist for i in range(13): run_test(f"key{i}", content_good) @@ -82,11 +83,9 @@ def run_test(key, content): for i in range(13): run_test(f"key{i}", content_good) -run_test(f"K", b"K = 7\r\n") -print(getenv_int("K")) - # Test value without trailing newline run_test(f"noeol", b"noeol=3") +# These return None now for content in content_bad: run_test("key", content) diff --git a/tests/circuitpython/getenv.py.exp b/tests/circuitpython/getenv.py.exp index 67707eb67fd75..89d654403dcf9 100644 --- a/tests/circuitpython/getenv.py.exp +++ b/tests/circuitpython/getenv.py.exp @@ -1,6 +1,6 @@ key None key0 'hello world' -key1 7 +key1 '7' key2 '\n' key3 'Áx' key4 'Áx' @@ -9,11 +9,11 @@ key6 '\t\r\x08' key7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' key8 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' key9 'hello comment' -key10 127 -key11 0 +key10 '0x7f' +key11 '0' key12 None key0 'hello world' -key1 7 +key1 '7' key2 '\n' key3 'Áx' key4 'Áx' @@ -22,14 +22,12 @@ key6 '\t\r\x08' key7 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' key8 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' key9 'hello comment' -key10 127 -key11 0 +key10 '0x7f' +key11 '0' key12 None -K 7 -7 -noeol 3 -key Invalid byte '\n' -key Invalid byte '"' -key invalid syntax for integer with base 10: '' -key Invalid byte 'EOF' -key invalid syntax for integer with base 10: 'strings must be quoted' +noeol '3' +key None +key None +key None +key None +key 'this is an unquoted string' diff --git a/tests/circuitpython/issue9705.py b/tests/circuitpython/issue9705.py new file mode 100644 index 0000000000000..0c694cc1b9fb1 --- /dev/null +++ b/tests/circuitpython/issue9705.py @@ -0,0 +1,30 @@ +import audiomp3, audiocore + +TEST_FILE = ( + __file__.rsplit("/", 1)[0] + + "/../circuitpython-manual/audiocore/jeplayer-splash-44100-stereo.mp3" +) + + +def loudness(values): + return sum(abs(a) for a in values) + + +def print_frame_loudness(decoder, n): + for i in range(n): + result, buf = audiocore.get_buffer(decoder) + print(f"{i} {result} {loudness(buf):5.0f}") + print() + + +# First frames +decoder = audiomp3.MP3Decoder(TEST_FILE) +print_frame_loudness(decoder, 8) + +# First frames (fresh decoder) +decoder = audiomp3.MP3Decoder(TEST_FILE) +print_frame_loudness(decoder, 2) + +# First frames (reopen) +decoder.open(TEST_FILE) +print_frame_loudness(decoder, 3) diff --git a/tests/circuitpython/issue9705.py.exp b/tests/circuitpython/issue9705.py.exp new file mode 100644 index 0000000000000..b57f8e63395c6 --- /dev/null +++ b/tests/circuitpython/issue9705.py.exp @@ -0,0 +1,16 @@ +0 1 0 +1 1 25 +2 1 830 +3 1 880 +4 1 932 +5 1 892 +6 1 869 +7 1 839 + +0 1 0 +1 1 25 + +0 1 0 +1 1 25 +2 1 830 + diff --git a/tests/circuitpython/mfm.py b/tests/circuitpython/mfm.py index 9839b5c756073..fd2745bc11d03 100644 --- a/tests/circuitpython/mfm.py +++ b/tests/circuitpython/mfm.py @@ -1,76 +1,76 @@ import floppyio mfm_content = ( - b'HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH' - b'H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0' - b'0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H' - b'HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH' - b'H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0' - b'0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H' - b'HHH00HHHH00HHHH00HHHH00HHHH00HHHH00H00000000000000000000000000' - b'00000000000000000000000000000000000000000000000000000000000000' - b'0000000H0H`H`0H`H`0H`H`00000H0HHH00HHHH00HHHH00HHHH00HHHH00HHH' - b'H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0' - b'0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H' - b'HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH' - b'H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0' - b'0HHHH00HHHH00HHHH00H000000000000000000000000000000000000000000' - b'00000000000000000000000000000000000000000000000000000H`H`H0`H`' - b'H0`H`H0000000H0000000000000000000000HH0000H`0HH`HH0`000`HH00HH' - b'HH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH' - b'00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00' - b'H0000000000000000000000000000000000000000000000000000000000000' - b'0000000000000000000000000000000000H`H`H0`H`H0`H`H00000`0`0H00H' - b'`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0' - b'HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH' - b'H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H' - b'H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0' - b'H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0' - b'0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H' - b'`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0' - b'HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH' - b'0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0' - b'H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0' - b'H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0' - b'0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H' - b'`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0' - b'HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH' - b'H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H' - b'H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0' - b'H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0' - b'0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H' - b'`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0' - b'HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH' - b'0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0' - b'H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0' - b'H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0' - b'0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H' - b'`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0' - b'HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH' - b'H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H' - b'H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0' - b'H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0' - b'0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H' - b'`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0' - b'HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH' - b'0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0' - b'H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0' - b'H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0' - b'0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H' - b'`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0' - b'HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH' - b'H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H' - b'H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0' - b'H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0' - b'0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H' - b'`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0' - b'HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH' - b'0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0' - b'H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0' - b'H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0' - b'0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H' - b'`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0' - b'HH0HH0H00H`0HHH0H0H00H`0HH0``HHHH0`0000hhhhhhhhhhhhhhhhhhhhhhh' + b"HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH" + b"H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0" + b"0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H" + b"HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH" + b"H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0" + b"0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H" + b"HHH00HHHH00HHHH00HHHH00HHHH00HHHH00H00000000000000000000000000" + b"00000000000000000000000000000000000000000000000000000000000000" + b"0000000H0H`H`0H`H`0H`H`00000H0HHH00HHHH00HHHH00HHHH00HHHH00HHH" + b"H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0" + b"0HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00H" + b"HHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHH" + b"H00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH0" + b"0HHHH00HHHH00HHHH00H000000000000000000000000000000000000000000" + b"00000000000000000000000000000000000000000000000000000H`H`H0`H`" + b"H0`H`H0000000H0000000000000000000000HH0000H`0HH`HH0`000`HH00HH" + b"HH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH" + b"00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00HHHH00" + b"H0000000000000000000000000000000000000000000000000000000000000" + b"0000000000000000000000000000000000H`H`H0`H`H0`H`H00000`0`0H00H" + b"`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0" + b"HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH" + b"H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H" + b"H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0" + b"H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0" + b"0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H" + b"`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0" + b"HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH" + b"0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0" + b"H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0" + b"H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0" + b"0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H" + b"`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0" + b"HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH" + b"H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H" + b"H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0" + b"H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0" + b"0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H" + b"`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0" + b"HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH" + b"0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0" + b"H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0" + b"H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0" + b"0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H" + b"`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0" + b"HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH" + b"H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H" + b"H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0" + b"H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0" + b"0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H" + b"`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0" + b"HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH" + b"0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0" + b"H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0" + b"H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0" + b"0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H" + b"`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0" + b"HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HH" + b"H0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0H" + b"H0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0" + b"H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H0" + b"0H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H" + b"`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0" + b"HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH" + b"0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0" + b"H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0" + b"H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H0" + b"0H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H" + b"`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0HH0HH0H00H`0HHH0H0H00H`0" + b"HH0HH0H00H`0HHH0H0H00H`0HH0``HHHH0`0000hhhhhhhhhhhhhhhhhhhhhhh" ) b = bytearray(512) diff --git a/tests/circuitpython/miditrack.py.exp b/tests/circuitpython/miditrack.py.exp index 5aedd79a6b3b0..22a78e54459a8 100644 --- a/tests/circuitpython/miditrack.py.exp +++ b/tests/circuitpython/miditrack.py.exp @@ -1,4 +1,4 @@ (0, 1, 512, 1) -1 [-16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, -16384, 16383, 16383] +1 [-16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383] (0, 1, 512, 1) -1 [0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16384, -16384, -16384, -16384, -16384, -16384, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0] +1 [0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0, 0, 0, 0, 0, -16383, -16383, -16383, -16383, -16383, -16383, 0, 0, 0, 0, 0, 0, 16383, 16383, 16383, 16383, 16383, 16383, 0, 0] diff --git a/tests/circuitpython/synth_note_amplitude.py.exp b/tests/circuitpython/synth_note_amplitude.py.exp index 7339e9aa7b58a..c5531195b74ce 100644 --- a/tests/circuitpython/synth_note_amplitude.py.exp +++ b/tests/circuitpython/synth_note_amplitude.py.exp @@ -499,504 +499,504 @@ 0.06225000000000001 0.004058837890625 0.7762060546875 0.06237500000000001 0.0 0.7762060546875 0.0625 0.0 0.7762060546875 -0.06262499999999999 -0.00408935546875 0.7762060546875 -0.06274999999999999 -0.00408935546875 0.7762060546875 -0.06287500000000001 -0.008148193359375 0.7762060546875 -0.063 -0.01220703125 0.7762060546875 -0.063125 -0.01220703125 0.7762060546875 -0.06325000000000001 -0.016265869140625 0.7762060546875 -0.063375 -0.016265869140625 0.7762060546875 -0.0635 -0.02032470703125 0.7762060546875 -0.063625 -0.024383544921875 0.7762060546875 -0.06375 -0.024383544921875 0.7762060546875 -0.063875 -0.0284423828125 0.7762060546875 -0.064 -0.034698486328125 0.9474169921874999 -0.064125 -0.039642333984375 0.9474169921874999 -0.06425000000000001 -0.044586181640625 0.9474169921874999 -0.064375 -0.044586181640625 0.9474169921874999 -0.0645 -0.049530029296875 0.9474169921874999 -0.064625 -0.049530029296875 0.9474169921874999 -0.06475 -0.054443359375 0.9474169921874999 -0.06487500000000001 -0.059356689453125 0.9474169921874999 -0.065 -0.059356689453125 0.9474169921874999 -0.065125 -0.064300537109375 0.9474169921874999 -0.06525 -0.064300537109375 0.9474169921874999 -0.06537500000000001 -0.0692138671875 0.9474169921874999 -0.06550000000000001 -0.0740966796875 0.9474169921874999 -0.065625 -0.0740966796875 0.9474169921874999 -0.06574999999999999 -0.079010009765625 0.9474169921874999 -0.065875 -0.079010009765625 0.9474169921874999 -0.06600000000000001 -0.083892822265625 0.9474169921874999 -0.066125 -0.088775634765625 0.9474169921874999 -0.06625000000000001 -0.088775634765625 0.9474169921874999 -0.06637500000000001 -0.0936279296875 0.9474169921874999 -0.0665 -0.0936279296875 0.9474169921874999 -0.066625 -0.098480224609375 0.9474169921874999 -0.06675 -0.10333251953125 0.9474169921874999 -0.06687500000000001 -0.10333251953125 0.9474169921874999 -0.067 -0.108184814453125 0.9474169921874999 -0.067125 -0.108184814453125 0.9474169921874999 -0.06725000000000001 -0.113006591796875 0.9474169921874999 -0.06737500000000001 -0.1177978515625 0.9474169921874999 -0.0675 -0.1177978515625 0.9474169921874999 -0.067625 -0.122589111328125 0.9474169921874999 -0.06775 -0.122589111328125 0.9474169921874999 -0.06787500000000001 -0.12738037109375 0.9474169921874999 -0.06800000000000001 -0.132171630859375 0.9474169921874999 -0.068125 -0.132171630859375 0.9474169921874999 -0.06825000000000001 -0.13690185546875 0.9474169921874999 -0.068375 -0.13690185546875 0.9474169921874999 -0.06850000000000001 -0.14166259765625 0.9474169921874999 -0.06862500000000001 -0.146392822265625 0.9474169921874999 -0.06875 -0.146392822265625 0.9474169921874999 -0.06887500000000001 -0.151092529296875 0.9474169921874999 -0.069 -0.151092529296875 0.9474169921874999 -0.06912500000000001 -0.155792236328125 0.9474169921874999 -0.06925000000000001 -0.16046142578125 0.9474169921874999 -0.06937500000000001 -0.16046142578125 0.9474169921874999 -0.06950000000000001 -0.165130615234375 0.9474169921874999 -0.069625 -0.165130615234375 0.9474169921874999 -0.06975 -0.169769287109375 0.9474169921874999 -0.06987500000000001 -0.17437744140625 0.9474169921874999 -0.07000000000000001 -0.17437744140625 0.9474169921874999 -0.070125 -0.178985595703125 0.9474169921874999 -0.07025000000000001 -0.178985595703125 0.9474169921874999 -0.07037500000000001 -0.183563232421875 0.9474169921874999 -0.07050000000000001 -0.188140869140625 0.9474169921874999 -0.070625 -0.188140869140625 0.9474169921874999 -0.07075 -0.192657470703125 0.9474169921874999 -0.07087500000000001 -0.192657470703125 0.9474169921874999 -0.07100000000000001 -0.19720458984375 0.9474169921874999 -0.07112500000000001 -0.201690673828125 0.9474169921874999 -0.07125000000000002 -0.201690673828125 0.9474169921874999 -0.07137500000000001 -0.2061767578125 0.9474169921874999 -0.0715 -0.2061767578125 0.9474169921874999 -0.07162500000000001 -0.21063232421875 0.9474169921874999 -0.07175000000000001 -0.215057373046875 0.9474169921874999 -0.07187500000000001 -0.215057373046875 0.9474169921874999 -0.07200000000000001 -0.219451904296875 0.9474169921874999 -0.07212499999999999 -0.219451904296875 0.9474169921874999 -0.07225 -0.223846435546875 0.9474169921874999 -0.07237499999999999 -0.22821044921875 0.9474169921874999 -0.0725 -0.22821044921875 0.9474169921874999 -0.07262499999999999 -0.2325439453125 0.9474169921874999 -0.07274999999999999 -0.2325439453125 0.9474169921874999 -0.072875 -0.236846923828125 0.9474169921874999 -0.073 -0.241119384765625 0.9474169921874999 -0.073125 -0.241119384765625 0.9474169921874999 -0.07324999999999999 -0.245391845703125 0.9474169921874999 -0.07337499999999999 -0.245391845703125 0.9474169921874999 -0.0735 -0.249603271484375 0.9474169921874999 -0.073625 -0.253814697265625 0.9474169921874999 -0.07374999999999999 -0.253814697265625 0.9474169921874999 -0.073875 -0.25799560546875 0.9474169921874999 -0.074 -0.25799560546875 0.9474169921874999 -0.074125 -0.26214599609375 0.9474169921874999 -0.07424999999999999 -0.266265869140625 0.9474169921874999 -0.07437499999999999 -0.266265869140625 0.9474169921874999 -0.0745 -0.270355224609375 0.9474169921874999 -0.07462499999999999 -0.270355224609375 0.9474169921874999 -0.07475 -0.2744140625 0.9474169921874999 -0.07487500000000001 -0.278411865234375 0.9474169921874999 -0.075 -0.278411865234375 0.9474169921874999 -0.07512499999999999 -0.282440185546875 0.9474169921874999 -0.07524999999999999 -0.282440185546875 0.9474169921874999 -0.075375 -0.286376953125 0.9474169921874999 -0.0755 -0.29034423828125 0.9474169921874999 -0.075625 -0.29034423828125 0.9474169921874999 -0.07574999999999999 -0.29425048828125 0.9474169921874999 -0.075875 -0.29425048828125 0.9474169921874999 -0.076 -0.298095703125 0.9474169921874999 -0.076125 -0.30194091796875 0.9474169921874999 -0.07625 -0.30194091796875 0.9474169921874999 -0.07637499999999999 -0.305755615234375 0.9474169921874999 -0.0765 -0.305755615234375 0.9474169921874999 -0.076625 -0.30950927734375 0.9474169921874999 -0.07675 -0.313262939453125 0.9474169921874999 -0.076875 -0.313262939453125 0.9474169921874999 -0.077 -0.31695556640625 0.9474169921874999 -0.077125 -0.31695556640625 0.9474169921874999 -0.07725 -0.320648193359375 0.9474169921874999 -0.07737499999999999 -0.324249267578125 0.9474169921874999 -0.0775 -0.324249267578125 0.9474169921874999 -0.077625 -0.327850341796875 0.9474169921874999 -0.07774999999999999 -0.327850341796875 0.9474169921874999 -0.07787500000000001 -0.3314208984375 0.9474169921874999 -0.07800000000000001 -0.3349609375 0.9474169921874999 -0.078125 -0.3349609375 0.9474169921874999 -0.07824999999999999 -0.33843994140625 0.9474169921874999 -0.07837499999999999 -0.33843994140625 0.9474169921874999 -0.07850000000000001 -0.341888427734375 0.9474169921874999 -0.078625 -0.345306396484375 0.9474169921874999 -0.07875 -0.345306396484375 0.9474169921874999 -0.07887500000000001 -0.34869384765625 0.9474169921874999 -0.079 -0.34869384765625 0.9474169921874999 -0.079125 -0.352020263671875 0.9474169921874999 -0.07925 -0.355316162109375 0.9474169921874999 -0.079375 -0.355316162109375 0.9474169921874999 -0.0795 -0.35858154296875 0.9474169921874999 -0.079625 -0.35858154296875 0.9474169921874999 -0.07975 -0.36181640625 0.9474169921874999 -0.07987500000000001 -0.364990234375 0.9474169921874999 -0.08 -0.364990234375 0.9474169921874999 -0.08012499999999999 -0.368133544921875 0.9474169921874999 -0.08025 -0.368133544921875 0.9474169921874999 -0.080375 -0.3712158203125 0.9474169921874999 -0.08050000000000001 -0.374298095703125 0.9474169921874999 -0.080625 -0.374298095703125 0.9474169921874999 -0.08074999999999999 -0.377288818359375 0.9474169921874999 -0.080875 -0.377288818359375 0.9474169921874999 -0.08100000000000001 -0.380279541015625 0.9474169921874999 -0.08112500000000001 -0.38323974609375 0.9474169921874999 -0.08125 -0.38323974609375 0.9474169921874999 -0.08137499999999999 -0.3861083984375 0.9474169921874999 -0.0815 -0.3861083984375 0.9474169921874999 -0.081625 -0.38897705078125 0.9474169921874999 -0.08175000000000001 -0.39178466796875 0.9474169921874999 -0.081875 -0.39178466796875 0.9474169921874999 -0.08200000000000001 -0.394561767578125 0.9474169921874999 -0.082125 -0.394561767578125 0.9474169921874999 -0.08225 -0.39727783203125 0.9474169921874999 -0.08237500000000001 -0.39996337890625 0.9474169921874999 -0.0825 -0.39996337890625 0.9474169921874999 -0.08262500000000001 -0.402587890625 0.9474169921874999 -0.08275 -0.402587890625 0.9474169921874999 -0.08287500000000001 -0.405181884765625 0.9474169921874999 -0.08300000000000001 -0.40771484375 0.9474169921874999 -0.083125 -0.40771484375 0.9474169921874999 -0.08324999999999999 -0.410247802734375 0.9474169921874999 -0.083375 -0.410247802734375 0.9474169921874999 -0.08350000000000001 -0.412689208984375 0.9474169921874999 -0.08362500000000001 -0.41510009765625 0.9474169921874999 -0.08375 -0.41510009765625 0.9474169921874999 -0.08387500000000001 -0.417449951171875 0.9474169921874999 -0.084 -0.417449951171875 0.9474169921874999 -0.08412500000000001 -0.4197998046875 0.9474169921874999 -0.08425000000000001 -0.42205810546875 0.9474169921874999 -0.084375 -0.42205810546875 0.9474169921874999 -0.08450000000000001 -0.424285888671875 0.9474169921874999 -0.084625 -0.424285888671875 0.9474169921874999 -0.08475 -0.42645263671875 0.9474169921874999 -0.08487500000000001 -0.428619384765625 0.9474169921874999 -0.085 -0.428619384765625 0.9474169921874999 -0.08512500000000001 -0.430694580078125 0.9474169921874999 -0.08525 -0.430694580078125 0.9474169921874999 -0.085375 -0.4327392578125 0.9474169921874999 -0.08550000000000001 -0.434722900390625 0.9474169921874999 -0.085625 -0.434722900390625 0.9474169921874999 -0.08575000000000001 -0.436676025390625 0.9474169921874999 -0.08587500000000002 -0.436676025390625 0.9474169921874999 -0.08600000000000001 -0.438568115234375 0.9474169921874999 -0.08612500000000001 -0.4404296875 0.9474169921874999 -0.08625 -0.4404296875 0.9474169921874999 -0.08637499999999999 -0.442230224609375 0.9474169921874999 -0.0865 -0.442230224609375 0.9474169921874999 -0.08662500000000001 -0.4439697265625 0.9474169921874999 -0.08675000000000001 -0.4456787109375 0.9474169921874999 -0.08687500000000002 -0.4456787109375 0.9474169921874999 -0.08700000000000001 -0.44732666015625 0.9474169921874999 -0.087125 -0.44732666015625 0.9474169921874999 -0.08725000000000001 -0.448944091796875 0.9474169921874999 -0.08737500000000001 -0.45050048828125 0.9474169921874999 -0.08750000000000002 -0.45050048828125 0.9474169921874999 -0.08762500000000001 -0.451995849609375 0.9474169921874999 -0.08775 -0.451995849609375 0.9474169921874999 -0.08787500000000001 -0.453460693359375 0.9474169921874999 -0.08799999999999999 -0.454864501953125 0.9474169921874999 -0.088125 -0.454864501953125 0.9474169921874999 -0.08824999999999999 -0.45623779296875 0.9474169921874999 -0.08837499999999999 -0.45623779296875 0.9474169921874999 -0.0885 -0.457550048828125 0.9474169921874999 -0.08862500000000001 -0.45880126953125 0.9474169921874999 -0.08875 -0.45880126953125 0.9474169921874999 -0.08887499999999999 -0.46002197265625 0.9474169921874999 -0.08899999999999999 -0.46002197265625 0.9474169921874999 -0.089125 -0.461181640625 0.9474169921874999 -0.08924999999999999 -0.4622802734375 0.9474169921874999 -0.089375 -0.4622802734375 0.9474169921874999 -0.08949999999999999 -0.46331787109375 0.9474169921874999 -0.089625 -0.46331787109375 0.9474169921874999 -0.08975 -0.46435546875 0.9474169921874999 -0.08987499999999999 -0.465301513671875 0.9474169921874999 -0.09 -0.465301513671875 0.9474169921874999 -0.09012499999999999 -0.466217041015625 0.9474169921874999 -0.09025 -0.466217041015625 0.9474169921874999 -0.090375 -0.467071533203125 0.9474169921874999 -0.09050000000000001 -0.467864990234375 0.9474169921874999 -0.090625 -0.467864990234375 0.9474169921874999 -0.09074999999999999 -0.468597412109375 0.9474169921874999 -0.09087499999999999 -0.468597412109375 0.9474169921874999 -0.091 -0.46929931640625 0.9474169921874999 -0.09112500000000001 -0.469940185546875 0.9474169921874999 -0.09125 -0.469940185546875 0.9474169921874999 -0.09137499999999999 -0.470550537109375 0.9474169921874999 -0.0915 -0.470550537109375 0.9474169921874999 -0.091625 -0.471099853515625 0.9474169921874999 -0.09175000000000001 -0.471588134765625 0.9474169921874999 -0.091875 -0.471588134765625 0.9474169921874999 -0.09199999999999999 -0.4720458984375 0.9474169921874999 -0.092125 -0.4720458984375 0.9474169921874999 -0.09225 -0.472412109375 0.9474169921874999 -0.09237499999999999 -0.472747802734375 0.9474169921874999 -0.0925 -0.472747802734375 0.9474169921874999 -0.09262499999999999 -0.473052978515625 0.9474169921874999 -0.09275 -0.473052978515625 0.9474169921874999 -0.092875 -0.4732666015625 0.9474169921874999 -0.09299999999999999 -0.47344970703125 0.9474169921874999 -0.093125 -0.47344970703125 0.9474169921874999 -0.09324999999999999 -0.47357177734375 0.9474169921874999 -0.093375 -0.47357177734375 0.9474169921874999 -0.09350000000000001 -0.473663330078125 0.9474169921874999 -0.09362500000000001 -0.47369384765625 0.9474169921874999 -0.09375 -0.47369384765625 0.9474169921874999 -0.09387499999999999 -0.473663330078125 0.9474169921874999 -0.09399999999999999 -0.473663330078125 0.9474169921874999 -0.094125 -0.47357177734375 0.9474169921874999 -0.09425000000000001 -0.47344970703125 0.9474169921874999 -0.094375 -0.47344970703125 0.9474169921874999 -0.09450000000000001 -0.4732666015625 0.9474169921874999 -0.094625 -0.4732666015625 0.9474169921874999 -0.09475 -0.473052978515625 0.9474169921874999 -0.09487500000000001 -0.472747802734375 0.9474169921874999 -0.095 -0.472747802734375 0.9474169921874999 -0.09512500000000001 -0.472412109375 0.9474169921874999 -0.09525 -0.472412109375 0.9474169921874999 -0.095375 -0.4720458984375 0.9474169921874999 -0.09550000000000001 -0.471588134765625 0.9474169921874999 -0.095625 -0.471588134765625 0.9474169921874999 -0.09574999999999999 -0.471099853515625 0.9474169921874999 -0.095875 -0.471099853515625 0.9474169921874999 -0.096 -0.496368408203125 0.9993847656250001 -0.09612500000000001 -0.4957275390625 0.9993847656250001 -0.09625 -0.4957275390625 0.9993847656250001 -0.09637499999999999 -0.49505615234375 0.9993847656250001 -0.0965 -0.49505615234375 0.9993847656250001 -0.09662500000000001 -0.49432373046875 0.9993847656250001 -0.09675000000000001 -0.4935302734375 0.9993847656250001 -0.096875 -0.4935302734375 0.9993847656250001 -0.09699999999999999 -0.49267578125 0.9993847656250001 -0.097125 -0.49267578125 0.9993847656250001 -0.09725 -0.491790771484375 0.9993847656250001 -0.09737500000000001 -0.490814208984375 0.9993847656250001 -0.0975 -0.490814208984375 0.9993847656250001 -0.09762500000000001 -0.48980712890625 0.9993847656250001 -0.09775 -0.48980712890625 0.9993847656250001 -0.097875 -0.488739013671875 0.9993847656250001 -0.09800000000000001 -0.487640380859375 0.9993847656250001 -0.098125 -0.487640380859375 0.9993847656250001 -0.09825000000000001 -0.486480712890625 0.9993847656250001 -0.098375 -0.486480712890625 0.9993847656250001 -0.09850000000000001 -0.485260009765625 0.9993847656250001 -0.09862500000000001 -0.483978271484375 0.9993847656250001 -0.09875 -0.483978271484375 0.9993847656250001 -0.09887499999999999 -0.482635498046875 0.9993847656250001 -0.099 -0.482635498046875 0.9993847656250001 -0.09912500000000001 -0.48126220703125 0.9993847656250001 -0.09925000000000001 -0.479827880859375 0.9993847656250001 -0.099375 -0.479827880859375 0.9993847656250001 -0.09950000000000001 -0.47833251953125 0.9993847656250001 -0.099625 -0.47833251953125 0.9993847656250001 -0.09975000000000001 -0.476806640625 0.9993847656250001 -0.09987500000000001 -0.4752197265625 0.9993847656250001 -0.1 -0.4752197265625 0.9993847656250001 -0.100125 -0.47357177734375 0.9993847656250001 -0.10025 -0.47357177734375 0.9993847656250001 -0.100375 -0.471893310546875 0.9993847656250001 -0.1005 -0.470123291015625 0.9993847656250001 -0.100625 -0.470123291015625 0.9993847656250001 -0.10075 -0.46832275390625 0.9993847656250001 -0.100875 -0.46832275390625 0.9993847656250001 -0.101 -0.46649169921875 0.9993847656250001 -0.101125 -0.464569091796875 0.9993847656250001 -0.10125 -0.464569091796875 0.9993847656250001 -0.101375 -0.462646484375 0.9993847656250001 -0.1015 -0.462646484375 0.9993847656250001 -0.101625 -0.46063232421875 0.9993847656250001 -0.10175 -0.458587646484375 0.9993847656250001 -0.101875 -0.458587646484375 0.9993847656250001 -0.102 -0.45648193359375 0.9993847656250001 -0.102125 -0.45648193359375 0.9993847656250001 -0.10225 -0.454315185546875 0.9993847656250001 -0.102375 -0.452117919921875 0.9993847656250001 -0.1025 -0.452117919921875 0.9993847656250001 -0.102625 -0.449859619140625 0.9993847656250001 -0.10275 -0.449859619140625 0.9993847656250001 -0.102875 -0.44757080078125 0.9993847656250001 -0.103 -0.445220947265625 0.9993847656250001 -0.103125 -0.445220947265625 0.9993847656250001 -0.10325 -0.44281005859375 0.9993847656250001 -0.103375 -0.44281005859375 0.9993847656250001 -0.1035 -0.44036865234375 0.9993847656250001 -0.103625 -0.4378662109375 0.9993847656250001 -0.10375 -0.4378662109375 0.9993847656250001 -0.103875 -0.435333251953125 0.9993847656250001 -0.104 -0.435333251953125 0.9993847656250001 -0.104125 -0.4327392578125 0.9993847656250001 -0.10425 -0.430084228515625 0.9993847656250001 -0.104375 -0.430084228515625 0.9993847656250001 -0.1045 -0.427398681640625 0.9993847656250001 -0.104625 -0.427398681640625 0.9993847656250001 -0.10475 -0.4246826171875 0.9993847656250001 -0.104875 -0.421905517578125 0.9993847656250001 -0.105 -0.421905517578125 0.9993847656250001 -0.105125 -0.4190673828125 0.9993847656250001 -0.10525 -0.4190673828125 0.9993847656250001 -0.105375 -0.41619873046875 0.9993847656250001 -0.1055 -0.41326904296875 0.9993847656250001 -0.105625 -0.41326904296875 0.9993847656250001 -0.10575 -0.410308837890625 0.9993847656250001 -0.105875 -0.410308837890625 0.9993847656250001 -0.106 -0.40728759765625 0.9993847656250001 -0.106125 -0.404266357421875 0.9993847656250001 -0.10625 -0.404266357421875 0.9993847656250001 -0.106375 -0.401153564453125 0.9993847656250001 -0.1065 -0.401153564453125 0.9993847656250001 -0.106625 -0.39801025390625 0.9993847656250001 -0.10675 -0.39483642578125 0.9993847656250001 -0.106875 -0.39483642578125 0.9993847656250001 -0.107 -0.3916015625 0.9993847656250001 -0.107125 -0.3916015625 0.9993847656250001 -0.10725 -0.3883056640625 0.9993847656250001 -0.107375 -0.385009765625 0.9993847656250001 -0.1075 -0.385009765625 0.9993847656250001 -0.107625 -0.38165283203125 0.9993847656250001 -0.10775 -0.38165283203125 0.9993847656250001 -0.107875 -0.378265380859375 0.9993847656250001 -0.108 -0.37481689453125 0.9993847656250001 -0.108125 -0.37481689453125 0.9993847656250001 -0.10825 -0.371337890625 0.9993847656250001 -0.108375 -0.371337890625 0.9993847656250001 -0.1085 -0.3677978515625 0.9993847656250001 -0.108625 -0.3642578125 0.9993847656250001 -0.10875 -0.3642578125 0.9993847656250001 -0.108875 -0.360626220703125 0.9993847656250001 -0.109 -0.360626220703125 0.9993847656250001 -0.109125 -0.35699462890625 0.9993847656250001 -0.10925 -0.35333251953125 0.9993847656250001 -0.109375 -0.35333251953125 0.9993847656250001 -0.1095 -0.349609375 0.9993847656250001 -0.109625 -0.349609375 0.9993847656250001 -0.10975 -0.345855712890625 0.9993847656250001 -0.109875 -0.342041015625 0.9993847656250001 -0.11 -0.342041015625 0.9993847656250001 -0.110125 -0.338226318359375 0.9993847656250001 -0.11025 -0.338226318359375 0.9993847656250001 -0.110375 -0.3343505859375 0.9993847656250001 -0.1105 -0.3304443359375 0.9993847656250001 -0.110625 -0.3304443359375 0.9993847656250001 -0.11075 -0.326507568359375 0.9993847656250001 -0.110875 -0.326507568359375 0.9993847656250001 -0.111 -0.322509765625 0.9993847656250001 -0.111125 -0.318511962890625 0.9993847656250001 -0.11125 -0.318511962890625 0.9993847656250001 -0.111375 -0.314453125 0.9993847656250001 -0.1115 -0.314453125 0.9993847656250001 -0.111625 -0.31036376953125 0.9993847656250001 -0.11175 -0.3062744140625 0.9993847656250001 -0.111875 -0.3062744140625 0.9993847656250001 -0.112 -0.302093505859375 0.9993847656250001 -0.112125 -0.302093505859375 0.9993847656250001 -0.11225 -0.29791259765625 0.9993847656250001 -0.112375 -0.293701171875 0.9993847656250001 -0.1125 -0.293701171875 0.9993847656250001 -0.112625 -0.289459228515625 0.9993847656250001 -0.11275 -0.289459228515625 0.9993847656250001 -0.112875 -0.285186767578125 0.9993847656250001 -0.113 -0.280853271484375 0.9993847656250001 -0.113125 -0.280853271484375 0.9993847656250001 -0.11325 -0.276519775390625 0.9993847656250001 -0.113375 -0.276519775390625 0.9993847656250001 -0.1135 -0.27215576171875 0.9993847656250001 -0.113625 -0.267730712890625 0.9993847656250001 -0.11375 -0.267730712890625 0.9993847656250001 -0.113875 -0.2633056640625 0.9993847656250001 -0.114 -0.2633056640625 0.9993847656250001 -0.114125 -0.25885009765625 0.9993847656250001 -0.11425 -0.254364013671875 0.9993847656250001 -0.114375 -0.254364013671875 0.9993847656250001 -0.1145 -0.249847412109375 0.9993847656250001 -0.114625 -0.249847412109375 0.9993847656250001 -0.11475 -0.24530029296875 0.9993847656250001 -0.114875 -0.24072265625 0.9993847656250001 -0.115 -0.24072265625 0.9993847656250001 -0.115125 -0.23614501953125 0.9993847656250001 -0.11525 -0.23614501953125 0.9993847656250001 -0.115375 -0.23150634765625 0.9993847656250001 -0.1155 -0.226837158203125 0.9993847656250001 -0.115625 -0.226837158203125 0.9993847656250001 -0.11575 -0.22216796875 0.9993847656250001 -0.115875 -0.22216796875 0.9993847656250001 -0.116 -0.21746826171875 0.9993847656250001 -0.116125 -0.2127685546875 0.9993847656250001 -0.11625 -0.2127685546875 0.9993847656250001 -0.116375 -0.2080078125 0.9993847656250001 -0.1165 -0.2080078125 0.9993847656250001 -0.116625 -0.2032470703125 0.9993847656250001 -0.11675 -0.198455810546875 0.9993847656250001 -0.116875 -0.198455810546875 0.9993847656250001 -0.117 -0.193634033203125 0.9993847656250001 -0.117125 -0.193634033203125 0.9993847656250001 -0.11725 -0.188812255859375 0.9993847656250001 -0.117375 -0.1839599609375 0.9993847656250001 -0.1175 -0.1839599609375 0.9993847656250001 -0.117625 -0.1790771484375 0.9993847656250001 -0.11775 -0.1790771484375 0.9993847656250001 -0.117875 -0.174163818359375 0.9993847656250001 -0.118 -0.16925048828125 0.9993847656250001 -0.118125 -0.16925048828125 0.9993847656250001 -0.11825 -0.164337158203125 0.9993847656250001 -0.118375 -0.164337158203125 0.9993847656250001 -0.1185 -0.159393310546875 0.9993847656250001 -0.118625 -0.1544189453125 0.9993847656250001 -0.11875 -0.1544189453125 0.9993847656250001 -0.118875 -0.1494140625 0.9993847656250001 -0.119 -0.1494140625 0.9993847656250001 -0.119125 -0.1444091796875 0.9993847656250001 -0.11925 -0.139404296875 0.9993847656250001 -0.119375 -0.139404296875 0.9993847656250001 -0.1195 -0.134368896484375 0.9993847656250001 -0.119625 -0.134368896484375 0.9993847656250001 -0.11975 -0.12933349609375 0.9993847656250001 -0.119875 -0.124267578125 0.9993847656250001 -0.12 -0.124267578125 0.9993847656250001 -0.120125 -0.11920166015625 0.9993847656250001 -0.12025 -0.11920166015625 0.9993847656250001 -0.120375 -0.114105224609375 0.9993847656250001 -0.1205 -0.1090087890625 0.9993847656250001 -0.120625 -0.1090087890625 0.9993847656250001 -0.12075 -0.1038818359375 0.9993847656250001 -0.120875 -0.1038818359375 0.9993847656250001 -0.121 -0.0987548828125 0.9993847656250001 -0.121125 -0.0936279296875 0.9993847656250001 -0.12125 -0.0936279296875 0.9993847656250001 -0.121375 -0.0885009765625 0.9993847656250001 -0.1215 -0.0885009765625 0.9993847656250001 -0.121625 -0.083343505859375 0.9993847656250001 -0.12175 -0.078155517578125 0.9993847656250001 -0.121875 -0.078155517578125 0.9993847656250001 -0.122 -0.072998046875 0.9993847656250001 -0.122125 -0.072998046875 0.9993847656250001 -0.12225 -0.06781005859375 0.9993847656250001 -0.122375 -0.0626220703125 0.9993847656250001 -0.1225 -0.0626220703125 0.9993847656250001 -0.122625 -0.05743408203125 0.9993847656250001 -0.12275 -0.05743408203125 0.9993847656250001 -0.122875 -0.05224609375 0.9993847656250001 -0.123 -0.047027587890625 0.9993847656250001 -0.123125 -0.047027587890625 0.9993847656250001 -0.12325 -0.04180908203125 0.9993847656250001 -0.123375 -0.04180908203125 0.9993847656250001 -0.1235 -0.036590576171875 0.9993847656250001 -0.123625 -0.0313720703125 0.9993847656250001 -0.12375 -0.0313720703125 0.9993847656250001 -0.123875 -0.026153564453125 0.9993847656250001 -0.124 -0.026153564453125 0.9993847656250001 -0.124125 -0.02093505859375 0.9993847656250001 -0.12425 -0.015716552734375 0.9993847656250001 -0.124375 -0.015716552734375 0.9993847656250001 -0.1245 -0.010467529296875 0.9993847656250001 -0.124625 -0.010467529296875 0.9993847656250001 -0.12475 -0.0052490234375 0.9993847656250001 +0.06262499999999999 -0.004058837890625 0.7762060546875 +0.06274999999999999 -0.004058837890625 0.7762060546875 +0.06287500000000001 -0.00811767578125 0.7762060546875 +0.063 -0.012176513671875 0.7762060546875 +0.063125 -0.012176513671875 0.7762060546875 +0.06325000000000001 -0.0162353515625 0.7762060546875 +0.063375 -0.0162353515625 0.7762060546875 +0.0635 -0.020294189453125 0.7762060546875 +0.063625 -0.02435302734375 0.7762060546875 +0.06375 -0.02435302734375 0.7762060546875 +0.063875 -0.028411865234375 0.7762060546875 +0.064 -0.03466796875 0.9474169921874999 +0.064125 -0.03961181640625 0.9474169921874999 +0.06425000000000001 -0.0445556640625 0.9474169921874999 +0.064375 -0.0445556640625 0.9474169921874999 +0.0645 -0.04949951171875 0.9474169921874999 +0.064625 -0.04949951171875 0.9474169921874999 +0.06475 -0.054412841796875 0.9474169921874999 +0.06487500000000001 -0.059326171875 0.9474169921874999 +0.065 -0.059326171875 0.9474169921874999 +0.065125 -0.06427001953125 0.9474169921874999 +0.06525 -0.06427001953125 0.9474169921874999 +0.06537500000000001 -0.069183349609375 0.9474169921874999 +0.06550000000000001 -0.074066162109375 0.9474169921874999 +0.065625 -0.074066162109375 0.9474169921874999 +0.06574999999999999 -0.0789794921875 0.9474169921874999 +0.065875 -0.0789794921875 0.9474169921874999 +0.06600000000000001 -0.0838623046875 0.9474169921874999 +0.066125 -0.0887451171875 0.9474169921874999 +0.06625000000000001 -0.0887451171875 0.9474169921874999 +0.06637500000000001 -0.093597412109375 0.9474169921874999 +0.0665 -0.093597412109375 0.9474169921874999 +0.066625 -0.09844970703125 0.9474169921874999 +0.06675 -0.103302001953125 0.9474169921874999 +0.06687500000000001 -0.103302001953125 0.9474169921874999 +0.067 -0.108154296875 0.9474169921874999 +0.067125 -0.108154296875 0.9474169921874999 +0.06725000000000001 -0.11297607421875 0.9474169921874999 +0.06737500000000001 -0.117767333984375 0.9474169921874999 +0.0675 -0.117767333984375 0.9474169921874999 +0.067625 -0.12255859375 0.9474169921874999 +0.06775 -0.12255859375 0.9474169921874999 +0.06787500000000001 -0.127349853515625 0.9474169921874999 +0.06800000000000001 -0.13214111328125 0.9474169921874999 +0.068125 -0.13214111328125 0.9474169921874999 +0.06825000000000001 -0.136871337890625 0.9474169921874999 +0.068375 -0.136871337890625 0.9474169921874999 +0.06850000000000001 -0.141632080078125 0.9474169921874999 +0.06862500000000001 -0.1463623046875 0.9474169921874999 +0.06875 -0.1463623046875 0.9474169921874999 +0.06887500000000001 -0.15106201171875 0.9474169921874999 +0.069 -0.15106201171875 0.9474169921874999 +0.06912500000000001 -0.15576171875 0.9474169921874999 +0.06925000000000001 -0.160430908203125 0.9474169921874999 +0.06937500000000001 -0.160430908203125 0.9474169921874999 +0.06950000000000001 -0.16510009765625 0.9474169921874999 +0.069625 -0.16510009765625 0.9474169921874999 +0.06975 -0.16973876953125 0.9474169921874999 +0.06987500000000001 -0.174346923828125 0.9474169921874999 +0.07000000000000001 -0.174346923828125 0.9474169921874999 +0.070125 -0.178955078125 0.9474169921874999 +0.07025000000000001 -0.178955078125 0.9474169921874999 +0.07037500000000001 -0.18353271484375 0.9474169921874999 +0.07050000000000001 -0.1881103515625 0.9474169921874999 +0.070625 -0.1881103515625 0.9474169921874999 +0.07075 -0.192626953125 0.9474169921874999 +0.07087500000000001 -0.192626953125 0.9474169921874999 +0.07100000000000001 -0.197174072265625 0.9474169921874999 +0.07112500000000001 -0.20166015625 0.9474169921874999 +0.07125000000000002 -0.20166015625 0.9474169921874999 +0.07137500000000001 -0.206146240234375 0.9474169921874999 +0.0715 -0.206146240234375 0.9474169921874999 +0.07162500000000001 -0.210601806640625 0.9474169921874999 +0.07175000000000001 -0.21502685546875 0.9474169921874999 +0.07187500000000001 -0.21502685546875 0.9474169921874999 +0.07200000000000001 -0.21942138671875 0.9474169921874999 +0.07212499999999999 -0.21942138671875 0.9474169921874999 +0.07225 -0.22381591796875 0.9474169921874999 +0.07237499999999999 -0.228179931640625 0.9474169921874999 +0.0725 -0.228179931640625 0.9474169921874999 +0.07262499999999999 -0.232513427734375 0.9474169921874999 +0.07274999999999999 -0.232513427734375 0.9474169921874999 +0.072875 -0.23681640625 0.9474169921874999 +0.073 -0.2410888671875 0.9474169921874999 +0.073125 -0.2410888671875 0.9474169921874999 +0.07324999999999999 -0.245361328125 0.9474169921874999 +0.07337499999999999 -0.245361328125 0.9474169921874999 +0.0735 -0.24957275390625 0.9474169921874999 +0.073625 -0.2537841796875 0.9474169921874999 +0.07374999999999999 -0.2537841796875 0.9474169921874999 +0.073875 -0.257965087890625 0.9474169921874999 +0.074 -0.257965087890625 0.9474169921874999 +0.074125 -0.262115478515625 0.9474169921874999 +0.07424999999999999 -0.2662353515625 0.9474169921874999 +0.07437499999999999 -0.2662353515625 0.9474169921874999 +0.0745 -0.27032470703125 0.9474169921874999 +0.07462499999999999 -0.27032470703125 0.9474169921874999 +0.07475 -0.274383544921875 0.9474169921874999 +0.07487500000000001 -0.27838134765625 0.9474169921874999 +0.075 -0.27838134765625 0.9474169921874999 +0.07512499999999999 -0.28240966796875 0.9474169921874999 +0.07524999999999999 -0.28240966796875 0.9474169921874999 +0.075375 -0.286346435546875 0.9474169921874999 +0.0755 -0.290313720703125 0.9474169921874999 +0.075625 -0.290313720703125 0.9474169921874999 +0.07574999999999999 -0.294219970703125 0.9474169921874999 +0.075875 -0.294219970703125 0.9474169921874999 +0.076 -0.298065185546875 0.9474169921874999 +0.076125 -0.301910400390625 0.9474169921874999 +0.07625 -0.301910400390625 0.9474169921874999 +0.07637499999999999 -0.30572509765625 0.9474169921874999 +0.0765 -0.30572509765625 0.9474169921874999 +0.076625 -0.309478759765625 0.9474169921874999 +0.07675 -0.313232421875 0.9474169921874999 +0.076875 -0.313232421875 0.9474169921874999 +0.077 -0.316925048828125 0.9474169921874999 +0.077125 -0.316925048828125 0.9474169921874999 +0.07725 -0.32061767578125 0.9474169921874999 +0.07737499999999999 -0.32421875 0.9474169921874999 +0.0775 -0.32421875 0.9474169921874999 +0.077625 -0.32781982421875 0.9474169921874999 +0.07774999999999999 -0.32781982421875 0.9474169921874999 +0.07787500000000001 -0.331390380859375 0.9474169921874999 +0.07800000000000001 -0.334930419921875 0.9474169921874999 +0.078125 -0.334930419921875 0.9474169921874999 +0.07824999999999999 -0.338409423828125 0.9474169921874999 +0.07837499999999999 -0.338409423828125 0.9474169921874999 +0.07850000000000001 -0.34185791015625 0.9474169921874999 +0.078625 -0.34527587890625 0.9474169921874999 +0.07875 -0.34527587890625 0.9474169921874999 +0.07887500000000001 -0.348663330078125 0.9474169921874999 +0.079 -0.348663330078125 0.9474169921874999 +0.079125 -0.35198974609375 0.9474169921874999 +0.07925 -0.35528564453125 0.9474169921874999 +0.079375 -0.35528564453125 0.9474169921874999 +0.0795 -0.358551025390625 0.9474169921874999 +0.079625 -0.358551025390625 0.9474169921874999 +0.07975 -0.361785888671875 0.9474169921874999 +0.07987500000000001 -0.364959716796875 0.9474169921874999 +0.08 -0.364959716796875 0.9474169921874999 +0.08012499999999999 -0.36810302734375 0.9474169921874999 +0.08025 -0.36810302734375 0.9474169921874999 +0.080375 -0.371185302734375 0.9474169921874999 +0.08050000000000001 -0.374267578125 0.9474169921874999 +0.080625 -0.374267578125 0.9474169921874999 +0.08074999999999999 -0.37725830078125 0.9474169921874999 +0.080875 -0.37725830078125 0.9474169921874999 +0.08100000000000001 -0.3802490234375 0.9474169921874999 +0.08112500000000001 -0.383209228515625 0.9474169921874999 +0.08125 -0.383209228515625 0.9474169921874999 +0.08137499999999999 -0.386077880859375 0.9474169921874999 +0.0815 -0.386077880859375 0.9474169921874999 +0.081625 -0.388946533203125 0.9474169921874999 +0.08175000000000001 -0.391754150390625 0.9474169921874999 +0.081875 -0.391754150390625 0.9474169921874999 +0.08200000000000001 -0.39453125 0.9474169921874999 +0.082125 -0.39453125 0.9474169921874999 +0.08225 -0.397247314453125 0.9474169921874999 +0.08237500000000001 -0.399932861328125 0.9474169921874999 +0.0825 -0.399932861328125 0.9474169921874999 +0.08262500000000001 -0.402557373046875 0.9474169921874999 +0.08275 -0.402557373046875 0.9474169921874999 +0.08287500000000001 -0.4051513671875 0.9474169921874999 +0.08300000000000001 -0.407684326171875 0.9474169921874999 +0.083125 -0.407684326171875 0.9474169921874999 +0.08324999999999999 -0.41021728515625 0.9474169921874999 +0.083375 -0.41021728515625 0.9474169921874999 +0.08350000000000001 -0.41265869140625 0.9474169921874999 +0.08362500000000001 -0.415069580078125 0.9474169921874999 +0.08375 -0.415069580078125 0.9474169921874999 +0.08387500000000001 -0.41741943359375 0.9474169921874999 +0.084 -0.41741943359375 0.9474169921874999 +0.08412500000000001 -0.419769287109375 0.9474169921874999 +0.08425000000000001 -0.422027587890625 0.9474169921874999 +0.084375 -0.422027587890625 0.9474169921874999 +0.08450000000000001 -0.42425537109375 0.9474169921874999 +0.084625 -0.42425537109375 0.9474169921874999 +0.08475 -0.426422119140625 0.9474169921874999 +0.08487500000000001 -0.4285888671875 0.9474169921874999 +0.085 -0.4285888671875 0.9474169921874999 +0.08512500000000001 -0.4306640625 0.9474169921874999 +0.08525 -0.4306640625 0.9474169921874999 +0.085375 -0.432708740234375 0.9474169921874999 +0.08550000000000001 -0.4346923828125 0.9474169921874999 +0.085625 -0.4346923828125 0.9474169921874999 +0.08575000000000001 -0.4366455078125 0.9474169921874999 +0.08587500000000002 -0.4366455078125 0.9474169921874999 +0.08600000000000001 -0.43853759765625 0.9474169921874999 +0.08612500000000001 -0.440399169921875 0.9474169921874999 +0.08625 -0.440399169921875 0.9474169921874999 +0.08637499999999999 -0.44219970703125 0.9474169921874999 +0.0865 -0.44219970703125 0.9474169921874999 +0.08662500000000001 -0.443939208984375 0.9474169921874999 +0.08675000000000001 -0.445648193359375 0.9474169921874999 +0.08687500000000002 -0.445648193359375 0.9474169921874999 +0.08700000000000001 -0.447296142578125 0.9474169921874999 +0.087125 -0.447296142578125 0.9474169921874999 +0.08725000000000001 -0.44891357421875 0.9474169921874999 +0.08737500000000001 -0.450469970703125 0.9474169921874999 +0.08750000000000002 -0.450469970703125 0.9474169921874999 +0.08762500000000001 -0.45196533203125 0.9474169921874999 +0.08775 -0.45196533203125 0.9474169921874999 +0.08787500000000001 -0.45343017578125 0.9474169921874999 +0.08799999999999999 -0.454833984375 0.9474169921874999 +0.088125 -0.454833984375 0.9474169921874999 +0.08824999999999999 -0.456207275390625 0.9474169921874999 +0.08837499999999999 -0.456207275390625 0.9474169921874999 +0.0885 -0.45751953125 0.9474169921874999 +0.08862500000000001 -0.458770751953125 0.9474169921874999 +0.08875 -0.458770751953125 0.9474169921874999 +0.08887499999999999 -0.459991455078125 0.9474169921874999 +0.08899999999999999 -0.459991455078125 0.9474169921874999 +0.089125 -0.461151123046875 0.9474169921874999 +0.08924999999999999 -0.462249755859375 0.9474169921874999 +0.089375 -0.462249755859375 0.9474169921874999 +0.08949999999999999 -0.463287353515625 0.9474169921874999 +0.089625 -0.463287353515625 0.9474169921874999 +0.08975 -0.464324951171875 0.9474169921874999 +0.08987499999999999 -0.46527099609375 0.9474169921874999 +0.09 -0.46527099609375 0.9474169921874999 +0.09012499999999999 -0.4661865234375 0.9474169921874999 +0.09025 -0.4661865234375 0.9474169921874999 +0.090375 -0.467041015625 0.9474169921874999 +0.09050000000000001 -0.46783447265625 0.9474169921874999 +0.090625 -0.46783447265625 0.9474169921874999 +0.09074999999999999 -0.46856689453125 0.9474169921874999 +0.09087499999999999 -0.46856689453125 0.9474169921874999 +0.091 -0.469268798828125 0.9474169921874999 +0.09112500000000001 -0.46990966796875 0.9474169921874999 +0.09125 -0.46990966796875 0.9474169921874999 +0.09137499999999999 -0.47052001953125 0.9474169921874999 +0.0915 -0.47052001953125 0.9474169921874999 +0.091625 -0.4710693359375 0.9474169921874999 +0.09175000000000001 -0.4715576171875 0.9474169921874999 +0.091875 -0.4715576171875 0.9474169921874999 +0.09199999999999999 -0.472015380859375 0.9474169921874999 +0.092125 -0.472015380859375 0.9474169921874999 +0.09225 -0.472381591796875 0.9474169921874999 +0.09237499999999999 -0.47271728515625 0.9474169921874999 +0.0925 -0.47271728515625 0.9474169921874999 +0.09262499999999999 -0.4730224609375 0.9474169921874999 +0.09275 -0.4730224609375 0.9474169921874999 +0.092875 -0.473236083984375 0.9474169921874999 +0.09299999999999999 -0.473419189453125 0.9474169921874999 +0.093125 -0.473419189453125 0.9474169921874999 +0.09324999999999999 -0.473541259765625 0.9474169921874999 +0.093375 -0.473541259765625 0.9474169921874999 +0.09350000000000001 -0.4736328125 0.9474169921874999 +0.09362500000000001 -0.473663330078125 0.9474169921874999 +0.09375 -0.473663330078125 0.9474169921874999 +0.09387499999999999 -0.4736328125 0.9474169921874999 +0.09399999999999999 -0.4736328125 0.9474169921874999 +0.094125 -0.473541259765625 0.9474169921874999 +0.09425000000000001 -0.473419189453125 0.9474169921874999 +0.094375 -0.473419189453125 0.9474169921874999 +0.09450000000000001 -0.473236083984375 0.9474169921874999 +0.094625 -0.473236083984375 0.9474169921874999 +0.09475 -0.4730224609375 0.9474169921874999 +0.09487500000000001 -0.47271728515625 0.9474169921874999 +0.095 -0.47271728515625 0.9474169921874999 +0.09512500000000001 -0.472381591796875 0.9474169921874999 +0.09525 -0.472381591796875 0.9474169921874999 +0.095375 -0.472015380859375 0.9474169921874999 +0.09550000000000001 -0.4715576171875 0.9474169921874999 +0.095625 -0.4715576171875 0.9474169921874999 +0.09574999999999999 -0.4710693359375 0.9474169921874999 +0.095875 -0.4710693359375 0.9474169921874999 +0.096 -0.496337890625 0.9993847656250001 +0.09612500000000001 -0.495697021484375 0.9993847656250001 +0.09625 -0.495697021484375 0.9993847656250001 +0.09637499999999999 -0.495025634765625 0.9993847656250001 +0.0965 -0.495025634765625 0.9993847656250001 +0.09662500000000001 -0.494293212890625 0.9993847656250001 +0.09675000000000001 -0.493499755859375 0.9993847656250001 +0.096875 -0.493499755859375 0.9993847656250001 +0.09699999999999999 -0.492645263671875 0.9993847656250001 +0.097125 -0.492645263671875 0.9993847656250001 +0.09725 -0.49176025390625 0.9993847656250001 +0.09737500000000001 -0.49078369140625 0.9993847656250001 +0.0975 -0.49078369140625 0.9993847656250001 +0.09762500000000001 -0.489776611328125 0.9993847656250001 +0.09775 -0.489776611328125 0.9993847656250001 +0.097875 -0.48870849609375 0.9993847656250001 +0.09800000000000001 -0.48760986328125 0.9993847656250001 +0.098125 -0.48760986328125 0.9993847656250001 +0.09825000000000001 -0.4864501953125 0.9993847656250001 +0.098375 -0.4864501953125 0.9993847656250001 +0.09850000000000001 -0.4852294921875 0.9993847656250001 +0.09862500000000001 -0.48394775390625 0.9993847656250001 +0.09875 -0.48394775390625 0.9993847656250001 +0.09887499999999999 -0.48260498046875 0.9993847656250001 +0.099 -0.48260498046875 0.9993847656250001 +0.09912500000000001 -0.481231689453125 0.9993847656250001 +0.09925000000000001 -0.47979736328125 0.9993847656250001 +0.099375 -0.47979736328125 0.9993847656250001 +0.09950000000000001 -0.478302001953125 0.9993847656250001 +0.099625 -0.478302001953125 0.9993847656250001 +0.09975000000000001 -0.476776123046875 0.9993847656250001 +0.09987500000000001 -0.475189208984375 0.9993847656250001 +0.1 -0.475189208984375 0.9993847656250001 +0.100125 -0.473541259765625 0.9993847656250001 +0.10025 -0.473541259765625 0.9993847656250001 +0.100375 -0.47186279296875 0.9993847656250001 +0.1005 -0.4700927734375 0.9993847656250001 +0.100625 -0.4700927734375 0.9993847656250001 +0.10075 -0.468292236328125 0.9993847656250001 +0.100875 -0.468292236328125 0.9993847656250001 +0.101 -0.466461181640625 0.9993847656250001 +0.101125 -0.46453857421875 0.9993847656250001 +0.10125 -0.46453857421875 0.9993847656250001 +0.101375 -0.462615966796875 0.9993847656250001 +0.1015 -0.462615966796875 0.9993847656250001 +0.101625 -0.460601806640625 0.9993847656250001 +0.10175 -0.45855712890625 0.9993847656250001 +0.101875 -0.45855712890625 0.9993847656250001 +0.102 -0.456451416015625 0.9993847656250001 +0.102125 -0.456451416015625 0.9993847656250001 +0.10225 -0.45428466796875 0.9993847656250001 +0.102375 -0.45208740234375 0.9993847656250001 +0.1025 -0.45208740234375 0.9993847656250001 +0.102625 -0.4498291015625 0.9993847656250001 +0.10275 -0.4498291015625 0.9993847656250001 +0.102875 -0.447540283203125 0.9993847656250001 +0.103 -0.4451904296875 0.9993847656250001 +0.103125 -0.4451904296875 0.9993847656250001 +0.10325 -0.442779541015625 0.9993847656250001 +0.103375 -0.442779541015625 0.9993847656250001 +0.1035 -0.440338134765625 0.9993847656250001 +0.103625 -0.437835693359375 0.9993847656250001 +0.10375 -0.437835693359375 0.9993847656250001 +0.103875 -0.435302734375 0.9993847656250001 +0.104 -0.435302734375 0.9993847656250001 +0.104125 -0.432708740234375 0.9993847656250001 +0.10425 -0.4300537109375 0.9993847656250001 +0.104375 -0.4300537109375 0.9993847656250001 +0.1045 -0.4273681640625 0.9993847656250001 +0.104625 -0.4273681640625 0.9993847656250001 +0.10475 -0.424652099609375 0.9993847656250001 +0.104875 -0.421875 0.9993847656250001 +0.105 -0.421875 0.9993847656250001 +0.105125 -0.419036865234375 0.9993847656250001 +0.10525 -0.419036865234375 0.9993847656250001 +0.105375 -0.416168212890625 0.9993847656250001 +0.1055 -0.413238525390625 0.9993847656250001 +0.105625 -0.413238525390625 0.9993847656250001 +0.10575 -0.4102783203125 0.9993847656250001 +0.105875 -0.4102783203125 0.9993847656250001 +0.106 -0.407257080078125 0.9993847656250001 +0.106125 -0.40423583984375 0.9993847656250001 +0.10625 -0.40423583984375 0.9993847656250001 +0.106375 -0.401123046875 0.9993847656250001 +0.1065 -0.401123046875 0.9993847656250001 +0.106625 -0.397979736328125 0.9993847656250001 +0.10675 -0.394805908203125 0.9993847656250001 +0.106875 -0.394805908203125 0.9993847656250001 +0.107 -0.391571044921875 0.9993847656250001 +0.107125 -0.391571044921875 0.9993847656250001 +0.10725 -0.388275146484375 0.9993847656250001 +0.107375 -0.384979248046875 0.9993847656250001 +0.1075 -0.384979248046875 0.9993847656250001 +0.107625 -0.381622314453125 0.9993847656250001 +0.10775 -0.381622314453125 0.9993847656250001 +0.107875 -0.37823486328125 0.9993847656250001 +0.108 -0.374786376953125 0.9993847656250001 +0.108125 -0.374786376953125 0.9993847656250001 +0.10825 -0.371307373046875 0.9993847656250001 +0.108375 -0.371307373046875 0.9993847656250001 +0.1085 -0.367767333984375 0.9993847656250001 +0.108625 -0.364227294921875 0.9993847656250001 +0.10875 -0.364227294921875 0.9993847656250001 +0.108875 -0.360595703125 0.9993847656250001 +0.109 -0.360595703125 0.9993847656250001 +0.109125 -0.356964111328125 0.9993847656250001 +0.10925 -0.353302001953125 0.9993847656250001 +0.109375 -0.353302001953125 0.9993847656250001 +0.1095 -0.349578857421875 0.9993847656250001 +0.109625 -0.349578857421875 0.9993847656250001 +0.10975 -0.3458251953125 0.9993847656250001 +0.109875 -0.342010498046875 0.9993847656250001 +0.11 -0.342010498046875 0.9993847656250001 +0.110125 -0.33819580078125 0.9993847656250001 +0.11025 -0.33819580078125 0.9993847656250001 +0.110375 -0.334320068359375 0.9993847656250001 +0.1105 -0.330413818359375 0.9993847656250001 +0.110625 -0.330413818359375 0.9993847656250001 +0.11075 -0.32647705078125 0.9993847656250001 +0.110875 -0.32647705078125 0.9993847656250001 +0.111 -0.322479248046875 0.9993847656250001 +0.111125 -0.3184814453125 0.9993847656250001 +0.11125 -0.3184814453125 0.9993847656250001 +0.111375 -0.314422607421875 0.9993847656250001 +0.1115 -0.314422607421875 0.9993847656250001 +0.111625 -0.310333251953125 0.9993847656250001 +0.11175 -0.306243896484375 0.9993847656250001 +0.111875 -0.306243896484375 0.9993847656250001 +0.112 -0.30206298828125 0.9993847656250001 +0.112125 -0.30206298828125 0.9993847656250001 +0.11225 -0.297882080078125 0.9993847656250001 +0.112375 -0.293670654296875 0.9993847656250001 +0.1125 -0.293670654296875 0.9993847656250001 +0.112625 -0.2894287109375 0.9993847656250001 +0.11275 -0.2894287109375 0.9993847656250001 +0.112875 -0.28515625 0.9993847656250001 +0.113 -0.28082275390625 0.9993847656250001 +0.113125 -0.28082275390625 0.9993847656250001 +0.11325 -0.2764892578125 0.9993847656250001 +0.113375 -0.2764892578125 0.9993847656250001 +0.1135 -0.272125244140625 0.9993847656250001 +0.113625 -0.2677001953125 0.9993847656250001 +0.11375 -0.2677001953125 0.9993847656250001 +0.113875 -0.263275146484375 0.9993847656250001 +0.114 -0.263275146484375 0.9993847656250001 +0.114125 -0.258819580078125 0.9993847656250001 +0.11425 -0.25433349609375 0.9993847656250001 +0.114375 -0.25433349609375 0.9993847656250001 +0.1145 -0.24981689453125 0.9993847656250001 +0.114625 -0.24981689453125 0.9993847656250001 +0.11475 -0.245269775390625 0.9993847656250001 +0.114875 -0.240692138671875 0.9993847656250001 +0.115 -0.240692138671875 0.9993847656250001 +0.115125 -0.236114501953125 0.9993847656250001 +0.11525 -0.236114501953125 0.9993847656250001 +0.115375 -0.231475830078125 0.9993847656250001 +0.1155 -0.226806640625 0.9993847656250001 +0.115625 -0.226806640625 0.9993847656250001 +0.11575 -0.222137451171875 0.9993847656250001 +0.115875 -0.222137451171875 0.9993847656250001 +0.116 -0.217437744140625 0.9993847656250001 +0.116125 -0.212738037109375 0.9993847656250001 +0.11625 -0.212738037109375 0.9993847656250001 +0.116375 -0.207977294921875 0.9993847656250001 +0.1165 -0.207977294921875 0.9993847656250001 +0.116625 -0.203216552734375 0.9993847656250001 +0.11675 -0.19842529296875 0.9993847656250001 +0.116875 -0.19842529296875 0.9993847656250001 +0.117 -0.193603515625 0.9993847656250001 +0.117125 -0.193603515625 0.9993847656250001 +0.11725 -0.18878173828125 0.9993847656250001 +0.117375 -0.183929443359375 0.9993847656250001 +0.1175 -0.183929443359375 0.9993847656250001 +0.117625 -0.179046630859375 0.9993847656250001 +0.11775 -0.179046630859375 0.9993847656250001 +0.117875 -0.17413330078125 0.9993847656250001 +0.118 -0.169219970703125 0.9993847656250001 +0.118125 -0.169219970703125 0.9993847656250001 +0.11825 -0.164306640625 0.9993847656250001 +0.118375 -0.164306640625 0.9993847656250001 +0.1185 -0.15936279296875 0.9993847656250001 +0.118625 -0.154388427734375 0.9993847656250001 +0.11875 -0.154388427734375 0.9993847656250001 +0.118875 -0.149383544921875 0.9993847656250001 +0.119 -0.149383544921875 0.9993847656250001 +0.119125 -0.144378662109375 0.9993847656250001 +0.11925 -0.139373779296875 0.9993847656250001 +0.119375 -0.139373779296875 0.9993847656250001 +0.1195 -0.13433837890625 0.9993847656250001 +0.119625 -0.13433837890625 0.9993847656250001 +0.11975 -0.129302978515625 0.9993847656250001 +0.119875 -0.124237060546875 0.9993847656250001 +0.12 -0.124237060546875 0.9993847656250001 +0.120125 -0.119171142578125 0.9993847656250001 +0.12025 -0.119171142578125 0.9993847656250001 +0.120375 -0.11407470703125 0.9993847656250001 +0.1205 -0.108978271484375 0.9993847656250001 +0.120625 -0.108978271484375 0.9993847656250001 +0.12075 -0.103851318359375 0.9993847656250001 +0.120875 -0.103851318359375 0.9993847656250001 +0.121 -0.098724365234375 0.9993847656250001 +0.121125 -0.093597412109375 0.9993847656250001 +0.12125 -0.093597412109375 0.9993847656250001 +0.121375 -0.088470458984375 0.9993847656250001 +0.1215 -0.088470458984375 0.9993847656250001 +0.121625 -0.08331298828125 0.9993847656250001 +0.12175 -0.078125 0.9993847656250001 +0.121875 -0.078125 0.9993847656250001 +0.122 -0.072967529296875 0.9993847656250001 +0.122125 -0.072967529296875 0.9993847656250001 +0.12225 -0.067779541015625 0.9993847656250001 +0.122375 -0.062591552734375 0.9993847656250001 +0.1225 -0.062591552734375 0.9993847656250001 +0.122625 -0.057403564453125 0.9993847656250001 +0.12275 -0.057403564453125 0.9993847656250001 +0.122875 -0.052215576171875 0.9993847656250001 +0.123 -0.0469970703125 0.9993847656250001 +0.123125 -0.0469970703125 0.9993847656250001 +0.12325 -0.041778564453125 0.9993847656250001 +0.123375 -0.041778564453125 0.9993847656250001 +0.1235 -0.03656005859375 0.9993847656250001 +0.123625 -0.031341552734375 0.9993847656250001 +0.12375 -0.031341552734375 0.9993847656250001 +0.123875 -0.026123046875 0.9993847656250001 +0.124 -0.026123046875 0.9993847656250001 +0.124125 -0.020904541015625 0.9993847656250001 +0.12425 -0.01568603515625 0.9993847656250001 +0.124375 -0.01568603515625 0.9993847656250001 +0.1245 -0.01043701171875 0.9993847656250001 +0.124625 -0.01043701171875 0.9993847656250001 +0.12475 -0.005218505859375 0.9993847656250001 0.124875 0.0 0.9993847656250001 0.125 0.0 0.9993847656250001 0.125125 0.005218505859375 0.9993847656250001 @@ -1499,504 +1499,504 @@ 0.18725 0.003814697265625 0.7327783203125 0.187375 0.0 0.7327783203125 0.1875 0.0 0.7327783203125 -0.187625 -0.00384521484375 0.7327783203125 -0.18775 -0.00384521484375 0.7327783203125 -0.187875 -0.0076904296875 0.7327783203125 -0.188 -0.01153564453125 0.7327783203125 -0.188125 -0.01153564453125 0.7327783203125 -0.18825 -0.015350341796875 0.7327783203125 -0.188375 -0.015350341796875 0.7327783203125 -0.1885 -0.0191650390625 0.7327783203125 -0.188625 -0.02301025390625 0.7327783203125 -0.18875 -0.02301025390625 0.7327783203125 -0.188875 -0.026824951171875 0.7327783203125 -0.189 -0.026824951171875 0.7327783203125 -0.189125 -0.030670166015625 0.7327783203125 -0.18925 -0.03448486328125 0.7327783203125 -0.189375 -0.03448486328125 0.7327783203125 -0.1895 -0.038299560546875 0.7327783203125 -0.189625 -0.038299560546875 0.7327783203125 -0.18975 -0.0421142578125 0.7327783203125 -0.189875 -0.045928955078125 0.7327783203125 -0.19 -0.045928955078125 0.7327783203125 -0.190125 -0.049713134765625 0.7327783203125 -0.19025 -0.049713134765625 0.7327783203125 -0.190375 -0.05352783203125 0.7327783203125 -0.1905 -0.05731201171875 0.7327783203125 -0.190625 -0.05731201171875 0.7327783203125 -0.19075 -0.06109619140625 0.7327783203125 -0.190875 -0.06109619140625 0.7327783203125 -0.191 -0.06488037109375 0.7327783203125 -0.191125 -0.06866455078125 0.7327783203125 -0.19125 -0.06866455078125 0.7327783203125 -0.191375 -0.072418212890625 0.7327783203125 -0.1915 -0.072418212890625 0.7327783203125 -0.191625 -0.076171875 0.7327783203125 -0.19175 -0.079925537109375 0.7327783203125 -0.191875 -0.079925537109375 0.7327783203125 -0.192 -0.052154541015625 0.4567333984374999 -0.192125 -0.052154541015625 0.4567333984374999 -0.19225 -0.054473876953125 0.4567333984374999 -0.192375 -0.056793212890625 0.4567333984374999 -0.1925 -0.056793212890625 0.4567333984374999 -0.192625 -0.059112548828125 0.4567333984374999 -0.19275 -0.059112548828125 0.4567333984374999 -0.192875 -0.0614013671875 0.4567333984374999 -0.193 -0.063720703125 0.4567333984374999 -0.193125 -0.063720703125 0.4567333984374999 -0.19325 -0.066009521484375 0.4567333984374999 -0.193375 -0.066009521484375 0.4567333984374999 -0.1935 -0.06829833984375 0.4567333984374999 -0.193625 -0.070587158203125 0.4567333984374999 -0.19375 -0.070587158203125 0.4567333984374999 -0.193875 -0.072845458984375 0.4567333984374999 -0.194 -0.072845458984375 0.4567333984374999 -0.194125 -0.075103759765625 0.4567333984374999 -0.19425 -0.077362060546875 0.4567333984374999 -0.194375 -0.077362060546875 0.4567333984374999 -0.1945 -0.07958984375 0.4567333984374999 -0.194625 -0.07958984375 0.4567333984374999 -0.19475 -0.08184814453125 0.4567333984374999 -0.194875 -0.084075927734375 0.4567333984374999 -0.195 -0.084075927734375 0.4567333984374999 -0.195125 -0.086273193359375 0.4567333984374999 -0.19525 -0.086273193359375 0.4567333984374999 -0.195375 -0.0885009765625 0.4567333984374999 -0.1955 -0.0906982421875 0.4567333984374999 -0.195625 -0.0906982421875 0.4567333984374999 -0.19575 -0.0928955078125 0.4567333984374999 -0.195875 -0.0928955078125 0.4567333984374999 -0.196 -0.095062255859375 0.4567333984374999 -0.196125 -0.09722900390625 0.4567333984374999 -0.19625 -0.09722900390625 0.4567333984374999 -0.196375 -0.099395751953125 0.4567333984374999 -0.1965 -0.099395751953125 0.4567333984374999 -0.196625 -0.101531982421875 0.4567333984374999 -0.19675 -0.103668212890625 0.4567333984374999 -0.196875 -0.103668212890625 0.4567333984374999 -0.197 -0.105804443359375 0.4567333984374999 -0.197125 -0.105804443359375 0.4567333984374999 -0.19725 -0.10791015625 0.4567333984374999 -0.197375 -0.110015869140625 0.4567333984374999 -0.1975 -0.110015869140625 0.4567333984374999 -0.197625 -0.112091064453125 0.4567333984374999 -0.19775 -0.112091064453125 0.4567333984374999 -0.197875 -0.11419677734375 0.4567333984374999 -0.198 -0.116241455078125 0.4567333984374999 -0.198125 -0.116241455078125 0.4567333984374999 -0.19825 -0.1182861328125 0.4567333984374999 -0.198375 -0.1182861328125 0.4567333984374999 -0.1985 -0.120330810546875 0.4567333984374999 -0.198625 -0.12237548828125 0.4567333984374999 -0.19875 -0.12237548828125 0.4567333984374999 -0.198875 -0.1243896484375 0.4567333984374999 -0.199 -0.1243896484375 0.4567333984374999 -0.199125 -0.126373291015625 0.4567333984374999 -0.19925 -0.12835693359375 0.4567333984374999 -0.199375 -0.12835693359375 0.4567333984374999 -0.1995 -0.130340576171875 0.4567333984374999 -0.199625 -0.130340576171875 0.4567333984374999 -0.19975 -0.132293701171875 0.4567333984374999 -0.199875 -0.13421630859375 0.4567333984374999 -0.2 -0.13421630859375 0.4567333984374999 -0.200125 -0.13616943359375 0.4567333984374999 -0.20025 -0.13616943359375 0.4567333984374999 -0.200375 -0.1380615234375 0.4567333984374999 -0.2005 -0.13995361328125 0.4567333984374999 -0.200625 -0.13995361328125 0.4567333984374999 -0.20075 -0.141845703125 0.4567333984374999 -0.200875 -0.141845703125 0.4567333984374999 -0.201 -0.143707275390625 0.4567333984374999 -0.201125 -0.14556884765625 0.4567333984374999 -0.20125 -0.14556884765625 0.4567333984374999 -0.201375 -0.14739990234375 0.4567333984374999 -0.2015 -0.14739990234375 0.4567333984374999 -0.201625 -0.149200439453125 0.4567333984374999 -0.20175 -0.151031494140625 0.4567333984374999 -0.201875 -0.151031494140625 0.4567333984374999 -0.202 -0.152801513671875 0.4567333984374999 -0.202125 -0.152801513671875 0.4567333984374999 -0.20225 -0.154571533203125 0.4567333984374999 -0.202375 -0.15631103515625 0.4567333984374999 -0.2025 -0.15631103515625 0.4567333984374999 -0.202625 -0.158050537109375 0.4567333984374999 -0.20275 -0.158050537109375 0.4567333984374999 -0.202875 -0.159759521484375 0.4567333984374999 -0.203 -0.161468505859375 0.4567333984374999 -0.203125 -0.161468505859375 0.4567333984374999 -0.20325 -0.16314697265625 0.4567333984374999 -0.203375 -0.16314697265625 0.4567333984374999 -0.2035 -0.164825439453125 0.4567333984374999 -0.203625 -0.166473388671875 0.4567333984374999 -0.20375 -0.166473388671875 0.4567333984374999 -0.203875 -0.1680908203125 0.4567333984374999 -0.204 -0.1680908203125 0.4567333984374999 -0.204125 -0.169708251953125 0.4567333984374999 -0.20425 -0.171295166015625 0.4567333984374999 -0.204375 -0.171295166015625 0.4567333984374999 -0.2045 -0.1728515625 0.4567333984374999 -0.204625 -0.1728515625 0.4567333984374999 -0.20475 -0.174407958984375 0.4567333984374999 -0.204875 -0.17596435546875 0.4567333984374999 -0.205 -0.17596435546875 0.4567333984374999 -0.205125 -0.177459716796875 0.4567333984374999 -0.20525 -0.177459716796875 0.4567333984374999 -0.205375 -0.178955078125 0.4567333984374999 -0.2055 -0.180450439453125 0.4567333984374999 -0.205625 -0.180450439453125 0.4567333984374999 -0.20575 -0.181884765625 0.4567333984374999 -0.205875 -0.181884765625 0.4567333984374999 -0.206 -0.183319091796875 0.4567333984374999 -0.206125 -0.18475341796875 0.4567333984374999 -0.20625 -0.18475341796875 0.4567333984374999 -0.206375 -0.186126708984375 0.4567333984374999 -0.2065 -0.186126708984375 0.4567333984374999 -0.206625 -0.1875 0.4567333984374999 -0.20675 -0.188873291015625 0.4567333984374999 -0.206875 -0.188873291015625 0.4567333984374999 -0.207 -0.190216064453125 0.4567333984374999 -0.207125 -0.190216064453125 0.4567333984374999 -0.20725 -0.191497802734375 0.4567333984374999 -0.207375 -0.19281005859375 0.4567333984374999 -0.2075 -0.19281005859375 0.4567333984374999 -0.207625 -0.194091796875 0.4567333984374999 -0.20775 -0.194091796875 0.4567333984374999 -0.207875 -0.1953125 0.4567333984374999 -0.208 -0.196563720703125 0.4567333984374999 -0.208125 -0.196563720703125 0.4567333984374999 -0.20825 -0.19775390625 0.4567333984374999 -0.208375 -0.19775390625 0.4567333984374999 -0.2085 -0.198944091796875 0.4567333984374999 -0.208625 -0.200103759765625 0.4567333984374999 -0.20875 -0.200103759765625 0.4567333984374999 -0.208875 -0.20123291015625 0.4567333984374999 -0.209 -0.20123291015625 0.4567333984374999 -0.209125 -0.202362060546875 0.4567333984374999 -0.20925 -0.203460693359375 0.4567333984374999 -0.209375 -0.203460693359375 0.4567333984374999 -0.2095 -0.20452880859375 0.4567333984374999 -0.209625 -0.20452880859375 0.4567333984374999 -0.20975 -0.205596923828125 0.4567333984374999 -0.209875 -0.206634521484375 0.4567333984374999 -0.21 -0.206634521484375 0.4567333984374999 -0.210125 -0.207611083984375 0.4567333984374999 -0.21025 -0.207611083984375 0.4567333984374999 -0.210375 -0.2086181640625 0.4567333984374999 -0.2105 -0.209564208984375 0.4567333984374999 -0.210625 -0.209564208984375 0.4567333984374999 -0.21075 -0.21051025390625 0.4567333984374999 -0.210875 -0.21051025390625 0.4567333984374999 -0.211 -0.21142578125 0.4567333984374999 -0.211125 -0.212310791015625 0.4567333984374999 -0.21125 -0.212310791015625 0.4567333984374999 -0.211375 -0.21319580078125 0.4567333984374999 -0.2115 -0.21319580078125 0.4567333984374999 -0.211625 -0.214019775390625 0.4567333984374999 -0.21175 -0.21484375 0.4567333984374999 -0.211875 -0.21484375 0.4567333984374999 -0.212 -0.21563720703125 0.4567333984374999 -0.212125 -0.21563720703125 0.4567333984374999 -0.21225 -0.2164306640625 0.4567333984374999 -0.212375 -0.217193603515625 0.4567333984374999 -0.2125 -0.217193603515625 0.4567333984374999 -0.212625 -0.2178955078125 0.4567333984374999 -0.21275 -0.2178955078125 0.4567333984374999 -0.212875 -0.218597412109375 0.4567333984374999 -0.213 -0.219268798828125 0.4567333984374999 -0.213125 -0.219268798828125 0.4567333984374999 -0.21325 -0.219940185546875 0.4567333984374999 -0.213375 -0.219940185546875 0.4567333984374999 -0.2135 -0.2205810546875 0.4567333984374999 -0.213625 -0.22119140625 0.4567333984374999 -0.21375 -0.22119140625 0.4567333984374999 -0.213875 -0.221771240234375 0.4567333984374999 -0.214 -0.221771240234375 0.4567333984374999 -0.214125 -0.222320556640625 0.4567333984374999 -0.21425 -0.22283935546875 0.4567333984374999 -0.214375 -0.22283935546875 0.4567333984374999 -0.2145 -0.223358154296875 0.4567333984374999 -0.214625 -0.223358154296875 0.4567333984374999 -0.21475 -0.223846435546875 0.4567333984374999 -0.214875 -0.22430419921875 0.4567333984374999 -0.215 -0.22430419921875 0.4567333984374999 -0.215125 -0.2247314453125 0.4567333984374999 -0.21525 -0.2247314453125 0.4567333984374999 -0.215375 -0.22515869140625 0.4567333984374999 -0.2155 -0.225555419921875 0.4567333984374999 -0.215625 -0.225555419921875 0.4567333984374999 -0.21575 -0.22589111328125 0.4567333984374999 -0.215875 -0.22589111328125 0.4567333984374999 -0.216 -0.226226806640625 0.4567333984374999 -0.216125 -0.2265625 0.4567333984374999 -0.21625 -0.2265625 0.4567333984374999 -0.216375 -0.226837158203125 0.4567333984374999 -0.2165 -0.226837158203125 0.4567333984374999 -0.216625 -0.22711181640625 0.4567333984374999 -0.21675 -0.227325439453125 0.4567333984374999 -0.216875 -0.227325439453125 0.4567333984374999 -0.217 -0.227569580078125 0.4567333984374999 -0.217125 -0.227569580078125 0.4567333984374999 -0.21725 -0.227752685546875 0.4567333984374999 -0.217375 -0.2279052734375 0.4567333984374999 -0.2175 -0.2279052734375 0.4567333984374999 -0.217625 -0.22802734375 0.4567333984374999 -0.21775 -0.22802734375 0.4567333984374999 -0.217875 -0.2281494140625 0.4567333984374999 -0.218 -0.228240966796875 0.4567333984374999 -0.218125 -0.228240966796875 0.4567333984374999 -0.21825 -0.228302001953125 0.4567333984374999 -0.218375 -0.228302001953125 0.4567333984374999 -0.2185 -0.22833251953125 0.4567333984374999 -0.218625 -0.228363037109375 0.4567333984374999 -0.21875 -0.228363037109375 0.4567333984374999 -0.218875 -0.22833251953125 0.4567333984374999 -0.219 -0.22833251953125 0.4567333984374999 -0.219125 -0.228302001953125 0.4567333984374999 -0.21925 -0.228240966796875 0.4567333984374999 -0.219375 -0.228240966796875 0.4567333984374999 -0.2195 -0.2281494140625 0.4567333984374999 -0.219625 -0.2281494140625 0.4567333984374999 -0.21975 -0.22802734375 0.4567333984374999 -0.219875 -0.2279052734375 0.4567333984374999 -0.22 -0.2279052734375 0.4567333984374999 -0.220125 -0.227752685546875 0.4567333984374999 -0.22025 -0.227752685546875 0.4567333984374999 -0.220375 -0.227569580078125 0.4567333984374999 -0.2205 -0.227325439453125 0.4567333984374999 -0.220625 -0.227325439453125 0.4567333984374999 -0.22075 -0.22711181640625 0.4567333984374999 -0.220875 -0.22711181640625 0.4567333984374999 -0.221 -0.226837158203125 0.4567333984374999 -0.221125 -0.2265625 0.4567333984374999 -0.22125 -0.2265625 0.4567333984374999 -0.221375 -0.226226806640625 0.4567333984374999 -0.2215 -0.226226806640625 0.4567333984374999 -0.221625 -0.22589111328125 0.4567333984374999 -0.22175 -0.225555419921875 0.4567333984374999 -0.221875 -0.225555419921875 0.4567333984374999 -0.222 -0.22515869140625 0.4567333984374999 -0.222125 -0.22515869140625 0.4567333984374999 -0.22225 -0.2247314453125 0.4567333984374999 -0.222375 -0.22430419921875 0.4567333984374999 -0.2225 -0.22430419921875 0.4567333984374999 -0.222625 -0.223846435546875 0.4567333984374999 -0.22275 -0.223846435546875 0.4567333984374999 -0.222875 -0.223358154296875 0.4567333984374999 -0.223 -0.22283935546875 0.4567333984374999 -0.223125 -0.22283935546875 0.4567333984374999 -0.22325 -0.222320556640625 0.4567333984374999 -0.223375 -0.222320556640625 0.4567333984374999 -0.2235 -0.221771240234375 0.4567333984374999 -0.223625 -0.22119140625 0.4567333984374999 -0.22375 -0.22119140625 0.4567333984374999 -0.223875 -0.2205810546875 0.4567333984374999 -0.224 -0.0675048828125 0.1397607421875001 -0.224125 -0.06732177734375 0.1397607421875001 -0.22425 -0.067108154296875 0.1397607421875001 -0.224375 -0.067108154296875 0.1397607421875001 -0.2245 -0.06689453125 0.1397607421875001 -0.224625 -0.06689453125 0.1397607421875001 -0.22475 -0.066680908203125 0.1397607421875001 -0.224875 -0.06646728515625 0.1397607421875001 -0.225 -0.06646728515625 0.1397607421875001 -0.225125 -0.06622314453125 0.1397607421875001 -0.22525 -0.06622314453125 0.1397607421875001 -0.225375 -0.066009521484375 0.1397607421875001 -0.2255 -0.065765380859375 0.1397607421875001 -0.225625 -0.065765380859375 0.1397607421875001 -0.22575 -0.06549072265625 0.1397607421875001 -0.225875 -0.06549072265625 0.1397607421875001 -0.226 -0.06524658203125 0.1397607421875001 -0.226125 -0.064971923828125 0.1397607421875001 -0.22625 -0.064971923828125 0.1397607421875001 -0.226375 -0.064697265625 0.1397607421875001 -0.2265 -0.064697265625 0.1397607421875001 -0.226625 -0.064422607421875 0.1397607421875001 -0.22675 -0.06414794921875 0.1397607421875001 -0.226875 -0.06414794921875 0.1397607421875001 -0.227 -0.0638427734375 0.1397607421875001 -0.227125 -0.0638427734375 0.1397607421875001 -0.22725 -0.06353759765625 0.1397607421875001 -0.227375 -0.063232421875 0.1397607421875001 -0.2275 -0.063232421875 0.1397607421875001 -0.227625 -0.06292724609375 0.1397607421875001 -0.22775 -0.06292724609375 0.1397607421875001 -0.227875 -0.062591552734375 0.1397607421875001 -0.228 -0.062255859375 0.1397607421875001 -0.228125 -0.062255859375 0.1397607421875001 -0.22825 -0.061920166015625 0.1397607421875001 -0.228375 -0.061920166015625 0.1397607421875001 -0.2285 -0.06158447265625 0.1397607421875001 -0.228625 -0.061248779296875 0.1397607421875001 -0.22875 -0.061248779296875 0.1397607421875001 -0.228875 -0.060882568359375 0.1397607421875001 -0.229 -0.060882568359375 0.1397607421875001 -0.229125 -0.060516357421875 0.1397607421875001 -0.22925 -0.060150146484375 0.1397607421875001 -0.229375 -0.060150146484375 0.1397607421875001 -0.2295 -0.059783935546875 0.1397607421875001 -0.229625 -0.059783935546875 0.1397607421875001 -0.22975 -0.05938720703125 0.1397607421875001 -0.229875 -0.05902099609375 0.1397607421875001 -0.23 -0.05902099609375 0.1397607421875001 -0.230125 -0.058624267578125 0.1397607421875001 -0.23025 -0.058624267578125 0.1397607421875001 -0.230375 -0.058197021484375 0.1397607421875001 -0.2305 -0.05780029296875 0.1397607421875001 -0.230625 -0.05780029296875 0.1397607421875001 -0.23075 -0.057373046875 0.1397607421875001 -0.230875 -0.057373046875 0.1397607421875001 -0.231 -0.056976318359375 0.1397607421875001 -0.231125 -0.056549072265625 0.1397607421875001 -0.23125 -0.056549072265625 0.1397607421875001 -0.231375 -0.05609130859375 0.1397607421875001 -0.2315 -0.05609130859375 0.1397607421875001 -0.231625 -0.0556640625 0.1397607421875001 -0.23175 -0.05523681640625 0.1397607421875001 -0.231875 -0.05523681640625 0.1397607421875001 -0.232 -0.054779052734375 0.1397607421875001 -0.232125 -0.054779052734375 0.1397607421875001 -0.23225 -0.0543212890625 0.1397607421875001 -0.232375 -0.053863525390625 0.1397607421875001 -0.2325 -0.053863525390625 0.1397607421875001 -0.232625 -0.053375244140625 0.1397607421875001 -0.23275 -0.053375244140625 0.1397607421875001 -0.232875 -0.05291748046875 0.1397607421875001 -0.233 -0.05242919921875 0.1397607421875001 -0.233125 -0.05242919921875 0.1397607421875001 -0.23325 -0.05194091796875 0.1397607421875001 -0.233375 -0.05194091796875 0.1397607421875001 -0.2335 -0.05145263671875 0.1397607421875001 -0.233625 -0.050933837890625 0.1397607421875001 -0.23375 -0.050933837890625 0.1397607421875001 -0.233875 -0.050445556640625 0.1397607421875001 -0.234 -0.050445556640625 0.1397607421875001 -0.234125 -0.0499267578125 0.1397607421875001 -0.23425 -0.049407958984375 0.1397607421875001 -0.234375 -0.049407958984375 0.1397607421875001 -0.2345 -0.04888916015625 0.1397607421875001 -0.234625 -0.04888916015625 0.1397607421875001 -0.23475 -0.048370361328125 0.1397607421875001 -0.234875 -0.0478515625 0.1397607421875001 -0.235 -0.0478515625 0.1397607421875001 -0.235125 -0.04730224609375 0.1397607421875001 -0.23525 -0.04730224609375 0.1397607421875001 -0.235375 -0.0467529296875 0.1397607421875001 -0.2355 -0.046234130859375 0.1397607421875001 -0.235625 -0.046234130859375 0.1397607421875001 -0.23575 -0.045654296875 0.1397607421875001 -0.235875 -0.045654296875 0.1397607421875001 -0.236 -0.04510498046875 0.1397607421875001 -0.236125 -0.0445556640625 0.1397607421875001 -0.23625 -0.0445556640625 0.1397607421875001 -0.236375 -0.043975830078125 0.1397607421875001 -0.2365 -0.043975830078125 0.1397607421875001 -0.236625 -0.043426513671875 0.1397607421875001 -0.23675 -0.0428466796875 0.1397607421875001 -0.236875 -0.0428466796875 0.1397607421875001 -0.237 -0.042266845703125 0.1397607421875001 -0.237125 -0.042266845703125 0.1397607421875001 -0.23725 -0.041656494140625 0.1397607421875001 -0.237375 -0.04107666015625 0.1397607421875001 -0.2375 -0.04107666015625 0.1397607421875001 -0.237625 -0.040496826171875 0.1397607421875001 -0.23775 -0.040496826171875 0.1397607421875001 -0.237875 -0.039886474609375 0.1397607421875001 -0.238 -0.039276123046875 0.1397607421875001 -0.238125 -0.039276123046875 0.1397607421875001 -0.23825 -0.038665771484375 0.1397607421875001 -0.238375 -0.038665771484375 0.1397607421875001 -0.2385 -0.038055419921875 0.1397607421875001 -0.238625 -0.037445068359375 0.1397607421875001 -0.23875 -0.037445068359375 0.1397607421875001 -0.238875 -0.036834716796875 0.1397607421875001 -0.239 -0.036834716796875 0.1397607421875001 -0.239125 -0.03619384765625 0.1397607421875001 -0.23925 -0.03558349609375 0.1397607421875001 -0.239375 -0.03558349609375 0.1397607421875001 -0.2395 -0.034942626953125 0.1397607421875001 -0.239625 -0.034942626953125 0.1397607421875001 -0.23975 -0.0343017578125 0.1397607421875001 -0.239875 -0.033660888671875 0.1397607421875001 -0.24 -0.033660888671875 0.1397607421875001 -0.240125 -0.03302001953125 0.1397607421875001 -0.24025 -0.03302001953125 0.1397607421875001 -0.240375 -0.032379150390625 0.1397607421875001 -0.2405 -0.03173828125 0.1397607421875001 -0.240625 -0.03173828125 0.1397607421875001 -0.24075 -0.03106689453125 0.1397607421875001 -0.240875 -0.03106689453125 0.1397607421875001 -0.241 -0.030426025390625 0.1397607421875001 -0.241125 -0.029754638671875 0.1397607421875001 -0.24125 -0.029754638671875 0.1397607421875001 -0.241375 -0.02911376953125 0.1397607421875001 -0.2415 -0.02911376953125 0.1397607421875001 -0.241625 -0.0284423828125 0.1397607421875001 -0.24175 -0.02777099609375 0.1397607421875001 -0.241875 -0.02777099609375 0.1397607421875001 -0.242 -0.027099609375 0.1397607421875001 -0.242125 -0.027099609375 0.1397607421875001 -0.24225 -0.026397705078125 0.1397607421875001 -0.242375 -0.025726318359375 0.1397607421875001 -0.2425 -0.025726318359375 0.1397607421875001 -0.242625 -0.025054931640625 0.1397607421875001 -0.24275 -0.025054931640625 0.1397607421875001 -0.242875 -0.02435302734375 0.1397607421875001 -0.243 -0.023681640625 0.1397607421875001 -0.243125 -0.023681640625 0.1397607421875001 -0.24325 -0.022979736328125 0.1397607421875001 -0.243375 -0.022979736328125 0.1397607421875001 -0.2435 -0.022308349609375 0.1397607421875001 -0.243625 -0.0216064453125 0.1397607421875001 -0.24375 -0.0216064453125 0.1397607421875001 -0.243875 -0.020904541015625 0.1397607421875001 -0.244 -0.020904541015625 0.1397607421875001 -0.244125 -0.02020263671875 0.1397607421875001 -0.24425 -0.019500732421875 0.1397607421875001 -0.244375 -0.019500732421875 0.1397607421875001 -0.2445 -0.018798828125 0.1397607421875001 -0.244625 -0.018798828125 0.1397607421875001 -0.24475 -0.018096923828125 0.1397607421875001 -0.244875 -0.01739501953125 0.1397607421875001 -0.245 -0.01739501953125 0.1397607421875001 -0.245125 -0.016693115234375 0.1397607421875001 -0.24525 -0.016693115234375 0.1397607421875001 -0.245375 -0.015960693359375 0.1397607421875001 -0.2455 -0.0152587890625 0.1397607421875001 -0.245625 -0.0152587890625 0.1397607421875001 -0.24575 -0.0145263671875 0.1397607421875001 -0.245875 -0.0145263671875 0.1397607421875001 -0.246 -0.013824462890625 0.1397607421875001 -0.246125 -0.013092041015625 0.1397607421875001 -0.24625 -0.013092041015625 0.1397607421875001 -0.246375 -0.01239013671875 0.1397607421875001 -0.2465 -0.01239013671875 0.1397607421875001 -0.246625 -0.01165771484375 0.1397607421875001 -0.24675 -0.010955810546875 0.1397607421875001 -0.246875 -0.010955810546875 0.1397607421875001 -0.247 -0.010223388671875 0.1397607421875001 -0.247125 -0.010223388671875 0.1397607421875001 -0.24725 -0.009490966796875 0.1397607421875001 -0.247375 -0.008758544921875 0.1397607421875001 -0.2475 -0.008758544921875 0.1397607421875001 -0.247625 -0.008056640625 0.1397607421875001 -0.24775 -0.008056640625 0.1397607421875001 -0.247875 -0.00732421875 0.1397607421875001 -0.248 -0.006591796875 0.1397607421875001 -0.248125 -0.006591796875 0.1397607421875001 -0.24825 -0.005859375 0.1397607421875001 -0.248375 -0.005859375 0.1397607421875001 -0.2485 -0.005126953125 0.1397607421875001 -0.248625 -0.00439453125 0.1397607421875001 -0.24875 -0.00439453125 0.1397607421875001 -0.248875 -0.003662109375 0.1397607421875001 -0.249 -0.003662109375 0.1397607421875001 -0.249125 -0.0029296875 0.1397607421875001 -0.24925 -0.002197265625 0.1397607421875001 -0.249375 -0.002197265625 0.1397607421875001 -0.2495 -0.00146484375 0.1397607421875001 -0.249625 -0.00146484375 0.1397607421875001 -0.24975 -0.000732421875 0.1397607421875001 +0.187625 -0.003814697265625 0.7327783203125 +0.18775 -0.003814697265625 0.7327783203125 +0.187875 -0.007659912109375 0.7327783203125 +0.188 -0.011505126953125 0.7327783203125 +0.188125 -0.011505126953125 0.7327783203125 +0.18825 -0.01531982421875 0.7327783203125 +0.188375 -0.01531982421875 0.7327783203125 +0.1885 -0.019134521484375 0.7327783203125 +0.188625 -0.022979736328125 0.7327783203125 +0.18875 -0.022979736328125 0.7327783203125 +0.188875 -0.02679443359375 0.7327783203125 +0.189 -0.02679443359375 0.7327783203125 +0.189125 -0.0306396484375 0.7327783203125 +0.18925 -0.034454345703125 0.7327783203125 +0.189375 -0.034454345703125 0.7327783203125 +0.1895 -0.03826904296875 0.7327783203125 +0.189625 -0.03826904296875 0.7327783203125 +0.18975 -0.042083740234375 0.7327783203125 +0.189875 -0.0458984375 0.7327783203125 +0.19 -0.0458984375 0.7327783203125 +0.190125 -0.0496826171875 0.7327783203125 +0.19025 -0.0496826171875 0.7327783203125 +0.190375 -0.053497314453125 0.7327783203125 +0.1905 -0.057281494140625 0.7327783203125 +0.190625 -0.057281494140625 0.7327783203125 +0.19075 -0.061065673828125 0.7327783203125 +0.190875 -0.061065673828125 0.7327783203125 +0.191 -0.064849853515625 0.7327783203125 +0.191125 -0.068634033203125 0.7327783203125 +0.19125 -0.068634033203125 0.7327783203125 +0.191375 -0.0723876953125 0.7327783203125 +0.1915 -0.0723876953125 0.7327783203125 +0.191625 -0.076141357421875 0.7327783203125 +0.19175 -0.07989501953125 0.7327783203125 +0.191875 -0.07989501953125 0.7327783203125 +0.192 -0.0521240234375 0.4567333984374999 +0.192125 -0.0521240234375 0.4567333984374999 +0.19225 -0.054443359375 0.4567333984374999 +0.192375 -0.0567626953125 0.4567333984374999 +0.1925 -0.0567626953125 0.4567333984374999 +0.192625 -0.05908203125 0.4567333984374999 +0.19275 -0.05908203125 0.4567333984374999 +0.192875 -0.061370849609375 0.4567333984374999 +0.193 -0.063690185546875 0.4567333984374999 +0.193125 -0.063690185546875 0.4567333984374999 +0.19325 -0.06597900390625 0.4567333984374999 +0.193375 -0.06597900390625 0.4567333984374999 +0.1935 -0.068267822265625 0.4567333984374999 +0.193625 -0.070556640625 0.4567333984374999 +0.19375 -0.070556640625 0.4567333984374999 +0.193875 -0.07281494140625 0.4567333984374999 +0.194 -0.07281494140625 0.4567333984374999 +0.194125 -0.0750732421875 0.4567333984374999 +0.19425 -0.07733154296875 0.4567333984374999 +0.194375 -0.07733154296875 0.4567333984374999 +0.1945 -0.079559326171875 0.4567333984374999 +0.194625 -0.079559326171875 0.4567333984374999 +0.19475 -0.081817626953125 0.4567333984374999 +0.194875 -0.08404541015625 0.4567333984374999 +0.195 -0.08404541015625 0.4567333984374999 +0.195125 -0.08624267578125 0.4567333984374999 +0.19525 -0.08624267578125 0.4567333984374999 +0.195375 -0.088470458984375 0.4567333984374999 +0.1955 -0.090667724609375 0.4567333984374999 +0.195625 -0.090667724609375 0.4567333984374999 +0.19575 -0.092864990234375 0.4567333984374999 +0.195875 -0.092864990234375 0.4567333984374999 +0.196 -0.09503173828125 0.4567333984374999 +0.196125 -0.097198486328125 0.4567333984374999 +0.19625 -0.097198486328125 0.4567333984374999 +0.196375 -0.099365234375 0.4567333984374999 +0.1965 -0.099365234375 0.4567333984374999 +0.196625 -0.10150146484375 0.4567333984374999 +0.19675 -0.1036376953125 0.4567333984374999 +0.196875 -0.1036376953125 0.4567333984374999 +0.197 -0.10577392578125 0.4567333984374999 +0.197125 -0.10577392578125 0.4567333984374999 +0.19725 -0.107879638671875 0.4567333984374999 +0.197375 -0.1099853515625 0.4567333984374999 +0.1975 -0.1099853515625 0.4567333984374999 +0.197625 -0.112060546875 0.4567333984374999 +0.19775 -0.112060546875 0.4567333984374999 +0.197875 -0.114166259765625 0.4567333984374999 +0.198 -0.1162109375 0.4567333984374999 +0.198125 -0.1162109375 0.4567333984374999 +0.19825 -0.118255615234375 0.4567333984374999 +0.198375 -0.118255615234375 0.4567333984374999 +0.1985 -0.12030029296875 0.4567333984374999 +0.198625 -0.122344970703125 0.4567333984374999 +0.19875 -0.122344970703125 0.4567333984374999 +0.198875 -0.124359130859375 0.4567333984374999 +0.199 -0.124359130859375 0.4567333984374999 +0.199125 -0.1263427734375 0.4567333984374999 +0.19925 -0.128326416015625 0.4567333984374999 +0.199375 -0.128326416015625 0.4567333984374999 +0.1995 -0.13031005859375 0.4567333984374999 +0.199625 -0.13031005859375 0.4567333984374999 +0.19975 -0.13226318359375 0.4567333984374999 +0.199875 -0.134185791015625 0.4567333984374999 +0.2 -0.134185791015625 0.4567333984374999 +0.200125 -0.136138916015625 0.4567333984374999 +0.20025 -0.136138916015625 0.4567333984374999 +0.200375 -0.138031005859375 0.4567333984374999 +0.2005 -0.139923095703125 0.4567333984374999 +0.200625 -0.139923095703125 0.4567333984374999 +0.20075 -0.141815185546875 0.4567333984374999 +0.200875 -0.141815185546875 0.4567333984374999 +0.201 -0.1436767578125 0.4567333984374999 +0.201125 -0.145538330078125 0.4567333984374999 +0.20125 -0.145538330078125 0.4567333984374999 +0.201375 -0.147369384765625 0.4567333984374999 +0.2015 -0.147369384765625 0.4567333984374999 +0.201625 -0.149169921875 0.4567333984374999 +0.20175 -0.1510009765625 0.4567333984374999 +0.201875 -0.1510009765625 0.4567333984374999 +0.202 -0.15277099609375 0.4567333984374999 +0.202125 -0.15277099609375 0.4567333984374999 +0.20225 -0.154541015625 0.4567333984374999 +0.202375 -0.156280517578125 0.4567333984374999 +0.2025 -0.156280517578125 0.4567333984374999 +0.202625 -0.15802001953125 0.4567333984374999 +0.20275 -0.15802001953125 0.4567333984374999 +0.202875 -0.15972900390625 0.4567333984374999 +0.203 -0.16143798828125 0.4567333984374999 +0.203125 -0.16143798828125 0.4567333984374999 +0.20325 -0.163116455078125 0.4567333984374999 +0.203375 -0.163116455078125 0.4567333984374999 +0.2035 -0.164794921875 0.4567333984374999 +0.203625 -0.16644287109375 0.4567333984374999 +0.20375 -0.16644287109375 0.4567333984374999 +0.203875 -0.168060302734375 0.4567333984374999 +0.204 -0.168060302734375 0.4567333984374999 +0.204125 -0.169677734375 0.4567333984374999 +0.20425 -0.1712646484375 0.4567333984374999 +0.204375 -0.1712646484375 0.4567333984374999 +0.2045 -0.172821044921875 0.4567333984374999 +0.204625 -0.172821044921875 0.4567333984374999 +0.20475 -0.17437744140625 0.4567333984374999 +0.204875 -0.175933837890625 0.4567333984374999 +0.205 -0.175933837890625 0.4567333984374999 +0.205125 -0.17742919921875 0.4567333984374999 +0.20525 -0.17742919921875 0.4567333984374999 +0.205375 -0.178924560546875 0.4567333984374999 +0.2055 -0.180419921875 0.4567333984374999 +0.205625 -0.180419921875 0.4567333984374999 +0.20575 -0.181854248046875 0.4567333984374999 +0.205875 -0.181854248046875 0.4567333984374999 +0.206 -0.18328857421875 0.4567333984374999 +0.206125 -0.184722900390625 0.4567333984374999 +0.20625 -0.184722900390625 0.4567333984374999 +0.206375 -0.18609619140625 0.4567333984374999 +0.2065 -0.18609619140625 0.4567333984374999 +0.206625 -0.187469482421875 0.4567333984374999 +0.20675 -0.1888427734375 0.4567333984374999 +0.206875 -0.1888427734375 0.4567333984374999 +0.207 -0.190185546875 0.4567333984374999 +0.207125 -0.190185546875 0.4567333984374999 +0.20725 -0.19146728515625 0.4567333984374999 +0.207375 -0.192779541015625 0.4567333984374999 +0.2075 -0.192779541015625 0.4567333984374999 +0.207625 -0.194061279296875 0.4567333984374999 +0.20775 -0.194061279296875 0.4567333984374999 +0.207875 -0.195281982421875 0.4567333984374999 +0.208 -0.196533203125 0.4567333984374999 +0.208125 -0.196533203125 0.4567333984374999 +0.20825 -0.197723388671875 0.4567333984374999 +0.208375 -0.197723388671875 0.4567333984374999 +0.2085 -0.19891357421875 0.4567333984374999 +0.208625 -0.2000732421875 0.4567333984374999 +0.20875 -0.2000732421875 0.4567333984374999 +0.208875 -0.201202392578125 0.4567333984374999 +0.209 -0.201202392578125 0.4567333984374999 +0.209125 -0.20233154296875 0.4567333984374999 +0.20925 -0.20343017578125 0.4567333984374999 +0.209375 -0.20343017578125 0.4567333984374999 +0.2095 -0.204498291015625 0.4567333984374999 +0.209625 -0.204498291015625 0.4567333984374999 +0.20975 -0.20556640625 0.4567333984374999 +0.209875 -0.20660400390625 0.4567333984374999 +0.21 -0.20660400390625 0.4567333984374999 +0.210125 -0.20758056640625 0.4567333984374999 +0.21025 -0.20758056640625 0.4567333984374999 +0.210375 -0.208587646484375 0.4567333984374999 +0.2105 -0.20953369140625 0.4567333984374999 +0.210625 -0.20953369140625 0.4567333984374999 +0.21075 -0.210479736328125 0.4567333984374999 +0.210875 -0.210479736328125 0.4567333984374999 +0.211 -0.211395263671875 0.4567333984374999 +0.211125 -0.2122802734375 0.4567333984374999 +0.21125 -0.2122802734375 0.4567333984374999 +0.211375 -0.213165283203125 0.4567333984374999 +0.2115 -0.213165283203125 0.4567333984374999 +0.211625 -0.2139892578125 0.4567333984374999 +0.21175 -0.214813232421875 0.4567333984374999 +0.211875 -0.214813232421875 0.4567333984374999 +0.212 -0.215606689453125 0.4567333984374999 +0.212125 -0.215606689453125 0.4567333984374999 +0.21225 -0.216400146484375 0.4567333984374999 +0.212375 -0.2171630859375 0.4567333984374999 +0.2125 -0.2171630859375 0.4567333984374999 +0.212625 -0.217864990234375 0.4567333984374999 +0.21275 -0.217864990234375 0.4567333984374999 +0.212875 -0.21856689453125 0.4567333984374999 +0.213 -0.21923828125 0.4567333984374999 +0.213125 -0.21923828125 0.4567333984374999 +0.21325 -0.21990966796875 0.4567333984374999 +0.213375 -0.21990966796875 0.4567333984374999 +0.2135 -0.220550537109375 0.4567333984374999 +0.213625 -0.221160888671875 0.4567333984374999 +0.21375 -0.221160888671875 0.4567333984374999 +0.213875 -0.22174072265625 0.4567333984374999 +0.214 -0.22174072265625 0.4567333984374999 +0.214125 -0.2222900390625 0.4567333984374999 +0.21425 -0.222808837890625 0.4567333984374999 +0.214375 -0.222808837890625 0.4567333984374999 +0.2145 -0.22332763671875 0.4567333984374999 +0.214625 -0.22332763671875 0.4567333984374999 +0.21475 -0.22381591796875 0.4567333984374999 +0.214875 -0.224273681640625 0.4567333984374999 +0.215 -0.224273681640625 0.4567333984374999 +0.215125 -0.224700927734375 0.4567333984374999 +0.21525 -0.224700927734375 0.4567333984374999 +0.215375 -0.225128173828125 0.4567333984374999 +0.2155 -0.22552490234375 0.4567333984374999 +0.215625 -0.22552490234375 0.4567333984374999 +0.21575 -0.225860595703125 0.4567333984374999 +0.215875 -0.225860595703125 0.4567333984374999 +0.216 -0.2261962890625 0.4567333984374999 +0.216125 -0.226531982421875 0.4567333984374999 +0.21625 -0.226531982421875 0.4567333984374999 +0.216375 -0.226806640625 0.4567333984374999 +0.2165 -0.226806640625 0.4567333984374999 +0.216625 -0.227081298828125 0.4567333984374999 +0.21675 -0.227294921875 0.4567333984374999 +0.216875 -0.227294921875 0.4567333984374999 +0.217 -0.2275390625 0.4567333984374999 +0.217125 -0.2275390625 0.4567333984374999 +0.21725 -0.22772216796875 0.4567333984374999 +0.217375 -0.227874755859375 0.4567333984374999 +0.2175 -0.227874755859375 0.4567333984374999 +0.217625 -0.227996826171875 0.4567333984374999 +0.21775 -0.227996826171875 0.4567333984374999 +0.217875 -0.228118896484375 0.4567333984374999 +0.218 -0.22821044921875 0.4567333984374999 +0.218125 -0.22821044921875 0.4567333984374999 +0.21825 -0.228271484375 0.4567333984374999 +0.218375 -0.228271484375 0.4567333984374999 +0.2185 -0.228302001953125 0.4567333984374999 +0.218625 -0.22833251953125 0.4567333984374999 +0.21875 -0.22833251953125 0.4567333984374999 +0.218875 -0.228302001953125 0.4567333984374999 +0.219 -0.228302001953125 0.4567333984374999 +0.219125 -0.228271484375 0.4567333984374999 +0.21925 -0.22821044921875 0.4567333984374999 +0.219375 -0.22821044921875 0.4567333984374999 +0.2195 -0.228118896484375 0.4567333984374999 +0.219625 -0.228118896484375 0.4567333984374999 +0.21975 -0.227996826171875 0.4567333984374999 +0.219875 -0.227874755859375 0.4567333984374999 +0.22 -0.227874755859375 0.4567333984374999 +0.220125 -0.22772216796875 0.4567333984374999 +0.22025 -0.22772216796875 0.4567333984374999 +0.220375 -0.2275390625 0.4567333984374999 +0.2205 -0.227294921875 0.4567333984374999 +0.220625 -0.227294921875 0.4567333984374999 +0.22075 -0.227081298828125 0.4567333984374999 +0.220875 -0.227081298828125 0.4567333984374999 +0.221 -0.226806640625 0.4567333984374999 +0.221125 -0.226531982421875 0.4567333984374999 +0.22125 -0.226531982421875 0.4567333984374999 +0.221375 -0.2261962890625 0.4567333984374999 +0.2215 -0.2261962890625 0.4567333984374999 +0.221625 -0.225860595703125 0.4567333984374999 +0.22175 -0.22552490234375 0.4567333984374999 +0.221875 -0.22552490234375 0.4567333984374999 +0.222 -0.225128173828125 0.4567333984374999 +0.222125 -0.225128173828125 0.4567333984374999 +0.22225 -0.224700927734375 0.4567333984374999 +0.222375 -0.224273681640625 0.4567333984374999 +0.2225 -0.224273681640625 0.4567333984374999 +0.222625 -0.22381591796875 0.4567333984374999 +0.22275 -0.22381591796875 0.4567333984374999 +0.222875 -0.22332763671875 0.4567333984374999 +0.223 -0.222808837890625 0.4567333984374999 +0.223125 -0.222808837890625 0.4567333984374999 +0.22325 -0.2222900390625 0.4567333984374999 +0.223375 -0.2222900390625 0.4567333984374999 +0.2235 -0.22174072265625 0.4567333984374999 +0.223625 -0.221160888671875 0.4567333984374999 +0.22375 -0.221160888671875 0.4567333984374999 +0.223875 -0.220550537109375 0.4567333984374999 +0.224 -0.067474365234375 0.1397607421875001 +0.224125 -0.067291259765625 0.1397607421875001 +0.22425 -0.06707763671875 0.1397607421875001 +0.224375 -0.06707763671875 0.1397607421875001 +0.2245 -0.066864013671875 0.1397607421875001 +0.224625 -0.066864013671875 0.1397607421875001 +0.22475 -0.066650390625 0.1397607421875001 +0.224875 -0.066436767578125 0.1397607421875001 +0.225 -0.066436767578125 0.1397607421875001 +0.225125 -0.066192626953125 0.1397607421875001 +0.22525 -0.066192626953125 0.1397607421875001 +0.225375 -0.06597900390625 0.1397607421875001 +0.2255 -0.06573486328125 0.1397607421875001 +0.225625 -0.06573486328125 0.1397607421875001 +0.22575 -0.065460205078125 0.1397607421875001 +0.225875 -0.065460205078125 0.1397607421875001 +0.226 -0.065216064453125 0.1397607421875001 +0.226125 -0.06494140625 0.1397607421875001 +0.22625 -0.06494140625 0.1397607421875001 +0.226375 -0.064666748046875 0.1397607421875001 +0.2265 -0.064666748046875 0.1397607421875001 +0.226625 -0.06439208984375 0.1397607421875001 +0.22675 -0.064117431640625 0.1397607421875001 +0.226875 -0.064117431640625 0.1397607421875001 +0.227 -0.063812255859375 0.1397607421875001 +0.227125 -0.063812255859375 0.1397607421875001 +0.22725 -0.063507080078125 0.1397607421875001 +0.227375 -0.063201904296875 0.1397607421875001 +0.2275 -0.063201904296875 0.1397607421875001 +0.227625 -0.062896728515625 0.1397607421875001 +0.22775 -0.062896728515625 0.1397607421875001 +0.227875 -0.06256103515625 0.1397607421875001 +0.228 -0.062225341796875 0.1397607421875001 +0.228125 -0.062225341796875 0.1397607421875001 +0.22825 -0.0618896484375 0.1397607421875001 +0.228375 -0.0618896484375 0.1397607421875001 +0.2285 -0.061553955078125 0.1397607421875001 +0.228625 -0.06121826171875 0.1397607421875001 +0.22875 -0.06121826171875 0.1397607421875001 +0.228875 -0.06085205078125 0.1397607421875001 +0.229 -0.06085205078125 0.1397607421875001 +0.229125 -0.06048583984375 0.1397607421875001 +0.22925 -0.06011962890625 0.1397607421875001 +0.229375 -0.06011962890625 0.1397607421875001 +0.2295 -0.05975341796875 0.1397607421875001 +0.229625 -0.05975341796875 0.1397607421875001 +0.22975 -0.059356689453125 0.1397607421875001 +0.229875 -0.058990478515625 0.1397607421875001 +0.23 -0.058990478515625 0.1397607421875001 +0.230125 -0.05859375 0.1397607421875001 +0.23025 -0.05859375 0.1397607421875001 +0.230375 -0.05816650390625 0.1397607421875001 +0.2305 -0.057769775390625 0.1397607421875001 +0.230625 -0.057769775390625 0.1397607421875001 +0.23075 -0.057342529296875 0.1397607421875001 +0.230875 -0.057342529296875 0.1397607421875001 +0.231 -0.05694580078125 0.1397607421875001 +0.231125 -0.0565185546875 0.1397607421875001 +0.23125 -0.0565185546875 0.1397607421875001 +0.231375 -0.056060791015625 0.1397607421875001 +0.2315 -0.056060791015625 0.1397607421875001 +0.231625 -0.055633544921875 0.1397607421875001 +0.23175 -0.055206298828125 0.1397607421875001 +0.231875 -0.055206298828125 0.1397607421875001 +0.232 -0.05474853515625 0.1397607421875001 +0.232125 -0.05474853515625 0.1397607421875001 +0.23225 -0.054290771484375 0.1397607421875001 +0.232375 -0.0538330078125 0.1397607421875001 +0.2325 -0.0538330078125 0.1397607421875001 +0.232625 -0.0533447265625 0.1397607421875001 +0.23275 -0.0533447265625 0.1397607421875001 +0.232875 -0.052886962890625 0.1397607421875001 +0.233 -0.052398681640625 0.1397607421875001 +0.233125 -0.052398681640625 0.1397607421875001 +0.23325 -0.051910400390625 0.1397607421875001 +0.233375 -0.051910400390625 0.1397607421875001 +0.2335 -0.051422119140625 0.1397607421875001 +0.233625 -0.0509033203125 0.1397607421875001 +0.23375 -0.0509033203125 0.1397607421875001 +0.233875 -0.0504150390625 0.1397607421875001 +0.234 -0.0504150390625 0.1397607421875001 +0.234125 -0.049896240234375 0.1397607421875001 +0.23425 -0.04937744140625 0.1397607421875001 +0.234375 -0.04937744140625 0.1397607421875001 +0.2345 -0.048858642578125 0.1397607421875001 +0.234625 -0.048858642578125 0.1397607421875001 +0.23475 -0.04833984375 0.1397607421875001 +0.234875 -0.047821044921875 0.1397607421875001 +0.235 -0.047821044921875 0.1397607421875001 +0.235125 -0.047271728515625 0.1397607421875001 +0.23525 -0.047271728515625 0.1397607421875001 +0.235375 -0.046722412109375 0.1397607421875001 +0.2355 -0.04620361328125 0.1397607421875001 +0.235625 -0.04620361328125 0.1397607421875001 +0.23575 -0.045623779296875 0.1397607421875001 +0.235875 -0.045623779296875 0.1397607421875001 +0.236 -0.045074462890625 0.1397607421875001 +0.236125 -0.044525146484375 0.1397607421875001 +0.23625 -0.044525146484375 0.1397607421875001 +0.236375 -0.0439453125 0.1397607421875001 +0.2365 -0.0439453125 0.1397607421875001 +0.236625 -0.04339599609375 0.1397607421875001 +0.23675 -0.042816162109375 0.1397607421875001 +0.236875 -0.042816162109375 0.1397607421875001 +0.237 -0.042236328125 0.1397607421875001 +0.237125 -0.042236328125 0.1397607421875001 +0.23725 -0.0416259765625 0.1397607421875001 +0.237375 -0.041046142578125 0.1397607421875001 +0.2375 -0.041046142578125 0.1397607421875001 +0.237625 -0.04046630859375 0.1397607421875001 +0.23775 -0.04046630859375 0.1397607421875001 +0.237875 -0.03985595703125 0.1397607421875001 +0.238 -0.03924560546875 0.1397607421875001 +0.238125 -0.03924560546875 0.1397607421875001 +0.23825 -0.03863525390625 0.1397607421875001 +0.238375 -0.03863525390625 0.1397607421875001 +0.2385 -0.03802490234375 0.1397607421875001 +0.238625 -0.03741455078125 0.1397607421875001 +0.23875 -0.03741455078125 0.1397607421875001 +0.238875 -0.03680419921875 0.1397607421875001 +0.239 -0.03680419921875 0.1397607421875001 +0.239125 -0.036163330078125 0.1397607421875001 +0.23925 -0.035552978515625 0.1397607421875001 +0.239375 -0.035552978515625 0.1397607421875001 +0.2395 -0.034912109375 0.1397607421875001 +0.239625 -0.034912109375 0.1397607421875001 +0.23975 -0.034271240234375 0.1397607421875001 +0.239875 -0.03363037109375 0.1397607421875001 +0.24 -0.03363037109375 0.1397607421875001 +0.240125 -0.032989501953125 0.1397607421875001 +0.24025 -0.032989501953125 0.1397607421875001 +0.240375 -0.0323486328125 0.1397607421875001 +0.2405 -0.031707763671875 0.1397607421875001 +0.240625 -0.031707763671875 0.1397607421875001 +0.24075 -0.031036376953125 0.1397607421875001 +0.240875 -0.031036376953125 0.1397607421875001 +0.241 -0.0303955078125 0.1397607421875001 +0.241125 -0.02972412109375 0.1397607421875001 +0.24125 -0.02972412109375 0.1397607421875001 +0.241375 -0.029083251953125 0.1397607421875001 +0.2415 -0.029083251953125 0.1397607421875001 +0.241625 -0.028411865234375 0.1397607421875001 +0.24175 -0.027740478515625 0.1397607421875001 +0.241875 -0.027740478515625 0.1397607421875001 +0.242 -0.027069091796875 0.1397607421875001 +0.242125 -0.027069091796875 0.1397607421875001 +0.24225 -0.0263671875 0.1397607421875001 +0.242375 -0.02569580078125 0.1397607421875001 +0.2425 -0.02569580078125 0.1397607421875001 +0.242625 -0.0250244140625 0.1397607421875001 +0.24275 -0.0250244140625 0.1397607421875001 +0.242875 -0.024322509765625 0.1397607421875001 +0.243 -0.023651123046875 0.1397607421875001 +0.243125 -0.023651123046875 0.1397607421875001 +0.24325 -0.02294921875 0.1397607421875001 +0.243375 -0.02294921875 0.1397607421875001 +0.2435 -0.02227783203125 0.1397607421875001 +0.243625 -0.021575927734375 0.1397607421875001 +0.24375 -0.021575927734375 0.1397607421875001 +0.243875 -0.0208740234375 0.1397607421875001 +0.244 -0.0208740234375 0.1397607421875001 +0.244125 -0.020172119140625 0.1397607421875001 +0.24425 -0.01947021484375 0.1397607421875001 +0.244375 -0.01947021484375 0.1397607421875001 +0.2445 -0.018768310546875 0.1397607421875001 +0.244625 -0.018768310546875 0.1397607421875001 +0.24475 -0.01806640625 0.1397607421875001 +0.244875 -0.017364501953125 0.1397607421875001 +0.245 -0.017364501953125 0.1397607421875001 +0.245125 -0.01666259765625 0.1397607421875001 +0.24525 -0.01666259765625 0.1397607421875001 +0.245375 -0.01593017578125 0.1397607421875001 +0.2455 -0.015228271484375 0.1397607421875001 +0.245625 -0.015228271484375 0.1397607421875001 +0.24575 -0.014495849609375 0.1397607421875001 +0.245875 -0.014495849609375 0.1397607421875001 +0.246 -0.0137939453125 0.1397607421875001 +0.246125 -0.0130615234375 0.1397607421875001 +0.24625 -0.0130615234375 0.1397607421875001 +0.246375 -0.012359619140625 0.1397607421875001 +0.2465 -0.012359619140625 0.1397607421875001 +0.246625 -0.011627197265625 0.1397607421875001 +0.24675 -0.01092529296875 0.1397607421875001 +0.246875 -0.01092529296875 0.1397607421875001 +0.247 -0.01019287109375 0.1397607421875001 +0.247125 -0.01019287109375 0.1397607421875001 +0.24725 -0.00946044921875 0.1397607421875001 +0.247375 -0.00872802734375 0.1397607421875001 +0.2475 -0.00872802734375 0.1397607421875001 +0.247625 -0.008026123046875 0.1397607421875001 +0.24775 -0.008026123046875 0.1397607421875001 +0.247875 -0.007293701171875 0.1397607421875001 +0.248 -0.006561279296875 0.1397607421875001 +0.248125 -0.006561279296875 0.1397607421875001 +0.24825 -0.005828857421875 0.1397607421875001 +0.248375 -0.005828857421875 0.1397607421875001 +0.2485 -0.005096435546875 0.1397607421875001 +0.248625 -0.004364013671875 0.1397607421875001 +0.24875 -0.004364013671875 0.1397607421875001 +0.248875 -0.003631591796875 0.1397607421875001 +0.249 -0.003631591796875 0.1397607421875001 +0.249125 -0.002899169921875 0.1397607421875001 +0.24925 -0.002166748046875 0.1397607421875001 +0.249375 -0.002166748046875 0.1397607421875001 +0.2495 -0.001434326171875 0.1397607421875001 +0.249625 -0.001434326171875 0.1397607421875001 +0.24975 -0.000701904296875 0.1397607421875001 0.249875 0.0 0.1397607421875001 0.25 0.0 0.1397607421875001 0.250125 0.000701904296875 0.1397607421875001 @@ -2046,457 +2046,457 @@ 0.255625 0.01947021484375 0.1397607421875001 0.25575 0.020172119140625 0.1397607421875001 0.255875 0.020172119140625 0.1397607421875001 -0.256 -0.02508544921875 -0.1676269531250002 -0.256125 -0.025909423828125 -0.1676269531250002 -0.25625 -0.025909423828125 -0.1676269531250002 -0.256375 -0.0267333984375 -0.1676269531250002 -0.2565 -0.0267333984375 -0.1676269531250002 -0.256625 -0.027587890625 -0.1676269531250002 -0.25675 -0.028411865234375 -0.1676269531250002 -0.256875 -0.028411865234375 -0.1676269531250002 -0.257 -0.02923583984375 -0.1676269531250002 -0.257125 -0.02923583984375 -0.1676269531250002 -0.25725 -0.030059814453125 -0.1676269531250002 -0.257375 -0.030853271484375 -0.1676269531250002 -0.2575 -0.030853271484375 -0.1676269531250002 -0.257625 -0.03167724609375 -0.1676269531250002 -0.25775 -0.03167724609375 -0.1676269531250002 -0.257875 -0.032501220703125 -0.1676269531250002 -0.258 -0.033294677734375 -0.1676269531250002 -0.258125 -0.033294677734375 -0.1676269531250002 -0.25825 -0.03411865234375 -0.1676269531250002 -0.258375 -0.03411865234375 -0.1676269531250002 -0.2585 -0.034912109375 -0.1676269531250002 -0.258625 -0.03570556640625 -0.1676269531250002 -0.25875 -0.03570556640625 -0.1676269531250002 -0.258875 -0.0364990234375 -0.1676269531250002 -0.259 -0.0364990234375 -0.1676269531250002 -0.259125 -0.03729248046875 -0.1676269531250002 -0.25925 -0.038055419921875 -0.1676269531250002 -0.259375 -0.038055419921875 -0.1676269531250002 -0.2595 -0.038848876953125 -0.1676269531250002 -0.259625 -0.038848876953125 -0.1676269531250002 -0.25975 -0.03961181640625 -0.1676269531250002 -0.259875 -0.0404052734375 -0.1676269531250002 -0.26 -0.0404052734375 -0.1676269531250002 -0.260125 -0.041168212890625 -0.1676269531250002 -0.26025 -0.041168212890625 -0.1676269531250002 -0.260375 -0.04193115234375 -0.1676269531250002 -0.2605 -0.04266357421875 -0.1676269531250002 -0.260625 -0.04266357421875 -0.1676269531250002 -0.26075 -0.043426513671875 -0.1676269531250002 -0.260875 -0.043426513671875 -0.1676269531250002 -0.261 -0.044189453125 -0.1676269531250002 -0.261125 -0.044921875 -0.1676269531250002 -0.26125 -0.044921875 -0.1676269531250002 -0.261375 -0.045654296875 -0.1676269531250002 -0.2615 -0.045654296875 -0.1676269531250002 -0.261625 -0.04638671875 -0.1676269531250002 -0.26175 -0.047119140625 -0.1676269531250002 -0.261875 -0.047119140625 -0.1676269531250002 -0.262 -0.0478515625 -0.1676269531250002 -0.262125 -0.0478515625 -0.1676269531250002 -0.26225 -0.048553466796875 -0.1676269531250002 -0.262375 -0.049285888671875 -0.1676269531250002 -0.2625 -0.049285888671875 -0.1676269531250002 -0.262625 -0.04998779296875 -0.1676269531250002 -0.26275 -0.04998779296875 -0.1676269531250002 -0.262875 -0.050689697265625 -0.1676269531250002 -0.263 -0.0513916015625 -0.1676269531250002 -0.263125 -0.0513916015625 -0.1676269531250002 -0.26325 -0.05206298828125 -0.1676269531250002 -0.263375 -0.05206298828125 -0.1676269531250002 -0.2635 -0.052764892578125 -0.1676269531250002 -0.263625 -0.053436279296875 -0.1676269531250002 -0.26375 -0.053436279296875 -0.1676269531250002 -0.263875 -0.054107666015625 -0.1676269531250002 -0.264 -0.054107666015625 -0.1676269531250002 -0.264125 -0.054779052734375 -0.1676269531250002 -0.26425 -0.055450439453125 -0.1676269531250002 -0.264375 -0.055450439453125 -0.1676269531250002 -0.2645 -0.05609130859375 -0.1676269531250002 -0.264625 -0.05609130859375 -0.1676269531250002 -0.26475 -0.056732177734375 -0.1676269531250002 -0.264875 -0.057403564453125 -0.1676269531250002 -0.265 -0.057403564453125 -0.1676269531250002 -0.265125 -0.058013916015625 -0.1676269531250002 -0.26525 -0.058013916015625 -0.1676269531250002 -0.265375 -0.05865478515625 -0.1676269531250002 -0.2655 -0.05926513671875 -0.1676269531250002 -0.265625 -0.05926513671875 -0.1676269531250002 -0.26575 -0.059906005859375 -0.1676269531250002 -0.265875 -0.059906005859375 -0.1676269531250002 -0.266 -0.060516357421875 -0.1676269531250002 -0.266125 -0.061126708984375 -0.1676269531250002 -0.26625 -0.061126708984375 -0.1676269531250002 -0.266375 -0.06170654296875 -0.1676269531250002 -0.2665 -0.06170654296875 -0.1676269531250002 -0.266625 -0.062286376953125 -0.1676269531250002 -0.26675 -0.062896728515625 -0.1676269531250002 -0.266875 -0.062896728515625 -0.1676269531250002 -0.267 -0.063446044921875 -0.1676269531250002 -0.267125 -0.063446044921875 -0.1676269531250002 -0.26725 -0.06402587890625 -0.1676269531250002 -0.267375 -0.064605712890625 -0.1676269531250002 -0.2675 -0.064605712890625 -0.1676269531250002 -0.267625 -0.065155029296875 -0.1676269531250002 -0.26775 -0.065155029296875 -0.1676269531250002 -0.267875 -0.065704345703125 -0.1676269531250002 -0.268 -0.066253662109375 -0.1676269531250002 -0.268125 -0.066253662109375 -0.1676269531250002 -0.26825 -0.0667724609375 -0.1676269531250002 -0.268375 -0.0667724609375 -0.1676269531250002 -0.2685 -0.067291259765625 -0.1676269531250002 -0.268625 -0.06781005859375 -0.1676269531250002 -0.26875 -0.06781005859375 -0.1676269531250002 -0.268875 -0.068328857421875 -0.1676269531250002 -0.269 -0.068328857421875 -0.1676269531250002 -0.269125 -0.06884765625 -0.1676269531250002 -0.26925 -0.0693359375 -0.1676269531250002 -0.2693750000000001 -0.0693359375 -0.1676269531250002 -0.2695 -0.06982421875 -0.1676269531250002 -0.269625 -0.06982421875 -0.1676269531250002 -0.26975 -0.0703125 -0.1676269531250002 -0.269875 -0.070770263671875 -0.1676269531250002 -0.27 -0.070770263671875 -0.1676269531250002 -0.270125 -0.071258544921875 -0.1676269531250002 -0.27025 -0.071258544921875 -0.1676269531250002 -0.270375 -0.07171630859375 -0.1676269531250002 -0.2705 -0.0721435546875 -0.1676269531250002 -0.270625 -0.0721435546875 -0.1676269531250002 -0.27075 -0.072601318359375 -0.1676269531250002 -0.270875 -0.072601318359375 -0.1676269531250002 -0.271 -0.073028564453125 -0.1676269531250002 -0.271125 -0.073455810546875 -0.1676269531250002 -0.27125 -0.073455810546875 -0.1676269531250002 -0.271375 -0.073883056640625 -0.1676269531250002 -0.2715 -0.073883056640625 -0.1676269531250002 -0.271625 -0.07427978515625 -0.1676269531250002 -0.27175 -0.07470703125 -0.1676269531250002 -0.271875 -0.07470703125 -0.1676269531250002 -0.272 -0.0750732421875 -0.1676269531250002 -0.272125 -0.0750732421875 -0.1676269531250002 -0.27225 -0.075469970703125 -0.1676269531250002 -0.272375 -0.075836181640625 -0.1676269531250002 -0.2725 -0.075836181640625 -0.1676269531250002 -0.272625 -0.07623291015625 -0.1676269531250002 -0.27275 -0.07623291015625 -0.1676269531250002 -0.272875 -0.076568603515625 -0.1676269531250002 -0.273 -0.076934814453125 -0.1676269531250002 -0.273125 -0.076934814453125 -0.1676269531250002 -0.27325 -0.0772705078125 -0.1676269531250002 -0.273375 -0.0772705078125 -0.1676269531250002 -0.2735 -0.077606201171875 -0.1676269531250002 -0.273625 -0.07794189453125 -0.1676269531250002 -0.27375 -0.07794189453125 -0.1676269531250002 -0.273875 -0.0782470703125 -0.1676269531250002 -0.274 -0.0782470703125 -0.1676269531250002 -0.274125 -0.078582763671875 -0.1676269531250002 -0.27425 -0.078857421875 -0.1676269531250002 -0.274375 -0.078857421875 -0.1676269531250002 -0.2745 -0.07916259765625 -0.1676269531250002 -0.274625 -0.07916259765625 -0.1676269531250002 -0.27475 -0.079437255859375 -0.1676269531250002 -0.274875 -0.0797119140625 -0.1676269531250002 -0.275 -0.0797119140625 -0.1676269531250002 -0.275125 -0.079986572265625 -0.1676269531250002 -0.27525 -0.079986572265625 -0.1676269531250002 -0.275375 -0.08026123046875 -0.1676269531250002 -0.2755 -0.08050537109375 -0.1676269531250002 -0.275625 -0.08050537109375 -0.1676269531250002 -0.27575 -0.08074951171875 -0.1676269531250002 -0.275875 -0.08074951171875 -0.1676269531250002 -0.276 -0.080963134765625 -0.1676269531250002 -0.276125 -0.081207275390625 -0.1676269531250002 -0.27625 -0.081207275390625 -0.1676269531250002 -0.276375 -0.0814208984375 -0.1676269531250002 -0.2765 -0.0814208984375 -0.1676269531250002 -0.276625 -0.08160400390625 -0.1676269531250002 -0.27675 -0.081817626953125 -0.1676269531250002 -0.276875 -0.081817626953125 -0.1676269531250002 -0.277 -0.082000732421875 -0.1676269531250002 -0.277125 -0.082000732421875 -0.1676269531250002 -0.27725 -0.082183837890625 -0.1676269531250002 -0.277375 -0.08233642578125 -0.1676269531250002 -0.2775 -0.08233642578125 -0.1676269531250002 -0.277625 -0.082489013671875 -0.1676269531250002 -0.27775 -0.082489013671875 -0.1676269531250002 -0.277875 -0.0826416015625 -0.1676269531250002 -0.278 -0.082794189453125 -0.1676269531250002 -0.278125 -0.082794189453125 -0.1676269531250002 -0.27825 -0.082916259765625 -0.1676269531250002 -0.278375 -0.082916259765625 -0.1676269531250002 -0.2785 -0.083038330078125 -0.1676269531250002 -0.278625 -0.083160400390625 -0.1676269531250002 -0.27875 -0.083160400390625 -0.1676269531250002 -0.278875 -0.083282470703125 -0.1676269531250002 -0.279 -0.083282470703125 -0.1676269531250002 -0.279125 -0.0833740234375 -0.1676269531250002 -0.27925 -0.083465576171875 -0.1676269531250002 -0.279375 -0.083465576171875 -0.1676269531250002 -0.2795 -0.083526611328125 -0.1676269531250002 -0.279625 -0.083526611328125 -0.1676269531250002 -0.27975 -0.0836181640625 -0.1676269531250002 -0.279875 -0.083648681640625 -0.1676269531250002 -0.28 -0.083648681640625 -0.1676269531250002 -0.280125 -0.083709716796875 -0.1676269531250002 -0.28025 -0.083709716796875 -0.1676269531250002 -0.280375 -0.083740234375 -0.1676269531250002 -0.2805 -0.083770751953125 -0.1676269531250002 -0.280625 -0.083770751953125 -0.1676269531250002 -0.28075 -0.08380126953125 -0.1676269531250002 -0.280875 -0.08380126953125 -0.1676269531250002 -0.281 -0.083831787109375 -0.1676269531250002 -0.281125 -0.083831787109375 -0.1676269531250002 -0.28125 -0.083831787109375 -0.1676269531250002 -0.281375 -0.083831787109375 -0.1676269531250002 -0.2815 -0.083831787109375 -0.1676269531250002 -0.281625 -0.08380126953125 -0.1676269531250002 -0.28175 -0.083770751953125 -0.1676269531250002 -0.281875 -0.083770751953125 -0.1676269531250002 -0.282 -0.083740234375 -0.1676269531250002 -0.282125 -0.083740234375 -0.1676269531250002 -0.28225 -0.083709716796875 -0.1676269531250002 -0.282375 -0.083648681640625 -0.1676269531250002 -0.2825 -0.083648681640625 -0.1676269531250002 -0.282625 -0.0836181640625 -0.1676269531250002 -0.28275 -0.0836181640625 -0.1676269531250002 -0.282875 -0.083526611328125 -0.1676269531250002 -0.283 -0.083465576171875 -0.1676269531250002 -0.283125 -0.083465576171875 -0.1676269531250002 -0.28325 -0.0833740234375 -0.1676269531250002 -0.283375 -0.0833740234375 -0.1676269531250002 -0.2835 -0.083282470703125 -0.1676269531250002 -0.283625 -0.083160400390625 -0.1676269531250002 -0.28375 -0.083160400390625 -0.1676269531250002 -0.283875 -0.083038330078125 -0.1676269531250002 -0.284 -0.083038330078125 -0.1676269531250002 -0.284125 -0.082916259765625 -0.1676269531250002 -0.28425 -0.082794189453125 -0.1676269531250002 -0.284375 -0.082794189453125 -0.1676269531250002 -0.2845 -0.0826416015625 -0.1676269531250002 -0.284625 -0.0826416015625 -0.1676269531250002 -0.28475 -0.082489013671875 -0.1676269531250002 -0.284875 -0.08233642578125 -0.1676269531250002 -0.2850000000000001 -0.08233642578125 -0.1676269531250002 -0.285125 -0.082183837890625 -0.1676269531250002 -0.28525 -0.082183837890625 -0.1676269531250002 -0.285375 -0.082000732421875 -0.1676269531250002 -0.2855 -0.081817626953125 -0.1676269531250002 -0.285625 -0.081817626953125 -0.1676269531250002 -0.28575 -0.08160400390625 -0.1676269531250002 -0.285875 -0.08160400390625 -0.1676269531250002 -0.286 -0.0814208984375 -0.1676269531250002 -0.286125 -0.081207275390625 -0.1676269531250002 -0.28625 -0.081207275390625 -0.1676269531250002 -0.286375 -0.080963134765625 -0.1676269531250002 -0.2865 -0.080963134765625 -0.1676269531250002 -0.286625 -0.08074951171875 -0.1676269531250002 -0.28675 -0.08050537109375 -0.1676269531250002 -0.286875 -0.08050537109375 -0.1676269531250002 -0.287 -0.08026123046875 -0.1676269531250002 -0.287125 -0.08026123046875 -0.1676269531250002 -0.28725 -0.079986572265625 -0.1676269531250002 -0.287375 -0.0797119140625 -0.1676269531250002 -0.2875 -0.0797119140625 -0.1676269531250002 -0.287625 -0.079437255859375 -0.1676269531250002 -0.28775 -0.079437255859375 -0.1676269531250002 -0.287875 -0.07916259765625 -0.1676269531250002 -0.288 -0.195892333984375 -0.4163818359375004 -0.288125 -0.195892333984375 -0.4163818359375004 -0.28825 -0.19512939453125 -0.4163818359375004 -0.288375 -0.19512939453125 -0.4163818359375004 -0.2885 -0.194366455078125 -0.4163818359375004 -0.288625 -0.193572998046875 -0.4163818359375004 -0.28875 -0.193572998046875 -0.4163818359375004 -0.288875 -0.192779541015625 -0.4163818359375004 -0.289 -0.192779541015625 -0.4163818359375004 -0.289125 -0.191925048828125 -0.4163818359375004 -0.28925 -0.191070556640625 -0.4163818359375004 -0.289375 -0.191070556640625 -0.4163818359375004 -0.2895 -0.190185546875 -0.4163818359375004 -0.289625 -0.190185546875 -0.4163818359375004 -0.28975 -0.189300537109375 -0.4163818359375004 -0.289875 -0.188385009765625 -0.4163818359375004 -0.29 -0.188385009765625 -0.4163818359375004 -0.290125 -0.18743896484375 -0.4163818359375004 -0.29025 -0.18743896484375 -0.4163818359375004 -0.290375 -0.186492919921875 -0.4163818359375004 -0.2905 -0.185516357421875 -0.4163818359375004 -0.290625 -0.185516357421875 -0.4163818359375004 -0.29075 -0.18450927734375 -0.4163818359375004 -0.290875 -0.18450927734375 -0.4163818359375004 -0.291 -0.1834716796875 -0.4163818359375004 -0.291125 -0.18243408203125 -0.4163818359375004 -0.29125 -0.18243408203125 -0.4163818359375004 -0.291375 -0.181396484375 -0.4163818359375004 -0.2915 -0.181396484375 -0.4163818359375004 -0.291625 -0.1802978515625 -0.4163818359375004 -0.29175 -0.17919921875 -0.4163818359375004 -0.291875 -0.17919921875 -0.4163818359375004 -0.292 -0.178070068359375 -0.4163818359375004 -0.292125 -0.178070068359375 -0.4163818359375004 -0.29225 -0.17694091796875 -0.4163818359375004 -0.292375 -0.17578125 -0.4163818359375004 -0.2925 -0.17578125 -0.4163818359375004 -0.292625 -0.17462158203125 -0.4163818359375004 -0.29275 -0.17462158203125 -0.4163818359375004 -0.292875 -0.17340087890625 -0.4163818359375004 -0.293 -0.17218017578125 -0.4163818359375004 -0.293125 -0.17218017578125 -0.4163818359375004 -0.29325 -0.17095947265625 -0.4163818359375004 -0.293375 -0.17095947265625 -0.4163818359375004 -0.2935 -0.169708251953125 -0.4163818359375004 -0.293625 -0.168426513671875 -0.4163818359375004 -0.29375 -0.168426513671875 -0.4163818359375004 -0.293875 -0.167144775390625 -0.4163818359375004 -0.294 -0.167144775390625 -0.4163818359375004 -0.294125 -0.16583251953125 -0.4163818359375004 -0.29425 -0.164520263671875 -0.4163818359375004 -0.294375 -0.164520263671875 -0.4163818359375004 -0.2945 -0.163177490234375 -0.4163818359375004 -0.294625 -0.163177490234375 -0.4163818359375004 -0.29475 -0.16180419921875 -0.4163818359375004 -0.294875 -0.160430908203125 -0.4163818359375004 -0.295 -0.160430908203125 -0.4163818359375004 -0.295125 -0.159027099609375 -0.4163818359375004 -0.29525 -0.159027099609375 -0.4163818359375004 -0.295375 -0.1575927734375 -0.4163818359375004 -0.2955 -0.156158447265625 -0.4163818359375004 -0.295625 -0.156158447265625 -0.4163818359375004 -0.29575 -0.15472412109375 -0.4163818359375004 -0.295875 -0.15472412109375 -0.4163818359375004 -0.296 -0.15325927734375 -0.4163818359375004 -0.296125 -0.151763916015625 -0.4163818359375004 -0.29625 -0.151763916015625 -0.4163818359375004 -0.296375 -0.1502685546875 -0.4163818359375004 -0.2965 -0.1502685546875 -0.4163818359375004 -0.296625 -0.14874267578125 -0.4163818359375004 -0.29675 -0.147216796875 -0.4163818359375004 -0.296875 -0.147216796875 -0.4163818359375004 -0.297 -0.145660400390625 -0.4163818359375004 -0.297125 -0.145660400390625 -0.4163818359375004 -0.29725 -0.14410400390625 -0.4163818359375004 -0.297375 -0.14251708984375 -0.4163818359375004 -0.2975 -0.14251708984375 -0.4163818359375004 -0.297625 -0.14093017578125 -0.4163818359375004 -0.29775 -0.14093017578125 -0.4163818359375004 -0.297875 -0.139312744140625 -0.4163818359375004 -0.298 -0.1376953125 -0.4163818359375004 -0.298125 -0.1376953125 -0.4163818359375004 -0.29825 -0.13604736328125 -0.4163818359375004 -0.298375 -0.13604736328125 -0.4163818359375004 -0.2985 -0.1343994140625 -0.4163818359375004 -0.298625 -0.132720947265625 -0.4163818359375004 -0.29875 -0.132720947265625 -0.4163818359375004 -0.298875 -0.131011962890625 -0.4163818359375004 -0.299 -0.131011962890625 -0.4163818359375004 -0.299125 -0.12933349609375 -0.4163818359375004 -0.29925 -0.12762451171875 -0.4163818359375004 -0.299375 -0.12762451171875 -0.4163818359375004 -0.2995 -0.125885009765625 -0.4163818359375004 -0.299625 -0.125885009765625 -0.4163818359375004 -0.29975 -0.1241455078125 -0.4163818359375004 -0.299875 -0.12237548828125 -0.4163818359375004 -0.3 -0.12237548828125 -0.4163818359375004 -0.300125 -0.12060546875 -0.4163818359375004 -0.30025 -0.12060546875 -0.4163818359375004 -0.300375 -0.11883544921875 -0.4163818359375004 -0.3005 -0.117034912109375 -0.4163818359375004 -0.3006250000000001 -0.117034912109375 -0.4163818359375004 -0.30075 -0.115203857421875 -0.4163818359375004 -0.300875 -0.115203857421875 -0.4163818359375004 -0.301 -0.1134033203125 -0.4163818359375004 -0.301125 -0.111572265625 -0.4163818359375004 -0.30125 -0.111572265625 -0.4163818359375004 -0.301375 -0.109710693359375 -0.4163818359375004 -0.3015 -0.109710693359375 -0.4163818359375004 -0.301625 -0.10784912109375 -0.4163818359375004 -0.30175 -0.105987548828125 -0.4163818359375004 -0.301875 -0.105987548828125 -0.4163818359375004 -0.302 -0.104095458984375 -0.4163818359375004 -0.302125 -0.104095458984375 -0.4163818359375004 -0.30225 -0.102203369140625 -0.4163818359375004 -0.302375 -0.100311279296875 -0.4163818359375004 -0.3025 -0.100311279296875 -0.4163818359375004 -0.302625 -0.098388671875 -0.4163818359375004 -0.30275 -0.098388671875 -0.4163818359375004 -0.302875 -0.096466064453125 -0.4163818359375004 -0.303 -0.094512939453125 -0.4163818359375004 -0.303125 -0.094512939453125 -0.4163818359375004 -0.30325 -0.09259033203125 -0.4163818359375004 -0.303375 -0.09259033203125 -0.4163818359375004 -0.3035 -0.09063720703125 -0.4163818359375004 -0.303625 -0.088653564453125 -0.4163818359375004 -0.30375 -0.088653564453125 -0.4163818359375004 -0.303875 -0.086669921875 -0.4163818359375004 -0.304 -0.086669921875 -0.4163818359375004 -0.304125 -0.084686279296875 -0.4163818359375004 -0.30425 -0.08270263671875 -0.4163818359375004 -0.304375 -0.08270263671875 -0.4163818359375004 -0.3045 -0.0806884765625 -0.4163818359375004 -0.304625 -0.0806884765625 -0.4163818359375004 -0.30475 -0.07867431640625 -0.4163818359375004 -0.304875 -0.07666015625 -0.4163818359375004 -0.305 -0.07666015625 -0.4163818359375004 -0.305125 -0.074615478515625 -0.4163818359375004 -0.30525 -0.074615478515625 -0.4163818359375004 -0.305375 -0.07257080078125 -0.4163818359375004 -0.3055 -0.070526123046875 -0.4163818359375004 -0.305625 -0.070526123046875 -0.4163818359375004 -0.30575 -0.0684814453125 -0.4163818359375004 -0.305875 -0.0684814453125 -0.4163818359375004 -0.306 -0.06640625 -0.4163818359375004 -0.306125 -0.0643310546875 -0.4163818359375004 -0.30625 -0.0643310546875 -0.4163818359375004 -0.306375 -0.062255859375 -0.4163818359375004 -0.3065 -0.062255859375 -0.4163818359375004 -0.306625 -0.0601806640625 -0.4163818359375004 -0.30675 -0.05810546875 -0.4163818359375004 -0.306875 -0.05810546875 -0.4163818359375004 -0.307 -0.055999755859375 -0.4163818359375004 -0.307125 -0.055999755859375 -0.4163818359375004 -0.30725 -0.05389404296875 -0.4163818359375004 -0.307375 -0.051788330078125 -0.4163818359375004 -0.3075 -0.051788330078125 -0.4163818359375004 -0.307625 -0.0496826171875 -0.4163818359375004 -0.30775 -0.0496826171875 -0.4163818359375004 -0.307875 -0.04754638671875 -0.4163818359375004 -0.308 -0.04541015625 -0.4163818359375004 -0.308125 -0.04541015625 -0.4163818359375004 -0.30825 -0.043304443359375 -0.4163818359375004 -0.308375 -0.043304443359375 -0.4163818359375004 -0.3085 -0.041168212890625 -0.4163818359375004 -0.308625 -0.039031982421875 -0.4163818359375004 -0.30875 -0.039031982421875 -0.4163818359375004 -0.308875 -0.036865234375 -0.4163818359375004 -0.309 -0.036865234375 -0.4163818359375004 -0.309125 -0.03472900390625 -0.4163818359375004 -0.30925 -0.032562255859375 -0.4163818359375004 -0.309375 -0.032562255859375 -0.4163818359375004 -0.3095 -0.030426025390625 -0.4163818359375004 -0.309625 -0.030426025390625 -0.4163818359375004 -0.30975 -0.02825927734375 -0.4163818359375004 -0.309875 -0.026092529296875 -0.4163818359375004 -0.31 -0.026092529296875 -0.4163818359375004 -0.310125 -0.023956298828125 -0.4163818359375004 -0.31025 -0.023956298828125 -0.4163818359375004 -0.310375 -0.02178955078125 -0.4163818359375004 -0.3105 -0.01959228515625 -0.4163818359375004 -0.310625 -0.01959228515625 -0.4163818359375004 -0.31075 -0.017425537109375 -0.4163818359375004 -0.310875 -0.017425537109375 -0.4163818359375004 -0.311 -0.0152587890625 -0.4163818359375004 -0.311125 -0.013092041015625 -0.4163818359375004 -0.31125 -0.013092041015625 -0.4163818359375004 -0.311375 -0.010894775390625 -0.4163818359375004 -0.3115 -0.010894775390625 -0.4163818359375004 -0.311625 -0.00872802734375 -0.4163818359375004 -0.31175 -0.006561279296875 -0.4163818359375004 -0.311875 -0.006561279296875 -0.4163818359375004 -0.312 -0.004364013671875 -0.4163818359375004 -0.312125 -0.004364013671875 -0.4163818359375004 -0.31225 -0.002197265625 -0.4163818359375004 +0.256 -0.025054931640625 -0.1676269531250002 +0.256125 -0.02587890625 -0.1676269531250002 +0.25625 -0.02587890625 -0.1676269531250002 +0.256375 -0.026702880859375 -0.1676269531250002 +0.2565 -0.026702880859375 -0.1676269531250002 +0.256625 -0.027557373046875 -0.1676269531250002 +0.25675 -0.02838134765625 -0.1676269531250002 +0.256875 -0.02838134765625 -0.1676269531250002 +0.257 -0.029205322265625 -0.1676269531250002 +0.257125 -0.029205322265625 -0.1676269531250002 +0.25725 -0.030029296875 -0.1676269531250002 +0.257375 -0.03082275390625 -0.1676269531250002 +0.2575 -0.03082275390625 -0.1676269531250002 +0.257625 -0.031646728515625 -0.1676269531250002 +0.25775 -0.031646728515625 -0.1676269531250002 +0.257875 -0.032470703125 -0.1676269531250002 +0.258 -0.03326416015625 -0.1676269531250002 +0.258125 -0.03326416015625 -0.1676269531250002 +0.25825 -0.034088134765625 -0.1676269531250002 +0.258375 -0.034088134765625 -0.1676269531250002 +0.2585 -0.034881591796875 -0.1676269531250002 +0.258625 -0.035675048828125 -0.1676269531250002 +0.25875 -0.035675048828125 -0.1676269531250002 +0.258875 -0.036468505859375 -0.1676269531250002 +0.259 -0.036468505859375 -0.1676269531250002 +0.259125 -0.037261962890625 -0.1676269531250002 +0.25925 -0.03802490234375 -0.1676269531250002 +0.259375 -0.03802490234375 -0.1676269531250002 +0.2595 -0.038818359375 -0.1676269531250002 +0.259625 -0.038818359375 -0.1676269531250002 +0.25975 -0.039581298828125 -0.1676269531250002 +0.259875 -0.040374755859375 -0.1676269531250002 +0.26 -0.040374755859375 -0.1676269531250002 +0.260125 -0.0411376953125 -0.1676269531250002 +0.26025 -0.0411376953125 -0.1676269531250002 +0.260375 -0.041900634765625 -0.1676269531250002 +0.2605 -0.042633056640625 -0.1676269531250002 +0.260625 -0.042633056640625 -0.1676269531250002 +0.26075 -0.04339599609375 -0.1676269531250002 +0.260875 -0.04339599609375 -0.1676269531250002 +0.261 -0.044158935546875 -0.1676269531250002 +0.261125 -0.044891357421875 -0.1676269531250002 +0.26125 -0.044891357421875 -0.1676269531250002 +0.261375 -0.045623779296875 -0.1676269531250002 +0.2615 -0.045623779296875 -0.1676269531250002 +0.261625 -0.046356201171875 -0.1676269531250002 +0.26175 -0.047088623046875 -0.1676269531250002 +0.261875 -0.047088623046875 -0.1676269531250002 +0.262 -0.047821044921875 -0.1676269531250002 +0.262125 -0.047821044921875 -0.1676269531250002 +0.26225 -0.04852294921875 -0.1676269531250002 +0.262375 -0.04925537109375 -0.1676269531250002 +0.2625 -0.04925537109375 -0.1676269531250002 +0.262625 -0.049957275390625 -0.1676269531250002 +0.26275 -0.049957275390625 -0.1676269531250002 +0.262875 -0.0506591796875 -0.1676269531250002 +0.263 -0.051361083984375 -0.1676269531250002 +0.263125 -0.051361083984375 -0.1676269531250002 +0.26325 -0.052032470703125 -0.1676269531250002 +0.263375 -0.052032470703125 -0.1676269531250002 +0.2635 -0.052734375 -0.1676269531250002 +0.263625 -0.05340576171875 -0.1676269531250002 +0.26375 -0.05340576171875 -0.1676269531250002 +0.263875 -0.0540771484375 -0.1676269531250002 +0.264 -0.0540771484375 -0.1676269531250002 +0.264125 -0.05474853515625 -0.1676269531250002 +0.26425 -0.055419921875 -0.1676269531250002 +0.264375 -0.055419921875 -0.1676269531250002 +0.2645 -0.056060791015625 -0.1676269531250002 +0.264625 -0.056060791015625 -0.1676269531250002 +0.26475 -0.05670166015625 -0.1676269531250002 +0.264875 -0.057373046875 -0.1676269531250002 +0.265 -0.057373046875 -0.1676269531250002 +0.265125 -0.0579833984375 -0.1676269531250002 +0.26525 -0.0579833984375 -0.1676269531250002 +0.265375 -0.058624267578125 -0.1676269531250002 +0.2655 -0.059234619140625 -0.1676269531250002 +0.265625 -0.059234619140625 -0.1676269531250002 +0.26575 -0.05987548828125 -0.1676269531250002 +0.265875 -0.05987548828125 -0.1676269531250002 +0.266 -0.06048583984375 -0.1676269531250002 +0.266125 -0.06109619140625 -0.1676269531250002 +0.26625 -0.06109619140625 -0.1676269531250002 +0.266375 -0.061676025390625 -0.1676269531250002 +0.2665 -0.061676025390625 -0.1676269531250002 +0.266625 -0.062255859375 -0.1676269531250002 +0.26675 -0.0628662109375 -0.1676269531250002 +0.266875 -0.0628662109375 -0.1676269531250002 +0.267 -0.06341552734375 -0.1676269531250002 +0.267125 -0.06341552734375 -0.1676269531250002 +0.26725 -0.063995361328125 -0.1676269531250002 +0.267375 -0.0645751953125 -0.1676269531250002 +0.2675 -0.0645751953125 -0.1676269531250002 +0.267625 -0.06512451171875 -0.1676269531250002 +0.26775 -0.06512451171875 -0.1676269531250002 +0.267875 -0.065673828125 -0.1676269531250002 +0.268 -0.06622314453125 -0.1676269531250002 +0.268125 -0.06622314453125 -0.1676269531250002 +0.26825 -0.066741943359375 -0.1676269531250002 +0.268375 -0.066741943359375 -0.1676269531250002 +0.2685 -0.0672607421875 -0.1676269531250002 +0.268625 -0.067779541015625 -0.1676269531250002 +0.26875 -0.067779541015625 -0.1676269531250002 +0.268875 -0.06829833984375 -0.1676269531250002 +0.269 -0.06829833984375 -0.1676269531250002 +0.269125 -0.068817138671875 -0.1676269531250002 +0.26925 -0.069305419921875 -0.1676269531250002 +0.2693750000000001 -0.069305419921875 -0.1676269531250002 +0.2695 -0.069793701171875 -0.1676269531250002 +0.269625 -0.069793701171875 -0.1676269531250002 +0.26975 -0.070281982421875 -0.1676269531250002 +0.269875 -0.07073974609375 -0.1676269531250002 +0.27 -0.07073974609375 -0.1676269531250002 +0.270125 -0.07122802734375 -0.1676269531250002 +0.27025 -0.07122802734375 -0.1676269531250002 +0.270375 -0.071685791015625 -0.1676269531250002 +0.2705 -0.072113037109375 -0.1676269531250002 +0.270625 -0.072113037109375 -0.1676269531250002 +0.27075 -0.07257080078125 -0.1676269531250002 +0.270875 -0.07257080078125 -0.1676269531250002 +0.271 -0.072998046875 -0.1676269531250002 +0.271125 -0.07342529296875 -0.1676269531250002 +0.27125 -0.07342529296875 -0.1676269531250002 +0.271375 -0.0738525390625 -0.1676269531250002 +0.2715 -0.0738525390625 -0.1676269531250002 +0.271625 -0.074249267578125 -0.1676269531250002 +0.27175 -0.074676513671875 -0.1676269531250002 +0.271875 -0.074676513671875 -0.1676269531250002 +0.272 -0.075042724609375 -0.1676269531250002 +0.272125 -0.075042724609375 -0.1676269531250002 +0.27225 -0.075439453125 -0.1676269531250002 +0.272375 -0.0758056640625 -0.1676269531250002 +0.2725 -0.0758056640625 -0.1676269531250002 +0.272625 -0.076202392578125 -0.1676269531250002 +0.27275 -0.076202392578125 -0.1676269531250002 +0.272875 -0.0765380859375 -0.1676269531250002 +0.273 -0.076904296875 -0.1676269531250002 +0.273125 -0.076904296875 -0.1676269531250002 +0.27325 -0.077239990234375 -0.1676269531250002 +0.273375 -0.077239990234375 -0.1676269531250002 +0.2735 -0.07757568359375 -0.1676269531250002 +0.273625 -0.077911376953125 -0.1676269531250002 +0.27375 -0.077911376953125 -0.1676269531250002 +0.273875 -0.078216552734375 -0.1676269531250002 +0.274 -0.078216552734375 -0.1676269531250002 +0.274125 -0.07855224609375 -0.1676269531250002 +0.27425 -0.078826904296875 -0.1676269531250002 +0.274375 -0.078826904296875 -0.1676269531250002 +0.2745 -0.079132080078125 -0.1676269531250002 +0.274625 -0.079132080078125 -0.1676269531250002 +0.27475 -0.07940673828125 -0.1676269531250002 +0.274875 -0.079681396484375 -0.1676269531250002 +0.275 -0.079681396484375 -0.1676269531250002 +0.275125 -0.0799560546875 -0.1676269531250002 +0.27525 -0.0799560546875 -0.1676269531250002 +0.275375 -0.080230712890625 -0.1676269531250002 +0.2755 -0.080474853515625 -0.1676269531250002 +0.275625 -0.080474853515625 -0.1676269531250002 +0.27575 -0.080718994140625 -0.1676269531250002 +0.275875 -0.080718994140625 -0.1676269531250002 +0.276 -0.0809326171875 -0.1676269531250002 +0.276125 -0.0811767578125 -0.1676269531250002 +0.27625 -0.0811767578125 -0.1676269531250002 +0.276375 -0.081390380859375 -0.1676269531250002 +0.2765 -0.081390380859375 -0.1676269531250002 +0.276625 -0.081573486328125 -0.1676269531250002 +0.27675 -0.081787109375 -0.1676269531250002 +0.276875 -0.081787109375 -0.1676269531250002 +0.277 -0.08197021484375 -0.1676269531250002 +0.277125 -0.08197021484375 -0.1676269531250002 +0.27725 -0.0821533203125 -0.1676269531250002 +0.277375 -0.082305908203125 -0.1676269531250002 +0.2775 -0.082305908203125 -0.1676269531250002 +0.277625 -0.08245849609375 -0.1676269531250002 +0.27775 -0.08245849609375 -0.1676269531250002 +0.277875 -0.082611083984375 -0.1676269531250002 +0.278 -0.082763671875 -0.1676269531250002 +0.278125 -0.082763671875 -0.1676269531250002 +0.27825 -0.0828857421875 -0.1676269531250002 +0.278375 -0.0828857421875 -0.1676269531250002 +0.2785 -0.0830078125 -0.1676269531250002 +0.278625 -0.0831298828125 -0.1676269531250002 +0.27875 -0.0831298828125 -0.1676269531250002 +0.278875 -0.083251953125 -0.1676269531250002 +0.279 -0.083251953125 -0.1676269531250002 +0.279125 -0.083343505859375 -0.1676269531250002 +0.27925 -0.08343505859375 -0.1676269531250002 +0.279375 -0.08343505859375 -0.1676269531250002 +0.2795 -0.08349609375 -0.1676269531250002 +0.279625 -0.08349609375 -0.1676269531250002 +0.27975 -0.083587646484375 -0.1676269531250002 +0.279875 -0.0836181640625 -0.1676269531250002 +0.28 -0.0836181640625 -0.1676269531250002 +0.280125 -0.08367919921875 -0.1676269531250002 +0.28025 -0.08367919921875 -0.1676269531250002 +0.280375 -0.083709716796875 -0.1676269531250002 +0.2805 -0.083740234375 -0.1676269531250002 +0.280625 -0.083740234375 -0.1676269531250002 +0.28075 -0.083770751953125 -0.1676269531250002 +0.280875 -0.083770751953125 -0.1676269531250002 +0.281 -0.08380126953125 -0.1676269531250002 +0.281125 -0.08380126953125 -0.1676269531250002 +0.28125 -0.08380126953125 -0.1676269531250002 +0.281375 -0.08380126953125 -0.1676269531250002 +0.2815 -0.08380126953125 -0.1676269531250002 +0.281625 -0.083770751953125 -0.1676269531250002 +0.28175 -0.083740234375 -0.1676269531250002 +0.281875 -0.083740234375 -0.1676269531250002 +0.282 -0.083709716796875 -0.1676269531250002 +0.282125 -0.083709716796875 -0.1676269531250002 +0.28225 -0.08367919921875 -0.1676269531250002 +0.282375 -0.0836181640625 -0.1676269531250002 +0.2825 -0.0836181640625 -0.1676269531250002 +0.282625 -0.083587646484375 -0.1676269531250002 +0.28275 -0.083587646484375 -0.1676269531250002 +0.282875 -0.08349609375 -0.1676269531250002 +0.283 -0.08343505859375 -0.1676269531250002 +0.283125 -0.08343505859375 -0.1676269531250002 +0.28325 -0.083343505859375 -0.1676269531250002 +0.283375 -0.083343505859375 -0.1676269531250002 +0.2835 -0.083251953125 -0.1676269531250002 +0.283625 -0.0831298828125 -0.1676269531250002 +0.28375 -0.0831298828125 -0.1676269531250002 +0.283875 -0.0830078125 -0.1676269531250002 +0.284 -0.0830078125 -0.1676269531250002 +0.284125 -0.0828857421875 -0.1676269531250002 +0.28425 -0.082763671875 -0.1676269531250002 +0.284375 -0.082763671875 -0.1676269531250002 +0.2845 -0.082611083984375 -0.1676269531250002 +0.284625 -0.082611083984375 -0.1676269531250002 +0.28475 -0.08245849609375 -0.1676269531250002 +0.284875 -0.082305908203125 -0.1676269531250002 +0.2850000000000001 -0.082305908203125 -0.1676269531250002 +0.285125 -0.0821533203125 -0.1676269531250002 +0.28525 -0.0821533203125 -0.1676269531250002 +0.285375 -0.08197021484375 -0.1676269531250002 +0.2855 -0.081787109375 -0.1676269531250002 +0.285625 -0.081787109375 -0.1676269531250002 +0.28575 -0.081573486328125 -0.1676269531250002 +0.285875 -0.081573486328125 -0.1676269531250002 +0.286 -0.081390380859375 -0.1676269531250002 +0.286125 -0.0811767578125 -0.1676269531250002 +0.28625 -0.0811767578125 -0.1676269531250002 +0.286375 -0.0809326171875 -0.1676269531250002 +0.2865 -0.0809326171875 -0.1676269531250002 +0.286625 -0.080718994140625 -0.1676269531250002 +0.28675 -0.080474853515625 -0.1676269531250002 +0.286875 -0.080474853515625 -0.1676269531250002 +0.287 -0.080230712890625 -0.1676269531250002 +0.287125 -0.080230712890625 -0.1676269531250002 +0.28725 -0.0799560546875 -0.1676269531250002 +0.287375 -0.079681396484375 -0.1676269531250002 +0.2875 -0.079681396484375 -0.1676269531250002 +0.287625 -0.07940673828125 -0.1676269531250002 +0.28775 -0.07940673828125 -0.1676269531250002 +0.287875 -0.079132080078125 -0.1676269531250002 +0.288 -0.19586181640625 -0.4163818359375004 +0.288125 -0.19586181640625 -0.4163818359375004 +0.28825 -0.195098876953125 -0.4163818359375004 +0.288375 -0.195098876953125 -0.4163818359375004 +0.2885 -0.1943359375 -0.4163818359375004 +0.288625 -0.19354248046875 -0.4163818359375004 +0.28875 -0.19354248046875 -0.4163818359375004 +0.288875 -0.1927490234375 -0.4163818359375004 +0.289 -0.1927490234375 -0.4163818359375004 +0.289125 -0.19189453125 -0.4163818359375004 +0.28925 -0.1910400390625 -0.4163818359375004 +0.289375 -0.1910400390625 -0.4163818359375004 +0.2895 -0.190155029296875 -0.4163818359375004 +0.289625 -0.190155029296875 -0.4163818359375004 +0.28975 -0.18927001953125 -0.4163818359375004 +0.289875 -0.1883544921875 -0.4163818359375004 +0.29 -0.1883544921875 -0.4163818359375004 +0.290125 -0.187408447265625 -0.4163818359375004 +0.29025 -0.187408447265625 -0.4163818359375004 +0.290375 -0.18646240234375 -0.4163818359375004 +0.2905 -0.18548583984375 -0.4163818359375004 +0.290625 -0.18548583984375 -0.4163818359375004 +0.29075 -0.184478759765625 -0.4163818359375004 +0.290875 -0.184478759765625 -0.4163818359375004 +0.291 -0.183441162109375 -0.4163818359375004 +0.291125 -0.182403564453125 -0.4163818359375004 +0.29125 -0.182403564453125 -0.4163818359375004 +0.291375 -0.181365966796875 -0.4163818359375004 +0.2915 -0.181365966796875 -0.4163818359375004 +0.291625 -0.180267333984375 -0.4163818359375004 +0.29175 -0.179168701171875 -0.4163818359375004 +0.291875 -0.179168701171875 -0.4163818359375004 +0.292 -0.17803955078125 -0.4163818359375004 +0.292125 -0.17803955078125 -0.4163818359375004 +0.29225 -0.176910400390625 -0.4163818359375004 +0.292375 -0.175750732421875 -0.4163818359375004 +0.2925 -0.175750732421875 -0.4163818359375004 +0.292625 -0.174591064453125 -0.4163818359375004 +0.29275 -0.174591064453125 -0.4163818359375004 +0.292875 -0.173370361328125 -0.4163818359375004 +0.293 -0.172149658203125 -0.4163818359375004 +0.293125 -0.172149658203125 -0.4163818359375004 +0.29325 -0.170928955078125 -0.4163818359375004 +0.293375 -0.170928955078125 -0.4163818359375004 +0.2935 -0.169677734375 -0.4163818359375004 +0.293625 -0.16839599609375 -0.4163818359375004 +0.29375 -0.16839599609375 -0.4163818359375004 +0.293875 -0.1671142578125 -0.4163818359375004 +0.294 -0.1671142578125 -0.4163818359375004 +0.294125 -0.165802001953125 -0.4163818359375004 +0.29425 -0.16448974609375 -0.4163818359375004 +0.294375 -0.16448974609375 -0.4163818359375004 +0.2945 -0.16314697265625 -0.4163818359375004 +0.294625 -0.16314697265625 -0.4163818359375004 +0.29475 -0.161773681640625 -0.4163818359375004 +0.294875 -0.160400390625 -0.4163818359375004 +0.295 -0.160400390625 -0.4163818359375004 +0.295125 -0.15899658203125 -0.4163818359375004 +0.29525 -0.15899658203125 -0.4163818359375004 +0.295375 -0.157562255859375 -0.4163818359375004 +0.2955 -0.1561279296875 -0.4163818359375004 +0.295625 -0.1561279296875 -0.4163818359375004 +0.29575 -0.154693603515625 -0.4163818359375004 +0.295875 -0.154693603515625 -0.4163818359375004 +0.296 -0.153228759765625 -0.4163818359375004 +0.296125 -0.1517333984375 -0.4163818359375004 +0.29625 -0.1517333984375 -0.4163818359375004 +0.296375 -0.150238037109375 -0.4163818359375004 +0.2965 -0.150238037109375 -0.4163818359375004 +0.296625 -0.148712158203125 -0.4163818359375004 +0.29675 -0.147186279296875 -0.4163818359375004 +0.296875 -0.147186279296875 -0.4163818359375004 +0.297 -0.1456298828125 -0.4163818359375004 +0.297125 -0.1456298828125 -0.4163818359375004 +0.29725 -0.144073486328125 -0.4163818359375004 +0.297375 -0.142486572265625 -0.4163818359375004 +0.2975 -0.142486572265625 -0.4163818359375004 +0.297625 -0.140899658203125 -0.4163818359375004 +0.29775 -0.140899658203125 -0.4163818359375004 +0.297875 -0.1392822265625 -0.4163818359375004 +0.298 -0.137664794921875 -0.4163818359375004 +0.298125 -0.137664794921875 -0.4163818359375004 +0.29825 -0.136016845703125 -0.4163818359375004 +0.298375 -0.136016845703125 -0.4163818359375004 +0.2985 -0.134368896484375 -0.4163818359375004 +0.298625 -0.1326904296875 -0.4163818359375004 +0.29875 -0.1326904296875 -0.4163818359375004 +0.298875 -0.1309814453125 -0.4163818359375004 +0.299 -0.1309814453125 -0.4163818359375004 +0.299125 -0.129302978515625 -0.4163818359375004 +0.29925 -0.127593994140625 -0.4163818359375004 +0.299375 -0.127593994140625 -0.4163818359375004 +0.2995 -0.1258544921875 -0.4163818359375004 +0.299625 -0.1258544921875 -0.4163818359375004 +0.29975 -0.124114990234375 -0.4163818359375004 +0.299875 -0.122344970703125 -0.4163818359375004 +0.3 -0.122344970703125 -0.4163818359375004 +0.300125 -0.120574951171875 -0.4163818359375004 +0.30025 -0.120574951171875 -0.4163818359375004 +0.300375 -0.118804931640625 -0.4163818359375004 +0.3005 -0.11700439453125 -0.4163818359375004 +0.3006250000000001 -0.11700439453125 -0.4163818359375004 +0.30075 -0.11517333984375 -0.4163818359375004 +0.300875 -0.11517333984375 -0.4163818359375004 +0.301 -0.113372802734375 -0.4163818359375004 +0.301125 -0.111541748046875 -0.4163818359375004 +0.30125 -0.111541748046875 -0.4163818359375004 +0.301375 -0.10968017578125 -0.4163818359375004 +0.3015 -0.10968017578125 -0.4163818359375004 +0.301625 -0.107818603515625 -0.4163818359375004 +0.30175 -0.10595703125 -0.4163818359375004 +0.301875 -0.10595703125 -0.4163818359375004 +0.302 -0.10406494140625 -0.4163818359375004 +0.302125 -0.10406494140625 -0.4163818359375004 +0.30225 -0.1021728515625 -0.4163818359375004 +0.302375 -0.10028076171875 -0.4163818359375004 +0.3025 -0.10028076171875 -0.4163818359375004 +0.302625 -0.098358154296875 -0.4163818359375004 +0.30275 -0.098358154296875 -0.4163818359375004 +0.302875 -0.096435546875 -0.4163818359375004 +0.303 -0.094482421875 -0.4163818359375004 +0.303125 -0.094482421875 -0.4163818359375004 +0.30325 -0.092559814453125 -0.4163818359375004 +0.303375 -0.092559814453125 -0.4163818359375004 +0.3035 -0.090606689453125 -0.4163818359375004 +0.303625 -0.088623046875 -0.4163818359375004 +0.30375 -0.088623046875 -0.4163818359375004 +0.303875 -0.086639404296875 -0.4163818359375004 +0.304 -0.086639404296875 -0.4163818359375004 +0.304125 -0.08465576171875 -0.4163818359375004 +0.30425 -0.082672119140625 -0.4163818359375004 +0.304375 -0.082672119140625 -0.4163818359375004 +0.3045 -0.080657958984375 -0.4163818359375004 +0.304625 -0.080657958984375 -0.4163818359375004 +0.30475 -0.078643798828125 -0.4163818359375004 +0.304875 -0.076629638671875 -0.4163818359375004 +0.305 -0.076629638671875 -0.4163818359375004 +0.305125 -0.0745849609375 -0.4163818359375004 +0.30525 -0.0745849609375 -0.4163818359375004 +0.305375 -0.072540283203125 -0.4163818359375004 +0.3055 -0.07049560546875 -0.4163818359375004 +0.305625 -0.07049560546875 -0.4163818359375004 +0.30575 -0.068450927734375 -0.4163818359375004 +0.305875 -0.068450927734375 -0.4163818359375004 +0.306 -0.066375732421875 -0.4163818359375004 +0.306125 -0.064300537109375 -0.4163818359375004 +0.30625 -0.064300537109375 -0.4163818359375004 +0.306375 -0.062225341796875 -0.4163818359375004 +0.3065 -0.062225341796875 -0.4163818359375004 +0.306625 -0.060150146484375 -0.4163818359375004 +0.30675 -0.058074951171875 -0.4163818359375004 +0.306875 -0.058074951171875 -0.4163818359375004 +0.307 -0.05596923828125 -0.4163818359375004 +0.307125 -0.05596923828125 -0.4163818359375004 +0.30725 -0.053863525390625 -0.4163818359375004 +0.307375 -0.0517578125 -0.4163818359375004 +0.3075 -0.0517578125 -0.4163818359375004 +0.307625 -0.049652099609375 -0.4163818359375004 +0.30775 -0.049652099609375 -0.4163818359375004 +0.307875 -0.047515869140625 -0.4163818359375004 +0.308 -0.045379638671875 -0.4163818359375004 +0.308125 -0.045379638671875 -0.4163818359375004 +0.30825 -0.04327392578125 -0.4163818359375004 +0.308375 -0.04327392578125 -0.4163818359375004 +0.3085 -0.0411376953125 -0.4163818359375004 +0.308625 -0.03900146484375 -0.4163818359375004 +0.30875 -0.03900146484375 -0.4163818359375004 +0.308875 -0.036834716796875 -0.4163818359375004 +0.309 -0.036834716796875 -0.4163818359375004 +0.309125 -0.034698486328125 -0.4163818359375004 +0.30925 -0.03253173828125 -0.4163818359375004 +0.309375 -0.03253173828125 -0.4163818359375004 +0.3095 -0.0303955078125 -0.4163818359375004 +0.309625 -0.0303955078125 -0.4163818359375004 +0.30975 -0.028228759765625 -0.4163818359375004 +0.309875 -0.02606201171875 -0.4163818359375004 +0.31 -0.02606201171875 -0.4163818359375004 +0.310125 -0.02392578125 -0.4163818359375004 +0.31025 -0.02392578125 -0.4163818359375004 +0.310375 -0.021759033203125 -0.4163818359375004 +0.3105 -0.019561767578125 -0.4163818359375004 +0.310625 -0.019561767578125 -0.4163818359375004 +0.31075 -0.01739501953125 -0.4163818359375004 +0.310875 -0.01739501953125 -0.4163818359375004 +0.311 -0.015228271484375 -0.4163818359375004 +0.311125 -0.0130615234375 -0.4163818359375004 +0.31125 -0.0130615234375 -0.4163818359375004 +0.311375 -0.0108642578125 -0.4163818359375004 +0.3115 -0.0108642578125 -0.4163818359375004 +0.311625 -0.008697509765625 -0.4163818359375004 +0.31175 -0.00653076171875 -0.4163818359375004 +0.311875 -0.00653076171875 -0.4163818359375004 +0.312 -0.00433349609375 -0.4163818359375004 +0.312125 -0.00433349609375 -0.4163818359375004 +0.31225 -0.002166748046875 -0.4163818359375004 0.312375 0.0 -0.4163818359375004 0.3125 0.0 -0.4163818359375004 0.312625 0.002166748046875 -0.4163818359375004 @@ -2999,504 +2999,504 @@ 0.37475 0.00311279296875 -0.5948388671875 0.374875 0.0 -0.5948388671875 0.375 0.0 -0.5948388671875 -0.375125 -0.003143310546875 -0.5948388671875 -0.37525 -0.003143310546875 -0.5948388671875 -0.375375 -0.006256103515625 -0.5948388671875 -0.3755 -0.009368896484375 -0.5948388671875 -0.375625 -0.009368896484375 -0.5948388671875 -0.37575 -0.012481689453125 -0.5948388671875 -0.375875 -0.012481689453125 -0.5948388671875 -0.376 -0.01556396484375 -0.5948388671875 -0.376125 -0.0186767578125 -0.5948388671875 -0.37625 -0.0186767578125 -0.5948388671875 -0.376375 -0.02178955078125 -0.5948388671875 -0.3765 -0.02178955078125 -0.5948388671875 -0.376625 -0.02490234375 -0.5948388671875 -0.37675 -0.027984619140625 -0.5948388671875 -0.376875 -0.027984619140625 -0.5948388671875 -0.377 -0.031097412109375 -0.5948388671875 -0.377125 -0.031097412109375 -0.5948388671875 -0.37725 -0.034210205078125 -0.5948388671875 -0.377375 -0.03729248046875 -0.5948388671875 -0.3775 -0.03729248046875 -0.5948388671875 -0.377625 -0.040374755859375 -0.5948388671875 -0.37775 -0.040374755859375 -0.5948388671875 -0.377875 -0.04345703125 -0.5948388671875 -0.378 -0.046539306640625 -0.5948388671875 -0.378125 -0.046539306640625 -0.5948388671875 -0.37825 -0.04962158203125 -0.5948388671875 -0.378375 -0.04962158203125 -0.5948388671875 -0.3785 -0.05267333984375 -0.5948388671875 -0.378625 -0.05572509765625 -0.5948388671875 -0.3787500000000001 -0.05572509765625 -0.5948388671875 -0.378875 -0.058807373046875 -0.5948388671875 -0.379 -0.058807373046875 -0.5948388671875 -0.379125 -0.061859130859375 -0.5948388671875 -0.37925 -0.06488037109375 -0.5948388671875 -0.379375 -0.06488037109375 -0.5948388671875 -0.3795 -0.06793212890625 -0.5948388671875 -0.379625 -0.06793212890625 -0.5948388671875 -0.37975 -0.070953369140625 -0.5948388671875 -0.379875 -0.073974609375 -0.5948388671875 -0.38 -0.073974609375 -0.5948388671875 -0.380125 -0.076995849609375 -0.5948388671875 -0.38025 -0.076995849609375 -0.5948388671875 -0.380375 -0.079986572265625 -0.5948388671875 -0.3805 -0.082977294921875 -0.5948388671875 -0.380625 -0.082977294921875 -0.5948388671875 -0.38075 -0.085968017578125 -0.5948388671875 -0.380875 -0.085968017578125 -0.5948388671875 -0.381 -0.088958740234375 -0.5948388671875 -0.381125 -0.0919189453125 -0.5948388671875 -0.38125 -0.0919189453125 -0.5948388671875 -0.381375 -0.094879150390625 -0.5948388671875 -0.3815 -0.094879150390625 -0.5948388671875 -0.381625 -0.097808837890625 -0.5948388671875 -0.38175 -0.10076904296875 -0.5948388671875 -0.381875 -0.10076904296875 -0.5948388671875 -0.382 -0.103668212890625 -0.5948388671875 -0.382125 -0.103668212890625 -0.5948388671875 -0.38225 -0.106597900390625 -0.5948388671875 -0.382375 -0.1094970703125 -0.5948388671875 -0.3825 -0.1094970703125 -0.5948388671875 -0.382625 -0.112396240234375 -0.5948388671875 -0.3827500000000001 -0.112396240234375 -0.5948388671875 -0.382875 -0.115264892578125 -0.5948388671875 -0.383 -0.118133544921875 -0.5948388671875 -0.383125 -0.118133544921875 -0.5948388671875 -0.38325 -0.1209716796875 -0.5948388671875 -0.383375 -0.1209716796875 -0.5948388671875 -0.3835 -0.123809814453125 -0.5948388671875 -0.383625 -0.12664794921875 -0.5948388671875 -0.38375 -0.12664794921875 -0.5948388671875 -0.383875 -0.12945556640625 -0.5948388671875 -0.384 -0.10797119140625 -0.4961181640624994 -0.384125 -0.110321044921875 -0.4961181640624994 -0.38425 -0.11260986328125 -0.4961181640624994 -0.384375 -0.11260986328125 -0.4961181640624994 -0.3845 -0.11492919921875 -0.4961181640624994 -0.384625 -0.11492919921875 -0.4961181640624994 -0.38475 -0.117218017578125 -0.4961181640624994 -0.384875 -0.1195068359375 -0.4961181640624994 -0.385 -0.1195068359375 -0.4961181640624994 -0.385125 -0.121795654296875 -0.4961181640624994 -0.38525 -0.121795654296875 -0.4961181640624994 -0.385375 -0.124053955078125 -0.4961181640624994 -0.3855 -0.12628173828125 -0.4961181640624994 -0.385625 -0.12628173828125 -0.4961181640624994 -0.38575 -0.128509521484375 -0.4961181640624994 -0.385875 -0.128509521484375 -0.4961181640624994 -0.386 -0.1307373046875 -0.4961181640624994 -0.386125 -0.1329345703125 -0.4961181640624994 -0.38625 -0.1329345703125 -0.4961181640624994 -0.386375 -0.135101318359375 -0.4961181640624994 -0.3865 -0.135101318359375 -0.4961181640624994 -0.386625 -0.13726806640625 -0.4961181640624994 -0.38675 -0.139434814453125 -0.4961181640624994 -0.386875 -0.139434814453125 -0.4961181640624994 -0.387 -0.141571044921875 -0.4961181640624994 -0.387125 -0.141571044921875 -0.4961181640624994 -0.38725 -0.143707275390625 -0.4961181640624994 -0.387375 -0.14581298828125 -0.4961181640624994 -0.3875 -0.14581298828125 -0.4961181640624994 -0.387625 -0.147918701171875 -0.4961181640624994 -0.38775 -0.147918701171875 -0.4961181640624994 -0.387875 -0.149993896484375 -0.4961181640624994 -0.388 -0.15203857421875 -0.4961181640624994 -0.388125 -0.15203857421875 -0.4961181640624994 -0.38825 -0.154083251953125 -0.4961181640624994 -0.388375 -0.154083251953125 -0.4961181640624994 -0.3885 -0.1561279296875 -0.4961181640624994 -0.388625 -0.15814208984375 -0.4961181640624994 -0.38875 -0.15814208984375 -0.4961181640624994 -0.388875 -0.160125732421875 -0.4961181640624994 -0.389 -0.160125732421875 -0.4961181640624994 -0.389125 -0.162109375 -0.4961181640624994 -0.38925 -0.1640625 -0.4961181640624994 -0.389375 -0.1640625 -0.4961181640624994 -0.3895 -0.165985107421875 -0.4961181640624994 -0.389625 -0.165985107421875 -0.4961181640624994 -0.38975 -0.16790771484375 -0.4961181640624994 -0.389875 -0.169830322265625 -0.4961181640624994 -0.39 -0.169830322265625 -0.4961181640624994 -0.390125 -0.17169189453125 -0.4961181640624994 -0.39025 -0.17169189453125 -0.4961181640624994 -0.390375 -0.173553466796875 -0.4961181640624994 -0.3905 -0.1754150390625 -0.4961181640624994 -0.390625 -0.1754150390625 -0.4961181640624994 -0.39075 -0.17724609375 -0.4961181640624994 -0.390875 -0.17724609375 -0.4961181640624994 -0.391 -0.179046630859375 -0.4961181640624994 -0.391125 -0.18084716796875 -0.4961181640624994 -0.39125 -0.18084716796875 -0.4961181640624994 -0.391375 -0.1826171875 -0.4961181640624994 -0.3915 -0.1826171875 -0.4961181640624994 -0.391625 -0.184356689453125 -0.4961181640624994 -0.39175 -0.186065673828125 -0.4961181640624994 -0.391875 -0.186065673828125 -0.4961181640624994 -0.392 -0.187774658203125 -0.4961181640624994 -0.392125 -0.187774658203125 -0.4961181640624994 -0.39225 -0.189483642578125 -0.4961181640624994 -0.392375 -0.191131591796875 -0.4961181640624994 -0.3925 -0.191131591796875 -0.4961181640624994 -0.392625 -0.192779541015625 -0.4961181640624994 -0.39275 -0.192779541015625 -0.4961181640624994 -0.392875 -0.19439697265625 -0.4961181640624994 -0.393 -0.196014404296875 -0.4961181640624994 -0.393125 -0.196014404296875 -0.4961181640624994 -0.39325 -0.197601318359375 -0.4961181640624994 -0.393375 -0.197601318359375 -0.4961181640624994 -0.3935 -0.19915771484375 -0.4961181640624994 -0.393625 -0.20068359375 -0.4961181640624994 -0.39375 -0.20068359375 -0.4961181640624994 -0.393875 -0.20220947265625 -0.4961181640624994 -0.394 -0.20220947265625 -0.4961181640624994 -0.394125 -0.203704833984375 -0.4961181640624994 -0.39425 -0.205169677734375 -0.4961181640624994 -0.3943750000000001 -0.205169677734375 -0.4961181640624994 -0.3945 -0.206634521484375 -0.4961181640624994 -0.394625 -0.206634521484375 -0.4961181640624994 -0.39475 -0.208038330078125 -0.4961181640624994 -0.394875 -0.209442138671875 -0.4961181640624994 -0.395 -0.209442138671875 -0.4961181640624994 -0.395125 -0.210845947265625 -0.4961181640624994 -0.39525 -0.210845947265625 -0.4961181640624994 -0.395375 -0.212188720703125 -0.4961181640624994 -0.3955 -0.213531494140625 -0.4961181640624994 -0.395625 -0.213531494140625 -0.4961181640624994 -0.39575 -0.21484375 -0.4961181640624994 -0.395875 -0.21484375 -0.4961181640624994 -0.396 -0.21612548828125 -0.4961181640624994 -0.396125 -0.217376708984375 -0.4961181640624994 -0.39625 -0.217376708984375 -0.4961181640624994 -0.396375 -0.2186279296875 -0.4961181640624994 -0.3965 -0.2186279296875 -0.4961181640624994 -0.396625 -0.2198486328125 -0.4961181640624994 -0.39675 -0.221038818359375 -0.4961181640624994 -0.396875 -0.221038818359375 -0.4961181640624994 -0.397 -0.222198486328125 -0.4961181640624994 -0.397125 -0.222198486328125 -0.4961181640624994 -0.39725 -0.22332763671875 -0.4961181640624994 -0.397375 -0.224456787109375 -0.4961181640624994 -0.3975 -0.224456787109375 -0.4961181640624994 -0.397625 -0.225555419921875 -0.4961181640624994 -0.39775 -0.225555419921875 -0.4961181640624994 -0.397875 -0.22662353515625 -0.4961181640624994 -0.398 -0.2276611328125 -0.4961181640624994 -0.398125 -0.2276611328125 -0.4961181640624994 -0.39825 -0.228668212890625 -0.4961181640624994 -0.3983750000000001 -0.228668212890625 -0.4961181640624994 -0.3985 -0.22967529296875 -0.4961181640624994 -0.398625 -0.23065185546875 -0.4961181640624994 -0.39875 -0.23065185546875 -0.4961181640624994 -0.398875 -0.231597900390625 -0.4961181640624994 -0.399 -0.231597900390625 -0.4961181640624994 -0.399125 -0.232513427734375 -0.4961181640624994 -0.39925 -0.2333984375 -0.4961181640624994 -0.399375 -0.2333984375 -0.4961181640624994 -0.3995 -0.234283447265625 -0.4961181640624994 -0.399625 -0.234283447265625 -0.4961181640624994 -0.39975 -0.235107421875 -0.4961181640624994 -0.399875 -0.235931396484375 -0.4961181640624994 -0.4 -0.235931396484375 -0.4961181640624994 -0.400125 -0.236724853515625 -0.4961181640624994 -0.40025 -0.236724853515625 -0.4961181640624994 -0.400375 -0.23748779296875 -0.4961181640624994 -0.4005 -0.23822021484375 -0.4961181640624994 -0.400625 -0.23822021484375 -0.4961181640624994 -0.40075 -0.238922119140625 -0.4961181640624994 -0.400875 -0.238922119140625 -0.4961181640624994 -0.401 -0.2396240234375 -0.4961181640624994 -0.401125 -0.240264892578125 -0.4961181640624994 -0.40125 -0.240264892578125 -0.4961181640624994 -0.401375 -0.24090576171875 -0.4961181640624994 -0.4015000000000001 -0.24090576171875 -0.4961181640624994 -0.401625 -0.24151611328125 -0.4961181640624994 -0.40175 -0.242095947265625 -0.4961181640624994 -0.401875 -0.242095947265625 -0.4961181640624994 -0.402 -0.242645263671875 -0.4961181640624994 -0.402125 -0.242645263671875 -0.4961181640624994 -0.40225 -0.2431640625 -0.4961181640624994 -0.402375 -0.243682861328125 -0.4961181640624994 -0.4025 -0.243682861328125 -0.4961181640624994 -0.402625 -0.244140625 -0.4961181640624994 -0.40275 -0.244140625 -0.4961181640624994 -0.402875 -0.244598388671875 -0.4961181640624994 -0.403 -0.245025634765625 -0.4961181640624994 -0.403125 -0.245025634765625 -0.4961181640624994 -0.40325 -0.245391845703125 -0.4961181640624994 -0.403375 -0.245391845703125 -0.4961181640624994 -0.4035 -0.245758056640625 -0.4961181640624994 -0.403625 -0.246124267578125 -0.4961181640624994 -0.40375 -0.246124267578125 -0.4961181640624994 -0.403875 -0.246429443359375 -0.4961181640624994 -0.404 -0.246429443359375 -0.4961181640624994 -0.404125 -0.2467041015625 -0.4961181640624994 -0.40425 -0.246978759765625 -0.4961181640624994 -0.404375 -0.246978759765625 -0.4961181640624994 -0.4045 -0.2471923828125 -0.4961181640624994 -0.4046250000000001 -0.2471923828125 -0.4961181640624994 -0.40475 -0.247406005859375 -0.4961181640624994 -0.404875 -0.247589111328125 -0.4961181640624994 -0.4050000000000001 -0.247589111328125 -0.4961181640624994 -0.405125 -0.24774169921875 -0.4961181640624994 -0.40525 -0.24774169921875 -0.4961181640624994 -0.405375 -0.24786376953125 -0.4961181640624994 -0.4055000000000001 -0.247955322265625 -0.4961181640624994 -0.405625 -0.247955322265625 -0.4961181640624994 -0.40575 -0.248016357421875 -0.4961181640624994 -0.405875 -0.248016357421875 -0.4961181640624994 -0.406 -0.248046875 -0.4961181640624994 -0.406125 -0.248077392578125 -0.4961181640624994 -0.40625 -0.248077392578125 -0.4961181640624994 -0.406375 -0.248046875 -0.4961181640624994 -0.4065 -0.248046875 -0.4961181640624994 -0.406625 -0.248016357421875 -0.4961181640624994 -0.40675 -0.247955322265625 -0.4961181640624994 -0.406875 -0.247955322265625 -0.4961181640624994 -0.407 -0.24786376953125 -0.4961181640624994 -0.407125 -0.24786376953125 -0.4961181640624994 -0.40725 -0.24774169921875 -0.4961181640624994 -0.407375 -0.247589111328125 -0.4961181640624994 -0.4075 -0.247589111328125 -0.4961181640624994 -0.407625 -0.247406005859375 -0.4961181640624994 -0.40775 -0.247406005859375 -0.4961181640624994 -0.4078749999999999 -0.2471923828125 -0.4961181640624994 -0.408 -0.246978759765625 -0.4961181640624994 -0.408125 -0.246978759765625 -0.4961181640624994 -0.40825 -0.2467041015625 -0.4961181640624994 -0.408375 -0.2467041015625 -0.4961181640624994 -0.4085 -0.246429443359375 -0.4961181640624994 -0.408625 -0.246124267578125 -0.4961181640624994 -0.40875 -0.246124267578125 -0.4961181640624994 -0.408875 -0.245758056640625 -0.4961181640624994 -0.409 -0.245758056640625 -0.4961181640624994 -0.409125 -0.245391845703125 -0.4961181640624994 -0.40925 -0.245025634765625 -0.4961181640624994 -0.409375 -0.245025634765625 -0.4961181640624994 -0.4095000000000001 -0.244598388671875 -0.4961181640624994 -0.409625 -0.244598388671875 -0.4961181640624994 -0.40975 -0.244140625 -0.4961181640624994 -0.409875 -0.243682861328125 -0.4961181640624994 -0.4100000000000001 -0.243682861328125 -0.4961181640624994 -0.410125 -0.2431640625 -0.4961181640624994 -0.41025 -0.2431640625 -0.4961181640624994 -0.410375 -0.242645263671875 -0.4961181640624994 -0.4105 -0.242095947265625 -0.4961181640624994 -0.410625 -0.242095947265625 -0.4961181640624994 -0.41075 -0.24151611328125 -0.4961181640624994 -0.410875 -0.24151611328125 -0.4961181640624994 -0.411 -0.24090576171875 -0.4961181640624994 -0.411125 -0.240264892578125 -0.4961181640624994 -0.41125 -0.240264892578125 -0.4961181640624994 -0.411375 -0.2396240234375 -0.4961181640624994 -0.4115 -0.2396240234375 -0.4961181640624994 -0.411625 -0.238922119140625 -0.4961181640624994 -0.41175 -0.23822021484375 -0.4961181640624994 -0.411875 -0.23822021484375 -0.4961181640624994 -0.412 -0.23748779296875 -0.4961181640624994 -0.412125 -0.23748779296875 -0.4961181640624994 -0.41225 -0.236724853515625 -0.4961181640624994 -0.412375 -0.235931396484375 -0.4961181640624994 -0.4125 -0.235931396484375 -0.4961181640624994 -0.4126250000000001 -0.235107421875 -0.4961181640624994 -0.41275 -0.235107421875 -0.4961181640624994 -0.412875 -0.234283447265625 -0.4961181640624994 -0.4130000000000001 -0.2333984375 -0.4961181640624994 -0.4131250000000001 -0.2333984375 -0.4961181640624994 -0.41325 -0.232513427734375 -0.4961181640624994 -0.413375 -0.232513427734375 -0.4961181640624994 -0.4135000000000001 -0.231597900390625 -0.4961181640624994 -0.413625 -0.23065185546875 -0.4961181640624994 -0.41375 -0.23065185546875 -0.4961181640624994 -0.413875 -0.22967529296875 -0.4961181640624994 -0.4140000000000001 -0.22967529296875 -0.4961181640624994 -0.414125 -0.228668212890625 -0.4961181640624994 -0.41425 -0.2276611328125 -0.4961181640624994 -0.414375 -0.2276611328125 -0.4961181640624994 -0.4145 -0.22662353515625 -0.4961181640624994 -0.414625 -0.22662353515625 -0.4961181640624994 -0.41475 -0.225555419921875 -0.4961181640624994 -0.414875 -0.224456787109375 -0.4961181640624994 -0.415 -0.224456787109375 -0.4961181640624994 -0.415125 -0.22332763671875 -0.4961181640624994 -0.41525 -0.22332763671875 -0.4961181640624994 -0.415375 -0.222198486328125 -0.4961181640624994 -0.4155 -0.221038818359375 -0.4961181640624994 -0.415625 -0.221038818359375 -0.4961181640624994 -0.41575 -0.2198486328125 -0.4961181640624994 -0.415875 -0.2198486328125 -0.4961181640624994 -0.416 -0.12615966796875 -0.2863085937499983 -0.416125 -0.125457763671875 -0.2863085937499983 -0.41625 -0.125457763671875 -0.2863085937499983 -0.416375 -0.124725341796875 -0.2863085937499983 -0.4165 -0.124725341796875 -0.2863085937499983 -0.416625 -0.123992919921875 -0.2863085937499983 -0.41675 -0.12322998046875 -0.2863085937499983 -0.416875 -0.12322998046875 -0.2863085937499983 -0.417 -0.122467041015625 -0.2863085937499983 -0.4171250000000001 -0.122467041015625 -0.2863085937499983 -0.41725 -0.121673583984375 -0.2863085937499983 -0.417375 -0.120880126953125 -0.2863085937499983 -0.4175 -0.120880126953125 -0.2863085937499983 -0.417625 -0.12005615234375 -0.2863085937499983 -0.41775 -0.12005615234375 -0.2863085937499983 -0.417875 -0.1192626953125 -0.2863085937499983 -0.418 -0.118408203125 -0.2863085937499983 -0.418125 -0.118408203125 -0.2863085937499983 -0.41825 -0.1175537109375 -0.2863085937499983 -0.418375 -0.1175537109375 -0.2863085937499983 -0.4185 -0.11669921875 -0.2863085937499983 -0.418625 -0.115814208984375 -0.2863085937499983 -0.41875 -0.115814208984375 -0.2863085937499983 -0.418875 -0.11492919921875 -0.2863085937499983 -0.419 -0.11492919921875 -0.2863085937499983 -0.419125 -0.114044189453125 -0.2863085937499983 -0.41925 -0.113128662109375 -0.2863085937499983 -0.419375 -0.113128662109375 -0.2863085937499983 -0.4195 -0.112213134765625 -0.2863085937499983 -0.419625 -0.112213134765625 -0.2863085937499983 -0.41975 -0.11126708984375 -0.2863085937499983 -0.419875 -0.110321044921875 -0.2863085937499983 -0.42 -0.110321044921875 -0.2863085937499983 -0.420125 -0.109344482421875 -0.2863085937499983 -0.4202500000000001 -0.109344482421875 -0.2863085937499983 -0.420375 -0.108367919921875 -0.2863085937499983 -0.4205 -0.107391357421875 -0.2863085937499983 -0.4206250000000001 -0.107391357421875 -0.2863085937499983 -0.42075 -0.10638427734375 -0.2863085937499983 -0.420875 -0.10638427734375 -0.2863085937499983 -0.421 -0.105377197265625 -0.2863085937499983 -0.4211250000000001 -0.1043701171875 -0.2863085937499983 -0.42125 -0.1043701171875 -0.2863085937499983 -0.421375 -0.10333251953125 -0.2863085937499983 -0.4215 -0.10333251953125 -0.2863085937499983 -0.421625 -0.102294921875 -0.2863085937499983 -0.42175 -0.101226806640625 -0.2863085937499983 -0.421875 -0.101226806640625 -0.2863085937499983 -0.422 -0.10015869140625 -0.2863085937499983 -0.422125 -0.10015869140625 -0.2863085937499983 -0.42225 -0.099090576171875 -0.2863085937499983 -0.422375 -0.0980224609375 -0.2863085937499983 -0.4225 -0.0980224609375 -0.2863085937499983 -0.422625 -0.096923828125 -0.2863085937499983 -0.42275 -0.096923828125 -0.2863085937499983 -0.422875 -0.095794677734375 -0.2863085937499983 -0.423 -0.094696044921875 -0.2863085937499983 -0.423125 -0.094696044921875 -0.2863085937499983 -0.42325 -0.09356689453125 -0.2863085937499983 -0.423375 -0.09356689453125 -0.2863085937499983 -0.4234999999999999 -0.0924072265625 -0.2863085937499983 -0.423625 -0.09124755859375 -0.2863085937499983 -0.42375 -0.09124755859375 -0.2863085937499983 -0.423875 -0.090087890625 -0.2863085937499983 -0.424 -0.090087890625 -0.2863085937499983 -0.424125 -0.08892822265625 -0.2863085937499983 -0.42425 -0.0877685546875 -0.2863085937499983 -0.424375 -0.0877685546875 -0.2863085937499983 -0.4245 -0.0865478515625 -0.2863085937499983 -0.424625 -0.0865478515625 -0.2863085937499983 -0.42475 -0.085357666015625 -0.2863085937499983 -0.424875 -0.08416748046875 -0.2863085937499983 -0.425 -0.08416748046875 -0.2863085937499983 -0.4251250000000001 -0.08294677734375 -0.2863085937499983 -0.42525 -0.08294677734375 -0.2863085937499983 -0.425375 -0.08172607421875 -0.2863085937499983 -0.4255 -0.080474853515625 -0.2863085937499983 -0.4256250000000001 -0.080474853515625 -0.2863085937499983 -0.42575 -0.0792236328125 -0.2863085937499983 -0.425875 -0.0792236328125 -0.2863085937499983 -0.426 -0.077972412109375 -0.2863085937499983 -0.426125 -0.07672119140625 -0.2863085937499983 -0.42625 -0.07672119140625 -0.2863085937499983 -0.426375 -0.075439453125 -0.2863085937499983 -0.4265 -0.075439453125 -0.2863085937499983 -0.426625 -0.07415771484375 -0.2863085937499983 -0.42675 -0.0728759765625 -0.2863085937499983 -0.426875 -0.0728759765625 -0.2863085937499983 -0.427 -0.07159423828125 -0.2863085937499983 -0.427125 -0.07159423828125 -0.2863085937499983 -0.42725 -0.070281982421875 -0.2863085937499983 -0.427375 -0.0689697265625 -0.2863085937499983 -0.4275 -0.0689697265625 -0.2863085937499983 -0.427625 -0.067657470703125 -0.2863085937499983 -0.42775 -0.067657470703125 -0.2863085937499983 -0.427875 -0.06634521484375 -0.2863085937499983 -0.428 -0.06500244140625 -0.2863085937499983 -0.428125 -0.06500244140625 -0.2863085937499983 -0.4282500000000001 -0.06365966796875 -0.2863085937499983 -0.428375 -0.06365966796875 -0.2863085937499983 -0.4285 -0.06231689453125 -0.2863085937499983 -0.4286250000000001 -0.06097412109375 -0.2863085937499983 -0.4287500000000001 -0.06097412109375 -0.2863085937499983 -0.428875 -0.059600830078125 -0.2863085937499983 -0.429 -0.059600830078125 -0.2863085937499983 -0.4291250000000001 -0.0582275390625 -0.2863085937499983 -0.42925 -0.056854248046875 -0.2863085937499983 -0.429375 -0.056854248046875 -0.2863085937499983 -0.4295 -0.05548095703125 -0.2863085937499983 -0.4296250000000001 -0.05548095703125 -0.2863085937499983 -0.42975 -0.054107666015625 -0.2863085937499983 -0.429875 -0.052703857421875 -0.2863085937499983 -0.43 -0.052703857421875 -0.2863085937499983 -0.430125 -0.051300048828125 -0.2863085937499983 -0.43025 -0.051300048828125 -0.2863085937499983 -0.430375 -0.0499267578125 -0.2863085937499983 -0.4305 -0.048492431640625 -0.2863085937499983 -0.430625 -0.048492431640625 -0.2863085937499983 -0.43075 -0.047088623046875 -0.2863085937499983 -0.430875 -0.047088623046875 -0.2863085937499983 -0.431 -0.045684814453125 -0.2863085937499983 -0.431125 -0.04425048828125 -0.2863085937499983 -0.43125 -0.04425048828125 -0.2863085937499983 -0.431375 -0.042816162109375 -0.2863085937499983 -0.4315 -0.042816162109375 -0.2863085937499983 -0.431625 -0.0413818359375 -0.2863085937499983 -0.43175 -0.039947509765625 -0.2863085937499983 -0.431875 -0.039947509765625 -0.2863085937499983 -0.432 -0.03851318359375 -0.2863085937499983 -0.432125 -0.03851318359375 -0.2863085937499983 -0.43225 -0.03704833984375 -0.2863085937499983 -0.432375 -0.035614013671875 -0.2863085937499983 -0.4325 -0.035614013671875 -0.2863085937499983 -0.432625 -0.034149169921875 -0.2863085937499983 -0.4327500000000001 -0.034149169921875 -0.2863085937499983 -0.432875 -0.03271484375 -0.2863085937499983 -0.433 -0.03125 -0.2863085937499983 -0.433125 -0.03125 -0.2863085937499983 -0.43325 -0.02978515625 -0.2863085937499983 -0.433375 -0.02978515625 -0.2863085937499983 -0.4335 -0.0283203125 -0.2863085937499983 -0.433625 -0.026824951171875 -0.2863085937499983 -0.43375 -0.026824951171875 -0.2863085937499983 -0.433875 -0.025360107421875 -0.2863085937499983 -0.434 -0.025360107421875 -0.2863085937499983 -0.434125 -0.023895263671875 -0.2863085937499983 -0.43425 -0.02239990234375 -0.2863085937499983 -0.434375 -0.02239990234375 -0.2863085937499983 -0.4345 -0.02093505859375 -0.2863085937499983 -0.434625 -0.02093505859375 -0.2863085937499983 -0.43475 -0.019439697265625 -0.2863085937499983 -0.434875 -0.0179443359375 -0.2863085937499983 -0.435 -0.0179443359375 -0.2863085937499983 -0.435125 -0.0164794921875 -0.2863085937499983 -0.43525 -0.0164794921875 -0.2863085937499983 -0.435375 -0.014984130859375 -0.2863085937499983 -0.4355 -0.01348876953125 -0.2863085937499983 -0.435625 -0.01348876953125 -0.2863085937499983 -0.43575 -0.011993408203125 -0.2863085937499983 -0.4358750000000001 -0.011993408203125 -0.2863085937499983 -0.436 -0.010498046875 -0.2863085937499983 -0.436125 -0.009002685546875 -0.2863085937499983 -0.4362500000000001 -0.009002685546875 -0.2863085937499983 -0.436375 -0.00750732421875 -0.2863085937499983 -0.4365 -0.00750732421875 -0.2863085937499983 -0.436625 -0.006011962890625 -0.2863085937499983 -0.4367500000000001 -0.0045166015625 -0.2863085937499983 -0.436875 -0.0045166015625 -0.2863085937499983 -0.437 -0.003021240234375 -0.2863085937499983 -0.437125 -0.003021240234375 -0.2863085937499983 -0.43725 -0.00152587890625 -0.2863085937499983 +0.375125 -0.00311279296875 -0.5948388671875 +0.37525 -0.00311279296875 -0.5948388671875 +0.375375 -0.0062255859375 -0.5948388671875 +0.3755 -0.00933837890625 -0.5948388671875 +0.375625 -0.00933837890625 -0.5948388671875 +0.37575 -0.012451171875 -0.5948388671875 +0.375875 -0.012451171875 -0.5948388671875 +0.376 -0.015533447265625 -0.5948388671875 +0.376125 -0.018646240234375 -0.5948388671875 +0.37625 -0.018646240234375 -0.5948388671875 +0.376375 -0.021759033203125 -0.5948388671875 +0.3765 -0.021759033203125 -0.5948388671875 +0.376625 -0.024871826171875 -0.5948388671875 +0.37675 -0.0279541015625 -0.5948388671875 +0.376875 -0.0279541015625 -0.5948388671875 +0.377 -0.03106689453125 -0.5948388671875 +0.377125 -0.03106689453125 -0.5948388671875 +0.37725 -0.0341796875 -0.5948388671875 +0.377375 -0.037261962890625 -0.5948388671875 +0.3775 -0.037261962890625 -0.5948388671875 +0.377625 -0.04034423828125 -0.5948388671875 +0.37775 -0.04034423828125 -0.5948388671875 +0.377875 -0.043426513671875 -0.5948388671875 +0.378 -0.0465087890625 -0.5948388671875 +0.378125 -0.0465087890625 -0.5948388671875 +0.37825 -0.049591064453125 -0.5948388671875 +0.378375 -0.049591064453125 -0.5948388671875 +0.3785 -0.052642822265625 -0.5948388671875 +0.378625 -0.055694580078125 -0.5948388671875 +0.3787500000000001 -0.055694580078125 -0.5948388671875 +0.378875 -0.05877685546875 -0.5948388671875 +0.379 -0.05877685546875 -0.5948388671875 +0.379125 -0.06182861328125 -0.5948388671875 +0.37925 -0.064849853515625 -0.5948388671875 +0.379375 -0.064849853515625 -0.5948388671875 +0.3795 -0.067901611328125 -0.5948388671875 +0.379625 -0.067901611328125 -0.5948388671875 +0.37975 -0.0709228515625 -0.5948388671875 +0.379875 -0.073944091796875 -0.5948388671875 +0.38 -0.073944091796875 -0.5948388671875 +0.380125 -0.07696533203125 -0.5948388671875 +0.38025 -0.07696533203125 -0.5948388671875 +0.380375 -0.0799560546875 -0.5948388671875 +0.3805 -0.08294677734375 -0.5948388671875 +0.380625 -0.08294677734375 -0.5948388671875 +0.38075 -0.0859375 -0.5948388671875 +0.380875 -0.0859375 -0.5948388671875 +0.381 -0.08892822265625 -0.5948388671875 +0.381125 -0.091888427734375 -0.5948388671875 +0.38125 -0.091888427734375 -0.5948388671875 +0.381375 -0.0948486328125 -0.5948388671875 +0.3815 -0.0948486328125 -0.5948388671875 +0.381625 -0.0977783203125 -0.5948388671875 +0.38175 -0.100738525390625 -0.5948388671875 +0.381875 -0.100738525390625 -0.5948388671875 +0.382 -0.1036376953125 -0.5948388671875 +0.382125 -0.1036376953125 -0.5948388671875 +0.38225 -0.1065673828125 -0.5948388671875 +0.382375 -0.109466552734375 -0.5948388671875 +0.3825 -0.109466552734375 -0.5948388671875 +0.382625 -0.11236572265625 -0.5948388671875 +0.3827500000000001 -0.11236572265625 -0.5948388671875 +0.382875 -0.115234375 -0.5948388671875 +0.383 -0.11810302734375 -0.5948388671875 +0.383125 -0.11810302734375 -0.5948388671875 +0.38325 -0.120941162109375 -0.5948388671875 +0.383375 -0.120941162109375 -0.5948388671875 +0.3835 -0.123779296875 -0.5948388671875 +0.383625 -0.126617431640625 -0.5948388671875 +0.38375 -0.126617431640625 -0.5948388671875 +0.383875 -0.129425048828125 -0.5948388671875 +0.384 -0.107940673828125 -0.4961181640624994 +0.384125 -0.11029052734375 -0.4961181640624994 +0.38425 -0.112579345703125 -0.4961181640624994 +0.384375 -0.112579345703125 -0.4961181640624994 +0.3845 -0.114898681640625 -0.4961181640624994 +0.384625 -0.114898681640625 -0.4961181640624994 +0.38475 -0.1171875 -0.4961181640624994 +0.384875 -0.119476318359375 -0.4961181640624994 +0.385 -0.119476318359375 -0.4961181640624994 +0.385125 -0.12176513671875 -0.4961181640624994 +0.38525 -0.12176513671875 -0.4961181640624994 +0.385375 -0.1240234375 -0.4961181640624994 +0.3855 -0.126251220703125 -0.4961181640624994 +0.385625 -0.126251220703125 -0.4961181640624994 +0.38575 -0.12847900390625 -0.4961181640624994 +0.385875 -0.12847900390625 -0.4961181640624994 +0.386 -0.130706787109375 -0.4961181640624994 +0.386125 -0.132904052734375 -0.4961181640624994 +0.38625 -0.132904052734375 -0.4961181640624994 +0.386375 -0.13507080078125 -0.4961181640624994 +0.3865 -0.13507080078125 -0.4961181640624994 +0.386625 -0.137237548828125 -0.4961181640624994 +0.38675 -0.139404296875 -0.4961181640624994 +0.386875 -0.139404296875 -0.4961181640624994 +0.387 -0.14154052734375 -0.4961181640624994 +0.387125 -0.14154052734375 -0.4961181640624994 +0.38725 -0.1436767578125 -0.4961181640624994 +0.387375 -0.145782470703125 -0.4961181640624994 +0.3875 -0.145782470703125 -0.4961181640624994 +0.387625 -0.14788818359375 -0.4961181640624994 +0.38775 -0.14788818359375 -0.4961181640624994 +0.387875 -0.14996337890625 -0.4961181640624994 +0.388 -0.152008056640625 -0.4961181640624994 +0.388125 -0.152008056640625 -0.4961181640624994 +0.38825 -0.154052734375 -0.4961181640624994 +0.388375 -0.154052734375 -0.4961181640624994 +0.3885 -0.156097412109375 -0.4961181640624994 +0.388625 -0.158111572265625 -0.4961181640624994 +0.38875 -0.158111572265625 -0.4961181640624994 +0.388875 -0.16009521484375 -0.4961181640624994 +0.389 -0.16009521484375 -0.4961181640624994 +0.389125 -0.162078857421875 -0.4961181640624994 +0.38925 -0.164031982421875 -0.4961181640624994 +0.389375 -0.164031982421875 -0.4961181640624994 +0.3895 -0.16595458984375 -0.4961181640624994 +0.389625 -0.16595458984375 -0.4961181640624994 +0.38975 -0.167877197265625 -0.4961181640624994 +0.389875 -0.1697998046875 -0.4961181640624994 +0.39 -0.1697998046875 -0.4961181640624994 +0.390125 -0.171661376953125 -0.4961181640624994 +0.39025 -0.171661376953125 -0.4961181640624994 +0.390375 -0.17352294921875 -0.4961181640624994 +0.3905 -0.175384521484375 -0.4961181640624994 +0.390625 -0.175384521484375 -0.4961181640624994 +0.39075 -0.177215576171875 -0.4961181640624994 +0.390875 -0.177215576171875 -0.4961181640624994 +0.391 -0.17901611328125 -0.4961181640624994 +0.391125 -0.180816650390625 -0.4961181640624994 +0.39125 -0.180816650390625 -0.4961181640624994 +0.391375 -0.182586669921875 -0.4961181640624994 +0.3915 -0.182586669921875 -0.4961181640624994 +0.391625 -0.184326171875 -0.4961181640624994 +0.39175 -0.18603515625 -0.4961181640624994 +0.391875 -0.18603515625 -0.4961181640624994 +0.392 -0.187744140625 -0.4961181640624994 +0.392125 -0.187744140625 -0.4961181640624994 +0.39225 -0.189453125 -0.4961181640624994 +0.392375 -0.19110107421875 -0.4961181640624994 +0.3925 -0.19110107421875 -0.4961181640624994 +0.392625 -0.1927490234375 -0.4961181640624994 +0.39275 -0.1927490234375 -0.4961181640624994 +0.392875 -0.194366455078125 -0.4961181640624994 +0.393 -0.19598388671875 -0.4961181640624994 +0.393125 -0.19598388671875 -0.4961181640624994 +0.39325 -0.19757080078125 -0.4961181640624994 +0.393375 -0.19757080078125 -0.4961181640624994 +0.3935 -0.199127197265625 -0.4961181640624994 +0.393625 -0.200653076171875 -0.4961181640624994 +0.39375 -0.200653076171875 -0.4961181640624994 +0.393875 -0.202178955078125 -0.4961181640624994 +0.394 -0.202178955078125 -0.4961181640624994 +0.394125 -0.20367431640625 -0.4961181640624994 +0.39425 -0.20513916015625 -0.4961181640624994 +0.3943750000000001 -0.20513916015625 -0.4961181640624994 +0.3945 -0.20660400390625 -0.4961181640624994 +0.394625 -0.20660400390625 -0.4961181640624994 +0.39475 -0.2080078125 -0.4961181640624994 +0.394875 -0.20941162109375 -0.4961181640624994 +0.395 -0.20941162109375 -0.4961181640624994 +0.395125 -0.2108154296875 -0.4961181640624994 +0.39525 -0.2108154296875 -0.4961181640624994 +0.395375 -0.212158203125 -0.4961181640624994 +0.3955 -0.2135009765625 -0.4961181640624994 +0.395625 -0.2135009765625 -0.4961181640624994 +0.39575 -0.214813232421875 -0.4961181640624994 +0.395875 -0.214813232421875 -0.4961181640624994 +0.396 -0.216094970703125 -0.4961181640624994 +0.396125 -0.21734619140625 -0.4961181640624994 +0.39625 -0.21734619140625 -0.4961181640624994 +0.396375 -0.218597412109375 -0.4961181640624994 +0.3965 -0.218597412109375 -0.4961181640624994 +0.396625 -0.219818115234375 -0.4961181640624994 +0.39675 -0.22100830078125 -0.4961181640624994 +0.396875 -0.22100830078125 -0.4961181640624994 +0.397 -0.22216796875 -0.4961181640624994 +0.397125 -0.22216796875 -0.4961181640624994 +0.39725 -0.223297119140625 -0.4961181640624994 +0.397375 -0.22442626953125 -0.4961181640624994 +0.3975 -0.22442626953125 -0.4961181640624994 +0.397625 -0.22552490234375 -0.4961181640624994 +0.39775 -0.22552490234375 -0.4961181640624994 +0.397875 -0.226593017578125 -0.4961181640624994 +0.398 -0.227630615234375 -0.4961181640624994 +0.398125 -0.227630615234375 -0.4961181640624994 +0.39825 -0.2286376953125 -0.4961181640624994 +0.3983750000000001 -0.2286376953125 -0.4961181640624994 +0.3985 -0.229644775390625 -0.4961181640624994 +0.398625 -0.230621337890625 -0.4961181640624994 +0.39875 -0.230621337890625 -0.4961181640624994 +0.398875 -0.2315673828125 -0.4961181640624994 +0.399 -0.2315673828125 -0.4961181640624994 +0.399125 -0.23248291015625 -0.4961181640624994 +0.39925 -0.233367919921875 -0.4961181640624994 +0.399375 -0.233367919921875 -0.4961181640624994 +0.3995 -0.2342529296875 -0.4961181640624994 +0.399625 -0.2342529296875 -0.4961181640624994 +0.39975 -0.235076904296875 -0.4961181640624994 +0.399875 -0.23590087890625 -0.4961181640624994 +0.4 -0.23590087890625 -0.4961181640624994 +0.400125 -0.2366943359375 -0.4961181640624994 +0.40025 -0.2366943359375 -0.4961181640624994 +0.400375 -0.237457275390625 -0.4961181640624994 +0.4005 -0.238189697265625 -0.4961181640624994 +0.400625 -0.238189697265625 -0.4961181640624994 +0.40075 -0.2388916015625 -0.4961181640624994 +0.400875 -0.2388916015625 -0.4961181640624994 +0.401 -0.239593505859375 -0.4961181640624994 +0.401125 -0.240234375 -0.4961181640624994 +0.40125 -0.240234375 -0.4961181640624994 +0.401375 -0.240875244140625 -0.4961181640624994 +0.4015000000000001 -0.240875244140625 -0.4961181640624994 +0.401625 -0.241485595703125 -0.4961181640624994 +0.40175 -0.2420654296875 -0.4961181640624994 +0.401875 -0.2420654296875 -0.4961181640624994 +0.402 -0.24261474609375 -0.4961181640624994 +0.402125 -0.24261474609375 -0.4961181640624994 +0.40225 -0.243133544921875 -0.4961181640624994 +0.402375 -0.24365234375 -0.4961181640624994 +0.4025 -0.24365234375 -0.4961181640624994 +0.402625 -0.244110107421875 -0.4961181640624994 +0.40275 -0.244110107421875 -0.4961181640624994 +0.402875 -0.24456787109375 -0.4961181640624994 +0.403 -0.2449951171875 -0.4961181640624994 +0.403125 -0.2449951171875 -0.4961181640624994 +0.40325 -0.245361328125 -0.4961181640624994 +0.403375 -0.245361328125 -0.4961181640624994 +0.4035 -0.2457275390625 -0.4961181640624994 +0.403625 -0.24609375 -0.4961181640624994 +0.40375 -0.24609375 -0.4961181640624994 +0.403875 -0.24639892578125 -0.4961181640624994 +0.404 -0.24639892578125 -0.4961181640624994 +0.404125 -0.246673583984375 -0.4961181640624994 +0.40425 -0.2469482421875 -0.4961181640624994 +0.404375 -0.2469482421875 -0.4961181640624994 +0.4045 -0.247161865234375 -0.4961181640624994 +0.4046250000000001 -0.247161865234375 -0.4961181640624994 +0.40475 -0.24737548828125 -0.4961181640624994 +0.404875 -0.24755859375 -0.4961181640624994 +0.4050000000000001 -0.24755859375 -0.4961181640624994 +0.405125 -0.247711181640625 -0.4961181640624994 +0.40525 -0.247711181640625 -0.4961181640624994 +0.405375 -0.247833251953125 -0.4961181640624994 +0.4055000000000001 -0.2479248046875 -0.4961181640624994 +0.405625 -0.2479248046875 -0.4961181640624994 +0.40575 -0.24798583984375 -0.4961181640624994 +0.405875 -0.24798583984375 -0.4961181640624994 +0.406 -0.248016357421875 -0.4961181640624994 +0.406125 -0.248046875 -0.4961181640624994 +0.40625 -0.248046875 -0.4961181640624994 +0.406375 -0.248016357421875 -0.4961181640624994 +0.4065 -0.248016357421875 -0.4961181640624994 +0.406625 -0.24798583984375 -0.4961181640624994 +0.40675 -0.2479248046875 -0.4961181640624994 +0.406875 -0.2479248046875 -0.4961181640624994 +0.407 -0.247833251953125 -0.4961181640624994 +0.407125 -0.247833251953125 -0.4961181640624994 +0.40725 -0.247711181640625 -0.4961181640624994 +0.407375 -0.24755859375 -0.4961181640624994 +0.4075 -0.24755859375 -0.4961181640624994 +0.407625 -0.24737548828125 -0.4961181640624994 +0.40775 -0.24737548828125 -0.4961181640624994 +0.4078749999999999 -0.247161865234375 -0.4961181640624994 +0.408 -0.2469482421875 -0.4961181640624994 +0.408125 -0.2469482421875 -0.4961181640624994 +0.40825 -0.246673583984375 -0.4961181640624994 +0.408375 -0.246673583984375 -0.4961181640624994 +0.4085 -0.24639892578125 -0.4961181640624994 +0.408625 -0.24609375 -0.4961181640624994 +0.40875 -0.24609375 -0.4961181640624994 +0.408875 -0.2457275390625 -0.4961181640624994 +0.409 -0.2457275390625 -0.4961181640624994 +0.409125 -0.245361328125 -0.4961181640624994 +0.40925 -0.2449951171875 -0.4961181640624994 +0.409375 -0.2449951171875 -0.4961181640624994 +0.4095000000000001 -0.24456787109375 -0.4961181640624994 +0.409625 -0.24456787109375 -0.4961181640624994 +0.40975 -0.244110107421875 -0.4961181640624994 +0.409875 -0.24365234375 -0.4961181640624994 +0.4100000000000001 -0.24365234375 -0.4961181640624994 +0.410125 -0.243133544921875 -0.4961181640624994 +0.41025 -0.243133544921875 -0.4961181640624994 +0.410375 -0.24261474609375 -0.4961181640624994 +0.4105 -0.2420654296875 -0.4961181640624994 +0.410625 -0.2420654296875 -0.4961181640624994 +0.41075 -0.241485595703125 -0.4961181640624994 +0.410875 -0.241485595703125 -0.4961181640624994 +0.411 -0.240875244140625 -0.4961181640624994 +0.411125 -0.240234375 -0.4961181640624994 +0.41125 -0.240234375 -0.4961181640624994 +0.411375 -0.239593505859375 -0.4961181640624994 +0.4115 -0.239593505859375 -0.4961181640624994 +0.411625 -0.2388916015625 -0.4961181640624994 +0.41175 -0.238189697265625 -0.4961181640624994 +0.411875 -0.238189697265625 -0.4961181640624994 +0.412 -0.237457275390625 -0.4961181640624994 +0.412125 -0.237457275390625 -0.4961181640624994 +0.41225 -0.2366943359375 -0.4961181640624994 +0.412375 -0.23590087890625 -0.4961181640624994 +0.4125 -0.23590087890625 -0.4961181640624994 +0.4126250000000001 -0.235076904296875 -0.4961181640624994 +0.41275 -0.235076904296875 -0.4961181640624994 +0.412875 -0.2342529296875 -0.4961181640624994 +0.4130000000000001 -0.233367919921875 -0.4961181640624994 +0.4131250000000001 -0.233367919921875 -0.4961181640624994 +0.41325 -0.23248291015625 -0.4961181640624994 +0.413375 -0.23248291015625 -0.4961181640624994 +0.4135000000000001 -0.2315673828125 -0.4961181640624994 +0.413625 -0.230621337890625 -0.4961181640624994 +0.41375 -0.230621337890625 -0.4961181640624994 +0.413875 -0.229644775390625 -0.4961181640624994 +0.4140000000000001 -0.229644775390625 -0.4961181640624994 +0.414125 -0.2286376953125 -0.4961181640624994 +0.41425 -0.227630615234375 -0.4961181640624994 +0.414375 -0.227630615234375 -0.4961181640624994 +0.4145 -0.226593017578125 -0.4961181640624994 +0.414625 -0.226593017578125 -0.4961181640624994 +0.41475 -0.22552490234375 -0.4961181640624994 +0.414875 -0.22442626953125 -0.4961181640624994 +0.415 -0.22442626953125 -0.4961181640624994 +0.415125 -0.223297119140625 -0.4961181640624994 +0.41525 -0.223297119140625 -0.4961181640624994 +0.415375 -0.22216796875 -0.4961181640624994 +0.4155 -0.22100830078125 -0.4961181640624994 +0.415625 -0.22100830078125 -0.4961181640624994 +0.41575 -0.219818115234375 -0.4961181640624994 +0.415875 -0.219818115234375 -0.4961181640624994 +0.416 -0.126129150390625 -0.2863085937499983 +0.416125 -0.12542724609375 -0.2863085937499983 +0.41625 -0.12542724609375 -0.2863085937499983 +0.416375 -0.12469482421875 -0.2863085937499983 +0.4165 -0.12469482421875 -0.2863085937499983 +0.416625 -0.12396240234375 -0.2863085937499983 +0.41675 -0.123199462890625 -0.2863085937499983 +0.416875 -0.123199462890625 -0.2863085937499983 +0.417 -0.1224365234375 -0.2863085937499983 +0.4171250000000001 -0.1224365234375 -0.2863085937499983 +0.41725 -0.12164306640625 -0.2863085937499983 +0.417375 -0.120849609375 -0.2863085937499983 +0.4175 -0.120849609375 -0.2863085937499983 +0.417625 -0.120025634765625 -0.2863085937499983 +0.41775 -0.120025634765625 -0.2863085937499983 +0.417875 -0.119232177734375 -0.2863085937499983 +0.418 -0.118377685546875 -0.2863085937499983 +0.418125 -0.118377685546875 -0.2863085937499983 +0.41825 -0.117523193359375 -0.2863085937499983 +0.418375 -0.117523193359375 -0.2863085937499983 +0.4185 -0.116668701171875 -0.2863085937499983 +0.418625 -0.11578369140625 -0.2863085937499983 +0.41875 -0.11578369140625 -0.2863085937499983 +0.418875 -0.114898681640625 -0.2863085937499983 +0.419 -0.114898681640625 -0.2863085937499983 +0.419125 -0.114013671875 -0.2863085937499983 +0.41925 -0.11309814453125 -0.2863085937499983 +0.419375 -0.11309814453125 -0.2863085937499983 +0.4195 -0.1121826171875 -0.2863085937499983 +0.419625 -0.1121826171875 -0.2863085937499983 +0.41975 -0.111236572265625 -0.2863085937499983 +0.419875 -0.11029052734375 -0.2863085937499983 +0.42 -0.11029052734375 -0.2863085937499983 +0.420125 -0.10931396484375 -0.2863085937499983 +0.4202500000000001 -0.10931396484375 -0.2863085937499983 +0.420375 -0.10833740234375 -0.2863085937499983 +0.4205 -0.10736083984375 -0.2863085937499983 +0.4206250000000001 -0.10736083984375 -0.2863085937499983 +0.42075 -0.106353759765625 -0.2863085937499983 +0.420875 -0.106353759765625 -0.2863085937499983 +0.421 -0.1053466796875 -0.2863085937499983 +0.4211250000000001 -0.104339599609375 -0.2863085937499983 +0.42125 -0.104339599609375 -0.2863085937499983 +0.421375 -0.103302001953125 -0.2863085937499983 +0.4215 -0.103302001953125 -0.2863085937499983 +0.421625 -0.102264404296875 -0.2863085937499983 +0.42175 -0.1011962890625 -0.2863085937499983 +0.421875 -0.1011962890625 -0.2863085937499983 +0.422 -0.100128173828125 -0.2863085937499983 +0.422125 -0.100128173828125 -0.2863085937499983 +0.42225 -0.09906005859375 -0.2863085937499983 +0.422375 -0.097991943359375 -0.2863085937499983 +0.4225 -0.097991943359375 -0.2863085937499983 +0.422625 -0.096893310546875 -0.2863085937499983 +0.42275 -0.096893310546875 -0.2863085937499983 +0.422875 -0.09576416015625 -0.2863085937499983 +0.423 -0.09466552734375 -0.2863085937499983 +0.423125 -0.09466552734375 -0.2863085937499983 +0.42325 -0.093536376953125 -0.2863085937499983 +0.423375 -0.093536376953125 -0.2863085937499983 +0.4234999999999999 -0.092376708984375 -0.2863085937499983 +0.423625 -0.091217041015625 -0.2863085937499983 +0.42375 -0.091217041015625 -0.2863085937499983 +0.423875 -0.090057373046875 -0.2863085937499983 +0.424 -0.090057373046875 -0.2863085937499983 +0.424125 -0.088897705078125 -0.2863085937499983 +0.42425 -0.087738037109375 -0.2863085937499983 +0.424375 -0.087738037109375 -0.2863085937499983 +0.4245 -0.086517333984375 -0.2863085937499983 +0.424625 -0.086517333984375 -0.2863085937499983 +0.42475 -0.0853271484375 -0.2863085937499983 +0.424875 -0.084136962890625 -0.2863085937499983 +0.425 -0.084136962890625 -0.2863085937499983 +0.4251250000000001 -0.082916259765625 -0.2863085937499983 +0.42525 -0.082916259765625 -0.2863085937499983 +0.425375 -0.081695556640625 -0.2863085937499983 +0.4255 -0.0804443359375 -0.2863085937499983 +0.4256250000000001 -0.0804443359375 -0.2863085937499983 +0.42575 -0.079193115234375 -0.2863085937499983 +0.425875 -0.079193115234375 -0.2863085937499983 +0.426 -0.07794189453125 -0.2863085937499983 +0.426125 -0.076690673828125 -0.2863085937499983 +0.42625 -0.076690673828125 -0.2863085937499983 +0.426375 -0.075408935546875 -0.2863085937499983 +0.4265 -0.075408935546875 -0.2863085937499983 +0.426625 -0.074127197265625 -0.2863085937499983 +0.42675 -0.072845458984375 -0.2863085937499983 +0.426875 -0.072845458984375 -0.2863085937499983 +0.427 -0.071563720703125 -0.2863085937499983 +0.427125 -0.071563720703125 -0.2863085937499983 +0.42725 -0.07025146484375 -0.2863085937499983 +0.427375 -0.068939208984375 -0.2863085937499983 +0.4275 -0.068939208984375 -0.2863085937499983 +0.427625 -0.067626953125 -0.2863085937499983 +0.42775 -0.067626953125 -0.2863085937499983 +0.427875 -0.066314697265625 -0.2863085937499983 +0.428 -0.064971923828125 -0.2863085937499983 +0.428125 -0.064971923828125 -0.2863085937499983 +0.4282500000000001 -0.063629150390625 -0.2863085937499983 +0.428375 -0.063629150390625 -0.2863085937499983 +0.4285 -0.062286376953125 -0.2863085937499983 +0.4286250000000001 -0.060943603515625 -0.2863085937499983 +0.4287500000000001 -0.060943603515625 -0.2863085937499983 +0.428875 -0.0595703125 -0.2863085937499983 +0.429 -0.0595703125 -0.2863085937499983 +0.4291250000000001 -0.058197021484375 -0.2863085937499983 +0.42925 -0.05682373046875 -0.2863085937499983 +0.429375 -0.05682373046875 -0.2863085937499983 +0.4295 -0.055450439453125 -0.2863085937499983 +0.4296250000000001 -0.055450439453125 -0.2863085937499983 +0.42975 -0.0540771484375 -0.2863085937499983 +0.429875 -0.05267333984375 -0.2863085937499983 +0.43 -0.05267333984375 -0.2863085937499983 +0.430125 -0.05126953125 -0.2863085937499983 +0.43025 -0.05126953125 -0.2863085937499983 +0.430375 -0.049896240234375 -0.2863085937499983 +0.4305 -0.0484619140625 -0.2863085937499983 +0.430625 -0.0484619140625 -0.2863085937499983 +0.43075 -0.04705810546875 -0.2863085937499983 +0.430875 -0.04705810546875 -0.2863085937499983 +0.431 -0.045654296875 -0.2863085937499983 +0.431125 -0.044219970703125 -0.2863085937499983 +0.43125 -0.044219970703125 -0.2863085937499983 +0.431375 -0.04278564453125 -0.2863085937499983 +0.4315 -0.04278564453125 -0.2863085937499983 +0.431625 -0.041351318359375 -0.2863085937499983 +0.43175 -0.0399169921875 -0.2863085937499983 +0.431875 -0.0399169921875 -0.2863085937499983 +0.432 -0.038482666015625 -0.2863085937499983 +0.432125 -0.038482666015625 -0.2863085937499983 +0.43225 -0.037017822265625 -0.2863085937499983 +0.432375 -0.03558349609375 -0.2863085937499983 +0.4325 -0.03558349609375 -0.2863085937499983 +0.432625 -0.03411865234375 -0.2863085937499983 +0.4327500000000001 -0.03411865234375 -0.2863085937499983 +0.432875 -0.032684326171875 -0.2863085937499983 +0.433 -0.031219482421875 -0.2863085937499983 +0.433125 -0.031219482421875 -0.2863085937499983 +0.43325 -0.029754638671875 -0.2863085937499983 +0.433375 -0.029754638671875 -0.2863085937499983 +0.4335 -0.028289794921875 -0.2863085937499983 +0.433625 -0.02679443359375 -0.2863085937499983 +0.43375 -0.02679443359375 -0.2863085937499983 +0.433875 -0.02532958984375 -0.2863085937499983 +0.434 -0.02532958984375 -0.2863085937499983 +0.434125 -0.02386474609375 -0.2863085937499983 +0.43425 -0.022369384765625 -0.2863085937499983 +0.434375 -0.022369384765625 -0.2863085937499983 +0.4345 -0.020904541015625 -0.2863085937499983 +0.434625 -0.020904541015625 -0.2863085937499983 +0.43475 -0.0194091796875 -0.2863085937499983 +0.434875 -0.017913818359375 -0.2863085937499983 +0.435 -0.017913818359375 -0.2863085937499983 +0.435125 -0.016448974609375 -0.2863085937499983 +0.43525 -0.016448974609375 -0.2863085937499983 +0.435375 -0.01495361328125 -0.2863085937499983 +0.4355 -0.013458251953125 -0.2863085937499983 +0.435625 -0.013458251953125 -0.2863085937499983 +0.43575 -0.011962890625 -0.2863085937499983 +0.4358750000000001 -0.011962890625 -0.2863085937499983 +0.436 -0.010467529296875 -0.2863085937499983 +0.436125 -0.00897216796875 -0.2863085937499983 +0.4362500000000001 -0.00897216796875 -0.2863085937499983 +0.436375 -0.007476806640625 -0.2863085937499983 +0.4365 -0.007476806640625 -0.2863085937499983 +0.436625 -0.0059814453125 -0.2863085937499983 +0.4367500000000001 -0.004486083984375 -0.2863085937499983 +0.436875 -0.004486083984375 -0.2863085937499983 +0.437 -0.00299072265625 -0.2863085937499983 +0.437125 -0.00299072265625 -0.2863085937499983 +0.43725 -0.001495361328125 -0.2863085937499983 0.437375 0.0 -0.2863085937499983 0.4375 0.0 -0.2863085937499983 0.437625 0.001495361328125 -0.2863085937499983 @@ -3582,421 +3582,421 @@ 0.447625 0.07025146484375 -0.2863085937499983 0.44775 0.07025146484375 -0.2863085937499983 0.447875 0.071563720703125 -0.2863085937499983 -0.448 -0.000274658203125 0.001074218750001854 -0.448125 -0.000274658203125 0.001074218750001854 -0.44825 -0.000274658203125 0.001074218750001854 -0.4483750000000001 -0.000274658203125 0.001074218750001854 -0.4485 -0.000274658203125 0.001074218750001854 -0.448625 -0.00030517578125 0.001074218750001854 -0.44875 -0.00030517578125 0.001074218750001854 -0.448875 -0.00030517578125 0.001074218750001854 -0.449 -0.00030517578125 0.001074218750001854 -0.449125 -0.00030517578125 0.001074218750001854 -0.44925 -0.00030517578125 0.001074218750001854 -0.449375 -0.00030517578125 0.001074218750001854 -0.4495 -0.00030517578125 0.001074218750001854 -0.449625 -0.00030517578125 0.001074218750001854 -0.44975 -0.00030517578125 0.001074218750001854 -0.449875 -0.00030517578125 0.001074218750001854 -0.45 -0.00030517578125 0.001074218750001854 -0.450125 -0.000335693359375 0.001074218750001854 -0.45025 -0.000335693359375 0.001074218750001854 -0.450375 -0.000335693359375 0.001074218750001854 -0.4505 -0.000335693359375 0.001074218750001854 -0.450625 -0.000335693359375 0.001074218750001854 -0.45075 -0.000335693359375 0.001074218750001854 -0.450875 -0.000335693359375 0.001074218750001854 -0.451 -0.000335693359375 0.001074218750001854 -0.451125 -0.000335693359375 0.001074218750001854 -0.45125 -0.000335693359375 0.001074218750001854 -0.451375 -0.000335693359375 0.001074218750001854 -0.4515000000000001 -0.000335693359375 0.001074218750001854 -0.451625 -0.0003662109375 0.001074218750001854 -0.45175 -0.0003662109375 0.001074218750001854 -0.4518750000000001 -0.0003662109375 0.001074218750001854 -0.452 -0.0003662109375 0.001074218750001854 -0.452125 -0.0003662109375 0.001074218750001854 -0.45225 -0.0003662109375 0.001074218750001854 -0.4523750000000001 -0.0003662109375 0.001074218750001854 -0.4525 -0.0003662109375 0.001074218750001854 -0.452625 -0.0003662109375 0.001074218750001854 -0.45275 -0.0003662109375 0.001074218750001854 -0.452875 -0.0003662109375 0.001074218750001854 -0.453 -0.000396728515625 0.001074218750001854 -0.453125 -0.000396728515625 0.001074218750001854 -0.45325 -0.000396728515625 0.001074218750001854 -0.453375 -0.000396728515625 0.001074218750001854 -0.4535 -0.000396728515625 0.001074218750001854 -0.453625 -0.000396728515625 0.001074218750001854 -0.45375 -0.000396728515625 0.001074218750001854 -0.453875 -0.000396728515625 0.001074218750001854 -0.454 -0.000396728515625 0.001074218750001854 -0.454125 -0.000396728515625 0.001074218750001854 -0.45425 -0.000396728515625 0.001074218750001854 -0.454375 -0.000396728515625 0.001074218750001854 -0.4545 -0.000396728515625 0.001074218750001854 -0.454625 -0.000396728515625 0.001074218750001854 -0.4547499999999999 -0.000396728515625 0.001074218750001854 -0.454875 -0.00042724609375 0.001074218750001854 -0.455 -0.00042724609375 0.001074218750001854 -0.455125 -0.00042724609375 0.001074218750001854 -0.45525 -0.00042724609375 0.001074218750001854 -0.455375 -0.00042724609375 0.001074218750001854 -0.4555 -0.00042724609375 0.001074218750001854 -0.455625 -0.00042724609375 0.001074218750001854 -0.45575 -0.00042724609375 0.001074218750001854 -0.455875 -0.00042724609375 0.001074218750001854 -0.456 -0.00042724609375 0.001074218750001854 -0.456125 -0.00042724609375 0.001074218750001854 -0.45625 -0.00042724609375 0.001074218750001854 -0.4563750000000001 -0.00042724609375 0.001074218750001854 -0.4565 -0.00042724609375 0.001074218750001854 -0.456625 -0.00042724609375 0.001074218750001854 -0.45675 -0.000457763671875 0.001074218750001854 -0.4568750000000001 -0.000457763671875 0.001074218750001854 -0.457 -0.000457763671875 0.001074218750001854 -0.457125 -0.000457763671875 0.001074218750001854 -0.45725 -0.000457763671875 0.001074218750001854 -0.457375 -0.000457763671875 0.001074218750001854 -0.4575 -0.000457763671875 0.001074218750001854 -0.457625 -0.000457763671875 0.001074218750001854 -0.45775 -0.000457763671875 0.001074218750001854 -0.457875 -0.000457763671875 0.001074218750001854 -0.458 -0.000457763671875 0.001074218750001854 -0.458125 -0.000457763671875 0.001074218750001854 -0.45825 -0.000457763671875 0.001074218750001854 -0.458375 -0.000457763671875 0.001074218750001854 -0.4585 -0.000457763671875 0.001074218750001854 -0.458625 -0.000457763671875 0.001074218750001854 -0.45875 -0.000457763671875 0.001074218750001854 -0.458875 -0.000457763671875 0.001074218750001854 -0.459 -0.000457763671875 0.001074218750001854 -0.459125 -0.00048828125 0.001074218750001854 -0.45925 -0.00048828125 0.001074218750001854 -0.459375 -0.00048828125 0.001074218750001854 -0.4595000000000001 -0.00048828125 0.001074218750001854 -0.459625 -0.00048828125 0.001074218750001854 -0.45975 -0.00048828125 0.001074218750001854 -0.4598750000000001 -0.00048828125 0.001074218750001854 -0.4600000000000001 -0.00048828125 0.001074218750001854 -0.460125 -0.00048828125 0.001074218750001854 -0.46025 -0.00048828125 0.001074218750001854 -0.4603750000000001 -0.00048828125 0.001074218750001854 -0.4605 -0.00048828125 0.001074218750001854 -0.460625 -0.00048828125 0.001074218750001854 -0.46075 -0.00048828125 0.001074218750001854 -0.4608750000000001 -0.00048828125 0.001074218750001854 -0.461 -0.00048828125 0.001074218750001854 -0.461125 -0.00048828125 0.001074218750001854 -0.46125 -0.00048828125 0.001074218750001854 -0.461375 -0.00048828125 0.001074218750001854 -0.4615 -0.00048828125 0.001074218750001854 -0.461625 -0.00048828125 0.001074218750001854 -0.46175 -0.00048828125 0.001074218750001854 -0.461875 -0.00048828125 0.001074218750001854 -0.462 -0.000518798828125 0.001074218750001854 -0.462125 -0.000518798828125 0.001074218750001854 -0.46225 -0.000518798828125 0.001074218750001854 -0.462375 -0.000518798828125 0.001074218750001854 -0.4625 -0.000518798828125 0.001074218750001854 -0.462625 -0.000518798828125 0.001074218750001854 -0.46275 -0.000518798828125 0.001074218750001854 -0.462875 -0.000518798828125 0.001074218750001854 -0.463 -0.000518798828125 0.001074218750001854 -0.463125 -0.000518798828125 0.001074218750001854 -0.46325 -0.000518798828125 0.001074218750001854 -0.463375 -0.000518798828125 0.001074218750001854 -0.4635 -0.000518798828125 0.001074218750001854 -0.463625 -0.000518798828125 0.001074218750001854 -0.46375 -0.000518798828125 0.001074218750001854 -0.463875 -0.000518798828125 0.001074218750001854 -0.4640000000000001 -0.000518798828125 0.001074218750001854 -0.464125 -0.000518798828125 0.001074218750001854 -0.46425 -0.000518798828125 0.001074218750001854 -0.464375 -0.000518798828125 0.001074218750001854 -0.4645 -0.000518798828125 0.001074218750001854 -0.464625 -0.000518798828125 0.001074218750001854 -0.46475 -0.000518798828125 0.001074218750001854 -0.464875 -0.000518798828125 0.001074218750001854 -0.465 -0.000518798828125 0.001074218750001854 -0.465125 -0.000518798828125 0.001074218750001854 -0.46525 -0.000518798828125 0.001074218750001854 -0.465375 -0.000518798828125 0.001074218750001854 -0.4655 -0.000518798828125 0.001074218750001854 -0.465625 -0.000518798828125 0.001074218750001854 -0.46575 -0.000518798828125 0.001074218750001854 -0.465875 -0.000518798828125 0.001074218750001854 -0.466 -0.000518798828125 0.001074218750001854 -0.466125 -0.000518798828125 0.001074218750001854 -0.46625 -0.000518798828125 0.001074218750001854 -0.466375 -0.000518798828125 0.001074218750001854 -0.4665 -0.000518798828125 0.001074218750001854 -0.466625 -0.000518798828125 0.001074218750001854 -0.46675 -0.000518798828125 0.001074218750001854 -0.466875 -0.000518798828125 0.001074218750001854 -0.467 -0.000518798828125 0.001074218750001854 -0.4671250000000001 -0.000518798828125 0.001074218750001854 -0.46725 -0.000518798828125 0.001074218750001854 -0.467375 -0.000518798828125 0.001074218750001854 -0.4675000000000001 -0.000518798828125 0.001074218750001854 -0.467625 -0.000518798828125 0.001074218750001854 -0.46775 -0.000518798828125 0.001074218750001854 -0.467875 -0.000518798828125 0.001074218750001854 -0.4680000000000001 -0.000518798828125 0.001074218750001854 -0.468125 -0.000518798828125 0.001074218750001854 -0.46825 -0.000518798828125 0.001074218750001854 -0.468375 -0.000518798828125 0.001074218750001854 -0.4685 -0.000518798828125 0.001074218750001854 -0.468625 -0.000518798828125 0.001074218750001854 -0.46875 -0.000518798828125 0.001074218750001854 -0.468875 -0.000518798828125 0.001074218750001854 -0.469 -0.000518798828125 0.001074218750001854 -0.469125 -0.000518798828125 0.001074218750001854 -0.46925 -0.000518798828125 0.001074218750001854 -0.469375 -0.000518798828125 0.001074218750001854 -0.4695 -0.000518798828125 0.001074218750001854 -0.469625 -0.000518798828125 0.001074218750001854 -0.46975 -0.000518798828125 0.001074218750001854 -0.469875 -0.000518798828125 0.001074218750001854 -0.47 -0.000518798828125 0.001074218750001854 -0.470125 -0.000518798828125 0.001074218750001854 -0.47025 -0.000518798828125 0.001074218750001854 -0.4703749999999999 -0.000518798828125 0.001074218750001854 -0.4705 -0.000518798828125 0.001074218750001854 -0.470625 -0.000518798828125 0.001074218750001854 -0.47075 -0.000518798828125 0.001074218750001854 -0.470875 -0.000518798828125 0.001074218750001854 -0.471 -0.000518798828125 0.001074218750001854 -0.471125 -0.000518798828125 0.001074218750001854 -0.47125 -0.000518798828125 0.001074218750001854 -0.471375 -0.000518798828125 0.001074218750001854 -0.4715 -0.000518798828125 0.001074218750001854 -0.471625 -0.000518798828125 0.001074218750001854 -0.47175 -0.000518798828125 0.001074218750001854 -0.471875 -0.000518798828125 0.001074218750001854 -0.4720000000000001 -0.000518798828125 0.001074218750001854 -0.472125 -0.000518798828125 0.001074218750001854 -0.47225 -0.000518798828125 0.001074218750001854 -0.472375 -0.000518798828125 0.001074218750001854 -0.4725000000000001 -0.000518798828125 0.001074218750001854 -0.472625 -0.000518798828125 0.001074218750001854 -0.47275 -0.000518798828125 0.001074218750001854 -0.472875 -0.000518798828125 0.001074218750001854 -0.473 -0.000518798828125 0.001074218750001854 -0.473125 -0.000518798828125 0.001074218750001854 -0.47325 -0.000518798828125 0.001074218750001854 -0.473375 -0.000518798828125 0.001074218750001854 -0.4735 -0.000518798828125 0.001074218750001854 -0.473625 -0.000518798828125 0.001074218750001854 -0.47375 -0.000518798828125 0.001074218750001854 -0.473875 -0.000518798828125 0.001074218750001854 -0.474 -0.000518798828125 0.001074218750001854 -0.474125 -0.000518798828125 0.001074218750001854 -0.47425 -0.000518798828125 0.001074218750001854 -0.474375 -0.000518798828125 0.001074218750001854 -0.4745 -0.000518798828125 0.001074218750001854 -0.474625 -0.000518798828125 0.001074218750001854 -0.47475 -0.000518798828125 0.001074218750001854 -0.474875 -0.000518798828125 0.001074218750001854 -0.475 -0.000518798828125 0.001074218750001854 -0.4751250000000001 -0.000518798828125 0.001074218750001854 -0.47525 -0.000518798828125 0.001074218750001854 -0.475375 -0.000518798828125 0.001074218750001854 -0.4755000000000001 -0.00048828125 0.001074218750001854 -0.4756250000000001 -0.00048828125 0.001074218750001854 -0.47575 -0.00048828125 0.001074218750001854 -0.475875 -0.00048828125 0.001074218750001854 -0.4760000000000001 -0.00048828125 0.001074218750001854 -0.476125 -0.00048828125 0.001074218750001854 -0.47625 -0.00048828125 0.001074218750001854 -0.476375 -0.00048828125 0.001074218750001854 -0.4765000000000001 -0.00048828125 0.001074218750001854 -0.476625 -0.00048828125 0.001074218750001854 -0.47675 -0.00048828125 0.001074218750001854 -0.476875 -0.00048828125 0.001074218750001854 -0.477 -0.00048828125 0.001074218750001854 -0.477125 -0.00048828125 0.001074218750001854 -0.47725 -0.00048828125 0.001074218750001854 -0.477375 -0.00048828125 0.001074218750001854 -0.4775 -0.00048828125 0.001074218750001854 -0.477625 -0.00048828125 0.001074218750001854 -0.47775 -0.00048828125 0.001074218750001854 -0.477875 -0.00048828125 0.001074218750001854 -0.478 -0.00048828125 0.001074218750001854 -0.478125 -0.00048828125 0.001074218750001854 -0.47825 -0.00048828125 0.001074218750001854 -0.478375 -0.00048828125 0.001074218750001854 -0.4785 -0.000457763671875 0.001074218750001854 -0.478625 -0.000457763671875 0.001074218750001854 -0.47875 -0.000457763671875 0.001074218750001854 -0.478875 -0.000457763671875 0.001074218750001854 -0.479 -0.000457763671875 0.001074218750001854 -0.479125 -0.000457763671875 0.001074218750001854 -0.47925 -0.000457763671875 0.001074218750001854 -0.479375 -0.000457763671875 0.001074218750001854 -0.4795 -0.000457763671875 0.001074218750001854 -0.4796250000000001 -0.000457763671875 0.001074218750001854 -0.47975 -0.000457763671875 0.001074218750001854 -0.479875 -0.000457763671875 0.001074218750001854 -0.48 -0.135162353515625 0.3201562500000024 -0.480125 -0.134246826171875 0.3201562500000024 -0.48025 -0.134246826171875 0.3201562500000024 -0.480375 -0.133331298828125 0.3201562500000024 -0.4805 -0.13238525390625 0.3201562500000024 -0.480625 -0.13238525390625 0.3201562500000024 -0.48075 -0.131439208984375 0.3201562500000024 -0.480875 -0.131439208984375 0.3201562500000024 -0.481 -0.1304931640625 0.3201562500000024 -0.481125 -0.1295166015625 0.3201562500000024 -0.48125 -0.1295166015625 0.3201562500000024 -0.481375 -0.128509521484375 0.3201562500000024 -0.4815 -0.128509521484375 0.3201562500000024 -0.481625 -0.12750244140625 0.3201562500000024 -0.48175 -0.126495361328125 0.3201562500000024 -0.481875 -0.126495361328125 0.3201562500000024 -0.482 -0.125457763671875 0.3201562500000024 -0.482125 -0.125457763671875 0.3201562500000024 -0.48225 -0.1243896484375 0.3201562500000024 -0.482375 -0.12335205078125 0.3201562500000024 -0.4825 -0.12335205078125 0.3201562500000024 -0.482625 -0.12225341796875 0.3201562500000024 -0.4827500000000001 -0.12225341796875 0.3201562500000024 -0.482875 -0.121185302734375 0.3201562500000024 -0.483 -0.120086669921875 0.3201562500000024 -0.4831250000000001 -0.120086669921875 0.3201562500000024 -0.48325 -0.11895751953125 0.3201562500000024 -0.483375 -0.11895751953125 0.3201562500000024 -0.4835 -0.117828369140625 0.3201562500000024 -0.4836250000000001 -0.11669921875 0.3201562500000024 -0.48375 -0.11669921875 0.3201562500000024 -0.483875 -0.11553955078125 0.3201562500000024 -0.484 -0.11553955078125 0.3201562500000024 -0.484125 -0.1143798828125 0.3201562500000024 -0.48425 -0.113189697265625 0.3201562500000024 -0.484375 -0.113189697265625 0.3201562500000024 -0.4845 -0.11199951171875 0.3201562500000024 -0.484625 -0.11199951171875 0.3201562500000024 -0.48475 -0.110809326171875 0.3201562500000024 -0.484875 -0.109588623046875 0.3201562500000024 -0.485 -0.109588623046875 0.3201562500000024 -0.485125 -0.108367919921875 0.3201562500000024 -0.48525 -0.108367919921875 0.3201562500000024 -0.485375 -0.10711669921875 0.3201562500000024 -0.4855 -0.105865478515625 0.3201562500000024 -0.485625 -0.105865478515625 0.3201562500000024 -0.48575 -0.104583740234375 0.3201562500000024 -0.485875 -0.104583740234375 0.3201562500000024 -0.4859999999999999 -0.10333251953125 0.3201562500000024 -0.486125 -0.10205078125 0.3201562500000024 -0.48625 -0.10205078125 0.3201562500000024 -0.486375 -0.100738525390625 0.3201562500000024 -0.4865 -0.100738525390625 0.3201562500000024 -0.486625 -0.09942626953125 0.3201562500000024 -0.48675 -0.098114013671875 0.3201562500000024 -0.486875 -0.098114013671875 0.3201562500000024 -0.487 -0.096771240234375 0.3201562500000024 -0.487125 -0.096771240234375 0.3201562500000024 -0.48725 -0.095458984375 0.3201562500000024 -0.487375 -0.094085693359375 0.3201562500000024 -0.4875 -0.094085693359375 0.3201562500000024 -0.4876250000000001 -0.092742919921875 0.3201562500000024 -0.48775 -0.092742919921875 0.3201562500000024 -0.487875 -0.09136962890625 0.3201562500000024 -0.488 -0.0899658203125 0.3201562500000024 -0.4881250000000001 -0.0899658203125 0.3201562500000024 -0.48825 -0.088592529296875 0.3201562500000024 -0.488375 -0.088592529296875 0.3201562500000024 -0.4885 -0.087188720703125 0.3201562500000024 -0.488625 -0.085784912109375 0.3201562500000024 -0.48875 -0.085784912109375 0.3201562500000024 -0.488875 -0.0843505859375 0.3201562500000024 -0.489 -0.0843505859375 0.3201562500000024 -0.489125 -0.082916259765625 0.3201562500000024 -0.48925 -0.08148193359375 0.3201562500000024 -0.489375 -0.08148193359375 0.3201562500000024 -0.4895 -0.080047607421875 0.3201562500000024 -0.489625 -0.080047607421875 0.3201562500000024 -0.48975 -0.078582763671875 0.3201562500000024 -0.489875 -0.077117919921875 0.3201562500000024 -0.49 -0.077117919921875 0.3201562500000024 -0.490125 -0.075653076171875 0.3201562500000024 -0.49025 -0.075653076171875 0.3201562500000024 -0.490375 -0.07415771484375 0.3201562500000024 -0.4905 -0.072662353515625 0.3201562500000024 -0.490625 -0.072662353515625 0.3201562500000024 -0.4907500000000001 -0.0711669921875 0.3201562500000024 -0.490875 -0.0711669921875 0.3201562500000024 -0.491 -0.069671630859375 0.3201562500000024 -0.4911250000000001 -0.06817626953125 0.3201562500000024 -0.4912500000000001 -0.06817626953125 0.3201562500000024 -0.491375 -0.066650390625 0.3201562500000024 -0.4915 -0.066650390625 0.3201562500000024 -0.4916250000000001 -0.06512451171875 0.3201562500000024 -0.49175 -0.063568115234375 0.3201562500000024 -0.491875 -0.063568115234375 0.3201562500000024 -0.492 -0.062042236328125 0.3201562500000024 -0.4921250000000001 -0.062042236328125 0.3201562500000024 -0.49225 -0.06048583984375 0.3201562500000024 -0.492375 -0.058929443359375 0.3201562500000024 -0.4925 -0.058929443359375 0.3201562500000024 -0.492625 -0.057373046875 0.3201562500000024 -0.49275 -0.057373046875 0.3201562500000024 -0.492875 -0.055816650390625 0.3201562500000024 -0.493 -0.054229736328125 0.3201562500000024 -0.493125 -0.054229736328125 0.3201562500000024 -0.49325 -0.052642822265625 0.3201562500000024 -0.493375 -0.052642822265625 0.3201562500000024 -0.4935 -0.051055908203125 0.3201562500000024 -0.493625 -0.049468994140625 0.3201562500000024 -0.49375 -0.049468994140625 0.3201562500000024 -0.493875 -0.047882080078125 0.3201562500000024 -0.494 -0.047882080078125 0.3201562500000024 -0.494125 -0.0462646484375 0.3201562500000024 -0.49425 -0.044677734375 0.3201562500000024 -0.494375 -0.044677734375 0.3201562500000024 -0.4945 -0.043060302734375 0.3201562500000024 -0.494625 -0.043060302734375 0.3201562500000024 -0.49475 -0.04144287109375 0.3201562500000024 -0.494875 -0.039825439453125 0.3201562500000024 -0.495 -0.039825439453125 0.3201562500000024 -0.495125 -0.0382080078125 0.3201562500000024 -0.4952500000000001 -0.0382080078125 0.3201562500000024 -0.495375 -0.03656005859375 0.3201562500000024 -0.4955 -0.034912109375 0.3201562500000024 -0.4956250000000001 -0.034912109375 0.3201562500000024 -0.49575 -0.033294677734375 0.3201562500000024 -0.495875 -0.033294677734375 0.3201562500000024 -0.496 -0.031646728515625 0.3201562500000024 -0.496125 -0.029998779296875 0.3201562500000024 -0.49625 -0.029998779296875 0.3201562500000024 -0.496375 -0.028350830078125 0.3201562500000024 -0.4965 -0.028350830078125 0.3201562500000024 -0.496625 -0.026702880859375 0.3201562500000024 -0.49675 -0.025054931640625 0.3201562500000024 -0.496875 -0.025054931640625 0.3201562500000024 -0.497 -0.023406982421875 0.3201562500000024 -0.497125 -0.023406982421875 0.3201562500000024 -0.49725 -0.021728515625 0.3201562500000024 -0.497375 -0.02008056640625 0.3201562500000024 -0.4975 -0.02008056640625 0.3201562500000024 -0.497625 -0.018402099609375 0.3201562500000024 -0.49775 -0.018402099609375 0.3201562500000024 -0.497875 -0.016754150390625 0.3201562500000024 -0.498 -0.01507568359375 0.3201562500000024 -0.498125 -0.01507568359375 0.3201562500000024 -0.49825 -0.013397216796875 0.3201562500000024 -0.4983750000000001 -0.013397216796875 0.3201562500000024 -0.4985 -0.01171875 0.3201562500000024 -0.498625 -0.01007080078125 0.3201562500000024 -0.4987500000000001 -0.01007080078125 0.3201562500000024 -0.498875 -0.008392333984375 0.3201562500000024 -0.499 -0.008392333984375 0.3201562500000024 -0.499125 -0.0067138671875 0.3201562500000024 -0.4992500000000001 -0.005035400390625 0.3201562500000024 -0.499375 -0.005035400390625 0.3201562500000024 -0.4995 -0.00335693359375 0.3201562500000024 -0.499625 -0.00335693359375 0.3201562500000024 -0.49975 -0.001678466796875 0.3201562500000024 +0.448 -0.000244140625 0.001074218750001854 +0.448125 -0.000244140625 0.001074218750001854 +0.44825 -0.000244140625 0.001074218750001854 +0.4483750000000001 -0.000244140625 0.001074218750001854 +0.4485 -0.000244140625 0.001074218750001854 +0.448625 -0.000274658203125 0.001074218750001854 +0.44875 -0.000274658203125 0.001074218750001854 +0.448875 -0.000274658203125 0.001074218750001854 +0.449 -0.000274658203125 0.001074218750001854 +0.449125 -0.000274658203125 0.001074218750001854 +0.44925 -0.000274658203125 0.001074218750001854 +0.449375 -0.000274658203125 0.001074218750001854 +0.4495 -0.000274658203125 0.001074218750001854 +0.449625 -0.000274658203125 0.001074218750001854 +0.44975 -0.000274658203125 0.001074218750001854 +0.449875 -0.000274658203125 0.001074218750001854 +0.45 -0.000274658203125 0.001074218750001854 +0.450125 -0.00030517578125 0.001074218750001854 +0.45025 -0.00030517578125 0.001074218750001854 +0.450375 -0.00030517578125 0.001074218750001854 +0.4505 -0.00030517578125 0.001074218750001854 +0.450625 -0.00030517578125 0.001074218750001854 +0.45075 -0.00030517578125 0.001074218750001854 +0.450875 -0.00030517578125 0.001074218750001854 +0.451 -0.00030517578125 0.001074218750001854 +0.451125 -0.00030517578125 0.001074218750001854 +0.45125 -0.00030517578125 0.001074218750001854 +0.451375 -0.00030517578125 0.001074218750001854 +0.4515000000000001 -0.00030517578125 0.001074218750001854 +0.451625 -0.000335693359375 0.001074218750001854 +0.45175 -0.000335693359375 0.001074218750001854 +0.4518750000000001 -0.000335693359375 0.001074218750001854 +0.452 -0.000335693359375 0.001074218750001854 +0.452125 -0.000335693359375 0.001074218750001854 +0.45225 -0.000335693359375 0.001074218750001854 +0.4523750000000001 -0.000335693359375 0.001074218750001854 +0.4525 -0.000335693359375 0.001074218750001854 +0.452625 -0.000335693359375 0.001074218750001854 +0.45275 -0.000335693359375 0.001074218750001854 +0.452875 -0.000335693359375 0.001074218750001854 +0.453 -0.0003662109375 0.001074218750001854 +0.453125 -0.0003662109375 0.001074218750001854 +0.45325 -0.0003662109375 0.001074218750001854 +0.453375 -0.0003662109375 0.001074218750001854 +0.4535 -0.0003662109375 0.001074218750001854 +0.453625 -0.0003662109375 0.001074218750001854 +0.45375 -0.0003662109375 0.001074218750001854 +0.453875 -0.0003662109375 0.001074218750001854 +0.454 -0.0003662109375 0.001074218750001854 +0.454125 -0.0003662109375 0.001074218750001854 +0.45425 -0.0003662109375 0.001074218750001854 +0.454375 -0.0003662109375 0.001074218750001854 +0.4545 -0.0003662109375 0.001074218750001854 +0.454625 -0.0003662109375 0.001074218750001854 +0.4547499999999999 -0.0003662109375 0.001074218750001854 +0.454875 -0.000396728515625 0.001074218750001854 +0.455 -0.000396728515625 0.001074218750001854 +0.455125 -0.000396728515625 0.001074218750001854 +0.45525 -0.000396728515625 0.001074218750001854 +0.455375 -0.000396728515625 0.001074218750001854 +0.4555 -0.000396728515625 0.001074218750001854 +0.455625 -0.000396728515625 0.001074218750001854 +0.45575 -0.000396728515625 0.001074218750001854 +0.455875 -0.000396728515625 0.001074218750001854 +0.456 -0.000396728515625 0.001074218750001854 +0.456125 -0.000396728515625 0.001074218750001854 +0.45625 -0.000396728515625 0.001074218750001854 +0.4563750000000001 -0.000396728515625 0.001074218750001854 +0.4565 -0.000396728515625 0.001074218750001854 +0.456625 -0.000396728515625 0.001074218750001854 +0.45675 -0.00042724609375 0.001074218750001854 +0.4568750000000001 -0.00042724609375 0.001074218750001854 +0.457 -0.00042724609375 0.001074218750001854 +0.457125 -0.00042724609375 0.001074218750001854 +0.45725 -0.00042724609375 0.001074218750001854 +0.457375 -0.00042724609375 0.001074218750001854 +0.4575 -0.00042724609375 0.001074218750001854 +0.457625 -0.00042724609375 0.001074218750001854 +0.45775 -0.00042724609375 0.001074218750001854 +0.457875 -0.00042724609375 0.001074218750001854 +0.458 -0.00042724609375 0.001074218750001854 +0.458125 -0.00042724609375 0.001074218750001854 +0.45825 -0.00042724609375 0.001074218750001854 +0.458375 -0.00042724609375 0.001074218750001854 +0.4585 -0.00042724609375 0.001074218750001854 +0.458625 -0.00042724609375 0.001074218750001854 +0.45875 -0.00042724609375 0.001074218750001854 +0.458875 -0.00042724609375 0.001074218750001854 +0.459 -0.00042724609375 0.001074218750001854 +0.459125 -0.000457763671875 0.001074218750001854 +0.45925 -0.000457763671875 0.001074218750001854 +0.459375 -0.000457763671875 0.001074218750001854 +0.4595000000000001 -0.000457763671875 0.001074218750001854 +0.459625 -0.000457763671875 0.001074218750001854 +0.45975 -0.000457763671875 0.001074218750001854 +0.4598750000000001 -0.000457763671875 0.001074218750001854 +0.4600000000000001 -0.000457763671875 0.001074218750001854 +0.460125 -0.000457763671875 0.001074218750001854 +0.46025 -0.000457763671875 0.001074218750001854 +0.4603750000000001 -0.000457763671875 0.001074218750001854 +0.4605 -0.000457763671875 0.001074218750001854 +0.460625 -0.000457763671875 0.001074218750001854 +0.46075 -0.000457763671875 0.001074218750001854 +0.4608750000000001 -0.000457763671875 0.001074218750001854 +0.461 -0.000457763671875 0.001074218750001854 +0.461125 -0.000457763671875 0.001074218750001854 +0.46125 -0.000457763671875 0.001074218750001854 +0.461375 -0.000457763671875 0.001074218750001854 +0.4615 -0.000457763671875 0.001074218750001854 +0.461625 -0.000457763671875 0.001074218750001854 +0.46175 -0.000457763671875 0.001074218750001854 +0.461875 -0.000457763671875 0.001074218750001854 +0.462 -0.00048828125 0.001074218750001854 +0.462125 -0.00048828125 0.001074218750001854 +0.46225 -0.00048828125 0.001074218750001854 +0.462375 -0.00048828125 0.001074218750001854 +0.4625 -0.00048828125 0.001074218750001854 +0.462625 -0.00048828125 0.001074218750001854 +0.46275 -0.00048828125 0.001074218750001854 +0.462875 -0.00048828125 0.001074218750001854 +0.463 -0.00048828125 0.001074218750001854 +0.463125 -0.00048828125 0.001074218750001854 +0.46325 -0.00048828125 0.001074218750001854 +0.463375 -0.00048828125 0.001074218750001854 +0.4635 -0.00048828125 0.001074218750001854 +0.463625 -0.00048828125 0.001074218750001854 +0.46375 -0.00048828125 0.001074218750001854 +0.463875 -0.00048828125 0.001074218750001854 +0.4640000000000001 -0.00048828125 0.001074218750001854 +0.464125 -0.00048828125 0.001074218750001854 +0.46425 -0.00048828125 0.001074218750001854 +0.464375 -0.00048828125 0.001074218750001854 +0.4645 -0.00048828125 0.001074218750001854 +0.464625 -0.00048828125 0.001074218750001854 +0.46475 -0.00048828125 0.001074218750001854 +0.464875 -0.00048828125 0.001074218750001854 +0.465 -0.00048828125 0.001074218750001854 +0.465125 -0.00048828125 0.001074218750001854 +0.46525 -0.00048828125 0.001074218750001854 +0.465375 -0.00048828125 0.001074218750001854 +0.4655 -0.00048828125 0.001074218750001854 +0.465625 -0.00048828125 0.001074218750001854 +0.46575 -0.00048828125 0.001074218750001854 +0.465875 -0.00048828125 0.001074218750001854 +0.466 -0.00048828125 0.001074218750001854 +0.466125 -0.00048828125 0.001074218750001854 +0.46625 -0.00048828125 0.001074218750001854 +0.466375 -0.00048828125 0.001074218750001854 +0.4665 -0.00048828125 0.001074218750001854 +0.466625 -0.00048828125 0.001074218750001854 +0.46675 -0.00048828125 0.001074218750001854 +0.466875 -0.00048828125 0.001074218750001854 +0.467 -0.00048828125 0.001074218750001854 +0.4671250000000001 -0.00048828125 0.001074218750001854 +0.46725 -0.00048828125 0.001074218750001854 +0.467375 -0.00048828125 0.001074218750001854 +0.4675000000000001 -0.00048828125 0.001074218750001854 +0.467625 -0.00048828125 0.001074218750001854 +0.46775 -0.00048828125 0.001074218750001854 +0.467875 -0.00048828125 0.001074218750001854 +0.4680000000000001 -0.00048828125 0.001074218750001854 +0.468125 -0.00048828125 0.001074218750001854 +0.46825 -0.00048828125 0.001074218750001854 +0.468375 -0.00048828125 0.001074218750001854 +0.4685 -0.00048828125 0.001074218750001854 +0.468625 -0.00048828125 0.001074218750001854 +0.46875 -0.00048828125 0.001074218750001854 +0.468875 -0.00048828125 0.001074218750001854 +0.469 -0.00048828125 0.001074218750001854 +0.469125 -0.00048828125 0.001074218750001854 +0.46925 -0.00048828125 0.001074218750001854 +0.469375 -0.00048828125 0.001074218750001854 +0.4695 -0.00048828125 0.001074218750001854 +0.469625 -0.00048828125 0.001074218750001854 +0.46975 -0.00048828125 0.001074218750001854 +0.469875 -0.00048828125 0.001074218750001854 +0.47 -0.00048828125 0.001074218750001854 +0.470125 -0.00048828125 0.001074218750001854 +0.47025 -0.00048828125 0.001074218750001854 +0.4703749999999999 -0.00048828125 0.001074218750001854 +0.4705 -0.00048828125 0.001074218750001854 +0.470625 -0.00048828125 0.001074218750001854 +0.47075 -0.00048828125 0.001074218750001854 +0.470875 -0.00048828125 0.001074218750001854 +0.471 -0.00048828125 0.001074218750001854 +0.471125 -0.00048828125 0.001074218750001854 +0.47125 -0.00048828125 0.001074218750001854 +0.471375 -0.00048828125 0.001074218750001854 +0.4715 -0.00048828125 0.001074218750001854 +0.471625 -0.00048828125 0.001074218750001854 +0.47175 -0.00048828125 0.001074218750001854 +0.471875 -0.00048828125 0.001074218750001854 +0.4720000000000001 -0.00048828125 0.001074218750001854 +0.472125 -0.00048828125 0.001074218750001854 +0.47225 -0.00048828125 0.001074218750001854 +0.472375 -0.00048828125 0.001074218750001854 +0.4725000000000001 -0.00048828125 0.001074218750001854 +0.472625 -0.00048828125 0.001074218750001854 +0.47275 -0.00048828125 0.001074218750001854 +0.472875 -0.00048828125 0.001074218750001854 +0.473 -0.00048828125 0.001074218750001854 +0.473125 -0.00048828125 0.001074218750001854 +0.47325 -0.00048828125 0.001074218750001854 +0.473375 -0.00048828125 0.001074218750001854 +0.4735 -0.00048828125 0.001074218750001854 +0.473625 -0.00048828125 0.001074218750001854 +0.47375 -0.00048828125 0.001074218750001854 +0.473875 -0.00048828125 0.001074218750001854 +0.474 -0.00048828125 0.001074218750001854 +0.474125 -0.00048828125 0.001074218750001854 +0.47425 -0.00048828125 0.001074218750001854 +0.474375 -0.00048828125 0.001074218750001854 +0.4745 -0.00048828125 0.001074218750001854 +0.474625 -0.00048828125 0.001074218750001854 +0.47475 -0.00048828125 0.001074218750001854 +0.474875 -0.00048828125 0.001074218750001854 +0.475 -0.00048828125 0.001074218750001854 +0.4751250000000001 -0.00048828125 0.001074218750001854 +0.47525 -0.00048828125 0.001074218750001854 +0.475375 -0.00048828125 0.001074218750001854 +0.4755000000000001 -0.000457763671875 0.001074218750001854 +0.4756250000000001 -0.000457763671875 0.001074218750001854 +0.47575 -0.000457763671875 0.001074218750001854 +0.475875 -0.000457763671875 0.001074218750001854 +0.4760000000000001 -0.000457763671875 0.001074218750001854 +0.476125 -0.000457763671875 0.001074218750001854 +0.47625 -0.000457763671875 0.001074218750001854 +0.476375 -0.000457763671875 0.001074218750001854 +0.4765000000000001 -0.000457763671875 0.001074218750001854 +0.476625 -0.000457763671875 0.001074218750001854 +0.47675 -0.000457763671875 0.001074218750001854 +0.476875 -0.000457763671875 0.001074218750001854 +0.477 -0.000457763671875 0.001074218750001854 +0.477125 -0.000457763671875 0.001074218750001854 +0.47725 -0.000457763671875 0.001074218750001854 +0.477375 -0.000457763671875 0.001074218750001854 +0.4775 -0.000457763671875 0.001074218750001854 +0.477625 -0.000457763671875 0.001074218750001854 +0.47775 -0.000457763671875 0.001074218750001854 +0.477875 -0.000457763671875 0.001074218750001854 +0.478 -0.000457763671875 0.001074218750001854 +0.478125 -0.000457763671875 0.001074218750001854 +0.47825 -0.000457763671875 0.001074218750001854 +0.478375 -0.000457763671875 0.001074218750001854 +0.4785 -0.00042724609375 0.001074218750001854 +0.478625 -0.00042724609375 0.001074218750001854 +0.47875 -0.00042724609375 0.001074218750001854 +0.478875 -0.00042724609375 0.001074218750001854 +0.479 -0.00042724609375 0.001074218750001854 +0.479125 -0.00042724609375 0.001074218750001854 +0.47925 -0.00042724609375 0.001074218750001854 +0.479375 -0.00042724609375 0.001074218750001854 +0.4795 -0.00042724609375 0.001074218750001854 +0.4796250000000001 -0.00042724609375 0.001074218750001854 +0.47975 -0.00042724609375 0.001074218750001854 +0.479875 -0.00042724609375 0.001074218750001854 +0.48 -0.1351318359375 0.3201562500000024 +0.480125 -0.13421630859375 0.3201562500000024 +0.48025 -0.13421630859375 0.3201562500000024 +0.480375 -0.13330078125 0.3201562500000024 +0.4805 -0.132354736328125 0.3201562500000024 +0.480625 -0.132354736328125 0.3201562500000024 +0.48075 -0.13140869140625 0.3201562500000024 +0.480875 -0.13140869140625 0.3201562500000024 +0.481 -0.130462646484375 0.3201562500000024 +0.481125 -0.129486083984375 0.3201562500000024 +0.48125 -0.129486083984375 0.3201562500000024 +0.481375 -0.12847900390625 0.3201562500000024 +0.4815 -0.12847900390625 0.3201562500000024 +0.481625 -0.127471923828125 0.3201562500000024 +0.48175 -0.12646484375 0.3201562500000024 +0.481875 -0.12646484375 0.3201562500000024 +0.482 -0.12542724609375 0.3201562500000024 +0.482125 -0.12542724609375 0.3201562500000024 +0.48225 -0.124359130859375 0.3201562500000024 +0.482375 -0.123321533203125 0.3201562500000024 +0.4825 -0.123321533203125 0.3201562500000024 +0.482625 -0.122222900390625 0.3201562500000024 +0.4827500000000001 -0.122222900390625 0.3201562500000024 +0.482875 -0.12115478515625 0.3201562500000024 +0.483 -0.12005615234375 0.3201562500000024 +0.4831250000000001 -0.12005615234375 0.3201562500000024 +0.48325 -0.118927001953125 0.3201562500000024 +0.483375 -0.118927001953125 0.3201562500000024 +0.4835 -0.1177978515625 0.3201562500000024 +0.4836250000000001 -0.116668701171875 0.3201562500000024 +0.48375 -0.116668701171875 0.3201562500000024 +0.483875 -0.115509033203125 0.3201562500000024 +0.484 -0.115509033203125 0.3201562500000024 +0.484125 -0.114349365234375 0.3201562500000024 +0.48425 -0.1131591796875 0.3201562500000024 +0.484375 -0.1131591796875 0.3201562500000024 +0.4845 -0.111968994140625 0.3201562500000024 +0.484625 -0.111968994140625 0.3201562500000024 +0.48475 -0.11077880859375 0.3201562500000024 +0.484875 -0.10955810546875 0.3201562500000024 +0.485 -0.10955810546875 0.3201562500000024 +0.485125 -0.10833740234375 0.3201562500000024 +0.48525 -0.10833740234375 0.3201562500000024 +0.485375 -0.107086181640625 0.3201562500000024 +0.4855 -0.1058349609375 0.3201562500000024 +0.485625 -0.1058349609375 0.3201562500000024 +0.48575 -0.10455322265625 0.3201562500000024 +0.485875 -0.10455322265625 0.3201562500000024 +0.4859999999999999 -0.103302001953125 0.3201562500000024 +0.486125 -0.102020263671875 0.3201562500000024 +0.48625 -0.102020263671875 0.3201562500000024 +0.486375 -0.1007080078125 0.3201562500000024 +0.4865 -0.1007080078125 0.3201562500000024 +0.486625 -0.099395751953125 0.3201562500000024 +0.48675 -0.09808349609375 0.3201562500000024 +0.486875 -0.09808349609375 0.3201562500000024 +0.487 -0.09674072265625 0.3201562500000024 +0.487125 -0.09674072265625 0.3201562500000024 +0.48725 -0.095428466796875 0.3201562500000024 +0.487375 -0.09405517578125 0.3201562500000024 +0.4875 -0.09405517578125 0.3201562500000024 +0.4876250000000001 -0.09271240234375 0.3201562500000024 +0.48775 -0.09271240234375 0.3201562500000024 +0.487875 -0.091339111328125 0.3201562500000024 +0.488 -0.089935302734375 0.3201562500000024 +0.4881250000000001 -0.089935302734375 0.3201562500000024 +0.48825 -0.08856201171875 0.3201562500000024 +0.488375 -0.08856201171875 0.3201562500000024 +0.4885 -0.087158203125 0.3201562500000024 +0.488625 -0.08575439453125 0.3201562500000024 +0.48875 -0.08575439453125 0.3201562500000024 +0.488875 -0.084320068359375 0.3201562500000024 +0.489 -0.084320068359375 0.3201562500000024 +0.489125 -0.0828857421875 0.3201562500000024 +0.48925 -0.081451416015625 0.3201562500000024 +0.489375 -0.081451416015625 0.3201562500000024 +0.4895 -0.08001708984375 0.3201562500000024 +0.489625 -0.08001708984375 0.3201562500000024 +0.48975 -0.07855224609375 0.3201562500000024 +0.489875 -0.07708740234375 0.3201562500000024 +0.49 -0.07708740234375 0.3201562500000024 +0.490125 -0.07562255859375 0.3201562500000024 +0.49025 -0.07562255859375 0.3201562500000024 +0.490375 -0.074127197265625 0.3201562500000024 +0.4905 -0.0726318359375 0.3201562500000024 +0.490625 -0.0726318359375 0.3201562500000024 +0.4907500000000001 -0.071136474609375 0.3201562500000024 +0.490875 -0.071136474609375 0.3201562500000024 +0.491 -0.06964111328125 0.3201562500000024 +0.4911250000000001 -0.068145751953125 0.3201562500000024 +0.4912500000000001 -0.068145751953125 0.3201562500000024 +0.491375 -0.066619873046875 0.3201562500000024 +0.4915 -0.066619873046875 0.3201562500000024 +0.4916250000000001 -0.065093994140625 0.3201562500000024 +0.49175 -0.06353759765625 0.3201562500000024 +0.491875 -0.06353759765625 0.3201562500000024 +0.492 -0.06201171875 0.3201562500000024 +0.4921250000000001 -0.06201171875 0.3201562500000024 +0.49225 -0.060455322265625 0.3201562500000024 +0.492375 -0.05889892578125 0.3201562500000024 +0.4925 -0.05889892578125 0.3201562500000024 +0.492625 -0.057342529296875 0.3201562500000024 +0.49275 -0.057342529296875 0.3201562500000024 +0.492875 -0.0557861328125 0.3201562500000024 +0.493 -0.05419921875 0.3201562500000024 +0.493125 -0.05419921875 0.3201562500000024 +0.49325 -0.0526123046875 0.3201562500000024 +0.493375 -0.0526123046875 0.3201562500000024 +0.4935 -0.051025390625 0.3201562500000024 +0.493625 -0.0494384765625 0.3201562500000024 +0.49375 -0.0494384765625 0.3201562500000024 +0.493875 -0.0478515625 0.3201562500000024 +0.494 -0.0478515625 0.3201562500000024 +0.494125 -0.046234130859375 0.3201562500000024 +0.49425 -0.044647216796875 0.3201562500000024 +0.494375 -0.044647216796875 0.3201562500000024 +0.4945 -0.04302978515625 0.3201562500000024 +0.494625 -0.04302978515625 0.3201562500000024 +0.49475 -0.041412353515625 0.3201562500000024 +0.494875 -0.039794921875 0.3201562500000024 +0.495 -0.039794921875 0.3201562500000024 +0.495125 -0.038177490234375 0.3201562500000024 +0.4952500000000001 -0.038177490234375 0.3201562500000024 +0.495375 -0.036529541015625 0.3201562500000024 +0.4955 -0.034881591796875 0.3201562500000024 +0.4956250000000001 -0.034881591796875 0.3201562500000024 +0.49575 -0.03326416015625 0.3201562500000024 +0.495875 -0.03326416015625 0.3201562500000024 +0.496 -0.0316162109375 0.3201562500000024 +0.496125 -0.02996826171875 0.3201562500000024 +0.49625 -0.02996826171875 0.3201562500000024 +0.496375 -0.0283203125 0.3201562500000024 +0.4965 -0.0283203125 0.3201562500000024 +0.496625 -0.02667236328125 0.3201562500000024 +0.49675 -0.0250244140625 0.3201562500000024 +0.496875 -0.0250244140625 0.3201562500000024 +0.497 -0.02337646484375 0.3201562500000024 +0.497125 -0.02337646484375 0.3201562500000024 +0.49725 -0.021697998046875 0.3201562500000024 +0.497375 -0.020050048828125 0.3201562500000024 +0.4975 -0.020050048828125 0.3201562500000024 +0.497625 -0.01837158203125 0.3201562500000024 +0.49775 -0.01837158203125 0.3201562500000024 +0.497875 -0.0167236328125 0.3201562500000024 +0.498 -0.015045166015625 0.3201562500000024 +0.498125 -0.015045166015625 0.3201562500000024 +0.49825 -0.01336669921875 0.3201562500000024 +0.4983750000000001 -0.01336669921875 0.3201562500000024 +0.4985 -0.011688232421875 0.3201562500000024 +0.498625 -0.010040283203125 0.3201562500000024 +0.4987500000000001 -0.010040283203125 0.3201562500000024 +0.498875 -0.00836181640625 0.3201562500000024 +0.499 -0.00836181640625 0.3201562500000024 +0.499125 -0.006683349609375 0.3201562500000024 +0.4992500000000001 -0.0050048828125 0.3201562500000024 +0.499375 -0.0050048828125 0.3201562500000024 +0.4995 -0.003326416015625 0.3201562500000024 +0.499625 -0.003326416015625 0.3201562500000024 +0.49975 -0.00164794921875 0.3201562500000024 0.499875 0.0 0.3201562500000024 0.5 0.0 0.3201562500000024 0.5001250000000001 0.00164794921875 0.3201562500000024 @@ -4499,504 +4499,504 @@ 0.56225 0.00445556640625 0.8530371093750013 0.5623749999999999 0.0 0.8530371093750013 0.5625 0.0 0.8530371093750013 -0.5626250000000001 -0.004486083984375 0.8530371093750013 -0.56275 -0.004486083984375 0.8530371093750013 -0.562875 -0.008941650390625 0.8530371093750013 -0.5630000000000001 -0.013397216796875 0.8530371093750013 -0.563125 -0.013397216796875 0.8530371093750013 -0.56325 -0.01788330078125 0.8530371093750013 -0.5633749999999999 -0.01788330078125 0.8530371093750013 -0.5635 -0.0223388671875 0.8530371093750013 -0.563625 -0.02679443359375 0.8530371093750013 -0.5637499999999999 -0.02679443359375 0.8530371093750013 -0.563875 -0.03125 0.8530371093750013 -0.5640000000000001 -0.03125 0.8530371093750013 -0.5641249999999999 -0.03570556640625 0.8530371093750013 -0.56425 -0.040130615234375 0.8530371093750013 -0.564375 -0.040130615234375 0.8530371093750013 -0.5645 -0.044586181640625 0.8530371093750013 -0.564625 -0.044586181640625 0.8530371093750013 -0.56475 -0.049041748046875 0.8530371093750013 -0.564875 -0.053466796875 0.8530371093750013 -0.565 -0.053466796875 0.8530371093750013 -0.565125 -0.057891845703125 0.8530371093750013 -0.56525 -0.057891845703125 0.8530371093750013 -0.565375 -0.06231689453125 0.8530371093750013 -0.5655 -0.06671142578125 0.8530371093750013 -0.565625 -0.06671142578125 0.8530371093750013 -0.56575 -0.071136474609375 0.8530371093750013 -0.565875 -0.071136474609375 0.8530371093750013 -0.566 -0.075531005859375 0.8530371093750013 -0.566125 -0.079925537109375 0.8530371093750013 -0.5662500000000001 -0.079925537109375 0.8530371093750013 -0.5663749999999999 -0.084320068359375 0.8530371093750013 -0.5665 -0.084320068359375 0.8530371093750013 -0.5666250000000001 -0.08868408203125 0.8530371093750013 -0.56675 -0.093048095703125 0.8530371093750013 -0.566875 -0.093048095703125 0.8530371093750013 -0.5670000000000001 -0.097412109375 0.8530371093750013 -0.567125 -0.097412109375 0.8530371093750013 -0.56725 -0.10174560546875 0.8530371093750013 -0.567375 -0.1060791015625 0.8530371093750013 -0.5675 -0.1060791015625 0.8530371093750013 -0.567625 -0.110382080078125 0.8530371093750013 -0.56775 -0.110382080078125 0.8530371093750013 -0.567875 -0.11468505859375 0.8530371093750013 -0.5680000000000001 -0.118988037109375 0.8530371093750013 -0.568125 -0.118988037109375 0.8530371093750013 -0.56825 -0.123260498046875 0.8530371093750013 -0.568375 -0.123260498046875 0.8530371093750013 -0.5685 -0.127532958984375 0.8530371093750013 -0.568625 -0.131805419921875 0.8530371093750013 -0.56875 -0.131805419921875 0.8530371093750013 -0.5688750000000001 -0.13604736328125 0.8530371093750013 -0.569 -0.13604736328125 0.8530371093750013 -0.569125 -0.1402587890625 0.8530371093750013 -0.5692500000000001 -0.14447021484375 0.8530371093750013 -0.569375 -0.14447021484375 0.8530371093750013 -0.5695 -0.148681640625 0.8530371093750013 -0.5696250000000001 -0.148681640625 0.8530371093750013 -0.56975 -0.15283203125 0.8530371093750013 -0.569875 -0.157012939453125 0.8530371093750013 -0.5700000000000001 -0.157012939453125 0.8530371093750013 -0.570125 -0.161163330078125 0.8530371093750013 -0.5702500000000001 -0.161163330078125 0.8530371093750013 -0.5703749999999999 -0.165283203125 0.8530371093750013 -0.5705 -0.169403076171875 0.8530371093750013 -0.5706250000000001 -0.169403076171875 0.8530371093750013 -0.57075 -0.1734619140625 0.8530371093750013 -0.570875 -0.1734619140625 0.8530371093750013 -0.5710000000000001 -0.17755126953125 0.8530371093750013 -0.571125 -0.181610107421875 0.8530371093750013 -0.57125 -0.181610107421875 0.8530371093750013 -0.5713749999999999 -0.185638427734375 0.8530371093750013 -0.5715 -0.185638427734375 0.8530371093750013 -0.571625 -0.18963623046875 0.8530371093750013 -0.5717499999999999 -0.193634033203125 0.8530371093750013 -0.571875 -0.193634033203125 0.8530371093750013 -0.5720000000000001 -0.197601318359375 0.8530371093750013 -0.572125 -0.197601318359375 0.8530371093750013 -0.57225 -0.2015380859375 0.8530371093750013 -0.572375 -0.205474853515625 0.8530371093750013 -0.5725 -0.205474853515625 0.8530371093750013 -0.572625 -0.209381103515625 0.8530371093750013 -0.57275 -0.209381103515625 0.8530371093750013 -0.572875 -0.2132568359375 0.8530371093750013 -0.573 -0.21710205078125 0.8530371093750013 -0.573125 -0.21710205078125 0.8530371093750013 -0.57325 -0.220947265625 0.8530371093750013 -0.573375 -0.220947265625 0.8530371093750013 -0.5735 -0.2247314453125 0.8530371093750013 -0.573625 -0.228546142578125 0.8530371093750013 -0.57375 -0.228546142578125 0.8530371093750013 -0.573875 -0.2322998046875 0.8530371093750013 -0.574 -0.2322998046875 0.8530371093750013 -0.574125 -0.23602294921875 0.8530371093750013 -0.5742500000000001 -0.239715576171875 0.8530371093750013 -0.5743749999999999 -0.239715576171875 0.8530371093750013 -0.5745 -0.243408203125 0.8530371093750013 -0.5746250000000001 -0.243408203125 0.8530371093750013 -0.57475 -0.2470703125 0.8530371093750013 -0.574875 -0.25067138671875 0.8530371093750013 -0.5750000000000001 -0.25067138671875 0.8530371093750013 -0.575125 -0.254302978515625 0.8530371093750013 -0.57525 -0.254302978515625 0.8530371093750013 -0.575375 -0.257843017578125 0.8530371093750013 -0.5755 -0.26141357421875 0.8530371093750013 -0.5756250000000001 -0.26141357421875 0.8530371093750013 -0.57575 -0.264923095703125 0.8530371093750013 -0.575875 -0.264923095703125 0.8530371093750013 -0.5760000000000001 -0.30889892578125 0.9817578125000006 -0.576125 -0.312896728515625 0.9817578125000006 -0.57625 -0.312896728515625 0.9817578125000006 -0.576375 -0.31683349609375 0.9817578125000006 -0.5765000000000001 -0.31683349609375 0.9817578125000006 -0.576625 -0.32073974609375 0.9817578125000006 -0.57675 -0.324615478515625 0.9817578125000006 -0.5768750000000001 -0.324615478515625 0.9817578125000006 -0.577 -0.328460693359375 0.9817578125000006 -0.577125 -0.328460693359375 0.9817578125000006 -0.5772500000000001 -0.332244873046875 0.9817578125000006 -0.577375 -0.33599853515625 0.9817578125000006 -0.5775 -0.33599853515625 0.9817578125000006 -0.5776250000000001 -0.339752197265625 0.9817578125000006 -0.57775 -0.339752197265625 0.9817578125000006 -0.577875 -0.343414306640625 0.9817578125000006 -0.5779999999999999 -0.347076416015625 0.9817578125000006 -0.578125 -0.347076416015625 0.9817578125000006 -0.5782500000000001 -0.3507080078125 0.9817578125000006 -0.578375 -0.3507080078125 0.9817578125000006 -0.5785 -0.354278564453125 0.9817578125000006 -0.5786250000000001 -0.357818603515625 0.9817578125000006 -0.57875 -0.357818603515625 0.9817578125000006 -0.578875 -0.361328125 0.9817578125000006 -0.5789999999999999 -0.361328125 0.9817578125000006 -0.579125 -0.364776611328125 0.9817578125000006 -0.57925 -0.368194580078125 0.9817578125000006 -0.5793749999999999 -0.368194580078125 0.9817578125000006 -0.5795 -0.37158203125 0.9817578125000006 -0.5796250000000001 -0.37158203125 0.9817578125000006 -0.5797499999999999 -0.374908447265625 0.9817578125000006 -0.579875 -0.378204345703125 0.9817578125000006 -0.58 -0.378204345703125 0.9817578125000006 -0.580125 -0.3814697265625 0.9817578125000006 -0.58025 -0.3814697265625 0.9817578125000006 -0.580375 -0.384674072265625 0.9817578125000006 -0.5805 -0.387847900390625 0.9817578125000006 -0.580625 -0.387847900390625 0.9817578125000006 -0.58075 -0.390960693359375 0.9817578125000006 -0.580875 -0.390960693359375 0.9817578125000006 -0.581 -0.394073486328125 0.9817578125000006 -0.581125 -0.397125244140625 0.9817578125000006 -0.58125 -0.397125244140625 0.9817578125000006 -0.581375 -0.400115966796875 0.9817578125000006 -0.5815 -0.400115966796875 0.9817578125000006 -0.581625 -0.403076171875 0.9817578125000006 -0.58175 -0.405975341796875 0.9817578125000006 -0.5818750000000001 -0.405975341796875 0.9817578125000006 -0.5819999999999999 -0.408843994140625 0.9817578125000006 -0.582125 -0.408843994140625 0.9817578125000006 -0.5822500000000001 -0.411651611328125 0.9817578125000006 -0.582375 -0.414459228515625 0.9817578125000006 -0.5825 -0.414459228515625 0.9817578125000006 -0.5826250000000001 -0.41717529296875 0.9817578125000006 -0.58275 -0.41717529296875 0.9817578125000006 -0.582875 -0.41986083984375 0.9817578125000006 -0.583 -0.4224853515625 0.9817578125000006 -0.583125 -0.4224853515625 0.9817578125000006 -0.58325 -0.42510986328125 0.9817578125000006 -0.583375 -0.42510986328125 0.9817578125000006 -0.5835 -0.427642822265625 0.9817578125000006 -0.5836250000000001 -0.430145263671875 0.9817578125000006 -0.58375 -0.430145263671875 0.9817578125000006 -0.583875 -0.432586669921875 0.9817578125000006 -0.584 -0.432586669921875 0.9817578125000006 -0.584125 -0.43499755859375 0.9817578125000006 -0.58425 -0.437347412109375 0.9817578125000006 -0.584375 -0.437347412109375 0.9817578125000006 -0.5845000000000001 -0.439666748046875 0.9817578125000006 -0.584625 -0.439666748046875 0.9817578125000006 -0.58475 -0.441925048828125 0.9817578125000006 -0.5848750000000001 -0.44415283203125 0.9817578125000006 -0.585 -0.44415283203125 0.9817578125000006 -0.585125 -0.4462890625 0.9817578125000006 -0.5852500000000001 -0.4462890625 0.9817578125000006 -0.585375 -0.44842529296875 0.9817578125000006 -0.5855 -0.45050048828125 0.9817578125000006 -0.5856250000000001 -0.45050048828125 0.9817578125000006 -0.58575 -0.452484130859375 0.9817578125000006 -0.5858750000000001 -0.452484130859375 0.9817578125000006 -0.5859999999999999 -0.4544677734375 0.9817578125000006 -0.586125 -0.456390380859375 0.9817578125000006 -0.5862500000000001 -0.456390380859375 0.9817578125000006 -0.586375 -0.458251953125 0.9817578125000006 -0.5865 -0.458251953125 0.9817578125000006 -0.5866250000000001 -0.460052490234375 0.9817578125000006 -0.58675 -0.461822509765625 0.9817578125000006 -0.586875 -0.461822509765625 0.9817578125000006 -0.5869999999999999 -0.46356201171875 0.9817578125000006 -0.587125 -0.46356201171875 0.9817578125000006 -0.58725 -0.4652099609375 0.9817578125000006 -0.5873749999999999 -0.466827392578125 0.9817578125000006 -0.5875 -0.466827392578125 0.9817578125000006 -0.5876250000000001 -0.4683837890625 0.9817578125000006 -0.58775 -0.4683837890625 0.9817578125000006 -0.587875 -0.46990966796875 0.9817578125000006 -0.588 -0.471343994140625 0.9817578125000006 -0.588125 -0.471343994140625 0.9817578125000006 -0.58825 -0.4727783203125 0.9817578125000006 -0.588375 -0.4727783203125 0.9817578125000006 -0.5885 -0.47412109375 0.9817578125000006 -0.588625 -0.475433349609375 0.9817578125000006 -0.58875 -0.475433349609375 0.9817578125000006 -0.588875 -0.4766845703125 0.9817578125000006 -0.589 -0.4766845703125 0.9817578125000006 -0.589125 -0.477874755859375 0.9817578125000006 -0.58925 -0.479034423828125 0.9817578125000006 -0.589375 -0.479034423828125 0.9817578125000006 -0.5895 -0.480133056640625 0.9817578125000006 -0.589625 -0.480133056640625 0.9817578125000006 -0.58975 -0.481170654296875 0.9817578125000006 -0.5898750000000001 -0.482147216796875 0.9817578125000006 -0.5899999999999999 -0.482147216796875 0.9817578125000006 -0.590125 -0.48309326171875 0.9817578125000006 -0.5902500000000001 -0.48309326171875 0.9817578125000006 -0.590375 -0.483978271484375 0.9817578125000006 -0.5905 -0.48480224609375 0.9817578125000006 -0.5906250000000001 -0.48480224609375 0.9817578125000006 -0.59075 -0.485595703125 0.9817578125000006 -0.590875 -0.485595703125 0.9817578125000006 -0.591 -0.486297607421875 0.9817578125000006 -0.591125 -0.486968994140625 0.9817578125000006 -0.5912500000000001 -0.486968994140625 0.9817578125000006 -0.591375 -0.48760986328125 0.9817578125000006 -0.5915 -0.48760986328125 0.9817578125000006 -0.5916250000000001 -0.4881591796875 0.9817578125000006 -0.59175 -0.488677978515625 0.9817578125000006 -0.591875 -0.488677978515625 0.9817578125000006 -0.592 -0.4891357421875 0.9817578125000006 -0.5921250000000001 -0.4891357421875 0.9817578125000006 -0.59225 -0.489532470703125 0.9817578125000006 -0.592375 -0.489898681640625 0.9817578125000006 -0.5925000000000001 -0.489898681640625 0.9817578125000006 -0.592625 -0.49017333984375 0.9817578125000006 -0.59275 -0.49017333984375 0.9817578125000006 -0.5928750000000001 -0.49041748046875 0.9817578125000006 -0.593 -0.4906005859375 0.9817578125000006 -0.593125 -0.4906005859375 0.9817578125000006 -0.5932500000000001 -0.490753173828125 0.9817578125000006 -0.593375 -0.490753173828125 0.9817578125000006 -0.5935 -0.4908447265625 0.9817578125000006 -0.5936249999999999 -0.490875244140625 0.9817578125000006 -0.59375 -0.490875244140625 0.9817578125000006 -0.5938750000000001 -0.4908447265625 0.9817578125000006 -0.594 -0.4908447265625 0.9817578125000006 -0.594125 -0.490753173828125 0.9817578125000006 -0.5942500000000001 -0.4906005859375 0.9817578125000006 -0.594375 -0.4906005859375 0.9817578125000006 -0.5945 -0.49041748046875 0.9817578125000006 -0.5946249999999999 -0.49041748046875 0.9817578125000006 -0.59475 -0.49017333984375 0.9817578125000006 -0.594875 -0.489898681640625 0.9817578125000006 -0.5949999999999999 -0.489898681640625 0.9817578125000006 -0.595125 -0.489532470703125 0.9817578125000006 -0.5952500000000001 -0.489532470703125 0.9817578125000006 -0.5953749999999999 -0.4891357421875 0.9817578125000006 -0.5955 -0.488677978515625 0.9817578125000006 -0.595625 -0.488677978515625 0.9817578125000006 -0.59575 -0.4881591796875 0.9817578125000006 -0.595875 -0.4881591796875 0.9817578125000006 -0.596 -0.48760986328125 0.9817578125000006 -0.596125 -0.486968994140625 0.9817578125000006 -0.59625 -0.486968994140625 0.9817578125000006 -0.596375 -0.486297607421875 0.9817578125000006 -0.5965 -0.486297607421875 0.9817578125000006 -0.596625 -0.485595703125 0.9817578125000006 -0.59675 -0.48480224609375 0.9817578125000006 -0.596875 -0.48480224609375 0.9817578125000006 -0.597 -0.483978271484375 0.9817578125000006 -0.597125 -0.483978271484375 0.9817578125000006 -0.59725 -0.48309326171875 0.9817578125000006 -0.597375 -0.482147216796875 0.9817578125000006 -0.5975000000000001 -0.482147216796875 0.9817578125000006 -0.5976249999999999 -0.481170654296875 0.9817578125000006 -0.59775 -0.481170654296875 0.9817578125000006 -0.5978750000000001 -0.480133056640625 0.9817578125000006 -0.598 -0.479034423828125 0.9817578125000006 -0.598125 -0.479034423828125 0.9817578125000006 -0.5982500000000001 -0.477874755859375 0.9817578125000006 -0.598375 -0.477874755859375 0.9817578125000006 -0.5985 -0.4766845703125 0.9817578125000006 -0.598625 -0.475433349609375 0.9817578125000006 -0.59875 -0.475433349609375 0.9817578125000006 -0.598875 -0.47412109375 0.9817578125000006 -0.599 -0.47412109375 0.9817578125000006 -0.599125 -0.4727783203125 0.9817578125000006 -0.5992500000000001 -0.471343994140625 0.9817578125000006 -0.599375 -0.471343994140625 0.9817578125000006 -0.5995 -0.46990966796875 0.9817578125000006 -0.599625 -0.46990966796875 0.9817578125000006 -0.59975 -0.4683837890625 0.9817578125000006 -0.599875 -0.466827392578125 0.9817578125000006 -0.6 -0.466827392578125 0.9817578125000006 -0.6001250000000001 -0.4652099609375 0.9817578125000006 -0.60025 -0.4652099609375 0.9817578125000006 -0.600375 -0.46356201171875 0.9817578125000006 -0.6005000000000001 -0.461822509765625 0.9817578125000006 -0.600625 -0.461822509765625 0.9817578125000006 -0.60075 -0.460052490234375 0.9817578125000006 -0.6008750000000001 -0.460052490234375 0.9817578125000006 -0.601 -0.458251953125 0.9817578125000006 -0.601125 -0.456390380859375 0.9817578125000006 -0.6012500000000001 -0.456390380859375 0.9817578125000006 -0.601375 -0.4544677734375 0.9817578125000006 -0.6015000000000001 -0.4544677734375 0.9817578125000006 -0.6016249999999999 -0.452484130859375 0.9817578125000006 -0.60175 -0.45050048828125 0.9817578125000006 -0.6018750000000001 -0.45050048828125 0.9817578125000006 -0.602 -0.44842529296875 0.9817578125000006 -0.602125 -0.44842529296875 0.9817578125000006 -0.6022500000000001 -0.4462890625 0.9817578125000006 -0.602375 -0.44415283203125 0.9817578125000006 -0.6025 -0.44415283203125 0.9817578125000006 -0.6026249999999999 -0.441925048828125 0.9817578125000006 -0.60275 -0.441925048828125 0.9817578125000006 -0.602875 -0.439666748046875 0.9817578125000006 -0.6029999999999999 -0.437347412109375 0.9817578125000006 -0.603125 -0.437347412109375 0.9817578125000006 -0.6032500000000001 -0.43499755859375 0.9817578125000006 -0.603375 -0.43499755859375 0.9817578125000006 -0.6035 -0.432586669921875 0.9817578125000006 -0.603625 -0.430145263671875 0.9817578125000006 -0.60375 -0.430145263671875 0.9817578125000006 -0.603875 -0.427642822265625 0.9817578125000006 -0.604 -0.427642822265625 0.9817578125000006 -0.604125 -0.42510986328125 0.9817578125000006 -0.60425 -0.4224853515625 0.9817578125000006 -0.604375 -0.4224853515625 0.9817578125000006 -0.6045 -0.41986083984375 0.9817578125000006 -0.604625 -0.41986083984375 0.9817578125000006 -0.60475 -0.41717529296875 0.9817578125000006 -0.604875 -0.414459228515625 0.9817578125000006 -0.605 -0.414459228515625 0.9817578125000006 -0.605125 -0.411651611328125 0.9817578125000006 -0.60525 -0.411651611328125 0.9817578125000006 -0.605375 -0.408843994140625 0.9817578125000006 -0.6055000000000001 -0.405975341796875 0.9817578125000006 -0.6056249999999999 -0.405975341796875 0.9817578125000006 -0.60575 -0.403076171875 0.9817578125000006 -0.6058750000000001 -0.403076171875 0.9817578125000006 -0.606 -0.400115966796875 0.9817578125000006 -0.606125 -0.397125244140625 0.9817578125000006 -0.6062500000000001 -0.397125244140625 0.9817578125000006 -0.606375 -0.394073486328125 0.9817578125000006 -0.6065 -0.394073486328125 0.9817578125000006 -0.606625 -0.390960693359375 0.9817578125000006 -0.60675 -0.387847900390625 0.9817578125000006 -0.6068750000000001 -0.387847900390625 0.9817578125000006 -0.607 -0.384674072265625 0.9817578125000006 -0.607125 -0.384674072265625 0.9817578125000006 -0.6072500000000001 -0.3814697265625 0.9817578125000006 -0.607375 -0.378204345703125 0.9817578125000006 -0.6075 -0.378204345703125 0.9817578125000006 -0.607625 -0.374908447265625 0.9817578125000006 -0.6077500000000001 -0.374908447265625 0.9817578125000006 -0.607875 -0.37158203125 0.9817578125000006 -0.608 -0.36968994140625 0.9857910156249996 -0.6081250000000001 -0.36968994140625 0.9857910156249996 -0.60825 -0.36627197265625 0.9857910156249996 -0.608375 -0.36627197265625 0.9857910156249996 -0.6085000000000001 -0.36279296875 0.9857910156249996 -0.608625 -0.359283447265625 0.9857910156249996 -0.60875 -0.359283447265625 0.9857910156249996 -0.6088750000000001 -0.355712890625 0.9857910156249996 -0.609 -0.355712890625 0.9857910156249996 -0.609125 -0.352142333984375 0.9857910156249996 -0.6092499999999999 -0.3485107421875 0.9857910156249996 -0.609375 -0.3485107421875 0.9857910156249996 -0.6095000000000001 -0.3448486328125 0.9857910156249996 -0.609625 -0.3448486328125 0.9857910156249996 -0.60975 -0.34112548828125 0.9857910156249996 -0.6098750000000001 -0.33740234375 0.9857910156249996 -0.61 -0.33740234375 0.9857910156249996 -0.610125 -0.3336181640625 0.9857910156249996 -0.6102499999999999 -0.3336181640625 0.9857910156249996 -0.610375 -0.329803466796875 0.9857910156249996 -0.6105 -0.325958251953125 0.9857910156249996 -0.6106249999999999 -0.325958251953125 0.9857910156249996 -0.61075 -0.322052001953125 0.9857910156249996 -0.6108750000000001 -0.322052001953125 0.9857910156249996 -0.6109999999999999 -0.318115234375 0.9857910156249996 -0.611125 -0.314178466796875 0.9857910156249996 -0.61125 -0.314178466796875 0.9857910156249996 -0.611375 -0.3101806640625 0.9857910156249996 -0.6115 -0.3101806640625 0.9857910156249996 -0.611625 -0.30615234375 0.9857910156249996 -0.61175 -0.302093505859375 0.9857910156249996 -0.611875 -0.302093505859375 0.9857910156249996 -0.612 -0.2979736328125 0.9857910156249996 -0.612125 -0.2979736328125 0.9857910156249996 -0.61225 -0.293853759765625 0.9857910156249996 -0.612375 -0.289703369140625 0.9857910156249996 -0.6125 -0.289703369140625 0.9857910156249996 -0.612625 -0.2855224609375 0.9857910156249996 -0.61275 -0.2855224609375 0.9857910156249996 -0.612875 -0.281280517578125 0.9857910156249996 -0.613 -0.27703857421875 0.9857910156249996 -0.6131250000000001 -0.27703857421875 0.9857910156249996 -0.6132499999999999 -0.272735595703125 0.9857910156249996 -0.613375 -0.272735595703125 0.9857910156249996 -0.6135000000000001 -0.2684326171875 0.9857910156249996 -0.613625 -0.26409912109375 0.9857910156249996 -0.61375 -0.26409912109375 0.9857910156249996 -0.6138750000000001 -0.25970458984375 0.9857910156249996 -0.614 -0.25970458984375 0.9857910156249996 -0.614125 -0.255340576171875 0.9857910156249996 -0.61425 -0.250885009765625 0.9857910156249996 -0.614375 -0.250885009765625 0.9857910156249996 -0.6145 -0.246429443359375 0.9857910156249996 -0.614625 -0.246429443359375 0.9857910156249996 -0.61475 -0.241943359375 0.9857910156249996 -0.6148750000000001 -0.237457275390625 0.9857910156249996 -0.615 -0.237457275390625 0.9857910156249996 -0.615125 -0.23291015625 0.9857910156249996 -0.61525 -0.23291015625 0.9857910156249996 -0.615375 -0.22833251953125 0.9857910156249996 -0.6155 -0.2237548828125 0.9857910156249996 -0.615625 -0.2237548828125 0.9857910156249996 -0.6157500000000001 -0.219146728515625 0.9857910156249996 -0.615875 -0.219146728515625 0.9857910156249996 -0.616 -0.214508056640625 0.9857910156249996 -0.6161250000000001 -0.209869384765625 0.9857910156249996 -0.61625 -0.209869384765625 0.9857910156249996 -0.616375 -0.205169677734375 0.9857910156249996 -0.6165000000000001 -0.205169677734375 0.9857910156249996 -0.616625 -0.200469970703125 0.9857910156249996 -0.61675 -0.19573974609375 0.9857910156249996 -0.6168750000000001 -0.19573974609375 0.9857910156249996 -0.617 -0.191009521484375 0.9857910156249996 -0.6171250000000001 -0.191009521484375 0.9857910156249996 -0.6172499999999999 -0.18621826171875 0.9857910156249996 -0.617375 -0.18145751953125 0.9857910156249996 -0.6175000000000001 -0.18145751953125 0.9857910156249996 -0.617625 -0.1766357421875 0.9857910156249996 -0.61775 -0.1766357421875 0.9857910156249996 -0.6178750000000001 -0.17181396484375 0.9857910156249996 -0.618 -0.166961669921875 0.9857910156249996 -0.618125 -0.166961669921875 0.9857910156249996 -0.6182499999999999 -0.162078857421875 0.9857910156249996 -0.618375 -0.162078857421875 0.9857910156249996 -0.6185 -0.1572265625 0.9857910156249996 -0.6186249999999999 -0.152313232421875 0.9857910156249996 -0.61875 -0.152313232421875 0.9857910156249996 -0.6188750000000001 -0.14739990234375 0.9857910156249996 -0.619 -0.14739990234375 0.9857910156249996 -0.619125 -0.1424560546875 0.9857910156249996 -0.61925 -0.13751220703125 0.9857910156249996 -0.619375 -0.13751220703125 0.9857910156249996 -0.6195 -0.132537841796875 0.9857910156249996 -0.619625 -0.132537841796875 0.9857910156249996 -0.61975 -0.1275634765625 0.9857910156249996 -0.619875 -0.12255859375 0.9857910156249996 -0.62 -0.12255859375 0.9857910156249996 -0.620125 -0.117584228515625 0.9857910156249996 -0.62025 -0.117584228515625 0.9857910156249996 -0.620375 -0.112548828125 0.9857910156249996 -0.6205 -0.107513427734375 0.9857910156249996 -0.620625 -0.107513427734375 0.9857910156249996 -0.62075 -0.10247802734375 0.9857910156249996 -0.620875 -0.10247802734375 0.9857910156249996 -0.621 -0.097412109375 0.9857910156249996 -0.6211250000000001 -0.09234619140625 0.9857910156249996 -0.6212499999999999 -0.09234619140625 0.9857910156249996 -0.621375 -0.0872802734375 0.9857910156249996 -0.6215000000000001 -0.0872802734375 0.9857910156249996 -0.621625 -0.08221435546875 0.9857910156249996 -0.62175 -0.07708740234375 0.9857910156249996 -0.6218750000000001 -0.07708740234375 0.9857910156249996 -0.622 -0.071990966796875 0.9857910156249996 -0.622125 -0.071990966796875 0.9857910156249996 -0.62225 -0.06689453125 0.9857910156249996 -0.622375 -0.061767578125 0.9857910156249996 -0.6225000000000001 -0.061767578125 0.9857910156249996 -0.622625 -0.056671142578125 0.9857910156249996 -0.62275 -0.056671142578125 0.9857910156249996 -0.6228750000000001 -0.051544189453125 0.9857910156249996 -0.623 -0.04638671875 0.9857910156249996 -0.623125 -0.04638671875 0.9857910156249996 -0.62325 -0.041229248046875 0.9857910156249996 -0.6233750000000001 -0.041229248046875 0.9857910156249996 -0.6235 -0.036102294921875 0.9857910156249996 -0.623625 -0.03094482421875 0.9857910156249996 -0.6237500000000001 -0.03094482421875 0.9857910156249996 -0.623875 -0.025787353515625 0.9857910156249996 -0.624 -0.025787353515625 0.9857910156249996 -0.6241250000000001 -0.020660400390625 0.9857910156249996 -0.62425 -0.0155029296875 0.9857910156249996 -0.624375 -0.0155029296875 0.9857910156249996 -0.6245000000000001 -0.010345458984375 0.9857910156249996 -0.624625 -0.010345458984375 0.9857910156249996 -0.62475 -0.00518798828125 0.9857910156249996 +0.5626250000000001 -0.00445556640625 0.8530371093750013 +0.56275 -0.00445556640625 0.8530371093750013 +0.562875 -0.0089111328125 0.8530371093750013 +0.5630000000000001 -0.01336669921875 0.8530371093750013 +0.563125 -0.01336669921875 0.8530371093750013 +0.56325 -0.017852783203125 0.8530371093750013 +0.5633749999999999 -0.017852783203125 0.8530371093750013 +0.5635 -0.022308349609375 0.8530371093750013 +0.563625 -0.026763916015625 0.8530371093750013 +0.5637499999999999 -0.026763916015625 0.8530371093750013 +0.563875 -0.031219482421875 0.8530371093750013 +0.5640000000000001 -0.031219482421875 0.8530371093750013 +0.5641249999999999 -0.035675048828125 0.8530371093750013 +0.56425 -0.04010009765625 0.8530371093750013 +0.564375 -0.04010009765625 0.8530371093750013 +0.5645 -0.0445556640625 0.8530371093750013 +0.564625 -0.0445556640625 0.8530371093750013 +0.56475 -0.04901123046875 0.8530371093750013 +0.564875 -0.053436279296875 0.8530371093750013 +0.565 -0.053436279296875 0.8530371093750013 +0.565125 -0.057861328125 0.8530371093750013 +0.56525 -0.057861328125 0.8530371093750013 +0.565375 -0.062286376953125 0.8530371093750013 +0.5655 -0.066680908203125 0.8530371093750013 +0.565625 -0.066680908203125 0.8530371093750013 +0.56575 -0.07110595703125 0.8530371093750013 +0.565875 -0.07110595703125 0.8530371093750013 +0.566 -0.07550048828125 0.8530371093750013 +0.566125 -0.07989501953125 0.8530371093750013 +0.5662500000000001 -0.07989501953125 0.8530371093750013 +0.5663749999999999 -0.08428955078125 0.8530371093750013 +0.5665 -0.08428955078125 0.8530371093750013 +0.5666250000000001 -0.088653564453125 0.8530371093750013 +0.56675 -0.093017578125 0.8530371093750013 +0.566875 -0.093017578125 0.8530371093750013 +0.5670000000000001 -0.097381591796875 0.8530371093750013 +0.567125 -0.097381591796875 0.8530371093750013 +0.56725 -0.101715087890625 0.8530371093750013 +0.567375 -0.106048583984375 0.8530371093750013 +0.5675 -0.106048583984375 0.8530371093750013 +0.567625 -0.1103515625 0.8530371093750013 +0.56775 -0.1103515625 0.8530371093750013 +0.567875 -0.114654541015625 0.8530371093750013 +0.5680000000000001 -0.11895751953125 0.8530371093750013 +0.568125 -0.11895751953125 0.8530371093750013 +0.56825 -0.12322998046875 0.8530371093750013 +0.568375 -0.12322998046875 0.8530371093750013 +0.5685 -0.12750244140625 0.8530371093750013 +0.568625 -0.13177490234375 0.8530371093750013 +0.56875 -0.13177490234375 0.8530371093750013 +0.5688750000000001 -0.136016845703125 0.8530371093750013 +0.569 -0.136016845703125 0.8530371093750013 +0.569125 -0.140228271484375 0.8530371093750013 +0.5692500000000001 -0.144439697265625 0.8530371093750013 +0.569375 -0.144439697265625 0.8530371093750013 +0.5695 -0.148651123046875 0.8530371093750013 +0.5696250000000001 -0.148651123046875 0.8530371093750013 +0.56975 -0.152801513671875 0.8530371093750013 +0.569875 -0.156982421875 0.8530371093750013 +0.5700000000000001 -0.156982421875 0.8530371093750013 +0.570125 -0.1611328125 0.8530371093750013 +0.5702500000000001 -0.1611328125 0.8530371093750013 +0.5703749999999999 -0.165252685546875 0.8530371093750013 +0.5705 -0.16937255859375 0.8530371093750013 +0.5706250000000001 -0.16937255859375 0.8530371093750013 +0.57075 -0.173431396484375 0.8530371093750013 +0.570875 -0.173431396484375 0.8530371093750013 +0.5710000000000001 -0.177520751953125 0.8530371093750013 +0.571125 -0.18157958984375 0.8530371093750013 +0.57125 -0.18157958984375 0.8530371093750013 +0.5713749999999999 -0.18560791015625 0.8530371093750013 +0.5715 -0.18560791015625 0.8530371093750013 +0.571625 -0.189605712890625 0.8530371093750013 +0.5717499999999999 -0.193603515625 0.8530371093750013 +0.571875 -0.193603515625 0.8530371093750013 +0.5720000000000001 -0.19757080078125 0.8530371093750013 +0.572125 -0.19757080078125 0.8530371093750013 +0.57225 -0.201507568359375 0.8530371093750013 +0.572375 -0.2054443359375 0.8530371093750013 +0.5725 -0.2054443359375 0.8530371093750013 +0.572625 -0.2093505859375 0.8530371093750013 +0.57275 -0.2093505859375 0.8530371093750013 +0.572875 -0.213226318359375 0.8530371093750013 +0.573 -0.217071533203125 0.8530371093750013 +0.573125 -0.217071533203125 0.8530371093750013 +0.57325 -0.220916748046875 0.8530371093750013 +0.573375 -0.220916748046875 0.8530371093750013 +0.5735 -0.224700927734375 0.8530371093750013 +0.573625 -0.228515625 0.8530371093750013 +0.57375 -0.228515625 0.8530371093750013 +0.573875 -0.232269287109375 0.8530371093750013 +0.574 -0.232269287109375 0.8530371093750013 +0.574125 -0.235992431640625 0.8530371093750013 +0.5742500000000001 -0.23968505859375 0.8530371093750013 +0.5743749999999999 -0.23968505859375 0.8530371093750013 +0.5745 -0.243377685546875 0.8530371093750013 +0.5746250000000001 -0.243377685546875 0.8530371093750013 +0.57475 -0.247039794921875 0.8530371093750013 +0.574875 -0.250640869140625 0.8530371093750013 +0.5750000000000001 -0.250640869140625 0.8530371093750013 +0.575125 -0.2542724609375 0.8530371093750013 +0.57525 -0.2542724609375 0.8530371093750013 +0.575375 -0.2578125 0.8530371093750013 +0.5755 -0.261383056640625 0.8530371093750013 +0.5756250000000001 -0.261383056640625 0.8530371093750013 +0.57575 -0.264892578125 0.8530371093750013 +0.575875 -0.264892578125 0.8530371093750013 +0.5760000000000001 -0.308868408203125 0.9817578125000006 +0.576125 -0.3128662109375 0.9817578125000006 +0.57625 -0.3128662109375 0.9817578125000006 +0.576375 -0.316802978515625 0.9817578125000006 +0.5765000000000001 -0.316802978515625 0.9817578125000006 +0.576625 -0.320709228515625 0.9817578125000006 +0.57675 -0.3245849609375 0.9817578125000006 +0.5768750000000001 -0.3245849609375 0.9817578125000006 +0.577 -0.32843017578125 0.9817578125000006 +0.577125 -0.32843017578125 0.9817578125000006 +0.5772500000000001 -0.33221435546875 0.9817578125000006 +0.577375 -0.335968017578125 0.9817578125000006 +0.5775 -0.335968017578125 0.9817578125000006 +0.5776250000000001 -0.3397216796875 0.9817578125000006 +0.57775 -0.3397216796875 0.9817578125000006 +0.577875 -0.3433837890625 0.9817578125000006 +0.5779999999999999 -0.3470458984375 0.9817578125000006 +0.578125 -0.3470458984375 0.9817578125000006 +0.5782500000000001 -0.350677490234375 0.9817578125000006 +0.578375 -0.350677490234375 0.9817578125000006 +0.5785 -0.354248046875 0.9817578125000006 +0.5786250000000001 -0.3577880859375 0.9817578125000006 +0.57875 -0.3577880859375 0.9817578125000006 +0.578875 -0.361297607421875 0.9817578125000006 +0.5789999999999999 -0.361297607421875 0.9817578125000006 +0.579125 -0.36474609375 0.9817578125000006 +0.57925 -0.3681640625 0.9817578125000006 +0.5793749999999999 -0.3681640625 0.9817578125000006 +0.5795 -0.371551513671875 0.9817578125000006 +0.5796250000000001 -0.371551513671875 0.9817578125000006 +0.5797499999999999 -0.3748779296875 0.9817578125000006 +0.579875 -0.378173828125 0.9817578125000006 +0.58 -0.378173828125 0.9817578125000006 +0.580125 -0.381439208984375 0.9817578125000006 +0.58025 -0.381439208984375 0.9817578125000006 +0.580375 -0.3846435546875 0.9817578125000006 +0.5805 -0.3878173828125 0.9817578125000006 +0.580625 -0.3878173828125 0.9817578125000006 +0.58075 -0.39093017578125 0.9817578125000006 +0.580875 -0.39093017578125 0.9817578125000006 +0.581 -0.39404296875 0.9817578125000006 +0.581125 -0.3970947265625 0.9817578125000006 +0.58125 -0.3970947265625 0.9817578125000006 +0.581375 -0.40008544921875 0.9817578125000006 +0.5815 -0.40008544921875 0.9817578125000006 +0.581625 -0.403045654296875 0.9817578125000006 +0.58175 -0.40594482421875 0.9817578125000006 +0.5818750000000001 -0.40594482421875 0.9817578125000006 +0.5819999999999999 -0.4088134765625 0.9817578125000006 +0.582125 -0.4088134765625 0.9817578125000006 +0.5822500000000001 -0.41162109375 0.9817578125000006 +0.582375 -0.4144287109375 0.9817578125000006 +0.5825 -0.4144287109375 0.9817578125000006 +0.5826250000000001 -0.417144775390625 0.9817578125000006 +0.58275 -0.417144775390625 0.9817578125000006 +0.582875 -0.419830322265625 0.9817578125000006 +0.583 -0.422454833984375 0.9817578125000006 +0.583125 -0.422454833984375 0.9817578125000006 +0.58325 -0.425079345703125 0.9817578125000006 +0.583375 -0.425079345703125 0.9817578125000006 +0.5835 -0.4276123046875 0.9817578125000006 +0.5836250000000001 -0.43011474609375 0.9817578125000006 +0.58375 -0.43011474609375 0.9817578125000006 +0.583875 -0.43255615234375 0.9817578125000006 +0.584 -0.43255615234375 0.9817578125000006 +0.584125 -0.434967041015625 0.9817578125000006 +0.58425 -0.43731689453125 0.9817578125000006 +0.584375 -0.43731689453125 0.9817578125000006 +0.5845000000000001 -0.43963623046875 0.9817578125000006 +0.584625 -0.43963623046875 0.9817578125000006 +0.58475 -0.44189453125 0.9817578125000006 +0.5848750000000001 -0.444122314453125 0.9817578125000006 +0.585 -0.444122314453125 0.9817578125000006 +0.585125 -0.446258544921875 0.9817578125000006 +0.5852500000000001 -0.446258544921875 0.9817578125000006 +0.585375 -0.448394775390625 0.9817578125000006 +0.5855 -0.450469970703125 0.9817578125000006 +0.5856250000000001 -0.450469970703125 0.9817578125000006 +0.58575 -0.45245361328125 0.9817578125000006 +0.5858750000000001 -0.45245361328125 0.9817578125000006 +0.5859999999999999 -0.454437255859375 0.9817578125000006 +0.586125 -0.45635986328125 0.9817578125000006 +0.5862500000000001 -0.45635986328125 0.9817578125000006 +0.586375 -0.458221435546875 0.9817578125000006 +0.5865 -0.458221435546875 0.9817578125000006 +0.5866250000000001 -0.46002197265625 0.9817578125000006 +0.58675 -0.4617919921875 0.9817578125000006 +0.586875 -0.4617919921875 0.9817578125000006 +0.5869999999999999 -0.463531494140625 0.9817578125000006 +0.587125 -0.463531494140625 0.9817578125000006 +0.58725 -0.465179443359375 0.9817578125000006 +0.5873749999999999 -0.466796875 0.9817578125000006 +0.5875 -0.466796875 0.9817578125000006 +0.5876250000000001 -0.468353271484375 0.9817578125000006 +0.58775 -0.468353271484375 0.9817578125000006 +0.587875 -0.469879150390625 0.9817578125000006 +0.588 -0.4713134765625 0.9817578125000006 +0.588125 -0.4713134765625 0.9817578125000006 +0.58825 -0.472747802734375 0.9817578125000006 +0.588375 -0.472747802734375 0.9817578125000006 +0.5885 -0.474090576171875 0.9817578125000006 +0.588625 -0.47540283203125 0.9817578125000006 +0.58875 -0.47540283203125 0.9817578125000006 +0.588875 -0.476654052734375 0.9817578125000006 +0.589 -0.476654052734375 0.9817578125000006 +0.589125 -0.47784423828125 0.9817578125000006 +0.58925 -0.47900390625 0.9817578125000006 +0.589375 -0.47900390625 0.9817578125000006 +0.5895 -0.4801025390625 0.9817578125000006 +0.589625 -0.4801025390625 0.9817578125000006 +0.58975 -0.48114013671875 0.9817578125000006 +0.5898750000000001 -0.48211669921875 0.9817578125000006 +0.5899999999999999 -0.48211669921875 0.9817578125000006 +0.590125 -0.483062744140625 0.9817578125000006 +0.5902500000000001 -0.483062744140625 0.9817578125000006 +0.590375 -0.48394775390625 0.9817578125000006 +0.5905 -0.484771728515625 0.9817578125000006 +0.5906250000000001 -0.484771728515625 0.9817578125000006 +0.59075 -0.485565185546875 0.9817578125000006 +0.590875 -0.485565185546875 0.9817578125000006 +0.591 -0.48626708984375 0.9817578125000006 +0.591125 -0.4869384765625 0.9817578125000006 +0.5912500000000001 -0.4869384765625 0.9817578125000006 +0.591375 -0.487579345703125 0.9817578125000006 +0.5915 -0.487579345703125 0.9817578125000006 +0.5916250000000001 -0.488128662109375 0.9817578125000006 +0.59175 -0.4886474609375 0.9817578125000006 +0.591875 -0.4886474609375 0.9817578125000006 +0.592 -0.489105224609375 0.9817578125000006 +0.5921250000000001 -0.489105224609375 0.9817578125000006 +0.59225 -0.489501953125 0.9817578125000006 +0.592375 -0.4898681640625 0.9817578125000006 +0.5925000000000001 -0.4898681640625 0.9817578125000006 +0.592625 -0.490142822265625 0.9817578125000006 +0.59275 -0.490142822265625 0.9817578125000006 +0.5928750000000001 -0.490386962890625 0.9817578125000006 +0.593 -0.490570068359375 0.9817578125000006 +0.593125 -0.490570068359375 0.9817578125000006 +0.5932500000000001 -0.49072265625 0.9817578125000006 +0.593375 -0.49072265625 0.9817578125000006 +0.5935 -0.490814208984375 0.9817578125000006 +0.5936249999999999 -0.4908447265625 0.9817578125000006 +0.59375 -0.4908447265625 0.9817578125000006 +0.5938750000000001 -0.490814208984375 0.9817578125000006 +0.594 -0.490814208984375 0.9817578125000006 +0.594125 -0.49072265625 0.9817578125000006 +0.5942500000000001 -0.490570068359375 0.9817578125000006 +0.594375 -0.490570068359375 0.9817578125000006 +0.5945 -0.490386962890625 0.9817578125000006 +0.5946249999999999 -0.490386962890625 0.9817578125000006 +0.59475 -0.490142822265625 0.9817578125000006 +0.594875 -0.4898681640625 0.9817578125000006 +0.5949999999999999 -0.4898681640625 0.9817578125000006 +0.595125 -0.489501953125 0.9817578125000006 +0.5952500000000001 -0.489501953125 0.9817578125000006 +0.5953749999999999 -0.489105224609375 0.9817578125000006 +0.5955 -0.4886474609375 0.9817578125000006 +0.595625 -0.4886474609375 0.9817578125000006 +0.59575 -0.488128662109375 0.9817578125000006 +0.595875 -0.488128662109375 0.9817578125000006 +0.596 -0.487579345703125 0.9817578125000006 +0.596125 -0.4869384765625 0.9817578125000006 +0.59625 -0.4869384765625 0.9817578125000006 +0.596375 -0.48626708984375 0.9817578125000006 +0.5965 -0.48626708984375 0.9817578125000006 +0.596625 -0.485565185546875 0.9817578125000006 +0.59675 -0.484771728515625 0.9817578125000006 +0.596875 -0.484771728515625 0.9817578125000006 +0.597 -0.48394775390625 0.9817578125000006 +0.597125 -0.48394775390625 0.9817578125000006 +0.59725 -0.483062744140625 0.9817578125000006 +0.597375 -0.48211669921875 0.9817578125000006 +0.5975000000000001 -0.48211669921875 0.9817578125000006 +0.5976249999999999 -0.48114013671875 0.9817578125000006 +0.59775 -0.48114013671875 0.9817578125000006 +0.5978750000000001 -0.4801025390625 0.9817578125000006 +0.598 -0.47900390625 0.9817578125000006 +0.598125 -0.47900390625 0.9817578125000006 +0.5982500000000001 -0.47784423828125 0.9817578125000006 +0.598375 -0.47784423828125 0.9817578125000006 +0.5985 -0.476654052734375 0.9817578125000006 +0.598625 -0.47540283203125 0.9817578125000006 +0.59875 -0.47540283203125 0.9817578125000006 +0.598875 -0.474090576171875 0.9817578125000006 +0.599 -0.474090576171875 0.9817578125000006 +0.599125 -0.472747802734375 0.9817578125000006 +0.5992500000000001 -0.4713134765625 0.9817578125000006 +0.599375 -0.4713134765625 0.9817578125000006 +0.5995 -0.469879150390625 0.9817578125000006 +0.599625 -0.469879150390625 0.9817578125000006 +0.59975 -0.468353271484375 0.9817578125000006 +0.599875 -0.466796875 0.9817578125000006 +0.6 -0.466796875 0.9817578125000006 +0.6001250000000001 -0.465179443359375 0.9817578125000006 +0.60025 -0.465179443359375 0.9817578125000006 +0.600375 -0.463531494140625 0.9817578125000006 +0.6005000000000001 -0.4617919921875 0.9817578125000006 +0.600625 -0.4617919921875 0.9817578125000006 +0.60075 -0.46002197265625 0.9817578125000006 +0.6008750000000001 -0.46002197265625 0.9817578125000006 +0.601 -0.458221435546875 0.9817578125000006 +0.601125 -0.45635986328125 0.9817578125000006 +0.6012500000000001 -0.45635986328125 0.9817578125000006 +0.601375 -0.454437255859375 0.9817578125000006 +0.6015000000000001 -0.454437255859375 0.9817578125000006 +0.6016249999999999 -0.45245361328125 0.9817578125000006 +0.60175 -0.450469970703125 0.9817578125000006 +0.6018750000000001 -0.450469970703125 0.9817578125000006 +0.602 -0.448394775390625 0.9817578125000006 +0.602125 -0.448394775390625 0.9817578125000006 +0.6022500000000001 -0.446258544921875 0.9817578125000006 +0.602375 -0.444122314453125 0.9817578125000006 +0.6025 -0.444122314453125 0.9817578125000006 +0.6026249999999999 -0.44189453125 0.9817578125000006 +0.60275 -0.44189453125 0.9817578125000006 +0.602875 -0.43963623046875 0.9817578125000006 +0.6029999999999999 -0.43731689453125 0.9817578125000006 +0.603125 -0.43731689453125 0.9817578125000006 +0.6032500000000001 -0.434967041015625 0.9817578125000006 +0.603375 -0.434967041015625 0.9817578125000006 +0.6035 -0.43255615234375 0.9817578125000006 +0.603625 -0.43011474609375 0.9817578125000006 +0.60375 -0.43011474609375 0.9817578125000006 +0.603875 -0.4276123046875 0.9817578125000006 +0.604 -0.4276123046875 0.9817578125000006 +0.604125 -0.425079345703125 0.9817578125000006 +0.60425 -0.422454833984375 0.9817578125000006 +0.604375 -0.422454833984375 0.9817578125000006 +0.6045 -0.419830322265625 0.9817578125000006 +0.604625 -0.419830322265625 0.9817578125000006 +0.60475 -0.417144775390625 0.9817578125000006 +0.604875 -0.4144287109375 0.9817578125000006 +0.605 -0.4144287109375 0.9817578125000006 +0.605125 -0.41162109375 0.9817578125000006 +0.60525 -0.41162109375 0.9817578125000006 +0.605375 -0.4088134765625 0.9817578125000006 +0.6055000000000001 -0.40594482421875 0.9817578125000006 +0.6056249999999999 -0.40594482421875 0.9817578125000006 +0.60575 -0.403045654296875 0.9817578125000006 +0.6058750000000001 -0.403045654296875 0.9817578125000006 +0.606 -0.40008544921875 0.9817578125000006 +0.606125 -0.3970947265625 0.9817578125000006 +0.6062500000000001 -0.3970947265625 0.9817578125000006 +0.606375 -0.39404296875 0.9817578125000006 +0.6065 -0.39404296875 0.9817578125000006 +0.606625 -0.39093017578125 0.9817578125000006 +0.60675 -0.3878173828125 0.9817578125000006 +0.6068750000000001 -0.3878173828125 0.9817578125000006 +0.607 -0.3846435546875 0.9817578125000006 +0.607125 -0.3846435546875 0.9817578125000006 +0.6072500000000001 -0.381439208984375 0.9817578125000006 +0.607375 -0.378173828125 0.9817578125000006 +0.6075 -0.378173828125 0.9817578125000006 +0.607625 -0.3748779296875 0.9817578125000006 +0.6077500000000001 -0.3748779296875 0.9817578125000006 +0.607875 -0.371551513671875 0.9817578125000006 +0.608 -0.369659423828125 0.9857910156249996 +0.6081250000000001 -0.369659423828125 0.9857910156249996 +0.60825 -0.366241455078125 0.9857910156249996 +0.608375 -0.366241455078125 0.9857910156249996 +0.6085000000000001 -0.362762451171875 0.9857910156249996 +0.608625 -0.3592529296875 0.9857910156249996 +0.60875 -0.3592529296875 0.9857910156249996 +0.6088750000000001 -0.355682373046875 0.9857910156249996 +0.609 -0.355682373046875 0.9857910156249996 +0.609125 -0.35211181640625 0.9857910156249996 +0.6092499999999999 -0.348480224609375 0.9857910156249996 +0.609375 -0.348480224609375 0.9857910156249996 +0.6095000000000001 -0.344818115234375 0.9857910156249996 +0.609625 -0.344818115234375 0.9857910156249996 +0.60975 -0.341094970703125 0.9857910156249996 +0.6098750000000001 -0.337371826171875 0.9857910156249996 +0.61 -0.337371826171875 0.9857910156249996 +0.610125 -0.333587646484375 0.9857910156249996 +0.6102499999999999 -0.333587646484375 0.9857910156249996 +0.610375 -0.32977294921875 0.9857910156249996 +0.6105 -0.325927734375 0.9857910156249996 +0.6106249999999999 -0.325927734375 0.9857910156249996 +0.61075 -0.322021484375 0.9857910156249996 +0.6108750000000001 -0.322021484375 0.9857910156249996 +0.6109999999999999 -0.318084716796875 0.9857910156249996 +0.611125 -0.31414794921875 0.9857910156249996 +0.61125 -0.31414794921875 0.9857910156249996 +0.611375 -0.310150146484375 0.9857910156249996 +0.6115 -0.310150146484375 0.9857910156249996 +0.611625 -0.306121826171875 0.9857910156249996 +0.61175 -0.30206298828125 0.9857910156249996 +0.611875 -0.30206298828125 0.9857910156249996 +0.612 -0.297943115234375 0.9857910156249996 +0.612125 -0.297943115234375 0.9857910156249996 +0.61225 -0.2938232421875 0.9857910156249996 +0.612375 -0.2896728515625 0.9857910156249996 +0.6125 -0.2896728515625 0.9857910156249996 +0.612625 -0.285491943359375 0.9857910156249996 +0.61275 -0.285491943359375 0.9857910156249996 +0.612875 -0.28125 0.9857910156249996 +0.613 -0.277008056640625 0.9857910156249996 +0.6131250000000001 -0.277008056640625 0.9857910156249996 +0.6132499999999999 -0.272705078125 0.9857910156249996 +0.613375 -0.272705078125 0.9857910156249996 +0.6135000000000001 -0.268402099609375 0.9857910156249996 +0.613625 -0.264068603515625 0.9857910156249996 +0.61375 -0.264068603515625 0.9857910156249996 +0.6138750000000001 -0.259674072265625 0.9857910156249996 +0.614 -0.259674072265625 0.9857910156249996 +0.614125 -0.25531005859375 0.9857910156249996 +0.61425 -0.2508544921875 0.9857910156249996 +0.614375 -0.2508544921875 0.9857910156249996 +0.6145 -0.24639892578125 0.9857910156249996 +0.614625 -0.24639892578125 0.9857910156249996 +0.61475 -0.241912841796875 0.9857910156249996 +0.6148750000000001 -0.2374267578125 0.9857910156249996 +0.615 -0.2374267578125 0.9857910156249996 +0.615125 -0.232879638671875 0.9857910156249996 +0.61525 -0.232879638671875 0.9857910156249996 +0.615375 -0.228302001953125 0.9857910156249996 +0.6155 -0.223724365234375 0.9857910156249996 +0.615625 -0.223724365234375 0.9857910156249996 +0.6157500000000001 -0.2191162109375 0.9857910156249996 +0.615875 -0.2191162109375 0.9857910156249996 +0.616 -0.2144775390625 0.9857910156249996 +0.6161250000000001 -0.2098388671875 0.9857910156249996 +0.61625 -0.2098388671875 0.9857910156249996 +0.616375 -0.20513916015625 0.9857910156249996 +0.6165000000000001 -0.20513916015625 0.9857910156249996 +0.616625 -0.200439453125 0.9857910156249996 +0.61675 -0.195709228515625 0.9857910156249996 +0.6168750000000001 -0.195709228515625 0.9857910156249996 +0.617 -0.19097900390625 0.9857910156249996 +0.6171250000000001 -0.19097900390625 0.9857910156249996 +0.6172499999999999 -0.186187744140625 0.9857910156249996 +0.617375 -0.181427001953125 0.9857910156249996 +0.6175000000000001 -0.181427001953125 0.9857910156249996 +0.617625 -0.176605224609375 0.9857910156249996 +0.61775 -0.176605224609375 0.9857910156249996 +0.6178750000000001 -0.171783447265625 0.9857910156249996 +0.618 -0.16693115234375 0.9857910156249996 +0.618125 -0.16693115234375 0.9857910156249996 +0.6182499999999999 -0.16204833984375 0.9857910156249996 +0.618375 -0.16204833984375 0.9857910156249996 +0.6185 -0.157196044921875 0.9857910156249996 +0.6186249999999999 -0.15228271484375 0.9857910156249996 +0.61875 -0.15228271484375 0.9857910156249996 +0.6188750000000001 -0.147369384765625 0.9857910156249996 +0.619 -0.147369384765625 0.9857910156249996 +0.619125 -0.142425537109375 0.9857910156249996 +0.61925 -0.137481689453125 0.9857910156249996 +0.619375 -0.137481689453125 0.9857910156249996 +0.6195 -0.13250732421875 0.9857910156249996 +0.619625 -0.13250732421875 0.9857910156249996 +0.61975 -0.127532958984375 0.9857910156249996 +0.619875 -0.122528076171875 0.9857910156249996 +0.62 -0.122528076171875 0.9857910156249996 +0.620125 -0.1175537109375 0.9857910156249996 +0.62025 -0.1175537109375 0.9857910156249996 +0.620375 -0.112518310546875 0.9857910156249996 +0.6205 -0.10748291015625 0.9857910156249996 +0.620625 -0.10748291015625 0.9857910156249996 +0.62075 -0.102447509765625 0.9857910156249996 +0.620875 -0.102447509765625 0.9857910156249996 +0.621 -0.097381591796875 0.9857910156249996 +0.6211250000000001 -0.092315673828125 0.9857910156249996 +0.6212499999999999 -0.092315673828125 0.9857910156249996 +0.621375 -0.087249755859375 0.9857910156249996 +0.6215000000000001 -0.087249755859375 0.9857910156249996 +0.621625 -0.082183837890625 0.9857910156249996 +0.62175 -0.077056884765625 0.9857910156249996 +0.6218750000000001 -0.077056884765625 0.9857910156249996 +0.622 -0.07196044921875 0.9857910156249996 +0.622125 -0.07196044921875 0.9857910156249996 +0.62225 -0.066864013671875 0.9857910156249996 +0.622375 -0.061737060546875 0.9857910156249996 +0.6225000000000001 -0.061737060546875 0.9857910156249996 +0.622625 -0.056640625 0.9857910156249996 +0.62275 -0.056640625 0.9857910156249996 +0.6228750000000001 -0.051513671875 0.9857910156249996 +0.623 -0.046356201171875 0.9857910156249996 +0.623125 -0.046356201171875 0.9857910156249996 +0.62325 -0.04119873046875 0.9857910156249996 +0.6233750000000001 -0.04119873046875 0.9857910156249996 +0.6235 -0.03607177734375 0.9857910156249996 +0.623625 -0.030914306640625 0.9857910156249996 +0.6237500000000001 -0.030914306640625 0.9857910156249996 +0.623875 -0.0257568359375 0.9857910156249996 +0.624 -0.0257568359375 0.9857910156249996 +0.6241250000000001 -0.0206298828125 0.9857910156249996 +0.62425 -0.015472412109375 0.9857910156249996 +0.624375 -0.015472412109375 0.9857910156249996 +0.6245000000000001 -0.01031494140625 0.9857910156249996 +0.624625 -0.01031494140625 0.9857910156249996 +0.62475 -0.005157470703125 0.9857910156249996 0.6248749999999999 0.0 0.9857910156249996 0.625 0.0 0.9857910156249996 0.6251250000000001 0.005157470703125 0.9857910156249996 @@ -5499,504 +5499,504 @@ 0.68725 0.003326416015625 0.6370898437499979 0.6873750000000001 0.0 0.6370898437499979 0.6875 0.0 0.6370898437499979 -0.6876250000000001 -0.00335693359375 0.6370898437499979 -0.68775 -0.00335693359375 0.6370898437499979 -0.687875 -0.006683349609375 0.6370898437499979 -0.6880000000000001 -0.010009765625 0.6370898437499979 -0.688125 -0.010009765625 0.6370898437499979 -0.68825 -0.01336669921875 0.6370898437499979 -0.6883749999999999 -0.01336669921875 0.6370898437499979 -0.6885 -0.01666259765625 0.6370898437499979 -0.688625 -0.02001953125 0.6370898437499979 -0.6887499999999999 -0.02001953125 0.6370898437499979 -0.688875 -0.023345947265625 0.6370898437499979 -0.6890000000000001 -0.023345947265625 0.6370898437499979 -0.6891249999999999 -0.02667236328125 0.6370898437499979 -0.68925 -0.029998779296875 0.6370898437499979 -0.689375 -0.029998779296875 0.6370898437499979 -0.6895 -0.033294677734375 0.6370898437499979 -0.689625 -0.033294677734375 0.6370898437499979 -0.68975 -0.03662109375 0.6370898437499979 -0.689875 -0.0399169921875 0.6370898437499979 -0.69 -0.0399169921875 0.6370898437499979 -0.690125 -0.043243408203125 0.6370898437499979 -0.69025 -0.043243408203125 0.6370898437499979 -0.690375 -0.046539306640625 0.6370898437499979 -0.6905 -0.049835205078125 0.6370898437499979 -0.690625 -0.049835205078125 0.6370898437499979 -0.69075 -0.053131103515625 0.6370898437499979 -0.690875 -0.053131103515625 0.6370898437499979 -0.691 -0.056427001953125 0.6370898437499979 -0.691125 -0.0596923828125 0.6370898437499979 -0.6912500000000001 -0.0596923828125 0.6370898437499979 -0.6913749999999999 -0.062957763671875 0.6370898437499979 -0.6915 -0.062957763671875 0.6370898437499979 -0.6916250000000001 -0.06622314453125 0.6370898437499979 -0.69175 -0.069488525390625 0.6370898437499979 -0.691875 -0.069488525390625 0.6370898437499979 -0.6920000000000001 -0.07275390625 0.6370898437499979 -0.692125 -0.07275390625 0.6370898437499979 -0.69225 -0.07598876953125 0.6370898437499979 -0.692375 -0.0792236328125 0.6370898437499979 -0.6925 -0.0792236328125 0.6370898437499979 -0.692625 -0.08245849609375 0.6370898437499979 -0.69275 -0.08245849609375 0.6370898437499979 -0.692875 -0.085662841796875 0.6370898437499979 -0.6930000000000001 -0.0888671875 0.6370898437499979 -0.693125 -0.0888671875 0.6370898437499979 -0.69325 -0.092071533203125 0.6370898437499979 -0.693375 -0.092071533203125 0.6370898437499979 -0.6935 -0.095245361328125 0.6370898437499979 -0.693625 -0.09844970703125 0.6370898437499979 -0.69375 -0.09844970703125 0.6370898437499979 -0.6938750000000001 -0.101593017578125 0.6370898437499979 -0.694 -0.101593017578125 0.6370898437499979 -0.694125 -0.104766845703125 0.6370898437499979 -0.6942500000000001 -0.10791015625 0.6370898437499979 -0.694375 -0.10791015625 0.6370898437499979 -0.6945 -0.11102294921875 0.6370898437499979 -0.6946250000000001 -0.11102294921875 0.6370898437499979 -0.69475 -0.114166259765625 0.6370898437499979 -0.694875 -0.117279052734375 0.6370898437499979 -0.6950000000000001 -0.117279052734375 0.6370898437499979 -0.695125 -0.120361328125 0.6370898437499979 -0.6952500000000001 -0.120361328125 0.6370898437499979 -0.6953749999999999 -0.123443603515625 0.6370898437499979 -0.6955 -0.126495361328125 0.6370898437499979 -0.6956250000000001 -0.126495361328125 0.6370898437499979 -0.69575 -0.12957763671875 0.6370898437499979 -0.695875 -0.12957763671875 0.6370898437499979 -0.6960000000000001 -0.132598876953125 0.6370898437499979 -0.696125 -0.1356201171875 0.6370898437499979 -0.69625 -0.1356201171875 0.6370898437499979 -0.6963749999999999 -0.138641357421875 0.6370898437499979 -0.6965 -0.138641357421875 0.6370898437499979 -0.696625 -0.141632080078125 0.6370898437499979 -0.6967499999999999 -0.144622802734375 0.6370898437499979 -0.696875 -0.144622802734375 0.6370898437499979 -0.6970000000000001 -0.1475830078125 0.6370898437499979 -0.697125 -0.1475830078125 0.6370898437499979 -0.69725 -0.150543212890625 0.6370898437499979 -0.697375 -0.1534423828125 0.6370898437499979 -0.6975 -0.1534423828125 0.6370898437499979 -0.697625 -0.1563720703125 0.6370898437499979 -0.69775 -0.1563720703125 0.6370898437499979 -0.697875 -0.159271240234375 0.6370898437499979 -0.698 -0.162139892578125 0.6370898437499979 -0.698125 -0.162139892578125 0.6370898437499979 -0.69825 -0.165008544921875 0.6370898437499979 -0.698375 -0.165008544921875 0.6370898437499979 -0.6985 -0.1678466796875 0.6370898437499979 -0.698625 -0.170684814453125 0.6370898437499979 -0.69875 -0.170684814453125 0.6370898437499979 -0.698875 -0.173492431640625 0.6370898437499979 -0.699 -0.173492431640625 0.6370898437499979 -0.699125 -0.17626953125 0.6370898437499979 -0.6992500000000001 -0.179046630859375 0.6370898437499979 -0.6993749999999999 -0.179046630859375 0.6370898437499979 -0.6995 -0.181793212890625 0.6370898437499979 -0.6996250000000001 -0.181793212890625 0.6370898437499979 -0.69975 -0.18450927734375 0.6370898437499979 -0.699875 -0.187225341796875 0.6370898437499979 -0.7000000000000001 -0.187225341796875 0.6370898437499979 -0.700125 -0.189910888671875 0.6370898437499979 -0.70025 -0.189910888671875 0.6370898437499979 -0.700375 -0.192596435546875 0.6370898437499979 -0.7005 -0.195220947265625 0.6370898437499979 -0.7006250000000001 -0.195220947265625 0.6370898437499979 -0.70075 -0.197845458984375 0.6370898437499979 -0.700875 -0.197845458984375 0.6370898437499979 -0.7010000000000001 -0.200469970703125 0.6370898437499979 -0.701125 -0.203033447265625 0.6370898437499979 -0.70125 -0.203033447265625 0.6370898437499979 -0.701375 -0.205596923828125 0.6370898437499979 -0.7015000000000001 -0.205596923828125 0.6370898437499979 -0.701625 -0.2081298828125 0.6370898437499979 -0.70175 -0.210662841796875 0.6370898437499979 -0.7018750000000001 -0.210662841796875 0.6370898437499979 -0.702 -0.213134765625 0.6370898437499979 -0.702125 -0.213134765625 0.6370898437499979 -0.7022500000000001 -0.215606689453125 0.6370898437499979 -0.702375 -0.218048095703125 0.6370898437499979 -0.7025 -0.218048095703125 0.6370898437499979 -0.7026250000000001 -0.220458984375 0.6370898437499979 -0.70275 -0.220458984375 0.6370898437499979 -0.702875 -0.222869873046875 0.6370898437499979 -0.7030000000000001 -0.2252197265625 0.6370898437499979 -0.703125 -0.2252197265625 0.6370898437499979 -0.7032500000000001 -0.22760009765625 0.6370898437499979 -0.703375 -0.22760009765625 0.6370898437499979 -0.7035 -0.229888916015625 0.6370898437499979 -0.7036250000000001 -0.232208251953125 0.6370898437499979 -0.70375 -0.232208251953125 0.6370898437499979 -0.703875 -0.234466552734375 0.6370898437499979 -0.7039999999999999 -0.1251220703125 0.3399999999999977 -0.704125 -0.1263427734375 0.3399999999999977 -0.70425 -0.12750244140625 0.3399999999999977 -0.7043749999999999 -0.12750244140625 0.3399999999999977 -0.7045 -0.128692626953125 0.3399999999999977 -0.7046250000000001 -0.128692626953125 0.3399999999999977 -0.7047499999999999 -0.129852294921875 0.3399999999999977 -0.704875 -0.1309814453125 0.3399999999999977 -0.705 -0.1309814453125 0.3399999999999977 -0.705125 -0.132110595703125 0.3399999999999977 -0.70525 -0.132110595703125 0.3399999999999977 -0.705375 -0.133209228515625 0.3399999999999977 -0.7055 -0.13433837890625 0.3399999999999977 -0.705625 -0.13433837890625 0.3399999999999977 -0.70575 -0.135406494140625 0.3399999999999977 -0.705875 -0.135406494140625 0.3399999999999977 -0.706 -0.136474609375 0.3399999999999977 -0.706125 -0.137542724609375 0.3399999999999977 -0.70625 -0.137542724609375 0.3399999999999977 -0.706375 -0.138580322265625 0.3399999999999977 -0.7065 -0.138580322265625 0.3399999999999977 -0.706625 -0.13958740234375 0.3399999999999977 -0.70675 -0.140594482421875 0.3399999999999977 -0.7068750000000001 -0.140594482421875 0.3399999999999977 -0.7069999999999999 -0.1416015625 0.3399999999999977 -0.707125 -0.1416015625 0.3399999999999977 -0.7072500000000001 -0.142578125 0.3399999999999977 -0.707375 -0.143524169921875 0.3399999999999977 -0.7075 -0.143524169921875 0.3399999999999977 -0.7076250000000001 -0.14447021484375 0.3399999999999977 -0.70775 -0.14447021484375 0.3399999999999977 -0.707875 -0.145416259765625 0.3399999999999977 -0.708 -0.146331787109375 0.3399999999999977 -0.708125 -0.146331787109375 0.3399999999999977 -0.70825 -0.147216796875 0.3399999999999977 -0.708375 -0.147216796875 0.3399999999999977 -0.7085 -0.148101806640625 0.3399999999999977 -0.7086250000000001 -0.148956298828125 0.3399999999999977 -0.70875 -0.148956298828125 0.3399999999999977 -0.708875 -0.149810791015625 0.3399999999999977 -0.709 -0.149810791015625 0.3399999999999977 -0.709125 -0.150634765625 0.3399999999999977 -0.70925 -0.151458740234375 0.3399999999999977 -0.709375 -0.151458740234375 0.3399999999999977 -0.7095000000000001 -0.152252197265625 0.3399999999999977 -0.709625 -0.152252197265625 0.3399999999999977 -0.70975 -0.153045654296875 0.3399999999999977 -0.7098750000000001 -0.15380859375 0.3399999999999977 -0.71 -0.15380859375 0.3399999999999977 -0.710125 -0.154571533203125 0.3399999999999977 -0.7102500000000001 -0.154571533203125 0.3399999999999977 -0.710375 -0.155303955078125 0.3399999999999977 -0.7105 -0.156005859375 0.3399999999999977 -0.7106250000000001 -0.156005859375 0.3399999999999977 -0.71075 -0.156707763671875 0.3399999999999977 -0.7108750000000001 -0.156707763671875 0.3399999999999977 -0.7109999999999999 -0.157379150390625 0.3399999999999977 -0.711125 -0.158050537109375 0.3399999999999977 -0.7112500000000001 -0.158050537109375 0.3399999999999977 -0.711375 -0.15869140625 0.3399999999999977 -0.7115 -0.15869140625 0.3399999999999977 -0.7116250000000001 -0.159332275390625 0.3399999999999977 -0.71175 -0.159942626953125 0.3399999999999977 -0.711875 -0.159942626953125 0.3399999999999977 -0.7119999999999999 -0.1605224609375 0.3399999999999977 -0.712125 -0.1605224609375 0.3399999999999977 -0.71225 -0.161102294921875 0.3399999999999977 -0.7123749999999999 -0.16168212890625 0.3399999999999977 -0.7125 -0.16168212890625 0.3399999999999977 -0.7126250000000001 -0.162200927734375 0.3399999999999977 -0.71275 -0.162200927734375 0.3399999999999977 -0.712875 -0.162750244140625 0.3399999999999977 -0.713 -0.163238525390625 0.3399999999999977 -0.713125 -0.163238525390625 0.3399999999999977 -0.71325 -0.163726806640625 0.3399999999999977 -0.713375 -0.163726806640625 0.3399999999999977 -0.7135 -0.1641845703125 0.3399999999999977 -0.713625 -0.164642333984375 0.3399999999999977 -0.71375 -0.164642333984375 0.3399999999999977 -0.713875 -0.16510009765625 0.3399999999999977 -0.714 -0.16510009765625 0.3399999999999977 -0.714125 -0.165496826171875 0.3399999999999977 -0.71425 -0.1658935546875 0.3399999999999977 -0.714375 -0.1658935546875 0.3399999999999977 -0.7145 -0.166259765625 0.3399999999999977 -0.714625 -0.166259765625 0.3399999999999977 -0.71475 -0.1666259765625 0.3399999999999977 -0.7148750000000001 -0.1669921875 0.3399999999999977 -0.7149999999999999 -0.1669921875 0.3399999999999977 -0.715125 -0.16729736328125 0.3399999999999977 -0.7152500000000001 -0.16729736328125 0.3399999999999977 -0.715375 -0.1676025390625 0.3399999999999977 -0.7155 -0.16790771484375 0.3399999999999977 -0.7156250000000001 -0.16790771484375 0.3399999999999977 -0.71575 -0.16815185546875 0.3399999999999977 -0.715875 -0.16815185546875 0.3399999999999977 -0.716 -0.168426513671875 0.3399999999999977 -0.716125 -0.16864013671875 0.3399999999999977 -0.7162500000000001 -0.16864013671875 0.3399999999999977 -0.716375 -0.168853759765625 0.3399999999999977 -0.7165 -0.168853759765625 0.3399999999999977 -0.7166250000000001 -0.1690673828125 0.3399999999999977 -0.71675 -0.16925048828125 0.3399999999999977 -0.716875 -0.16925048828125 0.3399999999999977 -0.717 -0.169403076171875 0.3399999999999977 -0.7171250000000001 -0.169403076171875 0.3399999999999977 -0.71725 -0.169525146484375 0.3399999999999977 -0.717375 -0.169647216796875 0.3399999999999977 -0.7175000000000001 -0.169647216796875 0.3399999999999977 -0.717625 -0.169769287109375 0.3399999999999977 -0.71775 -0.169769287109375 0.3399999999999977 -0.7178750000000001 -0.169830322265625 0.3399999999999977 -0.718 -0.169891357421875 0.3399999999999977 -0.718125 -0.169891357421875 0.3399999999999977 -0.7182500000000001 -0.169952392578125 0.3399999999999977 -0.718375 -0.169952392578125 0.3399999999999977 -0.7185 -0.16998291015625 0.3399999999999977 -0.7186250000000001 -0.16998291015625 0.3399999999999977 -0.71875 -0.16998291015625 0.3399999999999977 -0.7188750000000001 -0.16998291015625 0.3399999999999977 -0.719 -0.16998291015625 0.3399999999999977 -0.719125 -0.169952392578125 0.3399999999999977 -0.7192500000000001 -0.169891357421875 0.3399999999999977 -0.719375 -0.169891357421875 0.3399999999999977 -0.7195 -0.169830322265625 0.3399999999999977 -0.7196250000000001 -0.169830322265625 0.3399999999999977 -0.71975 -0.169769287109375 0.3399999999999977 -0.719875 -0.169647216796875 0.3399999999999977 -0.7199999999999999 -0.169647216796875 0.3399999999999977 -0.720125 -0.169525146484375 0.3399999999999977 -0.7202500000000001 -0.169525146484375 0.3399999999999977 -0.7203749999999999 -0.169403076171875 0.3399999999999977 -0.7205 -0.16925048828125 0.3399999999999977 -0.720625 -0.16925048828125 0.3399999999999977 -0.72075 -0.1690673828125 0.3399999999999977 -0.720875 -0.1690673828125 0.3399999999999977 -0.721 -0.168853759765625 0.3399999999999977 -0.721125 -0.16864013671875 0.3399999999999977 -0.72125 -0.16864013671875 0.3399999999999977 -0.721375 -0.168426513671875 0.3399999999999977 -0.7215 -0.168426513671875 0.3399999999999977 -0.721625 -0.16815185546875 0.3399999999999977 -0.72175 -0.16790771484375 0.3399999999999977 -0.721875 -0.16790771484375 0.3399999999999977 -0.722 -0.1676025390625 0.3399999999999977 -0.722125 -0.1676025390625 0.3399999999999977 -0.72225 -0.16729736328125 0.3399999999999977 -0.722375 -0.1669921875 0.3399999999999977 -0.7225000000000001 -0.1669921875 0.3399999999999977 -0.7226249999999999 -0.1666259765625 0.3399999999999977 -0.72275 -0.1666259765625 0.3399999999999977 -0.7228750000000001 -0.166259765625 0.3399999999999977 -0.723 -0.1658935546875 0.3399999999999977 -0.723125 -0.1658935546875 0.3399999999999977 -0.7232500000000001 -0.165496826171875 0.3399999999999977 -0.723375 -0.165496826171875 0.3399999999999977 -0.7235 -0.16510009765625 0.3399999999999977 -0.723625 -0.164642333984375 0.3399999999999977 -0.72375 -0.164642333984375 0.3399999999999977 -0.723875 -0.1641845703125 0.3399999999999977 -0.724 -0.1641845703125 0.3399999999999977 -0.724125 -0.163726806640625 0.3399999999999977 -0.7242500000000001 -0.163238525390625 0.3399999999999977 -0.724375 -0.163238525390625 0.3399999999999977 -0.7245 -0.162750244140625 0.3399999999999977 -0.724625 -0.162750244140625 0.3399999999999977 -0.72475 -0.162200927734375 0.3399999999999977 -0.724875 -0.16168212890625 0.3399999999999977 -0.725 -0.16168212890625 0.3399999999999977 -0.7251250000000001 -0.161102294921875 0.3399999999999977 -0.72525 -0.161102294921875 0.3399999999999977 -0.725375 -0.1605224609375 0.3399999999999977 -0.7255000000000001 -0.159942626953125 0.3399999999999977 -0.725625 -0.159942626953125 0.3399999999999977 -0.72575 -0.159332275390625 0.3399999999999977 -0.7258750000000001 -0.159332275390625 0.3399999999999977 -0.726 -0.15869140625 0.3399999999999977 -0.726125 -0.158050537109375 0.3399999999999977 -0.7262500000000001 -0.158050537109375 0.3399999999999977 -0.726375 -0.157379150390625 0.3399999999999977 -0.7265000000000001 -0.157379150390625 0.3399999999999977 -0.7266249999999999 -0.156707763671875 0.3399999999999977 -0.72675 -0.156005859375 0.3399999999999977 -0.7268750000000001 -0.156005859375 0.3399999999999977 -0.727 -0.155303955078125 0.3399999999999977 -0.727125 -0.155303955078125 0.3399999999999977 -0.7272500000000001 -0.154571533203125 0.3399999999999977 -0.727375 -0.15380859375 0.3399999999999977 -0.7275 -0.15380859375 0.3399999999999977 -0.7276249999999999 -0.153045654296875 0.3399999999999977 -0.72775 -0.153045654296875 0.3399999999999977 -0.727875 -0.152252197265625 0.3399999999999977 -0.7279999999999999 -0.151458740234375 0.3399999999999977 -0.728125 -0.151458740234375 0.3399999999999977 -0.7282500000000001 -0.150634765625 0.3399999999999977 -0.728375 -0.150634765625 0.3399999999999977 -0.7285 -0.149810791015625 0.3399999999999977 -0.728625 -0.148956298828125 0.3399999999999977 -0.72875 -0.148956298828125 0.3399999999999977 -0.728875 -0.148101806640625 0.3399999999999977 -0.729 -0.148101806640625 0.3399999999999977 -0.729125 -0.147216796875 0.3399999999999977 -0.72925 -0.146331787109375 0.3399999999999977 -0.729375 -0.146331787109375 0.3399999999999977 -0.7295 -0.145416259765625 0.3399999999999977 -0.729625 -0.145416259765625 0.3399999999999977 -0.72975 -0.14447021484375 0.3399999999999977 -0.729875 -0.143524169921875 0.3399999999999977 -0.73 -0.143524169921875 0.3399999999999977 -0.730125 -0.142578125 0.3399999999999977 -0.73025 -0.142578125 0.3399999999999977 -0.730375 -0.1416015625 0.3399999999999977 -0.7305000000000001 -0.140594482421875 0.3399999999999977 -0.7306249999999999 -0.140594482421875 0.3399999999999977 -0.73075 -0.13958740234375 0.3399999999999977 -0.7308750000000001 -0.13958740234375 0.3399999999999977 -0.731 -0.138580322265625 0.3399999999999977 -0.731125 -0.137542724609375 0.3399999999999977 -0.7312500000000001 -0.137542724609375 0.3399999999999977 -0.731375 -0.136474609375 0.3399999999999977 -0.7315 -0.136474609375 0.3399999999999977 -0.731625 -0.135406494140625 0.3399999999999977 -0.73175 -0.13433837890625 0.3399999999999977 -0.7318750000000001 -0.13433837890625 0.3399999999999977 -0.732 -0.133209228515625 0.3399999999999977 -0.732125 -0.133209228515625 0.3399999999999977 -0.7322500000000001 -0.132110595703125 0.3399999999999977 -0.732375 -0.1309814453125 0.3399999999999977 -0.7325 -0.1309814453125 0.3399999999999977 -0.732625 -0.129852294921875 0.3399999999999977 -0.7327500000000001 -0.129852294921875 0.3399999999999977 -0.732875 -0.128692626953125 0.3399999999999977 -0.733 -0.12750244140625 0.3399999999999977 -0.7331250000000001 -0.12750244140625 0.3399999999999977 -0.73325 -0.1263427734375 0.3399999999999977 -0.733375 -0.1263427734375 0.3399999999999977 -0.7335000000000001 -0.1251220703125 0.3399999999999977 -0.733625 -0.123931884765625 0.3399999999999977 -0.73375 -0.123931884765625 0.3399999999999977 -0.7338750000000001 -0.1226806640625 0.3399999999999977 -0.734 -0.1226806640625 0.3399999999999977 -0.734125 -0.1214599609375 0.3399999999999977 -0.7342500000000001 -0.120208740234375 0.3399999999999977 -0.734375 -0.120208740234375 0.3399999999999977 -0.7345000000000001 -0.118927001953125 0.3399999999999977 -0.734625 -0.118927001953125 0.3399999999999977 -0.73475 -0.11767578125 0.3399999999999977 -0.7348750000000001 -0.116363525390625 0.3399999999999977 -0.735 -0.116363525390625 0.3399999999999977 -0.735125 -0.115081787109375 0.3399999999999977 -0.7352500000000001 -0.115081787109375 0.3399999999999977 -0.735375 -0.113739013671875 0.3399999999999977 -0.7355 -0.1124267578125 0.3399999999999977 -0.7356249999999999 -0.1124267578125 0.3399999999999977 -0.73575 -0.111083984375 0.3399999999999977 -0.7358750000000001 -0.111083984375 0.3399999999999977 -0.7359999999999999 -0.00665283203125 0.02060546874999752 -0.736125 -0.006561279296875 0.02060546874999752 -0.73625 -0.006561279296875 0.02060546874999752 -0.736375 -0.006500244140625 0.02060546874999752 -0.7365 -0.006500244140625 0.02060546874999752 -0.736625 -0.00640869140625 0.02060546874999752 -0.73675 -0.006317138671875 0.02060546874999752 -0.736875 -0.006317138671875 0.02060546874999752 -0.737 -0.0062255859375 0.02060546874999752 -0.737125 -0.0062255859375 0.02060546874999752 -0.73725 -0.006134033203125 0.02060546874999752 -0.737375 -0.006072998046875 0.02060546874999752 -0.7375 -0.006072998046875 0.02060546874999752 -0.737625 -0.0059814453125 0.02060546874999752 -0.73775 -0.0059814453125 0.02060546874999752 -0.737875 -0.005889892578125 0.02060546874999752 -0.738 -0.00579833984375 0.02060546874999752 -0.7381250000000001 -0.00579833984375 0.02060546874999752 -0.7382499999999999 -0.005706787109375 0.02060546874999752 -0.738375 -0.005706787109375 0.02060546874999752 -0.7385000000000001 -0.005615234375 0.02060546874999752 -0.738625 -0.005523681640625 0.02060546874999752 -0.73875 -0.005523681640625 0.02060546874999752 -0.7388750000000001 -0.00543212890625 0.02060546874999752 -0.739 -0.00543212890625 0.02060546874999752 -0.739125 -0.005340576171875 0.02060546874999752 -0.73925 -0.0052490234375 0.02060546874999752 -0.739375 -0.0052490234375 0.02060546874999752 -0.7395 -0.005157470703125 0.02060546874999752 -0.739625 -0.005157470703125 0.02060546874999752 -0.73975 -0.00506591796875 0.02060546874999752 -0.7398750000000001 -0.004974365234375 0.02060546874999752 -0.74 -0.004974365234375 0.02060546874999752 -0.740125 -0.0048828125 0.02060546874999752 -0.74025 -0.0048828125 0.02060546874999752 -0.740375 -0.004791259765625 0.02060546874999752 -0.7405 -0.004669189453125 0.02060546874999752 -0.740625 -0.004669189453125 0.02060546874999752 -0.7407500000000001 -0.00457763671875 0.02060546874999752 -0.740875 -0.00457763671875 0.02060546874999752 -0.741 -0.004486083984375 0.02060546874999752 -0.7411250000000001 -0.00439453125 0.02060546874999752 -0.74125 -0.00439453125 0.02060546874999752 -0.741375 -0.004302978515625 0.02060546874999752 -0.7415000000000001 -0.004302978515625 0.02060546874999752 -0.741625 -0.00421142578125 0.02060546874999752 -0.74175 -0.00408935546875 0.02060546874999752 -0.7418750000000001 -0.00408935546875 0.02060546874999752 -0.742 -0.003997802734375 0.02060546874999752 -0.7421250000000001 -0.003997802734375 0.02060546874999752 -0.7422499999999999 -0.00390625 0.02060546874999752 -0.742375 -0.003814697265625 0.02060546874999752 -0.7425000000000001 -0.003814697265625 0.02060546874999752 -0.742625 -0.003692626953125 0.02060546874999752 -0.74275 -0.003692626953125 0.02060546874999752 -0.7428750000000001 -0.00360107421875 0.02060546874999752 -0.743 -0.003509521484375 0.02060546874999752 -0.743125 -0.003509521484375 0.02060546874999752 -0.7432499999999999 -0.003387451171875 0.02060546874999752 -0.743375 -0.003387451171875 0.02060546874999752 -0.7435 -0.0032958984375 0.02060546874999752 -0.7436249999999999 -0.003204345703125 0.02060546874999752 -0.74375 -0.003204345703125 0.02060546874999752 -0.7438750000000001 -0.003082275390625 0.02060546874999752 -0.744 -0.003082275390625 0.02060546874999752 -0.744125 -0.00299072265625 0.02060546874999752 -0.74425 -0.002899169921875 0.02060546874999752 -0.744375 -0.002899169921875 0.02060546874999752 -0.7445 -0.002777099609375 0.02060546874999752 -0.744625 -0.002777099609375 0.02060546874999752 -0.74475 -0.002685546875 0.02060546874999752 -0.744875 -0.0025634765625 0.02060546874999752 -0.745 -0.0025634765625 0.02060546874999752 -0.745125 -0.002471923828125 0.02060546874999752 -0.74525 -0.002471923828125 0.02060546874999752 -0.745375 -0.002349853515625 0.02060546874999752 -0.7455 -0.00225830078125 0.02060546874999752 -0.745625 -0.00225830078125 0.02060546874999752 -0.74575 -0.002166748046875 0.02060546874999752 -0.745875 -0.002166748046875 0.02060546874999752 -0.746 -0.002044677734375 0.02060546874999752 -0.7461250000000001 -0.001953125 0.02060546874999752 -0.7462499999999999 -0.001953125 0.02060546874999752 -0.746375 -0.0018310546875 0.02060546874999752 -0.7465000000000001 -0.0018310546875 0.02060546874999752 -0.746625 -0.001739501953125 0.02060546874999752 -0.74675 -0.001617431640625 0.02060546874999752 -0.7468750000000001 -0.001617431640625 0.02060546874999752 -0.747 -0.00152587890625 0.02060546874999752 -0.747125 -0.00152587890625 0.02060546874999752 -0.74725 -0.00140380859375 0.02060546874999752 -0.747375 -0.001312255859375 0.02060546874999752 -0.7475000000000001 -0.001312255859375 0.02060546874999752 -0.747625 -0.001190185546875 0.02060546874999752 -0.74775 -0.001190185546875 0.02060546874999752 -0.7478750000000001 -0.0010986328125 0.02060546874999752 -0.748 -0.0009765625 0.02060546874999752 -0.748125 -0.0009765625 0.02060546874999752 -0.74825 -0.000885009765625 0.02060546874999752 -0.7483750000000001 -0.000885009765625 0.02060546874999752 -0.7485 -0.000762939453125 0.02060546874999752 -0.748625 -0.00067138671875 0.02060546874999752 -0.7487500000000001 -0.00067138671875 0.02060546874999752 -0.748875 -0.00054931640625 0.02060546874999752 -0.749 -0.00054931640625 0.02060546874999752 -0.7491250000000001 -0.000457763671875 0.02060546874999752 -0.74925 -0.000335693359375 0.02060546874999752 -0.749375 -0.000335693359375 0.02060546874999752 -0.7495000000000001 -0.000244140625 0.02060546874999752 -0.749625 -0.000244140625 0.02060546874999752 -0.74975 -0.0001220703125 0.02060546874999752 +0.6876250000000001 -0.003326416015625 0.6370898437499979 +0.68775 -0.003326416015625 0.6370898437499979 +0.687875 -0.00665283203125 0.6370898437499979 +0.6880000000000001 -0.009979248046875 0.6370898437499979 +0.688125 -0.009979248046875 0.6370898437499979 +0.68825 -0.013336181640625 0.6370898437499979 +0.6883749999999999 -0.013336181640625 0.6370898437499979 +0.6885 -0.016632080078125 0.6370898437499979 +0.688625 -0.019989013671875 0.6370898437499979 +0.6887499999999999 -0.019989013671875 0.6370898437499979 +0.688875 -0.0233154296875 0.6370898437499979 +0.6890000000000001 -0.0233154296875 0.6370898437499979 +0.6891249999999999 -0.026641845703125 0.6370898437499979 +0.68925 -0.02996826171875 0.6370898437499979 +0.689375 -0.02996826171875 0.6370898437499979 +0.6895 -0.03326416015625 0.6370898437499979 +0.689625 -0.03326416015625 0.6370898437499979 +0.68975 -0.036590576171875 0.6370898437499979 +0.689875 -0.039886474609375 0.6370898437499979 +0.69 -0.039886474609375 0.6370898437499979 +0.690125 -0.043212890625 0.6370898437499979 +0.69025 -0.043212890625 0.6370898437499979 +0.690375 -0.0465087890625 0.6370898437499979 +0.6905 -0.0498046875 0.6370898437499979 +0.690625 -0.0498046875 0.6370898437499979 +0.69075 -0.0531005859375 0.6370898437499979 +0.690875 -0.0531005859375 0.6370898437499979 +0.691 -0.056396484375 0.6370898437499979 +0.691125 -0.059661865234375 0.6370898437499979 +0.6912500000000001 -0.059661865234375 0.6370898437499979 +0.6913749999999999 -0.06292724609375 0.6370898437499979 +0.6915 -0.06292724609375 0.6370898437499979 +0.6916250000000001 -0.066192626953125 0.6370898437499979 +0.69175 -0.0694580078125 0.6370898437499979 +0.691875 -0.0694580078125 0.6370898437499979 +0.6920000000000001 -0.072723388671875 0.6370898437499979 +0.692125 -0.072723388671875 0.6370898437499979 +0.69225 -0.075958251953125 0.6370898437499979 +0.692375 -0.079193115234375 0.6370898437499979 +0.6925 -0.079193115234375 0.6370898437499979 +0.692625 -0.082427978515625 0.6370898437499979 +0.69275 -0.082427978515625 0.6370898437499979 +0.692875 -0.08563232421875 0.6370898437499979 +0.6930000000000001 -0.088836669921875 0.6370898437499979 +0.693125 -0.088836669921875 0.6370898437499979 +0.69325 -0.092041015625 0.6370898437499979 +0.693375 -0.092041015625 0.6370898437499979 +0.6935 -0.09521484375 0.6370898437499979 +0.693625 -0.098419189453125 0.6370898437499979 +0.69375 -0.098419189453125 0.6370898437499979 +0.6938750000000001 -0.1015625 0.6370898437499979 +0.694 -0.1015625 0.6370898437499979 +0.694125 -0.104736328125 0.6370898437499979 +0.6942500000000001 -0.107879638671875 0.6370898437499979 +0.694375 -0.107879638671875 0.6370898437499979 +0.6945 -0.110992431640625 0.6370898437499979 +0.6946250000000001 -0.110992431640625 0.6370898437499979 +0.69475 -0.1141357421875 0.6370898437499979 +0.694875 -0.11724853515625 0.6370898437499979 +0.6950000000000001 -0.11724853515625 0.6370898437499979 +0.695125 -0.120330810546875 0.6370898437499979 +0.6952500000000001 -0.120330810546875 0.6370898437499979 +0.6953749999999999 -0.1234130859375 0.6370898437499979 +0.6955 -0.12646484375 0.6370898437499979 +0.6956250000000001 -0.12646484375 0.6370898437499979 +0.69575 -0.129547119140625 0.6370898437499979 +0.695875 -0.129547119140625 0.6370898437499979 +0.6960000000000001 -0.132568359375 0.6370898437499979 +0.696125 -0.135589599609375 0.6370898437499979 +0.69625 -0.135589599609375 0.6370898437499979 +0.6963749999999999 -0.13861083984375 0.6370898437499979 +0.6965 -0.13861083984375 0.6370898437499979 +0.696625 -0.1416015625 0.6370898437499979 +0.6967499999999999 -0.14459228515625 0.6370898437499979 +0.696875 -0.14459228515625 0.6370898437499979 +0.6970000000000001 -0.147552490234375 0.6370898437499979 +0.697125 -0.147552490234375 0.6370898437499979 +0.69725 -0.1505126953125 0.6370898437499979 +0.697375 -0.153411865234375 0.6370898437499979 +0.6975 -0.153411865234375 0.6370898437499979 +0.697625 -0.156341552734375 0.6370898437499979 +0.69775 -0.156341552734375 0.6370898437499979 +0.697875 -0.15924072265625 0.6370898437499979 +0.698 -0.162109375 0.6370898437499979 +0.698125 -0.162109375 0.6370898437499979 +0.69825 -0.16497802734375 0.6370898437499979 +0.698375 -0.16497802734375 0.6370898437499979 +0.6985 -0.167816162109375 0.6370898437499979 +0.698625 -0.170654296875 0.6370898437499979 +0.69875 -0.170654296875 0.6370898437499979 +0.698875 -0.1734619140625 0.6370898437499979 +0.699 -0.1734619140625 0.6370898437499979 +0.699125 -0.176239013671875 0.6370898437499979 +0.6992500000000001 -0.17901611328125 0.6370898437499979 +0.6993749999999999 -0.17901611328125 0.6370898437499979 +0.6995 -0.1817626953125 0.6370898437499979 +0.6996250000000001 -0.1817626953125 0.6370898437499979 +0.69975 -0.184478759765625 0.6370898437499979 +0.699875 -0.18719482421875 0.6370898437499979 +0.7000000000000001 -0.18719482421875 0.6370898437499979 +0.700125 -0.18988037109375 0.6370898437499979 +0.70025 -0.18988037109375 0.6370898437499979 +0.700375 -0.19256591796875 0.6370898437499979 +0.7005 -0.1951904296875 0.6370898437499979 +0.7006250000000001 -0.1951904296875 0.6370898437499979 +0.70075 -0.19781494140625 0.6370898437499979 +0.700875 -0.19781494140625 0.6370898437499979 +0.7010000000000001 -0.200439453125 0.6370898437499979 +0.701125 -0.2030029296875 0.6370898437499979 +0.70125 -0.2030029296875 0.6370898437499979 +0.701375 -0.20556640625 0.6370898437499979 +0.7015000000000001 -0.20556640625 0.6370898437499979 +0.701625 -0.208099365234375 0.6370898437499979 +0.70175 -0.21063232421875 0.6370898437499979 +0.7018750000000001 -0.21063232421875 0.6370898437499979 +0.702 -0.213104248046875 0.6370898437499979 +0.702125 -0.213104248046875 0.6370898437499979 +0.7022500000000001 -0.215576171875 0.6370898437499979 +0.702375 -0.218017578125 0.6370898437499979 +0.7025 -0.218017578125 0.6370898437499979 +0.7026250000000001 -0.220428466796875 0.6370898437499979 +0.70275 -0.220428466796875 0.6370898437499979 +0.702875 -0.22283935546875 0.6370898437499979 +0.7030000000000001 -0.225189208984375 0.6370898437499979 +0.703125 -0.225189208984375 0.6370898437499979 +0.7032500000000001 -0.227569580078125 0.6370898437499979 +0.703375 -0.227569580078125 0.6370898437499979 +0.7035 -0.2298583984375 0.6370898437499979 +0.7036250000000001 -0.232177734375 0.6370898437499979 +0.70375 -0.232177734375 0.6370898437499979 +0.703875 -0.23443603515625 0.6370898437499979 +0.7039999999999999 -0.125091552734375 0.3399999999999977 +0.704125 -0.126312255859375 0.3399999999999977 +0.70425 -0.127471923828125 0.3399999999999977 +0.7043749999999999 -0.127471923828125 0.3399999999999977 +0.7045 -0.128662109375 0.3399999999999977 +0.7046250000000001 -0.128662109375 0.3399999999999977 +0.7047499999999999 -0.12982177734375 0.3399999999999977 +0.704875 -0.130950927734375 0.3399999999999977 +0.705 -0.130950927734375 0.3399999999999977 +0.705125 -0.132080078125 0.3399999999999977 +0.70525 -0.132080078125 0.3399999999999977 +0.705375 -0.1331787109375 0.3399999999999977 +0.7055 -0.134307861328125 0.3399999999999977 +0.705625 -0.134307861328125 0.3399999999999977 +0.70575 -0.1353759765625 0.3399999999999977 +0.705875 -0.1353759765625 0.3399999999999977 +0.706 -0.136444091796875 0.3399999999999977 +0.706125 -0.13751220703125 0.3399999999999977 +0.70625 -0.13751220703125 0.3399999999999977 +0.706375 -0.1385498046875 0.3399999999999977 +0.7065 -0.1385498046875 0.3399999999999977 +0.706625 -0.139556884765625 0.3399999999999977 +0.70675 -0.14056396484375 0.3399999999999977 +0.7068750000000001 -0.14056396484375 0.3399999999999977 +0.7069999999999999 -0.141571044921875 0.3399999999999977 +0.707125 -0.141571044921875 0.3399999999999977 +0.7072500000000001 -0.142547607421875 0.3399999999999977 +0.707375 -0.14349365234375 0.3399999999999977 +0.7075 -0.14349365234375 0.3399999999999977 +0.7076250000000001 -0.144439697265625 0.3399999999999977 +0.70775 -0.144439697265625 0.3399999999999977 +0.707875 -0.1453857421875 0.3399999999999977 +0.708 -0.14630126953125 0.3399999999999977 +0.708125 -0.14630126953125 0.3399999999999977 +0.70825 -0.147186279296875 0.3399999999999977 +0.708375 -0.147186279296875 0.3399999999999977 +0.7085 -0.1480712890625 0.3399999999999977 +0.7086250000000001 -0.14892578125 0.3399999999999977 +0.70875 -0.14892578125 0.3399999999999977 +0.708875 -0.1497802734375 0.3399999999999977 +0.709 -0.1497802734375 0.3399999999999977 +0.709125 -0.150604248046875 0.3399999999999977 +0.70925 -0.15142822265625 0.3399999999999977 +0.709375 -0.15142822265625 0.3399999999999977 +0.7095000000000001 -0.1522216796875 0.3399999999999977 +0.709625 -0.1522216796875 0.3399999999999977 +0.70975 -0.15301513671875 0.3399999999999977 +0.7098750000000001 -0.153778076171875 0.3399999999999977 +0.71 -0.153778076171875 0.3399999999999977 +0.710125 -0.154541015625 0.3399999999999977 +0.7102500000000001 -0.154541015625 0.3399999999999977 +0.710375 -0.1552734375 0.3399999999999977 +0.7105 -0.155975341796875 0.3399999999999977 +0.7106250000000001 -0.155975341796875 0.3399999999999977 +0.71075 -0.15667724609375 0.3399999999999977 +0.7108750000000001 -0.15667724609375 0.3399999999999977 +0.7109999999999999 -0.1573486328125 0.3399999999999977 +0.711125 -0.15802001953125 0.3399999999999977 +0.7112500000000001 -0.15802001953125 0.3399999999999977 +0.711375 -0.158660888671875 0.3399999999999977 +0.7115 -0.158660888671875 0.3399999999999977 +0.7116250000000001 -0.1593017578125 0.3399999999999977 +0.71175 -0.159912109375 0.3399999999999977 +0.711875 -0.159912109375 0.3399999999999977 +0.7119999999999999 -0.160491943359375 0.3399999999999977 +0.712125 -0.160491943359375 0.3399999999999977 +0.71225 -0.16107177734375 0.3399999999999977 +0.7123749999999999 -0.161651611328125 0.3399999999999977 +0.7125 -0.161651611328125 0.3399999999999977 +0.7126250000000001 -0.16217041015625 0.3399999999999977 +0.71275 -0.16217041015625 0.3399999999999977 +0.712875 -0.1627197265625 0.3399999999999977 +0.713 -0.1632080078125 0.3399999999999977 +0.713125 -0.1632080078125 0.3399999999999977 +0.71325 -0.1636962890625 0.3399999999999977 +0.713375 -0.1636962890625 0.3399999999999977 +0.7135 -0.164154052734375 0.3399999999999977 +0.713625 -0.16461181640625 0.3399999999999977 +0.71375 -0.16461181640625 0.3399999999999977 +0.713875 -0.165069580078125 0.3399999999999977 +0.714 -0.165069580078125 0.3399999999999977 +0.714125 -0.16546630859375 0.3399999999999977 +0.71425 -0.165863037109375 0.3399999999999977 +0.714375 -0.165863037109375 0.3399999999999977 +0.7145 -0.166229248046875 0.3399999999999977 +0.714625 -0.166229248046875 0.3399999999999977 +0.71475 -0.166595458984375 0.3399999999999977 +0.7148750000000001 -0.166961669921875 0.3399999999999977 +0.7149999999999999 -0.166961669921875 0.3399999999999977 +0.715125 -0.167266845703125 0.3399999999999977 +0.7152500000000001 -0.167266845703125 0.3399999999999977 +0.715375 -0.167572021484375 0.3399999999999977 +0.7155 -0.167877197265625 0.3399999999999977 +0.7156250000000001 -0.167877197265625 0.3399999999999977 +0.71575 -0.168121337890625 0.3399999999999977 +0.715875 -0.168121337890625 0.3399999999999977 +0.716 -0.16839599609375 0.3399999999999977 +0.716125 -0.168609619140625 0.3399999999999977 +0.7162500000000001 -0.168609619140625 0.3399999999999977 +0.716375 -0.1688232421875 0.3399999999999977 +0.7165 -0.1688232421875 0.3399999999999977 +0.7166250000000001 -0.169036865234375 0.3399999999999977 +0.71675 -0.169219970703125 0.3399999999999977 +0.716875 -0.169219970703125 0.3399999999999977 +0.717 -0.16937255859375 0.3399999999999977 +0.7171250000000001 -0.16937255859375 0.3399999999999977 +0.71725 -0.16949462890625 0.3399999999999977 +0.717375 -0.16961669921875 0.3399999999999977 +0.7175000000000001 -0.16961669921875 0.3399999999999977 +0.717625 -0.16973876953125 0.3399999999999977 +0.71775 -0.16973876953125 0.3399999999999977 +0.7178750000000001 -0.1697998046875 0.3399999999999977 +0.718 -0.16986083984375 0.3399999999999977 +0.718125 -0.16986083984375 0.3399999999999977 +0.7182500000000001 -0.169921875 0.3399999999999977 +0.718375 -0.169921875 0.3399999999999977 +0.7185 -0.169952392578125 0.3399999999999977 +0.7186250000000001 -0.169952392578125 0.3399999999999977 +0.71875 -0.169952392578125 0.3399999999999977 +0.7188750000000001 -0.169952392578125 0.3399999999999977 +0.719 -0.169952392578125 0.3399999999999977 +0.719125 -0.169921875 0.3399999999999977 +0.7192500000000001 -0.16986083984375 0.3399999999999977 +0.719375 -0.16986083984375 0.3399999999999977 +0.7195 -0.1697998046875 0.3399999999999977 +0.7196250000000001 -0.1697998046875 0.3399999999999977 +0.71975 -0.16973876953125 0.3399999999999977 +0.719875 -0.16961669921875 0.3399999999999977 +0.7199999999999999 -0.16961669921875 0.3399999999999977 +0.720125 -0.16949462890625 0.3399999999999977 +0.7202500000000001 -0.16949462890625 0.3399999999999977 +0.7203749999999999 -0.16937255859375 0.3399999999999977 +0.7205 -0.169219970703125 0.3399999999999977 +0.720625 -0.169219970703125 0.3399999999999977 +0.72075 -0.169036865234375 0.3399999999999977 +0.720875 -0.169036865234375 0.3399999999999977 +0.721 -0.1688232421875 0.3399999999999977 +0.721125 -0.168609619140625 0.3399999999999977 +0.72125 -0.168609619140625 0.3399999999999977 +0.721375 -0.16839599609375 0.3399999999999977 +0.7215 -0.16839599609375 0.3399999999999977 +0.721625 -0.168121337890625 0.3399999999999977 +0.72175 -0.167877197265625 0.3399999999999977 +0.721875 -0.167877197265625 0.3399999999999977 +0.722 -0.167572021484375 0.3399999999999977 +0.722125 -0.167572021484375 0.3399999999999977 +0.72225 -0.167266845703125 0.3399999999999977 +0.722375 -0.166961669921875 0.3399999999999977 +0.7225000000000001 -0.166961669921875 0.3399999999999977 +0.7226249999999999 -0.166595458984375 0.3399999999999977 +0.72275 -0.166595458984375 0.3399999999999977 +0.7228750000000001 -0.166229248046875 0.3399999999999977 +0.723 -0.165863037109375 0.3399999999999977 +0.723125 -0.165863037109375 0.3399999999999977 +0.7232500000000001 -0.16546630859375 0.3399999999999977 +0.723375 -0.16546630859375 0.3399999999999977 +0.7235 -0.165069580078125 0.3399999999999977 +0.723625 -0.16461181640625 0.3399999999999977 +0.72375 -0.16461181640625 0.3399999999999977 +0.723875 -0.164154052734375 0.3399999999999977 +0.724 -0.164154052734375 0.3399999999999977 +0.724125 -0.1636962890625 0.3399999999999977 +0.7242500000000001 -0.1632080078125 0.3399999999999977 +0.724375 -0.1632080078125 0.3399999999999977 +0.7245 -0.1627197265625 0.3399999999999977 +0.724625 -0.1627197265625 0.3399999999999977 +0.72475 -0.16217041015625 0.3399999999999977 +0.724875 -0.161651611328125 0.3399999999999977 +0.725 -0.161651611328125 0.3399999999999977 +0.7251250000000001 -0.16107177734375 0.3399999999999977 +0.72525 -0.16107177734375 0.3399999999999977 +0.725375 -0.160491943359375 0.3399999999999977 +0.7255000000000001 -0.159912109375 0.3399999999999977 +0.725625 -0.159912109375 0.3399999999999977 +0.72575 -0.1593017578125 0.3399999999999977 +0.7258750000000001 -0.1593017578125 0.3399999999999977 +0.726 -0.158660888671875 0.3399999999999977 +0.726125 -0.15802001953125 0.3399999999999977 +0.7262500000000001 -0.15802001953125 0.3399999999999977 +0.726375 -0.1573486328125 0.3399999999999977 +0.7265000000000001 -0.1573486328125 0.3399999999999977 +0.7266249999999999 -0.15667724609375 0.3399999999999977 +0.72675 -0.155975341796875 0.3399999999999977 +0.7268750000000001 -0.155975341796875 0.3399999999999977 +0.727 -0.1552734375 0.3399999999999977 +0.727125 -0.1552734375 0.3399999999999977 +0.7272500000000001 -0.154541015625 0.3399999999999977 +0.727375 -0.153778076171875 0.3399999999999977 +0.7275 -0.153778076171875 0.3399999999999977 +0.7276249999999999 -0.15301513671875 0.3399999999999977 +0.72775 -0.15301513671875 0.3399999999999977 +0.727875 -0.1522216796875 0.3399999999999977 +0.7279999999999999 -0.15142822265625 0.3399999999999977 +0.728125 -0.15142822265625 0.3399999999999977 +0.7282500000000001 -0.150604248046875 0.3399999999999977 +0.728375 -0.150604248046875 0.3399999999999977 +0.7285 -0.1497802734375 0.3399999999999977 +0.728625 -0.14892578125 0.3399999999999977 +0.72875 -0.14892578125 0.3399999999999977 +0.728875 -0.1480712890625 0.3399999999999977 +0.729 -0.1480712890625 0.3399999999999977 +0.729125 -0.147186279296875 0.3399999999999977 +0.72925 -0.14630126953125 0.3399999999999977 +0.729375 -0.14630126953125 0.3399999999999977 +0.7295 -0.1453857421875 0.3399999999999977 +0.729625 -0.1453857421875 0.3399999999999977 +0.72975 -0.144439697265625 0.3399999999999977 +0.729875 -0.14349365234375 0.3399999999999977 +0.73 -0.14349365234375 0.3399999999999977 +0.730125 -0.142547607421875 0.3399999999999977 +0.73025 -0.142547607421875 0.3399999999999977 +0.730375 -0.141571044921875 0.3399999999999977 +0.7305000000000001 -0.14056396484375 0.3399999999999977 +0.7306249999999999 -0.14056396484375 0.3399999999999977 +0.73075 -0.139556884765625 0.3399999999999977 +0.7308750000000001 -0.139556884765625 0.3399999999999977 +0.731 -0.1385498046875 0.3399999999999977 +0.731125 -0.13751220703125 0.3399999999999977 +0.7312500000000001 -0.13751220703125 0.3399999999999977 +0.731375 -0.136444091796875 0.3399999999999977 +0.7315 -0.136444091796875 0.3399999999999977 +0.731625 -0.1353759765625 0.3399999999999977 +0.73175 -0.134307861328125 0.3399999999999977 +0.7318750000000001 -0.134307861328125 0.3399999999999977 +0.732 -0.1331787109375 0.3399999999999977 +0.732125 -0.1331787109375 0.3399999999999977 +0.7322500000000001 -0.132080078125 0.3399999999999977 +0.732375 -0.130950927734375 0.3399999999999977 +0.7325 -0.130950927734375 0.3399999999999977 +0.732625 -0.12982177734375 0.3399999999999977 +0.7327500000000001 -0.12982177734375 0.3399999999999977 +0.732875 -0.128662109375 0.3399999999999977 +0.733 -0.127471923828125 0.3399999999999977 +0.7331250000000001 -0.127471923828125 0.3399999999999977 +0.73325 -0.126312255859375 0.3399999999999977 +0.733375 -0.126312255859375 0.3399999999999977 +0.7335000000000001 -0.125091552734375 0.3399999999999977 +0.733625 -0.1239013671875 0.3399999999999977 +0.73375 -0.1239013671875 0.3399999999999977 +0.7338750000000001 -0.122650146484375 0.3399999999999977 +0.734 -0.122650146484375 0.3399999999999977 +0.734125 -0.121429443359375 0.3399999999999977 +0.7342500000000001 -0.12017822265625 0.3399999999999977 +0.734375 -0.12017822265625 0.3399999999999977 +0.7345000000000001 -0.118896484375 0.3399999999999977 +0.734625 -0.118896484375 0.3399999999999977 +0.73475 -0.117645263671875 0.3399999999999977 +0.7348750000000001 -0.1163330078125 0.3399999999999977 +0.735 -0.1163330078125 0.3399999999999977 +0.735125 -0.11505126953125 0.3399999999999977 +0.7352500000000001 -0.11505126953125 0.3399999999999977 +0.735375 -0.11370849609375 0.3399999999999977 +0.7355 -0.112396240234375 0.3399999999999977 +0.7356249999999999 -0.112396240234375 0.3399999999999977 +0.73575 -0.111053466796875 0.3399999999999977 +0.7358750000000001 -0.111053466796875 0.3399999999999977 +0.7359999999999999 -0.006622314453125 0.02060546874999752 +0.736125 -0.00653076171875 0.02060546874999752 +0.73625 -0.00653076171875 0.02060546874999752 +0.736375 -0.0064697265625 0.02060546874999752 +0.7365 -0.0064697265625 0.02060546874999752 +0.736625 -0.006378173828125 0.02060546874999752 +0.73675 -0.00628662109375 0.02060546874999752 +0.736875 -0.00628662109375 0.02060546874999752 +0.737 -0.006195068359375 0.02060546874999752 +0.737125 -0.006195068359375 0.02060546874999752 +0.73725 -0.006103515625 0.02060546874999752 +0.737375 -0.00604248046875 0.02060546874999752 +0.7375 -0.00604248046875 0.02060546874999752 +0.737625 -0.005950927734375 0.02060546874999752 +0.73775 -0.005950927734375 0.02060546874999752 +0.737875 -0.005859375 0.02060546874999752 +0.738 -0.005767822265625 0.02060546874999752 +0.7381250000000001 -0.005767822265625 0.02060546874999752 +0.7382499999999999 -0.00567626953125 0.02060546874999752 +0.738375 -0.00567626953125 0.02060546874999752 +0.7385000000000001 -0.005584716796875 0.02060546874999752 +0.738625 -0.0054931640625 0.02060546874999752 +0.73875 -0.0054931640625 0.02060546874999752 +0.7388750000000001 -0.005401611328125 0.02060546874999752 +0.739 -0.005401611328125 0.02060546874999752 +0.739125 -0.00531005859375 0.02060546874999752 +0.73925 -0.005218505859375 0.02060546874999752 +0.739375 -0.005218505859375 0.02060546874999752 +0.7395 -0.005126953125 0.02060546874999752 +0.739625 -0.005126953125 0.02060546874999752 +0.73975 -0.005035400390625 0.02060546874999752 +0.7398750000000001 -0.00494384765625 0.02060546874999752 +0.74 -0.00494384765625 0.02060546874999752 +0.740125 -0.004852294921875 0.02060546874999752 +0.74025 -0.004852294921875 0.02060546874999752 +0.740375 -0.0047607421875 0.02060546874999752 +0.7405 -0.004638671875 0.02060546874999752 +0.740625 -0.004638671875 0.02060546874999752 +0.7407500000000001 -0.004547119140625 0.02060546874999752 +0.740875 -0.004547119140625 0.02060546874999752 +0.741 -0.00445556640625 0.02060546874999752 +0.7411250000000001 -0.004364013671875 0.02060546874999752 +0.74125 -0.004364013671875 0.02060546874999752 +0.741375 -0.0042724609375 0.02060546874999752 +0.7415000000000001 -0.0042724609375 0.02060546874999752 +0.741625 -0.004180908203125 0.02060546874999752 +0.74175 -0.004058837890625 0.02060546874999752 +0.7418750000000001 -0.004058837890625 0.02060546874999752 +0.742 -0.00396728515625 0.02060546874999752 +0.7421250000000001 -0.00396728515625 0.02060546874999752 +0.7422499999999999 -0.003875732421875 0.02060546874999752 +0.742375 -0.0037841796875 0.02060546874999752 +0.7425000000000001 -0.0037841796875 0.02060546874999752 +0.742625 -0.003662109375 0.02060546874999752 +0.74275 -0.003662109375 0.02060546874999752 +0.7428750000000001 -0.003570556640625 0.02060546874999752 +0.743 -0.00347900390625 0.02060546874999752 +0.743125 -0.00347900390625 0.02060546874999752 +0.7432499999999999 -0.00335693359375 0.02060546874999752 +0.743375 -0.00335693359375 0.02060546874999752 +0.7435 -0.003265380859375 0.02060546874999752 +0.7436249999999999 -0.003173828125 0.02060546874999752 +0.74375 -0.003173828125 0.02060546874999752 +0.7438750000000001 -0.0030517578125 0.02060546874999752 +0.744 -0.0030517578125 0.02060546874999752 +0.744125 -0.002960205078125 0.02060546874999752 +0.74425 -0.00286865234375 0.02060546874999752 +0.744375 -0.00286865234375 0.02060546874999752 +0.7445 -0.00274658203125 0.02060546874999752 +0.744625 -0.00274658203125 0.02060546874999752 +0.74475 -0.002655029296875 0.02060546874999752 +0.744875 -0.002532958984375 0.02060546874999752 +0.745 -0.002532958984375 0.02060546874999752 +0.745125 -0.00244140625 0.02060546874999752 +0.74525 -0.00244140625 0.02060546874999752 +0.745375 -0.0023193359375 0.02060546874999752 +0.7455 -0.002227783203125 0.02060546874999752 +0.745625 -0.002227783203125 0.02060546874999752 +0.74575 -0.00213623046875 0.02060546874999752 +0.745875 -0.00213623046875 0.02060546874999752 +0.746 -0.00201416015625 0.02060546874999752 +0.7461250000000001 -0.001922607421875 0.02060546874999752 +0.7462499999999999 -0.001922607421875 0.02060546874999752 +0.746375 -0.001800537109375 0.02060546874999752 +0.7465000000000001 -0.001800537109375 0.02060546874999752 +0.746625 -0.001708984375 0.02060546874999752 +0.74675 -0.0015869140625 0.02060546874999752 +0.7468750000000001 -0.0015869140625 0.02060546874999752 +0.747 -0.001495361328125 0.02060546874999752 +0.747125 -0.001495361328125 0.02060546874999752 +0.74725 -0.001373291015625 0.02060546874999752 +0.747375 -0.00128173828125 0.02060546874999752 +0.7475000000000001 -0.00128173828125 0.02060546874999752 +0.747625 -0.00115966796875 0.02060546874999752 +0.74775 -0.00115966796875 0.02060546874999752 +0.7478750000000001 -0.001068115234375 0.02060546874999752 +0.748 -0.000946044921875 0.02060546874999752 +0.748125 -0.000946044921875 0.02060546874999752 +0.74825 -0.0008544921875 0.02060546874999752 +0.7483750000000001 -0.0008544921875 0.02060546874999752 +0.7485 -0.000732421875 0.02060546874999752 +0.748625 -0.000640869140625 0.02060546874999752 +0.7487500000000001 -0.000640869140625 0.02060546874999752 +0.748875 -0.000518798828125 0.02060546874999752 +0.749 -0.000518798828125 0.02060546874999752 +0.7491250000000001 -0.00042724609375 0.02060546874999752 +0.74925 -0.00030517578125 0.02060546874999752 +0.749375 -0.00030517578125 0.02060546874999752 +0.7495000000000001 -0.000213623046875 0.02060546874999752 +0.749625 -0.000213623046875 0.02060546874999752 +0.74975 -9.1552734375e-05 0.02060546874999752 0.7498750000000001 0.0 0.02060546874999752 0.75 0.0 0.02060546874999752 0.7501250000000001 9.1552734375e-05 0.02060546874999752 @@ -6142,361 +6142,361 @@ 0.767625 0.007965087890625 0.02060546874999752 0.76775 0.007965087890625 0.02060546874999752 0.767875 0.008056640625 0.02060546874999752 -0.768 -0.10675048828125 -0.2701904296875024 -0.768125 -0.10675048828125 -0.2701904296875024 -0.76825 -0.107635498046875 -0.2701904296875024 -0.768375 -0.107635498046875 -0.2701904296875024 -0.7685 -0.10845947265625 -0.2701904296875024 -0.768625 -0.10931396484375 -0.2701904296875024 -0.76875 -0.10931396484375 -0.2701904296875024 -0.768875 -0.110137939453125 -0.2701904296875024 -0.769 -0.110137939453125 -0.2701904296875024 -0.769125 -0.1109619140625 -0.2701904296875024 -0.76925 -0.11175537109375 -0.2701904296875024 -0.7693750000000001 -0.11175537109375 -0.2701904296875024 -0.7694999999999999 -0.112548828125 -0.2701904296875024 -0.769625 -0.112548828125 -0.2701904296875024 -0.7697500000000001 -0.113311767578125 -0.2701904296875024 -0.769875 -0.11407470703125 -0.2701904296875024 -0.77 -0.11407470703125 -0.2701904296875024 -0.7701250000000001 -0.114837646484375 -0.2701904296875024 -0.77025 -0.114837646484375 -0.2701904296875024 -0.770375 -0.115570068359375 -0.2701904296875024 -0.7705 -0.116302490234375 -0.2701904296875024 -0.770625 -0.116302490234375 -0.2701904296875024 -0.77075 -0.11700439453125 -0.2701904296875024 -0.770875 -0.11700439453125 -0.2701904296875024 -0.771 -0.117706298828125 -0.2701904296875024 -0.7711250000000001 -0.118408203125 -0.2701904296875024 -0.77125 -0.118408203125 -0.2701904296875024 -0.771375 -0.11907958984375 -0.2701904296875024 -0.7715 -0.11907958984375 -0.2701904296875024 -0.771625 -0.1197509765625 -0.2701904296875024 -0.77175 -0.120391845703125 -0.2701904296875024 -0.771875 -0.120391845703125 -0.2701904296875024 -0.7720000000000001 -0.12103271484375 -0.2701904296875024 -0.772125 -0.12103271484375 -0.2701904296875024 -0.77225 -0.12164306640625 -0.2701904296875024 -0.7723750000000001 -0.12225341796875 -0.2701904296875024 -0.7725 -0.12225341796875 -0.2701904296875024 -0.772625 -0.122833251953125 -0.2701904296875024 -0.7727500000000001 -0.122833251953125 -0.2701904296875024 -0.772875 -0.123443603515625 -0.2701904296875024 -0.773 -0.123992919921875 -0.2701904296875024 -0.7731250000000001 -0.123992919921875 -0.2701904296875024 -0.77325 -0.124542236328125 -0.2701904296875024 -0.7733750000000001 -0.124542236328125 -0.2701904296875024 -0.7734999999999999 -0.125091552734375 -0.2701904296875024 -0.773625 -0.1256103515625 -0.2701904296875024 -0.7737500000000001 -0.1256103515625 -0.2701904296875024 -0.773875 -0.126129150390625 -0.2701904296875024 -0.774 -0.126129150390625 -0.2701904296875024 -0.7741250000000001 -0.12664794921875 -0.2701904296875024 -0.77425 -0.12713623046875 -0.2701904296875024 -0.774375 -0.12713623046875 -0.2701904296875024 -0.7744999999999999 -0.127593994140625 -0.2701904296875024 -0.774625 -0.127593994140625 -0.2701904296875024 -0.77475 -0.1280517578125 -0.2701904296875024 -0.7748749999999999 -0.128509521484375 -0.2701904296875024 -0.775 -0.128509521484375 -0.2701904296875024 -0.7751250000000001 -0.128936767578125 -0.2701904296875024 -0.77525 -0.128936767578125 -0.2701904296875024 -0.775375 -0.12933349609375 -0.2701904296875024 -0.7755 -0.129730224609375 -0.2701904296875024 -0.775625 -0.129730224609375 -0.2701904296875024 -0.77575 -0.130126953125 -0.2701904296875024 -0.775875 -0.130126953125 -0.2701904296875024 -0.776 -0.1304931640625 -0.2701904296875024 -0.776125 -0.130859375 -0.2701904296875024 -0.77625 -0.130859375 -0.2701904296875024 -0.776375 -0.1312255859375 -0.2701904296875024 -0.7765 -0.1312255859375 -0.2701904296875024 -0.776625 -0.13153076171875 -0.2701904296875024 -0.77675 -0.131866455078125 -0.2701904296875024 -0.776875 -0.131866455078125 -0.2701904296875024 -0.777 -0.13214111328125 -0.2701904296875024 -0.777125 -0.13214111328125 -0.2701904296875024 -0.77725 -0.1324462890625 -0.2701904296875024 -0.7773750000000001 -0.132720947265625 -0.2701904296875024 -0.7774999999999999 -0.132720947265625 -0.2701904296875024 -0.777625 -0.132965087890625 -0.2701904296875024 -0.7777500000000001 -0.132965087890625 -0.2701904296875024 -0.777875 -0.133209228515625 -0.2701904296875024 -0.778 -0.133453369140625 -0.2701904296875024 -0.7781250000000001 -0.133453369140625 -0.2701904296875024 -0.77825 -0.1336669921875 -0.2701904296875024 -0.778375 -0.1336669921875 -0.2701904296875024 -0.7785 -0.13385009765625 -0.2701904296875024 -0.778625 -0.134033203125 -0.2701904296875024 -0.7787500000000001 -0.134033203125 -0.2701904296875024 -0.778875 -0.13421630859375 -0.2701904296875024 -0.779 -0.13421630859375 -0.2701904296875024 -0.7791250000000001 -0.134368896484375 -0.2701904296875024 -0.77925 -0.134521484375 -0.2701904296875024 -0.779375 -0.134521484375 -0.2701904296875024 -0.7795 -0.1346435546875 -0.2701904296875024 -0.7796250000000001 -0.1346435546875 -0.2701904296875024 -0.77975 -0.134735107421875 -0.2701904296875024 -0.779875 -0.134857177734375 -0.2701904296875024 -0.7800000000000001 -0.134857177734375 -0.2701904296875024 -0.780125 -0.134918212890625 -0.2701904296875024 -0.78025 -0.134918212890625 -0.2701904296875024 -0.7803750000000001 -0.134979248046875 -0.2701904296875024 -0.7805 -0.135040283203125 -0.2701904296875024 -0.780625 -0.135040283203125 -0.2701904296875024 -0.7807500000000001 -0.13507080078125 -0.2701904296875024 -0.780875 -0.13507080078125 -0.2701904296875024 -0.781 -0.135101318359375 -0.2701904296875024 -0.7811250000000001 -0.135101318359375 -0.2701904296875024 -0.78125 -0.135101318359375 -0.2701904296875024 -0.7813750000000001 -0.135101318359375 -0.2701904296875024 -0.7815 -0.135101318359375 -0.2701904296875024 -0.781625 -0.13507080078125 -0.2701904296875024 -0.7817500000000001 -0.135040283203125 -0.2701904296875024 -0.781875 -0.135040283203125 -0.2701904296875024 -0.782 -0.134979248046875 -0.2701904296875024 -0.7821250000000001 -0.134979248046875 -0.2701904296875024 -0.78225 -0.134918212890625 -0.2701904296875024 -0.782375 -0.134857177734375 -0.2701904296875024 -0.7824999999999999 -0.134857177734375 -0.2701904296875024 -0.782625 -0.134735107421875 -0.2701904296875024 -0.7827500000000001 -0.134735107421875 -0.2701904296875024 -0.7828749999999999 -0.1346435546875 -0.2701904296875024 -0.783 -0.134521484375 -0.2701904296875024 -0.7831250000000001 -0.134521484375 -0.2701904296875024 -0.78325 -0.134368896484375 -0.2701904296875024 -0.783375 -0.134368896484375 -0.2701904296875024 -0.7835 -0.13421630859375 -0.2701904296875024 -0.783625 -0.134033203125 -0.2701904296875024 -0.78375 -0.134033203125 -0.2701904296875024 -0.783875 -0.13385009765625 -0.2701904296875024 -0.784 -0.13385009765625 -0.2701904296875024 -0.784125 -0.1336669921875 -0.2701904296875024 -0.78425 -0.133453369140625 -0.2701904296875024 -0.784375 -0.133453369140625 -0.2701904296875024 -0.7845 -0.133209228515625 -0.2701904296875024 -0.784625 -0.133209228515625 -0.2701904296875024 -0.78475 -0.132965087890625 -0.2701904296875024 -0.784875 -0.132720947265625 -0.2701904296875024 -0.7850000000000001 -0.132720947265625 -0.2701904296875024 -0.7851249999999999 -0.1324462890625 -0.2701904296875024 -0.78525 -0.1324462890625 -0.2701904296875024 -0.7853750000000001 -0.13214111328125 -0.2701904296875024 -0.7855 -0.131866455078125 -0.2701904296875024 -0.785625 -0.131866455078125 -0.2701904296875024 -0.7857500000000001 -0.13153076171875 -0.2701904296875024 -0.785875 -0.13153076171875 -0.2701904296875024 -0.786 -0.1312255859375 -0.2701904296875024 -0.786125 -0.130859375 -0.2701904296875024 -0.78625 -0.130859375 -0.2701904296875024 -0.786375 -0.1304931640625 -0.2701904296875024 -0.7865 -0.1304931640625 -0.2701904296875024 -0.786625 -0.130126953125 -0.2701904296875024 -0.7867500000000001 -0.129730224609375 -0.2701904296875024 -0.786875 -0.129730224609375 -0.2701904296875024 -0.787 -0.12933349609375 -0.2701904296875024 -0.787125 -0.12933349609375 -0.2701904296875024 -0.78725 -0.128936767578125 -0.2701904296875024 -0.787375 -0.128509521484375 -0.2701904296875024 -0.7875 -0.128509521484375 -0.2701904296875024 -0.7876250000000001 -0.1280517578125 -0.2701904296875024 -0.78775 -0.1280517578125 -0.2701904296875024 -0.787875 -0.127593994140625 -0.2701904296875024 -0.7880000000000001 -0.12713623046875 -0.2701904296875024 -0.788125 -0.12713623046875 -0.2701904296875024 -0.78825 -0.12664794921875 -0.2701904296875024 -0.7883750000000001 -0.12664794921875 -0.2701904296875024 -0.7885 -0.126129150390625 -0.2701904296875024 -0.788625 -0.1256103515625 -0.2701904296875024 -0.7887500000000001 -0.1256103515625 -0.2701904296875024 -0.788875 -0.125091552734375 -0.2701904296875024 -0.7890000000000001 -0.125091552734375 -0.2701904296875024 -0.7891249999999999 -0.124542236328125 -0.2701904296875024 -0.78925 -0.123992919921875 -0.2701904296875024 -0.7893750000000001 -0.123992919921875 -0.2701904296875024 -0.7895 -0.123443603515625 -0.2701904296875024 -0.789625 -0.123443603515625 -0.2701904296875024 -0.7897500000000001 -0.122833251953125 -0.2701904296875024 -0.789875 -0.12225341796875 -0.2701904296875024 -0.79 -0.12225341796875 -0.2701904296875024 -0.7901249999999999 -0.12164306640625 -0.2701904296875024 -0.79025 -0.12164306640625 -0.2701904296875024 -0.790375 -0.12103271484375 -0.2701904296875024 -0.7904999999999999 -0.120391845703125 -0.2701904296875024 -0.790625 -0.120391845703125 -0.2701904296875024 -0.7907500000000001 -0.1197509765625 -0.2701904296875024 -0.790875 -0.1197509765625 -0.2701904296875024 -0.791 -0.11907958984375 -0.2701904296875024 -0.791125 -0.118408203125 -0.2701904296875024 -0.79125 -0.118408203125 -0.2701904296875024 -0.791375 -0.117706298828125 -0.2701904296875024 -0.7915 -0.117706298828125 -0.2701904296875024 -0.791625 -0.11700439453125 -0.2701904296875024 -0.79175 -0.116302490234375 -0.2701904296875024 -0.791875 -0.116302490234375 -0.2701904296875024 -0.792 -0.115570068359375 -0.2701904296875024 -0.792125 -0.115570068359375 -0.2701904296875024 -0.79225 -0.114837646484375 -0.2701904296875024 -0.792375 -0.11407470703125 -0.2701904296875024 -0.7925 -0.11407470703125 -0.2701904296875024 -0.792625 -0.113311767578125 -0.2701904296875024 -0.79275 -0.113311767578125 -0.2701904296875024 -0.792875 -0.112548828125 -0.2701904296875024 -0.7930000000000001 -0.11175537109375 -0.2701904296875024 -0.7931249999999999 -0.11175537109375 -0.2701904296875024 -0.79325 -0.1109619140625 -0.2701904296875024 -0.7933750000000001 -0.1109619140625 -0.2701904296875024 -0.7935 -0.110137939453125 -0.2701904296875024 -0.793625 -0.10931396484375 -0.2701904296875024 -0.7937500000000001 -0.10931396484375 -0.2701904296875024 -0.793875 -0.10845947265625 -0.2701904296875024 -0.794 -0.10845947265625 -0.2701904296875024 -0.794125 -0.107635498046875 -0.2701904296875024 -0.79425 -0.10675048828125 -0.2701904296875024 -0.7943750000000001 -0.10675048828125 -0.2701904296875024 -0.7945 -0.10589599609375 -0.2701904296875024 -0.794625 -0.10589599609375 -0.2701904296875024 -0.7947500000000001 -0.105010986328125 -0.2701904296875024 -0.794875 -0.104095458984375 -0.2701904296875024 -0.795 -0.104095458984375 -0.2701904296875024 -0.795125 -0.10321044921875 -0.2701904296875024 -0.7952500000000001 -0.10321044921875 -0.2701904296875024 -0.795375 -0.102294921875 -0.2701904296875024 -0.7955 -0.101348876953125 -0.2701904296875024 -0.7956250000000001 -0.101348876953125 -0.2701904296875024 -0.79575 -0.10040283203125 -0.2701904296875024 -0.795875 -0.10040283203125 -0.2701904296875024 -0.7960000000000001 -0.099456787109375 -0.2701904296875024 -0.796125 -0.0985107421875 -0.2701904296875024 -0.79625 -0.0985107421875 -0.2701904296875024 -0.7963750000000001 -0.0975341796875 -0.2701904296875024 -0.7965 -0.0975341796875 -0.2701904296875024 -0.796625 -0.096527099609375 -0.2701904296875024 -0.7967500000000001 -0.095550537109375 -0.2701904296875024 -0.796875 -0.095550537109375 -0.2701904296875024 -0.7970000000000001 -0.09454345703125 -0.2701904296875024 -0.797125 -0.09454345703125 -0.2701904296875024 -0.79725 -0.093505859375 -0.2701904296875024 -0.7973750000000001 -0.092498779296875 -0.2701904296875024 -0.7975 -0.092498779296875 -0.2701904296875024 -0.797625 -0.091461181640625 -0.2701904296875024 -0.7977500000000001 -0.091461181640625 -0.2701904296875024 -0.797875 -0.090423583984375 -0.2701904296875024 -0.798 -0.08935546875 -0.2701904296875024 -0.7981249999999999 -0.08935546875 -0.2701904296875024 -0.79825 -0.088287353515625 -0.2701904296875024 -0.7983750000000001 -0.088287353515625 -0.2701904296875024 -0.7984999999999999 -0.08721923828125 -0.2701904296875024 -0.798625 -0.08612060546875 -0.2701904296875024 -0.7987500000000001 -0.08612060546875 -0.2701904296875024 -0.798875 -0.08502197265625 -0.2701904296875024 -0.799 -0.08502197265625 -0.2701904296875024 -0.799125 -0.08392333984375 -0.2701904296875024 -0.79925 -0.08282470703125 -0.2701904296875024 -0.799375 -0.08282470703125 -0.2701904296875024 -0.7995 -0.081695556640625 -0.2701904296875024 -0.799625 -0.081695556640625 -0.2701904296875024 -0.79975 -0.08056640625 -0.2701904296875024 -0.799875 -0.07940673828125 -0.2701904296875024 -0.8 -0.142822265625 -0.4859716796875017 -0.8001249999999999 -0.140777587890625 -0.4859716796875017 -0.80025 -0.140777587890625 -0.4859716796875017 -0.800375 -0.138671875 -0.4859716796875017 -0.8004999999999999 -0.136566162109375 -0.4859716796875017 -0.800625 -0.136566162109375 -0.4859716796875017 -0.80075 -0.13446044921875 -0.4859716796875017 -0.8008749999999999 -0.13446044921875 -0.4859716796875017 -0.801 -0.132354736328125 -0.4859716796875017 -0.801125 -0.130218505859375 -0.4859716796875017 -0.8012499999999999 -0.130218505859375 -0.4859716796875017 -0.801375 -0.1280517578125 -0.4859716796875017 -0.8015000000000001 -0.1280517578125 -0.4859716796875017 -0.8016249999999999 -0.125885009765625 -0.4859716796875017 -0.80175 -0.123687744140625 -0.4859716796875017 -0.8018750000000001 -0.123687744140625 -0.4859716796875017 -0.802 -0.121490478515625 -0.4859716796875017 -0.802125 -0.121490478515625 -0.4859716796875017 -0.8022500000000001 -0.119293212890625 -0.4859716796875017 -0.802375 -0.1170654296875 -0.4859716796875017 -0.8025 -0.1170654296875 -0.4859716796875017 -0.8026250000000001 -0.114837646484375 -0.4859716796875017 -0.80275 -0.114837646484375 -0.4859716796875017 -0.802875 -0.112579345703125 -0.4859716796875017 -0.8030000000000001 -0.110321044921875 -0.4859716796875017 -0.803125 -0.110321044921875 -0.4859716796875017 -0.8032500000000001 -0.1080322265625 -0.4859716796875017 -0.8033750000000001 -0.1080322265625 -0.4859716796875017 -0.8035 -0.10577392578125 -0.4859716796875017 -0.8036250000000001 -0.10345458984375 -0.4859716796875017 -0.80375 -0.10345458984375 -0.4859716796875017 -0.803875 -0.101165771484375 -0.4859716796875017 -0.8040000000000001 -0.101165771484375 -0.4859716796875017 -0.804125 -0.098846435546875 -0.4859716796875017 -0.80425 -0.09649658203125 -0.4859716796875017 -0.8043750000000001 -0.09649658203125 -0.4859716796875017 -0.8045 -0.09417724609375 -0.4859716796875017 -0.8046250000000001 -0.09417724609375 -0.4859716796875017 -0.8047499999999999 -0.091827392578125 -0.4859716796875017 -0.804875 -0.089447021484375 -0.4859716796875017 -0.8050000000000001 -0.089447021484375 -0.4859716796875017 -0.805125 -0.08709716796875 -0.4859716796875017 -0.80525 -0.08709716796875 -0.4859716796875017 -0.8053750000000001 -0.084716796875 -0.4859716796875017 -0.8055 -0.082305908203125 -0.4859716796875017 -0.805625 -0.082305908203125 -0.4859716796875017 -0.8057499999999999 -0.079925537109375 -0.4859716796875017 -0.805875 -0.079925537109375 -0.4859716796875017 -0.806 -0.0775146484375 -0.4859716796875017 -0.8061249999999999 -0.075103759765625 -0.4859716796875017 -0.80625 -0.075103759765625 -0.4859716796875017 -0.8063750000000001 -0.072662353515625 -0.4859716796875017 -0.8065 -0.072662353515625 -0.4859716796875017 -0.806625 -0.07025146484375 -0.4859716796875017 -0.8067499999999999 -0.06781005859375 -0.4859716796875017 -0.806875 -0.06781005859375 -0.4859716796875017 -0.807 -0.065338134765625 -0.4859716796875017 -0.8071249999999999 -0.065338134765625 -0.4859716796875017 -0.80725 -0.062896728515625 -0.4859716796875017 -0.807375 -0.0604248046875 -0.4859716796875017 -0.8074999999999999 -0.0604248046875 -0.4859716796875017 -0.807625 -0.0579833984375 -0.4859716796875017 -0.8077500000000001 -0.0579833984375 -0.4859716796875017 -0.8078749999999999 -0.05548095703125 -0.4859716796875017 -0.808 -0.053009033203125 -0.4859716796875017 -0.8081250000000001 -0.053009033203125 -0.4859716796875017 -0.80825 -0.050537109375 -0.4859716796875017 -0.808375 -0.050537109375 -0.4859716796875017 -0.8085000000000001 -0.04803466796875 -0.4859716796875017 -0.808625 -0.0455322265625 -0.4859716796875017 -0.80875 -0.0455322265625 -0.4859716796875017 -0.8088750000000001 -0.04302978515625 -0.4859716796875017 -0.809 -0.04302978515625 -0.4859716796875017 -0.809125 -0.04052734375 -0.4859716796875017 -0.8092500000000001 -0.03802490234375 -0.4859716796875017 -0.809375 -0.03802490234375 -0.4859716796875017 -0.8095000000000001 -0.035491943359375 -0.4859716796875017 -0.8096250000000001 -0.035491943359375 -0.4859716796875017 -0.80975 -0.032989501953125 -0.4859716796875017 -0.8098750000000001 -0.03045654296875 -0.4859716796875017 -0.8100000000000001 -0.03045654296875 -0.4859716796875017 -0.810125 -0.0279541015625 -0.4859716796875017 -0.8102500000000001 -0.0279541015625 -0.4859716796875017 -0.8103750000000002 -0.025421142578125 -0.4859716796875017 -0.8105 -0.02288818359375 -0.4859716796875017 -0.8106250000000001 -0.02288818359375 -0.4859716796875017 -0.81075 -0.020355224609375 -0.4859716796875017 -0.8108750000000001 -0.020355224609375 -0.4859716796875017 -0.8110000000000001 -0.017791748046875 -0.4859716796875017 -0.811125 -0.0152587890625 -0.4859716796875017 -0.8112500000000001 -0.0152587890625 -0.4859716796875017 -0.8113750000000001 -0.012725830078125 -0.4859716796875017 -0.8115 -0.012725830078125 -0.4859716796875017 -0.8116250000000001 -0.01019287109375 -0.4859716796875017 -0.81175 -0.007659912109375 -0.4859716796875017 -0.811875 -0.007659912109375 -0.4859716796875017 -0.8120000000000001 -0.005096435546875 -0.4859716796875017 -0.812125 -0.005096435546875 -0.4859716796875017 -0.81225 -0.0025634765625 -0.4859716796875017 +0.768 -0.106719970703125 -0.2701904296875024 +0.768125 -0.106719970703125 -0.2701904296875024 +0.76825 -0.10760498046875 -0.2701904296875024 +0.768375 -0.10760498046875 -0.2701904296875024 +0.7685 -0.108428955078125 -0.2701904296875024 +0.768625 -0.109283447265625 -0.2701904296875024 +0.76875 -0.109283447265625 -0.2701904296875024 +0.768875 -0.110107421875 -0.2701904296875024 +0.769 -0.110107421875 -0.2701904296875024 +0.769125 -0.110931396484375 -0.2701904296875024 +0.76925 -0.111724853515625 -0.2701904296875024 +0.7693750000000001 -0.111724853515625 -0.2701904296875024 +0.7694999999999999 -0.112518310546875 -0.2701904296875024 +0.769625 -0.112518310546875 -0.2701904296875024 +0.7697500000000001 -0.11328125 -0.2701904296875024 +0.769875 -0.114044189453125 -0.2701904296875024 +0.77 -0.114044189453125 -0.2701904296875024 +0.7701250000000001 -0.11480712890625 -0.2701904296875024 +0.77025 -0.11480712890625 -0.2701904296875024 +0.770375 -0.11553955078125 -0.2701904296875024 +0.7705 -0.11627197265625 -0.2701904296875024 +0.770625 -0.11627197265625 -0.2701904296875024 +0.77075 -0.116973876953125 -0.2701904296875024 +0.770875 -0.116973876953125 -0.2701904296875024 +0.771 -0.11767578125 -0.2701904296875024 +0.7711250000000001 -0.118377685546875 -0.2701904296875024 +0.77125 -0.118377685546875 -0.2701904296875024 +0.771375 -0.119049072265625 -0.2701904296875024 +0.7715 -0.119049072265625 -0.2701904296875024 +0.771625 -0.119720458984375 -0.2701904296875024 +0.77175 -0.120361328125 -0.2701904296875024 +0.771875 -0.120361328125 -0.2701904296875024 +0.7720000000000001 -0.121002197265625 -0.2701904296875024 +0.772125 -0.121002197265625 -0.2701904296875024 +0.77225 -0.121612548828125 -0.2701904296875024 +0.7723750000000001 -0.122222900390625 -0.2701904296875024 +0.7725 -0.122222900390625 -0.2701904296875024 +0.772625 -0.122802734375 -0.2701904296875024 +0.7727500000000001 -0.122802734375 -0.2701904296875024 +0.772875 -0.1234130859375 -0.2701904296875024 +0.773 -0.12396240234375 -0.2701904296875024 +0.7731250000000001 -0.12396240234375 -0.2701904296875024 +0.77325 -0.12451171875 -0.2701904296875024 +0.7733750000000001 -0.12451171875 -0.2701904296875024 +0.7734999999999999 -0.12506103515625 -0.2701904296875024 +0.773625 -0.125579833984375 -0.2701904296875024 +0.7737500000000001 -0.125579833984375 -0.2701904296875024 +0.773875 -0.1260986328125 -0.2701904296875024 +0.774 -0.1260986328125 -0.2701904296875024 +0.7741250000000001 -0.126617431640625 -0.2701904296875024 +0.77425 -0.127105712890625 -0.2701904296875024 +0.774375 -0.127105712890625 -0.2701904296875024 +0.7744999999999999 -0.1275634765625 -0.2701904296875024 +0.774625 -0.1275634765625 -0.2701904296875024 +0.77475 -0.128021240234375 -0.2701904296875024 +0.7748749999999999 -0.12847900390625 -0.2701904296875024 +0.775 -0.12847900390625 -0.2701904296875024 +0.7751250000000001 -0.12890625 -0.2701904296875024 +0.77525 -0.12890625 -0.2701904296875024 +0.775375 -0.129302978515625 -0.2701904296875024 +0.7755 -0.12969970703125 -0.2701904296875024 +0.775625 -0.12969970703125 -0.2701904296875024 +0.77575 -0.130096435546875 -0.2701904296875024 +0.775875 -0.130096435546875 -0.2701904296875024 +0.776 -0.130462646484375 -0.2701904296875024 +0.776125 -0.130828857421875 -0.2701904296875024 +0.77625 -0.130828857421875 -0.2701904296875024 +0.776375 -0.131195068359375 -0.2701904296875024 +0.7765 -0.131195068359375 -0.2701904296875024 +0.776625 -0.131500244140625 -0.2701904296875024 +0.77675 -0.1318359375 -0.2701904296875024 +0.776875 -0.1318359375 -0.2701904296875024 +0.777 -0.132110595703125 -0.2701904296875024 +0.777125 -0.132110595703125 -0.2701904296875024 +0.77725 -0.132415771484375 -0.2701904296875024 +0.7773750000000001 -0.1326904296875 -0.2701904296875024 +0.7774999999999999 -0.1326904296875 -0.2701904296875024 +0.777625 -0.1329345703125 -0.2701904296875024 +0.7777500000000001 -0.1329345703125 -0.2701904296875024 +0.777875 -0.1331787109375 -0.2701904296875024 +0.778 -0.1334228515625 -0.2701904296875024 +0.7781250000000001 -0.1334228515625 -0.2701904296875024 +0.77825 -0.133636474609375 -0.2701904296875024 +0.778375 -0.133636474609375 -0.2701904296875024 +0.7785 -0.133819580078125 -0.2701904296875024 +0.778625 -0.134002685546875 -0.2701904296875024 +0.7787500000000001 -0.134002685546875 -0.2701904296875024 +0.778875 -0.134185791015625 -0.2701904296875024 +0.779 -0.134185791015625 -0.2701904296875024 +0.7791250000000001 -0.13433837890625 -0.2701904296875024 +0.77925 -0.134490966796875 -0.2701904296875024 +0.779375 -0.134490966796875 -0.2701904296875024 +0.7795 -0.134613037109375 -0.2701904296875024 +0.7796250000000001 -0.134613037109375 -0.2701904296875024 +0.77975 -0.13470458984375 -0.2701904296875024 +0.779875 -0.13482666015625 -0.2701904296875024 +0.7800000000000001 -0.13482666015625 -0.2701904296875024 +0.780125 -0.1348876953125 -0.2701904296875024 +0.78025 -0.1348876953125 -0.2701904296875024 +0.7803750000000001 -0.13494873046875 -0.2701904296875024 +0.7805 -0.135009765625 -0.2701904296875024 +0.780625 -0.135009765625 -0.2701904296875024 +0.7807500000000001 -0.135040283203125 -0.2701904296875024 +0.780875 -0.135040283203125 -0.2701904296875024 +0.781 -0.13507080078125 -0.2701904296875024 +0.7811250000000001 -0.13507080078125 -0.2701904296875024 +0.78125 -0.13507080078125 -0.2701904296875024 +0.7813750000000001 -0.13507080078125 -0.2701904296875024 +0.7815 -0.13507080078125 -0.2701904296875024 +0.781625 -0.135040283203125 -0.2701904296875024 +0.7817500000000001 -0.135009765625 -0.2701904296875024 +0.781875 -0.135009765625 -0.2701904296875024 +0.782 -0.13494873046875 -0.2701904296875024 +0.7821250000000001 -0.13494873046875 -0.2701904296875024 +0.78225 -0.1348876953125 -0.2701904296875024 +0.782375 -0.13482666015625 -0.2701904296875024 +0.7824999999999999 -0.13482666015625 -0.2701904296875024 +0.782625 -0.13470458984375 -0.2701904296875024 +0.7827500000000001 -0.13470458984375 -0.2701904296875024 +0.7828749999999999 -0.134613037109375 -0.2701904296875024 +0.783 -0.134490966796875 -0.2701904296875024 +0.7831250000000001 -0.134490966796875 -0.2701904296875024 +0.78325 -0.13433837890625 -0.2701904296875024 +0.783375 -0.13433837890625 -0.2701904296875024 +0.7835 -0.134185791015625 -0.2701904296875024 +0.783625 -0.134002685546875 -0.2701904296875024 +0.78375 -0.134002685546875 -0.2701904296875024 +0.783875 -0.133819580078125 -0.2701904296875024 +0.784 -0.133819580078125 -0.2701904296875024 +0.784125 -0.133636474609375 -0.2701904296875024 +0.78425 -0.1334228515625 -0.2701904296875024 +0.784375 -0.1334228515625 -0.2701904296875024 +0.7845 -0.1331787109375 -0.2701904296875024 +0.784625 -0.1331787109375 -0.2701904296875024 +0.78475 -0.1329345703125 -0.2701904296875024 +0.784875 -0.1326904296875 -0.2701904296875024 +0.7850000000000001 -0.1326904296875 -0.2701904296875024 +0.7851249999999999 -0.132415771484375 -0.2701904296875024 +0.78525 -0.132415771484375 -0.2701904296875024 +0.7853750000000001 -0.132110595703125 -0.2701904296875024 +0.7855 -0.1318359375 -0.2701904296875024 +0.785625 -0.1318359375 -0.2701904296875024 +0.7857500000000001 -0.131500244140625 -0.2701904296875024 +0.785875 -0.131500244140625 -0.2701904296875024 +0.786 -0.131195068359375 -0.2701904296875024 +0.786125 -0.130828857421875 -0.2701904296875024 +0.78625 -0.130828857421875 -0.2701904296875024 +0.786375 -0.130462646484375 -0.2701904296875024 +0.7865 -0.130462646484375 -0.2701904296875024 +0.786625 -0.130096435546875 -0.2701904296875024 +0.7867500000000001 -0.12969970703125 -0.2701904296875024 +0.786875 -0.12969970703125 -0.2701904296875024 +0.787 -0.129302978515625 -0.2701904296875024 +0.787125 -0.129302978515625 -0.2701904296875024 +0.78725 -0.12890625 -0.2701904296875024 +0.787375 -0.12847900390625 -0.2701904296875024 +0.7875 -0.12847900390625 -0.2701904296875024 +0.7876250000000001 -0.128021240234375 -0.2701904296875024 +0.78775 -0.128021240234375 -0.2701904296875024 +0.787875 -0.1275634765625 -0.2701904296875024 +0.7880000000000001 -0.127105712890625 -0.2701904296875024 +0.788125 -0.127105712890625 -0.2701904296875024 +0.78825 -0.126617431640625 -0.2701904296875024 +0.7883750000000001 -0.126617431640625 -0.2701904296875024 +0.7885 -0.1260986328125 -0.2701904296875024 +0.788625 -0.125579833984375 -0.2701904296875024 +0.7887500000000001 -0.125579833984375 -0.2701904296875024 +0.788875 -0.12506103515625 -0.2701904296875024 +0.7890000000000001 -0.12506103515625 -0.2701904296875024 +0.7891249999999999 -0.12451171875 -0.2701904296875024 +0.78925 -0.12396240234375 -0.2701904296875024 +0.7893750000000001 -0.12396240234375 -0.2701904296875024 +0.7895 -0.1234130859375 -0.2701904296875024 +0.789625 -0.1234130859375 -0.2701904296875024 +0.7897500000000001 -0.122802734375 -0.2701904296875024 +0.789875 -0.122222900390625 -0.2701904296875024 +0.79 -0.122222900390625 -0.2701904296875024 +0.7901249999999999 -0.121612548828125 -0.2701904296875024 +0.79025 -0.121612548828125 -0.2701904296875024 +0.790375 -0.121002197265625 -0.2701904296875024 +0.7904999999999999 -0.120361328125 -0.2701904296875024 +0.790625 -0.120361328125 -0.2701904296875024 +0.7907500000000001 -0.119720458984375 -0.2701904296875024 +0.790875 -0.119720458984375 -0.2701904296875024 +0.791 -0.119049072265625 -0.2701904296875024 +0.791125 -0.118377685546875 -0.2701904296875024 +0.79125 -0.118377685546875 -0.2701904296875024 +0.791375 -0.11767578125 -0.2701904296875024 +0.7915 -0.11767578125 -0.2701904296875024 +0.791625 -0.116973876953125 -0.2701904296875024 +0.79175 -0.11627197265625 -0.2701904296875024 +0.791875 -0.11627197265625 -0.2701904296875024 +0.792 -0.11553955078125 -0.2701904296875024 +0.792125 -0.11553955078125 -0.2701904296875024 +0.79225 -0.11480712890625 -0.2701904296875024 +0.792375 -0.114044189453125 -0.2701904296875024 +0.7925 -0.114044189453125 -0.2701904296875024 +0.792625 -0.11328125 -0.2701904296875024 +0.79275 -0.11328125 -0.2701904296875024 +0.792875 -0.112518310546875 -0.2701904296875024 +0.7930000000000001 -0.111724853515625 -0.2701904296875024 +0.7931249999999999 -0.111724853515625 -0.2701904296875024 +0.79325 -0.110931396484375 -0.2701904296875024 +0.7933750000000001 -0.110931396484375 -0.2701904296875024 +0.7935 -0.110107421875 -0.2701904296875024 +0.793625 -0.109283447265625 -0.2701904296875024 +0.7937500000000001 -0.109283447265625 -0.2701904296875024 +0.793875 -0.108428955078125 -0.2701904296875024 +0.794 -0.108428955078125 -0.2701904296875024 +0.794125 -0.10760498046875 -0.2701904296875024 +0.79425 -0.106719970703125 -0.2701904296875024 +0.7943750000000001 -0.106719970703125 -0.2701904296875024 +0.7945 -0.105865478515625 -0.2701904296875024 +0.794625 -0.105865478515625 -0.2701904296875024 +0.7947500000000001 -0.10498046875 -0.2701904296875024 +0.794875 -0.10406494140625 -0.2701904296875024 +0.795 -0.10406494140625 -0.2701904296875024 +0.795125 -0.103179931640625 -0.2701904296875024 +0.7952500000000001 -0.103179931640625 -0.2701904296875024 +0.795375 -0.102264404296875 -0.2701904296875024 +0.7955 -0.101318359375 -0.2701904296875024 +0.7956250000000001 -0.101318359375 -0.2701904296875024 +0.79575 -0.100372314453125 -0.2701904296875024 +0.795875 -0.100372314453125 -0.2701904296875024 +0.7960000000000001 -0.09942626953125 -0.2701904296875024 +0.796125 -0.098480224609375 -0.2701904296875024 +0.79625 -0.098480224609375 -0.2701904296875024 +0.7963750000000001 -0.097503662109375 -0.2701904296875024 +0.7965 -0.097503662109375 -0.2701904296875024 +0.796625 -0.09649658203125 -0.2701904296875024 +0.7967500000000001 -0.09552001953125 -0.2701904296875024 +0.796875 -0.09552001953125 -0.2701904296875024 +0.7970000000000001 -0.094512939453125 -0.2701904296875024 +0.797125 -0.094512939453125 -0.2701904296875024 +0.79725 -0.093475341796875 -0.2701904296875024 +0.7973750000000001 -0.09246826171875 -0.2701904296875024 +0.7975 -0.09246826171875 -0.2701904296875024 +0.797625 -0.0914306640625 -0.2701904296875024 +0.7977500000000001 -0.0914306640625 -0.2701904296875024 +0.797875 -0.09039306640625 -0.2701904296875024 +0.798 -0.089324951171875 -0.2701904296875024 +0.7981249999999999 -0.089324951171875 -0.2701904296875024 +0.79825 -0.0882568359375 -0.2701904296875024 +0.7983750000000001 -0.0882568359375 -0.2701904296875024 +0.7984999999999999 -0.087188720703125 -0.2701904296875024 +0.798625 -0.086090087890625 -0.2701904296875024 +0.7987500000000001 -0.086090087890625 -0.2701904296875024 +0.798875 -0.084991455078125 -0.2701904296875024 +0.799 -0.084991455078125 -0.2701904296875024 +0.799125 -0.083892822265625 -0.2701904296875024 +0.79925 -0.082794189453125 -0.2701904296875024 +0.799375 -0.082794189453125 -0.2701904296875024 +0.7995 -0.0816650390625 -0.2701904296875024 +0.799625 -0.0816650390625 -0.2701904296875024 +0.79975 -0.080535888671875 -0.2701904296875024 +0.799875 -0.079376220703125 -0.2701904296875024 +0.8 -0.142791748046875 -0.4859716796875017 +0.8001249999999999 -0.1407470703125 -0.4859716796875017 +0.80025 -0.1407470703125 -0.4859716796875017 +0.800375 -0.138641357421875 -0.4859716796875017 +0.8004999999999999 -0.13653564453125 -0.4859716796875017 +0.800625 -0.13653564453125 -0.4859716796875017 +0.80075 -0.134429931640625 -0.4859716796875017 +0.8008749999999999 -0.134429931640625 -0.4859716796875017 +0.801 -0.13232421875 -0.4859716796875017 +0.801125 -0.13018798828125 -0.4859716796875017 +0.8012499999999999 -0.13018798828125 -0.4859716796875017 +0.801375 -0.128021240234375 -0.4859716796875017 +0.8015000000000001 -0.128021240234375 -0.4859716796875017 +0.8016249999999999 -0.1258544921875 -0.4859716796875017 +0.80175 -0.1236572265625 -0.4859716796875017 +0.8018750000000001 -0.1236572265625 -0.4859716796875017 +0.802 -0.1214599609375 -0.4859716796875017 +0.802125 -0.1214599609375 -0.4859716796875017 +0.8022500000000001 -0.1192626953125 -0.4859716796875017 +0.802375 -0.117034912109375 -0.4859716796875017 +0.8025 -0.117034912109375 -0.4859716796875017 +0.8026250000000001 -0.11480712890625 -0.4859716796875017 +0.80275 -0.11480712890625 -0.4859716796875017 +0.802875 -0.112548828125 -0.4859716796875017 +0.8030000000000001 -0.11029052734375 -0.4859716796875017 +0.803125 -0.11029052734375 -0.4859716796875017 +0.8032500000000001 -0.108001708984375 -0.4859716796875017 +0.8033750000000001 -0.108001708984375 -0.4859716796875017 +0.8035 -0.105743408203125 -0.4859716796875017 +0.8036250000000001 -0.103424072265625 -0.4859716796875017 +0.80375 -0.103424072265625 -0.4859716796875017 +0.803875 -0.10113525390625 -0.4859716796875017 +0.8040000000000001 -0.10113525390625 -0.4859716796875017 +0.804125 -0.09881591796875 -0.4859716796875017 +0.80425 -0.096466064453125 -0.4859716796875017 +0.8043750000000001 -0.096466064453125 -0.4859716796875017 +0.8045 -0.094146728515625 -0.4859716796875017 +0.8046250000000001 -0.094146728515625 -0.4859716796875017 +0.8047499999999999 -0.091796875 -0.4859716796875017 +0.804875 -0.08941650390625 -0.4859716796875017 +0.8050000000000001 -0.08941650390625 -0.4859716796875017 +0.805125 -0.087066650390625 -0.4859716796875017 +0.80525 -0.087066650390625 -0.4859716796875017 +0.8053750000000001 -0.084686279296875 -0.4859716796875017 +0.8055 -0.082275390625 -0.4859716796875017 +0.805625 -0.082275390625 -0.4859716796875017 +0.8057499999999999 -0.07989501953125 -0.4859716796875017 +0.805875 -0.07989501953125 -0.4859716796875017 +0.806 -0.077484130859375 -0.4859716796875017 +0.8061249999999999 -0.0750732421875 -0.4859716796875017 +0.80625 -0.0750732421875 -0.4859716796875017 +0.8063750000000001 -0.0726318359375 -0.4859716796875017 +0.8065 -0.0726318359375 -0.4859716796875017 +0.806625 -0.070220947265625 -0.4859716796875017 +0.8067499999999999 -0.067779541015625 -0.4859716796875017 +0.806875 -0.067779541015625 -0.4859716796875017 +0.807 -0.0653076171875 -0.4859716796875017 +0.8071249999999999 -0.0653076171875 -0.4859716796875017 +0.80725 -0.0628662109375 -0.4859716796875017 +0.807375 -0.060394287109375 -0.4859716796875017 +0.8074999999999999 -0.060394287109375 -0.4859716796875017 +0.807625 -0.057952880859375 -0.4859716796875017 +0.8077500000000001 -0.057952880859375 -0.4859716796875017 +0.8078749999999999 -0.055450439453125 -0.4859716796875017 +0.808 -0.052978515625 -0.4859716796875017 +0.8081250000000001 -0.052978515625 -0.4859716796875017 +0.80825 -0.050506591796875 -0.4859716796875017 +0.808375 -0.050506591796875 -0.4859716796875017 +0.8085000000000001 -0.048004150390625 -0.4859716796875017 +0.808625 -0.045501708984375 -0.4859716796875017 +0.80875 -0.045501708984375 -0.4859716796875017 +0.8088750000000001 -0.042999267578125 -0.4859716796875017 +0.809 -0.042999267578125 -0.4859716796875017 +0.809125 -0.040496826171875 -0.4859716796875017 +0.8092500000000001 -0.037994384765625 -0.4859716796875017 +0.809375 -0.037994384765625 -0.4859716796875017 +0.8095000000000001 -0.03546142578125 -0.4859716796875017 +0.8096250000000001 -0.03546142578125 -0.4859716796875017 +0.80975 -0.032958984375 -0.4859716796875017 +0.8098750000000001 -0.030426025390625 -0.4859716796875017 +0.8100000000000001 -0.030426025390625 -0.4859716796875017 +0.810125 -0.027923583984375 -0.4859716796875017 +0.8102500000000001 -0.027923583984375 -0.4859716796875017 +0.8103750000000002 -0.025390625 -0.4859716796875017 +0.8105 -0.022857666015625 -0.4859716796875017 +0.8106250000000001 -0.022857666015625 -0.4859716796875017 +0.81075 -0.02032470703125 -0.4859716796875017 +0.8108750000000001 -0.02032470703125 -0.4859716796875017 +0.8110000000000001 -0.01776123046875 -0.4859716796875017 +0.811125 -0.015228271484375 -0.4859716796875017 +0.8112500000000001 -0.015228271484375 -0.4859716796875017 +0.8113750000000001 -0.0126953125 -0.4859716796875017 +0.8115 -0.0126953125 -0.4859716796875017 +0.8116250000000001 -0.010162353515625 -0.4859716796875017 +0.81175 -0.00762939453125 -0.4859716796875017 +0.811875 -0.00762939453125 -0.4859716796875017 +0.8120000000000001 -0.00506591796875 -0.4859716796875017 +0.812125 -0.00506591796875 -0.4859716796875017 +0.81225 -0.002532958984375 -0.4859716796875017 0.8123750000000001 0.0 -0.4859716796875017 0.8125 0.0 -0.4859716796875017 0.8126250000000001 0.002532958984375 -0.4859716796875017 @@ -6999,504 +6999,504 @@ 0.87475 0.00299072265625 -0.572260742187499 0.8748750000000001 0.0 -0.572260742187499 0.875 0.0 -0.572260742187499 -0.8751250000000001 -0.003021240234375 -0.572260742187499 -0.87525 -0.003021240234375 -0.572260742187499 -0.875375 -0.006011962890625 -0.572260742187499 -0.8755000000000001 -0.009002685546875 -0.572260742187499 -0.875625 -0.009002685546875 -0.572260742187499 -0.87575 -0.011993408203125 -0.572260742187499 -0.8758750000000001 -0.011993408203125 -0.572260742187499 -0.876 -0.014984130859375 -0.572260742187499 -0.876125 -0.017974853515625 -0.572260742187499 -0.8762499999999999 -0.017974853515625 -0.572260742187499 -0.876375 -0.020965576171875 -0.572260742187499 -0.8765000000000001 -0.020965576171875 -0.572260742187499 -0.8766249999999999 -0.023956298828125 -0.572260742187499 -0.87675 -0.026947021484375 -0.572260742187499 -0.8768750000000001 -0.026947021484375 -0.572260742187499 -0.877 -0.029937744140625 -0.572260742187499 -0.877125 -0.029937744140625 -0.572260742187499 -0.8772499999999999 -0.03289794921875 -0.572260742187499 -0.877375 -0.035858154296875 -0.572260742187499 -0.8775 -0.035858154296875 -0.572260742187499 -0.8776249999999999 -0.038848876953125 -0.572260742187499 -0.87775 -0.038848876953125 -0.572260742187499 -0.877875 -0.04180908203125 -0.572260742187499 -0.8779999999999999 -0.044769287109375 -0.572260742187499 -0.878125 -0.044769287109375 -0.572260742187499 -0.8782499999999999 -0.0477294921875 -0.572260742187499 -0.878375 -0.0477294921875 -0.572260742187499 -0.8785 -0.050689697265625 -0.572260742187499 -0.8786249999999999 -0.053619384765625 -0.572260742187499 -0.87875 -0.053619384765625 -0.572260742187499 -0.878875 -0.056549072265625 -0.572260742187499 -0.8789999999999999 -0.056549072265625 -0.572260742187499 -0.879125 -0.05950927734375 -0.572260742187499 -0.87925 -0.062408447265625 -0.572260742187499 -0.8793749999999999 -0.062408447265625 -0.572260742187499 -0.8795 -0.065338134765625 -0.572260742187499 -0.8796250000000001 -0.065338134765625 -0.572260742187499 -0.8797499999999999 -0.068267822265625 -0.572260742187499 -0.879875 -0.0711669921875 -0.572260742187499 -0.8800000000000001 -0.0711669921875 -0.572260742187499 -0.880125 -0.074066162109375 -0.572260742187499 -0.88025 -0.074066162109375 -0.572260742187499 -0.8803750000000001 -0.07696533203125 -0.572260742187499 -0.8805 -0.079833984375 -0.572260742187499 -0.880625 -0.079833984375 -0.572260742187499 -0.8807500000000001 -0.08270263671875 -0.572260742187499 -0.880875 -0.08270263671875 -0.572260742187499 -0.881 -0.0855712890625 -0.572260742187499 -0.8811250000000001 -0.08843994140625 -0.572260742187499 -0.88125 -0.08843994140625 -0.572260742187499 -0.8813750000000001 -0.091278076171875 -0.572260742187499 -0.8815000000000001 -0.091278076171875 -0.572260742187499 -0.881625 -0.0941162109375 -0.572260742187499 -0.8817500000000001 -0.096923828125 -0.572260742187499 -0.881875 -0.096923828125 -0.572260742187499 -0.882 -0.0997314453125 -0.572260742187499 -0.8821250000000001 -0.0997314453125 -0.572260742187499 -0.88225 -0.1025390625 -0.572260742187499 -0.882375 -0.1053466796875 -0.572260742187499 -0.8825000000000001 -0.1053466796875 -0.572260742187499 -0.882625 -0.108123779296875 -0.572260742187499 -0.8827500000000001 -0.108123779296875 -0.572260742187499 -0.8828749999999999 -0.11090087890625 -0.572260742187499 -0.883 -0.1136474609375 -0.572260742187499 -0.8831250000000001 -0.1136474609375 -0.572260742187499 -0.88325 -0.11639404296875 -0.572260742187499 -0.883375 -0.11639404296875 -0.572260742187499 -0.8835000000000001 -0.119110107421875 -0.572260742187499 -0.883625 -0.121826171875 -0.572260742187499 -0.88375 -0.121826171875 -0.572260742187499 -0.8838749999999999 -0.124542236328125 -0.572260742187499 -0.884 -0.124542236328125 -0.572260742187499 -0.884125 -0.127227783203125 -0.572260742187499 -0.8842499999999999 -0.129913330078125 -0.572260742187499 -0.884375 -0.129913330078125 -0.572260742187499 -0.8845000000000001 -0.132568359375 -0.572260742187499 -0.884625 -0.132568359375 -0.572260742187499 -0.88475 -0.135223388671875 -0.572260742187499 -0.8848749999999999 -0.137847900390625 -0.572260742187499 -0.885 -0.137847900390625 -0.572260742187499 -0.885125 -0.140472412109375 -0.572260742187499 -0.8852499999999999 -0.140472412109375 -0.572260742187499 -0.885375 -0.14306640625 -0.572260742187499 -0.8855 -0.145660400390625 -0.572260742187499 -0.8856249999999999 -0.145660400390625 -0.572260742187499 -0.88575 -0.148223876953125 -0.572260742187499 -0.8858750000000001 -0.148223876953125 -0.572260742187499 -0.8859999999999999 -0.150787353515625 -0.572260742187499 -0.886125 -0.1533203125 -0.572260742187499 -0.8862500000000001 -0.1533203125 -0.572260742187499 -0.886375 -0.155853271484375 -0.572260742187499 -0.8865 -0.155853271484375 -0.572260742187499 -0.8866250000000001 -0.158355712890625 -0.572260742187499 -0.88675 -0.16082763671875 -0.572260742187499 -0.886875 -0.16082763671875 -0.572260742187499 -0.8870000000000001 -0.163299560546875 -0.572260742187499 -0.887125 -0.163299560546875 -0.572260742187499 -0.88725 -0.165771484375 -0.572260742187499 -0.8873750000000001 -0.168182373046875 -0.572260742187499 -0.8875 -0.168182373046875 -0.572260742187499 -0.8876250000000001 -0.17059326171875 -0.572260742187499 -0.8877500000000001 -0.17059326171875 -0.572260742187499 -0.887875 -0.173004150390625 -0.572260742187499 -0.8880000000000001 -0.175384521484375 -0.572260742187499 -0.8881250000000001 -0.175384521484375 -0.572260742187499 -0.88825 -0.177734375 -0.572260742187499 -0.8883750000000001 -0.177734375 -0.572260742187499 -0.8885000000000002 -0.180084228515625 -0.572260742187499 -0.888625 -0.182403564453125 -0.572260742187499 -0.8887500000000001 -0.182403564453125 -0.572260742187499 -0.888875 -0.1846923828125 -0.572260742187499 -0.8890000000000001 -0.1846923828125 -0.572260742187499 -0.8891250000000001 -0.186981201171875 -0.572260742187499 -0.88925 -0.189239501953125 -0.572260742187499 -0.8893750000000001 -0.189239501953125 -0.572260742187499 -0.8895000000000001 -0.19146728515625 -0.572260742187499 -0.889625 -0.19146728515625 -0.572260742187499 -0.8897500000000001 -0.193695068359375 -0.572260742187499 -0.889875 -0.19586181640625 -0.572260742187499 -0.89 -0.19586181640625 -0.572260742187499 -0.8901250000000001 -0.19805908203125 -0.572260742187499 -0.89025 -0.19805908203125 -0.572260742187499 -0.890375 -0.2001953125 -0.572260742187499 -0.8905000000000001 -0.20233154296875 -0.572260742187499 -0.890625 -0.20233154296875 -0.572260742187499 -0.8907500000000001 -0.204437255859375 -0.572260742187499 -0.890875 -0.204437255859375 -0.572260742187499 -0.891 -0.206512451171875 -0.572260742187499 -0.8911250000000001 -0.208587646484375 -0.572260742187499 -0.89125 -0.208587646484375 -0.572260742187499 -0.891375 -0.21063232421875 -0.572260742187499 -0.8915000000000001 -0.21063232421875 -0.572260742187499 -0.891625 -0.212646484375 -0.572260742187499 -0.89175 -0.214630126953125 -0.572260742187499 -0.8918749999999999 -0.214630126953125 -0.572260742187499 -0.892 -0.21661376953125 -0.572260742187499 -0.8921250000000001 -0.21661376953125 -0.572260742187499 -0.8922499999999999 -0.21856689453125 -0.572260742187499 -0.892375 -0.220458984375 -0.572260742187499 -0.8925000000000001 -0.220458984375 -0.572260742187499 -0.892625 -0.222381591796875 -0.572260742187499 -0.89275 -0.222381591796875 -0.572260742187499 -0.8928749999999999 -0.2242431640625 -0.572260742187499 -0.893 -0.226104736328125 -0.572260742187499 -0.893125 -0.226104736328125 -0.572260742187499 -0.8932499999999999 -0.2279052734375 -0.572260742187499 -0.893375 -0.2279052734375 -0.572260742187499 -0.8935 -0.229705810546875 -0.572260742187499 -0.8936249999999999 -0.23150634765625 -0.572260742187499 -0.89375 -0.23150634765625 -0.572260742187499 -0.8938749999999999 -0.233245849609375 -0.572260742187499 -0.894 -0.233245849609375 -0.572260742187499 -0.894125 -0.234954833984375 -0.572260742187499 -0.8942499999999999 -0.236663818359375 -0.572260742187499 -0.894375 -0.236663818359375 -0.572260742187499 -0.8945 -0.23834228515625 -0.572260742187499 -0.8946249999999999 -0.23834228515625 -0.572260742187499 -0.89475 -0.239959716796875 -0.572260742187499 -0.894875 -0.241607666015625 -0.572260742187499 -0.8949999999999999 -0.241607666015625 -0.572260742187499 -0.895125 -0.243194580078125 -0.572260742187499 -0.8952500000000001 -0.243194580078125 -0.572260742187499 -0.8953749999999999 -0.2447509765625 -0.572260742187499 -0.8955 -0.24627685546875 -0.572260742187499 -0.8956250000000001 -0.24627685546875 -0.572260742187499 -0.89575 -0.247802734375 -0.572260742187499 -0.895875 -0.247802734375 -0.572260742187499 -0.8960000000000001 -0.1868896484375 -0.4289990234374976 -0.896125 -0.187957763671875 -0.4289990234374976 -0.89625 -0.187957763671875 -0.4289990234374976 -0.8963750000000001 -0.18902587890625 -0.4289990234374976 -0.8965 -0.18902587890625 -0.4289990234374976 -0.896625 -0.190093994140625 -0.4289990234374976 -0.8967500000000001 -0.191131591796875 -0.4289990234374976 -0.896875 -0.191131591796875 -0.4289990234374976 -0.8970000000000001 -0.192138671875 -0.4289990234374976 -0.8971250000000001 -0.192138671875 -0.4289990234374976 -0.89725 -0.193115234375 -0.4289990234374976 -0.8973750000000001 -0.194091796875 -0.4289990234374976 -0.8975 -0.194091796875 -0.4289990234374976 -0.897625 -0.195037841796875 -0.4289990234374976 -0.8977500000000001 -0.195037841796875 -0.4289990234374976 -0.897875 -0.195953369140625 -0.4289990234374976 -0.898 -0.196868896484375 -0.4289990234374976 -0.8981250000000001 -0.196868896484375 -0.4289990234374976 -0.89825 -0.197723388671875 -0.4289990234374976 -0.8983750000000001 -0.197723388671875 -0.4289990234374976 -0.8984999999999999 -0.1986083984375 -0.4289990234374976 -0.898625 -0.199432373046875 -0.4289990234374976 -0.8987500000000001 -0.199432373046875 -0.4289990234374976 -0.898875 -0.20025634765625 -0.4289990234374976 -0.899 -0.20025634765625 -0.4289990234374976 -0.8991250000000001 -0.2010498046875 -0.4289990234374976 -0.89925 -0.201812744140625 -0.4289990234374976 -0.899375 -0.201812744140625 -0.4289990234374976 -0.8994999999999999 -0.20257568359375 -0.4289990234374976 -0.899625 -0.20257568359375 -0.4289990234374976 -0.89975 -0.20330810546875 -0.4289990234374976 -0.8998749999999999 -0.204010009765625 -0.4289990234374976 -0.9 -0.204010009765625 -0.4289990234374976 -0.9001250000000001 -0.204681396484375 -0.4289990234374976 -0.90025 -0.204681396484375 -0.4289990234374976 -0.900375 -0.205352783203125 -0.4289990234374976 -0.9004999999999999 -0.20599365234375 -0.4289990234374976 -0.900625 -0.20599365234375 -0.4289990234374976 -0.90075 -0.20660400390625 -0.4289990234374976 -0.9008749999999999 -0.20660400390625 -0.4289990234374976 -0.901 -0.207183837890625 -0.4289990234374976 -0.901125 -0.207763671875 -0.4289990234374976 -0.9012499999999999 -0.207763671875 -0.4289990234374976 -0.901375 -0.20831298828125 -0.4289990234374976 -0.9015000000000001 -0.20831298828125 -0.4289990234374976 -0.9016249999999999 -0.208831787109375 -0.4289990234374976 -0.90175 -0.209320068359375 -0.4289990234374976 -0.9018750000000001 -0.209320068359375 -0.4289990234374976 -0.902 -0.209808349609375 -0.4289990234374976 -0.902125 -0.209808349609375 -0.4289990234374976 -0.9022500000000001 -0.21026611328125 -0.4289990234374976 -0.902375 -0.210693359375 -0.4289990234374976 -0.9025 -0.210693359375 -0.4289990234374976 -0.9026250000000001 -0.21112060546875 -0.4289990234374976 -0.90275 -0.21112060546875 -0.4289990234374976 -0.902875 -0.21148681640625 -0.4289990234374976 -0.9030000000000001 -0.21185302734375 -0.4289990234374976 -0.903125 -0.21185302734375 -0.4289990234374976 -0.9032500000000001 -0.212188720703125 -0.4289990234374976 -0.9033750000000001 -0.212188720703125 -0.4289990234374976 -0.9035 -0.2125244140625 -0.4289990234374976 -0.9036250000000001 -0.212799072265625 -0.4289990234374976 -0.9037500000000001 -0.212799072265625 -0.4289990234374976 -0.903875 -0.21307373046875 -0.4289990234374976 -0.9040000000000001 -0.21307373046875 -0.4289990234374976 -0.9041250000000002 -0.21331787109375 -0.4289990234374976 -0.90425 -0.213531494140625 -0.4289990234374976 -0.9043750000000001 -0.213531494140625 -0.4289990234374976 -0.9045 -0.2137451171875 -0.4289990234374976 -0.9046250000000001 -0.2137451171875 -0.4289990234374976 -0.9047500000000001 -0.21392822265625 -0.4289990234374976 -0.904875 -0.214080810546875 -0.4289990234374976 -0.9050000000000001 -0.214080810546875 -0.4289990234374976 -0.9051250000000001 -0.214202880859375 -0.4289990234374976 -0.90525 -0.214202880859375 -0.4289990234374976 -0.9053750000000001 -0.214324951171875 -0.4289990234374976 -0.9055 -0.214385986328125 -0.4289990234374976 -0.905625 -0.214385986328125 -0.4289990234374976 -0.9057500000000001 -0.214447021484375 -0.4289990234374976 -0.905875 -0.214447021484375 -0.4289990234374976 -0.906 -0.2144775390625 -0.4289990234374976 -0.9061250000000001 -0.214508056640625 -0.4289990234374976 -0.90625 -0.214508056640625 -0.4289990234374976 -0.9063750000000001 -0.2144775390625 -0.4289990234374976 -0.9065 -0.2144775390625 -0.4289990234374976 -0.906625 -0.214447021484375 -0.4289990234374976 -0.9067500000000001 -0.214385986328125 -0.4289990234374976 -0.906875 -0.214385986328125 -0.4289990234374976 -0.907 -0.214324951171875 -0.4289990234374976 -0.9071250000000001 -0.214324951171875 -0.4289990234374976 -0.90725 -0.214202880859375 -0.4289990234374976 -0.907375 -0.214080810546875 -0.4289990234374976 -0.9074999999999999 -0.214080810546875 -0.4289990234374976 -0.907625 -0.21392822265625 -0.4289990234374976 -0.9077500000000001 -0.21392822265625 -0.4289990234374976 -0.9078749999999999 -0.2137451171875 -0.4289990234374976 -0.908 -0.213531494140625 -0.4289990234374976 -0.9081250000000001 -0.213531494140625 -0.4289990234374976 -0.90825 -0.21331787109375 -0.4289990234374976 -0.908375 -0.21331787109375 -0.4289990234374976 -0.9084999999999999 -0.21307373046875 -0.4289990234374976 -0.908625 -0.212799072265625 -0.4289990234374976 -0.90875 -0.212799072265625 -0.4289990234374976 -0.9088749999999999 -0.2125244140625 -0.4289990234374976 -0.909 -0.2125244140625 -0.4289990234374976 -0.909125 -0.212188720703125 -0.4289990234374976 -0.9092499999999999 -0.21185302734375 -0.4289990234374976 -0.909375 -0.21185302734375 -0.4289990234374976 -0.9094999999999999 -0.21148681640625 -0.4289990234374976 -0.909625 -0.21148681640625 -0.4289990234374976 -0.90975 -0.21112060546875 -0.4289990234374976 -0.9098749999999999 -0.210693359375 -0.4289990234374976 -0.91 -0.210693359375 -0.4289990234374976 -0.910125 -0.21026611328125 -0.4289990234374976 -0.9102499999999999 -0.21026611328125 -0.4289990234374976 -0.910375 -0.209808349609375 -0.4289990234374976 -0.9105 -0.209320068359375 -0.4289990234374976 -0.9106249999999999 -0.209320068359375 -0.4289990234374976 -0.91075 -0.208831787109375 -0.4289990234374976 -0.9108750000000001 -0.208831787109375 -0.4289990234374976 -0.9109999999999999 -0.20831298828125 -0.4289990234374976 -0.911125 -0.207763671875 -0.4289990234374976 -0.9112500000000001 -0.207763671875 -0.4289990234374976 -0.911375 -0.207183837890625 -0.4289990234374976 -0.9115 -0.207183837890625 -0.4289990234374976 -0.9116250000000001 -0.20660400390625 -0.4289990234374976 -0.91175 -0.20599365234375 -0.4289990234374976 -0.911875 -0.20599365234375 -0.4289990234374976 -0.9120000000000001 -0.205352783203125 -0.4289990234374976 -0.912125 -0.205352783203125 -0.4289990234374976 -0.91225 -0.204681396484375 -0.4289990234374976 -0.9123750000000001 -0.204010009765625 -0.4289990234374976 -0.9125 -0.204010009765625 -0.4289990234374976 -0.9126250000000001 -0.20330810546875 -0.4289990234374976 -0.9127500000000001 -0.20330810546875 -0.4289990234374976 -0.912875 -0.20257568359375 -0.4289990234374976 -0.9130000000000001 -0.201812744140625 -0.4289990234374976 -0.913125 -0.201812744140625 -0.4289990234374976 -0.91325 -0.2010498046875 -0.4289990234374976 -0.9133750000000001 -0.2010498046875 -0.4289990234374976 -0.9135 -0.20025634765625 -0.4289990234374976 -0.913625 -0.199432373046875 -0.4289990234374976 -0.9137500000000001 -0.199432373046875 -0.4289990234374976 -0.913875 -0.1986083984375 -0.4289990234374976 -0.9140000000000001 -0.1986083984375 -0.4289990234374976 -0.9141249999999999 -0.197723388671875 -0.4289990234374976 -0.91425 -0.196868896484375 -0.4289990234374976 -0.9143750000000001 -0.196868896484375 -0.4289990234374976 -0.9145 -0.195953369140625 -0.4289990234374976 -0.914625 -0.195953369140625 -0.4289990234374976 -0.9147500000000001 -0.195037841796875 -0.4289990234374976 -0.914875 -0.194091796875 -0.4289990234374976 -0.915 -0.194091796875 -0.4289990234374976 -0.9151249999999999 -0.193115234375 -0.4289990234374976 -0.91525 -0.193115234375 -0.4289990234374976 -0.915375 -0.192138671875 -0.4289990234374976 -0.9154999999999999 -0.191131591796875 -0.4289990234374976 -0.915625 -0.191131591796875 -0.4289990234374976 -0.9157500000000001 -0.190093994140625 -0.4289990234374976 -0.915875 -0.190093994140625 -0.4289990234374976 -0.916 -0.18902587890625 -0.4289990234374976 -0.9161249999999999 -0.187957763671875 -0.4289990234374976 -0.91625 -0.187957763671875 -0.4289990234374976 -0.916375 -0.1868896484375 -0.4289990234374976 -0.9164999999999999 -0.1868896484375 -0.4289990234374976 -0.916625 -0.185760498046875 -0.4289990234374976 -0.91675 -0.18463134765625 -0.4289990234374976 -0.9168749999999999 -0.18463134765625 -0.4289990234374976 -0.917 -0.1834716796875 -0.4289990234374976 -0.9171250000000001 -0.1834716796875 -0.4289990234374976 -0.9172499999999999 -0.18231201171875 -0.4289990234374976 -0.917375 -0.181121826171875 -0.4289990234374976 -0.9175000000000001 -0.181121826171875 -0.4289990234374976 -0.917625 -0.179901123046875 -0.4289990234374976 -0.91775 -0.179901123046875 -0.4289990234374976 -0.9178750000000001 -0.17864990234375 -0.4289990234374976 -0.918 -0.177398681640625 -0.4289990234374976 -0.918125 -0.177398681640625 -0.4289990234374976 -0.9182500000000001 -0.1761474609375 -0.4289990234374976 -0.918375 -0.1761474609375 -0.4289990234374976 -0.9185 -0.174835205078125 -0.4289990234374976 -0.9186250000000001 -0.17352294921875 -0.4289990234374976 -0.91875 -0.17352294921875 -0.4289990234374976 -0.9188750000000001 -0.172210693359375 -0.4289990234374976 -0.9190000000000001 -0.172210693359375 -0.4289990234374976 -0.919125 -0.170867919921875 -0.4289990234374976 -0.9192500000000001 -0.16949462890625 -0.4289990234374976 -0.9193750000000001 -0.16949462890625 -0.4289990234374976 -0.9195 -0.1680908203125 -0.4289990234374976 -0.9196250000000001 -0.1680908203125 -0.4289990234374976 -0.9197500000000002 -0.16668701171875 -0.4289990234374976 -0.919875 -0.165283203125 -0.4289990234374976 -0.9200000000000001 -0.165283203125 -0.4289990234374976 -0.920125 -0.163848876953125 -0.4289990234374976 -0.9202500000000001 -0.163848876953125 -0.4289990234374976 -0.9203750000000001 -0.162384033203125 -0.4289990234374976 -0.9205 -0.160888671875 -0.4289990234374976 -0.9206250000000001 -0.160888671875 -0.4289990234374976 -0.9207500000000001 -0.159393310546875 -0.4289990234374976 -0.920875 -0.159393310546875 -0.4289990234374976 -0.9210000000000001 -0.15789794921875 -0.4289990234374976 -0.921125 -0.1563720703125 -0.4289990234374976 -0.92125 -0.1563720703125 -0.4289990234374976 -0.9213750000000001 -0.154815673828125 -0.4289990234374976 -0.9215 -0.154815673828125 -0.4289990234374976 -0.921625 -0.15325927734375 -0.4289990234374976 -0.9217500000000001 -0.15167236328125 -0.4289990234374976 -0.921875 -0.15167236328125 -0.4289990234374976 -0.9220000000000001 -0.15008544921875 -0.4289990234374976 -0.922125 -0.15008544921875 -0.4289990234374976 -0.92225 -0.148468017578125 -0.4289990234374976 -0.9223750000000001 -0.1468505859375 -0.4289990234374976 -0.9225 -0.1468505859375 -0.4289990234374976 -0.922625 -0.14520263671875 -0.4289990234374976 -0.9227500000000001 -0.14520263671875 -0.4289990234374976 -0.922875 -0.143524169921875 -0.4289990234374976 -0.923 -0.141845703125 -0.4289990234374976 -0.9231249999999999 -0.141845703125 -0.4289990234374976 -0.92325 -0.140167236328125 -0.4289990234374976 -0.9233750000000001 -0.140167236328125 -0.4289990234374976 -0.9234999999999999 -0.138458251953125 -0.4289990234374976 -0.923625 -0.13671875 -0.4289990234374976 -0.9237500000000001 -0.13671875 -0.4289990234374976 -0.923875 -0.134979248046875 -0.4289990234374976 -0.924 -0.134979248046875 -0.4289990234374976 -0.9241249999999999 -0.13323974609375 -0.4289990234374976 -0.92425 -0.1314697265625 -0.4289990234374976 -0.924375 -0.1314697265625 -0.4289990234374976 -0.9244999999999999 -0.12969970703125 -0.4289990234374976 -0.924625 -0.12969970703125 -0.4289990234374976 -0.92475 -0.127899169921875 -0.4289990234374976 -0.9248749999999999 -0.126068115234375 -0.4289990234374976 -0.925 -0.126068115234375 -0.4289990234374976 -0.9251249999999999 -0.124267578125 -0.4289990234374976 -0.92525 -0.124267578125 -0.4289990234374976 -0.925375 -0.1224365234375 -0.4289990234374976 -0.9254999999999999 -0.120574951171875 -0.4289990234374976 -0.925625 -0.120574951171875 -0.4289990234374976 -0.92575 -0.11871337890625 -0.4289990234374976 -0.9258749999999999 -0.11871337890625 -0.4289990234374976 -0.926 -0.1168212890625 -0.4289990234374976 -0.926125 -0.11492919921875 -0.4289990234374976 -0.9262499999999999 -0.11492919921875 -0.4289990234374976 -0.926375 -0.113037109375 -0.4289990234374976 -0.9265000000000001 -0.113037109375 -0.4289990234374976 -0.9266249999999999 -0.111114501953125 -0.4289990234374976 -0.92675 -0.10919189453125 -0.4289990234374976 -0.9268750000000001 -0.10919189453125 -0.4289990234374976 -0.927 -0.107269287109375 -0.4289990234374976 -0.927125 -0.107269287109375 -0.4289990234374976 -0.9272500000000001 -0.105316162109375 -0.4289990234374976 -0.927375 -0.10333251953125 -0.4289990234374976 -0.9275 -0.10333251953125 -0.4289990234374976 -0.9276250000000001 -0.10137939453125 -0.4289990234374976 -0.92775 -0.10137939453125 -0.4289990234374976 -0.927875 -0.099395751953125 -0.4289990234374976 -0.9280000000000001 -0.042083740234375 -0.1853759765624967 -0.928125 -0.042083740234375 -0.1853759765624967 -0.9282500000000001 -0.041229248046875 -0.1853759765624967 -0.9283750000000001 -0.041229248046875 -0.1853759765624967 -0.9285 -0.04034423828125 -0.1853759765624967 -0.9286250000000001 -0.03948974609375 -0.1853759765624967 -0.92875 -0.03948974609375 -0.1853759765624967 -0.928875 -0.038604736328125 -0.1853759765624967 -0.9290000000000001 -0.038604736328125 -0.1853759765624967 -0.929125 -0.0377197265625 -0.1853759765624967 -0.92925 -0.036834716796875 -0.1853759765624967 -0.9293750000000001 -0.036834716796875 -0.1853759765624967 -0.9295 -0.035919189453125 -0.1853759765624967 -0.9296250000000001 -0.035919189453125 -0.1853759765624967 -0.9297499999999999 -0.0350341796875 -0.1853759765624967 -0.929875 -0.03411865234375 -0.1853759765624967 -0.9300000000000001 -0.03411865234375 -0.1853759765624967 -0.930125 -0.033233642578125 -0.1853759765624967 -0.93025 -0.033233642578125 -0.1853759765624967 -0.9303750000000001 -0.032318115234375 -0.1853759765624967 -0.9305 -0.031402587890625 -0.1853759765624967 -0.930625 -0.031402587890625 -0.1853759765624967 -0.9307499999999999 -0.030487060546875 -0.1853759765624967 -0.930875 -0.030487060546875 -0.1853759765624967 -0.931 -0.029571533203125 -0.1853759765624967 -0.9311249999999999 -0.028656005859375 -0.1853759765624967 -0.93125 -0.028656005859375 -0.1853759765624967 -0.9313750000000001 -0.027740478515625 -0.1853759765624967 -0.9315 -0.027740478515625 -0.1853759765624967 -0.931625 -0.02679443359375 -0.1853759765624967 -0.9317499999999999 -0.02587890625 -0.1853759765624967 -0.931875 -0.02587890625 -0.1853759765624967 -0.932 -0.024932861328125 -0.1853759765624967 -0.9321249999999999 -0.024932861328125 -0.1853759765624967 -0.93225 -0.02398681640625 -0.1853759765624967 -0.932375 -0.0230712890625 -0.1853759765624967 -0.9324999999999999 -0.0230712890625 -0.1853759765624967 -0.932625 -0.022125244140625 -0.1853759765624967 -0.9327500000000001 -0.022125244140625 -0.1853759765624967 -0.9328749999999999 -0.02117919921875 -0.1853759765624967 -0.933 -0.020233154296875 -0.1853759765624967 -0.9331250000000001 -0.020233154296875 -0.1853759765624967 -0.93325 -0.019287109375 -0.1853759765624967 -0.933375 -0.019287109375 -0.1853759765624967 -0.9335000000000001 -0.018341064453125 -0.1853759765624967 -0.933625 -0.017364501953125 -0.1853759765624967 -0.93375 -0.017364501953125 -0.1853759765624967 -0.9338750000000001 -0.01641845703125 -0.1853759765624967 -0.934 -0.01641845703125 -0.1853759765624967 -0.934125 -0.015472412109375 -0.1853759765624967 -0.9342500000000001 -0.014495849609375 -0.1853759765624967 -0.934375 -0.014495849609375 -0.1853759765624967 -0.9345000000000001 -0.0135498046875 -0.1853759765624967 -0.9346250000000001 -0.0135498046875 -0.1853759765624967 -0.93475 -0.012603759765625 -0.1853759765624967 -0.9348750000000001 -0.011627197265625 -0.1853759765624967 -0.9350000000000001 -0.011627197265625 -0.1853759765624967 -0.935125 -0.01068115234375 -0.1853759765624967 -0.9352500000000001 -0.01068115234375 -0.1853759765624967 -0.9353750000000002 -0.00970458984375 -0.1853759765624967 -0.9355 -0.00872802734375 -0.1853759765624967 -0.9356250000000001 -0.00872802734375 -0.1853759765624967 -0.93575 -0.007781982421875 -0.1853759765624967 -0.9358750000000001 -0.007781982421875 -0.1853759765624967 -0.9360000000000001 -0.006805419921875 -0.1853759765624967 -0.936125 -0.005828857421875 -0.1853759765624967 -0.9362500000000001 -0.005828857421875 -0.1853759765624967 -0.9363750000000001 -0.004852294921875 -0.1853759765624967 -0.9365 -0.004852294921875 -0.1853759765624967 -0.9366250000000001 -0.00390625 -0.1853759765624967 -0.93675 -0.0029296875 -0.1853759765624967 -0.936875 -0.0029296875 -0.1853759765624967 -0.9370000000000001 -0.001953125 -0.1853759765624967 -0.937125 -0.001953125 -0.1853759765624967 -0.93725 -0.0009765625 -0.1853759765624967 +0.8751250000000001 -0.00299072265625 -0.572260742187499 +0.87525 -0.00299072265625 -0.572260742187499 +0.875375 -0.0059814453125 -0.572260742187499 +0.8755000000000001 -0.00897216796875 -0.572260742187499 +0.875625 -0.00897216796875 -0.572260742187499 +0.87575 -0.011962890625 -0.572260742187499 +0.8758750000000001 -0.011962890625 -0.572260742187499 +0.876 -0.01495361328125 -0.572260742187499 +0.876125 -0.0179443359375 -0.572260742187499 +0.8762499999999999 -0.0179443359375 -0.572260742187499 +0.876375 -0.02093505859375 -0.572260742187499 +0.8765000000000001 -0.02093505859375 -0.572260742187499 +0.8766249999999999 -0.02392578125 -0.572260742187499 +0.87675 -0.02691650390625 -0.572260742187499 +0.8768750000000001 -0.02691650390625 -0.572260742187499 +0.877 -0.0299072265625 -0.572260742187499 +0.877125 -0.0299072265625 -0.572260742187499 +0.8772499999999999 -0.032867431640625 -0.572260742187499 +0.877375 -0.03582763671875 -0.572260742187499 +0.8775 -0.03582763671875 -0.572260742187499 +0.8776249999999999 -0.038818359375 -0.572260742187499 +0.87775 -0.038818359375 -0.572260742187499 +0.877875 -0.041778564453125 -0.572260742187499 +0.8779999999999999 -0.04473876953125 -0.572260742187499 +0.878125 -0.04473876953125 -0.572260742187499 +0.8782499999999999 -0.047698974609375 -0.572260742187499 +0.878375 -0.047698974609375 -0.572260742187499 +0.8785 -0.0506591796875 -0.572260742187499 +0.8786249999999999 -0.0535888671875 -0.572260742187499 +0.87875 -0.0535888671875 -0.572260742187499 +0.878875 -0.0565185546875 -0.572260742187499 +0.8789999999999999 -0.0565185546875 -0.572260742187499 +0.879125 -0.059478759765625 -0.572260742187499 +0.87925 -0.0623779296875 -0.572260742187499 +0.8793749999999999 -0.0623779296875 -0.572260742187499 +0.8795 -0.0653076171875 -0.572260742187499 +0.8796250000000001 -0.0653076171875 -0.572260742187499 +0.8797499999999999 -0.0682373046875 -0.572260742187499 +0.879875 -0.071136474609375 -0.572260742187499 +0.8800000000000001 -0.071136474609375 -0.572260742187499 +0.880125 -0.07403564453125 -0.572260742187499 +0.88025 -0.07403564453125 -0.572260742187499 +0.8803750000000001 -0.076934814453125 -0.572260742187499 +0.8805 -0.079803466796875 -0.572260742187499 +0.880625 -0.079803466796875 -0.572260742187499 +0.8807500000000001 -0.082672119140625 -0.572260742187499 +0.880875 -0.082672119140625 -0.572260742187499 +0.881 -0.085540771484375 -0.572260742187499 +0.8811250000000001 -0.088409423828125 -0.572260742187499 +0.88125 -0.088409423828125 -0.572260742187499 +0.8813750000000001 -0.09124755859375 -0.572260742187499 +0.8815000000000001 -0.09124755859375 -0.572260742187499 +0.881625 -0.094085693359375 -0.572260742187499 +0.8817500000000001 -0.096893310546875 -0.572260742187499 +0.881875 -0.096893310546875 -0.572260742187499 +0.882 -0.099700927734375 -0.572260742187499 +0.8821250000000001 -0.099700927734375 -0.572260742187499 +0.88225 -0.102508544921875 -0.572260742187499 +0.882375 -0.105316162109375 -0.572260742187499 +0.8825000000000001 -0.105316162109375 -0.572260742187499 +0.882625 -0.10809326171875 -0.572260742187499 +0.8827500000000001 -0.10809326171875 -0.572260742187499 +0.8828749999999999 -0.110870361328125 -0.572260742187499 +0.883 -0.113616943359375 -0.572260742187499 +0.8831250000000001 -0.113616943359375 -0.572260742187499 +0.88325 -0.116363525390625 -0.572260742187499 +0.883375 -0.116363525390625 -0.572260742187499 +0.8835000000000001 -0.11907958984375 -0.572260742187499 +0.883625 -0.121795654296875 -0.572260742187499 +0.88375 -0.121795654296875 -0.572260742187499 +0.8838749999999999 -0.12451171875 -0.572260742187499 +0.884 -0.12451171875 -0.572260742187499 +0.884125 -0.127197265625 -0.572260742187499 +0.8842499999999999 -0.1298828125 -0.572260742187499 +0.884375 -0.1298828125 -0.572260742187499 +0.8845000000000001 -0.132537841796875 -0.572260742187499 +0.884625 -0.132537841796875 -0.572260742187499 +0.88475 -0.13519287109375 -0.572260742187499 +0.8848749999999999 -0.1378173828125 -0.572260742187499 +0.885 -0.1378173828125 -0.572260742187499 +0.885125 -0.14044189453125 -0.572260742187499 +0.8852499999999999 -0.14044189453125 -0.572260742187499 +0.885375 -0.143035888671875 -0.572260742187499 +0.8855 -0.1456298828125 -0.572260742187499 +0.8856249999999999 -0.1456298828125 -0.572260742187499 +0.88575 -0.148193359375 -0.572260742187499 +0.8858750000000001 -0.148193359375 -0.572260742187499 +0.8859999999999999 -0.1507568359375 -0.572260742187499 +0.886125 -0.153289794921875 -0.572260742187499 +0.8862500000000001 -0.153289794921875 -0.572260742187499 +0.886375 -0.15582275390625 -0.572260742187499 +0.8865 -0.15582275390625 -0.572260742187499 +0.8866250000000001 -0.1583251953125 -0.572260742187499 +0.88675 -0.160797119140625 -0.572260742187499 +0.886875 -0.160797119140625 -0.572260742187499 +0.8870000000000001 -0.16326904296875 -0.572260742187499 +0.887125 -0.16326904296875 -0.572260742187499 +0.88725 -0.165740966796875 -0.572260742187499 +0.8873750000000001 -0.16815185546875 -0.572260742187499 +0.8875 -0.16815185546875 -0.572260742187499 +0.8876250000000001 -0.170562744140625 -0.572260742187499 +0.8877500000000001 -0.170562744140625 -0.572260742187499 +0.887875 -0.1729736328125 -0.572260742187499 +0.8880000000000001 -0.17535400390625 -0.572260742187499 +0.8881250000000001 -0.17535400390625 -0.572260742187499 +0.88825 -0.177703857421875 -0.572260742187499 +0.8883750000000001 -0.177703857421875 -0.572260742187499 +0.8885000000000002 -0.1800537109375 -0.572260742187499 +0.888625 -0.182373046875 -0.572260742187499 +0.8887500000000001 -0.182373046875 -0.572260742187499 +0.888875 -0.184661865234375 -0.572260742187499 +0.8890000000000001 -0.184661865234375 -0.572260742187499 +0.8891250000000001 -0.18695068359375 -0.572260742187499 +0.88925 -0.189208984375 -0.572260742187499 +0.8893750000000001 -0.189208984375 -0.572260742187499 +0.8895000000000001 -0.191436767578125 -0.572260742187499 +0.889625 -0.191436767578125 -0.572260742187499 +0.8897500000000001 -0.19366455078125 -0.572260742187499 +0.889875 -0.195831298828125 -0.572260742187499 +0.89 -0.195831298828125 -0.572260742187499 +0.8901250000000001 -0.198028564453125 -0.572260742187499 +0.89025 -0.198028564453125 -0.572260742187499 +0.890375 -0.200164794921875 -0.572260742187499 +0.8905000000000001 -0.202301025390625 -0.572260742187499 +0.890625 -0.202301025390625 -0.572260742187499 +0.8907500000000001 -0.20440673828125 -0.572260742187499 +0.890875 -0.20440673828125 -0.572260742187499 +0.891 -0.20648193359375 -0.572260742187499 +0.8911250000000001 -0.20855712890625 -0.572260742187499 +0.89125 -0.20855712890625 -0.572260742187499 +0.891375 -0.210601806640625 -0.572260742187499 +0.8915000000000001 -0.210601806640625 -0.572260742187499 +0.891625 -0.212615966796875 -0.572260742187499 +0.89175 -0.214599609375 -0.572260742187499 +0.8918749999999999 -0.214599609375 -0.572260742187499 +0.892 -0.216583251953125 -0.572260742187499 +0.8921250000000001 -0.216583251953125 -0.572260742187499 +0.8922499999999999 -0.218536376953125 -0.572260742187499 +0.892375 -0.220428466796875 -0.572260742187499 +0.8925000000000001 -0.220428466796875 -0.572260742187499 +0.892625 -0.22235107421875 -0.572260742187499 +0.89275 -0.22235107421875 -0.572260742187499 +0.8928749999999999 -0.224212646484375 -0.572260742187499 +0.893 -0.22607421875 -0.572260742187499 +0.893125 -0.22607421875 -0.572260742187499 +0.8932499999999999 -0.227874755859375 -0.572260742187499 +0.893375 -0.227874755859375 -0.572260742187499 +0.8935 -0.22967529296875 -0.572260742187499 +0.8936249999999999 -0.231475830078125 -0.572260742187499 +0.89375 -0.231475830078125 -0.572260742187499 +0.8938749999999999 -0.23321533203125 -0.572260742187499 +0.894 -0.23321533203125 -0.572260742187499 +0.894125 -0.23492431640625 -0.572260742187499 +0.8942499999999999 -0.23663330078125 -0.572260742187499 +0.894375 -0.23663330078125 -0.572260742187499 +0.8945 -0.238311767578125 -0.572260742187499 +0.8946249999999999 -0.238311767578125 -0.572260742187499 +0.89475 -0.23992919921875 -0.572260742187499 +0.894875 -0.2415771484375 -0.572260742187499 +0.8949999999999999 -0.2415771484375 -0.572260742187499 +0.895125 -0.2431640625 -0.572260742187499 +0.8952500000000001 -0.2431640625 -0.572260742187499 +0.8953749999999999 -0.244720458984375 -0.572260742187499 +0.8955 -0.246246337890625 -0.572260742187499 +0.8956250000000001 -0.246246337890625 -0.572260742187499 +0.89575 -0.247772216796875 -0.572260742187499 +0.895875 -0.247772216796875 -0.572260742187499 +0.8960000000000001 -0.186859130859375 -0.4289990234374976 +0.896125 -0.18792724609375 -0.4289990234374976 +0.89625 -0.18792724609375 -0.4289990234374976 +0.8963750000000001 -0.188995361328125 -0.4289990234374976 +0.8965 -0.188995361328125 -0.4289990234374976 +0.896625 -0.1900634765625 -0.4289990234374976 +0.8967500000000001 -0.19110107421875 -0.4289990234374976 +0.896875 -0.19110107421875 -0.4289990234374976 +0.8970000000000001 -0.192108154296875 -0.4289990234374976 +0.8971250000000001 -0.192108154296875 -0.4289990234374976 +0.89725 -0.193084716796875 -0.4289990234374976 +0.8973750000000001 -0.194061279296875 -0.4289990234374976 +0.8975 -0.194061279296875 -0.4289990234374976 +0.897625 -0.19500732421875 -0.4289990234374976 +0.8977500000000001 -0.19500732421875 -0.4289990234374976 +0.897875 -0.1959228515625 -0.4289990234374976 +0.898 -0.19683837890625 -0.4289990234374976 +0.8981250000000001 -0.19683837890625 -0.4289990234374976 +0.89825 -0.19769287109375 -0.4289990234374976 +0.8983750000000001 -0.19769287109375 -0.4289990234374976 +0.8984999999999999 -0.198577880859375 -0.4289990234374976 +0.898625 -0.19940185546875 -0.4289990234374976 +0.8987500000000001 -0.19940185546875 -0.4289990234374976 +0.898875 -0.200225830078125 -0.4289990234374976 +0.899 -0.200225830078125 -0.4289990234374976 +0.8991250000000001 -0.201019287109375 -0.4289990234374976 +0.89925 -0.2017822265625 -0.4289990234374976 +0.899375 -0.2017822265625 -0.4289990234374976 +0.8994999999999999 -0.202545166015625 -0.4289990234374976 +0.899625 -0.202545166015625 -0.4289990234374976 +0.89975 -0.203277587890625 -0.4289990234374976 +0.8998749999999999 -0.2039794921875 -0.4289990234374976 +0.9 -0.2039794921875 -0.4289990234374976 +0.9001250000000001 -0.20465087890625 -0.4289990234374976 +0.90025 -0.20465087890625 -0.4289990234374976 +0.900375 -0.205322265625 -0.4289990234374976 +0.9004999999999999 -0.205963134765625 -0.4289990234374976 +0.900625 -0.205963134765625 -0.4289990234374976 +0.90075 -0.206573486328125 -0.4289990234374976 +0.9008749999999999 -0.206573486328125 -0.4289990234374976 +0.901 -0.2071533203125 -0.4289990234374976 +0.901125 -0.207733154296875 -0.4289990234374976 +0.9012499999999999 -0.207733154296875 -0.4289990234374976 +0.901375 -0.208282470703125 -0.4289990234374976 +0.9015000000000001 -0.208282470703125 -0.4289990234374976 +0.9016249999999999 -0.20880126953125 -0.4289990234374976 +0.90175 -0.20928955078125 -0.4289990234374976 +0.9018750000000001 -0.20928955078125 -0.4289990234374976 +0.902 -0.20977783203125 -0.4289990234374976 +0.902125 -0.20977783203125 -0.4289990234374976 +0.9022500000000001 -0.210235595703125 -0.4289990234374976 +0.902375 -0.210662841796875 -0.4289990234374976 +0.9025 -0.210662841796875 -0.4289990234374976 +0.9026250000000001 -0.211090087890625 -0.4289990234374976 +0.90275 -0.211090087890625 -0.4289990234374976 +0.902875 -0.211456298828125 -0.4289990234374976 +0.9030000000000001 -0.211822509765625 -0.4289990234374976 +0.903125 -0.211822509765625 -0.4289990234374976 +0.9032500000000001 -0.212158203125 -0.4289990234374976 +0.9033750000000001 -0.212158203125 -0.4289990234374976 +0.9035 -0.212493896484375 -0.4289990234374976 +0.9036250000000001 -0.2127685546875 -0.4289990234374976 +0.9037500000000001 -0.2127685546875 -0.4289990234374976 +0.903875 -0.213043212890625 -0.4289990234374976 +0.9040000000000001 -0.213043212890625 -0.4289990234374976 +0.9041250000000002 -0.213287353515625 -0.4289990234374976 +0.90425 -0.2135009765625 -0.4289990234374976 +0.9043750000000001 -0.2135009765625 -0.4289990234374976 +0.9045 -0.213714599609375 -0.4289990234374976 +0.9046250000000001 -0.213714599609375 -0.4289990234374976 +0.9047500000000001 -0.213897705078125 -0.4289990234374976 +0.904875 -0.21405029296875 -0.4289990234374976 +0.9050000000000001 -0.21405029296875 -0.4289990234374976 +0.9051250000000001 -0.21417236328125 -0.4289990234374976 +0.90525 -0.21417236328125 -0.4289990234374976 +0.9053750000000001 -0.21429443359375 -0.4289990234374976 +0.9055 -0.21435546875 -0.4289990234374976 +0.905625 -0.21435546875 -0.4289990234374976 +0.9057500000000001 -0.21441650390625 -0.4289990234374976 +0.905875 -0.21441650390625 -0.4289990234374976 +0.906 -0.214447021484375 -0.4289990234374976 +0.9061250000000001 -0.2144775390625 -0.4289990234374976 +0.90625 -0.2144775390625 -0.4289990234374976 +0.9063750000000001 -0.214447021484375 -0.4289990234374976 +0.9065 -0.214447021484375 -0.4289990234374976 +0.906625 -0.21441650390625 -0.4289990234374976 +0.9067500000000001 -0.21435546875 -0.4289990234374976 +0.906875 -0.21435546875 -0.4289990234374976 +0.907 -0.21429443359375 -0.4289990234374976 +0.9071250000000001 -0.21429443359375 -0.4289990234374976 +0.90725 -0.21417236328125 -0.4289990234374976 +0.907375 -0.21405029296875 -0.4289990234374976 +0.9074999999999999 -0.21405029296875 -0.4289990234374976 +0.907625 -0.213897705078125 -0.4289990234374976 +0.9077500000000001 -0.213897705078125 -0.4289990234374976 +0.9078749999999999 -0.213714599609375 -0.4289990234374976 +0.908 -0.2135009765625 -0.4289990234374976 +0.9081250000000001 -0.2135009765625 -0.4289990234374976 +0.90825 -0.213287353515625 -0.4289990234374976 +0.908375 -0.213287353515625 -0.4289990234374976 +0.9084999999999999 -0.213043212890625 -0.4289990234374976 +0.908625 -0.2127685546875 -0.4289990234374976 +0.90875 -0.2127685546875 -0.4289990234374976 +0.9088749999999999 -0.212493896484375 -0.4289990234374976 +0.909 -0.212493896484375 -0.4289990234374976 +0.909125 -0.212158203125 -0.4289990234374976 +0.9092499999999999 -0.211822509765625 -0.4289990234374976 +0.909375 -0.211822509765625 -0.4289990234374976 +0.9094999999999999 -0.211456298828125 -0.4289990234374976 +0.909625 -0.211456298828125 -0.4289990234374976 +0.90975 -0.211090087890625 -0.4289990234374976 +0.9098749999999999 -0.210662841796875 -0.4289990234374976 +0.91 -0.210662841796875 -0.4289990234374976 +0.910125 -0.210235595703125 -0.4289990234374976 +0.9102499999999999 -0.210235595703125 -0.4289990234374976 +0.910375 -0.20977783203125 -0.4289990234374976 +0.9105 -0.20928955078125 -0.4289990234374976 +0.9106249999999999 -0.20928955078125 -0.4289990234374976 +0.91075 -0.20880126953125 -0.4289990234374976 +0.9108750000000001 -0.20880126953125 -0.4289990234374976 +0.9109999999999999 -0.208282470703125 -0.4289990234374976 +0.911125 -0.207733154296875 -0.4289990234374976 +0.9112500000000001 -0.207733154296875 -0.4289990234374976 +0.911375 -0.2071533203125 -0.4289990234374976 +0.9115 -0.2071533203125 -0.4289990234374976 +0.9116250000000001 -0.206573486328125 -0.4289990234374976 +0.91175 -0.205963134765625 -0.4289990234374976 +0.911875 -0.205963134765625 -0.4289990234374976 +0.9120000000000001 -0.205322265625 -0.4289990234374976 +0.912125 -0.205322265625 -0.4289990234374976 +0.91225 -0.20465087890625 -0.4289990234374976 +0.9123750000000001 -0.2039794921875 -0.4289990234374976 +0.9125 -0.2039794921875 -0.4289990234374976 +0.9126250000000001 -0.203277587890625 -0.4289990234374976 +0.9127500000000001 -0.203277587890625 -0.4289990234374976 +0.912875 -0.202545166015625 -0.4289990234374976 +0.9130000000000001 -0.2017822265625 -0.4289990234374976 +0.913125 -0.2017822265625 -0.4289990234374976 +0.91325 -0.201019287109375 -0.4289990234374976 +0.9133750000000001 -0.201019287109375 -0.4289990234374976 +0.9135 -0.200225830078125 -0.4289990234374976 +0.913625 -0.19940185546875 -0.4289990234374976 +0.9137500000000001 -0.19940185546875 -0.4289990234374976 +0.913875 -0.198577880859375 -0.4289990234374976 +0.9140000000000001 -0.198577880859375 -0.4289990234374976 +0.9141249999999999 -0.19769287109375 -0.4289990234374976 +0.91425 -0.19683837890625 -0.4289990234374976 +0.9143750000000001 -0.19683837890625 -0.4289990234374976 +0.9145 -0.1959228515625 -0.4289990234374976 +0.914625 -0.1959228515625 -0.4289990234374976 +0.9147500000000001 -0.19500732421875 -0.4289990234374976 +0.914875 -0.194061279296875 -0.4289990234374976 +0.915 -0.194061279296875 -0.4289990234374976 +0.9151249999999999 -0.193084716796875 -0.4289990234374976 +0.91525 -0.193084716796875 -0.4289990234374976 +0.915375 -0.192108154296875 -0.4289990234374976 +0.9154999999999999 -0.19110107421875 -0.4289990234374976 +0.915625 -0.19110107421875 -0.4289990234374976 +0.9157500000000001 -0.1900634765625 -0.4289990234374976 +0.915875 -0.1900634765625 -0.4289990234374976 +0.916 -0.188995361328125 -0.4289990234374976 +0.9161249999999999 -0.18792724609375 -0.4289990234374976 +0.91625 -0.18792724609375 -0.4289990234374976 +0.916375 -0.186859130859375 -0.4289990234374976 +0.9164999999999999 -0.186859130859375 -0.4289990234374976 +0.916625 -0.18572998046875 -0.4289990234374976 +0.91675 -0.184600830078125 -0.4289990234374976 +0.9168749999999999 -0.184600830078125 -0.4289990234374976 +0.917 -0.183441162109375 -0.4289990234374976 +0.9171250000000001 -0.183441162109375 -0.4289990234374976 +0.9172499999999999 -0.182281494140625 -0.4289990234374976 +0.917375 -0.18109130859375 -0.4289990234374976 +0.9175000000000001 -0.18109130859375 -0.4289990234374976 +0.917625 -0.17987060546875 -0.4289990234374976 +0.91775 -0.17987060546875 -0.4289990234374976 +0.9178750000000001 -0.178619384765625 -0.4289990234374976 +0.918 -0.1773681640625 -0.4289990234374976 +0.918125 -0.1773681640625 -0.4289990234374976 +0.9182500000000001 -0.176116943359375 -0.4289990234374976 +0.918375 -0.176116943359375 -0.4289990234374976 +0.9185 -0.1748046875 -0.4289990234374976 +0.9186250000000001 -0.173492431640625 -0.4289990234374976 +0.91875 -0.173492431640625 -0.4289990234374976 +0.9188750000000001 -0.17218017578125 -0.4289990234374976 +0.9190000000000001 -0.17218017578125 -0.4289990234374976 +0.919125 -0.17083740234375 -0.4289990234374976 +0.9192500000000001 -0.169464111328125 -0.4289990234374976 +0.9193750000000001 -0.169464111328125 -0.4289990234374976 +0.9195 -0.168060302734375 -0.4289990234374976 +0.9196250000000001 -0.168060302734375 -0.4289990234374976 +0.9197500000000002 -0.166656494140625 -0.4289990234374976 +0.919875 -0.165252685546875 -0.4289990234374976 +0.9200000000000001 -0.165252685546875 -0.4289990234374976 +0.920125 -0.163818359375 -0.4289990234374976 +0.9202500000000001 -0.163818359375 -0.4289990234374976 +0.9203750000000001 -0.162353515625 -0.4289990234374976 +0.9205 -0.160858154296875 -0.4289990234374976 +0.9206250000000001 -0.160858154296875 -0.4289990234374976 +0.9207500000000001 -0.15936279296875 -0.4289990234374976 +0.920875 -0.15936279296875 -0.4289990234374976 +0.9210000000000001 -0.157867431640625 -0.4289990234374976 +0.921125 -0.156341552734375 -0.4289990234374976 +0.92125 -0.156341552734375 -0.4289990234374976 +0.9213750000000001 -0.15478515625 -0.4289990234374976 +0.9215 -0.15478515625 -0.4289990234374976 +0.921625 -0.153228759765625 -0.4289990234374976 +0.9217500000000001 -0.151641845703125 -0.4289990234374976 +0.921875 -0.151641845703125 -0.4289990234374976 +0.9220000000000001 -0.150054931640625 -0.4289990234374976 +0.922125 -0.150054931640625 -0.4289990234374976 +0.92225 -0.1484375 -0.4289990234374976 +0.9223750000000001 -0.146820068359375 -0.4289990234374976 +0.9225 -0.146820068359375 -0.4289990234374976 +0.922625 -0.145172119140625 -0.4289990234374976 +0.9227500000000001 -0.145172119140625 -0.4289990234374976 +0.922875 -0.14349365234375 -0.4289990234374976 +0.923 -0.141815185546875 -0.4289990234374976 +0.9231249999999999 -0.141815185546875 -0.4289990234374976 +0.92325 -0.14013671875 -0.4289990234374976 +0.9233750000000001 -0.14013671875 -0.4289990234374976 +0.9234999999999999 -0.138427734375 -0.4289990234374976 +0.923625 -0.136688232421875 -0.4289990234374976 +0.9237500000000001 -0.136688232421875 -0.4289990234374976 +0.923875 -0.13494873046875 -0.4289990234374976 +0.924 -0.13494873046875 -0.4289990234374976 +0.9241249999999999 -0.133209228515625 -0.4289990234374976 +0.92425 -0.131439208984375 -0.4289990234374976 +0.924375 -0.131439208984375 -0.4289990234374976 +0.9244999999999999 -0.129669189453125 -0.4289990234374976 +0.924625 -0.129669189453125 -0.4289990234374976 +0.92475 -0.12786865234375 -0.4289990234374976 +0.9248749999999999 -0.12603759765625 -0.4289990234374976 +0.925 -0.12603759765625 -0.4289990234374976 +0.9251249999999999 -0.124237060546875 -0.4289990234374976 +0.92525 -0.124237060546875 -0.4289990234374976 +0.925375 -0.122406005859375 -0.4289990234374976 +0.9254999999999999 -0.12054443359375 -0.4289990234374976 +0.925625 -0.12054443359375 -0.4289990234374976 +0.92575 -0.118682861328125 -0.4289990234374976 +0.9258749999999999 -0.118682861328125 -0.4289990234374976 +0.926 -0.116790771484375 -0.4289990234374976 +0.926125 -0.114898681640625 -0.4289990234374976 +0.9262499999999999 -0.114898681640625 -0.4289990234374976 +0.926375 -0.113006591796875 -0.4289990234374976 +0.9265000000000001 -0.113006591796875 -0.4289990234374976 +0.9266249999999999 -0.111083984375 -0.4289990234374976 +0.92675 -0.109161376953125 -0.4289990234374976 +0.9268750000000001 -0.109161376953125 -0.4289990234374976 +0.927 -0.10723876953125 -0.4289990234374976 +0.927125 -0.10723876953125 -0.4289990234374976 +0.9272500000000001 -0.10528564453125 -0.4289990234374976 +0.927375 -0.103302001953125 -0.4289990234374976 +0.9275 -0.103302001953125 -0.4289990234374976 +0.9276250000000001 -0.101348876953125 -0.4289990234374976 +0.92775 -0.101348876953125 -0.4289990234374976 +0.927875 -0.099365234375 -0.4289990234374976 +0.9280000000000001 -0.04205322265625 -0.1853759765624967 +0.928125 -0.04205322265625 -0.1853759765624967 +0.9282500000000001 -0.04119873046875 -0.1853759765624967 +0.9283750000000001 -0.04119873046875 -0.1853759765624967 +0.9285 -0.040313720703125 -0.1853759765624967 +0.9286250000000001 -0.039459228515625 -0.1853759765624967 +0.92875 -0.039459228515625 -0.1853759765624967 +0.928875 -0.03857421875 -0.1853759765624967 +0.9290000000000001 -0.03857421875 -0.1853759765624967 +0.929125 -0.037689208984375 -0.1853759765624967 +0.92925 -0.03680419921875 -0.1853759765624967 +0.9293750000000001 -0.03680419921875 -0.1853759765624967 +0.9295 -0.035888671875 -0.1853759765624967 +0.9296250000000001 -0.035888671875 -0.1853759765624967 +0.9297499999999999 -0.035003662109375 -0.1853759765624967 +0.929875 -0.034088134765625 -0.1853759765624967 +0.9300000000000001 -0.034088134765625 -0.1853759765624967 +0.930125 -0.033203125 -0.1853759765624967 +0.93025 -0.033203125 -0.1853759765624967 +0.9303750000000001 -0.03228759765625 -0.1853759765624967 +0.9305 -0.0313720703125 -0.1853759765624967 +0.930625 -0.0313720703125 -0.1853759765624967 +0.9307499999999999 -0.03045654296875 -0.1853759765624967 +0.930875 -0.03045654296875 -0.1853759765624967 +0.931 -0.029541015625 -0.1853759765624967 +0.9311249999999999 -0.02862548828125 -0.1853759765624967 +0.93125 -0.02862548828125 -0.1853759765624967 +0.9313750000000001 -0.0277099609375 -0.1853759765624967 +0.9315 -0.0277099609375 -0.1853759765624967 +0.931625 -0.026763916015625 -0.1853759765624967 +0.9317499999999999 -0.025848388671875 -0.1853759765624967 +0.931875 -0.025848388671875 -0.1853759765624967 +0.932 -0.02490234375 -0.1853759765624967 +0.9321249999999999 -0.02490234375 -0.1853759765624967 +0.93225 -0.023956298828125 -0.1853759765624967 +0.932375 -0.023040771484375 -0.1853759765624967 +0.9324999999999999 -0.023040771484375 -0.1853759765624967 +0.932625 -0.0220947265625 -0.1853759765624967 +0.9327500000000001 -0.0220947265625 -0.1853759765624967 +0.9328749999999999 -0.021148681640625 -0.1853759765624967 +0.933 -0.02020263671875 -0.1853759765624967 +0.9331250000000001 -0.02020263671875 -0.1853759765624967 +0.93325 -0.019256591796875 -0.1853759765624967 +0.933375 -0.019256591796875 -0.1853759765624967 +0.9335000000000001 -0.018310546875 -0.1853759765624967 +0.933625 -0.017333984375 -0.1853759765624967 +0.93375 -0.017333984375 -0.1853759765624967 +0.9338750000000001 -0.016387939453125 -0.1853759765624967 +0.934 -0.016387939453125 -0.1853759765624967 +0.934125 -0.01544189453125 -0.1853759765624967 +0.9342500000000001 -0.01446533203125 -0.1853759765624967 +0.934375 -0.01446533203125 -0.1853759765624967 +0.9345000000000001 -0.013519287109375 -0.1853759765624967 +0.9346250000000001 -0.013519287109375 -0.1853759765624967 +0.93475 -0.0125732421875 -0.1853759765624967 +0.9348750000000001 -0.0115966796875 -0.1853759765624967 +0.9350000000000001 -0.0115966796875 -0.1853759765624967 +0.935125 -0.010650634765625 -0.1853759765624967 +0.9352500000000001 -0.010650634765625 -0.1853759765624967 +0.9353750000000002 -0.009674072265625 -0.1853759765624967 +0.9355 -0.008697509765625 -0.1853759765624967 +0.9356250000000001 -0.008697509765625 -0.1853759765624967 +0.93575 -0.00775146484375 -0.1853759765624967 +0.9358750000000001 -0.00775146484375 -0.1853759765624967 +0.9360000000000001 -0.00677490234375 -0.1853759765624967 +0.936125 -0.00579833984375 -0.1853759765624967 +0.9362500000000001 -0.00579833984375 -0.1853759765624967 +0.9363750000000001 -0.00482177734375 -0.1853759765624967 +0.9365 -0.00482177734375 -0.1853759765624967 +0.9366250000000001 -0.003875732421875 -0.1853759765624967 +0.93675 -0.002899169921875 -0.1853759765624967 +0.936875 -0.002899169921875 -0.1853759765624967 +0.9370000000000001 -0.001922607421875 -0.1853759765624967 +0.937125 -0.001922607421875 -0.1853759765624967 +0.93725 -0.000946044921875 -0.1853759765624967 0.9373750000000001 0.0 -0.1853759765624967 0.9375 0.0 -0.1853759765624967 0.9376250000000001 0.000946044921875 -0.1853759765624967 @@ -7678,325 +7678,325 @@ 0.9596250000000001 0.0830078125 -0.1853759765624967 0.95975 0.08343505859375 -0.1853759765624967 0.9598750000000001 0.083831787109375 -0.1853759765624967 -0.96 -0.054168701171875 0.1197216796875046 -0.960125 -0.054412841796875 0.1197216796875046 -0.9602500000000001 -0.054412841796875 0.1197216796875046 -0.960375 -0.0546875 0.1197216796875046 -0.9605 -0.054931640625 0.1197216796875046 -0.9606250000000001 -0.054931640625 0.1197216796875046 -0.96075 -0.05517578125 0.1197216796875046 -0.9608750000000001 -0.05517578125 0.1197216796875046 -0.9609999999999999 -0.055419921875 0.1197216796875046 -0.961125 -0.0556640625 0.1197216796875046 -0.9612500000000001 -0.0556640625 0.1197216796875046 -0.961375 -0.055877685546875 0.1197216796875046 -0.9615 -0.055877685546875 0.1197216796875046 -0.9616250000000001 -0.05609130859375 0.1197216796875046 -0.96175 -0.056304931640625 0.1197216796875046 -0.961875 -0.056304931640625 0.1197216796875046 -0.9619999999999999 -0.0565185546875 0.1197216796875046 -0.962125 -0.0565185546875 0.1197216796875046 -0.96225 -0.056732177734375 0.1197216796875046 -0.9623749999999999 -0.056915283203125 0.1197216796875046 -0.9625 -0.056915283203125 0.1197216796875046 -0.9626250000000001 -0.05712890625 0.1197216796875046 -0.96275 -0.05712890625 0.1197216796875046 -0.962875 -0.05731201171875 0.1197216796875046 -0.9629999999999999 -0.0574951171875 0.1197216796875046 -0.963125 -0.0574951171875 0.1197216796875046 -0.96325 -0.057647705078125 0.1197216796875046 -0.9633749999999999 -0.057647705078125 0.1197216796875046 -0.9635 -0.057830810546875 0.1197216796875046 -0.963625 -0.0579833984375 0.1197216796875046 -0.9637499999999999 -0.0579833984375 0.1197216796875046 -0.963875 -0.058135986328125 0.1197216796875046 -0.9640000000000001 -0.058135986328125 0.1197216796875046 -0.9641249999999999 -0.05828857421875 0.1197216796875046 -0.96425 -0.05841064453125 0.1197216796875046 -0.9643750000000001 -0.05841064453125 0.1197216796875046 -0.9645 -0.058563232421875 0.1197216796875046 -0.964625 -0.058563232421875 0.1197216796875046 -0.9647500000000001 -0.058685302734375 0.1197216796875046 -0.964875 -0.058807373046875 0.1197216796875046 -0.965 -0.058807373046875 0.1197216796875046 -0.9651250000000001 -0.05889892578125 0.1197216796875046 -0.96525 -0.05889892578125 0.1197216796875046 -0.965375 -0.05902099609375 0.1197216796875046 -0.9655000000000001 -0.059112548828125 0.1197216796875046 -0.965625 -0.059112548828125 0.1197216796875046 -0.9657500000000001 -0.0592041015625 0.1197216796875046 -0.9658750000000001 -0.0592041015625 0.1197216796875046 -0.966 -0.059295654296875 0.1197216796875046 -0.9661250000000001 -0.05938720703125 0.1197216796875046 -0.9662500000000001 -0.05938720703125 0.1197216796875046 -0.966375 -0.0594482421875 0.1197216796875046 -0.9665000000000001 -0.0594482421875 0.1197216796875046 -0.9666250000000002 -0.059539794921875 0.1197216796875046 -0.96675 -0.059600830078125 0.1197216796875046 -0.9668750000000001 -0.059600830078125 0.1197216796875046 -0.967 -0.059661865234375 0.1197216796875046 -0.9671250000000001 -0.059661865234375 0.1197216796875046 -0.9672500000000001 -0.0596923828125 0.1197216796875046 -0.967375 -0.05975341796875 0.1197216796875046 -0.9675000000000001 -0.05975341796875 0.1197216796875046 -0.9676250000000001 -0.059783935546875 0.1197216796875046 -0.96775 -0.059783935546875 0.1197216796875046 -0.9678750000000001 -0.059814453125 0.1197216796875046 -0.968 -0.059814453125 0.1197216796875046 -0.968125 -0.059814453125 0.1197216796875046 -0.9682500000000001 -0.059844970703125 0.1197216796875046 -0.968375 -0.059844970703125 0.1197216796875046 -0.9685 -0.059844970703125 0.1197216796875046 -0.9686250000000001 -0.059844970703125 0.1197216796875046 -0.96875 -0.059844970703125 0.1197216796875046 -0.9688750000000001 -0.059844970703125 0.1197216796875046 -0.969 -0.059844970703125 0.1197216796875046 -0.969125 -0.059844970703125 0.1197216796875046 -0.9692500000000001 -0.059814453125 0.1197216796875046 -0.969375 -0.059814453125 0.1197216796875046 -0.9695 -0.059814453125 0.1197216796875046 -0.9696250000000001 -0.059814453125 0.1197216796875046 -0.96975 -0.059783935546875 0.1197216796875046 -0.969875 -0.05975341796875 0.1197216796875046 -0.9699999999999999 -0.05975341796875 0.1197216796875046 -0.970125 -0.0596923828125 0.1197216796875046 -0.9702500000000001 -0.0596923828125 0.1197216796875046 -0.9703749999999999 -0.059661865234375 0.1197216796875046 -0.9705 -0.059600830078125 0.1197216796875046 -0.9706250000000001 -0.059600830078125 0.1197216796875046 -0.97075 -0.059539794921875 0.1197216796875046 -0.970875 -0.059539794921875 0.1197216796875046 -0.9709999999999999 -0.0594482421875 0.1197216796875046 -0.971125 -0.05938720703125 0.1197216796875046 -0.97125 -0.05938720703125 0.1197216796875046 -0.9713749999999999 -0.059295654296875 0.1197216796875046 -0.9715 -0.059295654296875 0.1197216796875046 -0.971625 -0.0592041015625 0.1197216796875046 -0.9717499999999999 -0.059112548828125 0.1197216796875046 -0.971875 -0.059112548828125 0.1197216796875046 -0.9719999999999999 -0.05902099609375 0.1197216796875046 -0.972125 -0.05902099609375 0.1197216796875046 -0.97225 -0.05889892578125 0.1197216796875046 -0.9723749999999999 -0.058807373046875 0.1197216796875046 -0.9725 -0.058807373046875 0.1197216796875046 -0.972625 -0.058685302734375 0.1197216796875046 -0.9727499999999999 -0.058685302734375 0.1197216796875046 -0.972875 -0.058563232421875 0.1197216796875046 -0.973 -0.05841064453125 0.1197216796875046 -0.9731249999999999 -0.05841064453125 0.1197216796875046 -0.97325 -0.05828857421875 0.1197216796875046 -0.9733750000000001 -0.05828857421875 0.1197216796875046 -0.9734999999999999 -0.058135986328125 0.1197216796875046 -0.973625 -0.0579833984375 0.1197216796875046 -0.9737500000000001 -0.0579833984375 0.1197216796875046 -0.973875 -0.057830810546875 0.1197216796875046 -0.974 -0.057830810546875 0.1197216796875046 -0.9741250000000001 -0.057647705078125 0.1197216796875046 -0.97425 -0.0574951171875 0.1197216796875046 -0.974375 -0.0574951171875 0.1197216796875046 -0.9745000000000001 -0.05731201171875 0.1197216796875046 -0.974625 -0.05731201171875 0.1197216796875046 -0.97475 -0.05712890625 0.1197216796875046 -0.9748750000000001 -0.056915283203125 0.1197216796875046 -0.975 -0.056915283203125 0.1197216796875046 -0.9751250000000001 -0.056732177734375 0.1197216796875046 -0.9752500000000001 -0.056732177734375 0.1197216796875046 -0.975375 -0.0565185546875 0.1197216796875046 -0.9755000000000001 -0.056304931640625 0.1197216796875046 -0.9756250000000001 -0.056304931640625 0.1197216796875046 -0.97575 -0.05609130859375 0.1197216796875046 -0.9758750000000001 -0.05609130859375 0.1197216796875046 -0.976 -0.055877685546875 0.1197216796875046 -0.976125 -0.0556640625 0.1197216796875046 -0.9762500000000001 -0.0556640625 0.1197216796875046 -0.976375 -0.055419921875 0.1197216796875046 -0.9765000000000001 -0.055419921875 0.1197216796875046 -0.9766249999999999 -0.05517578125 0.1197216796875046 -0.97675 -0.054931640625 0.1197216796875046 -0.9768750000000001 -0.054931640625 0.1197216796875046 -0.977 -0.0546875 0.1197216796875046 -0.977125 -0.0546875 0.1197216796875046 -0.9772500000000001 -0.054412841796875 0.1197216796875046 -0.977375 -0.054168701171875 0.1197216796875046 -0.9775 -0.054168701171875 0.1197216796875046 -0.9776249999999999 -0.05389404296875 0.1197216796875046 -0.97775 -0.05389404296875 0.1197216796875046 -0.977875 -0.053619384765625 0.1197216796875046 -0.9779999999999999 -0.0533447265625 0.1197216796875046 -0.978125 -0.0533447265625 0.1197216796875046 -0.9782500000000001 -0.05303955078125 0.1197216796875046 -0.978375 -0.05303955078125 0.1197216796875046 -0.9785 -0.052764892578125 0.1197216796875046 -0.9786249999999999 -0.052459716796875 0.1197216796875046 -0.97875 -0.052459716796875 0.1197216796875046 -0.978875 -0.052154541015625 0.1197216796875046 -0.9789999999999999 -0.052154541015625 0.1197216796875046 -0.979125 -0.051849365234375 0.1197216796875046 -0.97925 -0.051513671875 0.1197216796875046 -0.9793749999999999 -0.051513671875 0.1197216796875046 -0.9795 -0.05120849609375 0.1197216796875046 -0.9796250000000001 -0.05120849609375 0.1197216796875046 -0.9797499999999999 -0.050872802734375 0.1197216796875046 -0.979875 -0.050537109375 0.1197216796875046 -0.9800000000000001 -0.050537109375 0.1197216796875046 -0.980125 -0.050201416015625 0.1197216796875046 -0.98025 -0.050201416015625 0.1197216796875046 -0.9803750000000001 -0.04986572265625 0.1197216796875046 -0.9805 -0.04949951171875 0.1197216796875046 -0.980625 -0.04949951171875 0.1197216796875046 -0.9807500000000001 -0.049163818359375 0.1197216796875046 -0.980875 -0.049163818359375 0.1197216796875046 -0.981 -0.048797607421875 0.1197216796875046 -0.9811250000000001 -0.048431396484375 0.1197216796875046 -0.98125 -0.048431396484375 0.1197216796875046 -0.9813750000000001 -0.048065185546875 0.1197216796875046 -0.9815000000000001 -0.048065185546875 0.1197216796875046 -0.981625 -0.04766845703125 0.1197216796875046 -0.9817500000000001 -0.04730224609375 0.1197216796875046 -0.9818750000000001 -0.04730224609375 0.1197216796875046 -0.982 -0.046905517578125 0.1197216796875046 -0.9821250000000001 -0.046905517578125 0.1197216796875046 -0.9822500000000002 -0.0465087890625 0.1197216796875046 -0.982375 -0.046112060546875 0.1197216796875046 -0.9825000000000001 -0.046112060546875 0.1197216796875046 -0.982625 -0.04571533203125 0.1197216796875046 -0.9827500000000001 -0.04571533203125 0.1197216796875046 -0.9828750000000001 -0.045318603515625 0.1197216796875046 -0.983 -0.044891357421875 0.1197216796875046 -0.9831250000000001 -0.044891357421875 0.1197216796875046 -0.9832500000000001 -0.04449462890625 0.1197216796875046 -0.983375 -0.04449462890625 0.1197216796875046 -0.9835000000000001 -0.0440673828125 0.1197216796875046 -0.983625 -0.04364013671875 0.1197216796875046 -0.98375 -0.04364013671875 0.1197216796875046 -0.9838750000000001 -0.043212890625 0.1197216796875046 -0.984 -0.043212890625 0.1197216796875046 -0.984125 -0.04278564453125 0.1197216796875046 -0.9842500000000001 -0.042327880859375 0.1197216796875046 -0.984375 -0.042327880859375 0.1197216796875046 -0.9845000000000001 -0.0418701171875 0.1197216796875046 -0.984625 -0.0418701171875 0.1197216796875046 -0.98475 -0.04144287109375 0.1197216796875046 -0.9848750000000001 -0.040985107421875 0.1197216796875046 -0.985 -0.040985107421875 0.1197216796875046 -0.985125 -0.04052734375 0.1197216796875046 -0.9852500000000001 -0.04052734375 0.1197216796875046 -0.985375 -0.040069580078125 0.1197216796875046 -0.9855 -0.039581298828125 0.1197216796875046 -0.9856249999999999 -0.039581298828125 0.1197216796875046 -0.98575 -0.03912353515625 0.1197216796875046 -0.9858750000000001 -0.03912353515625 0.1197216796875046 -0.9859999999999999 -0.03863525390625 0.1197216796875046 -0.986125 -0.03814697265625 0.1197216796875046 -0.9862500000000001 -0.03814697265625 0.1197216796875046 -0.986375 -0.037689208984375 0.1197216796875046 -0.9865 -0.037689208984375 0.1197216796875046 -0.9866249999999999 -0.037200927734375 0.1197216796875046 -0.98675 -0.03668212890625 0.1197216796875046 -0.986875 -0.03668212890625 0.1197216796875046 -0.9869999999999999 -0.03619384765625 0.1197216796875046 -0.987125 -0.03619384765625 0.1197216796875046 -0.98725 -0.03570556640625 0.1197216796875046 -0.9873749999999999 -0.035186767578125 0.1197216796875046 -0.9875 -0.035186767578125 0.1197216796875046 -0.9876249999999999 -0.03466796875 0.1197216796875046 -0.98775 -0.03466796875 0.1197216796875046 -0.987875 -0.0341796875 0.1197216796875046 -0.9879999999999999 -0.033660888671875 0.1197216796875046 -0.988125 -0.033660888671875 0.1197216796875046 -0.98825 -0.03314208984375 0.1197216796875046 -0.9883749999999999 -0.03314208984375 0.1197216796875046 -0.9885 -0.0325927734375 0.1197216796875046 -0.988625 -0.032073974609375 0.1197216796875046 -0.9887499999999999 -0.032073974609375 0.1197216796875046 -0.988875 -0.03155517578125 0.1197216796875046 -0.9890000000000001 -0.03155517578125 0.1197216796875046 -0.9891249999999999 -0.031005859375 0.1197216796875046 -0.98925 -0.030487060546875 0.1197216796875046 -0.9893750000000001 -0.030487060546875 0.1197216796875046 -0.9895 -0.029937744140625 0.1197216796875046 -0.989625 -0.029937744140625 0.1197216796875046 -0.9897500000000001 -0.029388427734375 0.1197216796875046 -0.989875 -0.028839111328125 0.1197216796875046 -0.99 -0.028839111328125 0.1197216796875046 -0.9901250000000001 -0.028289794921875 0.1197216796875046 -0.99025 -0.028289794921875 0.1197216796875046 -0.990375 -0.027740478515625 0.1197216796875046 -0.9905000000000001 -0.027191162109375 0.1197216796875046 -0.990625 -0.027191162109375 0.1197216796875046 -0.9907500000000001 -0.026611328125 0.1197216796875046 -0.9908750000000001 -0.026611328125 0.1197216796875046 -0.991 -0.02606201171875 0.1197216796875046 -0.9911250000000001 -0.025482177734375 0.1197216796875046 -0.9912500000000001 -0.025482177734375 0.1197216796875046 -0.991375 -0.024932861328125 0.1197216796875046 -0.9915000000000001 -0.024932861328125 0.1197216796875046 -0.991625 -0.02435302734375 0.1197216796875046 -0.99175 -0.023773193359375 0.1197216796875046 -0.9918750000000001 -0.023773193359375 0.1197216796875046 -0.992 -0.084808349609375 0.4376074218750045 -0.9921250000000001 -0.084808349609375 0.4376074218750045 -0.9922499999999999 -0.082672119140625 0.4376074218750045 -0.992375 -0.08056640625 0.4376074218750045 -0.9925000000000001 -0.08056640625 0.4376074218750045 -0.992625 -0.07843017578125 0.4376074218750045 -0.99275 -0.07843017578125 0.4376074218750045 -0.9928750000000001 -0.076263427734375 0.4376074218750045 -0.993 -0.074127197265625 0.4376074218750045 -0.993125 -0.074127197265625 0.4376074218750045 -0.9932499999999999 -0.07196044921875 0.4376074218750045 -0.993375 -0.07196044921875 0.4376074218750045 -0.9935 -0.069793701171875 0.4376074218750045 -0.9936249999999999 -0.067626953125 0.4376074218750045 -0.99375 -0.067626953125 0.4376074218750045 -0.9938750000000001 -0.0654296875 0.4376074218750045 -0.994 -0.0654296875 0.4376074218750045 -0.994125 -0.063232421875 0.4376074218750045 -0.9942499999999999 -0.061065673828125 0.4376074218750045 -0.994375 -0.061065673828125 0.4376074218750045 -0.9945 -0.058837890625 0.4376074218750045 -0.9946249999999999 -0.058837890625 0.4376074218750045 -0.99475 -0.056640625 0.4376074218750045 -0.994875 -0.054412841796875 0.4376074218750045 -0.9949999999999999 -0.054412841796875 0.4376074218750045 -0.995125 -0.052215576171875 0.4376074218750045 -0.9952500000000001 -0.052215576171875 0.4376074218750045 -0.9953749999999999 -0.04998779296875 0.4376074218750045 -0.9955 -0.0477294921875 0.4376074218750045 -0.9956250000000001 -0.0477294921875 0.4376074218750045 -0.99575 -0.045501708984375 0.4376074218750045 -0.995875 -0.045501708984375 0.4376074218750045 -0.9960000000000001 -0.043243408203125 0.4376074218750045 -0.996125 -0.041015625 0.4376074218750045 -0.99625 -0.041015625 0.4376074218750045 -0.9963750000000001 -0.03875732421875 0.4376074218750045 -0.9965 -0.03875732421875 0.4376074218750045 -0.996625 -0.0364990234375 0.4376074218750045 -0.9967500000000001 -0.03424072265625 0.4376074218750045 -0.996875 -0.03424072265625 0.4376074218750045 -0.9970000000000001 -0.031982421875 0.4376074218750045 -0.9971250000000001 -0.031982421875 0.4376074218750045 -0.99725 -0.029693603515625 0.4376074218750045 -0.9973750000000001 -0.027435302734375 0.4376074218750045 -0.9975000000000001 -0.027435302734375 0.4376074218750045 -0.997625 -0.025146484375 0.4376074218750045 -0.9977500000000001 -0.025146484375 0.4376074218750045 -0.9978750000000002 -0.02288818359375 0.4376074218750045 -0.998 -0.020599365234375 0.4376074218750045 -0.9981250000000001 -0.020599365234375 0.4376074218750045 -0.99825 -0.018310546875 0.4376074218750045 -0.9983750000000001 -0.018310546875 0.4376074218750045 -0.9985000000000001 -0.016021728515625 0.4376074218750045 -0.998625 -0.013763427734375 0.4376074218750045 -0.9987500000000001 -0.013763427734375 0.4376074218750045 -0.9988750000000001 -0.011474609375 0.4376074218750045 -0.999 -0.011474609375 0.4376074218750045 -0.9991250000000001 -0.009185791015625 0.4376074218750045 -0.99925 -0.00689697265625 0.4376074218750045 -0.999375 -0.00689697265625 0.4376074218750045 -0.9995000000000001 -0.004608154296875 0.4376074218750045 -0.999625 -0.004608154296875 0.4376074218750045 -0.99975 -0.0023193359375 0.4376074218750045 +0.96 -0.05413818359375 0.1197216796875046 +0.960125 -0.05438232421875 0.1197216796875046 +0.9602500000000001 -0.05438232421875 0.1197216796875046 +0.960375 -0.054656982421875 0.1197216796875046 +0.9605 -0.054901123046875 0.1197216796875046 +0.9606250000000001 -0.054901123046875 0.1197216796875046 +0.96075 -0.055145263671875 0.1197216796875046 +0.9608750000000001 -0.055145263671875 0.1197216796875046 +0.9609999999999999 -0.055389404296875 0.1197216796875046 +0.961125 -0.055633544921875 0.1197216796875046 +0.9612500000000001 -0.055633544921875 0.1197216796875046 +0.961375 -0.05584716796875 0.1197216796875046 +0.9615 -0.05584716796875 0.1197216796875046 +0.9616250000000001 -0.056060791015625 0.1197216796875046 +0.96175 -0.0562744140625 0.1197216796875046 +0.961875 -0.0562744140625 0.1197216796875046 +0.9619999999999999 -0.056488037109375 0.1197216796875046 +0.962125 -0.056488037109375 0.1197216796875046 +0.96225 -0.05670166015625 0.1197216796875046 +0.9623749999999999 -0.056884765625 0.1197216796875046 +0.9625 -0.056884765625 0.1197216796875046 +0.9626250000000001 -0.057098388671875 0.1197216796875046 +0.96275 -0.057098388671875 0.1197216796875046 +0.962875 -0.057281494140625 0.1197216796875046 +0.9629999999999999 -0.057464599609375 0.1197216796875046 +0.963125 -0.057464599609375 0.1197216796875046 +0.96325 -0.0576171875 0.1197216796875046 +0.9633749999999999 -0.0576171875 0.1197216796875046 +0.9635 -0.05780029296875 0.1197216796875046 +0.963625 -0.057952880859375 0.1197216796875046 +0.9637499999999999 -0.057952880859375 0.1197216796875046 +0.963875 -0.05810546875 0.1197216796875046 +0.9640000000000001 -0.05810546875 0.1197216796875046 +0.9641249999999999 -0.058258056640625 0.1197216796875046 +0.96425 -0.058380126953125 0.1197216796875046 +0.9643750000000001 -0.058380126953125 0.1197216796875046 +0.9645 -0.05853271484375 0.1197216796875046 +0.964625 -0.05853271484375 0.1197216796875046 +0.9647500000000001 -0.05865478515625 0.1197216796875046 +0.964875 -0.05877685546875 0.1197216796875046 +0.965 -0.05877685546875 0.1197216796875046 +0.9651250000000001 -0.058868408203125 0.1197216796875046 +0.96525 -0.058868408203125 0.1197216796875046 +0.965375 -0.058990478515625 0.1197216796875046 +0.9655000000000001 -0.05908203125 0.1197216796875046 +0.965625 -0.05908203125 0.1197216796875046 +0.9657500000000001 -0.059173583984375 0.1197216796875046 +0.9658750000000001 -0.059173583984375 0.1197216796875046 +0.966 -0.05926513671875 0.1197216796875046 +0.9661250000000001 -0.059356689453125 0.1197216796875046 +0.9662500000000001 -0.059356689453125 0.1197216796875046 +0.966375 -0.059417724609375 0.1197216796875046 +0.9665000000000001 -0.059417724609375 0.1197216796875046 +0.9666250000000002 -0.05950927734375 0.1197216796875046 +0.96675 -0.0595703125 0.1197216796875046 +0.9668750000000001 -0.0595703125 0.1197216796875046 +0.967 -0.05963134765625 0.1197216796875046 +0.9671250000000001 -0.05963134765625 0.1197216796875046 +0.9672500000000001 -0.059661865234375 0.1197216796875046 +0.967375 -0.059722900390625 0.1197216796875046 +0.9675000000000001 -0.059722900390625 0.1197216796875046 +0.9676250000000001 -0.05975341796875 0.1197216796875046 +0.96775 -0.05975341796875 0.1197216796875046 +0.9678750000000001 -0.059783935546875 0.1197216796875046 +0.968 -0.059783935546875 0.1197216796875046 +0.968125 -0.059783935546875 0.1197216796875046 +0.9682500000000001 -0.059814453125 0.1197216796875046 +0.968375 -0.059814453125 0.1197216796875046 +0.9685 -0.059814453125 0.1197216796875046 +0.9686250000000001 -0.059814453125 0.1197216796875046 +0.96875 -0.059814453125 0.1197216796875046 +0.9688750000000001 -0.059814453125 0.1197216796875046 +0.969 -0.059814453125 0.1197216796875046 +0.969125 -0.059814453125 0.1197216796875046 +0.9692500000000001 -0.059783935546875 0.1197216796875046 +0.969375 -0.059783935546875 0.1197216796875046 +0.9695 -0.059783935546875 0.1197216796875046 +0.9696250000000001 -0.059783935546875 0.1197216796875046 +0.96975 -0.05975341796875 0.1197216796875046 +0.969875 -0.059722900390625 0.1197216796875046 +0.9699999999999999 -0.059722900390625 0.1197216796875046 +0.970125 -0.059661865234375 0.1197216796875046 +0.9702500000000001 -0.059661865234375 0.1197216796875046 +0.9703749999999999 -0.05963134765625 0.1197216796875046 +0.9705 -0.0595703125 0.1197216796875046 +0.9706250000000001 -0.0595703125 0.1197216796875046 +0.97075 -0.05950927734375 0.1197216796875046 +0.970875 -0.05950927734375 0.1197216796875046 +0.9709999999999999 -0.059417724609375 0.1197216796875046 +0.971125 -0.059356689453125 0.1197216796875046 +0.97125 -0.059356689453125 0.1197216796875046 +0.9713749999999999 -0.05926513671875 0.1197216796875046 +0.9715 -0.05926513671875 0.1197216796875046 +0.971625 -0.059173583984375 0.1197216796875046 +0.9717499999999999 -0.05908203125 0.1197216796875046 +0.971875 -0.05908203125 0.1197216796875046 +0.9719999999999999 -0.058990478515625 0.1197216796875046 +0.972125 -0.058990478515625 0.1197216796875046 +0.97225 -0.058868408203125 0.1197216796875046 +0.9723749999999999 -0.05877685546875 0.1197216796875046 +0.9725 -0.05877685546875 0.1197216796875046 +0.972625 -0.05865478515625 0.1197216796875046 +0.9727499999999999 -0.05865478515625 0.1197216796875046 +0.972875 -0.05853271484375 0.1197216796875046 +0.973 -0.058380126953125 0.1197216796875046 +0.9731249999999999 -0.058380126953125 0.1197216796875046 +0.97325 -0.058258056640625 0.1197216796875046 +0.9733750000000001 -0.058258056640625 0.1197216796875046 +0.9734999999999999 -0.05810546875 0.1197216796875046 +0.973625 -0.057952880859375 0.1197216796875046 +0.9737500000000001 -0.057952880859375 0.1197216796875046 +0.973875 -0.05780029296875 0.1197216796875046 +0.974 -0.05780029296875 0.1197216796875046 +0.9741250000000001 -0.0576171875 0.1197216796875046 +0.97425 -0.057464599609375 0.1197216796875046 +0.974375 -0.057464599609375 0.1197216796875046 +0.9745000000000001 -0.057281494140625 0.1197216796875046 +0.974625 -0.057281494140625 0.1197216796875046 +0.97475 -0.057098388671875 0.1197216796875046 +0.9748750000000001 -0.056884765625 0.1197216796875046 +0.975 -0.056884765625 0.1197216796875046 +0.9751250000000001 -0.05670166015625 0.1197216796875046 +0.9752500000000001 -0.05670166015625 0.1197216796875046 +0.975375 -0.056488037109375 0.1197216796875046 +0.9755000000000001 -0.0562744140625 0.1197216796875046 +0.9756250000000001 -0.0562744140625 0.1197216796875046 +0.97575 -0.056060791015625 0.1197216796875046 +0.9758750000000001 -0.056060791015625 0.1197216796875046 +0.976 -0.05584716796875 0.1197216796875046 +0.976125 -0.055633544921875 0.1197216796875046 +0.9762500000000001 -0.055633544921875 0.1197216796875046 +0.976375 -0.055389404296875 0.1197216796875046 +0.9765000000000001 -0.055389404296875 0.1197216796875046 +0.9766249999999999 -0.055145263671875 0.1197216796875046 +0.97675 -0.054901123046875 0.1197216796875046 +0.9768750000000001 -0.054901123046875 0.1197216796875046 +0.977 -0.054656982421875 0.1197216796875046 +0.977125 -0.054656982421875 0.1197216796875046 +0.9772500000000001 -0.05438232421875 0.1197216796875046 +0.977375 -0.05413818359375 0.1197216796875046 +0.9775 -0.05413818359375 0.1197216796875046 +0.9776249999999999 -0.053863525390625 0.1197216796875046 +0.97775 -0.053863525390625 0.1197216796875046 +0.977875 -0.0535888671875 0.1197216796875046 +0.9779999999999999 -0.053314208984375 0.1197216796875046 +0.978125 -0.053314208984375 0.1197216796875046 +0.9782500000000001 -0.053009033203125 0.1197216796875046 +0.978375 -0.053009033203125 0.1197216796875046 +0.9785 -0.052734375 0.1197216796875046 +0.9786249999999999 -0.05242919921875 0.1197216796875046 +0.97875 -0.05242919921875 0.1197216796875046 +0.978875 -0.0521240234375 0.1197216796875046 +0.9789999999999999 -0.0521240234375 0.1197216796875046 +0.979125 -0.05181884765625 0.1197216796875046 +0.97925 -0.051483154296875 0.1197216796875046 +0.9793749999999999 -0.051483154296875 0.1197216796875046 +0.9795 -0.051177978515625 0.1197216796875046 +0.9796250000000001 -0.051177978515625 0.1197216796875046 +0.9797499999999999 -0.05084228515625 0.1197216796875046 +0.979875 -0.050506591796875 0.1197216796875046 +0.9800000000000001 -0.050506591796875 0.1197216796875046 +0.980125 -0.0501708984375 0.1197216796875046 +0.98025 -0.0501708984375 0.1197216796875046 +0.9803750000000001 -0.049835205078125 0.1197216796875046 +0.9805 -0.049468994140625 0.1197216796875046 +0.980625 -0.049468994140625 0.1197216796875046 +0.9807500000000001 -0.04913330078125 0.1197216796875046 +0.980875 -0.04913330078125 0.1197216796875046 +0.981 -0.04876708984375 0.1197216796875046 +0.9811250000000001 -0.04840087890625 0.1197216796875046 +0.98125 -0.04840087890625 0.1197216796875046 +0.9813750000000001 -0.04803466796875 0.1197216796875046 +0.9815000000000001 -0.04803466796875 0.1197216796875046 +0.981625 -0.047637939453125 0.1197216796875046 +0.9817500000000001 -0.047271728515625 0.1197216796875046 +0.9818750000000001 -0.047271728515625 0.1197216796875046 +0.982 -0.046875 0.1197216796875046 +0.9821250000000001 -0.046875 0.1197216796875046 +0.9822500000000002 -0.046478271484375 0.1197216796875046 +0.982375 -0.04608154296875 0.1197216796875046 +0.9825000000000001 -0.04608154296875 0.1197216796875046 +0.982625 -0.045684814453125 0.1197216796875046 +0.9827500000000001 -0.045684814453125 0.1197216796875046 +0.9828750000000001 -0.0452880859375 0.1197216796875046 +0.983 -0.04486083984375 0.1197216796875046 +0.9831250000000001 -0.04486083984375 0.1197216796875046 +0.9832500000000001 -0.044464111328125 0.1197216796875046 +0.983375 -0.044464111328125 0.1197216796875046 +0.9835000000000001 -0.044036865234375 0.1197216796875046 +0.983625 -0.043609619140625 0.1197216796875046 +0.98375 -0.043609619140625 0.1197216796875046 +0.9838750000000001 -0.043182373046875 0.1197216796875046 +0.984 -0.043182373046875 0.1197216796875046 +0.984125 -0.042755126953125 0.1197216796875046 +0.9842500000000001 -0.04229736328125 0.1197216796875046 +0.984375 -0.04229736328125 0.1197216796875046 +0.9845000000000001 -0.041839599609375 0.1197216796875046 +0.984625 -0.041839599609375 0.1197216796875046 +0.98475 -0.041412353515625 0.1197216796875046 +0.9848750000000001 -0.04095458984375 0.1197216796875046 +0.985 -0.04095458984375 0.1197216796875046 +0.985125 -0.040496826171875 0.1197216796875046 +0.9852500000000001 -0.040496826171875 0.1197216796875046 +0.985375 -0.0400390625 0.1197216796875046 +0.9855 -0.03955078125 0.1197216796875046 +0.9856249999999999 -0.03955078125 0.1197216796875046 +0.98575 -0.039093017578125 0.1197216796875046 +0.9858750000000001 -0.039093017578125 0.1197216796875046 +0.9859999999999999 -0.038604736328125 0.1197216796875046 +0.986125 -0.038116455078125 0.1197216796875046 +0.9862500000000001 -0.038116455078125 0.1197216796875046 +0.986375 -0.03765869140625 0.1197216796875046 +0.9865 -0.03765869140625 0.1197216796875046 +0.9866249999999999 -0.03717041015625 0.1197216796875046 +0.98675 -0.036651611328125 0.1197216796875046 +0.986875 -0.036651611328125 0.1197216796875046 +0.9869999999999999 -0.036163330078125 0.1197216796875046 +0.987125 -0.036163330078125 0.1197216796875046 +0.98725 -0.035675048828125 0.1197216796875046 +0.9873749999999999 -0.03515625 0.1197216796875046 +0.9875 -0.03515625 0.1197216796875046 +0.9876249999999999 -0.034637451171875 0.1197216796875046 +0.98775 -0.034637451171875 0.1197216796875046 +0.987875 -0.034149169921875 0.1197216796875046 +0.9879999999999999 -0.03363037109375 0.1197216796875046 +0.988125 -0.03363037109375 0.1197216796875046 +0.98825 -0.033111572265625 0.1197216796875046 +0.9883749999999999 -0.033111572265625 0.1197216796875046 +0.9885 -0.032562255859375 0.1197216796875046 +0.988625 -0.03204345703125 0.1197216796875046 +0.9887499999999999 -0.03204345703125 0.1197216796875046 +0.988875 -0.031524658203125 0.1197216796875046 +0.9890000000000001 -0.031524658203125 0.1197216796875046 +0.9891249999999999 -0.030975341796875 0.1197216796875046 +0.98925 -0.03045654296875 0.1197216796875046 +0.9893750000000001 -0.03045654296875 0.1197216796875046 +0.9895 -0.0299072265625 0.1197216796875046 +0.989625 -0.0299072265625 0.1197216796875046 +0.9897500000000001 -0.02935791015625 0.1197216796875046 +0.989875 -0.02880859375 0.1197216796875046 +0.99 -0.02880859375 0.1197216796875046 +0.9901250000000001 -0.02825927734375 0.1197216796875046 +0.99025 -0.02825927734375 0.1197216796875046 +0.990375 -0.0277099609375 0.1197216796875046 +0.9905000000000001 -0.02716064453125 0.1197216796875046 +0.990625 -0.02716064453125 0.1197216796875046 +0.9907500000000001 -0.026580810546875 0.1197216796875046 +0.9908750000000001 -0.026580810546875 0.1197216796875046 +0.991 -0.026031494140625 0.1197216796875046 +0.9911250000000001 -0.02545166015625 0.1197216796875046 +0.9912500000000001 -0.02545166015625 0.1197216796875046 +0.991375 -0.02490234375 0.1197216796875046 +0.9915000000000001 -0.02490234375 0.1197216796875046 +0.991625 -0.024322509765625 0.1197216796875046 +0.99175 -0.02374267578125 0.1197216796875046 +0.9918750000000001 -0.02374267578125 0.1197216796875046 +0.992 -0.08477783203125 0.4376074218750045 +0.9921250000000001 -0.08477783203125 0.4376074218750045 +0.9922499999999999 -0.0826416015625 0.4376074218750045 +0.992375 -0.080535888671875 0.4376074218750045 +0.9925000000000001 -0.080535888671875 0.4376074218750045 +0.992625 -0.078399658203125 0.4376074218750045 +0.99275 -0.078399658203125 0.4376074218750045 +0.9928750000000001 -0.07623291015625 0.4376074218750045 +0.993 -0.0740966796875 0.4376074218750045 +0.993125 -0.0740966796875 0.4376074218750045 +0.9932499999999999 -0.071929931640625 0.4376074218750045 +0.993375 -0.071929931640625 0.4376074218750045 +0.9935 -0.06976318359375 0.4376074218750045 +0.9936249999999999 -0.067596435546875 0.4376074218750045 +0.99375 -0.067596435546875 0.4376074218750045 +0.9938750000000001 -0.065399169921875 0.4376074218750045 +0.994 -0.065399169921875 0.4376074218750045 +0.994125 -0.063201904296875 0.4376074218750045 +0.9942499999999999 -0.06103515625 0.4376074218750045 +0.994375 -0.06103515625 0.4376074218750045 +0.9945 -0.058807373046875 0.4376074218750045 +0.9946249999999999 -0.058807373046875 0.4376074218750045 +0.99475 -0.056610107421875 0.4376074218750045 +0.994875 -0.05438232421875 0.4376074218750045 +0.9949999999999999 -0.05438232421875 0.4376074218750045 +0.995125 -0.05218505859375 0.4376074218750045 +0.9952500000000001 -0.05218505859375 0.4376074218750045 +0.9953749999999999 -0.049957275390625 0.4376074218750045 +0.9955 -0.047698974609375 0.4376074218750045 +0.9956250000000001 -0.047698974609375 0.4376074218750045 +0.99575 -0.04547119140625 0.4376074218750045 +0.995875 -0.04547119140625 0.4376074218750045 +0.9960000000000001 -0.043212890625 0.4376074218750045 +0.996125 -0.040985107421875 0.4376074218750045 +0.99625 -0.040985107421875 0.4376074218750045 +0.9963750000000001 -0.038726806640625 0.4376074218750045 +0.9965 -0.038726806640625 0.4376074218750045 +0.996625 -0.036468505859375 0.4376074218750045 +0.9967500000000001 -0.034210205078125 0.4376074218750045 +0.996875 -0.034210205078125 0.4376074218750045 +0.9970000000000001 -0.031951904296875 0.4376074218750045 +0.9971250000000001 -0.031951904296875 0.4376074218750045 +0.99725 -0.0296630859375 0.4376074218750045 +0.9973750000000001 -0.02740478515625 0.4376074218750045 +0.9975000000000001 -0.02740478515625 0.4376074218750045 +0.997625 -0.025115966796875 0.4376074218750045 +0.9977500000000001 -0.025115966796875 0.4376074218750045 +0.9978750000000002 -0.022857666015625 0.4376074218750045 +0.998 -0.02056884765625 0.4376074218750045 +0.9981250000000001 -0.02056884765625 0.4376074218750045 +0.99825 -0.018280029296875 0.4376074218750045 +0.9983750000000001 -0.018280029296875 0.4376074218750045 +0.9985000000000001 -0.0159912109375 0.4376074218750045 +0.998625 -0.01373291015625 0.4376074218750045 +0.9987500000000001 -0.01373291015625 0.4376074218750045 +0.9988750000000001 -0.011444091796875 0.4376074218750045 +0.999 -0.011444091796875 0.4376074218750045 +0.9991250000000001 -0.0091552734375 0.4376074218750045 +0.99925 -0.006866455078125 0.4376074218750045 +0.999375 -0.006866455078125 0.4376074218750045 +0.9995000000000001 -0.00457763671875 0.4376074218750045 +0.999625 -0.00457763671875 0.4376074218750045 +0.99975 -0.002288818359375 0.4376074218750045 0.9998750000000001 0.0 0.4376074218750045 1.0 0.0 0.4376074218750045 1.000125 0.002288818359375 0.4376074218750045 @@ -8499,504 +8499,504 @@ 1.06225 0.0047607421875 0.9150244140625022 1.062375 0.0 0.9150244140625022 1.0625 0.0 0.9150244140625022 -1.062625 -0.004791259765625 0.9150244140625022 -1.06275 -0.004791259765625 0.9150244140625022 -1.062875 -0.00958251953125 0.9150244140625022 -1.063 -0.014373779296875 0.9150244140625022 -1.063125 -0.014373779296875 0.9150244140625022 -1.06325 -0.0191650390625 0.9150244140625022 -1.063375 -0.0191650390625 0.9150244140625022 -1.0635 -0.023956298828125 0.9150244140625022 -1.063625 -0.02874755859375 0.9150244140625022 -1.06375 -0.02874755859375 0.9150244140625022 -1.063875 -0.03350830078125 0.9150244140625022 -1.064 -0.03350830078125 0.9150244140625022 -1.064125 -0.038299560546875 0.9150244140625022 -1.06425 -0.043060302734375 0.9150244140625022 -1.064375 -0.043060302734375 0.9150244140625022 -1.0645 -0.047821044921875 0.9150244140625022 -1.064625 -0.047821044921875 0.9150244140625022 -1.06475 -0.052581787109375 0.9150244140625022 -1.064875 -0.057342529296875 0.9150244140625022 -1.065 -0.057342529296875 0.9150244140625022 -1.065125 -0.062103271484375 0.9150244140625022 -1.06525 -0.062103271484375 0.9150244140625022 -1.065375 -0.06683349609375 0.9150244140625022 -1.0655 -0.071563720703125 0.9150244140625022 -1.065625 -0.071563720703125 0.9150244140625022 -1.06575 -0.0762939453125 0.9150244140625022 -1.065875 -0.0762939453125 0.9150244140625022 -1.066 -0.081024169921875 0.9150244140625022 -1.066125 -0.085723876953125 0.9150244140625022 -1.06625 -0.085723876953125 0.9150244140625022 -1.066375 -0.090423583984375 0.9150244140625022 -1.0665 -0.090423583984375 0.9150244140625022 -1.066625 -0.095123291015625 0.9150244140625022 -1.06675 -0.09979248046875 0.9150244140625022 -1.066875 -0.09979248046875 0.9150244140625022 -1.067 -0.1044921875 0.9150244140625022 -1.067125 -0.1044921875 0.9150244140625022 -1.06725 -0.109130859375 0.9150244140625022 -1.067375 -0.11376953125 0.9150244140625022 -1.0675 -0.11376953125 0.9150244140625022 -1.067625 -0.118408203125 0.9150244140625022 -1.06775 -0.118408203125 0.9150244140625022 -1.067875 -0.123046875 0.9150244140625022 -1.068 -0.127655029296875 0.9150244140625022 -1.068125 -0.127655029296875 0.9150244140625022 -1.06825 -0.132232666015625 0.9150244140625022 -1.068375 -0.132232666015625 0.9150244140625022 -1.0685 -0.136810302734375 0.9150244140625022 -1.068625 -0.141387939453125 0.9150244140625022 -1.06875 -0.141387939453125 0.9150244140625022 -1.068875 -0.14593505859375 0.9150244140625022 -1.069 -0.14593505859375 0.9150244140625022 -1.069125 -0.15045166015625 0.9150244140625022 -1.06925 -0.15496826171875 0.9150244140625022 -1.069375 -0.15496826171875 0.9150244140625022 -1.0695 -0.15948486328125 0.9150244140625022 -1.069625 -0.15948486328125 0.9150244140625022 -1.06975 -0.163970947265625 0.9150244140625022 -1.069875 -0.168426513671875 0.9150244140625022 -1.07 -0.168426513671875 0.9150244140625022 -1.070125 -0.1728515625 0.9150244140625022 -1.07025 -0.1728515625 0.9150244140625022 -1.070375 -0.177276611328125 0.9150244140625022 -1.0705 -0.18170166015625 0.9150244140625022 -1.070625 -0.18170166015625 0.9150244140625022 -1.07075 -0.18609619140625 0.9150244140625022 -1.070875 -0.18609619140625 0.9150244140625022 -1.071 -0.190460205078125 0.9150244140625022 -1.071125 -0.194793701171875 0.9150244140625022 -1.07125 -0.194793701171875 0.9150244140625022 -1.071375 -0.199127197265625 0.9150244140625022 -1.0715 -0.199127197265625 0.9150244140625022 -1.071625 -0.20343017578125 0.9150244140625022 -1.07175 -0.20770263671875 0.9150244140625022 -1.071875 -0.20770263671875 0.9150244140625022 -1.072 -0.211944580078125 0.9150244140625022 -1.072125 -0.211944580078125 0.9150244140625022 -1.07225 -0.2161865234375 0.9150244140625022 -1.072375 -0.22039794921875 0.9150244140625022 -1.0725 -0.22039794921875 0.9150244140625022 -1.072625 -0.224578857421875 0.9150244140625022 -1.07275 -0.224578857421875 0.9150244140625022 -1.072875 -0.228759765625 0.9150244140625022 -1.073 -0.232879638671875 0.9150244140625022 -1.073125 -0.232879638671875 0.9150244140625022 -1.07325 -0.23699951171875 0.9150244140625022 -1.073375 -0.23699951171875 0.9150244140625022 -1.0735 -0.2410888671875 0.9150244140625022 -1.073625 -0.245147705078125 0.9150244140625022 -1.07375 -0.245147705078125 0.9150244140625022 -1.073875 -0.249176025390625 0.9150244140625022 -1.074 -0.249176025390625 0.9150244140625022 -1.074125 -0.253173828125 0.9150244140625022 -1.07425 -0.25714111328125 0.9150244140625022 -1.074375 -0.25714111328125 0.9150244140625022 -1.0745 -0.2611083984375 0.9150244140625022 -1.074625 -0.2611083984375 0.9150244140625022 -1.07475 -0.2650146484375 0.9150244140625022 -1.074875 -0.2689208984375 0.9150244140625022 -1.075 -0.2689208984375 0.9150244140625022 -1.075125 -0.27276611328125 0.9150244140625022 -1.07525 -0.27276611328125 0.9150244140625022 -1.075375 -0.276611328125 0.9150244140625022 -1.0755 -0.280426025390625 0.9150244140625022 -1.075625 -0.280426025390625 0.9150244140625022 -1.07575 -0.2841796875 0.9150244140625022 -1.075875 -0.2841796875 0.9150244140625022 -1.076 -0.28790283203125 0.9150244140625022 -1.076125 -0.2916259765625 0.9150244140625022 -1.07625 -0.2916259765625 0.9150244140625022 -1.076375 -0.2952880859375 0.9150244140625022 -1.0765 -0.2952880859375 0.9150244140625022 -1.076625 -0.2989501953125 0.9150244140625022 -1.07675 -0.30255126953125 0.9150244140625022 -1.076875 -0.30255126953125 0.9150244140625022 -1.077 -0.306121826171875 0.9150244140625022 -1.077125 -0.306121826171875 0.9150244140625022 -1.07725 -0.309661865234375 0.9150244140625022 -1.077375 -0.31317138671875 0.9150244140625022 -1.0775 -0.31317138671875 0.9150244140625022 -1.077625 -0.316650390625 0.9150244140625022 -1.07775 -0.316650390625 0.9150244140625022 -1.077875 -0.320098876953125 0.9150244140625022 -1.078 -0.323486328125 0.9150244140625022 -1.078125 -0.323486328125 0.9150244140625022 -1.07825 -0.326873779296875 0.9150244140625022 -1.078375 -0.326873779296875 0.9150244140625022 -1.0785 -0.3302001953125 0.9150244140625022 -1.078625 -0.33349609375 0.9150244140625022 -1.07875 -0.33349609375 0.9150244140625022 -1.078875 -0.336761474609375 0.9150244140625022 -1.079 -0.336761474609375 0.9150244140625022 -1.079125 -0.339996337890625 0.9150244140625022 -1.07925 -0.343170166015625 0.9150244140625022 -1.079375 -0.343170166015625 0.9150244140625022 -1.0795 -0.3463134765625 0.9150244140625022 -1.079625 -0.3463134765625 0.9150244140625022 -1.07975 -0.34942626953125 0.9150244140625022 -1.079875 -0.352508544921875 0.9150244140625022 -1.08 -0.352508544921875 0.9150244140625022 -1.080125 -0.35552978515625 0.9150244140625022 -1.08025 -0.35552978515625 0.9150244140625022 -1.080375 -0.358551025390625 0.9150244140625022 -1.0805 -0.36151123046875 0.9150244140625022 -1.080625 -0.36151123046875 0.9150244140625022 -1.08075 -0.364410400390625 0.9150244140625022 -1.080875 -0.364410400390625 0.9150244140625022 -1.081 -0.367279052734375 0.9150244140625022 -1.081125 -0.3701171875 0.9150244140625022 -1.08125 -0.3701171875 0.9150244140625022 -1.081375 -0.3729248046875 0.9150244140625022 -1.0815 -0.3729248046875 0.9150244140625022 -1.081625 -0.37567138671875 0.9150244140625022 -1.08175 -0.378387451171875 0.9150244140625022 -1.081875 -0.378387451171875 0.9150244140625022 -1.082 -0.381072998046875 0.9150244140625022 -1.082125 -0.381072998046875 0.9150244140625022 -1.08225 -0.383697509765625 0.9150244140625022 -1.082375 -0.38629150390625 0.9150244140625022 -1.0825 -0.38629150390625 0.9150244140625022 -1.082625 -0.388824462890625 0.9150244140625022 -1.08275 -0.388824462890625 0.9150244140625022 -1.082875 -0.391326904296875 0.9150244140625022 -1.083 -0.393768310546875 0.9150244140625022 -1.083125 -0.393768310546875 0.9150244140625022 -1.08325 -0.396209716796875 0.9150244140625022 -1.083375 -0.396209716796875 0.9150244140625022 -1.0835 -0.398590087890625 0.9150244140625022 -1.083625 -0.400909423828125 0.9150244140625022 -1.08375 -0.400909423828125 0.9150244140625022 -1.083875 -0.4031982421875 0.9150244140625022 -1.084 -0.4031982421875 0.9150244140625022 -1.084125 -0.40545654296875 0.9150244140625022 -1.08425 -0.407623291015625 0.9150244140625022 -1.084375 -0.407623291015625 0.9150244140625022 -1.0845 -0.4097900390625 0.9150244140625022 -1.084625 -0.4097900390625 0.9150244140625022 -1.08475 -0.411895751953125 0.9150244140625022 -1.084875 -0.413970947265625 0.9150244140625022 -1.085 -0.413970947265625 0.9150244140625022 -1.085125 -0.41595458984375 0.9150244140625022 -1.08525 -0.41595458984375 0.9150244140625022 -1.085375 -0.417938232421875 0.9150244140625022 -1.0855 -0.419891357421875 0.9150244140625022 -1.085625 -0.419891357421875 0.9150244140625022 -1.08575 -0.4217529296875 0.9150244140625022 -1.085875 -0.4217529296875 0.9150244140625022 -1.086 -0.423583984375 0.9150244140625022 -1.086125 -0.42535400390625 0.9150244140625022 -1.08625 -0.42535400390625 0.9150244140625022 -1.086375 -0.4271240234375 0.9150244140625022 -1.0865 -0.4271240234375 0.9150244140625022 -1.086625 -0.428802490234375 0.9150244140625022 -1.08675 -0.430450439453125 0.9150244140625022 -1.086875 -0.430450439453125 0.9150244140625022 -1.087 -0.43206787109375 0.9150244140625022 -1.087125 -0.43206787109375 0.9150244140625022 -1.08725 -0.43359375 0.9150244140625022 -1.087375 -0.43511962890625 0.9150244140625022 -1.0875 -0.43511962890625 0.9150244140625022 -1.087625 -0.436553955078125 0.9150244140625022 -1.08775 -0.436553955078125 0.9150244140625022 -1.087875 -0.437957763671875 0.9150244140625022 -1.088 -0.479339599609375 0.9983886718750004 -1.088125 -0.479339599609375 0.9983886718750004 -1.08825 -0.48077392578125 0.9983886718750004 -1.088375 -0.48077392578125 0.9983886718750004 -1.0885 -0.482147216796875 0.9983886718750004 -1.088625 -0.483489990234375 0.9983886718750004 -1.08875 -0.483489990234375 0.9983886718750004 -1.088875 -0.484771728515625 0.9983886718750004 -1.089 -0.484771728515625 0.9983886718750004 -1.089125 -0.485992431640625 0.9983886718750004 -1.08925 -0.487152099609375 0.9983886718750004 -1.089375 -0.487152099609375 0.9983886718750004 -1.0895 -0.488250732421875 0.9983886718750004 -1.089625 -0.488250732421875 0.9983886718750004 -1.08975 -0.48931884765625 0.9983886718750004 -1.089875 -0.490325927734375 0.9983886718750004 -1.09 -0.490325927734375 0.9983886718750004 -1.090125 -0.49127197265625 0.9983886718750004 -1.09025 -0.49127197265625 0.9983886718750004 -1.090375 -0.4921875 0.9983886718750004 -1.0905 -0.493011474609375 0.9983886718750004 -1.090625 -0.493011474609375 0.9983886718750004 -1.09075 -0.493804931640625 0.9983886718750004 -1.090875 -0.493804931640625 0.9983886718750004 -1.091 -0.494537353515625 0.9983886718750004 -1.091125 -0.4952392578125 0.9983886718750004 -1.09125 -0.4952392578125 0.9983886718750004 -1.091375 -0.495849609375 0.9983886718750004 -1.0915 -0.495849609375 0.9983886718750004 -1.091625 -0.496429443359375 0.9983886718750004 -1.09175 -0.4969482421875 0.9983886718750004 -1.091875 -0.4969482421875 0.9983886718750004 -1.092 -0.4974365234375 0.9983886718750004 -1.092125 -0.4974365234375 0.9983886718750004 -1.09225 -0.497833251953125 0.9983886718750004 -1.092375 -0.498199462890625 0.9983886718750004 -1.0925 -0.498199462890625 0.9983886718750004 -1.092625 -0.498504638671875 0.9983886718750004 -1.09275 -0.498504638671875 0.9983886718750004 -1.092875 -0.498748779296875 0.9983886718750004 -1.093 -0.498931884765625 0.9983886718750004 -1.093125 -0.498931884765625 0.9983886718750004 -1.09325 -0.499053955078125 0.9983886718750004 -1.093375 -0.499053955078125 0.9983886718750004 -1.0935 -0.4991455078125 0.9983886718750004 -1.093625 -0.499176025390625 0.9983886718750004 -1.09375 -0.499176025390625 0.9983886718750004 -1.093875 -0.4991455078125 0.9983886718750004 -1.094 -0.4991455078125 0.9983886718750004 -1.094125 -0.499053955078125 0.9983886718750004 -1.09425 -0.498931884765625 0.9983886718750004 -1.094375 -0.498931884765625 0.9983886718750004 -1.0945 -0.498748779296875 0.9983886718750004 -1.094625 -0.498748779296875 0.9983886718750004 -1.09475 -0.498504638671875 0.9983886718750004 -1.094875 -0.498199462890625 0.9983886718750004 -1.095 -0.498199462890625 0.9983886718750004 -1.095125 -0.497833251953125 0.9983886718750004 -1.09525 -0.497833251953125 0.9983886718750004 -1.095375 -0.4974365234375 0.9983886718750004 -1.0955 -0.4969482421875 0.9983886718750004 -1.095625 -0.4969482421875 0.9983886718750004 -1.09575 -0.496429443359375 0.9983886718750004 -1.095875 -0.496429443359375 0.9983886718750004 -1.096 -0.495849609375 0.9983886718750004 -1.096125 -0.4952392578125 0.9983886718750004 -1.09625 -0.4952392578125 0.9983886718750004 -1.096375 -0.494537353515625 0.9983886718750004 -1.0965 -0.494537353515625 0.9983886718750004 -1.096625 -0.493804931640625 0.9983886718750004 -1.09675 -0.493011474609375 0.9983886718750004 -1.096875 -0.493011474609375 0.9983886718750004 -1.097 -0.4921875 0.9983886718750004 -1.097125 -0.4921875 0.9983886718750004 -1.09725 -0.49127197265625 0.9983886718750004 -1.097375 -0.490325927734375 0.9983886718750004 -1.0975 -0.490325927734375 0.9983886718750004 -1.097625 -0.48931884765625 0.9983886718750004 -1.09775 -0.48931884765625 0.9983886718750004 -1.097875 -0.488250732421875 0.9983886718750004 -1.098 -0.487152099609375 0.9983886718750004 -1.098125 -0.487152099609375 0.9983886718750004 -1.09825 -0.485992431640625 0.9983886718750004 -1.098375 -0.485992431640625 0.9983886718750004 -1.0985 -0.484771728515625 0.9983886718750004 -1.098625 -0.483489990234375 0.9983886718750004 -1.09875 -0.483489990234375 0.9983886718750004 -1.098875 -0.482147216796875 0.9983886718750004 -1.099 -0.482147216796875 0.9983886718750004 -1.099125 -0.48077392578125 0.9983886718750004 -1.09925 -0.479339599609375 0.9983886718750004 -1.099375 -0.479339599609375 0.9983886718750004 -1.0995 -0.477874755859375 0.9983886718750004 -1.099625 -0.477874755859375 0.9983886718750004 -1.09975 -0.476318359375 0.9983886718750004 -1.099875 -0.4747314453125 0.9983886718750004 -1.1 -0.4747314453125 0.9983886718750004 -1.100125 -0.47308349609375 0.9983886718750004 -1.10025 -0.47308349609375 0.9983886718750004 -1.100375 -0.471405029296875 0.9983886718750004 -1.1005 -0.46966552734375 0.9983886718750004 -1.100625 -0.46966552734375 0.9983886718750004 -1.10075 -0.467864990234375 0.9983886718750004 -1.100875 -0.467864990234375 0.9983886718750004 -1.101 -0.46600341796875 0.9983886718750004 -1.101125 -0.464111328125 0.9983886718750004 -1.10125 -0.464111328125 0.9983886718750004 -1.101375 -0.462188720703125 0.9983886718750004 -1.1015 -0.462188720703125 0.9983886718750004 -1.101625 -0.460174560546875 0.9983886718750004 -1.10175 -0.4581298828125 0.9983886718750004 -1.101875 -0.4581298828125 0.9983886718750004 -1.102 -0.456024169921875 0.9983886718750004 -1.102125 -0.456024169921875 0.9983886718750004 -1.10225 -0.453857421875 0.9983886718750004 -1.102375 -0.45166015625 0.9983886718750004 -1.1025 -0.45166015625 0.9983886718750004 -1.102625 -0.44940185546875 0.9983886718750004 -1.10275 -0.44940185546875 0.9983886718750004 -1.102875 -0.447113037109375 0.9983886718750004 -1.103 -0.44476318359375 0.9983886718750004 -1.103125 -0.44476318359375 0.9983886718750004 -1.10325 -0.4423828125 0.9983886718750004 -1.103375 -0.4423828125 0.9983886718750004 -1.1035 -0.439910888671875 0.9983886718750004 -1.103625 -0.437408447265625 0.9983886718750004 -1.10375 -0.437408447265625 0.9983886718750004 -1.103875 -0.43487548828125 0.9983886718750004 -1.104 -0.43487548828125 0.9983886718750004 -1.104125 -0.43231201171875 0.9983886718750004 -1.10425 -0.429656982421875 0.9983886718750004 -1.104375 -0.429656982421875 0.9983886718750004 -1.1045 -0.426971435546875 0.9983886718750004 -1.104625 -0.426971435546875 0.9983886718750004 -1.10475 -0.42425537109375 0.9983886718750004 -1.104875 -0.421478271484375 0.9983886718750004 -1.105 -0.421478271484375 0.9983886718750004 -1.105125 -0.41864013671875 0.9983886718750004 -1.10525 -0.41864013671875 0.9983886718750004 -1.105375 -0.415771484375 0.9983886718750004 -1.1055 -0.412841796875 0.9983886718750004 -1.105625 -0.412841796875 0.9983886718750004 -1.10575 -0.409881591796875 0.9983886718750004 -1.105875 -0.409881591796875 0.9983886718750004 -1.106 -0.406890869140625 0.9983886718750004 -1.106125 -0.403839111328125 0.9983886718750004 -1.10625 -0.403839111328125 0.9983886718750004 -1.106375 -0.400726318359375 0.9983886718750004 -1.1065 -0.400726318359375 0.9983886718750004 -1.106625 -0.3975830078125 0.9983886718750004 -1.10675 -0.394439697265625 0.9983886718750004 -1.106875 -0.394439697265625 0.9983886718750004 -1.107 -0.391204833984375 0.9983886718750004 -1.107125 -0.391204833984375 0.9983886718750004 -1.10725 -0.387939453125 0.9983886718750004 -1.107375 -0.384613037109375 0.9983886718750004 -1.1075 -0.384613037109375 0.9983886718750004 -1.107625 -0.381256103515625 0.9983886718750004 -1.10775 -0.381256103515625 0.9983886718750004 -1.107875 -0.37786865234375 0.9983886718750004 -1.108 -0.374420166015625 0.9983886718750004 -1.108125 -0.374420166015625 0.9983886718750004 -1.10825 -0.370941162109375 0.9983886718750004 -1.108375 -0.370941162109375 0.9983886718750004 -1.1085 -0.367431640625 0.9983886718750004 -1.108625 -0.3638916015625 0.9983886718750004 -1.10875 -0.3638916015625 0.9983886718750004 -1.108875 -0.36029052734375 0.9983886718750004 -1.109 -0.36029052734375 0.9983886718750004 -1.109125 -0.356658935546875 0.9983886718750004 -1.10925 -0.35296630859375 0.9983886718750004 -1.109375 -0.35296630859375 0.9983886718750004 -1.1095 -0.3492431640625 0.9983886718750004 -1.109625 -0.3492431640625 0.9983886718750004 -1.10975 -0.345489501953125 0.9983886718750004 -1.109875 -0.341705322265625 0.9983886718750004 -1.11 -0.341705322265625 0.9983886718750004 -1.110125 -0.337890625 0.9983886718750004 -1.11025 -0.337890625 0.9983886718750004 -1.110375 -0.334014892578125 0.9983886718750004 -1.1105 -0.330108642578125 0.9983886718750004 -1.110625 -0.330108642578125 0.9983886718750004 -1.11075 -0.326171875 0.9983886718750004 -1.110875 -0.326171875 0.9983886718750004 -1.111 -0.32220458984375 0.9983886718750004 -1.111125 -0.31817626953125 0.9983886718750004 -1.11125 -0.31817626953125 0.9983886718750004 -1.111375 -0.31414794921875 0.9983886718750004 -1.1115 -0.31414794921875 0.9983886718750004 -1.111625 -0.31005859375 0.9983886718750004 -1.11175 -0.305938720703125 0.9983886718750004 -1.111875 -0.305938720703125 0.9983886718750004 -1.112 -0.301788330078125 0.9983886718750004 -1.112125 -0.301788330078125 0.9983886718750004 -1.11225 -0.297607421875 0.9983886718750004 -1.112375 -0.29339599609375 0.9983886718750004 -1.1125 -0.29339599609375 0.9983886718750004 -1.112625 -0.289154052734375 0.9983886718750004 -1.11275 -0.289154052734375 0.9983886718750004 -1.112875 -0.284881591796875 0.9983886718750004 -1.113 -0.28057861328125 0.9983886718750004 -1.113125 -0.28057861328125 0.9983886718750004 -1.11325 -0.2762451171875 0.9983886718750004 -1.113375 -0.2762451171875 0.9983886718750004 -1.1135 -0.271881103515625 0.9983886718750004 -1.113625 -0.267486572265625 0.9983886718750004 -1.11375 -0.267486572265625 0.9983886718750004 -1.113875 -0.263031005859375 0.9983886718750004 -1.114 -0.263031005859375 0.9983886718750004 -1.114125 -0.25860595703125 0.9983886718750004 -1.11425 -0.25408935546875 0.9983886718750004 -1.114375 -0.25408935546875 0.9983886718750004 -1.1145 -0.249603271484375 0.9983886718750004 -1.114625 -0.249603271484375 0.9983886718750004 -1.11475 -0.24505615234375 0.9983886718750004 -1.114875 -0.240478515625 0.9983886718750004 -1.115 -0.240478515625 0.9983886718750004 -1.115125 -0.23590087890625 0.9983886718750004 -1.11525 -0.23590087890625 0.9983886718750004 -1.115375 -0.23126220703125 0.9983886718750004 -1.1155 -0.22662353515625 0.9983886718750004 -1.115625 -0.22662353515625 0.9983886718750004 -1.11575 -0.221954345703125 0.9983886718750004 -1.115875 -0.221954345703125 0.9983886718750004 -1.116 -0.217254638671875 0.9983886718750004 -1.116125 -0.212554931640625 0.9983886718750004 -1.11625 -0.212554931640625 0.9983886718750004 -1.116375 -0.207794189453125 0.9983886718750004 -1.1165 -0.207794189453125 0.9983886718750004 -1.116625 -0.203033447265625 0.9983886718750004 -1.11675 -0.1982421875 0.9983886718750004 -1.116875 -0.1982421875 0.9983886718750004 -1.117 -0.193450927734375 0.9983886718750004 -1.117125 -0.193450927734375 0.9983886718750004 -1.11725 -0.1885986328125 0.9983886718750004 -1.117375 -0.18377685546875 0.9983886718750004 -1.1175 -0.18377685546875 0.9983886718750004 -1.117625 -0.17889404296875 0.9983886718750004 -1.11775 -0.17889404296875 0.9983886718750004 -1.117875 -0.17401123046875 0.9983886718750004 -1.118 -0.169097900390625 0.9983886718750004 -1.118125 -0.169097900390625 0.9983886718750004 -1.11825 -0.164154052734375 0.9983886718750004 -1.118375 -0.164154052734375 0.9983886718750004 -1.1185 -0.159210205078125 0.9983886718750004 -1.118625 -0.154266357421875 0.9983886718750004 -1.11875 -0.154266357421875 0.9983886718750004 -1.118875 -0.149261474609375 0.9983886718750004 -1.119 -0.149261474609375 0.9983886718750004 -1.119125 -0.144287109375 0.9983886718750004 -1.11925 -0.139251708984375 0.9983886718750004 -1.119375 -0.139251708984375 0.9983886718750004 -1.1195 -0.134246826171875 0.9983886718750004 -1.119625 -0.134246826171875 0.9983886718750004 -1.11975 -0.12921142578125 0.9983886718750004 -1.119875 -0.1241455078125 0.9983886718750004 -1.12 -0.11865234375 0.9543457031249984 -1.120125 -0.11383056640625 0.9543457031249984 -1.12025 -0.11383056640625 0.9543457031249984 -1.120375 -0.108978271484375 0.9543457031249984 -1.1205 -0.104095458984375 0.9543457031249984 -1.120625 -0.104095458984375 0.9543457031249984 -1.12075 -0.099212646484375 0.9543457031249984 -1.120875 -0.099212646484375 0.9543457031249984 -1.121 -0.094329833984375 0.9543457031249984 -1.121125 -0.08941650390625 0.9543457031249984 -1.12125 -0.08941650390625 0.9543457031249984 -1.121375 -0.084503173828125 0.9543457031249984 -1.1215 -0.084503173828125 0.9543457031249984 -1.121625 -0.07958984375 0.9543457031249984 -1.12175 -0.07464599609375 0.9543457031249984 -1.121875 -0.07464599609375 0.9543457031249984 -1.122 -0.0697021484375 0.9543457031249984 -1.122125 -0.0697021484375 0.9543457031249984 -1.12225 -0.06475830078125 0.9543457031249984 -1.122375 -0.059814453125 0.9543457031249984 -1.1225 -0.059814453125 0.9543457031249984 -1.122625 -0.054840087890625 0.9543457031249984 -1.12275 -0.054840087890625 0.9543457031249984 -1.122875 -0.049896240234375 0.9543457031249984 -1.123 -0.044921875 0.9543457031249984 -1.123125 -0.044921875 0.9543457031249984 -1.12325 -0.0399169921875 0.9543457031249984 -1.123375 -0.0399169921875 0.9543457031249984 -1.1235 -0.034942626953125 0.9543457031249984 -1.123625 -0.02996826171875 0.9543457031249984 -1.12375 -0.02996826171875 0.9543457031249984 -1.123875 -0.02496337890625 0.9543457031249984 -1.124 -0.02496337890625 0.9543457031249984 -1.124125 -0.019989013671875 0.9543457031249984 -1.12425 -0.014984130859375 0.9543457031249984 -1.124375 -0.014984130859375 0.9543457031249984 -1.1245 -0.010009765625 0.9543457031249984 -1.124625 -0.010009765625 0.9543457031249984 -1.12475 -0.0050048828125 0.9543457031249984 +1.062625 -0.0047607421875 0.9150244140625022 +1.06275 -0.0047607421875 0.9150244140625022 +1.062875 -0.009552001953125 0.9150244140625022 +1.063 -0.01434326171875 0.9150244140625022 +1.063125 -0.01434326171875 0.9150244140625022 +1.06325 -0.019134521484375 0.9150244140625022 +1.063375 -0.019134521484375 0.9150244140625022 +1.0635 -0.02392578125 0.9150244140625022 +1.063625 -0.028717041015625 0.9150244140625022 +1.06375 -0.028717041015625 0.9150244140625022 +1.063875 -0.033477783203125 0.9150244140625022 +1.064 -0.033477783203125 0.9150244140625022 +1.064125 -0.03826904296875 0.9150244140625022 +1.06425 -0.04302978515625 0.9150244140625022 +1.064375 -0.04302978515625 0.9150244140625022 +1.0645 -0.04779052734375 0.9150244140625022 +1.064625 -0.04779052734375 0.9150244140625022 +1.06475 -0.05255126953125 0.9150244140625022 +1.064875 -0.05731201171875 0.9150244140625022 +1.065 -0.05731201171875 0.9150244140625022 +1.065125 -0.06207275390625 0.9150244140625022 +1.06525 -0.06207275390625 0.9150244140625022 +1.065375 -0.066802978515625 0.9150244140625022 +1.0655 -0.071533203125 0.9150244140625022 +1.065625 -0.071533203125 0.9150244140625022 +1.06575 -0.076263427734375 0.9150244140625022 +1.065875 -0.076263427734375 0.9150244140625022 +1.066 -0.08099365234375 0.9150244140625022 +1.066125 -0.085693359375 0.9150244140625022 +1.06625 -0.085693359375 0.9150244140625022 +1.066375 -0.09039306640625 0.9150244140625022 +1.0665 -0.09039306640625 0.9150244140625022 +1.066625 -0.0950927734375 0.9150244140625022 +1.06675 -0.099761962890625 0.9150244140625022 +1.066875 -0.099761962890625 0.9150244140625022 +1.067 -0.104461669921875 0.9150244140625022 +1.067125 -0.104461669921875 0.9150244140625022 +1.06725 -0.109100341796875 0.9150244140625022 +1.067375 -0.113739013671875 0.9150244140625022 +1.0675 -0.113739013671875 0.9150244140625022 +1.067625 -0.118377685546875 0.9150244140625022 +1.06775 -0.118377685546875 0.9150244140625022 +1.067875 -0.123016357421875 0.9150244140625022 +1.068 -0.12762451171875 0.9150244140625022 +1.068125 -0.12762451171875 0.9150244140625022 +1.06825 -0.1322021484375 0.9150244140625022 +1.068375 -0.1322021484375 0.9150244140625022 +1.0685 -0.13677978515625 0.9150244140625022 +1.068625 -0.141357421875 0.9150244140625022 +1.06875 -0.141357421875 0.9150244140625022 +1.068875 -0.145904541015625 0.9150244140625022 +1.069 -0.145904541015625 0.9150244140625022 +1.069125 -0.150421142578125 0.9150244140625022 +1.06925 -0.154937744140625 0.9150244140625022 +1.069375 -0.154937744140625 0.9150244140625022 +1.0695 -0.159454345703125 0.9150244140625022 +1.069625 -0.159454345703125 0.9150244140625022 +1.06975 -0.1639404296875 0.9150244140625022 +1.069875 -0.16839599609375 0.9150244140625022 +1.07 -0.16839599609375 0.9150244140625022 +1.070125 -0.172821044921875 0.9150244140625022 +1.07025 -0.172821044921875 0.9150244140625022 +1.070375 -0.17724609375 0.9150244140625022 +1.0705 -0.181671142578125 0.9150244140625022 +1.070625 -0.181671142578125 0.9150244140625022 +1.07075 -0.186065673828125 0.9150244140625022 +1.070875 -0.186065673828125 0.9150244140625022 +1.071 -0.1904296875 0.9150244140625022 +1.071125 -0.19476318359375 0.9150244140625022 +1.07125 -0.19476318359375 0.9150244140625022 +1.071375 -0.1990966796875 0.9150244140625022 +1.0715 -0.1990966796875 0.9150244140625022 +1.071625 -0.203399658203125 0.9150244140625022 +1.07175 -0.207672119140625 0.9150244140625022 +1.071875 -0.207672119140625 0.9150244140625022 +1.072 -0.2119140625 0.9150244140625022 +1.072125 -0.2119140625 0.9150244140625022 +1.07225 -0.216156005859375 0.9150244140625022 +1.072375 -0.220367431640625 0.9150244140625022 +1.0725 -0.220367431640625 0.9150244140625022 +1.072625 -0.22454833984375 0.9150244140625022 +1.07275 -0.22454833984375 0.9150244140625022 +1.072875 -0.228729248046875 0.9150244140625022 +1.073 -0.23284912109375 0.9150244140625022 +1.073125 -0.23284912109375 0.9150244140625022 +1.07325 -0.236968994140625 0.9150244140625022 +1.073375 -0.236968994140625 0.9150244140625022 +1.0735 -0.241058349609375 0.9150244140625022 +1.073625 -0.2451171875 0.9150244140625022 +1.07375 -0.2451171875 0.9150244140625022 +1.073875 -0.2491455078125 0.9150244140625022 +1.074 -0.2491455078125 0.9150244140625022 +1.074125 -0.253143310546875 0.9150244140625022 +1.07425 -0.257110595703125 0.9150244140625022 +1.074375 -0.257110595703125 0.9150244140625022 +1.0745 -0.261077880859375 0.9150244140625022 +1.074625 -0.261077880859375 0.9150244140625022 +1.07475 -0.264984130859375 0.9150244140625022 +1.074875 -0.268890380859375 0.9150244140625022 +1.075 -0.268890380859375 0.9150244140625022 +1.075125 -0.272735595703125 0.9150244140625022 +1.07525 -0.272735595703125 0.9150244140625022 +1.075375 -0.276580810546875 0.9150244140625022 +1.0755 -0.2803955078125 0.9150244140625022 +1.075625 -0.2803955078125 0.9150244140625022 +1.07575 -0.284149169921875 0.9150244140625022 +1.075875 -0.284149169921875 0.9150244140625022 +1.076 -0.287872314453125 0.9150244140625022 +1.076125 -0.291595458984375 0.9150244140625022 +1.07625 -0.291595458984375 0.9150244140625022 +1.076375 -0.295257568359375 0.9150244140625022 +1.0765 -0.295257568359375 0.9150244140625022 +1.076625 -0.298919677734375 0.9150244140625022 +1.07675 -0.302520751953125 0.9150244140625022 +1.076875 -0.302520751953125 0.9150244140625022 +1.077 -0.30609130859375 0.9150244140625022 +1.077125 -0.30609130859375 0.9150244140625022 +1.07725 -0.30963134765625 0.9150244140625022 +1.077375 -0.313140869140625 0.9150244140625022 +1.0775 -0.313140869140625 0.9150244140625022 +1.077625 -0.316619873046875 0.9150244140625022 +1.07775 -0.316619873046875 0.9150244140625022 +1.077875 -0.320068359375 0.9150244140625022 +1.078 -0.323455810546875 0.9150244140625022 +1.078125 -0.323455810546875 0.9150244140625022 +1.07825 -0.32684326171875 0.9150244140625022 +1.078375 -0.32684326171875 0.9150244140625022 +1.0785 -0.330169677734375 0.9150244140625022 +1.078625 -0.333465576171875 0.9150244140625022 +1.07875 -0.333465576171875 0.9150244140625022 +1.078875 -0.33673095703125 0.9150244140625022 +1.079 -0.33673095703125 0.9150244140625022 +1.079125 -0.3399658203125 0.9150244140625022 +1.07925 -0.3431396484375 0.9150244140625022 +1.079375 -0.3431396484375 0.9150244140625022 +1.0795 -0.346282958984375 0.9150244140625022 +1.079625 -0.346282958984375 0.9150244140625022 +1.07975 -0.349395751953125 0.9150244140625022 +1.079875 -0.35247802734375 0.9150244140625022 +1.08 -0.35247802734375 0.9150244140625022 +1.080125 -0.355499267578125 0.9150244140625022 +1.08025 -0.355499267578125 0.9150244140625022 +1.080375 -0.3585205078125 0.9150244140625022 +1.0805 -0.361480712890625 0.9150244140625022 +1.080625 -0.361480712890625 0.9150244140625022 +1.08075 -0.3643798828125 0.9150244140625022 +1.080875 -0.3643798828125 0.9150244140625022 +1.081 -0.36724853515625 0.9150244140625022 +1.081125 -0.370086669921875 0.9150244140625022 +1.08125 -0.370086669921875 0.9150244140625022 +1.081375 -0.372894287109375 0.9150244140625022 +1.0815 -0.372894287109375 0.9150244140625022 +1.081625 -0.375640869140625 0.9150244140625022 +1.08175 -0.37835693359375 0.9150244140625022 +1.081875 -0.37835693359375 0.9150244140625022 +1.082 -0.38104248046875 0.9150244140625022 +1.082125 -0.38104248046875 0.9150244140625022 +1.08225 -0.3836669921875 0.9150244140625022 +1.082375 -0.386260986328125 0.9150244140625022 +1.0825 -0.386260986328125 0.9150244140625022 +1.082625 -0.3887939453125 0.9150244140625022 +1.08275 -0.3887939453125 0.9150244140625022 +1.082875 -0.39129638671875 0.9150244140625022 +1.083 -0.39373779296875 0.9150244140625022 +1.083125 -0.39373779296875 0.9150244140625022 +1.08325 -0.39617919921875 0.9150244140625022 +1.083375 -0.39617919921875 0.9150244140625022 +1.0835 -0.3985595703125 0.9150244140625022 +1.083625 -0.40087890625 0.9150244140625022 +1.08375 -0.40087890625 0.9150244140625022 +1.083875 -0.403167724609375 0.9150244140625022 +1.084 -0.403167724609375 0.9150244140625022 +1.084125 -0.405426025390625 0.9150244140625022 +1.08425 -0.4075927734375 0.9150244140625022 +1.084375 -0.4075927734375 0.9150244140625022 +1.0845 -0.409759521484375 0.9150244140625022 +1.084625 -0.409759521484375 0.9150244140625022 +1.08475 -0.411865234375 0.9150244140625022 +1.084875 -0.4139404296875 0.9150244140625022 +1.085 -0.4139404296875 0.9150244140625022 +1.085125 -0.415924072265625 0.9150244140625022 +1.08525 -0.415924072265625 0.9150244140625022 +1.085375 -0.41790771484375 0.9150244140625022 +1.0855 -0.41986083984375 0.9150244140625022 +1.085625 -0.41986083984375 0.9150244140625022 +1.08575 -0.421722412109375 0.9150244140625022 +1.085875 -0.421722412109375 0.9150244140625022 +1.086 -0.423553466796875 0.9150244140625022 +1.086125 -0.425323486328125 0.9150244140625022 +1.08625 -0.425323486328125 0.9150244140625022 +1.086375 -0.427093505859375 0.9150244140625022 +1.0865 -0.427093505859375 0.9150244140625022 +1.086625 -0.42877197265625 0.9150244140625022 +1.08675 -0.430419921875 0.9150244140625022 +1.086875 -0.430419921875 0.9150244140625022 +1.087 -0.432037353515625 0.9150244140625022 +1.087125 -0.432037353515625 0.9150244140625022 +1.08725 -0.433563232421875 0.9150244140625022 +1.087375 -0.435089111328125 0.9150244140625022 +1.0875 -0.435089111328125 0.9150244140625022 +1.087625 -0.4365234375 0.9150244140625022 +1.08775 -0.4365234375 0.9150244140625022 +1.087875 -0.43792724609375 0.9150244140625022 +1.088 -0.47930908203125 0.9983886718750004 +1.088125 -0.47930908203125 0.9983886718750004 +1.08825 -0.480743408203125 0.9983886718750004 +1.088375 -0.480743408203125 0.9983886718750004 +1.0885 -0.48211669921875 0.9983886718750004 +1.088625 -0.48345947265625 0.9983886718750004 +1.08875 -0.48345947265625 0.9983886718750004 +1.088875 -0.4847412109375 0.9983886718750004 +1.089 -0.4847412109375 0.9983886718750004 +1.089125 -0.4859619140625 0.9983886718750004 +1.08925 -0.48712158203125 0.9983886718750004 +1.089375 -0.48712158203125 0.9983886718750004 +1.0895 -0.48822021484375 0.9983886718750004 +1.089625 -0.48822021484375 0.9983886718750004 +1.08975 -0.489288330078125 0.9983886718750004 +1.089875 -0.49029541015625 0.9983886718750004 +1.09 -0.49029541015625 0.9983886718750004 +1.090125 -0.491241455078125 0.9983886718750004 +1.09025 -0.491241455078125 0.9983886718750004 +1.090375 -0.492156982421875 0.9983886718750004 +1.0905 -0.49298095703125 0.9983886718750004 +1.090625 -0.49298095703125 0.9983886718750004 +1.09075 -0.4937744140625 0.9983886718750004 +1.090875 -0.4937744140625 0.9983886718750004 +1.091 -0.4945068359375 0.9983886718750004 +1.091125 -0.495208740234375 0.9983886718750004 +1.09125 -0.495208740234375 0.9983886718750004 +1.091375 -0.495819091796875 0.9983886718750004 +1.0915 -0.495819091796875 0.9983886718750004 +1.091625 -0.49639892578125 0.9983886718750004 +1.09175 -0.496917724609375 0.9983886718750004 +1.091875 -0.496917724609375 0.9983886718750004 +1.092 -0.497406005859375 0.9983886718750004 +1.092125 -0.497406005859375 0.9983886718750004 +1.09225 -0.497802734375 0.9983886718750004 +1.092375 -0.4981689453125 0.9983886718750004 +1.0925 -0.4981689453125 0.9983886718750004 +1.092625 -0.49847412109375 0.9983886718750004 +1.09275 -0.49847412109375 0.9983886718750004 +1.092875 -0.49871826171875 0.9983886718750004 +1.093 -0.4989013671875 0.9983886718750004 +1.093125 -0.4989013671875 0.9983886718750004 +1.09325 -0.4990234375 0.9983886718750004 +1.093375 -0.4990234375 0.9983886718750004 +1.0935 -0.499114990234375 0.9983886718750004 +1.093625 -0.4991455078125 0.9983886718750004 +1.09375 -0.4991455078125 0.9983886718750004 +1.093875 -0.499114990234375 0.9983886718750004 +1.094 -0.499114990234375 0.9983886718750004 +1.094125 -0.4990234375 0.9983886718750004 +1.09425 -0.4989013671875 0.9983886718750004 +1.094375 -0.4989013671875 0.9983886718750004 +1.0945 -0.49871826171875 0.9983886718750004 +1.094625 -0.49871826171875 0.9983886718750004 +1.09475 -0.49847412109375 0.9983886718750004 +1.094875 -0.4981689453125 0.9983886718750004 +1.095 -0.4981689453125 0.9983886718750004 +1.095125 -0.497802734375 0.9983886718750004 +1.09525 -0.497802734375 0.9983886718750004 +1.095375 -0.497406005859375 0.9983886718750004 +1.0955 -0.496917724609375 0.9983886718750004 +1.095625 -0.496917724609375 0.9983886718750004 +1.09575 -0.49639892578125 0.9983886718750004 +1.095875 -0.49639892578125 0.9983886718750004 +1.096 -0.495819091796875 0.9983886718750004 +1.096125 -0.495208740234375 0.9983886718750004 +1.09625 -0.495208740234375 0.9983886718750004 +1.096375 -0.4945068359375 0.9983886718750004 +1.0965 -0.4945068359375 0.9983886718750004 +1.096625 -0.4937744140625 0.9983886718750004 +1.09675 -0.49298095703125 0.9983886718750004 +1.096875 -0.49298095703125 0.9983886718750004 +1.097 -0.492156982421875 0.9983886718750004 +1.097125 -0.492156982421875 0.9983886718750004 +1.09725 -0.491241455078125 0.9983886718750004 +1.097375 -0.49029541015625 0.9983886718750004 +1.0975 -0.49029541015625 0.9983886718750004 +1.097625 -0.489288330078125 0.9983886718750004 +1.09775 -0.489288330078125 0.9983886718750004 +1.097875 -0.48822021484375 0.9983886718750004 +1.098 -0.48712158203125 0.9983886718750004 +1.098125 -0.48712158203125 0.9983886718750004 +1.09825 -0.4859619140625 0.9983886718750004 +1.098375 -0.4859619140625 0.9983886718750004 +1.0985 -0.4847412109375 0.9983886718750004 +1.098625 -0.48345947265625 0.9983886718750004 +1.09875 -0.48345947265625 0.9983886718750004 +1.098875 -0.48211669921875 0.9983886718750004 +1.099 -0.48211669921875 0.9983886718750004 +1.099125 -0.480743408203125 0.9983886718750004 +1.09925 -0.47930908203125 0.9983886718750004 +1.099375 -0.47930908203125 0.9983886718750004 +1.0995 -0.47784423828125 0.9983886718750004 +1.099625 -0.47784423828125 0.9983886718750004 +1.09975 -0.476287841796875 0.9983886718750004 +1.099875 -0.474700927734375 0.9983886718750004 +1.1 -0.474700927734375 0.9983886718750004 +1.100125 -0.473052978515625 0.9983886718750004 +1.10025 -0.473052978515625 0.9983886718750004 +1.100375 -0.47137451171875 0.9983886718750004 +1.1005 -0.469635009765625 0.9983886718750004 +1.100625 -0.469635009765625 0.9983886718750004 +1.10075 -0.46783447265625 0.9983886718750004 +1.100875 -0.46783447265625 0.9983886718750004 +1.101 -0.465972900390625 0.9983886718750004 +1.101125 -0.464080810546875 0.9983886718750004 +1.10125 -0.464080810546875 0.9983886718750004 +1.101375 -0.462158203125 0.9983886718750004 +1.1015 -0.462158203125 0.9983886718750004 +1.101625 -0.46014404296875 0.9983886718750004 +1.10175 -0.458099365234375 0.9983886718750004 +1.101875 -0.458099365234375 0.9983886718750004 +1.102 -0.45599365234375 0.9983886718750004 +1.102125 -0.45599365234375 0.9983886718750004 +1.10225 -0.453826904296875 0.9983886718750004 +1.102375 -0.451629638671875 0.9983886718750004 +1.1025 -0.451629638671875 0.9983886718750004 +1.102625 -0.449371337890625 0.9983886718750004 +1.10275 -0.449371337890625 0.9983886718750004 +1.102875 -0.44708251953125 0.9983886718750004 +1.103 -0.444732666015625 0.9983886718750004 +1.103125 -0.444732666015625 0.9983886718750004 +1.10325 -0.442352294921875 0.9983886718750004 +1.103375 -0.442352294921875 0.9983886718750004 +1.1035 -0.43988037109375 0.9983886718750004 +1.103625 -0.4373779296875 0.9983886718750004 +1.10375 -0.4373779296875 0.9983886718750004 +1.103875 -0.434844970703125 0.9983886718750004 +1.104 -0.434844970703125 0.9983886718750004 +1.104125 -0.432281494140625 0.9983886718750004 +1.10425 -0.42962646484375 0.9983886718750004 +1.104375 -0.42962646484375 0.9983886718750004 +1.1045 -0.42694091796875 0.9983886718750004 +1.104625 -0.42694091796875 0.9983886718750004 +1.10475 -0.424224853515625 0.9983886718750004 +1.104875 -0.42144775390625 0.9983886718750004 +1.105 -0.42144775390625 0.9983886718750004 +1.105125 -0.418609619140625 0.9983886718750004 +1.10525 -0.418609619140625 0.9983886718750004 +1.105375 -0.415740966796875 0.9983886718750004 +1.1055 -0.412811279296875 0.9983886718750004 +1.105625 -0.412811279296875 0.9983886718750004 +1.10575 -0.40985107421875 0.9983886718750004 +1.105875 -0.40985107421875 0.9983886718750004 +1.106 -0.4068603515625 0.9983886718750004 +1.106125 -0.40380859375 0.9983886718750004 +1.10625 -0.40380859375 0.9983886718750004 +1.106375 -0.40069580078125 0.9983886718750004 +1.1065 -0.40069580078125 0.9983886718750004 +1.106625 -0.397552490234375 0.9983886718750004 +1.10675 -0.3944091796875 0.9983886718750004 +1.106875 -0.3944091796875 0.9983886718750004 +1.107 -0.39117431640625 0.9983886718750004 +1.107125 -0.39117431640625 0.9983886718750004 +1.10725 -0.387908935546875 0.9983886718750004 +1.107375 -0.38458251953125 0.9983886718750004 +1.1075 -0.38458251953125 0.9983886718750004 +1.107625 -0.3812255859375 0.9983886718750004 +1.10775 -0.3812255859375 0.9983886718750004 +1.107875 -0.377838134765625 0.9983886718750004 +1.108 -0.3743896484375 0.9983886718750004 +1.108125 -0.3743896484375 0.9983886718750004 +1.10825 -0.37091064453125 0.9983886718750004 +1.108375 -0.37091064453125 0.9983886718750004 +1.1085 -0.367401123046875 0.9983886718750004 +1.108625 -0.363861083984375 0.9983886718750004 +1.10875 -0.363861083984375 0.9983886718750004 +1.108875 -0.360260009765625 0.9983886718750004 +1.109 -0.360260009765625 0.9983886718750004 +1.109125 -0.35662841796875 0.9983886718750004 +1.10925 -0.352935791015625 0.9983886718750004 +1.109375 -0.352935791015625 0.9983886718750004 +1.1095 -0.349212646484375 0.9983886718750004 +1.109625 -0.349212646484375 0.9983886718750004 +1.10975 -0.345458984375 0.9983886718750004 +1.109875 -0.3416748046875 0.9983886718750004 +1.11 -0.3416748046875 0.9983886718750004 +1.110125 -0.337860107421875 0.9983886718750004 +1.11025 -0.337860107421875 0.9983886718750004 +1.110375 -0.333984375 0.9983886718750004 +1.1105 -0.330078125 0.9983886718750004 +1.110625 -0.330078125 0.9983886718750004 +1.11075 -0.326141357421875 0.9983886718750004 +1.110875 -0.326141357421875 0.9983886718750004 +1.111 -0.322174072265625 0.9983886718750004 +1.111125 -0.318145751953125 0.9983886718750004 +1.11125 -0.318145751953125 0.9983886718750004 +1.111375 -0.314117431640625 0.9983886718750004 +1.1115 -0.314117431640625 0.9983886718750004 +1.111625 -0.310028076171875 0.9983886718750004 +1.11175 -0.305908203125 0.9983886718750004 +1.111875 -0.305908203125 0.9983886718750004 +1.112 -0.3017578125 0.9983886718750004 +1.112125 -0.3017578125 0.9983886718750004 +1.11225 -0.297576904296875 0.9983886718750004 +1.112375 -0.293365478515625 0.9983886718750004 +1.1125 -0.293365478515625 0.9983886718750004 +1.112625 -0.28912353515625 0.9983886718750004 +1.11275 -0.28912353515625 0.9983886718750004 +1.112875 -0.28485107421875 0.9983886718750004 +1.113 -0.280548095703125 0.9983886718750004 +1.113125 -0.280548095703125 0.9983886718750004 +1.11325 -0.276214599609375 0.9983886718750004 +1.113375 -0.276214599609375 0.9983886718750004 +1.1135 -0.2718505859375 0.9983886718750004 +1.113625 -0.2674560546875 0.9983886718750004 +1.11375 -0.2674560546875 0.9983886718750004 +1.113875 -0.26300048828125 0.9983886718750004 +1.114 -0.26300048828125 0.9983886718750004 +1.114125 -0.258575439453125 0.9983886718750004 +1.11425 -0.254058837890625 0.9983886718750004 +1.114375 -0.254058837890625 0.9983886718750004 +1.1145 -0.24957275390625 0.9983886718750004 +1.114625 -0.24957275390625 0.9983886718750004 +1.11475 -0.245025634765625 0.9983886718750004 +1.114875 -0.240447998046875 0.9983886718750004 +1.115 -0.240447998046875 0.9983886718750004 +1.115125 -0.235870361328125 0.9983886718750004 +1.11525 -0.235870361328125 0.9983886718750004 +1.115375 -0.231231689453125 0.9983886718750004 +1.1155 -0.226593017578125 0.9983886718750004 +1.115625 -0.226593017578125 0.9983886718750004 +1.11575 -0.221923828125 0.9983886718750004 +1.115875 -0.221923828125 0.9983886718750004 +1.116 -0.21722412109375 0.9983886718750004 +1.116125 -0.2125244140625 0.9983886718750004 +1.11625 -0.2125244140625 0.9983886718750004 +1.116375 -0.207763671875 0.9983886718750004 +1.1165 -0.207763671875 0.9983886718750004 +1.116625 -0.2030029296875 0.9983886718750004 +1.11675 -0.198211669921875 0.9983886718750004 +1.116875 -0.198211669921875 0.9983886718750004 +1.117 -0.19342041015625 0.9983886718750004 +1.117125 -0.19342041015625 0.9983886718750004 +1.11725 -0.188568115234375 0.9983886718750004 +1.117375 -0.183746337890625 0.9983886718750004 +1.1175 -0.183746337890625 0.9983886718750004 +1.117625 -0.178863525390625 0.9983886718750004 +1.11775 -0.178863525390625 0.9983886718750004 +1.117875 -0.173980712890625 0.9983886718750004 +1.118 -0.1690673828125 0.9983886718750004 +1.118125 -0.1690673828125 0.9983886718750004 +1.11825 -0.16412353515625 0.9983886718750004 +1.118375 -0.16412353515625 0.9983886718750004 +1.1185 -0.1591796875 0.9983886718750004 +1.118625 -0.15423583984375 0.9983886718750004 +1.11875 -0.15423583984375 0.9983886718750004 +1.118875 -0.14923095703125 0.9983886718750004 +1.119 -0.14923095703125 0.9983886718750004 +1.119125 -0.144256591796875 0.9983886718750004 +1.11925 -0.13922119140625 0.9983886718750004 +1.119375 -0.13922119140625 0.9983886718750004 +1.1195 -0.13421630859375 0.9983886718750004 +1.119625 -0.13421630859375 0.9983886718750004 +1.11975 -0.129180908203125 0.9983886718750004 +1.119875 -0.124114990234375 0.9983886718750004 +1.12 -0.118621826171875 0.9543457031249984 +1.120125 -0.113800048828125 0.9543457031249984 +1.12025 -0.113800048828125 0.9543457031249984 +1.120375 -0.10894775390625 0.9543457031249984 +1.1205 -0.10406494140625 0.9543457031249984 +1.120625 -0.10406494140625 0.9543457031249984 +1.12075 -0.09918212890625 0.9543457031249984 +1.120875 -0.09918212890625 0.9543457031249984 +1.121 -0.09429931640625 0.9543457031249984 +1.121125 -0.089385986328125 0.9543457031249984 +1.12125 -0.089385986328125 0.9543457031249984 +1.121375 -0.08447265625 0.9543457031249984 +1.1215 -0.08447265625 0.9543457031249984 +1.121625 -0.079559326171875 0.9543457031249984 +1.12175 -0.074615478515625 0.9543457031249984 +1.121875 -0.074615478515625 0.9543457031249984 +1.122 -0.069671630859375 0.9543457031249984 +1.122125 -0.069671630859375 0.9543457031249984 +1.12225 -0.064727783203125 0.9543457031249984 +1.122375 -0.059783935546875 0.9543457031249984 +1.1225 -0.059783935546875 0.9543457031249984 +1.122625 -0.0548095703125 0.9543457031249984 +1.12275 -0.0548095703125 0.9543457031249984 +1.122875 -0.04986572265625 0.9543457031249984 +1.123 -0.044891357421875 0.9543457031249984 +1.123125 -0.044891357421875 0.9543457031249984 +1.12325 -0.039886474609375 0.9543457031249984 +1.123375 -0.039886474609375 0.9543457031249984 +1.1235 -0.034912109375 0.9543457031249984 +1.123625 -0.029937744140625 0.9543457031249984 +1.12375 -0.029937744140625 0.9543457031249984 +1.123875 -0.024932861328125 0.9543457031249984 +1.124 -0.024932861328125 0.9543457031249984 +1.124125 -0.01995849609375 0.9543457031249984 +1.12425 -0.01495361328125 0.9543457031249984 +1.124375 -0.01495361328125 0.9543457031249984 +1.1245 -0.009979248046875 0.9543457031249984 +1.124625 -0.009979248046875 0.9543457031249984 +1.12475 -0.004974365234375 0.9543457031249984 1.124875 0.0 0.9543457031249984 1.125 0.0 0.9543457031249984 1.125125 0.004974365234375 0.9543457031249984 @@ -9499,489 +9499,489 @@ 1.18725 0.002777099609375 0.5314794921874958 1.187375 0.0 0.5314794921874958 1.1875 0.0 0.5314794921874958 -1.187625 -0.0028076171875 0.5314794921874958 -1.18775 -0.0028076171875 0.5314794921874958 -1.187875 -0.005584716796875 0.5314794921874958 -1.188 -0.00836181640625 0.5314794921874958 -1.188125 -0.00836181640625 0.5314794921874958 -1.18825 -0.011138916015625 0.5314794921874958 -1.188375 -0.011138916015625 0.5314794921874958 -1.1885 -0.013916015625 0.5314794921874958 -1.188625 -0.016693115234375 0.5314794921874958 -1.18875 -0.016693115234375 0.5314794921874958 -1.188875 -0.01947021484375 0.5314794921874958 -1.189 -0.01947021484375 0.5314794921874958 -1.189125 -0.022247314453125 0.5314794921874958 -1.18925 -0.0250244140625 0.5314794921874958 -1.189375 -0.0250244140625 0.5314794921874958 -1.1895 -0.027801513671875 0.5314794921874958 -1.189625 -0.027801513671875 0.5314794921874958 -1.18975 -0.030548095703125 0.5314794921874958 -1.189875 -0.0333251953125 0.5314794921874958 -1.19 -0.0333251953125 0.5314794921874958 -1.190125 -0.03607177734375 0.5314794921874958 -1.19025 -0.03607177734375 0.5314794921874958 -1.190375 -0.038818359375 0.5314794921874958 -1.1905 -0.04156494140625 0.5314794921874958 -1.190625 -0.04156494140625 0.5314794921874958 -1.19075 -0.0443115234375 0.5314794921874958 -1.190875 -0.0443115234375 0.5314794921874958 -1.191 -0.04705810546875 0.5314794921874958 -1.191125 -0.0498046875 0.5314794921874958 -1.19125 -0.0498046875 0.5314794921874958 -1.191375 -0.052520751953125 0.5314794921874958 -1.1915 -0.052520751953125 0.5314794921874958 -1.191625 -0.055267333984375 0.5314794921874958 -1.19175 -0.0579833984375 0.5314794921874958 -1.191875 -0.0579833984375 0.5314794921874958 -1.192 -0.060699462890625 0.5314794921874958 -1.192125 -0.060699462890625 0.5314794921874958 -1.19225 -0.063385009765625 0.5314794921874958 -1.192375 -0.06610107421875 0.5314794921874958 -1.1925 -0.06610107421875 0.5314794921874958 -1.192625 -0.06878662109375 0.5314794921874958 -1.19275 -0.06878662109375 0.5314794921874958 -1.192875 -0.07147216796875 0.5314794921874958 -1.193 -0.07415771484375 0.5314794921874958 -1.193125 -0.07415771484375 0.5314794921874958 -1.19325 -0.076812744140625 0.5314794921874958 -1.193375 -0.076812744140625 0.5314794921874958 -1.1935 -0.0794677734375 0.5314794921874958 -1.193625 -0.082122802734375 0.5314794921874958 -1.19375 -0.082122802734375 0.5314794921874958 -1.193875 -0.08477783203125 0.5314794921874958 -1.194 -0.08477783203125 0.5314794921874958 -1.194125 -0.08740234375 0.5314794921874958 -1.19425 -0.09002685546875 0.5314794921874958 -1.194375 -0.09002685546875 0.5314794921874958 -1.1945 -0.092620849609375 0.5314794921874958 -1.194625 -0.092620849609375 0.5314794921874958 -1.19475 -0.095245361328125 0.5314794921874958 -1.194875 -0.09783935546875 0.5314794921874958 -1.195 -0.09783935546875 0.5314794921874958 -1.195125 -0.10040283203125 0.5314794921874958 -1.19525 -0.10040283203125 0.5314794921874958 -1.195375 -0.10296630859375 0.5314794921874958 -1.1955 -0.10552978515625 0.5314794921874958 -1.195625 -0.10552978515625 0.5314794921874958 -1.19575 -0.10809326171875 0.5314794921874958 -1.195875 -0.10809326171875 0.5314794921874958 -1.196 -0.110626220703125 0.5314794921874958 -1.196125 -0.1131591796875 0.5314794921874958 -1.19625 -0.1131591796875 0.5314794921874958 -1.196375 -0.11566162109375 0.5314794921874958 -1.1965 -0.11566162109375 0.5314794921874958 -1.196625 -0.1181640625 0.5314794921874958 -1.19675 -0.120635986328125 0.5314794921874958 -1.196875 -0.120635986328125 0.5314794921874958 -1.197 -0.12310791015625 0.5314794921874958 -1.197125 -0.12310791015625 0.5314794921874958 -1.19725 -0.125579833984375 0.5314794921874958 -1.197375 -0.128021240234375 0.5314794921874958 -1.1975 -0.128021240234375 0.5314794921874958 -1.197625 -0.130462646484375 0.5314794921874958 -1.19775 -0.130462646484375 0.5314794921874958 -1.197875 -0.13287353515625 0.5314794921874958 -1.198 -0.135284423828125 0.5314794921874958 -1.198125 -0.135284423828125 0.5314794921874958 -1.19825 -0.137664794921875 0.5314794921874958 -1.198375 -0.137664794921875 0.5314794921874958 -1.1985 -0.140045166015625 0.5314794921874958 -1.198625 -0.14239501953125 0.5314794921874958 -1.19875 -0.14239501953125 0.5314794921874958 -1.198875 -0.144744873046875 0.5314794921874958 -1.199 -0.144744873046875 0.5314794921874958 -1.199125 -0.147064208984375 0.5314794921874958 -1.19925 -0.14935302734375 0.5314794921874958 -1.199375 -0.14935302734375 0.5314794921874958 -1.1995 -0.15167236328125 0.5314794921874958 -1.199625 -0.15167236328125 0.5314794921874958 -1.19975 -0.1539306640625 0.5314794921874958 -1.199875 -0.15618896484375 0.5314794921874958 -1.2 -0.15618896484375 0.5314794921874958 -1.200125 -0.158447265625 0.5314794921874958 -1.20025 -0.158447265625 0.5314794921874958 -1.200375 -0.160675048828125 0.5314794921874958 -1.2005 -0.162872314453125 0.5314794921874958 -1.200625 -0.162872314453125 0.5314794921874958 -1.20075 -0.165069580078125 0.5314794921874958 -1.200875 -0.165069580078125 0.5314794921874958 -1.201 -0.167236328125 0.5314794921874958 -1.201125 -0.169403076171875 0.5314794921874958 -1.20125 -0.169403076171875 0.5314794921874958 -1.201375 -0.1715087890625 0.5314794921874958 -1.2015 -0.1715087890625 0.5314794921874958 -1.201625 -0.17364501953125 0.5314794921874958 -1.20175 -0.175750732421875 0.5314794921874958 -1.201875 -0.175750732421875 0.5314794921874958 -1.202 -0.177825927734375 0.5314794921874958 -1.202125 -0.177825927734375 0.5314794921874958 -1.20225 -0.17987060546875 0.5314794921874958 -1.202375 -0.181915283203125 0.5314794921874958 -1.2025 -0.181915283203125 0.5314794921874958 -1.202625 -0.183929443359375 0.5314794921874958 -1.20275 -0.183929443359375 0.5314794921874958 -1.202875 -0.1859130859375 0.5314794921874958 -1.203 -0.187896728515625 0.5314794921874958 -1.203125 -0.187896728515625 0.5314794921874958 -1.20325 -0.18988037109375 0.5314794921874958 -1.203375 -0.18988037109375 0.5314794921874958 -1.2035 -0.191802978515625 0.5314794921874958 -1.203625 -0.1937255859375 0.5314794921874958 -1.20375 -0.1937255859375 0.5314794921874958 -1.203875 -0.19561767578125 0.5314794921874958 -1.204 -0.19561767578125 0.5314794921874958 -1.204125 -0.197479248046875 0.5314794921874958 -1.20425 -0.1993408203125 0.5314794921874958 -1.204375 -0.1993408203125 0.5314794921874958 -1.2045 -0.201171875 0.5314794921874958 -1.204625 -0.201171875 0.5314794921874958 -1.20475 -0.202972412109375 0.5314794921874958 -1.204875 -0.204742431640625 0.5314794921874958 -1.205 -0.204742431640625 0.5314794921874958 -1.205125 -0.206512451171875 0.5314794921874958 -1.20525 -0.206512451171875 0.5314794921874958 -1.205375 -0.208251953125 0.5314794921874958 -1.2055 -0.209991455078125 0.5314794921874958 -1.205625 -0.209991455078125 0.5314794921874958 -1.20575 -0.211669921875 0.5314794921874958 -1.205875 -0.211669921875 0.5314794921874958 -1.206 -0.213348388671875 0.5314794921874958 -1.206125 -0.214996337890625 0.5314794921874958 -1.20625 -0.214996337890625 0.5314794921874958 -1.206375 -0.21661376953125 0.5314794921874958 -1.2065 -0.21661376953125 0.5314794921874958 -1.206625 -0.21820068359375 0.5314794921874958 -1.20675 -0.21978759765625 0.5314794921874958 -1.206875 -0.21978759765625 0.5314794921874958 -1.207 -0.221343994140625 0.5314794921874958 -1.207125 -0.221343994140625 0.5314794921874958 -1.20725 -0.222869873046875 0.5314794921874958 -1.207375 -0.224365234375 0.5314794921874958 -1.2075 -0.224365234375 0.5314794921874958 -1.207625 -0.225860595703125 0.5314794921874958 -1.20775 -0.225860595703125 0.5314794921874958 -1.207875 -0.227294921875 0.5314794921874958 -1.208 -0.228729248046875 0.5314794921874958 -1.208125 -0.228729248046875 0.5314794921874958 -1.20825 -0.230133056640625 0.5314794921874958 -1.208375 -0.230133056640625 0.5314794921874958 -1.2085 -0.23150634765625 0.5314794921874958 -1.208625 -0.23284912109375 0.5314794921874958 -1.20875 -0.23284912109375 0.5314794921874958 -1.208875 -0.23419189453125 0.5314794921874958 -1.209 -0.23419189453125 0.5314794921874958 -1.209125 -0.235504150390625 0.5314794921874958 -1.20925 -0.236785888671875 0.5314794921874958 -1.209375 -0.236785888671875 0.5314794921874958 -1.2095 -0.238006591796875 0.5314794921874958 -1.209625 -0.238006591796875 0.5314794921874958 -1.20975 -0.2392578125 0.5314794921874958 -1.209875 -0.240447998046875 0.5314794921874958 -1.21 -0.240447998046875 0.5314794921874958 -1.210125 -0.241607666015625 0.5314794921874958 -1.21025 -0.241607666015625 0.5314794921874958 -1.210375 -0.242767333984375 0.5314794921874958 -1.2105 -0.243896484375 0.5314794921874958 -1.210625 -0.243896484375 0.5314794921874958 -1.21075 -0.244964599609375 0.5314794921874958 -1.210875 -0.244964599609375 0.5314794921874958 -1.211 -0.24603271484375 0.5314794921874958 -1.211125 -0.2470703125 0.5314794921874958 -1.21125 -0.2470703125 0.5314794921874958 -1.211375 -0.248077392578125 0.5314794921874958 -1.2115 -0.248077392578125 0.5314794921874958 -1.211625 -0.249053955078125 0.5314794921874958 -1.21175 -0.250030517578125 0.5314794921874958 -1.211875 -0.250030517578125 0.5314794921874958 -1.212 -0.250946044921875 0.5314794921874958 -1.212125 -0.250946044921875 0.5314794921874958 -1.21225 -0.251861572265625 0.5314794921874958 -1.212375 -0.25274658203125 0.5314794921874958 -1.2125 -0.25274658203125 0.5314794921874958 -1.212625 -0.253570556640625 0.5314794921874958 -1.21275 -0.253570556640625 0.5314794921874958 -1.212875 -0.25439453125 0.5314794921874958 -1.213 -0.25518798828125 0.5314794921874958 -1.213125 -0.25518798828125 0.5314794921874958 -1.21325 -0.255950927734375 0.5314794921874958 -1.213375 -0.255950927734375 0.5314794921874958 -1.2135 -0.256683349609375 0.5314794921874958 -1.213625 -0.25738525390625 0.5314794921874958 -1.21375 -0.25738525390625 0.5314794921874958 -1.213875 -0.258056640625 0.5314794921874958 -1.214 -0.258056640625 0.5314794921874958 -1.214125 -0.25872802734375 0.5314794921874958 -1.21425 -0.25933837890625 0.5314794921874958 -1.214375 -0.25933837890625 0.5314794921874958 -1.2145 -0.259918212890625 0.5314794921874958 -1.214625 -0.259918212890625 0.5314794921874958 -1.21475 -0.260498046875 0.5314794921874958 -1.214875 -0.261016845703125 0.5314794921874958 -1.215 -0.261016845703125 0.5314794921874958 -1.215125 -0.26153564453125 0.5314794921874958 -1.21525 -0.26153564453125 0.5314794921874958 -1.215375 -0.26202392578125 0.5314794921874958 -1.2155 -0.262451171875 0.5314794921874958 -1.215625 -0.262451171875 0.5314794921874958 -1.21575 -0.26287841796875 0.5314794921874958 -1.215875 -0.26287841796875 0.5314794921874958 -1.216 -0.1090087890625 0.220097656249995 -1.216125 -0.109161376953125 0.220097656249995 -1.21625 -0.109161376953125 0.220097656249995 -1.216375 -0.10931396484375 0.220097656249995 -1.2165 -0.10931396484375 0.220097656249995 -1.216625 -0.10943603515625 0.220097656249995 -1.21675 -0.10955810546875 0.220097656249995 -1.216875 -0.10955810546875 0.220097656249995 -1.217 -0.109649658203125 0.220097656249995 -1.217125 -0.109649658203125 0.220097656249995 -1.21725 -0.1097412109375 0.220097656249995 -1.217375 -0.109832763671875 0.220097656249995 -1.2175 -0.109832763671875 0.220097656249995 -1.217625 -0.109893798828125 0.220097656249995 -1.21775 -0.109893798828125 0.220097656249995 -1.217875 -0.109954833984375 0.220097656249995 -1.218 -0.1099853515625 0.220097656249995 -1.218125 -0.1099853515625 0.220097656249995 -1.21825 -0.110015869140625 0.220097656249995 -1.218375 -0.110015869140625 0.220097656249995 -1.2185 -0.11004638671875 0.220097656249995 -1.218625 -0.11004638671875 0.220097656249995 -1.21875 -0.11004638671875 0.220097656249995 -1.218875 -0.11004638671875 0.220097656249995 -1.219 -0.11004638671875 0.220097656249995 -1.219125 -0.110015869140625 0.220097656249995 -1.21925 -0.1099853515625 0.220097656249995 -1.219375 -0.1099853515625 0.220097656249995 -1.2195 -0.109954833984375 0.220097656249995 -1.219625 -0.109954833984375 0.220097656249995 -1.21975 -0.109893798828125 0.220097656249995 -1.219875 -0.109832763671875 0.220097656249995 -1.22 -0.109832763671875 0.220097656249995 -1.220125 -0.1097412109375 0.220097656249995 -1.22025 -0.1097412109375 0.220097656249995 -1.220375 -0.109649658203125 0.220097656249995 -1.2205 -0.10955810546875 0.220097656249995 -1.220625 -0.10955810546875 0.220097656249995 -1.22075 -0.10943603515625 0.220097656249995 -1.220875 -0.10943603515625 0.220097656249995 -1.221 -0.10931396484375 0.220097656249995 -1.221125 -0.109161376953125 0.220097656249995 -1.22125 -0.109161376953125 0.220097656249995 -1.221375 -0.1090087890625 0.220097656249995 -1.2215 -0.1090087890625 0.220097656249995 -1.221625 -0.108856201171875 0.220097656249995 -1.22175 -0.108673095703125 0.220097656249995 -1.221875 -0.108673095703125 0.220097656249995 -1.222 -0.108489990234375 0.220097656249995 -1.222125 -0.108489990234375 0.220097656249995 -1.22225 -0.108306884765625 0.220097656249995 -1.222375 -0.10809326171875 0.220097656249995 -1.2225 -0.10809326171875 0.220097656249995 -1.222625 -0.107879638671875 0.220097656249995 -1.22275 -0.107879638671875 0.220097656249995 -1.222875 -0.107635498046875 0.220097656249995 -1.223 -0.107391357421875 0.220097656249995 -1.223125 -0.107391357421875 0.220097656249995 -1.22325 -0.107147216796875 0.220097656249995 -1.223375 -0.107147216796875 0.220097656249995 -1.2235 -0.10687255859375 0.220097656249995 -1.223625 -0.106597900390625 0.220097656249995 -1.22375 -0.106597900390625 0.220097656249995 -1.223875 -0.106292724609375 0.220097656249995 -1.224 -0.106292724609375 0.220097656249995 -1.224125 -0.105987548828125 0.220097656249995 -1.22425 -0.105682373046875 0.220097656249995 -1.224375 -0.105682373046875 0.220097656249995 -1.2245 -0.1053466796875 0.220097656249995 -1.224625 -0.1053466796875 0.220097656249995 -1.22475 -0.105010986328125 0.220097656249995 -1.224875 -0.104644775390625 0.220097656249995 -1.225 -0.104644775390625 0.220097656249995 -1.225125 -0.10430908203125 0.220097656249995 -1.22525 -0.10430908203125 0.220097656249995 -1.225375 -0.103912353515625 0.220097656249995 -1.2255 -0.103546142578125 0.220097656249995 -1.225625 -0.103546142578125 0.220097656249995 -1.22575 -0.1031494140625 0.220097656249995 -1.225875 -0.1031494140625 0.220097656249995 -1.226 -0.10272216796875 0.220097656249995 -1.226125 -0.102325439453125 0.220097656249995 -1.22625 -0.102325439453125 0.220097656249995 -1.226375 -0.101898193359375 0.220097656249995 -1.2265 -0.101898193359375 0.220097656249995 -1.226625 -0.1014404296875 0.220097656249995 -1.22675 -0.100982666015625 0.220097656249995 -1.226875 -0.100982666015625 0.220097656249995 -1.227 -0.10052490234375 0.220097656249995 -1.227125 -0.10052490234375 0.220097656249995 -1.22725 -0.100067138671875 0.220097656249995 -1.227375 -0.099578857421875 0.220097656249995 -1.2275 -0.099578857421875 0.220097656249995 -1.227625 -0.09906005859375 0.220097656249995 -1.22775 -0.09906005859375 0.220097656249995 -1.227875 -0.09857177734375 0.220097656249995 -1.228 -0.098052978515625 0.220097656249995 -1.228125 -0.098052978515625 0.220097656249995 -1.22825 -0.0975341796875 0.220097656249995 -1.228375 -0.0975341796875 0.220097656249995 -1.2285 -0.09698486328125 0.220097656249995 -1.228625 -0.096435546875 0.220097656249995 -1.22875 -0.096435546875 0.220097656249995 -1.228875 -0.09588623046875 0.220097656249995 -1.229 -0.09588623046875 0.220097656249995 -1.229125 -0.095306396484375 0.220097656249995 -1.22925 -0.0947265625 0.220097656249995 -1.229375 -0.0947265625 0.220097656249995 -1.2295 -0.0941162109375 0.220097656249995 -1.229625 -0.0941162109375 0.220097656249995 -1.22975 -0.093536376953125 0.220097656249995 -1.229875 -0.092926025390625 0.220097656249995 -1.23 -0.092926025390625 0.220097656249995 -1.230125 -0.09228515625 0.220097656249995 -1.23025 -0.09228515625 0.220097656249995 -1.230375 -0.091644287109375 0.220097656249995 -1.2305 -0.09100341796875 0.220097656249995 -1.230625 -0.09100341796875 0.220097656249995 -1.23075 -0.090362548828125 0.220097656249995 -1.230875 -0.090362548828125 0.220097656249995 -1.231 -0.089691162109375 0.220097656249995 -1.231125 -0.089019775390625 0.220097656249995 -1.23125 -0.089019775390625 0.220097656249995 -1.231375 -0.088348388671875 0.220097656249995 -1.2315 -0.088348388671875 0.220097656249995 -1.231625 -0.087646484375 0.220097656249995 -1.23175 -0.086944580078125 0.220097656249995 -1.231875 -0.086944580078125 0.220097656249995 -1.232 -0.08624267578125 0.220097656249995 -1.232125 -0.08624267578125 0.220097656249995 -1.23225 -0.08551025390625 0.220097656249995 -1.232375 -0.08477783203125 0.220097656249995 -1.2325 -0.08477783203125 0.220097656249995 -1.232625 -0.08404541015625 0.220097656249995 -1.23275 -0.08404541015625 0.220097656249995 -1.232875 -0.08331298828125 0.220097656249995 -1.233 -0.082550048828125 0.220097656249995 -1.233125 -0.082550048828125 0.220097656249995 -1.23325 -0.081787109375 0.220097656249995 -1.233375 -0.081787109375 0.220097656249995 -1.2335 -0.08099365234375 0.220097656249995 -1.233625 -0.080230712890625 0.220097656249995 -1.23375 -0.080230712890625 0.220097656249995 -1.233875 -0.079437255859375 0.220097656249995 -1.234 -0.079437255859375 0.220097656249995 -1.234125 -0.07861328125 0.220097656249995 -1.23425 -0.07781982421875 0.220097656249995 -1.234375 -0.07781982421875 0.220097656249995 -1.2345 -0.076995849609375 0.220097656249995 -1.234625 -0.076995849609375 0.220097656249995 -1.23475 -0.076171875 0.220097656249995 -1.234875 -0.0753173828125 0.220097656249995 -1.235 -0.0753173828125 0.220097656249995 -1.235125 -0.074493408203125 0.220097656249995 -1.23525 -0.074493408203125 0.220097656249995 -1.235375 -0.073638916015625 0.220097656249995 -1.2355 -0.072784423828125 0.220097656249995 -1.235625 -0.072784423828125 0.220097656249995 -1.23575 -0.0718994140625 0.220097656249995 -1.235875 -0.0718994140625 0.220097656249995 -1.236 -0.071044921875 0.220097656249995 -1.236125 -0.070159912109375 0.220097656249995 -1.23625 -0.070159912109375 0.220097656249995 -1.236375 -0.069244384765625 0.220097656249995 -1.2365 -0.069244384765625 0.220097656249995 -1.236625 -0.068359375 0.220097656249995 -1.23675 -0.06744384765625 0.220097656249995 -1.236875 -0.06744384765625 0.220097656249995 -1.237 -0.0665283203125 0.220097656249995 -1.237125 -0.0665283203125 0.220097656249995 -1.23725 -0.06561279296875 0.220097656249995 -1.237375 -0.064697265625 0.220097656249995 -1.2375 -0.064697265625 0.220097656249995 -1.237625 -0.063751220703125 0.220097656249995 -1.23775 -0.063751220703125 0.220097656249995 -1.237875 -0.06280517578125 0.220097656249995 -1.238 -0.061859130859375 0.220097656249995 -1.238125 -0.061859130859375 0.220097656249995 -1.23825 -0.0609130859375 0.220097656249995 -1.238375 -0.0609130859375 0.220097656249995 -1.2385 -0.0599365234375 0.220097656249995 -1.238625 -0.0589599609375 0.220097656249995 -1.23875 -0.0589599609375 0.220097656249995 -1.238875 -0.0579833984375 0.220097656249995 -1.239 -0.0579833984375 0.220097656249995 -1.239125 -0.0570068359375 0.220097656249995 -1.23925 -0.0560302734375 0.220097656249995 -1.239375 -0.0560302734375 0.220097656249995 -1.2395 -0.055023193359375 0.220097656249995 -1.239625 -0.055023193359375 0.220097656249995 -1.23975 -0.05401611328125 0.220097656249995 -1.239875 -0.053009033203125 0.220097656249995 -1.24 -0.053009033203125 0.220097656249995 -1.240125 -0.052001953125 0.220097656249995 -1.24025 -0.052001953125 0.220097656249995 -1.240375 -0.050994873046875 0.220097656249995 -1.2405 -0.049957275390625 0.220097656249995 -1.240625 -0.049957275390625 0.220097656249995 -1.24075 -0.0489501953125 0.220097656249995 -1.240875 -0.0489501953125 0.220097656249995 -1.241 -0.04791259765625 0.220097656249995 -1.241125 -0.046875 0.220097656249995 -1.24125 -0.046875 0.220097656249995 -1.241375 -0.045806884765625 0.220097656249995 -1.2415 -0.045806884765625 0.220097656249995 -1.241625 -0.044769287109375 0.220097656249995 -1.24175 -0.043701171875 0.220097656249995 -1.241875 -0.043701171875 0.220097656249995 -1.242 -0.04266357421875 0.220097656249995 -1.242125 -0.04266357421875 0.220097656249995 -1.24225 -0.041595458984375 0.220097656249995 -1.242375 -0.04052734375 0.220097656249995 -1.2425 -0.04052734375 0.220097656249995 -1.242625 -0.0394287109375 0.220097656249995 -1.24275 -0.0394287109375 0.220097656249995 -1.242875 -0.038360595703125 0.220097656249995 -1.243 -0.03729248046875 0.220097656249995 -1.243125 -0.03729248046875 0.220097656249995 -1.24325 -0.03619384765625 0.220097656249995 -1.243375 -0.03619384765625 0.220097656249995 -1.2435 -0.03509521484375 0.220097656249995 -1.243625 -0.034027099609375 0.220097656249995 -1.24375 -0.034027099609375 0.220097656249995 -1.243875 -0.032928466796875 0.220097656249995 -1.244 -0.032928466796875 0.220097656249995 -1.244125 -0.03179931640625 0.220097656249995 -1.24425 -0.03070068359375 0.220097656249995 -1.244375 -0.03070068359375 0.220097656249995 -1.2445 -0.02960205078125 0.220097656249995 -1.244625 -0.02960205078125 0.220097656249995 -1.24475 -0.02850341796875 0.220097656249995 -1.244875 -0.027374267578125 0.220097656249995 -1.245 -0.027374267578125 0.220097656249995 -1.245125 -0.026275634765625 0.220097656249995 -1.24525 -0.026275634765625 0.220097656249995 -1.245375 -0.025146484375 0.220097656249995 -1.2455 -0.024017333984375 0.220097656249995 -1.245625 -0.024017333984375 0.220097656249995 -1.24575 -0.02288818359375 0.220097656249995 -1.245875 -0.02288818359375 0.220097656249995 -1.246 -0.021759033203125 0.220097656249995 -1.246125 -0.0206298828125 0.220097656249995 -1.24625 -0.0206298828125 0.220097656249995 -1.246375 -0.019500732421875 0.220097656249995 -1.2465 -0.019500732421875 0.220097656249995 -1.246625 -0.01837158203125 0.220097656249995 -1.24675 -0.0172119140625 0.220097656249995 -1.246875 -0.0172119140625 0.220097656249995 -1.247 -0.016082763671875 0.220097656249995 -1.247125 -0.016082763671875 0.220097656249995 -1.24725 -0.01495361328125 0.220097656249995 -1.247375 -0.0137939453125 0.220097656249995 -1.2475 -0.0137939453125 0.220097656249995 -1.247625 -0.012664794921875 0.220097656249995 -1.24775 -0.012664794921875 0.220097656249995 -1.247875 -0.011505126953125 0.220097656249995 +1.187625 -0.002777099609375 0.5314794921874958 +1.18775 -0.002777099609375 0.5314794921874958 +1.187875 -0.00555419921875 0.5314794921874958 +1.188 -0.008331298828125 0.5314794921874958 +1.188125 -0.008331298828125 0.5314794921874958 +1.18825 -0.0111083984375 0.5314794921874958 +1.188375 -0.0111083984375 0.5314794921874958 +1.1885 -0.013885498046875 0.5314794921874958 +1.188625 -0.01666259765625 0.5314794921874958 +1.18875 -0.01666259765625 0.5314794921874958 +1.188875 -0.019439697265625 0.5314794921874958 +1.189 -0.019439697265625 0.5314794921874958 +1.189125 -0.022216796875 0.5314794921874958 +1.18925 -0.024993896484375 0.5314794921874958 +1.189375 -0.024993896484375 0.5314794921874958 +1.1895 -0.02777099609375 0.5314794921874958 +1.189625 -0.02777099609375 0.5314794921874958 +1.18975 -0.030517578125 0.5314794921874958 +1.189875 -0.033294677734375 0.5314794921874958 +1.19 -0.033294677734375 0.5314794921874958 +1.190125 -0.036041259765625 0.5314794921874958 +1.19025 -0.036041259765625 0.5314794921874958 +1.190375 -0.038787841796875 0.5314794921874958 +1.1905 -0.041534423828125 0.5314794921874958 +1.190625 -0.041534423828125 0.5314794921874958 +1.19075 -0.044281005859375 0.5314794921874958 +1.190875 -0.044281005859375 0.5314794921874958 +1.191 -0.047027587890625 0.5314794921874958 +1.191125 -0.049774169921875 0.5314794921874958 +1.19125 -0.049774169921875 0.5314794921874958 +1.191375 -0.052490234375 0.5314794921874958 +1.1915 -0.052490234375 0.5314794921874958 +1.191625 -0.05523681640625 0.5314794921874958 +1.19175 -0.057952880859375 0.5314794921874958 +1.191875 -0.057952880859375 0.5314794921874958 +1.192 -0.0606689453125 0.5314794921874958 +1.192125 -0.0606689453125 0.5314794921874958 +1.19225 -0.0633544921875 0.5314794921874958 +1.192375 -0.066070556640625 0.5314794921874958 +1.1925 -0.066070556640625 0.5314794921874958 +1.192625 -0.068756103515625 0.5314794921874958 +1.19275 -0.068756103515625 0.5314794921874958 +1.192875 -0.071441650390625 0.5314794921874958 +1.193 -0.074127197265625 0.5314794921874958 +1.193125 -0.074127197265625 0.5314794921874958 +1.19325 -0.0767822265625 0.5314794921874958 +1.193375 -0.0767822265625 0.5314794921874958 +1.1935 -0.079437255859375 0.5314794921874958 +1.193625 -0.08209228515625 0.5314794921874958 +1.19375 -0.08209228515625 0.5314794921874958 +1.193875 -0.084747314453125 0.5314794921874958 +1.194 -0.084747314453125 0.5314794921874958 +1.194125 -0.087371826171875 0.5314794921874958 +1.19425 -0.089996337890625 0.5314794921874958 +1.194375 -0.089996337890625 0.5314794921874958 +1.1945 -0.09259033203125 0.5314794921874958 +1.194625 -0.09259033203125 0.5314794921874958 +1.19475 -0.09521484375 0.5314794921874958 +1.194875 -0.097808837890625 0.5314794921874958 +1.195 -0.097808837890625 0.5314794921874958 +1.195125 -0.100372314453125 0.5314794921874958 +1.19525 -0.100372314453125 0.5314794921874958 +1.195375 -0.102935791015625 0.5314794921874958 +1.1955 -0.105499267578125 0.5314794921874958 +1.195625 -0.105499267578125 0.5314794921874958 +1.19575 -0.108062744140625 0.5314794921874958 +1.195875 -0.108062744140625 0.5314794921874958 +1.196 -0.110595703125 0.5314794921874958 +1.196125 -0.113128662109375 0.5314794921874958 +1.19625 -0.113128662109375 0.5314794921874958 +1.196375 -0.115631103515625 0.5314794921874958 +1.1965 -0.115631103515625 0.5314794921874958 +1.196625 -0.118133544921875 0.5314794921874958 +1.19675 -0.12060546875 0.5314794921874958 +1.196875 -0.12060546875 0.5314794921874958 +1.197 -0.123077392578125 0.5314794921874958 +1.197125 -0.123077392578125 0.5314794921874958 +1.19725 -0.12554931640625 0.5314794921874958 +1.197375 -0.12799072265625 0.5314794921874958 +1.1975 -0.12799072265625 0.5314794921874958 +1.197625 -0.13043212890625 0.5314794921874958 +1.19775 -0.13043212890625 0.5314794921874958 +1.197875 -0.132843017578125 0.5314794921874958 +1.198 -0.13525390625 0.5314794921874958 +1.198125 -0.13525390625 0.5314794921874958 +1.19825 -0.13763427734375 0.5314794921874958 +1.198375 -0.13763427734375 0.5314794921874958 +1.1985 -0.1400146484375 0.5314794921874958 +1.198625 -0.142364501953125 0.5314794921874958 +1.19875 -0.142364501953125 0.5314794921874958 +1.198875 -0.14471435546875 0.5314794921874958 +1.199 -0.14471435546875 0.5314794921874958 +1.199125 -0.14703369140625 0.5314794921874958 +1.19925 -0.149322509765625 0.5314794921874958 +1.199375 -0.149322509765625 0.5314794921874958 +1.1995 -0.151641845703125 0.5314794921874958 +1.199625 -0.151641845703125 0.5314794921874958 +1.19975 -0.153900146484375 0.5314794921874958 +1.199875 -0.156158447265625 0.5314794921874958 +1.2 -0.156158447265625 0.5314794921874958 +1.200125 -0.158416748046875 0.5314794921874958 +1.20025 -0.158416748046875 0.5314794921874958 +1.200375 -0.16064453125 0.5314794921874958 +1.2005 -0.162841796875 0.5314794921874958 +1.200625 -0.162841796875 0.5314794921874958 +1.20075 -0.1650390625 0.5314794921874958 +1.200875 -0.1650390625 0.5314794921874958 +1.201 -0.167205810546875 0.5314794921874958 +1.201125 -0.16937255859375 0.5314794921874958 +1.20125 -0.16937255859375 0.5314794921874958 +1.201375 -0.171478271484375 0.5314794921874958 +1.2015 -0.171478271484375 0.5314794921874958 +1.201625 -0.173614501953125 0.5314794921874958 +1.20175 -0.17572021484375 0.5314794921874958 +1.201875 -0.17572021484375 0.5314794921874958 +1.202 -0.17779541015625 0.5314794921874958 +1.202125 -0.17779541015625 0.5314794921874958 +1.20225 -0.179840087890625 0.5314794921874958 +1.202375 -0.181884765625 0.5314794921874958 +1.2025 -0.181884765625 0.5314794921874958 +1.202625 -0.18389892578125 0.5314794921874958 +1.20275 -0.18389892578125 0.5314794921874958 +1.202875 -0.185882568359375 0.5314794921874958 +1.203 -0.1878662109375 0.5314794921874958 +1.203125 -0.1878662109375 0.5314794921874958 +1.20325 -0.189849853515625 0.5314794921874958 +1.203375 -0.189849853515625 0.5314794921874958 +1.2035 -0.1917724609375 0.5314794921874958 +1.203625 -0.193695068359375 0.5314794921874958 +1.20375 -0.193695068359375 0.5314794921874958 +1.203875 -0.195587158203125 0.5314794921874958 +1.204 -0.195587158203125 0.5314794921874958 +1.204125 -0.19744873046875 0.5314794921874958 +1.20425 -0.199310302734375 0.5314794921874958 +1.204375 -0.199310302734375 0.5314794921874958 +1.2045 -0.201141357421875 0.5314794921874958 +1.204625 -0.201141357421875 0.5314794921874958 +1.20475 -0.20294189453125 0.5314794921874958 +1.204875 -0.2047119140625 0.5314794921874958 +1.205 -0.2047119140625 0.5314794921874958 +1.205125 -0.20648193359375 0.5314794921874958 +1.20525 -0.20648193359375 0.5314794921874958 +1.205375 -0.208221435546875 0.5314794921874958 +1.2055 -0.2099609375 0.5314794921874958 +1.205625 -0.2099609375 0.5314794921874958 +1.20575 -0.211639404296875 0.5314794921874958 +1.205875 -0.211639404296875 0.5314794921874958 +1.206 -0.21331787109375 0.5314794921874958 +1.206125 -0.2149658203125 0.5314794921874958 +1.20625 -0.2149658203125 0.5314794921874958 +1.206375 -0.216583251953125 0.5314794921874958 +1.2065 -0.216583251953125 0.5314794921874958 +1.206625 -0.218170166015625 0.5314794921874958 +1.20675 -0.219757080078125 0.5314794921874958 +1.206875 -0.219757080078125 0.5314794921874958 +1.207 -0.2213134765625 0.5314794921874958 +1.207125 -0.2213134765625 0.5314794921874958 +1.20725 -0.22283935546875 0.5314794921874958 +1.207375 -0.224334716796875 0.5314794921874958 +1.2075 -0.224334716796875 0.5314794921874958 +1.207625 -0.225830078125 0.5314794921874958 +1.20775 -0.225830078125 0.5314794921874958 +1.207875 -0.227264404296875 0.5314794921874958 +1.208 -0.22869873046875 0.5314794921874958 +1.208125 -0.22869873046875 0.5314794921874958 +1.20825 -0.2301025390625 0.5314794921874958 +1.208375 -0.2301025390625 0.5314794921874958 +1.2085 -0.231475830078125 0.5314794921874958 +1.208625 -0.232818603515625 0.5314794921874958 +1.20875 -0.232818603515625 0.5314794921874958 +1.208875 -0.234161376953125 0.5314794921874958 +1.209 -0.234161376953125 0.5314794921874958 +1.209125 -0.2354736328125 0.5314794921874958 +1.20925 -0.23675537109375 0.5314794921874958 +1.209375 -0.23675537109375 0.5314794921874958 +1.2095 -0.23797607421875 0.5314794921874958 +1.209625 -0.23797607421875 0.5314794921874958 +1.20975 -0.239227294921875 0.5314794921874958 +1.209875 -0.24041748046875 0.5314794921874958 +1.21 -0.24041748046875 0.5314794921874958 +1.210125 -0.2415771484375 0.5314794921874958 +1.21025 -0.2415771484375 0.5314794921874958 +1.210375 -0.24273681640625 0.5314794921874958 +1.2105 -0.243865966796875 0.5314794921874958 +1.210625 -0.243865966796875 0.5314794921874958 +1.21075 -0.24493408203125 0.5314794921874958 +1.210875 -0.24493408203125 0.5314794921874958 +1.211 -0.246002197265625 0.5314794921874958 +1.211125 -0.247039794921875 0.5314794921874958 +1.21125 -0.247039794921875 0.5314794921874958 +1.211375 -0.248046875 0.5314794921874958 +1.2115 -0.248046875 0.5314794921874958 +1.211625 -0.2490234375 0.5314794921874958 +1.21175 -0.25 0.5314794921874958 +1.211875 -0.25 0.5314794921874958 +1.212 -0.25091552734375 0.5314794921874958 +1.212125 -0.25091552734375 0.5314794921874958 +1.21225 -0.2518310546875 0.5314794921874958 +1.212375 -0.252716064453125 0.5314794921874958 +1.2125 -0.252716064453125 0.5314794921874958 +1.212625 -0.2535400390625 0.5314794921874958 +1.21275 -0.2535400390625 0.5314794921874958 +1.212875 -0.254364013671875 0.5314794921874958 +1.213 -0.255157470703125 0.5314794921874958 +1.213125 -0.255157470703125 0.5314794921874958 +1.21325 -0.25592041015625 0.5314794921874958 +1.213375 -0.25592041015625 0.5314794921874958 +1.2135 -0.25665283203125 0.5314794921874958 +1.213625 -0.257354736328125 0.5314794921874958 +1.21375 -0.257354736328125 0.5314794921874958 +1.213875 -0.258026123046875 0.5314794921874958 +1.214 -0.258026123046875 0.5314794921874958 +1.214125 -0.258697509765625 0.5314794921874958 +1.21425 -0.259307861328125 0.5314794921874958 +1.214375 -0.259307861328125 0.5314794921874958 +1.2145 -0.2598876953125 0.5314794921874958 +1.214625 -0.2598876953125 0.5314794921874958 +1.21475 -0.260467529296875 0.5314794921874958 +1.214875 -0.260986328125 0.5314794921874958 +1.215 -0.260986328125 0.5314794921874958 +1.215125 -0.261505126953125 0.5314794921874958 +1.21525 -0.261505126953125 0.5314794921874958 +1.215375 -0.261993408203125 0.5314794921874958 +1.2155 -0.262420654296875 0.5314794921874958 +1.215625 -0.262420654296875 0.5314794921874958 +1.21575 -0.262847900390625 0.5314794921874958 +1.215875 -0.262847900390625 0.5314794921874958 +1.216 -0.108978271484375 0.220097656249995 +1.216125 -0.109130859375 0.220097656249995 +1.21625 -0.109130859375 0.220097656249995 +1.216375 -0.109283447265625 0.220097656249995 +1.2165 -0.109283447265625 0.220097656249995 +1.216625 -0.109405517578125 0.220097656249995 +1.21675 -0.109527587890625 0.220097656249995 +1.216875 -0.109527587890625 0.220097656249995 +1.217 -0.109619140625 0.220097656249995 +1.217125 -0.109619140625 0.220097656249995 +1.21725 -0.109710693359375 0.220097656249995 +1.217375 -0.10980224609375 0.220097656249995 +1.2175 -0.10980224609375 0.220097656249995 +1.217625 -0.10986328125 0.220097656249995 +1.21775 -0.10986328125 0.220097656249995 +1.217875 -0.10992431640625 0.220097656249995 +1.218 -0.109954833984375 0.220097656249995 +1.218125 -0.109954833984375 0.220097656249995 +1.21825 -0.1099853515625 0.220097656249995 +1.218375 -0.1099853515625 0.220097656249995 +1.2185 -0.110015869140625 0.220097656249995 +1.218625 -0.110015869140625 0.220097656249995 +1.21875 -0.110015869140625 0.220097656249995 +1.218875 -0.110015869140625 0.220097656249995 +1.219 -0.110015869140625 0.220097656249995 +1.219125 -0.1099853515625 0.220097656249995 +1.21925 -0.109954833984375 0.220097656249995 +1.219375 -0.109954833984375 0.220097656249995 +1.2195 -0.10992431640625 0.220097656249995 +1.219625 -0.10992431640625 0.220097656249995 +1.21975 -0.10986328125 0.220097656249995 +1.219875 -0.10980224609375 0.220097656249995 +1.22 -0.10980224609375 0.220097656249995 +1.220125 -0.109710693359375 0.220097656249995 +1.22025 -0.109710693359375 0.220097656249995 +1.220375 -0.109619140625 0.220097656249995 +1.2205 -0.109527587890625 0.220097656249995 +1.220625 -0.109527587890625 0.220097656249995 +1.22075 -0.109405517578125 0.220097656249995 +1.220875 -0.109405517578125 0.220097656249995 +1.221 -0.109283447265625 0.220097656249995 +1.221125 -0.109130859375 0.220097656249995 +1.22125 -0.109130859375 0.220097656249995 +1.221375 -0.108978271484375 0.220097656249995 +1.2215 -0.108978271484375 0.220097656249995 +1.221625 -0.10882568359375 0.220097656249995 +1.22175 -0.108642578125 0.220097656249995 +1.221875 -0.108642578125 0.220097656249995 +1.222 -0.10845947265625 0.220097656249995 +1.222125 -0.10845947265625 0.220097656249995 +1.22225 -0.1082763671875 0.220097656249995 +1.222375 -0.108062744140625 0.220097656249995 +1.2225 -0.108062744140625 0.220097656249995 +1.222625 -0.10784912109375 0.220097656249995 +1.22275 -0.10784912109375 0.220097656249995 +1.222875 -0.10760498046875 0.220097656249995 +1.223 -0.10736083984375 0.220097656249995 +1.223125 -0.10736083984375 0.220097656249995 +1.22325 -0.10711669921875 0.220097656249995 +1.223375 -0.10711669921875 0.220097656249995 +1.2235 -0.106842041015625 0.220097656249995 +1.223625 -0.1065673828125 0.220097656249995 +1.22375 -0.1065673828125 0.220097656249995 +1.223875 -0.10626220703125 0.220097656249995 +1.224 -0.10626220703125 0.220097656249995 +1.224125 -0.10595703125 0.220097656249995 +1.22425 -0.10565185546875 0.220097656249995 +1.224375 -0.10565185546875 0.220097656249995 +1.2245 -0.105316162109375 0.220097656249995 +1.224625 -0.105316162109375 0.220097656249995 +1.22475 -0.10498046875 0.220097656249995 +1.224875 -0.1046142578125 0.220097656249995 +1.225 -0.1046142578125 0.220097656249995 +1.225125 -0.104278564453125 0.220097656249995 +1.22525 -0.104278564453125 0.220097656249995 +1.225375 -0.1038818359375 0.220097656249995 +1.2255 -0.103515625 0.220097656249995 +1.225625 -0.103515625 0.220097656249995 +1.22575 -0.103118896484375 0.220097656249995 +1.225875 -0.103118896484375 0.220097656249995 +1.226 -0.102691650390625 0.220097656249995 +1.226125 -0.102294921875 0.220097656249995 +1.22625 -0.102294921875 0.220097656249995 +1.226375 -0.10186767578125 0.220097656249995 +1.2265 -0.10186767578125 0.220097656249995 +1.226625 -0.101409912109375 0.220097656249995 +1.22675 -0.1009521484375 0.220097656249995 +1.226875 -0.1009521484375 0.220097656249995 +1.227 -0.100494384765625 0.220097656249995 +1.227125 -0.100494384765625 0.220097656249995 +1.22725 -0.10003662109375 0.220097656249995 +1.227375 -0.09954833984375 0.220097656249995 +1.2275 -0.09954833984375 0.220097656249995 +1.227625 -0.099029541015625 0.220097656249995 +1.22775 -0.099029541015625 0.220097656249995 +1.227875 -0.098541259765625 0.220097656249995 +1.228 -0.0980224609375 0.220097656249995 +1.228125 -0.0980224609375 0.220097656249995 +1.22825 -0.097503662109375 0.220097656249995 +1.228375 -0.097503662109375 0.220097656249995 +1.2285 -0.096954345703125 0.220097656249995 +1.228625 -0.096405029296875 0.220097656249995 +1.22875 -0.096405029296875 0.220097656249995 +1.228875 -0.095855712890625 0.220097656249995 +1.229 -0.095855712890625 0.220097656249995 +1.229125 -0.09527587890625 0.220097656249995 +1.22925 -0.094696044921875 0.220097656249995 +1.229375 -0.094696044921875 0.220097656249995 +1.2295 -0.094085693359375 0.220097656249995 +1.229625 -0.094085693359375 0.220097656249995 +1.22975 -0.093505859375 0.220097656249995 +1.229875 -0.0928955078125 0.220097656249995 +1.23 -0.0928955078125 0.220097656249995 +1.230125 -0.092254638671875 0.220097656249995 +1.23025 -0.092254638671875 0.220097656249995 +1.230375 -0.09161376953125 0.220097656249995 +1.2305 -0.090972900390625 0.220097656249995 +1.230625 -0.090972900390625 0.220097656249995 +1.23075 -0.09033203125 0.220097656249995 +1.230875 -0.09033203125 0.220097656249995 +1.231 -0.08966064453125 0.220097656249995 +1.231125 -0.0889892578125 0.220097656249995 +1.23125 -0.0889892578125 0.220097656249995 +1.231375 -0.08831787109375 0.220097656249995 +1.2315 -0.08831787109375 0.220097656249995 +1.231625 -0.087615966796875 0.220097656249995 +1.23175 -0.0869140625 0.220097656249995 +1.231875 -0.0869140625 0.220097656249995 +1.232 -0.086212158203125 0.220097656249995 +1.232125 -0.086212158203125 0.220097656249995 +1.23225 -0.085479736328125 0.220097656249995 +1.232375 -0.084747314453125 0.220097656249995 +1.2325 -0.084747314453125 0.220097656249995 +1.232625 -0.084014892578125 0.220097656249995 +1.23275 -0.084014892578125 0.220097656249995 +1.232875 -0.083282470703125 0.220097656249995 +1.233 -0.08251953125 0.220097656249995 +1.233125 -0.08251953125 0.220097656249995 +1.23325 -0.081756591796875 0.220097656249995 +1.233375 -0.081756591796875 0.220097656249995 +1.2335 -0.080963134765625 0.220097656249995 +1.233625 -0.0802001953125 0.220097656249995 +1.23375 -0.0802001953125 0.220097656249995 +1.233875 -0.07940673828125 0.220097656249995 +1.234 -0.07940673828125 0.220097656249995 +1.234125 -0.078582763671875 0.220097656249995 +1.23425 -0.077789306640625 0.220097656249995 +1.234375 -0.077789306640625 0.220097656249995 +1.2345 -0.07696533203125 0.220097656249995 +1.234625 -0.07696533203125 0.220097656249995 +1.23475 -0.076141357421875 0.220097656249995 +1.234875 -0.075286865234375 0.220097656249995 +1.235 -0.075286865234375 0.220097656249995 +1.235125 -0.074462890625 0.220097656249995 +1.23525 -0.074462890625 0.220097656249995 +1.235375 -0.0736083984375 0.220097656249995 +1.2355 -0.07275390625 0.220097656249995 +1.235625 -0.07275390625 0.220097656249995 +1.23575 -0.071868896484375 0.220097656249995 +1.235875 -0.071868896484375 0.220097656249995 +1.236 -0.071014404296875 0.220097656249995 +1.236125 -0.07012939453125 0.220097656249995 +1.23625 -0.07012939453125 0.220097656249995 +1.236375 -0.0692138671875 0.220097656249995 +1.2365 -0.0692138671875 0.220097656249995 +1.236625 -0.068328857421875 0.220097656249995 +1.23675 -0.067413330078125 0.220097656249995 +1.236875 -0.067413330078125 0.220097656249995 +1.237 -0.066497802734375 0.220097656249995 +1.237125 -0.066497802734375 0.220097656249995 +1.23725 -0.065582275390625 0.220097656249995 +1.237375 -0.064666748046875 0.220097656249995 +1.2375 -0.064666748046875 0.220097656249995 +1.237625 -0.063720703125 0.220097656249995 +1.23775 -0.063720703125 0.220097656249995 +1.237875 -0.062774658203125 0.220097656249995 +1.238 -0.06182861328125 0.220097656249995 +1.238125 -0.06182861328125 0.220097656249995 +1.23825 -0.060882568359375 0.220097656249995 +1.238375 -0.060882568359375 0.220097656249995 +1.2385 -0.059906005859375 0.220097656249995 +1.238625 -0.058929443359375 0.220097656249995 +1.23875 -0.058929443359375 0.220097656249995 +1.238875 -0.057952880859375 0.220097656249995 +1.239 -0.057952880859375 0.220097656249995 +1.239125 -0.056976318359375 0.220097656249995 +1.23925 -0.055999755859375 0.220097656249995 +1.239375 -0.055999755859375 0.220097656249995 +1.2395 -0.05499267578125 0.220097656249995 +1.239625 -0.05499267578125 0.220097656249995 +1.23975 -0.053985595703125 0.220097656249995 +1.239875 -0.052978515625 0.220097656249995 +1.24 -0.052978515625 0.220097656249995 +1.240125 -0.051971435546875 0.220097656249995 +1.24025 -0.051971435546875 0.220097656249995 +1.240375 -0.05096435546875 0.220097656249995 +1.2405 -0.0499267578125 0.220097656249995 +1.240625 -0.0499267578125 0.220097656249995 +1.24075 -0.048919677734375 0.220097656249995 +1.240875 -0.048919677734375 0.220097656249995 +1.241 -0.047882080078125 0.220097656249995 +1.241125 -0.046844482421875 0.220097656249995 +1.24125 -0.046844482421875 0.220097656249995 +1.241375 -0.0457763671875 0.220097656249995 +1.2415 -0.0457763671875 0.220097656249995 +1.241625 -0.04473876953125 0.220097656249995 +1.24175 -0.043670654296875 0.220097656249995 +1.241875 -0.043670654296875 0.220097656249995 +1.242 -0.042633056640625 0.220097656249995 +1.242125 -0.042633056640625 0.220097656249995 +1.24225 -0.04156494140625 0.220097656249995 +1.242375 -0.040496826171875 0.220097656249995 +1.2425 -0.040496826171875 0.220097656249995 +1.242625 -0.039398193359375 0.220097656249995 +1.24275 -0.039398193359375 0.220097656249995 +1.242875 -0.038330078125 0.220097656249995 +1.243 -0.037261962890625 0.220097656249995 +1.243125 -0.037261962890625 0.220097656249995 +1.24325 -0.036163330078125 0.220097656249995 +1.243375 -0.036163330078125 0.220097656249995 +1.2435 -0.035064697265625 0.220097656249995 +1.243625 -0.03399658203125 0.220097656249995 +1.24375 -0.03399658203125 0.220097656249995 +1.243875 -0.03289794921875 0.220097656249995 +1.244 -0.03289794921875 0.220097656249995 +1.244125 -0.031768798828125 0.220097656249995 +1.24425 -0.030670166015625 0.220097656249995 +1.244375 -0.030670166015625 0.220097656249995 +1.2445 -0.029571533203125 0.220097656249995 +1.244625 -0.029571533203125 0.220097656249995 +1.24475 -0.028472900390625 0.220097656249995 +1.244875 -0.02734375 0.220097656249995 +1.245 -0.02734375 0.220097656249995 +1.245125 -0.0262451171875 0.220097656249995 +1.24525 -0.0262451171875 0.220097656249995 +1.245375 -0.025115966796875 0.220097656249995 +1.2455 -0.02398681640625 0.220097656249995 +1.245625 -0.02398681640625 0.220097656249995 +1.24575 -0.022857666015625 0.220097656249995 +1.245875 -0.022857666015625 0.220097656249995 +1.246 -0.021728515625 0.220097656249995 +1.246125 -0.020599365234375 0.220097656249995 +1.24625 -0.020599365234375 0.220097656249995 +1.246375 -0.01947021484375 0.220097656249995 +1.2465 -0.01947021484375 0.220097656249995 +1.246625 -0.018341064453125 0.220097656249995 +1.24675 -0.017181396484375 0.220097656249995 +1.246875 -0.017181396484375 0.220097656249995 +1.247 -0.01605224609375 0.220097656249995 +1.247125 -0.01605224609375 0.220097656249995 +1.24725 -0.014923095703125 0.220097656249995 +1.247375 -0.013763427734375 0.220097656249995 +1.2475 -0.013763427734375 0.220097656249995 +1.247625 -0.01263427734375 0.220097656249995 +1.24775 -0.01263427734375 0.220097656249995 +1.247875 -0.011474609375 0.220097656249995 1.248 0.004425048828125 -0.09448242187500444 1.248125 0.004425048828125 -0.09448242187500444 1.24825 0.003936767578125 -0.09448242187500444 @@ -9999,504 +9999,504 @@ 1.24975 0.00048828125 -0.09448242187500444 1.249875 0.0 -0.09448242187500444 1.25 0.0 -0.09448242187500444 -1.250125 -0.000518798828125 -0.09448242187500444 -1.25025 -0.000518798828125 -0.09448242187500444 -1.250375 -0.001007080078125 -0.09448242187500444 -1.2505 -0.001495361328125 -0.09448242187500444 -1.250625 -0.001495361328125 -0.09448242187500444 -1.25075 -0.001983642578125 -0.09448242187500444 -1.250875 -0.001983642578125 -0.09448242187500444 -1.251 -0.002471923828125 -0.09448242187500444 -1.251125 -0.00299072265625 -0.09448242187500444 -1.25125 -0.00299072265625 -0.09448242187500444 -1.251375 -0.00347900390625 -0.09448242187500444 -1.2515 -0.00347900390625 -0.09448242187500444 -1.251625 -0.00396728515625 -0.09448242187500444 -1.25175 -0.00445556640625 -0.09448242187500444 -1.251875 -0.00445556640625 -0.09448242187500444 -1.252 -0.00494384765625 -0.09448242187500444 -1.252125 -0.00494384765625 -0.09448242187500444 -1.25225 -0.00543212890625 -0.09448242187500444 -1.252375 -0.00592041015625 -0.09448242187500444 -1.2525 -0.00592041015625 -0.09448242187500444 -1.252625 -0.006439208984375 -0.09448242187500444 -1.25275 -0.006439208984375 -0.09448242187500444 -1.252875 -0.006927490234375 -0.09448242187500444 -1.253 -0.007415771484375 -0.09448242187500444 -1.253125 -0.007415771484375 -0.09448242187500444 -1.25325 -0.007904052734375 -0.09448242187500444 -1.253375 -0.007904052734375 -0.09448242187500444 -1.2535 -0.008392333984375 -0.09448242187500444 -1.253625 -0.008880615234375 -0.09448242187500444 -1.25375 -0.008880615234375 -0.09448242187500444 -1.253875 -0.00933837890625 -0.09448242187500444 -1.254 -0.00933837890625 -0.09448242187500444 -1.254125 -0.00982666015625 -0.09448242187500444 -1.25425 -0.01031494140625 -0.09448242187500444 -1.254375 -0.01031494140625 -0.09448242187500444 -1.2545 -0.01080322265625 -0.09448242187500444 -1.254625 -0.01080322265625 -0.09448242187500444 -1.25475 -0.01129150390625 -0.09448242187500444 -1.254875 -0.011749267578125 -0.09448242187500444 -1.255 -0.011749267578125 -0.09448242187500444 -1.255125 -0.012237548828125 -0.09448242187500444 -1.25525 -0.012237548828125 -0.09448242187500444 -1.255375 -0.012725830078125 -0.09448242187500444 -1.2555 -0.01318359375 -0.09448242187500444 -1.255625 -0.01318359375 -0.09448242187500444 -1.25575 -0.013671875 -0.09448242187500444 -1.255875 -0.013671875 -0.09448242187500444 -1.256 -0.014129638671875 -0.09448242187500444 -1.256125 -0.014617919921875 -0.09448242187500444 -1.25625 -0.014617919921875 -0.09448242187500444 -1.256375 -0.01507568359375 -0.09448242187500444 -1.2565 -0.01507568359375 -0.09448242187500444 -1.256625 -0.01556396484375 -0.09448242187500444 -1.25675 -0.016021728515625 -0.09448242187500444 -1.256875 -0.016021728515625 -0.09448242187500444 -1.257 -0.0164794921875 -0.09448242187500444 -1.257125 -0.0164794921875 -0.09448242187500444 -1.25725 -0.016937255859375 -0.09448242187500444 -1.257375 -0.01739501953125 -0.09448242187500444 -1.2575 -0.01739501953125 -0.09448242187500444 -1.257625 -0.017852783203125 -0.09448242187500444 -1.25775 -0.017852783203125 -0.09448242187500444 -1.257875 -0.018310546875 -0.09448242187500444 -1.258 -0.018768310546875 -0.09448242187500444 -1.258125 -0.018768310546875 -0.09448242187500444 -1.25825 -0.01922607421875 -0.09448242187500444 -1.258375 -0.01922607421875 -0.09448242187500444 -1.2585 -0.019683837890625 -0.09448242187500444 -1.258625 -0.0201416015625 -0.09448242187500444 -1.25875 -0.0201416015625 -0.09448242187500444 -1.258875 -0.02056884765625 -0.09448242187500444 -1.259 -0.02056884765625 -0.09448242187500444 -1.259125 -0.021026611328125 -0.09448242187500444 -1.25925 -0.021453857421875 -0.09448242187500444 -1.259375 -0.021453857421875 -0.09448242187500444 -1.2595 -0.02191162109375 -0.09448242187500444 -1.259625 -0.02191162109375 -0.09448242187500444 -1.25975 -0.0223388671875 -0.09448242187500444 -1.259875 -0.02276611328125 -0.09448242187500444 -1.26 -0.02276611328125 -0.09448242187500444 -1.260125 -0.023193359375 -0.09448242187500444 -1.26025 -0.023193359375 -0.09448242187500444 -1.260375 -0.02362060546875 -0.09448242187500444 -1.2605 -0.0240478515625 -0.09448242187500444 -1.260625 -0.0240478515625 -0.09448242187500444 -1.26075 -0.02447509765625 -0.09448242187500444 -1.260875 -0.02447509765625 -0.09448242187500444 -1.261 -0.02490234375 -0.09448242187500444 -1.261125 -0.02532958984375 -0.09448242187500444 -1.26125 -0.02532958984375 -0.09448242187500444 -1.261375 -0.0257568359375 -0.09448242187500444 -1.2615 -0.0257568359375 -0.09448242187500444 -1.261625 -0.026153564453125 -0.09448242187500444 -1.26175 -0.026580810546875 -0.09448242187500444 -1.261875 -0.026580810546875 -0.09448242187500444 -1.262 -0.0269775390625 -0.09448242187500444 -1.262125 -0.0269775390625 -0.09448242187500444 -1.26225 -0.027374267578125 -0.09448242187500444 -1.262375 -0.02777099609375 -0.09448242187500444 -1.2625 -0.02777099609375 -0.09448242187500444 -1.262625 -0.028167724609375 -0.09448242187500444 -1.26275 -0.028167724609375 -0.09448242187500444 -1.262875 -0.028564453125 -0.09448242187500444 -1.263 -0.028961181640625 -0.09448242187500444 -1.263125 -0.028961181640625 -0.09448242187500444 -1.26325 -0.02935791015625 -0.09448242187500444 -1.263375 -0.02935791015625 -0.09448242187500444 -1.2635 -0.029754638671875 -0.09448242187500444 -1.263625 -0.030120849609375 -0.09448242187500444 -1.26375 -0.030120849609375 -0.09448242187500444 -1.263875 -0.030517578125 -0.09448242187500444 -1.264 -0.030517578125 -0.09448242187500444 -1.264125 -0.0308837890625 -0.09448242187500444 -1.26425 -0.03125 -0.09448242187500444 -1.264375 -0.03125 -0.09448242187500444 -1.2645 -0.0316162109375 -0.09448242187500444 -1.264625 -0.0316162109375 -0.09448242187500444 -1.26475 -0.031982421875 -0.09448242187500444 -1.264875 -0.0323486328125 -0.09448242187500444 -1.265 -0.0323486328125 -0.09448242187500444 -1.265125 -0.03271484375 -0.09448242187500444 -1.26525 -0.03271484375 -0.09448242187500444 -1.265375 -0.0330810546875 -0.09448242187500444 -1.2655 -0.033416748046875 -0.09448242187500444 -1.265625 -0.033416748046875 -0.09448242187500444 -1.26575 -0.03375244140625 -0.09448242187500444 -1.265875 -0.03375244140625 -0.09448242187500444 -1.266 -0.03411865234375 -0.09448242187500444 -1.266125 -0.034454345703125 -0.09448242187500444 -1.26625 -0.034454345703125 -0.09448242187500444 -1.266375 -0.0347900390625 -0.09448242187500444 -1.2665 -0.0347900390625 -0.09448242187500444 -1.266625 -0.035125732421875 -0.09448242187500444 -1.26675 -0.03546142578125 -0.09448242187500444 -1.266875 -0.03546142578125 -0.09448242187500444 -1.267 -0.0357666015625 -0.09448242187500444 -1.267125 -0.0357666015625 -0.09448242187500444 -1.26725 -0.036102294921875 -0.09448242187500444 -1.267375 -0.036407470703125 -0.09448242187500444 -1.2675 -0.036407470703125 -0.09448242187500444 -1.267625 -0.036712646484375 -0.09448242187500444 -1.26775 -0.036712646484375 -0.09448242187500444 -1.267875 -0.03704833984375 -0.09448242187500444 -1.268 -0.037353515625 -0.09448242187500444 -1.268125 -0.037353515625 -0.09448242187500444 -1.26825 -0.037628173828125 -0.09448242187500444 -1.268375 -0.037628173828125 -0.09448242187500444 -1.2685 -0.037933349609375 -0.09448242187500444 -1.268625 -0.038238525390625 -0.09448242187500444 -1.26875 -0.038238525390625 -0.09448242187500444 -1.268875 -0.03851318359375 -0.09448242187500444 -1.269 -0.03851318359375 -0.09448242187500444 -1.269125 -0.038818359375 -0.09448242187500444 -1.26925 -0.039093017578125 -0.09448242187500444 -1.269375 -0.039093017578125 -0.09448242187500444 -1.2695 -0.03936767578125 -0.09448242187500444 -1.269625 -0.03936767578125 -0.09448242187500444 -1.26975 -0.039642333984375 -0.09448242187500444 -1.269875 -0.039886474609375 -0.09448242187500444 -1.27 -0.039886474609375 -0.09448242187500444 -1.270125 -0.0401611328125 -0.09448242187500444 -1.27025 -0.0401611328125 -0.09448242187500444 -1.270375 -0.040435791015625 -0.09448242187500444 -1.2705 -0.040679931640625 -0.09448242187500444 -1.270625 -0.040679931640625 -0.09448242187500444 -1.27075 -0.040924072265625 -0.09448242187500444 -1.270875 -0.040924072265625 -0.09448242187500444 -1.271 -0.041168212890625 -0.09448242187500444 -1.271125 -0.041412353515625 -0.09448242187500444 -1.27125 -0.041412353515625 -0.09448242187500444 -1.271375 -0.041656494140625 -0.09448242187500444 -1.2715 -0.041656494140625 -0.09448242187500444 -1.271625 -0.0418701171875 -0.09448242187500444 -1.27175 -0.0421142578125 -0.09448242187500444 -1.271875 -0.0421142578125 -0.09448242187500444 -1.272 -0.042327880859375 -0.09448242187500444 -1.272125 -0.042327880859375 -0.09448242187500444 -1.27225 -0.04254150390625 -0.09448242187500444 -1.272375 -0.042755126953125 -0.09448242187500444 -1.2725 -0.042755126953125 -0.09448242187500444 -1.272625 -0.04296875 -0.09448242187500444 -1.27275 -0.04296875 -0.09448242187500444 -1.272875 -0.043182373046875 -0.09448242187500444 -1.273 -0.043365478515625 -0.09448242187500444 -1.273125 -0.043365478515625 -0.09448242187500444 -1.27325 -0.043548583984375 -0.09448242187500444 -1.273375 -0.043548583984375 -0.09448242187500444 -1.2735 -0.04376220703125 -0.09448242187500444 -1.273625 -0.0439453125 -0.09448242187500444 -1.27375 -0.0439453125 -0.09448242187500444 -1.273875 -0.04412841796875 -0.09448242187500444 -1.274 -0.04412841796875 -0.09448242187500444 -1.274125 -0.044281005859375 -0.09448242187500444 -1.27425 -0.044464111328125 -0.09448242187500444 -1.274375 -0.044464111328125 -0.09448242187500444 -1.2745 -0.04461669921875 -0.09448242187500444 -1.274625 -0.04461669921875 -0.09448242187500444 -1.27475 -0.0447998046875 -0.09448242187500444 -1.274875 -0.044952392578125 -0.09448242187500444 -1.275 -0.044952392578125 -0.09448242187500444 -1.275125 -0.04510498046875 -0.09448242187500444 -1.27525 -0.04510498046875 -0.09448242187500444 -1.275375 -0.04522705078125 -0.09448242187500444 -1.2755 -0.045379638671875 -0.09448242187500444 -1.275625 -0.045379638671875 -0.09448242187500444 -1.27575 -0.045501708984375 -0.09448242187500444 -1.275875 -0.045501708984375 -0.09448242187500444 -1.276 -0.045654296875 -0.09448242187500444 -1.276125 -0.0457763671875 -0.09448242187500444 -1.27625 -0.0457763671875 -0.09448242187500444 -1.276375 -0.0458984375 -0.09448242187500444 -1.2765 -0.0458984375 -0.09448242187500444 -1.276625 -0.0460205078125 -0.09448242187500444 -1.27675 -0.046112060546875 -0.09448242187500444 -1.276875 -0.046112060546875 -0.09448242187500444 -1.277 -0.046234130859375 -0.09448242187500444 -1.277125 -0.046234130859375 -0.09448242187500444 -1.27725 -0.04632568359375 -0.09448242187500444 -1.277375 -0.046417236328125 -0.09448242187500444 -1.2775 -0.046417236328125 -0.09448242187500444 -1.277625 -0.0465087890625 -0.09448242187500444 -1.27775 -0.0465087890625 -0.09448242187500444 -1.277875 -0.046600341796875 -0.09448242187500444 -1.278 -0.046661376953125 -0.09448242187500444 -1.278125 -0.046661376953125 -0.09448242187500444 -1.27825 -0.0467529296875 -0.09448242187500444 -1.278375 -0.0467529296875 -0.09448242187500444 -1.2785 -0.04681396484375 -0.09448242187500444 -1.278625 -0.046875 -0.09448242187500444 -1.27875 -0.046875 -0.09448242187500444 -1.278875 -0.04693603515625 -0.09448242187500444 -1.279 -0.04693603515625 -0.09448242187500444 -1.279125 -0.0469970703125 -0.09448242187500444 -1.27925 -0.04705810546875 -0.09448242187500444 -1.279375 -0.04705810546875 -0.09448242187500444 -1.2795 -0.047088623046875 -0.09448242187500444 -1.279625 -0.047088623046875 -0.09448242187500444 -1.27975 -0.047119140625 -0.09448242187500444 -1.279875 -0.047149658203125 -0.09448242187500444 -1.28 -0.180694580078125 -0.3620751953125036 -1.280125 -0.1807861328125 -0.3620751953125036 -1.28025 -0.1807861328125 -0.3620751953125036 -1.280375 -0.180877685546875 -0.3620751953125036 -1.2805 -0.180938720703125 -0.3620751953125036 -1.280625 -0.180938720703125 -0.3620751953125036 -1.28075 -0.180999755859375 -0.3620751953125036 -1.280875 -0.180999755859375 -0.3620751953125036 -1.281 -0.1810302734375 -0.3620751953125036 -1.281125 -0.1810302734375 -0.3620751953125036 -1.28125 -0.1810302734375 -0.3620751953125036 -1.281375 -0.1810302734375 -0.3620751953125036 -1.2815 -0.1810302734375 -0.3620751953125036 -1.281625 -0.180999755859375 -0.3620751953125036 -1.28175 -0.180938720703125 -0.3620751953125036 -1.281875 -0.180938720703125 -0.3620751953125036 -1.282 -0.180877685546875 -0.3620751953125036 -1.282125 -0.180877685546875 -0.3620751953125036 -1.28225 -0.1807861328125 -0.3620751953125036 -1.282375 -0.180694580078125 -0.3620751953125036 -1.2825 -0.180694580078125 -0.3620751953125036 -1.282625 -0.1805419921875 -0.3620751953125036 -1.28275 -0.1805419921875 -0.3620751953125036 -1.282875 -0.180419921875 -0.3620751953125036 -1.283 -0.18023681640625 -0.3620751953125036 -1.283125 -0.18023681640625 -0.3620751953125036 -1.28325 -0.1800537109375 -0.3620751953125036 -1.283375 -0.1800537109375 -0.3620751953125036 -1.2835 -0.179840087890625 -0.3620751953125036 -1.283625 -0.179595947265625 -0.3620751953125036 -1.28375 -0.179595947265625 -0.3620751953125036 -1.283875 -0.179351806640625 -0.3620751953125036 -1.284 -0.179351806640625 -0.3620751953125036 -1.284125 -0.179107666015625 -0.3620751953125036 -1.28425 -0.178802490234375 -0.3620751953125036 -1.284375 -0.178802490234375 -0.3620751953125036 -1.2845 -0.178497314453125 -0.3620751953125036 -1.284625 -0.178497314453125 -0.3620751953125036 -1.28475 -0.178192138671875 -0.3620751953125036 -1.284875 -0.177825927734375 -0.3620751953125036 -1.285 -0.177825927734375 -0.3620751953125036 -1.285125 -0.177459716796875 -0.3620751953125036 -1.28525 -0.177459716796875 -0.3620751953125036 -1.285375 -0.177093505859375 -0.3620751953125036 -1.2855 -0.176666259765625 -0.3620751953125036 -1.285625 -0.176666259765625 -0.3620751953125036 -1.28575 -0.17626953125 -0.3620751953125036 -1.285875 -0.17626953125 -0.3620751953125036 -1.286 -0.175811767578125 -0.3620751953125036 -1.286125 -0.17535400390625 -0.3620751953125036 -1.28625 -0.17535400390625 -0.3620751953125036 -1.286375 -0.17486572265625 -0.3620751953125036 -1.2865 -0.17486572265625 -0.3620751953125036 -1.286625 -0.17437744140625 -0.3620751953125036 -1.28675 -0.173858642578125 -0.3620751953125036 -1.286875 -0.173858642578125 -0.3620751953125036 -1.287 -0.173309326171875 -0.3620751953125036 -1.287125 -0.173309326171875 -0.3620751953125036 -1.28725 -0.172760009765625 -0.3620751953125036 -1.287375 -0.17218017578125 -0.3620751953125036 -1.2875 -0.17218017578125 -0.3620751953125036 -1.287625 -0.17156982421875 -0.3620751953125036 -1.28775 -0.17156982421875 -0.3620751953125036 -1.287875 -0.17095947265625 -0.3620751953125036 -1.288 -0.170318603515625 -0.3620751953125036 -1.288125 -0.170318603515625 -0.3620751953125036 -1.28825 -0.169677734375 -0.3620751953125036 -1.288375 -0.169677734375 -0.3620751953125036 -1.2885 -0.16900634765625 -0.3620751953125036 -1.288625 -0.1683349609375 -0.3620751953125036 -1.28875 -0.1683349609375 -0.3620751953125036 -1.288875 -0.167633056640625 -0.3620751953125036 -1.289 -0.167633056640625 -0.3620751953125036 -1.289125 -0.166900634765625 -0.3620751953125036 -1.28925 -0.1661376953125 -0.3620751953125036 -1.289375 -0.1661376953125 -0.3620751953125036 -1.2895 -0.165374755859375 -0.3620751953125036 -1.289625 -0.165374755859375 -0.3620751953125036 -1.28975 -0.16461181640625 -0.3620751953125036 -1.289875 -0.163818359375 -0.3620751953125036 -1.29 -0.163818359375 -0.3620751953125036 -1.290125 -0.162994384765625 -0.3620751953125036 -1.29025 -0.162994384765625 -0.3620751953125036 -1.290375 -0.16217041015625 -0.3620751953125036 -1.2905 -0.16131591796875 -0.3620751953125036 -1.290625 -0.16131591796875 -0.3620751953125036 -1.29075 -0.160430908203125 -0.3620751953125036 -1.290875 -0.160430908203125 -0.3620751953125036 -1.291 -0.1595458984375 -0.3620751953125036 -1.291125 -0.15863037109375 -0.3620751953125036 -1.29125 -0.15863037109375 -0.3620751953125036 -1.291375 -0.15771484375 -0.3620751953125036 -1.2915 -0.15771484375 -0.3620751953125036 -1.291625 -0.15679931640625 -0.3620751953125036 -1.29175 -0.15582275390625 -0.3620751953125036 -1.291875 -0.15582275390625 -0.3620751953125036 -1.292 -0.15484619140625 -0.3620751953125036 -1.292125 -0.15484619140625 -0.3620751953125036 -1.29225 -0.15386962890625 -0.3620751953125036 -1.292375 -0.152862548828125 -0.3620751953125036 -1.2925 -0.152862548828125 -0.3620751953125036 -1.292625 -0.151824951171875 -0.3620751953125036 -1.29275 -0.151824951171875 -0.3620751953125036 -1.292875 -0.150787353515625 -0.3620751953125036 -1.293 -0.14971923828125 -0.3620751953125036 -1.293125 -0.14971923828125 -0.3620751953125036 -1.29325 -0.148651123046875 -0.3620751953125036 -1.293375 -0.148651123046875 -0.3620751953125036 -1.2935 -0.1475830078125 -0.3620751953125036 -1.293625 -0.146453857421875 -0.3620751953125036 -1.29375 -0.146453857421875 -0.3620751953125036 -1.293875 -0.145355224609375 -0.3620751953125036 -1.294 -0.145355224609375 -0.3620751953125036 -1.294125 -0.144195556640625 -0.3620751953125036 -1.29425 -0.14306640625 -0.3620751953125036 -1.294375 -0.14306640625 -0.3620751953125036 -1.2945 -0.141876220703125 -0.3620751953125036 -1.294625 -0.141876220703125 -0.3620751953125036 -1.29475 -0.14068603515625 -0.3620751953125036 -1.294875 -0.139495849609375 -0.3620751953125036 -1.295 -0.139495849609375 -0.3620751953125036 -1.295125 -0.138275146484375 -0.3620751953125036 -1.29525 -0.138275146484375 -0.3620751953125036 -1.295375 -0.137054443359375 -0.3620751953125036 -1.2955 -0.13580322265625 -0.3620751953125036 -1.295625 -0.13580322265625 -0.3620751953125036 -1.29575 -0.134552001953125 -0.3620751953125036 -1.295875 -0.134552001953125 -0.3620751953125036 -1.296 -0.133270263671875 -0.3620751953125036 -1.296125 -0.131988525390625 -0.3620751953125036 -1.29625 -0.131988525390625 -0.3620751953125036 -1.296375 -0.13067626953125 -0.3620751953125036 -1.2965 -0.13067626953125 -0.3620751953125036 -1.296625 -0.129364013671875 -0.3620751953125036 -1.29675 -0.128021240234375 -0.3620751953125036 -1.296875 -0.128021240234375 -0.3620751953125036 -1.297 -0.126678466796875 -0.3620751953125036 -1.297125 -0.126678466796875 -0.3620751953125036 -1.29725 -0.12530517578125 -0.3620751953125036 -1.297375 -0.123931884765625 -0.3620751953125036 -1.2975 -0.123931884765625 -0.3620751953125036 -1.297625 -0.12255859375 -0.3620751953125036 -1.29775 -0.12255859375 -0.3620751953125036 -1.297875 -0.12115478515625 -0.3620751953125036 -1.298 -0.119720458984375 -0.3620751953125036 -1.298125 -0.119720458984375 -0.3620751953125036 -1.29825 -0.1182861328125 -0.3620751953125036 -1.298375 -0.1182861328125 -0.3620751953125036 -1.2985 -0.116851806640625 -0.3620751953125036 -1.298625 -0.115386962890625 -0.3620751953125036 -1.29875 -0.115386962890625 -0.3620751953125036 -1.298875 -0.113922119140625 -0.3620751953125036 -1.299 -0.113922119140625 -0.3620751953125036 -1.299125 -0.112457275390625 -0.3620751953125036 -1.29925 -0.1109619140625 -0.3620751953125036 -1.299375 -0.1109619140625 -0.3620751953125036 -1.2995 -0.109466552734375 -0.3620751953125036 -1.299625 -0.109466552734375 -0.3620751953125036 -1.29975 -0.107940673828125 -0.3620751953125036 -1.299875 -0.106414794921875 -0.3620751953125036 -1.3 -0.106414794921875 -0.3620751953125036 -1.300125 -0.104888916015625 -0.3620751953125036 -1.30025 -0.104888916015625 -0.3620751953125036 -1.300375 -0.10333251953125 -0.3620751953125036 -1.3005 -0.101776123046875 -0.3620751953125036 -1.300625 -0.101776123046875 -0.3620751953125036 -1.30075 -0.100189208984375 -0.3620751953125036 -1.300875 -0.100189208984375 -0.3620751953125036 -1.301 -0.098602294921875 -0.3620751953125036 -1.301125 -0.097015380859375 -0.3620751953125036 -1.30125 -0.097015380859375 -0.3620751953125036 -1.301375 -0.09539794921875 -0.3620751953125036 -1.3015 -0.09539794921875 -0.3620751953125036 -1.301625 -0.093780517578125 -0.3620751953125036 -1.30175 -0.0921630859375 -0.3620751953125036 -1.301875 -0.0921630859375 -0.3620751953125036 -1.302 -0.09051513671875 -0.3620751953125036 -1.302125 -0.09051513671875 -0.3620751953125036 -1.30225 -0.0888671875 -0.3620751953125036 -1.302375 -0.08721923828125 -0.3620751953125036 -1.3025 -0.08721923828125 -0.3620751953125036 -1.302625 -0.0855712890625 -0.3620751953125036 -1.30275 -0.0855712890625 -0.3620751953125036 -1.302875 -0.083892822265625 -0.3620751953125036 -1.303 -0.082183837890625 -0.3620751953125036 -1.303125 -0.082183837890625 -0.3620751953125036 -1.30325 -0.08050537109375 -0.3620751953125036 -1.303375 -0.08050537109375 -0.3620751953125036 -1.3035 -0.07879638671875 -0.3620751953125036 -1.303625 -0.07708740234375 -0.3620751953125036 -1.30375 -0.07708740234375 -0.3620751953125036 -1.303875 -0.07537841796875 -0.3620751953125036 -1.304 -0.07537841796875 -0.3620751953125036 -1.304125 -0.073638916015625 -0.3620751953125036 -1.30425 -0.0718994140625 -0.3620751953125036 -1.304375 -0.0718994140625 -0.3620751953125036 -1.3045 -0.070159912109375 -0.3620751953125036 -1.304625 -0.070159912109375 -0.3620751953125036 -1.30475 -0.06842041015625 -0.3620751953125036 -1.304875 -0.066650390625 -0.3620751953125036 -1.305 -0.066650390625 -0.3620751953125036 -1.305125 -0.06488037109375 -0.3620751953125036 -1.30525 -0.06488037109375 -0.3620751953125036 -1.305375 -0.0631103515625 -0.3620751953125036 -1.3055 -0.06134033203125 -0.3620751953125036 -1.305625 -0.06134033203125 -0.3620751953125036 -1.30575 -0.059539794921875 -0.3620751953125036 -1.305875 -0.059539794921875 -0.3620751953125036 -1.306 -0.0577392578125 -0.3620751953125036 -1.306125 -0.055938720703125 -0.3620751953125036 -1.30625 -0.055938720703125 -0.3620751953125036 -1.306375 -0.05413818359375 -0.3620751953125036 -1.3065 -0.05413818359375 -0.3620751953125036 -1.306625 -0.052337646484375 -0.3620751953125036 -1.30675 -0.050506591796875 -0.3620751953125036 -1.306875 -0.050506591796875 -0.3620751953125036 -1.307 -0.0487060546875 -0.3620751953125036 -1.307125 -0.0487060546875 -0.3620751953125036 -1.30725 -0.046875 -0.3620751953125036 -1.307375 -0.0450439453125 -0.3620751953125036 -1.3075 -0.0450439453125 -0.3620751953125036 -1.307625 -0.043182373046875 -0.3620751953125036 -1.30775 -0.043182373046875 -0.3620751953125036 -1.307875 -0.041351318359375 -0.3620751953125036 -1.308 -0.03948974609375 -0.3620751953125036 -1.308125 -0.03948974609375 -0.3620751953125036 -1.30825 -0.03765869140625 -0.3620751953125036 -1.308375 -0.03765869140625 -0.3620751953125036 -1.3085 -0.035797119140625 -0.3620751953125036 -1.308625 -0.033935546875 -0.3620751953125036 -1.30875 -0.033935546875 -0.3620751953125036 -1.308875 -0.032073974609375 -0.3620751953125036 -1.309 -0.032073974609375 -0.3620751953125036 -1.309125 -0.03021240234375 -0.3620751953125036 -1.30925 -0.0283203125 -0.3620751953125036 -1.309375 -0.0283203125 -0.3620751953125036 -1.3095 -0.026458740234375 -0.3620751953125036 -1.309625 -0.026458740234375 -0.3620751953125036 -1.30975 -0.024566650390625 -0.3620751953125036 -1.309875 -0.022705078125 -0.3620751953125036 -1.31 -0.022705078125 -0.3620751953125036 -1.310125 -0.02081298828125 -0.3620751953125036 -1.31025 -0.02081298828125 -0.3620751953125036 -1.310375 -0.018951416015625 -0.3620751953125036 -1.3105 -0.017059326171875 -0.3620751953125036 -1.310625 -0.017059326171875 -0.3620751953125036 -1.31075 -0.015167236328125 -0.3620751953125036 -1.310875 -0.015167236328125 -0.3620751953125036 -1.311 -0.013275146484375 -0.3620751953125036 -1.311125 -0.011383056640625 -0.3620751953125036 -1.31125 -0.011383056640625 -0.3620751953125036 -1.311375 -0.009490966796875 -0.3620751953125036 -1.3115 -0.009490966796875 -0.3620751953125036 -1.311625 -0.007598876953125 -0.3620751953125036 -1.31175 -0.005706787109375 -0.3620751953125036 -1.311875 -0.005706787109375 -0.3620751953125036 -1.312 -0.00567626953125 -0.5400292968750023 -1.312125 -0.00567626953125 -0.5400292968750023 -1.31225 -0.002838134765625 -0.5400292968750023 +1.250125 -0.00048828125 -0.09448242187500444 +1.25025 -0.00048828125 -0.09448242187500444 +1.250375 -0.0009765625 -0.09448242187500444 +1.2505 -0.00146484375 -0.09448242187500444 +1.250625 -0.00146484375 -0.09448242187500444 +1.25075 -0.001953125 -0.09448242187500444 +1.250875 -0.001953125 -0.09448242187500444 +1.251 -0.00244140625 -0.09448242187500444 +1.251125 -0.002960205078125 -0.09448242187500444 +1.25125 -0.002960205078125 -0.09448242187500444 +1.251375 -0.003448486328125 -0.09448242187500444 +1.2515 -0.003448486328125 -0.09448242187500444 +1.251625 -0.003936767578125 -0.09448242187500444 +1.25175 -0.004425048828125 -0.09448242187500444 +1.251875 -0.004425048828125 -0.09448242187500444 +1.252 -0.004913330078125 -0.09448242187500444 +1.252125 -0.004913330078125 -0.09448242187500444 +1.25225 -0.005401611328125 -0.09448242187500444 +1.252375 -0.005889892578125 -0.09448242187500444 +1.2525 -0.005889892578125 -0.09448242187500444 +1.252625 -0.00640869140625 -0.09448242187500444 +1.25275 -0.00640869140625 -0.09448242187500444 +1.252875 -0.00689697265625 -0.09448242187500444 +1.253 -0.00738525390625 -0.09448242187500444 +1.253125 -0.00738525390625 -0.09448242187500444 +1.25325 -0.00787353515625 -0.09448242187500444 +1.253375 -0.00787353515625 -0.09448242187500444 +1.2535 -0.00836181640625 -0.09448242187500444 +1.253625 -0.00885009765625 -0.09448242187500444 +1.25375 -0.00885009765625 -0.09448242187500444 +1.253875 -0.009307861328125 -0.09448242187500444 +1.254 -0.009307861328125 -0.09448242187500444 +1.254125 -0.009796142578125 -0.09448242187500444 +1.25425 -0.010284423828125 -0.09448242187500444 +1.254375 -0.010284423828125 -0.09448242187500444 +1.2545 -0.010772705078125 -0.09448242187500444 +1.254625 -0.010772705078125 -0.09448242187500444 +1.25475 -0.011260986328125 -0.09448242187500444 +1.254875 -0.01171875 -0.09448242187500444 +1.255 -0.01171875 -0.09448242187500444 +1.255125 -0.01220703125 -0.09448242187500444 +1.25525 -0.01220703125 -0.09448242187500444 +1.255375 -0.0126953125 -0.09448242187500444 +1.2555 -0.013153076171875 -0.09448242187500444 +1.255625 -0.013153076171875 -0.09448242187500444 +1.25575 -0.013641357421875 -0.09448242187500444 +1.255875 -0.013641357421875 -0.09448242187500444 +1.256 -0.01409912109375 -0.09448242187500444 +1.256125 -0.01458740234375 -0.09448242187500444 +1.25625 -0.01458740234375 -0.09448242187500444 +1.256375 -0.015045166015625 -0.09448242187500444 +1.2565 -0.015045166015625 -0.09448242187500444 +1.256625 -0.015533447265625 -0.09448242187500444 +1.25675 -0.0159912109375 -0.09448242187500444 +1.256875 -0.0159912109375 -0.09448242187500444 +1.257 -0.016448974609375 -0.09448242187500444 +1.257125 -0.016448974609375 -0.09448242187500444 +1.25725 -0.01690673828125 -0.09448242187500444 +1.257375 -0.017364501953125 -0.09448242187500444 +1.2575 -0.017364501953125 -0.09448242187500444 +1.257625 -0.017822265625 -0.09448242187500444 +1.25775 -0.017822265625 -0.09448242187500444 +1.257875 -0.018280029296875 -0.09448242187500444 +1.258 -0.01873779296875 -0.09448242187500444 +1.258125 -0.01873779296875 -0.09448242187500444 +1.25825 -0.019195556640625 -0.09448242187500444 +1.258375 -0.019195556640625 -0.09448242187500444 +1.2585 -0.0196533203125 -0.09448242187500444 +1.258625 -0.020111083984375 -0.09448242187500444 +1.25875 -0.020111083984375 -0.09448242187500444 +1.258875 -0.020538330078125 -0.09448242187500444 +1.259 -0.020538330078125 -0.09448242187500444 +1.259125 -0.02099609375 -0.09448242187500444 +1.25925 -0.02142333984375 -0.09448242187500444 +1.259375 -0.02142333984375 -0.09448242187500444 +1.2595 -0.021881103515625 -0.09448242187500444 +1.259625 -0.021881103515625 -0.09448242187500444 +1.25975 -0.022308349609375 -0.09448242187500444 +1.259875 -0.022735595703125 -0.09448242187500444 +1.26 -0.022735595703125 -0.09448242187500444 +1.260125 -0.023162841796875 -0.09448242187500444 +1.26025 -0.023162841796875 -0.09448242187500444 +1.260375 -0.023590087890625 -0.09448242187500444 +1.2605 -0.024017333984375 -0.09448242187500444 +1.260625 -0.024017333984375 -0.09448242187500444 +1.26075 -0.024444580078125 -0.09448242187500444 +1.260875 -0.024444580078125 -0.09448242187500444 +1.261 -0.024871826171875 -0.09448242187500444 +1.261125 -0.025299072265625 -0.09448242187500444 +1.26125 -0.025299072265625 -0.09448242187500444 +1.261375 -0.025726318359375 -0.09448242187500444 +1.2615 -0.025726318359375 -0.09448242187500444 +1.261625 -0.026123046875 -0.09448242187500444 +1.26175 -0.02655029296875 -0.09448242187500444 +1.261875 -0.02655029296875 -0.09448242187500444 +1.262 -0.026947021484375 -0.09448242187500444 +1.262125 -0.026947021484375 -0.09448242187500444 +1.26225 -0.02734375 -0.09448242187500444 +1.262375 -0.027740478515625 -0.09448242187500444 +1.2625 -0.027740478515625 -0.09448242187500444 +1.262625 -0.02813720703125 -0.09448242187500444 +1.26275 -0.02813720703125 -0.09448242187500444 +1.262875 -0.028533935546875 -0.09448242187500444 +1.263 -0.0289306640625 -0.09448242187500444 +1.263125 -0.0289306640625 -0.09448242187500444 +1.26325 -0.029327392578125 -0.09448242187500444 +1.263375 -0.029327392578125 -0.09448242187500444 +1.2635 -0.02972412109375 -0.09448242187500444 +1.263625 -0.03009033203125 -0.09448242187500444 +1.26375 -0.03009033203125 -0.09448242187500444 +1.263875 -0.030487060546875 -0.09448242187500444 +1.264 -0.030487060546875 -0.09448242187500444 +1.264125 -0.030853271484375 -0.09448242187500444 +1.26425 -0.031219482421875 -0.09448242187500444 +1.264375 -0.031219482421875 -0.09448242187500444 +1.2645 -0.031585693359375 -0.09448242187500444 +1.264625 -0.031585693359375 -0.09448242187500444 +1.26475 -0.031951904296875 -0.09448242187500444 +1.264875 -0.032318115234375 -0.09448242187500444 +1.265 -0.032318115234375 -0.09448242187500444 +1.265125 -0.032684326171875 -0.09448242187500444 +1.26525 -0.032684326171875 -0.09448242187500444 +1.265375 -0.033050537109375 -0.09448242187500444 +1.2655 -0.03338623046875 -0.09448242187500444 +1.265625 -0.03338623046875 -0.09448242187500444 +1.26575 -0.033721923828125 -0.09448242187500444 +1.265875 -0.033721923828125 -0.09448242187500444 +1.266 -0.034088134765625 -0.09448242187500444 +1.266125 -0.034423828125 -0.09448242187500444 +1.26625 -0.034423828125 -0.09448242187500444 +1.266375 -0.034759521484375 -0.09448242187500444 +1.2665 -0.034759521484375 -0.09448242187500444 +1.266625 -0.03509521484375 -0.09448242187500444 +1.26675 -0.035430908203125 -0.09448242187500444 +1.266875 -0.035430908203125 -0.09448242187500444 +1.267 -0.035736083984375 -0.09448242187500444 +1.267125 -0.035736083984375 -0.09448242187500444 +1.26725 -0.03607177734375 -0.09448242187500444 +1.267375 -0.036376953125 -0.09448242187500444 +1.2675 -0.036376953125 -0.09448242187500444 +1.267625 -0.03668212890625 -0.09448242187500444 +1.26775 -0.03668212890625 -0.09448242187500444 +1.267875 -0.037017822265625 -0.09448242187500444 +1.268 -0.037322998046875 -0.09448242187500444 +1.268125 -0.037322998046875 -0.09448242187500444 +1.26825 -0.03759765625 -0.09448242187500444 +1.268375 -0.03759765625 -0.09448242187500444 +1.2685 -0.03790283203125 -0.09448242187500444 +1.268625 -0.0382080078125 -0.09448242187500444 +1.26875 -0.0382080078125 -0.09448242187500444 +1.268875 -0.038482666015625 -0.09448242187500444 +1.269 -0.038482666015625 -0.09448242187500444 +1.269125 -0.038787841796875 -0.09448242187500444 +1.26925 -0.0390625 -0.09448242187500444 +1.269375 -0.0390625 -0.09448242187500444 +1.2695 -0.039337158203125 -0.09448242187500444 +1.269625 -0.039337158203125 -0.09448242187500444 +1.26975 -0.03961181640625 -0.09448242187500444 +1.269875 -0.03985595703125 -0.09448242187500444 +1.27 -0.03985595703125 -0.09448242187500444 +1.270125 -0.040130615234375 -0.09448242187500444 +1.27025 -0.040130615234375 -0.09448242187500444 +1.270375 -0.0404052734375 -0.09448242187500444 +1.2705 -0.0406494140625 -0.09448242187500444 +1.270625 -0.0406494140625 -0.09448242187500444 +1.27075 -0.0408935546875 -0.09448242187500444 +1.270875 -0.0408935546875 -0.09448242187500444 +1.271 -0.0411376953125 -0.09448242187500444 +1.271125 -0.0413818359375 -0.09448242187500444 +1.27125 -0.0413818359375 -0.09448242187500444 +1.271375 -0.0416259765625 -0.09448242187500444 +1.2715 -0.0416259765625 -0.09448242187500444 +1.271625 -0.041839599609375 -0.09448242187500444 +1.27175 -0.042083740234375 -0.09448242187500444 +1.271875 -0.042083740234375 -0.09448242187500444 +1.272 -0.04229736328125 -0.09448242187500444 +1.272125 -0.04229736328125 -0.09448242187500444 +1.27225 -0.042510986328125 -0.09448242187500444 +1.272375 -0.042724609375 -0.09448242187500444 +1.2725 -0.042724609375 -0.09448242187500444 +1.272625 -0.042938232421875 -0.09448242187500444 +1.27275 -0.042938232421875 -0.09448242187500444 +1.272875 -0.04315185546875 -0.09448242187500444 +1.273 -0.0433349609375 -0.09448242187500444 +1.273125 -0.0433349609375 -0.09448242187500444 +1.27325 -0.04351806640625 -0.09448242187500444 +1.273375 -0.04351806640625 -0.09448242187500444 +1.2735 -0.043731689453125 -0.09448242187500444 +1.273625 -0.043914794921875 -0.09448242187500444 +1.27375 -0.043914794921875 -0.09448242187500444 +1.273875 -0.044097900390625 -0.09448242187500444 +1.274 -0.044097900390625 -0.09448242187500444 +1.274125 -0.04425048828125 -0.09448242187500444 +1.27425 -0.04443359375 -0.09448242187500444 +1.274375 -0.04443359375 -0.09448242187500444 +1.2745 -0.044586181640625 -0.09448242187500444 +1.274625 -0.044586181640625 -0.09448242187500444 +1.27475 -0.044769287109375 -0.09448242187500444 +1.274875 -0.044921875 -0.09448242187500444 +1.275 -0.044921875 -0.09448242187500444 +1.275125 -0.045074462890625 -0.09448242187500444 +1.27525 -0.045074462890625 -0.09448242187500444 +1.275375 -0.045196533203125 -0.09448242187500444 +1.2755 -0.04534912109375 -0.09448242187500444 +1.275625 -0.04534912109375 -0.09448242187500444 +1.27575 -0.04547119140625 -0.09448242187500444 +1.275875 -0.04547119140625 -0.09448242187500444 +1.276 -0.045623779296875 -0.09448242187500444 +1.276125 -0.045745849609375 -0.09448242187500444 +1.27625 -0.045745849609375 -0.09448242187500444 +1.276375 -0.045867919921875 -0.09448242187500444 +1.2765 -0.045867919921875 -0.09448242187500444 +1.276625 -0.045989990234375 -0.09448242187500444 +1.27675 -0.04608154296875 -0.09448242187500444 +1.276875 -0.04608154296875 -0.09448242187500444 +1.277 -0.04620361328125 -0.09448242187500444 +1.277125 -0.04620361328125 -0.09448242187500444 +1.27725 -0.046295166015625 -0.09448242187500444 +1.277375 -0.04638671875 -0.09448242187500444 +1.2775 -0.04638671875 -0.09448242187500444 +1.277625 -0.046478271484375 -0.09448242187500444 +1.27775 -0.046478271484375 -0.09448242187500444 +1.277875 -0.04656982421875 -0.09448242187500444 +1.278 -0.046630859375 -0.09448242187500444 +1.278125 -0.046630859375 -0.09448242187500444 +1.27825 -0.046722412109375 -0.09448242187500444 +1.278375 -0.046722412109375 -0.09448242187500444 +1.2785 -0.046783447265625 -0.09448242187500444 +1.278625 -0.046844482421875 -0.09448242187500444 +1.27875 -0.046844482421875 -0.09448242187500444 +1.278875 -0.046905517578125 -0.09448242187500444 +1.279 -0.046905517578125 -0.09448242187500444 +1.279125 -0.046966552734375 -0.09448242187500444 +1.27925 -0.047027587890625 -0.09448242187500444 +1.279375 -0.047027587890625 -0.09448242187500444 +1.2795 -0.04705810546875 -0.09448242187500444 +1.279625 -0.04705810546875 -0.09448242187500444 +1.27975 -0.047088623046875 -0.09448242187500444 +1.279875 -0.047119140625 -0.09448242187500444 +1.28 -0.1806640625 -0.3620751953125036 +1.280125 -0.180755615234375 -0.3620751953125036 +1.28025 -0.180755615234375 -0.3620751953125036 +1.280375 -0.18084716796875 -0.3620751953125036 +1.2805 -0.180908203125 -0.3620751953125036 +1.280625 -0.180908203125 -0.3620751953125036 +1.28075 -0.18096923828125 -0.3620751953125036 +1.280875 -0.18096923828125 -0.3620751953125036 +1.281 -0.180999755859375 -0.3620751953125036 +1.281125 -0.180999755859375 -0.3620751953125036 +1.28125 -0.180999755859375 -0.3620751953125036 +1.281375 -0.180999755859375 -0.3620751953125036 +1.2815 -0.180999755859375 -0.3620751953125036 +1.281625 -0.18096923828125 -0.3620751953125036 +1.28175 -0.180908203125 -0.3620751953125036 +1.281875 -0.180908203125 -0.3620751953125036 +1.282 -0.18084716796875 -0.3620751953125036 +1.282125 -0.18084716796875 -0.3620751953125036 +1.28225 -0.180755615234375 -0.3620751953125036 +1.282375 -0.1806640625 -0.3620751953125036 +1.2825 -0.1806640625 -0.3620751953125036 +1.282625 -0.180511474609375 -0.3620751953125036 +1.28275 -0.180511474609375 -0.3620751953125036 +1.282875 -0.180389404296875 -0.3620751953125036 +1.283 -0.180206298828125 -0.3620751953125036 +1.283125 -0.180206298828125 -0.3620751953125036 +1.28325 -0.180023193359375 -0.3620751953125036 +1.283375 -0.180023193359375 -0.3620751953125036 +1.2835 -0.1798095703125 -0.3620751953125036 +1.283625 -0.1795654296875 -0.3620751953125036 +1.28375 -0.1795654296875 -0.3620751953125036 +1.283875 -0.1793212890625 -0.3620751953125036 +1.284 -0.1793212890625 -0.3620751953125036 +1.284125 -0.1790771484375 -0.3620751953125036 +1.28425 -0.17877197265625 -0.3620751953125036 +1.284375 -0.17877197265625 -0.3620751953125036 +1.2845 -0.178466796875 -0.3620751953125036 +1.284625 -0.178466796875 -0.3620751953125036 +1.28475 -0.17816162109375 -0.3620751953125036 +1.284875 -0.17779541015625 -0.3620751953125036 +1.285 -0.17779541015625 -0.3620751953125036 +1.285125 -0.17742919921875 -0.3620751953125036 +1.28525 -0.17742919921875 -0.3620751953125036 +1.285375 -0.17706298828125 -0.3620751953125036 +1.2855 -0.1766357421875 -0.3620751953125036 +1.285625 -0.1766357421875 -0.3620751953125036 +1.28575 -0.176239013671875 -0.3620751953125036 +1.285875 -0.176239013671875 -0.3620751953125036 +1.286 -0.17578125 -0.3620751953125036 +1.286125 -0.175323486328125 -0.3620751953125036 +1.28625 -0.175323486328125 -0.3620751953125036 +1.286375 -0.174835205078125 -0.3620751953125036 +1.2865 -0.174835205078125 -0.3620751953125036 +1.286625 -0.174346923828125 -0.3620751953125036 +1.28675 -0.173828125 -0.3620751953125036 +1.286875 -0.173828125 -0.3620751953125036 +1.287 -0.17327880859375 -0.3620751953125036 +1.287125 -0.17327880859375 -0.3620751953125036 +1.28725 -0.1727294921875 -0.3620751953125036 +1.287375 -0.172149658203125 -0.3620751953125036 +1.2875 -0.172149658203125 -0.3620751953125036 +1.287625 -0.171539306640625 -0.3620751953125036 +1.28775 -0.171539306640625 -0.3620751953125036 +1.287875 -0.170928955078125 -0.3620751953125036 +1.288 -0.1702880859375 -0.3620751953125036 +1.288125 -0.1702880859375 -0.3620751953125036 +1.28825 -0.169647216796875 -0.3620751953125036 +1.288375 -0.169647216796875 -0.3620751953125036 +1.2885 -0.168975830078125 -0.3620751953125036 +1.288625 -0.168304443359375 -0.3620751953125036 +1.28875 -0.168304443359375 -0.3620751953125036 +1.288875 -0.1676025390625 -0.3620751953125036 +1.289 -0.1676025390625 -0.3620751953125036 +1.289125 -0.1668701171875 -0.3620751953125036 +1.28925 -0.166107177734375 -0.3620751953125036 +1.289375 -0.166107177734375 -0.3620751953125036 +1.2895 -0.16534423828125 -0.3620751953125036 +1.289625 -0.16534423828125 -0.3620751953125036 +1.28975 -0.164581298828125 -0.3620751953125036 +1.289875 -0.163787841796875 -0.3620751953125036 +1.29 -0.163787841796875 -0.3620751953125036 +1.290125 -0.1629638671875 -0.3620751953125036 +1.29025 -0.1629638671875 -0.3620751953125036 +1.290375 -0.162139892578125 -0.3620751953125036 +1.2905 -0.161285400390625 -0.3620751953125036 +1.290625 -0.161285400390625 -0.3620751953125036 +1.29075 -0.160400390625 -0.3620751953125036 +1.290875 -0.160400390625 -0.3620751953125036 +1.291 -0.159515380859375 -0.3620751953125036 +1.291125 -0.158599853515625 -0.3620751953125036 +1.29125 -0.158599853515625 -0.3620751953125036 +1.291375 -0.157684326171875 -0.3620751953125036 +1.2915 -0.157684326171875 -0.3620751953125036 +1.291625 -0.156768798828125 -0.3620751953125036 +1.29175 -0.155792236328125 -0.3620751953125036 +1.291875 -0.155792236328125 -0.3620751953125036 +1.292 -0.154815673828125 -0.3620751953125036 +1.292125 -0.154815673828125 -0.3620751953125036 +1.29225 -0.153839111328125 -0.3620751953125036 +1.292375 -0.15283203125 -0.3620751953125036 +1.2925 -0.15283203125 -0.3620751953125036 +1.292625 -0.15179443359375 -0.3620751953125036 +1.29275 -0.15179443359375 -0.3620751953125036 +1.292875 -0.1507568359375 -0.3620751953125036 +1.293 -0.149688720703125 -0.3620751953125036 +1.293125 -0.149688720703125 -0.3620751953125036 +1.29325 -0.14862060546875 -0.3620751953125036 +1.293375 -0.14862060546875 -0.3620751953125036 +1.2935 -0.147552490234375 -0.3620751953125036 +1.293625 -0.14642333984375 -0.3620751953125036 +1.29375 -0.14642333984375 -0.3620751953125036 +1.293875 -0.14532470703125 -0.3620751953125036 +1.294 -0.14532470703125 -0.3620751953125036 +1.294125 -0.1441650390625 -0.3620751953125036 +1.29425 -0.143035888671875 -0.3620751953125036 +1.294375 -0.143035888671875 -0.3620751953125036 +1.2945 -0.141845703125 -0.3620751953125036 +1.294625 -0.141845703125 -0.3620751953125036 +1.29475 -0.140655517578125 -0.3620751953125036 +1.294875 -0.13946533203125 -0.3620751953125036 +1.295 -0.13946533203125 -0.3620751953125036 +1.295125 -0.13824462890625 -0.3620751953125036 +1.29525 -0.13824462890625 -0.3620751953125036 +1.295375 -0.13702392578125 -0.3620751953125036 +1.2955 -0.135772705078125 -0.3620751953125036 +1.295625 -0.135772705078125 -0.3620751953125036 +1.29575 -0.134521484375 -0.3620751953125036 +1.295875 -0.134521484375 -0.3620751953125036 +1.296 -0.13323974609375 -0.3620751953125036 +1.296125 -0.1319580078125 -0.3620751953125036 +1.29625 -0.1319580078125 -0.3620751953125036 +1.296375 -0.130645751953125 -0.3620751953125036 +1.2965 -0.130645751953125 -0.3620751953125036 +1.296625 -0.12933349609375 -0.3620751953125036 +1.29675 -0.12799072265625 -0.3620751953125036 +1.296875 -0.12799072265625 -0.3620751953125036 +1.297 -0.12664794921875 -0.3620751953125036 +1.297125 -0.12664794921875 -0.3620751953125036 +1.29725 -0.125274658203125 -0.3620751953125036 +1.297375 -0.1239013671875 -0.3620751953125036 +1.2975 -0.1239013671875 -0.3620751953125036 +1.297625 -0.122528076171875 -0.3620751953125036 +1.29775 -0.122528076171875 -0.3620751953125036 +1.297875 -0.121124267578125 -0.3620751953125036 +1.298 -0.11968994140625 -0.3620751953125036 +1.298125 -0.11968994140625 -0.3620751953125036 +1.29825 -0.118255615234375 -0.3620751953125036 +1.298375 -0.118255615234375 -0.3620751953125036 +1.2985 -0.1168212890625 -0.3620751953125036 +1.298625 -0.1153564453125 -0.3620751953125036 +1.29875 -0.1153564453125 -0.3620751953125036 +1.298875 -0.1138916015625 -0.3620751953125036 +1.299 -0.1138916015625 -0.3620751953125036 +1.299125 -0.1124267578125 -0.3620751953125036 +1.29925 -0.110931396484375 -0.3620751953125036 +1.299375 -0.110931396484375 -0.3620751953125036 +1.2995 -0.10943603515625 -0.3620751953125036 +1.299625 -0.10943603515625 -0.3620751953125036 +1.29975 -0.10791015625 -0.3620751953125036 +1.299875 -0.10638427734375 -0.3620751953125036 +1.3 -0.10638427734375 -0.3620751953125036 +1.300125 -0.1048583984375 -0.3620751953125036 +1.30025 -0.1048583984375 -0.3620751953125036 +1.300375 -0.103302001953125 -0.3620751953125036 +1.3005 -0.10174560546875 -0.3620751953125036 +1.300625 -0.10174560546875 -0.3620751953125036 +1.30075 -0.10015869140625 -0.3620751953125036 +1.300875 -0.10015869140625 -0.3620751953125036 +1.301 -0.09857177734375 -0.3620751953125036 +1.301125 -0.09698486328125 -0.3620751953125036 +1.30125 -0.09698486328125 -0.3620751953125036 +1.301375 -0.095367431640625 -0.3620751953125036 +1.3015 -0.095367431640625 -0.3620751953125036 +1.301625 -0.09375 -0.3620751953125036 +1.30175 -0.092132568359375 -0.3620751953125036 +1.301875 -0.092132568359375 -0.3620751953125036 +1.302 -0.090484619140625 -0.3620751953125036 +1.302125 -0.090484619140625 -0.3620751953125036 +1.30225 -0.088836669921875 -0.3620751953125036 +1.302375 -0.087188720703125 -0.3620751953125036 +1.3025 -0.087188720703125 -0.3620751953125036 +1.302625 -0.085540771484375 -0.3620751953125036 +1.30275 -0.085540771484375 -0.3620751953125036 +1.302875 -0.0838623046875 -0.3620751953125036 +1.303 -0.0821533203125 -0.3620751953125036 +1.303125 -0.0821533203125 -0.3620751953125036 +1.30325 -0.080474853515625 -0.3620751953125036 +1.303375 -0.080474853515625 -0.3620751953125036 +1.3035 -0.078765869140625 -0.3620751953125036 +1.303625 -0.077056884765625 -0.3620751953125036 +1.30375 -0.077056884765625 -0.3620751953125036 +1.303875 -0.075347900390625 -0.3620751953125036 +1.304 -0.075347900390625 -0.3620751953125036 +1.304125 -0.0736083984375 -0.3620751953125036 +1.30425 -0.071868896484375 -0.3620751953125036 +1.304375 -0.071868896484375 -0.3620751953125036 +1.3045 -0.07012939453125 -0.3620751953125036 +1.304625 -0.07012939453125 -0.3620751953125036 +1.30475 -0.068389892578125 -0.3620751953125036 +1.304875 -0.066619873046875 -0.3620751953125036 +1.305 -0.066619873046875 -0.3620751953125036 +1.305125 -0.064849853515625 -0.3620751953125036 +1.30525 -0.064849853515625 -0.3620751953125036 +1.305375 -0.063079833984375 -0.3620751953125036 +1.3055 -0.061309814453125 -0.3620751953125036 +1.305625 -0.061309814453125 -0.3620751953125036 +1.30575 -0.05950927734375 -0.3620751953125036 +1.305875 -0.05950927734375 -0.3620751953125036 +1.306 -0.057708740234375 -0.3620751953125036 +1.306125 -0.055908203125 -0.3620751953125036 +1.30625 -0.055908203125 -0.3620751953125036 +1.306375 -0.054107666015625 -0.3620751953125036 +1.3065 -0.054107666015625 -0.3620751953125036 +1.306625 -0.05230712890625 -0.3620751953125036 +1.30675 -0.05047607421875 -0.3620751953125036 +1.306875 -0.05047607421875 -0.3620751953125036 +1.307 -0.048675537109375 -0.3620751953125036 +1.307125 -0.048675537109375 -0.3620751953125036 +1.30725 -0.046844482421875 -0.3620751953125036 +1.307375 -0.045013427734375 -0.3620751953125036 +1.3075 -0.045013427734375 -0.3620751953125036 +1.307625 -0.04315185546875 -0.3620751953125036 +1.30775 -0.04315185546875 -0.3620751953125036 +1.307875 -0.04132080078125 -0.3620751953125036 +1.308 -0.039459228515625 -0.3620751953125036 +1.308125 -0.039459228515625 -0.3620751953125036 +1.30825 -0.037628173828125 -0.3620751953125036 +1.308375 -0.037628173828125 -0.3620751953125036 +1.3085 -0.0357666015625 -0.3620751953125036 +1.308625 -0.033905029296875 -0.3620751953125036 +1.30875 -0.033905029296875 -0.3620751953125036 +1.308875 -0.03204345703125 -0.3620751953125036 +1.309 -0.03204345703125 -0.3620751953125036 +1.309125 -0.030181884765625 -0.3620751953125036 +1.30925 -0.028289794921875 -0.3620751953125036 +1.309375 -0.028289794921875 -0.3620751953125036 +1.3095 -0.02642822265625 -0.3620751953125036 +1.309625 -0.02642822265625 -0.3620751953125036 +1.30975 -0.0245361328125 -0.3620751953125036 +1.309875 -0.022674560546875 -0.3620751953125036 +1.31 -0.022674560546875 -0.3620751953125036 +1.310125 -0.020782470703125 -0.3620751953125036 +1.31025 -0.020782470703125 -0.3620751953125036 +1.310375 -0.0189208984375 -0.3620751953125036 +1.3105 -0.01702880859375 -0.3620751953125036 +1.310625 -0.01702880859375 -0.3620751953125036 +1.31075 -0.01513671875 -0.3620751953125036 +1.310875 -0.01513671875 -0.3620751953125036 +1.311 -0.01324462890625 -0.3620751953125036 +1.311125 -0.0113525390625 -0.3620751953125036 +1.31125 -0.0113525390625 -0.3620751953125036 +1.311375 -0.00946044921875 -0.3620751953125036 +1.3115 -0.00946044921875 -0.3620751953125036 +1.311625 -0.007568359375 -0.3620751953125036 +1.31175 -0.00567626953125 -0.3620751953125036 +1.311875 -0.00567626953125 -0.3620751953125036 +1.312 -0.005645751953125 -0.5400292968750023 +1.312125 -0.005645751953125 -0.5400292968750023 +1.31225 -0.0028076171875 -0.5400292968750023 1.312375 0.0 -0.5400292968750023 1.3125 0.0 -0.5400292968750023 1.312625 0.0028076171875 -0.5400292968750023 @@ -10999,504 +10999,504 @@ 1.37475 0.00311279296875 -0.5998974609374999 1.374875 0.0 -0.5998974609374999 1.375 0.0 -0.5998974609374999 -1.375125 -0.003143310546875 -0.5998974609374999 -1.37525 -0.003143310546875 -0.5998974609374999 -1.375375 -0.00628662109375 -0.5998974609374999 -1.3755 -0.009429931640625 -0.5998974609374999 -1.375625 -0.009429931640625 -0.5998974609374999 -1.37575 -0.0125732421875 -0.5998974609374999 -1.375875 -0.0125732421875 -0.5998974609374999 -1.376 -0.013946533203125 -0.5321582031249976 -1.376125 -0.0167236328125 -0.5321582031249976 -1.37625 -0.0167236328125 -0.5321582031249976 -1.376375 -0.019500732421875 -0.5321582031249976 -1.3765 -0.019500732421875 -0.5321582031249976 -1.376625 -0.02227783203125 -0.5321582031249976 -1.37675 -0.025054931640625 -0.5321582031249976 -1.376875 -0.025054931640625 -0.5321582031249976 -1.377 -0.02783203125 -0.5321582031249976 -1.377125 -0.02783203125 -0.5321582031249976 -1.37725 -0.030609130859375 -0.5321582031249976 -1.377375 -0.033355712890625 -0.5321582031249976 -1.3775 -0.033355712890625 -0.5321582031249976 -1.377625 -0.0361328125 -0.5321582031249976 -1.37775 -0.0361328125 -0.5321582031249976 -1.377875 -0.03887939453125 -0.5321582031249976 -1.378 -0.0416259765625 -0.5321582031249976 -1.378125 -0.0416259765625 -0.5321582031249976 -1.37825 -0.04437255859375 -0.5321582031249976 -1.378375 -0.04437255859375 -0.5321582031249976 -1.3785 -0.047119140625 -0.5321582031249976 -1.378625 -0.04986572265625 -0.5321582031249976 -1.37875 -0.04986572265625 -0.5321582031249976 -1.378875 -0.0526123046875 -0.5321582031249976 -1.379 -0.0526123046875 -0.5321582031249976 -1.379125 -0.055328369140625 -0.5321582031249976 -1.37925 -0.05804443359375 -0.5321582031249976 -1.379375 -0.05804443359375 -0.5321582031249976 -1.3795 -0.060760498046875 -0.5321582031249976 -1.379625 -0.060760498046875 -0.5321582031249976 -1.37975 -0.0634765625 -0.5321582031249976 -1.379875 -0.066192626953125 -0.5321582031249976 -1.38 -0.066192626953125 -0.5321582031249976 -1.380125 -0.068878173828125 -0.5321582031249976 -1.38025 -0.068878173828125 -0.5321582031249976 -1.380375 -0.071563720703125 -0.5321582031249976 -1.3805 -0.074249267578125 -0.5321582031249976 -1.380625 -0.074249267578125 -0.5321582031249976 -1.38075 -0.076904296875 -0.5321582031249976 -1.380875 -0.076904296875 -0.5321582031249976 -1.381 -0.07958984375 -0.5321582031249976 -1.381125 -0.082244873046875 -0.5321582031249976 -1.38125 -0.082244873046875 -0.5321582031249976 -1.381375 -0.084869384765625 -0.5321582031249976 -1.3815 -0.084869384765625 -0.5321582031249976 -1.381625 -0.0875244140625 -0.5321582031249976 -1.38175 -0.09014892578125 -0.5321582031249976 -1.381875 -0.09014892578125 -0.5321582031249976 -1.382 -0.092742919921875 -0.5321582031249976 -1.382125 -0.092742919921875 -0.5321582031249976 -1.38225 -0.095367431640625 -0.5321582031249976 -1.382375 -0.09796142578125 -0.5321582031249976 -1.3825 -0.09796142578125 -0.5321582031249976 -1.382625 -0.100555419921875 -0.5321582031249976 -1.38275 -0.100555419921875 -0.5321582031249976 -1.382875 -0.103118896484375 -0.5321582031249976 -1.383 -0.105682373046875 -0.5321582031249976 -1.383125 -0.105682373046875 -0.5321582031249976 -1.38325 -0.108245849609375 -0.5321582031249976 -1.383375 -0.108245849609375 -0.5321582031249976 -1.3835 -0.11077880859375 -0.5321582031249976 -1.383625 -0.113311767578125 -0.5321582031249976 -1.38375 -0.113311767578125 -0.5321582031249976 -1.383875 -0.115814208984375 -0.5321582031249976 -1.384 -0.115814208984375 -0.5321582031249976 -1.384125 -0.118316650390625 -0.5321582031249976 -1.38425 -0.12078857421875 -0.5321582031249976 -1.384375 -0.12078857421875 -0.5321582031249976 -1.3845 -0.123291015625 -0.5321582031249976 -1.384625 -0.123291015625 -0.5321582031249976 -1.38475 -0.125762939453125 -0.5321582031249976 -1.384875 -0.128204345703125 -0.5321582031249976 -1.385 -0.128204345703125 -0.5321582031249976 -1.385125 -0.130615234375 -0.5321582031249976 -1.38525 -0.130615234375 -0.5321582031249976 -1.385375 -0.133056640625 -0.5321582031249976 -1.3855 -0.13543701171875 -0.5321582031249976 -1.385625 -0.13543701171875 -0.5321582031249976 -1.38575 -0.137847900390625 -0.5321582031249976 -1.385875 -0.137847900390625 -0.5321582031249976 -1.386 -0.140228271484375 -0.5321582031249976 -1.386125 -0.142578125 -0.5321582031249976 -1.38625 -0.142578125 -0.5321582031249976 -1.386375 -0.144927978515625 -0.5321582031249976 -1.3865 -0.144927978515625 -0.5321582031249976 -1.386625 -0.147247314453125 -0.5321582031249976 -1.38675 -0.149566650390625 -0.5321582031249976 -1.386875 -0.149566650390625 -0.5321582031249976 -1.387 -0.15185546875 -0.5321582031249976 -1.387125 -0.15185546875 -0.5321582031249976 -1.38725 -0.154144287109375 -0.5321582031249976 -1.387375 -0.156402587890625 -0.5321582031249976 -1.3875 -0.156402587890625 -0.5321582031249976 -1.387625 -0.158660888671875 -0.5321582031249976 -1.38775 -0.158660888671875 -0.5321582031249976 -1.387875 -0.160888671875 -0.5321582031249976 -1.388 -0.1630859375 -0.5321582031249976 -1.388125 -0.1630859375 -0.5321582031249976 -1.38825 -0.165283203125 -0.5321582031249976 -1.388375 -0.165283203125 -0.5321582031249976 -1.3885 -0.167449951171875 -0.5321582031249976 -1.388625 -0.16961669921875 -0.5321582031249976 -1.38875 -0.16961669921875 -0.5321582031249976 -1.388875 -0.1717529296875 -0.5321582031249976 -1.389 -0.1717529296875 -0.5321582031249976 -1.389125 -0.173858642578125 -0.5321582031249976 -1.38925 -0.17596435546875 -0.5321582031249976 -1.389375 -0.17596435546875 -0.5321582031249976 -1.3895 -0.17803955078125 -0.5321582031249976 -1.389625 -0.17803955078125 -0.5321582031249976 -1.38975 -0.18011474609375 -0.5321582031249976 -1.389875 -0.182159423828125 -0.5321582031249976 -1.39 -0.182159423828125 -0.5321582031249976 -1.390125 -0.184173583984375 -0.5321582031249976 -1.39025 -0.184173583984375 -0.5321582031249976 -1.390375 -0.1861572265625 -0.5321582031249976 -1.3905 -0.188140869140625 -0.5321582031249976 -1.390625 -0.188140869140625 -0.5321582031249976 -1.39075 -0.19012451171875 -0.5321582031249976 -1.390875 -0.19012451171875 -0.5321582031249976 -1.391 -0.192047119140625 -0.5321582031249976 -1.391125 -0.1939697265625 -0.5321582031249976 -1.39125 -0.1939697265625 -0.5321582031249976 -1.391375 -0.19586181640625 -0.5321582031249976 -1.3915 -0.19586181640625 -0.5321582031249976 -1.391625 -0.19775390625 -0.5321582031249976 -1.39175 -0.1995849609375 -0.5321582031249976 -1.391875 -0.1995849609375 -0.5321582031249976 -1.392 -0.201416015625 -0.5321582031249976 -1.392125 -0.201416015625 -0.5321582031249976 -1.39225 -0.2032470703125 -0.5321582031249976 -1.392375 -0.20501708984375 -0.5321582031249976 -1.3925 -0.20501708984375 -0.5321582031249976 -1.392625 -0.206787109375 -0.5321582031249976 -1.39275 -0.206787109375 -0.5321582031249976 -1.392875 -0.208526611328125 -0.5321582031249976 -1.393 -0.21026611328125 -0.5321582031249976 -1.393125 -0.21026611328125 -0.5321582031249976 -1.39325 -0.211944580078125 -0.5321582031249976 -1.393375 -0.211944580078125 -0.5321582031249976 -1.3935 -0.213623046875 -0.5321582031249976 -1.393625 -0.21527099609375 -0.5321582031249976 -1.39375 -0.21527099609375 -0.5321582031249976 -1.393875 -0.216888427734375 -0.5321582031249976 -1.394 -0.216888427734375 -0.5321582031249976 -1.394125 -0.218505859375 -0.5321582031249976 -1.39425 -0.220062255859375 -0.5321582031249976 -1.394375 -0.220062255859375 -0.5321582031249976 -1.3945 -0.22161865234375 -0.5321582031249976 -1.394625 -0.22161865234375 -0.5321582031249976 -1.39475 -0.22314453125 -0.5321582031249976 -1.394875 -0.22467041015625 -0.5321582031249976 -1.395 -0.22467041015625 -0.5321582031249976 -1.395125 -0.22613525390625 -0.5321582031249976 -1.39525 -0.22613525390625 -0.5321582031249976 -1.395375 -0.22760009765625 -0.5321582031249976 -1.3955 -0.229034423828125 -0.5321582031249976 -1.395625 -0.229034423828125 -0.5321582031249976 -1.39575 -0.230438232421875 -0.5321582031249976 -1.395875 -0.230438232421875 -0.5321582031249976 -1.396 -0.2318115234375 -0.5321582031249976 -1.396125 -0.233184814453125 -0.5321582031249976 -1.39625 -0.233184814453125 -0.5321582031249976 -1.396375 -0.2344970703125 -0.5321582031249976 -1.3965 -0.2344970703125 -0.5321582031249976 -1.396625 -0.235809326171875 -0.5321582031249976 -1.39675 -0.237091064453125 -0.5321582031249976 -1.396875 -0.237091064453125 -0.5321582031249976 -1.397 -0.23834228515625 -0.5321582031249976 -1.397125 -0.23834228515625 -0.5321582031249976 -1.39725 -0.23956298828125 -0.5321582031249976 -1.397375 -0.240753173828125 -0.5321582031249976 -1.3975 -0.240753173828125 -0.5321582031249976 -1.397625 -0.241943359375 -0.5321582031249976 -1.39775 -0.241943359375 -0.5321582031249976 -1.397875 -0.243072509765625 -0.5321582031249976 -1.398 -0.24420166015625 -0.5321582031249976 -1.398125 -0.24420166015625 -0.5321582031249976 -1.39825 -0.24530029296875 -0.5321582031249976 -1.398375 -0.24530029296875 -0.5321582031249976 -1.3985 -0.246368408203125 -0.5321582031249976 -1.398625 -0.247406005859375 -0.5321582031249976 -1.39875 -0.247406005859375 -0.5321582031249976 -1.398875 -0.2484130859375 -0.5321582031249976 -1.399 -0.2484130859375 -0.5321582031249976 -1.399125 -0.2493896484375 -0.5321582031249976 -1.39925 -0.2503662109375 -0.5321582031249976 -1.399375 -0.2503662109375 -0.5321582031249976 -1.3995 -0.25128173828125 -0.5321582031249976 -1.399625 -0.25128173828125 -0.5321582031249976 -1.39975 -0.252197265625 -0.5321582031249976 -1.399875 -0.2530517578125 -0.5321582031249976 -1.4 -0.2530517578125 -0.5321582031249976 -1.400125 -0.25390625 -0.5321582031249976 -1.40025 -0.25390625 -0.5321582031249976 -1.400375 -0.254730224609375 -0.5321582031249976 -1.4005 -0.255523681640625 -0.5321582031249976 -1.400625 -0.255523681640625 -0.5321582031249976 -1.40075 -0.25628662109375 -0.5321582031249976 -1.400875 -0.25628662109375 -0.5321582031249976 -1.401 -0.25701904296875 -0.5321582031249976 -1.401125 -0.257720947265625 -0.5321582031249976 -1.40125 -0.257720947265625 -0.5321582031249976 -1.401375 -0.2584228515625 -0.5321582031249976 -1.4015 -0.2584228515625 -0.5321582031249976 -1.401625 -0.259063720703125 -0.5321582031249976 -1.40175 -0.259674072265625 -0.5321582031249976 -1.401875 -0.259674072265625 -0.5321582031249976 -1.402 -0.26025390625 -0.5321582031249976 -1.402125 -0.26025390625 -0.5321582031249976 -1.40225 -0.260833740234375 -0.5321582031249976 -1.402375 -0.261383056640625 -0.5321582031249976 -1.4025 -0.261383056640625 -0.5321582031249976 -1.402625 -0.261871337890625 -0.5321582031249976 -1.40275 -0.261871337890625 -0.5321582031249976 -1.402875 -0.262359619140625 -0.5321582031249976 -1.403 -0.2628173828125 -0.5321582031249976 -1.403125 -0.2628173828125 -0.5321582031249976 -1.40325 -0.26324462890625 -0.5321582031249976 -1.403375 -0.26324462890625 -0.5321582031249976 -1.4035 -0.26361083984375 -0.5321582031249976 -1.403625 -0.26397705078125 -0.5321582031249976 -1.40375 -0.26397705078125 -0.5321582031249976 -1.403875 -0.264312744140625 -0.5321582031249976 -1.404 -0.264312744140625 -0.5321582031249976 -1.404125 -0.264617919921875 -0.5321582031249976 -1.40425 -0.264892578125 -0.5321582031249976 -1.404375 -0.264892578125 -0.5321582031249976 -1.4045 -0.265167236328125 -0.5321582031249976 -1.404625 -0.265167236328125 -0.5321582031249976 -1.40475 -0.265380859375 -0.5321582031249976 -1.404875 -0.26556396484375 -0.5321582031249976 -1.405 -0.26556396484375 -0.5321582031249976 -1.405125 -0.265716552734375 -0.5321582031249976 -1.40525 -0.265716552734375 -0.5321582031249976 -1.405375 -0.265869140625 -0.5321582031249976 -1.4055 -0.265960693359375 -0.5321582031249976 -1.405625 -0.265960693359375 -0.5321582031249976 -1.40575 -0.266021728515625 -0.5321582031249976 -1.405875 -0.266021728515625 -0.5321582031249976 -1.406 -0.266082763671875 -0.5321582031249976 -1.406125 -0.266082763671875 -0.5321582031249976 -1.40625 -0.266082763671875 -0.5321582031249976 -1.406375 -0.266082763671875 -0.5321582031249976 -1.4065 -0.266082763671875 -0.5321582031249976 -1.406625 -0.266021728515625 -0.5321582031249976 -1.40675 -0.265960693359375 -0.5321582031249976 -1.406875 -0.265960693359375 -0.5321582031249976 -1.407 -0.265869140625 -0.5321582031249976 -1.407125 -0.265869140625 -0.5321582031249976 -1.40725 -0.265716552734375 -0.5321582031249976 -1.407375 -0.26556396484375 -0.5321582031249976 -1.4075 -0.26556396484375 -0.5321582031249976 -1.407625 -0.265380859375 -0.5321582031249976 -1.40775 -0.265380859375 -0.5321582031249976 -1.407875 -0.265167236328125 -0.5321582031249976 -1.408 -0.17303466796875 -0.3476074218749959 -1.408125 -0.17303466796875 -0.3476074218749959 -1.40825 -0.1728515625 -0.3476074218749959 -1.408375 -0.1728515625 -0.3476074218749959 -1.4085 -0.172637939453125 -0.3476074218749959 -1.408625 -0.17242431640625 -0.3476074218749959 -1.40875 -0.17242431640625 -0.3476074218749959 -1.408875 -0.17218017578125 -0.3476074218749959 -1.409 -0.17218017578125 -0.3476074218749959 -1.409125 -0.17193603515625 -0.3476074218749959 -1.40925 -0.171661376953125 -0.3476074218749959 -1.409375 -0.171661376953125 -0.3476074218749959 -1.4095 -0.17138671875 -0.3476074218749959 -1.409625 -0.17138671875 -0.3476074218749959 -1.40975 -0.171051025390625 -0.3476074218749959 -1.409875 -0.17071533203125 -0.3476074218749959 -1.41 -0.17071533203125 -0.3476074218749959 -1.410125 -0.170379638671875 -0.3476074218749959 -1.41025 -0.170379638671875 -0.3476074218749959 -1.410375 -0.170013427734375 -0.3476074218749959 -1.4105 -0.16961669921875 -0.3476074218749959 -1.410625 -0.16961669921875 -0.3476074218749959 -1.41075 -0.169219970703125 -0.3476074218749959 -1.410875 -0.169219970703125 -0.3476074218749959 -1.411 -0.168792724609375 -0.3476074218749959 -1.411125 -0.1683349609375 -0.3476074218749959 -1.41125 -0.1683349609375 -0.3476074218749959 -1.411375 -0.167877197265625 -0.3476074218749959 -1.4115 -0.167877197265625 -0.3476074218749959 -1.411625 -0.167388916015625 -0.3476074218749959 -1.41175 -0.166900634765625 -0.3476074218749959 -1.411875 -0.166900634765625 -0.3476074218749959 -1.412 -0.1663818359375 -0.3476074218749959 -1.412125 -0.1663818359375 -0.3476074218749959 -1.41225 -0.165863037109375 -0.3476074218749959 -1.412375 -0.165313720703125 -0.3476074218749959 -1.4125 -0.165313720703125 -0.3476074218749959 -1.412625 -0.16473388671875 -0.3476074218749959 -1.41275 -0.16473388671875 -0.3476074218749959 -1.412875 -0.16412353515625 -0.3476074218749959 -1.413 -0.163543701171875 -0.3476074218749959 -1.413125 -0.163543701171875 -0.3476074218749959 -1.41325 -0.16290283203125 -0.3476074218749959 -1.413375 -0.16290283203125 -0.3476074218749959 -1.4135 -0.162261962890625 -0.3476074218749959 -1.413625 -0.161590576171875 -0.3476074218749959 -1.41375 -0.161590576171875 -0.3476074218749959 -1.413875 -0.160919189453125 -0.3476074218749959 -1.414 -0.160919189453125 -0.3476074218749959 -1.414125 -0.16021728515625 -0.3476074218749959 -1.41425 -0.159515380859375 -0.3476074218749959 -1.414375 -0.159515380859375 -0.3476074218749959 -1.4145 -0.158782958984375 -0.3476074218749959 -1.414625 -0.158782958984375 -0.3476074218749959 -1.41475 -0.15802001953125 -0.3476074218749959 -1.414875 -0.157257080078125 -0.3476074218749959 -1.415 -0.157257080078125 -0.3476074218749959 -1.415125 -0.156494140625 -0.3476074218749959 -1.41525 -0.156494140625 -0.3476074218749959 -1.415375 -0.155670166015625 -0.3476074218749959 -1.4155 -0.154876708984375 -0.3476074218749959 -1.415625 -0.154876708984375 -0.3476074218749959 -1.41575 -0.154022216796875 -0.3476074218749959 -1.415875 -0.154022216796875 -0.3476074218749959 -1.416 -0.153167724609375 -0.3476074218749959 -1.416125 -0.152313232421875 -0.3476074218749959 -1.41625 -0.152313232421875 -0.3476074218749959 -1.416375 -0.15142822265625 -0.3476074218749959 -1.4165 -0.15142822265625 -0.3476074218749959 -1.416625 -0.1505126953125 -0.3476074218749959 -1.41675 -0.14959716796875 -0.3476074218749959 -1.416875 -0.14959716796875 -0.3476074218749959 -1.417 -0.148681640625 -0.3476074218749959 -1.417125 -0.148681640625 -0.3476074218749959 -1.41725 -0.147705078125 -0.3476074218749959 -1.417375 -0.146759033203125 -0.3476074218749959 -1.4175 -0.146759033203125 -0.3476074218749959 -1.417625 -0.145751953125 -0.3476074218749959 -1.41775 -0.145751953125 -0.3476074218749959 -1.417875 -0.144775390625 -0.3476074218749959 -1.418 -0.14373779296875 -0.3476074218749959 -1.418125 -0.14373779296875 -0.3476074218749959 -1.41825 -0.142730712890625 -0.3476074218749959 -1.418375 -0.142730712890625 -0.3476074218749959 -1.4185 -0.14166259765625 -0.3476074218749959 -1.418625 -0.140625 -0.3476074218749959 -1.41875 -0.140625 -0.3476074218749959 -1.418875 -0.1395263671875 -0.3476074218749959 -1.419 -0.1395263671875 -0.3476074218749959 -1.419125 -0.138427734375 -0.3476074218749959 -1.41925 -0.1373291015625 -0.3476074218749959 -1.419375 -0.1373291015625 -0.3476074218749959 -1.4195 -0.136199951171875 -0.3476074218749959 -1.419625 -0.136199951171875 -0.3476074218749959 -1.41975 -0.13507080078125 -0.3476074218749959 -1.419875 -0.1339111328125 -0.3476074218749959 -1.42 -0.1339111328125 -0.3476074218749959 -1.420125 -0.13275146484375 -0.3476074218749959 -1.42025 -0.13275146484375 -0.3476074218749959 -1.420375 -0.131561279296875 -0.3476074218749959 -1.4205 -0.13037109375 -0.3476074218749959 -1.420625 -0.13037109375 -0.3476074218749959 -1.42075 -0.129150390625 -0.3476074218749959 -1.420875 -0.129150390625 -0.3476074218749959 -1.421 -0.1279296875 -0.3476074218749959 -1.421125 -0.126708984375 -0.3476074218749959 -1.42125 -0.126708984375 -0.3476074218749959 -1.421375 -0.125457763671875 -0.3476074218749959 -1.4215 -0.125457763671875 -0.3476074218749959 -1.421625 -0.124176025390625 -0.3476074218749959 -1.42175 -0.122894287109375 -0.3476074218749959 -1.421875 -0.122894287109375 -0.3476074218749959 -1.422 -0.121612548828125 -0.3476074218749959 -1.422125 -0.121612548828125 -0.3476074218749959 -1.42225 -0.12030029296875 -0.3476074218749959 -1.422375 -0.118988037109375 -0.3476074218749959 -1.4225 -0.118988037109375 -0.3476074218749959 -1.422625 -0.117645263671875 -0.3476074218749959 -1.42275 -0.117645263671875 -0.3476074218749959 -1.422875 -0.116302490234375 -0.3476074218749959 -1.423 -0.114959716796875 -0.3476074218749959 -1.423125 -0.114959716796875 -0.3476074218749959 -1.42325 -0.11358642578125 -0.3476074218749959 -1.423375 -0.11358642578125 -0.3476074218749959 -1.4235 -0.1121826171875 -0.3476074218749959 -1.423625 -0.11077880859375 -0.3476074218749959 -1.42375 -0.11077880859375 -0.3476074218749959 -1.423875 -0.109375 -0.3476074218749959 -1.424 -0.109375 -0.3476074218749959 -1.424125 -0.10797119140625 -0.3476074218749959 -1.42425 -0.106536865234375 -0.3476074218749959 -1.424375 -0.106536865234375 -0.3476074218749959 -1.4245 -0.105072021484375 -0.3476074218749959 -1.424625 -0.105072021484375 -0.3476074218749959 -1.42475 -0.1036376953125 -0.3476074218749959 -1.424875 -0.1021728515625 -0.3476074218749959 -1.425 -0.1021728515625 -0.3476074218749959 -1.425125 -0.100677490234375 -0.3476074218749959 -1.42525 -0.100677490234375 -0.3476074218749959 -1.425375 -0.099212646484375 -0.3476074218749959 -1.4255 -0.097686767578125 -0.3476074218749959 -1.425625 -0.097686767578125 -0.3476074218749959 -1.42575 -0.09619140625 -0.3476074218749959 -1.425875 -0.09619140625 -0.3476074218749959 -1.426 -0.09466552734375 -0.3476074218749959 -1.426125 -0.0931396484375 -0.3476074218749959 -1.42625 -0.0931396484375 -0.3476074218749959 -1.426375 -0.091583251953125 -0.3476074218749959 -1.4265 -0.091583251953125 -0.3476074218749959 -1.426625 -0.090057373046875 -0.3476074218749959 -1.42675 -0.088470458984375 -0.3476074218749959 -1.426875 -0.088470458984375 -0.3476074218749959 -1.427 -0.0869140625 -0.3476074218749959 -1.427125 -0.0869140625 -0.3476074218749959 -1.42725 -0.0853271484375 -0.3476074218749959 -1.427375 -0.083740234375 -0.3476074218749959 -1.4275 -0.083740234375 -0.3476074218749959 -1.427625 -0.0821533203125 -0.3476074218749959 -1.42775 -0.0821533203125 -0.3476074218749959 -1.427875 -0.080535888671875 -0.3476074218749959 -1.428 -0.07891845703125 -0.3476074218749959 -1.428125 -0.07891845703125 -0.3476074218749959 -1.42825 -0.077301025390625 -0.3476074218749959 -1.428375 -0.077301025390625 -0.3476074218749959 -1.4285 -0.075653076171875 -0.3476074218749959 -1.428625 -0.074005126953125 -0.3476074218749959 -1.42875 -0.074005126953125 -0.3476074218749959 -1.428875 -0.072357177734375 -0.3476074218749959 -1.429 -0.072357177734375 -0.3476074218749959 -1.429125 -0.070709228515625 -0.3476074218749959 -1.42925 -0.06903076171875 -0.3476074218749959 -1.429375 -0.06903076171875 -0.3476074218749959 -1.4295 -0.067352294921875 -0.3476074218749959 -1.429625 -0.067352294921875 -0.3476074218749959 -1.42975 -0.065673828125 -0.3476074218749959 -1.429875 -0.063995361328125 -0.3476074218749959 -1.43 -0.063995361328125 -0.3476074218749959 -1.430125 -0.062286376953125 -0.3476074218749959 -1.43025 -0.062286376953125 -0.3476074218749959 -1.430375 -0.060577392578125 -0.3476074218749959 -1.4305 -0.058868408203125 -0.3476074218749959 -1.430625 -0.058868408203125 -0.3476074218749959 -1.43075 -0.057159423828125 -0.3476074218749959 -1.430875 -0.057159423828125 -0.3476074218749959 -1.431 -0.055450439453125 -0.3476074218749959 -1.431125 -0.0537109375 -0.3476074218749959 -1.43125 -0.0537109375 -0.3476074218749959 -1.431375 -0.051971435546875 -0.3476074218749959 -1.4315 -0.051971435546875 -0.3476074218749959 -1.431625 -0.05023193359375 -0.3476074218749959 -1.43175 -0.048492431640625 -0.3476074218749959 -1.431875 -0.048492431640625 -0.3476074218749959 -1.432 -0.0467529296875 -0.3476074218749959 -1.432125 -0.0467529296875 -0.3476074218749959 -1.43225 -0.04498291015625 -0.3476074218749959 -1.432375 -0.043243408203125 -0.3476074218749959 -1.4325 -0.043243408203125 -0.3476074218749959 -1.432625 -0.041473388671875 -0.3476074218749959 -1.43275 -0.041473388671875 -0.3476074218749959 -1.432875 -0.039703369140625 -0.3476074218749959 -1.433 -0.037933349609375 -0.3476074218749959 -1.433125 -0.037933349609375 -0.3476074218749959 -1.43325 -0.0361328125 -0.3476074218749959 -1.433375 -0.0361328125 -0.3476074218749959 -1.4335 -0.03436279296875 -0.3476074218749959 -1.433625 -0.032562255859375 -0.3476074218749959 -1.43375 -0.032562255859375 -0.3476074218749959 -1.433875 -0.030792236328125 -0.3476074218749959 -1.434 -0.030792236328125 -0.3476074218749959 -1.434125 -0.02899169921875 -0.3476074218749959 -1.43425 -0.027191162109375 -0.3476074218749959 -1.434375 -0.027191162109375 -0.3476074218749959 -1.4345 -0.025390625 -0.3476074218749959 -1.434625 -0.025390625 -0.3476074218749959 -1.43475 -0.023590087890625 -0.3476074218749959 -1.434875 -0.02178955078125 -0.3476074218749959 -1.435 -0.02178955078125 -0.3476074218749959 -1.435125 -0.019989013671875 -0.3476074218749959 -1.43525 -0.019989013671875 -0.3476074218749959 -1.435375 -0.0181884765625 -0.3476074218749959 -1.4355 -0.016357421875 -0.3476074218749959 -1.435625 -0.016357421875 -0.3476074218749959 -1.43575 -0.014556884765625 -0.3476074218749959 -1.435875 -0.014556884765625 -0.3476074218749959 -1.436 -0.012725830078125 -0.3476074218749959 -1.436125 -0.01092529296875 -0.3476074218749959 -1.43625 -0.01092529296875 -0.3476074218749959 -1.436375 -0.00909423828125 -0.3476074218749959 -1.4365 -0.00909423828125 -0.3476074218749959 -1.436625 -0.007293701171875 -0.3476074218749959 -1.43675 -0.005462646484375 -0.3476074218749959 -1.436875 -0.005462646484375 -0.3476074218749959 -1.437 -0.003662109375 -0.3476074218749959 -1.437125 -0.003662109375 -0.3476074218749959 -1.43725 -0.0018310546875 -0.3476074218749959 +1.375125 -0.00311279296875 -0.5998974609374999 +1.37525 -0.00311279296875 -0.5998974609374999 +1.375375 -0.006256103515625 -0.5998974609374999 +1.3755 -0.0093994140625 -0.5998974609374999 +1.375625 -0.0093994140625 -0.5998974609374999 +1.37575 -0.012542724609375 -0.5998974609374999 +1.375875 -0.012542724609375 -0.5998974609374999 +1.376 -0.013916015625 -0.5321582031249976 +1.376125 -0.016693115234375 -0.5321582031249976 +1.37625 -0.016693115234375 -0.5321582031249976 +1.376375 -0.01947021484375 -0.5321582031249976 +1.3765 -0.01947021484375 -0.5321582031249976 +1.376625 -0.022247314453125 -0.5321582031249976 +1.37675 -0.0250244140625 -0.5321582031249976 +1.376875 -0.0250244140625 -0.5321582031249976 +1.377 -0.027801513671875 -0.5321582031249976 +1.377125 -0.027801513671875 -0.5321582031249976 +1.37725 -0.03057861328125 -0.5321582031249976 +1.377375 -0.0333251953125 -0.5321582031249976 +1.3775 -0.0333251953125 -0.5321582031249976 +1.377625 -0.036102294921875 -0.5321582031249976 +1.37775 -0.036102294921875 -0.5321582031249976 +1.377875 -0.038848876953125 -0.5321582031249976 +1.378 -0.041595458984375 -0.5321582031249976 +1.378125 -0.041595458984375 -0.5321582031249976 +1.37825 -0.044342041015625 -0.5321582031249976 +1.378375 -0.044342041015625 -0.5321582031249976 +1.3785 -0.047088623046875 -0.5321582031249976 +1.378625 -0.049835205078125 -0.5321582031249976 +1.37875 -0.049835205078125 -0.5321582031249976 +1.378875 -0.052581787109375 -0.5321582031249976 +1.379 -0.052581787109375 -0.5321582031249976 +1.379125 -0.0552978515625 -0.5321582031249976 +1.37925 -0.058013916015625 -0.5321582031249976 +1.379375 -0.058013916015625 -0.5321582031249976 +1.3795 -0.06072998046875 -0.5321582031249976 +1.379625 -0.06072998046875 -0.5321582031249976 +1.37975 -0.063446044921875 -0.5321582031249976 +1.379875 -0.066162109375 -0.5321582031249976 +1.38 -0.066162109375 -0.5321582031249976 +1.380125 -0.06884765625 -0.5321582031249976 +1.38025 -0.06884765625 -0.5321582031249976 +1.380375 -0.071533203125 -0.5321582031249976 +1.3805 -0.07421875 -0.5321582031249976 +1.380625 -0.07421875 -0.5321582031249976 +1.38075 -0.076873779296875 -0.5321582031249976 +1.380875 -0.076873779296875 -0.5321582031249976 +1.381 -0.079559326171875 -0.5321582031249976 +1.381125 -0.08221435546875 -0.5321582031249976 +1.38125 -0.08221435546875 -0.5321582031249976 +1.381375 -0.0848388671875 -0.5321582031249976 +1.3815 -0.0848388671875 -0.5321582031249976 +1.381625 -0.087493896484375 -0.5321582031249976 +1.38175 -0.090118408203125 -0.5321582031249976 +1.381875 -0.090118408203125 -0.5321582031249976 +1.382 -0.09271240234375 -0.5321582031249976 +1.382125 -0.09271240234375 -0.5321582031249976 +1.38225 -0.0953369140625 -0.5321582031249976 +1.382375 -0.097930908203125 -0.5321582031249976 +1.3825 -0.097930908203125 -0.5321582031249976 +1.382625 -0.10052490234375 -0.5321582031249976 +1.38275 -0.10052490234375 -0.5321582031249976 +1.382875 -0.10308837890625 -0.5321582031249976 +1.383 -0.10565185546875 -0.5321582031249976 +1.383125 -0.10565185546875 -0.5321582031249976 +1.38325 -0.10821533203125 -0.5321582031249976 +1.383375 -0.10821533203125 -0.5321582031249976 +1.3835 -0.110748291015625 -0.5321582031249976 +1.383625 -0.11328125 -0.5321582031249976 +1.38375 -0.11328125 -0.5321582031249976 +1.383875 -0.11578369140625 -0.5321582031249976 +1.384 -0.11578369140625 -0.5321582031249976 +1.384125 -0.1182861328125 -0.5321582031249976 +1.38425 -0.120758056640625 -0.5321582031249976 +1.384375 -0.120758056640625 -0.5321582031249976 +1.3845 -0.123260498046875 -0.5321582031249976 +1.384625 -0.123260498046875 -0.5321582031249976 +1.38475 -0.125732421875 -0.5321582031249976 +1.384875 -0.128173828125 -0.5321582031249976 +1.385 -0.128173828125 -0.5321582031249976 +1.385125 -0.130584716796875 -0.5321582031249976 +1.38525 -0.130584716796875 -0.5321582031249976 +1.385375 -0.133026123046875 -0.5321582031249976 +1.3855 -0.135406494140625 -0.5321582031249976 +1.385625 -0.135406494140625 -0.5321582031249976 +1.38575 -0.1378173828125 -0.5321582031249976 +1.385875 -0.1378173828125 -0.5321582031249976 +1.386 -0.14019775390625 -0.5321582031249976 +1.386125 -0.142547607421875 -0.5321582031249976 +1.38625 -0.142547607421875 -0.5321582031249976 +1.386375 -0.1448974609375 -0.5321582031249976 +1.3865 -0.1448974609375 -0.5321582031249976 +1.386625 -0.147216796875 -0.5321582031249976 +1.38675 -0.1495361328125 -0.5321582031249976 +1.386875 -0.1495361328125 -0.5321582031249976 +1.387 -0.151824951171875 -0.5321582031249976 +1.387125 -0.151824951171875 -0.5321582031249976 +1.38725 -0.15411376953125 -0.5321582031249976 +1.387375 -0.1563720703125 -0.5321582031249976 +1.3875 -0.1563720703125 -0.5321582031249976 +1.387625 -0.15863037109375 -0.5321582031249976 +1.38775 -0.15863037109375 -0.5321582031249976 +1.387875 -0.160858154296875 -0.5321582031249976 +1.388 -0.163055419921875 -0.5321582031249976 +1.388125 -0.163055419921875 -0.5321582031249976 +1.38825 -0.165252685546875 -0.5321582031249976 +1.388375 -0.165252685546875 -0.5321582031249976 +1.3885 -0.16741943359375 -0.5321582031249976 +1.388625 -0.169586181640625 -0.5321582031249976 +1.38875 -0.169586181640625 -0.5321582031249976 +1.388875 -0.171722412109375 -0.5321582031249976 +1.389 -0.171722412109375 -0.5321582031249976 +1.389125 -0.173828125 -0.5321582031249976 +1.38925 -0.175933837890625 -0.5321582031249976 +1.389375 -0.175933837890625 -0.5321582031249976 +1.3895 -0.178009033203125 -0.5321582031249976 +1.389625 -0.178009033203125 -0.5321582031249976 +1.38975 -0.180084228515625 -0.5321582031249976 +1.389875 -0.18212890625 -0.5321582031249976 +1.39 -0.18212890625 -0.5321582031249976 +1.390125 -0.18414306640625 -0.5321582031249976 +1.39025 -0.18414306640625 -0.5321582031249976 +1.390375 -0.186126708984375 -0.5321582031249976 +1.3905 -0.1881103515625 -0.5321582031249976 +1.390625 -0.1881103515625 -0.5321582031249976 +1.39075 -0.190093994140625 -0.5321582031249976 +1.390875 -0.190093994140625 -0.5321582031249976 +1.391 -0.1920166015625 -0.5321582031249976 +1.391125 -0.193939208984375 -0.5321582031249976 +1.39125 -0.193939208984375 -0.5321582031249976 +1.391375 -0.195831298828125 -0.5321582031249976 +1.3915 -0.195831298828125 -0.5321582031249976 +1.391625 -0.197723388671875 -0.5321582031249976 +1.39175 -0.199554443359375 -0.5321582031249976 +1.391875 -0.199554443359375 -0.5321582031249976 +1.392 -0.201385498046875 -0.5321582031249976 +1.392125 -0.201385498046875 -0.5321582031249976 +1.39225 -0.203216552734375 -0.5321582031249976 +1.392375 -0.204986572265625 -0.5321582031249976 +1.3925 -0.204986572265625 -0.5321582031249976 +1.392625 -0.206756591796875 -0.5321582031249976 +1.39275 -0.206756591796875 -0.5321582031249976 +1.392875 -0.20849609375 -0.5321582031249976 +1.393 -0.210235595703125 -0.5321582031249976 +1.393125 -0.210235595703125 -0.5321582031249976 +1.39325 -0.2119140625 -0.5321582031249976 +1.393375 -0.2119140625 -0.5321582031249976 +1.3935 -0.213592529296875 -0.5321582031249976 +1.393625 -0.215240478515625 -0.5321582031249976 +1.39375 -0.215240478515625 -0.5321582031249976 +1.393875 -0.21685791015625 -0.5321582031249976 +1.394 -0.21685791015625 -0.5321582031249976 +1.394125 -0.218475341796875 -0.5321582031249976 +1.39425 -0.22003173828125 -0.5321582031249976 +1.394375 -0.22003173828125 -0.5321582031249976 +1.3945 -0.221588134765625 -0.5321582031249976 +1.394625 -0.221588134765625 -0.5321582031249976 +1.39475 -0.223114013671875 -0.5321582031249976 +1.394875 -0.224639892578125 -0.5321582031249976 +1.395 -0.224639892578125 -0.5321582031249976 +1.395125 -0.226104736328125 -0.5321582031249976 +1.39525 -0.226104736328125 -0.5321582031249976 +1.395375 -0.227569580078125 -0.5321582031249976 +1.3955 -0.22900390625 -0.5321582031249976 +1.395625 -0.22900390625 -0.5321582031249976 +1.39575 -0.23040771484375 -0.5321582031249976 +1.395875 -0.23040771484375 -0.5321582031249976 +1.396 -0.231781005859375 -0.5321582031249976 +1.396125 -0.233154296875 -0.5321582031249976 +1.39625 -0.233154296875 -0.5321582031249976 +1.396375 -0.234466552734375 -0.5321582031249976 +1.3965 -0.234466552734375 -0.5321582031249976 +1.396625 -0.23577880859375 -0.5321582031249976 +1.39675 -0.237060546875 -0.5321582031249976 +1.396875 -0.237060546875 -0.5321582031249976 +1.397 -0.238311767578125 -0.5321582031249976 +1.397125 -0.238311767578125 -0.5321582031249976 +1.39725 -0.239532470703125 -0.5321582031249976 +1.397375 -0.24072265625 -0.5321582031249976 +1.3975 -0.24072265625 -0.5321582031249976 +1.397625 -0.241912841796875 -0.5321582031249976 +1.39775 -0.241912841796875 -0.5321582031249976 +1.397875 -0.2430419921875 -0.5321582031249976 +1.398 -0.244171142578125 -0.5321582031249976 +1.398125 -0.244171142578125 -0.5321582031249976 +1.39825 -0.245269775390625 -0.5321582031249976 +1.398375 -0.245269775390625 -0.5321582031249976 +1.3985 -0.246337890625 -0.5321582031249976 +1.398625 -0.24737548828125 -0.5321582031249976 +1.39875 -0.24737548828125 -0.5321582031249976 +1.398875 -0.248382568359375 -0.5321582031249976 +1.399 -0.248382568359375 -0.5321582031249976 +1.399125 -0.249359130859375 -0.5321582031249976 +1.39925 -0.250335693359375 -0.5321582031249976 +1.399375 -0.250335693359375 -0.5321582031249976 +1.3995 -0.251251220703125 -0.5321582031249976 +1.399625 -0.251251220703125 -0.5321582031249976 +1.39975 -0.252166748046875 -0.5321582031249976 +1.399875 -0.253021240234375 -0.5321582031249976 +1.4 -0.253021240234375 -0.5321582031249976 +1.400125 -0.253875732421875 -0.5321582031249976 +1.40025 -0.253875732421875 -0.5321582031249976 +1.400375 -0.25469970703125 -0.5321582031249976 +1.4005 -0.2554931640625 -0.5321582031249976 +1.400625 -0.2554931640625 -0.5321582031249976 +1.40075 -0.256256103515625 -0.5321582031249976 +1.400875 -0.256256103515625 -0.5321582031249976 +1.401 -0.256988525390625 -0.5321582031249976 +1.401125 -0.2576904296875 -0.5321582031249976 +1.40125 -0.2576904296875 -0.5321582031249976 +1.401375 -0.258392333984375 -0.5321582031249976 +1.4015 -0.258392333984375 -0.5321582031249976 +1.401625 -0.259033203125 -0.5321582031249976 +1.40175 -0.2596435546875 -0.5321582031249976 +1.401875 -0.2596435546875 -0.5321582031249976 +1.402 -0.260223388671875 -0.5321582031249976 +1.402125 -0.260223388671875 -0.5321582031249976 +1.40225 -0.26080322265625 -0.5321582031249976 +1.402375 -0.2613525390625 -0.5321582031249976 +1.4025 -0.2613525390625 -0.5321582031249976 +1.402625 -0.2618408203125 -0.5321582031249976 +1.40275 -0.2618408203125 -0.5321582031249976 +1.402875 -0.2623291015625 -0.5321582031249976 +1.403 -0.262786865234375 -0.5321582031249976 +1.403125 -0.262786865234375 -0.5321582031249976 +1.40325 -0.263214111328125 -0.5321582031249976 +1.403375 -0.263214111328125 -0.5321582031249976 +1.4035 -0.263580322265625 -0.5321582031249976 +1.403625 -0.263946533203125 -0.5321582031249976 +1.40375 -0.263946533203125 -0.5321582031249976 +1.403875 -0.2642822265625 -0.5321582031249976 +1.404 -0.2642822265625 -0.5321582031249976 +1.404125 -0.26458740234375 -0.5321582031249976 +1.40425 -0.264862060546875 -0.5321582031249976 +1.404375 -0.264862060546875 -0.5321582031249976 +1.4045 -0.26513671875 -0.5321582031249976 +1.404625 -0.26513671875 -0.5321582031249976 +1.40475 -0.265350341796875 -0.5321582031249976 +1.404875 -0.265533447265625 -0.5321582031249976 +1.405 -0.265533447265625 -0.5321582031249976 +1.405125 -0.26568603515625 -0.5321582031249976 +1.40525 -0.26568603515625 -0.5321582031249976 +1.405375 -0.265838623046875 -0.5321582031249976 +1.4055 -0.26593017578125 -0.5321582031249976 +1.405625 -0.26593017578125 -0.5321582031249976 +1.40575 -0.2659912109375 -0.5321582031249976 +1.405875 -0.2659912109375 -0.5321582031249976 +1.406 -0.26605224609375 -0.5321582031249976 +1.406125 -0.26605224609375 -0.5321582031249976 +1.40625 -0.26605224609375 -0.5321582031249976 +1.406375 -0.26605224609375 -0.5321582031249976 +1.4065 -0.26605224609375 -0.5321582031249976 +1.406625 -0.2659912109375 -0.5321582031249976 +1.40675 -0.26593017578125 -0.5321582031249976 +1.406875 -0.26593017578125 -0.5321582031249976 +1.407 -0.265838623046875 -0.5321582031249976 +1.407125 -0.265838623046875 -0.5321582031249976 +1.40725 -0.26568603515625 -0.5321582031249976 +1.407375 -0.265533447265625 -0.5321582031249976 +1.4075 -0.265533447265625 -0.5321582031249976 +1.407625 -0.265350341796875 -0.5321582031249976 +1.40775 -0.265350341796875 -0.5321582031249976 +1.407875 -0.26513671875 -0.5321582031249976 +1.408 -0.173004150390625 -0.3476074218749959 +1.408125 -0.173004150390625 -0.3476074218749959 +1.40825 -0.172821044921875 -0.3476074218749959 +1.408375 -0.172821044921875 -0.3476074218749959 +1.4085 -0.172607421875 -0.3476074218749959 +1.408625 -0.172393798828125 -0.3476074218749959 +1.40875 -0.172393798828125 -0.3476074218749959 +1.408875 -0.172149658203125 -0.3476074218749959 +1.409 -0.172149658203125 -0.3476074218749959 +1.409125 -0.171905517578125 -0.3476074218749959 +1.40925 -0.171630859375 -0.3476074218749959 +1.409375 -0.171630859375 -0.3476074218749959 +1.4095 -0.171356201171875 -0.3476074218749959 +1.409625 -0.171356201171875 -0.3476074218749959 +1.40975 -0.1710205078125 -0.3476074218749959 +1.409875 -0.170684814453125 -0.3476074218749959 +1.41 -0.170684814453125 -0.3476074218749959 +1.410125 -0.17034912109375 -0.3476074218749959 +1.41025 -0.17034912109375 -0.3476074218749959 +1.410375 -0.16998291015625 -0.3476074218749959 +1.4105 -0.169586181640625 -0.3476074218749959 +1.410625 -0.169586181640625 -0.3476074218749959 +1.41075 -0.169189453125 -0.3476074218749959 +1.410875 -0.169189453125 -0.3476074218749959 +1.411 -0.16876220703125 -0.3476074218749959 +1.411125 -0.168304443359375 -0.3476074218749959 +1.41125 -0.168304443359375 -0.3476074218749959 +1.411375 -0.1678466796875 -0.3476074218749959 +1.4115 -0.1678466796875 -0.3476074218749959 +1.411625 -0.1673583984375 -0.3476074218749959 +1.41175 -0.1668701171875 -0.3476074218749959 +1.411875 -0.1668701171875 -0.3476074218749959 +1.412 -0.166351318359375 -0.3476074218749959 +1.412125 -0.166351318359375 -0.3476074218749959 +1.41225 -0.16583251953125 -0.3476074218749959 +1.412375 -0.165283203125 -0.3476074218749959 +1.4125 -0.165283203125 -0.3476074218749959 +1.412625 -0.164703369140625 -0.3476074218749959 +1.41275 -0.164703369140625 -0.3476074218749959 +1.412875 -0.164093017578125 -0.3476074218749959 +1.413 -0.16351318359375 -0.3476074218749959 +1.413125 -0.16351318359375 -0.3476074218749959 +1.41325 -0.162872314453125 -0.3476074218749959 +1.413375 -0.162872314453125 -0.3476074218749959 +1.4135 -0.1622314453125 -0.3476074218749959 +1.413625 -0.16156005859375 -0.3476074218749959 +1.41375 -0.16156005859375 -0.3476074218749959 +1.413875 -0.160888671875 -0.3476074218749959 +1.414 -0.160888671875 -0.3476074218749959 +1.414125 -0.160186767578125 -0.3476074218749959 +1.41425 -0.15948486328125 -0.3476074218749959 +1.414375 -0.15948486328125 -0.3476074218749959 +1.4145 -0.15875244140625 -0.3476074218749959 +1.414625 -0.15875244140625 -0.3476074218749959 +1.41475 -0.157989501953125 -0.3476074218749959 +1.414875 -0.1572265625 -0.3476074218749959 +1.415 -0.1572265625 -0.3476074218749959 +1.415125 -0.156463623046875 -0.3476074218749959 +1.41525 -0.156463623046875 -0.3476074218749959 +1.415375 -0.1556396484375 -0.3476074218749959 +1.4155 -0.15484619140625 -0.3476074218749959 +1.415625 -0.15484619140625 -0.3476074218749959 +1.41575 -0.15399169921875 -0.3476074218749959 +1.415875 -0.15399169921875 -0.3476074218749959 +1.416 -0.15313720703125 -0.3476074218749959 +1.416125 -0.15228271484375 -0.3476074218749959 +1.41625 -0.15228271484375 -0.3476074218749959 +1.416375 -0.151397705078125 -0.3476074218749959 +1.4165 -0.151397705078125 -0.3476074218749959 +1.416625 -0.150482177734375 -0.3476074218749959 +1.41675 -0.149566650390625 -0.3476074218749959 +1.416875 -0.149566650390625 -0.3476074218749959 +1.417 -0.148651123046875 -0.3476074218749959 +1.417125 -0.148651123046875 -0.3476074218749959 +1.41725 -0.147674560546875 -0.3476074218749959 +1.417375 -0.146728515625 -0.3476074218749959 +1.4175 -0.146728515625 -0.3476074218749959 +1.417625 -0.145721435546875 -0.3476074218749959 +1.41775 -0.145721435546875 -0.3476074218749959 +1.417875 -0.144744873046875 -0.3476074218749959 +1.418 -0.143707275390625 -0.3476074218749959 +1.418125 -0.143707275390625 -0.3476074218749959 +1.41825 -0.1427001953125 -0.3476074218749959 +1.418375 -0.1427001953125 -0.3476074218749959 +1.4185 -0.141632080078125 -0.3476074218749959 +1.418625 -0.140594482421875 -0.3476074218749959 +1.41875 -0.140594482421875 -0.3476074218749959 +1.418875 -0.139495849609375 -0.3476074218749959 +1.419 -0.139495849609375 -0.3476074218749959 +1.419125 -0.138397216796875 -0.3476074218749959 +1.41925 -0.137298583984375 -0.3476074218749959 +1.419375 -0.137298583984375 -0.3476074218749959 +1.4195 -0.13616943359375 -0.3476074218749959 +1.419625 -0.13616943359375 -0.3476074218749959 +1.41975 -0.135040283203125 -0.3476074218749959 +1.419875 -0.133880615234375 -0.3476074218749959 +1.42 -0.133880615234375 -0.3476074218749959 +1.420125 -0.132720947265625 -0.3476074218749959 +1.42025 -0.132720947265625 -0.3476074218749959 +1.420375 -0.13153076171875 -0.3476074218749959 +1.4205 -0.130340576171875 -0.3476074218749959 +1.420625 -0.130340576171875 -0.3476074218749959 +1.42075 -0.129119873046875 -0.3476074218749959 +1.420875 -0.129119873046875 -0.3476074218749959 +1.421 -0.127899169921875 -0.3476074218749959 +1.421125 -0.126678466796875 -0.3476074218749959 +1.42125 -0.126678466796875 -0.3476074218749959 +1.421375 -0.12542724609375 -0.3476074218749959 +1.4215 -0.12542724609375 -0.3476074218749959 +1.421625 -0.1241455078125 -0.3476074218749959 +1.42175 -0.12286376953125 -0.3476074218749959 +1.421875 -0.12286376953125 -0.3476074218749959 +1.422 -0.12158203125 -0.3476074218749959 +1.422125 -0.12158203125 -0.3476074218749959 +1.42225 -0.120269775390625 -0.3476074218749959 +1.422375 -0.11895751953125 -0.3476074218749959 +1.4225 -0.11895751953125 -0.3476074218749959 +1.422625 -0.11761474609375 -0.3476074218749959 +1.42275 -0.11761474609375 -0.3476074218749959 +1.422875 -0.11627197265625 -0.3476074218749959 +1.423 -0.11492919921875 -0.3476074218749959 +1.423125 -0.11492919921875 -0.3476074218749959 +1.42325 -0.113555908203125 -0.3476074218749959 +1.423375 -0.113555908203125 -0.3476074218749959 +1.4235 -0.112152099609375 -0.3476074218749959 +1.423625 -0.110748291015625 -0.3476074218749959 +1.42375 -0.110748291015625 -0.3476074218749959 +1.423875 -0.109344482421875 -0.3476074218749959 +1.424 -0.109344482421875 -0.3476074218749959 +1.424125 -0.107940673828125 -0.3476074218749959 +1.42425 -0.10650634765625 -0.3476074218749959 +1.424375 -0.10650634765625 -0.3476074218749959 +1.4245 -0.10504150390625 -0.3476074218749959 +1.424625 -0.10504150390625 -0.3476074218749959 +1.42475 -0.103607177734375 -0.3476074218749959 +1.424875 -0.102142333984375 -0.3476074218749959 +1.425 -0.102142333984375 -0.3476074218749959 +1.425125 -0.10064697265625 -0.3476074218749959 +1.42525 -0.10064697265625 -0.3476074218749959 +1.425375 -0.09918212890625 -0.3476074218749959 +1.4255 -0.09765625 -0.3476074218749959 +1.425625 -0.09765625 -0.3476074218749959 +1.42575 -0.096160888671875 -0.3476074218749959 +1.425875 -0.096160888671875 -0.3476074218749959 +1.426 -0.094635009765625 -0.3476074218749959 +1.426125 -0.093109130859375 -0.3476074218749959 +1.42625 -0.093109130859375 -0.3476074218749959 +1.426375 -0.091552734375 -0.3476074218749959 +1.4265 -0.091552734375 -0.3476074218749959 +1.426625 -0.09002685546875 -0.3476074218749959 +1.42675 -0.08843994140625 -0.3476074218749959 +1.426875 -0.08843994140625 -0.3476074218749959 +1.427 -0.086883544921875 -0.3476074218749959 +1.427125 -0.086883544921875 -0.3476074218749959 +1.42725 -0.085296630859375 -0.3476074218749959 +1.427375 -0.083709716796875 -0.3476074218749959 +1.4275 -0.083709716796875 -0.3476074218749959 +1.427625 -0.082122802734375 -0.3476074218749959 +1.42775 -0.082122802734375 -0.3476074218749959 +1.427875 -0.08050537109375 -0.3476074218749959 +1.428 -0.078887939453125 -0.3476074218749959 +1.428125 -0.078887939453125 -0.3476074218749959 +1.42825 -0.0772705078125 -0.3476074218749959 +1.428375 -0.0772705078125 -0.3476074218749959 +1.4285 -0.07562255859375 -0.3476074218749959 +1.428625 -0.073974609375 -0.3476074218749959 +1.42875 -0.073974609375 -0.3476074218749959 +1.428875 -0.07232666015625 -0.3476074218749959 +1.429 -0.07232666015625 -0.3476074218749959 +1.429125 -0.0706787109375 -0.3476074218749959 +1.42925 -0.069000244140625 -0.3476074218749959 +1.429375 -0.069000244140625 -0.3476074218749959 +1.4295 -0.06732177734375 -0.3476074218749959 +1.429625 -0.06732177734375 -0.3476074218749959 +1.42975 -0.065643310546875 -0.3476074218749959 +1.429875 -0.06396484375 -0.3476074218749959 +1.43 -0.06396484375 -0.3476074218749959 +1.430125 -0.062255859375 -0.3476074218749959 +1.43025 -0.062255859375 -0.3476074218749959 +1.430375 -0.060546875 -0.3476074218749959 +1.4305 -0.058837890625 -0.3476074218749959 +1.430625 -0.058837890625 -0.3476074218749959 +1.43075 -0.05712890625 -0.3476074218749959 +1.430875 -0.05712890625 -0.3476074218749959 +1.431 -0.055419921875 -0.3476074218749959 +1.431125 -0.053680419921875 -0.3476074218749959 +1.43125 -0.053680419921875 -0.3476074218749959 +1.431375 -0.05194091796875 -0.3476074218749959 +1.4315 -0.05194091796875 -0.3476074218749959 +1.431625 -0.050201416015625 -0.3476074218749959 +1.43175 -0.0484619140625 -0.3476074218749959 +1.431875 -0.0484619140625 -0.3476074218749959 +1.432 -0.046722412109375 -0.3476074218749959 +1.432125 -0.046722412109375 -0.3476074218749959 +1.43225 -0.044952392578125 -0.3476074218749959 +1.432375 -0.043212890625 -0.3476074218749959 +1.4325 -0.043212890625 -0.3476074218749959 +1.432625 -0.04144287109375 -0.3476074218749959 +1.43275 -0.04144287109375 -0.3476074218749959 +1.432875 -0.0396728515625 -0.3476074218749959 +1.433 -0.03790283203125 -0.3476074218749959 +1.433125 -0.03790283203125 -0.3476074218749959 +1.43325 -0.036102294921875 -0.3476074218749959 +1.433375 -0.036102294921875 -0.3476074218749959 +1.4335 -0.034332275390625 -0.3476074218749959 +1.433625 -0.03253173828125 -0.3476074218749959 +1.43375 -0.03253173828125 -0.3476074218749959 +1.433875 -0.03076171875 -0.3476074218749959 +1.434 -0.03076171875 -0.3476074218749959 +1.434125 -0.028961181640625 -0.3476074218749959 +1.43425 -0.02716064453125 -0.3476074218749959 +1.434375 -0.02716064453125 -0.3476074218749959 +1.4345 -0.025360107421875 -0.3476074218749959 +1.434625 -0.025360107421875 -0.3476074218749959 +1.43475 -0.0235595703125 -0.3476074218749959 +1.434875 -0.021759033203125 -0.3476074218749959 +1.435 -0.021759033203125 -0.3476074218749959 +1.435125 -0.01995849609375 -0.3476074218749959 +1.43525 -0.01995849609375 -0.3476074218749959 +1.435375 -0.018157958984375 -0.3476074218749959 +1.4355 -0.016326904296875 -0.3476074218749959 +1.435625 -0.016326904296875 -0.3476074218749959 +1.43575 -0.0145263671875 -0.3476074218749959 +1.435875 -0.0145263671875 -0.3476074218749959 +1.436 -0.0126953125 -0.3476074218749959 +1.436125 -0.010894775390625 -0.3476074218749959 +1.43625 -0.010894775390625 -0.3476074218749959 +1.436375 -0.009063720703125 -0.3476074218749959 +1.4365 -0.009063720703125 -0.3476074218749959 +1.436625 -0.00726318359375 -0.3476074218749959 +1.43675 -0.00543212890625 -0.3476074218749959 +1.436875 -0.00543212890625 -0.3476074218749959 +1.437 -0.003631591796875 -0.3476074218749959 +1.437125 -0.003631591796875 -0.3476074218749959 +1.43725 -0.001800537109375 -0.3476074218749959 1.437375 0.0 -0.3476074218749959 1.4375 0.0 -0.3476074218749959 1.437625 0.001800537109375 -0.3476074218749959 @@ -11774,229 +11774,229 @@ 1.471625 0.03741455078125 -0.07568847656249394 1.47175 0.037353515625 -0.07568847656249394 1.471875 0.037353515625 -0.07568847656249394 -1.472 -0.118408203125 0.2401757812500067 -1.472125 -0.118408203125 0.2401757812500067 -1.47225 -0.118194580078125 0.2401757812500067 -1.472375 -0.117950439453125 0.2401757812500067 -1.4725 -0.117950439453125 0.2401757812500067 -1.472625 -0.117706298828125 0.2401757812500067 -1.47275 -0.117706298828125 0.2401757812500067 -1.472875 -0.117462158203125 0.2401757812500067 -1.473 -0.1171875 0.2401757812500067 -1.473125 -0.1171875 0.2401757812500067 -1.47325 -0.116912841796875 0.2401757812500067 -1.473375 -0.116912841796875 0.2401757812500067 -1.4735 -0.116607666015625 0.2401757812500067 -1.473625 -0.116302490234375 0.2401757812500067 -1.47375 -0.116302490234375 0.2401757812500067 -1.473875 -0.115997314453125 0.2401757812500067 -1.474 -0.115997314453125 0.2401757812500067 -1.474125 -0.11566162109375 0.2401757812500067 -1.47425 -0.115325927734375 0.2401757812500067 -1.474375 -0.115325927734375 0.2401757812500067 -1.4745 -0.114959716796875 0.2401757812500067 -1.474625 -0.114959716796875 0.2401757812500067 -1.47475 -0.114593505859375 0.2401757812500067 -1.474875 -0.11419677734375 0.2401757812500067 -1.475 -0.11419677734375 0.2401757812500067 -1.475125 -0.113800048828125 0.2401757812500067 -1.47525 -0.113800048828125 0.2401757812500067 -1.475375 -0.1134033203125 0.2401757812500067 -1.4755 -0.11297607421875 0.2401757812500067 -1.475625 -0.11297607421875 0.2401757812500067 -1.47575 -0.112548828125 0.2401757812500067 -1.475875 -0.112548828125 0.2401757812500067 -1.476 -0.112091064453125 0.2401757812500067 -1.476125 -0.11163330078125 0.2401757812500067 -1.47625 -0.11163330078125 0.2401757812500067 -1.476375 -0.111175537109375 0.2401757812500067 -1.4765 -0.111175537109375 0.2401757812500067 -1.476625 -0.110687255859375 0.2401757812500067 -1.47675 -0.110198974609375 0.2401757812500067 -1.476875 -0.110198974609375 0.2401757812500067 -1.477 -0.109710693359375 0.2401757812500067 -1.477125 -0.109710693359375 0.2401757812500067 -1.47725 -0.10919189453125 0.2401757812500067 -1.477375 -0.108642578125 0.2401757812500067 -1.4775 -0.108642578125 0.2401757812500067 -1.477625 -0.108123779296875 0.2401757812500067 -1.47775 -0.108123779296875 0.2401757812500067 -1.477875 -0.1075439453125 0.2401757812500067 -1.478 -0.10699462890625 0.2401757812500067 -1.478125 -0.10699462890625 0.2401757812500067 -1.47825 -0.106414794921875 0.2401757812500067 -1.478375 -0.106414794921875 0.2401757812500067 -1.4785 -0.1058349609375 0.2401757812500067 -1.478625 -0.105224609375 0.2401757812500067 -1.47875 -0.105224609375 0.2401757812500067 -1.478875 -0.1046142578125 0.2401757812500067 -1.479 -0.1046142578125 0.2401757812500067 -1.479125 -0.10400390625 0.2401757812500067 -1.47925 -0.103363037109375 0.2401757812500067 -1.479375 -0.103363037109375 0.2401757812500067 -1.4795 -0.10272216796875 0.2401757812500067 -1.479625 -0.10272216796875 0.2401757812500067 -1.47975 -0.10205078125 0.2401757812500067 -1.479875 -0.10137939453125 0.2401757812500067 -1.48 -0.10137939453125 0.2401757812500067 -1.480125 -0.1007080078125 0.2401757812500067 -1.48025 -0.1007080078125 0.2401757812500067 -1.480375 -0.100006103515625 0.2401757812500067 -1.4805 -0.09930419921875 0.2401757812500067 -1.480625 -0.09930419921875 0.2401757812500067 -1.48075 -0.098602294921875 0.2401757812500067 -1.480875 -0.098602294921875 0.2401757812500067 -1.481 -0.097869873046875 0.2401757812500067 -1.481125 -0.097137451171875 0.2401757812500067 -1.48125 -0.097137451171875 0.2401757812500067 -1.481375 -0.096405029296875 0.2401757812500067 -1.4815 -0.096405029296875 0.2401757812500067 -1.481625 -0.09564208984375 0.2401757812500067 -1.48175 -0.094879150390625 0.2401757812500067 -1.481875 -0.094879150390625 0.2401757812500067 -1.482 -0.0941162109375 0.2401757812500067 -1.482125 -0.0941162109375 0.2401757812500067 -1.48225 -0.09332275390625 0.2401757812500067 -1.482375 -0.092529296875 0.2401757812500067 -1.4825 -0.092529296875 0.2401757812500067 -1.482625 -0.09173583984375 0.2401757812500067 -1.48275 -0.09173583984375 0.2401757812500067 -1.482875 -0.090911865234375 0.2401757812500067 -1.483 -0.090087890625 0.2401757812500067 -1.483125 -0.090087890625 0.2401757812500067 -1.48325 -0.0892333984375 0.2401757812500067 -1.483375 -0.0892333984375 0.2401757812500067 -1.4835 -0.088409423828125 0.2401757812500067 -1.483625 -0.087554931640625 0.2401757812500067 -1.48375 -0.087554931640625 0.2401757812500067 -1.483875 -0.086669921875 0.2401757812500067 -1.484 -0.086669921875 0.2401757812500067 -1.484125 -0.085784912109375 0.2401757812500067 -1.48425 -0.08489990234375 0.2401757812500067 -1.484375 -0.08489990234375 0.2401757812500067 -1.4845 -0.084014892578125 0.2401757812500067 -1.484625 -0.084014892578125 0.2401757812500067 -1.48475 -0.0831298828125 0.2401757812500067 -1.484875 -0.08221435546875 0.2401757812500067 -1.485 -0.08221435546875 0.2401757812500067 -1.485125 -0.081298828125 0.2401757812500067 -1.48525 -0.081298828125 0.2401757812500067 -1.485375 -0.080352783203125 0.2401757812500067 -1.4855 -0.07940673828125 0.2401757812500067 -1.485625 -0.07940673828125 0.2401757812500067 -1.48575 -0.078460693359375 0.2401757812500067 -1.485875 -0.078460693359375 0.2401757812500067 -1.486 -0.0775146484375 0.2401757812500067 -1.486125 -0.0765380859375 0.2401757812500067 -1.48625 -0.0765380859375 0.2401757812500067 -1.486375 -0.0755615234375 0.2401757812500067 -1.4865 -0.0755615234375 0.2401757812500067 -1.486625 -0.0745849609375 0.2401757812500067 -1.48675 -0.0736083984375 0.2401757812500067 -1.486875 -0.0736083984375 0.2401757812500067 -1.487 -0.072601318359375 0.2401757812500067 -1.487125 -0.072601318359375 0.2401757812500067 -1.48725 -0.07159423828125 0.2401757812500067 -1.487375 -0.070587158203125 0.2401757812500067 -1.4875 -0.070587158203125 0.2401757812500067 -1.487625 -0.069580078125 0.2401757812500067 -1.48775 -0.069580078125 0.2401757812500067 -1.487875 -0.06854248046875 0.2401757812500067 -1.488 -0.0675048828125 0.2401757812500067 -1.488125 -0.0675048828125 0.2401757812500067 -1.48825 -0.06646728515625 0.2401757812500067 -1.488375 -0.06646728515625 0.2401757812500067 -1.4885 -0.065399169921875 0.2401757812500067 -1.488625 -0.064361572265625 0.2401757812500067 -1.48875 -0.064361572265625 0.2401757812500067 -1.488875 -0.06329345703125 0.2401757812500067 -1.489 -0.06329345703125 0.2401757812500067 -1.489125 -0.062225341796875 0.2401757812500067 -1.48925 -0.061126708984375 0.2401757812500067 -1.489375 -0.061126708984375 0.2401757812500067 -1.4895 -0.06005859375 0.2401757812500067 -1.489625 -0.06005859375 0.2401757812500067 -1.48975 -0.0589599609375 0.2401757812500067 -1.489875 -0.057861328125 0.2401757812500067 -1.49 -0.057861328125 0.2401757812500067 -1.490125 -0.0567626953125 0.2401757812500067 -1.49025 -0.0567626953125 0.2401757812500067 -1.490375 -0.055633544921875 0.2401757812500067 -1.4905 -0.054534912109375 0.2401757812500067 -1.490625 -0.054534912109375 0.2401757812500067 -1.49075 -0.05340576171875 0.2401757812500067 -1.490875 -0.05340576171875 0.2401757812500067 -1.491 -0.052276611328125 0.2401757812500067 -1.491125 -0.0511474609375 0.2401757812500067 -1.49125 -0.0511474609375 0.2401757812500067 -1.491375 -0.04998779296875 0.2401757812500067 -1.4915 -0.04998779296875 0.2401757812500067 -1.491625 -0.048858642578125 0.2401757812500067 -1.49175 -0.047698974609375 0.2401757812500067 -1.491875 -0.047698974609375 0.2401757812500067 -1.492 -0.046539306640625 0.2401757812500067 -1.492125 -0.046539306640625 0.2401757812500067 -1.49225 -0.045379638671875 0.2401757812500067 -1.492375 -0.044219970703125 0.2401757812500067 -1.4925 -0.044219970703125 0.2401757812500067 -1.492625 -0.04302978515625 0.2401757812500067 -1.49275 -0.04302978515625 0.2401757812500067 -1.492875 -0.0418701171875 0.2401757812500067 -1.493 -0.040679931640625 0.2401757812500067 -1.493125 -0.040679931640625 0.2401757812500067 -1.49325 -0.03948974609375 0.2401757812500067 -1.493375 -0.03948974609375 0.2401757812500067 -1.4935 -0.038299560546875 0.2401757812500067 -1.493625 -0.037109375 0.2401757812500067 -1.49375 -0.037109375 0.2401757812500067 -1.493875 -0.035919189453125 0.2401757812500067 -1.494 -0.035919189453125 0.2401757812500067 -1.494125 -0.03472900390625 0.2401757812500067 -1.49425 -0.03350830078125 0.2401757812500067 -1.494375 -0.03350830078125 0.2401757812500067 -1.4945 -0.03228759765625 0.2401757812500067 -1.494625 -0.03228759765625 0.2401757812500067 -1.49475 -0.031097412109375 0.2401757812500067 -1.494875 -0.029876708984375 0.2401757812500067 -1.495 -0.029876708984375 0.2401757812500067 -1.495125 -0.028656005859375 0.2401757812500067 -1.49525 -0.028656005859375 0.2401757812500067 -1.495375 -0.027435302734375 0.2401757812500067 -1.4955 -0.026214599609375 0.2401757812500067 -1.495625 -0.026214599609375 0.2401757812500067 -1.49575 -0.02496337890625 0.2401757812500067 -1.495875 -0.02496337890625 0.2401757812500067 -1.496 -0.02374267578125 0.2401757812500067 -1.496125 -0.02252197265625 0.2401757812500067 -1.49625 -0.02252197265625 0.2401757812500067 -1.496375 -0.021270751953125 0.2401757812500067 -1.4965 -0.021270751953125 0.2401757812500067 -1.496625 -0.020050048828125 0.2401757812500067 -1.49675 -0.018798828125 0.2401757812500067 -1.496875 -0.018798828125 0.2401757812500067 -1.497 -0.017547607421875 0.2401757812500067 -1.497125 -0.017547607421875 0.2401757812500067 -1.49725 -0.01629638671875 0.2401757812500067 -1.497375 -0.01507568359375 0.2401757812500067 -1.4975 -0.01507568359375 0.2401757812500067 -1.497625 -0.013824462890625 0.2401757812500067 -1.49775 -0.013824462890625 0.2401757812500067 -1.497875 -0.0125732421875 0.2401757812500067 -1.498 -0.011322021484375 0.2401757812500067 -1.498125 -0.011322021484375 0.2401757812500067 -1.49825 -0.01007080078125 0.2401757812500067 -1.498375 -0.01007080078125 0.2401757812500067 -1.4985 -0.008819580078125 0.2401757812500067 -1.498625 -0.007537841796875 0.2401757812500067 -1.49875 -0.007537841796875 0.2401757812500067 -1.498875 -0.00628662109375 0.2401757812500067 -1.499 -0.00628662109375 0.2401757812500067 -1.499125 -0.005035400390625 0.2401757812500067 -1.49925 -0.0037841796875 0.2401757812500067 -1.499375 -0.0037841796875 0.2401757812500067 -1.4995 -0.002532958984375 0.2401757812500067 -1.499625 -0.002532958984375 0.2401757812500067 -1.49975 -0.00128173828125 0.2401757812500067 +1.472 -0.118377685546875 0.2401757812500067 +1.472125 -0.118377685546875 0.2401757812500067 +1.47225 -0.1181640625 0.2401757812500067 +1.472375 -0.117919921875 0.2401757812500067 +1.4725 -0.117919921875 0.2401757812500067 +1.472625 -0.11767578125 0.2401757812500067 +1.47275 -0.11767578125 0.2401757812500067 +1.472875 -0.117431640625 0.2401757812500067 +1.473 -0.117156982421875 0.2401757812500067 +1.473125 -0.117156982421875 0.2401757812500067 +1.47325 -0.11688232421875 0.2401757812500067 +1.473375 -0.11688232421875 0.2401757812500067 +1.4735 -0.1165771484375 0.2401757812500067 +1.473625 -0.11627197265625 0.2401757812500067 +1.47375 -0.11627197265625 0.2401757812500067 +1.473875 -0.115966796875 0.2401757812500067 +1.474 -0.115966796875 0.2401757812500067 +1.474125 -0.115631103515625 0.2401757812500067 +1.47425 -0.11529541015625 0.2401757812500067 +1.474375 -0.11529541015625 0.2401757812500067 +1.4745 -0.11492919921875 0.2401757812500067 +1.474625 -0.11492919921875 0.2401757812500067 +1.47475 -0.11456298828125 0.2401757812500067 +1.474875 -0.114166259765625 0.2401757812500067 +1.475 -0.114166259765625 0.2401757812500067 +1.475125 -0.11376953125 0.2401757812500067 +1.47525 -0.11376953125 0.2401757812500067 +1.475375 -0.113372802734375 0.2401757812500067 +1.4755 -0.112945556640625 0.2401757812500067 +1.475625 -0.112945556640625 0.2401757812500067 +1.47575 -0.112518310546875 0.2401757812500067 +1.475875 -0.112518310546875 0.2401757812500067 +1.476 -0.112060546875 0.2401757812500067 +1.476125 -0.111602783203125 0.2401757812500067 +1.47625 -0.111602783203125 0.2401757812500067 +1.476375 -0.11114501953125 0.2401757812500067 +1.4765 -0.11114501953125 0.2401757812500067 +1.476625 -0.11065673828125 0.2401757812500067 +1.47675 -0.11016845703125 0.2401757812500067 +1.476875 -0.11016845703125 0.2401757812500067 +1.477 -0.10968017578125 0.2401757812500067 +1.477125 -0.10968017578125 0.2401757812500067 +1.47725 -0.109161376953125 0.2401757812500067 +1.477375 -0.108612060546875 0.2401757812500067 +1.4775 -0.108612060546875 0.2401757812500067 +1.477625 -0.10809326171875 0.2401757812500067 +1.47775 -0.10809326171875 0.2401757812500067 +1.477875 -0.107513427734375 0.2401757812500067 +1.478 -0.106964111328125 0.2401757812500067 +1.478125 -0.106964111328125 0.2401757812500067 +1.47825 -0.10638427734375 0.2401757812500067 +1.478375 -0.10638427734375 0.2401757812500067 +1.4785 -0.105804443359375 0.2401757812500067 +1.478625 -0.105194091796875 0.2401757812500067 +1.47875 -0.105194091796875 0.2401757812500067 +1.478875 -0.104583740234375 0.2401757812500067 +1.479 -0.104583740234375 0.2401757812500067 +1.479125 -0.103973388671875 0.2401757812500067 +1.47925 -0.10333251953125 0.2401757812500067 +1.479375 -0.10333251953125 0.2401757812500067 +1.4795 -0.102691650390625 0.2401757812500067 +1.479625 -0.102691650390625 0.2401757812500067 +1.47975 -0.102020263671875 0.2401757812500067 +1.479875 -0.101348876953125 0.2401757812500067 +1.48 -0.101348876953125 0.2401757812500067 +1.480125 -0.100677490234375 0.2401757812500067 +1.48025 -0.100677490234375 0.2401757812500067 +1.480375 -0.0999755859375 0.2401757812500067 +1.4805 -0.099273681640625 0.2401757812500067 +1.480625 -0.099273681640625 0.2401757812500067 +1.48075 -0.09857177734375 0.2401757812500067 +1.480875 -0.09857177734375 0.2401757812500067 +1.481 -0.09783935546875 0.2401757812500067 +1.481125 -0.09710693359375 0.2401757812500067 +1.48125 -0.09710693359375 0.2401757812500067 +1.481375 -0.09637451171875 0.2401757812500067 +1.4815 -0.09637451171875 0.2401757812500067 +1.481625 -0.095611572265625 0.2401757812500067 +1.48175 -0.0948486328125 0.2401757812500067 +1.481875 -0.0948486328125 0.2401757812500067 +1.482 -0.094085693359375 0.2401757812500067 +1.482125 -0.094085693359375 0.2401757812500067 +1.48225 -0.093292236328125 0.2401757812500067 +1.482375 -0.092498779296875 0.2401757812500067 +1.4825 -0.092498779296875 0.2401757812500067 +1.482625 -0.091705322265625 0.2401757812500067 +1.48275 -0.091705322265625 0.2401757812500067 +1.482875 -0.09088134765625 0.2401757812500067 +1.483 -0.090057373046875 0.2401757812500067 +1.483125 -0.090057373046875 0.2401757812500067 +1.48325 -0.089202880859375 0.2401757812500067 +1.483375 -0.089202880859375 0.2401757812500067 +1.4835 -0.08837890625 0.2401757812500067 +1.483625 -0.0875244140625 0.2401757812500067 +1.48375 -0.0875244140625 0.2401757812500067 +1.483875 -0.086639404296875 0.2401757812500067 +1.484 -0.086639404296875 0.2401757812500067 +1.484125 -0.08575439453125 0.2401757812500067 +1.48425 -0.084869384765625 0.2401757812500067 +1.484375 -0.084869384765625 0.2401757812500067 +1.4845 -0.083984375 0.2401757812500067 +1.484625 -0.083984375 0.2401757812500067 +1.48475 -0.083099365234375 0.2401757812500067 +1.484875 -0.082183837890625 0.2401757812500067 +1.485 -0.082183837890625 0.2401757812500067 +1.485125 -0.081268310546875 0.2401757812500067 +1.48525 -0.081268310546875 0.2401757812500067 +1.485375 -0.080322265625 0.2401757812500067 +1.4855 -0.079376220703125 0.2401757812500067 +1.485625 -0.079376220703125 0.2401757812500067 +1.48575 -0.07843017578125 0.2401757812500067 +1.485875 -0.07843017578125 0.2401757812500067 +1.486 -0.077484130859375 0.2401757812500067 +1.486125 -0.076507568359375 0.2401757812500067 +1.48625 -0.076507568359375 0.2401757812500067 +1.486375 -0.075531005859375 0.2401757812500067 +1.4865 -0.075531005859375 0.2401757812500067 +1.486625 -0.074554443359375 0.2401757812500067 +1.48675 -0.073577880859375 0.2401757812500067 +1.486875 -0.073577880859375 0.2401757812500067 +1.487 -0.07257080078125 0.2401757812500067 +1.487125 -0.07257080078125 0.2401757812500067 +1.48725 -0.071563720703125 0.2401757812500067 +1.487375 -0.070556640625 0.2401757812500067 +1.4875 -0.070556640625 0.2401757812500067 +1.487625 -0.069549560546875 0.2401757812500067 +1.48775 -0.069549560546875 0.2401757812500067 +1.487875 -0.068511962890625 0.2401757812500067 +1.488 -0.067474365234375 0.2401757812500067 +1.488125 -0.067474365234375 0.2401757812500067 +1.48825 -0.066436767578125 0.2401757812500067 +1.488375 -0.066436767578125 0.2401757812500067 +1.4885 -0.06536865234375 0.2401757812500067 +1.488625 -0.0643310546875 0.2401757812500067 +1.48875 -0.0643310546875 0.2401757812500067 +1.488875 -0.063262939453125 0.2401757812500067 +1.489 -0.063262939453125 0.2401757812500067 +1.489125 -0.06219482421875 0.2401757812500067 +1.48925 -0.06109619140625 0.2401757812500067 +1.489375 -0.06109619140625 0.2401757812500067 +1.4895 -0.060028076171875 0.2401757812500067 +1.489625 -0.060028076171875 0.2401757812500067 +1.48975 -0.058929443359375 0.2401757812500067 +1.489875 -0.057830810546875 0.2401757812500067 +1.49 -0.057830810546875 0.2401757812500067 +1.490125 -0.056732177734375 0.2401757812500067 +1.49025 -0.056732177734375 0.2401757812500067 +1.490375 -0.05560302734375 0.2401757812500067 +1.4905 -0.05450439453125 0.2401757812500067 +1.490625 -0.05450439453125 0.2401757812500067 +1.49075 -0.053375244140625 0.2401757812500067 +1.490875 -0.053375244140625 0.2401757812500067 +1.491 -0.05224609375 0.2401757812500067 +1.491125 -0.051116943359375 0.2401757812500067 +1.49125 -0.051116943359375 0.2401757812500067 +1.491375 -0.049957275390625 0.2401757812500067 +1.4915 -0.049957275390625 0.2401757812500067 +1.491625 -0.048828125 0.2401757812500067 +1.49175 -0.04766845703125 0.2401757812500067 +1.491875 -0.04766845703125 0.2401757812500067 +1.492 -0.0465087890625 0.2401757812500067 +1.492125 -0.0465087890625 0.2401757812500067 +1.49225 -0.04534912109375 0.2401757812500067 +1.492375 -0.044189453125 0.2401757812500067 +1.4925 -0.044189453125 0.2401757812500067 +1.492625 -0.042999267578125 0.2401757812500067 +1.49275 -0.042999267578125 0.2401757812500067 +1.492875 -0.041839599609375 0.2401757812500067 +1.493 -0.0406494140625 0.2401757812500067 +1.493125 -0.0406494140625 0.2401757812500067 +1.49325 -0.039459228515625 0.2401757812500067 +1.493375 -0.039459228515625 0.2401757812500067 +1.4935 -0.03826904296875 0.2401757812500067 +1.493625 -0.037078857421875 0.2401757812500067 +1.49375 -0.037078857421875 0.2401757812500067 +1.493875 -0.035888671875 0.2401757812500067 +1.494 -0.035888671875 0.2401757812500067 +1.494125 -0.034698486328125 0.2401757812500067 +1.49425 -0.033477783203125 0.2401757812500067 +1.494375 -0.033477783203125 0.2401757812500067 +1.4945 -0.032257080078125 0.2401757812500067 +1.494625 -0.032257080078125 0.2401757812500067 +1.49475 -0.03106689453125 0.2401757812500067 +1.494875 -0.02984619140625 0.2401757812500067 +1.495 -0.02984619140625 0.2401757812500067 +1.495125 -0.02862548828125 0.2401757812500067 +1.49525 -0.02862548828125 0.2401757812500067 +1.495375 -0.02740478515625 0.2401757812500067 +1.4955 -0.02618408203125 0.2401757812500067 +1.495625 -0.02618408203125 0.2401757812500067 +1.49575 -0.024932861328125 0.2401757812500067 +1.495875 -0.024932861328125 0.2401757812500067 +1.496 -0.023712158203125 0.2401757812500067 +1.496125 -0.022491455078125 0.2401757812500067 +1.49625 -0.022491455078125 0.2401757812500067 +1.496375 -0.021240234375 0.2401757812500067 +1.4965 -0.021240234375 0.2401757812500067 +1.496625 -0.02001953125 0.2401757812500067 +1.49675 -0.018768310546875 0.2401757812500067 +1.496875 -0.018768310546875 0.2401757812500067 +1.497 -0.01751708984375 0.2401757812500067 +1.497125 -0.01751708984375 0.2401757812500067 +1.49725 -0.016265869140625 0.2401757812500067 +1.497375 -0.015045166015625 0.2401757812500067 +1.4975 -0.015045166015625 0.2401757812500067 +1.497625 -0.0137939453125 0.2401757812500067 +1.49775 -0.0137939453125 0.2401757812500067 +1.497875 -0.012542724609375 0.2401757812500067 +1.498 -0.01129150390625 0.2401757812500067 +1.498125 -0.01129150390625 0.2401757812500067 +1.49825 -0.010040283203125 0.2401757812500067 +1.498375 -0.010040283203125 0.2401757812500067 +1.4985 -0.0087890625 0.2401757812500067 +1.498625 -0.00750732421875 0.2401757812500067 +1.49875 -0.00750732421875 0.2401757812500067 +1.498875 -0.006256103515625 0.2401757812500067 +1.499 -0.006256103515625 0.2401757812500067 +1.499125 -0.0050048828125 0.2401757812500067 +1.49925 -0.003753662109375 0.2401757812500067 +1.499375 -0.003753662109375 0.2401757812500067 +1.4995 -0.00250244140625 0.2401757812500067 +1.499625 -0.00250244140625 0.2401757812500067 +1.49975 -0.001251220703125 0.2401757812500067 1.499875 0.0 0.2401757812500067 1.5 0.0 0.2401757812500067 1.500125 0.001251220703125 0.2401757812500067 @@ -12499,504 +12499,504 @@ 1.56225 0.004180908203125 0.8033593750000046 1.562375 0.0 0.8033593750000046 1.5625 0.0 0.8033593750000046 -1.562625 -0.00421142578125 0.8033593750000046 -1.56275 -0.00421142578125 0.8033593750000046 -1.562875 -0.0084228515625 0.8033593750000046 -1.563 -0.01263427734375 0.8033593750000046 -1.563125 -0.01263427734375 0.8033593750000046 -1.56325 -0.016845703125 0.8033593750000046 -1.563375 -0.016845703125 0.8033593750000046 -1.5635 -0.021026611328125 0.8033593750000046 -1.563625 -0.025238037109375 0.8033593750000046 -1.56375 -0.025238037109375 0.8033593750000046 -1.563875 -0.0294189453125 0.8033593750000046 -1.564 -0.0294189453125 0.8033593750000046 -1.564125 -0.033599853515625 0.8033593750000046 -1.56425 -0.037811279296875 0.8033593750000046 -1.564375 -0.037811279296875 0.8033593750000046 -1.5645 -0.0419921875 0.8033593750000046 -1.564625 -0.0419921875 0.8033593750000046 -1.56475 -0.046173095703125 0.8033593750000046 -1.564875 -0.05035400390625 0.8033593750000046 -1.565 -0.05035400390625 0.8033593750000046 -1.565125 -0.05450439453125 0.8033593750000046 -1.56525 -0.05450439453125 0.8033593750000046 -1.565375 -0.058685302734375 0.8033593750000046 -1.5655 -0.062835693359375 0.8033593750000046 -1.565625 -0.062835693359375 0.8033593750000046 -1.56575 -0.066986083984375 0.8033593750000046 -1.565875 -0.066986083984375 0.8033593750000046 -1.566 -0.071136474609375 0.8033593750000046 -1.566125 -0.07525634765625 0.8033593750000046 -1.56625 -0.07525634765625 0.8033593750000046 -1.566375 -0.07940673828125 0.8033593750000046 -1.5665 -0.07940673828125 0.8033593750000046 -1.566625 -0.083526611328125 0.8033593750000046 -1.56675 -0.087615966796875 0.8033593750000046 -1.566875 -0.087615966796875 0.8033593750000046 -1.567 -0.09173583984375 0.8033593750000046 -1.567125 -0.09173583984375 0.8033593750000046 -1.56725 -0.0958251953125 0.8033593750000046 -1.567375 -0.099884033203125 0.8033593750000046 -1.5675 -0.099884033203125 0.8033593750000046 -1.567625 -0.103973388671875 0.8033593750000046 -1.56775 -0.103973388671875 0.8033593750000046 -1.567875 -0.1080322265625 0.8033593750000046 -1.568 -0.134033203125 0.960815429687502 -1.568125 -0.134033203125 0.960815429687502 -1.56825 -0.13885498046875 0.960815429687502 -1.568375 -0.13885498046875 0.960815429687502 -1.5685 -0.143646240234375 0.960815429687502 -1.568625 -0.1484375 0.960815429687502 -1.56875 -0.1484375 0.960815429687502 -1.568875 -0.153228759765625 0.960815429687502 -1.569 -0.153228759765625 0.960815429687502 -1.569125 -0.157989501953125 0.960815429687502 -1.56925 -0.1627197265625 0.960815429687502 -1.569375 -0.1627197265625 0.960815429687502 -1.5695 -0.167449951171875 0.960815429687502 -1.569625 -0.167449951171875 0.960815429687502 -1.56975 -0.172149658203125 0.960815429687502 -1.569875 -0.176849365234375 0.960815429687502 -1.57 -0.176849365234375 0.960815429687502 -1.570125 -0.1815185546875 0.960815429687502 -1.57025 -0.1815185546875 0.960815429687502 -1.570375 -0.1861572265625 0.960815429687502 -1.5705 -0.1907958984375 0.960815429687502 -1.570625 -0.1907958984375 0.960815429687502 -1.57075 -0.195404052734375 0.960815429687502 -1.570875 -0.195404052734375 0.960815429687502 -1.571 -0.199981689453125 0.960815429687502 -1.571125 -0.20452880859375 0.960815429687502 -1.57125 -0.20452880859375 0.960815429687502 -1.571375 -0.209075927734375 0.960815429687502 -1.5715 -0.209075927734375 0.960815429687502 -1.571625 -0.213592529296875 0.960815429687502 -1.57175 -0.21807861328125 0.960815429687502 -1.571875 -0.21807861328125 0.960815429687502 -1.572 -0.222564697265625 0.960815429687502 -1.572125 -0.222564697265625 0.960815429687502 -1.57225 -0.227020263671875 0.960815429687502 -1.572375 -0.231414794921875 0.960815429687502 -1.5725 -0.231414794921875 0.960815429687502 -1.572625 -0.23583984375 0.960815429687502 -1.57275 -0.23583984375 0.960815429687502 -1.572875 -0.240203857421875 0.960815429687502 -1.573 -0.244537353515625 0.960815429687502 -1.573125 -0.244537353515625 0.960815429687502 -1.57325 -0.248870849609375 0.960815429687502 -1.573375 -0.248870849609375 0.960815429687502 -1.5735 -0.253143310546875 0.960815429687502 -1.573625 -0.257415771484375 0.960815429687502 -1.57375 -0.257415771484375 0.960815429687502 -1.573875 -0.26165771484375 0.960815429687502 -1.574 -0.26165771484375 0.960815429687502 -1.574125 -0.265838623046875 0.960815429687502 -1.57425 -0.27001953125 0.960815429687502 -1.574375 -0.27001953125 0.960815429687502 -1.5745 -0.274169921875 0.960815429687502 -1.574625 -0.274169921875 0.960815429687502 -1.57475 -0.278289794921875 0.960815429687502 -1.574875 -0.2823486328125 0.960815429687502 -1.575 -0.2823486328125 0.960815429687502 -1.575125 -0.286407470703125 0.960815429687502 -1.57525 -0.286407470703125 0.960815429687502 -1.575375 -0.290435791015625 0.960815429687502 -1.5755 -0.29443359375 0.960815429687502 -1.575625 -0.29443359375 0.960815429687502 -1.57575 -0.29840087890625 0.960815429687502 -1.575875 -0.29840087890625 0.960815429687502 -1.576 -0.30230712890625 0.960815429687502 -1.576125 -0.30621337890625 0.960815429687502 -1.57625 -0.30621337890625 0.960815429687502 -1.576375 -0.31005859375 0.960815429687502 -1.5765 -0.31005859375 0.960815429687502 -1.576625 -0.31390380859375 0.960815429687502 -1.57675 -0.31768798828125 0.960815429687502 -1.576875 -0.31768798828125 0.960815429687502 -1.577 -0.321441650390625 0.960815429687502 -1.577125 -0.321441650390625 0.960815429687502 -1.57725 -0.325164794921875 0.960815429687502 -1.577375 -0.328857421875 0.960815429687502 -1.5775 -0.328857421875 0.960815429687502 -1.577625 -0.332489013671875 0.960815429687502 -1.57775 -0.332489013671875 0.960815429687502 -1.577875 -0.336090087890625 0.960815429687502 -1.578 -0.339691162109375 0.960815429687502 -1.578125 -0.339691162109375 0.960815429687502 -1.57825 -0.343231201171875 0.960815429687502 -1.578375 -0.343231201171875 0.960815429687502 -1.5785 -0.346710205078125 0.960815429687502 -1.578625 -0.350189208984375 0.960815429687502 -1.57875 -0.350189208984375 0.960815429687502 -1.578875 -0.353607177734375 0.960815429687502 -1.579 -0.353607177734375 0.960815429687502 -1.579125 -0.35699462890625 0.960815429687502 -1.57925 -0.3603515625 0.960815429687502 -1.579375 -0.3603515625 0.960815429687502 -1.5795 -0.3636474609375 0.960815429687502 -1.579625 -0.3636474609375 0.960815429687502 -1.57975 -0.366912841796875 0.960815429687502 -1.579875 -0.370147705078125 0.960815429687502 -1.58 -0.370147705078125 0.960815429687502 -1.580125 -0.373321533203125 0.960815429687502 -1.58025 -0.373321533203125 0.960815429687502 -1.580375 -0.37646484375 0.960815429687502 -1.5805 -0.37957763671875 0.960815429687502 -1.580625 -0.37957763671875 0.960815429687502 -1.58075 -0.38262939453125 0.960815429687502 -1.580875 -0.38262939453125 0.960815429687502 -1.581 -0.385650634765625 0.960815429687502 -1.581125 -0.388641357421875 0.960815429687502 -1.58125 -0.388641357421875 0.960815429687502 -1.581375 -0.391571044921875 0.960815429687502 -1.5815 -0.391571044921875 0.960815429687502 -1.581625 -0.39447021484375 0.960815429687502 -1.58175 -0.397308349609375 0.960815429687502 -1.581875 -0.397308349609375 0.960815429687502 -1.582 -0.400115966796875 0.960815429687502 -1.582125 -0.400115966796875 0.960815429687502 -1.58225 -0.40289306640625 0.960815429687502 -1.582375 -0.405609130859375 0.960815429687502 -1.5825 -0.405609130859375 0.960815429687502 -1.582625 -0.40826416015625 0.960815429687502 -1.58275 -0.40826416015625 0.960815429687502 -1.582875 -0.410888671875 0.960815429687502 -1.583 -0.413482666015625 0.960815429687502 -1.583125 -0.413482666015625 0.960815429687502 -1.58325 -0.416046142578125 0.960815429687502 -1.583375 -0.416046142578125 0.960815429687502 -1.5835 -0.41851806640625 0.960815429687502 -1.583625 -0.42095947265625 0.960815429687502 -1.58375 -0.42095947265625 0.960815429687502 -1.583875 -0.423370361328125 0.960815429687502 -1.584 -0.423370361328125 0.960815429687502 -1.584125 -0.42572021484375 0.960815429687502 -1.58425 -0.42803955078125 0.960815429687502 -1.584375 -0.42803955078125 0.960815429687502 -1.5845 -0.4302978515625 0.960815429687502 -1.584625 -0.4302978515625 0.960815429687502 -1.58475 -0.4324951171875 0.960815429687502 -1.584875 -0.434661865234375 0.960815429687502 -1.585 -0.434661865234375 0.960815429687502 -1.585125 -0.436767578125 0.960815429687502 -1.58525 -0.436767578125 0.960815429687502 -1.585375 -0.438873291015625 0.960815429687502 -1.5855 -0.440887451171875 0.960815429687502 -1.585625 -0.440887451171875 0.960815429687502 -1.58575 -0.442840576171875 0.960815429687502 -1.585875 -0.442840576171875 0.960815429687502 -1.586 -0.444793701171875 0.960815429687502 -1.586125 -0.4466552734375 0.960815429687502 -1.58625 -0.4466552734375 0.960815429687502 -1.586375 -0.448486328125 0.960815429687502 -1.5865 -0.448486328125 0.960815429687502 -1.586625 -0.45025634765625 0.960815429687502 -1.58675 -0.451995849609375 0.960815429687502 -1.586875 -0.451995849609375 0.960815429687502 -1.587 -0.45367431640625 0.960815429687502 -1.587125 -0.45367431640625 0.960815429687502 -1.58725 -0.455291748046875 0.960815429687502 -1.587375 -0.456878662109375 0.960815429687502 -1.5875 -0.456878662109375 0.960815429687502 -1.587625 -0.458404541015625 0.960815429687502 -1.58775 -0.458404541015625 0.960815429687502 -1.587875 -0.459869384765625 0.960815429687502 -1.588 -0.4613037109375 0.960815429687502 -1.588125 -0.4613037109375 0.960815429687502 -1.58825 -0.462677001953125 0.960815429687502 -1.588375 -0.462677001953125 0.960815429687502 -1.5885 -0.464019775390625 0.960815429687502 -1.588625 -0.465301513671875 0.960815429687502 -1.58875 -0.465301513671875 0.960815429687502 -1.588875 -0.466522216796875 0.960815429687502 -1.589 -0.466522216796875 0.960815429687502 -1.589125 -0.467681884765625 0.960815429687502 -1.58925 -0.46881103515625 0.960815429687502 -1.589375 -0.46881103515625 0.960815429687502 -1.5895 -0.469879150390625 0.960815429687502 -1.589625 -0.469879150390625 0.960815429687502 -1.58975 -0.470916748046875 0.960815429687502 -1.589875 -0.47186279296875 0.960815429687502 -1.59 -0.47186279296875 0.960815429687502 -1.590125 -0.472808837890625 0.960815429687502 -1.59025 -0.472808837890625 0.960815429687502 -1.590375 -0.473663330078125 0.960815429687502 -1.5905 -0.474456787109375 0.960815429687502 -1.590625 -0.474456787109375 0.960815429687502 -1.59075 -0.4752197265625 0.960815429687502 -1.590875 -0.4752197265625 0.960815429687502 -1.591 -0.475921630859375 0.960815429687502 -1.591125 -0.476593017578125 0.960815429687502 -1.59125 -0.476593017578125 0.960815429687502 -1.591375 -0.477203369140625 0.960815429687502 -1.5915 -0.477203369140625 0.960815429687502 -1.591625 -0.477752685546875 0.960815429687502 -1.59175 -0.478240966796875 0.960815429687502 -1.591875 -0.478240966796875 0.960815429687502 -1.592 -0.47869873046875 0.960815429687502 -1.592125 -0.47869873046875 0.960815429687502 -1.59225 -0.479095458984375 0.960815429687502 -1.592375 -0.47943115234375 0.960815429687502 -1.5925 -0.47943115234375 0.960815429687502 -1.592625 -0.479736328125 0.960815429687502 -1.59275 -0.479736328125 0.960815429687502 -1.592875 -0.47998046875 0.960815429687502 -1.593 -0.480133056640625 0.960815429687502 -1.593125 -0.480133056640625 0.960815429687502 -1.59325 -0.48028564453125 0.960815429687502 -1.593375 -0.48028564453125 0.960815429687502 -1.5935 -0.480377197265625 0.960815429687502 -1.593625 -0.48040771484375 0.960815429687502 -1.59375 -0.48040771484375 0.960815429687502 -1.593875 -0.480377197265625 0.960815429687502 -1.594 -0.480377197265625 0.960815429687502 -1.594125 -0.48028564453125 0.960815429687502 -1.59425 -0.480133056640625 0.960815429687502 -1.594375 -0.480133056640625 0.960815429687502 -1.5945 -0.47998046875 0.960815429687502 -1.594625 -0.47998046875 0.960815429687502 -1.59475 -0.479736328125 0.960815429687502 -1.594875 -0.47943115234375 0.960815429687502 -1.595 -0.47943115234375 0.960815429687502 -1.595125 -0.479095458984375 0.960815429687502 -1.59525 -0.479095458984375 0.960815429687502 -1.595375 -0.47869873046875 0.960815429687502 -1.5955 -0.478240966796875 0.960815429687502 -1.595625 -0.478240966796875 0.960815429687502 -1.59575 -0.477752685546875 0.960815429687502 -1.595875 -0.477752685546875 0.960815429687502 -1.596 -0.477203369140625 0.960815429687502 -1.596125 -0.476593017578125 0.960815429687502 -1.59625 -0.476593017578125 0.960815429687502 -1.596375 -0.475921630859375 0.960815429687502 -1.5965 -0.475921630859375 0.960815429687502 -1.596625 -0.4752197265625 0.960815429687502 -1.59675 -0.474456787109375 0.960815429687502 -1.596875 -0.474456787109375 0.960815429687502 -1.597 -0.473663330078125 0.960815429687502 -1.597125 -0.473663330078125 0.960815429687502 -1.59725 -0.472808837890625 0.960815429687502 -1.597375 -0.47186279296875 0.960815429687502 -1.5975 -0.47186279296875 0.960815429687502 -1.597625 -0.470916748046875 0.960815429687502 -1.59775 -0.470916748046875 0.960815429687502 -1.597875 -0.469879150390625 0.960815429687502 -1.598 -0.46881103515625 0.960815429687502 -1.598125 -0.46881103515625 0.960815429687502 -1.59825 -0.467681884765625 0.960815429687502 -1.598375 -0.467681884765625 0.960815429687502 -1.5985 -0.466522216796875 0.960815429687502 -1.598625 -0.465301513671875 0.960815429687502 -1.59875 -0.465301513671875 0.960815429687502 -1.598875 -0.464019775390625 0.960815429687502 -1.599 -0.464019775390625 0.960815429687502 -1.599125 -0.462677001953125 0.960815429687502 -1.59925 -0.4613037109375 0.960815429687502 -1.599375 -0.4613037109375 0.960815429687502 -1.5995 -0.459869384765625 0.960815429687502 -1.599625 -0.459869384765625 0.960815429687502 -1.59975 -0.458404541015625 0.960815429687502 -1.599875 -0.456878662109375 0.960815429687502 -1.6 -0.474029541015625 0.9968652343749994 -1.600125 -0.472381591796875 0.9968652343749994 -1.60025 -0.472381591796875 0.9968652343749994 -1.600375 -0.470672607421875 0.9968652343749994 -1.6005 -0.46893310546875 0.9968652343749994 -1.600625 -0.46893310546875 0.9968652343749994 -1.60075 -0.467132568359375 0.9968652343749994 -1.600875 -0.467132568359375 0.9968652343749994 -1.601 -0.465301513671875 0.9968652343749994 -1.601125 -0.463409423828125 0.9968652343749994 -1.60125 -0.463409423828125 0.9968652343749994 -1.601375 -0.461456298828125 0.9968652343749994 -1.6015 -0.461456298828125 0.9968652343749994 -1.601625 -0.45947265625 0.9968652343749994 -1.60175 -0.457427978515625 0.9968652343749994 -1.601875 -0.457427978515625 0.9968652343749994 -1.602 -0.455322265625 0.9968652343749994 -1.602125 -0.455322265625 0.9968652343749994 -1.60225 -0.453155517578125 0.9968652343749994 -1.602375 -0.450958251953125 0.9968652343749994 -1.6025 -0.450958251953125 0.9968652343749994 -1.602625 -0.44873046875 0.9968652343749994 -1.60275 -0.44873046875 0.9968652343749994 -1.602875 -0.4464111328125 0.9968652343749994 -1.603 -0.444091796875 0.9968652343749994 -1.603125 -0.444091796875 0.9968652343749994 -1.60325 -0.441680908203125 0.9968652343749994 -1.603375 -0.441680908203125 0.9968652343749994 -1.6035 -0.439239501953125 0.9968652343749994 -1.603625 -0.436737060546875 0.9968652343749994 -1.60375 -0.436737060546875 0.9968652343749994 -1.603875 -0.434234619140625 0.9968652343749994 -1.604 -0.434234619140625 0.9968652343749994 -1.604125 -0.431640625 0.9968652343749994 -1.60425 -0.428985595703125 0.9968652343749994 -1.604375 -0.428985595703125 0.9968652343749994 -1.6045 -0.42633056640625 0.9968652343749994 -1.604625 -0.42633056640625 0.9968652343749994 -1.60475 -0.423583984375 0.9968652343749994 -1.604875 -0.42083740234375 0.9968652343749994 -1.605 -0.42083740234375 0.9968652343749994 -1.605125 -0.417999267578125 0.9968652343749994 -1.60525 -0.417999267578125 0.9968652343749994 -1.605375 -0.415130615234375 0.9968652343749994 -1.6055 -0.412200927734375 0.9968652343749994 -1.605625 -0.412200927734375 0.9968652343749994 -1.60575 -0.409271240234375 0.9968652343749994 -1.605875 -0.409271240234375 0.9968652343749994 -1.606 -0.406280517578125 0.9968652343749994 -1.606125 -0.403228759765625 0.9968652343749994 -1.60625 -0.403228759765625 0.9968652343749994 -1.606375 -0.400115966796875 0.9968652343749994 -1.6065 -0.400115966796875 0.9968652343749994 -1.606625 -0.397003173828125 0.9968652343749994 -1.60675 -0.393829345703125 0.9968652343749994 -1.606875 -0.393829345703125 0.9968652343749994 -1.607 -0.390594482421875 0.9968652343749994 -1.607125 -0.390594482421875 0.9968652343749994 -1.60725 -0.3873291015625 0.9968652343749994 -1.607375 -0.384033203125 0.9968652343749994 -1.6075 -0.384033203125 0.9968652343749994 -1.607625 -0.38067626953125 0.9968652343749994 -1.60775 -0.38067626953125 0.9968652343749994 -1.607875 -0.377288818359375 0.9968652343749994 -1.608 -0.37384033203125 0.9968652343749994 -1.608125 -0.37384033203125 0.9968652343749994 -1.60825 -0.370391845703125 0.9968652343749994 -1.608375 -0.370391845703125 0.9968652343749994 -1.6085 -0.36688232421875 0.9968652343749994 -1.608625 -0.36334228515625 0.9968652343749994 -1.60875 -0.36334228515625 0.9968652343749994 -1.608875 -0.359710693359375 0.9968652343749994 -1.609 -0.359710693359375 0.9968652343749994 -1.609125 -0.356109619140625 0.9968652343749994 -1.60925 -0.3524169921875 0.9968652343749994 -1.609375 -0.3524169921875 0.9968652343749994 -1.6095 -0.348724365234375 0.9968652343749994 -1.609625 -0.348724365234375 0.9968652343749994 -1.60975 -0.344970703125 0.9968652343749994 -1.609875 -0.3411865234375 0.9968652343749994 -1.61 -0.3411865234375 0.9968652343749994 -1.610125 -0.337371826171875 0.9968652343749994 -1.61025 -0.337371826171875 0.9968652343749994 -1.610375 -0.33349609375 0.9968652343749994 -1.6105 -0.329620361328125 0.9968652343749994 -1.610625 -0.329620361328125 0.9968652343749994 -1.61075 -0.32568359375 0.9968652343749994 -1.610875 -0.32568359375 0.9968652343749994 -1.611 -0.321685791015625 0.9968652343749994 -1.611125 -0.31768798828125 0.9968652343749994 -1.61125 -0.31768798828125 0.9968652343749994 -1.611375 -0.31365966796875 0.9968652343749994 -1.6115 -0.31365966796875 0.9968652343749994 -1.611625 -0.309600830078125 0.9968652343749994 -1.61175 -0.30548095703125 0.9968652343749994 -1.611875 -0.30548095703125 0.9968652343749994 -1.612 -0.30133056640625 0.9968652343749994 -1.612125 -0.30133056640625 0.9968652343749994 -1.61225 -0.297149658203125 0.9968652343749994 -1.612375 -0.292938232421875 0.9968652343749994 -1.6125 -0.292938232421875 0.9968652343749994 -1.612625 -0.288726806640625 0.9968652343749994 -1.61275 -0.288726806640625 0.9968652343749994 -1.612875 -0.284454345703125 0.9968652343749994 -1.613 -0.2801513671875 0.9968652343749994 -1.613125 -0.2801513671875 0.9968652343749994 -1.61325 -0.27581787109375 0.9968652343749994 -1.613375 -0.27581787109375 0.9968652343749994 -1.6135 -0.271453857421875 0.9968652343749994 -1.613625 -0.267059326171875 0.9968652343749994 -1.61375 -0.267059326171875 0.9968652343749994 -1.613875 -0.26263427734375 0.9968652343749994 -1.614 -0.26263427734375 0.9968652343749994 -1.614125 -0.258209228515625 0.9968652343749994 -1.61425 -0.25372314453125 0.9968652343749994 -1.614375 -0.25372314453125 0.9968652343749994 -1.6145 -0.24920654296875 0.9968652343749994 -1.614625 -0.24920654296875 0.9968652343749994 -1.61475 -0.244659423828125 0.9968652343749994 -1.614875 -0.2401123046875 0.9968652343749994 -1.615 -0.2401123046875 0.9968652343749994 -1.615125 -0.23553466796875 0.9968652343749994 -1.61525 -0.23553466796875 0.9968652343749994 -1.615375 -0.23089599609375 0.9968652343749994 -1.6155 -0.22625732421875 0.9968652343749994 -1.615625 -0.22625732421875 0.9968652343749994 -1.61575 -0.22161865234375 0.9968652343749994 -1.615875 -0.22161865234375 0.9968652343749994 -1.616 -0.2169189453125 0.9968652343749994 -1.616125 -0.21221923828125 0.9968652343749994 -1.61625 -0.21221923828125 0.9968652343749994 -1.616375 -0.207489013671875 0.9968652343749994 -1.6165 -0.207489013671875 0.9968652343749994 -1.616625 -0.202728271484375 0.9968652343749994 -1.61675 -0.19793701171875 0.9968652343749994 -1.616875 -0.19793701171875 0.9968652343749994 -1.617 -0.193145751953125 0.9968652343749994 -1.617125 -0.193145751953125 0.9968652343749994 -1.61725 -0.188323974609375 0.9968652343749994 -1.617375 -0.1834716796875 0.9968652343749994 -1.6175 -0.1834716796875 0.9968652343749994 -1.617625 -0.178619384765625 0.9968652343749994 -1.61775 -0.178619384765625 0.9968652343749994 -1.617875 -0.173736572265625 0.9968652343749994 -1.618 -0.1688232421875 0.9968652343749994 -1.618125 -0.1688232421875 0.9968652343749994 -1.61825 -0.163909912109375 0.9968652343749994 -1.618375 -0.163909912109375 0.9968652343749994 -1.6185 -0.158966064453125 0.9968652343749994 -1.618625 -0.154022216796875 0.9968652343749994 -1.61875 -0.154022216796875 0.9968652343749994 -1.618875 -0.1490478515625 0.9968652343749994 -1.619 -0.1490478515625 0.9968652343749994 -1.619125 -0.14404296875 0.9968652343749994 -1.61925 -0.1390380859375 0.9968652343749994 -1.619375 -0.1390380859375 0.9968652343749994 -1.6195 -0.134033203125 0.9968652343749994 -1.619625 -0.134033203125 0.9968652343749994 -1.61975 -0.128997802734375 0.9968652343749994 -1.619875 -0.12396240234375 0.9968652343749994 -1.62 -0.12396240234375 0.9968652343749994 -1.620125 -0.118896484375 0.9968652343749994 -1.62025 -0.118896484375 0.9968652343749994 -1.620375 -0.11383056640625 0.9968652343749994 -1.6205 -0.108734130859375 0.9968652343749994 -1.620625 -0.108734130859375 0.9968652343749994 -1.62075 -0.1036376953125 0.9968652343749994 -1.620875 -0.1036376953125 0.9968652343749994 -1.621 -0.0985107421875 0.9968652343749994 -1.621125 -0.0933837890625 0.9968652343749994 -1.62125 -0.0933837890625 0.9968652343749994 -1.621375 -0.0882568359375 0.9968652343749994 -1.6215 -0.0882568359375 0.9968652343749994 -1.621625 -0.0831298828125 0.9968652343749994 -1.62175 -0.077972412109375 0.9968652343749994 -1.621875 -0.077972412109375 0.9968652343749994 -1.622 -0.07281494140625 0.9968652343749994 -1.622125 -0.07281494140625 0.9968652343749994 -1.62225 -0.067626953125 0.9968652343749994 -1.622375 -0.062469482421875 0.9968652343749994 -1.6225 -0.062469482421875 0.9968652343749994 -1.622625 -0.05731201171875 0.9968652343749994 -1.62275 -0.05731201171875 0.9968652343749994 -1.622875 -0.0521240234375 0.9968652343749994 -1.623 -0.046905517578125 0.9968652343749994 -1.623125 -0.046905517578125 0.9968652343749994 -1.62325 -0.041717529296875 0.9968652343749994 -1.623375 -0.041717529296875 0.9968652343749994 -1.6235 -0.0364990234375 0.9968652343749994 -1.623625 -0.03131103515625 0.9968652343749994 -1.62375 -0.03131103515625 0.9968652343749994 -1.623875 -0.026092529296875 0.9968652343749994 -1.624 -0.026092529296875 0.9968652343749994 -1.624125 -0.0208740234375 0.9968652343749994 -1.62425 -0.015655517578125 0.9968652343749994 -1.624375 -0.015655517578125 0.9968652343749994 -1.6245 -0.01043701171875 0.9968652343749994 -1.624625 -0.01043701171875 0.9968652343749994 -1.62475 -0.005218505859375 0.9968652343749994 +1.562625 -0.004180908203125 0.8033593750000046 +1.56275 -0.004180908203125 0.8033593750000046 +1.562875 -0.008392333984375 0.8033593750000046 +1.563 -0.012603759765625 0.8033593750000046 +1.563125 -0.012603759765625 0.8033593750000046 +1.56325 -0.016815185546875 0.8033593750000046 +1.563375 -0.016815185546875 0.8033593750000046 +1.5635 -0.02099609375 0.8033593750000046 +1.563625 -0.02520751953125 0.8033593750000046 +1.56375 -0.02520751953125 0.8033593750000046 +1.563875 -0.029388427734375 0.8033593750000046 +1.564 -0.029388427734375 0.8033593750000046 +1.564125 -0.0335693359375 0.8033593750000046 +1.56425 -0.03778076171875 0.8033593750000046 +1.564375 -0.03778076171875 0.8033593750000046 +1.5645 -0.041961669921875 0.8033593750000046 +1.564625 -0.041961669921875 0.8033593750000046 +1.56475 -0.046142578125 0.8033593750000046 +1.564875 -0.050323486328125 0.8033593750000046 +1.565 -0.050323486328125 0.8033593750000046 +1.565125 -0.054473876953125 0.8033593750000046 +1.56525 -0.054473876953125 0.8033593750000046 +1.565375 -0.05865478515625 0.8033593750000046 +1.5655 -0.06280517578125 0.8033593750000046 +1.565625 -0.06280517578125 0.8033593750000046 +1.56575 -0.06695556640625 0.8033593750000046 +1.565875 -0.06695556640625 0.8033593750000046 +1.566 -0.07110595703125 0.8033593750000046 +1.566125 -0.075225830078125 0.8033593750000046 +1.56625 -0.075225830078125 0.8033593750000046 +1.566375 -0.079376220703125 0.8033593750000046 +1.5665 -0.079376220703125 0.8033593750000046 +1.566625 -0.08349609375 0.8033593750000046 +1.56675 -0.08758544921875 0.8033593750000046 +1.566875 -0.08758544921875 0.8033593750000046 +1.567 -0.091705322265625 0.8033593750000046 +1.567125 -0.091705322265625 0.8033593750000046 +1.56725 -0.095794677734375 0.8033593750000046 +1.567375 -0.099853515625 0.8033593750000046 +1.5675 -0.099853515625 0.8033593750000046 +1.567625 -0.10394287109375 0.8033593750000046 +1.56775 -0.10394287109375 0.8033593750000046 +1.567875 -0.108001708984375 0.8033593750000046 +1.568 -0.134002685546875 0.960815429687502 +1.568125 -0.134002685546875 0.960815429687502 +1.56825 -0.138824462890625 0.960815429687502 +1.568375 -0.138824462890625 0.960815429687502 +1.5685 -0.14361572265625 0.960815429687502 +1.568625 -0.148406982421875 0.960815429687502 +1.56875 -0.148406982421875 0.960815429687502 +1.568875 -0.1531982421875 0.960815429687502 +1.569 -0.1531982421875 0.960815429687502 +1.569125 -0.157958984375 0.960815429687502 +1.56925 -0.162689208984375 0.960815429687502 +1.569375 -0.162689208984375 0.960815429687502 +1.5695 -0.16741943359375 0.960815429687502 +1.569625 -0.16741943359375 0.960815429687502 +1.56975 -0.172119140625 0.960815429687502 +1.569875 -0.17681884765625 0.960815429687502 +1.57 -0.17681884765625 0.960815429687502 +1.570125 -0.181488037109375 0.960815429687502 +1.57025 -0.181488037109375 0.960815429687502 +1.570375 -0.186126708984375 0.960815429687502 +1.5705 -0.190765380859375 0.960815429687502 +1.570625 -0.190765380859375 0.960815429687502 +1.57075 -0.19537353515625 0.960815429687502 +1.570875 -0.19537353515625 0.960815429687502 +1.571 -0.199951171875 0.960815429687502 +1.571125 -0.204498291015625 0.960815429687502 +1.57125 -0.204498291015625 0.960815429687502 +1.571375 -0.20904541015625 0.960815429687502 +1.5715 -0.20904541015625 0.960815429687502 +1.571625 -0.21356201171875 0.960815429687502 +1.57175 -0.218048095703125 0.960815429687502 +1.571875 -0.218048095703125 0.960815429687502 +1.572 -0.2225341796875 0.960815429687502 +1.572125 -0.2225341796875 0.960815429687502 +1.57225 -0.22698974609375 0.960815429687502 +1.572375 -0.23138427734375 0.960815429687502 +1.5725 -0.23138427734375 0.960815429687502 +1.572625 -0.235809326171875 0.960815429687502 +1.57275 -0.235809326171875 0.960815429687502 +1.572875 -0.24017333984375 0.960815429687502 +1.573 -0.2445068359375 0.960815429687502 +1.573125 -0.2445068359375 0.960815429687502 +1.57325 -0.24884033203125 0.960815429687502 +1.573375 -0.24884033203125 0.960815429687502 +1.5735 -0.25311279296875 0.960815429687502 +1.573625 -0.25738525390625 0.960815429687502 +1.57375 -0.25738525390625 0.960815429687502 +1.573875 -0.261627197265625 0.960815429687502 +1.574 -0.261627197265625 0.960815429687502 +1.574125 -0.26580810546875 0.960815429687502 +1.57425 -0.269989013671875 0.960815429687502 +1.574375 -0.269989013671875 0.960815429687502 +1.5745 -0.274139404296875 0.960815429687502 +1.574625 -0.274139404296875 0.960815429687502 +1.57475 -0.27825927734375 0.960815429687502 +1.574875 -0.282318115234375 0.960815429687502 +1.575 -0.282318115234375 0.960815429687502 +1.575125 -0.286376953125 0.960815429687502 +1.57525 -0.286376953125 0.960815429687502 +1.575375 -0.2904052734375 0.960815429687502 +1.5755 -0.294403076171875 0.960815429687502 +1.575625 -0.294403076171875 0.960815429687502 +1.57575 -0.298370361328125 0.960815429687502 +1.575875 -0.298370361328125 0.960815429687502 +1.576 -0.302276611328125 0.960815429687502 +1.576125 -0.306182861328125 0.960815429687502 +1.57625 -0.306182861328125 0.960815429687502 +1.576375 -0.310028076171875 0.960815429687502 +1.5765 -0.310028076171875 0.960815429687502 +1.576625 -0.313873291015625 0.960815429687502 +1.57675 -0.317657470703125 0.960815429687502 +1.576875 -0.317657470703125 0.960815429687502 +1.577 -0.3214111328125 0.960815429687502 +1.577125 -0.3214111328125 0.960815429687502 +1.57725 -0.32513427734375 0.960815429687502 +1.577375 -0.328826904296875 0.960815429687502 +1.5775 -0.328826904296875 0.960815429687502 +1.577625 -0.33245849609375 0.960815429687502 +1.57775 -0.33245849609375 0.960815429687502 +1.577875 -0.3360595703125 0.960815429687502 +1.578 -0.33966064453125 0.960815429687502 +1.578125 -0.33966064453125 0.960815429687502 +1.57825 -0.34320068359375 0.960815429687502 +1.578375 -0.34320068359375 0.960815429687502 +1.5785 -0.3466796875 0.960815429687502 +1.578625 -0.35015869140625 0.960815429687502 +1.57875 -0.35015869140625 0.960815429687502 +1.578875 -0.35357666015625 0.960815429687502 +1.579 -0.35357666015625 0.960815429687502 +1.579125 -0.356964111328125 0.960815429687502 +1.57925 -0.360321044921875 0.960815429687502 +1.579375 -0.360321044921875 0.960815429687502 +1.5795 -0.363616943359375 0.960815429687502 +1.579625 -0.363616943359375 0.960815429687502 +1.57975 -0.36688232421875 0.960815429687502 +1.579875 -0.3701171875 0.960815429687502 +1.58 -0.3701171875 0.960815429687502 +1.580125 -0.373291015625 0.960815429687502 +1.58025 -0.373291015625 0.960815429687502 +1.580375 -0.376434326171875 0.960815429687502 +1.5805 -0.379547119140625 0.960815429687502 +1.580625 -0.379547119140625 0.960815429687502 +1.58075 -0.382598876953125 0.960815429687502 +1.580875 -0.382598876953125 0.960815429687502 +1.581 -0.3856201171875 0.960815429687502 +1.581125 -0.38861083984375 0.960815429687502 +1.58125 -0.38861083984375 0.960815429687502 +1.581375 -0.39154052734375 0.960815429687502 +1.5815 -0.39154052734375 0.960815429687502 +1.581625 -0.394439697265625 0.960815429687502 +1.58175 -0.39727783203125 0.960815429687502 +1.581875 -0.39727783203125 0.960815429687502 +1.582 -0.40008544921875 0.960815429687502 +1.582125 -0.40008544921875 0.960815429687502 +1.58225 -0.402862548828125 0.960815429687502 +1.582375 -0.40557861328125 0.960815429687502 +1.5825 -0.40557861328125 0.960815429687502 +1.582625 -0.408233642578125 0.960815429687502 +1.58275 -0.408233642578125 0.960815429687502 +1.582875 -0.410858154296875 0.960815429687502 +1.583 -0.4134521484375 0.960815429687502 +1.583125 -0.4134521484375 0.960815429687502 +1.58325 -0.416015625 0.960815429687502 +1.583375 -0.416015625 0.960815429687502 +1.5835 -0.418487548828125 0.960815429687502 +1.583625 -0.420928955078125 0.960815429687502 +1.58375 -0.420928955078125 0.960815429687502 +1.583875 -0.42333984375 0.960815429687502 +1.584 -0.42333984375 0.960815429687502 +1.584125 -0.425689697265625 0.960815429687502 +1.58425 -0.428009033203125 0.960815429687502 +1.584375 -0.428009033203125 0.960815429687502 +1.5845 -0.430267333984375 0.960815429687502 +1.584625 -0.430267333984375 0.960815429687502 +1.58475 -0.432464599609375 0.960815429687502 +1.584875 -0.43463134765625 0.960815429687502 +1.585 -0.43463134765625 0.960815429687502 +1.585125 -0.436737060546875 0.960815429687502 +1.58525 -0.436737060546875 0.960815429687502 +1.585375 -0.4388427734375 0.960815429687502 +1.5855 -0.44085693359375 0.960815429687502 +1.585625 -0.44085693359375 0.960815429687502 +1.58575 -0.44281005859375 0.960815429687502 +1.585875 -0.44281005859375 0.960815429687502 +1.586 -0.44476318359375 0.960815429687502 +1.586125 -0.446624755859375 0.960815429687502 +1.58625 -0.446624755859375 0.960815429687502 +1.586375 -0.448455810546875 0.960815429687502 +1.5865 -0.448455810546875 0.960815429687502 +1.586625 -0.450225830078125 0.960815429687502 +1.58675 -0.45196533203125 0.960815429687502 +1.586875 -0.45196533203125 0.960815429687502 +1.587 -0.453643798828125 0.960815429687502 +1.587125 -0.453643798828125 0.960815429687502 +1.58725 -0.45526123046875 0.960815429687502 +1.587375 -0.45684814453125 0.960815429687502 +1.5875 -0.45684814453125 0.960815429687502 +1.587625 -0.4583740234375 0.960815429687502 +1.58775 -0.4583740234375 0.960815429687502 +1.587875 -0.4598388671875 0.960815429687502 +1.588 -0.461273193359375 0.960815429687502 +1.588125 -0.461273193359375 0.960815429687502 +1.58825 -0.462646484375 0.960815429687502 +1.588375 -0.462646484375 0.960815429687502 +1.5885 -0.4639892578125 0.960815429687502 +1.588625 -0.46527099609375 0.960815429687502 +1.58875 -0.46527099609375 0.960815429687502 +1.588875 -0.46649169921875 0.960815429687502 +1.589 -0.46649169921875 0.960815429687502 +1.589125 -0.4676513671875 0.960815429687502 +1.58925 -0.468780517578125 0.960815429687502 +1.589375 -0.468780517578125 0.960815429687502 +1.5895 -0.4698486328125 0.960815429687502 +1.589625 -0.4698486328125 0.960815429687502 +1.58975 -0.47088623046875 0.960815429687502 +1.589875 -0.471832275390625 0.960815429687502 +1.59 -0.471832275390625 0.960815429687502 +1.590125 -0.4727783203125 0.960815429687502 +1.59025 -0.4727783203125 0.960815429687502 +1.590375 -0.4736328125 0.960815429687502 +1.5905 -0.47442626953125 0.960815429687502 +1.590625 -0.47442626953125 0.960815429687502 +1.59075 -0.475189208984375 0.960815429687502 +1.590875 -0.475189208984375 0.960815429687502 +1.591 -0.47589111328125 0.960815429687502 +1.591125 -0.4765625 0.960815429687502 +1.59125 -0.4765625 0.960815429687502 +1.591375 -0.4771728515625 0.960815429687502 +1.5915 -0.4771728515625 0.960815429687502 +1.591625 -0.47772216796875 0.960815429687502 +1.59175 -0.47821044921875 0.960815429687502 +1.591875 -0.47821044921875 0.960815429687502 +1.592 -0.478668212890625 0.960815429687502 +1.592125 -0.478668212890625 0.960815429687502 +1.59225 -0.47906494140625 0.960815429687502 +1.592375 -0.479400634765625 0.960815429687502 +1.5925 -0.479400634765625 0.960815429687502 +1.592625 -0.479705810546875 0.960815429687502 +1.59275 -0.479705810546875 0.960815429687502 +1.592875 -0.479949951171875 0.960815429687502 +1.593 -0.4801025390625 0.960815429687502 +1.593125 -0.4801025390625 0.960815429687502 +1.59325 -0.480255126953125 0.960815429687502 +1.593375 -0.480255126953125 0.960815429687502 +1.5935 -0.4803466796875 0.960815429687502 +1.593625 -0.480377197265625 0.960815429687502 +1.59375 -0.480377197265625 0.960815429687502 +1.593875 -0.4803466796875 0.960815429687502 +1.594 -0.4803466796875 0.960815429687502 +1.594125 -0.480255126953125 0.960815429687502 +1.59425 -0.4801025390625 0.960815429687502 +1.594375 -0.4801025390625 0.960815429687502 +1.5945 -0.479949951171875 0.960815429687502 +1.594625 -0.479949951171875 0.960815429687502 +1.59475 -0.479705810546875 0.960815429687502 +1.594875 -0.479400634765625 0.960815429687502 +1.595 -0.479400634765625 0.960815429687502 +1.595125 -0.47906494140625 0.960815429687502 +1.59525 -0.47906494140625 0.960815429687502 +1.595375 -0.478668212890625 0.960815429687502 +1.5955 -0.47821044921875 0.960815429687502 +1.595625 -0.47821044921875 0.960815429687502 +1.59575 -0.47772216796875 0.960815429687502 +1.595875 -0.47772216796875 0.960815429687502 +1.596 -0.4771728515625 0.960815429687502 +1.596125 -0.4765625 0.960815429687502 +1.59625 -0.4765625 0.960815429687502 +1.596375 -0.47589111328125 0.960815429687502 +1.5965 -0.47589111328125 0.960815429687502 +1.596625 -0.475189208984375 0.960815429687502 +1.59675 -0.47442626953125 0.960815429687502 +1.596875 -0.47442626953125 0.960815429687502 +1.597 -0.4736328125 0.960815429687502 +1.597125 -0.4736328125 0.960815429687502 +1.59725 -0.4727783203125 0.960815429687502 +1.597375 -0.471832275390625 0.960815429687502 +1.5975 -0.471832275390625 0.960815429687502 +1.597625 -0.47088623046875 0.960815429687502 +1.59775 -0.47088623046875 0.960815429687502 +1.597875 -0.4698486328125 0.960815429687502 +1.598 -0.468780517578125 0.960815429687502 +1.598125 -0.468780517578125 0.960815429687502 +1.59825 -0.4676513671875 0.960815429687502 +1.598375 -0.4676513671875 0.960815429687502 +1.5985 -0.46649169921875 0.960815429687502 +1.598625 -0.46527099609375 0.960815429687502 +1.59875 -0.46527099609375 0.960815429687502 +1.598875 -0.4639892578125 0.960815429687502 +1.599 -0.4639892578125 0.960815429687502 +1.599125 -0.462646484375 0.960815429687502 +1.59925 -0.461273193359375 0.960815429687502 +1.599375 -0.461273193359375 0.960815429687502 +1.5995 -0.4598388671875 0.960815429687502 +1.599625 -0.4598388671875 0.960815429687502 +1.59975 -0.4583740234375 0.960815429687502 +1.599875 -0.45684814453125 0.960815429687502 +1.6 -0.4739990234375 0.9968652343749994 +1.600125 -0.47235107421875 0.9968652343749994 +1.60025 -0.47235107421875 0.9968652343749994 +1.600375 -0.47064208984375 0.9968652343749994 +1.6005 -0.468902587890625 0.9968652343749994 +1.600625 -0.468902587890625 0.9968652343749994 +1.60075 -0.46710205078125 0.9968652343749994 +1.600875 -0.46710205078125 0.9968652343749994 +1.601 -0.46527099609375 0.9968652343749994 +1.601125 -0.46337890625 0.9968652343749994 +1.60125 -0.46337890625 0.9968652343749994 +1.601375 -0.46142578125 0.9968652343749994 +1.6015 -0.46142578125 0.9968652343749994 +1.601625 -0.459442138671875 0.9968652343749994 +1.60175 -0.4573974609375 0.9968652343749994 +1.601875 -0.4573974609375 0.9968652343749994 +1.602 -0.455291748046875 0.9968652343749994 +1.602125 -0.455291748046875 0.9968652343749994 +1.60225 -0.453125 0.9968652343749994 +1.602375 -0.450927734375 0.9968652343749994 +1.6025 -0.450927734375 0.9968652343749994 +1.602625 -0.448699951171875 0.9968652343749994 +1.60275 -0.448699951171875 0.9968652343749994 +1.602875 -0.446380615234375 0.9968652343749994 +1.603 -0.444061279296875 0.9968652343749994 +1.603125 -0.444061279296875 0.9968652343749994 +1.60325 -0.441650390625 0.9968652343749994 +1.603375 -0.441650390625 0.9968652343749994 +1.6035 -0.439208984375 0.9968652343749994 +1.603625 -0.43670654296875 0.9968652343749994 +1.60375 -0.43670654296875 0.9968652343749994 +1.603875 -0.4342041015625 0.9968652343749994 +1.604 -0.4342041015625 0.9968652343749994 +1.604125 -0.431610107421875 0.9968652343749994 +1.60425 -0.428955078125 0.9968652343749994 +1.604375 -0.428955078125 0.9968652343749994 +1.6045 -0.426300048828125 0.9968652343749994 +1.604625 -0.426300048828125 0.9968652343749994 +1.60475 -0.423553466796875 0.9968652343749994 +1.604875 -0.420806884765625 0.9968652343749994 +1.605 -0.420806884765625 0.9968652343749994 +1.605125 -0.41796875 0.9968652343749994 +1.60525 -0.41796875 0.9968652343749994 +1.605375 -0.41510009765625 0.9968652343749994 +1.6055 -0.41217041015625 0.9968652343749994 +1.605625 -0.41217041015625 0.9968652343749994 +1.60575 -0.40924072265625 0.9968652343749994 +1.605875 -0.40924072265625 0.9968652343749994 +1.606 -0.40625 0.9968652343749994 +1.606125 -0.4031982421875 0.9968652343749994 +1.60625 -0.4031982421875 0.9968652343749994 +1.606375 -0.40008544921875 0.9968652343749994 +1.6065 -0.40008544921875 0.9968652343749994 +1.606625 -0.39697265625 0.9968652343749994 +1.60675 -0.393798828125 0.9968652343749994 +1.606875 -0.393798828125 0.9968652343749994 +1.607 -0.39056396484375 0.9968652343749994 +1.607125 -0.39056396484375 0.9968652343749994 +1.60725 -0.387298583984375 0.9968652343749994 +1.607375 -0.384002685546875 0.9968652343749994 +1.6075 -0.384002685546875 0.9968652343749994 +1.607625 -0.380645751953125 0.9968652343749994 +1.60775 -0.380645751953125 0.9968652343749994 +1.607875 -0.37725830078125 0.9968652343749994 +1.608 -0.373809814453125 0.9968652343749994 +1.608125 -0.373809814453125 0.9968652343749994 +1.60825 -0.370361328125 0.9968652343749994 +1.608375 -0.370361328125 0.9968652343749994 +1.6085 -0.366851806640625 0.9968652343749994 +1.608625 -0.363311767578125 0.9968652343749994 +1.60875 -0.363311767578125 0.9968652343749994 +1.608875 -0.35968017578125 0.9968652343749994 +1.609 -0.35968017578125 0.9968652343749994 +1.609125 -0.3560791015625 0.9968652343749994 +1.60925 -0.352386474609375 0.9968652343749994 +1.609375 -0.352386474609375 0.9968652343749994 +1.6095 -0.34869384765625 0.9968652343749994 +1.609625 -0.34869384765625 0.9968652343749994 +1.60975 -0.344940185546875 0.9968652343749994 +1.609875 -0.341156005859375 0.9968652343749994 +1.61 -0.341156005859375 0.9968652343749994 +1.610125 -0.33734130859375 0.9968652343749994 +1.61025 -0.33734130859375 0.9968652343749994 +1.610375 -0.333465576171875 0.9968652343749994 +1.6105 -0.32958984375 0.9968652343749994 +1.610625 -0.32958984375 0.9968652343749994 +1.61075 -0.325653076171875 0.9968652343749994 +1.610875 -0.325653076171875 0.9968652343749994 +1.611 -0.3216552734375 0.9968652343749994 +1.611125 -0.317657470703125 0.9968652343749994 +1.61125 -0.317657470703125 0.9968652343749994 +1.611375 -0.313629150390625 0.9968652343749994 +1.6115 -0.313629150390625 0.9968652343749994 +1.611625 -0.3095703125 0.9968652343749994 +1.61175 -0.305450439453125 0.9968652343749994 +1.611875 -0.305450439453125 0.9968652343749994 +1.612 -0.301300048828125 0.9968652343749994 +1.612125 -0.301300048828125 0.9968652343749994 +1.61225 -0.297119140625 0.9968652343749994 +1.612375 -0.29290771484375 0.9968652343749994 +1.6125 -0.29290771484375 0.9968652343749994 +1.612625 -0.2886962890625 0.9968652343749994 +1.61275 -0.2886962890625 0.9968652343749994 +1.612875 -0.284423828125 0.9968652343749994 +1.613 -0.280120849609375 0.9968652343749994 +1.613125 -0.280120849609375 0.9968652343749994 +1.61325 -0.275787353515625 0.9968652343749994 +1.613375 -0.275787353515625 0.9968652343749994 +1.6135 -0.27142333984375 0.9968652343749994 +1.613625 -0.26702880859375 0.9968652343749994 +1.61375 -0.26702880859375 0.9968652343749994 +1.613875 -0.262603759765625 0.9968652343749994 +1.614 -0.262603759765625 0.9968652343749994 +1.614125 -0.2581787109375 0.9968652343749994 +1.61425 -0.253692626953125 0.9968652343749994 +1.614375 -0.253692626953125 0.9968652343749994 +1.6145 -0.249176025390625 0.9968652343749994 +1.614625 -0.249176025390625 0.9968652343749994 +1.61475 -0.24462890625 0.9968652343749994 +1.614875 -0.240081787109375 0.9968652343749994 +1.615 -0.240081787109375 0.9968652343749994 +1.615125 -0.235504150390625 0.9968652343749994 +1.61525 -0.235504150390625 0.9968652343749994 +1.615375 -0.230865478515625 0.9968652343749994 +1.6155 -0.226226806640625 0.9968652343749994 +1.615625 -0.226226806640625 0.9968652343749994 +1.61575 -0.221588134765625 0.9968652343749994 +1.615875 -0.221588134765625 0.9968652343749994 +1.616 -0.216888427734375 0.9968652343749994 +1.616125 -0.212188720703125 0.9968652343749994 +1.61625 -0.212188720703125 0.9968652343749994 +1.616375 -0.20745849609375 0.9968652343749994 +1.6165 -0.20745849609375 0.9968652343749994 +1.616625 -0.20269775390625 0.9968652343749994 +1.61675 -0.197906494140625 0.9968652343749994 +1.616875 -0.197906494140625 0.9968652343749994 +1.617 -0.193115234375 0.9968652343749994 +1.617125 -0.193115234375 0.9968652343749994 +1.61725 -0.18829345703125 0.9968652343749994 +1.617375 -0.183441162109375 0.9968652343749994 +1.6175 -0.183441162109375 0.9968652343749994 +1.617625 -0.1785888671875 0.9968652343749994 +1.61775 -0.1785888671875 0.9968652343749994 +1.617875 -0.1737060546875 0.9968652343749994 +1.618 -0.168792724609375 0.9968652343749994 +1.618125 -0.168792724609375 0.9968652343749994 +1.61825 -0.16387939453125 0.9968652343749994 +1.618375 -0.16387939453125 0.9968652343749994 +1.6185 -0.158935546875 0.9968652343749994 +1.618625 -0.15399169921875 0.9968652343749994 +1.61875 -0.15399169921875 0.9968652343749994 +1.618875 -0.149017333984375 0.9968652343749994 +1.619 -0.149017333984375 0.9968652343749994 +1.619125 -0.144012451171875 0.9968652343749994 +1.61925 -0.139007568359375 0.9968652343749994 +1.619375 -0.139007568359375 0.9968652343749994 +1.6195 -0.134002685546875 0.9968652343749994 +1.619625 -0.134002685546875 0.9968652343749994 +1.61975 -0.12896728515625 0.9968652343749994 +1.619875 -0.123931884765625 0.9968652343749994 +1.62 -0.123931884765625 0.9968652343749994 +1.620125 -0.118865966796875 0.9968652343749994 +1.62025 -0.118865966796875 0.9968652343749994 +1.620375 -0.113800048828125 0.9968652343749994 +1.6205 -0.10870361328125 0.9968652343749994 +1.620625 -0.10870361328125 0.9968652343749994 +1.62075 -0.103607177734375 0.9968652343749994 +1.620875 -0.103607177734375 0.9968652343749994 +1.621 -0.098480224609375 0.9968652343749994 +1.621125 -0.093353271484375 0.9968652343749994 +1.62125 -0.093353271484375 0.9968652343749994 +1.621375 -0.088226318359375 0.9968652343749994 +1.6215 -0.088226318359375 0.9968652343749994 +1.621625 -0.083099365234375 0.9968652343749994 +1.62175 -0.07794189453125 0.9968652343749994 +1.621875 -0.07794189453125 0.9968652343749994 +1.622 -0.072784423828125 0.9968652343749994 +1.622125 -0.072784423828125 0.9968652343749994 +1.62225 -0.067596435546875 0.9968652343749994 +1.622375 -0.06243896484375 0.9968652343749994 +1.6225 -0.06243896484375 0.9968652343749994 +1.622625 -0.057281494140625 0.9968652343749994 +1.62275 -0.057281494140625 0.9968652343749994 +1.622875 -0.052093505859375 0.9968652343749994 +1.623 -0.046875 0.9968652343749994 +1.623125 -0.046875 0.9968652343749994 +1.62325 -0.04168701171875 0.9968652343749994 +1.623375 -0.04168701171875 0.9968652343749994 +1.6235 -0.036468505859375 0.9968652343749994 +1.623625 -0.031280517578125 0.9968652343749994 +1.62375 -0.031280517578125 0.9968652343749994 +1.623875 -0.02606201171875 0.9968652343749994 +1.624 -0.02606201171875 0.9968652343749994 +1.624125 -0.020843505859375 0.9968652343749994 +1.62425 -0.015625 0.9968652343749994 +1.624375 -0.015625 0.9968652343749994 +1.6245 -0.010406494140625 0.9968652343749994 +1.624625 -0.010406494140625 0.9968652343749994 +1.62475 -0.00518798828125 0.9968652343749994 1.624875 0.0 0.9968652343749994 1.625 0.0 0.9968652343749994 1.625125 0.00518798828125 0.9968652343749994 @@ -13499,504 +13499,504 @@ 1.68725 0.003662109375 0.7021142578124948 1.687375 0.0 0.7021142578124948 1.6875 0.0 0.7021142578124948 -1.687625 -0.003692626953125 0.7021142578124948 -1.68775 -0.003692626953125 0.7021142578124948 -1.687875 -0.007354736328125 0.7021142578124948 -1.688 -0.01104736328125 0.7021142578124948 -1.688125 -0.01104736328125 0.7021142578124948 -1.68825 -0.01470947265625 0.7021142578124948 -1.688375 -0.01470947265625 0.7021142578124948 -1.6885 -0.01837158203125 0.7021142578124948 -1.688625 -0.022064208984375 0.7021142578124948 -1.68875 -0.022064208984375 0.7021142578124948 -1.688875 -0.025726318359375 0.7021142578124948 -1.689 -0.025726318359375 0.7021142578124948 -1.689125 -0.029388427734375 0.7021142578124948 -1.68925 -0.033050537109375 0.7021142578124948 -1.689375 -0.033050537109375 0.7021142578124948 -1.6895 -0.036712646484375 0.7021142578124948 -1.689625 -0.036712646484375 0.7021142578124948 -1.68975 -0.040374755859375 0.7021142578124948 -1.689875 -0.04400634765625 0.7021142578124948 -1.69 -0.04400634765625 0.7021142578124948 -1.690125 -0.047637939453125 0.7021142578124948 -1.69025 -0.047637939453125 0.7021142578124948 -1.690375 -0.051300048828125 0.7021142578124948 -1.6905 -0.054931640625 0.7021142578124948 -1.690625 -0.054931640625 0.7021142578124948 -1.69075 -0.058563232421875 0.7021142578124948 -1.690875 -0.058563232421875 0.7021142578124948 -1.691 -0.062164306640625 0.7021142578124948 -1.691125 -0.0657958984375 0.7021142578124948 -1.69125 -0.0657958984375 0.7021142578124948 -1.691375 -0.06939697265625 0.7021142578124948 -1.6915 -0.06939697265625 0.7021142578124948 -1.691625 -0.072998046875 0.7021142578124948 -1.69175 -0.076568603515625 0.7021142578124948 -1.691875 -0.076568603515625 0.7021142578124948 -1.692 -0.080169677734375 0.7021142578124948 -1.692125 -0.080169677734375 0.7021142578124948 -1.69225 -0.083740234375 0.7021142578124948 -1.692375 -0.087310791015625 0.7021142578124948 -1.6925 -0.087310791015625 0.7021142578124948 -1.692625 -0.090850830078125 0.7021142578124948 -1.69275 -0.090850830078125 0.7021142578124948 -1.692875 -0.09442138671875 0.7021142578124948 -1.693 -0.097930908203125 0.7021142578124948 -1.693125 -0.097930908203125 0.7021142578124948 -1.69325 -0.101470947265625 0.7021142578124948 -1.693375 -0.101470947265625 0.7021142578124948 -1.6935 -0.10498046875 0.7021142578124948 -1.693625 -0.108489990234375 0.7021142578124948 -1.69375 -0.108489990234375 0.7021142578124948 -1.693875 -0.111968994140625 0.7021142578124948 -1.694 -0.111968994140625 0.7021142578124948 -1.694125 -0.115447998046875 0.7021142578124948 -1.69425 -0.118927001953125 0.7021142578124948 -1.694375 -0.118927001953125 0.7021142578124948 -1.6945 -0.12237548828125 0.7021142578124948 -1.694625 -0.12237548828125 0.7021142578124948 -1.69475 -0.12579345703125 0.7021142578124948 -1.694875 -0.129241943359375 0.7021142578124948 -1.695 -0.129241943359375 0.7021142578124948 -1.695125 -0.13262939453125 0.7021142578124948 -1.69525 -0.13262939453125 0.7021142578124948 -1.695375 -0.13604736328125 0.7021142578124948 -1.6955 -0.139434814453125 0.7021142578124948 -1.695625 -0.139434814453125 0.7021142578124948 -1.69575 -0.142791748046875 0.7021142578124948 -1.695875 -0.142791748046875 0.7021142578124948 -1.696 -0.087066650390625 0.4183349609374934 -1.696125 -0.08905029296875 0.4183349609374934 -1.69625 -0.08905029296875 0.4183349609374934 -1.696375 -0.091033935546875 0.4183349609374934 -1.6965 -0.091033935546875 0.4183349609374934 -1.696625 -0.093017578125 0.4183349609374934 -1.69675 -0.094970703125 0.4183349609374934 -1.696875 -0.094970703125 0.4183349609374934 -1.697 -0.096893310546875 0.4183349609374934 -1.697125 -0.096893310546875 0.4183349609374934 -1.69725 -0.098846435546875 0.4183349609374934 -1.697375 -0.10076904296875 0.4183349609374934 -1.6975 -0.10076904296875 0.4183349609374934 -1.697625 -0.102691650390625 0.4183349609374934 -1.69775 -0.102691650390625 0.4183349609374934 -1.697875 -0.104583740234375 0.4183349609374934 -1.698 -0.106475830078125 0.4183349609374934 -1.698125 -0.106475830078125 0.4183349609374934 -1.69825 -0.108367919921875 0.4183349609374934 -1.698375 -0.108367919921875 0.4183349609374934 -1.6985 -0.1102294921875 0.4183349609374934 -1.698625 -0.112091064453125 0.4183349609374934 -1.69875 -0.112091064453125 0.4183349609374934 -1.698875 -0.113922119140625 0.4183349609374934 -1.699 -0.113922119140625 0.4183349609374934 -1.699125 -0.115753173828125 0.4183349609374934 -1.69925 -0.1175537109375 0.4183349609374934 -1.699375 -0.1175537109375 0.4183349609374934 -1.6995 -0.119384765625 0.4183349609374934 -1.699625 -0.119384765625 0.4183349609374934 -1.69975 -0.12115478515625 0.4183349609374934 -1.699875 -0.122955322265625 0.4183349609374934 -1.7 -0.122955322265625 0.4183349609374934 -1.700125 -0.12469482421875 0.4183349609374934 -1.70025 -0.12469482421875 0.4183349609374934 -1.700375 -0.12646484375 0.4183349609374934 -1.7005 -0.128204345703125 0.4183349609374934 -1.700625 -0.128204345703125 0.4183349609374934 -1.70075 -0.129913330078125 0.4183349609374934 -1.700875 -0.129913330078125 0.4183349609374934 -1.701 -0.131622314453125 0.4183349609374934 -1.701125 -0.133331298828125 0.4183349609374934 -1.70125 -0.133331298828125 0.4183349609374934 -1.701375 -0.135009765625 0.4183349609374934 -1.7015 -0.135009765625 0.4183349609374934 -1.701625 -0.13665771484375 0.4183349609374934 -1.70175 -0.138336181640625 0.4183349609374934 -1.701875 -0.138336181640625 0.4183349609374934 -1.702 -0.13995361328125 0.4183349609374934 -1.702125 -0.13995361328125 0.4183349609374934 -1.70225 -0.141571044921875 0.4183349609374934 -1.702375 -0.1431884765625 0.4183349609374934 -1.7025 -0.1431884765625 0.4183349609374934 -1.702625 -0.144775390625 0.4183349609374934 -1.70275 -0.144775390625 0.4183349609374934 -1.702875 -0.146331787109375 0.4183349609374934 -1.703 -0.14788818359375 0.4183349609374934 -1.703125 -0.14788818359375 0.4183349609374934 -1.70325 -0.149444580078125 0.4183349609374934 -1.703375 -0.149444580078125 0.4183349609374934 -1.7035 -0.150970458984375 0.4183349609374934 -1.703625 -0.1524658203125 0.4183349609374934 -1.70375 -0.1524658203125 0.4183349609374934 -1.703875 -0.153961181640625 0.4183349609374934 -1.704 -0.153961181640625 0.4183349609374934 -1.704125 -0.155426025390625 0.4183349609374934 -1.70425 -0.156890869140625 0.4183349609374934 -1.704375 -0.156890869140625 0.4183349609374934 -1.7045 -0.1583251953125 0.4183349609374934 -1.704625 -0.1583251953125 0.4183349609374934 -1.70475 -0.159759521484375 0.4183349609374934 -1.704875 -0.161163330078125 0.4183349609374934 -1.705 -0.161163330078125 0.4183349609374934 -1.705125 -0.16253662109375 0.4183349609374934 -1.70525 -0.16253662109375 0.4183349609374934 -1.705375 -0.163909912109375 0.4183349609374934 -1.7055 -0.165283203125 0.4183349609374934 -1.705625 -0.165283203125 0.4183349609374934 -1.70575 -0.166595458984375 0.4183349609374934 -1.705875 -0.166595458984375 0.4183349609374934 -1.706 -0.16790771484375 0.4183349609374934 -1.706125 -0.169219970703125 0.4183349609374934 -1.70625 -0.169219970703125 0.4183349609374934 -1.706375 -0.170501708984375 0.4183349609374934 -1.7065 -0.170501708984375 0.4183349609374934 -1.706625 -0.1717529296875 0.4183349609374934 -1.70675 -0.173004150390625 0.4183349609374934 -1.706875 -0.173004150390625 0.4183349609374934 -1.707 -0.174224853515625 0.4183349609374934 -1.707125 -0.174224853515625 0.4183349609374934 -1.70725 -0.1754150390625 0.4183349609374934 -1.707375 -0.176605224609375 0.4183349609374934 -1.7075 -0.176605224609375 0.4183349609374934 -1.707625 -0.177764892578125 0.4183349609374934 -1.70775 -0.177764892578125 0.4183349609374934 -1.707875 -0.17889404296875 0.4183349609374934 -1.708 -0.180023193359375 0.4183349609374934 -1.708125 -0.180023193359375 0.4183349609374934 -1.70825 -0.18115234375 0.4183349609374934 -1.708375 -0.18115234375 0.4183349609374934 -1.7085 -0.182220458984375 0.4183349609374934 -1.708625 -0.18328857421875 0.4183349609374934 -1.70875 -0.18328857421875 0.4183349609374934 -1.708875 -0.184326171875 0.4183349609374934 -1.709 -0.184326171875 0.4183349609374934 -1.709125 -0.18536376953125 0.4183349609374934 -1.70925 -0.186370849609375 0.4183349609374934 -1.709375 -0.186370849609375 0.4183349609374934 -1.7095 -0.187347412109375 0.4183349609374934 -1.709625 -0.187347412109375 0.4183349609374934 -1.70975 -0.18829345703125 0.4183349609374934 -1.709875 -0.189239501953125 0.4183349609374934 -1.71 -0.189239501953125 0.4183349609374934 -1.710125 -0.190185546875 0.4183349609374934 -1.71025 -0.190185546875 0.4183349609374934 -1.710375 -0.191070556640625 0.4183349609374934 -1.7105 -0.19195556640625 0.4183349609374934 -1.710625 -0.19195556640625 0.4183349609374934 -1.71075 -0.19281005859375 0.4183349609374934 -1.710875 -0.19281005859375 0.4183349609374934 -1.711 -0.19366455078125 0.4183349609374934 -1.711125 -0.1944580078125 0.4183349609374934 -1.71125 -0.1944580078125 0.4183349609374934 -1.711375 -0.19525146484375 0.4183349609374934 -1.7115 -0.19525146484375 0.4183349609374934 -1.711625 -0.196044921875 0.4183349609374934 -1.71175 -0.19677734375 0.4183349609374934 -1.711875 -0.19677734375 0.4183349609374934 -1.712 -0.197540283203125 0.4183349609374934 -1.712125 -0.197540283203125 0.4183349609374934 -1.71225 -0.1982421875 0.4183349609374934 -1.712375 -0.19891357421875 0.4183349609374934 -1.7125 -0.19891357421875 0.4183349609374934 -1.712625 -0.1995849609375 0.4183349609374934 -1.71275 -0.1995849609375 0.4183349609374934 -1.712875 -0.200225830078125 0.4183349609374934 -1.713 -0.200836181640625 0.4183349609374934 -1.713125 -0.200836181640625 0.4183349609374934 -1.71325 -0.201446533203125 0.4183349609374934 -1.713375 -0.201446533203125 0.4183349609374934 -1.7135 -0.2020263671875 0.4183349609374934 -1.713625 -0.20257568359375 0.4183349609374934 -1.71375 -0.20257568359375 0.4183349609374934 -1.713875 -0.203125 0.4183349609374934 -1.714 -0.203125 0.4183349609374934 -1.714125 -0.203643798828125 0.4183349609374934 -1.71425 -0.204132080078125 0.4183349609374934 -1.714375 -0.204132080078125 0.4183349609374934 -1.7145 -0.20458984375 0.4183349609374934 -1.714625 -0.20458984375 0.4183349609374934 -1.71475 -0.20501708984375 0.4183349609374934 -1.714875 -0.2054443359375 0.4183349609374934 -1.715 -0.2054443359375 0.4183349609374934 -1.715125 -0.205841064453125 0.4183349609374934 -1.71525 -0.205841064453125 0.4183349609374934 -1.715375 -0.20623779296875 0.4183349609374934 -1.7155 -0.206573486328125 0.4183349609374934 -1.715625 -0.206573486328125 0.4183349609374934 -1.71575 -0.2069091796875 0.4183349609374934 -1.715875 -0.2069091796875 0.4183349609374934 -1.716 -0.20721435546875 0.4183349609374934 -1.716125 -0.20751953125 0.4183349609374934 -1.71625 -0.20751953125 0.4183349609374934 -1.716375 -0.207763671875 0.4183349609374934 -1.7165 -0.207763671875 0.4183349609374934 -1.716625 -0.2080078125 0.4183349609374934 -1.71675 -0.208221435546875 0.4183349609374934 -1.716875 -0.208221435546875 0.4183349609374934 -1.717 -0.20843505859375 0.4183349609374934 -1.717125 -0.20843505859375 0.4183349609374934 -1.71725 -0.208587646484375 0.4183349609374934 -1.717375 -0.208740234375 0.4183349609374934 -1.7175 -0.208740234375 0.4183349609374934 -1.717625 -0.2088623046875 0.4183349609374934 -1.71775 -0.2088623046875 0.4183349609374934 -1.717875 -0.208984375 0.4183349609374934 -1.718 -0.20904541015625 0.4183349609374934 -1.718125 -0.20904541015625 0.4183349609374934 -1.71825 -0.2091064453125 0.4183349609374934 -1.718375 -0.2091064453125 0.4183349609374934 -1.7185 -0.209136962890625 0.4183349609374934 -1.718625 -0.20916748046875 0.4183349609374934 -1.71875 -0.20916748046875 0.4183349609374934 -1.718875 -0.209136962890625 0.4183349609374934 -1.719 -0.209136962890625 0.4183349609374934 -1.719125 -0.2091064453125 0.4183349609374934 -1.71925 -0.20904541015625 0.4183349609374934 -1.719375 -0.20904541015625 0.4183349609374934 -1.7195 -0.208984375 0.4183349609374934 -1.719625 -0.208984375 0.4183349609374934 -1.71975 -0.2088623046875 0.4183349609374934 -1.719875 -0.208740234375 0.4183349609374934 -1.72 -0.208740234375 0.4183349609374934 -1.720125 -0.208587646484375 0.4183349609374934 -1.72025 -0.208587646484375 0.4183349609374934 -1.720375 -0.20843505859375 0.4183349609374934 -1.7205 -0.208221435546875 0.4183349609374934 -1.720625 -0.208221435546875 0.4183349609374934 -1.72075 -0.2080078125 0.4183349609374934 -1.720875 -0.2080078125 0.4183349609374934 -1.721 -0.207763671875 0.4183349609374934 -1.721125 -0.20751953125 0.4183349609374934 -1.72125 -0.20751953125 0.4183349609374934 -1.721375 -0.20721435546875 0.4183349609374934 -1.7215 -0.20721435546875 0.4183349609374934 -1.721625 -0.2069091796875 0.4183349609374934 -1.72175 -0.206573486328125 0.4183349609374934 -1.721875 -0.206573486328125 0.4183349609374934 -1.722 -0.20623779296875 0.4183349609374934 -1.722125 -0.20623779296875 0.4183349609374934 -1.72225 -0.205841064453125 0.4183349609374934 -1.722375 -0.2054443359375 0.4183349609374934 -1.7225 -0.2054443359375 0.4183349609374934 -1.722625 -0.20501708984375 0.4183349609374934 -1.72275 -0.20501708984375 0.4183349609374934 -1.722875 -0.20458984375 0.4183349609374934 -1.723 -0.204132080078125 0.4183349609374934 -1.723125 -0.204132080078125 0.4183349609374934 -1.72325 -0.203643798828125 0.4183349609374934 -1.723375 -0.203643798828125 0.4183349609374934 -1.7235 -0.203125 0.4183349609374934 -1.723625 -0.20257568359375 0.4183349609374934 -1.72375 -0.20257568359375 0.4183349609374934 -1.723875 -0.2020263671875 0.4183349609374934 -1.724 -0.2020263671875 0.4183349609374934 -1.724125 -0.201446533203125 0.4183349609374934 -1.72425 -0.200836181640625 0.4183349609374934 -1.724375 -0.200836181640625 0.4183349609374934 -1.7245 -0.200225830078125 0.4183349609374934 -1.724625 -0.200225830078125 0.4183349609374934 -1.72475 -0.1995849609375 0.4183349609374934 -1.724875 -0.19891357421875 0.4183349609374934 -1.725 -0.19891357421875 0.4183349609374934 -1.725125 -0.1982421875 0.4183349609374934 -1.72525 -0.1982421875 0.4183349609374934 -1.725375 -0.197540283203125 0.4183349609374934 -1.7255 -0.19677734375 0.4183349609374934 -1.725625 -0.19677734375 0.4183349609374934 -1.72575 -0.196044921875 0.4183349609374934 -1.725875 -0.196044921875 0.4183349609374934 -1.726 -0.19525146484375 0.4183349609374934 -1.726125 -0.1944580078125 0.4183349609374934 -1.72625 -0.1944580078125 0.4183349609374934 -1.726375 -0.19366455078125 0.4183349609374934 -1.7265 -0.19366455078125 0.4183349609374934 -1.726625 -0.19281005859375 0.4183349609374934 -1.72675 -0.19195556640625 0.4183349609374934 -1.726875 -0.19195556640625 0.4183349609374934 -1.727 -0.191070556640625 0.4183349609374934 -1.727125 -0.191070556640625 0.4183349609374934 -1.72725 -0.190185546875 0.4183349609374934 -1.727375 -0.189239501953125 0.4183349609374934 -1.7275 -0.189239501953125 0.4183349609374934 -1.727625 -0.18829345703125 0.4183349609374934 -1.72775 -0.18829345703125 0.4183349609374934 -1.727875 -0.187347412109375 0.4183349609374934 -1.728 -0.04443359375 0.09975585937499341 -1.728125 -0.04443359375 0.09975585937499341 -1.72825 -0.044219970703125 0.09975585937499341 -1.728375 -0.044219970703125 0.09975585937499341 -1.7285 -0.0439453125 0.09975585937499341 -1.728625 -0.043701171875 0.09975585937499341 -1.72875 -0.043701171875 0.09975585937499341 -1.728875 -0.04345703125 0.09975585937499341 -1.729 -0.04345703125 0.09975585937499341 -1.729125 -0.043212890625 0.09975585937499341 -1.72925 -0.042938232421875 0.09975585937499341 -1.729375 -0.042938232421875 0.09975585937499341 -1.7295 -0.04266357421875 0.09975585937499341 -1.729625 -0.04266357421875 0.09975585937499341 -1.72975 -0.042388916015625 0.09975585937499341 -1.729875 -0.0421142578125 0.09975585937499341 -1.73 -0.0421142578125 0.09975585937499341 -1.730125 -0.041839599609375 0.09975585937499341 -1.73025 -0.041839599609375 0.09975585937499341 -1.730375 -0.041534423828125 0.09975585937499341 -1.7305 -0.041259765625 0.09975585937499341 -1.730625 -0.041259765625 0.09975585937499341 -1.73075 -0.04095458984375 0.09975585937499341 -1.730875 -0.04095458984375 0.09975585937499341 -1.731 -0.0406494140625 0.09975585937499341 -1.731125 -0.04034423828125 0.09975585937499341 -1.73125 -0.04034423828125 0.09975585937499341 -1.731375 -0.0400390625 0.09975585937499341 -1.7315 -0.0400390625 0.09975585937499341 -1.731625 -0.03973388671875 0.09975585937499341 -1.73175 -0.0394287109375 0.09975585937499341 -1.731875 -0.0394287109375 0.09975585937499341 -1.732 -0.039093017578125 0.09975585937499341 -1.732125 -0.039093017578125 0.09975585937499341 -1.73225 -0.03875732421875 0.09975585937499341 -1.732375 -0.038421630859375 0.09975585937499341 -1.7325 -0.038421630859375 0.09975585937499341 -1.732625 -0.0380859375 0.09975585937499341 -1.73275 -0.0380859375 0.09975585937499341 -1.732875 -0.037750244140625 0.09975585937499341 -1.733 -0.03741455078125 0.09975585937499341 -1.733125 -0.03741455078125 0.09975585937499341 -1.73325 -0.037078857421875 0.09975585937499341 -1.733375 -0.037078857421875 0.09975585937499341 -1.7335 -0.036712646484375 0.09975585937499341 -1.733625 -0.036376953125 0.09975585937499341 -1.73375 -0.036376953125 0.09975585937499341 -1.733875 -0.0360107421875 0.09975585937499341 -1.734 -0.0360107421875 0.09975585937499341 -1.734125 -0.03564453125 0.09975585937499341 -1.73425 -0.0352783203125 0.09975585937499341 -1.734375 -0.0352783203125 0.09975585937499341 -1.7345 -0.034912109375 0.09975585937499341 -1.734625 -0.034912109375 0.09975585937499341 -1.73475 -0.034515380859375 0.09975585937499341 -1.734875 -0.034149169921875 0.09975585937499341 -1.735 -0.034149169921875 0.09975585937499341 -1.735125 -0.03375244140625 0.09975585937499341 -1.73525 -0.03375244140625 0.09975585937499341 -1.735375 -0.03338623046875 0.09975585937499341 -1.7355 -0.032989501953125 0.09975585937499341 -1.735625 -0.032989501953125 0.09975585937499341 -1.73575 -0.0325927734375 0.09975585937499341 -1.735875 -0.0325927734375 0.09975585937499341 -1.736 -0.032196044921875 0.09975585937499341 -1.736125 -0.03179931640625 0.09975585937499341 -1.73625 -0.03179931640625 0.09975585937499341 -1.736375 -0.031402587890625 0.09975585937499341 -1.7365 -0.031402587890625 0.09975585937499341 -1.736625 -0.030975341796875 0.09975585937499341 -1.73675 -0.03057861328125 0.09975585937499341 -1.736875 -0.03057861328125 0.09975585937499341 -1.737 -0.0301513671875 0.09975585937499341 -1.737125 -0.0301513671875 0.09975585937499341 -1.73725 -0.029754638671875 0.09975585937499341 -1.737375 -0.029327392578125 0.09975585937499341 -1.7375 -0.029327392578125 0.09975585937499341 -1.737625 -0.028900146484375 0.09975585937499341 -1.73775 -0.028900146484375 0.09975585937499341 -1.737875 -0.028472900390625 0.09975585937499341 -1.738 -0.028045654296875 0.09975585937499341 -1.738125 -0.028045654296875 0.09975585937499341 -1.73825 -0.027618408203125 0.09975585937499341 -1.738375 -0.027618408203125 0.09975585937499341 -1.7385 -0.02716064453125 0.09975585937499341 -1.738625 -0.0267333984375 0.09975585937499341 -1.73875 -0.0267333984375 0.09975585937499341 -1.738875 -0.026275634765625 0.09975585937499341 -1.739 -0.026275634765625 0.09975585937499341 -1.739125 -0.025848388671875 0.09975585937499341 -1.73925 -0.025390625 0.09975585937499341 -1.739375 -0.025390625 0.09975585937499341 -1.7395 -0.024932861328125 0.09975585937499341 -1.739625 -0.024932861328125 0.09975585937499341 -1.73975 -0.024505615234375 0.09975585937499341 -1.739875 -0.0240478515625 0.09975585937499341 -1.74 -0.0240478515625 0.09975585937499341 -1.740125 -0.023590087890625 0.09975585937499341 -1.74025 -0.023590087890625 0.09975585937499341 -1.740375 -0.023101806640625 0.09975585937499341 -1.7405 -0.02264404296875 0.09975585937499341 -1.740625 -0.02264404296875 0.09975585937499341 -1.74075 -0.022186279296875 0.09975585937499341 -1.740875 -0.022186279296875 0.09975585937499341 -1.741 -0.021728515625 0.09975585937499341 -1.741125 -0.021240234375 0.09975585937499341 -1.74125 -0.021240234375 0.09975585937499341 -1.741375 -0.020782470703125 0.09975585937499341 -1.7415 -0.020782470703125 0.09975585937499341 -1.741625 -0.020294189453125 0.09975585937499341 -1.74175 -0.019805908203125 0.09975585937499341 -1.741875 -0.019805908203125 0.09975585937499341 -1.742 -0.01934814453125 0.09975585937499341 -1.742125 -0.01934814453125 0.09975585937499341 -1.74225 -0.01885986328125 0.09975585937499341 -1.742375 -0.01837158203125 0.09975585937499341 -1.7425 -0.01837158203125 0.09975585937499341 -1.742625 -0.01788330078125 0.09975585937499341 -1.74275 -0.01788330078125 0.09975585937499341 -1.742875 -0.01739501953125 0.09975585937499341 -1.743 -0.01690673828125 0.09975585937499341 -1.743125 -0.01690673828125 0.09975585937499341 -1.74325 -0.01641845703125 0.09975585937499341 -1.743375 -0.01641845703125 0.09975585937499341 -1.7435 -0.01593017578125 0.09975585937499341 -1.743625 -0.015411376953125 0.09975585937499341 -1.74375 -0.015411376953125 0.09975585937499341 -1.743875 -0.014923095703125 0.09975585937499341 -1.744 -0.014923095703125 0.09975585937499341 -1.744125 -0.014434814453125 0.09975585937499341 -1.74425 -0.013916015625 0.09975585937499341 -1.744375 -0.013916015625 0.09975585937499341 -1.7445 -0.013427734375 0.09975585937499341 -1.744625 -0.013427734375 0.09975585937499341 -1.74475 -0.012908935546875 0.09975585937499341 -1.744875 -0.012420654296875 0.09975585937499341 -1.745 -0.012420654296875 0.09975585937499341 -1.745125 -0.01190185546875 0.09975585937499341 -1.74525 -0.01190185546875 0.09975585937499341 -1.745375 -0.01141357421875 0.09975585937499341 -1.7455 -0.010894775390625 0.09975585937499341 -1.745625 -0.010894775390625 0.09975585937499341 -1.74575 -0.0103759765625 0.09975585937499341 -1.745875 -0.0103759765625 0.09975585937499341 -1.746 -0.009857177734375 0.09975585937499341 -1.746125 -0.009368896484375 0.09975585937499341 -1.74625 -0.009368896484375 0.09975585937499341 -1.746375 -0.00885009765625 0.09975585937499341 -1.7465 -0.00885009765625 0.09975585937499341 -1.746625 -0.008331298828125 0.09975585937499341 -1.74675 -0.0078125 0.09975585937499341 -1.746875 -0.0078125 0.09975585937499341 -1.747 -0.007293701171875 0.09975585937499341 -1.747125 -0.007293701171875 0.09975585937499341 -1.74725 -0.00677490234375 0.09975585937499341 -1.747375 -0.006256103515625 0.09975585937499341 -1.7475 -0.006256103515625 0.09975585937499341 -1.747625 -0.0057373046875 0.09975585937499341 -1.74775 -0.0057373046875 0.09975585937499341 -1.747875 -0.005218505859375 0.09975585937499341 -1.748 -0.00469970703125 0.09975585937499341 -1.748125 -0.00469970703125 0.09975585937499341 -1.74825 -0.004180908203125 0.09975585937499341 -1.748375 -0.004180908203125 0.09975585937499341 -1.7485 -0.003662109375 0.09975585937499341 -1.748625 -0.003143310546875 0.09975585937499341 -1.74875 -0.003143310546875 0.09975585937499341 -1.748875 -0.00262451171875 0.09975585937499341 -1.749 -0.00262451171875 0.09975585937499341 -1.749125 -0.002105712890625 0.09975585937499341 -1.74925 -0.0015869140625 0.09975585937499341 -1.749375 -0.0015869140625 0.09975585937499341 -1.7495 -0.001068115234375 0.09975585937499341 -1.749625 -0.001068115234375 0.09975585937499341 -1.74975 -0.00054931640625 0.09975585937499341 +1.687625 -0.003662109375 0.7021142578124948 +1.68775 -0.003662109375 0.7021142578124948 +1.687875 -0.00732421875 0.7021142578124948 +1.688 -0.011016845703125 0.7021142578124948 +1.688125 -0.011016845703125 0.7021142578124948 +1.68825 -0.014678955078125 0.7021142578124948 +1.688375 -0.014678955078125 0.7021142578124948 +1.6885 -0.018341064453125 0.7021142578124948 +1.688625 -0.02203369140625 0.7021142578124948 +1.68875 -0.02203369140625 0.7021142578124948 +1.688875 -0.02569580078125 0.7021142578124948 +1.689 -0.02569580078125 0.7021142578124948 +1.689125 -0.02935791015625 0.7021142578124948 +1.68925 -0.03302001953125 0.7021142578124948 +1.689375 -0.03302001953125 0.7021142578124948 +1.6895 -0.03668212890625 0.7021142578124948 +1.689625 -0.03668212890625 0.7021142578124948 +1.68975 -0.04034423828125 0.7021142578124948 +1.689875 -0.043975830078125 0.7021142578124948 +1.69 -0.043975830078125 0.7021142578124948 +1.690125 -0.047607421875 0.7021142578124948 +1.69025 -0.047607421875 0.7021142578124948 +1.690375 -0.05126953125 0.7021142578124948 +1.6905 -0.054901123046875 0.7021142578124948 +1.690625 -0.054901123046875 0.7021142578124948 +1.69075 -0.05853271484375 0.7021142578124948 +1.690875 -0.05853271484375 0.7021142578124948 +1.691 -0.0621337890625 0.7021142578124948 +1.691125 -0.065765380859375 0.7021142578124948 +1.69125 -0.065765380859375 0.7021142578124948 +1.691375 -0.069366455078125 0.7021142578124948 +1.6915 -0.069366455078125 0.7021142578124948 +1.691625 -0.072967529296875 0.7021142578124948 +1.69175 -0.0765380859375 0.7021142578124948 +1.691875 -0.0765380859375 0.7021142578124948 +1.692 -0.08013916015625 0.7021142578124948 +1.692125 -0.08013916015625 0.7021142578124948 +1.69225 -0.083709716796875 0.7021142578124948 +1.692375 -0.0872802734375 0.7021142578124948 +1.6925 -0.0872802734375 0.7021142578124948 +1.692625 -0.0908203125 0.7021142578124948 +1.69275 -0.0908203125 0.7021142578124948 +1.692875 -0.094390869140625 0.7021142578124948 +1.693 -0.097900390625 0.7021142578124948 +1.693125 -0.097900390625 0.7021142578124948 +1.69325 -0.1014404296875 0.7021142578124948 +1.693375 -0.1014404296875 0.7021142578124948 +1.6935 -0.104949951171875 0.7021142578124948 +1.693625 -0.10845947265625 0.7021142578124948 +1.69375 -0.10845947265625 0.7021142578124948 +1.693875 -0.1119384765625 0.7021142578124948 +1.694 -0.1119384765625 0.7021142578124948 +1.694125 -0.11541748046875 0.7021142578124948 +1.69425 -0.118896484375 0.7021142578124948 +1.694375 -0.118896484375 0.7021142578124948 +1.6945 -0.122344970703125 0.7021142578124948 +1.694625 -0.122344970703125 0.7021142578124948 +1.69475 -0.125762939453125 0.7021142578124948 +1.694875 -0.12921142578125 0.7021142578124948 +1.695 -0.12921142578125 0.7021142578124948 +1.695125 -0.132598876953125 0.7021142578124948 +1.69525 -0.132598876953125 0.7021142578124948 +1.695375 -0.136016845703125 0.7021142578124948 +1.6955 -0.139404296875 0.7021142578124948 +1.695625 -0.139404296875 0.7021142578124948 +1.69575 -0.14276123046875 0.7021142578124948 +1.695875 -0.14276123046875 0.7021142578124948 +1.696 -0.0870361328125 0.4183349609374934 +1.696125 -0.089019775390625 0.4183349609374934 +1.69625 -0.089019775390625 0.4183349609374934 +1.696375 -0.09100341796875 0.4183349609374934 +1.6965 -0.09100341796875 0.4183349609374934 +1.696625 -0.092987060546875 0.4183349609374934 +1.69675 -0.094940185546875 0.4183349609374934 +1.696875 -0.094940185546875 0.4183349609374934 +1.697 -0.09686279296875 0.4183349609374934 +1.697125 -0.09686279296875 0.4183349609374934 +1.69725 -0.09881591796875 0.4183349609374934 +1.697375 -0.100738525390625 0.4183349609374934 +1.6975 -0.100738525390625 0.4183349609374934 +1.697625 -0.1026611328125 0.4183349609374934 +1.69775 -0.1026611328125 0.4183349609374934 +1.697875 -0.10455322265625 0.4183349609374934 +1.698 -0.1064453125 0.4183349609374934 +1.698125 -0.1064453125 0.4183349609374934 +1.69825 -0.10833740234375 0.4183349609374934 +1.698375 -0.10833740234375 0.4183349609374934 +1.6985 -0.110198974609375 0.4183349609374934 +1.698625 -0.112060546875 0.4183349609374934 +1.69875 -0.112060546875 0.4183349609374934 +1.698875 -0.1138916015625 0.4183349609374934 +1.699 -0.1138916015625 0.4183349609374934 +1.699125 -0.11572265625 0.4183349609374934 +1.69925 -0.117523193359375 0.4183349609374934 +1.699375 -0.117523193359375 0.4183349609374934 +1.6995 -0.119354248046875 0.4183349609374934 +1.699625 -0.119354248046875 0.4183349609374934 +1.69975 -0.121124267578125 0.4183349609374934 +1.699875 -0.1229248046875 0.4183349609374934 +1.7 -0.1229248046875 0.4183349609374934 +1.700125 -0.124664306640625 0.4183349609374934 +1.70025 -0.124664306640625 0.4183349609374934 +1.700375 -0.126434326171875 0.4183349609374934 +1.7005 -0.128173828125 0.4183349609374934 +1.700625 -0.128173828125 0.4183349609374934 +1.70075 -0.1298828125 0.4183349609374934 +1.700875 -0.1298828125 0.4183349609374934 +1.701 -0.131591796875 0.4183349609374934 +1.701125 -0.13330078125 0.4183349609374934 +1.70125 -0.13330078125 0.4183349609374934 +1.701375 -0.134979248046875 0.4183349609374934 +1.7015 -0.134979248046875 0.4183349609374934 +1.701625 -0.136627197265625 0.4183349609374934 +1.70175 -0.1383056640625 0.4183349609374934 +1.701875 -0.1383056640625 0.4183349609374934 +1.702 -0.139923095703125 0.4183349609374934 +1.702125 -0.139923095703125 0.4183349609374934 +1.70225 -0.14154052734375 0.4183349609374934 +1.702375 -0.143157958984375 0.4183349609374934 +1.7025 -0.143157958984375 0.4183349609374934 +1.702625 -0.144744873046875 0.4183349609374934 +1.70275 -0.144744873046875 0.4183349609374934 +1.702875 -0.14630126953125 0.4183349609374934 +1.703 -0.147857666015625 0.4183349609374934 +1.703125 -0.147857666015625 0.4183349609374934 +1.70325 -0.1494140625 0.4183349609374934 +1.703375 -0.1494140625 0.4183349609374934 +1.7035 -0.15093994140625 0.4183349609374934 +1.703625 -0.152435302734375 0.4183349609374934 +1.70375 -0.152435302734375 0.4183349609374934 +1.703875 -0.1539306640625 0.4183349609374934 +1.704 -0.1539306640625 0.4183349609374934 +1.704125 -0.1553955078125 0.4183349609374934 +1.70425 -0.1568603515625 0.4183349609374934 +1.704375 -0.1568603515625 0.4183349609374934 +1.7045 -0.158294677734375 0.4183349609374934 +1.704625 -0.158294677734375 0.4183349609374934 +1.70475 -0.15972900390625 0.4183349609374934 +1.704875 -0.1611328125 0.4183349609374934 +1.705 -0.1611328125 0.4183349609374934 +1.705125 -0.162506103515625 0.4183349609374934 +1.70525 -0.162506103515625 0.4183349609374934 +1.705375 -0.16387939453125 0.4183349609374934 +1.7055 -0.165252685546875 0.4183349609374934 +1.705625 -0.165252685546875 0.4183349609374934 +1.70575 -0.16656494140625 0.4183349609374934 +1.705875 -0.16656494140625 0.4183349609374934 +1.706 -0.167877197265625 0.4183349609374934 +1.706125 -0.169189453125 0.4183349609374934 +1.70625 -0.169189453125 0.4183349609374934 +1.706375 -0.17047119140625 0.4183349609374934 +1.7065 -0.17047119140625 0.4183349609374934 +1.706625 -0.171722412109375 0.4183349609374934 +1.70675 -0.1729736328125 0.4183349609374934 +1.706875 -0.1729736328125 0.4183349609374934 +1.707 -0.1741943359375 0.4183349609374934 +1.707125 -0.1741943359375 0.4183349609374934 +1.70725 -0.175384521484375 0.4183349609374934 +1.707375 -0.17657470703125 0.4183349609374934 +1.7075 -0.17657470703125 0.4183349609374934 +1.707625 -0.177734375 0.4183349609374934 +1.70775 -0.177734375 0.4183349609374934 +1.707875 -0.178863525390625 0.4183349609374934 +1.708 -0.17999267578125 0.4183349609374934 +1.708125 -0.17999267578125 0.4183349609374934 +1.70825 -0.181121826171875 0.4183349609374934 +1.708375 -0.181121826171875 0.4183349609374934 +1.7085 -0.18218994140625 0.4183349609374934 +1.708625 -0.183258056640625 0.4183349609374934 +1.70875 -0.183258056640625 0.4183349609374934 +1.708875 -0.184295654296875 0.4183349609374934 +1.709 -0.184295654296875 0.4183349609374934 +1.709125 -0.185333251953125 0.4183349609374934 +1.70925 -0.18634033203125 0.4183349609374934 +1.709375 -0.18634033203125 0.4183349609374934 +1.7095 -0.18731689453125 0.4183349609374934 +1.709625 -0.18731689453125 0.4183349609374934 +1.70975 -0.188262939453125 0.4183349609374934 +1.709875 -0.189208984375 0.4183349609374934 +1.71 -0.189208984375 0.4183349609374934 +1.710125 -0.190155029296875 0.4183349609374934 +1.71025 -0.190155029296875 0.4183349609374934 +1.710375 -0.1910400390625 0.4183349609374934 +1.7105 -0.191925048828125 0.4183349609374934 +1.710625 -0.191925048828125 0.4183349609374934 +1.71075 -0.192779541015625 0.4183349609374934 +1.710875 -0.192779541015625 0.4183349609374934 +1.711 -0.193634033203125 0.4183349609374934 +1.711125 -0.194427490234375 0.4183349609374934 +1.71125 -0.194427490234375 0.4183349609374934 +1.711375 -0.195220947265625 0.4183349609374934 +1.7115 -0.195220947265625 0.4183349609374934 +1.711625 -0.196014404296875 0.4183349609374934 +1.71175 -0.196746826171875 0.4183349609374934 +1.711875 -0.196746826171875 0.4183349609374934 +1.712 -0.197509765625 0.4183349609374934 +1.712125 -0.197509765625 0.4183349609374934 +1.71225 -0.198211669921875 0.4183349609374934 +1.712375 -0.198883056640625 0.4183349609374934 +1.7125 -0.198883056640625 0.4183349609374934 +1.712625 -0.199554443359375 0.4183349609374934 +1.71275 -0.199554443359375 0.4183349609374934 +1.712875 -0.2001953125 0.4183349609374934 +1.713 -0.2008056640625 0.4183349609374934 +1.713125 -0.2008056640625 0.4183349609374934 +1.71325 -0.201416015625 0.4183349609374934 +1.713375 -0.201416015625 0.4183349609374934 +1.7135 -0.201995849609375 0.4183349609374934 +1.713625 -0.202545166015625 0.4183349609374934 +1.71375 -0.202545166015625 0.4183349609374934 +1.713875 -0.203094482421875 0.4183349609374934 +1.714 -0.203094482421875 0.4183349609374934 +1.714125 -0.20361328125 0.4183349609374934 +1.71425 -0.2041015625 0.4183349609374934 +1.714375 -0.2041015625 0.4183349609374934 +1.7145 -0.204559326171875 0.4183349609374934 +1.714625 -0.204559326171875 0.4183349609374934 +1.71475 -0.204986572265625 0.4183349609374934 +1.714875 -0.205413818359375 0.4183349609374934 +1.715 -0.205413818359375 0.4183349609374934 +1.715125 -0.205810546875 0.4183349609374934 +1.71525 -0.205810546875 0.4183349609374934 +1.715375 -0.206207275390625 0.4183349609374934 +1.7155 -0.20654296875 0.4183349609374934 +1.715625 -0.20654296875 0.4183349609374934 +1.71575 -0.206878662109375 0.4183349609374934 +1.715875 -0.206878662109375 0.4183349609374934 +1.716 -0.207183837890625 0.4183349609374934 +1.716125 -0.207489013671875 0.4183349609374934 +1.71625 -0.207489013671875 0.4183349609374934 +1.716375 -0.207733154296875 0.4183349609374934 +1.7165 -0.207733154296875 0.4183349609374934 +1.716625 -0.207977294921875 0.4183349609374934 +1.71675 -0.20819091796875 0.4183349609374934 +1.716875 -0.20819091796875 0.4183349609374934 +1.717 -0.208404541015625 0.4183349609374934 +1.717125 -0.208404541015625 0.4183349609374934 +1.71725 -0.20855712890625 0.4183349609374934 +1.717375 -0.208709716796875 0.4183349609374934 +1.7175 -0.208709716796875 0.4183349609374934 +1.717625 -0.208831787109375 0.4183349609374934 +1.71775 -0.208831787109375 0.4183349609374934 +1.717875 -0.208953857421875 0.4183349609374934 +1.718 -0.209014892578125 0.4183349609374934 +1.718125 -0.209014892578125 0.4183349609374934 +1.71825 -0.209075927734375 0.4183349609374934 +1.718375 -0.209075927734375 0.4183349609374934 +1.7185 -0.2091064453125 0.4183349609374934 +1.718625 -0.209136962890625 0.4183349609374934 +1.71875 -0.209136962890625 0.4183349609374934 +1.718875 -0.2091064453125 0.4183349609374934 +1.719 -0.2091064453125 0.4183349609374934 +1.719125 -0.209075927734375 0.4183349609374934 +1.71925 -0.209014892578125 0.4183349609374934 +1.719375 -0.209014892578125 0.4183349609374934 +1.7195 -0.208953857421875 0.4183349609374934 +1.719625 -0.208953857421875 0.4183349609374934 +1.71975 -0.208831787109375 0.4183349609374934 +1.719875 -0.208709716796875 0.4183349609374934 +1.72 -0.208709716796875 0.4183349609374934 +1.720125 -0.20855712890625 0.4183349609374934 +1.72025 -0.20855712890625 0.4183349609374934 +1.720375 -0.208404541015625 0.4183349609374934 +1.7205 -0.20819091796875 0.4183349609374934 +1.720625 -0.20819091796875 0.4183349609374934 +1.72075 -0.207977294921875 0.4183349609374934 +1.720875 -0.207977294921875 0.4183349609374934 +1.721 -0.207733154296875 0.4183349609374934 +1.721125 -0.207489013671875 0.4183349609374934 +1.72125 -0.207489013671875 0.4183349609374934 +1.721375 -0.207183837890625 0.4183349609374934 +1.7215 -0.207183837890625 0.4183349609374934 +1.721625 -0.206878662109375 0.4183349609374934 +1.72175 -0.20654296875 0.4183349609374934 +1.721875 -0.20654296875 0.4183349609374934 +1.722 -0.206207275390625 0.4183349609374934 +1.722125 -0.206207275390625 0.4183349609374934 +1.72225 -0.205810546875 0.4183349609374934 +1.722375 -0.205413818359375 0.4183349609374934 +1.7225 -0.205413818359375 0.4183349609374934 +1.722625 -0.204986572265625 0.4183349609374934 +1.72275 -0.204986572265625 0.4183349609374934 +1.722875 -0.204559326171875 0.4183349609374934 +1.723 -0.2041015625 0.4183349609374934 +1.723125 -0.2041015625 0.4183349609374934 +1.72325 -0.20361328125 0.4183349609374934 +1.723375 -0.20361328125 0.4183349609374934 +1.7235 -0.203094482421875 0.4183349609374934 +1.723625 -0.202545166015625 0.4183349609374934 +1.72375 -0.202545166015625 0.4183349609374934 +1.723875 -0.201995849609375 0.4183349609374934 +1.724 -0.201995849609375 0.4183349609374934 +1.724125 -0.201416015625 0.4183349609374934 +1.72425 -0.2008056640625 0.4183349609374934 +1.724375 -0.2008056640625 0.4183349609374934 +1.7245 -0.2001953125 0.4183349609374934 +1.724625 -0.2001953125 0.4183349609374934 +1.72475 -0.199554443359375 0.4183349609374934 +1.724875 -0.198883056640625 0.4183349609374934 +1.725 -0.198883056640625 0.4183349609374934 +1.725125 -0.198211669921875 0.4183349609374934 +1.72525 -0.198211669921875 0.4183349609374934 +1.725375 -0.197509765625 0.4183349609374934 +1.7255 -0.196746826171875 0.4183349609374934 +1.725625 -0.196746826171875 0.4183349609374934 +1.72575 -0.196014404296875 0.4183349609374934 +1.725875 -0.196014404296875 0.4183349609374934 +1.726 -0.195220947265625 0.4183349609374934 +1.726125 -0.194427490234375 0.4183349609374934 +1.72625 -0.194427490234375 0.4183349609374934 +1.726375 -0.193634033203125 0.4183349609374934 +1.7265 -0.193634033203125 0.4183349609374934 +1.726625 -0.192779541015625 0.4183349609374934 +1.72675 -0.191925048828125 0.4183349609374934 +1.726875 -0.191925048828125 0.4183349609374934 +1.727 -0.1910400390625 0.4183349609374934 +1.727125 -0.1910400390625 0.4183349609374934 +1.72725 -0.190155029296875 0.4183349609374934 +1.727375 -0.189208984375 0.4183349609374934 +1.7275 -0.189208984375 0.4183349609374934 +1.727625 -0.188262939453125 0.4183349609374934 +1.72775 -0.188262939453125 0.4183349609374934 +1.727875 -0.18731689453125 0.4183349609374934 +1.728 -0.044403076171875 0.09975585937499341 +1.728125 -0.044403076171875 0.09975585937499341 +1.72825 -0.044189453125 0.09975585937499341 +1.728375 -0.044189453125 0.09975585937499341 +1.7285 -0.043914794921875 0.09975585937499341 +1.728625 -0.043670654296875 0.09975585937499341 +1.72875 -0.043670654296875 0.09975585937499341 +1.728875 -0.043426513671875 0.09975585937499341 +1.729 -0.043426513671875 0.09975585937499341 +1.729125 -0.043182373046875 0.09975585937499341 +1.72925 -0.04290771484375 0.09975585937499341 +1.729375 -0.04290771484375 0.09975585937499341 +1.7295 -0.042633056640625 0.09975585937499341 +1.729625 -0.042633056640625 0.09975585937499341 +1.72975 -0.0423583984375 0.09975585937499341 +1.729875 -0.042083740234375 0.09975585937499341 +1.73 -0.042083740234375 0.09975585937499341 +1.730125 -0.04180908203125 0.09975585937499341 +1.73025 -0.04180908203125 0.09975585937499341 +1.730375 -0.04150390625 0.09975585937499341 +1.7305 -0.041229248046875 0.09975585937499341 +1.730625 -0.041229248046875 0.09975585937499341 +1.73075 -0.040924072265625 0.09975585937499341 +1.730875 -0.040924072265625 0.09975585937499341 +1.731 -0.040618896484375 0.09975585937499341 +1.731125 -0.040313720703125 0.09975585937499341 +1.73125 -0.040313720703125 0.09975585937499341 +1.731375 -0.040008544921875 0.09975585937499341 +1.7315 -0.040008544921875 0.09975585937499341 +1.731625 -0.039703369140625 0.09975585937499341 +1.73175 -0.039398193359375 0.09975585937499341 +1.731875 -0.039398193359375 0.09975585937499341 +1.732 -0.0390625 0.09975585937499341 +1.732125 -0.0390625 0.09975585937499341 +1.73225 -0.038726806640625 0.09975585937499341 +1.732375 -0.03839111328125 0.09975585937499341 +1.7325 -0.03839111328125 0.09975585937499341 +1.732625 -0.038055419921875 0.09975585937499341 +1.73275 -0.038055419921875 0.09975585937499341 +1.732875 -0.0377197265625 0.09975585937499341 +1.733 -0.037384033203125 0.09975585937499341 +1.733125 -0.037384033203125 0.09975585937499341 +1.73325 -0.03704833984375 0.09975585937499341 +1.733375 -0.03704833984375 0.09975585937499341 +1.7335 -0.03668212890625 0.09975585937499341 +1.733625 -0.036346435546875 0.09975585937499341 +1.73375 -0.036346435546875 0.09975585937499341 +1.733875 -0.035980224609375 0.09975585937499341 +1.734 -0.035980224609375 0.09975585937499341 +1.734125 -0.035614013671875 0.09975585937499341 +1.73425 -0.035247802734375 0.09975585937499341 +1.734375 -0.035247802734375 0.09975585937499341 +1.7345 -0.034881591796875 0.09975585937499341 +1.734625 -0.034881591796875 0.09975585937499341 +1.73475 -0.03448486328125 0.09975585937499341 +1.734875 -0.03411865234375 0.09975585937499341 +1.735 -0.03411865234375 0.09975585937499341 +1.735125 -0.033721923828125 0.09975585937499341 +1.73525 -0.033721923828125 0.09975585937499341 +1.735375 -0.033355712890625 0.09975585937499341 +1.7355 -0.032958984375 0.09975585937499341 +1.735625 -0.032958984375 0.09975585937499341 +1.73575 -0.032562255859375 0.09975585937499341 +1.735875 -0.032562255859375 0.09975585937499341 +1.736 -0.03216552734375 0.09975585937499341 +1.736125 -0.031768798828125 0.09975585937499341 +1.73625 -0.031768798828125 0.09975585937499341 +1.736375 -0.0313720703125 0.09975585937499341 +1.7365 -0.0313720703125 0.09975585937499341 +1.736625 -0.03094482421875 0.09975585937499341 +1.73675 -0.030548095703125 0.09975585937499341 +1.736875 -0.030548095703125 0.09975585937499341 +1.737 -0.030120849609375 0.09975585937499341 +1.737125 -0.030120849609375 0.09975585937499341 +1.73725 -0.02972412109375 0.09975585937499341 +1.737375 -0.029296875 0.09975585937499341 +1.7375 -0.029296875 0.09975585937499341 +1.737625 -0.02886962890625 0.09975585937499341 +1.73775 -0.02886962890625 0.09975585937499341 +1.737875 -0.0284423828125 0.09975585937499341 +1.738 -0.02801513671875 0.09975585937499341 +1.738125 -0.02801513671875 0.09975585937499341 +1.73825 -0.027587890625 0.09975585937499341 +1.738375 -0.027587890625 0.09975585937499341 +1.7385 -0.027130126953125 0.09975585937499341 +1.738625 -0.026702880859375 0.09975585937499341 +1.73875 -0.026702880859375 0.09975585937499341 +1.738875 -0.0262451171875 0.09975585937499341 +1.739 -0.0262451171875 0.09975585937499341 +1.739125 -0.02581787109375 0.09975585937499341 +1.73925 -0.025360107421875 0.09975585937499341 +1.739375 -0.025360107421875 0.09975585937499341 +1.7395 -0.02490234375 0.09975585937499341 +1.739625 -0.02490234375 0.09975585937499341 +1.73975 -0.02447509765625 0.09975585937499341 +1.739875 -0.024017333984375 0.09975585937499341 +1.74 -0.024017333984375 0.09975585937499341 +1.740125 -0.0235595703125 0.09975585937499341 +1.74025 -0.0235595703125 0.09975585937499341 +1.740375 -0.0230712890625 0.09975585937499341 +1.7405 -0.022613525390625 0.09975585937499341 +1.740625 -0.022613525390625 0.09975585937499341 +1.74075 -0.02215576171875 0.09975585937499341 +1.740875 -0.02215576171875 0.09975585937499341 +1.741 -0.021697998046875 0.09975585937499341 +1.741125 -0.021209716796875 0.09975585937499341 +1.74125 -0.021209716796875 0.09975585937499341 +1.741375 -0.020751953125 0.09975585937499341 +1.7415 -0.020751953125 0.09975585937499341 +1.741625 -0.020263671875 0.09975585937499341 +1.74175 -0.019775390625 0.09975585937499341 +1.741875 -0.019775390625 0.09975585937499341 +1.742 -0.019317626953125 0.09975585937499341 +1.742125 -0.019317626953125 0.09975585937499341 +1.74225 -0.018829345703125 0.09975585937499341 +1.742375 -0.018341064453125 0.09975585937499341 +1.7425 -0.018341064453125 0.09975585937499341 +1.742625 -0.017852783203125 0.09975585937499341 +1.74275 -0.017852783203125 0.09975585937499341 +1.742875 -0.017364501953125 0.09975585937499341 +1.743 -0.016876220703125 0.09975585937499341 +1.743125 -0.016876220703125 0.09975585937499341 +1.74325 -0.016387939453125 0.09975585937499341 +1.743375 -0.016387939453125 0.09975585937499341 +1.7435 -0.015899658203125 0.09975585937499341 +1.743625 -0.015380859375 0.09975585937499341 +1.74375 -0.015380859375 0.09975585937499341 +1.743875 -0.014892578125 0.09975585937499341 +1.744 -0.014892578125 0.09975585937499341 +1.744125 -0.014404296875 0.09975585937499341 +1.74425 -0.013885498046875 0.09975585937499341 +1.744375 -0.013885498046875 0.09975585937499341 +1.7445 -0.013397216796875 0.09975585937499341 +1.744625 -0.013397216796875 0.09975585937499341 +1.74475 -0.01287841796875 0.09975585937499341 +1.744875 -0.01239013671875 0.09975585937499341 +1.745 -0.01239013671875 0.09975585937499341 +1.745125 -0.011871337890625 0.09975585937499341 +1.74525 -0.011871337890625 0.09975585937499341 +1.745375 -0.011383056640625 0.09975585937499341 +1.7455 -0.0108642578125 0.09975585937499341 +1.745625 -0.0108642578125 0.09975585937499341 +1.74575 -0.010345458984375 0.09975585937499341 +1.745875 -0.010345458984375 0.09975585937499341 +1.746 -0.00982666015625 0.09975585937499341 +1.746125 -0.00933837890625 0.09975585937499341 +1.74625 -0.00933837890625 0.09975585937499341 +1.746375 -0.008819580078125 0.09975585937499341 +1.7465 -0.008819580078125 0.09975585937499341 +1.746625 -0.00830078125 0.09975585937499341 +1.74675 -0.007781982421875 0.09975585937499341 +1.746875 -0.007781982421875 0.09975585937499341 +1.747 -0.00726318359375 0.09975585937499341 +1.747125 -0.00726318359375 0.09975585937499341 +1.74725 -0.006744384765625 0.09975585937499341 +1.747375 -0.0062255859375 0.09975585937499341 +1.7475 -0.0062255859375 0.09975585937499341 +1.747625 -0.005706787109375 0.09975585937499341 +1.74775 -0.005706787109375 0.09975585937499341 +1.747875 -0.00518798828125 0.09975585937499341 +1.748 -0.004669189453125 0.09975585937499341 +1.748125 -0.004669189453125 0.09975585937499341 +1.74825 -0.004150390625 0.09975585937499341 +1.748375 -0.004150390625 0.09975585937499341 +1.7485 -0.003631591796875 0.09975585937499341 +1.748625 -0.00311279296875 0.09975585937499341 +1.74875 -0.00311279296875 0.09975585937499341 +1.748875 -0.002593994140625 0.09975585937499341 +1.749 -0.002593994140625 0.09975585937499341 +1.749125 -0.0020751953125 0.09975585937499341 +1.74925 -0.001556396484375 0.09975585937499341 +1.749375 -0.001556396484375 0.09975585937499341 +1.7495 -0.00103759765625 0.09975585937499341 +1.749625 -0.00103759765625 0.09975585937499341 +1.74975 -0.000518798828125 0.09975585937499341 1.749875 0.0 0.09975585937499341 1.75 0.0 0.09975585937499341 1.750125 0.000518798828125 0.09975585937499341 @@ -14078,425 +14078,425 @@ 1.759625 0.0230712890625 0.09975585937499341 1.75975 0.0235595703125 0.09975585937499341 1.759875 0.024017333984375 0.09975585937499341 -1.76 -0.04888916015625 -0.202866210937506 -1.760125 -0.0498046875 -0.202866210937506 -1.76025 -0.0498046875 -0.202866210937506 -1.760375 -0.05072021484375 -0.202866210937506 -1.7605 -0.0516357421875 -0.202866210937506 -1.760625 -0.0516357421875 -0.202866210937506 -1.76075 -0.05255126953125 -0.202866210937506 -1.760875 -0.05255126953125 -0.202866210937506 -1.761 -0.053466796875 -0.202866210937506 -1.761125 -0.054351806640625 -0.202866210937506 -1.76125 -0.054351806640625 -0.202866210937506 -1.761375 -0.055267333984375 -0.202866210937506 -1.7615 -0.055267333984375 -0.202866210937506 -1.761625 -0.05615234375 -0.202866210937506 -1.76175 -0.057037353515625 -0.202866210937506 -1.761875 -0.057037353515625 -0.202866210937506 -1.762 -0.057891845703125 -0.202866210937506 -1.762125 -0.057891845703125 -0.202866210937506 -1.76225 -0.05877685546875 -0.202866210937506 -1.762375 -0.05963134765625 -0.202866210937506 -1.7625 -0.05963134765625 -0.202866210937506 -1.762625 -0.06048583984375 -0.202866210937506 -1.76275 -0.06048583984375 -0.202866210937506 -1.762875 -0.06134033203125 -0.202866210937506 -1.763 -0.06219482421875 -0.202866210937506 -1.763125 -0.06219482421875 -0.202866210937506 -1.76325 -0.063018798828125 -0.202866210937506 -1.763375 -0.063018798828125 -0.202866210937506 -1.7635 -0.0638427734375 -0.202866210937506 -1.763625 -0.064666748046875 -0.202866210937506 -1.76375 -0.064666748046875 -0.202866210937506 -1.763875 -0.06549072265625 -0.202866210937506 -1.764 -0.06549072265625 -0.202866210937506 -1.764125 -0.0662841796875 -0.202866210937506 -1.76425 -0.067108154296875 -0.202866210937506 -1.764375 -0.067108154296875 -0.202866210937506 -1.7645 -0.067901611328125 -0.202866210937506 -1.764625 -0.067901611328125 -0.202866210937506 -1.76475 -0.06866455078125 -0.202866210937506 -1.764875 -0.0694580078125 -0.202866210937506 -1.765 -0.0694580078125 -0.202866210937506 -1.765125 -0.070220947265625 -0.202866210937506 -1.76525 -0.070220947265625 -0.202866210937506 -1.765375 -0.07098388671875 -0.202866210937506 -1.7655 -0.071746826171875 -0.202866210937506 -1.765625 -0.071746826171875 -0.202866210937506 -1.76575 -0.072479248046875 -0.202866210937506 -1.765875 -0.072479248046875 -0.202866210937506 -1.766 -0.073211669921875 -0.202866210937506 -1.766125 -0.073974609375 -0.202866210937506 -1.76625 -0.073974609375 -0.202866210937506 -1.766375 -0.074676513671875 -0.202866210937506 -1.7665 -0.074676513671875 -0.202866210937506 -1.766625 -0.075408935546875 -0.202866210937506 -1.76675 -0.07611083984375 -0.202866210937506 -1.766875 -0.07611083984375 -0.202866210937506 -1.767 -0.076812744140625 -0.202866210937506 -1.767125 -0.076812744140625 -0.202866210937506 -1.76725 -0.077484130859375 -0.202866210937506 -1.767375 -0.07818603515625 -0.202866210937506 -1.7675 -0.07818603515625 -0.202866210937506 -1.767625 -0.078857421875 -0.202866210937506 -1.76775 -0.078857421875 -0.202866210937506 -1.767875 -0.079498291015625 -0.202866210937506 -1.768 -0.080169677734375 -0.202866210937506 -1.768125 -0.080169677734375 -0.202866210937506 -1.76825 -0.080810546875 -0.202866210937506 -1.768375 -0.080810546875 -0.202866210937506 -1.7685 -0.081451416015625 -0.202866210937506 -1.768625 -0.08209228515625 -0.202866210937506 -1.76875 -0.08209228515625 -0.202866210937506 -1.768875 -0.08270263671875 -0.202866210937506 -1.769 -0.08270263671875 -0.202866210937506 -1.769125 -0.08331298828125 -0.202866210937506 -1.76925 -0.08392333984375 -0.202866210937506 -1.769375 -0.08392333984375 -0.202866210937506 -1.7695 -0.084503173828125 -0.202866210937506 -1.769625 -0.084503173828125 -0.202866210937506 -1.76975 -0.0850830078125 -0.202866210937506 -1.769875 -0.085662841796875 -0.202866210937506 -1.77 -0.085662841796875 -0.202866210937506 -1.770125 -0.086212158203125 -0.202866210937506 -1.77025 -0.086212158203125 -0.202866210937506 -1.770375 -0.0867919921875 -0.202866210937506 -1.7705 -0.087310791015625 -0.202866210937506 -1.770625 -0.087310791015625 -0.202866210937506 -1.77075 -0.087860107421875 -0.202866210937506 -1.770875 -0.087860107421875 -0.202866210937506 -1.771 -0.08837890625 -0.202866210937506 -1.771125 -0.088897705078125 -0.202866210937506 -1.77125 -0.088897705078125 -0.202866210937506 -1.771375 -0.08941650390625 -0.202866210937506 -1.7715 -0.08941650390625 -0.202866210937506 -1.771625 -0.08990478515625 -0.202866210937506 -1.77175 -0.09039306640625 -0.202866210937506 -1.771875 -0.09039306640625 -0.202866210937506 -1.772 -0.09088134765625 -0.202866210937506 -1.772125 -0.09088134765625 -0.202866210937506 -1.77225 -0.091339111328125 -0.202866210937506 -1.772375 -0.091796875 -0.202866210937506 -1.7725 -0.091796875 -0.202866210937506 -1.772625 -0.092254638671875 -0.202866210937506 -1.77275 -0.092254638671875 -0.202866210937506 -1.772875 -0.092681884765625 -0.202866210937506 -1.773 -0.093109130859375 -0.202866210937506 -1.773125 -0.093109130859375 -0.202866210937506 -1.77325 -0.093536376953125 -0.202866210937506 -1.773375 -0.093536376953125 -0.202866210937506 -1.7735 -0.09393310546875 -0.202866210937506 -1.773625 -0.094329833984375 -0.202866210937506 -1.77375 -0.094329833984375 -0.202866210937506 -1.773875 -0.0947265625 -0.202866210937506 -1.774 -0.0947265625 -0.202866210937506 -1.774125 -0.0950927734375 -0.202866210937506 -1.77425 -0.095458984375 -0.202866210937506 -1.774375 -0.095458984375 -0.202866210937506 -1.7745 -0.095794677734375 -0.202866210937506 -1.774625 -0.095794677734375 -0.202866210937506 -1.77475 -0.096160888671875 -0.202866210937506 -1.774875 -0.09649658203125 -0.202866210937506 -1.775 -0.09649658203125 -0.202866210937506 -1.775125 -0.0968017578125 -0.202866210937506 -1.77525 -0.0968017578125 -0.202866210937506 -1.775375 -0.09710693359375 -0.202866210937506 -1.7755 -0.097412109375 -0.202866210937506 -1.775625 -0.097412109375 -0.202866210937506 -1.77575 -0.09771728515625 -0.202866210937506 -1.775875 -0.09771728515625 -0.202866210937506 -1.776 -0.097991943359375 -0.202866210937506 -1.776125 -0.0982666015625 -0.202866210937506 -1.77625 -0.0982666015625 -0.202866210937506 -1.776375 -0.0985107421875 -0.202866210937506 -1.7765 -0.0985107421875 -0.202866210937506 -1.776625 -0.098785400390625 -0.202866210937506 -1.77675 -0.0989990234375 -0.202866210937506 -1.776875 -0.0989990234375 -0.202866210937506 -1.777 -0.0992431640625 -0.202866210937506 -1.777125 -0.0992431640625 -0.202866210937506 -1.77725 -0.099456787109375 -0.202866210937506 -1.777375 -0.099639892578125 -0.202866210937506 -1.7775 -0.099639892578125 -0.202866210937506 -1.777625 -0.099853515625 -0.202866210937506 -1.77775 -0.099853515625 -0.202866210937506 -1.777875 -0.10003662109375 -0.202866210937506 -1.778 -0.100189208984375 -0.202866210937506 -1.778125 -0.100189208984375 -0.202866210937506 -1.77825 -0.100372314453125 -0.202866210937506 -1.778375 -0.100372314453125 -0.202866210937506 -1.7785 -0.10052490234375 -0.202866210937506 -1.778625 -0.10064697265625 -0.202866210937506 -1.77875 -0.10064697265625 -0.202866210937506 -1.778875 -0.10076904296875 -0.202866210937506 -1.779 -0.10076904296875 -0.202866210937506 -1.779125 -0.10089111328125 -0.202866210937506 -1.77925 -0.10101318359375 -0.202866210937506 -1.779375 -0.10101318359375 -0.202866210937506 -1.7795 -0.101104736328125 -0.202866210937506 -1.779625 -0.101104736328125 -0.202866210937506 -1.77975 -0.101165771484375 -0.202866210937506 -1.779875 -0.10125732421875 -0.202866210937506 -1.78 -0.10125732421875 -0.202866210937506 -1.780125 -0.101318359375 -0.202866210937506 -1.78025 -0.101318359375 -0.202866210937506 -1.780375 -0.101348876953125 -0.202866210937506 -1.7805 -0.101409912109375 -0.202866210937506 -1.780625 -0.101409912109375 -0.202866210937506 -1.78075 -0.1014404296875 -0.202866210937506 -1.780875 -0.1014404296875 -0.202866210937506 -1.781 -0.1014404296875 -0.202866210937506 -1.781125 -0.1014404296875 -0.202866210937506 -1.78125 -0.1014404296875 -0.202866210937506 -1.781375 -0.1014404296875 -0.202866210937506 -1.7815 -0.1014404296875 -0.202866210937506 -1.781625 -0.1014404296875 -0.202866210937506 -1.78175 -0.101409912109375 -0.202866210937506 -1.781875 -0.101409912109375 -0.202866210937506 -1.782 -0.101348876953125 -0.202866210937506 -1.782125 -0.101348876953125 -0.202866210937506 -1.78225 -0.101318359375 -0.202866210937506 -1.782375 -0.10125732421875 -0.202866210937506 -1.7825 -0.10125732421875 -0.202866210937506 -1.782625 -0.101165771484375 -0.202866210937506 -1.78275 -0.101165771484375 -0.202866210937506 -1.782875 -0.101104736328125 -0.202866210937506 -1.783 -0.10101318359375 -0.202866210937506 -1.783125 -0.10101318359375 -0.202866210937506 -1.78325 -0.10089111328125 -0.202866210937506 -1.783375 -0.10089111328125 -0.202866210937506 -1.7835 -0.10076904296875 -0.202866210937506 -1.783625 -0.10064697265625 -0.202866210937506 -1.78375 -0.10064697265625 -0.202866210937506 -1.783875 -0.10052490234375 -0.202866210937506 -1.784 -0.10052490234375 -0.202866210937506 -1.784125 -0.100372314453125 -0.202866210937506 -1.78425 -0.100189208984375 -0.202866210937506 -1.784375 -0.100189208984375 -0.202866210937506 -1.7845 -0.10003662109375 -0.202866210937506 -1.784625 -0.10003662109375 -0.202866210937506 -1.78475 -0.099853515625 -0.202866210937506 -1.784875 -0.099639892578125 -0.202866210937506 -1.785 -0.099639892578125 -0.202866210937506 -1.785125 -0.099456787109375 -0.202866210937506 -1.78525 -0.099456787109375 -0.202866210937506 -1.785375 -0.0992431640625 -0.202866210937506 -1.7855 -0.0989990234375 -0.202866210937506 -1.785625 -0.0989990234375 -0.202866210937506 -1.78575 -0.098785400390625 -0.202866210937506 -1.785875 -0.098785400390625 -0.202866210937506 -1.786 -0.0985107421875 -0.202866210937506 -1.786125 -0.0982666015625 -0.202866210937506 -1.78625 -0.0982666015625 -0.202866210937506 -1.786375 -0.097991943359375 -0.202866210937506 -1.7865 -0.097991943359375 -0.202866210937506 -1.786625 -0.09771728515625 -0.202866210937506 -1.78675 -0.097412109375 -0.202866210937506 -1.786875 -0.097412109375 -0.202866210937506 -1.787 -0.09710693359375 -0.202866210937506 -1.787125 -0.09710693359375 -0.202866210937506 -1.78725 -0.0968017578125 -0.202866210937506 -1.787375 -0.09649658203125 -0.202866210937506 -1.7875 -0.09649658203125 -0.202866210937506 -1.787625 -0.096160888671875 -0.202866210937506 -1.78775 -0.096160888671875 -0.202866210937506 -1.787875 -0.095794677734375 -0.202866210937506 -1.788 -0.095458984375 -0.202866210937506 -1.788125 -0.095458984375 -0.202866210937506 -1.78825 -0.0950927734375 -0.202866210937506 -1.788375 -0.0950927734375 -0.202866210937506 -1.7885 -0.0947265625 -0.202866210937506 -1.788625 -0.094329833984375 -0.202866210937506 -1.78875 -0.094329833984375 -0.202866210937506 -1.788875 -0.09393310546875 -0.202866210937506 -1.789 -0.09393310546875 -0.202866210937506 -1.789125 -0.093536376953125 -0.202866210937506 -1.78925 -0.093109130859375 -0.202866210937506 -1.789375 -0.093109130859375 -0.202866210937506 -1.7895 -0.092681884765625 -0.202866210937506 -1.789625 -0.092681884765625 -0.202866210937506 -1.78975 -0.092254638671875 -0.202866210937506 -1.789875 -0.091796875 -0.202866210937506 -1.79 -0.091796875 -0.202866210937506 -1.790125 -0.091339111328125 -0.202866210937506 -1.79025 -0.091339111328125 -0.202866210937506 -1.790375 -0.09088134765625 -0.202866210937506 -1.7905 -0.09039306640625 -0.202866210937506 -1.790625 -0.09039306640625 -0.202866210937506 -1.79075 -0.08990478515625 -0.202866210937506 -1.790875 -0.08990478515625 -0.202866210937506 -1.791 -0.08941650390625 -0.202866210937506 -1.791125 -0.088897705078125 -0.202866210937506 -1.79125 -0.088897705078125 -0.202866210937506 -1.791375 -0.08837890625 -0.202866210937506 -1.7915 -0.08837890625 -0.202866210937506 -1.791625 -0.087860107421875 -0.202866210937506 -1.79175 -0.087310791015625 -0.202866210937506 -1.791875 -0.087310791015625 -0.202866210937506 -1.792 -0.188690185546875 -0.4412060546875043 -1.792125 -0.188690185546875 -0.4412060546875043 -1.79225 -0.1875 -0.4412060546875043 -1.792375 -0.186279296875 -0.4412060546875043 -1.7925 -0.186279296875 -0.4412060546875043 -1.792625 -0.18499755859375 -0.4412060546875043 -1.79275 -0.18499755859375 -0.4412060546875043 -1.792875 -0.183746337890625 -0.4412060546875043 -1.793 -0.182464599609375 -0.4412060546875043 -1.793125 -0.182464599609375 -0.4412060546875043 -1.79325 -0.18115234375 -0.4412060546875043 -1.793375 -0.18115234375 -0.4412060546875043 -1.7935 -0.1798095703125 -0.4412060546875043 -1.793625 -0.178466796875 -0.4412060546875043 -1.79375 -0.178466796875 -0.4412060546875043 -1.793875 -0.177093505859375 -0.4412060546875043 -1.794 -0.177093505859375 -0.4412060546875043 -1.794125 -0.17572021484375 -0.4412060546875043 -1.79425 -0.17431640625 -0.4412060546875043 -1.794375 -0.17431640625 -0.4412060546875043 -1.7945 -0.172882080078125 -0.4412060546875043 -1.794625 -0.172882080078125 -0.4412060546875043 -1.79475 -0.17144775390625 -0.4412060546875043 -1.794875 -0.16998291015625 -0.4412060546875043 -1.795 -0.16998291015625 -0.4412060546875043 -1.795125 -0.168487548828125 -0.4412060546875043 -1.79525 -0.168487548828125 -0.4412060546875043 -1.795375 -0.1669921875 -0.4412060546875043 -1.7955 -0.16546630859375 -0.4412060546875043 -1.795625 -0.16546630859375 -0.4412060546875043 -1.79575 -0.1639404296875 -0.4412060546875043 -1.795875 -0.1639404296875 -0.4412060546875043 -1.796 -0.162384033203125 -0.4412060546875043 -1.796125 -0.16082763671875 -0.4412060546875043 -1.79625 -0.16082763671875 -0.4412060546875043 -1.796375 -0.159210205078125 -0.4412060546875043 -1.7965 -0.159210205078125 -0.4412060546875043 -1.796625 -0.157623291015625 -0.4412060546875043 -1.79675 -0.155975341796875 -0.4412060546875043 -1.796875 -0.155975341796875 -0.4412060546875043 -1.797 -0.15435791015625 -0.4412060546875043 -1.797125 -0.15435791015625 -0.4412060546875043 -1.79725 -0.152679443359375 -0.4412060546875043 -1.797375 -0.1510009765625 -0.4412060546875043 -1.7975 -0.1510009765625 -0.4412060546875043 -1.797625 -0.149322509765625 -0.4412060546875043 -1.79775 -0.149322509765625 -0.4412060546875043 -1.797875 -0.147613525390625 -0.4412060546875043 -1.798 -0.145904541015625 -0.4412060546875043 -1.798125 -0.145904541015625 -0.4412060546875043 -1.79825 -0.144134521484375 -0.4412060546875043 -1.798375 -0.144134521484375 -0.4412060546875043 -1.7985 -0.14239501953125 -0.4412060546875043 -1.798625 -0.140625 -0.4412060546875043 -1.79875 -0.140625 -0.4412060546875043 -1.798875 -0.138824462890625 -0.4412060546875043 -1.799 -0.138824462890625 -0.4412060546875043 -1.799125 -0.13702392578125 -0.4412060546875043 -1.79925 -0.135223388671875 -0.4412060546875043 -1.799375 -0.135223388671875 -0.4412060546875043 -1.7995 -0.133392333984375 -0.4412060546875043 -1.799625 -0.133392333984375 -0.4412060546875043 -1.79975 -0.13153076171875 -0.4412060546875043 -1.799875 -0.129669189453125 -0.4412060546875043 -1.8 -0.129669189453125 -0.4412060546875043 -1.800125 -0.1278076171875 -0.4412060546875043 -1.80025 -0.1278076171875 -0.4412060546875043 -1.800375 -0.12591552734375 -0.4412060546875043 -1.8005 -0.123992919921875 -0.4412060546875043 -1.800625 -0.123992919921875 -0.4412060546875043 -1.80075 -0.1220703125 -0.4412060546875043 -1.800875 -0.1220703125 -0.4412060546875043 -1.801 -0.120147705078125 -0.4412060546875043 -1.801125 -0.11822509765625 -0.4412060546875043 -1.80125 -0.11822509765625 -0.4412060546875043 -1.801375 -0.116241455078125 -0.4412060546875043 -1.8015 -0.116241455078125 -0.4412060546875043 -1.801625 -0.114288330078125 -0.4412060546875043 -1.80175 -0.1123046875 -0.4412060546875043 -1.801875 -0.1123046875 -0.4412060546875043 -1.802 -0.110321044921875 -0.4412060546875043 -1.802125 -0.110321044921875 -0.4412060546875043 -1.80225 -0.108306884765625 -0.4412060546875043 -1.802375 -0.106292724609375 -0.4412060546875043 -1.8025 -0.106292724609375 -0.4412060546875043 -1.802625 -0.104248046875 -0.4412060546875043 -1.80275 -0.104248046875 -0.4412060546875043 -1.802875 -0.102203369140625 -0.4412060546875043 -1.803 -0.10015869140625 -0.4412060546875043 -1.803125 -0.10015869140625 -0.4412060546875043 -1.80325 -0.09808349609375 -0.4412060546875043 -1.803375 -0.09808349609375 -0.4412060546875043 -1.8035 -0.09600830078125 -0.4412060546875043 -1.803625 -0.09393310546875 -0.4412060546875043 -1.80375 -0.09393310546875 -0.4412060546875043 -1.803875 -0.091827392578125 -0.4412060546875043 -1.804 -0.091827392578125 -0.4412060546875043 -1.804125 -0.0897216796875 -0.4412060546875043 -1.80425 -0.087615966796875 -0.4412060546875043 -1.804375 -0.087615966796875 -0.4412060546875043 -1.8045 -0.085479736328125 -0.4412060546875043 -1.804625 -0.085479736328125 -0.4412060546875043 -1.80475 -0.083343505859375 -0.4412060546875043 -1.804875 -0.081207275390625 -0.4412060546875043 -1.805 -0.081207275390625 -0.4412060546875043 -1.805125 -0.079071044921875 -0.4412060546875043 -1.80525 -0.079071044921875 -0.4412060546875043 -1.805375 -0.076904296875 -0.4412060546875043 -1.8055 -0.074737548828125 -0.4412060546875043 -1.805625 -0.074737548828125 -0.4412060546875043 -1.80575 -0.072540283203125 -0.4412060546875043 -1.805875 -0.072540283203125 -0.4412060546875043 -1.806 -0.07037353515625 -0.4412060546875043 -1.806125 -0.06817626953125 -0.4412060546875043 -1.80625 -0.06817626953125 -0.4412060546875043 -1.806375 -0.06597900390625 -0.4412060546875043 -1.8065 -0.06597900390625 -0.4412060546875043 -1.806625 -0.06378173828125 -0.4412060546875043 -1.80675 -0.061553955078125 -0.4412060546875043 -1.806875 -0.061553955078125 -0.4412060546875043 -1.807 -0.059326171875 -0.4412060546875043 -1.807125 -0.059326171875 -0.4412060546875043 -1.80725 -0.057098388671875 -0.4412060546875043 -1.807375 -0.05487060546875 -0.4412060546875043 -1.8075 -0.05487060546875 -0.4412060546875043 -1.807625 -0.052642822265625 -0.4412060546875043 -1.80775 -0.052642822265625 -0.4412060546875043 -1.807875 -0.050384521484375 -0.4412060546875043 -1.808 -0.048126220703125 -0.4412060546875043 -1.808125 -0.048126220703125 -0.4412060546875043 -1.80825 -0.045867919921875 -0.4412060546875043 -1.808375 -0.045867919921875 -0.4412060546875043 -1.8085 -0.043609619140625 -0.4412060546875043 -1.808625 -0.041351318359375 -0.4412060546875043 -1.80875 -0.041351318359375 -0.4412060546875043 -1.808875 -0.0390625 -0.4412060546875043 -1.809 -0.0390625 -0.4412060546875043 -1.809125 -0.03680419921875 -0.4412060546875043 -1.80925 -0.034515380859375 -0.4412060546875043 -1.809375 -0.034515380859375 -0.4412060546875043 -1.8095 -0.0322265625 -0.4412060546875043 -1.809625 -0.0322265625 -0.4412060546875043 -1.80975 -0.029937744140625 -0.4412060546875043 -1.809875 -0.02764892578125 -0.4412060546875043 -1.81 -0.02764892578125 -0.4412060546875043 -1.810125 -0.025360107421875 -0.4412060546875043 -1.81025 -0.025360107421875 -0.4412060546875043 -1.810375 -0.0230712890625 -0.4412060546875043 -1.8105 -0.020782470703125 -0.4412060546875043 -1.810625 -0.020782470703125 -0.4412060546875043 -1.81075 -0.018463134765625 -0.4412060546875043 -1.810875 -0.018463134765625 -0.4412060546875043 -1.811 -0.01617431640625 -0.4412060546875043 -1.811125 -0.01385498046875 -0.4412060546875043 -1.81125 -0.01385498046875 -0.4412060546875043 -1.811375 -0.011566162109375 -0.4412060546875043 -1.8115 -0.011566162109375 -0.4412060546875043 -1.811625 -0.009246826171875 -0.4412060546875043 -1.81175 -0.006927490234375 -0.4412060546875043 -1.811875 -0.006927490234375 -0.4412060546875043 -1.812 -0.004638671875 -0.4412060546875043 -1.812125 -0.004638671875 -0.4412060546875043 -1.81225 -0.0023193359375 -0.4412060546875043 +1.76 -0.048858642578125 -0.202866210937506 +1.760125 -0.049774169921875 -0.202866210937506 +1.76025 -0.049774169921875 -0.202866210937506 +1.760375 -0.050689697265625 -0.202866210937506 +1.7605 -0.051605224609375 -0.202866210937506 +1.760625 -0.051605224609375 -0.202866210937506 +1.76075 -0.052520751953125 -0.202866210937506 +1.760875 -0.052520751953125 -0.202866210937506 +1.761 -0.053436279296875 -0.202866210937506 +1.761125 -0.0543212890625 -0.202866210937506 +1.76125 -0.0543212890625 -0.202866210937506 +1.761375 -0.05523681640625 -0.202866210937506 +1.7615 -0.05523681640625 -0.202866210937506 +1.761625 -0.056121826171875 -0.202866210937506 +1.76175 -0.0570068359375 -0.202866210937506 +1.761875 -0.0570068359375 -0.202866210937506 +1.762 -0.057861328125 -0.202866210937506 +1.762125 -0.057861328125 -0.202866210937506 +1.76225 -0.058746337890625 -0.202866210937506 +1.762375 -0.059600830078125 -0.202866210937506 +1.7625 -0.059600830078125 -0.202866210937506 +1.762625 -0.060455322265625 -0.202866210937506 +1.76275 -0.060455322265625 -0.202866210937506 +1.762875 -0.061309814453125 -0.202866210937506 +1.763 -0.062164306640625 -0.202866210937506 +1.763125 -0.062164306640625 -0.202866210937506 +1.76325 -0.06298828125 -0.202866210937506 +1.763375 -0.06298828125 -0.202866210937506 +1.7635 -0.063812255859375 -0.202866210937506 +1.763625 -0.06463623046875 -0.202866210937506 +1.76375 -0.06463623046875 -0.202866210937506 +1.763875 -0.065460205078125 -0.202866210937506 +1.764 -0.065460205078125 -0.202866210937506 +1.764125 -0.066253662109375 -0.202866210937506 +1.76425 -0.06707763671875 -0.202866210937506 +1.764375 -0.06707763671875 -0.202866210937506 +1.7645 -0.06787109375 -0.202866210937506 +1.764625 -0.06787109375 -0.202866210937506 +1.76475 -0.068634033203125 -0.202866210937506 +1.764875 -0.069427490234375 -0.202866210937506 +1.765 -0.069427490234375 -0.202866210937506 +1.765125 -0.0701904296875 -0.202866210937506 +1.76525 -0.0701904296875 -0.202866210937506 +1.765375 -0.070953369140625 -0.202866210937506 +1.7655 -0.07171630859375 -0.202866210937506 +1.765625 -0.07171630859375 -0.202866210937506 +1.76575 -0.07244873046875 -0.202866210937506 +1.765875 -0.07244873046875 -0.202866210937506 +1.766 -0.07318115234375 -0.202866210937506 +1.766125 -0.073944091796875 -0.202866210937506 +1.76625 -0.073944091796875 -0.202866210937506 +1.766375 -0.07464599609375 -0.202866210937506 +1.7665 -0.07464599609375 -0.202866210937506 +1.766625 -0.07537841796875 -0.202866210937506 +1.76675 -0.076080322265625 -0.202866210937506 +1.766875 -0.076080322265625 -0.202866210937506 +1.767 -0.0767822265625 -0.202866210937506 +1.767125 -0.0767822265625 -0.202866210937506 +1.76725 -0.07745361328125 -0.202866210937506 +1.767375 -0.078155517578125 -0.202866210937506 +1.7675 -0.078155517578125 -0.202866210937506 +1.767625 -0.078826904296875 -0.202866210937506 +1.76775 -0.078826904296875 -0.202866210937506 +1.767875 -0.0794677734375 -0.202866210937506 +1.768 -0.08013916015625 -0.202866210937506 +1.768125 -0.08013916015625 -0.202866210937506 +1.76825 -0.080780029296875 -0.202866210937506 +1.768375 -0.080780029296875 -0.202866210937506 +1.7685 -0.0814208984375 -0.202866210937506 +1.768625 -0.082061767578125 -0.202866210937506 +1.76875 -0.082061767578125 -0.202866210937506 +1.768875 -0.082672119140625 -0.202866210937506 +1.769 -0.082672119140625 -0.202866210937506 +1.769125 -0.083282470703125 -0.202866210937506 +1.76925 -0.083892822265625 -0.202866210937506 +1.769375 -0.083892822265625 -0.202866210937506 +1.7695 -0.08447265625 -0.202866210937506 +1.769625 -0.08447265625 -0.202866210937506 +1.76975 -0.085052490234375 -0.202866210937506 +1.769875 -0.08563232421875 -0.202866210937506 +1.77 -0.08563232421875 -0.202866210937506 +1.770125 -0.086181640625 -0.202866210937506 +1.77025 -0.086181640625 -0.202866210937506 +1.770375 -0.086761474609375 -0.202866210937506 +1.7705 -0.0872802734375 -0.202866210937506 +1.770625 -0.0872802734375 -0.202866210937506 +1.77075 -0.08782958984375 -0.202866210937506 +1.770875 -0.08782958984375 -0.202866210937506 +1.771 -0.088348388671875 -0.202866210937506 +1.771125 -0.0888671875 -0.202866210937506 +1.77125 -0.0888671875 -0.202866210937506 +1.771375 -0.089385986328125 -0.202866210937506 +1.7715 -0.089385986328125 -0.202866210937506 +1.771625 -0.089874267578125 -0.202866210937506 +1.77175 -0.090362548828125 -0.202866210937506 +1.771875 -0.090362548828125 -0.202866210937506 +1.772 -0.090850830078125 -0.202866210937506 +1.772125 -0.090850830078125 -0.202866210937506 +1.77225 -0.09130859375 -0.202866210937506 +1.772375 -0.091766357421875 -0.202866210937506 +1.7725 -0.091766357421875 -0.202866210937506 +1.772625 -0.09222412109375 -0.202866210937506 +1.77275 -0.09222412109375 -0.202866210937506 +1.772875 -0.0926513671875 -0.202866210937506 +1.773 -0.09307861328125 -0.202866210937506 +1.773125 -0.09307861328125 -0.202866210937506 +1.77325 -0.093505859375 -0.202866210937506 +1.773375 -0.093505859375 -0.202866210937506 +1.7735 -0.093902587890625 -0.202866210937506 +1.773625 -0.09429931640625 -0.202866210937506 +1.77375 -0.09429931640625 -0.202866210937506 +1.773875 -0.094696044921875 -0.202866210937506 +1.774 -0.094696044921875 -0.202866210937506 +1.774125 -0.095062255859375 -0.202866210937506 +1.77425 -0.095428466796875 -0.202866210937506 +1.774375 -0.095428466796875 -0.202866210937506 +1.7745 -0.09576416015625 -0.202866210937506 +1.774625 -0.09576416015625 -0.202866210937506 +1.77475 -0.09613037109375 -0.202866210937506 +1.774875 -0.096466064453125 -0.202866210937506 +1.775 -0.096466064453125 -0.202866210937506 +1.775125 -0.096771240234375 -0.202866210937506 +1.77525 -0.096771240234375 -0.202866210937506 +1.775375 -0.097076416015625 -0.202866210937506 +1.7755 -0.097381591796875 -0.202866210937506 +1.775625 -0.097381591796875 -0.202866210937506 +1.77575 -0.097686767578125 -0.202866210937506 +1.775875 -0.097686767578125 -0.202866210937506 +1.776 -0.09796142578125 -0.202866210937506 +1.776125 -0.098236083984375 -0.202866210937506 +1.77625 -0.098236083984375 -0.202866210937506 +1.776375 -0.098480224609375 -0.202866210937506 +1.7765 -0.098480224609375 -0.202866210937506 +1.776625 -0.0987548828125 -0.202866210937506 +1.77675 -0.098968505859375 -0.202866210937506 +1.776875 -0.098968505859375 -0.202866210937506 +1.777 -0.099212646484375 -0.202866210937506 +1.777125 -0.099212646484375 -0.202866210937506 +1.77725 -0.09942626953125 -0.202866210937506 +1.777375 -0.099609375 -0.202866210937506 +1.7775 -0.099609375 -0.202866210937506 +1.777625 -0.099822998046875 -0.202866210937506 +1.77775 -0.099822998046875 -0.202866210937506 +1.777875 -0.100006103515625 -0.202866210937506 +1.778 -0.10015869140625 -0.202866210937506 +1.778125 -0.10015869140625 -0.202866210937506 +1.77825 -0.100341796875 -0.202866210937506 +1.778375 -0.100341796875 -0.202866210937506 +1.7785 -0.100494384765625 -0.202866210937506 +1.778625 -0.100616455078125 -0.202866210937506 +1.77875 -0.100616455078125 -0.202866210937506 +1.778875 -0.100738525390625 -0.202866210937506 +1.779 -0.100738525390625 -0.202866210937506 +1.779125 -0.100860595703125 -0.202866210937506 +1.77925 -0.100982666015625 -0.202866210937506 +1.779375 -0.100982666015625 -0.202866210937506 +1.7795 -0.10107421875 -0.202866210937506 +1.779625 -0.10107421875 -0.202866210937506 +1.77975 -0.10113525390625 -0.202866210937506 +1.779875 -0.101226806640625 -0.202866210937506 +1.78 -0.101226806640625 -0.202866210937506 +1.780125 -0.101287841796875 -0.202866210937506 +1.78025 -0.101287841796875 -0.202866210937506 +1.780375 -0.101318359375 -0.202866210937506 +1.7805 -0.10137939453125 -0.202866210937506 +1.780625 -0.10137939453125 -0.202866210937506 +1.78075 -0.101409912109375 -0.202866210937506 +1.780875 -0.101409912109375 -0.202866210937506 +1.781 -0.101409912109375 -0.202866210937506 +1.781125 -0.101409912109375 -0.202866210937506 +1.78125 -0.101409912109375 -0.202866210937506 +1.781375 -0.101409912109375 -0.202866210937506 +1.7815 -0.101409912109375 -0.202866210937506 +1.781625 -0.101409912109375 -0.202866210937506 +1.78175 -0.10137939453125 -0.202866210937506 +1.781875 -0.10137939453125 -0.202866210937506 +1.782 -0.101318359375 -0.202866210937506 +1.782125 -0.101318359375 -0.202866210937506 +1.78225 -0.101287841796875 -0.202866210937506 +1.782375 -0.101226806640625 -0.202866210937506 +1.7825 -0.101226806640625 -0.202866210937506 +1.782625 -0.10113525390625 -0.202866210937506 +1.78275 -0.10113525390625 -0.202866210937506 +1.782875 -0.10107421875 -0.202866210937506 +1.783 -0.100982666015625 -0.202866210937506 +1.783125 -0.100982666015625 -0.202866210937506 +1.78325 -0.100860595703125 -0.202866210937506 +1.783375 -0.100860595703125 -0.202866210937506 +1.7835 -0.100738525390625 -0.202866210937506 +1.783625 -0.100616455078125 -0.202866210937506 +1.78375 -0.100616455078125 -0.202866210937506 +1.783875 -0.100494384765625 -0.202866210937506 +1.784 -0.100494384765625 -0.202866210937506 +1.784125 -0.100341796875 -0.202866210937506 +1.78425 -0.10015869140625 -0.202866210937506 +1.784375 -0.10015869140625 -0.202866210937506 +1.7845 -0.100006103515625 -0.202866210937506 +1.784625 -0.100006103515625 -0.202866210937506 +1.78475 -0.099822998046875 -0.202866210937506 +1.784875 -0.099609375 -0.202866210937506 +1.785 -0.099609375 -0.202866210937506 +1.785125 -0.09942626953125 -0.202866210937506 +1.78525 -0.09942626953125 -0.202866210937506 +1.785375 -0.099212646484375 -0.202866210937506 +1.7855 -0.098968505859375 -0.202866210937506 +1.785625 -0.098968505859375 -0.202866210937506 +1.78575 -0.0987548828125 -0.202866210937506 +1.785875 -0.0987548828125 -0.202866210937506 +1.786 -0.098480224609375 -0.202866210937506 +1.786125 -0.098236083984375 -0.202866210937506 +1.78625 -0.098236083984375 -0.202866210937506 +1.786375 -0.09796142578125 -0.202866210937506 +1.7865 -0.09796142578125 -0.202866210937506 +1.786625 -0.097686767578125 -0.202866210937506 +1.78675 -0.097381591796875 -0.202866210937506 +1.786875 -0.097381591796875 -0.202866210937506 +1.787 -0.097076416015625 -0.202866210937506 +1.787125 -0.097076416015625 -0.202866210937506 +1.78725 -0.096771240234375 -0.202866210937506 +1.787375 -0.096466064453125 -0.202866210937506 +1.7875 -0.096466064453125 -0.202866210937506 +1.787625 -0.09613037109375 -0.202866210937506 +1.78775 -0.09613037109375 -0.202866210937506 +1.787875 -0.09576416015625 -0.202866210937506 +1.788 -0.095428466796875 -0.202866210937506 +1.788125 -0.095428466796875 -0.202866210937506 +1.78825 -0.095062255859375 -0.202866210937506 +1.788375 -0.095062255859375 -0.202866210937506 +1.7885 -0.094696044921875 -0.202866210937506 +1.788625 -0.09429931640625 -0.202866210937506 +1.78875 -0.09429931640625 -0.202866210937506 +1.788875 -0.093902587890625 -0.202866210937506 +1.789 -0.093902587890625 -0.202866210937506 +1.789125 -0.093505859375 -0.202866210937506 +1.78925 -0.09307861328125 -0.202866210937506 +1.789375 -0.09307861328125 -0.202866210937506 +1.7895 -0.0926513671875 -0.202866210937506 +1.789625 -0.0926513671875 -0.202866210937506 +1.78975 -0.09222412109375 -0.202866210937506 +1.789875 -0.091766357421875 -0.202866210937506 +1.79 -0.091766357421875 -0.202866210937506 +1.790125 -0.09130859375 -0.202866210937506 +1.79025 -0.09130859375 -0.202866210937506 +1.790375 -0.090850830078125 -0.202866210937506 +1.7905 -0.090362548828125 -0.202866210937506 +1.790625 -0.090362548828125 -0.202866210937506 +1.79075 -0.089874267578125 -0.202866210937506 +1.790875 -0.089874267578125 -0.202866210937506 +1.791 -0.089385986328125 -0.202866210937506 +1.791125 -0.0888671875 -0.202866210937506 +1.79125 -0.0888671875 -0.202866210937506 +1.791375 -0.088348388671875 -0.202866210937506 +1.7915 -0.088348388671875 -0.202866210937506 +1.791625 -0.08782958984375 -0.202866210937506 +1.79175 -0.0872802734375 -0.202866210937506 +1.791875 -0.0872802734375 -0.202866210937506 +1.792 -0.18865966796875 -0.4412060546875043 +1.792125 -0.18865966796875 -0.4412060546875043 +1.79225 -0.187469482421875 -0.4412060546875043 +1.792375 -0.186248779296875 -0.4412060546875043 +1.7925 -0.186248779296875 -0.4412060546875043 +1.792625 -0.184967041015625 -0.4412060546875043 +1.79275 -0.184967041015625 -0.4412060546875043 +1.792875 -0.1837158203125 -0.4412060546875043 +1.793 -0.18243408203125 -0.4412060546875043 +1.793125 -0.18243408203125 -0.4412060546875043 +1.79325 -0.181121826171875 -0.4412060546875043 +1.793375 -0.181121826171875 -0.4412060546875043 +1.7935 -0.179779052734375 -0.4412060546875043 +1.793625 -0.178436279296875 -0.4412060546875043 +1.79375 -0.178436279296875 -0.4412060546875043 +1.793875 -0.17706298828125 -0.4412060546875043 +1.794 -0.17706298828125 -0.4412060546875043 +1.794125 -0.175689697265625 -0.4412060546875043 +1.79425 -0.174285888671875 -0.4412060546875043 +1.794375 -0.174285888671875 -0.4412060546875043 +1.7945 -0.1728515625 -0.4412060546875043 +1.794625 -0.1728515625 -0.4412060546875043 +1.79475 -0.171417236328125 -0.4412060546875043 +1.794875 -0.169952392578125 -0.4412060546875043 +1.795 -0.169952392578125 -0.4412060546875043 +1.795125 -0.16845703125 -0.4412060546875043 +1.79525 -0.16845703125 -0.4412060546875043 +1.795375 -0.166961669921875 -0.4412060546875043 +1.7955 -0.165435791015625 -0.4412060546875043 +1.795625 -0.165435791015625 -0.4412060546875043 +1.79575 -0.163909912109375 -0.4412060546875043 +1.795875 -0.163909912109375 -0.4412060546875043 +1.796 -0.162353515625 -0.4412060546875043 +1.796125 -0.160797119140625 -0.4412060546875043 +1.79625 -0.160797119140625 -0.4412060546875043 +1.796375 -0.1591796875 -0.4412060546875043 +1.7965 -0.1591796875 -0.4412060546875043 +1.796625 -0.1575927734375 -0.4412060546875043 +1.79675 -0.15594482421875 -0.4412060546875043 +1.796875 -0.15594482421875 -0.4412060546875043 +1.797 -0.154327392578125 -0.4412060546875043 +1.797125 -0.154327392578125 -0.4412060546875043 +1.79725 -0.15264892578125 -0.4412060546875043 +1.797375 -0.150970458984375 -0.4412060546875043 +1.7975 -0.150970458984375 -0.4412060546875043 +1.797625 -0.1492919921875 -0.4412060546875043 +1.79775 -0.1492919921875 -0.4412060546875043 +1.797875 -0.1475830078125 -0.4412060546875043 +1.798 -0.1458740234375 -0.4412060546875043 +1.798125 -0.1458740234375 -0.4412060546875043 +1.79825 -0.14410400390625 -0.4412060546875043 +1.798375 -0.14410400390625 -0.4412060546875043 +1.7985 -0.142364501953125 -0.4412060546875043 +1.798625 -0.140594482421875 -0.4412060546875043 +1.79875 -0.140594482421875 -0.4412060546875043 +1.798875 -0.1387939453125 -0.4412060546875043 +1.799 -0.1387939453125 -0.4412060546875043 +1.799125 -0.136993408203125 -0.4412060546875043 +1.79925 -0.13519287109375 -0.4412060546875043 +1.799375 -0.13519287109375 -0.4412060546875043 +1.7995 -0.13336181640625 -0.4412060546875043 +1.799625 -0.13336181640625 -0.4412060546875043 +1.79975 -0.131500244140625 -0.4412060546875043 +1.799875 -0.129638671875 -0.4412060546875043 +1.8 -0.129638671875 -0.4412060546875043 +1.800125 -0.127777099609375 -0.4412060546875043 +1.80025 -0.127777099609375 -0.4412060546875043 +1.800375 -0.125885009765625 -0.4412060546875043 +1.8005 -0.12396240234375 -0.4412060546875043 +1.800625 -0.12396240234375 -0.4412060546875043 +1.80075 -0.122039794921875 -0.4412060546875043 +1.800875 -0.122039794921875 -0.4412060546875043 +1.801 -0.1201171875 -0.4412060546875043 +1.801125 -0.118194580078125 -0.4412060546875043 +1.80125 -0.118194580078125 -0.4412060546875043 +1.801375 -0.1162109375 -0.4412060546875043 +1.8015 -0.1162109375 -0.4412060546875043 +1.801625 -0.1142578125 -0.4412060546875043 +1.80175 -0.112274169921875 -0.4412060546875043 +1.801875 -0.112274169921875 -0.4412060546875043 +1.802 -0.11029052734375 -0.4412060546875043 +1.802125 -0.11029052734375 -0.4412060546875043 +1.80225 -0.1082763671875 -0.4412060546875043 +1.802375 -0.10626220703125 -0.4412060546875043 +1.8025 -0.10626220703125 -0.4412060546875043 +1.802625 -0.104217529296875 -0.4412060546875043 +1.80275 -0.104217529296875 -0.4412060546875043 +1.802875 -0.1021728515625 -0.4412060546875043 +1.803 -0.100128173828125 -0.4412060546875043 +1.803125 -0.100128173828125 -0.4412060546875043 +1.80325 -0.098052978515625 -0.4412060546875043 +1.803375 -0.098052978515625 -0.4412060546875043 +1.8035 -0.095977783203125 -0.4412060546875043 +1.803625 -0.093902587890625 -0.4412060546875043 +1.80375 -0.093902587890625 -0.4412060546875043 +1.803875 -0.091796875 -0.4412060546875043 +1.804 -0.091796875 -0.4412060546875043 +1.804125 -0.089691162109375 -0.4412060546875043 +1.80425 -0.08758544921875 -0.4412060546875043 +1.804375 -0.08758544921875 -0.4412060546875043 +1.8045 -0.08544921875 -0.4412060546875043 +1.804625 -0.08544921875 -0.4412060546875043 +1.80475 -0.08331298828125 -0.4412060546875043 +1.804875 -0.0811767578125 -0.4412060546875043 +1.805 -0.0811767578125 -0.4412060546875043 +1.805125 -0.07904052734375 -0.4412060546875043 +1.80525 -0.07904052734375 -0.4412060546875043 +1.805375 -0.076873779296875 -0.4412060546875043 +1.8055 -0.07470703125 -0.4412060546875043 +1.805625 -0.07470703125 -0.4412060546875043 +1.80575 -0.072509765625 -0.4412060546875043 +1.805875 -0.072509765625 -0.4412060546875043 +1.806 -0.070343017578125 -0.4412060546875043 +1.806125 -0.068145751953125 -0.4412060546875043 +1.80625 -0.068145751953125 -0.4412060546875043 +1.806375 -0.065948486328125 -0.4412060546875043 +1.8065 -0.065948486328125 -0.4412060546875043 +1.806625 -0.063751220703125 -0.4412060546875043 +1.80675 -0.0615234375 -0.4412060546875043 +1.806875 -0.0615234375 -0.4412060546875043 +1.807 -0.059295654296875 -0.4412060546875043 +1.807125 -0.059295654296875 -0.4412060546875043 +1.80725 -0.05706787109375 -0.4412060546875043 +1.807375 -0.054840087890625 -0.4412060546875043 +1.8075 -0.054840087890625 -0.4412060546875043 +1.807625 -0.0526123046875 -0.4412060546875043 +1.80775 -0.0526123046875 -0.4412060546875043 +1.807875 -0.05035400390625 -0.4412060546875043 +1.808 -0.048095703125 -0.4412060546875043 +1.808125 -0.048095703125 -0.4412060546875043 +1.80825 -0.04583740234375 -0.4412060546875043 +1.808375 -0.04583740234375 -0.4412060546875043 +1.8085 -0.0435791015625 -0.4412060546875043 +1.808625 -0.04132080078125 -0.4412060546875043 +1.80875 -0.04132080078125 -0.4412060546875043 +1.808875 -0.039031982421875 -0.4412060546875043 +1.809 -0.039031982421875 -0.4412060546875043 +1.809125 -0.036773681640625 -0.4412060546875043 +1.80925 -0.03448486328125 -0.4412060546875043 +1.809375 -0.03448486328125 -0.4412060546875043 +1.8095 -0.032196044921875 -0.4412060546875043 +1.809625 -0.032196044921875 -0.4412060546875043 +1.80975 -0.0299072265625 -0.4412060546875043 +1.809875 -0.027618408203125 -0.4412060546875043 +1.81 -0.027618408203125 -0.4412060546875043 +1.810125 -0.02532958984375 -0.4412060546875043 +1.81025 -0.02532958984375 -0.4412060546875043 +1.810375 -0.023040771484375 -0.4412060546875043 +1.8105 -0.020751953125 -0.4412060546875043 +1.810625 -0.020751953125 -0.4412060546875043 +1.81075 -0.0184326171875 -0.4412060546875043 +1.810875 -0.0184326171875 -0.4412060546875043 +1.811 -0.016143798828125 -0.4412060546875043 +1.811125 -0.013824462890625 -0.4412060546875043 +1.81125 -0.013824462890625 -0.4412060546875043 +1.811375 -0.01153564453125 -0.4412060546875043 +1.8115 -0.01153564453125 -0.4412060546875043 +1.811625 -0.00921630859375 -0.4412060546875043 +1.81175 -0.00689697265625 -0.4412060546875043 +1.811875 -0.00689697265625 -0.4412060546875043 +1.812 -0.004608154296875 -0.4412060546875043 +1.812125 -0.004608154296875 -0.4412060546875043 +1.81225 -0.002288818359375 -0.4412060546875043 1.812375 0.0 -0.4412060546875043 1.8125 0.0 -0.4412060546875043 1.812625 0.002288818359375 -0.4412060546875043 @@ -14999,504 +14999,504 @@ 1.87475 0.003082275390625 -0.5893066406249988 1.874875 0.0 -0.5893066406249988 1.875 0.0 -0.5893066406249988 -1.875125 -0.00311279296875 -0.5893066406249988 -1.87525 -0.00311279296875 -0.5893066406249988 -1.875375 -0.006195068359375 -0.5893066406249988 -1.8755 -0.00927734375 -0.5893066406249988 -1.875625 -0.00927734375 -0.5893066406249988 -1.87575 -0.012359619140625 -0.5893066406249988 -1.875875 -0.012359619140625 -0.5893066406249988 -1.876 -0.01544189453125 -0.5893066406249988 -1.876125 -0.018524169921875 -0.5893066406249988 -1.87625 -0.018524169921875 -0.5893066406249988 -1.876375 -0.021575927734375 -0.5893066406249988 -1.8765 -0.021575927734375 -0.5893066406249988 -1.876625 -0.024658203125 -0.5893066406249988 -1.87675 -0.027740478515625 -0.5893066406249988 -1.876875 -0.027740478515625 -0.5893066406249988 -1.877 -0.03082275390625 -0.5893066406249988 -1.877125 -0.03082275390625 -0.5893066406249988 -1.87725 -0.03387451171875 -0.5893066406249988 -1.877375 -0.03692626953125 -0.5893066406249988 -1.8775 -0.03692626953125 -0.5893066406249988 -1.877625 -0.040008544921875 -0.5893066406249988 -1.87775 -0.040008544921875 -0.5893066406249988 -1.877875 -0.043060302734375 -0.5893066406249988 -1.878 -0.046112060546875 -0.5893066406249988 -1.878125 -0.046112060546875 -0.5893066406249988 -1.87825 -0.04913330078125 -0.5893066406249988 -1.878375 -0.04913330078125 -0.5893066406249988 -1.8785 -0.05218505859375 -0.5893066406249988 -1.878625 -0.055206298828125 -0.5893066406249988 -1.87875 -0.055206298828125 -0.5893066406249988 -1.878875 -0.058258056640625 -0.5893066406249988 -1.879 -0.058258056640625 -0.5893066406249988 -1.879125 -0.061279296875 -0.5893066406249988 -1.87925 -0.06427001953125 -0.5893066406249988 -1.879375 -0.06427001953125 -0.5893066406249988 -1.8795 -0.067291259765625 -0.5893066406249988 -1.879625 -0.067291259765625 -0.5893066406249988 -1.87975 -0.070281982421875 -0.5893066406249988 -1.879875 -0.073272705078125 -0.5893066406249988 -1.88 -0.073272705078125 -0.5893066406249988 -1.880125 -0.076263427734375 -0.5893066406249988 -1.88025 -0.076263427734375 -0.5893066406249988 -1.880375 -0.079254150390625 -0.5893066406249988 -1.8805 -0.08221435546875 -0.5893066406249988 -1.880625 -0.08221435546875 -0.5893066406249988 -1.88075 -0.085174560546875 -0.5893066406249988 -1.880875 -0.085174560546875 -0.5893066406249988 -1.881 -0.088104248046875 -0.5893066406249988 -1.881125 -0.091064453125 -0.5893066406249988 -1.88125 -0.091064453125 -0.5893066406249988 -1.881375 -0.093994140625 -0.5893066406249988 -1.8815 -0.093994140625 -0.5893066406249988 -1.881625 -0.096893310546875 -0.5893066406249988 -1.88175 -0.099822998046875 -0.5893066406249988 -1.881875 -0.099822998046875 -0.5893066406249988 -1.882 -0.10272216796875 -0.5893066406249988 -1.882125 -0.10272216796875 -0.5893066406249988 -1.88225 -0.1055908203125 -0.5893066406249988 -1.882375 -0.108489990234375 -0.5893066406249988 -1.8825 -0.108489990234375 -0.5893066406249988 -1.882625 -0.111328125 -0.5893066406249988 -1.88275 -0.111328125 -0.5893066406249988 -1.882875 -0.11419677734375 -0.5893066406249988 -1.883 -0.117034912109375 -0.5893066406249988 -1.883125 -0.117034912109375 -0.5893066406249988 -1.88325 -0.119842529296875 -0.5893066406249988 -1.883375 -0.119842529296875 -0.5893066406249988 -1.8835 -0.122650146484375 -0.5893066406249988 -1.883625 -0.125457763671875 -0.5893066406249988 -1.88375 -0.125457763671875 -0.5893066406249988 -1.883875 -0.12823486328125 -0.5893066406249988 -1.884 -0.12823486328125 -0.5893066406249988 -1.884125 -0.131011962890625 -0.5893066406249988 -1.88425 -0.133758544921875 -0.5893066406249988 -1.884375 -0.133758544921875 -0.5893066406249988 -1.8845 -0.136505126953125 -0.5893066406249988 -1.884625 -0.136505126953125 -0.5893066406249988 -1.88475 -0.139251708984375 -0.5893066406249988 -1.884875 -0.1419677734375 -0.5893066406249988 -1.885 -0.1419677734375 -0.5893066406249988 -1.885125 -0.1446533203125 -0.5893066406249988 -1.88525 -0.1446533203125 -0.5893066406249988 -1.885375 -0.1473388671875 -0.5893066406249988 -1.8855 -0.149993896484375 -0.5893066406249988 -1.885625 -0.149993896484375 -0.5893066406249988 -1.88575 -0.15264892578125 -0.5893066406249988 -1.885875 -0.15264892578125 -0.5893066406249988 -1.886 -0.1552734375 -0.5893066406249988 -1.886125 -0.15789794921875 -0.5893066406249988 -1.88625 -0.15789794921875 -0.5893066406249988 -1.886375 -0.160491943359375 -0.5893066406249988 -1.8865 -0.160491943359375 -0.5893066406249988 -1.886625 -0.163055419921875 -0.5893066406249988 -1.88675 -0.165618896484375 -0.5893066406249988 -1.886875 -0.165618896484375 -0.5893066406249988 -1.887 -0.16815185546875 -0.5893066406249988 -1.887125 -0.16815185546875 -0.5893066406249988 -1.88725 -0.170684814453125 -0.5893066406249988 -1.887375 -0.173187255859375 -0.5893066406249988 -1.8875 -0.173187255859375 -0.5893066406249988 -1.887625 -0.175689697265625 -0.5893066406249988 -1.88775 -0.175689697265625 -0.5893066406249988 -1.887875 -0.178131103515625 -0.5893066406249988 -1.888 -0.145721435546875 -0.4754394531249956 -1.888125 -0.145721435546875 -0.4754394531249956 -1.88825 -0.147674560546875 -0.4754394531249956 -1.888375 -0.147674560546875 -0.4754394531249956 -1.8885 -0.14959716796875 -0.4754394531249956 -1.888625 -0.151519775390625 -0.4754394531249956 -1.88875 -0.151519775390625 -0.4754394531249956 -1.888875 -0.1534423828125 -0.4754394531249956 -1.889 -0.1534423828125 -0.4754394531249956 -1.889125 -0.15533447265625 -0.4754394531249956 -1.88925 -0.1572265625 -0.4754394531249956 -1.889375 -0.1572265625 -0.4754394531249956 -1.8895 -0.1590576171875 -0.4754394531249956 -1.889625 -0.1590576171875 -0.4754394531249956 -1.88975 -0.160919189453125 -0.4754394531249956 -1.889875 -0.1627197265625 -0.4754394531249956 -1.89 -0.1627197265625 -0.4754394531249956 -1.890125 -0.16455078125 -0.4754394531249956 -1.89025 -0.16455078125 -0.4754394531249956 -1.890375 -0.16632080078125 -0.4754394531249956 -1.8905 -0.1680908203125 -0.4754394531249956 -1.890625 -0.1680908203125 -0.4754394531249956 -1.89075 -0.16986083984375 -0.4754394531249956 -1.890875 -0.16986083984375 -0.4754394531249956 -1.891 -0.17156982421875 -0.4754394531249956 -1.891125 -0.173309326171875 -0.4754394531249956 -1.89125 -0.173309326171875 -0.4754394531249956 -1.891375 -0.17498779296875 -0.4754394531249956 -1.8915 -0.17498779296875 -0.4754394531249956 -1.891625 -0.176666259765625 -0.4754394531249956 -1.89175 -0.178314208984375 -0.4754394531249956 -1.891875 -0.178314208984375 -0.4754394531249956 -1.892 -0.179962158203125 -0.4754394531249956 -1.892125 -0.179962158203125 -0.4754394531249956 -1.89225 -0.18157958984375 -0.4754394531249956 -1.892375 -0.18316650390625 -0.4754394531249956 -1.8925 -0.18316650390625 -0.4754394531249956 -1.892625 -0.18475341796875 -0.4754394531249956 -1.89275 -0.18475341796875 -0.4754394531249956 -1.892875 -0.186309814453125 -0.4754394531249956 -1.893 -0.187835693359375 -0.4754394531249956 -1.893125 -0.187835693359375 -0.4754394531249956 -1.89325 -0.189361572265625 -0.4754394531249956 -1.893375 -0.189361572265625 -0.4754394531249956 -1.8935 -0.19085693359375 -0.4754394531249956 -1.893625 -0.19232177734375 -0.4754394531249956 -1.89375 -0.19232177734375 -0.4754394531249956 -1.893875 -0.19378662109375 -0.4754394531249956 -1.894 -0.19378662109375 -0.4754394531249956 -1.894125 -0.195220947265625 -0.4754394531249956 -1.89425 -0.196624755859375 -0.4754394531249956 -1.894375 -0.196624755859375 -0.4754394531249956 -1.8945 -0.197998046875 -0.4754394531249956 -1.894625 -0.197998046875 -0.4754394531249956 -1.89475 -0.199371337890625 -0.4754394531249956 -1.894875 -0.200714111328125 -0.4754394531249956 -1.895 -0.200714111328125 -0.4754394531249956 -1.895125 -0.2020263671875 -0.4754394531249956 -1.89525 -0.2020263671875 -0.4754394531249956 -1.895375 -0.203338623046875 -0.4754394531249956 -1.8955 -0.204620361328125 -0.4754394531249956 -1.895625 -0.204620361328125 -0.4754394531249956 -1.89575 -0.20587158203125 -0.4754394531249956 -1.895875 -0.20587158203125 -0.4754394531249956 -1.896 -0.207122802734375 -0.4754394531249956 -1.896125 -0.20831298828125 -0.4754394531249956 -1.89625 -0.20831298828125 -0.4754394531249956 -1.896375 -0.209503173828125 -0.4754394531249956 -1.8965 -0.209503173828125 -0.4754394531249956 -1.896625 -0.210662841796875 -0.4754394531249956 -1.89675 -0.211822509765625 -0.4754394531249956 -1.896875 -0.211822509765625 -0.4754394531249956 -1.897 -0.212921142578125 -0.4754394531249956 -1.897125 -0.212921142578125 -0.4754394531249956 -1.89725 -0.214019775390625 -0.4754394531249956 -1.897375 -0.215087890625 -0.4754394531249956 -1.8975 -0.215087890625 -0.4754394531249956 -1.897625 -0.216156005859375 -0.4754394531249956 -1.89775 -0.216156005859375 -0.4754394531249956 -1.897875 -0.2171630859375 -0.4754394531249956 -1.898 -0.218170166015625 -0.4754394531249956 -1.898125 -0.218170166015625 -0.4754394531249956 -1.89825 -0.219146728515625 -0.4754394531249956 -1.898375 -0.219146728515625 -0.4754394531249956 -1.8985 -0.2200927734375 -0.4754394531249956 -1.898625 -0.221038818359375 -0.4754394531249956 -1.89875 -0.221038818359375 -0.4754394531249956 -1.898875 -0.221923828125 -0.4754394531249956 -1.899 -0.221923828125 -0.4754394531249956 -1.899125 -0.222808837890625 -0.4754394531249956 -1.89925 -0.223663330078125 -0.4754394531249956 -1.899375 -0.223663330078125 -0.4754394531249956 -1.8995 -0.2244873046875 -0.4754394531249956 -1.899625 -0.2244873046875 -0.4754394531249956 -1.89975 -0.225311279296875 -0.4754394531249956 -1.899875 -0.22607421875 -0.4754394531249956 -1.9 -0.22607421875 -0.4754394531249956 -1.900125 -0.226837158203125 -0.4754394531249956 -1.90025 -0.226837158203125 -0.4754394531249956 -1.900375 -0.227569580078125 -0.4754394531249956 -1.9005 -0.228271484375 -0.4754394531249956 -1.900625 -0.228271484375 -0.4754394531249956 -1.90075 -0.228973388671875 -0.4754394531249956 -1.900875 -0.228973388671875 -0.4754394531249956 -1.901 -0.2296142578125 -0.4754394531249956 -1.901125 -0.230255126953125 -0.4754394531249956 -1.90125 -0.230255126953125 -0.4754394531249956 -1.901375 -0.230865478515625 -0.4754394531249956 -1.9015 -0.230865478515625 -0.4754394531249956 -1.901625 -0.2314453125 -0.4754394531249956 -1.90175 -0.23199462890625 -0.4754394531249956 -1.901875 -0.23199462890625 -0.4754394531249956 -1.902 -0.232513427734375 -0.4754394531249956 -1.902125 -0.232513427734375 -0.4754394531249956 -1.90225 -0.2330322265625 -0.4754394531249956 -1.902375 -0.2335205078125 -0.4754394531249956 -1.9025 -0.2335205078125 -0.4754394531249956 -1.902625 -0.233978271484375 -0.4754394531249956 -1.90275 -0.233978271484375 -0.4754394531249956 -1.902875 -0.234405517578125 -0.4754394531249956 -1.903 -0.23480224609375 -0.4754394531249956 -1.903125 -0.23480224609375 -0.4754394531249956 -1.90325 -0.23516845703125 -0.4754394531249956 -1.903375 -0.23516845703125 -0.4754394531249956 -1.9035 -0.235504150390625 -0.4754394531249956 -1.903625 -0.23583984375 -0.4754394531249956 -1.90375 -0.23583984375 -0.4754394531249956 -1.903875 -0.23614501953125 -0.4754394531249956 -1.904 -0.23614501953125 -0.4754394531249956 -1.904125 -0.236419677734375 -0.4754394531249956 -1.90425 -0.236663818359375 -0.4754394531249956 -1.904375 -0.236663818359375 -0.4754394531249956 -1.9045 -0.23687744140625 -0.4754394531249956 -1.904625 -0.23687744140625 -0.4754394531249956 -1.90475 -0.237091064453125 -0.4754394531249956 -1.904875 -0.23724365234375 -0.4754394531249956 -1.905 -0.23724365234375 -0.4754394531249956 -1.905125 -0.237396240234375 -0.4754394531249956 -1.90525 -0.237396240234375 -0.4754394531249956 -1.905375 -0.237518310546875 -0.4754394531249956 -1.9055 -0.23760986328125 -0.4754394531249956 -1.905625 -0.23760986328125 -0.4754394531249956 -1.90575 -0.2376708984375 -0.4754394531249956 -1.905875 -0.2376708984375 -0.4754394531249956 -1.906 -0.237701416015625 -0.4754394531249956 -1.906125 -0.23773193359375 -0.4754394531249956 -1.90625 -0.23773193359375 -0.4754394531249956 -1.906375 -0.237701416015625 -0.4754394531249956 -1.9065 -0.237701416015625 -0.4754394531249956 -1.906625 -0.2376708984375 -0.4754394531249956 -1.90675 -0.23760986328125 -0.4754394531249956 -1.906875 -0.23760986328125 -0.4754394531249956 -1.907 -0.237518310546875 -0.4754394531249956 -1.907125 -0.237518310546875 -0.4754394531249956 -1.90725 -0.237396240234375 -0.4754394531249956 -1.907375 -0.23724365234375 -0.4754394531249956 -1.9075 -0.23724365234375 -0.4754394531249956 -1.907625 -0.237091064453125 -0.4754394531249956 -1.90775 -0.237091064453125 -0.4754394531249956 -1.907875 -0.23687744140625 -0.4754394531249956 -1.908 -0.236663818359375 -0.4754394531249956 -1.908125 -0.236663818359375 -0.4754394531249956 -1.90825 -0.236419677734375 -0.4754394531249956 -1.908375 -0.236419677734375 -0.4754394531249956 -1.9085 -0.23614501953125 -0.4754394531249956 -1.908625 -0.23583984375 -0.4754394531249956 -1.90875 -0.23583984375 -0.4754394531249956 -1.908875 -0.235504150390625 -0.4754394531249956 -1.909 -0.235504150390625 -0.4754394531249956 -1.909125 -0.23516845703125 -0.4754394531249956 -1.90925 -0.23480224609375 -0.4754394531249956 -1.909375 -0.23480224609375 -0.4754394531249956 -1.9095 -0.234405517578125 -0.4754394531249956 -1.909625 -0.234405517578125 -0.4754394531249956 -1.90975 -0.233978271484375 -0.4754394531249956 -1.909875 -0.2335205078125 -0.4754394531249956 -1.91 -0.2335205078125 -0.4754394531249956 -1.910125 -0.2330322265625 -0.4754394531249956 -1.91025 -0.2330322265625 -0.4754394531249956 -1.910375 -0.232513427734375 -0.4754394531249956 -1.9105 -0.23199462890625 -0.4754394531249956 -1.910625 -0.23199462890625 -0.4754394531249956 -1.91075 -0.2314453125 -0.4754394531249956 -1.910875 -0.2314453125 -0.4754394531249956 -1.911 -0.230865478515625 -0.4754394531249956 -1.911125 -0.230255126953125 -0.4754394531249956 -1.91125 -0.230255126953125 -0.4754394531249956 -1.911375 -0.2296142578125 -0.4754394531249956 -1.9115 -0.2296142578125 -0.4754394531249956 -1.911625 -0.228973388671875 -0.4754394531249956 -1.91175 -0.228271484375 -0.4754394531249956 -1.911875 -0.228271484375 -0.4754394531249956 -1.912 -0.227569580078125 -0.4754394531249956 -1.912125 -0.227569580078125 -0.4754394531249956 -1.91225 -0.226837158203125 -0.4754394531249956 -1.912375 -0.22607421875 -0.4754394531249956 -1.9125 -0.22607421875 -0.4754394531249956 -1.912625 -0.225311279296875 -0.4754394531249956 -1.91275 -0.225311279296875 -0.4754394531249956 -1.912875 -0.2244873046875 -0.4754394531249956 -1.913 -0.223663330078125 -0.4754394531249956 -1.913125 -0.223663330078125 -0.4754394531249956 -1.91325 -0.222808837890625 -0.4754394531249956 -1.913375 -0.222808837890625 -0.4754394531249956 -1.9135 -0.221923828125 -0.4754394531249956 -1.913625 -0.221038818359375 -0.4754394531249956 -1.91375 -0.221038818359375 -0.4754394531249956 -1.913875 -0.2200927734375 -0.4754394531249956 -1.914 -0.2200927734375 -0.4754394531249956 -1.914125 -0.219146728515625 -0.4754394531249956 -1.91425 -0.218170166015625 -0.4754394531249956 -1.914375 -0.218170166015625 -0.4754394531249956 -1.9145 -0.2171630859375 -0.4754394531249956 -1.914625 -0.2171630859375 -0.4754394531249956 -1.91475 -0.216156005859375 -0.4754394531249956 -1.914875 -0.215087890625 -0.4754394531249956 -1.915 -0.215087890625 -0.4754394531249956 -1.915125 -0.214019775390625 -0.4754394531249956 -1.91525 -0.214019775390625 -0.4754394531249956 -1.915375 -0.212921142578125 -0.4754394531249956 -1.9155 -0.211822509765625 -0.4754394531249956 -1.915625 -0.211822509765625 -0.4754394531249956 -1.91575 -0.210662841796875 -0.4754394531249956 -1.915875 -0.210662841796875 -0.4754394531249956 -1.916 -0.209503173828125 -0.4754394531249956 -1.916125 -0.20831298828125 -0.4754394531249956 -1.91625 -0.20831298828125 -0.4754394531249956 -1.916375 -0.207122802734375 -0.4754394531249956 -1.9165 -0.207122802734375 -0.4754394531249956 -1.916625 -0.20587158203125 -0.4754394531249956 -1.91675 -0.204620361328125 -0.4754394531249956 -1.916875 -0.204620361328125 -0.4754394531249956 -1.917 -0.203338623046875 -0.4754394531249956 -1.917125 -0.203338623046875 -0.4754394531249956 -1.91725 -0.2020263671875 -0.4754394531249956 -1.917375 -0.200714111328125 -0.4754394531249956 -1.9175 -0.200714111328125 -0.4754394531249956 -1.917625 -0.199371337890625 -0.4754394531249956 -1.91775 -0.199371337890625 -0.4754394531249956 -1.917875 -0.197998046875 -0.4754394531249956 -1.918 -0.196624755859375 -0.4754394531249956 -1.918125 -0.196624755859375 -0.4754394531249956 -1.91825 -0.195220947265625 -0.4754394531249956 -1.918375 -0.195220947265625 -0.4754394531249956 -1.9185 -0.19378662109375 -0.4754394531249956 -1.918625 -0.19232177734375 -0.4754394531249956 -1.91875 -0.19232177734375 -0.4754394531249956 -1.918875 -0.19085693359375 -0.4754394531249956 -1.919 -0.19085693359375 -0.4754394531249956 -1.919125 -0.189361572265625 -0.4754394531249956 -1.91925 -0.187835693359375 -0.4754394531249956 -1.919375 -0.187835693359375 -0.4754394531249956 -1.9195 -0.186309814453125 -0.4754394531249956 -1.919625 -0.186309814453125 -0.4754394531249956 -1.91975 -0.18475341796875 -0.4754394531249956 -1.919875 -0.18316650390625 -0.4754394531249956 -1.92 -0.0977783203125 -0.2537792968749932 -1.920125 -0.096923828125 -0.2537792968749932 -1.92025 -0.096923828125 -0.2537792968749932 -1.920375 -0.0960693359375 -0.2537792968749932 -1.9205 -0.095184326171875 -0.2537792968749932 -1.920625 -0.095184326171875 -0.2537792968749932 -1.92075 -0.09429931640625 -0.2537792968749932 -1.920875 -0.09429931640625 -0.2537792968749932 -1.921 -0.093414306640625 -0.2537792968749932 -1.921125 -0.092498779296875 -0.2537792968749932 -1.92125 -0.092498779296875 -0.2537792968749932 -1.921375 -0.091583251953125 -0.2537792968749932 -1.9215 -0.091583251953125 -0.2537792968749932 -1.921625 -0.090667724609375 -0.2537792968749932 -1.92175 -0.0897216796875 -0.2537792968749932 -1.921875 -0.0897216796875 -0.2537792968749932 -1.922 -0.08880615234375 -0.2537792968749932 -1.922125 -0.08880615234375 -0.2537792968749932 -1.92225 -0.08782958984375 -0.2537792968749932 -1.922375 -0.086883544921875 -0.2537792968749932 -1.9225 -0.086883544921875 -0.2537792968749932 -1.922625 -0.085906982421875 -0.2537792968749932 -1.92275 -0.085906982421875 -0.2537792968749932 -1.922875 -0.084930419921875 -0.2537792968749932 -1.923 -0.08392333984375 -0.2537792968749932 -1.923125 -0.08392333984375 -0.2537792968749932 -1.92325 -0.082916259765625 -0.2537792968749932 -1.923375 -0.082916259765625 -0.2537792968749932 -1.9235 -0.0819091796875 -0.2537792968749932 -1.923625 -0.080902099609375 -0.2537792968749932 -1.92375 -0.080902099609375 -0.2537792968749932 -1.923875 -0.079864501953125 -0.2537792968749932 -1.924 -0.079864501953125 -0.2537792968749932 -1.924125 -0.078826904296875 -0.2537792968749932 -1.92425 -0.077789306640625 -0.2537792968749932 -1.924375 -0.077789306640625 -0.2537792968749932 -1.9245 -0.07672119140625 -0.2537792968749932 -1.924625 -0.07672119140625 -0.2537792968749932 -1.92475 -0.075653076171875 -0.2537792968749932 -1.924875 -0.0745849609375 -0.2537792968749932 -1.925 -0.0745849609375 -0.2537792968749932 -1.925125 -0.073516845703125 -0.2537792968749932 -1.92525 -0.073516845703125 -0.2537792968749932 -1.925375 -0.072418212890625 -0.2537792968749932 -1.9255 -0.071319580078125 -0.2537792968749932 -1.925625 -0.071319580078125 -0.2537792968749932 -1.92575 -0.070220947265625 -0.2537792968749932 -1.925875 -0.070220947265625 -0.2537792968749932 -1.926 -0.069122314453125 -0.2537792968749932 -1.926125 -0.0679931640625 -0.2537792968749932 -1.92625 -0.0679931640625 -0.2537792968749932 -1.926375 -0.066864013671875 -0.2537792968749932 -1.9265 -0.066864013671875 -0.2537792968749932 -1.926625 -0.06573486328125 -0.2537792968749932 -1.92675 -0.064605712890625 -0.2537792968749932 -1.926875 -0.064605712890625 -0.2537792968749932 -1.927 -0.063446044921875 -0.2537792968749932 -1.927125 -0.063446044921875 -0.2537792968749932 -1.92725 -0.06231689453125 -0.2537792968749932 -1.927375 -0.061126708984375 -0.2537792968749932 -1.9275 -0.061126708984375 -0.2537792968749932 -1.927625 -0.059967041015625 -0.2537792968749932 -1.92775 -0.059967041015625 -0.2537792968749932 -1.927875 -0.058807373046875 -0.2537792968749932 -1.928 -0.0576171875 -0.2537792968749932 -1.928125 -0.0576171875 -0.2537792968749932 -1.92825 -0.056427001953125 -0.2537792968749932 -1.928375 -0.056427001953125 -0.2537792968749932 -1.9285 -0.05523681640625 -0.2537792968749932 -1.928625 -0.054046630859375 -0.2537792968749932 -1.92875 -0.054046630859375 -0.2537792968749932 -1.928875 -0.052825927734375 -0.2537792968749932 -1.929 -0.052825927734375 -0.2537792968749932 -1.929125 -0.0516357421875 -0.2537792968749932 -1.92925 -0.0504150390625 -0.2537792968749932 -1.929375 -0.0504150390625 -0.2537792968749932 -1.9295 -0.0491943359375 -0.2537792968749932 -1.929625 -0.0491943359375 -0.2537792968749932 -1.92975 -0.047943115234375 -0.2537792968749932 -1.929875 -0.046722412109375 -0.2537792968749932 -1.93 -0.046722412109375 -0.2537792968749932 -1.930125 -0.04547119140625 -0.2537792968749932 -1.93025 -0.04547119140625 -0.2537792968749932 -1.930375 -0.04425048828125 -0.2537792968749932 -1.9305 -0.042999267578125 -0.2537792968749932 -1.930625 -0.042999267578125 -0.2537792968749932 -1.93075 -0.041748046875 -0.2537792968749932 -1.930875 -0.041748046875 -0.2537792968749932 -1.931 -0.040496826171875 -0.2537792968749932 -1.931125 -0.039215087890625 -0.2537792968749932 -1.93125 -0.039215087890625 -0.2537792968749932 -1.931375 -0.0379638671875 -0.2537792968749932 -1.9315 -0.0379638671875 -0.2537792968749932 -1.931625 -0.03668212890625 -0.2537792968749932 -1.93175 -0.035400390625 -0.2537792968749932 -1.931875 -0.035400390625 -0.2537792968749932 -1.932 -0.034149169921875 -0.2537792968749932 -1.932125 -0.034149169921875 -0.2537792968749932 -1.93225 -0.032867431640625 -0.2537792968749932 -1.932375 -0.03155517578125 -0.2537792968749932 -1.9325 -0.03155517578125 -0.2537792968749932 -1.932625 -0.0302734375 -0.2537792968749932 -1.93275 -0.0302734375 -0.2537792968749932 -1.932875 -0.02899169921875 -0.2537792968749932 -1.933 -0.027679443359375 -0.2537792968749932 -1.933125 -0.027679443359375 -0.2537792968749932 -1.93325 -0.026397705078125 -0.2537792968749932 -1.933375 -0.026397705078125 -0.2537792968749932 -1.9335 -0.02508544921875 -0.2537792968749932 -1.933625 -0.023773193359375 -0.2537792968749932 -1.93375 -0.023773193359375 -0.2537792968749932 -1.933875 -0.022491455078125 -0.2537792968749932 -1.934 -0.022491455078125 -0.2537792968749932 -1.934125 -0.02117919921875 -0.2537792968749932 -1.93425 -0.019866943359375 -0.2537792968749932 -1.934375 -0.019866943359375 -0.2537792968749932 -1.9345 -0.0185546875 -0.2537792968749932 -1.934625 -0.0185546875 -0.2537792968749932 -1.93475 -0.017242431640625 -0.2537792968749932 -1.934875 -0.01593017578125 -0.2537792968749932 -1.935 -0.01593017578125 -0.2537792968749932 -1.935125 -0.01458740234375 -0.2537792968749932 -1.93525 -0.01458740234375 -0.2537792968749932 -1.935375 -0.013275146484375 -0.2537792968749932 -1.9355 -0.011962890625 -0.2537792968749932 -1.935625 -0.011962890625 -0.2537792968749932 -1.93575 -0.0106201171875 -0.2537792968749932 -1.935875 -0.0106201171875 -0.2537792968749932 -1.936 -0.009307861328125 -0.2537792968749932 -1.936125 -0.00799560546875 -0.2537792968749932 -1.93625 -0.00799560546875 -0.2537792968749932 -1.936375 -0.00665283203125 -0.2537792968749932 -1.9365 -0.00665283203125 -0.2537792968749932 -1.936625 -0.005340576171875 -0.2537792968749932 -1.93675 -0.003997802734375 -0.2537792968749932 -1.936875 -0.003997802734375 -0.2537792968749932 -1.937 -0.002685546875 -0.2537792968749932 -1.937125 -0.002685546875 -0.2537792968749932 -1.93725 -0.0013427734375 -0.2537792968749932 +1.875125 -0.003082275390625 -0.5893066406249988 +1.87525 -0.003082275390625 -0.5893066406249988 +1.875375 -0.00616455078125 -0.5893066406249988 +1.8755 -0.009246826171875 -0.5893066406249988 +1.875625 -0.009246826171875 -0.5893066406249988 +1.87575 -0.0123291015625 -0.5893066406249988 +1.875875 -0.0123291015625 -0.5893066406249988 +1.876 -0.015411376953125 -0.5893066406249988 +1.876125 -0.01849365234375 -0.5893066406249988 +1.87625 -0.01849365234375 -0.5893066406249988 +1.876375 -0.02154541015625 -0.5893066406249988 +1.8765 -0.02154541015625 -0.5893066406249988 +1.876625 -0.024627685546875 -0.5893066406249988 +1.87675 -0.0277099609375 -0.5893066406249988 +1.876875 -0.0277099609375 -0.5893066406249988 +1.877 -0.030792236328125 -0.5893066406249988 +1.877125 -0.030792236328125 -0.5893066406249988 +1.87725 -0.033843994140625 -0.5893066406249988 +1.877375 -0.036895751953125 -0.5893066406249988 +1.8775 -0.036895751953125 -0.5893066406249988 +1.877625 -0.03997802734375 -0.5893066406249988 +1.87775 -0.03997802734375 -0.5893066406249988 +1.877875 -0.04302978515625 -0.5893066406249988 +1.878 -0.04608154296875 -0.5893066406249988 +1.878125 -0.04608154296875 -0.5893066406249988 +1.87825 -0.049102783203125 -0.5893066406249988 +1.878375 -0.049102783203125 -0.5893066406249988 +1.8785 -0.052154541015625 -0.5893066406249988 +1.878625 -0.05517578125 -0.5893066406249988 +1.87875 -0.05517578125 -0.5893066406249988 +1.878875 -0.0582275390625 -0.5893066406249988 +1.879 -0.0582275390625 -0.5893066406249988 +1.879125 -0.061248779296875 -0.5893066406249988 +1.87925 -0.064239501953125 -0.5893066406249988 +1.879375 -0.064239501953125 -0.5893066406249988 +1.8795 -0.0672607421875 -0.5893066406249988 +1.879625 -0.0672607421875 -0.5893066406249988 +1.87975 -0.07025146484375 -0.5893066406249988 +1.879875 -0.0732421875 -0.5893066406249988 +1.88 -0.0732421875 -0.5893066406249988 +1.880125 -0.07623291015625 -0.5893066406249988 +1.88025 -0.07623291015625 -0.5893066406249988 +1.880375 -0.0792236328125 -0.5893066406249988 +1.8805 -0.082183837890625 -0.5893066406249988 +1.880625 -0.082183837890625 -0.5893066406249988 +1.88075 -0.08514404296875 -0.5893066406249988 +1.880875 -0.08514404296875 -0.5893066406249988 +1.881 -0.08807373046875 -0.5893066406249988 +1.881125 -0.091033935546875 -0.5893066406249988 +1.88125 -0.091033935546875 -0.5893066406249988 +1.881375 -0.093963623046875 -0.5893066406249988 +1.8815 -0.093963623046875 -0.5893066406249988 +1.881625 -0.09686279296875 -0.5893066406249988 +1.88175 -0.09979248046875 -0.5893066406249988 +1.881875 -0.09979248046875 -0.5893066406249988 +1.882 -0.102691650390625 -0.5893066406249988 +1.882125 -0.102691650390625 -0.5893066406249988 +1.88225 -0.105560302734375 -0.5893066406249988 +1.882375 -0.10845947265625 -0.5893066406249988 +1.8825 -0.10845947265625 -0.5893066406249988 +1.882625 -0.111297607421875 -0.5893066406249988 +1.88275 -0.111297607421875 -0.5893066406249988 +1.882875 -0.114166259765625 -0.5893066406249988 +1.883 -0.11700439453125 -0.5893066406249988 +1.883125 -0.11700439453125 -0.5893066406249988 +1.88325 -0.11981201171875 -0.5893066406249988 +1.883375 -0.11981201171875 -0.5893066406249988 +1.8835 -0.12261962890625 -0.5893066406249988 +1.883625 -0.12542724609375 -0.5893066406249988 +1.88375 -0.12542724609375 -0.5893066406249988 +1.883875 -0.128204345703125 -0.5893066406249988 +1.884 -0.128204345703125 -0.5893066406249988 +1.884125 -0.1309814453125 -0.5893066406249988 +1.88425 -0.13372802734375 -0.5893066406249988 +1.884375 -0.13372802734375 -0.5893066406249988 +1.8845 -0.136474609375 -0.5893066406249988 +1.884625 -0.136474609375 -0.5893066406249988 +1.88475 -0.13922119140625 -0.5893066406249988 +1.884875 -0.141937255859375 -0.5893066406249988 +1.885 -0.141937255859375 -0.5893066406249988 +1.885125 -0.144622802734375 -0.5893066406249988 +1.88525 -0.144622802734375 -0.5893066406249988 +1.885375 -0.147308349609375 -0.5893066406249988 +1.8855 -0.14996337890625 -0.5893066406249988 +1.885625 -0.14996337890625 -0.5893066406249988 +1.88575 -0.152618408203125 -0.5893066406249988 +1.885875 -0.152618408203125 -0.5893066406249988 +1.886 -0.155242919921875 -0.5893066406249988 +1.886125 -0.157867431640625 -0.5893066406249988 +1.88625 -0.157867431640625 -0.5893066406249988 +1.886375 -0.16046142578125 -0.5893066406249988 +1.8865 -0.16046142578125 -0.5893066406249988 +1.886625 -0.16302490234375 -0.5893066406249988 +1.88675 -0.16558837890625 -0.5893066406249988 +1.886875 -0.16558837890625 -0.5893066406249988 +1.887 -0.168121337890625 -0.5893066406249988 +1.887125 -0.168121337890625 -0.5893066406249988 +1.88725 -0.170654296875 -0.5893066406249988 +1.887375 -0.17315673828125 -0.5893066406249988 +1.8875 -0.17315673828125 -0.5893066406249988 +1.887625 -0.1756591796875 -0.5893066406249988 +1.88775 -0.1756591796875 -0.5893066406249988 +1.887875 -0.1781005859375 -0.5893066406249988 +1.888 -0.14569091796875 -0.4754394531249956 +1.888125 -0.14569091796875 -0.4754394531249956 +1.88825 -0.14764404296875 -0.4754394531249956 +1.888375 -0.14764404296875 -0.4754394531249956 +1.8885 -0.149566650390625 -0.4754394531249956 +1.888625 -0.1514892578125 -0.4754394531249956 +1.88875 -0.1514892578125 -0.4754394531249956 +1.888875 -0.153411865234375 -0.4754394531249956 +1.889 -0.153411865234375 -0.4754394531249956 +1.889125 -0.155303955078125 -0.4754394531249956 +1.88925 -0.157196044921875 -0.4754394531249956 +1.889375 -0.157196044921875 -0.4754394531249956 +1.8895 -0.159027099609375 -0.4754394531249956 +1.889625 -0.159027099609375 -0.4754394531249956 +1.88975 -0.160888671875 -0.4754394531249956 +1.889875 -0.162689208984375 -0.4754394531249956 +1.89 -0.162689208984375 -0.4754394531249956 +1.890125 -0.164520263671875 -0.4754394531249956 +1.89025 -0.164520263671875 -0.4754394531249956 +1.890375 -0.166290283203125 -0.4754394531249956 +1.8905 -0.168060302734375 -0.4754394531249956 +1.890625 -0.168060302734375 -0.4754394531249956 +1.89075 -0.169830322265625 -0.4754394531249956 +1.890875 -0.169830322265625 -0.4754394531249956 +1.891 -0.171539306640625 -0.4754394531249956 +1.891125 -0.17327880859375 -0.4754394531249956 +1.89125 -0.17327880859375 -0.4754394531249956 +1.891375 -0.174957275390625 -0.4754394531249956 +1.8915 -0.174957275390625 -0.4754394531249956 +1.891625 -0.1766357421875 -0.4754394531249956 +1.89175 -0.17828369140625 -0.4754394531249956 +1.891875 -0.17828369140625 -0.4754394531249956 +1.892 -0.179931640625 -0.4754394531249956 +1.892125 -0.179931640625 -0.4754394531249956 +1.89225 -0.181549072265625 -0.4754394531249956 +1.892375 -0.183135986328125 -0.4754394531249956 +1.8925 -0.183135986328125 -0.4754394531249956 +1.892625 -0.184722900390625 -0.4754394531249956 +1.89275 -0.184722900390625 -0.4754394531249956 +1.892875 -0.186279296875 -0.4754394531249956 +1.893 -0.18780517578125 -0.4754394531249956 +1.893125 -0.18780517578125 -0.4754394531249956 +1.89325 -0.1893310546875 -0.4754394531249956 +1.893375 -0.1893310546875 -0.4754394531249956 +1.8935 -0.190826416015625 -0.4754394531249956 +1.893625 -0.192291259765625 -0.4754394531249956 +1.89375 -0.192291259765625 -0.4754394531249956 +1.893875 -0.193756103515625 -0.4754394531249956 +1.894 -0.193756103515625 -0.4754394531249956 +1.894125 -0.1951904296875 -0.4754394531249956 +1.89425 -0.19659423828125 -0.4754394531249956 +1.894375 -0.19659423828125 -0.4754394531249956 +1.8945 -0.197967529296875 -0.4754394531249956 +1.894625 -0.197967529296875 -0.4754394531249956 +1.89475 -0.1993408203125 -0.4754394531249956 +1.894875 -0.20068359375 -0.4754394531249956 +1.895 -0.20068359375 -0.4754394531249956 +1.895125 -0.201995849609375 -0.4754394531249956 +1.89525 -0.201995849609375 -0.4754394531249956 +1.895375 -0.20330810546875 -0.4754394531249956 +1.8955 -0.20458984375 -0.4754394531249956 +1.895625 -0.20458984375 -0.4754394531249956 +1.89575 -0.205841064453125 -0.4754394531249956 +1.895875 -0.205841064453125 -0.4754394531249956 +1.896 -0.20709228515625 -0.4754394531249956 +1.896125 -0.208282470703125 -0.4754394531249956 +1.89625 -0.208282470703125 -0.4754394531249956 +1.896375 -0.20947265625 -0.4754394531249956 +1.8965 -0.20947265625 -0.4754394531249956 +1.896625 -0.21063232421875 -0.4754394531249956 +1.89675 -0.2117919921875 -0.4754394531249956 +1.896875 -0.2117919921875 -0.4754394531249956 +1.897 -0.212890625 -0.4754394531249956 +1.897125 -0.212890625 -0.4754394531249956 +1.89725 -0.2139892578125 -0.4754394531249956 +1.897375 -0.215057373046875 -0.4754394531249956 +1.8975 -0.215057373046875 -0.4754394531249956 +1.897625 -0.21612548828125 -0.4754394531249956 +1.89775 -0.21612548828125 -0.4754394531249956 +1.897875 -0.217132568359375 -0.4754394531249956 +1.898 -0.2181396484375 -0.4754394531249956 +1.898125 -0.2181396484375 -0.4754394531249956 +1.89825 -0.2191162109375 -0.4754394531249956 +1.898375 -0.2191162109375 -0.4754394531249956 +1.8985 -0.220062255859375 -0.4754394531249956 +1.898625 -0.22100830078125 -0.4754394531249956 +1.89875 -0.22100830078125 -0.4754394531249956 +1.898875 -0.221893310546875 -0.4754394531249956 +1.899 -0.221893310546875 -0.4754394531249956 +1.899125 -0.2227783203125 -0.4754394531249956 +1.89925 -0.2236328125 -0.4754394531249956 +1.899375 -0.2236328125 -0.4754394531249956 +1.8995 -0.224456787109375 -0.4754394531249956 +1.899625 -0.224456787109375 -0.4754394531249956 +1.89975 -0.22528076171875 -0.4754394531249956 +1.899875 -0.226043701171875 -0.4754394531249956 +1.9 -0.226043701171875 -0.4754394531249956 +1.900125 -0.226806640625 -0.4754394531249956 +1.90025 -0.226806640625 -0.4754394531249956 +1.900375 -0.2275390625 -0.4754394531249956 +1.9005 -0.228240966796875 -0.4754394531249956 +1.900625 -0.228240966796875 -0.4754394531249956 +1.90075 -0.22894287109375 -0.4754394531249956 +1.900875 -0.22894287109375 -0.4754394531249956 +1.901 -0.229583740234375 -0.4754394531249956 +1.901125 -0.230224609375 -0.4754394531249956 +1.90125 -0.230224609375 -0.4754394531249956 +1.901375 -0.2308349609375 -0.4754394531249956 +1.9015 -0.2308349609375 -0.4754394531249956 +1.901625 -0.231414794921875 -0.4754394531249956 +1.90175 -0.231964111328125 -0.4754394531249956 +1.901875 -0.231964111328125 -0.4754394531249956 +1.902 -0.23248291015625 -0.4754394531249956 +1.902125 -0.23248291015625 -0.4754394531249956 +1.90225 -0.233001708984375 -0.4754394531249956 +1.902375 -0.233489990234375 -0.4754394531249956 +1.9025 -0.233489990234375 -0.4754394531249956 +1.902625 -0.23394775390625 -0.4754394531249956 +1.90275 -0.23394775390625 -0.4754394531249956 +1.902875 -0.234375 -0.4754394531249956 +1.903 -0.234771728515625 -0.4754394531249956 +1.903125 -0.234771728515625 -0.4754394531249956 +1.90325 -0.235137939453125 -0.4754394531249956 +1.903375 -0.235137939453125 -0.4754394531249956 +1.9035 -0.2354736328125 -0.4754394531249956 +1.903625 -0.235809326171875 -0.4754394531249956 +1.90375 -0.235809326171875 -0.4754394531249956 +1.903875 -0.236114501953125 -0.4754394531249956 +1.904 -0.236114501953125 -0.4754394531249956 +1.904125 -0.23638916015625 -0.4754394531249956 +1.90425 -0.23663330078125 -0.4754394531249956 +1.904375 -0.23663330078125 -0.4754394531249956 +1.9045 -0.236846923828125 -0.4754394531249956 +1.904625 -0.236846923828125 -0.4754394531249956 +1.90475 -0.237060546875 -0.4754394531249956 +1.904875 -0.237213134765625 -0.4754394531249956 +1.905 -0.237213134765625 -0.4754394531249956 +1.905125 -0.23736572265625 -0.4754394531249956 +1.90525 -0.23736572265625 -0.4754394531249956 +1.905375 -0.23748779296875 -0.4754394531249956 +1.9055 -0.237579345703125 -0.4754394531249956 +1.905625 -0.237579345703125 -0.4754394531249956 +1.90575 -0.237640380859375 -0.4754394531249956 +1.905875 -0.237640380859375 -0.4754394531249956 +1.906 -0.2376708984375 -0.4754394531249956 +1.906125 -0.237701416015625 -0.4754394531249956 +1.90625 -0.237701416015625 -0.4754394531249956 +1.906375 -0.2376708984375 -0.4754394531249956 +1.9065 -0.2376708984375 -0.4754394531249956 +1.906625 -0.237640380859375 -0.4754394531249956 +1.90675 -0.237579345703125 -0.4754394531249956 +1.906875 -0.237579345703125 -0.4754394531249956 +1.907 -0.23748779296875 -0.4754394531249956 +1.907125 -0.23748779296875 -0.4754394531249956 +1.90725 -0.23736572265625 -0.4754394531249956 +1.907375 -0.237213134765625 -0.4754394531249956 +1.9075 -0.237213134765625 -0.4754394531249956 +1.907625 -0.237060546875 -0.4754394531249956 +1.90775 -0.237060546875 -0.4754394531249956 +1.907875 -0.236846923828125 -0.4754394531249956 +1.908 -0.23663330078125 -0.4754394531249956 +1.908125 -0.23663330078125 -0.4754394531249956 +1.90825 -0.23638916015625 -0.4754394531249956 +1.908375 -0.23638916015625 -0.4754394531249956 +1.9085 -0.236114501953125 -0.4754394531249956 +1.908625 -0.235809326171875 -0.4754394531249956 +1.90875 -0.235809326171875 -0.4754394531249956 +1.908875 -0.2354736328125 -0.4754394531249956 +1.909 -0.2354736328125 -0.4754394531249956 +1.909125 -0.235137939453125 -0.4754394531249956 +1.90925 -0.234771728515625 -0.4754394531249956 +1.909375 -0.234771728515625 -0.4754394531249956 +1.9095 -0.234375 -0.4754394531249956 +1.909625 -0.234375 -0.4754394531249956 +1.90975 -0.23394775390625 -0.4754394531249956 +1.909875 -0.233489990234375 -0.4754394531249956 +1.91 -0.233489990234375 -0.4754394531249956 +1.910125 -0.233001708984375 -0.4754394531249956 +1.91025 -0.233001708984375 -0.4754394531249956 +1.910375 -0.23248291015625 -0.4754394531249956 +1.9105 -0.231964111328125 -0.4754394531249956 +1.910625 -0.231964111328125 -0.4754394531249956 +1.91075 -0.231414794921875 -0.4754394531249956 +1.910875 -0.231414794921875 -0.4754394531249956 +1.911 -0.2308349609375 -0.4754394531249956 +1.911125 -0.230224609375 -0.4754394531249956 +1.91125 -0.230224609375 -0.4754394531249956 +1.911375 -0.229583740234375 -0.4754394531249956 +1.9115 -0.229583740234375 -0.4754394531249956 +1.911625 -0.22894287109375 -0.4754394531249956 +1.91175 -0.228240966796875 -0.4754394531249956 +1.911875 -0.228240966796875 -0.4754394531249956 +1.912 -0.2275390625 -0.4754394531249956 +1.912125 -0.2275390625 -0.4754394531249956 +1.91225 -0.226806640625 -0.4754394531249956 +1.912375 -0.226043701171875 -0.4754394531249956 +1.9125 -0.226043701171875 -0.4754394531249956 +1.912625 -0.22528076171875 -0.4754394531249956 +1.91275 -0.22528076171875 -0.4754394531249956 +1.912875 -0.224456787109375 -0.4754394531249956 +1.913 -0.2236328125 -0.4754394531249956 +1.913125 -0.2236328125 -0.4754394531249956 +1.91325 -0.2227783203125 -0.4754394531249956 +1.913375 -0.2227783203125 -0.4754394531249956 +1.9135 -0.221893310546875 -0.4754394531249956 +1.913625 -0.22100830078125 -0.4754394531249956 +1.91375 -0.22100830078125 -0.4754394531249956 +1.913875 -0.220062255859375 -0.4754394531249956 +1.914 -0.220062255859375 -0.4754394531249956 +1.914125 -0.2191162109375 -0.4754394531249956 +1.91425 -0.2181396484375 -0.4754394531249956 +1.914375 -0.2181396484375 -0.4754394531249956 +1.9145 -0.217132568359375 -0.4754394531249956 +1.914625 -0.217132568359375 -0.4754394531249956 +1.91475 -0.21612548828125 -0.4754394531249956 +1.914875 -0.215057373046875 -0.4754394531249956 +1.915 -0.215057373046875 -0.4754394531249956 +1.915125 -0.2139892578125 -0.4754394531249956 +1.91525 -0.2139892578125 -0.4754394531249956 +1.915375 -0.212890625 -0.4754394531249956 +1.9155 -0.2117919921875 -0.4754394531249956 +1.915625 -0.2117919921875 -0.4754394531249956 +1.91575 -0.21063232421875 -0.4754394531249956 +1.915875 -0.21063232421875 -0.4754394531249956 +1.916 -0.20947265625 -0.4754394531249956 +1.916125 -0.208282470703125 -0.4754394531249956 +1.91625 -0.208282470703125 -0.4754394531249956 +1.916375 -0.20709228515625 -0.4754394531249956 +1.9165 -0.20709228515625 -0.4754394531249956 +1.916625 -0.205841064453125 -0.4754394531249956 +1.91675 -0.20458984375 -0.4754394531249956 +1.916875 -0.20458984375 -0.4754394531249956 +1.917 -0.20330810546875 -0.4754394531249956 +1.917125 -0.20330810546875 -0.4754394531249956 +1.91725 -0.201995849609375 -0.4754394531249956 +1.917375 -0.20068359375 -0.4754394531249956 +1.9175 -0.20068359375 -0.4754394531249956 +1.917625 -0.1993408203125 -0.4754394531249956 +1.91775 -0.1993408203125 -0.4754394531249956 +1.917875 -0.197967529296875 -0.4754394531249956 +1.918 -0.19659423828125 -0.4754394531249956 +1.918125 -0.19659423828125 -0.4754394531249956 +1.91825 -0.1951904296875 -0.4754394531249956 +1.918375 -0.1951904296875 -0.4754394531249956 +1.9185 -0.193756103515625 -0.4754394531249956 +1.918625 -0.192291259765625 -0.4754394531249956 +1.91875 -0.192291259765625 -0.4754394531249956 +1.918875 -0.190826416015625 -0.4754394531249956 +1.919 -0.190826416015625 -0.4754394531249956 +1.919125 -0.1893310546875 -0.4754394531249956 +1.91925 -0.18780517578125 -0.4754394531249956 +1.919375 -0.18780517578125 -0.4754394531249956 +1.9195 -0.186279296875 -0.4754394531249956 +1.919625 -0.186279296875 -0.4754394531249956 +1.91975 -0.184722900390625 -0.4754394531249956 +1.919875 -0.183135986328125 -0.4754394531249956 +1.92 -0.097747802734375 -0.2537792968749932 +1.920125 -0.096893310546875 -0.2537792968749932 +1.92025 -0.096893310546875 -0.2537792968749932 +1.920375 -0.096038818359375 -0.2537792968749932 +1.9205 -0.09515380859375 -0.2537792968749932 +1.920625 -0.09515380859375 -0.2537792968749932 +1.92075 -0.094268798828125 -0.2537792968749932 +1.920875 -0.094268798828125 -0.2537792968749932 +1.921 -0.0933837890625 -0.2537792968749932 +1.921125 -0.09246826171875 -0.2537792968749932 +1.92125 -0.09246826171875 -0.2537792968749932 +1.921375 -0.091552734375 -0.2537792968749932 +1.9215 -0.091552734375 -0.2537792968749932 +1.921625 -0.09063720703125 -0.2537792968749932 +1.92175 -0.089691162109375 -0.2537792968749932 +1.921875 -0.089691162109375 -0.2537792968749932 +1.922 -0.088775634765625 -0.2537792968749932 +1.922125 -0.088775634765625 -0.2537792968749932 +1.92225 -0.087799072265625 -0.2537792968749932 +1.922375 -0.08685302734375 -0.2537792968749932 +1.9225 -0.08685302734375 -0.2537792968749932 +1.922625 -0.08587646484375 -0.2537792968749932 +1.92275 -0.08587646484375 -0.2537792968749932 +1.922875 -0.08489990234375 -0.2537792968749932 +1.923 -0.083892822265625 -0.2537792968749932 +1.923125 -0.083892822265625 -0.2537792968749932 +1.92325 -0.0828857421875 -0.2537792968749932 +1.923375 -0.0828857421875 -0.2537792968749932 +1.9235 -0.081878662109375 -0.2537792968749932 +1.923625 -0.08087158203125 -0.2537792968749932 +1.92375 -0.08087158203125 -0.2537792968749932 +1.923875 -0.079833984375 -0.2537792968749932 +1.924 -0.079833984375 -0.2537792968749932 +1.924125 -0.07879638671875 -0.2537792968749932 +1.92425 -0.0777587890625 -0.2537792968749932 +1.924375 -0.0777587890625 -0.2537792968749932 +1.9245 -0.076690673828125 -0.2537792968749932 +1.924625 -0.076690673828125 -0.2537792968749932 +1.92475 -0.07562255859375 -0.2537792968749932 +1.924875 -0.074554443359375 -0.2537792968749932 +1.925 -0.074554443359375 -0.2537792968749932 +1.925125 -0.073486328125 -0.2537792968749932 +1.92525 -0.073486328125 -0.2537792968749932 +1.925375 -0.0723876953125 -0.2537792968749932 +1.9255 -0.0712890625 -0.2537792968749932 +1.925625 -0.0712890625 -0.2537792968749932 +1.92575 -0.0701904296875 -0.2537792968749932 +1.925875 -0.0701904296875 -0.2537792968749932 +1.926 -0.069091796875 -0.2537792968749932 +1.926125 -0.067962646484375 -0.2537792968749932 +1.92625 -0.067962646484375 -0.2537792968749932 +1.926375 -0.06683349609375 -0.2537792968749932 +1.9265 -0.06683349609375 -0.2537792968749932 +1.926625 -0.065704345703125 -0.2537792968749932 +1.92675 -0.0645751953125 -0.2537792968749932 +1.926875 -0.0645751953125 -0.2537792968749932 +1.927 -0.06341552734375 -0.2537792968749932 +1.927125 -0.06341552734375 -0.2537792968749932 +1.92725 -0.062286376953125 -0.2537792968749932 +1.927375 -0.06109619140625 -0.2537792968749932 +1.9275 -0.06109619140625 -0.2537792968749932 +1.927625 -0.0599365234375 -0.2537792968749932 +1.92775 -0.0599365234375 -0.2537792968749932 +1.927875 -0.05877685546875 -0.2537792968749932 +1.928 -0.057586669921875 -0.2537792968749932 +1.928125 -0.057586669921875 -0.2537792968749932 +1.92825 -0.056396484375 -0.2537792968749932 +1.928375 -0.056396484375 -0.2537792968749932 +1.9285 -0.055206298828125 -0.2537792968749932 +1.928625 -0.05401611328125 -0.2537792968749932 +1.92875 -0.05401611328125 -0.2537792968749932 +1.928875 -0.05279541015625 -0.2537792968749932 +1.929 -0.05279541015625 -0.2537792968749932 +1.929125 -0.051605224609375 -0.2537792968749932 +1.92925 -0.050384521484375 -0.2537792968749932 +1.929375 -0.050384521484375 -0.2537792968749932 +1.9295 -0.049163818359375 -0.2537792968749932 +1.929625 -0.049163818359375 -0.2537792968749932 +1.92975 -0.04791259765625 -0.2537792968749932 +1.929875 -0.04669189453125 -0.2537792968749932 +1.93 -0.04669189453125 -0.2537792968749932 +1.930125 -0.045440673828125 -0.2537792968749932 +1.93025 -0.045440673828125 -0.2537792968749932 +1.930375 -0.044219970703125 -0.2537792968749932 +1.9305 -0.04296875 -0.2537792968749932 +1.930625 -0.04296875 -0.2537792968749932 +1.93075 -0.041717529296875 -0.2537792968749932 +1.930875 -0.041717529296875 -0.2537792968749932 +1.931 -0.04046630859375 -0.2537792968749932 +1.931125 -0.0391845703125 -0.2537792968749932 +1.93125 -0.0391845703125 -0.2537792968749932 +1.931375 -0.037933349609375 -0.2537792968749932 +1.9315 -0.037933349609375 -0.2537792968749932 +1.931625 -0.036651611328125 -0.2537792968749932 +1.93175 -0.035369873046875 -0.2537792968749932 +1.931875 -0.035369873046875 -0.2537792968749932 +1.932 -0.03411865234375 -0.2537792968749932 +1.932125 -0.03411865234375 -0.2537792968749932 +1.93225 -0.0328369140625 -0.2537792968749932 +1.932375 -0.031524658203125 -0.2537792968749932 +1.9325 -0.031524658203125 -0.2537792968749932 +1.932625 -0.030242919921875 -0.2537792968749932 +1.93275 -0.030242919921875 -0.2537792968749932 +1.932875 -0.028961181640625 -0.2537792968749932 +1.933 -0.02764892578125 -0.2537792968749932 +1.933125 -0.02764892578125 -0.2537792968749932 +1.93325 -0.0263671875 -0.2537792968749932 +1.933375 -0.0263671875 -0.2537792968749932 +1.9335 -0.025054931640625 -0.2537792968749932 +1.933625 -0.02374267578125 -0.2537792968749932 +1.93375 -0.02374267578125 -0.2537792968749932 +1.933875 -0.0224609375 -0.2537792968749932 +1.934 -0.0224609375 -0.2537792968749932 +1.934125 -0.021148681640625 -0.2537792968749932 +1.93425 -0.01983642578125 -0.2537792968749932 +1.934375 -0.01983642578125 -0.2537792968749932 +1.9345 -0.018524169921875 -0.2537792968749932 +1.934625 -0.018524169921875 -0.2537792968749932 +1.93475 -0.0172119140625 -0.2537792968749932 +1.934875 -0.015899658203125 -0.2537792968749932 +1.935 -0.015899658203125 -0.2537792968749932 +1.935125 -0.014556884765625 -0.2537792968749932 +1.93525 -0.014556884765625 -0.2537792968749932 +1.935375 -0.01324462890625 -0.2537792968749932 +1.9355 -0.011932373046875 -0.2537792968749932 +1.935625 -0.011932373046875 -0.2537792968749932 +1.93575 -0.010589599609375 -0.2537792968749932 +1.935875 -0.010589599609375 -0.2537792968749932 +1.936 -0.00927734375 -0.2537792968749932 +1.936125 -0.007965087890625 -0.2537792968749932 +1.93625 -0.007965087890625 -0.2537792968749932 +1.936375 -0.006622314453125 -0.2537792968749932 +1.9365 -0.006622314453125 -0.2537792968749932 +1.936625 -0.00531005859375 -0.2537792968749932 +1.93675 -0.00396728515625 -0.2537792968749932 +1.936875 -0.00396728515625 -0.2537792968749932 +1.937 -0.002655029296875 -0.2537792968749932 +1.937125 -0.002655029296875 -0.2537792968749932 +1.93725 -0.001312255859375 -0.2537792968749932 1.937375 0.0 -0.2537792968749932 1.9375 0.0 -0.2537792968749932 1.937625 0.001312255859375 -0.2537792968749932 @@ -15614,389 +15614,389 @@ 1.951625 0.0828857421875 -0.2537792968749932 1.95175 0.083892822265625 -0.2537792968749932 1.951875 0.083892822265625 -0.2537792968749932 -1.952 -0.013458251953125 0.04025390625000896 -1.952125 -0.013458251953125 0.04025390625000896 -1.95225 -0.013641357421875 0.04025390625000896 -1.952375 -0.0137939453125 0.04025390625000896 -1.9525 -0.0137939453125 0.04025390625000896 -1.952625 -0.013946533203125 0.04025390625000896 -1.95275 -0.013946533203125 0.04025390625000896 -1.952875 -0.01409912109375 0.04025390625000896 -1.953 -0.01422119140625 0.04025390625000896 -1.953125 -0.01422119140625 0.04025390625000896 -1.95325 -0.014373779296875 0.04025390625000896 -1.953375 -0.014373779296875 0.04025390625000896 -1.9535 -0.0145263671875 0.04025390625000896 -1.953625 -0.014678955078125 0.04025390625000896 -1.95375 -0.014678955078125 0.04025390625000896 -1.953875 -0.01483154296875 0.04025390625000896 -1.954 -0.01483154296875 0.04025390625000896 -1.954125 -0.01495361328125 0.04025390625000896 -1.95425 -0.015106201171875 0.04025390625000896 -1.954375 -0.015106201171875 0.04025390625000896 -1.9545 -0.015228271484375 0.04025390625000896 -1.954625 -0.015228271484375 0.04025390625000896 -1.95475 -0.015380859375 0.04025390625000896 -1.954875 -0.0155029296875 0.04025390625000896 -1.955 -0.0155029296875 0.04025390625000896 -1.955125 -0.015655517578125 0.04025390625000896 -1.95525 -0.015655517578125 0.04025390625000896 -1.955375 -0.015777587890625 0.04025390625000896 -1.9555 -0.015899658203125 0.04025390625000896 -1.955625 -0.015899658203125 0.04025390625000896 -1.95575 -0.016021728515625 0.04025390625000896 -1.955875 -0.016021728515625 0.04025390625000896 -1.956 -0.01617431640625 0.04025390625000896 -1.956125 -0.01629638671875 0.04025390625000896 -1.95625 -0.01629638671875 0.04025390625000896 -1.956375 -0.01641845703125 0.04025390625000896 -1.9565 -0.01641845703125 0.04025390625000896 -1.956625 -0.01654052734375 0.04025390625000896 -1.95675 -0.01666259765625 0.04025390625000896 -1.956875 -0.01666259765625 0.04025390625000896 -1.957 -0.016754150390625 0.04025390625000896 -1.957125 -0.016754150390625 0.04025390625000896 -1.95725 -0.016876220703125 0.04025390625000896 -1.957375 -0.016998291015625 0.04025390625000896 -1.9575 -0.016998291015625 0.04025390625000896 -1.957625 -0.017120361328125 0.04025390625000896 -1.95775 -0.017120361328125 0.04025390625000896 -1.957875 -0.0172119140625 0.04025390625000896 -1.958 -0.017333984375 0.04025390625000896 -1.958125 -0.017333984375 0.04025390625000896 -1.95825 -0.017425537109375 0.04025390625000896 -1.958375 -0.017425537109375 0.04025390625000896 -1.9585 -0.017547607421875 0.04025390625000896 -1.958625 -0.01763916015625 0.04025390625000896 -1.95875 -0.01763916015625 0.04025390625000896 -1.958875 -0.017730712890625 0.04025390625000896 -1.959 -0.017730712890625 0.04025390625000896 -1.959125 -0.017822265625 0.04025390625000896 -1.95925 -0.0179443359375 0.04025390625000896 -1.959375 -0.0179443359375 0.04025390625000896 -1.9595 -0.018035888671875 0.04025390625000896 -1.959625 -0.018035888671875 0.04025390625000896 -1.95975 -0.01812744140625 0.04025390625000896 -1.959875 -0.018218994140625 0.04025390625000896 -1.96 -0.018218994140625 0.04025390625000896 -1.960125 -0.018310546875 0.04025390625000896 -1.96025 -0.018310546875 0.04025390625000896 -1.960375 -0.018402099609375 0.04025390625000896 -1.9605 -0.018463134765625 0.04025390625000896 -1.960625 -0.018463134765625 0.04025390625000896 -1.96075 -0.0185546875 0.04025390625000896 -1.960875 -0.0185546875 0.04025390625000896 -1.961 -0.018646240234375 0.04025390625000896 -1.961125 -0.018707275390625 0.04025390625000896 -1.96125 -0.018707275390625 0.04025390625000896 -1.961375 -0.018798828125 0.04025390625000896 -1.9615 -0.018798828125 0.04025390625000896 -1.961625 -0.01885986328125 0.04025390625000896 -1.96175 -0.018951416015625 0.04025390625000896 -1.961875 -0.018951416015625 0.04025390625000896 -1.962 -0.019012451171875 0.04025390625000896 -1.962125 -0.019012451171875 0.04025390625000896 -1.96225 -0.019073486328125 0.04025390625000896 -1.962375 -0.019134521484375 0.04025390625000896 -1.9625 -0.019134521484375 0.04025390625000896 -1.962625 -0.019195556640625 0.04025390625000896 -1.96275 -0.019195556640625 0.04025390625000896 -1.962875 -0.019256591796875 0.04025390625000896 -1.963 -0.019317626953125 0.04025390625000896 -1.963125 -0.019317626953125 0.04025390625000896 -1.96325 -0.019378662109375 0.04025390625000896 -1.963375 -0.019378662109375 0.04025390625000896 -1.9635 -0.019439697265625 0.04025390625000896 -1.963625 -0.019500732421875 0.04025390625000896 -1.96375 -0.019500732421875 0.04025390625000896 -1.963875 -0.01953125 0.04025390625000896 -1.964 -0.01953125 0.04025390625000896 -1.964125 -0.01959228515625 0.04025390625000896 -1.96425 -0.0196533203125 0.04025390625000896 -1.964375 -0.0196533203125 0.04025390625000896 -1.9645 -0.019683837890625 0.04025390625000896 -1.964625 -0.019683837890625 0.04025390625000896 -1.96475 -0.01971435546875 0.04025390625000896 -1.964875 -0.019775390625 0.04025390625000896 -1.965 -0.019775390625 0.04025390625000896 -1.965125 -0.019805908203125 0.04025390625000896 -1.96525 -0.019805908203125 0.04025390625000896 -1.965375 -0.01983642578125 0.04025390625000896 -1.9655 -0.019866943359375 0.04025390625000896 -1.965625 -0.019866943359375 0.04025390625000896 -1.96575 -0.0198974609375 0.04025390625000896 -1.965875 -0.0198974609375 0.04025390625000896 -1.966 -0.019927978515625 0.04025390625000896 -1.966125 -0.01995849609375 0.04025390625000896 -1.96625 -0.01995849609375 0.04025390625000896 -1.966375 -0.019989013671875 0.04025390625000896 -1.9665 -0.019989013671875 0.04025390625000896 -1.966625 -0.02001953125 0.04025390625000896 -1.96675 -0.020050048828125 0.04025390625000896 -1.966875 -0.020050048828125 0.04025390625000896 -1.967 -0.020050048828125 0.04025390625000896 -1.967125 -0.020050048828125 0.04025390625000896 -1.96725 -0.02008056640625 0.04025390625000896 -1.967375 -0.02008056640625 0.04025390625000896 -1.9675 -0.02008056640625 0.04025390625000896 -1.967625 -0.020111083984375 0.04025390625000896 -1.96775 -0.020111083984375 0.04025390625000896 -1.967875 -0.020111083984375 0.04025390625000896 -1.968 -0.020111083984375 0.04025390625000896 -1.968125 -0.020111083984375 0.04025390625000896 -1.96825 -0.020111083984375 0.04025390625000896 -1.968375 -0.020111083984375 0.04025390625000896 -1.9685 -0.020111083984375 0.04025390625000896 -1.968625 -0.020111083984375 0.04025390625000896 -1.96875 -0.020111083984375 0.04025390625000896 -1.968875 -0.020111083984375 0.04025390625000896 -1.969 -0.020111083984375 0.04025390625000896 -1.969125 -0.020111083984375 0.04025390625000896 -1.96925 -0.020111083984375 0.04025390625000896 -1.969375 -0.020111083984375 0.04025390625000896 -1.9695 -0.020111083984375 0.04025390625000896 -1.969625 -0.020111083984375 0.04025390625000896 -1.96975 -0.020111083984375 0.04025390625000896 -1.969875 -0.02008056640625 0.04025390625000896 -1.97 -0.02008056640625 0.04025390625000896 -1.970125 -0.02008056640625 0.04025390625000896 -1.97025 -0.02008056640625 0.04025390625000896 -1.970375 -0.020050048828125 0.04025390625000896 -1.9705 -0.020050048828125 0.04025390625000896 -1.970625 -0.020050048828125 0.04025390625000896 -1.97075 -0.02001953125 0.04025390625000896 -1.970875 -0.02001953125 0.04025390625000896 -1.971 -0.019989013671875 0.04025390625000896 -1.971125 -0.01995849609375 0.04025390625000896 -1.97125 -0.01995849609375 0.04025390625000896 -1.971375 -0.019927978515625 0.04025390625000896 -1.9715 -0.019927978515625 0.04025390625000896 -1.971625 -0.0198974609375 0.04025390625000896 -1.97175 -0.019866943359375 0.04025390625000896 -1.971875 -0.019866943359375 0.04025390625000896 -1.972 -0.01983642578125 0.04025390625000896 -1.972125 -0.01983642578125 0.04025390625000896 -1.97225 -0.019805908203125 0.04025390625000896 -1.972375 -0.019775390625 0.04025390625000896 -1.9725 -0.019775390625 0.04025390625000896 -1.972625 -0.01971435546875 0.04025390625000896 -1.97275 -0.01971435546875 0.04025390625000896 -1.972875 -0.019683837890625 0.04025390625000896 -1.973 -0.0196533203125 0.04025390625000896 -1.973125 -0.0196533203125 0.04025390625000896 -1.97325 -0.01959228515625 0.04025390625000896 -1.973375 -0.01959228515625 0.04025390625000896 -1.9735 -0.01953125 0.04025390625000896 -1.973625 -0.019500732421875 0.04025390625000896 -1.97375 -0.019500732421875 0.04025390625000896 -1.973875 -0.019439697265625 0.04025390625000896 -1.974 -0.019439697265625 0.04025390625000896 -1.974125 -0.019378662109375 0.04025390625000896 -1.97425 -0.019317626953125 0.04025390625000896 -1.974375 -0.019317626953125 0.04025390625000896 -1.9745 -0.019256591796875 0.04025390625000896 -1.974625 -0.019256591796875 0.04025390625000896 -1.97475 -0.019195556640625 0.04025390625000896 -1.974875 -0.019134521484375 0.04025390625000896 -1.975 -0.019134521484375 0.04025390625000896 -1.975125 -0.019073486328125 0.04025390625000896 -1.97525 -0.019073486328125 0.04025390625000896 -1.975375 -0.019012451171875 0.04025390625000896 -1.9755 -0.018951416015625 0.04025390625000896 -1.975625 -0.018951416015625 0.04025390625000896 -1.97575 -0.01885986328125 0.04025390625000896 -1.975875 -0.01885986328125 0.04025390625000896 -1.976 -0.018798828125 0.04025390625000896 -1.976125 -0.018707275390625 0.04025390625000896 -1.97625 -0.018707275390625 0.04025390625000896 -1.976375 -0.018646240234375 0.04025390625000896 -1.9765 -0.018646240234375 0.04025390625000896 -1.976625 -0.0185546875 0.04025390625000896 -1.97675 -0.018463134765625 0.04025390625000896 -1.976875 -0.018463134765625 0.04025390625000896 -1.977 -0.018402099609375 0.04025390625000896 -1.977125 -0.018402099609375 0.04025390625000896 -1.97725 -0.018310546875 0.04025390625000896 -1.977375 -0.018218994140625 0.04025390625000896 -1.9775 -0.018218994140625 0.04025390625000896 -1.977625 -0.01812744140625 0.04025390625000896 -1.97775 -0.01812744140625 0.04025390625000896 -1.977875 -0.018035888671875 0.04025390625000896 -1.978 -0.0179443359375 0.04025390625000896 -1.978125 -0.0179443359375 0.04025390625000896 -1.97825 -0.017822265625 0.04025390625000896 -1.978375 -0.017822265625 0.04025390625000896 -1.9785 -0.017730712890625 0.04025390625000896 -1.978625 -0.01763916015625 0.04025390625000896 -1.97875 -0.01763916015625 0.04025390625000896 -1.978875 -0.017547607421875 0.04025390625000896 -1.979 -0.017547607421875 0.04025390625000896 -1.979125 -0.017425537109375 0.04025390625000896 -1.97925 -0.017333984375 0.04025390625000896 -1.979375 -0.017333984375 0.04025390625000896 -1.9795 -0.0172119140625 0.04025390625000896 -1.979625 -0.0172119140625 0.04025390625000896 -1.97975 -0.017120361328125 0.04025390625000896 -1.979875 -0.016998291015625 0.04025390625000896 -1.98 -0.016998291015625 0.04025390625000896 -1.980125 -0.016876220703125 0.04025390625000896 -1.98025 -0.016876220703125 0.04025390625000896 -1.980375 -0.016754150390625 0.04025390625000896 -1.9805 -0.01666259765625 0.04025390625000896 -1.980625 -0.01666259765625 0.04025390625000896 -1.98075 -0.01654052734375 0.04025390625000896 -1.980875 -0.01654052734375 0.04025390625000896 -1.981 -0.01641845703125 0.04025390625000896 -1.981125 -0.01629638671875 0.04025390625000896 -1.98125 -0.01629638671875 0.04025390625000896 -1.981375 -0.01617431640625 0.04025390625000896 -1.9815 -0.01617431640625 0.04025390625000896 -1.981625 -0.016021728515625 0.04025390625000896 -1.98175 -0.015899658203125 0.04025390625000896 -1.981875 -0.015899658203125 0.04025390625000896 -1.982 -0.015777587890625 0.04025390625000896 -1.982125 -0.015777587890625 0.04025390625000896 -1.98225 -0.015655517578125 0.04025390625000896 -1.982375 -0.0155029296875 0.04025390625000896 -1.9825 -0.0155029296875 0.04025390625000896 -1.982625 -0.015380859375 0.04025390625000896 -1.98275 -0.015380859375 0.04025390625000896 -1.982875 -0.015228271484375 0.04025390625000896 -1.983 -0.015106201171875 0.04025390625000896 -1.983125 -0.015106201171875 0.04025390625000896 -1.98325 -0.01495361328125 0.04025390625000896 -1.983375 -0.01495361328125 0.04025390625000896 -1.9835 -0.01483154296875 0.04025390625000896 -1.983625 -0.014678955078125 0.04025390625000896 -1.98375 -0.014678955078125 0.04025390625000896 -1.983875 -0.0145263671875 0.04025390625000896 -1.984 -0.12982177734375 0.3597460937500089 -1.984125 -0.128509521484375 0.3597460937500089 -1.98425 -0.127197265625 0.3597460937500089 -1.984375 -0.127197265625 0.3597460937500089 -1.9845 -0.1258544921875 0.3597460937500089 -1.984625 -0.1258544921875 0.3597460937500089 -1.98475 -0.124481201171875 0.3597460937500089 -1.984875 -0.123138427734375 0.3597460937500089 -1.985 -0.123138427734375 0.3597460937500089 -1.985125 -0.12176513671875 0.3597460937500089 -1.98525 -0.12176513671875 0.3597460937500089 -1.985375 -0.120361328125 0.3597460937500089 -1.9855 -0.11895751953125 0.3597460937500089 -1.985625 -0.11895751953125 0.3597460937500089 -1.98575 -0.117523193359375 0.3597460937500089 -1.985875 -0.117523193359375 0.3597460937500089 -1.986 -0.1160888671875 0.3597460937500089 -1.986125 -0.114654541015625 0.3597460937500089 -1.98625 -0.114654541015625 0.3597460937500089 -1.986375 -0.113189697265625 0.3597460937500089 -1.9865 -0.113189697265625 0.3597460937500089 -1.986625 -0.111724853515625 0.3597460937500089 -1.98675 -0.110260009765625 0.3597460937500089 -1.986875 -0.110260009765625 0.3597460937500089 -1.987 -0.108734130859375 0.3597460937500089 -1.987125 -0.108734130859375 0.3597460937500089 -1.98725 -0.10723876953125 0.3597460937500089 -1.987375 -0.105712890625 0.3597460937500089 -1.9875 -0.105712890625 0.3597460937500089 -1.987625 -0.10418701171875 0.3597460937500089 -1.98775 -0.10418701171875 0.3597460937500089 -1.987875 -0.1026611328125 0.3597460937500089 -1.988 -0.101104736328125 0.3597460937500089 -1.988125 -0.101104736328125 0.3597460937500089 -1.98825 -0.09954833984375 0.3597460937500089 -1.988375 -0.09954833984375 0.3597460937500089 -1.9885 -0.09796142578125 0.3597460937500089 -1.988625 -0.09637451171875 0.3597460937500089 -1.98875 -0.09637451171875 0.3597460937500089 -1.988875 -0.09478759765625 0.3597460937500089 -1.989 -0.09478759765625 0.3597460937500089 -1.989125 -0.093170166015625 0.3597460937500089 -1.98925 -0.091552734375 0.3597460937500089 -1.989375 -0.091552734375 0.3597460937500089 -1.9895 -0.089935302734375 0.3597460937500089 -1.989625 -0.089935302734375 0.3597460937500089 -1.98975 -0.088287353515625 0.3597460937500089 -1.989875 -0.086669921875 0.3597460937500089 -1.99 -0.086669921875 0.3597460937500089 -1.990125 -0.084991455078125 0.3597460937500089 -1.99025 -0.084991455078125 0.3597460937500089 -1.990375 -0.083343505859375 0.3597460937500089 -1.9905 -0.0816650390625 0.3597460937500089 -1.990625 -0.0816650390625 0.3597460937500089 -1.99075 -0.079986572265625 0.3597460937500089 -1.990875 -0.079986572265625 0.3597460937500089 -1.991 -0.078277587890625 0.3597460937500089 -1.991125 -0.07659912109375 0.3597460937500089 -1.99125 -0.07659912109375 0.3597460937500089 -1.991375 -0.07489013671875 0.3597460937500089 -1.9915 -0.07489013671875 0.3597460937500089 -1.991625 -0.073150634765625 0.3597460937500089 -1.99175 -0.071441650390625 0.3597460937500089 -1.991875 -0.071441650390625 0.3597460937500089 -1.992 -0.0697021484375 0.3597460937500089 -1.992125 -0.0697021484375 0.3597460937500089 -1.99225 -0.067962646484375 0.3597460937500089 -1.992375 -0.06622314453125 0.3597460937500089 -1.9925 -0.06622314453125 0.3597460937500089 -1.992625 -0.064453125 0.3597460937500089 -1.99275 -0.064453125 0.3597460937500089 -1.992875 -0.062713623046875 0.3597460937500089 -1.993 -0.060943603515625 0.3597460937500089 -1.993125 -0.060943603515625 0.3597460937500089 -1.99325 -0.05914306640625 0.3597460937500089 -1.993375 -0.05914306640625 0.3597460937500089 -1.9935 -0.057373046875 0.3597460937500089 -1.993625 -0.05560302734375 0.3597460937500089 -1.99375 -0.05560302734375 0.3597460937500089 -1.993875 -0.053802490234375 0.3597460937500089 -1.994 -0.053802490234375 0.3597460937500089 -1.994125 -0.052001953125 0.3597460937500089 -1.99425 -0.050201416015625 0.3597460937500089 -1.994375 -0.050201416015625 0.3597460937500089 -1.9945 -0.048370361328125 0.3597460937500089 -1.994625 -0.048370361328125 0.3597460937500089 -1.99475 -0.04656982421875 0.3597460937500089 -1.994875 -0.04473876953125 0.3597460937500089 -1.995 -0.04473876953125 0.3597460937500089 -1.995125 -0.04290771484375 0.3597460937500089 -1.99525 -0.04290771484375 0.3597460937500089 -1.995375 -0.04107666015625 0.3597460937500089 -1.9955 -0.03924560546875 0.3597460937500089 -1.995625 -0.03924560546875 0.3597460937500089 -1.99575 -0.03741455078125 0.3597460937500089 -1.995875 -0.03741455078125 0.3597460937500089 -1.996 -0.035552978515625 0.3597460937500089 -1.996125 -0.033721923828125 0.3597460937500089 -1.99625 -0.033721923828125 0.3597460937500089 -1.996375 -0.0318603515625 0.3597460937500089 -1.9965 -0.0318603515625 0.3597460937500089 -1.996625 -0.029998779296875 0.3597460937500089 -1.99675 -0.02813720703125 0.3597460937500089 -1.996875 -0.02813720703125 0.3597460937500089 -1.997 -0.026275634765625 0.3597460937500089 -1.997125 -0.026275634765625 0.3597460937500089 -1.99725 -0.0244140625 0.3597460937500089 -1.997375 -0.022552490234375 0.3597460937500089 -1.9975 -0.022552490234375 0.3597460937500089 -1.997625 -0.02069091796875 0.3597460937500089 -1.99775 -0.02069091796875 0.3597460937500089 -1.997875 -0.018829345703125 0.3597460937500089 -1.998 -0.016937255859375 0.3597460937500089 -1.998125 -0.016937255859375 0.3597460937500089 -1.99825 -0.015045166015625 0.3597460937500089 -1.998375 -0.015045166015625 0.3597460937500089 -1.9985 -0.01318359375 0.3597460937500089 -1.998625 -0.01129150390625 0.3597460937500089 -1.99875 -0.01129150390625 0.3597460937500089 -1.998875 -0.009429931640625 0.3597460937500089 -1.999 -0.009429931640625 0.3597460937500089 -1.999125 -0.007537841796875 0.3597460937500089 -1.99925 -0.00567626953125 0.3597460937500089 -1.999375 -0.00567626953125 0.3597460937500089 -1.9995 -0.0037841796875 0.3597460937500089 -1.999625 -0.0037841796875 0.3597460937500089 -1.99975 -0.00189208984375 0.3597460937500089 +1.952 -0.013427734375 0.04025390625000896 +1.952125 -0.013427734375 0.04025390625000896 +1.95225 -0.01361083984375 0.04025390625000896 +1.952375 -0.013763427734375 0.04025390625000896 +1.9525 -0.013763427734375 0.04025390625000896 +1.952625 -0.013916015625 0.04025390625000896 +1.95275 -0.013916015625 0.04025390625000896 +1.952875 -0.014068603515625 0.04025390625000896 +1.953 -0.014190673828125 0.04025390625000896 +1.953125 -0.014190673828125 0.04025390625000896 +1.95325 -0.01434326171875 0.04025390625000896 +1.953375 -0.01434326171875 0.04025390625000896 +1.9535 -0.014495849609375 0.04025390625000896 +1.953625 -0.0146484375 0.04025390625000896 +1.95375 -0.0146484375 0.04025390625000896 +1.953875 -0.014801025390625 0.04025390625000896 +1.954 -0.014801025390625 0.04025390625000896 +1.954125 -0.014923095703125 0.04025390625000896 +1.95425 -0.01507568359375 0.04025390625000896 +1.954375 -0.01507568359375 0.04025390625000896 +1.9545 -0.01519775390625 0.04025390625000896 +1.954625 -0.01519775390625 0.04025390625000896 +1.95475 -0.015350341796875 0.04025390625000896 +1.954875 -0.015472412109375 0.04025390625000896 +1.955 -0.015472412109375 0.04025390625000896 +1.955125 -0.015625 0.04025390625000896 +1.95525 -0.015625 0.04025390625000896 +1.955375 -0.0157470703125 0.04025390625000896 +1.9555 -0.015869140625 0.04025390625000896 +1.955625 -0.015869140625 0.04025390625000896 +1.95575 -0.0159912109375 0.04025390625000896 +1.955875 -0.0159912109375 0.04025390625000896 +1.956 -0.016143798828125 0.04025390625000896 +1.956125 -0.016265869140625 0.04025390625000896 +1.95625 -0.016265869140625 0.04025390625000896 +1.956375 -0.016387939453125 0.04025390625000896 +1.9565 -0.016387939453125 0.04025390625000896 +1.956625 -0.016510009765625 0.04025390625000896 +1.95675 -0.016632080078125 0.04025390625000896 +1.956875 -0.016632080078125 0.04025390625000896 +1.957 -0.0167236328125 0.04025390625000896 +1.957125 -0.0167236328125 0.04025390625000896 +1.95725 -0.016845703125 0.04025390625000896 +1.957375 -0.0169677734375 0.04025390625000896 +1.9575 -0.0169677734375 0.04025390625000896 +1.957625 -0.01708984375 0.04025390625000896 +1.95775 -0.01708984375 0.04025390625000896 +1.957875 -0.017181396484375 0.04025390625000896 +1.958 -0.017303466796875 0.04025390625000896 +1.958125 -0.017303466796875 0.04025390625000896 +1.95825 -0.01739501953125 0.04025390625000896 +1.958375 -0.01739501953125 0.04025390625000896 +1.9585 -0.01751708984375 0.04025390625000896 +1.958625 -0.017608642578125 0.04025390625000896 +1.95875 -0.017608642578125 0.04025390625000896 +1.958875 -0.0177001953125 0.04025390625000896 +1.959 -0.0177001953125 0.04025390625000896 +1.959125 -0.017791748046875 0.04025390625000896 +1.95925 -0.017913818359375 0.04025390625000896 +1.959375 -0.017913818359375 0.04025390625000896 +1.9595 -0.01800537109375 0.04025390625000896 +1.959625 -0.01800537109375 0.04025390625000896 +1.95975 -0.018096923828125 0.04025390625000896 +1.959875 -0.0181884765625 0.04025390625000896 +1.96 -0.0181884765625 0.04025390625000896 +1.960125 -0.018280029296875 0.04025390625000896 +1.96025 -0.018280029296875 0.04025390625000896 +1.960375 -0.01837158203125 0.04025390625000896 +1.9605 -0.0184326171875 0.04025390625000896 +1.960625 -0.0184326171875 0.04025390625000896 +1.96075 -0.018524169921875 0.04025390625000896 +1.960875 -0.018524169921875 0.04025390625000896 +1.961 -0.01861572265625 0.04025390625000896 +1.961125 -0.0186767578125 0.04025390625000896 +1.96125 -0.0186767578125 0.04025390625000896 +1.961375 -0.018768310546875 0.04025390625000896 +1.9615 -0.018768310546875 0.04025390625000896 +1.961625 -0.018829345703125 0.04025390625000896 +1.96175 -0.0189208984375 0.04025390625000896 +1.961875 -0.0189208984375 0.04025390625000896 +1.962 -0.01898193359375 0.04025390625000896 +1.962125 -0.01898193359375 0.04025390625000896 +1.96225 -0.01904296875 0.04025390625000896 +1.962375 -0.01910400390625 0.04025390625000896 +1.9625 -0.01910400390625 0.04025390625000896 +1.962625 -0.0191650390625 0.04025390625000896 +1.96275 -0.0191650390625 0.04025390625000896 +1.962875 -0.01922607421875 0.04025390625000896 +1.963 -0.019287109375 0.04025390625000896 +1.963125 -0.019287109375 0.04025390625000896 +1.96325 -0.01934814453125 0.04025390625000896 +1.963375 -0.01934814453125 0.04025390625000896 +1.9635 -0.0194091796875 0.04025390625000896 +1.963625 -0.01947021484375 0.04025390625000896 +1.96375 -0.01947021484375 0.04025390625000896 +1.963875 -0.019500732421875 0.04025390625000896 +1.964 -0.019500732421875 0.04025390625000896 +1.964125 -0.019561767578125 0.04025390625000896 +1.96425 -0.019622802734375 0.04025390625000896 +1.964375 -0.019622802734375 0.04025390625000896 +1.9645 -0.0196533203125 0.04025390625000896 +1.964625 -0.0196533203125 0.04025390625000896 +1.96475 -0.019683837890625 0.04025390625000896 +1.964875 -0.019744873046875 0.04025390625000896 +1.965 -0.019744873046875 0.04025390625000896 +1.965125 -0.019775390625 0.04025390625000896 +1.96525 -0.019775390625 0.04025390625000896 +1.965375 -0.019805908203125 0.04025390625000896 +1.9655 -0.01983642578125 0.04025390625000896 +1.965625 -0.01983642578125 0.04025390625000896 +1.96575 -0.019866943359375 0.04025390625000896 +1.965875 -0.019866943359375 0.04025390625000896 +1.966 -0.0198974609375 0.04025390625000896 +1.966125 -0.019927978515625 0.04025390625000896 +1.96625 -0.019927978515625 0.04025390625000896 +1.966375 -0.01995849609375 0.04025390625000896 +1.9665 -0.01995849609375 0.04025390625000896 +1.966625 -0.019989013671875 0.04025390625000896 +1.96675 -0.02001953125 0.04025390625000896 +1.966875 -0.02001953125 0.04025390625000896 +1.967 -0.02001953125 0.04025390625000896 +1.967125 -0.02001953125 0.04025390625000896 +1.96725 -0.020050048828125 0.04025390625000896 +1.967375 -0.020050048828125 0.04025390625000896 +1.9675 -0.020050048828125 0.04025390625000896 +1.967625 -0.02008056640625 0.04025390625000896 +1.96775 -0.02008056640625 0.04025390625000896 +1.967875 -0.02008056640625 0.04025390625000896 +1.968 -0.02008056640625 0.04025390625000896 +1.968125 -0.02008056640625 0.04025390625000896 +1.96825 -0.02008056640625 0.04025390625000896 +1.968375 -0.02008056640625 0.04025390625000896 +1.9685 -0.02008056640625 0.04025390625000896 +1.968625 -0.02008056640625 0.04025390625000896 +1.96875 -0.02008056640625 0.04025390625000896 +1.968875 -0.02008056640625 0.04025390625000896 +1.969 -0.02008056640625 0.04025390625000896 +1.969125 -0.02008056640625 0.04025390625000896 +1.96925 -0.02008056640625 0.04025390625000896 +1.969375 -0.02008056640625 0.04025390625000896 +1.9695 -0.02008056640625 0.04025390625000896 +1.969625 -0.02008056640625 0.04025390625000896 +1.96975 -0.02008056640625 0.04025390625000896 +1.969875 -0.020050048828125 0.04025390625000896 +1.97 -0.020050048828125 0.04025390625000896 +1.970125 -0.020050048828125 0.04025390625000896 +1.97025 -0.020050048828125 0.04025390625000896 +1.970375 -0.02001953125 0.04025390625000896 +1.9705 -0.02001953125 0.04025390625000896 +1.970625 -0.02001953125 0.04025390625000896 +1.97075 -0.019989013671875 0.04025390625000896 +1.970875 -0.019989013671875 0.04025390625000896 +1.971 -0.01995849609375 0.04025390625000896 +1.971125 -0.019927978515625 0.04025390625000896 +1.97125 -0.019927978515625 0.04025390625000896 +1.971375 -0.0198974609375 0.04025390625000896 +1.9715 -0.0198974609375 0.04025390625000896 +1.971625 -0.019866943359375 0.04025390625000896 +1.97175 -0.01983642578125 0.04025390625000896 +1.971875 -0.01983642578125 0.04025390625000896 +1.972 -0.019805908203125 0.04025390625000896 +1.972125 -0.019805908203125 0.04025390625000896 +1.97225 -0.019775390625 0.04025390625000896 +1.972375 -0.019744873046875 0.04025390625000896 +1.9725 -0.019744873046875 0.04025390625000896 +1.972625 -0.019683837890625 0.04025390625000896 +1.97275 -0.019683837890625 0.04025390625000896 +1.972875 -0.0196533203125 0.04025390625000896 +1.973 -0.019622802734375 0.04025390625000896 +1.973125 -0.019622802734375 0.04025390625000896 +1.97325 -0.019561767578125 0.04025390625000896 +1.973375 -0.019561767578125 0.04025390625000896 +1.9735 -0.019500732421875 0.04025390625000896 +1.973625 -0.01947021484375 0.04025390625000896 +1.97375 -0.01947021484375 0.04025390625000896 +1.973875 -0.0194091796875 0.04025390625000896 +1.974 -0.0194091796875 0.04025390625000896 +1.974125 -0.01934814453125 0.04025390625000896 +1.97425 -0.019287109375 0.04025390625000896 +1.974375 -0.019287109375 0.04025390625000896 +1.9745 -0.01922607421875 0.04025390625000896 +1.974625 -0.01922607421875 0.04025390625000896 +1.97475 -0.0191650390625 0.04025390625000896 +1.974875 -0.01910400390625 0.04025390625000896 +1.975 -0.01910400390625 0.04025390625000896 +1.975125 -0.01904296875 0.04025390625000896 +1.97525 -0.01904296875 0.04025390625000896 +1.975375 -0.01898193359375 0.04025390625000896 +1.9755 -0.0189208984375 0.04025390625000896 +1.975625 -0.0189208984375 0.04025390625000896 +1.97575 -0.018829345703125 0.04025390625000896 +1.975875 -0.018829345703125 0.04025390625000896 +1.976 -0.018768310546875 0.04025390625000896 +1.976125 -0.0186767578125 0.04025390625000896 +1.97625 -0.0186767578125 0.04025390625000896 +1.976375 -0.01861572265625 0.04025390625000896 +1.9765 -0.01861572265625 0.04025390625000896 +1.976625 -0.018524169921875 0.04025390625000896 +1.97675 -0.0184326171875 0.04025390625000896 +1.976875 -0.0184326171875 0.04025390625000896 +1.977 -0.01837158203125 0.04025390625000896 +1.977125 -0.01837158203125 0.04025390625000896 +1.97725 -0.018280029296875 0.04025390625000896 +1.977375 -0.0181884765625 0.04025390625000896 +1.9775 -0.0181884765625 0.04025390625000896 +1.977625 -0.018096923828125 0.04025390625000896 +1.97775 -0.018096923828125 0.04025390625000896 +1.977875 -0.01800537109375 0.04025390625000896 +1.978 -0.017913818359375 0.04025390625000896 +1.978125 -0.017913818359375 0.04025390625000896 +1.97825 -0.017791748046875 0.04025390625000896 +1.978375 -0.017791748046875 0.04025390625000896 +1.9785 -0.0177001953125 0.04025390625000896 +1.978625 -0.017608642578125 0.04025390625000896 +1.97875 -0.017608642578125 0.04025390625000896 +1.978875 -0.01751708984375 0.04025390625000896 +1.979 -0.01751708984375 0.04025390625000896 +1.979125 -0.01739501953125 0.04025390625000896 +1.97925 -0.017303466796875 0.04025390625000896 +1.979375 -0.017303466796875 0.04025390625000896 +1.9795 -0.017181396484375 0.04025390625000896 +1.979625 -0.017181396484375 0.04025390625000896 +1.97975 -0.01708984375 0.04025390625000896 +1.979875 -0.0169677734375 0.04025390625000896 +1.98 -0.0169677734375 0.04025390625000896 +1.980125 -0.016845703125 0.04025390625000896 +1.98025 -0.016845703125 0.04025390625000896 +1.980375 -0.0167236328125 0.04025390625000896 +1.9805 -0.016632080078125 0.04025390625000896 +1.980625 -0.016632080078125 0.04025390625000896 +1.98075 -0.016510009765625 0.04025390625000896 +1.980875 -0.016510009765625 0.04025390625000896 +1.981 -0.016387939453125 0.04025390625000896 +1.981125 -0.016265869140625 0.04025390625000896 +1.98125 -0.016265869140625 0.04025390625000896 +1.981375 -0.016143798828125 0.04025390625000896 +1.9815 -0.016143798828125 0.04025390625000896 +1.981625 -0.0159912109375 0.04025390625000896 +1.98175 -0.015869140625 0.04025390625000896 +1.981875 -0.015869140625 0.04025390625000896 +1.982 -0.0157470703125 0.04025390625000896 +1.982125 -0.0157470703125 0.04025390625000896 +1.98225 -0.015625 0.04025390625000896 +1.982375 -0.015472412109375 0.04025390625000896 +1.9825 -0.015472412109375 0.04025390625000896 +1.982625 -0.015350341796875 0.04025390625000896 +1.98275 -0.015350341796875 0.04025390625000896 +1.982875 -0.01519775390625 0.04025390625000896 +1.983 -0.01507568359375 0.04025390625000896 +1.983125 -0.01507568359375 0.04025390625000896 +1.98325 -0.014923095703125 0.04025390625000896 +1.983375 -0.014923095703125 0.04025390625000896 +1.9835 -0.014801025390625 0.04025390625000896 +1.983625 -0.0146484375 0.04025390625000896 +1.98375 -0.0146484375 0.04025390625000896 +1.983875 -0.014495849609375 0.04025390625000896 +1.984 -0.129791259765625 0.3597460937500089 +1.984125 -0.12847900390625 0.3597460937500089 +1.98425 -0.127166748046875 0.3597460937500089 +1.984375 -0.127166748046875 0.3597460937500089 +1.9845 -0.125823974609375 0.3597460937500089 +1.984625 -0.125823974609375 0.3597460937500089 +1.98475 -0.12445068359375 0.3597460937500089 +1.984875 -0.12310791015625 0.3597460937500089 +1.985 -0.12310791015625 0.3597460937500089 +1.985125 -0.121734619140625 0.3597460937500089 +1.98525 -0.121734619140625 0.3597460937500089 +1.985375 -0.120330810546875 0.3597460937500089 +1.9855 -0.118927001953125 0.3597460937500089 +1.985625 -0.118927001953125 0.3597460937500089 +1.98575 -0.11749267578125 0.3597460937500089 +1.985875 -0.11749267578125 0.3597460937500089 +1.986 -0.116058349609375 0.3597460937500089 +1.986125 -0.1146240234375 0.3597460937500089 +1.98625 -0.1146240234375 0.3597460937500089 +1.986375 -0.1131591796875 0.3597460937500089 +1.9865 -0.1131591796875 0.3597460937500089 +1.986625 -0.1116943359375 0.3597460937500089 +1.98675 -0.1102294921875 0.3597460937500089 +1.986875 -0.1102294921875 0.3597460937500089 +1.987 -0.10870361328125 0.3597460937500089 +1.987125 -0.10870361328125 0.3597460937500089 +1.98725 -0.107208251953125 0.3597460937500089 +1.987375 -0.105682373046875 0.3597460937500089 +1.9875 -0.105682373046875 0.3597460937500089 +1.987625 -0.104156494140625 0.3597460937500089 +1.98775 -0.104156494140625 0.3597460937500089 +1.987875 -0.102630615234375 0.3597460937500089 +1.988 -0.10107421875 0.3597460937500089 +1.988125 -0.10107421875 0.3597460937500089 +1.98825 -0.099517822265625 0.3597460937500089 +1.988375 -0.099517822265625 0.3597460937500089 +1.9885 -0.097930908203125 0.3597460937500089 +1.988625 -0.096343994140625 0.3597460937500089 +1.98875 -0.096343994140625 0.3597460937500089 +1.988875 -0.094757080078125 0.3597460937500089 +1.989 -0.094757080078125 0.3597460937500089 +1.989125 -0.0931396484375 0.3597460937500089 +1.98925 -0.091522216796875 0.3597460937500089 +1.989375 -0.091522216796875 0.3597460937500089 +1.9895 -0.08990478515625 0.3597460937500089 +1.989625 -0.08990478515625 0.3597460937500089 +1.98975 -0.0882568359375 0.3597460937500089 +1.989875 -0.086639404296875 0.3597460937500089 +1.99 -0.086639404296875 0.3597460937500089 +1.990125 -0.0849609375 0.3597460937500089 +1.99025 -0.0849609375 0.3597460937500089 +1.990375 -0.08331298828125 0.3597460937500089 +1.9905 -0.081634521484375 0.3597460937500089 +1.990625 -0.081634521484375 0.3597460937500089 +1.99075 -0.0799560546875 0.3597460937500089 +1.990875 -0.0799560546875 0.3597460937500089 +1.991 -0.0782470703125 0.3597460937500089 +1.991125 -0.076568603515625 0.3597460937500089 +1.99125 -0.076568603515625 0.3597460937500089 +1.991375 -0.074859619140625 0.3597460937500089 +1.9915 -0.074859619140625 0.3597460937500089 +1.991625 -0.0731201171875 0.3597460937500089 +1.99175 -0.0714111328125 0.3597460937500089 +1.991875 -0.0714111328125 0.3597460937500089 +1.992 -0.069671630859375 0.3597460937500089 +1.992125 -0.069671630859375 0.3597460937500089 +1.99225 -0.06793212890625 0.3597460937500089 +1.992375 -0.066192626953125 0.3597460937500089 +1.9925 -0.066192626953125 0.3597460937500089 +1.992625 -0.064422607421875 0.3597460937500089 +1.99275 -0.064422607421875 0.3597460937500089 +1.992875 -0.06268310546875 0.3597460937500089 +1.993 -0.0609130859375 0.3597460937500089 +1.993125 -0.0609130859375 0.3597460937500089 +1.99325 -0.059112548828125 0.3597460937500089 +1.993375 -0.059112548828125 0.3597460937500089 +1.9935 -0.057342529296875 0.3597460937500089 +1.993625 -0.055572509765625 0.3597460937500089 +1.99375 -0.055572509765625 0.3597460937500089 +1.993875 -0.05377197265625 0.3597460937500089 +1.994 -0.05377197265625 0.3597460937500089 +1.994125 -0.051971435546875 0.3597460937500089 +1.99425 -0.0501708984375 0.3597460937500089 +1.994375 -0.0501708984375 0.3597460937500089 +1.9945 -0.04833984375 0.3597460937500089 +1.994625 -0.04833984375 0.3597460937500089 +1.99475 -0.046539306640625 0.3597460937500089 +1.994875 -0.044708251953125 0.3597460937500089 +1.995 -0.044708251953125 0.3597460937500089 +1.995125 -0.042877197265625 0.3597460937500089 +1.99525 -0.042877197265625 0.3597460937500089 +1.995375 -0.041046142578125 0.3597460937500089 +1.9955 -0.039215087890625 0.3597460937500089 +1.995625 -0.039215087890625 0.3597460937500089 +1.99575 -0.037384033203125 0.3597460937500089 +1.995875 -0.037384033203125 0.3597460937500089 +1.996 -0.0355224609375 0.3597460937500089 +1.996125 -0.03369140625 0.3597460937500089 +1.99625 -0.03369140625 0.3597460937500089 +1.996375 -0.031829833984375 0.3597460937500089 +1.9965 -0.031829833984375 0.3597460937500089 +1.996625 -0.02996826171875 0.3597460937500089 +1.99675 -0.028106689453125 0.3597460937500089 +1.996875 -0.028106689453125 0.3597460937500089 +1.997 -0.0262451171875 0.3597460937500089 +1.997125 -0.0262451171875 0.3597460937500089 +1.99725 -0.024383544921875 0.3597460937500089 +1.997375 -0.02252197265625 0.3597460937500089 +1.9975 -0.02252197265625 0.3597460937500089 +1.997625 -0.020660400390625 0.3597460937500089 +1.99775 -0.020660400390625 0.3597460937500089 +1.997875 -0.018798828125 0.3597460937500089 +1.998 -0.01690673828125 0.3597460937500089 +1.998125 -0.01690673828125 0.3597460937500089 +1.99825 -0.0150146484375 0.3597460937500089 +1.998375 -0.0150146484375 0.3597460937500089 +1.9985 -0.013153076171875 0.3597460937500089 +1.998625 -0.011260986328125 0.3597460937500089 +1.99875 -0.011260986328125 0.3597460937500089 +1.998875 -0.0093994140625 0.3597460937500089 +1.999 -0.0093994140625 0.3597460937500089 +1.999125 -0.00750732421875 0.3597460937500089 +1.99925 -0.005645751953125 0.3597460937500089 +1.999375 -0.005645751953125 0.3597460937500089 +1.9995 -0.003753662109375 0.3597460937500089 +1.999625 -0.003753662109375 0.3597460937500089 +1.99975 -0.001861572265625 0.3597460937500089 1.999875 0.0 0.3597460937500089 2.0 0.0 0.3597460937500089 2.000125 0.001861572265625 0.3597460937500089 diff --git a/tests/circuitpython/synth_note_bend.py.exp b/tests/circuitpython/synth_note_bend.py.exp index fda9787b38c58..e79811509e00d 100644 --- a/tests/circuitpython/synth_note_bend.py.exp +++ b/tests/circuitpython/synth_note_bend.py.exp @@ -208,188 +208,188 @@ 0.025875 0.01043701171875 -0.743977294921875 0.026 0.005218505859375 -0.743977294921875 0.026125 0.0 -0.743977294921875 -0.02625 -0.010467529296875 -0.743977294921875 -0.026375 -0.015716552734375 -0.743977294921875 -0.0265 -0.026153564453125 -0.743977294921875 -0.026625 -0.031402587890625 -0.743977294921875 -0.02675 -0.041839599609375 -0.743977294921875 -0.026875 -0.04705810546875 -0.743977294921875 -0.027 -0.052276611328125 -0.743977294921875 -0.027125 -0.062652587890625 -0.743977294921875 -0.02725 -0.067840576171875 -0.743977294921875 -0.027375 -0.078216552734375 -0.743977294921875 -0.0275 -0.0833740234375 -0.743977294921875 -0.027625 -0.09368896484375 -0.743977294921875 -0.02775 -0.09881591796875 -0.743977294921875 -0.027875 -0.10906982421875 -0.743977294921875 -0.028 -0.114166259765625 -0.743977294921875 -0.028125 -0.1192626953125 -0.743977294921875 -0.02825 -0.12939453125 -0.743977294921875 -0.028375 -0.13446044921875 -0.743977294921875 -0.02850000000000001 -0.144500732421875 -0.743977294921875 -0.028625 -0.149505615234375 -0.743977294921875 -0.02875 -0.15948486328125 -0.743977294921875 -0.028875 -0.1644287109375 -0.743977294921875 -0.029 -0.16937255859375 -0.743977294921875 -0.029125 -0.179168701171875 -0.743977294921875 -0.02925 -0.184051513671875 -0.743977294921875 -0.029375 -0.193756103515625 -0.743977294921875 -0.0295 -0.198577880859375 -0.743977294921875 -0.029625 -0.2081298828125 -0.743977294921875 -0.02975000000000001 -0.212890625 -0.743977294921875 -0.029875 -0.217620849609375 -0.743977294921875 -0.03 -0.22698974609375 -0.743977294921875 -0.030125 -0.23162841796875 -0.743977294921875 -0.03025 -0.240875244140625 -0.743977294921875 -0.030375 -0.245452880859375 -0.743977294921875 -0.0305 -0.254486083984375 -0.743977294921875 -0.030625 -0.259002685546875 -0.743977294921875 -0.03075 -0.263458251953125 -0.743977294921875 -0.03087499999999999 -0.272308349609375 -0.743977294921875 -0.031 -0.27667236328125 -0.743977294921875 -0.031125 -0.28533935546875 -0.743977294921875 -0.03125 -0.28961181640625 -0.743977294921875 -0.031375 -0.298095703125 -0.743977294921875 -0.0315 -0.302276611328125 -0.743977294921875 -0.03162500000000001 -0.310546875 -0.743977294921875 -0.03175 -0.31463623046875 -0.743977294921875 -0.031875 -0.318695068359375 -0.743977294921875 -0.032 -0.326690673828125 -0.487985107421875 -0.032125 -0.33453369140625 -0.487985107421875 -0.03225 -0.342254638671875 -0.487985107421875 -0.032375 -0.346038818359375 -0.487985107421875 -0.0325 -0.353515625 -0.487985107421875 -0.032625 -0.36083984375 -0.487985107421875 -0.03275 -0.364471435546875 -0.487985107421875 -0.032875 -0.371551513671875 -0.487985107421875 -0.033 -0.37847900390625 -0.487985107421875 -0.033125 -0.385223388671875 -0.487985107421875 -0.03325 -0.3885498046875 -0.487985107421875 -0.033375 -0.395050048828125 -0.487985107421875 -0.0335 -0.4013671875 -0.487985107421875 -0.03362500000000001 -0.40447998046875 -0.487985107421875 -0.03375 -0.410552978515625 -0.487985107421875 -0.033875 -0.41644287109375 -0.487985107421875 -0.034 -0.4193115234375 -0.487985107421875 -0.03412500000000001 -0.4249267578125 -0.487985107421875 -0.03425 -0.430328369140625 -0.487985107421875 -0.034375 -0.435577392578125 -0.487985107421875 -0.0345 -0.4381103515625 -0.487985107421875 -0.034625 -0.443084716796875 -0.487985107421875 -0.03475000000000001 -0.44781494140625 -0.487985107421875 -0.034875 -0.45013427734375 -0.487985107421875 -0.035 -0.45458984375 -0.487985107421875 -0.03512500000000001 -0.4588623046875 -0.487985107421875 -0.03525 -0.462921142578125 -0.487985107421875 -0.035375 -0.46484375 -0.487985107421875 -0.0355 -0.468597412109375 -0.487985107421875 -0.03562500000000001 -0.47216796875 -0.487985107421875 -0.03575 -0.473846435546875 -0.487985107421875 -0.035875 -0.477081298828125 -0.487985107421875 -0.03600000000000001 -0.4801025390625 -0.487985107421875 -0.036125 -0.482940673828125 -0.487985107421875 -0.03625 -0.4842529296875 -0.487985107421875 -0.036375 -0.48675537109375 -0.487985107421875 -0.0365 -0.489044189453125 -0.487985107421875 -0.036625 -0.4901123046875 -0.487985107421875 -0.03675 -0.4920654296875 -0.487985107421875 -0.036875 -0.493804931640625 -0.487985107421875 -0.037 -0.495330810546875 -0.487985107421875 -0.03712499999999999 -0.49603271484375 -0.487985107421875 -0.03725 -0.497222900390625 -0.487985107421875 -0.037375 -0.49822998046875 -0.487985107421875 -0.0375 -0.498626708984375 -0.487985107421875 -0.037625 -0.499298095703125 -0.487985107421875 -0.03775 -0.499725341796875 -0.487985107421875 -0.037875 -0.49993896484375 -0.487985107421875 -0.038 -0.499969482421875 -0.487985107421875 -0.038125 -0.499847412109375 -0.487985107421875 -0.03825 -0.499542236328125 -0.487985107421875 -0.038375 -0.499298095703125 -0.487985107421875 -0.0385 -0.498626708984375 -0.487985107421875 -0.038625 -0.49774169921875 -0.487985107421875 -0.03875 -0.49664306640625 -0.487985107421875 -0.038875 -0.49603271484375 -0.487985107421875 -0.039 -0.494598388671875 -0.487985107421875 -0.039125 -0.49298095703125 -0.487985107421875 -0.03925 -0.4920654296875 -0.487985107421875 -0.039375 -0.4901123046875 -0.487985107421875 -0.0395 -0.4879150390625 -0.487985107421875 -0.039625 -0.48553466796875 -0.487985107421875 -0.03975 -0.4842529296875 -0.487985107421875 -0.039875 -0.481536865234375 -0.487985107421875 -0.04 -0.4786376953125 -0.487985107421875 -0.040125 -0.477081298828125 -0.487985107421875 -0.04025 -0.473846435546875 -0.487985107421875 -0.040375 -0.47039794921875 -0.487985107421875 -0.04050000000000001 -0.468597412109375 -0.487985107421875 -0.040625 -0.46484375 -0.487985107421875 -0.04075 -0.460906982421875 -0.487985107421875 -0.040875 -0.456756591796875 -0.487985107421875 -0.04100000000000001 -0.45458984375 -0.487985107421875 -0.041125 -0.45013427734375 -0.487985107421875 -0.04125 -0.445465087890625 -0.487985107421875 -0.041375 -0.443084716796875 -0.487985107421875 -0.0415 -0.4381103515625 -0.487985107421875 -0.041625 -0.4329833984375 -0.487985107421875 -0.04175000000000001 -0.427642822265625 -0.487985107421875 -0.041875 -0.4249267578125 -0.487985107421875 -0.042 -0.4193115234375 -0.487985107421875 -0.042125 -0.41351318359375 -0.487985107421875 -0.04225000000000001 -0.410552978515625 -0.487985107421875 -0.042375 -0.40447998046875 -0.487985107421875 -0.0425 -0.398223876953125 -0.487985107421875 -0.042625 -0.391815185546875 -0.487985107421875 -0.04275 -0.3885498046875 -0.487985107421875 -0.04287500000000001 -0.381866455078125 -0.487985107421875 -0.04300000000000001 -0.375030517578125 -0.487985107421875 -0.043125 -0.371551513671875 -0.487985107421875 -0.04325 -0.364471435546875 -0.487985107421875 -0.043375 -0.357208251953125 -0.487985107421875 -0.04350000000000001 -0.34979248046875 -0.487985107421875 -0.04362500000000001 -0.346038818359375 -0.487985107421875 -0.04375000000000001 -0.338409423828125 -0.487985107421875 -0.043875 -0.33062744140625 -0.487985107421875 -0.04399999999999999 -0.326690673828125 -0.487985107421875 -0.044125 -0.318695068359375 -0.487985107421875 -0.04425 -0.310546875 -0.487985107421875 -0.044375 -0.302276611328125 -0.487985107421875 -0.04449999999999999 -0.298095703125 -0.487985107421875 -0.04462499999999999 -0.28961181640625 -0.487985107421875 -0.04475 -0.281005859375 -0.487985107421875 -0.044875 -0.27667236328125 -0.487985107421875 -0.045 -0.26788330078125 -0.487985107421875 -0.045125 -0.259002685546875 -0.487985107421875 -0.04525 -0.25 -0.487985107421875 -0.045375 -0.245452880859375 -0.487985107421875 -0.0455 -0.23626708984375 -0.487985107421875 -0.045625 -0.22698974609375 -0.487985107421875 -0.04575 -0.222320556640625 -0.487985107421875 -0.045875 -0.212890625 -0.487985107421875 -0.046 -0.203369140625 -0.487985107421875 -0.046125 -0.193756103515625 -0.487985107421875 -0.04625 -0.18890380859375 -0.487985107421875 -0.046375 -0.179168701171875 -0.487985107421875 -0.04649999999999999 -0.16937255859375 -0.487985107421875 -0.046625 -0.1644287109375 -0.487985107421875 -0.04675000000000001 -0.154510498046875 -0.487985107421875 -0.046875 -0.144500732421875 -0.487985107421875 -0.04699999999999999 -0.139495849609375 -0.487985107421875 -0.047125 -0.12939453125 -0.487985107421875 -0.04725000000000001 -0.1192626953125 -0.487985107421875 -0.047375 -0.10906982421875 -0.487985107421875 -0.0475 -0.10394287109375 -0.487985107421875 -0.047625 -0.09368896484375 -0.487985107421875 -0.04775 -0.0833740234375 -0.487985107421875 -0.047875 -0.078216552734375 -0.487985107421875 -0.048 -0.067840576171875 -0.487985107421875 -0.048125 -0.057464599609375 -0.487985107421875 -0.04825 -0.04705810546875 -0.487985107421875 -0.048375 -0.041839599609375 -0.487985107421875 -0.0485 -0.031402587890625 -0.487985107421875 -0.048625 -0.02093505859375 -0.487985107421875 -0.04875 -0.015716552734375 -0.487985107421875 -0.048875 -0.0052490234375 -0.487985107421875 +0.02625 -0.01043701171875 -0.743977294921875 +0.026375 -0.01568603515625 -0.743977294921875 +0.0265 -0.026123046875 -0.743977294921875 +0.026625 -0.0313720703125 -0.743977294921875 +0.02675 -0.04180908203125 -0.743977294921875 +0.026875 -0.047027587890625 -0.743977294921875 +0.027 -0.05224609375 -0.743977294921875 +0.027125 -0.0626220703125 -0.743977294921875 +0.02725 -0.06781005859375 -0.743977294921875 +0.027375 -0.07818603515625 -0.743977294921875 +0.0275 -0.083343505859375 -0.743977294921875 +0.027625 -0.093658447265625 -0.743977294921875 +0.02775 -0.098785400390625 -0.743977294921875 +0.027875 -0.109039306640625 -0.743977294921875 +0.028 -0.1141357421875 -0.743977294921875 +0.028125 -0.119232177734375 -0.743977294921875 +0.02825 -0.129364013671875 -0.743977294921875 +0.028375 -0.134429931640625 -0.743977294921875 +0.02850000000000001 -0.14447021484375 -0.743977294921875 +0.028625 -0.14947509765625 -0.743977294921875 +0.02875 -0.159454345703125 -0.743977294921875 +0.028875 -0.164398193359375 -0.743977294921875 +0.029 -0.169342041015625 -0.743977294921875 +0.029125 -0.17913818359375 -0.743977294921875 +0.02925 -0.18402099609375 -0.743977294921875 +0.029375 -0.1937255859375 -0.743977294921875 +0.0295 -0.19854736328125 -0.743977294921875 +0.029625 -0.208099365234375 -0.743977294921875 +0.02975000000000001 -0.212860107421875 -0.743977294921875 +0.029875 -0.21759033203125 -0.743977294921875 +0.03 -0.226959228515625 -0.743977294921875 +0.030125 -0.231597900390625 -0.743977294921875 +0.03025 -0.2408447265625 -0.743977294921875 +0.030375 -0.24542236328125 -0.743977294921875 +0.0305 -0.25445556640625 -0.743977294921875 +0.030625 -0.25897216796875 -0.743977294921875 +0.03075 -0.263427734375 -0.743977294921875 +0.03087499999999999 -0.27227783203125 -0.743977294921875 +0.031 -0.276641845703125 -0.743977294921875 +0.031125 -0.285308837890625 -0.743977294921875 +0.03125 -0.289581298828125 -0.743977294921875 +0.031375 -0.298065185546875 -0.743977294921875 +0.0315 -0.30224609375 -0.743977294921875 +0.03162500000000001 -0.310516357421875 -0.743977294921875 +0.03175 -0.314605712890625 -0.743977294921875 +0.031875 -0.31866455078125 -0.743977294921875 +0.032 -0.32666015625 -0.487985107421875 +0.032125 -0.334503173828125 -0.487985107421875 +0.03225 -0.34222412109375 -0.487985107421875 +0.032375 -0.34600830078125 -0.487985107421875 +0.0325 -0.353485107421875 -0.487985107421875 +0.032625 -0.360809326171875 -0.487985107421875 +0.03275 -0.36444091796875 -0.487985107421875 +0.032875 -0.37152099609375 -0.487985107421875 +0.033 -0.378448486328125 -0.487985107421875 +0.033125 -0.38519287109375 -0.487985107421875 +0.03325 -0.388519287109375 -0.487985107421875 +0.033375 -0.39501953125 -0.487985107421875 +0.0335 -0.401336669921875 -0.487985107421875 +0.03362500000000001 -0.404449462890625 -0.487985107421875 +0.03375 -0.4105224609375 -0.487985107421875 +0.033875 -0.416412353515625 -0.487985107421875 +0.034 -0.419281005859375 -0.487985107421875 +0.03412500000000001 -0.424896240234375 -0.487985107421875 +0.03425 -0.4302978515625 -0.487985107421875 +0.034375 -0.435546875 -0.487985107421875 +0.0345 -0.438079833984375 -0.487985107421875 +0.034625 -0.44305419921875 -0.487985107421875 +0.03475000000000001 -0.447784423828125 -0.487985107421875 +0.034875 -0.450103759765625 -0.487985107421875 +0.035 -0.454559326171875 -0.487985107421875 +0.03512500000000001 -0.458831787109375 -0.487985107421875 +0.03525 -0.462890625 -0.487985107421875 +0.035375 -0.464813232421875 -0.487985107421875 +0.0355 -0.46856689453125 -0.487985107421875 +0.03562500000000001 -0.472137451171875 -0.487985107421875 +0.03575 -0.47381591796875 -0.487985107421875 +0.035875 -0.47705078125 -0.487985107421875 +0.03600000000000001 -0.480072021484375 -0.487985107421875 +0.036125 -0.48291015625 -0.487985107421875 +0.03625 -0.484222412109375 -0.487985107421875 +0.036375 -0.486724853515625 -0.487985107421875 +0.0365 -0.489013671875 -0.487985107421875 +0.036625 -0.490081787109375 -0.487985107421875 +0.03675 -0.492034912109375 -0.487985107421875 +0.036875 -0.4937744140625 -0.487985107421875 +0.037 -0.49530029296875 -0.487985107421875 +0.03712499999999999 -0.496002197265625 -0.487985107421875 +0.03725 -0.4971923828125 -0.487985107421875 +0.037375 -0.498199462890625 -0.487985107421875 +0.0375 -0.49859619140625 -0.487985107421875 +0.037625 -0.499267578125 -0.487985107421875 +0.03775 -0.49969482421875 -0.487985107421875 +0.037875 -0.499908447265625 -0.487985107421875 +0.038 -0.49993896484375 -0.487985107421875 +0.038125 -0.49981689453125 -0.487985107421875 +0.03825 -0.49951171875 -0.487985107421875 +0.038375 -0.499267578125 -0.487985107421875 +0.0385 -0.49859619140625 -0.487985107421875 +0.038625 -0.497711181640625 -0.487985107421875 +0.03875 -0.496612548828125 -0.487985107421875 +0.038875 -0.496002197265625 -0.487985107421875 +0.039 -0.49456787109375 -0.487985107421875 +0.039125 -0.492950439453125 -0.487985107421875 +0.03925 -0.492034912109375 -0.487985107421875 +0.039375 -0.490081787109375 -0.487985107421875 +0.0395 -0.487884521484375 -0.487985107421875 +0.039625 -0.485504150390625 -0.487985107421875 +0.03975 -0.484222412109375 -0.487985107421875 +0.039875 -0.48150634765625 -0.487985107421875 +0.04 -0.478607177734375 -0.487985107421875 +0.040125 -0.47705078125 -0.487985107421875 +0.04025 -0.47381591796875 -0.487985107421875 +0.040375 -0.470367431640625 -0.487985107421875 +0.04050000000000001 -0.46856689453125 -0.487985107421875 +0.040625 -0.464813232421875 -0.487985107421875 +0.04075 -0.46087646484375 -0.487985107421875 +0.040875 -0.45672607421875 -0.487985107421875 +0.04100000000000001 -0.454559326171875 -0.487985107421875 +0.041125 -0.450103759765625 -0.487985107421875 +0.04125 -0.4454345703125 -0.487985107421875 +0.041375 -0.44305419921875 -0.487985107421875 +0.0415 -0.438079833984375 -0.487985107421875 +0.041625 -0.432952880859375 -0.487985107421875 +0.04175000000000001 -0.4276123046875 -0.487985107421875 +0.041875 -0.424896240234375 -0.487985107421875 +0.042 -0.419281005859375 -0.487985107421875 +0.042125 -0.413482666015625 -0.487985107421875 +0.04225000000000001 -0.4105224609375 -0.487985107421875 +0.042375 -0.404449462890625 -0.487985107421875 +0.0425 -0.398193359375 -0.487985107421875 +0.042625 -0.39178466796875 -0.487985107421875 +0.04275 -0.388519287109375 -0.487985107421875 +0.04287500000000001 -0.3818359375 -0.487985107421875 +0.04300000000000001 -0.375 -0.487985107421875 +0.043125 -0.37152099609375 -0.487985107421875 +0.04325 -0.36444091796875 -0.487985107421875 +0.043375 -0.357177734375 -0.487985107421875 +0.04350000000000001 -0.349761962890625 -0.487985107421875 +0.04362500000000001 -0.34600830078125 -0.487985107421875 +0.04375000000000001 -0.33837890625 -0.487985107421875 +0.043875 -0.330596923828125 -0.487985107421875 +0.04399999999999999 -0.32666015625 -0.487985107421875 +0.044125 -0.31866455078125 -0.487985107421875 +0.04425 -0.310516357421875 -0.487985107421875 +0.044375 -0.30224609375 -0.487985107421875 +0.04449999999999999 -0.298065185546875 -0.487985107421875 +0.04462499999999999 -0.289581298828125 -0.487985107421875 +0.04475 -0.280975341796875 -0.487985107421875 +0.044875 -0.276641845703125 -0.487985107421875 +0.045 -0.267852783203125 -0.487985107421875 +0.045125 -0.25897216796875 -0.487985107421875 +0.04525 -0.249969482421875 -0.487985107421875 +0.045375 -0.24542236328125 -0.487985107421875 +0.0455 -0.236236572265625 -0.487985107421875 +0.045625 -0.226959228515625 -0.487985107421875 +0.04575 -0.2222900390625 -0.487985107421875 +0.045875 -0.212860107421875 -0.487985107421875 +0.046 -0.203338623046875 -0.487985107421875 +0.046125 -0.1937255859375 -0.487985107421875 +0.04625 -0.188873291015625 -0.487985107421875 +0.046375 -0.17913818359375 -0.487985107421875 +0.04649999999999999 -0.169342041015625 -0.487985107421875 +0.046625 -0.164398193359375 -0.487985107421875 +0.04675000000000001 -0.15447998046875 -0.487985107421875 +0.046875 -0.14447021484375 -0.487985107421875 +0.04699999999999999 -0.13946533203125 -0.487985107421875 +0.047125 -0.129364013671875 -0.487985107421875 +0.04725000000000001 -0.119232177734375 -0.487985107421875 +0.047375 -0.109039306640625 -0.487985107421875 +0.0475 -0.103912353515625 -0.487985107421875 +0.047625 -0.093658447265625 -0.487985107421875 +0.04775 -0.083343505859375 -0.487985107421875 +0.047875 -0.07818603515625 -0.487985107421875 +0.048 -0.06781005859375 -0.487985107421875 +0.048125 -0.05743408203125 -0.487985107421875 +0.04825 -0.047027587890625 -0.487985107421875 +0.048375 -0.04180908203125 -0.487985107421875 +0.0485 -0.0313720703125 -0.487985107421875 +0.048625 -0.020904541015625 -0.487985107421875 +0.04875 -0.01568603515625 -0.487985107421875 +0.048875 -0.005218505859375 -0.487985107421875 0.049 0.005218505859375 -0.487985107421875 0.04912500000000001 0.01568603515625 -0.487985107421875 0.04925000000000001 0.020904541015625 -0.487985107421875 @@ -556,153 +556,153 @@ 0.06937500000000001 0.0313720703125 -0.2319929199218749 0.06950000000000001 0.01568603515625 -0.2319929199218749 0.069625 0.005218505859375 -0.2319929199218749 -0.06975 -0.0052490234375 -0.2319929199218749 -0.06987500000000001 -0.015716552734375 -0.2319929199218749 -0.07000000000000001 -0.026153564453125 -0.2319929199218749 -0.070125 -0.03662109375 -0.2319929199218749 -0.07025000000000001 -0.04705810546875 -0.2319929199218749 -0.07037500000000001 -0.057464599609375 -0.2319929199218749 -0.07050000000000001 -0.067840576171875 -0.2319929199218749 -0.070625 -0.078216552734375 -0.2319929199218749 -0.07075 -0.088531494140625 -0.2319929199218749 -0.07087500000000001 -0.09881591796875 -0.2319929199218749 -0.07100000000000001 -0.10906982421875 -0.2319929199218749 -0.07112500000000001 -0.1192626953125 -0.2319929199218749 -0.07125000000000002 -0.12939453125 -0.2319929199218749 -0.07137500000000001 -0.139495849609375 -0.2319929199218749 -0.0715 -0.149505615234375 -0.2319929199218749 -0.07162500000000001 -0.15948486328125 -0.2319929199218749 -0.07175000000000001 -0.16937255859375 -0.2319929199218749 -0.07187500000000001 -0.179168701171875 -0.2319929199218749 -0.07200000000000001 -0.18890380859375 -0.2319929199218749 -0.07212499999999999 -0.198577880859375 -0.2319929199218749 -0.07225 -0.212890625 -0.2319929199218749 -0.07237499999999999 -0.222320556640625 -0.2319929199218749 -0.0725 -0.23162841796875 -0.2319929199218749 -0.07262499999999999 -0.240875244140625 -0.2319929199218749 -0.07274999999999999 -0.25 -0.2319929199218749 -0.072875 -0.259002685546875 -0.2319929199218749 -0.073 -0.26788330078125 -0.2319929199218749 -0.073125 -0.27667236328125 -0.2319929199218749 -0.07324999999999999 -0.28533935546875 -0.2319929199218749 -0.07337499999999999 -0.293853759765625 -0.2319929199218749 -0.0735 -0.302276611328125 -0.2319929199218749 -0.073625 -0.310546875 -0.2319929199218749 -0.07374999999999999 -0.318695068359375 -0.2319929199218749 -0.073875 -0.326690673828125 -0.2319929199218749 -0.074 -0.33453369140625 -0.2319929199218749 -0.074125 -0.342254638671875 -0.2319929199218749 -0.07424999999999999 -0.34979248046875 -0.2319929199218749 -0.07437499999999999 -0.357208251953125 -0.2319929199218749 -0.0745 -0.364471435546875 -0.2319929199218749 -0.07462499999999999 -0.371551513671875 -0.2319929199218749 -0.07475 -0.37847900390625 -0.2319929199218749 -0.07487500000000001 -0.385223388671875 -0.2319929199218749 -0.075 -0.391815185546875 -0.2319929199218749 -0.07512499999999999 -0.4013671875 -0.2319929199218749 -0.07524999999999999 -0.40753173828125 -0.2319929199218749 -0.075375 -0.41351318359375 -0.2319929199218749 -0.0755 -0.4193115234375 -0.2319929199218749 -0.075625 -0.4249267578125 -0.2319929199218749 -0.07574999999999999 -0.430328369140625 -0.2319929199218749 -0.075875 -0.435577392578125 -0.2319929199218749 -0.076 -0.44061279296875 -0.2319929199218749 -0.076125 -0.445465087890625 -0.2319929199218749 -0.07625 -0.45013427734375 -0.2319929199218749 -0.07637499999999999 -0.45458984375 -0.2319929199218749 -0.0765 -0.4588623046875 -0.2319929199218749 -0.076625 -0.462921142578125 -0.2319929199218749 -0.07675 -0.466766357421875 -0.2319929199218749 -0.076875 -0.47039794921875 -0.2319929199218749 -0.077 -0.473846435546875 -0.2319929199218749 -0.077125 -0.477081298828125 -0.2319929199218749 -0.07725 -0.4801025390625 -0.2319929199218749 -0.07737499999999999 -0.482940673828125 -0.2319929199218749 -0.0775 -0.48553466796875 -0.2319929199218749 -0.077625 -0.4879150390625 -0.2319929199218749 -0.07774999999999999 -0.4901123046875 -0.2319929199218749 -0.07787500000000001 -0.4920654296875 -0.2319929199218749 -0.07800000000000001 -0.494598388671875 -0.2319929199218749 -0.078125 -0.49603271484375 -0.2319929199218749 -0.07824999999999999 -0.497222900390625 -0.2319929199218749 -0.07837499999999999 -0.49822998046875 -0.2319929199218749 -0.07850000000000001 -0.498992919921875 -0.2319929199218749 -0.078625 -0.499542236328125 -0.2319929199218749 -0.07875 -0.499847412109375 -0.2319929199218749 -0.07887500000000001 -0.499969482421875 -0.2319929199218749 -0.079 -0.499847412109375 -0.2319929199218749 -0.079125 -0.499542236328125 -0.2319929199218749 -0.07925 -0.498992919921875 -0.2319929199218749 -0.079375 -0.49822998046875 -0.2319929199218749 -0.0795 -0.497222900390625 -0.2319929199218749 -0.079625 -0.49603271484375 -0.2319929199218749 -0.07975 -0.494598388671875 -0.2319929199218749 -0.07987500000000001 -0.49298095703125 -0.2319929199218749 -0.08 -0.491119384765625 -0.2319929199218749 -0.08012499999999999 -0.489044189453125 -0.2319929199218749 -0.08025 -0.48675537109375 -0.2319929199218749 -0.080375 -0.4842529296875 -0.2319929199218749 -0.08050000000000001 -0.481536865234375 -0.2319929199218749 -0.080625 -0.4786376953125 -0.2319929199218749 -0.08074999999999999 -0.473846435546875 -0.2319929199218749 -0.080875 -0.47039794921875 -0.2319929199218749 -0.08100000000000001 -0.466766357421875 -0.2319929199218749 -0.08112500000000001 -0.462921142578125 -0.2319929199218749 -0.08125 -0.4588623046875 -0.2319929199218749 -0.08137499999999999 -0.45458984375 -0.2319929199218749 -0.0815 -0.45013427734375 -0.2319929199218749 -0.081625 -0.445465087890625 -0.2319929199218749 -0.08175000000000001 -0.44061279296875 -0.2319929199218749 -0.081875 -0.435577392578125 -0.2319929199218749 -0.08200000000000001 -0.430328369140625 -0.2319929199218749 -0.082125 -0.4249267578125 -0.2319929199218749 -0.08225 -0.4193115234375 -0.2319929199218749 -0.08237500000000001 -0.41351318359375 -0.2319929199218749 -0.0825 -0.40753173828125 -0.2319929199218749 -0.08262500000000001 -0.4013671875 -0.2319929199218749 -0.08275 -0.395050048828125 -0.2319929199218749 -0.08287500000000001 -0.3885498046875 -0.2319929199218749 -0.08300000000000001 -0.381866455078125 -0.2319929199218749 -0.083125 -0.375030517578125 -0.2319929199218749 -0.08324999999999999 -0.368011474609375 -0.2319929199218749 -0.083375 -0.36083984375 -0.2319929199218749 -0.08350000000000001 -0.353515625 -0.2319929199218749 -0.08362500000000001 -0.342254638671875 -0.2319929199218749 -0.08375 -0.33453369140625 -0.2319929199218749 -0.08387500000000001 -0.326690673828125 -0.2319929199218749 -0.084 -0.318695068359375 -0.2319929199218749 -0.08412500000000001 -0.310546875 -0.2319929199218749 -0.08425000000000001 -0.302276611328125 -0.2319929199218749 -0.084375 -0.293853759765625 -0.2319929199218749 -0.08450000000000001 -0.28533935546875 -0.2319929199218749 -0.084625 -0.27667236328125 -0.2319929199218749 -0.08475 -0.26788330078125 -0.2319929199218749 -0.08487500000000001 -0.259002685546875 -0.2319929199218749 -0.085 -0.25 -0.2319929199218749 -0.08512500000000001 -0.240875244140625 -0.2319929199218749 -0.08525 -0.23162841796875 -0.2319929199218749 -0.085375 -0.222320556640625 -0.2319929199218749 -0.08550000000000001 -0.212890625 -0.2319929199218749 -0.085625 -0.203369140625 -0.2319929199218749 -0.08575000000000001 -0.193756103515625 -0.2319929199218749 -0.08587500000000002 -0.184051513671875 -0.2319929199218749 -0.08600000000000001 -0.174285888671875 -0.2319929199218749 -0.08612500000000001 -0.1644287109375 -0.2319929199218749 -0.08625 -0.154510498046875 -0.2319929199218749 -0.08637499999999999 -0.144500732421875 -0.2319929199218749 -0.0865 -0.12939453125 -0.2319929199218749 -0.08662500000000001 -0.1192626953125 -0.2319929199218749 -0.08675000000000001 -0.10906982421875 -0.2319929199218749 -0.08687500000000002 -0.09881591796875 -0.2319929199218749 -0.08700000000000001 -0.088531494140625 -0.2319929199218749 -0.087125 -0.078216552734375 -0.2319929199218749 -0.08725000000000001 -0.067840576171875 -0.2319929199218749 -0.08737500000000001 -0.057464599609375 -0.2319929199218749 -0.08750000000000002 -0.04705810546875 -0.2319929199218749 -0.08762500000000001 -0.03662109375 -0.2319929199218749 -0.08775 -0.026153564453125 -0.2319929199218749 -0.08787500000000001 -0.015716552734375 -0.2319929199218749 -0.08799999999999999 -0.0052490234375 -0.2319929199218749 +0.06975 -0.005218505859375 -0.2319929199218749 +0.06987500000000001 -0.01568603515625 -0.2319929199218749 +0.07000000000000001 -0.026123046875 -0.2319929199218749 +0.070125 -0.036590576171875 -0.2319929199218749 +0.07025000000000001 -0.047027587890625 -0.2319929199218749 +0.07037500000000001 -0.05743408203125 -0.2319929199218749 +0.07050000000000001 -0.06781005859375 -0.2319929199218749 +0.070625 -0.07818603515625 -0.2319929199218749 +0.07075 -0.0885009765625 -0.2319929199218749 +0.07087500000000001 -0.098785400390625 -0.2319929199218749 +0.07100000000000001 -0.109039306640625 -0.2319929199218749 +0.07112500000000001 -0.119232177734375 -0.2319929199218749 +0.07125000000000002 -0.129364013671875 -0.2319929199218749 +0.07137500000000001 -0.13946533203125 -0.2319929199218749 +0.0715 -0.14947509765625 -0.2319929199218749 +0.07162500000000001 -0.159454345703125 -0.2319929199218749 +0.07175000000000001 -0.169342041015625 -0.2319929199218749 +0.07187500000000001 -0.17913818359375 -0.2319929199218749 +0.07200000000000001 -0.188873291015625 -0.2319929199218749 +0.07212499999999999 -0.19854736328125 -0.2319929199218749 +0.07225 -0.212860107421875 -0.2319929199218749 +0.07237499999999999 -0.2222900390625 -0.2319929199218749 +0.0725 -0.231597900390625 -0.2319929199218749 +0.07262499999999999 -0.2408447265625 -0.2319929199218749 +0.07274999999999999 -0.249969482421875 -0.2319929199218749 +0.072875 -0.25897216796875 -0.2319929199218749 +0.073 -0.267852783203125 -0.2319929199218749 +0.073125 -0.276641845703125 -0.2319929199218749 +0.07324999999999999 -0.285308837890625 -0.2319929199218749 +0.07337499999999999 -0.2938232421875 -0.2319929199218749 +0.0735 -0.30224609375 -0.2319929199218749 +0.073625 -0.310516357421875 -0.2319929199218749 +0.07374999999999999 -0.31866455078125 -0.2319929199218749 +0.073875 -0.32666015625 -0.2319929199218749 +0.074 -0.334503173828125 -0.2319929199218749 +0.074125 -0.34222412109375 -0.2319929199218749 +0.07424999999999999 -0.349761962890625 -0.2319929199218749 +0.07437499999999999 -0.357177734375 -0.2319929199218749 +0.0745 -0.36444091796875 -0.2319929199218749 +0.07462499999999999 -0.37152099609375 -0.2319929199218749 +0.07475 -0.378448486328125 -0.2319929199218749 +0.07487500000000001 -0.38519287109375 -0.2319929199218749 +0.075 -0.39178466796875 -0.2319929199218749 +0.07512499999999999 -0.401336669921875 -0.2319929199218749 +0.07524999999999999 -0.407501220703125 -0.2319929199218749 +0.075375 -0.413482666015625 -0.2319929199218749 +0.0755 -0.419281005859375 -0.2319929199218749 +0.075625 -0.424896240234375 -0.2319929199218749 +0.07574999999999999 -0.4302978515625 -0.2319929199218749 +0.075875 -0.435546875 -0.2319929199218749 +0.076 -0.440582275390625 -0.2319929199218749 +0.076125 -0.4454345703125 -0.2319929199218749 +0.07625 -0.450103759765625 -0.2319929199218749 +0.07637499999999999 -0.454559326171875 -0.2319929199218749 +0.0765 -0.458831787109375 -0.2319929199218749 +0.076625 -0.462890625 -0.2319929199218749 +0.07675 -0.46673583984375 -0.2319929199218749 +0.076875 -0.470367431640625 -0.2319929199218749 +0.077 -0.47381591796875 -0.2319929199218749 +0.077125 -0.47705078125 -0.2319929199218749 +0.07725 -0.480072021484375 -0.2319929199218749 +0.07737499999999999 -0.48291015625 -0.2319929199218749 +0.0775 -0.485504150390625 -0.2319929199218749 +0.077625 -0.487884521484375 -0.2319929199218749 +0.07774999999999999 -0.490081787109375 -0.2319929199218749 +0.07787500000000001 -0.492034912109375 -0.2319929199218749 +0.07800000000000001 -0.49456787109375 -0.2319929199218749 +0.078125 -0.496002197265625 -0.2319929199218749 +0.07824999999999999 -0.4971923828125 -0.2319929199218749 +0.07837499999999999 -0.498199462890625 -0.2319929199218749 +0.07850000000000001 -0.49896240234375 -0.2319929199218749 +0.078625 -0.49951171875 -0.2319929199218749 +0.07875 -0.49981689453125 -0.2319929199218749 +0.07887500000000001 -0.49993896484375 -0.2319929199218749 +0.079 -0.49981689453125 -0.2319929199218749 +0.079125 -0.49951171875 -0.2319929199218749 +0.07925 -0.49896240234375 -0.2319929199218749 +0.079375 -0.498199462890625 -0.2319929199218749 +0.0795 -0.4971923828125 -0.2319929199218749 +0.079625 -0.496002197265625 -0.2319929199218749 +0.07975 -0.49456787109375 -0.2319929199218749 +0.07987500000000001 -0.492950439453125 -0.2319929199218749 +0.08 -0.4910888671875 -0.2319929199218749 +0.08012499999999999 -0.489013671875 -0.2319929199218749 +0.08025 -0.486724853515625 -0.2319929199218749 +0.080375 -0.484222412109375 -0.2319929199218749 +0.08050000000000001 -0.48150634765625 -0.2319929199218749 +0.080625 -0.478607177734375 -0.2319929199218749 +0.08074999999999999 -0.47381591796875 -0.2319929199218749 +0.080875 -0.470367431640625 -0.2319929199218749 +0.08100000000000001 -0.46673583984375 -0.2319929199218749 +0.08112500000000001 -0.462890625 -0.2319929199218749 +0.08125 -0.458831787109375 -0.2319929199218749 +0.08137499999999999 -0.454559326171875 -0.2319929199218749 +0.0815 -0.450103759765625 -0.2319929199218749 +0.081625 -0.4454345703125 -0.2319929199218749 +0.08175000000000001 -0.440582275390625 -0.2319929199218749 +0.081875 -0.435546875 -0.2319929199218749 +0.08200000000000001 -0.4302978515625 -0.2319929199218749 +0.082125 -0.424896240234375 -0.2319929199218749 +0.08225 -0.419281005859375 -0.2319929199218749 +0.08237500000000001 -0.413482666015625 -0.2319929199218749 +0.0825 -0.407501220703125 -0.2319929199218749 +0.08262500000000001 -0.401336669921875 -0.2319929199218749 +0.08275 -0.39501953125 -0.2319929199218749 +0.08287500000000001 -0.388519287109375 -0.2319929199218749 +0.08300000000000001 -0.3818359375 -0.2319929199218749 +0.083125 -0.375 -0.2319929199218749 +0.08324999999999999 -0.36798095703125 -0.2319929199218749 +0.083375 -0.360809326171875 -0.2319929199218749 +0.08350000000000001 -0.353485107421875 -0.2319929199218749 +0.08362500000000001 -0.34222412109375 -0.2319929199218749 +0.08375 -0.334503173828125 -0.2319929199218749 +0.08387500000000001 -0.32666015625 -0.2319929199218749 +0.084 -0.31866455078125 -0.2319929199218749 +0.08412500000000001 -0.310516357421875 -0.2319929199218749 +0.08425000000000001 -0.30224609375 -0.2319929199218749 +0.084375 -0.2938232421875 -0.2319929199218749 +0.08450000000000001 -0.285308837890625 -0.2319929199218749 +0.084625 -0.276641845703125 -0.2319929199218749 +0.08475 -0.267852783203125 -0.2319929199218749 +0.08487500000000001 -0.25897216796875 -0.2319929199218749 +0.085 -0.249969482421875 -0.2319929199218749 +0.08512500000000001 -0.2408447265625 -0.2319929199218749 +0.08525 -0.231597900390625 -0.2319929199218749 +0.085375 -0.2222900390625 -0.2319929199218749 +0.08550000000000001 -0.212860107421875 -0.2319929199218749 +0.085625 -0.203338623046875 -0.2319929199218749 +0.08575000000000001 -0.1937255859375 -0.2319929199218749 +0.08587500000000002 -0.18402099609375 -0.2319929199218749 +0.08600000000000001 -0.17425537109375 -0.2319929199218749 +0.08612500000000001 -0.164398193359375 -0.2319929199218749 +0.08625 -0.15447998046875 -0.2319929199218749 +0.08637499999999999 -0.14447021484375 -0.2319929199218749 +0.0865 -0.129364013671875 -0.2319929199218749 +0.08662500000000001 -0.119232177734375 -0.2319929199218749 +0.08675000000000001 -0.109039306640625 -0.2319929199218749 +0.08687500000000002 -0.098785400390625 -0.2319929199218749 +0.08700000000000001 -0.0885009765625 -0.2319929199218749 +0.087125 -0.07818603515625 -0.2319929199218749 +0.08725000000000001 -0.06781005859375 -0.2319929199218749 +0.08737500000000001 -0.05743408203125 -0.2319929199218749 +0.08750000000000002 -0.047027587890625 -0.2319929199218749 +0.08762500000000001 -0.036590576171875 -0.2319929199218749 +0.08775 -0.026123046875 -0.2319929199218749 +0.08787500000000001 -0.01568603515625 -0.2319929199218749 +0.08799999999999999 -0.005218505859375 -0.2319929199218749 0.088125 0.005218505859375 -0.2319929199218749 0.08824999999999999 0.01568603515625 -0.2319929199218749 0.08837499999999999 0.026123046875 -0.2319929199218749 @@ -836,129 +836,129 @@ 0.104375 0.0313720703125 0.02399926757812504 0.1045 0.020904541015625 0.02399926757812504 0.104625 0.005218505859375 0.02399926757812504 -0.10475 -0.0052490234375 0.02399926757812504 -0.104875 -0.02093505859375 0.02399926757812504 -0.105 -0.031402587890625 0.02399926757812504 -0.105125 -0.041839599609375 0.02399926757812504 -0.10525 -0.057464599609375 0.02399926757812504 -0.105375 -0.067840576171875 0.02399926757812504 -0.1055 -0.0833740234375 0.02399926757812504 -0.105625 -0.09368896484375 0.02399926757812504 -0.10575 -0.10906982421875 0.02399926757812504 -0.105875 -0.1192626953125 0.02399926757812504 -0.106 -0.13446044921875 0.02399926757812504 -0.106125 -0.144500732421875 0.02399926757812504 -0.10625 -0.154510498046875 0.02399926757812504 -0.106375 -0.16937255859375 0.02399926757812504 -0.1065 -0.179168701171875 0.02399926757812504 -0.106625 -0.193756103515625 0.02399926757812504 -0.10675 -0.203369140625 0.02399926757812504 -0.106875 -0.217620849609375 0.02399926757812504 -0.107 -0.22698974609375 0.02399926757812504 -0.107125 -0.240875244140625 0.02399926757812504 -0.10725 -0.25 0.02399926757812504 -0.107375 -0.259002685546875 0.02399926757812504 -0.1075 -0.272308349609375 0.02399926757812504 -0.107625 -0.281005859375 0.02399926757812504 -0.10775 -0.293853759765625 0.02399926757812504 -0.107875 -0.302276611328125 0.02399926757812504 -0.108 -0.31463623046875 0.02399926757812504 -0.108125 -0.32269287109375 0.02399926757812504 -0.10825 -0.33062744140625 0.02399926757812504 -0.108375 -0.342254638671875 0.02399926757812504 -0.1085 -0.34979248046875 0.02399926757812504 -0.108625 -0.36083984375 0.02399926757812504 -0.10875 -0.368011474609375 0.02399926757812504 -0.108875 -0.37847900390625 0.02399926757812504 -0.109 -0.385223388671875 0.02399926757812504 -0.109125 -0.395050048828125 0.02399926757812504 -0.10925 -0.4013671875 0.02399926757812504 -0.109375 -0.40753173828125 0.02399926757812504 -0.1095 -0.41644287109375 0.02399926757812504 -0.109625 -0.422149658203125 0.02399926757812504 -0.10975 -0.430328369140625 0.02399926757812504 -0.109875 -0.435577392578125 0.02399926757812504 -0.11 -0.443084716796875 0.02399926757812504 -0.110125 -0.44781494140625 0.02399926757812504 -0.11025 -0.45458984375 0.02399926757812504 -0.110375 -0.4588623046875 0.02399926757812504 -0.1105 -0.462921142578125 0.02399926757812504 -0.110625 -0.468597412109375 0.02399926757812504 -0.11075 -0.47216796875 0.02399926757812504 -0.110875 -0.477081298828125 0.02399926757812504 -0.111 -0.4801025390625 0.02399926757812504 -0.111125 -0.4842529296875 0.02399926757812504 -0.11125 -0.48675537109375 0.02399926757812504 -0.111375 -0.4901123046875 0.02399926757812504 -0.1115 -0.4920654296875 0.02399926757812504 -0.111625 -0.493804931640625 0.02399926757812504 -0.11175 -0.49603271484375 0.02399926757812504 -0.111875 -0.497222900390625 0.02399926757812504 -0.112 -0.498626708984375 0.02399926757812504 -0.112125 -0.499298095703125 0.02399926757812504 -0.11225 -0.499847412109375 0.02399926757812504 -0.112375 -0.499969482421875 0.02399926757812504 -0.1125 -0.499847412109375 0.02399926757812504 -0.112625 -0.499298095703125 0.02399926757812504 -0.11275 -0.498626708984375 0.02399926757812504 -0.112875 -0.497222900390625 0.02399926757812504 -0.113 -0.49603271484375 0.02399926757812504 -0.113125 -0.493804931640625 0.02399926757812504 -0.11325 -0.4920654296875 0.02399926757812504 -0.113375 -0.489044189453125 0.02399926757812504 -0.1135 -0.48675537109375 0.02399926757812504 -0.113625 -0.4842529296875 0.02399926757812504 -0.11375 -0.4801025390625 0.02399926757812504 -0.113875 -0.477081298828125 0.02399926757812504 -0.114 -0.47216796875 0.02399926757812504 -0.114125 -0.468597412109375 0.02399926757812504 -0.11425 -0.462921142578125 0.02399926757812504 -0.114375 -0.4588623046875 0.02399926757812504 -0.1145 -0.452392578125 0.02399926757812504 -0.114625 -0.44781494140625 0.02399926757812504 -0.11475 -0.443084716796875 0.02399926757812504 -0.114875 -0.435577392578125 0.02399926757812504 -0.115 -0.430328369140625 0.02399926757812504 -0.115125 -0.422149658203125 0.02399926757812504 -0.11525 -0.41644287109375 0.02399926757812504 -0.115375 -0.40753173828125 0.02399926757812504 -0.1155 -0.4013671875 0.02399926757812504 -0.115625 -0.391815185546875 0.02399926757812504 -0.11575 -0.385223388671875 0.02399926757812504 -0.115875 -0.37847900390625 0.02399926757812504 -0.116 -0.368011474609375 0.02399926757812504 -0.116125 -0.36083984375 0.02399926757812504 -0.11625 -0.34979248046875 0.02399926757812504 -0.116375 -0.342254638671875 0.02399926757812504 -0.1165 -0.33062744140625 0.02399926757812504 -0.116625 -0.32269287109375 0.02399926757812504 -0.11675 -0.31463623046875 0.02399926757812504 -0.116875 -0.302276611328125 0.02399926757812504 -0.117 -0.293853759765625 0.02399926757812504 -0.117125 -0.281005859375 0.02399926757812504 -0.11725 -0.272308349609375 0.02399926757812504 -0.117375 -0.259002685546875 0.02399926757812504 -0.1175 -0.25 0.02399926757812504 -0.117625 -0.23626708984375 0.02399926757812504 -0.11775 -0.22698974609375 0.02399926757812504 -0.117875 -0.217620849609375 0.02399926757812504 -0.118 -0.203369140625 0.02399926757812504 -0.118125 -0.193756103515625 0.02399926757812504 -0.11825 -0.179168701171875 0.02399926757812504 -0.118375 -0.16937255859375 0.02399926757812504 -0.1185 -0.154510498046875 0.02399926757812504 -0.118625 -0.144500732421875 0.02399926757812504 -0.11875 -0.12939453125 0.02399926757812504 -0.118875 -0.1192626953125 0.02399926757812504 -0.119 -0.10906982421875 0.02399926757812504 -0.119125 -0.09368896484375 0.02399926757812504 -0.11925 -0.0833740234375 0.02399926757812504 -0.119375 -0.067840576171875 0.02399926757812504 -0.1195 -0.057464599609375 0.02399926757812504 -0.119625 -0.041839599609375 0.02399926757812504 -0.11975 -0.031402587890625 0.02399926757812504 -0.119875 -0.015716552734375 0.02399926757812504 -0.12 -0.0052490234375 0.02399926757812504 +0.10475 -0.005218505859375 0.02399926757812504 +0.104875 -0.020904541015625 0.02399926757812504 +0.105 -0.0313720703125 0.02399926757812504 +0.105125 -0.04180908203125 0.02399926757812504 +0.10525 -0.05743408203125 0.02399926757812504 +0.105375 -0.06781005859375 0.02399926757812504 +0.1055 -0.083343505859375 0.02399926757812504 +0.105625 -0.093658447265625 0.02399926757812504 +0.10575 -0.109039306640625 0.02399926757812504 +0.105875 -0.119232177734375 0.02399926757812504 +0.106 -0.134429931640625 0.02399926757812504 +0.106125 -0.14447021484375 0.02399926757812504 +0.10625 -0.15447998046875 0.02399926757812504 +0.106375 -0.169342041015625 0.02399926757812504 +0.1065 -0.17913818359375 0.02399926757812504 +0.106625 -0.1937255859375 0.02399926757812504 +0.10675 -0.203338623046875 0.02399926757812504 +0.106875 -0.21759033203125 0.02399926757812504 +0.107 -0.226959228515625 0.02399926757812504 +0.107125 -0.2408447265625 0.02399926757812504 +0.10725 -0.249969482421875 0.02399926757812504 +0.107375 -0.25897216796875 0.02399926757812504 +0.1075 -0.27227783203125 0.02399926757812504 +0.107625 -0.280975341796875 0.02399926757812504 +0.10775 -0.2938232421875 0.02399926757812504 +0.107875 -0.30224609375 0.02399926757812504 +0.108 -0.314605712890625 0.02399926757812504 +0.108125 -0.322662353515625 0.02399926757812504 +0.10825 -0.330596923828125 0.02399926757812504 +0.108375 -0.34222412109375 0.02399926757812504 +0.1085 -0.349761962890625 0.02399926757812504 +0.108625 -0.360809326171875 0.02399926757812504 +0.10875 -0.36798095703125 0.02399926757812504 +0.108875 -0.378448486328125 0.02399926757812504 +0.109 -0.38519287109375 0.02399926757812504 +0.109125 -0.39501953125 0.02399926757812504 +0.10925 -0.401336669921875 0.02399926757812504 +0.109375 -0.407501220703125 0.02399926757812504 +0.1095 -0.416412353515625 0.02399926757812504 +0.109625 -0.422119140625 0.02399926757812504 +0.10975 -0.4302978515625 0.02399926757812504 +0.109875 -0.435546875 0.02399926757812504 +0.11 -0.44305419921875 0.02399926757812504 +0.110125 -0.447784423828125 0.02399926757812504 +0.11025 -0.454559326171875 0.02399926757812504 +0.110375 -0.458831787109375 0.02399926757812504 +0.1105 -0.462890625 0.02399926757812504 +0.110625 -0.46856689453125 0.02399926757812504 +0.11075 -0.472137451171875 0.02399926757812504 +0.110875 -0.47705078125 0.02399926757812504 +0.111 -0.480072021484375 0.02399926757812504 +0.111125 -0.484222412109375 0.02399926757812504 +0.11125 -0.486724853515625 0.02399926757812504 +0.111375 -0.490081787109375 0.02399926757812504 +0.1115 -0.492034912109375 0.02399926757812504 +0.111625 -0.4937744140625 0.02399926757812504 +0.11175 -0.496002197265625 0.02399926757812504 +0.111875 -0.4971923828125 0.02399926757812504 +0.112 -0.49859619140625 0.02399926757812504 +0.112125 -0.499267578125 0.02399926757812504 +0.11225 -0.49981689453125 0.02399926757812504 +0.112375 -0.49993896484375 0.02399926757812504 +0.1125 -0.49981689453125 0.02399926757812504 +0.112625 -0.499267578125 0.02399926757812504 +0.11275 -0.49859619140625 0.02399926757812504 +0.112875 -0.4971923828125 0.02399926757812504 +0.113 -0.496002197265625 0.02399926757812504 +0.113125 -0.4937744140625 0.02399926757812504 +0.11325 -0.492034912109375 0.02399926757812504 +0.113375 -0.489013671875 0.02399926757812504 +0.1135 -0.486724853515625 0.02399926757812504 +0.113625 -0.484222412109375 0.02399926757812504 +0.11375 -0.480072021484375 0.02399926757812504 +0.113875 -0.47705078125 0.02399926757812504 +0.114 -0.472137451171875 0.02399926757812504 +0.114125 -0.46856689453125 0.02399926757812504 +0.11425 -0.462890625 0.02399926757812504 +0.114375 -0.458831787109375 0.02399926757812504 +0.1145 -0.452362060546875 0.02399926757812504 +0.114625 -0.447784423828125 0.02399926757812504 +0.11475 -0.44305419921875 0.02399926757812504 +0.114875 -0.435546875 0.02399926757812504 +0.115 -0.4302978515625 0.02399926757812504 +0.115125 -0.422119140625 0.02399926757812504 +0.11525 -0.416412353515625 0.02399926757812504 +0.115375 -0.407501220703125 0.02399926757812504 +0.1155 -0.401336669921875 0.02399926757812504 +0.115625 -0.39178466796875 0.02399926757812504 +0.11575 -0.38519287109375 0.02399926757812504 +0.115875 -0.378448486328125 0.02399926757812504 +0.116 -0.36798095703125 0.02399926757812504 +0.116125 -0.360809326171875 0.02399926757812504 +0.11625 -0.349761962890625 0.02399926757812504 +0.116375 -0.34222412109375 0.02399926757812504 +0.1165 -0.330596923828125 0.02399926757812504 +0.116625 -0.322662353515625 0.02399926757812504 +0.11675 -0.314605712890625 0.02399926757812504 +0.116875 -0.30224609375 0.02399926757812504 +0.117 -0.2938232421875 0.02399926757812504 +0.117125 -0.280975341796875 0.02399926757812504 +0.11725 -0.27227783203125 0.02399926757812504 +0.117375 -0.25897216796875 0.02399926757812504 +0.1175 -0.249969482421875 0.02399926757812504 +0.117625 -0.236236572265625 0.02399926757812504 +0.11775 -0.226959228515625 0.02399926757812504 +0.117875 -0.21759033203125 0.02399926757812504 +0.118 -0.203338623046875 0.02399926757812504 +0.118125 -0.1937255859375 0.02399926757812504 +0.11825 -0.17913818359375 0.02399926757812504 +0.118375 -0.169342041015625 0.02399926757812504 +0.1185 -0.15447998046875 0.02399926757812504 +0.118625 -0.14447021484375 0.02399926757812504 +0.11875 -0.129364013671875 0.02399926757812504 +0.118875 -0.119232177734375 0.02399926757812504 +0.119 -0.109039306640625 0.02399926757812504 +0.119125 -0.093658447265625 0.02399926757812504 +0.11925 -0.083343505859375 0.02399926757812504 +0.119375 -0.06781005859375 0.02399926757812504 +0.1195 -0.05743408203125 0.02399926757812504 +0.119625 -0.04180908203125 0.02399926757812504 +0.11975 -0.0313720703125 0.02399926757812504 +0.119875 -0.01568603515625 0.02399926757812504 +0.12 -0.005218505859375 0.02399926757812504 0.120125 0.005218505859375 0.02399926757812504 0.12025 0.020904541015625 0.02399926757812504 0.120375 0.0313720703125 0.02399926757812504 @@ -1072,109 +1072,109 @@ 0.133875 0.036590576171875 0.2799914550781251 0.134 0.020904541015625 0.2799914550781251 0.134125 0.01043701171875 0.2799914550781251 -0.13425 -0.0052490234375 0.2799914550781251 -0.134375 -0.02093505859375 0.2799914550781251 -0.1345 -0.03662109375 0.2799914550781251 -0.134625 -0.052276611328125 0.2799914550781251 -0.13475 -0.067840576171875 0.2799914550781251 -0.134875 -0.0833740234375 0.2799914550781251 -0.135 -0.09881591796875 0.2799914550781251 -0.135125 -0.114166259765625 0.2799914550781251 -0.13525 -0.12939453125 0.2799914550781251 -0.135375 -0.144500732421875 0.2799914550781251 -0.1355 -0.15948486328125 0.2799914550781251 -0.135625 -0.16937255859375 0.2799914550781251 -0.13575 -0.184051513671875 0.2799914550781251 -0.135875 -0.198577880859375 0.2799914550781251 -0.136 -0.212890625 0.2799914550781251 -0.136125 -0.22698974609375 0.2799914550781251 -0.13625 -0.240875244140625 0.2799914550781251 -0.136375 -0.254486083984375 0.2799914550781251 -0.1365 -0.26788330078125 0.2799914550781251 -0.136625 -0.281005859375 0.2799914550781251 -0.13675 -0.293853759765625 0.2799914550781251 -0.136875 -0.306427001953125 0.2799914550781251 -0.137 -0.318695068359375 0.2799914550781251 -0.137125 -0.326690673828125 0.2799914550781251 -0.13725 -0.338409423828125 0.2799914550781251 -0.137375 -0.34979248046875 0.2799914550781251 -0.1375 -0.36083984375 0.2799914550781251 -0.137625 -0.371551513671875 0.2799914550781251 -0.13775 -0.381866455078125 0.2799914550781251 -0.137875 -0.391815185546875 0.2799914550781251 -0.138 -0.4013671875 0.2799914550781251 -0.138125 -0.410552978515625 0.2799914550781251 -0.13825 -0.4193115234375 0.2799914550781251 -0.138375 -0.427642822265625 0.2799914550781251 -0.1385 -0.435577392578125 0.2799914550781251 -0.138625 -0.44061279296875 0.2799914550781251 -0.13875 -0.44781494140625 0.2799914550781251 -0.138875 -0.45458984375 0.2799914550781251 -0.139 -0.460906982421875 0.2799914550781251 -0.139125 -0.466766357421875 0.2799914550781251 -0.13925 -0.47216796875 0.2799914550781251 -0.139375 -0.477081298828125 0.2799914550781251 -0.1395 -0.481536865234375 0.2799914550781251 -0.139625 -0.48553466796875 0.2799914550781251 -0.13975 -0.489044189453125 0.2799914550781251 -0.139875 -0.4920654296875 0.2799914550781251 -0.14 -0.493804931640625 0.2799914550781251 -0.140125 -0.49603271484375 0.2799914550781251 -0.14025 -0.49774169921875 0.2799914550781251 -0.140375 -0.498992919921875 0.2799914550781251 -0.1405 -0.499725341796875 0.2799914550781251 -0.140625 -0.499969482421875 0.2799914550781251 -0.14075 -0.499725341796875 0.2799914550781251 -0.140875 -0.498992919921875 0.2799914550781251 -0.141 -0.49774169921875 0.2799914550781251 -0.141125 -0.49603271484375 0.2799914550781251 -0.14125 -0.493804931640625 0.2799914550781251 -0.141375 -0.491119384765625 0.2799914550781251 -0.1415 -0.489044189453125 0.2799914550781251 -0.141625 -0.48553466796875 0.2799914550781251 -0.14175 -0.481536865234375 0.2799914550781251 -0.141875 -0.477081298828125 0.2799914550781251 -0.142 -0.47216796875 0.2799914550781251 -0.142125 -0.466766357421875 0.2799914550781251 -0.14225 -0.460906982421875 0.2799914550781251 -0.142375 -0.45458984375 0.2799914550781251 -0.1425 -0.44781494140625 0.2799914550781251 -0.142625 -0.44061279296875 0.2799914550781251 -0.14275 -0.4329833984375 0.2799914550781251 -0.142875 -0.4249267578125 0.2799914550781251 -0.143 -0.4193115234375 0.2799914550781251 -0.143125 -0.410552978515625 0.2799914550781251 -0.14325 -0.4013671875 0.2799914550781251 -0.143375 -0.391815185546875 0.2799914550781251 -0.1435 -0.381866455078125 0.2799914550781251 -0.143625 -0.371551513671875 0.2799914550781251 -0.14375 -0.36083984375 0.2799914550781251 -0.143875 -0.34979248046875 0.2799914550781251 -0.144 -0.338409423828125 0.2799914550781251 -0.144125 -0.326690673828125 0.2799914550781251 -0.14425 -0.31463623046875 0.2799914550781251 -0.144375 -0.302276611328125 0.2799914550781251 -0.1445 -0.293853759765625 0.2799914550781251 -0.144625 -0.281005859375 0.2799914550781251 -0.14475 -0.26788330078125 0.2799914550781251 -0.144875 -0.254486083984375 0.2799914550781251 -0.145 -0.240875244140625 0.2799914550781251 -0.145125 -0.22698974609375 0.2799914550781251 -0.14525 -0.212890625 0.2799914550781251 -0.145375 -0.198577880859375 0.2799914550781251 -0.1455 -0.184051513671875 0.2799914550781251 -0.145625 -0.16937255859375 0.2799914550781251 -0.14575 -0.154510498046875 0.2799914550781251 -0.145875 -0.139495849609375 0.2799914550781251 -0.146 -0.12939453125 0.2799914550781251 -0.146125 -0.114166259765625 0.2799914550781251 -0.14625 -0.09881591796875 0.2799914550781251 -0.146375 -0.0833740234375 0.2799914550781251 -0.1465 -0.067840576171875 0.2799914550781251 -0.146625 -0.052276611328125 0.2799914550781251 -0.14675 -0.03662109375 0.2799914550781251 -0.146875 -0.02093505859375 0.2799914550781251 -0.147 -0.0052490234375 0.2799914550781251 +0.13425 -0.005218505859375 0.2799914550781251 +0.134375 -0.020904541015625 0.2799914550781251 +0.1345 -0.036590576171875 0.2799914550781251 +0.134625 -0.05224609375 0.2799914550781251 +0.13475 -0.06781005859375 0.2799914550781251 +0.134875 -0.083343505859375 0.2799914550781251 +0.135 -0.098785400390625 0.2799914550781251 +0.135125 -0.1141357421875 0.2799914550781251 +0.13525 -0.129364013671875 0.2799914550781251 +0.135375 -0.14447021484375 0.2799914550781251 +0.1355 -0.159454345703125 0.2799914550781251 +0.135625 -0.169342041015625 0.2799914550781251 +0.13575 -0.18402099609375 0.2799914550781251 +0.135875 -0.19854736328125 0.2799914550781251 +0.136 -0.212860107421875 0.2799914550781251 +0.136125 -0.226959228515625 0.2799914550781251 +0.13625 -0.2408447265625 0.2799914550781251 +0.136375 -0.25445556640625 0.2799914550781251 +0.1365 -0.267852783203125 0.2799914550781251 +0.136625 -0.280975341796875 0.2799914550781251 +0.13675 -0.2938232421875 0.2799914550781251 +0.136875 -0.306396484375 0.2799914550781251 +0.137 -0.31866455078125 0.2799914550781251 +0.137125 -0.32666015625 0.2799914550781251 +0.13725 -0.33837890625 0.2799914550781251 +0.137375 -0.349761962890625 0.2799914550781251 +0.1375 -0.360809326171875 0.2799914550781251 +0.137625 -0.37152099609375 0.2799914550781251 +0.13775 -0.3818359375 0.2799914550781251 +0.137875 -0.39178466796875 0.2799914550781251 +0.138 -0.401336669921875 0.2799914550781251 +0.138125 -0.4105224609375 0.2799914550781251 +0.13825 -0.419281005859375 0.2799914550781251 +0.138375 -0.4276123046875 0.2799914550781251 +0.1385 -0.435546875 0.2799914550781251 +0.138625 -0.440582275390625 0.2799914550781251 +0.13875 -0.447784423828125 0.2799914550781251 +0.138875 -0.454559326171875 0.2799914550781251 +0.139 -0.46087646484375 0.2799914550781251 +0.139125 -0.46673583984375 0.2799914550781251 +0.13925 -0.472137451171875 0.2799914550781251 +0.139375 -0.47705078125 0.2799914550781251 +0.1395 -0.48150634765625 0.2799914550781251 +0.139625 -0.485504150390625 0.2799914550781251 +0.13975 -0.489013671875 0.2799914550781251 +0.139875 -0.492034912109375 0.2799914550781251 +0.14 -0.4937744140625 0.2799914550781251 +0.140125 -0.496002197265625 0.2799914550781251 +0.14025 -0.497711181640625 0.2799914550781251 +0.140375 -0.49896240234375 0.2799914550781251 +0.1405 -0.49969482421875 0.2799914550781251 +0.140625 -0.49993896484375 0.2799914550781251 +0.14075 -0.49969482421875 0.2799914550781251 +0.140875 -0.49896240234375 0.2799914550781251 +0.141 -0.497711181640625 0.2799914550781251 +0.141125 -0.496002197265625 0.2799914550781251 +0.14125 -0.4937744140625 0.2799914550781251 +0.141375 -0.4910888671875 0.2799914550781251 +0.1415 -0.489013671875 0.2799914550781251 +0.141625 -0.485504150390625 0.2799914550781251 +0.14175 -0.48150634765625 0.2799914550781251 +0.141875 -0.47705078125 0.2799914550781251 +0.142 -0.472137451171875 0.2799914550781251 +0.142125 -0.46673583984375 0.2799914550781251 +0.14225 -0.46087646484375 0.2799914550781251 +0.142375 -0.454559326171875 0.2799914550781251 +0.1425 -0.447784423828125 0.2799914550781251 +0.142625 -0.440582275390625 0.2799914550781251 +0.14275 -0.432952880859375 0.2799914550781251 +0.142875 -0.424896240234375 0.2799914550781251 +0.143 -0.419281005859375 0.2799914550781251 +0.143125 -0.4105224609375 0.2799914550781251 +0.14325 -0.401336669921875 0.2799914550781251 +0.143375 -0.39178466796875 0.2799914550781251 +0.1435 -0.3818359375 0.2799914550781251 +0.143625 -0.37152099609375 0.2799914550781251 +0.14375 -0.360809326171875 0.2799914550781251 +0.143875 -0.349761962890625 0.2799914550781251 +0.144 -0.33837890625 0.2799914550781251 +0.144125 -0.32666015625 0.2799914550781251 +0.14425 -0.314605712890625 0.2799914550781251 +0.144375 -0.30224609375 0.2799914550781251 +0.1445 -0.2938232421875 0.2799914550781251 +0.144625 -0.280975341796875 0.2799914550781251 +0.14475 -0.267852783203125 0.2799914550781251 +0.144875 -0.25445556640625 0.2799914550781251 +0.145 -0.2408447265625 0.2799914550781251 +0.145125 -0.226959228515625 0.2799914550781251 +0.14525 -0.212860107421875 0.2799914550781251 +0.145375 -0.19854736328125 0.2799914550781251 +0.1455 -0.18402099609375 0.2799914550781251 +0.145625 -0.169342041015625 0.2799914550781251 +0.14575 -0.15447998046875 0.2799914550781251 +0.145875 -0.13946533203125 0.2799914550781251 +0.146 -0.129364013671875 0.2799914550781251 +0.146125 -0.1141357421875 0.2799914550781251 +0.14625 -0.098785400390625 0.2799914550781251 +0.146375 -0.083343505859375 0.2799914550781251 +0.1465 -0.06781005859375 0.2799914550781251 +0.146625 -0.05224609375 0.2799914550781251 +0.14675 -0.036590576171875 0.2799914550781251 +0.146875 -0.020904541015625 0.2799914550781251 +0.147 -0.005218505859375 0.2799914550781251 0.147125 0.01043701171875 0.2799914550781251 0.14725 0.026123046875 0.2799914550781251 0.147375 0.036590576171875 0.2799914550781251 @@ -1278,92 +1278,92 @@ 0.159625 0.036590576171875 0.2799914550781251 0.15975 0.020904541015625 0.2799914550781251 0.159875 0.005218505859375 0.2799914550781251 -0.16 -0.010467529296875 0.535983642578125 -0.160125 -0.031402587890625 0.535983642578125 -0.16025 -0.04705810546875 0.535983642578125 -0.160375 -0.067840576171875 0.535983642578125 -0.1605 -0.0833740234375 0.535983642578125 -0.160625 -0.10394287109375 0.535983642578125 -0.16075 -0.1192626953125 0.535983642578125 -0.160875 -0.139495849609375 0.535983642578125 -0.161 -0.154510498046875 0.535983642578125 -0.161125 -0.174285888671875 0.535983642578125 -0.16125 -0.18890380859375 0.535983642578125 -0.161375 -0.2081298828125 0.535983642578125 -0.1615 -0.222320556640625 0.535983642578125 -0.161625 -0.240875244140625 0.535983642578125 -0.16175 -0.254486083984375 0.535983642578125 -0.161875 -0.272308349609375 0.535983642578125 -0.162 -0.28533935546875 0.535983642578125 -0.162125 -0.302276611328125 0.535983642578125 -0.16225 -0.31463623046875 0.535983642578125 -0.162375 -0.33062744140625 0.535983642578125 -0.1625 -0.342254638671875 0.535983642578125 -0.162625 -0.357208251953125 0.535983642578125 -0.16275 -0.368011474609375 0.535983642578125 -0.162875 -0.381866455078125 0.535983642578125 -0.163 -0.391815185546875 0.535983642578125 -0.163125 -0.40447998046875 0.535983642578125 -0.16325 -0.41351318359375 0.535983642578125 -0.163375 -0.422149658203125 0.535983642578125 -0.1635 -0.4329833984375 0.535983642578125 -0.163625 -0.44061279296875 0.535983642578125 -0.16375 -0.45013427734375 0.535983642578125 -0.163875 -0.456756591796875 0.535983642578125 -0.164 -0.46484375 0.535983642578125 -0.164125 -0.47039794921875 0.535983642578125 -0.16425 -0.477081298828125 0.535983642578125 -0.164375 -0.481536865234375 0.535983642578125 -0.1645 -0.48675537109375 0.535983642578125 -0.164625 -0.4901123046875 0.535983642578125 -0.16475 -0.493804931640625 0.535983642578125 -0.164875 -0.49603271484375 0.535983642578125 -0.165 -0.49822998046875 0.535983642578125 -0.165125 -0.499298095703125 0.535983642578125 -0.16525 -0.49993896484375 0.535983642578125 -0.165375 -0.499847412109375 0.535983642578125 -0.1655 -0.498992919921875 0.535983642578125 -0.165625 -0.49774169921875 0.535983642578125 -0.16575 -0.495330810546875 0.535983642578125 -0.165875 -0.49298095703125 0.535983642578125 -0.166 -0.489044189453125 0.535983642578125 -0.166125 -0.48553466796875 0.535983642578125 -0.16625 -0.4801025390625 0.535983642578125 -0.166375 -0.475494384765625 0.535983642578125 -0.1665 -0.468597412109375 0.535983642578125 -0.166625 -0.462921142578125 0.535983642578125 -0.16675 -0.456756591796875 0.535983642578125 -0.166875 -0.44781494140625 0.535983642578125 -0.167 -0.44061279296875 0.535983642578125 -0.167125 -0.430328369140625 0.535983642578125 -0.16725 -0.422149658203125 0.535983642578125 -0.167375 -0.410552978515625 0.535983642578125 -0.1675 -0.4013671875 0.535983642578125 -0.167625 -0.3885498046875 0.535983642578125 -0.16775 -0.37847900390625 0.535983642578125 -0.167875 -0.364471435546875 0.535983642578125 -0.168 -0.353515625 0.535983642578125 -0.168125 -0.338409423828125 0.535983642578125 -0.16825 -0.326690673828125 0.535983642578125 -0.168375 -0.310546875 0.535983642578125 -0.1685 -0.298095703125 0.535983642578125 -0.168625 -0.281005859375 0.535983642578125 -0.16875 -0.26788330078125 0.535983642578125 -0.168875 -0.25 0.535983642578125 -0.169 -0.23626708984375 0.535983642578125 -0.169125 -0.217620849609375 0.535983642578125 -0.16925 -0.203369140625 0.535983642578125 -0.169375 -0.184051513671875 0.535983642578125 -0.1695 -0.16937255859375 0.535983642578125 -0.169625 -0.149505615234375 0.535983642578125 -0.16975 -0.13446044921875 0.535983642578125 -0.169875 -0.1192626953125 0.535983642578125 -0.17 -0.09881591796875 0.535983642578125 -0.170125 -0.0833740234375 0.535983642578125 -0.17025 -0.062652587890625 0.535983642578125 -0.170375 -0.04705810546875 0.535983642578125 -0.1705 -0.026153564453125 0.535983642578125 -0.170625 -0.010467529296875 0.535983642578125 +0.16 -0.01043701171875 0.535983642578125 +0.160125 -0.0313720703125 0.535983642578125 +0.16025 -0.047027587890625 0.535983642578125 +0.160375 -0.06781005859375 0.535983642578125 +0.1605 -0.083343505859375 0.535983642578125 +0.160625 -0.103912353515625 0.535983642578125 +0.16075 -0.119232177734375 0.535983642578125 +0.160875 -0.13946533203125 0.535983642578125 +0.161 -0.15447998046875 0.535983642578125 +0.161125 -0.17425537109375 0.535983642578125 +0.16125 -0.188873291015625 0.535983642578125 +0.161375 -0.208099365234375 0.535983642578125 +0.1615 -0.2222900390625 0.535983642578125 +0.161625 -0.2408447265625 0.535983642578125 +0.16175 -0.25445556640625 0.535983642578125 +0.161875 -0.27227783203125 0.535983642578125 +0.162 -0.285308837890625 0.535983642578125 +0.162125 -0.30224609375 0.535983642578125 +0.16225 -0.314605712890625 0.535983642578125 +0.162375 -0.330596923828125 0.535983642578125 +0.1625 -0.34222412109375 0.535983642578125 +0.162625 -0.357177734375 0.535983642578125 +0.16275 -0.36798095703125 0.535983642578125 +0.162875 -0.3818359375 0.535983642578125 +0.163 -0.39178466796875 0.535983642578125 +0.163125 -0.404449462890625 0.535983642578125 +0.16325 -0.413482666015625 0.535983642578125 +0.163375 -0.422119140625 0.535983642578125 +0.1635 -0.432952880859375 0.535983642578125 +0.163625 -0.440582275390625 0.535983642578125 +0.16375 -0.450103759765625 0.535983642578125 +0.163875 -0.45672607421875 0.535983642578125 +0.164 -0.464813232421875 0.535983642578125 +0.164125 -0.470367431640625 0.535983642578125 +0.16425 -0.47705078125 0.535983642578125 +0.164375 -0.48150634765625 0.535983642578125 +0.1645 -0.486724853515625 0.535983642578125 +0.164625 -0.490081787109375 0.535983642578125 +0.16475 -0.4937744140625 0.535983642578125 +0.164875 -0.496002197265625 0.535983642578125 +0.165 -0.498199462890625 0.535983642578125 +0.165125 -0.499267578125 0.535983642578125 +0.16525 -0.499908447265625 0.535983642578125 +0.165375 -0.49981689453125 0.535983642578125 +0.1655 -0.49896240234375 0.535983642578125 +0.165625 -0.497711181640625 0.535983642578125 +0.16575 -0.49530029296875 0.535983642578125 +0.165875 -0.492950439453125 0.535983642578125 +0.166 -0.489013671875 0.535983642578125 +0.166125 -0.485504150390625 0.535983642578125 +0.16625 -0.480072021484375 0.535983642578125 +0.166375 -0.4754638671875 0.535983642578125 +0.1665 -0.46856689453125 0.535983642578125 +0.166625 -0.462890625 0.535983642578125 +0.16675 -0.45672607421875 0.535983642578125 +0.166875 -0.447784423828125 0.535983642578125 +0.167 -0.440582275390625 0.535983642578125 +0.167125 -0.4302978515625 0.535983642578125 +0.16725 -0.422119140625 0.535983642578125 +0.167375 -0.4105224609375 0.535983642578125 +0.1675 -0.401336669921875 0.535983642578125 +0.167625 -0.388519287109375 0.535983642578125 +0.16775 -0.378448486328125 0.535983642578125 +0.167875 -0.36444091796875 0.535983642578125 +0.168 -0.353485107421875 0.535983642578125 +0.168125 -0.33837890625 0.535983642578125 +0.16825 -0.32666015625 0.535983642578125 +0.168375 -0.310516357421875 0.535983642578125 +0.1685 -0.298065185546875 0.535983642578125 +0.168625 -0.280975341796875 0.535983642578125 +0.16875 -0.267852783203125 0.535983642578125 +0.168875 -0.249969482421875 0.535983642578125 +0.169 -0.236236572265625 0.535983642578125 +0.169125 -0.21759033203125 0.535983642578125 +0.16925 -0.203338623046875 0.535983642578125 +0.169375 -0.18402099609375 0.535983642578125 +0.1695 -0.169342041015625 0.535983642578125 +0.169625 -0.14947509765625 0.535983642578125 +0.16975 -0.134429931640625 0.535983642578125 +0.169875 -0.119232177734375 0.535983642578125 +0.17 -0.098785400390625 0.535983642578125 +0.170125 -0.083343505859375 0.535983642578125 +0.17025 -0.0626220703125 0.535983642578125 +0.170375 -0.047027587890625 0.535983642578125 +0.1705 -0.026123046875 0.535983642578125 +0.170625 -0.01043701171875 0.535983642578125 0.17075 0.01043701171875 0.535983642578125 0.170875 0.026123046875 0.535983642578125 0.171 0.047027587890625 0.535983642578125 @@ -1450,92 +1450,92 @@ 0.181125 0.047027587890625 0.535983642578125 0.18125 0.0313720703125 0.535983642578125 0.181375 0.01043701171875 0.535983642578125 -0.1815 -0.0052490234375 0.535983642578125 -0.181625 -0.026153564453125 0.535983642578125 -0.18175 -0.041839599609375 0.535983642578125 -0.181875 -0.062652587890625 0.535983642578125 -0.182 -0.078216552734375 0.535983642578125 -0.182125 -0.09881591796875 0.535983642578125 -0.18225 -0.114166259765625 0.535983642578125 -0.182375 -0.13446044921875 0.535983642578125 -0.1825 -0.149505615234375 0.535983642578125 -0.182625 -0.16937255859375 0.535983642578125 -0.18275 -0.184051513671875 0.535983642578125 -0.182875 -0.203369140625 0.535983642578125 -0.183 -0.217620849609375 0.535983642578125 -0.183125 -0.23626708984375 0.535983642578125 -0.18325 -0.25 0.535983642578125 -0.183375 -0.263458251953125 0.535983642578125 -0.1835 -0.281005859375 0.535983642578125 -0.183625 -0.293853759765625 0.535983642578125 -0.18375 -0.310546875 0.535983642578125 -0.183875 -0.32269287109375 0.535983642578125 -0.184 -0.338409423828125 0.535983642578125 -0.184125 -0.34979248046875 0.535983642578125 -0.18425 -0.364471435546875 0.535983642578125 -0.184375 -0.375030517578125 0.535983642578125 -0.1845 -0.3885498046875 0.535983642578125 -0.184625 -0.398223876953125 0.535983642578125 -0.18475 -0.410552978515625 0.535983642578125 -0.184875 -0.4193115234375 0.535983642578125 -0.185 -0.430328369140625 0.535983642578125 -0.185125 -0.4381103515625 0.535983642578125 -0.18525 -0.44781494140625 0.535983642578125 -0.185375 -0.45458984375 0.535983642578125 -0.1855 -0.462921142578125 0.535983642578125 -0.185625 -0.468597412109375 0.535983642578125 -0.18575 -0.475494384765625 0.535983642578125 -0.185875 -0.4801025390625 0.535983642578125 -0.186 -0.48553466796875 0.535983642578125 -0.186125 -0.489044189453125 0.535983642578125 -0.18625 -0.49298095703125 0.535983642578125 -0.186375 -0.495330810546875 0.535983642578125 -0.1865 -0.497222900390625 0.535983642578125 -0.186625 -0.498992919921875 0.535983642578125 -0.18675 -0.499725341796875 0.535983642578125 -0.186875 -0.49993896484375 0.535983642578125 -0.187 -0.499542236328125 0.535983642578125 -0.187125 -0.49822998046875 0.535983642578125 -0.18725 -0.49664306640625 0.535983642578125 -0.187375 -0.493804931640625 0.535983642578125 -0.1875 -0.491119384765625 0.535983642578125 -0.187625 -0.48675537109375 0.535983642578125 -0.18775 -0.482940673828125 0.535983642578125 -0.187875 -0.477081298828125 0.535983642578125 -0.188 -0.47216796875 0.535983642578125 -0.188125 -0.46484375 0.535983642578125 -0.18825 -0.4588623046875 0.535983642578125 -0.188375 -0.45013427734375 0.535983642578125 -0.1885 -0.443084716796875 0.535983642578125 -0.188625 -0.4329833984375 0.535983642578125 -0.18875 -0.4249267578125 0.535983642578125 -0.188875 -0.41351318359375 0.535983642578125 -0.189 -0.40447998046875 0.535983642578125 -0.189125 -0.391815185546875 0.535983642578125 -0.18925 -0.381866455078125 0.535983642578125 -0.189375 -0.368011474609375 0.535983642578125 -0.1895 -0.357208251953125 0.535983642578125 -0.189625 -0.342254638671875 0.535983642578125 -0.18975 -0.33062744140625 0.535983642578125 -0.189875 -0.318695068359375 0.535983642578125 -0.19 -0.302276611328125 0.535983642578125 -0.190125 -0.28961181640625 0.535983642578125 -0.19025 -0.272308349609375 0.535983642578125 -0.190375 -0.259002685546875 0.535983642578125 -0.1905 -0.240875244140625 0.535983642578125 -0.190625 -0.22698974609375 0.535983642578125 -0.19075 -0.2081298828125 0.535983642578125 -0.190875 -0.193756103515625 0.535983642578125 -0.191 -0.174285888671875 0.535983642578125 -0.191125 -0.15948486328125 0.535983642578125 -0.19125 -0.139495849609375 0.535983642578125 -0.191375 -0.12432861328125 0.535983642578125 -0.1915 -0.10394287109375 0.535983642578125 -0.191625 -0.088531494140625 0.535983642578125 -0.19175 -0.067840576171875 0.535983642578125 -0.191875 -0.052276611328125 0.535983642578125 -0.192 -0.031402587890625 0.791975830078125 -0.192125 -0.0052490234375 0.791975830078125 +0.1815 -0.005218505859375 0.535983642578125 +0.181625 -0.026123046875 0.535983642578125 +0.18175 -0.04180908203125 0.535983642578125 +0.181875 -0.0626220703125 0.535983642578125 +0.182 -0.07818603515625 0.535983642578125 +0.182125 -0.098785400390625 0.535983642578125 +0.18225 -0.1141357421875 0.535983642578125 +0.182375 -0.134429931640625 0.535983642578125 +0.1825 -0.14947509765625 0.535983642578125 +0.182625 -0.169342041015625 0.535983642578125 +0.18275 -0.18402099609375 0.535983642578125 +0.182875 -0.203338623046875 0.535983642578125 +0.183 -0.21759033203125 0.535983642578125 +0.183125 -0.236236572265625 0.535983642578125 +0.18325 -0.249969482421875 0.535983642578125 +0.183375 -0.263427734375 0.535983642578125 +0.1835 -0.280975341796875 0.535983642578125 +0.183625 -0.2938232421875 0.535983642578125 +0.18375 -0.310516357421875 0.535983642578125 +0.183875 -0.322662353515625 0.535983642578125 +0.184 -0.33837890625 0.535983642578125 +0.184125 -0.349761962890625 0.535983642578125 +0.18425 -0.36444091796875 0.535983642578125 +0.184375 -0.375 0.535983642578125 +0.1845 -0.388519287109375 0.535983642578125 +0.184625 -0.398193359375 0.535983642578125 +0.18475 -0.4105224609375 0.535983642578125 +0.184875 -0.419281005859375 0.535983642578125 +0.185 -0.4302978515625 0.535983642578125 +0.185125 -0.438079833984375 0.535983642578125 +0.18525 -0.447784423828125 0.535983642578125 +0.185375 -0.454559326171875 0.535983642578125 +0.1855 -0.462890625 0.535983642578125 +0.185625 -0.46856689453125 0.535983642578125 +0.18575 -0.4754638671875 0.535983642578125 +0.185875 -0.480072021484375 0.535983642578125 +0.186 -0.485504150390625 0.535983642578125 +0.186125 -0.489013671875 0.535983642578125 +0.18625 -0.492950439453125 0.535983642578125 +0.186375 -0.49530029296875 0.535983642578125 +0.1865 -0.4971923828125 0.535983642578125 +0.186625 -0.49896240234375 0.535983642578125 +0.18675 -0.49969482421875 0.535983642578125 +0.186875 -0.499908447265625 0.535983642578125 +0.187 -0.49951171875 0.535983642578125 +0.187125 -0.498199462890625 0.535983642578125 +0.18725 -0.496612548828125 0.535983642578125 +0.187375 -0.4937744140625 0.535983642578125 +0.1875 -0.4910888671875 0.535983642578125 +0.187625 -0.486724853515625 0.535983642578125 +0.18775 -0.48291015625 0.535983642578125 +0.187875 -0.47705078125 0.535983642578125 +0.188 -0.472137451171875 0.535983642578125 +0.188125 -0.464813232421875 0.535983642578125 +0.18825 -0.458831787109375 0.535983642578125 +0.188375 -0.450103759765625 0.535983642578125 +0.1885 -0.44305419921875 0.535983642578125 +0.188625 -0.432952880859375 0.535983642578125 +0.18875 -0.424896240234375 0.535983642578125 +0.188875 -0.413482666015625 0.535983642578125 +0.189 -0.404449462890625 0.535983642578125 +0.189125 -0.39178466796875 0.535983642578125 +0.18925 -0.3818359375 0.535983642578125 +0.189375 -0.36798095703125 0.535983642578125 +0.1895 -0.357177734375 0.535983642578125 +0.189625 -0.34222412109375 0.535983642578125 +0.18975 -0.330596923828125 0.535983642578125 +0.189875 -0.31866455078125 0.535983642578125 +0.19 -0.30224609375 0.535983642578125 +0.190125 -0.289581298828125 0.535983642578125 +0.19025 -0.27227783203125 0.535983642578125 +0.190375 -0.25897216796875 0.535983642578125 +0.1905 -0.2408447265625 0.535983642578125 +0.190625 -0.226959228515625 0.535983642578125 +0.19075 -0.208099365234375 0.535983642578125 +0.190875 -0.1937255859375 0.535983642578125 +0.191 -0.17425537109375 0.535983642578125 +0.191125 -0.159454345703125 0.535983642578125 +0.19125 -0.13946533203125 0.535983642578125 +0.191375 -0.124298095703125 0.535983642578125 +0.1915 -0.103912353515625 0.535983642578125 +0.191625 -0.0885009765625 0.535983642578125 +0.19175 -0.06781005859375 0.535983642578125 +0.191875 -0.05224609375 0.535983642578125 +0.192 -0.0313720703125 0.791975830078125 +0.192125 -0.005218505859375 0.791975830078125 0.19225 0.01568603515625 0.791975830078125 0.192375 0.036590576171875 0.791975830078125 0.1925 0.05743408203125 0.791975830078125 @@ -1608,78 +1608,78 @@ 0.200875 0.05743408203125 0.791975830078125 0.201 0.0313720703125 0.791975830078125 0.201125 0.01043701171875 0.791975830078125 -0.20125 -0.010467529296875 0.791975830078125 -0.201375 -0.031402587890625 0.791975830078125 -0.2015 -0.052276611328125 0.791975830078125 -0.201625 -0.073028564453125 0.791975830078125 -0.20175 -0.09881591796875 0.791975830078125 -0.201875 -0.1192626953125 0.791975830078125 -0.202 -0.139495849609375 0.791975830078125 -0.202125 -0.15948486328125 0.791975830078125 -0.20225 -0.179168701171875 0.791975830078125 -0.202375 -0.198577880859375 0.791975830078125 -0.2025 -0.222320556640625 0.791975830078125 -0.202625 -0.240875244140625 0.791975830078125 -0.20275 -0.259002685546875 0.791975830078125 -0.202875 -0.27667236328125 0.791975830078125 -0.203 -0.293853759765625 0.791975830078125 -0.203125 -0.310546875 0.791975830078125 -0.20325 -0.326690673828125 0.791975830078125 -0.203375 -0.346038818359375 0.791975830078125 -0.2035 -0.36083984375 0.791975830078125 -0.203625 -0.375030517578125 0.791975830078125 -0.20375 -0.3885498046875 0.791975830078125 -0.203875 -0.4013671875 0.791975830078125 -0.204 -0.41351318359375 0.791975830078125 -0.204125 -0.427642822265625 0.791975830078125 -0.20425 -0.4381103515625 0.791975830078125 -0.204375 -0.44781494140625 0.791975830078125 -0.2045 -0.456756591796875 0.791975830078125 -0.204625 -0.46484375 0.791975830078125 -0.20475 -0.47216796875 0.791975830078125 -0.204875 -0.4801025390625 0.791975830078125 -0.205 -0.48553466796875 0.791975830078125 -0.205125 -0.4901123046875 0.791975830078125 -0.20525 -0.493804931640625 0.791975830078125 -0.205375 -0.49664306640625 0.791975830078125 -0.2055 -0.498626708984375 0.791975830078125 -0.205625 -0.499725341796875 0.791975830078125 -0.20575 -0.499847412109375 0.791975830078125 -0.205875 -0.498992919921875 0.791975830078125 -0.206 -0.497222900390625 0.791975830078125 -0.206125 -0.494598388671875 0.791975830078125 -0.20625 -0.491119384765625 0.791975830078125 -0.206375 -0.48675537109375 0.791975830078125 -0.2065 -0.4801025390625 0.791975830078125 -0.206625 -0.473846435546875 0.791975830078125 -0.20675 -0.466766357421875 0.791975830078125 -0.206875 -0.4588623046875 0.791975830078125 -0.207 -0.45013427734375 0.791975830078125 -0.207125 -0.44061279296875 0.791975830078125 -0.20725 -0.427642822265625 0.791975830078125 -0.207375 -0.41644287109375 0.791975830078125 -0.2075 -0.40447998046875 0.791975830078125 -0.207625 -0.391815185546875 0.791975830078125 -0.20775 -0.37847900390625 0.791975830078125 -0.207875 -0.364471435546875 0.791975830078125 -0.208 -0.34979248046875 0.791975830078125 -0.208125 -0.33062744140625 0.791975830078125 -0.20825 -0.31463623046875 0.791975830078125 -0.208375 -0.298095703125 0.791975830078125 -0.2085 -0.281005859375 0.791975830078125 -0.208625 -0.263458251953125 0.791975830078125 -0.20875 -0.245452880859375 0.791975830078125 -0.208875 -0.222320556640625 0.791975830078125 -0.209 -0.203369140625 0.791975830078125 -0.209125 -0.184051513671875 0.791975830078125 -0.20925 -0.1644287109375 0.791975830078125 -0.209375 -0.144500732421875 0.791975830078125 -0.2095 -0.12432861328125 0.791975830078125 -0.209625 -0.10394287109375 0.791975830078125 -0.20975 -0.078216552734375 0.791975830078125 -0.209875 -0.057464599609375 0.791975830078125 -0.21 -0.03662109375 0.791975830078125 -0.210125 -0.015716552734375 0.791975830078125 +0.20125 -0.01043701171875 0.791975830078125 +0.201375 -0.0313720703125 0.791975830078125 +0.2015 -0.05224609375 0.791975830078125 +0.201625 -0.072998046875 0.791975830078125 +0.20175 -0.098785400390625 0.791975830078125 +0.201875 -0.119232177734375 0.791975830078125 +0.202 -0.13946533203125 0.791975830078125 +0.202125 -0.159454345703125 0.791975830078125 +0.20225 -0.17913818359375 0.791975830078125 +0.202375 -0.19854736328125 0.791975830078125 +0.2025 -0.2222900390625 0.791975830078125 +0.202625 -0.2408447265625 0.791975830078125 +0.20275 -0.25897216796875 0.791975830078125 +0.202875 -0.276641845703125 0.791975830078125 +0.203 -0.2938232421875 0.791975830078125 +0.203125 -0.310516357421875 0.791975830078125 +0.20325 -0.32666015625 0.791975830078125 +0.203375 -0.34600830078125 0.791975830078125 +0.2035 -0.360809326171875 0.791975830078125 +0.203625 -0.375 0.791975830078125 +0.20375 -0.388519287109375 0.791975830078125 +0.203875 -0.401336669921875 0.791975830078125 +0.204 -0.413482666015625 0.791975830078125 +0.204125 -0.4276123046875 0.791975830078125 +0.20425 -0.438079833984375 0.791975830078125 +0.204375 -0.447784423828125 0.791975830078125 +0.2045 -0.45672607421875 0.791975830078125 +0.204625 -0.464813232421875 0.791975830078125 +0.20475 -0.472137451171875 0.791975830078125 +0.204875 -0.480072021484375 0.791975830078125 +0.205 -0.485504150390625 0.791975830078125 +0.205125 -0.490081787109375 0.791975830078125 +0.20525 -0.4937744140625 0.791975830078125 +0.205375 -0.496612548828125 0.791975830078125 +0.2055 -0.49859619140625 0.791975830078125 +0.205625 -0.49969482421875 0.791975830078125 +0.20575 -0.49981689453125 0.791975830078125 +0.205875 -0.49896240234375 0.791975830078125 +0.206 -0.4971923828125 0.791975830078125 +0.206125 -0.49456787109375 0.791975830078125 +0.20625 -0.4910888671875 0.791975830078125 +0.206375 -0.486724853515625 0.791975830078125 +0.2065 -0.480072021484375 0.791975830078125 +0.206625 -0.47381591796875 0.791975830078125 +0.20675 -0.46673583984375 0.791975830078125 +0.206875 -0.458831787109375 0.791975830078125 +0.207 -0.450103759765625 0.791975830078125 +0.207125 -0.440582275390625 0.791975830078125 +0.20725 -0.4276123046875 0.791975830078125 +0.207375 -0.416412353515625 0.791975830078125 +0.2075 -0.404449462890625 0.791975830078125 +0.207625 -0.39178466796875 0.791975830078125 +0.20775 -0.378448486328125 0.791975830078125 +0.207875 -0.36444091796875 0.791975830078125 +0.208 -0.349761962890625 0.791975830078125 +0.208125 -0.330596923828125 0.791975830078125 +0.20825 -0.314605712890625 0.791975830078125 +0.208375 -0.298065185546875 0.791975830078125 +0.2085 -0.280975341796875 0.791975830078125 +0.208625 -0.263427734375 0.791975830078125 +0.20875 -0.24542236328125 0.791975830078125 +0.208875 -0.2222900390625 0.791975830078125 +0.209 -0.203338623046875 0.791975830078125 +0.209125 -0.18402099609375 0.791975830078125 +0.20925 -0.164398193359375 0.791975830078125 +0.209375 -0.14447021484375 0.791975830078125 +0.2095 -0.124298095703125 0.791975830078125 +0.209625 -0.103912353515625 0.791975830078125 +0.20975 -0.07818603515625 0.791975830078125 +0.209875 -0.05743408203125 0.791975830078125 +0.21 -0.036590576171875 0.791975830078125 +0.210125 -0.01568603515625 0.791975830078125 0.21025 0.005218505859375 0.791975830078125 0.210375 0.026123046875 0.791975830078125 0.2105 0.05224609375 0.791975830078125 @@ -1752,74 +1752,74 @@ 0.218875 0.0626220703125 0.791975830078125 0.219 0.04180908203125 0.791975830078125 0.219125 0.020904541015625 0.791975830078125 -0.21925 -0.0052490234375 0.791975830078125 -0.219375 -0.026153564453125 0.791975830078125 -0.2195 -0.04705810546875 0.791975830078125 -0.219625 -0.067840576171875 0.791975830078125 -0.21975 -0.088531494140625 0.791975830078125 -0.219875 -0.10906982421875 0.791975830078125 -0.22 -0.13446044921875 0.791975830078125 -0.220125 -0.154510498046875 0.791975830078125 -0.22025 -0.174285888671875 0.791975830078125 -0.220375 -0.193756103515625 0.791975830078125 -0.2205 -0.212890625 0.791975830078125 -0.220625 -0.23162841796875 0.791975830078125 -0.22075 -0.25 0.791975830078125 -0.220875 -0.272308349609375 0.791975830078125 -0.221 -0.28961181640625 0.791975830078125 -0.221125 -0.306427001953125 0.791975830078125 -0.22125 -0.32269287109375 0.791975830078125 -0.221375 -0.338409423828125 0.791975830078125 -0.2215 -0.353515625 0.791975830078125 -0.221625 -0.371551513671875 0.791975830078125 -0.22175 -0.385223388671875 0.791975830078125 -0.221875 -0.398223876953125 0.791975830078125 -0.222 -0.410552978515625 0.791975830078125 -0.222125 -0.422149658203125 0.791975830078125 -0.22225 -0.4329833984375 0.791975830078125 -0.222375 -0.445465087890625 0.791975830078125 -0.2225 -0.45458984375 0.791975830078125 -0.222625 -0.462921142578125 0.791975830078125 -0.22275 -0.47039794921875 0.791975830078125 -0.222875 -0.477081298828125 0.791975830078125 -0.223 -0.482940673828125 0.791975830078125 -0.223125 -0.4879150390625 0.791975830078125 -0.22325 -0.49298095703125 0.791975830078125 -0.223375 -0.49603271484375 0.791975830078125 -0.2235 -0.49822998046875 0.791975830078125 -0.223625 -0.499542236328125 0.791975830078125 -0.22375 -0.499969482421875 0.791975830078125 -0.223875 -0.499542236328125 0.791975830078125 -0.224 -0.49774169921875 0.9999084491282701 -0.224125 -0.494598388671875 0.9999084491282701 -0.22425 -0.4901123046875 0.9999084491282701 -0.224375 -0.4842529296875 0.9999084491282701 -0.2245 -0.4786376953125 0.9999084491282701 -0.224625 -0.47039794921875 0.9999084491282701 -0.22475 -0.460906982421875 0.9999084491282701 -0.224875 -0.45013427734375 0.9999084491282701 -0.225 -0.4381103515625 0.9999084491282701 -0.225125 -0.427642822265625 0.9999084491282701 -0.22525 -0.41351318359375 0.9999084491282701 -0.225375 -0.398223876953125 0.9999084491282701 -0.2255 -0.381866455078125 0.9999084491282701 -0.225625 -0.364471435546875 0.9999084491282701 -0.22575 -0.34979248046875 0.9999084491282701 -0.225875 -0.33062744140625 0.9999084491282701 -0.226 -0.310546875 0.9999084491282701 -0.226125 -0.28961181640625 0.9999084491282701 -0.22625 -0.26788330078125 0.9999084491282701 -0.226375 -0.25 0.9999084491282701 -0.2265 -0.22698974609375 0.9999084491282701 -0.226625 -0.203369140625 0.9999084491282701 -0.22675 -0.179168701171875 0.9999084491282701 -0.226875 -0.154510498046875 0.9999084491282701 -0.227 -0.13446044921875 0.9999084491282701 -0.227125 -0.10906982421875 0.9999084491282701 -0.22725 -0.0833740234375 0.9999084491282701 -0.227375 -0.057464599609375 0.9999084491282701 -0.2275 -0.031402587890625 0.9999084491282701 -0.227625 -0.010467529296875 0.9999084491282701 +0.21925 -0.005218505859375 0.791975830078125 +0.219375 -0.026123046875 0.791975830078125 +0.2195 -0.047027587890625 0.791975830078125 +0.219625 -0.06781005859375 0.791975830078125 +0.21975 -0.0885009765625 0.791975830078125 +0.219875 -0.109039306640625 0.791975830078125 +0.22 -0.134429931640625 0.791975830078125 +0.220125 -0.15447998046875 0.791975830078125 +0.22025 -0.17425537109375 0.791975830078125 +0.220375 -0.1937255859375 0.791975830078125 +0.2205 -0.212860107421875 0.791975830078125 +0.220625 -0.231597900390625 0.791975830078125 +0.22075 -0.249969482421875 0.791975830078125 +0.220875 -0.27227783203125 0.791975830078125 +0.221 -0.289581298828125 0.791975830078125 +0.221125 -0.306396484375 0.791975830078125 +0.22125 -0.322662353515625 0.791975830078125 +0.221375 -0.33837890625 0.791975830078125 +0.2215 -0.353485107421875 0.791975830078125 +0.221625 -0.37152099609375 0.791975830078125 +0.22175 -0.38519287109375 0.791975830078125 +0.221875 -0.398193359375 0.791975830078125 +0.222 -0.4105224609375 0.791975830078125 +0.222125 -0.422119140625 0.791975830078125 +0.22225 -0.432952880859375 0.791975830078125 +0.222375 -0.4454345703125 0.791975830078125 +0.2225 -0.454559326171875 0.791975830078125 +0.222625 -0.462890625 0.791975830078125 +0.22275 -0.470367431640625 0.791975830078125 +0.222875 -0.47705078125 0.791975830078125 +0.223 -0.48291015625 0.791975830078125 +0.223125 -0.487884521484375 0.791975830078125 +0.22325 -0.492950439453125 0.791975830078125 +0.223375 -0.496002197265625 0.791975830078125 +0.2235 -0.498199462890625 0.791975830078125 +0.223625 -0.49951171875 0.791975830078125 +0.22375 -0.49993896484375 0.791975830078125 +0.223875 -0.49951171875 0.791975830078125 +0.224 -0.497711181640625 0.9999084491282701 +0.224125 -0.49456787109375 0.9999084491282701 +0.22425 -0.490081787109375 0.9999084491282701 +0.224375 -0.484222412109375 0.9999084491282701 +0.2245 -0.478607177734375 0.9999084491282701 +0.224625 -0.470367431640625 0.9999084491282701 +0.22475 -0.46087646484375 0.9999084491282701 +0.224875 -0.450103759765625 0.9999084491282701 +0.225 -0.438079833984375 0.9999084491282701 +0.225125 -0.4276123046875 0.9999084491282701 +0.22525 -0.413482666015625 0.9999084491282701 +0.225375 -0.398193359375 0.9999084491282701 +0.2255 -0.3818359375 0.9999084491282701 +0.225625 -0.36444091796875 0.9999084491282701 +0.22575 -0.349761962890625 0.9999084491282701 +0.225875 -0.330596923828125 0.9999084491282701 +0.226 -0.310516357421875 0.9999084491282701 +0.226125 -0.289581298828125 0.9999084491282701 +0.22625 -0.267852783203125 0.9999084491282701 +0.226375 -0.249969482421875 0.9999084491282701 +0.2265 -0.226959228515625 0.9999084491282701 +0.226625 -0.203338623046875 0.9999084491282701 +0.22675 -0.17913818359375 0.9999084491282701 +0.226875 -0.15447998046875 0.9999084491282701 +0.227 -0.134429931640625 0.9999084491282701 +0.227125 -0.109039306640625 0.9999084491282701 +0.22725 -0.083343505859375 0.9999084491282701 +0.227375 -0.05743408203125 0.9999084491282701 +0.2275 -0.0313720703125 0.9999084491282701 +0.227625 -0.01043701171875 0.9999084491282701 0.22775 0.01568603515625 0.9999084491282701 0.227875 0.04180908203125 0.9999084491282701 0.228 0.06781005859375 0.9999084491282701 @@ -1882,69 +1882,69 @@ 0.235125 0.072998046875 0.9999084491282701 0.23525 0.047027587890625 0.9999084491282701 0.235375 0.020904541015625 0.9999084491282701 -0.2355 -0.0052490234375 0.9999084491282701 -0.235625 -0.031402587890625 0.9999084491282701 -0.23575 -0.052276611328125 0.9999084491282701 -0.235875 -0.078216552734375 0.9999084491282701 -0.236 -0.10394287109375 0.9999084491282701 -0.236125 -0.12939453125 0.9999084491282701 -0.23625 -0.154510498046875 0.9999084491282701 -0.236375 -0.174285888671875 0.9999084491282701 -0.2365 -0.198577880859375 0.9999084491282701 -0.236625 -0.222320556640625 0.9999084491282701 -0.23675 -0.245452880859375 0.9999084491282701 -0.236875 -0.26788330078125 0.9999084491282701 -0.237 -0.28533935546875 0.9999084491282701 -0.237125 -0.306427001953125 0.9999084491282701 -0.23725 -0.326690673828125 0.9999084491282701 -0.237375 -0.346038818359375 0.9999084491282701 -0.2375 -0.364471435546875 0.9999084491282701 -0.237625 -0.37847900390625 0.9999084491282701 -0.23775 -0.395050048828125 0.9999084491282701 -0.237875 -0.410552978515625 0.9999084491282701 -0.238 -0.4249267578125 0.9999084491282701 -0.238125 -0.4381103515625 0.9999084491282701 -0.23825 -0.44781494140625 0.9999084491282701 -0.238375 -0.4588623046875 0.9999084491282701 -0.2385 -0.468597412109375 0.9999084491282701 -0.238625 -0.477081298828125 0.9999084491282701 -0.23875 -0.4842529296875 0.9999084491282701 -0.238875 -0.489044189453125 0.9999084491282701 -0.239 -0.493804931640625 0.9999084491282701 -0.239125 -0.497222900390625 0.9999084491282701 -0.23925 -0.499298095703125 0.9999084491282701 -0.239375 -0.499969482421875 0.9999084491282701 -0.2395 -0.499542236328125 0.9999084491282701 -0.239625 -0.49774169921875 0.9999084491282701 -0.23975 -0.494598388671875 0.9999084491282701 -0.239875 -0.4901123046875 0.9999084491282701 -0.24 -0.4842529296875 0.9999084491282701 -0.240125 -0.4786376953125 0.9999084491282701 -0.24025 -0.47039794921875 0.9999084491282701 -0.240375 -0.460906982421875 0.9999084491282701 -0.2405 -0.45013427734375 0.9999084491282701 -0.240625 -0.4381103515625 0.9999084491282701 -0.24075 -0.427642822265625 0.9999084491282701 -0.240875 -0.41351318359375 0.9999084491282701 -0.241 -0.398223876953125 0.9999084491282701 -0.241125 -0.381866455078125 0.9999084491282701 -0.24125 -0.364471435546875 0.9999084491282701 -0.241375 -0.34979248046875 0.9999084491282701 -0.2415 -0.33062744140625 0.9999084491282701 -0.241625 -0.310546875 0.9999084491282701 -0.24175 -0.28961181640625 0.9999084491282701 -0.241875 -0.26788330078125 0.9999084491282701 -0.242 -0.25 0.9999084491282701 -0.242125 -0.22698974609375 0.9999084491282701 -0.24225 -0.203369140625 0.9999084491282701 -0.242375 -0.179168701171875 0.9999084491282701 -0.2425 -0.154510498046875 0.9999084491282701 -0.242625 -0.13446044921875 0.9999084491282701 -0.24275 -0.10906982421875 0.9999084491282701 -0.242875 -0.0833740234375 0.9999084491282701 -0.243 -0.057464599609375 0.9999084491282701 -0.243125 -0.031402587890625 0.9999084491282701 -0.24325 -0.010467529296875 0.9999084491282701 +0.2355 -0.005218505859375 0.9999084491282701 +0.235625 -0.0313720703125 0.9999084491282701 +0.23575 -0.05224609375 0.9999084491282701 +0.235875 -0.07818603515625 0.9999084491282701 +0.236 -0.103912353515625 0.9999084491282701 +0.236125 -0.129364013671875 0.9999084491282701 +0.23625 -0.15447998046875 0.9999084491282701 +0.236375 -0.17425537109375 0.9999084491282701 +0.2365 -0.19854736328125 0.9999084491282701 +0.236625 -0.2222900390625 0.9999084491282701 +0.23675 -0.24542236328125 0.9999084491282701 +0.236875 -0.267852783203125 0.9999084491282701 +0.237 -0.285308837890625 0.9999084491282701 +0.237125 -0.306396484375 0.9999084491282701 +0.23725 -0.32666015625 0.9999084491282701 +0.237375 -0.34600830078125 0.9999084491282701 +0.2375 -0.36444091796875 0.9999084491282701 +0.237625 -0.378448486328125 0.9999084491282701 +0.23775 -0.39501953125 0.9999084491282701 +0.237875 -0.4105224609375 0.9999084491282701 +0.238 -0.424896240234375 0.9999084491282701 +0.238125 -0.438079833984375 0.9999084491282701 +0.23825 -0.447784423828125 0.9999084491282701 +0.238375 -0.458831787109375 0.9999084491282701 +0.2385 -0.46856689453125 0.9999084491282701 +0.238625 -0.47705078125 0.9999084491282701 +0.23875 -0.484222412109375 0.9999084491282701 +0.238875 -0.489013671875 0.9999084491282701 +0.239 -0.4937744140625 0.9999084491282701 +0.239125 -0.4971923828125 0.9999084491282701 +0.23925 -0.499267578125 0.9999084491282701 +0.239375 -0.49993896484375 0.9999084491282701 +0.2395 -0.49951171875 0.9999084491282701 +0.239625 -0.497711181640625 0.9999084491282701 +0.23975 -0.49456787109375 0.9999084491282701 +0.239875 -0.490081787109375 0.9999084491282701 +0.24 -0.484222412109375 0.9999084491282701 +0.240125 -0.478607177734375 0.9999084491282701 +0.24025 -0.470367431640625 0.9999084491282701 +0.240375 -0.46087646484375 0.9999084491282701 +0.2405 -0.450103759765625 0.9999084491282701 +0.240625 -0.438079833984375 0.9999084491282701 +0.24075 -0.4276123046875 0.9999084491282701 +0.240875 -0.413482666015625 0.9999084491282701 +0.241 -0.398193359375 0.9999084491282701 +0.241125 -0.3818359375 0.9999084491282701 +0.24125 -0.36444091796875 0.9999084491282701 +0.241375 -0.349761962890625 0.9999084491282701 +0.2415 -0.330596923828125 0.9999084491282701 +0.241625 -0.310516357421875 0.9999084491282701 +0.24175 -0.289581298828125 0.9999084491282701 +0.241875 -0.267852783203125 0.9999084491282701 +0.242 -0.249969482421875 0.9999084491282701 +0.242125 -0.226959228515625 0.9999084491282701 +0.24225 -0.203338623046875 0.9999084491282701 +0.242375 -0.17913818359375 0.9999084491282701 +0.2425 -0.15447998046875 0.9999084491282701 +0.242625 -0.134429931640625 0.9999084491282701 +0.24275 -0.109039306640625 0.9999084491282701 +0.242875 -0.083343505859375 0.9999084491282701 +0.243 -0.05743408203125 0.9999084491282701 +0.243125 -0.0313720703125 0.9999084491282701 +0.24325 -0.01043701171875 0.9999084491282701 0.243375 0.01568603515625 0.9999084491282701 0.2435 0.04180908203125 0.9999084491282701 0.243625 0.06781005859375 0.9999084491282701 @@ -2007,42 +2007,42 @@ 0.25075 0.072998046875 0.9999084491282701 0.250875 0.047027587890625 0.9999084491282701 0.251 0.020904541015625 0.9999084491282701 -0.251125 -0.0052490234375 0.9999084491282701 -0.25125 -0.031402587890625 0.9999084491282701 -0.251375 -0.052276611328125 0.9999084491282701 -0.2515 -0.078216552734375 0.9999084491282701 -0.251625 -0.10394287109375 0.9999084491282701 -0.25175 -0.12939453125 0.9999084491282701 -0.251875 -0.154510498046875 0.9999084491282701 -0.252 -0.174285888671875 0.9999084491282701 -0.252125 -0.198577880859375 0.9999084491282701 -0.25225 -0.222320556640625 0.9999084491282701 -0.252375 -0.245452880859375 0.9999084491282701 -0.2525 -0.26788330078125 0.9999084491282701 -0.252625 -0.28533935546875 0.9999084491282701 -0.25275 -0.306427001953125 0.9999084491282701 -0.252875 -0.326690673828125 0.9999084491282701 -0.253 -0.346038818359375 0.9999084491282701 -0.253125 -0.364471435546875 0.9999084491282701 -0.25325 -0.37847900390625 0.9999084491282701 -0.253375 -0.395050048828125 0.9999084491282701 -0.2535 -0.410552978515625 0.9999084491282701 -0.253625 -0.4249267578125 0.9999084491282701 -0.2537500000000001 -0.4381103515625 0.9999084491282701 -0.253875 -0.44781494140625 0.9999084491282701 -0.254 -0.4588623046875 0.9999084491282701 -0.254125 -0.468597412109375 0.9999084491282701 -0.25425 -0.477081298828125 0.9999084491282701 -0.254375 -0.4842529296875 0.9999084491282701 -0.2545 -0.489044189453125 0.9999084491282701 -0.254625 -0.493804931640625 0.9999084491282701 -0.25475 -0.497222900390625 0.9999084491282701 -0.254875 -0.499298095703125 0.9999084491282701 -0.255 -0.499969482421875 0.9999084491282701 -0.255125 -0.499542236328125 0.9999084491282701 -0.25525 -0.49774169921875 0.9999084491282701 -0.255375 -0.494598388671875 0.9999084491282701 -0.2555 -0.4901123046875 0.9999084491282701 -0.255625 -0.4842529296875 0.9999084491282701 -0.25575 -0.4786376953125 0.9999084491282701 -0.255875 -0.47039794921875 0.9999084491282701 +0.251125 -0.005218505859375 0.9999084491282701 +0.25125 -0.0313720703125 0.9999084491282701 +0.251375 -0.05224609375 0.9999084491282701 +0.2515 -0.07818603515625 0.9999084491282701 +0.251625 -0.103912353515625 0.9999084491282701 +0.25175 -0.129364013671875 0.9999084491282701 +0.251875 -0.15447998046875 0.9999084491282701 +0.252 -0.17425537109375 0.9999084491282701 +0.252125 -0.19854736328125 0.9999084491282701 +0.25225 -0.2222900390625 0.9999084491282701 +0.252375 -0.24542236328125 0.9999084491282701 +0.2525 -0.267852783203125 0.9999084491282701 +0.252625 -0.285308837890625 0.9999084491282701 +0.25275 -0.306396484375 0.9999084491282701 +0.252875 -0.32666015625 0.9999084491282701 +0.253 -0.34600830078125 0.9999084491282701 +0.253125 -0.36444091796875 0.9999084491282701 +0.25325 -0.378448486328125 0.9999084491282701 +0.253375 -0.39501953125 0.9999084491282701 +0.2535 -0.4105224609375 0.9999084491282701 +0.253625 -0.424896240234375 0.9999084491282701 +0.2537500000000001 -0.438079833984375 0.9999084491282701 +0.253875 -0.447784423828125 0.9999084491282701 +0.254 -0.458831787109375 0.9999084491282701 +0.254125 -0.46856689453125 0.9999084491282701 +0.25425 -0.47705078125 0.9999084491282701 +0.254375 -0.484222412109375 0.9999084491282701 +0.2545 -0.489013671875 0.9999084491282701 +0.254625 -0.4937744140625 0.9999084491282701 +0.25475 -0.4971923828125 0.9999084491282701 +0.254875 -0.499267578125 0.9999084491282701 +0.255 -0.49993896484375 0.9999084491282701 +0.255125 -0.49951171875 0.9999084491282701 +0.25525 -0.497711181640625 0.9999084491282701 +0.255375 -0.49456787109375 0.9999084491282701 +0.2555 -0.490081787109375 0.9999084491282701 +0.255625 -0.484222412109375 0.9999084491282701 +0.25575 -0.478607177734375 0.9999084491282701 +0.255875 -0.470367431640625 0.9999084491282701 diff --git a/tests/circuitpython/synth_note_envelope.py.exp b/tests/circuitpython/synth_note_envelope.py.exp index c490380cb3118..d4c7d0adc2462 100644 --- a/tests/circuitpython/synth_note_envelope.py.exp +++ b/tests/circuitpython/synth_note_envelope.py.exp @@ -29,37 +29,37 @@ 0.0035 0.034515380859375 0.302396875 0.003625 0.0189208984375 0.302396875 0.00375 0.004730224609375 0.302396875 -0.003875 -0.011077880859375 0.302396875 -0.004 -0.025238037109375 0.302396875 -0.004125 -0.040679931640625 0.302396875 -0.00425 -0.0556640625 0.302396875 -0.004375000000000001 -0.068634033203125 0.302396875 -0.004500000000000001 -0.082366943359375 0.302396875 -0.004625 -0.09393310546875 0.302396875 -0.00475 -0.10577392578125 0.302396875 -0.004875 -0.116485595703125 0.302396875 -0.005 -0.12506103515625 0.302396875 -0.005125000000000001 -0.13323974609375 0.302396875 -0.00525 -0.139373779296875 0.302396875 -0.005375000000000001 -0.144744873046875 0.302396875 -0.005499999999999999 -0.148529052734375 0.302396875 -0.005625 -0.1505126953125 0.302396875 -0.00575 -0.15118408203125 0.302396875 -0.005874999999999999 -0.150360107421875 0.302396875 -0.006 -0.14788818359375 0.302396875 -0.006125 -0.143798828125 0.302396875 -0.00625 -0.138763427734375 0.302396875 -0.006375 -0.1317138671875 0.302396875 -0.0065 -0.1241455078125 0.302396875 -0.006625000000000001 -0.11444091796875 0.302396875 -0.00675 -0.103515625 0.302396875 -0.006875 -0.092681884765625 0.302396875 -0.007000000000000001 -0.079681396484375 0.302396875 -0.007125000000000002 -0.067230224609375 0.302396875 -0.007250000000000001 -0.052703857421875 0.302396875 -0.007375 -0.03759765625 0.302396875 -0.0075 -0.023651123046875 0.302396875 -0.007625 -0.0079345703125 0.302396875 +0.003875 -0.01104736328125 0.302396875 +0.004 -0.02520751953125 0.302396875 +0.004125 -0.0406494140625 0.302396875 +0.00425 -0.055633544921875 0.302396875 +0.004375000000000001 -0.068603515625 0.302396875 +0.004500000000000001 -0.08233642578125 0.302396875 +0.004625 -0.093902587890625 0.302396875 +0.00475 -0.105743408203125 0.302396875 +0.004875 -0.116455078125 0.302396875 +0.005 -0.125030517578125 0.302396875 +0.005125000000000001 -0.133209228515625 0.302396875 +0.00525 -0.13934326171875 0.302396875 +0.005375000000000001 -0.14471435546875 0.302396875 +0.005499999999999999 -0.14849853515625 0.302396875 +0.005625 -0.150482177734375 0.302396875 +0.00575 -0.151153564453125 0.302396875 +0.005874999999999999 -0.15032958984375 0.302396875 +0.006 -0.147857666015625 0.302396875 +0.006125 -0.143768310546875 0.302396875 +0.00625 -0.13873291015625 0.302396875 +0.006375 -0.131683349609375 0.302396875 +0.0065 -0.124114990234375 0.302396875 +0.006625000000000001 -0.114410400390625 0.302396875 +0.00675 -0.103485107421875 0.302396875 +0.006875 -0.0926513671875 0.302396875 +0.007000000000000001 -0.07965087890625 0.302396875 +0.007125000000000002 -0.06719970703125 0.302396875 +0.007250000000000001 -0.05267333984375 0.302396875 +0.007375 -0.037567138671875 0.302396875 +0.0075 -0.02362060546875 0.302396875 +0.007625 -0.007904052734375 0.302396875 0.00775 0.006317138671875 0.302396875 0.007875 0.022064208984375 0.302396875 0.008 0.037567138671875 0.302396875 @@ -91,37 +91,37 @@ 0.01125 0.042144775390625 0.302396875 0.011375 0.026763916015625 0.302396875 0.0115 0.01263427734375 0.302396875 -0.011625 -0.003173828125 0.302396875 -0.01175 -0.018951416015625 0.302396875 -0.011875 -0.032989501953125 0.302396875 -0.012 -0.048248291015625 0.302396875 -0.012125 -0.061492919921875 0.302396875 -0.01225 -0.075592041015625 0.302396875 -0.012375 -0.0888671875 0.302396875 -0.0125 -0.100006103515625 0.302396875 -0.012625 -0.111297607421875 0.302396875 -0.01275 -0.12042236328125 0.302396875 -0.012875 -0.12933349609375 0.302396875 -0.013 -0.136810302734375 0.302396875 -0.013125 -0.142242431640625 0.302396875 -0.01325 -0.146820068359375 0.302396875 -0.013375 -0.149566650390625 0.302396875 -0.0135 -0.15106201171875 0.302396875 -0.013625 -0.150909423828125 0.302396875 -0.01375 -0.149322509765625 0.302396875 -0.013875 -0.146026611328125 0.302396875 -0.014 -0.1417236328125 0.302396875 -0.014125 -0.13543701171875 0.302396875 -0.01425 -0.127655029296875 0.302396875 -0.014375 -0.119476318359375 0.302396875 -0.0145 -0.109130859375 0.302396875 -0.014625 -0.098785400390625 0.302396875 -0.01475 -0.0863037109375 0.302396875 -0.014875 -0.072845458984375 0.302396875 -0.015 -0.06005859375 0.302396875 -0.015125 -0.04522705078125 0.302396875 -0.01525 -0.03143310546875 0.302396875 -0.015375 -0.01580810546875 0.302396875 +0.011625 -0.003143310546875 0.302396875 +0.01175 -0.0189208984375 0.302396875 +0.011875 -0.032958984375 0.302396875 +0.012 -0.0482177734375 0.302396875 +0.012125 -0.06146240234375 0.302396875 +0.01225 -0.0755615234375 0.302396875 +0.012375 -0.088836669921875 0.302396875 +0.0125 -0.0999755859375 0.302396875 +0.012625 -0.11126708984375 0.302396875 +0.01275 -0.120391845703125 0.302396875 +0.012875 -0.129302978515625 0.302396875 +0.013 -0.13677978515625 0.302396875 +0.013125 -0.1422119140625 0.302396875 +0.01325 -0.14678955078125 0.302396875 +0.013375 -0.1495361328125 0.302396875 +0.0135 -0.151031494140625 0.302396875 +0.013625 -0.15087890625 0.302396875 +0.01375 -0.1492919921875 0.302396875 +0.013875 -0.14599609375 0.302396875 +0.014 -0.141693115234375 0.302396875 +0.014125 -0.135406494140625 0.302396875 +0.01425 -0.12762451171875 0.302396875 +0.014375 -0.11944580078125 0.302396875 +0.0145 -0.109100341796875 0.302396875 +0.014625 -0.0987548828125 0.302396875 +0.01475 -0.086273193359375 0.302396875 +0.014875 -0.07281494140625 0.302396875 +0.015 -0.060028076171875 0.302396875 +0.015125 -0.045196533203125 0.302396875 +0.01525 -0.031402587890625 0.302396875 +0.015375 -0.015777587890625 0.302396875 0.0155 0.0 0.302396875 0.015625 0.01422119140625 0.302396875 0.01575 0.029876708984375 0.302396875 @@ -154,37 +154,37 @@ 0.019125 0.034515380859375 0.302396875 0.01925 0.0189208984375 0.302396875 0.019375 0.004730224609375 0.302396875 -0.0195 -0.011077880859375 0.302396875 -0.019625 -0.025238037109375 0.302396875 -0.01975 -0.040679931640625 0.302396875 -0.019875 -0.0556640625 0.302396875 -0.02 -0.068634033203125 0.302396875 -0.020125 -0.082366943359375 0.302396875 -0.02025 -0.09393310546875 0.302396875 -0.020375 -0.10577392578125 0.302396875 -0.0205 -0.116485595703125 0.302396875 -0.020625 -0.12506103515625 0.302396875 -0.02075 -0.13323974609375 0.302396875 -0.020875 -0.139373779296875 0.302396875 -0.021 -0.144744873046875 0.302396875 -0.021125 -0.148529052734375 0.302396875 -0.02125 -0.1505126953125 0.302396875 -0.021375 -0.15118408203125 0.302396875 -0.0215 -0.150360107421875 0.302396875 -0.021625 -0.14788818359375 0.302396875 -0.02175 -0.143798828125 0.302396875 -0.021875 -0.138763427734375 0.302396875 -0.022 -0.1317138671875 0.302396875 -0.022125 -0.1241455078125 0.302396875 -0.02225 -0.11444091796875 0.302396875 -0.022375 -0.103515625 0.302396875 -0.0225 -0.092681884765625 0.302396875 -0.022625 -0.079681396484375 0.302396875 -0.02275 -0.067230224609375 0.302396875 -0.022875 -0.052703857421875 0.302396875 -0.023 -0.03759765625 0.302396875 -0.023125 -0.023651123046875 0.302396875 -0.02325 -0.0079345703125 0.302396875 +0.0195 -0.01104736328125 0.302396875 +0.019625 -0.02520751953125 0.302396875 +0.01975 -0.0406494140625 0.302396875 +0.019875 -0.055633544921875 0.302396875 +0.02 -0.068603515625 0.302396875 +0.020125 -0.08233642578125 0.302396875 +0.02025 -0.093902587890625 0.302396875 +0.020375 -0.105743408203125 0.302396875 +0.0205 -0.116455078125 0.302396875 +0.020625 -0.125030517578125 0.302396875 +0.02075 -0.133209228515625 0.302396875 +0.020875 -0.13934326171875 0.302396875 +0.021 -0.14471435546875 0.302396875 +0.021125 -0.14849853515625 0.302396875 +0.02125 -0.150482177734375 0.302396875 +0.021375 -0.151153564453125 0.302396875 +0.0215 -0.15032958984375 0.302396875 +0.021625 -0.147857666015625 0.302396875 +0.02175 -0.143768310546875 0.302396875 +0.021875 -0.13873291015625 0.302396875 +0.022 -0.131683349609375 0.302396875 +0.022125 -0.124114990234375 0.302396875 +0.02225 -0.114410400390625 0.302396875 +0.022375 -0.103485107421875 0.302396875 +0.0225 -0.0926513671875 0.302396875 +0.022625 -0.07965087890625 0.302396875 +0.02275 -0.06719970703125 0.302396875 +0.022875 -0.05267333984375 0.302396875 +0.023 -0.037567138671875 0.302396875 +0.023125 -0.02362060546875 0.302396875 +0.02325 -0.007904052734375 0.302396875 0.023375 0.006317138671875 0.302396875 0.0235 0.022064208984375 0.302396875 0.023625 0.037567138671875 0.302396875 @@ -216,37 +216,37 @@ 0.026875 0.042144775390625 0.302396875 0.027 0.026763916015625 0.302396875 0.027125 0.01263427734375 0.302396875 -0.02725 -0.003173828125 0.302396875 -0.027375 -0.018951416015625 0.302396875 -0.0275 -0.032989501953125 0.302396875 -0.027625 -0.048248291015625 0.302396875 -0.02775 -0.061492919921875 0.302396875 -0.027875 -0.075592041015625 0.302396875 -0.028 -0.0888671875 0.302396875 -0.028125 -0.100006103515625 0.302396875 -0.02825 -0.111297607421875 0.302396875 -0.028375 -0.12042236328125 0.302396875 -0.02850000000000001 -0.12933349609375 0.302396875 -0.028625 -0.136810302734375 0.302396875 -0.02875 -0.142242431640625 0.302396875 -0.028875 -0.146820068359375 0.302396875 -0.029 -0.149566650390625 0.302396875 -0.029125 -0.15106201171875 0.302396875 -0.02925 -0.150909423828125 0.302396875 -0.029375 -0.149322509765625 0.302396875 -0.0295 -0.146026611328125 0.302396875 -0.029625 -0.1417236328125 0.302396875 -0.02975000000000001 -0.13543701171875 0.302396875 -0.029875 -0.127655029296875 0.302396875 -0.03 -0.119476318359375 0.302396875 -0.030125 -0.109130859375 0.302396875 -0.03025 -0.098785400390625 0.302396875 -0.030375 -0.0863037109375 0.302396875 -0.0305 -0.072845458984375 0.302396875 -0.030625 -0.06005859375 0.302396875 -0.03075 -0.04522705078125 0.302396875 -0.03087499999999999 -0.03143310546875 0.302396875 -0.031 -0.01580810546875 0.302396875 +0.02725 -0.003143310546875 0.302396875 +0.027375 -0.0189208984375 0.302396875 +0.0275 -0.032958984375 0.302396875 +0.027625 -0.0482177734375 0.302396875 +0.02775 -0.06146240234375 0.302396875 +0.027875 -0.0755615234375 0.302396875 +0.028 -0.088836669921875 0.302396875 +0.028125 -0.0999755859375 0.302396875 +0.02825 -0.11126708984375 0.302396875 +0.028375 -0.120391845703125 0.302396875 +0.02850000000000001 -0.129302978515625 0.302396875 +0.028625 -0.13677978515625 0.302396875 +0.02875 -0.1422119140625 0.302396875 +0.028875 -0.14678955078125 0.302396875 +0.029 -0.1495361328125 0.302396875 +0.029125 -0.151031494140625 0.302396875 +0.02925 -0.15087890625 0.302396875 +0.029375 -0.1492919921875 0.302396875 +0.0295 -0.14599609375 0.302396875 +0.029625 -0.141693115234375 0.302396875 +0.02975000000000001 -0.135406494140625 0.302396875 +0.029875 -0.12762451171875 0.302396875 +0.03 -0.11944580078125 0.302396875 +0.030125 -0.109100341796875 0.302396875 +0.03025 -0.0987548828125 0.302396875 +0.030375 -0.086273193359375 0.302396875 +0.0305 -0.07281494140625 0.302396875 +0.030625 -0.060028076171875 0.302396875 +0.03075 -0.045196533203125 0.302396875 +0.03087499999999999 -0.031402587890625 0.302396875 +0.031 -0.015777587890625 0.302396875 0.031125 0.0 0.302396875 0.03125 0.01422119140625 0.302396875 0.031375 0.029876708984375 0.302396875 @@ -279,37 +279,37 @@ 0.03475000000000001 0.04620361328125 0.4047937500000001 0.034875 0.02532958984375 0.4047937500000001 0.035 0.00634765625 0.4047937500000001 -0.03512500000000001 -0.01483154296875 0.4047937500000001 -0.03525 -0.03375244140625 0.4047937500000001 -0.035375 -0.054443359375 0.4047937500000001 -0.0355 -0.07452392578125 0.4047937500000001 -0.03562500000000001 -0.091888427734375 0.4047937500000001 -0.03575 -0.1102294921875 0.4047937500000001 -0.035875 -0.125701904296875 0.4047937500000001 -0.03600000000000001 -0.1416015625 0.4047937500000001 -0.036125 -0.15594482421875 0.4047937500000001 -0.03625 -0.167388916015625 0.4047937500000001 -0.036375 -0.178375244140625 0.4047937500000001 -0.0365 -0.18658447265625 0.4047937500000001 -0.036625 -0.193756103515625 0.4047937500000001 -0.03675 -0.19879150390625 0.4047937500000001 -0.036875 -0.20147705078125 0.4047937500000001 -0.037 -0.202362060546875 0.4047937500000001 -0.03712499999999999 -0.201263427734375 0.4047937500000001 -0.03725 -0.197967529296875 0.4047937500000001 -0.037375 -0.192474365234375 0.4047937500000001 -0.0375 -0.18572998046875 0.4047937500000001 -0.037625 -0.17633056640625 0.4047937500000001 -0.03775 -0.16619873046875 0.4047937500000001 -0.037875 -0.1531982421875 0.4047937500000001 -0.038 -0.1385498046875 0.4047937500000001 -0.038125 -0.124053955078125 0.4047937500000001 -0.03825 -0.106658935546875 0.4047937500000001 -0.038375 -0.089996337890625 0.4047937500000001 -0.0385 -0.070556640625 0.4047937500000001 -0.038625 -0.050323486328125 0.4047937500000001 -0.03875 -0.03167724609375 0.4047937500000001 -0.038875 -0.010589599609375 0.4047937500000001 +0.03512500000000001 -0.014801025390625 0.4047937500000001 +0.03525 -0.033721923828125 0.4047937500000001 +0.035375 -0.054412841796875 0.4047937500000001 +0.0355 -0.074493408203125 0.4047937500000001 +0.03562500000000001 -0.09185791015625 0.4047937500000001 +0.03575 -0.110198974609375 0.4047937500000001 +0.035875 -0.12567138671875 0.4047937500000001 +0.03600000000000001 -0.141571044921875 0.4047937500000001 +0.036125 -0.155914306640625 0.4047937500000001 +0.03625 -0.1673583984375 0.4047937500000001 +0.036375 -0.1783447265625 0.4047937500000001 +0.0365 -0.186553955078125 0.4047937500000001 +0.036625 -0.1937255859375 0.4047937500000001 +0.03675 -0.198760986328125 0.4047937500000001 +0.036875 -0.201446533203125 0.4047937500000001 +0.037 -0.20233154296875 0.4047937500000001 +0.03712499999999999 -0.20123291015625 0.4047937500000001 +0.03725 -0.19793701171875 0.4047937500000001 +0.037375 -0.19244384765625 0.4047937500000001 +0.0375 -0.185699462890625 0.4047937500000001 +0.037625 -0.176300048828125 0.4047937500000001 +0.03775 -0.166168212890625 0.4047937500000001 +0.037875 -0.153167724609375 0.4047937500000001 +0.038 -0.138519287109375 0.4047937500000001 +0.038125 -0.1240234375 0.4047937500000001 +0.03825 -0.10662841796875 0.4047937500000001 +0.038375 -0.0899658203125 0.4047937500000001 +0.0385 -0.070526123046875 0.4047937500000001 +0.038625 -0.05029296875 0.4047937500000001 +0.03875 -0.031646728515625 0.4047937500000001 +0.038875 -0.01055908203125 0.4047937500000001 0.039 0.008453369140625 0.4047937500000001 0.039125 0.029541015625 0.4047937500000001 0.03925 0.05029296875 0.4047937500000001 @@ -341,37 +341,37 @@ 0.0425 0.056427001953125 0.4047937500000001 0.042625 0.03582763671875 0.4047937500000001 0.04275 0.01690673828125 0.4047937500000001 -0.04287500000000001 -0.004241943359375 0.4047937500000001 -0.04300000000000001 -0.025360107421875 0.4047937500000001 -0.043125 -0.044158935546875 0.4047937500000001 -0.04325 -0.0645751953125 0.4047937500000001 -0.043375 -0.08233642578125 0.4047937500000001 -0.04350000000000001 -0.1011962890625 0.4047937500000001 -0.04362500000000001 -0.11895751953125 0.4047937500000001 -0.04375000000000001 -0.13385009765625 0.4047937500000001 -0.043875 -0.14898681640625 0.4047937500000001 -0.04399999999999999 -0.16119384765625 0.4047937500000001 -0.044125 -0.173126220703125 0.4047937500000001 -0.04425 -0.183135986328125 0.4047937500000001 -0.044375 -0.1904296875 0.4047937500000001 -0.04449999999999999 -0.196533203125 0.4047937500000001 -0.04462499999999999 -0.200225830078125 0.4047937500000001 -0.04475 -0.20220947265625 0.4047937500000001 -0.044875 -0.201995849609375 0.4047937500000001 -0.045 -0.19989013671875 0.4047937500000001 -0.045125 -0.19549560546875 0.4047937500000001 -0.04525 -0.189697265625 0.4047937500000001 -0.045375 -0.1812744140625 0.4047937500000001 -0.0455 -0.170867919921875 0.4047937500000001 -0.045625 -0.159912109375 0.4047937500000001 -0.04575 -0.146087646484375 0.4047937500000001 -0.045875 -0.132232666015625 0.4047937500000001 -0.046 -0.115509033203125 0.4047937500000001 -0.046125 -0.097503662109375 0.4047937500000001 -0.04625 -0.08038330078125 0.4047937500000001 -0.046375 -0.060516357421875 0.4047937500000001 -0.04649999999999999 -0.042083740234375 0.4047937500000001 -0.046625 -0.02117919921875 0.4047937500000001 +0.04287500000000001 -0.00421142578125 0.4047937500000001 +0.04300000000000001 -0.02532958984375 0.4047937500000001 +0.043125 -0.04412841796875 0.4047937500000001 +0.04325 -0.064544677734375 0.4047937500000001 +0.043375 -0.082305908203125 0.4047937500000001 +0.04350000000000001 -0.101165771484375 0.4047937500000001 +0.04362500000000001 -0.118927001953125 0.4047937500000001 +0.04375000000000001 -0.133819580078125 0.4047937500000001 +0.043875 -0.148956298828125 0.4047937500000001 +0.04399999999999999 -0.161163330078125 0.4047937500000001 +0.044125 -0.173095703125 0.4047937500000001 +0.04425 -0.18310546875 0.4047937500000001 +0.044375 -0.190399169921875 0.4047937500000001 +0.04449999999999999 -0.196502685546875 0.4047937500000001 +0.04462499999999999 -0.2001953125 0.4047937500000001 +0.04475 -0.202178955078125 0.4047937500000001 +0.044875 -0.20196533203125 0.4047937500000001 +0.045 -0.199859619140625 0.4047937500000001 +0.045125 -0.195465087890625 0.4047937500000001 +0.04525 -0.189666748046875 0.4047937500000001 +0.045375 -0.181243896484375 0.4047937500000001 +0.0455 -0.17083740234375 0.4047937500000001 +0.045625 -0.159881591796875 0.4047937500000001 +0.04575 -0.14605712890625 0.4047937500000001 +0.045875 -0.1322021484375 0.4047937500000001 +0.046 -0.115478515625 0.4047937500000001 +0.046125 -0.09747314453125 0.4047937500000001 +0.04625 -0.080352783203125 0.4047937500000001 +0.046375 -0.06048583984375 0.4047937500000001 +0.04649999999999999 -0.04205322265625 0.4047937500000001 +0.046625 -0.021148681640625 0.4047937500000001 0.04675000000000001 0.0 0.4047937500000001 0.046875 0.019012451171875 0.4047937500000001 0.04699999999999999 0.03997802734375 0.4047937500000001 @@ -404,37 +404,37 @@ 0.05037500000000001 0.04620361328125 0.4047937500000001 0.0505 0.02532958984375 0.4047937500000001 0.05062500000000001 0.00634765625 0.4047937500000001 -0.05075000000000001 -0.01483154296875 0.4047937500000001 -0.050875 -0.03375244140625 0.4047937500000001 -0.051 -0.054443359375 0.4047937500000001 -0.051125 -0.07452392578125 0.4047937500000001 -0.05125000000000001 -0.091888427734375 0.4047937500000001 -0.051375 -0.1102294921875 0.4047937500000001 -0.0515 -0.125701904296875 0.4047937500000001 -0.05162500000000001 -0.1416015625 0.4047937500000001 -0.05175000000000001 -0.15594482421875 0.4047937500000001 -0.051875 -0.167388916015625 0.4047937500000001 -0.052 -0.178375244140625 0.4047937500000001 -0.052125 -0.18658447265625 0.4047937500000001 -0.05225 -0.193756103515625 0.4047937500000001 -0.05237499999999999 -0.19879150390625 0.4047937500000001 -0.0525 -0.20147705078125 0.4047937500000001 -0.052625 -0.202362060546875 0.4047937500000001 -0.05274999999999999 -0.201263427734375 0.4047937500000001 -0.052875 -0.197967529296875 0.4047937500000001 -0.05300000000000001 -0.192474365234375 0.4047937500000001 -0.053125 -0.18572998046875 0.4047937500000001 -0.05324999999999999 -0.17633056640625 0.4047937500000001 -0.05337499999999999 -0.16619873046875 0.4047937500000001 -0.05350000000000001 -0.1531982421875 0.4047937500000001 -0.053625 -0.1385498046875 0.4047937500000001 -0.05375 -0.124053955078125 0.4047937500000001 -0.05387499999999999 -0.106658935546875 0.4047937500000001 -0.054 -0.089996337890625 0.4047937500000001 -0.054125 -0.070556640625 0.4047937500000001 -0.05425 -0.050323486328125 0.4047937500000001 -0.054375 -0.03167724609375 0.4047937500000001 -0.0545 -0.010589599609375 0.4047937500000001 +0.05075000000000001 -0.014801025390625 0.4047937500000001 +0.050875 -0.033721923828125 0.4047937500000001 +0.051 -0.054412841796875 0.4047937500000001 +0.051125 -0.074493408203125 0.4047937500000001 +0.05125000000000001 -0.09185791015625 0.4047937500000001 +0.051375 -0.110198974609375 0.4047937500000001 +0.0515 -0.12567138671875 0.4047937500000001 +0.05162500000000001 -0.141571044921875 0.4047937500000001 +0.05175000000000001 -0.155914306640625 0.4047937500000001 +0.051875 -0.1673583984375 0.4047937500000001 +0.052 -0.1783447265625 0.4047937500000001 +0.052125 -0.186553955078125 0.4047937500000001 +0.05225 -0.1937255859375 0.4047937500000001 +0.05237499999999999 -0.198760986328125 0.4047937500000001 +0.0525 -0.201446533203125 0.4047937500000001 +0.052625 -0.20233154296875 0.4047937500000001 +0.05274999999999999 -0.20123291015625 0.4047937500000001 +0.052875 -0.19793701171875 0.4047937500000001 +0.05300000000000001 -0.19244384765625 0.4047937500000001 +0.053125 -0.185699462890625 0.4047937500000001 +0.05324999999999999 -0.176300048828125 0.4047937500000001 +0.05337499999999999 -0.166168212890625 0.4047937500000001 +0.05350000000000001 -0.153167724609375 0.4047937500000001 +0.053625 -0.138519287109375 0.4047937500000001 +0.05375 -0.1240234375 0.4047937500000001 +0.05387499999999999 -0.10662841796875 0.4047937500000001 +0.054 -0.0899658203125 0.4047937500000001 +0.054125 -0.070526123046875 0.4047937500000001 +0.05425 -0.05029296875 0.4047937500000001 +0.054375 -0.031646728515625 0.4047937500000001 +0.0545 -0.01055908203125 0.4047937500000001 0.054625 0.008453369140625 0.4047937500000001 0.05475 0.029541015625 0.4047937500000001 0.054875 0.05029296875 0.4047937500000001 @@ -466,37 +466,37 @@ 0.058125 0.056427001953125 0.4047937500000001 0.05825 0.03582763671875 0.4047937500000001 0.058375 0.01690673828125 0.4047937500000001 -0.05850000000000001 -0.004241943359375 0.4047937500000001 -0.05862500000000001 -0.025360107421875 0.4047937500000001 -0.05875 -0.044158935546875 0.4047937500000001 -0.058875 -0.0645751953125 0.4047937500000001 -0.059 -0.08233642578125 0.4047937500000001 -0.05912500000000001 -0.1011962890625 0.4047937500000001 -0.05925000000000001 -0.11895751953125 0.4047937500000001 -0.059375 -0.13385009765625 0.4047937500000001 -0.05950000000000001 -0.14898681640625 0.4047937500000001 -0.059625 -0.16119384765625 0.4047937500000001 -0.05975000000000001 -0.173126220703125 0.4047937500000001 -0.059875 -0.183135986328125 0.4047937500000001 -0.06 -0.1904296875 0.4047937500000001 -0.06012499999999999 -0.196533203125 0.4047937500000001 -0.06025 -0.200225830078125 0.4047937500000001 -0.060375 -0.20220947265625 0.4047937500000001 -0.0605 -0.201995849609375 0.4047937500000001 -0.060625 -0.19989013671875 0.4047937500000001 -0.06074999999999999 -0.19549560546875 0.4047937500000001 -0.060875 -0.189697265625 0.4047937500000001 -0.061 -0.1812744140625 0.4047937500000001 -0.061125 -0.170867919921875 0.4047937500000001 -0.06125 -0.159912109375 0.4047937500000001 -0.061375 -0.146087646484375 0.4047937500000001 -0.0615 -0.132232666015625 0.4047937500000001 -0.061625 -0.115509033203125 0.4047937500000001 -0.06174999999999999 -0.097503662109375 0.4047937500000001 -0.061875 -0.08038330078125 0.4047937500000001 -0.062 -0.060516357421875 0.4047937500000001 -0.06212499999999999 -0.042083740234375 0.4047937500000001 -0.06225000000000001 -0.02117919921875 0.4047937500000001 +0.05850000000000001 -0.00421142578125 0.4047937500000001 +0.05862500000000001 -0.02532958984375 0.4047937500000001 +0.05875 -0.04412841796875 0.4047937500000001 +0.058875 -0.064544677734375 0.4047937500000001 +0.059 -0.082305908203125 0.4047937500000001 +0.05912500000000001 -0.101165771484375 0.4047937500000001 +0.05925000000000001 -0.118927001953125 0.4047937500000001 +0.059375 -0.133819580078125 0.4047937500000001 +0.05950000000000001 -0.148956298828125 0.4047937500000001 +0.059625 -0.161163330078125 0.4047937500000001 +0.05975000000000001 -0.173095703125 0.4047937500000001 +0.059875 -0.18310546875 0.4047937500000001 +0.06 -0.190399169921875 0.4047937500000001 +0.06012499999999999 -0.196502685546875 0.4047937500000001 +0.06025 -0.2001953125 0.4047937500000001 +0.060375 -0.202178955078125 0.4047937500000001 +0.0605 -0.20196533203125 0.4047937500000001 +0.060625 -0.199859619140625 0.4047937500000001 +0.06074999999999999 -0.195465087890625 0.4047937500000001 +0.060875 -0.189666748046875 0.4047937500000001 +0.061 -0.181243896484375 0.4047937500000001 +0.061125 -0.17083740234375 0.4047937500000001 +0.06125 -0.159881591796875 0.4047937500000001 +0.061375 -0.14605712890625 0.4047937500000001 +0.0615 -0.1322021484375 0.4047937500000001 +0.061625 -0.115478515625 0.4047937500000001 +0.06174999999999999 -0.09747314453125 0.4047937500000001 +0.061875 -0.080352783203125 0.4047937500000001 +0.062 -0.06048583984375 0.4047937500000001 +0.06212499999999999 -0.04205322265625 0.4047937500000001 +0.06225000000000001 -0.021148681640625 0.4047937500000001 0.06237500000000001 0.0 0.4047937500000001 0.0625 0.019012451171875 0.4047937500000001 0.06262499999999999 0.03997802734375 0.4047937500000001 @@ -529,37 +529,37 @@ 0.06600000000000001 0.057891845703125 0.507190625 0.066125 0.031768798828125 0.507190625 0.06625000000000001 0.0079345703125 0.507190625 -0.06637500000000001 -0.018585205078125 0.507190625 -0.0665 -0.04229736328125 0.507190625 -0.066625 -0.068206787109375 0.507190625 -0.06675 -0.093353271484375 0.507190625 -0.06687500000000001 -0.115142822265625 0.507190625 -0.067 -0.13812255859375 0.507190625 -0.067125 -0.15753173828125 0.507190625 -0.06725000000000001 -0.17742919921875 0.507190625 -0.06737500000000001 -0.195404052734375 0.507190625 -0.0675 -0.209747314453125 0.507190625 -0.067625 -0.223480224609375 0.507190625 -0.06775 -0.2337646484375 0.507190625 -0.06787500000000001 -0.242767333984375 0.507190625 -0.06800000000000001 -0.24908447265625 0.507190625 -0.068125 -0.252471923828125 0.507190625 -0.06825000000000001 -0.253570556640625 0.507190625 -0.068375 -0.252197265625 0.507190625 -0.06850000000000001 -0.248046875 0.507190625 -0.06862500000000001 -0.241180419921875 0.507190625 -0.06875 -0.23272705078125 0.507190625 -0.06887500000000001 -0.220947265625 0.507190625 -0.069 -0.208221435546875 0.507190625 -0.06912500000000001 -0.19195556640625 0.507190625 -0.06925000000000001 -0.173583984375 0.507190625 -0.06937500000000001 -0.155426025390625 0.507190625 -0.06950000000000001 -0.133636474609375 0.507190625 -0.069625 -0.112762451171875 0.507190625 -0.06975 -0.088409423828125 0.507190625 -0.06987500000000001 -0.063079833984375 0.507190625 -0.07000000000000001 -0.0396728515625 0.507190625 -0.070125 -0.013275146484375 0.507190625 +0.06637500000000001 -0.0185546875 0.507190625 +0.0665 -0.042266845703125 0.507190625 +0.066625 -0.06817626953125 0.507190625 +0.06675 -0.09332275390625 0.507190625 +0.06687500000000001 -0.1151123046875 0.507190625 +0.067 -0.138092041015625 0.507190625 +0.067125 -0.157501220703125 0.507190625 +0.06725000000000001 -0.177398681640625 0.507190625 +0.06737500000000001 -0.19537353515625 0.507190625 +0.0675 -0.209716796875 0.507190625 +0.067625 -0.22344970703125 0.507190625 +0.06775 -0.233734130859375 0.507190625 +0.06787500000000001 -0.24273681640625 0.507190625 +0.06800000000000001 -0.249053955078125 0.507190625 +0.068125 -0.25244140625 0.507190625 +0.06825000000000001 -0.2535400390625 0.507190625 +0.068375 -0.252166748046875 0.507190625 +0.06850000000000001 -0.248016357421875 0.507190625 +0.06862500000000001 -0.24114990234375 0.507190625 +0.06875 -0.232696533203125 0.507190625 +0.06887500000000001 -0.220916748046875 0.507190625 +0.069 -0.20819091796875 0.507190625 +0.06912500000000001 -0.191925048828125 0.507190625 +0.06925000000000001 -0.173553466796875 0.507190625 +0.06937500000000001 -0.1553955078125 0.507190625 +0.06950000000000001 -0.13360595703125 0.507190625 +0.069625 -0.11273193359375 0.507190625 +0.06975 -0.08837890625 0.507190625 +0.06987500000000001 -0.06304931640625 0.507190625 +0.07000000000000001 -0.039642333984375 0.507190625 +0.070125 -0.01324462890625 0.507190625 0.07025000000000001 0.010589599609375 0.507190625 0.07037500000000001 0.037017822265625 0.507190625 0.07050000000000001 0.06304931640625 0.507190625 @@ -591,37 +591,37 @@ 0.07374999999999999 0.07073974609375 0.507190625 0.073875 0.044891357421875 0.507190625 0.074 0.021209716796875 0.507190625 -0.074125 -0.00531005859375 0.507190625 -0.07424999999999999 -0.03179931640625 0.507190625 -0.07437499999999999 -0.055328369140625 0.507190625 -0.0745 -0.080902099609375 0.507190625 -0.07462499999999999 -0.1031494140625 0.507190625 -0.07475 -0.126800537109375 0.507190625 -0.07487500000000001 -0.1490478515625 0.507190625 -0.075 -0.167694091796875 0.507190625 -0.07512499999999999 -0.186676025390625 0.507190625 -0.07524999999999999 -0.201995849609375 0.507190625 -0.075375 -0.2169189453125 0.507190625 -0.0755 -0.229461669921875 0.507190625 -0.075625 -0.23858642578125 0.507190625 -0.07574999999999999 -0.24627685546875 0.507190625 -0.075875 -0.2508544921875 0.507190625 -0.076 -0.25335693359375 0.507190625 -0.076125 -0.253082275390625 0.507190625 -0.07625 -0.250457763671875 0.507190625 -0.07637499999999999 -0.24493408203125 0.507190625 -0.0765 -0.2376708984375 0.507190625 -0.076625 -0.227142333984375 0.507190625 -0.07675 -0.214111328125 0.507190625 -0.076875 -0.20037841796875 0.507190625 -0.077 -0.18304443359375 0.507190625 -0.077125 -0.16571044921875 0.507190625 -0.07725 -0.144744873046875 0.507190625 -0.07737499999999999 -0.122161865234375 0.507190625 -0.0775 -0.1007080078125 0.507190625 -0.077625 -0.075836181640625 0.507190625 -0.07774999999999999 -0.052734375 0.507190625 -0.07787500000000001 -0.026519775390625 0.507190625 +0.074125 -0.005279541015625 0.507190625 +0.07424999999999999 -0.031768798828125 0.507190625 +0.07437499999999999 -0.0552978515625 0.507190625 +0.0745 -0.08087158203125 0.507190625 +0.07462499999999999 -0.103118896484375 0.507190625 +0.07475 -0.12677001953125 0.507190625 +0.07487500000000001 -0.149017333984375 0.507190625 +0.075 -0.16766357421875 0.507190625 +0.07512499999999999 -0.1866455078125 0.507190625 +0.07524999999999999 -0.20196533203125 0.507190625 +0.075375 -0.216888427734375 0.507190625 +0.0755 -0.22943115234375 0.507190625 +0.075625 -0.238555908203125 0.507190625 +0.07574999999999999 -0.246246337890625 0.507190625 +0.075875 -0.250823974609375 0.507190625 +0.076 -0.253326416015625 0.507190625 +0.076125 -0.2530517578125 0.507190625 +0.07625 -0.25042724609375 0.507190625 +0.07637499999999999 -0.244903564453125 0.507190625 +0.0765 -0.237640380859375 0.507190625 +0.076625 -0.22711181640625 0.507190625 +0.07675 -0.214080810546875 0.507190625 +0.076875 -0.200347900390625 0.507190625 +0.077 -0.183013916015625 0.507190625 +0.077125 -0.165679931640625 0.507190625 +0.07725 -0.14471435546875 0.507190625 +0.07737499999999999 -0.12213134765625 0.507190625 +0.0775 -0.100677490234375 0.507190625 +0.077625 -0.0758056640625 0.507190625 +0.07774999999999999 -0.052703857421875 0.507190625 +0.07787500000000001 -0.0264892578125 0.507190625 0.07800000000000001 0.0 0.507190625 0.078125 0.023834228515625 0.507190625 0.07824999999999999 0.05010986328125 0.507190625 @@ -654,37 +654,37 @@ 0.081625 0.057891845703125 0.507190625 0.08175000000000001 0.031768798828125 0.507190625 0.081875 0.0079345703125 0.507190625 -0.08200000000000001 -0.018585205078125 0.507190625 -0.082125 -0.04229736328125 0.507190625 -0.08225 -0.068206787109375 0.507190625 -0.08237500000000001 -0.093353271484375 0.507190625 -0.0825 -0.115142822265625 0.507190625 -0.08262500000000001 -0.13812255859375 0.507190625 -0.08275 -0.15753173828125 0.507190625 -0.08287500000000001 -0.17742919921875 0.507190625 -0.08300000000000001 -0.195404052734375 0.507190625 -0.083125 -0.209747314453125 0.507190625 -0.08324999999999999 -0.223480224609375 0.507190625 -0.083375 -0.2337646484375 0.507190625 -0.08350000000000001 -0.242767333984375 0.507190625 -0.08362500000000001 -0.24908447265625 0.507190625 -0.08375 -0.252471923828125 0.507190625 -0.08387500000000001 -0.253570556640625 0.507190625 -0.084 -0.252197265625 0.507190625 -0.08412500000000001 -0.248046875 0.507190625 -0.08425000000000001 -0.241180419921875 0.507190625 -0.084375 -0.23272705078125 0.507190625 -0.08450000000000001 -0.220947265625 0.507190625 -0.084625 -0.208221435546875 0.507190625 -0.08475 -0.19195556640625 0.507190625 -0.08487500000000001 -0.173583984375 0.507190625 -0.085 -0.155426025390625 0.507190625 -0.08512500000000001 -0.133636474609375 0.507190625 -0.08525 -0.112762451171875 0.507190625 -0.085375 -0.088409423828125 0.507190625 -0.08550000000000001 -0.063079833984375 0.507190625 -0.085625 -0.0396728515625 0.507190625 -0.08575000000000001 -0.013275146484375 0.507190625 +0.08200000000000001 -0.0185546875 0.507190625 +0.082125 -0.042266845703125 0.507190625 +0.08225 -0.06817626953125 0.507190625 +0.08237500000000001 -0.09332275390625 0.507190625 +0.0825 -0.1151123046875 0.507190625 +0.08262500000000001 -0.138092041015625 0.507190625 +0.08275 -0.157501220703125 0.507190625 +0.08287500000000001 -0.177398681640625 0.507190625 +0.08300000000000001 -0.19537353515625 0.507190625 +0.083125 -0.209716796875 0.507190625 +0.08324999999999999 -0.22344970703125 0.507190625 +0.083375 -0.233734130859375 0.507190625 +0.08350000000000001 -0.24273681640625 0.507190625 +0.08362500000000001 -0.249053955078125 0.507190625 +0.08375 -0.25244140625 0.507190625 +0.08387500000000001 -0.2535400390625 0.507190625 +0.084 -0.252166748046875 0.507190625 +0.08412500000000001 -0.248016357421875 0.507190625 +0.08425000000000001 -0.24114990234375 0.507190625 +0.084375 -0.232696533203125 0.507190625 +0.08450000000000001 -0.220916748046875 0.507190625 +0.084625 -0.20819091796875 0.507190625 +0.08475 -0.191925048828125 0.507190625 +0.08487500000000001 -0.173553466796875 0.507190625 +0.085 -0.1553955078125 0.507190625 +0.08512500000000001 -0.13360595703125 0.507190625 +0.08525 -0.11273193359375 0.507190625 +0.085375 -0.08837890625 0.507190625 +0.08550000000000001 -0.06304931640625 0.507190625 +0.085625 -0.039642333984375 0.507190625 +0.08575000000000001 -0.01324462890625 0.507190625 0.08587500000000002 0.010589599609375 0.507190625 0.08600000000000001 0.037017822265625 0.507190625 0.08612500000000001 0.06304931640625 0.507190625 @@ -716,37 +716,37 @@ 0.089375 0.07073974609375 0.507190625 0.08949999999999999 0.044891357421875 0.507190625 0.089625 0.021209716796875 0.507190625 -0.08975 -0.00531005859375 0.507190625 -0.08987499999999999 -0.03179931640625 0.507190625 -0.09 -0.055328369140625 0.507190625 -0.09012499999999999 -0.080902099609375 0.507190625 -0.09025 -0.1031494140625 0.507190625 -0.090375 -0.126800537109375 0.507190625 -0.09050000000000001 -0.1490478515625 0.507190625 -0.090625 -0.167694091796875 0.507190625 -0.09074999999999999 -0.186676025390625 0.507190625 -0.09087499999999999 -0.201995849609375 0.507190625 -0.091 -0.2169189453125 0.507190625 -0.09112500000000001 -0.229461669921875 0.507190625 -0.09125 -0.23858642578125 0.507190625 -0.09137499999999999 -0.24627685546875 0.507190625 -0.0915 -0.2508544921875 0.507190625 -0.091625 -0.25335693359375 0.507190625 -0.09175000000000001 -0.253082275390625 0.507190625 -0.091875 -0.250457763671875 0.507190625 -0.09199999999999999 -0.24493408203125 0.507190625 -0.092125 -0.2376708984375 0.507190625 -0.09225 -0.227142333984375 0.507190625 -0.09237499999999999 -0.214111328125 0.507190625 -0.0925 -0.20037841796875 0.507190625 -0.09262499999999999 -0.18304443359375 0.507190625 -0.09275 -0.16571044921875 0.507190625 -0.092875 -0.144744873046875 0.507190625 -0.09299999999999999 -0.122161865234375 0.507190625 -0.093125 -0.1007080078125 0.507190625 -0.09324999999999999 -0.075836181640625 0.507190625 -0.093375 -0.052734375 0.507190625 -0.09350000000000001 -0.026519775390625 0.507190625 +0.08975 -0.005279541015625 0.507190625 +0.08987499999999999 -0.031768798828125 0.507190625 +0.09 -0.0552978515625 0.507190625 +0.09012499999999999 -0.08087158203125 0.507190625 +0.09025 -0.103118896484375 0.507190625 +0.090375 -0.12677001953125 0.507190625 +0.09050000000000001 -0.149017333984375 0.507190625 +0.090625 -0.16766357421875 0.507190625 +0.09074999999999999 -0.1866455078125 0.507190625 +0.09087499999999999 -0.20196533203125 0.507190625 +0.091 -0.216888427734375 0.507190625 +0.09112500000000001 -0.22943115234375 0.507190625 +0.09125 -0.238555908203125 0.507190625 +0.09137499999999999 -0.246246337890625 0.507190625 +0.0915 -0.250823974609375 0.507190625 +0.091625 -0.253326416015625 0.507190625 +0.09175000000000001 -0.2530517578125 0.507190625 +0.091875 -0.25042724609375 0.507190625 +0.09199999999999999 -0.244903564453125 0.507190625 +0.092125 -0.237640380859375 0.507190625 +0.09225 -0.22711181640625 0.507190625 +0.09237499999999999 -0.214080810546875 0.507190625 +0.0925 -0.200347900390625 0.507190625 +0.09262499999999999 -0.183013916015625 0.507190625 +0.09275 -0.165679931640625 0.507190625 +0.092875 -0.14471435546875 0.507190625 +0.09299999999999999 -0.12213134765625 0.507190625 +0.093125 -0.100677490234375 0.507190625 +0.09324999999999999 -0.0758056640625 0.507190625 +0.093375 -0.052703857421875 0.507190625 +0.09350000000000001 -0.0264892578125 0.507190625 0.09362500000000001 0.0 0.507190625 0.09375 0.023834228515625 0.507190625 0.09387499999999999 0.05010986328125 0.507190625 @@ -779,37 +779,37 @@ 0.09725 0.069580078125 0.6095875 0.09737500000000001 0.038177490234375 0.6095875 0.0975 0.009552001953125 0.6095875 -0.09762500000000001 -0.0223388671875 0.6095875 -0.09775 -0.05084228515625 0.6095875 -0.097875 -0.08197021484375 0.6095875 -0.09800000000000001 -0.112213134765625 0.6095875 -0.098125 -0.13836669921875 0.6095875 -0.09825000000000001 -0.166015625 0.6095875 -0.098375 -0.1893310546875 0.6095875 -0.09850000000000001 -0.2132568359375 0.6095875 -0.09862500000000001 -0.234832763671875 0.6095875 -0.09875 -0.2520751953125 0.6095875 -0.09887499999999999 -0.26861572265625 0.6095875 -0.099 -0.280975341796875 0.6095875 -0.09912500000000001 -0.291778564453125 0.6095875 -0.09925000000000001 -0.29937744140625 0.6095875 -0.099375 -0.303436279296875 0.6095875 -0.09950000000000001 -0.304779052734375 0.6095875 -0.099625 -0.3031005859375 0.6095875 -0.09975000000000001 -0.298126220703125 0.6095875 -0.09987500000000001 -0.28985595703125 0.6095875 -0.1 -0.27972412109375 0.6095875 -0.100125 -0.265533447265625 0.6095875 -0.10025 -0.250274658203125 0.6095875 -0.100375 -0.230712890625 0.6095875 -0.1005 -0.208648681640625 0.6095875 -0.100625 -0.186798095703125 0.6095875 -0.10075 -0.160614013671875 0.6095875 -0.100875 -0.135528564453125 0.6095875 -0.101 -0.106231689453125 0.6095875 -0.101125 -0.0758056640625 0.6095875 -0.10125 -0.04766845703125 0.6095875 -0.101375 -0.015960693359375 0.6095875 +0.09762500000000001 -0.022308349609375 0.6095875 +0.09775 -0.050811767578125 0.6095875 +0.097875 -0.081939697265625 0.6095875 +0.09800000000000001 -0.1121826171875 0.6095875 +0.098125 -0.138336181640625 0.6095875 +0.09825000000000001 -0.165985107421875 0.6095875 +0.098375 -0.189300537109375 0.6095875 +0.09850000000000001 -0.213226318359375 0.6095875 +0.09862500000000001 -0.23480224609375 0.6095875 +0.09875 -0.252044677734375 0.6095875 +0.09887499999999999 -0.268585205078125 0.6095875 +0.099 -0.28094482421875 0.6095875 +0.09912500000000001 -0.291748046875 0.6095875 +0.09925000000000001 -0.299346923828125 0.6095875 +0.099375 -0.30340576171875 0.6095875 +0.09950000000000001 -0.30474853515625 0.6095875 +0.099625 -0.303070068359375 0.6095875 +0.09975000000000001 -0.298095703125 0.6095875 +0.09987500000000001 -0.289825439453125 0.6095875 +0.1 -0.279693603515625 0.6095875 +0.100125 -0.2655029296875 0.6095875 +0.10025 -0.250244140625 0.6095875 +0.100375 -0.230682373046875 0.6095875 +0.1005 -0.2086181640625 0.6095875 +0.100625 -0.186767578125 0.6095875 +0.10075 -0.16058349609375 0.6095875 +0.100875 -0.135498046875 0.6095875 +0.101 -0.106201171875 0.6095875 +0.101125 -0.075775146484375 0.6095875 +0.10125 -0.047637939453125 0.6095875 +0.101375 -0.01593017578125 0.6095875 0.1015 0.01275634765625 0.6095875 0.101625 0.04449462890625 0.6095875 0.10175 0.075775146484375 0.6095875 @@ -841,37 +841,37 @@ 0.105 0.084991455078125 0.6095875 0.105125 0.053955078125 0.6095875 0.10525 0.025482177734375 0.6095875 -0.105375 -0.00640869140625 0.6095875 -0.1055 -0.0382080078125 0.6095875 -0.105625 -0.066497802734375 0.6095875 -0.10575 -0.09722900390625 0.6095875 -0.105875 -0.12396240234375 0.6095875 -0.106 -0.15240478515625 0.6095875 -0.106125 -0.17913818359375 0.6095875 -0.10625 -0.201568603515625 0.6095875 -0.106375 -0.224334716796875 0.6095875 -0.1065 -0.242767333984375 0.6095875 -0.106625 -0.260711669921875 0.6095875 -0.10675 -0.275787353515625 0.6095875 -0.106875 -0.286773681640625 0.6095875 -0.107 -0.295989990234375 0.6095875 -0.107125 -0.301513671875 0.6095875 -0.10725 -0.30450439453125 0.6095875 -0.107375 -0.304168701171875 0.6095875 -0.1075 -0.301025390625 0.6095875 -0.107625 -0.294403076171875 0.6095875 -0.10775 -0.285675048828125 0.6095875 -0.107875 -0.272979736328125 0.6095875 -0.108 -0.257354736328125 0.6095875 -0.108125 -0.2408447265625 0.6095875 -0.10825 -0.219970703125 0.6095875 -0.108375 -0.19915771484375 0.6095875 -0.1085 -0.1739501953125 0.6095875 -0.108625 -0.146820068359375 0.6095875 -0.10875 -0.121063232421875 0.6095875 -0.108875 -0.091156005859375 0.6095875 -0.109 -0.063385009765625 0.6095875 -0.109125 -0.0318603515625 0.6095875 +0.105375 -0.006378173828125 0.6095875 +0.1055 -0.038177490234375 0.6095875 +0.105625 -0.06646728515625 0.6095875 +0.10575 -0.097198486328125 0.6095875 +0.105875 -0.123931884765625 0.6095875 +0.106 -0.152374267578125 0.6095875 +0.106125 -0.179107666015625 0.6095875 +0.10625 -0.2015380859375 0.6095875 +0.106375 -0.22430419921875 0.6095875 +0.1065 -0.24273681640625 0.6095875 +0.106625 -0.26068115234375 0.6095875 +0.10675 -0.2757568359375 0.6095875 +0.106875 -0.2867431640625 0.6095875 +0.107 -0.29595947265625 0.6095875 +0.107125 -0.301483154296875 0.6095875 +0.10725 -0.304473876953125 0.6095875 +0.107375 -0.30413818359375 0.6095875 +0.1075 -0.300994873046875 0.6095875 +0.107625 -0.29437255859375 0.6095875 +0.10775 -0.28564453125 0.6095875 +0.107875 -0.27294921875 0.6095875 +0.108 -0.25732421875 0.6095875 +0.108125 -0.240814208984375 0.6095875 +0.10825 -0.219940185546875 0.6095875 +0.108375 -0.199127197265625 0.6095875 +0.1085 -0.173919677734375 0.6095875 +0.108625 -0.14678955078125 0.6095875 +0.10875 -0.12103271484375 0.6095875 +0.108875 -0.09112548828125 0.6095875 +0.109 -0.0633544921875 0.6095875 +0.109125 -0.031829833984375 0.6095875 0.10925 0.0 0.6095875 0.109375 0.028656005859375 0.6095875 0.1095 0.060211181640625 0.6095875 @@ -904,37 +904,37 @@ 0.112875 0.069580078125 0.6095875 0.113 0.038177490234375 0.6095875 0.113125 0.009552001953125 0.6095875 -0.11325 -0.0223388671875 0.6095875 -0.113375 -0.05084228515625 0.6095875 -0.1135 -0.08197021484375 0.6095875 -0.113625 -0.112213134765625 0.6095875 -0.11375 -0.13836669921875 0.6095875 -0.113875 -0.166015625 0.6095875 -0.114 -0.1893310546875 0.6095875 -0.114125 -0.2132568359375 0.6095875 -0.11425 -0.234832763671875 0.6095875 -0.114375 -0.2520751953125 0.6095875 -0.1145 -0.26861572265625 0.6095875 -0.114625 -0.280975341796875 0.6095875 -0.11475 -0.291778564453125 0.6095875 -0.114875 -0.29937744140625 0.6095875 -0.115 -0.303436279296875 0.6095875 -0.115125 -0.304779052734375 0.6095875 -0.11525 -0.3031005859375 0.6095875 -0.115375 -0.298126220703125 0.6095875 -0.1155 -0.28985595703125 0.6095875 -0.115625 -0.27972412109375 0.6095875 -0.11575 -0.265533447265625 0.6095875 -0.115875 -0.250274658203125 0.6095875 -0.116 -0.230712890625 0.6095875 -0.116125 -0.208648681640625 0.6095875 -0.11625 -0.186798095703125 0.6095875 -0.116375 -0.160614013671875 0.6095875 -0.1165 -0.135528564453125 0.6095875 -0.116625 -0.106231689453125 0.6095875 -0.11675 -0.0758056640625 0.6095875 -0.116875 -0.04766845703125 0.6095875 -0.117 -0.015960693359375 0.6095875 +0.11325 -0.022308349609375 0.6095875 +0.113375 -0.050811767578125 0.6095875 +0.1135 -0.081939697265625 0.6095875 +0.113625 -0.1121826171875 0.6095875 +0.11375 -0.138336181640625 0.6095875 +0.113875 -0.165985107421875 0.6095875 +0.114 -0.189300537109375 0.6095875 +0.114125 -0.213226318359375 0.6095875 +0.11425 -0.23480224609375 0.6095875 +0.114375 -0.252044677734375 0.6095875 +0.1145 -0.268585205078125 0.6095875 +0.114625 -0.28094482421875 0.6095875 +0.11475 -0.291748046875 0.6095875 +0.114875 -0.299346923828125 0.6095875 +0.115 -0.30340576171875 0.6095875 +0.115125 -0.30474853515625 0.6095875 +0.11525 -0.303070068359375 0.6095875 +0.115375 -0.298095703125 0.6095875 +0.1155 -0.289825439453125 0.6095875 +0.115625 -0.279693603515625 0.6095875 +0.11575 -0.2655029296875 0.6095875 +0.115875 -0.250244140625 0.6095875 +0.116 -0.230682373046875 0.6095875 +0.116125 -0.2086181640625 0.6095875 +0.11625 -0.186767578125 0.6095875 +0.116375 -0.16058349609375 0.6095875 +0.1165 -0.135498046875 0.6095875 +0.116625 -0.106201171875 0.6095875 +0.11675 -0.075775146484375 0.6095875 +0.116875 -0.047637939453125 0.6095875 +0.117 -0.01593017578125 0.6095875 0.117125 0.01275634765625 0.6095875 0.11725 0.04449462890625 0.6095875 0.117375 0.075775146484375 0.6095875 @@ -966,37 +966,37 @@ 0.120625 0.084991455078125 0.6095875 0.12075 0.053955078125 0.6095875 0.120875 0.025482177734375 0.6095875 -0.121 -0.00640869140625 0.6095875 -0.121125 -0.0382080078125 0.6095875 -0.12125 -0.066497802734375 0.6095875 -0.121375 -0.09722900390625 0.6095875 -0.1215 -0.12396240234375 0.6095875 -0.121625 -0.15240478515625 0.6095875 -0.12175 -0.17913818359375 0.6095875 -0.121875 -0.201568603515625 0.6095875 -0.122 -0.224334716796875 0.6095875 -0.122125 -0.242767333984375 0.6095875 -0.12225 -0.260711669921875 0.6095875 -0.122375 -0.275787353515625 0.6095875 -0.1225 -0.286773681640625 0.6095875 -0.122625 -0.295989990234375 0.6095875 -0.12275 -0.301513671875 0.6095875 -0.122875 -0.30450439453125 0.6095875 -0.123 -0.304168701171875 0.6095875 -0.123125 -0.301025390625 0.6095875 -0.12325 -0.294403076171875 0.6095875 -0.123375 -0.285675048828125 0.6095875 -0.1235 -0.272979736328125 0.6095875 -0.123625 -0.257354736328125 0.6095875 -0.12375 -0.2408447265625 0.6095875 -0.123875 -0.219970703125 0.6095875 -0.124 -0.19915771484375 0.6095875 -0.124125 -0.1739501953125 0.6095875 -0.12425 -0.146820068359375 0.6095875 -0.124375 -0.121063232421875 0.6095875 -0.1245 -0.091156005859375 0.6095875 -0.124625 -0.063385009765625 0.6095875 -0.12475 -0.0318603515625 0.6095875 +0.121 -0.006378173828125 0.6095875 +0.121125 -0.038177490234375 0.6095875 +0.12125 -0.06646728515625 0.6095875 +0.121375 -0.097198486328125 0.6095875 +0.1215 -0.123931884765625 0.6095875 +0.121625 -0.152374267578125 0.6095875 +0.12175 -0.179107666015625 0.6095875 +0.121875 -0.2015380859375 0.6095875 +0.122 -0.22430419921875 0.6095875 +0.122125 -0.24273681640625 0.6095875 +0.12225 -0.26068115234375 0.6095875 +0.122375 -0.2757568359375 0.6095875 +0.1225 -0.2867431640625 0.6095875 +0.122625 -0.29595947265625 0.6095875 +0.12275 -0.301483154296875 0.6095875 +0.122875 -0.304473876953125 0.6095875 +0.123 -0.30413818359375 0.6095875 +0.123125 -0.300994873046875 0.6095875 +0.12325 -0.29437255859375 0.6095875 +0.123375 -0.28564453125 0.6095875 +0.1235 -0.27294921875 0.6095875 +0.123625 -0.25732421875 0.6095875 +0.12375 -0.240814208984375 0.6095875 +0.123875 -0.219940185546875 0.6095875 +0.124 -0.199127197265625 0.6095875 +0.124125 -0.173919677734375 0.6095875 +0.12425 -0.14678955078125 0.6095875 +0.124375 -0.12103271484375 0.6095875 +0.1245 -0.09112548828125 0.6095875 +0.124625 -0.0633544921875 0.6095875 +0.12475 -0.031829833984375 0.6095875 0.124875 0.0 0.6095875 0.125 0.028656005859375 0.6095875 0.125125 0.060211181640625 0.6095875 @@ -1029,37 +1029,37 @@ 0.1285 0.081268310546875 0.7119843750000001 0.128625 0.044586181640625 0.7119843750000001 0.12875 0.01116943359375 0.7119843750000001 -0.128875 -0.02606201171875 0.7119843750000001 -0.129 -0.05938720703125 0.7119843750000001 -0.129125 -0.095733642578125 0.7119843750000001 -0.12925 -0.13104248046875 0.7119843750000001 -0.129375 -0.16162109375 0.7119843750000001 -0.1295 -0.193878173828125 0.7119843750000001 -0.129625 -0.22113037109375 0.7119843750000001 -0.12975 -0.249053955078125 0.7119843750000001 -0.129875 -0.2742919921875 0.7119843750000001 -0.13 -0.294403076171875 0.7119843750000001 -0.130125 -0.313720703125 0.7119843750000001 -0.13025 -0.328155517578125 0.7119843750000001 -0.130375 -0.340789794921875 0.7119843750000001 -0.1305 -0.34967041015625 0.7119843750000001 -0.130625 -0.354400634765625 0.7119843750000001 -0.13075 -0.35595703125 0.7119843750000001 -0.130875 -0.354034423828125 0.7119843750000001 -0.131 -0.348175048828125 0.7119843750000001 -0.131125 -0.33856201171875 0.7119843750000001 -0.13125 -0.326690673828125 0.7119843750000001 -0.131375 -0.31011962890625 0.7119843750000001 -0.1315 -0.29229736328125 0.7119843750000001 -0.131625 -0.26947021484375 0.7119843750000001 -0.13175 -0.243682861328125 0.7119843750000001 -0.131875 -0.218170166015625 0.7119843750000001 -0.132 -0.187591552734375 0.7119843750000001 -0.132125 -0.158294677734375 0.7119843750000001 -0.13225 -0.12408447265625 0.7119843750000001 -0.132375 -0.088531494140625 0.7119843750000001 -0.1325 -0.055694580078125 0.7119843750000001 -0.132625 -0.018646240234375 0.7119843750000001 +0.128875 -0.026031494140625 0.7119843750000001 +0.129 -0.059356689453125 0.7119843750000001 +0.129125 -0.095703125 0.7119843750000001 +0.12925 -0.131011962890625 0.7119843750000001 +0.129375 -0.161590576171875 0.7119843750000001 +0.1295 -0.19384765625 0.7119843750000001 +0.129625 -0.221099853515625 0.7119843750000001 +0.12975 -0.2490234375 0.7119843750000001 +0.129875 -0.274261474609375 0.7119843750000001 +0.13 -0.29437255859375 0.7119843750000001 +0.130125 -0.313690185546875 0.7119843750000001 +0.13025 -0.328125 0.7119843750000001 +0.130375 -0.34075927734375 0.7119843750000001 +0.1305 -0.349639892578125 0.7119843750000001 +0.130625 -0.3543701171875 0.7119843750000001 +0.13075 -0.355926513671875 0.7119843750000001 +0.130875 -0.35400390625 0.7119843750000001 +0.131 -0.34814453125 0.7119843750000001 +0.131125 -0.338531494140625 0.7119843750000001 +0.13125 -0.32666015625 0.7119843750000001 +0.131375 -0.310089111328125 0.7119843750000001 +0.1315 -0.292266845703125 0.7119843750000001 +0.131625 -0.269439697265625 0.7119843750000001 +0.13175 -0.24365234375 0.7119843750000001 +0.131875 -0.2181396484375 0.7119843750000001 +0.132 -0.18756103515625 0.7119843750000001 +0.132125 -0.15826416015625 0.7119843750000001 +0.13225 -0.124053955078125 0.7119843750000001 +0.132375 -0.0885009765625 0.7119843750000001 +0.1325 -0.0556640625 0.7119843750000001 +0.132625 -0.01861572265625 0.7119843750000001 0.13275 0.014892578125 0.7119843750000001 0.132875 0.051971435546875 0.7119843750000001 0.133 0.0885009765625 0.7119843750000001 @@ -1091,37 +1091,37 @@ 0.13625 0.099273681640625 0.7119843750000001 0.136375 0.063018798828125 0.7119843750000001 0.1365 0.029754638671875 0.7119843750000001 -0.136625 -0.007476806640625 0.7119843750000001 -0.13675 -0.04461669921875 0.7119843750000001 -0.136875 -0.077667236328125 0.7119843750000001 -0.137 -0.113555908203125 0.7119843750000001 -0.137125 -0.144805908203125 0.7119843750000001 -0.13725 -0.177978515625 0.7119843750000001 -0.137375 -0.209228515625 0.7119843750000001 -0.1375 -0.23541259765625 0.7119843750000001 -0.137625 -0.26202392578125 0.7119843750000001 -0.13775 -0.283538818359375 0.7119843750000001 -0.137875 -0.304473876953125 0.7119843750000001 -0.138 -0.32208251953125 0.7119843750000001 -0.138125 -0.334930419921875 0.7119843750000001 -0.13825 -0.345703125 0.7119843750000001 -0.138375 -0.352142333984375 0.7119843750000001 -0.1385 -0.35565185546875 0.7119843750000001 -0.138625 -0.35528564453125 0.7119843750000001 -0.13875 -0.351593017578125 0.7119843750000001 -0.138875 -0.343841552734375 0.7119843750000001 -0.139 -0.333648681640625 0.7119843750000001 -0.139125 -0.31884765625 0.7119843750000001 -0.13925 -0.300567626953125 0.7119843750000001 -0.139375 -0.281280517578125 0.7119843750000001 -0.1395 -0.256927490234375 0.7119843750000001 -0.139625 -0.23260498046875 0.7119843750000001 -0.13975 -0.203155517578125 0.7119843750000001 -0.139875 -0.1715087890625 0.7119843750000001 -0.14 -0.141387939453125 0.7119843750000001 -0.140125 -0.1064453125 0.7119843750000001 -0.14025 -0.074005126953125 0.7119843750000001 -0.140375 -0.0372314453125 0.7119843750000001 +0.136625 -0.0074462890625 0.7119843750000001 +0.13675 -0.044586181640625 0.7119843750000001 +0.136875 -0.07763671875 0.7119843750000001 +0.137 -0.113525390625 0.7119843750000001 +0.137125 -0.144775390625 0.7119843750000001 +0.13725 -0.177947998046875 0.7119843750000001 +0.137375 -0.209197998046875 0.7119843750000001 +0.1375 -0.235382080078125 0.7119843750000001 +0.137625 -0.261993408203125 0.7119843750000001 +0.13775 -0.28350830078125 0.7119843750000001 +0.137875 -0.304443359375 0.7119843750000001 +0.138 -0.322052001953125 0.7119843750000001 +0.138125 -0.33489990234375 0.7119843750000001 +0.13825 -0.345672607421875 0.7119843750000001 +0.138375 -0.35211181640625 0.7119843750000001 +0.1385 -0.355621337890625 0.7119843750000001 +0.138625 -0.355255126953125 0.7119843750000001 +0.13875 -0.3515625 0.7119843750000001 +0.138875 -0.34381103515625 0.7119843750000001 +0.139 -0.3336181640625 0.7119843750000001 +0.139125 -0.318817138671875 0.7119843750000001 +0.13925 -0.300537109375 0.7119843750000001 +0.139375 -0.28125 0.7119843750000001 +0.1395 -0.25689697265625 0.7119843750000001 +0.139625 -0.232574462890625 0.7119843750000001 +0.13975 -0.203125 0.7119843750000001 +0.139875 -0.171478271484375 0.7119843750000001 +0.14 -0.141357421875 0.7119843750000001 +0.140125 -0.106414794921875 0.7119843750000001 +0.14025 -0.073974609375 0.7119843750000001 +0.140375 -0.037200927734375 0.7119843750000001 0.1405 0.0 0.7119843750000001 0.140625 0.033477783203125 0.7119843750000001 0.14075 0.070343017578125 0.7119843750000001 @@ -1154,37 +1154,37 @@ 0.144125 0.081268310546875 0.7119843750000001 0.14425 0.044586181640625 0.7119843750000001 0.144375 0.01116943359375 0.7119843750000001 -0.1445 -0.02606201171875 0.7119843750000001 -0.144625 -0.05938720703125 0.7119843750000001 -0.14475 -0.095733642578125 0.7119843750000001 -0.144875 -0.13104248046875 0.7119843750000001 -0.145 -0.16162109375 0.7119843750000001 -0.145125 -0.193878173828125 0.7119843750000001 -0.14525 -0.22113037109375 0.7119843750000001 -0.145375 -0.249053955078125 0.7119843750000001 -0.1455 -0.2742919921875 0.7119843750000001 -0.145625 -0.294403076171875 0.7119843750000001 -0.14575 -0.313720703125 0.7119843750000001 -0.145875 -0.328155517578125 0.7119843750000001 -0.146 -0.340789794921875 0.7119843750000001 -0.146125 -0.34967041015625 0.7119843750000001 -0.14625 -0.354400634765625 0.7119843750000001 -0.146375 -0.35595703125 0.7119843750000001 -0.1465 -0.354034423828125 0.7119843750000001 -0.146625 -0.348175048828125 0.7119843750000001 -0.14675 -0.33856201171875 0.7119843750000001 -0.146875 -0.326690673828125 0.7119843750000001 -0.147 -0.31011962890625 0.7119843750000001 -0.147125 -0.29229736328125 0.7119843750000001 -0.14725 -0.26947021484375 0.7119843750000001 -0.147375 -0.243682861328125 0.7119843750000001 -0.1475 -0.218170166015625 0.7119843750000001 -0.147625 -0.187591552734375 0.7119843750000001 -0.14775 -0.158294677734375 0.7119843750000001 -0.147875 -0.12408447265625 0.7119843750000001 -0.148 -0.088531494140625 0.7119843750000001 -0.148125 -0.055694580078125 0.7119843750000001 -0.14825 -0.018646240234375 0.7119843750000001 +0.1445 -0.026031494140625 0.7119843750000001 +0.144625 -0.059356689453125 0.7119843750000001 +0.14475 -0.095703125 0.7119843750000001 +0.144875 -0.131011962890625 0.7119843750000001 +0.145 -0.161590576171875 0.7119843750000001 +0.145125 -0.19384765625 0.7119843750000001 +0.14525 -0.221099853515625 0.7119843750000001 +0.145375 -0.2490234375 0.7119843750000001 +0.1455 -0.274261474609375 0.7119843750000001 +0.145625 -0.29437255859375 0.7119843750000001 +0.14575 -0.313690185546875 0.7119843750000001 +0.145875 -0.328125 0.7119843750000001 +0.146 -0.34075927734375 0.7119843750000001 +0.146125 -0.349639892578125 0.7119843750000001 +0.14625 -0.3543701171875 0.7119843750000001 +0.146375 -0.355926513671875 0.7119843750000001 +0.1465 -0.35400390625 0.7119843750000001 +0.146625 -0.34814453125 0.7119843750000001 +0.14675 -0.338531494140625 0.7119843750000001 +0.146875 -0.32666015625 0.7119843750000001 +0.147 -0.310089111328125 0.7119843750000001 +0.147125 -0.292266845703125 0.7119843750000001 +0.14725 -0.269439697265625 0.7119843750000001 +0.147375 -0.24365234375 0.7119843750000001 +0.1475 -0.2181396484375 0.7119843750000001 +0.147625 -0.18756103515625 0.7119843750000001 +0.14775 -0.15826416015625 0.7119843750000001 +0.147875 -0.124053955078125 0.7119843750000001 +0.148 -0.0885009765625 0.7119843750000001 +0.148125 -0.0556640625 0.7119843750000001 +0.14825 -0.01861572265625 0.7119843750000001 0.148375 0.014892578125 0.7119843750000001 0.1485 0.051971435546875 0.7119843750000001 0.148625 0.0885009765625 0.7119843750000001 @@ -1216,37 +1216,37 @@ 0.151875 0.099273681640625 0.7119843750000001 0.152 0.063018798828125 0.7119843750000001 0.152125 0.029754638671875 0.7119843750000001 -0.15225 -0.007476806640625 0.7119843750000001 -0.152375 -0.04461669921875 0.7119843750000001 -0.1525 -0.077667236328125 0.7119843750000001 -0.152625 -0.113555908203125 0.7119843750000001 -0.15275 -0.144805908203125 0.7119843750000001 -0.152875 -0.177978515625 0.7119843750000001 -0.153 -0.209228515625 0.7119843750000001 -0.153125 -0.23541259765625 0.7119843750000001 -0.15325 -0.26202392578125 0.7119843750000001 -0.153375 -0.283538818359375 0.7119843750000001 -0.1535 -0.304473876953125 0.7119843750000001 -0.153625 -0.32208251953125 0.7119843750000001 -0.15375 -0.334930419921875 0.7119843750000001 -0.153875 -0.345703125 0.7119843750000001 -0.154 -0.352142333984375 0.7119843750000001 -0.154125 -0.35565185546875 0.7119843750000001 -0.15425 -0.35528564453125 0.7119843750000001 -0.154375 -0.351593017578125 0.7119843750000001 -0.1545 -0.343841552734375 0.7119843750000001 -0.154625 -0.333648681640625 0.7119843750000001 -0.15475 -0.31884765625 0.7119843750000001 -0.154875 -0.300567626953125 0.7119843750000001 -0.155 -0.281280517578125 0.7119843750000001 -0.155125 -0.256927490234375 0.7119843750000001 -0.15525 -0.23260498046875 0.7119843750000001 -0.155375 -0.203155517578125 0.7119843750000001 -0.1555 -0.1715087890625 0.7119843750000001 -0.155625 -0.141387939453125 0.7119843750000001 -0.15575 -0.1064453125 0.7119843750000001 -0.155875 -0.074005126953125 0.7119843750000001 -0.156 -0.0372314453125 0.7119843750000001 +0.15225 -0.0074462890625 0.7119843750000001 +0.152375 -0.044586181640625 0.7119843750000001 +0.1525 -0.07763671875 0.7119843750000001 +0.152625 -0.113525390625 0.7119843750000001 +0.15275 -0.144775390625 0.7119843750000001 +0.152875 -0.177947998046875 0.7119843750000001 +0.153 -0.209197998046875 0.7119843750000001 +0.153125 -0.235382080078125 0.7119843750000001 +0.15325 -0.261993408203125 0.7119843750000001 +0.153375 -0.28350830078125 0.7119843750000001 +0.1535 -0.304443359375 0.7119843750000001 +0.153625 -0.322052001953125 0.7119843750000001 +0.15375 -0.33489990234375 0.7119843750000001 +0.153875 -0.345672607421875 0.7119843750000001 +0.154 -0.35211181640625 0.7119843750000001 +0.154125 -0.355621337890625 0.7119843750000001 +0.15425 -0.355255126953125 0.7119843750000001 +0.154375 -0.3515625 0.7119843750000001 +0.1545 -0.34381103515625 0.7119843750000001 +0.154625 -0.3336181640625 0.7119843750000001 +0.15475 -0.318817138671875 0.7119843750000001 +0.154875 -0.300537109375 0.7119843750000001 +0.155 -0.28125 0.7119843750000001 +0.155125 -0.25689697265625 0.7119843750000001 +0.15525 -0.232574462890625 0.7119843750000001 +0.155375 -0.203125 0.7119843750000001 +0.1555 -0.171478271484375 0.7119843750000001 +0.155625 -0.141357421875 0.7119843750000001 +0.15575 -0.106414794921875 0.7119843750000001 +0.155875 -0.073974609375 0.7119843750000001 +0.156 -0.037200927734375 0.7119843750000001 0.156125 0.0 0.7119843750000001 0.15625 0.033477783203125 0.7119843750000001 0.156375 0.070343017578125 0.7119843750000001 @@ -1279,37 +1279,37 @@ 0.15975 0.081268310546875 0.7119843750000001 0.159875 0.044586181640625 0.7119843750000001 0.16 0.01275634765625 0.8143812500000001 -0.160125 -0.029815673828125 0.8143812500000001 -0.16025 -0.067901611328125 0.8143812500000001 -0.160375 -0.1094970703125 0.8143812500000001 -0.1605 -0.14990234375 0.8143812500000001 -0.160625 -0.184844970703125 0.8143812500000001 -0.16075 -0.221771240234375 0.8143812500000001 -0.160875 -0.2529296875 0.8143812500000001 -0.161 -0.284881591796875 0.8143812500000001 -0.161125 -0.313751220703125 0.8143812500000001 -0.16125 -0.336761474609375 0.8143812500000001 -0.161375 -0.358856201171875 0.8143812500000001 -0.1615 -0.3753662109375 0.8143812500000001 -0.161625 -0.389801025390625 0.8143812500000001 -0.16175 -0.39996337890625 0.8143812500000001 -0.161875 -0.405364990234375 0.8143812500000001 -0.162 -0.40716552734375 0.8143812500000001 -0.162125 -0.404937744140625 0.8143812500000001 -0.16225 -0.398284912109375 0.8143812500000001 -0.162375 -0.387237548828125 0.8143812500000001 -0.1625 -0.373687744140625 0.8143812500000001 -0.162625 -0.354736328125 0.8143812500000001 -0.16275 -0.3343505859375 0.8143812500000001 -0.162875 -0.3082275390625 0.8143812500000001 -0.163 -0.27874755859375 0.8143812500000001 -0.163125 -0.24957275390625 0.8143812500000001 -0.16325 -0.214569091796875 0.8143812500000001 -0.163375 -0.181060791015625 0.8143812500000001 -0.1635 -0.141937255859375 0.8143812500000001 -0.163625 -0.10125732421875 0.8143812500000001 -0.16375 -0.063690185546875 0.8143812500000001 -0.163875 -0.02130126953125 0.8143812500000001 +0.160125 -0.02978515625 0.8143812500000001 +0.16025 -0.06787109375 0.8143812500000001 +0.160375 -0.109466552734375 0.8143812500000001 +0.1605 -0.149871826171875 0.8143812500000001 +0.160625 -0.184814453125 0.8143812500000001 +0.16075 -0.22174072265625 0.8143812500000001 +0.160875 -0.252899169921875 0.8143812500000001 +0.161 -0.28485107421875 0.8143812500000001 +0.161125 -0.313720703125 0.8143812500000001 +0.16125 -0.33673095703125 0.8143812500000001 +0.161375 -0.35882568359375 0.8143812500000001 +0.1615 -0.375335693359375 0.8143812500000001 +0.161625 -0.3897705078125 0.8143812500000001 +0.16175 -0.399932861328125 0.8143812500000001 +0.161875 -0.40533447265625 0.8143812500000001 +0.162 -0.407135009765625 0.8143812500000001 +0.162125 -0.4049072265625 0.8143812500000001 +0.16225 -0.39825439453125 0.8143812500000001 +0.162375 -0.38720703125 0.8143812500000001 +0.1625 -0.3736572265625 0.8143812500000001 +0.162625 -0.354705810546875 0.8143812500000001 +0.16275 -0.334320068359375 0.8143812500000001 +0.162875 -0.308197021484375 0.8143812500000001 +0.163 -0.278717041015625 0.8143812500000001 +0.163125 -0.249542236328125 0.8143812500000001 +0.16325 -0.21453857421875 0.8143812500000001 +0.163375 -0.1810302734375 0.8143812500000001 +0.1635 -0.14190673828125 0.8143812500000001 +0.163625 -0.101226806640625 0.8143812500000001 +0.16375 -0.06365966796875 0.8143812500000001 +0.163875 -0.021270751953125 0.8143812500000001 0.164 0.01702880859375 0.8143812500000001 0.164125 0.0594482421875 0.8143812500000001 0.16425 0.101226806640625 0.8143812500000001 @@ -1341,37 +1341,37 @@ 0.1675 0.11358642578125 0.8143812500000001 0.167625 0.07208251953125 0.8143812500000001 0.16775 0.0340576171875 0.8143812500000001 -0.167875 -0.008544921875 0.8143812500000001 -0.168 -0.051025390625 0.8143812500000001 -0.168125 -0.088836669921875 0.8143812500000001 -0.16825 -0.1298828125 0.8143812500000001 -0.168375 -0.165618896484375 0.8143812500000001 -0.1685 -0.203582763671875 0.8143812500000001 -0.168625 -0.23931884765625 0.8143812500000001 -0.16875 -0.269287109375 0.8143812500000001 -0.168875 -0.299713134765625 0.8143812500000001 -0.169 -0.3243408203125 0.8143812500000001 -0.169125 -0.348297119140625 0.8143812500000001 -0.16925 -0.368438720703125 0.8143812500000001 -0.169375 -0.383087158203125 0.8143812500000001 -0.1695 -0.395416259765625 0.8143812500000001 -0.169625 -0.402801513671875 0.8143812500000001 -0.16975 -0.406829833984375 0.8143812500000001 -0.169875 -0.4063720703125 0.8143812500000001 -0.17 -0.40216064453125 0.8143812500000001 -0.170125 -0.393310546875 0.8143812500000001 -0.17025 -0.381622314453125 0.8143812500000001 -0.170375 -0.364715576171875 0.8143812500000001 -0.1705 -0.34381103515625 0.8143812500000001 -0.170625 -0.321746826171875 0.8143812500000001 -0.17075 -0.29388427734375 0.8143812500000001 -0.170875 -0.26605224609375 0.8143812500000001 -0.171 -0.232391357421875 0.8143812500000001 -0.171125 -0.1961669921875 0.8143812500000001 -0.17125 -0.161712646484375 0.8143812500000001 -0.171375 -0.12176513671875 0.8143812500000001 -0.1715 -0.08465576171875 0.8143812500000001 -0.171625 -0.042572021484375 0.8143812500000001 +0.167875 -0.008514404296875 0.8143812500000001 +0.168 -0.050994873046875 0.8143812500000001 +0.168125 -0.08880615234375 0.8143812500000001 +0.16825 -0.129852294921875 0.8143812500000001 +0.168375 -0.16558837890625 0.8143812500000001 +0.1685 -0.20355224609375 0.8143812500000001 +0.168625 -0.239288330078125 0.8143812500000001 +0.16875 -0.269256591796875 0.8143812500000001 +0.168875 -0.2996826171875 0.8143812500000001 +0.169 -0.324310302734375 0.8143812500000001 +0.169125 -0.3482666015625 0.8143812500000001 +0.16925 -0.368408203125 0.8143812500000001 +0.169375 -0.383056640625 0.8143812500000001 +0.1695 -0.3953857421875 0.8143812500000001 +0.169625 -0.40277099609375 0.8143812500000001 +0.16975 -0.40679931640625 0.8143812500000001 +0.169875 -0.406341552734375 0.8143812500000001 +0.17 -0.402130126953125 0.8143812500000001 +0.170125 -0.393280029296875 0.8143812500000001 +0.17025 -0.381591796875 0.8143812500000001 +0.170375 -0.36468505859375 0.8143812500000001 +0.1705 -0.343780517578125 0.8143812500000001 +0.170625 -0.32171630859375 0.8143812500000001 +0.17075 -0.293853759765625 0.8143812500000001 +0.170875 -0.266021728515625 0.8143812500000001 +0.171 -0.23236083984375 0.8143812500000001 +0.171125 -0.196136474609375 0.8143812500000001 +0.17125 -0.16168212890625 0.8143812500000001 +0.171375 -0.121734619140625 0.8143812500000001 +0.1715 -0.084625244140625 0.8143812500000001 +0.171625 -0.04254150390625 0.8143812500000001 0.17175 0.0 0.8143812500000001 0.171875 0.038299560546875 0.8143812500000001 0.172 0.0804443359375 0.8143812500000001 @@ -1404,37 +1404,37 @@ 0.175375 0.09295654296875 0.8143812500000001 0.1755 0.050994873046875 0.8143812500000001 0.175625 0.01275634765625 0.8143812500000001 -0.17575 -0.029815673828125 0.8143812500000001 -0.175875 -0.067901611328125 0.8143812500000001 -0.176 -0.1094970703125 0.8143812500000001 -0.176125 -0.14990234375 0.8143812500000001 -0.17625 -0.184844970703125 0.8143812500000001 -0.176375 -0.221771240234375 0.8143812500000001 -0.1765 -0.2529296875 0.8143812500000001 -0.176625 -0.284881591796875 0.8143812500000001 -0.17675 -0.313751220703125 0.8143812500000001 -0.176875 -0.336761474609375 0.8143812500000001 -0.177 -0.358856201171875 0.8143812500000001 -0.177125 -0.3753662109375 0.8143812500000001 -0.17725 -0.389801025390625 0.8143812500000001 -0.177375 -0.39996337890625 0.8143812500000001 -0.1775 -0.405364990234375 0.8143812500000001 -0.177625 -0.40716552734375 0.8143812500000001 -0.17775 -0.404937744140625 0.8143812500000001 -0.177875 -0.398284912109375 0.8143812500000001 -0.178 -0.387237548828125 0.8143812500000001 -0.178125 -0.373687744140625 0.8143812500000001 -0.17825 -0.354736328125 0.8143812500000001 -0.178375 -0.3343505859375 0.8143812500000001 -0.1785 -0.3082275390625 0.8143812500000001 -0.178625 -0.27874755859375 0.8143812500000001 -0.17875 -0.24957275390625 0.8143812500000001 -0.178875 -0.214569091796875 0.8143812500000001 -0.179 -0.181060791015625 0.8143812500000001 -0.179125 -0.141937255859375 0.8143812500000001 -0.17925 -0.10125732421875 0.8143812500000001 -0.179375 -0.063690185546875 0.8143812500000001 -0.1795 -0.02130126953125 0.8143812500000001 +0.17575 -0.02978515625 0.8143812500000001 +0.175875 -0.06787109375 0.8143812500000001 +0.176 -0.109466552734375 0.8143812500000001 +0.176125 -0.149871826171875 0.8143812500000001 +0.17625 -0.184814453125 0.8143812500000001 +0.176375 -0.22174072265625 0.8143812500000001 +0.1765 -0.252899169921875 0.8143812500000001 +0.176625 -0.28485107421875 0.8143812500000001 +0.17675 -0.313720703125 0.8143812500000001 +0.176875 -0.33673095703125 0.8143812500000001 +0.177 -0.35882568359375 0.8143812500000001 +0.177125 -0.375335693359375 0.8143812500000001 +0.17725 -0.3897705078125 0.8143812500000001 +0.177375 -0.399932861328125 0.8143812500000001 +0.1775 -0.40533447265625 0.8143812500000001 +0.177625 -0.407135009765625 0.8143812500000001 +0.17775 -0.4049072265625 0.8143812500000001 +0.177875 -0.39825439453125 0.8143812500000001 +0.178 -0.38720703125 0.8143812500000001 +0.178125 -0.3736572265625 0.8143812500000001 +0.17825 -0.354705810546875 0.8143812500000001 +0.178375 -0.334320068359375 0.8143812500000001 +0.1785 -0.308197021484375 0.8143812500000001 +0.178625 -0.278717041015625 0.8143812500000001 +0.17875 -0.249542236328125 0.8143812500000001 +0.178875 -0.21453857421875 0.8143812500000001 +0.179 -0.1810302734375 0.8143812500000001 +0.179125 -0.14190673828125 0.8143812500000001 +0.17925 -0.101226806640625 0.8143812500000001 +0.179375 -0.06365966796875 0.8143812500000001 +0.1795 -0.021270751953125 0.8143812500000001 0.179625 0.01702880859375 0.8143812500000001 0.17975 0.0594482421875 0.8143812500000001 0.179875 0.101226806640625 0.8143812500000001 @@ -1466,37 +1466,37 @@ 0.183125 0.11358642578125 0.8143812500000001 0.18325 0.07208251953125 0.8143812500000001 0.183375 0.0340576171875 0.8143812500000001 -0.1835 -0.008544921875 0.8143812500000001 -0.183625 -0.051025390625 0.8143812500000001 -0.18375 -0.088836669921875 0.8143812500000001 -0.183875 -0.1298828125 0.8143812500000001 -0.184 -0.165618896484375 0.8143812500000001 -0.184125 -0.203582763671875 0.8143812500000001 -0.18425 -0.23931884765625 0.8143812500000001 -0.184375 -0.269287109375 0.8143812500000001 -0.1845 -0.299713134765625 0.8143812500000001 -0.184625 -0.3243408203125 0.8143812500000001 -0.18475 -0.348297119140625 0.8143812500000001 -0.184875 -0.368438720703125 0.8143812500000001 -0.185 -0.383087158203125 0.8143812500000001 -0.185125 -0.395416259765625 0.8143812500000001 -0.18525 -0.402801513671875 0.8143812500000001 -0.185375 -0.406829833984375 0.8143812500000001 -0.1855 -0.4063720703125 0.8143812500000001 -0.185625 -0.40216064453125 0.8143812500000001 -0.18575 -0.393310546875 0.8143812500000001 -0.185875 -0.381622314453125 0.8143812500000001 -0.186 -0.364715576171875 0.8143812500000001 -0.186125 -0.34381103515625 0.8143812500000001 -0.18625 -0.321746826171875 0.8143812500000001 -0.186375 -0.29388427734375 0.8143812500000001 -0.1865 -0.26605224609375 0.8143812500000001 -0.186625 -0.232391357421875 0.8143812500000001 -0.18675 -0.1961669921875 0.8143812500000001 -0.186875 -0.161712646484375 0.8143812500000001 -0.187 -0.12176513671875 0.8143812500000001 -0.187125 -0.08465576171875 0.8143812500000001 -0.18725 -0.042572021484375 0.8143812500000001 +0.1835 -0.008514404296875 0.8143812500000001 +0.183625 -0.050994873046875 0.8143812500000001 +0.18375 -0.08880615234375 0.8143812500000001 +0.183875 -0.129852294921875 0.8143812500000001 +0.184 -0.16558837890625 0.8143812500000001 +0.184125 -0.20355224609375 0.8143812500000001 +0.18425 -0.239288330078125 0.8143812500000001 +0.184375 -0.269256591796875 0.8143812500000001 +0.1845 -0.2996826171875 0.8143812500000001 +0.184625 -0.324310302734375 0.8143812500000001 +0.18475 -0.3482666015625 0.8143812500000001 +0.184875 -0.368408203125 0.8143812500000001 +0.185 -0.383056640625 0.8143812500000001 +0.185125 -0.3953857421875 0.8143812500000001 +0.18525 -0.40277099609375 0.8143812500000001 +0.185375 -0.40679931640625 0.8143812500000001 +0.1855 -0.406341552734375 0.8143812500000001 +0.185625 -0.402130126953125 0.8143812500000001 +0.18575 -0.393280029296875 0.8143812500000001 +0.185875 -0.381591796875 0.8143812500000001 +0.186 -0.36468505859375 0.8143812500000001 +0.186125 -0.343780517578125 0.8143812500000001 +0.18625 -0.32171630859375 0.8143812500000001 +0.186375 -0.293853759765625 0.8143812500000001 +0.1865 -0.266021728515625 0.8143812500000001 +0.186625 -0.23236083984375 0.8143812500000001 +0.18675 -0.196136474609375 0.8143812500000001 +0.186875 -0.16168212890625 0.8143812500000001 +0.187 -0.121734619140625 0.8143812500000001 +0.187125 -0.084625244140625 0.8143812500000001 +0.18725 -0.04254150390625 0.8143812500000001 0.187375 0.0 0.8143812500000001 0.1875 0.038299560546875 0.8143812500000001 0.187625 0.0804443359375 0.8143812500000001 @@ -1529,37 +1529,37 @@ 0.191 0.09295654296875 0.8143812500000001 0.191125 0.050994873046875 0.8143812500000001 0.19125 0.01275634765625 0.8143812500000001 -0.191375 -0.029815673828125 0.8143812500000001 -0.1915 -0.067901611328125 0.8143812500000001 -0.191625 -0.1094970703125 0.8143812500000001 -0.19175 -0.14990234375 0.8143812500000001 -0.191875 -0.184844970703125 0.8143812500000001 -0.192 -0.249664306640625 0.9167781250000001 -0.192125 -0.28472900390625 0.9167781250000001 -0.19225 -0.320709228515625 0.9167781250000001 -0.192375 -0.353179931640625 0.9167781250000001 -0.1925 -0.37908935546875 0.9167781250000001 -0.192625 -0.403961181640625 0.9167781250000001 -0.19275 -0.42254638671875 0.9167781250000001 -0.192875 -0.438812255859375 0.9167781250000001 -0.193 -0.45025634765625 0.9167781250000001 -0.193125 -0.456329345703125 0.9167781250000001 -0.19325 -0.458343505859375 0.9167781250000001 -0.193375 -0.45587158203125 0.9167781250000001 -0.1935 -0.448333740234375 0.9167781250000001 -0.193625 -0.435943603515625 0.9167781250000001 -0.19375 -0.420684814453125 0.9167781250000001 -0.193875 -0.39935302734375 0.9167781250000001 -0.194 -0.37640380859375 0.9167781250000001 -0.194125 -0.34698486328125 0.9167781250000001 -0.19425 -0.31378173828125 0.9167781250000001 -0.194375 -0.28094482421875 0.9167781250000001 -0.1945 -0.241546630859375 0.9167781250000001 -0.194625 -0.203826904296875 0.9167781250000001 -0.19475 -0.1597900390625 0.9167781250000001 -0.194875 -0.113983154296875 0.9167781250000001 -0.195 -0.07171630859375 0.9167781250000001 -0.195125 -0.02398681640625 0.9167781250000001 +0.191375 -0.02978515625 0.8143812500000001 +0.1915 -0.06787109375 0.8143812500000001 +0.191625 -0.109466552734375 0.8143812500000001 +0.19175 -0.149871826171875 0.8143812500000001 +0.191875 -0.184814453125 0.8143812500000001 +0.192 -0.2496337890625 0.9167781250000001 +0.192125 -0.284698486328125 0.9167781250000001 +0.19225 -0.3206787109375 0.9167781250000001 +0.192375 -0.3531494140625 0.9167781250000001 +0.1925 -0.379058837890625 0.9167781250000001 +0.192625 -0.4039306640625 0.9167781250000001 +0.19275 -0.422515869140625 0.9167781250000001 +0.192875 -0.43878173828125 0.9167781250000001 +0.193 -0.450225830078125 0.9167781250000001 +0.193125 -0.456298828125 0.9167781250000001 +0.19325 -0.45831298828125 0.9167781250000001 +0.193375 -0.455841064453125 0.9167781250000001 +0.1935 -0.44830322265625 0.9167781250000001 +0.193625 -0.4359130859375 0.9167781250000001 +0.19375 -0.420654296875 0.9167781250000001 +0.193875 -0.399322509765625 0.9167781250000001 +0.194 -0.376373291015625 0.9167781250000001 +0.194125 -0.346954345703125 0.9167781250000001 +0.19425 -0.313751220703125 0.9167781250000001 +0.194375 -0.280914306640625 0.9167781250000001 +0.1945 -0.24151611328125 0.9167781250000001 +0.194625 -0.20379638671875 0.9167781250000001 +0.19475 -0.159759521484375 0.9167781250000001 +0.194875 -0.11395263671875 0.9167781250000001 +0.195 -0.071685791015625 0.9167781250000001 +0.195125 -0.023956298828125 0.9167781250000001 0.19525 0.0191650390625 0.9167781250000001 0.195375 0.066925048828125 0.9167781250000001 0.1955 0.11395263671875 0.9167781250000001 @@ -1591,37 +1591,37 @@ 0.19875 0.127838134765625 0.9167781250000001 0.198875 0.081146240234375 0.9167781250000001 0.199 0.038330078125 0.9167781250000001 -0.199125 -0.009613037109375 0.9167781250000001 -0.19925 -0.057464599609375 0.9167781250000001 -0.199375 -0.0999755859375 0.9167781250000001 -0.1995 -0.146209716796875 0.9167781250000001 -0.199625 -0.186431884765625 0.9167781250000001 -0.19975 -0.22918701171875 0.9167781250000001 -0.199875 -0.2694091796875 0.9167781250000001 -0.2 -0.303131103515625 0.9167781250000001 -0.200125 -0.33740234375 0.9167781250000001 -0.20025 -0.3651123046875 0.9167781250000001 -0.200375 -0.392059326171875 0.9167781250000001 -0.2005 -0.41473388671875 0.9167781250000001 -0.200625 -0.4312744140625 0.9167781250000001 -0.20075 -0.44512939453125 0.9167781250000001 -0.200875 -0.453460693359375 0.9167781250000001 -0.201 -0.457977294921875 0.9167781250000001 -0.201125 -0.45745849609375 0.9167781250000001 -0.20125 -0.452728271484375 0.9167781250000001 -0.201375 -0.4427490234375 0.9167781250000001 -0.2015 -0.42962646484375 0.9167781250000001 -0.201625 -0.410552978515625 0.9167781250000001 -0.20175 -0.38702392578125 0.9167781250000001 -0.201875 -0.3621826171875 0.9167781250000001 -0.202 -0.330841064453125 0.9167781250000001 -0.202125 -0.29949951171875 0.9167781250000001 -0.20225 -0.2615966796875 0.9167781250000001 -0.202375 -0.2208251953125 0.9167781250000001 -0.2025 -0.182037353515625 0.9167781250000001 -0.202625 -0.1370849609375 0.9167781250000001 -0.20275 -0.095306396484375 0.9167781250000001 -0.202875 -0.04791259765625 0.9167781250000001 +0.199125 -0.00958251953125 0.9167781250000001 +0.19925 -0.05743408203125 0.9167781250000001 +0.199375 -0.099945068359375 0.9167781250000001 +0.1995 -0.14617919921875 0.9167781250000001 +0.199625 -0.1864013671875 0.9167781250000001 +0.19975 -0.229156494140625 0.9167781250000001 +0.199875 -0.269378662109375 0.9167781250000001 +0.2 -0.3031005859375 0.9167781250000001 +0.200125 -0.337371826171875 0.9167781250000001 +0.20025 -0.365081787109375 0.9167781250000001 +0.200375 -0.39202880859375 0.9167781250000001 +0.2005 -0.414703369140625 0.9167781250000001 +0.200625 -0.431243896484375 0.9167781250000001 +0.20075 -0.445098876953125 0.9167781250000001 +0.200875 -0.45343017578125 0.9167781250000001 +0.201 -0.45794677734375 0.9167781250000001 +0.201125 -0.457427978515625 0.9167781250000001 +0.20125 -0.45269775390625 0.9167781250000001 +0.201375 -0.442718505859375 0.9167781250000001 +0.2015 -0.429595947265625 0.9167781250000001 +0.201625 -0.4105224609375 0.9167781250000001 +0.20175 -0.386993408203125 0.9167781250000001 +0.201875 -0.362152099609375 0.9167781250000001 +0.202 -0.330810546875 0.9167781250000001 +0.202125 -0.299468994140625 0.9167781250000001 +0.20225 -0.261566162109375 0.9167781250000001 +0.202375 -0.220794677734375 0.9167781250000001 +0.2025 -0.1820068359375 0.9167781250000001 +0.202625 -0.137054443359375 0.9167781250000001 +0.20275 -0.09527587890625 0.9167781250000001 +0.202875 -0.047882080078125 0.9167781250000001 0.203 0.0 0.9167781250000001 0.203125 0.043121337890625 0.9167781250000001 0.20325 0.090576171875 0.9167781250000001 @@ -1654,37 +1654,37 @@ 0.206625 0.104644775390625 0.9167781250000001 0.20675 0.05743408203125 0.9167781250000001 0.206875 0.014373779296875 0.9167781250000001 -0.207 -0.0335693359375 0.9167781250000001 -0.207125 -0.076446533203125 0.9167781250000001 -0.20725 -0.123260498046875 0.9167781250000001 -0.207375 -0.168731689453125 0.9167781250000001 -0.2075 -0.208099365234375 0.9167781250000001 -0.207625 -0.249664306640625 0.9167781250000001 -0.20775 -0.28472900390625 0.9167781250000001 -0.207875 -0.320709228515625 0.9167781250000001 -0.208 -0.353179931640625 0.9167781250000001 -0.208125 -0.37908935546875 0.9167781250000001 -0.20825 -0.403961181640625 0.9167781250000001 -0.208375 -0.42254638671875 0.9167781250000001 -0.2085 -0.438812255859375 0.9167781250000001 -0.208625 -0.45025634765625 0.9167781250000001 -0.20875 -0.456329345703125 0.9167781250000001 -0.208875 -0.458343505859375 0.9167781250000001 -0.209 -0.45587158203125 0.9167781250000001 -0.209125 -0.448333740234375 0.9167781250000001 -0.20925 -0.435943603515625 0.9167781250000001 -0.209375 -0.420684814453125 0.9167781250000001 -0.2095 -0.39935302734375 0.9167781250000001 -0.209625 -0.37640380859375 0.9167781250000001 -0.20975 -0.34698486328125 0.9167781250000001 -0.209875 -0.31378173828125 0.9167781250000001 -0.21 -0.28094482421875 0.9167781250000001 -0.210125 -0.241546630859375 0.9167781250000001 -0.21025 -0.203826904296875 0.9167781250000001 -0.210375 -0.1597900390625 0.9167781250000001 -0.2105 -0.113983154296875 0.9167781250000001 -0.210625 -0.07171630859375 0.9167781250000001 -0.21075 -0.02398681640625 0.9167781250000001 +0.207 -0.033538818359375 0.9167781250000001 +0.207125 -0.076416015625 0.9167781250000001 +0.20725 -0.12322998046875 0.9167781250000001 +0.207375 -0.168701171875 0.9167781250000001 +0.2075 -0.20806884765625 0.9167781250000001 +0.207625 -0.2496337890625 0.9167781250000001 +0.20775 -0.284698486328125 0.9167781250000001 +0.207875 -0.3206787109375 0.9167781250000001 +0.208 -0.3531494140625 0.9167781250000001 +0.208125 -0.379058837890625 0.9167781250000001 +0.20825 -0.4039306640625 0.9167781250000001 +0.208375 -0.422515869140625 0.9167781250000001 +0.2085 -0.43878173828125 0.9167781250000001 +0.208625 -0.450225830078125 0.9167781250000001 +0.20875 -0.456298828125 0.9167781250000001 +0.208875 -0.45831298828125 0.9167781250000001 +0.209 -0.455841064453125 0.9167781250000001 +0.209125 -0.44830322265625 0.9167781250000001 +0.20925 -0.4359130859375 0.9167781250000001 +0.209375 -0.420654296875 0.9167781250000001 +0.2095 -0.399322509765625 0.9167781250000001 +0.209625 -0.376373291015625 0.9167781250000001 +0.20975 -0.346954345703125 0.9167781250000001 +0.209875 -0.313751220703125 0.9167781250000001 +0.21 -0.280914306640625 0.9167781250000001 +0.210125 -0.24151611328125 0.9167781250000001 +0.21025 -0.20379638671875 0.9167781250000001 +0.210375 -0.159759521484375 0.9167781250000001 +0.2105 -0.11395263671875 0.9167781250000001 +0.210625 -0.071685791015625 0.9167781250000001 +0.21075 -0.023956298828125 0.9167781250000001 0.210875 0.0191650390625 0.9167781250000001 0.211 0.066925048828125 0.9167781250000001 0.211125 0.11395263671875 0.9167781250000001 @@ -1716,37 +1716,37 @@ 0.214375 0.127838134765625 0.9167781250000001 0.2145 0.081146240234375 0.9167781250000001 0.214625 0.038330078125 0.9167781250000001 -0.21475 -0.009613037109375 0.9167781250000001 -0.214875 -0.057464599609375 0.9167781250000001 -0.215 -0.0999755859375 0.9167781250000001 -0.215125 -0.146209716796875 0.9167781250000001 -0.21525 -0.186431884765625 0.9167781250000001 -0.215375 -0.22918701171875 0.9167781250000001 -0.2155 -0.2694091796875 0.9167781250000001 -0.215625 -0.303131103515625 0.9167781250000001 -0.21575 -0.33740234375 0.9167781250000001 -0.215875 -0.3651123046875 0.9167781250000001 -0.216 -0.392059326171875 0.9167781250000001 -0.216125 -0.41473388671875 0.9167781250000001 -0.21625 -0.4312744140625 0.9167781250000001 -0.216375 -0.44512939453125 0.9167781250000001 -0.2165 -0.453460693359375 0.9167781250000001 -0.216625 -0.457977294921875 0.9167781250000001 -0.21675 -0.45745849609375 0.9167781250000001 -0.216875 -0.452728271484375 0.9167781250000001 -0.217 -0.4427490234375 0.9167781250000001 -0.217125 -0.42962646484375 0.9167781250000001 -0.21725 -0.410552978515625 0.9167781250000001 -0.217375 -0.38702392578125 0.9167781250000001 -0.2175 -0.3621826171875 0.9167781250000001 -0.217625 -0.330841064453125 0.9167781250000001 -0.21775 -0.29949951171875 0.9167781250000001 -0.217875 -0.2615966796875 0.9167781250000001 -0.218 -0.2208251953125 0.9167781250000001 -0.218125 -0.182037353515625 0.9167781250000001 -0.21825 -0.1370849609375 0.9167781250000001 -0.218375 -0.095306396484375 0.9167781250000001 -0.2185 -0.04791259765625 0.9167781250000001 +0.21475 -0.00958251953125 0.9167781250000001 +0.214875 -0.05743408203125 0.9167781250000001 +0.215 -0.099945068359375 0.9167781250000001 +0.215125 -0.14617919921875 0.9167781250000001 +0.21525 -0.1864013671875 0.9167781250000001 +0.215375 -0.229156494140625 0.9167781250000001 +0.2155 -0.269378662109375 0.9167781250000001 +0.215625 -0.3031005859375 0.9167781250000001 +0.21575 -0.337371826171875 0.9167781250000001 +0.215875 -0.365081787109375 0.9167781250000001 +0.216 -0.39202880859375 0.9167781250000001 +0.216125 -0.414703369140625 0.9167781250000001 +0.21625 -0.431243896484375 0.9167781250000001 +0.216375 -0.445098876953125 0.9167781250000001 +0.2165 -0.45343017578125 0.9167781250000001 +0.216625 -0.45794677734375 0.9167781250000001 +0.21675 -0.457427978515625 0.9167781250000001 +0.216875 -0.45269775390625 0.9167781250000001 +0.217 -0.442718505859375 0.9167781250000001 +0.217125 -0.429595947265625 0.9167781250000001 +0.21725 -0.4105224609375 0.9167781250000001 +0.217375 -0.386993408203125 0.9167781250000001 +0.2175 -0.362152099609375 0.9167781250000001 +0.217625 -0.330810546875 0.9167781250000001 +0.21775 -0.299468994140625 0.9167781250000001 +0.217875 -0.261566162109375 0.9167781250000001 +0.218 -0.220794677734375 0.9167781250000001 +0.218125 -0.1820068359375 0.9167781250000001 +0.21825 -0.137054443359375 0.9167781250000001 +0.218375 -0.09527587890625 0.9167781250000001 +0.2185 -0.047882080078125 0.9167781250000001 0.218625 0.0 0.9167781250000001 0.21875 0.043121337890625 0.9167781250000001 0.218875 0.090576171875 0.9167781250000001 @@ -1779,37 +1779,37 @@ 0.22225 0.104644775390625 0.9167781250000001 0.222375 0.05743408203125 0.9167781250000001 0.2225 0.014373779296875 0.9167781250000001 -0.222625 -0.0335693359375 0.9167781250000001 -0.22275 -0.076446533203125 0.9167781250000001 -0.222875 -0.123260498046875 0.9167781250000001 -0.223 -0.168731689453125 0.9167781250000001 -0.223125 -0.208099365234375 0.9167781250000001 -0.22325 -0.249664306640625 0.9167781250000001 -0.223375 -0.28472900390625 0.9167781250000001 -0.2235 -0.320709228515625 0.9167781250000001 -0.223625 -0.353179931640625 0.9167781250000001 -0.22375 -0.37908935546875 0.9167781250000001 -0.223875 -0.403961181640625 0.9167781250000001 -0.224 -0.46087646484375 0.9999511726200581 -0.224125 -0.478607177734375 0.9999511726200581 -0.22425 -0.4910888671875 0.9999511726200581 -0.224375 -0.49774169921875 0.9999511726200581 -0.2245 -0.49993896484375 0.9999511726200581 -0.224625 -0.497222900390625 0.9999511726200581 -0.22475 -0.489013671875 0.9999511726200581 -0.224875 -0.475494384765625 0.9999511726200581 -0.225 -0.458831787109375 0.9999511726200581 -0.225125 -0.435577392578125 0.9999511726200581 -0.22525 -0.4105224609375 0.9999511726200581 -0.225375 -0.378448486328125 0.9999511726200581 -0.2255 -0.34222412109375 0.9999511726200581 -0.225625 -0.306427001953125 0.9999511726200581 -0.22575 -0.263458251953125 0.9999511726200581 -0.225875 -0.2222900390625 0.9999511726200581 -0.226 -0.17425537109375 0.9999511726200581 -0.226125 -0.12432861328125 0.9999511726200581 -0.22625 -0.078216552734375 0.9999511726200581 -0.226375 -0.026153564453125 0.9999511726200581 +0.222625 -0.033538818359375 0.9167781250000001 +0.22275 -0.076416015625 0.9167781250000001 +0.222875 -0.12322998046875 0.9167781250000001 +0.223 -0.168701171875 0.9167781250000001 +0.223125 -0.20806884765625 0.9167781250000001 +0.22325 -0.2496337890625 0.9167781250000001 +0.223375 -0.284698486328125 0.9167781250000001 +0.2235 -0.3206787109375 0.9167781250000001 +0.223625 -0.3531494140625 0.9167781250000001 +0.22375 -0.379058837890625 0.9167781250000001 +0.223875 -0.4039306640625 0.9167781250000001 +0.224 -0.460845947265625 0.9999511726200581 +0.224125 -0.47857666015625 0.9999511726200581 +0.22425 -0.491058349609375 0.9999511726200581 +0.224375 -0.497711181640625 0.9999511726200581 +0.2245 -0.499908447265625 0.9999511726200581 +0.224625 -0.4971923828125 0.9999511726200581 +0.22475 -0.488983154296875 0.9999511726200581 +0.224875 -0.4754638671875 0.9999511726200581 +0.225 -0.45880126953125 0.9999511726200581 +0.225125 -0.435546875 0.9999511726200581 +0.22525 -0.410491943359375 0.9999511726200581 +0.225375 -0.37841796875 0.9999511726200581 +0.2255 -0.342193603515625 0.9999511726200581 +0.225625 -0.306396484375 0.9999511726200581 +0.22575 -0.263427734375 0.9999511726200581 +0.225875 -0.222259521484375 0.9999511726200581 +0.226 -0.174224853515625 0.9999511726200581 +0.226125 -0.124298095703125 0.9999511726200581 +0.22625 -0.07818603515625 0.9999511726200581 +0.226375 -0.026123046875 0.9999511726200581 0.2265 0.020904541015625 0.9999511726200581 0.226625 0.072998046875 0.9999511726200581 0.22675 0.124298095703125 0.9999511726200581 @@ -1841,37 +1841,37 @@ 0.23 0.13946533203125 0.9999511726200581 0.230125 0.0885009765625 0.9999511726200581 0.23025 0.04180908203125 0.9999511726200581 -0.230375 -0.010467529296875 0.9999511726200581 -0.2305 -0.062652587890625 0.9999511726200581 -0.230625 -0.10906982421875 0.9999511726200581 -0.23075 -0.15948486328125 0.9999511726200581 -0.230875 -0.203338623046875 0.9999511726200581 -0.231 -0.249969482421875 0.9999511726200581 -0.231125 -0.293853759765625 0.9999511726200581 -0.23125 -0.33062744140625 0.9999511726200581 -0.231375 -0.368011474609375 0.9999511726200581 -0.2315 -0.398223876953125 0.9999511726200581 -0.231625 -0.427642822265625 0.9999511726200581 -0.23175 -0.452362060546875 0.9999511726200581 -0.231875 -0.47039794921875 0.9999511726200581 -0.232 -0.48553466796875 0.9999511726200581 -0.232125 -0.494598388671875 0.9999511726200581 -0.23225 -0.49951171875 0.9999511726200581 -0.232375 -0.49896240234375 0.9999511726200581 -0.2325 -0.493804931640625 0.9999511726200581 -0.232625 -0.48291015625 0.9999511726200581 -0.23275 -0.468597412109375 0.9999511726200581 -0.232875 -0.44781494140625 0.9999511726200581 -0.233 -0.422119140625 0.9999511726200581 -0.233125 -0.395050048828125 0.9999511726200581 -0.23325 -0.36083984375 0.9999511726200581 -0.233375 -0.326690673828125 0.9999511726200581 -0.2335 -0.28533935546875 0.9999511726200581 -0.233625 -0.2408447265625 0.9999511726200581 -0.23375 -0.19854736328125 0.9999511726200581 -0.233875 -0.149505615234375 0.9999511726200581 -0.234 -0.10394287109375 0.9999511726200581 -0.234125 -0.052276611328125 0.9999511726200581 +0.230375 -0.01043701171875 0.9999511726200581 +0.2305 -0.0626220703125 0.9999511726200581 +0.230625 -0.109039306640625 0.9999511726200581 +0.23075 -0.159454345703125 0.9999511726200581 +0.230875 -0.20330810546875 0.9999511726200581 +0.231 -0.24993896484375 0.9999511726200581 +0.231125 -0.2938232421875 0.9999511726200581 +0.23125 -0.330596923828125 0.9999511726200581 +0.231375 -0.36798095703125 0.9999511726200581 +0.2315 -0.398193359375 0.9999511726200581 +0.231625 -0.4276123046875 0.9999511726200581 +0.23175 -0.45233154296875 0.9999511726200581 +0.231875 -0.470367431640625 0.9999511726200581 +0.232 -0.485504150390625 0.9999511726200581 +0.232125 -0.49456787109375 0.9999511726200581 +0.23225 -0.499481201171875 0.9999511726200581 +0.232375 -0.498931884765625 0.9999511726200581 +0.2325 -0.4937744140625 0.9999511726200581 +0.232625 -0.482879638671875 0.9999511726200581 +0.23275 -0.46856689453125 0.9999511726200581 +0.232875 -0.447784423828125 0.9999511726200581 +0.233 -0.422088623046875 0.9999511726200581 +0.233125 -0.39501953125 0.9999511726200581 +0.23325 -0.360809326171875 0.9999511726200581 +0.233375 -0.32666015625 0.9999511726200581 +0.2335 -0.285308837890625 0.9999511726200581 +0.233625 -0.240814208984375 0.9999511726200581 +0.23375 -0.198516845703125 0.9999511726200581 +0.233875 -0.14947509765625 0.9999511726200581 +0.234 -0.103912353515625 0.9999511726200581 +0.234125 -0.05224609375 0.9999511726200581 0.23425 0.0 0.9999511726200581 0.234375 0.047027587890625 0.9999511726200581 0.2345 0.098785400390625 0.9999511726200581 @@ -1904,37 +1904,37 @@ 0.237875 0.1141357421875 0.9999511726200581 0.238 0.0626220703125 0.9999511726200581 0.238125 0.01568603515625 0.9999511726200581 -0.23825 -0.03662109375 0.9999511726200581 -0.238375 -0.0833740234375 0.9999511726200581 -0.2385 -0.13446044921875 0.9999511726200581 -0.238625 -0.184051513671875 0.9999511726200581 -0.23875 -0.226959228515625 0.9999511726200581 -0.238875 -0.272308349609375 0.9999511726200581 -0.239 -0.310546875 0.9999511726200581 -0.239125 -0.34979248046875 0.9999511726200581 -0.23925 -0.385223388671875 0.9999511726200581 -0.239375 -0.413482666015625 0.9999511726200581 -0.2395 -0.44061279296875 0.9999511726200581 -0.239625 -0.46087646484375 0.9999511726200581 -0.23975 -0.478607177734375 0.9999511726200581 -0.239875 -0.4910888671875 0.9999511726200581 -0.24 -0.49774169921875 0.9999511726200581 -0.240125 -0.49993896484375 0.9999511726200581 -0.24025 -0.497222900390625 0.9999511726200581 -0.240375 -0.489013671875 0.9999511726200581 -0.2405 -0.475494384765625 0.9999511726200581 -0.240625 -0.458831787109375 0.9999511726200581 -0.24075 -0.435577392578125 0.9999511726200581 -0.240875 -0.4105224609375 0.9999511726200581 -0.241 -0.378448486328125 0.9999511726200581 -0.241125 -0.34222412109375 0.9999511726200581 -0.24125 -0.306427001953125 0.9999511726200581 -0.241375 -0.263458251953125 0.9999511726200581 -0.2415 -0.2222900390625 0.9999511726200581 -0.241625 -0.17425537109375 0.9999511726200581 -0.24175 -0.12432861328125 0.9999511726200581 -0.241875 -0.078216552734375 0.9999511726200581 -0.242 -0.026153564453125 0.9999511726200581 +0.23825 -0.036590576171875 0.9999511726200581 +0.238375 -0.083343505859375 0.9999511726200581 +0.2385 -0.134429931640625 0.9999511726200581 +0.238625 -0.18402099609375 0.9999511726200581 +0.23875 -0.2269287109375 0.9999511726200581 +0.238875 -0.27227783203125 0.9999511726200581 +0.239 -0.310516357421875 0.9999511726200581 +0.239125 -0.349761962890625 0.9999511726200581 +0.23925 -0.38519287109375 0.9999511726200581 +0.239375 -0.4134521484375 0.9999511726200581 +0.2395 -0.440582275390625 0.9999511726200581 +0.239625 -0.460845947265625 0.9999511726200581 +0.23975 -0.47857666015625 0.9999511726200581 +0.239875 -0.491058349609375 0.9999511726200581 +0.24 -0.497711181640625 0.9999511726200581 +0.240125 -0.499908447265625 0.9999511726200581 +0.24025 -0.4971923828125 0.9999511726200581 +0.240375 -0.488983154296875 0.9999511726200581 +0.2405 -0.4754638671875 0.9999511726200581 +0.240625 -0.45880126953125 0.9999511726200581 +0.24075 -0.435546875 0.9999511726200581 +0.240875 -0.410491943359375 0.9999511726200581 +0.241 -0.37841796875 0.9999511726200581 +0.241125 -0.342193603515625 0.9999511726200581 +0.24125 -0.306396484375 0.9999511726200581 +0.241375 -0.263427734375 0.9999511726200581 +0.2415 -0.222259521484375 0.9999511726200581 +0.241625 -0.174224853515625 0.9999511726200581 +0.24175 -0.124298095703125 0.9999511726200581 +0.241875 -0.07818603515625 0.9999511726200581 +0.242 -0.026123046875 0.9999511726200581 0.242125 0.020904541015625 0.9999511726200581 0.24225 0.072998046875 0.9999511726200581 0.242375 0.124298095703125 0.9999511726200581 @@ -1966,37 +1966,37 @@ 0.245625 0.13946533203125 0.9999511726200581 0.24575 0.0885009765625 0.9999511726200581 0.245875 0.04180908203125 0.9999511726200581 -0.246 -0.010467529296875 0.9999511726200581 -0.246125 -0.062652587890625 0.9999511726200581 -0.24625 -0.10906982421875 0.9999511726200581 -0.246375 -0.15948486328125 0.9999511726200581 -0.2465 -0.203338623046875 0.9999511726200581 -0.246625 -0.249969482421875 0.9999511726200581 -0.24675 -0.293853759765625 0.9999511726200581 -0.246875 -0.33062744140625 0.9999511726200581 -0.247 -0.368011474609375 0.9999511726200581 -0.247125 -0.398223876953125 0.9999511726200581 -0.24725 -0.427642822265625 0.9999511726200581 -0.247375 -0.452362060546875 0.9999511726200581 -0.2475 -0.47039794921875 0.9999511726200581 -0.247625 -0.48553466796875 0.9999511726200581 -0.24775 -0.494598388671875 0.9999511726200581 -0.247875 -0.49951171875 0.9999511726200581 -0.248 -0.49896240234375 0.9999511726200581 -0.248125 -0.493804931640625 0.9999511726200581 -0.24825 -0.48291015625 0.9999511726200581 -0.248375 -0.468597412109375 0.9999511726200581 -0.2485 -0.44781494140625 0.9999511726200581 -0.248625 -0.422119140625 0.9999511726200581 -0.24875 -0.395050048828125 0.9999511726200581 -0.248875 -0.36083984375 0.9999511726200581 -0.249 -0.326690673828125 0.9999511726200581 -0.249125 -0.28533935546875 0.9999511726200581 -0.24925 -0.2408447265625 0.9999511726200581 -0.249375 -0.19854736328125 0.9999511726200581 -0.2495 -0.149505615234375 0.9999511726200581 -0.249625 -0.10394287109375 0.9999511726200581 -0.24975 -0.052276611328125 0.9999511726200581 +0.246 -0.01043701171875 0.9999511726200581 +0.246125 -0.0626220703125 0.9999511726200581 +0.24625 -0.109039306640625 0.9999511726200581 +0.246375 -0.159454345703125 0.9999511726200581 +0.2465 -0.20330810546875 0.9999511726200581 +0.246625 -0.24993896484375 0.9999511726200581 +0.24675 -0.2938232421875 0.9999511726200581 +0.246875 -0.330596923828125 0.9999511726200581 +0.247 -0.36798095703125 0.9999511726200581 +0.247125 -0.398193359375 0.9999511726200581 +0.24725 -0.4276123046875 0.9999511726200581 +0.247375 -0.45233154296875 0.9999511726200581 +0.2475 -0.470367431640625 0.9999511726200581 +0.247625 -0.485504150390625 0.9999511726200581 +0.24775 -0.49456787109375 0.9999511726200581 +0.247875 -0.499481201171875 0.9999511726200581 +0.248 -0.498931884765625 0.9999511726200581 +0.248125 -0.4937744140625 0.9999511726200581 +0.24825 -0.482879638671875 0.9999511726200581 +0.248375 -0.46856689453125 0.9999511726200581 +0.2485 -0.447784423828125 0.9999511726200581 +0.248625 -0.422088623046875 0.9999511726200581 +0.24875 -0.39501953125 0.9999511726200581 +0.248875 -0.360809326171875 0.9999511726200581 +0.249 -0.32666015625 0.9999511726200581 +0.249125 -0.285308837890625 0.9999511726200581 +0.24925 -0.240814208984375 0.9999511726200581 +0.249375 -0.198516845703125 0.9999511726200581 +0.2495 -0.14947509765625 0.9999511726200581 +0.249625 -0.103912353515625 0.9999511726200581 +0.24975 -0.05224609375 0.9999511726200581 0.249875 0.0 0.9999511726200581 0.25 0.047027587890625 0.9999511726200581 0.250125 0.098785400390625 0.9999511726200581 @@ -2029,20 +2029,20 @@ 0.2535 0.1141357421875 0.9999511726200581 0.253625 0.0626220703125 0.9999511726200581 0.2537500000000001 0.01568603515625 0.9999511726200581 -0.253875 -0.03662109375 0.9999511726200581 -0.254 -0.0833740234375 0.9999511726200581 -0.254125 -0.13446044921875 0.9999511726200581 -0.25425 -0.184051513671875 0.9999511726200581 -0.254375 -0.226959228515625 0.9999511726200581 -0.2545 -0.272308349609375 0.9999511726200581 -0.254625 -0.310546875 0.9999511726200581 -0.25475 -0.34979248046875 0.9999511726200581 -0.254875 -0.385223388671875 0.9999511726200581 -0.255 -0.413482666015625 0.9999511726200581 -0.255125 -0.44061279296875 0.9999511726200581 -0.25525 -0.46087646484375 0.9999511726200581 -0.255375 -0.478607177734375 0.9999511726200581 -0.2555 -0.4910888671875 0.9999511726200581 -0.255625 -0.49774169921875 0.9999511726200581 -0.25575 -0.49993896484375 0.9999511726200581 -0.255875 -0.497222900390625 0.9999511726200581 +0.253875 -0.036590576171875 0.9999511726200581 +0.254 -0.083343505859375 0.9999511726200581 +0.254125 -0.134429931640625 0.9999511726200581 +0.25425 -0.18402099609375 0.9999511726200581 +0.254375 -0.2269287109375 0.9999511726200581 +0.2545 -0.27227783203125 0.9999511726200581 +0.254625 -0.310516357421875 0.9999511726200581 +0.25475 -0.349761962890625 0.9999511726200581 +0.254875 -0.38519287109375 0.9999511726200581 +0.255 -0.4134521484375 0.9999511726200581 +0.255125 -0.440582275390625 0.9999511726200581 +0.25525 -0.460845947265625 0.9999511726200581 +0.255375 -0.47857666015625 0.9999511726200581 +0.2555 -0.491058349609375 0.9999511726200581 +0.255625 -0.497711181640625 0.9999511726200581 +0.25575 -0.499908447265625 0.9999511726200581 +0.255875 -0.4971923828125 0.9999511726200581 diff --git a/tests/circuitpython/synth_note_ring.py.exp b/tests/circuitpython/synth_note_ring.py.exp index b45858d5aadc8..4335f62a65c2b 100644 --- a/tests/circuitpython/synth_note_ring.py.exp +++ b/tests/circuitpython/synth_note_ring.py.exp @@ -29,37 +29,37 @@ 0.0035 0.008331298828125 -0.743977294921875 0.003625 0.005218505859375 -0.743977294921875 0.00375 0.00128173828125 -0.743977294921875 -0.003875 -0.0030517578125 -0.743977294921875 -0.004 -0.006988525390625 -0.743977294921875 -0.004125 -0.01263427734375 -0.743977294921875 -0.00425 -0.017303466796875 -0.743977294921875 -0.004375000000000001 -0.0213623046875 -0.743977294921875 -0.004500000000000001 -0.025634765625 -0.743977294921875 -0.004625 -0.032470703125 -0.743977294921875 -0.00475 -0.03656005859375 -0.743977294921875 -0.004875 -0.040252685546875 -0.743977294921875 -0.005 -0.047515869140625 -0.743977294921875 -0.005125000000000001 -0.050628662109375 -0.743977294921875 -0.00525 -0.052978515625 -0.743977294921875 -0.005375000000000001 -0.055023193359375 -0.743977294921875 -0.005499999999999999 -0.061553955078125 -0.743977294921875 -0.005625 -0.0623779296875 -0.743977294921875 -0.00575 -0.062652587890625 -0.743977294921875 -0.005874999999999999 -0.06231689453125 -0.743977294921875 -0.006 -0.06634521484375 -0.743977294921875 -0.006125 -0.06451416015625 -0.743977294921875 -0.00625 -0.062255859375 -0.743977294921875 -0.006375 -0.059112548828125 -0.743977294921875 -0.0065 -0.059967041015625 -0.743977294921875 -0.006625000000000001 -0.055267333984375 -0.743977294921875 -0.00675 -0.04998779296875 -0.743977294921875 -0.006875 -0.047943115234375 -0.743977294921875 -0.007000000000000001 -0.04119873046875 -0.743977294921875 -0.007125000000000002 -0.034759521484375 -0.743977294921875 -0.007250000000000001 -0.027252197265625 -0.743977294921875 -0.007375 -0.020721435546875 -0.743977294921875 -0.0075 -0.013031005859375 -0.743977294921875 -0.007625 -0.004364013671875 -0.743977294921875 +0.003875 -0.003021240234375 -0.743977294921875 +0.004 -0.0069580078125 -0.743977294921875 +0.004125 -0.012603759765625 -0.743977294921875 +0.00425 -0.01727294921875 -0.743977294921875 +0.004375000000000001 -0.021331787109375 -0.743977294921875 +0.004500000000000001 -0.025604248046875 -0.743977294921875 +0.004625 -0.032440185546875 -0.743977294921875 +0.00475 -0.036529541015625 -0.743977294921875 +0.004875 -0.04022216796875 -0.743977294921875 +0.005 -0.0474853515625 -0.743977294921875 +0.005125000000000001 -0.05059814453125 -0.743977294921875 +0.00525 -0.052947998046875 -0.743977294921875 +0.005375000000000001 -0.05499267578125 -0.743977294921875 +0.005499999999999999 -0.0615234375 -0.743977294921875 +0.005625 -0.062347412109375 -0.743977294921875 +0.00575 -0.0626220703125 -0.743977294921875 +0.005874999999999999 -0.062286376953125 -0.743977294921875 +0.006 -0.066314697265625 -0.743977294921875 +0.006125 -0.064483642578125 -0.743977294921875 +0.00625 -0.062225341796875 -0.743977294921875 +0.006375 -0.05908203125 -0.743977294921875 +0.0065 -0.0599365234375 -0.743977294921875 +0.006625000000000001 -0.05523681640625 -0.743977294921875 +0.00675 -0.049957275390625 -0.743977294921875 +0.006875 -0.04791259765625 -0.743977294921875 +0.007000000000000001 -0.041168212890625 -0.743977294921875 +0.007125000000000002 -0.03472900390625 -0.743977294921875 +0.007250000000000001 -0.0272216796875 -0.743977294921875 +0.007375 -0.02069091796875 -0.743977294921875 +0.0075 -0.01300048828125 -0.743977294921875 +0.007625 -0.00433349609375 -0.743977294921875 0.00775 0.003448486328125 -0.743977294921875 0.007875 0.012908935546875 -0.743977294921875 0.008 0.02197265625 -0.743977294921875 @@ -91,37 +91,37 @@ 0.01125 0.034637451171875 -0.743977294921875 0.011375 0.02197265625 -0.743977294921875 0.0115 0.0103759765625 -0.743977294921875 -0.011625 -0.002716064453125 -0.743977294921875 -0.01175 -0.016204833984375 -0.743977294921875 -0.011875 -0.028228759765625 -0.743977294921875 -0.012 -0.042877197265625 -0.743977294921875 -0.012125 -0.0546875 -0.743977294921875 -0.01225 -0.067230224609375 -0.743977294921875 -0.012375 -0.079010009765625 -0.743977294921875 -0.0125 -0.09222412109375 -0.743977294921875 -0.012625 -0.1026611328125 -0.743977294921875 -0.01275 -0.111083984375 -0.743977294921875 -0.012875 -0.119293212890625 -0.743977294921875 -0.013 -0.1307373046875 -0.743977294921875 -0.013125 -0.135955810546875 -0.743977294921875 -0.01325 -0.14031982421875 -0.743977294921875 -0.013375 -0.14788818359375 -0.743977294921875 -0.0135 -0.149383544921875 -0.743977294921875 -0.013625 -0.149200439453125 -0.743977294921875 -0.01375 -0.14764404296875 -0.743977294921875 -0.013875 -0.14923095703125 -0.743977294921875 -0.014 -0.144805908203125 -0.743977294921875 -0.014125 -0.13836669921875 -0.743977294921875 -0.01425 -0.13043212890625 -0.743977294921875 -0.014375 -0.126007080078125 -0.743977294921875 -0.0145 -0.115081787109375 -0.743977294921875 -0.014625 -0.10418701171875 -0.743977294921875 -0.01475 -0.09100341796875 -0.743977294921875 -0.014875 -0.079193115234375 -0.743977294921875 -0.015 -0.0653076171875 -0.743977294921875 -0.015125 -0.049163818359375 -0.743977294921875 -0.01525 -0.03521728515625 -0.743977294921875 -0.015375 -0.0177001953125 -0.743977294921875 +0.011625 -0.002685546875 -0.743977294921875 +0.01175 -0.01617431640625 -0.743977294921875 +0.011875 -0.0281982421875 -0.743977294921875 +0.012 -0.0428466796875 -0.743977294921875 +0.012125 -0.054656982421875 -0.743977294921875 +0.01225 -0.06719970703125 -0.743977294921875 +0.012375 -0.0789794921875 -0.743977294921875 +0.0125 -0.092193603515625 -0.743977294921875 +0.012625 -0.102630615234375 -0.743977294921875 +0.01275 -0.111053466796875 -0.743977294921875 +0.012875 -0.1192626953125 -0.743977294921875 +0.013 -0.130706787109375 -0.743977294921875 +0.013125 -0.13592529296875 -0.743977294921875 +0.01325 -0.140289306640625 -0.743977294921875 +0.013375 -0.147857666015625 -0.743977294921875 +0.0135 -0.14935302734375 -0.743977294921875 +0.013625 -0.149169921875 -0.743977294921875 +0.01375 -0.147613525390625 -0.743977294921875 +0.013875 -0.149200439453125 -0.743977294921875 +0.014 -0.144775390625 -0.743977294921875 +0.014125 -0.138336181640625 -0.743977294921875 +0.01425 -0.130401611328125 -0.743977294921875 +0.014375 -0.1259765625 -0.743977294921875 +0.0145 -0.11505126953125 -0.743977294921875 +0.014625 -0.104156494140625 -0.743977294921875 +0.01475 -0.090972900390625 -0.743977294921875 +0.014875 -0.07916259765625 -0.743977294921875 +0.015 -0.065277099609375 -0.743977294921875 +0.015125 -0.04913330078125 -0.743977294921875 +0.01525 -0.035186767578125 -0.743977294921875 +0.015375 -0.017669677734375 -0.743977294921875 0.0155 0.0 -0.743977294921875 0.015625 0.015899658203125 -0.743977294921875 0.01575 0.034423828125 -0.743977294921875 @@ -154,37 +154,37 @@ 0.019125 0.0474853515625 -0.743977294921875 0.01925 0.02606201171875 -0.743977294921875 0.019375 0.006500244140625 -0.743977294921875 -0.0195 -0.015594482421875 -0.743977294921875 -0.019625 -0.035491943359375 -0.743977294921875 -0.01975 -0.0572509765625 -0.743977294921875 -0.019875 -0.078369140625 -0.743977294921875 -0.02 -0.098785400390625 -0.743977294921875 -0.020125 -0.118499755859375 -0.743977294921875 -0.02025 -0.135162353515625 -0.743977294921875 -0.020375 -0.155517578125 -0.743977294921875 -0.0205 -0.171295166015625 -0.743977294921875 -0.020625 -0.183837890625 -0.743977294921875 -0.02075 -0.1959228515625 -0.743977294921875 -0.020875 -0.209228515625 -0.743977294921875 -0.021 -0.21728515625 -0.743977294921875 -0.021125 -0.222930908203125 -0.743977294921875 -0.02125 -0.2259521484375 -0.743977294921875 -0.021375 -0.231597900390625 -0.743977294921875 -0.0215 -0.2303466796875 -0.743977294921875 -0.021625 -0.2265625 -0.743977294921875 -0.02175 -0.224700927734375 -0.743977294921875 -0.021875 -0.216827392578125 -0.743977294921875 -0.022 -0.205841064453125 -0.743977294921875 -0.022125 -0.194000244140625 -0.743977294921875 -0.02225 -0.18231201171875 -0.743977294921875 -0.022375 -0.16485595703125 -0.743977294921875 -0.0225 -0.147613525390625 -0.743977294921875 -0.022625 -0.126922607421875 -0.743977294921875 -0.02275 -0.109130859375 -0.743977294921875 -0.022875 -0.085540771484375 -0.743977294921875 -0.023 -0.06103515625 -0.743977294921875 -0.023125 -0.03839111328125 -0.743977294921875 -0.02325 -0.0130615234375 -0.743977294921875 +0.0195 -0.01556396484375 -0.743977294921875 +0.019625 -0.03546142578125 -0.743977294921875 +0.01975 -0.057220458984375 -0.743977294921875 +0.019875 -0.078338623046875 -0.743977294921875 +0.02 -0.0987548828125 -0.743977294921875 +0.020125 -0.11846923828125 -0.743977294921875 +0.02025 -0.1351318359375 -0.743977294921875 +0.020375 -0.155487060546875 -0.743977294921875 +0.0205 -0.1712646484375 -0.743977294921875 +0.020625 -0.183807373046875 -0.743977294921875 +0.02075 -0.195892333984375 -0.743977294921875 +0.020875 -0.209197998046875 -0.743977294921875 +0.021 -0.217254638671875 -0.743977294921875 +0.021125 -0.222900390625 -0.743977294921875 +0.02125 -0.225921630859375 -0.743977294921875 +0.021375 -0.2315673828125 -0.743977294921875 +0.0215 -0.230316162109375 -0.743977294921875 +0.021625 -0.226531982421875 -0.743977294921875 +0.02175 -0.22467041015625 -0.743977294921875 +0.021875 -0.216796875 -0.743977294921875 +0.022 -0.205810546875 -0.743977294921875 +0.022125 -0.1939697265625 -0.743977294921875 +0.02225 -0.182281494140625 -0.743977294921875 +0.022375 -0.164825439453125 -0.743977294921875 +0.0225 -0.1475830078125 -0.743977294921875 +0.022625 -0.12689208984375 -0.743977294921875 +0.02275 -0.109100341796875 -0.743977294921875 +0.022875 -0.08551025390625 -0.743977294921875 +0.023 -0.061004638671875 -0.743977294921875 +0.023125 -0.038360595703125 -0.743977294921875 +0.02325 -0.013031005859375 -0.743977294921875 0.023375 0.01043701171875 -0.743977294921875 0.0235 0.036468505859375 -0.743977294921875 0.023625 0.063262939453125 -0.743977294921875 @@ -216,37 +216,37 @@ 0.026875 0.079559326171875 -0.743977294921875 0.027 0.050506591796875 -0.743977294921875 0.027125 0.023834228515625 -0.743977294921875 -0.02725 -0.0059814453125 -0.743977294921875 -0.027375 -0.036285400390625 -0.743977294921875 -0.0275 -0.06317138671875 -0.743977294921875 -0.027625 -0.092376708984375 -0.743977294921875 -0.02775 -0.1177978515625 -0.743977294921875 -0.027875 -0.14691162109375 -0.743977294921875 -0.028 -0.1727294921875 -0.743977294921875 -0.028125 -0.1943359375 -0.743977294921875 -0.02825 -0.21942138671875 -0.743977294921875 -0.028375 -0.2374267578125 -0.743977294921875 -0.02850000000000001 -0.25494384765625 -0.743977294921875 -0.028625 -0.269683837890625 -0.743977294921875 -0.02875 -0.28436279296875 -0.743977294921875 -0.028875 -0.29351806640625 -0.743977294921875 -0.029 -0.29901123046875 -0.743977294921875 -0.029125 -0.301971435546875 -0.743977294921875 -0.02925 -0.305816650390625 -0.743977294921875 -0.029375 -0.302642822265625 -0.743977294921875 -0.0295 -0.29595947265625 -0.743977294921875 -0.029625 -0.287200927734375 -0.743977294921875 -0.02975000000000001 -0.27813720703125 -0.743977294921875 -0.029875 -0.26220703125 -0.743977294921875 -0.03 -0.245391845703125 -0.743977294921875 -0.030125 -0.227081298828125 -0.743977294921875 -0.03025 -0.20556640625 -0.743977294921875 -0.030375 -0.1795654296875 -0.743977294921875 -0.0305 -0.151580810546875 -0.743977294921875 -0.030625 -0.126556396484375 -0.743977294921875 -0.03075 -0.095306396484375 -0.743977294921875 -0.03087499999999999 -0.066253662109375 -0.743977294921875 -0.031 -0.0333251953125 -0.743977294921875 +0.02725 -0.005950927734375 -0.743977294921875 +0.027375 -0.0362548828125 -0.743977294921875 +0.0275 -0.063140869140625 -0.743977294921875 +0.027625 -0.09234619140625 -0.743977294921875 +0.02775 -0.117767333984375 -0.743977294921875 +0.027875 -0.146881103515625 -0.743977294921875 +0.028 -0.172698974609375 -0.743977294921875 +0.028125 -0.194305419921875 -0.743977294921875 +0.02825 -0.219390869140625 -0.743977294921875 +0.028375 -0.237396240234375 -0.743977294921875 +0.02850000000000001 -0.254913330078125 -0.743977294921875 +0.028625 -0.2696533203125 -0.743977294921875 +0.02875 -0.284332275390625 -0.743977294921875 +0.028875 -0.293487548828125 -0.743977294921875 +0.029 -0.298980712890625 -0.743977294921875 +0.029125 -0.30194091796875 -0.743977294921875 +0.02925 -0.3057861328125 -0.743977294921875 +0.029375 -0.3026123046875 -0.743977294921875 +0.0295 -0.295928955078125 -0.743977294921875 +0.029625 -0.28717041015625 -0.743977294921875 +0.02975000000000001 -0.278106689453125 -0.743977294921875 +0.029875 -0.262176513671875 -0.743977294921875 +0.03 -0.245361328125 -0.743977294921875 +0.030125 -0.22705078125 -0.743977294921875 +0.03025 -0.205535888671875 -0.743977294921875 +0.030375 -0.179534912109375 -0.743977294921875 +0.0305 -0.15155029296875 -0.743977294921875 +0.030625 -0.12652587890625 -0.743977294921875 +0.03075 -0.09527587890625 -0.743977294921875 +0.03087499999999999 -0.06622314453125 -0.743977294921875 +0.031 -0.033294677734375 -0.743977294921875 0.031125 0.0 -0.743977294921875 0.03125 0.03033447265625 -0.743977294921875 0.031375 0.063751220703125 -0.743977294921875 @@ -279,37 +279,37 @@ 0.03475000000000001 0.08154296875 -0.487985107421875 0.034875 0.04473876953125 -0.487985107421875 0.035 0.011199951171875 -0.487985107421875 -0.03512500000000001 -0.02642822265625 -0.487985107421875 -0.03525 -0.0601806640625 -0.487985107421875 -0.035375 -0.097015380859375 -0.487985107421875 -0.0355 -0.1341552734375 -0.487985107421875 -0.03562500000000001 -0.16546630859375 -0.487985107421875 -0.03575 -0.198486328125 -0.487985107421875 -0.035875 -0.22857666015625 -0.487985107421875 -0.03600000000000001 -0.257476806640625 -0.487985107421875 -0.036125 -0.283538818359375 -0.487985107421875 -0.03625 -0.307281494140625 -0.487985107421875 -0.036375 -0.327423095703125 -0.487985107421875 -0.0365 -0.342498779296875 -0.487985107421875 -0.036625 -0.35565185546875 -0.487985107421875 -0.03675 -0.36834716796875 -0.487985107421875 -0.036875 -0.373321533203125 -0.487985107421875 -0.037 -0.374969482421875 -0.487985107421875 -0.03712499999999999 -0.376373291015625 -0.487985107421875 -0.03725 -0.37017822265625 -0.487985107421875 -0.037375 -0.35992431640625 -0.487985107421875 -0.0375 -0.350433349609375 -0.487985107421875 -0.037625 -0.332672119140625 -0.487985107421875 -0.03775 -0.31353759765625 -0.487985107421875 -0.037875 -0.291595458984375 -0.487985107421875 -0.038 -0.263671875 -0.487985107421875 -0.038125 -0.236114501953125 -0.487985107421875 -0.03825 -0.204742431640625 -0.487985107421875 -0.038375 -0.172760009765625 -0.487985107421875 -0.0385 -0.13543701171875 -0.487985107421875 -0.038625 -0.097442626953125 -0.487985107421875 -0.03875 -0.061279296875 -0.487985107421875 -0.038875 -0.0205078125 -0.487985107421875 +0.03512500000000001 -0.026397705078125 -0.487985107421875 +0.03525 -0.060150146484375 -0.487985107421875 +0.035375 -0.09698486328125 -0.487985107421875 +0.0355 -0.134124755859375 -0.487985107421875 +0.03562500000000001 -0.165435791015625 -0.487985107421875 +0.03575 -0.198455810546875 -0.487985107421875 +0.035875 -0.228546142578125 -0.487985107421875 +0.03600000000000001 -0.2574462890625 -0.487985107421875 +0.036125 -0.28350830078125 -0.487985107421875 +0.03625 -0.3072509765625 -0.487985107421875 +0.036375 -0.327392578125 -0.487985107421875 +0.0365 -0.34246826171875 -0.487985107421875 +0.036625 -0.355621337890625 -0.487985107421875 +0.03675 -0.368316650390625 -0.487985107421875 +0.036875 -0.373291015625 -0.487985107421875 +0.037 -0.37493896484375 -0.487985107421875 +0.03712499999999999 -0.3763427734375 -0.487985107421875 +0.03725 -0.370147705078125 -0.487985107421875 +0.037375 -0.359893798828125 -0.487985107421875 +0.0375 -0.35040283203125 -0.487985107421875 +0.037625 -0.3326416015625 -0.487985107421875 +0.03775 -0.313507080078125 -0.487985107421875 +0.037875 -0.29156494140625 -0.487985107421875 +0.038 -0.263641357421875 -0.487985107421875 +0.038125 -0.236083984375 -0.487985107421875 +0.03825 -0.2047119140625 -0.487985107421875 +0.038375 -0.1727294921875 -0.487985107421875 +0.0385 -0.135406494140625 -0.487985107421875 +0.038625 -0.097412109375 -0.487985107421875 +0.03875 -0.061248779296875 -0.487985107421875 +0.038875 -0.020477294921875 -0.487985107421875 0.039 0.016510009765625 -0.487985107421875 0.039125 0.05767822265625 -0.487985107421875 0.03925 0.09820556640625 -0.487985107421875 @@ -341,37 +341,37 @@ 0.0425 0.11773681640625 -0.487985107421875 0.042625 0.07470703125 -0.487985107421875 0.04275 0.0352783203125 -0.487985107421875 -0.04287500000000001 -0.008880615234375 -0.487985107421875 -0.04300000000000001 -0.053253173828125 -0.487985107421875 -0.043125 -0.092681884765625 -0.487985107421875 -0.04325 -0.135528564453125 -0.487985107421875 -0.043375 -0.173919677734375 -0.487985107421875 -0.04350000000000001 -0.21380615234375 -0.487985107421875 -0.04362500000000001 -0.2513427734375 -0.487985107421875 -0.04375000000000001 -0.284576416015625 -0.487985107421875 -0.043875 -0.316741943359375 -0.487985107421875 -0.04399999999999999 -0.342742919921875 -0.487985107421875 -0.044125 -0.370330810546875 -0.487985107421875 -0.04425 -0.391754150390625 -0.487985107421875 -0.044375 -0.4073486328125 -0.487985107421875 -0.04449999999999999 -0.4229736328125 -0.487985107421875 -0.04462499999999999 -0.430877685546875 -0.487985107421875 -0.04475 -0.4351806640625 -0.487985107421875 -0.044875 -0.437225341796875 -0.487985107421875 -0.045 -0.432708740234375 -0.487985107421875 -0.045125 -0.42315673828125 -0.487985107421875 -0.04525 -0.4129638671875 -0.487985107421875 -0.045375 -0.394622802734375 -0.487985107421875 -0.0455 -0.37200927734375 -0.487985107421875 -0.045625 -0.350067138671875 -0.487985107421875 -0.04575 -0.31976318359375 -0.487985107421875 -0.045875 -0.28948974609375 -0.487985107421875 -0.046 -0.25421142578125 -0.487985107421875 -0.046125 -0.214599609375 -0.487985107421875 -0.04625 -0.176910400390625 -0.487985107421875 -0.046375 -0.1339111328125 -0.487985107421875 -0.04649999999999999 -0.093109130859375 -0.487985107421875 -0.046625 -0.04681396484375 -0.487985107421875 +0.04287500000000001 -0.00885009765625 -0.487985107421875 +0.04300000000000001 -0.05322265625 -0.487985107421875 +0.043125 -0.0926513671875 -0.487985107421875 +0.04325 -0.135498046875 -0.487985107421875 +0.043375 -0.17388916015625 -0.487985107421875 +0.04350000000000001 -0.213775634765625 -0.487985107421875 +0.04362500000000001 -0.251312255859375 -0.487985107421875 +0.04375000000000001 -0.2845458984375 -0.487985107421875 +0.043875 -0.31671142578125 -0.487985107421875 +0.04399999999999999 -0.34271240234375 -0.487985107421875 +0.044125 -0.37030029296875 -0.487985107421875 +0.04425 -0.3917236328125 -0.487985107421875 +0.044375 -0.407318115234375 -0.487985107421875 +0.04449999999999999 -0.422943115234375 -0.487985107421875 +0.04462499999999999 -0.43084716796875 -0.487985107421875 +0.04475 -0.435150146484375 -0.487985107421875 +0.044875 -0.43719482421875 -0.487985107421875 +0.045 -0.43267822265625 -0.487985107421875 +0.045125 -0.423126220703125 -0.487985107421875 +0.04525 -0.412933349609375 -0.487985107421875 +0.045375 -0.39459228515625 -0.487985107421875 +0.0455 -0.371978759765625 -0.487985107421875 +0.045625 -0.35003662109375 -0.487985107421875 +0.04575 -0.319732666015625 -0.487985107421875 +0.045875 -0.289459228515625 -0.487985107421875 +0.046 -0.254180908203125 -0.487985107421875 +0.046125 -0.214569091796875 -0.487985107421875 +0.04625 -0.1768798828125 -0.487985107421875 +0.046375 -0.133880615234375 -0.487985107421875 +0.04649999999999999 -0.09307861328125 -0.487985107421875 +0.046625 -0.046783447265625 -0.487985107421875 0.04675000000000001 0.0 -0.487985107421875 0.046875 0.042327880859375 -0.487985107421875 0.04699999999999999 0.08892822265625 -0.487985107421875 @@ -404,37 +404,37 @@ 0.05037500000000001 0.106964111328125 -0.487985107421875 0.0505 0.058685302734375 -0.487985107421875 0.05062500000000001 0.014678955078125 -0.487985107421875 -0.05075000000000001 -0.034454345703125 -0.487985107421875 -0.050875 -0.07843017578125 -0.487985107421875 -0.051 -0.126495361328125 -0.487985107421875 -0.051125 -0.173797607421875 -0.487985107421875 -0.05125000000000001 -0.214324951171875 -0.487985107421875 -0.051375 -0.25714111328125 -0.487985107421875 -0.0515 -0.2943115234375 -0.487985107421875 -0.05162500000000001 -0.331512451171875 -0.487985107421875 -0.05175000000000001 -0.365081787109375 -0.487985107421875 -0.051875 -0.39324951171875 -0.487985107421875 -0.052 -0.419036865234375 -0.487985107421875 -0.052125 -0.438323974609375 -0.487985107421875 -0.05225 -0.456695556640625 -0.487985107421875 -0.05237499999999999 -0.468597412109375 -0.487985107421875 -0.0525 -0.474945068359375 -0.487985107421875 -0.052625 -0.47857666015625 -0.487985107421875 -0.05274999999999999 -0.475982666015625 -0.487985107421875 -0.052875 -0.4681396484375 -0.487985107421875 -0.05300000000000001 -0.456573486328125 -0.487985107421875 -0.053125 -0.44061279296875 -0.487985107421875 -0.05324999999999999 -0.418243408203125 -0.487985107421875 -0.05337499999999999 -0.39422607421875 -0.487985107421875 -0.05350000000000001 -0.364501953125 -0.487985107421875 -0.053625 -0.329620361328125 -0.487985107421875 -0.05375 -0.295135498046875 -0.487985107421875 -0.05387499999999999 -0.25445556640625 -0.487985107421875 -0.054 -0.2147216796875 -0.487985107421875 -0.054125 -0.1683349609375 -0.487985107421875 -0.05425 -0.12042236328125 -0.487985107421875 -0.054375 -0.07574462890625 -0.487985107421875 -0.0545 -0.02532958984375 -0.487985107421875 +0.05075000000000001 -0.034423828125 -0.487985107421875 +0.050875 -0.078399658203125 -0.487985107421875 +0.051 -0.12646484375 -0.487985107421875 +0.051125 -0.17376708984375 -0.487985107421875 +0.05125000000000001 -0.21429443359375 -0.487985107421875 +0.051375 -0.257110595703125 -0.487985107421875 +0.0515 -0.294281005859375 -0.487985107421875 +0.05162500000000001 -0.33148193359375 -0.487985107421875 +0.05175000000000001 -0.36505126953125 -0.487985107421875 +0.051875 -0.393218994140625 -0.487985107421875 +0.052 -0.41900634765625 -0.487985107421875 +0.052125 -0.43829345703125 -0.487985107421875 +0.05225 -0.4566650390625 -0.487985107421875 +0.05237499999999999 -0.46856689453125 -0.487985107421875 +0.0525 -0.47491455078125 -0.487985107421875 +0.052625 -0.478546142578125 -0.487985107421875 +0.05274999999999999 -0.4759521484375 -0.487985107421875 +0.052875 -0.468109130859375 -0.487985107421875 +0.05300000000000001 -0.45654296875 -0.487985107421875 +0.053125 -0.440582275390625 -0.487985107421875 +0.05324999999999999 -0.418212890625 -0.487985107421875 +0.05337499999999999 -0.394195556640625 -0.487985107421875 +0.05350000000000001 -0.364471435546875 -0.487985107421875 +0.053625 -0.32958984375 -0.487985107421875 +0.05375 -0.29510498046875 -0.487985107421875 +0.05387499999999999 -0.254425048828125 -0.487985107421875 +0.054 -0.214691162109375 -0.487985107421875 +0.054125 -0.168304443359375 -0.487985107421875 +0.05425 -0.120391845703125 -0.487985107421875 +0.054375 -0.075714111328125 -0.487985107421875 +0.0545 -0.025299072265625 -0.487985107421875 0.054625 0.020294189453125 -0.487985107421875 0.05475 0.070892333984375 -0.487985107421875 0.054875 0.120697021484375 -0.487985107421875 @@ -466,37 +466,37 @@ 0.058125 0.137939453125 -0.487985107421875 0.05825 0.087554931640625 -0.487985107421875 0.058375 0.041351318359375 -0.487985107421875 -0.05850000000000001 -0.0103759765625 -0.487985107421875 -0.05862500000000001 -0.06207275390625 -0.487985107421875 -0.05875 -0.1080322265625 -0.487985107421875 -0.058875 -0.158203125 -0.487985107421875 -0.059 -0.201751708984375 -0.487985107421875 -0.05912500000000001 -0.248016357421875 -0.487985107421875 -0.05925000000000001 -0.291900634765625 -0.487985107421875 -0.059375 -0.32843017578125 -0.487985107421875 -0.05950000000000001 -0.36553955078125 -0.487985107421875 -0.059625 -0.396026611328125 -0.487985107421875 -0.05975000000000001 -0.42529296875 -0.487985107421875 -0.059875 -0.44989013671875 -0.487985107421875 -0.06 -0.468292236328125 -0.487985107421875 -0.06012499999999999 -0.483367919921875 -0.487985107421875 -0.06025 -0.49237060546875 -0.487985107421875 -0.060375 -0.497283935546875 -0.487985107421875 -0.0605 -0.497222900390625 -0.487985107421875 -0.060625 -0.4920654296875 -0.487985107421875 -0.06074999999999999 -0.481201171875 -0.487985107421875 -0.060875 -0.467315673828125 -0.487985107421875 -0.061 -0.44659423828125 -0.487985107421875 -0.061125 -0.420989990234375 -0.487985107421875 -0.06125 -0.394256591796875 -0.487985107421875 -0.061375 -0.360107421875 -0.487985107421875 -0.0615 -0.326019287109375 -0.487985107421875 -0.061625 -0.284912109375 -0.487985107421875 -0.06174999999999999 -0.240509033203125 -0.487985107421875 -0.061875 -0.198272705078125 -0.487985107421875 -0.062 -0.149383544921875 -0.487985107421875 -0.06212499999999999 -0.103851318359375 -0.487985107421875 -0.06225000000000001 -0.052215576171875 -0.487985107421875 +0.05850000000000001 -0.010345458984375 -0.487985107421875 +0.05862500000000001 -0.062042236328125 -0.487985107421875 +0.05875 -0.108001708984375 -0.487985107421875 +0.058875 -0.158172607421875 -0.487985107421875 +0.059 -0.20172119140625 -0.487985107421875 +0.05912500000000001 -0.24798583984375 -0.487985107421875 +0.05925000000000001 -0.2918701171875 -0.487985107421875 +0.059375 -0.328399658203125 -0.487985107421875 +0.05950000000000001 -0.365509033203125 -0.487985107421875 +0.059625 -0.39599609375 -0.487985107421875 +0.05975000000000001 -0.425262451171875 -0.487985107421875 +0.059875 -0.449859619140625 -0.487985107421875 +0.06 -0.46826171875 -0.487985107421875 +0.06012499999999999 -0.48333740234375 -0.487985107421875 +0.06025 -0.492340087890625 -0.487985107421875 +0.060375 -0.49725341796875 -0.487985107421875 +0.0605 -0.4971923828125 -0.487985107421875 +0.060625 -0.492034912109375 -0.487985107421875 +0.06074999999999999 -0.481170654296875 -0.487985107421875 +0.060875 -0.46728515625 -0.487985107421875 +0.061 -0.446563720703125 -0.487985107421875 +0.061125 -0.42095947265625 -0.487985107421875 +0.06125 -0.39422607421875 -0.487985107421875 +0.061375 -0.360076904296875 -0.487985107421875 +0.0615 -0.32598876953125 -0.487985107421875 +0.061625 -0.284881591796875 -0.487985107421875 +0.06174999999999999 -0.240478515625 -0.487985107421875 +0.061875 -0.1982421875 -0.487985107421875 +0.062 -0.14935302734375 -0.487985107421875 +0.06212499999999999 -0.10382080078125 -0.487985107421875 +0.06225000000000001 -0.05218505859375 -0.487985107421875 0.06237500000000001 0.0 -0.487985107421875 0.0625 0.0469970703125 -0.487985107421875 0.06262499999999999 0.098724365234375 -0.487985107421875 @@ -529,37 +529,37 @@ 0.06600000000000001 0.11383056640625 -0.2319929199218749 0.066125 0.06243896484375 -0.2319929199218749 0.06625000000000001 0.015625 -0.2319929199218749 -0.06637500000000001 -0.036468505859375 -0.2319929199218749 -0.0665 -0.08306884765625 -0.2319929199218749 -0.066625 -0.13385009765625 -0.2319929199218749 -0.06675 -0.1832275390625 -0.2319929199218749 -0.06687500000000001 -0.2257080078125 -0.2319929199218749 -0.067 -0.270782470703125 -0.2319929199218749 -0.067125 -0.308837890625 -0.2319929199218749 -0.06725000000000001 -0.347442626953125 -0.2319929199218749 -0.06737500000000001 -0.382659912109375 -0.2319929199218749 -0.0675 -0.41021728515625 -0.2319929199218749 -0.067625 -0.437103271484375 -0.2319929199218749 -0.06775 -0.457244873046875 -0.2319929199218749 -0.06787500000000001 -0.47418212890625 -0.2319929199218749 -0.06800000000000001 -0.486541748046875 -0.2319929199218749 -0.068125 -0.49310302734375 -0.2319929199218749 -0.06825000000000001 -0.49456787109375 -0.2319929199218749 -0.068375 -0.491851806640625 -0.2319929199218749 -0.06850000000000001 -0.48297119140625 -0.2319929199218749 -0.06862500000000001 -0.4696044921875 -0.2319929199218749 -0.06875 -0.45318603515625 -0.2319929199218749 -0.06887500000000001 -0.429473876953125 -0.2319929199218749 -0.069 -0.40478515625 -0.2319929199218749 -0.06912500000000001 -0.372467041015625 -0.2319929199218749 -0.06925000000000001 -0.336822509765625 -0.2319929199218749 -0.06937500000000001 -0.30157470703125 -0.2319929199218749 -0.06950000000000001 -0.258758544921875 -0.2319929199218749 -0.069625 -0.218353271484375 -0.2319929199218749 -0.06975 -0.171173095703125 -0.2319929199218749 -0.06987500000000001 -0.121856689453125 -0.2319929199218749 -0.07000000000000001 -0.07666015625 -0.2319929199218749 -0.070125 -0.02557373046875 -0.2319929199218749 +0.06637500000000001 -0.03643798828125 -0.2319929199218749 +0.0665 -0.083038330078125 -0.2319929199218749 +0.066625 -0.133819580078125 -0.2319929199218749 +0.06675 -0.183197021484375 -0.2319929199218749 +0.06687500000000001 -0.225677490234375 -0.2319929199218749 +0.067 -0.270751953125 -0.2319929199218749 +0.067125 -0.308807373046875 -0.2319929199218749 +0.06725000000000001 -0.347412109375 -0.2319929199218749 +0.06737500000000001 -0.38262939453125 -0.2319929199218749 +0.0675 -0.410186767578125 -0.2319929199218749 +0.067625 -0.43707275390625 -0.2319929199218749 +0.06775 -0.45721435546875 -0.2319929199218749 +0.06787500000000001 -0.474151611328125 -0.2319929199218749 +0.06800000000000001 -0.48651123046875 -0.2319929199218749 +0.068125 -0.493072509765625 -0.2319929199218749 +0.06825000000000001 -0.494537353515625 -0.2319929199218749 +0.068375 -0.4918212890625 -0.2319929199218749 +0.06850000000000001 -0.482940673828125 -0.2319929199218749 +0.06862500000000001 -0.469573974609375 -0.2319929199218749 +0.06875 -0.453155517578125 -0.2319929199218749 +0.06887500000000001 -0.429443359375 -0.2319929199218749 +0.069 -0.404754638671875 -0.2319929199218749 +0.06912500000000001 -0.3724365234375 -0.2319929199218749 +0.06925000000000001 -0.3367919921875 -0.2319929199218749 +0.06937500000000001 -0.301544189453125 -0.2319929199218749 +0.06950000000000001 -0.25872802734375 -0.2319929199218749 +0.069625 -0.21832275390625 -0.2319929199218749 +0.06975 -0.171142578125 -0.2319929199218749 +0.06987500000000001 -0.121826171875 -0.2319929199218749 +0.07000000000000001 -0.076629638671875 -0.2319929199218749 +0.070125 -0.025543212890625 -0.2319929199218749 0.07025000000000001 0.02044677734375 -0.2319929199218749 0.07037500000000001 0.0714111328125 -0.2319929199218749 0.07050000000000001 0.121307373046875 -0.2319929199218749 @@ -591,37 +591,37 @@ 0.07374999999999999 0.132171630859375 -0.2319929199218749 0.073875 0.0838623046875 -0.2319929199218749 0.074 0.03961181640625 -0.2319929199218749 -0.074125 -0.0098876953125 -0.2319929199218749 -0.07424999999999999 -0.059173583984375 -0.2319929199218749 -0.07437499999999999 -0.10260009765625 -0.2319929199218749 -0.0745 -0.1500244140625 -0.2319929199218749 -0.07462499999999999 -0.191314697265625 -0.2319929199218749 -0.07475 -0.234283447265625 -0.2319929199218749 -0.07487500000000001 -0.275421142578125 -0.2319929199218749 -0.075 -0.30865478515625 -0.2319929199218749 -0.07512499999999999 -0.343536376953125 -0.2319929199218749 -0.07524999999999999 -0.37176513671875 -0.2319929199218749 -0.075375 -0.3975830078125 -0.2319929199218749 -0.0755 -0.42059326171875 -0.2319929199218749 -0.075625 -0.437347412109375 -0.2319929199218749 -0.07574999999999999 -0.44952392578125 -0.2319929199218749 -0.075875 -0.457916259765625 -0.2319929199218749 -0.076 -0.460479736328125 -0.2319929199218749 -0.076125 -0.4599609375 -0.2319929199218749 -0.07625 -0.4552001953125 -0.2319929199218749 -0.07637499999999999 -0.44317626953125 -0.2319929199218749 -0.0765 -0.4300537109375 -0.2319929199218749 -0.076625 -0.409088134765625 -0.2319929199218749 -0.07675 -0.3856201171875 -0.2319929199218749 -0.076875 -0.360870361328125 -0.2319929199218749 -0.077 -0.32806396484375 -0.2319929199218749 -0.077125 -0.2969970703125 -0.2319929199218749 -0.07725 -0.2593994140625 -0.2319929199218749 -0.07737499999999999 -0.217926025390625 -0.2319929199218749 -0.0775 -0.179656982421875 -0.2319929199218749 -0.077625 -0.13458251953125 -0.2319929199218749 -0.07774999999999999 -0.09356689453125 -0.2319929199218749 -0.07787500000000001 -0.04705810546875 -0.2319929199218749 +0.074125 -0.009857177734375 -0.2319929199218749 +0.07424999999999999 -0.05914306640625 -0.2319929199218749 +0.07437499999999999 -0.102569580078125 -0.2319929199218749 +0.0745 -0.149993896484375 -0.2319929199218749 +0.07462499999999999 -0.1912841796875 -0.2319929199218749 +0.07475 -0.2342529296875 -0.2319929199218749 +0.07487500000000001 -0.275390625 -0.2319929199218749 +0.075 -0.308624267578125 -0.2319929199218749 +0.07512499999999999 -0.343505859375 -0.2319929199218749 +0.07524999999999999 -0.371734619140625 -0.2319929199218749 +0.075375 -0.397552490234375 -0.2319929199218749 +0.0755 -0.420562744140625 -0.2319929199218749 +0.075625 -0.43731689453125 -0.2319929199218749 +0.07574999999999999 -0.449493408203125 -0.2319929199218749 +0.075875 -0.4578857421875 -0.2319929199218749 +0.076 -0.46044921875 -0.2319929199218749 +0.076125 -0.459930419921875 -0.2319929199218749 +0.07625 -0.455169677734375 -0.2319929199218749 +0.07637499999999999 -0.443145751953125 -0.2319929199218749 +0.0765 -0.430023193359375 -0.2319929199218749 +0.076625 -0.4090576171875 -0.2319929199218749 +0.07675 -0.385589599609375 -0.2319929199218749 +0.076875 -0.36083984375 -0.2319929199218749 +0.077 -0.328033447265625 -0.2319929199218749 +0.077125 -0.296966552734375 -0.2319929199218749 +0.07725 -0.259368896484375 -0.2319929199218749 +0.07737499999999999 -0.2178955078125 -0.2319929199218749 +0.0775 -0.17962646484375 -0.2319929199218749 +0.077625 -0.134552001953125 -0.2319929199218749 +0.07774999999999999 -0.093536376953125 -0.2319929199218749 +0.07787500000000001 -0.047027587890625 -0.2319929199218749 0.07800000000000001 0.0 -0.2319929199218749 0.078125 0.0421142578125 -0.2319929199218749 0.07824999999999999 0.0880126953125 -0.2319929199218749 @@ -654,37 +654,37 @@ 0.081625 0.095703125 -0.2319929199218749 0.08175000000000001 0.052520751953125 -0.2319929199218749 0.081875 0.0130615234375 -0.2319929199218749 -0.08200000000000001 -0.030487060546875 -0.2319929199218749 -0.082125 -0.069427490234375 -0.2319929199218749 -0.08225 -0.111175537109375 -0.2319929199218749 -0.08237500000000001 -0.1522216796875 -0.2319929199218749 -0.0825 -0.186370849609375 -0.2319929199218749 -0.08262500000000001 -0.223602294921875 -0.2319929199218749 -0.08275 -0.254974365234375 -0.2319929199218749 -0.08287500000000001 -0.285125732421875 -0.2319929199218749 -0.08300000000000001 -0.313995361328125 -0.2319929199218749 -0.083125 -0.3370361328125 -0.2319929199218749 -0.08324999999999999 -0.3564453125 -0.2319929199218749 -0.083375 -0.37286376953125 -0.2319929199218749 -0.08350000000000001 -0.38421630859375 -0.2319929199218749 -0.08362500000000001 -0.39422607421875 -0.2319929199218749 -0.08375 -0.399566650390625 -0.2319929199218749 -0.08387500000000001 -0.398193359375 -0.2319929199218749 -0.084 -0.396026611328125 -0.2319929199218749 -0.08412500000000001 -0.386383056640625 -0.2319929199218749 -0.08425000000000001 -0.375701904296875 -0.2319929199218749 -0.084375 -0.362548828125 -0.2319929199218749 -0.08450000000000001 -0.341339111328125 -0.2319929199218749 -0.084625 -0.32171630859375 -0.2319929199218749 -0.08475 -0.29656982421875 -0.2319929199218749 -0.08487500000000001 -0.265960693359375 -0.2319929199218749 -0.085 -0.238128662109375 -0.2319929199218749 -0.08512500000000001 -0.2030029296875 -0.2319929199218749 -0.08525 -0.171295166015625 -0.2319929199218749 -0.085375 -0.13427734375 -0.2319929199218749 -0.08550000000000001 -0.094970703125 -0.2319929199218749 -0.085625 -0.059722900390625 -0.2319929199218749 -0.08575000000000001 -0.019805908203125 -0.2319929199218749 +0.08200000000000001 -0.03045654296875 -0.2319929199218749 +0.082125 -0.06939697265625 -0.2319929199218749 +0.08225 -0.11114501953125 -0.2319929199218749 +0.08237500000000001 -0.152191162109375 -0.2319929199218749 +0.0825 -0.18634033203125 -0.2319929199218749 +0.08262500000000001 -0.22357177734375 -0.2319929199218749 +0.08275 -0.25494384765625 -0.2319929199218749 +0.08287500000000001 -0.28509521484375 -0.2319929199218749 +0.08300000000000001 -0.31396484375 -0.2319929199218749 +0.083125 -0.337005615234375 -0.2319929199218749 +0.08324999999999999 -0.356414794921875 -0.2319929199218749 +0.083375 -0.372833251953125 -0.2319929199218749 +0.08350000000000001 -0.384185791015625 -0.2319929199218749 +0.08362500000000001 -0.394195556640625 -0.2319929199218749 +0.08375 -0.3995361328125 -0.2319929199218749 +0.08387500000000001 -0.398162841796875 -0.2319929199218749 +0.084 -0.39599609375 -0.2319929199218749 +0.08412500000000001 -0.3863525390625 -0.2319929199218749 +0.08425000000000001 -0.37567138671875 -0.2319929199218749 +0.084375 -0.362518310546875 -0.2319929199218749 +0.08450000000000001 -0.34130859375 -0.2319929199218749 +0.084625 -0.321685791015625 -0.2319929199218749 +0.08475 -0.296539306640625 -0.2319929199218749 +0.08487500000000001 -0.26593017578125 -0.2319929199218749 +0.085 -0.23809814453125 -0.2319929199218749 +0.08512500000000001 -0.202972412109375 -0.2319929199218749 +0.08525 -0.1712646484375 -0.2319929199218749 +0.085375 -0.134246826171875 -0.2319929199218749 +0.08550000000000001 -0.094940185546875 -0.2319929199218749 +0.085625 -0.0596923828125 -0.2319929199218749 +0.08575000000000001 -0.019775390625 -0.2319929199218749 0.08587500000000002 0.01580810546875 -0.2319929199218749 0.08600000000000001 0.05523681640625 -0.2319929199218749 0.08612500000000001 0.093231201171875 -0.2319929199218749 @@ -716,37 +716,37 @@ 0.089375 0.094390869140625 -0.2319929199218749 0.08949999999999999 0.059906005859375 -0.2319929199218749 0.089625 0.028289794921875 -0.2319929199218749 -0.08975 -0.00701904296875 -0.2319929199218749 -0.08987499999999999 -0.04193115234375 -0.2319929199218749 -0.09 -0.072113037109375 -0.2319929199218749 -0.09012499999999999 -0.10546875 -0.2319929199218749 -0.09025 -0.13446044921875 -0.2319929199218749 -0.090375 -0.163330078125 -0.2319929199218749 -0.09050000000000001 -0.1920166015625 -0.2319929199218749 -0.090625 -0.216033935546875 -0.2319929199218749 -0.09074999999999999 -0.237518310546875 -0.2319929199218749 -0.09087499999999999 -0.25701904296875 -0.2319929199218749 -0.091 -0.2725830078125 -0.2319929199218749 -0.09112500000000001 -0.288330078125 -0.2319929199218749 -0.09125 -0.299835205078125 -0.2319929199218749 -0.09137499999999999 -0.3055419921875 -0.2319929199218749 -0.0915 -0.31121826171875 -0.2319929199218749 -0.091625 -0.310272216796875 -0.2319929199218749 -0.09175000000000001 -0.3099365234375 -0.2319929199218749 -0.091875 -0.30670166015625 -0.2319929199218749 -0.09199999999999999 -0.29595947265625 -0.2319929199218749 -0.092125 -0.287200927734375 -0.2319929199218749 -0.09225 -0.274444580078125 -0.2319929199218749 -0.09237499999999999 -0.25518798828125 -0.2319929199218749 -0.0925 -0.23883056640625 -0.2319929199218749 -0.09262499999999999 -0.21514892578125 -0.2319929199218749 -0.09275 -0.19476318359375 -0.2319929199218749 -0.092875 -0.17010498046875 -0.2319929199218749 -0.09299999999999999 -0.141571044921875 -0.2319929199218749 -0.093125 -0.11669921875 -0.2319929199218749 -0.09324999999999999 -0.08660888671875 -0.2319929199218749 -0.093375 -0.060211181640625 -0.2319929199218749 -0.09350000000000001 -0.0302734375 -0.2319929199218749 +0.08975 -0.006988525390625 -0.2319929199218749 +0.08987499999999999 -0.041900634765625 -0.2319929199218749 +0.09 -0.07208251953125 -0.2319929199218749 +0.09012499999999999 -0.105438232421875 -0.2319929199218749 +0.09025 -0.134429931640625 -0.2319929199218749 +0.090375 -0.163299560546875 -0.2319929199218749 +0.09050000000000001 -0.191986083984375 -0.2319929199218749 +0.090625 -0.21600341796875 -0.2319929199218749 +0.09074999999999999 -0.23748779296875 -0.2319929199218749 +0.09087499999999999 -0.256988525390625 -0.2319929199218749 +0.091 -0.272552490234375 -0.2319929199218749 +0.09112500000000001 -0.288299560546875 -0.2319929199218749 +0.09125 -0.2998046875 -0.2319929199218749 +0.09137499999999999 -0.305511474609375 -0.2319929199218749 +0.0915 -0.311187744140625 -0.2319929199218749 +0.091625 -0.31024169921875 -0.2319929199218749 +0.09175000000000001 -0.309906005859375 -0.2319929199218749 +0.091875 -0.306671142578125 -0.2319929199218749 +0.09199999999999999 -0.295928955078125 -0.2319929199218749 +0.092125 -0.28717041015625 -0.2319929199218749 +0.09225 -0.2744140625 -0.2319929199218749 +0.09237499999999999 -0.255157470703125 -0.2319929199218749 +0.0925 -0.238800048828125 -0.2319929199218749 +0.09262499999999999 -0.215118408203125 -0.2319929199218749 +0.09275 -0.194732666015625 -0.2319929199218749 +0.092875 -0.170074462890625 -0.2319929199218749 +0.09299999999999999 -0.14154052734375 -0.2319929199218749 +0.093125 -0.116668701171875 -0.2319929199218749 +0.09324999999999999 -0.086578369140625 -0.2319929199218749 +0.093375 -0.0601806640625 -0.2319929199218749 +0.09350000000000001 -0.030242919921875 -0.2319929199218749 0.09362500000000001 0.0 -0.2319929199218749 0.09375 0.026824951171875 -0.2319929199218749 0.09387499999999999 0.056365966796875 -0.2319929199218749 @@ -779,37 +779,37 @@ 0.09725 0.0528564453125 0.02399926757812504 0.09737500000000001 0.02899169921875 0.02399926757812504 0.0975 0.007110595703125 0.02399926757812504 -0.09762500000000001 -0.016632080078125 0.02399926757812504 -0.09775 -0.037841796875 0.02399926757812504 -0.097875 -0.059783935546875 0.02399926757812504 -0.09800000000000001 -0.081817626953125 0.02399926757812504 -0.098125 -0.098785400390625 0.02399926757812504 -0.09825000000000001 -0.118499755859375 0.02399926757812504 -0.098375 -0.132232666015625 0.02399926757812504 -0.09850000000000001 -0.14892578125 0.02399926757812504 -0.09862500000000001 -0.160369873046875 0.02399926757812504 -0.09875 -0.172119140625 0.02399926757812504 -0.09887499999999999 -0.17919921875 0.02399926757812504 -0.099 -0.187469482421875 0.02399926757812504 -0.09912500000000001 -0.194671630859375 0.02399926757812504 -0.09925000000000001 -0.195037841796875 0.02399926757812504 -0.099375 -0.197662353515625 0.02399926757812504 -0.09950000000000001 -0.1937255859375 0.02399926757812504 -0.099625 -0.192657470703125 0.02399926757812504 -0.09975000000000001 -0.18475341796875 0.02399926757812504 -0.09987500000000001 -0.179656982421875 0.02399926757812504 -0.1 -0.168914794921875 0.02399926757812504 -0.100125 -0.16033935546875 0.02399926757812504 -0.10025 -0.147125244140625 0.02399926757812504 -0.100375 -0.1356201171875 0.02399926757812504 -0.1005 -0.122650146484375 0.02399926757812504 -0.100625 -0.1068115234375 0.02399926757812504 -0.10075 -0.091827392578125 0.02399926757812504 -0.100875 -0.075286865234375 0.02399926757812504 -0.101 -0.05902099609375 0.02399926757812504 -0.101125 -0.0408935546875 0.02399926757812504 -0.10125 -0.025726318359375 0.02399926757812504 -0.101375 -0.008331298828125 0.02399926757812504 +0.09762500000000001 -0.0166015625 0.02399926757812504 +0.09775 -0.037811279296875 0.02399926757812504 +0.097875 -0.05975341796875 0.02399926757812504 +0.09800000000000001 -0.081787109375 0.02399926757812504 +0.098125 -0.0987548828125 0.02399926757812504 +0.09825000000000001 -0.11846923828125 0.02399926757812504 +0.098375 -0.1322021484375 0.02399926757812504 +0.09850000000000001 -0.148895263671875 0.02399926757812504 +0.09862500000000001 -0.16033935546875 0.02399926757812504 +0.09875 -0.172088623046875 0.02399926757812504 +0.09887499999999999 -0.179168701171875 0.02399926757812504 +0.099 -0.18743896484375 0.02399926757812504 +0.09912500000000001 -0.19464111328125 0.02399926757812504 +0.09925000000000001 -0.19500732421875 0.02399926757812504 +0.099375 -0.1976318359375 0.02399926757812504 +0.09950000000000001 -0.193695068359375 0.02399926757812504 +0.099625 -0.192626953125 0.02399926757812504 +0.09975000000000001 -0.184722900390625 0.02399926757812504 +0.09987500000000001 -0.17962646484375 0.02399926757812504 +0.1 -0.16888427734375 0.02399926757812504 +0.100125 -0.160308837890625 0.02399926757812504 +0.10025 -0.1470947265625 0.02399926757812504 +0.100375 -0.135589599609375 0.02399926757812504 +0.1005 -0.12261962890625 0.02399926757812504 +0.100625 -0.106781005859375 0.02399926757812504 +0.10075 -0.091796875 0.02399926757812504 +0.100875 -0.07525634765625 0.02399926757812504 +0.101 -0.058990478515625 0.02399926757812504 +0.101125 -0.040863037109375 0.02399926757812504 +0.10125 -0.02569580078125 0.02399926757812504 +0.101375 -0.00830078125 0.02399926757812504 0.1015 0.00665283203125 0.02399926757812504 0.101625 0.02252197265625 0.02399926757812504 0.10175 0.03839111328125 0.02399926757812504 @@ -841,37 +841,37 @@ 0.105 0.026092529296875 0.02399926757812504 0.105125 0.01654052734375 0.02399926757812504 0.10525 0.00738525390625 0.02399926757812504 -0.105375 -0.001861572265625 0.02399926757812504 -0.1055 -0.01043701171875 0.02399926757812504 -0.105625 -0.0181884765625 0.02399926757812504 -0.10575 -0.024932861328125 0.02399926757812504 -0.105875 -0.03179931640625 0.02399926757812504 -0.106 -0.0364990234375 0.02399926757812504 -0.106125 -0.04290771484375 0.02399926757812504 -0.10625 -0.04486083984375 0.02399926757812504 -0.106375 -0.0499267578125 0.02399926757812504 -0.1065 -0.054046630859375 0.02399926757812504 -0.106625 -0.0535888671875 0.02399926757812504 -0.10675 -0.05670166015625 0.02399926757812504 -0.106875 -0.0540771484375 0.02399926757812504 -0.107 -0.055816650390625 0.02399926757812504 -0.107125 -0.05169677734375 0.02399926757812504 -0.10725 -0.052215576171875 0.02399926757812504 -0.107375 -0.04693603515625 0.02399926757812504 -0.1075 -0.04644775390625 0.02399926757812504 -0.107625 -0.0404052734375 0.02399926757812504 -0.10775 -0.0391845703125 0.02399926757812504 -0.107875 -0.03277587890625 0.02399926757812504 -0.108 -0.030914306640625 0.02399926757812504 -0.108125 -0.0289306640625 0.02399926757812504 -0.10825 -0.02264404296875 0.02399926757812504 -0.108375 -0.0205078125 0.02399926757812504 -0.1085 -0.014923095703125 0.02399926757812504 -0.108625 -0.012603759765625 0.02399926757812504 -0.10875 -0.00830078125 0.02399926757812504 -0.108875 -0.006256103515625 0.02399926757812504 -0.109 -0.003265380859375 0.02399926757812504 -0.109125 -0.00164794921875 0.02399926757812504 +0.105375 -0.0018310546875 0.02399926757812504 +0.1055 -0.010406494140625 0.02399926757812504 +0.105625 -0.018157958984375 0.02399926757812504 +0.10575 -0.02490234375 0.02399926757812504 +0.105875 -0.031768798828125 0.02399926757812504 +0.106 -0.036468505859375 0.02399926757812504 +0.106125 -0.042877197265625 0.02399926757812504 +0.10625 -0.044830322265625 0.02399926757812504 +0.106375 -0.049896240234375 0.02399926757812504 +0.1065 -0.05401611328125 0.02399926757812504 +0.106625 -0.053558349609375 0.02399926757812504 +0.10675 -0.056671142578125 0.02399926757812504 +0.106875 -0.054046630859375 0.02399926757812504 +0.107 -0.0557861328125 0.02399926757812504 +0.107125 -0.051666259765625 0.02399926757812504 +0.10725 -0.05218505859375 0.02399926757812504 +0.107375 -0.046905517578125 0.02399926757812504 +0.1075 -0.046417236328125 0.02399926757812504 +0.107625 -0.040374755859375 0.02399926757812504 +0.10775 -0.039154052734375 0.02399926757812504 +0.107875 -0.032745361328125 0.02399926757812504 +0.108 -0.0308837890625 0.02399926757812504 +0.108125 -0.028900146484375 0.02399926757812504 +0.10825 -0.022613525390625 0.02399926757812504 +0.108375 -0.020477294921875 0.02399926757812504 +0.1085 -0.014892578125 0.02399926757812504 +0.108625 -0.0125732421875 0.02399926757812504 +0.10875 -0.008270263671875 0.02399926757812504 +0.108875 -0.0062255859375 0.02399926757812504 +0.109 -0.00323486328125 0.02399926757812504 +0.109125 -0.001617431640625 0.02399926757812504 0.10925 0.0 0.02399926757812504 0.109375 0.000946044921875 0.02399926757812504 0.1095 0.002044677734375 0.02399926757812504 @@ -879,31 +879,31 @@ 0.10975 0.001983642578125 0.02399926757812504 0.109875 0.0 0.02399926757812504 0.11 0.0 0.02399926757812504 -0.110125 -0.003387451171875 0.02399926757812504 -0.11025 -0.003753662109375 0.02399926757812504 -0.110375 -0.008209228515625 0.02399926757812504 -0.1105 -0.00885009765625 0.02399926757812504 -0.110625 -0.01397705078125 0.02399926757812504 -0.11075 -0.0146484375 0.02399926757812504 -0.110875 -0.01513671875 0.02399926757812504 -0.111 -0.0206298828125 0.02399926757812504 -0.111125 -0.020904541015625 0.02399926757812504 -0.11125 -0.026153564453125 0.02399926757812504 -0.111375 -0.025909423828125 0.02399926757812504 -0.1115 -0.030548095703125 0.02399926757812504 -0.111625 -0.029632568359375 0.02399926757812504 -0.11175 -0.033111572265625 0.02399926757812504 -0.111875 -0.031494140625 0.02399926757812504 -0.112 -0.0335693359375 0.02399926757812504 -0.112125 -0.03106689453125 0.02399926757812504 -0.11225 -0.031463623046875 0.02399926757812504 -0.112375 -0.02764892578125 0.02399926757812504 -0.1125 -0.023956298828125 0.02399926757812504 -0.112625 -0.021759033203125 0.02399926757812504 -0.11275 -0.017181396484375 0.02399926757812504 -0.112875 -0.01312255859375 0.02399926757812504 -0.113 -0.0072021484375 0.02399926757812504 -0.113125 -0.001953125 0.02399926757812504 +0.110125 -0.00335693359375 0.02399926757812504 +0.11025 -0.00372314453125 0.02399926757812504 +0.110375 -0.0081787109375 0.02399926757812504 +0.1105 -0.008819580078125 0.02399926757812504 +0.110625 -0.013946533203125 0.02399926757812504 +0.11075 -0.014617919921875 0.02399926757812504 +0.110875 -0.015106201171875 0.02399926757812504 +0.111 -0.020599365234375 0.02399926757812504 +0.111125 -0.0208740234375 0.02399926757812504 +0.11125 -0.026123046875 0.02399926757812504 +0.111375 -0.02587890625 0.02399926757812504 +0.1115 -0.030517578125 0.02399926757812504 +0.111625 -0.02960205078125 0.02399926757812504 +0.11175 -0.0330810546875 0.02399926757812504 +0.111875 -0.031463623046875 0.02399926757812504 +0.112 -0.033538818359375 0.02399926757812504 +0.112125 -0.031036376953125 0.02399926757812504 +0.11225 -0.03143310546875 0.02399926757812504 +0.112375 -0.027618408203125 0.02399926757812504 +0.1125 -0.02392578125 0.02399926757812504 +0.112625 -0.021728515625 0.02399926757812504 +0.11275 -0.01715087890625 0.02399926757812504 +0.112875 -0.013092041015625 0.02399926757812504 +0.113 -0.007171630859375 0.02399926757812504 +0.113125 -0.001922607421875 0.02399926757812504 0.11325 0.004547119140625 0.02399926757812504 0.113375 0.01129150390625 0.02399926757812504 0.1135 0.018218994140625 0.02399926757812504 @@ -935,37 +935,37 @@ 0.11675 0.032135009765625 0.02399926757812504 0.116875 0.02020263671875 0.02399926757812504 0.117 0.006988525390625 0.02399926757812504 -0.117125 -0.005615234375 0.02399926757812504 -0.11725 -0.0203857421875 0.02399926757812504 -0.117375 -0.03466796875 0.02399926757812504 -0.1175 -0.0489501953125 0.02399926757812504 -0.117625 -0.062896728515625 0.02399926757812504 -0.11775 -0.07745361328125 0.02399926757812504 -0.117875 -0.09039306640625 0.02399926757812504 -0.118 -0.105743408203125 0.02399926757812504 -0.118125 -0.115875244140625 0.02399926757812504 -0.11825 -0.12591552734375 0.02399926757812504 -0.118375 -0.138092041015625 0.02399926757812504 -0.1185 -0.14569091796875 0.02399926757812504 -0.118625 -0.1563720703125 0.02399926757812504 -0.11875 -0.160430908203125 0.02399926757812504 -0.118875 -0.168212890625 0.02399926757812504 -0.119 -0.1693115234375 0.02399926757812504 -0.119125 -0.17364501953125 0.02399926757812504 -0.11925 -0.171173095703125 0.02399926757812504 -0.119375 -0.17205810546875 0.02399926757812504 -0.1195 -0.1658935546875 0.02399926757812504 -0.119625 -0.1630859375 0.02399926757812504 -0.11975 -0.153289794921875 0.02399926757812504 -0.119875 -0.141815185546875 0.02399926757812504 -0.12 -0.133575439453125 0.02399926757812504 -0.120125 -0.118865966796875 0.02399926757812504 -0.12025 -0.107208251953125 0.02399926757812504 -0.120375 -0.089752197265625 0.02399926757812504 -0.1205 -0.073089599609375 0.02399926757812504 -0.120625 -0.055389404296875 0.02399926757812504 -0.12075 -0.0360107421875 0.02399926757812504 -0.120875 -0.016998291015625 0.02399926757812504 +0.117125 -0.005584716796875 0.02399926757812504 +0.11725 -0.020355224609375 0.02399926757812504 +0.117375 -0.034637451171875 0.02399926757812504 +0.1175 -0.048919677734375 0.02399926757812504 +0.117625 -0.0628662109375 0.02399926757812504 +0.11775 -0.077423095703125 0.02399926757812504 +0.117875 -0.090362548828125 0.02399926757812504 +0.118 -0.105712890625 0.02399926757812504 +0.118125 -0.1158447265625 0.02399926757812504 +0.11825 -0.125885009765625 0.02399926757812504 +0.118375 -0.1380615234375 0.02399926757812504 +0.1185 -0.145660400390625 0.02399926757812504 +0.118625 -0.156341552734375 0.02399926757812504 +0.11875 -0.160400390625 0.02399926757812504 +0.118875 -0.168182373046875 0.02399926757812504 +0.119 -0.169281005859375 0.02399926757812504 +0.119125 -0.173614501953125 0.02399926757812504 +0.11925 -0.171142578125 0.02399926757812504 +0.119375 -0.172027587890625 0.02399926757812504 +0.1195 -0.165863037109375 0.02399926757812504 +0.119625 -0.163055419921875 0.02399926757812504 +0.11975 -0.15325927734375 0.02399926757812504 +0.119875 -0.14178466796875 0.02399926757812504 +0.12 -0.133544921875 0.02399926757812504 +0.120125 -0.11883544921875 0.02399926757812504 +0.12025 -0.107177734375 0.02399926757812504 +0.120375 -0.0897216796875 0.02399926757812504 +0.1205 -0.07305908203125 0.02399926757812504 +0.120625 -0.05535888671875 0.02399926757812504 +0.12075 -0.035980224609375 0.02399926757812504 +0.120875 -0.0169677734375 0.02399926757812504 0.121 0.00433349609375 0.02399926757812504 0.121125 0.02606201171875 0.02399926757812504 0.12125 0.045379638671875 0.02399926757812504 @@ -998,37 +998,37 @@ 0.124625 0.0556640625 0.02399926757812504 0.12475 0.027984619140625 0.02399926757812504 0.124875 0.0 0.02399926757812504 -0.125 -0.025634765625 0.02399926757812504 -0.125125 -0.0546875 0.02399926757812504 -0.12525 -0.0799560546875 0.02399926757812504 -0.125375 -0.10888671875 0.02399926757812504 -0.1255 -0.1353759765625 0.02399926757812504 -0.125625 -0.157958984375 0.02399926757812504 -0.12575 -0.184173583984375 0.02399926757812504 -0.125875 -0.203857421875 0.02399926757812504 -0.126 -0.226959228515625 0.02399926757812504 -0.126125 -0.244537353515625 0.02399926757812504 -0.12625 -0.261810302734375 0.02399926757812504 -0.126375 -0.274322509765625 0.02399926757812504 -0.1265 -0.287078857421875 0.02399926757812504 -0.126625 -0.29388427734375 0.02399926757812504 -0.12675 -0.301666259765625 0.02399926757812504 -0.126875 -0.302093505859375 0.02399926757812504 -0.127 -0.3035888671875 0.02399926757812504 -0.127125 -0.298309326171875 0.02399926757812504 -0.12725 -0.28936767578125 0.02399926757812504 -0.127375 -0.280975341796875 0.02399926757812504 -0.1275 -0.26727294921875 0.02399926757812504 -0.127625 -0.2525634765625 0.02399926757812504 -0.12775 -0.233795166015625 0.02399926757812504 -0.127875 -0.213226318359375 0.02399926757812504 -0.128 -0.18731689453125 0.2799914550781251 -0.128125 -0.16424560546875 0.2799914550781251 -0.12825 -0.13433837890625 0.2799914550781251 -0.128375 -0.107421875 0.2799914550781251 -0.1285 -0.0745849609375 0.2799914550781251 -0.128625 -0.04144287109375 0.2799914550781251 -0.12875 -0.010498046875 0.2799914550781251 +0.125 -0.025604248046875 0.02399926757812504 +0.125125 -0.054656982421875 0.02399926757812504 +0.12525 -0.079925537109375 0.02399926757812504 +0.125375 -0.108856201171875 0.02399926757812504 +0.1255 -0.135345458984375 0.02399926757812504 +0.125625 -0.157928466796875 0.02399926757812504 +0.12575 -0.18414306640625 0.02399926757812504 +0.125875 -0.203826904296875 0.02399926757812504 +0.126 -0.2269287109375 0.02399926757812504 +0.126125 -0.2445068359375 0.02399926757812504 +0.12625 -0.26177978515625 0.02399926757812504 +0.126375 -0.2742919921875 0.02399926757812504 +0.1265 -0.28704833984375 0.02399926757812504 +0.126625 -0.293853759765625 0.02399926757812504 +0.12675 -0.3016357421875 0.02399926757812504 +0.126875 -0.30206298828125 0.02399926757812504 +0.127 -0.303558349609375 0.02399926757812504 +0.127125 -0.29827880859375 0.02399926757812504 +0.12725 -0.289337158203125 0.02399926757812504 +0.127375 -0.28094482421875 0.02399926757812504 +0.1275 -0.267242431640625 0.02399926757812504 +0.127625 -0.252532958984375 0.02399926757812504 +0.12775 -0.2337646484375 0.02399926757812504 +0.127875 -0.21319580078125 0.02399926757812504 +0.128 -0.187286376953125 0.2799914550781251 +0.128125 -0.164215087890625 0.2799914550781251 +0.12825 -0.134307861328125 0.2799914550781251 +0.128375 -0.107391357421875 0.2799914550781251 +0.1285 -0.074554443359375 0.2799914550781251 +0.128625 -0.041412353515625 0.2799914550781251 +0.12875 -0.010467529296875 0.2799914550781251 0.128875 0.02447509765625 0.2799914550781251 0.129 0.056396484375 0.2799914550781251 0.129125 0.090972900390625 0.2799914550781251 @@ -1060,37 +1060,37 @@ 0.132375 0.096588134765625 0.2799914550781251 0.1325 0.061248779296875 0.2799914550781251 0.132625 0.0206298828125 0.2799914550781251 -0.13275 -0.01654052734375 0.2799914550781251 -0.132875 -0.05816650390625 0.2799914550781251 -0.133 -0.099029541015625 0.2799914550781251 -0.133125 -0.135955810546875 0.2799914550781251 -0.13325 -0.1746826171875 0.2799914550781251 -0.133375 -0.20953369140625 0.2799914550781251 -0.1335 -0.244537353515625 0.2799914550781251 -0.133625 -0.278961181640625 0.2799914550781251 -0.13375 -0.3056640625 0.2799914550781251 -0.133875 -0.334625244140625 0.2799914550781251 -0.134 -0.35809326171875 0.2799914550781251 -0.134125 -0.37774658203125 0.2799914550781251 -0.13425 -0.396026611328125 0.2799914550781251 -0.134375 -0.4063720703125 0.2799914550781251 -0.1345 -0.41650390625 0.2799914550781251 -0.134625 -0.419189453125 0.2799914550781251 -0.13475 -0.420654296875 0.2799914550781251 -0.134875 -0.414642333984375 0.2799914550781251 -0.135 -0.40802001953125 0.2799914550781251 -0.135125 -0.393402099609375 0.2799914550781251 -0.13525 -0.37896728515625 0.2799914550781251 -0.135375 -0.3583984375 0.2799914550781251 -0.1355 -0.33154296875 0.2799914550781251 -0.135625 -0.30615234375 0.2799914550781251 -0.13575 -0.2724609375 0.2799914550781251 -0.135875 -0.24102783203125 0.2799914550781251 -0.136 -0.2017822265625 0.2799914550781251 -0.136125 -0.161285400390625 0.2799914550781251 -0.13625 -0.122222900390625 0.2799914550781251 -0.136375 -0.078033447265625 0.2799914550781251 -0.1365 -0.036865234375 0.2799914550781251 +0.13275 -0.016510009765625 0.2799914550781251 +0.132875 -0.058135986328125 0.2799914550781251 +0.133 -0.0989990234375 0.2799914550781251 +0.133125 -0.13592529296875 0.2799914550781251 +0.13325 -0.174652099609375 0.2799914550781251 +0.133375 -0.209503173828125 0.2799914550781251 +0.1335 -0.2445068359375 0.2799914550781251 +0.133625 -0.2789306640625 0.2799914550781251 +0.13375 -0.305633544921875 0.2799914550781251 +0.133875 -0.3345947265625 0.2799914550781251 +0.134 -0.358062744140625 0.2799914550781251 +0.134125 -0.377716064453125 0.2799914550781251 +0.13425 -0.39599609375 0.2799914550781251 +0.134375 -0.406341552734375 0.2799914550781251 +0.1345 -0.416473388671875 0.2799914550781251 +0.134625 -0.419158935546875 0.2799914550781251 +0.13475 -0.420623779296875 0.2799914550781251 +0.134875 -0.41461181640625 0.2799914550781251 +0.135 -0.407989501953125 0.2799914550781251 +0.135125 -0.39337158203125 0.2799914550781251 +0.13525 -0.378936767578125 0.2799914550781251 +0.135375 -0.358367919921875 0.2799914550781251 +0.1355 -0.331512451171875 0.2799914550781251 +0.135625 -0.306121826171875 0.2799914550781251 +0.13575 -0.272430419921875 0.2799914550781251 +0.135875 -0.240997314453125 0.2799914550781251 +0.136 -0.201751708984375 0.2799914550781251 +0.136125 -0.1612548828125 0.2799914550781251 +0.13625 -0.1221923828125 0.2799914550781251 +0.136375 -0.0780029296875 0.2799914550781251 +0.1365 -0.036834716796875 0.2799914550781251 0.136625 0.009246826171875 0.2799914550781251 0.13675 0.0557861328125 0.2799914550781251 0.136875 0.097137451171875 0.2799914550781251 @@ -1123,37 +1123,37 @@ 0.14025 0.09881591796875 0.2799914550781251 0.140375 0.0496826171875 0.2799914550781251 0.1405 0.0 0.2799914550781251 -0.140625 -0.044891357421875 0.2799914550781251 -0.14075 -0.0946044921875 0.2799914550781251 -0.140875 -0.138763427734375 0.2799914550781251 -0.141 -0.18603515625 0.2799914550781251 -0.141125 -0.231964111328125 0.2799914550781251 -0.14125 -0.2706298828125 0.2799914550781251 -0.141375 -0.311676025390625 0.2799914550781251 -0.1415 -0.34503173828125 0.2799914550781251 -0.141625 -0.379486083984375 0.2799914550781251 -0.14175 -0.408843994140625 0.2799914550781251 -0.141875 -0.432586669921875 0.2799914550781251 -0.142 -0.4532470703125 0.2799914550781251 -0.142125 -0.468780517578125 0.2799914550781251 -0.14225 -0.4810791015625 0.2799914550781251 -0.142375 -0.4869384765625 0.2799914550781251 -0.1425 -0.48876953125 0.2799914550781251 -0.142625 -0.484466552734375 0.2799914550781251 -0.14275 -0.477142333984375 0.2799914550781251 -0.142875 -0.46282958984375 0.2799914550781251 -0.143 -0.4443359375 0.2799914550781251 -0.143125 -0.422698974609375 0.2799914550781251 -0.14325 -0.39501953125 0.2799914550781251 -0.143375 -0.3663330078125 0.2799914550781251 -0.1435 -0.329833984375 0.2799914550781251 -0.143625 -0.29022216796875 0.2799914550781251 -0.14375 -0.2513427734375 0.2799914550781251 -0.143875 -0.205902099609375 0.2799914550781251 -0.144 -0.162628173828125 0.2799914550781251 -0.144125 -0.11309814453125 0.2799914550781251 -0.14425 -0.06207275390625 0.2799914550781251 -0.144375 -0.01556396484375 0.2799914550781251 +0.140625 -0.04486083984375 0.2799914550781251 +0.14075 -0.094573974609375 0.2799914550781251 +0.140875 -0.13873291015625 0.2799914550781251 +0.141 -0.186004638671875 0.2799914550781251 +0.141125 -0.23193359375 0.2799914550781251 +0.14125 -0.270599365234375 0.2799914550781251 +0.141375 -0.3116455078125 0.2799914550781251 +0.1415 -0.345001220703125 0.2799914550781251 +0.141625 -0.37945556640625 0.2799914550781251 +0.14175 -0.4088134765625 0.2799914550781251 +0.141875 -0.43255615234375 0.2799914550781251 +0.142 -0.453216552734375 0.2799914550781251 +0.142125 -0.46875 0.2799914550781251 +0.14225 -0.481048583984375 0.2799914550781251 +0.142375 -0.486907958984375 0.2799914550781251 +0.1425 -0.488739013671875 0.2799914550781251 +0.142625 -0.48443603515625 0.2799914550781251 +0.14275 -0.47711181640625 0.2799914550781251 +0.142875 -0.462799072265625 0.2799914550781251 +0.143 -0.444305419921875 0.2799914550781251 +0.143125 -0.42266845703125 0.2799914550781251 +0.14325 -0.394989013671875 0.2799914550781251 +0.143375 -0.366302490234375 0.2799914550781251 +0.1435 -0.329803466796875 0.2799914550781251 +0.143625 -0.290191650390625 0.2799914550781251 +0.14375 -0.251312255859375 0.2799914550781251 +0.143875 -0.20587158203125 0.2799914550781251 +0.144 -0.16259765625 0.2799914550781251 +0.144125 -0.113067626953125 0.2799914550781251 +0.14425 -0.062042236328125 0.2799914550781251 +0.144375 -0.015533447265625 0.2799914550781251 0.1445 0.036285400390625 0.2799914550781251 0.144625 0.082794189453125 0.2799914550781251 0.14475 0.1336669921875 0.2799914550781251 @@ -1185,37 +1185,37 @@ 0.148 0.124176025390625 0.2799914550781251 0.148125 0.078094482421875 0.2799914550781251 0.14825 0.026092529296875 0.2799914550781251 -0.148375 -0.020904541015625 0.2799914550781251 -0.1485 -0.0728759765625 0.2799914550781251 -0.148625 -0.12408447265625 0.2799914550781251 -0.14875 -0.16888427734375 0.2799914550781251 -0.148875 -0.216827392578125 0.2799914550781251 -0.149 -0.258056640625 0.2799914550781251 -0.149125 -0.3009033203125 0.2799914550781251 -0.14925 -0.3406982421875 0.2799914550781251 -0.149375 -0.372955322265625 0.2799914550781251 -0.1495 -0.4052734375 0.2799914550781251 -0.149625 -0.430084228515625 0.2799914550781251 -0.14975 -0.45367431640625 0.2799914550781251 -0.149875 -0.471710205078125 0.2799914550781251 -0.15 -0.484039306640625 0.2799914550781251 -0.150125 -0.492034912109375 0.2799914550781251 -0.15025 -0.494476318359375 0.2799914550781251 -0.150375 -0.49285888671875 0.2799914550781251 -0.1505 -0.48504638671875 0.2799914550781251 -0.150625 -0.47418212890625 0.2799914550781251 -0.15075 -0.4564208984375 0.2799914550781251 -0.150875 -0.436859130859375 0.2799914550781251 -0.151 -0.409820556640625 0.2799914550781251 -0.151125 -0.379119873046875 0.2799914550781251 -0.15125 -0.34722900390625 0.2799914550781251 -0.151375 -0.30902099609375 0.2799914550781251 -0.1515 -0.27117919921875 0.2799914550781251 -0.151625 -0.2265625 0.2799914550781251 -0.15175 -0.180023193359375 0.2799914550781251 -0.151875 -0.1361083984375 0.2799914550781251 -0.152 -0.086395263671875 0.2799914550781251 -0.152125 -0.04071044921875 0.2799914550781251 +0.148375 -0.0208740234375 0.2799914550781251 +0.1485 -0.072845458984375 0.2799914550781251 +0.148625 -0.124053955078125 0.2799914550781251 +0.14875 -0.168853759765625 0.2799914550781251 +0.148875 -0.216796875 0.2799914550781251 +0.149 -0.258026123046875 0.2799914550781251 +0.149125 -0.300872802734375 0.2799914550781251 +0.14925 -0.340667724609375 0.2799914550781251 +0.149375 -0.3729248046875 0.2799914550781251 +0.1495 -0.405242919921875 0.2799914550781251 +0.149625 -0.4300537109375 0.2799914550781251 +0.14975 -0.453643798828125 0.2799914550781251 +0.149875 -0.4716796875 0.2799914550781251 +0.15 -0.4840087890625 0.2799914550781251 +0.150125 -0.49200439453125 0.2799914550781251 +0.15025 -0.49444580078125 0.2799914550781251 +0.150375 -0.492828369140625 0.2799914550781251 +0.1505 -0.485015869140625 0.2799914550781251 +0.150625 -0.474151611328125 0.2799914550781251 +0.15075 -0.456390380859375 0.2799914550781251 +0.150875 -0.43682861328125 0.2799914550781251 +0.151 -0.4097900390625 0.2799914550781251 +0.151125 -0.37908935546875 0.2799914550781251 +0.15125 -0.347198486328125 0.2799914550781251 +0.151375 -0.308990478515625 0.2799914550781251 +0.1515 -0.271148681640625 0.2799914550781251 +0.151625 -0.226531982421875 0.2799914550781251 +0.15175 -0.17999267578125 0.2799914550781251 +0.151875 -0.136077880859375 0.2799914550781251 +0.152 -0.08636474609375 0.2799914550781251 +0.152125 -0.040679931640625 0.2799914550781251 0.15225 0.010162353515625 0.2799914550781251 0.152375 0.060821533203125 0.2799914550781251 0.1525 0.105865478515625 0.2799914550781251 @@ -1248,37 +1248,37 @@ 0.155875 0.095794677734375 0.2799914550781251 0.156 0.047943115234375 0.2799914550781251 0.156125 0.0 0.2799914550781251 -0.15625 -0.04296875 0.2799914550781251 -0.156375 -0.09027099609375 0.2799914550781251 -0.1565 -0.131378173828125 0.2799914550781251 -0.156625 -0.1761474609375 0.2799914550781251 -0.15675 -0.217926025390625 0.2799914550781251 -0.156875 -0.25299072265625 0.2799914550781251 -0.157 -0.290496826171875 0.2799914550781251 -0.157125 -0.3199462890625 0.2799914550781251 -0.15725 -0.350921630859375 0.2799914550781251 -0.157375 -0.3760986328125 0.2799914550781251 -0.1575 -0.396881103515625 0.2799914550781251 -0.157625 -0.413604736328125 0.2799914550781251 -0.15775 -0.426727294921875 0.2799914550781251 -0.157875 -0.434417724609375 0.2799914550781251 -0.158 -0.439727783203125 0.2799914550781251 -0.158125 -0.4378662109375 0.2799914550781251 -0.15825 -0.4315185546875 0.2799914550781251 -0.158375 -0.424041748046875 0.2799914550781251 -0.1585 -0.40887451171875 0.2799914550781251 -0.158625 -0.391754150390625 0.2799914550781251 -0.15875 -0.370361328125 0.2799914550781251 -0.158875 -0.345458984375 0.2799914550781251 -0.159 -0.317779541015625 0.2799914550781251 -0.159125 -0.2861328125 0.2799914550781251 -0.15925 -0.249755859375 0.2799914550781251 -0.159375 -0.216278076171875 0.2799914550781251 -0.1595 -0.17572021484375 0.2799914550781251 -0.159625 -0.13787841796875 0.2799914550781251 -0.15975 -0.095733642578125 0.2799914550781251 -0.159875 -0.05218505859375 0.2799914550781251 -0.16 -0.013092041015625 0.535983642578125 +0.15625 -0.042938232421875 0.2799914550781251 +0.156375 -0.090240478515625 0.2799914550781251 +0.1565 -0.13134765625 0.2799914550781251 +0.156625 -0.176116943359375 0.2799914550781251 +0.15675 -0.2178955078125 0.2799914550781251 +0.156875 -0.252960205078125 0.2799914550781251 +0.157 -0.29046630859375 0.2799914550781251 +0.157125 -0.319915771484375 0.2799914550781251 +0.15725 -0.35089111328125 0.2799914550781251 +0.157375 -0.376068115234375 0.2799914550781251 +0.1575 -0.3968505859375 0.2799914550781251 +0.157625 -0.41357421875 0.2799914550781251 +0.15775 -0.42669677734375 0.2799914550781251 +0.157875 -0.43438720703125 0.2799914550781251 +0.158 -0.439697265625 0.2799914550781251 +0.158125 -0.437835693359375 0.2799914550781251 +0.15825 -0.431488037109375 0.2799914550781251 +0.158375 -0.42401123046875 0.2799914550781251 +0.1585 -0.408843994140625 0.2799914550781251 +0.158625 -0.3917236328125 0.2799914550781251 +0.15875 -0.370330810546875 0.2799914550781251 +0.158875 -0.345428466796875 0.2799914550781251 +0.159 -0.3177490234375 0.2799914550781251 +0.159125 -0.286102294921875 0.2799914550781251 +0.15925 -0.249725341796875 0.2799914550781251 +0.159375 -0.21624755859375 0.2799914550781251 +0.1595 -0.175689697265625 0.2799914550781251 +0.159625 -0.137847900390625 0.2799914550781251 +0.15975 -0.095703125 0.2799914550781251 +0.159875 -0.052154541015625 0.2799914550781251 +0.16 -0.0130615234375 0.535983642578125 0.160125 0.030242919921875 0.535983642578125 0.16025 0.06842041015625 0.535983642578125 0.160375 0.1103515625 0.535983642578125 @@ -1310,37 +1310,37 @@ 0.163625 0.087890625 0.535983642578125 0.16375 0.0546875 0.535983642578125 0.163875 0.01806640625 0.535983642578125 -0.164 -0.014495849609375 0.535983642578125 -0.164125 -0.04998779296875 0.535983642578125 -0.16425 -0.084136962890625 0.535983642578125 -0.164375 -0.1146240234375 0.535983642578125 -0.1645 -0.145599365234375 0.535983642578125 -0.164625 -0.173309326171875 0.535983642578125 -0.16475 -0.19989013671875 0.535983642578125 -0.164875 -0.2236328125 0.535983642578125 -0.165 -0.245025634765625 0.535983642578125 -0.165125 -0.263031005859375 0.535983642578125 -0.16525 -0.275970458984375 0.535983642578125 -0.165375 -0.291107177734375 0.535983642578125 -0.1655 -0.299224853515625 0.535983642578125 -0.165625 -0.30303955078125 0.535983642578125 -0.16575 -0.3084716796875 0.535983642578125 -0.165875 -0.30633544921875 0.535983642578125 -0.166 -0.301177978515625 0.535983642578125 -0.166125 -0.296905517578125 0.535983642578125 -0.16625 -0.286224365234375 0.535983642578125 -0.166375 -0.272064208984375 0.535983642578125 -0.1665 -0.260406494140625 0.535983642578125 -0.166625 -0.241241455078125 0.535983642578125 -0.16675 -0.2198486328125 0.535983642578125 -0.166875 -0.201751708984375 0.535983642578125 -0.167 -0.176849365234375 0.535983642578125 -0.167125 -0.153106689453125 0.535983642578125 -0.16725 -0.128173828125 0.535983642578125 -0.167375 -0.100250244140625 0.535983642578125 -0.1675 -0.075958251953125 0.535983642578125 -0.167625 -0.04742431640625 0.535983642578125 -0.16775 -0.02203369140625 0.535983642578125 +0.164 -0.01446533203125 0.535983642578125 +0.164125 -0.049957275390625 0.535983642578125 +0.16425 -0.0841064453125 0.535983642578125 +0.164375 -0.114593505859375 0.535983642578125 +0.1645 -0.14556884765625 0.535983642578125 +0.164625 -0.17327880859375 0.535983642578125 +0.16475 -0.199859619140625 0.535983642578125 +0.164875 -0.223602294921875 0.535983642578125 +0.165 -0.2449951171875 0.535983642578125 +0.165125 -0.26300048828125 0.535983642578125 +0.16525 -0.27593994140625 0.535983642578125 +0.165375 -0.29107666015625 0.535983642578125 +0.1655 -0.2991943359375 0.535983642578125 +0.165625 -0.303009033203125 0.535983642578125 +0.16575 -0.308441162109375 0.535983642578125 +0.165875 -0.306304931640625 0.535983642578125 +0.166 -0.3011474609375 0.535983642578125 +0.166125 -0.296875 0.535983642578125 +0.16625 -0.28619384765625 0.535983642578125 +0.166375 -0.27203369140625 0.535983642578125 +0.1665 -0.2603759765625 0.535983642578125 +0.166625 -0.2412109375 0.535983642578125 +0.16675 -0.219818115234375 0.535983642578125 +0.166875 -0.20172119140625 0.535983642578125 +0.167 -0.17681884765625 0.535983642578125 +0.167125 -0.153076171875 0.535983642578125 +0.16725 -0.128143310546875 0.535983642578125 +0.167375 -0.1002197265625 0.535983642578125 +0.1675 -0.075927734375 0.535983642578125 +0.167625 -0.047393798828125 0.535983642578125 +0.16775 -0.022003173828125 0.535983642578125 0.167875 0.0054931640625 0.535983642578125 0.168 0.03240966796875 0.535983642578125 0.168125 0.05548095703125 0.535983642578125 @@ -1373,37 +1373,37 @@ 0.1715 0.03619384765625 0.535983642578125 0.171625 0.017669677734375 0.535983642578125 0.17175 0.0 0.535983642578125 -0.171875 -0.015472412109375 0.535983642578125 -0.172 -0.031524658203125 0.535983642578125 -0.172125 -0.044647216796875 0.535983642578125 -0.17225 -0.05987548828125 0.535983642578125 -0.172375 -0.072021484375 0.535983642578125 -0.1725 -0.081207275390625 0.535983642578125 -0.172625 -0.09326171875 0.535983642578125 -0.17275 -0.099639892578125 0.535983642578125 -0.172875 -0.1053466796875 0.535983642578125 -0.173 -0.113525390625 0.535983642578125 -0.173125 -0.11529541015625 0.535983642578125 -0.17325 -0.12078857421875 0.535983642578125 -0.173375 -0.1197509765625 0.535983642578125 -0.1735 -0.117584228515625 0.535983642578125 -0.173625 -0.1190185546875 0.535983642578125 -0.17375 -0.114105224609375 0.535983642578125 -0.173875 -0.1080322265625 0.535983642578125 -0.174 -0.106170654296875 0.535983642578125 -0.174125 -0.09814453125 0.535983642578125 -0.17425 -0.08941650390625 0.535983642578125 -0.174375 -0.085052490234375 0.535983642578125 -0.1745 -0.0751953125 0.535983642578125 -0.174625 -0.0657958984375 0.535983642578125 -0.17475 -0.059234619140625 0.535983642578125 -0.174875 -0.04901123046875 0.535983642578125 -0.175 -0.039794921875 0.535983642578125 -0.175125 -0.032562255859375 0.535983642578125 -0.17525 -0.024017333984375 0.535983642578125 -0.175375 -0.0155029296875 0.535983642578125 -0.1755 -0.008514404296875 0.535983642578125 -0.175625 -0.001953125 0.535983642578125 +0.171875 -0.01544189453125 0.535983642578125 +0.172 -0.031494140625 0.535983642578125 +0.172125 -0.04461669921875 0.535983642578125 +0.17225 -0.059844970703125 0.535983642578125 +0.172375 -0.071990966796875 0.535983642578125 +0.1725 -0.0811767578125 0.535983642578125 +0.172625 -0.093231201171875 0.535983642578125 +0.17275 -0.099609375 0.535983642578125 +0.172875 -0.105316162109375 0.535983642578125 +0.173 -0.113494873046875 0.535983642578125 +0.173125 -0.115264892578125 0.535983642578125 +0.17325 -0.120758056640625 0.535983642578125 +0.173375 -0.119720458984375 0.535983642578125 +0.1735 -0.1175537109375 0.535983642578125 +0.173625 -0.118988037109375 0.535983642578125 +0.17375 -0.11407470703125 0.535983642578125 +0.173875 -0.108001708984375 0.535983642578125 +0.174 -0.10614013671875 0.535983642578125 +0.174125 -0.098114013671875 0.535983642578125 +0.17425 -0.089385986328125 0.535983642578125 +0.174375 -0.08502197265625 0.535983642578125 +0.1745 -0.075164794921875 0.535983642578125 +0.174625 -0.065765380859375 0.535983642578125 +0.17475 -0.0592041015625 0.535983642578125 +0.174875 -0.048980712890625 0.535983642578125 +0.175 -0.039764404296875 0.535983642578125 +0.175125 -0.03253173828125 0.535983642578125 +0.17525 -0.02398681640625 0.535983642578125 +0.175375 -0.015472412109375 0.535983642578125 +0.1755 -0.00848388671875 0.535983642578125 +0.175625 -0.001922607421875 0.535983642578125 0.17575 0.004180908203125 0.535983642578125 0.175875 0.009552001953125 0.535983642578125 0.176 0.014007568359375 0.535983642578125 @@ -1423,18 +1423,18 @@ 0.17775 0.00518798828125 0.535983642578125 0.177875 0.0 0.535983642578125 0.178 0.0 0.535983642578125 -0.178125 -0.004791259765625 0.535983642578125 -0.17825 -0.009124755859375 0.535983642578125 -0.178375 -0.00860595703125 0.535983642578125 -0.1785 -0.011871337890625 0.535983642578125 -0.178625 -0.01434326171875 0.535983642578125 -0.17875 -0.0128173828125 0.535983642578125 -0.178875 -0.0137939453125 0.535983642578125 -0.179 -0.013946533203125 0.535983642578125 -0.179125 -0.01092529296875 0.535983642578125 -0.17925 -0.00909423828125 0.535983642578125 -0.179375 -0.0057373046875 0.535983642578125 -0.1795 -0.002197265625 0.535983642578125 +0.178125 -0.0047607421875 0.535983642578125 +0.17825 -0.00909423828125 0.535983642578125 +0.178375 -0.008575439453125 0.535983642578125 +0.1785 -0.0118408203125 0.535983642578125 +0.178625 -0.014312744140625 0.535983642578125 +0.17875 -0.012786865234375 0.535983642578125 +0.178875 -0.013763427734375 0.535983642578125 +0.179 -0.013916015625 0.535983642578125 +0.179125 -0.010894775390625 0.535983642578125 +0.17925 -0.009063720703125 0.535983642578125 +0.179375 -0.005706787109375 0.535983642578125 +0.1795 -0.002166748046875 0.535983642578125 0.179625 0.001953125 0.535983642578125 0.17975 0.0068359375 0.535983642578125 0.179875 0.012969970703125 0.535983642578125 @@ -1466,37 +1466,37 @@ 0.183125 0.03887939453125 0.535983642578125 0.18325 0.025543212890625 0.535983642578125 0.183375 0.012054443359375 0.535983642578125 -0.1835 -0.003143310546875 0.535983642578125 -0.183625 -0.01934814453125 0.535983642578125 -0.18375 -0.03369140625 0.535983642578125 -0.183875 -0.050872802734375 0.535983642578125 -0.184 -0.066864013671875 0.535983642578125 -0.184125 -0.08221435546875 0.535983642578125 -0.18425 -0.09954833984375 0.535983642578125 -0.184375 -0.115234375 0.535983642578125 -0.1845 -0.128265380859375 0.535983642578125 -0.184625 -0.1427001953125 0.535983642578125 -0.18475 -0.15740966796875 0.535983642578125 -0.184875 -0.166534423828125 0.535983642578125 -0.185 -0.177734375 0.535983642578125 -0.185125 -0.188140869140625 0.535983642578125 -0.18525 -0.191650390625 0.535983642578125 -0.185375 -0.198394775390625 0.535983642578125 -0.1855 -0.198150634765625 0.535983642578125 -0.185625 -0.200836181640625 0.535983642578125 -0.18575 -0.201019287109375 0.535983642578125 -0.185875 -0.195068359375 0.535983642578125 -0.186 -0.190673828125 0.535983642578125 -0.186125 -0.1837158203125 0.535983642578125 -0.18625 -0.17193603515625 0.535983642578125 -0.186375 -0.160430908203125 0.535983642578125 -0.1865 -0.1483154296875 0.535983642578125 -0.186625 -0.1295166015625 0.535983642578125 -0.18675 -0.111572265625 0.535983642578125 -0.186875 -0.093841552734375 0.535983642578125 -0.187 -0.070648193359375 0.535983642578125 -0.187125 -0.050079345703125 0.535983642578125 -0.18725 -0.025665283203125 0.535983642578125 +0.1835 -0.00311279296875 0.535983642578125 +0.183625 -0.019317626953125 0.535983642578125 +0.18375 -0.033660888671875 0.535983642578125 +0.183875 -0.05084228515625 0.535983642578125 +0.184 -0.06683349609375 0.535983642578125 +0.184125 -0.082183837890625 0.535983642578125 +0.18425 -0.099517822265625 0.535983642578125 +0.184375 -0.115203857421875 0.535983642578125 +0.1845 -0.12823486328125 0.535983642578125 +0.184625 -0.142669677734375 0.535983642578125 +0.18475 -0.157379150390625 0.535983642578125 +0.184875 -0.16650390625 0.535983642578125 +0.185 -0.177703857421875 0.535983642578125 +0.185125 -0.1881103515625 0.535983642578125 +0.18525 -0.191619873046875 0.535983642578125 +0.185375 -0.1983642578125 0.535983642578125 +0.1855 -0.1981201171875 0.535983642578125 +0.185625 -0.2008056640625 0.535983642578125 +0.18575 -0.20098876953125 0.535983642578125 +0.185875 -0.195037841796875 0.535983642578125 +0.186 -0.190643310546875 0.535983642578125 +0.186125 -0.183685302734375 0.535983642578125 +0.18625 -0.171905517578125 0.535983642578125 +0.186375 -0.160400390625 0.535983642578125 +0.1865 -0.148284912109375 0.535983642578125 +0.186625 -0.129486083984375 0.535983642578125 +0.18675 -0.111541748046875 0.535983642578125 +0.186875 -0.09381103515625 0.535983642578125 +0.187 -0.07061767578125 0.535983642578125 +0.187125 -0.050048828125 0.535983642578125 +0.18725 -0.025634765625 0.535983642578125 0.187375 0.0 0.535983642578125 0.1875 0.02349853515625 0.535983642578125 0.187625 0.050262451171875 0.535983642578125 @@ -1529,37 +1529,37 @@ 0.191 0.074554443359375 0.535983642578125 0.191125 0.041412353515625 0.535983642578125 0.19125 0.010345458984375 0.535983642578125 -0.191375 -0.024505615234375 0.535983642578125 -0.1915 -0.056427001953125 0.535983642578125 -0.191625 -0.09100341796875 0.535983642578125 -0.19175 -0.1259765625 0.535983642578125 -0.191875 -0.1571044921875 0.535983642578125 -0.192 -0.190521240234375 0.791975830078125 -0.192125 -0.21728515625 0.791975830078125 -0.19225 -0.247344970703125 0.791975830078125 -0.192375 -0.27520751953125 0.791975830078125 -0.1925 -0.298431396484375 0.791975830078125 -0.192625 -0.3179931640625 0.791975830078125 -0.19275 -0.335968017578125 0.791975830078125 -0.192875 -0.352294921875 0.791975830078125 -0.193 -0.36492919921875 0.791975830078125 -0.193125 -0.373321533203125 0.791975830078125 -0.19325 -0.374969482421875 0.791975830078125 -0.193375 -0.376373291015625 0.791975830078125 -0.1935 -0.373504638671875 0.791975830078125 -0.193625 -0.366363525390625 0.791975830078125 -0.19375 -0.353515625 0.791975830078125 -0.193875 -0.338470458984375 0.791975830078125 -0.194 -0.32171630859375 0.791975830078125 -0.194125 -0.299041748046875 0.791975830078125 -0.19425 -0.2725830078125 0.791975830078125 -0.194375 -0.24407958984375 0.791975830078125 -0.1945 -0.21148681640625 0.791975830078125 -0.194625 -0.179840087890625 0.791975830078125 -0.19475 -0.142059326171875 0.791975830078125 -0.194875 -0.101348876953125 0.791975830078125 -0.195 -0.064208984375 0.791975830078125 -0.195125 -0.021636962890625 0.791975830078125 +0.191375 -0.02447509765625 0.535983642578125 +0.1915 -0.056396484375 0.535983642578125 +0.191625 -0.090972900390625 0.535983642578125 +0.19175 -0.125946044921875 0.535983642578125 +0.191875 -0.157073974609375 0.535983642578125 +0.192 -0.19049072265625 0.791975830078125 +0.192125 -0.217254638671875 0.791975830078125 +0.19225 -0.247314453125 0.791975830078125 +0.192375 -0.275177001953125 0.791975830078125 +0.1925 -0.29840087890625 0.791975830078125 +0.192625 -0.317962646484375 0.791975830078125 +0.19275 -0.3359375 0.791975830078125 +0.192875 -0.352264404296875 0.791975830078125 +0.193 -0.364898681640625 0.791975830078125 +0.193125 -0.373291015625 0.791975830078125 +0.19325 -0.37493896484375 0.791975830078125 +0.193375 -0.3763427734375 0.791975830078125 +0.1935 -0.37347412109375 0.791975830078125 +0.193625 -0.3663330078125 0.791975830078125 +0.19375 -0.353485107421875 0.791975830078125 +0.193875 -0.33843994140625 0.791975830078125 +0.194 -0.321685791015625 0.791975830078125 +0.194125 -0.29901123046875 0.791975830078125 +0.19425 -0.272552490234375 0.791975830078125 +0.194375 -0.244049072265625 0.791975830078125 +0.1945 -0.211456298828125 0.791975830078125 +0.194625 -0.1798095703125 0.791975830078125 +0.19475 -0.14202880859375 0.791975830078125 +0.194875 -0.101318359375 0.791975830078125 +0.195 -0.064178466796875 0.791975830078125 +0.195125 -0.0216064453125 0.791975830078125 0.19525 0.01739501953125 0.791975830078125 0.195375 0.06121826171875 0.791975830078125 0.1955 0.104248046875 0.791975830078125 @@ -1591,37 +1591,37 @@ 0.19875 0.130706787109375 0.791975830078125 0.198875 0.08294677734375 0.791975830078125 0.199 0.039306640625 0.791975830078125 -0.199125 -0.0098876953125 0.791975830078125 -0.19925 -0.05938720703125 0.791975830078125 -0.199375 -0.10369873046875 0.791975830078125 -0.1995 -0.15167236328125 0.791975830078125 -0.199625 -0.19403076171875 0.791975830078125 -0.19975 -0.23931884765625 0.791975830078125 -0.199875 -0.28216552734375 0.791975830078125 -0.2 -0.317474365234375 0.791975830078125 -0.200125 -0.35443115234375 0.791975830078125 -0.20025 -0.3846435546875 0.791975830078125 -0.200375 -0.4141845703125 0.791975830078125 -0.2005 -0.439300537109375 0.791975830078125 -0.200625 -0.456817626953125 0.791975830078125 -0.20075 -0.472686767578125 0.791975830078125 -0.200875 -0.482666015625 0.791975830078125 -0.201 -0.48858642578125 0.791975830078125 -0.201125 -0.488037109375 0.791975830078125 -0.20125 -0.484039306640625 0.791975830078125 -0.201375 -0.474334716796875 0.791975830078125 -0.2015 -0.461181640625 0.791975830078125 -0.201625 -0.4415283203125 0.791975830078125 -0.20175 -0.41619873046875 0.791975830078125 -0.201875 -0.390167236328125 0.791975830078125 -0.202 -0.356964111328125 0.791975830078125 -0.202125 -0.323638916015625 0.791975830078125 -0.20225 -0.28265380859375 0.791975830078125 -0.202375 -0.23895263671875 0.791975830078125 -0.2025 -0.197235107421875 0.791975830078125 -0.202625 -0.148681640625 0.791975830078125 -0.20275 -0.103485107421875 0.791975830078125 -0.202875 -0.052032470703125 0.791975830078125 +0.199125 -0.009857177734375 0.791975830078125 +0.19925 -0.059356689453125 0.791975830078125 +0.199375 -0.103668212890625 0.791975830078125 +0.1995 -0.151641845703125 0.791975830078125 +0.199625 -0.194000244140625 0.791975830078125 +0.19975 -0.239288330078125 0.791975830078125 +0.199875 -0.282135009765625 0.791975830078125 +0.2 -0.31744384765625 0.791975830078125 +0.200125 -0.354400634765625 0.791975830078125 +0.20025 -0.384613037109375 0.791975830078125 +0.200375 -0.414154052734375 0.791975830078125 +0.2005 -0.43927001953125 0.791975830078125 +0.200625 -0.456787109375 0.791975830078125 +0.20075 -0.47265625 0.791975830078125 +0.200875 -0.482635498046875 0.791975830078125 +0.201 -0.488555908203125 0.791975830078125 +0.201125 -0.488006591796875 0.791975830078125 +0.20125 -0.4840087890625 0.791975830078125 +0.201375 -0.47430419921875 0.791975830078125 +0.2015 -0.461151123046875 0.791975830078125 +0.201625 -0.441497802734375 0.791975830078125 +0.20175 -0.416168212890625 0.791975830078125 +0.201875 -0.39013671875 0.791975830078125 +0.202 -0.35693359375 0.791975830078125 +0.202125 -0.3236083984375 0.791975830078125 +0.20225 -0.282623291015625 0.791975830078125 +0.202375 -0.238922119140625 0.791975830078125 +0.2025 -0.19720458984375 0.791975830078125 +0.202625 -0.148651123046875 0.791975830078125 +0.20275 -0.10345458984375 0.791975830078125 +0.202875 -0.052001953125 0.791975830078125 0.203 0.0 0.791975830078125 0.203125 0.046875 0.791975830078125 0.20325 0.09857177734375 0.791975830078125 @@ -1654,37 +1654,37 @@ 0.206625 0.11273193359375 0.791975830078125 0.20675 0.061737060546875 0.791975830078125 0.206875 0.01544189453125 0.791975830078125 -0.207 -0.036041259765625 0.791975830078125 -0.207125 -0.081878662109375 0.791975830078125 -0.20725 -0.13177490234375 0.791975830078125 -0.207375 -0.180419921875 0.791975830078125 -0.2075 -0.222015380859375 0.791975830078125 -0.207625 -0.265716552734375 0.791975830078125 -0.20775 -0.302337646484375 0.791975830078125 -0.207875 -0.339691162109375 0.791975830078125 -0.208 -0.37408447265625 0.791975830078125 -0.208125 -0.400482177734375 0.791975830078125 -0.20825 -0.425567626953125 0.791975830078125 -0.208375 -0.443878173828125 0.791975830078125 -0.2085 -0.460968017578125 0.791975830078125 -0.208625 -0.471588134765625 0.791975830078125 -0.20875 -0.476470947265625 0.791975830078125 -0.208875 -0.47705078125 0.791975830078125 -0.209 -0.472869873046875 0.791975830078125 -0.209125 -0.465087890625 0.791975830078125 -0.20925 -0.45062255859375 0.791975830078125 -0.209375 -0.433319091796875 0.791975830078125 -0.2095 -0.4097900390625 0.791975830078125 -0.209625 -0.38623046875 0.791975830078125 -0.20975 -0.354705810546875 0.791975830078125 -0.209875 -0.319488525390625 0.791975830078125 -0.21 -0.284881591796875 0.791975830078125 -0.210125 -0.243927001953125 0.791975830078125 -0.21025 -0.205810546875 0.791975830078125 -0.210375 -0.16064453125 0.791975830078125 -0.2105 -0.114105224609375 0.791975830078125 -0.210625 -0.071441650390625 0.791975830078125 -0.21075 -0.023895263671875 0.791975830078125 +0.207 -0.0360107421875 0.791975830078125 +0.207125 -0.08184814453125 0.791975830078125 +0.20725 -0.131744384765625 0.791975830078125 +0.207375 -0.180389404296875 0.791975830078125 +0.2075 -0.22198486328125 0.791975830078125 +0.207625 -0.26568603515625 0.791975830078125 +0.20775 -0.30230712890625 0.791975830078125 +0.207875 -0.33966064453125 0.791975830078125 +0.208 -0.374053955078125 0.791975830078125 +0.208125 -0.40045166015625 0.791975830078125 +0.20825 -0.425537109375 0.791975830078125 +0.208375 -0.44384765625 0.791975830078125 +0.2085 -0.4609375 0.791975830078125 +0.208625 -0.4715576171875 0.791975830078125 +0.20875 -0.4764404296875 0.791975830078125 +0.208875 -0.477020263671875 0.791975830078125 +0.209 -0.47283935546875 0.791975830078125 +0.209125 -0.465057373046875 0.791975830078125 +0.20925 -0.450592041015625 0.791975830078125 +0.209375 -0.43328857421875 0.791975830078125 +0.2095 -0.409759521484375 0.791975830078125 +0.209625 -0.386199951171875 0.791975830078125 +0.20975 -0.35467529296875 0.791975830078125 +0.209875 -0.3194580078125 0.791975830078125 +0.21 -0.28485107421875 0.791975830078125 +0.210125 -0.243896484375 0.791975830078125 +0.21025 -0.205780029296875 0.791975830078125 +0.210375 -0.160614013671875 0.791975830078125 +0.2105 -0.11407470703125 0.791975830078125 +0.210625 -0.0714111328125 0.791975830078125 +0.21075 -0.02386474609375 0.791975830078125 0.210875 0.019012451171875 0.791975830078125 0.211 0.0660400390625 0.791975830078125 0.211125 0.111907958984375 0.791975830078125 @@ -1716,37 +1716,37 @@ 0.214375 0.11016845703125 0.791975830078125 0.2145 0.0693359375 0.791975830078125 0.214625 0.032470703125 0.791975830078125 -0.21475 -0.008148193359375 0.791975830078125 -0.214875 -0.04827880859375 0.791975830078125 -0.215 -0.083282470703125 0.791975830078125 -0.215125 -0.120697021484375 0.791975830078125 -0.21525 -0.15252685546875 0.791975830078125 -0.215375 -0.1875 0.791975830078125 -0.2155 -0.2183837890625 0.791975830078125 -0.215625 -0.243377685546875 0.791975830078125 -0.21575 -0.26824951171875 0.791975830078125 -0.215875 -0.290283203125 0.791975830078125 -0.216 -0.308624267578125 0.791975830078125 -0.216125 -0.32318115234375 0.791975830078125 -0.21625 -0.332611083984375 0.791975830078125 -0.216375 -0.339691162109375 0.791975830078125 -0.2165 -0.346038818359375 0.791975830078125 -0.216625 -0.345733642578125 0.791975830078125 -0.21675 -0.341552734375 0.791975830078125 -0.216875 -0.334228515625 0.791975830078125 -0.217 -0.326873779296875 0.791975830078125 -0.217125 -0.31353759765625 0.791975830078125 -0.21725 -0.296142578125 0.791975830078125 -0.217375 -0.27581787109375 0.791975830078125 -0.2175 -0.254974365234375 0.791975830078125 -0.217625 -0.23291015625 0.791975830078125 -0.21775 -0.208221435546875 0.791975830078125 -0.217875 -0.1795654296875 0.791975830078125 -0.218 -0.14959716796875 0.791975830078125 -0.218125 -0.123321533203125 0.791975830078125 -0.21825 -0.091644287109375 0.791975830078125 -0.218375 -0.062835693359375 0.791975830078125 -0.2185 -0.031158447265625 0.791975830078125 +0.21475 -0.00811767578125 0.791975830078125 +0.214875 -0.048248291015625 0.791975830078125 +0.215 -0.083251953125 0.791975830078125 +0.215125 -0.12066650390625 0.791975830078125 +0.21525 -0.152496337890625 0.791975830078125 +0.215375 -0.187469482421875 0.791975830078125 +0.2155 -0.218353271484375 0.791975830078125 +0.215625 -0.24334716796875 0.791975830078125 +0.21575 -0.268218994140625 0.791975830078125 +0.215875 -0.290252685546875 0.791975830078125 +0.216 -0.30859375 0.791975830078125 +0.216125 -0.323150634765625 0.791975830078125 +0.21625 -0.33258056640625 0.791975830078125 +0.216375 -0.33966064453125 0.791975830078125 +0.2165 -0.34600830078125 0.791975830078125 +0.216625 -0.345703125 0.791975830078125 +0.21675 -0.341522216796875 0.791975830078125 +0.216875 -0.334197998046875 0.791975830078125 +0.217 -0.32684326171875 0.791975830078125 +0.217125 -0.313507080078125 0.791975830078125 +0.21725 -0.296112060546875 0.791975830078125 +0.217375 -0.275787353515625 0.791975830078125 +0.2175 -0.25494384765625 0.791975830078125 +0.217625 -0.232879638671875 0.791975830078125 +0.21775 -0.20819091796875 0.791975830078125 +0.217875 -0.179534912109375 0.791975830078125 +0.218 -0.149566650390625 0.791975830078125 +0.218125 -0.123291015625 0.791975830078125 +0.21825 -0.09161376953125 0.791975830078125 +0.218375 -0.06280517578125 0.791975830078125 +0.2185 -0.0311279296875 0.791975830078125 0.218625 0.0 0.791975830078125 0.21875 0.027618408203125 0.791975830078125 0.218875 0.057220458984375 0.791975830078125 @@ -1779,37 +1779,37 @@ 0.22225 0.044219970703125 0.791975830078125 0.222375 0.023651123046875 0.791975830078125 0.2225 0.0057373046875 0.791975830078125 -0.222625 -0.01348876953125 0.791975830078125 -0.22275 -0.029876708984375 0.791975830078125 -0.222875 -0.046844482421875 0.791975830078125 -0.223 -0.062347412109375 0.791975830078125 -0.223125 -0.07464599609375 0.791975830078125 -0.22325 -0.08953857421875 0.791975830078125 -0.223375 -0.09906005859375 0.791975830078125 -0.2235 -0.10809326171875 0.791975830078125 -0.223625 -0.115203857421875 0.791975830078125 -0.22375 -0.1195068359375 0.791975830078125 -0.223875 -0.127349853515625 0.791975830078125 -0.224 -0.128570556640625 0.9999084491282701 -0.224125 -0.128692626953125 0.9999084491282701 -0.22425 -0.127105712890625 0.9999084491282701 -0.224375 -0.123779296875 0.9999084491282701 -0.2245 -0.1192626953125 0.9999084491282701 -0.224625 -0.113525390625 0.9999084491282701 -0.22475 -0.106658935546875 0.9999084491282701 -0.224875 -0.10369873046875 0.9999084491282701 -0.225 -0.09539794921875 0.9999084491282701 -0.225125 -0.086090087890625 0.9999084491282701 -0.22525 -0.076904296875 0.9999084491282701 -0.225375 -0.0670166015625 0.9999084491282701 -0.2255 -0.05706787109375 0.9999084491282701 -0.225625 -0.047943115234375 0.9999084491282701 -0.22575 -0.038482666015625 0.9999084491282701 -0.225875 -0.0301513671875 0.9999084491282701 -0.226 -0.0218505859375 0.9999084491282701 -0.226125 -0.01556396484375 0.9999084491282701 -0.22625 -0.009002685546875 0.9999084491282701 -0.226375 -0.00274658203125 0.9999084491282701 +0.222625 -0.013458251953125 0.791975830078125 +0.22275 -0.02984619140625 0.791975830078125 +0.222875 -0.04681396484375 0.791975830078125 +0.223 -0.06231689453125 0.791975830078125 +0.223125 -0.074615478515625 0.791975830078125 +0.22325 -0.089508056640625 0.791975830078125 +0.223375 -0.099029541015625 0.791975830078125 +0.2235 -0.108062744140625 0.791975830078125 +0.223625 -0.11517333984375 0.791975830078125 +0.22375 -0.119476318359375 0.791975830078125 +0.223875 -0.1273193359375 0.791975830078125 +0.224 -0.1285400390625 0.9999084491282701 +0.224125 -0.128662109375 0.9999084491282701 +0.22425 -0.1270751953125 0.9999084491282701 +0.224375 -0.123748779296875 0.9999084491282701 +0.2245 -0.119232177734375 0.9999084491282701 +0.224625 -0.113494873046875 0.9999084491282701 +0.22475 -0.10662841796875 0.9999084491282701 +0.224875 -0.103668212890625 0.9999084491282701 +0.225 -0.095367431640625 0.9999084491282701 +0.225125 -0.0860595703125 0.9999084491282701 +0.22525 -0.076873779296875 0.9999084491282701 +0.225375 -0.066986083984375 0.9999084491282701 +0.2255 -0.057037353515625 0.9999084491282701 +0.225625 -0.04791259765625 0.9999084491282701 +0.22575 -0.0384521484375 0.9999084491282701 +0.225875 -0.030120849609375 0.9999084491282701 +0.226 -0.021820068359375 0.9999084491282701 +0.226125 -0.015533447265625 0.9999084491282701 +0.22625 -0.00897216796875 0.9999084491282701 +0.226375 -0.002716064453125 0.9999084491282701 0.2265 0.001953125 0.9999084491282701 0.226625 0.006072998046875 0.9999084491282701 0.22675 0.009063720703125 0.9999084491282701 @@ -1821,26 +1821,26 @@ 0.2275 0.0078125 0.9999084491282701 0.227625 0.004241943359375 0.9999084491282701 0.22775 0.0 0.9999084491282701 -0.227875 -0.004791259765625 0.9999084491282701 -0.228 -0.00994873046875 0.9999084491282701 -0.228125 -0.01531982421875 0.9999084491282701 -0.22825 -0.020782470703125 0.9999084491282701 -0.228375 -0.026153564453125 0.9999084491282701 -0.2285 -0.031280517578125 0.9999084491282701 -0.228625 -0.03082275390625 0.9999084491282701 -0.22875 -0.03515625 0.9999084491282701 -0.228875 -0.038726806640625 0.9999084491282701 -0.229 -0.04168701171875 0.9999084491282701 -0.229125 -0.04351806640625 0.9999084491282701 -0.22925 -0.044281005859375 0.9999084491282701 -0.229375 -0.0443115234375 0.9999084491282701 -0.2295 -0.042694091796875 0.9999084491282701 -0.229625 -0.0404052734375 0.9999084491282701 -0.22975 -0.036224365234375 0.9999084491282701 -0.229875 -0.028778076171875 0.9999084491282701 -0.23 -0.02325439453125 0.9999084491282701 -0.230125 -0.01568603515625 0.9999084491282701 -0.23025 -0.007843017578125 0.9999084491282701 +0.227875 -0.0047607421875 0.9999084491282701 +0.228 -0.009918212890625 0.9999084491282701 +0.228125 -0.015289306640625 0.9999084491282701 +0.22825 -0.020751953125 0.9999084491282701 +0.228375 -0.026123046875 0.9999084491282701 +0.2285 -0.03125 0.9999084491282701 +0.228625 -0.030792236328125 0.9999084491282701 +0.22875 -0.035125732421875 0.9999084491282701 +0.228875 -0.0386962890625 0.9999084491282701 +0.229 -0.041656494140625 0.9999084491282701 +0.229125 -0.043487548828125 0.9999084491282701 +0.22925 -0.04425048828125 0.9999084491282701 +0.229375 -0.044281005859375 0.9999084491282701 +0.2295 -0.04266357421875 0.9999084491282701 +0.229625 -0.040374755859375 0.9999084491282701 +0.22975 -0.03619384765625 0.9999084491282701 +0.229875 -0.02874755859375 0.9999084491282701 +0.23 -0.023223876953125 0.9999084491282701 +0.230125 -0.015655517578125 0.9999084491282701 +0.23025 -0.0078125 0.9999084491282701 0.230375 0.002044677734375 0.9999084491282701 0.2305 0.01300048828125 0.9999084491282701 0.230625 0.02374267578125 0.9999084491282701 @@ -1873,37 +1873,37 @@ 0.234 0.047149658203125 0.9999084491282701 0.234125 0.024169921875 0.9999084491282701 0.23425 0.0 0.9999084491282701 -0.234375 -0.022674560546875 0.9999084491282701 -0.2345 -0.048492431640625 0.9999084491282701 -0.234625 -0.072235107421875 0.9999084491282701 -0.23475 -0.098602294921875 0.9999084491282701 -0.234875 -0.122589111328125 0.9999084491282701 -0.235 -0.14556884765625 0.9999084491282701 -0.235125 -0.1700439453125 0.9999084491282701 -0.23525 -0.19140625 0.9999084491282701 -0.235375 -0.213409423828125 0.9999084491282701 -0.2355 -0.23358154296875 0.9999084491282701 -0.235625 -0.2503662109375 0.9999084491282701 -0.23575 -0.266357421875 0.9999084491282701 -0.235875 -0.2789306640625 0.9999084491282701 -0.236 -0.28973388671875 0.9999084491282701 -0.236125 -0.29327392578125 0.9999084491282701 -0.23625 -0.29791259765625 0.9999084491282701 -0.236375 -0.2994384765625 0.9999084491282701 -0.2365 -0.298309326171875 0.9999084491282701 -0.236625 -0.29327392578125 0.9999084491282701 -0.23675 -0.28466796875 0.9999084491282701 -0.236875 -0.2742919921875 0.9999084491282701 -0.237 -0.259033203125 0.9999084491282701 -0.237125 -0.242767333984375 0.9999084491282701 -0.23725 -0.221221923828125 0.9999084491282701 -0.237375 -0.1943359375 0.9999084491282701 -0.2375 -0.1702880859375 0.9999084491282701 -0.237625 -0.140869140625 0.9999084491282701 -0.23775 -0.112548828125 0.9999084491282701 -0.237875 -0.079010009765625 0.9999084491282701 -0.238 -0.0438232421875 0.9999084491282701 -0.238125 -0.0111083984375 0.9999084491282701 +0.234375 -0.02264404296875 0.9999084491282701 +0.2345 -0.0484619140625 0.9999084491282701 +0.234625 -0.07220458984375 0.9999084491282701 +0.23475 -0.09857177734375 0.9999084491282701 +0.234875 -0.12255859375 0.9999084491282701 +0.235 -0.145538330078125 0.9999084491282701 +0.235125 -0.170013427734375 0.9999084491282701 +0.23525 -0.191375732421875 0.9999084491282701 +0.235375 -0.21337890625 0.9999084491282701 +0.2355 -0.233551025390625 0.9999084491282701 +0.235625 -0.250335693359375 0.9999084491282701 +0.23575 -0.266326904296875 0.9999084491282701 +0.235875 -0.278900146484375 0.9999084491282701 +0.236 -0.289703369140625 0.9999084491282701 +0.236125 -0.293243408203125 0.9999084491282701 +0.23625 -0.297882080078125 0.9999084491282701 +0.236375 -0.299407958984375 0.9999084491282701 +0.2365 -0.29827880859375 0.9999084491282701 +0.236625 -0.293243408203125 0.9999084491282701 +0.23675 -0.284637451171875 0.9999084491282701 +0.236875 -0.274261474609375 0.9999084491282701 +0.237 -0.259002685546875 0.9999084491282701 +0.237125 -0.24273681640625 0.9999084491282701 +0.23725 -0.22119140625 0.9999084491282701 +0.237375 -0.194305419921875 0.9999084491282701 +0.2375 -0.170257568359375 0.9999084491282701 +0.237625 -0.140838623046875 0.9999084491282701 +0.23775 -0.112518310546875 0.9999084491282701 +0.237875 -0.0789794921875 0.9999084491282701 +0.238 -0.043792724609375 0.9999084491282701 +0.238125 -0.011077880859375 0.9999084491282701 0.23825 0.026123046875 0.9999084491282701 0.238375 0.060150146484375 0.9999084491282701 0.2385 0.09796142578125 0.9999084491282701 @@ -1935,37 +1935,37 @@ 0.24175 0.1082763671875 0.9999084491282701 0.241875 0.0684814453125 0.9999084491282701 0.242 0.02301025390625 0.9999084491282701 -0.242125 -0.0185546875 0.9999084491282701 -0.24225 -0.0650634765625 0.9999084491282701 -0.242375 -0.11077880859375 0.9999084491282701 -0.2425 -0.15167236328125 0.9999084491282701 -0.242625 -0.195892333984375 0.9999084491282701 -0.24275 -0.234344482421875 0.9999084491282701 -0.242875 -0.274810791015625 0.9999084491282701 -0.243 -0.312652587890625 0.9999084491282701 -0.243125 -0.344146728515625 0.9999084491282701 -0.24325 -0.37567138671875 0.9999084491282701 -0.243375 -0.40087890625 0.9999084491282701 -0.2435 -0.424652099609375 0.9999084491282701 -0.243625 -0.44207763671875 0.9999084491282701 -0.24375 -0.455474853515625 0.9999084491282701 -0.243875 -0.4654541015625 0.9999084491282701 -0.244 -0.47027587890625 0.9999084491282701 -0.244125 -0.470489501953125 0.9999084491282701 -0.24425 -0.465423583984375 0.9999084491282701 -0.244375 -0.456573486328125 0.9999084491282701 -0.2445 -0.44171142578125 0.9999084491282701 -0.244625 -0.42413330078125 0.9999084491282701 -0.24475 -0.399871826171875 0.9999084491282701 -0.244875 -0.369903564453125 0.9999084491282701 -0.245 -0.340484619140625 0.9999084491282701 -0.245125 -0.30389404296875 0.9999084491282701 -0.24525 -0.2679443359375 0.9999084491282701 -0.245375 -0.224945068359375 0.9999084491282701 -0.2455 -0.179168701171875 0.9999084491282701 -0.245625 -0.1361083984375 0.9999084491282701 -0.24575 -0.086578369140625 0.9999084491282701 -0.245875 -0.040985107421875 0.9999084491282701 +0.242125 -0.018524169921875 0.9999084491282701 +0.24225 -0.065032958984375 0.9999084491282701 +0.242375 -0.110748291015625 0.9999084491282701 +0.2425 -0.151641845703125 0.9999084491282701 +0.242625 -0.19586181640625 0.9999084491282701 +0.24275 -0.23431396484375 0.9999084491282701 +0.242875 -0.2747802734375 0.9999084491282701 +0.243 -0.3126220703125 0.9999084491282701 +0.243125 -0.3441162109375 0.9999084491282701 +0.24325 -0.375640869140625 0.9999084491282701 +0.243375 -0.400848388671875 0.9999084491282701 +0.2435 -0.42462158203125 0.9999084491282701 +0.243625 -0.442047119140625 0.9999084491282701 +0.24375 -0.4554443359375 0.9999084491282701 +0.243875 -0.465423583984375 0.9999084491282701 +0.244 -0.470245361328125 0.9999084491282701 +0.244125 -0.470458984375 0.9999084491282701 +0.24425 -0.46539306640625 0.9999084491282701 +0.244375 -0.45654296875 0.9999084491282701 +0.2445 -0.441680908203125 0.9999084491282701 +0.244625 -0.424102783203125 0.9999084491282701 +0.24475 -0.39984130859375 0.9999084491282701 +0.244875 -0.369873046875 0.9999084491282701 +0.245 -0.3404541015625 0.9999084491282701 +0.245125 -0.303863525390625 0.9999084491282701 +0.24525 -0.267913818359375 0.9999084491282701 +0.245375 -0.22491455078125 0.9999084491282701 +0.2455 -0.17913818359375 0.9999084491282701 +0.245625 -0.136077880859375 0.9999084491282701 +0.24575 -0.0865478515625 0.9999084491282701 +0.245875 -0.04095458984375 0.9999084491282701 0.246 0.01025390625 0.9999084491282701 0.246125 0.0615234375 0.9999084491282701 0.24625 0.1072998046875 0.9999084491282701 @@ -1998,37 +1998,37 @@ 0.249625 0.103546142578125 0.9999084491282701 0.24975 0.052001953125 0.9999084491282701 0.249875 0.0 0.9999084491282701 -0.25 -0.046783447265625 0.9999084491282701 -0.250125 -0.09814453125 0.9999084491282701 -0.25025 -0.143341064453125 0.9999084491282701 -0.250375 -0.191925048828125 0.9999084491282701 -0.2505 -0.238250732421875 0.9999084491282701 -0.250625 -0.27752685546875 0.9999084491282701 -0.25075 -0.31817626953125 0.9999084491282701 -0.250875 -0.3515625 0.9999084491282701 -0.251 -0.384857177734375 0.9999084491282701 -0.251125 -0.414642333984375 0.9999084491282701 -0.25125 -0.4366455078125 0.9999084491282701 -0.251375 -0.456512451171875 0.9999084491282701 -0.2515 -0.46990966796875 0.9999084491282701 -0.251625 -0.47991943359375 0.9999084491282701 -0.25175 -0.48455810546875 0.9999084491282701 -0.251875 -0.483978271484375 0.9999084491282701 -0.252 -0.478424072265625 0.9999084491282701 -0.252125 -0.468780517578125 0.9999084491282701 -0.25225 -0.453369140625 0.9999084491282701 -0.252375 -0.43438720703125 0.9999084491282701 -0.2525 -0.411956787109375 0.9999084491282701 -0.252625 -0.38299560546875 0.9999084491282701 -0.25275 -0.35333251953125 0.9999084491282701 -0.252875 -0.317047119140625 0.9999084491282701 -0.253 -0.277496337890625 0.9999084491282701 -0.253125 -0.23944091796875 0.9999084491282701 -0.25325 -0.195068359375 0.9999084491282701 -0.253375 -0.153472900390625 0.9999084491282701 -0.2535 -0.10614013671875 0.9999084491282701 -0.253625 -0.058258056640625 0.9999084491282701 -0.2537500000000001 -0.0145263671875 0.9999084491282701 +0.25 -0.0467529296875 0.9999084491282701 +0.250125 -0.098114013671875 0.9999084491282701 +0.25025 -0.143310546875 0.9999084491282701 +0.250375 -0.19189453125 0.9999084491282701 +0.2505 -0.23822021484375 0.9999084491282701 +0.250625 -0.277496337890625 0.9999084491282701 +0.25075 -0.318145751953125 0.9999084491282701 +0.250875 -0.351531982421875 0.9999084491282701 +0.251 -0.38482666015625 0.9999084491282701 +0.251125 -0.41461181640625 0.9999084491282701 +0.25125 -0.436614990234375 0.9999084491282701 +0.251375 -0.45648193359375 0.9999084491282701 +0.2515 -0.469879150390625 0.9999084491282701 +0.251625 -0.479888916015625 0.9999084491282701 +0.25175 -0.484527587890625 0.9999084491282701 +0.251875 -0.48394775390625 0.9999084491282701 +0.252 -0.4783935546875 0.9999084491282701 +0.252125 -0.46875 0.9999084491282701 +0.25225 -0.453338623046875 0.9999084491282701 +0.252375 -0.434356689453125 0.9999084491282701 +0.2525 -0.41192626953125 0.9999084491282701 +0.252625 -0.382965087890625 0.9999084491282701 +0.25275 -0.353302001953125 0.9999084491282701 +0.252875 -0.3170166015625 0.9999084491282701 +0.253 -0.2774658203125 0.9999084491282701 +0.253125 -0.239410400390625 0.9999084491282701 +0.25325 -0.195037841796875 0.9999084491282701 +0.253375 -0.1534423828125 0.9999084491282701 +0.2535 -0.106109619140625 0.9999084491282701 +0.253625 -0.0582275390625 0.9999084491282701 +0.2537500000000001 -0.014495849609375 0.9999084491282701 0.253875 0.033721923828125 0.9999084491282701 0.254 0.07647705078125 0.9999084491282701 0.254125 0.122772216796875 0.9999084491282701 diff --git a/tests/circuitpython/synthesizer.py.exp b/tests/circuitpython/synthesizer.py.exp index fb2e8c07bd658..98f45f8bf85c4 100644 --- a/tests/circuitpython/synthesizer.py.exp +++ b/tests/circuitpython/synthesizer.py.exp @@ -1,30 +1,30 @@ () [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] (80,) -[-16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384, 16383, 16383, 16383, 16383, 16383, -16384, -16384, -16384, -16384, -16384] +[-16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383, 16383, 16383, 16383, 16383, 16383, -16383, -16383, -16383, -16383, -16383] (80, 91) -[-1, -1, 28045, 28045, -1, -28046, -28046, -1, 28045, 28045, -1, -1, 28045, -1, -1, -28046, -28046, -1, 28045, 28045, -1, -1, 28045, -1] +[0, 0, 28045, 28045, 0, -28046, -28046, 0, 28045, 28045, 0, 0, 28045, 0, 0, -28046, -28046, 0, 28045, 28045, 0, 0, 28045, 0] (91,) -[-28046, -1, -1, 28045, -1, -1, 28045, 28045, -1, -28046, -28046, -1, 28045, 28045, -1, -1, 28045, -1, -1, -28046, -28046, -28046, 28045, 28045] -(-5243, 5242) +[-28046, 0, 0, 28045, 0, 0, 28045, 28045, 0, -28046, -28046, 0, 28045, 28045, 0, 0, 28045, 0, 0, -28046, -28046, -28046, 28045, 28045] +(-5242, 5242) (-10485, 10484) -(-15728, 15727) -(-16384, 16383) -(-14287, 14286) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-13107, 13106) -(-11010, 11009) -(-8913, 8912) -(-6816, 6815) -(-4719, 4718) -(-2622, 2621) -(-525, 524) +(-15727, 15727) +(-16383, 16383) +(-14286, 14286) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-13106, 13106) +(-11009, 11009) +(-8912, 8912) +(-6815, 6815) +(-4718, 4718) +(-2621, 2621) +(-524, 524) (0, 0) (0, 0) (0, 0) diff --git a/tests/circuitpython/synthesizer_note.py.exp b/tests/circuitpython/synthesizer_note.py.exp index 43d07e5e7da9c..422fb7b9affad 100644 --- a/tests/circuitpython/synthesizer_note.py.exp +++ b/tests/circuitpython/synthesizer_note.py.exp @@ -1,13 +1,13 @@ () [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] -(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0, waveform_loop_end=16384, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0, ring_waveform_loop_end=16384),) +(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0.0, waveform_loop_end=16384.0, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0.0, ring_waveform_loop_end=16384.0),) [-16383, -16383, -16383, -16383, 16382, 16382, 16382, 16382, 16382, -16383, -16383, -16383, -16383, -16383, 16382, 16382, 16382, 16382, 16382, -16383, -16383, -16383, -16383, -16383] -(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0, waveform_loop_end=16384, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0, ring_waveform_loop_end=16384), Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0, waveform_loop_end=16384, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0, ring_waveform_loop_end=16384)) +(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0.0, waveform_loop_end=16384.0, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0.0, ring_waveform_loop_end=16384.0), Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0.0, waveform_loop_end=16384.0, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0.0, ring_waveform_loop_end=16384.0)) [-1, -1, -1, -1, -1, -1, -1, -1, 28045, -1, -1, -1, -1, -28046, -1, -1, -1, -1, 28045, -1, -1, -1, -1, -28046] -(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0, waveform_loop_end=16384, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0, ring_waveform_loop_end=16384),) +(Note(frequency=830.6076004423605, panning=0.0, amplitude=1.0, bend=0.0, waveform=None, waveform_loop_start=0.0, waveform_loop_end=16384.0, envelope=None, filter=None, ring_frequency=0.0, ring_bend=0.0, ring_waveform=None, ring_waveform_loop_start=0.0, ring_waveform_loop_end=16384.0),) [-1, -1, -1, 28045, -1, -1, -1, -1, -1, -1, -1, -1, 28045, -1, -1, -1, -1, -28046, -1, -1, -1, -1, 28045, -1] (-5242, 5241) -(-10485, 10484) +(-10484, 10484) (-15727, 15726) (-16383, 16382) (-14286, 14285) diff --git a/tests/circuitpython/synthio_biquad.py b/tests/circuitpython/synthio_biquad.py index 92b8e64a054b8..9fb67fb81e385 100644 --- a/tests/circuitpython/synthio_biquad.py +++ b/tests/circuitpython/synthio_biquad.py @@ -1,12 +1,17 @@ -from synthio import Synthesizer +from synthnotehelper import * +from synthio import Biquad, FilterMode +import random -s = Synthesizer(sample_rate=48000) +random.seed(41) +white_noise = array.array("h", [random.randint(-32000, 32000) for i in range(600)]) -def print_filter(x): - print(" ".join(f"{v:.4g}" for v in x)) - -print_filter(s.low_pass_filter(330)) -print_filter(s.high_pass_filter(330)) -print_filter(s.band_pass_filter(330)) +@synth_test_rms +def gen(synth): + l = LFO(sweep, offset=1440, scale=2880, rate=0.025, once=True) + yield [l] + b = Biquad(FilterMode.LOW_PASS, l, Q=0.5**0.5) + n = Note(100, filter=b, waveform=white_noise) + synth.press(n) + yield 20 diff --git a/tests/circuitpython/synthio_biquad.py.exp b/tests/circuitpython/synthio_biquad.py.exp index 2b9ca364c6ea3..36805bd3af43a 100644 --- a/tests/circuitpython/synthio_biquad.py.exp +++ b/tests/circuitpython/synthio_biquad.py.exp @@ -1,3 +1,640 @@ --1.939 0.9407 0.0004526 0.0009052 0.0004526 --1.939 0.9407 0.9699 -1.94 0.9699 --1.939 0.9407 0.02963 0 -0.02963 +0.0 0.4292414482077013 -1435.412246704102 +0.03125 0.4301957475984245 -1430.912384033203 +0.0625 0.443415096786705 -1426.412521362305 +0.09375 0.4138944101201059 -1421.912658691406 +0.125 0.4405400571695613 -1417.412796020508 +0.15625 0.4016394462659425 -1412.912933349609 +0.1875 0.4327624316124036 -1408.413070678711 +0.21875 0.4287368973626116 -1403.913208007813 +0.25 0.4345957058398272 -1399.413345336914 +0.28125 0.4309447646333486 -1394.913482666016 +0.3125 0.4354826789649687 -1390.413619995117 +0.34375 0.4342858719298666 -1385.913757324219 +0.375 0.4377970872905904 -1381.41389465332 +0.40625 0.4370108811124707 -1376.914031982422 +0.4375 0.4295542636055871 -1372.414169311523 +0.46875 0.4329853290304969 -1367.914306640625 +0.5 0.4455501064219861 -1363.414443969727 +0.53125 0.4415799690008891 -1358.914581298828 +0.5625 0.430107469300593 -1354.41471862793 +0.59375 0.4115680204350006 -1349.914855957031 +0.625 0.439561328340486 -1345.414993286133 +0.65625 0.4253925109033371 -1340.915130615234 +0.6875 0.4185943916302574 -1336.415267944336 +0.71875 0.4258237185752813 -1331.915405273438 +0.75 0.4112320384281056 -1327.415542602539 +0.78125 0.4421489522731164 -1322.915679931641 +0.8125 0.4285193689964977 -1318.415817260742 +0.84375 0.4244358011163597 -1313.915954589844 +0.875 0.4445975208808163 -1309.416091918945 +0.90625 0.4471065627393449 -1304.916229248047 +0.9375 0.4568033022778143 -1300.416366577148 +0.96875 0.4259499858352917 -1295.91650390625 +1.0 0.4536505096800783 -1291.416641235352 +1.03125 0.4273680768687785 -1286.916778564453 +1.0625 0.4693132711352654 -1282.416915893555 +1.09375 0.4160924678698707 -1277.917053222656 +1.125 0.4515606024849182 -1273.417190551758 +1.15625 0.4364089459564787 -1268.917327880859 +1.1875 0.4348510600055276 -1264.41746520996 +1.21875 0.451432630170392 -1259.917602539063 +1.25 0.4416638694710183 -1255.417739868164 +1.28125 0.451611407724486 -1250.917877197266 +1.3125 0.4625336702141225 -1246.418014526367 +1.34375 0.4648639812435186 -1241.918151855469 +1.375 0.4460508471392539 -1237.41828918457 +1.40625 0.4374704584317717 -1232.918426513672 +1.4375 0.4302419180820578 -1228.418563842773 +1.46875 0.4136589658399674 -1223.918701171875 +1.5 0.4402948947417665 -1219.418838500977 +1.53125 0.4354149960453673 -1214.918975830078 +1.5625 0.4207519521348172 -1210.41911315918 +1.59375 0.4517893119386277 -1205.919250488281 +1.625 0.4377037203023695 -1201.419387817383 +1.65625 0.4381095879613992 -1196.919525146485 +1.6875 0.4335728977482941 -1192.419662475586 +1.71875 0.4251033969710498 -1187.919799804688 +1.75 0.4214479982981709 -1183.41993713379 +1.78125 0.433242942953255 -1178.920074462891 +1.8125 0.398152072548805 -1174.420211791993 +1.84375 0.4372636185762459 -1169.920349121094 +1.875 0.4291250895649827 -1165.420486450196 +1.90625 0.4138667249705813 -1160.920623779297 +1.9375 0.4269810851192543 -1156.420761108398 +1.96875 0.4237267320491086 -1151.9208984375 +2.0 0.4258018952548287 -1147.421035766602 +2.03125 0.4036759087596965 -1142.921173095704 +2.0625 0.4071953834764041 -1138.421310424805 +2.09375 0.4069726709639113 -1133.921447753906 +2.125 0.4253069738402361 -1129.421585083008 +2.15625 0.4278676768058594 -1124.92172241211 +2.1875 0.4273060577495892 -1120.421859741211 +2.21875 0.4148458356935921 -1115.921997070313 +2.25 0.4035167256876282 -1111.422134399415 +2.28125 0.4130066098571691 -1106.922271728516 +2.3125 0.4025638392426288 -1102.422409057618 +2.34375 0.392949305348438 -1097.922546386719 +2.375 0.4055346571156643 -1093.422683715821 +2.40625 0.3841531504399494 -1088.922821044922 +2.4375 0.3966926384714262 -1084.422958374024 +2.46875 0.4102200419660115 -1079.923095703125 +2.5 0.4030059077414907 -1075.423233032227 +2.53125 0.3876811705709198 -1070.923370361329 +2.5625 0.3900713483040226 -1066.42350769043 +2.59375 0.3957986944065445 -1061.923645019532 +2.625 0.3799874774938255 -1057.423782348633 +2.65625 0.399969004242642 -1052.923919677735 +2.6875 0.4030233464415128 -1048.424057006837 +2.71875 0.3893539782322431 -1043.924194335938 +2.75 0.3909872816448433 -1039.42433166504 +2.78125 0.3904856531720035 -1034.924468994141 +2.8125 0.3964487403729973 -1030.424606323243 +2.84375 0.367141125232508 -1025.924743652345 +2.875 0.3755638797772791 -1021.424880981446 +2.90625 0.3998548247989561 -1016.925018310548 +2.9375 0.4025267173160954 -1012.425155639649 +2.96875 0.3773823339352469 -1007.925292968751 +3.0 0.4042089102378084 -1003.425430297852 +3.03125 0.3949071386325466 -998.9255676269536 +3.0625 0.4064082535642184 -994.4257049560556 +3.09375 0.4010787430493667 -989.9258422851567 +3.125 0.4017930109841857 -985.4259796142587 +3.15625 0.3892376075083491 -980.9261169433603 +3.1875 0.3971434904652945 -976.4262542724618 +3.21875 0.3892411665720613 -971.9263916015634 +3.25 0.3839529716571926 -967.4265289306654 +3.28125 0.3824722893209285 -962.9266662597665 +3.3125 0.3952780375942706 -958.4268035888681 +3.34375 0.4179519059519968 -953.9269409179697 +3.375 0.3898154262936899 -949.4270782470712 +3.40625 0.3976718277347342 -944.9272155761732 +3.4375 0.3850638479108297 -940.4273529052743 +3.46875 0.3958265371547819 -935.9274902343764 +3.5 0.4004332350927074 -931.4276275634775 +3.53125 0.3888213325698884 -926.927764892579 +3.5625 0.371131695964836 -922.4279022216811 +3.59375 0.4188939439713424 -917.9280395507822 +3.625 0.4081025456433866 -913.4281768798842 +3.65625 0.3733601855622199 -908.9283142089857 +3.6875 0.3808196119266348 -904.4284515380868 +3.71875 0.392660092123199 -899.9285888671889 +3.75 0.3808027498263037 -895.4287261962904 +3.78125 0.4068448640657261 -890.928863525392 +3.8125 0.3980447756551903 -886.4290008544936 +3.84375 0.4036631225200267 -881.9291381835951 +3.875 0.3876801629403572 -877.4292755126967 +3.90625 0.3984128299621498 -872.9294128417982 +3.9375 0.411005762062684 -868.4295501708998 +3.96875 0.3823055352727712 -863.9296875000014 +4.0 0.4033390445203946 -859.4298248291029 +4.03125 0.3869349079589102 -854.9299621582045 +4.0625 0.406561858202515 -850.4300994873065 +4.09375 0.4198370291448769 -845.9302368164076 +4.125 0.4089914984288221 -841.4303741455092 +4.15625 0.3857109649839493 -836.9305114746107 +4.1875 0.4142716745626002 -832.4306488037123 +4.21875 0.391505346562964 -827.9307861328143 +4.25 0.4030787954726662 -823.4309234619159 +4.28125 0.3766501680871163 -818.931060791017 +4.3125 0.3803567013661997 -814.4311981201186 +4.34375 0.417475410602975 -809.9313354492201 +4.375 0.4004163242806387 -805.4314727783221 +4.40625 0.3685731937453348 -800.9316101074237 +4.4375 0.3979205436317936 -796.4317474365248 +4.46875 0.4078888087177493 -791.9318847656264 +4.5 0.3921430399033289 -787.4320220947279 +4.53125 0.4119813312521327 -782.9321594238299 +4.5625 0.3935698957084185 -778.4322967529315 +4.59375 0.3727464496698831 -773.9324340820326 +4.625 0.3955035731153163 -769.4325714111342 +4.65625 0.3942862357046499 -764.9327087402362 +4.6875 0.3843275918191916 -760.4328460693378 +4.71875 0.3851421952649138 -755.9329833984393 +4.75 0.3902906061399617 -751.4331207275409 +4.78125 0.3844671126461341 -746.933258056642 +4.8125 0.3791288781111852 -742.433395385744 +4.84375 0.3837003871047081 -737.9335327148456 +4.875 0.3870946995015528 -733.4336700439471 +4.90625 0.39553933731762 -728.9338073730487 +4.9375 0.3744296300001198 -724.4339447021498 +4.96875 0.3667587510805197 -719.9340820312518 +5.0 0.3916190946800228 -715.4342193603534 +5.03125 0.3814689280310855 -710.9343566894549 +5.0625 0.3967725697688225 -706.4344940185565 +5.09375 0.3937405019170813 -701.9346313476576 +5.125 0.3777270428748825 -697.4347686767592 +5.15625 0.3870083970450706 -692.9349060058612 +5.1875 0.3883337842102841 -688.4350433349628 +5.21875 0.3763887168339391 -683.9351806640639 +5.25 0.3774724312165993 -679.4353179931654 +5.28125 0.3893272640042596 -674.935455322267 +5.3125 0.3953789887892353 -670.4355926513686 +5.34375 0.3801785044601818 -665.9357299804701 +5.375 0.3954135587096122 -661.4358673095712 +5.40625 0.3874319561492619 -656.9360046386728 +5.4375 0.3928975156161072 -652.4361419677748 +5.46875 0.39136415848977 -647.9362792968759 +5.5 0.3926008598161878 -643.4364166259775 +5.53125 0.3886504623120136 -638.9365539550786 +5.5625 0.3831538016240389 -634.4366912841806 +5.59375 0.383033101461492 -629.9368286132817 +5.625 0.382207202634286 -625.4369659423833 +5.65625 0.3913172446646332 -620.9371032714853 +5.6875 0.3847724862238807 -616.4372406005864 +5.71875 0.3939629239442654 -611.937377929688 +5.75 0.383305155845298 -607.4375152587891 +5.78125 0.3916892245619181 -602.9376525878911 +5.8125 0.3946926061973548 -598.4377899169926 +5.84375 0.3892107176066872 -593.9379272460935 +5.875 0.3814936484084122 -589.4380645751953 +5.90625 0.3943244857223315 -584.9382019042969 +5.9375 0.3857112348864788 -580.4383392333984 +5.96875 0.3942048347924611 -575.9384765625002 +6.0 0.3911875153619875 -571.4386138916011 +6.03125 0.3915132752539617 -566.9387512207027 +6.0625 0.3909499616216763 -562.4388885498047 +6.09375 0.3827724950107045 -557.939025878906 +6.125 0.3875329733845965 -553.4391632080074 +6.15625 0.4000548290909773 -548.9393005371087 +6.1875 0.3967315317827893 -544.4394378662105 +6.21875 0.3951006062355771 -539.9395751953118 +6.25 0.3969628666712315 -535.4397125244132 +6.28125 0.400093117621525 -530.9398498535152 +6.3125 0.4020018744063912 -526.4399871826165 +6.34375 0.3987096233393185 -521.9401245117178 +6.375 0.3959471927998633 -517.4402618408189 +6.40625 0.4069494471924576 -512.940399169921 +6.4375 0.402011726755101 -508.4405364990225 +6.46875 0.4008641623960937 -503.9406738281236 +6.5 0.4115701831441808 -499.4408111572252 +6.53125 0.4090335063892219 -494.9409484863268 +6.5625 0.4116842419628069 -490.4410858154286 +6.59375 0.4075960414244354 -485.9412231445301 +6.625 0.4081717451924282 -481.441360473631 +6.65625 0.4114323463061593 -476.9414978027328 +6.6875 0.4104565432056045 -472.4416351318346 +6.71875 0.4086514255916335 -467.9417724609359 +6.75 0.4115800192393992 -463.4419097900372 +6.78125 0.4093340265005087 -458.9420471191386 +6.8125 0.409278958418651 -454.4421844482406 +6.84375 0.4109678400408193 -449.9423217773419 +6.875 0.4084525067207762 -445.442459106443 +6.90625 0.4082485968008172 -440.9425964355451 +6.9375 0.4105211605776111 -436.4427337646464 +6.96875 0.40786863169688 -431.9428710937477 +7.0 0.4077589637368115 -427.4430084228491 +7.03125 0.4099997876338798 -422.9431457519509 +7.0625 0.4076714572193215 -418.4432830810526 +7.09375 0.407600712291866 -413.9434204101535 +7.125 0.4099004227397708 -409.4435577392551 +7.15625 0.4076214554633187 -404.9436950683569 +7.1875 0.4076326145533956 -400.4438323974584 +7.21875 0.410172474134385 -395.94396972656 +7.25 0.4078638574512831 -391.4441070556611 +7.28125 0.4080910709976476 -386.9442443847627 +7.3125 0.4104988189153643 -382.4443817138647 +7.34375 0.4084689949124797 -377.944519042966 +7.375 0.4087428208523811 -373.4446563720671 +7.40625 0.4113910072710569 -368.9447937011685 +7.4375 0.4094289014902302 -364.4449310302705 +7.46875 0.4095101423242618 -359.9450683593718 +7.5 0.4120630250505489 -355.4452056884732 +7.53125 0.4101384419541137 -350.9453430175749 +7.5625 0.4106321409247253 -346.4454803466763 +7.59375 0.4030961427991869 -341.9456176757776 +7.625 0.3903383621279249 -337.4457550048789 +7.65625 0.3937734927031041 -332.945892333981 +7.6875 0.3993492619940964 -328.4460296630825 +7.71875 0.385989496319416 -323.9461669921836 +7.75 0.3856861598937419 -319.4463043212852 +7.78125 0.3837838633055601 -314.9464416503868 +7.8125 0.3769300123298409 -310.4465789794883 +7.84375 0.3802207026470601 -305.9467163085901 +7.875 0.3828481259638064 -301.446853637691 +7.90625 0.379447179037863 -296.9469909667926 +7.9375 0.3802018507541309 -292.4471282958946 +7.96875 0.3769802547339046 -287.9472656249959 +8.0 0.3803390667074351 -283.4474029540972 +8.03125 0.3765104961974802 -278.9475402831986 +8.0625 0.3776210843927699 -274.4476776123004 +8.09375 0.3836716114153597 -269.9478149414017 +8.125 0.378769734236955 -265.447952270503 +8.15625 0.3775582564371868 -260.9480895996051 +8.1875 0.3773662771903655 -256.4482269287064 +8.21875 0.3775344932552112 -251.9483642578077 +8.25 0.3757562127863197 -247.4485015869091 +8.28125 0.376097649450651 -242.9486389160109 +8.3125 0.3758356013089041 -238.4487762451124 +8.34375 0.3773684844987389 -233.9489135742135 +8.375 0.3760552163029725 -229.4490509033151 +8.40625 0.376033096148381 -224.9491882324169 +8.4375 0.372452661362901 -220.4493255615184 +8.46875 0.3745717686363883 -215.94946289062 +8.5 0.3743486371073519 -211.4496002197211 +8.53125 0.3721674311277588 -206.9497375488227 +8.5625 0.3772128703769017 -202.4498748779247 +8.59375 0.3725790043542761 -197.9500122070258 +8.625 0.3758827155435686 -193.4501495361271 +8.65625 0.3743209259913767 -188.9502868652285 +8.6875 0.3706332323722716 -184.4504241943305 +8.71875 0.3755192620341588 -179.9505615234318 +8.75 0.3699010282695 -175.4506988525332 +8.78125 0.3751761002140255 -170.9508361816349 +8.8125 0.3673193831680472 -166.4509735107363 +8.84375 0.3703267596781248 -161.9511108398376 +8.875 0.3689641620418253 -157.4512481689389 +8.90625 0.3736852079969759 -152.951385498041 +8.9375 0.3672869869059834 -148.4515228271425 +8.96875 0.3740974122030886 -143.9516601562434 +9.0 0.3688860256628344 -139.4517974853452 +9.03125 0.3670327501993761 -134.9519348144468 +9.0625 0.3645313570401571 -130.4520721435483 +9.09375 0.3713930936780955 -125.9522094726499 +9.125 0.362916495103013 -121.452346801751 +9.15625 0.3690865039572091 -116.9524841308526 +9.1875 0.3615905851475338 -112.4526214599546 +9.21875 0.3681245712573865 -107.9527587890559 +9.25 0.3686344395996596 -103.4528961181572 +9.28125 0.3631918162418778 -98.95303344725835 +9.3125 0.365473890830738 -94.45317077636037 +9.34375 0.3665819288655671 -89.9533081054617 +9.375 0.3647457959760047 -85.45344543456304 +9.40625 0.3566742883671927 -80.95358276366505 +9.4375 0.3700218291726018 -76.45372009276616 +9.46875 0.3601955685082416 -71.9538574218675 +9.5 0.3677156049795945 -67.45399475096883 +9.53125 0.356669428135651 -62.95413208007085 +9.5625 0.365584468725112 -58.45426940917241 +9.59375 0.3620575963727736 -53.95440673827352 +9.625 0.3660536419997879 -49.45454406737508 +9.65625 0.3615481587068067 -44.95468139647664 +9.6875 0.3586519996027659 -40.45481872557843 +9.71875 0.3629708505110769 -35.95495605468 +9.75 0.3542547978069129 -31.45509338378088 +9.78125 0.3645631627542719 -26.95523071288267 +9.8125 0.3618473039061899 -22.45536804198446 +9.84375 0.3354950625427833 -17.95550537108579 +9.875 0.361595305808895 -13.45564270018713 +9.90625 0.3870185128971818 -8.955780029288462 +9.9375 0.342119700127982 -4.455917358390479 +9.96875 0.2711789125448073 0.04394531250841283 +10.0 0.406221045358242 4.54380798340685 +10.03125 0.1225360785801001 9.043670654305288 +10.0625 0.03174341737930414 13.54353332520373 +10.09375 0.02515935958829191 18.04339599610239 +10.125 0.009574457743938767 22.54325866700106 +10.15625 0.01745846809196387 27.04312133789927 +10.1875 0.02601177395465528 31.54298400879748 +10.21875 0.01415917685015583 36.04284667969637 +10.25 0.02245157778259128 40.54270935059503 +10.28125 0.04115089615388722 45.04257202149324 +10.3125 0.03874860340661093 49.54243469239145 +10.34375 0.02196631571892786 54.04229736329034 +10.375 0.02196023427652383 58.54216003418901 +10.40625 0.0352765758538488 63.04202270508745 +10.4375 0.03353321733296127 67.54188537598566 +10.46875 0.01609885633939395 72.04174804688409 +10.5 0.03742903210189786 76.54161071778299 +10.53125 0.05782232775915963 81.04147338868142 +10.5625 0.05286637288968352 85.54133605957986 +10.59375 0.02993413459140702 90.0411987304783 +10.625 0.03332199932412696 94.54106140137696 +10.65625 0.04622037701881601 99.04092407227517 +10.6875 0.04868105644814895 103.5407867431738 +10.71875 0.0231836361330315 108.0406494140725 +10.75 0.0501623458922407 112.5405120849709 +10.78125 0.06726940399118371 117.0403747558692 +10.8125 0.06636219231850592 121.5402374267676 +10.84375 0.03537720946864608 126.0401000976665 +10.875 0.04340484157782403 130.5399627685651 +10.90625 0.05485402611003761 135.0398254394634 +10.9375 0.06113000098851544 139.5396881103616 +10.96875 0.03212352569671814 144.0395507812602 +11.0 0.05856805737285709 148.5394134521591 +11.03125 0.0725659329387529 153.0392761230576 +11.0625 0.07546797747627238 157.5391387939558 +11.09375 0.04136378348487984 162.0390014648542 +11.125 0.05072249289502579 166.5388641357529 +11.15625 0.06118250358285766 171.0387268066515 +11.1875 0.0695532710528029 175.5385894775497 +11.21875 0.04135687164376359 180.0384521484484 +11.25 0.06422446600489478 184.5383148193469 +11.28125 0.07619244002924606 189.0381774902453 +11.3125 0.081678977474969 193.5380401611437 +11.34375 0.04818716548974017 198.0379028320426 +11.375 0.05578818150521037 202.5377655029411 +11.40625 0.06688108361255097 207.0376281738393 +11.4375 0.07569228149357033 211.5374908447377 +11.46875 0.05089722962555985 216.0373535156364 +11.5 0.06911272709822142 220.5372161865353 +11.53125 0.07893477798107136 225.0370788574335 +11.5625 0.08640667841789856 229.5369415283317 +11.59375 0.05577030990461401 234.0368041992303 +11.625 0.06029106376627119 238.5366668701292 +11.65625 0.07219505660275832 243.0365295410274 +11.6875 0.08061693794150473 247.5363922119257 +11.71875 0.06017290280756791 252.0362548828243 +11.75 0.07395877654929304 256.536117553723 +11.78125 0.08157274132241021 261.0359802246214 +11.8125 0.09019650384242192 265.5358428955199 +11.84375 0.06347961235055553 270.0357055664183 +11.875 0.06435324878239179 274.535568237317 +11.90625 0.07722535662613761 279.0354309082154 +11.9375 0.08458446293174319 283.5352935791138 +11.96875 0.06861468517765807 288.0351562500125 +12.0 0.07904605919763272 292.5350189209112 +12.03125 0.08422023125176194 297.0348815918094 +12.0625 0.09351761888096444 301.5347442627076 +12.09375 0.07075114359961844 306.0346069336065 +12.125 0.06814997827985858 310.5344696045051 +12.15625 0.08190920638078293 315.0343322754034 +12.1875 0.08804602366444849 319.5341949463016 +12.21875 0.07604590990738279 324.0340576172002 +12.25 0.08425930564405258 328.5339202880991 +12.28125 0.08701614143436316 333.0337829589976 +12.3125 0.09661797601881215 337.5336456298958 +12.34375 0.07745903467176028 342.0335083007942 +12.375 0.07166234233169564 346.5333709716929 +12.40625 0.08627936659419088 351.0332336425915 +12.4375 0.09123440443547194 355.53309631349 +12.46875 0.08251618031640428 360.0329589843884 +12.5 0.08939742073464346 364.5328216552869 +12.53125 0.08993018035099734 369.0326843261853 +12.5625 0.09946877941152422 373.532546997084 +12.59375 0.08355935392802863 378.0324096679826 +12.625 0.07499857786276619 382.5322723388811 +12.65625 0.09031205637078164 387.0321350097793 +12.6875 0.09418302582863182 391.5319976806777 +12.71875 0.08812572733899099 396.0318603515766 +12.75 0.09417803172836386 400.5317230224753 +12.78125 0.09295798430981622 405.0315856933735 +12.8125 0.1020913836496992 409.5314483642717 +12.84375 0.08922251972285368 414.0313110351703 +12.875 0.0781182008630799 418.5311737060692 +12.90625 0.09405343485309603 423.0310363769676 +12.9375 0.09704892139554945 427.5308990478658 +12.96875 0.09322388880971026 432.0307617187643 +13.0 0.09868619890806334 436.530624389663 +13.03125 0.09605992100961673 441.0304870605615 +13.0625 0.1046930899935769 445.53034973146 +13.09375 0.09456408660702788 450.0302124023584 +13.125 0.08110867864214342 454.530075073257 +13.15625 0.0975426225549988 459.0299377441554 +13.1875 0.09995899929625697 463.5298004150538 +13.21875 0.09788404878149466 468.0296630859526 +13.25 0.1028301855526857 472.5295257568512 +13.28125 0.09925688270323969 477.0293884277494 +13.3125 0.1071644181891975 481.5292510986477 +13.34375 0.09956183461201409 486.0291137695466 +13.375 0.08398404998945123 490.5289764404453 +13.40625 0.1009046731659027 495.0288391113435 +13.4375 0.1028961861915068 499.5287017822417 +13.46875 0.1023205405202272 504.0285644531403 +13.5 0.1066522016295972 508.5284271240392 +13.53125 0.1023131818494744 513.0282897949376 +13.5625 0.1096446073686916 517.5281524658358 +13.59375 0.1042795141110983 522.0280151367343 +13.625 0.08678495956048039 526.5278778076331 +13.65625 0.1040609464200182 531.0277404785315 +13.6875 0.1058129356918997 535.52760314943 +13.71875 0.1065241690470741 540.0274658203285 +13.75 0.1101692764682358 544.527328491227 +13.78125 0.1053728794049568 549.0271911621254 +13.8125 0.1120205616464041 553.527053833024 +13.84375 0.1087432537847466 558.0269165039226 +13.875 0.08954349595632319 562.5267791748212 +13.90625 0.1070489596553324 567.0266418457194 +13.9375 0.108737268129603 571.5265045166177 +13.96875 0.1105828075727535 576.0263671875166 +14.0 0.1133862716213715 580.5262298584153 +14.03125 0.1082443737836045 585.0260925293135 +14.0625 0.1143955628482857 589.5259552002117 +14.09375 0.1129309169134834 594.0258178711105 +14.125 0.09230387726595179 598.5256805420092 +14.15625 0.1099178483011606 603.0255432129077 +14.1875 0.1116656194509316 607.5254058838059 +14.21875 0.1145220685293726 612.0252685547043 +14.25 0.1163868784387258 616.5251312256031 +14.28125 0.1109951431026079 621.0249938965017 +14.3125 0.1167800812205802 625.5248565674 +14.34375 0.1168299870930108 630.0247192382985 +14.375 0.09508428012321064 634.5245819091971 +14.40625 0.1126210646498637 639.0244445800954 +14.4375 0.1145807105754756 643.524307250994 +14.46875 0.1183057967740651 648.0241699218926 +14.5 0.1192327743590527 652.5240325927912 +14.53125 0.113623220453224 657.0238952636894 +14.5625 0.1191589397759562 661.5237579345878 +14.59375 0.1204955963604885 666.0236206054866 +14.625 0.09785472222088311 670.5234832763853 +14.65625 0.1152061978790822 675.0233459472836 +14.6875 0.117487024010307 679.5232086181818 +14.71875 0.1219502913409791 684.0230712890805 +14.75 0.1219010915259758 688.5229339599792 +14.78125 0.116143028092938 693.0227966308777 +14.8125 0.1215908489467233 697.5226593017759 +14.84375 0.1239291718953261 702.0225219726744 +14.875 0.1005908519420451 706.5223846435731 +14.90625 0.1176327957295311 711.0222473144717 +14.9375 0.1204112286611297 715.52210998537 +14.96875 0.1254704428283171 720.0219726562685 +15.0 0.1244291183492105 724.5218353271671 +15.03125 0.1185450466115126 729.0216979980654 +15.0625 0.1240204967151066 733.521560668964 +15.09375 0.1271621521553429 738.0214233398626 +15.125 0.103344801653342 742.5212860107612 +15.15625 0.119976043761817 747.0211486816594 +15.1875 0.1232841884025795 751.5210113525578 +15.21875 0.1288287545809712 756.0208740234566 +15.25 0.1268517152789468 760.5207366943554 +15.28125 0.1208359538717516 765.0205993652536 +15.3125 0.1264688007806249 769.5204620361518 +15.34375 0.1301826291181721 774.0203247070505 +15.375 0.1060773553858188 778.5201873779494 +15.40625 0.1222327917123172 783.0200500488477 +15.4375 0.1261778571473278 787.5199127197459 +15.46875 0.132099606594904 792.0197753906444 +15.5 0.1292017331168378 796.5196380615431 +15.53125 0.1230463525417094 801.0195007324417 +15.5625 0.1289390944096008 805.5193634033401 +15.59375 0.1330080828518648 810.0192260742385 +15.625 0.1087347812054992 814.5190887451371 +15.65625 0.1244078270815042 819.0189514160355 +15.6875 0.1289984754599436 823.5188140869341 +15.71875 0.1352044176214791 828.0186767578327 +15.75 0.1314331050059518 832.5185394287313 +15.78125 0.1252001443500418 837.0184020996295 +15.8125 0.1314225736550603 841.5182647705278 +15.84375 0.1356923505299284 846.0181274414267 +15.875 0.1113592613931671 850.5179901123254 +15.90625 0.1265039886229113 855.0178527832236 +15.9375 0.1318380975435933 859.5177154541218 +15.96875 0.1382110410428466 864.0175781250205 +16.0 0.133645843276335 868.5174407959194 +16.03125 0.1272813740631589 873.0173034668177 +16.0625 0.1338764836326204 877.5171661377159 +16.09375 0.1382226505450681 882.0170288086144 +16.125 0.1139284279251886 886.5168914795131 +16.15625 0.128567740548516 891.0167541504117 +16.1875 0.1346064739793712 895.5166168213101 +16.21875 0.1410771584547389 900.0164794922086 +16.25 0.1357569773028019 904.5163421631071 +16.28125 0.1293390899769853 909.0162048340055 +16.3125 0.1363479303235955 913.5160675049041 +16.34375 0.1406301235519381 918.0159301758027 +16.375 0.1164264014174787 922.5157928467013 +16.40625 0.1305825259909043 927.0156555175995 +16.4375 0.1373327768151904 931.5155181884979 +16.46875 0.1438468870152026 936.0153808593967 +16.5 0.1378419788316238 940.5152435302954 +16.53125 0.1313468501722584 945.0151062011936 +16.5625 0.1388098763737581 949.5149688720919 +16.59375 0.142928449398856 954.0148315429906 +16.625 0.1188403445358696 958.5146942138894 +16.65625 0.1325693241873736 963.0145568847877 +16.6875 0.1400230280957335 967.5144195556859 +16.71875 0.146525034054905 972.0142822265846 +16.75 0.1398711075188404 976.5141448974832 +16.78125 0.1333366552258372 981.0140075683817 +16.8125 0.1412509738125822 985.5138702392801 +16.84375 0.14513106491862 990.0137329101786 +16.875 0.1211815448666828 994.5135955810772 +16.90625 0.1345247800333754 999.0134582519755 +16.9375 0.1426686705334448 1003.513320922874 +16.96875 0.1490777179904879 1008.013183593773 +17.0 0.1418577471119871 1012.513046264671 +17.03125 0.1353303711931278 1017.012908935569 +17.0625 0.1436528991104431 1021.512771606468 +17.09375 0.1472664606662112 1026.012634277367 +17.125 0.1234454704751765 1030.512496948265 +17.15625 0.1364810456185349 1035.012359619164 +17.1875 0.1452703757402087 1039.512222290062 +17.21875 0.151558096607376 1044.012084960961 +17.25 0.1437807634181667 1048.511947631859 +17.28125 0.1372932878525469 1053.011810302758 +17.3125 0.1460302780701482 1057.511672973656 +17.34375 0.149320031639015 1062.011535644554 +17.375 0.1256427569591505 1066.511398315453 +17.40625 0.1384081478964682 1071.011260986352 +17.4375 0.1478135356307372 1075.51112365725 +17.46875 0.1539460615922551 1080.010986328149 +17.5 0.1456910404241564 1084.510848999047 +17.53125 0.1392582263378612 1089.010711669946 +17.5625 0.1483559610229651 1093.510574340844 +17.59375 0.1513181838768209 1098.010437011743 +17.625 0.1277435288016546 1102.510299682641 +17.65625 0.1403378517935006 1107.010162353539 +17.6875 0.1503008487276927 1111.510025024438 +17.71875 0.1562707256982678 1116.009887695337 +17.75 0.1475671806734729 1120.509750366235 +17.78125 0.1412248824712325 1125.009613037134 +17.8125 0.150659328971417 1129.509475708032 +17.84375 0.1532766656979263 1134.009338378931 +17.875 0.1297824584132571 1138.509201049829 +17.90625 0.1422618854658679 1143.009063720728 +17.9375 0.1527256888451842 1147.508926391626 +17.96875 0.1584890480232386 1152.008789062525 +18.0 0.149405706732398 1156.508651733423 +18.03125 0.143171640792158 1161.008514404322 +18.0625 0.1529176761471478 1165.50837707522 +18.09375 0.1551977467377527 1170.008239746119 +18.125 0.131765400816527 1174.508102417017 +18.15625 0.1441938818980655 1179.007965087916 +18.1875 0.1550992225797607 1183.507827758814 +18.21875 0.1606570964232007 1188.007690429713 +18.25 0.1512058190790308 1192.507553100611 +18.28125 0.1451520205717164 1197.00741577151 +18.3125 0.1551183561850391 1201.507278442408 +18.34375 0.1570812889608072 1206.007141113307 +18.375 0.1336776271382248 1210.507003784206 +18.40625 0.1461136221129975 1215.006866455104 +18.4375 0.1574403087767436 1219.506729126002 +18.46875 0.1627479710117066 1224.006591796901 +18.5 0.1529973838232315 1228.506454467799 +18.53125 0.1471144758169647 1233.006317138698 +18.5625 0.157290873772812 1237.506179809596 +18.59375 0.1589416558445609 1242.006042480495 +18.625 0.1355352497255837 1246.505905151393 +18.65625 0.1480350786705765 1251.005767822292 +18.6875 0.1597404963023554 1255.50563049319 +18.71875 0.1647598358394601 1260.005493164089 +18.75 0.1547691158700678 1264.505355834987 +18.78125 0.1490751600212936 1269.005218505886 +18.8125 0.1594177692844409 1273.505081176784 +18.84375 0.1607950683386228 1278.004943847683 +18.875 0.1373442606771443 1282.504806518581 +18.90625 0.1499764982195686 1287.00466918948 +18.9375 0.161981916396387 1291.504531860378 +18.96875 0.1667161355701408 1296.004394531277 +19.0 0.1564970791017503 1300.504257202175 +19.03125 0.1510421101147244 1305.004119873074 +19.0625 0.1614940714004816 1309.503982543972 +19.09375 0.1626278045674801 1314.003845214871 +19.125 0.1391070684490964 1318.503707885769 +19.15625 0.1518963284417672 1323.003570556668 +19.1875 0.1641776433754442 1327.503433227566 +19.21875 0.1686227398941271 1332.003295898465 +19.25 0.158245898565777 1336.503158569363 +19.28125 0.153010602347685 1341.003021240262 +19.3125 0.1635401191148302 1345.50288391116 +19.34375 0.1644706200297989 1350.002746582059 +19.375 0.140837795269601 1354.502609252957 +19.40625 0.153819852891827 1359.002471923856 +19.4375 0.1663483805712817 1363.502334594754 +19.46875 0.1704527034458771 1368.002197265653 +19.5 0.1599450644585954 1372.502059936551 +19.53125 0.154992649837243 1377.00192260745 +19.5625 0.1655498824196527 1381.501785278348 +19.59375 0.1663063172499863 1386.001647949247 +19.625 0.142544544595813 1390.501510620146 +19.65625 0.1557303075785325 1395.001373291044 +19.6875 0.1684970432426142 1399.501235961942 +19.71875 0.17221935361306 1404.001098632841 +19.75 0.1616491616340551 1408.50096130374 +19.78125 0.1569578150703002 1413.000823974638 +19.8125 0.167533124847069 1417.500686645536 +19.84375 0.1681580952994133 1422.000549316435 +19.875 0.1442139440246979 1426.500411987333 +19.90625 0.1576452601836673 1431.000274658232 +19.9375 0.1706020388366926 1435.50013732913 +19.96875 0.1739429533647216 1440.000000000029 diff --git a/tests/circuitpython/traceback_test_chained.py b/tests/circuitpython/traceback_test_chained.py index 3b96eb7a3ca9e..46adfdb841a4d 100644 --- a/tests/circuitpython/traceback_test_chained.py +++ b/tests/circuitpython/traceback_test_chained.py @@ -73,9 +73,11 @@ def print_exc_info(e, chain=True): print_exc_info(e) print() + class SomeException(RuntimeError): pass + try: try: raise Exception("inner") diff --git a/tests/circuitpython/traceback_test_chained.py.exp b/tests/circuitpython/traceback_test_chained.py.exp index 498be1f0b7989..9105ac1d98bdd 100644 --- a/tests/circuitpython/traceback_test_chained.py.exp +++ b/tests/circuitpython/traceback_test_chained.py.exp @@ -76,75 +76,75 @@ ZeroDivisionError: division by zero ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 81, in + File "circuitpython/traceback_test_chained.py", line 83, in Exception: inner During handling of the above exception, another exception occurred: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 83, in + File "circuitpython/traceback_test_chained.py", line 85, in SomeException: outer ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 89, in + File "circuitpython/traceback_test_chained.py", line 91, in Exception: inner The above exception was the direct cause of the following exception: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 92, in + File "circuitpython/traceback_test_chained.py", line 94, in SomeException: outer ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 99, in + File "circuitpython/traceback_test_chained.py", line 101, in RuntimeError: inner The above exception was the direct cause of the following exception: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 101, in + File "circuitpython/traceback_test_chained.py", line 103, in Exception: outer ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 107, in + File "circuitpython/traceback_test_chained.py", line 109, in RuntimeError: inner The above exception was the direct cause of the following exception: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 110, in + File "circuitpython/traceback_test_chained.py", line 112, in Exception: outer ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 117, in + File "circuitpython/traceback_test_chained.py", line 119, in RuntimeError: inner During handling of the above exception, another exception occurred: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 119, in + File "circuitpython/traceback_test_chained.py", line 121, in SomeException: outer ------------------------------------------------------------------------ ------------------------------------------------------------------------ Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 125, in + File "circuitpython/traceback_test_chained.py", line 127, in RuntimeError: inner The above exception was the direct cause of the following exception: Traceback (most recent call last): - File "circuitpython/traceback_test_chained.py", line 128, in + File "circuitpython/traceback_test_chained.py", line 130, in SomeException: outer ------------------------------------------------------------------------ diff --git a/tests/cmdline/cmd_compile_only.py b/tests/cmdline/cmd_compile_only.py new file mode 100644 index 0000000000000..89964c1b5bdf2 --- /dev/null +++ b/tests/cmdline/cmd_compile_only.py @@ -0,0 +1,13 @@ +# cmdline: -X compile-only +# test compile-only functionality +print("This should not be printed") +x = 1 + 2 + + +def hello(): + return "world" + + +class TestClass: + def __init__(self): + self.value = 42 diff --git a/tests/cmdline/cmd_compile_only.py.exp b/tests/cmdline/cmd_compile_only.py.exp new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/tests/cmdline/cmd_compile_only.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/cmd_compile_only_error.py b/tests/cmdline/cmd_compile_only_error.py new file mode 100644 index 0000000000000..326937a5c07ef --- /dev/null +++ b/tests/cmdline/cmd_compile_only_error.py @@ -0,0 +1,6 @@ +# cmdline: -X compile-only +# test compile-only with syntax error +print("This should not be printed") +def broken_syntax( + # Missing closing parenthesis + return "error" diff --git a/tests/cmdline/cmd_compile_only_error.py.exp b/tests/cmdline/cmd_compile_only_error.py.exp new file mode 100644 index 0000000000000..3911f71d6244d --- /dev/null +++ b/tests/cmdline/cmd_compile_only_error.py.exp @@ -0,0 +1 @@ +CRASH \ No newline at end of file diff --git a/tests/cmdline/cmd_file_variable.py b/tests/cmdline/cmd_file_variable.py new file mode 100644 index 0000000000000..6cac6744d904e --- /dev/null +++ b/tests/cmdline/cmd_file_variable.py @@ -0,0 +1,5 @@ +# Test that __file__ is set correctly for script execution +try: + print("__file__ =", __file__) +except NameError: + print("__file__ not defined") diff --git a/tests/cmdline/cmd_file_variable.py.exp b/tests/cmdline/cmd_file_variable.py.exp new file mode 100644 index 0000000000000..6807569f662b5 --- /dev/null +++ b/tests/cmdline/cmd_file_variable.py.exp @@ -0,0 +1 @@ +__file__ = cmdline/cmd_file_variable.py diff --git a/tests/cmdline/cmd_module_atexit.py b/tests/cmdline/cmd_module_atexit.py new file mode 100644 index 0000000000000..100bc112777e1 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit.py @@ -0,0 +1,16 @@ +# cmdline: -m cmdline.cmd_module_atexit +# +# Test running as a module and using sys.atexit. + +import sys + +if not hasattr(sys, "atexit"): + print("SKIP") + raise SystemExit + +# Verify we ran as a module. +print(sys.argv) + +sys.atexit(lambda: print("done")) + +print("start") diff --git a/tests/cmdline/cmd_module_atexit.py.exp b/tests/cmdline/cmd_module_atexit.py.exp new file mode 100644 index 0000000000000..2a0f756b1e799 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit.py.exp @@ -0,0 +1,3 @@ +['cmdline.cmd_module_atexit', 'cmdline/cmd_module_atexit.py'] +start +done diff --git a/tests/cmdline/cmd_module_atexit_exc.py b/tests/cmdline/cmd_module_atexit_exc.py new file mode 100644 index 0000000000000..88940a7741fb9 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit_exc.py @@ -0,0 +1,19 @@ +# cmdline: -m cmdline.cmd_module_atexit_exc +# +# Test running as a module and using sys.atexit, with script completion via sys.exit. + +import sys + +if not hasattr(sys, "atexit"): + print("SKIP") + raise SystemExit + +# Verify we ran as a module. +print(sys.argv) + +sys.atexit(lambda: print("done")) + +print("start") + +# This will raise SystemExit to finish the script, and atexit should still be run. +sys.exit(0) diff --git a/tests/cmdline/cmd_module_atexit_exc.py.exp b/tests/cmdline/cmd_module_atexit_exc.py.exp new file mode 100644 index 0000000000000..6320d9d2d3011 --- /dev/null +++ b/tests/cmdline/cmd_module_atexit_exc.py.exp @@ -0,0 +1,3 @@ +['cmdline.cmd_module_atexit_exc', 'cmdline/cmd_module_atexit_exc.py'] +start +done diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp index 6ec553b8a9ae2..672c212a965b9 100644 --- a/tests/cmdline/cmd_parsetree.py.exp +++ b/tests/cmdline/cmd_parsetree.py.exp @@ -1,6 +1,6 @@ ---------------- [ 1] file_input_2(1) (n=10) - tok(6) + tok(5) [ 4] \(rule\|for_stmt\)(22) (n=4) id(i) [ 4] \(rule\|atom_paren\)(45) (n=1) @@ -9,7 +9,7 @@ NULL [ 6] \(rule\|expr_stmt\)(5) (n=2) id(a) - tok(16) + tok(15) [ 7] \(rule\|expr_stmt\)(5) (n=2) id(b) str(str) diff --git a/tests/cmdline/cmd_sys_exit_0.py b/tests/cmdline/cmd_sys_exit_0.py new file mode 100644 index 0000000000000..1294b739e8ff1 --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_0.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit(0) - success exit code +import sys + +sys.exit(0) diff --git a/tests/cmdline/cmd_sys_exit_0.py.exp b/tests/cmdline/cmd_sys_exit_0.py.exp new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_0.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/cmd_sys_exit_error.py b/tests/cmdline/cmd_sys_exit_error.py new file mode 100644 index 0000000000000..ecac15e94f1bf --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_error.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit() functionality and exit codes +import sys + +sys.exit(123) diff --git a/tests/cmdline/cmd_sys_exit_error.py.exp b/tests/cmdline/cmd_sys_exit_error.py.exp new file mode 100644 index 0000000000000..3911f71d6244d --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_error.py.exp @@ -0,0 +1 @@ +CRASH \ No newline at end of file diff --git a/tests/cmdline/cmd_sys_exit_none.py b/tests/cmdline/cmd_sys_exit_none.py new file mode 100644 index 0000000000000..66e19666589ed --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_none.py @@ -0,0 +1,5 @@ +# cmdline: +# test sys.exit(None) - should exit with code 0 +import sys + +sys.exit(None) diff --git a/tests/cmdline/cmd_sys_exit_none.py.exp b/tests/cmdline/cmd_sys_exit_none.py.exp new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/tests/cmdline/cmd_sys_exit_none.py.exp @@ -0,0 +1 @@ + diff --git a/tests/cmdline/repl_autocomplete.py.exp b/tests/cmdline/repl_autocomplete.py.exp index 2e2397bb028d3..7840e52e8a4a2 100644 --- a/tests/cmdline/repl_autocomplete.py.exp +++ b/tests/cmdline/repl_autocomplete.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # tests for autocompletion >>> import sys >>> not_exist. @@ -11,4 +11,4 @@ Use \.\+ >>> i.lower('ABC') 'abc' >>> None. ->>> +>>> \$ diff --git a/tests/cmdline/repl_autocomplete_underscore.py b/tests/cmdline/repl_autocomplete_underscore.py new file mode 100644 index 0000000000000..e685a7fe7ff02 --- /dev/null +++ b/tests/cmdline/repl_autocomplete_underscore.py @@ -0,0 +1,33 @@ +# Test REPL autocompletion filtering of underscore attributes + +# Start paste mode +{\x05} +class TestClass: + def __init__(self): + self.public_attr = 1 + self._private_attr = 2 + self.__very_private = 3 + + def public_method(self): + pass + + def _private_method(self): + pass + + @property + def public_property(self): + return 42 + + @property + def _private_property(self): + return 99 + +{\x04} +# Paste executed + +# Create an instance +obj = TestClass() + +# Test tab completion on the instance +# The tab character after `obj.` and 'a' below triggers the completions +obj.{\x09}{\x09}a{\x09} diff --git a/tests/cmdline/repl_autocomplete_underscore.py.exp b/tests/cmdline/repl_autocomplete_underscore.py.exp new file mode 100644 index 0000000000000..98e6c2aeb05a3 --- /dev/null +++ b/tests/cmdline/repl_autocomplete_underscore.py.exp @@ -0,0 +1,41 @@ + +Adafruit CircuitPython \.\+ version +>>> # Test REPL autocompletion filtering of underscore attributes +>>> \$ +>>> # Start paste mode +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== class TestClass: +=== def __init__(self): +=== self.public_attr = 1 +=== self._private_attr = 2 +=== self.__very_private = 3 +=== \$ +=== def public_method(self): +=== pass +=== \$ +=== def _private_method(self): +=== pass +=== \$ +=== @property +=== def public_property(self): +=== return 42 +=== \$ +=== @property +=== def _private_property(self): +=== return 99 +=== \$ +=== \$ +>>> # Paste executed +>>> \$ +>>> # Create an instance +>>> obj = TestClass() +>>> \$ +>>> # Test tab completion on the instance +>>> # The tab character after `obj.` and 'a' below triggers the completions +>>> obj.public_ +public_attr public_method public_property +>>> obj.public_attr +1 +>>> \$ diff --git a/tests/cmdline/repl_autoindent.py.exp b/tests/cmdline/repl_autoindent.py.exp index 9ff83a92870e8..04f00686b208d 100644 --- a/tests/cmdline/repl_autoindent.py.exp +++ b/tests/cmdline/repl_autoindent.py.exp @@ -1,22 +1,22 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # tests for autoindent >>> if 1: ... print(1) -... -... -... +... \$ +... \$ +... \$ 1 >>> if 0: ...  print(2) ... else: ... print(3) -... +... \$ 3 >>> if 0: ... print(4) ... else: ... print(5) -... +... \$ 5 ->>> +>>> \$ diff --git a/tests/cmdline/repl_basic.py.exp b/tests/cmdline/repl_basic.py.exp index 26442b6445589..5bdcc9d6d3246 100644 --- a/tests/cmdline/repl_basic.py.exp +++ b/tests/cmdline/repl_basic.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # basic REPL tests >>> print(1) 1 @@ -7,4 +7,4 @@ Use \.\+ 1 >>> 2 2 ->>> +>>> \$ diff --git a/tests/cmdline/repl_cont.py.exp b/tests/cmdline/repl_cont.py.exp index 6eed4a3e02c47..41f2436ac18a0 100644 --- a/tests/cmdline/repl_cont.py.exp +++ b/tests/cmdline/repl_cont.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # check REPL allows to continue input >>> 1 \\\\ ... + 2 @@ -54,4 +54,4 @@ two >>> if1 = 2 >>> print(if1) 2 ->>> +>>> \$ diff --git a/tests/cmdline/repl_emacs_keys.py.exp b/tests/cmdline/repl_emacs_keys.py.exp index 2e8667a8e6ca9..4979f8bbfc3ab 100644 --- a/tests/cmdline/repl_emacs_keys.py.exp +++ b/tests/cmdline/repl_emacs_keys.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # REPL tests of GNU-ish readline navigation >>> # history buffer navigation >>> 1 @@ -16,4 +16,4 @@ Use \.\+ >>> t = 121 >>> \.\+ 'foobar' ->>> +>>> \$ diff --git a/tests/cmdline/repl_inspect.py.exp b/tests/cmdline/repl_inspect.py.exp index 8ece5ffc37f5c..30257f31aab93 100644 --- a/tests/cmdline/repl_inspect.py.exp +++ b/tests/cmdline/repl_inspect.py.exp @@ -1,6 +1,6 @@ test -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # cmdline: -i -c print("test") >>> # -c option combined with -i option results in REPL ->>> +>>> \$ diff --git a/tests/cmdline/repl_lock.py b/tests/cmdline/repl_lock.py new file mode 100644 index 0000000000000..77e2e9327401a --- /dev/null +++ b/tests/cmdline/repl_lock.py @@ -0,0 +1,7 @@ +import micropython +micropython.heap_lock() +1+1 +micropython.heap_lock() +None # Cause the repl's line storage to be enlarged ---------------- +micropython.heap_lock() +raise SystemExit diff --git a/tests/cmdline/repl_lock.py.exp b/tests/cmdline/repl_lock.py.exp new file mode 100644 index 0000000000000..e6d63fcf20044 --- /dev/null +++ b/tests/cmdline/repl_lock.py.exp @@ -0,0 +1,10 @@ + +Adafruit CircuitPython \.\+ version +>>> import micropython +>>> micropython.heap_lock() +>>> 1+1 +2 +>>> micropython.heap_lock() +>>> None # Cause the repl's line storage to be enlarged ---------------- +>>> micropython.heap_lock() +>>> raise SystemExit diff --git a/tests/cmdline/repl_micropyinspect.py.exp b/tests/cmdline/repl_micropyinspect.py.exp index 3c9cbc030c0b5..36bef37c62c6b 100644 --- a/tests/cmdline/repl_micropyinspect.py.exp +++ b/tests/cmdline/repl_micropyinspect.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # cmdline: cmdline/repl_micropyinspect >>> # setting MICROPYINSPECT environment variable before program exit triggers REPL ->>> +>>> \$ diff --git a/tests/cmdline/repl_paste.py b/tests/cmdline/repl_paste.py new file mode 100644 index 0000000000000..7cec450fce7bf --- /dev/null +++ b/tests/cmdline/repl_paste.py @@ -0,0 +1,90 @@ +# Test REPL paste mode functionality + +# Basic paste mode with a simple function +{\x05} +def hello(): + print('Hello from paste mode!') +hello() +{\x04} + +# Paste mode with multiple indentation levels +{\x05} +def calculate(n): + if n > 0: + for i in range(n): + if i % 2 == 0: + print(f'Even: {i}') + else: + print(f'Odd: {i}') + else: + print('n must be positive') + +calculate(5) +{\x04} + +# Paste mode with blank lines +{\x05} +def function_with_blanks(): + print('First line') + + print('After blank line') + + + print('After two blank lines') + +function_with_blanks() +{\x04} + +# Paste mode with class definition and multiple methods +{\x05} +class TestClass: + def __init__(self, value): + self.value = value + + def display(self): + print(f'Value is: {self.value}') + + def double(self): + self.value *= 2 + return self.value + +obj = TestClass(21) +obj.display() +print(f'Doubled: {obj.double()}') +obj.display() +{\x04} + +# Paste mode with exception handling +{\x05} +try: + x = 1 / 0 +except ZeroDivisionError: + print('Caught division by zero') +finally: + print('Finally block executed') +{\x04} + +# Cancel paste mode with Ctrl-C +{\x05} +print('This should not execute') +{\x03} + +# Normal REPL still works after cancelled paste +print('Back to normal REPL') + +# Paste mode with syntax error +{\x05} +def bad_syntax(: + print('Missing parameter') +{\x04} + +# Paste mode with runtime error +{\x05} +def will_error(): + undefined_variable + +will_error() +{\x04} + +# Final test to show REPL is still functioning +1 + 2 + 3 diff --git a/tests/cmdline/repl_paste.py.exp b/tests/cmdline/repl_paste.py.exp new file mode 100644 index 0000000000000..cc5ac2f08007d --- /dev/null +++ b/tests/cmdline/repl_paste.py.exp @@ -0,0 +1,133 @@ + +Adafruit CircuitPython \.\+ version +>>> # Test REPL paste mode functionality +>>> \$ +>>> # Basic paste mode with a simple function +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def hello(): +=== print('Hello from paste mode!') +=== hello() +=== \$ +Hello from paste mode! +>>> \$ +>>> # Paste mode with multiple indentation levels +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def calculate(n): +=== if n > 0: +=== for i in range(n): +=== if i % 2 == 0: +=== print(f'Even: {i}') +=== else: +=== print(f'Odd: {i}') +=== else: +=== print('n must be positive') +=== \$ +=== calculate(5) +=== \$ +Even: 0 +Odd: 1 +Even: 2 +Odd: 3 +Even: 4 +>>> \$ +>>> # Paste mode with blank lines +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def function_with_blanks(): +=== print('First line') +=== \$ +=== print('After blank line') +=== \$ +=== \$ +=== print('After two blank lines') +=== \$ +=== function_with_blanks() +=== \$ +First line +After blank line +After two blank lines +>>> \$ +>>> # Paste mode with class definition and multiple methods +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== class TestClass: +=== def __init__(self, value): +=== self.value = value +=== \$ +=== def display(self): +=== print(f'Value is: {self.value}') +=== \$ +=== def double(self): +=== self.value *= 2 +=== return self.value +=== \$ +=== obj = TestClass(21) +=== obj.display() +=== print(f'Doubled: {obj.double()}') +=== obj.display() +=== \$ +Value is: 21 +Doubled: 42 +Value is: 42 +>>> \$ +>>> # Paste mode with exception handling +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== try: +=== x = 1 / 0 +=== except ZeroDivisionError: +=== print('Caught division by zero') +=== finally: +=== print('Finally block executed') +=== \$ +Caught division by zero +Finally block executed +>>> \$ +>>> # Cancel paste mode with Ctrl-C +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== print('This should not execute') +=== \$ +>>> \$ +>>> \$ +>>> # Normal REPL still works after cancelled paste +>>> print('Back to normal REPL') +Back to normal REPL +>>> \$ +>>> # Paste mode with syntax error +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def bad_syntax(: +=== print('Missing parameter') +=== \$ +Traceback (most recent call last): + File "", line 2 +SyntaxError: invalid syntax +>>> \$ +>>> # Paste mode with runtime error +>>> \$ +paste mode; Ctrl-C to cancel, Ctrl-D to finish +=== \$ +=== def will_error(): +=== undefined_variable +=== \$ +=== will_error() +=== \$ +Traceback (most recent call last): + File "", line 5, in + File "", line 3, in will_error +NameError: name 'undefined_variable' isn't defined +>>> \$ +>>> # Final test to show REPL is still functioning +>>> 1 + 2 + 3 +6 +>>> \$ diff --git a/tests/cmdline/repl_sys_ps1_ps2.py.exp b/tests/cmdline/repl_sys_ps1_ps2.py.exp index 452a54fe5ae9b..d4bcf7a44d592 100644 --- a/tests/cmdline/repl_sys_ps1_ps2.py.exp +++ b/tests/cmdline/repl_sys_ps1_ps2.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # test changing ps1/ps2 >>> import sys >>> sys.ps1 = "PS1" diff --git a/tests/cmdline/repl_words_move.py.exp b/tests/cmdline/repl_words_move.py.exp index ba5c3648cff98..41ad3d8e73351 100644 --- a/tests/cmdline/repl_words_move.py.exp +++ b/tests/cmdline/repl_words_move.py.exp @@ -1,5 +1,5 @@ -CircuitPython \.\+ version -Use \.\+ + +Adafruit CircuitPython \.\+ version >>> # word movement >>> # backward-word, start in word >>> \.\+ @@ -19,7 +19,7 @@ Use \.\+ >>> # forward-word on eol. if cursor is moved, this will result in a SyntaxError >>> \.\+ 6 ->>> +>>> \$ >>> # kill word >>> # backward-kill-word, start in word >>> \.\+ @@ -33,7 +33,7 @@ Use \.\+ >>> # forward-kill-word, don't start in word >>> \.\+ 3 ->>> +>>> \$ >>> # extra move/kill shortcuts >>> # ctrl-left >>> \.\+ @@ -44,4 +44,4 @@ Use \.\+ >>> # ctrl-w >>> \.\+ 1 ->>> +>>> \$ diff --git a/tests/cpydiff/builtin_next_arg2.py b/tests/cpydiff/builtin_next_arg2.py deleted file mode 100644 index 5df2d6e70f837..0000000000000 --- a/tests/cpydiff/builtin_next_arg2.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -categories: Modules,builtins -description: Second argument to next() is not implemented -cause: MicroPython is optimised for code space. -workaround: Instead of ``val = next(it, deflt)`` use:: - - try: - val = next(it) - except StopIteration: - val = deflt -""" -print(next(iter(range(0)), 42)) diff --git a/tests/cpydiff/core_class_delnotimpl.py b/tests/cpydiff/core_class_delnotimpl.py index 18c176e9bb1f7..6fac764ac9828 100644 --- a/tests/cpydiff/core_class_delnotimpl.py +++ b/tests/cpydiff/core_class_delnotimpl.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + import gc diff --git a/tests/cpydiff/core_class_initsubclass.py b/tests/cpydiff/core_class_initsubclass.py new file mode 100644 index 0000000000000..8683271dcb0f2 --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass.py @@ -0,0 +1,21 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't automatically called. +cause: MicroPython does not currently implement PEP 487. +workaround: Manually call ``__init_subclass__`` after class creation if needed. e.g.:: + + class A(Base): + pass + A.__init_subclass__() + +""" + + +class Base: + @classmethod + def __init_subclass__(cls): + print(f"Base.__init_subclass__({cls.__name__})") + + +class A(Base): + pass diff --git a/tests/cpydiff/core_class_initsubclass_autoclassmethod.py b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py new file mode 100644 index 0000000000000..b2f7628976c92 --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_autoclassmethod.py @@ -0,0 +1,31 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` isn't an implicit classmethod. +cause: MicroPython does not currently implement PEP 487. ``__init_subclass__`` is not currently in the list of special-cased class/static methods. +workaround: Decorate declarations of ``__init_subclass__`` with ``@classmethod``. +""" + + +def regularize_spelling(text, prefix="bound_"): + # for regularizing across the CPython "method" vs MicroPython "bound_method" spelling for the type of a bound classmethod + if text.startswith(prefix): + return text[len(prefix) :] + return text + + +class A: + def __init_subclass__(cls): + pass + + @classmethod + def manual_decorated(cls): + pass + + +a = type(A.__init_subclass__).__name__ +b = type(A.manual_decorated).__name__ + +print(regularize_spelling(a)) +print(regularize_spelling(b)) +if a != b: + print("FAIL") diff --git a/tests/cpydiff/core_class_initsubclass_kwargs.py b/tests/cpydiff/core_class_initsubclass_kwargs.py new file mode 100644 index 0000000000000..ed5157afeaede --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_kwargs.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: MicroPython doesn't support parameterized ``__init_subclass__`` class customization. +cause: MicroPython does not currently implement PEP 487. The MicroPython syntax tree does not include a kwargs node after the class inheritance list. +workaround: Use class variables or another mechanism to specify base-class customizations. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, arg=None, **kwargs): + cls.init_subclass_was_called = True + print(f"Base.__init_subclass__({cls.__name__}, {arg=!r}, {kwargs=!r})") + + +class A(Base, arg="arg"): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__() diff --git a/tests/cpydiff/core_class_initsubclass_super.py b/tests/cpydiff/core_class_initsubclass_super.py new file mode 100644 index 0000000000000..d18671a74bf8e --- /dev/null +++ b/tests/cpydiff/core_class_initsubclass_super.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: ``__init_subclass__`` can't be defined a cooperatively-recursive way. +cause: MicroPython does not currently implement PEP 487. The base object type does not have an ``__init_subclass__`` implementation. +workaround: Omit the recursive ``__init_subclass__`` call unless it's known that the grandparent also defines it. +""" + + +class Base: + @classmethod + def __init_subclass__(cls, **kwargs): + cls.init_subclass_was_called = True + super().__init_subclass__(**kwargs) + + +class A(Base): + pass + + +# Regularize across MicroPython not automatically calling __init_subclass__ either. +if not getattr(A, "init_subclass_was_called", False): + A.__init_subclass__() diff --git a/tests/cpydiff/core_class_name_mangling.py b/tests/cpydiff/core_class_name_mangling.py new file mode 100644 index 0000000000000..39153209debe8 --- /dev/null +++ b/tests/cpydiff/core_class_name_mangling.py @@ -0,0 +1,26 @@ +""" +categories: Core,Classes +description: Private Class Members name mangling is not implemented +cause: The MicroPython compiler does not implement name mangling for private class members. +workaround: Avoid using or having a collision with global names, by adding a unique prefix to the private class member name manually. +""" + + +def __print_string(string): + print(string) + + +class Foo: + def __init__(self, string): + self.string = string + + def do_print(self): + __print_string(self.string) + + +example_string = "Example String to print." + +class_item = Foo(example_string) +print(class_item.string) + +class_item.do_print() diff --git a/tests/cpydiff/core_class_super_init.py b/tests/cpydiff/core_class_super_init.py new file mode 100644 index 0000000000000..1774f61dd82e4 --- /dev/null +++ b/tests/cpydiff/core_class_super_init.py @@ -0,0 +1,31 @@ +""" +categories: Core,Classes +description: When inheriting native types, calling a method in ``__init__(self, ...)`` before ``super().__init__()`` raises an ``AttributeError`` (or segfaults if ``MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG`` is not enabled). +cause: MicroPython does not have separate ``__new__`` and ``__init__`` methods in native types. +workaround: Call ``super().__init__()`` first. +""" + + +class L1(list): + def __init__(self, a): + self.append(a) + + +try: + L1(1) + print("OK") +except AttributeError: + print("AttributeError") + + +class L2(list): + def __init__(self, a): + super().__init__() + self.append(a) + + +try: + L2(1) + print("OK") +except AttributeError: + print("AttributeError") diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/cpydiff/core_class_superproperty.py new file mode 100644 index 0000000000000..2d7775a9028e8 --- /dev/null +++ b/tests/cpydiff/core_class_superproperty.py @@ -0,0 +1,22 @@ +""" +categories: Core,Classes +description: Calling super() getter property in subclass will return a property object, not the value +cause: Unknown +workaround: Unknown +""" + + +class A: + @property + def p(self): + return {"a": 10} + + +class AA(A): + @property + def p(self): + return super().p + + +a = AA() +print(a.p) diff --git a/tests/cpydiff/core_fstring_concat.py b/tests/cpydiff/core_fstring_concat.py index c2bdb4e666a2d..2fbe1b961a1e6 100644 --- a/tests/cpydiff/core_fstring_concat.py +++ b/tests/cpydiff/core_fstring_concat.py @@ -1,13 +1,14 @@ """ -categories: Core -description: f-strings don't support concatenation with adjacent literals if the adjacent literals contain braces or are f-strings +categories: Core,f-strings +description: f-strings don't support concatenation with adjacent literals if the adjacent literals contain braces cause: MicroPython is optimised for code space. -workaround: Use the + operator between literal strings when either or both are f-strings +workaround: Use the + operator between literal strings when they are not both f-strings """ x, y = 1, 2 +# fmt: off print("aa" f"{x}") # works print(f"{x}" "ab") # works print("a{}a" f"{x}") # fails print(f"{x}" "a{}b") # fails -print(f"{x}" f"{y}") # fails +# fmt: on diff --git a/tests/cpydiff/core_fstring_parser.py b/tests/cpydiff/core_fstring_parser.py index 22bbc5866ec3a..4964b9707aceb 100644 --- a/tests/cpydiff/core_fstring_parser.py +++ b/tests/cpydiff/core_fstring_parser.py @@ -1,9 +1,10 @@ """ -categories: Core +categories: Core,f-strings description: f-strings cannot support expressions that require parsing to resolve unbalanced nested braces and brackets cause: MicroPython is optimised for code space. workaround: Always use balanced braces and brackets in expressions inside f-strings """ -print(f'{"hello { world"}') -print(f'{"hello ] world"}') +# CIRCUITPY-CHANGE: add noqa so ruff won't complain about unmatched braces +print(f"{'hello { world'}") # noqa +print(f"{'hello ] world'}") # noqa diff --git a/tests/cpydiff/core_fstring_raw.py b/tests/cpydiff/core_fstring_raw.py deleted file mode 100644 index 84e265f70fc52..0000000000000 --- a/tests/cpydiff/core_fstring_raw.py +++ /dev/null @@ -1,8 +0,0 @@ -""" -categories: Core -description: Raw f-strings are not supported -cause: MicroPython is optimised for code space. -workaround: Unknown -""" - -rf"hello" diff --git a/tests/cpydiff/core_fstring_repr.py b/tests/cpydiff/core_fstring_repr.py index d37fb48db758c..2589a34b7e3b9 100644 --- a/tests/cpydiff/core_fstring_repr.py +++ b/tests/cpydiff/core_fstring_repr.py @@ -1,5 +1,5 @@ """ -categories: Core +categories: Core,f-strings description: f-strings don't support !a conversions cause: MicropPython does not implement ascii() workaround: None diff --git a/tests/cpydiff/core_function_argcount.py b/tests/cpydiff/core_function_argcount.py index 5f3dca4dcdbe4..c257def726aca 100644 --- a/tests/cpydiff/core_function_argcount.py +++ b/tests/cpydiff/core_function_argcount.py @@ -4,6 +4,7 @@ cause: MicroPython counts "self" as an argument. workaround: Interpret error messages with the information above in mind. """ + try: [].append() except Exception as e: diff --git a/tests/cpydiff/core_import_all.py b/tests/cpydiff/core_import_all.py deleted file mode 100644 index 5adf9ae3eb1e6..0000000000000 --- a/tests/cpydiff/core_import_all.py +++ /dev/null @@ -1,9 +0,0 @@ -""" -categories: Core,import -description: __all__ is unsupported in __init__.py in MicroPython. -cause: Not implemented. -workaround: Manually import the sub-modules directly in __init__.py using ``from . import foo, bar``. -""" -from modules3 import * - -foo.hello() diff --git a/tests/cpydiff/core_import_path.py b/tests/cpydiff/core_import_path.py index 959fd571f57ab..2028386be84b0 100644 --- a/tests/cpydiff/core_import_path.py +++ b/tests/cpydiff/core_import_path.py @@ -4,6 +4,7 @@ cause: MicroPython doesn't support namespace packages split across filesystem. Beyond that, MicroPython's import system is highly optimized for minimal memory usage. workaround: Details of import handling is inherently implementation dependent. Don't rely on such details in portable applications. """ + import modules print(modules.__path__) diff --git a/tests/cpydiff/core_import_split_ns_pkgs.py b/tests/cpydiff/core_import_split_ns_pkgs.py index 5c92b63124a50..a1cfd84893d4e 100644 --- a/tests/cpydiff/core_import_split_ns_pkgs.py +++ b/tests/cpydiff/core_import_split_ns_pkgs.py @@ -4,6 +4,7 @@ cause: MicroPython's import system is highly optimized for simplicity, minimal memory usage, and minimal filesystem search overhead. workaround: Don't install modules belonging to the same namespace package in different directories. For MicroPython, it's recommended to have at most 3-component module search paths: for your current application, per-user (writable), system-wide (non-writable). """ + import sys sys.path.append(sys.path[1] + "/modules") diff --git a/tests/cpydiff/core_locals_eval.py b/tests/cpydiff/core_locals_eval.py index 025d226372986..3f6ad2a1dbbc6 100644 --- a/tests/cpydiff/core_locals_eval.py +++ b/tests/cpydiff/core_locals_eval.py @@ -4,6 +4,7 @@ cause: MicroPython doesn't maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can't be accessed by a name. Effectively, ``eval(expr)`` in MicroPython is equivalent to ``eval(expr, globals(), globals())``. workaround: Unknown """ + val = 1 diff --git a/tests/cpydiff/module_array_comparison.py b/tests/cpydiff/module_array_comparison.py index a442af3f5bc96..4929b1e590dac 100644 --- a/tests/cpydiff/module_array_comparison.py +++ b/tests/cpydiff/module_array_comparison.py @@ -4,6 +4,7 @@ cause: Code size workaround: Compare individual elements """ + import array array.array("b", [1, 2]) == array.array("i", [1, 2]) diff --git a/tests/cpydiff/module_array_constructor.py b/tests/cpydiff/module_array_constructor.py index 08cf2ef2d1c3c..a53589d22ae76 100644 --- a/tests/cpydiff/module_array_constructor.py +++ b/tests/cpydiff/module_array_constructor.py @@ -4,6 +4,7 @@ cause: MicroPython implements implicit truncation in order to reduce code size and execution time workaround: If CPython compatibility is needed then mask the value explicitly """ + import array a = array.array("b", [257]) diff --git a/tests/cpydiff/modules3/__init__.py b/tests/cpydiff/modules3/__init__.py deleted file mode 100644 index 27a2bf2ad9044..0000000000000 --- a/tests/cpydiff/modules3/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__all__ = ["foo"] diff --git a/tests/cpydiff/modules3/foo.py b/tests/cpydiff/modules3/foo.py deleted file mode 100644 index dd9b9d4ddd4c4..0000000000000 --- a/tests/cpydiff/modules3/foo.py +++ /dev/null @@ -1,2 +0,0 @@ -def hello(): - print("hello") diff --git a/tests/cpydiff/modules_array_containment.py b/tests/cpydiff/modules_array_containment.py index 8f25b0d49149d..b29895aa75892 100644 --- a/tests/cpydiff/modules_array_containment.py +++ b/tests/cpydiff/modules_array_containment.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + import array print(1 in array.array("B", b"12")) diff --git a/tests/cpydiff/modules_array_deletion.py b/tests/cpydiff/modules_array_deletion.py index 3376527373edf..2e7c31124b2da 100644 --- a/tests/cpydiff/modules_array_deletion.py +++ b/tests/cpydiff/modules_array_deletion.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + import array a = array.array("b", (1, 2, 3)) diff --git a/tests/cpydiff/modules_array_subscrstep.py b/tests/cpydiff/modules_array_subscrstep.py index 24308bd9042d1..65b12332f54cd 100644 --- a/tests/cpydiff/modules_array_subscrstep.py +++ b/tests/cpydiff/modules_array_subscrstep.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + import array a = array.array("b", (1, 2, 3)) diff --git a/tests/cpydiff/modules_deque.py b/tests/cpydiff/modules_deque.py index 4d2746d1f864e..9eb9edbda620b 100644 --- a/tests/cpydiff/modules_deque.py +++ b/tests/cpydiff/modules_deque.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Use regular lists. micropython-lib has implementation of collections.deque. """ + import collections D = collections.deque() diff --git a/tests/cpydiff/modules_errno_enotsup.py b/tests/cpydiff/modules_errno_enotsup.py new file mode 100644 index 0000000000000..80e5ad9d03220 --- /dev/null +++ b/tests/cpydiff/modules_errno_enotsup.py @@ -0,0 +1,10 @@ +""" +categories: Modules,errno +description: MicroPython does not include ``ENOTSUP`` as a name for errno 95. +cause: MicroPython does not implement the ``ENOTSUP`` canonical alias for ``EOPNOTSUPP`` added in CPython 3.2. +workaround: Use ``errno.EOPNOTSUPP`` in place of ``errno.ENOTSUP``. +""" + +import errno + +print(f"{errno.errorcode[errno.EOPNOTSUPP]=!s}") diff --git a/tests/cpydiff/modules_json_nonserializable.py b/tests/cpydiff/modules_json_nonserializable.py index ffe523786f501..d83e7beca2d5a 100644 --- a/tests/cpydiff/modules_json_nonserializable.py +++ b/tests/cpydiff/modules_json_nonserializable.py @@ -4,12 +4,10 @@ cause: Unknown workaround: Unknown """ + import json -a = bytes(x for x in range(256)) try: - z = json.dumps(a) - x = json.loads(z) - print("Should not get here") + print(json.dumps(b"shouldn't be able to serialise bytes")) except TypeError: print("TypeError") diff --git a/tests/cpydiff/modules_os_environ.py b/tests/cpydiff/modules_os_environ.py index 491d8a3101636..4edde16656781 100644 --- a/tests/cpydiff/modules_os_environ.py +++ b/tests/cpydiff/modules_os_environ.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Use ``getenv``, ``putenv`` and ``unsetenv`` """ + import os try: diff --git a/tests/cpydiff/modules_os_getenv.py b/tests/cpydiff/modules_os_getenv.py index d1e828438e456..d5acd414eb3da 100644 --- a/tests/cpydiff/modules_os_getenv.py +++ b/tests/cpydiff/modules_os_getenv.py @@ -4,6 +4,7 @@ cause: The ``environ`` attribute is not implemented workaround: Unknown """ + import os print(os.getenv("NEW_VARIABLE")) diff --git a/tests/cpydiff/modules_struct_fewargs.py b/tests/cpydiff/modules_struct_fewargs.py index cb6b0fd874ec4..f6346a67938ed 100644 --- a/tests/cpydiff/modules_struct_fewargs.py +++ b/tests/cpydiff/modules_struct_fewargs.py @@ -1,9 +1,10 @@ """ categories: Modules,struct -description: Struct pack with too few args, not checked by uPy +description: Struct pack with too few args, not checked by MicroPython cause: Unknown workaround: Unknown """ + import struct try: diff --git a/tests/cpydiff/modules_struct_manyargs.py b/tests/cpydiff/modules_struct_manyargs.py index 03395baad3b59..b2ea93b6c9330 100644 --- a/tests/cpydiff/modules_struct_manyargs.py +++ b/tests/cpydiff/modules_struct_manyargs.py @@ -1,9 +1,10 @@ """ categories: Modules,struct -description: Struct pack with too many args, not checked by uPy +description: Struct pack with too many args, not checked by MicroPython cause: Unknown workaround: Unknown """ + import struct try: diff --git a/tests/cpydiff/modules_struct_whitespace_in_format.py b/tests/cpydiff/modules_struct_whitespace_in_format.py index a882b38569a95..8b609425eb01c 100644 --- a/tests/cpydiff/modules_struct_whitespace_in_format.py +++ b/tests/cpydiff/modules_struct_whitespace_in_format.py @@ -1,9 +1,10 @@ """ categories: Modules,struct -description: Struct pack with whitespace in format, whitespace ignored by CPython, error on uPy +description: Struct pack with whitespace in format, whitespace ignored by CPython, error on MicroPython cause: MicroPython is optimised for code size. workaround: Don't use spaces in format strings. """ + import struct try: diff --git a/tests/cpydiff/modules_sys_stdassign.py b/tests/cpydiff/modules_sys_stdassign.py index 7d086078a93d6..29afe1b1203c9 100644 --- a/tests/cpydiff/modules_sys_stdassign.py +++ b/tests/cpydiff/modules_sys_stdassign.py @@ -4,6 +4,7 @@ cause: They are stored in read-only memory. workaround: Unknown """ + import sys sys.stdin = None diff --git a/tests/cpydiff/syntax_arg_unpacking.py b/tests/cpydiff/syntax_arg_unpacking.py index e54832ddb9165..7133a8a28272c 100644 --- a/tests/cpydiff/syntax_arg_unpacking.py +++ b/tests/cpydiff/syntax_arg_unpacking.py @@ -1,5 +1,5 @@ """ -categories: Syntax +categories: Syntax,Unpacking description: Argument unpacking does not work if the argument being unpacked is the nth or greater argument where n is the number of bits in an MP_SMALL_INT. cause: The implementation uses an MP_SMALL_INT to flag args that need to be unpacked. workaround: Use fewer arguments. diff --git a/tests/cpydiff/syntax_assign_expr.py b/tests/cpydiff/syntax_assign_expr.py index d4ed063b39ae7..704c5c3ecab37 100644 --- a/tests/cpydiff/syntax_assign_expr.py +++ b/tests/cpydiff/syntax_assign_expr.py @@ -1,7 +1,8 @@ """ categories: Syntax,Operators -description: MicroPython allows using := to assign to the variable of a comprehension, CPython raises a SyntaxError. -cause: MicroPython is optimised for code size and doesn't check this case. -workaround: Do not rely on this behaviour if writing CPython compatible code. +description: MicroPython allows := to assign to the iteration variable in nested comprehensions, CPython does not. +cause: MicroPython is optimised for code size. Although it is a syntax error to assign to the iteration variable in a standard comprehension (same as CPython), it doesn't check if an inner nested comprehension assigns to the iteration variable of the outer comprehension. +workaround: Do not use := to assign to the iteration variable of a comprehension. """ -print([i := -1 for i in range(4)]) + +print([[(j := i) for i in range(2)] for j in range(2)]) diff --git a/tests/cpydiff/syntax_literal_underscore.py b/tests/cpydiff/syntax_literal_underscore.py new file mode 100644 index 0000000000000..4b1406e9f3f71 --- /dev/null +++ b/tests/cpydiff/syntax_literal_underscore.py @@ -0,0 +1,19 @@ +""" +categories: Syntax,Literals +description: MicroPython accepts underscores in numeric literals where CPython doesn't +cause: Different parser implementation + +MicroPython's tokenizer ignores underscores in numeric literals, while CPython +rejects multiple consecutive underscores and underscores after the last digit. + +workaround: Remove the underscores not accepted by CPython. +""" + +try: + print(eval("1__1")) +except SyntaxError: + print("Should not work") +try: + print(eval("1_")) +except SyntaxError: + print("Should not work") diff --git a/tests/cpydiff/syntax_spaces.py b/tests/cpydiff/syntax_spaces.py index c308240a78da5..670cefdeac23e 100644 --- a/tests/cpydiff/syntax_spaces.py +++ b/tests/cpydiff/syntax_spaces.py @@ -1,9 +1,17 @@ """ -categories: Syntax,Spaces -description: uPy requires spaces between literal numbers and keywords, CPy doesn't -cause: Unknown -workaround: Unknown +categories: Syntax,Literals +description: MicroPython requires spaces between literal numbers and keywords or ".", CPython doesn't +cause: Different parser implementation + +MicroPython's tokenizer treats a sequence like ``1and`` as a single token, while CPython treats it as two tokens. + +Since CPython 3.11, when the literal number is followed by a token, this syntax causes a ``SyntaxWarning`` for an "invalid literal". When a literal number is followed by a "." denoting attribute access, CPython does not warn. + +workaround: Add a space between the integer literal and the intended next token. + +This also fixes the ``SyntaxWarning`` in CPython. """ + try: print(eval("1and 0")) except SyntaxError: @@ -16,3 +24,7 @@ print(eval("1if 1else 0")) except SyntaxError: print("Should have worked") +try: + print(eval("0x1.to_bytes(1)")) +except SyntaxError: + print("Should have worked") diff --git a/tests/cpydiff/syntax_unicode_nameesc.py b/tests/cpydiff/syntax_unicode_nameesc.py index 21628c974d80f..838394b6ebd09 100644 --- a/tests/cpydiff/syntax_unicode_nameesc.py +++ b/tests/cpydiff/syntax_unicode_nameesc.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Unknown """ + print("\N{LATIN SMALL LETTER A}") diff --git a/tests/cpydiff/types_bytearray_sliceassign.py b/tests/cpydiff/types_bytearray_sliceassign.py index e4068b04b988b..353f61988fa04 100644 --- a/tests/cpydiff/types_bytearray_sliceassign.py +++ b/tests/cpydiff/types_bytearray_sliceassign.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + b = bytearray(4) b[0:1] = [1, 2] print(b) diff --git a/tests/cpydiff/types_bytes_format.py b/tests/cpydiff/types_bytes_format.py index ad0498771165c..1a15e572c8ade 100644 --- a/tests/cpydiff/types_bytes_format.py +++ b/tests/cpydiff/types_bytes_format.py @@ -4,4 +4,5 @@ cause: MicroPython strives to be a more regular implementation, so if both `str` and `bytes` support ``__mod__()`` (the % operator), it makes sense to support ``format()`` for both too. Support for ``__mod__`` can also be compiled out, which leaves only ``format()`` for bytes formatting. workaround: If you are interested in CPython compatibility, don't use ``.format()`` on bytes objects. """ + print(b"{}".format(1)) diff --git a/tests/cpydiff/types_bytes_keywords.py b/tests/cpydiff/types_bytes_keywords.py index ade83d0a709eb..a459c94b41ed9 100644 --- a/tests/cpydiff/types_bytes_keywords.py +++ b/tests/cpydiff/types_bytes_keywords.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Pass the encoding as a positional parameter, e.g. ``print(bytes('abc', 'utf-8'))`` """ + print(bytes("abc", encoding="utf8")) diff --git a/tests/cpydiff/types_bytes_subscrstep.py b/tests/cpydiff/types_bytes_subscrstep.py index 51b94cb710f1c..c566cbdb630aa 100644 --- a/tests/cpydiff/types_bytes_subscrstep.py +++ b/tests/cpydiff/types_bytes_subscrstep.py @@ -4,4 +4,5 @@ cause: MicroPython is highly optimized for memory usage. workaround: Use explicit loop for this very rare operation. """ + print(b"123"[0:3:2]) diff --git a/tests/cpydiff/types_complex_parser.py b/tests/cpydiff/types_complex_parser.py new file mode 100644 index 0000000000000..4a012987d9e48 --- /dev/null +++ b/tests/cpydiff/types_complex_parser.py @@ -0,0 +1,14 @@ +""" +categories: Types,complex +description: MicroPython's complex() accepts certain incorrect values that CPython rejects +cause: MicroPython is highly optimized for memory usage. +workaround: Do not use non-standard complex literals as argument to complex() + +MicroPython's ``complex()`` function accepts literals that contain a space and +no sign between the real and imaginary parts, and interprets it as a plus. +""" + +try: + print(complex("1 1j")) +except ValueError: + print("ValueError") diff --git a/tests/cpydiff/types_dict_keys_set.py b/tests/cpydiff/types_dict_keys_set.py index 3a0849a35564c..a5f127962e6c2 100644 --- a/tests/cpydiff/types_dict_keys_set.py +++ b/tests/cpydiff/types_dict_keys_set.py @@ -4,4 +4,5 @@ cause: Not implemented. workaround: Explicitly convert keys to a set before using set operations. """ + print({1: 2, 3: 4}.keys() & {1}) diff --git a/tests/cpydiff/types_exception_attrs.py b/tests/cpydiff/types_exception_attrs.py index ad72b62a61a5d..5fed45451d2d9 100644 --- a/tests/cpydiff/types_exception_attrs.py +++ b/tests/cpydiff/types_exception_attrs.py @@ -4,6 +4,7 @@ cause: MicroPython is optimised to reduce code size. workaround: Only use ``value`` on ``StopIteration`` exceptions, and ``errno`` on ``OSError`` exceptions. Do not use or rely on these attributes on other exceptions. """ + e = Exception(1) print(e.value) print(e.errno) diff --git a/tests/cpydiff/types_exception_chaining.py b/tests/cpydiff/types_exception_chaining.py index 836c4eb3e73f5..cff68d4124aec 100644 --- a/tests/cpydiff/types_exception_chaining.py +++ b/tests/cpydiff/types_exception_chaining.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Unknown """ + try: raise TypeError except TypeError: diff --git a/tests/cpydiff/types_exception_instancevar.py b/tests/cpydiff/types_exception_instancevar.py index adc353361f015..fb67771baf33e 100644 --- a/tests/cpydiff/types_exception_instancevar.py +++ b/tests/cpydiff/types_exception_instancevar.py @@ -4,6 +4,7 @@ cause: MicroPython is highly optimized for memory usage. workaround: Use user-defined exception subclasses. """ + e = Exception() e.x = 0 print(e.x) diff --git a/tests/cpydiff/types_exception_loops.py b/tests/cpydiff/types_exception_loops.py index 8d326cbbbb000..549f1dd0a5bf0 100644 --- a/tests/cpydiff/types_exception_loops.py +++ b/tests/cpydiff/types_exception_loops.py @@ -4,6 +4,7 @@ cause: Condition checks are optimized to happen at the end of loop body, and that line number is reported. workaround: Unknown """ + l = ["-foo", "-bar"] i = 0 diff --git a/tests/cpydiff/types_float_implicit_conversion.py b/tests/cpydiff/types_float_implicit_conversion.py index 3726839fac6d1..764c9e4e6ed7a 100644 --- a/tests/cpydiff/types_float_implicit_conversion.py +++ b/tests/cpydiff/types_float_implicit_conversion.py @@ -1,6 +1,6 @@ """ categories: Types,float -description: uPy allows implicit conversion of objects in maths operations while CPython does not. +description: MicroPython allows implicit conversion of objects in maths operations while CPython does not. cause: Unknown workaround: Objects should be wrapped in ``float(obj)`` for compatibility with CPython. """ diff --git a/tests/cpydiff/types_float_rounding.py b/tests/cpydiff/types_float_rounding.py deleted file mode 100644 index a5b591966b0de..0000000000000 --- a/tests/cpydiff/types_float_rounding.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -categories: Types,float -description: uPy and CPython outputs formats may differ -cause: Unknown -workaround: Unknown -""" -print("%.1g" % -9.9) diff --git a/tests/cpydiff/types_int_to_bytes.py b/tests/cpydiff/types_int_to_bytes.py new file mode 100644 index 0000000000000..6530a2a32ecb7 --- /dev/null +++ b/tests/cpydiff/types_int_to_bytes.py @@ -0,0 +1,16 @@ +""" +categories: Types,int +description: ``to_bytes`` method doesn't implement signed parameter. +cause: The ``signed`` keyword-only parameter is not implemented for ``int.to_bytes()``. + +When the integer is negative, MicroPython behaves the same as CPython ``int.to_bytes(..., signed=True)`` + +When the integer is non-negative, MicroPython behaves the same as CPython ``int.to_bytes(..., signed=False)``. + +(The difference is subtle, but in CPython a positive integer converted with ``signed=True`` may require one byte more in the output length, in order to fit the 0 sign bit.) + +workaround: Take care when calling ``to_bytes()`` on an integer value which may be negative. +""" + +x = -1 +print(x.to_bytes(1, "big")) diff --git a/tests/cpydiff/types_list_delete_subscrstep.py b/tests/cpydiff/types_list_delete_subscrstep.py index 36e6f526b3d23..3c801d84949e0 100644 --- a/tests/cpydiff/types_list_delete_subscrstep.py +++ b/tests/cpydiff/types_list_delete_subscrstep.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Use explicit loop for this rare operation. """ + l = [1, 2, 3, 4] del l[0:4:2] print(l) diff --git a/tests/cpydiff/types_list_store_noniter.py b/tests/cpydiff/types_list_store_noniter.py index 1d69b4a823188..581b1369801ac 100644 --- a/tests/cpydiff/types_list_store_noniter.py +++ b/tests/cpydiff/types_list_store_noniter.py @@ -4,6 +4,7 @@ cause: RHS is restricted to be a tuple or list workaround: Use ``list()`` on RHS to convert the iterable to a list """ + l = [10, 20] l[0:1] = range(4) print(l) diff --git a/tests/cpydiff/types_list_store_subscrstep.py b/tests/cpydiff/types_list_store_subscrstep.py index 1460372bb1754..97590267f4a64 100644 --- a/tests/cpydiff/types_list_store_subscrstep.py +++ b/tests/cpydiff/types_list_store_subscrstep.py @@ -4,6 +4,7 @@ cause: Unknown workaround: Use explicit loop for this rare operation. """ + l = [1, 2, 3, 4] l[0:4:2] = [5, 6] print(l) diff --git a/tests/cpydiff/types_memoryview_invalid.py b/tests/cpydiff/types_memoryview_invalid.py new file mode 100644 index 0000000000000..f288c50ab57b7 --- /dev/null +++ b/tests/cpydiff/types_memoryview_invalid.py @@ -0,0 +1,13 @@ +""" +categories: Types,memoryview +description: memoryview can become invalid if its target is resized +cause: CPython prevents a ``bytearray`` or ``io.bytesIO`` object from changing size while there is a ``memoryview`` object that references it. MicroPython requires the programmer to manually ensure that an object is not resized while any ``memoryview`` references it. + +In the worst case scenario, resizing an object which is the target of a memoryview can cause the memoryview(s) to reference invalid freed memory (a use-after-free bug) and corrupt the MicroPython runtime. +workaround: Do not change the size of any ``bytearray`` or ``io.bytesIO`` object that has a ``memoryview`` assigned to it. +""" + +b = bytearray(b"abcdefg") +m = memoryview(b) +b.extend(b"hijklmnop") +print(b, bytes(m)) diff --git a/tests/cpydiff/types_oserror_errnomap.py b/tests/cpydiff/types_oserror_errnomap.py new file mode 100644 index 0000000000000..6627bd2af4ab7 --- /dev/null +++ b/tests/cpydiff/types_oserror_errnomap.py @@ -0,0 +1,48 @@ +""" +categories: Types,OSError +description: OSError constructor returns a plain OSError for all errno values, rather than a relevant subtype. +cause: MicroPython does not include the CPython-standard OSError subclasses. +workaround: Catch OSError and use its errno attribute to discriminate the cause. +""" + +import errno + +errno_list = [ # i.e. the set implemented by micropython + errno.EPERM, + errno.ENOENT, + errno.EIO, + errno.EBADF, + errno.EAGAIN, + errno.ENOMEM, + errno.EACCES, + errno.EEXIST, + errno.ENODEV, + errno.EISDIR, + errno.EINVAL, + errno.EOPNOTSUPP, + errno.EADDRINUSE, + errno.ECONNABORTED, + errno.ECONNRESET, + errno.ENOBUFS, + errno.ENOTCONN, + errno.ETIMEDOUT, + errno.ECONNREFUSED, + errno.EHOSTUNREACH, + errno.EALREADY, + errno.EINPROGRESS, +] + + +def errno_output_type(n): + try: + raise OSError(n, "") + except OSError as e: + return f"{type(e).__name__}" + except Exception as e: + return f"non-OSError {type(e).__name__}" + else: + return "no error" + + +for n in errno_list: + print(errno.errorcode[n], "=", errno_output_type(n)) diff --git a/tests/cpydiff/types_range_limits.py b/tests/cpydiff/types_range_limits.py new file mode 100644 index 0000000000000..e53d5fd4088f3 --- /dev/null +++ b/tests/cpydiff/types_range_limits.py @@ -0,0 +1,26 @@ +""" +categories: Types,range +description: Range objects with large start or stop arguments misbehave. +cause: Intermediate calculations overflow the C mp_int_t type +workaround: Avoid using such ranges +""" + +from sys import maxsize + +# A range including `maxsize-1` cannot be created +try: + print(range(-maxsize - 1, 0)) +except OverflowError: + print("OverflowError") + +# A range with `stop-start` exceeding sys.maxsize has incorrect len(), while CPython cannot calculate len(). +try: + print(len(range(-maxsize, maxsize))) +except OverflowError: + print("OverflowError") + +# A range with `stop-start` exceeding sys.maxsize has incorrect len() +try: + print(len(range(-maxsize, maxsize, maxsize))) +except OverflowError: + print("OverflowError") diff --git a/tests/cpydiff/types_str_endswith.py b/tests/cpydiff/types_str_endswith.py deleted file mode 100644 index f222ac1cd3ad3..0000000000000 --- a/tests/cpydiff/types_str_endswith.py +++ /dev/null @@ -1,7 +0,0 @@ -""" -categories: Types,str -description: Start/end indices such as str.endswith(s, start) not implemented -cause: Unknown -workaround: Unknown -""" -print("abc".endswith("c", 1)) diff --git a/tests/cpydiff/types_str_formatsep.py b/tests/cpydiff/types_str_formatsep.py new file mode 100644 index 0000000000000..05d0b8d3d2cf4 --- /dev/null +++ b/tests/cpydiff/types_str_formatsep.py @@ -0,0 +1,19 @@ +""" +categories: Types,str +description: MicroPython accepts the "," grouping option with any radix, unlike CPython +cause: To reduce code size, MicroPython does not issue an error for this combination +workaround: Do not use a format string like ``{:,b}`` if CPython compatibility is required. +""" + +try: + print("{:,b}".format(99)) +except ValueError: + print("ValueError") +try: + print("{:,x}".format(99)) +except ValueError: + print("ValueError") +try: + print("{:,o}".format(99)) +except ValueError: + print("ValueError") diff --git a/tests/cpydiff/types_str_formatsep_float.py b/tests/cpydiff/types_str_formatsep_float.py new file mode 100644 index 0000000000000..b487cd3758e73 --- /dev/null +++ b/tests/cpydiff/types_str_formatsep_float.py @@ -0,0 +1,11 @@ +""" +categories: Types,str +description: MicroPython accepts but does not properly implement the "," or "_" grouping character for float values +cause: To reduce code size, MicroPython does not implement this combination. Grouping characters will not appear in the number's significant digits and will appear at incorrect locations in leading zeros. +workaround: Do not use a format string like ``{:,f}`` if exact CPython compatibility is required. +""" + +print("{:,f}".format(3141.159)) +print("{:_f}".format(3141.159)) +print("{:011,.2f}".format(3141.159)) +print("{:011_.2f}".format(3141.159)) diff --git a/tests/cpydiff/types_str_formatsubscr.py b/tests/cpydiff/types_str_formatsubscr.py index 1b83cfff6cd34..5c59a1d200a9b 100644 --- a/tests/cpydiff/types_str_formatsubscr.py +++ b/tests/cpydiff/types_str_formatsubscr.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Unknown """ + print("{a[0]}".format(a=[1, 2])) diff --git a/tests/cpydiff/types_str_keywords.py b/tests/cpydiff/types_str_keywords.py index 77a4eac1c1db2..640dfa6c39132 100644 --- a/tests/cpydiff/types_str_keywords.py +++ b/tests/cpydiff/types_str_keywords.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Input the encoding format directly. eg ``print(bytes('abc', 'utf-8'))`` """ + print(str(b"abc", encoding="utf8")) diff --git a/tests/cpydiff/types_str_ljust_rjust.py b/tests/cpydiff/types_str_ljust_rjust.py index 72e5105e025b2..7f91c137e905f 100644 --- a/tests/cpydiff/types_str_ljust_rjust.py +++ b/tests/cpydiff/types_str_ljust_rjust.py @@ -4,4 +4,5 @@ cause: MicroPython is highly optimized for memory usage. Easy workarounds available. workaround: Instead of ``s.ljust(10)`` use ``"%-10s" % s``, instead of ``s.rjust(10)`` use ``"% 10s" % s``. Alternatively, ``"{:<10}".format(s)`` or ``"{:>10}".format(s)``. """ + print("abc".ljust(10)) diff --git a/tests/cpydiff/types_str_rsplitnone.py b/tests/cpydiff/types_str_rsplitnone.py index 5d334fea2f846..ae524620a08a8 100644 --- a/tests/cpydiff/types_str_rsplitnone.py +++ b/tests/cpydiff/types_str_rsplitnone.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Unknown """ + print("a a a".rsplit(None, 1)) diff --git a/tests/cpydiff/types_str_subscrstep.py b/tests/cpydiff/types_str_subscrstep.py index 2d3245e5582f5..cd57f18ccb345 100644 --- a/tests/cpydiff/types_str_subscrstep.py +++ b/tests/cpydiff/types_str_subscrstep.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Unknown """ + print("abcdefghi"[0:9:2]) diff --git a/tests/cpydiff/types_tuple_subscrstep.py b/tests/cpydiff/types_tuple_subscrstep.py index f90f3c5bf4d16..60ba31af4cf74 100644 --- a/tests/cpydiff/types_tuple_subscrstep.py +++ b/tests/cpydiff/types_tuple_subscrstep.py @@ -4,4 +4,5 @@ cause: Unknown workaround: Unknown """ + print((1, 2, 3, 4)[0:4:2]) diff --git a/tests/extmod/asyncio_await_return.py b/tests/extmod/asyncio_await_return.py index be6b3f4f11b00..0e74fc1f26226 100644 --- a/tests/extmod/asyncio_await_return.py +++ b/tests/extmod/asyncio_await_return.py @@ -13,7 +13,10 @@ async def foo(): # CIRCUITPY-CHANGE: await try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_await_return.py.exp b/tests/extmod/asyncio_await_return.py.exp deleted file mode 100644 index daaac9e303029..0000000000000 --- a/tests/extmod/asyncio_await_return.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -42 -42 diff --git a/tests/extmod/asyncio_basic.py b/tests/extmod/asyncio_basic.py index bdc4f613335cb..411a5e28b44a5 100644 --- a/tests/extmod/asyncio_basic.py +++ b/tests/extmod/asyncio_basic.py @@ -11,7 +11,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_basic.py.exp b/tests/extmod/asyncio_basic.py.exp deleted file mode 100644 index 478e22abc8ff6..0000000000000 --- a/tests/extmod/asyncio_basic.py.exp +++ /dev/null @@ -1,6 +0,0 @@ -start -after sleep -short -long -negative -took 200 400 0 diff --git a/tests/extmod/asyncio_basic2.py.exp b/tests/extmod/asyncio_basic2.py.exp deleted file mode 100644 index 3ca3521728d44..0000000000000 --- a/tests/extmod/asyncio_basic2.py.exp +++ /dev/null @@ -1,4 +0,0 @@ -main start -forever start -main done -42 diff --git a/tests/extmod/asyncio_cancel_fair.py.exp b/tests/extmod/asyncio_cancel_fair.py.exp deleted file mode 100644 index 8f5da08e4ced4..0000000000000 --- a/tests/extmod/asyncio_cancel_fair.py.exp +++ /dev/null @@ -1,24 +0,0 @@ -start 0 -start 1 -start 2 -done 0 -0 cancels 1 -start 0 -cancelled 1 -1 cancels 0 -start 1 -done 2 -start 2 -cancelled 0 -0 cancels 1 -start 0 -cancelled 1 -1 cancels 0 -start 1 -done 2 -start 2 -cancelled 0 -0 cancels 1 -cancelled 1 -1 cancels 0 -done 2 diff --git a/tests/extmod/asyncio_cancel_fair2.py.exp b/tests/extmod/asyncio_cancel_fair2.py.exp deleted file mode 100644 index e9dd649b453f9..0000000000000 --- a/tests/extmod/asyncio_cancel_fair2.py.exp +++ /dev/null @@ -1,8 +0,0 @@ -sleep a -sleep b 0 -sleep b 1 -sleep b 2 -cancelled a -done b 0 -done b 1 -done b 2 diff --git a/tests/extmod/asyncio_cancel_task.py.exp b/tests/extmod/asyncio_cancel_task.py.exp deleted file mode 100644 index 031b94023fd03..0000000000000 --- a/tests/extmod/asyncio_cancel_task.py.exp +++ /dev/null @@ -1,31 +0,0 @@ -True -task start -True -main sleep -task cancel -task start -True -True -True -True -main sleep -task cancel -main wait -main got CancelledError -task start -task done -False ----- -task 2 -task start -main cancel -main sleep -task cancel -task 2 cancel ----- -task 2 -task start -main cancel -main sleep -task cancel -task 2 done diff --git a/tests/extmod/asyncio_cancel_wait_on_finished.py.exp b/tests/extmod/asyncio_cancel_wait_on_finished.py.exp deleted file mode 100644 index 60e871bfe56f0..0000000000000 --- a/tests/extmod/asyncio_cancel_wait_on_finished.py.exp +++ /dev/null @@ -1,7 +0,0 @@ -main sleep -sleep_task sleep -wait_task wait -main sleep -sleep_task wake -main wait -CancelledError() diff --git a/tests/extmod/asyncio_current_task.py b/tests/extmod/asyncio_current_task.py index 18058230f2d90..a25e543d0c5b1 100644 --- a/tests/extmod/asyncio_current_task.py +++ b/tests/extmod/asyncio_current_task.py @@ -19,4 +19,15 @@ async def main(): print(t is result[0]) +try: + print(asyncio.current_task()) +except RuntimeError: + print("RuntimeError") + + asyncio.run(main()) + +try: + print(asyncio.current_task()) +except RuntimeError: + print("RuntimeError") diff --git a/tests/extmod/asyncio_current_task.py.exp b/tests/extmod/asyncio_current_task.py.exp deleted file mode 100644 index 0ca95142bb715..0000000000000 --- a/tests/extmod/asyncio_current_task.py.exp +++ /dev/null @@ -1 +0,0 @@ -True diff --git a/tests/extmod/asyncio_event.py.exp b/tests/extmod/asyncio_event.py.exp deleted file mode 100644 index 3188f291e584d..0000000000000 --- a/tests/extmod/asyncio_event.py.exp +++ /dev/null @@ -1,33 +0,0 @@ -False -True -False ----- -yield -start 1 -start 2 -set event -yield -True -end 1 -True -end 2 ----- -yield -start 3 -True -end 3 ----- -clear event -start 4 -set event -True -end 4 ----- -start 5 ----- -start 6 ----- -set event ----- -TimeoutError -set event diff --git a/tests/extmod/asyncio_event_fair.py b/tests/extmod/asyncio_event_fair.py index d8f398dbcb751..b878cabfe1b64 100644 --- a/tests/extmod/asyncio_event_fair.py +++ b/tests/extmod/asyncio_event_fair.py @@ -14,7 +14,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_event_fair.py.exp b/tests/extmod/asyncio_event_fair.py.exp deleted file mode 100644 index fe2e3d6e47a63..0000000000000 --- a/tests/extmod/asyncio_event_fair.py.exp +++ /dev/null @@ -1,16 +0,0 @@ -sleep 0 -wait 2 -sleep 1 -wait 3 -sleep 0 -sleep 1 -wait 2 -sleep 0 -sleep 1 -wait 3 -sleep 0 -sleep 1 -wait 2 -wait 3 -wait 2 -wait 3 diff --git a/tests/extmod/asyncio_event_queue.py b/tests/extmod/asyncio_event_queue.py new file mode 100644 index 0000000000000..e0125b1aefe13 --- /dev/null +++ b/tests/extmod/asyncio_event_queue.py @@ -0,0 +1,64 @@ +# Ensure that an asyncio task can wait on an Event when the +# _task_queue is empty +# https://github.com/micropython/micropython/issues/16569 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + +# This test requires checking that the asyncio scheduler +# remains active "indefinitely" when the task queue is empty. +# +# To check this, we need another independent scheduler that +# can wait for a certain amount of time. So we have to +# create one using micropython.schedule() and time.ticks_ms() +# +# Technically, this code breaks the rules, as it is clearly +# documented that Event.set() should _NOT_ be called from a +# schedule (soft IRQ) because in some cases, a race condition +# can occur, resulting in a crash. However: +# - since the risk of a race condition in that specific +# case has been analysed and excluded +# - given that there is no other simple alternative to +# write this test case, +# an exception to the rule was deemed acceptable. See +# https://github.com/micropython/micropython/pull/16772 + +import micropython, time + +try: + micropython.schedule +except AttributeError: + print("SKIP") + raise SystemExit + + +evt = asyncio.Event() + + +def schedule_watchdog(end_ticks): + if time.ticks_diff(end_ticks, time.ticks_ms()) <= 0: + print("asyncio still pending, unlocking event") + # Caution: about to call Event.set() from a schedule + # (see the note in the comment above) + evt.set() + return + micropython.schedule(schedule_watchdog, end_ticks) + + +async def foo(): + print("foo waiting") + schedule_watchdog(time.ticks_add(time.ticks_ms(), 100)) + await evt.wait() + print("foo done") + + +async def main(): + print("main started") + await foo() + print("main done") + + +asyncio.run(main()) diff --git a/tests/extmod/asyncio_event_queue.py.exp b/tests/extmod/asyncio_event_queue.py.exp new file mode 100644 index 0000000000000..ee42c96d83ed8 --- /dev/null +++ b/tests/extmod/asyncio_event_queue.py.exp @@ -0,0 +1,5 @@ +main started +foo waiting +asyncio still pending, unlocking event +foo done +main done diff --git a/tests/extmod/asyncio_exception.py.exp b/tests/extmod/asyncio_exception.py.exp deleted file mode 100644 index b2ee860170ece..0000000000000 --- a/tests/extmod/asyncio_exception.py.exp +++ /dev/null @@ -1,7 +0,0 @@ -main start -ValueError 1 -main start -task start -ValueError 2 -main start -ValueError 3 diff --git a/tests/extmod/asyncio_fair.py b/tests/extmod/asyncio_fair.py index 43076fef1d707..3e3ac04735898 100644 --- a/tests/extmod/asyncio_fair.py +++ b/tests/extmod/asyncio_fair.py @@ -20,7 +20,7 @@ async def main(): t2 = asyncio.create_task(task(2, 0.1)) t3 = asyncio.create_task(task(3, 0.18)) t4 = asyncio.create_task(task(4, -100)) - await asyncio.sleep(0.5) + await asyncio.sleep(0.45) # t2 prints 5 times, t3 prints 3 times t1.cancel() t2.cancel() t3.cancel() diff --git a/tests/extmod/asyncio_fair.py.exp b/tests/extmod/asyncio_fair.py.exp deleted file mode 100644 index b4b6481db019f..0000000000000 --- a/tests/extmod/asyncio_fair.py.exp +++ /dev/null @@ -1,13 +0,0 @@ -task start 1 -task start 2 -task work 2 -task start 3 -task work 3 -task start 4 -task work 2 -task work 3 -task work 2 -task work 2 -task work 3 -task work 2 -finish diff --git a/tests/extmod/asyncio_gather.py b/tests/extmod/asyncio_gather.py index bb16db381f8c9..3095af203187b 100644 --- a/tests/extmod/asyncio_gather.py +++ b/tests/extmod/asyncio_gather.py @@ -13,7 +13,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_gather_notimpl.py b/tests/extmod/asyncio_gather_notimpl.py index 5e4cc44a4a3b5..be1b974a69a46 100644 --- a/tests/extmod/asyncio_gather_notimpl.py +++ b/tests/extmod/asyncio_gather_notimpl.py @@ -13,7 +13,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_heaplock.py b/tests/extmod/asyncio_heaplock.py index 8326443f0e6c5..9e9908de1cb6a 100644 --- a/tests/extmod/asyncio_heaplock.py +++ b/tests/extmod/asyncio_heaplock.py @@ -4,7 +4,11 @@ # - StreamWriter.write, stream is blocked and data to write is a bytes object # - StreamWriter.write, when stream is not blocked -import micropython +try: + import asyncio, micropython +except ImportError: + print("SKIP") + raise SystemExit # strict stackless builds can't call functions without allocating a frame on the heap try: @@ -24,12 +28,6 @@ def f(x): print("SKIP") raise SystemExit -try: - import asyncio -except ImportError: - print("SKIP") - raise SystemExit - class TestStream: def __init__(self, blocked): diff --git a/tests/extmod/asyncio_iterator_event.py b/tests/extmod/asyncio_iterator_event.py new file mode 100644 index 0000000000000..f61fefcf051be --- /dev/null +++ b/tests/extmod/asyncio_iterator_event.py @@ -0,0 +1,86 @@ +# Ensure that an asyncio task can wait on an Event when the +# _task_queue is empty, in the context of an async iterator +# https://github.com/micropython/micropython/issues/16318 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + +# This test requires checking that the asyncio scheduler +# remains active "indefinitely" when the task queue is empty. +# +# To check this, we need another independent scheduler that +# can wait for a certain amount of time. So we have to +# create one using micropython.schedule() and time.ticks_ms() +# +# Technically, this code breaks the rules, as it is clearly +# documented that Event.set() should _NOT_ be called from a +# schedule (soft IRQ) because in some cases, a race condition +# can occur, resulting in a crash. However: +# - since the risk of a race condition in that specific +# case has been analysed and excluded +# - given that there is no other simple alternative to +# write this test case, +# an exception to the rule was deemed acceptable. See +# https://github.com/micropython/micropython/pull/16772 + +import micropython, time + +try: + micropython.schedule +except AttributeError: + print("SKIP") + raise SystemExit + +ai = None + + +def schedule_watchdog(end_ticks): + if time.ticks_diff(end_ticks, time.ticks_ms()) <= 0: + print("good: asyncio iterator is still pending, exiting") + # Caution: ai.fetch_data() will invoke Event.set() + # (see the note in the comment above) + ai.fetch_data(None) + return + micropython.schedule(schedule_watchdog, end_ticks) + + +async def test(ai): + for x in range(3): + await asyncio.sleep(0.1) + ai.fetch_data("bar {}".format(x)) + + +class AsyncIterable: + def __init__(self): + self.message = None + self.evt = asyncio.Event() + + def __aiter__(self): + return self + + async def __anext__(self): + await self.evt.wait() + self.evt.clear() + if self.message is None: + raise StopAsyncIteration + return self.message + + def fetch_data(self, message): + self.message = message + self.evt.set() + + +async def main(): + global ai + ai = AsyncIterable() + asyncio.create_task(test(ai)) + schedule_watchdog(time.ticks_add(time.ticks_ms(), 500)) + async for message in ai: + print(message) + print("end main") + + +asyncio.run(main()) diff --git a/tests/extmod/asyncio_iterator_event.py.exp b/tests/extmod/asyncio_iterator_event.py.exp new file mode 100644 index 0000000000000..a1893197d02ef --- /dev/null +++ b/tests/extmod/asyncio_iterator_event.py.exp @@ -0,0 +1,5 @@ +bar 0 +bar 1 +bar 2 +good: asyncio iterator is still pending, exiting +end main diff --git a/tests/extmod/asyncio_lock.py b/tests/extmod/asyncio_lock.py index f565adb03fc39..10d3285be0f86 100644 --- a/tests/extmod/asyncio_lock.py +++ b/tests/extmod/asyncio_lock.py @@ -1,4 +1,8 @@ # Test Lock class +# +# This test has a corresponding .exp file because it tests a very specific ordering of +# events when cancelling a task waiting on a lock, and that ordering should not change +# (even though it does match CPython's output). try: import asyncio diff --git a/tests/extmod/asyncio_lock.py.exp b/tests/extmod/asyncio_lock.py.exp deleted file mode 100644 index a37dfcbd2e519..0000000000000 --- a/tests/extmod/asyncio_lock.py.exp +++ /dev/null @@ -1,41 +0,0 @@ -False -True -False -have lock ----- -task start 1 -task start 2 -task start 3 -task have 1 0 -task have 2 0 -task have 3 0 -task have 1 1 -task have 2 1 -task have 3 1 -task have 1 2 -task end 1 -task have 2 2 -task end 2 -task have 3 2 -task end 3 ----- -task have True -task release False -task have True -task release False -task have again -task have again ----- -task got 0 -task release 0 -task cancel 1 -task got 2 -task release 2 -False ----- -task got 0 -task cancel 1 -task release 0 -task got 2 -task cancel 2 -False diff --git a/tests/extmod/asyncio_lock_cancel.py b/tests/extmod/asyncio_lock_cancel.py index 27fe108b0e1e8..63b2a29bcbce1 100644 --- a/tests/extmod/asyncio_lock_cancel.py +++ b/tests/extmod/asyncio_lock_cancel.py @@ -1,7 +1,7 @@ # Test that locks work when cancelling multiple waiters on the lock try: - import uasyncio as asyncio + import asyncio except ImportError: print("SKIP") raise SystemExit @@ -13,7 +13,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_lock_cancel.py.exp b/tests/extmod/asyncio_lock_cancel.py.exp deleted file mode 100644 index 49ae253887436..0000000000000 --- a/tests/extmod/asyncio_lock_cancel.py.exp +++ /dev/null @@ -1,11 +0,0 @@ -task 0 start -task 1 start -task 2 start -task 3 start -task 1 cancel -task 2 cancel -task 0 lock_flag False -task 0 done -task 3 lock_flag False -task 3 done -False diff --git a/tests/extmod/asyncio_loop_stop.py b/tests/extmod/asyncio_loop_stop.py index b4bd0c74ad90a..e2a4cdc1af853 100644 --- a/tests/extmod/asyncio_loop_stop.py +++ b/tests/extmod/asyncio_loop_stop.py @@ -34,7 +34,7 @@ async def main(): loop.stop() -loop = asyncio.get_event_loop() +loop = asyncio.new_event_loop() loop.create_task(main()) for i in range(3): diff --git a/tests/extmod/asyncio_loop_stop.py.exp b/tests/extmod/asyncio_loop_stop.py.exp deleted file mode 100644 index bada5f0d8412c..0000000000000 --- a/tests/extmod/asyncio_loop_stop.py.exp +++ /dev/null @@ -1,7 +0,0 @@ -run 0 -start -sleep -run 1 -run 2 -task -end diff --git a/tests/extmod/asyncio_micropython.py.exp b/tests/extmod/asyncio_micropython.py.exp index f5be1dc75a254..4d1c6d681f2f6 100644 --- a/tests/extmod/asyncio_micropython.py.exp +++ b/tests/extmod/asyncio_micropython.py.exp @@ -1,4 +1,5 @@ True +OverflowError task start 1 task end 1 2 diff --git a/tests/extmod/asyncio_new_event_loop.py b/tests/extmod/asyncio_new_event_loop.py index a3feb02126c70..3f05ffdd551d7 100644 --- a/tests/extmod/asyncio_new_event_loop.py +++ b/tests/extmod/asyncio_new_event_loop.py @@ -6,6 +6,21 @@ print("SKIP") raise SystemExit +# CPython 3.12 deprecated calling get_event_loop() when there is no current event +# loop, so to make this test run on CPython requires setting the event loop. +if hasattr(asyncio, "set_event_loop"): + asyncio.set_event_loop(asyncio.new_event_loop()) + + +def exception_handler(loop, context): + # This is a workaround for a difference between CPython and MicroPython: if + # a CPython event loop is closed while there are tasks pending (i.e. not finished) + # on it, then the task will log an error. MicroPython does not log this error. + if context.get("message", "") == "Task was destroyed but it is pending!": + pass + else: + loop.default_exception_handler(context) + async def task(): for i in range(4): @@ -17,17 +32,21 @@ async def task(): async def main(): print("start") loop.create_task(task()) - await asyncio.sleep(0) + await asyncio.sleep(0) # yields, meaning new task will run once print("stop") loop.stop() # Use default event loop to run some tasks loop = asyncio.get_event_loop() +loop.set_exception_handler(exception_handler) loop.create_task(main()) loop.run_forever() +loop.close() # Create new event loop, old one should not keep running loop = asyncio.new_event_loop() +loop.set_exception_handler(exception_handler) loop.create_task(main()) loop.run_forever() +loop.close() diff --git a/tests/extmod/asyncio_new_event_loop.py.exp b/tests/extmod/asyncio_new_event_loop.py.exp deleted file mode 100644 index 9e104fda39c94..0000000000000 --- a/tests/extmod/asyncio_new_event_loop.py.exp +++ /dev/null @@ -1,6 +0,0 @@ -start -task 0 -stop -start -task 0 -stop diff --git a/tests/extmod/asyncio_set_exception_handler.py b/tests/extmod/asyncio_set_exception_handler.py index 5935f0f4ebeaa..0ac4a624224ce 100644 --- a/tests/extmod/asyncio_set_exception_handler.py +++ b/tests/extmod/asyncio_set_exception_handler.py @@ -12,7 +12,7 @@ def custom_handler(loop, context): async def task(i): - # Raise with 2 args so exception prints the same in uPy and CPython + # Raise with 2 args so exception prints the same in MicroPython and CPython raise ValueError(i, i + 1) diff --git a/tests/extmod/asyncio_set_exception_handler.py.exp b/tests/extmod/asyncio_set_exception_handler.py.exp deleted file mode 100644 index fb4711469dc5b..0000000000000 --- a/tests/extmod/asyncio_set_exception_handler.py.exp +++ /dev/null @@ -1,9 +0,0 @@ -None -True -sleep -custom_handler ValueError(0, 1) -sleep -custom_handler ValueError(1, 2) -custom_handler ValueError(2, 3) -ValueError(3, 4) -done diff --git a/tests/extmod/asyncio_task_done.py.exp b/tests/extmod/asyncio_task_done.py.exp deleted file mode 100644 index ddda04c5ec43b..0000000000000 --- a/tests/extmod/asyncio_task_done.py.exp +++ /dev/null @@ -1,24 +0,0 @@ -========== -False -task start -task done -True -True -========== -False -task start -False -task done -True -========== -False -task start -True -ValueError() -True -========== -False -task start -False -ValueError() -True diff --git a/tests/extmod/asyncio_wait_for_fwd.py b/tests/extmod/asyncio_wait_for_fwd.py index fd7dc6ff3d3a5..9574678ed0923 100644 --- a/tests/extmod/asyncio_wait_for_fwd.py +++ b/tests/extmod/asyncio_wait_for_fwd.py @@ -13,7 +13,10 @@ async def foo(): try: - foo().__await__ + fooc = foo() + fooc.__await__ + # Avoid "coroutine was never awaited" warning + asyncio.run(fooc) except AttributeError: print("SKIP") raise SystemExit diff --git a/tests/extmod/asyncio_wait_for_linked_task.py b/tests/extmod/asyncio_wait_for_linked_task.py new file mode 100644 index 0000000000000..4dda62d5476c7 --- /dev/null +++ b/tests/extmod/asyncio_wait_for_linked_task.py @@ -0,0 +1,66 @@ +# Test asyncio.wait_for, with dependent tasks +# https://github.com/micropython/micropython/issues/16759 + +try: + import asyncio +except ImportError: + print("SKIP") + raise SystemExit + + +# CPython 3.12 deprecated calling get_event_loop() when there is no current event +# loop, so to make this test run on CPython requires setting the event loop. +if hasattr(asyncio, "set_event_loop"): + asyncio.set_event_loop(asyncio.new_event_loop()) + + +class Worker: + def __init__(self): + self._eventLoop = None + self._tasks = [] + + def launchTask(self, asyncJob): + if self._eventLoop is None: + self._eventLoop = asyncio.get_event_loop() + return self._eventLoop.create_task(asyncJob) + + async def job(self, prerequisite, taskName): + if prerequisite: + await prerequisite + await asyncio.sleep(0.1) + print(taskName, "work completed") + + def planTasks(self): + self._tasks.append(self.launchTask(self.job(None, "task0"))) + self._tasks.append(self.launchTask(self.job(self._tasks[0], "task1"))) + self._tasks.append(self.launchTask(self.job(self._tasks[1], "task2"))) + + async def waitForTask(self, taskIdx): + return await self._tasks[taskIdx] + + def syncWaitForTask(self, taskIdx): + return self._eventLoop.run_until_complete(self._tasks[taskIdx]) + + +async def async_test(): + print("--- async test") + worker = Worker() + worker.planTasks() + await worker.waitForTask(0) + print("-> task0 done") + await worker.waitForTask(2) + print("-> task2 done") + + +def sync_test(): + print("--- sync test") + worker = Worker() + worker.planTasks() + worker.syncWaitForTask(0) + print("-> task0 done") + worker.syncWaitForTask(2) + print("-> task2 done") + + +asyncio.get_event_loop().run_until_complete(async_test()) +sync_test() diff --git a/tests/extmod/asyncio_wait_task.py b/tests/extmod/asyncio_wait_task.py index bce426d971046..7d79104f8cf8f 100644 --- a/tests/extmod/asyncio_wait_task.py +++ b/tests/extmod/asyncio_wait_task.py @@ -68,5 +68,16 @@ async def main(): except ValueError: print("ValueError") + # Wait on a task that raises, but the waiting is done some time later. + # Need to suppress the "Task exception wasn't retrieved" message. + asyncio.get_event_loop().set_exception_handler(lambda loop, context: None) + t = asyncio.create_task(task_raise()) + for _ in range(5): + await asyncio.sleep(0) + try: + await t + except ValueError: + print("ValueError") + asyncio.run(main()) diff --git a/tests/extmod/asyncio_wait_task.py.exp b/tests/extmod/asyncio_wait_task.py.exp deleted file mode 100644 index 04be37f48406d..0000000000000 --- a/tests/extmod/asyncio_wait_task.py.exp +++ /dev/null @@ -1,10 +0,0 @@ -start -task 1 -task 2 ----- -start -hello -world -took 200 200 -task_raise -ValueError diff --git a/tests/extmod/binascii_hexlify.py b/tests/extmod/binascii_hexlify.py index d06029aabaffb..ae90b67336586 100644 --- a/tests/extmod/binascii_hexlify.py +++ b/tests/extmod/binascii_hexlify.py @@ -1,5 +1,5 @@ try: - import binascii + from binascii import hexlify except ImportError: print("SKIP") raise SystemExit @@ -10,10 +10,10 @@ b"\x7f\x80\xff", b"1234ABCDabcd", ): - print(binascii.hexlify(x)) + print(hexlify(x)) # Two-argument version (now supported in CPython) -print(binascii.hexlify(b"123", ":")) +print(hexlify(b"123", ":")) # zero length buffer -print(binascii.hexlify(b"", b":")) +print(hexlify(b"", b":")) diff --git a/tests/extmod/binascii_unhexlify.py b/tests/extmod/binascii_unhexlify.py index 731b6a2bd4d10..b08704cba65b2 100644 --- a/tests/extmod/binascii_unhexlify.py +++ b/tests/extmod/binascii_unhexlify.py @@ -1,5 +1,5 @@ try: - import binascii + from binascii import unhexlify except ImportError: print("SKIP") raise SystemExit @@ -10,18 +10,18 @@ b"7f80ff", b"313233344142434461626364", ): - print(binascii.unhexlify(x)) + print(unhexlify(x)) # CIRCUITPY-CHANGE # Unicode strings can be decoded -print(binascii.unhexlify("313233344142434461626364")) +print(unhexlify("313233344142434461626364")) try: - a = binascii.unhexlify(b"0") # odd buffer length + a = unhexlify(b"0") # odd buffer length except ValueError: print("ValueError") try: - a = binascii.unhexlify(b"gg") # digit not hex + a = unhexlify(b"gg") # digit not hex except ValueError: print("ValueError") diff --git a/tests/extmod/deflate_compress_memory_error.py b/tests/extmod/deflate_compress_memory_error.py new file mode 100644 index 0000000000000..19bef87bff3da --- /dev/null +++ b/tests/extmod/deflate_compress_memory_error.py @@ -0,0 +1,39 @@ +# Test deflate.DeflateIO compression, with out-of-memory errors. + +try: + # Check if deflate is available. + import deflate + import io +except ImportError: + print("SKIP") + raise SystemExit + +# Check if compression is enabled. +if not hasattr(deflate.DeflateIO, "write"): + print("SKIP") + raise SystemExit + +# Create a compressor object. +b = io.BytesIO() +g = deflate.DeflateIO(b, deflate.RAW, 15) + +# Then, use up most of the heap. +l = [] +while True: + try: + l.append(bytearray(1000)) + except: + break +l.pop() + +# Try to compress. This will try to allocate a large window and fail. +try: + g.write("test") +except MemoryError: + print("MemoryError") + +# Should still be able to close the stream. +g.close() + +# The underlying output stream should be unchanged. +print(b.getvalue()) diff --git a/tests/extmod/deflate_compress_memory_error.py.exp b/tests/extmod/deflate_compress_memory_error.py.exp new file mode 100644 index 0000000000000..606315c14604c --- /dev/null +++ b/tests/extmod/deflate_compress_memory_error.py.exp @@ -0,0 +1,2 @@ +MemoryError +b'' diff --git a/tests/extmod/framebuf_blit.py b/tests/extmod/framebuf_blit.py new file mode 100644 index 0000000000000..b1d98b330a838 --- /dev/null +++ b/tests/extmod/framebuf_blit.py @@ -0,0 +1,68 @@ +# Test FrameBuffer.blit method. + +try: + import framebuf +except ImportError: + print("SKIP") + raise SystemExit + + +def printbuf(): + print("--8<--") + for y in range(h): + for x in range(w): + print("%02x" % buf[(x + y * w)], end="") + print() + print("-->8--") + + +w = 5 +h = 4 +buf = bytearray(w * h) +fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.GS8) + +fbuf2 = framebuf.FrameBuffer(bytearray(4), 2, 2, framebuf.GS8) +fbuf2.fill(0xFF) + +# Blit another FrameBuffer, at various locations. +for x, y in ((-1, -1), (0, 0), (1, 1), (4, 3)): + fbuf.fill(0) + fbuf.blit(fbuf2, x, y) + printbuf() + +# Blit a bytes object. +fbuf.fill(0) +image = (b"\x10\x11\x12\x13", 2, 2, framebuf.GS8) +fbuf.blit(image, 1, 1) +printbuf() + +# Blit a bytes object that has a stride. +fbuf.fill(0) +image = (b"\x20\x21\xff\x22\x23\xff", 2, 2, framebuf.GS8, 3) +fbuf.blit(image, 1, 1) +printbuf() + +# Blit a bytes object with a bytes palette. +fbuf.fill(0) +image = (b"\x00\x01\x01\x00", 2, 2, framebuf.GS8) +palette = (b"\xa1\xa2", 2, 1, framebuf.GS8) +fbuf.blit(image, 1, 1, -1, palette) +printbuf() + +# Not enough elements in the tuple. +try: + fbuf.blit((0, 0, 0), 0, 0) +except ValueError: + print("ValueError") + +# Too many elements in the tuple. +try: + fbuf.blit((0, 0, 0, 0, 0, 0), 0, 0) +except ValueError: + print("ValueError") + +# Bytes too small. +try: + fbuf.blit((b"", 1, 1, framebuf.GS8), 0, 0) +except ValueError: + print("ValueError") diff --git a/tests/extmod/framebuf_blit.py.exp b/tests/extmod/framebuf_blit.py.exp new file mode 100644 index 0000000000000..e340f1990c783 --- /dev/null +++ b/tests/extmod/framebuf_blit.py.exp @@ -0,0 +1,45 @@ +--8<-- +ff00000000 +0000000000 +0000000000 +0000000000 +-->8-- +--8<-- +ffff000000 +ffff000000 +0000000000 +0000000000 +-->8-- +--8<-- +0000000000 +00ffff0000 +00ffff0000 +0000000000 +-->8-- +--8<-- +0000000000 +0000000000 +0000000000 +00000000ff +-->8-- +--8<-- +0000000000 +0010110000 +0012130000 +0000000000 +-->8-- +--8<-- +0000000000 +0020210000 +0022230000 +0000000000 +-->8-- +--8<-- +0000000000 +00a1a20000 +00a2a10000 +0000000000 +-->8-- +ValueError +ValueError +ValueError diff --git a/tests/extmod/hashlib_md5.py b/tests/extmod/hashlib_md5.py index 5f925fc97d02e..ebbe9155e0493 100644 --- a/tests/extmod/hashlib_md5.py +++ b/tests/extmod/hashlib_md5.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/hashlib_sha1.py b/tests/extmod/hashlib_sha1.py index af23033a591f2..46ffb73fcbe01 100644 --- a/tests/extmod/hashlib_sha1.py +++ b/tests/extmod/hashlib_sha1.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/hashlib_sha256.py b/tests/extmod/hashlib_sha256.py index 95cd301d160d0..209fcb3987792 100644 --- a/tests/extmod/hashlib_sha256.py +++ b/tests/extmod/hashlib_sha256.py @@ -1,8 +1,7 @@ try: import hashlib except ImportError: - # This is neither uPy, nor cPy, so must be uPy with - # hashlib module disabled. + # MicroPython with hashlib module disabled. print("SKIP") raise SystemExit diff --git a/tests/extmod/json_dump.py b/tests/extmod/json_dump.py index 897d33cc81253..0beb4f5f85698 100644 --- a/tests/extmod/json_dump.py +++ b/tests/extmod/json_dump.py @@ -16,11 +16,11 @@ # dump to a small-int not allowed try: json.dump(123, 1) -except (AttributeError, OSError): # CPython and uPy have different errors +except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") # dump to an object not allowed try: json.dump(123, {}) -except (AttributeError, OSError): # CPython and uPy have different errors +except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") diff --git a/tests/extmod/json_dump_iobase.py b/tests/extmod/json_dump_iobase.py index 94d317b87968f..81105e36dccec 100644 --- a/tests/extmod/json_dump_iobase.py +++ b/tests/extmod/json_dump_iobase.py @@ -18,7 +18,7 @@ def __init__(self): def write(self, buf): if type(buf) == bytearray: - # uPy passes a bytearray, CPython passes a str + # MicroPython passes a bytearray, CPython passes a str buf = str(buf, "ascii") self.buf += buf return len(buf) diff --git a/tests/extmod/json_dump_separators.py b/tests/extmod/json_dump_separators.py index 4f8e56dceb536..ce39294820fa9 100644 --- a/tests/extmod/json_dump_separators.py +++ b/tests/extmod/json_dump_separators.py @@ -25,20 +25,20 @@ # dump to a small-int not allowed try: json.dump(123, 1, separators=sep) - except (AttributeError, OSError): # CPython and uPy have different errors + except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") # dump to an object not allowed try: json.dump(123, {}, separators=sep) - except (AttributeError, OSError): # CPython and uPy have different errors + except (AttributeError, OSError): # CPython and MicroPython have different errors print("Exception") try: s = StringIO() json.dump(False, s, separators={"a": 1}) -except (TypeError, ValueError): # CPython and uPy have different errors +except (TypeError, ValueError): # CPython and MicroPython have different errors print("Exception") # invalid separator types diff --git a/tests/extmod/json_dumps_extra.py b/tests/extmod/json_dumps_extra.py index 9074416a99d93..70efc86645115 100644 --- a/tests/extmod/json_dumps_extra.py +++ b/tests/extmod/json_dumps_extra.py @@ -1,9 +1,6 @@ -# test uPy json behaviour that's not valid in CPy - -try: - import json -except ImportError: - print("SKIP") - raise SystemExit +# test MicroPython json behaviour that's not valid in CPy +# CIRCUITPY-CHANGE: This behavior matches CPython +print("SKIP") +raise SystemExit print(json.dumps(b"1234")) diff --git a/tests/extmod/json_dumps_separators.py b/tests/extmod/json_dumps_separators.py index a3a9ec308f09d..0a95f489a08ec 100644 --- a/tests/extmod/json_dumps_separators.py +++ b/tests/extmod/json_dumps_separators.py @@ -39,7 +39,7 @@ try: json.dumps(False, separators={"a": 1}) -except (TypeError, ValueError): # CPython and uPy have different errors +except (TypeError, ValueError): # CPython and MicroPython have different errors print("Exception") # invalid separator types diff --git a/tests/extmod/json_load_readinto.py b/tests/extmod/json_load_readinto.py index 25e5c6cc0cd36..740a21ef40e89 100644 --- a/tests/extmod/json_load_readinto.py +++ b/tests/extmod/json_load_readinto.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this file import json # Test that json can load from any object with readinto diff --git a/tests/extmod/json_loads.py b/tests/extmod/json_loads.py index f9073c121e2ef..092402d715d69 100644 --- a/tests/extmod/json_loads.py +++ b/tests/extmod/json_loads.py @@ -71,3 +71,27 @@ def my_print(o): my_print(json.loads("[null] a")) except ValueError: print("ValueError") + +# incomplete object declaration +try: + my_print(json.loads('{"a":0,')) +except ValueError: + print("ValueError") + +# incomplete nested array declaration +try: + my_print(json.loads('{"a":0, [')) +except ValueError: + print("ValueError") + +# incomplete array declaration +try: + my_print(json.loads("[0,")) +except ValueError: + print("ValueError") + +# incomplete nested object declaration +try: + my_print(json.loads('[0, {"a":0, ')) +except ValueError: + print("ValueError") diff --git a/tests/extmod/json_loads_bytes.py.exp b/tests/extmod/json_loads_bytes.py.exp deleted file mode 100644 index c2735a99052d2..0000000000000 --- a/tests/extmod/json_loads_bytes.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -[1, 2] -[None] diff --git a/tests/extmod/json_loads_int_64.py b/tests/extmod/json_loads_int_64.py new file mode 100644 index 0000000000000..f6236f1904a87 --- /dev/null +++ b/tests/extmod/json_loads_int_64.py @@ -0,0 +1,16 @@ +# Parse 64-bit integers from JSON payloads. +# +# This also exercises parsing integers from strings +# where the value may not be null terminated (last line) +try: + import json +except ImportError: + print("SKIP") + raise SystemExit + + +print(json.loads("9111222333444555666")) +print(json.loads("-9111222333444555666")) +print(json.loads("9111222333444555666")) +print(json.loads("-9111222333444555666")) +print(json.loads('["9111222333444555666777",9111222333444555666]')) diff --git a/tests/extmod/machine_hard_timer.py b/tests/extmod/machine_hard_timer.py new file mode 100644 index 0000000000000..8fe42ea850842 --- /dev/null +++ b/tests/extmod/machine_hard_timer.py @@ -0,0 +1,45 @@ +import sys + +try: + from machine import Timer + from time import sleep_ms +except: + print("SKIP") + raise SystemExit + +if sys.platform == "esp8266": + timer = Timer(0) +else: + # Hardware timers are not implemented. + print("SKIP") + raise SystemExit + +# Test both hard and soft IRQ handlers and both one-shot and periodic +# timers. We adjust period in tests/extmod/machine_soft_timer.py, so try +# adjusting freq here instead. The heap should be locked in hard callbacks +# and unlocked in soft callbacks. + + +def callback(t): + print("callback", mode[1], kind[1], freq, end=" ") + try: + allocate = bytearray(1) + print("unlocked") + except MemoryError: + print("locked") + + +modes = [(Timer.ONE_SHOT, "one-shot"), (Timer.PERIODIC, "periodic")] +kinds = [(False, "soft"), (True, "hard")] + +for mode in modes: + for kind in kinds: + for freq in 50, 25: + timer.init( + mode=mode[0], + freq=freq, + hard=kind[0], + callback=callback, + ) + sleep_ms(90) + timer.deinit() diff --git a/tests/extmod/machine_hard_timer.py.exp b/tests/extmod/machine_hard_timer.py.exp new file mode 100644 index 0000000000000..26cdc644fdd08 --- /dev/null +++ b/tests/extmod/machine_hard_timer.py.exp @@ -0,0 +1,16 @@ +callback one-shot soft 50 unlocked +callback one-shot soft 25 unlocked +callback one-shot hard 50 locked +callback one-shot hard 25 locked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 25 unlocked +callback periodic soft 25 unlocked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 25 locked +callback periodic hard 25 locked diff --git a/tests/extmod/machine_timer.py b/tests/extmod/machine_timer.py new file mode 100644 index 0000000000000..ef97ea4e94955 --- /dev/null +++ b/tests/extmod/machine_timer.py @@ -0,0 +1,48 @@ +import sys + +try: + from machine import Timer + from time import sleep_ms +except: + print("SKIP") + raise SystemExit + +if sys.platform in ("esp32", "esp8266", "nrf"): + # Software timers aren't implemented on the esp32 and esp8266 ports. + # The nrf port doesn't support selection of hard and soft callbacks, + # and only allows Timer(period=N), not Timer(freq=N). + print("SKIP") + raise SystemExit +else: + timer_id = -1 + +# Test both hard and soft IRQ handlers and both one-shot and periodic +# timers. We adjust period in tests/extmod/machine_soft_timer.py, so try +# adjusting freq here instead. The heap should be locked in hard callbacks +# and unlocked in soft callbacks. + + +def callback(t): + print("callback", mode[1], kind[1], freq, end=" ") + try: + allocate = bytearray(1) + print("unlocked") + except MemoryError: + print("locked") + + +modes = [(Timer.ONE_SHOT, "one-shot"), (Timer.PERIODIC, "periodic")] +kinds = [(False, "soft"), (True, "hard")] + +for mode in modes: + for kind in kinds: + for freq in 50, 25: + timer = Timer( + timer_id, + mode=mode[0], + freq=freq, + hard=kind[0], + callback=callback, + ) + sleep_ms(90) + timer.deinit() diff --git a/tests/extmod/machine_timer.py.exp b/tests/extmod/machine_timer.py.exp new file mode 100644 index 0000000000000..26cdc644fdd08 --- /dev/null +++ b/tests/extmod/machine_timer.py.exp @@ -0,0 +1,16 @@ +callback one-shot soft 50 unlocked +callback one-shot soft 25 unlocked +callback one-shot hard 50 locked +callback one-shot hard 25 locked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 50 unlocked +callback periodic soft 25 unlocked +callback periodic soft 25 unlocked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 50 locked +callback periodic hard 25 locked +callback periodic hard 25 locked diff --git a/tests/extmod/marshal_basic.py b/tests/extmod/marshal_basic.py new file mode 100644 index 0000000000000..9e7b70be4829d --- /dev/null +++ b/tests/extmod/marshal_basic.py @@ -0,0 +1,38 @@ +# Test the marshal module, basic functionality. + +try: + import marshal + + (lambda: 0).__code__ +except (AttributeError, ImportError): + print("SKIP") + raise SystemExit + +ftype = type(lambda: 0) + +# Test basic dumps and loads. +print(ftype(marshal.loads(marshal.dumps((lambda: a).__code__)), {"a": 4})()) + +# Test dumps of a result from compile(). +ftype(marshal.loads(marshal.dumps(compile("print(a)", "", "exec"))), {"print": print, "a": 5})() + +# Test marshalling a function with arguments. +print(ftype(marshal.loads(marshal.dumps((lambda x, y: x + y).__code__)), {})(1, 2)) + +# Test marshalling a function with default arguments. +print(ftype(marshal.loads(marshal.dumps((lambda x=0: x).__code__)), {})("arg")) + +# Test marshalling a function containing constant objects (a tuple). +print(ftype(marshal.loads(marshal.dumps((lambda: (None, ...)).__code__)), {})()) + +# Test instantiating multiple code's with different globals dicts. +code = marshal.loads(marshal.dumps((lambda: a).__code__)) +f1 = ftype(code, {"a": 1}) +f2 = ftype(code, {"a": 2}) +print(f1(), f2()) + +# Test unmarshallable object. +try: + marshal.dumps(type) +except ValueError: + print("ValueError") diff --git a/tests/extmod/marshal_micropython.py b/tests/extmod/marshal_micropython.py new file mode 100644 index 0000000000000..213b3bf31895d --- /dev/null +++ b/tests/extmod/marshal_micropython.py @@ -0,0 +1,21 @@ +# Test the marshal module, MicroPython-specific functionality. + +try: + import marshal +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + + +class Test(unittest.TestCase): + def test_function_with_children(self): + # Can't marshal a function with children (in this case the module has a child function f). + code = compile("def f(): pass", "", "exec") + with self.assertRaises(ValueError): + marshal.dumps(code) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/marshal_stress.py b/tests/extmod/marshal_stress.py new file mode 100644 index 0000000000000..b52475c0361dc --- /dev/null +++ b/tests/extmod/marshal_stress.py @@ -0,0 +1,122 @@ +# Test the marshal module, stressing edge cases. + +try: + import marshal + + (lambda: 0).__code__ +except (AttributeError, ImportError): + print("SKIP") + raise SystemExit + +ftype = type(lambda: 0) + +# Test a large function. + + +def large_function(arg0, arg1, arg2, arg3): + # Arguments. + print(arg0, arg1, arg2, arg3) + + # Positive medium-sized integer (still a small-int though). + print(1234) + + # Negative small-ish integer. + print(-20) + + # More than 64 constant objects. + x = (0,) + x = (1,) + x = (2,) + x = (3,) + x = (4,) + x = (5,) + x = (6,) + x = (7,) + x = (8,) + x = (9,) + x = (10,) + x = (11,) + x = (12,) + x = (13,) + x = (14,) + x = (15,) + x = (16,) + x = (17,) + x = (18,) + x = (19,) + x = (20,) + x = (21,) + x = (22,) + x = (23,) + x = (24,) + x = (25,) + x = (26,) + x = (27,) + x = (28,) + x = (29,) + x = (30,) + x = (31,) + x = (32,) + x = (33,) + x = (34,) + x = (35,) + x = (36,) + x = (37,) + x = (38,) + x = (39,) + x = (40,) + x = (41,) + x = (42,) + x = (43,) + x = (44,) + x = (45,) + x = (46,) + x = (47,) + x = (48,) + x = (49,) + x = (50,) + x = (51,) + x = (52,) + x = (53,) + x = (54,) + x = (55,) + x = (56,) + x = (57,) + x = (58,) + x = (59,) + x = (60,) + x = (61,) + x = (62,) + x = (63,) + x = (64,) + + # Small jump. + x = 0 + while x < 2: + print("loop", x) + x += 1 + + # Large jump. + x = 0 + while x < 2: + try: + try: + try: + print + except Exception as e: + print + finally: + print + except Exception as e: + print + finally: + print + except Exception as e: + print + finally: + print("loop", x) + x += 1 + + +code = marshal.dumps(large_function.__code__) +ftype(marshal.loads(code), {"print": print})(0, 1, 2, 3) diff --git a/tests/extmod/msgpack_pack.py b/tests/extmod/msgpack_pack.py index 511ee642dd55a..edf58c2c6c363 100644 --- a/tests/extmod/msgpack_pack.py +++ b/tests/extmod/msgpack_pack.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this file try: from io import BytesIO import msgpack diff --git a/tests/extmod/platform_basic.py b/tests/extmod/platform_basic.py new file mode 100644 index 0000000000000..eb6f2be13c17a --- /dev/null +++ b/tests/extmod/platform_basic.py @@ -0,0 +1,8 @@ +try: + import platform +except ImportError: + print("SKIP") + raise SystemExit + +print(type(platform.python_compiler())) +print(type(platform.libc_ver())) diff --git a/tests/extmod/qrio.py b/tests/extmod/qrio.py index 53c83706f8803..9dcc12054633c 100644 --- a/tests/extmod/qrio.py +++ b/tests/extmod/qrio.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this file try: import qrio except: diff --git a/tests/extmod/random_extra_float.py b/tests/extmod/random_extra_float.py index 3b37ed8dcef2f..03973c583492d 100644 --- a/tests/extmod/random_extra_float.py +++ b/tests/extmod/random_extra_float.py @@ -1,12 +1,8 @@ try: import random -except ImportError: - print("SKIP") - raise SystemExit -try: - random.randint -except AttributeError: + random.random +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/extmod/re1.py b/tests/extmod/re1.py index 0680a65889d3a..34647325106ef 100644 --- a/tests/extmod/re1.py +++ b/tests/extmod/re1.py @@ -25,7 +25,7 @@ except IndexError: print("IndexError") -# CIRCUITPY-CHANGE +# CIRCUITPY-CHANGE: line-ending tests r = re.compile(r"\n") m = r.match("\n") print(m.group(0)) diff --git a/tests/extmod/re_error.py b/tests/extmod/re_error.py index f61d0913289e1..bd678c9d25156 100644 --- a/tests/extmod/re_error.py +++ b/tests/extmod/re_error.py @@ -11,7 +11,7 @@ def test_re(r): try: re.compile(r) print("OK") - except: # uPy and CPy use different errors, so just ignore the type + except: # MPy and CPy use different errors, so just ignore the type print("Error") diff --git a/tests/extmod/re_start_end_pos.py b/tests/extmod/re_start_end_pos.py new file mode 100644 index 0000000000000..bd16584374b89 --- /dev/null +++ b/tests/extmod/re_start_end_pos.py @@ -0,0 +1,78 @@ +# test start and end pos specification + +try: + import re +except ImportError: + print("SKIP") + raise SystemExit + + +def print_groups(match): + print("----") + try: + if match is not None: + i = 0 + while True: + print(match.group(i)) + i += 1 + except IndexError: + pass + + +p = re.compile(r"o") +m = p.match("dog") +print_groups(m) + +m = p.match("dog", 1) +print_groups(m) + +m = p.match("dog", 2) +print_groups(m) + +# No match past end of input +m = p.match("dog", 5) +print_groups(m) + +m = p.match("dog", 0, 1) +print_groups(m) + +# Caret only matches the actual beginning +p = re.compile(r"^o") +m = p.match("dog", 1) +print_groups(m) + +# End at beginning means searching empty string +p = re.compile(r"o") +m = p.match("dog", 1, 1) +print_groups(m) + +# End before the beginning doesn't match anything +m = p.match("dog", 2, 1) +print_groups(m) + +# Negative starting values don't crash +m = p.search("dog", -2) +print_groups(m) + +m = p.search("dog", -2, -5) +print_groups(m) + +# Search also works +print("--search") + +p = re.compile(r"o") +m = p.search("dog") +print_groups(m) + +m = p.search("dog", 1) +print_groups(m) + +m = p.search("dog", 2) +print_groups(m) + +# Negative starting values don't crash +m = p.search("dog", -2) +print_groups(m) + +m = p.search("dog", -2, -5) +print_groups(m) diff --git a/tests/extmod/re_sub.py b/tests/extmod/re_sub.py index 2c7c6c10f1a49..bb9aa111287e6 100644 --- a/tests/extmod/re_sub.py +++ b/tests/extmod/re_sub.py @@ -10,6 +10,8 @@ print("SKIP") raise SystemExit +import sys + def multiply(m): return str(int(m.group(0)) * 2) @@ -47,7 +49,12 @@ def A(): print(re.sub("a", "b", "c")) # with maximum substitution count specified -print(re.sub("a", "b", "1a2a3a", 2)) +# CIRCUITPY-CHANGE: was "micropython" +if sys.implementation.name != "circuitpython": + # On CPython 3.13 and later the substitution count must be a keyword argument. + print(re.sub("a", "b", "1a2a3a", count=2)) +else: + print(re.sub("a", "b", "1a2a3a", 2)) # invalid group try: @@ -55,7 +62,7 @@ def A(): except: print("invalid group") -# invalid group with very large number (to test overflow in uPy) +# invalid group with very large number (to test overflow in MicroPython) try: re.sub("(a)", "b\\199999999999999999999999999999999999999", "a") except: diff --git a/tests/extmod/re_sub_unmatched.py.exp b/tests/extmod/re_sub_unmatched.py.exp deleted file mode 100644 index 1e5f0fda0554d..0000000000000 --- a/tests/extmod/re_sub_unmatched.py.exp +++ /dev/null @@ -1 +0,0 @@ -1-a2 diff --git a/tests/extmod/select_ipoll.py b/tests/extmod/select_ipoll.py deleted file mode 100644 index 0b661c11c8331..0000000000000 --- a/tests/extmod/select_ipoll.py +++ /dev/null @@ -1,55 +0,0 @@ -# Test select.ipoll(). - -try: - import socket, select -except ImportError: - print("SKIP") - raise SystemExit - - -def print_poll_output(lst): - print([(type(obj), flags) for obj, flags in lst]) - - -poller = select.poll() - -# Use a new UDP socket for tests, which should be writable but not readable. -try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) -except OSError: - print("SKIP") - raise SystemExit - -poller.register(s) - -# Basic polling. -print_poll_output(poller.ipoll(0)) - -# Pass in flags=1 for one-shot behaviour. -print_poll_output(poller.ipoll(0, 1)) - -# Socket should be deregistered and poll should return nothing. -print_poll_output(poller.ipoll(0)) - -# Create a second socket. -s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s2.bind(socket.getaddrinfo("127.0.0.1", 8001)[0][-1]) - -# Register both sockets (to reset the first one). -poller.register(s) -poller.register(s2) - -# Basic polling with two sockets. -print_poll_output(poller.ipoll(0)) - -# Unregister the first socket, to test polling the remaining one. -poller.unregister(s) -print_poll_output(poller.ipoll(0)) - -# Unregister the second socket, to test polling none. -poller.unregister(s2) -print_poll_output(poller.ipoll(0)) - -s2.close() -s.close() diff --git a/tests/extmod/select_ipoll.py.exp b/tests/extmod/select_ipoll.py.exp deleted file mode 100644 index cbeabdce902c8..0000000000000 --- a/tests/extmod/select_ipoll.py.exp +++ /dev/null @@ -1,6 +0,0 @@ -[(, 4)] -[(, 4)] -[] -[(, 4), (, 4)] -[(, 4)] -[] diff --git a/tests/extmod/select_poll_custom.py b/tests/extmod/select_poll_custom.py deleted file mode 100644 index b854a8a14da55..0000000000000 --- a/tests/extmod/select_poll_custom.py +++ /dev/null @@ -1,102 +0,0 @@ -# Test custom pollable objects implemented in Python. - -from micropython import const - -try: - import socket, select, io -except ImportError: - print("SKIP") - raise SystemExit - -_MP_STREAM_POLL = const(3) -_MP_STREAM_GET_FILENO = const(10) - -_MP_STREAM_POLL_RD = const(0x0001) -_MP_STREAM_POLL_WR = const(0x0004) - - -def print_poll_output(lst): - print([(type(obj), flags) for obj, flags in lst]) - - -class CustomPollable(io.IOBase): - def __init__(self): - self.poll_state = 0 - - def ioctl(self, cmd, arg): - if cmd == _MP_STREAM_GET_FILENO: - # Bare-metal ports don't call this ioctl, so don't print it. - return -1 - - print("CustomPollable.ioctl", cmd, arg) - if cmd == _MP_STREAM_POLL: - if self.poll_state == "delay_rd": - self.poll_state = _MP_STREAM_POLL_RD - return 0 - elif self.poll_state < 0: - return self.poll_state - else: - return self.poll_state & arg - - -poller = select.poll() - -# Use a new UDP socket for tests, which should be writable but not readable. -try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) -except OSError: - print("SKIP") - raise SystemExit - -x = CustomPollable() - -# Register both a file-descriptor-based object and a custom pure-Python object. -poller.register(s) -poller.register(x) - -# Modify the flags for the custom object. -poller.modify(x, select.POLLIN) - -# Test polling. -print_poll_output(poller.poll(0)) -x.poll_state = _MP_STREAM_POLL_WR -print_poll_output(poller.poll(0)) -x.poll_state = _MP_STREAM_POLL_RD -print_poll_output(poller.poll(0)) - -# The custom object becomes readable only after being polled. -poller.modify(s, select.POLLIN) -x.poll_state = "delay_rd" -print_poll_output(poller.poll()) - -# The custom object returns an error. -x.poll_state = -1000 -try: - poller.poll(0) -except OSError as er: - print("OSError", er.errno) - -# Register then unregister a socket (a native stream), then test -# that the Python object is still pollable. -s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -x.poll_state = _MP_STREAM_POLL_RD -poller.register(s2) -poller.unregister(s2) -print_poll_output(poller.poll()) - -# Test registering and unregistering multiple times. -for _ in range(2): - poller.unregister(s) - poller.unregister(x) - poller.register(s2) - poller.register(s, select.POLLIN) - poller.register(x, select.POLLIN) - poller.unregister(s2) - print_poll_output(poller.poll()) - -# Clean up. -poller.unregister(x) -poller.unregister(s) -s2.close() -s.close() diff --git a/tests/extmod/select_poll_custom.py.exp b/tests/extmod/select_poll_custom.py.exp deleted file mode 100644 index d85508bab240e..0000000000000 --- a/tests/extmod/select_poll_custom.py.exp +++ /dev/null @@ -1,17 +0,0 @@ -CustomPollable.ioctl 3 1 -[(, 4)] -CustomPollable.ioctl 3 1 -[(, 4)] -CustomPollable.ioctl 3 1 -[(, 4), (, 1)] -CustomPollable.ioctl 3 1 -CustomPollable.ioctl 3 1 -[(, 1)] -CustomPollable.ioctl 3 1 -OSError 1000 -CustomPollable.ioctl 3 1 -[(, 1)] -CustomPollable.ioctl 3 1 -[(, 1)] -CustomPollable.ioctl 3 1 -[(, 1)] diff --git a/tests/extmod/select_poll_eintr.py b/tests/extmod/select_poll_eintr.py deleted file mode 100644 index e1cbc2aaf57d0..0000000000000 --- a/tests/extmod/select_poll_eintr.py +++ /dev/null @@ -1,50 +0,0 @@ -# Test interruption of select.poll by EINTR signal, when -# MICROPY_PY_SELECT_POSIX_OPTIMISATIONS is enabled. - -try: - import time, gc, select, socket, _thread - - time.time_ns # Check for time_ns on MicroPython - select.poll # Raises AttributeError for CPython implementations without poll() -except (ImportError, AttributeError): - print("SKIP") - raise SystemExit - - -def thread_main(): - lock.acquire() - time.sleep(0.2) - print("thread gc start") - # The unix gc.collect() implementation will raise EINTR on other threads. - # Could possibly use _thread._interrupt_main() instead if MicroPython had it. - gc.collect() - print("thread gc end") - - -# Start a thread to interrupt the main thread during its call to poll. -lock = _thread.allocate_lock() -lock.acquire() -_thread.start_new_thread(thread_main, ()) - -# Use a new UDP socket for tests, which should be writable but not readable. -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) - -# Create the poller object. -poller = select.poll() -poller.register(s, select.POLLIN) - -# Poll on the UDP socket for a set timeout, which should be reached. -print("poll") -lock.release() -t0 = time.time_ns() -result = poller.poll(400) -dt_ms = (time.time_ns() - t0) / 1e6 -print("result:", result) -if 380 <= dt_ms <= 600: - print("dt in range") -else: - print("dt not in range:", dt_ms) - -# Clean up. -s.close() diff --git a/tests/extmod/select_poll_fd.py b/tests/extmod/select_poll_fd.py deleted file mode 100644 index 5f9dcc286a0cc..0000000000000 --- a/tests/extmod/select_poll_fd.py +++ /dev/null @@ -1,63 +0,0 @@ -# Test select.poll in combination with file descriptors. - -try: - import select, errno - - select.poll # Raises AttributeError for CPython implementations without poll() -except (ImportError, AttributeError): - print("SKIP") - raise SystemExit - -# Check that poll supports registering file descriptors (integers). -try: - select.poll().register(0) -except OSError: - print("SKIP") - raise SystemExit - -# Register invalid file descriptor. -try: - select.poll().register(-1) -except ValueError: - print("ValueError") - -# Test polling stdout, it should be writable. -poller = select.poll() -poller.register(1) -poller.modify(1, select.POLLOUT) -print(poller.poll()) - -# Unregister then re-register. -poller.unregister(1) -poller.register(1, select.POLLIN) - -# Poll for input, should return an empty list. -print(poller.poll(0)) - -# Test registering a very large number of file descriptors (will trigger -# EINVAL due to more than OPEN_MAX fds). Typically it's 1024 (and on GitHub CI -# we force this via `ulimit -n 1024`). -# CIRCUITPY-CHANGE: Skip this test. poller.poll() does not have a limit and will `assert False` -# The ulimit change in the micropython tests may not be working properly. -# on GitHub CI, the limit is far larger than 6000. It is 1024 on desktop Ubuntu, but -# higher on the runners. I don't think this test is testing what it means to test. -# poller = select.poll() -# fd_last = 0 -# for fd in range(6000): -# fd_last = fd -# poller.register(fd) -# try: -# poller.poll() -# assert False -# except OSError as er: -# print("fd_last", fd_last) -# print(er.errno == errno.EINVAL) - -# Register stdout/stderr, plus many extra ones to trigger the fd vector -# resizing. Then unregister the excess ones and verify poll still works. -poller = select.poll() -for fd in range(1, 1000): - poller.register(fd) -for i in range(3, 1000): - poller.unregister(i) -print(sorted(poller.poll())) diff --git a/tests/extmod/socket_badconstructor.py b/tests/extmod/socket_badconstructor.py new file mode 100644 index 0000000000000..4a9d2668c7f1a --- /dev/null +++ b/tests/extmod/socket_badconstructor.py @@ -0,0 +1,22 @@ +# Test passing in bad values to socket.socket constructor. + +try: + import socket +except: + print("SKIP") + raise SystemExit + +try: + s = socket.socket(None) +except TypeError: + print("TypeError") + +try: + s = socket.socket(socket.AF_INET, None) +except TypeError: + print("TypeError") + +try: + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, None) +except TypeError: + print("TypeError") diff --git a/tests/extmod/socket_fileno.py b/tests/extmod/socket_fileno.py new file mode 100644 index 0000000000000..da15825e3d56b --- /dev/null +++ b/tests/extmod/socket_fileno.py @@ -0,0 +1,17 @@ +# Test socket.fileno() functionality + +try: + import socket +except ImportError: + print("SKIP") + raise SystemExit + +if not hasattr(socket.socket, "fileno"): + print("SKIP") + raise SystemExit + +s = socket.socket() +print(s.fileno() >= 0) + +s.close() +print(s.fileno()) # should print -1 diff --git a/tests/extmod/socket_udp_nonblock.py b/tests/extmod/socket_udp_nonblock.py deleted file mode 100644 index 1e74e2917dc30..0000000000000 --- a/tests/extmod/socket_udp_nonblock.py +++ /dev/null @@ -1,21 +0,0 @@ -# test non-blocking UDP sockets - -try: - import socket, errno -except ImportError: - print("SKIP") - raise SystemExit - -try: - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.bind(socket.getaddrinfo("127.0.0.1", 8000)[0][-1]) -except OSError: - print("SKIP") - raise SystemExit - -s.settimeout(0) - -try: - s.recv(1) -except OSError as er: - print("EAGAIN:", er.errno == errno.EAGAIN) diff --git a/tests/extmod/ssl_cadata.py b/tests/extmod/ssl_cadata.py deleted file mode 100644 index e66f6ca825baf..0000000000000 --- a/tests/extmod/ssl_cadata.py +++ /dev/null @@ -1,18 +0,0 @@ -# Test ssl.wrap_socket() with cadata passed in. - -try: - import io - import ssl -except ImportError: - print("SKIP") - raise SystemExit - -# Invalid cadata. -try: - ssl.wrap_socket(io.BytesIO(), cadata=b"!") -except TypeError: - # "cadata" keyword argument is not supported by axtls. - print("SKIP") - raise SystemExit -except ValueError as er: - print(repr(er)) diff --git a/tests/extmod/ssl_cadata.py.exp b/tests/extmod/ssl_cadata.py.exp deleted file mode 100644 index 9f1cf732e33ff..0000000000000 --- a/tests/extmod/ssl_cadata.py.exp +++ /dev/null @@ -1 +0,0 @@ -ValueError('invalid cert',) diff --git a/tests/extmod/ssl_ioctl.py b/tests/extmod/ssl_ioctl.py deleted file mode 100644 index 4db7c2df82aeb..0000000000000 --- a/tests/extmod/ssl_ioctl.py +++ /dev/null @@ -1,31 +0,0 @@ -# Test SSL ioctl method. -# Direct access to this method is only available if MICROPY_UNIX_COVERAGE is enabled. - -try: - import io, ssl - - io.BytesIO -except (ImportError, AttributeError): - print("SKIP") - raise SystemExit - -_MP_STREAM_POLL = 3 -_MP_STREAM_CLOSE = 4 -_MP_STREAM_GET_FILENO = 10 - -s = ssl.wrap_socket(io.BytesIO(), server_side=1, do_handshake=0) - -if not hasattr(s, "ioctl"): - print("SKIP") - raise SystemExit - -# These ioctl's should be unsupported. -for request in (-1, 0, _MP_STREAM_GET_FILENO): - try: - s.ioctl(request, 0) - except OSError: - print(request, "OSError") - -# These ioctl's should be supported. -for request in (_MP_STREAM_CLOSE, _MP_STREAM_POLL, _MP_STREAM_CLOSE): - print(request, s.ioctl(request, 0)) diff --git a/tests/extmod/ssl_ioctl.py.exp b/tests/extmod/ssl_ioctl.py.exp deleted file mode 100644 index 22208b00cc94d..0000000000000 --- a/tests/extmod/ssl_ioctl.py.exp +++ /dev/null @@ -1,6 +0,0 @@ --1 OSError -0 OSError -10 OSError -4 0 -3 32 -4 0 diff --git a/tests/extmod/ssl_poll.py b/tests/extmod/ssl_poll.py deleted file mode 100644 index 347e5f7d37a42..0000000000000 --- a/tests/extmod/ssl_poll.py +++ /dev/null @@ -1,196 +0,0 @@ -try: - import select - import ssl - import io - import binascii -except ImportError: - print("SKIP") - raise SystemExit - -from micropython import const - -_MP_STREAM_POLL_RD = const(0x0001) -_MP_STREAM_POLL_WR = const(0x0004) -_MP_STREAM_POLL_NVAL = const(0x0020) -_MP_STREAM_POLL = const(3) -_MP_STREAM_CLOSE = const(4) - - -# This self-signed key/cert pair is randomly generated and to be used for -# testing/demonstration only. You should always generate your own key/cert. -key = binascii.unhexlify( - b"3082013b020100024100cc20643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef" - b"610a6a6ba14abb891745cd18a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f" - b"872d0203010001024100bb17a54aeb3dd7ae4edec05e775ca9632cf02d29c2a089b563b0" - b"d05cdf95aeca507de674553f28b4eadaca82d5549a86058f9996b07768686a5b02cb240d" - b"d9f1022100f4a63f5549e817547dca97b5c658038e8593cb78c5aba3c4642cc4cd031d86" - b"8f022100d598d870ffe4a34df8de57047a50b97b71f4d23e323f527837c9edae88c79483" - b"02210098560c89a70385c36eb07fd7083235c4c1184e525d838aedf7128958bedfdbb102" - b"2051c0dab7057a8176ca966f3feb81123d4974a733df0f958525f547dfd1c271f9022044" - b"6c2cafad455a671a8cf398e642e1be3b18a3d3aec2e67a9478f83c964c4f1f" -) -cert = binascii.unhexlify( - b"308201d53082017f020203e8300d06092a864886f70d01010505003075310b3009060355" - b"0406130258583114301206035504080c0b54686550726f76696e63653110300e06035504" - b"070c075468654369747931133011060355040a0c0a436f6d70616e7958595a3113301106" - b"0355040b0c0a436f6d70616e7958595a3114301206035504030c0b546865486f73744e61" - b"6d65301e170d3139313231383033333935355a170d3239313231353033333935355a3075" - b"310b30090603550406130258583114301206035504080c0b54686550726f76696e636531" - b"10300e06035504070c075468654369747931133011060355040a0c0a436f6d70616e7958" - b"595a31133011060355040b0c0a436f6d70616e7958595a3114301206035504030c0b5468" - b"65486f73744e616d65305c300d06092a864886f70d0101010500034b003048024100cc20" - b"643fd3d9c21a0acba4f48f61aadd675f52175a9dcf07fbef610a6a6ba14abb891745cd18" - b"a1d4c056580d8ff1a639460f867013c8391cdc9f2e573b0f872d0203010001300d06092a" - b"864886f70d0101050500034100b0513fe2829e9ecbe55b6dd14c0ede7502bde5d46153c8" - b"e960ae3ebc247371b525caeb41bbcf34686015a44c50d226e66aef0a97a63874ca5944ef" - b"979b57f0b3" -) - - -class _Pipe(io.IOBase): - def __init__(self): - self._other = None - self.block_reads = False - self.block_writes = False - - self.write_buffers = [] - self.last_poll_arg = None - - def readinto(self, buf): - if self.block_reads or len(self._other.write_buffers) == 0: - return None - - read_buf = self._other.write_buffers[0] - l = min(len(buf), len(read_buf)) - buf[:l] = read_buf[:l] - if l == len(read_buf): - self._other.write_buffers.pop(0) - else: - self._other.write_buffers[0] = read_buf[l:] - return l - - def write(self, buf): - if self.block_writes: - return None - - self.write_buffers.append(memoryview(bytes(buf))) - return len(buf) - - def ioctl(self, request, arg): - if request == _MP_STREAM_POLL: - self.last_poll_arg = arg - ret = 0 - if arg & _MP_STREAM_POLL_RD: - if not self.block_reads and self._other.write_buffers: - ret |= _MP_STREAM_POLL_RD - if arg & _MP_STREAM_POLL_WR: - if not self.block_writes: - ret |= _MP_STREAM_POLL_WR - return ret - - elif request == _MP_STREAM_CLOSE: - return 0 - - raise NotImplementedError() - - @classmethod - def new_pair(cls): - p1 = cls() - p2 = cls() - p1._other = p2 - p2._other = p1 - return p1, p2 - - -def assert_poll(s, i, arg, expected_arg, expected_ret): - ret = s.ioctl(_MP_STREAM_POLL, arg) - assert i.last_poll_arg == expected_arg - i.last_poll_arg = None - assert ret == expected_ret - - -def assert_raises(cb, *args, **kwargs): - try: - cb(*args, **kwargs) - raise AssertionError("should have raised") - except Exception as exc: - pass - - -client_io, server_io = _Pipe.new_pair() - -client_io.block_reads = True -client_io.block_writes = True -client_sock = ssl.wrap_socket(client_io, do_handshake=False) - -server_sock = ssl.wrap_socket(server_io, key=key, cert=cert, server_side=True, do_handshake=False) - -# Do a test read, at this point the TLS handshake wants to write, -# so it returns None: -assert client_sock.read(128) is None - -# Polling for either read or write actually check if the underlying socket can write: -assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_WR, 0) -assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR, 0) - -# Mark the socket as writable, and do another test read: -client_io.block_writes = False -assert client_sock.read(128) is None - -# The client wrote the CLIENT_HELLO message -assert len(client_io.write_buffers) == 1 - -# At this point the TLS handshake wants to read, but we don't know that yet: -assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, 0) -assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_WR) - -# Do a test write -client_sock.write(b"foo") - -# Now we know that we want to read: -assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, 0) -assert_poll(client_sock, client_io, _MP_STREAM_POLL_WR, _MP_STREAM_POLL_RD, 0) - -# Unblock reads and nudge the two sockets: -client_io.block_reads = False -while server_io.write_buffers or client_io.write_buffers: - if server_io.write_buffers: - assert client_sock.read(128) is None - if client_io.write_buffers: - assert server_sock.read(128) is None - -# At this point, the handshake is done, try writing data: -client_sock.write(b"foo") -assert server_sock.read(3) == b"foo" - -# Test reading partial data: -client_sock.write(b"foobar") -assert server_sock.read(3) == b"foo" -server_io.block_reads = True -assert_poll( - server_sock, server_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_RD -) # Did not go to the socket, just consumed buffered data -assert server_sock.read(3) == b"bar" - - -# Polling on a closed socket errors out: -client_io, _ = _Pipe.new_pair() -client_sock = ssl.wrap_socket(client_io, do_handshake=False) -client_sock.close() -assert_poll( - client_sock, client_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_NVAL -) # Did not go to the socket - - -# Errors propagates to poll: -client_io, server_io = _Pipe.new_pair() -client_sock = ssl.wrap_socket(client_io, do_handshake=False) - -# The server returns garbage: -server_io.write(b"fooba") # Needs to be exactly 5 bytes - -assert_poll(client_sock, client_io, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD, _MP_STREAM_POLL_RD) -assert_raises(client_sock.read, 128) -assert_poll( - client_sock, client_io, _MP_STREAM_POLL_RD, None, _MP_STREAM_POLL_NVAL -) # Did not go to the socket diff --git a/tests/extmod/ssl_sslcontext.py b/tests/extmod/ssl_sslcontext.py deleted file mode 100644 index 23ff9c29646c0..0000000000000 --- a/tests/extmod/ssl_sslcontext.py +++ /dev/null @@ -1,25 +0,0 @@ -# Very basic test of ssl.SSLContext class. - -try: - import socket, ssl -except ImportError: - print("SKIP") - raise SystemExit - -# Test constructing with arguments. -ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) -ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) - -# Test printing object. -ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) -print("SSLContext" in str(ctx)) - -# Coverage test for destructor, and calling it twice. -if hasattr(ctx, "__del__"): - ctx.__del__() - ctx.__del__() - -# Test calling .wrap_socket() method, multiple times. -ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) -ctx.wrap_socket(socket.socket(), do_handshake_on_connect=False) -ctx.wrap_socket(socket.socket(), do_handshake_on_connect=False) diff --git a/tests/extmod/ssl_sslcontext_ciphers.py b/tests/extmod/ssl_sslcontext_ciphers.py deleted file mode 100644 index 20c00b917623c..0000000000000 --- a/tests/extmod/ssl_sslcontext_ciphers.py +++ /dev/null @@ -1,31 +0,0 @@ -# Basic test of ssl.SSLContext get_ciphers() and set_ciphers() methods. - -try: - import ssl -except ImportError: - print("SKIP") - raise SystemExit - - -ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) - -ciphers = ctx.get_ciphers() - -for ci in ciphers: - # Only print those ciphers know to exist on all ports. - if ("TLS-ECDHE-ECDSA-WITH-AES" in ci or "TLS-RSA-WITH-AES" in ci) and "CBC" in ci: - print(ci) - -ctx.set_ciphers(ciphers[:1]) - -# Test error cases. - -try: - ctx.set_ciphers(ciphers[0]) -except TypeError as e: - print(e) - -try: - ctx.set_ciphers(["BAR"]) -except OSError as e: - print(e) diff --git a/tests/extmod/ssl_sslcontext_ciphers.py.exp b/tests/extmod/ssl_sslcontext_ciphers.py.exp deleted file mode 100644 index 0d21a3bd253e7..0000000000000 --- a/tests/extmod/ssl_sslcontext_ciphers.py.exp +++ /dev/null @@ -1,10 +0,0 @@ -TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384 -TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA -TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256 -TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA -TLS-RSA-WITH-AES-256-CBC-SHA256 -TLS-RSA-WITH-AES-256-CBC-SHA -TLS-RSA-WITH-AES-128-CBC-SHA256 -TLS-RSA-WITH-AES-128-CBC-SHA -object 'str' isn't a tuple or list -(-24192, 'MBEDTLS_ERR_SSL_BAD_CONFIG') diff --git a/tests/extmod/ssl_sslcontext_micropython.py b/tests/extmod/ssl_sslcontext_micropython.py deleted file mode 100644 index 136fb8a054ed7..0000000000000 --- a/tests/extmod/ssl_sslcontext_micropython.py +++ /dev/null @@ -1,29 +0,0 @@ -# Test MicroPython-specific behaviour of ssl.SSLContext. - -try: - import ssl -except ImportError: - print("SKIP") - raise SystemExit - -# Test constructing without any arguments (in CPython it's a DeprecationWarning). -try: - ssl.SSLContext() -except TypeError: - print("TypeError") - -# Test attributes that don't exist (in CPython new attributes can be added). -# This test is needed for coverage because SSLContext implements a custom attr handler. -ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) -try: - ctx.does_not_exist -except AttributeError: - print("AttributeError on load") -try: - ctx.does_not_exist = None -except AttributeError: - print("AttributeError on store") -try: - del ctx.does_not_exist -except AttributeError: - print("AttributeError on delete") diff --git a/tests/extmod/ssl_sslcontext_micropython.py.exp b/tests/extmod/ssl_sslcontext_micropython.py.exp deleted file mode 100644 index 21e65258ff2a1..0000000000000 --- a/tests/extmod/ssl_sslcontext_micropython.py.exp +++ /dev/null @@ -1,4 +0,0 @@ -TypeError -AttributeError on load -AttributeError on store -AttributeError on delete diff --git a/tests/extmod/ssl_sslcontext_verify_mode.py b/tests/extmod/ssl_sslcontext_verify_mode.py deleted file mode 100644 index daccc2f4a956b..0000000000000 --- a/tests/extmod/ssl_sslcontext_verify_mode.py +++ /dev/null @@ -1,24 +0,0 @@ -# Test ssl.SSLContext.verify_mode attribute. -# It's not available in the axtls implementation, so has an independent test. - -try: - import ssl -except ImportError: - print("SKIP") - raise SystemExit - -if not hasattr(ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT), "verify_mode"): - print("SKIP") - raise SystemExit - -# Test default verify_mode for server (client default is different in MicroPython). -ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) -print(ctx.verify_mode == ssl.CERT_NONE) - -# Test setting and getting verify_mode. -ctx.verify_mode = ssl.CERT_NONE -print(ctx.verify_mode == ssl.CERT_NONE) -ctx.verify_mode = ssl.CERT_OPTIONAL -print(ctx.verify_mode == ssl.CERT_OPTIONAL) -ctx.verify_mode = ssl.CERT_REQUIRED -print(ctx.verify_mode == ssl.CERT_REQUIRED) diff --git a/tests/extmod/ticks_add.py b/tests/extmod/ticks_add.py deleted file mode 100644 index 4f465f3cfbac5..0000000000000 --- a/tests/extmod/ticks_add.py +++ /dev/null @@ -1,42 +0,0 @@ -try: - from time import ticks_diff, ticks_add -except ImportError: - print("SKIP") - raise SystemExit - -# Maximum value returned from ticks_add, ticks_ms, etc. -TICKS_MAX = ticks_add(0, -1) -# Maximum value returned from ticks_diff. -TICKS_INTERVAL_MAX = TICKS_MAX // 2 - -# Invariants: -# - ticks_diff(ticks_add(T, delta), T) == delta -# - ticks_diff(T, ticks_add(T, delta)) == -delta - -# Check actual values of ticks_add. -print(ticks_add(20, 12)) -print(ticks_add(20, -12)) - -# Check invariant. -print(ticks_diff(ticks_add(100, 123), 100)) -print(ticks_diff(ticks_add(100, -123), 100)) -print(ticks_diff(100, ticks_add(100, 123))) -print(ticks_diff(100, ticks_add(100, -123))) - -# Check limits. -for T in (0, 10, TICKS_MAX): - for delta in ( - -TICKS_INTERVAL_MAX - 1, - -TICKS_INTERVAL_MAX, - 0, - TICKS_INTERVAL_MAX, - TICKS_INTERVAL_MAX + 1, - ): - try: - print(ticks_diff(ticks_add(T, delta), T) == delta) - except OverflowError: - print("OverflowError") - try: - print(ticks_diff(T, ticks_add(T, delta)) == -delta) - except OverflowError: - print("OverflowError") diff --git a/tests/extmod/ticks_add.py.exp b/tests/extmod/ticks_add.py.exp deleted file mode 100644 index 60dc6f5afda6b..0000000000000 --- a/tests/extmod/ticks_add.py.exp +++ /dev/null @@ -1,36 +0,0 @@ -32 -8 -123 --123 --123 -123 -OverflowError -OverflowError -True -True -True -True -True -True -OverflowError -OverflowError -OverflowError -OverflowError -True -True -True -True -True -True -OverflowError -OverflowError -OverflowError -OverflowError -True -True -True -True -True -True -OverflowError -OverflowError diff --git a/tests/extmod/ticks_diff.py b/tests/extmod/ticks_diff.py deleted file mode 100644 index b2445f0d62454..0000000000000 --- a/tests/extmod/ticks_diff.py +++ /dev/null @@ -1,37 +0,0 @@ -try: - from time import ticks_diff, ticks_add -except ImportError: - print("SKIP") - raise SystemExit - -MAX = ticks_add(0, -1) -# Should be done like this to avoid small int overflow -MODULO_HALF = MAX // 2 + 1 - -# Invariants: -# if ticks_diff(a, b) = c, -# then ticks_diff(b, a) = -c - -assert ticks_diff(1, 0) == 1, ticks_diff(1, 0) -assert ticks_diff(0, 1) == -1 - -assert ticks_diff(0, MAX) == 1 -assert ticks_diff(MAX, 0) == -1 - -assert ticks_diff(0, MAX - 1) == 2 - -# Maximum "positive" distance -assert ticks_diff(MODULO_HALF, 1) == MODULO_HALF - 1, ticks_diff(MODULO_HALF, 1) -# Step further, and it becomes a negative distance -assert ticks_diff(MODULO_HALF, 0) == -MODULO_HALF - -# Offsetting that in either direction doesn't affect the result -off = 100 -# Cheating and skipping to use ticks_add() when we know there's no wraparound -# Real apps should use always it. -assert ticks_diff(MODULO_HALF + off, 1 + off) == MODULO_HALF - 1 -assert ticks_diff(MODULO_HALF + off, 0 + off) == -MODULO_HALF -assert ticks_diff(MODULO_HALF - off, ticks_add(1, -off)) == MODULO_HALF - 1 -assert ticks_diff(MODULO_HALF - off, ticks_add(0, -off)) == -MODULO_HALF - -print("OK") diff --git a/tests/extmod/ticks_diff.py.exp b/tests/extmod/ticks_diff.py.exp deleted file mode 100644 index d86bac9de59ab..0000000000000 --- a/tests/extmod/ticks_diff.py.exp +++ /dev/null @@ -1 +0,0 @@ -OK diff --git a/tests/extmod/time_mktime.py b/tests/extmod/time_mktime.py new file mode 100644 index 0000000000000..7fc643dc3cb8c --- /dev/null +++ b/tests/extmod/time_mktime.py @@ -0,0 +1,120 @@ +# test conversion from date tuple to timestamp and back + +try: + import time + + time.localtime +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +# Range of date expected to work on all MicroPython platforms +MIN_YEAR = 1970 +MAX_YEAR = 2099 +# CPython properly supported date range: +# - on Windows: year 1970 to 3000+ +# - on Unix: year 1583 to 3000+ + +# Start test from Jan 1, 2001 13:00 (Feb 2000 might already be broken) +SAFE_DATE = (2001, 1, 1, 13, 0, 0, 0, 0, -1) + + +# mktime function that checks that the result is reversible +def safe_mktime(date_tuple): + try: + res = time.mktime(date_tuple) + chk = time.localtime(res) + except OverflowError: + print("safe_mktime:", date_tuple, "overflow error") + return None + if chk[0:5] != date_tuple[0:5]: + print("safe_mktime:", date_tuple[0:5], " -> ", res, " -> ", chk[0:5]) + return None + return res + + +# localtime function that checks that the result is reversible +def safe_localtime(timestamp): + try: + res = time.localtime(timestamp) + chk = time.mktime(res) + except OverflowError: + print("safe_localtime:", timestamp, "overflow error") + return None + if chk != timestamp: + print("safe_localtime:", timestamp, " -> ", res, " -> ", chk) + return None + return res + + +# look for smallest valid timestamps by iterating backwards on tuple +def test_bwd(date_tuple): + curr_stamp = safe_mktime(date_tuple) + year = date_tuple[0] + month = date_tuple[1] - 1 + if month < 1: + year -= 1 + month = 12 + while year >= MIN_YEAR: + while month >= 1: + next_tuple = (year, month) + date_tuple[2:] + next_stamp = safe_mktime(next_tuple) + # at this stage, only test consistency and monotonicity + if next_stamp is None or next_stamp >= curr_stamp: + return date_tuple + date_tuple = next_tuple + curr_stamp = next_stamp + month -= 1 + year -= 1 + month = 12 + return date_tuple + + +# test day-by-day to ensure that every date is properly converted +def test_fwd(start_date): + DAYS_PER_MONTH = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + curr_stamp = safe_mktime(start_date) + curr_date = safe_localtime(curr_stamp) + while curr_date[0] <= MAX_YEAR: + if curr_date[2] < 15: + skip_days = 13 + else: + skip_days = 1 + next_stamp = curr_stamp + skip_days * 86400 + next_date = safe_localtime(next_stamp) + if next_date is None: + return curr_date + if next_date[2] != curr_date[2] + skip_days: + # next month + if next_date[2] != 1: + print("wrong day of month:", next_date) + return curr_date + # check the number of days in previous month + month_days = DAYS_PER_MONTH[curr_date[1]] + if month_days == 28 and curr_date[0] % 4 == 0: + if curr_date[0] % 100 != 0 or curr_date[0] % 400 == 0: + month_days += 1 + if curr_date[2] != month_days: + print("wrong day count in prev month:", curr_date[2], "vs", month_days) + return curr_date + if next_date[1] != curr_date[1] + 1: + # next year + if curr_date[1] != 12: + print("wrong month count in prev year:", curr_date[1]) + return curr_date + if next_date[1] != 1: + print("wrong month:", next_date) + return curr_date + if next_date[0] != curr_date[0] + 1: + print("wrong year:", next_date) + return curr_date + curr_stamp = next_stamp + curr_date = next_date + return curr_date + + +small_date = test_bwd(SAFE_DATE) +large_date = test_fwd(small_date) +print("tested from", small_date[0:3], "to", large_date[0:3]) +print(small_date[0:3], "wday is", small_date[6]) +print(large_date[0:3], "wday is", large_date[6]) diff --git a/tests/extmod/time_ms_us.py b/tests/extmod/time_ms_us.py deleted file mode 100644 index e26c6e677a910..0000000000000 --- a/tests/extmod/time_ms_us.py +++ /dev/null @@ -1,23 +0,0 @@ -try: - import time - - time.sleep_ms, time.sleep_us, time.ticks_diff, time.ticks_ms, time.ticks_us, time.ticks_cpu -except (ImportError, AttributeError): - print("SKIP") - raise SystemExit - -time.sleep_ms(1) -time.sleep_us(1) - -t0 = time.ticks_ms() -t1 = time.ticks_ms() -print(0 <= time.ticks_diff(t1, t0) <= 1) - -t0 = time.ticks_us() -t1 = time.ticks_us() -print(0 <= time.ticks_diff(t1, t0) <= 500) - -# ticks_cpu may not be implemented, at least make sure it doesn't decrease -t0 = time.ticks_cpu() -t1 = time.ticks_cpu() -print(time.ticks_diff(t1, t0) >= 0) diff --git a/tests/extmod/time_ms_us.py.exp b/tests/extmod/time_ms_us.py.exp deleted file mode 100644 index b8ca7e7ef092a..0000000000000 --- a/tests/extmod/time_ms_us.py.exp +++ /dev/null @@ -1,3 +0,0 @@ -True -True -True diff --git a/tests/extmod/time_res.py b/tests/extmod/time_res.py index 548bef1f1747c..ef20050b914d7 100644 --- a/tests/extmod/time_res.py +++ b/tests/extmod/time_res.py @@ -37,9 +37,12 @@ def test(): time.sleep_ms(100) for func_name, _ in EXPECTED_MAP: try: - time_func = getattr(time, func_name, None) or globals()[func_name] + if func_name.endswith("_time"): + time_func = globals()[func_name] + else: + time_func = getattr(time, func_name) now = time_func() # may raise AttributeError - except (KeyError, AttributeError): + except AttributeError: continue try: results_map[func_name].add(now) diff --git a/tests/extmod/time_time_ns.py b/tests/extmod/time_time_ns.py deleted file mode 100644 index 3ef58e56a9459..0000000000000 --- a/tests/extmod/time_time_ns.py +++ /dev/null @@ -1,24 +0,0 @@ -# test time.time_ns() - -try: - import time - - time.sleep_us - time.time_ns -except (ImportError, AttributeError): - print("SKIP") - raise SystemExit - - -t0 = time.time_ns() -time.sleep_us(5000) -t1 = time.time_ns() - -# Check that time_ns increases. -print(t0 < t1) - -# Check that time_ns counts correctly, but be very lenient with the bounds (2ms to 50ms). -if 2000000 < t1 - t0 < 50000000: - print(True) -else: - print(t0, t1, t1 - t0) diff --git a/tests/extmod/time_time_ns.py.exp b/tests/extmod/time_time_ns.py.exp deleted file mode 100644 index dbde422651c9a..0000000000000 --- a/tests/extmod/time_time_ns.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -True -True diff --git a/tests/extmod/tls_dtls.py b/tests/extmod/tls_dtls.py new file mode 100644 index 0000000000000..753ab2fee4f40 --- /dev/null +++ b/tests/extmod/tls_dtls.py @@ -0,0 +1,61 @@ +# Test DTLS functionality including timeout handling + +try: + from tls import PROTOCOL_DTLS_CLIENT, PROTOCOL_DTLS_SERVER, SSLContext, CERT_NONE + import io +except ImportError: + print("SKIP") + raise SystemExit + + +class DummySocket(io.IOBase): + def __init__(self): + self.write_buffer = bytearray() + self.read_buffer = bytearray() + + def write(self, data): + return len(data) + + def readinto(self, buf): + # This is a placeholder socket that doesn't actually read anything + # so the read buffer is always empty. + return None + + def ioctl(self, req, arg): + if req == 4: # MP_STREAM_CLOSE + return 0 + return -1 + + +# Create dummy sockets for testing +server_socket = DummySocket() +client_socket = DummySocket() + +# Wrap the DTLS Server +dtls_server_ctx = SSLContext(PROTOCOL_DTLS_SERVER) +dtls_server_ctx.verify_mode = CERT_NONE +dtls_server = dtls_server_ctx.wrap_socket( + server_socket, do_handshake_on_connect=False, client_id=b"dummy_client_id" +) +print("Wrapped DTLS Server") + +# wrap DTLS server with invalid client_id +try: + dtls_server = dtls_server_ctx.wrap_socket( + server_socket, do_handshake_on_connect=False, client_id=4 + ) +except OSError: + print("Failed to wrap DTLS Server with invalid client_id") + +# Wrap the DTLS Client +dtls_client_ctx = SSLContext(PROTOCOL_DTLS_CLIENT) +dtls_client_ctx.verify_mode = CERT_NONE +dtls_client = dtls_client_ctx.wrap_socket(client_socket, do_handshake_on_connect=False) +print("Wrapped DTLS Client") + +# Trigger the timing check multiple times with different elapsed times +for i in range(10): # Try multiple iterations to hit the timing window + dtls_client.write(b"test") + data = dtls_server.read(1024) # This should eventually hit the timing condition + +print("OK") diff --git a/tests/extmod/tls_dtls.py.exp b/tests/extmod/tls_dtls.py.exp new file mode 100644 index 0000000000000..dbd005d0edfb8 --- /dev/null +++ b/tests/extmod/tls_dtls.py.exp @@ -0,0 +1,4 @@ +Wrapped DTLS Server +Failed to wrap DTLS Server with invalid client_id +Wrapped DTLS Client +OK diff --git a/tests/extmod/tls_noleak.py b/tests/extmod/tls_noleak.py new file mode 100644 index 0000000000000..870032d58e63e --- /dev/null +++ b/tests/extmod/tls_noleak.py @@ -0,0 +1,50 @@ +# Ensure that SSLSockets can be allocated sequentially +# without running out of available memory. +try: + import io + import tls +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + + +class TestSocket(io.IOBase): + def write(self, buf): + return len(buf) + + def readinto(self, buf): + return 0 + + def ioctl(self, cmd, arg): + return 0 + + def setblocking(self, value): + pass + + +ITERS = 128 + + +class TLSNoLeaks(unittest.TestCase): + def test_unique_context(self): + for n in range(ITERS): + print(n) + s = TestSocket() + ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT) + ctx.verify_mode = tls.CERT_NONE + s = ctx.wrap_socket(s, do_handshake_on_connect=False) + + def test_shared_context(self): + # Single SSLContext, multiple sockets + ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT) + ctx.verify_mode = tls.CERT_NONE + for n in range(ITERS): + print(n) + s = TestSocket() + s = ctx.wrap_socket(s, do_handshake_on_connect=False) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/tls_threads.py b/tests/extmod/tls_threads.py new file mode 100644 index 0000000000000..1e0c3d23d2f38 --- /dev/null +++ b/tests/extmod/tls_threads.py @@ -0,0 +1,58 @@ +# Ensure that SSL sockets can be allocated from multiple +# threads without thread safety issues + +try: + import _thread + import io + import tls + import time +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + + +class TestSocket(io.IOBase): + def write(self, buf): + return len(buf) + + def readinto(self, buf): + return 0 + + def ioctl(self, cmd, arg): + return 0 + + def setblocking(self, value): + pass + + +ITERS = 256 + + +class TLSThreads(unittest.TestCase): + def test_sslsocket_threaded(self): + self.done = False + # only run in two threads: too much RAM demand otherwise, and rp2 only + # supports two anyhow + _thread.start_new_thread(self._alloc_many_sockets, (True,)) + self._alloc_many_sockets(False) + while not self.done: + time.sleep(0.1) + print("done") + + def _alloc_many_sockets(self, set_done_flag): + print("start", _thread.get_ident()) + ctx = tls.SSLContext(tls.PROTOCOL_TLS_CLIENT) + ctx.verify_mode = tls.CERT_NONE + for n in range(ITERS): + s = TestSocket() + s = ctx.wrap_socket(s, do_handshake_on_connect=False) + s.close() # Free associated resources now from thread, not in a GC pass + print("done", _thread.get_ident()) + if set_done_flag: + self.done = True + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/uctypes_addressof.py b/tests/extmod/uctypes_addressof.py new file mode 100644 index 0000000000000..213fcc05eee2b --- /dev/null +++ b/tests/extmod/uctypes_addressof.py @@ -0,0 +1,19 @@ +# Test uctypes.addressof(). + +try: + from sys import maxsize + import uctypes +except ImportError: + print("SKIP") + raise SystemExit + +# Test small addresses. +for i in range(8): + print(uctypes.addressof(uctypes.bytearray_at(1 << i, 8))) + +# Test address that is bigger than the greatest small-int but still within the address range. +try: + large_addr = maxsize + 1 + print(uctypes.addressof(uctypes.bytearray_at(large_addr, 8)) == large_addr) +except OverflowError: + print(True) # systems with 64-bit bigints will overflow on the above operation diff --git a/tests/extmod/uctypes_addressof.py.exp b/tests/extmod/uctypes_addressof.py.exp new file mode 100644 index 0000000000000..5b48569d0185d --- /dev/null +++ b/tests/extmod/uctypes_addressof.py.exp @@ -0,0 +1,9 @@ +1 +2 +4 +8 +16 +32 +64 +128 +True diff --git a/tests/extmod/uctypes_array_load_store.py b/tests/extmod/uctypes_array_load_store.py index 0a82d789605c9..695352da57983 100644 --- a/tests/extmod/uctypes_array_load_store.py +++ b/tests/extmod/uctypes_array_load_store.py @@ -6,6 +6,13 @@ print("SKIP") raise SystemExit +# 'int' needs to be able to represent UINT64 for this test +try: + int("FF" * 8, 16) +except OverflowError: + print("SKIP") + raise SystemExit + N = 5 for endian in ("NATIVE", "LITTLE_ENDIAN", "BIG_ENDIAN"): @@ -15,6 +22,7 @@ data = bytearray(sz) s = uctypes.struct(uctypes.addressof(data), desc, getattr(uctypes, endian)) for i in range(N): + # CIRCUITPY-CHANGE: overflow checks try: s.arr[i] = i - 2 except OverflowError: diff --git a/tests/extmod/uctypes_sizeof.py b/tests/extmod/uctypes_sizeof.py index 6e52232e39eba..d295cc85b6828 100644 --- a/tests/extmod/uctypes_sizeof.py +++ b/tests/extmod/uctypes_sizeof.py @@ -43,8 +43,47 @@ print(uctypes.sizeof(S.sub)) assert uctypes.sizeof(S.sub) == 1 -# invalid descriptor +# invalid descriptors try: print(uctypes.sizeof([])) except TypeError: print("TypeError") + +try: + print(uctypes.sizeof(())) +except TypeError: + print("TypeError") + +try: + print(uctypes.sizeof(("garbage",))) +except TypeError: + print("TypeError") + +try: + # PTR * 3 is intended to be an invalid agg_type (STRUCT, PTR, ARRAY are valid ones). + print(uctypes.sizeof((uctypes.PTR * 3,))) +except TypeError: + print("TypeError") + +try: + print(uctypes.sizeof((0, {}, "garbage"))) +except TypeError: + print("TypeError") + +try: + print(uctypes.sizeof((uctypes.PTR | 0,))) +except TypeError: + print("TypeError") + +try: + print(uctypes.sizeof((uctypes.ARRAY | 0,))) +except TypeError: + print("TypeError") + +try: + print(uctypes.sizeof((uctypes.ARRAY | 0, 1, {}, "garbage"))) +except TypeError: + print("TypeError") + +# empty descriptor +print(uctypes.sizeof({})) diff --git a/tests/extmod/uctypes_sizeof.py.exp b/tests/extmod/uctypes_sizeof.py.exp index b35b11aa0cea9..edcc05a441f79 100644 --- a/tests/extmod/uctypes_sizeof.py.exp +++ b/tests/extmod/uctypes_sizeof.py.exp @@ -5,3 +5,11 @@ TypeError 6 1 TypeError +TypeError +TypeError +TypeError +TypeError +TypeError +TypeError +TypeError +0 diff --git a/tests/extmod/uctypes_sizeof_od.py b/tests/extmod/uctypes_sizeof_od.py index 375f05f5e2ce0..8aff363631508 100644 --- a/tests/extmod/uctypes_sizeof_od.py +++ b/tests/extmod/uctypes_sizeof_od.py @@ -45,9 +45,3 @@ print(uctypes.sizeof(S.sub)) assert uctypes.sizeof(S.sub) == 1 - -# invalid descriptor -try: - print(uctypes.sizeof([])) -except TypeError: - print("TypeError") diff --git a/tests/extmod/uctypes_sizeof_od.py.exp b/tests/extmod/uctypes_sizeof_od.py.exp index b35b11aa0cea9..fb74def602b97 100644 --- a/tests/extmod/uctypes_sizeof_od.py.exp +++ b/tests/extmod/uctypes_sizeof_od.py.exp @@ -4,4 +4,3 @@ TypeError 6 1 -TypeError diff --git a/tests/extmod/vfs_basic.py b/tests/extmod/vfs_basic.py index 028846406a145..2c0ce8f5295ad 100644 --- a/tests/extmod/vfs_basic.py +++ b/tests/extmod/vfs_basic.py @@ -1,10 +1,8 @@ # test VFS functionality without any particular filesystem type try: - import os - - os.mount -except (ImportError, AttributeError): + import os, vfs +except ImportError: print("SKIP") raise SystemExit @@ -59,11 +57,11 @@ def open(self, file, mode): # first we umount any existing mount points the target may have try: - os.umount("/") + vfs.umount("/") except OSError: pass for path in os.listdir("/"): - os.umount("/" + path) + vfs.umount("/" + path) # stat root dir print(os.stat("/")) @@ -83,7 +81,7 @@ def open(self, file, mode): print(func, arg, "OSError") # basic mounting and listdir -os.mount(Filesystem(1), "/test_mnt") +vfs.mount(Filesystem(1), "/test_mnt") print(os.listdir()) # ilistdir @@ -103,13 +101,13 @@ def open(self, file, mode): print(os.listdir("/test_mnt")) # mounting another filesystem -os.mount(Filesystem(2), "/test_mnt2", readonly=True) +vfs.mount(Filesystem(2), "/test_mnt2", readonly=True) print(os.listdir()) print(os.listdir("/test_mnt2")) # mounting over an existing mount point try: - os.mount(Filesystem(3), "/test_mnt2") + vfs.mount(Filesystem(3), "/test_mnt2") except OSError: print("OSError") @@ -139,23 +137,23 @@ def open(self, file, mode): open("test_file", "wb") # umount -os.umount("/test_mnt") -os.umount("/test_mnt2") +vfs.umount("/test_mnt") +vfs.umount("/test_mnt2") # umount a non-existent mount point try: - os.umount("/test_mnt") + vfs.umount("/test_mnt") except OSError: print("OSError") # root dir -os.mount(Filesystem(3), "/") +vfs.mount(Filesystem(3), "/") print(os.stat("/")) print(os.statvfs("/")) print(os.listdir()) open("test") -os.mount(Filesystem(4), "/mnt") +vfs.mount(Filesystem(4), "/mnt") print(os.listdir()) print(os.listdir("/mnt")) os.chdir("/mnt") @@ -166,9 +164,9 @@ def open(self, file, mode): print(os.listdir()) os.chdir("/") -os.umount("/") +vfs.umount("/") print(os.listdir("/")) -os.umount("/mnt") +vfs.umount("/mnt") # chdir to a non-existent mount point (current directory should remain unchanged) try: @@ -178,7 +176,7 @@ def open(self, file, mode): print(os.getcwd()) # chdir to a non-existent subdirectory in a mounted filesystem -os.mount(Filesystem(5, 1), "/mnt") +vfs.mount(Filesystem(5, 1), "/mnt") try: os.chdir("/mnt/subdir") except OSError: diff --git a/tests/extmod/vfs_blockdev.py b/tests/extmod/vfs_blockdev.py index f4c84ea9213c2..a1f0749962745 100644 --- a/tests/extmod/vfs_blockdev.py +++ b/tests/extmod/vfs_blockdev.py @@ -1,10 +1,10 @@ # Test for behaviour of combined standard and extended block device try: - import os + import vfs - os.VfsFat - os.VfsLfs2 + vfs.VfsFat + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -65,12 +65,10 @@ def test(bdev, vfs_class): try: - import os - bdev = RAMBlockDevice(50) except MemoryError: print("SKIP") raise SystemExit -test(bdev, os.VfsFat) -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsFat) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_blockdev_invalid.py b/tests/extmod/vfs_blockdev_invalid.py new file mode 100644 index 0000000000000..29d6bd6b2f9f7 --- /dev/null +++ b/tests/extmod/vfs_blockdev_invalid.py @@ -0,0 +1,89 @@ +# Tests where the block device returns invalid values + +try: + import vfs + + vfs.VfsFat + vfs.VfsLfs2 +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +class RAMBlockDevice: + ERASE_BLOCK_SIZE = 512 + + def __init__(self, blocks): + self.data = bytearray(blocks * self.ERASE_BLOCK_SIZE) + self.read_res = 0 + self.write_res = 0 + + def readblocks(self, block, buf, off=0): + # print("readblocks", block, len(buf), off) + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + buf[i] = self.data[addr + i] + return self.read_res + + def writeblocks(self, block, buf, off=None): + if off is None: + # erase, then write + off = 0 + addr = block * self.ERASE_BLOCK_SIZE + off + for i in range(len(buf)): + self.data[addr + i] = buf[i] + return self.write_res + + def ioctl(self, op, arg): + if op == 4: # block count + return len(self.data) // self.ERASE_BLOCK_SIZE + if op == 5: # block size + return self.ERASE_BLOCK_SIZE + if op == 6: # erase block + return 0 + + +try: + bdev = RAMBlockDevice(50) +except MemoryError: + print("SKIP") + raise SystemExit + + +def test(vfs_class): + print(vfs_class) + bdev.read_res = 0 # reset function results + bdev.write_res = 0 + + vfs_class.mkfs(bdev) + fs = vfs_class(bdev) + + with fs.open("test", "w") as f: + f.write("a" * 64) + + for res in (0, -5, 5, 33, "invalid"): + # -5 is a legitimate negative failure (EIO), positive integer + # is not + + # This variant will fail on open + bdev.read_res = res + try: + with fs.open("test", "r") as f: + print("opened") + except Exception as e: + print(type(e), e) + + # This variant should succeed on open, may fail on read + # unless the filesystem cached the contents already + bdev.read_res = 0 + try: + with fs.open("test", "r") as f: + bdev.read_res = res + print("read 1", f.read(1)) + print("read rest", f.read()) + except Exception as e: + print(type(e), e) + + +test(vfs.VfsLfs2) +test(vfs.VfsFat) diff --git a/tests/extmod/vfs_blockdev_invalid.py.exp b/tests/extmod/vfs_blockdev_invalid.py.exp new file mode 100644 index 0000000000000..0ea0353501de3 --- /dev/null +++ b/tests/extmod/vfs_blockdev_invalid.py.exp @@ -0,0 +1,28 @@ + +opened +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [Errno 5] EIO +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [Errno 22] EINVAL +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [Errno 22] EINVAL +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + can't convert str to int +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + +opened +read 1 a +read rest aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + [Errno 5] EIO + can't convert str to int + can't convert str to int diff --git a/tests/extmod/vfs_fat_case.py b/tests/extmod/vfs_fat_case.py index bf2c18ea69f11..6bc15eab10a44 100644 --- a/tests/extmod/vfs_fat_case.py +++ b/tests/extmod/vfs_fat_case.py @@ -1,3 +1,4 @@ +# CIRCUITPY-CHANGE: micropython does not have this file import errno import os as os diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py index 9f8bb9162db81..ca702e373adb4 100644 --- a/tests/extmod/vfs_fat_fileio1.py +++ b/tests/extmod/vfs_fat_fileio1.py @@ -1,13 +1,8 @@ try: - import errno - import os -except ImportError: - print("SKIP") - raise SystemExit + import errno, os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -40,13 +35,13 @@ def ioctl(self, op, arg): try: bdev = RAMFS(50) - os.VfsFat.mkfs(bdev) + vfs.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -vfs = os.VfsFat(bdev) -os.mount(vfs, "/ramdisk") +fs = vfs.VfsFat(bdev) +vfs.mount(fs, "/ramdisk") os.chdir("/ramdisk") # file IO @@ -101,12 +96,12 @@ def ioctl(self, op, arg): # print(f.read()) # dirs -vfs.mkdir("foo_dir") +fs.mkdir("foo_dir") try: - vfs.rmdir("foo_file.txt") + fs.rmdir("foo_file.txt") except OSError as e: print(e.errno == 20) # errno.ENOTDIR -vfs.remove("foo_file.txt") -print(list(vfs.ilistdir())) +fs.remove("foo_file.txt") +print(list(fs.ilistdir())) diff --git a/tests/extmod/vfs_fat_fileio2.py b/tests/extmod/vfs_fat_fileio2.py index 4059ec337daea..744f3bf11b1dd 100644 --- a/tests/extmod/vfs_fat_fileio2.py +++ b/tests/extmod/vfs_fat_fileio2.py @@ -1,13 +1,8 @@ try: - import errno - import os -except ImportError: - print("SKIP") - raise SystemExit + import errno, os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -38,32 +33,32 @@ def ioctl(self, op, arg): try: bdev = RAMFS(50) - os.VfsFat.mkfs(bdev) + vfs.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -vfs = os.VfsFat(bdev) -os.mount(vfs, "/ramdisk") +fs = vfs.VfsFat(bdev) +vfs.mount(fs, "/ramdisk") os.chdir("/ramdisk") try: - vfs.mkdir("foo_dir") + fs.mkdir("foo_dir") except OSError as e: print(e.errno == errno.EEXIST) try: - vfs.remove("foo_dir") + fs.remove("foo_dir") except OSError as e: print(e.errno == errno.EISDIR) try: - vfs.remove("no_file.txt") + fs.remove("no_file.txt") except OSError as e: print(e.errno == errno.ENOENT) try: - vfs.rename("foo_dir", "/null/file") + fs.rename("foo_dir", "/null/file") except OSError as e: print(e.errno == errno.ENOENT) @@ -85,34 +80,34 @@ def ioctl(self, op, arg): # directory not empty try: - vfs.rmdir("foo_dir") + fs.rmdir("foo_dir") except OSError as e: print(e.errno == errno.EACCES) # trim full path -vfs.rename("foo_dir/file-in-dir.txt", "foo_dir/file.txt") -print(list(vfs.ilistdir("foo_dir"))) +fs.rename("foo_dir/file-in-dir.txt", "foo_dir/file.txt") +print(list(fs.ilistdir("foo_dir"))) -vfs.rename("foo_dir/file.txt", "moved-to-root.txt") -print(list(vfs.ilistdir())) +fs.rename("foo_dir/file.txt", "moved-to-root.txt") +print(list(fs.ilistdir())) # check that renaming to existing file will overwrite it with open("temp", "w") as f: f.write("new text") -vfs.rename("temp", "moved-to-root.txt") -print(list(vfs.ilistdir())) +fs.rename("temp", "moved-to-root.txt") +print(list(fs.ilistdir())) with open("moved-to-root.txt") as f: print(f.read()) # valid removes -vfs.remove("foo_dir/sub_file.txt") -vfs.rmdir("foo_dir") -print(list(vfs.ilistdir())) +fs.remove("foo_dir/sub_file.txt") +fs.rmdir("foo_dir") +print(list(fs.ilistdir())) # disk full try: - bsize = vfs.statvfs("/ramdisk")[0] - free = vfs.statvfs("/ramdisk")[2] + 1 + bsize = fs.statvfs("/ramdisk")[0] + free = fs.statvfs("/ramdisk")[2] + 1 f = open("large_file.txt", "wb") f.write(bytearray(bsize * free)) except OSError as e: diff --git a/tests/extmod/vfs_fat_finaliser.py b/tests/extmod/vfs_fat_finaliser.py index a2cce7846c22b..7be3cda1a353a 100644 --- a/tests/extmod/vfs_fat_finaliser.py +++ b/tests/extmod/vfs_fat_finaliser.py @@ -1,9 +1,9 @@ # Test VfsFat class and its finaliser try: - import errno, os + import errno, os, vfs - os.VfsFat + vfs.VfsFat except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -39,8 +39,8 @@ def ioctl(self, op, arg): raise SystemExit # Format block device and create VFS object -os.VfsFat.mkfs(bdev) -vfs = os.VfsFat(bdev) +vfs.VfsFat.mkfs(bdev) +fs = vfs.VfsFat(bdev) # Here we test that opening a file with the heap locked fails correctly. This # is a special case because file objects use a finaliser and allocating with a @@ -52,7 +52,7 @@ def ioctl(self, op, arg): try: import errno, os - vfs.open("x", "r") + fs.open("x", "r") except MemoryError: print("MemoryError") micropython.heap_unlock() @@ -77,10 +77,10 @@ def ioctl(self, op, arg): # Only read back N-1 files because the last one may not be finalised due to # references to it being left on the C stack. for n in names: - f = vfs.open(n, "w") + f = fs.open(n, "w") f.write(n) f = None # release f without closing gc.collect() # should finalise at least the first N-1 files by closing them for n in names[:-1]: - with vfs.open(n, "r") as f: + with fs.open(n, "r") as f: print(f.read()) diff --git a/tests/extmod/vfs_fat_ilistdir_del.py b/tests/extmod/vfs_fat_ilistdir_del.py index 055836ad71bef..964e6b12868eb 100644 --- a/tests/extmod/vfs_fat_ilistdir_del.py +++ b/tests/extmod/vfs_fat_ilistdir_del.py @@ -1,10 +1,9 @@ # Test ilistdir __del__ for VfsFat using a RAM device. -import gc try: - import os + import gc, os, vfs - os.VfsFat + vfs.VfsFat except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -37,29 +36,29 @@ def ioctl(self, op, arg): def test(bdev, vfs_class): vfs_class.mkfs(bdev) - vfs = vfs_class(bdev) - vfs.mkdir("/test_d1") - vfs.mkdir("/test_d2") - vfs.mkdir("/test_d3") + fs = vfs_class(bdev) + fs.mkdir("/test_d1") + fs.mkdir("/test_d2") + fs.mkdir("/test_d3") for i in range(10): print(i) # We want to partially iterate the ilistdir iterator to leave it in an # open state, which will then test the finaliser when it's garbage collected. - idir = vfs.ilistdir("/") + idir = fs.ilistdir("/") print(any(idir)) # Alternate way of partially iterating the ilistdir object, modifying the # filesystem while it's open. - for dname, *_ in vfs.ilistdir("/"): - vfs.rmdir(dname) + for dname, *_ in fs.ilistdir("/"): + fs.rmdir(dname) break - vfs.mkdir(dname) + fs.mkdir(dname) - # Also create a fully drained iterator and ensure trying to re-use it + # Also create a fully drained iterator and ensure trying to reuse it # throws the correct exception. - idir_emptied = vfs.ilistdir("/") + idir_emptied = fs.ilistdir("/") l = list(idir_emptied) print(len(l)) try: @@ -68,7 +67,7 @@ def test(bdev, vfs_class): pass gc.collect() - vfs.open("/test", "w").close() + fs.open("/test", "w").close() try: @@ -77,4 +76,4 @@ def test(bdev, vfs_class): print("SKIP") raise SystemExit -test(bdev, os.VfsFat) +test(bdev, vfs.VfsFat) diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py index 9096024c4a960..6605964d43323 100644 --- a/tests/extmod/vfs_fat_more.py +++ b/tests/extmod/vfs_fat_more.py @@ -1,12 +1,8 @@ try: - import os -except ImportError: - print("SKIP") - raise SystemExit + import os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -46,14 +42,14 @@ def ioctl(self, op, arg): # first we umount any existing mount points the target may have try: - os.umount("/") + vfs.umount("/") except OSError: pass for path in os.listdir("/"): - os.umount("/" + path) + vfs.umount("/" + path) -os.VfsFat.mkfs(bdev) -os.mount(bdev, "/") +vfs.VfsFat.mkfs(bdev) +vfs.mount(bdev, "/") print(os.getcwd()) @@ -96,8 +92,8 @@ def ioctl(self, op, arg): os.chdir("/") print(os.stat("test5.txt")[:-3]) -os.VfsFat.mkfs(bdev2) -os.mount(bdev2, "/sys") +vfs.VfsFat.mkfs(bdev2) +vfs.mount(bdev2, "/sys") print(os.listdir()) print(os.listdir("sys")) print(os.listdir("/sys")) @@ -106,7 +102,7 @@ def ioctl(self, op, arg): os.remove("test5.txt") print(os.listdir()) -os.umount("/") +vfs.umount("/") print(os.getcwd()) print(os.listdir()) print(os.listdir("sys")) diff --git a/tests/extmod/vfs_fat_mtime.py b/tests/extmod/vfs_fat_mtime.py index 1ceb611364a18..0c7e10a54869d 100644 --- a/tests/extmod/vfs_fat_mtime.py +++ b/tests/extmod/vfs_fat_mtime.py @@ -1,11 +1,11 @@ # Test for VfsFat using a RAM device, mtime feature try: - import time, os + import time, os, vfs time.time time.sleep - os.VfsFat + vfs.VfsFat except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -41,21 +41,21 @@ def test(bdev, vfs_class): vfs_class.mkfs(bdev) # construction - vfs = vfs_class(bdev) + fs = vfs_class(bdev) # Create an empty file, should have a timestamp. current_time = int(time.time()) - vfs.open("test1", "wt").close() + fs.open("test1", "wt").close() # Wait 2 seconds so mtime will increase (FAT has 2 second resolution). time.sleep(2) # Create another empty file, should have a timestamp. - vfs.open("test2", "wt").close() + fs.open("test2", "wt").close() # Stat the files and check mtime is non-zero. - stat1 = vfs.stat("test1") - stat2 = vfs.stat("test2") + stat1 = fs.stat("test1") + stat2 = fs.stat("test2") print(stat1[8] != 0, stat2[8] != 0) # Check that test1 has mtime which matches time.time() at point of creation. @@ -67,8 +67,8 @@ def test(bdev, vfs_class): print(stat1[8] < stat2[8]) # Unmount. - vfs.umount() + fs.umount() bdev = RAMBlockDevice(50) -test(bdev, os.VfsFat) +test(bdev, vfs.VfsFat) diff --git a/tests/extmod/vfs_fat_oldproto.py b/tests/extmod/vfs_fat_oldproto.py index 72b414cf01b16..53c262cdd9c8b 100644 --- a/tests/extmod/vfs_fat_oldproto.py +++ b/tests/extmod/vfs_fat_oldproto.py @@ -1,13 +1,8 @@ try: - import errno - import os -except ImportError: - print("SKIP") - raise SystemExit + import errno, os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -45,18 +40,18 @@ def count(self): print("SKIP") raise SystemExit -os.VfsFat.mkfs(bdev) -vfs = os.VfsFat(bdev) -os.mount(vfs, "/ramdisk") +vfs.VfsFat.mkfs(bdev) +fs = vfs.VfsFat(bdev) +vfs.mount(fs, "/ramdisk") # file io -with vfs.open("file.txt", "w") as f: +with fs.open("file.txt", "w") as f: f.write("hello!") -print(list(vfs.ilistdir())) +print(list(fs.ilistdir())) -with vfs.open("file.txt", "r") as f: +with fs.open("file.txt", "r") as f: print(f.read()) -vfs.remove("file.txt") -print(list(vfs.ilistdir())) +fs.remove("file.txt") +print(list(fs.ilistdir())) diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index 6f822892d408a..d3836414c4dee 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -1,13 +1,8 @@ try: - import errno - import os -except ImportError: - print("SKIP") - raise SystemExit + import errno, os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -42,7 +37,7 @@ def ioctl(self, op, arg): try: bdev = RAMFS(50) - os.VfsFat.mkfs(bdev) + vfs.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit @@ -50,53 +45,50 @@ def ioctl(self, op, arg): print(b"FOO_FILETXT" not in bdev.data) print(b"hello!" not in bdev.data) -vfs = os.VfsFat(bdev) -os.mount(vfs, "/ramdisk") +fs = vfs.VfsFat(bdev) +vfs.mount(fs, "/ramdisk") -# CIRCUITPY-CHANGE -vfs.label = "label test" -print("label:", vfs.label) -print("statvfs:", vfs.statvfs("/ramdisk")) -print("getcwd:", vfs.getcwd()) +print("statvfs:", fs.statvfs("/ramdisk")) +print("getcwd:", fs.getcwd()) try: - vfs.stat("no_file.txt") + fs.stat("no_file.txt") except OSError as e: print(e.errno == errno.ENOENT) -with vfs.open("foo_file.txt", "w") as f: +with fs.open("foo_file.txt", "w") as f: f.write("hello!") -print(list(vfs.ilistdir())) +print(list(fs.ilistdir())) -print("stat root:", vfs.stat("/")[:-3]) # timestamps differ across runs -print("stat file:", vfs.stat("foo_file.txt")[:-3]) # timestamps differ across runs +print("stat root:", fs.stat("/")[:-3]) # timestamps differ across runs +print("stat file:", fs.stat("foo_file.txt")[:-3]) # timestamps differ across runs print(b"FOO_FILETXT" in bdev.data) print(b"hello!" in bdev.data) -vfs.mkdir("foo_dir") -vfs.chdir("foo_dir") -print("getcwd:", vfs.getcwd()) -print(list(vfs.ilistdir())) +fs.mkdir("foo_dir") +fs.chdir("foo_dir") +print("getcwd:", fs.getcwd()) +print(list(fs.ilistdir())) -with vfs.open("sub_file.txt", "w") as f: +with fs.open("sub_file.txt", "w") as f: f.write("subdir file") try: - vfs.chdir("sub_file.txt") + fs.chdir("sub_file.txt") except OSError as e: print(e.errno == errno.ENOENT) -vfs.chdir("..") -print("getcwd:", vfs.getcwd()) +fs.chdir("..") +print("getcwd:", fs.getcwd()) -os.umount(vfs) +vfs.umount(fs) -vfs = os.VfsFat(bdev) -print(list(vfs.ilistdir(b""))) +fs = vfs.VfsFat(bdev) +print(list(fs.ilistdir(b""))) # list a non-existent directory try: - vfs.ilistdir(b"no_exist") + fs.ilistdir(b"no_exist") except OSError as e: print("ENOENT:", e.errno == errno.ENOENT) diff --git a/tests/extmod/vfs_fat_ramdisklarge.py b/tests/extmod/vfs_fat_ramdisklarge.py index 40cba9ee430a1..38ad772b44397 100644 --- a/tests/extmod/vfs_fat_ramdisklarge.py +++ b/tests/extmod/vfs_fat_ramdisklarge.py @@ -1,14 +1,10 @@ # test making a FAT filesystem on a very large block device try: - import os -except ImportError: - print("SKIP") - raise SystemExit + import os, vfs -try: - os.VfsFat -except AttributeError: + vfs.VfsFat +except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -46,24 +42,24 @@ def ioctl(self, op, arg): try: bdev = RAMBDevSparse(4 * 1024 * 1024 * 1024 // RAMBDevSparse.SEC_SIZE) - os.VfsFat.mkfs(bdev) + vfs.VfsFat.mkfs(bdev) except MemoryError: print("SKIP") raise SystemExit -vfs = os.VfsFat(bdev) -os.mount(vfs, "/ramdisk") +fs = vfs.VfsFat(bdev) +vfs.mount(fs, "/ramdisk") -print("statvfs:", vfs.statvfs("/ramdisk")) +print("statvfs:", fs.statvfs("/ramdisk")) f = open("/ramdisk/test.txt", "w") f.write("test file") f.close() -print("statvfs:", vfs.statvfs("/ramdisk")) +print("statvfs:", fs.statvfs("/ramdisk")) f = open("/ramdisk/test.txt") print(f.read()) f.close() -os.umount(vfs) +vfs.umount(fs) diff --git a/tests/extmod/vfs_lfs.py b/tests/extmod/vfs_lfs.py index 83377653b2cfb..40d58e9c9f743 100644 --- a/tests/extmod/vfs_lfs.py +++ b/tests/extmod/vfs_lfs.py @@ -1,10 +1,10 @@ # Test for VfsLittle using a RAM device try: - import os + import os, vfs - os.VfsLfs1 - os.VfsLfs2 + vfs.VfsLfs1 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -47,44 +47,44 @@ def test(bdev, vfs_class): vfs_class.mkfs(bdev) # construction - vfs = vfs_class(bdev) + fs = vfs_class(bdev) # statvfs - print(vfs.statvfs("/")) + print(fs.statvfs("/")) # open, write close - f = vfs.open("test", "w") + f = fs.open("test", "w") f.write("littlefs") f.close() # statvfs after creating a file - print(vfs.statvfs("/")) + print(fs.statvfs("/")) # ilistdir - print(list(vfs.ilistdir())) - print(list(vfs.ilistdir("/"))) - print(list(vfs.ilistdir(b"/"))) + print(list(fs.ilistdir())) + print(list(fs.ilistdir("/"))) + print(list(fs.ilistdir(b"/"))) # mkdir, rmdir - vfs.mkdir("testdir") - print(list(vfs.ilistdir())) - print(sorted(list(vfs.ilistdir("testdir")))) - vfs.rmdir("testdir") - print(list(vfs.ilistdir())) - vfs.mkdir("testdir") + fs.mkdir("testdir") + print(list(fs.ilistdir())) + print(sorted(list(fs.ilistdir("testdir")))) + fs.rmdir("testdir") + print(list(fs.ilistdir())) + fs.mkdir("testdir") # stat a file - print_stat(vfs.stat("test")) + print_stat(fs.stat("test")) # stat a dir (size seems to vary on LFS2 so don't print that) - print_stat(vfs.stat("testdir"), False) + print_stat(fs.stat("testdir"), False) # read - with vfs.open("test", "r") as f: + with fs.open("test", "r") as f: print(f.read()) # create large file - with vfs.open("testbig", "w") as f: + with fs.open("testbig", "w") as f: data = "large012" * 32 * 16 print("data length:", len(data)) for i in range(4): @@ -92,63 +92,63 @@ def test(bdev, vfs_class): f.write(data) # stat after creating large file - print(vfs.statvfs("/")) + print(fs.statvfs("/")) # rename - vfs.rename("testbig", "testbig2") - print(sorted(list(vfs.ilistdir()))) - vfs.chdir("testdir") - vfs.rename("/testbig2", "testbig2") - print(sorted(list(vfs.ilistdir()))) - vfs.rename("testbig2", "/testbig2") - vfs.chdir("/") - print(sorted(list(vfs.ilistdir()))) + fs.rename("testbig", "testbig2") + print(sorted(list(fs.ilistdir()))) + fs.chdir("testdir") + fs.rename("/testbig2", "testbig2") + print(sorted(list(fs.ilistdir()))) + fs.rename("testbig2", "/testbig2") + fs.chdir("/") + print(sorted(list(fs.ilistdir()))) # remove - vfs.remove("testbig2") - print(sorted(list(vfs.ilistdir()))) + fs.remove("testbig2") + print(sorted(list(fs.ilistdir()))) # getcwd, chdir - vfs.mkdir("/testdir2") - vfs.mkdir("/testdir/subdir") - print(vfs.getcwd()) - vfs.chdir("/testdir") - print(vfs.getcwd()) + fs.mkdir("/testdir2") + fs.mkdir("/testdir/subdir") + print(fs.getcwd()) + fs.chdir("/testdir") + print(fs.getcwd()) # create file in directory to make sure paths are relative - vfs.open("test2", "w").close() - print_stat(vfs.stat("test2")) - print_stat(vfs.stat("/testdir/test2")) - vfs.remove("test2") + fs.open("test2", "w").close() + print_stat(fs.stat("test2")) + print_stat(fs.stat("/testdir/test2")) + fs.remove("test2") # chdir back to root and remove testdir - vfs.chdir("/") - print(vfs.getcwd()) - vfs.chdir("testdir") - print(vfs.getcwd()) - vfs.chdir("..") - print(vfs.getcwd()) - vfs.chdir("testdir/subdir") - print(vfs.getcwd()) - vfs.chdir("../..") - print(vfs.getcwd()) - vfs.chdir("/./testdir2") - print(vfs.getcwd()) - vfs.chdir("../testdir") - print(vfs.getcwd()) - vfs.chdir("../..") - print(vfs.getcwd()) - vfs.chdir(".//testdir") - print(vfs.getcwd()) - vfs.chdir("subdir/./") - print(vfs.getcwd()) - vfs.chdir("/") - print(vfs.getcwd()) - vfs.rmdir("testdir/subdir") - vfs.rmdir("testdir") - vfs.rmdir("testdir2") + fs.chdir("/") + print(fs.getcwd()) + fs.chdir("testdir") + print(fs.getcwd()) + fs.chdir("..") + print(fs.getcwd()) + fs.chdir("testdir/subdir") + print(fs.getcwd()) + fs.chdir("../..") + print(fs.getcwd()) + fs.chdir("/./testdir2") + print(fs.getcwd()) + fs.chdir("../testdir") + print(fs.getcwd()) + fs.chdir("..") + print(fs.getcwd()) + fs.chdir(".//testdir") + print(fs.getcwd()) + fs.chdir("subdir/./") + print(fs.getcwd()) + fs.chdir("/") + print(fs.getcwd()) + fs.rmdir("testdir/subdir") + fs.rmdir("testdir") + fs.rmdir("testdir2") bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs1) -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsLfs1) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_corrupt.py b/tests/extmod/vfs_lfs_corrupt.py index c49dcad92b441..0365c0c23f3c8 100644 --- a/tests/extmod/vfs_lfs_corrupt.py +++ b/tests/extmod/vfs_lfs_corrupt.py @@ -1,10 +1,10 @@ # Test for VfsLittle using a RAM device, testing error handling from corrupt block device try: - import os + import vfs - os.VfsLfs1 - os.VfsLfs2 + vfs.VfsLfs1 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -47,28 +47,28 @@ def corrupt(bdev, block): def create_vfs(bdev, vfs_class): bdev.ret = 0 vfs_class.mkfs(bdev) - vfs = vfs_class(bdev) - with vfs.open("f", "w") as f: + fs = vfs_class(bdev) + with fs.open("f", "w") as f: for i in range(100): f.write("test") - return vfs + return fs def test(bdev, vfs_class): print("test", vfs_class) # statvfs - vfs = create_vfs(bdev, vfs_class) + fs = create_vfs(bdev, vfs_class) corrupt(bdev, 0) corrupt(bdev, 1) try: - print(vfs.statvfs("")) + print(fs.statvfs("")) except OSError: print("statvfs OSError") # error during read - vfs = create_vfs(bdev, vfs_class) - f = vfs.open("f", "r") + fs = create_vfs(bdev, vfs_class) + f = fs.open("f", "r") bdev.ret = -5 # EIO try: f.read(10) @@ -76,8 +76,8 @@ def test(bdev, vfs_class): print("read OSError") # error during write - vfs = create_vfs(bdev, vfs_class) - f = vfs.open("f", "a") + fs = create_vfs(bdev, vfs_class) + f = fs.open("f", "a") bdev.ret = -5 # EIO try: f.write("test") @@ -85,8 +85,8 @@ def test(bdev, vfs_class): print("write OSError") # error during close - vfs = create_vfs(bdev, vfs_class) - f = vfs.open("f", "w") + fs = create_vfs(bdev, vfs_class) + f = fs.open("f", "w") f.write("test") bdev.ret = -5 # EIO try: @@ -95,8 +95,8 @@ def test(bdev, vfs_class): print("close OSError") # error during flush - vfs = create_vfs(bdev, vfs_class) - f = vfs.open("f", "w") + fs = create_vfs(bdev, vfs_class) + f = fs.open("f", "w") f.write("test") bdev.ret = -5 # EIO try: @@ -108,5 +108,5 @@ def test(bdev, vfs_class): bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs1) -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsLfs1) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_error.py b/tests/extmod/vfs_lfs_error.py index 32b76b2821258..73cdf3437330b 100644 --- a/tests/extmod/vfs_lfs_error.py +++ b/tests/extmod/vfs_lfs_error.py @@ -1,10 +1,10 @@ # Test for VfsLittle using a RAM device, testing error handling try: - import os + import errno, vfs - os.VfsLfs1 - os.VfsLfs2 + vfs.VfsLfs1 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -41,81 +41,81 @@ def test(bdev, vfs_class): # mkfs with too-small block device try: vfs_class.mkfs(RAMBlockDevice(1)) - except OSError: - print("mkfs OSError") + except OSError as er: + print("mkfs OSError", er.errno > 0) # mount with invalid filesystem try: vfs_class(bdev) - except OSError: - print("mount OSError") + except OSError as er: + print("mount OSError", er.errno > 0) # set up for following tests vfs_class.mkfs(bdev) - vfs = vfs_class(bdev) - with vfs.open("testfile", "w") as f: + fs = vfs_class(bdev) + with fs.open("testfile", "w") as f: f.write("test") - vfs.mkdir("testdir") + fs.mkdir("testdir") # ilistdir try: - vfs.ilistdir("noexist") - except OSError: - print("ilistdir OSError") + fs.ilistdir("noexist") + except OSError as er: + print("ilistdir OSError", er) # remove try: - vfs.remove("noexist") - except OSError: - print("remove OSError") + fs.remove("noexist") + except OSError as er: + print("remove OSError", er) # rmdir try: - vfs.rmdir("noexist") - except OSError: - print("rmdir OSError") + fs.rmdir("noexist") + except OSError as er: + print("rmdir OSError", er) # rename try: - vfs.rename("noexist", "somethingelse") - except OSError: - print("rename OSError") + fs.rename("noexist", "somethingelse") + except OSError as er: + print("rename OSError", er) # mkdir try: - vfs.mkdir("testdir") - except OSError: - print("mkdir OSError") + fs.mkdir("testdir") + except OSError as er: + print("mkdir OSError", er) # chdir to nonexistent try: - vfs.chdir("noexist") - except OSError: - print("chdir OSError") - print(vfs.getcwd()) # check still at root + fs.chdir("noexist") + except OSError as er: + print("chdir OSError", er) + print(fs.getcwd()) # check still at root # chdir to file try: - vfs.chdir("testfile") - except OSError: - print("chdir OSError") - print(vfs.getcwd()) # check still at root + fs.chdir("testfile") + except OSError as er: + print("chdir OSError", er) + print(fs.getcwd()) # check still at root # stat try: - vfs.stat("noexist") - except OSError: - print("stat OSError") + fs.stat("noexist") + except OSError as er: + print("stat OSError", er) # error during seek - with vfs.open("testfile", "r") as f: + with fs.open("testfile", "r") as f: f.seek(1 << 30) # SEEK_SET try: f.seek(1 << 30, 1) # SEEK_CUR - except OSError: - print("seek OSError") + except OSError as er: + print("seek OSError", er) bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs1) -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsLfs1) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_error.py.exp b/tests/extmod/vfs_lfs_error.py.exp index f4327f6962ec3..440607ed84b22 100644 --- a/tests/extmod/vfs_lfs_error.py.exp +++ b/tests/extmod/vfs_lfs_error.py.exp @@ -1,28 +1,28 @@ test -mkfs OSError -mount OSError -ilistdir OSError -remove OSError -rmdir OSError -rename OSError -mkdir OSError -chdir OSError +mkfs OSError True +mount OSError True +ilistdir OSError [Errno 2] ENOENT +remove OSError [Errno 2] ENOENT +rmdir OSError [Errno 2] ENOENT +rename OSError [Errno 2] ENOENT +mkdir OSError [Errno 17] EEXIST +chdir OSError [Errno 2] ENOENT / -chdir OSError +chdir OSError [Errno 2] ENOENT / -stat OSError -seek OSError +stat OSError [Errno 2] ENOENT +seek OSError [Errno 22] EINVAL test -mkfs OSError -mount OSError -ilistdir OSError -remove OSError -rmdir OSError -rename OSError -mkdir OSError -chdir OSError +mkfs OSError True +mount OSError True +ilistdir OSError [Errno 2] ENOENT +remove OSError [Errno 2] ENOENT +rmdir OSError [Errno 2] ENOENT +rename OSError [Errno 2] ENOENT +mkdir OSError [Errno 17] EEXIST +chdir OSError [Errno 2] ENOENT / -chdir OSError +chdir OSError [Errno 2] ENOENT / -stat OSError -seek OSError +stat OSError [Errno 2] ENOENT +seek OSError [Errno 22] EINVAL diff --git a/tests/extmod/vfs_lfs_file.py b/tests/extmod/vfs_lfs_file.py index b745bb8112def..2620d9f729620 100644 --- a/tests/extmod/vfs_lfs_file.py +++ b/tests/extmod/vfs_lfs_file.py @@ -1,10 +1,10 @@ # Test for VfsLittle using a RAM device, file IO try: - import os + import vfs - os.VfsLfs1 - os.VfsLfs2 + vfs.VfsLfs1 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -42,10 +42,10 @@ def test(bdev, vfs_class): vfs_class.mkfs(bdev) # construction - vfs = vfs_class(bdev) + fs = vfs_class(bdev) # create text, print, write, close - f = vfs.open("test.txt", "wt") + f = fs.open("test.txt", "wt") print(f) f.write("littlefs") f.close() @@ -54,7 +54,7 @@ def test(bdev, vfs_class): f.close() # create binary, print, write, flush, close - f = vfs.open("test.bin", "wb") + f = fs.open("test.bin", "wb") print(f) # CIRCUITPY-CHANGE f.write(b"littlefs") @@ -62,43 +62,43 @@ def test(bdev, vfs_class): f.close() # create for append - f = vfs.open("test.bin", "ab") + f = fs.open("test.bin", "ab") # CIRCUITPY-CHANGE f.write(b"more") f.close() # create exclusive - f = vfs.open("test2.bin", "xb") + f = fs.open("test2.bin", "xb") f.close() # create exclusive with error try: - vfs.open("test2.bin", "x") + fs.open("test2.bin", "x") except OSError: print("open OSError") # read default - with vfs.open("test.txt", "") as f: + with fs.open("test.txt", "") as f: print(f.read()) # read text - with vfs.open("test.txt", "rt") as f: + with fs.open("test.txt", "rt") as f: print(f.read()) # read binary - with vfs.open("test.bin", "rb") as f: + with fs.open("test.bin", "rb") as f: print(f.read()) # create read and write - with vfs.open("test.bin", "r+b") as f: + with fs.open("test.bin", "r+b") as f: print(f.read(8)) # CIRCUITPY-CHANGE f.write(b"MORE") - with vfs.open("test.bin", "rb") as f: + with fs.open("test.bin", "rb") as f: print(f.read()) # seek and tell - f = vfs.open("test.txt", "r") + f = fs.open("test.txt", "r") print(f.tell()) f.seek(3, 0) print(f.tell()) @@ -106,13 +106,13 @@ def test(bdev, vfs_class): # open nonexistent try: - vfs.open("noexist", "r") + fs.open("noexist", "r") except OSError: print("open OSError") # open multiple files at the same time - f1 = vfs.open("test.txt", "") - f2 = vfs.open("test.bin", "b") + f1 = fs.open("test.txt", "") + f2 = fs.open("test.bin", "b") print(f1.read()) print(f2.read()) f1.close() @@ -120,5 +120,5 @@ def test(bdev, vfs_class): bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs1) -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsLfs1) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_ilistdir_del.py b/tests/extmod/vfs_lfs_ilistdir_del.py index ff66717147868..828c85a258856 100644 --- a/tests/extmod/vfs_lfs_ilistdir_del.py +++ b/tests/extmod/vfs_lfs_ilistdir_del.py @@ -1,10 +1,9 @@ # Test ilistdir __del__ for VfsLittle using a RAM device. -import gc try: - import os + import gc, vfs - os.VfsLfs2 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -37,29 +36,29 @@ def ioctl(self, op, arg): def test(bdev, vfs_class): vfs_class.mkfs(bdev) - vfs = vfs_class(bdev) - vfs.mkdir("/test_d1") - vfs.mkdir("/test_d2") - vfs.mkdir("/test_d3") + fs = vfs_class(bdev) + fs.mkdir("/test_d1") + fs.mkdir("/test_d2") + fs.mkdir("/test_d3") for i in range(10): print(i) # We want to partially iterate the ilistdir iterator to leave it in an # open state, which will then test the finaliser when it's garbage collected. - idir = vfs.ilistdir("/") + idir = fs.ilistdir("/") print(any(idir)) # Alternate way of partially iterating the ilistdir object, modifying the # filesystem while it's open. - for dname, *_ in vfs.ilistdir("/"): - vfs.rmdir(dname) + for dname, *_ in fs.ilistdir("/"): + fs.rmdir(dname) break - vfs.mkdir(dname) + fs.mkdir(dname) - # Also create a fully drained iterator and ensure trying to re-use it + # Also create a fully drained iterator and ensure trying to reuse it # throws the correct exception. - idir_emptied = vfs.ilistdir("/") + idir_emptied = fs.ilistdir("/") l = list(idir_emptied) print(len(l)) try: @@ -68,8 +67,13 @@ def test(bdev, vfs_class): pass gc.collect() - vfs.open("/test", "w").close() + fs.open("/test", "w").close() -bdev = RAMBlockDevice(30) -test(bdev, os.VfsLfs2) +try: + bdev = RAMBlockDevice(30) +except MemoryError: + print("SKIP") + raise SystemExit + +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_mount.py b/tests/extmod/vfs_lfs_mount.py index 4ebd9ac6233f8..4887ddcec0085 100644 --- a/tests/extmod/vfs_lfs_mount.py +++ b/tests/extmod/vfs_lfs_mount.py @@ -1,10 +1,10 @@ # Test for VfsLittle using a RAM device, with mount/umount try: - import os + import os, vfs - os.VfsLfs1 - os.VfsLfs2 + vfs.VfsLfs1 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -42,7 +42,7 @@ def test(vfs_class): # mount bdev unformatted try: - os.mount(bdev, "/lfs") + vfs.mount(bdev, "/lfs") except Exception as er: print(repr(er)) @@ -50,10 +50,10 @@ def test(vfs_class): vfs_class.mkfs(bdev) # construction - vfs = vfs_class(bdev) + fs = vfs_class(bdev) # mount - os.mount(vfs, "/lfs") + vfs.mount(fs, "/lfs") # import with open("/lfs/lfsmod.py", "w") as f: @@ -73,11 +73,11 @@ def test(vfs_class): import lfsmod2 # umount - os.umount("/lfs") + vfs.umount("/lfs") # mount read-only - vfs = vfs_class(bdev) - os.mount(vfs, "/lfs", readonly=True) + fs = vfs_class(bdev) + vfs.mount(fs, "/lfs", readonly=True) # test reading works with open("/lfs/subdir/lfsmod2.py") as f: @@ -90,13 +90,13 @@ def test(vfs_class): print(repr(er)) # umount - os.umount("/lfs") + vfs.umount("/lfs") # mount bdev again - os.mount(bdev, "/lfs") + vfs.mount(bdev, "/lfs") # umount - os.umount("/lfs") + vfs.umount("/lfs") # clear imported modules sys.modules.clear() @@ -110,5 +110,5 @@ def test(vfs_class): sys.path.append("") # run tests -test(os.VfsLfs1) -test(os.VfsLfs2) +test(vfs.VfsLfs1) +test(vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_mtime.py b/tests/extmod/vfs_lfs_mtime.py index ade02fa144987..d4404de4dcb88 100644 --- a/tests/extmod/vfs_lfs_mtime.py +++ b/tests/extmod/vfs_lfs_mtime.py @@ -1,11 +1,11 @@ # Test for VfsLfs using a RAM device, mtime feature try: - import time, os + import time, vfs - time.time + time.time_ns time.sleep - os.VfsLfs2 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -44,24 +44,25 @@ def test(bdev, vfs_class): # construction print("mtime=True") - vfs = vfs_class(bdev, mtime=True) + fs = vfs_class(bdev, mtime=True) # Create an empty file, should have a timestamp. - current_time = int(time.time()) - vfs.open("test1", "wt").close() + # Use time_ns() for current time because that's what's used for VfsLfs2 time. + current_time = time.time_ns() // 1_000_000_000 + fs.open("test1", "wt").close() # Wait 1 second so mtime will increase by at least 1. time.sleep(1) # Create another empty file, should have a timestamp. - vfs.open("test2", "wt").close() + fs.open("test2", "wt").close() # Stat the files and check mtime is non-zero. - stat1 = vfs.stat("test1") - stat2 = vfs.stat("test2") + stat1 = fs.stat("test1") + stat2 = fs.stat("test2") print(stat1[8] != 0, stat2[8] != 0) - # Check that test1 has mtime which matches time.time() at point of creation. + # Check that test1 has mtime which matches time.time_ns() at point of creation. print(current_time <= stat1[8] <= current_time + 1) # Check that test1 is older than test2. @@ -71,34 +72,34 @@ def test(bdev, vfs_class): time.sleep(1) # Open test1 for reading and ensure mtime did not change. - vfs.open("test1", "rt").close() - print(vfs.stat("test1") == stat1) + fs.open("test1", "rt").close() + print(fs.stat("test1") == stat1) # Open test1 for writing and ensure mtime increased from the previous value. - vfs.open("test1", "wt").close() + fs.open("test1", "wt").close() stat1_old = stat1 - stat1 = vfs.stat("test1") + stat1 = fs.stat("test1") print(stat1_old[8] < stat1[8]) # Unmount. - vfs.umount() + fs.umount() # Check that remounting with mtime=False can read the timestamps. print("mtime=False") - vfs = vfs_class(bdev, mtime=False) - print(vfs.stat("test1") == stat1) - print(vfs.stat("test2") == stat2) - f = vfs.open("test1", "wt") + fs = vfs_class(bdev, mtime=False) + print(fs.stat("test1") == stat1) + print(fs.stat("test2") == stat2) + f = fs.open("test1", "wt") f.close() - print(vfs.stat("test1") == stat1) - vfs.umount() + print(fs.stat("test1") == stat1) + fs.umount() # Check that remounting with mtime=True still has the timestamps. print("mtime=True") - vfs = vfs_class(bdev, mtime=True) - print(vfs.stat("test1") == stat1) - print(vfs.stat("test2") == stat2) - vfs.umount() + fs = vfs_class(bdev, mtime=True) + print(fs.stat("test1") == stat1) + print(fs.stat("test2") == stat2) + fs.umount() try: @@ -107,4 +108,4 @@ def test(bdev, vfs_class): print("SKIP") raise SystemExit -test(bdev, os.VfsLfs2) +test(bdev, vfs.VfsLfs2) diff --git a/tests/extmod/vfs_lfs_superblock.py b/tests/extmod/vfs_lfs_superblock.py index b8a8ec60b967a..74b6004e991c0 100644 --- a/tests/extmod/vfs_lfs_superblock.py +++ b/tests/extmod/vfs_lfs_superblock.py @@ -1,9 +1,9 @@ # Test for VfsLfs using a RAM device, when the first superblock does not exist try: - import os + import os, vfs - os.VfsLfs2 + vfs.VfsLfs2 except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -36,12 +36,12 @@ def ioctl(self, op, arg): bdev = RAMBlockDevice(64, lfs2_data) # Create the VFS explicitly, no auto-detection is needed for this. -vfs = os.VfsLfs2(bdev) -print(list(vfs.ilistdir())) +fs = vfs.VfsLfs2(bdev) +print(list(fs.ilistdir())) # Mount the block device directly; this relies on auto-detection. -os.mount(bdev, "/userfs") +vfs.mount(bdev, "/userfs") print(os.listdir("/userfs")) # Clean up. -os.umount("/userfs") +vfs.umount("/userfs") diff --git a/tests/extmod/vfs_mountinfo.py b/tests/extmod/vfs_mountinfo.py new file mode 100644 index 0000000000000..b31dc60ce76d7 --- /dev/null +++ b/tests/extmod/vfs_mountinfo.py @@ -0,0 +1,65 @@ +# test VFS functionality without any particular filesystem type + +try: + import os, vfs +except ImportError: + print("SKIP") + raise SystemExit + + +class Filesystem: + def __init__(self, id, paths=[]): + self.id = id + self.paths = paths + + def mount(self, readonly, mksfs): + print("mount", self) + + def umount(self): + print("umount", self) + + def stat(self, path): + if path in self.paths: + return (0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + else: + raise OSError + + statvfs = stat + + def open(self, path, mode): + pass + + def __repr__(self): + return "Filesystem(%d)" % self.id + + +# first we umount any existing mount points the target may have +try: + vfs.umount("/") +except OSError: + pass +for path in os.listdir("/"): + vfs.umount("/" + path) + + +print(vfs.mount()) + +vfs.mount(Filesystem(1), "/foo") + +print(vfs.mount()) + +vfs.mount(Filesystem(2), "/bar/baz") + +print(vfs.mount()) + +vfs.mount(Filesystem(3), "/bar") + +print(vfs.mount()) + +vfs.umount("/bar/baz") + +print(vfs.mount()) + +vfs.mount(Filesystem(4), "/") + +print(vfs.mount()) diff --git a/tests/extmod/vfs_mountinfo.py.exp b/tests/extmod/vfs_mountinfo.py.exp new file mode 100644 index 0000000000000..4ddf06c8c976f --- /dev/null +++ b/tests/extmod/vfs_mountinfo.py.exp @@ -0,0 +1,11 @@ +[] +mount Filesystem(1) +[(Filesystem(1), '/foo')] +mount Filesystem(2) +[(Filesystem(1), '/foo'), (Filesystem(2), '/bar/baz')] +mount Filesystem(3) +[(Filesystem(1), '/foo'), (Filesystem(2), '/bar/baz'), (Filesystem(3), '/bar')] +umount Filesystem(2) +[(Filesystem(1), '/foo'), (Filesystem(3), '/bar')] +mount Filesystem(4) +[(Filesystem(1), '/foo'), (Filesystem(3), '/bar'), (Filesystem(4), '/')] diff --git a/tests/extmod/vfs_posix.py b/tests/extmod/vfs_posix.py index bc4c7c2014b6c..b3ca2753ba9cf 100644 --- a/tests/extmod/vfs_posix.py +++ b/tests/extmod/vfs_posix.py @@ -1,10 +1,9 @@ # Test for VfsPosix try: - import gc - import os + import gc, os, vfs - os.VfsPosix + vfs.VfsPosix except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -13,8 +12,6 @@ # Skip the test if it does exist. temp_dir = "micropy_test_dir" try: - import os - os.stat(temp_dir) print("SKIP") raise SystemExit @@ -32,7 +29,21 @@ print(type(os.stat("/"))) # listdir and ilistdir -print(type(os.listdir("/"))) +target = "/" +try: + import platform + + # On Android non-root users are permitted full filesystem access only to + # selected directories. To let this test pass on bionic, the internal + # user-accessible storage area root is enumerated instead of the + # filesystem root. "/storage/emulated/0" should be there on pretty much + # any recent-ish device; querying the proper location requires a JNI + # round-trip, not really worth it. + if platform.platform().startswith("Android-"): + target = "/storage/emulated/0" +except ImportError: + pass +print(type(os.listdir(target))) # mkdir os.mkdir(temp_dir) @@ -87,35 +98,35 @@ def write_files_without_closing(): print(os.listdir(temp_dir)) # construct new VfsPosix with path argument -vfs = os.VfsPosix(temp_dir) -# when VfsPosix is used the intended way via os.mount(), it can only be called +fs = vfs.VfsPosix(temp_dir) +# when VfsPosix is used the intended way via vfs.mount(), it can only be called # with relative paths when the CWD is inside or at its root, so simulate that os.chdir(temp_dir) -print(list(i[0] for i in vfs.ilistdir("."))) +print(list(i[0] for i in fs.ilistdir("."))) # stat, statvfs (statvfs may not exist) -print(type(vfs.stat("."))) -if hasattr(vfs, "statvfs"): - assert type(vfs.statvfs(".")) is tuple +print(type(fs.stat("."))) +if hasattr(fs, "statvfs"): + assert type(fs.statvfs(".")) is tuple # check types of ilistdir with str/bytes arguments -print(type(list(vfs.ilistdir("."))[0][0])) -print(type(list(vfs.ilistdir(b"."))[0][0])) +print(type(list(fs.ilistdir("."))[0][0])) +print(type(list(fs.ilistdir(b"."))[0][0])) # chdir should not affect absolute paths (regression test) -vfs.mkdir("/subdir") -vfs.mkdir("/subdir/micropy_test_dir") -with vfs.open("/subdir/micropy_test_dir/test2", "w") as f: +fs.mkdir("/subdir") +fs.mkdir("/subdir/micropy_test_dir") +with fs.open("/subdir/micropy_test_dir/test2", "w") as f: f.write("wrong") -vfs.chdir("/subdir") -with vfs.open("/test2", "r") as f: +fs.chdir("/subdir") +with fs.open("/test2", "r") as f: print(f.read()) os.chdir(curdir) -vfs.remove("/subdir/micropy_test_dir/test2") -vfs.rmdir("/subdir/micropy_test_dir") -vfs.rmdir("/subdir") +fs.remove("/subdir/micropy_test_dir/test2") +fs.rmdir("/subdir/micropy_test_dir") +fs.rmdir("/subdir") -# done with vfs, restore CWD +# done with fs, restore CWD os.chdir(curdir) # remove diff --git a/tests/extmod/vfs_posix_enoent.py b/tests/extmod/vfs_posix_enoent.py index e6010d79d58f0..7b00388da539a 100644 --- a/tests/extmod/vfs_posix_enoent.py +++ b/tests/extmod/vfs_posix_enoent.py @@ -1,10 +1,9 @@ # Test for VfsPosix error conditions try: - import os - import sys + import os, sys, vfs - os.VfsPosix + vfs.VfsPosix except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -36,7 +35,7 @@ print("getcwd():", repr(e)) try: - print("VfsPosix():", os.VfsPosix("something")) + print("VfsPosix():", vfs.VfsPosix("something")) except OSError as e: # expecting ENOENT = 2 print("VfsPosix():", repr(e)) diff --git a/tests/extmod/vfs_posix_ilistdir_del.py b/tests/extmod/vfs_posix_ilistdir_del.py index 8c8e6978b6540..8b5984cd81c05 100644 --- a/tests/extmod/vfs_posix_ilistdir_del.py +++ b/tests/extmod/vfs_posix_ilistdir_del.py @@ -1,10 +1,9 @@ # Test ilistdir __del__ for VfsPosix. -import gc try: - import os + import gc, os, vfs - os.VfsPosix + vfs.VfsPosix except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -12,34 +11,34 @@ def test(testdir): curdir = os.getcwd() - vfs = os.VfsPosix(testdir) - # When VfsPosix is used the intended way via os.mount(), it can only be called + fs = vfs.VfsPosix(testdir) + # When VfsPosix is used the intended way via vfs.mount(), it can only be called # with relative paths when the CWD is inside or at its root, so simulate that. # (Although perhaps calling with a relative path was an oversight in this case - # and the respective line below was meant to read `vfs.rmdir("/" + dname)`.) + # and the respective line below was meant to read `fs.rmdir("/" + dname)`.) os.chdir(testdir) - vfs.mkdir("/test_d1") - vfs.mkdir("/test_d2") - vfs.mkdir("/test_d3") + fs.mkdir("/test_d1") + fs.mkdir("/test_d2") + fs.mkdir("/test_d3") for i in range(10): print(i) # We want to partially iterate the ilistdir iterator to leave it in an # open state, which will then test the finaliser when it's garbage collected. - idir = vfs.ilistdir("/") + idir = fs.ilistdir("/") print(any(idir)) # Alternate way of partially iterating the ilistdir object, modifying the # filesystem while it's open. - for dname, *_ in vfs.ilistdir("/"): - vfs.rmdir(dname) + for dname, *_ in fs.ilistdir("/"): + fs.rmdir(dname) break - vfs.mkdir(dname) + fs.mkdir(dname) - # Also create a fully drained iterator and ensure trying to re-use it + # Also create a fully drained iterator and ensure trying to reuse it # throws the correct exception. - idir_emptied = vfs.ilistdir("/") + idir_emptied = fs.ilistdir("/") l = list(idir_emptied) print(len(l)) try: @@ -51,10 +50,10 @@ def test(testdir): # Create and delete a file, try to flush out any filesystem # corruption that may be caused over the loops. - vfs.open("/test", "w").close() - vfs.remove("/test") + fs.open("/test", "w").close() + fs.remove("/test") - # Done with vfs, restore CWD. + # Done with fs, restore CWD. os.chdir(curdir) diff --git a/tests/extmod/vfs_posix_ilistdir_filter.py b/tests/extmod/vfs_posix_ilistdir_filter.py index 54012746057a8..6df9542045935 100644 --- a/tests/extmod/vfs_posix_ilistdir_filter.py +++ b/tests/extmod/vfs_posix_ilistdir_filter.py @@ -1,9 +1,9 @@ # Test ilistdir filter of . and .. for VfsPosix. try: - import os + import os, vfs - os.VfsPosix + vfs.VfsPosix except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -11,24 +11,24 @@ def test(testdir): curdir = os.getcwd() - vfs = os.VfsPosix(testdir) - # When VfsPosix is used the intended way via os.mount(), it can only be called + fs = vfs.VfsPosix(testdir) + # When VfsPosix is used the intended way via vfs.mount(), it can only be called # with relative paths when the CWD is inside or at its root, so simulate that. os.chdir(testdir) dirs = [".a", "..a", "...a", "a.b", "a..b"] for dir in dirs: - vfs.mkdir(dir) + fs.mkdir(dir) dirs = [] - for entry in vfs.ilistdir("/"): + for entry in fs.ilistdir("/"): dirs.append(entry[0]) dirs.sort() print(dirs) - # Done with vfs, restore CWD. + # Done with fs, restore CWD. os.chdir(curdir) diff --git a/tests/extmod/vfs_posix_paths.py b/tests/extmod/vfs_posix_paths.py index 5806a34521a23..c06318748a327 100644 --- a/tests/extmod/vfs_posix_paths.py +++ b/tests/extmod/vfs_posix_paths.py @@ -1,9 +1,9 @@ # Test for VfsPosix with relative paths try: - import os + import os, vfs - os.VfsPosix + vfs.VfsPosix except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -12,8 +12,6 @@ # Skip the test if it does exist. temp_dir = "vfs_posix_paths_test_dir" try: - import os - os.stat(temp_dir) print("SKIP") raise SystemExit @@ -25,26 +23,26 @@ # construct new VfsPosix with absolute path argument temp_dir_abs = os.getcwd() + os.sep + temp_dir -vfs = os.VfsPosix(temp_dir_abs) -# when VfsPosix is used the intended way via os.mount(), it can only be called +fs = vfs.VfsPosix(temp_dir_abs) +# when VfsPosix is used the intended way via vfs.mount(), it can only be called # with relative paths when the CWD is inside or at its root, so simulate that os.chdir(temp_dir_abs) -vfs.mkdir("subdir") -vfs.mkdir("subdir/one") -print('listdir("/"):', sorted(i[0] for i in vfs.ilistdir("/"))) -print('listdir("."):', sorted(i[0] for i in vfs.ilistdir("."))) -print('getcwd() in {"", "/"}:', vfs.getcwd() in {"", "/"}) -print('chdir("subdir"):', vfs.chdir("subdir")) -print("getcwd():", vfs.getcwd()) -print('mkdir("two"):', vfs.mkdir("two")) -f = vfs.open("file.py", "w") +fs.mkdir("subdir") +fs.mkdir("subdir/one") +print('listdir("/"):', sorted(i[0] for i in fs.ilistdir("/"))) +print('listdir("."):', sorted(i[0] for i in fs.ilistdir("."))) +print('getcwd() in ("", "/"):', fs.getcwd() in ("", "/")) +print('chdir("subdir"):', fs.chdir("subdir")) +print("getcwd():", fs.getcwd()) +print('mkdir("two"):', fs.mkdir("two")) +f = fs.open("file.py", "w") f.write("print('hello')") f.close() -print('listdir("/"):', sorted(i[0] for i in vfs.ilistdir("/"))) -print('listdir("/subdir"):', sorted(i[0] for i in vfs.ilistdir("/subdir"))) -print('listdir("."):', sorted(i[0] for i in vfs.ilistdir("."))) +print('listdir("/"):', sorted(i[0] for i in fs.ilistdir("/"))) +print('listdir("/subdir"):', sorted(i[0] for i in fs.ilistdir("/subdir"))) +print('listdir("."):', sorted(i[0] for i in fs.ilistdir("."))) try: - f = vfs.open("/subdir/file.py", "r") + f = fs.open("/subdir/file.py", "r") print(f.read()) f.close() except Exception as e: @@ -59,17 +57,17 @@ except Exception as e: print(e) del sys.path[0] -vfs.remove("file.py") -vfs.rmdir("two") -vfs.rmdir("/subdir/one") -vfs.chdir("/") -vfs.rmdir("/subdir") +fs.remove("file.py") +fs.rmdir("two") +fs.rmdir("/subdir/one") +fs.chdir("/") +fs.rmdir("/subdir") -# done with vfs, restore CWD +# done with fs, restore CWD os.chdir(curdir) # some integration tests with a mounted VFS -os.mount(os.VfsPosix(temp_dir_abs), "/mnt") +vfs.mount(vfs.VfsPosix(temp_dir_abs), "/mnt") os.mkdir("/mnt/dir") print('chdir("/mnt/dir"):', os.chdir("/mnt/dir")) print("getcwd():", os.getcwd()) @@ -82,7 +80,7 @@ print('chdir(".."):', os.chdir("..")) print("getcwd():", os.getcwd()) os.rmdir("/mnt/dir") -os.umount("/mnt") +vfs.umount("/mnt") # restore CWD os.chdir(curdir) diff --git a/tests/extmod/vfs_posix_paths.py.exp b/tests/extmod/vfs_posix_paths.py.exp index ecc13222aaaeb..d6a0960efd249 100644 --- a/tests/extmod/vfs_posix_paths.py.exp +++ b/tests/extmod/vfs_posix_paths.py.exp @@ -1,6 +1,6 @@ listdir("/"): ['subdir'] listdir("."): ['subdir'] -getcwd() in {"", "/"}: True +getcwd() in ("", "/"): True chdir("subdir"): None getcwd(): /subdir mkdir("two"): None diff --git a/tests/extmod/vfs_posix_readonly.py b/tests/extmod/vfs_posix_readonly.py new file mode 100644 index 0000000000000..e7821381006fd --- /dev/null +++ b/tests/extmod/vfs_posix_readonly.py @@ -0,0 +1,99 @@ +# Test for VfsPosix + +try: + import gc, os, vfs, errno + + vfs.VfsPosix +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +# We need a directory for testing that doesn't already exist. +# Skip the test if it does exist. +temp_dir = "vfs_posix_readonly_test_dir" +try: + os.stat(temp_dir) + raise SystemExit("Target directory {} exists".format(temp_dir)) +except OSError: + pass + +# mkdir (skip test if whole filesystem is readonly) +try: + os.mkdir(temp_dir) +except OSError as e: + if e.errno == errno.EROFS: + print("SKIP") + raise SystemExit + +fs_factory = lambda: vfs.VfsPosix(temp_dir) + +# mount +fs = fs_factory() +vfs.mount(fs, "/vfs") + +with open("/vfs/file", "w") as f: + f.write("content") + +# test reading works +with open("/vfs/file") as f: + print("file:", f.read()) + +os.mkdir("/vfs/emptydir") + +# umount +vfs.umount("/vfs") + +# mount read-only +fs = fs_factory() +vfs.mount(fs, "/vfs", readonly=True) + +# test reading works +with open("/vfs/file") as f: + print("file 2:", f.read()) + +# test writing fails +try: + with open("/vfs/test_write", "w"): + pass + print("opened") +except OSError as er: + print(repr(er)) + +# test removing fails +try: + os.unlink("/vfs/file") + print("unlinked") +except OSError as er: + print(repr(er)) + +# test renaming fails +try: + os.rename("/vfs/file2", "/vfs/renamed") + print("renamed") +except OSError as er: + print(repr(er)) + +# test removing directory fails +try: + os.rmdir("/vfs/emptydir") + print("rmdir'd") +except OSError as er: + print(repr(er)) + +# test creating directory fails +try: + os.mkdir("/vfs/emptydir2") + print("mkdir'd") +except OSError as er: + print(repr(er)) + +# umount +vfs.umount("/vfs") + +fs = fs_factory() +vfs.mount(fs, "/vfs") + +os.rmdir("/vfs/emptydir") +os.unlink("/vfs/file") + +os.rmdir(temp_dir) diff --git a/tests/extmod/vfs_posix_readonly.py.exp b/tests/extmod/vfs_posix_readonly.py.exp new file mode 100644 index 0000000000000..40e4316775ff3 --- /dev/null +++ b/tests/extmod/vfs_posix_readonly.py.exp @@ -0,0 +1,7 @@ +file: content +file 2: content +OSError(30,) +OSError(30,) +OSError(30,) +OSError(30,) +OSError(30,) diff --git a/tests/extmod/vfs_rom.py b/tests/extmod/vfs_rom.py new file mode 100644 index 0000000000000..18ae1f5cf96c8 --- /dev/null +++ b/tests/extmod/vfs_rom.py @@ -0,0 +1,489 @@ +# Test VfsRom filesystem. + +try: + import errno, sys, struct, os, uctypes, vfs + + vfs.VfsRom +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +try: + import select +except ImportError: + select = None + +import unittest + +IFDIR = 0x4000 +IFREG = 0x8000 + +SEEK_SET = 0 +SEEK_CUR = 1 +SEEK_END = 2 + +# An mpy file with four constant objects: str, bytes, long-int, float. +test_mpy = ( + # header + b"M\x06\x00\x1e" # mpy file header, -msmall-int-bits=30 + b"\x06" # n_qstr + b"\x05" # n_obj + # qstrs + b"\x0etest.py\x00" # qstr0 = "test.py" + b"\x0f" # qstr1 = "" + b"\x0estr_obj\x00" # qstr2 = "str_obj" + b"\x12bytes_obj\x00" # qstr3 = "bytes_obj" + b"\x0eint_obj\x00" # qstr4 = "int_obj" + b"\x12float_obj\x00" # qstr5 = "float_obj" + # objects + b"\x05\x14this is a str object\x00" + b"\x06\x16this is a bytes object\x00" + b"\x07\x0a1234567890" # long-int object + b"\x08\x041.23" # float object + b"\x05\x07str_obj\x00" # str object of existing qstr + # bytecode + b"\x81\x28" # 21 bytes, no children, bytecode + b"\x00\x02" # prelude + b"\x01" # simple name () + b"\x23\x00" # LOAD_CONST_OBJ(0) + b"\x16\x02" # STORE_NAME(str_obj) + b"\x23\x01" # LOAD_CONST_OBJ(1) + b"\x16\x03" # STORE_NAME(bytes_obj) + b"\x23\x02" # LOAD_CONST_OBJ(2) + b"\x16\x04" # STORE_NAME(int_obj) + b"\x23\x03" # LOAD_CONST_OBJ(3) + b"\x16\x05" # STORE_NAME(float_obj) + b"\x51" # LOAD_CONST_NONE + b"\x63" # RETURN_VALUE +) + + +class VfsRomWriter: + ROMFS_HEADER = b"\xd2\xcd\x31" + + ROMFS_RECORD_KIND_UNUSED = 0 + ROMFS_RECORD_KIND_PADDING = 1 + ROMFS_RECORD_KIND_DATA_VERBATIM = 2 + ROMFS_RECORD_KIND_DATA_POINTER = 3 + ROMFS_RECORD_KIND_DIRECTORY = 4 + ROMFS_RECORD_KIND_FILE = 5 + + def __init__(self): + self._dir_stack = [(None, bytearray())] + + def _encode_uint(self, value): + encoded = [value & 0x7F] + value >>= 7 + while value != 0: + encoded.insert(0, 0x80 | (value & 0x7F)) + value >>= 7 + return bytes(encoded) + + def _pack(self, kind, payload): + return self._encode_uint(kind) + self._encode_uint(len(payload)) + payload + + def _extend(self, data): + buf = self._dir_stack[-1][1] + buf.extend(data) + return len(buf) + + def finalise(self): + _, data = self._dir_stack.pop() + encoded_kind = VfsRomWriter.ROMFS_HEADER + encoded_len = self._encode_uint(len(data)) + if (len(encoded_kind) + len(encoded_len) + len(data)) % 2 == 1: + encoded_len = b"\x80" + encoded_len + data = encoded_kind + encoded_len + data + return data + + def opendir(self, dirname): + self._dir_stack.append((dirname, bytearray())) + + def closedir(self): + dirname, dirdata = self._dir_stack.pop() + dirdata = self._encode_uint(len(dirname)) + bytes(dirname, "ascii") + dirdata + self._extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DIRECTORY, dirdata)) + + def mkdata(self, data): + assert len(self._dir_stack) == 1 + return self._extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_VERBATIM, data)) - len( + data + ) + + def mkfile(self, filename, filedata, extra_payload=b""): + filename = bytes(filename, "ascii") + payload = self._encode_uint(len(filename)) + payload += filename + payload += extra_payload + if isinstance(filedata, tuple): + sub_payload = self._encode_uint(filedata[0]) + sub_payload += self._encode_uint(filedata[1]) + payload += self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_POINTER, sub_payload) + else: + payload += self._pack(VfsRomWriter.ROMFS_RECORD_KIND_DATA_VERBATIM, filedata) + self._dir_stack[-1][1].extend(self._pack(VfsRomWriter.ROMFS_RECORD_KIND_FILE, payload)) + + +def _make_romfs(fs, files, data_map): + for filename, contents in files: + if isinstance(contents, tuple): + fs.opendir(filename) + _make_romfs(fs, contents, data_map) + fs.closedir() + elif isinstance(contents, int): + fs.mkfile(filename, data_map[contents]) + else: + fs.mkfile(filename, contents) + + +def make_romfs(files, data=None): + fs = VfsRomWriter() + data_map = {} + if data: + for k, v in data.items(): + data_map[k] = len(v), fs.mkdata(v) + _make_romfs(fs, files, data_map) + return fs.finalise() + + +# A class to test if a value is within a range, needed because MicroPython's range +# doesn't support arbitrary objects. +class Range: + def __init__(self, lower, upper): + self._lower = lower + self._upper = upper + + def __repr__(self): + return "Range({}, {})".format(self._lower, self._upper) + + def __contains__(self, value): + return self._lower <= value < self._upper + + +class TestBase(unittest.TestCase): + @classmethod + def setUpClass(cls): + fs_inner = make_romfs((("test_inner.txt", b"contents_inner"), ("c.py", b""))) + cls.romfs = make_romfs( + ( + ("fs.romfs", 0), + ("test.txt", b"contents"), + ( + "dir", + ( + ("a.py", b"x = 1"), + ("b.py", b"x = 2"), + ("test.mpy", test_mpy), + ), + ), + ), + {0: fs_inner}, + ) + cls.romfs_ilistdir = [ + ("fs.romfs", IFREG, 0, 46), + ("test.txt", IFREG, 0, 8), + ("dir", IFDIR, 0, 198), + ] + cls.romfs_listdir = [x[0] for x in cls.romfs_ilistdir] + cls.romfs_listdir_dir = ["a.py", "b.py", "test.mpy"] + cls.romfs_listdir_bytes = [bytes(x, "ascii") for x in cls.romfs_listdir] + cls.romfs_addr = uctypes.addressof(cls.romfs) + cls.romfs_addr_range = Range(cls.romfs_addr, cls.romfs_addr + len(cls.romfs)) + + +class TestEdgeCases(unittest.TestCase): + def test_empty_romfs(self): + empty_romfs = make_romfs(()) + self.assertEqual(empty_romfs, bytes([0x80 | ord("R"), 0x80 | ord("M"), ord("1"), 0])) + fs = vfs.VfsRom(empty_romfs) + self.assertIsInstance(fs, vfs.VfsRom) + fs.mount(True, False) + self.assertEqual(list(fs.ilistdir("")), []) + self.assertEqual(fs.stat(""), (IFDIR, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + self.assertEqual(fs.statvfs(""), (1, 0, 0, 0, 0, 0, 0, 0, 0, 32767)) + + def test_error(self): + for bad_romfs in (b"", b"xxx", b"not a romfs"): + with self.assertRaises(OSError) as ctx: + vfs.VfsRom(bad_romfs) + self.assertEqual(ctx.exception.errno, errno.ENODEV) + + def test_unknown_record(self): + fs = VfsRomWriter() + fs._extend(fs._pack(VfsRomWriter.ROMFS_RECORD_KIND_PADDING, b"payload")) + fs.mkfile( + "test", + b"contents", + extra_payload=fs._pack(VfsRomWriter.ROMFS_RECORD_KIND_PADDING, b"pad"), + ) + romfs = fs.finalise() + fs = vfs.VfsRom(romfs) + self.assertEqual(list(fs.ilistdir("")), [("test", IFREG, 0, 8)]) + with fs.open("test", "rb") as f: + self.assertEqual(f.read(), b"contents") + + +class TestCorrupt(unittest.TestCase): + def test_corrupt_filesystem(self): + # Make the filesystem length bigger than the buffer. + romfs = bytearray(make_romfs(())) + romfs[3] = 0x01 + with self.assertRaises(OSError): + vfs.VfsRom(romfs) + + # Corrupt the filesystem length. + romfs = bytearray(make_romfs(())) + romfs[3] = 0xFF + with self.assertRaises(OSError): + vfs.VfsRom(romfs) + + # Corrupt the contents of the filesystem. + romfs = bytearray(make_romfs(())) + romfs[3] = 0x01 + romfs.extend(b"\xff\xff") + fs = vfs.VfsRom(romfs) + with self.assertRaises(OSError): + fs.stat("a") + self.assertEqual(list(fs.ilistdir("")), []) + + def test_corrupt_file_entry(self): + romfs = make_romfs((("file", b"data"),)) + + # Corrupt the length of filename. + romfs_corrupt = bytearray(romfs) + romfs_corrupt[7:] = b"\xff" * (len(romfs) - 7) + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + self.assertEqual(list(fs.ilistdir("")), []) + + # Erase the data record (change it to a padding record). + romfs_corrupt = bytearray(romfs) + romfs_corrupt[12] = VfsRomWriter.ROMFS_RECORD_KIND_PADDING + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + self.assertEqual(list(fs.ilistdir("")), []) + + # Corrupt the header of the data record. + romfs_corrupt = bytearray(romfs) + romfs_corrupt[12:] = b"\xff" * (len(romfs) - 12) + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + + # Corrupt the interior of the data record. + romfs_corrupt = bytearray(romfs) + romfs_corrupt[13:] = b"\xff" * (len(romfs) - 13) + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + + # Change the data record to an indirect pointer and corrupt the length. + romfs_corrupt = bytearray(romfs) + romfs_corrupt[12] = VfsRomWriter.ROMFS_RECORD_KIND_DATA_POINTER + romfs_corrupt[14:18] = b"\xff\xff\xff\xff" + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + + # Change the data record to an indirect pointer and corrupt the offset. + romfs_corrupt = bytearray(romfs) + romfs_corrupt[12] = VfsRomWriter.ROMFS_RECORD_KIND_DATA_POINTER + romfs_corrupt[14:18] = b"\x00\xff\xff\xff" + fs = vfs.VfsRom(romfs_corrupt) + with self.assertRaises(OSError): + fs.stat("file") + + +class TestStandalone(TestBase): + def test_constructor(self): + self.assertIsInstance(vfs.VfsRom(self.romfs), vfs.VfsRom) + with self.assertRaises(TypeError): + vfs.VfsRom(self.romfs_addr) + + def test_mount(self): + vfs.VfsRom(self.romfs).mount(True, False) + with self.assertRaises(OSError): + vfs.VfsRom(self.romfs).mount(True, True) + + def test_ilistdir(self): + fs = vfs.VfsRom(self.romfs) + self.assertEqual(list(fs.ilistdir("")), self.romfs_ilistdir) + self.assertEqual(list(fs.ilistdir("/")), self.romfs_ilistdir) + with self.assertRaises(OSError): + fs.ilistdir("does not exist") + + def test_stat(self): + fs = vfs.VfsRom(self.romfs) + self.assertEqual(fs.stat(""), (IFDIR, 0, 0, 0, 0, 0, 289, 0, 0, 0)) + self.assertEqual(fs.stat("/"), (IFDIR, 0, 0, 0, 0, 0, 289, 0, 0, 0)) + self.assertEqual(fs.stat("/test.txt"), (IFREG, 0, 0, 0, 0, 0, 8, 0, 0, 0)) + self.assertEqual(fs.stat("/dir"), (IFDIR, 0, 0, 0, 0, 0, 198, 0, 0, 0)) + with self.assertRaises(OSError): + fs.stat("/does-not-exist") + + def test_statvfs(self): + fs = vfs.VfsRom(self.romfs) + self.assertEqual(fs.statvfs(""), (1, 0, 289, 0, 0, 0, 0, 0, 0, 32767)) + + def test_open(self): + fs = vfs.VfsRom(self.romfs) + + with fs.open("/test.txt", "") as f: + self.assertEqual(f.read(), "contents") + with fs.open("/test.txt", "rt") as f: + self.assertEqual(f.read(), "contents") + with fs.open("/test.txt", "rb") as f: + self.assertEqual(f.read(), b"contents") + + with self.assertRaises(OSError) as ctx: + fs.open("/file-does-not-exist", "") + self.assertEqual(ctx.exception.errno, errno.ENOENT) + + with self.assertRaises(OSError) as ctx: + fs.open("/dir", "rb") + self.assertEqual(ctx.exception.errno, errno.EISDIR) + + with self.assertRaises(OSError): + fs.open("/test.txt", "w") + with self.assertRaises(OSError): + fs.open("/test.txt", "a") + with self.assertRaises(OSError): + fs.open("/test.txt", "+") + + def test_file_seek(self): + fs = vfs.VfsRom(self.romfs) + with fs.open("/test.txt", "") as f: + self.assertEqual(f.seek(0, SEEK_SET), 0) + self.assertEqual(f.seek(3, SEEK_SET), 3) + self.assertEqual(f.read(), "tents") + self.assertEqual(f.seek(0, SEEK_SET), 0) + self.assertEqual(f.seek(100, SEEK_CUR), 8) + self.assertEqual(f.seek(-1, SEEK_END), 7) + self.assertEqual(f.read(), "s") + self.assertEqual(f.seek(1, SEEK_END), 8) + with self.assertRaises(OSError): + f.seek(-1, SEEK_SET) + f.seek(0, SEEK_SET) + with self.assertRaises(OSError): + f.seek(-1, SEEK_CUR) + with self.assertRaises(OSError): + f.seek(-100, SEEK_END) + + @unittest.skipIf(select is None, "no select module") + def test_file_ioctl_invalid(self): + fs = vfs.VfsRom(self.romfs) + with fs.open("/test.txt", "") as f: + p = select.poll() + p.register(f) + with self.assertRaises(OSError): + p.poll(0) + + def test_memory_mapping(self): + fs = vfs.VfsRom(self.romfs) + with fs.open("/test.txt", "rb") as f: + addr = uctypes.addressof(f) + data = memoryview(f) + self.assertIn(addr, self.romfs_addr_range) + self.assertIn(addr + len(data), self.romfs_addr_range) + self.assertEqual(bytes(data), b"contents") + + +class TestMounted(TestBase): + def setUp(self): + self.orig_sys_path = list(sys.path) + self.orig_cwd = os.getcwd() + sys.path = [] + vfs.mount(vfs.VfsRom(self.romfs), "/test_rom") + + def tearDown(self): + vfs.umount("/test_rom") + os.chdir(self.orig_cwd) + sys.path = self.orig_sys_path + + def test_listdir(self): + self.assertEqual(os.listdir("/test_rom"), self.romfs_listdir) + self.assertEqual(os.listdir("/test_rom/dir"), self.romfs_listdir_dir) + self.assertEqual(os.listdir(b"/test_rom"), self.romfs_listdir_bytes) + + def test_chdir(self): + os.chdir("/test_rom") + self.assertEqual(os.getcwd(), "/test_rom") + self.assertEqual(os.listdir(), self.romfs_listdir) + + os.chdir("/test_rom/") + self.assertEqual(os.getcwd(), "/test_rom") + self.assertEqual(os.listdir(), self.romfs_listdir) + + # chdir within the romfs is not implemented. + with self.assertRaises(OSError): + os.chdir("/test_rom/dir") + + def test_stat(self): + self.assertEqual(os.stat("/test_rom"), (IFDIR, 0, 0, 0, 0, 0, 289, 0, 0, 0)) + self.assertEqual(os.stat("/test_rom/"), (IFDIR, 0, 0, 0, 0, 0, 289, 0, 0, 0)) + self.assertEqual(os.stat("/test_rom/test.txt"), (IFREG, 0, 0, 0, 0, 0, 8, 0, 0, 0)) + self.assertEqual(os.stat("/test_rom/dir"), (IFDIR, 0, 0, 0, 0, 0, 198, 0, 0, 0)) + with self.assertRaises(OSError): + os.stat("/test_rom/does-not-exist") + + def test_open(self): + with open("/test_rom/test.txt") as f: + self.assertEqual(f.read(), "contents") + with open("/test_rom/test.txt", "b") as f: + self.assertEqual(f.read(), b"contents") + + with self.assertRaises(OSError) as ctx: + open("/test_rom/file-does-not-exist") + self.assertEqual(ctx.exception.errno, errno.ENOENT) + + with self.assertRaises(OSError) as ctx: + open("/test_rom/dir") + self.assertEqual(ctx.exception.errno, errno.EISDIR) + + def test_import_py(self): + sys.path.append("/test_rom/dir") + a = __import__("a") + b = __import__("b") + self.assertEqual(a.__file__, "/test_rom/dir/a.py") + self.assertEqual(a.x, 1) + self.assertEqual(b.__file__, "/test_rom/dir/b.py") + self.assertEqual(b.x, 2) + + def test_import_mpy(self): + sys.path.append("/test_rom/dir") + test = __import__("test") + self.assertEqual(test.__file__, "/test_rom/dir/test.mpy") + self.assertEqual(test.str_obj, "this is a str object") + self.assertEqual(test.bytes_obj, b"this is a bytes object") + self.assertEqual(test.int_obj, 1234567890) + self.assertEqual(test.float_obj, 1.23) + self.assertIn(uctypes.addressof(test.str_obj), self.romfs_addr_range) + self.assertIn(uctypes.addressof(test.bytes_obj), self.romfs_addr_range) + + def test_romfs_inner(self): + with open("/test_rom/fs.romfs", "rb") as f: + romfs_inner = vfs.VfsRom(memoryview(f)) + + vfs.mount(romfs_inner, "/test_rom2") + + self.assertEqual(os.listdir("/test_rom2"), ["test_inner.txt", "c.py"]) + + sys.path.append("/test_rom2") + self.assertEqual(__import__("c").__file__, "/test_rom2/c.py") + + with open("/test_rom2/test_inner.txt") as f: + self.assertEqual(f.read(), "contents_inner") + + with open("/test_rom2/test_inner.txt", "rb") as f: + addr = uctypes.addressof(f) + data = memoryview(f) + self.assertIn(addr, self.romfs_addr_range) + self.assertIn(addr + len(data), self.romfs_addr_range) + + vfs.umount("/test_rom2") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod/vfs_userfs.py b/tests/extmod/vfs_userfs.py index 5c487315eb5eb..a7b87ec0b0d0c 100644 --- a/tests/extmod/vfs_userfs.py +++ b/tests/extmod/vfs_userfs.py @@ -4,12 +4,9 @@ import sys try: - import io + import io, vfs io.IOBase - import os - - os.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -79,7 +76,7 @@ def open(self, path, mode): "/usermod5.py": b"print('in usermod5')", "/usermod6.py": b"print('in usermod6')", } -os.mount(UserFS(user_files), "/userfs") +vfs.mount(UserFS(user_files), "/userfs") # open and read a file f = open("/userfs/data.txt") @@ -110,5 +107,5 @@ def open(self, path, mode): import usermod6 # unmount and undo path addition -os.umount("/userfs") +vfs.umount("/userfs") sys.path.pop() diff --git a/tests/extmod/websocket_toobig.py b/tests/extmod/websocket_toobig.py new file mode 100644 index 0000000000000..f4c5a74bbceac --- /dev/null +++ b/tests/extmod/websocket_toobig.py @@ -0,0 +1,28 @@ +try: + import io + import errno + import websocket +except ImportError: + print("SKIP") + raise SystemExit + +try: + buf = "x" * 65536 +except MemoryError: + print("SKIP") + raise SystemExit + + +# do a websocket write and then return the raw data from the stream +def ws_write(msg, sz): + s = io.BytesIO() + ws = websocket.websocket(s) + ws.write(msg) + s.seek(0) + return s.read(sz) + + +try: + print(ws_write(buf, 1)) +except OSError as e: + print("ioctl: ENOBUFS:", e.errno == errno.ENOBUFS) diff --git a/tests/extmod/websocket_toobig.py.exp b/tests/extmod/websocket_toobig.py.exp new file mode 100644 index 0000000000000..3bbd95282fdfe --- /dev/null +++ b/tests/extmod/websocket_toobig.py.exp @@ -0,0 +1 @@ +ioctl: ENOBUFS: True diff --git a/tests/extmod_hardware/machine_counter.py b/tests/extmod_hardware/machine_counter.py new file mode 100644 index 0000000000000..62ac1fed47ce7 --- /dev/null +++ b/tests/extmod_hardware/machine_counter.py @@ -0,0 +1,90 @@ +# Test machine.Counter implementation +# +# IMPORTANT: This test requires hardware connections: the out_pin and in_pin +# must be wired together. + +try: + from machine import Counter +except ImportError: + print("SKIP") + raise SystemExit + +import sys +from machine import Pin + +if "esp32" in sys.platform: + id = 0 + out_pin = 4 + in_pin = 5 +else: + print("Please add support for this test on this platform.") + raise SystemExit + +import unittest + +out_pin = Pin(out_pin, mode=Pin.OUT) +in_pin = Pin(in_pin, mode=Pin.IN) + + +def toggle(times): + for _ in range(times): + out_pin(1) + out_pin(0) + + +class TestCounter(unittest.TestCase): + def setUp(self): + out_pin(0) + self.counter = Counter(id, in_pin) + + def tearDown(self): + self.counter.deinit() + + def assertCounter(self, value): + self.assertEqual(self.counter.value(), value) + + def test_connections(self): + # Test the hardware connections are correct. If this test fails, all tests will fail. + out_pin(1) + self.assertEqual(1, in_pin()) + out_pin(0) + self.assertEqual(0, in_pin()) + + def test_count_rising(self): + self.assertCounter(0) + toggle(100) + self.assertCounter(100) + out_pin(1) + self.assertEqual(self.counter.value(0), 101) + self.assertCounter(0) # calling value(0) resets + out_pin(0) + self.assertCounter(0) # no rising edge + out_pin(1) + self.assertCounter(1) + + def test_change_directions(self): + self.assertCounter(0) + toggle(100) + self.assertCounter(100) + self.counter.init(in_pin, direction=Counter.DOWN) + self.assertCounter(0) # calling init() zeroes the counter + self.counter.value(100) # need to manually reset the value + self.assertCounter(100) + toggle(25) + self.assertCounter(75) + + def test_count_falling(self): + self.counter.init(in_pin, direction=Counter.UP, edge=Counter.FALLING) + toggle(20) + self.assertCounter(20) + out_pin(1) + self.assertCounter(20) # no falling edge + out_pin(0) + self.assertCounter(21) + self.counter.value(-(2**24)) + toggle(20) + self.assertCounter(-(2**24 - 20)) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod_hardware/machine_encoder.py b/tests/extmod_hardware/machine_encoder.py new file mode 100644 index 0000000000000..c218c8bfb646a --- /dev/null +++ b/tests/extmod_hardware/machine_encoder.py @@ -0,0 +1,153 @@ +# Test machine.Encoder implementation +# +# IMPORTANT: This test requires hardware connections: +# - out0_pin and in0_pin must be wired together. +# - out1_pin and in1_pin must be wired together. + +try: + from machine import Encoder +except ImportError: + print("SKIP") + raise SystemExit + +import sys +import unittest +from machine import Pin +from target_wiring import encoder_loopback_id, encoder_loopback_out_pins, encoder_loopback_in_pins + +PRINT = False +PIN_INIT_VALUE = 1 + +id = encoder_loopback_id +out0_pin, out1_pin = encoder_loopback_out_pins +in0_pin, in1_pin = encoder_loopback_in_pins + +out0_pin = Pin(out0_pin, mode=Pin.OUT) +in0_pin = Pin(in0_pin, mode=Pin.IN) +out1_pin = Pin(out1_pin, mode=Pin.OUT) +in1_pin = Pin(in1_pin, mode=Pin.IN) + + +class TestEncoder(unittest.TestCase): + def setUp(self): + out0_pin(PIN_INIT_VALUE) + out1_pin(PIN_INIT_VALUE) + self.enc = Encoder(id, in0_pin, in1_pin, phases=1) + self.enc2 = Encoder(id + 1, in0_pin, in1_pin, phases=2) + self.enc4 = Encoder(id + 2, in0_pin, in1_pin, phases=4) + self.pulses = 0 # track the expected encoder position in software + if PRINT: + print( + "\nout0_pin() out1_pin() enc.value() enc2.value() enc4.value() |", + out0_pin(), + out1_pin(), + "|", + self.enc.value(), + self.enc2.value(), + self.enc4.value(), + ) + + def tearDown(self): + self.enc.deinit() + try: + self.enc2.deinit() + except: + pass + try: + self.enc4.deinit() + except: + pass + + def rotate(self, pulses): + for _ in range(abs(pulses)): + self.pulses += 1 if (pulses > 0) else -1 + if pulses > 0: + if self.pulses % 2: + out0_pin(not out0_pin()) + else: + out1_pin(not out1_pin()) + else: + if self.pulses % 2: + out1_pin(not out1_pin()) + else: + out0_pin(not out0_pin()) + if PRINT: + print( + "out0_pin() out1_pin() enc.value() enc2.value() enc4.value() pulses self.pulses |", + out0_pin(), + out1_pin(), + "|", + self.enc.value(), + self.enc2.value(), + self.enc4.value(), + "|", + pulses, + self.pulses, + ) + + def assertPosition(self, value, value2=None, value4=None): + self.assertEqual(self.enc.value(), value) + if not value2 is None: + self.assertEqual(self.enc2.value(), value2) + if not value4 is None: + self.assertEqual(self.enc4.value(), value4) + pass + + @unittest.skipIf(sys.platform == "mimxrt", "cannot read back the pin") + def test_connections(self): + # Test the hardware connections are correct. If this test fails, all tests will fail. + for ch, outp, inp in ((0, out0_pin, in0_pin), (1, out1_pin, in1_pin)): + print("Testing channel ", ch) + outp(1) + self.assertEqual(1, inp()) + outp(0) + self.assertEqual(0, inp()) + + def test_basics(self): + self.assertPosition(0) + self.rotate(100) + self.assertPosition(100 // 4, 100 // 2, 100) + self.rotate(-100) + self.assertPosition(0) + + def test_partial(self): + # With phase=1 (default), need 4x pulses to count a rotation + self.assertPosition(0) + self.rotate(1) + self.assertPosition(1, 1, 1) + self.rotate(1) + self.assertPosition(1, 1, 2) + self.rotate(1) + self.assertPosition(1, 2, 3) + self.rotate(1) + self.assertPosition(1, 2, 4) # +4 + self.rotate(1) + self.assertPosition(2, 3, 5) + self.rotate(1) + self.assertPosition(2, 3, 6) + self.rotate(1) + self.assertPosition(2, 4, 7) + self.rotate(1) + self.assertPosition(2, 4, 8) # +4 + self.rotate(-1) + self.assertPosition(2, 4, 7) + self.rotate(-3) + self.assertPosition(1, 2, 4) # -4 + self.rotate(-4) + self.assertPosition(0, 0, 0) # -4 + self.rotate(-1) + self.assertPosition(0, 0, -1) + self.rotate(-1) + self.assertPosition(0, -1, -2) + self.rotate(-1) + self.assertPosition(0, -1, -3) + self.rotate(-1) + self.assertPosition(-1, -2, -4) # -4 + self.rotate(-1) + self.assertPosition(-1, -2, -5) + self.rotate(-3) + self.assertPosition(-2, -4, -8) # -4 + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod_hardware/machine_i2c_target.py b/tests/extmod_hardware/machine_i2c_target.py new file mode 100644 index 0000000000000..763e6f4771e0f --- /dev/null +++ b/tests/extmod_hardware/machine_i2c_target.py @@ -0,0 +1,307 @@ +# Test machine.I2CTarget. +# +# IMPORTANT: This test requires hardware connections: a SoftI2C instance must be +# wired to a hardware I2C target. See pin definitions below. + +import sys + +try: + from machine import Pin, SoftI2C, I2CTarget +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + +ADDR = 67 + +kwargs_target = {} + +# Configure pins based on the target. +if sys.platform == "alif" and sys.implementation._build == "ALIF_ENSEMBLE": + args_controller = {"scl": "P1_1", "sda": "P1_0"} + args_target = (0,) # on pins P0_3/P0_2 +elif sys.platform == "esp32": + args_controller = {"scl": 5, "sda": 6} + args_target = (0,) # on pins 9/8 for C3 and S3, 18/19 for others + kwargs_target = {"scl": 9, "sda": 8} +elif sys.platform == "rp2": + args_controller = {"scl": 5, "sda": 4} + args_target = (1,) +elif sys.platform == "pyboard": + if sys.implementation._build == "NUCLEO_WB55": + args_controller = {"scl": "B8", "sda": "B9"} + args_target = (3,) + else: + args_controller = {"scl": "X1", "sda": "X2"} + args_target = ("X",) +elif "zephyr-nucleo_wb55rg" in sys.implementation._machine: + # PB8=I2C1_SCL, PB9=I2C1_SDA (on Arduino header D15/D14) + # PC0=I2C3_SCL, PC1=I2C3_SDA (on Arduino header A0/A1) + args_controller = {"scl": Pin(("gpiob", 8)), "sda": Pin(("gpiob", 9))} + args_target = ("i2c3",) +elif "zephyr-rpi_pico" in sys.implementation._machine: + args_controller = {"scl": Pin(("gpio0", 5)), "sda": Pin(("gpio0", 4))} + args_target = ("i2c1",) # on gpio7/gpio6 +elif sys.platform == "mimxrt": + if "Teensy" in sys.implementation._machine: + args_controller = {"scl": "A6", "sda": "A3"} # D20/D17 + else: + args_controller = {"scl": "D0", "sda": "D1"} + args_target = (0,) # pins 19/18 On Teensy 4.x +elif sys.platform == "samd": + args_controller = {"scl": "D5", "sda": "D1"} + args_target = () +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def config_pull_up(): + Pin(args_controller["scl"], Pin.OPEN_DRAIN, Pin.PULL_UP) + Pin(args_controller["sda"], Pin.OPEN_DRAIN, Pin.PULL_UP) + + +class TestMemory(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.mem = bytearray(8) + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, **kwargs_target, addr=ADDR, mem=cls.mem) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_scan(self): + self.assertIn(ADDR, self.i2c.scan()) + + def test_write(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 0, b"test") + self.assertEqual(self.mem, bytearray(b"test4567")) + self.i2c.writeto_mem(ADDR, 4, b"TEST") + self.assertEqual(self.mem, bytearray(b"testTEST")) + + def test_write_wrap(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 6, b"test") + self.assertEqual(self.mem, bytearray(b"st2345te")) + + @unittest.skipIf(sys.platform == "esp32", "write lengths larger than buffer unsupported") + def test_write_wrap_large(self): + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 0, b"testTESTmore") + self.assertEqual(self.mem, bytearray(b"moreTEST")) + + def test_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 4), b"0123") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 4, 4), b"4567") + + def test_read_wrap(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 4), b"0123") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 2, 4), b"2345") + self.assertEqual(self.i2c.readfrom_mem(ADDR, 6, 4), b"6701") + + @unittest.skipIf(sys.platform == "esp32", "read lengths larger than buffer unsupported") + def test_read_wrap_large(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 0, 12), b"012345670123") + + def test_write_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.writeto(ADDR, b"\x02"), 1) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"2345") + + @unittest.skipIf(sys.platform == "esp32", "read after read unsupported") + def test_write_read_read(self): + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.writeto(ADDR, b"\x02"), 1) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"2345") + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"7012") + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_END_READ"), "IRQ unsupported") +class TestMemoryIRQ(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target): + flags = i2c_target.irq().flags() + TestMemoryIRQ.events[TestMemoryIRQ.num_events] = flags + TestMemoryIRQ.events[TestMemoryIRQ.num_events + 1] = i2c_target.memaddr + TestMemoryIRQ.num_events += 2 + + @classmethod + def setUpClass(cls): + cls.mem = bytearray(8) + cls.events = [0] * 8 + cls.num_events = 0 + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, **kwargs_target, addr=ADDR, mem=cls.mem) + cls.i2c_target.irq(TestMemoryIRQ.irq_handler) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + @unittest.skipIf(sys.platform == "esp32", "scan doesn't trigger IRQ_END_WRITE") + def test_scan(self): + TestMemoryIRQ.num_events = 0 + self.i2c.scan() + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_WRITE, 0]) + + def test_write(self): + TestMemoryIRQ.num_events = 0 + self.mem[:] = b"01234567" + self.i2c.writeto_mem(ADDR, 2, b"test") + self.assertEqual(self.mem, bytearray(b"01test67")) + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_WRITE, 2]) + + def test_read(self): + TestMemoryIRQ.num_events = 0 + self.mem[:] = b"01234567" + self.assertEqual(self.i2c.readfrom_mem(ADDR, 2, 4), b"2345") + self.assertEqual(self.events[: self.num_events], [I2CTarget.IRQ_END_READ, 2]) + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_WRITE_REQ"), "IRQ unsupported") +@unittest.skipIf(sys.platform == "mimxrt", "not working") +@unittest.skipIf(sys.platform == "pyboard", "can't queue more than one byte") +@unittest.skipIf(sys.platform == "samd", "not working") +@unittest.skipIf(sys.platform == "zephyr", "must call readinto/write in IRQ handler") +class TestPolling(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target, buf=bytearray(1)): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_READ_REQ: + i2c_target.write(b"0123") + + @classmethod + def setUpClass(cls): + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, addr=ADDR) + cls.i2c_target.irq( + TestPolling.irq_handler, + I2CTarget.IRQ_WRITE_REQ | I2CTarget.IRQ_READ_REQ, + hard=True, + ) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_read(self): + # Can't write data up front, must wait until IRQ_READ_REQ. + # self.assertEqual(self.i2c_target.write(b"abcd"), 4) + self.assertEqual(self.i2c.readfrom(ADDR, 4), b"0123") + + def test_write(self): + # Can do the read outside the IRQ, but requires IRQ_WRITE_REQ trigger to be set. + self.assertEqual(self.i2c.writeto(ADDR, b"0123"), 4) + buf = bytearray(8) + self.assertEqual(self.i2c_target.readinto(buf), 4) + self.assertEqual(buf, b"0123\x00\x00\x00\x00") + + +@unittest.skipUnless(hasattr(I2CTarget, "IRQ_ADDR_MATCH_READ"), "IRQ unsupported") +class TestIRQ(unittest.TestCase): + @staticmethod + def irq_handler(i2c_target, buf=bytearray(1)): + flags = i2c_target.irq().flags() + TestIRQ.events[TestIRQ.num_events] = flags + TestIRQ.num_events += 1 + if flags & I2CTarget.IRQ_READ_REQ: + i2c_target.write(b"Y") + if flags & I2CTarget.IRQ_WRITE_REQ: + i2c_target.readinto(buf) + TestIRQ.events[TestIRQ.num_events] = buf[0] + TestIRQ.num_events += 1 + + @classmethod + def setUpClass(cls): + cls.events = [0] * 8 + cls.num_events = 0 + cls.i2c = SoftI2C(**args_controller) + cls.i2c_target = I2CTarget(*args_target, addr=ADDR) + cls.i2c_target.irq( + TestIRQ.irq_handler, + I2CTarget.IRQ_ADDR_MATCH_READ + | I2CTarget.IRQ_ADDR_MATCH_WRITE + | I2CTarget.IRQ_WRITE_REQ + | I2CTarget.IRQ_READ_REQ + | I2CTarget.IRQ_END_READ + | I2CTarget.IRQ_END_WRITE, + hard=True, + ) + config_pull_up() + + @classmethod + def tearDownClass(cls): + cls.i2c_target.deinit() + + def test_scan(self): + TestIRQ.num_events = 0 + self.i2c.scan() + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_END_WRITE, + ], + ) + + def test_write(self): + TestIRQ.num_events = 0 + self.i2c.writeto(ADDR, b"XYZ") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_WRITE_REQ, + ord(b"X"), + I2CTarget.IRQ_WRITE_REQ, + ord(b"Y"), + I2CTarget.IRQ_WRITE_REQ, + ord(b"Z"), + I2CTarget.IRQ_END_WRITE, + ], + ) + + def test_read(self): + TestIRQ.num_events = 0 + self.assertEqual(self.i2c.readfrom(ADDR, 1), b"Y") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_READ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_END_READ, + ], + ) + + def test_write_read(self): + TestIRQ.num_events = 0 + self.i2c.writeto(ADDR, b"X", False) + self.assertEqual(self.i2c.readfrom(ADDR, 1), b"Y") + self.assertEqual( + self.events[: self.num_events], + [ + I2CTarget.IRQ_ADDR_MATCH_WRITE, + I2CTarget.IRQ_WRITE_REQ, + ord(b"X"), + I2CTarget.IRQ_END_WRITE, + I2CTarget.IRQ_ADDR_MATCH_READ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_READ_REQ, + I2CTarget.IRQ_END_READ, + ], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/extmod_hardware/machine_pwm.py b/tests/extmod_hardware/machine_pwm.py new file mode 100644 index 0000000000000..e27da32548659 --- /dev/null +++ b/tests/extmod_hardware/machine_pwm.py @@ -0,0 +1,166 @@ +# Test machine.PWM, frequency and duty cycle (using machine.time_pulse_us). +# +# IMPORTANT: This test requires hardware connections: the PWM-output and pulse-input +# pins must be wired together (see the variable `pwm_pulse_pins`). + +import sys +import time + +try: + from machine import time_pulse_us, Pin, PWM +except ImportError: + print("SKIP") + raise SystemExit + +import unittest + +pwm_freq_limit = 1000000 +freq_margin_per_thousand = 0 +duty_margin_per_thousand = 0 +timing_margin_us = 5 + +# Configure pins based on the target. +if "esp32" in sys.platform: + pwm_pulse_pins = ((4, 5),) + freq_margin_per_thousand = 2 + duty_margin_per_thousand = 1 + timing_margin_us = 20 +elif "esp8266" in sys.platform: + pwm_pulse_pins = ((4, 5),) + pwm_freq_limit = 1_000 + duty_margin_per_thousand = 3 + timing_margin_us = 50 +elif "mimxrt" in sys.platform: + if "Teensy" in sys.implementation._machine: + # Teensy 4.x + pwm_pulse_pins = ( + ("D0", "D1"), # FLEXPWM X and UART 1 + ("D2", "D3"), # FLEXPWM A/B + ("D11", "D12"), # QTMR and MOSI/MISO of SPI 0 + ) + else: + pwm_pulse_pins = (("D0", "D1"),) +elif "rp2" in sys.platform: + pwm_pulse_pins = (("GPIO0", "GPIO1"),) +elif "samd" in sys.platform: + pwm_pulse_pins = (("D0", "D1"),) + if "SAMD21" in sys.implementation._machine: + # MCU is too slow to capture short pulses. + pwm_freq_limit = 2_000 +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +# Test a specific frequency and duty cycle. +def _test_freq_duty(self, pulse_in, pwm, freq, duty_u16): + print("freq={:<5} duty_u16={:<5} :".format(freq, duty_u16), end="") + + # Check configured freq/duty_u16 is within error bound. + freq_error = abs(pwm.freq() - freq) * 1000 // freq + duty_error = abs(pwm.duty_u16() - duty_u16) * 1000 // (duty_u16 or 1) + print(" freq={} freq_er={}".format(pwm.freq(), freq_error), end="") + print(" duty={} duty_er={}".format(pwm.duty_u16(), duty_error), end="") + print(" :", end="") + self.assertLessEqual(freq_error, freq_margin_per_thousand) + self.assertLessEqual(duty_error, duty_margin_per_thousand) + + # Calculate expected timing. + expected_total_us = 1_000_000 // freq + expected_high_us = expected_total_us * duty_u16 // 65535 + expected_low_us = expected_total_us - expected_high_us + expected_us = (expected_low_us, expected_high_us) + timeout = 2 * expected_total_us + + # Wait for output to settle. + time_pulse_us(pulse_in, 0, timeout) + time_pulse_us(pulse_in, 1, timeout) + + if duty_u16 == 0 or duty_u16 == 65535: + # Expect a constant output level. + no_pulse = ( + time_pulse_us(pulse_in, 0, timeout) < 0 and time_pulse_us(pulse_in, 1, timeout) < 0 + ) + self.assertTrue(no_pulse) + if expected_high_us == 0: + # Expect a constant low level. + self.assertEqual(pulse_in(), 0) + else: + # Expect a constant high level. + self.assertEqual(pulse_in(), 1) + else: + # Test timing of low and high pulse. + n_averaging = 10 + for level in (0, 1): + t = 0 + time_pulse_us(pulse_in, level, timeout) + for _ in range(n_averaging): + t += time_pulse_us(pulse_in, level, timeout) + t //= n_averaging + expected = expected_us[level] + print(" level={} timing_er={}".format(level, abs(t - expected)), end="") + self.assertLessEqual(abs(t - expected), timing_margin_us) + + print() + + +# Test a specific frequency with multiple duty cycles. +def _test_freq(self, freq): + print() + self.pwm.freq(freq) + for duty in (0, 10, 25, 50, 75, 90, 100): + duty_u16 = duty * 65535 // 100 + if sys.platform == "esp32": + # TODO why is this bit needed to get it working on esp32? + self.pwm.init(freq=freq, duty_u16=duty_u16) + time.sleep(0.1) + self.pwm.duty_u16(duty_u16) + _test_freq_duty(self, self.pulse_in, self.pwm, freq, duty_u16) + + +# Given a set of pins, this test class will test multiple frequencies and duty cycles. +class TestBase: + @classmethod + def setUpClass(cls): + print("set up pins:", cls.pwm_pin, cls.pulse_pin) + cls.pwm = PWM(cls.pwm_pin) + cls.pulse_in = Pin(cls.pulse_pin, Pin.IN) + + @classmethod + def tearDownClass(cls): + cls.pwm.deinit() + + def test_freq_50(self): + _test_freq(self, 50) + + def test_freq_100(self): + _test_freq(self, 100) + + def test_freq_500(self): + _test_freq(self, 500) + + def test_freq_1000(self): + _test_freq(self, 1000) + + @unittest.skipIf(pwm_freq_limit < 2000, "frequency too high") + def test_freq_2000(self): + _test_freq(self, 2000) + + @unittest.skipIf(pwm_freq_limit < 5000, "frequency too high") + def test_freq_5000(self): + _test_freq(self, 5000) + + @unittest.skipIf(pwm_freq_limit < 10000, "frequency too high") + def test_freq_10000(self): + _test_freq(self, 10000) + + +# Generate test classes, one for each set of pins to test. +for pwm, pulse in pwm_pulse_pins: + cls_name = "Test_{}_{}".format(pwm, pulse) + globals()[cls_name] = type( + cls_name, (TestBase, unittest.TestCase), {"pwm_pin": pwm, "pulse_pin": pulse} + ) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/feature_check/float.py b/tests/feature_check/float.py deleted file mode 100644 index d6d2a99d2429d..0000000000000 --- a/tests/feature_check/float.py +++ /dev/null @@ -1,13 +0,0 @@ -# detect how many bits of precision the floating point implementation has - -try: - float -except NameError: - print(0) -else: - if float("1.0000001") == float("1.0"): - print(30) - elif float("1e300") == float("inf"): - print(32) - else: - print(64) diff --git a/tests/feature_check/float.py.exp b/tests/feature_check/float.py.exp deleted file mode 100644 index 900731ffd51ff..0000000000000 --- a/tests/feature_check/float.py.exp +++ /dev/null @@ -1 +0,0 @@ -64 diff --git a/tests/feature_check/inlineasm_rv32.py b/tests/feature_check/inlineasm_rv32.py new file mode 100644 index 0000000000000..21dd103b6c3fe --- /dev/null +++ b/tests/feature_check/inlineasm_rv32.py @@ -0,0 +1,9 @@ +# check if RISC-V 32 inline asm is supported + + +@micropython.asm_rv32 +def f(): + add(a0, a0, a0) + + +print("rv32") diff --git a/tests/feature_check/inlineasm_rv32.py.exp b/tests/feature_check/inlineasm_rv32.py.exp new file mode 100644 index 0000000000000..5eecf09c22403 --- /dev/null +++ b/tests/feature_check/inlineasm_rv32.py.exp @@ -0,0 +1 @@ +rv32 diff --git a/tests/feature_check/inlineasm_rv32_zba.py b/tests/feature_check/inlineasm_rv32_zba.py new file mode 100644 index 0000000000000..81228819042ee --- /dev/null +++ b/tests/feature_check/inlineasm_rv32_zba.py @@ -0,0 +1,10 @@ +# check if RISC-V 32 inline asm supported Zba opcodes + + +@micropython.asm_rv32 +def f(): + sh1add(a0, a0, a0) + + +f() +print("rv32_zba") diff --git a/tests/feature_check/inlineasm_rv32_zba.py.exp b/tests/feature_check/inlineasm_rv32_zba.py.exp new file mode 100644 index 0000000000000..fde22f5f40090 --- /dev/null +++ b/tests/feature_check/inlineasm_rv32_zba.py.exp @@ -0,0 +1 @@ +rv32_zba diff --git a/tests/feature_check/inlineasm_thumb.py b/tests/feature_check/inlineasm_thumb.py new file mode 100644 index 0000000000000..321eab0e2f87a --- /dev/null +++ b/tests/feature_check/inlineasm_thumb.py @@ -0,0 +1,9 @@ +# check if Thumb inline asm is supported + + +@micropython.asm_thumb +def f(): + nop() + + +print("thumb") diff --git a/tests/feature_check/inlineasm_thumb.py.exp b/tests/feature_check/inlineasm_thumb.py.exp new file mode 100644 index 0000000000000..bb48e1a2f03c2 --- /dev/null +++ b/tests/feature_check/inlineasm_thumb.py.exp @@ -0,0 +1 @@ +thumb diff --git a/tests/feature_check/inlineasm_xtensa.py b/tests/feature_check/inlineasm_xtensa.py new file mode 100644 index 0000000000000..2a24d39973c8c --- /dev/null +++ b/tests/feature_check/inlineasm_xtensa.py @@ -0,0 +1,9 @@ +# check if Xtensa inline asm is supported + + +@micropython.asm_xtensa +def f(): + ret_n() + + +print("xtensa") diff --git a/tests/feature_check/inlineasm_xtensa.py.exp b/tests/feature_check/inlineasm_xtensa.py.exp new file mode 100644 index 0000000000000..036142c5097b5 --- /dev/null +++ b/tests/feature_check/inlineasm_xtensa.py.exp @@ -0,0 +1 @@ +xtensa diff --git a/tests/feature_check/int_64.py b/tests/feature_check/int_64.py new file mode 100644 index 0000000000000..4d053782ca82b --- /dev/null +++ b/tests/feature_check/int_64.py @@ -0,0 +1,2 @@ +# Check whether 64-bit long integers are supported +print(1 << 62) diff --git a/tests/feature_check/int_64.py.exp b/tests/feature_check/int_64.py.exp new file mode 100644 index 0000000000000..aef5454e66263 --- /dev/null +++ b/tests/feature_check/int_64.py.exp @@ -0,0 +1 @@ +4611686018427387904 diff --git a/tests/feature_check/io_module.py b/tests/feature_check/io_module.py deleted file mode 100644 index 9094e605316ba..0000000000000 --- a/tests/feature_check/io_module.py +++ /dev/null @@ -1,6 +0,0 @@ -try: - import io - - print("io") -except ImportError: - print("no") diff --git a/tests/feature_check/repl_emacs_check.py.exp b/tests/feature_check/repl_emacs_check.py.exp index 82a4e28ee4f84..5fe8ba1cd2df8 100644 --- a/tests/feature_check/repl_emacs_check.py.exp +++ b/tests/feature_check/repl_emacs_check.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # Check for emacs keys in REPL >>> t = \.\+ >>> t == 2 diff --git a/tests/feature_check/repl_words_move_check.py.exp b/tests/feature_check/repl_words_move_check.py.exp index 82a4e28ee4f84..5fe8ba1cd2df8 100644 --- a/tests/feature_check/repl_words_move_check.py.exp +++ b/tests/feature_check/repl_words_move_check.py.exp @@ -1,5 +1,5 @@ MicroPython \.\+ version -Use \.\+ +Type "help()" for more information. >>> # Check for emacs keys in REPL >>> t = \.\+ >>> t == 2 diff --git a/tests/feature_check/target_info.py b/tests/feature_check/target_info.py new file mode 100644 index 0000000000000..e95530023d7cb --- /dev/null +++ b/tests/feature_check/target_info.py @@ -0,0 +1,39 @@ +# Retrieve the native architecture of the target. +# See https://docs.micropython.org/en/latest/reference/mpyfiles.html#versioning-and-compatibility-of-mpy-files +# for more details. + +import sys + +platform = getattr(sys, "platform", "minimal") +sys_mpy = getattr(sys.implementation, "_mpy", 0) +arch = [ + None, + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + "rv32imc", + "rv64imc", +][(sys_mpy >> 10) & 0x0F] +arch_flags = sys_mpy >> 16 +build = getattr(sys.implementation, "_build", "unknown") +thread = getattr(sys.implementation, "_thread", None) + +# Detect how many bits of precision the floating point implementation has. +try: + if float("1.0000001") == float("1.0"): + float_prec = 30 + elif float("1e300") == float("inf"): + float_prec = 32 + else: + float_prec = 64 +except NameError: + float_prec = 0 + +print(platform, arch, arch_flags, build, thread, float_prec, len("α") == 1) diff --git a/tests/feature_check/target_info.py.exp b/tests/feature_check/target_info.py.exp new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/tests/float/cmath_fun.py b/tests/float/cmath_fun.py index 39011733b02b4..0037d7c65596c 100644 --- a/tests/float/cmath_fun.py +++ b/tests/float/cmath_fun.py @@ -51,6 +51,9 @@ print("%.5g" % ret) elif type(ret) == tuple: print("%.5g %.5g" % ret) + elif f_name == "exp": + # exp amplifies REPR_C inaccuracies, so we need to check one digit less + print("complex(%.4g, %.4g)" % (real, ret.imag)) else: # some test (eg cmath.sqrt(-0.5)) disagree with CPython with tiny real part real = ret.real diff --git a/tests/float/complex1.py b/tests/float/complex1.py index f4107a1390fee..0a1d98b9af3eb 100644 --- a/tests/float/complex1.py +++ b/tests/float/complex1.py @@ -12,9 +12,11 @@ print(complex("1+j")) print(complex("1+2j")) print(complex("-1-2j")) +print(complex("-1+2j")) print(complex("+1-2j")) print(complex(" -1-2j ")) print(complex(" +1-2j ")) +print(complex(" -1+2j ")) print(complex("nanj")) print(complex("nan-infj")) print(complex(1, 2)) diff --git a/tests/float/float2int_intbig.py b/tests/float/float2int_intbig.py index 4167a2721ca19..3318df857655b 100644 --- a/tests/float/float2int_intbig.py +++ b/tests/float/float2int_intbig.py @@ -47,6 +47,7 @@ # TODO why does 10**12 fail this test for single precision float? testpass = True +# CIRCUITPY-CHANGE: correct negation p10_rng = 9 if (ll_type == 0 and not is_64bit) else 11 for i in range(0, p10_rng): digcnt = len(str(int(10.0**i))) - 1 diff --git a/tests/float/float_array.py b/tests/float/float_array.py index 3d128da83819f..cfff3b220c657 100644 --- a/tests/float/float_array.py +++ b/tests/float/float_array.py @@ -19,4 +19,10 @@ def test(a): test(array("f")) test(array("d")) -print("{:.4f}".format(array("f", bytes(array("I", [0x3DCCCCCC])))[0])) +# hand-crafted floats, including non-standard nan +for float_hex in (0x3DCCCCCC, 0x7F800024, 0x7FC00004): + f = array("f", bytes(array("I", [float_hex])))[0] + if type(f) is float: + print("{:.4e}".format(f)) + else: + print(f) diff --git a/tests/float/float_format.py b/tests/float/float_format.py index 98ed0eb096fa4..0eb8b232b063a 100644 --- a/tests/float/float_format.py +++ b/tests/float/float_format.py @@ -2,14 +2,25 @@ # general rounding for val in (116, 1111, 1234, 5010, 11111): - print("%.0f" % val) - print("%.1f" % val) - print("%.3f" % val) + print("Test on %d / 1000:" % val) + for fmt in ("%.5e", "%.3e", "%.1e", "%.0e", "%.3f", "%.1f", "%.0f", "%.3g", "%.1g", "%.0g"): + print(fmt, fmt % (val / 1000)) + +# make sure round-up to the next unit is handled properly +for val in range(4, 9): + divi = 10**val + print("Test on 99994 / (10 ** %d):" % val) + for fmt in ("%.5e", "%.3e", "%.1e", "%.0e", "%.3f", "%.1f", "%.0f", "%.3g", "%.1g", "%.0g"): + print(fmt, fmt % (99994 / divi)) # make sure rounding is done at the correct precision for prec in range(8): print(("%%.%df" % prec) % 6e-5) +# make sure trailing zeroes are added properly +for prec in range(8): + print(("%%.%df" % prec) % 1e19) + # check certain cases that had a digit value of 10 render as a ":" character print("%.2e" % float("9" * 51 + "e-39")) print("%.2e" % float("9" * 40 + "e-21")) diff --git a/tests/float/float_format_accuracy.py b/tests/float/float_format_accuracy.py new file mode 100644 index 0000000000000..f9467f9c05d89 --- /dev/null +++ b/tests/float/float_format_accuracy.py @@ -0,0 +1,73 @@ +# Test accuracy of `repr` conversions. +# This test also increases code coverage for corner cases. + +try: + import array, math, random +except ImportError: + print("SKIP") + raise SystemExit + +# The largest errors come from seldom used very small numbers, near the +# limit of the representation. So we keep them out of this test to keep +# the max relative error display useful. +if float("1e-100") == 0.0: + # single-precision + float_type = "f" + float_size = 4 + # testing range + min_expo = -96 # i.e. not smaller than 1.0e-29 + # Expected results (given >=50'000 samples): + # - MICROPY_FLTCONV_IMPL_EXACT: 100% exact conversions + # - MICROPY_FLTCONV_IMPL_APPROX: >=98.53% exact conversions, max relative error <= 1.01e-7 + min_success = 0.980 # with only 1200 samples, the success rate is lower + max_rel_err = 1.1e-7 + # REPR_C is typically used with FORMAT_IMPL_BASIC, which has a larger error + is_REPR_C = float("1.0000001") == float("1.0") + if is_REPR_C: # REPR_C + min_success = 0.83 + max_rel_err = 5.75e-07 +else: + # double-precision + float_type = "d" + float_size = 8 + # testing range + min_expo = -845 # i.e. not smaller than 1.0e-254 + # Expected results (given >=200'000 samples): + # - MICROPY_FLTCONV_IMPL_EXACT: 100% exact conversions + # - MICROPY_FLTCONV_IMPL_APPROX: >=99.83% exact conversions, max relative error <= 2.7e-16 + min_success = 0.997 # with only 1200 samples, the success rate is lower + max_rel_err = 2.7e-16 + + +# Deterministic pseudorandom generator. Designed to be uniform +# on mantissa values and exponents, not on the represented number +def pseudo_randfloat(): + rnd_buff = bytearray(float_size) + for _ in range(float_size): + rnd_buff[_] = random.getrandbits(8) + return array.array(float_type, rnd_buff)[0] + + +random.seed(42) +stats = 0 +N = 1200 +max_err = 0 +for _ in range(N): + f = pseudo_randfloat() + while type(f) is not float or math.isinf(f) or math.isnan(f) or math.frexp(f)[1] <= min_expo: + f = pseudo_randfloat() + + str_f = repr(f) + f2 = float(str_f) + if f2 == f: + stats += 1 + else: + error = abs((f2 - f) / f) + if max_err < error: + max_err = error + +print(N, "values converted") +if stats / N >= min_success and max_err <= max_rel_err: + print("float format accuracy OK") +else: + print("FAILED: repr rate=%.3f%% max_err=%.3e" % (100 * stats / N, max_err)) diff --git a/tests/float/float_format_ints.py b/tests/float/float_format_ints.py index df4444166c5fa..7b7b30c4b340b 100644 --- a/tests/float/float_format_ints.py +++ b/tests/float/float_format_ints.py @@ -12,14 +12,42 @@ print(title, "with format", f_fmt, "gives", f_fmt.format(f)) print(title, "with format", g_fmt, "gives", g_fmt.format(f)) +# The tests below check border cases involving all mantissa bits. +# In case of REPR_C, where the mantissa is missing two bits, the +# the string representation for such numbers might not always be exactly +# the same but nevertheless be correct, so we must allow a few exceptions. +is_REPR_C = float("1.0000001") == float("1.0") + # 16777215 is 2^24 - 1, the largest integer that can be completely held # in a float32. -print("{:f}".format(16777215)) +val_str = "{:f}".format(16777215) + +# When using REPR_C, 16777215.0 is the same as 16777212.0 or 16777214.4 +# (depending on the implementation of pow() function, the result may differ) +if is_REPR_C and (val_str == "16777212.000000" or val_str == "16777214.400000"): + val_str = "16777215.000000" + +print(val_str) + # 4294967040 = 16777215 * 128 is the largest integer that is exactly # represented by a float32 and that will also fit within a (signed) int32. # The upper bound of our integer-handling code is actually double this, # but that constant might cause trouble on systems using 32 bit ints. -print("{:f}".format(2147483520)) +val_str = "{:f}".format(2147483520) + +# When using FLOAT_IMPL_FLOAT, 2147483520.0 == 2147483500.0 +# Both representations are valid, the second being "simpler" +is_float32 = float("1e300") == float("inf") +if is_float32 and val_str == "2147483500.000000": + val_str = "2147483520.000000" + +# When using REPR_C, 2147483520.0 is the same as 2147483200.0 +# Both representations are valid, the second being "simpler" +if is_REPR_C and val_str == "2147483200.000000": + val_str = "2147483520.000000" + +print(val_str) + # Very large positive integers can be a test for precision and resolution. # This is a weird way to represent 1e38 (largest power of 10 for float32). print("{:.6e}".format(float("9" * 30 + "e8"))) diff --git a/tests/float/float_format_ints_power10.py b/tests/float/float_format_ints_power10.py index 98900c135b2e4..7ea200f18ef06 100644 --- a/tests/float/float_format_ints_power10.py +++ b/tests/float/float_format_ints_power10.py @@ -3,6 +3,6 @@ # Check that powers of 10 (that fit in float32) format correctly. for i in range(31): - # It works to 12 digits on all platforms *except* qemu-arm, where + # It works to 12 digits on all platforms *except* qemu, where # 10^11 comes out as 10000000820 or something. print(i, "{:.7g}".format(float("1e" + str(i)))) diff --git a/tests/float/float_parse.py b/tests/float/float_parse.py index de27c33e7be57..6131da0a63ab9 100644 --- a/tests/float/float_parse.py +++ b/tests/float/float_parse.py @@ -31,6 +31,9 @@ print(float("1e18446744073709551621")) print(float("1e-18446744073709551621")) +# mantissa overflow while processing deferred trailing zeros +print(float("10000000000000000000001")) + # check small decimals are as close to their true value as possible for n in range(1, 10): print(float("0.%u" % n) == n / 10) diff --git a/tests/float/float_parse_doubleprec.py b/tests/float/float_parse_doubleprec.py index 81fcadcee88b4..c1b0b4823b038 100644 --- a/tests/float/float_parse_doubleprec.py +++ b/tests/float/float_parse_doubleprec.py @@ -19,3 +19,9 @@ print(float("1.00000000000000000000e-307")) print(float("10.0000000000000000000e-308")) print(float("100.000000000000000000e-309")) + +# ensure repr() adds an extra digit when needed for accurate parsing +print(float(repr(float("2.0") ** 100)) == float("2.0") ** 100) + +# ensure repr does not add meaningless extra digits (1.234999999999) +print(repr(1.2345)) diff --git a/tests/float/float_struct.py b/tests/float/float_struct.py index 47fe405018038..6e282a6afe3ee 100644 --- a/tests/float/float_struct.py +++ b/tests/float/float_struct.py @@ -8,7 +8,7 @@ i = 1.0 + 1 / 2 # TODO: it looks like '=' format modifier is not yet supported # for fmt in ('f', 'd', '>f', '>d', 'f", ">d", "e", ">f", ">d", "", "=", "^"): for fill in ("", " ", "0", "@"): for sign in ("", "+", "-", " "): - # An empty precision defaults to 6, but when uPy is + # An empty precision defaults to 6, but when MicroPython is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses @@ -164,7 +164,7 @@ def test_fmt(conv, fill, alignment, sign, prefix, width, precision, type, arg): for alignment in ("", "<", ">", "=", "^"): for fill in ("", " ", "0", "@"): for sign in ("", "+", "-", " "): - # An empty precision defaults to 6, but when uPy is + # An empty precision defaults to 6, but when MicroPython is # configured to use a float, we can only use a # precision of 6 with numbers less than 10 and still # get results that compare to CPython (which uses diff --git a/tests/float/string_format_fp30.py b/tests/float/string_format_fp30.py deleted file mode 100644 index 5f0b213daa342..0000000000000 --- a/tests/float/string_format_fp30.py +++ /dev/null @@ -1,42 +0,0 @@ -def test(fmt, *args): - print("{:8s}".format(fmt) + ">" + fmt.format(*args) + "<") - - -test("{:10.4}", 123.456) -test("{:10.4e}", 123.456) -test("{:10.4e}", -123.456) -# test("{:10.4f}", 123.456) -# test("{:10.4f}", -123.456) -test("{:10.4g}", 123.456) -test("{:10.4g}", -123.456) -test("{:10.4n}", 123.456) -test("{:e}", 100) -test("{:f}", 200) -test("{:g}", 300) - -test("{:10.4E}", 123.456) -test("{:10.4E}", -123.456) -# test("{:10.4F}", 123.456) -# test("{:10.4F}", -123.456) -test("{:10.4G}", 123.456) -test("{:10.4G}", -123.456) - -test("{:06e}", float("inf")) -test("{:06e}", float("-inf")) -test("{:06e}", float("nan")) - -# The following fails right now -# test("{:10.1}", 0.0) - -print("%.0f" % (1.750000 % 0.08333333333)) -# Below isn't compatible with single-precision float -# print("%.1f" % (1.750000 % 0.08333333333)) -# print("%.2f" % (1.750000 % 0.08333333333)) -# print("%.12f" % (1.750000 % 0.08333333333)) - -# tests for errors in format string - -try: - "{:10.1b}".format(0.0) -except ValueError: - print("ValueError") diff --git a/tests/float/string_format_modulo.py b/tests/float/string_format_modulo.py index 3c206b7393588..55314643351db 100644 --- a/tests/float/string_format_modulo.py +++ b/tests/float/string_format_modulo.py @@ -6,7 +6,7 @@ print("%u" % 1.0) # these 3 have different behaviour in Python 3.x versions -# uPy raises a TypeError, following Python 3.5 (earlier versions don't) +# MicroPython raises a TypeError, following Python 3.5 (earlier versions don't) # print("%x" % 18.0) # print("%o" % 18.0) # print("%X" % 18.0) diff --git a/tests/float/string_format_modulo3.py b/tests/float/string_format_modulo3.py index f9d9c43cdf42d..f8aeeda20f29c 100644 --- a/tests/float/string_format_modulo3.py +++ b/tests/float/string_format_modulo3.py @@ -1,3 +1,3 @@ -# uPy and CPython outputs differ for the following +# Test corner cases where MicroPython and CPython outputs used to differ in the past print("%.1g" % -9.9) # round up 'g' with '-' sign print("%.2g" % 99.9) # round up diff --git a/tests/float/string_format_modulo3.py.exp b/tests/float/string_format_modulo3.py.exp deleted file mode 100644 index 71432b3404519..0000000000000 --- a/tests/float/string_format_modulo3.py.exp +++ /dev/null @@ -1,2 +0,0 @@ --10 -100 diff --git a/tests/frozen/frozentest.py b/tests/frozen/frozentest.py index 78cdd60bf0431..74bdfb3b267f2 100644 --- a/tests/frozen/frozentest.py +++ b/tests/frozen/frozentest.py @@ -1,4 +1,4 @@ -print("uPy") +print("interned") print("a long string that is not interned") print("a string that has unicode αβγ chars") print(b"bytes 1234\x01") diff --git a/tests/import/builtin_ext.py b/tests/import/builtin_ext.py index 9d2344d400dae..79ee901ea6774 100644 --- a/tests/import/builtin_ext.py +++ b/tests/import/builtin_ext.py @@ -1,3 +1,9 @@ +try: + import uos, utime +except ImportError: + print("SKIP") + raise SystemExit + # Verify that sys is a builtin. import sys diff --git a/tests/import/builtin_import.py b/tests/import/builtin_import.py index 734498d1be47b..364b0bae912ae 100644 --- a/tests/import/builtin_import.py +++ b/tests/import/builtin_import.py @@ -20,3 +20,12 @@ __import__("xyz", None, None, None, -1) except ValueError: print("ValueError") + +# globals is not checked for level=0 +__import__("builtins", "globals") + +# globals must be a dict (or None) for level>0 +try: + __import__("builtins", "globals", None, None, 1) +except TypeError: + print("TypeError") diff --git a/tests/import/ext/os.py b/tests/import/ext/os.py index 00c2194d345f4..4cd8a0dde03af 100644 --- a/tests/import/ext/os.py +++ b/tests/import/ext/os.py @@ -1,3 +1,4 @@ print("os from filesystem") +# CIRCUITPY-CHANGE: no uos extra = 1 diff --git a/tests/import/import_broken.py b/tests/import/import_broken.py index 3c7cf4a498528..440922157ef10 100644 --- a/tests/import/import_broken.py +++ b/tests/import/import_broken.py @@ -1,3 +1,9 @@ +try: + Exception.__class__ +except AttributeError: + print("SKIP") + raise SystemExit + import sys, pkg # Modules we import are usually added to sys.modules. diff --git a/tests/import/import_file.py b/tests/import/import_file.py index 90ec4e41e77aa..4cf307641c62d 100644 --- a/tests/import/import_file.py +++ b/tests/import/import_file.py @@ -1,3 +1,7 @@ +if "__file__" not in globals(): + print("SKIP") + raise SystemExit + import import1b print(import1b.__file__) diff --git a/tests/import/import_override.py b/tests/import/import_override.py index 029ebe54c1f70..0144e78cb9f32 100644 --- a/tests/import/import_override.py +++ b/tests/import/import_override.py @@ -2,6 +2,10 @@ def custom_import(name, globals, locals, fromlist, level): + # CPython always tries to import _io, so just let that through as-is. + if name == "_io": + return orig_import(name, globals, locals, fromlist, level) + print("import", name, fromlist, level) class M: diff --git a/tests/import/import_override.py.exp b/tests/import/import_override.py.exp deleted file mode 100644 index 365248da6d847..0000000000000 --- a/tests/import/import_override.py.exp +++ /dev/null @@ -1,2 +0,0 @@ -import import1b None 0 -456 diff --git a/tests/import/import_override2.py b/tests/import/import_override2.py new file mode 100644 index 0000000000000..25aac44fe98d0 --- /dev/null +++ b/tests/import/import_override2.py @@ -0,0 +1,18 @@ +# test overriding __import__ combined with importing from the filesystem + + +def custom_import(name, globals, locals, fromlist, level): + if level > 0: + print("import", name, fromlist, level) + return orig_import(name, globals, locals, fromlist, level) + + +orig_import = __import__ +try: + __import__("builtins").__import__ = custom_import +except AttributeError: + print("SKIP") + raise SystemExit + +# import calls __import__ behind the scenes +import pkg7.subpkg1.subpkg2.mod3 diff --git a/tests/import/import_pkg7.py.exp b/tests/import/import_pkg7.py.exp deleted file mode 100644 index 8f21a615f6a61..0000000000000 --- a/tests/import/import_pkg7.py.exp +++ /dev/null @@ -1,8 +0,0 @@ -pkg __name__: pkg7 -pkg __name__: pkg7.subpkg1 -pkg __name__: pkg7.subpkg1.subpkg2 -mod1 -mod2 -mod1.foo -mod2.bar -ImportError diff --git a/tests/import/import_pkg9.py b/tests/import/import_pkg9.py index 4de028494f1a2..c2e0b618b6969 100644 --- a/tests/import/import_pkg9.py +++ b/tests/import/import_pkg9.py @@ -13,4 +13,4 @@ import pkg9.mod2 pkg9.mod1() -print(pkg9.mod2.__name__, type(pkg9.mod2).__name__) +print(pkg9.mod2.__name__, type(pkg9.mod2)) diff --git a/tests/import/import_star.py b/tests/import/import_star.py new file mode 100644 index 0000000000000..2cb21b877d728 --- /dev/null +++ b/tests/import/import_star.py @@ -0,0 +1,59 @@ +# test `from package import *` conventions, including __all__ support +# +# This test requires MICROPY_CONFIG_ROM_LEVEL_AT_LEAST_BASIC_FEATURES + +try: + next(iter([]), 42) +except TypeError: + # 2-argument version of next() not supported + # we are probably not at MICROPY_CONFIG_ROM_LEVEL_BASIC_FEATURES + print("SKIP") + raise SystemExit + +# 1. test default visibility +from pkgstar_default import * + +print("visibleFun" in globals()) +print("VisibleClass" in globals()) +print("_hiddenFun" in globals()) +print("_HiddenClass" in globals()) +print(visibleFun()) + +# 2. test explicit visibility as defined by __all__ (as an array) +from pkgstar_all_array import * + +print("publicFun" in globals()) +print("PublicClass" in globals()) +print("unlistedFun" in globals()) +print("UnlistedClass" in globals()) +print("_privateFun" in globals()) +print("_PrivateClass" in globals()) +print(publicFun()) +# test dynamic import as used in asyncio +print("dynamicFun" in globals()) +print(dynamicFun()) + +# 3. test explicit visibility as defined by __all__ (as an tuple) +from pkgstar_all_tuple import * + +print("publicFun2" in globals()) +print("PublicClass2" in globals()) +print("unlistedFun2" in globals()) +print("UnlistedClass2" in globals()) +print(publicFun2()) + +# 4. test reporting of missing entries in __all__ +try: + from pkgstar_all_miss import * + + print("missed detection of incorrect __all__ definition") +except AttributeError as er: + print("AttributeError triggered for bad __all__ definition") + +# 5. test reporting of invalid __all__ definition +try: + from pkgstar_all_inval import * + + print("missed detection of incorrect __all__ definition") +except TypeError as er: + print("TypeError triggered for bad __all__ definition") diff --git a/tests/import/import_star_error.py b/tests/import/import_star_error.py index 9e1757b6ef5a2..73d9c863d6f51 100644 --- a/tests/import/import_star_error.py +++ b/tests/import/import_star_error.py @@ -1,5 +1,10 @@ # test errors with import * +if not hasattr(object, "__init__"): + # target doesn't have MICROPY_CPYTHON_COMPAT enabled, so doesn't check for "import *" + print("SKIP") + raise SystemExit + # 'import *' is not allowed in function scope try: exec("def foo(): from x import *") diff --git a/tests/import/module_getattr.py.exp b/tests/import/module_getattr.py.exp deleted file mode 100644 index bc59c12aa16bd..0000000000000 --- a/tests/import/module_getattr.py.exp +++ /dev/null @@ -1 +0,0 @@ -False diff --git a/tests/import/pkg7/subpkg1/subpkg2/mod3.py b/tests/import/pkg7/subpkg1/subpkg2/mod3.py index b0f4279fcf57b..f7f4c1e65f46f 100644 --- a/tests/import/pkg7/subpkg1/subpkg2/mod3.py +++ b/tests/import/pkg7/subpkg1/subpkg2/mod3.py @@ -5,7 +5,9 @@ print(bar) # attempted relative import beyond top-level package +# On older versions of CPython (eg 3.8) this is a ValueError, but on +# newer CPython (eg 3.11) and MicroPython it's an ImportError. try: from .... import mod1 -except ImportError: +except (ImportError, ValueError): print("ImportError") diff --git a/tests/import/pkgstar_all_array/__init__.py b/tests/import/pkgstar_all_array/__init__.py new file mode 100644 index 0000000000000..03b012123fe0c --- /dev/null +++ b/tests/import/pkgstar_all_array/__init__.py @@ -0,0 +1,49 @@ +__all__ = ["publicFun", "PublicClass", "dynamicFun"] + + +# Definitions below should always be imported by a star import +def publicFun(): + return 1 + + +class PublicClass: + def __init__(self): + self._val = 1 + + +# If __all__ support is enabled, definitions below +# should not be imported by a star import +def unlistedFun(): + return 0 + + +class UnlistedClass: + def __init__(self): + self._val = 0 + + +# Definitions below should be not be imported by a star import +# (they start with an underscore, and are not listed in __all__) +def _privateFun(): + return -1 + + +class _PrivateClass: + def __init__(self): + self._val = -1 + + +# Test lazy loaded function, as used by extmod/asyncio: +# Works with a star import only if __all__ support is enabled +_attrs = { + "dynamicFun": "funcs", +} + + +def __getattr__(attr): + mod = _attrs.get(attr, None) + if mod is None: + raise AttributeError(attr) + value = getattr(__import__(mod, globals(), locals(), True, 1), attr) + globals()[attr] = value + return value diff --git a/tests/import/pkgstar_all_array/funcs.py b/tests/import/pkgstar_all_array/funcs.py new file mode 100644 index 0000000000000..7540d70f66bce --- /dev/null +++ b/tests/import/pkgstar_all_array/funcs.py @@ -0,0 +1,2 @@ +def dynamicFun(): + return 777 diff --git a/tests/import/pkgstar_all_inval/__init__.py b/tests/import/pkgstar_all_inval/__init__.py new file mode 100644 index 0000000000000..7022476c19be8 --- /dev/null +++ b/tests/import/pkgstar_all_inval/__init__.py @@ -0,0 +1 @@ +__all__ = 42 diff --git a/tests/import/pkgstar_all_miss/__init__.py b/tests/import/pkgstar_all_miss/__init__.py new file mode 100644 index 0000000000000..f9bbb538072bf --- /dev/null +++ b/tests/import/pkgstar_all_miss/__init__.py @@ -0,0 +1,8 @@ +__all__ = ("existingFun", "missingFun") + + +def existingFun(): + return None + + +# missingFun is not defined, should raise an error on import diff --git a/tests/import/pkgstar_all_tuple/__init__.py b/tests/import/pkgstar_all_tuple/__init__.py new file mode 100644 index 0000000000000..433ddc8e97639 --- /dev/null +++ b/tests/import/pkgstar_all_tuple/__init__.py @@ -0,0 +1,22 @@ +__all__ = ("publicFun2", "PublicClass2") + + +# Definitions below should always be imported by a star import +def publicFun2(): + return 2 + + +class PublicClass2: + def __init__(self): + self._val = 2 + + +# If __all__ support is enabled, definitions below +# should not be imported by a star import +def unlistedFun2(): + return 0 + + +class UnlistedClass2: + def __init__(self): + self._val = 0 diff --git a/tests/import/pkgstar_default/__init__.py b/tests/import/pkgstar_default/__init__.py new file mode 100644 index 0000000000000..4947e4ce7f180 --- /dev/null +++ b/tests/import/pkgstar_default/__init__.py @@ -0,0 +1,20 @@ +# When __all__ is undefined, star import should only +# show objects that do not start with an underscore + + +def visibleFun(): + return 42 + + +class VisibleClass: + def __init__(self): + self._val = 42 + + +def _hiddenFun(): + return -1 + + +class _HiddenClass: + def __init__(self): + self._val = -1 diff --git a/tests/inlineasm/rv32/asmargs.py b/tests/inlineasm/rv32/asmargs.py new file mode 100644 index 0000000000000..78afd511150d6 --- /dev/null +++ b/tests/inlineasm/rv32/asmargs.py @@ -0,0 +1,44 @@ +# test passing arguments + + +@micropython.asm_rv32 +def arg0(): + c_li(a0, 1) + + +print(arg0()) + + +@micropython.asm_rv32 +def arg1(a0): + addi(a0, a0, 1) + + +print(arg1(1)) + + +@micropython.asm_rv32 +def arg2(a0, a1): + add(a0, a0, a1) + + +print(arg2(1, 2)) + + +@micropython.asm_rv32 +def arg3(a0, a1, a2): + add(a0, a0, a1) + add(a0, a0, a2) + + +print(arg3(1, 2, 3)) + + +@micropython.asm_rv32 +def arg4(a0, a1, a2, a3): + add(a0, a0, a1) + add(a0, a0, a2) + add(a0, a0, a3) + + +print(arg4(1, 2, 3, 4)) diff --git a/tests/inlineasm/asmargs.py.exp b/tests/inlineasm/rv32/asmargs.py.exp similarity index 100% rename from tests/inlineasm/asmargs.py.exp rename to tests/inlineasm/rv32/asmargs.py.exp diff --git a/tests/inlineasm/rv32/asmarith.py b/tests/inlineasm/rv32/asmarith.py new file mode 100644 index 0000000000000..8b864c0b3b289 --- /dev/null +++ b/tests/inlineasm/rv32/asmarith.py @@ -0,0 +1,79 @@ +# test arithmetic opcodes + + +@micropython.asm_rv32 +def f1(): + li(a0, 0x100) + li(a1, 1) + add(a0, a0, a1) + addi(a0, a0, 1) + addi(a0, a0, -2) + sub(a0, a0, a1) + c_add(a0, a1) + c_addi(a0, -1) + c_sub(a0, a1) + + +print(hex(f1())) + + +@micropython.asm_rv32 +def f2(): + li(a0, 0x10FF) + li(a1, 1) + and_(a2, a0, a1) + andi(a3, a0, 0x10) + or_(a2, a2, a3) + ori(a2, a2, 8) + li(a1, 0x200) + c_or(a2, a1) + li(a1, 0xF0) + mv(a0, a2) + c_and(a0, a1) + li(a1, 0x101) + xor(a0, a0, a1) + xori(a0, a0, 0x101) + c_xor(a0, a1) + + +print(hex(f2())) + + +@micropython.asm_rv32 +def f3(a0, a1): + slt(a0, a0, a1) + + +print(f3(0xFFFFFFF0, 0xFFFFFFF1)) +print(f3(0x0, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF0)) + + +@micropython.asm_rv32 +def f4(a0, a1): + sltu(a0, a0, a1) + + +print(f3(0xFFFFFFF0, 0xFFFFFFF1)) +print(f3(0x0, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF1)) +print(f3(0xFFFFFFF1, 0xFFFFFFF0)) + + +@micropython.asm_rv32 +def f5(a0): + slti(a0, a0, -2) + + +print(f5(-1)) +print(f5(-3)) + + +@micropython.asm_rv32 +def f6(a0): + sltiu(a0, a0, -2) + + +print(f6(-1)) +print(f6(-3)) diff --git a/tests/inlineasm/rv32/asmarith.py.exp b/tests/inlineasm/rv32/asmarith.py.exp new file mode 100644 index 0000000000000..7da4dd5c93c40 --- /dev/null +++ b/tests/inlineasm/rv32/asmarith.py.exp @@ -0,0 +1,14 @@ +0xfe +0x111 +1 +0 +0 +0 +1 +0 +0 +0 +0 +1 +0 +1 diff --git a/tests/inlineasm/rv32/asmbranch.py b/tests/inlineasm/rv32/asmbranch.py new file mode 100644 index 0000000000000..d7d059d4067c6 --- /dev/null +++ b/tests/inlineasm/rv32/asmbranch.py @@ -0,0 +1,161 @@ +# test branch instructions + + +@micropython.asm_rv32 +def tbeq(a0): + mv(a1, a0) + + li(a0, 10) + li(a2, 1) + beq(a1, a2, end) + + li(a0, 20) + li(a2, 2) + beq(a1, a2, end) + + li(a0, 30) + li(a2, 3) + beq(a1, a2, end) + + li(a0, 0) + + label(end) + + +print(tbeq(0)) +print(tbeq(1)) +print(tbeq(2)) +print(tbeq(3)) + + +@micropython.asm_rv32 +def tbne(a0): + mv(a1, a0) + + li(a0, 10) + li(a2, 1) + bne(a1, a2, end) + + li(a0, 20) + li(a2, 2) + bne(a1, a2, end) + + li(a0, 30) + li(a2, 3) + bne(a1, a2, end) + + li(a0, 0) + + label(end) + + +print(tbne(0)) +print(tbne(1)) +print(tbne(2)) +print(tbne(3)) + + +@micropython.asm_rv32 +def tbgeu(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, 2) + bgeu(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbgeu(0)) +print(tbgeu(1)) +print(tbgeu(2)) +print(tbgeu(3)) + + +@micropython.asm_rv32 +def tbltu(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, 2) + bltu(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbltu(0)) +print(tbltu(1)) +print(tbltu(2)) +print(tbltu(3)) + + +@micropython.asm_rv32 +def tbge(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, -2) + bge(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tbge(-3)) +print(tbge(-2)) +print(tbge(-1)) +print(tbge(0)) + + +@micropython.asm_rv32 +def tblt(a0): + mv(a1, a0) + + li(a0, 1) + li(a2, -2) + blt(a1, a2, end) + li(a0, 0) + + label(end) + + +print(tblt(-3)) +print(tblt(-2)) +print(tblt(-1)) +print(tblt(0)) + + +@micropython.asm_rv32 +def tcbeqz(a0): + mv(a1, a0) + + li(a0, 1) + c_beqz(a1, end) + li(a0, 0) + + label(end) + + +print(tcbeqz(0)) +print(tcbeqz(1)) +print(tcbeqz(2)) +print(tcbeqz(3)) + + +@micropython.asm_rv32 +def tcbnez(a0): + mv(a1, a0) + + li(a0, 1) + c_bnez(a1, end) + li(a0, 0) + + label(end) + + +print(tcbnez(0)) +print(tcbnez(1)) +print(tcbnez(2)) +print(tcbnez(3)) diff --git a/tests/inlineasm/rv32/asmbranch.py.exp b/tests/inlineasm/rv32/asmbranch.py.exp new file mode 100644 index 0000000000000..baae69149538e --- /dev/null +++ b/tests/inlineasm/rv32/asmbranch.py.exp @@ -0,0 +1,32 @@ +0 +10 +20 +30 +10 +20 +10 +10 +0 +0 +1 +1 +1 +1 +0 +0 +0 +1 +1 +1 +1 +0 +0 +0 +1 +0 +0 +0 +0 +1 +1 +1 diff --git a/tests/inlineasm/rv32/asmconst.py b/tests/inlineasm/rv32/asmconst.py new file mode 100644 index 0000000000000..2b6363a43db95 --- /dev/null +++ b/tests/inlineasm/rv32/asmconst.py @@ -0,0 +1,49 @@ +# test constants in assembler + + +@micropython.asm_rv32 +def c1(): + li(a0, 0xFFFFFFFF) + li(a1, 0xF0000000) + sub(a0, a0, a1) + + +print(hex(c1())) + + +@micropython.asm_rv32 +def c2(): + lui(a0, 0x12345) + li(a1, 0x678) + add(a0, a0, a1) + + +print(hex(c2())) + + +@micropython.asm_rv32 +def c3() -> uint: + lui(a0, 0) + addi(a0, a0, 0x7FF) + + +print(hex(c3())) + + +@micropython.asm_rv32 +def c4() -> uint: + lui(a0, 0) + addi(a0, a0, -1) + + +print(hex(c4())) + + +@micropython.asm_rv32 +def c5(): + c_lui(a0, 1) + c_li(a1, 1) + c_add(a0, a1) + + +print(hex(c5())) diff --git a/tests/inlineasm/rv32/asmconst.py.exp b/tests/inlineasm/rv32/asmconst.py.exp new file mode 100644 index 0000000000000..0c713a841486b --- /dev/null +++ b/tests/inlineasm/rv32/asmconst.py.exp @@ -0,0 +1,5 @@ +0xfffffff +0x12345678 +0x7ff +0xffffffff +0x1001 diff --git a/tests/inlineasm/rv32/asmcsr.py b/tests/inlineasm/rv32/asmcsr.py new file mode 100644 index 0000000000000..f27e2aa5e34ec --- /dev/null +++ b/tests/inlineasm/rv32/asmcsr.py @@ -0,0 +1,65 @@ +# test csr instructions + +# CSR 0x340 is `mscratch`. This test suite is only safe to run on a system +# where it is known that there is no other code that can read from or write +# to that register. The qemu port is one such system, as the CSR is only +# accessed when a machine exception occurs, and at that point it doesn't matter +# anymore whether these tests are running or not. + + +@micropython.asm_rv32 +def csr(): + li(a0, 0) + csrrw(zero, zero, 0x340) # All zeroes + csrrs(a1, zero, 0x340) # Read zeroes + c_bnez(a1, end) + addi(a0, a0, 1) + li(a1, 0xA5A5A5A5) + li(a2, 0x5A5A5A5A) + csrrs(a2, a1, 0x340) # Read zeroes, set 0xA5A5A5A5 + c_bnez(a2, end) + addi(a0, a0, 1) + csrrs(a3, zero, 0x340) # Read 0xA5A5A5A5 + bne(a3, a1, end) + addi(a0, a0, 1) + li(a2, 0xF0F0F0F0) + csrrc(zero, a2, 0x340) # Clear upper half + csrrs(a3, zero, 0x340) # Read 0x05050505 + xori(a2, a2, -1) + and_(a2, a1, a2) + bne(a2, a3, end) + addi(a0, a0, 1) + label(end) + + +print(csr()) + + +@micropython.asm_rv32 +def csri(): + li(a0, 0) + csrrwi(zero, 0x340, 15) # Write 0xF + csrrs(a1, zero, 0x340) # Read 0xF + csrrsi(a2, 0x340, 0) # Read + bne(a1, a2, end) + addi(a0, a0, 1) + csrrci(a2, 0x340, 0) # Read + bne(a1, a2, end) + addi(a0, a0, 1) + li(a2, 15) + bne(a1, a2, end) + addi(a0, a0, 1) + csrrci(zero, 0x340, 1) # Clear bit 1 + csrrs(a1, zero, 0x340) # Read 0xE + li(a2, 14) + bne(a1, a2, end) + addi(a0, a0, 1) + csrrsi(zero, 0x340, 1) # Set bit 1 + csrrs(a1, zero, 0x340) # Read 0xF + li(a2, 15) + bne(a1, a2, end) + addi(a0, a0, 1) + label(end) + + +print(csri()) diff --git a/tests/inlineasm/rv32/asmcsr.py.exp b/tests/inlineasm/rv32/asmcsr.py.exp new file mode 100644 index 0000000000000..61c83cba41ce3 --- /dev/null +++ b/tests/inlineasm/rv32/asmcsr.py.exp @@ -0,0 +1,2 @@ +4 +5 diff --git a/tests/inlineasm/rv32/asmdata.py b/tests/inlineasm/rv32/asmdata.py new file mode 100644 index 0000000000000..5e555ef4bf465 --- /dev/null +++ b/tests/inlineasm/rv32/asmdata.py @@ -0,0 +1,33 @@ +# test the "data" directive + + +@micropython.asm_rv32 +def ret_num(a0) -> uint: + slli(a0, a0, 2) + addi(a0, a0, 16) + auipc(a1, 0) + add(a1, a1, a0) + lw(a0, 0(a1)) + jal(zero, HERE) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num(i))) + + +@micropython.asm_rv32 +def ret_num_la(a0) -> uint: + slli(a0, a0, 2) + la(a1, DATA) + add(a1, a1, a0) + lw(a0, 0(a1)) + jal(zero, HERE) + label(DATA) + data(4, 0x12345678, 0x20000000, 0x40000000, 0x7FFFFFFF + 1, (1 << 32) - 2) + label(HERE) + + +for i in range(5): + print(hex(ret_num_la(i))) diff --git a/tests/inlineasm/rv32/asmdata.py.exp b/tests/inlineasm/rv32/asmdata.py.exp new file mode 100644 index 0000000000000..79e92bdfa5de5 --- /dev/null +++ b/tests/inlineasm/rv32/asmdata.py.exp @@ -0,0 +1,10 @@ +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe +0x12345678 +0x20000000 +0x40000000 +0x80000000 +0xfffffffe diff --git a/tests/inlineasm/rv32/asmdivmul.py b/tests/inlineasm/rv32/asmdivmul.py new file mode 100644 index 0000000000000..e1120c6f63cef --- /dev/null +++ b/tests/inlineasm/rv32/asmdivmul.py @@ -0,0 +1,63 @@ +@micropython.asm_rv32 +def sdiv(a0, a1): + div(a0, a0, a1) + + +@micropython.asm_rv32 +def udiv(a0, a1): + divu(a0, a0, a1) + + +@micropython.asm_rv32 +def srem(a0, a1): + rem(a0, a0, a1) + + +@micropython.asm_rv32 +def urem(a0, a1): + remu(a0, a0, a1) + + +print(sdiv(1234, 3)) +print(sdiv(-1234, 3)) +print(sdiv(1234, -3)) +print(sdiv(-1234, -3)) + +print(udiv(1234, 3)) +print(udiv(0xFFFFFFFF, 0x7FFFFFFF)) +print(udiv(0xFFFFFFFF, 0xFFFFFFFF)) + +print(srem(1234, 3)) +print(srem(-1234, 3)) +print(srem(1234, -3)) +print(srem(-1234, -3)) + +print(urem(1234, 3)) +print(urem(0xFFFFFFFF, 0x7FFFFFFF)) +print(urem(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_rv32 +def m1(a0, a1): + mul(a0, a0, a1) + + +@micropython.asm_rv32 +def m2(a0, a1): + mulh(a0, a0, a1) + + +@micropython.asm_rv32 +def m3(a0, a1): + mulhu(a0, a0, a1) + + +@micropython.asm_rv32 +def m4(a0, a1): + mulhsu(a0, a0, a1) + + +print(m1(0xFFFFFFFF, 2)) +print(m2(0xFFFFFFFF, 0xFFFFFFF0)) +print(m3(0xFFFFFFFF, 0xFFFFFFF0)) +print(m4(0xFFFFFFFF, 0xFFFFFFF0)) diff --git a/tests/inlineasm/rv32/asmdivmul.py.exp b/tests/inlineasm/rv32/asmdivmul.py.exp new file mode 100644 index 0000000000000..60d28635f792b --- /dev/null +++ b/tests/inlineasm/rv32/asmdivmul.py.exp @@ -0,0 +1,18 @@ +411 +-411 +-411 +411 +411 +2 +1 +1 +-1 +1 +-1 +1 +1 +0 +-2 +0 +-17 +-1 diff --git a/tests/inlineasm/rv32/asmjump.py b/tests/inlineasm/rv32/asmjump.py new file mode 100644 index 0000000000000..fe87d3f968b37 --- /dev/null +++ b/tests/inlineasm/rv32/asmjump.py @@ -0,0 +1,115 @@ +@micropython.asm_rv32 +def f1(): + li(a0, 0) + la(a1, END) + c_jr(a1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + + +print(f1()) + + +@micropython.asm_rv32 +def f2(): + addi(sp, sp, -4) + c_swsp(ra, 0) + li(ra, 0) + li(a0, 0) + c_jal(END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(ra, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + c_lwsp(ra, 0) + addi(sp, sp, 4) + + +print(f2()) + + +@micropython.asm_rv32 +def f3(): + li(a0, 0) + c_j(END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + + +print(f3()) + + +@micropython.asm_rv32 +def f4(): + addi(sp, sp, -4) + c_swsp(ra, 0) + li(ra, 0) + li(a0, 0) + la(a1, END) + c_jalr(a1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(ra, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + c_lwsp(ra, 0) + addi(sp, sp, 4) + + +print(f4()) + + +@micropython.asm_rv32 +def f5(): + li(a0, 0) + li(a1, 0) + jal(a1, END) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + label(END) + bne(a1, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + + +print(f5()) + + +@micropython.asm_rv32 +def f6(): + li(a0, 0) + la(a1, JUMP) + li(a2, 0) + jalr(a2, a1, 10) + label(JUMP) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + c_addi(a0, 1) + bne(a2, zero, SUCCESS) + c_addi(a0, 2) + label(SUCCESS) + + +print(f6()) diff --git a/tests/inlineasm/rv32/asmjump.py.exp b/tests/inlineasm/rv32/asmjump.py.exp new file mode 100644 index 0000000000000..f7eb44d66e0b1 --- /dev/null +++ b/tests/inlineasm/rv32/asmjump.py.exp @@ -0,0 +1,6 @@ +0 +0 +0 +0 +0 +0 diff --git a/tests/inlineasm/rv32/asmloadstore.py b/tests/inlineasm/rv32/asmloadstore.py new file mode 100644 index 0000000000000..2c49e07b41a5c --- /dev/null +++ b/tests/inlineasm/rv32/asmloadstore.py @@ -0,0 +1,86 @@ +# test load/store opcodes + + +@micropython.asm_rv32 +def l(): + li(a5, 4) + addi(sp, sp, -12) + li(a0, 0x123) + c_swsp(a0, 0) + addi(a1, a0, 0x111) + c_swsp(a1, 4) + addi(a2, a1, 0x111) + c_swsp(a2, 8) + mv(a4, sp) + c_lw(a3, 0(a4)) + bne(a3, a0, END) + addi(a5, a5, -1) + lw(a3, 4(a4)) + bne(a3, a1, END) + addi(a5, a5, -1) + lhu(a3, 8(a4)) + bne(a3, a2, END) + addi(a5, a5, -1) + lbu(a0, 8(a4)) + addi(a0, a0, 0x300) + bne(a0, a2, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 12) + mv(a0, a5) + + +print(l()) + + +@micropython.asm_rv32 +def s(): + li(a5, 4) + addi(sp, sp, -12) + c_swsp(zero, 0) + c_swsp(zero, 4) + c_swsp(zero, 8) + li(a0, 0x12345) + mv(a4, sp) + c_sw(a0, 0(a4)) + sh(a0, 4(a4)) + sb(a0, 8(a4)) + li(a1, 0xFFFF) + and_(a1, a0, a1) + andi(a2, a0, 0xFF) + lw(a3, 0(sp)) + bne(a3, a0, END) + addi(a5, a5, -1) + lw(a3, 4(sp)) + bne(a3, a1, END) + addi(a5, a5, -1) + lw(a3, 8(sp)) + bne(a3, a2, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 12) + mv(a0, a5) + + +print(s()) + + +@micropython.asm_rv32 +def lu(): + li(a5, 4) + addi(sp, sp, -8) + li(a0, 0xF1234567) + c_swsp(a0, 0) + c_swsp(a0, 4) + lh(a1, 0(sp)) + blt(a1, zero, END) + addi(a5, a5, -1) + lb(a2, 4(sp)) + blt(a2, zero, END) + addi(a5, a5, -1) + label(END) + addi(sp, sp, 8) + mv(a0, a5) + + +print(lu()) diff --git a/tests/inlineasm/rv32/asmloadstore.py.exp b/tests/inlineasm/rv32/asmloadstore.py.exp new file mode 100644 index 0000000000000..4539bbf2d22d5 --- /dev/null +++ b/tests/inlineasm/rv32/asmloadstore.py.exp @@ -0,0 +1,3 @@ +0 +1 +2 diff --git a/tests/inlineasm/rv32/asmrettype.py b/tests/inlineasm/rv32/asmrettype.py new file mode 100644 index 0000000000000..fc7ae61d15225 --- /dev/null +++ b/tests/inlineasm/rv32/asmrettype.py @@ -0,0 +1,33 @@ +# test return type of inline asm + + +@micropython.asm_rv32 +def ret_obj(a0) -> object: + pass + + +ret_obj(print)(1) + + +@micropython.asm_rv32 +def ret_bool(a0) -> bool: + pass + + +print(ret_bool(0), ret_bool(1)) + + +@micropython.asm_rv32 +def ret_int(a0) -> int: + slli(a0, a0, 29) + + +print(ret_int(0), hex(ret_int(1)), hex(ret_int(2)), hex(ret_int(4))) + + +@micropython.asm_rv32 +def ret_uint(a0) -> uint: + slli(a0, a0, 29) + + +print(ret_uint(0), hex(ret_uint(1)), hex(ret_uint(2)), hex(ret_uint(4))) diff --git a/tests/inlineasm/asmrettype.py.exp b/tests/inlineasm/rv32/asmrettype.py.exp similarity index 100% rename from tests/inlineasm/asmrettype.py.exp rename to tests/inlineasm/rv32/asmrettype.py.exp diff --git a/tests/inlineasm/rv32/asmsanity.py b/tests/inlineasm/rv32/asmsanity.py new file mode 100644 index 0000000000000..1a16d3504dbfe --- /dev/null +++ b/tests/inlineasm/rv32/asmsanity.py @@ -0,0 +1,204 @@ +TEMPLATE3 = """ +@micropython.asm_rv32 +def f(): + {}({}, {}, {}) +""" + +TEMPLATE2 = """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""" + +TEMPLATE1 = """ +@micropython.asm_rv32 +def f(): + {}({}) +""" + + +REGISTERS = [ + "zero", + "s0", + "s1", + "s2", + "s3", + "s4", + "s5", + "s6", + "s7", + "s8", + "s9", + "s10", + "s11", + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "a6", + "a7", + "tp", + "gp", + "sp", + "ra", + "t0", + "t1", + "t2", + "t3", + "t4", + "t5", + "t6", + "x0", + "x1", + "x2", + "x3", + "x4", + "x5", + "x6", + "x7", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", + "x16", + "x17", + "x18", + "x19", + "x20", + "x21", + "x22", + "x23", + "x24", + "x25", + "x26", + "x27", + "x28", + "x29", + "x30", + "x31", +] + + +def harness(opcode, fragment, tag): + try: + exec(fragment) + except SyntaxError: + print(tag, opcode) + + +for opcode in ("slli", "srli", "srai"): + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -1), "-") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 33), "+") + +for opcode in ("c_slli", "c_srli", "c_srai"): + harness(opcode, TEMPLATE2.format(opcode, "a0", -1), "-") + harness(opcode, TEMPLATE2.format(opcode, "a0", 33), "+") + +harness("c_slli", TEMPLATE2.format("c_slli", "zero", 0), "0") +harness("c_slli", TEMPLATE2.format("c_slli", "x0", 0), "0") + +for opcode in ("c_srli", "c_srai"): + for register in REGISTERS: + harness(opcode, TEMPLATE2.format(opcode, register, 0), register) + +for opcode in ("c_mv", "c_add"): + harness(opcode, TEMPLATE2.format(opcode, "a0", "zero"), "0l") + harness(opcode, TEMPLATE2.format(opcode, "zero", "a0"), "0r") + harness(opcode, TEMPLATE2.format(opcode, "zero", "zero"), "0b") + +harness("c_jr", TEMPLATE1.format("c_jr", "zero"), "0") + +for opcode in ("addi", "andi", "ori", "slti", "sltiu", "xori"): + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 0x7FF), ">=s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", 0x800), ">s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -2048), "<=s") + harness(opcode, TEMPLATE3.format(opcode, "a0", "a0", -2049), "=s") + harness(opcode, TEMPLATE.format(opcode, 0x800), ">s") + harness(opcode, TEMPLATE.format(opcode, -2048), "<=s") + harness(opcode, TEMPLATE.format(opcode, -2049), "0") +harness("c_addi", TEMPLATE2.format("c_andi", "zero", -512), "<0") +harness("c_addi", TEMPLATE2.format("c_andi", "s0", 0), "s0") +harness("c_addi", TEMPLATE2.format("c_andi", "s0", -100), "s") + +harness("c_andi", TEMPLATE2.format("c_andi", "zero", 0), "00") +harness("c_andi", TEMPLATE2.format("c_andi", "zero", 512), ">0") +harness("c_andi", TEMPLATE2.format("c_andi", "zero", -512), "<0") +harness("c_andi", TEMPLATE2.format("c_andi", "s0", 0), "s0") +harness("c_andi", TEMPLATE2.format("c_andi", "s0", -100), "s") + +C_REGISTERS = ( + "a0", + "a1", + "a2", + "a3", + "a4", + "a5", + "s0", + "s1", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", +) + +for opcode in ("c_and", "c_or", "c_xor"): + for source in REGISTERS: + for destination in REGISTERS: + if source in C_REGISTERS and destination in C_REGISTERS: + try: + exec( + """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""".format(opcode, source, destination) + ) + except SyntaxError: + print(source, destination, opcode) + else: + try: + exec( + """ +@micropython.asm_rv32 +def f(): + {}({}, {}) +""".format(opcode, source, destination) + ) + print(source, destination, opcode) + except SyntaxError: + pass + print(opcode) + +for opcode in ("c_lw", "c_sw"): + TEMPLATE = """ +@micropython.asm_rv32 +def f(): + {}(a0, {}(a0)) +""" + harness(opcode, TEMPLATE.format(opcode, 60), ">=s") + harness(opcode, TEMPLATE.format(opcode, 61), ">s") + harness(opcode, TEMPLATE.format(opcode, -60), "<=s") + harness(opcode, TEMPLATE.format(opcode, -61), "s addi +s andi +s ori +s slti +s sltiu +s xori +s lb +s lbu +s lh +s lhu +s lw +s sb +s sh +s sw +0 c_addi +<0 c_addi +s c_addi +00 c_andi +>0 c_andi +<0 c_andi +s c_andi +c_and +c_or +c_xor +>s c_lw +s c_sw + int: + addmi(a2, a2, {}) +print(f1(0)) +""" + +for value in (-32768, -32767, 32512, 32513, 0): + try: + exec(ADDMI_TEMPLATE.format(value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def a2(a2, a3) -> int: + addx2(a2, a2, a3) + + +@micropython.asm_xtensa +def a4(a2, a3) -> int: + addx4(a2, a2, a3) + + +@micropython.asm_xtensa +def a8(a2, a3) -> int: + addx8(a2, a2, a3) + + +@micropython.asm_xtensa +def s2(a2, a3) -> int: + subx2(a2, a2, a3) + + +@micropython.asm_xtensa +def s4(a2, a3) -> int: + subx4(a2, a2, a3) + + +@micropython.asm_xtensa +def s8(a2, a3) -> int: + subx8(a2, a2, a3) + + +for first, second in ((100, 100), (-100, 100), (-100, -100), (100, -100)): + print("a2", a2(first, second)) + print("a4", a4(first, second)) + print("a8", a8(first, second)) + print("s2", s2(first, second)) + print("s4", s4(first, second)) + print("s8", s8(first, second)) + + +@micropython.asm_xtensa +def f5(a2) -> int: + neg(a2, a2) + + +for value in (0, -100, 100): + print(f5(value)) + + +@micropython.asm_xtensa +def f6(): + movi(a2, 0x100) + movi(a3, 1) + add(a2, a2, a3) + addi(a2, a2, 1) + addi(a2, a2, -2) + sub(a2, a2, a3) + + +print(hex(f6())) + + +@micropython.asm_xtensa +def f7(): + movi(a2, 0x10FF) + movi(a3, 1) + and_(a4, a2, a3) + or_(a4, a4, a3) + movi(a3, 0x200) + xor(a2, a4, a3) + + +print(hex(f7())) + + +@micropython.asm_xtensa +def f8(a2, a3): + add_n(a2, a2, a3) + + +print(f8(100, 200)) + + +@micropython.asm_xtensa +def f9(a2): + addi_n(a2, a2, 1) + + +print(f9(100)) + + +@micropython.asm_xtensa +def f10(a2, a3) -> uint: + mull(a2, a2, a3) + + +print(hex(f10(0xC0000000, 2))) diff --git a/tests/inlineasm/xtensa/asmarith.py.exp b/tests/inlineasm/xtensa/asmarith.py.exp new file mode 100644 index 0000000000000..7aba46a27d9b5 --- /dev/null +++ b/tests/inlineasm/xtensa/asmarith.py.exp @@ -0,0 +1,40 @@ +10 +10 +0 +-32768 +-32767 is not a multiple of 256 +32512 +'addmi' integer 32513 isn't within range -32768..32512 +0 +a2 300 +a4 500 +a8 900 +s2 100 +s4 300 +s8 700 +a2 -100 +a4 -300 +a8 -700 +s2 -300 +s4 -500 +s8 -900 +a2 -300 +a4 -500 +a8 -900 +s2 -100 +s4 -300 +s8 -700 +a2 100 +a4 300 +a8 700 +s2 300 +s4 500 +s8 900 +0 +100 +-100 +0xff +0x201 +300 +101 +0x80000000 diff --git a/tests/inlineasm/xtensa/asmbranch.py b/tests/inlineasm/xtensa/asmbranch.py new file mode 100644 index 0000000000000..22bcd5a7c71a3 --- /dev/null +++ b/tests/inlineasm/xtensa/asmbranch.py @@ -0,0 +1,299 @@ +# test branch instructions + + +@micropython.asm_xtensa +def tball(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + ball(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tball(0xFFFFFFFF, 0xFFFFFFFF)) +print(tball(0xFFFEFFFF, 0xFFFFFFFF)) +print(tball(0x00000000, 0xFFFFFFFF)) +print(tball(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbany(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bany(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbany(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbany(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbany(0x00000000, 0xFFFFFFFF)) +print(tbany(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbbc(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bbc(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbbc(0xFFFFFFFF, 4)) +print(tbbc(0xFFFEFFFF, 16)) +print(tbbc(0x00000000, 1)) + + +BBCI_TEMPLATE = """ +@micropython.asm_xtensa +def tbbci(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bbci(a3, {}, end) + movi(a2, -1) + label(end) + +print(tbbci({})) +""" + + +for value, bit in ((0xFFFFFFFF, 4), (0xFFFEFFFF, 16), (0x00000000, 1)): + try: + exec(BBCI_TEMPLATE.format(bit, value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def tbbs(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bbs(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbbs(0x00000000, 4)) +print(tbbs(0x00010000, 16)) +print(tbbs(0xFFFFFFFF, 1)) + + +BBSI_TEMPLATE = """ +@micropython.asm_xtensa +def tbbsi(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bbsi(a3, {}, end) + movi(a2, -1) + label(end) + +print(tbbsi({})) +""" + + +for value, bit in ((0x00000000, 4), (0x00010000, 16), (0xFFFFFFFF, 1)): + try: + exec(BBSI_TEMPLATE.format(bit, value)) + except SyntaxError as error: + print(error) + + +@micropython.asm_xtensa +def tbeq(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + beq(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbeq(0x00000000, 0x00000000)) +print(tbeq(0x00010000, 0x00000000)) +print(tbeq(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbeqz(a2) -> int: + mov(a3, a2) + movi(a2, 0) + beqz(a3, end) + movi(a2, -1) + label(end) + + +print(tbeqz(0)) +print(tbeqz(0x12345678)) +print(tbeqz(-1)) + + +@micropython.asm_xtensa +def tbge(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bge(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbge(0x00000000, 0x00000000)) +print(tbge(0x00010000, 0x00000000)) +print(tbge(0xF0000000, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbgeu(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bgeu(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbgeu(0x00000000, 0x00000000)) +print(tbgeu(0x00010000, 0x00000000)) +print(tbgeu(0xF0000000, 0xFFFFFFFF)) +print(tbgeu(0xFFFFFFFF, 0xF0000000)) + + +@micropython.asm_xtensa +def tbgez(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bgez(a3, end) + movi(a2, -1) + label(end) + + +print(tbgez(0)) +print(tbgez(0x12345678)) +print(tbgez(-1)) + + +@micropython.asm_xtensa +def tblt(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + blt(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tblt(0x00000000, 0x00000000)) +print(tblt(0x00010000, 0x00000000)) +print(tblt(0xF0000000, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbltu(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bltu(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbltu(0x00000000, 0x00000000)) +print(tbltu(0x00010000, 0x00000000)) +print(tbltu(0xF0000000, 0xFFFFFFFF)) +print(tbltu(0xFFFFFFFF, 0xF0000000)) + + +@micropython.asm_xtensa +def tbltz(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bltz(a3, end) + movi(a2, -1) + label(end) + + +print(tbltz(0)) +print(tbltz(0x12345678)) +print(tbltz(-1)) + + +@micropython.asm_xtensa +def tbnall(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bnall(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbnall(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbnall(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbnall(0x00000000, 0xFFFFFFFF)) +print(tbnall(0xFFFFFFFF, 0x01010101)) + + +@micropython.asm_xtensa +def tbne(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bne(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbne(0x00000000, 0x00000000)) +print(tbne(0x00010000, 0x00000000)) +print(tbne(0xFFFFFFFF, 0xFFFFFFFF)) + + +@micropython.asm_xtensa +def tbnez(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bnez(a3, end) + movi(a2, -1) + label(end) + + +print(tbnez(0)) +print(tbnez(0x12345678)) +print(tbnez(-1)) + + +@micropython.asm_xtensa +def tbnone(a2, a3) -> int: + mov(a4, a2) + movi(a2, 0) + bnone(a4, a3, end) + movi(a2, -1) + label(end) + + +print(tbnone(0xFFFFFFFF, 0xFFFFFFFF)) +print(tbnone(0xFFFEFFFF, 0xFFFFFFFF)) +print(tbnone(0x00000000, 0xFFFFFFFF)) +print(tbnone(0x10101010, 0x01010101)) + + +@micropython.asm_xtensa +def tbeqz_n(a2) -> int: + mov(a3, a2) + movi(a2, 0) + beqz_n(a3, end) + movi(a2, -1) + label(end) + + +print(tbeqz_n(0)) +print(tbeqz_n(0x12345678)) +print(tbeqz_n(-1)) + + +@micropython.asm_xtensa +def tbnez_n(a2) -> int: + mov(a3, a2) + movi(a2, 0) + bnez(a3, end) + movi(a2, -1) + label(end) + + +print(tbnez_n(0)) +print(tbnez_n(0x12345678)) +print(tbnez_n(-1)) diff --git a/tests/inlineasm/xtensa/asmbranch.py.exp b/tests/inlineasm/xtensa/asmbranch.py.exp new file mode 100644 index 0000000000000..319a4b435ef2f --- /dev/null +++ b/tests/inlineasm/xtensa/asmbranch.py.exp @@ -0,0 +1,66 @@ +0 +-1 +-1 +0 +0 +0 +-1 +0 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +0 +-1 +0 +0 +-1 +-1 +0 +0 +-1 +0 +0 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +-1 +-1 +0 +-1 +-1 +-1 +0 +-1 +0 +0 +-1 +-1 +0 +-1 +-1 +0 +0 +-1 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +0 diff --git a/tests/inlineasm/xtensa/asmjump.py b/tests/inlineasm/xtensa/asmjump.py new file mode 100644 index 0000000000000..f41c9482319da --- /dev/null +++ b/tests/inlineasm/xtensa/asmjump.py @@ -0,0 +1,26 @@ +@micropython.asm_xtensa +def jump() -> int: + movi(a2, 0) + j(NEXT) + addi(a2, a2, 1) + j(DONE) + label(NEXT) + addi(a2, a2, 2) + label(DONE) + + +print(jump()) + + +@micropython.asm_xtensa +def jumpx() -> int: + call0(ENTRY) + label(ENTRY) + movi(a2, 0) + addi(a3, a0, 12) + jx(a3) + movi(a2, 1) + movi(a2, 2) + + +print(jumpx()) diff --git a/tests/inlineasm/xtensa/asmjump.py.exp b/tests/inlineasm/xtensa/asmjump.py.exp new file mode 100644 index 0000000000000..51993f072d583 --- /dev/null +++ b/tests/inlineasm/xtensa/asmjump.py.exp @@ -0,0 +1,2 @@ +2 +2 diff --git a/tests/inlineasm/xtensa/asmloadstore.py b/tests/inlineasm/xtensa/asmloadstore.py new file mode 100644 index 0000000000000..b185e30520cc9 --- /dev/null +++ b/tests/inlineasm/xtensa/asmloadstore.py @@ -0,0 +1,98 @@ +import array + +# On the 8266 the generated code gets put into the IRAM segment, which is only +# word-addressable. Therefore, to test byte and halfword load/store opcodes +# some memory must be reserved in the DRAM segment. + +BYTE_DATA = array.array("B", (0x11, 0x22, 0x33, 0x44)) +WORD_DATA = array.array("h", (100, 200, -100, -200)) +DWORD_DATA = array.array("i", (100_000, -200_000, 300_000, -400_000)) + + +@micropython.asm_xtensa +def tl32r() -> int: + nop() + j(CODE) + align(4) + label(DATA) + data(1, 1, 2, 3, 4, 5, 6, 7) + align(4) + label(CODE) + nop_n() + nop_n() + l32r(a2, DATA) + + +print(hex(tl32r())) + + +@micropython.asm_xtensa +def tl32i() -> uint: + call0(ENTRY) + label(ENTRY) + l32i(a2, a0, 0) + + +print(hex(tl32i())) + + +@micropython.asm_xtensa +def tl8ui(a2) -> uint: + mov(a3, a2) + l8ui(a2, a3, 1) + + +print(hex(tl8ui(BYTE_DATA))) + + +@micropython.asm_xtensa +def tl16ui(a2) -> uint: + mov(a3, a2) + l16ui(a2, a3, 2) + + +print(tl16ui(WORD_DATA)) + + +@micropython.asm_xtensa +def tl16si(a2) -> int: + mov(a3, a2) + l16si(a2, a3, 6) + + +print(tl16si(WORD_DATA)) + + +@micropython.asm_xtensa +def ts8i(a2, a3): + s8i(a3, a2, 1) + + +ts8i(BYTE_DATA, 0xFF) +print(BYTE_DATA) + + +@micropython.asm_xtensa +def ts16i(a2, a3): + s16i(a3, a2, 2) + + +ts16i(WORD_DATA, -123) +print(WORD_DATA) + + +@micropython.asm_xtensa +def ts32i(a2, a3) -> uint: + s32i(a3, a2, 4) + + +ts32i(DWORD_DATA, -123456) +print(DWORD_DATA) + + +@micropython.asm_xtensa +def tl32i_n(a2) -> uint: + l32i_n(a2, a2, 8) + + +print(tl32i_n(DWORD_DATA)) diff --git a/tests/inlineasm/xtensa/asmloadstore.py.exp b/tests/inlineasm/xtensa/asmloadstore.py.exp new file mode 100644 index 0000000000000..e6672df6f8132 --- /dev/null +++ b/tests/inlineasm/xtensa/asmloadstore.py.exp @@ -0,0 +1,9 @@ +0x4030201 +0xf8002022 +0x22 +200 +-200 +array('B', [17, 255, 51, 68]) +array('h', [100, -123, -100, -200]) +array('i', [100000, -123456, 300000, -400000]) +300000 diff --git a/tests/inlineasm/xtensa/asmmisc.py b/tests/inlineasm/xtensa/asmmisc.py new file mode 100644 index 0000000000000..271ab836625dc --- /dev/null +++ b/tests/inlineasm/xtensa/asmmisc.py @@ -0,0 +1,25 @@ +@micropython.asm_xtensa +def tnop(a2, a3, a4, a5): + nop() + + +out2 = tnop(0x100, 0x200, 0x300, 0x400) +print(out2 == 0x100) + + +@micropython.asm_xtensa +def tnop_n(a2, a3, a4, a5): + nop_n() + + +out2 = tnop_n(0x100, 0x200, 0x300, 0x400) +print(out2 == 0x100) + + +@micropython.asm_xtensa +def tmov_n(a2, a3): + mov_n(a4, a3) + add(a2, a4, a3) + + +print(tmov_n(0, 1)) diff --git a/tests/inlineasm/xtensa/asmmisc.py.exp b/tests/inlineasm/xtensa/asmmisc.py.exp new file mode 100644 index 0000000000000..eefaa35daf0f1 --- /dev/null +++ b/tests/inlineasm/xtensa/asmmisc.py.exp @@ -0,0 +1,3 @@ +True +True +2 diff --git a/tests/inlineasm/xtensa/asmshift.py b/tests/inlineasm/xtensa/asmshift.py new file mode 100644 index 0000000000000..271ca1ccd494c --- /dev/null +++ b/tests/inlineasm/xtensa/asmshift.py @@ -0,0 +1,137 @@ +@micropython.asm_xtensa +def lsl1(a2): + slli(a2, a2, 1) + + +print(hex(lsl1(0x123))) + + +@micropython.asm_xtensa +def lsl23(a2): + slli(a2, a2, 23) + + +print(hex(lsl23(1))) + + +@micropython.asm_xtensa +def lsr1(a2): + srli(a2, a2, 1) + + +print(hex(lsr1(0x123))) + + +@micropython.asm_xtensa +def lsr15(a2): + srli(a2, a2, 15) + + +print(hex(lsr15(0x80000000))) + + +@micropython.asm_xtensa +def asr1(a2): + srai(a2, a2, 1) + + +print(hex(asr1(0x123))) + + +@micropython.asm_xtensa +def asr31(a2): + srai(a2, a2, 31) + + +print(hex(asr31(0x80000000))) + + +@micropython.asm_xtensa +def lsl1r(a2): + movi(a3, 1) + ssl(a3) + sll(a2, a2) + + +print(hex(lsl1r(0x123))) + + +@micropython.asm_xtensa +def lsr1r(a2): + movi(a3, 1) + ssr(a3) + srl(a2, a2) + + +print(hex(lsr1r(0x123))) + + +@micropython.asm_xtensa +def asr1r(a2): + movi(a3, 1) + ssr(a3) + sra(a2, a2) + + +print(hex(asr1r(0x123))) + + +@micropython.asm_xtensa +def sll9(a2): + ssai(9) + sll(a2, a2) + + +print(hex(sll9(1))) + + +@micropython.asm_xtensa +def srlr(a2, a3): + ssa8l(a3) + srl(a2, a2) + + +print(hex(srlr(0x12340000, 2))) + + +@micropython.asm_xtensa +def sllr(a2, a3): + ssa8b(a3) + sll(a2, a2) + + +print(hex(sllr(0x1234, 2))) + + +@micropython.asm_xtensa +def srcr(a2, a3, a4): + ssr(a4) + src(a2, a2, a3) + + +print(hex(srcr(0x00000001, 0x80000000, 2))) + + +@micropython.asm_xtensa +def srai24(a2): + srai(a2, a2, 24) + + +print(hex(srai24(0x12345678))) + + +@micropython.asm_xtensa +def nsar(a2, a3): + nsa(a2, a3) + + +print(nsar(0x12345678, 0)) +print(nsar(0x12345678, -1)) + + +@micropython.asm_xtensa +def nsaur(a2, a3): + nsau(a2, a3) + + +print(nsaur(0x12345678, 0)) diff --git a/tests/inlineasm/xtensa/asmshift.py.exp b/tests/inlineasm/xtensa/asmshift.py.exp new file mode 100644 index 0000000000000..3e2bb3b4aefa9 --- /dev/null +++ b/tests/inlineasm/xtensa/asmshift.py.exp @@ -0,0 +1,17 @@ +0x246 +0x800000 +0x91 +0x10000 +0x91 +-0x1 +0x246 +0x91 +0x91 +0x800000 +0x1234 +0x12340000 +0x60000000 +0x12 +31 +31 +32 diff --git a/tests/internal_bench/class_create-0-empty.py b/tests/internal_bench/class_create-0-empty.py new file mode 100644 index 0000000000000..1fd8ccd925715 --- /dev/null +++ b/tests/internal_bench/class_create-0-empty.py @@ -0,0 +1,11 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-1-slots.py b/tests/internal_bench/class_create-1-slots.py new file mode 100644 index 0000000000000..9b3e4b9570da2 --- /dev/null +++ b/tests/internal_bench/class_create-1-slots.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + l = ["x"] + for i in range(num // 40): + + class X: + __slots__ = l + + +bench.run(test) diff --git a/tests/internal_bench/class_create-1.1-slots5.py b/tests/internal_bench/class_create-1.1-slots5.py new file mode 100644 index 0000000000000..ccac77dec9daa --- /dev/null +++ b/tests/internal_bench/class_create-1.1-slots5.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + l = ["a", "b", "c", "d", "x"] + for i in range(num // 40): + + class X: + __slots__ = l + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2-classattr.py b/tests/internal_bench/class_create-2-classattr.py new file mode 100644 index 0000000000000..049a7dab170c1 --- /dev/null +++ b/tests/internal_bench/class_create-2-classattr.py @@ -0,0 +1,11 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + x = 1 + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2.1-classattr5.py b/tests/internal_bench/class_create-2.1-classattr5.py new file mode 100644 index 0000000000000..5051e7dcca70d --- /dev/null +++ b/tests/internal_bench/class_create-2.1-classattr5.py @@ -0,0 +1,15 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + a = 0 + b = 0 + c = 0 + d = 0 + x = 1 + + +bench.run(test) diff --git a/tests/internal_bench/class_create-2.3-classattr5objs.py b/tests/internal_bench/class_create-2.3-classattr5objs.py new file mode 100644 index 0000000000000..74540865dcd14 --- /dev/null +++ b/tests/internal_bench/class_create-2.3-classattr5objs.py @@ -0,0 +1,20 @@ +import bench + + +class Class: + pass + + +def test(num): + instance = Class() + for i in range(num // 40): + + class X: + a = instance + b = instance + c = instance + d = instance + x = instance + + +bench.run(test) diff --git a/tests/internal_bench/class_create-3-instancemethod.py b/tests/internal_bench/class_create-3-instancemethod.py new file mode 100644 index 0000000000000..e8c201cb2c3c6 --- /dev/null +++ b/tests/internal_bench/class_create-3-instancemethod.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def x(self): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-4-classmethod.py b/tests/internal_bench/class_create-4-classmethod.py new file mode 100644 index 0000000000000..f34962bc67117 --- /dev/null +++ b/tests/internal_bench/class_create-4-classmethod.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @classmethod + def x(cls): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-4.1-classmethod_implicit.py b/tests/internal_bench/class_create-4.1-classmethod_implicit.py new file mode 100644 index 0000000000000..f2d1fcfd18821 --- /dev/null +++ b/tests/internal_bench/class_create-4.1-classmethod_implicit.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __new__(cls): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-5-staticmethod.py b/tests/internal_bench/class_create-5-staticmethod.py new file mode 100644 index 0000000000000..0633556667544 --- /dev/null +++ b/tests/internal_bench/class_create-5-staticmethod.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @staticmethod + def x(): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6-getattribute.py b/tests/internal_bench/class_create-6-getattribute.py new file mode 100644 index 0000000000000..10a4fe7ce8d9f --- /dev/null +++ b/tests/internal_bench/class_create-6-getattribute.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __getattribute__(self, name): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.1-getattr.py b/tests/internal_bench/class_create-6.1-getattr.py new file mode 100644 index 0000000000000..b4b9ba2f5525b --- /dev/null +++ b/tests/internal_bench/class_create-6.1-getattr.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + def __getattr__(self, name): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.2-property.py b/tests/internal_bench/class_create-6.2-property.py new file mode 100644 index 0000000000000..cf847b6dc9c9f --- /dev/null +++ b/tests/internal_bench/class_create-6.2-property.py @@ -0,0 +1,13 @@ +import bench + + +def test(num): + for i in range(num // 40): + + class X: + @property + def x(self): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-6.3-descriptor.py b/tests/internal_bench/class_create-6.3-descriptor.py new file mode 100644 index 0000000000000..7b0a635726380 --- /dev/null +++ b/tests/internal_bench/class_create-6.3-descriptor.py @@ -0,0 +1,17 @@ +import bench + + +class D: + def __get__(self, instance, owner=None): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_create-7-inherit.py b/tests/internal_bench/class_create-7-inherit.py new file mode 100644 index 0000000000000..f48fb215e0ab8 --- /dev/null +++ b/tests/internal_bench/class_create-7-inherit.py @@ -0,0 +1,14 @@ +import bench + + +def test(num): + class B: + pass + + for i in range(num // 40): + + class X(B): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-7.1-inherit_initsubclass.py b/tests/internal_bench/class_create-7.1-inherit_initsubclass.py new file mode 100644 index 0000000000000..0660fa86258fe --- /dev/null +++ b/tests/internal_bench/class_create-7.1-inherit_initsubclass.py @@ -0,0 +1,16 @@ +import bench + + +def test(num): + class B: + @classmethod + def __init_subclass__(cls): + pass + + for i in range(num // 40): + + class X(B): + pass + + +bench.run(test) diff --git a/tests/internal_bench/class_create-8-metaclass_setname.py b/tests/internal_bench/class_create-8-metaclass_setname.py new file mode 100644 index 0000000000000..e4515b54279d1 --- /dev/null +++ b/tests/internal_bench/class_create-8-metaclass_setname.py @@ -0,0 +1,17 @@ +import bench + + +class D: + def __set_name__(self, owner, name): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_create-8.1-metaclass_setname5.py b/tests/internal_bench/class_create-8.1-metaclass_setname5.py new file mode 100644 index 0000000000000..5daa3f8471bca --- /dev/null +++ b/tests/internal_bench/class_create-8.1-metaclass_setname5.py @@ -0,0 +1,21 @@ +import bench + + +class D: + def __set_name__(self, owner, name): + pass + + +def test(num): + descriptor = D() + for i in range(num // 40): + + class X: + a = descriptor + b = descriptor + c = descriptor + d = descriptor + x = descriptor + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-0-object.py b/tests/internal_bench/class_instance-0-object.py new file mode 100644 index 0000000000000..401c8ea7e3cc2 --- /dev/null +++ b/tests/internal_bench/class_instance-0-object.py @@ -0,0 +1,11 @@ +import bench + +X = object + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-0.1-object-gc.py b/tests/internal_bench/class_instance-0.1-object-gc.py new file mode 100644 index 0000000000000..7c475963a8e81 --- /dev/null +++ b/tests/internal_bench/class_instance-0.1-object-gc.py @@ -0,0 +1,13 @@ +import bench +import gc + +X = object + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1-empty.py b/tests/internal_bench/class_instance-1-empty.py new file mode 100644 index 0000000000000..617d47a86e92b --- /dev/null +++ b/tests/internal_bench/class_instance-1-empty.py @@ -0,0 +1,13 @@ +import bench + + +class X: + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.1-classattr.py b/tests/internal_bench/class_instance-1.1-classattr.py new file mode 100644 index 0000000000000..4e667533d4aa1 --- /dev/null +++ b/tests/internal_bench/class_instance-1.1-classattr.py @@ -0,0 +1,13 @@ +import bench + + +class X: + x = 0 + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.2-func.py b/tests/internal_bench/class_instance-1.2-func.py new file mode 100644 index 0000000000000..21bf7a1ac48fc --- /dev/null +++ b/tests/internal_bench/class_instance-1.2-func.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def f(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-1.3-empty-gc.py b/tests/internal_bench/class_instance-1.3-empty-gc.py new file mode 100644 index 0000000000000..a5108ef8e8156 --- /dev/null +++ b/tests/internal_bench/class_instance-1.3-empty-gc.py @@ -0,0 +1,15 @@ +import bench +import gc + + +class X: + pass + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2-init.py b/tests/internal_bench/class_instance-2-init.py new file mode 100644 index 0000000000000..86619d3154840 --- /dev/null +++ b/tests/internal_bench/class_instance-2-init.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __init__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2.1-init_super.py b/tests/internal_bench/class_instance-2.1-init_super.py new file mode 100644 index 0000000000000..38bca5fef877a --- /dev/null +++ b/tests/internal_bench/class_instance-2.1-init_super.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __init__(self): + return super().__init__() + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-2.2-new.py b/tests/internal_bench/class_instance-2.2-new.py new file mode 100644 index 0000000000000..dc5e78ea5ef98 --- /dev/null +++ b/tests/internal_bench/class_instance-2.2-new.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __new__(cls): + return super().__new__(cls) + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-3-del.py b/tests/internal_bench/class_instance-3-del.py new file mode 100644 index 0000000000000..af700f72a94a8 --- /dev/null +++ b/tests/internal_bench/class_instance-3-del.py @@ -0,0 +1,14 @@ +import bench + + +class X: + def __del__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-3.1-del-gc.py b/tests/internal_bench/class_instance-3.1-del-gc.py new file mode 100644 index 0000000000000..311c71c3571b0 --- /dev/null +++ b/tests/internal_bench/class_instance-3.1-del-gc.py @@ -0,0 +1,16 @@ +import bench +import gc + + +class X: + def __del__(self): + pass + + +def test(num): + for i in range(num // 5): + x = X() + gc.collect() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-4-slots.py b/tests/internal_bench/class_instance-4-slots.py new file mode 100644 index 0000000000000..51b067fedf0b7 --- /dev/null +++ b/tests/internal_bench/class_instance-4-slots.py @@ -0,0 +1,13 @@ +import bench + + +class X: + __slots__ = ["x"] + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/class_instance-4.1-slots5.py b/tests/internal_bench/class_instance-4.1-slots5.py new file mode 100644 index 0000000000000..8f5c2ecb456d8 --- /dev/null +++ b/tests/internal_bench/class_instance-4.1-slots5.py @@ -0,0 +1,13 @@ +import bench + + +class X: + __slots__ = ["a", "b", "c", "d", "x"] + + +def test(num): + for i in range(num // 5): + x = X() + + +bench.run(test) diff --git a/tests/internal_bench/var-6.2-instance-speciallookup.py b/tests/internal_bench/var-6.2-instance-speciallookup.py new file mode 100644 index 0000000000000..fee12b2f930c3 --- /dev/null +++ b/tests/internal_bench/var-6.2-instance-speciallookup.py @@ -0,0 +1,19 @@ +import bench + + +class Foo: + def __init__(self): + self.num = 20000000 + + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.3-instance-property.py b/tests/internal_bench/var-6.3-instance-property.py new file mode 100644 index 0000000000000..b4426ef7928e1 --- /dev/null +++ b/tests/internal_bench/var-6.3-instance-property.py @@ -0,0 +1,17 @@ +import bench + + +class Foo: + @property + def num(self): + return 20000000 + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.4-instance-descriptor.py b/tests/internal_bench/var-6.4-instance-descriptor.py new file mode 100644 index 0000000000000..b4df69f878f10 --- /dev/null +++ b/tests/internal_bench/var-6.4-instance-descriptor.py @@ -0,0 +1,20 @@ +import bench + + +class Descriptor: + def __get__(self, instance, owner=None): + return 20000000 + + +class Foo: + num = Descriptor() + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.5-instance-getattr.py b/tests/internal_bench/var-6.5-instance-getattr.py new file mode 100644 index 0000000000000..3b2ef6721105f --- /dev/null +++ b/tests/internal_bench/var-6.5-instance-getattr.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + def __getattr__(self, name): + return 20000000 + + +def test(num): + o = Foo() + i = 0 + while i < o.num: + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-6.6-instance-builtin_ordered.py b/tests/internal_bench/var-6.6-instance-builtin_ordered.py new file mode 100644 index 0000000000000..02d7525230192 --- /dev/null +++ b/tests/internal_bench/var-6.6-instance-builtin_ordered.py @@ -0,0 +1,12 @@ +import bench + + +def test(num): + i = 0 + o = set() # object with largest rom-frozen ordered locals_dict + n = "__contains__" # last element in that dict for longest lookup + while i < num: + i += hasattr(o, n) # True, converts to 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9-getattr.py b/tests/internal_bench/var-9-getattr.py new file mode 100644 index 0000000000000..69d2bfed2e0ac --- /dev/null +++ b/tests/internal_bench/var-9-getattr.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + o.num = num + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.1-getattr_default.py b/tests/internal_bench/var-9.1-getattr_default.py new file mode 100644 index 0000000000000..e803d39b32667 --- /dev/null +++ b/tests/internal_bench/var-9.1-getattr_default.py @@ -0,0 +1,15 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.2-getattr_default_special.py b/tests/internal_bench/var-9.2-getattr_default_special.py new file mode 100644 index 0000000000000..c48ec0742cff6 --- /dev/null +++ b/tests/internal_bench/var-9.2-getattr_default_special.py @@ -0,0 +1,16 @@ +import bench + + +class Foo: + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + i = 0 + while i < getattr(o, "num", num): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.3-except_ok.py b/tests/internal_bench/var-9.3-except_ok.py new file mode 100644 index 0000000000000..efc1a8f858cd0 --- /dev/null +++ b/tests/internal_bench/var-9.3-except_ok.py @@ -0,0 +1,23 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + o.num = num + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.4-except_selfinduced.py b/tests/internal_bench/var-9.4-except_selfinduced.py new file mode 100644 index 0000000000000..544609ca4b6b3 --- /dev/null +++ b/tests/internal_bench/var-9.4-except_selfinduced.py @@ -0,0 +1,22 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + + def get(): + try: + raise AttributeError + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.5-except_error.py b/tests/internal_bench/var-9.5-except_error.py new file mode 100644 index 0000000000000..caf83fa46ab3d --- /dev/null +++ b/tests/internal_bench/var-9.5-except_error.py @@ -0,0 +1,22 @@ +import bench + + +class Foo: + pass + + +def test(num): + o = Foo() + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/internal_bench/var-9.6-except_error_special.py b/tests/internal_bench/var-9.6-except_error_special.py new file mode 100644 index 0000000000000..8bc395b4d7ef8 --- /dev/null +++ b/tests/internal_bench/var-9.6-except_error_special.py @@ -0,0 +1,23 @@ +import bench + + +class Foo: + def __delattr__(self, name): # just trigger the 'special lookups' flag on the class + pass + + +def test(num): + o = Foo() + + def get(): + try: + return o.num + except AttributeError: + return num + + i = 0 + while i < get(): + i += 1 + + +bench.run(test) diff --git a/tests/io/builtin_print_file.py b/tests/io/builtin_print_file.py index 822356a6cc305..e00f58635a9d2 100644 --- a/tests/io/builtin_print_file.py +++ b/tests/io/builtin_print_file.py @@ -13,5 +13,5 @@ try: print(file=1) -except (AttributeError, OSError): # CPython and uPy differ in error message +except (AttributeError, OSError): # CPython and MicroPython differ in error message print("Error") diff --git a/tests/io/data/bigfile1 b/tests/io/data/bigfile1 index 5afbf01a6f4e5..777c436a21f2f 100644 --- a/tests/io/data/bigfile1 +++ b/tests/io/data/bigfile1 @@ -1,147 +1,147 @@ { "info": { - "maintainer": null, - "docs_url": "", - "requires_python": null, - "maintainer_email": null, - "cheesecake_code_kwalitee_id": null, - "keywords": null, - "package_url": "http://pypi.python.org/pypi/micropython-uasyncio", - "author": "MicroPython Developers", - "author_email": "micro-python@googlegroups.com", - "download_url": "UNKNOWN", - "platform": "UNKNOWN", - "version": "0.8.1", - "cheesecake_documentation_id": null, - "_pypi_hidden": false, - "description": "Lightweight asyncio-like library built around native Python coroutines, not around un-Python devices like callback mess.", - "release_url": "http://pypi.python.org/pypi/micropython-uasyncio/0.8.1", + "maintainer": null, + "docs_url": "", + "requires_python": null, + "maintainer_email": null, + "cheesecake_code_kwalitee_id": null, + "keywords": null, + "package_url": "http://pypi.python.org/pypi/micropython-uasyncio", + "author": "MicroPython Developers", + "author_email": "micro-python@googlegroups.com", + "download_url": "UNKNOWN", + "platform": "UNKNOWN", + "version": "0.8.1", + "cheesecake_documentation_id": null, + "_pypi_hidden": false, + "description": "Lightweight asyncio-like library built around native Python coroutines, not around un-Python devices like callback mess.", + "release_url": "http://pypi.python.org/pypi/micropython-uasyncio/0.8.1", "downloads": { - "last_month": 942, - "last_week": 173, + "last_month": 942, + "last_week": 173, "last_day": 29 - }, - "_pypi_ordering": 6, - "classifiers": [], - "name": "micropython-uasyncio", - "bugtrack_url": null, - "license": "MIT", - "summary": "uasyncio module for MicroPython", - "home_page": "https://github.com/micropython/micropython/issues/405", - "stable_version": null, + }, + "_pypi_ordering": 6, + "classifiers": [], + "name": "micropython-uasyncio", + "bugtrack_url": null, + "license": "MIT", + "summary": "uasyncio module for MicroPython", + "home_page": "https://github.com/micropython/micropython/issues/405", + "stable_version": null, "cheesecake_installability_id": null - }, + }, "releases": { "0.8": [ { - "has_sig": false, - "upload_time": "2015-01-01T23:52:41", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.tar.gz", - "md5_digest": "5df4d0d6b5fdb7c05fc418e5785e1336", - "downloads": 352, - "filename": "micropython-uasyncio-0.8.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2015-01-01T23:52:41", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.tar.gz", + "md5_digest": "5df4d0d6b5fdb7c05fc418e5785e1336", + "downloads": 352, + "filename": "micropython-uasyncio-0.8.tar.gz", + "packagetype": "sdist", "size": 2476 } - ], + ], "0.6.2": [ { - "has_sig": false, - "upload_time": "2014-10-18T11:26:52", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.2.tar.gz", - "md5_digest": "c85fa7c11ef437f4e73c1fcd639db066", - "downloads": 475, - "filename": "micropython-uasyncio-0.6.2.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2014-10-18T11:26:52", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.2.tar.gz", + "md5_digest": "c85fa7c11ef437f4e73c1fcd639db066", + "downloads": 475, + "filename": "micropython-uasyncio-0.6.2.tar.gz", + "packagetype": "sdist", "size": 3262 } - ], + ], "0.6.1": [ { - "has_sig": false, - "upload_time": "2014-10-11T02:21:17", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.1.tar.gz", - "md5_digest": "48cb0db7d8249d5f4a86db9c4b302d03", - "downloads": 507, - "filename": "micropython-uasyncio-0.6.1.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2014-10-11T02:21:17", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.1.tar.gz", + "md5_digest": "48cb0db7d8249d5f4a86db9c4b302d03", + "downloads": 507, + "filename": "micropython-uasyncio-0.6.1.tar.gz", + "packagetype": "sdist", "size": 3237 } - ], + ], "0.8.1": [ { - "has_sig": false, - "upload_time": "2015-01-04T20:02:03", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", - "md5_digest": "940d2647b8355289d54de543ff710b05", - "downloads": 249, - "filename": "micropython-uasyncio-0.8.1.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2015-01-04T20:02:03", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", + "md5_digest": "940d2647b8355289d54de543ff710b05", + "downloads": 249, + "filename": "micropython-uasyncio-0.8.1.tar.gz", + "packagetype": "sdist", "size": 2484 } - ], + ], "0.7": [ { - "has_sig": false, - "upload_time": "2014-10-23T22:02:11", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.tar.gz", - "md5_digest": "81250a0ee6649b5117878d5788ba96d3", - "downloads": 457, - "filename": "micropython-uasyncio-0.7.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2014-10-23T22:02:11", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.tar.gz", + "md5_digest": "81250a0ee6649b5117878d5788ba96d3", + "downloads": 457, + "filename": "micropython-uasyncio-0.7.tar.gz", + "packagetype": "sdist", "size": 2277 } - ], + ], "0.7.1": [ { - "has_sig": false, - "upload_time": "2014-11-04T00:56:16", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.1.tar.gz", - "md5_digest": "21eda0501142830730cd82e1b0fa1a33", - "downloads": 412, - "filename": "micropython-uasyncio-0.7.1.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2014-11-04T00:56:16", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.7.1.tar.gz", + "md5_digest": "21eda0501142830730cd82e1b0fa1a33", + "downloads": 412, + "filename": "micropython-uasyncio-0.7.1.tar.gz", + "packagetype": "sdist", "size": 2474 } - ], + ], "0.6": [ { - "has_sig": false, - "upload_time": "2014-08-27T00:17:45", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.tar.gz", - "md5_digest": "9d0b15108c5ade3a6902c9370c9dacf1", - "downloads": 668, - "filename": "micropython-uasyncio-0.6.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2014-08-27T00:17:45", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.6.tar.gz", + "md5_digest": "9d0b15108c5ade3a6902c9370c9dacf1", + "downloads": 668, + "filename": "micropython-uasyncio-0.6.tar.gz", + "packagetype": "sdist", "size": 3246 } ] - }, + }, "urls": [ { - "has_sig": false, - "upload_time": "2015-01-04T20:02:03", - "comment_text": "", - "python_version": "source", - "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", - "md5_digest": "940d2647b8355289d54de543ff710b05", - "downloads": 249, - "filename": "micropython-uasyncio-0.8.1.tar.gz", - "packagetype": "sdist", + "has_sig": false, + "upload_time": "2015-01-04T20:02:03", + "comment_text": "", + "python_version": "source", + "url": "https://pypi.python.org/packages/source/m/micropython-uasyncio/micropython-uasyncio-0.8.1.tar.gz", + "md5_digest": "940d2647b8355289d54de543ff710b05", + "downloads": 249, + "filename": "micropython-uasyncio-0.8.1.tar.gz", + "packagetype": "sdist", "size": 2484 } ] diff --git a/tests/io/file_seek.py b/tests/io/file_seek.py index 3990df8409051..b9f9593786fe6 100644 --- a/tests/io/file_seek.py +++ b/tests/io/file_seek.py @@ -30,5 +30,5 @@ try: f.seek(1) except (OSError, ValueError): - # CPy raises ValueError, uPy raises OSError + # CPy raises ValueError, MPy raises OSError print("OSError or ValueError") diff --git a/tests/micropython/builtin_execfile.py b/tests/micropython/builtin_execfile.py index 9b6d6a0aa00bc..4fd4d66d4ee25 100644 --- a/tests/micropython/builtin_execfile.py +++ b/tests/micropython/builtin_execfile.py @@ -1,11 +1,10 @@ # Test builtin execfile function using VFS. try: - import io, os + import io, os, vfs execfile io.IOBase - os.mount except (ImportError, NameError, AttributeError): print("SKIP") raise SystemExit @@ -17,7 +16,9 @@ def __init__(self, data): self.off = 0 def ioctl(self, request, arg): - return 0 + if request == 4: # MP_STREAM_CLOSE + return 0 + return -1 def readinto(self, buf): buf[:] = memoryview(self.data)[self.off : self.off + len(buf)] @@ -44,25 +45,21 @@ def open(self, file, mode): # First umount any existing mount points the target may have. try: - import io, os - - os.umount("/") + vfs.umount("/") except OSError: pass for path in os.listdir("/"): - os.umount("/" + path) + vfs.umount("/" + path) # Create and mount the VFS object. files = { "/test.py": "print(123)", } fs = Filesystem(files) -os.mount(fs, "/test_mnt") +vfs.mount(fs, "/test_mnt") # Test execfile with a file that doesn't exist. try: - import io, os - execfile("/test_mnt/noexist.py") except OSError: print("OSError") @@ -77,4 +74,25 @@ def open(self, file, mode): print("TypeError") # Unmount the VFS object. -os.umount(fs) +vfs.umount(fs) + + +class EvilFilesystem: + def mount(self, readonly, mkfs): + print("mount", readonly, mkfs) + + def umount(self): + print("umount") + + def open(self, file, mode): + return None + + +fs = EvilFilesystem() +vfs.mount(fs, "/test_mnt") +try: + execfile("/test_mnt/test.py") + print("ExecFile succeeded") +except OSError: + print("OSError") +vfs.umount(fs) diff --git a/tests/micropython/builtin_execfile.py.exp b/tests/micropython/builtin_execfile.py.exp index 49703d570763d..d93dee547b6ea 100644 --- a/tests/micropython/builtin_execfile.py.exp +++ b/tests/micropython/builtin_execfile.py.exp @@ -5,3 +5,6 @@ open /test.py rb 123 TypeError umount +mount False False +OSError +umount diff --git a/tests/micropython/const_error.py b/tests/micropython/const_error.py index d35be530a7c8d..950360e4dc782 100644 --- a/tests/micropython/const_error.py +++ b/tests/micropython/const_error.py @@ -18,8 +18,6 @@ def test_syntax(code): # these operations are not supported within const test_syntax("A = const(1 @ 2)") -test_syntax("A = const(1 / 2)") -test_syntax("A = const(1 ** -2)") test_syntax("A = const(1 << -2)") test_syntax("A = const(1 >> -2)") test_syntax("A = const(1 % 0)") diff --git a/tests/micropython/const_error.py.exp b/tests/micropython/const_error.py.exp index 3edc3efe9c3e9..bef69eb32ea7d 100644 --- a/tests/micropython/const_error.py.exp +++ b/tests/micropython/const_error.py.exp @@ -5,5 +5,3 @@ SyntaxError SyntaxError SyntaxError SyntaxError -SyntaxError -SyntaxError diff --git a/tests/micropython/const_float.py b/tests/micropython/const_float.py new file mode 100644 index 0000000000000..c3a0df0276bf8 --- /dev/null +++ b/tests/micropython/const_float.py @@ -0,0 +1,23 @@ +# test constant optimisation, with consts that are floats + +from micropython import const + +# check we can make consts from floats +F1 = const(2.5) +F2 = const(-0.3) +print(type(F1), F1) +print(type(F2), F2) + +# check arithmetic with floats +F3 = const(F1 + F2) +F4 = const(F1**2) +print(F3, F4) + +# check int operations with float results +F5 = const(1 / 2) +F6 = const(2**-2) +print(F5, F6) + +# note: we also test float expression folding when +# we're compiling test cases in tests/float, as +# many expressions are resolved at compile time. diff --git a/tests/micropython/const_float.py.exp b/tests/micropython/const_float.py.exp new file mode 100644 index 0000000000000..17a86a6d936c2 --- /dev/null +++ b/tests/micropython/const_float.py.exp @@ -0,0 +1,4 @@ + 2.5 + -0.3 +2.2 6.25 +0.5 0.25 diff --git a/tests/micropython/const_math.py b/tests/micropython/const_math.py new file mode 100644 index 0000000000000..7ee5edc6d3240 --- /dev/null +++ b/tests/micropython/const_math.py @@ -0,0 +1,18 @@ +# Test expressions based on math module constants +try: + import math +except ImportError: + print("SKIP") + raise SystemExit + +from micropython import const + +# check that we can make consts from math constants +# (skip if the target has MICROPY_COMP_MODULE_CONST disabled) +try: + exec("two_pi = const(2.0 * math.pi)") +except SyntaxError: + print("SKIP") + raise SystemExit + +print(math.cos(two_pi)) diff --git a/tests/micropython/const_math.py.exp b/tests/micropython/const_math.py.exp new file mode 100644 index 0000000000000..d3827e75a5cad --- /dev/null +++ b/tests/micropython/const_math.py.exp @@ -0,0 +1 @@ +1.0 diff --git a/tests/micropython/decorator_error.py b/tests/micropython/decorator_error.py index 94772ac1e5fef..b5eae65b29209 100644 --- a/tests/micropython/decorator_error.py +++ b/tests/micropython/decorator_error.py @@ -1,4 +1,4 @@ -# test syntax errors for uPy-specific decorators +# test syntax errors for MicroPython-specific decorators def test_syntax(code): diff --git a/tests/micropython/emg_exc.py b/tests/micropython/emg_exc.py index a74757d028ff2..cf918b3dc8ac5 100644 --- a/tests/micropython/emg_exc.py +++ b/tests/micropython/emg_exc.py @@ -1,10 +1,9 @@ # test that emergency exceptions work -import micropython import sys try: - import io + import io, micropython except ImportError: print("SKIP") raise SystemExit diff --git a/tests/micropython/emg_exc.py.native.exp b/tests/micropython/emg_exc.py.native.exp new file mode 100644 index 0000000000000..879fa7ef5b943 --- /dev/null +++ b/tests/micropython/emg_exc.py.native.exp @@ -0,0 +1 @@ +ValueError(1,) diff --git a/tests/micropython/extreme_exc.py b/tests/micropython/extreme_exc.py index ad819e408fd82..17323b566d3b5 100644 --- a/tests/micropython/extreme_exc.py +++ b/tests/micropython/extreme_exc.py @@ -1,6 +1,10 @@ # test some extreme cases of allocating exceptions and tracebacks -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on the heap. diff --git a/tests/micropython/heap_lock.py b/tests/micropython/heap_lock.py index f2892a6dc581e..209a3143461a5 100644 --- a/tests/micropython/heap_lock.py +++ b/tests/micropython/heap_lock.py @@ -1,6 +1,10 @@ # check that heap_lock/heap_unlock work as expected -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit l = [] l2 = list(range(100)) diff --git a/tests/micropython/heap_locked.py b/tests/micropython/heap_locked.py index d9e5b5d4090af..d9d99493dd6b7 100644 --- a/tests/micropython/heap_locked.py +++ b/tests/micropython/heap_locked.py @@ -1,8 +1,10 @@ # test micropython.heap_locked() -import micropython +try: + import micropython -if not hasattr(micropython, "heap_locked"): + micropython.heap_locked +except (AttributeError, ImportError): print("SKIP") raise SystemExit diff --git a/tests/micropython/heapalloc.py b/tests/micropython/heapalloc.py index e19f8d0255deb..010bf878a07b0 100644 --- a/tests/micropython/heapalloc.py +++ b/tests/micropython/heapalloc.py @@ -1,6 +1,10 @@ # check that we can do certain things without allocating heap memory -import micropython +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on heap. diff --git a/tests/micropython/heapalloc_exc_compressed.py b/tests/micropython/heapalloc_exc_compressed.py index cddc0f7b4095d..96fe3ca4f7e00 100644 --- a/tests/micropython/heapalloc_exc_compressed.py +++ b/tests/micropython/heapalloc_exc_compressed.py @@ -1,10 +1,16 @@ -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Tests both code paths for built-in exception raising. # mp_obj_new_exception_msg_varg (exception requires decompression at raise-time to format) # mp_obj_new_exception_msg (decompression can be deferred) -# NameError uses mp_obj_new_exception_msg_varg for NameError("name '%q' is not defined") +# NameError uses mp_obj_new_exception_msg_varg for NameError("name '%q' isn't defined") # `raise 0` uses mp_obj_new_exception_msg for TypeError("exceptions must derive from BaseException") # Tests that deferred decompression works both via print(e) and accessing the message directly via e.args. diff --git a/tests/micropython/heapalloc_exc_compressed.py.exp b/tests/micropython/heapalloc_exc_compressed.py.exp index c2690353b07f2..c3e6e5dd9f749 100644 --- a/tests/micropython/heapalloc_exc_compressed.py.exp +++ b/tests/micropython/heapalloc_exc_compressed.py.exp @@ -1,6 +1,6 @@ -NameError name 'name' is not defined +NameError name 'name' isn't defined TypeError exceptions must derive from BaseException -name 'name' is not defined +name 'name' isn't defined exceptions must derive from BaseException NameError TypeError diff --git a/tests/micropython/heapalloc_exc_compressed_emg_exc.py b/tests/micropython/heapalloc_exc_compressed_emg_exc.py index 48ce9dd69e6e2..31d937b8f9345 100644 --- a/tests/micropython/heapalloc_exc_compressed_emg_exc.py +++ b/tests/micropython/heapalloc_exc_compressed_emg_exc.py @@ -1,4 +1,10 @@ -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Does the full test from heapalloc_exc_compressed.py but while the heap is # locked (this can only work when the emergency exception buf is enabled). diff --git a/tests/micropython/heapalloc_exc_compressed_emg_exc.py.exp b/tests/micropython/heapalloc_exc_compressed_emg_exc.py.exp index c3974250d4e26..1fc81093392a2 100644 --- a/tests/micropython/heapalloc_exc_compressed_emg_exc.py.exp +++ b/tests/micropython/heapalloc_exc_compressed_emg_exc.py.exp @@ -1,4 +1,4 @@ -NameError name 'name' is not defined +NameError name 'name' isn't defined TypeError exceptions must derive from BaseException -name 'name' is not defined +name 'name' isn't defined exceptions must derive from BaseException diff --git a/tests/micropython/heapalloc_exc_raise.py b/tests/micropython/heapalloc_exc_raise.py index 99810e0075064..917ccf42f1e16 100644 --- a/tests/micropython/heapalloc_exc_raise.py +++ b/tests/micropython/heapalloc_exc_raise.py @@ -1,6 +1,12 @@ # Test that we can raise and catch (preallocated) exception # without memory allocation. -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit e = ValueError("error") diff --git a/tests/micropython/heapalloc_fail_bytearray.py b/tests/micropython/heapalloc_fail_bytearray.py index 1bf7ddd600b93..9ee73d1c583f2 100644 --- a/tests/micropython/heapalloc_fail_bytearray.py +++ b/tests/micropython/heapalloc_fail_bytearray.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with bytearray -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_dict.py b/tests/micropython/heapalloc_fail_dict.py index ce2d158bd09c6..04c79183578ff 100644 --- a/tests/micropython/heapalloc_fail_dict.py +++ b/tests/micropython/heapalloc_fail_dict.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with dict -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create dict x = 1 diff --git a/tests/micropython/heapalloc_fail_list.py b/tests/micropython/heapalloc_fail_list.py index 9a2e9a555f3e2..7afb6dc1019b3 100644 --- a/tests/micropython/heapalloc_fail_list.py +++ b/tests/micropython/heapalloc_fail_list.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with list -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_memoryview.py b/tests/micropython/heapalloc_fail_memoryview.py index da2d1abffa634..17e3e1262472c 100644 --- a/tests/micropython/heapalloc_fail_memoryview.py +++ b/tests/micropython/heapalloc_fail_memoryview.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with memoryview -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class GetSlice: diff --git a/tests/micropython/heapalloc_fail_set.py b/tests/micropython/heapalloc_fail_set.py index 3c347660ad763..0c4d85eef62a8 100644 --- a/tests/micropython/heapalloc_fail_set.py +++ b/tests/micropython/heapalloc_fail_set.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with set -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create set x = 1 diff --git a/tests/micropython/heapalloc_fail_tuple.py b/tests/micropython/heapalloc_fail_tuple.py index de79385e3e3cb..11718a8107b3a 100644 --- a/tests/micropython/heapalloc_fail_tuple.py +++ b/tests/micropython/heapalloc_fail_tuple.py @@ -1,6 +1,12 @@ # test handling of failed heap allocation with tuple -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # create tuple x = 1 diff --git a/tests/micropython/heapalloc_inst_call.py b/tests/micropython/heapalloc_inst_call.py index 14d8826bf06ce..f78aa3cf87798 100644 --- a/tests/micropython/heapalloc_inst_call.py +++ b/tests/micropython/heapalloc_inst_call.py @@ -1,6 +1,13 @@ # Test that calling clazz.__call__() with up to at least 3 arguments # doesn't require heap allocation. -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit class Foo0: diff --git a/tests/micropython/heapalloc_int_from_bytes.py b/tests/micropython/heapalloc_int_from_bytes.py index 5fe50443ae335..3310ea95d1472 100644 --- a/tests/micropython/heapalloc_int_from_bytes.py +++ b/tests/micropython/heapalloc_int_from_bytes.py @@ -1,6 +1,13 @@ # Test that int.from_bytes() for small number of bytes generates # small int. -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit micropython.heap_lock() print(int.from_bytes(b"1", "little")) diff --git a/tests/micropython/heapalloc_slice.py b/tests/micropython/heapalloc_slice.py new file mode 100644 index 0000000000000..62d96595c719e --- /dev/null +++ b/tests/micropython/heapalloc_slice.py @@ -0,0 +1,18 @@ +# slice operations that don't require allocation +try: + from micropython import heap_lock, heap_unlock +except (ImportError, AttributeError): + heap_lock = heap_unlock = lambda: 0 + +b = bytearray(range(10)) + +m = memoryview(b) + +heap_lock() + +b[3:5] = b"aa" +m[5:7] = b"bb" + +heap_unlock() + +print(b) diff --git a/tests/micropython/heapalloc_str.py b/tests/micropython/heapalloc_str.py index 39aa56ccd7834..6372df5d37b13 100644 --- a/tests/micropython/heapalloc_str.py +++ b/tests/micropython/heapalloc_str.py @@ -1,5 +1,12 @@ # String operations which don't require allocation -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit micropython.heap_lock() diff --git a/tests/micropython/heapalloc_super.py b/tests/micropython/heapalloc_super.py index 51afae3d83d06..6839eee330acd 100644 --- a/tests/micropython/heapalloc_super.py +++ b/tests/micropython/heapalloc_super.py @@ -1,5 +1,12 @@ # test super() operations which don't require allocation -import micropython + +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Check for stackless build, which can't call functions without # allocating a frame on heap. diff --git a/tests/micropython/heapalloc_traceback.py.native.exp b/tests/micropython/heapalloc_traceback.py.native.exp new file mode 100644 index 0000000000000..d6ac26aa829e1 --- /dev/null +++ b/tests/micropython/heapalloc_traceback.py.native.exp @@ -0,0 +1,3 @@ +StopIteration +StopIteration: + diff --git a/tests/micropython/heapalloc_yield_from.py b/tests/micropython/heapalloc_yield_from.py index 950717189087d..9d4f8c6940f16 100644 --- a/tests/micropython/heapalloc_yield_from.py +++ b/tests/micropython/heapalloc_yield_from.py @@ -1,6 +1,12 @@ # Check that yield-from can work without heap allocation -import micropython +try: + import micropython + + micropython.heap_lock +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit # Yielding from a function generator diff --git a/tests/micropython/import_mpy_invalid.py b/tests/micropython/import_mpy_invalid.py index d4077a31f33eb..8c11b39c0760b 100644 --- a/tests/micropython/import_mpy_invalid.py +++ b/tests/micropython/import_mpy_invalid.py @@ -1,10 +1,10 @@ # test importing of invalid .mpy files try: - import sys, io, os + import sys, io, vfs + sys.implementation._mpy io.IOBase - os.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -26,7 +26,9 @@ def readinto(self, buf): return n def ioctl(self, req, arg): - return 0 + if req == 4: # MP_STREAM_CLOSE + return 0 + return -1 class UserFS: @@ -57,7 +59,7 @@ def open(self, path, mode): } # create and mount a user filesystem -os.mount(UserFS(user_files), "/userfs") +vfs.mount(UserFS(user_files), "/userfs") sys.path.append("/userfs") # import .mpy files from the user filesystem @@ -70,5 +72,5 @@ def open(self, path, mode): print(mod, type(e).__name__, e) # unmount and undo path addition -os.umount("/userfs") +vfs.umount("/userfs") sys.path.pop() diff --git a/tests/micropython/import_mpy_native.py b/tests/micropython/import_mpy_native.py index 4efb1e18a32c7..59181b203bba9 100644 --- a/tests/micropython/import_mpy_native.py +++ b/tests/micropython/import_mpy_native.py @@ -1,11 +1,10 @@ # test importing of .mpy files with native code try: - import sys, io, os + import sys, io, vfs sys.implementation._mpy io.IOBase - os.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -29,7 +28,9 @@ def readinto(self, buf): return n def ioctl(self, req, arg): - return 0 + if req == 4: # MP_STREAM_CLOSE + return 0 + return -1 class UserFS: @@ -53,12 +54,13 @@ def open(self, path, mode): # these are the test .mpy files # CIRCUITPY-CHANGE -valid_header = bytes([ord("C"), 6, mpy_arch, 31]) +small_int_bits = 31 +valid_header = bytes([77, 6, (mpy_arch & 0x3F), small_int_bits]) # fmt: off user_files = { # bad architecture (mpy_arch needed for sub-version) # CIRCUITPY-CHANGE - '/mod0.mpy': bytes([ord('C'), 6, 0xfc | mpy_arch, 31]), + '/mod0.mpy': bytes([ord('C'), 6, 0xfc | (mpy_arch & 3), small_int_bits]), # test loading of viper and asm '/mod1.mpy': valid_header + ( @@ -112,7 +114,7 @@ def open(self, path, mode): # fmt: on # create and mount a user filesystem -os.mount(UserFS(user_files), "/userfs") +vfs.mount(UserFS(user_files), "/userfs") sys.path.append("/userfs") # import .mpy files from the user filesystem @@ -125,5 +127,5 @@ def open(self, path, mode): print(mod, "ValueError", er) # unmount and undo path addition -os.umount("/userfs") +vfs.umount("/userfs") sys.path.pop() diff --git a/tests/micropython/import_mpy_native_gc.py b/tests/micropython/import_mpy_native_gc.py index 35759ce95ba7f..5159cc9e9f9cf 100644 --- a/tests/micropython/import_mpy_native_gc.py +++ b/tests/micropython/import_mpy_native_gc.py @@ -1,11 +1,10 @@ -# Test that native code loaded from a .mpy file is retained after a GC. +# Test that native text/BSS/rodata loaded from a .mpy file is retained after a GC. try: - import gc, sys, io, os + import gc, sys, io, vfs sys.implementation._mpy io.IOBase - os.mount except (ImportError, AttributeError): print("SKIP") raise SystemExit @@ -23,7 +22,9 @@ def readinto(self, buf): return n def ioctl(self, req, arg): - return 0 + if req == 4: # MP_STREAM_CLOSE + return 0 + return -1 class UserFS: @@ -45,19 +46,24 @@ def open(self, path, mode): return UserFile(self.files[path]) -# Pre-compiled examples/natmod/features0 example for various architectures, keyed +# Pre-compiled import_mpy_native_gc_module example for various architectures, keyed # by the required value of sys.implementation._mpy (without sub-version). -# cd examples/natmod/features0 -# make clean -# make ARCH=x64 # or ARCH=armv6m -# cat features0.mpy | python -c 'import sys; print(sys.stdin.buffer.read())' +# To rebuild: +# $ cd import_mpy_native_gc_module +# $ make clean +# $ make ARCH=x64 # or ARCH=armv6m or ARCH=xtensawin +# Then copy the bytes object printed on the last line. + # CIRCUITPY-CHANGE: 'C' instead of 'M' mpy marker. features0_file_contents = { # -march=x64 - 0x806: b'C\x06\n\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x8a\x02\xe93\x00\x00\x00\xf3\x0f\x1e\xfaSH\x8b\x1d\x7f\x00\x00\x00\xbe\x02\x00\x00\x00\xffS\x18\xbf\x01\x00\x00\x00H\x85\xc0u\x0cH\x8bC \xbe\x02\x00\x00\x00[\xff\xe0H\x0f\xaf\xf8H\xff\xc8\xeb\xe6\xf3\x0f\x1e\xfaATUSH\x8b\x1dI\x00\x00\x00H\x8bG\x08L\x8bc(H\x8bx\x08A\xff\xd4H\x8d5#\x00\x00\x00H\x89\xc5H\x8b\x051\x00\x00\x00\x0f\xb7x\x02\xffShH\x89\xefA\xff\xd4H\x8b\x03[]A\\\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11$\r&\xa5 \x01"\xff', + 0x806: b"C\x06\x0b\x1f\x03\x002build/test_x64.native.mpy\x00\x08add1\x00\x0cunused\x00\x91B\xe9I\x00\x00\x00H\x8b\x05\xf4\x00\x00\x00H\x8b\x00\xc3H\x8b\x05\xf9\x00\x00\x00\xbe\x02\x00\x00\x00\x8b8H\x8b\x05\xdb\x00\x00\x00H\x8b@ \xff\xe0H\x8b\x05\xce\x00\x00\x00S\xbe\x02\x00\x00\x00H\x8bX \xffP\x18\xbe\x02\x00\x00\x00H\x8dx\x01H\x89\xd8[\xff\xe0AVAUATUSH\x8b\x1d\xa3\x00\x00\x00H\x8bG\x08L\x8bk(H\x8bx\x08A\xff\xd5L\x8b5\x95\x00\x00\x00L\x8bchH\x8d5r\x00\x00\x00H\x89\xc5H\x8b\x05\x88\x00\x00\x00A\x0f\xb7~\x04\xc7\x00@\xe2\x01\x00A\xff\xd4H\x8d5C\x00\x00\x00\xbfV\x00\x00\x00A\xff\xd4A\x0f\xb7~\x02H\x8d5\x1f\x00\x00\x00A\xff\xd4H\x89\xefA\xff\xd5H\x8b\x03[]A\\A]A^\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11@\rB\tD\xaf4\x016\xad8\x01:\xaf<\x01>\xff", # -march=armv6m - 0x1006: b'C\x06\x12\x1f\x02\x004build/features0.native.mpy\x00\x12factorial\x00\x88\x02\x18\xe0\x00\x00\x10\xb5\tK\tJ{D\x9cX\x02!\xe3h\x98G\x03\x00\x01 \x00+\x02\xd0XC\x01;\xfa\xe7\x02!#i\x98G\x10\xbd\xc0Fj\x00\x00\x00\x00\x00\x00\x00\xf8\xb5\nN\nK~D\xf4XChgiXh\xb8G\x05\x00\x07K\x08I\xf3XyDX\x88ck\x98G(\x00\xb8G h\xf8\xbd\xc0F:\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x11<\r>\xa58\x01:\xff' -, + 0x1006: b"C\x06\x13\x1f\x03\x008build/test_armv6m.native.mpy\x00\x08add1\x00\x0cunused\x00\x8eb0\xe0\x00\x00\x00\x00\x00\x00\x02K\x03J{D\x9bX\x18hpG\xd0\x00\x00\x00\x00\x00\x00\x00\x10\xb5\x05K\x05I\x06J{D\x9aX[X\x10h\x02!\x1bi\x98G\x10\xbd\xb8\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x10\xb5\x06K\x06J{D\x9bX\x02!\x1ci\xdbh\x98G\x02!\x010\xa0G\x10\xbd\xc0F\x96\x00\x00\x00\x00\x00\x00\x00\xf7\xb5\x12O\x12K\x7fD\xfdX\x12Lki|D\x00\x93ChXh\x00\x9b\x98G\x0fK\x01\x90\x0fJ\xfbXnk\x1a`\x0eK!\x00\xffX\xb8\x88\xb0G!\x00V \x081\xb0G!\x00x\x88\x101\xb0G\x01\x98\x00\x9b\x98G(h\xfe\xbd\xc0Fr\x00\x00\x00\x00\x00\x00\x00R\x00\x00\x00\x08\x00\x00\x00@\xe2\x01\x00\x04\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11p\rr\tt\xafd\x01f\xadh\x01j\xafl\x01n\xff", + # -march=xtensawin + 0x2806: b"C\x06+\x1f\x03\x00>build/test_xtensawin.native.mpy\x00\x08add1\x00\x0cunused\x00\x8a\x12\x06\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x006A\x00\x81\xf9\xff(\x08\x1d\xf0\x00\x006A\x00\x91\xfb\xff\x81\xf5\xff\xa8\t\x88H\x0c+\xe0\x08\x00-\n\x1d\xf0\x00\x006A\x00\x81\xf0\xff\xad\x02xH\x888\x0c+\xe0\x08\x00\x0c+\x1b\xaa\xe0\x07\x00-\n\x1d\xf06A\x00a\xe9\xff\x88\x122&\x05\xa2(\x01\xe0\x03\x00q\xe6\xff\x81\xea\xff\x92\xa7\x89\xa0\x99\x11H\xd6]\n\xb1\xe3\xff\xa2\x17\x02\x99\x08\xe0\x04\x00\xb1\xe2\xff\\j\xe0\x04\x00\xb1\xe1\xff\xa2\x17\x01\xe0\x04\x00\xad\x05\xe0\x03\x00(\x06\x1d\xf0p\x18\x04\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x11\x02\r\x04\x07\x06\x03\t\x0c\xaf\x01\x01\x03\xad\x05\x01\x07\xaf\t\x01\x0b\xff", + # -march=rv32imc + 0x2C06: b'C\x06/\x1f\x03\x00:build/test_rv32imc.native.mpy\x00\x08add1\x00\x0cunused\x00\x8fb\x97\x0f\x00\x00g\x80\x0f\x05\x97\x07\x00\x00\x83\xa7\x07\x0e\x88C\x82\x80\x97\x07\x00\x00\x83\xa7G\r\x17\x07\x00\x00\x03\'\xc7\r\x9cK\x08C\x89E\x82\x87A\x11\x97\x07\x00\x00\x83\xa7\xa7\x0b"\xc4\x80K\xdcG\x06\xc6\x89E\x82\x97\xa2\x87"D\xb2@\x89E\x05\x05A\x01\x82\x87\\A\x01\x11"\xcc\x17\x04\x00\x00\x03$$\tN\xc6\xc8C\x83)D\x01\x06\xce&\xcaJ\xc8R\xc4\x82\x99\x17\n\x00\x00\x03*\xca\x07\x03)D\x03\xaa\x84\xf9g\x03UJ\x00\x93\x87\x07$\x17\x07\x00\x00\x03\'\x07\x07\x1c\xc3\x97\x05\x00\x00\x93\x85\xe5\x03\x02\x99\x97\x05\x00\x00\x93\x85\xc5\x03\x13\x05`\x05\x02\x99\x03U*\x00\x97\x05\x00\x00\x93\x85%\x03\x02\x99&\x85\x82\x99\x08@\xf2@bD\xd2DBI\xb2I"J\x05a\x82\x80\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00P\x04\x11t\rv\xafx\xadz\t|\xafh\x01j\xadl\x01n\xafp\x01r\xff', } # Populate armv7m-derived archs based on armv6m. @@ -65,7 +71,7 @@ def open(self, path, mode): features0_file_contents[arch] = features0_file_contents[0x1006] # Check that a .mpy exists for the target (ignore sub-version in lookup). -sys_implementation_mpy = sys.implementation._mpy & ~(3 << 8) +sys_implementation_mpy = (sys.implementation._mpy & ~(3 << 8)) & 0xFFFF if sys_implementation_mpy not in features0_file_contents: print("SKIP") raise SystemExit @@ -74,16 +80,29 @@ def open(self, path, mode): user_files = {"/features0.mpy": features0_file_contents[sys_implementation_mpy]} # Create and mount a user filesystem. -os.mount(UserFS(user_files), "/userfs") +vfs.mount(UserFS(user_files), "/userfs") sys.path.append("/userfs") # Import the native function. gc.collect() -from features0 import factorial +from features0 import get, add1 + +# Test that the native functions work to begin with. +print(get()) +print(add1(12)) # Free the module that contained the function. del sys.modules["features0"] + +# Sweep the stack to remove any stray pointers that we are aiming to reclaim. +def recurse(n): + if n: + recurse(n - 1) + + +recurse(10) + # Run a GC cycle which should reclaim the module but not the function. gc.collect() @@ -91,9 +110,10 @@ def open(self, path, mode): for i in range(1000): [] -# Run the native function, it should not have been freed or overwritten. -print(factorial(10)) +# Run the native function, its text/BSS/rodata should not have been freed or overwritten. +print(get()) +print(add1(12)) # Unmount and undo path addition. -os.umount("/userfs") +vfs.umount("/userfs") sys.path.pop() diff --git a/tests/micropython/import_mpy_native_gc.py.exp b/tests/micropython/import_mpy_native_gc.py.exp index 3fbd4a8698fa3..4250a13c72693 100644 --- a/tests/micropython/import_mpy_native_gc.py.exp +++ b/tests/micropython/import_mpy_native_gc.py.exp @@ -1 +1,4 @@ -3628800 +123456 +13 +123456 +13 diff --git a/tests/micropython/kbd_intr.py b/tests/micropython/kbd_intr.py index 81977aaa52f6f..e1ed7185ef0a2 100644 --- a/tests/micropython/kbd_intr.py +++ b/tests/micropython/kbd_intr.py @@ -1,10 +1,10 @@ # test the micropython.kbd_intr() function -import micropython - try: + import micropython + micropython.kbd_intr -except AttributeError: +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/micropython/meminfo.py b/tests/micropython/meminfo.py index 9df341fbb8334..f4dd8fdb6042c 100644 --- a/tests/micropython/meminfo.py +++ b/tests/micropython/meminfo.py @@ -1,12 +1,14 @@ # tests meminfo functions in micropython module -import micropython +try: + import micropython -# these functions are not always available -if not hasattr(micropython, "mem_info"): + micropython.mem_info +except (ImportError, AttributeError): print("SKIP") -else: - micropython.mem_info() - micropython.mem_info(1) - micropython.qstr_info() - micropython.qstr_info(1) + raise SystemExit + +micropython.mem_info() +micropython.mem_info(1) +micropython.qstr_info() +micropython.qstr_info(1) diff --git a/tests/micropython/memstats.py b/tests/micropython/memstats.py index dee3a4ce2f225..0e2e7b1c0b326 100644 --- a/tests/micropython/memstats.py +++ b/tests/micropython/memstats.py @@ -1,17 +1,19 @@ # tests meminfo functions in micropython module -import micropython +try: + import micropython -# these functions are not always available -if not hasattr(micropython, "mem_total"): + micropython.mem_total +except (ImportError, AttributeError): print("SKIP") -else: - t = micropython.mem_total() - c = micropython.mem_current() - p = micropython.mem_peak() + raise SystemExit - l = list(range(10000)) +t = micropython.mem_total() +c = micropython.mem_current() +p = micropython.mem_peak() - print(micropython.mem_total() > t) - print(micropython.mem_current() > c) - print(micropython.mem_peak() > p) +l = list(range(10000)) + +print(micropython.mem_total() > t) +print(micropython.mem_current() > c) +print(micropython.mem_peak() > p) diff --git a/tests/micropython/native_fun_attrs_code.py b/tests/micropython/native_fun_attrs_code.py new file mode 100644 index 0000000000000..d277a7b9b2670 --- /dev/null +++ b/tests/micropython/native_fun_attrs_code.py @@ -0,0 +1,21 @@ +# Test MicroPython-specific restrictions of function.__code__ attribute. + +try: + (lambda: 0).__code__ +except AttributeError: + print("SKIP") + raise SystemExit + +import micropython + + +@micropython.native +def f_native(): + pass + + +# Can't access __code__ when function is native code. +try: + f_native.__code__ +except AttributeError: + print("AttributeError") diff --git a/tests/micropython/native_fun_attrs_code.py.exp b/tests/micropython/native_fun_attrs_code.py.exp new file mode 100644 index 0000000000000..d169edffb4cfb --- /dev/null +++ b/tests/micropython/native_fun_attrs_code.py.exp @@ -0,0 +1 @@ +AttributeError diff --git a/tests/micropython/native_with.py.exp b/tests/micropython/native_with.py.exp index 6eef7822fbaf8..7e28663f6fcf0 100644 --- a/tests/micropython/native_with.py.exp +++ b/tests/micropython/native_with.py.exp @@ -5,5 +5,5 @@ __exit__ None None None __init__ __enter__ 1 -__exit__ name 'fail' is not defined None +__exit__ name 'fail' isn't defined None NameError diff --git a/tests/micropython/opt_level.py b/tests/micropython/opt_level.py index dd5493a7a3cb8..789197d8825bf 100644 --- a/tests/micropython/opt_level.py +++ b/tests/micropython/opt_level.py @@ -1,4 +1,10 @@ -import micropython as micropython +# test micropython.opt_level() + +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit # check we can get and set the level micropython.opt_level(0) diff --git a/tests/micropython/opt_level_lineno.py b/tests/micropython/opt_level_lineno.py new file mode 100644 index 0000000000000..4ca76625de49a --- /dev/null +++ b/tests/micropython/opt_level_lineno.py @@ -0,0 +1,24 @@ +# test micropython.opt_level() and line numbers + +try: + import micropython +except ImportError: + print("SKIP") + raise SystemExit + +# check that level 3 doesn't store line numbers +# the expected output is that any line is printed as "line 1" +micropython.opt_level(3) + +# force bytecode emitter, because native emitter doesn't store line numbers +exec(""" +@micropython.bytecode +def f(): + try: + xyz + except NameError as er: + # CIRCUITPY-CHANGE: use traceback.print_exception() instead of sys.print_exception() + import traceback + traceback.print_exception(er) +f() +""") diff --git a/tests/micropython/opt_level_lineno.py.exp b/tests/micropython/opt_level_lineno.py.exp new file mode 100644 index 0000000000000..b50f0628c81fb --- /dev/null +++ b/tests/micropython/opt_level_lineno.py.exp @@ -0,0 +1,3 @@ +Traceback (most recent call last): + File "", line 1, in f +NameError: name 'xyz' isn't defined diff --git a/tests/micropython/ringio_big.py b/tests/micropython/ringio_big.py new file mode 100644 index 0000000000000..ddbbae12a630c --- /dev/null +++ b/tests/micropython/ringio_big.py @@ -0,0 +1,29 @@ +# Check that micropython.RingIO works correctly. + +try: + import micropython + + micropython.RingIO +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + +try: + # The maximum possible size + micropython.RingIO(bytearray(65535)) + micropython.RingIO(65534) + + try: + # Buffer may not be too big + micropython.RingIO(bytearray(65536)) + except ValueError as ex: + print(type(ex)) + + try: + # Size may not be too big + micropython.RingIO(65535) + except ValueError as ex: + print(type(ex)) +except MemoryError: + print("SKIP") + raise SystemExit diff --git a/tests/micropython/ringio_big.py.exp b/tests/micropython/ringio_big.py.exp new file mode 100644 index 0000000000000..72af34b383872 --- /dev/null +++ b/tests/micropython/ringio_big.py.exp @@ -0,0 +1,2 @@ + + diff --git a/tests/micropython/schedule.py b/tests/micropython/schedule.py index 6a91459ea3d54..f3dd32661267b 100644 --- a/tests/micropython/schedule.py +++ b/tests/micropython/schedule.py @@ -1,10 +1,10 @@ # test micropython.schedule() function -import micropython - try: + import micropython + micropython.schedule -except AttributeError: +except (ImportError, AttributeError): print("SKIP") raise SystemExit diff --git a/tests/micropython/stack_use.py b/tests/micropython/stack_use.py index 266885d9d1897..5d36fdca2fe01 100644 --- a/tests/micropython/stack_use.py +++ b/tests/micropython/stack_use.py @@ -1,7 +1,11 @@ # tests stack_use function in micropython module -import micropython -if not hasattr(micropython, "stack_use"): +try: + import micropython + + micropython.stack_use +except (ImportError, AttributeError): print("SKIP") -else: - print(type(micropython.stack_use())) # output varies + raise SystemExit + +print(type(micropython.stack_use())) # output varies diff --git a/tests/micropython/test_normalize_newlines.py b/tests/micropython/test_normalize_newlines.py new file mode 100644 index 0000000000000..f19aaa69a3f75 --- /dev/null +++ b/tests/micropython/test_normalize_newlines.py @@ -0,0 +1,14 @@ +# Test for normalize_newlines functionality +# This test verifies that test framework handles various newline combinations correctly + +# Note: This is more of an integration test since normalize_newlines is in the test framework +# The actual testing happens when this test is run through run-tests.py + +print("Testing newline handling") +print("Line 1\r\nLine 2") # Windows-style line ending - should be normalized +print("Line 3") # Normal line +print("Line 4") # Normal line +print("Line 5\nLine 6") # Unix-style line ending - already normalized + +# Test that literal \r in strings is preserved +print(repr("test\rstring")) # Should show 'test\rstring' not 'test\nstring' diff --git a/tests/micropython/test_normalize_newlines.py.exp b/tests/micropython/test_normalize_newlines.py.exp new file mode 100644 index 0000000000000..c4395468cf109 --- /dev/null +++ b/tests/micropython/test_normalize_newlines.py.exp @@ -0,0 +1,8 @@ +Testing newline handling +Line 1 +Line 2 +Line 3 +Line 4 +Line 5 +Line 6 +'test\rstring' diff --git a/tests/micropython/viper_error.py b/tests/micropython/viper_error.py index 80617af0c1f29..6c5c3ba200702 100644 --- a/tests/micropython/viper_error.py +++ b/tests/micropython/viper_error.py @@ -50,6 +50,9 @@ def f(): # incorrect return type test("@micropython.viper\ndef f() -> int: return []") +# can't do unary op of incompatible type +test("@micropython.viper\ndef f(x:ptr): -x") + # can't do binary op between incompatible types test("@micropython.viper\ndef f(): 1 + []") test("@micropython.viper\ndef f(x:int, y:uint): x < y") @@ -69,9 +72,7 @@ def f(): test("@micropython.viper\ndef f(): raise 1") # unary ops not implemented -test("@micropython.viper\ndef f(x:int): +x") -test("@micropython.viper\ndef f(x:int): -x") -test("@micropython.viper\ndef f(x:int): ~x") +test("@micropython.viper\ndef f(x:int): not x") # binary op not implemented test("@micropython.viper\ndef f(x:uint, y:uint): res = x // y") diff --git a/tests/micropython/viper_error.py.exp b/tests/micropython/viper_error.py.exp index 31c85b1d872af..51cbd6c7097cd 100644 --- a/tests/micropython/viper_error.py.exp +++ b/tests/micropython/viper_error.py.exp @@ -5,6 +5,7 @@ ViperTypeError("local 'x' used before type known",) ViperTypeError("local 'x' has type 'int' but source is 'object'",) ViperTypeError("can't implicitly convert 'ptr' to 'bool'",) ViperTypeError("return expected 'int' but got 'object'",) +ViperTypeError("can't do unary op of 'ptr'",) ViperTypeError("can't do binary op between 'int' and 'object'",) ViperTypeError('comparison of int and uint',) ViperTypeError("can't load from 'int'",) @@ -15,9 +16,7 @@ ViperTypeError("can't store to 'int'",) ViperTypeError("can't store 'None'",) ViperTypeError("can't store 'None'",) ViperTypeError('must raise an object',) -ViperTypeError('unary op __pos__ not implemented',) -ViperTypeError('unary op __neg__ not implemented',) -ViperTypeError('unary op __invert__ not implemented',) +ViperTypeError("'not' not implemented",) ViperTypeError('div/mod not implemented for uint',) ViperTypeError('div/mod not implemented for uint',) ViperTypeError('binary op not implemented',) diff --git a/tests/micropython/viper_large_jump.py b/tests/micropython/viper_large_jump.py new file mode 100644 index 0000000000000..1c5913dec1ea2 --- /dev/null +++ b/tests/micropython/viper_large_jump.py @@ -0,0 +1,20 @@ +COUNT = 600 + + +try: + code = """ +@micropython.viper +def f() -> int: + x = 0 + while x < 10: +""" + for i in range(COUNT): + code += " x += 1\n" + code += " return x" + exec(code) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +print(f()) diff --git a/tests/micropython/viper_large_jump.py.exp b/tests/micropython/viper_large_jump.py.exp new file mode 100644 index 0000000000000..e9f960cf4ac4e --- /dev/null +++ b/tests/micropython/viper_large_jump.py.exp @@ -0,0 +1 @@ +600 diff --git a/tests/micropython/viper_ptr16_load_boundary.py b/tests/micropython/viper_ptr16_load_boundary.py new file mode 100644 index 0000000000000..0d4c3105b685b --- /dev/null +++ b/tests/micropython/viper_ptr16_load_boundary.py @@ -0,0 +1,39 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr16) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 2 + + +@micropython.viper +def get_index(src: ptr16, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = ((1 << bit) - (2 * SIZE), (1 << bit) - (1 * SIZE), 1 << bit) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr16_load_boundary.py.exp b/tests/micropython/viper_ptr16_load_boundary.py.exp new file mode 100644 index 0000000000000..56f1d32290468 --- /dev/null +++ b/tests/micropython/viper_ptr16_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x100 0x302 0x504 +0x100 +0x302 +0x504 +--- 8 +0x706 0x908 0xb0a +0x706 +0x908 +0xb0a +--- 11 +0xd0c 0xf0e 0x1110 +0xd0c +0xf0e +0x1110 +--- 12 +0x1312 0x1514 0x1716 +0x1312 +0x1514 +0x1716 diff --git a/tests/micropython/viper_ptr16_store_boundary.py b/tests/micropython/viper_ptr16_store_boundary.py new file mode 100644 index 0000000000000..7c774d4d1ca18 --- /dev/null +++ b/tests/micropython/viper_ptr16_store_boundary.py @@ -0,0 +1,63 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr16): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 2 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src, i): + return src[i * SIZE] + (src[(i * SIZE) + 1] << 8) + + +@micropython.viper +def set_index(dest: ptr16, i: int, val: uint): + saved = dest + dest[i] = val + assert int(saved) == int(dest) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr16_store_boundary.py.exp b/tests/micropython/viper_ptr16_store_boundary.py.exp new file mode 100644 index 0000000000000..007a50b3edafb --- /dev/null +++ b/tests/micropython/viper_ptr16_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x102 +0x203 +0xc0d +0xd0e +0xe0f +--- 8 +0x304 +0x405 +0x506 +0xf10 +0x1011 +0x1112 +--- 11 +0x607 +0x708 +0x809 +0x1213 +0x1314 +0x1415 +--- 12 +0x90a +0xa0b +0xb0c +0x1516 +0x1617 +0x1718 diff --git a/tests/micropython/viper_ptr32_load_boundary.py b/tests/micropython/viper_ptr32_load_boundary.py new file mode 100644 index 0000000000000..971d1113c49bb --- /dev/null +++ b/tests/micropython/viper_ptr32_load_boundary.py @@ -0,0 +1,39 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr32) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 4 + + +@micropython.viper +def get_index(src: ptr32, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit)) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + pre, idx, post = pre // SIZE, idx // SIZE, post // SIZE + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr32_load_boundary.py.exp b/tests/micropython/viper_ptr32_load_boundary.py.exp new file mode 100644 index 0000000000000..1e22a8b361333 --- /dev/null +++ b/tests/micropython/viper_ptr32_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x3020100 0x7060504 0xb0a0908 +0x3020100 +0x7060504 +0xb0a0908 +--- 8 +0xf0e0d0c 0x13121110 0x17161514 +0xf0e0d0c +0x13121110 +0x17161514 +--- 11 +0x1b1a1918 0x1f1e1d1c 0x23222120 +0x1b1a1918 +0x1f1e1d1c +0x23222120 +--- 12 +0x27262524 0x2b2a2928 0x2f2e2d2c +0x27262524 +0x2b2a2928 +0x2f2e2d2c diff --git a/tests/micropython/viper_ptr32_store_boundary.py b/tests/micropython/viper_ptr32_store_boundary.py new file mode 100644 index 0000000000000..96ca74ad3ca70 --- /dev/null +++ b/tests/micropython/viper_ptr32_store_boundary.py @@ -0,0 +1,68 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr32): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 4 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src, i): + return ( + src[i * SIZE] + + (src[(i * SIZE) + 1] << 8) + + (src[(i * SIZE) + 2] << 16) + + (src[(i * SIZE) + 3] << 24) + ) + + +@micropython.viper +def set_index(dest: ptr32, i: int, val: uint): + saved = dest + dest[i] = val + assert int(dest) == int(saved) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr32_store_boundary.py.exp b/tests/micropython/viper_ptr32_store_boundary.py.exp new file mode 100644 index 0000000000000..7a9a51624743e --- /dev/null +++ b/tests/micropython/viper_ptr32_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x102 +0x10203 +0xa0b0c0d +0xb0c0d0e +0xc0d0e0f +--- 8 +0x1020304 +0x2030405 +0x3040506 +0xd0e0f10 +0xe0f1011 +0xf101112 +--- 11 +0x4050607 +0x5060708 +0x6070809 +0x10111213 +0x11121314 +0x12131415 +--- 12 +0x708090a +0x8090a0b +0x90a0b0c +0x13141516 +0x14151617 +0x15161718 diff --git a/tests/micropython/viper_ptr8_load_boundary.py b/tests/micropython/viper_ptr8_load_boundary.py new file mode 100644 index 0000000000000..57e06da5709ab --- /dev/null +++ b/tests/micropython/viper_ptr8_load_boundary.py @@ -0,0 +1,38 @@ +# Test boundary conditions for various architectures + +GET_TEMPLATE = """ +@micropython.viper +def get{off}(src: ptr8) -> uint: + return uint(src[{off}]) +print(hex(get{off}(buffer))) +""" + + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 1 + + +@micropython.viper +def get_index(src: ptr8, i: int) -> int: + return src[i] + + +def data(start, len): + output = bytearray(len) + for idx in range(len): + output[idx] = (start + idx) & 0xFF + return output + + +buffer = bytearray((((1 << max(BIT_THRESHOLDS)) + 1) // 1024) * 1024) +val = 0 +for bit in BIT_THRESHOLDS: + print("---", bit) + pre, idx, post = (((1 << bit) - (2 * SIZE)), ((1 << bit) - (1 * SIZE)), (1 << bit)) + buffer[pre:post] = data(val, 3 * SIZE) + val = val + (3 * SIZE) + + print(hex(get_index(buffer, pre)), hex(get_index(buffer, idx)), hex(get_index(buffer, post))) + exec(GET_TEMPLATE.format(off=pre)) + exec(GET_TEMPLATE.format(off=idx)) + exec(GET_TEMPLATE.format(off=post)) diff --git a/tests/micropython/viper_ptr8_load_boundary.py.exp b/tests/micropython/viper_ptr8_load_boundary.py.exp new file mode 100644 index 0000000000000..a0e423686b8fa --- /dev/null +++ b/tests/micropython/viper_ptr8_load_boundary.py.exp @@ -0,0 +1,20 @@ +--- 5 +0x0 0x1 0x2 +0x0 +0x1 +0x2 +--- 8 +0x3 0x4 0x5 +0x3 +0x4 +0x5 +--- 11 +0x6 0x7 0x8 +0x6 +0x7 +0x8 +--- 12 +0x9 0xa 0xb +0x9 +0xa +0xb diff --git a/tests/micropython/viper_ptr8_store_boundary.py b/tests/micropython/viper_ptr8_store_boundary.py new file mode 100644 index 0000000000000..68b76fd598b88 --- /dev/null +++ b/tests/micropython/viper_ptr8_store_boundary.py @@ -0,0 +1,63 @@ +# Test boundary conditions for various architectures + +SET_TEMPLATE = """ +@micropython.viper +def set{off}(dest: ptr8): + saved = dest + dest[{off}] = {val} + assert int(saved) == int(dest) +""" + +BIT_THRESHOLDS = (5, 8, 11, 12) +SIZE = 1 +MASK = (1 << (8 * SIZE)) - 1 + +next_int = 1 +test_buffer = bytearray(SIZE) + + +def next_value() -> uint: + global next_int + global test_buffer + for index in range(1, SIZE): + test_buffer[index - 1] = test_buffer[index] + test_buffer[SIZE - 1] = next_int + next_int += 1 + output = 0 + for byte in test_buffer: + output = (output << 8) | byte + return output & MASK + + +def get_index(src: ptr8, i: int): + return src[i] + + +@micropython.viper +def set_index(dest: ptr8, i: int, val: uint): + saved = dest + dest[i] = val + assert int(dest) == int(saved) + + +try: + buffer = bytearray((((1 << max(BIT_THRESHOLDS)) // 1024) + 1) * 1024) + + for bit in BIT_THRESHOLDS: + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + exec(SET_TEMPLATE.format(off=(offset + index) // SIZE, val=next_value())) +except MemoryError: + print("SKIP-TOO-LARGE") + raise SystemExit + + +for bit in BIT_THRESHOLDS: + print("---", bit) + offset = (1 << bit) - (2 * SIZE) + for index in range(0, 3 * SIZE, SIZE): + globals()["set{}".format((offset + index) // SIZE)](buffer) + print(hex(get_index(buffer, (offset + index) // SIZE))) + for index in range(0, 3 * SIZE, SIZE): + set_index(buffer, (offset + index) // SIZE, next_value()) + print(hex(get_index(buffer, (offset + index) // SIZE))) diff --git a/tests/micropython/viper_ptr8_store_boundary.py.exp b/tests/micropython/viper_ptr8_store_boundary.py.exp new file mode 100644 index 0000000000000..621295d81a896 --- /dev/null +++ b/tests/micropython/viper_ptr8_store_boundary.py.exp @@ -0,0 +1,28 @@ +--- 5 +0x1 +0x2 +0x3 +0xd +0xe +0xf +--- 8 +0x4 +0x5 +0x6 +0x10 +0x11 +0x12 +--- 11 +0x7 +0x8 +0x9 +0x13 +0x14 +0x15 +--- 12 +0xa +0xb +0xc +0x16 +0x17 +0x18 diff --git a/tests/micropython/viper_unop.py b/tests/micropython/viper_unop.py new file mode 100644 index 0000000000000..61cbd5125f167 --- /dev/null +++ b/tests/micropython/viper_unop.py @@ -0,0 +1,31 @@ +# test unary operators + + +@micropython.viper +def pos(x: int) -> int: + return +x + + +print(pos(0)) +print(pos(1)) +print(pos(-2)) + + +@micropython.viper +def neg(x: int) -> int: + return -x + + +print(neg(0)) +print(neg(1)) +print(neg(-2)) + + +@micropython.viper +def inv(x: int) -> int: + return ~x + + +print(inv(0)) +print(inv(1)) +print(inv(-2)) diff --git a/tests/micropython/viper_unop.py.exp b/tests/micropython/viper_unop.py.exp new file mode 100644 index 0000000000000..6d93312caa136 --- /dev/null +++ b/tests/micropython/viper_unop.py.exp @@ -0,0 +1,9 @@ +0 +1 +-2 +0 +-1 +2 +-1 +-2 +1 diff --git a/tests/micropython/viper_with.py.exp b/tests/micropython/viper_with.py.exp index 6eef7822fbaf8..7e28663f6fcf0 100644 --- a/tests/micropython/viper_with.py.exp +++ b/tests/micropython/viper_with.py.exp @@ -5,5 +5,5 @@ __exit__ None None None __init__ __enter__ 1 -__exit__ name 'fail' is not defined None +__exit__ name 'fail' isn't defined None NameError diff --git a/tests/misc/cexample_class.py b/tests/misc/cexample_class.py index 6b8718ad8cc5f..06d741922d289 100644 --- a/tests/misc/cexample_class.py +++ b/tests/misc/cexample_class.py @@ -22,3 +22,20 @@ print(timer) print(0 <= t_start <= TOLERANCE_MS) print(SLEEP_MS - TOLERANCE_MS <= t_end <= SLEEP_MS + TOLERANCE_MS) + +advanced_timer = cexample.AdvancedTimer() + +time.sleep_ms(100) + +print(repr(advanced_timer)) +print(str(advanced_timer)) + +print(advanced_timer.seconds) +advanced_timer.seconds = 123 +print(advanced_timer.seconds) +print(advanced_timer.time() < 123000 + TOLERANCE_MS) + +try: + advanced_timer.seconds = "bad input" +except TypeError: + print("TypeError") diff --git a/tests/misc/cexample_class.py.exp b/tests/misc/cexample_class.py.exp index b9a06602a316a..a86d4d14f78df 100644 --- a/tests/misc/cexample_class.py.exp +++ b/tests/misc/cexample_class.py.exp @@ -1,3 +1,9 @@ True True +AdvancedTimer() +AdvancedTimer() # created 0 seconds ago +0 +123 +True +TypeError diff --git a/tests/misc/cexample_module.py b/tests/misc/cexample_module.py index c1da2ecf7ab24..979c1fa24b376 100644 --- a/tests/misc/cexample_module.py +++ b/tests/misc/cexample_module.py @@ -12,5 +12,6 @@ d = dir(cexample) d.index("add_ints") d.index("Timer") +d.index("AdvancedTimer") print(cexample.add_ints(1, 3)) diff --git a/tests/misc/cexample_subclass.py b/tests/misc/cexample_subclass.py new file mode 100644 index 0000000000000..9f52a2c737add --- /dev/null +++ b/tests/misc/cexample_subclass.py @@ -0,0 +1,37 @@ +# test subclassing custom native class + +try: + from cexample import AdvancedTimer +except ImportError: + print("SKIP") + raise SystemExit + + +class SubTimer(AdvancedTimer): + def __init__(self): + # At this point, self does not yet represent a AdvancedTimer instance. + print(self) + + # So lookups via type.attr handler will fail. + try: + self.seconds + except AttributeError: + print("AttributeError") + + # Also applies to builtin methods. + try: + self.time() + except AttributeError: + print("AttributeError") + + # Initialize base class. + super().__init__(self) + + # Now you can access methods and attributes normally. + self.time() + print(self.seconds) + self.seconds = 123 + print(self.seconds) + + +watch = SubTimer() diff --git a/tests/misc/cexample_subclass.py.exp b/tests/misc/cexample_subclass.py.exp new file mode 100644 index 0000000000000..a035649e475db --- /dev/null +++ b/tests/misc/cexample_subclass.py.exp @@ -0,0 +1,5 @@ + +AttributeError +AttributeError +0 +123 diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index deeb9fb19225b..8608f2322f8e8 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -39,7 +39,7 @@ except NotImplementedError: print("NotImplementedError") -# uPy raises TypeError, should be ValueError +# MicroPython raises TypeError, should be ValueError try: "%c" % b"\x01\x02" except (TypeError, ValueError): @@ -63,12 +63,6 @@ except NotImplementedError: print("NotImplementedError") -# str.endswith(s, start) not implemented -try: - "abc".endswith("c", 1) -except NotImplementedError: - print("NotImplementedError") - # str subscr with step!=1 not implemented try: print("abc"[1:2:3]) @@ -106,10 +100,10 @@ print("NotImplementedError") # CIRCUITPY-CHANGE: We do check these. -# struct pack with too many args, not checked by uPy +# struct pack with too many args, not checked by MicroPython # print(struct.pack("bb", 1, 2, 3)) -# struct pack with too few args, not checked by uPy +# struct pack with too few args, not checked by MicroPython # print(struct.pack("bb", 1)) # array slice assignment with unsupported RHS diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index 8518828ec3ab1..006ddee1b7322 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -14,7 +14,6 @@ NotImplementedError NotImplementedError NotImplementedError NotImplementedError -NotImplementedError AttributeError TypeError A.foo diff --git a/tests/misc/non_compliant_lexer.py b/tests/misc/non_compliant_lexer.py index e1c21f3d713c4..04c605953e705 100644 --- a/tests/misc/non_compliant_lexer.py +++ b/tests/misc/non_compliant_lexer.py @@ -11,7 +11,7 @@ def test(code): print("NotImplementedError") -# uPy requires spaces between literal numbers and keywords, CPy doesn't +# MPy requires spaces between literal numbers and keywords, CPy doesn't try: eval("1and 0") except SyntaxError: diff --git a/tests/misc/print_exception.py.native.exp b/tests/misc/print_exception.py.native.exp new file mode 100644 index 0000000000000..59e856ae3c44a --- /dev/null +++ b/tests/misc/print_exception.py.native.exp @@ -0,0 +1,18 @@ +caught +Exception: msg + +caught +Exception: fail + +finally +caught +Exception: fail + +reraise +Exception: fail + +caught +Exception: fail + +AttributeError: 'function' object has no attribute 'X' + diff --git a/tests/misc/rge_sm.py b/tests/misc/rge_sm.py index 5e071687c495d..33aa4edb7427a 100644 --- a/tests/misc/rge_sm.py +++ b/tests/misc/rge_sm.py @@ -39,14 +39,6 @@ def solve(self, finishtime): if not self.iterate(): break - def solveNSteps(self, nSteps): - for i in range(nSteps): - if not self.iterate(): - break - - def series(self): - return zip(*self.Trajectory) - # 1-loop RGES for the main parameters of the SM # couplings are: g1, g2, g3 of U(1), SU(2), SU(3); yt (top Yukawa), lambda (Higgs quartic) @@ -55,70 +47,36 @@ def series(self): lambda *a: 41.0 / 96.0 / math.pi**2 * a[1] ** 3, # g1 lambda *a: -19.0 / 96.0 / math.pi**2 * a[2] ** 3, # g2 lambda *a: -42.0 / 96.0 / math.pi**2 * a[3] ** 3, # g3 - lambda *a: 1.0 - / 16.0 - / math.pi**2 - * ( - 9.0 / 2.0 * a[4] ** 3 - - 8.0 * a[3] ** 2 * a[4] - - 9.0 / 4.0 * a[2] ** 2 * a[4] - - 17.0 / 12.0 * a[1] ** 2 * a[4] + lambda *a: ( + 1.0 + / 16.0 + / math.pi**2 + * ( + 9.0 / 2.0 * a[4] ** 3 + - 8.0 * a[3] ** 2 * a[4] + - 9.0 / 4.0 * a[2] ** 2 * a[4] + - 17.0 / 12.0 * a[1] ** 2 * a[4] + ) ), # yt - lambda *a: 1.0 - / 16.0 - / math.pi**2 - * ( - 24.0 * a[5] ** 2 - + 12.0 * a[4] ** 2 * a[5] - - 9.0 * a[5] * (a[2] ** 2 + 1.0 / 3.0 * a[1] ** 2) - - 6.0 * a[4] ** 4 - + 9.0 / 8.0 * a[2] ** 4 - + 3.0 / 8.0 * a[1] ** 4 - + 3.0 / 4.0 * a[2] ** 2 * a[1] ** 2 + lambda *a: ( + 1.0 + / 16.0 + / math.pi**2 + * ( + 24.0 * a[5] ** 2 + + 12.0 * a[4] ** 2 * a[5] + - 9.0 * a[5] * (a[2] ** 2 + 1.0 / 3.0 * a[1] ** 2) + - 6.0 * a[4] ** 4 + + 9.0 / 8.0 * a[2] ** 4 + + 3.0 / 8.0 * a[1] ** 4 + + 3.0 / 4.0 * a[2] ** 2 * a[1] ** 2 + ) ), # lambda ) -def drange(start, stop, step): - r = start - while r < stop: - yield r - r += step - - -def phaseDiagram(system, trajStart, trajPlot, h=0.1, tend=1.0, range=1.0): - tstart = 0.0 - for i in drange(0, range, 0.1 * range): - for j in drange(0, range, 0.1 * range): - rk = RungeKutta(system, trajStart(i, j), tstart, h) - rk.solve(tend) - # draw the line - for tr in rk.Trajectory: - x, y = trajPlot(tr) - print(x, y) - print() - # draw the arrow - continue - l = (len(rk.Trajectory) - 1) / 3 - if l > 0 and 2 * l < len(rk.Trajectory): - p1 = rk.Trajectory[l] - p2 = rk.Trajectory[2 * l] - x1, y1 = trajPlot(p1) - x2, y2 = trajPlot(p2) - dx = -0.5 * (y2 - y1) # orthogonal to line - dy = 0.5 * (x2 - x1) # orthogonal to line - # l = math.sqrt(dx*dx + dy*dy) - # if abs(l) > 1e-3: - # l = 0.1 / l - # dx *= l - # dy *= l - print(x1 + dx, y1 + dy) - print(x2, y2) - print(x1 - dx, y1 - dy) - print() - - def singleTraj(system, trajStart, h=0.02, tend=1.0): + is_REPR_C = float("1.0000001") == float("1.0") tstart = 0.0 # compute the trajectory @@ -130,10 +88,15 @@ def singleTraj(system, trajStart, h=0.02, tend=1.0): for i in range(len(rk.Trajectory)): tr = rk.Trajectory[i] - print(" ".join(["{:.4f}".format(t) for t in tr])) - + tr_str = " ".join(["{:.4f}".format(t) for t in tr]) + if is_REPR_C: + # allow two small deviations for REPR_C + if tr_str == "1.0000 0.3559 0.6485 1.1944 0.9271 0.1083": + tr_str = "1.0000 0.3559 0.6485 1.1944 0.9272 0.1083" + if tr_str == "16.0000 0.3894 0.5793 0.7017 0.5686 -0.0168": + tr_str = "16.0000 0.3894 0.5793 0.7017 0.5686 -0.0167" + print(tr_str) -# phaseDiagram(sysSM, (lambda i, j: [0.354, 0.654, 1.278, 0.8 + 0.2 * i, 0.1 + 0.1 * j]), (lambda a: (a[4], a[5])), h=0.1, tend=math.log(10**17)) # initial conditions at M_Z singleTraj(sysSM, [0.354, 0.654, 1.278, 0.983, 0.131], h=0.5, tend=math.log(10**17)) # true values diff --git a/tests/misc/sys_exc_info.py b/tests/misc/sys_exc_info.py index d7e8a2d943b5e..c076dd572b07b 100644 --- a/tests/misc/sys_exc_info.py +++ b/tests/misc/sys_exc_info.py @@ -8,13 +8,14 @@ def f(): - print(sys.exc_info()[0:2]) + e = sys.exc_info() + print(e[0], e[1]) try: raise ValueError("value", 123) except: - print(sys.exc_info()[0:2]) + print(sys.exc_info()[0], sys.exc_info()[1]) f() # Outside except block, sys.exc_info() should be back to None's diff --git a/tests/misc/sys_settrace_cov.py b/tests/misc/sys_settrace_cov.py new file mode 100644 index 0000000000000..579c8a4a25e50 --- /dev/null +++ b/tests/misc/sys_settrace_cov.py @@ -0,0 +1,23 @@ +import sys + +try: + sys.settrace +except AttributeError: + print("SKIP") + raise SystemExit + + +def trace_tick_handler(frame, event, arg): + print("FRAME", frame) + print("LASTI", frame.f_lasti) + return None + + +def f(): + x = 3 + return x + + +sys.settrace(trace_tick_handler) +f() +sys.settrace(None) diff --git a/tests/misc/sys_settrace_cov.py.exp b/tests/misc/sys_settrace_cov.py.exp new file mode 100644 index 0000000000000..423d78ec42b89 --- /dev/null +++ b/tests/misc/sys_settrace_cov.py.exp @@ -0,0 +1,2 @@ +FRAME +LASTI \\d\+ diff --git a/tests/misc/sys_settrace_features.py b/tests/misc/sys_settrace_features.py index 8ca6b382e3c64..6eeb2b900f18c 100644 --- a/tests/misc/sys_settrace_features.py +++ b/tests/misc/sys_settrace_features.py @@ -6,6 +6,10 @@ print("SKIP") raise SystemExit +if sys.version.startswith("3.12"): + # There is a CPython change in settrace that is reverted in 3.13! + print("WARNING: this test will fail when compared to CPython 3.12.x behaviour") + def print_stacktrace(frame, level=0): # Ignore CPython specific helpers. diff --git a/tests/multi_extmod/machine_i2c_target_irq.py b/tests/multi_extmod/machine_i2c_target_irq.py new file mode 100644 index 0000000000000..eafd9dfdca838 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_irq.py @@ -0,0 +1,137 @@ +# Test I2CTarget IRQs and clock stretching. +# +# Requires two instances with their SCL and SDA lines connected together. +# Any combination of the below supported boards can be used. +# +# Notes: +# - pull-up resistors may be needed +# - alif use 1.8V signalling + +import sys +import time +from machine import I2C, I2CTarget + +if not hasattr(I2CTarget, "IRQ_ADDR_MATCH_READ"): + print("SKIP") + raise SystemExit + +ADDR = 67 +clock_stretch_us = 200 + +# Configure pins based on the target. +if sys.platform == "alif": + i2c_args = (1,) # pins P3_7/P3_6 + i2c_kwargs = {} +elif sys.platform == "mimxrt": + i2c_args = (0,) # pins 19/18 on Teensy 4.x + i2c_kwargs = {} + clock_stretch_us = 50 # mimxrt cannot delay too long in the IRQ handler +elif sys.platform == "rp2": + i2c_args = (0,) + i2c_kwargs = {"scl": 9, "sda": 8} +elif sys.platform == "pyboard": + i2c_args = ("Y",) + i2c_kwargs = {} +elif sys.platform == "samd": + i2c_args = () # pins SCL/SDA + i2c_kwargs = {} +elif "zephyr-rpi_pico" in sys.implementation._machine: + i2c_args = ("i2c1",) # on gpio7/gpio6 + i2c_kwargs = {} +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def simple_irq(i2c_target): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_ADDR_MATCH_READ: + print("IRQ_ADDR_MATCH_READ") + if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE: + print("IRQ_ADDR_MATCH_WRITE") + + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + +class I2CTargetMemory: + def __init__(self, i2c_target, mem): + self.buf1 = bytearray(1) + self.mem = mem + self.memaddr = 0 + self.state = 0 + i2c_target.irq( + self.irq, + I2CTarget.IRQ_ADDR_MATCH_WRITE | I2CTarget.IRQ_READ_REQ | I2CTarget.IRQ_WRITE_REQ, + hard=True, + ) + + def irq(self, i2c_target): + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_ADDR_MATCH_WRITE: + self.state = 0 + if flags & I2CTarget.IRQ_READ_REQ: + self.buf1[0] = self.mem[self.memaddr] + self.memaddr += 1 + i2c_target.write(self.buf1) + if flags & I2CTarget.IRQ_WRITE_REQ: + i2c_target.readinto(self.buf1) + if self.state == 0: + self.state = 1 + self.memaddr = self.buf1[0] + else: + self.mem[self.memaddr] = self.buf1[0] + self.memaddr += 1 + self.memaddr %= len(self.mem) + + # Force clock stretching. + time.sleep_us(clock_stretch_us) + + +# I2C controller +def instance0(): + i2c = I2C(*i2c_args, **i2c_kwargs) + multitest.next() + for iteration in range(2): + print("controller iteration", iteration) + multitest.wait("target stage 1") + i2c.writeto_mem(ADDR, 2, "0123") + multitest.broadcast("controller stage 2") + multitest.wait("target stage 3") + print(i2c.readfrom_mem(ADDR, 2, 4)) + multitest.broadcast("controller stage 4") + print("done") + + +# I2C target +def instance1(): + multitest.next() + + for iteration in range(2): + print("target iteration", iteration) + buf = bytearray(b"--------") + if iteration == 0: + # Use built-in memory capability of I2CTarget. + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf) + i2c_target.irq( + simple_irq, + I2CTarget.IRQ_ADDR_MATCH_READ | I2CTarget.IRQ_ADDR_MATCH_WRITE, + hard=True, + ) + else: + # Implement a memory device by hand. + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR) + I2CTargetMemory(i2c_target, buf) + + multitest.broadcast("target stage 1") + multitest.wait("controller stage 2") + print(buf) + multitest.broadcast("target stage 3") + multitest.wait("controller stage 4") + + i2c_target.deinit() + + print("done") diff --git a/tests/multi_extmod/machine_i2c_target_irq.py.exp b/tests/multi_extmod/machine_i2c_target_irq.py.exp new file mode 100644 index 0000000000000..a17c8f43858b3 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_irq.py.exp @@ -0,0 +1,15 @@ +--- instance0 --- +controller iteration 0 +b'0123' +controller iteration 1 +b'0123' +done +--- instance1 --- +target iteration 0 +IRQ_ADDR_MATCH_WRITE +bytearray(b'--0123--') +IRQ_ADDR_MATCH_WRITE +IRQ_ADDR_MATCH_READ +target iteration 1 +bytearray(b'--0123--') +done diff --git a/tests/multi_extmod/machine_i2c_target_memory.py b/tests/multi_extmod/machine_i2c_target_memory.py new file mode 100644 index 0000000000000..6b3f0d03eb7fe --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_memory.py @@ -0,0 +1,79 @@ +# Test basic use of I2CTarget and a memory buffer. +# +# Requires two instances with their SCL and SDA lines connected together. +# Any combination of the below supported boards can be used. +# +# Notes: +# - pull-up resistors may be needed +# - alif use 1.8V signalling + +import sys +from machine import I2C, I2CTarget + +ADDR = 67 + +# Configure pins based on the target. +if sys.platform == "alif": + i2c_args = (1,) # pins P3_7/P3_6 + i2c_kwargs = {} +elif sys.platform == "esp32": + i2c_args = (1,) # on pins 9/8 + i2c_kwargs = {} +elif sys.platform == "mimxrt": + i2c_args = (0,) # pins 19/18 on Teensy 4.x + i2c_kwargs = {} +elif sys.platform == "rp2": + i2c_args = (0,) + i2c_kwargs = {"scl": 9, "sda": 8} +elif sys.platform == "pyboard": + i2c_args = ("Y",) + i2c_kwargs = {} +elif sys.platform == "samd": + i2c_args = () # pins SCL/SDA + i2c_kwargs = {} +elif "zephyr-rpi_pico" in sys.implementation._machine: + i2c_args = ("i2c1",) # on gpio7/gpio6 + i2c_kwargs = {} +else: + print("Please add support for this test on this platform.") + raise SystemExit + + +def simple_irq(i2c_target): + flags = i2c_target.irq().flags() + if flags & I2CTarget.IRQ_END_READ: + print("IRQ_END_READ", i2c_target.memaddr) + if flags & I2CTarget.IRQ_END_WRITE: + print("IRQ_END_WRITE", i2c_target.memaddr) + + +# I2C controller +def instance0(): + i2c = I2C(*i2c_args, **i2c_kwargs) + multitest.next() + for iteration in range(2): + print("controller iteration", iteration) + multitest.wait("target stage 1") + i2c.writeto_mem(ADDR, 2 + iteration, "0123") + multitest.broadcast("controller stage 2") + multitest.wait("target stage 3") + print(i2c.readfrom_mem(ADDR, 2 + iteration, 4)) + multitest.broadcast("controller stage 4") + print("done") + + +# I2C target +def instance1(): + buf = bytearray(b"--------") + i2c_target = I2CTarget(*i2c_args, **i2c_kwargs, addr=ADDR, mem=buf) + i2c_target.irq(simple_irq) + multitest.next() + for iteration in range(2): + print("target iteration", iteration) + multitest.broadcast("target stage 1") + multitest.wait("controller stage 2") + print(buf) + multitest.broadcast("target stage 3") + multitest.wait("controller stage 4") + i2c_target.deinit() + print("done") diff --git a/tests/multi_extmod/machine_i2c_target_memory.py.exp b/tests/multi_extmod/machine_i2c_target_memory.py.exp new file mode 100644 index 0000000000000..71386cfe769d9 --- /dev/null +++ b/tests/multi_extmod/machine_i2c_target_memory.py.exp @@ -0,0 +1,16 @@ +--- instance0 --- +controller iteration 0 +b'0123' +controller iteration 1 +b'0123' +done +--- instance1 --- +target iteration 0 +IRQ_END_WRITE 2 +bytearray(b'--0123--') +IRQ_END_READ 2 +target iteration 1 +IRQ_END_WRITE 3 +bytearray(b'--00123-') +IRQ_END_READ 3 +done diff --git a/tests/perf_bench/bm_fft.py b/tests/perf_bench/bm_fft.py index 9a2d03d11b97c..e35c1216c139f 100644 --- a/tests/perf_bench/bm_fft.py +++ b/tests/perf_bench/bm_fft.py @@ -15,7 +15,7 @@ def reverse(x, bits): # Initialization n = len(vector) - levels = int(math.log(n) / math.log(2)) + levels = int(round(math.log(n) / math.log(2))) coef = (2 if inverse else -2) * cmath.pi / n exptable = [cmath.rect(1, i * coef) for i in range(n // 2)] vector = [vector[reverse(i, levels)] for i in range(n)] # Copy with bit-reversed permutation diff --git a/tests/perf_bench/bm_pidigits.py b/tests/perf_bench/bm_pidigits.py index bdaa73cec7e9f..c935f103c5b78 100644 --- a/tests/perf_bench/bm_pidigits.py +++ b/tests/perf_bench/bm_pidigits.py @@ -5,6 +5,12 @@ # This benchmark stresses big integer arithmetic. # Adapted from code on: http://benchmarksgame.alioth.debian.org/ +try: + int("0x10000000000000000", 16) +except: + print("SKIP") # No support for >64-bit integers + raise SystemExit + def compose(a, b): aq, ar, as_, at = a diff --git a/tests/perf_bench/core_import_mpy_multi.py b/tests/perf_bench/core_import_mpy_multi.py index 364c325042843..67deec0508801 100644 --- a/tests/perf_bench/core_import_mpy_multi.py +++ b/tests/perf_bench/core_import_mpy_multi.py @@ -1,12 +1,12 @@ # Test performance of importing an .mpy file many times. -import sys, io, os +import sys, io, vfs -if not (hasattr(io, "IOBase") and hasattr(os, "mount")): +if not hasattr(io, "IOBase"): print("SKIP") raise SystemExit -# This is the test.py file that is compiled to test.mpy below. +# This is the test.py file that is compiled to test.mpy below. mpy-cross must be invoked with `-msmall-int-bits=30`. """ class A: def __init__(self, arg): @@ -23,7 +23,7 @@ def f(): x = ("const tuple", None, False, True, 1, 2, 3) result = 123 """ -file_data = b'M\x06\x00\x1f\x14\x03\x0etest.py\x00\x0f\x02A\x00\x02f\x00\x0cresult\x00/-5#\x82I\x81{\x81w\x82/\x81\x05\x81\x17Iom\x82\x13\x06arg\x00\x05\x1cthis will be a string object\x00\x06\x1bthis will be a bytes object\x00\n\x07\x05\x0bconst tuple\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x81\\\x10\n\x01\x89\x07d`T2\x00\x10\x024\x02\x16\x022\x01\x16\x03"\x80{\x16\x04Qc\x02\x81d\x00\x08\x02(DD\x11\x05\x16\x06\x10\x02\x16\x072\x00\x16\x082\x01\x16\t2\x02\x16\nQc\x03`\x1a\x08\x08\x12\x13@\xb1\xb0\x18\x13Qc@\t\x08\t\x12` Qc@\t\x08\n\x12``Qc\x82@ \x0e\x03\x80\x08+)##\x12\x0b\x12\x0c\x12\r\x12\x0e*\x04Y\x12\x0f\x12\x10\x12\x11*\x03Y#\x00\xc0#\x01\xc0#\x02\xc0Qc' +file_data = b'M\x06\x00\x1e\x14\x03\x0etest.py\x00\x0f\x02A\x00\x02f\x00\x0cresult\x00/-5#\x82I\x81{\x81w\x82/\x81\x05\x81\x17Iom\x82\x13\x06arg\x00\x05\x1cthis will be a string object\x00\x06\x1bthis will be a bytes object\x00\n\x07\x05\x0bconst tuple\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x81\\\x10\n\x01\x89\x07d`T2\x00\x10\x024\x02\x16\x022\x01\x16\x03"\x80{\x16\x04Qc\x02\x81d\x00\x08\x02(DD\x11\x05\x16\x06\x10\x02\x16\x072\x00\x16\x082\x01\x16\t2\x02\x16\nQc\x03`\x1a\x08\x08\x12\x13@\xb1\xb0\x18\x13Qc@\t\x08\t\x12` Qc@\t\x08\n\x12``Qc\x82@ \x0e\x03\x80\x08+)##\x12\x0b\x12\x0c\x12\r\x12\x0e*\x04Y\x12\x0f\x12\x10\x12\x11*\x03Y#\x00\xc0#\x01\xc0#\x02\xc0Qc' class File(io.IOBase): @@ -31,7 +31,9 @@ def __init__(self): self.off = 0 def ioctl(self, request, arg): - return 0 + if request == 4: # MP_STREAM_CLOSE + return 0 + return -1 def readinto(self, buf): buf[:] = memoryview(file_data)[self.off : self.off + len(buf)] @@ -57,7 +59,7 @@ def open(self, path, mode): def mount(): - os.mount(FS(), "/__remote") + vfs.mount(FS(), "/__remote") sys.path.insert(0, "/__remote") diff --git a/tests/perf_bench/core_import_mpy_single.py b/tests/perf_bench/core_import_mpy_single.py index 5757c3eaf1fdf..f472bb6476278 100644 --- a/tests/perf_bench/core_import_mpy_single.py +++ b/tests/perf_bench/core_import_mpy_single.py @@ -2,13 +2,13 @@ # The first import of a module will intern strings that don't already exist, and # this test should be representative of what happens in a real application. -import io, os, sys +import sys, io, vfs -if not (hasattr(io, "IOBase") and hasattr(os, "mount")): +if not hasattr(io, "IOBase"): print("SKIP") raise SystemExit -# This is the test.py file that is compiled to test.mpy below. +# This is the test.py file that is compiled to test.mpy below. mpy-cross must be invoked with `-msmall-int-bits=30`. # Many known and unknown names/strings are included to test the linking process. """ class A0: @@ -78,7 +78,7 @@ def f1(): x = ("const tuple 9", None, False, True, 1, 2, 3) result = 123 """ -file_data = b"M\x06\x00\x1f\x81=\x1e\x0etest.py\x00\x0f\x04A0\x00\x04A1\x00\x04f0\x00\x04f1\x00\x0cresult\x00/-5\x04a0\x00\x04a1\x00\x04a2\x00\x04a3\x00\x13\x15\x17\x19\x1b\x1d\x1f!#%')+1379;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}\x7f\x81\x01\x81\x03\x81\x05\x81\x07\x81\t\x81\x0b\x81\r\x81\x0f\x81\x11\x81\x13\x81\x15\x81\x17\x81\x19\x81\x1b\x81\x1d\x81\x1f\x81!\x81#\x81%\x81'\x81)\x81+\x81-\x81/\x811\x813\x815\x817\x819\x81;\x81=\x81?\x81A\x81C\x81E\x81G\x81I\x81K\x81M\x81O\x81Q\x81S\x81U\x81W\x81Y\x81[\x81]\x81_\x81a\x81c\x81e\x81g\x81i\x81k\x81m\x81o\x81q\x81s\x81u\x81w\x81y\x81{\x81}\x81\x7f\x82\x01\x82\x03\x82\x05\x82\x07\x82\t\x82\x0b\x82\r\x82\x0f\x82\x11\x82\x13\x82\x15\x82\x17\x82\x19\x82\x1b\x82\x1d\x82\x1f\x82!\x82#\x82%\x82'\x82)\x82+\x82-\x82/\x821\x823\x825\x827\x829\x82;\x82=\x82?\x82A\x82E\x82G\x82I\x82K\nname0\x00\nname1\x00\nname2\x00\nname3\x00\nname4\x00\nname5\x00\nname6\x00\nname7\x00\nname8\x00\nname9\x00$quite_a_long_name0\x00$quite_a_long_name1\x00$quite_a_long_name2\x00$quite_a_long_name3\x00$quite_a_long_name4\x00$quite_a_long_name5\x00$quite_a_long_name6\x00$quite_a_long_name7\x00$quite_a_long_name8\x00$quite_a_long_name9\x00&quite_a_long_name10\x00&quite_a_long_name11\x00\x05\x1ethis will be a string object 0\x00\x05\x1ethis will be a string object 1\x00\x05\x1ethis will be a string object 2\x00\x05\x1ethis will be a string object 3\x00\x05\x1ethis will be a string object 4\x00\x05\x1ethis will be a string object 5\x00\x05\x1ethis will be a string object 6\x00\x05\x1ethis will be a string object 7\x00\x05\x1ethis will be a string object 8\x00\x05\x1ethis will be a string object 9\x00\x06\x1dthis will be a bytes object 0\x00\x06\x1dthis will be a bytes object 1\x00\x06\x1dthis will be a bytes object 2\x00\x06\x1dthis will be a bytes object 3\x00\x06\x1dthis will be a bytes object 4\x00\x06\x1dthis will be a bytes object 5\x00\x06\x1dthis will be a bytes object 6\x00\x06\x1dthis will be a bytes object 7\x00\x06\x1dthis will be a bytes object 8\x00\x06\x1dthis will be a bytes object 9\x00\n\x07\x05\rconst tuple 0\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 1\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 2\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 3\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 4\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 5\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 6\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 7\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 8\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 9\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x82d\x10\x12\x01i@i@\x84\x18\x84\x1fT2\x00\x10\x024\x02\x16\x02T2\x01\x10\x034\x02\x16\x032\x02\x16\x042\x03\x16\x05\"\x80{\x16\x06Qc\x04\x82\x0c\x00\n\x02($$$\x11\x07\x16\x08\x10\x02\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04@\t\x08\n\x81\x0b Qc@\t\x08\x0b\x81\x0b@Qc@\t\x08\x0c\x81\x0b`QcH\t\n\r\x81\x0b` Qc\x82\x14\x00\x0c\x03h`$$$\x11\x07\x16\x08\x10\x03\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04H\t\n\n\x81\x0b``QcH\t\n\x0b\x81\x0b\x80\x07QcH\t\n\x0c\x81\x0b\x80\x08QcH\t\n\r\x81\x0b\x80\tQc\xa08P:\x04\x80\x0b13///---997799<\x1f%\x1f\"\x1f%)\x1f\"//\x12\x0e\x12\x0f\x12\x10\x12\x11\x12\x12\x12\x13\x12\x14*\x07Y\x12\x15\x12\x16\x12\x17\x12\x18\x12\x19\x12\x1a\x12\x08\x12\x07*\x08Y\x12\x1b\x12\x1c\x12\t\x12\x1d\x12\x1e\x12\x1f*\x06Y\x12 \x12!\x12\"\x12#\x12$\x12%*\x06Y\x12&\x12'\x12(\x12)\x12*\x12+*\x06Y\x12,\x12-\x12.\x12/\x120*\x05Y\x121\x122\x123\x124\x125*\x05Y\x126\x127\x128\x129\x12:*\x05Y\x12;\x12<\x12=\x12>\x12?\x12@\x12A\x12B\x12C\x12D\x12E*\x0bY\x12F\x12G\x12H\x12I\x12J\x12K\x12L\x12M\x12N\x12O\x12P*\x0bY\x12Q\x12R\x12S\x12T\x12U\x12V\x12W\x12X\x12Y\x12Z*\nY\x12[\x12\\\x12]\x12^\x12_\x12`\x12a\x12b\x12c\x12d*\nY\x12e\x12f\x12g\x12h\x12i\x12j\x12k\x12l\x12m\x12n\x12o*\x0bY\x12p\x12q\x12r\x12s\x12t\x12u\x12v\x12w\x12x\x12y\x12z*\x0bY\x12{\x12|\x12}\x12~\x12\x7f\x12\x81\x00\x12\x81\x01\x12\x81\x02\x12\x81\x03\x12\x81\x04*\nY\x12\x81\x05\x12\x81\x06\x12\x81\x07\x12\x81\x08\x12\x81\t\x12\x81\n\x12\x81\x0b\x12\x81\x0c\x12\x81\r\x12\x81\x0e\x12\x81\x0f*\x0bY\x12\x81\x10\x12\x81\x11\x12\x81\x12\x12\x81\x13\x12\x81\x14\x12\x81\x15\x12\x81\x16\x12\x81\x17\x12\x81\x18\x12\x81\x19*\nY\x12\x81\x1a\x12\x81\x1b\x12\x81\x1c\x12\x81\x1d\x12\x81\x1e\x12\x81\x1f\x12\x81 \x12\x81!\x12\x81\"\x12\x81#\x12\x81$*\x0bY\x12\x81%\x12\x81&*\x02Y\x12\x81'\x12\x81(\x12\x81)\x12\x81*\x12\x81+\x12\x81,\x12\x81-\x12\x81.\x12\x81/\x12\x810*\nY\x12\x811\x12\x812\x12\x813\x12\x814*\x04Y\x12\x815\x12\x816\x12\x817\x12\x818*\x04Y\x12\x819\x12\x81:\x12\x81;\x12\x81<*\x04YQc\x87p\x08@\x05\x80###############################\x00\xc0#\x01\xc0#\x02\xc0#\x03\xc0#\x04\xc0#\x05\xc0#\x06\xc0#\x07\xc0#\x08\xc0#\t\xc0#\n\xc0#\x0b\xc0#\x0c\xc0#\r\xc0#\x0e\xc0#\x0f\xc0#\x10\xc0#\x11\xc0#\x12\xc0#\x13\xc0#\x14\xc0#\x15\xc0#\x16\xc0#\x17\xc0#\x18\xc0#\x19\xc0#\x1a\xc0#\x1b\xc0#\x1c\xc0#\x1d\xc0Qc" +file_data = b"M\x06\x00\x1e\x81=\x1e\x0etest.py\x00\x0f\x04A0\x00\x04A1\x00\x04f0\x00\x04f1\x00\x0cresult\x00/-5\x04a0\x00\x04a1\x00\x04a2\x00\x04a3\x00\x13\x15\x17\x19\x1b\x1d\x1f!#%')+1379;=?ACEGIKMOQSUWY[]_acegikmoqsuwy{}\x7f\x81\x01\x81\x03\x81\x05\x81\x07\x81\t\x81\x0b\x81\r\x81\x0f\x81\x11\x81\x13\x81\x15\x81\x17\x81\x19\x81\x1b\x81\x1d\x81\x1f\x81!\x81#\x81%\x81'\x81)\x81+\x81-\x81/\x811\x813\x815\x817\x819\x81;\x81=\x81?\x81A\x81C\x81E\x81G\x81I\x81K\x81M\x81O\x81Q\x81S\x81U\x81W\x81Y\x81[\x81]\x81_\x81a\x81c\x81e\x81g\x81i\x81k\x81m\x81o\x81q\x81s\x81u\x81w\x81y\x81{\x81}\x81\x7f\x82\x01\x82\x03\x82\x05\x82\x07\x82\t\x82\x0b\x82\r\x82\x0f\x82\x11\x82\x13\x82\x15\x82\x17\x82\x19\x82\x1b\x82\x1d\x82\x1f\x82!\x82#\x82%\x82'\x82)\x82+\x82-\x82/\x821\x823\x825\x827\x829\x82;\x82=\x82?\x82A\x82E\x82G\x82I\x82K\nname0\x00\nname1\x00\nname2\x00\nname3\x00\nname4\x00\nname5\x00\nname6\x00\nname7\x00\nname8\x00\nname9\x00$quite_a_long_name0\x00$quite_a_long_name1\x00$quite_a_long_name2\x00$quite_a_long_name3\x00$quite_a_long_name4\x00$quite_a_long_name5\x00$quite_a_long_name6\x00$quite_a_long_name7\x00$quite_a_long_name8\x00$quite_a_long_name9\x00&quite_a_long_name10\x00&quite_a_long_name11\x00\x05\x1ethis will be a string object 0\x00\x05\x1ethis will be a string object 1\x00\x05\x1ethis will be a string object 2\x00\x05\x1ethis will be a string object 3\x00\x05\x1ethis will be a string object 4\x00\x05\x1ethis will be a string object 5\x00\x05\x1ethis will be a string object 6\x00\x05\x1ethis will be a string object 7\x00\x05\x1ethis will be a string object 8\x00\x05\x1ethis will be a string object 9\x00\x06\x1dthis will be a bytes object 0\x00\x06\x1dthis will be a bytes object 1\x00\x06\x1dthis will be a bytes object 2\x00\x06\x1dthis will be a bytes object 3\x00\x06\x1dthis will be a bytes object 4\x00\x06\x1dthis will be a bytes object 5\x00\x06\x1dthis will be a bytes object 6\x00\x06\x1dthis will be a bytes object 7\x00\x06\x1dthis will be a bytes object 8\x00\x06\x1dthis will be a bytes object 9\x00\n\x07\x05\rconst tuple 0\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 1\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 2\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 3\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 4\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 5\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 6\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 7\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 8\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\n\x07\x05\rconst tuple 9\x00\x01\x02\x03\x07\x011\x07\x012\x07\x013\x82d\x10\x12\x01i@i@\x84\x18\x84\x1fT2\x00\x10\x024\x02\x16\x02T2\x01\x10\x034\x02\x16\x032\x02\x16\x042\x03\x16\x05\"\x80{\x16\x06Qc\x04\x82\x0c\x00\n\x02($$$\x11\x07\x16\x08\x10\x02\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04@\t\x08\n\x81\x0b Qc@\t\x08\x0b\x81\x0b@Qc@\t\x08\x0c\x81\x0b`QcH\t\n\r\x81\x0b` Qc\x82\x14\x00\x0c\x03h`$$$\x11\x07\x16\x08\x10\x03\x16\t2\x00\x16\n2\x01\x16\x0b2\x02\x16\x0c2\x03\x16\rQc\x04H\t\n\n\x81\x0b``QcH\t\n\x0b\x81\x0b\x80\x07QcH\t\n\x0c\x81\x0b\x80\x08QcH\t\n\r\x81\x0b\x80\tQc\xa08P:\x04\x80\x0b13///---997799<\x1f%\x1f\"\x1f%)\x1f\"//\x12\x0e\x12\x0f\x12\x10\x12\x11\x12\x12\x12\x13\x12\x14*\x07Y\x12\x15\x12\x16\x12\x17\x12\x18\x12\x19\x12\x1a\x12\x08\x12\x07*\x08Y\x12\x1b\x12\x1c\x12\t\x12\x1d\x12\x1e\x12\x1f*\x06Y\x12 \x12!\x12\"\x12#\x12$\x12%*\x06Y\x12&\x12'\x12(\x12)\x12*\x12+*\x06Y\x12,\x12-\x12.\x12/\x120*\x05Y\x121\x122\x123\x124\x125*\x05Y\x126\x127\x128\x129\x12:*\x05Y\x12;\x12<\x12=\x12>\x12?\x12@\x12A\x12B\x12C\x12D\x12E*\x0bY\x12F\x12G\x12H\x12I\x12J\x12K\x12L\x12M\x12N\x12O\x12P*\x0bY\x12Q\x12R\x12S\x12T\x12U\x12V\x12W\x12X\x12Y\x12Z*\nY\x12[\x12\\\x12]\x12^\x12_\x12`\x12a\x12b\x12c\x12d*\nY\x12e\x12f\x12g\x12h\x12i\x12j\x12k\x12l\x12m\x12n\x12o*\x0bY\x12p\x12q\x12r\x12s\x12t\x12u\x12v\x12w\x12x\x12y\x12z*\x0bY\x12{\x12|\x12}\x12~\x12\x7f\x12\x81\x00\x12\x81\x01\x12\x81\x02\x12\x81\x03\x12\x81\x04*\nY\x12\x81\x05\x12\x81\x06\x12\x81\x07\x12\x81\x08\x12\x81\t\x12\x81\n\x12\x81\x0b\x12\x81\x0c\x12\x81\r\x12\x81\x0e\x12\x81\x0f*\x0bY\x12\x81\x10\x12\x81\x11\x12\x81\x12\x12\x81\x13\x12\x81\x14\x12\x81\x15\x12\x81\x16\x12\x81\x17\x12\x81\x18\x12\x81\x19*\nY\x12\x81\x1a\x12\x81\x1b\x12\x81\x1c\x12\x81\x1d\x12\x81\x1e\x12\x81\x1f\x12\x81 \x12\x81!\x12\x81\"\x12\x81#\x12\x81$*\x0bY\x12\x81%\x12\x81&*\x02Y\x12\x81'\x12\x81(\x12\x81)\x12\x81*\x12\x81+\x12\x81,\x12\x81-\x12\x81.\x12\x81/\x12\x810*\nY\x12\x811\x12\x812\x12\x813\x12\x814*\x04Y\x12\x815\x12\x816\x12\x817\x12\x818*\x04Y\x12\x819\x12\x81:\x12\x81;\x12\x81<*\x04YQc\x87p\x08@\x05\x80###############################\x00\xc0#\x01\xc0#\x02\xc0#\x03\xc0#\x04\xc0#\x05\xc0#\x06\xc0#\x07\xc0#\x08\xc0#\t\xc0#\n\xc0#\x0b\xc0#\x0c\xc0#\r\xc0#\x0e\xc0#\x0f\xc0#\x10\xc0#\x11\xc0#\x12\xc0#\x13\xc0#\x14\xc0#\x15\xc0#\x16\xc0#\x17\xc0#\x18\xc0#\x19\xc0#\x1a\xc0#\x1b\xc0#\x1c\xc0#\x1d\xc0Qc" class File(io.IOBase): @@ -86,7 +86,9 @@ def __init__(self): self.off = 0 def ioctl(self, request, arg): - return 0 + if request == 4: # MP_STREAM_CLOSE + return 0 + return -1 def readinto(self, buf): buf[:] = memoryview(file_data)[self.off : self.off + len(buf)] @@ -112,7 +114,7 @@ def open(self, path, mode): def mount(): - os.mount(FS(), "/__remote") + vfs.mount(FS(), "/__remote") sys.path.insert(0, "/__remote") diff --git a/tests/pyboard.py b/tests/pyboard.py deleted file mode 120000 index 616773a313a18..0000000000000 --- a/tests/pyboard.py +++ /dev/null @@ -1 +0,0 @@ -../tools/cpboard.py \ No newline at end of file diff --git a/tests/run-internalbench.py b/tests/run-internalbench.py index c9f783e474c9c..99c6304afe9d6 100755 --- a/tests/run-internalbench.py +++ b/tests/run-internalbench.py @@ -8,6 +8,10 @@ from glob import glob from collections import defaultdict +run_tests_module = __import__("run-tests") +sys.path.append(run_tests_module.base_path("../tools")) +import pyboard + if os.name == "nt": MICROPYTHON = os.getenv( "MICROPY_MICROPYTHON", "../ports/windows/build-standard/micropython.exe" @@ -15,13 +19,39 @@ else: MICROPYTHON = os.getenv("MICROPY_MICROPYTHON", "../ports/unix/build-standard/micropython") +injected_bench_code = b""" +import time + +class bench_class: + ITERS = 20000000 + + @staticmethod + def run(test): + t = time.ticks_us() + test(bench_class.ITERS) + t = time.ticks_diff(time.ticks_us(), t) + s, us = divmod(t, 1_000_000) + print("{}.{:06}".format(s, us)) + +import sys +sys.modules['bench'] = bench_class +""" + -def run_tests(pyb, test_dict): +def execbench(pyb, filename, iters): + with open(filename, "rb") as f: + pyfile = f.read() + code = (injected_bench_code + pyfile).replace(b"20000000", str(iters).encode("utf-8")) + return pyb.exec(code).replace(b"\r\n", b"\n") + + +def run_tests(pyb, test_dict, iters): test_count = 0 testcase_count = 0 for base_test, tests in sorted(test_dict.items()): print(base_test + ":") + baseline = None for test_file in tests: # run MicroPython if pyb is None: @@ -36,20 +66,25 @@ def run_tests(pyb, test_dict): # run on pyboard pyb.enter_raw_repl() try: - output_mupy = pyb.execfile(test_file).replace(b"\r\n", b"\n") + output_mupy = execbench(pyb, test_file[0], iters) except pyboard.PyboardError: output_mupy = b"CRASH" - output_mupy = float(output_mupy.strip()) + try: + output_mupy = float(output_mupy.strip()) + except ValueError: + output_mupy = -1 test_file[1] = output_mupy testcase_count += 1 - test_count += 1 - baseline = None - for t in tests: if baseline is None: - baseline = t[1] - print(" %.3fs (%+06.2f%%) %s" % (t[1], (t[1] * 100 / baseline) - 100, t[0])) + baseline = test_file[1] + print( + " %.3fs (%+06.2f%%) %s" + % (test_file[1], (test_file[1] * 100 / baseline) - 100, test_file[0]) + ) + + test_count += 1 print("{} tests performed ({} individual testcases)".format(test_count, testcase_count)) @@ -58,27 +93,47 @@ def run_tests(pyb, test_dict): def main(): - cmd_parser = argparse.ArgumentParser(description="Run tests for MicroPython.") - cmd_parser.add_argument("--pyboard", action="store_true", help="run the tests on the pyboard") + cmd_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=f"""Run and manage tests for MicroPython. + +{run_tests_module.test_instance_description} +{run_tests_module.test_directory_description} +""", + epilog=run_tests_module.test_instance_epilog, + ) + cmd_parser.add_argument( + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" + ) + cmd_parser.add_argument( + "-b", "--baudrate", default=115200, help="the baud rate of the serial device" + ) + cmd_parser.add_argument("-u", "--user", default="micro", help="the telnet login username") + cmd_parser.add_argument("-p", "--password", default="python", help="the telnet login password") + cmd_parser.add_argument( + "-d", "--test-dirs", nargs="*", help="input test directories (if no files given)" + ) + cmd_parser.add_argument( + "-I", + "--iters", + type=int, + default=200_000, + help="number of test iterations, only for remote instances (default 200,000)", + ) cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() # Note pyboard support is copied over from run-tests.py, not tests, and likely needs revamping - if args.pyboard: - import pyboard - - pyb = pyboard.Pyboard("/dev/ttyACM0") - pyb.enter_raw_repl() - else: - pyb = None + pyb = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) if len(args.files) == 0: - if pyb is None: - # run PC tests - test_dirs = ("internal_bench",) + if args.test_dirs: + test_dirs = tuple(args.test_dirs) else: - # run pyboard tests - test_dirs = ("basics", "float", "pyb") + test_dirs = ("internal_bench",) + tests = sorted( test_file for test_files in (glob("{}/*.py".format(dir)) for dir in test_dirs) @@ -95,7 +150,7 @@ def main(): continue test_dict[m.group(1)].append([t, None]) - if not run_tests(pyb, test_dict): + if not run_tests(pyb, test_dict, args.iters): sys.exit(1) diff --git a/tests/run-multitests.py b/tests/run-multitests.py index 5ae8b8ea48014..e5458ffe0d00c 100755 --- a/tests/run-multitests.py +++ b/tests/run-multitests.py @@ -15,6 +15,8 @@ import subprocess import tempfile +run_tests_module = __import__("run-tests") + test_dir = os.path.abspath(os.path.dirname(__file__)) if os.path.abspath(sys.path[0]) == test_dir: @@ -27,13 +29,15 @@ if os.name == "nt": CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3.exe") - MICROPYTHON = os.getenv( - "MICROPY_MICROPYTHON", test_dir + "/../ports/windows/build-standard/micropython.exe" + MICROPYTHON = os.path.abspath( + os.getenv( + "MICROPY_MICROPYTHON", test_dir + "/../ports/windows/build-standard/micropython.exe" + ) ) else: CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") - MICROPYTHON = os.getenv( - "MICROPY_MICROPYTHON", test_dir + "/../ports/unix/build-standard/micropython" + MICROPYTHON = os.path.abspath( + os.getenv("MICROPY_MICROPYTHON", test_dir + "/../ports/unix/build-standard/micropython") ) # For diff'ing test output @@ -103,15 +107,14 @@ def output_metric(data): multitest.flush() """ -# The btstack implementation on Unix generates some spurious output that we -# can't control. Also other platforms may output certain warnings/errors that -# can be safely ignored. +# Some ports generate output we can't control, and that can be safely ignored. IGNORE_OUTPUT_MATCHES = ( - "libusb: error ", # It tries to open devices that it doesn't have access to (libusb prints unconditionally). + "libusb: error ", # unix btstack tries to open devices that it doesn't have access to (libusb prints unconditionally). "hci_transport_h2_libusb.c", # Same issue. We enable LOG_ERROR in btstack. - "USB Path: ", # Hardcoded in btstack's libusb transport. - "hci_number_completed_packet", # Warning from btstack. + "USB Path: ", # Hardcoded in unix btstack's libusb transport. + "hci_number_completed_packet", # Warning from unix btstack. "lld_pdu_get_tx_flush_nb HCI packet count mismatch (", # From ESP-IDF, see https://github.com/espressif/esp-idf/issues/5105 + " ets_task(", # ESP8266 port debug output ) @@ -129,6 +132,11 @@ def get_host_ip(_ip_cache=[]): return _ip_cache[0] +def decode(output): + # Convenience function to convert raw process or serial output to ASCII + return str(output, "ascii", "backslashreplace") + + class PyInstance: def __init__(self): pass @@ -155,6 +163,7 @@ def start_file(self, filename, prepend="", append=""): class PyInstanceSubProcess(PyInstance): def __init__(self, argv, env=None): self.argv = argv + self.cwd = None self.env = {n: v for n, v in (i.split("=") for i in env)} if env else None self.popen = None self.finished = True @@ -163,8 +172,9 @@ def __str__(self): return self.argv[0].rsplit("/")[-1] def prepare_script_from_file(self, filename, prepend, append): - # Make tests run in an isolated environment (i.e. `import io` would - # otherwise get the `tests/io` directory). + # Make tests run in the directory of the test file, and in an isolated environment + # (i.e. `import io` would otherwise get the `tests/io` directory). + self.cwd = os.path.dirname(filename) remove_cwd_from_sys_path = b"import sys\nsys.path.remove('')\n\n" return remove_cwd_from_sys_path + super().prepare_script_from_file( filename, prepend, append @@ -179,12 +189,13 @@ def run_script(self, script): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, input=script, + cwd=self.cwd, env=self.env, ) output = p.stdout except subprocess.CalledProcessError as er: err = er - return str(output.strip(), "ascii"), err + return decode(output.strip()), err def start_script(self, script): self.popen = subprocess.Popen( @@ -192,6 +203,7 @@ def start_script(self, script): stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + cwd=self.cwd, env=self.env, ) self.finished = False @@ -210,7 +222,7 @@ def readline(self): self.finished = self.popen.poll() is not None return None, None else: - return str(out.rstrip(), "ascii"), None + return decode(out.rstrip()), None def write(self, data): self.popen.stdin.write(data) @@ -222,21 +234,12 @@ def is_finished(self): def wait_finished(self): self.popen.wait() out = self.popen.stdout.read() - return str(out, "ascii"), "" + return decode(out), "" class PyInstancePyboard(PyInstance): - @staticmethod - def map_device_shortcut(device): - if device[0] == "a" and device[1:].isdigit(): - return "/dev/ttyACM" + device[1:] - elif device[0] == "u" and device[1:].isdigit(): - return "/dev/ttyUSB" + device[1:] - else: - return device - def __init__(self, device): - device = self.map_device_shortcut(device) + device = device self.device = device self.pyb = pyboard.Pyboard(device) self.pyb.enter_raw_repl() @@ -257,7 +260,7 @@ def run_script(self, script): output = self.pyb.exec_(script) except pyboard.PyboardError as er: err = er - return str(output.strip(), "ascii"), err + return decode(output.strip()), err def start_script(self, script): self.pyb.enter_raw_repl() @@ -276,13 +279,13 @@ def readline(self): if out.endswith(b"\x04"): self.finished = True out = out[:-1] - err = str(self.pyb.read_until(1, b"\x04"), "ascii") + err = decode(self.pyb.read_until(1, b"\x04")) err = err[:-1] if not out and not err: return None, None else: err = None - return str(out.rstrip(), "ascii"), err + return decode(out.rstrip()), err def write(self, data): self.pyb.serial.write(data) @@ -292,7 +295,7 @@ def is_finished(self): def wait_finished(self): out, err = self.pyb.follow(10, None) - return str(out, "ascii"), str(err, "ascii") + return decode(out), decode(err) def prepare_test_file_list(test_files): @@ -483,9 +486,7 @@ def print_diff(a, b): def run_tests(test_files, instances_truth, instances_test): - skipped_tests = [] - passed_tests = [] - failed_tests = [] + test_results = [] for test_file, num_instances in test_files: instances_str = "|".join(str(instances_test[i]) for i in range(num_instances)) @@ -521,13 +522,13 @@ def run_tests(test_files, instances_truth, instances_test): # Print result of test if skip: print("skip") - skipped_tests.append(test_file) + test_results.append((test_file, "skip", "")) elif output_test == output_truth: print("pass") - passed_tests.append(test_file) + test_results.append((test_file, "pass", "")) else: print("FAIL") - failed_tests.append(test_file) + test_results.append((test_file, "fail", "")) if not cmd_args.show_output: print("### TEST ###") print(output_test, end="") @@ -544,15 +545,7 @@ def run_tests(test_files, instances_truth, instances_test): if cmd_args.show_output: print() - print("{} tests performed".format(len(skipped_tests) + len(passed_tests) + len(failed_tests))) - print("{} tests passed".format(len(passed_tests))) - - if skipped_tests: - print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests))) - if failed_tests: - print("{} tests failed: {}".format(len(failed_tests), " ".join(failed_tests))) - - return not failed_tests + return test_results def main(): @@ -560,16 +553,24 @@ def main(): cmd_parser = argparse.ArgumentParser( description="Run network tests for MicroPython", + epilog=( + run_tests_module.test_instance_epilog + + "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + ), formatter_class=argparse.RawTextHelpFormatter, ) cmd_parser.add_argument( "-s", "--show-output", action="store_true", help="show test output after running" ) cmd_parser.add_argument( - "-t", "--trace-output", action="store_true", help="trace test output while running" + "-c", "--trace-output", action="store_true", help="trace test output while running" ) cmd_parser.add_argument( - "-i", "--instance", action="append", default=[], help="instance(s) to run the tests on" + "-t", + "--test-instance", + action="append", + default=[], + help="instance(s) to run the tests on", ) cmd_parser.add_argument( "-p", @@ -578,13 +579,11 @@ def main(): default=1, help="repeat the test with this many permutations of the instance order", ) - cmd_parser.epilog = ( - "Supported instance types:\r\n" - " -i pyb: physical device (eg. pyboard) on provided repl port.\n" - " -i micropython unix micropython instance, path customised with MICROPY_MICROPYTHON env.\n" - " -i cpython desktop python3 instance, path customised with MICROPY_CPYTHON3 env.\n" - " -i exec: custom program run on provided path.\n" - "Each instance arg can optionally have custom env provided, eg. ,ENV=VAR,ENV=VAR...\n" + cmd_parser.add_argument( + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", ) cmd_parser.add_argument("files", nargs="+", help="input test files") cmd_args = cmd_parser.parse_args() @@ -598,33 +597,36 @@ def main(): instances_truth = [PyInstanceSubProcess([PYTHON_TRUTH]) for _ in range(max_instances)] instances_test = [] - for i in cmd_args.instance: + for i in cmd_args.test_instance: # Each instance arg is ,ENV=VAR,ENV=VAR... i = i.split(",") cmd = i[0] env = i[1:] if cmd.startswith("exec:"): instances_test.append(PyInstanceSubProcess([cmd[len("exec:") :]], env)) - elif cmd == "micropython": + elif cmd == "unix": instances_test.append(PyInstanceSubProcess([MICROPYTHON], env)) elif cmd == "cpython": instances_test.append(PyInstanceSubProcess([CPYTHON3], env)) - elif cmd.startswith("pyb:"): - instances_test.append(PyInstancePyboard(cmd[len("pyb:") :])) + elif cmd == "webassembly" or cmd.startswith("execpty:"): + print("unsupported instance string: {}".format(cmd), file=sys.stderr) + sys.exit(2) else: - print("unknown instance string: {}".format(cmd), file=sys.stderr) - sys.exit(1) + device = run_tests_module.convert_device_shortcut_to_real_device(cmd) + instances_test.append(PyInstancePyboard(device)) for _ in range(max_instances - len(instances_test)): instances_test.append(PyInstanceSubProcess([MICROPYTHON])) + os.makedirs(cmd_args.result_dir, exist_ok=True) all_pass = True try: for i, instances_test_permutation in enumerate(itertools.permutations(instances_test)): if i >= cmd_args.permutations: break - all_pass &= run_tests(test_files, instances_truth, instances_test_permutation) + test_results = run_tests(test_files, instances_truth, instances_test_permutation) + all_pass &= run_tests_module.create_test_report(cmd_args, test_results) finally: for i in instances_truth: diff --git a/tests/run-natmodtests.py b/tests/run-natmodtests.py index 85ac92672a12a..6d2a975b82a0b 100755 --- a/tests/run-natmodtests.py +++ b/tests/run-natmodtests.py @@ -9,7 +9,7 @@ import sys import argparse -#CIRCUITPY-CHANGE: no pyboard +run_tests_module = __import__("run-tests") # Paths for host executables CPYTHON3 = os.getenv("MICROPY_CPYTHON3", "python3") @@ -17,23 +17,42 @@ NATMOD_EXAMPLE_DIR = "../examples/natmod/" -#CIRCUITPY-CHANGE: different TEST_MAPPINGS +# CIRCUITPY-CHANGE: different TEST_MAPPINGS # Supported tests and their corresponding mpy module TEST_MAPPINGS = { "heapq": "heapq/heapq_$(ARCH).mpy", "random": "random/random_$(ARCH).mpy", "re": "re/re_$(ARCH).mpy", - "zlib": "zlib/zlib_$(ARCH).mpy", } +# Supported architectures for native mpy modules +AVAILABLE_ARCHS = ( + "x86", + "x64", + "armv6", + "armv6m", + "armv7m", + "armv7em", + "armv7emsp", + "armv7emdp", + "xtensa", + "xtensawin", + "rv32imc", +) + +ARCH_MAPPINGS = {"armv7em": "armv7m"} + # Code to allow a target MicroPython to import an .mpy from RAM injected_import_hook_code = """\ -import sys, os, io +# CIRCUITPY-CHANGE: no vfs, but still have os +import sys, io, os class __File(io.IOBase): def __init__(self): self.off = 0 def ioctl(self, request, arg): - return 0 + if request == 4: # MP_STREAM_CLOSE + return 0 + return -1 def readinto(self, buf): buf[:] = memoryview(__buf)[self.off:self.off + len(buf)] self.off += len(buf) @@ -50,8 +69,10 @@ def stat(self, path): raise OSError(-2) # ENOENT def open(self, path, mode): return __File() +# CIRCUITPY-CHANGE: no vfs, but still have os os.mount(__FS(), '/__remote') sys.path.insert(0, '/__remote') +{import_prelude} sys.modules['{}'] = __import__('__injected') """ @@ -88,17 +109,45 @@ def run_script(self, script): output = self.pyb.exec_(script) output = output.replace(b"\r\n", b"\n") return output, None - except pyboard.PyboardError as er: + except run_tests_module.pyboard.PyboardError as er: return b"", er -def run_tests(target_truth, target, args, stats): +def detect_architecture(target): + with open("./feature_check/target_info.py", "rb") as f: + target_info_data = f.read() + result_out, error = target.run_script(target_info_data) + if error is not None: + return None, None, error + info = result_out.split(b" ") + if len(info) < 2: + return None, None, "unexpected target info: {}".format(info) + platform = info[0].strip().decode() + arch = info[1].strip().decode() + if arch not in AVAILABLE_ARCHS: + if arch == "None": + return None, None, "the target does not support dynamic modules" + else: + return None, None, "{} is not a supported architecture".format(arch) + return platform, arch, None + + +def run_tests(target_truth, target, args, resolved_arch): + global injected_import_hook_code + + prelude = "" + if args.begin: + prelude = args.begin.read() + injected_import_hook_code = injected_import_hook_code.replace("{import_prelude}", prelude) + + test_results = [] for test_file in args.files: # Find supported test + test_file_basename = os.path.basename(test_file) for k, v in TEST_MAPPINGS.items(): - if test_file.find(k) != -1: + if test_file_basename.startswith(k): test_module = k - test_mpy = v.replace("$(ARCH)", args.arch) + test_mpy = v.replace("$(ARCH)", resolved_arch) break else: print("---- {} - no matching mpy".format(test_file)) @@ -114,9 +163,11 @@ def run_tests(target_truth, target, args, stats): with open(NATMOD_EXAMPLE_DIR + test_mpy, "rb") as f: test_script += b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n" except OSError: - print("---- {} - mpy file not compiled".format(test_file)) + test_results.append((test_file, "skip", "mpy file not compiled")) + print("skip {} - mpy file not compiled".format(test_file)) continue test_script += bytes(injected_import_hook_code.format(test_module), "ascii") + test_script += b"print('START TEST')\n" test_script += test_file_data # Run test under MicroPython @@ -124,8 +175,18 @@ def run_tests(target_truth, target, args, stats): # Work out result of test extra = "" + result_out = result_out.removeprefix(b"START TEST\n") if error is None and result_out == b"SKIP\n": result = "SKIP" + elif ( + error is not None + and error.args[0] == "exception" + and error.args[1] == b"" + and b"MemoryError" in error.args[2] + ): + # Test had a MemoryError before anything (should be at least "START TEST") + # was printed, so the test is too big for the target. + result = "LRGE" elif error is not None: result = "FAIL" extra = " - " + str(error) @@ -146,55 +207,86 @@ def run_tests(target_truth, target, args, stats): result = "pass" # Accumulate statistics - stats["total"] += 1 if result == "pass": - stats["pass"] += 1 + test_results.append((test_file, "pass", "")) elif result == "SKIP": - stats["skip"] += 1 + test_results.append((test_file, "skip", "")) + elif result == "LRGE": + test_results.append((test_file, "skip", "too large")) else: - stats["fail"] += 1 + test_results.append((test_file, "fail", "")) # Print result print("{:4} {}{}".format(result, test_file, extra)) + return test_results + def main(): cmd_parser = argparse.ArgumentParser( - description="Run dynamic-native-module tests under MicroPython" + description="Run dynamic-native-module tests under MicroPython", + epilog=run_tests_module.test_instance_epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + cmd_parser.add_argument( + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" ) + cmd_parser.add_argument("--baudrate", default=115200, help="baud rate of the serial device") + cmd_parser.add_argument("--user", default="micro", help="telnet login username") + cmd_parser.add_argument("--password", default="python", help="telnet login password") cmd_parser.add_argument( - "-p", "--pyboard", action="store_true", help="run tests via pyboard.py" + "-a", "--arch", choices=AVAILABLE_ARCHS, help="override native architecture of the target" ) cmd_parser.add_argument( - "-d", "--device", default="/dev/ttyACM0", help="the device for pyboard.py" + "-b", + "--begin", + type=argparse.FileType("rt"), + default=None, + help="prologue python file to execute before module import", ) cmd_parser.add_argument( - "-a", "--arch", default="x64", help="native architecture of the target" + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", ) cmd_parser.add_argument("files", nargs="*", help="input test files") args = cmd_parser.parse_args() target_truth = TargetSubprocess([CPYTHON3]) - if args.pyboard: - target = TargetPyboard(pyboard.Pyboard(args.device)) - else: + target = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) + if target is None: + # Use the unix port of MicroPython. target = TargetSubprocess([MICROPYTHON]) + else: + # Use a remote target. + target = TargetPyboard(target) - stats = {"total": 0, "pass": 0, "fail": 0, "skip": 0} - run_tests(target_truth, target, args, stats) + if hasattr(args, "arch") and args.arch is not None: + target_arch = args.arch + target_platform = None + else: + target_platform, target_arch, error = detect_architecture(target) + if error: + print("Cannot run tests: {}".format(error)) + sys.exit(1) + target_arch = ARCH_MAPPINGS.get(target_arch, target_arch) + + if target_platform: + print("platform={} ".format(target_platform), end="") + print("arch={}".format(target_arch)) + + os.makedirs(args.result_dir, exist_ok=True) + test_results = run_tests(target_truth, target, args, target_arch) + res = run_tests_module.create_test_report(args, test_results) target.close() target_truth.close() - print("{} tests performed".format(stats["total"])) - print("{} tests passed".format(stats["pass"])) - if stats["fail"]: - print("{} tests failed".format(stats["fail"])) - if stats["skip"]: - print("{} tests skipped".format(stats["skip"])) - - if stats["fail"]: + if not res: sys.exit(1) diff --git a/tests/run-perfbench.py b/tests/run-perfbench.py index 81d873c45997d..039d11a36111e 100755 --- a/tests/run-perfbench.py +++ b/tests/run-perfbench.py @@ -10,10 +10,9 @@ import argparse from glob import glob -sys.path.append("../tools") -import pyboard +run_tests_module = __import__("run-tests") -prepare_script_for_target = __import__("run-tests").prepare_script_for_target +prepare_script_for_target = run_tests_module.prepare_script_for_target # Paths for host executables if os.name == "nt": @@ -45,12 +44,12 @@ def run_script_on_target(target, script): output = b"" err = None - if isinstance(target, pyboard.Pyboard): + if hasattr(target, "enter_raw_repl"): # Run via pyboard interface try: target.enter_raw_repl() output = target.exec_(script) - except pyboard.PyboardError as er: + except run_tests_module.pyboard.PyboardError as er: err = er else: # Run local executable @@ -90,9 +89,9 @@ def run_benchmark_on_target(target, script): def run_benchmarks(args, target, param_n, param_m, n_average, test_list): + test_results = [] skip_complex = run_feature_test(target, "complex") != "complex" skip_native = run_feature_test(target, "native_check") != "native" - target_had_error = False for test_file in sorted(test_list): print(test_file + ": ", end="") @@ -105,6 +104,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): and test_file.find("viper_") != -1 ) if skip: + test_results.append((test_file, "skip", "")) print("SKIP") continue @@ -122,9 +122,10 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): f.write(test_script) # Process script through mpy-cross if needed - if isinstance(target, pyboard.Pyboard) or args.via_mpy: + if hasattr(target, "enter_raw_repl") or args.via_mpy: crash, test_script_target = prepare_script_for_target(args, script_text=test_script) if crash: + test_results.append((test_file, "fail", "preparation")) print("CRASH:", test_script_target) continue else: @@ -162,10 +163,13 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): error = "FAIL truth" if error is not None: - if not error.startswith("SKIP"): - target_had_error = True + if error.startswith("SKIP"): + test_results.append((test_file, "skip", error)) + else: + test_results.append((test_file, "fail", error)) print(error) else: + test_results.append((test_file, "pass", "")) t_avg, t_sd = compute_stats(times) s_avg, s_sd = compute_stats(scores) print( @@ -179,7 +183,7 @@ def run_benchmarks(args, target, param_n, param_m, n_average, test_list): sys.stdout.flush() - return target_had_error + return test_results def parse_output(filename): @@ -190,7 +194,13 @@ def parse_output(filename): m = int(m.split("=")[1]) data = [] for l in f: - if ": " in l and ": SKIP" not in l and "CRASH: " not in l: + if ( + ": " in l + and ": SKIP" not in l + and "CRASH: " not in l + and "skipped: " not in l + and "failed: " not in l + ): name, values = l.strip().split(": ") values = tuple(float(v) for v in values.split()) data.append((name,) + values) @@ -246,17 +256,17 @@ def compute_diff(file1, file2, diff_score): def main(): cmd_parser = argparse.ArgumentParser(description="Run benchmarks for MicroPython") cmd_parser.add_argument( - "-t", "--diff-time", action="store_true", help="diff time outputs from a previous run" + "-m", "--diff-time", action="store_true", help="diff time outputs from a previous run" ) cmd_parser.add_argument( "-s", "--diff-score", action="store_true", help="diff score outputs from a previous run" ) cmd_parser.add_argument( - "-p", "--pyboard", action="store_true", help="run tests via pyboard.py" - ) - cmd_parser.add_argument( - "-d", "--device", default="/dev/ttyACM0", help="the device for pyboard.py" + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" ) + cmd_parser.add_argument("--baudrate", default=115200, help="baud rate of the serial device") + cmd_parser.add_argument("--user", default="micro", help="telnet login username") + cmd_parser.add_argument("--password", default="python", help="telnet login password") cmd_parser.add_argument("-a", "--average", default="8", help="averaging number") cmd_parser.add_argument( "--emit", default="bytecode", help="MicroPython emitter to use (bytecode or native)" @@ -264,6 +274,12 @@ def main(): cmd_parser.add_argument("--heapsize", help="heapsize to use (use default if not specified)") cmd_parser.add_argument("--via-mpy", action="store_true", help="compile code to .mpy first") cmd_parser.add_argument("--mpy-cross-flags", default="", help="flags to pass to mpy-cross") + cmd_parser.add_argument( + "-r", + "--result-dir", + default=run_tests_module.base_path("results"), + help="directory for test results", + ) cmd_parser.add_argument( "N", nargs=1, help="N parameter (approximate target CPU frequency in MHz)" ) @@ -282,15 +298,18 @@ def main(): M = int(args.M[0]) n_average = int(args.average) - if args.pyboard: - if not args.mpy_cross_flags: - args.mpy_cross_flags = "-march=armv7m" - target = pyboard.Pyboard(args.device) - target.enter_raw_repl() - else: + target = run_tests_module.get_test_instance( + args.test_instance, args.baudrate, args.user, args.password + ) + if target is None: + # Use the unix port of MicroPython. target = [MICROPYTHON, "-X", "emit=" + args.emit] if args.heapsize is not None: target.extend(["-X", "heapsize=" + args.heapsize]) + else: + # Use a remote target. + if not args.mpy_cross_flags: + args.mpy_cross_flags = "-march=armv7m" if len(args.files) == 0: tests_skip = ("benchrun.py",) @@ -307,13 +326,15 @@ def main(): print("N={} M={} n_average={}".format(N, M, n_average)) - target_had_error = run_benchmarks(args, target, N, M, n_average, tests) + os.makedirs(args.result_dir, exist_ok=True) + test_results = run_benchmarks(args, target, N, M, n_average, tests) + res = run_tests_module.create_test_report(args, test_results) - if isinstance(target, pyboard.Pyboard): + if hasattr(target, "exit_raw_repl"): target.exit_raw_repl() target.close() - if target_had_error: + if not res: sys.exit(1) diff --git a/tests/run-tests-exp.py b/tests/run-tests-exp.py deleted file mode 100644 index bbb057f4cede9..0000000000000 --- a/tests/run-tests-exp.py +++ /dev/null @@ -1,94 +0,0 @@ -# -# This is minimal MicroPython variant of run-tests.py script, which uses -# .exp files as generated by run-tests.py --write-exp. It is useful to run -# testsuite on systems which have neither CPython3 nor unix shell. -# This script is intended to be run by the same interpreter executable -# which is to be tested, so should use minimal language functionality. -# -import sys -import os - - -tests = ["basics", "micropython", "float", "import", "io", " misc", "unicode", "extmod", "unix"] - -if sys.platform == "win32": - MICROPYTHON = "micropython.exe" -else: - MICROPYTHON = "micropython" - - -def should_skip(test): - if test.startswith("native"): - return True - if test.startswith("viper"): - return True - - -test_count = 0 -passed_count = 0 -skip_count = 0 - -for suite in tests: - # print("Running in: %s" % suite) - if sys.platform == "win32": - # dir /b prints only contained filenames, one on a line - # http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/dir.mspx - r = os.system("dir /b %s/*.py >tests.lst" % suite) - else: - r = os.system("ls %s/*.py | xargs -n1 basename >tests.lst" % suite) - assert r == 0 - - with open("tests.lst") as f: - testcases = f.readlines() - testcases = [l[:-1] for l in testcases] - assert testcases, "No tests found in dir '%s', which is implausible" % suite - # print(testcases) - for t in testcases: - if t == "native_check.py": - continue - - qtest = "%s/%s" % (suite, t) - - if should_skip(t): - print("skip " + qtest) - skip_count += 1 - continue - - exp = None - try: - f = open(qtest + ".exp") - exp = f.read() - f.close() - except OSError: - pass - - if exp is not None: - # print("run " + qtest) - r = os.system(MICROPYTHON + " %s >.tst.out" % qtest) - if r == 0: - f = open(".tst.out") - out = f.read() - f.close() - else: - out = "CRASH" - - if out == "SKIP\n": - print("skip " + qtest) - skip_count += 1 - else: - if out == exp: - print("pass " + qtest) - passed_count += 1 - else: - print("FAIL " + qtest) - - test_count += 1 - else: - skip_count += 1 - -print("%s tests performed" % test_count) -print("%s tests passed" % passed_count) -if test_count != passed_count: - print("%s tests failed" % (test_count - passed_count)) -if skip_count: - print("%s tests skipped" % skip_count) diff --git a/tests/run-tests-exp.sh b/tests/run-tests-exp.sh deleted file mode 100755 index 177090cd8db93..0000000000000 --- a/tests/run-tests-exp.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh -# -# This is plain shell variant of run-tests.py script, which uses .exp files -# as generated by run-tests.py --write-exp. It is useful to run testsuite -# on embedded systems which don't have CPython3. -# - -RM="rm -f" -MP_PY=micropython - -numtests=0 -numtestcases=0 -numpassed=0 -numskipped=0 -numfailed=0 -nameskipped= -namefailed= - -if [ $# -eq 0 ] -then - tests="basics/*.py micropython/*.py float/*.py import/*.py io/*.py misc/*.py unicode/*.py extmod/*.py unix/*.py" -else - tests="$@" -fi - -for infile in $tests -do - basename=`basename $infile .py` - outfile=${basename}.py.out - expfile=$infile.exp - - $MP_PY $infile > $outfile - numtestcases=$(expr $numtestcases + $(cat $expfile | wc -l)) - - if grep -q "SKIP\|SyntaxError: invalid micropython decorator" $outfile - then - # we don't count tests that explicitly ask to be skipped - # we don't count tests that fail due to unsupported decorator - echo "skip $infile" - $RM $outfile - numskipped=$(expr $numskipped + 1) - nameskipped="$nameskipped $basename" - else - diff --brief $expfile $outfile > /dev/null - - if [ $? -eq 0 ] - then - echo "pass $infile" - $RM $outfile - numpassed=$(expr $numpassed + 1) - else - echo "FAIL $infile" - numfailed=$(expr $numfailed + 1) - namefailed="$namefailed $basename" - fi - fi - - numtests=$(expr $numtests + 1) -done - -echo "$numtests tests performed ($numtestcases individual testcases)" -echo "$numpassed tests passed" -if [ $numskipped != 0 ] -then - echo "$numskipped tests skipped -$nameskipped" -fi -if [ $numfailed != 0 ] -then - echo "$numfailed tests failed -$namefailed" - exit 1 -else - exit 0 -fi diff --git a/tests/run-tests.py b/tests/run-tests.py index 52204cc9fe2ee..71570292ce7f7 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -3,9 +3,11 @@ import os import subprocess import sys +import sysconfig import platform import argparse import inspect +import json import re from glob import glob import multiprocessing @@ -13,13 +15,15 @@ import threading import tempfile -# Maximum time to run a PC-based test, in seconds. -TEST_TIMEOUT = 30 +# Maximum time to run a single test, in seconds. +TEST_TIMEOUT = float(os.environ.get("MICROPY_TEST_TIMEOUT", 30)) # See stackoverflow.com/questions/2632199: __file__ nor sys.argv[0] # are guaranteed to always work, this one should though. BASEPATH = os.path.dirname(os.path.abspath(inspect.getsourcefile(lambda: None))) +RV32_ARCH_FLAGS = {"zba": 1 << 0} + def base_path(*p): return os.path.abspath(os.path.join(BASEPATH, *p)).replace("\\", "/") @@ -47,6 +51,8 @@ def base_path(*p): # (not site packages which may clash with u-module names), and improve start up time. CPYTHON3_CMD = [CPYTHON3, "-BS"] +# File with the test results. +RESULTS_FILE = "_results.json" # For diff'ing test output DIFF = os.getenv("MICROPY_DIFF", "diff -u") @@ -54,14 +60,38 @@ def base_path(*p): # Set PYTHONIOENCODING so that CPython will use utf-8 on systems which set another encoding in the locale os.environ["PYTHONIOENCODING"] = "utf-8" + +def normalize_newlines(data): + """Normalize newline variations to \\n. + + Only normalizes actual line endings, not literal \\r characters in strings. + Handles \\r\\r\\n and \\r\\n cases to ensure consistent comparison + across different platforms and terminals. + """ + if isinstance(data, bytes): + # Handle PTY double-newline issue first + data = data.replace(b"\r\r\n", b"\n") + # Then handle standard Windows line endings + data = data.replace(b"\r\n", b"\n") + # Don't convert standalone \r as it might be literal content + return data + + # Code to allow a target MicroPython to import an .mpy from RAM +# Note: the module is named `__injected_test` but it needs to have `__name__` set to +# `__main__` so that the test sees itself as the main module, eg so unittest works. injected_import_hook_code = """\ -import sys, os, io +import sys, os, io, vfs class __File(io.IOBase): def __init__(self): + module = sys.modules['__injected_test'] + module.__name__ = '__main__' + sys.modules['__main__'] = module self.off = 0 def ioctl(self, request, arg): - return 0 + if request == 4: # MP_STREAM_CLOSE + return 0 + return -1 def readinto(self, buf): buf[:] = memoryview(__buf)[self.off:self.off + len(buf)] self.off += len(buf) @@ -73,18 +103,235 @@ def umount(self): pass def chdir(self, path): pass + def getcwd(self): + return "" def stat(self, path): if path == '__injected_test.mpy': - return tuple(0 for _ in range(10)) + return (0,0,0,0,0,0,0,0,0,0) else: - raise OSError(-2) # ENOENT + raise OSError(2) # ENOENT def open(self, path, mode): + self.stat(path) return __File() -os.mount(__FS(), '/__vfstest') +vfs.mount(__FS(), '/__vfstest') os.chdir('/__vfstest') +{import_prologue} __import__('__injected_test') """ +# Platforms associated with the unix port, values of `sys.platform`. +PC_PLATFORMS = ("darwin", "linux", "win32") + +# Mapping from `sys.platform` to the port name, for special cases. +# See `platform_to_port()` function. +platform_to_port_map = {"pyboard": "stm32", "WiPy": "cc3200"} +platform_to_port_map.update({p: "unix" for p in PC_PLATFORMS}) + +# Tests to skip for values of the `--via-mpy` argument. +via_mpy_tests_to_skip = { + # Skip the following when mpy is enabled. + True: ( + # These print out the filename and that's expected to match the .py name. + "import/import_file.py", + "io/argv.py", + "misc/sys_settrace_features.py", + "misc/sys_settrace_generator.py", + "misc/sys_settrace_loop.py", + ), +} + +# Tests to skip for specific emitters. +emitter_tests_to_skip = { + # Some tests are known to fail with native emitter. + # Remove them from the below when they work. + "native": ( + # These require raise_varargs. + "basics/gen_yield_from_close.py", + "basics/try_finally_return2.py", + "basics/try_reraise.py", + "basics/try_reraise2.py", + "misc/features.py", + # These require checking for unbound local. + "basics/annotate_var.py", + "basics/del_deref.py", + "basics/del_local.py", + "basics/scope_implicit.py", + "basics/unboundlocal.py", + # These require "raise from". + "basics/exception_chain.py", + # These require stack-allocated slice optimisation. + "micropython/heapalloc_slice.py", + # These require running the scheduler. + "micropython/schedule.py", + "extmod/asyncio_event_queue.py", + "extmod/asyncio_iterator_event.py", + # These require sys.exc_info(). + "misc/sys_exc_info.py", + # These require sys.settrace(). + "misc/sys_settrace_cov.py", + "misc/sys_settrace_features.py", + "misc/sys_settrace_generator.py", + "misc/sys_settrace_loop.py", + # These are bytecode-specific tests. + "stress/bytecode_limit.py", + ), +} + +# Tests to skip on specific targets. +# These are tests that are difficult to detect that they should not be run on the given target. +platform_tests_to_skip = { + "minimal": ( + "basics/class_inplace_op.py", # all special methods not supported + "basics/subclass_native_init.py", # native subclassing corner cases not support + "micropython/opt_level.py", # don't assume line numbers are stored + ), + "nrf": ( + "basics/io_buffered_writer.py", + "basics/io_bytesio_cow.py", + "basics/io_bytesio_ext.py", + "basics/io_bytesio_ext2.py", + "basics/io_iobase.py", + "basics/io_stringio1.py", + "basics/io_stringio_base.py", + "basics/io_stringio_with.py", + "basics/io_write_ext.py", + "basics/memoryview1.py", # no item assignment for memoryview + "extmod/random_basic.py", # unimplemented: random.seed + "micropython/opt_level.py", # no support for line numbers + "misc/non_compliant.py", # no item assignment for bytearray + ), + "renesas-ra": ( + "extmod/time_time_ns.py", # RA fsp rtc function doesn't support nano sec info + ), + "rp2": ( + # Skip thread tests that require more that 2 threads. + "thread/stress_heap.py", + "thread/thread_lock2.py", + "thread/thread_lock3.py", + "thread/thread_shared2.py", + ), + "webassembly": ( + "basics/string_format_modulo.py", # can't print nulls to stdout + "basics/string_strip.py", # can't print nulls to stdout + "extmod/asyncio_basic2.py", + "extmod/asyncio_cancel_self.py", + "extmod/asyncio_current_task.py", + "extmod/asyncio_exception.py", + "extmod/asyncio_gather_finished_early.py", + "extmod/asyncio_get_event_loop.py", + "extmod/asyncio_heaplock.py", + "extmod/asyncio_loop_stop.py", + "extmod/asyncio_new_event_loop.py", + "extmod/asyncio_threadsafeflag.py", + "extmod/asyncio_wait_for_fwd.py", + "extmod/asyncio_event_queue.py", + "extmod/asyncio_iterator_event.py", + "extmod/asyncio_wait_for_linked_task.py", + "extmod/binascii_a2b_base64.py", + "extmod/deflate_compress_memory_error.py", # tries to allocate unlimited memory + "extmod/re_stack_overflow.py", + "extmod/time_res.py", + "extmod/vfs_posix.py", + "extmod/vfs_posix_enoent.py", + "extmod/vfs_posix_paths.py", + "extmod/vfs_userfs.py", + "micropython/emg_exc.py", + "micropython/extreme_exc.py", + "micropython/heapalloc_exc_compressed_emg_exc.py", + ), + "WiPy": ( + "misc/print_exception.py", # requires error reporting full + ), + "zephyr": ( + # Skip thread tests that require more than 4 threads. + "thread/stress_heap.py", + "thread/thread_lock3.py", + ), +} + +# These tests don't test float explicitly but rather use it to perform the test. +tests_requiring_float = ( + "extmod/asyncio_basic.py", + "extmod/asyncio_basic2.py", + "extmod/asyncio_cancel_task.py", + "extmod/asyncio_event.py", + "extmod/asyncio_fair.py", + "extmod/asyncio_gather.py", + "extmod/asyncio_gather_notimpl.py", + "extmod/asyncio_get_event_loop.py", + "extmod/asyncio_iterator_event.py", + "extmod/asyncio_lock.py", + "extmod/asyncio_task_done.py", + "extmod/asyncio_wait_for.py", + "extmod/asyncio_wait_for_fwd.py", + "extmod/asyncio_wait_for_linked_task.py", + "extmod/asyncio_wait_task.py", + "extmod/json_dumps_float.py", + "extmod/json_loads_float.py", + "extmod/random_extra_float.py", + "extmod/select_poll_eintr.py", + "extmod/tls_threads.py", + "extmod/uctypes_le_float.py", + "extmod/uctypes_native_float.py", + "extmod/uctypes_sizeof_float.py", + "misc/rge_sm.py", + "ports/unix/ffi_float.py", + "ports/unix/ffi_float2.py", +) + +# These tests don't test slice explicitly but rather use it to perform the test. +tests_requiring_slice = ( + "basics/builtin_range.py", + "basics/bytearray1.py", + "basics/class_super.py", + "basics/containment.py", + "basics/errno1.py", + "basics/fun_str.py", + "basics/generator1.py", + "basics/globals_del.py", + "basics/memoryview1.py", + "basics/memoryview_gc.py", + "basics/object1.py", + "basics/python34.py", + "basics/struct_endian.py", + "extmod/btree1.py", + "extmod/deflate_decompress.py", + "extmod/framebuf16.py", + "extmod/framebuf4.py", + "extmod/machine1.py", + "extmod/time_mktime.py", + "extmod/time_res.py", + "extmod/tls_sslcontext_ciphers.py", + "extmod/vfs_fat_fileio1.py", + "extmod/vfs_fat_finaliser.py", + "extmod/vfs_fat_more.py", + "extmod/vfs_fat_ramdisk.py", + "extmod/vfs_fat_ramdisklarge.py", + "extmod/vfs_lfs.py", + "extmod/vfs_rom.py", + "float/string_format_modulo.py", + "micropython/builtin_execfile.py", + "micropython/extreme_exc.py", + "micropython/heapalloc_fail_bytearray.py", + "micropython/heapalloc_fail_list.py", + "micropython/heapalloc_fail_memoryview.py", + "micropython/import_mpy_invalid.py", + "micropython/import_mpy_native.py", + "micropython/import_mpy_native_gc.py", + "misc/non_compliant.py", + "misc/rge_sm.py", +) + +# Tests that require `import target_wiring` to work. +tests_requiring_target_wiring = ( + "extmod/machine_uart_irq_txidle.py", + "extmod/machine_uart_tx.py", + "extmod_hardware/machine_encoder.py", + "extmod_hardware/machine_uart_irq_break.py", + "extmod_hardware/machine_uart_irq_rx.py", + "extmod_hardware/machine_uart_irq_rxidle.py", +) + def rm_f(fname): if os.path.exists(fname): @@ -111,22 +358,158 @@ def convert_regex_escapes(line): return bytes("".join(cs), "utf8") -def prepare_script_for_target(args, *, script_filename=None, script_text=None, force_plain=False): +def platform_to_port(platform): + return platform_to_port_map.get(platform, platform) + + +def convert_device_shortcut_to_real_device(device): + if device.startswith("port:"): + return device.split(":", 1)[1] + elif device.startswith("a") and device[1:].isdigit(): + return "/dev/ttyACM" + device[1:] + elif device.startswith("u") and device[1:].isdigit(): + return "/dev/ttyUSB" + device[1:] + elif device.startswith("c") and device[1:].isdigit(): + return "COM" + device[1:] + else: + return device + + +def get_test_instance(test_instance, baudrate, user, password): + if test_instance == "unix": + return None + elif test_instance == "webassembly": + return PyboardNodeRunner() + else: + # Assume it's a device path. + port = convert_device_shortcut_to_real_device(test_instance) + + global pyboard + sys.path.append(base_path("../tools")) + import pyboard + + pyb = pyboard.Pyboard(port, baudrate, user, password) + pyboard.Pyboard.run_script_on_remote_target = run_script_on_remote_target + pyb.enter_raw_repl() + return pyb + + +def detect_inline_asm_arch(pyb, args): + for arch in ("rv32", "thumb", "xtensa"): + output = run_feature_check(pyb, args, "inlineasm_{}.py".format(arch)) + if output.strip() == arch.encode(): + return arch + return None + + +def map_rv32_arch_flags(flags): + mapped_flags = [] + for extension, bit in RV32_ARCH_FLAGS.items(): + if flags & bit: + mapped_flags.append(extension) + flags &= ~bit + if flags: + raise Exception("Unexpected flag bits set in value {}".format(flags)) + return mapped_flags + + +def detect_test_platform(pyb, args): + # Run a script to detect various bits of information about the target test instance. + output = run_feature_check(pyb, args, "target_info.py") + if output.endswith(b"CRASH"): + raise ValueError("cannot detect platform: {}".format(output)) + platform, arch, arch_flags, build, thread, float_prec, unicode = ( + str(output, "ascii").strip().split() + ) + if arch == "None": + arch = None + inlineasm_arch = detect_inline_asm_arch(pyb, args) + if thread == "None": + thread = None + float_prec = int(float_prec) + unicode = unicode == "True" + if arch == "rv32imc": + arch_flags = map_rv32_arch_flags(int(arch_flags)) + else: + arch_flags = None + + args.platform = platform + args.arch = arch + args.arch_flags = arch_flags + if arch and not args.mpy_cross_flags: + args.mpy_cross_flags = "-march=" + arch + if arch_flags: + args.mpy_cross_flags += " -march-flags=" + ",".join(arch_flags) + args.inlineasm_arch = inlineasm_arch + args.build = build + args.thread = thread + args.float_prec = float_prec + args.unicode = unicode + + # Print the detected information about the target. + print("platform={}".format(platform), end="") + if arch: + print(" arch={}".format(arch), end="") + if arch_flags: + print(" arch_flags={}".format(",".join(arch_flags)), end="") + if inlineasm_arch: + print(" inlineasm={}".format(inlineasm_arch), end="") + if thread: + print(" thread={}".format(thread), end="") + if float_prec: + print(" float={}-bit".format(float_prec), end="") + if unicode: + print(" unicode", end="") + + +def detect_target_wiring_script(pyb, args): + tw_data = b"" + tw_source = None + if args.target_wiring: + # A target_wiring path is explicitly provided, so use that. + tw_source = args.target_wiring + with open(tw_source, "rb") as f: + tw_data = f.read() + elif hasattr(pyb, "exec_raw") and pyb.exec_raw("import target_wiring") == (b"", b""): + # The board already has a target_wiring module available, so use that. + tw_source = "on-device" + else: + port = platform_to_port(args.platform) + build = args.build + tw_board_exact = None + tw_board_partial = None + tw_port = None + for file in os.listdir("target_wiring"): + file_base = file.removesuffix(".py") + if file_base == build: + # A file matching the target's board/build name. + tw_board_exact = file + elif file_base.endswith("x") and build.startswith(file_base.removesuffix("x")): + # A file with a partial match to the target's board/build name. + tw_board_partial = file + elif file_base == port: + # A file matching the target's port. + tw_port = file + tw_source = tw_board_exact or tw_board_partial or tw_port + if tw_source: + with open("target_wiring/" + tw_source, "rb") as f: + tw_data = f.read() + if tw_source: + print(" target_wiring={}".format(tw_source), end="") + pyb.target_wiring_script = tw_data + + +def prepare_script_for_target(args, *, script_text=None, force_plain=False): if force_plain or (not args.via_mpy and args.emit == "bytecode"): - if script_filename is not None: - with open(script_filename, "rb") as f: - script_text = f.read() + # A plain test to run as-is, no processing needed. + pass elif args.via_mpy: tempname = tempfile.mktemp(dir="") mpy_filename = tempname + ".mpy" - if script_filename is None: - script_filename = tempname + ".py" - cleanup_script_filename = True - with open(script_filename, "wb") as f: - f.write(script_text) - else: - cleanup_script_filename = False + script_filename = tempname + ".py" + with open(script_filename, "wb") as f: + f.write(script_text) try: subprocess.check_output( @@ -142,8 +525,7 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f script_text = b"__buf=" + bytes(repr(f.read()), "ascii") + b"\n" rm_f(mpy_filename) - if cleanup_script_filename: - rm_f(script_filename) + rm_f(script_filename) script_text += bytes(injected_import_hook_code, "ascii") else: @@ -154,42 +536,72 @@ def prepare_script_for_target(args, *, script_filename=None, script_text=None, f def run_script_on_remote_target(pyb, args, test_file, is_special): - had_crash, script = prepare_script_for_target( - args, script_filename=test_file, force_plain=is_special - ) + with open(test_file, "rb") as f: + script = f.read() + + # If the test is not a special test, prepend it with a print to indicate that it started. + # If the print does not execute this means that the test did not even start, eg it was + # too large for the target. + prepend_start_test = not is_special + if prepend_start_test: + if script.startswith(b"#"): + script = b"print('START TEST')" + script + else: + script = b"print('START TEST')\n" + script + + had_crash, script = prepare_script_for_target(args, script_text=script, force_plain=is_special) + if had_crash: return True, script try: had_crash = False pyb.enter_raw_repl() - output_mupy = pyb.exec_(script) + if test_file.endswith(tests_requiring_target_wiring) and pyb.target_wiring_script: + pyb.exec_( + "import sys;sys.modules['target_wiring']=__build_class__(lambda:exec(" + + repr(pyb.target_wiring_script) + + "),'target_wiring')" + ) + output_mupy = pyb.exec_(script, timeout=TEST_TIMEOUT) except pyboard.PyboardError as e: had_crash = True if not is_special and e.args[0] == "exception": - output_mupy = e.args[1] + e.args[2] + b"CRASH" + if prepend_start_test and e.args[1] == b"" and b"MemoryError" in e.args[2]: + output_mupy = b"SKIP-TOO-LARGE\n" + else: + output_mupy = e.args[1] + e.args[2] + b"CRASH" else: output_mupy = bytes(e.args[0], "ascii") + b"\nCRASH" + + if prepend_start_test: + if output_mupy.startswith(b"START TEST\r\n"): + output_mupy = output_mupy.removeprefix(b"START TEST\r\n") + else: + had_crash = True + return had_crash, output_mupy -def run_micropython(pyb, args, test_file, is_special=False): - special_tests = ( +tests_with_regex_output = [ + base_path(file) + for file in ( + # CIRCUITPY-CHANGE: removal and additions "micropython/meminfo.py", "basics/bytes_compare3.py", "basics/builtin_help.py", "thread/thread_exc2.py", - "esp32/partition_ota.py", - "circuitpython/traceback_test.py", # CIRCUITPY-CHANGE - "circuitpython/traceback_test_chained.py", # CIRCUITPY-CHANGE + "circuitpython/traceback_test.py", + "circuitpython/traceback_test_chained.py", ) +] + + +def run_micropython(pyb, args, test_file, test_file_abspath, is_special=False): had_crash = False if pyb is None: # run on PC - if ( - test_file.startswith(("cmdline/", base_path("feature_check/"))) - or test_file in special_tests - ): + if test_file_abspath.startswith((base_path("cmdline/"), base_path("feature_check/"))): # special handling for tests of the unix cmdline program is_special = True @@ -204,7 +616,7 @@ def run_micropython(pyb, args, test_file, is_special=False): # run the test, possibly with redirected input try: - if "repl_" in test_file: + if os.path.basename(test_file).startswith("repl_"): # Need to use a PTY to test command line editing try: import pty @@ -228,6 +640,10 @@ def get(required=False): return rv def send_get(what): + # Detect {\x00} pattern and convert to ctrl-key codes. + ctrl_code = lambda m: bytes([int(m.group(1))]) + what = re.sub(rb"{\\x(\d\d)}", ctrl_code, what) + os.write(master, what) return get() @@ -282,7 +698,7 @@ def send_get(what): mpy_modname = os.path.splitext(os.path.basename(mpy_filename))[0] cmdlist.extend(["-m", mpy_modname]) else: - cmdlist.append(os.path.abspath(test_file)) + cmdlist.append(test_file_abspath) # run the actual test try: @@ -302,20 +718,22 @@ def send_get(what): else: # run via pyboard interface - had_crash, output_mupy = run_script_on_remote_target(pyb, args, test_file, is_special) + had_crash, output_mupy = pyb.run_script_on_remote_target( + args, test_file_abspath, is_special + ) # canonical form for all ports/platforms is to use \n for end-of-line - output_mupy = output_mupy.replace(b"\r\n", b"\n") + output_mupy = normalize_newlines(output_mupy) # don't try to convert the output if we should skip this test - if had_crash or output_mupy in (b"SKIP\n", b"CRASH"): + if had_crash or output_mupy in (b"SKIP\n", b"SKIP-TOO-LARGE\n", b"CRASH"): return output_mupy # skipped special tests will output "SKIP" surrounded by other interpreter debug output if is_special and not had_crash and b"\nSKIP\n" in output_mupy: return b"SKIP\n" - if is_special or test_file in special_tests: + if is_special or test_file_abspath in tests_with_regex_output: # convert parts of the output that are not stable across runs with open(test_file + ".exp", "rb") as f: lines_exp = [] @@ -359,11 +777,16 @@ def send_get(what): return output_mupy -def run_feature_check(pyb, args, base_path, test_file): +def run_feature_check(pyb, args, test_file): if pyb is not None and test_file.startswith("repl_"): # REPL feature tests will not run via pyboard because they require prompt interactivity return b"" - return run_micropython(pyb, args, base_path("feature_check", test_file), is_special=True) + test_file_path = base_path("feature_check", test_file) + return run_micropython(pyb, args, test_file_path, test_file_path, is_special=True) + + +class TestError(Exception): + pass class ThreadSafeCounter: @@ -386,168 +809,202 @@ def value(self): return self._value +class PyboardNodeRunner: + def __init__(self): + mjs = os.getenv("MICROPY_MICROPYTHON_MJS") + if mjs is None: + mjs = base_path("../ports/webassembly/build-standard/micropython.mjs") + else: + mjs = os.path.abspath(mjs) + self.micropython_mjs = mjs + + def close(self): + pass + + def run_script_on_remote_target(self, args, test_file, is_special): + cwd = os.path.dirname(test_file) + + # Create system command list. + cmdlist = ["node"] + if test_file.endswith(".py"): + # Run a Python script indirectly via "node micropython.mjs ". + cmdlist.append(self.micropython_mjs) + if args.heapsize is not None: + cmdlist.extend(["-X", "heapsize=" + args.heapsize]) + cmdlist.append(test_file) + else: + # Run a js/mjs script directly with Node, passing in the path to micropython.mjs. + cmdlist.append(test_file) + cmdlist.append(self.micropython_mjs) + + # Run the script. + try: + had_crash = False + output_mupy = subprocess.check_output( + cmdlist, stderr=subprocess.STDOUT, timeout=TEST_TIMEOUT, cwd=cwd + ) + except subprocess.CalledProcessError as er: + had_crash = True + output_mupy = er.output + b"CRASH" + except subprocess.TimeoutExpired as er: + had_crash = True + output_mupy = (er.output or b"") + b"TIMEOUT" + + # Return the results. + return had_crash, output_mupy + + def run_tests(pyb, tests, args, result_dir, num_threads=1): - test_count = ThreadSafeCounter() testcase_count = ThreadSafeCounter() - passed_count = ThreadSafeCounter() - failed_tests = ThreadSafeCounter([]) - skipped_tests = ThreadSafeCounter([]) + test_results = ThreadSafeCounter([]) skip_tests = set() skip_native = False skip_int_big = False + skip_int_64 = False skip_bytearray = False skip_set_type = False skip_slice = False skip_async = False skip_const = False skip_revops = False - skip_io_module = False skip_fstring = False skip_endian = False + skip_inlineasm = False has_complex = True has_coverage = False - upy_float_precision = 32 - - # If we're asked to --list-tests, we can't assume that there's a - # connection to target, so we can't run feature checks usefully. - if not (args.list_tests or args.write_exp): + if True: # Even if we run completely different tests in a different directory, # we need to access feature_checks from the same directory as the # run-tests.py script itself so use base_path. # Check if micropython.native is supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "native_check.py") + output = run_feature_check(pyb, args, "native_check.py") if output != b"native\n": skip_native = True # Check if arbitrary-precision integers are supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "int_big.py") + output = run_feature_check(pyb, args, "int_big.py") if output != b"1000000000000000000000000000000000000000000000\n": skip_int_big = True + # Check if 'long long' precision integers are supported, even if arbitrary precision is not + output = run_feature_check(pyb, args, "int_64.py") + if output != b"4611686018427387904\n": + skip_int_64 = True + # Check if bytearray is supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "bytearray.py") + output = run_feature_check(pyb, args, "bytearray.py") if output != b"bytearray\n": skip_bytearray = True # Check if set type (and set literals) is supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "set_check.py") + output = run_feature_check(pyb, args, "set_check.py") if output != b"{1}\n": skip_set_type = True # Check if slice is supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "slice.py") + output = run_feature_check(pyb, args, "slice.py") if output != b"slice\n": skip_slice = True # Check if async/await keywords are supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "async_check.py") + output = run_feature_check(pyb, args, "async_check.py") if output != b"async\n": skip_async = True # Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "const.py") + output = run_feature_check(pyb, args, "const.py") if output != b"1\n": skip_const = True # Check if __rOP__ special methods are supported, and skip such tests if it's not - output = run_feature_check(pyb, args, base_path, "reverse_ops.py") + output = run_feature_check(pyb, args, "reverse_ops.py") if output == b"TypeError\n": skip_revops = True - # Check if io module exists, and skip such tests if it doesn't - output = run_feature_check(pyb, args, base_path, "io_module.py") - if output != b"io\n": - skip_io_module = True - # Check if fstring feature is enabled, and skip such tests if it doesn't - output = run_feature_check(pyb, args, base_path, "fstring.py") + output = run_feature_check(pyb, args, "fstring.py") if output != b"a=1\n": skip_fstring = True - # Check if @micropython.asm_thumb supports Thumb2 instructions, and skip such tests if it doesn't - output = run_feature_check(pyb, args, base_path, "inlineasm_thumb2.py") - if output != b"thumb2\n": - skip_tests.add("inlineasm/asmbcc.py") - skip_tests.add("inlineasm/asmbitops.py") - skip_tests.add("inlineasm/asmconst.py") - skip_tests.add("inlineasm/asmdiv.py") - skip_tests.add("inlineasm/asmfpaddsub.py") - skip_tests.add("inlineasm/asmfpcmp.py") - skip_tests.add("inlineasm/asmfpldrstr.py") - skip_tests.add("inlineasm/asmfpmuldiv.py") - skip_tests.add("inlineasm/asmfpsqrt.py") - skip_tests.add("inlineasm/asmit.py") - skip_tests.add("inlineasm/asmspecialregs.py") + if args.inlineasm_arch == "thumb": + # Check if @micropython.asm_thumb supports Thumb2 instructions, and skip such tests if it doesn't + output = run_feature_check(pyb, args, "inlineasm_thumb2.py") + if output != b"thumb2\n": + skip_tests.add("inlineasm/thumb/asmbcc.py") + skip_tests.add("inlineasm/thumb/asmbitops.py") + skip_tests.add("inlineasm/thumb/asmconst.py") + skip_tests.add("inlineasm/thumb/asmdiv.py") + skip_tests.add("inlineasm/thumb/asmit.py") + skip_tests.add("inlineasm/thumb/asmspecialregs.py") + if args.arch not in ("armv7emsp", "armv7emdp"): + skip_tests.add("inlineasm/thumb/asmfpaddsub.py") + skip_tests.add("inlineasm/thumb/asmfpcmp.py") + skip_tests.add("inlineasm/thumb/asmfpldrstr.py") + skip_tests.add("inlineasm/thumb/asmfpmuldiv.py") + skip_tests.add("inlineasm/thumb/asmfpsqrt.py") + + if args.inlineasm_arch == "rv32": + # Check if @micropython.asm_rv32 supports Zba instructions, and skip such tests if it doesn't + output = run_feature_check(pyb, args, "inlineasm_rv32_zba.py") + if output != b"rv32_zba\n": + skip_tests.add("inlineasm/rv32/asmzba.py") # Check if emacs repl is supported, and skip such tests if it's not - t = run_feature_check(pyb, args, base_path, "repl_emacs_check.py") + t = run_feature_check(pyb, args, "repl_emacs_check.py") if "True" not in str(t, "ascii"): skip_tests.add("cmdline/repl_emacs_keys.py") # Check if words movement in repl is supported, and skip such tests if it's not - t = run_feature_check(pyb, args, base_path, "repl_words_move_check.py") + t = run_feature_check(pyb, args, "repl_words_move_check.py") if "True" not in str(t, "ascii"): skip_tests.add("cmdline/repl_words_move.py") - upy_byteorder = run_feature_check(pyb, args, base_path, "byteorder.py") - upy_float_precision = run_feature_check(pyb, args, base_path, "float.py") - try: - upy_float_precision = int(upy_float_precision) - except ValueError: - upy_float_precision = 0 - has_complex = run_feature_check(pyb, args, base_path, "complex.py") == b"complex\n" - has_coverage = run_feature_check(pyb, args, base_path, "coverage.py") == b"coverage\n" + upy_byteorder = run_feature_check(pyb, args, "byteorder.py") + has_complex = run_feature_check(pyb, args, "complex.py") == b"complex\n" + has_coverage = run_feature_check(pyb, args, "coverage.py") == b"coverage\n" cpy_byteorder = subprocess.check_output( CPYTHON3_CMD + [base_path("feature_check/byteorder.py")] ) skip_endian = upy_byteorder != cpy_byteorder - # These tests don't test slice explicitly but rather use it to perform the test - misc_slice_tests = ( - "builtin_range", - "class_super", - "containment", - "errno1", - "fun_str", - "generator1", - "globals_del", - "memoryview1", - "memoryview_gc", - "object1", - "python34", - "struct_endian", - ) + skip_inlineasm = args.inlineasm_arch is None # Some tests shouldn't be run on GitHub Actions if os.getenv("GITHUB_ACTIONS") == "true": skip_tests.add("thread/stress_schedule.py") # has reliability issues - if upy_float_precision == 0: - skip_tests.add("extmod/uctypes_le_float.py") - skip_tests.add("extmod/uctypes_native_float.py") - skip_tests.add("extmod/uctypes_sizeof_float.py") - skip_tests.add("extmod/ujson_dumps_float.py") - skip_tests.add("extmod/ujson_loads_float.py") - skip_tests.add("extmod/urandom_extra_float.py") - skip_tests.add("misc/rge_sm.py") - if upy_float_precision < 32: + if os.getenv("RUNNER_OS") == "Windows" and os.getenv("CI_BUILD_CONFIGURATION") == "Debug": + # fails with stack overflow on Debug builds + skip_tests.add("misc/sys_settrace_features.py") + + if args.float_prec == 0: + skip_tests.update(tests_requiring_float) + if args.float_prec < 32: skip_tests.add( "float/float2int_intbig.py" ) # requires fp32, there's float2int_fp30_intbig.py instead skip_tests.add( - "float/string_format.py" - ) # requires fp32, there's string_format_fp30.py instead + "float/float_struct_e.py" + ) # requires fp32, there's float_struct_e_fp30.py instead skip_tests.add("float/bytes_construct.py") # requires fp32 skip_tests.add("float/bytearray_construct.py") # requires fp32 - if upy_float_precision < 64: + skip_tests.add("float/float_format_ints_power10.py") # requires fp32 + if args.float_prec < 64: skip_tests.add("float/float_divmod.py") # tested by float/float_divmod_relaxed.py instead skip_tests.add("float/float2int_doubleprec_intbig.py") + skip_tests.add("float/float_struct_e_doubleprec.py") skip_tests.add("float/float_format_ints_doubleprec.py") skip_tests.add("float/float_parse_doubleprec.py") + if not args.unicode: + skip_tests.add("extmod/json_loads.py") # tests loading a utf-8 character + + if skip_slice: + skip_tests.update(tests_requiring_slice) + if not has_complex: skip_tests.add("float/complex1.py") skip_tests.add("float/complex1_intbig.py") @@ -561,55 +1018,30 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): if not has_coverage: skip_tests.add("cmdline/cmd_parsetree.py") skip_tests.add("cmdline/repl_sys_ps1_ps2.py") - skip_tests.add("extmod/ussl_poll.py") + skip_tests.add("extmod/ssl_poll.py") - # Some tests shouldn't be run on a PC - if args.target == "unix": - # unix build does not have the GIL so can't run thread mutation tests + # Skip thread mutation tests on targets that have unsafe threading behaviour. + if args.thread == "unsafe": for t in tests: if t.startswith("thread/mutate_"): skip_tests.add(t) # Some tests shouldn't be run on pyboard - if args.target != "unix": + if args.platform not in PC_PLATFORMS: skip_tests.add("basics/exception_chain.py") # warning is not printed skip_tests.add("micropython/meminfo.py") # output is very different to PC output - skip_tests.add("extmod/machine_mem.py") # raw memory access not supported - - if args.target == "wipy": - skip_tests.add("misc/print_exception.py") # requires error reporting full - skip_tests.update( - { - "extmod/uctypes_%s.py" % t - for t in "bytearray le native_le ptr_le ptr_native_le sizeof sizeof_native array_assign_le array_assign_native_le".split() - } - ) # requires uctypes - skip_tests.add("extmod/heapq1.py") # heapq not supported by WiPy - skip_tests.add("extmod/random_basic.py") # requires random - skip_tests.add("extmod/random_extra.py") # requires random - elif args.target == "esp8266": - skip_tests.add("misc/rge_sm.py") # too large - elif args.target == "minimal": - skip_tests.add("basics/class_inplace_op.py") # all special methods not supported - skip_tests.add( - "basics/subclass_native_init.py" - ) # native subclassing corner cases not support - skip_tests.add("misc/rge_sm.py") # too large - skip_tests.add("micropython/opt_level.py") # don't assume line numbers are stored - elif args.target == "nrf": - skip_tests.add("basics/memoryview1.py") # no item assignment for memoryview - skip_tests.add("extmod/random_basic.py") # unimplemented: random.seed - skip_tests.add("micropython/opt_level.py") # no support for line numbers - skip_tests.add("misc/non_compliant.py") # no item assignment for bytearray - for t in tests: - if t.startswith("basics/io_"): - skip_tests.add(t) - elif args.target == "renesas-ra": - skip_tests.add( - "extmod/time_time_ns.py" - ) # RA fsp rtc function doesn't support nano sec info - elif args.target == "qemu-arm": - skip_tests.add("misc/print_exception.py") # requires sys stdfiles + skip_tests.add("unicode/file1.py") # requires local file access + skip_tests.add("unicode/file2.py") # requires local file access + skip_tests.add("unicode/file_invalid.py") # requires local file access + + # Skip certain tests when going via a .mpy file. + skip_tests.update(via_mpy_tests_to_skip.get(args.via_mpy, ())) + + # Skip emitter-specific tests. + skip_tests.update(emitter_tests_to_skip.get(args.emit, ())) + + # Skip platform-specific tests. + skip_tests.update(platform_tests_to_skip.get(args.platform, ())) # Some tests are known to fail on 64-bit machines if pyb is None and platform.architecture()[0] == "64bit": @@ -617,66 +1049,16 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): # Some tests use unsupported features on Windows if os.name == "nt": - skip_tests.add("import/import_file.py") # works but CPython prints forward slashes - - # Some tests are known to fail with native emitter - # Remove them from the below when they work - if args.emit == "native": - skip_tests.update( - {"basics/%s.py" % t for t in "gen_yield_from_close generator_name".split()} - ) # require raise_varargs, generator name - skip_tests.update( - {"basics/async_%s.py" % t for t in "with with2 with_break with_return".split()} - ) # require async_with - skip_tests.update( - {"basics/%s.py" % t for t in "try_reraise try_reraise2".split()} - ) # require raise_varargs - skip_tests.add("basics/annotate_var.py") # requires checking for unbound local - skip_tests.add("basics/del_deref.py") # requires checking for unbound local - skip_tests.add("basics/del_local.py") # requires checking for unbound local - skip_tests.add("basics/exception_chain.py") # raise from is not supported - skip_tests.add("basics/fun_name.py") # requires proper names for native functions - skip_tests.add("basics/scope_implicit.py") # requires checking for unbound local - skip_tests.add("basics/sys_tracebacklimit.py") # requires traceback info - skip_tests.add("basics/try_finally_return2.py") # requires raise_varargs - skip_tests.add("basics/unboundlocal.py") # requires checking for unbound local - # CIRCUITPY-CHANGE - skip_tests.update( - ( - "basics/chained_exception.py", - "circuitpython/traceback_test.py", - "circuitpython/traceback_test_chained.py", - ) - ) # because native doesn't have proper traceback info - skip_tests.add("extmod/asyncio_event.py") # unknown issue - skip_tests.add("extmod/asyncio_lock.py") # requires async with - skip_tests.add("extmod/asyncio_micropython.py") # unknown issue - skip_tests.add("extmod/asyncio_wait_for.py") # unknown issue - skip_tests.add("misc/features.py") # requires raise_varargs - skip_tests.add( - "misc/print_exception.py" - ) # because native doesn't have proper traceback info - skip_tests.add("misc/sys_exc_info.py") # sys.exc_info() is not supported for native - skip_tests.add("misc/sys_settrace_features.py") # sys.settrace() not supported - skip_tests.add("misc/sys_settrace_generator.py") # sys.settrace() not supported - skip_tests.add("misc/sys_settrace_loop.py") # sys.settrace() not supported - skip_tests.add( - "micropython/emg_exc.py" - ) # because native doesn't have proper traceback info - skip_tests.add( - "micropython/heapalloc_traceback.py" - ) # because native doesn't have proper traceback info - skip_tests.add( - "micropython/opt_level_lineno.py" - ) # native doesn't have proper traceback info - skip_tests.add("micropython/schedule.py") # native code doesn't check pending events - skip_tests.add("stress/bytecode_limit.py") # bytecode specific test + if not sysconfig.get_platform().startswith("mingw"): + # Works but CPython uses '\' path separator + skip_tests.add("import/import_file.py") def run_one_test(test_file): test_file = test_file.replace("\\", "/") + test_file_abspath = os.path.abspath(test_file).replace("\\", "/") if args.filters: - # Default verdict is the opposit of the first action + # Default verdict is the opposite of the first action verdict = "include" if args.filters[0][0] == "exclude" else "exclude" for action, pat in args.filters: if pat.search(test_file): @@ -686,135 +1068,261 @@ def run_one_test(test_file): test_basename = test_file.replace("..", "_").replace("./", "").replace("/", "_") test_name = os.path.splitext(os.path.basename(test_file))[0] - is_native = ( - test_name.startswith("native_") - or test_name.startswith("viper_") - or args.emit == "native" - ) + is_native = test_name.startswith("native_") or test_name.startswith("viper_") is_endian = test_name.endswith("_endian") - is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig") + is_int_big = ( + test_name.startswith("int_big") + or test_name.endswith("_intbig") + or test_name.startswith("ffi_int") # these tests contain large integer literals + ) + is_int_64 = test_name.startswith("int_64") or test_name.endswith("_int64") is_bytearray = test_name.startswith("bytearray") or test_name.endswith("_bytearray") is_set_type = test_name.startswith(("set_", "frozenset")) or test_name.endswith("_set") - is_slice = test_name.find("slice") != -1 or test_name in misc_slice_tests - is_async = test_name.startswith(("async_", "asyncio_")) + is_slice = test_name.find("slice") != -1 + is_async = test_name.startswith(("async_", "asyncio_")) or test_name.endswith("_async") is_const = test_name.startswith("const") - is_io_module = test_name.startswith("io_") is_fstring = test_name.startswith("string_fstring") + is_inlineasm = test_name.startswith("asm") skip_it = test_file in skip_tests skip_it |= skip_native and is_native skip_it |= skip_endian and is_endian skip_it |= skip_int_big and is_int_big + skip_it |= skip_int_64 and is_int_64 skip_it |= skip_bytearray and is_bytearray skip_it |= skip_set_type and is_set_type skip_it |= skip_slice and is_slice skip_it |= skip_async and is_async skip_it |= skip_const and is_const skip_it |= skip_revops and "reverse_op" in test_name - skip_it |= skip_io_module and is_io_module skip_it |= skip_fstring and is_fstring - - if args.list_tests: - if not skip_it: - print(test_file) - return + skip_it |= skip_inlineasm and is_inlineasm if skip_it: print("skip ", test_file) - skipped_tests.append(test_name) - return - - # get expected output - test_file_expected = test_file + ".exp" - if os.path.isfile(test_file_expected): - # expected output given by a file, so read that in - with open(test_file_expected, "rb") as f: - output_expected = f.read() - else: - # CIRCUITPY-CHANGE: set language & make sure testlib is available for `skip_ok`. - e = { - "PYTHONPATH": base_path("testlib"), - "PATH": os.environ["PATH"], - "LANG": "en_US.UTF-8", - } - # run CPython to work out expected output - try: - output_expected = subprocess.check_output( - CPYTHON3_CMD + [os.path.abspath(test_file)], - cwd=os.path.dirname(test_file), - stderr=subprocess.STDOUT, - env=e, - ) - if args.write_exp: - with open(test_file_expected, "wb") as f: - f.write(output_expected) - except subprocess.CalledProcessError: - output_expected = b"CPYTHON3 CRASH" - - # canonical form for all host platforms is to use \n for end-of-line - output_expected = output_expected.replace(b"\r\n", b"\n") - - if args.write_exp: + test_results.append((test_file, "skip", "")) return - # run MicroPython - output_mupy = run_micropython(pyb, args, test_file) + # Run the test on the MicroPython target. + output_mupy = run_micropython(pyb, args, test_file, test_file_abspath) + # Check if the target requested to skip this test. if output_mupy == b"SKIP\n": + if pyb is not None and hasattr(pyb, "read_until"): + # Running on a target over a serial connection, and the target requested + # to skip the test. It does this via a SystemExit which triggers a soft + # reset. Wait for the soft reset to finish, so we don't interrupt the + # start-up code (eg boot.py) when preparing to run the next test. + pyb.read_until(1, b"raw REPL; CTRL-B to exit\r\n") print("skip ", test_file) - skipped_tests.append(test_name) + test_results.append((test_file, "skip", "")) return + elif output_mupy == b"SKIP-TOO-LARGE\n": + print("lrge ", test_file) + test_results.append((test_file, "skip", "too large")) + return + + # Look at the output of the test to see if unittest was used. + uses_unittest = False + output_mupy_lines = output_mupy.splitlines() + if any( + line == b"ImportError: no module named 'unittest'" for line in output_mupy_lines[-3:] + ): + raise TestError( + ( + "error: test {} requires unittest".format(test_file), + "(eg run `mpremote mip install unittest` to install it)", + ) + ) + elif ( + len(output_mupy_lines) > 4 + and output_mupy_lines[-4] == b"-" * 70 + and output_mupy_lines[-2] == b"" + ): + # look for unittest summary + unittest_ran_match = re.match(rb"Ran (\d+) tests$", output_mupy_lines[-3]) + unittest_result_match = re.match( + b"(" + rb"(OK)( \(skipped=(\d+)\))?" + b"|" + rb"(FAILED) \(failures=(\d+), errors=(\d+)\)" + b")$", + output_mupy_lines[-1], + ) + uses_unittest = unittest_ran_match and unittest_result_match - testcase_count.add(len(output_expected.splitlines())) + # Determine the expected output. + if uses_unittest: + # Expected output is result of running unittest. + output_expected = None + else: + # Prefer emitter-specific expected output. + test_file_expected = test_file + "." + args.emit + ".exp" + if not os.path.isfile(test_file_expected): + # Fall back to generic expected output. + test_file_expected = test_file + ".exp" + if os.path.isfile(test_file_expected): + # Expected output given by a file, so read that in. + with open(test_file_expected, "rb") as f: + output_expected = f.read() + else: + # CIRCUITPY-CHANGE: set language & make sure testlib is available for `skip_ok`. + e = { + "PYTHONPATH": base_path("testlib"), + "PATH": os.environ["PATH"], + "LANG": "en_US.UTF-8", + } + # CIRCUITPY-CHANGE: --keep-path applies to PYTHONPATH as well + if args.keep_path and os.getenv("PYTHONPATH"): + e["PYTHONPATH"] += ":" + os.getenv("PYTHONPATH") + + # Run CPython to work out expected output. + try: + output_expected = subprocess.check_output( + CPYTHON3_CMD + [test_file_abspath], + cwd=os.path.dirname(test_file), + stderr=subprocess.STDOUT, + # CIRCUITPY-CHANGE: pass environment + env=e, + ) + except subprocess.CalledProcessError as er: + output_expected = b"CPYTHON3 CRASH:\n" + er.output + + # Canonical form for all host platforms is to use \n for end-of-line. + output_expected = output_expected.replace(b"\r\n", b"\n") + + # Work out if test passed or not. + test_passed = False + extra_info = "" + if uses_unittest: + test_passed = unittest_result_match.group(2) == b"OK" + num_test_cases = int(unittest_ran_match.group(1)) + extra_info = "unittest: {} ran".format(num_test_cases) + if test_passed and unittest_result_match.group(4) is not None: + num_skipped = int(unittest_result_match.group(4)) + num_test_cases -= num_skipped + extra_info += ", {} skipped".format(num_skipped) + elif not test_passed: + num_failures = int(unittest_result_match.group(6)) + num_errors = int(unittest_result_match.group(7)) + extra_info += ", {} failures, {} errors".format(num_failures, num_errors) + extra_info = "(" + extra_info + ")" + testcase_count.add(num_test_cases) + else: + testcase_count.add(len(output_expected.splitlines())) + test_passed = output_expected == output_mupy filename_expected = os.path.join(result_dir, test_basename + ".exp") filename_mupy = os.path.join(result_dir, test_basename + ".out") - if output_expected == output_mupy: - print("pass ", test_file) - passed_count.increment() + # Print test summary, update counters, and save .exp/.out files if needed. + if test_passed: + print("pass ", test_file, extra_info) + test_results.append((test_file, "pass", "")) rm_f(filename_expected) rm_f(filename_mupy) else: - with open(filename_expected, "wb") as f: - f.write(output_expected) + print("FAIL ", test_file, extra_info) + if output_expected is not None: + with open(filename_expected, "wb") as f: + f.write(output_expected) + else: + rm_f(filename_expected) # in case left over from previous failed run with open(filename_mupy, "wb") as f: f.write(output_mupy) - print("FAIL ", test_file) - failed_tests.append(test_name) - - test_count.increment() + test_results.append((test_file, "fail", "")) + + # Print a note if this looks like it might have been a misfired unittest + if not uses_unittest and not test_passed: + with open(test_file, "r") as f: + if any(re.match("^import.+unittest", l) for l in f.readlines()): + print( + "NOTE: {} may be a unittest that doesn't run unittest.main()".format( + test_file + ) + ) - if pyb or args.list_tests: + if pyb: num_threads = 1 - if num_threads > 1: - pool = ThreadPool(num_threads) - pool.map(run_one_test, tests) - else: - for test in tests: - run_one_test(test) + try: + if num_threads > 1: + pool = ThreadPool(num_threads) + pool.map(run_one_test, tests) + else: + for test in tests: + run_one_test(test) + except TestError as er: + for line in er.args[0]: + print(line) + sys.exit(1) - if args.list_tests: - return True + # Return test results. + return test_results.value, testcase_count.value - print( - "{} tests performed ({} individual testcases)".format( - test_count.value, testcase_count.value - ) + +# Print a summary of the results and save them to a JSON file. +# Returns True if everything succeeded, False otherwise. +def create_test_report(args, test_results, testcase_count=None): + passed_tests = list(r for r in test_results if r[1] == "pass") + skipped_tests = list(r for r in test_results if r[1] == "skip" and r[2] != "too large") + skipped_tests_too_large = list( + r for r in test_results if r[1] == "skip" and r[2] == "too large" ) - print("{} tests passed".format(passed_count.value)) + failed_tests = list(r for r in test_results if r[1] == "fail") + + num_tests_performed = len(passed_tests) + len(failed_tests) + + testcase_count_info = "" + if testcase_count is not None: + testcase_count_info = " ({} individual testcases)".format(testcase_count) + print("{} tests performed{}".format(num_tests_performed, testcase_count_info)) + + print("{} tests passed".format(len(passed_tests))) - skipped_tests = sorted(skipped_tests.value) if len(skipped_tests) > 0: - print("{} tests skipped: {}".format(len(skipped_tests), " ".join(skipped_tests))) - failed_tests = sorted(failed_tests.value) + print( + "{} tests skipped: {}".format( + len(skipped_tests), " ".join(test[0] for test in skipped_tests) + ) + ) + + if len(skipped_tests_too_large) > 0: + print( + "{} tests skipped because they are too large: {}".format( + len(skipped_tests_too_large), " ".join(test[0] for test in skipped_tests_too_large) + ) + ) + if len(failed_tests) > 0: - print("{} tests failed: {}".format(len(failed_tests), " ".join(failed_tests))) - return False + print( + "{} tests failed: {}".format( + len(failed_tests), " ".join(test[0] for test in failed_tests) + ) + ) + + # Serialize regex added by append_filter. + def to_json(obj): + if isinstance(obj, re.Pattern): + return obj.pattern + return obj + + with open(os.path.join(args.result_dir, RESULTS_FILE), "w") as f: + json.dump( + { + # The arguments passed on the command-line. + "args": vars(args), + # A list of all results of the form [(test, result, reason), ...]. + "results": list(test for test in test_results), + # A list of failed tests. This is deprecated, use the "results" above instead. + "failed_tests": [test[0] for test in failed_tests], + }, + f, + default=to_json, + ) - # all tests succeeded - return True + # Return True only if all tests succeeded. + return len(failed_tests) == 0 class append_filter(argparse.Action): @@ -831,22 +1339,55 @@ def __call__(self, parser, args, value, option): args.filters.append((option, re.compile(value))) -def main(): - cmd_parser = argparse.ArgumentParser( - formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Run and manage tests for MicroPython. +test_instance_description = """\ +By default the tests are run against the unix port of MicroPython. To run it +against something else, use the -t option. See below for details. +""" +test_instance_epilog = """\ +The -t option accepts the following for the test instance: +- unix - use the unix port of MicroPython, specified by the MICROPY_MICROPYTHON + environment variable (which defaults to the standard variant of either the unix + or windows ports, depending on the host platform) +- webassembly - use the webassembly port of MicroPython, specified by the + MICROPY_MICROPYTHON_MJS environment variable (which defaults to the standard + variant of the webassembly port) +- port: - connect to and use the given serial port device +- a - connect to and use /dev/ttyACM +- u - connect to and use /dev/ttyUSB +- c - connect to and use COM +- exec: - execute a command and attach to its stdin/stdout +- execpty: - execute a command and attach to the printed /dev/pts/ device +- ... - connect to the given IPv4 address +- anything else specifies a serial port +""" +test_directory_description = """\ Tests are discovered by scanning test directories for .py files or using the specified test files. If test files nor directories are specified, the script expects to be ran in the tests directory (where this file is located) and the builtin tests suitable for the target platform are ran. +""" + + +def main(): + global injected_import_hook_code + + cmd_parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=f"""Run and manage tests for MicroPython. + +{test_instance_description} +{test_directory_description} + When running tests, run-tests.py compares the MicroPython output of the test with the output -produced by running the test through CPython unless a .exp file is found, in which -case it is used as comparison. +produced by running the test through CPython unless a .exp file is found (or a +.native.exp file when using the native emitter), in which case it is used as comparison. + If a test fails, run-tests.py produces a pair of .out and .exp files in the result directory with the MicroPython output and the expectations, respectively. """, - epilog="""\ + epilog=f"""\ +{test_instance_epilog} Options -i and -e can be multiple and processed in the order given. Regex "search" (vs "match") operation is used. An action (include/exclude) of the last matching regex is used: @@ -855,11 +1396,8 @@ def main(): run-tests.py -e async -i async_foo - include all, exclude async, yet still include async_foo """, ) - cmd_parser.add_argument("--target", default="unix", help="the target platform") cmd_parser.add_argument( - "--device", - default="/dev/ttyACM0", - help="the serial device or the IP address of the pyboard", + "-t", "--test-instance", default="unix", help="the MicroPython instance to test" ) cmd_parser.add_argument( "-b", "--baudrate", default=115200, help="the baud rate of the serial device" @@ -888,14 +1426,6 @@ def main(): dest="filters", help="include test by regex on path/name.py", ) - cmd_parser.add_argument( - "--write-exp", - action="store_true", - help="use CPython to generate .exp files to run tests w/o CPython", - ) - cmd_parser.add_argument( - "--list-tests", action="store_true", help="list tests instead of running them" - ) cmd_parser.add_argument( "--emit", default="bytecode", help="MicroPython emitter to use (bytecode or native)" ) @@ -926,14 +1456,43 @@ def main(): action="store_true", help="delete the .exp and .out files from failed tests and exit", ) + cmd_parser.add_argument( + "--run-failures", + action="store_true", + help="re-run only the failed tests", + ) + cmd_parser.add_argument( + "--begin", + metavar="PROLOGUE", + default=None, + help="prologue python file to execute before module import", + ) + cmd_parser.add_argument( + "--target-wiring", + default=None, + help="force the given script to be used as target_wiring.py", + ) args = cmd_parser.parse_args() + prologue = "" + if args.begin: + with open(args.begin, "rt") as source: + prologue = source.read() + injected_import_hook_code = injected_import_hook_code.replace("{import_prologue}", prologue) + if args.print_failures: - for exp in glob(os.path.join(args.result_dir, "*.exp")): - testbase = exp[:-4] + for out in glob(os.path.join(args.result_dir, "*.out")): + testbase = out[:-4] print() print("FAILURE {0}".format(testbase)) - os.system("{0} {1}.exp {1}.out".format(DIFF, testbase)) + if os.path.exists(testbase + ".exp"): + # Show diff of expected and actual output. + os.system("{0} {1}.exp {1}.out".format(DIFF, testbase)) + else: + # No expected output, just show the actual output (eg from a unittest). + with open(out) as f: + for line in f: + print(line, end="") sys.exit(0) @@ -942,123 +1501,100 @@ def main(): os.path.join(args.result_dir, "*.out") ): os.remove(f) + rm_f(os.path.join(args.result_dir, RESULTS_FILE)) sys.exit(0) - LOCAL_TARGETS = ( - "unix", - "qemu-arm", - ) - EXTERNAL_TARGETS = ( - "pyboard", - "wipy", - "esp8266", - "esp32", - "minimal", - "nrf", - "renesas-ra", - "rp2", - ) - if args.list_tests: - pyb = None - elif args.target in LOCAL_TARGETS: - pyb = None - if not args.mpy_cross_flags: - if args.target == "unix": - args.mpy_cross_flags = "-march=host" - elif args.target == "qemu-arm": - args.mpy_cross_flags = "-march=armv7m" - elif args.target in EXTERNAL_TARGETS: - global pyboard - sys.path.append(base_path("../tools")) - import pyboard - - if not args.mpy_cross_flags: - if args.target == "esp8266": - args.mpy_cross_flags = "-march=xtensa" - elif args.target == "esp32": - args.mpy_cross_flags = "-march=xtensawin" - elif args.target == "rp2": - args.mpy_cross_flags = "-march=armv6m" - elif args.target == "pyboard": - args.mpy_cross_flags = "-march=armv7emsp" - else: - args.mpy_cross_flags = "-march=armv7m" + # Get the test instance to run on. + pyb = get_test_instance(args.test_instance, args.baudrate, args.user, args.password) - pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password) - pyb.enter_raw_repl() - else: - raise ValueError("target must be one of %s" % ", ".join(LOCAL_TARGETS + EXTERNAL_TARGETS)) + # Automatically detect the platform. + detect_test_platform(pyb, args) + + if args.run_failures and (any(args.files) or args.test_dirs is not None): + raise ValueError( + "--run-failures cannot be used together with files or --test-dirs arguments" + ) + + if args.run_failures: + results_file = os.path.join(args.result_dir, RESULTS_FILE) + if os.path.exists(results_file): + with open(results_file, "r") as f: + tests = list(test[0] for test in json.load(f)["results"] if test[1] == "fail") + else: + tests = [] + elif len(args.files) == 0: + test_extensions = ("*.py",) + if args.platform == "webassembly": + test_extensions += ("*.js", "*.mjs") - if len(args.files) == 0: if args.test_dirs is None: test_dirs = ( "basics", - "circuitpython", # CIRCUITPY-CHANGE "micropython", "misc", "extmod", + "stress", ) - if args.target == "pyboard": - # run pyboard tests - test_dirs += ("float", "stress", "pyb", "inlineasm") - elif args.target in ("renesas-ra"): - test_dirs += ("float", "inlineasm", "renesas-ra") - elif args.target == "rp2": - test_dirs += ("float", "stress", "inlineasm") - elif args.target in ("esp8266", "esp32", "minimal", "nrf"): + if args.inlineasm_arch is not None: + test_dirs += ("inlineasm/{}".format(args.inlineasm_arch),) + if args.thread is not None: + test_dirs += ("thread",) + if args.float_prec > 0: test_dirs += ("float",) - elif args.target == "wipy": - # run WiPy tests - test_dirs += ("wipy",) - elif args.target == "unix": + if args.unicode: + test_dirs += ("unicode",) + port_specific_test_dir = "ports/{}".format(platform_to_port(args.platform)) + if os.path.isdir(port_specific_test_dir): + test_dirs += (port_specific_test_dir,) + if args.platform in PC_PLATFORMS: # run PC tests - test_dirs += ( - "float", - "import", - "io", - "stress", - "unicode", - "unix", - "cmdline", - ) - elif args.target == "qemu-arm": - if not args.write_exp: - raise ValueError("--target=qemu-arm must be used with --write-exp") - # Generate expected output files for qemu run. - # This list should match the test_dirs tuple in tinytest-codegen.py. - test_dirs += ( - "float", - "inlineasm", - "qemu-arm", - ) + test_dirs += ("import",) + if args.build != "minimal": + test_dirs += ("cmdline", "io") else: # run tests from these directories test_dirs = args.test_dirs tests = sorted( test_file - for test_files in (glob("{}/*.py".format(dir)) for dir in test_dirs) + for test_files in ( + glob(os.path.join(dir, ext)) for dir in test_dirs for ext in test_extensions + ) for test_file in test_files ) else: # tests explicitly given tests = args.files + # If any tests need it, prepare the target_wiring script for the target. + if pyb and any(test.endswith(tests_requiring_target_wiring) for test in tests): + detect_target_wiring_script(pyb, args) + + # End the target information line. + print() + if not args.keep_path: - # clear search path to make sure tests use only builtin modules and those that can be frozen + # Clear search path to make sure tests use only builtin modules, those in + # extmod, and a path to unittest in case it's needed. # CIRCUITPY-CHANGE: Add testlib for skip_if and our async stuff. - os.environ["MICROPYPATH"] = os.pathsep.join( - [ - ".frozen", - base_path("testlib"), - base_path("../frozen/Adafruit_CircuitPython_asyncio"), - base_path("../frozen/Adafruit_CircuitPython_Ticks"), - ] + os.environ["MICROPYPATH"] = ( + ".frozen" + + os.pathsep + + base_path("testlib") + + os.pathsep + + base_path("../frozen/Adafruit_CircuitPython_asyncio") + + os.pathsep + + base_path("../frozen/Adafruit_CircuitPython_Ticks") + + os.pathsep + + base_path("../extmod") + + os.pathsep + + base_path("../lib/micropython-lib/python-stdlib/unittest") ) try: os.makedirs(args.result_dir, exist_ok=True) - res = run_tests(pyb, tests, args, args.result_dir, args.jobs) + test_results, testcase_count = run_tests(pyb, tests, args, args.result_dir, args.jobs) + res = create_test_report(args, test_results, testcase_count) finally: if pyb: pyb.close() diff --git a/tests/serial_test.py b/tests/serial_test.py new file mode 100755 index 0000000000000..3b5940d91a907 --- /dev/null +++ b/tests/serial_test.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python +# +# Performance and reliability test for serial port communication. +# +# Basic usage: +# serial_test.py [-t serial-device] +# +# The `serial-device` will default to /dev/ttyACM0. + +import argparse +import random +import serial +import sys +import time + +run_tests_module = __import__("run-tests") + +echo_test_script = """ +import sys +bytes_min=%u +bytes_max=%u +repeat=%u +b=memoryview(bytearray(bytes_max)) +for n in range(bytes_min,bytes_max+1): + for _ in range(repeat): + n2 = sys.stdin.readinto(b[:n]) + sys.stdout.write(b[:n2]) +""" + +read_test_script = """ +bin = True +try: + wr=__import__("pyb").USB_VCP(0).send +except: + import sys + if hasattr(sys.stdout,'buffer'): + wr=sys.stdout.buffer.write + else: + wr=sys.stdout.write + bin = False +b=bytearray(%u) +if bin: + wr('BIN') + for i in range(len(b)): + b[i] = i & 0xff +else: + wr('TXT') + for i in range(len(b)): + b[i] = 0x20 + (i & 0x3f) +for _ in range(%d): + wr(b) +""" + + +write_test_script_verified = """ +import sys +try: + rd=__import__("pyb").USB_VCP(0).recv +except: + rd=sys.stdin.readinto +b=bytearray(%u) +for _ in range(%u): + n = rd(b) + fail = 0 + for i in range(n): + if b[i] != 32 + (i & 0x3f): + fail += 1 + if fail: + sys.stdout.write(b'ER%%05u' %% fail) + else: + sys.stdout.write(b'OK%%05u' %% n) +""" + +write_test_script_unverified = """ +import sys +try: + rd=__import__("pyb").USB_VCP(0).recv +except: + rd=sys.stdin.readinto +b=bytearray(%u) +for _ in range(%u): + n = rd(b) + if n != len(b): + sys.stdout.write(b'ER%%05u' %% n) + else: + sys.stdout.write(b'OK%%05u' %% n) +""" + + +class TestError(Exception): + pass + + +def drain_input(ser): + time.sleep(0.1) + while ser.inWaiting() > 0: + data = ser.read(ser.inWaiting()) + time.sleep(0.1) + + +def send_script(ser, script): + ser.write(b"\x03\x01\x04") # break, raw-repl, soft-reboot + drain_input(ser) + chunk_size = 32 + for i in range(0, len(script), chunk_size): + ser.write(script[i : i + chunk_size]) + time.sleep(0.01) + ser.write(b"\x04") # eof + ser.flush() + response = ser.read(2) + if response != b"OK": + response += ser.read(ser.inWaiting()) + raise TestError("could not send script", response) + + +def echo_test(ser_repl, ser_data): + global test_passed + + # Make the test data deterministic. + random.seed(0) + + # Set parameters for the test. + # Go just a bit above the size of a USB high-speed packet. + bytes_min = 1 + bytes_max = 520 + num_repeat = 1 + + # Load and run the write_test_script. + script = bytes(echo_test_script % (bytes_min, bytes_max, num_repeat), "ascii") + send_script(ser_repl, script) + + # A selection of printable bytes for echo data. + printable_bytes = list(range(48, 58)) + list(range(65, 91)) + list(range(97, 123)) + + # Write data to the device and record the echo'd data. + # Use a different selection of random printable characters for each + # echo, to make it easier to debug when the echo doesn't match. + num_errors = 0 + echo_results = [] + for num_bytes in range(bytes_min, bytes_max + 1): + print(f"DATA ECHO: {num_bytes} / {bytes_max}", end="\r") + for repeat in range(num_repeat): + rand_bytes = list(random.choice(printable_bytes) for _ in range(8)) + buf = bytes(random.choice(rand_bytes) for _ in range(num_bytes)) + ser_data.write(buf) + buf2 = ser_data.read(len(buf)) + match = buf == buf2 + num_errors += not match + echo_results.append((match, buf, buf2)) + if num_errors > 8: + # Stop early if there are too many errors. + break + ser_repl.write(b"\x03") + + # Print results. + if all(match for match, _, _ in echo_results): + print("DATA ECHO: OK for {}-{} bytes at a time".format(bytes_min, bytes_max)) + else: + test_passed = False + print("DATA ECHO: FAIL ") + for match, buf, buf2 in echo_results: + print(" sent", len(buf), buf) + if match: + print(" echo match") + else: + print(" echo", len(buf), buf2) + + +def read_test(ser_repl, ser_data, bufsize, nbuf): + global test_passed + + assert bufsize % 256 == 0 # for verify to work + + # how long to wait for data from device + # (if UART TX is also enabled then it can take 1.4s to send + # out a 16KB butter at 115200bps) + READ_TIMEOUT_S = 2 + + # Load and run the read_test_script. + script = bytes(read_test_script % (bufsize, nbuf), "ascii") + send_script(ser_repl, script) + + # Read from the device the type of data that it will send (BIN or TXT). + data_type = ser_data.read(3) + + # Read data from the device, check it is correct, and measure throughput. + n = 0 + last_byte = None + t_start = time.time() + remain = nbuf * bufsize + total_data = bytearray(remain) + while remain: + t0 = time.monotonic_ns() + while ser_data.inWaiting() == 0: + if time.monotonic_ns() - t0 > READ_TIMEOUT_S * 1e9: + # timeout waiting for data from device + break + time.sleep(0.0001) + if not ser_data.inWaiting(): + test_passed = False + print("ERROR: timeout waiting for data") + print(total_data[:n]) + return 0 + to_read = min(ser_data.inWaiting(), remain) + data = ser_data.read(to_read) + remain -= len(data) + print(f"{n} / {nbuf * bufsize}", end="\r") + total_data[n : n + len(data)] = data + n += len(data) + t_end = time.time() + for i in range(0, len(total_data)): + if data_type == b"BIN": + wanted = i & 0xFF + else: + wanted = 0x20 + (i & 0x3F) + if total_data[i] != wanted: + test_passed = False + print("ERROR: data mismatch:", i, wanted, total_data[i]) + ser_repl.write(b"\x03") # break + t = t_end - t_start + + # Print results. + print( + "DATA IN: bufsize=%u, read %u bytes in %.2f msec = %.2f kibytes/sec = %.2f MBits/sec" + % (bufsize, n, t * 1000, n / 1024 / t, n * 8 / 1000000 / t) + ) + + return n / t + + +def write_test(ser_repl, ser_data, bufsize, nbuf, verified): + global test_passed + + # Load and run the write_test_script. + if verified: + script = write_test_script_verified + else: + script = write_test_script_unverified + script = bytes(script % (bufsize, nbuf), "ascii") + send_script(ser_repl, script) + drain_input(ser_repl) + + # Write data to the device, check it is correct, and measure throughput. + n = 0 + t_start = time.time() + buf = bytearray(bufsize) + for i in range(len(buf)): + buf[i] = 32 + (i & 0x3F) # don't want to send ctrl chars! + for i in range(nbuf): + ser_data.write(buf) + n += len(buf) + print(f"{n} / {nbuf * bufsize}", end="\r") + response = ser_repl.read(7) + if response != b"OK%05u" % bufsize: + test_passed = False + print("ERROR: bad response, expecting OK%05u, got %r" % (bufsize, response)) + t_end = time.time() + ser_repl.write(b"\x03") # break + t = t_end - t_start + + # Print results. + print( + "DATA OUT: verify=%d, bufsize=%u, wrote %u bytes in %.2f msec = %.2f kibytes/sec = %.2f MBits/sec" + % (verified, bufsize, n, t * 1000, n / 1024 / t, n * 8 / 1000000 / t) + ) + + return n / t + + +def do_test(dev_repl, dev_data=None, time_per_subtest=1): + if dev_data is None: + print("REPL and data on", dev_repl) + ser_repl = serial.Serial(dev_repl, baudrate=115200, timeout=1) + ser_data = ser_repl + else: + print("REPL on", dev_repl) + print("data on", dev_data) + ser_repl = serial.Serial(dev_repl, baudrate=115200, timeout=1) + ser_data = serial.Serial(dev_data, baudrate=115200, timeout=1) + + # Do echo test first, and abort if it doesn't pass. + echo_test(ser_repl, ser_data) + if not test_passed: + return + + # Do read and write throughput test. + for test_func, test_args, bufsize in ( + (read_test, (), 256), + (write_test, (True,), 128), + (write_test, (False,), 128), + ): + nbuf = 128 + while bufsize <= 16384: + rate = test_func(ser_repl, ser_data, bufsize, nbuf, *test_args) + bufsize *= 2 + if rate: + # Adjust the amount of data based on the rate, to keep each subtest + # at around time_per_subtest seconds long. + nbuf = max(min(128, int(rate * time_per_subtest / bufsize)), 1) + + ser_repl.close() + ser_data.close() + + +def main(): + global test_passed + + cmd_parser = argparse.ArgumentParser( + description="Test performance and reliability of serial port communication.", + epilog=run_tests_module.test_instance_epilog, + formatter_class=argparse.RawTextHelpFormatter, + ) + cmd_parser.add_argument( + "-t", + "--test-instance", + default="a0", + help="MicroPython instance to test", + ) + cmd_parser.add_argument( + "--time-per-subtest", default="1", help="approximate time to take per subtest (in seconds)" + ) + args = cmd_parser.parse_args() + + dev_repl = run_tests_module.convert_device_shortcut_to_real_device(args.test_instance) + + test_passed = True + try: + do_test(dev_repl, None, float(args.time_per_subtest)) + except TestError as er: + test_passed = False + print("ERROR:", er) + + if not test_passed: + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/tests/stress/bytecode_limit.py b/tests/stress/bytecode_limit.py index ad090637f6a68..0a72b66fa05b6 100644 --- a/tests/stress/bytecode_limit.py +++ b/tests/stress/bytecode_limit.py @@ -1,16 +1,30 @@ # Test the limits of bytecode generation. +import sys + +# Tune the test parameters based on the target's bytecode generator. +if hasattr(sys.implementation, "_mpy"): + # Target can load .mpy files so generated bytecode uses 1 byte per qstr. + number_of_body_copies = (433, 432, 431, 399) +else: + # Target can't load .mpy files so generated bytecode uses 2 bytes per qstr. + number_of_body_copies = (401, 400, 399, 398) + body = " with f()()() as a:\n try:\n f()()()\n except Exception:\n pass\n" # Test overflow of jump offset. -for n in (433, 432, 431, 430): +# Print results at the end in case an intermediate value of n fails with MemoryError. +results = [] +for n in number_of_body_copies: try: exec("cond = 0\nif cond:\n" + body * n + "else:\n print('cond false')\n") + results.append("ok") except MemoryError: print("SKIP") raise SystemExit - except RuntimeError: - print("RuntimeError") + except RuntimeError as er: + results.append(repr(er)) +print(results) # Test changing size of code info (source line/bytecode mapping) due to changing # bytecode size in the final passes. This test is very specific to how the diff --git a/tests/stress/bytecode_limit.py.exp b/tests/stress/bytecode_limit.py.exp index 1d892250b01e6..50511665f0076 100644 --- a/tests/stress/bytecode_limit.py.exp +++ b/tests/stress/bytecode_limit.py.exp @@ -1,5 +1,4 @@ -RuntimeError -RuntimeError cond false cond false +["RuntimeError('bytecode overflow',)", "RuntimeError('bytecode overflow',)", 'ok', 'ok'] [123] diff --git a/tests/stress/dict_copy.py b/tests/stress/dict_copy.py index 73d3a5b51d601..f9b742e20f716 100644 --- a/tests/stress/dict_copy.py +++ b/tests/stress/dict_copy.py @@ -1,6 +1,11 @@ # copying a large dictionary -a = {i: 2 * i for i in range(1000)} +try: + a = {i: 2 * i for i in range(1000)} +except MemoryError: + print("SKIP") + raise SystemExit + b = a.copy() for i in range(1000): print(i, b[i]) diff --git a/tests/stress/dict_create.py b/tests/stress/dict_create.py index e9db40a8e6c5b..91a83a12f9d85 100644 --- a/tests/stress/dict_create.py +++ b/tests/stress/dict_create.py @@ -3,6 +3,10 @@ d = {} x = 1 while x < 1000: - d[x] = x + try: + d[x] = x + except MemoryError: + print("SKIP") + raise SystemExit x += 1 print(d[500]) diff --git a/tests/stress/fun_call_limit.py b/tests/stress/fun_call_limit.py index b802aadd558c0..69f8aa5aec413 100644 --- a/tests/stress/fun_call_limit.py +++ b/tests/stress/fun_call_limit.py @@ -16,14 +16,16 @@ def test(n): # If the port has at least 32-bits then this test should pass. -print(test(29)) +print(test(28)) # This test should fail on all ports (overflows a small int). print(test(70)) -# Check that there is a correct transition to the limit of too many args before *args. +# 28 is the biggest number that will pass on a 32-bit port using object +# representation B, which has 1<<28 still fitting in a positive small int. reached_limit = False -for i in range(30, 70): +any_test_succeeded = False +for i in range(28, 70): result = test(i) if reached_limit: if result != "SyntaxError": @@ -34,3 +36,5 @@ def test(n): else: if result != i + 4: print("FAIL") + any_test_succeeded = True +assert any_test_succeeded # At least one iteration must have passed diff --git a/tests/stress/fun_call_limit.py.exp b/tests/stress/fun_call_limit.py.exp index 53d2b28043015..491abbfa8be72 100644 --- a/tests/stress/fun_call_limit.py.exp +++ b/tests/stress/fun_call_limit.py.exp @@ -1,2 +1,2 @@ -33 +32 SyntaxError diff --git a/tests/stress/qstr_limit.py b/tests/stress/qstr_limit.py index 08b10a039f509..c7bd437f3adc1 100644 --- a/tests/stress/qstr_limit.py +++ b/tests/stress/qstr_limit.py @@ -12,8 +12,8 @@ def make_id(n, base="a"): var = make_id(l) try: exec(var + "=1", g) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) continue print(var in g) @@ -26,16 +26,16 @@ def f(**k): for l in range(254, 259): try: exec("f({}=1)".format(make_id(l))) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # type construction for l in range(254, 259): id = make_id(l) try: - print(type(id, (), {}).__name__) - except RuntimeError: - print("RuntimeError", l) + print(type(id, (), {})) + except RuntimeError as er: + print("RuntimeError", er, l) # hasattr, setattr, getattr @@ -48,28 +48,20 @@ class A: a = A() try: setattr(a, id, 123) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) try: print(hasattr(a, id), getattr(a, id)) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # format with keys for l in range(254, 259): id = make_id(l) try: print(("{" + id + "}").format(**{id: l})) - except RuntimeError: - print("RuntimeError", l) - -# modulo format with keys -for l in range(254, 259): - id = make_id(l) - try: - print(("%(" + id + ")d") % {id: l}) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # import module # (different OS's have different results so only run those that are consistent) @@ -78,8 +70,8 @@ class A: __import__(make_id(l)) except ImportError: print("ok", l) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) # import package for l in (100, 101, 102, 128, 129): @@ -87,5 +79,5 @@ class A: exec("import " + make_id(l) + "." + make_id(l, "A")) except ImportError: print("ok", l) - except RuntimeError: - print("RuntimeError", l) + except RuntimeError as er: + print("RuntimeError", er, l) diff --git a/tests/stress/qstr_limit.py.exp b/tests/stress/qstr_limit.py.exp index 455761bc71e4a..2349adf220f98 100644 --- a/tests/stress/qstr_limit.py.exp +++ b/tests/stress/qstr_limit.py.exp @@ -1,43 +1,38 @@ True True -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst': 1} {'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu': 1} -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 -abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrst -abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 + + +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 True 123 True 123 -RuntimeError 256 -RuntimeError 256 -RuntimeError 257 -RuntimeError 257 -RuntimeError 258 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 257 +RuntimeError name too long 258 +RuntimeError name too long 258 254 255 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 -254 -255 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 ok 100 ok 101 -RuntimeError 256 -RuntimeError 257 -RuntimeError 258 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 ok 100 ok 101 ok 102 -RuntimeError 128 -RuntimeError 129 +RuntimeError name too long 128 +RuntimeError name too long 129 diff --git a/tests/stress/qstr_limit_str_modulo.py b/tests/stress/qstr_limit_str_modulo.py new file mode 100644 index 0000000000000..90b9f4364ec6f --- /dev/null +++ b/tests/stress/qstr_limit_str_modulo.py @@ -0,0 +1,21 @@ +# Test interning qstrs that go over the qstr length limit (255 bytes in default configuration). +# The tests here are specifically for str formatting with %. + +try: + "" % () +except TypeError: + print("SKIP") + raise SystemExit + + +def make_id(n, base="a"): + return "".join(chr(ord(base) + i % 26) for i in range(n)) + + +# modulo format with keys +for l in range(254, 259): + id = make_id(l) + try: + print(("%(" + id + ")d") % {id: l}) + except RuntimeError as er: + print("RuntimeError", er, l) diff --git a/tests/stress/qstr_limit_str_modulo.py.exp b/tests/stress/qstr_limit_str_modulo.py.exp new file mode 100644 index 0000000000000..3632c85bffea3 --- /dev/null +++ b/tests/stress/qstr_limit_str_modulo.py.exp @@ -0,0 +1,5 @@ +254 +255 +RuntimeError name too long 256 +RuntimeError name too long 257 +RuntimeError name too long 258 diff --git a/tests/stress/recursive_iternext.py b/tests/stress/recursive_iternext.py index bbc389e726237..c737f1e36d70a 100644 --- a/tests/stress/recursive_iternext.py +++ b/tests/stress/recursive_iternext.py @@ -1,4 +1,8 @@ # This tests that recursion with iternext doesn't lead to segfault. +# +# This test segfaults CPython, but that's not a bug as CPython doesn't enforce +# limits on C recursion - see +# https://github.com/python/cpython/issues/58218#issuecomment-1093570209 try: enumerate filter @@ -9,49 +13,25 @@ print("SKIP") raise SystemExit -# We need to pick an N that is large enough to hit the recursion -# limit, but not too large that we run out of heap memory. -try: - # large stack/heap, eg unix - [0] * 80000 - N = 5000 -except: - try: - # medium, eg pyboard - [0] * 10000 - N = 1000 - except: - # small, eg esp8266 - N = 100 - -try: - x = (1, 2) - for i in range(N): - x = enumerate(x) - tuple(x) -except RuntimeError: - print("RuntimeError") -try: +# Progressively build a bigger nested iterator structure (10 at a time for speed), +# and then try to evaluate it via tuple(x) which makes deep recursive function calls. +# +# Eventually this should raise a RuntimeError as MicroPython runs out of stack. +# It shouldn't ever raise a MemoryError, if it does then somehow MicroPython has +# run out of heap (for the nested structure) before running out of stack. +def recurse_iternext(nested_fn): x = (1, 2) - for i in range(N): - x = filter(None, x) - tuple(x) -except RuntimeError: - print("RuntimeError") + while True: + for _ in range(10): + x = nested_fn(x) + try: + tuple(x) + except RuntimeError: + print("RuntimeError") + break -try: - x = (1, 2) - for i in range(N): - x = map(max, x, ()) - tuple(x) -except RuntimeError: - print("RuntimeError") -try: - x = (1, 2) - for i in range(N): - x = zip(x) - tuple(x) -except RuntimeError: - print("RuntimeError") +# Test on various nested iterator structures +for nested_fn in [enumerate, lambda x: filter(None, x), lambda x: map(max, x, ()), zip]: + recurse_iternext(nested_fn) diff --git a/tests/target_wiring/EK_RA6M2.py b/tests/target_wiring/EK_RA6M2.py new file mode 100644 index 0000000000000..7d4a8cbbd6484 --- /dev/null +++ b/tests/target_wiring/EK_RA6M2.py @@ -0,0 +1,8 @@ +# Target wiring for EK_RA6M2. +# +# Connect: +# - P601 to P602 + +# UART(9) is on P602/P601. +uart_loopback_args = (9,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/NUCLEO_WB55.py b/tests/target_wiring/NUCLEO_WB55.py new file mode 100644 index 0000000000000..ad7c120d3770e --- /dev/null +++ b/tests/target_wiring/NUCLEO_WB55.py @@ -0,0 +1,8 @@ +# Target wiring for NUCLEO_WB55. +# +# Connect: +# - PA2 to PA3 + +# LPUART(1) is on PA2/PA3. +uart_loopback_args = ("LP1",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/PYBx.py b/tests/target_wiring/PYBx.py new file mode 100644 index 0000000000000..10ce520ef0af4 --- /dev/null +++ b/tests/target_wiring/PYBx.py @@ -0,0 +1,8 @@ +# Target wiring for PYBV10, PYBV11, PYBLITEV10, PYBD_SF2, PYBD_SF3, PYBD_SF6. +# +# Connect: +# - X1 to X2 + +# UART("XA") is on X1/X2 (usually UART(4) on PA0/PA1). +uart_loopback_args = ("XA",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py b/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py new file mode 100644 index 0000000000000..c7ca2ac26f794 --- /dev/null +++ b/tests/target_wiring/ZEPHYR_NUCLEO_WB55RG.py @@ -0,0 +1,7 @@ +# Target wiring for zephyr nucleo_wb55rg. +# +# Connect: +# - TX=PC0 to RX=PC1 + +uart_loopback_args = ("lpuart1",) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/alif.py b/tests/target_wiring/alif.py new file mode 100644 index 0000000000000..18f3cbe7e5e0d --- /dev/null +++ b/tests/target_wiring/alif.py @@ -0,0 +1,7 @@ +# Target wiring for general alif board. +# +# Connect: +# - UART1 TX and RX, usually P0_5 and P0_4 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/esp32.py b/tests/target_wiring/esp32.py new file mode 100644 index 0000000000000..2767cd5acb2e8 --- /dev/null +++ b/tests/target_wiring/esp32.py @@ -0,0 +1,12 @@ +# Target wiring for general esp32 board. +# +# Connect: +# - GPIO4 to GPIO5 +# - GPIO12 to GPIO13 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {"tx": 4, "rx": 5} + +encoder_loopback_id = 0 +encoder_loopback_out_pins = (4, 12) +encoder_loopback_in_pins = (5, 13) diff --git a/tests/target_wiring/mimxrt.py b/tests/target_wiring/mimxrt.py new file mode 100644 index 0000000000000..669e9095990db --- /dev/null +++ b/tests/target_wiring/mimxrt.py @@ -0,0 +1,7 @@ +# Target wiring for general mimxrt board. +# +# Connect: +# - UART1 TX and RX, usually D0 and D1 + +uart_loopback_args = (1,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/nrf.py b/tests/target_wiring/nrf.py new file mode 100644 index 0000000000000..6979dd28ee595 --- /dev/null +++ b/tests/target_wiring/nrf.py @@ -0,0 +1,7 @@ +# Target wiring for general nrf board. +# +# Connect: +# - UART0 TX and RX + +uart_loopback_args = (0,) +uart_loopback_kwargs = {} diff --git a/tests/target_wiring/rp2.py b/tests/target_wiring/rp2.py new file mode 100644 index 0000000000000..cb0fa0d626339 --- /dev/null +++ b/tests/target_wiring/rp2.py @@ -0,0 +1,7 @@ +# Target wiring for general rp2 board. +# +# Connect: +# - GPIO0 to GPIO1 + +uart_loopback_args = (0,) +uart_loopback_kwargs = {"tx": "GPIO0", "rx": "GPIO1"} diff --git a/tests/target_wiring/samd.py b/tests/target_wiring/samd.py new file mode 100644 index 0000000000000..887c43a242f9b --- /dev/null +++ b/tests/target_wiring/samd.py @@ -0,0 +1,7 @@ +# Target wiring for general samd board. +# +# Connect: +# - D0 to D1 + +uart_loopback_args = () +uart_loopback_kwargs = {"tx": "D1", "rx": "D0"} diff --git a/tests/testlib/audiofilterhelper.py b/tests/testlib/audiofilterhelper.py new file mode 100644 index 0000000000000..c182bb73c5772 --- /dev/null +++ b/tests/testlib/audiofilterhelper.py @@ -0,0 +1,33 @@ +import array +import random +from ulab import numpy as np +from math import sin, pi, ceil +from audiocore import get_buffer, RawSample +from synthio import Note, LFO, MathOperation, Synthesizer + +random.seed(41) + +whitedata = array.array("h", [random.randint(-32000, 32000) for i in range(600)]) +white8k = RawSample(whitedata, sample_rate=8000) + +sinedata = array.array("h", [int(32767 * sin(i * 2 * pi / 600)) for i in range(600)]) +sine8k = RawSample(sinedata, sample_rate=8000) + + +def synth_test(_gen=None, dtype=np.int16, divisor=32768, channel_count=1): + def func(gen): + g = gen() + synth, blocks = next(g) + t = 0 + for nframes in g: + for i in range(nframes): + samples = np.frombuffer(get_buffer(synth)[1], dtype=dtype) / divisor + block_values = [b.value for b in blocks] + for k in range(0, len(samples), channel_count): + print(t, *(list(samples[k : k + channel_count]) + block_values)) + t += 1 + + if _gen is None: + return func + else: + func(_gen) diff --git a/tests/thread/disable_irq.py b/tests/thread/disable_irq.py new file mode 100644 index 0000000000000..596e3e477b9c8 --- /dev/null +++ b/tests/thread/disable_irq.py @@ -0,0 +1,57 @@ +# Ensure that disabling IRQs creates mutual exclusion between threads +# (also tests nesting of disable_irq across threads) + +# CIRCUITPY-CHANGE: no machine +try: + import machine + import time + import _thread +except ImportError: + print("SKIP") + raise SystemExit + +if not hasattr(machine, "disable_irq"): + print("SKIP") + raise SystemExit + +count = 0 +thread_done = False + + +def inc_count(): + global count + a = machine.disable_irq() + try: + count += 1 + i = 0 + while i < 20: + b = machine.disable_irq() + try: + count += 1 + count -= 1 + i += 1 + finally: + machine.enable_irq(b) + finally: + machine.enable_irq(a) + + +def inc_count_multiple(times): + for _ in range(times): + inc_count() + + +def thread_entry(inc_times): + global thread_done + inc_count_multiple(inc_times) + thread_done = True + + +_thread.start_new_thread(thread_entry, (1000,)) +inc_count_multiple(1000) + +time.sleep(1) + +print("count", count, thread_done) +if count == 2000: + print("PASS") diff --git a/tests/thread/disable_irq.py.exp b/tests/thread/disable_irq.py.exp new file mode 100644 index 0000000000000..2174b91d0d044 --- /dev/null +++ b/tests/thread/disable_irq.py.exp @@ -0,0 +1,2 @@ +count 2000 True +PASS diff --git a/tests/thread/mutate_bytearray.py b/tests/thread/mutate_bytearray.py index b4664781a1522..7116d291cfeec 100644 --- a/tests/thread/mutate_bytearray.py +++ b/tests/thread/mutate_bytearray.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared bytearray @@ -36,7 +37,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check bytearray has correct contents print(len(ba)) diff --git a/tests/thread/mutate_dict.py b/tests/thread/mutate_dict.py index 3777af66248c6..dd5f69e6c5d66 100644 --- a/tests/thread/mutate_dict.py +++ b/tests/thread/mutate_dict.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared dict @@ -38,7 +39,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check dict has correct contents print(sorted(di.items())) diff --git a/tests/thread/mutate_instance.py b/tests/thread/mutate_instance.py index 306ad91c95cfa..63f7fb1e23df8 100644 --- a/tests/thread/mutate_instance.py +++ b/tests/thread/mutate_instance.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -40,7 +41,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check user instance has correct contents print(user.a, user.b, user.c) diff --git a/tests/thread/mutate_list.py b/tests/thread/mutate_list.py index 6f1e8812541a0..d7398a2f1e0b4 100644 --- a/tests/thread/mutate_list.py +++ b/tests/thread/mutate_list.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared list @@ -39,7 +40,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check list has correct contents li.sort() diff --git a/tests/thread/mutate_set.py b/tests/thread/mutate_set.py index 2d9a3e0ce9efd..7dcefa1d113f9 100644 --- a/tests/thread/mutate_set.py +++ b/tests/thread/mutate_set.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread # the shared set @@ -33,7 +34,7 @@ def th(n, lo, hi): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) # check set has correct contents print(sorted(se)) diff --git a/tests/thread/stress_aes.py b/tests/thread/stress_aes.py index b25da855aeffc..ca25f8ad2fd57 100644 --- a/tests/thread/stress_aes.py +++ b/tests/thread/stress_aes.py @@ -273,15 +273,15 @@ def thread_entry(n_loop): elif sys.platform == "rp2": n_thread = 1 n_loop = 2 - elif sys.platform in ("esp32", "pyboard"): + elif sys.platform in ("esp32", "pyboard", "zephyr"): n_thread = 2 n_loop = 2 else: - n_thread = 20 + n_thread = 10 n_loop = 5 for i in range(n_thread): _thread.start_new_thread(thread_entry, (n_loop,)) thread_entry(n_loop) - while count.value < n_thread: + while count.value < n_thread + 1: time.sleep(1) print("done") diff --git a/tests/thread/stress_recurse.py b/tests/thread/stress_recurse.py index 73b3a40f33daa..ec8b43fe8fc22 100644 --- a/tests/thread/stress_recurse.py +++ b/tests/thread/stress_recurse.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -24,5 +25,5 @@ def thread_entry(): # busy wait for thread to finish while not finished: - pass + time.sleep(0) print("done") diff --git a/tests/thread/stress_schedule.py b/tests/thread/stress_schedule.py index 40191e6620986..362d71aa12e38 100644 --- a/tests/thread/stress_schedule.py +++ b/tests/thread/stress_schedule.py @@ -19,6 +19,7 @@ n = 0 # How many times the task successfully ran. t = None # Start time of test, assigned here to preallocate entry in globals dict. +thread_run = True # If the thread should continue running. def task(x): @@ -26,8 +27,10 @@ def task(x): n += 1 +# This function must always use the bytecode emitter so it bounces the GIL when running. +@micropython.bytecode def thread(): - while True: + while thread_run: try: micropython.schedule(task, None) except RuntimeError: @@ -36,12 +39,22 @@ def thread(): for i in range(8): - _thread.start_new_thread(thread, ()) + try: + _thread.start_new_thread(thread, ()) + except OSError: + # System cannot create a new thead, so stop trying to create them. + break # Wait up to 10 seconds for 10000 tasks to be scheduled. t = time.ticks_ms() while n < _NUM_TASKS and time.ticks_diff(time.ticks_ms(), t) < _TIMEOUT_MS: - pass + time.sleep(0) + +# Stop all threads. +thread_run = False +time.sleep_ms(20) + +gc.enable() if n < _NUM_TASKS: # Not all the tasks were scheduled, likely the scheduler stopped working. diff --git a/tests/thread/thread_coop.py b/tests/thread/thread_coop.py new file mode 100644 index 0000000000000..85cda789c936e --- /dev/null +++ b/tests/thread/thread_coop.py @@ -0,0 +1,56 @@ +# Threads should be semi-cooperative, to the point where one busy +# thread can't starve out another. +# +# (Note on ports without the GIL this one should always be true, on ports with GIL it's +# a test of the GIL behaviour.) + +import _thread +import sys +from time import ticks_ms, ticks_diff, sleep_ms +import micropython + + +done = False + +ITERATIONS = 5 +SLEEP_MS = 250 +MAX_DELTA = 30 + +if sys.platform in ("win32", "linux", "darwin"): + # Conventional operating systems get looser timing restrictions + SLEEP_MS = 300 + MAX_DELTA = 100 + + +# This function must always use the bytecode emitter so the VM can bounce the GIL when running. +@micropython.bytecode +def busy_thread(): + while not done: + pass + + +def test_sleeps(): + global done + ok = True + for _ in range(ITERATIONS): + t0 = ticks_ms() + sleep_ms(SLEEP_MS) + t1 = ticks_ms() + d = ticks_diff(t1, t0) + if d < SLEEP_MS - MAX_DELTA or d > SLEEP_MS + MAX_DELTA: + print("Slept too long ", d) + ok = False + print("OK" if ok else "Not OK") + done = True + + +# make the thread the busy one, and check sleep time on main task +_thread.start_new_thread(busy_thread, ()) +test_sleeps() + +sleep_ms(100) +done = False + +# now swap them +_thread.start_new_thread(test_sleeps, ()) +busy_thread() diff --git a/tests/thread/thread_coop.py.exp b/tests/thread/thread_coop.py.exp new file mode 100644 index 0000000000000..2c94e48371001 --- /dev/null +++ b/tests/thread/thread_coop.py.exp @@ -0,0 +1,2 @@ +OK +OK diff --git a/tests/thread/thread_exc1.py b/tests/thread/thread_exc1.py index cd87740929103..cd6599983c141 100644 --- a/tests/thread/thread_exc1.py +++ b/tests/thread/thread_exc1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -34,5 +35,5 @@ def thread_entry(): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print("done") diff --git a/tests/thread/thread_exc2.py.native.exp b/tests/thread/thread_exc2.py.native.exp new file mode 100644 index 0000000000000..9b2e715ef8dfc --- /dev/null +++ b/tests/thread/thread_exc2.py.native.exp @@ -0,0 +1,3 @@ +Unhandled exception in thread started by +ValueError: +done diff --git a/tests/thread/thread_gc1.py b/tests/thread/thread_gc1.py index dd1e64d89444d..45c17cc17bed3 100644 --- a/tests/thread/thread_gc1.py +++ b/tests/thread/thread_gc1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import gc import _thread @@ -16,21 +17,34 @@ def thread_entry(n): data[i] = data[i] gc.collect() - # print whether the data remains intact and indicate we are finished + # check whether the data remains intact and indicate we are finished with lock: - print(list(data) == list(range(256))) - global n_finished + global n_correct, n_finished + n_correct += list(data) == list(range(256)) n_finished += 1 lock = _thread.allocate_lock() -n_thread = 4 +n_thread = 0 +n_thread_max = 4 +n_correct = 0 n_finished = 0 # spawn threads -for i in range(n_thread): - _thread.start_new_thread(thread_entry, (10,)) +for _ in range(n_thread_max): + try: + _thread.start_new_thread(thread_entry, (10,)) + n_thread += 1 + except OSError: + # System cannot create a new thead, so stop trying to create them. + break + +# also run the function on this main thread +thread_entry(10) +n_thread += 1 # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) + +print(n_correct == n_finished) diff --git a/tests/thread/thread_ident1.py b/tests/thread/thread_ident1.py index 8e106cd317f4e..08cfd3eb36e8a 100644 --- a/tests/thread/thread_ident1.py +++ b/tests/thread/thread_ident1.py @@ -2,10 +2,16 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread +# Initialise variables (also preallocate their spot in the globals dict so the +# globals dict is not resized while threads are running). tid = None +tid_main = None +new_tid = None +finished = False def thread_entry(): @@ -19,10 +25,9 @@ def thread_entry(): tid_main = _thread.get_ident() print("main", type(tid_main) == int, tid_main != 0) -finished = False new_tid = _thread.start_new_thread(thread_entry, ()) while not finished: - pass + time.sleep(0) print("done", type(new_tid) == int, new_tid == tid) diff --git a/tests/thread/thread_lock3.py b/tests/thread/thread_lock3.py index a927dc6829e15..c5acfa21b7dc6 100644 --- a/tests/thread/thread_lock3.py +++ b/tests/thread/thread_lock3.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread lock = _thread.allocate_lock() @@ -26,4 +27,4 @@ def thread_entry(idx): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) diff --git a/tests/thread/thread_lock4.py b/tests/thread/thread_lock4.py deleted file mode 100644 index 97c3dc538007d..0000000000000 --- a/tests/thread/thread_lock4.py +++ /dev/null @@ -1,51 +0,0 @@ -# test using lock to coordinate access to global mutable objects -# -# MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd - -import time -import _thread - - -def fac(n): - x = 1 - for i in range(1, n + 1): - x *= i - return x - - -def thread_entry(): - while True: - with jobs_lock: - try: - f, arg = jobs.pop(0) - except IndexError: - return - ans = f(arg) - with output_lock: - output.append((arg, ans)) - - -# create a list of jobs -jobs = [(fac, i) for i in range(20, 80)] -jobs_lock = _thread.allocate_lock() -n_jobs = len(jobs) - -# create a list to store the results -output = [] -output_lock = _thread.allocate_lock() - -# spawn threads to do the jobs -for i in range(4): - _thread.start_new_thread(thread_entry, ()) - -# wait for the jobs to complete -while True: - with jobs_lock: - if len(output) == n_jobs: - break - time.sleep(1) - -# sort and print the results -output.sort(key=lambda x: x[0]) -for arg, ans in output: - print(arg, ans) diff --git a/tests/thread/thread_lock4_intbig.py b/tests/thread/thread_lock4_intbig.py new file mode 100644 index 0000000000000..b424ee3d02f98 --- /dev/null +++ b/tests/thread/thread_lock4_intbig.py @@ -0,0 +1,55 @@ +# test using lock to coordinate access to global mutable objects +# +# MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd + +import time +import _thread + + +def fac(n): + x = 1 + for i in range(1, n + 1): + x *= i + return x + + +def thread_entry(): + while True: + with jobs_lock: + try: + f, arg = jobs.pop(0) + except IndexError: + return + ans = f(arg) + with output_lock: + output.append((arg, ans)) + + +# create a list of jobs +jobs = [(fac, i) for i in range(20, 80)] +jobs_lock = _thread.allocate_lock() +n_jobs = len(jobs) + +# create a list to store the results +output = [] +output_lock = _thread.allocate_lock() + +# spawn threads to do the jobs +for i in range(4): + try: + _thread.start_new_thread(thread_entry, ()) + except OSError: + # System cannot create a new thead, so stop trying to create them. + break + +# wait for the jobs to complete +while True: + with jobs_lock: + if len(output) == n_jobs: + break + time.sleep(0) + +# sort and print the results +output.sort(key=lambda x: x[0]) +for arg, ans in output: + print(arg, ans) diff --git a/tests/thread/thread_qstr1.py b/tests/thread/thread_qstr1.py index f184d2a58e1d4..96f12c5d8c93f 100644 --- a/tests/thread/thread_qstr1.py +++ b/tests/thread/thread_qstr1.py @@ -24,16 +24,26 @@ def th(base, n): lock = _thread.allocate_lock() -n_thread = 4 +n_thread = 0 +n_thread_max = 4 n_finished = 0 n_qstr_per_thread = 100 # make 1000 for a more stressful test (uses more heap) # spawn threads -for i in range(n_thread): - _thread.start_new_thread(th, (i * n_qstr_per_thread, n_qstr_per_thread)) +for _ in range(n_thread_max): + try: + _thread.start_new_thread(th, (n_thread * n_qstr_per_thread, n_qstr_per_thread)) + n_thread += 1 + except OSError: + # System cannot create a new thead, so stop trying to create them. + break + +# also run the function on this main thread +th(n_thread * n_qstr_per_thread, n_qstr_per_thread) +n_thread += 1 # wait for threads to finish while n_finished < n_thread: - time.sleep(1) + time.sleep(0) print("pass") diff --git a/tests/thread/thread_shared1.py b/tests/thread/thread_shared1.py index 582b01fc34356..c2e33abcec7ee 100644 --- a/tests/thread/thread_shared1.py +++ b/tests/thread/thread_shared1.py @@ -2,6 +2,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -18,17 +19,27 @@ def thread_entry(n, tup): lock = _thread.allocate_lock() -n_thread = 2 +n_thread = 0 +n_thread_max = 2 n_finished = 0 # the shared data structure tup = (1, 2, 3, 4) # spawn threads -for i in range(n_thread): - _thread.start_new_thread(thread_entry, (100, tup)) +for _ in range(n_thread_max): + try: + _thread.start_new_thread(thread_entry, (100, tup)) + n_thread += 1 + except OSError: + # System cannot create a new thead, so stop trying to create them. + break + +# also run the function on this main thread +thread_entry(100, tup) +n_thread += 1 # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print(tup) diff --git a/tests/thread/thread_shared2.py b/tests/thread/thread_shared2.py index a1223c2b94f40..4ce9057ca017e 100644 --- a/tests/thread/thread_shared2.py +++ b/tests/thread/thread_shared2.py @@ -3,6 +3,7 @@ # # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd +import time import _thread @@ -31,5 +32,5 @@ def thread_entry(n, lst, idx): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print(lst) diff --git a/tests/thread/thread_sleep1.py b/tests/thread/thread_sleep1.py index add9b02f1573b..36f775d1f6eff 100644 --- a/tests/thread/thread_sleep1.py +++ b/tests/thread/thread_sleep1.py @@ -12,7 +12,8 @@ import _thread lock = _thread.allocate_lock() -n_thread = 4 +n_thread = 0 +n_thread_max = 4 n_finished = 0 @@ -24,10 +25,20 @@ def thread_entry(t): n_finished += 1 -for i in range(n_thread): - _thread.start_new_thread(thread_entry, (10 * i,)) +# spawn threads +for _ in range(n_thread_max): + try: + _thread.start_new_thread(thread_entry, (10 * n_thread,)) + n_thread += 1 + except OSError: + # System cannot create a new thead, so stop trying to create them. + break + +# also run the function on this main thread +thread_entry(10 * n_thread) +n_thread += 1 # wait for threads to finish while n_finished < n_thread: sleep_ms(100) -print("done", n_thread) +print("done") diff --git a/tests/thread/thread_sleep2.py b/tests/thread/thread_sleep2.py new file mode 100644 index 0000000000000..2dec24cabec93 --- /dev/null +++ b/tests/thread/thread_sleep2.py @@ -0,0 +1,31 @@ +# Test accuracy of sleep within a thread. + +import time +import _thread + + +def sleep(t, valid_range): + t0 = time.time_ns() + time.sleep(t) + dt_ms = (time.time_ns() - t0) // 1_000_000 + if dt_ms in valid_range: + print("dt in range", t) + else: + print("dt not in range:", dt_ms) + + +def thread_entry(): + lock.acquire() + print("thread start") + sleep(0.2, range(180, 400)) + print("thread end") + + +lock = _thread.allocate_lock() +lock.acquire() +_thread.start_new_thread(thread_entry, ()) + +print("main start") +lock.release() +sleep(0.5, range(480, 800)) +print("main end") diff --git a/tests/thread/thread_stacksize1.py b/tests/thread/thread_stacksize1.py index 140d165cb3497..75e1da9642f95 100644 --- a/tests/thread/thread_stacksize1.py +++ b/tests/thread/thread_stacksize1.py @@ -3,6 +3,7 @@ # MIT license; Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd import sys +import time import _thread # different implementations have different minimum sizes @@ -51,5 +52,5 @@ def thread_entry(): # busy wait for threads to finish while n_finished < n_thread: - pass + time.sleep(0) print("done") diff --git a/tests/thread/thread_stdin.py b/tests/thread/thread_stdin.py new file mode 100644 index 0000000000000..498b0a3a27022 --- /dev/null +++ b/tests/thread/thread_stdin.py @@ -0,0 +1,45 @@ +# Test that having multiple threads block on stdin doesn't cause any issues. +# +# The test doesn't expect any input on stdin. +# +# This is a regression test for https://github.com/micropython/micropython/issues/15230 +# on rp2, but doubles as a general property to test across all ports. +import sys +import time +import _thread + +try: + import select +except ImportError: + print("SKIP") + raise SystemExit + + +class StdinWaiter: + def __init__(self): + self._done = False + + def wait_stdin(self, timeout_ms): + poller = select.poll() + poller.register(sys.stdin, select.POLLIN) + poller.poll(timeout_ms) + # Ignoring the poll result as we don't expect any input + self._done = True + + def is_done(self): + return self._done + + +thread_waiter = StdinWaiter() +_thread.start_new_thread(thread_waiter.wait_stdin, (1000,)) +StdinWaiter().wait_stdin(1000) + +# Spinning here is mostly not necessary but there is some inconsistency waking +# the two threads, especially on CPython CI runners where the thread may not +# have run yet. The actual delay is <20ms but spinning here instead of +# sleep(0.1) means the test can run on MP builds without float support. +while not thread_waiter.is_done(): + time.sleep(0) + +# The background thread should have completed its wait by now. +print(thread_waiter.is_done()) diff --git a/tests/unicode/unicode.py b/tests/unicode/unicode.py index 072e049fde416..58d406e63eb2a 100644 --- a/tests/unicode/unicode.py +++ b/tests/unicode/unicode.py @@ -5,7 +5,7 @@ # Test all three forms of Unicode escape, and # all blocks of UTF-8 byte patterns -s = "a\xA9\xFF\u0123\u0800\uFFEE\U0001F44C" +s = "a\xa9\xff\u0123\u0800\uffee\U0001f44c" for i in range(-len(s), len(s)): print("s[%d]: %s %X" % (i, s[i], ord(s[i]))) print("s[:%d]: %d chars, '%s'" % (i, len(s[:i]), s[:i])) diff --git a/tests/unix/extra_coverage.py b/tests/unix/extra_coverage.py index 0ea8f7886bfff..ec10a44ff39b3 100644 --- a/tests/unix/extra_coverage.py +++ b/tests/unix/extra_coverage.py @@ -6,6 +6,16 @@ import errno import io +import uctypes + +# create an int-like variable used for coverage of `mp_obj_get_ll` +buf = bytearray(b"\xde\xad\xbe\xef") +struct = uctypes.struct( + uctypes.addressof(buf), + {"f32": uctypes.UINT32 | 0}, + uctypes.BIG_ENDIAN, +) +deadbeef = struct.f32 data = extra_coverage() @@ -23,6 +33,7 @@ print(stream.read(1)) # read 1 byte encounters non-blocking error print(stream.readline()) # readline encounters non-blocking error print(stream.readinto(bytearray(10))) # readinto encounters non-blocking error +print(stream.readinto1(bytearray(10))) # readinto1 encounters non-blocking error print(stream.write(b"1")) # write encounters non-blocking error print(stream.write1(b"1")) # write1 encounters non-blocking error stream.set_buf(b"123") @@ -38,6 +49,28 @@ stream.set_error(0) print(stream.ioctl(0, bytearray(10))) # successful ioctl call +print("# stream.readinto") + +# stream.readinto will read 3 bytes then try to read more to fill the buffer, +# but on the second attempt will encounter EIO and should raise that error. +stream.set_error(errno.EIO) +stream.set_buf(b"123") +buf = bytearray(4) +try: + stream.readinto(buf) +except OSError as er: + print("OSError", er.errno == errno.EIO) +print(buf) + +# stream.readinto1 will read 3 bytes then should return them immediately, and +# not encounter the EIO. +stream.set_error(errno.EIO) +stream.set_buf(b"123") +buf = bytearray(4) +print(stream.readinto1(buf), buf) + +print("# stream textio") + stream2 = data[3] # is textio print(stream2.read(1)) # read 1 byte encounters non-blocking error with textio stream @@ -92,7 +125,7 @@ print(returns_NULL()) -# test for freeze_mpy +# test for freeze_mpy (importing prints several lines) import frozentest print(frozentest.__file__) diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp index c75676fad9aff..cdb1145569497 100644 --- a/tests/unix/extra_coverage.py.exp +++ b/tests/unix/extra_coverage.py.exp @@ -2,25 +2,41 @@ -123 +123 123 -0123 123 -123 -1ABCDEF +123f +123F +7fffffffffffffff +7FFFFFFFFFFFFFFF +18446744073709551615 +789f +789F ab abc ' abc' ' True' 'Tru' false true (null) -2147483648 2147483648 -80000000 -80000000 +8000000f +8000000F abc % +.a . +<%> + + +<43690> +<43690> +<43690> + +<1000.000000> + +<9223372036854775807> # GC -0x0 -0x0 +0 +0 # GC part 2 pass # tracked allocation -m_tracked_head = 0x0 +m_tracked_head = 0 0 1 1 1 2 1 @@ -37,7 +53,7 @@ m_tracked_head = 0x0 5 1 6 1 7 1 -m_tracked_head = 0x0 +m_tracked_head = 0 # vstr tests sts @@ -90,19 +106,29 @@ data 1 12345 6 +-1 +0 +1 +0 +0.000000 +deadbeef +c0ffee777c0ffee +deadbeef +0deadbeef +c0ffee +000c0ffee # runtime utils TypeError: unsupported type for __abs__: 'str' TypeError: unsupported types for __divmod__: 'str', 'str' +0 1 2 OverflowError: overflow converting long int to machine word OverflowError: overflow converting long int to machine word +TypeError: can't convert NoneType to int +TypeError: can't convert NoneType to int ValueError: Warning: test -# format float -? -+1e+00 -+1e+00 # binary 123 456 @@ -122,6 +148,13 @@ unlocked KeyboardInterrupt: KeyboardInterrupt: 10 +loop +scheduled function +loop +scheduled function +loop +scheduled function +scheduled function # ringbuf 99 0 98 1 @@ -144,6 +177,11 @@ cc99 22ff -1 -1 +0 +0 +abc123 +-1 +-2 # pairheap create: 0 0 0 0 pop all: 0 1 2 3 @@ -164,6 +202,8 @@ pop all: 1 2 4 5 1 1 0 0 1 1 +# stackctrl +1 1 # end coverage.c 0123456789 b'0123456789' 7300 @@ -176,11 +216,17 @@ None None None None +None b'123' b'123' b'123' OSError 0 +# stream.readinto +OSError True +bytearray(b'123\x00') +3 bytearray(b'123\x00') +# stream textio None None cpp None @@ -203,8 +249,10 @@ ZeroDivisionError X '\x1b' b'\x00\xff' +frzmpy4 1 +frzmpy4 2 NULL -uPy +interned a long string that is not interned a string that has unicode αβγ chars b'bytes 1234\x01' diff --git a/tests/unix/ffi_float2.py b/tests/unix/ffi_float2.py index bbed6966627e1..eac6cd106cf43 100644 --- a/tests/unix/ffi_float2.py +++ b/tests/unix/ffi_float2.py @@ -29,4 +29,5 @@ def ffi_open(names): for fun in (tgammaf,): for val in (0.5, 1, 1.0, 1.5, 4, 4.0): - print("%.6f" % fun(val)) + # limit to 5 decimals in order to pass with REPR_C with FORMAT_IMPL_BASIC + print("%.5f" % fun(val)) diff --git a/tests/unix/ffi_float2.py.exp b/tests/unix/ffi_float2.py.exp index 58fc6a01acb07..4c750e223a3a6 100644 --- a/tests/unix/ffi_float2.py.exp +++ b/tests/unix/ffi_float2.py.exp @@ -1,6 +1,6 @@ -1.772454 -1.000000 -1.000000 -0.886227 -6.000000 -6.000000 +1.77245 +1.00000 +1.00000 +0.88623 +6.00000 +6.00000 diff --git a/tests/unix/ffi_int_base.py b/tests/unix/ffi_int_base.py new file mode 100644 index 0000000000000..906bc3c1e1467 --- /dev/null +++ b/tests/unix/ffi_int_base.py @@ -0,0 +1,49 @@ +# common tests for ffi_int_types/long32/long64 +# requires ffi_lib.c to be compiled as: $(CC) -shared -o ffi_lib.so ffi_lib.c + +import os, sys + +try: + import ffi +except ImportError: + print("SKIP") + raise SystemExit + +ffi_lib_filename = sys.argv[0].rsplit("/", 1)[0] + "/ffi_lib.so" +try: + os.stat(ffi_lib_filename) +except OSError: + print("SKIP") + raise SystemExit + +ffi_lib = ffi.open(ffi_lib_filename) + + +def test(funcs): + for type, name in funcs: + func = ffi_lib.func(type, name, type) + for val in ( + 0, + 0x7F, + 0x80, + 0xFF, + 0x100, + 0x7FFF, + 0x8000, + 0xFFFF, + 0x10000, + 0x7FFFFFFF, + 0x80000000, + 0xFFFFFFFF, + 0x100000000, + 0x7FFF_FFFF_FFFF_FFFF, + 0x8000_0000_0000_0000, + 0xFFFF_FFFF_FFFF_FFFF, + 0x1_0000_0000_0000_0000, + ): + print("{}({:x}) = {:x}".format(name, val, func(val))) + + +if __name__ == "__main__": + print("SKIP") + raise SystemExit diff --git a/tests/unix/ffi_int_long32.py b/tests/unix/ffi_int_long32.py new file mode 100644 index 0000000000000..32fdb8e0ec7df --- /dev/null +++ b/tests/unix/ffi_int_long32.py @@ -0,0 +1,16 @@ +# test 32-bit long arguments and return types for ffi functions + +import struct + +import ffi_int_base + +if struct.calcsize("l") != 4: + print("SKIP") + raise SystemExit + +ffi_int_base.test( + [ + ("l", "fli"), + ("L", "flu"), + ] +) diff --git a/tests/unix/ffi_int_long32.py.exp b/tests/unix/ffi_int_long32.py.exp new file mode 100644 index 0000000000000..e0f1338a48ed2 --- /dev/null +++ b/tests/unix/ffi_int_long32.py.exp @@ -0,0 +1,34 @@ +fli(0) = 1 +fli(7f) = 7e +fli(80) = 81 +fli(ff) = fe +fli(100) = 101 +fli(7fff) = 7ffe +fli(8000) = 8001 +fli(ffff) = fffe +fli(10000) = 10001 +fli(7fffffff) = 7ffffffe +fli(80000000) = -7fffffff +fli(ffffffff) = -2 +fli(100000000) = 1 +fli(7fffffffffffffff) = -2 +fli(8000000000000000) = 1 +fli(ffffffffffffffff) = -2 +fli(10000000000000000) = 1 +flu(0) = 1 +flu(7f) = 7e +flu(80) = 81 +flu(ff) = fe +flu(100) = 101 +flu(7fff) = 7ffe +flu(8000) = 8001 +flu(ffff) = fffe +flu(10000) = 10001 +flu(7fffffff) = 7ffffffe +flu(80000000) = 80000001 +flu(ffffffff) = fffffffe +flu(100000000) = 1 +flu(7fffffffffffffff) = fffffffe +flu(8000000000000000) = 1 +flu(ffffffffffffffff) = fffffffe +flu(10000000000000000) = 1 diff --git a/tests/unix/ffi_int_long64.py b/tests/unix/ffi_int_long64.py new file mode 100644 index 0000000000000..55bf6605232f0 --- /dev/null +++ b/tests/unix/ffi_int_long64.py @@ -0,0 +1,16 @@ +# test 64-bit long arguments and return types for ffi functions + +import struct + +import ffi_int_base + +if struct.calcsize("l") != 8: + print("SKIP") + raise SystemExit + +ffi_int_base.test( + [ + ("l", "fli"), + ("L", "flu"), + ] +) diff --git a/tests/unix/ffi_int_long64.py.exp b/tests/unix/ffi_int_long64.py.exp new file mode 100644 index 0000000000000..904e6c3ed445e --- /dev/null +++ b/tests/unix/ffi_int_long64.py.exp @@ -0,0 +1,34 @@ +fli(0) = 1 +fli(7f) = 7e +fli(80) = 81 +fli(ff) = fe +fli(100) = 101 +fli(7fff) = 7ffe +fli(8000) = 8001 +fli(ffff) = fffe +fli(10000) = 10001 +fli(7fffffff) = 7ffffffe +fli(80000000) = 80000001 +fli(ffffffff) = fffffffe +fli(100000000) = 100000001 +fli(7fffffffffffffff) = 7ffffffffffffffe +fli(8000000000000000) = -7fffffffffffffff +fli(ffffffffffffffff) = -2 +fli(10000000000000000) = 1 +flu(0) = 1 +flu(7f) = 7e +flu(80) = 81 +flu(ff) = fe +flu(100) = 101 +flu(7fff) = 7ffe +flu(8000) = 8001 +flu(ffff) = fffe +flu(10000) = 10001 +flu(7fffffff) = 7ffffffe +flu(80000000) = 80000001 +flu(ffffffff) = fffffffe +flu(100000000) = 100000001 +flu(7fffffffffffffff) = 7ffffffffffffffe +flu(8000000000000000) = 8000000000000001 +flu(ffffffffffffffff) = fffffffffffffffe +flu(10000000000000000) = 1 diff --git a/tests/unix/ffi_int_types.py b/tests/unix/ffi_int_types.py new file mode 100644 index 0000000000000..24fa2a721b210 --- /dev/null +++ b/tests/unix/ffi_int_types.py @@ -0,0 +1,16 @@ +# test 8/16/32/64 bit signed/unsigned integer arguments and return types for ffi functions + +import ffi_int_base + +ffi_int_base.test( + [ + ("b", "f8i"), + ("B", "f8u"), + ("h", "f16i"), + ("H", "f16u"), + ("i", "f32i"), + ("I", "f32u"), + ("q", "f64i"), + ("Q", "f64u"), + ] +) diff --git a/tests/unix/ffi_int_types.py.exp b/tests/unix/ffi_int_types.py.exp new file mode 100644 index 0000000000000..d6324477d6105 --- /dev/null +++ b/tests/unix/ffi_int_types.py.exp @@ -0,0 +1,136 @@ +f8i(0) = 1 +f8i(7f) = 7e +f8i(80) = -7f +f8i(ff) = -2 +f8i(100) = 1 +f8i(7fff) = -2 +f8i(8000) = 1 +f8i(ffff) = -2 +f8i(10000) = 1 +f8i(7fffffff) = -2 +f8i(80000000) = 1 +f8i(ffffffff) = -2 +f8i(100000000) = 1 +f8i(7fffffffffffffff) = -2 +f8i(8000000000000000) = 1 +f8i(ffffffffffffffff) = -2 +f8i(10000000000000000) = 1 +f8u(0) = 1 +f8u(7f) = 7e +f8u(80) = 81 +f8u(ff) = fe +f8u(100) = 1 +f8u(7fff) = fe +f8u(8000) = 1 +f8u(ffff) = fe +f8u(10000) = 1 +f8u(7fffffff) = fe +f8u(80000000) = 1 +f8u(ffffffff) = fe +f8u(100000000) = 1 +f8u(7fffffffffffffff) = fe +f8u(8000000000000000) = 1 +f8u(ffffffffffffffff) = fe +f8u(10000000000000000) = 1 +f16i(0) = 1 +f16i(7f) = 7e +f16i(80) = 81 +f16i(ff) = fe +f16i(100) = 101 +f16i(7fff) = 7ffe +f16i(8000) = -7fff +f16i(ffff) = -2 +f16i(10000) = 1 +f16i(7fffffff) = -2 +f16i(80000000) = 1 +f16i(ffffffff) = -2 +f16i(100000000) = 1 +f16i(7fffffffffffffff) = -2 +f16i(8000000000000000) = 1 +f16i(ffffffffffffffff) = -2 +f16i(10000000000000000) = 1 +f16u(0) = 1 +f16u(7f) = 7e +f16u(80) = 81 +f16u(ff) = fe +f16u(100) = 101 +f16u(7fff) = 7ffe +f16u(8000) = 8001 +f16u(ffff) = fffe +f16u(10000) = 1 +f16u(7fffffff) = fffe +f16u(80000000) = 1 +f16u(ffffffff) = fffe +f16u(100000000) = 1 +f16u(7fffffffffffffff) = fffe +f16u(8000000000000000) = 1 +f16u(ffffffffffffffff) = fffe +f16u(10000000000000000) = 1 +f32i(0) = 1 +f32i(7f) = 7e +f32i(80) = 81 +f32i(ff) = fe +f32i(100) = 101 +f32i(7fff) = 7ffe +f32i(8000) = 8001 +f32i(ffff) = fffe +f32i(10000) = 10001 +f32i(7fffffff) = 7ffffffe +f32i(80000000) = -7fffffff +f32i(ffffffff) = -2 +f32i(100000000) = 1 +f32i(7fffffffffffffff) = -2 +f32i(8000000000000000) = 1 +f32i(ffffffffffffffff) = -2 +f32i(10000000000000000) = 1 +f32u(0) = 1 +f32u(7f) = 7e +f32u(80) = 81 +f32u(ff) = fe +f32u(100) = 101 +f32u(7fff) = 7ffe +f32u(8000) = 8001 +f32u(ffff) = fffe +f32u(10000) = 10001 +f32u(7fffffff) = 7ffffffe +f32u(80000000) = 80000001 +f32u(ffffffff) = fffffffe +f32u(100000000) = 1 +f32u(7fffffffffffffff) = fffffffe +f32u(8000000000000000) = 1 +f32u(ffffffffffffffff) = fffffffe +f32u(10000000000000000) = 1 +f64i(0) = 1 +f64i(7f) = 7e +f64i(80) = 81 +f64i(ff) = fe +f64i(100) = 101 +f64i(7fff) = 7ffe +f64i(8000) = 8001 +f64i(ffff) = fffe +f64i(10000) = 10001 +f64i(7fffffff) = 7ffffffe +f64i(80000000) = 80000001 +f64i(ffffffff) = fffffffe +f64i(100000000) = 100000001 +f64i(7fffffffffffffff) = 7ffffffffffffffe +f64i(8000000000000000) = -7fffffffffffffff +f64i(ffffffffffffffff) = -2 +f64i(10000000000000000) = 1 +f64u(0) = 1 +f64u(7f) = 7e +f64u(80) = 81 +f64u(ff) = fe +f64u(100) = 101 +f64u(7fff) = 7ffe +f64u(8000) = 8001 +f64u(ffff) = fffe +f64u(10000) = 10001 +f64u(7fffffff) = 7ffffffe +f64u(80000000) = 80000001 +f64u(ffffffff) = fffffffe +f64u(100000000) = 100000001 +f64u(7fffffffffffffff) = 7ffffffffffffffe +f64u(8000000000000000) = 8000000000000001 +f64u(ffffffffffffffff) = fffffffffffffffe +f64u(10000000000000000) = 1 diff --git a/tests/unix/ffi_lib.c b/tests/unix/ffi_lib.c index 35340536aeede..dae4e04bc4463 100644 --- a/tests/unix/ffi_lib.c +++ b/tests/unix/ffi_lib.c @@ -31,3 +31,11 @@ int64_t f64i(int64_t x) { uint64_t f64u(uint64_t x) { return x ^ 1; } + +long fli(long x) { + return x ^ 1; +} + +unsigned long flu(unsigned long x) { + return x ^ 1; +} diff --git a/tests/unix/mod_os.py b/tests/unix/mod_os.py index f69fa45b2b22a..468f6badd1e75 100644 --- a/tests/unix/mod_os.py +++ b/tests/unix/mod_os.py @@ -1,6 +1,9 @@ # This module is not entirely compatible with CPython import os +if not hasattr(os, "getenv"): + print("SKIP") + raise SystemExit os.putenv("TEST_VARIABLE", "TEST_VALUE") diff --git a/tests/unix/time_mktime_localtime.py b/tests/unix/time_mktime_localtime.py index d1c03c103d704..df5d6cda690a2 100644 --- a/tests/unix/time_mktime_localtime.py +++ b/tests/unix/time_mktime_localtime.py @@ -1,4 +1,8 @@ -import time +try: + import time +except ImportError: + print("SKIP") + raise SystemExit DAYS_PER_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] diff --git a/tools/.gitignore b/tools/.gitignore deleted file mode 100644 index 9f65f493bc655..0000000000000 --- a/tools/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -tinytest/.gitignore -tinytest/.travis.yml -tinytest/Makefile -tinytest/Makefile.arm-cortex-m3-qemu -tinytest/Makefile.avr -tinytest/TODO -tinytest/portable_demo.c -tinytest/tinytest_demo.c diff --git a/tools/analyze_heap_dump.py b/tools/analyze_heap_dump.py index a5e5e1d48eabb..a7be95db7d9f3 100755 --- a/tools/analyze_heap_dump.py +++ b/tools/analyze_heap_dump.py @@ -82,7 +82,7 @@ help="Draw the ownership graph of blocks on the heap", ) @click.option("--analyze-snapshots", default="last", type=click.Choice(["all", "last"])) -def do_all_the_things( +def do_all_the_things( # noqa: C901 too complex ram_filename, bin_filename, map_filename, diff --git a/tools/analyze_mpy.py b/tools/analyze_mpy.py index 3f212e2679188..f8da7a85f9dc9 100755 --- a/tools/analyze_mpy.py +++ b/tools/analyze_mpy.py @@ -229,7 +229,7 @@ def __init__(self, encoded_raw_code): while bc.peek(1)[0] == 0xFF: bc.read(1) bc = bytearray(bc.read()) - # print(encoded_code_info, bc) + print(encoded_code_info, bc) self.qstrs = [] diff --git a/tools/ar_util.py b/tools/ar_util.py new file mode 100644 index 0000000000000..b90d379031467 --- /dev/null +++ b/tools/ar_util.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python3 +# +# This file is part of the MicroPython project, http://micropython.org/ +# +# The MIT License (MIT) +# +# Copyright (c) 2024 Volodymyr Shymanskyy +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import os +import re +import hashlib +import functools +import pickle + +from elftools.elf import elffile +from collections import defaultdict + +try: + from ar import Archive +except: + Archive = None + + +class PickleCache: + def __init__(self, path, prefix=""): + self.path = path + self._get_fn = lambda key: os.path.join(path, prefix + key[:24]) + + def store(self, key, data): + os.makedirs(self.path, exist_ok=True) + # See also https://bford.info/cachedir/ + cachedir_tag_path = os.path.join(self.path, "CACHEDIR.TAG") + if not os.path.exists(cachedir_tag_path): + with open(cachedir_tag_path, "w") as f: + f.write( + "Signature: 8a477f597d28d172789f06886806bc55\n" + "# This file is a cache directory tag created by MicroPython.\n" + "# For information about cache directory tags see https://bford.info/cachedir/\n" + ) + with open(self._get_fn(key), "wb") as f: + pickle.dump(data, f) + + def load(self, key): + with open(self._get_fn(key), "rb") as f: + return pickle.load(f) + + +def cached(key, cache): + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + cache_key = key(*args, **kwargs) + try: + d = cache.load(cache_key) + if d["key"] != cache_key: + raise Exception("Cache key mismatch") + return d["data"] + except Exception: + res = func(*args, **kwargs) + try: + cache.store( + cache_key, + { + "key": cache_key, + "data": res, + }, + ) + except Exception: + pass + return res + + return wrapper + + return decorator + + +class CachedArFile: + def __init__(self, fn): + if not Archive: + raise RuntimeError("Please run 'pip install ar' to link .a files") + self.fn = fn + self._archive = Archive(open(fn, "rb")) + info = self.load_symbols() + self.objs = info["objs"] + self.symbols = info["symbols"] + + def open(self, obj): + return self._archive.open(obj, "rb") + + def _cache_key(self): + sha = hashlib.sha256() + with open(self.fn, "rb") as f: + for chunk in iter(lambda: f.read(4096), b""): + sha.update(chunk) + # Change this salt if the cache data format changes + sha.update(bytes.fromhex("00000000000000000000000000000001")) + return sha.hexdigest() + + @cached(key=_cache_key, cache=PickleCache(path=".mpy_ld_cache", prefix="ar_")) + def load_symbols(self): + print("Loading", self.fn) + objs = defaultdict(lambda: {"def": set(), "undef": set(), "weak": set()}) + symbols = {} + for entry in self._archive: + obj_name = entry.name + elf = elffile.ELFFile(self.open(obj_name)) + symtab = elf.get_section_by_name(".symtab") + if not symtab: + continue + + obj = objs[obj_name] + + for symbol in symtab.iter_symbols(): + sym_name = symbol.name + sym_bind = symbol["st_info"]["bind"] + + if sym_bind in ("STB_GLOBAL", "STB_WEAK"): + if symbol.entry["st_shndx"] != "SHN_UNDEF": + obj["def"].add(sym_name) + symbols[sym_name] = obj_name + else: + obj["undef"].add(sym_name) + + if sym_bind == "STB_WEAK": + obj["weak"].add(sym_name) + + return {"objs": dict(objs), "symbols": symbols} + + +def resolve(archives, symbols): + resolved_objs = [] # Object files needed to resolve symbols + unresolved_symbols = set() + provided_symbols = {} # Which symbol is provided by which object + symbol_stack = list(symbols) + + # A helper function to handle symbol resolution from a particular object + def add_obj(archive, symbol): + obj_name = archive.symbols[symbol] + obj_info = archive.objs[obj_name] + + obj_tuple = (archive, obj_name) + if obj_tuple in resolved_objs: + return # Already processed this object + + resolved_objs.append(obj_tuple) + + # Add the symbols this object defines + for defined_symbol in obj_info["def"]: + if defined_symbol in provided_symbols and not defined_symbol.startswith( + "__x86.get_pc_thunk." + ): + if defined_symbol in obj_info["weak"]: + continue + else: + raise RuntimeError(f"Multiple definitions for {defined_symbol}") + provided_symbols[defined_symbol] = obj_name # TODO: mark weak if needed + + # Recursively add undefined symbols from this object + for undef_symbol in obj_info["undef"]: + if undef_symbol in obj_info["weak"]: + print(f"Skippping weak dependency: {undef_symbol}") + continue + if undef_symbol not in provided_symbols: + symbol_stack.append(undef_symbol) # Add undefined symbol to resolve + + while symbol_stack: + symbol = symbol_stack.pop(0) + + if symbol in provided_symbols: + continue # Symbol is already resolved + + found = False + for archive in archives: + if symbol in archive.symbols: + add_obj(archive, symbol) + found = True + break + + if not found: + unresolved_symbols.add(symbol) + + return resolved_objs, list(unresolved_symbols) + + +def expand_ld_script(fn): + # This function parses a subset of ld scripts + # Typically these are just groups of static lib references + group_pattern = re.compile(r"GROUP\s*\(\s*([^\)]+)\s*\)", re.MULTILINE) + output_format_pattern = re.compile(r"OUTPUT_FORMAT\s*\(\s*([^\)]+)\s*\)", re.MULTILINE) + comment_pattern = re.compile(r"/\*.*?\*/", re.MULTILINE | re.DOTALL) + + with open(fn, "r") as f: + content = f.read() + content = comment_pattern.sub("", content).strip() + + # Ensure no unrecognized instructions + leftovers = content + for pattern in (group_pattern, output_format_pattern): + leftovers = pattern.sub("", leftovers) + if leftovers.strip(): + raise ValueError("Invalid instruction found in the ld script:" + leftovers) + + # Extract files from GROUP instructions + files = [] + for match in group_pattern.findall(content): + files.extend([file.strip() for file in re.split(r"[,\s]+", match) if file.strip()]) + + return files + + +def load_archive(fn): + ar_header = b"!\012" + with open(fn, "rb") as f: + is_ar_file = f.read(len(ar_header)) == ar_header + if is_ar_file: + return [CachedArFile(fn)] + else: + return [CachedArFile(item) for item in expand_ld_script(fn)] diff --git a/tools/black_bindings.py b/tools/black_bindings.py deleted file mode 100755 index 1c6fa3cfe89bd..0000000000000 --- a/tools/black_bindings.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/python3 -import os -import re -import subprocess -import sys -from concurrent.futures import ThreadPoolExecutor -from dataclasses import dataclass -from enum import Enum, auto - -MARK_C_IN_PY = "##| " -MARK_PY_IN_C = "//| " - - -class Mode(Enum): - C = auto() - PY = auto() - - -@dataclass(frozen=True) -class LineWithMode: - data: str - mode: Mode - - -class OutputWriter: - def __init__(self): - self.content = [] - - def write(self, line): - self.content.append(line.rstrip()) - - def getcontent(self): - return "\n".join(self.content) - - -class PythonOutputWriter(OutputWriter): - def write(self, line): - if isinstance(line, str): - super().write(line) - elif line.mode == Mode.PY: - super().write(line.data) - else: # line mode is C - super().write(MARK_C_IN_PY + line.data) - - -class COutputWriter(OutputWriter): - def write(self, line): - if isinstance(line, str): - super().write(line) - elif line.mode == Mode.PY: - super().write(MARK_PY_IN_C + line.data) - else: # line mode is C - super().write(line.data) - - -def parse_line(line, defmode, mark, smark, markmode): - sline = line.strip() - if sline == smark or sline.startswith(mark): - return LineWithMode(sline[len(mark) :], markmode) - else: - return LineWithMode(line, defmode) - - -def parse_lines(lines, defmode, mark, markmode): - smark = mark.strip() - return [parse_line(line, defmode, mark, smark, markmode) for line in lines] - - -def swap_comment_markers(content, input_mode): - lines = content.rstrip().split("\n") - - if input_mode == Mode.C: - parsed = parse_lines(lines, Mode.C, MARK_PY_IN_C, Mode.PY) - writer = PythonOutputWriter() - else: - parsed = parse_lines(lines, Mode.PY, MARK_C_IN_PY, Mode.C) - writer = COutputWriter() - - for line in parsed: - writer.write(line) - - newcontent = writer.getcontent() + "\n" - - return newcontent - - -def process_one_file(fn): - with open(fn, "r", encoding="utf-8") as f: - c_content = f.read() - - if not "\n//| " in c_content: - return - - py_content = swap_comment_markers(c_content, Mode.C) - - try: - # Line length is 95 so that with "//| " the max is 99 - result = subprocess.run( - ["black", "--pyi", "-l95", "-q", "-"], - input=py_content, - check=True, - stdout=subprocess.PIPE, - encoding="utf-8", - ) - except subprocess.CalledProcessError as e: - print(f"{fn}:0: Failed to process file ") - raise - - new_py_content = result.stdout - new_c_content = swap_comment_markers(new_py_content, Mode.PY) - - if new_c_content != c_content: - with open(fn, "w", encoding="utf-8") as f: - f.write(new_c_content) - - -if __name__ == "__main__": - # Use a thread pool because most processing is inside black! - executor = ThreadPoolExecutor(max_workers=os.cpu_count()) - futures = [executor.submit(process_one_file, fn) for fn in sys.argv[1:]] - status = 0 - for f in futures: - try: - f.result() - except Exception as e: - print(e) - status = 1 - executor.shutdown() - raise SystemExit(status) diff --git a/tools/board_stubs/build_board_specific_stubs/board_stub_builder.py b/tools/board_stubs/build_board_specific_stubs/board_stub_builder.py index a35f50719016e..fb6219f373b3b 100644 --- a/tools/board_stubs/build_board_specific_stubs/board_stub_builder.py +++ b/tools/board_stubs/build_board_specific_stubs/board_stub_builder.py @@ -27,6 +27,7 @@ def get_board_pins(pin_filename): continue board_member = search.group(1) + extra_typing = None board_type_search = re.search(r"MP_ROM_PTR\(&pin_(.*?)\)", line) if board_type_search: @@ -38,8 +39,18 @@ def get_board_pins(pin_filename): board_type_search = re.search( r"MP_ROM_PTR\(&(.*?)\[0\].[display|epaper_display]", line ) + + if board_type_search is None: + board_type_search = re.search(r"MP_ROM_PTR\(&(.*?)_tuple", line) + if board_type_search is not None: + extra_typing = "Tuple[Any]" + if board_type_search is None: + board_type_search = re.search(r"MP_ROM_PTR\(&(.*?)_dict", line) + if board_type_search is not None: + extra_typing = "Dict[str, Any]" + if board_type_search is None: - records.append(["unmapped", None, line]) + records.append(["unmapped", None, line, extra_typing]) continue board_type = board_type_search.group(1) @@ -56,7 +67,7 @@ def get_board_pins(pin_filename): if extra_search: extra = extra_search.group(1) - records.append([board_type, board_member, extra]) + records.append([board_type, board_member, extra, extra_typing]) return records @@ -69,8 +80,10 @@ def create_board_stubs(board_id, records, mappings, board_filename): needs_busio = False needs_displayio = False needs_microcontroller = False + needs_dict = False + needs_tuple = False - for board_type, board_member, extra in records: + for board_type, board_member, extra, extra_typing in records: if board_type == "pin": needs_microcontroller = True comment = f" # {extra}" @@ -121,6 +134,13 @@ def create_board_stubs(board_id, records, mappings, board_filename): member_data += f"{board_member}: {class_name}\n" members.append(member_data) + elif extra_typing is not None: + if "Dict" in extra_typing: + needs_dict = True + elif "Tuple" in extra_typing: + needs_tuple = True + members.append(f"{board_member}: {extra_typing}\n") + elif board_type == "unmapped": unmapped.append(extra) @@ -137,10 +157,10 @@ def create_board_stubs(board_id, records, mappings, board_filename): boards_file.write("#\n") boards_file.write("# SPDX-License-Identifier: MIT\n") boards_file.write('"""\n') - boards_file.write(f'Board stub for {mappings["board_name"]}\n') - boards_file.write(f' - port: {mappings["port"]}\n') + boards_file.write(f"Board stub for {mappings['board_name']}\n") + boards_file.write(f" - port: {mappings['port']}\n") boards_file.write(f" - board_id: {board_id}\n") - boards_file.write(f' - NVM size: {mappings["nvm_size"]}\n') + boards_file.write(f" - NVM size: {mappings['nvm_size']}\n") boards_file.write(f" - Included modules: {included_modules}\n") boards_file.write(f" - Frozen libraries: {frozen_libraries}\n") boards_file.write('"""\n\n') @@ -152,6 +172,14 @@ def create_board_stubs(board_id, records, mappings, board_filename): if needs_microcontroller: boards_file.write("import microcontroller\n") + if needs_dict: + if needs_tuple: + boards_file.write("from typing import Any, Dict, Tuple\n") + else: + boards_file.write("from typing import Any, Dict\n") + elif needs_tuple: + boards_file.write("from typing import Any, Tuple\n") + boards_file.write("\n\n") boards_file.write("# Board Info:\n") boards_file.write("board_id: str\n") @@ -200,7 +228,7 @@ def process(board_mappings, export_dir): records = get_board_pins(pin_filename) create_board_stubs(board_id, records, mappings, f"{sub_dir}/__init__.pyi") - for board_type, board_member, extra in records: + for board_type, board_member, extra, extra_typing in records: if board_type == "pin": total_pins += 1 elif board_type == "unmapped": @@ -269,7 +297,7 @@ def build_stubs(circuitpython_dir, circuitpython_org_dir, export_dir, version="8 else: lookup = board - port_path = f'{circuitpython_dir}ports/{board_data["port"]}/' + port_path = f"{circuitpython_dir}ports/{board_data['port']}/" board_path = f"{port_path}boards/{lookup}/" pins_path = f"{board_path}pins.c" if not os.path.isfile(pins_path): diff --git a/tools/board_stubs/circuitpython_setboard/__init__.py b/tools/board_stubs/circuitpython_setboard/__init__.py index 3a73beb3119df..69a405405b800 100644 --- a/tools/board_stubs/circuitpython_setboard/__init__.py +++ b/tools/board_stubs/circuitpython_setboard/__init__.py @@ -12,7 +12,12 @@ import shutil from collections import defaultdict from importlib import resources -from importlib.abc import Traversable + +try: + from importlib.resources.abc import Traversable +except ModuleNotFoundError: + # 3.10 and earlier. + from importlib.abc import Traversable def get_definitions_or_exit(board: str) -> Traversable: diff --git a/tools/board_summaries.py b/tools/board_summaries.py index 08ddc644af48d..3ea87e68d5590 100644 --- a/tools/board_summaries.py +++ b/tools/board_summaries.py @@ -61,7 +61,7 @@ def frozen_incidence_matrix_csvs(support_matrix, rows=1000, present="1", absent= all_frozen = set() for info in support_matrix.values(): frozen = info["frozen_libraries"] - frozen = [f[0] if type(f) == tuple else f for f in frozen] + frozen = [f[0] if isinstance(f, tuple) else f for f in frozen] all_frozen.update(frozen) all_frozen = sorted(all_frozen) csvs = [] @@ -75,7 +75,7 @@ def frozen_incidence_matrix_csvs(support_matrix, rows=1000, present="1", absent= chip_pin_set = set([chip_pin for _, chip_pin in info["pins"]]) n_chip_pins = len(chip_pin_set) - frozen = [f[0] if type(f) == tuple else f for f in frozen] + frozen = [f[0] if isinstance(f, tuple) else f for f in frozen] frozen_incidence = [present if f in frozen else absent for f in all_frozen] line = ( f"{board},{info.get('branded_name')},{info.get('mcu')}," @@ -150,8 +150,7 @@ def board_pins_matrix_csvs(support_matrix, rows=1000): for board, info in support_matrix.items(): if (row % rows) == 0: csv = [ - "board,branded_name,mcu,flash,port,n_board_pins," - "board_pins,n_chip_pins,chip_pins\n" + "board,branded_name,mcu,flash,port,n_board_pins,board_pins,n_chip_pins,chip_pins\n" ] board_pins = [board_pin for board_pin, _ in info["pins"]] chip_pins = [chip_pin for _, chip_pin in info["pins"]] @@ -186,12 +185,12 @@ def write_csvs(rows=1000, present="1", absent="0"): "frozen": frozen_incidence_matrix_csvs(s, rows=rows, present=present, absent=absent), "pins": board_pins_matrix_csvs(s, rows=rows), } - for key in csvs: - for i in range(len(csvs[key])): + for key, values in csvs: + for i in range(len(values)): filename = f"{key}_{i}.csv" print(f"writing {filename}") with open(filename, "w") as f: - f.writelines(csvs[key][i]) + f.writelines(values[i]) if __name__ == "__main__": diff --git a/tools/board_to_port.py b/tools/board_to_port.py new file mode 100644 index 0000000000000..325105f987389 --- /dev/null +++ b/tools/board_to_port.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 + +# SPDX-FileCopyrightText: 2025 CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) +# +# SPDX-License-Identifier: MIT + +import sys +from pathlib import Path + +docs = Path(__file__).parent.parent / "docs" +sys.path.append(str(docs)) +from shared_bindings_matrix import get_board_mapping + +board = sys.argv[1] + +board_mapping = get_board_mapping() +if board in board_mapping: + board_info = board_mapping[board] + print(board_info["port"]) + sys.exit(0) + +raise ValueError(f"No port directory associated with the board tag given {board}.") diff --git a/tools/boardgen.py b/tools/boardgen.py index caa9fe851c768..3723e7ce31b83 100644 --- a/tools/boardgen.py +++ b/tools/boardgen.py @@ -108,6 +108,10 @@ def add_board_pin_name(self, board_pin_name, hidden=False): ) ) + # Iterate over board pin names in consistent sorted order. + def board_pin_names(self): + return sorted(self._board_pin_names, key=lambda x: x[0]) + # Override this to handle an af specified in af.csv. def add_af(self, af_idx, af_name, af): raise NotImplementedError @@ -172,6 +176,8 @@ def __init__(self, pin_type, enable_af=False): self._pins = [] self._pin_type = pin_type self._enable_af = enable_af + self._pin_cpu_num_entries = 0 + self._pin_board_num_entries = 0 # Allows a port to define a known cpu pin (without relying on it being in the # csv file). @@ -289,15 +295,18 @@ def find_pin_by_cpu_pin_name(self, cpu_pin_name, create=True): def print_board_locals_dict(self, out_source): print(file=out_source) print( - "STATIC const mp_rom_map_elem_t machine_pin_board_pins_locals_dict_table[] = {", + "static const mp_rom_map_elem_t machine_pin_board_pins_locals_dict_table[] = {", file=out_source, ) for pin in self.available_pins(): - for board_pin_name, board_hidden in pin._board_pin_names: + for board_pin_name, board_hidden in pin.board_pin_names(): if board_hidden: # Don't include hidden pins in Pins.board. continue + # Keep track of the total number of Pin.board entries. + self._pin_board_num_entries += 1 + # We don't use the enable macro for board pins, because they # shouldn't be referenced in pins.csv unless they're # available. @@ -318,10 +327,13 @@ def print_board_locals_dict(self, out_source): def print_cpu_locals_dict(self, out_source): print(file=out_source) print( - "STATIC const mp_rom_map_elem_t machine_pin_cpu_pins_locals_dict_table[] = {", + "static const mp_rom_map_elem_t machine_pin_cpu_pins_locals_dict_table[] = {", file=out_source, ) for pin in self.available_pins(exclude_hidden=True): + # Keep track of the total number of Pin.cpu entries. + self._pin_cpu_num_entries += 1 + m = pin.enable_macro() if m: print(" #if {}".format(m), file=out_source) @@ -351,6 +363,20 @@ def board_name_define_prefix(self): # Print the pin_CPUNAME and pin_BOARDNAME macros. def print_defines(self, out_header, cpu=True, board=True): + # Provide #defines for the number of cpu and board pins. + print( + "#define MICROPY_PY_MACHINE_PIN_CPU_NUM_ENTRIES ({})".format( + self._pin_cpu_num_entries + ), + file=out_header, + ) + print( + "#define MICROPY_PY_MACHINE_PIN_BOARD_NUM_ENTRIES ({})".format( + self._pin_board_num_entries + ), + file=out_header, + ) + # Provide #defines for each cpu pin. for pin in self.available_pins(): print(file=out_header) @@ -367,7 +393,7 @@ def print_defines(self, out_header, cpu=True, board=True): # #define pin_BOARDNAME (pin_CPUNAME) if board: - for board_pin_name, _board_hidden in pin._board_pin_names: + for board_pin_name, _board_hidden in pin.board_pin_names(): # Note: Hidden board pins are still available to C via the macro. # Note: The RHS isn't wrapped in (), which is necessary to make the # STATIC_AF_ macro work on STM32. diff --git a/tools/build-stm-latest.sh b/tools/build-stm-latest.sh deleted file mode 100755 index bfee1b1922e85..0000000000000 --- a/tools/build-stm-latest.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/bash - -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -# function for building firmware -function do_build() { - descr=$1 - board=$2 - shift - shift - echo "building $descr $board" - build_dir=/tmp/stm-build-$board - make -B $@ BOARD=$board BUILD=$build_dir || exit 1 - mv $build_dir/firmware.dfu $dest_dir/$descr-$date-$git_tag.dfu - rm -rf $build_dir -} - -# check/get parameters -if [ $# != 1 ]; then - echo "usage: $0 " - exit 1 -fi - -dest_dir=$1 - -# check we are in the correct directory -if [ ! -r modpyb.c ]; then - echo "must be in stm directory" - exit 1 -fi - -# get the date -date=$(date '+%Y-%m-%d') - -# get the git tag -git_tag="$(git describe --dirty || echo unknown)" - -# build the versions -do_build pybv3 PYBV3 -do_build pybv3-network PYBV3 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 -do_build pybv10 PYBV10 -do_build pybv10-network PYBV10 MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1 -do_build stm32f4disc STM32F4DISC -do_build espruino-pico ESPRUINO_PICO diff --git a/tools/build_board_info.py b/tools/build_board_info.py index 44f2f4759d4e4..8b56539a233b4 100755 --- a/tools/build_board_info.py +++ b/tools/build_board_info.py @@ -173,6 +173,14 @@ def create_pr(changes, updated, git_info, user): changes["new_release"], boards, languages ) + # Sync main so that the fork has the same commit sha1 + sync_main = {"branch": "main"} + response = github.post( + "/repos/{}/circuitpython-org/merge-upstream".format(user), json=sync_main + ) + if not response.ok: + raise SystemExit(f"unable to sync main: {response.text}") + create_branch = {"ref": "refs/heads/" + branch_name, "sha": commit_sha} response = github.post("/repos/{}/circuitpython-org/git/refs".format(user), json=create_branch) if not response.ok and response.json()["message"] != "Reference already exists": @@ -216,9 +224,6 @@ def print_active_user(): def generate_download_info(): - boards = {} - errors = [] - new_tag = os.environ["RELEASE_TAG"] changes = {"new_release": new_tag, "new_boards": [], "new_languages": []} @@ -251,29 +256,21 @@ def generate_download_info(): board_mapping = get_board_mapping() - for port in SUPPORTED_PORTS: - board_path = os.path.join("../ports", port, "boards") - for board_path in os.scandir(board_path): - if board_path.is_dir(): - board_files = os.listdir(board_path.path) - board_id = board_path.name - board_info = board_mapping[board_id] - for alias in [board_id] + board_info["aliases"]: - alias_info = board_mapping[alias] - if alias not in current_info: - changes["new_boards"].append(alias) - current_info[alias] = {"downloads": 0, "versions": []} - new_version = { - "stable": new_stable, - "version": new_tag, - "languages": languages, - # add modules, extensions, frozen_libraries explicitly - "modules": support_matrix[alias]["modules"], - "extensions": support_matrix[alias]["extensions"], - "frozen_libraries": support_matrix[alias]["frozen_libraries"], - } - current_info[alias]["downloads"] = alias_info["download_count"] - current_info[alias]["versions"].append(new_version) + for board_id, board_info in board_mapping.items(): + if board_id not in current_info: + changes["new_boards"].append(board_id) + current_info[board_id] = {"downloads": 0, "versions": []} + new_version = { + "stable": new_stable, + "version": new_tag, + "languages": languages, + # add modules, extensions, frozen_libraries explicitly + "modules": support_matrix[board_id]["modules"], + "extensions": support_matrix[board_id]["extensions"], + "frozen_libraries": support_matrix[board_id]["frozen_libraries"], + } + current_info[board_id]["downloads"] = board_info["download_count"] + current_info[board_id]["versions"].append(new_version) changes["new_languages"] = set(languages) - previous_languages diff --git a/tools/build_memory_info.py b/tools/build_memory_info.py index 09d2e72a6416f..ff5bbfad710ce 100755 --- a/tools/build_memory_info.py +++ b/tools/build_memory_info.py @@ -38,8 +38,7 @@ if line.startswith(("FLASH_FIRMWARE", "RAM")): regions[line.split()[0]] = line.split("=")[-1] -for region in regions: - space = regions[region] +for region, space in regions.items(): if "/*" in space: space = space.split("/*")[0] space = K_PATTERN.sub(K_REPLACE, space) diff --git a/tools/build_release_files.py b/tools/build_release_files.py index d8f5e3c3de711..25ae0facd1b90 100755 --- a/tools/build_release_files.py +++ b/tools/build_release_files.py @@ -10,12 +10,16 @@ import subprocess import shutil import build_board_info as build_info +import pathlib import time import json +import tomllib sys.path.append("../docs") from shared_bindings_matrix import get_settings_from_makefile +TOP = pathlib.Path(__file__).resolve().parent.parent + for port in build_info.SUPPORTED_PORTS: result = subprocess.run("rm -rf ../ports/{port}/build*".format(port=port), shell=True) @@ -44,7 +48,25 @@ bin_directory = "../bin/{}/".format(board) os.makedirs(bin_directory, exist_ok=True) board_info = all_boards[board] - board_settings = get_settings_from_makefile("../ports/" + board_info["port"], board) + if board_info["port"] == "zephyr-cp": + # Split the vendor portion out of the board name. + next_underscore = board.find("_") + while next_underscore != -1: + vendor = board[:next_underscore] + target = board[next_underscore + 1 :] + cp_toml = TOP / f"ports/zephyr-cp/boards/{vendor}/{target}/circuitpython.toml" + if cp_toml.exists(): + break + next_underscore = board.find("_", next_underscore + 1) + board_settings = {"CLEAN_REBUILD_LANGUAGES": []} + with cp_toml.open("rb") as f: + board_settings.update(tomllib.load(f)) + else: + board_settings = get_settings_from_makefile("../ports/" + board_info["port"], board) + board_settings["CIRCUITPY_BUILD_EXTENSIONS"] = [ + extension.strip() + for extension in board_settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",") + ] languages.remove(LANGUAGE_FIRST) languages.insert(0, LANGUAGE_FIRST) @@ -54,27 +76,27 @@ os.makedirs(bin_directory, exist_ok=True) start_time = time.monotonic() - # Normally different language builds are all done based on the same set of compiled sources. - # But sometimes a particular language needs to be built from scratch, if, for instance, - # CFLAGS_INLINE_LIMIT is set for a particular language to make it fit. - clean_build_check_result = subprocess.run( - "make -C ../ports/{port} TRANSLATION={language} BOARD={board} check-release-needs-clean-build -j {cores} | fgrep 'RELEASE_NEEDS_CLEAN_BUILD = 1'".format( - port=board_info["port"], language=language, board=board, cores=cores - ), - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - clean_build = clean_build_check_result.returncode == 0 + if "CLEAN_REBUILD_LANGUAGES" in board_settings: + clean_build = language in board_settings["CLEAN_REBUILD_LANGUAGES"] + else: + # Normally different language builds are all done based on the same set of compiled sources. + # But sometimes a particular language needs to be built from scratch, if, for instance, + # CFLAGS_INLINE_LIMIT is set for a particular language to make it fit. + clean_build_check_result = subprocess.run( + "make -C ../ports/{port} TRANSLATION={language} BOARD={board} check-release-needs-clean-build -j {cores} | fgrep 'RELEASE_NEEDS_CLEAN_BUILD = 1'".format( + port=board_info["port"], language=language, board=board, cores=cores + ), + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + clean_build = clean_build_check_result.returncode == 0 build_dir = "build-{board}".format(board=board) if clean_build: build_dir += "-{language}".format(language=language) - extensions = [ - extension.strip() - for extension in board_settings["CIRCUITPY_BUILD_EXTENSIONS"].split(",") - ] + extensions = board_settings["CIRCUITPY_BUILD_EXTENSIONS"] artifacts = [os.path.join(build_dir, "firmware." + extension) for extension in extensions] make_result = subprocess.run( diff --git a/tools/cc1 b/tools/cc1 index 827d5886a04f5..aa2534f01e7bb 100755 --- a/tools/cc1 +++ b/tools/cc1 @@ -23,8 +23,8 @@ import re # TODO somehow make them externally configurable # this is the path to the true C compiler -cc1_path = '/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1' -#cc1_path = '/usr/lib/gcc/arm-none-eabi/5.3.0/cc1' +cc1_path = "/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/cc1" +# cc1_path = '/usr/lib/gcc/arm-none-eabi/5.3.0/cc1' # this must be the same as MICROPY_QSTR_BYTES_IN_HASH bytes_in_qstr_hash = 2 @@ -41,11 +41,16 @@ print_debug = False ################################################################################ # precompile regexs -re_preproc_line = re.compile(r'# [0-9]+ ') -re_map_entry = re.compile(r'\{.+?\(MP_QSTR_([A-Za-z0-9_]+)\).+\},') -re_mp_obj_dict_t = re.compile(r'(?P(static )?const mp_obj_dict_t (?P[a-z0-9_]+) = \{ \.base = \{&mp_type_dict\}, \.map = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') -re_mp_map_t = re.compile(r'(?P(static )?const mp_map_t (?P[a-z0-9_]+) = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$') -re_mp_rom_map_elem_t = re.compile(r'static const mp_rom_map_elem_t [a-z_0-9]+\[\] = {$') +re_preproc_line = re.compile(r"# [0-9]+ ") +re_map_entry = re.compile(r"\{.+?\(MP_QSTR_([A-Za-z0-9_]+)\).+\},") +re_mp_obj_dict_t = re.compile( + r"(?P(static )?const mp_obj_dict_t (?P[a-z0-9_]+) = \{ \.base = \{&mp_type_dict\}, \.map = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$" +) +re_mp_map_t = re.compile( + r"(?P(static )?const mp_map_t (?P[a-z0-9_]+) = \{ \.all_keys_are_qstrs = 1, \.is_fixed = 1, \.is_ordered = )1(?P, \.used = .+ };)$" +) +re_mp_rom_map_elem_t = re.compile(r"static const mp_rom_map_elem_t [a-z_0-9]+\[\] = {$") + # this must match the equivalent function in qstr.c def compute_hash(qstr): @@ -55,18 +60,19 @@ def compute_hash(qstr): # Make sure that valid hash is never zero, zero means "hash not computed" return (hash & ((1 << (8 * bytes_in_qstr_hash)) - 1)) or 1 + # this algo must match the equivalent in map.c def hash_insert(map, key, value): hash = compute_hash(key) pos = hash % len(map) start_pos = pos if print_debug: - print(' insert %s: start at %u/%u -- ' % (key, pos, len(map)), end='') + print(" insert %s: start at %u/%u -- " % (key, pos, len(map)), end="") while True: if map[pos] is None: # found empty slot, so key is not in table if print_debug: - print('put at %u' % pos) + print("put at %u" % pos) map[pos] = (key, value) return else: @@ -76,6 +82,7 @@ def hash_insert(map, key, value): pos = (pos + 1) % len(map) assert pos != start_pos + def hash_find(map, key): hash = compute_hash(key) pos = hash % len(map) @@ -92,6 +99,7 @@ def hash_find(map, key): if pos == start_pos: return attempts, None + def process_map_table(file, line, output): output.append(line) @@ -101,7 +109,7 @@ def process_map_table(file, line, output): while True: line = file.readline() if len(line) == 0: - print('unexpected end of input') + print("unexpected end of input") sys.exit(1) line = line.strip() if len(line) == 0: @@ -110,38 +118,38 @@ def process_map_table(file, line, output): if re_preproc_line.match(line): # preprocessor line number comment continue - if line == '};': + if line == "};": # end of table (we assume it appears on a single line) break table_contents.append(line) # make combined string of entries - entries_str = ''.join(table_contents) + entries_str = "".join(table_contents) # split into individual entries entries = [] while entries_str: # look for single entry, by matching nested braces match = None - if entries_str[0] == '{': + if entries_str[0] == "{": nested_braces = 0 for i in range(len(entries_str)): - if entries_str[i] == '{': + if entries_str[i] == "{": nested_braces += 1 - elif entries_str[i] == '}': + elif entries_str[i] == "}": nested_braces -= 1 if nested_braces == 0: - match = re_map_entry.match(entries_str[:i + 2]) + match = re_map_entry.match(entries_str[: i + 2]) break if not match: - print('unknown line in table:', entries_str) + print("unknown line in table:", entries_str) sys.exit(1) # extract single entry line = match.group(0) qstr = match.group(1) - entries_str = entries_str[len(line):].lstrip() + entries_str = entries_str[len(line) :].lstrip() # add the qstr and the whole line to list of all entries entries.append((qstr, line)) @@ -164,28 +172,28 @@ def process_map_table(file, line, output): attempts, line = hash_find(map, qstr) assert line is not None if print_debug: - print(' %s lookup took %u attempts' % (qstr, attempts)) + print(" %s lookup took %u attempts" % (qstr, attempts)) total_attempts += attempts - if len(entries): + if entries: stats = len(map), len(entries) / len(map), total_attempts / len(entries) else: stats = 0, 0, 0 if print_debug: - print(' table stats: size=%d, load=%.2f, avg_lookups=%.1f' % stats) + print(" table stats: size=%d, load=%.2f, avg_lookups=%.1f" % stats) # output hash table for row in map: if row is None: - output.append('{ 0, 0 },\n') + output.append("{ 0, 0 },\n") else: - output.append(row[1] + '\n') - output.append('};\n') + output.append(row[1] + "\n") + output.append("};\n") # skip to next non-blank line while True: line = file.readline() if len(line) == 0: - print('unexpected end of input') + print("unexpected end of input") sys.exit(1) line = line.strip() if len(line) == 0: @@ -197,19 +205,20 @@ def process_map_table(file, line, output): if match is None: match = re_mp_map_t.match(line) if match is None: - print('expecting mp_obj_dict_t or mp_map_t definition') + print("expecting mp_obj_dict_t or mp_map_t definition") print(output[0]) print(line) sys.exit(1) - line = match.group('head') + '0' + match.group('tail') + '\n' + line = match.group("head") + "0" + match.group("tail") + "\n" output.append(line) - return (match.group('id'),) + stats + return (match.group("id"),) + stats + def process_file(filename): output = [] file_changed = False - with open(filename, 'rt') as f: + with open(filename, "rt") as f: while True: line = f.readline() if not line: @@ -218,39 +227,41 @@ def process_file(filename): file_changed = True stats = process_map_table(f, line, output) if print_stats: - print(' [%s: size=%d, load=%.2f, avg_lookups=%.1f]' % stats) + print(" [%s: size=%d, load=%.2f, avg_lookups=%.1f]" % stats) else: output.append(line) if file_changed: if print_debug: - print(' modifying static maps in', output[0].strip()) - with open(filename, 'wt') as f: + print(" modifying static maps in", output[0].strip()) + with open(filename, "wt") as f: for line in output: f.write(line) + def main(): # run actual C compiler # need to quote args that have special characters in them def quote(s): - if s.find('<') != -1 or s.find('>') != -1: + if s.find("<") != -1 or s.find(">") != -1: return "'" + s + "'" else: return s - ret = os.system(cc1_path + ' ' + ' '.join(quote(s) for s in sys.argv[1:])) + + ret = os.system(cc1_path + " " + " ".join(quote(s) for s in sys.argv[1:])) if ret != 0: - ret = (ret & 0x7f) or 127 # make it in range 0-127, but non-zero + ret = (ret & 0x7F) or 127 # make it in range 0-127, but non-zero sys.exit(ret) - if sys.argv[1] == '-E': + if sys.argv[1] == "-E": # CPP has been run, now do our processing stage for i, arg in enumerate(sys.argv): - if arg == '-o': + if arg == "-o": return process_file(sys.argv[i + 1]) print('%s: could not find "-o" option' % (sys.argv[0],)) sys.exit(1) - elif sys.argv[1] == '-fpreprocessed': + elif sys.argv[1] == "-fpreprocessed": # compiler has been run, nothing more to do return else: @@ -258,5 +269,6 @@ def main(): print('%s: unknown first option "%s"' % (sys.argv[0], sys.argv[1])) sys.exit(1) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/tools/chart_code_size.py b/tools/chart_code_size.py index cefe3b809488c..f3d9c5bdc40f5 100644 --- a/tools/chart_code_size.py +++ b/tools/chart_code_size.py @@ -24,7 +24,7 @@ def parse_hex(h): @click.command() @click.argument("elf_filename") -def do_all_the_things(elf_filename): +def do_all_the_things(elf_filename): # noqa: C901 too complex symbol = None last_address = 0 all_symbols = {} @@ -124,7 +124,7 @@ def do_all_the_things(elf_filename): if not symbol_stack[-1]["subtype"]: symbol_stack[-1]["subtype"] = symbol elif symbol_stack[-1]["subtype"]["type"] == symbol["type"]: - second_subtype = True + pass else: raise RuntimeError() elif tag == "DW_AT_upper_bound": @@ -164,7 +164,6 @@ def do_all_the_things(elf_filename): # print(line) pass - MEMORY_NONE = 0 MEMORY_POINTER = 1 MEMORY_PY_OBJECT = 2 @@ -214,15 +213,14 @@ def get_pointer_map(t, depth=0): return {} # Do a second pass to dereference the types - for symbol_address in symbols_by_memory_address: - symbol = symbols_by_memory_address[symbol_address] + for symbol_address, symbol in symbols_by_memory_address.items(): if "type" in symbol: if symbol["debug_type"] == "DW_TAG_variable": symbol["pointer_map"] = get_pointer_map(symbols_by_debug_address[symbol["type"]]) type_string = [] t = symbol["type"] offset = [] - while t != None: + while t is not None: t_symbol = symbols_by_debug_address[t] t = t_symbol.get("type", None) if "name" in t_symbol: @@ -252,7 +250,6 @@ def get_pointer_map(t, depth=0): text_dump_lines = text_dump.stdout.decode("utf-8").split("\n") section = None symbol = None - symbol_type = None for line in text_dump_lines[4:]: if line.startswith("Disassembly of section"): section = line.split()[-1].strip(":") @@ -267,7 +264,6 @@ def get_pointer_map(t, depth=0): symbol_address = parse_hex(symbol_address) symbol_name = symbol_name.strip("<>:") if symbol_name in symbols_by_linkage_name: - linked_name = symbol_name symbol = symbols_by_linkage_name[symbol_name] if "name" in symbol: non_linkage = symbol["name"] @@ -303,10 +299,8 @@ def get_pointer_map(t, depth=0): if symbol["debug_type"] == "DW_TAG_subprogram": symbol["outgoing_jumps"] = set() symbol["incoming_jumps"] = set() - symbol_type = None elif symbol["debug_type"] == "DW_TAG_variable": symbol["outgoing_pointers"] = set() - symbol_type = symbols_by_debug_address[symbol["type"]] all_symbols[symbol_name] = symbol elif line[0] == " ": @@ -360,8 +354,7 @@ def get_pointer_map(t, depth=0): print("converting outgoing pointers to names") # Convert outgoing pointers to names from addresses - for symbol_name in all_symbols: - symbol = all_symbols[symbol_name] + for symbol_name, symbol in all_symbols.items(): if "outgoing_pointers" not in symbol: continue converted = set() @@ -378,8 +371,7 @@ def get_pointer_map(t, depth=0): print("linking back") # Link back - for symbol_name in all_symbols: - symbol = all_symbols[symbol_name] + for symbol_name, symbol in all_symbols.items(): if "outgoing_jumps" in symbol: for outgoing in symbol["outgoing_jumps"]: if outgoing not in all_symbols: diff --git a/tools/ci.sh b/tools/ci.sh index 95b1f19ffc4a6..132fbd8f81cf3 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -9,18 +9,38 @@ fi # Ensure known OPEN_MAX (NO_FILES) limit. ulimit -n 1024 +# Fail on some things which are warnings otherwise +export MICROPY_MAINTAINER_BUILD=1 + ######################################################################################## # general helper functions function ci_gcc_arm_setup { + sudo apt-get update sudo apt-get install gcc-arm-none-eabi libnewlib-arm-none-eabi arm-none-eabi-gcc --version } +function ci_gcc_riscv_setup { + sudo apt-get update + sudo apt-get install gcc-riscv64-unknown-elf picolibc-riscv64-unknown-elf + riscv64-unknown-elf-gcc --version +} + +function ci_picotool_setup { + # Manually installing picotool ensures we use a release version, and speeds up the build. + git clone https://github.com/raspberrypi/pico-sdk.git + (cd pico-sdk && git submodule update --init lib/mbedtls) + git clone https://github.com/raspberrypi/picotool.git + (cd picotool && mkdir build && cd build && cmake -DPICO_SDK_PATH=../../pico-sdk .. && make && sudo make install) + picotool version +} + ######################################################################################## # c code formatting function ci_c_code_formatting_setup { + sudo apt-get update sudo apt-get install uncrustify uncrustify --version } @@ -30,27 +50,22 @@ function ci_c_code_formatting_run { tools/codeformat.py -v -c } -######################################################################################## -# code spelling - -function ci_code_spell_setup { - pip3 install codespell tomli -} - -function ci_code_spell_run { - codespell -} - ######################################################################################## # commit formatting function ci_commit_formatting_run { - git remote add upstream https://github.com/micropython/micropython.git - git fetch --depth=100 upstream master + # Default GitHub Actions checkout for a PR is a generated merge commit where + # the parents are the head of base branch (i.e. master) and the head of the + # PR branch, respectively. Use these parents to find the merge-base (i.e. + # where the PR branch head was branched) + # If the common ancestor commit hasn't been found, fetch more. - git merge-base upstream/master HEAD || git fetch --unshallow upstream master - # For a PR, upstream/master..HEAD ends with a merge commit into master, exclude that one. - tools/verifygitlog.py -v upstream/master..HEAD --no-merges + git merge-base HEAD^1 HEAD^2 || git fetch --unshallow origin + + MERGE_BASE=$(git merge-base HEAD^1 HEAD^2) + HEAD=$(git rev-parse HEAD^2) + echo "Checking commits between merge base ${MERGE_BASE} and PR head ${HEAD}..." + tools/verifygitlog.py -v "${MERGE_BASE}..${HEAD}" } ######################################################################################## @@ -61,49 +76,110 @@ function ci_code_size_setup { sudo apt-get install gcc-multilib gcc --version ci_gcc_arm_setup + ci_gcc_riscv_setup + ci_picotool_setup +} + +function _ci_is_git_merge { + [[ $(git log -1 --format=%P "$1" | wc -w) > 1 ]] } function ci_code_size_build { # check the following ports for the change in their code size - PORTS_TO_CHECK=bmusxpd - SUBMODULES="lib/asf4 lib/berkeley-db-1.xx lib/mbedtls lib/micropython-lib lib/nxp_driver lib/pico-sdk lib/stm32lib lib/tinyusb" - - # starts off at either the ref/pull/N/merge FETCH_HEAD, or the current branch HEAD - git checkout -b pull_request # save the current location - git remote add upstream https://github.com/micropython/micropython.git - git fetch --depth=100 upstream master - # If the common ancestor commit hasn't been found, fetch more. - git merge-base upstream/master HEAD || git fetch --unshallow upstream master - # build reference, save to size0 - # ignore any errors with this build, in case master is failing - git checkout `git merge-base --fork-point upstream/master pull_request` - git submodule update --init $SUBMODULES - git show -s - tools/metrics.py clean $PORTS_TO_CHECK - tools/metrics.py build $PORTS_TO_CHECK | tee ~/size0 || true - # build PR/branch, save to size1 - git checkout pull_request - git submodule update --init $SUBMODULES - git log upstream/master..HEAD - tools/metrics.py clean $PORTS_TO_CHECK - tools/metrics.py build $PORTS_TO_CHECK | tee ~/size1 + # Override the list by setting PORTS_TO_CHECK in the environment before invoking ci. + : ${PORTS_TO_CHECK:=bmusxpdv} + + SUBMODULES="lib/asf4 lib/berkeley-db-1.xx lib/btstack lib/cyw43-driver lib/lwip lib/mbedtls lib/micropython-lib lib/nxp_driver lib/pico-sdk lib/stm32lib lib/tinyusb" + + # Default GitHub pull request sets HEAD to a generated merge commit + # between PR branch (HEAD^2) and base branch (i.e. master) (HEAD^1). + # + # We want to compare this generated commit with the base branch, to see what + # the code size impact would be if we merged this PR. During CI we are at a merge commit, + # so this tests the merged PR against its merge base. + # Override the refs by setting REFERENCE and/or COMPARISON in the environment before invoking ci. + : ${COMPARISON:=$(git rev-parse --short HEAD)} + : ${REFERENCE:=$(git rev-parse --short ${COMPARISON}^1)} + + echo "Comparing sizes of reference ${REFERENCE} to ${COMPARISON}..." + git log --oneline $REFERENCE..$COMPARISON + + OLD_BRANCH="$(git rev-parse --abbrev-ref HEAD)" + + ( # Execute in a subshell so the trap & code_size_build_step doesn't leak + function code_size_build_step { + if [ ! -z "$OLD_BRANCH" ]; then + trap 'git checkout "$OLD_BRANCH"' RETURN EXIT ERR + fi + + COMMIT=$1 + OUTFILE=$2 + IGNORE_ERRORS=$3 + + git checkout --detach $COMMIT + git submodule update --init $SUBMODULES + git show -s + tools/metrics.py clean "$PORTS_TO_CHECK" + # Allow errors from tools/metrics.py to propagate out of the pipe below. + set -o pipefail + tools/metrics.py build "$PORTS_TO_CHECK" | tee -a $OUTFILE || $IGNORE_ERRORS + return $? + } + + # build reference, save to size0 + # ignore any errors with this build, in case master is failing + echo "BUILDING $(git log --format='%s [%h]' -1 ${REFERENCE})" > ~/size0 + code_size_build_step $REFERENCE ~/size0 true + # build PR/branch, save to size1 + if _ci_is_git_merge "$COMPARISON"; then + echo "BUILDING $(git log --oneline -1 --format='%s [merge of %h]' ${COMPARISON}^2)" + else + echo "BUILDING $(git log --oneline -1 --formta='%s [%h]' ${COMPARISON})" + fi > ~/size1 + code_size_build_step $COMPARISON ~/size1 false + ) +} + +function ci_code_size_report { + # Allow errors from tools/metrics.py to propagate out of the pipe above. + (set -o pipefail; tools/metrics.py diff ~/size0 ~/size1 | tee diff) } ######################################################################################## # .mpy file format function ci_mpy_format_setup { + sudo apt-get update sudo pip3 install pyelftools + python3 --version } function ci_mpy_format_test { # Test mpy-tool.py dump feature on bytecode - python2 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy python3 ./tools/mpy-tool.py -xd tests/frozen/frozentest.mpy + # Build MicroPython + ci_unix_standard_build + micropython=./ports/unix/build-standard/micropython + $micropython -m mip install --target . argparse __future__ + export MICROPYPATH=. + + # Test mpy-tool.py running under MicroPython + $micropython ./tools/mpy-tool.py -x -d tests/frozen/frozentest.mpy + # Test mpy-tool.py dump feature on native code make -C examples/natmod/features1 ./tools/mpy-tool.py -xd examples/natmod/features1/features1.mpy + $micropython ./tools/mpy-tool.py -x -d examples/natmod/features1/features1.mpy +} + +function ci_mpy_cross_debug_emitter { + make ${MAKEOPTS} -C mpy-cross + mpy_cross=./mpy-cross/build/mpy-cross + + # Make sure the debug emitter does not crash or fail for simple files + $mpy_cross -X emit=native -march=debug ./tests/basics/0prelim.py | \ + grep -E "ENTRY|EXIT" | wc -l | grep "^2$" } ######################################################################################## @@ -121,18 +197,26 @@ function ci_cc3200_build { ######################################################################################## # ports/esp32 -# GitHub tag of ESP-IDF to use for CI (note: must be a tag or a branch) -IDF_VER=v5.0.4 +# GitHub tag of ESP-IDF to use for CI, extracted from the esp32 dependency lockfile +# This should end up as a tag name like vX.Y.Z +# (note: This hacky parsing can be replaced with 'yq' once Ubuntu >=24.04 is in use) +IDF_VER=v$(grep -A10 "idf:" ports/esp32/lockfiles/dependencies.lock.esp32 | grep "version:" | head -n1 | sed -E 's/ +version: //') +PYTHON=$(command -v python3 2> /dev/null) +PYTHON_VER=$(${PYTHON:-python} --version | cut -d' ' -f2) export IDF_CCACHE_ENABLE=1 function ci_esp32_idf_setup { - pip3 install pyelftools + echo "Using ESP-IDF version $IDF_VER" git clone --depth 1 --branch $IDF_VER https://github.com/espressif/esp-idf.git # doing a treeless clone isn't quite as good as --shallow-submodules, but it # is smaller than full clones and works when the submodule commit isn't a head. git -C esp-idf submodule update --init --recursive --filter=tree:0 ./esp-idf/install.sh + # Install additional packages for mpy_ld into the IDF env + source esp-idf/export.sh + pip3 install pyelftools + pip3 install ar } function ci_esp32_build_common { @@ -162,13 +246,28 @@ function ci_esp32_build_s3_c3 { make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C3 } +function ci_esp32_build_c2_c5_c6 { + ci_esp32_build_common + + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C2 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C5 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_C6 +} + +function ci_esp32_build_p4 { + ci_esp32_build_common + + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_P4 + make ${MAKEOPTS} -C ports/esp32 BOARD=ESP32_GENERIC_P4 BOARD_VARIANT=C6_WIFI +} + ######################################################################################## # ports/esp8266 function ci_esp8266_setup { - sudo pip install pyserial esptool==3.3.1 - wget https://github.com/jepler/esp-open-sdk/releases/download/2018-06-10/xtensa-lx106-elf-standalone.tar.gz - zcat xtensa-lx106-elf-standalone.tar.gz | tar x + sudo pip3 install pyserial esptool==3.3.1 pyelftools ar + wget https://micropython.org/resources/xtensa-lx106-elf-standalone.tar.gz + (set -o pipefail; zcat xtensa-lx106-elf-standalone.tar.gz | tar x) # Remove this esptool.py so pip version is used instead rm xtensa-lx106-elf/bin/esptool.py } @@ -183,24 +282,28 @@ function ci_esp8266_build { make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_512K make ${MAKEOPTS} -C ports/esp8266 BOARD=ESP8266_GENERIC BOARD_VARIANT=FLASH_1M + + # Test building native .mpy with xtensa architecture. + ci_native_mpy_modules_build xtensa } ######################################################################################## # ports/webassembly function ci_webassembly_setup { + npm install terser git clone https://github.com/emscripten-core/emsdk.git (cd emsdk && ./emsdk install latest && ./emsdk activate latest) } function ci_webassembly_build { source emsdk/emsdk_env.sh - make ${MAKEOPTS} -C ports/webassembly + make ${MAKEOPTS} -C ports/webassembly VARIANT=pyscript submodules + make ${MAKEOPTS} -C ports/webassembly VARIANT=pyscript } function ci_webassembly_run_tests { - # This port is very slow at running, so only run a few of the tests. - (cd tests && MICROPY_MICROPYTHON=../ports/webassembly/node_run.sh ./run-tests.py -j1 basics/builtin_*.py) + make -C ports/webassembly VARIANT=pyscript test_min } ######################################################################################## @@ -216,6 +319,8 @@ function ci_mimxrt_build { make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1020_EVK make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 submodules make ${MAKEOPTS} -C ports/mimxrt BOARD=TEENSY40 + make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1060_EVK submodules + make ${MAKEOPTS} -C ports/mimxrt BOARD=MIMXRT1060_EVK CFLAGS_EXTRA=-DMICROPY_HW_USB_MSC=1 } ######################################################################################## @@ -249,24 +354,88 @@ function ci_powerpc_build { } ######################################################################################## -# ports/qemu-arm +# ports/qemu -function ci_qemu_arm_setup { +function ci_qemu_setup_arm { ci_gcc_arm_setup sudo apt-get update sudo apt-get install qemu-system + sudo pip3 install pyelftools + sudo pip3 install ar qemu-system-arm --version } -function ci_qemu_arm_build { +function ci_qemu_setup_rv32 { + ci_gcc_riscv_setup + sudo apt-get update + sudo apt-get install qemu-system + sudo pip3 install pyelftools + sudo pip3 install ar + qemu-system-riscv32 --version +} + +function ci_qemu_setup_rv64 { + ci_gcc_riscv_setup + sudo apt-get update + sudo apt-get install qemu-system + qemu-system-riscv64 --version +} + +function ci_qemu_build_arm_prepare { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/qemu submodules +} + +function ci_qemu_build_arm_bigendian { + ci_qemu_build_arm_prepare + make ${MAKEOPTS} -C ports/qemu CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 +} + +function ci_qemu_build_arm_sabrelite { + ci_qemu_build_arm_prepare + make ${MAKEOPTS} -C ports/qemu BOARD=SABRELITE test_full +} + +function ci_qemu_build_arm_thumb_softfp { + ci_qemu_build_arm_prepare + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_full + + # Test building native .mpy with ARM-M softfp architectures. + ci_native_mpy_modules_build armv6m + ci_native_mpy_modules_build armv7m + + # Test running native .mpy with all ARM-M architectures. + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv6m" + make BOARD=MPS2_AN385 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7m" +} + +function ci_qemu_build_arm_thumb_hardfp { + ci_qemu_build_arm_prepare + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_full + + # Test building native .mpy with all ARM-M hardfp architectures. + ci_native_mpy_modules_build armv7emsp + ci_native_mpy_modules_build armv7emdp + + # Test running native .mpy with all ARM-M hardfp architectures. + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7emsp" + make BOARD=MPS2_AN500 ${MAKEOPTS} -C ports/qemu test_natmod RUN_TESTS_EXTRA="--arch armv7emdp" +} + +function ci_qemu_build_rv32 { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV32 submodules + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV32 test_full + + # Test building and running native .mpy with rv32imc architecture. + ci_native_mpy_modules_build rv32imc + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV32 test_natmod +} + +function ci_qemu_build_rv64 { make ${MAKEOPTS} -C mpy-cross - make ${MAKEOPTS} -C ports/qemu-arm submodules - make ${MAKEOPTS} -C ports/qemu-arm CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 - make ${MAKEOPTS} -C ports/qemu-arm clean - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test submodules - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test clean - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test BOARD=sabrelite test + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV64 submodules + make ${MAKEOPTS} -C ports/qemu BOARD=VIRT_RV64 test } ######################################################################################## @@ -294,6 +463,7 @@ function ci_renesas_ra_board_build { function ci_rp2_setup { ci_gcc_arm_setup + ci_picotool_setup } function ci_rp2_build { @@ -302,8 +472,11 @@ function ci_rp2_build { make ${MAKEOPTS} -C ports/rp2 make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO_W submodules make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO_W USER_C_MODULES=../../examples/usercmodule/micropython.cmake + make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO2 submodules + make ${MAKEOPTS} -C ports/rp2 BOARD=RPI_PICO2 make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO submodules - make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO + # This build doubles as a build test for disabling threads in the config + make ${MAKEOPTS} -C ports/rp2 BOARD=W5100S_EVB_PICO CFLAGS_EXTRA=-DMICROPY_PY_THREAD=0 # Test building ninaw10 driver and NIC interface. make ${MAKEOPTS} -C ports/rp2 BOARD=ARDUINO_NANO_RP2040_CONNECT submodules @@ -328,12 +501,22 @@ function ci_samd_build { # ports/stm32 function ci_stm32_setup { - ci_gcc_arm_setup + # Use a recent version of the ARM toolchain, to work with Cortex-M55. + wget https://developer.arm.com/-/media/Files/downloads/gnu/14.3.rel1/binrel/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz + xzcat arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz | tar x + pip3 install pyelftools + pip3 install ar pip3 install pyhy } +function ci_stm32_path { + echo $(pwd)/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin +} + function ci_stm32_pyb_build { + # This function builds the following MCU families: F4, F7. + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 MICROPY_PY_NETWORK_WIZNET5K=5200 submodules make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 submodules @@ -341,24 +524,22 @@ function ci_stm32_pyb_build { git submodule update --init lib/mynewt-nimble make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_NETWORK_WIZNET5K=5200 USER_C_MODULES=../../examples/usercmodule make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2 - make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1 + make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 COPT=-O2 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1' make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBD_SF6 make ${MAKEOPTS} -C ports/stm32/mboot BOARD=STM32F769DISC CFLAGS_EXTRA='-DMBOOT_ADDRESS_SPACE_64BIT=1 -DMBOOT_SDCARD_ADDR=0x100000000ULL -DMBOOT_SDCARD_BYTE_SIZE=0x400000000ULL -DMBOOT_FSLOAD=1 -DMBOOT_VFS_FAT=1' - - # Test building native .mpy with armv7emsp architecture. - git submodule update --init lib/berkeley-db-1.xx - ci_native_mpy_modules_build armv7emsp } function ci_stm32_nucleo_build { + # This function builds the following MCU families: F0, H5, H7, L0, L4, WB. + make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI submodules git submodule update --init lib/mynewt-nimble # Test building various MCU families, some with additional options. make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC - make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK + make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK CFLAGS_EXTRA='-DMICROPY_HW_TINYUSB_STACK=1' make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI COPT=-O2 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1' make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L073RZ make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L476RG DEBUG=1 @@ -377,16 +558,23 @@ function ci_stm32_nucleo_build { diff $BUILD_WB55/firmware.unpack.dfu $BUILD_WB55/firmware.unpack_no_sk.dfu } +function ci_stm32_misc_build { + # This function builds the following MCU families: G0, G4, H7, L1, N6, U5, WL. + + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/stm32 BOARD=ARDUINO_GIGA submodules + make ${MAKEOPTS} -C ports/stm32 BOARD=ARDUINO_GIGA + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_G0B1RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_G474RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L152RE + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_N657X0 + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_U5A5ZJ_Q + make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_WL55 +} + ######################################################################################## # ports/unix -CI_UNIX_OPTS_SYS_SETTRACE=( - MICROPY_PY_BTREE=0 - MICROPY_PY_FFI=0 - MICROPY_PY_SSL=0 - CFLAGS_EXTRA="-DMICROPY_PY_SYS_SETTRACE=1" -) - CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS=( MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 @@ -398,7 +586,6 @@ CI_UNIX_OPTS_QEMU_MIPS=( CROSS_COMPILE=mips-linux-gnu- VARIANT=coverage MICROPY_STANDALONE=1 - LDFLAGS_EXTRA="-static" ) CI_UNIX_OPTS_QEMU_ARM=( @@ -407,6 +594,32 @@ CI_UNIX_OPTS_QEMU_ARM=( MICROPY_STANDALONE=1 ) +CI_UNIX_OPTS_QEMU_RISCV64=( + CROSS_COMPILE=riscv64-linux-gnu- + VARIANT=coverage + MICROPY_STANDALONE=1 +) + +CI_UNIX_OPTS_SANITIZE_ADDRESS=( + # Macro MP_ASAN allows detecting ASan on gcc<=13 + CFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0 -DMP_ASAN=1" + LDFLAGS_EXTRA="-fsanitize=address --param asan-use-after-return=0" +) + +CI_UNIX_OPTS_SANITIZE_UNDEFINED=( + # Macro MP_UBSAN allows detecting UBSan on gcc<=13 + CFLAGS_EXTRA="-fsanitize=undefined -fno-sanitize=nonnull-attribute -DMP_UBSAN=1" + LDFLAGS_EXTRA="-fsanitize=undefined -fno-sanitize=nonnull-attribute" +) + +CI_UNIX_OPTS_REPR_B=( + VARIANT=standard + CFLAGS_EXTRA="-DMICROPY_OBJ_REPR=MICROPY_OBJ_REPR_B -DMICROPY_PY_UCTYPES=0 -Dmp_int_t=int32_t -Dmp_uint_t=uint32_t" + MICROPY_FORCE_32BIT=1 + RUN_TESTS_MPY_CROSS_FLAGS="--mpy-cross-flags=\"-march=x86 -msmall-int-bits=30\"" + +) + function ci_unix_build_helper { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix "$@" submodules @@ -415,20 +628,33 @@ function ci_unix_build_helper { } function ci_unix_build_ffi_lib_helper { - $1 $2 -shared -o tests/unix/ffi_lib.so tests/unix/ffi_lib.c + $1 $2 -shared -o tests/ports/unix/ffi_lib.so tests/ports/unix/ffi_lib.c } function ci_unix_run_tests_helper { make -C ports/unix "$@" test } +function ci_unix_run_tests_full_extra { + micropython=$1 + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) + (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py --average 1 1000 1000) +} + +function ci_unix_run_tests_full_no_native_helper { + variant=$1 + shift + micropython=../ports/unix/build-$variant/micropython + make -C ports/unix VARIANT=$variant "$@" test_full_no_native + ci_unix_run_tests_full_extra $micropython +} + function ci_unix_run_tests_full_helper { variant=$1 shift micropython=../ports/unix/build-$variant/micropython make -C ports/unix VARIANT=$variant "$@" test_full - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-multitests.py multi_net/*.py) - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=$micropython ./run-perfbench.py 1000 1000) + ci_unix_run_tests_full_extra $micropython } function ci_native_mpy_modules_build { @@ -437,16 +663,19 @@ function ci_native_mpy_modules_build { else arch=$1 fi - make -C examples/natmod/features1 ARCH=$arch - make -C examples/natmod/features2 ARCH=$arch - make -C examples/natmod/features3 ARCH=$arch - make -C examples/natmod/features4 ARCH=$arch - make -C examples/natmod/btree ARCH=$arch - make -C examples/natmod/deflate ARCH=$arch - make -C examples/natmod/framebuf ARCH=$arch - make -C examples/natmod/heapq ARCH=$arch - make -C examples/natmod/random ARCH=$arch - make -C examples/natmod/re ARCH=$arch + for natmod in btree deflate features1 features3 features4 framebuf heapq random re + do + make -C examples/natmod/$natmod ARCH=$arch clean + make -C examples/natmod/$natmod ARCH=$arch + done + + # features2 requires soft-float on rv32imc and xtensa. + make -C examples/natmod/features2 ARCH=$arch clean + if [ $arch = "rv32imc" ] || [ $arch = "xtensa" ]; then + make -C examples/natmod/features2 ARCH=$arch MICROPY_FLOAT_IMPL=float + else + make -C examples/natmod/features2 ARCH=$arch + fi } function ci_native_mpy_modules_32bit_build { @@ -458,7 +687,7 @@ function ci_unix_minimal_build { } function ci_unix_minimal_run_tests { - (cd tests && MICROPY_CPYTHON3=python3 MICROPY_MICROPYTHON=../ports/unix/build-minimal/micropython ./run-tests.py -e exception_chain -e self_type_check -e subclass_native_init -d basics) + make -C ports/unix VARIANT=minimal test } function ci_unix_standard_build { @@ -480,8 +709,9 @@ function ci_unix_standard_v2_run_tests { } function ci_unix_coverage_setup { - sudo pip3 install setuptools - sudo pip3 install pyelftools + pip3 install setuptools + pip3 install pyelftools + pip3 install ar gcc --version python3 --version } @@ -492,7 +722,7 @@ function ci_unix_coverage_build { } function ci_unix_coverage_run_tests { - ci_unix_run_tests_full_helper coverage + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage } function ci_unix_coverage_run_mpy_merge_tests { @@ -521,7 +751,7 @@ function ci_unix_coverage_run_mpy_merge_tests { function ci_unix_coverage_run_native_mpy_tests { MICROPYPATH=examples/natmod/features2 ./ports/unix/build-coverage/micropython -m features2 - (cd tests && ./run-natmodtests.py "$@" extmod/{btree*,deflate*,framebuf*,heapq*,random*,re*}.py) + (cd tests && ./run-natmodtests.py "$@" extmod/*.py) } function ci_unix_32bit_setup { @@ -530,6 +760,7 @@ function ci_unix_32bit_setup { sudo apt-get install gcc-multilib g++-multilib libffi-dev:i386 sudo pip3 install setuptools sudo pip3 install pyelftools + sudo pip3 install ar gcc --version python3 --version } @@ -548,13 +779,20 @@ function ci_unix_coverage_32bit_run_native_mpy_tests { } function ci_unix_nanbox_build { - # Use Python 2 to check that it can run the build scripts - ci_unix_build_helper PYTHON=python2 VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1" + ci_unix_build_helper VARIANT=nanbox CFLAGS_EXTRA="-DMICROPY_PY_MATH_CONSTANTS=1" ci_unix_build_ffi_lib_helper gcc -m32 } function ci_unix_nanbox_run_tests { - ci_unix_run_tests_full_helper nanbox PYTHON=python2 + ci_unix_run_tests_full_no_native_helper nanbox +} + +function ci_unix_longlong_build { + ci_unix_build_helper VARIANT=longlong "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" +} + +function ci_unix_longlong_run_tests { + ci_unix_run_tests_full_helper longlong } function ci_unix_float_build { @@ -567,7 +805,17 @@ function ci_unix_float_run_tests { ci_unix_run_tests_helper CFLAGS_EXTRA="-DMICROPY_FLOAT_IMPL=MICROPY_FLOAT_IMPL_FLOAT" } +function ci_unix_gil_enabled_build { + ci_unix_build_helper VARIANT=standard MICROPY_PY_THREAD_GIL=1 + ci_unix_build_ffi_lib_helper gcc +} + +function ci_unix_gil_enabled_run_tests { + ci_unix_run_tests_full_helper standard MICROPY_PY_THREAD_GIL=1 +} + function ci_unix_clang_setup { + sudo apt-get update sudo apt-get install clang clang --version } @@ -579,7 +827,8 @@ function ci_unix_stackless_clang_build { } function ci_unix_stackless_clang_run_tests { - ci_unix_run_tests_helper CC=clang + # Timeout needs to be increased for thread/stress_aes.py test. + MICROPY_TEST_TIMEOUT=90 ci_unix_run_tests_helper CC=clang } function ci_unix_float_clang_build { @@ -592,30 +841,39 @@ function ci_unix_float_clang_run_tests { ci_unix_run_tests_helper CC=clang } -function ci_unix_settrace_build { +function ci_unix_settrace_stackless_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" + make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" } -function ci_unix_settrace_run_tests { - ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE[@]}" +function ci_unix_settrace_stackless_run_tests { + ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" } -function ci_unix_settrace_stackless_build { +function ci_unix_sanitize_undefined_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules - make ${MAKEOPTS} -C ports/unix "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" + make ${MAKEOPTS} -C ports/unix VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" + ci_unix_build_ffi_lib_helper gcc } -function ci_unix_settrace_stackless_run_tests { - ci_unix_run_tests_full_helper standard "${CI_UNIX_OPTS_SYS_SETTRACE_STACKLESS[@]}" +function ci_unix_sanitize_undefined_run_tests { + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_UNDEFINED[@]}" } -function ci_unix_macos_build { - # Install pkg-config to configure libffi paths. - brew install pkg-config +function ci_unix_sanitize_address_build { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/unix submodules + make ${MAKEOPTS} -C ports/unix VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_ADDRESS[@]}" + ci_unix_build_ffi_lib_helper gcc +} +function ci_unix_sanitize_address_run_tests { + MICROPY_TEST_TIMEOUT=60 ci_unix_run_tests_full_helper coverage VARIANT=coverage "${CI_UNIX_OPTS_SANITIZE_ADDRESS[@]}" +} + +function ci_unix_macos_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/unix submodules #make ${MAKEOPTS} -C ports/unix deplibs @@ -627,29 +885,34 @@ function ci_unix_macos_build { function ci_unix_macos_run_tests { # Issues with macOS tests: - # - import_pkg7 has a problem with relative imports - # - random_basic has a problem with getrandbits(0) - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude 'import_pkg7.py' --exclude 'random_basic.py') + # - float_parse and float_parse_doubleprec parse/print floats out by a few mantissa bits + # - ffi_callback crashes for an unknown reason + # - thread/stress_heap.py is flaky + # - thread/thread_gc1.py is flaky + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-standard/micropython ./run-tests.py --exclude '(float_parse|float_parse_doubleprec|ffi_callback|thread/stress_heap|thread/thread_gc1).py') } function ci_unix_qemu_mips_setup { sudo apt-get update - sudo apt-get install gcc-mips-linux-gnu g++-mips-linux-gnu + sudo apt-get install gcc-mips-linux-gnu g++-mips-linux-gnu libc6-mips-cross sudo apt-get install qemu-user qemu-mips --version + sudo mkdir /etc/qemu-binfmt + sudo ln -s /usr/mips-linux-gnu/ /etc/qemu-binfmt/mips } function ci_unix_qemu_mips_build { - # qemu-mips on GitHub Actions will seg-fault if not linked statically ci_unix_build_helper "${CI_UNIX_OPTS_QEMU_MIPS[@]}" + ci_unix_build_ffi_lib_helper mips-linux-gnu-gcc } function ci_unix_qemu_mips_run_tests { # Issues with MIPS tests: - # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) - # - ffi tests do not work + # - thread/stress_aes.py takes around 50 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py' --exclude 'ffi_(callback|float|float2).py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=90 ./run-tests.py --exclude 'thread/stress_recurse.py|thread/thread_gc1.py') } function ci_unix_qemu_arm_setup { @@ -657,6 +920,8 @@ function ci_unix_qemu_arm_setup { sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi sudo apt-get install qemu-user qemu-arm --version + sudo mkdir /etc/qemu-binfmt + sudo ln -s /usr/arm-linux-gnueabi/ /etc/qemu-binfmt/arm } function ci_unix_qemu_arm_build { @@ -667,15 +932,52 @@ function ci_unix_qemu_arm_build { function ci_unix_qemu_arm_run_tests { # Issues with ARM tests: # - (i)listdir does not work, it always returns the empty list (it's an issue with the underlying C call) - export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi + # - thread/stress_aes.py takes around 70 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky file ./ports/unix/build-coverage/micropython - (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython ./run-tests.py --exclude 'vfs_posix.*\.py') + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=90 ./run-tests.py --exclude 'vfs_posix.*\.py|thread/stress_recurse.py|thread/thread_gc1.py') +} + +function ci_unix_qemu_riscv64_setup { + sudo apt-get update + sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu + sudo apt-get install qemu-user + qemu-riscv64 --version + sudo mkdir /etc/qemu-binfmt + sudo ln -s /usr/riscv64-linux-gnu/ /etc/qemu-binfmt/riscv64 +} + +function ci_unix_qemu_riscv64_build { + ci_unix_build_helper "${CI_UNIX_OPTS_QEMU_RISCV64[@]}" + ci_unix_build_ffi_lib_helper riscv64-linux-gnu-gcc +} + +function ci_unix_qemu_riscv64_run_tests { + # Issues with RISCV-64 tests: + # - thread/stress_aes.py takes around 140 seconds + # - thread/stress_recurse.py is flaky + # - thread/thread_gc1.py is flaky + file ./ports/unix/build-coverage/micropython + (cd tests && MICROPY_MICROPYTHON=../ports/unix/build-coverage/micropython MICROPY_TEST_TIMEOUT=180 ./run-tests.py --exclude 'thread/stress_recurse.py|thread/thread_gc1.py') +} + +function ci_unix_repr_b_build { + ci_unix_build_helper "${CI_UNIX_OPTS_REPR_B[@]}" + ci_unix_build_ffi_lib_helper gcc -m32 +} + +function ci_unix_repr_b_run_tests { + # ci_unix_run_tests_full_no_native_helper is not used due to + # https://github.com/micropython/micropython/issues/18105 + ci_unix_run_tests_helper "${CI_UNIX_OPTS_REPR_B[@]}" } ######################################################################################## # ports/windows function ci_windows_setup { + sudo apt-get update sudo apt-get install gcc-mingw-w64 } @@ -683,25 +985,44 @@ function ci_windows_build { make ${MAKEOPTS} -C mpy-cross make ${MAKEOPTS} -C ports/windows submodules make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=i686-w64-mingw32- + make ${MAKEOPTS} -C ports/windows CROSS_COMPILE=x86_64-w64-mingw32- BUILD=build-standard-w64 } ######################################################################################## # ports/zephyr -ZEPHYR_DOCKER_VERSION=v0.21.0 -ZEPHYR_SDK_VERSION=0.13.2 -ZEPHYR_VERSION=v3.1.0 +ZEPHYR_DOCKER_VERSION=v0.28.1 +ZEPHYR_SDK_VERSION=0.17.2 +ZEPHYR_VERSION=v4.2.0 function ci_zephyr_setup { - docker pull zephyrprojectrtos/ci:${ZEPHYR_DOCKER_VERSION} + IMAGE=ghcr.io/zephyrproject-rtos/ci:${ZEPHYR_DOCKER_VERSION} + + docker pull ${IMAGE} + + # Directories cached by GitHub Actions, mounted + # into the container + ZEPHYRPROJECT_DIR="$(pwd)/zephyrproject" + CCACHE_DIR="$(pwd)/.ccache" + + mkdir -p "${ZEPHYRPROJECT_DIR}" + mkdir -p "${CCACHE_DIR}" + docker run --name zephyr-ci -d -it \ -v "$(pwd)":/micropython \ + -v "${ZEPHYRPROJECT_DIR}":/zephyrproject \ + -v "${CCACHE_DIR}":/root/.cache/ccache \ -e ZEPHYR_SDK_INSTALL_DIR=/opt/toolchains/zephyr-sdk-${ZEPHYR_SDK_VERSION} \ -e ZEPHYR_TOOLCHAIN_VARIANT=zephyr \ -e ZEPHYR_BASE=/zephyrproject/zephyr \ -w /micropython/ports/zephyr \ - zephyrprojectrtos/ci:${ZEPHYR_DOCKER_VERSION} + ${IMAGE} docker ps -a + + # qemu-system-arm is needed to run the test suite. + sudo apt-get update + sudo apt-get install qemu-system-arm + qemu-system-arm --version } function ci_zephyr_install { @@ -711,8 +1032,112 @@ function ci_zephyr_install { } function ci_zephyr_build { + git submodule update --init lib/micropython-lib docker exec zephyr-ci west build -p auto -b qemu_x86 -- -DCONF_FILE=prj_minimal.conf docker exec zephyr-ci west build -p auto -b frdm_k64f docker exec zephyr-ci west build -p auto -b mimxrt1050_evk docker exec zephyr-ci west build -p auto -b nucleo_wb55rg # for bluetooth } + +function ci_zephyr_run_tests { + docker exec zephyr-ci west build -p auto -b qemu_cortex_m3 -- -DCONF_FILE=prj_minimal.conf + (cd tests && ./run-tests.py -t execpty:"qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -monitor null -serial pty -kernel ../ports/zephyr/build/zephyr/zephyr.elf") +} + +######################################################################################## +# ports/alif + +function ci_alif_setup { + ci_gcc_arm_setup +} + +function ci_alif_ae3_build { + make ${MAKEOPTS} -C mpy-cross + make ${MAKEOPTS} -C ports/alif BOARD=OPENMV_AE3 MCU_CORE=M55_HP submodules + make ${MAKEOPTS} -C ports/alif BOARD=OPENMV_AE3 MCU_CORE=M55_HE submodules + make ${MAKEOPTS} -C ports/alif BOARD=OPENMV_AE3 MCU_CORE=M55_DUAL + make ${MAKEOPTS} -C ports/alif BOARD=ALIF_ENSEMBLE MCU_CORE=M55_DUAL +} + +function _ci_help { + # Note: these lines must be indented with tab characters (required by bash <<-EOF) + cat <<-EOF + ci.sh: Script fragments used during CI + + When invoked as a script, runs a sequence of ci steps, + stopping after the first error. + + Usage: + ${BASH_SOURCE} step1 step2... + + Steps: + EOF + if type -path column > /dev/null 2>&1; then + grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//' | column + else + grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//' + fi + exit +} + +function _ci_bash_completion { + echo "alias ci=\"$(readlink -f "$0")\"; complete -W '$(grep '^function ci_' $0 | awk '{print $2}' | sed 's/^ci_//')' ci" +} + +function _ci_zsh_completion { + echo "alias ci=\"$(readlink -f "$0"\"); _complete_mpy_ci_zsh() { compadd $(grep '^function ci_' $0 | awk '{sub(/^ci_/,"",$2); print $2}' | tr '\n' ' ') }; autoload -Uz compinit; compinit; compdef _complete_mpy_ci_zsh $(readlink -f "$0")" +} + +function _ci_fish_completion { + echo "alias ci=\"$(readlink -f "$0"\"); complete -c ci -p $(readlink -f "$0") -f -a '$(grep '^function ci_' $(readlink -f "$0") | awk '{sub(/^ci_/,"",$2); print $2}' | tr '\n' ' ')'" +} + +function _ci_main { + case "$1" in + (-h|-?|--help) + _ci_help + ;; + (--bash-completion) + _ci_bash_completion + ;; + (--zsh-completion) + _ci_zsh_completion + ;; + (--fish-completion) + _ci_fish_completion + ;; + (-*) + echo "Unknown option: $1" 1>&2 + exit 1 + ;; + (*) + set -e + cd $(dirname "$0")/.. + while [ $# -ne 0 ]; do + ci_$1 + shift + done + ;; + esac +} + +# https://stackoverflow.com/questions/2683279/how-to-detect-if-a-script-is-being-sourced +sourced=0 +if [ -n "$ZSH_VERSION" ]; then + case $ZSH_EVAL_CONTEXT in *:file) sourced=1;; esac +elif [ -n "$KSH_VERSION" ]; then + [ "$(cd -- "$(dirname -- "$0")" && pwd -P)/$(basename -- "$0")" != "$(cd -- "$(dirname -- "${.sh.file}")" && pwd -P)/$(basename -- "${.sh.file}")" ] && sourced=1 +elif [ -n "$BASH_VERSION" ]; then + (return 0 2>/dev/null) && sourced=1 +else # All other shells: examine $0 for known shell binary filenames. + # Detects `sh` and `dash`; add additional shell filenames as needed. + case ${0##*/} in sh|-sh|dash|-dash) sourced=1;; esac +fi + +if [ $sourced -eq 0 ]; then + # invoked as a command + if [ "$#" -eq 0 ]; then + set -- --help + fi + _ci_main "$@" +fi diff --git a/tools/ci_check_duplicate_usb_vid_pid.py b/tools/ci_check_duplicate_usb_vid_pid.py index 2a644a8393f54..38cce0f28be94 100644 --- a/tools/ci_check_duplicate_usb_vid_pid.py +++ b/tools/ci_check_duplicate_usb_vid_pid.py @@ -53,6 +53,7 @@ "0x303A:0x7003": [ "espressif_esp32s3_devkitc_1_n8", "espressif_esp32s3_devkitc_1_n8r2", + "espressif_esp32s3_devkitc_1_n8r2_ros", "espressif_esp32s3_devkitc_1_n8r8", "espressif_esp32s3_devkitc_1_n8r8_hacktablet", "espressif_esp32s3_devkitc_1_n16", @@ -63,11 +64,16 @@ "espressif_esp32s2_devkitc_1_n4r2", "espressif_esp32s2_devkitc_1_n8r2", ], + "0x303A:0x81DA": [ + "m5stack_cardputer", + "m5stack_cardputer_ros", + ], "0x239A:0x102E": ["weact_studio_pico", "weact_studio_pico_16mb"], "0x303A:0x8166": ["yd_esp32_s3_n8r8", "yd_esp32_s3_n16r8"], "0x2341:0x056B": ["arduino_nano_esp32s3", "arduino_nano_esp32s3_inverted_statusled"], "0x2E8A:0x1020": ["waveshare_rp2040_plus_4mb", "waveshare_rp2040_plus_16mb"], "0x2341:0x805A": ["arduino_nano_33_ble", "arduino_nano_33_ble_rev2"], + "0x303A:0x8154": ["lilygo_tqt_pro_nopsram", "lilygo_tqt_pro_psram"], } cli_parser = argparse.ArgumentParser( @@ -98,7 +104,7 @@ def check_vid_pid(files, clusterlist): """ usb_pattern = re.compile( - r"^CIRCUITPY_USB_DEVICE\s*=\s*0$|^IDF_TARGET = (esp32|esp32c2|esp32c3|esp32c6|esp32h2)$|^MCU_SERIES = MG24$", + r"^CIRCUITPY_USB_DEVICE\s*=\s*0$|^IDF_TARGET = (esp32|esp32c2|esp32c3|esp32c5|esp32c6|esp32c61|esp32h2|esp32p4)$|^MCU_SERIES = MG24$", flags=re.M, ) @@ -138,9 +144,9 @@ def check_vid_pid(files, clusterlist): cluster = set(clusterlist.get(key, [])) if cluster != boards: if key == "": - duplicates.append(f"- Non-USB:\n" f" Boards: {', '.join(sorted(boards))}") + duplicates.append(f"- Non-USB:\n Boards: {', '.join(sorted(boards))}") else: - duplicates.append(f"- VID/PID: {key}\n" f" Boards: {', '.join(sorted(boards))}") + duplicates.append(f"- VID/PID: {key}\n Boards: {', '.join(sorted(boards))}") if duplicates: duplicates = "\n".join(duplicates) diff --git a/tools/ci_fetch_deps.py b/tools/ci_fetch_deps.py index cbae4b3ff5e07..be190ad660668 100644 --- a/tools/ci_fetch_deps.py +++ b/tools/ci_fetch_deps.py @@ -35,17 +35,15 @@ def _all_submodules(): all_submodules = _all_submodules() -def matching_submodules(s): - if s.endswith("/"): - return [m for m in all_submodules if m.startswith(s)] - elif s not in all_submodules: - raise ValueError(f"{s!r} is not a submodule") - return [s] - - # Submodules needed by port builds outside of their ports directory. # Should we try and detect these? PORT_DEPS = { + "analog": [ + "extmod/ulab/", + "lib/tlsf/", + "lib/tinyusb/", + "lib/protomatter", + ], "atmel-samd": [ "extmod/ulab/", "lib/adafruit_floppy/", @@ -98,6 +96,11 @@ def matching_submodules(s): "lib/tlsf", "data/nvm.toml/", ], + "zephyr-cp": [ + "lib/certificates/", + "lib/tinyusb/", + "lib/tlsf", + ], # omit unix which is part of the "test" target below } @@ -182,6 +185,9 @@ def main(target): submodules.extend(PORT_DEPS[port]) unique_submodules = set(submodules) submodules = list(unique_submodules) + elif target == "windows-zephyr": + submodules.append("ports/zephyr-cp") + submodules.extend(PORT_DEPS["zephyr-cp"]) elif target == "website": submodules = ["tools/adabot", "frozen"] elif target == "pre-commit": @@ -191,28 +197,47 @@ def main(target): target ] else: - p = list(pathlib.Path(TOP).glob(f"ports/*/boards/{target}/mpconfigboard.mk")) + p = list(TOP.glob(f"ports/*/boards/{target}/mpconfigboard.mk")) + # Check to see if the board is nested under vendor. + if not p: + next_underscore = target.find("_") + while next_underscore != -1: + vendor = target[:next_underscore] + board = target[next_underscore + 1 :] + p = list(TOP.glob(f"ports/*/boards/{vendor}/{board}/circuitpython.toml")) + if p: + break + next_underscore = target.find("_", next_underscore + 1) + if not p: raise RuntimeError(f"Unsupported target: {target}") config = p[0] # Add the ports folder to init submodules - port_folder = config.parents[2] + + if config.suffix == ".mk": + port_folder = config.parents[2] + else: + port_folder = config.parents[3] port = port_folder.name submodules.append(f"ports/{port}") submodules.append("tools/") # for huffman submodules.extend(PORT_DEPS[port]) - with config.open() as f: - for line in f.readlines(): - prefix = "FROZEN_MPY_DIRS += $(TOP)/" - if line.startswith(prefix): - lib_folder = line.strip()[len(prefix) :] - # Drop everything after the second folder because the frozen - # folder may be inside the submodule. - if lib_folder.count("/") > 1: - lib_folder = lib_folder.split("/", maxsplit=2) - lib_folder = "/".join(lib_folder[:2]) - submodules.append(lib_folder) + if config.suffix == ".mk": + with config.open() as f: + for line in f.readlines(): + prefix = "FROZEN_MPY_DIRS += $(TOP)/" + if line.startswith(prefix): + lib_folder = line.strip()[len(prefix) :] + # Drop everything after the second folder because the frozen + # folder may be inside the submodule. + if lib_folder.count("/") > 1: + lib_folder = lib_folder.split("/", maxsplit=2) + lib_folder = "/".join(lib_folder[:2]) + submodules.append(lib_folder) + else: + # TODO: Add a way to specify frozen modules in circuitpython.toml + pass print("Submodules:", " ".join(submodules)) diff --git a/tools/ci_set_idf_constraint.py b/tools/ci_set_idf_constraint.py new file mode 100644 index 0000000000000..49c187f458782 --- /dev/null +++ b/tools/ci_set_idf_constraint.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 Adafruit Industries LLC +# +# SPDX-License-Identifier: MIT + +"""Set IDF_CONSTRAINT_FILE for CI. + +CI installs requirements-dev.txt for all ports, but on Espressif builds we must +also apply the matching ESP-IDF constraints file so pip does not upgrade shared +packages (for example click) beyond what ESP-IDF allows. This script derives the +active ESP-IDF major.minor version from version.cmake and exports the exact +constraints file path into GITHUB_ENV for later install steps. +""" + +import os +import pathlib +import re + +TOP = pathlib.Path(__file__).resolve().parent.parent + + +def main() -> None: + version_cmake = TOP / "ports" / "espressif" / "esp-idf" / "tools" / "cmake" / "version.cmake" + data = version_cmake.read_text(encoding="utf-8") + + major = re.search(r"IDF_VERSION_MAJOR\s+(\d+)", data) + minor = re.search(r"IDF_VERSION_MINOR\s+(\d+)", data) + if major is None or minor is None: + raise RuntimeError(f"Unable to parse IDF version from {version_cmake}") + + idf_tools_path = os.environ.get("IDF_TOOLS_PATH") + if not idf_tools_path: + raise RuntimeError("IDF_TOOLS_PATH is not set") + + constraint = ( + pathlib.Path(idf_tools_path) / f"espidf.constraints.v{major.group(1)}.{minor.group(1)}.txt" + ) + + github_env = os.environ.get("GITHUB_ENV") + if github_env: + with open(github_env, "a", encoding="utf-8") as f: + f.write(f"IDF_CONSTRAINT_FILE={constraint}\n") + + print(f"Set IDF_CONSTRAINT_FILE={constraint}") + + +if __name__ == "__main__": + main() diff --git a/tools/ci_set_matrix.py b/tools/ci_set_matrix.py index d050d8e44c946..11bffbaa755c3 100755 --- a/tools/ci_set_matrix.py +++ b/tools/ci_set_matrix.py @@ -39,7 +39,6 @@ from shared_bindings_matrix import ( get_settings_from_makefile, SUPPORTED_PORTS, - all_ports_all_boards, ) # Files that never influence board builds @@ -151,7 +150,7 @@ def get_settings(board): if not build_all: pattern_port = re.compile(r"^ports/([^/]+)/") - pattern_board = re.compile(r"^ports/[^/]+/boards/([^/]+)/") + pattern_board = re.compile(r"^ports/([^/]+)/boards/([^/]+)/") pattern_module = re.compile( r"^(ports/[^/]+/(?:common-hal|bindings)|shared-bindings|shared-module)/([^/]+)/" ) @@ -166,7 +165,14 @@ def get_settings(board): # See if it is board specific board_matches = pattern_board.search(file) if board_matches: - boards_to_build.add(board_matches.group(1)) + port = board_matches.group(1) + board = board_matches.group(2) + if port == "zephyr-cp": + p = pathlib.Path(file) + board_id = p.parent.name + vendor_id = p.parent.parent.name + board = f"{vendor_id}_{board_id}" + boards_to_build.add(board) continue # See if it is port specific @@ -181,7 +187,19 @@ def get_settings(board): # As a (nearly) last resort, for some certain files, we compute the settings from the # makefile for each board and determine whether to build them that way if file.startswith("frozen") or file.startswith("supervisor") or module_matches: - boards = port_to_board[port] if port else all_board_ids + # Take a copy, because we remove items from it below. For + # instance, if we remove items from, say, all_board_ids, then + # the logic to build all boards breaks. + boards = set(port_to_board[port] if port else all_board_ids) + + # Zephyr boards don't use make, so build them and don't compute their settings. + for board in port_to_board["zephyr-cp"]: + if board in boards: + boards_to_build.add(board) + + for board in boards_to_build: + if board in boards: + boards.remove(board) compute_board_settings(boards) for board in boards: @@ -234,6 +252,7 @@ def get_settings(board): # A board can appear due to its _deletion_ (rare) # if this happens it's not in `board_to_port`. if not port: + print("skip", board) continue port_to_boards_to_build.setdefault(port, []).append(board) print(" ", board) diff --git a/tools/circuitpy_header_change.py b/tools/circuitpy_header_change.py index 8d5534874909f..aa931f65602f8 100755 --- a/tools/circuitpy_header_change.py +++ b/tools/circuitpy_header_change.py @@ -48,18 +48,16 @@ def find_related_copyrights(filename): def fix_file(filename, change): copyrights = [] mit_license = False - empty_file = False first_line = "" no_existing_header = False with open(filename, "r") as f: lines = f.readlines() if not lines: - empty_file = True no_existing_header = True mit_license = True copyrights.append( - f"// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC" + "// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC" ) else: first_line = lines.pop(0) @@ -111,7 +109,7 @@ def fix_file(filename, change): copyrights = find_related_copyrights(filename) if not copyrights: copyrights.append( - f"// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC" + "// SPDX-FileCopyrightText: Copyright (c) 2024 Adafruit Industries LLC" ) if change: diff --git a/tools/codeformat.py b/tools/codeformat.py index 8a95e7894f2c7..cf91049a73162 100644 --- a/tools/codeformat.py +++ b/tools/codeformat.py @@ -39,7 +39,6 @@ # Relative to top-level repo dir. # CIRCUITPY-CHANGE: different directory trees PATHS = [ - # C "main.c", "devices/**/*.[ch]", "extmod/*.[ch]", @@ -52,26 +51,14 @@ "shared-bindings/**/*.[ch]", "shared-module/**/*.[ch]", "supervisor/**/*.[ch]", - # Python - "extmod/*.py", - "ports/**/*.py", - "py/**/*.py", - "tools/**/*.py", - "tests/circuitpython-*/**/*.py", ] # CIRCUITPY-CHANGE: different exclusions EXCLUSIONS = [ # STM32 build includes generated Python code. "ports/*/build*", - # gitignore in ports/unix ignores *.py, so also do it here. - "ports/unix/*.py", - # not real python files - "tests/**/repl_*.py", # don't reindent this third-party code we vendored in "ports/raspberrypi/lwip_src", - # line breaks - "tools/mpy-tool.py", ] @@ -119,12 +106,6 @@ def transform(m): TOP = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) UNCRUSTIFY_CFG = os.path.join(TOP, "tools/uncrustify.cfg") -# CIRCUITPY-CHANGE -C_EXTS = ( - ".c", - ".h", -) -PY_EXTS = (".py",) def check_uncrustify_version(): @@ -217,14 +198,8 @@ def main(): # Expand the arguments passed on the command line, subject to the PATHS and EXCLUSIONS files = list_files(args.files) - # Extract files matching a specific language. - def lang_files(exts): - for file in files: - if os.path.splitext(file)[1].lower() in exts: - yield file - def bindings_files(): - for file in lang_files(C_EXTS): + for file in files: if file.startswith("shared-bindings/") or "/bindings/" in file: yield file @@ -248,22 +223,23 @@ def batch(cmd, files, N=200, check=False): command = ["uncrustify", "-c", UNCRUSTIFY_CFG, "-lC", "--no-backup"] if not args.v: command.append("-q") - batch(command, lang_files(C_EXTS)) - for file in lang_files(C_EXTS): + batch(command, iter(files)) + for file in files: fixup_c(file) - # Format bindings with black_bindings + # Format bindings with ruff_bindings if format_py: - command = ["python3", "tools/black_bindings.py"] + command = ["python3", "tools/ruff_bindings.py"] batch(command, bindings_files(), check=True) - # Format Python files with black. + # Format Python files with "ruff format" (using config in pyproject.toml). if format_py: - command = ["black", "--fast", "--line-length=99"] + command = ["ruff", "format"] if args.v: command.append("-v") else: command.append("-q") - batch(command, lang_files(PY_EXTS)) + command.append(".") + subprocess.check_call(command, cwd=TOP) if __name__ == "__main__": diff --git a/tools/cortex-m-fault-gdb.py b/tools/cortex-m-fault-gdb.py index 8de754ed26056..dd8838c44f538 100644 --- a/tools/cortex-m-fault-gdb.py +++ b/tools/cortex-m-fault-gdb.py @@ -1,5 +1,7 @@ """Source this file into gdb `source ../../tools/cortex-m-fault-gdb.py` then run - `cortex-m-fault` to print basic info about the fault registers.""" +`cortex-m-fault` to print basic info about the fault registers.""" + +import gdb SCS = 0xE000E000 SCB = SCS + 0x0D00 @@ -180,7 +182,7 @@ def invoke(self, arg, from_tty): architecture = (cpuid >> 16) & 0xF revision = cpuid & 0xF part_no = (cpuid >> 4) & 0xFFF - print(PARTS[part_no]) + print(PARTS[part_no], variant, revision) if part_no == 0xD21: self._armv8m_fault() diff --git a/tools/cpboard.py b/tools/cpboard.py index 12d7d374a35e0..d72d14a2402f1 100644 --- a/tools/cpboard.py +++ b/tools/cpboard.py @@ -343,7 +343,6 @@ def from_usb(cls, baudrate=115200, wait=0, timeout=10, **kwargs): dev = usb.core.find(**kwargs) if not dev: - s = "Can't find USB device: " args = [] for x in kwargs.items(): try: diff --git a/tools/describe b/tools/describe deleted file mode 100755 index 0f3b541e3cd70..0000000000000 --- a/tools/describe +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -if [ -z "$CP_VERSION" ]; then - git describe --first-parent --dirty --tags --match "[1-9].*" "$@" -else - echo $CP_VERSION -fi diff --git a/tools/diff_nm_sizes.py b/tools/diff_nm_sizes.py index 241355ea1824e..fdfcdaad4964e 100644 --- a/tools/diff_nm_sizes.py +++ b/tools/diff_nm_sizes.py @@ -44,8 +44,7 @@ continue print(f"{name:<{longest_symbol}}{size - old_size:>+6}") -for name in old_symbols: - old_size = old_symbols[name] +for name, old_size in old_symbols.items(): print(f"{name:<{longest_symbol}}{-old_size:>+6}") print() diff --git a/tools/extract_pyi.py b/tools/extract_pyi.py index e6bc703c021a4..e340712d189a8 100644 --- a/tools/extract_pyi.py +++ b/tools/extract_pyi.py @@ -62,7 +62,7 @@ def is_typed(node, allow_any=False): return False elif ( isinstance(node, ast.Attribute) - and type(node.value) == ast.Name + and type(node.value) is ast.Name and node.value.id == "typing" and node.attr == "Any" ): diff --git a/tools/file2h.py b/tools/file2h.py index df9cc02fdabba..2707d4a16e5cf 100644 --- a/tools/file2h.py +++ b/tools/file2h.py @@ -9,8 +9,6 @@ # ; # This script simply prints the escaped string straight to stdout -from __future__ import print_function - import sys # Can either be set explicitly, or left blank to auto-detect diff --git a/tools/fixup_translations.py b/tools/fixup_translations.py index 4c6f89b26fff7..21a5812da9651 100644 --- a/tools/fixup_translations.py +++ b/tools/fixup_translations.py @@ -84,8 +84,7 @@ first_translations.save(po_filename) print() -for commit in bad_commits: - files = bad_commits[commit] +for commit, files in bad_commits.items(): print(commit) for file in files: print("\t", file) diff --git a/tools/gdb-stack-size.py b/tools/gdb-stack-size.py index 4d3fc9fe08aa1..6426cf429564b 100644 --- a/tools/gdb-stack-size.py +++ b/tools/gdb-stack-size.py @@ -1,5 +1,7 @@ """Source this file into gdb `source ../../tools/gdb-stack-size.py` then run - `stack-size` to print a backtrace with each frame size next to it.""" +`stack-size` to print a backtrace with each frame size next to it.""" + +import gdb class StackSize(gdb.Command): diff --git a/tools/gen-changelog.sh b/tools/gen-changelog.sh index b29606b0c784d..2dbbc24960f53 100755 --- a/tools/gen-changelog.sh +++ b/tools/gen-changelog.sh @@ -6,7 +6,7 @@ echo "MicroPython change log" -for t in $(git tag | grep -v v1.0-rc1 | sort -rV); do +for t in $(git tag | grep -v -- '-rc1\|-preview' | sort -rV); do echo '' echo '========' echo '' diff --git a/tools/gen_display_resources.py b/tools/gen_display_resources.py index dbf3f9a994675..9ed829f7d3738 100644 --- a/tools/gen_display_resources.py +++ b/tools/gen_display_resources.py @@ -8,8 +8,8 @@ import struct import sys -sys.path.insert(0, "bitmap_font") -sys.path.insert(0, "../../tools/bitmap_font") +sys.path.insert(0, "tools/bitmap_font") # For running from root +sys.path.insert(0, "../../tools/bitmap_font") # For running from a port directory from adafruit_bitmap_font import bitmap_font @@ -234,9 +234,7 @@ def _load_row(self, y, row): .in_group = true }}; #endif -""".format( - blinka_size - ) +""".format(blinka_size) ) c_file.write( @@ -285,9 +283,7 @@ def _load_row(self, y, row): .inline_tiles = false, .in_group = true }}; -""".format( - len(all_characters), tile_x, tile_y - ) +""".format(len(all_characters), tile_x, tile_y) ) c_file.write( @@ -315,17 +311,13 @@ def _load_row(self, y, row): .inline_tiles = false, .in_group = true }}; -""".format( - len(all_characters), tile_x, tile_y - ) +""".format(len(all_characters), tile_x, tile_y) ) c_file.write( """\ const uint32_t font_bitmap_data[{}] = {{ -""".format( - bytes_per_row * tile_y // 4 - ) +""".format(bytes_per_row * tile_y // 4) ) for i, word in enumerate(struct.iter_unpack("\n\n") +c_file.write("// Autogenerated by tools/gen_web_workflow_static.py\n") +c_file.write("#include \n\n") for f in args.files: path = pathlib.Path(f.name) diff --git a/tools/insert-usb-ids.py b/tools/insert-usb-ids.py index 4691d5a710c1e..1b043e1fef04f 100644 --- a/tools/insert-usb-ids.py +++ b/tools/insert-usb-ids.py @@ -6,8 +6,6 @@ # inserts those values into the template file specified by sys.argv[2], # printing the result to stdout -from __future__ import print_function - import sys import re import string diff --git a/tools/makemanifest.py b/tools/makemanifest.py index a74a6934aeabe..860935397af14 100644 --- a/tools/makemanifest.py +++ b/tools/makemanifest.py @@ -24,7 +24,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import sys import os import subprocess @@ -245,7 +244,11 @@ def main(): b'#include "py/emitglue.h"\n' b"extern const qstr_pool_t mp_qstr_const_pool;\n" b"const qstr_pool_t mp_qstr_frozen_const_pool = {\n" - b" (qstr_pool_t*)&mp_qstr_const_pool, MP_QSTRnumber_of, 0, 0\n" + b" #if MICROPY_QSTR_BYTES_IN_HASH\n" + b" (qstr_pool_t*)&mp_qstr_const_pool, MP_QSTRnumber_of, 0, 0, 0, NULL, NULL, {},\n" + b" #else\n" + b" (qstr_pool_t*)&mp_qstr_const_pool, MP_QSTRnumber_of, 0, 0, 0, NULL, {},\n" + b" #endif\n" b"};\n" b'const char mp_frozen_names[] = { MP_FROZEN_STR_NAMES "\\0"};\n' b"const mp_raw_code_t *const mp_frozen_mpy_content[] = {NULL};\n" diff --git a/tools/manifestfile.py b/tools/manifestfile.py index aa85c4650f2a6..9c7a6e140f968 100644 --- a/tools/manifestfile.py +++ b/tools/manifestfile.py @@ -25,7 +25,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from __future__ import print_function import contextlib import os import sys @@ -62,6 +61,9 @@ # URL to file. (TODO) FILE_TYPE_HTTP = 2 +# Default list of libraries in micropython-lib to search for library packages. +BASE_LIBRARY_NAMES = ("micropython", "python-stdlib", "python-ecosys") + class ManifestFileError(Exception): pass @@ -196,6 +198,12 @@ def __init__(self, mode, path_vars=None): self._metadata = [ManifestPackageMetadata()] # Registered external libraries. self._libraries = {} + # List of directories to search for packages. + self._library_dirs = [] + # Add default micropython-lib libraries if $(MPY_LIB_DIR) has been specified. + if self._path_vars["MPY_LIB_DIR"]: + for lib in BASE_LIBRARY_NAMES: + self.add_library(lib, os.path.join("$(MPY_LIB_DIR)", lib)) def _resolve_path(self, path): # Convert path to an absolute path, applying variable substitutions. @@ -282,7 +290,7 @@ def _add_file(self, full_path, target_path, kind=KIND_AUTO, opt=None): def _search(self, base_path, package_path, files, exts, kind, opt=None, strict=False): base_path = self._resolve_path(base_path) - if files: + if files is not None: # Use explicit list of files (relative to package_path). for file in files: if package_path: @@ -398,18 +406,16 @@ def _require_from_path(self, library_path, name, version, extra_kwargs): return True return False - def require(self, name, version=None, unix_ffi=False, pypi=None, library=None, **kwargs): + def require(self, name, version=None, pypi=None, library=None, **kwargs): """ Require a package by name from micropython-lib. - Optionally specify unix_ffi=True to use a module from the unix-ffi directory. - Optionally specify pipy="package-name" to indicate that this should use the named package from PyPI when building for CPython. Optionally specify library="name" to reference a package from a library that has been previously registered with add_library(). Otherwise - micropython-lib will be used. + the list of library paths will be used. """ self._metadata[-1].check_initialised(self._mode) @@ -426,39 +432,35 @@ def require(self, name, version=None, unix_ffi=False, pypi=None, library=None, * raise ValueError("Unknown library '{}' for require('{}').".format(library, name)) library_path = self._libraries[library] # Search for {library_path}/**/{name}/manifest.py. - if not self._require_from_path(library_path, name, version, kwargs): - raise ValueError( - "Package '{}' not found in external library '{}' ({}).".format( - name, library, library_path - ) + if self._require_from_path(library_path, name, version, kwargs): + return + raise ValueError( + "Package '{}' not found in external library '{}' ({}).".format( + name, library, library_path ) - elif self._path_vars["MPY_LIB_DIR"]: - # Find package in micropython-lib, in one of the three top-level directories. - lib_dirs = ["micropython", "python-stdlib", "python-ecosys"] - if unix_ffi: - # Additionally search unix-ffi only if unix_ffi=True, and make unix-ffi modules - # take precedence. - lib_dirs = ["unix-ffi"] + lib_dirs - - for lib_dir in lib_dirs: - # Search for {lib_dir}/**/{name}/manifest.py. - if self._require_from_path( - os.path.join(self._path_vars["MPY_LIB_DIR"], lib_dir), name, version, kwargs - ): - return - - raise ValueError("Package '{}' not found in local micropython-lib.".format(name)) - else: - # TODO: HTTP request to obtain URLs from manifest.json. - raise ValueError("micropython-lib not available for require('{}').", name) + ) - def add_library(self, library, library_path): + for lib_dir in self._library_dirs: + # Search for {lib_dir}/**/{name}/manifest.py. + if self._require_from_path(lib_dir, name, version, kwargs): + return + + raise ValueError("Package '{}' not found in any known library.".format(name)) + + def add_library(self, library, library_path, prepend=False): """ Register the path to an external named library. - This allows require("name", library="library") to find packages in that library. + The path will be automatically searched when using require(). By default the + added library is added to the end of the list of libraries to search. Pass + `prepend=True` to add it to the start of the list. + + Additionally, the added library can be explicitly requested by using + `require("name", library="library")`. """ - self._libraries[library] = self._resolve_path(library_path) + library_path = self._resolve_path(library_path) + self._libraries[library] = library_path + self._library_dirs.insert(0 if prepend else len(self._library_dirs), library_path) def package(self, package_path, files=None, base_path=".", opt=None): """ @@ -600,6 +602,9 @@ def main(): default=os.path.join(os.path.dirname(__file__), "../lib/micropython-lib"), help="path to micropython-lib repo", ) + cmd_parser.add_argument( + "--unix-ffi", action="store_true", help="prepend unix-ffi to the library path" + ) cmd_parser.add_argument("--port", default=None, help="path to port dir") cmd_parser.add_argument("--board", default=None, help="path to board dir") cmd_parser.add_argument( @@ -629,6 +634,8 @@ def main(): exit(1) m = ManifestFile(mode, path_vars) + if args.unix_ffi: + m.add_library("unix-ffi", os.path.join("$(MPY_LIB_DIR)", "unix-ffi"), prepend=True) for manifest_file in args.files: try: m.execute(manifest_file) diff --git a/tools/merge_micropython.py b/tools/merge_micropython.py index 37d44c3b7e3a0..7c4d76507930b 100644 --- a/tools/merge_micropython.py +++ b/tools/merge_micropython.py @@ -8,7 +8,7 @@ I add a sys.exit(0) after a section, and once a section runs, I delete it temporarily and move on to the next section. -- dhalbert -Updated for v1.22.2 merge - dhalbert +Updated for v1.25.0 merge - dhalbert """ @@ -18,256 +18,233 @@ from sh import git import sys -out_buf = StringIO() -ports_to_delete = [ - "bare-arm", - "cc3200", - "embed", - "esp32", - "esp8266", - "mimxrt", - "minimal", - "nrf", - "pic16bit", - "powerpc", - "qemu-arm", - "renesas-ra", - "rp2", - "samd", - "stm32", - "webassembly", - "windows", - "zephyr", -] -for p in ports_to_delete: - try: - git.rm("-rf", "ports/" + p) - except sh.ErrorReturnCode_128: - pass +def rm_paths(base, paths): + for path in paths: + try: + git.rm("-rf", base + "/" + path) + except sh.ErrorReturnCode_128: + pass -# We inherit stm32 changes into stm because we did a git rename. -git.status("--porcelain=1", "ports/stm", _out=out_buf) -out_buf.seek(0) -line = out_buf.readline() -while line: - state, path = line.split() - if state == "UU": - git.checkout("--ours", path) - git.add(path) - elif state == "UA": - git.rm(path) - line = out_buf.readline() -# MicroPython has their own CI settings. Let's not use them now. -out_buf = StringIO() -git.status("--porcelain=1", ".github/workflows", _out=out_buf) -out_buf.seek(0) -line = out_buf.readline() -while line: - state, path = line.split() - if state == "A": - git.rm("-f", path) - else: - print(state, path) - line = out_buf.readline() - -# Delete docs and tests for things we don't need anymore -docs_to_delete = [ - "conf.py", - "develop", - "differences", - "esp32", - "esp8266", - "library/bluetooth.rst", - "library/btree.rst", - "library/cryptolib.rst", - "library/esp*.rst", - "library/framebuf.rst", - "library/hashlib.rst", - "library/lcd160cr.rst", - "library/machine*.rst", - "library/math.rst", - "library/network*.rst", - "library/os.rst", - "library/pyb*.rst", - "library/random.rst", - "library/rp2*.rst", - "library/uos.rst", - "library/socket.rst", - "library/ssl.rst", - "library/stm.rst", - "library/struct.rst", - "library/_thread.rst", - "library/time.rst", - "library/uasyncio.rst", - "library/uctypes.rst", - "library/wipy.rst", - "library/wm8960.rst", - "library/zephyr*.rst", - "library/zlib.rst", - "make.bat", - "mimxrt", - "pyboard", - "reference", - "renesas-ra", - "rp2", - "samd", - "templates/topindex.html", - "wipy", - "zephyr", -] -for d in docs_to_delete: - try: - git.rm("-rf", "docs/" + d) - except sh.ErrorReturnCode_128: - pass - -tests_to_delete = [ - "esp32", - "multi_bluetooth", - "multi_espnow", - "multi_net", - "net_hosted", - "net_inet", - "pyb", - "wipy", -] -for t in tests_to_delete: - try: - git.rm("-rf", "tests/" + t) - except sh.ErrorReturnCode_128: - pass - - -libs_to_delete = [ - "asf4", - "btstack", - "libhydrogen", - "lwip", - "micropython-lib", - "mynewt-nimble", - "nrfx", - "nxp_driver", - "pico-sdk", - "protobuf-c", - "stm32lib", - "wiznet5k", -] -for l in libs_to_delete: - try: - git.rm("-rf", "lib/" + l) - except sh.ErrorReturnCode_128: - pass - -extmod_to_delete = [ - "btstack", - "extmod.cmake", - "machine_*", - "mbedtls", - "modbluetooth.*", - "modbtree.*", - "modframebuf.*", - "modlwip.*", - "modnetwork.*", - "modonewire.*", - "moducryptolib.*", - "modsocket.*", - "modssl_*.*", - "modtimeq.*", - "modwebsocket.*", - "modwebrepl.*", - "mpbthci.*", - "network_*.*", - "nimble", -] -for e in extmod_to_delete: - try: - git.rm("-rf", "extmod/" + e) - except sh.ErrorReturnCode_128 as error: - print(error) - -top_delete = [ - "drivers", - "README.md", - "CODEOFCONDUCT.md", - "CODECONVENTIONS.md", -] -for t in top_delete: - try: - git.rm("-rf", t) - except sh.ErrorReturnCode_128: - pass - -dot_github_delete = [ - ".github/dependabot.yml", - ".github/FUNDING.yml", - ".github/ISSUE_TEMPLATE/documentation.md", - ".github/ISSUE_TEMPLATE/security.md", - ".github/workflows/code_formatting.yml", - ".github/workflows/code_size_comment.yml", - ".github/workflows/code_size.yml", - ".github/workflows/commit_formatting.yml", - ".github/workflows/docs.yml", - ".github/workflows/examples.yml", - ".github/workflows/mpremote.yml", - ".github/workflows/mpy_format.yml", - ".github/workflows/mpy_format.yml", - ".github/workflows/ports_*.yml", -] -for t in dot_github_delete: - try: - git.rm("-rf", t) - except sh.ErrorReturnCode_128: - pass - -# Always ours: -always_ours = [ - ".github", - "devices", - "supervisor", - "shared-bindings", - "shared-module", - "ports/atmel-samd", - "ports/cxd56", - "ports/espressif", - "ports/mimxrt10xx", - "ports/raspberrypi", - "ports/stm", -] -for ours in always_ours: - out_buf = StringIO() - git.status("--porcelain=1", ours, _out=out_buf) - out_buf.seek(0) - line = out_buf.readline() - while line: - state, path = line.split() - if state == "UU": - print("ours", path) - git.checkout("--ours", path) - git.add(path) - else: - print(state, path) +def checkout_ours(always_ours): + for ours in always_ours: + out_buf = StringIO() + git.status("--porcelain=1", ours, _out=out_buf) + out_buf.seek(0) line = out_buf.readline() + while line: + state, path = line.split() + if state == "UU": + print("ours", path) + git.checkout("--ours", path) + git.add(path) + else: + print(state, path) + line = out_buf.readline() + + +rm_paths( + "ports", + [ + "alif", + "bare-arm", + "cc3200", + "embed", + "esp32", + "esp8266", + "mimxrt", + "minimal", + "nrf", + "pic16bit", + "powerpc", + "qemu", + "renesas-ra", + "rp2", + "samd", + "stm32", + "webassembly", + "windows", + "zephyr", + ], +) + +# Delete MicroPython-specific docs. +rm_paths( + "docs", + [ + "conf.py", + "develop", + "differences", + "esp32", + "esp8266", + "library/bluetooth.rst", + "library/btree.rst", + "library/cryptolib.rst", + "library/esp*.rst", + "library/framebuf.rst", + "library/hashlib.rst", + "library/lcd160cr.rst", + "library/machine*.rst", + "library/math.rst", + "library/network*.rst", + "library/os.rst", + "library/pyb*.rst", + "library/random.rst", + "library/rp2*.rst", + "library/uos.rst", + "library/socket.rst", + "library/ssl.rst", + "library/stm.rst", + "library/struct.rst", + "library/_thread.rst", + "library/time.rst", + "library/uasyncio.rst", + "library/uctypes.rst", + "library/vfs.rst", + "library/wipy.rst", + "library/wm8960.rst", + "library/zephyr*.rst", + "library/zlib.rst", + "make.bat", + "mimxrt", + "pyboard", + "renesas-ra", + "rp2", + "samd", + "templates/topindex.html", + "wipy", + "zephyr", + ], +) + +# Delete MicroPython-specific tests. +rm_paths( + "tests", + [ + "esp32", + "multi_bluetooth", + "multi_espnow", + "multi_net", + "multi_pyb_can", + "multi_wlan", + "net_hosted", + "net_inet", + "ports", + "pyb", + "wipy", + ], +) + +# libs we don't use +rm_paths( + "lib", + [ + "alif*", + "asf4", + "btstack", + "libhydrogen", + "lwip", + "mynewt-nimble", + "nrfx", + "nxp_driver", + "pico-sdk", + "protobuf-c", + "stm32lib", + "wiznet5k", + ], +) + +# extmod modules we don't use +rm_paths( + "extmod", + [ + "btstack", + "extmod.cmake", + "machine_*", + "mbedtls", + "modbluetooth.*", + "modbtree.*", + "modframebuf.*", + "modlwip.*", + "modmachine.*", + "modnetwork.*", + "modonewire.*", + "moducryptolib.*", + "modsocket.*", + "modssl_*", + "modtls_*", + "modtimeq.*", + "modwebsocket.*", + "modwebrepl.*", + "mpbthci.*", + "network_*", + "nimble", + "virtpin.*", + ], +) + +# shared things we don't use +rm_paths( + "shared", + [ + "netutils", + "tinyusb", + "runtime/softtimer.*", + ], +) + +# top-level files and dirs we don't use +rm_paths( + "", + [ + "drivers", + "LICENSE_MicroPython", + "README.md", + "CODEOFCONDUCT.md", + "CODECONVENTIONS.md", + ], +) + +# .github and CI we don't use +rm_paths( + ".github", + [ + "dependabot.yml", + "FUNDING.yml", + "ISSUE_TEMPLATE/feature_request.yml", + "ISSUE_TEMPLATE/documentation.yml", + "ISSUE_TEMPLATE/security.yml", + "workflows/biome.yml", + "workflows/code_formatting.yml", + "workflows/code_size_comment.yml", + "workflows/code_size.yml", + "workflows/codespell.yml", + "workflows/commit_formatting.yml", + "workflows/docs.yml", + "workflows/examples.ymlworkflows/mpremote.yml", + "workflows/mpy_format.yml", + "workflows/ports_*.yml", + "workflows/ruff.yml", + ], +) -# # Check to see if any files changed only in formatting -# out_buf = StringIO() -# git.status("--porcelain=1", ".", _out=out_buf) -# out_buf.seek(0) -# line = out_buf.readline() -# while line: -# state = line.split()[0] -# if state in ("D", "R", "DD"): -# line = out_buf.readline() -# continue -# state, path = line.split() -# log_buf = StringIO() -# git.log("--pretty=tformat:%H", "25ae98f..HEAD", path, _out=log_buf, _tty_out=False) -# log_buf.seek(0) -# commits = [] -# for line in log_buf.readlines(): -# commits.append(line.strip()) -# if state in ["UU", "M"] and commits == ["a52eb88031620a81521b937f2a0651dbac2bb350"]: -# git.checkout("--theirs", path) -# git.add(path) -# line = out_buf.readline() +# Always ours: +checkout_ours( + [ + ".github", + "devices", + "lib/mbedtls_config", + "supervisor", + "shared-bindings", + "shared-module", + "ports/atmel-samd", + "ports/cxd56", + "ports/espressif", + "ports/mimxrt10xx", + "ports/raspberrypi", + "ports/silabs", + # We inherit stm32 changes into stm because we did a git rename. + "ports/stm", + ] +) diff --git a/tools/metrics.py b/tools/metrics.py index 9c5ed1d7d5a60..8bb96ba119a23 100755 --- a/tools/metrics.py +++ b/tools/metrics.py @@ -43,20 +43,23 @@ """ -import collections, sys, re, subprocess +import collections, os, sys, re, shlex, subprocess, multiprocessing -MAKE_FLAGS = ["-j3", "CFLAGS_EXTRA=-DNDEBUG"] +MAKE_FLAGS = ["-j{}".format(multiprocessing.cpu_count()), "CFLAGS_EXTRA=-DNDEBUG"] class PortData: - def __init__(self, name, dir, output, make_flags=None): + def __init__(self, name, dir, output, make_flags=None, pre_cmd=None): self.name = name self.dir = dir self.output = output self.make_flags = make_flags self.needs_mpy_cross = dir not in ("bare-arm", "minimal") + self.pre_cmd = pre_cmd +mpy_cross_output = "mpy-cross/build/mpy-cross" + port_data = { "b": PortData("bare-arm", "bare-arm", "build/firmware.elf"), "m": PortData("minimal x86", "minimal", "build/firmware.elf"), @@ -65,16 +68,29 @@ def __init__(self, name, dir, output, make_flags=None): "s": PortData("stm32", "stm32", "build-PYBV10/firmware.elf", "BOARD=PYBV10"), "c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"), "8": PortData("esp8266", "esp8266", "build-ESP8266_GENERIC/firmware.elf"), - "3": PortData("esp32", "esp32", "build-ESP32_GENERIC/micropython.elf"), + "3": PortData( + "esp32", + "esp32", + "build-ESP32_GENERIC/micropython.elf", + pre_cmd=". esp-idf/export.sh", + ), "x": PortData("mimxrt", "mimxrt", "build-TEENSY40/firmware.elf"), "e": PortData("renesas-ra", "renesas-ra", "build-EK_RA6M2/firmware.elf"), "r": PortData("nrf", "nrf", "build-PCA10040/firmware.elf"), - "p": PortData("rp2", "rp2", "build-RPI_PICO/firmware.elf"), + "p": PortData("rp2", "rp2", "build-RPI_PICO_W/firmware.elf", "BOARD=RPI_PICO_W"), "d": PortData("samd", "samd", "build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf"), + "v": PortData("qemu rv32", "qemu", "build-VIRT_RV32/firmware.elf", "BOARD=VIRT_RV32"), } +for port_letter, port in port_data.items(): + port.pre_cmd = os.environ.get(f"PRE_CMD_{port_letter}", port.pre_cmd) + + +def quoted(args): + return " ".join(shlex.quote(word) for word in args) -def syscmd(*args): + +def syscmd(*args, pre_cmd=None): sys.stdout.flush() a2 = [] for a in args: @@ -82,6 +98,10 @@ def syscmd(*args): a2.append(a) elif a: a2.extend(a) + if pre_cmd is not None: + a2_quoted = quoted(a2) + a2 = ["bash", "-c", "{} && {}".format(pre_cmd, a2_quoted)] + print(a2) subprocess.check_call(a2) @@ -107,6 +127,8 @@ def read_build_log(filename): with open(filename) as f: for line in f: line = line.strip() + if line.startswith("BUILDING ") and "_ref" not in data: + data["_ref"] = line.removeprefix("BUILDING ") if line.strip() == "COMPUTING SIZES": found_sizes = True elif found_sizes: @@ -138,9 +160,15 @@ def do_diff(args): data1 = read_build_log(args[0]) data2 = read_build_log(args[1]) + ref1 = data1.pop("_ref", "(unknown ref)") + ref2 = data2.pop("_ref", "(unknown ref)") + print(f"Reference: {ref1}") + print(f"Comparison: {ref2}") max_delta = None for key, value1 in data1.items(): value2 = data2[key] + if key == mpy_cross_output: + name = "mpy-cross" for port in port_data.values(): if key == "ports/{}/{}".format(port.dir, port.output): name = port.name @@ -180,8 +208,19 @@ def do_clean(args): ports = parse_port_list(args) print("CLEANING") + + if any(port.needs_mpy_cross for port in ports): + syscmd("make", "-C", "mpy-cross", "clean") + for port in ports: - syscmd("make", "-C", "ports/{}".format(port.dir), port.make_flags, "clean") + syscmd( + "make", + "-C", + "ports/{}".format(port.dir), + port.make_flags, + "clean", + pre_cmd=port.pre_cmd, + ) def do_build(args): @@ -195,7 +234,14 @@ def do_build(args): print("BUILDING PORTS") for port in ports: - syscmd("make", "-C", "ports/{}".format(port.dir), MAKE_FLAGS, port.make_flags) + syscmd( + "make", + "-C", + "ports/{}".format(port.dir), + MAKE_FLAGS, + port.make_flags, + pre_cmd=port.pre_cmd, + ) do_sizes(args) @@ -206,6 +252,10 @@ def do_sizes(args): ports = parse_port_list(args) print("COMPUTING SIZES") + + if any(port.needs_mpy_cross for port in ports): + syscmd("size", mpy_cross_output) + for port in ports: syscmd("size", "ports/{}/{}".format(port.dir, port.output)) diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py index 8bb1c6020d09a..bf0b89018e4e7 100755 --- a/tools/mpy-tool.py +++ b/tools/mpy-tool.py @@ -24,40 +24,21 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# Python 2/3 compatibility code -from __future__ import print_function -import platform - -if platform.python_version_tuple()[0] == "2": - from binascii import hexlify as hexlify_py2 - - str_cons = lambda val, enc=None: str(val) - bytes_cons = lambda val, enc=None: bytearray(val) - is_str_type = lambda o: isinstance(o, str) - is_bytes_type = lambda o: type(o) is bytearray - is_int_type = lambda o: isinstance(o, int) or isinstance(o, long) # noqa: F821 - - def hexlify_to_str(b): - x = hexlify_py2(b) - return ":".join(x[i : i + 2] for i in range(0, len(x), 2)) - -else: - from binascii import hexlify +import io +import struct +import sys +from binascii import hexlify - str_cons = str - bytes_cons = bytes - is_str_type = lambda o: isinstance(o, str) - is_bytes_type = lambda o: isinstance(o, bytes) - is_int_type = lambda o: isinstance(o, int) +str_cons = str +bytes_cons = bytes +is_str_type = lambda o: isinstance(o, str) +is_bytes_type = lambda o: isinstance(o, bytes) +is_int_type = lambda o: isinstance(o, int) - def hexlify_to_str(b): - return str(hexlify(b, ":"), "ascii") +def hexlify_to_str(b): + return str(hexlify(b, ":"), "ascii") -# end compatibility code - -import sys -import struct sys.path.append(sys.path[0] + "/../py") import makeqstrdata as qstrutil @@ -88,7 +69,7 @@ def __str__(self): class Config: MPY_VERSION = 6 - MPY_SUB_VERSION = 2 + MPY_SUB_VERSION = 3 MICROPY_LONGINT_IMPL_NONE = 0 MICROPY_LONGINT_IMPL_LONGLONG = 1 MICROPY_LONGINT_IMPL_MPZ = 2 @@ -113,6 +94,24 @@ class Config: MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 MP_NATIVE_ARCH_XTENSAWIN = 10 +MP_NATIVE_ARCH_RV32IMC = 11 +MP_NATIVE_ARCH_RV64IMC = 12 + +MP_NATIVE_ARCH_NAMES = [ + "NONE", + "X86", + "X64", + "ARMV6", + "ARMV6M", + "ARMV7M", + "ARMV7EM", + "ARMV7EMSP", + "ARMV7EMDP", + "XTENSA", + "XTENSAWIN", + "RV32IMC", + "RV64IMC", +] MP_PERSISTENT_OBJ_FUN_TABLE = 0 MP_PERSISTENT_OBJ_NONE = 1 @@ -126,7 +125,10 @@ class Config: MP_PERSISTENT_OBJ_COMPLEX = 9 MP_PERSISTENT_OBJ_TUPLE = 10 -# Circuitpython: this does not match upstream because we added MP_SCOPE_FLAG_ASYNC + +MP_SCOPE_FLAG_GENERATOR = 0x01 +# CIRCUITPY-CHANGE: async is distinct from generator; flag constants are different +MP_SCOPE_FLAG_ASYNC = 0x10 MP_SCOPE_FLAG_VIPERRELOC = 0x20 MP_SCOPE_FLAG_VIPERRODATA = 0x40 MP_SCOPE_FLAG_VIPERBSS = 0x80 @@ -138,6 +140,8 @@ class Config: MP_BC_FORMAT_VAR_UINT = 2 MP_BC_FORMAT_OFFSET = 3 +MP_NATIVE_ARCH_FLAGS_PRESENT = 0x40 + mp_unary_op_method_name = ( "__pos__", "__neg__", @@ -302,6 +306,25 @@ class Opcode: MP_BC_POP_JUMP_IF_TRUE, MP_BC_POP_JUMP_IF_FALSE, ) + ALL_OFFSET = ( + MP_BC_UNWIND_JUMP, + MP_BC_JUMP, + MP_BC_POP_JUMP_IF_TRUE, + MP_BC_POP_JUMP_IF_FALSE, + MP_BC_JUMP_IF_TRUE_OR_POP, + MP_BC_JUMP_IF_FALSE_OR_POP, + MP_BC_SETUP_WITH, + MP_BC_SETUP_EXCEPT, + MP_BC_SETUP_FINALLY, + MP_BC_POP_EXCEPT_JUMP, + MP_BC_FOR_ITER, + ) + ALL_WITH_CHILD = ( + MP_BC_MAKE_FUNCTION, + MP_BC_MAKE_FUNCTION_DEFARGS, + MP_BC_MAKE_CLOSURE, + MP_BC_MAKE_CLOSURE_DEFARGS, + ) # Create a dict mapping opcode value to opcode name. mapping = ["unknown" for _ in range(256)] @@ -558,6 +581,7 @@ def __init__( mpy_source_file, mpy_segments, header, + arch_flags, qstr_table, obj_table, raw_code, @@ -570,6 +594,7 @@ def __init__( self.mpy_segments = mpy_segments self.source_file = qstr_table[0] self.header = header + self.arch_flags = arch_flags self.qstr_table = qstr_table self.obj_table = obj_table self.raw_code = raw_code @@ -647,6 +672,14 @@ def disassemble(self): print("mpy_source_file:", self.mpy_source_file) print("source_file:", self.source_file.str) print("header:", hexlify_to_str(self.header)) + arch_index = (self.header[2] >> 2) & 0x2F + if arch_index >= len(MP_NATIVE_ARCH_NAMES): + arch_name = "UNKNOWN" + else: + arch_name = MP_NATIVE_ARCH_NAMES[arch_index] + print("arch:", arch_name) + if self.header[2] & MP_NATIVE_ARCH_FLAGS_PRESENT != 0: + print("arch_flags:", hex(self.arch_flags)) print("qstr_table[%u]:" % len(self.qstr_table)) for q in self.qstr_table: print(" %s" % q.str) @@ -682,7 +715,7 @@ def freeze(self, compiled_module_index): else: print(" .obj_table = NULL,") print(" },") - print(" .rc = &raw_code_%s," % self.raw_code.escaped_name) + print(" .proto_fun = &proto_fun_%s," % self.raw_code.escaped_name) print("};") def freeze_constant_obj(self, obj_name, obj): @@ -732,8 +765,8 @@ def freeze_constant_obj(self, obj_name, obj): elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE: raise FreezeError(self, "target does not support long int") elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_LONGLONG: - # TODO - raise FreezeError(self, "freezing int to long-long is not implemented") + print("static const mp_obj_int_t %s = {{&mp_type_int}, %d};" % (obj_name, obj)) + return "MP_ROM_PTR(&%s)" % obj_name elif config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_MPZ: neg = 0 if obj < 0: @@ -884,7 +917,7 @@ def __init__(self, parent_name, qstr_table, fun_data, prelude_offset, code_kind) self.escaped_name = unique_escaped_name def disassemble_children(self): - print(" children:", [rc.simple_name.str for rc in self.children]) + self.print_children_annotated() for rc in self.children: rc.disassemble() @@ -897,7 +930,8 @@ def freeze_children(self, prelude_ptr=None): print() print("static const mp_raw_code_t *const children_%s[] = {" % self.escaped_name) for rc in self.children: - print(" &raw_code_%s," % rc.escaped_name) + # CIRCUITPY-CHANGE: add (void *) to prevent cast-align compiler warning + print(" (const mp_raw_code_t *)(void *)&proto_fun_%s," % rc.escaped_name) if prelude_ptr: print(" (void *)%s," % prelude_ptr) print("};") @@ -905,14 +939,25 @@ def freeze_children(self, prelude_ptr=None): def freeze_raw_code(self, prelude_ptr=None, type_sig=0): # Generate mp_raw_code_t. - print("static const mp_raw_code_t raw_code_%s = {" % self.escaped_name) + if self.code_kind == MP_CODE_NATIVE_ASM: + raw_code_type = "mp_raw_code_t" + else: + raw_code_type = "mp_raw_code_truncated_t" + + empty_children = len(self.children) == 0 and prelude_ptr is None + generate_minimal = self.code_kind == MP_CODE_BYTECODE and empty_children + + if generate_minimal: + print("#if MICROPY_PERSISTENT_CODE_SAVE") + + print("static const %s proto_fun_%s = {" % (raw_code_type, self.escaped_name)) + print(" .proto_fun_indicator[0] = MP_PROTO_FUN_INDICATOR_RAW_CODE_0,") + print(" .proto_fun_indicator[1] = MP_PROTO_FUN_INDICATOR_RAW_CODE_1,") print(" .kind = %s," % RawCode.code_kind_str[self.code_kind]) - print(" .scope_flags = 0x%02x," % self.scope_flags) - print(" .n_pos_args = %u," % self.n_pos_args) + print(" .is_generator = %d," % bool(self.scope_flags & MP_SCOPE_FLAG_GENERATOR)) + # CIRCUITPY-CHANGE: async is distinct from generator + print(" .is_async = %d," % bool(self.scope_flags & MP_SCOPE_FLAG_ASYNC)) print(" .fun_data = fun_data_%s," % self.escaped_name) - print(" #if MICROPY_PERSISTENT_CODE_SAVE || MICROPY_DEBUG_PRINTERS") - print(" .fun_data_len = %u," % len(self.fun_data)) - print(" #endif") if len(self.children): print(" .children = (void *)&children_%s," % self.escaped_name) elif prelude_ptr: @@ -920,9 +965,14 @@ def freeze_raw_code(self, prelude_ptr=None, type_sig=0): else: print(" .children = NULL,") print(" #if MICROPY_PERSISTENT_CODE_SAVE") + print(" .fun_data_len = %u," % len(self.fun_data)) print(" .n_children = %u," % len(self.children)) + print(" #if MICROPY_EMIT_MACHINE_CODE") + print(" .prelude_offset = %u," % self.prelude_offset) + print(" #endif") if self.code_kind == MP_CODE_BYTECODE: print(" #if MICROPY_PY_SYS_SETTRACE") + print(" .line_of_definition = %u," % 0) # TODO print(" .prelude = {") print(" .n_state = %u," % self.prelude_signature[0]) print(" .n_exc_stack = %u," % self.prelude_signature[1]) @@ -943,21 +993,91 @@ def freeze_raw_code(self, prelude_ptr=None, type_sig=0): " .opcodes = fun_data_%s + %u," % (self.escaped_name, self.offset_opcodes) ) print(" },") - print(" .line_of_definition = %u," % 0) # TODO print(" #endif") - print(" #if MICROPY_EMIT_MACHINE_CODE") - print(" .prelude_offset = %u," % self.prelude_offset) - print(" #endif") - print(" #endif") - print(" #if MICROPY_EMIT_MACHINE_CODE") - print(" .type_sig = %u," % type_sig) print(" #endif") + if self.code_kind == MP_CODE_NATIVE_ASM: + print(" .asm_n_pos_args = %u," % self.n_pos_args) + print(" .asm_type_sig = %u," % type_sig) print("};") + if generate_minimal: + print("#else") + print("#define proto_fun_%s fun_data_%s[0]" % (self.escaped_name, self.escaped_name)) + print("#endif") + global raw_code_count, raw_code_content raw_code_count += 1 raw_code_content += 4 * 4 + @staticmethod + def decode_lineinfo(line_info: memoryview) -> "tuple[int, int, memoryview]": + c = line_info[0] + if (c & 0x80) == 0: + # 0b0LLBBBBB encoding + return (c & 0x1F), (c >> 5), line_info[1:] + else: + # 0b1LLLBBBB 0bLLLLLLLL encoding (l's LSB in second byte) + return (c & 0xF), (((c << 4) & 0x700) | line_info[1]), line_info[2:] + + def get_source_annotation(self, ip: int, file=None) -> dict: + bc_offset = ip - self.offset_opcodes + try: + line_info = memoryview(self.fun_data)[self.offset_line_info : self.offset_opcodes] + except AttributeError: + return {"file": file, "line": None} + + source_line = 1 + while line_info: + bc_increment, line_increment, line_info = self.decode_lineinfo(line_info) + if bc_offset >= bc_increment: + bc_offset -= bc_increment + source_line += line_increment + else: + break + + return {"file": file, "line": source_line} + + def get_label(self, ip: "int | None" = None, child_num: "int | None" = None) -> str: + if ip is not None: + assert child_num is None + return "%s.%d" % (self.escaped_name, ip) + elif child_num is not None: + return "%s.child%d" % (self.escaped_name, child_num) + else: + return "%s" % self.escaped_name + + def print_children_annotated(self) -> None: + """ + Equivalent to `print(" children:", [child.simple_name.str for child in self.children])`, + but also includes json markers for the start and end of each one's name in that line. + """ + + labels = ["%s.children" % self.escaped_name] + annotation_labels = [] + output = io.StringIO() + output.write(" children: [") + sep = ", " + for i, child in enumerate(self.children): + if i != 0: + output.write(sep) + start_col = output.tell() + 1 + output.write(child.simple_name.str) + end_col = output.tell() + 1 + labels.append(self.get_label(child_num=i)) + annotation_labels.append( + { + "name": self.get_label(child_num=i), + "target": child.get_label(), + "range": { + "startCol": start_col, + "endCol": end_col, + }, + }, + ) + output.write("]") + + print(output.getvalue(), annotations={"labels": annotation_labels}, labels=labels) + class RawCodeBytecode(RawCode): def __init__(self, parent_name, qstr_table, obj_table, fun_data): @@ -966,9 +1086,58 @@ def __init__(self, parent_name, qstr_table, obj_table, fun_data): parent_name, qstr_table, fun_data, 0, MP_CODE_BYTECODE ) + def get_opcode_annotations_labels( + self, opcode: int, ip: int, arg: int, sz: int, arg_pos: int, arg_len: int + ) -> "tuple[dict, list[str]]": + annotations = { + "source": self.get_source_annotation(ip), + "disassembly": Opcode.mapping[opcode], + } + labels = [self.get_label(ip)] + + if opcode in Opcode.ALL_OFFSET: + annotations["link"] = { + "offset": arg_pos, + "length": arg_len, + "to": ip + arg + sz, + } + annotations["labels"] = [ + { + "name": self.get_label(ip), + "target": self.get_label(ip + arg + sz), + "range": { + "startCol": arg_pos + 1, + "endCol": arg_pos + arg_len + 1, + }, + }, + ] + + elif opcode in Opcode.ALL_WITH_CHILD: + try: + child = self.children[arg] + except IndexError: + # link out-of-range child to the child array itself + target = "%s.children" % self.escaped_name + else: + # link resolvable child to the actual child + target = child.get_label() + + annotations["labels"] = [ + { + "name": self.get_label(ip), + "target": target, + "range": { + "startCol": arg_pos + 1, + "endCol": arg_pos + arg_len + 1, + }, + }, + ] + + return annotations, labels + def disassemble(self): bc = self.fun_data - print("simple_name:", self.simple_name.str) + print("simple_name:", self.simple_name.str, labels=[self.get_label()]) print(" raw bytecode:", len(bc), hexlify_to_str(bc)) print(" prelude:", self.prelude_signature) print(" args:", [self.qstr_table[i].str for i in self.names[1:]]) @@ -984,9 +1153,22 @@ def disassemble(self): pass else: arg = "" - print( - " %-11s %s %s" % (hexlify_to_str(bc[ip : ip + sz]), Opcode.mapping[bc[ip]], arg) + + pre_arg_part = " %-11s %s" % ( + hexlify_to_str(bc[ip : ip + sz]), + Opcode.mapping[bc[ip]], + ) + arg_part = "%s" % arg + annotations, labels = self.get_opcode_annotations_labels( + opcode=bc[ip], + ip=ip, + arg=arg, + sz=sz, + arg_pos=len(pre_arg_part) + 1, + arg_len=len(arg_part), ) + + print(pre_arg_part, arg_part, annotations=annotations, labels=labels) ip += sz self.disassemble_children() @@ -1062,6 +1244,8 @@ def __init__( MP_NATIVE_ARCH_X64, MP_NATIVE_ARCH_XTENSA, MP_NATIVE_ARCH_XTENSAWIN, + MP_NATIVE_ARCH_RV32IMC, + MP_NATIVE_ARCH_RV64IMC, ): self.fun_data_attributes = '__attribute__((section(".text,\\"ax\\",@progbits # ")))' else: @@ -1077,13 +1261,15 @@ def __init__( ): # ARMV6 or Xtensa -- four byte align. self.fun_data_attributes += " __attribute__ ((aligned (4)))" - elif MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP: - # ARMVxxM -- two byte align. + elif ( + MP_NATIVE_ARCH_ARMV6M <= config.native_arch <= MP_NATIVE_ARCH_ARMV7EMDP + ) or MP_NATIVE_ARCH_RV32IMC <= config.native_arch <= MP_NATIVE_ARCH_RV64IMC: + # ARMVxxM or RV{32,64}IMC -- two byte align. self.fun_data_attributes += " __attribute__ ((aligned (2)))" def disassemble(self): fun_data = self.fun_data - print("simple_name:", self.simple_name.str) + print("simple_name:", self.simple_name.str, labels=[self.get_label()]) print( " raw data:", len(fun_data), @@ -1331,12 +1517,13 @@ def read_mpy(filename): # Read and verify the header. header = reader.read_bytes(4) + # CIRCUITPY-CHANGE: "C" is used for CircuitPython if header[0] != ord("C"): raise MPYReadError(filename, "not a valid .mpy file") if header[1] != config.MPY_VERSION: raise MPYReadError(filename, "incompatible .mpy version") feature_byte = header[2] - mpy_native_arch = feature_byte >> 2 + mpy_native_arch = (feature_byte >> 2) & 0x2F if mpy_native_arch != MP_NATIVE_ARCH_NONE: mpy_sub_version = feature_byte & 3 if mpy_sub_version != config.MPY_SUB_VERSION: @@ -1347,6 +1534,11 @@ def read_mpy(filename): raise MPYReadError(filename, "native architecture mismatch") config.mp_small_int_bits = header[3] + arch_flags = 0 + # Read the architecture-specific flag bits if present. + if (feature_byte & MP_NATIVE_ARCH_FLAGS_PRESENT) != 0: + arch_flags = reader.read_uint() + # Read number of qstrs, and number of objects. n_qstr = reader.read_uint() n_obj = reader.read_uint() @@ -1375,6 +1567,7 @@ def read_mpy(filename): filename, segments, header, + arch_flags, qstr_table, obj_table, raw_code, @@ -1472,21 +1665,20 @@ def freeze_mpy(firmware_qstr_idents, compiled_modules): raw_code_count = 0 raw_code_content = 0 - print() - print("const qstr_hash_t mp_qstr_frozen_const_hashes[] = {") - qstr_size = {"metadata": 0, "data": 0} - for _, _, _, qbytes in new: - qhash = qstrutil.compute_hash(qbytes, config.MICROPY_QSTR_BYTES_IN_HASH) - print(" %d," % qhash) - print("};") + if config.MICROPY_QSTR_BYTES_IN_HASH: + print() + print("const qstr_hash_t mp_qstr_frozen_const_hashes[] = {") + for _, _, _, qbytes in new: + qhash = qstrutil.compute_hash(qbytes, config.MICROPY_QSTR_BYTES_IN_HASH) + print(" %d," % qhash) + qstr_content += config.MICROPY_QSTR_BYTES_IN_HASH + print("};") print() print("const qstr_len_t mp_qstr_frozen_const_lengths[] = {") for _, _, _, qbytes in new: print(" %d," % len(qbytes)) - qstr_size["metadata"] += ( - config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH - ) - qstr_size["data"] += len(qbytes) + qstr_content += config.MICROPY_QSTR_BYTES_IN_LEN + qstr_content += len(qbytes) + 1 # include NUL print("};") print() print("extern const qstr_pool_t mp_qstr_const_pool;") @@ -1496,14 +1688,12 @@ def freeze_mpy(firmware_qstr_idents, compiled_modules): print(" true, // is_sorted") print(" %u, // allocated entries" % qstr_pool_alloc) print(" %u, // used entries" % len(new)) - print(" (qstr_hash_t *)mp_qstr_frozen_const_hashes,") + if config.MICROPY_QSTR_BYTES_IN_HASH: + print(" (qstr_hash_t *)mp_qstr_frozen_const_hashes,") print(" (qstr_len_t *)mp_qstr_frozen_const_lengths,") print(" {") for _, _, qstr, qbytes in new: print(' "%s",' % qstrutil.escape_bytes(qstr, qbytes)) - qstr_content += ( - config.MICROPY_QSTR_BYTES_IN_LEN + config.MICROPY_QSTR_BYTES_IN_HASH + len(qbytes) + 1 - ) print(" },") print("};") @@ -1673,25 +1863,40 @@ def merge_mpy(compiled_modules, output_file): merged_mpy.extend(f.read()) else: main_cm_idx = None + arch_flags = 0 for idx, cm in enumerate(compiled_modules): feature_byte = cm.header[2] - mpy_native_arch = feature_byte >> 2 + mpy_native_arch = (feature_byte >> 2) & 0x2F if mpy_native_arch: # Must use qstr_table and obj_table from this raw_code if main_cm_idx is not None: raise Exception("can't merge files when more than one contains native code") main_cm_idx = idx + arch_flags = cm.arch_flags if main_cm_idx is not None: # Shift main_cm to front of list. compiled_modules.insert(0, compiled_modules.pop(main_cm_idx)) + if config.arch_flags is not None: + arch_flags = config.arch_flags + header = bytearray(4) + ## CIRCUITPY-CHANGE: "C" is used for CircuitPython header[0] = ord("C") header[1] = config.MPY_VERSION - header[2] = config.native_arch << 2 | config.MPY_SUB_VERSION if config.native_arch else 0 + header[2] = ( + (MP_NATIVE_ARCH_FLAGS_PRESENT if arch_flags != 0 else 0) + | config.native_arch << 2 + | config.MPY_SUB_VERSION + if config.native_arch + else 0 + ) header[3] = config.mp_small_int_bits merged_mpy.extend(header) + if arch_flags != 0: + merged_mpy.extend(mp_encode_uint(arch_flags)) + n_qstr = 0 n_obj = 0 for cm in compiled_modules: @@ -1716,10 +1921,13 @@ def copy_section(file, offset, offset2): bytecode.append(0b00000010) # prelude size (n_info=1, n_cell=0) bytecode.extend(b"\x00") # simple_name: qstr index 0 (will use source filename) for idx in range(len(compiled_modules)): - bytecode.append(0x32) # MP_BC_MAKE_FUNCTION - bytecode.append(idx) # index raw code - bytecode.extend(b"\x34\x00\x59") # MP_BC_CALL_FUNCTION, 0 args, MP_BC_POP_TOP - bytecode.extend(b"\x51\x63") # MP_BC_LOAD_NONE, MP_BC_RETURN_VALUE + bytecode.append(Opcode.MP_BC_MAKE_FUNCTION) + bytecode.extend(mp_encode_uint(idx)) # index of raw code + bytecode.append(Opcode.MP_BC_CALL_FUNCTION) + bytecode.append(0) # 0 arguments + bytecode.append(Opcode.MP_BC_POP_TOP) + bytecode.append(Opcode.MP_BC_LOAD_CONST_NONE) + bytecode.append(Opcode.MP_BC_RETURN_VALUE) merged_mpy.extend(mp_encode_uint(len(bytecode) << 3 | 1 << 2)) # length, has_children merged_mpy.extend(bytecode) @@ -1744,7 +1952,139 @@ def copy_section(file, offset, offset2): f.write(merged_mpy) -def main(): +def extract_segments(compiled_modules, basename, kinds_arg): + import re + + kind_str = ("META", "QSTR", "OBJ", "CODE") + kinds = set() + if kinds_arg is not None: + for kind in kinds_arg.upper().split(","): + if kind in kind_str: + kinds.add(kind) + else: + raise Exception('unknown segment kind "%s"' % (kind,)) + segments = [] + for module in compiled_modules: + for segment in module.mpy_segments: + if not kinds or kind_str[segment.kind] in kinds: + segments.append((module.mpy_source_file, module.source_file.str, segment)) + count_len = len(str(len(segments))) + sanitiser = re.compile("[^a-zA-Z0-9_.-]") + for counter, entry in enumerate(segments): + file_name, source_file, segment = entry + output_name = ( + basename + + "_" + + str(counter).rjust(count_len, "0") + + "_" + + sanitiser.sub("_", source_file) + + "_" + + kind_str[segment.kind] + + "_" + + sanitiser.sub("_", str(segment.name)) + + ".bin" + ) + with open(file_name, "rb") as source: + with open(output_name, "wb") as output: + source.seek(segment.start) + output.write(source.read(segment.end - segment.start)) + + +class PrintShim: + """Base class for interposing extra functionality onto the global `print` method.""" + + def __init__(self): + self.wrapped_print = None + + def __enter__(self): + global print + + if self.wrapped_print is not None: + raise RecursionError + + self.wrapped_print = print + print = self + + return self + + def __exit__(self, exc_type, exc_value, traceback): + global print + + if self.wrapped_print is None: + return + + print = self.wrapped_print + self.wrapped_print = None + + self.on_exit() + + def on_exit(self): + pass + + def __call__(self, *a, **k): + return self.wrapped_print(*a, **k) + + +class PrintIgnoreExtraArgs(PrintShim): + """Just strip the `annotations` and `labels` kwargs and pass down to the underlying print.""" + + def __call__(self, *a, annotations: dict = {}, labels: "list[str]" = (), **k): + return super().__call__(*a, **k) + + +class PrintJson(PrintShim): + """Output lines as godbolt-compatible JSON with extra annotation info from `annotations` and `labels`, rather than plain text.""" + + def __init__(self, fp=sys.stdout, language_id: str = "mpy"): + super().__init__() + self.fp = fp + self.asm = { + "asm": [], + "labelDefinitions": {}, + "languageId": language_id, + } + self.line_number: int = 0 + self.buf: "io.StringIO | None" = None + + def on_exit(self): + import json + + if self.buf is not None: + # flush last partial line + self.__call__() + + json.dump(self.asm, self.fp) + + def __call__(self, *a, annotations: dict = {}, labels: "list[str]" = (), **k): + # ignore prints directed to an explicit output + if "file" in k: + return super().__call__(*a, **k) + + if self.buf is None: + self.buf = io.StringIO() + + super().__call__(*a, file=sys.stderr, **k) + + if "end" in k: + # buffer partial-line prints to collect into a single AsmResultLine + return super().__call__(*a, file=self.buf, **k) + else: + retval = super().__call__(*a, file=self.buf, end="", **k) + output = self.buf.getvalue() + self.buf = None + + asm_line = {"text": output} + asm_line.update(annotations) + self.asm["asm"].append(asm_line) + + self.line_number += 1 + for label in labels: + self.asm["labelDefinitions"][label] = self.line_number + + return retval + + +def main(args=None): global global_qstrs import argparse @@ -1757,9 +2097,23 @@ def main(): "-d", "--disassemble", action="store_true", help="output disassembled contents of files" ) cmd_parser.add_argument("-f", "--freeze", action="store_true", help="freeze files") + cmd_parser.add_argument( + "-j", + "--json", + action="store_true", + help="output hexdump, disassembly, and frozen code as JSON with extra metadata", + ) cmd_parser.add_argument( "--merge", action="store_true", help="merge multiple .mpy files into one" ) + cmd_parser.add_argument( + "-e", "--extract", metavar="BASE", type=str, help="write segments into separate files" + ) + cmd_parser.add_argument( + "--extract-only", + metavar="KIND[,...]", + help="extract only segments of the given type (meta, qstr, obj, code)", + ) cmd_parser.add_argument("-q", "--qstr-header", help="qstr header file to freeze against") cmd_parser.add_argument( "-mlongint-impl", @@ -1774,9 +2128,15 @@ def main(): default=16, help="mpz digit size used by target (default 16)", ) + cmd_parser.add_argument( + "-march-flags", + metavar="F", + type=int, + help="architecture flags value to set in the output file (strips existing flags if not present)", + ) cmd_parser.add_argument("-o", "--output", default=None, help="output file") cmd_parser.add_argument("files", nargs="+", help="input .mpy files") - args = cmd_parser.parse_args() + args = cmd_parser.parse_args(args) # set config values relevant to target machine config.MICROPY_LONGINT_IMPL = { @@ -1786,6 +2146,7 @@ def main(): }[args.mlongint_impl] config.MPZ_DIG_SIZE = args.mmpz_dig_size config.native_arch = MP_NATIVE_ARCH_NONE + config.arch_flags = args.march_flags # set config values for qstrs, and get the existing base set of qstrs # already in the firmware @@ -1797,7 +2158,7 @@ def main(): else: config.MICROPY_QSTR_BYTES_IN_LEN = 1 config.MICROPY_QSTR_BYTES_IN_HASH = 1 - firmware_qstr_idents = set(qstrutil.static_qstr_list) + firmware_qstr_idents = set(qstrutil.static_qstr_list_ident) # Create initial list of global qstrs. global_qstrs = GlobalQStrList() @@ -1809,24 +2170,40 @@ def main(): print(er, file=sys.stderr) sys.exit(1) - if args.hexdump: - hexdump_mpy(compiled_modules) + if args.json: + if args.freeze: + print_shim = PrintJson(sys.stdout, language_id="c") + elif args.hexdump: + print_shim = PrintJson(sys.stdout, language_id="stderr") + elif args.disassemble: + print_shim = PrintJson(sys.stdout, language_id="mpy") + else: + print_shim = PrintJson(sys.stdout) + else: + print_shim = PrintIgnoreExtraArgs() - if args.disassemble: + with print_shim: if args.hexdump: - print() - disassemble_mpy(compiled_modules) + hexdump_mpy(compiled_modules) - if args.freeze: - try: - freeze_mpy(firmware_qstr_idents, compiled_modules) - except FreezeError as er: - print(er, file=sys.stderr) - sys.exit(1) + if args.disassemble: + if args.hexdump: + print() + disassemble_mpy(compiled_modules) + + if args.freeze: + try: + freeze_mpy(firmware_qstr_idents, compiled_modules) + except FreezeError as er: + print(er, file=sys.stderr) + sys.exit(1) if args.merge: merge_mpy(compiled_modules, args.output) + if args.extract: + extract_segments(compiled_modules, args.extract, args.extract_only) + if __name__ == "__main__": main() diff --git a/tools/mpy_ld.py b/tools/mpy_ld.py index cecb65d0efec4..26db07261631c 100755 --- a/tools/mpy_ld.py +++ b/tools/mpy_ld.py @@ -30,13 +30,14 @@ import sys, os, struct, re from elftools.elf import elffile +import ar_util sys.path.append(os.path.dirname(__file__) + "/../py") import makeqstrdata as qstrutil # MicroPython constants MPY_VERSION = 6 -MPY_SUB_VERSION = 2 +MPY_SUB_VERSION = 3 MP_CODE_BYTECODE = 2 MP_CODE_NATIVE_VIPER = 4 MP_NATIVE_ARCH_X86 = 1 @@ -47,15 +48,17 @@ MP_NATIVE_ARCH_ARMV7EMDP = 8 MP_NATIVE_ARCH_XTENSA = 9 MP_NATIVE_ARCH_XTENSAWIN = 10 +MP_NATIVE_ARCH_RV32IMC = 11 MP_PERSISTENT_OBJ_STR = 5 -# Circuitpython: this does not match upstream because we added MP_SCOPE_FLAG_ASYNC -MP_SCOPE_FLAG_VIPERRELOC = 0x20 -MP_SCOPE_FLAG_VIPERRODATA = 0x40 -MP_SCOPE_FLAG_VIPERBSS = 0x80 +MP_SCOPE_FLAG_VIPERRELOC = 0x10 +MP_SCOPE_FLAG_VIPERRODATA = 0x20 +MP_SCOPE_FLAG_VIPERBSS = 0x40 MP_SMALL_INT_BITS = 31 +MP_FUN_TABLE_MP_TYPE_TYPE_OFFSET = 73 # ELF constants R_386_32 = 1 +R_RISCV_32 = 1 R_X86_64_64 = 1 R_XTENSA_32 = 1 R_386_PC32 = 2 @@ -69,15 +72,58 @@ R_386_GOTOFF = 9 R_386_GOTPC = 10 R_ARM_THM_CALL = 10 +R_XTENSA_ASM_EXPAND = 11 +R_RISCV_BRANCH = 16 +R_RISCV_JAL = 17 +R_RISCV_CALL = 18 +R_RISCV_CALL_PLT = 19 R_XTENSA_DIFF32 = 19 R_XTENSA_SLOT0_OP = 20 +R_RISCV_GOT_HI20 = 20 +R_RISCV_TLS_GD_HI20 = 22 +R_RISCV_PCREL_HI20 = 23 +R_RISCV_PCREL_LO12_I = 24 +R_RISCV_PCREL_LO12_S = 25 R_ARM_BASE_PREL = 25 # aka R_ARM_GOTPC R_ARM_GOT_BREL = 26 # aka R_ARM_GOT32 R_ARM_THM_JUMP24 = 30 +R_RISCV_HI20 = 26 +R_RISCV_LO12_I = 27 +R_RISCV_LO12_S = 28 +R_RISCV_TPREL_HI20 = 29 +R_RISCV_TPREL_LO12_I = 30 +R_RISCV_TPREL_LO12_S = 31 +R_RISCV_TPREL_ADD = 32 +R_RISCV_ADD8 = 33 +R_RISCV_ADD16 = 34 +R_RISCV_ADD32 = 35 +R_RISCV_ADD64 = 36 +R_RISCV_SUB8 = 37 +R_RISCV_SUB16 = 38 +R_RISCV_SUB32 = 39 +R_RISCV_SUB64 = 40 +R_RISCV_GOT32_PCREL = 41 R_X86_64_GOTPCREL = 9 R_X86_64_REX_GOTPCRELX = 42 R_386_GOT32X = 43 +R_RISCV_ALIGN = 43 +R_RISCV_RVC_BRANCH = 44 +R_RISCV_RVC_JUMP = 45 +R_RISCV_RELAX = 51 +R_RISCV_SUB6 = 52 +R_RISCV_SET6 = 53 +R_RISCV_SET8 = 54 +R_RISCV_SET16 = 55 +R_RISCV_SET32 = 56 +R_RISCV_32_PCREL = 57 +R_RISCV_PLT32 = 59 R_XTENSA_PDIFF32 = 59 +R_RISCV_SET_ULEB128 = 60 +R_RISCV_SUB_ULEB128 = 61 +R_RISCV_TLSDESC_HI20 = 62 +R_RISCC_TLSDESC_LOAD_LO12 = 63 +R_RISCV_TLSDESC_ADD_LO12 = 64 +R_RISCV_TLSDESC_CALL = 65 ################################################################################ # Architecture configuration @@ -88,10 +134,26 @@ def asm_jump_x86(entry): def asm_jump_thumb(entry): - # Only signed values that fit in 12 bits are supported + # This function must return the same number of bytes for the encoding of the jump + # regardless of the value of `entry`. b_off = entry - 4 - assert b_off >> 11 == 0 or b_off >> 11 == -1, b_off - return struct.pack("> 1 & 0x07FF)) + if b_off >> 11 == 0 or b_off >> 11 == -1: + # Signed value fits in 12 bits. + b0 = 0xE000 | (b_off >> 1 & 0x07FF) + b1 = 0 + b2 = 0 + b3 = 0 + else: + # Use bl to do a large jump/call: + # push {r0, lr} + # bl + # pop {r0, pc} + b_off -= 2 # skip "push {r0, lr}" + b0 = 0xB400 | 0x0100 | 0x0001 # push, lr, r0 + b1 = 0xF000 | (((b_off) >> 12) & 0x07FF) + b2 = 0xF800 | (((b_off) >> 1) & 0x07FF) + b3 = 0xBC00 | 0x0100 | 0x0001 # pop, pc, r0 + return struct.pack("> 8) +def asm_jump_rv32(entry): + # This could be 6 bytes shorter, but the code currently cannot + # support a trampoline with varying length depending on the offset. + + # auipc t6, HI(entry) + # jalr zero, t6, LO(entry) + upper, lower = split_riscv_address(entry) + return struct.pack( + "> 16 & 0xFF +def split_riscv_address(value): + # The address can be represented with just the lowest 12 bits + if value < 0 and value > -2048: + value = 4096 + value + return 0, value + # 2s complement + if value < 0: + value = 0x100000000 + value + upper, lower = (value & 0xFFFFF000), (value & 0xFFF) + if lower & 0x800 != 0: + # Reverse lower part sign extension + upper += 0x1000 + return upper & 0xFFFFFFFF, lower & 0xFFFFFFFF + + def xxd(text): for i in range(0, len(text), 16): print("{:08x}:".format(i), end="") @@ -306,6 +402,7 @@ def __init__(self, arch): self.known_syms = {} # dict of symbols that are defined self.unresolved_syms = [] # list of unresolved symbols self.mpy_relocs = [] # list of relocations needed in the output .mpy file + self.externs = {} # dict of externally-defined symbols def check_arch(self, arch_name): if arch_name != self.arch.name: @@ -329,7 +426,7 @@ def build_got_generic(env): for r in sec.reloc: s = r.sym if not ( - s.entry["st_info"]["bind"] == "STB_GLOBAL" + s.entry["st_info"]["bind"] in ("STB_GLOBAL", "STB_WEAK") and r["r_info_type"] in env.arch.arch_got ): continue @@ -395,10 +492,14 @@ def populate_got(env): sym = got_entry.sym if hasattr(sym, "resolved"): sym = sym.resolved - sec = sym.section - addr = sym["st_value"] - got_entry.sec_name = sec.name - got_entry.link_addr += sec.addr + addr + if sym.name in env.externs: + got_entry.sec_name = ".external.fixed_addr" + got_entry.link_addr = env.externs[sym.name] + else: + sec = sym.section + addr = sym["st_value"] + got_entry.sec_name = sec.name + got_entry.link_addr += sec.addr + addr # Get sorted GOT, sorted by external, text, rodata, bss so relocations can be combined got_list = sorted( @@ -424,6 +525,9 @@ def populate_got(env): dest = int(got_entry.name.split("+")[1], 16) // env.arch.word_size elif got_entry.sec_name == ".external.mp_fun_table": dest = got_entry.sym.mp_fun_table_offset + elif got_entry.sec_name == ".external.fixed_addr": + # Fixed-address symbols should not be relocated. + continue elif got_entry.sec_name.startswith(".text"): dest = ".text" elif got_entry.sec_name.startswith(".rodata"): @@ -470,6 +574,8 @@ def do_relocation_text(env, text_addr, r): # Default relocation type and name for logging reloc_type = "le32" log_name = None + addr = None + value = None if ( env.arch.name == "EM_386" @@ -562,18 +668,62 @@ def do_relocation_text(env, text_addr, r): reloc = addr - r_offset reloc_type = "xtensa_l32r" - elif env.arch.name == "EM_XTENSA" and r_info_type in (R_XTENSA_DIFF32, R_XTENSA_PDIFF32): - if s.section.name.startswith(".text"): - # it looks like R_XTENSA_[P]DIFF32 into .text is already correctly relocated + elif env.arch.name == "EM_XTENSA" and r_info_type in ( + R_XTENSA_DIFF32, + R_XTENSA_PDIFF32, + R_XTENSA_ASM_EXPAND, + ): + if not hasattr(s, "section") or s.section.name.startswith(".text"): + # it looks like R_XTENSA_[P]DIFF32 into .text is already correctly relocated, + # and expand relaxations cannot occur in non-executable sections. return assert 0 + elif env.arch.name == "EM_RISCV" and r_info_type in ( + R_RISCV_TLS_GD_HI20, + R_RISCV_TLSDESC_HI20, + R_RISCV_TLSDESC_ADD_LO12, + R_RISCV_TLSDESC_CALL, + ): + # TLS relocations are not supported. + raise LinkError("{}: RISC-V TLS relocation: {}".format(s.filename, s.name)) + + elif env.arch.name == "EM_RISCV" and r_info_type in ( + R_RISCV_TPREL_HI20, + R_RISCV_TPREL_LO12_I, + R_RISCV_TPREL_LO12_S, + R_RISCV_TPREL_ADD, + ): + # ThreadPointer-relative relocations are not supported. + raise LinkError("{}: RISC-V TP-relative relocation: {}".format(s.filename, s.name)) + + elif env.arch.name == "EM_RISCV" and r_info_type in (R_RISCV_SET_ULEB128, R_RISCV_SUB_ULEB128): + # 128-bit value relocations are not supported + raise LinkError("{}: RISC-V ULEB128 relocation: {}".format(s.filename, s.name)) + + elif env.arch.name == "EM_RISCV" and r_info_type in (R_RISCV_RELAX, R_RISCV_ALIGN): + # To keep things simple, no relocations are relaxed and thus no + # size optimisation is performed even if there is the chance, along + # with no offsets to fix up. + return + + elif env.arch.name == "EM_RISCV": + (addr, value) = process_riscv32_relocation(env, text_addr, r) + + elif env.arch.name == "EM_ARM" and r_info_type == R_ARM_ABS32: + # Absolute relocation, handled as a data relocation. + do_relocation_data(env, text_addr, r) + return + else: # Unknown/unsupported relocation - assert 0, r_info_type + assert 0, (r_info_type, s.name, s.entry, env.arch.name) # Write relocation - if reloc_type == "le32": + if env.arch.name == "EM_RISCV": + # This case is already handled by `process_riscv_relocation`. + pass + elif reloc_type == "le32": (existing,) = struct.unpack_from(" {:08x}".format(r_offset, log_name, addr)) + if addr is not None: + log(LOG_LEVEL_3, " {:08x} {} -> {:08x}".format(r_offset, log_name, addr)) + else: + log(LOG_LEVEL_3, " {:08x} {} == {:08x}".format(r_offset, log_name, value)) def do_relocation_data(env, text_addr, r): @@ -624,12 +777,16 @@ def do_relocation_data(env, text_addr, r): and r_info_type == R_ARM_ABS32 or env.arch.name == "EM_XTENSA" and r_info_type == R_XTENSA_32 + or env.arch.name == "EM_RISCV" + and r_info_type == R_RISCV_32 ): # Relocation in data.rel.ro to internal/external symbol if env.arch.word_size == 4: - struct_type = "> 1) + | ((reloc & 0x20) >> 3) + | ((reloc & 0x18) << 7) + | ((reloc & 0x06) << 2) + ) + & 0xFFFF, + ) + elif reloc_type == "riscv_cj": + # Patch the target of a compressed jump opcode + (existing,) = struct.unpack_from("> 2) + | ((reloc & 0x300) << 1) + | ((reloc & 0x80) >> 1) + | ((reloc & 0x40) << 1) + | ((reloc & 0x20) >> 3) + | ((reloc & 0x10) << 7) + | ((reloc & 0x0E) << 2) + ) + & 0xFFFF, + ) + elif reloc_type == "riscv_call": + # Patch a pair of opcodes forming a call operation + upper, lower = split_riscv_address(reloc) + (existing,) = struct.unpack_from("> 4) + | ((reloc & 0x7E0) << 20) + | ((reloc & 0x1E) << 7) + ) + & 0xFFFFFFFF, + ) + elif reloc_type == "riscv_j": + # Patch a jump/jump with link opcode + (existing,) = struct.unpack_from("/). + + symbols = {} + + LINE_REGEX = re.compile( + r"^(?PPROVIDE\()?" # optional weak marker start + r"(?P[a-zA-Z_]\w*)" # symbol name + r"=0x(?P
[\da-fA-F]{1,8})*" # symbol address + r"(?(weak)\));$", # optional weak marker end and line terminator + re.ASCII, + ) + + inside_comment = False + for line in (line.strip() for line in source.readlines()): + if line.startswith("/*") and not inside_comment: + if not line.endswith("*/"): + inside_comment = True + continue + if inside_comment: + if line.endswith("*/"): + inside_comment = False + continue + if line.startswith("//"): + continue + match = LINE_REGEX.match("".join(line.split())) + if not match: + continue + tokens = match.groupdict() + symbol = tokens["symbol"] + address = int(tokens["address"], 16) + if symbol in symbols: + raise ValueError(f"Symbol {symbol} already defined") + symbols[symbol] = address + return symbols + + def main(): import argparse - cmd_parser = argparse.ArgumentParser(description="Run scripts on the pyboard.") + cmd_parser = argparse.ArgumentParser(description="Link native object files into a MPY bundle.") cmd_parser.add_argument( "--verbose", "-v", action="count", default=1, help="increase verbosity" ) cmd_parser.add_argument("--arch", default="x64", help="architecture") cmd_parser.add_argument("--preprocess", action="store_true", help="preprocess source files") cmd_parser.add_argument("--qstrs", default=None, help="file defining additional qstrs") + cmd_parser.add_argument( + "--libs", "-l", dest="libs", action="append", help="static .a libraries to link" + ) cmd_parser.add_argument( "--output", "-o", default=None, help="output .mpy file (default to input with .o->.mpy)" ) + cmd_parser.add_argument( + "--externs", + "-e", + type=argparse.FileType("rt"), + default=None, + help="linkerscript providing fixed-address symbols to augment symbol resolution", + ) cmd_parser.add_argument("files", nargs="+", help="input files") args = cmd_parser.parse_args() diff --git a/tools/msgfmt.py b/tools/msgfmt.py index 1ed594b84f97f..428a0fbc5c54a 100644 --- a/tools/msgfmt.py +++ b/tools/msgfmt.py @@ -1,5 +1,8 @@ #! /usr/bin/env python3 -# Written by Martin v. Löwis + +# From: https://github.com/python/cpython/blob/main/Tools/i18n/msgfmt.py +# SPDX-License-Identifier: PSF-2.0 +# SPDX-FileCopyrightText: Written by Martin v. Löwis """Generate binary message catalog from textual translation description. This program converts a textual Uniforum-style message catalog (.po file) into diff --git a/tools/preprocess_frozen_modules.py b/tools/preprocess_frozen_modules.py index eb835961f67e3..3767d54bf4cd2 100755 --- a/tools/preprocess_frozen_modules.py +++ b/tools/preprocess_frozen_modules.py @@ -42,9 +42,13 @@ def version_string(path=None, *, valid_semver=False): return version -# Visit all the .py files in topdir. Replace any __version__ = "0.0.0-auto.0" type of info +# Visit all the .py files in topdir or src. Replace any __version__ = "0.0.0-auto.0" type of info # with actual version info derived from git. def copy_and_process(in_dir, out_dir): + # setuptools default: use modules from 'src' if the directory exists + src_dir = in_dir + os.path.sep + "src" + if os.path.exists(src_dir) and os.path.isdir(src_dir): + in_dir = src_dir for root, subdirs, files in os.walk(in_dir): # Skip library examples directory and subfolders. relative_path_parts = Path(root).relative_to(in_dir).parts @@ -74,6 +78,7 @@ def copy_and_process(in_dir, out_dir): if line.startswith("__version__"): module_version = version_string(root, valid_semver=True) line = line.replace("0.0.0-auto.0", module_version) + line = line.replace("0.0.0+auto.0", module_version) output.write(line) diff --git a/tools/pyboard.py b/tools/pyboard.py index 87b3851ead1a4..c9f65d5d873c2 100755 --- a/tools/pyboard.py +++ b/tools/pyboard.py @@ -216,15 +216,17 @@ def __init__(self, cmd): preexec_fn=os.setsid, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + stderr=subprocess.STDOUT, ) - pty_line = self.subp.stderr.readline().decode("utf-8") + pty_line = self.subp.stdout.readline().decode("utf-8") m = re.search(r"/dev/pts/[0-9]+", pty_line) if not m: print("Error: unable to find PTY device in startup line:", pty_line) self.close() sys.exit(1) pty = m.group() + # Compensate for some boards taking a bit longer to start + time.sleep(0.1) # rtscts, dsrdtr params are to workaround pyserial bug: # http://stackoverflow.com/questions/34831131/pyserial-does-not-play-well-with-virtual-port self.serial = serial.Serial(pty, interCharTimeout=1, rtscts=True, dsrdtr=True) @@ -246,14 +248,22 @@ def inWaiting(self): class Pyboard: def __init__( - self, device, baudrate=115200, user="micro", password="python", wait=0, exclusive=True + self, + device, + baudrate=115200, + user="micro", + password="python", + wait=0, + exclusive=True, + timeout=None, + write_timeout=5, ): self.in_raw_repl = False self.use_raw_paste = True if device.startswith("exec:"): self.serial = ProcessToSerial(device[len("exec:") :]) elif device.startswith("execpty:"): - self.serial = ProcessPtyToTerminal(device[len("qemupty:") :]) + self.serial = ProcessPtyToTerminal(device[len("execpty:") :]) elif device and device[0].isdigit() and device[-1].isdigit() and device.count(".") == 3: # device looks like an IP address self.serial = TelnetToSerial(device, user, password, read_timeout=10) @@ -262,7 +272,12 @@ def __init__( import serial.tools.list_ports # Set options, and exclusive if pyserial supports it - serial_kwargs = {"baudrate": baudrate, "interCharTimeout": 1} + serial_kwargs = { + "baudrate": baudrate, + "timeout": timeout, + "write_timeout": write_timeout, + "interCharTimeout": 1, + } if serial.__version__ >= "3.3": serial_kwargs["exclusive"] = exclusive @@ -302,14 +317,25 @@ def __init__( def close(self): self.serial.close() - def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): - # if data_consumer is used then data is not accumulated and the ending must be 1 byte long + def read_until( + self, min_num_bytes, ending, timeout=10, data_consumer=None, timeout_overall=None + ): + """ + min_num_bytes: Obsolete. + ending: Return if 'ending' matches. + timeout [s]: Return if timeout between characters. None: Infinite timeout. + timeout_overall [s]: Return not later than timeout_overall. None: Infinite timeout. + data_consumer: Use callback for incoming characters. + If data_consumer is used then data is not accumulated and the ending must be 1 byte long + + It is not visible to the caller why the function returned. It could be ending or timeout. + """ assert data_consumer is None or len(ending) == 1 + assert isinstance(timeout, (type(None), int, float)) + assert isinstance(timeout_overall, (type(None), int, float)) - data = self.serial.read(min_num_bytes) - if data_consumer: - data_consumer(data) - timeout_count = 0 + data = b"" + begin_overall_s = begin_char_s = time.monotonic() while True: if data.endswith(ending): break @@ -320,16 +346,26 @@ def read_until(self, min_num_bytes, ending, timeout=10, data_consumer=None): data = new_data else: data = data + new_data - timeout_count = 0 + begin_char_s = time.monotonic() else: - timeout_count += 1 - if timeout is not None and timeout_count >= 100 * timeout: + if timeout is not None and time.monotonic() >= begin_char_s + timeout: + break + if ( + timeout_overall is not None + and time.monotonic() >= begin_overall_s + timeout_overall + ): break time.sleep(0.01) return data - def enter_raw_repl(self, soft_reset=True): - self.serial.write(b"\r\x03\x03") # ctrl-C twice: interrupt any running program + def enter_raw_repl(self, soft_reset=True, timeout_overall=10): + try: + self._enter_raw_repl_unprotected(soft_reset, timeout_overall) + except OSError as er: + raise PyboardError("could not enter raw repl: {}".format(er)) + + def _enter_raw_repl_unprotected(self, soft_reset, timeout_overall): + self.serial.write(b"\r\x03") # ctrl-C: interrupt any running program # flush input (without relying on serial.flushInput()) n = self.serial.inWaiting() @@ -340,7 +376,9 @@ def enter_raw_repl(self, soft_reset=True): self.serial.write(b"\r\x01") # ctrl-A: enter raw REPL if soft_reset: - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n>") + data = self.read_until( + 1, b"raw REPL; CTRL-B to exit\r\n>", timeout_overall=timeout_overall + ) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n>"): print(data) raise PyboardError("could not enter raw repl") @@ -350,12 +388,12 @@ def enter_raw_repl(self, soft_reset=True): # Waiting for "soft reboot" independently to "raw REPL" (done below) # allows boot.py to print, which will show up after "soft reboot" # and before "raw REPL". - data = self.read_until(1, b"soft reboot\r\n") + data = self.read_until(1, b"soft reboot\r\n", timeout_overall=timeout_overall) if not data.endswith(b"soft reboot\r\n"): print(data) raise PyboardError("could not enter raw repl") - data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n") + data = self.read_until(1, b"raw REPL; CTRL-B to exit\r\n", timeout_overall=timeout_overall) if not data.endswith(b"raw REPL; CTRL-B to exit\r\n"): print(data) raise PyboardError("could not enter raw repl") @@ -473,8 +511,8 @@ def eval(self, expression, parse=False): return ret # In Python3, call as pyboard.exec(), see the setattr call below. - def exec_(self, command, data_consumer=None): - ret, ret_err = self.exec_raw(command, data_consumer=data_consumer) + def exec_(self, command, timeout=10, data_consumer=None): + ret, ret_err = self.exec_raw(command, timeout, data_consumer) if ret_err: raise PyboardError("exception", ret, ret_err) return ret @@ -485,7 +523,7 @@ def execfile(self, filename): return self.exec_(pyfile) def get_time(self): - t = str(self.eval("pyb.RTC().datetime()"), encoding="utf8")[1:-1].split(", ") + t = str(self.eval("machine.RTC().datetime()"), encoding="utf8")[1:-1].split(", ") return int(t[4]) * 3600 + int(t[5]) * 60 + int(t[6]) def fs_exists(self, src): @@ -509,7 +547,7 @@ def fs_listdir(self, src=""): def repr_consumer(b): buf.extend(b.replace(b"\x04", b"")) - cmd = "import os\nfor f in os.ilistdir(%s):\n" " print(repr(f), end=',')" % ( + cmd = "import os\nfor f in os.ilistdir(%s):\n print(repr(f), end=',')" % ( ("'%s'" % src) if src else "" ) try: diff --git a/tools/pydfu.py b/tools/pydfu.py index e1e4074a6baff..376c697cbd5eb 100755 --- a/tools/pydfu.py +++ b/tools/pydfu.py @@ -11,8 +11,6 @@ See document UM0391 for a description of the DFuse file. """ -from __future__ import print_function - import argparse import collections import inspect @@ -75,11 +73,7 @@ # USB DFU interface __DFU_INTERFACE = 0 -# Python 3 deprecated getargspec in favour of getfullargspec, but -# Python 2 doesn't have the latter, so detect which one to use -getargspec = getattr(inspect, "getfullargspec", getattr(inspect, "getargspec", None)) - -if "length" in getargspec(usb.util.get_string).args: +if "length" in inspect.getfullargspec(usb.util.get_string).args: # PyUSB 1.0.0.b1 has the length argument def get_string(dev, index): return usb.util.get_string(dev, 255, index) @@ -344,8 +338,7 @@ def read_dfu_file(filename): # B uint8_t targets Number of targets dfu_prefix, data = consume("<5sBIB", data, "signature version size targets") print( - " %(signature)s v%(version)d, image size: %(size)d, " - "targets: %(targets)d" % dfu_prefix + " %(signature)s v%(version)d, image size: %(size)d, targets: %(targets)d" % dfu_prefix ) for target_idx in range(dfu_prefix["targets"]): # Decode the Image Prefix @@ -359,7 +352,7 @@ def read_dfu_file(filename): # I uint32_t size Size of image (without prefix) # I uint32_t elements Number of elements in the image img_prefix, data = consume( - "<6sBI255s2I", data, "signature altsetting named name " "size elements" + "<6sBI255s2I", data, "signature altsetting named name size elements" ) img_prefix["num"] = target_idx if img_prefix["named"]: diff --git a/tools/ruff_bindings.py b/tools/ruff_bindings.py new file mode 100755 index 0000000000000..a8367ea0df1b7 --- /dev/null +++ b/tools/ruff_bindings.py @@ -0,0 +1,129 @@ +#!/usr/bin/python3 +import os +import re +import subprocess +import sys +from concurrent.futures import ThreadPoolExecutor +from dataclasses import dataclass +from enum import Enum, auto + +MARK_C_IN_PY = "##| " +MARK_PY_IN_C = "//| " + + +class Mode(Enum): + C = auto() + PY = auto() + + +@dataclass(frozen=True) +class LineWithMode: + data: str + mode: Mode + + +class OutputWriter: + def __init__(self): + self.content = [] + + def write(self, line): + self.content.append(line.rstrip()) + + def getcontent(self): + return "\n".join(self.content) + + +class PythonOutputWriter(OutputWriter): + def write(self, line): + if isinstance(line, str): + super().write(line) + elif line.mode == Mode.PY: + super().write(line.data) + else: # line mode is C + super().write(MARK_C_IN_PY + line.data) + + +class COutputWriter(OutputWriter): + def write(self, line): + if isinstance(line, str): + super().write(line) + elif line.mode == Mode.PY: + super().write(MARK_PY_IN_C + line.data) + else: # line mode is C + super().write(line.data) + + +def parse_line(line, defmode, mark, smark, markmode): + sline = line.strip() + if sline == smark or sline.startswith(mark): + return LineWithMode(sline[len(mark) :], markmode) + else: + return LineWithMode(line, defmode) + + +def parse_lines(lines, defmode, mark, markmode): + smark = mark.strip() + return [parse_line(line, defmode, mark, smark, markmode) for line in lines] + + +def swap_comment_markers(content, input_mode): + lines = content.rstrip().split("\n") + + if input_mode == Mode.C: + parsed = parse_lines(lines, Mode.C, MARK_PY_IN_C, Mode.PY) + writer = PythonOutputWriter() + else: + parsed = parse_lines(lines, Mode.PY, MARK_C_IN_PY, Mode.C) + writer = COutputWriter() + + for line in parsed: + writer.write(line) + + newcontent = writer.getcontent() + "\n" + + return newcontent + + +def process_one_file(fn): + with open(fn, "r", encoding="utf-8") as f: + c_content = f.read() + + if "\n//| " not in c_content: + return + + py_content = swap_comment_markers(c_content, Mode.C) + + try: + # Line length is 95 so that with "//| " the max is 99 + result = subprocess.run( + ["ruff", "format", "--line-length", "95", "-q", "-"], + input=py_content, + check=True, + stdout=subprocess.PIPE, + encoding="utf-8", + ) + except subprocess.CalledProcessError: + print(f"{fn}:0: Failed to process file ") + raise + + new_py_content = result.stdout + new_c_content = swap_comment_markers(new_py_content, Mode.PY) + + if new_c_content != c_content: + with open(fn, "w", encoding="utf-8") as f: + f.write(new_c_content) + + +if __name__ == "__main__": + # Use a thread pool because most processing is inside black! + executor = ThreadPoolExecutor(max_workers=os.cpu_count()) + futures = [executor.submit(process_one_file, fn) for fn in sys.argv[1:]] + status = 0 + for f in futures: + try: + f.result() + except Exception as e: + print(e) + status = 1 + executor.shutdown() + raise SystemExit(status) diff --git a/tools/stack-loc-to-pc.py b/tools/stack-loc-to-pc.py index a1ce788f2b652..d4287f3a5d6e6 100644 --- a/tools/stack-loc-to-pc.py +++ b/tools/stack-loc-to-pc.py @@ -1,10 +1,10 @@ """Prints the pcs that access each stack location in a function. Useful for finding - infrequently used stack space. +infrequently used stack space. - Pipe in disassembly like so: +Pipe in disassembly like so: - arm-none-eabi-objdump --disassemble=mp_execute_bytecode build-metro_m0_express/firmware.elf | python ../../tools/stack-loc-to-pc.py - """ +arm-none-eabi-objdump --disassemble=mp_execute_bytecode build-metro_m0_express/firmware.elf | python ../../tools/stack-loc-to-pc.py +""" import sys import re diff --git a/tools/test-stubs.sh b/tools/test-stubs.sh index 907604aee5d7f..2339960fd7c92 100755 --- a/tools/test-stubs.sh +++ b/tools/test-stubs.sh @@ -2,7 +2,7 @@ rm -rf test-stubs python3 -m venv test-stubs . test-stubs/bin/activate -pip install mypy isort black adafruit-circuitpython-typing wheel build +pip install mypy isort black adafruit-circuitpython-typing wheel build setuptools_scm rm -rf circuitpython-stubs .mypy_cache make stubs # Allow either dash or underscore as separator. setuptools v69.3.0 changed from "-" to "_". diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py deleted file mode 100755 index 0f0428a8f1053..0000000000000 --- a/tools/tinytest-codegen.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python3 - -# SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) -# -# SPDX-License-Identifier: MIT - -import os, sys -from glob import glob -from re import sub -import argparse - - -def escape(s): - s = s.decode() - lookup = { - "\0": "\\0", - "\t": "\\t", - "\n": '\\n"\n"', - "\r": "\\r", - "\\": "\\\\", - '"': '\\"', - } - return '""\n"{}"'.format("".join([lookup[x] if x in lookup else x for x in s])) - - -def chew_filename(t): - return {"func": "test_{}_fn".format(sub(r"/|\.|-", "_", t)), "desc": t} - - -def script_to_map(test_file): - r = {"name": chew_filename(test_file)["func"]} - with open(test_file, "rb") as test: - script = test.readlines() - - # Test for import skip_if and inject it into the test as needed. - if "import skip_if\n" in script: - index = script.index("import skip_if\n") - script.pop(index) - script.insert(index, "class skip_if:\n") - with open("../tests/skip_if.py") as skip_if: - total_lines = 1 - for line in skip_if: - stripped = line.strip() - if not stripped or stripped.startswith(("#", '"""')): - continue - script.insert(index + total_lines, "\t" + line) - total_lines += 1 - r["script"] = escape(b"".join(script)) - - with open(test_file + ".exp", "rb") as f: - r["output"] = escape(f.read()) - - return r - - -def load_profile(profile_file, test_dirs, exclude_tests): - profile_globals = {"test_dirs": test_dirs, "exclude_tests": exclude_tests} - exec(profile_file.read(), profile_globals) - return profile_globals["test_dirs"], profile_globals["exclude_tests"] - - -test_function = ( - "void {name}(void* data) {{\n" - " static const char pystr[] = {script};\n" - " static const char exp[] = {output};\n" - ' printf("\\n");\n' - " upytest_set_expected_output(exp, sizeof(exp) - 1);\n" - " upytest_execute_test(pystr);\n" - ' printf("result: ");\n' - "}}" -) - -testcase_struct = "struct testcase_t {name}_tests[] = {{\n{body}\n END_OF_TESTCASES\n}};" -testcase_member = ' {{ "{desc}", {func}, TT_ENABLED_, 0, 0 }},' - -testgroup_struct = "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n}};" -testgroup_member = ' {{ "{name}", {name}_tests }},' - -## XXX: may be we could have `--without ` argument... - -test_dirs = set( - ( - "basics", - "extmod", - "float", - "micropython", - "misc", - ) -) - -exclude_tests = set( - ( - # pattern matching in .exp - "basics/bytes_compare3.py", - "extmod/ticks_diff.py", - "extmod/time_ms_us.py", - # unicode char issue - "extmod/json_loads.py", - # doesn't output to python stdout - "extmod/re_debug.py", - "extmod/vfs_basic.py", - "extmod/vfs_fat_ramdisk.py", - "extmod/vfs_fat_fileio.py", - "extmod/vfs_fat_fsusermount.py", - "extmod/vfs_fat_oldproto.py", - # rounding issues - "float/float_divmod.py", - # requires double precision floating point to work - "float/float2int_doubleprec_intbig.py", - "float/float_format_ints_doubleprec.py", - "float/float_parse_doubleprec.py", - # different filename in output - "micropython/emg_exc.py", - "micropython/heapalloc_traceback.py", - # don't have emergency exception buffer - "micropython/heapalloc_exc_compressed_emg_exc.py", - # pattern matching in .exp - "micropython/meminfo.py", - # needs sys stdfiles - "misc/print_exception.py", - # settrace .exp files are too large - "misc/sys_settrace_loop.py", - "misc/sys_settrace_generator.py", - "misc/sys_settrace_features.py", - # don't have f-string - "basics/string_fstring.py", - "basics/string_fstring_debug.py", - ) -) - -output = [] -tests = [] - -argparser = argparse.ArgumentParser( - description="Convert native MicroPython tests to tinytest/upytesthelper C code" -) -argparser.add_argument("--stdin", action="store_true", help="read list of tests from stdin") -argparser.add_argument("--exclude", action="append", help="exclude test by name") -argparser.add_argument( - "--profile", - type=argparse.FileType("rt", encoding="utf-8"), - help="optional profile file providing test directories and exclusion list", -) -args = argparser.parse_args() - -if not args.stdin: - if args.profile: - test_dirs, exclude_tests = load_profile(args.profile, test_dirs, exclude_tests) - if args.exclude: - exclude_tests = exclude_tests.union(args.exclude) - for group in test_dirs: - tests += [test for test in glob("{}/*.py".format(group)) if test not in exclude_tests] -else: - for l in sys.stdin: - tests.append(l.rstrip()) - -output.extend([test_function.format(**script_to_map(test)) for test in tests]) -testcase_members = [testcase_member.format(**chew_filename(test)) for test in tests] -output.append(testcase_struct.format(name="", body="\n".join(testcase_members))) - -testgroup_members = [testgroup_member.format(name=group) for group in [""]] - -output.append(testgroup_struct.format(body="\n".join(testgroup_members))) - -## XXX: may be we could have `--output ` argument... -# Don't depend on what system locale is set, use utf8 encoding. -sys.stdout.buffer.write("\n\n".join(output).encode("utf8")) diff --git a/tools/verifygitlog.py b/tools/verifygitlog.py index ad9385e7ac540..dba6ebd6de59a 100755 --- a/tools/verifygitlog.py +++ b/tools/verifygitlog.py @@ -47,7 +47,7 @@ def git_log(pretty_format, *args): def diagnose_subject_line(subject_line, subject_line_format, err): - err.error("Subject line: " + subject_line) + err.error('Subject line: "' + subject_line + '"') if not subject_line.endswith("."): err.error('* must end with "."') if not re.match(r"^[^!]+: ", subject_line): @@ -96,20 +96,47 @@ def verify_message_body(raw_body, err): if len(subject_line) >= 73: err.error("Subject line must be 72 or fewer characters: " + subject_line) + # Do additional checks on the prefix of the subject line. + verify_subject_line_prefix(subject_line.split(": ")[0], err) + # Second one divides subject and body. if len(raw_body) > 1 and raw_body[1]: err.error("Second message line must be empty: " + raw_body[1]) # Message body lines. for line in raw_body[2:]: - # Long lines with URLs are exempt from the line length rule. - if len(line) >= 76 and "://" not in line: + # Long lines with URLs or human names are exempt from the line length rule. + if len(line) >= 76 and not ( + "://" in line + or line.startswith("Co-authored-by: ") + or line.startswith("Signed-off-by: ") + ): err.error("Message lines should be 75 or less characters: " + line) if not raw_body[-1].startswith("Signed-off-by: ") or "@" not in raw_body[-1]: err.error('Message must be signed-off. Use "git commit -s".') +def verify_subject_line_prefix(prefix, err): + ext = (".c", ".h", ".cpp", ".js", ".rst", ".md") + + if prefix.startswith((".", "/")): + err.error('Subject prefix cannot begin with "." or "/".') + + if prefix.endswith("/"): + err.error('Subject prefix cannot end with "/".') + + if prefix.startswith("ports/"): + err.error( + 'Subject prefix cannot begin with "ports/", start with the name of the port instead.' + ) + + if prefix.endswith(ext): + err.error( + "Subject prefix cannot end with a file extension, use the main part of the filename without the extension." + ) + + def run(args): verbose("run", *args)